--- linux-2.6.27.orig/MAINTAINERS +++ linux-2.6.27/MAINTAINERS @@ -360,7 +360,7 @@ ALI1563 I2C DRIVER P: Rudolf Marek M: r.marek@assembler.cz -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained ALPHA PORT @@ -1681,7 +1681,7 @@ P: Jochen Friedrich M: jochen@scram.de L: linuxppc-dev@ozlabs.org -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained FREESCALE SOC FS_ENET DRIVER @@ -1982,7 +1982,7 @@ I2C/SMBUS STUB DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained I2C SUBSYSTEM @@ -1990,14 +1990,14 @@ M: khali@linux-fr.org P: Ben Dooks (embedded platforms) M: ben-linux@fluff.org -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/ S: Maintained I2C-TINY-USB DRIVER P: Till Harbaum M: till@harbaum.org -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org T: http://www.harbaum.org/till/i2c_tiny_usb S: Maintained @@ -3070,7 +3070,7 @@ OPENCORES I2C BUS DRIVER P: Peter Korsgaard M: jacmet@sunsite.dk -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained ORACLE CLUSTER FILESYSTEM 2 (OCFS2) @@ -3144,7 +3144,7 @@ PA SEMI SMBUS DRIVER P: Olof Johansson M: olof@lixom.net -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained PARALLEL PORT SUPPORT @@ -3280,7 +3280,7 @@ PNXxxxx I2C DRIVER P: Vitaly Wool M: vitalywool@gmail.com -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained PPP PROTOCOL DRIVERS AND COMPRESSORS @@ -3725,7 +3725,7 @@ SIS 96X I2C/SMBUS DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained SIS FRAMEBUFFER DRIVER @@ -4445,7 +4445,7 @@ VIAPRO SMBUS DRIVER P: Jean Delvare M: khali@linux-fr.org -L: i2c@lm-sensors.org +L: linux-i2c@vger.kernel.org S: Maintained VIA VELOCITY NETWORK DRIVER --- linux-2.6.27.orig/Makefile +++ linux-2.6.27/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -NAME = Rotary Wombat +EXTRAVERSION = .6 +NAME = Trembling Tortoise # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -328,14 +328,24 @@ CFLAGS_KERNEL = AFLAGS_KERNEL = +# Prefer linux-backports-modules +ifneq ($(KBUILD_SRC),) +ifneq ($(shell if test -e $(KBUILD_OUTPUT)/ubuntu-build; then echo yes; fi),yes) +UBUNTUINCLUDE := -I/usr/src/linux-headers-lbm-$(KERNELRELEASE) +endif +endif # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option -LINUXINCLUDE := -Iinclude \ +LINUXINCLUDE := $(UBUNTUINCLUDE) -Iinclude \ $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ -I$(srctree)/arch/$(hdr-arch)/include \ -include include/linux/autoconf.h +# UBUNTU: Include our third party driver stuff too +LINUXINCLUDE += -Iubuntu/include \ + $(if $(KBUILD_SRC),-I$(srctree)/ubuntu/include) + KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ @@ -458,7 +468,7 @@ # Objects we will link into vmlinux / subdirs we need to visit init-y := init/ -drivers-y := drivers/ sound/ firmware/ +drivers-y := drivers/ sound/ firmware/ ubuntu/ net-y := net/ libs-y := lib/ core-y := usr/ --- linux-2.6.27.orig/drivers/ata/pata_it821x.c +++ linux-2.6.27/drivers/ata/pata_it821x.c @@ -557,9 +557,8 @@ if (strstr(model_num, "Integrated Technology Express")) { /* Set feature bits the firmware neglects */ id[49] |= 0x0300; /* LBA, DMA */ - id[82] |= 0x0400; /* LBA48 */ id[83] &= 0x7FFF; - id[83] |= 0x4000; /* Word 83 is valid */ + id[83] |= 0x4400; /* Word 83 is valid and LBA48 */ id[86] |= 0x0400; /* LBA48 on */ id[ATA_ID_MAJOR_VER] |= 0x1F; } --- linux-2.6.27.orig/drivers/ata/libata-core.c +++ linux-2.6.27/drivers/ata/libata-core.c @@ -3976,6 +3976,7 @@ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, + { "FUJITSU MHW2160BH PL", "0084001E", ATA_HORKAGE_NONCQ, }, /* devices which puke on READ_NATIVE_MAX */ { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, @@ -5259,6 +5260,8 @@ #ifdef CONFIG_ATA_SFF INIT_DELAYED_WORK(&ap->port_task, ata_pio_task); +#else + INIT_DELAYED_WORK(&ap->port_task, NULL); #endif INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); --- linux-2.6.27.orig/drivers/ata/sata_nv.c +++ linux-2.6.27/drivers/ata/sata_nv.c @@ -307,10 +307,10 @@ static void nv_nf2_freeze(struct ata_port *ap); static void nv_nf2_thaw(struct ata_port *ap); +static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline); static int nv_adma_slave_config(struct scsi_device *sdev); static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); static void nv_adma_qc_prep(struct ata_queued_cmd *qc); @@ -405,17 +405,8 @@ .slave_configure = nv_swncq_slave_config, }; -/* OSDL bz3352 reports that some nv controllers can't determine device - * signature reliably and nv_hardreset is implemented to work around - * the problem. This was reported on nf3 and it's unclear whether any - * other controllers are affected. However, the workaround has been - * applied to all variants and there isn't much to gain by trying to - * find out exactly which ones are affected at this point especially - * because NV has moved over to ahci for newer controllers. - */ static struct ata_port_operations nv_common_ops = { .inherits = &ata_bmdma_port_ops, - .hardreset = nv_hardreset, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; @@ -429,12 +420,22 @@ .hardreset = ATA_OP_NULL, }; +/* OSDL bz3352 reports that nf2/3 controllers can't determine device + * signature reliably. Also, the following thread reports detection + * failure on cold boot with the standard debouncing timing. + * + * http://thread.gmane.org/gmane.linux.ide/34098 + * + * Debounce with hotplug timing and request follow-up SRST. + */ static struct ata_port_operations nv_nf2_ops = { .inherits = &nv_common_ops, .freeze = nv_nf2_freeze, .thaw = nv_nf2_thaw, + .hardreset = nv_nf2_hardreset, }; +/* CK804 finally gets hardreset right */ static struct ata_port_operations nv_ck804_ops = { .inherits = &nv_common_ops, .freeze = nv_ck804_freeze, @@ -443,7 +444,7 @@ }; static struct ata_port_operations nv_adma_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_ck804_ops, .check_atapi_dma = nv_adma_check_atapi_dma, .sff_tf_read = nv_adma_tf_read, @@ -467,7 +468,7 @@ }; static struct ata_port_operations nv_swncq_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_generic_ops, .qc_defer = ata_std_qc_defer, .qc_prep = nv_swncq_qc_prep, @@ -1553,6 +1554,17 @@ iowrite8(mask, scr_addr + NV_INT_ENABLE); } +static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + bool online; + int rc; + + rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, + &online, NULL); + return online ? -EAGAIN : rc; +} + static void nv_ck804_freeze(struct ata_port *ap) { void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; @@ -1605,21 +1617,6 @@ ata_sff_thaw(ap); } -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - int rc; - - /* SATA hardreset fails to retrieve proper device signature on - * some controllers. Request follow up SRST. For more info, - * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 - */ - rc = sata_sff_hardreset(link, class, deadline); - if (rc) - return rc; - return -EAGAIN; -} - static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; --- linux-2.6.27.orig/drivers/ata/libata-eh.c +++ linux-2.6.27/drivers/ata/libata-eh.c @@ -604,9 +604,6 @@ if (ata_ncq_enabled(dev)) ehc->saved_ncq_enabled |= 1 << devno; } - - /* set last reset timestamp to some time in the past */ - ehc->last_reset = jiffies - 60 * HZ; } ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; @@ -2209,17 +2206,21 @@ if (link->flags & ATA_LFLAG_NO_SRST) softreset = NULL; - now = jiffies; - deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); - if (time_before(now, deadline)) - schedule_timeout_uninterruptible(deadline - now); + /* make sure each reset attemp is at least COOL_DOWN apart */ + if (ehc->i.flags & ATA_EHI_DID_RESET) { + now = jiffies; + WARN_ON(time_after(ehc->last_reset, now)); + deadline = ata_deadline(ehc->last_reset, + ATA_EH_RESET_COOL_DOWN); + if (time_before(now, deadline)) + schedule_timeout_uninterruptible(deadline - now); + } spin_lock_irqsave(ap->lock, flags); ap->pflags |= ATA_PFLAG_RESETTING; spin_unlock_irqrestore(ap->lock, flags); ata_eh_about_to_do(link, NULL, ATA_EH_RESET); - ehc->last_reset = jiffies; ata_link_for_each_dev(dev, link) { /* If we issue an SRST then an ATA drive (not ATAPI) @@ -2285,7 +2286,6 @@ /* * Perform reset */ - ehc->last_reset = jiffies; if (ata_is_host_link(link)) ata_eh_freeze_port(ap); @@ -2297,6 +2297,7 @@ reset == softreset ? "soft" : "hard"); /* mark that this EH session started with reset */ + ehc->last_reset = jiffies; if (reset == hardreset) ehc->i.flags |= ATA_EHI_DID_HARDRESET; else @@ -2404,7 +2405,7 @@ /* reset successful, schedule revalidation */ ata_eh_done(link, NULL, ATA_EH_RESET); - ehc->last_reset = jiffies; + ehc->last_reset = jiffies; /* update to completion time */ ehc->i.action |= ATA_EH_REVALIDATE; rc = 0; --- linux-2.6.27.orig/drivers/ata/sata_promise.c +++ linux-2.6.27/drivers/ata/sata_promise.c @@ -153,6 +153,10 @@ static void pdc_sata_freeze(struct ata_port *ap); static void pdc_thaw(struct ata_port *ap); static void pdc_sata_thaw(struct ata_port *ap); +static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); +static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static void pdc_error_handler(struct ata_port *ap); static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); static int pdc_pata_cable_detect(struct ata_port *ap); @@ -186,6 +190,7 @@ .scr_read = pdc_sata_scr_read, .scr_write = pdc_sata_scr_write, .port_start = pdc_sata_port_start, + .hardreset = pdc_sata_hardreset, }; /* First-generation chips need a more restrictive ->check_atapi_dma op */ @@ -200,6 +205,7 @@ .freeze = pdc_freeze, .thaw = pdc_thaw, .port_start = pdc_common_port_start, + .softreset = pdc_pata_softreset, }; static const struct ata_port_info pdc_port_info[] = { @@ -691,6 +697,20 @@ readl(host_mmio + hotplug_offset); /* flush */ } +static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + pdc_reset_port(link->ap); + return ata_sff_softreset(link, class, deadline); +} + +static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + pdc_reset_port(link->ap); + return sata_sff_hardreset(link, class, deadline); +} + static void pdc_error_handler(struct ata_port *ap) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) --- linux-2.6.27.orig/drivers/edac/cell_edac.c +++ linux-2.6.27/drivers/edac/cell_edac.c @@ -142,7 +142,7 @@ csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT; csrow->last_page = csrow->first_page + csrow->nr_pages - 1; csrow->mtype = MEM_XDR; - csrow->edac_mode = EDAC_FLAG_EC | EDAC_FLAG_SECDED; + csrow->edac_mode = EDAC_SECDED; dev_dbg(mci->dev, "Initialized on node %d, chanmask=0x%x," " first_page=0x%lx, nr_pages=0x%x\n", --- linux-2.6.27.orig/drivers/hid/hidraw.c +++ linux-2.6.27/drivers/hid/hidraw.c @@ -113,7 +113,7 @@ if (!dev->hid_output_raw_report) return -ENODEV; - if (count > HID_MIN_BUFFER_SIZE) { + if (count > HID_MAX_BUFFER_SIZE) { printk(KERN_WARNING "hidraw: pid %d passed too large report\n", task_pid_nr(current)); return -EINVAL; --- linux-2.6.27.orig/drivers/hid/usbhid/hid-quirks.c +++ linux-2.6.27/drivers/hid/usbhid/hid-quirks.c @@ -247,8 +247,6 @@ #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 #define USB_VENDOR_ID_LOGITECH 0x046d -#define USB_DEVICE_ID_LOGITECH_LX3 0xc044 -#define USB_DEVICE_ID_LOGITECH_V150 0xc047 #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 #define USB_DEVICE_ID_LOGITECH_HARMONY 0xc110 #define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111 @@ -603,8 +601,6 @@ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS }, --- linux-2.6.27.orig/drivers/firewire/fw-cdev.c +++ linux-2.6.27/drivers/firewire/fw-cdev.c @@ -720,8 +720,8 @@ #define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff) #define GET_INTERRUPT(v) (((v) >> 16) & 0x01) #define GET_SKIP(v) (((v) >> 17) & 0x01) -#define GET_TAG(v) (((v) >> 18) & 0x02) -#define GET_SY(v) (((v) >> 20) & 0x04) +#define GET_TAG(v) (((v) >> 18) & 0x03) +#define GET_SY(v) (((v) >> 20) & 0x0f) #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff) static int ioctl_queue_iso(struct client *client, void *buffer) @@ -913,7 +913,7 @@ return -EFAULT; } - return 0; + return retval; } static long --- linux-2.6.27.orig/drivers/firewire/fw-transaction.h +++ linux-2.6.27/drivers/firewire/fw-transaction.h @@ -248,7 +248,7 @@ struct fw_node *local_node; struct fw_node *root_node; struct fw_node *irm_node; - int color; + u8 color; /* must be u8 to match the definition in struct fw_node */ int gap_count; bool beta_repeaters_present; --- linux-2.6.27.orig/drivers/firewire/fw-topology.c +++ linux-2.6.27/drivers/firewire/fw-topology.c @@ -413,7 +413,7 @@ update_tree(struct fw_card *card, struct fw_node *root) { struct list_head list0, list1; - struct fw_node *node0, *node1; + struct fw_node *node0, *node1, *next1; int i, event; INIT_LIST_HEAD(&list0); @@ -485,7 +485,9 @@ } node0 = fw_node(node0->link.next); - node1 = fw_node(node1->link.next); + next1 = fw_node(node1->link.next); + fw_node_put(node1); + node1 = next1; } } --- linux-2.6.27.orig/drivers/firewire/fw-sbp2.c +++ linux-2.6.27/drivers/firewire/fw-sbp2.c @@ -172,6 +172,9 @@ int blocked; /* ditto */ }; +/* Impossible login_id, to detect logout attempt before successful login */ +#define INVALID_LOGIN_ID 0x10000 + /* * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be * provided in the config rom. Most devices do provide a value, which @@ -791,9 +794,20 @@ scsi_remove_device(sdev); scsi_device_put(sdev); } - sbp2_send_management_orb(lu, tgt->node_id, lu->generation, - SBP2_LOGOUT_REQUEST, lu->login_id, NULL); - + if (lu->login_id != INVALID_LOGIN_ID) { + int generation, node_id; + /* + * tgt->node_id may be obsolete here if we failed + * during initial login or after a bus reset where + * the topology changed. + */ + generation = device->generation; + smp_rmb(); /* node_id vs. generation */ + node_id = device->node_id; + sbp2_send_management_orb(lu, node_id, generation, + SBP2_LOGOUT_REQUEST, + lu->login_id, NULL); + } fw_core_remove_address_handler(&lu->address_handler); list_del(&lu->link); kfree(lu); @@ -808,19 +822,20 @@ static struct workqueue_struct *sbp2_wq; +static void sbp2_target_put(struct sbp2_target *tgt) +{ + kref_put(&tgt->kref, sbp2_release_target); +} + /* * Always get the target's kref when scheduling work on one its units. * Each workqueue job is responsible to call sbp2_target_put() upon return. */ static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) { - if (queue_delayed_work(sbp2_wq, &lu->work, delay)) - kref_get(&lu->tgt->kref); -} - -static void sbp2_target_put(struct sbp2_target *tgt) -{ - kref_put(&tgt->kref, sbp2_release_target); + kref_get(&lu->tgt->kref); + if (!queue_delayed_work(sbp2_wq, &lu->work, delay)) + sbp2_target_put(lu->tgt); } static void @@ -993,6 +1008,7 @@ lu->tgt = tgt; lu->lun = lun_entry & 0xffff; + lu->login_id = INVALID_LOGIN_ID; lu->retries = 0; lu->has_sdev = false; lu->blocked = false; @@ -1158,7 +1174,7 @@ /* Do the login in a workqueue so we can easily reschedule retries. */ list_for_each_entry(lu, &tgt->lu_list, link) - sbp2_queue_work(lu, 0); + sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); return 0; fail_tgt_put: --- linux-2.6.27.orig/drivers/usb/atm/speedtch.c +++ linux-2.6.27/drivers/usb/atm/speedtch.c @@ -722,6 +722,16 @@ flush_scheduled_work(); } +static int speedtch_pre_reset(struct usb_interface *intf) +{ + return 0; +} + +static int speedtch_post_reset(struct usb_interface *intf) +{ + return 0; +} + /********** ** USB ** @@ -740,6 +750,8 @@ .name = speedtch_driver_name, .probe = speedtch_usb_probe, .disconnect = usbatm_usb_disconnect, + .pre_reset = speedtch_pre_reset, + .post_reset = speedtch_post_reset, .id_table = speedtch_usb_ids }; --- linux-2.6.27.orig/drivers/usb/serial/ipaq.c +++ linux-2.6.27/drivers/usb/serial/ipaq.c @@ -548,7 +548,6 @@ { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ - { USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */ { } /* Terminating entry */ }; --- linux-2.6.27.orig/drivers/usb/serial/option.c +++ linux-2.6.27/drivers/usb/serial/option.c @@ -205,9 +205,6 @@ #define BANDRICH_PRODUCT_1011 0x1011 #define BANDRICH_PRODUCT_1012 0x1012 -#define AMOI_VENDOR_ID 0x1614 -#define AMOI_PRODUCT_9508 0x0800 - #define QUALCOMM_VENDOR_ID 0x05C6 #define MAXON_VENDOR_ID 0x16d8 @@ -275,7 +272,6 @@ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, - { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ --- linux-2.6.27.orig/drivers/usb/class/cdc-wdm.c +++ linux-2.6.27/drivers/usb/class/cdc-wdm.c @@ -42,6 +42,8 @@ { } }; +MODULE_DEVICE_TABLE (usb, wdm_ids); + #define WDM_MINOR_BASE 176 --- linux-2.6.27.orig/drivers/usb/class/cdc-acm.c +++ linux-2.6.27/drivers/usb/class/cdc-acm.c @@ -849,9 +849,10 @@ { int i; struct acm_wb *wb; + struct usb_device *usb_dev = interface_to_usbdev(acm->control); for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { - usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); + usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah); } } --- linux-2.6.27.orig/drivers/usb/musb/musb_core.c +++ linux-2.6.27/drivers/usb/musb/musb_core.c @@ -82,9 +82,9 @@ /* * This gets many kinds of configuration information: * - Kconfig for everything user-configurable - * - for SOC or family details * - platform_device for addressing, irq, and platform_data * - platform_data is mostly for board-specific informarion + * (plus recentrly, SOC or family details) * * Most of the conditional compilation will (someday) vanish. */ @@ -974,9 +974,9 @@ /* * The silicon either has hard-wired endpoint configurations, or else * "dynamic fifo" sizing. The driver has support for both, though at this - * writing only the dynamic sizing is very well tested. We use normal - * idioms to so both modes are compile-tested, but dead code elimination - * leaves only the relevant one in the object file. + * writing only the dynamic sizing is very well tested. Since we switched + * away from compile-time hardware parameters, we can no longer rely on + * dead code elimination to leave only the relevant one in the object file. * * We don't currently use dynamic fifo setup capability to do anything * more than selecting one of a bunch of predefined configurations. --- linux-2.6.27.orig/drivers/usb/musb/Kconfig +++ linux-2.6.27/drivers/usb/musb/Kconfig @@ -33,10 +33,6 @@ default y if ARCH_DAVINCI default y if ARCH_OMAP2430 default y if ARCH_OMAP34XX - help - Use a static file to describe how the - controller is configured (endpoints, mechanisms, etc) on the - current iteration of a given system-on-chip. comment "DaVinci 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI --- linux-2.6.27.orig/drivers/usb/musb/davinci.c +++ linux-2.6.27/drivers/usb/musb/davinci.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -39,7 +40,7 @@ #include "musb_core.h" #ifdef CONFIG_MACH_DAVINCI_EVM -#include +#define GPIO_nVBUS_DRV 87 #endif #include "davinci.h" @@ -138,7 +139,6 @@ /* VBUS SWITCHING IS BOARD-SPECIFIC */ #ifdef CONFIG_MACH_DAVINCI_EVM -#ifndef CONFIG_MACH_DAVINCI_EVM_OTG /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice @@ -146,12 +146,11 @@ */ static void evm_deferred_drvvbus(struct work_struct *ignored) { - davinci_i2c_expander_op(0x3a, USB_DRVVBUS, vbus_state); + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); vbus_state = !vbus_state; } static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); -#endif /* modified board */ #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) @@ -165,21 +164,10 @@ #ifdef CONFIG_MACH_DAVINCI_EVM if (machine_is_davinci_evm()) { -#ifdef CONFIG_MACH_DAVINCI_EVM_OTG - /* modified EVM board switching VBUS with GPIO(6) not I2C - * NOTE: PINMUX0.RGB888 (bit23) must be clear - */ - if (is_on) - gpio_set(GPIO(6)); - else - gpio_clear(GPIO(6)); - immediate = 1; -#else if (immediate) - davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on); + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); else schedule_work(&evm_vbus_work); -#endif } #endif if (immediate) --- linux-2.6.27.orig/drivers/usb/musb/musb_host.c +++ linux-2.6.27/drivers/usb/musb/musb_host.c @@ -108,7 +108,7 @@ /* * Clear TX fifo. Needed to avoid BABBLE errors. */ -static inline void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) +static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) { void __iomem *epio = ep->regs; u16 csr; @@ -436,7 +436,7 @@ } } -static inline u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) +static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) { /* we don't want fifo to fill itself again; * ignore dma (various models), @@ -1005,7 +1005,7 @@ /* * Handle default endpoint interrupt as host. Only called in IRQ time - * from the LinuxIsr() interrupt service routine. + * from musb_interrupt(). * * called with controller irqlocked */ --- linux-2.6.27.orig/drivers/usb/musb/cppi_dma.h +++ linux-2.6.27/drivers/usb/musb/cppi_dma.h @@ -119,8 +119,8 @@ void __iomem *mregs; /* Mentor regs */ void __iomem *tibase; /* TI/CPPI regs */ - struct cppi_channel tx[MUSB_C_NUM_EPT - 1]; - struct cppi_channel rx[MUSB_C_NUM_EPR - 1]; + struct cppi_channel tx[4]; + struct cppi_channel rx[4]; struct dma_pool *pool; --- linux-2.6.27.orig/drivers/usb/host/ohci-hcd.c +++ linux-2.6.27/drivers/usb/host/ohci-hcd.c @@ -1098,6 +1098,7 @@ printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name); pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, sizeof (struct ed), sizeof (struct td)); + set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); #ifdef DEBUG ohci_debug_root = debugfs_create_dir("ohci", NULL); @@ -1184,6 +1185,7 @@ error_debug: #endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); return retval; } module_init(ohci_hcd_mod_init); @@ -1214,6 +1216,7 @@ #ifdef DEBUG debugfs_remove(ohci_debug_root); #endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); } module_exit(ohci_hcd_mod_exit); --- linux-2.6.27.orig/drivers/usb/host/uhci-hcd.c +++ linux-2.6.27/drivers/usb/host/uhci-hcd.c @@ -953,6 +953,7 @@ printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n", ignore_oc ? ", overcurrent ignored" : ""); + set_bit(USB_UHCI_LOADED, &usb_hcds_loaded); if (usb_disabled()) return -ENODEV; @@ -988,6 +989,7 @@ errbuf_failed: + clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); return retval; } @@ -997,6 +999,7 @@ kmem_cache_destroy(uhci_up_cachep); debugfs_remove(uhci_debugfs_root); kfree(errbuf); + clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); } module_init(uhci_hcd_init); --- linux-2.6.27.orig/drivers/usb/host/ohci-hub.c +++ linux-2.6.27/drivers/usb/host/ohci-hub.c @@ -359,21 +359,24 @@ /* Carry out polling-, autostop-, and autoresume-related state changes */ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, - int any_connected) + int any_connected, int rhsc_status) { int poll_rh = 1; - int rhsc; + int rhsc_enable; - rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; - switch (ohci->hc_control & OHCI_CTRL_HCFS) { + /* Some broken controllers never turn off RHCS in the interrupt + * status register. For their sake we won't re-enable RHSC + * interrupts if the interrupt bit is already active. + */ + rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC; + switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: - /* If no status changes are pending, enable status-change - * interrupts. - */ - if (!rhsc && !changed) { - rhsc = OHCI_INTR_RHSC; - ohci_writel(ohci, rhsc, &ohci->regs->intrenable); + /* If no status changes are pending, enable RHSC interrupts. */ + if (!rhsc_enable && !rhsc_status && !changed) { + rhsc_enable = OHCI_INTR_RHSC; + ohci_writel(ohci, rhsc_enable, &ohci->regs->intrenable); } /* Keep on polling until we know a device is connected @@ -383,7 +386,7 @@ if (any_connected || !device_may_wakeup(&ohci_to_hcd(ohci) ->self.root_hub->dev)) { - if (rhsc) + if (rhsc_enable) poll_rh = 0; } else { ohci->autostop = 1; @@ -396,34 +399,45 @@ ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (rhsc && time_after_eq(jiffies, + } else if (time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & OHCI_SCHED_ENABLES)) { ohci_rh_suspend(ohci, 1); - poll_rh = 0; + if (rhsc_enable) + poll_rh = 0; } } break; - /* if there is a port change, autostart or ask to be resumed */ case OHCI_USB_SUSPEND: case OHCI_USB_RESUME: + /* if there is a port change, autostart or ask to be resumed */ if (changed) { if (ohci->autostop) ohci_rh_resume(ohci); else usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); - } else { - if (!rhsc && (ohci->autostop || - ohci_to_hcd(ohci)->self.root_hub-> - do_remote_wakeup)) - ohci_writel(ohci, OHCI_INTR_RHSC, - &ohci->regs->intrenable); - /* everything is idle, no need for polling */ + /* If remote wakeup is disabled, stop polling */ + } else if (!ohci->autostop && + !ohci_to_hcd(ohci)->self.root_hub-> + do_remote_wakeup) { poll_rh = 0; + + } else { + /* If no status changes are pending, + * enable RHSC interrupts + */ + if (!rhsc_enable && !rhsc_status) { + rhsc_enable = OHCI_INTR_RHSC; + ohci_writel(ohci, rhsc_enable, + &ohci->regs->intrenable); + } + /* Keep polling until RHSC is enabled */ + if (rhsc_enable) + poll_rh = 0; } break; } @@ -441,18 +455,22 @@ * autostop isn't used when CONFIG_PM is turned off. */ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, - int any_connected) + int any_connected, int rhsc_status) { /* If RHSC is enabled, don't poll */ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) return 0; - /* If no status changes are pending, enable status-change interrupts */ - if (!changed) { - ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); - return 0; - } - return 1; + /* If status changes are pending, continue polling. + * Conversely, if no status changes are pending but the RHSC + * status bit was set, then RHSC may be broken so continue polling. + */ + if (changed || rhsc_status) + return 1; + + /* It's safe to re-enable RHSC interrupts */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + return 0; } #endif /* CONFIG_PM */ @@ -467,6 +485,7 @@ struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; int any_connected = 0; + int rhsc_status; unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); @@ -492,12 +511,10 @@ length++; } - /* Some broken controllers never turn off RHCS in the interrupt - * status register. For their sake we won't re-enable RHSC - * interrupts if the flag is already set. - */ - if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) - changed = 1; + /* Clear the RHSC status flag before reading the port statuses */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrstatus); + rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) & + OHCI_INTR_RHSC; /* look at each port */ for (i = 0; i < ohci->num_ports; i++) { @@ -517,7 +534,7 @@ } hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed, - any_connected); + any_connected, rhsc_status); done: spin_unlock_irqrestore (&ohci->lock, flags); --- linux-2.6.27.orig/drivers/usb/host/ehci-hcd.c +++ linux-2.6.27/drivers/usb/host/ehci-hcd.c @@ -1049,6 +1049,12 @@ { int retval = 0; + set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || + test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) + printk(KERN_WARNING "Warning! ehci_hcd should always be loaded" + " before uhci_hcd and ohci_hcd, not after\n"); + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", hcd_name, sizeof(struct ehci_qh), sizeof(struct ehci_qtd), @@ -1056,8 +1062,10 @@ #ifdef DEBUG ehci_debug_root = debugfs_create_dir("ehci", NULL); - if (!ehci_debug_root) - return -ENOENT; + if (!ehci_debug_root) { + retval = -ENOENT; + goto err_debug; + } #endif #ifdef PLATFORM_DRIVER @@ -1104,7 +1112,9 @@ #ifdef DEBUG debugfs_remove(ehci_debug_root); ehci_debug_root = NULL; +err_debug: #endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); return retval; } module_init(ehci_hcd_init); @@ -1126,6 +1136,7 @@ #ifdef DEBUG debugfs_remove(ehci_debug_root); #endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); } module_exit(ehci_hcd_cleanup); --- linux-2.6.27.orig/drivers/usb/gadget/s3c2410_udc.c +++ linux-2.6.27/drivers/usb/gadget/s3c2410_udc.c @@ -1651,7 +1651,7 @@ return -EBUSY; if (!driver->bind || !driver->setup - || driver->speed != USB_SPEED_FULL) { + || driver->speed < USB_SPEED_FULL) { printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n", driver->bind, driver->setup, driver->speed); return -EINVAL; --- linux-2.6.27.orig/drivers/usb/gadget/u_ether.c +++ linux-2.6.27/drivers/usb/gadget/u_ether.c @@ -873,6 +873,13 @@ spin_lock(&dev->lock); dev->port_usb = link; link->ioport = dev; + if (netif_running(dev->net)) { + if (link->open) + link->open(link); + } else { + if (link->close) + link->close(link); + } spin_unlock(&dev->lock); netif_carrier_on(dev->net); --- linux-2.6.27.orig/drivers/usb/core/hcd.c +++ linux-2.6.27/drivers/usb/core/hcd.c @@ -81,6 +81,10 @@ /*-------------------------------------------------------------------------*/ +/* Keep track of which host controller drivers are loaded */ +unsigned long usb_hcds_loaded; +EXPORT_SYMBOL_GPL(usb_hcds_loaded); + /* host controllers we manage */ LIST_HEAD (usb_bus_list); EXPORT_SYMBOL_GPL (usb_bus_list); @@ -102,6 +106,9 @@ /* used when updating an endpoint's URB list */ static DEFINE_SPINLOCK(hcd_urb_list_lock); +/* used to protect against unlinking URBs after the device is gone */ +static DEFINE_SPINLOCK(hcd_urb_unlink_lock); + /* wait queue for synchronous unlinks */ DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); @@ -1373,10 +1380,25 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) { struct usb_hcd *hcd; - int retval; + int retval = -EIDRM; + unsigned long flags; - hcd = bus_to_hcd(urb->dev->bus); - retval = unlink1(hcd, urb, status); + /* Prevent the device and bus from going away while + * the unlink is carried out. If they are already gone + * then urb->use_count must be 0, since disconnected + * devices can't have any active URBs. + */ + spin_lock_irqsave(&hcd_urb_unlink_lock, flags); + if (atomic_read(&urb->use_count) > 0) { + retval = 0; + usb_get_dev(urb->dev); + } + spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); + if (retval == 0) { + hcd = bus_to_hcd(urb->dev->bus); + retval = unlink1(hcd, urb, status); + usb_put_dev(urb->dev); + } if (retval == 0) retval = -EINPROGRESS; @@ -1525,6 +1547,17 @@ hcd->driver->endpoint_disable(hcd, ep); } +/* Protect against drivers that try to unlink URBs after the device + * is gone, by waiting until all unlinks for @udev are finished. + * Since we don't currently track URBs by device, simply wait until + * nothing is running in the locked region of usb_hcd_unlink_urb(). + */ +void usb_hcd_synchronize_unlinks(struct usb_device *udev) +{ + spin_lock_irq(&hcd_urb_unlink_lock); + spin_unlock_irq(&hcd_urb_unlink_lock); +} + /*-------------------------------------------------------------------------*/ /* called in any context */ --- linux-2.6.27.orig/drivers/usb/core/hub.c +++ linux-2.6.27/drivers/usb/core/hub.c @@ -1349,6 +1349,7 @@ */ dev_dbg (&udev->dev, "unregistering device\n"); usb_disable_device(udev, 0); + usb_hcd_synchronize_unlinks(udev); usb_unlock_device(udev); @@ -3424,7 +3425,7 @@ USB_INTERFACE_BOUND) rebind = 1; } - if (rebind) + if (ret == 0 && rebind) usb_rebind_intf(cintf); } } --- linux-2.6.27.orig/drivers/usb/core/hcd.h +++ linux-2.6.27/drivers/usb/core/hcd.h @@ -232,6 +232,7 @@ struct usb_host_endpoint *ep); extern void usb_hcd_disable_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep); +extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); extern int usb_hcd_get_frame_number(struct usb_device *udev); extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, @@ -482,4 +483,10 @@ */ extern struct rw_semaphore ehci_cf_port_reset_rwsem; +/* Keep track of which host controller drivers are loaded */ +#define USB_UHCI_LOADED 0 +#define USB_OHCI_LOADED 1 +#define USB_EHCI_LOADED 2 +extern unsigned long usb_hcds_loaded; + #endif /* __KERNEL__ */ --- linux-2.6.27.orig/drivers/usb/core/driver.c +++ linux-2.6.27/drivers/usb/core/driver.c @@ -1609,7 +1609,8 @@ status = usb_resume_both(udev); udev->last_busy = jiffies; usb_pm_unlock(udev); - do_unbind_rebind(udev, DO_REBIND); + if (status == 0) + do_unbind_rebind(udev, DO_REBIND); /* Now that the device is awake, we can start trying to autosuspend * it again. */ --- linux-2.6.27.orig/drivers/usb/core/urb.c +++ linux-2.6.27/drivers/usb/core/urb.c @@ -465,6 +465,12 @@ * indicating that the request has been canceled (rather than any other * code). * + * Drivers should not call this routine or related routines, such as + * usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect + * method has returned. The disconnect function should synchronize with + * a driver's I/O routines to insure that all URB-related activity has + * completed before it returns. + * * This request is always asynchronous. Success is indicated by * returning -EINPROGRESS, at which time the URB will probably not yet * have been given back to the device driver. When it is eventually @@ -541,6 +547,9 @@ * This routine may not be used in an interrupt context (such as a bottom * half or a completion handler), or when holding a spinlock, or in other * situations where the caller can't schedule(). + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_kill_urb(struct urb *urb) { @@ -568,6 +577,9 @@ * * this allows all outstanding URBs to be killed starting * from the back of the queue + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_kill_anchored_urbs(struct usb_anchor *anchor) { @@ -597,6 +609,9 @@ * from the back of the queue. This function is asynchronous. * The unlinking is just tiggered. It may happen after this * function has returned. + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_unlink_anchored_urbs(struct usb_anchor *anchor) { --- linux-2.6.27.orig/drivers/usb/storage/unusual_devs.h +++ linux-2.6.27/drivers/usb/storage/unusual_devs.h @@ -1745,6 +1745,15 @@ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Alexandre Oliva + * JMicron responds to USN and several other SCSI ioctls with a + * residue that causes subsequent I/O requests to fail. */ +UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, + "JMicron", + "USB to ATA/ATAPI Bridge", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Robert Schedel * Note: this is a 'super top' device like the above 14cd/6600 device */ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, --- linux-2.6.27.orig/drivers/video/vesafb.c +++ linux-2.6.27/drivers/video/vesafb.c @@ -28,6 +28,12 @@ #define dac_reg (0x3c8) #define dac_val (0x3c9) +struct vesafb_info +{ + u32 pseudo_palette[256]; + int mtrr_hdl; +}; + /* --------------------------------------------------------------------- */ static struct fb_var_screeninfo vesafb_defined __initdata = { @@ -47,16 +53,37 @@ .accel = FB_ACCEL_NONE, }; +#ifndef MODULE static int inverse __read_mostly; +#endif static int mtrr __read_mostly; /* disable mtrr */ static int vram_remap __initdata; /* Set amount of memory to be used */ static int vram_total __initdata; /* Set total amount of memory */ static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */ +static int redraw __read_mostly; static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */ +static int ywrap __read_mostly; static void (*pmi_start)(void) __read_mostly; static void (*pmi_pal) (void) __read_mostly; static int depth __read_mostly; static int vga_compat __read_mostly; + +module_param(redraw, bool, 0); +module_param(ypan, bool, 0); +module_param(ywrap, bool, 0); +module_param_named(vgapal, pmi_setpal, invbool, 0); +MODULE_PARM_DESC(vgapal, "Use VGA for setting palette (default)"); +module_param_named(pmipal, pmi_setpal, bool, 0); +MODULE_PARM_DESC(pmipal, "Use PMI for setting palette"); +module_param(mtrr, bool, 0); +MODULE_PARM_DESC(mtrr, "Enable MTRR support (default)"); +module_param_named(nomtrr, mtrr, invbool, 0); +MODULE_PARM_DESC(nomtrr, "Disable MTRR support"); +module_param(vram_remap, int, 0); +MODULE_PARM_DESC(vram_remap, "Set total amount of memory to be used"); +module_param(vram_total, int, 0); +MODULE_PARM_DESC(vram_total, "Total amount of memory"); + /* --------------------------------------------------------------------- */ static int vesafb_pan_display(struct fb_var_screeninfo *var, @@ -183,6 +210,7 @@ .fb_imageblit = cfb_imageblit, }; +#ifndef MODULE static int __init vesafb_setup(char *options) { char *this_opt; @@ -216,6 +244,7 @@ } return 0; } +#endif static int __init vesafb_probe(struct platform_device *dev) { @@ -463,8 +492,28 @@ return err; } +static int __exit vesafb_remove(struct platform_device *device) +{ + struct fb_info *info = dev_get_drvdata(&device->dev); + + unregister_framebuffer(info); +#ifdef CONFIG_MTRR + { + struct vesafb_info *vfb_info = (struct vesafb_info *) info->par; + if (vfb_info->mtrr_hdl >= 0) + mtrr_del(vfb_info->mtrr_hdl, 0, 0); + } +#endif + iounmap(info->screen_base); + framebuffer_release(info); + release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len); + + return 0; +} + static struct platform_driver vesafb_driver = { .probe = vesafb_probe, + .remove = vesafb_remove, .driver = { .name = "vesafb", }, @@ -475,11 +524,18 @@ static int __init vesafb_init(void) { int ret; +#ifndef MODULE char *option = NULL; /* ignore error return of fb_get_options */ fb_get_options("vesafb", &option); vesafb_setup(option); +#else + if (redraw) + ypan = 0; + if (ywrap) + ypan = 2; +#endif ret = platform_driver_register(&vesafb_driver); if (!ret) { @@ -498,6 +554,14 @@ return ret; } + +static void __exit vesafb_exit(void) +{ + platform_device_unregister(vesafb_device); + platform_driver_unregister(&vesafb_driver); +} + module_init(vesafb_init); +module_exit(vesafb_exit); MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/drivers/video/Kconfig +++ linux-2.6.27/drivers/video/Kconfig @@ -673,8 +673,8 @@ If unsure, say N. config FB_VESA - bool "VESA VGA graphics support" - depends on (FB = y) && X86 + tristate "VESA VGA graphics support" + depends on FB && X86 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT --- linux-2.6.27.orig/drivers/video/console/fbcon.c +++ linux-2.6.27/drivers/video/console/fbcon.c @@ -2996,8 +2996,8 @@ p = &fb_display[vc->vc_num]; set_blitting_type(vc, info); var_to_display(p, &info->var, info); - cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres); + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; vc_resize(vc, cols, rows); --- linux-2.6.27.orig/drivers/acpi/ec.c +++ linux-2.6.27/drivers/acpi/ec.c @@ -1,7 +1,7 @@ /* - * ec.c - ACPI Embedded Controller Driver (v2.0) + * ec.c - ACPI Embedded Controller Driver (v2.1) * - * Copyright (C) 2006, 2007 Alexey Starikovskiy + * Copyright (C) 2006-2008 Alexey Starikovskiy * Copyright (C) 2006 Denis Sadykov * Copyright (C) 2004 Luming Yu * Copyright (C) 2001, 2002 Andy Grover @@ -26,7 +26,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* Uncomment next line to get verbose print outs*/ +/* Uncomment next line to get verbose printout */ /* #define DEBUG */ #include @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -65,22 +66,21 @@ ACPI_EC_COMMAND_QUERY = 0x84, }; -/* EC events */ -enum ec_event { - ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ - ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ -}; - #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ +#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts + per one transaction */ + enum { - EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ - EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ + EC_FLAGS_GPE_MODE, /* Expect GPE to be sent + * for status change */ EC_FLAGS_NO_GPE, /* Don't use GPE mode */ - EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ + EC_FLAGS_GPE_STORM, /* GPE storm detected */ + EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and + * OpReg are installed */ }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -95,6 +95,15 @@ u8 query_bit; }; +struct transaction { + const u8 *wdata; + u8 *rdata; + unsigned short irq_count; + u8 command; + u8 wlen; + u8 rlen; +}; + static struct acpi_ec { acpi_handle handle; unsigned long gpe; @@ -105,9 +114,8 @@ struct mutex lock; wait_queue_head_t wait; struct list_head list; - struct delayed_work work; - atomic_t irq_count; - u8 handlers_installed; + struct transaction *curr; + spinlock_t curr_lock; } *boot_ec, *first_ec; /* @@ -150,7 +158,7 @@ { u8 x = inb(ec->data_addr); pr_debug(PREFIX "---> data = 0x%2.2x\n", x); - return inb(ec->data_addr); + return x; } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) @@ -165,158 +173,172 @@ outb(data, ec->data_addr); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) +static int ec_transaction_done(struct acpi_ec *ec) { - if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags)) - return 0; - if (event == ACPI_EC_EVENT_OBF_1) { - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) - return 1; - } else if (event == ACPI_EC_EVENT_IBF_0) { - if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) - return 1; - } - - return 0; + unsigned long flags; + int ret = 0; + spin_lock_irqsave(&ec->curr_lock, flags); + if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) + ret = 1; + spin_unlock_irqrestore(&ec->curr_lock, flags); + return ret; } -static void ec_schedule_ec_poll(struct acpi_ec *ec) +static void gpe_transaction(struct acpi_ec *ec, u8 status) { - if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) - schedule_delayed_work(&ec->work, - msecs_to_jiffies(ACPI_EC_DELAY)); + unsigned long flags; + spin_lock_irqsave(&ec->curr_lock, flags); + if (!ec->curr) + goto unlock; + if (ec->curr->wlen > 0) { + if ((status & ACPI_EC_FLAG_IBF) == 0) { + acpi_ec_write_data(ec, *(ec->curr->wdata++)); + --ec->curr->wlen; + } else + /* false interrupt, state didn't change */ + ++ec->curr->irq_count; + + } else if (ec->curr->rlen > 0) { + if ((status & ACPI_EC_FLAG_OBF) == 1) { + *(ec->curr->rdata++) = acpi_ec_read_data(ec); + --ec->curr->rlen; + } else + /* false interrupt, state didn't change */ + ++ec->curr->irq_count; + } +unlock: + spin_unlock_irqrestore(&ec->curr_lock, flags); } -static void ec_switch_to_poll_mode(struct acpi_ec *ec) +static int acpi_ec_wait(struct acpi_ec *ec) { + if (wait_event_timeout(ec->wait, ec_transaction_done(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + /* missing GPEs, switch back to poll mode */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " + "switch off interrupt mode.\n"); set_bit(EC_FLAGS_NO_GPE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); + return 1; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) { - atomic_set(&ec->irq_count, 0); - if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && - likely(!force_poll)) { - if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), - msecs_to_jiffies(ACPI_EC_DELAY))) - return 0; - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - if (acpi_ec_check_status(ec, event)) { - /* missing GPEs, switch back to poll mode */ - if (printk_ratelimit()) - pr_info(PREFIX "missing confirmations, " - "switch off interrupt mode.\n"); - ec_switch_to_poll_mode(ec); - ec_schedule_ec_poll(ec); - return 0; - } - } else { - unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - while (time_before(jiffies, delay)) { - if (acpi_ec_check_status(ec, event)) - return 0; - msleep(1); - } - if (acpi_ec_check_status(ec,event)) + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) + return acpi_os_execute(OSL_EC_BURST_HANDLER, + acpi_ec_gpe_query, ec); + } + return 0; +} + +static int ec_poll(struct acpi_ec *ec) +{ + unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + msleep(1); + while (time_before(jiffies, delay)) { + gpe_transaction(ec, acpi_ec_read_status(ec)); + msleep(1); + if (ec_transaction_done(ec)) return 0; } - pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", - acpi_ec_read_status(ec), - (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); return -ETIME; } -static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, +static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, + struct transaction *t, int force_poll) { - int result = 0; - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); + unsigned long tmp; + int ret = 0; pr_debug(PREFIX "transaction start\n"); - acpi_ec_write_cmd(ec, command); - for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); - if (result) { - pr_err(PREFIX - "write_cmd timeout, command = %d\n", command); - goto end; - } - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - acpi_ec_write_data(ec, *(wdata++)); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + } + /* start transaction */ + spin_lock_irqsave(&ec->curr_lock, tmp); + /* following two actions should be kept atomic */ + t->irq_count = 0; + ec->curr = t; + acpi_ec_write_cmd(ec, ec->curr->command); + if (ec->curr->command == ACPI_EC_COMMAND_QUERY) + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); + spin_unlock_irqrestore(&ec->curr_lock, tmp); + /* if we selected poll mode or failed in GPE-mode do a poll loop */ + if (force_poll || + !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) || + acpi_ec_wait(ec)) + ret = ec_poll(ec); + pr_debug(PREFIX "transaction end\n"); + spin_lock_irqsave(&ec->curr_lock, tmp); + ec->curr = NULL; + spin_unlock_irqrestore(&ec->curr_lock, tmp); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* check if we received SCI during transaction */ + ec_check_sci(ec, acpi_ec_read_status(ec)); + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + t->irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_debug(PREFIX "GPE storm detected\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } + return ret; +} - if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); - if (result) { - pr_err(PREFIX - "finish-write timeout, command = %d\n", command); - goto end; - } - } else if (command == ACPI_EC_COMMAND_QUERY) - clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); +static int ec_check_ibf0(struct acpi_ec *ec) +{ + u8 status = acpi_ec_read_status(ec); + return (status & ACPI_EC_FLAG_IBF) == 0; +} - for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); - if (result) { - pr_err(PREFIX "read timeout, command = %d\n", command); - goto end; - } - /* Don't expect GPE after last read */ - if (rdata_len > 1) - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - *(rdata++) = acpi_ec_read_data(ec); - } - end: - pr_debug(PREFIX "transaction end\n"); - return result; +static int ec_wait_ibf0(struct acpi_ec *ec) +{ + unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + /* interrupt wait manually if GPE mode is not active */ + unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ? + msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1); + while (time_before(jiffies, delay)) + if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout)) + return 0; + return -ETIME; } -static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, +static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, int force_poll) { int status; u32 glk; - - if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) + if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) return -EINVAL; - - if (rdata) - memset(rdata, 0, rdata_len); - + if (t->rdata) + memset(t->rdata, 0, t->rlen); mutex_lock(&ec->lock); if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) { - mutex_unlock(&ec->lock); - return -ENODEV; + status = -ENODEV; + goto unlock; } } - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); - if (status) { + if (ec_wait_ibf0(ec)) { pr_err(PREFIX "input buffer is not empty, " "aborting transaction\n"); + status = -ETIME; goto end; } - - status = acpi_ec_transaction_unlocked(ec, command, - wdata, wdata_len, - rdata, rdata_len, - force_poll); - - end: - + status = acpi_ec_transaction_unlocked(ec, t, force_poll); +end: if (ec->global_lock) acpi_release_global_lock(glk); +unlock: mutex_unlock(&ec->lock); - return status; } @@ -327,21 +349,32 @@ int acpi_ec_burst_enable(struct acpi_ec *ec) { u8 d; - return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0); + struct transaction t = {.command = ACPI_EC_BURST_ENABLE, + .wdata = NULL, .rdata = &d, + .wlen = 0, .rlen = 1}; + + return acpi_ec_transaction(ec, &t, 0); } int acpi_ec_burst_disable(struct acpi_ec *ec) { - return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0); + struct transaction t = {.command = ACPI_EC_BURST_DISABLE, + .wdata = NULL, .rdata = NULL, + .wlen = 0, .rlen = 0}; + + return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? + acpi_ec_transaction(ec, &t, 0) : 0; } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) { int result; u8 d; + struct transaction t = {.command = ACPI_EC_COMMAND_READ, + .wdata = &address, .rdata = &d, + .wlen = 1, .rlen = 1}; - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, - &address, 1, &d, 1, 0); + result = acpi_ec_transaction(ec, &t, 0); *data = d; return result; } @@ -349,8 +382,11 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) { u8 wdata[2] = { address, data }; - return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, - wdata, 2, NULL, 0, 0); + struct transaction t = {.command = ACPI_EC_COMMAND_WRITE, + .wdata = wdata, .rdata = NULL, + .wlen = 2, .rlen = 0}; + + return acpi_ec_transaction(ec, &t, 0); } /* @@ -412,12 +448,13 @@ u8 * rdata, unsigned rdata_len, int force_poll) { + struct transaction t = {.command = command, + .wdata = wdata, .rdata = rdata, + .wlen = wdata_len, .rlen = rdata_len}; if (!first_ec) return -ENODEV; - return acpi_ec_transaction(first_ec, command, wdata, - wdata_len, rdata, rdata_len, - force_poll); + return acpi_ec_transaction(first_ec, &t, force_poll); } EXPORT_SYMBOL(ec_transaction); @@ -426,7 +463,9 @@ { int result; u8 d; - + struct transaction t = {.command = ACPI_EC_COMMAND_QUERY, + .wdata = NULL, .rdata = &d, + .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; @@ -436,7 +475,7 @@ * bit to be cleared (and thus clearing the interrupt source). */ - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0); + result = acpi_ec_transaction(ec, &t, 0); if (result) return result; @@ -513,46 +552,26 @@ static u32 acpi_ec_gpe_handler(void *data) { - acpi_status status = AE_OK; struct acpi_ec *ec = data; - u8 state = acpi_ec_read_status(ec); + u8 status; pr_debug(PREFIX "~~~> interrupt\n"); - atomic_inc(&ec->irq_count); - if (atomic_read(&ec->irq_count) > 5) { - pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); - ec_switch_to_poll_mode(ec); - goto end; - } - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) + status = acpi_ec_read_status(ec); + + gpe_transaction(ec, status); + if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) wake_up(&ec->wait); - if (state & ACPI_EC_FLAG_SCI) { - if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - status = acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); - } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && - !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && - in_interrupt()) { + ec_check_sci(ec, status); + if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { /* this is non-query, must be confirmation */ if (printk_ratelimit()) pr_info(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); - clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); } -end: - ec_schedule_ec_poll(ec); - return ACPI_SUCCESS(status) ? - ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; -} - -static void do_ec_poll(struct work_struct *work) -{ - struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); - atomic_set(&ec->irq_count, 0); - (void)acpi_ec_gpe_handler(ec); + return ACPI_INTERRUPT_HANDLED; } /* -------------------------------------------------------------------------- @@ -696,8 +715,7 @@ mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); - INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); - atomic_set(&ec->irq_count, 0); + spin_lock_init(&ec->curr_lock); return ec; } @@ -736,22 +754,15 @@ return AE_CTRL_TERMINATE; } -static void ec_poll_stop(struct acpi_ec *ec) -{ - clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); - cancel_delayed_work(&ec->work); -} - static void ec_remove_handlers(struct acpi_ec *ec) { - ec_poll_stop(ec); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) pr_err(PREFIX "failed to remove space handler\n"); if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler))) pr_err(PREFIX "failed to remove gpe handler\n"); - ec->handlers_installed = 0; + clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); } static int acpi_ec_add(struct acpi_device *device) @@ -846,17 +857,15 @@ static int ec_install_handlers(struct acpi_ec *ec) { acpi_status status; - if (ec->handlers_installed) + if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) return 0; status = acpi_install_gpe_handler(NULL, ec->gpe, - ACPI_GPE_EDGE_TRIGGERED, - &acpi_ec_gpe_handler, ec); + ACPI_GPE_EDGE_TRIGGERED, + &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) return -ENODEV; - acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, @@ -866,7 +875,7 @@ return -ENODEV; } - ec->handlers_installed = 1; + set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); return 0; } @@ -887,7 +896,6 @@ /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - ec_schedule_ec_poll(ec); return ret; } @@ -906,7 +914,7 @@ int __init acpi_boot_ec_enable(void) { - if (!boot_ec || boot_ec->handlers_installed) + if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) return 0; if (!ec_install_handlers(boot_ec)) { first_ec = boot_ec; --- linux-2.6.27.orig/drivers/acpi/reboot.c +++ linux-2.6.27/drivers/acpi/reboot.c @@ -15,9 +15,28 @@ rr = &acpi_gbl_FADT.reset_register; - /* Is the reset register supported? */ - if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || - rr->bit_width != 8 || rr->bit_offset != 0) + /* + * Is the ACPI reset register supported? + * + * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates + * whether the ACPI reset mechanism is supported. + * + * However, some boxes have this bit clear, yet a valid + * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only + * mechanism that works for them after S3. + * + * This suggests that other operating systems may not be checking + * the RESET_REG_SUP bit, and are using other means to decide + * whether to use the ACPI reboot mechanism or not. + * + * So when acpi reboot is requested, + * only the reset_register is checked. If the following + * conditions are met, it indicates that the reset register is supported. + * a. reset_register is not zero + * b. the access width is eight + * c. the bit_offset is zero + */ + if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) return; reset_value = acpi_gbl_FADT.reset_value; --- linux-2.6.27.orig/drivers/acpi/Kconfig +++ linux-2.6.27/drivers/acpi/Kconfig @@ -301,6 +301,17 @@ bool default ACPI_CUSTOM_DSDT_FILE != "" +config ACPI_CUSTOM_DSDT_INITRD + bool "Read Custom DSDT from initramfs" + depends on BLK_DEV_INITRD + default n + help + This option supports a custom DSDT by optionally loading it from initrd. + See Documentation/acpi/dsdt-override.txt + + If you are not using this feature now, but may use it later, + it is safe to say Y here. + config ACPI_BLACKLIST_YEAR int "Disable ACPI for systems before Jan 1st this year" if X86_32 default 0 --- linux-2.6.27.orig/drivers/acpi/processor_idle.c +++ linux-2.6.27/drivers/acpi/processor_idle.c @@ -129,52 +129,7 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { { set_max_cstate, "IBM ThinkPad R40e", { DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET70WW")}, (void *)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (void*)1}, + DMI_MATCH(DMI_BIOS_VERSION,"1SET")}, (void *)1}, { set_max_cstate, "Medion 41700", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J")}, (void *)1}, --- linux-2.6.27.orig/drivers/acpi/dock.c +++ linux-2.6.27/drivers/acpi/dock.c @@ -604,14 +604,17 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) { struct dock_station *ds = data; + struct acpi_device *tmp; switch (event) { case ACPI_NOTIFY_BUS_CHECK: - if (!dock_in_progress(ds) && dock_present(ds)) { + if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, + &tmp)) { begin_dock(ds); dock(ds); if (!dock_present(ds)) { printk(KERN_ERR PREFIX "Unable to dock!\n"); + complete_dock(ds); break; } atomic_notifier_call_chain(&dock_notifier_list, --- linux-2.6.27.orig/drivers/acpi/button.c +++ linux-2.6.27/drivers/acpi/button.c @@ -262,6 +262,7 @@ return -ENODEV; /* input layer checks if event is redundant */ input_report_switch(button->input, SW_LID, !state); + input_sync(button->input); return 0; } @@ -285,8 +286,8 @@ input_report_key(input, keycode, 1); input_sync(input); input_report_key(input, keycode, 0); + input_sync(input); } - input_sync(input); acpi_bus_generate_proc_event(button->device, event, ++button->pushed); --- linux-2.6.27.orig/drivers/acpi/osl.c +++ linux-2.6.27/drivers/acpi/osl.c @@ -96,6 +96,11 @@ #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ static char osi_additional_string[OSI_STRING_LENGTH_MAX]; +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD +static __initdata int acpi_no_initrd_override; +extern struct acpi_table_header *acpi_find_dsdt_initrd(void); +#endif + /* * "Ode to _OSI(Linux)" * @@ -338,6 +343,16 @@ if (strncmp(existing_table->signature, "DSDT", 4) == 0) *new_table = (struct acpi_table_header *)AmlCode; #endif +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD + if ((strncmp(existing_table->signature, "DSDT", 4) == 0) && + !acpi_no_initrd_override) { + struct acpi_table_header *initrd_table; + + initrd_table = acpi_find_dsdt_initrd(); + if (initrd_table) + *new_table = initrd_table; + } +#endif if (*new_table != NULL) { printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], " "this is unsafe: tainting kernel\n", @@ -348,6 +363,15 @@ return AE_OK; } +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD +static int __init acpi_no_initrd_override_setup(char *s) +{ + acpi_no_initrd_override = 1; + return 1; +} +__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup); +#endif + static irqreturn_t acpi_irq(int irq, void *dev_id) { u32 handled; --- linux-2.6.27.orig/drivers/acpi/sleep/main.c +++ linux-2.6.27/drivers/acpi/sleep/main.c @@ -200,6 +200,8 @@ break; } + /* If ACPI is not enabled by the BIOS, we need to enable it here. */ + acpi_enable(); /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(acpi_state); @@ -296,6 +298,14 @@ DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "HP xw4600 Workstation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ --- linux-2.6.27.orig/drivers/acpi/executer/exconfig.c +++ linux-2.6.27/drivers/acpi/executer/exconfig.c @@ -284,6 +284,7 @@ u32 table_index; acpi_status status; u32 length; + void *maddr; ACPI_FUNCTION_TRACE(ex_load_op); @@ -315,14 +316,24 @@ } } - /* - * We will simply map the memory region for the table. However, the - * memory region is technically not guaranteed to remain stable and - * we may eventually have to copy the table to a local buffer. - */ + length = obj_desc->region.length; + table_desc.pointer = ACPI_ALLOCATE(length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + maddr = acpi_os_map_memory(obj_desc->region.address, length); + if (!maddr) { + ACPI_FREE(table_desc.pointer); + return_ACPI_STATUS(AE_NO_MEMORY); + } + ACPI_MEMCPY(table_desc.pointer, maddr, length); + acpi_os_unmap_memory(maddr, length); + + /* Keep the address for the pretty table info print */ table_desc.address = obj_desc->region.address; table_desc.length = obj_desc->region.length; - table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; + table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; break; case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ --- linux-2.6.27.orig/drivers/acpi/hardware/hwsleep.c +++ linux-2.6.27/drivers/acpi/hardware/hwsleep.c @@ -78,19 +78,17 @@ return_ACPI_STATUS(status); } - /* Set the vector */ + /* + * According to the ACPI specification 2.0c and later, the 64-bit + * waking vector should be cleared and the 32-bit waking vector should + * be used, unless we want the wake-up code to be called by the BIOS in + * Protected Mode. Some systems (for example HP dv5-1004nr) are known + * to fail to resume if the 64-bit vector is used. + */ + if (facs->version >= 1) + facs->xfirmware_waking_vector = 0; - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - facs->firmware_waking_vector = (u32) physical_address; - } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ - facs->xfirmware_waking_vector = physical_address; - } + facs->firmware_waking_vector = (u32)physical_address; return_ACPI_STATUS(AE_OK); } @@ -134,20 +132,7 @@ } /* Get the vector */ - - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - *physical_address = - (acpi_physical_address) facs->firmware_waking_vector; - } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ - *physical_address = - (acpi_physical_address) facs->xfirmware_waking_vector; - } + *physical_address = (acpi_physical_address)facs->firmware_waking_vector; return_ACPI_STATUS(AE_OK); } @@ -627,6 +612,13 @@ } /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + /* + * Some BIOSes assume that WAK_STS will be cleared on resume and use + * it to determine whether the system is rebooting or resuming. Clear + * it for compatibility. + */ + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ --- linux-2.6.27.orig/drivers/dca/dca-core.c +++ linux-2.6.27/drivers/dca/dca-core.c @@ -270,6 +270,6 @@ dca_sysfs_exit(); } -module_init(dca_init); +subsys_initcall(dca_init); module_exit(dca_exit); --- linux-2.6.27.orig/drivers/gpio/gpiolib.c +++ linux-2.6.27/drivers/gpio/gpiolib.c @@ -1020,7 +1020,7 @@ might_sleep_if(extra_checks); chip = gpio_to_chip(gpio); - return chip->get(chip, gpio - chip->base); + return chip->get ? chip->get(chip, gpio - chip->base) : 0; } EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); --- linux-2.6.27.orig/drivers/block/cpqarray.c +++ linux-2.6.27/drivers/block/cpqarray.c @@ -567,7 +567,12 @@ num_cntlrs_reg++; } - return(num_cntlrs_reg); + if (num_cntlrs_reg) + return 0; + else { + pci_unregister_driver(&cpqarray_pci_driver); + return -ENODEV; + } } /* Function to find the first free pointer into our hba[] array */ --- linux-2.6.27.orig/drivers/block/cciss.c +++ linux-2.6.27/drivers/block/cciss.c @@ -96,6 +96,8 @@ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} @@ -133,6 +135,8 @@ {0x3245103C, "Smart Array P410i", &SA5_access}, {0x3247103C, "Smart Array P411", &SA5_access}, {0x3249103C, "Smart Array P812", &SA5_access}, + {0x324A103C, "Smart Array P712m", &SA5_access}, + {0x324B103C, "Smart Array P711m", &SA5_access}, {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; @@ -1365,6 +1369,7 @@ disk->first_minor = drv_index << NWD_SHIFT; disk->fops = &cciss_fops; disk->private_data = &h->drv[drv_index]; + disk->driverfs_dev = &h->pdev->dev; /* Set up queue information */ blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); @@ -3403,7 +3408,8 @@ int i; int j = 0; int rc; - int dac; + int dac, return_code; + InquiryData_struct *inq_buff = NULL; i = alloc_cciss_hba(); if (i < 0) @@ -3509,6 +3515,25 @@ /* Turn the interrupts on so we can service requests */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); + /* Get the firmware version */ + inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL); + if (inq_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + goto clean4; + } + + return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff, + sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD); + if (return_code == IO_OK) { + hba[i]->firm_ver[0] = inq_buff->data_byte[32]; + hba[i]->firm_ver[1] = inq_buff->data_byte[33]; + hba[i]->firm_ver[2] = inq_buff->data_byte[34]; + hba[i]->firm_ver[3] = inq_buff->data_byte[35]; + } else { /* send command failed */ + printk(KERN_WARNING "cciss: unable to determine firmware" + " version of controller\n"); + } + cciss_procinit(i); hba[i]->cciss_max_sectors = 2048; @@ -3519,6 +3544,7 @@ return 1; clean4: + kfree(inq_buff); #ifdef CONFIG_CISS_SCSI_TAPE kfree(hba[i]->scsi_rejects.complete); #endif --- linux-2.6.27.orig/drivers/dma/ioat_dma.c +++ linux-2.6.27/drivers/dma/ioat_dma.c @@ -519,7 +519,7 @@ } hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; - if (new->async_tx.callback) { + if (first->async_tx.callback) { hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; if (first != new) { /* move callback into to last desc */ @@ -611,7 +611,7 @@ } hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS; - if (new->async_tx.callback) { + if (first->async_tx.callback) { hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; if (first != new) { /* move callback into to last desc */ @@ -801,6 +801,12 @@ struct ioat_desc_sw *desc, *_desc; int in_use_descs = 0; + /* Before freeing channel resources first check + * if they have been previously allocated for this channel. + */ + if (ioat_chan->desccount == 0) + return; + tasklet_disable(&ioat_chan->cleanup_task); ioat_dma_memcpy_cleanup(ioat_chan); @@ -863,6 +869,7 @@ ioat_chan->last_completion = ioat_chan->completion_addr = 0; ioat_chan->pending = 0; ioat_chan->dmacount = 0; + ioat_chan->desccount = 0; ioat_chan->watchdog_completion = 0; ioat_chan->last_compl_desc_addr_hw = 0; ioat_chan->watchdog_tcp_cookie = --- linux-2.6.27.orig/drivers/dma/iovlock.c +++ linux-2.6.27/drivers/dma/iovlock.c @@ -55,7 +55,6 @@ int nr_iovecs = 0; int iovec_len_used = 0; int iovec_pages_used = 0; - long err; /* don't pin down non-user-based iovecs */ if (segment_eq(get_fs(), KERNEL_DS)) @@ -72,23 +71,21 @@ local_list = kmalloc(sizeof(*local_list) + (nr_iovecs * sizeof (struct dma_page_list)) + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); - if (!local_list) { - err = -ENOMEM; + if (!local_list) goto out; - } /* list of pages starts right after the page list array */ pages = (struct page **) &local_list->page_list[nr_iovecs]; + local_list->nr_iovecs = 0; + for (i = 0; i < nr_iovecs; i++) { struct dma_page_list *page_list = &local_list->page_list[i]; len -= iov[i].iov_len; - if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) { - err = -EFAULT; + if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) goto unpin; - } page_list->nr_pages = num_pages_spanned(&iov[i]); page_list->base_address = iov[i].iov_base; @@ -109,10 +106,8 @@ NULL); up_read(¤t->mm->mmap_sem); - if (ret != page_list->nr_pages) { - err = -ENOMEM; + if (ret != page_list->nr_pages) goto unpin; - } local_list->nr_iovecs = i + 1; } @@ -122,7 +117,7 @@ unpin: dma_unpin_iovec_pages(local_list); out: - return ERR_PTR(err); + return NULL; } void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) --- linux-2.6.27.orig/drivers/scsi/scsi_transport_fc.c +++ linux-2.6.27/drivers/scsi/scsi_transport_fc.c @@ -479,10 +479,30 @@ MODULE_PARM_DESC(dev_loss_tmo, "Maximum number of seconds that the FC transport should" " insulate the loss of a remote port. Once this value is" - " exceeded, the scsi target is removed. Value should be" + " exceeded, the scsi target may be removed. Reference the" + " remove_on_dev_loss module parameter. Value should be" " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT."); /* + * remove_on_dev_loss: controls whether the transport will + * remove a scsi target after the device loss timer expires. + * Removal on disconnect is modeled after the USB subsystem + * and expects subsystems layered on SCSI to be aware of + * potential device loss and handle it appropriately. However, + * many subsystems do not support device removal, leaving situations + * where structure references may remain, causing new device + * name assignments, etc., if the target returns. + */ +static unsigned int fc_remove_on_dev_loss = 0; +module_param_named(remove_on_dev_loss, fc_remove_on_dev_loss, + int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(remove_on_dev_loss, + "Boolean. When the device loss timer fires, this variable" + " controls whether the scsi infrastructure for the target" + " device is removed. Values: zero means do not remove," + " non-zero means remove. Default is zero."); + +/** * Netlink Infrastructure */ @@ -2371,7 +2391,8 @@ if (i->f->terminate_rport_io) i->f->terminate_rport_io(rport); - scsi_remove_target(&rport->dev); + if (fc_remove_on_dev_loss) + scsi_remove_target(&rport->dev); } @@ -3006,9 +3027,13 @@ return; } - dev_printk(KERN_ERR, &rport->dev, - "blocked FC remote port time out: removing target and " - "saving binding\n"); + if (fc_remove_on_dev_loss) + dev_printk(KERN_ERR, &rport->dev, + "blocked FC remote port time out: removing target and " + "saving binding\n"); + else + dev_printk(KERN_ERR, &rport->dev, + "blocked FC remote port time out: saving binding\n"); list_move_tail(&rport->peers, &fc_host->rport_bindings); --- linux-2.6.27.orig/drivers/scsi/sd.c +++ linux-2.6.27/drivers/scsi/sd.c @@ -1047,7 +1047,6 @@ good_bytes = sd_completed_bytes(SCpnt); break; case RECOVERED_ERROR: - case NO_SENSE: /* Inform the user, but make sure that it's not treated * as a hard error. */ @@ -1056,6 +1055,15 @@ memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); good_bytes = scsi_bufflen(SCpnt); break; + case NO_SENSE: + /* This indicates a false check condition, so ignore it. An + * unknown amount of data was transferred so treat it as an + * error. + */ + scsi_print_sense("sd", SCpnt); + SCpnt->result = 0; + memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); + break; case ABORTED_COMMAND: if (sshdr.asc == 0x10) { /* DIF: Disk detected corruption */ scsi_print_result(SCpnt); --- linux-2.6.27.orig/drivers/scsi/device_handler/scsi_dh_rdac.c +++ linux-2.6.27/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -590,6 +590,8 @@ {"STK", "OPENstorage D280"}, {"SUN", "CSM200_R"}, {"SUN", "LCSM100_F"}, + {"DELL", "MD3000"}, + {"DELL", "MD3000i"}, {NULL, NULL}, }; --- linux-2.6.27.orig/drivers/base/sys.c +++ linux-2.6.27/drivers/base/sys.c @@ -488,7 +488,8 @@ if (end == buf) return -EINVAL; *(unsigned long *)(ea->var) = new; - return end - buf; + /* Always return full write size even if we didn't consume all */ + return size; } EXPORT_SYMBOL_GPL(sysdev_store_ulong); @@ -511,7 +512,8 @@ if (end == buf || new > INT_MAX || new < INT_MIN) return -EINVAL; *(int *)(ea->var) = new; - return end - buf; + /* Always return full write size even if we didn't consume all */ + return size; } EXPORT_SYMBOL_GPL(sysdev_store_int); --- linux-2.6.27.orig/drivers/base/core.c +++ linux-2.6.27/drivers/base/core.c @@ -523,11 +523,16 @@ * device_initialize - init device structure. * @dev: device. * - * This prepares the device for use by other layers, - * including adding it to the device hierarchy. + * This prepares the device for use by other layers by initializing + * its fields. * It is the first half of device_register(), if called by - * that, though it can also be called separately, so one - * may use @dev's fields (e.g. the refcount). + * that function, though it can also be called separately, so one + * may use @dev's fields. In particular, get_device()/put_device() + * may be used for reference counting of @dev after calling this + * function. + * + * NOTE: Use put_device() to give up your reference instead of freeing + * @dev directly once you have called this function. */ void device_initialize(struct device *dev) { @@ -836,9 +841,13 @@ * This is part 2 of device_register(), though may be called * separately _iff_ device_initialize() has been called separately. * - * This adds it to the kobject hierarchy via kobject_add(), adds it + * This adds @dev to the kobject hierarchy via kobject_add(), adds it * to the global and sibling lists for the device, then * adds it to the other relevant subsystems of the driver model. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use put_device() to give up your + * reference instead. */ int device_add(struct device *dev) { @@ -965,6 +974,10 @@ * I.e. you should only call the two helpers separately if * have a clearly defined need to use and refcount the device * before it is added to the hierarchy. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use put_device() to give up the + * reference initialized in this function instead. */ int device_register(struct device *dev) { @@ -1243,7 +1256,7 @@ return dev; error: - kfree(dev); + put_device(dev); return ERR_PTR(retval); } EXPORT_SYMBOL_GPL(device_create_vargs); --- linux-2.6.27.orig/drivers/char/hvc_console.c +++ linux-2.6.27/drivers/char/hvc_console.c @@ -367,13 +367,13 @@ spin_lock_irqsave(&hp->lock, flags); if (--hp->count == 0) { - if (hp->ops->notifier_del) - hp->ops->notifier_del(hp, hp->data); - /* We are done with the tty pointer now. */ hp->tty = NULL; spin_unlock_irqrestore(&hp->lock, flags); + if (hp->ops->notifier_del) + hp->ops->notifier_del(hp, hp->data); + /* * Chain calls chars_in_buffer() and returns immediately if * there is no buffered data otherwise sleeps on a wait queue @@ -416,11 +416,11 @@ hp->n_outbuf = 0; hp->tty = NULL; + spin_unlock_irqrestore(&hp->lock, flags); + if (hp->ops->notifier_del) hp->ops->notifier_del(hp, hp->data); - spin_unlock_irqrestore(&hp->lock, flags); - while(temp_open_count) { --temp_open_count; kref_put(&hp->kref, destroy_hvc_struct); --- linux-2.6.27.orig/drivers/char/tty_io.c +++ linux-2.6.27/drivers/char/tty_io.c @@ -2996,7 +2996,7 @@ case TIOCSTI: return tiocsti(tty, p); case TIOCGWINSZ: - return tiocgwinsz(tty, p); + return tiocgwinsz(real_tty, p); case TIOCSWINSZ: return tiocswinsz(tty, real_tty, p); case TIOCCONS: --- linux-2.6.27.orig/drivers/char/keyboard.c +++ linux-2.6.27/drivers/char/keyboard.c @@ -1068,6 +1068,8 @@ int code; switch (keycode) { + case KEY_RESERVED: + break; case KEY_PAUSE: put_queue(vc, 0xe1); put_queue(vc, 0x1d | up_flag); @@ -1127,6 +1129,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag) { + if (keycode == KEY_RESERVED) + return 0; if (keycode > 127) return -1; --- linux-2.6.27.orig/drivers/char/vt_ioctl.c +++ linux-2.6.27/drivers/char/vt_ioctl.c @@ -35,6 +35,8 @@ #include #include +#define max_font_size 65536 + char vt_dont_switch; extern struct tty_driver *console_driver; @@ -1252,6 +1254,7 @@ static void complete_change_console(struct vc_data *vc) { unsigned char old_vc_mode; + struct vc_data *oldvc = vc_cons[fg_console].d; last_console = fg_console; @@ -1260,9 +1263,31 @@ * KD_TEXT mode or vice versa, which means we need to blank or * unblank the screen later. */ - old_vc_mode = vc_cons[fg_console].d->vc_mode; + old_vc_mode = oldvc->vc_mode; + +#if defined(CONFIG_VGA_CONSOLE) + if (old_vc_mode == KD_TEXT && oldvc->vc_sw == &vga_con && + oldvc->vc_sw->con_font_get) { + if (!oldvc->vc_font.data) + oldvc->vc_font.data = kmalloc(max_font_size, + GFP_KERNEL); + lock_kernel(); + oldvc->vc_sw->con_font_get(oldvc, &oldvc->vc_font); + unlock_kernel(); + } +#endif switch_screen(vc); +#if defined(CONFIG_VGA_CONSOLE) + if (vc->vc_mode == KD_TEXT && vc->vc_sw == &vga_con && + vc->vc_sw->con_font_set) { + if (vc->vc_font.data) { + lock_kernel(); + vc->vc_sw->con_font_set(vc, &vc->vc_font, 0); + unlock_kernel(); + } + } +#endif /* * This can't appear below a successful kill_pid(). If it did, * then the *blank_screen operation could occur while X, having --- linux-2.6.27.orig/drivers/char/agp/intel-agp.c +++ linux-2.6.27/drivers/char/agp/intel-agp.c @@ -54,8 +54,7 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB) #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ @@ -63,7 +62,8 @@ #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB) extern int agp_memory_reserved; @@ -525,8 +525,10 @@ size += 4; } else if (IS_G4X) { /* On 4 series hardware, GTT stolen is separate from graphics - * stolen, ignore it in stolen gtt entries counting */ - size = 0; + * stolen, ignore it in stolen gtt entries counting. However, + * 4KB of the stolen memory doesn't get mapped to the GTT. + */ + size = 4; } else { /* On previous hardware, the GTT size was just what was * required to map the aperture. --- linux-2.6.27.orig/drivers/char/ipmi/ipmi_devintf.c +++ linux-2.6.27/drivers/char/ipmi/ipmi_devintf.c @@ -957,3 +957,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Corey Minyard "); MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); +MODULE_ALIAS("platform:ipmi_si"); --- linux-2.6.27.orig/drivers/gpu/drm/i915/i915_dma.c +++ linux-2.6.27/drivers/gpu/drm/i915/i915_dma.c @@ -836,7 +836,7 @@ DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ), DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); --- linux-2.6.27.orig/drivers/rtc/rtc-cmos.c +++ linux-2.6.27/drivers/rtc/rtc-cmos.c @@ -1030,29 +1030,32 @@ static int __init cmos_init(void) { + int retval = 0; + +#ifdef CONFIG_PNP + pnp_register_driver(&cmos_pnp_driver); +#endif + + if (!cmos_rtc.dev) + retval = platform_driver_probe(&cmos_platform_driver, + cmos_platform_probe); + + if (retval == 0) + return 0; + #ifdef CONFIG_PNP - if (pnp_platform_devices) - return pnp_register_driver(&cmos_pnp_driver); - else - return platform_driver_probe(&cmos_platform_driver, - cmos_platform_probe); -#else - return platform_driver_probe(&cmos_platform_driver, - cmos_platform_probe); -#endif /* CONFIG_PNP */ + pnp_unregister_driver(&cmos_pnp_driver); +#endif + return retval; } module_init(cmos_init); static void __exit cmos_exit(void) { #ifdef CONFIG_PNP - if (pnp_platform_devices) - pnp_unregister_driver(&cmos_pnp_driver); - else - platform_driver_unregister(&cmos_platform_driver); -#else + pnp_unregister_driver(&cmos_pnp_driver); +#endif platform_driver_unregister(&cmos_platform_driver); -#endif /* CONFIG_PNP */ } module_exit(cmos_exit); --- linux-2.6.27.orig/drivers/message/fusion/mptbase.c +++ linux-2.6.27/drivers/message/fusion/mptbase.c @@ -3014,6 +3014,16 @@ pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus); pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo); pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices); + /* + * VMware emulation is broken, its PortFact's MaxDevices reports value + * programmed by IOC Init, so if you program IOC Init to 256 (which is 0, + * as that field is only 8 bit), it reports back 0 in port facts, instead + * of 256... And unfortunately using 256 triggers another bug in the + * code (parallel SCSI can have only 16 devices). + */ + if (pfacts->MaxDevices == 0) { + pfacts->MaxDevices = 16; + } pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID); pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags); pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers); --- linux-2.6.27.orig/drivers/input/tablet/wacom_sys.c +++ linux-2.6.27/drivers/input/tablet/wacom_sys.c @@ -14,8 +14,43 @@ #include "wacom.h" #include "wacom_wac.h" +/* defines to get HID report descriptor */ +#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01) +#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02) +#define HID_USAGE_PAGE 0x05 +#define HID_USAGE_PAGE_DIGITIZER 0x0d +#define HID_USAGE_PAGE_DESKTOP 0x01 +#define HID_USAGE 0x09 +#define HID_USAGE_X 0x30 +#define HID_USAGE_Y 0x31 +#define HID_USAGE_X_TILT 0x3d +#define HID_USAGE_Y_TILT 0x3e +#define HID_USAGE_FINGER 0x22 +#define HID_USAGE_STYLUS 0x20 +#define HID_COLLECTION 0xc0 +#define HID_USAGE_PAGE_VDEFINED 0xff + +enum { + WCM_UNDEFINED = 0, + WCM_DESKTOP, + WCM_DIGITIZER, + MAX_USAGE_PAGE +}; + +struct hid_descriptor +{ + struct usb_descriptor_header header; + __le16 bcdHID; + u8 bCountryCode; + u8 bNumDescriptors; + u8 bDescriptorType; + __le16 wDescriptorLength; +} __attribute__ ((packed)); + +/* defines to get/set USB message */ #define USB_REQ_GET_REPORT 0x01 #define USB_REQ_SET_REPORT 0x09 +#define WAC_HID_FEATURE_REPORT 0x03 static int usb_get_report(struct usb_interface *intf, unsigned char type, unsigned char id, void *buf, int size) @@ -56,10 +91,10 @@ case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, urb->status); + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, urb->status); + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto exit; } @@ -74,7 +109,7 @@ retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", - __func__, retval); + __FUNCTION__, retval); } void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) @@ -160,7 +195,7 @@ void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_1) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_1) | BIT_MASK(BTN_5); input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); } @@ -170,7 +205,7 @@ input_dev->evbit[0] |= BIT_MASK(EV_MSC); input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_4); } @@ -178,7 +213,7 @@ { input_dev->evbit[0] |= BIT_MASK(EV_REL); input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | + input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); @@ -188,7 +223,7 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); @@ -196,14 +231,14 @@ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_4) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7); input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); } void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); } void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -211,7 +246,7 @@ input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL); input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | + input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | @@ -228,8 +263,7 @@ void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2) | - BIT_MASK(BTN_TOOL_RUBBER); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); } void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -237,15 +271,106 @@ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); } +static void wacom_paser_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, + struct wacom_wac *wacom_wac, char *report) +{ + struct usb_device *dev = interface_to_usbdev(intf); + char limit = 0, result = 0; + int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; + + /* retrive report descriptors */ + do { + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, + USB_RECIP_INTERFACE | USB_DIR_IN, + HID_DEVICET_REPORT << 8, + intf->altsetting[0].desc.bInterfaceNumber, /* interface */ + report, + hid_desc->wDescriptorLength, + 5000); /* 5 secs */ + } while (limit++ < 5); + + for (i=0; iwDescriptorLength; i++) { + if ((unsigned short)report[i] == HID_USAGE_PAGE) { + switch ((unsigned short)report[i+1]) { + case HID_USAGE_PAGE_DIGITIZER: + usage = WCM_DIGITIZER; + i++; + continue; + case HID_USAGE_PAGE_DESKTOP: + usage = WCM_DESKTOP; + i++; + continue; + case HID_USAGE_PAGE_VDEFINED: + if (!report[i+3]) { /* capacity */ + wacom_wac->features->pressure_max = (unsigned short)report[i+5]; + } + i += 6; + continue; + } + } + + if ((unsigned short)report[i] == HID_USAGE) { + switch ((unsigned short)report[i+1]) { + case HID_USAGE_X: + if (usage == WCM_DESKTOP) { + if (finger) { + wacom_wac->features->touch_x_max = + wacom_wac->features->touch_y_max = (unsigned short) + (wacom_le16_to_cpu(&report[i+3])); + wacom_wac->features->x_max = (unsigned short) + (wacom_le16_to_cpu(&report[i+6])); + i += 7; + } else if (pen) { + wacom_wac->features->x_max = (unsigned short) + (wacom_le16_to_cpu(&report[i+3])); + i += 4; + } + } else if (usage == WCM_DIGITIZER) { + /* max pressure isn't reported + wacom_wac->features->pressure_max = (unsigned short) + (report[i+4] << 8 | report[i+3]); + */ + wacom_wac->features->pressure_max = 255; + i += 4; + } + break; + case HID_USAGE_Y: + if (usage == WCM_DESKTOP) { + wacom_wac->features->y_max = (unsigned short) + (wacom_le16_to_cpu(&report[i+3])); + } + i += 4; + break; + case HID_USAGE_FINGER: + finger = 1; + i++; + break; + case HID_USAGE_STYLUS: + pen = 1; + i++; + break; + } + } + + if ((unsigned short)report[i] == HID_COLLECTION) { + /* reset UsagePage ans Finger */ + finger = usage = 0; + } + } +} + static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); + struct usb_host_interface *interface = intf->cur_altsetting; struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; struct wacom_wac *wacom_wac; struct input_dev *input_dev; int error = -ENOMEM; - char rep_data[2], limit = 0; + char rep_data[2], limit = 0, mode = 2, *report = NULL; + struct hid_descriptor *hid_desc; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); @@ -282,18 +407,38 @@ input_dev->open = wacom_open; input_dev->close = wacom_close; + endpoint = &intf->cur_altsetting->endpoint[0].desc; + + /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ + if (wacom_wac->features->type == TABLETPC) { + if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { + if (usb_get_extra_descriptor(&interface->endpoint[0], + HID_DEVICET_REPORT, &hid_desc)) { + printk("wacom: can not retrive extra class descriptor\n"); + goto fail2; + } + } + report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); + if (!report) { + goto fail2; + } + wacom_paser_hid(intf, hid_desc, wacom_wac, report); + } + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | - BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS); input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0); input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); + if (wacom_wac->features->type == TABLETPC) { + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); + input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->touch_x_max, 4, 0); + input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->touch_y_max, 4, 0); + } input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); wacom_init_input_dev(input_dev, wacom_wac); - endpoint = &intf->cur_altsetting->endpoint[0].desc; - usb_fill_int_urb(wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), wacom_wac->data, wacom_wac->features->pktlen, @@ -305,15 +450,21 @@ if (error) goto fail3; - /* Ask the tablet to report tablet data. Repeat until it succeeds */ - do { - rep_data[0] = 2; - rep_data[1] = 2; - usb_set_report(intf, 3, 2, rep_data, 2); - usb_get_report(intf, 3, 2, rep_data, 2); - } while (rep_data[1] != 2 && limit++ < 5); + /* Ask the tablet to report tablet data if it is not a Tablet PC. + * Repeat until it succeeds + */ + if (wacom_wac->features->type != TABLETPC) { + do { + rep_data[0] = 2; + rep_data[1] = mode; + error = error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, 2, rep_data, 2); + if(error >= 0) + error = usb_get_report(intf, WAC_HID_FEATURE_REPORT, 2, rep_data, 2); + } while (((error <= 0) || (rep_data[1] != mode)) && limit++ < 5); + } usb_set_intfdata(intf, wacom); + kfree(report); return 0; fail3: usb_free_urb(wacom->irq); --- linux-2.6.27.orig/drivers/input/tablet/wacom_wac.h +++ linux-2.6.27/drivers/input/tablet/wacom_wac.h @@ -10,6 +10,7 @@ #define WACOM_WAC_H #define STYLUS_DEVICE_ID 0x02 +#define TOUCH_DEVICE_ID 0x03 #define CURSOR_DEVICE_ID 0x06 #define ERASER_DEVICE_ID 0x0A #define PAD_DEVICE_ID 0x0F @@ -27,6 +28,7 @@ CINTIQ, WACOM_BEE, WACOM_MO, + TABLETPC, MAX_TYPE }; @@ -38,6 +40,8 @@ int pressure_max; int distance_max; int type; + int touch_x_max; + int touch_y_max; }; struct wacom_wac { --- linux-2.6.27.orig/drivers/input/tablet/wacom.h +++ linux-2.6.27/drivers/input/tablet/wacom.h @@ -66,6 +66,7 @@ * - Support Intuos3 4x6 * v1.47 (pc) - Added support for Bamboo * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX + * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) */ /* @@ -86,7 +87,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.48" +#define DRIVER_VERSION "v1.49" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" @@ -105,7 +106,7 @@ struct urb *irq; struct wacom_wac * wacom_wac; struct mutex lock; - unsigned int open:1; + int open:1; char phys[32]; }; --- linux-2.6.27.orig/drivers/input/mouse/alps.c +++ linux-2.6.27/drivers/input/mouse/alps.c @@ -54,6 +54,7 @@ { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ + { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ }; @@ -421,7 +422,8 @@ static int alps_reconnect(struct psmouse *psmouse) { - psmouse_reset(psmouse); + /* UBUNTU: Causes lockups on resume */ + /* psmouse_reset(psmouse); */ if (alps_hw_init(psmouse, NULL)) return -1; --- linux-2.6.27.orig/drivers/input/serio/i8042-x86ia64io.h +++ linux-2.6.27/drivers/input/serio/i8042-x86ia64io.h @@ -322,6 +322,13 @@ DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), }, }, + { + .ident = "IBM 2656", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IBM"), + DMI_MATCH(DMI_PRODUCT_NAME, "2656"), + }, + }, { } }; --- linux-2.6.27.orig/drivers/input/keyboard/atkbd.c +++ linux-2.6.27/drivers/input/keyboard/atkbd.c @@ -834,10 +834,10 @@ } /* - * Most special keys (Fn+F?) on Dell Latitudes do not generate release + * Most special keys (Fn+F?) on Dell laptops do not generate release * events so we have to do it ourselves. */ -static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd) +static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) { const unsigned int forced_release_keys[] = { 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, @@ -1461,13 +1461,13 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { { - .ident = "Dell Latitude series", + .ident = "Dell Laptop", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), + DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ }, .callback = atkbd_setup_fixup, - .driver_data = atkbd_latitude_keymap_fixup, + .driver_data = atkbd_dell_laptop_keymap_fixup, }, { .ident = "HP 2133", --- linux-2.6.27.orig/drivers/bluetooth/bt3c_cs.c +++ linux-2.6.27/drivers/bluetooth/bt3c_cs.c @@ -344,7 +344,10 @@ unsigned int iobase; int iir; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } iobase = info->p_dev->io.BasePort1; --- linux-2.6.27.orig/drivers/bluetooth/bluecard_cs.c +++ linux-2.6.27/drivers/bluetooth/bluecard_cs.c @@ -503,7 +503,10 @@ unsigned int iobase; unsigned char reg; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } if (!test_bit(CARD_READY, &(info->hw_state))) return IRQ_HANDLED; --- linux-2.6.27.orig/drivers/bluetooth/hci_usb.c +++ linux-2.6.27/drivers/bluetooth/hci_usb.c @@ -137,6 +137,9 @@ { USB_DEVICE(0x413c, 0x8156), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU }, /* Dell Wireless 410 */ { USB_DEVICE(0x413c, 0x8152), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU }, + + /* Broadcom 2046 */ + { USB_DEVICE(0x0a5c, 0x2151), .driver_info = HCI_RESET }, /* Broadcom 2046 */ { USB_DEVICE(0x0a5c, 0x2151), .driver_info = HCI_RESET }, --- linux-2.6.27.orig/drivers/bluetooth/btusb.c +++ linux-2.6.27/drivers/bluetooth/btusb.c @@ -125,6 +125,9 @@ /* Dell laptop with Broadcom chip */ { USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, + /* Dell Wireless 365 */ + { USB_DEVICE(0x413c, 0x8160), .driver_info = BTUSB_RESET }, + /* Dell Wireless 370 */ { USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, --- linux-2.6.27.orig/drivers/bluetooth/dtl1_cs.c +++ linux-2.6.27/drivers/bluetooth/dtl1_cs.c @@ -298,7 +298,10 @@ int boguscount = 0; int iir, lsr; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } iobase = info->p_dev->io.BasePort1; --- linux-2.6.27.orig/drivers/bluetooth/btuart_cs.c +++ linux-2.6.27/drivers/bluetooth/btuart_cs.c @@ -294,7 +294,10 @@ int boguscount = 0; int iir, lsr; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } iobase = info->p_dev->io.BasePort1; --- linux-2.6.27.orig/drivers/pci/probe.c +++ linux-2.6.27/drivers/pci/probe.c @@ -219,7 +219,7 @@ res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; - if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64) + if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) return pci_bar_mem64; return pci_bar_mem32; } --- linux-2.6.27.orig/drivers/pci/setup-res.c +++ linux-2.6.27/drivers/pci/setup-res.c @@ -162,8 +162,8 @@ } if (ret) { - dev_err(&dev->dev, "BAR %d: can't allocate %s resource " - "[%#llx-%#llx]\n", resno, + dev_warn(&dev->dev, "BAR %d: can't allocate %s resource " + "[%#llx-%#llx]\n", resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", (unsigned long long)res->start, (unsigned long long)res->end); --- linux-2.6.27.orig/drivers/pci/hotplug/cpqphp_core.c +++ linux-2.6.27/drivers/pci/hotplug/cpqphp_core.c @@ -435,7 +435,7 @@ slot->number, ctrl->slot_device_offset, slot_number); result = pci_hp_register(hotplug_slot, - ctrl->pci_dev->subordinate, + ctrl->pci_dev->bus, slot->device); if (result) { err("pci_hp_register failed with error %d\n", result); --- linux-2.6.27.orig/drivers/net/sky2.c +++ linux-2.6.27/drivers/net/sky2.c @@ -3034,7 +3034,8 @@ struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; - if (wol->wolopts & ~sky2_wol_supported(sky2->hw)) + if ((wol->wolopts & ~sky2_wol_supported(sky2->hw)) + || !device_can_wakeup(&hw->pdev->dev)) return -EOPNOTSUPP; sky2->wol = wol->wolopts; @@ -3045,6 +3046,8 @@ sky2_write32(hw, B0_CTST, sky2->wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); + device_set_wakeup_enable(&hw->pdev->dev, sky2->wol); + if (!netif_running(dev)) sky2_wol_init(sky2); return 0; @@ -4166,18 +4169,6 @@ return err; } -static int __devinit pci_wake_enabled(struct pci_dev *dev) -{ - int pm = pci_find_capability(dev, PCI_CAP_ID_PM); - u16 value; - - if (!pm) - return 0; - if (pci_read_config_word(dev, pm + PCI_PM_CTRL, &value)) - return 0; - return value & PCI_PM_CTRL_PME_ENABLE; -} - /* This driver supports yukon2 chipset only */ static const char *sky2_name(u8 chipid, char *buf, int sz) { @@ -4238,7 +4229,7 @@ } } - wol_default = pci_wake_enabled(pdev) ? WAKE_MAGIC : 0; + wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0; err = -ENOMEM; hw = kzalloc(sizeof(*hw), GFP_KERNEL); --- linux-2.6.27.orig/drivers/net/r8169.c +++ linux-2.6.27/drivers/net/r8169.c @@ -370,8 +370,9 @@ }; enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), + RTL_FEATURE_WOL = (1 << 0), + RTL_FEATURE_MSI = (1 << 1), + RTL_FEATURE_GMII = (1 << 2), }; struct rtl8169_private { @@ -406,13 +407,15 @@ struct vlan_group *vlgrp; #endif int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - void (*get_settings)(struct net_device *, struct ethtool_cmd *); + int (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(void __iomem *); void (*hw_start)(struct net_device *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); struct delayed_work task; unsigned features; + + struct mii_if_info mii; }; MODULE_AUTHOR("Realtek and the Linux r8169 crew "); @@ -482,6 +485,23 @@ return value; } +static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, + int val) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + mdio_write(ioaddr, location, val); +} + +static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + return mdio_read(ioaddr, location); +} + static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) { RTL_W16(IntrMask, 0x0000); @@ -720,9 +740,13 @@ auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - if ((tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version == RTL_GIGA_MAC_VER_17)) { - /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */ + if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || + (tp->mac_version == RTL_GIGA_MAC_VER_12) || + (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { + /* + * Wake up the PHY. + * Vendor specific (0x1f) and reserved (0x0e) MII registers. + */ mdio_write(ioaddr, 0x1f, 0x0000); mdio_write(ioaddr, 0x0e, 0x0000); } @@ -850,7 +874,7 @@ #endif -static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) +static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; @@ -867,65 +891,29 @@ cmd->speed = SPEED_1000; cmd->duplex = DUPLEX_FULL; /* Always set */ + + return 0; } -static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) +static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 status; - cmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP; - - cmd->autoneg = 1; - cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - cmd->advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - cmd->advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - cmd->advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - cmd->advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - cmd->advertising |= ADVERTISED_1000baseT_Full; - - status = RTL_R8(PHYstatus); - - if (status & _1000bpsF) - cmd->speed = SPEED_1000; - else if (status & _100bps) - cmd->speed = SPEED_100; - else if (status & _10bps) - cmd->speed = SPEED_10; - - if (status & TxFlowCtrl) - cmd->advertising |= ADVERTISED_Asym_Pause; - if (status & RxFlowCtrl) - cmd->advertising |= ADVERTISED_Pause; - - cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; + return mii_ethtool_gset(&tp->mii, cmd); } static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); unsigned long flags; + int rc; spin_lock_irqsave(&tp->lock, flags); - tp->get_settings(dev, cmd); + rc = tp->get_settings(dev, cmd); spin_unlock_irqrestore(&tp->lock, flags); - return 0; + return rc; } static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, @@ -1513,7 +1501,7 @@ unsigned int align; u16 intr_event; u16 napi_event; - unsigned msi; + unsigned features; } rtl_cfg_infos [] = { [RTL_CFG_0] = { .hw_start = rtl_hw_start_8169, @@ -1522,7 +1510,7 @@ .intr_event = SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = 0 + .features = RTL_FEATURE_GMII }, [RTL_CFG_1] = { .hw_start = rtl_hw_start_8168, @@ -1531,7 +1519,7 @@ .intr_event = SYSErr | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI + .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI }, [RTL_CFG_2] = { .hw_start = rtl_hw_start_8101, @@ -1540,7 +1528,7 @@ .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI + .features = RTL_FEATURE_MSI } }; @@ -1552,7 +1540,7 @@ u8 cfg2; cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->msi) { + if (cfg->features & RTL_FEATURE_MSI) { if (pci_enable_msi(pdev)) { dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); } else { @@ -1578,6 +1566,7 @@ const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; const unsigned int region = cfg->region; struct rtl8169_private *tp; + struct mii_if_info *mii; struct net_device *dev; void __iomem *ioaddr; unsigned int i; @@ -1602,6 +1591,14 @@ tp->pci_dev = pdev; tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); + mii = &tp->mii; + mii->dev = dev; + mii->mdio_read = rtl_mdio_read; + mii->mdio_write = rtl_mdio_write; + mii->phy_id_mask = 0x1f; + mii->reg_num_mask = 0x1f; + mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); + /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pci_enable_device(pdev); if (rc < 0) { @@ -1757,6 +1754,13 @@ dev->poll_controller = rtl8169_netpoll; #endif + /* Ubuntu temporary workaround for bug #76489, disable + * NETIF_F_TSO by default for RTL8111/8168B chipsets. + * People can re-enable if required */ + if (tp->mac_version == RTL_GIGA_MAC_VER_11 + || tp->mac_version == RTL_GIGA_MAC_VER_12) + dev->features &= ~NETIF_F_TSO; + tp->intr_mask = 0xffff; tp->mmio_addr = ioaddr; tp->align = cfg->align; @@ -2099,8 +2103,6 @@ RTL_R8(IntrMask); - RTL_W32(RxMissed, 0); - rtl_set_rx_mode(dev); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); @@ -2143,8 +2145,6 @@ RTL_R8(IntrMask); - RTL_W32(RxMissed, 0); - rtl_set_rx_mode(dev); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); @@ -2922,6 +2922,17 @@ return work_done; } +static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) +{ + struct rtl8169_private *tp = netdev_priv(dev); + + if (tp->mac_version > RTL_GIGA_MAC_VER_06) + return; + + dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); + RTL_W32(RxMissed, 0); +} + static void rtl8169_down(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -2939,9 +2950,7 @@ rtl8169_asic_down(ioaddr); - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock); @@ -3063,8 +3072,7 @@ if (netif_running(dev)) { spin_lock_irqsave(&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irqrestore(&tp->lock, flags); } @@ -3089,8 +3097,7 @@ rtl8169_asic_down(ioaddr); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock); --- linux-2.6.27.orig/drivers/net/tulip/tulip_core.c +++ linux-2.6.27/drivers/net/tulip/tulip_core.c @@ -228,8 +228,12 @@ { 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 }, { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 }, + /* Ubuntu: On non-sparc, this seems to be handled better by the + * dmfe driver. */ +#ifdef __sparc__ { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, +#endif { 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 }, { 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, @@ -392,6 +396,11 @@ goto media_picked; } } + if (tp->chip_id == PCI_ULI5261_ID || tp->chip_id == PCI_ULI5263_ID) { + for (i = tp->mtable->leafcount - 1; i >= 0; i--) + if (tulip_media_cap[tp->mtable->mleaf[i].media] & MediaIsMII) + goto media_picked; + } /* Start sensing first non-full-duplex media. */ for (i = tp->mtable->leafcount - 1; (tulip_media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--) --- linux-2.6.27.orig/drivers/net/tulip/tulip.h +++ linux-2.6.27/drivers/net/tulip/tulip.h @@ -38,7 +38,10 @@ #define TULIP_BAR 0 /* CBIO */ #endif - +#ifndef PCI_ULI5261_ID +#define PCI_ULI5261_ID 0x526110B9 /* ULi M5261 ID*/ +#define PCI_ULI5263_ID 0x526310B9 /* ULi M5263 ID*/ +#endif struct tulip_chip_table { char *chip_name; --- linux-2.6.27.orig/drivers/net/wireless/orinoco_cs.c +++ linux-2.6.27/drivers/net/wireless/orinoco_cs.c @@ -11,6 +11,7 @@ */ #define DRIVER_NAME "orinoco_cs" +#define OVERLAP_DRIVER_NAME "orinoco_cs_overlap" #define PFX DRIVER_NAME ": " #include @@ -440,67 +441,94 @@ " (David Gibson , " "Pavel Roskin , et al)"; -static struct pcmcia_device_id orinoco_cs_ids[] = { +/* + * PCMCIA IDs that are also defined in hostap_cs. + */ +static struct pcmcia_device_id orinoco_overlap_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */ - PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */ PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */ PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */ + PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */ + PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */ + PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */ + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */ + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */ + + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), + PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), + + PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2), + + PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), + PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), + PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), + PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), + PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), + PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), + PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), + PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), + + PCMCIA_DEVICE_NULL, +}; + +static struct pcmcia_driver orinoco_overlap_driver = { + .owner = THIS_MODULE, + .drv = { + .name = OVERLAP_DRIVER_NAME, + }, + .probe = orinoco_cs_probe, + .remove = orinoco_cs_detach, + .id_table = orinoco_overlap_cs_ids, + .suspend = orinoco_cs_suspend, + .resume = orinoco_cs_resume, +}; + +static struct pcmcia_device_id orinoco_cs_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */ PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */ - PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */ - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */ - PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */ PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */ - PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */ PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */ PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */ PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */ - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */ - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */ + PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9), PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), - PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092), - PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb), - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), - PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), - PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), - PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916), PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), - PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077), - PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), - PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), - PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), - PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2), PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), - PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), @@ -517,11 +545,8 @@ PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), - PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), - PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39), - PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); @@ -538,18 +563,39 @@ .resume = orinoco_cs_resume, }; +static int orinoco_driver_registered = 0; +static int orinoco_overlap_driver_registered = 0; + static int __init init_orinoco_cs(void) { + int status; + printk(KERN_DEBUG "%s\n", version); - return pcmcia_register_driver(&orinoco_driver); + status = pcmcia_register_driver(&orinoco_driver); + if (status >= 0) + orinoco_driver_registered = 1; + + status = pcmcia_register_driver(&orinoco_overlap_driver); + if (status >= 0) + orinoco_overlap_driver_registered = 1; + + return status; } static void __exit exit_orinoco_cs(void) { - pcmcia_unregister_driver(&orinoco_driver); + if (orinoco_overlap_driver_registered) { + pcmcia_unregister_driver(&orinoco_overlap_driver); + orinoco_overlap_driver_registered = 0; + } + + if (orinoco_driver_registered) { + pcmcia_unregister_driver(&orinoco_driver); + orinoco_driver_registered = 0; + } } module_init(init_orinoco_cs); --- linux-2.6.27.orig/drivers/net/wireless/ipw2200.c +++ linux-2.6.27/drivers/net/wireless/ipw2200.c @@ -87,7 +87,7 @@ static int mode = 0; static u32 ipw_debug_level; -static int associate = 1; +static int associate; static int auto_create = 1; static int led = 0; static int disable = 0; --- linux-2.6.27.orig/drivers/net/wireless/ath9k/main.c +++ linux-2.6.27/drivers/net/wireless/ath9k/main.c @@ -1007,6 +1007,11 @@ return ret; } +static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value) +{ + return -EOPNOTSUPP; +} + static struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -1031,7 +1036,8 @@ .get_tsf = ath9k_get_tsf, .reset_tsf = ath9k_reset_tsf, .tx_last_beacon = NULL, - .ampdu_action = ath9k_ampdu_action + .ampdu_action = ath9k_ampdu_action, + .set_frag_threshold = ath9k_no_fragmentation, }; void ath_get_beaconconfig(struct ath_softc *sc, --- linux-2.6.27.orig/drivers/net/wireless/ath9k/core.h +++ linux-2.6.27/drivers/net/wireless/ath9k/core.h @@ -316,7 +316,7 @@ #define ATH_RX_TIMEOUT 40 /* 40 milliseconds */ #define WME_NUM_TID 16 #define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ -#define IEEE80211_BAR_CTL_TID_S 2 /* tid shift */ +#define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */ enum ATH_RX_TYPE { ATH_RX_NON_CONSUMED = 0, --- linux-2.6.27.orig/drivers/net/wireless/hostap/hostap_info.c +++ linux-2.6.27/drivers/net/wireless/hostap/hostap_info.c @@ -238,6 +238,7 @@ wrqu.data.length = 0; wrqu.data.flags = 0; wireless_send_event(local->dev, SIOCGIWSCAN, &wrqu, NULL); + wireless_send_event(local->ddev, SIOCGIWSCAN, &wrqu, NULL); /* Allow SIOCGIWSCAN handling to occur since we have received * scanning result */ @@ -451,8 +452,10 @@ * frames and can confuse wpa_supplicant about the current association * status. */ - if (connected || local->prev_linkstatus_connected) + if (connected || local->prev_linkstatus_connected) { wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(local->ddev, SIOCGIWAP, &wrqu, NULL); + } local->prev_linkstatus_connected = connected; } --- linux-2.6.27.orig/drivers/net/wireless/hostap/hostap_hw.c +++ linux-2.6.27/drivers/net/wireless/hostap/hostap_hw.c @@ -3447,6 +3447,7 @@ memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(local->ddev, SIOCGIWAP, &wrqu, NULL); /* Disable hardware and firmware */ prism2_hw_shutdown(dev, 0); --- linux-2.6.27.orig/drivers/net/wireless/hostap/hostap_main.c +++ linux-2.6.27/drivers/net/wireless/hostap/hostap_main.c @@ -1094,6 +1094,7 @@ (u8 *) &val, 2); memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(local->ddev, SIOCGIWAP, &wrqu, NULL); return ret; } --- linux-2.6.27.orig/drivers/net/wireless/b43legacy/xmit.c +++ linux-2.6.27/drivers/net/wireless/b43legacy/xmit.c @@ -626,7 +626,7 @@ tmp = hw->count; status.frame_count = (tmp >> 4); status.rts_count = (tmp & 0x0F); - tmp = hw->flags; + tmp = hw->flags << 1; status.supp_reason = ((tmp & 0x1C) >> 2); status.pm_indicated = !!(tmp & 0x80); status.intermediate = !!(tmp & 0x40); --- linux-2.6.27.orig/drivers/net/wireless/zd1211rw/zd_usb.c +++ linux-2.6.27/drivers/net/wireless/zd1211rw/zd_usb.c @@ -61,6 +61,7 @@ { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, @@ -82,6 +83,7 @@ { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, --- linux-2.6.27.orig/drivers/net/wireless/libertas/main.c +++ linux-2.6.27/drivers/net/wireless/libertas/main.c @@ -1196,7 +1196,13 @@ cancel_delayed_work_sync(&priv->scan_work); cancel_delayed_work_sync(&priv->assoc_work); cancel_work_sync(&priv->mcast_work); + + /* worker thread destruction blocks on the in-flight command which + * should have been cleared already in lbs_stop_card(). + */ + lbs_deb_main("destroying worker thread\n"); destroy_workqueue(priv->work_thread); + lbs_deb_main("done destroying worker thread\n"); if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; @@ -1314,14 +1320,26 @@ device_remove_file(&dev->dev, &dev_attr_lbs_rtap); } - /* Flush pending command nodes */ + /* Delete the timeout of the currently processing command */ del_timer_sync(&priv->command_timer); + + /* Flush pending command nodes */ spin_lock_irqsave(&priv->driver_lock, flags); + lbs_deb_main("clearing pending commands\n"); list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { cmdnode->result = -ENOENT; cmdnode->cmdwaitqwoken = 1; wake_up_interruptible(&cmdnode->cmdwait_q); } + + /* Flush the command the card is currently processing */ + if (priv->cur_cmd) { + lbs_deb_main("clearing current command\n"); + priv->cur_cmd->result = -ENOENT; + priv->cur_cmd->cmdwaitqwoken = 1; + wake_up_interruptible(&priv->cur_cmd->cmdwait_q); + } + lbs_deb_main("done clearing commands\n"); spin_unlock_irqrestore(&priv->driver_lock, flags); unregister_netdev(dev); --- linux-2.6.27.orig/drivers/net/wireless/libertas/scan.c +++ linux-2.6.27/drivers/net/wireless/libertas/scan.c @@ -598,8 +598,8 @@ switch (elem->id) { case MFIE_TYPE_SSID: - bss->ssid_len = elem->len; - memcpy(bss->ssid, elem->data, elem->len); + bss->ssid_len = min_t(int, 32, elem->len); + memcpy(bss->ssid, elem->data, bss->ssid_len); lbs_deb_scan("got SSID IE: '%s', len %u\n", escape_essid(bss->ssid, bss->ssid_len), bss->ssid_len); --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-core.h +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-core.h @@ -186,7 +186,6 @@ void iwl_hw_detect(struct iwl_priv *priv); void iwl_clear_stations_table(struct iwl_priv *priv); -void iwl_free_calib_results(struct iwl_priv *priv); void iwl_reset_qos(struct iwl_priv *priv); void iwl_set_rxon_chain(struct iwl_priv *priv); int iwl_set_rxon_channel(struct iwl_priv *priv, @@ -291,6 +290,13 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); void iwl_setup_scan_deferred_work(struct iwl_priv *priv); +/******************************************************************************* + * Calibrations - implemented in iwl-calib.c + ******************************************************************************/ +int iwl_send_calib_results(struct iwl_priv *priv); +int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); +void iwl_calib_free_results(struct iwl_priv *priv); + /***************************************************** * S e n d i n g H o s t C o m m a n d s * *****************************************************/ --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-core.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-core.c @@ -646,8 +646,14 @@ struct iwl_rxon_cmd *rxon = &priv->staging_rxon; u32 val; - if (!ht_info->is_ht) + if (!ht_info->is_ht) { + rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | + RXON_FLG_CHANNEL_MODE_PURE_40_MSK | + RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | + RXON_FLG_FAT_PROT_MSK | + RXON_FLG_HT_PROT_MSK); return; + } /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ if (iwl_is_fat_tx_allowed(priv, NULL)) @@ -950,22 +956,6 @@ } EXPORT_SYMBOL(iwl_init_drv); -void iwl_free_calib_results(struct iwl_priv *priv) -{ - kfree(priv->calib_results.lo_res); - priv->calib_results.lo_res = NULL; - priv->calib_results.lo_res_len = 0; - - kfree(priv->calib_results.tx_iq_res); - priv->calib_results.tx_iq_res = NULL; - priv->calib_results.tx_iq_res_len = 0; - - kfree(priv->calib_results.tx_iq_perd_res); - priv->calib_results.tx_iq_perd_res = NULL; - priv->calib_results.tx_iq_perd_res_len = 0; -} -EXPORT_SYMBOL(iwl_free_calib_results); - int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { int ret = 0; @@ -993,10 +983,9 @@ } EXPORT_SYMBOL(iwl_set_tx_power); - void iwl_uninit_drv(struct iwl_priv *priv) { - iwl_free_calib_results(priv); + iwl_calib_free_results(priv); iwlcore_free_geos(priv); iwl_free_channel_map(priv); kfree(priv->scan); --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-5000.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -445,48 +445,6 @@ sizeof(cal_cmd), &cal_cmd); } -static int iwl5000_send_calib_results(struct iwl_priv *priv) -{ - int ret = 0; - - struct iwl_host_cmd hcmd = { - .id = REPLY_PHY_CALIBRATION_CMD, - .meta.flags = CMD_SIZE_HUGE, - }; - - if (priv->calib_results.lo_res) { - hcmd.len = priv->calib_results.lo_res_len; - hcmd.data = priv->calib_results.lo_res; - ret = iwl_send_cmd_sync(priv, &hcmd); - - if (ret) - goto err; - } - - if (priv->calib_results.tx_iq_res) { - hcmd.len = priv->calib_results.tx_iq_res_len; - hcmd.data = priv->calib_results.tx_iq_res; - ret = iwl_send_cmd_sync(priv, &hcmd); - - if (ret) - goto err; - } - - if (priv->calib_results.tx_iq_perd_res) { - hcmd.len = priv->calib_results.tx_iq_perd_res_len; - hcmd.data = priv->calib_results.tx_iq_perd_res; - ret = iwl_send_cmd_sync(priv, &hcmd); - - if (ret) - goto err; - } - - return 0; -err: - IWL_ERROR("Error %d\n", ret); - return ret; -} - static int iwl5000_send_calib_cfg(struct iwl_priv *priv) { struct iwl5000_calib_cfg_cmd calib_cfg_cmd; @@ -511,33 +469,30 @@ struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw; int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK; - - iwl_free_calib_results(priv); + int index; /* reduce the size of the length field itself */ len -= 4; + /* Define the order in which the results will be sent to the runtime + * uCode. iwl_send_calib_results sends them in a row according to their + * index. We sort them here */ switch (hdr->op_code) { case IWL5000_PHY_CALIBRATE_LO_CMD: - priv->calib_results.lo_res = kzalloc(len, GFP_ATOMIC); - priv->calib_results.lo_res_len = len; - memcpy(priv->calib_results.lo_res, pkt->u.raw, len); + index = IWL5000_CALIB_LO; break; case IWL5000_PHY_CALIBRATE_TX_IQ_CMD: - priv->calib_results.tx_iq_res = kzalloc(len, GFP_ATOMIC); - priv->calib_results.tx_iq_res_len = len; - memcpy(priv->calib_results.tx_iq_res, pkt->u.raw, len); + index = IWL5000_CALIB_TX_IQ; break; case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD: - priv->calib_results.tx_iq_perd_res = kzalloc(len, GFP_ATOMIC); - priv->calib_results.tx_iq_perd_res_len = len; - memcpy(priv->calib_results.tx_iq_perd_res, pkt->u.raw, len); + index = IWL5000_CALIB_TX_IQ_PERD; break; default: IWL_ERROR("Unknown calibration notification %d\n", hdr->op_code); return; } + iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); } static void iwl5000_rx_calib_complete(struct iwl_priv *priv, @@ -832,7 +787,7 @@ iwl5000_send_Xtal_calib(priv); if (priv->ucode_type == UCODE_RT) - iwl5000_send_calib_results(priv); + iwl_send_calib_results(priv); return 0; } --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-power.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-power.c @@ -324,7 +324,7 @@ * this will be usefull for rate scale to disable PM during heavy * Tx/Rx activities */ -int iwl_power_disable_management(struct iwl_priv *priv) +int iwl_power_disable_management(struct iwl_priv *priv, u32 ms) { u16 prev_mode; int ret = 0; @@ -337,6 +337,11 @@ ret = iwl_power_update_mode(priv, 0); priv->power_data.power_disabled = 1; priv->power_data.user_power_setting = prev_mode; + cancel_delayed_work(&priv->set_power_save); + if (ms) + queue_delayed_work(priv->workqueue, &priv->set_power_save, + msecs_to_jiffies(ms)); + return ret; } @@ -431,3 +436,35 @@ return ret; } EXPORT_SYMBOL(iwl_power_temperature_change); + +static void iwl_bg_set_power_save(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, + struct iwl_priv, set_power_save.work); + IWL_DEBUG(IWL_DL_STATE, "update power\n"); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + + /* on starting association we disable power managment + * until association, if association failed then this + * timer will expire and enable PM again. + */ + if (!iwl_is_associated(priv)) + iwl_power_enable_management(priv); + + mutex_unlock(&priv->mutex); +} +void iwl_setup_power_deferred_work(struct iwl_priv *priv) +{ + INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save); +} +EXPORT_SYMBOL(iwl_setup_power_deferred_work); + +void iwl_power_cancel_timeout(struct iwl_priv *priv) +{ + cancel_delayed_work(&priv->set_power_save); +} +EXPORT_SYMBOL(iwl_power_cancel_timeout); --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-scan.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -464,11 +464,6 @@ int iwl_scan_initiate(struct iwl_priv *priv) { - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - IWL_ERROR("APs don't scan.\n"); - return 0; - } - if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); return -EIO; @@ -480,8 +475,7 @@ } if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Scan request while abort pending. " - "Queuing.\n"); + IWL_DEBUG_SCAN("Scan request while abort pending\n"); return -EAGAIN; } --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -129,6 +129,13 @@ __le32 padding2; } __attribute__ ((packed)); +/* calibrations defined for 5000 */ +/* defines the order in which results should be sent to the runtime uCode */ +enum iwl5000_calib { + IWL5000_CALIB_LO, + IWL5000_CALIB_TX_IQ, + IWL5000_CALIB_TX_IQ_PERD, +}; #endif /* __iwl_5000_hw_h__ */ --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-calib.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -66,6 +66,66 @@ #include "iwl-core.h" #include "iwl-calib.h" +/***************************************************************************** + * INIT calibrations framework + *****************************************************************************/ + + int iwl_send_calib_results(struct iwl_priv *priv) +{ + int ret = 0; + int i = 0; + + struct iwl_host_cmd hcmd = { + .id = REPLY_PHY_CALIBRATION_CMD, + .meta.flags = CMD_SIZE_HUGE, + }; + + for (i = 0; i < IWL_CALIB_MAX; i++) + if (priv->calib_results[i].buf) { + hcmd.len = priv->calib_results[i].buf_len; + hcmd.data = priv->calib_results[i].buf; + ret = iwl_send_cmd_sync(priv, &hcmd); + if (ret) + goto err; + } + + return 0; +err: + IWL_ERROR("Error %d iteration %d\n", ret, i); + return ret; +} +EXPORT_SYMBOL(iwl_send_calib_results); + +int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) +{ + if (res->buf_len != len) { + kfree(res->buf); + res->buf = kzalloc(len, GFP_ATOMIC); + } + if (unlikely(res->buf == NULL)) + return -ENOMEM; + + res->buf_len = len; + memcpy(res->buf, buf, len); + return 0; +} +EXPORT_SYMBOL(iwl_calib_set); + +void iwl_calib_free_results(struct iwl_priv *priv) +{ + int i; + + for (i = 0; i < IWL_CALIB_MAX; i++) { + kfree(priv->calib_results[i].buf); + priv->calib_results[i].buf = NULL; + priv->calib_results[i].buf_len = 0; + } +} + +/***************************************************************************** + * RUNTIME calibrations framework + *****************************************************************************/ + /* "false alarms" are signals that our DSP tries to lock onto, * but then determines that they are either noise, or transmissions * from a distant wireless network (also "noise", really) that get --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-dev.h +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -745,13 +745,10 @@ u32 beacon_energy_c; }; -struct iwl_calib_results { - void *tx_iq_res; - void *tx_iq_perd_res; - void *lo_res; - u32 tx_iq_res_len; - u32 tx_iq_perd_res_len; - u32 lo_res_len; +/* Opaque calibration results */ +struct iwl_calib_result { + void *buf; + size_t buf_len; }; enum ucode_type { @@ -813,6 +810,7 @@ #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ +#define IWL_CALIB_MAX 3 struct iwl_priv { @@ -857,7 +855,7 @@ s32 last_temperature; /* init calibration results */ - struct iwl_calib_results calib_results; + struct iwl_calib_result calib_results[IWL_CALIB_MAX]; /* Scan related variables */ unsigned long last_scan_jiffies; @@ -1047,6 +1045,7 @@ struct tasklet_struct irq_tasklet; + struct delayed_work set_power_save; struct delayed_work init_alive_start; struct delayed_work alive_start; struct delayed_work scan_check; --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-tx.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1192,10 +1192,9 @@ /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (txq_id != IWL_CMD_QUEUE_NUM) - IWL_ERROR("Error wrong command queue %d command id 0x%X\n", - txq_id, pkt->hdr.cmd); - BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); + if (WARN(txq_id != IWL_CMD_QUEUE_NUM, + "wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd)) + return; cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5761,7 +5761,6 @@ if (priv->error_recovering) iwl3945_error_recovery(priv); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); return; restart: @@ -6006,6 +6005,7 @@ mutex_lock(&priv->mutex); iwl3945_alive_start(priv); mutex_unlock(&priv->mutex); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl3945_bg_rf_kill(struct work_struct *work) @@ -6259,6 +6259,11 @@ direct_mask, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + if (scan->channel_count == 0) { + IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); + goto done; + } + cmd.len += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl3945_scan_channel); cmd.data = scan; --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-agn.c +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2090,7 +2090,6 @@ iwl4965_error_recovery(priv); iwl_power_update_mode(priv, 1); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) iwl4965_set_mode(priv, priv->iw_mode); @@ -2342,6 +2341,7 @@ mutex_lock(&priv->mutex); iwl_alive_start(priv); mutex_unlock(&priv->mutex); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl4965_bg_rf_kill(struct work_struct *work) @@ -2486,6 +2486,7 @@ if (!priv->vif || !priv->is_open) return; + iwl_power_cancel_timeout(priv); iwl_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -2503,8 +2504,7 @@ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - if (priv->current_ht_config.is_ht) - iwl_set_rxon_ht(priv, &priv->current_ht_config); + iwl_set_rxon_ht(priv, &priv->current_ht_config); iwl_set_rxon_chain(priv); priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); @@ -2550,10 +2550,6 @@ break; } - /* Enable Rx differential gain and sensitivity calibrations */ - iwl_chain_noise_reset(priv); - priv->start_calib = 1; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) priv->assoc_station_added = 1; @@ -2561,7 +2557,12 @@ iwl_activate_qos(priv, 0); spin_unlock_irqrestore(&priv->lock, flags); - iwl_power_update_mode(priv, 0); + iwl_power_enable_management(priv); + + /* Enable Rx differential gain and sensitivity calibrations */ + iwl_chain_noise_reset(priv); + priv->start_calib = 1; + /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } @@ -3212,18 +3213,26 @@ goto out_unlock; } - /* we don't schedule scan within next_scan_jiffies period */ + /* We don't schedule scan within next_scan_jiffies period. + * Avoid scanning during possible EAPOL exchange, return + * success immediately. + */ if (priv->next_scan_jiffies && - time_after(priv->next_scan_jiffies, jiffies)) { - rc = -EAGAIN; + time_after(priv->next_scan_jiffies, jiffies)) { + IWL_DEBUG_SCAN("scan rejected: within next scan period\n"); + queue_work(priv->workqueue, &priv->scan_completed); + rc = 0; goto out_unlock; } /* if we just finished scan ask for delay */ - if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + - IWL_DELAY_NEXT_SCAN, jiffies)) { - rc = -EAGAIN; + if (iwl_is_associated(priv) && priv->last_scan_jiffies && + time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { + IWL_DEBUG_SCAN("scan rejected: within previous scan period\n"); + queue_work(priv->workqueue, &priv->scan_completed); + rc = 0; goto out_unlock; } + if (len) { IWL_DEBUG_SCAN("direct scan for %s [%d]\n ", iwl_escape_essid(ssid, len), (int)len); @@ -3266,7 +3275,12 @@ return; } - iwl_scan_cancel_timeout(priv, 100); + if (iwl_scan_cancel(priv)) { + /* cancel scan failed, just live w/ bad key and rely + briefly on SW decrpyption */ + IWL_DEBUG_MAC80211("leave - failed to cancel scan\n"); + return; + } key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); @@ -3546,6 +3560,16 @@ /* Per mac80211.h: This is only used in IBSS mode... */ if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + /* switch to CAM during association period. + * the ucode will block any association/authentication + * frome during assiciation period if it can not hear + * the AP because of PM. the timer enable PM back is + * association do not complete + */ + if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN | + IEEE80211_CHAN_RADAR)) + iwl_power_disable_management(priv, 3000); + IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); return; @@ -4083,6 +4107,7 @@ /* FIXME : remove when resolved PENDING */ INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); iwl_setup_scan_deferred_work(priv); + iwl_setup_power_deferred_work(priv); if (priv->cfg->ops->lib->setup_deferred_work) priv->cfg->ops->lib->setup_deferred_work(priv); @@ -4102,6 +4127,7 @@ cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); + cancel_delayed_work_sync(&priv->set_power_save); cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); @@ -4204,13 +4230,13 @@ pci_set_master(pdev); - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); if (err) { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); /* both attempts failed: */ if (err) { printk(KERN_WARNING "%s: No suitable DMA available.\n", --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-power.h +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-power.h @@ -78,8 +78,10 @@ u8 power_disabled; /* flag to disable using power saving level */ }; +void iwl_setup_power_deferred_work(struct iwl_priv *priv); +void iwl_power_cancel_timeout(struct iwl_priv *priv); int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh); -int iwl_power_disable_management(struct iwl_priv *priv); +int iwl_power_disable_management(struct iwl_priv *priv, u32 ms); int iwl_power_enable_management(struct iwl_priv *priv); int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode); int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode); --- linux-2.6.27.orig/drivers/net/wireless/p54/p54usb.c +++ linux-2.6.27/drivers/net/wireless/p54/p54usb.c @@ -60,7 +60,7 @@ {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ - {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ +// DUPE {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ --- linux-2.6.27.orig/drivers/net/bonding/bond_alb.c +++ linux-2.6.27/drivers/net/bonding/bond_alb.c @@ -167,11 +167,14 @@ /* clear slave from tx_hashtbl */ tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl; - index = SLAVE_TLB_INFO(slave).head; - while (index != TLB_NULL_INDEX) { - u32 next_index = tx_hash_table[index].next; - tlb_init_table_entry(&tx_hash_table[index], save_load); - index = next_index; + /* skip this if we've already freed the tx hash table */ + if (tx_hash_table) { + index = SLAVE_TLB_INFO(slave).head; + while (index != TLB_NULL_INDEX) { + u32 next_index = tx_hash_table[index].next; + tlb_init_table_entry(&tx_hash_table[index], save_load); + index = next_index; + } } tlb_init_slave(slave); --- linux-2.6.27.orig/drivers/net/atlx/atl1.h +++ linux-2.6.27/drivers/net/atlx/atl1.h @@ -504,7 +504,7 @@ #define TPD_PKTNT_MASK 0x0001 #define TPD_PKTINT_SHIFT 15 #define TPD_VLANTAG_MASK 0xFFFF -#define TPD_VLAN_SHIFT 16 +#define TPD_VLANTAG_SHIFT 16 /* tpd word 3 bits 0:13 */ #define TPD_EOP_MASK 0x0001 --- linux-2.6.27.orig/drivers/net/atlx/atl1.c +++ linux-2.6.27/drivers/net/atlx/atl1.c @@ -2317,7 +2317,8 @@ if (tpd != ptpd) memcpy(tpd, ptpd, sizeof(struct tx_packet_desc)); tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - tpd->word2 = (cpu_to_le16(buffer_info->length) & + tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT); + tpd->word2 |= (cpu_to_le16(buffer_info->length) & TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT; /* @@ -2426,8 +2427,8 @@ vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) | ((vlan_tag >> 9) & 0x8); ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT; - ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) << - TPD_VL_TAGGED_SHIFT; + ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) << + TPD_VLANTAG_SHIFT; } tso = atl1_tso(adapter, skb, ptpd); --- linux-2.6.27.orig/drivers/net/atl1e/atl1e_main.c +++ linux-2.6.27/drivers/net/atl1e/atl1e_main.c @@ -2390,9 +2390,7 @@ } /* Init GPHY as early as possible due to power saving issue */ - spin_lock(&adapter->mdio_lock); atl1e_phy_init(&adapter->hw); - spin_unlock(&adapter->mdio_lock); /* reset the controller to * put the device in a known good starting state */ err = atl1e_reset_hw(&adapter->hw); --- linux-2.6.27.orig/drivers/net/e1000e/netdev.c +++ linux-2.6.27/drivers/net/e1000e/netdev.c @@ -4768,11 +4768,21 @@ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V_2), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_V), board_ich9lan }, + /* Even those these are ICH10 devices, the ICH9 setup (which really + * uses ICH8) works fine. Just drop this patch when it collides with + * upstream. I ripped this from the SourceForge e1000e "0.4.1.7" driver. + */ +#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE +#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich9lan }, + { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); --- linux-2.6.27.orig/drivers/net/e1000e/hw.h +++ linux-2.6.27/drivers/net/e1000e/hw.h @@ -349,6 +349,7 @@ #define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 #define E1000_DEV_ID_ICH9_IGP_M 0x10BF #define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB +#define E1000_DEV_ID_ICH9_IGP_M_V_2 0x10BE #define E1000_DEV_ID_ICH9_IGP_C 0x294C #define E1000_DEV_ID_ICH9_IFE 0x10C0 #define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 --- linux-2.6.27.orig/drivers/mmc/core/core.c +++ linux-2.6.27/drivers/mmc/core/core.c @@ -280,7 +280,11 @@ (card->host->ios.clock / 1000); if (data->flags & MMC_DATA_WRITE) - limit_us = 250000; + /* + * The limit is really 250 ms, but that is + * insufficient for some crappy cards. + */ + limit_us = 300000; else limit_us = 100000; @@ -520,7 +524,7 @@ * This delay must be at least 74 clock sizes, or 1 ms, or the * time required to reach a stable voltage. */ - mmc_delay(2); + mmc_delay(10); } static void mmc_power_off(struct mmc_host *host) --- linux-2.6.27.orig/drivers/media/video/tvaudio.c +++ linux-2.6.27/drivers/media/video/tvaudio.c @@ -1792,7 +1792,7 @@ break; case VIDIOC_S_FREQUENCY: chip->mode = 0; /* automatic */ - if (desc->checkmode) { + if (desc->checkmode && desc->setmode) { desc->setmode(chip,V4L2_TUNER_MODE_MONO); if (chip->prevmode != V4L2_TUNER_MODE_MONO) chip->prevmode = -1; /* reset previous mode */ --- linux-2.6.27.orig/drivers/media/video/cx88/cx88-cards.c +++ linux-2.6.27/drivers/media/video/cx88/cx88-cards.c @@ -1238,7 +1238,7 @@ }, [CX88_BOARD_WINFAST_DTV2000H] = { /* video inputs and radio still in testing */ - .name = "WinFast DTV2000 H", + .name = "WinFast DTV2000 H ver. I (old)", .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, @@ -1254,6 +1254,45 @@ }}, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_WINFAST_DTV2000H_2] = { + /* this is just a try */ + .name = "WinFast DTV2000 H ver. J (new)", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00017300, + .gpio1 = 0x00008207, + .gpio2 = 0x00000000, + .gpio3 = 0x02000000, + }, { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00018300, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + } }, + .mpeg = CX88_MPEG_DVB, + }, [CX88_BOARD_GENIATECH_DVBS] = { .name = "Geniatech DVB-S", .tuner_type = TUNER_ABSENT, @@ -1913,6 +1952,10 @@ .subdevice = 0x665e, .card = CX88_BOARD_WINFAST_DTV2000H, },{ + .subvendor = 0x107d, + .subdevice = 0x6f2b, + .card = CX88_BOARD_WINFAST_DTV2000H_2, + },{ .subvendor = 0x18ac, .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */ .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q, --- linux-2.6.27.orig/drivers/media/video/cx88/cx88-dvb.c +++ linux-2.6.27/drivers/media/video/cx88/cx88-dvb.c @@ -554,6 +554,7 @@ } break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_2: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: --- linux-2.6.27.orig/drivers/media/video/cx88/cx88.h +++ linux-2.6.27/drivers/media/video/cx88/cx88.h @@ -221,6 +221,7 @@ #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 #define CX88_BOARD_PROLINK_PV_8000GT 66 #define CX88_BOARD_KWORLD_ATSC_120 67 +#define CX88_BOARD_WINFAST_DTV2000H_2 68 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, --- linux-2.6.27.orig/drivers/media/video/cx88/cx88-mpeg.c +++ linux-2.6.27/drivers/media/video/cx88/cx88-mpeg.c @@ -126,6 +126,11 @@ cx_write(TS_VALERR_CNTRL, 0); udelay(100); break; + case CX88_BOARD_WINFAST_DTV2000H_2: + /* switch signal input to antena */ + cx_write(MO_GP0_IO, 0x00017300); + cx_write(TS_SOP_STAT, 0x00); + break; default: cx_write(TS_SOP_STAT, 0x00); break; --- linux-2.6.27.orig/drivers/media/video/cx88/cx88-input.c +++ linux-2.6.27/drivers/media/video/cx88/cx88-input.c @@ -229,6 +229,7 @@ ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_2: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; --- linux-2.6.27.orig/drivers/media/video/uvc/uvc_driver.c +++ linux-2.6.27/drivers/media/video/uvc/uvc_driver.c @@ -1938,6 +1938,15 @@ .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX }, + /* COMPAL JHL90 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x064e, + .idProduct = 0xa115, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, {} --- linux-2.6.27.orig/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ linux-2.6.27/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -402,6 +402,10 @@ ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); + /* prevent the PTSs from slowly drifting away in the generated + MPEG stream */ + ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1); + return ret; } --- linux-2.6.27.orig/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ linux-2.6.27/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -60,7 +60,6 @@ static DEFINE_MUTEX(pvr2_unit_mtx); static int ctlchg; -static int initusbreset = 1; static int procreload; static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; @@ -71,8 +70,6 @@ MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); module_param(init_pause_msec, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay"); -module_param(initusbreset, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe"); module_param(procreload, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(procreload, "Attempt init failure recovery with firmware reload"); @@ -1698,9 +1695,6 @@ } hdw->fw1_state = FW1_STATE_OK; - if (initusbreset) { - pvr2_hdw_device_reset(hdw); - } if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) { --- linux-2.6.27.orig/drivers/media/video/au0828/au0828-cards.c +++ linux-2.6.27/drivers/media/video/au0828/au0828-cards.c @@ -90,6 +90,7 @@ case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */ + case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ break; @@ -198,6 +199,8 @@ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, { USB_DEVICE(0x2040, 0x721b), .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, + { USB_DEVICE(0x2040, 0x721e), + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, { USB_DEVICE(0x2040, 0x721f), .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, { USB_DEVICE(0x2040, 0x7280), --- linux-2.6.27.orig/drivers/media/dvb/siano/sms-cards.c +++ linux-2.6.27/drivers/media/dvb/siano/sms-cards.c @@ -42,6 +42,10 @@ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0x5510), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5520), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5530), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0x5580), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0x5590), --- linux-2.6.27.orig/drivers/media/dvb/frontends/s5h1411.c +++ linux-2.6.27/drivers/media/dvb/frontends/s5h1411.c @@ -471,6 +471,20 @@ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val); } +static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial) +{ + struct s5h1411_state *state = fe->demodulator_priv; + u16 val; + + dprintk("%s(%d)\n", __func__, serial); + val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100; + + if (serial == 1) + val |= 0x100; + + return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val); +} + static int s5h1411_enable_modulation(struct dvb_frontend *fe, fe_modulation_t m) { @@ -535,7 +549,7 @@ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val); } -static int s5h1411_sleep(struct dvb_frontend *fe, int enable) +static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable) { struct s5h1411_state *state = fe->demodulator_priv; @@ -551,6 +565,11 @@ return 0; } +static int s5h1411_sleep(struct dvb_frontend *fe) +{ + return s5h1411_set_powerstate(fe, 1); +} + static int s5h1411_register_reset(struct dvb_frontend *fe) { struct s5h1411_state *state = fe->demodulator_priv; @@ -574,9 +593,6 @@ s5h1411_enable_modulation(fe, p->u.vsb.modulation); - /* Allow the demod to settle */ - msleep(100); - if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -587,6 +603,10 @@ fe->ops.i2c_gate_ctrl(fe, 0); } + /* Issue a reset to the demod so it knows to resync against the + newly tuned frequency */ + s5h1411_softreset(fe); + return 0; } @@ -599,7 +619,7 @@ dprintk("%s()\n", __func__); - s5h1411_sleep(fe, 0); + s5h1411_set_powerstate(fe, 0); s5h1411_register_reset(fe); for (i = 0; i < ARRAY_SIZE(init_tab); i++) @@ -612,10 +632,10 @@ if (state->config->output_mode == S5H1411_SERIAL_OUTPUT) /* Serial */ - s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101); + s5h1411_set_serialmode(fe, 1); else /* Parallel */ - s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001); + s5h1411_set_serialmode(fe, 0); s5h1411_set_spectralinversion(fe, state->config->inversion); s5h1411_set_if_freq(fe, state->config->vsb_if); @@ -863,6 +883,7 @@ }, .init = s5h1411_init, + .sleep = s5h1411_sleep, .i2c_gate_ctrl = s5h1411_i2c_gate_ctrl, .set_frontend = s5h1411_set_frontend, .get_frontend = s5h1411_get_frontend, --- linux-2.6.27.orig/drivers/i2c/busses/scx200_i2c.c +++ linux-2.6.27/drivers/i2c/busses/scx200_i2c.c @@ -81,6 +81,7 @@ static struct i2c_adapter scx200_i2c_ops = { .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .id = I2C_HW_B_SCX200, .algo_data = &scx200_i2c_data, .name = "NatSemi SCx200 I2C", --- linux-2.6.27.orig/drivers/mtd/chips/jedec_probe.c +++ linux-2.6.27/drivers/mtd/chips/jedec_probe.c @@ -1808,9 +1808,7 @@ * several first banks can contain 0x7f instead of actual ID */ do { - uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), - cfi_interleave(cfi), - cfi->device_type); + uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi); mask = (1 << (cfi->device_type * 8)) - 1; result = map_read(map, base + ofs); bank++; @@ -1824,7 +1822,7 @@ { map_word result; unsigned long mask; - u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type); + u32 ofs = cfi_build_cmd_addr(1, map, cfi); mask = (1 << (cfi->device_type * 8)) -1; result = map_read(map, base + ofs); return result.x[0] & mask; @@ -2067,8 +2065,8 @@ } /* Ensure the unlock addresses we try stay inside the map */ - probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, cfi_interleave(cfi), cfi->device_type); - probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, cfi_interleave(cfi), cfi->device_type); + probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, map, cfi); + probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, map, cfi); if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) goto retry; --- linux-2.6.27.orig/drivers/mtd/chips/cfi_cmdset_0002.c +++ linux-2.6.27/drivers/mtd/chips/cfi_cmdset_0002.c @@ -362,19 +362,6 @@ /* Set the default CFI lock/unlock addresses */ cfi->addr_unlock1 = 0x555; cfi->addr_unlock2 = 0x2aa; - /* Modify the unlock address if we are in compatibility mode */ - if ( /* x16 in x8 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X8) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X8_BY_X16_ASYNC)) || - /* x32 in x16 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X16) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X16_BY_X32_ASYNC))) - { - cfi->addr_unlock1 = 0xaaa; - cfi->addr_unlock2 = 0x555; - } } /* CFI mode */ else if (cfi->cfi_mode == CFI_MODE_JEDEC) { --- linux-2.6.27.orig/drivers/md/dm.c +++ linux-2.6.27/drivers/md/dm.c @@ -1674,6 +1674,7 @@ { return md->disk; } +EXPORT_SYMBOL_GPL(dm_disk); int dm_suspended(struct mapped_device *md) { --- linux-2.6.27.orig/drivers/md/dm-snap.c +++ linux-2.6.27/drivers/md/dm-snap.c @@ -824,8 +824,10 @@ * the bios for the original write to the origin. */ if (primary_pe && - atomic_dec_and_test(&primary_pe->ref_count)) + atomic_dec_and_test(&primary_pe->ref_count)) { origin_bios = bio_list_get(&primary_pe->origin_bios); + free_pending_exception(primary_pe); + } /* * Free the pe if it's not linked to an origin write or if @@ -834,12 +836,6 @@ if (!primary_pe || primary_pe != pe) free_pending_exception(pe); - /* - * Free the primary pe if nothing references it. - */ - if (primary_pe && !atomic_read(&primary_pe->ref_count)) - free_pending_exception(primary_pe); - return origin_bios; } --- linux-2.6.27.orig/drivers/md/dm-kcopyd.c +++ linux-2.6.27/drivers/md/dm-kcopyd.c @@ -268,6 +268,17 @@ spin_unlock_irqrestore(&kc->job_lock, flags); } + +static void push_head(struct list_head *jobs, struct kcopyd_job *job) +{ + unsigned long flags; + struct dm_kcopyd_client *kc = job->kc; + + spin_lock_irqsave(&kc->job_lock, flags); + list_add(&job->list, jobs); + spin_unlock_irqrestore(&kc->job_lock, flags); +} + /* * These three functions process 1 item from the corresponding * job list. @@ -398,7 +409,7 @@ * We couldn't service this job ATM, so * push this job back onto the list. */ - push(jobs, job); + push_head(jobs, job); break; } --- linux-2.6.27.orig/drivers/md/md.c +++ linux-2.6.27/drivers/md/md.c @@ -2109,8 +2109,6 @@ if (strict_strtoull(buf, 10, &size) < 0) return -EINVAL; - if (size < my_mddev->size) - return -EINVAL; if (my_mddev->pers && rdev->raid_disk >= 0) { if (my_mddev->persistent) { size = super_types[my_mddev->major_version]. @@ -2121,9 +2119,9 @@ size = (rdev->bdev->bd_inode->i_size >> 10); size -= rdev->data_offset/2; } - if (size < my_mddev->size) - return -EINVAL; /* component must fit device */ } + if (size < my_mddev->size) + return -EINVAL; /* component must fit device */ rdev->size = size; if (size > oldsize && my_mddev->external) { --- linux-2.6.27.orig/drivers/md/raid10.c +++ linux-2.6.27/drivers/md/raid10.c @@ -1132,7 +1132,7 @@ if (!enough(conf)) return -EINVAL; - if (rdev->raid_disk) + if (rdev->raid_disk >= 0) first = last = rdev->raid_disk; if (rdev->saved_raid_disk >= 0 && --- linux-2.6.27.orig/drivers/md/linear.c +++ linux-2.6.27/drivers/md/linear.c @@ -157,6 +157,8 @@ min_spacing = conf->array_sectors / 2; sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *)); + if (min_spacing == 0) + min_spacing = 1; /* min_spacing is the minimum spacing that will fit the hash * table in one PAGE. This may be much smaller than needed. --- linux-2.6.27.orig/drivers/hwmon/applesmc.c +++ linux-2.6.27/drivers/hwmon/applesmc.c @@ -49,6 +49,9 @@ #define APPLESMC_MAX_DATA_LENGTH 32 +#define APPLESMC_MIN_WAIT 0x0040 +#define APPLESMC_MAX_WAIT 0x8000 + #define APPLESMC_STATUS_MASK 0x0f #define APPLESMC_READ_CMD 0x10 #define APPLESMC_WRITE_CMD 0x11 @@ -57,8 +60,8 @@ #define KEY_COUNT_KEY "#KEY" /* r-o ui32 */ -#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */ -#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */ +#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */ +#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */ #define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */ #define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */ @@ -104,6 +107,15 @@ /* Set 6: Macbook3 set */ { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H", "Th0S", "Th1H", NULL }, +/* Set 7: Macbook Air */ + { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP", + "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL }, +/* Set 8: Macbook Pro 4,1 (Penryn) */ + { "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H", + "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, +/* Set 9: Macbook Pro 3,1 (Santa Rosa) */ + { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", + "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -163,25 +175,25 @@ static struct workqueue_struct *applesmc_led_wq; /* - * __wait_status - Wait up to 2ms for the status port to get a certain value + * __wait_status - Wait up to 32ms for the status port to get a certain value * (masked with 0x0f), returning zero if the value is obtained. Callers must * hold applesmc_lock. */ static int __wait_status(u8 val) { - unsigned int i; + int us; val = val & APPLESMC_STATUS_MASK; - for (i = 0; i < 200; i++) { + for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { + udelay(us); if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) { if (debug) printk(KERN_DEBUG - "Waited %d us for status %x\n", - i*10, val); + "Waited %d us for status %x\n", + 2 * us - APPLESMC_MIN_WAIT, val); return 0; } - udelay(10); } printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n", @@ -191,6 +203,25 @@ } /* + * special treatment of command port - on newer macbooks, it seems necessary + * to resend the command byte before polling the status again. Callers must + * hold applesmc_lock. + */ +static int send_command(u8 cmd) +{ + int us; + for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { + outb(cmd, APPLESMC_CMD_PORT); + udelay(us); + if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) + return 0; + } + printk(KERN_WARNING "applesmc: command failed: %x -> %x\n", + cmd, inb(APPLESMC_CMD_PORT)); + return -EIO; +} + +/* * applesmc_read_key - reads len bytes from a given key, and put them in buffer. * Returns zero on success or a negative error on failure. Callers must * hold applesmc_lock. @@ -205,8 +236,7 @@ return -EINVAL; } - outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT); - if (__wait_status(0x0c)) + if (send_command(APPLESMC_READ_CMD)) return -EIO; for (i = 0; i < 4; i++) { @@ -249,8 +279,7 @@ return -EINVAL; } - outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT); - if (__wait_status(0x0c)) + if (send_command(APPLESMC_WRITE_CMD)) return -EIO; for (i = 0; i < 4; i++) { @@ -284,8 +313,7 @@ readkey[2] = index >> 8; readkey[3] = index; - outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT); - if (__wait_status(0x0c)) + if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD)) return -EIO; for (i = 0; i < 4; i++) { @@ -315,8 +343,7 @@ { int i; - outb(APPLESMC_GET_KEY_TYPE_CMD, APPLESMC_CMD_PORT); - if (__wait_status(0x0c)) + if (send_command(APPLESMC_GET_KEY_TYPE_CMD)) return -EIO; for (i = 0; i < 4; i++) { @@ -325,7 +352,7 @@ return -EIO; } - outb(5, APPLESMC_DATA_PORT); + outb(6, APPLESMC_DATA_PORT); for (i = 0; i < 6; i++) { if (__wait_status(0x05)) @@ -527,17 +554,27 @@ static ssize_t applesmc_light_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { + static int data_length; int ret; u8 left = 0, right = 0; - u8 buffer[6]; + u8 buffer[10], query[6]; mutex_lock(&applesmc_lock); - ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, 6); + if (!data_length) { + ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query); + if (ret) + goto out; + data_length = clamp_val(query[0], 0, 10); + printk(KERN_INFO "applesmc: light sensor data length set to " + "%d\n", data_length); + } + + ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length); left = buffer[2]; if (ret) goto out; - ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, 6); + ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length); right = buffer[2]; out: @@ -1233,11 +1270,29 @@ { .accelerometer = 0, .light = 0, .temperature_set = 5 }, /* MacBook3: accelerometer and temperature set 6 */ { .accelerometer = 1, .light = 0, .temperature_set = 6 }, +/* MacBook Air: accelerometer, backlight and temperature set 7 */ + { .accelerometer = 1, .light = 1, .temperature_set = 7 }, +/* MacBook Pro 4: accelerometer, backlight and temperature set 8 */ + { .accelerometer = 1, .light = 1, .temperature_set = 8 }, +/* MacBook Pro 3: accelerometer, backlight and temperature set 9 */ + { .accelerometer = 1, .light = 1, .temperature_set = 9 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". * So we need to put "Apple MacBook Pro" before "Apple MacBook". */ static __initdata struct dmi_system_id applesmc_whitelist[] = { + { applesmc_dmi_match, "Apple MacBook Air", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, + (void*)&applesmc_dmi_data[7]}, + { applesmc_dmi_match, "Apple MacBook Pro 3", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") }, + &applesmc_dmi_data[9]}, + { applesmc_dmi_match, "Apple MacBook Pro 4", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") }, + &applesmc_dmi_data[8]}, { applesmc_dmi_match, "Apple MacBook Pro", { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, --- linux-2.6.27.orig/drivers/hwmon/hdaps.c +++ linux-2.6.27/drivers/hwmon/hdaps.c @@ -533,6 +533,9 @@ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p"), + HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T61P"), + HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R61"), + HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T61"), { .ident = NULL } }; --- linux-2.6.27.orig/init/version.c +++ linux-2.6.27/init/version.c @@ -39,7 +39,11 @@ /* FIXED STRINGS! Don't touch! */ const char linux_banner[] = "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" - LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; + LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION +#ifdef CONFIG_VERSION_SIGNATURE + " (" CONFIG_VERSION_SIGNATURE ")" +#endif + "\n"; const char linux_proc_banner[] = "%s version %s" --- linux-2.6.27.orig/init/do_mounts_rd.c +++ linux-2.6.27/init/do_mounts_rd.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -51,6 +53,7 @@ struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -62,6 +65,7 @@ ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -99,6 +103,18 @@ goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ --- linux-2.6.27.orig/init/Kconfig +++ linux-2.6.27/init/Kconfig @@ -101,6 +101,15 @@ which is done within the script "scripts/setlocalversion".) +config VERSION_SIGNATURE + string "Arbitrary version signature" + help + This string will be created in a file, /proc/version_signature. It + is useful in determining arbitrary data about your kernel. For instance, + if you have several kernels of the same version, but need to keep track + of a revision of the same kernel, but not affect it's ability to load + compatible modules, this is the easiest way to do that. + config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK --- linux-2.6.27.orig/init/initramfs.c +++ linux-2.6.27/init/initramfs.c @@ -6,6 +6,9 @@ #include #include #include +#ifdef ACPI_CONFIG +#include +#endif static __initdata char *message; static void __init error(char *x) @@ -80,6 +83,12 @@ static __initdata uid_t uid; static __initdata gid_t gid; static __initdata unsigned rdev; +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD +static __initdata char *file_looked_for; +static __initdata struct acpi_table_header *file_mem; +#else +const char *file_looked_for = NULL; +#endif static void __init parse_header(char *s) { @@ -113,6 +122,7 @@ SkipIt, GotName, CopyFile, + CopyFileMem, GotSymlink, Reset } state, next_state; @@ -249,6 +259,54 @@ static __initdata int wfd; +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD +static __init int is_file_looked_for(char *filename) +{ + char *tmp_collected = collected; + if (file_looked_for == NULL) + return 0; + if (!S_ISREG(mode)) + return 0; + /* remove the leading / */ + while (*tmp_collected == '/') + tmp_collected++; + return (strcmp(tmp_collected, file_looked_for) == 0); +} + +static int __init do_copy_mem(void) +{ + static void *file_current; /* current position in the memory */ + if (file_mem == NULL) { + if (body_len < 4) { /* check especially against empty files */ + error("file is less than 4 bytes"); + return 1; + } + file_mem = kmalloc(body_len, GFP_ATOMIC); + if (!file_mem) { + error("failed to allocate enough memory"); + return 1; + } + file_current = file_mem; + } + if (count >= body_len) { + memcpy(file_current, victim, body_len); + eat(body_len); + file_looked_for = NULL; /* don't find files with same name */ + state = SkipIt; + return 0; + } else { + memcpy(file_current, victim, count); + file_current += count; + body_len -= count; + eat(count); + return 1; + } +} +#else +static inline int is_file_looked_for(char *filename) {return 0;} +#define do_copy_mem NULL /* because it is used as a pointer */ +#endif + static int __init do_name(void) { state = SkipIt; @@ -257,6 +315,8 @@ free_hash(); return 0; } + if (is_file_looked_for(file_looked_for)) + state = CopyFileMem; if (dry_run) return 0; clean_path(collected, mode); @@ -323,6 +383,7 @@ [SkipIt] = do_skip, [GotName] = do_name, [CopyFile] = do_copy, + [CopyFileMem] = do_copy_mem, [GotSymlink] = do_symlink, [Reset] = do_reset, }; @@ -560,3 +621,31 @@ return 0; } rootfs_initcall(populate_rootfs); + +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD +struct __init acpi_table_header *acpi_find_dsdt_initrd(void) +{ + char *err, *ramfs_dsdt_name = "DSDT.aml"; + + printk(KERN_INFO "ACPI: Checking initramfs for custom DSDT\n"); + file_mem = NULL; + file_looked_for = ramfs_dsdt_name; + err = unpack_to_rootfs((char *)initrd_start, + initrd_end - initrd_start, 1); + file_looked_for = NULL; + + if (err) { + /* + * Even if reading the DSDT file was successful, + * we give up if the initramfs cannot be entirely read. + */ + kfree(file_mem); + printk(KERN_ERR "ACPI: Aborted because %s.\n", err); + return NULL; + } + if (file_mem) + printk(KERN_INFO "ACPI: Found DSDT in %s.\n", ramfs_dsdt_name); + + return file_mem; +} +#endif --- linux-2.6.27.orig/debian/rules +++ linux-2.6.27/debian/rules @@ -0,0 +1,116 @@ +#!/usr/bin/make -f +# +# debian/rules for Ubuntu linux +# +# Use this however you want, just give credit where credit is due. +# +# Copyright (c) 2007 Ben Collins +# + +# dpkg-buildpackage passes options that are incomptatible +# with the kernel build. +unexport CFLAGS +unexport LDFLAGS + +# This is the debhelper compatability version to use. +export DH_COMPAT=4 +export LC_ALL=C +export SHELL=/bin/bash -e + +# Common variables for all architectures +include debian/rules.d/0-common-vars.mk + +# Pill in some arch specific stuff +include debian/rules.d/$(arch).mk + +# Maintainer targets +include debian/rules.d/1-maintainer.mk + +# Debian Build System targets +binary: binary-indep binary-arch + +build: build-arch build-indep + +clean: debian/control + dh_testdir + dh_testroot + dh_clean + + # d-i stuff + rm -rf modules kernel-versions package-list + rm -rf debian/d-i-$(arch) + + # normal build junk + rm -rf debian/abi/$(release)-$(revision) + rm -rf $(builddir) + rm -f $(stampdir)/stamp-* + rm -rf debian/linux-* + + # This gets rid of the d-i packages in control + cp -f debian/control.stub debian/control + +# Builds the image, arch headers and debug packages +include debian/rules.d/2-binary-arch.mk + +# Rules for building the udebs (debian-installer) +include debian/rules.d/5-udebs.mk + +# Builds the source, doc and linux-headers indep packages +include debian/rules.d/3-binary-indep.mk + +# Various checks to be performed on builds +include debian/rules.d/4-checks.mk + +# Misc stuff +debian/control.stub: debian/d-i/kernel-versions.in \ + debian/scripts/control-create \ + debian/control.stub.in \ + debian/changelog \ + $(wildcard debian/control.d/* debian/sub-flavours/*.vars) + for i in debian/d-i/kernel-versions.in debian/control.stub.in; do \ + new=`echo $$i | sed 's/\.in$$//'`; \ + cat $$i | sed -e 's/PKGVER/$(release)/g' -e 's/ABINUM/$(abinum)/g' > \ + $$new; \ + done + flavours="$(wildcard debian/control.d/vars.* debian/sub-flavours/*.vars)";\ + for i in $$flavours; do \ + $(SHELL) debian/scripts/control-create $$i | \ + sed -e 's/PKGVER/$(release)/g' -e 's/ABINUM/$(abinum)/g' >> \ + debian/control.stub; \ + done + cp debian/control.stub debian/control + +.PHONY: debian/control +debian/control: debian/control.stub + rm -rf modules kernel-versions package-list + mkdir -p modules/$(arch)/ + cp debian/d-i/modules/* modules/$(arch)/ + cp debian/d-i/package-list debian/d-i/kernel-versions . + touch modules/$(arch)/kernel-image + + # Per flavour module lists + flavour_modules=`ls debian/d-i/modules.$(arch)-* 2>/dev/null` \ + || true; \ + if [ "$$flavour_modules" != "" ]; then \ + for flav in $$flavour_modules; do \ + name=`echo $$flav | sed 's/.*\/modules.$(arch)-//'`; \ + mkdir modules/$(arch)-$$name; \ + (cd debian/d-i/modules/; tar cf - `cat ../../../$$flav`) |\ + (cd modules/$(arch)-$$name/; tar xf -); \ + touch modules/$(arch)-$$name/kernel-image; \ + done; \ + fi + + # Remove unwanted stuff + if [ -r "debian/d-i/exclude-modules.$(arch)" ]; then \ + (cat debian/d-i/exclude-modules.$(arch); \ + ls modules/$(arch)/) | sort | uniq -d | \ + (cd modules/$(arch)/; xargs rm -f); \ + fi + + if [ ! -d modules/$(build_arch) ]; then \ + mkdir -p modules/$(build_arch); \ + cp modules/$(arch)/* modules/$(build_arch); \ + fi + + kernel-wedge gen-control > debian/control --- linux-2.6.27.orig/debian/NOTES +++ linux-2.6.27/debian/NOTES @@ -0,0 +1,4 @@ +eSCO patch removed. Replaced upstream with a disable_esco module parm. +airprime: Module gone, use option driver instead +AppArmor: Patch is all there and ported. Ooops when enabled, so default + off (still can be enabled apparmor=1) --- linux-2.6.27.orig/debian/changelog +++ linux-2.6.27/debian/changelog @@ -0,0 +1,2618 @@ +linux (2.6.27-9.18) jaunty; urgency=low + + [ Amit Kucheria ] + + * Add the armel architecture + + [ Leann Ogasawara ] + + * Reboot stalls after installing Intrepid from alternate on a Dell + Optiplex 330 + - LP: #293372 + + [ Stefan Bader ] + + * (no-up) buildenv: Update git-ubuntu-log + + [ Tim Gardner ] + + * SAUCE: Firmware Version is invalid in cciss (version 2) + - LP: #284031 + * Add igb to debian installer udeb + - LP: #290073 + + [ Upstream Kernel Changes ] + + * Revert "HID: Invert HWHEEL mappings for some Logitech mice" + * md: fix bug in raid10 recovery. + - LP: #285156 + * SCSI: sd: Fix handling of NO_SENSE check condition + * S390: Fix sysdev class file creation. + * sysfs: Fix return values for sysdev_store_{ulong, int} + * USB: fix crash when URBs are unlinked after the device is gone + * ALSA: hda - Add reboot notifier + * kbuild: mkspec - fix build rpm + * x86: fix /dev/mem mmap breakage when PAT is disabled + * atl1: fix vlan tag regression + * libertas: fix buffer overrun + * libata: initialize port_task when !CONFIG_ATA_SFF + * syncookies: fix inclusion of tcp options in syn-ack + * tcpv6: fix option space offsets with md5 + * pkt_sched: sch_generic: Fix oops in sch_teql + * sparc64: Fix race in arch/sparc64/kernel/trampoline.S + * math-emu: Fix signalling of underflow and inexact while packing result. + * firewire: fix setting tag and sy in iso transmission + * firewire: fix ioctl() return code + * firewire: Survive more than 256 bus resets + * firewire: fix struct fw_node memory leak + * firewire: fw-sbp2: delay first login to avoid retries + * firewire: fw-sbp2: fix races + * ACPI: Always report a sync event after a lid state change + * powerpc: fix i2c on PPC linkstation / kurobox machines + * powerpc: Reserve in bootmem lmb reserved regions that cross NUMA nodes + * powerpc/numa: Make memory reserve code more robust + * powerpc: Don't use a 16G page if beyond mem= limits + * i2c: The i2c mailing list is moving + * scx200_i2c: Add missing class parameter + * ALSA: use correct lock in snd_ctl_dev_disconnect() + * V4L: pvrusb2: Keep MPEG PTSs from drifting away + * DVB: s5h1411: bugfix: Setting serial or parallel mode could destroy + bits + * DVB: s5h1411: Perform s5h1411 soft reset after tuning + * DVB: s5h1411: Power down s5h1411 when not in use + * PCI: fix 64-vbit prefetchable memory resource BARs + * sched: disable the hrtick for now + * sched_clock: prevent scd->clock from moving backwards + * x86: avoid dereferencing beyond stack + THREAD_SIZE + * rtc-cmos: look for PNP RTC first, then for platform RTC + * USB: storage: Avoid I/O errors when issuing SCSI ioctls to JMicron + USB/ATA bridge + * sata_promise: add ATA engine reset to reset ops + * sata_nv: fix generic, nf2/3 detection regression + * ACPI: EC: Rename some variables + * ACPI: EC: Check for IBF=0 periodically if not in GPE mode + * libata: Fix LBA48 on pata_it821x RAID volumes. + * ACPI: Ingore the RESET_REG_SUP bit when using ACPI reset mechanism + * ACPI: Clear WAK_STS on resume + * hfsplus: fix Buffer overflow with a corrupted image + * hfsplus: check read_mapping_page() return value + * bonding: fix panic when taking bond interface down before removing + module + * file caps: always start with clear bprm->caps_* + * net: Fix recursive descent in __scm_destroy(). + * Linux 2.6.27.5 + * ext3: wait on all pending commits in ext3_sync_fs + * x86: add DMI quirk for AMI BIOS which corrupts address 0xc000 during + resume + * x86: reserve low 64K on AMI and Phoenix BIOS boxen + * x86: add X86_RESERVE_LOW_64K + * x86: fix CONFIG_X86_RESERVE_LOW_64K=y + * x86: fix macro with bad_bios_dmi_table + * cgroups: fix invalid cgrp->dentry before cgroup has been completely + removed + * hugetlb: pull gigantic page initialisation out of the default path + * hugetlbfs: handle pages higher order than MAX_ORDER + * cciss: fix sysfs broken symlink regression + * cciss: new hardware support + * md: linear: Fix a division by zero bug for very small arrays. + * JFFS2: fix race condition in jffs2_lzo_compress() + * JFFS2: Fix lack of locking in thread_should_wake() + * ARM: xsc3: fix xsc3_l2_inv_range + * MTD: [NOR] Fix cfi_send_gen_cmd handling of x16 devices in x8 mode (v4) + * x86: don't use tsc_khz to calculate lpj if notsc is passed + * net: unix: fix inflight counting bug in garbage collector + * r8169: get ethtool settings through the generic mii helper + * r8169: fix RxMissed register access + * r8169: wake up the PHY of the 8168 + * I/OAT: fix channel resources free for not allocated channels + * I/OAT: fix dma_pin_iovec_pages() error handling + * I/OAT: fix async_tx.callback checking + * dca: fixup initialization dependency + * iwlwifi: allow consecutive scans in unassociated state + * iwlwifi: allow association on radar channel in power save + * iwlwifi: remove HT flags from RXON when not in HT anymore + * iwlwifi: don't fail if scan is issued too early + * iwlwifi: use correct DMA_MASK + * iwlwifi: fix suspend to RAM in iwlwifi + * iwlwifi: generic init calibrations framework + * zd1211rw: Add 2 device IDs + * iwl3945: fix deadlock on suspend + * iwl3945: do not send scan command if channel count zero + * cpqarry: fix return value of cpqarray_init() + * ACPI: dock: avoid check _STA method + * ARM: 5300/1: fixup spitz reset during boot + * KEYS: Make request key instantiate the per-user keyrings + * libata: fix last_reset timestamp handling + * Fix __pfn_to_page(pfn) for CONFIG_DISCONTIGMEM=y + * mmc: increase SD write timeout for crappy cards + * hfs: fix namelength memory corruption (CVE-2008-5025) + * HID: fix incorrent length condition in hidraw_write() + * Linux 2.6.27.6 + * Add mouse-modules udeb + + -- Amit Kucheria Tue, 18 Nov 2008 09:37:42 -0700 + +linux (2.6.27-8.17) intrepid-proposed; urgency=low + + [ John W. Linville ] + + * SAUCE: iwlagn: avoid sleep in softirq context + -LP: #286285 + + [ Tim Gardner ] + + * Dell Wireless 365 needs BTUSB_RESET quirk. + - LP: #293670 + * SAUCE: ALSA: hda: make a STAC_DELL_EQ option (version 2) + - LP: #293271 + + [ Upstream Kernel Changes ] + + * iwlagn: downgrade BUG_ON in interrupt + * Input: atkbd - expand Latitude's force release quirk to other Dells + * fbcon_set_all_vcs: fix kernel crash when switching the rotated consoles + * modules: fix module "notes" kobject leak + * Driver core: Fix cleanup in device_create_vargs(). + * Driver core: Clarify device cleanup. + * ath9k/mac80211: disallow fragmentation in ath9k, report to userspace + * md: Fix rdev_size_store with size == 0 + * xfs: fix remount rw with unrecognized options + * OHCI: Allow broken controllers to auto-stop + * USB: OHCI: fix endless polling behavior + * USB: Fix s3c2410_udc usb speed handling + * USB: EHCI: log a warning if ehci-hcd is not loaded first + * usb gadget: cdc ethernet notification bugfix + * usb: musb_hdrc build fixes + * drm/i915: fix ioremap of a user address for non-root (CVE-2008-3831) + * DVB: au0828: add support for another USB id for Hauppauge HVR950Q + * DVB: sms1xxx: support two new revisions of the Hauppauge WinTV + MiniStick + * security: avoid calling a NULL function pointer in + drivers/video/tvaudio.c + * Linux 2.6.27.3 + -LP: #294152 + + * gpiolib: fix oops in gpio_get_value_cansleep() + * edac cell: fix incorrect edac_mode + * x86 ACPI: fix breakage of resume on 64-bit UP systems with SMP kernel + * sched: fix the wrong mask_len + * USB: cdc-wdm: make module autoload work + * USB: don't rebind drivers after failed resume or reset + * USB: fix memory leak in cdc-acm + * USB: Speedtouch: add pre_reset and post_reset routines + * dm kcopyd: avoid queue shuffle + * dm snapshot: fix primary_pe race + * amd_iommu: fix nasty bug that caused ILLEGAL_DEVICE_TABLE_ENTRY errors + * CIFS: fix saving of resume key before CIFSFindNext + * netfilter: xt_iprange: fix range inversion match + * netfilter: snmp nat leaks memory in case of failure + * netfilter: restore lost ifdef guarding defrag exception + * anon_vma_prepare: properly lock even newly allocated entries + * hvc_console: Fix free_irq in spinlocked section + * ACPI Suspend: Enable ACPI during resume if SCI_EN is not set + * ACPI suspend: Blacklist HP xw4600 Workstation for old code ordering + * ACPI suspend: Always use the 32-bit waking vector + * proc: fix vma display mismatch between /proc/pid/{maps,smaps} + * SCSI: scsi_dh: add Dell product information into rdac device handler + * PCI hotplug: cpqphp: fix kernel NULL pointer dereference + * V4L/DVB (9300): pvrusb2: Fix deadlock problem + * Linux 2.6.27.4 + -LP: #294155 + + -- Tim Gardner Tue, 04 Nov 2008 12:16:07 -0700 + +linux (2.6.27-7.16) intrepid-security; urgency=low + + [ Tim Gardner ] + + * ndiswrapper remote buffer overflows on long ESSIDs (CVE 2008-4395) + - LP: #275860 + + [ Upstream Kernel Changes ] + + * ext[234]: Avoid printk floods in the face of directory corruption + (CVE-2008-3528) + + -- Tim Gardner Mon, 03 Nov 2008 13:34:42 -0700 + +linux (2.6.27-7.15) intrepid-security; urgency=low + + [ Upstream Kernel Changes ] + + * tcp: Restore ordering of TCP options for the sake of inter-operability + - LP: #264019 + + -- Tim Gardner Mon, 27 Oct 2008 19:28:06 -0600 + +linux (2.6.27-7.14) intrepid; urgency=low + + [ Tim Gardner ] + + * Disable ath5k in 2.6.27 + - LP: #288148 + + -- Tim Gardner Thu, 23 Oct 2008 07:40:43 -0600 + +linux (2.6.27-7.13) intrepid; urgency=low + + [ Stefan Bader ] + + * gfs1: GFS1 can't create more than 4kb file + + [ Tim Gardner ] + + * Revert "SAUCE: x86: Reserve FIRST_DEVICE_VECTOR in used_vectors + bitmap.". Use upstream commit to avoid future conflicts. + * Revert "STABLE queue: mac80211: fix two issues in debugfs". + Use upstream commit to avoid future conflicts. + * Revert "x86, early_ioremap: fix fencepost error" + Use upstream commit to avoid future conflicts. + + [ Upstream Kernel Changes ] + + * sched_rt.c: resch needed in rt_rq_enqueue() for the root rt_rq + * x86: Reserve FIRST_DEVICE_VECTOR in used_vectors bitmap. + * mac80211: fix two issues in debugfs + * Fix barrier fail detection in XFS + * tty: Termios locking - sort out real_tty confusions and lock reads + * CIFS: make sure we have the right resume info before calling + CIFSFindNext + * rfkill: update LEDs for all state changes + * libertas: clear current command on card removal + * b43legacy: Fix failure in rate-adjustment mechanism + * x86, early_ioremap: fix fencepost error + * x86: SB450: skip IRQ0 override if it is not routed to INT2 of IOAPIC + * x86: improve UP kernel when CPU-hotplug and SMP is enabled + * sky2: Fix WOL regression + * netdrvr: atl1e: Don't take the mdio_lock in atl1e_probe + * Linux 2.6.27.2 + + [ Amit Kucheria ] + + * Ubuntu: agp: Fix stolen memory counting on G4X. + -LP: 285572 + + [ Scott Remnant ] + + * add MODULE_ALIAS to load ipmi_devintf with ipmi_si + + -- Tim Gardner Sun, 19 Oct 2008 10:06:21 -0600 + +linux (2.6.27-7.12) intrepid; urgency=low + + [ Chuck Short ] + + * xen: Add xen modules to virtual flavours. + + [ Mario Limonciello ] + + * SAUCE: Add back in lost commit for Apple BT Wireless Keyboard + - LP: #162083 + + [ Tim Gardner ] + + * Remove depmod created files from packages. + - LP: #250511 + * Changed default TCP congestion algorithm to 'cubic' (again) + - LP: #278801 + * Update configs for 'disable CONFIG_DYNAMIC_FTRACE' + - LP: #263555 + + [ Upstream Kernel Changes ] + + * x86: register a platform RTC device if PNP doesn't describe it + * disable CONFIG_DYNAMIC_FTRACE due to possible memory corruption on + module unload + + -- Tim Gardner Fri, 17 Oct 2008 11:25:39 -0600 + +linux (2.6.27-7.11) intrepid; urgency=low + + [ Amit Kucheria ] + + * STABLE queue: mac80211: fix two issues in debugfs + - LP: #275227 + * SAUCE: Adds support for COMPAL JHL90 webcam + + [ Ben Collins ] + + * SAUCE: (no-up) x86: Quiet "Kernel alive" messages + - LP: #39985 + * SAUCE: (no-up) Modularize vesafb + * build/config: Enable vesafb module + * build: Switch to vesafb as preferred. + + [ Leann Ogasawara ] + + * Add Dell Dimension 9200 reboot quirk + - LP: #271370 + + [ Michael Haas ] + + * SAUCE: Revert aufs changes from AppArmor merge + + [ Tim Gardner ] + + * fix virtio udeb layout + - LP: #257739 + * Enabled CONFIG_EXT4DEV_FS=m + * Changed default TCP congestion algorithm to 'cubic' + - LP: #278801 + * SAUCE: ipw2200: change default policy for auto-associate + - LP: #264104 + + [ Upstream Kernel Changes ] + + * x86, early_ioremap: fix fencepost error + - LP: #263543 + + -- Tim Gardner Sat, 11 Oct 2008 08:07:42 -0600 + +linux (2.6.27-7.10) intrepid; urgency=low + + [ Alexey Starikovskiy ] + + * SAUCE: ACPI: EC: do transaction from interrupt context + - LP: #277802 + + [ Ben Collins ] + + * build/d-i: Change virtio-modules udeb to prio standard + + [ Colin Ian King ] + + * SAUCE: Blacklist IBM 2656 in serio/i8042 + - LP: #21558 + + [ Henrik Rydberg ] + + * Revert "SAUCE: applesmc: Add MacBookAir" + * SAUCE: [PATCH 1/5] hwmon: applesmc: Specified number of bytes to read + should match actual + * SAUCE: [PATCH 2/5] hwmon: applesmc: Fix the 'wait status failed: c != + 8' problem + * SAUCE: [PATCH 3/5] hwmon: applesmc: Prolong status wait + * SAUCE: [PATCH 4/5] hwmon: applesmc: Allow for variable ALV0 and ALV1 + package length + * SAUCE: [PATCH 5/5] hwmon: applesmc: Add support for Macbook Air + * SAUCE: hwmon: applesmc: Add support for Macbook Pro 4 + * SAUCE: hwmon: applesmc: Add support for Macbook Pro 3 + * SAUCE: hwmon: applesmc: Lighter wait mechanism, drastic improvement + + [ Leann Ogasawara ] + + * Add automatic model setting for Samsung Q45 + - LP: #200210 + + [ Tim Gardner ] + + * SAUCE: Correctly blacklist Thinkpad r40e in ACPI + - LP: #278794 + * SAUCE: Update Wacom tablet driver to 1.49 + - LP: #260675 + * SAUCE: ALPS touchpad for Dell Latitude E6500/E6400 + - LP: #270643 + * SAUCE: Fix Wacom tablet 1.49 porting errors + * SAUCE: Enable an e1000e Intel Corporation 82567 Gigabit controller + * SAUCE: Fix Oops in wlan_setup + - LP: #263309 + + [ Upstream Kernel Changes ] + + * ath9k: fix oops on trying to hold the wrong spinlock + * [Bluetooth] Fix double frees on error paths of btusb and bpa10x drivers + * [Bluetooth] Add reset quirk for new Targus and Belkin dongles + * [Bluetooth] Add reset quirk for A-Link BlueUSB21 dongle + * Revert "ax25: Fix std timer socket destroy handling." + * ax25: Quick fix for making sure unaccepted sockets get destroyed. + * netrom: Fix sock_orphan() use in nr_release + * Revert "V4L/DVB (8904): cx88: add missing unlock_kernel" + * SLOB: fix bogus ksize calculation + * net: only invoke dev->change_rx_flags when device is UP + * tcp: Fix possible double-ack w/ user dma + * net: Fix netdev_run_todo dead-lock + * tcp: Fix tcp_hybla zero congestion window growth with small rho and large cwnd. + * [MIPS] Sibyte: Register PIO PATA device only for Swarm and Litte Sur + * eeepc-laptop: Fix hwmon interface + * hwmon: (it87) Prevent power-off on Shuttle SN68PT + * hwmon: Define sysfs interface for energy consumption register + * hwmon: (adt7473) Fix some bogosity in documentation file + * hwmon: (abituguru3) Enable reading from AUX3 fan on Abit AT8 32X + * hwmon: (abituguru3) Enable DMI probing feature on Abit AT8 32X + * [CPUFREQ] correct broken links and email addresses + * SLOB: fix bogus ksize calculation fix + * Don't allow splice() to files opened with O_APPEND + * Linux 2.6.27 + + -- Tim Gardner Wed, 08 Oct 2008 21:19:34 -0600 + +linux (2.6.27-6.9) intrepid; urgency=low + + [ Kees Cook ] + + * SAUCE: AppArmor: update to upstream subversion r1302 + - LP: #269921 + + [ Stefan Bader ] + + * Update configuration files to be compliant to desktop specs + - LP: #279019 + + [ Tim Gardner ] + + * Add support in e1000e for a couple of ICH10 PCI IDs + * Enable CONFIG_INPUT_PCSPKR=m + - LP: #275453 + + [ Upstream Kernel Changes ] + + * V4L/DVB (8559a): Fix a merge conflict at gspca/sonixb + * V4L/DVB (8789): wm8739: remove wrong kfree + * V4L/DVB (8883): w9968cf: Fix order of usb_alloc_urb validation + * V4L/DVB (8884): em28xx-audio: fix memory leak + * V4L/DVB (8885): cpia2_usb: fix memory leak + * V4L/DVB (8886): ov511: fix memory leak + * V4L/DVB (8887): gspca: fix memory leak + * V4L/DVB (8892): pvrusb2: Handle USB ID 2040:2950 same as 2040:2900 + * V4L/DVB (8904): cx88: add missing unlock_kernel + * V4L/DVB (8905): ov511: fix exposure sysfs attribute bug + * V4L/DVB (8909): gspca: PAC 7302 webcam 093a:262a added. + * hrtimer: migrate pending list on cpu offline + * hrtimer: fix migration of CB_IRQSAFE_NO_SOFTIRQ hrtimers + * hrtimer: mark migration state + * hrtimer: prevent migration of per CPU hrtimers + * [IA64] Put the space for cpu0 per-cpu area into .data section + * powerpc: Fix PCI in Holly device tree + * powerpc: Fix failure to shutdown with CPU hotplug + * mfd: Fix Kconfig accroding to the new gpiolib symbols + * mfd: Fix asic3 compilation + * x86: fix typo in enable_mtrr_cleanup early parameter + * ipsec: Fix pskb_expand_head corruption in xfrm_state_check_space + * iucv: Fix mismerge again. + * ALSA: ASoC: Fix cs4270 error path + * ALSA: hda - Fix model for Dell Inspiron 1525 + * sctp: Fix kernel panic while process protocol violation parameter + * x86: Fix broken LDT access in VMI + * x86, vmi: fix broken LDT access + * tcp: Fix NULL dereference in tcp_4_send_ack() + * ipv6: NULL pointer dereferrence in tcp_v6_send_ack + * XFRM,IPv6: initialize ip6_dst_blackhole_ops.kmem_cachep + * af_key: Free dumping state on socket close + * dm: always allow one page in dm_merge_bvec + * dm: cope with access beyond end of device in dm_merge_bvec + * dm mpath: add missing path switching locking + * MN10300: Fix IRQ handling + * pxa2xx_spi: fix build breakage + * e1000e: write protect ICHx NVM to prevent malicious write/erase + * powerpc: Fix boot hang regression on MPC8544DS + * ASoC: Set correct name for WM8753 rec mixer output + * ALSA: snd-powermac: mixers for PowerMac G4 AGP + * ALSA: snd-powermac: HP detection for 1st iMac G3 SL + * fbcon: fix monochrome color value calculation + * inotify: fix lock ordering wrt do_page_fault's mmap_sem + * braille_console: only register notifiers when the braille console is used + * fix error-path NULL deref in alloc_posix_timer() + * memory hotplug: missing zone->lock in test_pages_isolated() + * mm: tiny-shmem nommu fix + * mm: handle initialising compound pages at orders greater than MAX_ORDER + * e1000e: reset swflag after resetting hardware + * e1000e: do not ever sleep in interrupt context + * e1000e: remove phy read from inside spinlock + * e1000e: drop stats lock + * e1000e: debug contention on NVM SWFLAG + * e1000e: update version from k4 to k6 + * Check mapped ranges on sysfs resource files + * e1000e: Fix incorrect debug warning + * [MIPS] Build fix: Fix irq flags type + * [MIPS] SMTC: Build fix: Fix filename in Makefile + * [MIPS] SMTC: Fix holes in SMTC and FPU affinity support. + * [MIPS] SMTC: Close tiny holes in the SMTC IPI replay system. + * [MIPS] SMTC: Fix SMTC dyntick support. + * [S390] nohz: Fix __udelay. + * [S390] qdio: prevent stack clobber + * Fix init/main.c to use regular printk with '%pF' for initcall fn + * x86 setup: correct segfault in generation of 32-bit reloc kernel + * selinux: Fix an uninitialized variable BUG/panic in selinux_secattr_to_sid() + * rtc: fix kernel panic on second use of SIGIO nofitication + * fbdev: fix recursive notifier and locking when fbdev console is blanked + * orion_spi: fix handling of default transfer speed + * include/linux/stacktrace.h: declare struct task_struct + * cpusets: remove pj from cpuset maintainers + * MAINTAINERS: add mailing list for man-pages + * SubmitChecklist: interfaces changes should CC linux-api@ + * Documentation/HOWTO: info about interface changes should CC linux-api@vger + * dw_dmac: fix copy/paste bug in tasklet + * leds-fsg: change order of initialization and deinitialization + * leds-pca955x: add proper error handling and fix bogus memory handling + * ACPI: Make /proc/acpi/wakeup interface handle PCI devices (again) + * clockevents: check broadcast tick device not the clock events device + * V4L/DVB (8919): cx18: Fix tuner audio input for Compro H900 cards + * V4L/DVB (8926): gspca: Bad fix of leak memory (changeset 43d2ead315b1). + * V4L/DVB (8933): gspca: Disable light frquency for zc3xx cs2102 Kokom. + * V4L/DVB (8935): em28xx-cards: Remove duplicate entry (EM2800_BOARD_KWORLD_USB2800) + * V4L/DVB (8955): bttv: Prevent NULL pointer dereference in radio_open + * V4L/DVB (8957): zr36067: Restore the default pixel format + * V4L/DVB (8958): zr36067: Return proper bytes-per-line value + * V4L/DVB (8960): drivers/media/video/cafe_ccic.c needs mm.h + * V4L/DVB (8961): zr36067: Fix RGBR pixel format + * V4L/DVB (8963): s2255drv field count fix + * V4L/DVB (8967): Use correct XC3028L firmware for AMD ATI TV Wonder 600 + * V4L/DVB (8978): sms1xxx: fix product name for Hauppauge WinTV MiniStick + * V4L/DVB (8979): sms1xxx: Add new USB product ID for Hauppauge WinTV MiniStick + * V4L/DVB (9029): Fix deadlock in demux code + * V4L/DVB (9037): Fix support for Hauppauge Nova-S SE + * V4L/DVB (9043): S5H1420: Fix size of shadow-array to avoid overflow + * V4L/DVB (9053): fix buffer overflow in uvc-video + * V4L/DVB (9075): gspca: Bad check of returned status in i2c_read() spca561. + * V4L/DVB (9080): gspca: Add a delay after writing to the sonixj sensors. + * V4L/DVB (9092): gspca: Bad init values for sonixj ov7660. + * V4L/DVB (9099): em28xx: Add detection for K-WORLD DVB-T 310U + * V4L/DVB (9103): em28xx: HVR-900 B3C0 - fix audio clicking issue + * x86: gart iommu have direct mapping when agp is present too + * ide-cd: temporary tray close fix + * ide-dma: fix ide_build_dmatable() for TRM290 + * IDE: Fix platform device registration in Swarm IDE driver (v2) + * ide-cd: Optiarc DVD RW AD-7200A does play audio + * ide: workaround for bogus gcc warning in ide_sysfs_register_port() + * [MIPS] Fix CMP Kconfig configuration and mark as broken. + * [MIPS] IP27: Fix build errors if CONFIG_MAPPED_KERNEL=y + * x86 ACPI: Blacklist two HP machines with buggy BIOSes + * kgdb, x86: Avoid invoking kgdb_nmicallback twice per NMI + * kgdb: call touch_softlockup_watchdog on resume + * atmel-mci: Initialize BLKR before sending data transfer command + * Marker depmod fix core kernel list + * Linux 2.6.27-rc9 + + -- Tim Gardner Sun, 05 Oct 2008 21:27:49 -0600 + +linux (2.6.27-5.8) intrepid; urgency=low + + [ Amit Kucheria ] + + * Update AUFS-related Kconfig + - LP: #264048 + + [ Michael Haas ] + + * add proper aufs source tree from 20080922 + * Fix AUFS compilation in vfsub.c + * Add splice-2.6.23.patch from AUFS to export a symbol needed by AUFS + * Add put_filp.patch from AUFS to export a symbol needed by AUFS + * apply (modified) lhash.patch from AUFS to export __lookup_hash() + * Add deny_write_access.patch from AUFS - export deny_write_access + * Add sec_perm-2.6.24.patch from AUFS - export security_inode_permission + * make sure TMPFS_MAGIC is defined in AUFS Makefile + + [ Tim Gardner ] + + * Enabled CONFIG_IPWIRELESS + - LP: #274748 + * Enabled CONFIG_E1000E, disabled CONFIG_E1000E_NEW + This takes advantage of the upstream NVM protection fix in + commit 4a7703582836f55a1cbad0e2c1c6ebbee3f9b3a7. + + [ Upstream Kernel Changes ] + + * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ + handler" + * [SCSI] qla2xxx: Defer enablement of RISC interrupts until ISP + initialization completes. + * PCI: Fix pcie_aspm=force + * PCI: fix compiler warnings in pci_get_subsys() + * UBIFS: create the name of the background thread in every case + * UBIFS: TNC / GC race fixes + * UBIFS: remove incorrect assert + * UBIFS: fix printk format warnings + * AMD IOMMU: set iommu sunc flag after command queuing + * AMD IOMMU: protect completion wait loop with iommu lock + * sparc64: Fix disappearing PCI devices on e3500. + * x86, oprofile: BUG scheduling while atomic + * ALSA: ASoC: Fix at32-pcm build breakage with PM enabled + * ath9k: connectivity is lost after Group rekeying is done + * wireless: zd1211rw: add device ID fix wifi dongle "trust nw-3100" + * [IA64] Ski simulator doesn't need check_sal_cache_flush + * [IA64] kexec fails on systems with blocks of uncached memory + * ath9k: Fix IRQ nobody cared issue with ath9k + * [Bluetooth] Fix I/O errors on MacBooks with Broadcom chips + * [Bluetooth] Fix wrong URB handling of btusb driver + * [Bluetooth] Fix USB disconnect handling of btusb driver + * sparc64: Fix missing devices due to PCI bridge test in + of_create_pci_dev(). + * [WATCHDOG] ibmasr: remove unnecessary spin_unlock() + * [WATCHDOG] wdt285: fix sparse warnings + * [WATCHDOG] unlocked_ioctl changes + * x86: fix 27-rc crash on vsmp due to paravirt during module load + * sched: fix init_hrtick() section mismatch warning + * clockevents: prevent cpu online to interfere with nohz + * x86: prevent stale state of c1e_mask across CPU offline/online + * clockevents: prevent stale tick_next_period for onlining CPUs + * clockevents: check broadcast device not tick device + * clockevents: prevent mode mismatch on cpu online + * x86: prevent C-states hang on AMD C1E enabled machines + * x86: c1e_idle: don't mark TSC unstable if CPU has invariant TSC + * timers: fix build error in !oneshot case + * ALSA: ASoC: maintainers - update email address for Liam Girdwood + * ibmasr: remove unnecessary spin_unlock() + * smb.h: do not include linux/time.h in userspace + * kernel-doc: allow structs whose members are all private + * kexec: fix segmentation fault in kimage_add_entry + * Documentation/DMA-mapping.txt: update for pci_dma_mapping_error() + changes + * sys_paccept: disable paccept() until API design is resolved + * mm: tiny-shmem fix lock ordering: mmap_sem vs i_mutex + * Documentation/sysctl/kernel.txt: fix softlockup_thresh description + * memcg: check under limit at shrink_usage + * atmel_serial: update the powersave handler to match serial core + * [SCSI] Fix hang with split requests + * USB Storage: Sierra: Non-configurable TRU-Install + * USB Serial: Sierra: Device addition & version rev + * USB: ehci: fix some ehci hangs and crashes + * USB: Fix the Nokia 6300 storage-mode. + * USB: Correct Sierra Wireless USB EVDO Modem Device ID + * USB: fix hcd interrupt disabling + * USB: update of Documentation/usb/anchors.txt + * usb gadget: fix omap_udc DMA regression + * USB: Fixing Nokia 3310c in storage mode + * usb: musb: fix include path + * USB: fix EHCI periodic transfers + * usb-serial: Add Siemens EF81 to PL-2303 hack triggers + * USB: SERIAL CP2101 add device IDs + * USB: unusual_devs addition for RockChip MP3 player + * USB: fsl_usb2_udc: fix VDBG() format string + * usb serial: ti_usb_3410_5052 obviously broken by firmware changes + * USB: ftdi_sio: Add 0x5050/0x0900 USB IDs (Papouch Quido USB 4/4) + * USB: serial: add ZTE CDMA Tech id to option driver + * USB Serial: Sierra: Add MC8785 VID/PID + * USB: drivers/usb/musb/: disable it on SuperH + * usb: ftdi_sio: add support for Domintell devices + * usb: unusual devs patch for Nokia 5310 Music Xpress + * USB: revert recovery from transient errors + * [MIPS] au1000: Fix gpio direction + * [MIPS] Fixe the definition of PTRS_PER_PGD + * x86: prevent stale state of c1e_mask across CPU offline/online, fix + * x86: disable apm on the olpc + * i2c-powermac: Fix section for probe and remove functions + * i2c-dev: Return correct error code on class_create() failure + * i2c: Fix mailing lists in two MAINTAINERS entries + * ath9k: disable MIB interrupts to fix interrupt storm + * 9p: implement proper trans module refcounting and unregistration + * 9p-trans_fd: fix trans_fd::p9_conn_destroy() + * 9p-trans_fd: clean up p9_conn_create() + * 9p-trans_fd: don't do fs segment mangling in p9_fd_poll() + * 9p-trans_fd: fix and clean up module init/exit paths + * 9p: introduce missing kfree + * 9p: use an IS_ERR test rather than a NULL test + * 9p: fix put_data error handling + * netfilter: ip6t_{hbh,dst}: Rejects not-strict mode on rule insertion + * MN10300: Move asm-arm/cnt32_to_63.h to include/linux/ + * MN10300: Make sched_clock() report time since boot + * ALSA: fix locking in snd_pcm_open*() and snd_rawmidi_open*() + * ALSA: remove unneeded power_mutex lock in snd_pcm_drop + * IPoIB: Fix crash when path record fails after path flush + * [XFS] Fix extent list corruption in xfs_iext_irec_compact_full(). + * [XFS] Remove xfs_iext_irec_compact_full() + * kgdb: could not write to the last of valid memory with kgdb + * kgdb, x86, arm, mips, powerpc: ignore user space single stepping + * kgdb, x86_64: gdb serial has BX and DX reversed + * kgdb, x86_64: fix PS CS SS registers in gdb serial + * kgdboc,tty: Fix tty polling search to use name correctly + * ARM: Delete ARM's own cnt32_to_63.h + * m32r: remove the unused NOHIGHMEM option + * m32r: don't offer CONFIG_ISA + * m32r: export empty_zero_page + * m32r: export __ndelay + * m32r/kernel/: cleanups + * [MIPS] au1000: Make sure GPIO value is zero or one + * [MIPS] IP27: Switch to dynamic interrupt routing avoding panic on + error. + * [MIPS] BCM47xx: Fix build error due to missing PCI functions + * [SSB] Initialise dma_mask for SSB_BUSTYPE_SSB devices + * Swarm: Fix crash due to missing initialization + * ide-tape: fix vendor strings + * ide: note that IDE generic may prevent other drivers from attaching + * cdrom: update ioctl documentation + * [SCSI] qlogicpti: fix sg list traversal error in continuation entries + * sata_nv: reinstate nv_hardreset() for non generic controllers + * scsi: fix fall out of sg-chaining patch in qlogicpti + * ALSA: make the CS4270 driver a new-style I2C driver + * ALSA: ASoC: Fix another cs4270 error path + * Fix NULL pointer dereference in proc_sys_compare + * kconfig: fix silentoldconfig + * kconfig: readd lost change count + * mm owner: fix race between swapoff and exit + * Linux 2.6.27-rc8 + * e1000e: write protect ICHx NVM to prevent malicious write/erase + + -- Amit Kucheria Tue, 30 Sep 2008 18:22:35 +0300 + +linux (2.6.27-4.7) intrepid; urgency=low + + [ Ben Collins ] + + * build/abi: Add gfs1 to perm blacklist + * build/abi: Ignored changes in gfs2 symbols + + [ Fabio M. Di Nitto ] + + * Revert "SAUCE: Export gfs2 symbols required for gfs1 kernel module" + * ubuntu: update GFS Cluster File System + + [ Stefan Bader ] + + * SAUCE: x86: Reserve FIRST_DEVICE_VECTOR in used_vectors bitmap. + - LP: #276334 + + [ Tim Gardner ] + + * Revert "Disable e1000e until the NVRAM corruption problem is found." + * Add atl1e and atl2 to Debian installer bits + - LP: #273904 + * SAUCE: e1000e: Map NV RAM dynamically only when needed. + - LP: #263555 + + -- Tim Gardner Fri, 26 Sep 2008 20:51:22 -0600 + +linux (2.6.27-4.6) intrepid; urgency=low + + [ Tim Gardner ] + + * Disable e1000e until the NVRAM corruption problem is found. + - LP: #263555 + + [ Upstream Kernel Changes ] + + * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ + handler" + + -- Ben Collins Tue, 23 Sep 2008 09:53:57 -0400 + +linux (2.6.27-4.5) intrepid; urgency=low + + [ Upstream Kernel Changes ] + + * Revert "b43/b43legacy: add RFKILL_STATE_HARD_BLOCKED support" + * udf: Fix lock inversion between iprune_mutex and alloc_mutex (v2) + * udf: Fix error paths in udf_new_inode() + * [SCSI] sd: select CRC_T10DIF only when necessary + * [SCSI] zfcp: Fix request queue locking + * [SCSI] zfcp: Correctly query end flag in gpn_ft response + * [SCSI] zfcp: Simplify ccw notify handler + * [SCSI] zfcp: Fix reference counter for remote ports + * [SCSI] zfcp: channel cannot be detached due to refcount imbalance + * [SCSI] zfcp: Remove duplicated unlikely() macros. + * [SCSI] scsi_dh: make check_sense return ADD_TO_MLQUEUE + * [SCSI] make scsi_check_sense HARDWARE_ERROR return ADD_TO_MLQUEUE on + retry + * [SCSI] fix check of PQ and PDT bits for WLUNs + * pcm037: add rts/cts support for serial port + * i.MX serial: fix init failure + * imx serial: set RXD mux bit on i.MX27 and i.MX31 + * imx serial: fix rts handling for non imx1 based hardware + * mlx4_core: Set RAE and init mtt_sz field in FRMR MPT entries + * udf: add llseek method + * PCI/iommu: blacklist DMAR on Intel G31/G33 chipsets + * PCI: Fix printk warnings in probe.c + * PCI: Fix printk warnings in setup-bus.c + * PCI Hotplug: fakephp: fix deadlock... again + * clockevents: remove WARN_ON which was used to gather information + * ocfs2: Fix a bug in direct IO read. + * arch/x86/kernel/kdebugfs.c: introduce missing kfree + * [IA64] fix compile failure with non modular builds + * [IA64] fix up bte.h + * [IA64] arch/ia64/sn/pci/tioca_provider.c: introduce missing kfree + * PCI: fix pciehp_free_irq() + * [IA64] prevent ia64 from invoking irq handlers on offline CPUs + * ide: Fix pointer arithmetic in hpt3xx driver code (3rd try) + * add deprecated ide-scsi to feature-removal-schedule.txt + * swiotlb: fix back-off path when memory allocation fails + * sparc64: Fix interrupt register calculations on Psycho and Sabre. + * VIDEO_SH_MOBILE_CEU should depend on HAS_DMA + * m68k: Update defconfigs for 2.6.27-rc6 + * sparc32: Fix function signature of of_bus_sbus_get_flags(). + * sched: fix 2.6.27-rc5 couldn't boot on tulsa machine randomly + * sched: fix deadlock in setting scheduler parameter to zero + * KVM: SVM: fix random segfaults with NPT enabled + * KVM: SVM: fix guest global tlb flushes with NPT + * KVM: VMX: Always return old for clear_flush_young() when using EPT + * clocksource, acpi_pm.c: fix check for monotonicity + * [ARM] OMAP: Fix MMC device data + * block: disable sysfs parts of the disk command filter + * ath9k: Assign seq# when mac80211 requests this + * sg: disable interrupts inside sg_copy_buffer + * MN10300: Change the fault handler to check in_atomic() not + in_interrupt() + * [Bluetooth] Fix regression from using default link policy + * netlink: fix overrun in attribute iteration + * x86: fix possible x86_64 and EFI regression + * sparc64: Fix PCI error interrupt registry on PSYCHO. + * sparc: Fix user_regset 'n' field values. + * niu: panic on reset + * PCI: re-add debug prints for unmodified BARs + * [ARM] 5245/1: Fix warning about unused return value in drivers/pcmcia + * [ARM] 5246/1: tosa: add proper clock alias for tc6393xb clock + * [ARM] 5247/1: tosa: SW_EAR_IN support + * [ARM] Fix PCI_DMA_BUS_IS_PHYS for ARM + * ata: duplicate variable sparse warning + * sata_inic162x: enable LED blinking + * [libata] LBA28/LBA48 off-by-one bug in ata.h + * proc: more debugging for "already registered" case + * include/linux/ioport.h: add missing macro argument for devm_release_* + family + * cpuset: avoid changing cpuset's cpus when -errno returned + * cpuset: hotplug documentation fix + * coredump_filter: add description of bit 4 + * bfs: fix Lockdep warning + * mm: ifdef Quicklists in /proc/meminfo + * spi_mpc83xx: fix clockrate calculation for low speed + * spi_mpc83xx: reject invalid transfer sizes + * pxa2xx_spi: chipselect bugfixes + * pxa2xx_spi: dma bugfixes + * mm: mark the correct zone as full when scanning zonelists + * Documentation/ABI: /sys/class/gpio + * MAINTAINERS: fix USB VIDEO CLASS mail list address + * ia64: fix panic during `modprobe -r xpc' + * atmel_lcdfb: disable LCD and DMA engines when suspending + * spi_s3c24xx: fix section warning + * rescan_partitions(): make device capacity errors non-fatal + * memstick: fix MSProHG 8-bit interface mode support + * Add Uwe Kleine-König to .mailmap + * xen: fix for xen guest with mem > 3.7G + * x86/paravirt: Remove duplicate paravirt_pagetable_setup_{start, done}() + * crypto: talitos - Avoid consecutive packets going out with same IV + * slub: fixed uninitialized counter in struct kmem_cache_node + * udp: Fix rcv socket locking + * IB/mlx4: Fix up fast register page list format + * [MIPS] VR41xx: unsigned irq cannot be negative + * x86: completely disable NOPL on 32 bits + * [S390] cio: Fix driver_data handling for ccwgroup devices. + * [S390] cio: fix orb initialization in cio_start_key + * sparc64: Fix OOPS in psycho_pcierr_intr_other(). + * sparc64: Fix SMP bootup with CONFIG_STACK_DEBUG or ftrace. + * RDMA/nes: Fix client side QP destroy + * IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop() + * clockevents: make device shutdown robust + * powerpc: Fix interrupt values for DMA2 in MPC8610 HPCD device tree + * hpplus: fix build regression + * Fix PNP build failure, bugzilla #11276 + * warn: Turn the netdev timeout WARN_ON() into a WARN() + * [XFS] Move memory allocations for log tracing out of the critical path + * [XFS] Fix regression introduced by remount fixup + * [XFS] Prevent direct I/O from mapping extents beyond eof + * [XFS] Fix barrier status change detection. + * [XFS] Prevent lockdep false positives when locking two inodes. + * [XFS] Fix use-after-free with buffers + * [XFS] Don't do I/O beyond eof when unreserving space + * powerpc: Holly board needs dtbImage target + * Fix compile failure with non modular builds + * [ARM] 5249/1: davinci: remove redundant check in davinci_psc_config() + * [ARM] omap: back out 'internal_clock' support + * sctp: set the skb->ip_summed correctly when sending over loopback. + * [ARM] 5255/1: Update jornada ssp to remove build errors/warnings + * sctp: do not enable peer features if we can't do them. + * sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH + * bnx2: Promote vector field in bnx2_irq structure from u16 to unsigned + int + * forcedeth: call restore mac addr in nv_shutdown path + * e1000: prevent corruption of EEPROM/NVM + * e100: Use pci_pme_active to clear PME_Status and disable PME# + * md: Don't wait UNINTERRUPTIBLE for other resync to finish + * atstk1000: fix build breakage with BOARD_ATSTK100X_SW2_CUSTOM=y + * avr32: add .gitignore files + * avr32: add generic_find_next_le_bit bit function + * avr32: fix sys_sync_file_range() call convention + * avr32: nmi_enter() without nmi_exit() + * KVM: ia64: 'struct fdesc' build fix + * hwmon: (atxp1) Fix device detection logic + * hwmon: (it87) Fix fan tachometer reading in IT8712F rev 0x7 (I) + * hwmon: (ad7414) Make ad7414_update_device() static + * tmio_mmc: fix compilation with debug enabled + * atmel-mci: debugfs: enable clock before dumping regs + * atmel-mci: Fix memory leak in atmci_regs_show + * atmel-mci: Fix bogus debugfs file size + * atmel-mci: Set MMC_CAP_NEEDS_POLL if no detect_pin + * mmc_block: handle error from mmc_register_driver() + * mmc_test: initialize mmc_test_lock statically + * [MIPS] Fix 64-bit IP checksum code + * [MIPS] SMTC: Clear TIF_FPUBOUND on clone / fork. + * [MIPS] Fix potential latency problem due to non-atomic cpu_wait. + * [MIPS] vmlinux.lds.S: handle .text.* + * MAINTAINERS: Trivial whitespace cleanups + * MAINTAINERS: Various fixes + * Linux 2.6.27-rc7 + + -- Tim Gardner Sun, 21 Sep 2008 21:49:28 -0600 + +linux (2.6.27-3.4) intrepid; urgency=low + + [ Colin Ian King ] + + * SAUCE: fix kernel oops in VirtualBox during paravirt patching + - LP: #246067 + * SAUCE: qc-usb: Enable Logitech QuickCam Messenger + - LP: #209901 + * SAUCE: appleir: Enable driver for new MacBook Pro + - LP: #157919 + + [ Tim Gardner ] + + * Enabled CONFIG_DEBUG_RODATA=y + + [ Upstream Kernel Changes ] + + * Revert "ALSA: hda - Added model selection for iMac 24"" + * Revert "x86: fix HPET regression in 2.6.26 versus 2.6.25, check hpet + against BAR, v3" + * Revert "[ARM] use the new byteorder headers" + * Revert "mac80211: Use IWEVASSOCREQIE instead of IWEVCUSTOM" + * Revert "crypto: camellia - Use kernel-provided bitops, unaligned access + helpers" + * svcrdma: Fix race between svc_rdma_recvfrom thread and the dto_tasklet + * sched, cpuset: rework sched domains and CPU hotplug handling (v4) + * ACPI: Fix now signed module parameter. + * ACPI: Change package length error to warning + * ACPI: Fix now signed module parameter. + * ACPI: Fix typo in "Disable MWAIT via DMI on broken Compal board" + * acpi: add checking for NULL early param + * UBIFS: fix zero-length truncations + * Input: bcm5974 - add maintainer entry + * sh64: re-add the __strnlen_user() prototype + * sh: fix ptrace_64.c:user_disable_single_step() + * PNPACPI: ignore the producer/consumer bit for extended IRQ descriptors + * UBIFS: always read hashed-key nodes under TNC mutex + * UBIFS: allow for racing between GC and TNC + * [CIFS] Fix plaintext authentication + * sparc32: Implement smp_call_function_single(). + * sh: crash kernel resource fix + * sh: fix kexec entry point for crash kernels + * sh: fix platform_resource_setup_memory() section mismatch + * sh: update Migo-R defconfig + * sh: update AP325RXA defconfig + * sh: fix semtimedop syscall + * cifs: fix O_APPEND on directio mounts + * [CIFS] update cifs change log + * [CIFS] Turn off Unicode during session establishment for plaintext + authentication + * ACPI: thinkpad-acpi: wan radio control is not experimental + * sparc: Fix resource flags for PCI children in OF device tree. + * remove blk_register_filter and blk_unregister_filter in gendisk + * ALSA: oxygen: fix distorted output on AK4396-based cards + * ipv6: When we droped a packet, we should return NET_RX_DROP instead of + 0 + * pkt_sched: Fix locking of qdisc_root with qdisc_root_sleeping_lock() + * net: Unbreak userspace usage of linux/mroute.h + * Don't trigger softlockup detector on network fs blocked tasks + * Resource handling: add 'insert_resource_expand_to_fit()' function + * sparc64: setup_valid_addr_bitmap_from_pavail() should be __init + * UBIFS: do not update min_idx_lebs in stafs + * UBIFS: push empty flash hack down + * UBIFS: remove incorrect index space check + * UBIFS: improve statfs reporting + * UBIFS: fix assertion + * UBIFS: add forgotten gc_idx_lebs component + * UBIFS: introduce LEB overhead + * UBIFS: improve statfs reporting even more + * UBIFS: fill f_fsid + * drm/radeon: downgrade debug message from info to debug. + * Remove invalidate_partition call from do_md_stop. + * Fix problem with waiting while holding rcu read lock in md/bitmap.c + * ALSA: hda: Distortion fix for dell_m6_core_init + * ALSA: ASoC: fix pxa2xx-i2s clk_get call + * block: restore original behavior of /proc/partition when there's no + partition + * debugobjects: fix lockdep warning + * avr32: Fix lockup after Java stack underflow in user mode + * avr32: pm_standby low-power ram bug fix + * nfsd: fix compound state allocation error handling + * sunrpc: fix possible overrun on read of /proc/sys/sunrpc/transports + * nfsd: fix buffer overrun decoding NFSv4 acl + * audit: Moved variable declaration to beginning of function + * Fix modules_install on RO nfs-exported trees. + * Remove '#include ' from mm/page_isolation.c + * dabusb_fpga_download(): fix a memory leak + * [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl() + * ALSA: hda - Fix ALC663 auto-probe + * ALSA: hda - Add mic-boost controls to ALC662/663 auto configuration + * Un-break printk strings in x86 PCI probing code + * kernel/resource.c: fix new kernel-doc warning + * softlockup: minor cleanup, don't check task->state twice + * fix typo in arch/parisc/hpux/fs.c + * m68k: atari_keyb_init operator precedence fix + * ACPI: Fix typo in "Disable MWAIT via DMI on broken Compal board" + * don't diff generated firmware files + * IDE: compile fix for sff_dma_ops + * IDE: palm_bk3710: fix compile warning for unused variable + * ide: fix hwif_to_node() + * palm_bk3710: improve IDE registration + * ide-disk: remove stale init_idedisk_capacity() documentation + * ide/Kconfig: mark ide-scsi as deprecated + * net/wireless/Kconfig: clarify the description for + CONFIG_WIRELESS_EXT_SYSFS + * iwlwifi: do not use GFP_DMA in iwl_tx_queue_init + * iwlwifi: workaround interrupt handling no some platforms + * iwlwifi: fix apm_stop (wrong bit polarity for FLAG_INIT_DONE) + * iwlwifi: fix 64bit platform firmware loading + * orinoco: Multicast to the specified addresses + * wireless/libertas/if_cs.c: fix memory leaks + * mac80211: Fix debugfs union misuse and pointer corruption + * rt2x00: Compiler warning unmasked by fix of BUILD_BUG_ON + * ath9k: Incorrect key used when group and pairwise ciphers are + different. + * ath9: Fix ath_rx_flush_tid() for IRQs disabled kernel warning message. + * net/xfrm: Use an IS_ERR test rather than a NULL test + * ipv: Re-enable IP when MTU > 68 + * NTFS: update homepage + * mm: make setup_zone_migrate_reserve() aware of overlapping nodes + * VFS: fix dio write returning EIO when try_to_release_page fails + * acer-wmi: remove debugfs entries upon unloading + * mm/bootmem: silence section mismatch warning - + contig_page_data/bootmem_node_data + * MAINTAINERS: add a maintainer for the BCM5974 multitouch driver + * 8250: improve workaround for UARTs that don't re-assert THRE correctly + * mmc: at91_mci: don't use coherent dma buffers + * pid_ns: zap_pid_ns_processes: fix the ->child_reaper changing + * pid_ns: (BUG 11391) change ->child_reaper when init->group_leader exits + * cirrusfb: check_par fixes + * devcgroup: fix race against rmdir() + * mm: show quicklist usage in /proc/meminfo + * mm: size of quicklists shouldn't be proportional to the number of CPUs + * ipc: document the new auto_msgmni proc file + * hp-wmi: update to match current rfkill semantics + * hp-wmi: add proper hotkey support + * tdfxfb: fix SDRAM memory size detection + * tdfxfb: fix frame buffer name overrun + * rtc_time_to_tm: fix signed/unsigned arithmetic + * ibft: fix target info parsing in ibft module + * sysfs: document files in /sys/firmware/sgi_uv/ + * rtc-cmos: wake again from S5 + * pm_qos_requirement might sleep + * drivers/char/random.c: fix a race which can lead to a bogus BUG() + * ipsec: Fix deadlock in xfrm_state management. + * [x86] Fix TSC calibration issues + * tipc: Don't use structure names which easily globally conflict. + * sparc64: Fix IPI call locking. + * [ARM] omap: fix gpio.c build error + * sparc64: Prevent sparc64 from invoking irq handlers on offline CPUs + * powerpc: Fix uninitialised variable in VSX alignment code + * powerpc: Only make kernel text pages of linear mapping executable + * powerpc: Make sure _etext is after all kernel text + * powerpc: Work around gcc's -fno-omit-frame-pointer bug + * powerpc: Fix build error with 64K pages and !hugetlbfs + * powerpc: Fix for getting CPU number in power_save_ppc32_restore() + * UBIFS: amend f_fsid + * net/usb/pegasus: avoid hundreds of diagnostics + * ixgbe: initialize interrupt throttle rate + * pcnet-cs, axnet_cs: add new IDs, remove dup ID with less info + * netxen: Remove workaround for chipset quirk + * Split up PIT part of TSC calibration from native_calibrate_tsc + * iwlwifi: W/A for the TSF correction in IBSS + * iwlwifi: fix hidden ssid discovery in passive channels + * iwlwifi: remove false rxon if rx chain changes + * iwlwifi: fix station mimo power save values + * iwlwifi: fix rx_chain computation + * iwlwifi: fix Tx cmd memory allocation failure handling + * iwlwifi: call apm stop on exit + * iwlwifi: fix STATUS_EXIT_PENDING is not set on pci_remove + * ath9k: Fix TX status reporting + * ath9k: Fix TX control flag use for no ACK and RTS/CTS + * V4L/DVB (8555): au8522: add mechanism to configure IF frequency for vsb + and qam + * V4L/DVB (8556): au0828: add support for Hauppauge Woodbury + * V4L/DVB (8598): au8522: clean up function au8522_set_if + * V4L/DVB (8599): au8522: remove if frequency settings from vsb/qam + modulation tables + * V4L/DVB (8600): au0828: explicitly set 6 MHz IF frequency in + hauppauge_hvr950q_config + * V4L/DVB (8629): v4l2-ioctl: do not try to handle private V4L1 ioctls + * V4L/DVB (8633): ivtv: update ivtv version number + * V4L/DVB (8648): ivtv: improve CC support + * V4L/DVB (8660): gspca: Simplify the scan of URB packets in pac7311. + * V4L/DVB (8661): gspca: Bug in the previous changeset about pac7311. + * V4L/DVB (8663): gspca: Webcam 0c45:6128 added in sonixj. + * V4L/DVB (8664): gspca: The bridge/sensor of the webcam 093a:2621 is a + PAC 7302. + * V4L/DVB (8665): gspca: Fix the 640x480 resolution of the webcam + 093a:2621. + * V4L/DVB (8666): gspca: Bad scanning of frames in pac7311. + * V4L/DVB (8667): gspca: Bad probe of Z-Star/Vimicro webcams with pas106 + sensor. + * V4L/DVB (8668): gspca: Conflict GSPCA / ET61X251 for the webcam + 102c:6251. + * V4L/DVB (8669): gspca: Add white balance control for spca561 rev 012A. + * V4L/DVB (8671): gspca: Remove the unused field 'dev_name' of the device + structure. + * V4L/DVB (8672): gspca: Big rewrite of spca561. + * V4L/DVB (8673): gspca: Bad frame scanning again and bad init in + pac7311. + * V4L/DVB (8674): gspca: Webcam 0c45:612e added in sonixj. + * V4L/DVB (8675): gspca: Pixmap PJPG (Pixart 73xx JPEG) added, generated + by pac7311. + * V4L/DVB (8678): Remove the dead CONFIG_RADIO_MIROPCM20{,_RDS} code + * V4L/DVB (8681): v4l2-ioctl.c: fix warning + * V4L/DVB (8682): V4L: fix return value of register video func + * V4L/DVB (8701): cx18: Add missing lock for when the irq handler + manipulates the queues + * V4L/DVB (8703): gspca: Do controls work for spca561 revision 12a. + * V4L/DVB (8705): gspca: Adjust some control limits in spca561. + * V4L/DVB (8706): Make contrast and brightness work for pac7302. + * V4L/DVB (8707): gspca: Colors, hflip and vflip controls added for + pac7302. + * V4L/DVB (8709): gspca: Fix initialization and controls of sn9x110 - + ov7630. + * V4L/DVB (8710): gspca: Bad color control in sonixj. + * V4L/DVB (8711): gspca: Bad controls and quantization table of pac7311. + * V4L/DVB (8712): gspca: Bad start of sonixj webcams since changeset + a8779025e7e8. + * V4L/DVB (8713): gspca: Bad color control again in sonixj. + * V4L/DVB (8714): gspca: Bad start of sn9c110 and sensor om6802. + * V4L/DVB (8715): gspca: Change the name of some webcam in the gspca doc. + * V4L/DVB (8716): gspca: Bad start of sn9c110 and sensor ov7630. + * V4L/DVB (8717): gspca: Frame buffer too small for small resolutions + (sonixj and t613). + * V4L/DVB (8718): gspca: suspend/resume added. + * V4L/DVB (8719): gspca: Have VIDIOC_QUERYCTRL more compliant to the + spec. + * V4L/DVB (8720): gspca: V4L2_CAP_SENSOR_UPSIDE_DOWN added as a cap for + some webcams. + * V4L/DVB (8722): sms1xxx: fix typo in license header + * V4L/DVB (8726): link tuner before saa7134 + * V4L/DVB (8727): V4L1: make PMS not autoprobe when builtin. + * V4L/DVB (8728): 1-make-pms-not-autoprobe-when-builtin update + * V4L/DVB (8749): Fix error code, when camera is not turned on by sonypi + * V4L/DVB (8750): V4L: check inval in video_register_device_index() + * V4L/DVB (8751): vivi: Fix some issues at vivi register routine + * V4L/DVB (8757): v4l-dvb: fix a bunch of sparse warnings + * V4L/DVB (8769): cx18: Simplify queue flush logic to prevent oops in + cx18_flush_queues() + * V4L/DVB (8778): radio: fix incorrect video_register_device result check + * V4L/DVB (8779): v4l: fix more incorrect video_register_device result + checks + * V4L/DVB (8790): saa7115: call i2c_set_clientdata only when state != + NULL + * V4L/DVB (8803): s5h1409: Enable QAM_AUTO mode + * V4L/DVB (8804): s5h1411: Enable QAM_AUTO mode + * V4L/DVB (8805): Steven Toth email address change + * V4L/DVB (8809): gspca: Revert commit + 9a9335776548d01525141c6e8f0c12e86bbde982 + * V4L/DVB (8810): gspca: Compile error when CONFIG_PM not defined. + * V4L/DVB (8812): gspca: Do pac73xx webcams work. + * V4L/DVB (8813): gspca: Adjust SOF detection for pac73xx. + * V4L/DVB (8814): gspca: Set DISABLED the disabled controls at query + control time. + * V4L/DVB (8815): gspca: Fix problems with disabled controls. + * V4L/DVB (8816): gspca: Set disabled ctrls and fix a register pb with + ovxxxx in sonixb. + * V4L/DVB (8817): gspca: LED and proble changes in sonixb. + * V4L/DVB (8818): gspca: Reinitialize the device on resume. + * V4L/DVB (8819): gspca: Initialize the ov519 at open time and source + cleanup. + * V4L/DVB (8820): gspca: Change initialization and gamma of zc3xx - + pas106. + * V4L/DVB (8822): gspca: Change some subdriver functions for + suspend/resume. + * V4L/DVB (8823): gspca: H and V flips work for ov7670 only in ov519. + * V4L/DVB (8824): gspca: Too much code removed in the suspend/resume + changeset. + * V4L/DVB (8825): gspca: More controls for pac73xx and new webcam + 093a:2624. + * V4L/DVB (8826): gspca: Webcam Labtec 2200 (093a:2626) added in pac7311. + * V4L/DVB (8827): gspca: Stop pac7302 autogain oscillation. + * V4L/DVB (8828): gspca: Set the clock at the end of initialization in + sonixj. + * V4L/DVB (8829): gspca: Have a clean kmalloc-ated buffer for USB + exchanges. + * V4L/DVB (8830): gspca: Move some probe code to the new init function. + * V4L/DVB (8831): gspca: Resolve webcam conflicts between some drivers. + * V4L/DVB (8832): gspca: Bad pixelformat of vc0321 webcams. + * V4L/DVB (8833): gspca: Cleanup the sonixb code. + * V4L/DVB (8834): gspca: Have a bigger buffer for sn9c10x compressed + images. + * V4L/DVB (8835): gspca: Same pixfmt as the sn9c102 driver and raw Bayer + added in sonixb. + * V4L/DVB (8837): dvb: fix I2C adapters name size + * V4L/DVB (8839): dib0700: add comment to identify 35th USB id pair + * V4L/DVB (8840): dib0700: add basic support for Hauppauge Nova-TD-500 + (84xxx) + * V4L/DVB (8842): vivi_release(): fix use-after-free + * V4L/DVB (8843): tda10048_firmware_upload(): fix a memory leak + * V4L/DVB (8844): dabusb_fpga_download(): fix a memory leak + * bnx2x: Accessing un-mapped page + * SELinux: memory leak in security_context_to_sid_core + * x86: add io delay quirk for Presario F700 + * mmap: fix petty bug in anonymous shared mmap offset handling + * x86: Change warning message in TSC calibration. + * PCI: fix pbus_size_mem() resource alignment for CardBus controllers + * [ARM] omap: fix build error in ohci-omap.c + * [ARM] remove unused #include + * ACPI: Make Len Brown the ACPI maintainer again + * fujitsu-laptop: fix regression for P8010 in 2.6.27-rc + * ACPI: Avoid bogus timeout about SMbus check + * acer-wmi: remove debugfs entries upon unloading + * forgotten refcount on sysctl root table + * V4L/DVB (8868): gspca: Support for vga modes with sif sensors in + sonixb. + * V4L/DVB (8869): gspca: Move the Sonix webcams with TAS5110C1B from + sn9c102 to gspca. + * V4L/DVB (8870): gspca: Fix dark room problem with sonixb. + * V4L/DVB (8872): gspca: Bad image format and offset with rev072a of + spca561. + * V4L/DVB (8873): gspca: Bad image offset with rev012a of spca561 and + adjust exposure. + * V4L/DVB (8874): gspca: Adjust hstart for sn9c103/ov7630 and update + usb-id's. + * [ARM] omap: fix virtual vs physical address space confusions + * V4L/DVB (8876): budget: udelay changed to mdelay + * V4L/DVB (8877): b2c2 and bt8xx: udelay to mdelay + * V4L/DVB (8880): PATCH: Fix parents on some webcam drivers + * V4L/DVB (8881): gspca: After 'while (retry--) {...}', retry will be -1 + but not 0. + * powerpc/spufs: Fix multiple get_spu_context() + * powerpc/spufs: Fix race for a free SPU + * Input: bcm5974 - small formatting cleanup + * Input: bcm5974 - improve finger tracking and counting + * Input: bcm5974 - add BTN_TOUCH event for mousedev benefit + * Input: i8042 - make Lenovo 3000 N100 blacklist entry more specific + * sh: resume_kernel fix for kernel oops built with CONFIG_BKL_PREEMPT=y. + * sh64: resume_kernel fix for kernel oops built with + CONFIG_BKL_PREEMPT=y. + * i2c: fix i2c-sh_mobile timing issues + * clockevents: prevent clockevent event_handler ending up handler_noop + * clockevents: prevent endless loop in periodic broadcast handler + * clockevents: enforce reprogram in oneshot setup + * clockevents: prevent multiple init/shutdown + * clockevents: prevent endless loop lockup + * HPET: make minimum reprogramming delta useful + * [MTD] [NAND] tmio_nand: fix base address programming + * Fix conditional export of kvh.h and a.out.h to userspace. + * async_tx: fix the bug in async_tx_run_dependencies + * sched_clock: fix NOHZ interaction + * sched: fix process time monotonicity + * UBIFS: fix division by zero + * UBIFS: make minimum fanout 3 + * [MIPS] Fix data bus error recovery + * [MIPS] Fix WARNING: at kernel/smp.c:290 + * [MIPS] TXx9: Fix txx9_pcode initialization + * [MIPS] TX39xx: Add missing local_flush_icache_range initialization + * [MIPS] Probe initrd header only if explicitly specified + * res_counter: fix off-by-one bug in setting limit + * forcedeth: fix kexec regression + * atmel_lcdfb: fix oops in rmmod when framebuffer fails to register + * tracehook: comment pasto fixes + * drivers/mmc/card/block.c: fix refcount leak in mmc_block_open() + * x86: boot: stub out unimplemented CPU feature words + * x86: add NOPL as a synthetic CPU feature bit + * x86: use X86_FEATURE_NOPL in alternatives + * clockevents: broadcast fixup possible waiters + * x86: HPET fix moronic 32/64bit thinko + * x86: HPET: read back compare register before reading counter + * Fix CONFIG_AC97_BUS dependency + * [ARM] 5241/1: provide ioremap_wc() + * ntp: fix calculation of the next jiffie to trigger RTC sync + * clocksource, acpi_pm.c: use proper read function also in errata mode + * clocksource, acpi_pm.c: check for monotonicity + * x86: delay early cpu initialization until cpuid is done + * x86: move mtrr cpu cap setting early in early_init_xxxx + * sched: arch_reinit_sched_domains() must destroy domains to force + rebuild + * x86, xen: Use native_pte_flags instead of native_pte_val for .pte_flags + * x86: pda_init(): fix memory leak when using CPU hotplug + * x86: cpu_init(): fix memory leak when using CPU hotplug + * powerpc/spufs: Fix possible scheduling of a context to multiple SPEs + * netfilter: nf_conntrack_sip: de-static helper pointers + * netfilter: nf_conntrack_gre: more locking around keymap list + * netfilter: nf_conntrack_gre: nf_ct_gre_keymap_flush() fixlet + * netfilter: nf_conntrack_irc: make sure string is terminated before + calling simple_strtoul + * pkt_sched: Fix qdisc state in net_tx_action() + * powerpc: Fix rare boot build breakage + * ahci, pata_marvell: play nicely together + * sata_mv: add RocketRaid 1720 PCI ID to driver + * ahci: disable PMP for marvell ahcis + * sata_nv: disable hardreset for generic + * libata-sff: kill spurious WARN_ON() in ata_hsm_move() + * pata_sil680: remove duplicate pcim_enable_device + * ahci: RAID mode SATA patch for Intel Ibex Peak DeviceIDs + * [MIPS] IP22: Fix detection of second HPC3 on Challenge S + * xen: fix 2.6.27-rc5 xen balloon driver warnings + * x86: disable static NOPLs on 32 bits + * netns : fix kernel panic in timewait socket destruction + * bridge: don't allow setting hello time to zero + * NFS: Restore missing hunk in NFS mount option parser + * usb: fix null deferences in low level usb serial + * Fix format of MAINTAINERS + * sparc64: Disable timer interrupts in fixup_irqs(). + * [Bluetooth] Fix reference counting during ACL config stage + * [Bluetooth] Enforce correct authentication requirements + * [Bluetooth] Reject L2CAP connections on an insecure ACL link + * [S390] CVE-2008-1514: prevent ptrace padding area read/write in 31-bit + mode + * [S390] cio: Correct cleanup on error. + * [S390] cio: handle ssch() return codes correctly. + * [S390] cio: allow offline processing for disconnected devices + * ipsec: Restore larval states and socket policies in dump + * update Documentation/filesystems/Locking for 2.6.27 changes + * MAINTAINERS: add Atheros maintainer for atlx + * lib: Correct printk %pF to work on all architectures + * x86: fix memmap=exactmap boot argument + * clockevents: remove WARN_ON which was used to gather information + * ipv6: Fix OOPS in ip6_dst_lookup_tail(). + * Linux 2.6.27-rc6 + + -- Ben Collins Tue, 02 Sep 2008 12:45:56 -0400 + +linux (2.6.27-2.3) intrepid; urgency=low + + [ Ben Collins ] + + * build/retag: Make script save .orig of tags for later use + * ubuntu/lirc: Fix device_create call + * build/firmware: Put in-kernel firmware into version specific subdir + - LP: #262115 + * Rebase on linux-2.6 git. + * ABI bump + + [ Herton Ronaldo Krzesinski ] + + * SAUCE: (no-up) Apparmor warning fixes + + [ John Johansen ] + + * SAUCE: (no-up) Proper AppArmor ptrace updates for newer lsm API + + [ Mackenzie Morgan ] + + * SAUCE: Add quirk for ASUS Z37E to make sound audible after resume + - LP: #25896 + + -- Ben Collins Wed, 27 Aug 2008 14:03:05 -0400 + +linux (2.6.27-1.2) intrepid; urgency=low + + [ Amit Kucheria ] + + * SAUCE: make fc transport removal of target configurable + * SAUCE: pm: Config option to disable handling of console during + suspend/resume + + [ Ben Collins ] + + * SAUCE: Lower warning level of some PCI messages + * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps + * SAUCE: tulip: Let dmfe handle davicom on non-sparc + * SAUCE: tulip: Define ULI PCI ID's + * SAUCE: (no-up) version: Implement version_signature proc file. + * SAUCE: (no-up) connector.h: Add idx/val for drbd + * SAUCE: (no-up) swap: Add notify_swap_entry_free callback for compcache + * SAUCE: drivers: Remove some duplicate device entries in various modules + * SAUCE: (no-up) [AppArmor] merge with upstream subversion r1291 + * SAUCE: apparmor: Update for changes to ptrace lsm hooks + * SAUCE: (no-up) Enable ubuntu extra subdirectory + * SAUCE: applesmc: Add MacBookAir + * SAUCE: (no-up) ACPI: initramfs DSDT override support + * ubuntu: Add drbd module + * ubuntu: Add iscsitarget module + * ubuntu: Add BOM for iscsitarget + * ubuntu: Add squashfs driver + * SAUCE: (no-up) Check for squashfs superblock in initramfs mounting. + * ubuntu: Add aufs module + * ubuntu: Added atl2 driver + * ubuntu: Added et131x driver + * ubuntu: Add dm-raid4-5 driver + * ubuntu: Add ndiswrapper driver + * ubuntu: Added ram backed compressed swap module (compcache) + * ubuntu: Add misc drivers from hardy lum + * ubuntu: Add heci driver 3.2.0.24 + * ubuntu: Add ov511 and bt-sco drivers + * ubuntu: Add acx, prism2_usb wireless drivers + * ubuntu: Add at76 driver to build + * ubuntu: Add fsam7400 sw kill switch driver + * ubuntu: Added qc-usb driver + * ubuntu: e1000e: Upgraded module to 0.4.1.7 + * ubuntu: Added rfkill drivers + * ubuntu: VIA - Add VIA DRM Chrome9 3D engine + * ubuntu: unionfs: Added v1.4 module from hardy + * ubuntu: Add LIRC driver + * ubuntu: Add GFS driver + * ubuntu: New tlsup driver for toshiba laptops + * Update config files + * build/d-i: Remove obsolete dm modules + + [ Chuck Short ] + + * SAUCE: ata: blacklist FUJITSU MHW2160BH PL + + [ Colin Ian King ] + + * ubuntu: Add dm-loop + * SAUCE: Enable speedstep for sonoma processors. + + [ Dennis Noordsij ] + + * SAUCE: Work around ACPI corruption upon suspend on some Dell machines. + + [ Fabio M. Di Nitto ] + + * SAUCE: Export gfs2 symbols required for gfs1 kernel module + + [ Matthew Garrett ] + + * SAUCE: hostap: send events on data interface as well as master + interface + + [ Michael Frey (Senior Manager, MID ] + + * SAUCE: Send HCI_RESET for Broadcomm 2046 + + [ Phillip Lougher ] + + * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets. + + [ Stefan Bader ] + + * SAUCE: (no-up) Export dm_disk function of device-mapper + * SAUCE: Restore VT fonts on switch + * SAUCE: mmc: Increase power_up deleay to fix TI readers + + [ Tim Gardner ] + + * SAUCE: Add extra headers to linux-libc-dev + * SAUCE: Catch nonsense keycodes and silently ignore + * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM + * SAUCE: Guest OS does not recognize a lun with non zero target id on + Vmware ESX Server + * SAUCE: (no-up) Take care of orinoco_cs overlap with hostap_cs + * ubuntu: Add GNBD driver + + -- Ben Collins Sat, 23 Aug 2008 15:48:35 -0400 + +linux (2.6.27-0.0) intrepid; urgency=low + + * Not uploaded, placeholder for new release + + -- Ben Collins Sat, 23 Aug 2008 15:48:35 -0400 + +linux (2.6.26-5.17) intrepid; urgency=low + + [ Ben Collins ] + + * build/abi: Add tosh_smm symbol to blacklist + + -- Ben Collins Fri, 15 Aug 2008 09:29:34 -0400 + +linux (2.6.26-5.16) intrepid; urgency=low + + [ Ben Collins ] + + * Revert "SAUCE: toshiba_acpi: Rewrote most of the proc entry bits." + * Revert "SAUCE: Update toshiba_acpi.c to version 0.19a" + * build/config: Disable in-kernel toshiba driver(s) + * ubuntu/tlsup: New driver for toshiba laptops + * build/config: Enable TLSUP driver + * SAUCE: e1000e: Fix E1000E_ENABLED logic to check for our E1000E_NEW + driver as well + * ubuntu/e1000e: Remove E1000E_ENABLED option in local config + * build/config: Update configs to have E1000E_ENABLED set + * ubuntu/prism2: Remove duplicate device + + [ Fabio M. Di Nitto ] + + * SAUCE: Export gfs2 symbols required for gfs1 kernel module + + [ Stefan Bader ] + + * SAUCE: x86: HPET rework for SB700 + - LP: #255910 + + [ Tim Gardner ] + + * Add GNBD driver + * Enable GNBD driver + * SAUCE: Add GFS driver + * SAUCE: Enable gfs driver configs + * b43: Linksys WMP54G (BCM4306/3) card in a PCI format has an SPROM + coding + + [ Upstream Kernel Changes ] + + * KVM: x86 emulator: emulate clflush + * USB: quirk PLL power down mode + + -- Ben Collins Mon, 11 Aug 2008 13:19:28 -0400 + +linux (2.6.26-5.15) intrepid; urgency=low + + [ Ben Collins ] + + * Revert "SAUCE: Add blacklist support to fix Belkin bluetooth dongle." + - Superceded by upstream changes. + * build/config: New option enabled for uvcvideo + * build/control: Add Vcs-Git meta data to control file + * SAUCE: toshiba_acpi: Rewrote most of the new code + * abi/perm-blacklist: Add emu10k1 driver to blacklist + + [ Upstream Kernel Changes ] + + * pxamci: trivial fix of DMA alignment register bit clearing + * udplite: Protection against coverage value wrap-around + * ipv6: use timer pending + * ipv6: __KERNEL__ ifdef struct ipv6_devconf + * hdlcdrv: Fix CRC calculation. + * quota: fix possible infinite loop in quota code + * isofs: fix minor filesystem corruption + * KVM: VMX: Fix a wrong usage of vmcs_config + * KVM: SVM: fix suspend/resume support + * KVM: mmu_shrink: kvm_mmu_zap_page requires slots_lock to be held + * KVM: VMX: Add ept_sync_context in flush_tlb + * KVM: x86 emulator: Fix HLT instruction + * KVM: MMU: nuke shadowed pgtable pages and ptes on memslot destruction + * KVM: MMU: Fix potential race setting upper shadow ptes on nonpae hosts + * Patch Upstream: x86 ptrace: fix PTRACE_GETFPXREGS error + * rcu: fix rcu_try_flip_waitack_needed() to prevent grace-period stall + * Fix typos from signal_32/64.h merge + * x86 reboot quirks: add Dell Precision WorkStation T5400 + * USB: fix usb serial pm counter decrement for disconnected interfaces + * x86, suspend, acpi: enter Big Real Mode + * markers: fix duplicate modpost entry + * Fix build on COMPAT platforms when CONFIG_EPOLL is disabled + * proc: fix /proc/*/pagemap some more + * cpusets: fix wrong domain attr updates + * x86: fix crash due to missing debugctlmsr on AMD K6-3 + * ide-cd: fix oops when using growisofs + * rtc-at91rm9200: avoid spurious irqs + * vmlinux.lds: move __attribute__((__cold__)) functions back into final + .text section + * ARM: fix fls() for 64-bit arguments + * tcp: Clear probes_out more aggressively in tcp_ack(). + * sparc64: Fix lockdep issues in LDC protocol layer. + * sparc64: Fix cpufreq notifier registry. + * sparc64: Do not define BIO_VMERGE_BOUNDARY. + * iop-adma: fix platform driver hotplug/coldplug + * myri10ge: do not forget to setup the single slice pointers + * myri10ge: do not use mgp->max_intr_slots before loading the firmware + * ALSA: trident - pause s/pdif output + * V4L: cx18: Upgrade to newer firmware & update documentation + * DVB: dib0700: add support for Hauppauge Nova-TD Stick 52009 + * V4L: uvcvideo: Fix a buffer overflow in format descriptor parsing + * V4L: uvcvideo: Use GFP_NOIO when allocating memory during resume + * V4L: uvcvideo: Don't free URB buffers on suspend + * V4L: uvcvideo: Make input device support optional + * V4L: uvcvideo: Add support for Medion Akoya Mini E1210 integrated + webcam + * V4L: saa7134: Copy tuner data earlier to avoid overwriting manual tuner + type + * V4L: cx23885: Bugfix for concurrent use of /dev/video0 and /dev/video1 + * DVB: cx23885: Ensure PAD_CTRL is always reset to a sensible default + * DVB: cx23885: DVB Transport cards using DVB port VIDB/TS1 did not + stream + * DVB: cx23885: Reallocated the sram to avoid concurrent VIDB/C issues + * DVB: cx23885: SRAM changes for the 885 and 887 silicon parts + * x86: fix kernel_physical_mapping_init() for large x86 systems + * eCryptfs: use page_alloc not kmalloc to get a page of memory + * UML - Fix boot crash + * ixgbe: remove device ID for unsupported device + * mpc52xx_psc_spi: fix block transfer + * tmpfs: fix kernel BUG in shmem_delete_inode + * markers: fix markers read barrier for multiple probes + * VFS: increase pseudo-filesystem block size to PAGE_SIZE + * cpufreq acpi: only call _PPC after cpufreq ACPI init funcs got called + already + * b43legacy: Release mutex in error handling code + * ath5k: don't enable MSI, we cannot handle it yet + * Fix off-by-one error in iov_iter_advance() + * Linux 2.6.26.1 + * ftrace: remove unneeded documentation + * romfs_readpage: don't report errors for pages beyond i_size + * netfilter: nf_nat_sip: c= is optional for session + * SCSI: bsg: fix bsg_mutex hang with device removal + * x86: idle process - add checking for NULL early param + * x86: io delay - add checking for NULL early param + * Close race in md_probe + * Kprobe smoke test lockdep warning + * netfilter: xt_time: fix time's time_mt()'s use of do_div() + * linear: correct disk numbering error check + * SCSI: ch: fix ch_remove oops + * NFS: Ensure we zap only the access and acl caches when setting new acls + * jbd: fix race between free buffer and commit transaction + * Input: i8042 - add Intel D845PESV to nopnp list + * Input: i8042 - add Gericom Bellagio to nomux blacklist + * Input: i8042 - add Acer Aspire 1360 to nomux blacklist + * Bluetooth: Signal user-space for HIDP and BNEP socket errors + * Add compat handler for PTRACE_GETSIGINFO + * ALSA: hda - Fix wrong volumes in AD1988 auto-probe mode + * ALSA: hda - Fix DMA position inaccuracy + * ALSA: hda - Add missing Thinkpad Z60m support + * ALSA: emu10k1 - Fix inverted Analog/Digital mixer switch on Audigy2 + * vfs: fix lookup on deleted directory + * Ath5k: fix memory corruption + * Ath5k: kill tasklets on shutdown + * sound: ensure device number is valid in snd_seq_oss_synth_make_info + * Linux 2.6.26.2 + + -- Ben Collins Sun, 03 Aug 2008 13:25:02 -0400 + +linux (2.6.26-5.14) intrepid; urgency=low + + [ Ben Collins ] + + * SAUCE: applesmc: Add MacBookAir + * build: Do not build ddeb unless we are on the buildd + * build: control: Consistency in arch fields. + * SAUCE: Update toshiba_acpi.c to version 0.19a + - LP: #77026 + * build: Added perm blacklist support and per-module support to abi-check + - Blacklist p80211 module from abi checks + * ubuntu/lirc: Get rid of drivers symlink and use real include stuff + + + [ Colin Ian King ] + + * SAUCE: acerhk module - add support for Amilo A1650g keyboard + - LP: #84159 + * SAUCE: rt2x00: Fix OOPS on failed creation of rt2x00lib workqueue + - LP: #249242 + + [ Mario Limonciello ] + + * Add LIRC back in + + [ Tim Gardner ] + + * Makefile race condition can lead to ndiswrapper build failure + - LP: #241547 + * update linux-wlan-ng (prism2_usb) to upstream version 1861 + - LP: #245026 + + [ Upstream Kernel Changes ] + + * Fix typos from signal_32/64.h merge + + -- Ben Collins Fri, 01 Aug 2008 00:05:01 -0400 + +linux (2.6.26-5.13) intrepid; urgency=low + + [ Ben Collins ] + + * build: Make makedumpfile an amd64/i386 only build-dep + * ubuntu/acerhk: Fixup assembly to compile with newer binutils + + -- Ben Collins Sat, 26 Jul 2008 16:41:50 -0400 + +linux (2.6.26-4.12) intrepid; urgency=low + + [ Ben Collins ] + + * e1000e: Upgraded module to 0.4.1.7 upstream. Placed in ubuntu/, + in-kernel driver disabled + * config: Disable e1000e in-kernel, and enable newer driver in ubuntu/ + * rfkill: Update to 1.3 drivers, and move to common location + * ubuntu: Actually link kconfig/kbuild into rfkill subdir + * config: Enable loading dsdt from initramfs + - LP: #246222 + * ubuntu: [compcache] Update to fix crashes in improper BUG() + * build: Create a retag scripts to recover tags from rebases + * build: Updates for dbg pkg + * build: Make sure no empty lines show up in debian/files + * ubuntu: atl1e: Add new driver from 2.6.27-pre-rc1 + - LP: #243894 + * sys_getcwd: Fix some brokeness introduced by AppArmor __d_path + changes + - LP: #251223 + * ubuntu: unionfs: Added v1.4 module from hardy + * build: Add sub-flavour infrastructure, and virtual subflav + + [ Eric Piel ] + + * ACPI: Allow custom DSDT tables to be loaded from initramfs + + [ Kees Cook ] + + * AppArmor: Smack VFS patches + + [ Mario Limonciello ] + + * Work around ACPI corruption upon suspend on some Dell machines. + - LP: #183033 + + [ Tim Gardner ] + + * Export usbhid_modify_dquirk for LBM module bcm5974 + - LP: #250838 + * VIA - Add VIA DRM Chrome9 3D engine + - LP: #251862 + * Define TRUE/FALSE for VIA DRM driver. + + -- Ben Collins Tue, 15 Jul 2008 12:51:39 -0400 + +linux (2.6.26-4.11) intrepid; urgency=low + + [ Ben Collins ] + + * config: Enable bcm5974 driver in all configs + + [ 2.6.26-4.10 ] + + [ Amit Kucheria ] + + * Fix typo in GSPCA Makefile and make it compile + + [ Ben Collins ] + + * ubuntu: Remove UVC driver in favor of in-kernel one (-rc9) + * config: Updates for -rc9 + * ubuntu: Add acx, prism2_usb wireless drivers + * config: Enable prism2_usb and acx drivers. + * ubuntu: Add at76 driver to build + * config: Enable at76_usb driver. + * iscsitarget: Fix prototype for bi_end_io callback. + * acx: Fix section type mismatch warnings + * fsam7400: Add sw kill switch driver + * config: Enable fsam7400 driver + * qc-usb: Added new driver + * config: Enable qc-usb driver + * drbd: Remove built-in connector usage + * drbd: Do not define idx/val for connector here + * connector.h: Add idx/val for drbd + * bcm5974: Added new driver + + [ Kees Cook ] + + * SAUCE: [AppArmor] merge with upstream subversion r1291 + * SAUCE: [AppArmor] fix typo in selinux_inode_link + * SAUCE: [AppArmor] aufs patches + + [ Michael Frey (Senior Manager, MID ] + + * SAUCE: Send HCI_RESET for Broadcomm 2046 + - LP: #241749 + + [ Tim Gardner ] + + * SAUCE: Medion Akoya Mini E1210 + + [ Upstream Kernel Changes ] + + * Revert "BAST: Remove old IDE driver" + * ARM: OMAP: DMA: Don't mark channel active in omap_enable_channel_irq + * ARM: OMAP: Correcting the gpmc prefetch control register address + * debugobjects: fix lockdep warning + * [ARM] 5115/1: pxafb: fix ifdef for command line option handling + * [ARM] 5116/1: pxafb: cleanup and fix order of failure handling + * [ARM] 5109/1: Mark rtc sa1100 driver as wakeup source before + registering it + * [ARM] Export dma_sync_sg_for_device() + * fix cgroup-inflicted breakage in block_dev.c + * [patch for 2.6.26 2/4] vfs: utimensat(): be consistent with utime() for + immutable and append-only files + * [patch for 2.6.26 1/4] vfs: utimensat(): ignore tv_sec if tv_nsec == + UTIME_OMIT or UTIME_NOW + * [patch for 2.6.26 3/4] vfs: utimensat(): fix error checking for + {UTIME_NOW,UTIME_OMIT} case + * [patch for 2.6.26 4/4] vfs: utimensat(): fix write access check for + futimens() + * [patch 1/4] vfs: path_{get,put}() cleanups + * [patch 2/4] fs: make struct file arg to d_path const + * [patch 3/4] vfs: fix ERR_PTR abuse in generic_readlink + * [patch 4/4] flock: remove unused fields from file_lock_operations + * [patch 3/3] vfs: make d_path() consistent across mount operations + * [patch 1/3] vfs: dcache sparse fixes + * [patch 2/3] vfs: dcache cleanups + * udf: Fix regression in UDF anchor block detection + * [SCSI] ses: Fix timeout + * netfilter: ip6table_mangle: don't reroute in LOCAL_IN + * [SCSI] esp: Fix OOPS in esp_reset_cleanup(). + * kernel/audit.c: nlh->nlmsg_type is gotten more than once + * audit: fix kernel-doc parameter notation + * remove useless argument type in audit_filter_user() + * Blackfin arch: fix bug - kernel boot fails when Spinlock and rw-lock + debugging enabled + * Blackfin arch: fix up section mismatch warning + * mac80211: implement EU regulatory domain + * b43: Do not return TX_BUSY from op_tx + * b43legacy: Do not return TX_BUSY from op_tx + * b43: Fix possible MMIO access while device is down + * b43legacy: Fix possible NULL pointer dereference in DMA code + * rt2x00: Fix unbalanced mutex locking + * iwlwifi: improve scanning band selection management + * [SCSI] esp: tidy up target reference counting + * [ARM] 5117/1: pxafb: fix __devinit/exit annotations + * thermal: Create CONFIG_THERMAL_HWMON=n + * ACPI: don't walk tables if ACPI was disabled + * dock: bay: Don't call acpi_walk_namespace() when ACPI is disabled. + * x86: shift bits the right way in native_read_tscp + * x86: section/warning fixes + * V4L/DVB (8004): Fix INPUT dependency at budget-ci + * V4L/DVB (8005): Fix OOPS if frontend is null + * V4L/DVB (8007): cx18/cx25840: the S-Video LUMA input can use all + In1-In8 inputs + * V4L/DVB (8008): cx18: remove duplicate audio and video input enums + * V4L/DVB (8010): em28xx: Properly register extensions for already + attached devices + * V4L/DVB (8011): em28xx: enable DVB for HVR-900 + * V4L/DVB (8012): gl861: sleep a little to avoid I2C errors + * V4L/DVB (8013): gl861: remove useless identify_state + * V4L/DVB (8015): gl861: replace non critical msleep(0) with msleep(1) to + be on the safe side + * V4L/DVB (8017): Ensure em28xx extensions only get run against devs that + support them + * V4L/DVB (8018): Add em2860 chip ID + * V4L/DVB (8020): Fix callbacks functions of saa7134_empress + * V4L/DVB (8022): saa7134: fix race between opening and closing the + device + * V4L/DVB (8026): Avoids an OOPS if dev struct can't be successfully + recovered + * V4L/DVB (8027): saa7134: Avermedia A700: only s-video and composite + input are working + * V4L/DVB (8028): Improve error messages for tda1004x attach + * V4L/DVB (8029): Improve error message at tda1004x_attach + * V4L/DVB (8034): tda18271: fix IF notch frequency handling + * V4L/DVB (8035): tda18271: dont touch EB14 if rf_cal lookup is out of + range + * V4L/DVB (8036): tda18271: toggle rf agc speed mode on TDA18271HD/C2 + only + * V4L/DVB (8037): tda18271: ensure that the thermometer is off during + channel configuration + * V4L/DVB (8039): pxa-camera: fix platform_get_irq() error handling. + * V4L/DVB (8040): soc-camera: remove soc_camera_host_class class + * V4L/DVB (8042): DVB-USB UMT-010 channel scan oops + * V4L/DVB (8043): au0828: add support for additional USB device id's + * V4L/DVB (8044): au8522: tuning optimizations + * V4L/DVB (8048): saa7134: Fix entries for Avermedia A16d and Avermedia + E506 + * V4L/DVB (8061): cx18: only select tuner / frontend modules if + !DVB_FE_CUSTOMISE + * V4L/DVB (8063): cx18: Fix unintended auto configurations in + cx18-av-core + * V4L/DVB (8066): cx18: Fix audio mux input definitions for HVR-1600 Line + In 2 and FM radio + * V4L/DVB (8067): cx18: Fix firmware load for case when digital capture + happens first + * V4L/DVB (8068): cx18: Add I2C slave reset via GPIO upon initialization + * V4L/DVB (8069): cx18: Fix S-Video and Compsite inputs for the Yuan + MPC718 and enable card entry + * V4L/DVB (8071): tda10023: Fix possible kernel oops during + initialisation + * V4L/DVB (8073): av7110: Catch another type of ARM crash + * V4L/DVB (8074): av7110: OSD transfers should not be interrupted + * V4L/DVB (8075): stv0299: Uncorrected block count and bit error rate + fixed + * V4L/DVB (8092): videodev: simplify and fix standard enumeration + * V4L/DVB (8096): au8522: prevent false-positive lock status + * V4L/DVB (8097): xc5000: check device hardware state to determine if + firmware download is needed + * V4L/DVB (8100): V4L/vivi: fix possible memory leak in vivi_fillbuff + * V4L/DVB (8108): Fix open/close race in saa7134 + * s2io: fix documentation about intr_type + * tc35815: Mark carrier-off before starting PHY + * tc35815: Fix receiver hangup on Rx FIFO overflow + * ixgbe: fix EEH recovery during reset on PPC + * igb: fix EEH recovery during reset on PPC + * e1000e: fix EEH recovery during reset on PPC + * pcnet_cs, axnet_cs: clear bogus interrupt before request_irq + * drivers/net/r6040.c: Eliminate double sizeof + * ipg: fix jumbo frame compilation + * ipg: use NULL, not zero, for pointers + * [netdrvr] 3c59x: remove irqs_disabled warning from local_bh_enable + * [netdrvr] netxen: fix netxen_pci_tbl[] breakage + * e100: Do pci_dma_sync after skb_alloc for proper operation on ixp4xx + * e1000: only enable TSO6 via ethtool when using correct hardware + * [netdrvr] Fix IOMMU overflow checking in s2io.c + * qla3xxx: Hold RTNL while calling dev_close() + * Hold RTNL while calling dev_close() + * sata_uli: hardreset is broken + * rt2x00: Fix lock dependency errror + * prism: islpci_eth.c endianness fix + * mac80211: fix an oops in several failure paths in key allocation + * firewire: fw-sbp2: fix parsing of logical unit directories + * kbuild: fix a.out.h export to userspace with O= build. + * Ensure interrupted recovery completed properly (v1 metadata plus + bitmap) + * Don't acknowlege that stripe-expand is complete until it really is. + * Fix error paths if md_probe fails. + * hamradio: remove unused variable + * tcp: calculate tcp_mem based on low memory instead of all memory + * tcp: fix for splice receive when used with software LRO + * af_unix: fix 'poll for write'/connected DGRAM sockets + * netdevice: Fix typo of dev_unicast_add() comment + * pkt_sched: ERR_PTR() ususally encodes an negative errno, not positive. + * pkt_sched: Remove CONFIG_NET_SCH_RR + * include/linux/netdevice.h: don't export MAX_HEADER to userspace + * tcp: /proc/net/tcp rto,ato values not scaled properly (v2) + * netlink: Fix some doc comments in net/netlink/attr.c + * CONNECTOR: add a proc entry to list connectors + * inet fragments: fix race between inet_frag_find and + inet_frag_secret_rebuild + * net/inet_lro: remove setting skb->ip_summed when not LRO-able + * netlabel: Fix a problem when dumping the default IPv6 static labels + * ipv6 route: Convert rt6_device_match() to use RT6_LOOKUP_F_xxx flags. + * sched: fix cpu hotplug + * Fix and clean top .gitignore + * x86: fix cpu hotplug crash + * ptrace GET/SET FPXREGS broken + * Input: add KEY_MEDIA_REPEAT definition + * Input: fix locking in force-feedback core + * [ARM] 5131/1: Annotate platform_secondary_init with trace_hardirqs_off + * ide: fix /proc/ide/ide?/mate reporting + * netfilter: nf_conntrack_tcp: fixing to check the lower bound of valid + ACK + * textsearch: fix Boyer-Moore text search bug + * hostap: don't report useless WDS frames by default + * hostap: fix sparse warnings + * mac80211: don't accept WEP keys other than WEP40 and WEP104 + * V4L/DVB (8145a): USB Video Class driver + * [IA64] Bugfix for system with 32 cpus + * [IA64] export account_system_vtime + * sched: fix divide error when trying to configure rt_period to zero + * x86: fix NODES_SHIFT Kconfig range + * block: Fix the starving writes bug in the anticipatory IO scheduler + * Properly notify block layer of sync writes + * rcu: fix hotplug vs rcu race + * I2C: S3C2410: Check ACK on byte transmission + * I2C: S3C2410: Fixup error codes returned rom a transfer. + * I2C: S3C2410: Add MODULE_ALIAS() for s3c2440 device. + * PCI: Restrict VPD read permission to root + * powerpc/bootwrapper: update for initrd with simpleImage + * i2c: Documentation: fix device matching description + * i2c: Fix bad hint about irqs in i2c.h + * powerpc/legacy_serial: Bail if reg-offset/shift properties are present + * powerpc/mpc5200: Fix lite5200b suspend/resume + * ipv4: fix sysctl documentation of time related values + * net-sched: change tcf_destroy_chain() to clear start of filter list + * net-sched: fix filter destruction in atm/hfsc qdisc destruction + * netlink: Unneeded local variable + * net: Tyop of sk_filter() comment + * netdevice: Fix wrong string handle in kernel command line parsing + * net: fib_rules: fix error code for unsupported families + * dm crypt: use cond_resched + * V4L/DVB (8178): uvc: Fix compilation breakage for the other drivers, if + uvc is selected + * PCI: Limit VPD read/write lengths for Broadcom 5706, 5708, 5709 rev. + * PCI: acpiphp: cleanup notify handler on all root bridges + * drivers/input/ff-core.c needs + * DRM/i915: only use tiled blits on 965+ + * tty: Fix inverted logic in send_break + * x86: fix Intel Mac booting with EFI + * arch/x86/mm/init_64.c: early_memtest(): fix types + * 9p: fix O_APPEND in legacy mode + * slub: Do not use 192 byte sized cache if minimum alignment is 128 byte + * Do not overwrite nr_zones on !NUMA when initialising zlcache_ptr + * [MIPS] IP32: Fix unexpected irq 71 + * [MIPS] IP22: Fix crashes due to wrong L1_CACHE_BYTES + * [MIPS] cevt-txx9: Reset timer counter on initialization + * hrtimer: prevent migration for raising softirq + * svcrpc: fix handling of garbage args + * OHCI: Fix problem if SM501 and another platform driver is selected + * USB: fix cdc-acm resume() + * USB: ehci - fix timer regression + * USB: ohci - record data toggle after unlink + * USB: mass storage: new id for US_SC_CYP_ATACB + * sisusbvga: Fix oops on disconnect. + * USB: New device ID for ftdi_sio driver + * USB: fix interrupt disabling for HCDs with shared interrupt handlers + * USB: don't lose disconnections during suspend + * USB: another option device id + * USB: add a pl2303 device id + * USB: fix Oops on loading ipaq module since 2.6.26 + * USB: adding comment for ipaq forcing number of ports + * [MIPS] Fix bug in atomic_sub_if_positive. + * xen: fix address truncation in pte mfn<->pfn conversion + * sata_sil24: add DID for another adaptec flavor + * ahci: always clear all bits in irq_stat + * libata-sff: improve HSM violation reporting + * sata_mv: safer logic for limit_warnings + * Update maintainers for powerpc + * Christoph has moved + * mm: dirty page accounting vs VM_MIXEDMAP + * rtc: rtc_read_alarm() handles wraparound + * firmware: fix the request_firmware() dummy + * serial: fix serial_match_port() for dynamic major tty-device numbers + * get_user_pages(): fix possible page leak on oom + * rtc-x1205: Fix alarm set + * rtc: fix CMOS time error after writing /proc/acpi/alarm + * pci: VT3336 can't do MSI either + * Miguel Ojeda has moved + * ext3: add missing unlock to error path in ext3_quota_write() + * ext4: add missing unlock to an error path in ext4_quota_write() + * reiserfs: add missing unlock to an error path in reiserfs_quota_write() + * ecryptfs: remove unnecessary mux from ecryptfs_init_ecryptfs_miscdev() + * lib: taint kernel in common report_bug() WARN path. + * gpio: pca953x (i2c) handles max7310 too + * fsl_diu_fb: fix build with CONFIG_PM=y, plus fix some warnings + * Update taskstats-struct document for scaled time accounting + * cciss: fix regression that no device nodes are created if no logical + drives are configured. + * delay accounting: maintainer update + * Doc*/kernel-parameters.txt: fix stale references + * hdaps: add support for various newer Lenovo thinkpads + * mn10300: export certain arch symbols required to build allmodconfig + * mn10300: provide __ucmpdi2() for MN10300 + * Introduce rculist.h + * man-pages is supported + * ntfs: update help text + * add kernel-doc for simple_read_from_buffer and memory_read_from_buffer + * w100fb: do not depend on SHARPSL + * w100fb: add 80 MHz modeline + * MFD maintainer + * cgroups: document the effect of attaching PID 0 to a cgroup + * spi: fix the read path in spidev + * doc: doc maintainers + * security: filesystem capabilities: fix fragile setuid fixup code + * security: filesystem capabilities: fix CAP_SETPCAP handling + * Alpha Linux kernel fails with inconsistent kallsyms data + * cpusets: document proc status cpus and mems allowed lists + * MAINTAINERS: update the email address of Andreas Dilger + * cciss: read config to obtain max outstanding commands per controller + * olpc: sdhci: add quirk for the Marvell CaFe's vdd/powerup issue + * olpc: sdhci: add quirk for the Marvell CaFe's interrupt timeout + * cpumask: introduce new APIs + * mm: switch node meminfo Active & Inactive pages to Kbytes + * Update MAINTAINERS file for the TPM device driver + * devcgroup: fix odd behaviour when writing 'a' to devices.allow + * doc: document the relax_domain_level kernel boot argument + * mmc: don't use DMA on newer ENE controllers + * mempolicy: mask off internal flags for userspace API + * x86 ACPI: normalize segment descriptor register on resume + * x86 ACPI: fix resume from suspend to RAM on uniprocessor x86-64 + * softlockup: print a module list on being stuck + * ide: fix hwif->gendev refcounting + * ide: ide_unregister() warm-plug bugfix + * ide: ide_unregister() locking bugfix + * ahci: give another shot at clearing all bits in irq_stat + * Fix clear_refs_write() use of struct mm_walk + * Move _RET_IP_ and _THIS_IP_ to include/linux/kernel.h + * Fix pagemap_read() use of struct mm_walk + * Linux 2.6.26-rc9 + * Revert "USB: don't explicitly reenable root-hub status interrupts" + * Revert "PCI: Correct last two HP entries in the bfsort whitelist" + * iwlwifi: fix incorrect 5GHz rates reported in monitor mode + * iwlwifi: drop skb silently for Tx request in monitor mode + * libertas: support USB persistence on suspend/resume (resend) + * tcp: net/ipv4/tcp.c needs linux/scatterlist.h + * tcp: fix a size_t < 0 comparison in tcp_read_sock + * bridge: fix use-after-free in br_cleanup_bridges() + * Add missing skb->dev assignment in Frame Relay RX code + * forcedeth: fix lockdep warning on ethtool -s + * ehea: fix might sleep problem + * ehea: add MODULE_DEVICE_TABLE + * ehea: fix race condition + * ehea: Access iph->tot_len with correct endianness + * pasemi_mac: Access iph->tot_len with correct endianness + * ibm_newemac: Fixes kernel crashes when speed of cable connected changes + * ibm_newemac: Fixes entry of short packets + * fs_enet: restore promiscuous and multicast settings in restart() + * can: add sanity checks + * x86: KVM guest: Add memory clobber to hypercalls + * KVM: IOAPIC: Fix level-triggered irq injection hang + * [SCSI] erase invalid data returned by device + * pxamci: fix byte aligned DMA transfers + * vsprintf: split out '%s' handling logic + * vsprintf: split out '%p' handling logic + * vsprintf: add infrastructure support for extended '%p' specifiers + * vsprintf: add support for '%pS' and '%pF' pointer formats + * powerpc: Fix unterminated of_device_id array in legacy_serial.c + * [UML] fix gcc ICEs and unresolved externs + * ocfs2/dlm: Fixes oops in dlm_new_lockres() + * hostap_cs: correct poor NULL checks in suspend/resume routines + * drivers/net/wireless/iwlwifi/iwl-3945.c Fix type issue on 64bit + * mac80211: move netif_carrier_on to after + ieee80211_bss_info_change_notify + * mac80211: Only flush workqueue when last interface was removed + * zd1211rw: add ID for AirTies WUS-201 + * ssb-pcicore: Fix IRQ-vector init on embedded devices + * mac80211: don't report selected IBSS when not found + * crypto: tcrypt - Fix memory leak in test_cipher + * sctp: Mark the tsn as received after all allocations finish + * [S390] protect _PAGE_SPECIAL bit against mprotect + * irda: via-ircc proper dma freeing + * irda: New device ID for nsc-ircc + * irda: Fix netlink error path return value + * [SCSI] mptspi: fix oops in mptspi_dv_renegotiate_work() + * Correct hash flushing from huge_ptep_set_wrprotect() + * ide: add __ide_default_irq() inline helper + * palm_bk3710: fix IDECLK period calculation + * it8213: fix return value in it8213_init_one() + * [MIPS] Atlas, decstation: Fix section mismatches triggered by + defconfigs + * [MIPS] Fix 32bit kernels on R4k with 128 byte cache line size + * NFS: Fix readdir cache invalidation + * SUNRPC: Fix a double-free in rpcbind + * SUNRPC: Fix an rpcbind breakage for the case of IPv6 lookups + * reiserfs: discard prealloc in reiserfs_delete_inode + * Fix broken fix for fsl-diu-db + * RDMA/cxgb3: Fix regression caused by class_device -> device conversion + * ipv6: fix race between ipv6_del_addr and DAD timer + * sctp: Add documentation for sctp sysctl variable + * kernel/printk.c: Made printk_recursion_bug_msg static. + * powerpc: Add missing reference to coherent_dma_mask + * rc80211_pid: Fix fast_start parameter handling + * rt2x00: Disable synchronization during initialization + * zd1211rw: stop beacons on remove_interface + * libertas: fix memory alignment problems on the blackfin + * netfilter: nf_conntrack_tcp: fix endless loop + * netfilter: nf_nat_snmp_basic: fix a range check in NAT for SNMP + * md: ensure all blocks are uptodate or locked when syncing + * sched: fix cpu hotplug + * x86: fix /dev/mem compatibility under PAT + * crypto: chainiv - Invoke completion function + * ocfs2: Fix flags in ocfs2_file_lock + * kernel/kprobes.c: Made kprobe_blacklist static. + * arch/x86/kernel/.gitignore: Added vmlinux.lds to .gitignore file + because it shouldn't be tracked. + * ftrace: Documentation + * Fix PREEMPT_RCU without HOTPLUG_CPU + * sched: fix cpu hotplug, cleanup + * exec: fix stack excutability without PT_GNU_STACK + * slub: Fix use-after-preempt of per-CPU data structure + * Documentation: clarify tcp_{r,w}mem sysctl docs + * ip: sysctl documentation cleanup + * tcp: correct kcalloc usage + * ipv4: fib_trie: Fix lookup error return + * netlabel: netlink_unicast calls kfree_skb on error path by itself + * ipv6: missed namespace context in ipv6_rthdr_rcv + * xfrm: Add a XFRM_STATE_AF_UNSPEC flag to xfrm_usersa_info + * tun: Persistent devices can get stuck in xoff state + * tpm: add Intel TPM TIS device HID + * rapidio: fix device reference counting + * Fix name of Russell King in various comments + * rtc: fix reported IRQ rate for when HPET is enabled + * libata-acpi: filter out DIPM enable + * Added Targa Visionary 1000 IDE adapter to pata_sis.c + * libata-acpi: don't call sleeping function from invalid context + * Fix reference counting race on log buffers + * [SCSI] ipr: Fix HDIO_GET_IDENTITY oops for SATA devices + * IPMI: return correct value from ipmi_write + * x86: fix ldt limit for 64 bit + * [SCSI] fusion: default MSI to disabled for SPI and FC controllers + * [SCSI] bsg: fix oops on remove + * drivers/char/pcmcia/ipwireless/hardware.c fix resource leak + * drivers/isdn/i4l/isdn_common.c fix small resource leak + * fbdev: bugfix for multiprocess defio + * serial8250: sanity check nr_uarts on all paths. + * ov7670: clean up ov7670_read semantics + * rtc-fm3130: fix chip naming + * rtc-pcf8563: add chip id + * OProfile kernel maintainership changes + * frv: fix irqs_disabled() to return an int, not an unsigned long + * cifs: fix inode leak in cifs_get_inode_info_unix + * cifs: fix wksidarr declaration to be big-endian friendly + * cpusets, hotplug, scheduler: fix scheduler domain breakage + * Documentation/HOWTO: correct wrong kernel bugzilla FAQ URL + * devcgroup: always show positive major/minor num + * devcgroup: fix permission check when adding entry to child cgroup + * Linux 2.6.26 + + -- Ben Collins Mon, 14 Jul 2008 13:41:50 -0400 + +linux (2.6.26-3.9) intrepid; urgency=low + + * abi: Add dca and ioatdma to modules.ignore + + [ 2.6.26-3.8 ] + + [ Ben Collins ] + + * ubuntu: Add heci driver 3.2.0.24 + * ubuntu: Add heci to kconfig/kbuild + * config: Enable heci module on all flavours + * dm-bbr: Update to get it to compile with 2.6.26 + * config: Enable dm-bbr + * ubuntu: Add some media drivers + * config: Enable misc media drivers + * udeb: Switch to uvesafb in fb-modules + * abi: Add more modules to ignore (known) + + [ 2.6.26-3.7 ] + + [Amit Kucheria] + + * SAUCE: make fc transport removal of target configurable + - LP: #163075 + * SAUCE: pm: Config option to disable handling of console during + suspend/resume + + [Ben Collins] + + * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps + * SAUCE: irda: Default to dongle type 9 on IBM hardware + * SAUCE: tulip: Let dmfe handle davicom on non-sparc + * SAUCE: tulip: Define ULI PCI ID's + * SAUCE: version: Implement version_signature proc file. + * build: Cleanup arches + * build: Remove remnants of unused binary-custom infrastructure + * build: Remove disable_d_i (not needed) and cleanup ppa build stuff + * ubuntu: New modules, acer-acpi + * build: Remove -virtual, and rebuild configs + * ubuntu: Add drbd module + * acer-acpi: Fix makefile + * x86/Kconfig: Fix missing quote for ubuntu Kconfig source + * ubuntu: Add iscsitarget module + * ubuntu: Added Amiga FS driver + * ubuntu: Add squashfs driver + * ubuntu: Remove asfs (Amiga FS). Need to be in linux-ports instead + * squashfs: Move headers to real include directory + * build/configs: The Great Config Consistency Check of 2008 + * ubuntu: Move third-party includes to ubuntu/include + * ubuntu: Add aufs module + * ubuntu: Added atl2 driver + * ubuntu: Add dm-radi4-5 driver + * build: Add CONFIG_DEBUG_SECTION_MISMATCH=y to get old style warnings + from build + * ubuntu/Makefile: Fixup dm-raid4-5 and add kludge for kbuild + * squashfs: Fixes for VFS changes + * ubuntu/dm-raid4-5: Fixups for moved/renamed headers/functions in core + md + * ubuntu: Add ndiswrapper driver + * d-i: Update module listings + * build: Disable xd block device (ancient) + * ndiswrapper: Fixup makefile + * d-i: Remove efi-modules. The only module, efivars, is built-in + * build: Remove install-source, obsolete and caused build failure + * Ubuntu-2.6.26-1.3 + * build: linux-doc rules got broken when disabling html side. Fixed now. + * Ubuntu-2.6.26-1.4 + * x86: Update to -rc6 allows CONFIG_PCI_OLPC to work with PCI_GOANY + * d-i: Make virtio-ring optional (it's built-in on i386) + * Ubuntu-2.6.26-1.4 + * Ubuntu-2.6.26-1.5 + * config: Enable DVB devices + * ubuntu/aufs: Make aufs a bool config, since it needs to be built-in + * config: Build aufs into the kernels + * build: Fix arguments passed to link-headers script + * config: Disable early printk + * d-i: Move isofs to storage-core and kill st (scsi tape) from list + * config: Enable non-promiscuous access to /dev/mem + * x86: Add option to disable decompression info messages + * config: Enable no-bz-chatter config options + * build: Re-add linux-source package + * d-i: Re-add socket-modules. Accidentally removed + - LP: #241295 + * Ubuntu-2.6.26-2.6 + * Use makedumpfile to generate a vmcoreinfo file. + * build: Build-Depend on makedumpfile for vmcoreinfo generation + * build: Remove debug print from git-ubuntu-log + * Updated configs for -rc7 + * build: postinst, do not call depmod with -F + * config: Enable rtc-cmos as a built-in driver. + * control: Provide ndiswrapper-modules-1.9 + * build: Generate vmcoreinfo in image build for crashdumps without debug + image + * config: Disable vesafb, since we'll prefer uvesafb + * build: Copy uvesafb module to initrd mod directory + * abi-check: New, more robust script + * config: Enable heap randomization by default + * abi-check: Cleanup output and call with perl (not $SHELL) + * abi: Ignore missing vesafb (known) + * config: Disable pcspkr (in favor of snd-pcsp) + * swap: Add notify_swap_entry_free callback for compcache + * compcache: Added ram backed compressed swap module + * ubuntu: Enable kbuild and kconfig for compcache + * config: Enable compcache and tlsf allocator as modules + * config: Updated for -rc8. Disables XEN on i386 + * config: Switch i386-server to 64G, enable PAE, 64-bit res, and XEN + * ubuntu: Add misc drivers from hardy lum + * ubuntu: Enable build of misc/ subdir + * config: Enable misc drivers + * aufs: Fix warning about single non-string-literal arg to printf style + function + * drivers: Remove some duplicate device entries in various modules + * config: Disable some duplicate drivers + * keyspan: Remove duplicate device ID's + * check-aliases: Cleanup output, and fix rolling checks + * ubuntu: Disable dm-bbr for now + * dm-bbr: First cut at forward portiong. Still needs work. + * ubuntu: Disable dm-bbr in kbuild/kconfig + + [Chuck Short] + + * SAUCE: ata: blacklist FUJITSU MHW2160BH PL + - LP: #175834 + * SAUCE: [USB]: add ASUS LCM to the blacklist + + [Colin Ian King] + + * SAUCE: airprime.c supports more devices + - LP: #208250 + * SAUCE: Enable speedstep for sonoma processors. + - LP: #132271 + * Add dm-loop + * Add dm-loop BOM + + [Kyle McMartin] + + * SAUCE: fix orinoco_cs oops + + [Mario Limonciello] + + * SAUCE: Enable Reset and SCO workaround on Dell 410 BT adapter + + [Matthew Garrett] + + * SAUCE: hostap: send events on data interface as well as master + interface + + [Phillip Lougher] + + * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets. + + [Stefan Bader] + + * SAUCE: Export dm_disk function of device-mapper + * SAUCE: Restore VT fonts on switch + * SAUCE: Always use SCO protocol (disable eSCO support) Bug: #39414 + * SAUCE: mmc: Increase power_up deleay to fix TI readers OriginalAuthor: + Pascal Terjan Bug: #137686 + * SAUCE: Add blacklist support to fix Belkin bluetooth dongle. Bug: + #140511 + * SAUCE: Lower warning level of pci resource allocation messages. Bug: + 159241 + * SAUCE: Lower message level for PCI memory and I/O allocation. + - LP: #159241 + * Modify log generation to catch bug numbers when adding with git-am. + + [Tim Gardner] + + * Added the debian directory. Ignore: yes + * Add support for UBUNTUINCLUDE Ignore: yes + * LUM headers go in /usr/src Ignore: yes + * First pass at 2.6.25 configs Ignore: yes + * i386 -generic builds. Ignore: yes + * SAUCE: Increase CONFIG_IDE_MAX_HWIFS to 8 (from 4) + * SAUCE: Add extra headers to linux-libc-dev OriginalAuthor: Soren Hansen + OriginalLocation: + https://lists.ubuntu.com/archives/kernel-team/2007-November/001891.html + * Set CONFIG_DEVKMEM=n Ignore: yes + * Enabled ALSA and CGROUPS for i386 Ignore: yes + * Enabled amd64 configs. Ignore: yes + * CONFIG_STANDALONE=n Ignore: yes + * CONFIG_BLK_DEV_4DRIVES=n for i386 Ignore: yes + * CONFIG: CONFIG_DEFAULT_RELATIME=y for all flavours. Ignore: yes + * Set CONFIG_EDD_OFF=y Ignore: yes + * SAUCE: Blacklist Bluetooth Dell Wireless 370 for SCO MTU + OriginalAuthor: Mario Limonciello Bug: + #209715 + * SAUCE: Catch nonsense keycodes and silently ignore + * SAUCE: frame buffer regression - screen blank except for blinking + cursor after fbcon vtswitch OriginalAuthor: Matthew Garrett + Bug: #201591 + * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM + OriginalAuthor: Klaus S. Madsen + OriginalAuthor: Chuck Short + * SAUCE: Guest OS does not recognize a lun with non zero target id on + Vmware ESX Server + * SAUCE: orinoco_cs.ko missing + * Set CONFIG_FB_VESA=m for i386/amd64 Ignore: yes + * Set CONFIG_PM_DISABLE_CONSOLE=y for all flavours Ignore: yes + * Thorough review of amd64 -generic config Ignore: yes + * Build PPA packages for Hardy until the Intrepid archive is opened. + * Deleted obsolete flavours Ignore: yes + * Don't build docs for PPA Ignore: yes + * Build all standard packages in PPA. Ignore: yes + * Remove duplicate USB ids + * SAUCE: DVB-USB UMT-010 driver oops on install Bug: #115284 + * Update configs after rebase to 2.6.26-rc1 Ignore: yes + * Update configs after rebase Ignore: yes + * Disable V4L until the build issues get ironed out. Ignore: yes + * Update configs after rebase. Ignore: yes + * Another device enable pass Ignore: yes + * Update configs after merge. Ignore: yes + * SAUCE: fn key doesn't work in hardy with macbook pro fourth generation + (4,1) + - LP: #207127 + * Enabled CONFIG_CIFS_DFS_UPCALL=y and CONFIG_CIFS_UPCALL=y + - LP: #236830 + + [Upstream Kernel Changes] + + * Revert "[WATCHDOG] hpwdt: Add CFLAGS to get driver working" + * mac80211: detect driver tx bugs + * hwmon: (lm85) Fix function RANGE_TO_REG() + * hwmon: (adt7473) Initialize max_duty_at_overheat before use + * hwmon: Update the sysfs interface documentation + * hwmon: (abituguru3) Identify Abit AW8D board as such + * hwmon: (w83791d) new maintainer + * hwmon: (abituguru3) update driver detection + * hwmon: (lm75) sensor reading bugfix + * ipv6: Remove options header when setsockopt's optlen is 0 + * ipv6: Drop packets for loopback address from outside of the box. + * sched: rt: dont stop the period timer when there are tasks wanting to + run + * sched: fix wait_for_completion_timeout() spurious failure under heavy + load + * x86: fix NULL pointer deref in __switch_to + * xen: Use wmb instead of rmb in xen_evtchn_do_upcall(). + * xen: mask unwanted pte bits in __supported_pte_mask + * xen: don't drop NX bit + * sched: refactor wait_for_completion_timeout() + * Ext4: Fix online resize block group descriptor corruption + * [IA64] SN2: security hole in sn2_ptc_proc_write + * alpha: fix module load failures on smp (bug #10926) + * alpha: link failure fix + * alpha: fix compile failures with gcc-4.3 (bug #10438) + * alpha: resurrect Cypress IDE quirk + * pppoe: warning fix + * sctp: Make sure N * sizeof(union sctp_addr) does not overflow. + * netns: Don't receive new packets in a dead network namespace. + * Add return value to reserve_bootmem_node() + * Slab: Fix memory leak in fallback_alloc() + * Fix performance regression on lmbench select benchmark + * ALSA: aw2 - Fix Oops at initialization + * ALSA: sb - Fix wrong assertions + * futexes: fix fault handling in futex_lock_pi + * IB/mthca: Clear ICM pages before handing to FW + * tty_driver: Update required method documentation + * removed unused var real_tty on n_tty_ioctl() + * Fix ZERO_PAGE breakage with vmware + * mm: fix race in COW logic + * NFS: Reduce the NFS mount code stack usage. + * NFS: Fix filehandle size comparisons in the mount code + * NFS: nfs_updatepage(): don't mark page as dirty if an error occurred + * alpha: fix compile error in arch/alpha/mm/init.c + * KVM: Fix race between timer migration and vcpu migration + * KVM: close timer injection race window in __vcpu_run + * KVM: MMU: Fix rmap_write_protect() hugepage iteration bug + * KVM: MMU: large page update_pte issue with non-PAE 32-bit guests + (resend) + * KVM: MMU: Fix oops on guest userspace access to guest pagetable + * KVM: ioapic: fix lost interrupt when changing a device's irq + * KVM: VMX: Fix host msr corruption with preemption enabled + * [GFS2] BUG: unable to handle kernel paging request at ffff81002690e000 + * xen: remove support for non-PAE 32-bit + * kgdb: documentation update - remove kgdboe + * kgdb: sparse fix + * [IA64] Fix boot failure on ia64/sn2 + * [IA64] Handle count==0 in sn2_ptc_proc_write() + * [IA64] Eliminate NULL test after alloc_bootmem in iosapic_alloc_rte() + * [GFS2] fix gfs2 block allocation (cleaned up) + * x86: Add structs and functions for paravirt clocksource + * x86: Make xen use the paravirt clocksource structs and functions + * KVM: Make kvm host use the paravirt clocksource structs + * x86: KVM guest: Use the paravirt clocksource structs and functions + * KVM: Remove now unused structs from kvm_para.h + * enable bus mastering on i915 at resume time + * Linux 2.6.26-rc8 + * # Ubuntu external driver commit. + * # Ubuntu commit template. + + -- Ben Collins Sat, 21 Jun 2008 09:05:15 -0400 + +linux (2.6.26-2.6) intrepid; urgency=low + + [Ben Collins] + + * Revert "SAUCE: Export symbols for aufs (in lum) (not needed) + * config: Enable DVB devices + * ubuntu/aufs: Make aufs a bool config, since it needs to be built-in + * config: Build aufs into the kernels + * build: Fix arguments passed to link-headers script + * config: Disable early printk + * d-i: Move isofs to storage-core and kill st (scsi tape) from list + * config: Enable non-promiscuous access to /dev/mem + * x86: Add option to disable decompression info messages + * config: Enable no-bz-chatter config options + * build: Re-add linux-source package + * d-i: Re-add socket-modules. Accidentally removed + - LP: #241295 + + [Colin Ian King] + + * Add dm-loop + + [Tim Gardner] + + * Revert "SAUCE: USB bluetooth device 0x0e5e:0x6622 floods errors to + syslog (merged upstream) + + -- Ben Collins Mon, 16 Jun 2008 10:56:01 -0400 + +linux (2.6.26-1.5) intrepid; urgency=low + + * d-i: Make virtio-ring optional (it's built-in on i386) + * Rebased on 2.6.26-rc6 + + [Ubuntu-2.6.26-1.4 Changes below] + + * build: linux-doc rules got broken when disabling html side. Fixed now. + + [Ubuntu-2.6.26-1.3 Changes below] + + * build: Remove install-source, obsolete and caused build failure + + [Ubuntu-2.6.26-1.2 Changes below] + + * Remove efi-modules from d-i module list (efivars is built-in). Caused a + build failure. + * Patch to arch/x86/xen/time.c to remove __divdi3 usage (build failure on + i386). + + [Ubuntu-2.6.26-1.1 Changes below] + + [Amit Kucheria] + + * SAUCE: make fc transport removal of target configurable + * SAUCE: Add AGP support for Radeon Mobility 9000 chipset + * SAUCE: pm: Config option to disable handling of console during + suspend/resume + + [Ben Collins] + + * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps + * SAUCE: irda: Default to dongle type 9 on IBM hardware + * SAUCE: tulip: Let dmfe handle davicom on non-sparc + * SAUCE: tulip: Define ULI PCI ID's + * SAUCE: version: Implement version_signature proc file. + * build: Remove remnants of unused binary-custom infrastructure + * mmc_block: Fix bad allocation on 64-bit (zero len array) + * ubuntu: New modules, acer-acpi + * build: Remove -virtual, and rebuild configs + * ubuntu: Add drbd module + * ubuntu: Add iscsitarget module + * ubuntu: Add squashfs driver + * build/configs: The Great Config Consistency Check of 2008 + * ubuntu: Add aufs module + * ubuntu: Added atl2 driver + * ubuntu: Add dm-radi4-5 driver + * build: Add CONFIG_DEBUG_SECTION_MISMATCH=y to get old style warnings + from build + * squashfs: Fixes for VFS changes + * ubuntu/dm-raid4-5: Fixups for moved/renamed headers/functions in core + md + * ubuntu: Add ndiswrapper driver + * d-i: Update module listings + + [Chuck Short] + + * SAUCE: ata: blacklist FUJITSU MHW2160BH PL + * SAUCE: [USB]: add ASUS LCM to the blacklist + + [Colin Ian King] + + * SAUCE: Enable speedstep for sonoma processors. + * SAUCE: airprime.c supports more devices + + [Kyle McMartin] + + * SAUCE: fix orinoco_cs oops + + [Mario Limonciello] + + * SAUCE: Enable Reset and SCO workaround on Dell 410 BT adapter + + [Matthew Garrett] + + * SAUCE: hostap: send events on data interface as well as master + interface + + [Phillip Lougher] + + * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets. + + [Stefan Bader] + + * SAUCE: Export dm_disk function of device-mapper + * SAUCE: Restore VT fonts on switch + * SAUCE: Always use SCO protocol (disable eSCO support) Bug: #39414 + * SAUCE: mmc: Increase power_up deleay to fix TI readers + * SAUCE: Add blacklist support to fix Belkin bluetooth dongle. + * SAUCE: Lower warning level of pci resource allocation messages. + * SAUCE: Lower message level for PCI memory and I/O allocation. + - LP: #159241 + * Modify log generation to catch bug numbers when adding with git-am. + + [Tim Gardner] + + * SAUCE: hdaps module does not load on Thinkpad T61P + * SAUCE: Add extra headers to linux-libc-dev + * SAUCE: Export symbols for aufs (in lum). + * SAUCE: USB bluetooth device 0x0e5e:0x6622 floods errors to syslog + * SAUCE: Blacklist Bluetooth Dell Wireless 370 for SCO MTU + * SAUCE: Catch nonsense keycodes and silently ignore + * SAUCE: frame buffer regression - screen blank except for blinking + cursor after fbcon vtswitch + * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM + * SAUCE: Guest OS does not recognize a lun with non zero target id on + Vmware ESX Server + * SAUCE: Modualrize vesafb + * SAUCE: DVB-USB UMT-010 driver oops on install + * SAUCE: fn key doesn't work in hardy with macbook pro fourth generation + (4,1) + - LP: #207127 + + -- Ben Collins Wed, 11 Jun 2008 05:28:35 -0400 --- linux-2.6.27.orig/debian/control.stub.in +++ linux-2.6.27/debian/control.stub.in @@ -0,0 +1,70 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.6.1 +Build-Depends: debhelper (>= 3), module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [!armel] +Build-Depends-Indep: xmlto, docbook-utils, gs, transfig, bzip2, sharutils +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-intrepid + +Package: linux-source-PKGVER +Architecture: all +Section: devel +Priority: optional +Provides: linux-source, linux-source-2.6 +Depends: binutils, bzip2, coreutils | fileutils (>= 4.0) +Recommends: libc-dev, gcc, make +Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev +Description: Linux kernel source for version PKGVER with Ubuntu patches + This package provides the source code for the Linux kernel version + PKGVER. + . + This package is mainly meant for other packages to use, in order to build + custom flavours. + . + If you wish to use this package to create a custom Linux kernel, then it + is suggested that you investigate the package kernel-package, which has + been designed to ease the task of creating kernel image packages. + . + If you are simply trying to build third-party modules for your kernel, + you do not want this package. Install the appropriate linux-headers + package instead. + +Package: linux-doc-PKGVER +Architecture: all +Section: doc +Priority: optional +Provides: linux-doc-2.6 +Conflicts: linux-doc-2.6 +Replaces: linux-doc-2.6 +Depends: coreutils | fileutils (>= 4.0) +Description: Linux kernel specific documentation for version PKGVER + This package provides the various readme's in the PKGVER kernel + Documentation/ subdirectory: these typically contain kernel-specific + installation notes for some drivers for example. See + /usr/share/doc/linux-doc-PKGVER/Documentation/00-INDEX for a list of what + is contained in each file. Please read the Changes file, as it contains + information about the problems, which may result by upgrading your + kernel. + +Package: linux-headers-PKGVER-ABINUM +Architecture: all +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0) +Provides: linux-headers, linux-headers-2.6 +Description: Header files related to Linux kernel version PKGVER + This package provides kernel header files for version PKGVER, for sites + that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-PKGVER-ABINUM/debian.README.gz for details + +Package: linux-libc-dev +Architecture: i386 amd64 armel +Conflicts: libc6-dev (<< 2.3.2.ds1-6), libc6.1-dev (<< 2.3.2.ds1-6), dvb-dev (<< 1.0.1-6), amd64-libs-dev (<= 1.1), linux-kernel-headers +Replaces: libc6-dev (<< 2.3.2.ds1-6), libc6.1-dev (<< 2.3.2.ds1-6), dvb-dev (<< 1.0.1-6), linux-kernel-headers +Provides: linux-kernel-headers +Description: Linux Kernel Headers for development + This package provides headers from the Linux kernel. These headers + are used by the installed headers for GNU glibc and other system + libraries. They are NOT meant to be used to build third-party modules for + your kernel. Use linux-headers-* packages for that. --- linux-2.6.27.orig/debian/copyright +++ linux-2.6.27/debian/copyright @@ -0,0 +1,30 @@ +This is the Ubuntu prepackaged version of the Linux kernel. +Linux was written by Linus Torvalds +and others. + +This package was put together by the Ubuntu Kernel Team, from +sources retrieved from upstream linux git. +The sources may be found at most Linux ftp sites, including +ftp://ftp.kernel.org/pub/linux/kernel/ + +This package is currently maintained by the +Ubuntu Kernel Team + +Linux is copyrighted by Linus Torvalds and others. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + +On Ubuntu Linux systems, the complete text of the GNU General +Public License v2 can be found in `/usr/share/common-licenses/GPL-2'. --- linux-2.6.27.orig/debian/control.stub +++ linux-2.6.27/debian/control.stub @@ -0,0 +1,420 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.6.1 +Build-Depends: debhelper (>= 3), module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [!armel] +Build-Depends-Indep: xmlto, docbook-utils, gs, transfig, bzip2, sharutils +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-intrepid + +Package: linux-source-2.6.27 +Architecture: all +Section: devel +Priority: optional +Provides: linux-source, linux-source-2.6 +Depends: binutils, bzip2, coreutils | fileutils (>= 4.0) +Recommends: libc-dev, gcc, make +Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev +Description: Linux kernel source for version 2.6.27 with Ubuntu patches + This package provides the source code for the Linux kernel version + 2.6.27. + . + This package is mainly meant for other packages to use, in order to build + custom flavours. + . + If you wish to use this package to create a custom Linux kernel, then it + is suggested that you investigate the package kernel-package, which has + been designed to ease the task of creating kernel image packages. + . + If you are simply trying to build third-party modules for your kernel, + you do not want this package. Install the appropriate linux-headers + package instead. + +Package: linux-doc-2.6.27 +Architecture: all +Section: doc +Priority: optional +Provides: linux-doc-2.6 +Conflicts: linux-doc-2.6 +Replaces: linux-doc-2.6 +Depends: coreutils | fileutils (>= 4.0) +Description: Linux kernel specific documentation for version 2.6.27 + This package provides the various readme's in the 2.6.27 kernel + Documentation/ subdirectory: these typically contain kernel-specific + installation notes for some drivers for example. See + /usr/share/doc/linux-doc-2.6.27/Documentation/00-INDEX for a list of what + is contained in each file. Please read the Changes file, as it contains + information about the problems, which may result by upgrading your + kernel. + +Package: linux-headers-2.6.27-9 +Architecture: all +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0) +Provides: linux-headers, linux-headers-2.6 +Description: Header files related to Linux kernel version 2.6.27 + This package provides kernel header files for version 2.6.27, for sites + that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details + +Package: linux-libc-dev +Architecture: i386 amd64 armel +Conflicts: libc6-dev (<< 2.3.2.ds1-6), libc6.1-dev (<< 2.3.2.ds1-6), dvb-dev (<< 1.0.1-6), amd64-libs-dev (<= 1.1), linux-kernel-headers +Replaces: libc6-dev (<< 2.3.2.ds1-6), libc6.1-dev (<< 2.3.2.ds1-6), dvb-dev (<< 1.0.1-6), linux-kernel-headers +Provides: linux-kernel-headers +Description: Linux Kernel Headers for development + This package provides headers from the Linux kernel. These headers + are used by the installed headers for GNU glibc and other system + libraries. They are NOT meant to be used to build third-party modules for + your kernel. Use linux-headers-* packages for that. + +Package: linux-image-2.6.27-9-generic +Architecture: i386 amd64 +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: lilo (>= 19.1) | grub +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.27 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward desktop systems. + . + You likely do not want to install this package directly. Instead, install + the linux-generic meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on x86/x86_64 + This package provides kernel header files for version 2.6.27 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on x86/x86_64 + This package provides a kernel debug image for version 2.6.27 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-iop32x +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on IOP32x-based systems + This package contains the Linux kernel image for version 2.6.27 on + IOP32x-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports IOP32x processors. + . + Thecus N2100, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-iop32x meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-iop32x +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on IOP32x-based systems + This package provides kernel header files for version 2.6.27 on + IOP32x-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-iop32x +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on IOP32x-based systems + This package provides a kernel debug image for version 2.6.27 on + IOP32x-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-ixp4xx +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on IXP4xx-based systems + This package contains the Linux kernel image for version 2.6.27 on + IXP4xx-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports IXP4xx processors. + . + Linksys NSLU2, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-ixp4xx meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-ixp4xx +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on IXP4xx-based systems + This package provides kernel header files for version 2.6.27 on + IXP4xx-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-ixp4xx +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on IXP4xx-based systems + This package provides a kernel debug image for version 2.6.27 on + IXP4xx-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-orion5x +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on Orion5x-based systems + This package contains the Linux kernel image for version 2.6.27 on + Orion5x-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Orion 5181, 5182 and 5281 processors. + . + QNAP TS-109/TS-209, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-orion5x meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-orion5x +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on Orion5x-based systems + This package provides kernel header files for version 2.6.27 on + Orion5x-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-orion5x +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on Orion5x-based systems + This package provides a kernel debug image for version 2.6.27 on + Orion5x-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-server +Architecture: i386 amd64 +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9 +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: lilo (>= 19.1) | grub +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.27 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Server processors. + . + Geared toward server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-server meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-server +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on x86/x86_64 + This package provides kernel header files for version 2.6.27 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-server +Architecture: i386 amd64 +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on x86/x86_64 + This package provides a kernel debug image for version 2.6.27 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-versatile +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on Versatile-based systems + This package contains the Linux kernel image for version 2.6.27 on + Versatile-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Versatile processors. + . + PB, AB, Qemu, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-versatile meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-versatile +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on Versatile-based systems + This package provides kernel header files for version 2.6.27 on + Versatile-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-versatile +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on Versatile-based systems + This package provides a kernel debug image for version 2.6.27 on + Versatile-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-virtual +Architecture: i386 amd64 +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1), linux-image-2.6.27-9-server +Recommends: lilo (>= 19.1) | grub +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.27 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Virtual processors. + . + Geared toward virtual machine guests. + . + You likely do not want to install this package directly. Instead, install + the linux-virtual meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. --- linux-2.6.27.orig/debian/changelog.historical +++ linux-2.6.27/debian/changelog.historical @@ -0,0 +1,5745 @@ +linux (2.6.24-19.33) UNRELEASED; urgency=low + + CHANGELOG: Do not edit directly. Autogenerated at release. + CHANGELOG: Use the printchanges target to see the curent changes. + CHANGELOG: Use the insertchanges target to create the final log. + + -- Tim Gardner Sun, 04 May 2008 20:22:21 -0600 + +linux (2.6.24-18.32) hardy-security; urgency=low + + * CVE-2007-6694: [POWERPC] CHRP: Fix possible NULL pointer dereference + * fix SMP ordering hole in fcntl_setlk() (CVE-2008-1669) + * Fix dnotify/close race (CVE-2008-1375) + * tehuti: check register size (CVE-2008-1675) + * tehuti: move ioctl perm check closer to function start (CVE-2008-1675) + + -- Ben Collins Mon, 19 May 2008 16:50:11 +0000 + +linux (2.6.24-17.31) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: Fix mutex in the toshiba_acpi driver + * rt: Updated configuration files + + [Ben Collins] + + * build: Fix revert detection in git-ubuntu-log + * SAUCE: Re-add eeprom_bad_csum_allow module-param + - LP: #60388 + + [Stefan Bader] + + * Pulled updates to openvz custom build. Fixes openvz 'refuses to boot' problem. + - LP: #210672 + * sched: retain vruntime, fix delayed key events when CONFIG_FAIR_GROUP_SCHED. + - LP: #218516 + * UBUNTU: SAUCE: Add blacklist support to fix Belkin bluetooth dongle. + - LP: #140511 + + [Tim Gardner] + + * Enable CONFIG_ISCSI_TCP for -virtual + - LP: #218215 + * build: Add fancontrol modules to powerpc64-smp debian installer + * Fix Xen Dom0/DomU bridging + - LP: #218126 + * TSC Clocksource can cause hangs and time jumps + - LP: #221351 + * Kernel should use CONFIG_FAIR_CGROUP_SCHED. Fixes high load issues + with pulseaudio. + - LP: #188226 + + [Upstream Kernel Changes] + + * KVM: MMU: prepopulate guest pages after write-protecting + - LP: #221032 + + -- Tim Gardner Fri, 11 Apr 2008 07:59:10 -0600 + +linux (2.6.24-16.30) hardy; urgency=low + + * Fix amd64/i386 ABI and module check FTBS by creating an ignore + and ignore.modules in the ABI directory. + + -- Tim Gardner Wed, 09 Apr 2008 21:58:25 -0600 + +linux (2.6.24-16.29) hardy; urgency=low + + [Stephan Bader] + + * UBUNTU: SAUCE: mmc: Increase power_up deleay to fix TI readers + + [Alessio Igor Bogani] + + * rt: Updated configuration files + + [Chuck Short] + + * Xen updates for vitrio changes. + + [Tim Gardner] + + * openvz updates for vitrio changes. + + -- Tim Gardner Tue, 08 Apr 2008 21:48:16 -0600 + +linux (2.6.24-16.28) hardy; urgency=low + + [Tim Gardner] + + * Revert "UBUNTU: x86: tsc prevent time going backwards" + + [Kees Cook] + + * AppArmor: implement mmap_min_addr check as done in mainline. + + [Soren Hansen] + + * Bring our virtio code up to date with 2.6.25-rc7 + + [Upstream Kernel Changes] + + * Ubuntu: Revert all our virtio changes + * lguest: Reboot support + * lguest: adapt launcher to per-cpuness + * virtio: Implement skb_partial_csum_set, for setting partial csums on + untrusted packets. + * virtio: simplify config mechanism. + * virtio: explicit enable_cb/disable_cb rather than callback return. + * virtio: configuration change callback + * virtio: Fix vring_init/vring_size to take unsigned long + * virtio: clarify NO_NOTIFY flag usage + * virtio: remove unused id field from struct virtio_blk_outhdr + * virtio: Net header needs hdr_len + * virtio: Tweak virtio_net defines + * virtio: populate network rings in the probe routine, not open + * virtio: reset function + * virtio: handle interrupts after callbacks turned off + * virtio: Use the sg_phys convenience function. + * virtio: Allow virtio to be modular and used by modules + * virtnet: remove double ether_setup + * virtio: flush buffers on open + * virtio: free transmit skbs when notified, not on next xmit. + * virtio_net: parametrize the napi_weight for virtio receive queue. + * virtio_blk: provide getgeo + * virtio_blk: Dont waste major numbers + * virtio_blk: implement naming for vda-vdz,vdaa-vdzz,vdaaa-vdzzz + * virtio: PCI device + * virtio: Use PCI revision field to indicate virtio PCI ABI version + * virtio: balloon driver + * virtio net: fix oops on interface-up + * virtio: add missing #include + * virtio: fix race in enable_cb + * virtio: handle > 2 billion page balloon targets + * virtio_net: Fix oops on early interrupts - introduced by virtio reset + code + * lguest: Do not append space to guests kernel command line + * virtio: Use spin_lock_irqsave/restore for virtio-pci + * virtio: Fix sysfs bits to have proper block symlink + * virtio: Enable netpoll interface for netconsole logging + * virtio_pci: unregister virtio device at device remove + * lguest: Add puppies which where previously missing. + * lguest: lguest.txt documentation fix + * lguest: Don't need comment terminator before disk section. + * virtio_pci iomem annotations + * virtio_net: remove overzealous printk + * virtio: remove overzealous BUG_ON. + + -- Tim Gardner Tue, 08 Apr 2008 11:53:49 -0600 + +linux (2.6.24-15.27) hardy; urgency=low + + [Alan Stern] + + * usb-storage: don't access beyond the end of the sg buffer + - LP: #204922 + + [Mario Limonciello] + + * Enable Reset and SCO workaround on Dell 410 BT adapter + + [Tim Gardner] + + * Enable CONFIG_E1000 in the i386 virtual image. + - LP: #205646 + + [Thomas Gleixner] + + * x86: tsc prevent time going backwards + + [Matthew Garrett] + + * Fix framebuffer fonts on non-x86 platforms + + -- Tim Gardner Fri, 04 Apr 2008 08:14:49 -0600 + +linux (2.6.24-15.26) hardy; urgency=low + + [Colin Ian King] + + * airprime.c supports more devices + - LP: #208250 + + [Kees Cook] + + * AppArmor: get latest batch of upstream fixes into Hardy (svn 1160) + + [Stefan Bader] + + * ACPI: fix boot oops regression in kernel + - LP: #207014 + + [Tim Gardner] + + * Enable CGROUPS for non x86/x86_64 arches, all flavours. + - LP: #188226 + + -- Tim Gardner Thu, 03 Apr 2008 07:00:29 -0600 + +linux (2.6.24-14.25) hardy; urgency=low + + [Mario Limonciello] + + * Resolve sky2 race condition leading to failed suspends + - LP: #210877 + + [Tim Gardner] + + * Copy drivers/media internal header files into header + package for external LUM compilation. This paves the + way for LP #202065. + + -- Tim Gardner Wed, 02 Apr 2008 08:28:32 -0600 + +linux (2.6.24-14.24) hardy; urgency=low + + [Amit Kucheria] + + * LPIA: Update from moblin + * LPIA: Fix reboot problem after S3/S4 + * LPIA: Integrate latest Dabney thermal patches + * LPIA: Change-umd_dbg-debug-level-to-KERN_INFO + * LPIA: Compile modules into kernel to save on boot time + * LPIA: lots of Dabney CONFIG options dissapeared + * LPIA: Purge nonexistent config options + + [Jay Chetty] + + * UBUNTU:USBC:Integrated USBC 2.0.0.32L.0009 + + [Misha Zhilin] + + * USB: ehci: handle large bulk URBs correctly (again) + - LP: #204857 + + [Tim Gardner] + + * frame buffer regression - screen blank except for blinking cursor after + fbcon vtswitch + - LP: #201591 + * Blacklist Bluetooth Dell Wireless 370 for SCO MTU + - LP: #209715 + * Set CONFIG_FAIR_CGROUP_SCHED for server flavours. + - LP: #188226 + * Add DMI IO_DELAY support. + - LP: #200057 + + -- Tim Gardner Mon, 31 Mar 2008 11:19:49 -0600 + +linux (2.6.24-13.23) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: Updated configuration files + + [Ben Collins] + + * openvz: New custom flavour for OpenVZ + * config: Disable IDE AMD driver in favor of PATA version + - LP: #181561 + * config: Disable IDE VIA driver in favor of PATA version + - LP: #181561 + * drivers/video: Restore gutsy backlight dimming behavior + - LP: #205261 + * build/config: Enable CONFIG_CIFS_WEAK_PW_HASH + - LP: #202445 + + [Colin Ian King] + + * SAUCE: Add support for version 4 of Chelsio NICs in cxgb3 driver + - LP: #201893 + + [Kees Cook] + + * AppArmor: re-add missing "type" field in syslog reports. + - LP: #202888 + * kvm: reset TSS on x86_64 to avoid ioperm bitmap corruption + - LP: #144900 + + [Stefan Bader] + + * USB: EHCI: add separate IAA watchdog timer + - LP: #198619 + * SAUCE: Always use SCO protocol (disable eSCO support) + - LP: #39414 + * PM: Introduce PM_EVENT_HIBERNATE callback state + - LP: #201086 + + [Tim Gardner] + + * Disable DRM suspend/resume on pre-915 Intel chips + - LP: #207496 + * frame buffer regression - screen blank except for blinking cursor after fbcon + vtswitch + - LP: #201591 + + -- Tim Gardner Wed, 19 Mar 2008 10:05:05 -0400 + +linux (2.6.24-12.22) hardy; urgency=low + + [Ben Collins] + + * custom/rt: Disable toshiba_acpi, since it isn't compatible + + -- Ben Collins Wed, 12 Mar 2008 14:38:59 -0400 + +linux (2.6.24-12.21) hardy; urgency=low + + [Ben Collins] + + * build: Fix vesafb module inclusion into initrd subdir + - LP: #129910 + * net/bluetooth: POWERBOOK => APPLE, fix for apple keyboard patch + * custom/xen: Remove asix portion of xen patch, breaks driver + - LP: #199296 + + [Colin Ian King] + + * SAUCE: fix Udma not fully available in Acer 1694 Wlmi + - LP: #187121 + * SAUCE: Update toshiba_acpi.c to version 0.19a + - LP: #77026 + + [Stefan Bader] + + * x86: Clear DF before calling signal handler + * Enable FN key on Apple aluminum bluetooth keyboard + - LP: #162083 + + -- Ben Collins Tue, 11 Mar 2008 13:20:49 -0400 + +linux (2.6.24-12.20) hardy; urgency=low + + [Ben Collins] + + * Enable CONFIG_SOUND at least, so alsa build in lum works + - LP: #200338 + + -- Ben Collins Mon, 10 Mar 2008 08:15:00 -0400 + +linux (2.6.24-12.19) hardy; urgency=low + + * Re-upload of -12.18 to fix build failures + * Fixup binary-custom configs + * Fixup xen patch to cope with kvm changes + + [Amit Kucheria] + + * Move Marvell 8686 and 8688 to LUM + * Poulsbo: Sync patches with moblin/ume-hardy tree + * Break if a patch fails to apply + * SAUCE: implement smarter atime updates support + - LP: #199427 + * Enable USB_PERSIST to allow devices with /root on usb to work with + suspend + * Enable USB_PERSIST across the board + + [Ben Collins] + + * build/config: Really fix ide on smp ppc configs + * build/configs: Enable relatime config option for all flavors + * build/abi: Ignore ide-core module for ppc, moved to built-in + + [Colin Ian King] + + * fix reversed logic for bbuild check leads to -j1 default + - LP: #197040 + * Enable IDE_PMAC for powerpc-smp + - LP: #196686 + * Disable CONFIG_USB_OHCI_HCD_SSB + - LP: #182716 + * SAUCE: fix arcmsr + archttp64 calls dma_free_coherent() with irqs + disabled - dmesg filled with warnings + - LP: #194207 + + [Jorge Boncompte [DTI2]] + + * Fix Messed multicast lists after dev_mc_sync/unsync + - LP: #193468 + + [Stefan Bader] + + * Add support for Apple Aluminium keyboards. + - LP: #162083 + * SAUCE: Restore VT fonts on switch + + [Upstream Kernel Changes] + + * [NET]: Messed multicast lists after dev_mc_sync/unsync + * KVM: x86 emulator: add support for group decoding + * KVM: x86 emulator: group decoding for group 1A + * KVM: x86 emulator: Group decoding for group 3 + * KVM: x86 emulator: Group decoding for groups 4 and 5 + * KVM: x86 emulator: add group 7 decoding + * KVM: constify function pointer tables + * KVM: Only x86 has pio + * KVM: x86 emulator: group decoding for group 1 instructions + * KVM: MMU: Decouple mmio from shadow page tables + * KVM: Limit vcpu mmap size to one page on non-x86 + * KVM: VMX: Enable Virtual Processor Identification (VPID) + * KVM: Use CONFIG_PREEMPT_NOTIFIERS around struct preempt_notifier + * KVM: Disable pagefaults during copy_from_user_inatomic() + * KVM: make EFER_RESERVED_BITS configurable for architecture code + * KVM: align valid EFER bits with the features of the host system + * KVM: allow access to EFER in 32bit KVM + * kvm: i386 fix + * KVM: export information about NPT to generic x86 code + * KVM: MMU: make the __nonpaging_map function generic + * KVM: export the load_pdptrs() function to modules + * KVM: MMU: add TDP support to the KVM MMU + * KVM: x86 emulator: Fix 'jmp abs' + * KVM: x86 emulator: fix group 5 decoding + * KVM: Fix kvm_arch_vcpu_ioctl_set_sregs so that set_cr0 works properly + * KVM: Make the supported cpuid list a host property rather than a vm + property + * KVM: emulate access to MSR_IA32_MCG_CTL + * KVM: remove the usage of the mmap_sem for the protection of the memory + slots. + * KVM: SVM: allocate the MSR permission map per VCPU + * KVM: make MMU_DEBUG compile again + * KVM: paravirtualized clocksource: host part + * KVM: Add missing semicolon + * KVM: x86 emulator: add ad_mask static inline + * KVM: x86 emulator: make register_address, address_mask static inlines + * KVM: x86 emulator: make register_address_increment and JMP_REL static + inlines + * KVM: Add API to retrieve the number of supported vcpus per vm + * KVM: Increase vcpu count to 16 + * KVM: Add API for determining the number of supported memory slots + * KVM: Increase the number of user memory slots per vm + * KVM: Add stat counter for hypercalls + * KVM: x86 emulator: fix sparse warnings in x86_emulate.c + * KVM: sparse fixes for kvm/x86.c + * KVM: Implement dummy values for MSR_PERF_STATUS + * KVM: MMU: ignore zapped root pagetables + * KVM: call write_guest_time as soon as we register the paravirt clock + * KVM: MMU: large page support + * KVM: Prefix control register accessors with kvm_ to avoid namespace + pollution + * KVM: Avoid infinite-frequency local apic timer + * KVM: Route irq 0 to vcpu 0 exclusively + * KVM: SVM: add support for Nested Paging + * KVM: SVM: enable LBR virtualization + * KVM: SVM: make iopm_base static + * KVM: SVM: let init_vmcb() take struct vcpu_svm as parameter + * KVM: VMX: fix typo in VMX header define + * KVM: SVM: fix Windows XP 64 bit installation crash + * KVM: VMX: Fix invalid opcode of VPID + * KVM: VMX: Handle machines without EFER + * KVM: move alloc_apic_access_page() outside of non-preemptable region + * KVM: VMX: unifdef the EFER specific code + * KVM: SVM: move feature detection to hardware setup code + * KVM: Export include/linux/kvm.h only if $ARCH actually supports KVM + * dlm: fix rcom_names message to self + * virtio: Net header needs hdr_len + + -- Tim Gardner Mon, 03 Mar 2008 07:07:16 -0700 + +linux (2.6.24-11.17) hardy; urgency=low + + [Alan Cox] + + * Pull in fixes for pata_it821x. + - LP: #106931 + + [Alessio Igor Bogani] + + * rt: Synchronized with upstream (2.6.24.3-rt3) + * rt: Updated configuration files + + [Amit Kucheria] + + * Add AGP support for Radeon Mobility 9000 chipset + - LP: #178634 + * Bluetooth: SCO flow control to enable bluetooth headsets + + [Ben Collins] + + * binary: Include vesafs in initrd subdir, should fix vga= usage + + [Colin Ian King] + + * AMD SB700 south bridge support patches + - LP: #195354 + * BCM4311 Revision 2 fix + - LP: #184600 + + [Mauro Carvalho Chehab] + + * V4L/DVB (6753): Fix vivi to support non-zero minor node + + [Tim Gardner] + + * Merged 2.6.24.3 + * Add atl1 to d-i bits. + - LP: #159561 + * SAUCE: Add xpad support for RedOctane Guitar Hero + - LP: #196745 + + [Upstream Kernel Changes] + + * DVB: cx23885: add missing subsystem ID for Hauppauge HVR1800 Retail + * slab: fix bootstrap on memoryless node + * vm audit: add VM_DONTEXPAND to mmap for drivers that need it + (CVE-2008-0007) + * USB: keyspan: Fix oops + * usb gadget: fix fsl_usb2_udc potential OOPS + * USB: CP2101 New Device IDs + * USB: add support for 4348:5523 WinChipHead USB->RS 232 adapter + * USB: Sierra - Add support for Aircard 881U + * USB: Adding YC Cable USB Serial device to pl2303 + * USB: sierra driver - add devices + * USB: ftdi_sio - enabling multiple ELV devices, adding EM1010PC + * USB: ftdi-sio: Patch to add vendor/device id for ATK_16IC CCD + * USB: sierra: add support for Onda H600/Zte MF330 datacard to USB Driver + for Sierra Wireless + * USB: remove duplicate entry in Option driver and Pl2303 driver for + Huawei modem + * USB: pl2303: add support for RATOC REX-USB60F + * USB: ftdi driver - add support for optical probe device + * USB: use GFP_NOIO in reset path + * USB: Variant of the Dell Wireless 5520 driver + * USB: storage: Add unusual_dev for HP r707 + * USB: fix usbtest halt check on big endian systems + * USB: handle idVendor of 0x0000 + * USB: Fix usb_serial_driver structure for Kobil cardreader driver. + * forcedeth: mac address mcp77/79 + * lockdep: annotate epoll + * sys_remap_file_pages: fix ->vm_file accounting + * PCI: Fix fakephp deadlock + * ACPI: update ACPI blacklist + * x86: restore correct module name for apm + * sky2: restore multicast addresses after recovery + * sky2: fix for WOL on some devices + * b43: Fix suspend/resume + * b43: Drop packets we are not able to encrypt + * b43: Fix dma-slot resource leakage + * b43legacy: fix PIO crash + * b43legacy: fix suspend/resume + * b43legacy: drop packets we are not able to encrypt + * b43legacy: fix DMA slot resource leakage + * selinux: fix labeling of /proc/net inodes + * b43: Reject new firmware early + * sched: let +nice tasks have smaller impact + * sched: fix high wake up latencies with FAIR_USER_SCHED + * fix writev regression: pan hanging unkillable and un-straceable + * Driver core: Revert "Fix Firmware class name collision" + * drm: the drm really should call pci_set_master.. + * splice: missing user pointer access verification (CVE-2008-0009/10) + * Linux 2.6.24.1 + * splice: fix user pointer access in get_iovec_page_array() + * Linux 2.6.24.2 + * ACPI: video: Rationalise ACPI backlight implementation + * ACPI: video: Ignore ACPI video devices that aren't present in hardware + * SPARC/SPARC64: Fix usage of .section .sched.text in assembler code. + * NETFILTER: nf_conntrack_tcp: conntrack reopening fix + * NFS: Fix a potential file corruption issue when writing + * inotify: fix check for one-shot watches before destroying them + * hugetlb: add locking for overcommit sysctl + * XFS: Fix oops in xfs_file_readdir() + * Fix dl2k constants + * SCSI: sd: handle bad lba in sense information + * TCP: Fix a bug in strategy_allowed_congestion_control + * TC: oops in em_meta + * SELinux: Fix double free in selinux_netlbl_sock_setsid() + * PKT_SCHED: ematch: oops from uninitialized variable (resend) + * NET: Add if_addrlabel.h to sanitized headers. + * IPV4: fib_trie: apply fixes from fib_hash + * IPV4: fib: fix route replacement, fib_info is shared + * IPCOMP: Fix reception of incompressible packets + * IPCOMP: Fetch nexthdr before ipch is destroyed + * INET_DIAG: Fix inet_diag_lock_handler error path. + * INET: Prevent out-of-sync truesize on ip_fragment slow path + * BLUETOOTH: Add conn add/del workqueues to avoid connection fail. + * AUDIT: Increase skb->truesize in audit_expand + * Be more robust about bad arguments in get_user_pages() + * Disable G5 NAP mode during SMU commands on U3 + * hrtimer: fix *rmtp handling in hrtimer_nanosleep() + * hrtimer: fix *rmtp/restarts handling in compat_sys_nanosleep() + * SLUB: Deal with annoying gcc warning on kfree() + * hrtimer: check relative timeouts for overflow + * hrtimer: catch expired CLOCK_REALTIME timers early + * genirq: do not leave interupts enabled on free_irq + * S390: Fix futex_atomic_cmpxchg_std inline assembly. + * USB: fix pm counter leak in usblp + * SCSI: gdth: scan for scsi devices + * PCMCIA: Fix station address detection in smc + * POWERPC: Revert chrp_pci_fixup_vt8231_ata devinit to fix libata on + pegasos + * bonding: fix NULL pointer deref in startup processing + * x86_64: CPA, fix cache attribute inconsistency bug + * Linux 2.6.24.3 + + -- Tim Gardner Mon, 25 Feb 2008 12:28:13 -0700 + +linux (2.6.24-10.16) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: Synchronized with upstream (2.6.24.2-rt2) + * rt: Updated configuration files + + [Eric Piel] + + * SAUCE: ACPI: Allow custom DSDT tables to be loaded from initramfs + Amit Kucheria consolidated the DSDT patch with another fix that + ifdefs symbols required when BLK_DEV_INITR is disabled. + + [Stefan Bader] + + * Add Optiarc DVD drive to audio quirks list. + - LP: #186664 + * Update drm and i915 drm driver to fix suspend issues. + - LP: #189260 + + [Tim Gardner] + + * Fix FTBS without BLK_DEV_INITRD + - LP: #193507 + * 64 bit CPA cache attribute bug + - LP: #193736 + * Implemented default EDD control + + [Upstream Kernel Changes] + + * bonding: fix NULL pointer deref in startup processing + * dlm: bind connections from known local address when using TCP + * dlm: proper prototypes + * dlm: don't print common non-errors + * dlm: use dlm prefix on alloc and free functions + * dlm: close othercons + * dlm: align midcomms message buffer + * dlm: swap bytes for rcom lock reply + * dlm: use fixed errno values in messages + * dlm: clear ast_type when removing from astqueue + * dlm: recover locks waiting for overlap replies + * dlm: another call to confirm_master in receive_request_reply + * dlm: reject messages from non-members + * dlm: validate messages before processing + * dlm: reject normal unlock when lock is waiting for lookup + * dlm: limit dir lookup loop + * dlm: fix possible use-after-free + * dlm: change error message to debug + * dlm: keep cached master rsbs during recovery + * dlm: Sanity check namelen before copying it + * dlm: clean ups + * dlm: static initialization improvements + * dlm: use proper C for dlm/requestqueue stuff (and fix alignment bug) + * dlm: dlm_process_incoming_buffer() fixes + * dlm: do not byteswap rcom_lock + * dlm: do not byteswap rcom_config + * dlm: use proper type for ->ls_recover_buf + * dlm: missing length check in check_config() + * dlm: validate data in dlm_recover_directory() + * dlm: verify that places expecting rcom_lock have packet long enough + * dlm: receive_rcom_lock_args() overflow check + * dlm: make find_rsb() fail gracefully when namelen is too large + * dlm: fix overflows when copying from ->m_extra to lvb + * dlm: fix dlm_dir_lookup() handling of too long names + * dlm: dlm/user.c input validation fixes + * dlm: proper types for asts and basts + * dlm: eliminate astparam type casting + * dlm: add __init and __exit marks to init and exit functions + * virtio: Use PCI revision field to indicate virtio PCI ABI version + + -- Tim Gardner Tue, 19 Feb 2008 09:57:18 -0700 + +linux (2.6.24-9.15) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: Fix FTBS + * rt: Updated configuration files + + [Tim Gardner] + + * SAUCE: make /dev/kmem a config option + * SAUCE: x86: introduce /dev/mem restrictions with a config option + * Fixed CGROUP FTBS caused by AppArmor patch. + * Enabled CGROUP and CPUSETS for server flavor. + - LP: #182434 + + [Colin King] + + * Turn on /proc/acpi/alarm for x86_64 (amd64) + - LP: #186297 + + [Upstream Kernel Changes] + + * Ubuntu: LatencyTOP infrastructure patch + + -- Tim Gardner Thu, 14 Feb 2008 13:34:55 -0700 + +linux (2.6.24-8.14) hardy; urgency=low + + [cking] + + * Support Novatel U727 EVDO modem: Add pid and vid to + drivers/usb/serial/airprime.c + - LP: #150996 + * Enable speedstep for sonoma processors. + - LP: #132271 + + [Stefan Bader] + + * SAUCE: Export dm_disk function of device-mapper + + -- Tim Gardner Wed, 13 Feb 2008 21:47:18 -0700 + +linux (2.6.24-8.13) hardy; urgency=low + + [Soren Hansen] + + * Add missing iscsi modules to kernel udebs + + [Stefan Bader] + + * Lower message level for PCI memory and I/O allocation. + + [Tim Gardner] + + * Enabled IP_ADVANCED_ROUTER and IP_MULTIPLE_TABLES in sparc, hppa + - LP: #189560 + * Compile RealTek 8139 using PIO method. + - LP: #90271 + * Add WD WD800ADFS NCQ horkage quirk support. + - LP: #147858 + + [Upstream Kernel Changes] + + * Introduce WEXT scan capabilities + * DVB: cx23885: add missing subsystem ID for Hauppauge HVR1800 Retail + * slab: fix bootstrap on memoryless node + * vm audit: add VM_DONTEXPAND to mmap for drivers that need it + (CVE-2008-0007) + * USB: keyspan: Fix oops + * usb gadget: fix fsl_usb2_udc potential OOPS + * USB: CP2101 New Device IDs + * USB: add support for 4348:5523 WinChipHead USB->RS 232 adapter + * USB: Sierra - Add support for Aircard 881U + * USB: Adding YC Cable USB Serial device to pl2303 + * USB: sierra driver - add devices + * USB: ftdi_sio - enabling multiple ELV devices, adding EM1010PC + * USB: ftdi-sio: Patch to add vendor/device id for ATK_16IC CCD + * USB: sierra: add support for Onda H600/Zte MF330 datacard to USB Driver + for Sierra Wireless + * USB: remove duplicate entry in Option driver and Pl2303 driver for + Huawei modem + * USB: pl2303: add support for RATOC REX-USB60F + * USB: ftdi driver - add support for optical probe device + * USB: use GFP_NOIO in reset path + * USB: Variant of the Dell Wireless 5520 driver + * USB: storage: Add unusual_dev for HP r707 + * USB: fix usbtest halt check on big endian systems + * USB: handle idVendor of 0x0000 + * forcedeth: mac address mcp77/79 + * lockdep: annotate epoll + * sys_remap_file_pages: fix ->vm_file accounting + * PCI: Fix fakephp deadlock + * ACPI: update ACPI blacklist + * x86: restore correct module name for apm + * sky2: restore multicast addresses after recovery + * sky2: fix for WOL on some devices + * b43: Fix suspend/resume + * b43: Drop packets we are not able to encrypt + * b43: Fix dma-slot resource leakage + * b43legacy: fix PIO crash + * b43legacy: fix suspend/resume + * b43legacy: drop packets we are not able to encrypt + * b43legacy: fix DMA slot resource leakage + * selinux: fix labeling of /proc/net inodes + * b43: Reject new firmware early + * sched: let +nice tasks have smaller impact + * sched: fix high wake up latencies with FAIR_USER_SCHED + * fix writev regression: pan hanging unkillable and un-straceable + * Driver core: Revert "Fix Firmware class name collision" + * drm: the drm really should call pci_set_master.. + * splice: missing user pointer access verification (CVE-2008-0009/10) + * Linux 2.6.24.1 + * splice: fix user pointer access in get_iovec_page_array() + * Linux 2.6.24.2 + + -- Tim Gardner Thu, 07 Feb 2008 06:50:13 -0700 + +linux (2.6.24-7.12) hardy; urgency=low + + [Jay Chetty] + + * Added patch to fix legacy USB interrupt issue + * Enabled Poulsbo PATA udma5 support + * Add touchscreen doubleclick workaround + + [Amit Kucheria] + + * Add AGP support for Radeon Mobility 9000 chipset + - LP: #178634 + + [Soren Hansen] + + * Add virtio modules to the relevant udebs + * Add missing "?" for virtio modules in storage-core-modules + + [Stefan Bader] + + * Added vendor id for Dell 5720 broadband modem + + -- Jay Chetty Wed, 06 Feb 2008 14:13:41 -0800 + +linux (2.6.24-7.11) hardy; urgency=low + + [Jay Chetty] + + * poulsbo: Add a 100ms delay for SiB workaround + + [Tim Gardner] + + * -6.10 should have been an ABI bump, but due to incomplete build testing + went undetected. + + -- Tim Gardner Mon, 04 Feb 2008 19:13:52 -0700 + +linux (2.6.24-6.10) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: Synced with upstream, removed old kvm related patches and updated + configurations files. + + [Chuck Short] + + * SAUCE: Enable Xen + + [Soren Hansen] + + * Update kvm driver to kvm-60. + * Added CONFIG_ARCH_SUPPORTS_KVM=y for lpia, i386, and amd64 + * Add rtl8139 driver to -virtual flavour + + [Stefan Bader] + + * Fix usb_serial_driver structure for Kobil cardreader driver. + - LP: #183109 + * Lower warning level of pci resource allocation messages. + - LP: #159241 + + [Tim Gardner] + + * Enabled CONFIG_BLK_DEV_IDE_PMAC + - LP: #185862 + * Add virtio config options to lpiacompat. + * SAUCE: Export symbols for aufs (in lum). + * Enabled Xen + + [Upstream Kernel Changes] + + * KVM: mmu: add missing dirty page tracking cases + * KVM: Move virtualization deactivation from CPU_DEAD state to + CPU_DOWN_PREPARE + * KVM: Cosmetics + * KVM: vmx: hack set_cr0_no_modeswitch() to actually do modeswitch + * KVM: Use ARRAY_SIZE macro instead of manual calculation. + * KVM: Use page_private()/set_page_private() apis + * KVM: add MSR based hypercall API + * KVM: Add host hypercall support for vmx + * KVM: Add hypercall host support for svm + * KVM: Wire up hypercall handlers to a central arch-independent location + * KVM: svm: init cr0 with the wp bit set + * KVM: SVM: intercept SMI to handle it at host level + * KVM: More 0 -> NULL conversions + * kvm, dirty pages log: adding some calls to mark_page_dirty() + * KVM: Add internal filesystem for generating inodes + * KVM: Create an inode per virtual machine + * KVM: Rename some kvm_dev_ioctl_*() functions to kvm_vm_ioctl_*() + * KVM: Move kvm_vm_ioctl_create_vcpu() around + * KVM: Per-vcpu inodes + * KVM: Bump API version + * .gitignore: ignore emacs backup files (*~) + * kvm: dirty pages log: fix bitmap size/access calculation + * kvm: move do_remove_write_access() up + * kvm: dirty page logging: remove write access permissions when + dirty-page-logging is enabled + * KVM: Add missing calls to mark_page_dirty() + * KVM: Fix dirty page log bitmap size/access calculation + * kvm: move do_remove_write_access() up + * KVM: Remove write access permissions when dirty-page-logging is enabled + * KVM: Fix bogus failure in kvm.ko module initialization + * KVM: Move kvmfs magic number to + * KVM: Unset kvm_arch_ops if arch module loading failed + * KVM: Fix guest register corruption on paravirt hypercall + * KVM: Use the generic skip_emulated_instruction() in hypercall code + * KVM: Use own minor number + * KVM: Fix guest sysenter on vmx + * KVM: Export + * KVM: Fix bogus sign extension in mmu mapping audit + * KVM: MMU: Fix guest writes to nonpae pde + * KVM: MMU: Fix host memory corruption on i386 with >= 4GB ram + * KVM: trivial whitespace fixes + * KVM: always reload segment selectors + * KVM: Remove extraneous guest entry on mmio read + * added KVM_GET_MEM_MAP ioctl to get the memory bitmap for a memory slot + * KVM: Prevent system selectors leaking into guest on real->protected + mode transition on vmx + * KVM: Use a shared page for kernel/user communication when runing a vcpu + * KVM: Do not communicate to userspace through cpu registers during PIO + * KVM: Initialize PIO I/O count + * KVM: Handle cpuid in the kernel instead of punting to userspace + * KVM: Remove the 'emulated' field from the userspace interface + * KVM: Remove minor wart from KVM_CREATE_VCPU ioctl + * KVM: Renumber ioctls + * KVM: Add method to check for backwards-compatible API extensions + * KVM: Allow userspace to process hypercalls which have no kernel handler + * KVM: Fold kvm_run::exit_type into kvm_run::exit_reason + * KVM: Add a special exit reason when exiting due to an interrupt + * KVM: Initialize the apic_base msr on svm too + * KVM: Add guest mode signal mask + * KVM: Allow kernel to select size of mmap() buffer + * KVM: Future-proof argument-less ioctls + * KVM: Avoid guest virtual addresses in string pio userspace interface + * KVM: MMU: Remove unnecessary check for pdptr access + * KVM: MMU: Remove global pte tracking + * KVM: Workaround vmx inability to virtualize the reset state + * KVM: Remove set_cr0_no_modeswitch() arch op + * KVM: Modify guest segments after potentially switching modes + * KVM: Hack real-mode segments on vmx from KVM_SET_SREGS + * KVM: Don't allow the guest to turn off the cpu cache + * KVM: Remove unused and write-only variables + * KVM: Handle writes to MCG_STATUS msr + * KVM: MMU: Fix hugepage pdes mapping same physical address with + different access + * KVM: SVM: Ensure timestamp counter monotonicity + * KVM: Remove unused function + * KVM: Remove debug message + * KVM: x86 emulator: fix bit string operations operand size + * KVM: SVM: enable LBRV virtualization if available + * Add mmu cache clear function + * KVM: Simply gfn_to_page() + * KVM: Add physical memory aliasing feature + * KVM: Add fpu get/set operations + * KVM: Use kernel-standard types + * KVM: Fix overflow bug in overflow detection code + * KVM: Fix memory leak on pio completion + * KVM: Handle partial pae pdptr + * KVM: Fix string pio when count == 0 + * KVM: Use slab caches to allocate mmu data structures + * KVM: Retry sleeping allocation if atomic allocation fails + * KVM: Fix pio completion + * KVM: SVM: Report hardware exit reason to userspace instead of dmesg + * KVM: Handle guest page faults when emulating mmio + * KVM: VMX: Reduce unnecessary saving of host msrs + * KVM: Fix off-by-one when writing to a nonpae guest pde + * KVM: VMX: Don't switch 64-bit msrs for 32-bit guests + * KVM: Fold drivers/kvm/kvm_vmx.h into drivers/kvm/vmx.c + * KVM: VMX: Only save/restore MSR_K6_STAR if necessary + * KVM: Per-vcpu statistics + * KVM: Silence compile warning on i386 + * KVM: Allow passing 64-bit values to the emulated read/write API + * KVM: Lazy FPU support for SVM + * KVM: Fix msr-avoidance regression on Core processors + * KVM: Don't complain about cpu erratum AA15 + * KVM: Document MSR_K6_STAR's special place in the msr index array + * KVM: MMU: Avoid heavy ASSERT at non debug mode. + * KVM: Initialize cr0 to indicate an fpu is present + * KVM: We want asserts on debug builds, not release + * KVM: Avoid unused function warning due to assertion removal + * KVM: VMX: Avoid unnecessary vcpu_load()/vcpu_put() cycles + * KVM: Move need_resched() check to common code + * KVM: VMX: Properly shadow the CR0 register in the vcpu struct + * KVM: VMX: Add lazy FPU support for VT + * KVM: fix an if() condition + * KVM: SVM: Only save/restore MSRs when needed + * KVM: Remove trailing whitespace + * KVM: Remove extraneous guest entry on mmio read + * KVM: Don't require explicit indication of completion of mmio or pio + * KVM: Remove unused 'instruction_length' + * KVM: VMX: Enable io bitmaps to avoid IO port 0x80 VMEXITs + * KVM: SVM: Allow direct guest access to PC debug port + * KVM: Fix RMW mmio handling + * KVM: Assume that writes smaller than 4 bytes are to non-pagetable pages + * KVM: Avoid saving and restoring some host CPU state on lightweight + vmexit + * KVM: Unindent some code + * KVM: Reduce misfirings of the fork detector + * KVM: Be more careful restoring fs on lightweight vmexit + * KVM: Unify kvm_mmu_pre_write() and kvm_mmu_post_write() + * KVM: MMU: Respect nonpae pagetable quadrant when zapping ptes + * KVM: Update shadow pte on write to guest pte + * KVM: Increase mmu shadow cache to 1024 pages + * KVM: Fix potential guest state leak into host + * KVM: Prevent guest fpu state from leaking into the host + * KVM: Move some more msr mangling into vmx_save_host_state() + * KVM: Rationalize exception bitmap usage + * KVM: Consolidate guest fpu activation and deactivation + * KVM: Ensure host cr0.ts is saved + * KVM: Set cr0.mp for guests + * KVM: Implement IA32_EBL_CR_POWERON msr + * KVM: MMU: Simplify kvm_mmu_free_page() a tiny bit + * KVM: MMU: Store shadow page tables as kernel virtual addresses, not + physical + * KVM: VMX: Only reload guest msrs if they are already loaded + * KVM: Avoid corrupting tr in real mode + * KVM: Fix vmx I/O bitmap initialization on highmem systems + * KVM: Remove merge artifact + * KVM: VMX: Use local labels in inline assembly + * KVM: VMX: Handle #SS faults from real mode + * KVM: VMX: Avoid saving and restoring msrs on lightweight vmexit + * KVM: VMX: Compile-fix for 32-bit hosts + * KVM: VMX: Cleanup redundant code in MSR set + * KVM: VMX: Fix a typo which mixes X86_64 and CONFIG_X86_64 + * KVM: VMX: Avoid saving and restoring msr_efer on lightweight vmexit + * KVM: VMX: Remove warnings on i386 + * Use menuconfig objects II - KVM/Virt + * KVM: x86 emulator: implement wbinvd + * KVM: Fix includes + * KVM: Use symbolic constants instead of magic numbers + * KVM: MMU: Use slab caches for shadow pages and their headers + * KVM: MMU: Simplify fetch() a little bit + * KVM: MMU: Move set_pte_common() to pte width dependent code + * KVM: MMU: Pass the guest pde to set_pte_common + * KVM: MMU: Fold fix_read_pf() into set_pte_common() + * KVM: MMU: Fold fix_write_pf() into set_pte_common() + * KVM: Move shadow pte modifications from set_pte/set_pde to + set_pde_common() + * KVM: Make shadow pte updates atomic + * KVM: MMU: Make setting shadow ptes atomic on i386 + * KVM: MMU: Remove cr0.wp tricks + * KVM: MMU: Simpify accessed/dirty/present/nx bit handling + * KVM: MMU: Don't cache guest access bits in the shadow page table + * KVM: MMU: Remove unused large page marker + * KVM: VMX: Fix asm constraint + * KVM: Lazy guest cr3 switching + * KVM: Replace C code with call to ARRAY_SIZE() macro. + * KVM: Remove unnecessary initialization and checks in mark_page_dirty() + * KVM: Fix vcpu freeing for guest smp + * KVM: Fix adding an smp virtual machine to the vm list + * KVM: Enable guest smp + * KVM: Move duplicate halt handling code into kvm_main.c + * KVM: Emulate hlt on real mode for Intel + * KVM: Keep an upper bound of initialized vcpus + * KVM: Flush remote tlbs when reducing shadow pte permissions + * KVM: SVM: Replace memset(, 0, PAGESIZE) with clear_page() + * KVM: VMX: Replace memset(, 0, PAGESIZE) with clear_page() + * KVM: Require a cpu which can set 64-bit values atomically + * KVM: Initialize the BSP bit in the APIC_BASE msr correctly + * KVM: VMX: Ensure vcpu time stamp counter is monotonous + * KVM: Bring local tree in line with origin + * KVM: Implement emulation of "pop reg" instruction (opcode 0x58-0x5f) + * KVM: Implement emulation of instruction "ret" (opcode 0xc3) + * KVM: Adds support for in-kernel mmio handlers + * KVM: VMX: Fix interrupt checking on lightweight exit + * KVM: Add support for in-kernel pio handlers + * KVM: Fix x86 emulator writeback + * KVM: Avoid useless memory write when possible + * KVM: VMX: Reinitialize the real-mode tss when entering real mode + * KVM: MMU: Fix Wrong tlb flush order + * KVM: VMX: Remove unnecessary code in vmx_tlb_flush() + * KVM: SVM: Reliably detect if SVM was disabled by BIOS + * KVM: Remove kvmfs in favor of the anonymous inodes source + * KVM: Clean up #includes + * KVM: Fix svm availability check miscompile on i386 + * HOTPLUG: Add CPU_DYING notifier + * HOTPLUG: Adapt cpuset hotplug callback to CPU_DYING + * HOTPLUG: Adapt thermal throttle to CPU_DYING + * SMP: Implement on_cpu() + * KVM: Keep track of which cpus have virtualization enabled + * KVM: Tune hotplug/suspend IPIs + * KVM: Use CPU_DYING for disabling virtualization + * KVM: MMU: Store nx bit for large page shadows + * KVM: Fix *nopage() in kvm_main.c + * KVM: SMP: Add vcpu_id field in struct vcpu + * KVM - add hypercall nr to kvm_run + * KVM:: Future-proof the exit information union ABI + * KVM: In-kernel string pio write support + * KVM: Fix memory slot management functions for guest smp + * KVM: x86 emulator: implement rdmsr and wrmsr + * KVM: Trivial: /dev/kvm interface is no longer experimental. + * KVM: Trivial: Remove unused struct cpu_user_regs declaration + * KVM: Trivial: Make decode_register() static + * KVM: Trivial: Comment spelling may escape grep + * KVM: Trivial: Avoid hardware_disable predeclaration + * KVM: Trivial: Use standard CR0 flags macros from asm/cpu-features.h + * Use standard CR3 flags, tighten checking + * Use standard CR4 flags, tighten checking + * KVM: Trivial: Use standard BITMAP macros, open-code userspace-exposed + header + * KVM: Set exit_reason to KVM_EXIT_MMIO where run->mmio is initialized. + * KVM: Use standard CR8 flags, and fix TPR definition + * KVM: MMU: Fix oopses with SLUB + * KVM: x86 emulator: fix cmov for writeback changes + * KVM: MMU: Fix cleaning up the shadow page allocation cache + * KVM: Require CONFIG_ANON_INODES + * KVM: x86 emulator: fix faulty check for two-byte opcode + * KVM: Correctly handle writes crossing a page boundary + * KVM: Fix unlikely kvm_create vs decache_vcpus_on_cpu race + * KVM: Hoist kvm_mmu_reload() out of the critical section + * KVM: Fix removal of nx capability from guest cpuid + * KVM: Move gfn_to_page out of kmap/unmap pairs + * KVM: disable writeback for 0x0f 0x01 instructions. + * KVM: VMX: Import some constants of vmcs from IA32 SDM + * KVM: Remove dead code in the cmpxchg instruction emulation + * KVM: load_pdptrs() cleanups + * KVM: Remove arch specific components from the general code + * KVM: Dynamically allocate vcpus + * KVM: VMX: Improve the method of writing vmcs control + * KVM: Use the scheduler preemption notifiers to make kvm preemptible + * KVM: Convert vm lock to a mutex + * KVM: fx_init() needs preemption disabled while it plays with the FPU + state + * KVM: VMX: pass vcpu_vmx internally + * KVM: Remove three magic numbers + * KVM: SVM: de-containization + * KVM: SVM: internal function name cleanup + * KVM: x86 emulator: disable writeback for debug register instructions + * KVM: Change the emulator_{read,write,cmpxchg}_* functions to take a + vcpu + * KVM: Remove kvm_{read,write}_guest() + * KVM: Use kmem cache for allocating vcpus + * KVM: Use alignment properties of vcpu to simplify FPU ops + * KVM: kvm_vm_ioctl_get_dirty_log restore "nothing dirty" optimization + * KVM: VMX: Add cpu consistency check + * KVM: Don't assign vcpu->cr3 if it's invalid: check first, set last + * KVM: Cleanup mark_page_dirty + * KVM: SVM: Make set_msr_interception more reliable + * KVM: Remove redundant alloc_vmcs_cpu declaration + * KVM: Fix defined but not used warning in drivers/kvm/vmx.c + * KVM: Remove stat_set from debugfs + * KVM: Remove unneeded kvm_dev_open and kvm_dev_release functions. + * KVM: Add and use pr_unimpl for standard formatting of unimplemented + features + * KVM: Use kmem_cache_free for kmem_cache_zalloc'ed objects + * KVM: VMX: Remove a duplicated ia32e mode vm entry control + * KVM: Remove useless assignment + * KVM: Cleanup string I/O instruction emulation + * KVM: Clean up kvm_setup_pio() + * KVM: VMX: Don't require cr8 load/store exit capability when running on + 32-bit + * KVM: Close minor race in signal handling + * KVM: Communicate cr8 changes to userspace + * KVM: x86 emulator: implement 'and $imm, %{al|ax|eax}' + * KVM: x86 emulator: implement 'jmp rel' instruction (opcode 0xe9) + * KVM: x86 emulator: Implement 'jmp rel short' instruction (opcode 0xeb) + * KVM: x86 emulator: implement 'push reg' (opcodes 0x50-0x57) + * KVM: VMX: allow rmode_tss_base() to work with >2G of guest memory + * KVM: Avoid calling smp_call_function_single() with interrupts disabled + * KVM: MMU: Fix rare oops on guest context switch + * KVM: Support more memory slots + * KVM: X86 emulator: fix 'push reg' writeback + * KVM: VMX: Split segments reload in vmx_load_host_state() + * KVM: Add support for in-kernel PIC emulation + * KVM: Define and use cr8 access functions + * KVM: Emulate local APIC in kernel + * KVM: In-kernel I/O APIC model + * KVM: Emulate hlt in the kernel + * KVM: Protect in-kernel pio using kvm->lock + * KVM: Add get/set irqchip ioctls for in-kernel PIC live migration + support + * KVM: Bypass irq_pending get/set when using in kernel irqchip + * KVM: in-kernel IOAPIC save and restore support + * KVM: in-kernel LAPIC save and restore support + * KVM: pending irq save/restore + * KVM: VMX: Use shadow TPR/cr8 for 64-bits guests + * KVM: Keep track of missed timer irq injections + * KVM: Migrate lapic hrtimer when vcpu moves to another cpu + * KVM: disable tpr/cr8 sync when in-kernel APIC is used + * KVM: VMX: Fix tpr threshold updating + * KVM: deliver PIC interrupt only to vcpu0 + * KVM: round robin for APIC lowest priority delivery mode + * KVM: enable in-kernel APIC INIT/SIPI handling + * KVM: Set the ET flag in CR0 after initializing FX + * KVM: Remove the unused invlpg member of struct kvm_arch_ops. + * KVM: Clean up unloved invlpg emulation + * KVM: Keep control regs in sync + * KVM: Hoist SVM's get_cs_db_l_bits into core code. + * KVM: Simplify memory allocation + * KVM: Rename kvm_arch_ops to kvm_x86_ops + * KVM: Fix lapic 64-bit division on 32-bit hosts + * KVM: fix apic timer migration when inactive + * KVM: MMU: Don't do GFP_NOWAIT allocations + * KVM: Remove smp_processor_id() in kvm_vcpu_kick() + * KVM: VMX: Move vm entry failure handling to the exit handler + * KVM: Move main vcpu loop into subarch independent code + * KVM: Fix link error to "genapic" + * KVM: VMX: Fix exit qualification width on i386 + * KVM: x86 emulator: push imm8 + * KVM: x86 emulator: call near + * KVM: x86 emulator: pushf + * KVM: Improve emulation failure reporting + * KVM: VMX: Prevent setting CPU_BASED_TPR_SHADOW on i386 host + * KVM: x86 emulator: sort opcodes into ascending order + * KVM: x86 emulator: imlpement jump conditional relative + * KVM: X86 emulator: jump conditional short + * KVM: x86 emulator: lea + * KVM: x86 emulator: jmp abs + * KVM: x86 emulator: fix src, dst value initialization + * KVM: x86 emulator: popf + * KVM: Skip pio instruction when it is emulated, not executed + * KVM: fix PIC interrupt delivery on different APIC conditions + * KVM: Fix kvm_vcpu_ioctl_get_sregs() warning on i386 + * KVM: Remove errant printk() in kvm_vcpu_ioctl_get_sregs() + * KVM: Fix virtualization menu help text + * KVM: x86 emulator: Add vmmcall/vmcall to x86_emulate (v3) + * KVM: Refactor hypercall infrastructure (v3) + * KVM: x86 emulator: remove unused functions + * KVM: x86 emulator: move all x86_emulate_memop() to a structure + * KVM: x86 emulator: move all decoding process to function + x86_decode_insn() + * KVM: emulate_instruction() calls now x86_decode_insn() and + x86_emulate_insn() + * KVM: Call x86_decode_insn() only when needed + * KVM: Fix ioapic level-triggered interrupt redelivery + * KVM: Fix #UD exception delivery + * KVM: VMX: Further reduce efer reloads + * KVM: VMX: Fix build on i386 due to EFER_LMA not defined + * KVM: Fix ioapic.c compilation failure due to missing include + * KVM: x86 emulator: fix merge screwup due to emulator split + * KVM: x85 emulator: Correct inconcistency in between cr2 and ctxt->cr2. + * KVM: Avoid redelivery of edge-triggered irq if it is already in service + * KVM: Implement ioapic irq polarity bit + * KVM: x86 emulator: fix repne/repnz decoding + * KVM: Fix host oops due to guest changing efer + * KVM: Fix ioapic edge-triggered interrupts + * KVM: MMU: Set shadow pte atomically in mmu_pte_write_zap_pte() + * KVM: Allow not-present guest page faults to bypass kvm + * KVM: MMU: Make flooding detection work when guest page faults are + bypassed + * KVM: MMU: Ignore reserved bits in cr3 in non-pae mode + * KVM: x86 emulator: split some decoding into functions for readability + * KVM: x86 emulator: remove _eflags and use directly ctxt->eflags. + * KVM: x86 emulator: Remove no_wb, use dst.type = OP_NONE instead + * KVM: x86_emulator: no writeback for bt + * KVM: apic round robin cleanup + * KVM: Purify x86_decode_insn() error case management + * KVM: x86 emulator: Any legacy prefix after a REX prefix nullifies its + effect + * i386: Expose IOAPIC register definitions even if CONFIG_X86_IO_APIC is + not set + * KVM: x86 emulator: On a pop instruction, don't restore ECX and EIP on + error + * KVM: x86 emulator: remove unused variable + * KVM: VMX: Don't clear the vmcs if the vcpu is not loaded on any + processor + * KVM: VMX: Simplify vcpu_clear() + * KVM: Remove the usage of paeg->private field by rmap + * KVM: x86 emulator: Correct management of REP prefix + * KVM: Add general accessors to read and write guest memory + * KVM: Allow dynamic allocation of the mmu shadow cache size + * KVM: Check I/O APIC indirect index before writing + * KVM: Add kvm_free_lapic() to pair with kvm_create_lapic() + * KVM: Hoist kvm_create_lapic() into kvm_vcpu_init() + * KVM: Remove gratuitous casts from lapic.c + * KVM: CodingStyle cleanup + * KVM: VMX: Handle NMIs before enabling interrupts and preemption + * KVM: Support assigning userspace memory to the guest + * KVM: Export PIC reset for kernel device reset + * KVM: Split IOAPIC reset function and export for kernel RESET + * KVM: VMX: Reset mmu context when entering real mode + * KVM: Replace enum by #define + * KVM: Move x86 msr handling to new files x86.[ch] + * KVM: MMU: Clean up MMU functions to take struct kvm when appropriate + * KVM: MMU: More struct kvm_vcpu -> struct kvm cleanups + * KVM: Move guest pte dirty bit management to the guest pagetable walker + * KVM: MMU: Fix nx access bit for huge pages + * KVM: MMU: Disable write access on clean large pages + * KVM: MMU: Instatiate real-mode shadows as user writable shadows + * KVM: MMU: Move dirty bit updates to a separate function + * KVM: MMU: When updating the dirty bit, inform the mmu about it + * KVM: Portability: split kvm_vcpu_ioctl + * KVM: Restore missing #include + * KVM: Add some \n in ioapic_debug() + * KVM: x86 emulator: implement 'movnti mem, reg' + * KVM: MMU: Call update_dirty_bit() without disabling preemption + * KVM: Move apic timer interrupt backlog processing to common code + * KVM: Move interrupt injection out of interrupt disabled section + * KVM: Rename KVM_TLB_FLUSH to KVM_REQ_TLB_FLUSH + * KVM: VMX: Force vm86 mode if setting flags during real mode + * KVM: MMU: Simplify page table walker + * KVM: Actually move the interrupt injection code out of the critical + section + * KVM: x86 emulator: cmc, clc, cli, sti + * KVM: x86 emulator: use a defined flag definition + * KVM: x86 emulator: fix access registers for instructions with ModR/M + byte and Mod = 3 + * KVM: MMU: Add rmap_next(), a helper for walking kvm rmaps + * KVM: MMU: Keep a reverse mapping of non-writable translations + * KVM: MMU: Make gfn_to_page() always safe + * KVM: Partial swapping of guest memory + * KVM: VMX: Initialize vcpu with preemption enabled + * KVM: Use virtual cpu accounting if available for guest times. + * KVM: Move kvm_guest_exit() after local_irq_enable() + * KVM: MMU: Fix dirty bit pte gpa calculation + * KVM: Allocate userspace memory for older userspace + * KVM: Portability: Split kvm_vcpu into arch dependent and independent + parts (part 1) + * KVM: Fix local apic timer divide by zero + * KVM: Move vmx_vcpu_reset() out of vmx_vcpu_setup() + * KVM: Add a might_sleep() annotation to gfn_to_page() + * KVM: VMX: vmx_vcpu_setup(): remove unused variable. + * KVM: Per-architecture hypercall definitions + * KVM: Use new smp_call_function_mask() in kvm_flush_remote_tlbs() + * KVM: Unmap kernel-allocated memory on slot destruction + * KVM: Export memory slot allocation mechanism + * KVM: Add kernel-internal memory slots + * KVM: Add ioctl to tss address from userspace, + * KVM: x86 emulator: fix 'push imm8' emulation + * KVM: VMX: Let gcc to choose which registers to save (x86_64) + * KVM: VMX: Let gcc to choose which registers to save (i386) + * KVM: SVM: Let gcc to choose which registers to save (x86_64) + * KVM: SVM: Let gcc to choose which registers to save (i386) + * KVM: x86 emulator: invd instruction + * KVM: SVM: Intercept the 'invd' and 'wbinvd' instructions + * KVM: x86 emulator: don't depend on cr2 for mov abs emulation + * KVM: Move page fault processing to common code + * KVM: MMU: Topup the mmu memory preallocation caches before emulating an + insn + * KVM: Portability: Split kvm_vm_ioctl v3 + * KVM: Portability: Move memory segmentation to x86.c + * KVM: Portability: move get/set_apic_base to x86.c + * KVM: Portability: Move control register helper functions to x86.c + * KVM: VMX: Enable memory mapped TPR shadow (FlexPriority) + * KVM: Fix gfn_to_page() acquiring mmap_sem twice + * KVM: Portability: Move kvm_get/set_msr[_common] to x86.c + * KVM: Portability: Move x86 emulation and mmio device hook to x86.c + * KVM: Portability: Move pio emulation functions to x86.c + * KVM: x86 emulator: Extract the common code of SrcReg and DstReg + * KVM: x86 emulator: centralize decoding of one-byte register access + insns + * KVM: Simplify decode_register_operand() calling convention + * KVM: Make mark_page_dirty() work for aliased pages too. + * KVM: x86 emulator: Hoist modrm and abs decoding into separate functions + * KVM: Portability: Make exported debugfs data architecture-specific + * KVM: Portability: Move x86 instruction emulation code to x86.c + * KVM: Portability: Move x86 FPU handling to x86.c + * KVM: Portability: Move x86 vcpu ioctl handlers to x86.c + * KVM: x86 emulator: Move one-byte insns with reg operand into one-byte + section + * KVM: VMX: Fix repeated allocation of apic access page on smp + * KVM: SVM: Fix SMP with kernel apic + * KVM: Add make_page_dirty() to kvm_clear_guest_page() + * KVM: SVM: Defer nmi processing until switch to host state is complete + * KVM: VMX: Avoid reloading host efer on cpus that don't have it + * KVM: VMX: Use vmx to inject real interrupts + * KVM: Go back to atomically injecting interrupts + * KVM: VMX: Comment VMX primary/secondary exec ctl definitions + * KVM: VMX: wbinvd exiting + * KVM: x86 emulator: fix JMP_REL + * KVM: x86 emulator: fix the saving of of the eip value + * KVM: x86 emulator: remove 8 bytes operands emulator for call near + instruction + * KVM: Simplify CPU_TASKS_FROZEN cpu notifier handling + * KVM: add kvm_is_error_hva() + * KVM: introduce gfn_to_hva() + * KVM: Change kvm_{read,write}_guest() to use copy_{from,to}_user() + * KVM: Portability: Move some includes to x86.c + * KVM: Portability: Move kvm_x86_ops to x86.c + * KVM: Portability: Add vcpu and hardware management arch hooks + * KVM: Portability: Combine kvm_init and kvm_init_x86 + * KVM: Portability: Move x86 specific code from kvm_init() to kvm_arch() + * KVM: x86 emulator: modify 'lods', and 'stos' not to depend on CR2 + * KVM: Portability: move KVM_CHECK_EXTENSION + * KVM: VMX: Consolidate register usage in vmx_vcpu_run() + * KVM: Portability: Make kvm_vcpu_ioctl_translate arch dependent + * KVM: x86 emulator: Rename 'cr2' to 'memop' + * KVM: Remove ptr comparisons to 0 + * KVM: Remove __init attributes for kvm_init_debug and kvm_init_msr_list + * KVM: Portability: Add two hooks to handle kvm_create and destroy vm + * KVM: Replace 'light_exits' stat with 'host_state_reload' + * KVM: Add fpu_reload counter + * KVM: Add instruction emulation statistics + * KVM: Extend stats support for VM stats + * KVM: MMU: Add some mmu statistics + * KVM: x86 emulator: Use emulator_write_emulated and not + emulator_write_std + * KVM: Make unloading of FPU state when putting vcpu arch-independent + * KVM: SVM: Disable Lazy FPU optimization + * KVM: Portability: Move kvm_vcpu_ioctl_get_dirty_log to arch-specific + file + * KVM: Portability: MMU initialization and teardown split + * KVM: Portability: Move some macro definitions from kvm.h to x86.h + * KVM: Portability: Move struct kvm_x86_ops definition to x86.h + * KVM: Portability: Move vcpu regs enumeration definition to x86.h + * KVM: Move some static inline functions out from kvm.h into x86.h + * KVM: Portability: Move some function declarations to x86.h + * KVM: VMX: Force seg.base == (seg.sel << 4) in real mode + * KVM: MMU: Change guest pte access to kvm_{read,write}_guest() + * kvm: simplify kvm_clear_guest_page() + * KVM: Add missing #include + * KVM: MMU: Remove unused variable + * KVM: Remove unused "rmap_overflow" variable + * KVM: Correct consistent typo: "destory" -> "destroy" + * KVM: Move misplaced comment + * KVM: Portability: Move kvm_memory_alias to asm/kvm.h + * KVM: Portability: Move x86 pic strutctures + * KVM: Portability: Move kvm_regs to + * KVM: Portability: Move structure lapic_state to + * KVM: Portability: Move kvm_segment & kvm_dtable structure to + + * KVM: Portability: Move kvm_sregs and msr structures to + * KVM: Portability: Move cpuid structures to + * KVM: Export include/asm-x86/kvm.h + * KVM: MMU: Fix potential memory leak with smp real-mode + * KVM: MMU: Selectively set PageDirty when releasing guest memory + * KVM: x86 emulator: retire ->write_std() + * KVM: x86 emulator: prefetch up to 15 bytes of the instruction executed + * KVM: SVM: Fix FPU leak and re-enable lazy FPU switching + * KVM: Recalculate mmu pages needed for every memory region change + * KVM: Portability: Split kvm_set_memory_region() to have an arch + callout + * KVM: Split vcpu creation to avoid vcpu_load() before preemption setup + * KVM: MMU: Implement guest page fault bypass for nonpae + * KVM: Add statistic for remote tlb flushes + * KVM: MMU: Avoid unnecessary remote tlb flushes when guest updates a pte + * KVM: Add parentheses to silence gcc + * KVM: Don't bother the mmu if cr3 load doesn't change cr3 + * KVM: MMU: Code cleanup + * KVM: MMU: Introduce and use gpte_to_gfn() + * KVM: MMU: Move pse36 handling to the guest walker + * KVM: MMU: Remove extra gaddr parameter from set_pte_common() + * KVM: MMU: Remove set_pde() + * KVM: MMU: Adjust page_header_update_slot() to accept a gfn instead of a + gpa + * KVM: MMU: Introduce gfn_to_gpa() + * KVM: MMU: Simplify nonpaging_map() + * KVM: MMU: Remove gva_to_hpa() + * KVM: Remove gpa_to_hpa() + * KVM: MMU: Rename variable of type 'struct kvm_mmu_page *' + * KVM: MMU: Rename 'release_page' + * KVM: Disallow fork() and similar games when using a VM + * KVM: Enhance guest cpuid management + * KVM: Replace private 'struct segment descriptor' by x86's desc_struct + * KVM: Remove segment_descriptor, part 2 + * KVM: Fix compile error on i386 + * KVM: VMX: Read & store IDT_VECTORING_INFO_FIELD + * KVM: Fix faults during injection of real-mode interrupts + * KVM: x86 emulator: Fix instruction fetch cache hit check + * KVM: VMX: Remove the secondary execute control dependency on irqchip + * KVM: Portability: Move unalias_gfn to arch dependent file + * KVM: x86 emulator: Make a distinction between repeat prefixes F3 and F2 + * KVM: x86 emulator: address size and operand size overrides are sticky + * KVM: Remove desc.h include in kvm_main.c + * KVM: Revert segment_descriptor.h removal + * KVM: Remove misleading check for mmio during event injection + * KVM: MMU: mark pages that were inserted to the shadow pages table as + accessed + * KVM: x86 emulator: rename REP_REPE_PREFIX + * KVM: x86 emulator: cmps instruction + * KVM: Add ifdef in irqchip struct for x86 only structures + * KVM: Fix cpuid2 killing 32-bit guests on non-NX machines + * KVM: x86 emulator: Move rep processing before instruction execution + * KVM: x86 emulator: unify two switches + * KVM: x86 emulator: unify four switch statements into two + * KVM: Don't bypass the mmu if in pae and pdptrs changed + * KVM: Portability: Move KVM_INTERRUPT vcpu ioctl to x86.c + * KVM: Correct kvm_init() error paths not freeing bad_pge. + * KVM: Export include/linux/kvm.h only if $ARCH actually supports KVM + * KVM: SVM: Remove KVM specific defines for MSR_EFER + * KVM: Replace kvm_lapic with kvm_vcpu in ioapic/lapic interface + * KVM: Replace dest_Lowest_Prio and dest_Fixed with self-defined macros + * KVM: Extend ioapic code to support iosapic + * KVM: Portability: Move address types to their own header file + * KVM: Portability: Move IO device definitions to its own header file + * KVM: Portability: Stop including x86-specific headers in kvm_main.c + * KVM: Portability: Create kvm_arch_vcpu_runnable() function + * KVM: Convert KVM from ->nopage() to ->fault() + * KVM: MMU: Remove unused prev_shadow_ent variable from fetch() + * KVM: Generalize exception injection mechanism + * KVM: Replace page fault injection by the generalized exception queue + * KVM: Replace #GP injection by the generalized exception queue + * KVM: Use generalized exception queue for injecting #UD + * KVM: x86 emulator: fix eflags preparation for emulation + * KVM: VMX: Avoid exit when setting cr8 if the local apic is in the + kernel + * KVM: SVM: Emulate read/write access to cr8 + * KVM: x86 emulator: Fix stack instructions on 64-bit mode + * KVM: SVM: Trap access to the cr8 register + * KVM: VMX: Fix cr8 exit optimization + * KVM: MMU: Use cmpxchg for pte updates on walk_addr() + * KVM: MMU: Simplify calculation of pte access + * KVM: MMU: Set nx bit correctly on shadow ptes + * KVM: MMU: Move pte access calculation into a helper function + * KVM: MMU: Fix inherited permissions for emulated guest pte updates + * KVM: MMU: No need to pick up nx bit from guest pte + * KVM: MMU: Pass pte dirty flag to set_pte() instead of calculating it + on-site + * KVM: MMU: Remove walker argument to set_pte() + * KVM: MMU: Move set_pte() into guest paging mode independent code + * KVM: MMU: Adjust mmu_set_spte() debug code for gpte removal + * KVM: MMU: Use mmu_set_spte() for real-mode shadows + * KVM: SVM: Exit to userspace if write to cr8 and not using in-kernel + apic + * KVM: SVM: support writing 0 to K8 performance counter control registers + * KVM: MMU: Fix kunmap_atomic() call in cmpxchg_gpte() + * KVM: MMU: Fix SMP shadow instantiation race + * KVM: LAPIC: minor debugging compile fix + * KVM: MMU: emulated cmpxchg8b should be atomic on i386 + * KVM: Fix bad kunmap_atomic() paramerter inm cmpxchg emulation + * KVM: Make cmpxchg emulation compile on i386 + * KVM: Another cmpxchg i386 compile fix + * KVM: Another cmpxchg emulation compile fix + * KVM: Another cmpxchg emulation compile fix + * KVM: Portability: Move kvm{pic,ioapic} accesors to x86 specific code + * KVM: Portability: Introduce kvm_vcpu_arch + * KVM: Portability: Split mmu-related static inline functions to mmu.h + * KVM: Portability: Move kvm_vcpu definition back to kvm.h + * KVM: Portability: Expand the KVM_VCPU_COMM in kvm_vcpu structure. + * KVM: Portability: Move kvm_vcpu_stat to x86.h + * KVM: Portability: Move memslot aliases to new struct kvm_arch + * KVM: Portability: Move mmu-related fields to kvm_arch + * KVM: Portability: move vpic and vioapic to kvm_arch + * KVM: Portability: Move round_robin_prev_vcpu and tss_addr to kvm_arch + * KVM: Portability: Move kvm_vm_stat to x86.h + * KVM: VMX: Add printk_ratelimit in vmx_intr_assist + * KVM: Move arch dependent files to new directory arch/x86/kvm/ + * KVM: Move drivers/kvm/* to virt/kvm/ + * KVM: Fix compile error in asm/kvm_host.h + * KVM: Move irqchip declarations into new ioapic.h and lapic.h + * KVM: Move ioapic code to common directory. + * KVM: Move kvm_vcpu_kick() to x86.c + * KVM: Expose ioapic to ia64 save/restore APIs + * KVM: MMU: Coalesce remote tlb flushes + * KVM: MMU: Add cache miss statistic + * KVM: Print data for unimplemented wrmsr + * KVM: Ensure pages are copied on write + * KVM: MMU: Fix cmpxchg8b emulation on i386 (again) + * KVM: x86 emulator: Add vmmcall/vmcall to x86_emulate (v3) + * KVM: Refactor hypercall infrastructure (v3) + * KVM: x86 emulator: remove unused functions + * KVM: x86 emulator: move all x86_emulate_memop() to a structure + * KVM: x86 emulator: move all decoding process to function + x86_decode_insn() + * KVM: emulate_instruction() calls now x86_decode_insn() and + x86_emulate_insn() + * KVM: Call x86_decode_insn() only when needed + * KVM: VMX: Further reduce efer reloads + * KVM: Allow not-present guest page faults to bypass kvm + * KVM: MMU: Make flooding detection work when guest page faults are + bypassed + * KVM: MMU: Ignore reserved bits in cr3 in non-pae mode + * KVM: x86 emulator: split some decoding into functions for readability + * KVM: x86 emulator: remove _eflags and use directly ctxt->eflags. + * KVM: x86 emulator: Remove no_wb, use dst.type = OP_NONE instead + * KVM: x86_emulator: no writeback for bt + * KVM: Purify x86_decode_insn() error case management + * KVM: x86 emulator: Any legacy prefix after a REX prefix nullifies its + effect + * KVM: VMX: Don't clear the vmcs if the vcpu is not loaded on any + processor + * KVM: VMX: Simplify vcpu_clear() + * KVM: Remove the usage of page->private field by rmap + * KVM: Add general accessors to read and write guest memory + * KVM: Allow dynamic allocation of the mmu shadow cache size + * KVM: Add kvm_free_lapic() to pair with kvm_create_lapic() + * KVM: Hoist kvm_create_lapic() into kvm_vcpu_init() + * KVM: Remove gratuitous casts from lapic.c + * KVM: CodingStyle cleanup + * KVM: Support assigning userspace memory to the guest + * KVM: Move x86 msr handling to new files x86.[ch] + * KVM: MMU: Clean up MMU functions to take struct kvm when appropriate + * KVM: MMU: More struct kvm_vcpu -> struct kvm cleanups + * KVM: Move guest pte dirty bit management to the guest pagetable walker + * KVM: MMU: Fix nx access bit for huge pages + * KVM: MMU: Disable write access on clean large pages + * KVM: MMU: Instantiate real-mode shadows as user writable shadows + * KVM: MMU: Move dirty bit updates to a separate function + * KVM: MMU: When updating the dirty bit, inform the mmu about it + * KVM: Portability: split kvm_vcpu_ioctl + * KVM: apic round robin cleanup + * KVM: Add some \n in ioapic_debug() + * KVM: Move apic timer interrupt backlog processing to common code + * KVM: Rename KVM_TLB_FLUSH to KVM_REQ_TLB_FLUSH + * KVM: x86 emulator: Implement emulation of instruction: inc & dec + * KVM: MMU: Simplify page table walker + * KVM: x86 emulator: cmc, clc, cli, sti + * KVM: MMU: Add rmap_next(), a helper for walking kvm rmaps + * KVM: MMU: Keep a reverse mapping of non-writable translations + * KVM: MMU: Make gfn_to_page() always safe + * KVM: MMU: Partial swapping of guest memory + * KVM: Use virtual cpu accounting if available for guest times. + * KVM: Allocate userspace memory for older userspace + * KVM: Portability: Split kvm_vcpu into arch dependent and independent + parts (part 1) + * KVM: Move vmx_vcpu_reset() out of vmx_vcpu_setup() + * KVM: Add a might_sleep() annotation to gfn_to_page() + * KVM: Export PIC reset for kernel device reset + * KVM: Split IOAPIC reset function and export for kernel RESET + * KVM: Per-architecture hypercall definitions + * KVM: Unmap kernel-allocated memory on slot destruction + * KVM: Export memory slot allocation mechanism + * KVM: Add kernel-internal memory slots + * KVM: Add ioctl to tss address from userspace, + * KVM: VMX: Let gcc to choose which registers to save (x86_64) + * KVM: VMX: Let gcc to choose which registers to save (i386) + * KVM: SVM: Let gcc to choose which registers to save (x86_64) + * KVM: SVM: Let gcc to choose which registers to save (i386) + * KVM: x86 emulator: don't depend on cr2 for mov abs emulation + * KVM: Move page fault processing to common code + * KVM: MMU: Topup the mmu memory preallocation caches before emulating an + insn + * KVM: Portability: Split kvm_vm_ioctl v3 + * KVM: Portability: Move memory segmentation to x86.c + * KVM: Portability: move get/set_apic_base to x86.c + * KVM: Portability: Move control register helper functions to x86.c + * KVM: VMX: Enable memory mapped TPR shadow (FlexPriority) + * KVM: Fix gfn_to_page() acquiring mmap_sem twice + * KVM: Portability: Move kvm_get/set_msr[_common] to x86.c + * KVM: Portability: Move x86 emulation and mmio device hook to x86.c + * KVM: Portability: Move pio emulation functions to x86.c + * KVM: x86 emulator: Extract the common code of SrcReg and DstReg + * KVM: x86 emulator: centralize decoding of one-byte register access + insns + * KVM: Simplify decode_register_operand() calling convention + * KVM: Make mark_page_dirty() work for aliased pages too. + * KVM: x86 emulator: Hoist modrm and abs decoding into separate functions + * KVM: Portability: Make exported debugfs data architecture-specific + * KVM: Portability: Move x86 instruction emulation code to x86.c + * KVM: Portability: Move x86 FPU handling to x86.c + * KVM: Portability: Move x86 vcpu ioctl handlers to x86.c + * KVM: Add make_page_dirty() to kvm_clear_guest_page() + * KVM: VMX: Use vmx to inject real-mode interrupts + * KVM: VMX: Read & store IDT_VECTORING_INFO_FIELD + * KVM: Fix faults during injection of real-mode interrupts + * KVM: VMX: Comment VMX primary/secondary exec ctl definitions + * KVM: VMX: wbinvd exiting + * KVM: x86 emulator: remove 8 bytes operands emulator for call near + instruction + * KVM: Simplify CPU_TASKS_FROZEN cpu notifier handling + * KVM: add kvm_is_error_hva() + * KVM: introduce gfn_to_hva() + * KVM: Change kvm_{read,write}_guest() to use copy_{from,to}_user() + * KVM: Portability: Move some includes to x86.c + * KVM: Portability: Move kvm_x86_ops to x86.c + * KVM: Portability: Add vcpu and hardware management arch hooks + * KVM: Portability: Combine kvm_init and kvm_init_x86 + * KVM: Portability: Move x86 specific code from kvm_init() to kvm_arch() + * KVM: x86 emulator: modify 'lods', and 'stos' not to depend on CR2 + * KVM: Portability: move KVM_CHECK_EXTENSION + * KVM: VMX: Consolidate register usage in vmx_vcpu_run() + * KVM: Portability: Make kvm_vcpu_ioctl_translate arch dependent + * KVM: Remove ptr comparisons to 0 + * KVM: Remove __init attributes for kvm_init_debug and kvm_init_msr_list + * KVM: Portability: Add two hooks to handle kvm_create and destroy vm + * KVM: Replace 'light_exits' stat with 'host_state_reload' + * KVM: Add fpu_reload counter + * KVM: Add instruction emulation statistics + * KVM: Extend stats support for VM stats + * KVM: MMU: Add some mmu statistics + * KVM: Make unloading of FPU state when putting vcpu arch-independent + * KVM: Portability: Move kvm_vcpu_ioctl_get_dirty_log to arch-specific + file + * KVM: Portability: MMU initialization and teardown split + * KVM: Portability: Move some macro definitions from kvm.h to x86.h + * KVM: Portability: Move struct kvm_x86_ops definition to x86.h + * KVM: Portability: Move vcpu regs enumeration definition to x86.h + * KVM: Move some static inline functions out from kvm.h into x86.h + * KVM: Portability: Move some function declarations to x86.h + * KVM: VMX: Force seg.base == (seg.sel << 4) in real mode + * KVM: MMU: Change guest pte access to kvm_{read,write}_guest() + * KVM: Simplify kvm_clear_guest_page() + * KVM: Add missing #include + * KVM: MMU: Remove unused variable + * KVM: Remove unused "rmap_overflow" variable + * KVM: Correct consistent typo: "destory" -> "destroy" + * KVM: Move misplaced comment + * KVM: Portability: Move kvm_memory_alias to asm/kvm.h + * KVM: Portability: Move x86 pic strutctures + * KVM: Portability: Move kvm_regs to + * KVM: Portability: Move structure lapic_state to + * KVM: Portability: Move kvm_segment & kvm_dtable structure to + + * KVM: Portability: Move kvm_sregs and msr structures to + * KVM: Portability: Move cpuid structures to + * KVM: Export include/asm-x86/kvm.h + * KVM: MMU: Fix potential memory leak with smp real-mode + * KVM: MMU: Selectively set PageDirty when releasing guest memory + * KVM: x86 emulator: retire ->write_std() + * KVM: x86 emulator: prefetch up to 15 bytes of the instruction executed + * KVM: Recalculate mmu pages needed for every memory region change + * KVM: Portability: Split kvm_set_memory_region() to have an arch + callout + * KVM: Split vcpu creation to avoid vcpu_load() before preemption setup + * KVM: MMU: Implement guest page fault bypass for nonpae + * KVM: Add statistic for remote tlb flushes + * KVM: MMU: Avoid unnecessary remote tlb flushes when guest updates a pte + * KVM: Don't bother the mmu if cr3 load doesn't change cr3 + * KVM: MMU: Code cleanup + * KVM: MMU: Introduce and use gpte_to_gfn() + * KVM: MMU: Move pse36 handling to the guest walker + * KVM: MMU: Remove extra gaddr parameter from set_pte_common() + * KVM: MMU: Remove set_pde() + * KVM: MMU: Adjust page_header_update_slot() to accept a gfn instead of a + gpa + * KVM: MMU: Introduce gfn_to_gpa() + * KVM: MMU: Simplify nonpaging_map() + * KVM: MMU: Remove gva_to_hpa() + * KVM: Remove gpa_to_hpa() + * KVM: MMU: Rename variables of type 'struct kvm_mmu_page *' + * KVM: MMU: Rename 'release_page' + * KVM: Disallow fork() and similar games when using a VM + * KVM: Enhance guest cpuid management + * KVM: VMX: Remove the secondary execute control dependency on irqchip + * KVM: Portability: Move unalias_gfn to arch dependent file + * KVM: x86 emulator: Make a distinction between repeat prefixes F3 and F2 + * KVM: x86 emulator: address size and operand size overrides are sticky + * KVM: Remove misleading check for mmio during event injection + * KVM: MMU: mark pages that were inserted to the shadow pages table as + accessed + * KVM: x86 emulator: rename REP_REPE_PREFIX + * KVM: x86 emulator: Rename 'cr2' to 'memop' + * KVM: x86 emulator: cmps instruction + * KVM: Add ifdef in irqchip struct for x86 only structures + * KVM: Fix cpuid2 killing 32-bit guests on non-NX machines + * KVM: x86 emulator: Move rep processing before instruction execution + * KVM: x86 emulator: unify two switches + * KVM: x86 emulator: unify four switch statements into two + * KVM: Portability: Move KVM_INTERRUPT vcpu ioctl to x86.c + * KVM: Correct kvm_init() error paths not freeing bad_pge. + * KVM: Export include/linux/kvm.h only if $ARCH actually supports KVM + * KVM: SVM: Remove KVM specific defines for MSR_EFER + * KVM: Replace kvm_lapic with kvm_vcpu in ioapic/lapic interface + * KVM: Replace dest_Lowest_Prio and dest_Fixed with self-defined macros + * KVM: Extend ioapic code to support iosapic + * KVM: Portability: Move address types to their own header file + * KVM: Portability: Move IO device definitions to its own header file + * KVM: Portability: Stop including x86-specific headers in kvm_main.c + * KVM: Portability: Create kvm_arch_vcpu_runnable() function + * KVM: Convert KVM from ->nopage() to ->fault() + * KVM: MMU: Remove unused prev_shadow_ent variable from fetch() + * KVM: Generalize exception injection mechanism + * KVM: Replace page fault injection by the generalized exception queue + * KVM: Replace #GP injection by the generalized exception queue + * KVM: Use generalized exception queue for injecting #UD + * KVM: x86 emulator: fix eflags preparation for emulation + * KVM: VMX: Avoid exit when setting cr8 if the local apic is in the + kernel + * KVM: SVM: Emulate read/write access to cr8 + * KVM: x86 emulator: Fix stack instructions on 64-bit mode + * KVM: SVM: Trap access to the cr8 register + * KVM: VMX: Fix cr8 exit optimization + * KVM: MMU: Use cmpxchg for pte updates on walk_addr() + * KVM: MMU: Simplify calculation of pte access + * KVM: MMU: Set nx bit correctly on shadow ptes + * KVM: MMU: Move pte access calculation into a helper function + * KVM: MMU: Fix inherited permissions for emulated guest pte updates + * KVM: MMU: No need to pick up nx bit from guest pte + * KVM: MMU: Pass pte dirty flag to set_pte() instead of calculating it + on-site + * KVM: MMU: Remove walker argument to set_pte() + * KVM: MMU: Move set_pte() into guest paging mode independent code + * KVM: MMU: Adjust mmu_set_spte() debug code for gpte removal + * KVM: MMU: Use mmu_set_spte() for real-mode shadows + * KVM: SVM: Exit to userspace if write to cr8 and not using in-kernel + apic + * KVM: MMU: Fix SMP shadow instantiation race + * KVM: LAPIC: minor debugging compile fix + * KVM: SVM: support writing 0 to K8 performance counter control registers + * KVM: MMU: emulated cmpxchg8b should be atomic on i386 + * KVM: Portability: Move kvm{pic,ioapic} accesors to x86 specific code + * KVM: Portability: Introduce kvm_vcpu_arch + * KVM: Portability: Split mmu-related static inline functions to mmu.h + * KVM: Portability: Move kvm_vcpu definition back to kvm.h + * KVM: Portability: Expand the KVM_VCPU_COMM in kvm_vcpu structure. + * KVM: Portability: Move kvm_vcpu_stat to x86.h + * KVM: Portability: Move memslot aliases to new struct kvm_arch + * KVM: Portability: Move mmu-related fields to kvm_arch + * KVM: Portability: move vpic and vioapic to kvm_arch + * KVM: Portability: Move round_robin_prev_vcpu and tss_addr to kvm_arch + * KVM: Portability: Move kvm_vm_stat to x86.h + * KVM: VMX: Add printk_ratelimit in vmx_intr_assist + * KVM: Move arch dependent files to new directory arch/x86/kvm/ + * KVM: Move drivers/kvm/* to virt/kvm/ + * KVM: Move irqchip declarations into new ioapic.h and lapic.h + * KVM: Move ioapic code to common directory. + * KVM: Move kvm_vcpu_kick() to x86.c + * KVM: Expose ioapic to ia64 save/restore APIs + * KVM: MMU: Coalesce remote tlb flushes + * KVM: MMU: Add cache miss statistic + * KVM: Print data for unimplemented wrmsr + * KVM: Ensure pages are copied on write + * KVM: local APIC TPR access reporting facility + * KVM: Accelerated apic support + * KVM: Disable vapic support on Intel machines with FlexPriority + * KVM: MMU: Concurrent guest walkers + * KVM: Add kvm_read_guest_atomic() + * KVM: MMU: Avoid calling gfn_to_page() in mmu_set_spte() + * KVM: MMU: Switch to mmu spinlock + * KVM: MMU: Move kvm_free_some_pages() into critical section + * KVM: MMU: Broaden scope of mmap_sem to include actual mapping + * KVM: MMU: Fix recursive locking of mmap_sem() + * KVM: Fix unbalanced mmap_sem operations in cmpxchg8b emulation + * KVM: Mark vapic page as dirty for save/restore/migrate + * KVM: x86 emulator: Only allow VMCALL/VMMCALL trapped by #UD + * KVM: MMU: Update shadow ptes on partial guest pte writes + * KVM: MMU: Simplify hash table indexing + * KVM: Portability: Move kvm_fpu to asm-x86/kvm.h + * KVM: MMU: Fix dirty page setting for pages removed from rmap + * KVM: Initialize the mmu caches only after verifying cpu support + * KVM: Fix unbounded preemption latency + * KVM: Put kvm_para.h include outside __KERNEL__ + * KVM: Move apic timer migration away from critical section + * KVM: SVM: Fix lazy FPU switching + * KVM: MMU: Fix gpa truncation when reading a pte + * [GFS2] Handle multiple glock demote requests + * [GFS2] Clean up internal read function + * [GFS2] Use ->page_mkwrite() for mmap() + * [GFS2] Remove useless i_cache from inodes + * [GFS2] Remove unused field in struct gfs2_inode + * [GFS2] Add gfs2_is_writeback() + * [GFS2] Introduce gfs2_set_aops() + * [GFS2] Split gfs2_writepage into three cases + * [GFS2] Add writepages for GFS2 jdata + * [GFS2] Don't hold page lock when starting transaction + * [GFS2] Use correct include file in ops_address.c + * [GFS2] Remove unused variables + * [GFS2] Remove "reclaim limit" + * [GFS2] Add sync_page to metadata address space operations + * [GFS2] Reorder writeback for glock sync + * [GFS2] Remove flags no longer required + * [GFS2] Given device ID rather than s_id in "id" sysfs file + * [GFS2] check kthread_should_stop when waiting + * [GFS2] Don't add glocks to the journal + * [GFS2] Use atomic_t for journal free blocks counter + * [GFS2] Move gfs2_logd into log.c + * [GFS2] Don't periodically update the jindex + * [GFS2] Check for installation of mount helpers for DLM mounts + * [GFS2] tidy up error message + * [GFS2] Fix runtime issue with UP kernels + * [GFS2] remove unnecessary permission checks + * [GFS2] Fix build warnings + * [GFS2] Remove unrequired code + * [GFS2] Remove lock methods for lock_nolock protocol + * [GFS2] patch to check for recursive lock requests in gfs2_rename code + path + * [GFS2] Remove unused variable + * [GFS2] use pid for plock owner for nfs clients + * [GFS2] Remove function gfs2_get_block + * [GFS2] Journal extent mapping + * [GFS2] Get rid of useless "found" variable in quota.c + * [GFS2] Run through full bitmaps quicker in gfs2_bitfit + * [GFS2] Reorganize function gfs2_glmutex_lock + * [GFS2] Only fetch the dinode once in block_map + * [GFS2] Function meta_read optimization + * [GFS2] Incremental patch to fix compiler warning + * [GFS2] Eliminate the no longer needed sd_statfs_mutex + * [GFS2] Minor correction + * [GFS2] Fix log block mapper + * [GFS2] Remove unused variable + * [GFS2] Allow page migration for writeback and ordered pages + * [GFS2] Initialize extent_list earlier + * [GFS2] Fix problems relating to execution of files on GFS2 + * [GFS2] Fix assert in log code + * [GFS2] Reduce inode size by moving i_alloc out of line + * [GFS2] Remove unneeded i_spin + * [GFS2] gfs2_alloc_required performance + * [GFS2] Fix write alloc required shortcut calculation + * [GFS2] Fix typo + * [GFS2] Fix page_mkwrite truncation race path + * [GFS2] Lockup on error + * [GFS2] Allow journal recovery on read-only mount + + -- Tim Gardner Sun, 27 Jan 2008 20:37:18 -0700 + +linux (2.6.24-5.9) hardy; urgency=low + + [Amit Kucheria] + + * Fix LPIA FTBFS due to virtio Ignore: yes + + [Upstream Kernel Changes] + + * ACPI: processor: Fix null pointer dereference in throttling + * [SPARC64]: Fix of section mismatch warnings. + * [SPARC64]: Fix section error in sparcspkr + * [SPARC]: Constify function pointer tables. + * [BLUETOOTH]: Move children of connection device to NULL before + connection down. + * [TULIP] DMFE: Fix SROM parsing regression. + * [IPV4]: Add missing skb->truesize increment in ip_append_page(). + * iwlwifi: fix possible read attempt on ucode that is not available + * [NETNS]: Re-export init_net via EXPORT_SYMBOL. + * [INET]: Fix truesize setting in ip_append_data + * sis190: add cmos ram access code for the SiS19x/968 chipset pair + * sis190: remove duplicate INIT_WORK + * sis190: mdio operation failure is not correctly detected + * sis190: scheduling while atomic error + * Update ctime and mtime for memory-mapped files + * [SCSI] initio: fix module hangs on loading + * xen: disable vcpu_info placement for now + * agp/intel: add support for E7221 chipset + * drm/i915: add support for E7221 chipset + * DMI: move dmi_available declaration to linux/dmi.h + * DMI: create dmi_get_slot() + * ACPI: create acpi_dmi_dump() + * ACPI: on OSI(Linux), print needed DMI rather than requesting dmidecode + output + * ACPI: Delete Intel Customer Reference Board (CRB) from OSI(Linux) DMI + list + * ACPI: make _OSI(Linux) console messages smarter + * ACPI: Add ThinkPad R61, ThinkPad T61 to OSI(Linux) white-list + * ACPI: DMI blacklist to reduce console warnings on OSI(Linux) systems. + * ACPI: EC: fix dmesg spam regression + * ACPI: EC: add leading zeros to debug messages + * Pull bugzilla-9747 into release branch + * Pull bugzilla-8459 into release branch + * Pull bugzilla-9798 into release branch + * Pull dmi-2.6.24 into release branch + * [SPARC64]: Partially revert "Constify function pointer tables." + * lockdep: fix kernel crash on module unload + * sysctl: kill binary sysctl KERN_PPC_L2CR + * fix hugepages leak due to pagetable page sharing + * spi: omap2_mcspi PIO RX fix + * Linux 2.6.24 + + -- Tim Gardner Fri, 25 Jan 2008 01:44:27 -0700 + +linux (2.6.24-5.8) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: Update to 2.6.24-rc8-rt1 + * rt: Update configuration files + + [Amit Kucheria] + + * Asix: fix breakage caused in 2.6.24-rc7 + * Add CONFIG_CPUSETS to server-related flavours + - LP: #182434 + + [Chuck Short] + + * SAUCE: ata: blacklist FUJITSU MHW2160BH PL + - LP: #175834 + + [Kees Cook] + + * AppArmor: updated patch series to upstream SVN 1079. + + [Soren Hansen] + + * Updated configs to enable virtio stuff Ignore: yes + + [Stefan Bader] + + * Enabled CONFIG_BSD_PROCESS_ACCT=y for sparc. + - LP: #176587 + * Enable CONFIG_AUDITSYSCALL=y. + - LP: #140784 + * Added CONFIG_AUDIT_SYSCALL=y to custom lpia(compat) + * Enabled CONFIG_HUGETLBFS=y for i386/server amd64/server and ia64. + * Lower priority of pnpacpi resource messages to warning level. + - LP: #159241 + * Fix the messed up message level of pnpacpi parser. + + [Tim Gardner] + + * Start new release, bump ABI to -5 + * Disabled iwlwifi preperatory to moving it to l-u-m. + * Enabled CONFIG_USB_SERIAL_KEYSPAN + * Disabled CONFIG_CGROUPS. + * Virtio config settings for -rt. + * Re-enable IWLWIFI in the kernel. + * Fixed -rt saa7134-core.c FTBS + + [Upstream Kernel Changes] + + * Input: Handle EV_PWR type of input caps in input_set_capability. + * Input: jornada680_kbd - fix default keymap + * increase PNP_MAX_PORT to 40 from 24 + * sched: fix gcc warnings + * leds: Fix leds_list_lock locking issues + * leds: Fix locomo LED driver oops + * x86: fix asm-x86/byteorder.h for userspace export + * x86: fix asm-x86/msr.h for user-space export + * ACPI: EC: Enable boot EC before bus_scan + * ACPI: Make sysfs interface in ACPI power optional. + * fix lguest rmmod "bad pgd" + * slub: provide /proc/slabinfo + * [POWERPC] Fix build failure on Cell when CONFIG_SPU_FS=y + * slub: register slabinfo to procfs + * [SCSI] scsi_sysfs: restore prep_fn when ULD is removed + * Unify /proc/slabinfo configuration + * scsi: revert "[SCSI] Get rid of scsi_cmnd->done" + * restrict reading from /proc//maps to those who share ->mm or can + ptrace pid + * Fix kernel/ptrace.c compile problem (missing "may_attach()") + * hwmon: (w83627ehf) Be more careful when changing VID input level + * NFS: Fix a possible Oops in fs/nfs/super.c + * NFSv4: Fix circular locking dependency in nfs4_kill_renewd + * NFS: add newline to kernel warning message in auth_gss code + * NFSv4: nfs4_open_confirm must not set the open_owner as confirmed on + error + * NFSv4: Fix open_to_lock_owner sequenceid allocation... + * gameport: don't export functions that are static inline + * Input: spitzkbd - fix suspend key handling + * Input: pass EV_PWR events to event handlers + * [ARM] 4735/1: Unbreak pxa25x suspend/resume + * IB/srp: Fix list corruption/oops on module reload + * Console is utf-8 by default + * [IA64] Update Altix BTE error return status patch + * [IA64] Update Altix nofault code + * [X25]: Add missing x25_neigh_put + * [XFRM]: Do not define km_migrate() if !CONFIG_XFRM_MIGRATE + * [CASSINI]: Fix endianness bug. + * [CASSINI]: Revert 'dont touch page_count'. + * [CASSINI]: Program parent Intel31154 bridge when necessary. + * [CASSINI]: Set skb->truesize properly on receive packets. + * [CASSINI]: Fix two obvious NAPI bugs. + * [CASSINI]: Bump driver version and release date. + * [INET]: Fix netdev renaming and inet address labels + * [CONNECTOR]: Return proper error code in cn_call_callback() + * [ISDN] i4l: 'NO CARRIER' message lost after ldisc flush + * [ISDN]: i4l: Fix DLE handling for i4l-audio + * fix: using joysticks in 32 bit applications on 64 bit systems + * [ARM] 4691/1: add missing i2c_board_info struct for at91rm9200 + * hda_intel suspend latency: shorten codec read + * CPU hotplug: fix cpu_is_offline() on !CONFIG_HOTPLUG_CPU + * Linux 2.6.24-rc7 + * sh: Fix argument page dcache flushing regression. + * V4L/DVB (6944a): Fix Regression VIDIOCGMBUF ioctl hangs on bttv driver + * V4L/DVB (6916): ivtv: udelay has to be changed *after* the eeprom was + read, not before + * [MIPS] Move inclusing of kernel/time/Kconfig menu to appropriate place + * [MIPS] Alchemy: Fix use of __init code bug exposed by modpost warning + * [MIPS] Fix IP32 breakage + * [MIPS] Assume R4000/R4400 newer than 3.0 don't have the mfc0 count bug + * [MIPS] Fix CONFIG_BOOT_RAW. + * ACPI: Reintroduce run time configurable max_cstate for !CPU_IDLE case + * core dump: real_parent ppid + * acct: real_parent ppid + * IB/mlx4: Fix value of pkey_index in QP1 completions + * IB/srp: Release transport before removing host + * x86: fix do_fork_idle section mismatch + * spi_bitbang: always grab lock with irqs blocked + * fat: optimize fat_count_free_clusters() + * KEYS: fix macro + * md: fix data corruption when a degraded raid5 array is reshaped + * xip: fix get_zeroed_page with __GFP_HIGHMEM + * eCryptfs: fix dentry handling on create error, unlink, and inode + destroy + * vmcoreinfo: add the array length of "free_list" for filtering free + pages + * dmi-id: fix for __you_cannot_kmalloc_that_much failure + * snd_mixer_oss_build_input(): fix for __you_cannot_kmalloc_that_much + failure with gcc-3.2 + * Fix crash with FLAT_MEMORY and ARCH_PFN_OFFSET != 0 + * hfs: handle more on-disk corruptions without oopsing + * pl2303: Fix mode switching regression + * futex: Prevent stale futex owner when interrupted/timeout + * [NIU]: Fix slowpath interrupt handling. + * [NIU]: Missing ->last_rx update. + * [NIU]: Fix potentially stuck TCP socket send queues. + * [NIU]: Update driver version and release date. + * [IPV4] raw: Strengthen check on validity of iph->ihl + * [IPV4] ipconfig: Fix regression in ip command line processing + * [NET]: Fix netx-eth.c compilation. + * [METH]: Fix MAC address handling. + * [TULIP]: NAPI full quantum bug. + * [ATM]: [nicstar] delay irq setup until card is configured + * [SCTP]: Fix the name of the authentication event. + * [SCTP]: Correctly handle AUTH parameters in unexpected INIT + * [SCTP]: Add back the code that accounted for FORWARD_TSN parameter in + INIT. + * [IRDA]: irda_create() nuke user triggable printk + * b43: Fix rxheader channel parsing + * [NET]: Do not grab device reference when scheduling a NAPI poll. + * [NET]: Add NAPI_STATE_DISABLE. + * [NET]: Do not check netif_running() and carrier state in ->poll() + * ssb: Fix probing of PCI cores if PCI and PCIE core is available + * mac80211: return an error when SIWRATE doesn't match any rate + * [NETXEN]: Fix ->poll() done logic. + * [NET]: Fix drivers to handle napi_disable() disabling interrupts. + * [NET]: Stop polling when napi_disable() is pending. + * [NET]: Make ->poll() breakout consistent in Intel ethernet drivers. + * [NET] Intel ethernet drivers: update MAINTAINERS + * [NET]: kaweth was forgotten in msec switchover of usb_start_wait_urb + * [IPV4] ROUTE: ip_rt_dump() is unecessary slow + * [NET]: Clone the sk_buff 'iif' field in __skb_clone() + * [LRO] Fix lro_mgr->features checks + * [NET]: mcs7830 passes msecs instead of jiffies to usb_control_msg + * [FORCEDETH]: Fix reversing the MAC address on suspend. + * [XFRM]: xfrm_algo_clone() allocates too much memory + * [SOCK]: Adds a rcu_dereference() in sk_filter + * [CONNECTOR]: Don't touch queue dev after decrement of ref count. + * [IPV6]: IPV6_MULTICAST_IF setting is ignored on link-local connect() + * [ATM]: Check IP header validity in mpc_send_packet + * show_task: real_parent + * [SCSI] qla1280: fix 32 bit segment code + * [NIU]: Support for Marvell PHY + * [NEIGH]: Fix race between neigh_parms_release and neightbl_fill_parms + * [IPV4] ROUTE: fix rcu_dereference() uses in /proc/net/rt_cache + * [AX25]: Kill user triggable printks. + * [ARM] pxa: silence warnings from cpu_is_xxx() macros + * [POWERPC] efika: add phy-handle property for fec_mpc52xx + * [ARM] vfp: fix fuitod/fsitod instructions + * [CRYPTO] padlock: Fix alignment fault in aes_crypt_copy + * rt2x00: Allow rt61 to catch up after a missing tx report + * rt2x00: Corectly initialize rt2500usb MAC + * rt2x00: Put 802.11 data on 4 byte boundary + * NFSv4: Give the lock stateid its own sequence queue + * sata_qstor: use hardreset instead of softreset + * libata-sff: PCI IRQ handling fix + * pata_pdc202xx_old: Further fixups + * pata_ixp4xx_cf: fix compilation introduced by ata_port_desc() + conversion + * libata-pmp: 4726 hates SRST + * libata-pmp: propagate timeout to host link + * libata: don't normalize UNKNOWN to NONE after reset + * Update kernel parameter document for libata DMA mode setting knobs. + * sata_sil24: prevent hba lockup when pass-through ATA commands are used + * ide: workaround suspend bug for ACPI IDE + * ide: fix cable detection for SATA bridges + * trm290: do hook dma_host_{on,off} methods (take 2) + * libata and starting/stopping ATAPI floppy devices + * ACPI : Not register gsi for PCI IDE controller in legacy mode + * ACPICA: fix acpi_serialize hang regression + * sh: Force __access_ok() to obey address space limit. + * [AX25] af_ax25: Possible circular locking. + * ACPI: apply quirk_ich6_lpc_acpi to more ICH8 and ICH9 + * [POWERPC] Fix CPU hotplug when using the SLB shadow buffer + * [BLUETOOTH]: rfcomm tty BUG_ON() code fix + * [BLUETOOTH]: Always send explicit hci_ll wake-up acks. + * [DECNET] ROUTE: fix rcu_dereference() uses in /proc/net/decnet_cache + * [VLAN]: nested VLAN: fix lockdep's recursive locking warning + * [MACVLAN]: Prevent nesting macvlan devices + * [NETFILTER]: ip6t_eui64: Fixes calculation of Universal/Local bit + * [NETFILTER]: xt_helper: Do not bypass RCU + * [XFS] fix unaligned access in readdir + * Don't blatt first element of prv in sg_chain() + * loop: fix bad bio_alloc() nr_iovec request + * block: fix blktrace timestamps + * blktrace: kill the unneeded initcall + * V4L/DVB (6999): ivtv: stick to udelay=10 after all + * V4L/DVB (7001): av7110: fix section mismatch + * [MIPS] Wrong CONFIG option prevents setup of DMA zone. + * [MIPS] pnx8xxx: move to clocksource + * [MIPS] Malta: Fix software reset on big endian + * [MIPS] Lasat: Fix built in separate object directory. + * [MIPS] Replace 40c7869b693b18412491fdcff64682215b739f9e kludge + * Pull bugzilla-5637 into release branch + * Pull bugzilla-8171 into release branch + * Pull bugzilla-8973 into release branch + * PM: ACPI and APM must not be enabled at the same time + * Pull bugzilla-9194 into release branch + * Pull bugzilla-9494 into release branch + * Pull bugzilla-9535 into release branch + * Pull bugzilla-9627 into release branch + * Pull bugzilla-9683 into release branch + * IDE: terminate ACPI DMI list + * cache invalidation error for buffered write + * ps3fb: prevent use after free of fb_info + * ps3fb: fix deadlock on kexec() + * [NETFILTER]: bridge: fix double POST_ROUTING invocation + * xircom_cb endianness fixes + * de4x5 fixes + * endianness noise in tulip_core + * netxen: update MAINTAINERS + * netxen: update driver version + * netxen: stop second phy correctly + * netxen: optimize tx handling + * netxen: fix byte-swapping in tx and rx + * 3c509: PnP resource management fix + * Fixed a small typo in the loopback driver + * ip1000: menu location change + * r8169: fix missing loop variable increment + * [usb netdev] asix: fix regression + * fs_enet: check for phydev existence in the ethtool handlers + * Use access mode instead of open flags to determine needed permissions + * sky2: large memory workaround. + * sky2: remove check for PCI wakeup setting from BIOS + * spidernet MAINTAINERship update + * pnpacpi: print resource shortage message only once + * Pull bugzilla-9535 into release branch + * [SPARC]: Make gettimeofday() monotonic again. + * [SPARC64]: Fix build with SPARSEMEM_VMEMMAP disabled. + * remove task_ppid_nr_ns + * knfsd: Allow NFSv2/3 WRITE calls to succeed when krb5i etc is used. + * Input: improve Kconfig help entries for HP Jornada devices + * [TOKENRING]: rif_timer not initialized properly + * modules: de-mutex more symbol lookup paths in the module code + * w1: decrement slave counter only in ->release() callback + * Kick CPUS that might be sleeping in cpus_idle_wait + * TPM: fix suspend and resume failure + * MAINTAINERS: email update and add missing entry + * quicklists: Only consider memory that can be used with GFP_KERNEL + * macintosh: fix fabrication of caplock key events + * scsi/qla2xxx/qla_os.c section fix + * cciss: section mismatch + * advansys: fix section mismatch warning + * hugetlbfs: fix quota leak + * s3c2410fb: fix incorrect argument type in resume function + * CRIS: define __ARCH_WANT_SYS_RT_SIGSUSPEND in unistd.h for CRIS + * CRIS v10: correct do_signal to fix oops and clean up signal handling in + general + * CRIS v10: kernel/time.c needs to include linux/vmstat.h to compile + * uvesafb: fix section mismatch warnings + * CRIS v10: driver for ds1302 needs to include cris-specific i2c.h + * OSS msnd: fix array overflows + * i2c-omap: Fix NULL pointer dereferencing + * i2c: Spelling fixes + * i2c: Driver IDs are optional + * i2c-sibyte: Fix an error path + * fix the "remove task_ppid_nr_ns" commit + * [MIPS] Kconfig fixes for BCM47XX platform + * [MIPS] Cobalt: Fix ethernet interrupts for RaQ1 + * [MIPS] Cobalt: Qube1 has no serial port so don't use it + * [MIPS] Cacheops.h: Fix typo. + * ata_piix: ignore ATA_DMA_ERR on vmware ich4 + * sata_sil24: fix stupid typo + * sata_sil24: freeze on non-dev errors reported via CERR + * libata: relocate sdev->manage_start_stop configuration + * [POWERPC] Fix boot failure on POWER6 + * x86: fix boot crash on HIGHMEM4G && SPARSEMEM + * x86: asm-x86/msr.h: pull in linux/types.h + * x86: fix RTC_AIE with CONFIG_HPET_EMULATE_RTC + * Fix ARM profiling/instrumentation configuration + * Fix Blackfin HARDWARE_PM support + * libata fixes for sparse-found problems + * [libata] pata_bf54x: checkpatch fixes + * [libata] core checkpatch fix + * libata: correct handling of TSS DVD + * [IA64] Fix unaligned handler for floating point instructions with base + update + * Linux 2.6.24-rc8 + * lockdep: fix internal double unlock during self-test + * lockdep: fix workqueue creation API lockdep interaction + * lockdep: more hardirq annotations for notify_die() + * hostap: section mismatch warning + * wireless/libertas support for 88w8385 sdio older revision + * ipw2200: fix typo in kerneldoc + * b43: fix use-after-free rfkill bug + * rt2x00: Fix ieee80211 payload alignment + * sysfs: make sysfs_lookup() return ERR_PTR(-ENOENT) on failed lookup + * sysfs: fix bugs in sysfs_rename/move_dir() + * Use access mode instead of open flags to determine needed permissions + (CVE-2008-0001) + * IB/ipath: Fix receiving UD messages with immediate data + * [NET]: Fix TX timeout regression in Intel drivers. + * [NIU]: Fix 1G PHY link state handling. + * [SPARC64]: Fix hypervisor TLB operation error reporting. + * Input: mousedev - handle mice that use absolute coordinates + * Input: usbtouchscreen - fix buffer overflow, make more egalax work + * Input: psmouse - fix potential memory leak in psmouse_connect() + * Input: psmouse - fix input_dev leak in lifebook driver + * Input: ALPS - fix sync loss on Acer Aspire 5720ZG + * ipg: balance locking in irq handler + * ipg: plug Tx completion leak + * ipg: fix queue stop condition in the xmit handler + * ipg: fix Tx completion irq request + * cpufreq: Initialise default governor before use + * hfs: fix coverity-found null deref + * pnpacpi: print resource shortage message only once (more) + * CRIS v10: vmlinux.lds.S: ix kernel oops on boot and use common defines + * mm: fix section mismatch warning in page_alloc.c + * jbd: do not try lock_acquire after handle made invalid + * alpha: fix conversion from denormal float to double + * #ifdef very expensive debug check in page fault path + * Fix unbalanced helper_lock in kernel/kmod.c + * fix wrong sized spinlock flags argument + * bonding: fix locking in sysfs primary/active selection + * bonding: fix ASSERT_RTNL that produces spurious warnings + * bonding: fix locking during alb failover and slave removal + * bonding: release slaves when master removed via sysfs + * bonding: Fix up parameter parsing + * bonding: fix lock ordering for rtnl and bonding_rwsem + * bonding: Don't hold lock when calling rtnl_unlock + * Documentation: add a guideline for hard_start_xmit method + * atl1: fix frame length bug + * S2io: Fixed synchronization between scheduling of napi with card reset + and close + * dscc4 endian fixes + * wan/lmc bitfields fixes + * sbni endian fixes + * 3c574, 3c515 bitfields abuse + * dl2k: BMCR_t fixes + * dl2k: ANAR, ANLPAR fixes + * dl2k: BMSR fixes + * dl2k: MSCR, MSSR, ESR, PHY_SCR fixes + * dl2k: the rest + * Replace cpmac fix + * [WATCHDOG] Revert "Stop looking for device as soon as one is found" + * [WATCHDOG] clarify watchdog operation in documentation + * x86: add support for the latest Intel processors to Oprofile + * Selecting LGUEST should turn on Guest support, as in 2.6.23. + * ARM: OMAP1: Keymap fix for f-sample and p2-sample + * ARM: OMAP1: Fix compile for board-nokia770 + * pata_pdc202xx_old: Fix crashes with ATAPI + * arch: Ignore arch/i386 and arch/x86_64 + * Remove bogus duplicate CONFIG_LGUEST_GUEST entry. + * [ARM] pxa: don't rely on r2 being preserved over a function call + * [ARM] 4748/1: dca: source drivers/dca/Kconfig in arch/arm/Kconfig to + fix warning + * rfkill: call rfkill_led_trigger_unregister() on error + * [IPV6]: Mischecked tw match in __inet6_check_established. + * [IPV4] fib_hash: fix duplicated route issue + * [IPV4] fib_trie: fix duplicated route issue + * [NET]: Fix interrupt semaphore corruption in Intel drivers. + * [IPV4] FIB_HASH : Avoid unecessary loop in fn_hash_dump_zone() + * [IPV6] ROUTE: Make sending algorithm more friendly with RFC 4861. + * [NETFILTER]: bridge-netfilter: fix net_device refcnt leaks + * [NEIGH]: Revert 'Fix race between neigh_parms_release and + neightbl_fill_parms' + * [IrDA]: af_irda memory leak fixes + * [ATM] atm/idt77105.c: Fix section mismatch. + * [ATM] atm/suni.c: Fix section mismatch. + * [AF_KEY]: Fix skb leak on pfkey_send_migrate() error + * [NET]: rtnl_link: fix use-after-free + * [IPV6]: ICMP6_MIB_OUTMSGS increment duplicated + * [IPV6]: RFC 2011 compatibility broken + * [ICMP]: ICMP_MIB_OUTMSGS increment duplicated + * selinux: fix memory leak in netlabel code + * [MIPS] SMTC: Fix build error. + * [MIPS] Malta: Fix reading the PCI clock frequency on big-endian + * tc35815: Use irq number for tc35815-mac platform device id + * keyspan: fix oops + * hrtimer: fix section mismatch + * timer: fix section mismatch + * CRIS: add missed local_irq_restore call + * s3c2410_fb: fix line length calculation + * Fix filesystem capability support + * sched: group scheduler, set uid share fix + * hwmon: (it87) request only Environment Controller ports + * W1: w1_therm.c ds18b20 decode freezing temperatures correctly + * W1: w1_therm.c is flagging 0C etc as invalid + * rcu: fix section mismatch + * Fix file references in documentation and Kconfig + * x86: GEODE fix a race condition in the MFGPT timer tick + * virtnet: remove double ether_setup + * virtio:simplify-config-mechanism + * virtio: An entropy device, as suggested by hpa. + * virtio: Export vring functions for modules to use + * virtio: Put the virtio under the virtualization menu + * virtio:pci-device + * Fix vring_init/vring_size to take unsigned long + * virtio:vring-kick-when-empty + * virtio:explicit-callback-disable + * virtio:net-flush-queue-on-init + * virtio:net-fix-xmit-skb-free-real + * Parametrize the napi_weight for virtio receive queue. + * Handle module unload Add the device release function. + * Update all status fields on driver unload + * Make virtio modules GPL + * Make virtio_pci license be GPL2+ + * Use Qumranet donated PCI vendor/device IDs + * virtio:more-interrupt-suppression + * Reboot Implemented + * lguest:reboot-fix + * introduce vcpu struct + * adapt lguest launcher to per-cpuness + * initialize vcpu + * per-cpu run guest + * make write() operation smp aware + * make hypercalls use the vcpu struct + * per-vcpu lguest timers + * per-vcpu interrupt processing. + * map_switcher_in_guest() per-vcpu + * make emulate_insn receive a vcpu struct. + * make registers per-vcpu + * replace lguest_arch with lg_cpu_arch. + * per-vcpu lguest task management + * makes special fields be per-vcpu + * make pending notifications per-vcpu + * per-vcpu lguest pgdir management + + -- Tim Gardner Thu, 17 Jan 2008 14:45:01 -0700 + +linux (2.6.24-4.7) hardy; urgency=low + + [Amit Kucheria] + + * Poulsbo: Add SD8686 and 8688 WLAN drivers + * Poulsbo: Mass update of patches to be identical to those on moblin + * SAUCE: make fc transport removal of target configurable OriginalAuthor: + Michael Reed sgi.com> OriginalLocation: + http://thread.gmane.org/gmane.linux.scsi/25318 Bug: 163075 + + [Fabio M. Di Nitto] + + * Fix handling of gcc-4.1 for powerpc and ia64 + + [Tim Gardner] + + * Re-engineered architecture specific linux-headers compiler version + dependencies. + * Doh! Changed header-depends to header_depends. + + -- Tim Gardner Fri, 11 Jan 2008 07:10:46 -0700 + +linux (2.6.24-4.6) hardy; urgency=low + + [Alessio Igor Bogani] + + * Fix -rt build FTBS. + + [Amit Kucheria] + + * LPIACOMPAT: Update thermal patches to be inline with lpia flavour + * Poulsbo: Add USB Controller patch and corresponding config change + + [Fabio M. Di Nitto] + + * Enable aoe and nbd modules on hppa Ignore: yes + * Fix ia64 build by using gcc-4.1 + + [Tim Gardner] + + * Enable JFFS2 LZO compression. + - LP: #178343 + * Remove IS_G33 special handling. + - LP: #174367 + * Enabled CONFIG_SECURITY_CAPABILITIES and + CONFIG_SECURITY_FILE_CAPABILITIES + - LP: #95089 + * Enabled CONFIG_TASKSTATS and CONFIG_TASK_IO_ACCOUNTING + * Turned CONFIG_SECURITY_FILE_CAPABILITIES back off. + * Enabled CONFIG_B43LEGACY=m + * Enabled CONFIG_SCSI_QLOGIC_1280=m + * Enabled CONFIG_FUSION=y for virtual + * USB bluetooth device 0x0e5e:0x6622 floods errors to syslog + - LP: #152689 + * Removed lpia from d-i. + * Added ia64 modules. + * Added hppa32/64 modules. + + [Upstream Kernel Changes] + + * DMI autoload dcdbas on all Dell systems. + * sched: fix gcc warnings + * leds: Fix leds_list_lock locking issues + * leds: Fix locomo LED driver oops + * x86: fix asm-x86/byteorder.h for userspace export + * x86: fix asm-x86/msr.h for user-space export + * fix lguest rmmod "bad pgd" + * slub: provide /proc/slabinfo + * [POWERPC] Fix build failure on Cell when CONFIG_SPU_FS=y + * slub: register slabinfo to procfs + * [SCSI] scsi_sysfs: restore prep_fn when ULD is removed + * Unify /proc/slabinfo configuration + * scsi: revert "[SCSI] Get rid of scsi_cmnd->done" + * restrict reading from /proc//maps to those who share ->mm or can + ptrace pid + * Fix kernel/ptrace.c compile problem (missing "may_attach()") + * hwmon: (w83627ehf) Be more careful when changing VID input level + * NFS: Fix a possible Oops in fs/nfs/super.c + * NFSv4: Fix circular locking dependency in nfs4_kill_renewd + * NFS: add newline to kernel warning message in auth_gss code + * NFSv4: nfs4_open_confirm must not set the open_owner as confirmed on + error + * NFSv4: Fix open_to_lock_owner sequenceid allocation... + * IB/srp: Fix list corruption/oops on module reload + * Console is utf-8 by default + * [IA64] Update Altix BTE error return status patch + * [IA64] Update Altix nofault code + * [X25]: Add missing x25_neigh_put + * [XFRM]: Do not define km_migrate() if !CONFIG_XFRM_MIGRATE + * [CASSINI]: Fix endianness bug. + * [CASSINI]: Revert 'dont touch page_count'. + * [CASSINI]: Program parent Intel31154 bridge when necessary. + * [CASSINI]: Set skb->truesize properly on receive packets. + * [CASSINI]: Fix two obvious NAPI bugs. + * [CASSINI]: Bump driver version and release date. + * [INET]: Fix netdev renaming and inet address labels + * [CONNECTOR]: Return proper error code in cn_call_callback() + * [ISDN] i4l: 'NO CARRIER' message lost after ldisc flush + * [ISDN]: i4l: Fix DLE handling for i4l-audio + * fix: using joysticks in 32 bit applications on 64 bit systems + * hda_intel suspend latency: shorten codec read + * CPU hotplug: fix cpu_is_offline() on !CONFIG_HOTPLUG_CPU + * Linux 2.6.24-rc7 + * PIE executable randomization (upstream cherry pick by kees) + + -- Tim Gardner Fri, 04 Jan 2008 07:15:47 -0700 + +linux (2.6.24-3.5) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: Fix rt preempt patchset version + * Updated README file for binary custom flavours + * Fix -rt build FTBS. + * rt: Update configuration files + + [Tim Gardner] + + * SAUCE: Add extra headers to linux-libc-dev + + [Upstream Kernel Changes] + + * [WATCHDOG] at32ap700x_wdt: add support for boot status and add fix for + silicon errata + * [WATCHDOG] Stop looking for device as soon as one is found + * [WATCHDOG] bfin_wdt, remove SPIN_LOCK_UNLOCKED + * [WATCHDOG] Sbus: cpwatchdog, remove SPIN_LOCK_UNLOCKED + * [WATCHDOG] IT8212F watchdog driver + * ACPI: acpiphp: Remove dmesg spam on device remove + * [WATCHDOG] ipmi: add the standard watchdog timeout ioctls + * [WATCHDOG] add Nano 7240 driver + * ACPI: battery: fix ACPI battery technology reporting + * [ARM] 4667/1: CM-X270 fixes + * [ARM] 4690/1: PXA: fix CKEN corruption in PXA27x AC97 cold reset code + * [IPV6] XFRM: Fix auditing rt6i_flags; use RTF_xxx flags instead of + RTCF_xxx. + * [IPV4]: Swap the ifa allocation with the"ipv4_devconf_setall" call + * [IPv4] ESP: Discard dummy packets introduced in rfc4303 + * [IPv6] ESP: Discard dummy packets introduced in rfc4303 + * [UM]: Fix use of skb after netif_rx + * [XTENSA]: Fix use of skb after netif_rx + * [S390]: Fix use of skb after netif_rx + * [BNX2]: Add PHY_DIS_EARLY_DAC workaround. + * [BNX2]: Fix RX packet rot. + * [BNX2]: Update version to 1.6.9. + * [NET]: Fix wrong comments for unregister_net* + * [VLAN]: Fix potential race in vlan_cleanup_module vs + vlan_ioctl_handler. + * [IPSEC]: Fix potential dst leak in xfrm_lookup + * V4L/DVB (6485): ivtv: fix compile warning + * V4L/DVB (6540): em28xx: fix failing autodetection after the reboot + * V4L/DVB (6542): Fix S-video mode on tvp5150 + * V4L/DVB (6579): Fix bug #8824: Correct support for Diseqc on tda10086 + * V4L/DVB (6581): Fix: avoids negative vma usage count + * V4L/DVB (6601): V4L: videobuf-core locking fixes and comments + * V4L/DVB (6602): V4L: Convert videobuf drivers to videobuf_stop + * V4L/DVB (6615): V4L: Fix VIDIOCGMBUF locking in saa7146 + * V4L/DVB (6629): zl10353: fix default adc_clock and TRL nominal rate + calculation + * V4L/DVB (6666): saa7134-alsa: fix period handling + * V4L/DVB (6684): Complement va_start() with va_end() + style fixes + * V4L/DVB (6686): saa7134: fix composite over s-video input on the Tevion + MD 9717 + * V4L/DVB (6690): saa7134: fix ignored interrupts + * V4L/DVB (6751): V4L: Memory leak! Fix count in videobuf-vmalloc mmap + * V4L/DVB (6746): saa7134-dvb: fix tuning for WinTV HVR-1110 + * V4L/DVB (6750): Fix in-kernel compilation for cxusb + * V4L/DVB (6733): DVB: Compile 3000MC-specific DIB code only for + CONFIG_DVB_DIB3000MC + * V4L/DVB (6794): Fix compilation when dib3000mc is compiled as a module + * NFS: Fix NFS mountpoint crossing... + * V4L/DVB (6796): ivtv/ section fix + * V4L/DVB (6797): bt8xx/ section fixes + * NFSv2/v3: Fix a memory leak when using -onolock + * V4L/DVB (6609): Re-adds lock safe videobuf_read_start + * i2c: Delete an outdated piece of documentation + * i2c-gpio: Initialize adapter class + * i2c: Add missing spaces in split log messages + * i2c/isp1301_omap: Build fix + * [SERIAL] sparc: Infrastructure to fix section mismatch bugs. + * NFS: Fix an Oops in NFS unmount + * sdhci: describe quirks + * sdhci: don't warn about sdhci 2.0 controllers + * sdhci: use PIO when DMA can't satisfy the request + * sdhci: support JMicron JMB38x chips + * mmc: remove unused 'mode' from the mmc_host structure + * IB/ehca: Return correct number of SGEs for SRQ + * IB/ehca: Serialize HCA-related hCalls if necessary + * ide-scsi: add ide_scsi_hex_dump() helper + * ide: add missing checks for control register existence + * ide: deprecate CONFIG_BLK_DEV_OFFBOARD + * ide: fix ide_scan_pcibus() error message + * ide: coding style fixes for drivers/ide/setup-pci.c + * ide: add /sys/bus/ide/devices/*/{model,firmware,serial} sysfs entries + * ide: DMA reporting and validity checking fixes (take 3) + * ide-cd: remove dead post_transform_command() + * pdc202xx_new: fix Promise TX4 support + * hpt366: fix HPT37x PIO mode timings (take 2) + * ide: remove dead code from __ide_dma_test_irq() + * ide: remove stale changelog from ide-disk.c + * ide: remove stale changelog from ide-probe.c + * ide: fix ->io_32bit race in set_io_32bit() + * MAINTAINERS: update the NFS CLIENT entry + * V4L/DVB (6803): buf-core.c locking fixes + * [SPARC64]: Fix two kernel linear mapping setup bugs. + * IB/ehca: Fix lock flag variable location, bump version number + * kbuild: re-enable Makefile generation in a new O=... directory + * V4L/DVB (6798): saa7134: enable LNA in analog mode for Hauppauge WinTV + HVR-1110 + * V4L/DVB (6814): Makefile: always enter video/ + * V4L/DVB (6819): i2c: fix drivers/media/video/bt866.c + * V4L/DVB (6820): s5h1409: QAM SNR related fixes + * ACPI: video_device_list corruption + * ACPI: fix modpost warnings + * ACPI: thinkpad-acpi: fix lenovo keymap for brightness + * Pull thinkpad-2.6.24 into release branch + * Pull battery-2.6.24 into release branch + * [POWERPC] Fix typo #ifdef -> #ifndef + * [POWERPC] Kill non-existent symbols from ksyms and commproc.h + * [POWRPC] CPM2: Eliminate section mismatch warning in cpm2_reset(). + * [POWERPC] 82xx: mpc8272ads, pq2fads: Update defconfig with + CONFIG_FS_ENET_MDIO_FCC + * [POWERPC] iSeries: don't printk with HV spinlock held + * [POWERPC] Fix rounding bug in emulation for double float operating + * [POWERPC] Make PS3_SYS_MANAGER default y, not m + * [MIPS] time: Set up Cobalt's mips_hpt_frequency + * [MIPS] Alchemy: fix PCI resource conflict + * [MIPS] Alchemy: fix off by two error in __fixup_bigphys_addr() + * [MIPS] Atlas, Malta: Don't free firmware memory on free_initmem. + * [MIPS] PCI: Make pcibios_fixup_device_resources ignore legacy + resources. + * [MIPS] time: Delete weak definition of plat_time_init() due to gcc bug. + * [MIPS] Ensure that ST0_FR is never set on a 32 bit kernel + * [SPARC32]: Silence sparc32 warnings on missing syscalls. + * Pull hotplug into release branch + * ACPI: SBS: Reset alarm bit + * ACPI: SBS: Ignore alarms coming from unknown devices + * ACPI: SBS: Return rate in mW if capacity in mWh + * Pull bugzilla-9362 into release branch + * sky2: RX lockup fix + * sundance fixes + * starfire VLAN fix + * e100: free IRQ to remove warningwhenrebooting + * hamachi endianness fixes + * drivers/net/sis190.c section fix + * drivers/net/s2io.c section fixes + * ucc_geth: minor whitespace fix + * net: smc911x: shut up compiler warnings + * Net: ibm_newemac, remove SPIN_LOCK_UNLOCKED + * ixgb: make sure jumbos stay enabled after reset + * [NETFILTER]: ctnetlink: set expected bit for related conntracks + * [NETFILTER]: ip_tables: fix compat copy race + * [XFRM]: Display the audited SPI value in host byte order. + * [NETFILTER]: xt_hashlimit should use time_after_eq() + * [TIPC]: Fix semaphore handling. + * [SYNCPPP]: Endianness and 64bit fixes. + * [NETFILTER]: bridge: fix missing link layer headers on outgoing routed + packets + * [ATM]: Fix compiler warning noise with FORE200E driver + * [IPV4]: Updates to nfsroot documentation + * [BRIDGE]: Assign random address. + * [IPV6]: Fix the return value of ipv6_getsockopt + * [IPV4]: Make tcp_input_metrics() get minimum RTO via tcp_rto_min() + * [AX25]: Locking dependencies fix in ax25_disconnect(). + * [SCTP]: Flush fragment queue when exiting partial delivery. + * [IRDA]: Race between open and disconnect in irda-usb. + * [IRDA]: mcs7780 needs to free allocated rx buffer. + * [IRDA]: irlmp_unregister_link() needs to free lsaps. + * [IRDA]: stir4200 fixes. + * [IRDA]: irda parameters warning fixes. + * [S390] pud_present/pmd_present bug. + * [ARM] 4710/1: Fix coprocessor 14 usage for debug messages via ICEDCC + * [ARM] 4694/1: IXP4xx: Update clockevent support for shutdown and resume + * kobject: fix the documentation of how kobject_set_name works + * tipar: remove obsolete module + * HOWTO: Change man-page maintainer address for Japanese HOWTO + * Add Documentation for FAIR_USER_SCHED sysfs files + * HOWTO: change addresses of maintainer and lxr url for Korean HOWTO + * add stable_api_nonsense.txt in korean + * HOWTO: update misspelling and word incorrected + * PCI: Restore PCI expansion ROM P2P prefetch window creation + * USB: sierra: fix product id + * usb-storage: Fix devices that cannot handle 32k transfers + * USB: cp2101: new device id + * USB: option: Bind to the correct interface of the Huawei E220 + * usb.h: fix kernel-doc warning + * USB: fix locking loop by avoiding flush_scheduled_work + * USB: use IRQF_DISABLED for HCD interrupt handlers + * USB: at91_udc: correct hanging while disconnecting usb cable + * usb: Remove broken optimisation in OHCI IRQ handler + * USB: revert portions of "UNUSUAL_DEV: Sync up some reported devices + from Ubuntu" + * ocfs2: fix exit-while-locked bug in ocfs2_queue_orphans() + * ocfs2: Don't panic when truncating an empty extent + * ocfs2: Allow for debugging of transaction extends + * ocfs2: Re-journal buffers after transaction extend + * pcnet_cs: add new id + * ucc_geth: really fix section mismatch + * sis190 endianness + * libertas: add Dan Williams as maintainer + * zd1211rw: Fix alignment problems + * wireless/ipw2200.c: add __dev{init,exit} annotations + * ieee80211_rate: missed unlock + * iwlwifi3945/4965: fix rate control algo reference leak + * libertas: select WIRELESS_EXT + * bcm43xx_debugfs sscanf fix + * b43: Fix rfkill radio LED + * iwlwifi: fix rf_kill state inconsistent during suspend and resume + * sata_sil: fix spurious IRQ handling + * libata: clear link->eh_info.serror from ata_std_postreset() + * libata: add ST3160023AS / 3.42 to NCQ blacklist + * sata_mv: improve warnings about Highpoint RocketRAID 23xx cards + * libata-acpi: adjust constness in ata_acpi_gtm/stm() parameters + * libata: update ata_*_printk() macros such that level can be a variable + * libata: add more opcodes to ata.h + * libata: ata_dev_disable() should be called from EH context + * libata-acpi: add new hooks ata_acpi_dissociate() and + ata_acpi_on_disable() + * libata-acpi: implement and use ata_acpi_init_gtm() + * libata-acpi: implement dev->gtf_cache and evaluate _GTF right after + _STM during resume + * libata-acpi: improve ACPI disabling + * libata-acpi: improve _GTF execution error handling and reporting + * libata-acpi: implement _GTF command filtering + * libata: update atapi_eh_request_sense() such that lbam/lbah contains + buffer size + * libata: fix ATAPI draining + * fix headers_install + * revert "Hibernation: Use temporary page tables for kernel text mapping + on x86_64" + * uml: stop gdb from deleting breakpoints when running UML + * alpha: strncpy/strncat fixes + * rtc-at32ap700x: fix irq init oops + * parport: "dev->timeslice" is an unsigned long, not an int + * ecryptfs: initialize new auth_tokens before teardown + * Fix lguest documentation + * sparsemem: make SPARSEMEM_VMEMMAP selectable + * fs/Kconfig: grammar fix + * ext3, ext4: avoid divide by zero + * alpha: build fixes + * cpufreq: fix missing unlocks in cpufreq_add_dev error paths. + * mm/sparse.c: check the return value of sparse_index_alloc() + * mm/sparse.c: improve the error handling for sparse_add_one_section() + * pktcdvd: add kobject_put when kobject register fails + * drivers/macintosh/via-pmu.c: Added a missing iounmap + * drivers/cpufreq/cpufreq_stats.c section fix + * apm_event{,info}_t are userspace types + * mm: fix page allocation for larger I/O segments + * ecryptfs: set s_blocksize from lower fs in sb + * I/OAT: fixups from code comments + * I/OAT: fix null device in call to dev_err() + * fix bloat-o-meter for ppc64 + * ecryptfs: fix fsx data corruption problems + * Documentation: update hugetlb information + * Fix compilation warning in dquot.c + * SLUB: remove useless masking of GFP_ZERO + * quicklist: Set tlb->need_flush if pages are remaining in quicklist 0 + * sysctl: fix ax25 checks + * [XFS] Don't wait for pending I/Os when purging blocks beyond eof. + * [XFS] Put the correct offset in dirent d_off + * block: use jiffies conversion functions in scsi_ioctl.c + * as-iosched: fix incorrect comments + * as-iosched: fix write batch start point + * block: let elv_register() return void + * Cleanup umem driver: fix most checkpatch warnings, conform to kernel + * sched: fix crash on ia64, introduce task_current() + * sched: mark rwsem functions as __sched for wchan/profiling + * sched: sysctl, proc_dointvec_minmax() expects int values for + * sched: touch softlockup watchdog after idling + * sched: do not hurt SCHED_BATCH on wakeup + * oprofile: op_model_athlon.c support for AMD family 10h barcelona + performance counters + * clockevents: fix reprogramming decision in oneshot broadcast + * genirq: add unlocked version of set_irq_handler() + * timer: kernel/timer.c section fixes + * x86: jprobe bugfix + * x86: kprobes bugfix + * x86: also define AT_VECTOR_SIZE_ARCH + * genirq: revert lazy irq disable for simple irqs + * x86: fix "Kernel panic - not syncing: IO-APIC + timer doesn't work!" + * [SCSI] sym53c8xx: fix free_irq() regression + * [SCSI] dpt_i2o: driver is only 32 bit so don't set 64 bit DMA mask + * [SCSI] sym53c8xx: fix "irq X: nobody cared" regression + * [SCSI] initio: fix conflict when loading driver + * [SCSI] st: fix kernel BUG at include/linux/scatterlist.h:59! + * [SCSI] initio: bugfix for accessors patch + * IA64: Slim down __clear_bit_unlock + * [IA64] signal: remove redundant code in setup_sigcontext() + * [IA64] ia32 nopage + * [IA64] Avoid unnecessary TLB flushes when allocating memory + * [IA64] Two trivial spelling fixes + * [IA64] print kernel release in OOPS to make kerneloops.org happy + * [IA64] set_thread_area fails in IA32 chroot + * [IA64] Remove compiler warinings about uninitialized variable in + irq_ia64.c + * [IA64] Remove assembler warnings on head.S + * [IA64] Fix Altix BTE error return status + * [IA64] Guard elfcorehdr_addr with #if CONFIG_PROC_FS + * [IA64] make flush_tlb_kernel_range() an inline function + * [IA64] Adjust CMCI mask on CPU hotplug + * Do dirty page accounting when removing a page from the page cache + * x86 apic_32.c section fix + * x86 smpboot_32.c section fixes + * x86_32: select_idle_routine() must be __cpuinit + * x86_32: disable_pse must be __cpuinitdata + * x86: fix show cpuinfo cpu number always zero + * ps3fb: Update for firmware 2.10 + * ps3fb: Fix ps3fb free_irq() dev_id + * pata_hpt37x: Fix HPT374 detection + * mac80211: Drop out of associated state if link is lost + * mac80211: fix header ops + * NET: mac80211: fix inappropriate memory freeing + * [TG3]: Endianness annotations. + * [TG3]: Endianness bugfix. + * rtl8187: Add USB ID for Sitecom WL-168 v1 001 + * p54: add Kconfig description + * iwlwifi: fix possible priv->mutex deadlock during suspend + * ipw2200: prevent alloc of unspecified size on stack + * [IPV4] ARP: Remove not used code + * [IPSEC]: Avoid undefined shift operation when testing algorithm ID + * [XFRM]: Audit function arguments misordered + * [IPV4] ip_gre: set mac_header correctly in receive path + * [NET]: Correct two mistaken skb_reset_mac_header() conversions. + * [SPARC64]: Fix OOPS in dma_sync_*_for_device() + * sched: rt: account the cpu time during the tick + * debug: add end-of-oops marker + * mm: fix exit_mmap BUG() on a.out binary exit + * dm: table detect io beyond device + * dm mpath: hp requires scsi + * dm crypt: fix write endio + * dm: trigger change uevent on rename + * dm: merge max_hw_sector + * dm crypt: use bio_add_page + * [SPARC64]: Spelling fixes + * [SPARC32]: Spelling fixes + * [NET] include/net/: Spelling fixes + * [DCCP]: Spelling fixes + * [IRDA]: Spelling fixes + * [IPV6]: Spelling fixes + * [NET] net/core/: Spelling fixes + * [PKT_SCHED]: Spelling fixes + * [NETLABEL]: Spelling fixes + * [SCTP]: Spelling fixes + * [NETFILTER]: Spelling fixes + * [NETFILTER] ipv4: Spelling fixes + * [ATM]: Spelling fixes + * [NET]: Fix function put_cmsg() which may cause usr application memory + overflow + * x86: fix die() to not be preemptible + * x86: intel_cacheinfo.c: cpu cache info entry for Intel Tolapai + * [XFS] Fix mknod regression + * [XFS] Initialise current offset in xfs_file_readdir correctly + * Linux 2.6.24-rc6 + * [IPV4]: OOPS with NETLINK_FIB_LOOKUP netlink socket + * SLUB: Improve hackbench speed + * typhoon: endianness bug in tx/rx byte counters + * typhoon: missing le32_to_cpu() in get_drvinfo + * typhoon: set_settings broken on big-endian + * typhoon: missed rx overruns on big-endian + * typhoon: memory corruptor on big-endian if TSO is enabled + * typhoon: trivial endianness annotations + * cycx: annotations and fixes (.24 fodder?) + * asix fixes + * yellowfin: annotations and fixes (.24 fodder?) + * dl2k endianness fixes (.24 fodder?) + * r8169 endianness + * rrunner: use offsetof() instead of homegrown insanity + * 3c574 and 3c589 endianness fixes (.24?) + * fec_mpc52xx: write in C... + * 3c359 endianness annotations and fixes + * MACB: clear transmit buffers properly on transmit underrun + * UIO: Add a MAINTAINERS entry for Userspace I/O + * Modules: fix memory leak of module names + * USB: Unbreak fsl_usb2_udc + * USB: VID/PID update for sierra + * USB: New device ID for the CP2101 driver + * quicklists: do not release off node pages early + * ecryptfs: fix string overflow on long cipher names + * Fix computation of SKB size for quota messages + * Don't send quota messages repeatedly when hardlimit reached + * ecryptfs: fix unlocking in error paths + * ecryptfs: redo dget,mntget on dentry_open failure + * MAINTAINERS: mailing list archives are web links + * ps3: vuart: fix error path locking + * lib: proportion: fix underflow in prop_norm_percpu() + * pcmcia: remove pxa2xx_lubbock build warning + * kconfig: obey KCONFIG_ALLCONFIG choices with randconfig. + * tty: fix logic change introduced by wait_event_interruptible_timeout() + * uml: user of helper_wait() got missed when it got extra arguments + * V4L/DVB (6871): Kconfig: VIDEO_CX23885 must select DVB_LGDT330X + * V4L/DVB (6876): ivtv: mspx4xx needs a longer i2c udelay + * drivers/ide/: Spelling fixes + * ide-cd: fix SAMSUNG CD-ROM SCR-3231 quirk + * ide-cd: fix ACER/AOpen 24X CDROM speed reporting on big-endian machines + * ide-cd: use ide_cd_release() in ide_cd_probe() + * ide-cd: fix error messages in cdrom_{read,write}_check_ireason() + * ide-cd: add missing 'ireason' masking to cdrom_write_intr() + * ide-cd: fix error messages in cdrom_write_intr() + * ide-cd: add error message for DMA error to cdrom_read_intr() + * ide-cd: fix error message in cdrom_pc_intr() + * ide-cd: fix 'ireason' reporting in cdrom_pc_intr() + * MAINTAINERS: update ide-cd entry + * [SPARC64]: Implement pci_resource_to_user() + * mac80211: round station cleanup timer + * mac80211: warn when receiving frames with unaligned data + * [NETFILTER]: nf_conntrack_ipv4: fix module parameter compatibility + * [TUNTAP]: Fix wrong debug message. + * [NET] tc_nat: header install + * [VETH]: move veth.h to include/linux + * [IPV4]: Fix ip command line processing. + * Revert quicklist need->flush fix + * [CRYPTO] padlock: Fix spurious ECB page fault + * [POWERPC] Oprofile: Remove dependency on spufs module + * [POWERPC] PS3: Fix printing of os-area magic numbers + * [PCI] Do not enable CRS Software Visibility by default + * [IPV4] Fix ip=dhcp regression + * [SERIAL]: Fix section mismatches in Sun serial console drivers. + * [TCP]: use non-delayed ACK for congestion control RTT + * [BLUETOOTH]: put_device before device_del fix + + -- Tim Gardner Sat, 22 Dec 2007 15:16:11 -0700 + +linux (2.6.24-2.4) hardy; urgency=low + + [Alessio Igor Bogani] + + * rt: First import for Hardy + + [Amit Kucheria] + + * LPIA: Fix FTBFS for hda + * LPIA: Trim configs including disabling stock DRM + + [Tim Gardner] + + * SAUCE: Increase CONFIG_IDE_MAX_HWIFS to 8 (from 4) + - LP: #157909 + Then reverted since it causes an ABI bump. Will pick it up + again when next the ABI changes. + * Expose apm for applications. + + -- Tim Gardner Wed, 19 Dec 2007 13:17:31 -0700 + +linux (2.6.24-2.3) hardy; urgency=low + + [Amit Kucheria] + + * LPIA: Add thermal framework from Intel + * LPIA: Poulsbo-specific patches + * LPIA: Add thermal framework from Intel + + [Tim Gardner] + + * SAUCE: hdaps module does not load on Thinkpad T61P + - LP: #133636 + + [Upstream Kernel Changes] + + * Rebased against 2.6.24-rc5 + + -- Tim Gardner Wed, 12 Dec 2007 13:58:52 -0700 + +linux (2.6.24-1.2) hardy; urgency=low + + [Ben Collins] + + * cell: Remove cell custom flavour, merged upstream + * apparmor: Added module from SVN repo + * ubuntu: Update configs to enable apparmor + * ubuntu/configs: Disable vga type framebuffers on hppa32. Fixes FTBFS + + [Tim Gardner] + + * Add support for PPA builds. + + [Upstream Kernel Changes] + + * [SPARC64] Export symbols for sunvnet and sunvdc to be built modular + + -- Ben Collins Fri, 07 Dec 2007 15:18:32 -0500 + +linux (2.6.24-1.1) hardy; urgency=low + + [Ben Collins] + + * ubuntu: Disable custom binary flavours for now + * ubuntu: Remove cruft in headers-postinst + * ubuntu: Set skipabi/skipmodule to true if prev_revions == 0.0 + * ubuntu: Do not fail on missing module lists when skipmodule is set + * ubuntu: capability.ko is built-in now, no need to place in initrd. + * ubuntu: Change to "linux" instead of "linux-source-2.6.x" + * d-i: cdrom-modules disappeared, and sha256/aes modules renamed. + * ubuntu-build: Add asm_link= to arch rules, and use them + * config: Re-enable snd-hda-intel + + -- Ben Collins Wed, 28 Nov 2007 12:58:37 -0500 + +linux-source-2.6.22 (2.6.22-14.46) gutsy; urgency=low + + [Upstream Kernel Changes] + + * [SPARC64]: Fix bugs in SYSV IPC handling in 64-bit processes. + + -- Kyle McMartin Sun, 14 Oct 2007 20:30:09 +0000 + +linux-source-2.6.22 (2.6.22-14.45) gutsy; urgency=low + + [Upstream Kernel Changes] + + * [SPARC64]: Fix register usage in xor_raid_4(). + + -- Kyle McMartin Sun, 14 Oct 2007 12:34:44 -0400 + +linux-source-2.6.22 (2.6.22-14.44) gutsy; urgency=low + + [Kyle McMartin] + + * Revert "sparc wants ehci built in" + + [Upstream Kernel Changes] + + * Revert "[PATCH]: Gutsy OHCI hang workaround for Huron" + * [USB]: Serialize EHCI CF initialization. + + -- Kyle McMartin Sun, 14 Oct 2007 16:25:51 +0000 + +linux-source-2.6.22 (2.6.22-14.43) gutsy; urgency=low + + [Kyle McMartin] + + * sparc wants ehci built in + + -- Kyle McMartin Tue, 09 Oct 2007 20:07:58 +0000 + +linux-source-2.6.22 (2.6.22-14.42) gutsy; urgency=low + + [Kyle McMartin] + + * fix up module-check to bail early if asked to ignore modules + * disable kernel DRM on lpia (we provide one in lum) + - LP: #145168 + * add ignore for ia64 abi too + + [Upstream Kernel Changes] + + * [NIU]: Use netif_msg_*(). + * [NIU]: Use pr_info(). + * [NIU]: Remove redundant BUILD_BUG_ON() in __niu_wait_bits_clear(). + * [NIU]: Remove BUG_ON() NULL pointer checks. + * [NIU]: Use dev_err(). + * [NIU]: Fix x86_64 build failure. + * [NIU]: Use linux/io.h instead of asm/io.h + * [NIU]: Fix some checkpatch caught coding style issues. + * [NIU]: Fix shadowed local variables. + * [NIU]: Fix locking errors in link_status_10g(). + * [NIU]: Document a few magic constants using comments. + * [NIU]: MII phy handling fixes. + * [NIU]: Make sure link_up status is set to something in + link_status_{1,10}g(). + * [PATCH]: Gutsy OHCI hang workaround for Huron + + -- Kyle McMartin Tue, 09 Oct 2007 17:25:06 +0000 + +linux-source-2.6.22 (2.6.22-14.41) gutsy; urgency=low + + [Ben Collins] + + * ubuntu/d-i: Add niu to nic-modules + + [Kyle McMartin] + + * vesafb is not for ia64 + * remove CONFIG_NIU from places it shouldn't be + * fix orinoco_cs oops + - LP: #149997 + + [Upstream Kernel Changes] + + * [SPARC64]: Allow userspace to get at the machine description. + * [SPARC64]: Niagara-2 optimized copies. + * [SPARC64]: Do not touch %tick_cmpr on sun4v cpus. + * [SPARC64]: SMP trampoline needs to avoid %tick_cmpr on sun4v too. + * [SPARC64]: Create a HWCAP_SPARC_N2 and report it to userspace on + Niagara-2. + * [MATH-EMU]: Fix underflow exception reporting. + * [SPARC64]: Need to clobber global reg vars in switch_to(). + * [MATH]: Fix typo in FP_TRAPPING_EXCEPTIONS default setting. + * [SUNVDC]: Use slice 0xff on VD_DISK_TYPE_DISK. + * [SPARC64]: Fix type and constant sizes wrt. sun4u IMAP/ICLR handling. + * [SPARC64]: Enable MSI on sun4u Fire PCI-E controllers. + * [SPARC64]: Fix several bugs in MSI handling. + * [SPARC64]: Fix booting on V100 systems. + * [SPARC64]: Fix lockdep, particularly on SMP. + * [SPARC64]: Warn user if cpu is ignored. + * [SUNSAB]: Fix several bugs. + * [SUNSAB]: Fix broken SYSRQ. + * [SPARC64]: Fix missing load-twin usage in Niagara-1 memcpy. + * [SPARC64]: Don't use in/local regs for ldx/stx data in N1 memcpy. + * [SPARC64]: Fix domain-services port probing. + * [SPARC64]: VIO device addition log message level is too high. + * [SPARC64]: check fork_idle() error + * [SPARC64]: Fix 'niu' complex IRQ probing. + * [NIU]: Add Sun Neptune ethernet driver. + + -- Kyle McMartin Tue, 09 Oct 2007 00:38:16 +0000 + +linux-source-2.6.22 (2.6.22-13.40) gutsy; urgency=low + + [Amit Kucheria] + + * Enable CONFIG_VM86 for LPIA + - LP: #146311 + * Update configuration files + * Disable MSI by default + * Add mmconf documentation + * Update configuration files + + [Bartlomiej Zolnierkiewicz] + + * ide-disk: workaround for buggy HPA support on ST340823A (take 3) + - LP: #26119 + + [Ben Collins] + + * ubuntu/cell: Fixup ps3 related modules for d-i, enable RTAS console + * ubuntu/cell: Enable CELLEB and related modules (pata_scc) + * ubuntu/cell: Move ps3rom to storage-core. Also use spidernet, not + spider_net. + * ubuntu/cell: Set PS3_MANAGER=y + * ubuntu: Set NR_CPUS=256 for sparc64-smp + + [Chuck Short] + + * [USB] USB] Support for MediaTek MT6227 in cdc-acm. + - LP: #134123 + * [XEN] Fix xen vif create with more than 14 guests. + - LP: #14486 + + [Jorge Juan Chico] + + * ide: ST320413A has the same problem as ST340823A + - LP: #26119 + + [Kyle McMartin] + + * fix -rt build + * fix ia32entry-xen.S for CVE-2007-4573 + * fix build when CONFIG_PCI_MSI is not set + + [Matthew Garrett] + + * hostap: send events on data interface as well as master interface + - LP: #57146 + * A malformed _GTF object should not prevent ATA device recovery + - LP: #139079 + * hostap: send events on data interface as well as master interface + - LP: #57146 + * A malformed _GTF object should not prevent ATA device recovery + - LP: #139079 + * Don't lose appletouch button release events + * Fix build with appletouch change + * Disable Thinkpad backlight support on machines with ACPI video + - LP: #148055 + * Don't attempt to register a callback if there is no CMOS object + - LP: #145857 + * Update ACPI bay hotswap code to support locking + - LP: #148219 + * Update ACPI bay hotswap code to support locking + - LP: #148219 + * Don't attempt to register a callback if there is no CMOS object + - LP: #145857 + * Disable Thinkpad backlight support on machines with ACPI video + - LP: #148055 + + [Steffen Klassert] + + * 3c59x: fix duplex configuration + - LP: #94186 + + [Thomas Gleixner] + + * clockevents: remove the suspend/resume workaround^Wthinko + + [Tim Gardner] + + * orinoco_cs.ko missing + - LP: #125832 + * Marvell Technology ethernet card not recognized and not operational + - LP: #135316 + * Marvell Technology ethernet card not recognized and not operational + - LP: #135316 + * acpi_scan_rsdp() breaks some PCs by not honouring ACPI specification + - LP: #144336 + * VIA southbridge Intel id missing + - LP: #128289 + * Add T-Sinus 111card to hostap_cs driver to be able to upload firmware + - LP: #132466 + * RTL8111 PCI Express Gigabit driver r8169 big files produce slow file + transfer + - LP: #114171 + * Guest OS does not recognize a lun with non zero target id on Vmware ESX + Server + - LP: #140761 + * Modualrize vesafb + - LP: #139505 + * Nikon cameras need support in unusual_devs.h + - LP: #134477 + * agp for i830m broken in gutsy + - LP: #139767 + * hdaps: Added support for Thinkpad T61 + - LP: #147383 + * xen: Update config for i386 + - LP: #139047 + * xen: resync for amd64 + - LP: #139047 + * ide-disk: workaround for buggy HPA support on ST340823A (take 4) + - LP: #26119 + + [Upstream Kernel Changes] + + * Convert snd-page-alloc proc file to use seq_file (CVE-2007-4571) + * Linux 2.6.22.8 + * ACPI: disable lower idle C-states across suspend/resume + * V4L: ivtv: fix VIDIOC_S_FBUF: new OSD values were never set + * DVB: get_dvb_firmware: update script for new location of sp8870 + firmware + * DVB: get_dvb_firmware: update script for new location of tda10046 + firmware + * DVB: b2c2-flexcop: fix Airstar HD5000 tuning regression + * setpgid(child) fails if the child was forked by sub-thread + * sigqueue_free: fix the race with collect_signal() + * kconfig: oldconfig shall not set symbols if it does not need to + * MTD: Makefile fix for mtdsuper + * USB: fix linked list insertion bugfix for usb core + * ACPI: Validate XSDT, use RSDT if XSDT fails + * POWERPC: Flush registers to proper task context + * 3w-9xxx: Fix dma mask setting + * MTD: Initialise s_flags in get_sb_mtd_aux() + * JFFS2: fix write deadlock regression + * V4L: cx88: Avoid a NULL pointer dereference during mpeg_open() + * hwmon: End of I/O region off-by-one + * Fix debug regression in video/pwc + * splice: fix direct splice error handling + * rpc: fix garbage in printk in svc_tcp_accept() + * disable sys_timerfd() + * afs: mntput called before dput + * Fix DAC960 driver on machines which don't support 64-bit DMA + * Fix "Fix DAC960 driver on machines which don't support 64-bit DMA" + * firewire: fw-ohci: ignore failure of pci_set_power_state (fix suspend + regression) + * futex_compat: fix list traversal bugs + * Leases can be hidden by flocks + * ext34: ensure do_split leaves enough free space in both blocks + * nfs: fix oops re sysctls and V4 support + * dir_index: error out instead of BUG on corrupt dx dirs + * ieee1394: ohci1394: fix initialization if built non-modular + * Correctly close old nfsd/lockd sockets. + * Fix race with shared tag queue maps + * crypto: blkcipher_get_spot() handling of buffer at end of page + * fix realtek phy id in forcedeth + * Fix decnet device address listing. + * Fix device address listing for ipv4. + * Fix inet_diag OOPS. + * Fix IPV6 append OOPS. + * Fix IPSEC AH4 options handling + * Fix ipv6 double-sock-release with MSG_CONFIRM + * Fix IPV6 DAD handling + * Fix ipv6 source address handling. + * Fix oops in vlan and bridging code + * Fix tc_ematch kbuild + * Handle snd_una in tcp_cwnd_down() + * Fix TCP DSACK cwnd handling + * Fix datagram recvmsg NULL iov handling regression. + * Fix pktgen src_mac handling. + * Fix sparc64 v100 platform booting. + * bcm43xx: Fix cancellation of work queue crashes + * Linux 2.6.22.9 + * usb: serial/pl2303: support for BenQ Siemens Mobile Phone EF81 + * pata_it821x: fix lost interrupt with atapi devices + * i915: make vbl interrupts work properly on i965g/gm hw. + + -- Kyle McMartin Thu, 04 Oct 2007 13:57:53 +0000 + +linux-source-2.6.22 (2.6.22-12.39) gutsy; urgency=low + + [Ben Collins] + + * ubuntu: Re-order deps so that binary-custom is done before + binary-udebs. Fixes ppc build + + [Upstream Kernel Changes] + + * x86_64: Zero extend all registers after ptrace in 32bit entry path. + * Linux 2.6.22.7 + + -- Ben Collins Sun, 23 Sep 2007 11:05:32 -0400 + +linux-source-2.6.22 (2.6.22-12.38) gutsy; urgency=low + + [Kyle McMartin] + + * add -12 abi files + * update getabis for new flavours + + -- Kyle McMartin Fri, 21 Sep 2007 13:35:49 -0400 + +linux-source-2.6.22 (2.6.22-12.37) gutsy; urgency=low + + [Kyle McMartin] + + * enable d-i for cell flavour + * ignore ABI check on all hppa flavours + + -- Kyle McMartin Fri, 21 Sep 2007 11:28:34 -0400 + +linux-source-2.6.22 (2.6.22-12.36) gutsy; urgency=low + + [Ben Collins] + + * ABI bump due to LED support being enabled. + + [Kyle McMartin] + + * fix memory leak in psparse.c + - Bug introduced in previous commit to acpi + + [Upstream Kernel Changes] + + * Ubuntu: Allocate acpi_devices structure rather than leaving it on the + stack. + * ipw2100: Fix `iwpriv set_power` error + * Fix ipw2200 set wrong power parameter causing firmware error + * [SCSI] Fix async scanning double-add problems + - LP: #110997 + + -- Ben Collins Thu, 20 Sep 2007 11:34:52 -0400 + +linux-source-2.6.22 (2.6.22-11.34) gutsy; urgency=low + + [Alan Stern] + + * USB: disable autosuspend by default for non-hubs + - LP: #85488 + + [Ben Collins] + + * ubuntu: Enable LEDS_TRIGGERS and related options + - Needed for iwlwifi + * ubuntu: Add real ABI files for virtual flavour + * ubuntu: Re-enable missing CONFIG_SERPENT for hppa64 + - Noticed by Lamont + * ubuntu: Add linux-headers postinst to handle hooks + - LP: #125816 + * ubuntu: Add support for /etc/kernel/headers_postinst.d/ to + headers-postinst + - LP: #120049 + * cell: Add binary-custom flavour "cell" to support ps3 + + [Mattia Dongili] + + * sony-laptop: restore the last user requested brightness level on + resume. + - LP: #117331 + + [Tejun Heo] + + * ata_piix: fix suspend/resume for some TOSHIBA laptops + - LP: #139045 + * PCI: export __pci_reenable_device() + - needed for ata_piix change + + [Tim Gardner] + + * Enable Sierra Wireless MC8775 0x6813 + - LP: #131167 + + [Zhang Rui] + + * ACPI: work around duplicate name "VID" problem on T61 + - Noted by mjg59 + + -- Ben Collins Sun, 16 Sep 2007 22:31:47 -0400 + +linux-source-2.6.22 (2.6.22-11.33) gutsy; urgency=low + + [Alessio Igor Bogani] + + * rt: Update to rt9 + * rt: Update configuration files + + [Ben Collins] + + * ubuntu: Enable A100 driver + - LP: #138632 + * libata: Default to hpa being overridden + + [Chuck Short] + + * [HDAPS] Add support for Thinkpad R61. + * [LIBATA] Add more hard drives to blacklist. + * [USB] Added support for Sprint Pantech PX-500. + * [XEN] No really enable amd64. + * [XEN] Fix amd64 yet again. + + [Matthew Garrett] + + * alter default behaviour of ACPI video module + * Add infrastructure for notification on ACPI method execution + * Get thinkpad_acpi to send notifications on CMOS updates + * Add support to libata-acpi for acpi-based bay hotplug + + [Phillip Lougher] + + * Add kernel flavour optimised for virtualised environments + * Change abi-check script to check for $flavour.ignore in previous abi + * Disable abi and module check for virtual flavour + + [Richard Hughes] + + * Refresh laptop lid status on resume + + [Upstream Kernel Changes] + + * [pata_marvell]: Add more identifiers + + -- Ben Collins Sun, 16 Sep 2007 22:13:08 -0400 + +linux-source-2.6.22 (2.6.22-11.32) gutsy; urgency=low + + [Amit Kucheria] + + * Build system: Allow custom builds to comprise multiple patches + * Move UME to a Custom build and add first setup of thermal framework + + [Ben Collins] + + * ubuntu: Enable CONFIG_BLK_DEV_IO_TRACE + * bcm203x: Fix firmware loading + - LP: #85247 + * ubuntu: mtd changes caused module renaming. Ignore + * rt: Do not patch top level Makefile for SUBLEVEL. Will always end up + breaking + + [Chuck Short] + + * [USB] Unusual Device support for Gold MP3 Player Energy + - LP: #125250 + * [SIERRA] Adds support for Onda H600 ZTE MF330 + - LP: #129433 + * [HDAPS] Add Thinkpad T61P to whitelist. + - LP: #133636 + * [USB] Add support for Toshiba (Novatel Wireless) HSDPA for M400. + - LP: #133650 + + [Kyle McMartin] + + * apparmor 10.3 hooks + * unionfs 2.1 hooks + * nuke UNION_FS stuff from fs/{Kconfig,Makefile} + + [Tim Gardner] + + * Paravirt-ops I/O hypercalls + * Fix lazy vmalloc bug for Gutsy + * bluetooth headset patch + - LP: #130870 + * Add the PCI ID of this ICH4 in list of laptops that use short cables. + * v2.6.22.5 merge + * Update Xen config options. + - LP: #132726 + * Remove mtd modules from ABI + * Support parallel= in DEB_BUILD_OPTIONS + - LP: #136426 + + [Upstream Kernel Changes] + + * hwmon: fix w83781d temp sensor type setting + * hwmon: (smsc47m1) restore missing name attribute + * sky2: restore workarounds for lost interrupts + * sky2: carrier management + * sky2: check for more work before leaving NAPI + * sky2: check drop truncated packets + * revert "x86, serial: convert legacy COM ports to platform devices" + * ACPICA: Fixed possible corruption of global GPE list + * ACPICA: Clear reserved fields for incoming ACPI 1.0 FADTs + * AVR32: Fix atomic_add_unless() and atomic_sub_unless() + * r8169: avoid needless NAPI poll scheduling + * forcedeth: fix random hang in forcedeth driver when using netconsole + * libata: add ATI SB700 device IDs to AHCI driver + * Hibernation: do not try to mark invalid PFNs as nosave + * i386: allow debuggers to access the vsyscall page with compat vDSO + * x86_64: Check for .cfi_rel_offset in CFI probe + * x86_64: Change PMDS invocation to single macro + * i386: Handle P6s without performance counters in nmi watchdog + * i386: Fix double fault handler + * JFFS2 locking regression fix. + * [Input]: appletouch - improve powersaving for Geyser3 devices + * [Input]: add driver for Fujitsu serial touchscreens + * [sdhci]: add support to ENE-CB714 + * v2.6.22.5 + * [MTD] Makefile fix for mtdsuper + * ocfs2: Fix bad source start calculation during kernel writes + * NET: Share correct feature code between bridging and bonding + * sky2: don't clear phy power bits + * uml: fix previous request size limit fix + * i386: fix lazy mode vmalloc synchronization for paravirt + * signalfd: fix interaction with posix-timers + * signalfd: make it group-wide, fix posix-timers scheduling + * DCCP: Fix DCCP GFP_KERNEL allocation in atomic context + * IPV6: Fix kernel panic while send SCTP data with IP fragments + * IPv6: Invalid semicolon after if statement + * Fix soft-fp underflow handling. + * Netfilter: Missing Kbuild entry for netfilter + * SNAP: Fix SNAP protocol header accesses. + * NET: Fix missing rcu unlock in __sock_create() + * SPARC64: Fix sparc64 task stack traces. + * SPARC64: Fix sparc64 PCI config accesses on sun4u + * TCP: Do not autobind ports for TCP sockets + * TCP: Fix TCP rate-halving on bidirectional flows. + * TCP: Fix TCP handling of SACK in bidirectional flows. + * PPP: Fix PPP buffer sizing. + * PCI: lets kill the 'PCI hidden behind bridge' message + * PCI: disable MSI on RS690 + * PCI: disable MSI on RD580 + * PCI: disable MSI on RX790 + * USB: allow retry on descriptor fetch errors + * USB: fix DoS in pwc USB video driver + * usb: add PRODUCT, TYPE to usb-interface events + * Linux 2.6.22.6 + * V4L/DVB (6042): b2c2-flexcop: fix Airstar HD5000 tuning regression + * V4L/DVB (5967): ivtv: fix VIDIOC_S_FBUF:new OSD values where never set + * Re-add _GTM and _STM support + + -- Ben Collins Fri, 31 Aug 2007 16:26:56 -0400 + +linux-source-2.6.22 (2.6.22-10.30) gutsy; urgency=low + + * URGENT upload to fix FTBFS with xen-{i386,amd64} configs, + lpia d-i ftbfs, xen ftbfs. + * URGENT fix module-check to actually ignore things + * URGENT ignore ume modules + + [Alek Du] + + * Add Intel Poulsbo chipset Libata support + + [Amit Kucheria] + + * Update configuration files + * Enable stylus on Lenovo X60/X61 thinkpads + + [Ben Collins] + + * ubuntu: Disable snd-hda-intel, in favor of lum updated version + + [Kyle McMartin] + + * apparmor 10.3 hooks + * add lpia d-i udeb generation + * fix bits of rt/diff for -rt8 + * fix rt/diff for 2.6.22.3 changes + * fix up rt/diff for stable 2.6.22.4 + + [LaMont Jones] + + * Update configuration files + + [Phillip Lougher] + + * WriteSupportForNTFS: make fuse module available to d-i + + [Tim Gardner] + + * Gutsy Tribe 3 CD don't load on Dell Inspiron 1501 + - LP: #121111 + * Update configuration files + * Update configuration files + * Update configuration files + + [Upstream Kernel Changes] + + * [SPARC64]: Fix handling of multiple vdc-port nodes. + * [SPARC64]: Tweak assertions in sun4v_build_virq(). + * [SPARC64]: Fix log message type in vio_create_one(). + * [SPARC64]: Fix two year old bug in early bootup asm. + * [SPARC64]: Improve VIO device naming further. + * [SPARC64]: Handle multiple domain-services-port nodes properly. + * [SPARC64]: Add proper multicast support to VNET driver. + * [SPARC64]: Do not flood log with failed DS messages. + * [SPARC64]: Use KERN_ERR in IRQ manipulation error printks. + * [SPARC64]: Fix virq decomposition. + * [SPARC]: Fix serial console device detection. + * [SPARC64]: fix section mismatch warning in pci_sunv4 + * [SPARC64]: fix section mismatch warning in mdesc.c + * [SPARC64] viohs: extern on function definition + * [SPARC64]: Fix sun4u PCI config space accesses on sun4u. + * [SPARC64]: Fix show_stack() when stack argument is NULL. + * [SUNLANCE]: Fix sparc32 crashes by using of_*() interfaces. + * [SPARC]: Centralize find_in_proplist() instead of duplicating N times. + * [SPARC64]: Fix hard-coding of cpu type output in /proc/cpuinfo on + sun4v. + * [SPARC64]: Do not assume sun4v chips have load-twin/store-init support. + * [SPARC64]: Fix memory leak when cpu hotplugging. + * USB: cdc-acm: fix sysfs attribute registration bug + * TCP FRTO retransmit bug fix + * Fix TC deadlock. + * Fix IPCOMP crashes. + * Fix console write locking in sparc drivers. + * Add a PCI ID for santa rosa's PATA controller. + * Missing header include in ipt_iprange.h + * SCTP scope_id handling fix + * Fix rfkill IRQ flags. + * gen estimator timer unload race + * gen estimator deadlock fix + * Fix error queue socket lookup in ipv6 + * Fix ipv6 link down handling. + * Netpoll leak + * Sparc64 bootup assembler bug + * Fix ipv6 tunnel endianness bug. + * Fix sparc32 memset() + * Fix sparc32 udelay() rounding errors. + * Fix TCP IPV6 MD5 bug. + * KVM: SVM: Reliably detect if SVM was disabled by BIOS + * USB: fix warning caused by autosuspend counter going negative + * usb-serial: Fix edgeport regression on non-EPiC devices + * Fix reported task file values in sense data + * aacraid: fix security hole + * firewire: fw-sbp2: set correct maximum payload (fixes CardBus adapters) + * make timerfd return a u64 and fix the __put_user + * V4L: Add check for valid control ID to v4l2_ctrl_next + * V4L: ivtv: fix broken VBI output support + * V4L: ivtv: fix DMA timeout when capturing VBI + another stream + * V4L: ivtv: Add locking to ensure stream setup is atomic + * V4L: wm8775/wm8739: Fix memory leak when unloading module + * Input: lifebook - fix an oops on Panasonic CF-18 + * splice: fix double page unlock + * drm/i915: Fix i965 secured batchbuffer usage (CVE-2007-3851) + * Fix leak on /proc/lockdep_stats + * CPU online file permission + * Fix user struct leakage with locked IPC shem segment + * md: handle writes to broken raid10 arrays gracefully + * md: raid10: fix use-after-free of bio + * pcmcia: give socket time to power down + * Fix leaks on /proc/{*/sched, sched_debug, timer_list, timer_stats} + * futex: pass nr_wake2 to futex_wake_op + * "ext4_ext_put_in_cache" uses __u32 to receive physical block number + * Include serial_reg.h with userspace headers + * dm io: fix panic on large request + * i386: HPET, check if the counter works + * fw-ohci: fix "scheduling while atomic" + * firewire: fix memory leak of fw_request instances + * softmac: Fix ESSID problem + * eCryptfs: ecryptfs_setattr() bugfix + * nfsd: fix possible read-ahead cache and export table corruption + * readahead: MIN_RA_PAGES/MAX_RA_PAGES macros + * fs: 9p/conv.c error path fix + * forcedeth bug fix: cicada phy + * forcedeth bug fix: vitesse phy + * forcedeth bug fix: realtek phy + * acpi-cpufreq: Proper ReadModifyWrite of PERF_CTL MSR + * jbd commit: fix transaction dropping + * jbd2 commit: fix transaction dropping + * hugetlb: fix race in alloc_fresh_huge_page() + * do not limit locked memory when RLIMIT_MEMLOCK is RLIM_INFINITY + * uml: limit request size on COWed devices + * sony-laptop: fix bug in event handling + * destroy_workqueue() can livelock + * drivers/video/macmodes.c:mac_find_mode() mustn't be __devinit + * cfq-iosched: fix async queue behaviour + * libata: add FUJITSU MHV2080BH to NCQ blacklist + * ieee1394: revert "sbp2: enforce 32bit DMA mapping" + * nfsd: fix possible oops on re-insertion of rpcsec_gss modules + * dm raid1: fix status + * dm io: fix another panic on large request + * dm snapshot: permit invalid activation + * dm: disable barriers + * cr_backlight_probe() allocates too little storage for struct cr_panel + * ACPI: dock: fix opps after dock driver fails to initialize + * Hangup TTY before releasing rfcomm_dev + * Keep rfcomm_dev on the list until it is freed + * nf_conntrack: don't track locally generated special ICMP error + * IPV6: /proc/net/anycast6 unbalanced inet6_dev refcnt + * sysfs: release mutex when kmalloc() failed in sysfs_open_file(). + * Netfilter: Fix logging regression + * USB: fix for ftdi_sio quirk handling + * sx: switch subven and subid values + * UML: exports for hostfs + * Linux 2.6.22.2 + * fix oops in __audit_signal_info() + * random: fix bound check ordering (CVE-2007-3105) + * softmac: Fix deadlock of wx_set_essid with assoc work + * ata_piix: update map 10b for ich8m + * PPC: Revert "[POWERPC] Don't complain if size-cells == 0 in + prom_parse()" + * PPC: Revert "[POWERPC] Add 'mdio' to bus scan id list for platforms + with QE UEC" + * powerpc: Fix size check for hugetlbfs + * direct-io: fix error-path crashes + * stifb: detect cards in double buffer mode more reliably + * pata_atiixp: add SB700 PCI ID + * CPUFREQ: ondemand: fix tickless accounting and software coordination + bug + * CPUFREQ: ondemand: add a check to avoid negative load calculation + * Linux 2.6.22.3 + * intel_agp: really fix 945/965GME + * Reset current->pdeath_signal on SUID binary execution (CVE-2007-3848) + * MSS(mmc/sd/sdio) driver patch + + -- Kyle McMartin Thu, 16 Aug 2007 12:17:27 -0400 + +linux-source-2.6.22 (2.6.22-9.25) gutsy; urgency=low + + [Kyle McMartin] + + * ubuntu: Fix FTBFS -- forgot to bump debian/abi + + -- Kyle McMartin Thu, 02 Aug 2007 22:13:28 +0000 + +linux-source-2.6.22 (2.6.22-9.24) gutsy; urgency=low + + [Colin Watson] + + * provide Provides for fs-*-modules udebs + + [Matthias Klose] + + * test $dilist before using it + + [Lamont Jones] + + * hppa: Update abi files + + -- Kyle McMartin Thu, 02 Aug 2007 18:26:34 +0000 + +linux-source-2.6.22 (2.6.22-9.23) gutsy; urgency=low + + [Ben Collins] + + * ubuntu: Add missing newline to module-check script + * ubuntu: Add lpia to linux-libc-dev. Should finally build now. + + -- Ben Collins Thu, 02 Aug 2007 13:10:23 -0400 + +linux-source-2.6.22 (2.6.22-9.22) gutsy; urgency=low + + [Ben Collins] + + * ubuntu: Use DEB_HOST_ARCH, not DEB_HOST_ARCH_CPU + + -- Ben Collins Thu, 02 Aug 2007 08:44:09 -0400 + +linux-source-2.6.22 (2.6.22-9.21) gutsy; urgency=low + + [Ben Collins] + + * lpia: Add build stuff for lpia architecture + + [LaMont Jones] + + * abi files for hppa + * UBUNTU-HPPA: configs that seem to work + * hppa: abi files for 9.20 + + -- Ben Collins Wed, 01 Aug 2007 11:12:59 -0400 + +linux-source-2.6.22 (2.6.22-9.20) gutsy; urgency=low + + [Ben Collins] + + * tulip: Fix for Uli5261 chipsets. + * tulip: Define ULI PCI ID's + * tulip: Let dmfe handle davicom on non-sparc + * input: Allow root to inject unknown scan codes. + * irda: Default to dongle type 9 on IBM hardware + * input/mouse/alps: Do not call psmouse_reset() for alps + * pcmcia: Do not insert pcmcia cards on resume + * ide-cd: Disable verbose errors. + * block: Make CDROMEJECT more robust + * pm: Config option to disable handling of console during suspend/resume. + * version: Implement version_signature proc file. + * update toshiba_acpi to 0.19a-dev + * xpad: Update to latest version from xbox-linux. + * ubuntu: Enable setting of CONFIG_VERSION_SIGNATURE at build time + * toshiba_acpi: Don't use init_MUTEX_LOCKED + + [Chuck Short] + + * [USB]: add ASUS LCM to the blacklist + * [NET]: Add mcp73 to forcedeth. + * [USB]: Added support for Sanwa PC5000 multimeter usb cable (KB-USB2). + * [ATA] Add support for Sb700 AHCI nor-raid5 and raid5 + + [Fabio M. Di Nitto] + + * drivers/char/vt.c: make promcon driver init a boot option. + + [Kyle McMartin] + + * Disable MMCONFIG by default + + [Phillip Lougher] + + * fix NFS mounting regression from Edgy->Feisty + * r8169: disable TSO by default for RTL8111/8168B chipsets. + + [Tim Gardner] + + * Catch nonsense keycodes and silently ignore + * Cause SoftMac to emit an association event when setting ESSID. + + -- Ben Collins Mon, 30 Jul 2007 12:01:43 -0400 + +linux-source-2.6.22 (2.6.22-9.19) gutsy; urgency=low + + [Amit Kucheria] + + * Fix for FTBFS bug 123178 + * Fix for FTBFS bug 123178 + * Add devices to USB quirks to prevent USB autosuspend + * More devices added to USB quirks + - LP: #85488 + * Support for ENE CB-712/4 SD card reader + * Reorder quirk list based on Vendor/Product ID + + [Ben Collins] + + * ubuntu: Enable HOTPLUG_CPU in sparc64-smp config. + * ubuntu: Add xen to amd64 custom builds + * ubuntu: Update real-time kernel to -rt4 + * rt: Patch from Alessio Igor Bogani for RT-8 + + [Chuck Short] + + * IDE: add MHV2080BH to NCQ blacklist + * XEN: update to 2.6.22 final and amd64 support. + * NET: Add more pci-ids to zd1211rw + * IDE: add new PCI ID + * USB: fix oops in ftdi_sio + + [Eric Piel] + + * ACPI: Allow custom DSDT tables to be loaded from initramfs + + [Ryan Lortie] + + * Macbook calibration loop fix + - LP: #54621 + + [Upstream Kernel Changes] + + * NETFILTER: {ip, nf}_conntrack_sctp: fix remotely triggerable NULL ptr + dereference (CVE-2007-2876) + * Linux 2.6.22.1 + * [SPARC64]: Use KERN_ERR in sun4v IRQ printk()'s. + * [SPARC64]: Add LDOM virtual channel driver and VIO device layer. + * [SPARC64]: Add Sun LDOM virtual network driver. + * [SPARC64]: Add Sun LDOM virtual disk driver. + * [SPARC64]: Create proper obppath sysfs files for VIO bus devices. + * [SPARC64] LDC: Do limited polled retry on setting RX queue head. + * [SUNVNET]: Validate RX descriptor size field. + * [SPARC64]: Add missing symbol exports for LDOM infrastructure. + * [SPARC64]: Temporary workaround for LDC INO double-delivery. + * [SPARC64]: Create 'devspec' nodes for vio devices. + * [SPARC64]: vdev->type can be NULL, handle this in devspec_show(). + * [SPARC64]: Assorted LDC bug cures. + * [SPARC64]: Add domain-services nodes to VIO device tree. + * [SPARC64]: Export powerd facilities for external entities. + * [SPARC64]: Initial domain-services driver. + * [SPARC64]: Use more mearningful names for IRQ registry. + * [SPARC64]: Abstract out mdesc accesses for better MD update handling. + * [SPARC64]: Fix MD property lifetime bugs. + * [SPARC64]: Fix setting of variables in LDOM guest. + * [SPARC64]: Initial LDOM cpu hotplug support. + * [SPARC64]: Unconditionally register vio_bus_type. + * [SPARC64]: Fix build regressions added by dr-cpu changes. + * [SPARC64]: mdesc.c needs linux/mm.h + * [SPARC64]: SMP build fixes. + * [SPARC64]: More sensible udelay implementation. + * [SPARC64]: Process dr-cpu events in a kthread instead of workqueue. + * [SPARC64]: Add ->set_affinity IRQ handlers. + * [SPARC64]: Fix leak when DR added cpu does not bootup. + * [SPARC64]: Clear cpu_{core,sibling}_map[] in + smp_fill_in_sib_core_maps() + * [SPARC64]: Give more accurate errors in dr_cpu_configure(). + * [SERIAL]: Fix console write locking in sparc drivers. + * [TIMER]: Fix clockevent notifications on 64-bit. + * [SPARC64]: dr-cpu unconfigure support. + * [SPARC64]: Fix UP build. + * [SPARC64]: SMP build fix. + * [SPARC64]: Fix race between MD update and dr-cpu add. + * [SERIAL] SUNHV: Fix jerky console on LDOM guests. + * [SPARC64]: Kill explicit %gl register reference. + * [SPARC64]: Add basic infrastructure for MD add/remove notification. + * [SPARC64]: Simplify VDC device probing. + * [SPARC64]: Simplify VNET probing. + * [SPARC64]: Massively simplify VIO device layer and support hot + add/remove. + * [SPARC64]: Handle LDC resets properly in domain-services driver. + * [SPARC64]: Handle reset events in vio_link_state_change(). + * [SPARC64]: Fix reset handling in VNET driver. + * [SPARC64]: Set vio->desc_buf to NULL after freeing. + * [SPARC64]: Fix MODULE_DEVICE_TABLE() specification in VDC and VNET. + * [SPARC64]: Fix device type matching in VIO's devspec_show(). + * Add empty + * Add dummy isa_(bus|virt)_to_(virt|bus) inlines + * Clean up sti_flush + * Do not allow STI_CONSOLE to be modular + * Use compat_sys_getdents + + -- Ben Collins Sat, 28 Jul 2007 12:30:53 -0400 + +linux-source-2.6.22 (2.6.22-8.18) gutsy; urgency=low + + [Ben Collins] + + * ubuntu: *sigh* update xen config to fix FTBFS + + -- Ben Collins Thu, 12 Jul 2007 14:23:20 +0100 + +linux-source-2.6.22 (2.6.22-8.17) gutsy; urgency=low + + [Ben Collins] + + * ubuntu: Actually enable the -xen build. + + -- Ben Collins Thu, 12 Jul 2007 09:51:01 +0100 + +linux-source-2.6.22 (2.6.22-8.16) gutsy; urgency=low + + * Removed CONFIG_BLINK from all configs and added to modules.ignore + * This fixes a build failure for 8.15 + + [Alexey Starikovskiy] + + * Fix ACPI battery detection on Asus + + [Amit Kucheria] + + * Export symbols required to build GFS1 in LUM + * Update configuration files + * 2.6.22-7.14 ABI + * Remove old ABI + * Update d-i modules to support Sparc LDOM + * Introducing the UME kernel flavour + + [Jacob Pan] + + * Poulsbo SMBus Controller + * Intel Poulsbo SCH IDE Controller + * Intel Poulsbo HD audio controller + + [Phillip Lougher] + + * xen: Update custom binary flavour (Xen 3.1 for 2.6.22-rc5) + * xen: Update xen/config.i386 to enable PAE + + [Upstream Kernel Changes] + + * [SCSI] fusion: fix for BZ 8426 - massive slowdown on SCSI CD/DVD drive + * [XFS] Update the MAINTAINERS file entry for XFS. + * IB/mlx4: Fix handling of wq->tail for send completions + * IB/mlx4: Fix warning in rounding up queue sizes + * [SCSI] ESP: Don't forget to clear ESP_FLAG_RESETTING. + * firewire: fix hang after card ejection + * ieee1394: fix to ether1394_tx in ether1394.c + * [ARM] Add support for pause_on_oops and display preempt/smp options + * sh: Fix restartable syscall arg5 clobbering. + * ACPI: gracefully print null trip-point device + * ACPICA: fix error path in new external package objects as method + arguments + * sh: oops_enter()/oops_exit() in die(). + * [ARM] Update show_regs/oops register format + * IB/mlx4: Handle new FW requirement for send request prefetching + * IB/mlx4: Get rid of max_inline_data calculation + * IB/mlx4: Handle buffer wraparound in __mlx4_ib_cq_clean() + * IB/mlx4: Handle FW command interface rev 3 + * Fix signalfd interaction with thread-private signals + * sched: fix SysRq-N (normalize RT tasks) + * Fix possible runqueue lock starvation in wait_task_inactive() + * sh: Handle -ERESTART_RESTARTBLOCK for restartable syscalls. + * sh64: Handle -ERESTART_RESTARTBLOCK for restartable syscalls. + * [POWERPC] Fix snd-powermac refcounting bugs + * [XFS] s/memclear_highpage_flush/zero_user_page/ + * [XFS] Update the MAINTAINERS file entry for XFS - change git repo name. + * [XFRM]: Fix MTU calculation for non-ESP SAs + * [IPVS]: Fix state variable on failure to start ipvs threads + * [AF_RXRPC]: Return the number of bytes buffered in rxrpc_send_data() + * [S390] Missing blank when appending cio_ignore kernel parameter + * [S390] Fix zfcpdump header + * [S390] Fix yet another two section mismatches. + * [S390] Print list of modules on die(). + * [S390] Add oops_enter()/oops_exit() calls to die(). + * [S390] Move psw_set_key. + * [POWERPC] rheap - eliminates internal fragments caused by alignment + * [POWERPC] PowerPC: Prevent data exception in kernel space (32-bit) + * [POWERPC] Fix powermac late initcall to only run on powermac + * [MIPS] Don't drag a platform specific header into generic arch code. + * x86_64: Fix readahead/sync_file_range/fadvise64 compat calls + * x86_64: Fix eventd/timerfd syscalls + * x86: Disable DAC on VIA bridges + * x86_64: Quieten Atari keyboard warnings in Kconfig + * x86: Only make Macintosh drivers default on Macs + * x86: Disable KPROBES with DEBUG_RODATA for now + * x86: change_page_attr bandaids + * x86_64: fix link warning between for .text and .init.text + * Fix up CREDIT entry ordering + * firewire: Only set client->iso_context if allocation was successful. + * spidernet: null out skb pointer after its been used. + * spidernet: Cure RX ram full bug + * spidernet: Don't terminate the RX ring + * spidernet: silence the ramfull messages + * spidernet: turn off descriptor chain end interrupt. + * spidernet: checksum and ethtool + * bonding: Fix use after free in unregister path + * bonding: Fix 802.3ad no carrier on "no partner found" instance + * s390: print correct level for HiperSockets devices + * s390: qeth driver does not recover + * s390: avoid inconsistent lock state in qeth + * s390: qeth: wrong packet length in qdio header + * s390: Use ccw_device_get_id() in qeth/claw drivers + * s390: don't call iucv_path_connect from tasklet context + * s390: netiucv spinlock initializer cleanup + * s390: netiucv inlining cleanup + * forcedeth: use unicast receive mode for WoL + * natsemi irq flags + * cxgb3 - fix skb->dev dereference + * cxgb3 - fix netpoll hanlder + * cxgb3 - Fix direct XAUI support + * cxgb3 - Stop mac RX when changing MTU + * cxgb3 - MAC watchdog update + * PATA: Add the MCP73/77 support to PATA driver + * pata_it821x: (partially) fix DMA in RAID mode + * libata: more NONCQ devices + * kerneldoc fix in libata + * ahci: fix PORTS_IMPL override + * fix module_param mistake in it821x + * Blackfin arch: update ANOMALY handling + * Blackfin arch: update printk to use KERN_EMERG and reformat crash + output + * Blackfin arch: add missing braces around array bfin serial init + * Blackfin arch: match kernel startup messaage with new linker script + * Blackfin arch: move cond_syscall() behind __KERNEL__ like all other + architectures + * Blackfin arch: Add definition of dma_mapping_error + * Blackfin arch: add proper const volatile to addr argument to the read + functions + * [AGPGART] intel_agp: don't load if no IGD and AGP port + * IB/umem: Fix possible hang on process exit + * IPoIB/cm: Initialize RX before moving QP to RTR + * IPoIB/cm: Fix interoperability when MTU doesn't match + * IPoIB/cm: Remove dead definition of struct ipoib_cm_id + * IB/mlx4: Correct max_srq_wr returned from mlx4_ib_query_device() + * [PARISC] stop lcd driver from stripping initial whitespace + * [PARISC] Handle wrapping in expand_upwards() + * [PARISC] Fix unwinder on 64-bit kernels + * [PARISC] unwinder improvements + * page_mapping must avoid slub pages + * posix-timers: Prevent softirq starvation by small intervals and SIG_IGN + * Allow DEBUG_RODATA and KPROBES to co-exist + * [NETFILTER]: nf_conntrack_sip: add missing message types containing RTP + info + * [NETFILTER]: nfctnetlink: Don't allow to change helper + * [IPV6] NDISC: Fix thinko to control Router Preference support. + * [IPV4]: include sysctl.h from inetdevice.h + * i386: Make CMPXCHG64 only dependent on PAE + * x86_64: Fix only make Macintosh drivers default on Macs + * x86_64: Ignore compat mode SYSCALL when IA32_EMULATION is not defined + * [AVR32] Fix bug in invalidate_dcache_region() + * [AVR32] NGW100, Remove relics of the old USART mapping scheme + * [AVR32] Initialize dma_mask and dma_coherent_mask + * [AVR32] Update defconfigs + * ACPI: fix 2.6.20 SMP boot regression + * [SKBUFF]: Fix incorrect config #ifdef around skb_copy_secmark + * [TIPC]: Fix infinite loop in netlink handler + * [PPP]: Revert 606f585e363527da9feaed79465132c0c661fd9e + * [PPP]: Fix osize too small errors when decoding mppe. + * [TCP] tcp_read_sock: Allow recv_actor() return return negative error + value. + * [NET]: Re-enable irqs before pushing pending DMA requests + * [NET]: Make skb_seq_read unmap the last fragment + * hwmon/coretemp: fix a broken error path + * fix refcounting of nsproxy object when unshared + * console UTF-8 fixes (fix) + * SM501: suspend support + * SM501: initialise SDRAM clock before bus clocks + * SM501: Fix sm501_init_reg() mask/set order + * SM501: Clock updates and checks + * SM501: Add Documentation/SM501.txt + * SM501: Check SM501 ID register on initialisation + * SLUB: fix behavior if the text output of list_locations overflows + PAGE_SIZE + * sched: fix next_interval determination in idle_balance() + * update checkpatch.pl to version 0.05 + * alpha: fix alignment problem in csum_ipv6_magic() + * Char: stallion, fix oops during init with ISA cards + * uml: use generic BUG + * uml: add asm/paravirt.h + * "volatile considered harmful" + * document nlink function + * slab allocators: MAX_ORDER one off fix + * update checkpatch.pl to version 0.06 + * x86_64: fix misplaced `continue' in mce.c + * ext2: disallow setting xip on remount + * audit: fix oops removing watch if audit disabled + * ext3: lost brelse in ext3_read_inode() + * ext4: lost brelse in ext4_read_inode() + * ACPI: preserve the ebx value in acpi_copy_wakeup_routine + * FUTEX: Restore the dropped ERSCH fix + * Linus 2.6.22-rc6 + * [ARM] 4452/1: Force the literal pool dump before reloc_end + * [ARM] 4449/1: more entries in arch/arm/boot/.gitignore + * fix nmi_watchdog=2 bootup hang + * [POWERPC] Update g5_defconfig + * [POWERPC] Update defconfigs + * [POWERPC] Fix VDSO gettimeofday() when called with NULL struct timeval + * [POWERPC] Fix subtle FP state corruption bug in signal return on SMP + * USB: g_file_storage: call allow_signal() + * USB: ti serial driver sleeps with spinlock held + * USB: memory leak in iowarrior.c + * USB: usblcd doesn't limit memory consumption during write + * USB: fix race leading to use after free in io_edgeport + * USB: add new device id to option driver + * USB: ftdio_sio: New IPlus device ID + * [MIPS] __ucmpdi2 arguments are unsigned long long. + * [MIPS] add io_map_base to pci_controller on Cobalt + * [MIPS] remove "support for" from system type entry + * [MIPS] Alchemy: Fix wrong cast + * [MIPS] Fix pb1500 reg B access + * [MIPS] AP/SP requires shadow registers, auto enable support. + * [MIPS] 20K: Handle WAIT related bugs according to errata information + * [MIPS] use compat_siginfo in rt_sigframe_n32 + * [MIPS] Remove a duplicated local variable in test_and_clear_bit() + * [MIPS] EMMA2RH: Disable GEN_RTC, it can't possibly work. + * [MIPS] SMTC and non-SMTC kernel and modules are incompatible + * [MIPS] Count timer interrupts correctly. + * x86_64: set the irq_chip name for lapic + * x86_64 irq: use mask/unmask and proper locking in fixup_irqs() + * [SPARC64]: Add irqs to mdesc_node. + * [SPARC64]: Fix VIRQ enabling. + * [SPARC64]: Need to set state to IDLE during sun4v IRQ enable. + * [SPARC64]: Add LDOM virtual channel driver and VIO device layer. + * [SPARC64]: Add Sun LDOM virtual network driver. + * [SPARC64]: Add Sun LDOM virtual disk driver. + * [SPARC64]: Create proper obppath sysfs files for VIO bus devices. + * [SPARC64] LDC: Do limited polled retry on setting RX queue head. + * [GFS2] Fix gfs2_block_truncate_page err return + * [DLM] Telnet to port 21064 can stop all lockspaces + * [GFS2] inode size inconsistency + * [GFS2] remounting w/o acl option leaves acls enabled + * [GFS2] System won't suspend with GFS2 file system mounted + * [GFS2] git-gfs2-nmw-build-fix + * [GFS2] Obtaining no_formal_ino from directory entry + * [GFS2] Remove i_mode passing from NFS File Handle + * [SUNVNET]: Validate RX descriptor size field. + * [SPARC64]: Add missing symbol exports for LDOM infrastructure. + * [SPARC64]: Temporary workaround for LDC INO double-delivery. + * [SPARC64]: Create 'devspec' nodes for vio devices. + * [SPARC64]: vdev->type can be NULL, handle this in devspec_show(). + + -- Amit Kucheria Mon, 09 Jul 2007 12:55:56 +0300 + +linux-source-2.6.22 (2.6.22-7.14) gutsy; urgency=low + + [Ben Collins] + + * build/vars: Provide ivtv-modules + * Bump ABI + * ubuntu/config: Enable Intermediate Functional Block device + * coredump: Fix typo in patch merge + * ubuntu/scripts: Make sure to symlink *.lds for ia64 builds + * ubuntu/config: Enable NO_HZ for server and sparc64 targets. + * ubuntu/config: Remove bigiron target, see if anyone complains + * ubuntu: Ok, really remove bigiron + * ubuntu/control-scripts: Fo sho, remove the debconf stuff from controls + scripts + * AppArmor: Enable exports and changes for AppArmor usage + * ubuntu: Add feisty changelog for historical purposes. + + [Colin Watson] + + * Move isofs to storage-core-modules udeb from fs-core-modules. + + [Upstream Kernel Changes] + + * [MTD] [MAPS] don't force uclinux mtd map to be root dev + * [MTD] generalise the handling of MTD-specific superblocks + * [SCSI] zfcp: avoid clutter in erp_dbf + * [SCSI] zfcp: IO stall after deleting and path checker changes after + reenabling zfcp devices + * [SCSI] ipr: Proper return codes for eh_dev_reset for SATA devices + * [SCSI] stex: fix id mapping issue + * [SCSI] stex: extend hard reset wait time + * [SCSI] stex: fix reset recovery for console device + * [SCSI] stex: minor cleanup and version update + * [SCSI] MegaRAID: Update MAINTAINERS email-id + * [SCSI] tgt: fix a rdma indirect transfer error bug + * [SCSI] NCR53C9x: correct spelling mistake in deprecation notice + * [SCSI] aacraid: Correct sa platform support. (Was: [Bug 8469] Bad EIP + value on pentium3 SMP kernel-2.6.21.1) + * [SCSI] aacraid: fix panic on short Inquiry + * [WATCHDOG] ks8695_wdt.c - new KS8695 watchdog driver + * [JFFS2] Fix BUG() caused by failing to discard xattrs on deleted files. + * [JFFS2] Fix potential memory leak of dead xattrs on unmount. + * [SCSI] sd: fix refcounting regression in suspend/resume routines + * [SCSI] aacraid: apply commit config for reset_devices flag + * [SCSI] aic7xxx: fix aicasm build failure with gcc-3.4.6 + * [SCSI] aic94xx: asd_clear_nexus should fail if the cleared task does + not complete + * [SCSI] fusion: Fix |/|| confusion + * parisc: make command_line[] static + * parisc: sync compat getdents + * [PARISC] Move #undef to end of syscall table + * [PARISC] Wire up kexec_load syscall + * parisc: convert /proc/gsc/pcxl_dma to seq_file + * [PARISC] Let PA-8900 processors boot + * [PARISC] Disable LWS debugging + * [PARISC] spelling fixes: arch/parisc/ + * sh: section mismatch fixes for system timer. + * [PARISC] ROUND_UP macro cleanup in arch/parisc + * [PARISC] ROUNDUP macro cleanup in drivers/parisc + * [PPC] Fix COMMON symbol warnings + * [PPC] Remove duplicate export of __div64_32. + * [POWERPC] 52xx: unbreak lite5200 dts (_pic vs. -pic) + * [POWERPC] QE: fix Kconfig 'select' warning with UCC_FAST + * [POWERPC] Fix Section mismatch warnings + * [POWERPC] Fix modpost warning + * [PPC] Fix modpost warning + * [CIFS] Fix oops on failed cifs mount (in kthread_stop) + * [POWERPC] Fix Kconfig warning + * [CIFS] typo in previous patch + * [SCSI] megaraid_sas: intercept cmd timeout and throttle io + * [WATCHDOG] clean-up watchdog documentation + * drm: Spinlock initializer cleanup + * drm/radeon: add more IGP chipset pci ids + * drm: make sure the drawable code doesn't call malloc(0). + * [PARISC] kobject is embedded in subsys, not kset + * [PARISC] Build fixes for power.c + * [ARM] 4401/1: S3C2443: Add definitions for port GPIOJ + * [ARM] 4402/1: S3C2443: Add physical address of HSMMC controller + * [ARM] 4403/1: Make the PXA-I2C driver work with lockdep validator + * [ARM] 4404/1: Trivial IXP42x Kconfig cleanup + * [ARM] 4405/1: NSLU2, DSM-G600 frequency fixup code + * [ARM] 4406/1: Trivial NSLU2 / NAS-100D header & setup code cleanup + * [ARM] remove unused header file: arch/arm/mach-s3c2410/bast.h + * [PARISC] fix lasi_82596 build + * [PARISC] fix section mismatch in parport_gsc + * [PARISC] fix section mismatch in parisc STI video drivers + * [PARISC] fix section mismatch in ccio-dma + * [PARISC] fix section mismatches in arch/parisc/kernel + * [PARISC] fix section mismatch in parisc eisa driver + * [PARISC] fix section mismatch in superio serial drivers + * [PARISC] Wire up utimensat/signalfd/timerfd/eventfd syscalls + * hwmon/ds1621: Fix swapped temperature limits + * hwmon/coretemp: Add more safety checks + * hwmon/w83627hf: Be quiet when no chip is found + * hwmon-vid: Don't spam the logs when VRM version is missing + * hwmon/applesmc: Simplify dependencies + * hwmon/applesmc: Handle name file creation error and deletion + * ieee1394: sbp2: include workqueue.h + * ieee1394: eth1394: remove bogus netif_wake_queue + * ieee1394: eth1394: handle tlabel exhaustion + * ieee1394: eth1394: bring back a parent device + * ieee1394: raw1394: Fix async send + * firewire: Add missing byteswapping for receive DMA programs. + * firewire: prefix modules with firewire- instead of fw- + * firewire: fix return code + * [libata] Add drive to NCQ blacklist + * [ARM] enable arbitary speed tty ioctls and split input/output speed + * Input: db9 - do not ignore dev2 module parameter + * Input: logips2pp - fix typo in Kconfig + * [XFS] Write at EOF may not update filesize correctly. + * [SCSI] pluto: Use wait_for_completion_timeout. + * [SPARC64]: Kill unused DIE_PAGE_FAULT enum value. + * [SPARC64]: Don't be picky about virtual-dma values on sun4v. + * [SPARC32]: Removes mismatch section warnigs in sparc time.c file + * [SERIAL] sunzilog: section mismatch fix + * [SPARC64]: PCI device scan is way too verbose by default. + * [SCSI] jazz_esp: Converted to use esp_core. + * [SCSI] ESP: Kill SCSI_ESP_CORE and link directly just like jazz_esp + * [SPARC64]: Fix typo in sun4v_hvapi_register error handling. + * [SPARC64]: Report proper system soft state to the hypervisor. + * [SPARC64]: Negotiate hypervisor API for PCI services. + * [SPARC64]: Use machine description and OBP properly for cpu probing. + * [SPARC64]: Eliminate NR_CPUS limitations. + * [SPARC64]: arch/sparc64/time.c doesn't compile on Ultra 1 (no PCI) + * [SPARC]: Linux always started with 9600 8N1 + * [SPARC64]: Fix _PAGE_EXEC_4U check in sun4u I-TLB miss handler. + * [SPARC]: Emulate cmpxchg like parisc + * [SPARC]: Mark as emulating cmpxchg, add appropriate depends for DRM. + * [SPARC64]: Fix two bugs wrt. kernel 4MB TSB. + * [SPARC64]: Fill holes in hypervisor APIs and fix KTSB registry. + * mac80211: fail back to use associate from reassociate + * mac80211: fix memory leak when defrag fragments + * mac80211: always set carrier status on open + * mac80211: avoid null ptr deref in ieee80211_ibss_add_sta + * prism54: fix monitor mode oops + * ieee80211: fix incomplete error message + * softmac: alloc_ieee80211() NULL check + * hostap: Allocate enough tailroom for TKIP + * sparc64: fix alignment bug in linker definition script + * USB: replace flush_workqueue with cancel_sync_work + * ACPICA: allow Load(OEMx) tables + * ACPI: thermal: Replace pointer with name in trip_points + * ACPI: extend "acpi_osi=" boot option + * IB/mthca: Fix handling of send CQE with error for QPs connected to SRQ + * IPoIB/cm: Fix performance regression on Mellanox + * IB/cm: Fix stale connection detection + * IB/mlx4: Fix last allocated object tracking in bitmap allocator + * NOHZ: prevent multiplication overflow - stop timer for huge timeouts + * random: fix error in entropy extraction + * random: fix seeding with zero entropy + * ACPI: Make _OSI(Linux) a special case + * ACPI: add __init to acpi_initialize_subsystem() + * [PARISC] fix "ENTRY" macro redefinition + * [PARISC] fix section mismatch in smp.c + * [PARISC] remove remnants of parisc-specific softirq code + * [PARISC] fix trivial spelling nit in asm/linkage.h + * [PARISC] fix null ptr deref in unwind.c + * [PARISC] fix "reduce size of task_struct on 64-bit machines" fallout + * [PARISC] be more defensive in process.c::get_wchan + * [ARM] use __used attribute + * [ARM] Fix stacktrace FP range checking + * [ARM] oprofile: avoid lockdep warnings on mpcore oprofile init + * [ARM] 4411/1: KS8695: Another serial driver fix + * [ARM] 4412/1: S3C2412: reset errata fix + * [ARM] 4414/1: S3C2443: sparse fix for clock.c + * [ARM] 4415/1: AML5900: fix sparse warnings from map_io + * [ARM] 4416/1: NWFPE: fix undeclared symbols + * [ARM] 4410/1: Remove extern declarations in coyote/ixdpg425-pci.c + * [ARM] 4394/1: ARMv7: Add the TLB range operations + * [ARM] 4417/1: Serial: Fix AMBA drivers locking + * sky2: dont set bogus bit in PHY register + * sky2: checksum offload plus vlan bug + * sky2: program proper register for fiber PHY + * defxx: Fix the handling of ioremap() failures + * e1000: restore netif_poll_enable call but make sure IRQs are off + * sky2: enable IRQ on duplex renegotiation + * ehea: Fixed multi queue RX bug + * [SCSI] fix CONFIG_SCSI_WAIT_SCAN=m + * [SCSI] qla2xxx: fix timeout in qla2x00_down_timeout + * [ARM] Fix some section mismatch warnings + * alpha: cleanup in bitops.h + * alpha: support new syscalls + * fix possible null ptr deref in kallsyms_lookup + * NFS: Fix a refcount leakage in O_DIRECT + * a bug in ramfs_nommu_resize function, passing old size to vmtruncate + * sh: Fix pcrel too far for in_nmi label. + * sh: Trivial fix for dma-api compile failure. + * sh: Fix vsyscall build failure. + * sh: trivial build cleanups. + * sh: support older gcc's + * [ALSA] HDA: Add support for Gateway NX860 + * [ALSA] HDA: Add more systems to Sigmatel codec + * [ALSA] HDA: Fix headphone mute issue on non-eapd Conexant systems + * [ALSA] hda-codec - Add support for ASUS A8J modem + * [ALSA] ali5451 - Fix possible NULL dereference + * [ALSA] hda-intel: fix ASUS M2V detection + * [ALSA] Fix ASoC s3c24xx-pcm spinlock bug + * [ALSA] hda-codec - Add quirk for MSI S420 + * [ALSA] hda-codec - Add quirk for Supermicro PDSBA to alc883_cfg_tbl[] + * [ALSA] hda-codec - Add support for MSI K9N Ultra + * [ALSA] hda-codec - Fix pin configs for Gateway MX6453 + * [ALSA] hda-codec - Fix input with STAC92xx + * [ALSA] hda-codec - Fix STAC922x capture boost level + * [CRYPTO] cryptd: Fix problem with cryptd and the freezer + * [CASSINI]: Fix printk message typo. + * [XFRM]: Allow XFRM_ACQ_EXPIRES to be tunable via sysctl. + * [XFRM]: xfrm_larval_drop sysctl should be __read_mostly. + * [IPSEC]: Fix IPv6 AH calculation in outbound + * [IPV6] ROUTE: No longer handle ::/0 specially. + * [NET]: parse ip:port strings correctly in in4_pton + * [IPSEC]: Fix panic when using inter address familiy IPsec on loopback. + * [IPV4]: Kill references to bogus non-existent CONFIG_IP_NOSIOCRT + * [AF_PACKET]: Kill bogus CONFIG_PACKET_MULTICAST + * [IPV6]: Fix build warning. + * [AF_PACKET]: Kill CONFIG_PACKET_SOCKET. + * [SOCK]: Shrink struct sock by 8 bytes on 64-bit. + * [TCP]: Consolidate checking for tcp orphan count being too big. + * [NET] napi: Call __netif_rx_complete in netif_rx_complete + * [IPV6] ADDRCONF: Fix conflicts in DEVCONF_xxx constant. + * [TCP] tcp_probe: a trivial fix for mismatched number of printl + arguments. + * [TCP] tcp_probe: use GCC printf attribute + * [BRIDGE]: Reduce frequency of forwarding cleanup timer in bridge. + * [BRIDGE]: Round off STP perodic timers. + * [IPSEC]: Add xfrm_sysctl.txt. + * [SPARC64]: Add missing NCS and SVC hypervisor interfaces. + * [SPARC32]: Build fix. + * [SPARC]: Missing #include in drivers/sbus/char/flash.c + * [ALSA] version 1.0.14 + * neofb: Fix pseudo_palette array overrun in neofb_setcolreg + * smpboot: fix cachesize comparison in smp_tune_scheduling() + * at91: fix enable/disable_irq_wake symmetry in pcmcia driver + * SLUB: More documentation + * pci-quirks: fix MSI disabling on RS400-200 and RS480 + * ntfs_init_locked_inode(): fix array indexing + * m68k: runtime patching infrastructure + * SLUB: Fix NUMA / SYSFS bootstrap issue + * afs: needs sched.h + * m68k: discontinuous memory support + * [S390] Add exception handler for diagnose 224 + * [S390] dasd_eer: use mutex instead of semaphore + * [S390] arch/s390/kernel/debug.c: use mutex instead of semaphore + * [S390] raw3270: use mutex instead of semaphore + * [S390] Fix section annotations. + * [S390] cio: Use device_schedule_callback() for removing disconnected + devices. + * [S390] cio: deregister ccw device when pgid disband failed + * ACPI: thinkpad-acpi: do not use named sysfs groups + * ieee1394: fix calculation of sysfs attribute "address" + * ieee1394: sbp2: offer SAM-conforming target port ID in sysfs + * firewire: fw-sbp2: implement sysfs ieee1394_id + * firewire: add to MAINTAINERS + * firewire: Implement suspend/resume PCI driver hooks. + * firewire: Change struct fw_cdev_iso_packet to not use bitfields. + * firewire: Install firewire-constants.h and firewire-cdev.h for + userspace. + * EXT4: Fix whitespace + * Remove unnecessary exported symbols. + * ext4: Extent overlap bugfix + * When ext4_ext_insert_extent() fails to insert new blocks + * Define/reserve new ext4 superblock fields + * msi: fix ARM compile + * PCI: disable MSI by default on systems with Serverworks HT1000 chips + * PCI: Fix pci_find_present + * PCI: i386: fixup for Siemens Nixdorf AG FSC Multiprocessor Interrupt + Controllers + * PCI: quirk disable MSI on via vt3351 + * [XTENSA] fix bit operations in bitops.h + * [XTENSA] Spelling fixes in arch/xtensa + * [XTENSA] fix sources using deprecated assembler directive + * [XTENSA] Remove multi-exported symbols from xtensa_ksyms.c + * [XTENSA] Use generic 64-bit division + * [XTENSA] clean-up header files + * [XTENSA] Move common sections into bss sections + * [XTENSA] Remove non-rt signal handling + * Xtensa: use asm-generic/fcntl.h + * [JFFS2] Fix buffer length calculations in jffs2_get_inode_nodes() + * Fix vmi.c compilation + * x86_64: allocate sparsemem memmap above 4G + * Add select PHYLIB to the UCC_GETH Kconfig option + * Fix possible UDF data corruption + * m68k: parenthesis balance + * msi: fix the ordering of msix irqs + * msi: mask the msix vector before we unmap it + * potential parse error in ifdef + * parse errors in ifdefs + * pci_ids: update patch for Intel ICH9M + * x86: fix oprofile double free + * Work around Dell E520 BIOS reboot bug + * fix compat futex code for private futexes + * skeletonfb: fix of xxxfb_setup ifdef + * vt8623fb: arkfb: null pointer dereference fix + * cfag12864bfb: Use sys_ instead of cfb_ framebuffer accessors + * fbdev: Move declaration of fb_class to + * misc/tifm_7xx1: replace deprecated irq flag + * add a trivial patch style checker + * Documentation: How to use GDB to decode OOPSes + * RTC: use fallback IRQ if PNP tables don't provide one + * memory hotplug: fix unnecessary calling of init_currenty_empty_zone() + * tty: fix leakage of -ERESTARTSYS to userland + * ISDN4Linux: fix maturity label + * Fix broken CLIR in isdn driver + * prism54: MAINTAINERS update + * atmel_spi dma address bugfix + * h8300 trival patches + * ALPHA: support graphics on non-zero PCI domains + * ALPHA: correct low-level I/O routines for sable-lynx + * ALPHA: misc fixes + * Better documentation for ERESTARTSYS + * serial_core.h: include + * SPI: Freescale iMX SPI controller driver fixes + * SLUB: fix locking for hotplug callbacks + * pm3fb: switching between X and fb fix + * microcode: fix section mismatch warning + * isdn: fix section mismatch warnings + * acpi: fix section mismatch warning in asus + toshiba + * kvm: fix section mismatch warning in kvm-intel.o + * net/hp100: fix section mismatch warning + * timer statistics: fix race + * timer stats: speedups + * [SCSI] aacraid: fix shutdown handler to also disable interrupts. + * [MTD] Fix error checking after get_mtd_device() in get_sb_mtd functions + * [JFFS2] Fix obsoletion of metadata nodes in jffs2_add_tn_to_tree() + * ACPI: Section mismatch ... acpi_map_pxm_to_node + * ACPICA: Support for external package objects as method arguments + * Pull now into release branch + * Pull osi-now into release branch + * [POWERPC] Update documentation for of_find_node_by_type() + * [POWERPC] Fix ppc32 single-stepping out of syscalls + * [POWERPC] Fix compiler/assembler flags for Ebony platform boot files + * [POWERPC] Fix possible access to free pages + * [POWERPC] ps3/interrupt.c uses get_hard_smp_processor_id + * [POWERPC] pasemi idle uses hard_smp_processor_id + * [POWERPC] Create a zImage for legacy iSeries + * [POWERPC] Don't use HOSTCFLAGS in BOOTCFLAGS + * [POWERPC] Fix compile warning in pseries xics code + * [POWERPC] Fix return from pte_alloc_one() in out-of-memory case + * [POWERPC] Compare irq numbers with NO_IRQ not IRQ_NONE + * [POWERPC] Don't allow PMAC_APM_EMU for 64-bit + * [POWERPC] Fix compile breakage for IBM/AMCC 4xx arch/ppc platforms + * [POWERPC] Fix zImage.coff generation for 32-bit pmac + * [ARM] 4392/2: Do not corrupt the SP register in compressed/head.S + * [ARM] 4418/1: AT91: Number of programmable clocks differs + * [ARM] 4419/1: AT91: SAM9 USB clocks check for suspending + * [ARM] 4422/1: Fix default value handling in gpio_direction_output (PXA) + * [ARM] Solve buggy smp_processor_id() usage + * qla3xxx: device doesnt do hardware checksumming. + * VLAN: kill_vid is only useful for VLAN filtering devices + * sky2: Fix VLAN unregistration + * 8139cp: fix VLAN unregistration + * atl1: eliminate unneeded kill_vid code + * network drivers: eliminate unneeded kill_vid code + * e1000: disable polling before registering netdevice + * smc91x: sh solution engine fixes. + * Update tulip maintainer email address + * NetXen: Removal of extra free_irq call + * myri10ge: report link up/down in standard ethtool way + * NET: add MAINTAINERS entry for ucc_geth driver + * [ARM] 4421/1: AT91: Value of _KEY fields. + * [PARISC] Fix bug when syscall nr is __NR_Linux_syscalls + * [AF_UNIX]: Make socket locking much less confusing. + * [TG3]: Fix link problem on Dell's onboard 5906. + * [AF_UNIX]: Fix datagram connect race causing an OOPS. + * [TCP]: Use default 32768-61000 outgoing port range in all cases. + * [ATM]: Fix warning. + * [NET]: Make net watchdog timers 1 sec jiffy aligned. + * [NET]: Fix comparisons of unsigned < 0. + * [TCP]: Fix GSO ignorance of pkts_acked arg (cong.cntrl modules) + * [NET] gso: Fix GSO feature mask in sk_setup_caps + * [IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP + * [ICMP]: Fix icmp_errors_use_inbound_ifaddr sysctl + * [VIDEO]: XVR500 and XVR2500 require FB=y + * [ATA]: Don't allow to enable this for SPARC64 without PCI. + * sh: Fix in_nmi symbol build error. + * sh: microdev: Fix compile warnings. + * sh: Fix SH4-202 clock fwk set_rate() mismatch. + * sh: voyagergx: Fix build warnings. + * sh: ioremap() through PMB needs asm/mmu.h. + * sh: Fix se73180 platform device registration. + * Input: ucb1x00 - do not access input_dev->private directly + * Input: reduce raciness when input handlers disconnect + * [PARISC] Fix kernel panic in check_ivt + * [SCSI] atari_NCR5380: update_timeout removal + * [SCSI] JAZZ ESP and SUN ESP need SPI_ATTRS + * [CIFS] fix mempool destroy done in wrong order in cifs error path + * SPI dynamic busid generation bugfix + * mtrr atomicity fix + * vanishing ioctl handler debugging + * libata: always use polling SETXFER + * Linux 2.6.22-rc4 + * [SPARC64]: Move topology init code into new file, sysfs.c + * [SPARC64]: Export basic cpu properties via sysfs. + * [SPARC64]: Fix service channel hypervisor function names. + * [SPARC64]: Provide mmu statistics via sysfs. + * [SPARC64]: Proper multi-core scheduling support. + * [SPARC64]: Make core and sibling groups equal on UltraSPARC-IV. + * [SPARC64]: Fix {mc,smt}_capable(). + * [SPARC64]: Fill in gaps in non-PCI dma_*() NOP implementation. + * [ATA]: Back out bogus (SPARC64 && !PCI) Kconfig depends. + * [VIDEO]: Fix section mismatch warning in promcon. + * [CIFS] whitespace cleanup + * [ARM] Fix 4417/1: Serial: Fix AMBA drivers locking + * [VIDEO] ffb: The pseudo_palette is only 16 elements long + * [ARM] pxa: fix pxa27x keyboard driver + * [VIDEO] sunxvr2500fb: Fix pseudo_palette array size + * [VIDEO] sunxvr500fb: Fix pseudo_palette array size + * [CIFS] whitespace cleanup part 2 + * [CIFS] Missing flag on negprot needed for some servers to force packet + signing + * [MIPS] Atlas, Malta, SEAD: Remove scroll from interrupt handler. + * [MIPS] Remove duplicate fpu enable hazard code. + * [MIPS] EMMA2RH: remove dead KGDB code + * [MIPS] RM300: Fix MMIO problems by marking the PCI INT ACK region busy + * [MIPS] Fix VGA corruption on RM300C + * [MIPS] Drop __ARCH_WANT_SYS_FADVISE64 + * [MIPS] Make dma_map_sg handle sg elements which are longer than one + page + * [MIPS] Fix some system calls with long long arguments + * [MIPS] Remove prototype for deleted function qemu_handle_int + * [MIPS] Fix some minor typoes in arch/mips/Kconfig. + * [MIPS] Fix warning by moving do_default_vi into CONFIG_CPU_MIPSR2_SRS + * [AGPGART] intel_agp: cleanup intel private data + * [AGPGART] intel_agp: use table for device probe + * [AGPGART] intel_agp: add support for 965GME/GLE + * [AGPGART] intel_agp: add support for 945GME + * [AGPGART] intel_agp: Add support for G33, Q33 and Q35 chipsets + * ocfs2: Fix masklog breakage + * ocfs2: Fix invalid assertion during write on 64k pages + * [POWERPC] pasemi: Fix iommu + 64K PAGE_SIZE bug + * [POWERPC] spufs: Refuse to load the module when not running on cell + * [POWERPC] spufs: Hook up spufs_release_mem + * [POWERPC] spufs: Fix gang destroy leaks + * [POWERPC] spufs: Free mm if spufs_fill_dir() failed + * [POWERPC] spufs: Synchronize pte invalidation vs ps close + * [POWERPC] spufs scheduler: Fix wakeup races + * [POWERPC] Fix pci_setup_phb_io_dynamic for pci_iomap + * [POWERPC] cbe_cpufreq: Limit frequency via cpufreq notifier chain + * [POWERPC] scc_sio: Fix link failure + * [POWERPC] Fix typo in booting-without-of-txt section numbering + * [POWERPC] spufs: Don't yield nosched context + * [POWERPC] Add table of contents to booting-without-of.txt + * [POWERPC] spufs: Fix error handling in spufs_fill_dir() + * mmc-atmel: remove linux/mmc/protocol.h dependencies + * au1xmmc: Replace C code with call to ARRAY_SIZE() macro. + * mmc: fix broken if clause + * mmc: don't call switch on old cards + * [POWERPC] Fix building of COFF zImages + * checkpatch.pl: should be executable + * Restrict clearing TIF_SIGPENDING + * mlx4_core: Fix CQ context layout + * mlx4_core: Initialize ctx_list and ctx_lock earlier + * mlx4_core: Free catastrophic error MSI-X interrupt with correct dev_id + * IB/mthca, mlx4_core: Fix typo in comment + * [BNX2]: Fix netdev watchdog on 5708. + * [BNX2]: Add missing wait in bnx2_init_5709_context(). + * [BNX2]: Enable DMA on 5709. + * [BNX2]: Fix occasional counter corruption on 5708. + * [BNX2]: Update version and reldate. + * [TCP]: Honour sk_bound_dev_if in tcp_v4_send_ack + * [IPV4]: Only panic if inetdev_init fails for loopback + * [IPV4]: Convert IPv4 devconf to an array + * [IPV4]: Add default config support after inetdev_init + * [IPV4]: Restore old behaviour of default config values + * [RFKILL]: Make rfkill->name const + * [TCP]: Use LIMIT_NETDEBUG in tcp_retransmit_timer(). + * [TCP] tcp_probe: Attach printf attribute properly to printl(). + * [NETLINK]: Mark netlink policies const + * [RTNETLINK]: ifindex 0 does not exist + * [NETFILTER]: nf_conntrack: fix helper module unload races + * [NETFILTER]: ip_tables: fix compat related crash + * [NETFILTER]: nf_conntrack_amanda: fix textsearch_prepare() error check + * [AF_UNIX]: Fix stream recvmsg() race. + * [UDP]: Revert 2-pass hashing changes. + * [NET]: Avoid duplicate netlink notification when changing link state + * [NET_SCHED]: Fix filter double free + * xfrm: Add security check before flushing SAD/SPD + * [SPARC64]: Fix 2 bugs in PCI Sabre bus scanning. + * [SPARC64]: Fix SBUS IRQ regression caused by PCI-E driver. + * frv: build fix + * enable interrupts in user path of page fault. + * RAMFS NOMMU: missed POSIX UID/GID inode attribute checking + * [SPARC64]: Include instead of . + * [SPARC64]: Handle PCI bridges without 'ranges' property. + * mlx4_core: Check firmware command interface revision + * mlx4_core: Don't set MTT address in dMPT entries with PA set + * IB/mlx4: Fix zeroing of rnr_retry value in ib_modify_qp() + * RDMA/cma: Fix initialization of next_port + * IB/mlx4: Make sure RQ allocation is always valid + * splice: move inode size check into generic_file_splice_read() + * splice: remove do_splice_direct() symbol export + * pipe: move pipe_inode_info structure decleration up before it's used + * splice: move balance_dirty_pages_ratelimited() outside of splice actor + * splice: __generic_file_splice_read: fix i_size_read() length checks + * splice: __generic_file_splice_read: fix read/truncate race + * V4L/DVB (5702): Fix Kconfig items to avoid linkedition errors + * V4L/DVB (5700): Saa7111: fix picture settings cache bug + * V4L/DVB (5699): Cinergyt2: fix file release handler + * V4L/DVB (5675): Move big PIO accesses from the interrupt handler to a + workhandler + * V4L/DVB (5716): Tda10086,tda826x: fix tuning, STR/SNR values + * V4L/DVB (5720): Usbvision: fix urb allocation and submits + * V4L/DVB (5730): Remove unused V4L2_CAP_VIDEO_OUTPUT_POS + * V4L/DVB (5732): Add ivtv CROPCAP support and fix ivtv S_CROP for video + output. + * V4L/DVB (5736): Add V4L2_FBUF_CAP/FLAG_LOCAL/GLOBAL_INV_ALPHA + * V4L/DVB (5673): Fix audio stuttering for saa711x/ivtv when in radio + mode. + * V4L/DVB (5761): Fix broken b2c2 dependency on non x86 architectures + * V4L/DVB (5751): Ivtv: fix ia64 printk format warnings. + * serverworks: remove crappy code + * serverworks: fix CSB6 tuning logic + * it821x: RAID mode fixes + * ide: HPA detect from resume + * ide: generic IDE PCI driver, add another device exception + * hpt366: disallow Ultra133 for HPT374 + * Add the PATA controller device ID to pci_ids.h for MCP73/MCP77. + * ide: Add the MCP73/77 support to PATA driver + * [CIFS] CIFS should honour umask + * update Documentation/driver-model/platform.txt + * Driver core: keep PHYSDEV for old struct class_device + * Driver core: kill unused code + * kobject: use the proper printk level for kobject error + * firmware: remove orphaned Email + * [IPV4]: Do not remove idev when addresses are cleared + * [NetLabel]: consolidate the struct socket/sock handling to just struct + sock + * [CIPSO]: Fix several unaligned kernel accesses in the CIPSO engine. + * USB: set default y for CONFIG_USB_DEVICE_CLASS + * usblp: Don't let suspend to kill ->used + * USB: usb gadgets avoid le{16,32}_to_cpup() + * USB: UNUSUAL_DEV: Sync up some reported devices from Ubuntu + * USB: cxacru: add Documentation file + * USB: cxacru: create sysfs attributes in atm_start instead of bind + * USB: cxacru: ignore error trying to start ADSL in atm_start + * USB: Fix up bogus bInterval values in endpoint descriptors + * OHCI: Fix machine check in ohci_hub_status_data + * update checkpatch.pl to version 0.03 + * m68knommu: fix ColdFire timer off by 1 + * nommu: report correct errno in message + * loop: preallocate eight loop devices + * document Acked-by: + * update feature-removal-schedule.txt to include deprecated functions + * mount -t tmpfs -o mpol=: check nodes online + * slab: fix alien cache handling + * potential parse error in ifdef part 3 + * SLUB: return ZERO_SIZE_PTR for kmalloc(0) + * uml: fix kernel stack size on x86_64 + * Documentation/atomic_ops.txt typo fix + * Move three functions that are only needed for CONFIG_MEMORY_HOTPLUG + * Char: stallion, don't fail with less than max panels + * Char: stallion, alloc tty before pci devices init + * Char: stallion, proper fail return values + * uml: get declaration of simple_strtoul + * isdn/diva: fix section mismatch + * sata_promise: use TF interface for polling NODATA commands + * rt-mutex: fix stale return value + * rt-mutex: fix chain walk early wakeup bug + * pi-futex: fix exit races and locking problems + * fix sysrq-m oops + * x86_64: oops_begin() fix + * reiserfs: mailing list has moved + * checkpatch: produce fewer lines of output + * MAINTAINERS: corrections + * hexdump: more output formatting + * update checkpatch.pl to version 0.04 + * Protect from multiple inclusion + * [IrDA]: Fix Rx/Tx path race. + * [IrDA]: f-timer reloading when sending rejected frames. + * ibmveth: Fix h_free_logical_lan error on pool resize + * ibmveth: Automatically enable larger rx buffer pools for larger mtu + * typo in via-velocity.c + * NetXen: Fix ping issue after reboot on Blades with 3.4.19 firmware + * NetXen: Fix compile failure seen on PPC architecture + * ehea: Fixed possible kernel panic on VLAN packet recv + * phylib: add RGMII-ID mode to the Marvell m88e1111 PHY to fix broken + ucc_geth + * net: fix typo in drivers/net/usb/Kconfig + * remove unused variable in pata_isapnp + * libata: disable NCQ for HITACHI HTS541680J9SA00/SB21C7EP + * libata: fix probe time irq printouts + * libata: print device model and firmware revision for ATAPI devices + * libata: fix hw_sata_spd_limit initialization + * ahci: Add MCP73/MCP77 support to AHCI driver + * libata-core/sff: Fix multiple assumptions about DMA + * libata: Correct abuse of language + * libata passthru: update protocol numbers + * libata passthru: support PIO multi commands + * libata passthru: map UDMA protocols + * libata passthru: always enforce correct DEV bit + * libata passthru: update cached device paramters + * i915: add new pciids for 945GME, 965GME/GLE + * drm/i915: Add support for the G33, Q33, and Q35 chipsets. + * drm: fix radeon setparam on 32/64 bit systems. + * [ARM] VFP: fix section mismatch error + * libata: force PIO on IOMEGA ZIP 250 ATAPI + * libata: limit post SRST nsect/lbal wait to ~100ms + * Blackfin arch: remove defconfig file + * Blackfin arch: DMA code minor naming convention fix + * Blackfin arch: spelling fixes + * Blackfin arch: fix bug ad1836 fails to build properly for BF533-EZKIT + * Blackfin arch: all symbols were offset by 4k, since we didn't have the + __text label. + * Blackfin arch: mark our memory init functions with __init so they get + freed after init + * Blackfin arch: implement a basic /proc/sram file for L1 allocation + visibility + * Blackfin arch: fixup Blackfin MAINTIANERS team member list + * Blackfin arch: scrub old console defines + * Blackfin arch: update defconfigs + * Blackfin arch: unify differences between our diff head.S files -- no + functional changes + * Blackfin arch: move more of our startup code to .init so it can be + freed once we are up and running + * Blackfin arch: add proper ENDPROC() + * Blackfin arch: try to split up functions like this into smaller units + according to LKML review + * Blackfin arch: fix spelling typo in output + * Blackfin arch: As Mike pointed out range goes form m..MAX_BLACKFIN_GPIO + -1 + * Blackfin arch: add missing gpio.h header to fix compiling in some pm + configurations + * Blackfin arch: add support for Alon Bar-Lev's dynamic kernel + command-line + * Blackfin arch: fix bug can not wakeup from sleep via push buttons + * Blackfin arch: make sure we initialize our L1 Data B section properly + based on the linked kernel + * Blackfin arch: redo our linker script a bit + * Blackfin arch: move HI/LO macros into blackfin.h and punt the rest of + macros.h as it includes VDSP macros we never use + * Blackfin serial driver: hook up our UARTs STP bit with userspaces + CMSPAR + * Blackfin serial driver: ignore framing and parity errors + * Blackfin serial driver: actually implement the break_ctl() function + * Blackfin serial driver: decouple PARODD and CMSPAR checking from PARENB + * Blackfin RTC drivers: update MAINTAINERS information + * Blackfin SPI driver: tweak spi cleanup function to match newer kernel + changes + * [ARM] 4442/1: OSIRIS: Fix CPLD register definitions + * [ARM] 4443/1: OSIRIS: Add watchdog device to machine devices + * [ARM] 4444/2: OSIRIS: CPLD suspend fix + * [ARM] 4445/1: ANUBIS: Fix CPLD registers + * Blackfin SPI driver: fix bug SPI DMA incomplete transmission + * Blackfin SMC91X ethernet supporting driver: SMC91C111 LEDs are note + drived in the kernel like in uboot + * [MIPS] Fix KMODE for the R3000 + * [MIPS] SMTC: Don't set and restore irqregs ptr from self_ipi. + * [MIPS] Always install the DSP exception handler. + * [MIPS] Atlas: Fix build. + * [MIPS] Wire up utimensat, signalfd, timerfd, eventfd + * [MIPS] SMTC: Fix warning. + * [MIPS] SMTC: Don't continue in set_vi_srs_handler on detected bad + arguments. + * [MIPS] SMTC: The MT ASE requires to initialize c0_pagemask and + c0_wired. + * [MIPS] SMTC: Fix build error caused by nonsense code. + * [MIPS] Fix modpost warnings by making start_secondary __cpuinit + * [MIPS] Fix IP27 build + * [MIPS] Fix smp barriers in test_and_{change,clear,set}_bit + * libertas: scan two channels per scan command + * libertas: rename wlan_association_worker + * libertas: a debug output was missing a newline + * libertas: fix removal of all debugfs files + * libertas: remove deprecated pm_register and associated code + * libertas: remove __FILE__ from debug output + * libertas: remove unused/superfluous definitions of DEV_NAME_LEN + * libertas: move vendor & product id's into if_usb.c + * libertas: make libertas_wlan_data_rates static + * libertas: fix scanning from associate path + * libertas: exclude non-used code when PROC_DEBUG is not set + * libertas: make debug configurable + * libertas: tune debug code + * libertas: single out mesh code + * libertas: change debug output of libertas_interrupt() + * libertas: get rid of libertas_sbi_get_priv() + * libertas: fix SSID output + * libertas: changed some occurences of kmalloc() + memset(&a,0,sz) to + kzalloc() + * libertas: move reset_device() code main.c to if_usb.c + * libertas: split wlan_add_card() + * libertas: fixed transmission flow control on the mesh interface + * libertas: fix error handling of card initialization + * libertas: added transmission failures to mesh statistics + * libertas: wakeup both mesh and normal wakeup when getting out of scan + * libertas: indirect all hardware access via hw_XXXX functions + * libertas: move contents of fw.h to decl.h + * libertas: split module into two (libertas.ko and usb8xxx.ko) + * libertas: fix RESET logic at unload time + * libertas: let DRV_NAME be overridable + * libertas: remove unused variables in wlan_dev_t + * libertas: fixed incorrect assigment of fcs errors to frag errors + * libertas: add URB debug info + * libertas: fixed kernel oops on module/card removal + * libertas: call SET_NETDEV_DEV from common code + * libertas: replace 'macaddress' with 'bssid' + * libertas: correctly unregister mesh netdev on error + * libertas: don't tear down netdev in libertas_activate_card + * libertas: version bump (321p0) and cmds update for new fw (5.220.10.p0) + * libertas: updated mesh commands for 5.220.9.p11 + * libertas: make scan result handling more flexible + * libertas: fix 'keep previous scan' behavior + * libertas: cleanup of fwt_list_route processing + * libertas: fix oops on rmmod + * libertas: move channel changing into association framework + * libertas: make association paths consistent + * libertas: use MAC_FMT and MAC_ARG where appropriate + * libertas: use compare_ether_addr() rather than memcmp() where + appropriate + * libertas: fix debug enter/leave prints for + libertas_execute_next_command + * libertas: correctly balance locking in libertas_process_rx_command + * libertas: correct error report paths for wlan_fwt_list_ioctl + * libertas: fix deadlock SIOCGIWSCAN handler + * libertas: fix default adhoc channel + * libertas: honor specific channel requests during association + * libertas: send SIOCGIWSCAN event after partial scans too + * libertas: debug print spacing fixes in assoc.c + * libertas: add more verbose debugging to libertas_cmd_80211_authenticate + * libertas: Make WPA work through supplicant handshake + * libertas: updated readme file + * libertas: make mac address configuration work with mesh interface too + * libertas: split wext for eth and msh + * libertas: support for mesh autostart on firmware 5.220.11 + * libertas: fix character set in README + * libertas: sparse fixes + * libertas: first pass at fixing up endianness issues + * libertas: More endianness fixes. + * libertas: more endianness fixes, in tx.c this time + * libertas: don't byte-swap firmware version number. It's a byte array. + * libertas: fix big-endian associate command. + * libertas: tweak association debug output + * libertas: remove structure WLAN_802_11_SSID and libertas_escape_essid + * libertas: remove WPA_SUPPLICANT structure + * libertas: reduce SSID and BSSID mixed-case abuse + * kbuild: fix sh64 section mismatch problems + * cfg80211: fix signed macaddress in sysfs + * mac80211: fix debugfs tx power reduction output + * mac80211: Don't stop tx queue on master device while scanning. + * Input: usbtouchscreen - fix fallout caused by move from drivers/usb + * Input: i8042 - add ASUS P65UP5 to the noloop list + * Input: i8042 - add ULI EV4873 to noloop list + * [PARISC] remove global_ack_eiem + * libertas: pull current channel from firmware on mesh autostart + * libertas: deauthenticate from AP in channel switch + * libertas: actually send mesh frames to mesh netdev + * libertas: convert libertas_mpp into anycast_mask + * [PPP_MPPE]: Fix "osize too small" check. + * NetXen: Fix link status messages + * myri10ge: limit the number of recoveries + * myri10ge: report when the link partner is running in Myrinet mode + * myri10ge: update driver version + * sysfs: store sysfs inode nrs in s_ino to avoid readdir oopses + * sysfs: fix condition check in sysfs_drop_dentry() + * sysfs: fix race condition around sd->s_dentry, take#2 + * [TCP]: Fix left_out setting during FRTO + * Input: move input-polldev to drivers/input + * [SPARC64]: Wire up cookie based sun4v interrupt registry. + * [SPARC64]: Fix IO/MEM space sizing for PCI. + * [SPARC64]: Really fix parport. + * [SPARC64]: Fix args to sun4v_ldc_revoke(). + * [TCP]: Set initial_ssthresh default to zero in Cubic and BIC. + * mmc-omap: fix sd response type 6 vs. 1 + * mmc: get back read-only switch function + * [SCTP]: Correctly set daddr for IPv6 sockets during peeloff + * [SCTP]: Allow unspecified port in sctp_bindx() + * [SCTP] Fix leak in sctp_getsockopt_local_addrs when copy_to_user fails + * [SCTP] Update pmtu handling to be similar to tcp + * [SCTP] Flag a pmtu change request + * [SCTP] Don't disable PMTU discovery when mtu is small + * [POWERPC] Fix per-cpu allocation on oldworld SMP powermacs + * [POWERPC] Fix console output getting dropped on platforms without + udbg_putc + * [AVR32] ratelimit segfault reporting rate + * [AVR32] gpio_*_cansleep() fix + * [AVR32] STK1000: Set SPI_MODE_3 in the ltv350qv board info + * [AVR32] Define ARCH_KMALLOC_MINALIGN to L1_CACHE_BYTES + * [MIPS] Malta: Fix for SOCitSC based Maltas + * [MIPS] Separate performance counter interrupts + * [MIPS] Fix builds where MSC01E_xxx is undefined. + * [TCP]: Add missing break to TCP option parsing code + * [IPV6] addrconf: Fix IPv6 on tuntap tunnels + * [AGPGART] intel_agp: fix device probe + * KVM: Prevent guest fpu state from leaking into the host + * splice: adjust balance_dirty_pages_ratelimited() call + * splice: fix leak of pages on short splice to pipe + * splice: only check do_wakeup in splice_to_pipe() for a real pipe + * [TCP]: Congestion control API RTT sampling fix + * [TCP]: Fix logic breakage due to DSACK separation + * [RXRPC] net/rxrpc/ar-connection.c: fix NULL dereference + * block: always requeue !fs requests at the front + * mm: Fix memory/cpu hotplug section mismatch and oops. + * Resume from RAM on HPC nx6325 broken + * ide-scsi: fix OOPS in idescsi_expiry() + * fix radeon setparam on 32/64 systems, harder. + * tty: restore locked ioctl file op + * i386: fix NMI watchdog not reserving its MSRs + * i386: use the right wrapper to disable the NMI watchdog + * SLUB slab validation: Alloc while interrupts are disabled must use + GFP_ATOMIC + * Restore shmid as inode# to fix /proc/pid/maps ABI breakage + * i386 mm: use pte_update() in ptep_test_and_clear_dirty() + * cpuset: zero malloc - fix for old cpusets + * toshiba_acpi: fix section mismatch in allyesconfig + * swsusp: Fix userland interface + * perfctr-watchdog: fix interchanged parameters to + release_{evntsel,perfctr}_nmi + * fuse: ->fs_flags fixlet + * md: fix two raid10 bugs + * md: fix bug in error handling during raid1 repair + * spi doc updates + * uml: remove PAGE_SIZE from libc code + * uml: kill x86_64 STACK_TOP_MAX + * random: fix output buffer folding + * Rework ptep_set_access_flags and fix sun4c + * SLUB: minimum alignment fixes + * udf: fix possible leakage of blocks + * hugetlb: fix get_policy for stacked shared memory files + * shm: fix the filename of hugetlb sysv shared memory + * Linux 2.6.22-rc5 + * [GFS2] flush the glock completely in inode_go_sync + * [DLM] fix a couple of races + * [GFS2] kernel changes to support new gfs2_grow command + * [GFS2] Kernel changes to support new gfs2_grow command (part 2) + * [GFS2] use zero_user_page + * [GFS2] Addendum patch 2 for gfs2_grow + * [GFS2] Reduce size of struct gdlm_lock + * [GFS2] Clean up inode number handling + * [GFS2] Quotas non-functional - fix bug + * [DLM] keep dlm from panicing when traversing rsb list in debugfs + * [DLM] block scand during recovery [1/6] + * [DLM] add lock timeouts and warnings [2/6] + * [DLM] dlm_device interface changes [3/6] + * [DLM] cancel in conversion deadlock [4/6] + * [DLM] fix new_lockspace error exit [5/6] + * [DLM] wait for config check during join [6/6] + * [DLM] fix compile breakage + * [GFS2] latest gfs2-nmw headers break userland build + * [DLM] Compile fix + * [DLM] timeout fixes + * [DLM] canceling deadlocked lock + * [DLM] dumping master locks + * [DLM] show default protocol + * [GFS2] Quotas non-functional - fix another bug + * [GFS2] Make the log reserved blocks depend on block size + * [DLM] fix socket shutdown + * [GFS2] fix jdata issues + * [GFS2] Fix sign problem in quota/statfs and cleanup _host structures + * [GFS2] Add nanosecond timestamp feature + * [DLM] fix reference counting + * [DLM] variable allocation + * [GFS2] Fix typo in rename of directories + * [GFS2] Fix bug in error path of inode + * [GFS2] Can't mount GFS2 file system on AoE device + * [GFS2] Recovery for lost unlinked inodes + * [GFS2] gfs2_lookupi() uninitialised var fix + * [GFS2] set plock owner in GETLK info + * [GFS2] return conflicts for GETLK + * [GFS2] Fix deallocation issues + * [DLM] don't require FS flag on all nodes + * [GFS2] Journaled file write/unstuff bug + * [GFS2] Remove bogus '\0' in rgrp.c + * [GFS2] Use zero_user_page() in stuffed_readpage() + * [GFS2] assertion failure after writing to journaled file, umount + * [GFS2] Simplify multiple glock aquisition + * [GFS2] Addendum to the journaled file/unmount patch + + -- Ben Collins Fri, 01 Jun 2007 12:15:58 -0400 + +linux-source-2.6.22 (2.6.22-6.13) gutsy; urgency=low + + [Ben Collins] + + * Bump ABI + * build/scripts: Remove all remnants of debconf from control scripts + * build/config: Re-enable paravirt/vmi + * build/config: Build ide-core as a module + * i386/x86_64: Allow disabling the putstr's from compressed boot wrapper + * PM: Do not require dev spew to get PM_DEBUG + * RTC: Ratelimit "lost interrupts" message + * UNUSUAL_DEV: Sync up some reported devices from Ubuntu + * build/d-i: Include ide-core in storage-core udeb, not that it's modular + * build/d-i: Make ide-modules depend on storage-code-modules + * build/config: Enable CONFIG_TIMER_STATS on x86_64. + * build/config: Disable CONFIG_RTC_DRV_CMOS + * build/config: Enable TIMER_STATS everywhere. + * build/config: Enable SND_AC97_POWER_SAVE + - LP: #116679 + * kmod: Improve call_usermodehelper_pipe to handle data close + * coredump: Convert to new call_usermodehelper_pipe symantics + * PPC: Only set hwif stuff when ide-core is non-modular + * PPC/MEDIABAY: Export some functions for modular ide-core/ppc-ide + + [Colin Watson] + + * Move isofs to storage-core-modules udeb from fs-core-modules. + + [Upstream Kernel Changes] + + * Input: logips2pp - add type 72 (PS/2 TrackMan Marble) + * Input: adbhid - do not access input_dev->private directly + * sh: Shut up compiler warnings in __do_page_fault(). + * sh: Fix up psw build rules for r7780rp. + * sh: Kill off pmb slab cache destructor. + * sh: landisk: rtc-rs5c313 support. + * sh: landisk: Header cleanups. + * input: hp680_ts compile fixes. + * [ARM] 4375/1: sharpsl_pm: Fix compile warnings + * [ARM] 4376/1: Selects GENERIC_GPIO for ARCH_IXP4XX in Kconfig + * [ARM] 4378/1: KS8695: Serial driver fix + * [ARM] Remove Integrator/CP SMP platform support + * [ARM] 4382/1: iop13xx: fix msi support + * [ARM] 4383/1: iop: fix usage of '__init' and 'inline' in iop files + * [ARM] 4384/1: S3C2412/13 SPI registers offset correction + * [ARM] Update ARM syscalls + * [ARM] Silence OMAP kernel configuration warning + * [ARM] gic: Fix gic cascade irq handling + * [ARM] integrator: fix pci_v3 compile error with DEBUG_LL + * [ARM] ARMv6: add CPU_HAS_ASID configuration + * [CRYPTO] padlock: Make CRYPTO_DEV_PADLOCK a tristate again + * [CRYPTO] tcrypt: Add missing error check + * eventfd use waitqueue lock ... + * timerfd use waitqueue lock ... + * [IA64] Fix bogus messages about system calls not implemented. + * [IA64] Yet another section mismatch warning + * Fix roundup_pow_of_two(1) + * Further update of the i386 boot documentation + * cciss: Fix pci_driver.shutdown while device is still active + * Linux v2.6.22-rc2 + * [CRYPTO] api: Read module pointer before freeing algorithm + * powerpc: Fix the MODALIAS generation in modpost for of devices + * kbuild: include limits.h in sumversion.c for PATH_MAX + * kconfig: search harder for curses library in check-lxdialog.sh + * kbuild: make modpost section warnings clearer + * kbuild: make better section mismatch reports on i386, arm and mips + * kbuild: add "Section mismatch" warning whitelist for powerpc + * all-archs: consolidate .text section definition in asm-generic + * all-archs: consolidate .data section definition in asm-generic + * kbuild: introduce __init_refok/__initdata_refok to supress section + mismatch warnings + * init/main: use __init_refok to fix section mismatch + * mm: fix section mismatch warnings + * mm/slab: fix section mismatch warning + * IB/core: Free umem when mm is already gone + * IB/ipath: Fix potential deadlock with multicast spinlocks + * IB/core: Add helpers for uncached GID and P_Key searches + * IB/core: Use start_port() and end_port() + * IPoIB: Handle P_Key table reordering + * IB/ehca: Return proper error code if register_mr fails + * IB/mthca: Fix use-after-free on device restart + * IB/mlx4: Fix check of max_qp_dest_rdma in modify QP + * IB/mthca: Set GRH:HopLimit when building MLX headers + * IB/mlx4: Set GRH:HopLimit when sending globally routed MADs + * IB/mthca: Fix RESET to ERROR transition + * IB/mlx4: Fix RESET to RESET and RESET to ERROR transitions + * mlx4_core: Fix array overrun in dump_dev_cap_flags() + * IB/mlx4: Fix check of opcode in mlx4_ib_post_send() + * [IPV6]: Add ip6_tunnel.h to headers_install + * [RFKILL]: Fix check for correct rfkill allocation + * [NET]: Fix net/core/skbuff.c gcc-3.2.3 compilation error + * [TCP] FRTO: Add missing ECN CWR sending to one of the responses + * [TCP] FRTO: Prevent state inconsistency in corner cases + * [IPSEC] pfkey: Load specific algorithm in pfkey_add rather than all + * [NETFILTER]: nf_conntrack: fix use-after-free in helper destroy + callback invocation + * [NETFILTER]: nf_conntrack_ipv4: fix incorrect #ifdef config name + * [IPV4]: icmp: fix crash with sysctl_icmp_errors_use_inbound_ifaddr + * [NET]: Fix race condition about network device name allocation. + * IB/mlx4: Pass send queue sizes from userspace to kernel + * [ARM] 4387/1: fix /proc/cpuinfo formatting for pre-ARM7 parts + * [ARM] 4388/1: no need for arm/mm mmap range checks for non-mmu + * [ARM] 4395/1: S3C24XX: add include of to relevant + machines + * [ARM] 4396/1: S3C2443: Add missing HCLK clocks + * [ARM] 4397/1: S3C2443: remove SDI0/1 IRQ ambiguity + * [ARM] 4398/1: S3C2443: Fix watchdog IRQ number + * [ARM] 4399/2: S3C2443: Fix SMDK2443 nand timings + * [ARM] 4400/1: S3C24XX: Add high-speed MMC device definition + * [ARM] at91_adc parenthesis balance + * [ARM] spelling fixes + * IB/mlx4: Check if SRQ is full when posting receive + * spelling fixes: arch/sh/ + * sh: revert addition of page fault notifiers + * sh: Wire up signalfd/timerfd/eventfd syscalls. + * sh: Fix up various compile warnings for SE boards. + * sh: Fix page size alignment in __copy_user_page(). + * sh: Disable psw support for R7785RP. + * fs: Kill sh dependency for binfmt_flat. + * sh: disable genrtc support. + * sh: sr.bl toggling around idle sleep. + * sh: Wire up kdump crash kernel exec in die(). + * sh: Fix clock multiplier on SH7722. + * sh: Fix dreamcast build for IRQ changes. + * [S390] cio: Update documentation. + * [S390] Wire up sys_utimensat. + * [S390] Wire up signald, timerfd and eventfd syscalls. + * [S390] Make use of kretprobe_assert. + * [S390] More verbose show_mem() like other architectures. + * Fix "fs: convert core functions to zero_user_page" + * Detach sched.h from mm.h + * Blackfin arch: Add Workaround for ANOMALY 05000257 + * Blackfin arch: add SPI MMC driver support on bf533-stamp, tested on + STAMP-BF533 + * Blackfin arch: ISP1761 doesn't work for USB flash disk + * Blackfin arch: fix a few random warnings + * Blackfin arch: Add configuration data for ISP176x on BF561 + * Blackfin arch: mark a bunch of local functions as static + * Blackfin arch: Fix reserved map after we changed PORT_H definition + * Blackfin arch: Move write to VR_CTL closer to IDLE + * Blackfin arch: DMA operation cleanup + * Blackfin arch: GPIO fix some defines + * Blackfin arch: fix trace output for FLAT binaries + * Blackfin arch: Fix bug using usb keyboard crashes kernel + * Blackfin arch: initial tepla-bf561 board support + * Blackfin arch: make sure we declare the revid functions as pure (since + they are) + * Blackfin arch: dont clear status register bits in SWRST so we can + actually use it + * Blackfin arch: finish removing p* volatile defines for MMRs + * Blackfin arch: move board specific setup out of common init code and + into the board specific init code + * Blackfin arch: issue reset via SWRST so we dont clobber the watchdog + state + * Blackfin arch: document why we have to touch the UART peripheral in our + boot up code + * Blackfin arch: dma_memcpy borken for > 64K + * Blackfin arch: dont clear the bit that tells coreb to start booting + * Blackfin arch: make sure we use local labels + * Blackfin arch: update blackfin header files to latest one in VDSP. + * Blackfin arch: cache SWRST value at bootup so other things like + watchdog can non-destructively query it + * Blackfin arch: fix signal handling bug + * Blackfin arch: Change NO_ACCESS_CHECK to ACCESS_CHECK + * Blackfin arch: add board default configs to blackfin arch + * Blackfin arch: update defconfig files + * Blackfin arch: update pm.c according to power management API change. + * Blackfin serial driver: fix overhead issue + * Blackfin serial driver: implement support for ignoring parity/break + errors + * Blackfin SPI: cleanup according to David Brownell's review + * x86_64: Update defconfig + * i386: Update defconfig + * x86_64: Support x86_64 in make buildtar + * i386: Fix K8/core2 oprofile on multiple CPUs + * x86_64: Support gcc 5 properly + * i386: Clear MCE flag on AMD K6 + * i386: Fix wrong CPU error message in early boot path + * i386: Enable CX8/PGE CPUID bits early on VIA C3 + * x86_64: early_print kernel console should send CRLF not LFCR + * x86_64: vsyscall time() fix + * i386: fix PGE mask + * LDM: Fix for Windows Vista dynamic disks + * IB/ipoib: Fix typos in error messages + * IPoIB/cm: Fix SRQ WR leak + * IB/cm: Improve local id allocation + * e1000: Don't enable polling in open() (was: e1000: assertion hit in + e1000_clean(), kernel 2.6.21.1) + * declance: Remove a dangling spin_unlock_irq() thingy + * Add constant for FCS/CRC length (frame check sequence) + * ahci: disable 64bit dma on sb600 + * libata: Add Seagate STT20000A to DMA blacklist. + * pata_hpt366: Enable bits are unreliable so don't use them + * ata_piix: clean up + * libata: Kiss post_set_mode goodbye + * libata: Trim trailing whitespace + * partitions/LDM: build fix + * Make 'headerscheck' stop immediately on an error + * Fix headers check fallout + * [POWERPC] Fix smp_call_function to be preempt-safe + * [POWERPC] Add missing pmc_type fields in cpu_table + * [POWERPC] Fix typo: MMCR0_PMA0 != MMCR0_PMAO + * [POWERPC] Fix powerpc vmlinux.lds.S + * [POWERPC] Fix warning in 32-bit builds with CONFIG_HIGHMEM + * libertas: skb dereferenced after netif_rx + * drivers/net/wireless/libertas/fw.c: fix use-before-check + * drivers/net/wireless/libertas/rx.c: fix use-after-free + * [IA64] Improve unwind checking. + * [IA64] Only unwind non-running tasks. + * [IA64] fix kmalloc(0) in arch/ia64/pci/pci.c + * i2c: Legacy i2c drivers shouldn't issue uevents + * i2c-tiny-usb: Fix truncated adapter name + * i2c-s3c2410: Fix build warning + * V4L/DVB (5639): Fix Kconfig dependencies for ivtv + * V4L/DVB (5640): Fix: em28xx shouldn't be selecting VIDEO_BUF + * V4L/DVB (5670): Adding new fields to v4l2_pix_format broke the ABI, + reverted that change + * V4L/DVB (5639a): Fix dst usage count + * V4L/DVB (5630): Dvb-core: Handle failures to create devices + * V4L/DVB (5680): Tuner-simple.c fix suport for SECAM with FI1216MF + * V4L/DVB (5690): Cafe_ccic: Properly power down the sensor + * V4L/DVB (5691): Ov7670: reset clkrc in rgb565 mode + * [IPSEC]: Fix warnings with casting int to pointer + * [AF_RXRPC]: AF_RXRPC depends on IPv4 + * [AF_RXRPC]: Make call state names available if CONFIG_PROC_FS=n + * [RTNETLINK]: Allow changing of subsets of netdevice flags in + rtnl_setlink + * [RTNETLINK]: Remove remains of wireless extensions over rtnetlink + * Input: iforce - fix force feedback not working + * Input: iforce - minor clean-ups + * Input: ALPS - force stream mode + * Input: ucb1400_ts - use sched_setscheduler() + * Input: ucb1x00-ts - remove commented out code + * Input: input-polldev - add module info + * Input: ads7846 - document that it handles tsc2046 too + * Input: ads7846 - SPI_CPHA mode bugfix + * USB: fix omninet memory leak found by coverity + * USB: remove useless check in mos7840 found by coverity + * usb-storage: ignore Sitecom WL-117 USB-WLAN + * USB: fix more ftdi-elan/u132-hcd #include lossage + * USB: handle more rndis_host oddities + * USB: remove usb DocBook warnings + * USB: address FIXME in usbnet w.r.t drivers claiming multiple interfaces + * EHCI: fix problem with BIOS handoff + * USB: more autosuspend timer stuff + * USB: remove unneeded WARN_ON + * USB: New device PID for ftdi_sio driver + * USB: set the correct Interrupt interval in usb_bulk_msg + * USB: fsl_usb2_udc: Fix UMTI_WIDE support and a compile warning + * USB: auerswald: fix file release handler + * USB: Remove duplicate IDs from option card driver + * USB: Deref URB after usbmon is done with it + * USB: remove short initial timeout for device descriptor fetch + * USB: don't try to kzalloc 0 bytes + * USB: Onetouch - switch to using input_dev->dev.parent + * USB: Fix debug output of ark3116 + * USB: usblp: Use correct DMA address in case of probe error + * USB: Fix USB OHCI Subvendor for Toshiba Portege 4000 + * USB: make the autosuspend workqueue thread freezable + * USB: handle errors in power/level attribute + * USB: fix ratelimit call semantics + * USB: ftdi_sio: Add USB Product Id for OpenDCC + * USB: ldusb bugfix + * USB: Add support for Sierra Wireless Aircard 595U + * USB: Add support for Olimex arm-usb-ocd JTAG interface serial port + * IB/mlx4: Don't allocate RQ doorbell if using SRQ + * [IA64] start_secondary() and smp_callin() should be __cpuinit + * add the IDE device ID for ATI SB700 + * ide/pci/serverworks.c: Fix corruption/timeouts with MegaIDE + * Add two missing chipsets to drivers/ide/ide-proc.c + * Match DMA blacklist entries between ide-dma.c and libata-core.c + * ide serverworks warning fixes + * freezer: close potential race between refrigerator and thaw_tasks + * freezer: fix vfork problem + * freezer: take kernel_execve into consideration + * freezer: fix kthread_create vs freezer theoretical race + * freezer: fix PF_NOFREEZE vs freezeable race + * freezer: move frozen_process() to kernel/power/process.c + * Ignore bogus ACPI info for offline CPUs + * SLUB Debug: Fix object size calculation + * fuse: fix mknod of regular file + * mpc52xx_psc_spi: fix it for CONFIG_PPC_MERGE + * spi doc update: describe clock mode bits + * NOHZ: Rate limit the local softirq pending warning output + * genhd: expose AN to user space + * genhd: send async notification on media change + * capability.h warning fix + * spi/spidev: check message size before copying + * uml: improve PTRACE_SYSEMU checking + * prohibit rcutorture from being compiled into the kernel + * Documentation: fix the explanation of Kconfig files + * Avoid zero size allocation in cache_k8_northbridges() + * recalc_sigpending_tsk fixes + * optimize compat_core_sys_select() by a using stack space for small fd + sets + * spi: potential memleak in spidev_ioctl + * fbdev: cleanup of sparc FB options + * pm2fb: RDAC_WR barriers clean up + * pm3fb: various fixes + * w100fb: fix compile warnings + * ps3fb: use FB_SYS_* instead of FB_CFB_* + * imxfb: remove ifdefs + * imxfb: fix memory hole + * Missing 'const' from reiserfs MIN_KEY declaration. + * uselib: add missing MNT_NOEXEC check + * fuse: generic_write_checks() for direct_io + * fuse: delete inode on drop + * fix unused setup_nr_node_ids + * SLUB Debug: fix check for super sized slabs (>512k 64bit, >256k 32bit) + * Char: cyclades, fix deadlock + * simplify cleanup_workqueue_thread() + * phantom: move to unlocked_ioctl + * Misc: phantom, take care of pci posting + * power: Fix sizeof(PAGE_SIZE) typo + * update dontdiff file + * signalfd: retrieve multiple signals with one read() call + * i2o: destroy event queue only when drv->event is set + * i2o: fix notifiers when max_drivers is configured + * i2o: eliminate a peculiar constraint on i2o_max_drivers + * i386, x86-64: show that CONFIG_HOTPLUG_CPU is required for suspend on + SMP + * md: avoid overflow in raid0 calculation with large components + * md: don't write more than is required of the last page of a bitmap + * md: fix bug with linear hot-add and elsewhere + * documentation: Documentation/initrd.txt + * HiSax: fix error checking for hisax_register()] + * applesmc - sensors patch missing from 2.6.22-rc2 + * Off by one in floppy.c + * eCryptfs: delay writing 0's after llseek until write + * document clocksources + * ehci-fsl: fix cache coherency problem on system with large memory + * Prevent going idle with softirq pending + * i386: fix early usage of atomic_add_return and local_add_return on real + i386 + * Documentation/memory-barriers.txt: various fixes + * omap_uwire: SPI_CPHA mode bugfix + * capifunc warning fixes + * drivers/isdn/hardware/eicon/message.c warning fixes + * i386 bigsmp: section mismatch fixes + * boot documentation: clarifications + * mmc: clean up unused parts of block driver + * mmc: mark unmaintained drivers + * mmc: Add maintainers for TI OMAP MMC interface + * mmc: add maintainer for iMX MMC interface + * mmc: add maintainer for ARM Primecell controller + * [CRYPTO] geode: Fix in-place operations and set key + * [Bluetooth] Always send HCI_Reset for Broadcom devices + * [Bluetooth] Fix L2CAP configuration parameter handling + * NFS: Avoid a deadlock situation on write + * NFS: Fix handful of compiler warnings in direct.c + * NFS: Fix nfs_direct_dirty_pages() + * Don't call a warnign a bug. It's a warning. + * [IA64] Fix using uninitialized data in _PDC setup + * [IA64] Cleanup acpi header to reuse the generic _PDC defines + * Documentation: Fix up docs still talking about i_sem + * [IA64] acpi_get_sysname() should be __init + * IB/mlx4: Initialize send queue entry ownership bits + * IB/ehca: Fix number of send WRs reported for new QP + * IPoIB/cm: Fix timeout check in ipoib_cm_dev_stop() + * IPoIB/cm: Drain cq in ipoib_cm_dev_stop() + * ucc_geth: Fix MODULE_DEVICE_TABLE() duplication + * ucc_geth:trivial fix + * asix.c - Add Belkin F5D5055 ids + * fix compiler warning in fixed.c + * remove unnecessary dependency on VIA velocity config + * meth driver renovation + * spidernet: skb used after netif_receive_skb + * chelsio parenthesis fix + * forcedeth: fix cpu irq mask + * [NET_SCHED]: Fix qdisc_restart return value when dequeue is empty + * [IPV6]: Ignore ipv6 events on non-IPV6 capable devices. + * [ATM]: Use mutex instead of binary semaphore in idt77252 driver. + * [DCCP]: Use menuconfig objects. + * [IPVS]: Use menuconfig objects. + * [SCTP]: Use menuconfig objects. + * [TIPC]: Use menuconfig objects. + * [ARCNET]: Use menuconfig objects. + * [TR]: Use menuconfig objects. + * [RTNETLINK]: Fix sending netlink message when replace route. + * [TIPC]: Fixed erroneous introduction of for_each_netdev + * [DCCP]: Fix build warning when debugging is disabled. + * [NET_SCHED]: sch_htb: fix event cache time calculation + * [NETFILTER]: nf_conntrack_ftp: fix newline sequence number update + * [NETFILTER]: nf_conntrack_ftp: fix newline sequence number calculation + * [NETFILTER]: nf_conntrack_h323: fix ASN.1 types + * [NETFILTER]: nf_conntrack_h323: fix get_h225_addr() for IPv6 address + access + * [NETFILTER]: nf_conntrack_h323: remove unnecessary process of + Information signal + * [NETFILTER]: nf_conntrack_h323: add missing T.120 address in OLCA + * [NETFILTER]: nf_nat_h323: call set_h225_addr instead of + set_h225_addr_hook + * [NET]: "wrong timeout value" in sk_wait_data() v2 + * hpt3x2n: Correct revision boundary + * pata_sis: Fix and clean up some timing setups + * ata_piix: add short 40c quirk for Acer Aspire 2030, take #2 + * libata: don't consider 0xff as port empty if SStatus is available + * libata: -ENODEV during prereset isn't an error + * pata_via: Handle laptops via DMI + * [CASSINI]: Check pci_set_mwi() return value. + * [XFRM]: Allow packet drops during larval state resolution. + * [libata] sata_promise: fix flags typo + * [libata] sata_mv: add TODO list + * Fix build failure for drivers/ata/pata_scc.c + * libata: sata_sis fixes + * [libata] Fix decoding of 6-byte commands + * [libata] sata_via, pata_via: Add PCI IDs. + * ocfs2: trylock in ocfs2_readpage() + * ocfs2: unmap_mapping_range() in ocfs2_truncate() + * ocfs2: use zero_user_page + * ocfs2: fix inode leak + * ocfs2: use generic_segment_checks + * pata: Trivia + * pata_hpt37x: Further improvements based on the IDE updates and vendor + drivers + * fix compat console unimap regression + * Linux 2.6.22-rc3 + + -- Ben Collins Thu, 31 May 2007 12:35:44 -0400 + +linux-source-2.6.22 (2.6.22-5.11) gutsy; urgency=low + + [Ben Collins] + + * build/headers/ppc: Correct asm-ppc -> asm for arch symlink + * build/headers/ia64: Fix find command line to correctly pull in *.lds + files + * Bump ABI + + [Upstream Kernel Changes] + + * [IA64] spelling fixes: arch/ia64/ + * [AVR32] Remove bogus comment in arch/avr32/kernel/irq.c + * [AVR32] optimize pagefault path + * [AVR32] Wire up signalfd, timerfd and eventfd + * [IA64] wire up {signal,timer,event}fd syscalls + * [IA64] kdump on INIT needs multi-nodes sync-up (v.2) + * [IA64] s/scalibility/scalability/ + * [AVR32] Implement platform hooks for atmel_lcdfb driver + * [IA64] Fix section conflict of ia64_mlogbuf_finish + * [SPARC64]: Add hypervisor API negotiation and fix console bugs. + * pata_scc had been missed by ata_std_prereset() switch + * libata: separate out ata_dev_reread_id() + * libata: during revalidation, check n_sectors after device is configured + * libata-acpi: add ATA_FLAG_ACPI_SATA port flag + * libata: fix shutdown warning message printing + * libata: track spindown status and skip spindown_compat if possible + * [ALSA] usb-audio: another Logitech QuickCam ID + * [ALSA] hda-codec - Make the mixer capability check more robust + * [ALSA] ASoC AC97 static GPL symbol fix + * [ALSA] ASoC AC97 device reg bugfix + * [ALSA] hda-codec - Fix ALC882/861VD codec support on some laptops + * [ALSA] version 1.0.14rc4 + * [ALSA] Fix probe of non-PnP ISA devices + * [ALSA] Include quirks from Ubuntu Dapper/Edgy/Feisty + * [ALSA] usbaudio - Coping with short replies in usbmixer + * [IA64] optimize pagefaults a little + * Fix ACPI suspend / device suspend ordering problem + * AFS: write back dirty data on unmount + * SLUB: It is legit to allocate a slab of the maximum permitted size + * slub: don't confuse ctor and dtor + * AFS: Fix afs_prepare_write() + * spi: fix spidev for >sizeof(long)/32 devices + * parport_pc needs dma-mapping.h + * Fix: find_or_create_page skips cpuset memory spreading. + * slob: implement RCU freeing + * Slab allocators: Drop support for destructors + * SLUB: Remove depends on EXPERIMENTAL and !ARCH_USES_SLAB_PAGE_STRUCT + * SLAB: Move two remaining SLAB specific definitions to slab_def.h + * SLUB: Define functions for cpu slab handling instead of using + PageActive + * slab: warn on zero-length allocations + * slub: fix handling of oversized slabs + * SLUB: slabinfo fixes + * SLUB: Do our own flags based on PG_active and PG_error + * Remove SLAB_CTOR_CONSTRUCTOR + * SLUB: Simplify debug code + * Slab allocators: define common size limitations + * acpi: fix potential call to a freed memory section. + * i386/x86-64: fix section mismatch + * Make __vunmap static + * simplify compat_sys_timerfd + * Let smp_call_function_single return -EBUSY on UP + * Refine SCREEN_INFO sanity check for vgacon initialization + * make freezeable workqueues singlethread + * parport: mailing list is subscribers-only + * docbook: make kernel-locking table readable + * gpio interface loosens call restrictions + * rtc-omap build fix + * rtc kconfig clarification + * icom: add new sub-device-id to support new adapter + * make sysctl/kernel/core_pattern and fs/exec.c agree on maximum core + filename size + * ecryptfs: use zero_user_page + * i386: don't check_pgt_cache in flush_tlb_mm + * circular locking dependency found in QUOTA OFF + * swsusp: fix sysfs interface + * Fix page allocation flags in grow_dev_page() + * mm: more rmap checking + * NS16550A: Restore HS settings in EXCR2 on resume + * Fix incorrect prototype for ipxrtr_route_packet() + * sky2: remove Gigabyte 88e8056 restriction + * sky2: PHY register settings + * sky2: keep track of receive alloc failures + * sky2: MIB counter overflow handling + * sky2: remove dual port workaround + * sky2: memory barriers change + * small netdevices.txt fix + * ibm_emac: fix section mismatch warnings + * ibm_emac: improved PHY support + * ibm_emac: fix link speed detection change + * gianfar: Add I/O barriers when touching buffer descriptor ownership. + * spidernet: node-aware skbuff allocation + * NetXen: Fix NetXen driver ping on system-p + * ixgb: don't print error if pci_enable_msi() fails, cleanup minor leak + * e1000: Fix msi enable leak on error, don't print error message, cleanup + * drivers/ata: remove the wildcard from sata_nv driver + * sata_nv: fix fallout of devres conversion + * libata: remove libata.spindown_compat + * sata_via: pcim_iomap_regions() conversion missed BAR5 + + -- Ben Collins Thu, 17 May 2007 14:54:16 -0400 + +linux-source-2.6.22 (2.6.22-4.10) gutsy; urgency=low + + [Ben Collins] + + * Bump ABI + * build/config: Disable obsolete tsdev driver. + * build: Add tsdev to list of modules intentionally removed. + * build/headers: Include *.lds files (fixes ia64 headers). + * build/headers: Add arch/powerpc/include/asm symlink to get all headers. + * build/module-check: Fix logic for printed messages. + * build/maintainer: Use linux instead of upstream-linux for local diffs + * build/config: Enable SLUB slab allocator (vs. SLAB). + * build/config: Disable orinoco_nortel, use prefered hostap_plx + * build/config: Disable ir-usb in favor of irda-usb + * build/config: Disable sis5513(ide) in favor of pata_sis(libata) + * build/config: Disable piix(ide) in favour of pata_oldpiix, ata_piix and + pata_mpiix (libata) + * build/config: Disable zaurus driver in favour of the cdc_ether driver + * build/abi: Note a few modules intentionally removed. + * build/config: Disable mxb and dpc7146 driver in favour of hexium_orion + * build/config: Disable usbtest driver (for development only) + * build/config: Disable keyspan driver in favour of keyspan_pda + * build/abi: Add mxb and usbtest to list of removed modules. + + [Upstream Kernel Changes] + + * net: Trivial MLX4_DEBUG dependency fix. + * mlx4_core: Remove unused doorbell_lock + * [CPUFREQ] Support rev H AMD64s in powernow-k8 + * [CPUFREQ] powernow-k7: fix MHz rounding issue with perflib + * [AGPGART] Fix wrong ID in via-agp.c + * sh64: ROUND_UP macro cleanup in arch/sh64/kernel/pci_sh5.c + * spelling fixes: arch/sh64/ + * sh64: Wire up many new syscalls. + * sh64: Fixups for the irq_regs changes. + * sh64: dma-mapping updates. + * sh64: ppoll/pselect6() and restartable syscalls. + * sh64: Fixup sh-sci build. + * sh64: Update cayman defconfig. + * sh64: generic quicklist support. + * sh64: Add .gitignore entry for syscalltab. + * IB/mlx4: Fix uninitialized spinlock for 32-bit archs + * IB/ipath: Shadow the gpio_mask register + * IB/ehca: Serialize hypervisor calls in ehca_register_mr() + * IB/ehca: Correctly set GRH mask bit in ehca_modify_qp() + * IB/ehca: Fix AQP0/1 QP number + * IB/ehca: Remove _irqsave, move #ifdef + * IB/ehca: Beautify sysfs attribute code and fix compiler warnings + * IB/ehca: Disable scaling code by default, bump version number + * RDMA/cma: Simplify device removal handling code + * RDMA/cma: Fix synchronization with device removal in cma_iw_handler + * RDMA/cma: Add check to validate that cm_id is bound to a device + * IB/mthca: Fix posting >255 recv WRs for Tavor + * IB/mthca: Set cleaned CQEs back to HW ownership when cleaning CQ + * IPoIB/cm: Optimize stale connection detection + * [CPUFREQ] Correct revision mask for powernow-k8 + * fix epoll single pass code and add wait-exclusive flag + * epoll locks changes and cleanups + * epoll: fix some comments + * epoll: move kfree inside ep_free + * nommu: add ioremap_page_range() + * h8300 atomic.h update + * alpha: fix hard_smp_processor_id compile error + * m68k: implement __clear_user() + * Remove cpu hotplug defines for __INIT & __INITDATA + * i386: move common parts of smp into their own file + * i386: fix voyager build + * SLUB: CONFIG_LARGE_ALLOCS must consider MAX_ORDER limit + * ll_rw_blk: fix gcc 4.2 warning on current_io_context() + * pasemi_mac: Fix register defines + * pasemi_mac: Interrupt ack fixes + * pasemi_mac: Terminate PCI ID list + * pasemi_mac: Fix local-mac-address parsing + * smc911x: fix compilation breakage + * ucc_geth: eliminate max-speed, change interface-type to + phy-connection-type + * pdc202xx_old: rewrite mode programming code (v2) + * serverworks: PIO mode setup fixes + * sis5513: PIO mode setup fixes + * alim15x3: use ide_tune_dma() + * pdc202xx_new: use ide_tune_dma() + * ide: always disable DMA before tuning it + * cs5530/sc1200: add ->udma_filter methods + * ide: use ide_tune_dma() part #2 + * cs5530/sc1200: DMA support cleanup + * cs5530/sc1200: add ->speedproc support + * sl82c105: add speedproc() method and MWDMA0/1 support + * ide: remove ide_dma_enable() + * ide: add missing validity checks for identify words 62 and 63 + * ide: remove ide_use_dma() + * sl82c105: Switch to ref counting API + * Use menuconfig objects: IDE + * x86: Fix discontigmem + non-HIGHMEM compile + * missing mm.h in fw-ohci + * missing dependencies for USB drivers in input + * missing includes in mlx4 + * em28xx and ivtv should depend on PCI + * rpadlpar breakage - fallout of struct subsystem removal + * m32r: __xchg() should be always_inline + * audit_match_signal() and friends are used only if CONFIG_AUDITSYSCALL + is set + * fix uml-x86_64 + * arm: walk_stacktrace() needs to be exported + + -- Ben Collins Tue, 15 May 2007 10:13:23 -0400 + +linux-source-2.6.22 (2.6.22-3.9) gutsy; urgency=low + + * Fixup firmware-modules -> efi-modules in exclude files. + + [Ben Collins] + + * build/config: Enable CONFIG_TIMER_STATS + * build/config: Disable CONFIG_IRQBALANCE, handled in userspace now + * build: Update modules that have been deprecated + * sparc64: Get some drivers compiling, till patches get upstream. + * powerpc: Add 64-bit cmp op for 32-bit. + * build/config: Disable apm_emu, pasemi_mac and cbe_cpufreq on ppc64 + * build/d-i(cjwatson): Rename firmware-modules to efi-modules + + -- Ben Collins Fri, 11 May 2007 09:38:50 +0200 + +linux-source-2.6.22 (2.6.22-2.7) gutsy; urgency=low + + [Changes for 2.7] + + * Added some more modules going missing to ignore. + * Disable ADB_PMU_LED on powerpc64. FTBFS. + + [Ben Collins] + + * XXX: Well, xen and rt got disabled in this upload. Hopefully things will + get working again soon. + + * build: Add check for nrcpus on buildd's for CONCURRENCY_LEVEL + * build: No longer provide ndiswrapper or ivtv modules (l-u-m does). + * build/d-i: Remove firmware lists, since we no longer supply those udebs + * build: Remove more firmware stuff + * build/control: Build-dep on coreutils + * Update configuration files + * build/custom: Updated xen/rt patches and configs. + * build: Make sure to use /bin/bash for headers_install + * build: Add SHELL=/bin/bash to headers_install + * Update configuration files + * Bump ABI + * Update module lists to match module name changes and merges. + * build/rt: Trimmed down real-time patch from Alessio Igor Bogani. + * Update configuration files + * Update configuration files + * build/rt: Fix typo in diff + * Update configuration files + * build: make explicit binary-headers target + * Update configuration files + * build/control-scripts: Remove debconf from pre-rm script + * build/ia64: Compress and use vmlinuz for target install + * build/config: Diable OSS i810_audio driver (Alsa driver prefered) + * build/config: Disable OSS cs4232 driver (Alsa prefered) + * build/config: Disable OSS via82xx driver (Alsa prefered) + * build/config: Disable OSS trident driver (Alsa prefered) + * build/config: Disable OSS Sound Blaster driver (Alsa prefered) + * build/config: Disable IDE generic, ata_generic prefered + * build/config: Disable siimage, pata_sil680 prefered + * build/module-check: More robust module checking + * build: Call module-check with perl, not $SHELL + * Update configuration files + * build: Fixup calling conventions of module-check + * build: Add modules.ignore from 1.3 revision + * build/config: Disable obsolete MOXA_SMARTIO in favor of new driver. + * build/config: Disable orinoco_cs in favor of hostap_cs + * build/config: Disable orinoco_pci in favor of hostap_pci + * build/config: Disable orinoco_{plx,tmd} in favor of hostap_plx + * build/config: Disable sk98lin in favor of skge + * build: Add more modules intentionally removed since 1.3 + + -- Ben Collins Fri, 27 Apr 2007 09:04:29 -0400 + +linux-source-2.6.22 (2.6.22-1.3) gutsy; urgency=low + + [Ben Collins] + + * build: Only use bzip2 for linux-image, and pre-depend on proper dpkg + + [2.6.22-1.2] + + [Ben Collins] + + * build: Add build-arch target. FTBFS + + [2.6.22-1.1] + + [Ben Collins] + + * debian: New build system, from scratch + * debian: Rename place holder so debian/stamps/ sticks around + * debian: Create stamp-flavours at start of build (for build scripts) + * debian/abi: Add revision 0.0 bootstrap module list. + * debian: Fix backwards logic in module/abi checkers. + * debian: Add arch= to vars.* files + * Update configuration files + * build: Added control scripts for images + * build/config: Disable CONFIG_PARAVIRT for now + * build/config: Enable CONFIG_FB_VESA + * build: Take CONCURRENCY_LEVEL from env if it exists. + * build: Do not print SHAs by default for changelog + * build/config(i386): Disable NO_HZ on all but generic + * build: Implement udeb rules + * build/d-i: Remove speakup-modules udeb + * build/udebs: Fix a couple trivial errors in the build. + * build/config: Disable CONFIG_FB_IMSTT on powerpc64-smp (no NVRAM) + * build/config: Disable some modules for ppc64 that don't use DMA API + * build/config: Yet another module to disable on ppc64 + * build/tests: New test infrastructure + * build: Special kernel build infrastructure + * build: Fix typo from last commit + * build/custom: Move custom files for each flavour into subdir. + * build/config: Disable some drivers on sparc that don't support DMA API + * build/sparc: Add new compress_file config, and use it for sparc + * build: Fix typo in compress_file commit. + * build/schedcfs: Update to v6 of the patch. + * build: Fix control file generation for custom images + * build: Correct message in link-headers + * build: 2.6.21 is released, force our SUBLEVEL to .22 + * build/vars: kvm API is at 4, provide that. + * build/custom: Allow custom builds to override things like build_image + * build/custom: Fix type causing custom rules not to be included. + * build/custom: Hello Xen 3.0.5 + * build/custom: Remove sched-cfs. Superseded in use by rt. + * build/custom: Add 2.6.21-rt1 patch for -rt custom flavour + * build/link-headers: Make sure to copy new files for custom + + -- Ben Collins Fri, 27 Apr 2007 08:29:00 -0400 --- linux-2.6.27.orig/debian/control +++ linux-2.6.27/debian/control @@ -0,0 +1,420 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.6.1 +Build-Depends: debhelper (>= 3), module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [!armel] +Build-Depends-Indep: xmlto, docbook-utils, gs, transfig, bzip2, sharutils +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-intrepid + +Package: linux-source-2.6.27 +Architecture: all +Section: devel +Priority: optional +Provides: linux-source, linux-source-2.6 +Depends: binutils, bzip2, coreutils | fileutils (>= 4.0) +Recommends: libc-dev, gcc, make +Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev +Description: Linux kernel source for version 2.6.27 with Ubuntu patches + This package provides the source code for the Linux kernel version + 2.6.27. + . + This package is mainly meant for other packages to use, in order to build + custom flavours. + . + If you wish to use this package to create a custom Linux kernel, then it + is suggested that you investigate the package kernel-package, which has + been designed to ease the task of creating kernel image packages. + . + If you are simply trying to build third-party modules for your kernel, + you do not want this package. Install the appropriate linux-headers + package instead. + +Package: linux-doc-2.6.27 +Architecture: all +Section: doc +Priority: optional +Provides: linux-doc-2.6 +Conflicts: linux-doc-2.6 +Replaces: linux-doc-2.6 +Depends: coreutils | fileutils (>= 4.0) +Description: Linux kernel specific documentation for version 2.6.27 + This package provides the various readme's in the 2.6.27 kernel + Documentation/ subdirectory: these typically contain kernel-specific + installation notes for some drivers for example. See + /usr/share/doc/linux-doc-2.6.27/Documentation/00-INDEX for a list of what + is contained in each file. Please read the Changes file, as it contains + information about the problems, which may result by upgrading your + kernel. + +Package: linux-headers-2.6.27-9 +Architecture: all +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0) +Provides: linux-headers, linux-headers-2.6 +Description: Header files related to Linux kernel version 2.6.27 + This package provides kernel header files for version 2.6.27, for sites + that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details + +Package: linux-libc-dev +Architecture: i386 amd64 armel +Conflicts: libc6-dev (<< 2.3.2.ds1-6), libc6.1-dev (<< 2.3.2.ds1-6), dvb-dev (<< 1.0.1-6), amd64-libs-dev (<= 1.1), linux-kernel-headers +Replaces: libc6-dev (<< 2.3.2.ds1-6), libc6.1-dev (<< 2.3.2.ds1-6), dvb-dev (<< 1.0.1-6), linux-kernel-headers +Provides: linux-kernel-headers +Description: Linux Kernel Headers for development + This package provides headers from the Linux kernel. These headers + are used by the installed headers for GNU glibc and other system + libraries. They are NOT meant to be used to build third-party modules for + your kernel. Use linux-headers-* packages for that. + +Package: linux-image-2.6.27-9-generic +Architecture: i386 amd64 +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: lilo (>= 19.1) | grub +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.27 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward desktop systems. + . + You likely do not want to install this package directly. Instead, install + the linux-generic meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on x86/x86_64 + This package provides kernel header files for version 2.6.27 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on x86/x86_64 + This package provides a kernel debug image for version 2.6.27 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-iop32x +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on IOP32x-based systems + This package contains the Linux kernel image for version 2.6.27 on + IOP32x-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports IOP32x processors. + . + Thecus N2100, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-iop32x meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-iop32x +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on IOP32x-based systems + This package provides kernel header files for version 2.6.27 on + IOP32x-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-iop32x +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on IOP32x-based systems + This package provides a kernel debug image for version 2.6.27 on + IOP32x-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-ixp4xx +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on IXP4xx-based systems + This package contains the Linux kernel image for version 2.6.27 on + IXP4xx-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports IXP4xx processors. + . + Linksys NSLU2, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-ixp4xx meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-ixp4xx +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on IXP4xx-based systems + This package provides kernel header files for version 2.6.27 on + IXP4xx-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-ixp4xx +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on IXP4xx-based systems + This package provides a kernel debug image for version 2.6.27 on + IXP4xx-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-orion5x +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on Orion5x-based systems + This package contains the Linux kernel image for version 2.6.27 on + Orion5x-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Orion 5181, 5182 and 5281 processors. + . + QNAP TS-109/TS-209, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-orion5x meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-orion5x +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on Orion5x-based systems + This package provides kernel header files for version 2.6.27 on + Orion5x-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-orion5x +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on Orion5x-based systems + This package provides a kernel debug image for version 2.6.27 on + Orion5x-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-server +Architecture: i386 amd64 +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9 +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: lilo (>= 19.1) | grub +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.27 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Server processors. + . + Geared toward server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-server meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-server +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on x86/x86_64 + This package provides kernel header files for version 2.6.27 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-server +Architecture: i386 amd64 +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on x86/x86_64 + This package provides a kernel debug image for version 2.6.27 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-versatile +Architecture: armel +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on Versatile-based systems + This package contains the Linux kernel image for version 2.6.27 on + Versatile-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Versatile processors. + . + PB, AB, Qemu, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-versatile meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.27-9-versatile +Architecture: armel +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-2.6.27-9, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.27 on Versatile-based systems + This package provides kernel header files for version 2.6.27 on + Versatile-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.27-9/debian.README.gz for details. + +Package: linux-image-debug-2.6.27-9-versatile +Architecture: armel +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.27 on Versatile-based systems + This package provides a kernel debug image for version 2.6.27 on + Versatile-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.27-9-virtual +Architecture: i386 amd64 +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1), linux-image-2.6.27-9-server +Recommends: lilo (>= 19.1) | grub +Suggests: fdutils, linux-doc-2.6.27 | linux-source-2.6.27 +Description: Linux kernel image for version 2.6.27 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.27 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Virtual processors. + . + Geared toward virtual machine guests. + . + You likely do not want to install this package directly. Instead, install + the linux-virtual meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. --- linux-2.6.27.orig/debian/control-scripts/prerm +++ linux-2.6.27/debian/control-scripts/prerm @@ -0,0 +1,294 @@ +#! /usr/bin/perl +# -*- Mode: Perl -*- +# image.prerm --- +# Author : root ( root@melkor.pilgrim.umass.edu ) +# Created On : Fri May 17 03:28:59 1996 +# Created On Node : melkor.pilgrim.umass.edu +# Last Modified By : Manoj Srivastava +# Last Modified On : Sat Aug 5 13:14:17 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 85 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# +# $Id: image.prerm,v 1.22 2003/10/07 16:24:20 srivasta Exp $ +# +# +#use strict; + +$|=1; +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlinks = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, or nettrom +my $image_dir = "/boot"; # where the image is located +my $clobber_modules = ''; # target machine defined +my $initrd = "YES"; # initrd kernel +my $use_hard_links = ''; # hardlinks do not wirk across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $relink_build_link = 'YES'; # There is no harm in checking the link +my $force_build_link = ''; # There is no harm in checking the link +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; +my $package_name = "linux-image-$version"; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; + + +# This should not point to /tmp, because of security risks. +my $temp_file_name = "/var/log/$loader" . "_log.$$"; + +#known variables +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $CONF_LOC = '/etc/kernel-img.conf'; +my $relative_links = ''; +my $silent_loader = ''; +my $warn_reboot = 'Yes'; # Warn that we are installing a version of + # the kernel we are running + +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + +my $DEBUG = 0; + +# Variables used +my $image=''; +my $ret=0; +my $seen=''; +my $answer=''; +my $running = ''; +my $WouldInvalidate = 0; + +if ($ARGV[0] && ($ARGV[0] =~ /remove/ || $ARGV[0] =~ /upgrade/)) { + if (-l "/usr/doc/linux-image-$version") { + unlink "/usr/doc/linux-image-$version"; + } +} + +# Ignore all invocations uxcept when called on to remove +exit 0 unless ($ARGV[0] && $ARGV[0] =~ /remove/) ; + +# Paranoid check to make sure that the correct value is put in there +if (! $kimage) { $kimage = "vmlinuz";} # Hmm. empty +elsif ($kimage =~ m/^b?zImage$/o) { $kimage = "vmlinuz";} # these produce vmlinuz +elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage; } +elsif ($kimage =~ m/^vmlinux$/o) { my $nop = $kimage; } +else { $kimage = "vmlinuz";} # Default + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $do_initrd = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig; + $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig; + + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $do_initrd = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig; + $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + } +} + + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + +#check to see if we are trying to remove a running kernel +# if so we abort right now. +chop($running=`uname -r`); +if ($running eq $version) { + print STDERR "WARN: Proceeding with removing running kernel image.\n"; +} + +#Now, they have an alternate kernel which they are currently running + +# This is just us being nice to lilo users. + +chdir("/") or die "could not chdir to /:$!\n"; + +if (-f "/etc/$loader.conf") { #I know, could be a link, but .. + open (LILO, "/etc/$loader.conf") || &success(); # this is not critical + while () { + chop; + s/\#.*//; # nix the comments + next unless /^\s*image\s*=\s(\S+)/o; + $image = $1; + if ($image && -e $image) { + while (defined($image) && -l $image) { + $image = readlink ($image); + } + if (defined($image) && -e $image) { + $WouldInvalidate |= $image =~ /$kimage-$version/; + } + else { + &success(); # invalid $loader.conf file + } + } + else { + &success(); # invalid $loader.conf file + } + } + close (LILO); + if ($WouldInvalidate) { + print STFERR "WARN: Proceeding with removing running kernel image.\n"; + &success(); + } +} + + +# set the env var stem +$ENV{'STEM'} = "linux"; + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + + +## Run user hook script here, if any +if (-x "$prerm_hook") { + &run_hook("prerm", $prerm_hook); +} +if (-d "/etc/kernel/prerm.d") { + print STDERR "Examining /etc/kernel/prerm.d.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version /etc/kernel/prerm.d") && + die "Failed to process /etc/kernel/prerm.d"; +} +if (-d "/etc/kernel/prerm.d/$version") { + print STDERR "Examining /etc/kernel/prerm.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version" . + " --arg=$realimageloc$kimage-$version " . + "/etc/kernel/prerm.d/$version") && + die "Failed to process /etc/kernel/prerm.d/$version"; +} + +sub success () { + -f "/lib/modules/$version/modules.dep" && + unlink "/lib/modules/$version/modules.dep"; + exit 0; +} + + + +&success(); +exit 0; +__END__ + + + + + --- linux-2.6.27.orig/debian/control-scripts/postinst +++ linux-2.6.27/debian/control-scripts/postinst @@ -0,0 +1,1087 @@ +#! /usr/bin/perl +# OriginalAuthor : Manoj Srivastava ( srivasta@pilgrim.umass.edu ) +# +# Customized for Ubuntu by: Ben Collins + +#use strict; #for debugging +use Cwd 'abs_path'; + +$|=1; + +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlink = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, nettrom, arcboot or delo +my $image_dir = "/boot"; # where the image is located +my $clobber_modules = ''; # target machine defined +my $relative_links = ""; # target machine defined +my $initrd = "YES"; # initrd kernel +my $do_initrd = ''; # Normally we do not +my $use_hard_links = ''; # hardlinks do not work across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; # List of tools to create initial ram fs. +my $notifier = "/usr/share/update-notifier/notify-reboot-required"; +my $package_name = "linux-image-$version"; +my $explicit_do_loader = 'Yes'; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; +$Loader = "ARCBOOT" if $loader =~ /^arcboot/io; +$Loader = "DELO" if $loader =~ /^delo/io; + +# This should not point to /tmp, because of security risks. +my $temp_file_name = "/var/log/$loader" . "_log.$$"; + +#known variables +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $silent_modules = ''; +my $silent_loader = ''; +my $warn_reboot = 'Yes'; # Warn that we are installing a version of + # the kernel we are running + +my $modules_base = '/lib/modules'; +my $CONF_LOC = '/etc/kernel-img.conf'; + +# Ignore all invocations except when called on to configure. +exit 0 unless $ARGV[0] =~ /configure/; + +my $DEBUG = 0; + +# Do some preliminary sanity checks here to ensure we actually have an +# valid image dir +chdir('/') or die "could not chdir to /:$!\n"; +die "Internal Error: ($image_dir) is not a directory!\n" + unless -d $image_dir; + +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; +die "Internal Error: ($realimageloc) is not a directory!\n" + unless -d $realimageloc; + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlink\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $explicit_do_loader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $do_initrd = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_modules = '' if /^\s*silent_modules\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $explicit_do_loader = "YES" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $do_initrd = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_modules = 'Yes' if /^\s*silent_modules\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + } +} + + + +# For some versions of kernel-package, we had this warning in the +# postinst, but the rules did not really interpolate the value in. +# Here is a sanity check. +my $pattern = "=" . "I"; +$initrd=~ s/^$pattern$//; + +if ($link_in_boot) { + $image_dest = "/$image_dir/"; # same as realimageloc +} + +# Tack on at least one trainling / +$image_dest = "$image_dest/"; +$image_dest =~ s|^/*|/|o; +$image_dest =~ s|/+$|/|o; + +if (! -d "$image_dest") { + die "Expected Image Destination dir ($image_dest) to be a valid directory!\n"; +} + +# sanity +if (!($do_bootfloppy || $do_bootloader)) { + $do_boot_enable = ''; +} +if ($do_symlink && $no_symlink) { + warn "Both do_symlinks and no_symlinks options enabled; disabling no_symlinks\n"; + $no_symlink = 0; +} + +# most of our work is done in $image_dest (nominally /) +chdir("$image_dest") or die "could not chdir to $image_dest:$!\n"; + +# Paranoid check to make sure that the correct value is put in there +if (! $kimage) { $kimage = "vmlinuz"; } # Hmm. empty +elsif ($kimage =~ m/^b?zImage$/o) { $kimage = "vmlinuz"; } # these produce vmlinuz +elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage; } +elsif ($kimage =~ m/^vmlinux$/o) { my $nop = $kimage; } +else { $kimage = "vmlinuz"; } # Default + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + + +die "Internal Error: Could not find image (" . $realimageloc + . "$kimage-$version)\n" unless -e $realimageloc + . "$kimage-$version"; + +# search for the boot loader in the path +my $loader_exec; +($loader_exec = $loader) =~ s|.*/||; +my ($loaderloc) = grep -x, map "$_/$loader_exec", + map { length($_) ? $_ : "." } split /:/, $ENV{PATH}; + + +###################################################################### +###################################################################### +########### Test whether a relative symlinkwould be OK ####### +###################################################################### +###################################################################### +sub test_relative { + my %params = @_; + my $cwd; + + die "Internal Error: Missing Required paramater 'Old Dir' " + unless $params{'Old Dir'}; + die "Internal Error: Missing Required paramater New Dir' " + unless $params{'New Dir'}; + + + die "Internal Error: No such dir $params{'Old Dir'} " + unless -d $params{'Old Dir'}; + die "Internal Error: No such dir $params{'New Dir'} " + unless -d $params{'New Dir'}; + + warn "Test relative: testing $params{'Old Dir'} -> $params{'New Dir'}" + if $DEBUG; + chomp($cwd = `pwd`); + chdir ($params{'New Dir'}) or die "Could not chdir to $params{'New Dir'}:$!"; + my $ok = 0; + $params{'Old Dir'} =~ s|^/*||o; + if (-d $params{'Old Dir'} ) { + if (defined $params{'Test File'}) { + if (-e $params{'Old Dir'} . $params{'Test File'}) { + $ok = 1; + } + } else { + $ok = 1; # well, backward compatibility + } + } + chdir ($cwd) or die "Could not chdir to $params{'New Dir'}:$!"; + return $ok; +} + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +# sub CanonicalizePath { +# my $path = join '/', @_; +# my @work = split '/', $path; +# my @out; +# my $is_absolute; + +# if (@work && $work[0] eq "") { +# $is_absolute = 1; shift @work; +# } + +# while (@work) { +# my $seg = shift @work; +# if ($seg eq "." || $seg eq "") { +# } +# elsif ($seg eq "..") { +# if (@out && $out[-1] ne "..") { +# pop @out; +# } +# else { +# # Leading "..", or "../..", etc. +# push @out, $seg; +# } +# } +# else { +# push @out, $seg; +# } +# } + +# unshift @out, "" if $is_absolute; +# return join('/', @out); +# } +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### + +sub spath { + my %params = @_; + + die "Missing Required paramater 'Old'" unless $params{'Old'}; + die "Missing Required paramater 'New'" unless $params{'New'}; + + my @olddir = split '/', `readlink -q -m $params{'Old'}`; + my @newdir = split '/', `readlink -q -m $params{'New'}`; + my @outdir = @olddir; + + my $out = ''; + my $i; + for ($i = 0; $i <= $#olddir && $i <= $#newdir; $i++) { + $out++ if ($olddir[$i] ne $newdir[$i]); + shift @outdir unless $out; + unshift @outdir, ".." if $out; + } + if ($#newdir > $#olddir) { + for ($i=0; $i < $#newdir; $i++) { + unshift @outdir, ".."; + } + } + return join ('/', @outdir); +} +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### + + +# This routine actually moves the kernel image +# From: $realimageloc/$kimage-$version (/boot/vmlinuz-2.6.12) +# To: $image_dest/$kimage-$version (/vmlinuz-2.6.12) +# Note that the image is moved to a versioned destination, but ordinary +# symlinks we create otherwise are not normally versioned +sub really_move_image { + my $src_dir = $_[0]; + my $target = $_[1]; + my $dest_dir = $_[2]; + + warn "Really move image: src_dir=$src_dir, target=$target,\n destdir=$dest_dir" + if $DEBUG; + if (-e "$target") { + # we should be in dir $dest_dir == $image_dest /, normally + rename("$target", "$target.$$") || + die "failed to move " . $dest_dir . "$target:$!"; + warn "mv $target $target.$$" if $DEBUG; + } + warn "mv -f $src_dir$target $target" if $DEBUG; + my $ret = system("mv -f " . $src_dir . "$target " . + " $target"); + if ($ret) { + die("Failed to move " . $src_dir . "$target to " + . $dest_dir . "$target.\n"); + } + # Ok, now we may clobber the previous .old files + if (-e "$target.$$") { + rename("$target.$$", "$target.old") || + die "failed to move " . $dest_dir . "$target:$!"; + warn "mv $target.$$ $target " if $DEBUG; + } +} + +# Normally called after really_move_image; and only called if we asked for +# reversed link this routine reverses the symbolic link that is notmally +# created. Since the real kernel image has been moved over to +# $image_dest/$kimage-$version. So, this routine links +# From: $image_dest/$kimage-$version (/vmlinuz-2.6.12) +# To: $realimageloc/$kimage-$version (/boot/vmlinuz-2.6.12) +sub really_reverse_link { + my $src_dir = $_[0]; + my $link_name = $_[1]; + my $dest_dir = $_[2]; + warn "Really reverse link: src_dir=$src_dir, link name=$link_name\n" . + "\tdestdir=$dest_dir" if $DEBUG; + + my $Old = $dest_dir; + if (test_relative ('Old Dir' => $Old, 'New Dir' => $src_dir, + 'Test File' => "$link_name")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$src_dir" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + if ($use_hard_links =~ m/YES/i) { + link($Old . "$link_name", $src_dir . "$link_name") || + die("Failed to symbolic-link " . $dest_dir . "$link_name to " . $src_dir + . "$link_name .\n"); + warn "ln " . $Old . "$link_name " . $src_dir . "$link_name" if $DEBUG; + } + else { + symlink($Old . "$link_name", $src_dir . "$link_name") || + die("Failed to link " . $dest_dir . "$link_name to " . $src_dir . + "$link_name .\n"); + warn "ln -s " . $Old . "$link_name " . $src_dir . "$link_name" if $DEBUG; + } +} + +# This routine is invoked if there is a symbolic link in place +# in $image_dest/$kimage -- so a symlink exists in the destination. +# What we are trying to determine is if we need to move the symbolic link over +# to the the .old location +sub move_p { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + my $force_move = 0; + warn "Move?: kimage=$kimage, image_dest=$image_dest, \n" . + "\timage_name=$image_name, src_dir=$src_dir" if $DEBUG; + + if ($no_symlink || $reverse_symlink) { + # we do not want links, yet we have a symbolic link here! + warn "found a symbolic link in " . $image_dest . "$kimage \n" . + "even though no_symlink is defined\n" if $no_symlink; + warn "found a symbolic link in " . $image_dest . "$kimage \n" . + "even though reverse_symlink is defined\n" if $reverse_symlink; + # make sure we change this state of affairs + $force_move = 1; + return $force_move; + } + + warn "DEBUG: OK. We found symlink, and we should have a symlink here.\n" + if $DEBUG; + my $vmlinuz_target = readlink "$kimage"; + my $real_target = ''; + my $target = `readlink -q -m "${realimageloc}${kimage-$version}"`; + $real_target = abs_path($vmlinuz_target) if defined($vmlinuz_target); + + if (!defined($vmlinuz_target) || ! -f "$real_target") { + # what, a dangling symlink? + warn "The link " . $image_dest . "$kimage is a dangling link" . + "to $real_target\n"; + $force_move = 1; + return $force_move; + } + + + warn "DEBUG: The link $kimage points to ($vmlinuz_target)\n" if $DEBUG; + warn "DEBUG: ($vmlinuz_target) is really ($real_target)\n" if $DEBUG; + my $cwd; + chomp ($cwd=`pwd`); + if ($vmlinuz_target !~ m|^/|o) { + $vmlinuz_target = $cwd . "/" . $vmlinuz_target; + $vmlinuz_target =~ s|/+|/|o; + } + $vmlinuz_target = `readlink -q -m $vmlinuz_target`; + + if ("$vmlinuz_target" ne "$target") { + warn "DEBUG: We need to handle this.\n" if $DEBUG; + if ($minimal_swap) { + warn "DEBUG: Minimal swap.\n" if $DEBUG; + if (-l "$kimage.old") { + warn "DEBUG: There is an old link at $kimage.old\n" if $DEBUG; + my $old_target = readlink "$kimage.old"; + my $real_old_target = ''; + $real_old_target=abs_path($old_target) if defined ($old_target); + + if ($real_old_target && -f "$real_old_target") { + if ($old_target !~ m|^/|o) { + $old_target = $cwd . "/" . $old_target; + $old_target =~ s|/+|/|o; + } + $old_target = `readlink -q -m $old_target`; + if ("$old_target" ne "$target") { + $force_move = 1; + warn "DEBUG: Old link ($old_target) does not point to us ($target)\n" + if $DEBUG; + } + else { # The .old points to the current + warn "$kimage.old --> $target -- doing nothing"; + $force_move = 0; + } + } + else { + warn "DEBUG: Well, the old link does not exist -- so we move\n" + if $DEBUG; + $force_move = 1; + } + } + else { + warn "DEBUG: No .old link -- OK to move\n" + if $DEBUG; + $force_move = 1; + } + } + else { + warn "DEBUG: ok, minimal swap is no-- so we move.\n" + if $DEBUG; + $force_move = 1; + } + } + else { # already have proper link + warn "$kimage($vmlinuz_target) points to $target ($real_target) -- doing nothing"; + $force_move = 0; + } + return $force_move; +} + + +# This routine moves the symbolic link around (/vmlinuz -> /vmlinuz.old) +# It pays attention to whether we should the fact whether we should be using +# hard links or not. +sub really_move_link { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + warn "really_move_link: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + # don't clobber $kimage.old quite yet + rename("$kimage", "$kimage.$$") || + die "failed to move " . $image_dest . "$kimage:$!"; + warn "mv $kimage $kimage.$$" if $DEBUG; + my $Old = $src_dir; + my $cwd; + + chomp($cwd=`pwd`); + if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd, + 'Test File' => "$image_name")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + if ($use_hard_links =~ m/YES/i) { + warn "ln ${Old}${image_name} $kimage" if $DEBUG; + if (! link("${Old}${image_name}", "$kimage")) { + rename("$kimage.$$", "$kimage"); + die("Failed to link ${Old}${image_name} to " . + "${image_dest}${kimage}.\n"); + } + } + else { + warn "ln -s ${Old}${image_name} $kimage" if $DEBUG; + if (! symlink("${Old}${image_name}", "$kimage")) { + rename("$kimage.$$", "$kimage"); + die("Failed to symbolic-link ${Old}${image_name} to " . + "${image_dest}${kimage}.\n"); + } + } + + # Ok, now we may clobber the previous .old file + if (-l "$kimage.old" || ! -e "$kimage.old" ) { + rename("$kimage.$$", "$kimage.old"); + warn "mv $kimage.$$ $kimage.old" if $DEBUG; + } + else { + warn "$kimage.old is not a symlink, not clobbering\n"; + warn "rm $kimage.$$"; + unlink "$kimage.$$" if $DEBUG; + } +} + +# This routine handles a request to do symlinks, but there is no +# symlink file already there. Either we are supposed to use copy, or we are +# installing on a pristine system, or the user does not want symbolic links at +# all. We use a configuration file to tell the last two cases apart, creating +# a config file if needed. +sub handle_missing_link { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + warn "handle_missing_link: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + if ($no_symlink) { + warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("cp -a --backup=t " . $realimageloc . + "$image_name " . " $kimage"); + if ($ret) { + die("Failed to copy " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + elsif ($reverse_symlink) { + warn "mv -f $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("mv -f " . $realimageloc . "$image_name " + . "$kimage"); + if ($ret) { + die("Failed to move " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + else { + if (! $have_conffile) { + my $ret; + my $answer=''; + $do_symlink = "Yes"; + + if (open(CONF, ">$CONF_LOC")) { + print CONF "# Kernel Image management overrides\n"; + print CONF "# See kernel-img.conf(5) for details\n"; + if ($loader =~ /palo/i) { + print CONF "link_in_boot = Yes\n"; + print CONF "do_symlinks = Yes\n"; + print CONF "relative_links = Yes\n"; + print CONF "do_bootloader = No\n"; + } else { + print CONF "do_symlinks = $do_symlink\n"; + } + close CONF; + } + $have_conffile = "Yes"; + } + } + + if (! $no_symlink && $do_symlink =~ /Yes/i) { + my $Old = $realimageloc; + my $New = $image_dest; + my $Name = "$image_name"; + my $Link_Dest = "$kimage"; + + if ($reverse_symlink) { + $Old = $image_dest; + $New = $realimageloc; + $Name = "$kimage"; + $Link_Dest = $realimageloc . "$image_name"; + } + if (test_relative ('Old Dir' => $Old, + 'New Dir' => $New, + 'Test File' => $Name)) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$New" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + symlink($Old . "$Name", "$Link_Dest") || + die("Failed to symbolic-link ${Old}$Name to $Link_Dest.\n"); + warn "ln -s ${Old}$Name $Link_Dest" if $DEBUG; + + } +} + +# This routine handles the rest of the cases, where the user has requested +# non-traditional handling, like using cp, or reverse symlinks, or hard links. +sub handle_non_symlinks { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + warn "handle_non_link: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + # Save the current image. We do this in all four cases + rename("$kimage", "$kimage.$$") || + die "failed to move " . $image_dest . "$kimage:$!"; + warn "mv $kimage $kimage.$$" if $DEBUG; + + ##,#### + # case One + #`#### + if ($no_symlink) { + # Maybe /$image_dest is on a dos system? + warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("cp -a --backup=t " . $realimageloc + . "$image_name " . "$kimage"); + if ($ret) { + if (-e "$kimage.$$") { + rename("$kimage.$$", "$kimage"); + warn "mv $kimage.$$ $kimage" if $DEBUG; + } + die("Failed to copy " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + ##,#### + # case Two + #`#### + elsif ($reverse_symlink) { # Maybe /$image_dest is on a dos system? + warn "mv -f $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("mv -f " . $realimageloc . "$image_name " + . $image_dest . "$kimage"); + if ($ret) { + if (-e "$kimage.$$") { + rename("$kimage.$$", "$kimage"); + warn "mv $kimage.$$ $kimage" if $DEBUG; + } + die("Failed to move " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + my $Old = $image_dest; + if (test_relative ('Old Dir' => $Old, 'New Dir' => $realimageloc, + 'Test File' => "$kimage")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$realimageloc" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + if ($use_hard_links =~ m/YES/i) { + warn "ln " . $Old . "$kimage " . $realimageloc . "$image_name" if $DEBUG; + if (! link($Old . "$kimage", $realimageloc . "$image_name")) { + warn "Could not link " . $image_dest . + "$kimage to $image_name :$!"; + } + } + else { + warn "ln -s " . $Old . "$kimage " . $realimageloc . "$image_name" if $DEBUG; + if (! symlink($Old . "$kimage", $realimageloc . "$image_name")) { + warn "Could not symlink " . $image_dest . + "$kimage to $image_name :$!"; + } + } + } + ##,#### + # case Three + #`#### + elsif ($use_hard_links =~ m/YES/i ) { + # Ok then. this ought to be a hard link, and hence fair game + # don't clobber $kimage.old quite yet + my $Old = $realimageloc; + my $cwd; + chomp($cwd=`pwd`); + if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd, + 'Test File' => "$image_name")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + warn "ln " . $Old . "$image_name " . "$kimage" if $DEBUG; + if (! link($Old . "$image_name", "$kimage")) { + warn "mv $kimage.$$ $kimage" if $DEBUG; + rename("$kimage.$$", "$kimage"); + die("Failed to link " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + ##,#### + # case Four + #`#### + else { + # We just use cp + warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("cp -a --backup=t " . $realimageloc + . "$image_name " . "$kimage"); + if ($ret) { + if (-e "$kimage.$$") { + warn "mv $kimage.$$ $kimage" if $DEBUG; + rename("$kimage.$$", "$kimage"); + } + die("Failed to copy " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + # Ok, now we may clobber the previous .old file + warn "mv $kimage.$$ $kimage.old if -e $kimage.$$" if $DEBUG; + rename("$kimage.$$", "$kimage.old") if -e "$kimage.$$"; +} + +# This routine is responsible for setting up the symbolic links +# So, the actual kernel image lives in +# $realimageloc/$image_name (/boot/vmlinuz-2.6.12). +# This routine creates symbolic links in $image_dest/$kimage (/vmlinuz) +sub image_magic { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = "$kimage-$version"; + my $src_dir = $realimageloc; + warn "image_magic: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + # Well, in any case, if the destination (the symlink we are trying + # to create) is a directory, we should do nothing, except throw a + # diagnostic. + if (-d "$kimage" ) { + die ("Hmm. $kimage is a directory, which I did not expect. I am\n" . + "trying to create a symbolic link with that name linked to \n" . + "$image_dest . Since a directory exists here, my assumptions \n" . + "are way off, and I am aborting.\n" ); + exit (3); + } + + if ($move_image) { # Maybe $image_dest is in on dos, or something? + # source dir, link name, dest dir + really_move_image( $realimageloc, $image_name, $image_dest); + really_reverse_link($realimageloc, $image_name, $image_dest) + if $reverse_symlink; + return; + } + + if (-l "$kimage") { # There is a symbolic link + warn "DEBUG: There is a symlink for $kimage\n" if $DEBUG; + my $force_move = move_p($kimage, $image_dest, $image_name, $src_dir); + + if ($force_move) { + really_move_link($kimage, $image_dest, $image_name, $src_dir); + } + } + elsif (! -e "$kimage") { + # Hmm. Pristine system? How can that be? Installing from scratch? + # Or maybe the user does not want a symbolic link here. + # Possibly they do not want a link here. (we should be in / + # here[$image_dest, really] + handle_missing_link($kimage, $image_dest, $image_name, $src_dir); + } + elsif (-e "$kimage" ) { + # OK, $kimage exists -- but is not a link + handle_non_symlinks($kimage, $image_dest, $image_name, $src_dir); + } +} + +###################################################################### +###################################################################### +###################################################################### +###################################################################### + +# We may not have any modules installed +if ( -d "$modules_base/$version" ) { + print STDERR "Running depmod.\n"; + my $ret = system("depmod -a $version"); + if ($ret) { + print STDERR "Failed to run depmod\n"; + exit(1); + } +} + + + +sub find_initrd_tool { + my $hostversion = shift; + my $version = shift; + print STDERR "Finding valid ramdisk creators.\n"; + my @ramdisks = + grep { + my $args = + "$_ " . + "--supported-host-version=$hostversion " . + "--supported-target-version=$version " . + "1>/dev/null 2>&1" + ; + system($args) == 0; + } + split (/[:,\s]+/, $ramdisk); +} + +# The initrd symlink should probably be in the same dir that the +# symlinks are in +if ($initrd) { + my $success = 0; + + # Update-initramfs is called slightly different than mkinitrd and + # mkinitramfs. XXX It should really be made compatible with this stuff + # some how. + my $upgrading = 1; + if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m//og) { + $upgrading = 0; + } + my $ret = system("$ramdisk " . ($upgrading ? "-u" : "-c") . " -k " . $version . " >&2"); + $success = 1 unless $ret; + die "Failed to create initrd image.\n" unless $success; + if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m//og) { + image_magic("initrd.img", $image_dest); + } + else { + if (! -e "initrd.img") { + handle_missing_link("initrd.img", $image_dest, "initrd.img-$version", + $realimageloc); + } + else { + print STDERR + "Not updating initrd symbolic links since we are being updated/reinstalled \n"; + print STDERR + "($ARGV[1] was configured last, according to dpkg)\n"; + } + } + + if ($initrd && -l "initrd" ) { + unlink "initrd"; + } + + if ($initrd && -l "$image_dir/initrd" && ! $link_in_boot) { + unlink "$image_dir/initrd"; + } +} +else { # Not making an initrd emage + if (-l "initrd.img") { + # Ooh, last image was an initrd image? in any case, we should move it. + my $target = readlink "initrd.img"; + my $real_target = ''; + $real_target = abs_path($target) if defined ($target); + + if (!defined($target) || ! -f "$real_target") { + # Eh. dangling link. can safely be removed. + unlink("initrd.img"); + } else { + if (-l "initrd.img.old" || ! -e "initrd.img.old" ) { + rename("initrd.img", "initrd.img.old"); + } else { + warn "initrd.img.old is not a symlink, not clobbering\n"; + unlink("initrd.img"); + } + } + } +} + +# Warn of a reboot +if (-x $notifier) { + system($notifier); +} + +# Let programs know not to hibernate if the kernel that would be used for +# resume-from-hibernate is likely to differ from the currently running kernel. +system("mountpoint -q /var/run"); +if ($? eq 0) { + system("touch /var/run/do-not-hibernate"); +} + +# Only change the symlinks if we are not being upgraded +if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m//og) { + image_magic($kimage, $image_dest); +} +else { + if (! -e "$kimage") { + handle_missing_link($kimage, $image_dest, "$kimage-$version", + $realimageloc); + } + else { + print STDERR + "Not updating image symbolic links since we are being updated/reinstalled \n"; + print STDERR + "($ARGV[1] was configured last, according to dpkg)\n"; + } +} + +# We used to have System.* files in / +if (-e "/System.map" || -e "/System.old") { + unlink '/System.map' if -e '/System.map'; + unlink '/System.old' if -e '/System.old'; +} + +# creating some info about kernel and initrd +if ($DEBUG) { + my $ksize=sprintf("%.0f",(stat($realimageloc . + "$kimage-$version"))[7]/1024)."kB"; + my $initrdsize=''; + if ($initrd) { + $initrdsize=sprintf("%.0f",(stat($realimageloc . + "initrd.img-$version"))[7]/1024)."kB"; + } + + print STDERR <<"EOMSG"; +A new kernel image has been installed at $realimageloc$kimage-$version + (Size: $ksize) + +Symbolic links, unless otherwise specified, can be found in $image_dest + +EOMSG + ; + + if ($initrd) { + print STDERR <<"EOMSGA"; + + Initial rootdisk image: ${realimageloc}initrd.img-$version (Size: $initrdsize) +EOMSGA + ; + } +} + +# set the env var stem +$ENV{'STEM'} = "linux"; +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + +## Run user hook script here, if any +if ($postinst_hook) { + &run_hook("postinst", $postinst_hook); +} + +if (-d "/etc/kernel/postinst.d") { + print STDERR "Examining /etc/kernel/postinst.d.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postinst.d") && + die "Failed to process /etc/kernel/postinst.d"; +} + +if (-d "/etc/kernel/postinst.d/$version") { + print STDERR "Examining /etc/kernel/postinst.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postinst.d/$version") && + die "Failed to process /etc/kernel/postinst.d/$version"; +} + +LOADER: { + last unless $do_boot_enable; # Exit if explicitly asked to + + last if $loader =~ /silo/i; # SILO does not have to be executed. + last if $loader =~ /yaboot/i; # yaboot does not have to be executed. + last if $loader =~ /milo/i; # MILO does not have to be executed. + last if $loader =~ /nettrom/i; # NETTROM does not have to be executed. + last if $loader =~ /arcboot/i; # ARCBOOT does not have to be executed. + last if $loader =~ /delo/i; # DELO does not have to be executed. + last if $loader =~ /quik/i; # maintainer asked quik invocation to be ignored + + last unless $loaderloc; + last unless -x $loaderloc; + last unless $do_bootloader; + + if (-T "/etc/$loader.conf") { + # Trust and use the existing lilo.conf. + print STDERR "You already have a $Loader configuration in /etc/$loader.conf\n"; + my $ret = &run_lilo(); + exit $ret if $ret; + } +} + + +sub run_lilo (){ + my $ret; + # Try and figure out if the user really wants lilo to be run -- + # since the default is to run the boot laoder, which is ! grub -- but + # the user may be using grub now, and not changed the default. + + # So, if the user has explicitly asked for the loader to be run, or + # if there is no postinst hook, or if there is no grub installed -- + # we are OK. Or else, we ask. + if ($explicit_do_loader || (! ($postinst_hook && -x '/usr/sbin/grub'))) { + print STDERR "Running boot loader as requested\n"; + } else { + print STDERR "Ok, not running $loader\n"; + } + if ($loader =~ /^lilo/io or $loader =~ /vmelilo/io) { + print STDERR "Testing $loader.conf ... \n"; + unlink $temp_file_name; # security + $ret = system("$loaderloc -t >$temp_file_name 2>&1"); + if ($ret) { + print STDERR "Boot loader test failed\n"; + return $ret; + } + unlink "$temp_file_name"; + print STDERR "Testing successful.\n"; + print STDERR "Installing the "; + print STDERR "partition " if $loader =~ /^lilo/io; + print STDERR "boot sector... \n"; + } + + print STDERR "Running $loaderloc ... \n"; + if ($loader =~ /^elilo/io) { + $ret = system("$loaderloc 2>&1 | tee $temp_file_name"); + } else { + $ret = system("$loaderloc >$temp_file_name 2>&1"); + } + if ($ret) { + print STDERR "Boot loader failed to run\n"; + return $ret; + } + unlink $temp_file_name; + print STDERR "Installation successful.\n"; + return 0; +} + +exit 0; + +__END__ + --- linux-2.6.27.orig/debian/control-scripts/preinst +++ linux-2.6.27/debian/control-scripts/preinst @@ -0,0 +1,299 @@ +#! /usr/bin/perl +# -*- Mode: Cperl -*- +# image.preinst --- +# Author : Manoj Srivastava ( srivasta@tiamat.datasync.com ) +# Created On : Sun Jun 14 03:38:02 1998 +# Created On Node : tiamat.datasync.com +# Last Modified By : Manoj Srivastava +# Last Modified On : Sun Sep 24 14:04:42 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 99 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# + +# +#use strict; #for debugging + +use Debconf::Client::ConfModule qw(:all); +version('2.0'); +my $capb=capb("backup"); + +$|=1; + +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlink = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, nettrom + # or elilo +my $image_dir = "/boot"; # where the image is located +my $initrd = "YES"; # initrd kernel +my $use_hard_links = ''; # hardlinks do not wirk across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $relink_src_link = 'YES'; # There is no harm in checking the link +my $relink_build_link = 'YES'; # There is no harm in checking the link +my $force_build_link = ''; # There is no harm in checking the link +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; # List of tools to create initial ram fs. +my $package_name = "linux-image-$version"; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; + + +#known variables +my @boilerplate = (); +my @silotemplate = (); +my @quiktemplate = (); +my @palotemplate = (); +my @vmelilotemplate = (); +my $bootdevice = ''; +my $rootdevice = ''; +my $rootdisk = ''; +my $rootpartition = ''; +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $CONF_LOC = '/etc/kernel-img.conf'; +my $relative_links = ''; +my $silent_loader = ''; +my $warn_reboot = ''; # Warn that we are installing a version of + # the kernel we are running + +my $modules_base = '/lib/modules'; + +die "Pre inst Internal error. Aborting." unless $version; + +exit 0 if $ARGV[0] =~ /abort-upgrade/; +exit 1 unless $ARGV[0] =~ /(install|upgrade)/; + +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + $relink_src_link = '' if /^\s*relink_src_link\s*=\s*(no|false|0)\s*$/ig; + $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig; + $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig; + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + $relink_src_link = 'Yes' if /^\s*relink_src_link\s*=\s*(yes|true|1)\s*$/ig; + $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig; + $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + $have_conffile = "Yes"; # stop perl complaining + } +} + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + +# About to upgrade this package from version $2 TO THIS VERSION. +# "prerm upgrade" has already been called for the old version of +# this package. + +sub find_initrd_tool { + my $hostversion = shift; + my $version = shift; + my @ramdisks = + grep { + my $args = + "$_ " . + "--supported-host-version=$hostversion " . + "--supported-target-version=$version " . + "1>/dev/null 2>&1" + ; + system($args) == 0; + } + split (/[:,\s]+/, $ramdisk); +} + +sub check { + my $version = shift; + my $lib_modules="$modules_base/$version"; + my $message = ''; + + if (-d "$lib_modules") { + opendir(DIR, $lib_modules) || die "can’t opendir $lib_modules: $!"; + my @children = readdir(DIR); + if ($#children > 1) { + my @dirs = grep { -d "$lib_modules/$_" } @children; + if ($#dirs > 1) { # we have subdirs + my $dir_message=''; + for my $dir (@dirs) { + if ($dir =~/kernel$/) { + $dir_message="An older install was detected.\n"; + } + else { + $dir_message="Module sub-directories were detected.\n" + unless $dir_message; + } + } + $message += $dir_message if $dir_message; + } + + my @links = grep { -l "$lib_modules/$_" } @children; + if ($#links > -1) { + my $links_message = ''; + for my $link (@links) { + next if ($link =~ /^build$/); + next if ($link =~ /^source$/); + $links_message = "Symbolic links were detected in $modules_base/$version.\n"; + } + $message += $links_message if $links_message; + } + my @files = grep { -f "$lib_modules/$_" } @children; + $message += "Additional files also exist in $modules_base/$version.\n" + if ($#files > -1); + } + } + else { $message .= "$lib_modules does not exist. ";} + return $message; +} + +if (-d "$modules_base/$version") { + my $errors=check($version); + warn "Info:\n$errors\n" if $errors; +} + +# set the env var stem +$ENV{'STEM'} = "linux"; + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + + +## Run user hook script here, if any +if (-x "$preinst_hook") { + &run_hook("preinst", $preinst_hook); +} +if (-d "/etc/kernel/preinst.d") { + print STDERR "Examining /etc/kernel/preinst.d/\n"; + system ("run-parts --verbose --exit-on-error --arg=$version" . + " --arg=$realimageloc$kimage-$version" . + " /etc/kernel/preinst.d") && + die "Failed to process /etc/kernel/preinst.d"; +} +if (-d "/etc/kernel/preinst.d/$version") { + print STDERR "Examining /etc/kernel/preinst.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version" . + " --arg=$realimageloc$kimage-$version" . + " /etc/kernel/preinst.d/$version") && + die "Failed to process /etc/kernel/preinst.d/$version"; +} +print STDERR "Done.\n"; + +exit 0; + +__END__ + + --- linux-2.6.27.orig/debian/control-scripts/headers-postinst +++ linux-2.6.27/debian/control-scripts/headers-postinst @@ -0,0 +1,126 @@ +#!/usr/bin/perl +# -*- Mode: Cperl -*- +# debian.postinst --- +# Author : Manoj Srivastava ( srivasta@pilgrim.umass.edu ) +# Created On : Sat Apr 27 05:42:43 1996 +# Created On Node : melkor.pilgrim.umass.edu +# Last Modified By : Manoj Srivastava +# Last Modified On : Sat Aug 5 13:20:22 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 45 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# +# +# arch-tag: 1c716174-2f0a-476d-a626-a1322e62503a +# + + +$|=1; + +# Predefined values: +my $version = "=V"; +my $kimage = "=K"; +my $package_name = "linux-image-$version"; + + +# Ignore all invocations uxcept when called on to configure. +exit 0 unless ($ARGV[0] && $ARGV[0] =~ /configure/); + +#known variables +my $image_dest = "/"; +my $realimageloc = "/boot/"; +my $silent_modules = ''; +my $modules_base = '/lib/modules'; +my $CONF_LOC = '/etc/kernel-img.conf'; +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + +chdir '/usr/src' or die "Could not chdir to /usr/src:$!"; + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $header_postinst_hook = "$1" if /^\s*header_postinst_hook\s*=\s*(\S+)/ig; + } + close CONF; + } +} + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + +## Run user hook script here, if any +if (-x "$header_postinst_hook") { + &run_hook("postinst", $header_postinst_hook); +} + +if (-d "/etc/kernel/header_postinst.d") { + print STDERR "Examining /etc/kernel/header_postinst.d.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/header_postinst.d") && + die "Failed to process /etc/kernel/header_postinst.d"; +} + +if (-d "/etc/kernel/header_postinst.d/$version") { + print STDERR "Examining /etc/kernel/header_postinst.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/header_postinst.d/$version") && + die "Failed to process /etc/kernel/header_postinst.d/$version"; +} + +exit 0; + +__END__ --- linux-2.6.27.orig/debian/control-scripts/postrm +++ linux-2.6.27/debian/control-scripts/postrm @@ -0,0 +1,376 @@ +#! /usr/bin/perl +# -*- Mode: Cperl -*- +# image.postrm --- +# Author : Manoj Srivastava ( srivasta@glaurung.green-gryphon.com ) +# Created On : Sat May 15 11:05:13 1999 +# Created On Node : glaurung.green-gryphon.com +# Last Modified By : Manoj Srivastava +# Last Modified On : Wed Sep 13 11:26:19 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 57 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# $Id: image.postrm,v 1.31 2003/10/07 16:24:20 srivasta Exp $ +# + + +# +#use strict; #for debugging +use Cwd 'abs_path'; + +$|=1; + +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlink = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, or nettrom +my $image_dir = "/boot"; # where the image is located +my $clobber_modules = ''; # target machine defined +my $initrd = "YES"; # initrd kernel +my $do_initrd = ''; # Normally, we don't +my $warn_initrd = 'YES'; # Normally we do +my $use_hard_links = ''; # hardlinks do not work across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $relink_build_link = 'YES'; # There is no harm in checking the link +my $force_build_link = ''; # we shall not create a dangling link +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; +my $package_name = "linux-image-$version"; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; + + +# This should not point to /tmp, because of security risks. +my $temp_file_name = "/var/log/$loader" . "_log.$$"; + +#known variables +my @boilerplate = (); +my @silotemplate = (); +my @quiktemplate = (); +my @palotemplate = (); +my @vmelilotemplate = (); +my $bootdevice = ''; +my $rootdevice = ''; +my $rootdisk = ''; +my $rootpartition = ''; +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $CONF_LOC = '/etc/kernel-img.conf'; +my $relative_links = ''; +my $silent_modules = ''; +my $silent_loader = ''; +my $warn_reboot = 'Yes'; # Warn that we are installing a version of + # the kernel we are running + +chdir('/') or die "could not chdir to /:$!\n"; +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $do_initrd = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig; + $warn_initrd = '' if /^\s*warn_initrd\s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_modules = '' if /^\s*silent_modules\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig; + $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig; + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $do_initrd = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig; + $warn_initrd = "Yes" if /^\s*warn_initrd\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_modules = 'Yes' if /^\s*silent_modules\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig; + $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + } +} + +if ($link_in_boot) { + $image_dest = "/$image_dir/"; + $image_dest =~ s|^/*|/|o; +} + +$image_dest = "$image_dest/"; +$image_dest =~ s|/+$|/|o; + +# The destdir may be gone by now. +if (-d "$image_dest") { + chdir("$image_dest") or die "could not chdir to $image_dest:$!\n"; +} + +# Paranoid check to make sure that the correct value is put in there +if (! $kimage) {$kimage = "vmlinuz"} # Hmm. empty +elsif ($kimage =~ m/^b?zImage$/o) {$kimage = "vmlinuz"} # these produce vmlinuz +elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage;} +elsif ($kimage =~ m/^vmlinux$/o) { my $nop = $kimage;} +else {$kimage = "vmlinuz"} # default + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +sub remove_sym_link { + my $bad_image = $_[0]; + + warn "Removing symbolic link $bad_image \n"; + if ($loader =~ /lilo/i) + { + warn "Unless you used the optional flag in lilo, \n"; + } + warn " you may need to re-run your boot loader" . ($loader ? "[$loader]":"") + . "\n"; + # Remove the dangling link + unlink "$bad_image"; +} + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +sub CanonicalizePath { + my $path = join '/', @_; + my @work = split '/', $path; + my @out; + my $is_absolute; + + if (@work && $work[0] eq "") { $is_absolute = 1; shift @work; } + + while (@work) { + my $seg = shift @work; + if ($seg eq "." || $seg eq "") { + } elsif ($seg eq "..") { + if (@out && $out[-1] ne "..") { + pop @out; + } else { + # Leading "..", or "../..", etc. + push @out, $seg; + } + } else { + push @out, $seg; + } + } + + unshift @out, "" if $is_absolute; + return join('/', @out); +} + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +# This removes dangling symlinks. What do we do about hard links? Surely a +# something with the nane $image_dest . "$kimage" ought not to be left behind? +sub image_magic { + my $kimage = $_[0]; + my $image_dest = $_[1]; + + if (-l "$kimage") { + # There is a symbolic link + my $force_move = 0; + my $vmlinuz_target = readlink "$kimage"; + my $real_target = ''; + $real_target = abs_path($vmlinuz_target) if defined ($vmlinuz_target); + if (!defined($vmlinuz_target) || ! -f "$real_target") { + # what, a dangling symlink? + warn "The link " . $image_dest . "$kimage is a damaged link\n"; + # Remove the dangling link + &remove_sym_link("$kimage"); + } + else { + my $canonical_target = CanonicalizePath("$vmlinuz_target"); + if (! -e $canonical_target) { + warn "The link " . $image_dest . "$kimage is a dangling link\n"; + &remove_sym_link("$kimage"); + } + } + } +} + +# set the env var stem +$ENV{'STEM'} = "linux"; + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + warn "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + warn "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + +## Run user hook script here, if any +if ($postrm_hook) { + &run_hook("postrm", $postrm_hook); +} +if (-d "/etc/kernel/postrm.d") { + warn "Examining /etc/kernel/postrm.d .\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postrm.d") && + die "Failed to process /etc/kernel/postrm.d"; +} +if (-d "/etc/kernel/postrm.d/$version") { + warn "Examining /etc/kernel/postrm.d/$version .\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postrm.d/$version") && + die "Failed to process /etc/kernel/postrm.d/$version"; +} + +# check and remove damaged and dangling symlinks +if ($ARGV[0] !~ /upgrade/) { + system("$ramdisk -d -k " . $version . " > /dev/null 2>&1"); + if (-f $realimageloc . "initrd.img-$version.bak") { + unlink $realimageloc . "initrd.img-$version.bak"; + } + image_magic($kimage, $image_dest); + image_magic($kimage . ".old", $image_dest); + image_magic("initrd.img", $image_dest) if $initrd; + image_magic("initrd.img.old", $image_dest) if $initrd; +} + + +# Ignore all invocations except when called on to purge. +exit 0 unless $ARGV[0] =~ /purge/; + +my @files_to_remove = qw{ + modules.dep modules.isapnpmap modules.pcimap + modules.usbmap modules.parportmap + modules.generic_string modules.ieee1394map + modules.ieee1394map modules.pnpbiosmap + modules.alias modules.ccwmap modules.inputmap + modules.symbols build source modules.ofmap + }; + +foreach my $extra_file (@files_to_remove) { + if (-f "/lib/modules/$version/$extra_file") { + unlink "/lib/modules/$version/$extra_file"; + } +} + +if (-d "/lib/modules/$version" ) { + system ("rmdir", "/lib/modules/$version"); +} + +exit 0; + +__END__ + + + + + + --- linux-2.6.27.orig/debian/abi/perm-blacklist +++ linux-2.6.27/debian/abi/perm-blacklist @@ -0,0 +1,3 @@ +M: ubuntu/misc/wireless/p80211/p80211 +M: sound/pci/emu10k1/snd-emu10k1 +M: fs/xfs/xfs --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/abiname +++ linux-2.6.27/debian/abi/2.6.27-8.17/abiname @@ -0,0 +1 @@ +8 --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/amd64/server +++ linux-2.6.27/debian/abi/2.6.27-8.17/amd64/server @@ -0,0 +1,8114 @@ +EXPORT_SYMBOL arch/x86/kvm/kvm 0xb6a40fbf kvm_cpu_has_pending_timer +EXPORT_SYMBOL arch/x86/kvm/kvm 0xd3a6cf78 kvm_read_guest_atomic +EXPORT_SYMBOL crypto/gf128mul 0x0c2f123f gf128mul_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x1068004b gf128mul_bbe +EXPORT_SYMBOL crypto/gf128mul 0x2f2889a0 gf128mul_init_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0x3755f990 gf128mul_init_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x384ef9ce gf128mul_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x56af0dbd gf128mul_x_ble +EXPORT_SYMBOL crypto/gf128mul 0x83581089 gf128mul_init_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0x9b2560b9 gf128mul_init_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x9e13f6f6 gf128mul_lle +EXPORT_SYMBOL crypto/gf128mul 0xbd17a0df gf128mul_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0xc0890413 gf128mul_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0xd60736ec gf128mul_free_64k +EXPORT_SYMBOL crypto/xor 0x5b6c00e6 xor_blocks +EXPORT_SYMBOL drivers/acpi/processor 0x0603377d acpi_processor_preregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0x8461fbfe acpi_processor_unregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0xcc337eed acpi_processor_notify_smm +EXPORT_SYMBOL drivers/acpi/processor 0xd78b77e1 acpi_processor_register_performance +EXPORT_SYMBOL drivers/acpi/processor 0xe8a3605f acpi_processor_set_thermal_limit +EXPORT_SYMBOL drivers/atm/suni 0xd3e7299a suni_init +EXPORT_SYMBOL drivers/atm/uPD98402 0x3edc4815 uPD98402_init +EXPORT_SYMBOL drivers/block/loop 0xbfee3ad5 loop_unregister_transfer +EXPORT_SYMBOL drivers/block/loop 0xcf881fae loop_register_transfer +EXPORT_SYMBOL drivers/block/paride/paride 0x25013aa1 pi_do_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0x38ed437c pi_release +EXPORT_SYMBOL drivers/block/paride/paride 0x50e50d6f pi_write_regr +EXPORT_SYMBOL drivers/block/paride/paride 0x53c0dbe1 pi_disconnect +EXPORT_SYMBOL drivers/block/paride/paride 0x77812371 paride_register +EXPORT_SYMBOL drivers/block/paride/paride 0x970aeb81 pi_init +EXPORT_SYMBOL drivers/block/paride/paride 0x9a585316 pi_read_regr +EXPORT_SYMBOL drivers/block/paride/paride 0xaa7a3854 pi_write_block +EXPORT_SYMBOL drivers/block/paride/paride 0xbf431b76 pi_schedule_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0xbfe35d8a pi_read_block +EXPORT_SYMBOL drivers/block/paride/paride 0xd3e5cea5 paride_unregister +EXPORT_SYMBOL drivers/block/paride/paride 0xe3890807 pi_connect +EXPORT_SYMBOL drivers/cdrom/cdrom 0x0b3fe3b7 cdrom_release +EXPORT_SYMBOL drivers/cdrom/cdrom 0x0c9ee323 cdrom_mode_sense +EXPORT_SYMBOL drivers/cdrom/cdrom 0x296214bd unregister_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0x45074893 register_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0x49284050 cdrom_get_media_event +EXPORT_SYMBOL drivers/cdrom/cdrom 0x4f476e96 init_cdrom_command +EXPORT_SYMBOL drivers/cdrom/cdrom 0xa467e472 cdrom_media_changed +EXPORT_SYMBOL drivers/cdrom/cdrom 0xa5283b53 cdrom_get_last_written +EXPORT_SYMBOL drivers/cdrom/cdrom 0xd210662e cdrom_mode_select +EXPORT_SYMBOL drivers/cdrom/cdrom 0xd242062a cdrom_open +EXPORT_SYMBOL drivers/cdrom/cdrom 0xde511722 cdrom_ioctl +EXPORT_SYMBOL drivers/cdrom/cdrom 0xf2108d74 cdrom_number_of_slots +EXPORT_SYMBOL drivers/char/generic_serial 0x0e049d30 gs_getserial +EXPORT_SYMBOL drivers/char/generic_serial 0x1a5c53a2 gs_flush_chars +EXPORT_SYMBOL drivers/char/generic_serial 0x20a17646 gs_write +EXPORT_SYMBOL drivers/char/generic_serial 0x265c1076 gs_got_break +EXPORT_SYMBOL drivers/char/generic_serial 0x2bed6446 gs_stop +EXPORT_SYMBOL drivers/char/generic_serial 0x41b705bc gs_put_char +EXPORT_SYMBOL drivers/char/generic_serial 0x4474023f gs_flush_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0x4a2144b3 gs_set_termios +EXPORT_SYMBOL drivers/char/generic_serial 0x515108b3 gs_chars_in_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0x935000f0 gs_setserial +EXPORT_SYMBOL drivers/char/generic_serial 0xb26a97f8 gs_close +EXPORT_SYMBOL drivers/char/generic_serial 0xb4c08446 gs_write_room +EXPORT_SYMBOL drivers/char/generic_serial 0xbb1e63b4 gs_block_til_ready +EXPORT_SYMBOL drivers/char/generic_serial 0xd30e7394 gs_hangup +EXPORT_SYMBOL drivers/char/generic_serial 0xf9207b39 gs_init_port +EXPORT_SYMBOL drivers/char/generic_serial 0xffed6eda gs_start +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0715ad27 ipmi_get_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0a6a132b ipmi_get_version +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x1ba3dad4 ipmi_set_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x1ce3dc1d ipmi_register_smi +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x25e9b58c ipmi_register_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x265a1b39 ipmi_smi_watchdog_pretimeout +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2d8686f4 ipmi_destroy_user +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x33138598 ipmi_set_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x3d93bbe9 ipmi_get_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x40f2b10c ipmi_alloc_smi_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x5a8a109b ipmi_smi_watcher_register +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x61d07c83 ipmi_set_gets_events +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x65aa95bd ipmi_request_supply_msgs +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x804f922a ipmi_addr_length +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x80c3ea9b ipmi_set_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x81d46def ipmi_request_settime +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x84c0526b ipmi_free_recv_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x9bb1e851 ipmi_unregister_smi +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xa1b909ac ipmi_smi_msg_received +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc0cbe7eb ipmi_unregister_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc85b64e9 ipmi_get_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xd559bd4d ipmi_create_user +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4c8ba05 ipmi_smi_add_proc_entry +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4f4665b ipmi_validate_addr +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe9675869 ipmi_smi_watcher_unregister +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xec361bb7 ipmi_poll_interface +EXPORT_SYMBOL drivers/char/nsc_gpio 0x207290f0 nsc_gpio_read +EXPORT_SYMBOL drivers/char/nsc_gpio 0x3c090386 nsc_gpio_dump +EXPORT_SYMBOL drivers/char/nsc_gpio 0x911cceae nsc_gpio_write +EXPORT_SYMBOL drivers/char/nvram 0x0f28cb91 nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x17ff2c1d __nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x2adec1e0 __nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x7da28f12 nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x9ce3f83f nvram_write_byte +EXPORT_SYMBOL drivers/char/nvram 0xa8813189 __nvram_write_byte +EXPORT_SYMBOL drivers/cpufreq/cpufreq_conservative 0x434e2f5f cpufreq_gov_conservative +EXPORT_SYMBOL drivers/cpufreq/cpufreq_ondemand 0x6a9cfc28 cpufreq_gov_ondemand +EXPORT_SYMBOL drivers/cpufreq/cpufreq_powersave 0xcd36ab09 cpufreq_gov_powersave +EXPORT_SYMBOL drivers/cpufreq/cpufreq_userspace 0x1df831c7 cpufreq_gov_userspace +EXPORT_SYMBOL drivers/edac/edac_core 0x2f92104e edac_mc_find +EXPORT_SYMBOL drivers/edac/edac_core 0xc1ead374 edac_mc_handle_fbd_ue +EXPORT_SYMBOL drivers/edac/edac_core 0xf6bde75d edac_mc_handle_fbd_ce +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0836695c drm_sman_takedown +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0c7eac99 drm_agp_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0x20645642 drm_debug +EXPORT_SYMBOL drivers/gpu/drm/drm 0x21451ac4 drm_sman_owner_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x232bdc50 drm_core_get_reg_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2916bf63 drm_sman_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2eb2f903 drm_sman_free_key +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2f8ade0a drm_pci_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3074f033 drm_order +EXPORT_SYMBOL drivers/gpu/drm/drm 0x30942ecd drm_mmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0x33bc76b3 drm_ioctl +EXPORT_SYMBOL drivers/gpu/drm/drm 0x369b254c drm_get_resource_start +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3d159d00 drm_core_reclaim_buffers +EXPORT_SYMBOL drivers/gpu/drm/drm 0x48a40a8b drm_pci_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0x5012ed9e drm_addbufs_agp +EXPORT_SYMBOL drivers/gpu/drm/drm 0x5221e3fd drm_agp_bind +EXPORT_SYMBOL drivers/gpu/drm/drm 0x55ca413a drm_idlelock_take +EXPORT_SYMBOL drivers/gpu/drm/drm 0x55f060ee drm_sman_set_range +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6b6bd23e drm_addbufs_pci +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6f8944c2 drm_fasync +EXPORT_SYMBOL drivers/gpu/drm/drm 0x709c286c drm_ati_pcigart_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x70d433ed drm_get_resource_len +EXPORT_SYMBOL drivers/gpu/drm/drm 0x75cd47f6 drm_vbl_send_signals +EXPORT_SYMBOL drivers/gpu/drm/drm 0x780c53f2 drm_agp_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0x8610a9dd drm_sg_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9a8543a7 drm_core_ioremapfree +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9b76add4 drm_compat_ioctl +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9c25b192 drm_core_get_map_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa36653d2 drm_core_ioremap_wc +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa6d94ca2 drm_core_ioremap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa6e04a07 drm_get_drawable_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0xaa4b8d96 drm_agp_enable +EXPORT_SYMBOL drivers/gpu/drm/drm 0xaf29788e drm_sman_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb23a0242 drm_exit +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb3ef7ffc drm_irq_uninstall +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb72e49ae drm_open +EXPORT_SYMBOL drivers/gpu/drm/drm 0xba33c377 drm_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc35f9568 drm_agp_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc913c1b5 drm_poll +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc99537f1 drm_addmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd2433566 drm_i_have_hw_lock +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3028e75 drm_sman_set_manager +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd924975e drm_getsarea +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe06ea6cc drm_idlelock_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe267fedc drm_agp_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe919dd5c drm_sman_owner_clean +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf1b10877 drm_rmmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf315470a drm_agp_acquire +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf3e5d708 drm_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf4341077 drm_ati_pcigart_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfcf5182c drm_locked_tasklet +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdc9b1b9 drm_agp_unbind +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdfbad19 drm_sman_alloc +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0x0903c239 vid_from_reg +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0xef1c781c vid_which_vrm +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x83bfe513 i2c_bit_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0xf27847d8 i2c_bit_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0x4f0e1244 i2c_pca_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0xee24900a i2c_pca_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pcf 0xbff8a04f i2c_pcf_add_bus +EXPORT_SYMBOL drivers/i2c/busses/i2c-amd756 0xb6ce3bf1 amd756_smbus +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x02d4ad0f tps65013_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x28485130 tps65010_config_vregs1 +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x33739de7 tps65010_set_vib +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x9fd44c69 tps65010_set_led +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xb14080cc tps65010_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xd5bb106d tps65010_set_vbus_draw +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xe99b3f36 tps65010_set_gpio_out_value +EXPORT_SYMBOL drivers/i2c/i2c-core 0x11eb5952 i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x35864ff2 i2c_master_send +EXPORT_SYMBOL drivers/i2c/i2c-core 0x45c4b342 i2c_smbus_read_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x55994d78 i2c_smbus_write_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x57489085 i2c_transfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0x5cd68967 i2c_smbus_read_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6773a7bb i2c_master_recv +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6e1900ac i2c_verify_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6e4db592 i2c_smbus_write_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x71d8d9f2 i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x8e6d4b75 i2c_register_driver +EXPORT_SYMBOL drivers/i2c/i2c-core 0x8ead13cf i2c_smbus_write_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x920cdf0a i2c_smbus_write_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0x9e0148bb i2c_detach_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x9e04ec05 i2c_smbus_read_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0xaa0ddde6 i2c_attach_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xb0b2d96a i2c_del_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xb6726786 i2c_get_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xba5956d4 i2c_put_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xbdcb6ad5 i2c_smbus_xfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0xd558294d i2c_add_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xd6939282 i2c_smbus_read_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0xde8be4f9 i2c_probe +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe06645a6 i2c_clients_command +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe14c53b7 i2c_use_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xeb8c4694 i2c_release_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xee914b23 i2c_del_driver +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x04680630 hpsb_destroy_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x056be1ac hpsb_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x088df759 hpsb_iso_recv_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0b234c4e dma_prog_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0c6da941 csr1212_release_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0d8e68a8 hpsb_unregister_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0e5a659c csr1212_new_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x110394aa hpsb_iso_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x11dd6ce9 hpsb_get_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x13b4a268 csr1212_attach_keyval_to_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x158ac548 dma_region_offset_to_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x168d2706 hpsb_alloc_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x18148340 hpsb_iso_n_ready +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x19f1f97b csr1212_parse_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1e931cb5 hpsb_get_hostinfo_bykey +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x20063a05 hpsb_resume_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2933cfc1 hpsb_create_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2b4eeacb hpsb_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2dd29f75 csr1212_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ebf6e5a dma_prog_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x31008801 hpsb_protocol_class +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3191c974 hpsb_iso_recv_release_packets +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x320a6985 hpsb_send_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x35a4916e hpsb_free_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3784fb59 hpsb_remove_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3e41541a hpsb_make_writepacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x416666b0 hpsb_unregister_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x484826b3 hpsb_register_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4a75c152 hpsb_set_packet_complete_task +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4fdbb421 hpsb_alloc_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x552ad218 hpsb_iso_stop +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x57dcc69f hpsb_update_config_rom_image +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5a689d9d hpsb_reset_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x625026a1 hpsb_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x672ad148 dma_region_sync_for_device +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6757ae29 hpsb_bus_reset +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x68561125 hpsb_node_fill_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6dabd92e hpsb_make_readpacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6e9920e8 hpsb_iso_recv_unlisten_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7328028c hpsb_iso_recv_flush +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x76bc1a5c dma_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7714ebd6 hpsb_iso_recv_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x79530b08 csr1212_get_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7f59d84b hpsb_iso_xmit_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8154a494 hpsb_node_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8879f8f0 dma_region_sync_for_cpu +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8ec2b312 dma_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x91da8413 hpsb_make_streampacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x978e8124 hpsb_set_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9b523756 hpsb_read_cycle_timer +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9e716efe hpsb_selfid_complete +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa0fdfb0c hpsb_unregister_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa4cfaefa hpsb_get_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa8fdd974 hpsb_iso_recv_listen_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa90de565 hpsb_iso_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaf7ce172 hpsb_allocate_and_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb4873145 hpsb_make_phypacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb5c9357b dma_region_mmap +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb68cb47a hpsb_packet_success +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xbf7cc767 hpsb_iso_shutdown +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc0cef6d2 hpsb_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc21c4ebc hpsb_update_config_rom +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc4ac84e2 hpsb_set_hostinfo_key +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc669a4d3 csr1212_detach_keyval_from_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcb1690bd hpsb_free_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcd9e772b dma_prog_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xce2d1f9c hpsb_iso_xmit_queue_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd376c0be hpsb_iso_wake +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd4875fa9 hpsb_iso_xmit_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xdd3630bf hpsb_make_lock64packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe356788e hpsb_add_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe608d4eb hpsb_selfid_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe72adfa1 hpsb_make_lockpacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xea4152ff dma_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xec68b660 __hpsb_register_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xef8afa96 hpsb_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xf1093281 hpsb_iso_recv_set_channel_mask +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfba57f51 hpsb_speedto_str +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfe5541c0 hpsb_iso_xmit_sync +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x187d5594 ohci1394_register_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x4ed04bc8 ohci1394_stop_context +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x7bff34a7 ohci1394_unregister_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xb37ab086 ohci1394_init_iso_tasklet +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x27ce491b rdma_translate_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x6aaa2fad rdma_addr_cancel +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x6e0915f2 rdma_resolve_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x71de06c2 rdma_addr_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x843c5216 rdma_copy_addr +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xbe81bb46 rdma_addr_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x04b169a8 ib_send_cm_rtu +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x0654b8e3 ib_send_cm_sidr_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x146dc20b ib_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x1544b3dc cm_class +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x2bacdf05 ib_send_cm_mra +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x42822045 ib_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x5adfd5c2 ib_cm_notify +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x65c20fdb ib_send_cm_lap +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x66a28bcc ib_send_cm_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x7f3a8018 ib_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x7fc620fb ib_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x8b0e79d8 ib_send_cm_apr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x8c411d0c ib_send_cm_rej +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x904a28e2 ib_send_cm_dreq +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xca836be5 ib_send_cm_sidr_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xde90e767 ib_send_cm_drep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xff2118be ib_send_cm_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x004d2a70 ib_umem_get +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x06830b9a ib_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0964c4da ib_modify_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0b248c8d ib_find_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0f957906 ib_query_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x10122270 ib_destroy_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1561cfce ib_fmr_pool_unmap +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1921fc61 ib_query_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1e491a04 ib_unmap_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1f58ecc1 ib_get_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x231a6e93 ib_alloc_fast_reg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x259834f1 ib_init_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2b8f6d54 ib_get_cached_lmc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2d345739 ib_fmr_pool_map_phys +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3506abbb ib_set_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x36848662 ib_register_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x373c6da1 ib_detach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3b5e707b ib_query_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3eb9d53f ib_query_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3f7567fd ib_rate_to_mult +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x4432c666 ib_rereg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x474ca838 ib_register_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x588a0061 ib_dealloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x592ca5ce ib_create_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x68882ef6 ib_umem_page_count +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6a2bb8f9 ib_destroy_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6b10f6ab ib_modify_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x704e804b ib_dereg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7235ee5d ib_destroy_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x728d4eea ib_modify_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x731b6898 ib_alloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x78b45481 ib_create_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7967e26e ib_dealloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7cf9419d ib_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x855a57ca ib_find_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x856dc8ae ib_get_dma_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8640eaeb ib_modify_qp_is_ok +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x86dc4a4c ib_create_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x87b614d8 ib_ud_header_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x95b6837c ib_create_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x960f762c ib_umem_release +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x96ce6c46 rdma_node_get_transport +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x99a2094a ib_dealloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d804fa1 mult_to_ib_rate +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa17c4d91 ib_query_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa5984d7b ib_alloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa73cb4ca ib_alloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xaa34acf0 ib_flush_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xab693bd0 ib_dealloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xadd9225d ib_get_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb07c55e4 ib_dispatch_event +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb3004b57 ib_modify_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb774bb9f ib_reg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb7b1f331 ib_query_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xbc1f0063 ib_find_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xc0e27f25 ib_destroy_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcabf41af ib_alloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcbad2f74 ib_destroy_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcfe26f98 ib_create_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd17ba9d1 ib_ud_header_init +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd77f8f39 ib_modify_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd93d3258 ib_attach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdc93a1f7 ib_unregister_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xddc775a0 ib_query_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdeda17d2 ib_get_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe3374fd3 ib_free_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe44a6d2b ib_unregister_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe4b25a7c ib_find_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe9ba86dd ib_alloc_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe9fd8052 ib_modify_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xed5ed015 ib_resize_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xee72ba70 ib_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf2d2bcae ib_query_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf36498b9 ib_ud_header_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf3e1ace5 ib_create_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf96fc9de ib_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x0fc9cca2 ib_modify_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x267035d0 ib_register_mad_snoop +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x3750239d ib_process_mad_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x4ac70f4f ib_unregister_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x52d45043 ib_create_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x56343a94 ib_redirect_mad_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6b63e17b ib_cancel_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6ef787ed ib_response_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6f077fcf ib_get_mad_data_offset +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x7b5d4b7a ib_is_mad_class_rmpp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xb13fd774 ib_get_rmpp_segment +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xe06ea7bd ib_register_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xe0916d6b ib_post_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xf1109a13 ib_free_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xf6ac6a5d ib_free_recv_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x12d2f9c2 ib_init_ah_from_mcmember +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x16199856 ib_sa_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x1f8df4ab ib_init_ah_from_path +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x3672be1b ib_sa_get_mcmember_rec +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x512ba124 ib_sa_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x576fdbac ib_sa_free_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xa3a2ff6e ib_sa_cancel_query +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xa487a41c ib_sa_service_rec_query +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xb99bf08c ib_sa_path_rec_get +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xd6315f72 ib_sa_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x02f847bc ib_copy_path_rec_from_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x07cf5a51 ib_copy_ah_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x18382f6a ib_copy_path_rec_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x184f3575 ib_copy_qp_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x0164358a iw_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x1422c606 iw_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x22d3f0a2 iw_cm_disconnect +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x54b8b621 iw_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x5c059721 iw_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x6cb1270b iw_cm_accept +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x838bc8ee iw_cm_reject +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xb77a1dd0 iw_cm_connect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x0419a7ca rdma_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x14fb7a11 rdma_create_qp +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x16e788b0 rdma_reject +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x2f7a2430 rdma_set_service_type +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x4446f20b rdma_resolve_route +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x595c6cc8 rdma_accept +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x5db2ff4b rdma_destroy_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x613ef179 rdma_set_ib_paths +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x724a2455 rdma_connect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x8032f06f rdma_disconnect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x9fb1b1aa rdma_notify +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xa8458c14 rdma_listen +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xae0f3e91 rdma_leave_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb11329f9 rdma_resolve_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb5c01a61 rdma_bind_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xcdf54013 rdma_create_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd31d1f0f rdma_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xf08ffdae rdma_destroy_qp +EXPORT_SYMBOL drivers/input/gameport/gameport 0x035e26b4 gameport_unregister_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0x3b5ec2eb gameport_unregister_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0x4898e54e __gameport_register_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0x710a1f30 gameport_close +EXPORT_SYMBOL drivers/input/gameport/gameport 0x988f0129 gameport_set_phys +EXPORT_SYMBOL drivers/input/gameport/gameport 0xab086f17 __gameport_register_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0xaf1e25bf gameport_open +EXPORT_SYMBOL drivers/input/gameport/gameport 0xe7cd08fa gameport_start_polling +EXPORT_SYMBOL drivers/input/gameport/gameport 0xf3dfecac gameport_stop_polling +EXPORT_SYMBOL drivers/input/input-polldev 0x566472e2 input_free_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xcfaebc0d input_unregister_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xf459885c input_allocate_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xfe1f83ab input_register_polled_device +EXPORT_SYMBOL drivers/isdn/capi/capifs 0x2c54c957 capifs_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/capifs 0xd0bc06ce capifs_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x04403fcf unregister_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x14f2aa5a capi20_get_version +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2b8eab1f capilib_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2baa6586 capilib_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x31c24aa4 capi20_isinstalled +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x3b3578ff capi_ctr_handle_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x47d3fc51 capi_info2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x47dbfa0a capi_message2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x50b33ca4 capi_cmsg2message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x56d99518 capi20_set_callback +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6057c6f3 capi_message2cmsg +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x62e32d43 capilib_data_b3_conf +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6d970af8 detach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6ed9b03f capi_ctr_suspend_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x71e8d5ba capilib_data_b3_req +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x788d398c capi_cmsg2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7a33596c capi20_get_serial +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7e6f1307 capi20_get_manufacturer +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x83092047 capi_ctr_ready +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8f699913 capilib_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8f71ada9 capi20_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x9f823278 register_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xaa165d27 capilib_release_appl +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xac3dc7a4 capi_ctr_reseted +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xada5fb07 capi20_put_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb19fda8d capi_cmd2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb60e5e5f capi_cmsg_header +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xc5327ee3 capi20_register +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xd5a982ef capi_ctr_resume_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe19a11ac capi20_get_profile +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe9640a93 attach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe9f62f29 cdebbuf_free +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xed061606 capi20_manufacturer +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x4fc40c21 b1_alloc_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x65f35e4f b1_getrevision +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x7efa651c b1_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x829bf3fe avmcard_dma_alloc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x85f09690 b1_irq_table +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x8af9867e b1_free_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x96f9d2f4 b1_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x9cc15157 b1_load_t4file +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xa372a74c b1_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xb6d6b17c avmcard_dma_free +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xc56b349e b1ctl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xce4e5aaf b1_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xcf7222b0 b1_load_config +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xd56d5012 b1_parse_version +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xd5fb157a b1_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xdfd28376 b1_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xf5ce1f3f b1_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xfb16ad93 b1_loaded +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x1675c45a t1pci_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x288f3c4a b1dma_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x295e6c95 b1dma_reset +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x2a386384 b1dma_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x317a5e50 b1dma_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x3bcaac3e b1pciv4_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x5ed0119d b1dma_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x7cfc0478 b1dmactl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x96274fce b1dma_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xe0181ac8 b1dma_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0x29562993 b1pcmcia_delcard +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xaec3240e b1pcmcia_addcard_m1 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xea620116 b1pcmcia_addcard_m2 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xf14bf8b1 b1pcmcia_addcard_b1 +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0x2974ead1 DIVA_DIDD_Read +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0xff3b8318 proc_net_eicon +EXPORT_SYMBOL drivers/isdn/hardware/mISDN/hfcmulti 0x5293ed86 plx_lock +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x07f4f2ce hisax_unregister +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x148f0c99 FsmFree +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x212b184f hisax_init_pcmcia +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x2844a899 FsmInitTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x93a64734 FsmChangeState +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x9df0cd27 FsmEvent +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xc0c558f9 FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xd94696e8 FsmDelTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xee93522c hisax_register +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xf0a16657 FsmNew +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xfc27303b HiSax_closecard +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x0b689858 isac_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x183005f8 isacsx_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x3f3b323a isac_d_l2l1 +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x49c0338f isac_init +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x935bbd27 isacsx_irq +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0xf874594e isac_irq +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x1ee629e2 isdnhdlc_rcv_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x95aed401 isdnhdlc_decode +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x9ffc8215 isdnhdlc_out_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0xf5c8131d isdnhdlc_encode +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x0f59ec6f isdn_ppp_register_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x1c49efa2 register_isdn +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xc6eb3fd3 isdn_ppp_unregister_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xfa06820f isdn_register_divert +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x0cda05e8 recv_Dchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x121a2d2b queue_ch_frame +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x2322ba99 mISDN_unregister_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x2348cc3c mISDN_FsmFree +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x305dcb83 get_next_dframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3e3bf4c2 get_next_bframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3e957c8a dchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3ea336fd mISDN_FsmAddTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x429129f2 mISDN_FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x469429f1 recv_Bchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x50c2230c mISDN_FsmChangeState +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6752033b mISDN_initdchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6b758763 mISDN_unregister_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6e23e131 recv_Bchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x7ec9c982 mISDN_register_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x81a3910d mISDN_freebchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x97863efb l1_event +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x996595fc mISDN_initbchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xace35cae mISDN_FsmDelTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xbbf229b8 mISDN_register_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xc15267d9 confirm_Bsend +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd5145151 mISDN_FsmEvent +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd9a7fbfd mISDN_FsmInitTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xe6ab7be9 mISDN_freedchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xe9d81796 recv_Dchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xf9e7832f mISDN_FsmNew +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xfdedee71 create_l1 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xfe88aa5a bchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x4c2ec443 mISDN_dsp_element_register +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x60721da7 dsp_audio_law_to_s32 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xa215f1b2 dsp_audio_s16_to_law +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xd3a023b8 mISDN_dsp_element_unregister +EXPORT_SYMBOL drivers/md/dm-log 0x1f3b2d7a dm_dirty_log_create +EXPORT_SYMBOL drivers/md/dm-log 0x38ec0daf dm_dirty_log_type_unregister +EXPORT_SYMBOL drivers/md/dm-log 0x4d1f6694 dm_dirty_log_type_register +EXPORT_SYMBOL drivers/md/dm-log 0x83efade3 dm_dirty_log_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x0056bbab dm_kcopyd_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0x15eb4b5a dm_unregister_target +EXPORT_SYMBOL drivers/md/dm-mod 0x1a1d7bed dm_io_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0x29a5385b dm_table_unplug_all +EXPORT_SYMBOL drivers/md/dm-mod 0x2a73bda8 dm_register_target +EXPORT_SYMBOL drivers/md/dm-mod 0x2d885944 dm_kcopyd_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x3103523c dm_table_get_md +EXPORT_SYMBOL drivers/md/dm-mod 0x44be23dc dm_table_get_size +EXPORT_SYMBOL drivers/md/dm-mod 0x59794a46 dm_get_device +EXPORT_SYMBOL drivers/md/dm-mod 0x62068ecb dm_get_mapinfo +EXPORT_SYMBOL drivers/md/dm-mod 0x6a94470c dm_table_get +EXPORT_SYMBOL drivers/md/dm-mod 0x82f65633 dm_io_client_resize +EXPORT_SYMBOL drivers/md/dm-mod 0x954c8af3 dm_io_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x9ae2adaa dm_table_event +EXPORT_SYMBOL drivers/md/dm-mod 0xa0115881 dm_io +EXPORT_SYMBOL drivers/md/dm-mod 0xbb7efdd2 dm_put_device +EXPORT_SYMBOL drivers/md/dm-mod 0xc79bcd36 dm_vcalloc +EXPORT_SYMBOL drivers/md/dm-mod 0xd92d6965 dm_table_put +EXPORT_SYMBOL drivers/md/dm-mod 0xdafb5eca dm_table_get_mode +EXPORT_SYMBOL drivers/md/dm-mod 0xf13c0837 dm_kcopyd_copy +EXPORT_SYMBOL drivers/md/md-mod 0x01a71c55 md_check_recovery +EXPORT_SYMBOL drivers/md/md-mod 0x0fc585b2 md_register_thread +EXPORT_SYMBOL drivers/md/md-mod 0x103b5521 md_wait_for_blocked_rdev +EXPORT_SYMBOL drivers/md/md-mod 0x1e383a74 bitmap_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0x47da3943 unregister_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0x51409eca bitmap_cond_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0x69d57564 md_unregister_thread +EXPORT_SYMBOL drivers/md/md-mod 0x707f756d bitmap_close_sync +EXPORT_SYMBOL drivers/md/md-mod 0x792bc41f md_write_start +EXPORT_SYMBOL drivers/md/md-mod 0x813010a2 register_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0x87791895 bitmap_startwrite +EXPORT_SYMBOL drivers/md/md-mod 0x8dc820c4 md_write_end +EXPORT_SYMBOL drivers/md/md-mod 0xa8b4d6e7 md_wakeup_thread +EXPORT_SYMBOL drivers/md/md-mod 0xb4a22f80 md_error +EXPORT_SYMBOL drivers/md/md-mod 0xb6cfb1af bitmap_unplug +EXPORT_SYMBOL drivers/md/md-mod 0xdb97ec5a md_done_sync +EXPORT_SYMBOL drivers/md/md-mod 0xe911c42e bitmap_endwrite +EXPORT_SYMBOL drivers/md/md-mod 0xfba3b7d9 bitmap_start_sync +EXPORT_SYMBOL drivers/media/common/tuners/mt2060 0xd204cfe7 mt2060_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2131 0x243892f9 mt2131_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2266 0x185fe6b8 mt2266_attach +EXPORT_SYMBOL drivers/media/common/tuners/mxl5005s 0x11312dbd mxl5005s_attach +EXPORT_SYMBOL drivers/media/common/tuners/qt1010 0x1d5e4d0b qt1010_attach +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0x0cb4b189 tuners +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0xc2821775 tuner_count +EXPORT_SYMBOL drivers/media/common/tuners/tuner-xc2028 0x49514733 xc2028_attach +EXPORT_SYMBOL drivers/media/common/tuners/xc5000 0x81e28a78 xc5000_attach +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x17628635 flexcop_device_kfree +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x1daae7bf flexcop_sram_ctrl +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x21cac457 flexcop_pass_dmx_data +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x2f0e883a flexcop_dma_xfer_control +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x333d6e39 flexcop_dma_control_timer_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x41b5c418 flexcop_dma_config_timer +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x44f568f5 flexcop_i2c_request +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x739a05be flexcop_eeprom_check_mac_addr +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x73f18b61 flexcop_dma_config +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x87ccfaaf flexcop_wan_set_speed +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xac037ec9 flexcop_sram_set_dest +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb28406dc flexcop_dma_control_size_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb44b47a1 flexcop_device_exit +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xd3a43db4 flexcop_pass_dmx_packets +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xdb151ded flexcop_device_initialize +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xdfa01aba flexcop_dump_reg +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xe1c483ff flexcop_dma_free +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xed6ea3b9 flexcop_device_kmalloc +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xf13e7f3e flexcop_dma_allocate +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x6ee7dc0f bt878 +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x8224583f bt878_start +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xd5d0bdef bt878_num +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xe9ef946a bt878_stop +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xedcc728d bt878_device_control +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x3ec95d82 dst_wait_dst_ready +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x441dc5c5 dst_attach +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x48154fc1 dst_error_bailout +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x49f20f68 dst_pio_disable +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x82af4f48 dst_comm_init +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xc4afd7b2 read_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xc9339448 dst_error_recovery +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xd686600b rdc_reset_state +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xe17ab117 write_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xe94b8c9c dst_check_sum +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst_ca 0x4574500f dst_ca_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x06a66320 dvb_net_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x0bccd3ae dvb_frontend_detach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x0c457c5c dvb_ringbuffer_flush_spinlock_wakeup +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x0f4b1233 dvb_register_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x10ba1261 dvb_unregister_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x1a4cb6dc dvb_generic_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x36c8ea1f dvb_frontend_sleep_until +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x42e01d94 dvb_ca_en50221_camchange_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x4db3899f dvb_dmx_swfilter_packets +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x50958ad4 dvb_unregister_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x51f3767c dvb_ringbuffer_read +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x55d0c68f dvb_frontend_reinitialise +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x5649dcda dvb_ca_en50221_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6988f784 dvb_ringbuffer_read_user +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6bbb7d7d dvb_unregister_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x74a5a698 dvb_filter_pes2ts_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x7c2c3da5 dvb_dmxdev_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x7c8f903a dvb_net_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x80e3832d dvb_filter_get_ac3info +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x8b49a23f timeval_usec_diff +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x93a76e15 dvb_generic_open +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xa0774422 dvb_dmxdev_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xaa72b6c5 dvb_register_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xac4ca1b0 intlog2 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb07f9a51 dvb_ca_en50221_frda_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xba2c8ee1 dvb_ca_en50221_camready_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xbb5605bb dvb_register_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc324b69b dvb_dmx_swfilter_204 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc80754c1 dvb_dmx_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xcb89fc7d dvb_ringbuffer_free +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xcca08cb5 dvb_ringbuffer_avail +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xcce0eeed dvb_ringbuffer_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xd05d3fee dvb_generic_ioctl +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xd639b9bc dvb_ringbuffer_write +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xd7765e69 dvb_ringbuffer_empty +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe3234dd3 dvb_ca_en50221_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe5ae8707 intlog10 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xee73de0a dvb_dmx_swfilter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xf826deb0 dvb_filter_pes2ts +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xf86f20c5 dvb_dmx_init +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x0393b31f dvb_usb_generic_write +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x58e20f63 dvb_usb_device_init +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x5e22deb3 dvb_usb_generic_rw +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x5f075c06 usb_cypress_load_firmware +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x6d6f0fc2 dvb_usb_nec_rc_key_to_event +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x8a412dc2 dvb_usb_get_hexline +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0xa16f8e1c dvb_usb_device_exit +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0x2edc4728 af9005_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0xc1f33b40 af9005_rc_decode +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0xd3383957 af9005_rc_keys_size +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x0fee6893 dibusb_read_eeprom_byte +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x1406e352 dibusb2_0_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x150d0e5f dibusb_rc_query +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x77fb0393 dibusb_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xad10b6a8 dibusb_pid_filter_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xb130eedc dibusb_dib3000mc_tuner_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xb5905684 dibusb_dib3000mc_frontend_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xbf166b2e dibusb2_0_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xcdc1bfc5 dibusb_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd1674eea dibusb_pid_filter +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd4d3dddc dibusb_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xfa3163c5 dibusb_i2c_algo +EXPORT_SYMBOL drivers/media/dvb/frontends/au8522 0x462bd9a0 au8522_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/bcm3510 0x03339406 bcm3510_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22700 0x2ee5db72 cx22700_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22702 0x566c0b0b cx22702_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24110 0xa5087cef cx24110_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0x0a1b40d8 cx24123_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0xaf799b2e cx24123_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0x5b236b1c dib0070_wbd_offset +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0x9c1e1e48 dib0070_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mb 0x5b12ac26 dib3000mb_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x4bdecef8 dib3000mc_pid_parse +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x518f0fb2 dib3000mc_set_config +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x578986b2 dib3000mc_pid_control +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x91b72971 dib3000mc_get_tuner_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xafe12325 dib3000mc_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xca05f5e2 dib3000mc_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x02ae9036 dib7000m_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x59b7af96 dib7000m_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0xac6e3024 dib7000m_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x5a9caab5 dib7000p_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x869ac61d dib7000pc_detection +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x9c6c5b88 dib7000p_set_gpio +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xa80250e4 dib7000p_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xb3820e97 dib7000p_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xd7e7873f dib7000p_set_wbd_ref +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0x42db0787 dibx000_init_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0xc8b22238 dibx000_get_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0xe6c25eb0 dibx000_exit_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/drx397xD 0xfd457fec drx397xD_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dvb-pll 0xd8023134 dvb_pll_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6405 0xe6a9182d isl6405_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6421 0x71298970 isl6421_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/itd1000 0x90a1a44f itd1000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/l64781 0x74f72efd l64781_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lgdt330x 0xa7e9c290 lgdt330x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lnbp21 0x29ea6a22 lnbp21_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt312 0x24230799 mt312_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt352 0x3817324b mt352_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt200x 0x5c1aa564 nxt200x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt6000 0xa71ee2c8 nxt6000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51132 0x83bbfb46 or51132_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51211 0xcacad09b or51211_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1409 0xfe684200 s5h1409_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1411 0x7eabc6c6 s5h1411_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0x5b253a53 s5h1420_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0xf2ee342c s5h1420_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/sp8870 0x352596b8 sp8870_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/sp887x 0xd637a724 sp887x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0297 0xab836214 stv0297_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0299 0xaf176d95 stv0299_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10021 0x922f9b10 tda10021_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10023 0xd7eda584 tda10023_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10048 0x434d855d tda10048_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0x086a0e5d tda10046_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0x739af687 tda10045_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10086 0x5f3405b8 tda10086_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda8083 0xec992d6d tda8083_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda826x 0xfc7008e9 tda826x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tua6100 0x11338e8a tua6100_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1820 0xb7bc5cb3 ves1820_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1x93 0x5c576a65 ves1x93_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/zl10353 0xbf104be5 zl10353_attach +EXPORT_SYMBOL drivers/media/dvb/ttpci/ttpci-eeprom 0x257acc92 ttpci_eeprom_parse_mac +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0x8489e335 ttusbdecfe_dvbs_attach +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0xaf4ee2ff ttusbdecfe_dvbt_attach +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x11dc4b6d bttv_gpio_enable +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x507622bd bttv_sub_register +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x76c9d789 bttv_sub_unregister +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x8ecf4acc bttv_write_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xbcf2d2fb bttv_read_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xbf4b1101 bttv_get_pcidev +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x3456dd5f btcx_riscmem_alloc +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x495e4b0c btcx_calc_skips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xad2fe38b btcx_sort_clips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xc368f8e6 btcx_align +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xcda0ded2 btcx_screen_clips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xfd39dc3a btcx_riscmem_free +EXPORT_SYMBOL drivers/media/video/cpia 0x69a120ae cpia_unregister_camera +EXPORT_SYMBOL drivers/media/video/cpia 0x857c4e49 cpia_register_camera +EXPORT_SYMBOL drivers/media/video/cx18/cx18 0x2cdea06d cx18_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/cx2341x 0x0224a947 cx2341x_update +EXPORT_SYMBOL drivers/media/video/cx2341x 0x3559ba71 cx2341x_ext_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0x8fdbede1 cx2341x_fill_defaults +EXPORT_SYMBOL drivers/media/video/cx2341x 0xcf8b77a4 cx2341x_mpeg_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0xde1da524 cx2341x_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx2341x 0xeacc6fab cx2341x_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/cx2341x 0xfb8bd71f cx2341x_log_status +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x3663d3c7 cx23885_get_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x3a4da341 cx23885_enum_input +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x440aeaa0 cx23885_set_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xe12fa84c cx23885_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xe19b1f2f cx23885_set_freq +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xfb885537 cx23885_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xfd7f4d0d cx23885_video_mux +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0x2dbcaf56 vp3054_i2c_probe +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0xd4d17f23 vp3054_i2c_remove +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x0666bc48 cx88_enum_input +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xa3304d11 cx88_set_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xac4e53b9 cx88_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xbd6e9fbb cx88_set_freq +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xbdbc79f5 cx8800_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xf71c10fe cx88_get_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xfd0effc2 cx88_video_mux +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x15845a8a cx8802_buf_queue +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x2636cd8e cx8802_buf_prepare +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x482c62db cx8802_get_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x56493b0b cx8802_cancel_buffers +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x676c2010 cx8802_register_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x796c6bb6 cx8802_unregister_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x89e30243 cx8802_get_device +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x08d19264 cx88_set_scale +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x09751616 cx88_set_tvnorm +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x1446d23b cx88_core_get +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x1662b45e cx88_vdev_init +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x275abcb5 cx88_core_irq +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x27ab4c7c cx88_shutdown +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x550c54c5 cx88_newstation +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x5bf81fb8 cx88_free_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7b5cdee1 cx88_tuner_callback +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7c704e69 cx88_get_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7d101d8a cx88_wakeup +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x904b8696 cx88_audio_thread +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x918b9c59 cx88_call_i2c_clients +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x96d77e91 cx88_risc_databuffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x974d1ab5 cx88_ir_start +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x9b140fff cx88_sram_channels +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xb3c7685f cx88_sram_channel_dump +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xb47f6cda cx88_print_irqbits +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xba1db23d cx88_set_tvaudio +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc2c78eaf cx88_core_put +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc77d3330 cx88_risc_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc9c953c5 cx88_ir_stop +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xcde42a36 cx88_set_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xe446f703 cx88_sram_channel_setup +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xf80f8637 cx88_risc_stopper +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xfd79e873 cx88_reset +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0x102de5d5 em28xx_register_extension +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0xf6552203 em28xx_unregister_extension +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x2797ecf1 gspca_dev_probe +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x2ed1b17e gspca_disconnect +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x5401a38e gspca_auto_gain_n_exposure +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x8df8ff77 gspca_frame_add +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x9670af2c gspca_debug +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0xa099de0c gspca_resume +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0xa87382c8 gspca_suspend +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0538e449 ivtv_cards_lock +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0924162b ivtv_api +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x14f67530 ivtv_debug +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x175fce32 ivtv_udma_alloc +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x24e38fe2 ivtv_cards +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x2d96c803 ivtv_udma_setup +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x2effad37 ivtv_vapi_result +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x70196ffb ivtv_cards_active +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xa771c06a ivtv_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xb19959a6 ivtv_set_irq_mask +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xb539197e ivtv_vapi +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xbd35b4a7 ivtv_init_on_first_open +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xd8e6bcdc ivtv_udma_unmap +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xddea26f3 ivtv_udma_prepare +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xecfbe7bc ivtv_clear_irq_mask +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x1211df5d saa7134_devlist +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x1773055d saa7134_tvaudio_setmute +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x2fba9bf6 saa7134_pgtable_build +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x5684a2eb saa7134_set_gpio +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x62bf6ca1 saa7134_pgtable_alloc +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x64b7c43d saa7134_dmasound_exit +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x67ffe4a7 saa7134_dmasound_init +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x6f342cb6 saa7134_pgtable_free +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x8122ea45 saa7134_set_dmabits +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x85593767 saa7134_tuner_callback +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x98af79c1 saa7134_boards +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xb16b1c09 saa7134_ts_unregister +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xe4dab64a saa7134_ts_register +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xf6bd440a saa_dsp_writel +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xf9b5bb04 saa7134_i2c_call_clients +EXPORT_SYMBOL drivers/media/video/soc_camera 0x01c40d5c soc_camera_device_unregister +EXPORT_SYMBOL drivers/media/video/soc_camera 0x0e4d94ee soc_camera_host_unregister +EXPORT_SYMBOL drivers/media/video/soc_camera 0x24de4198 soc_camera_host_register +EXPORT_SYMBOL drivers/media/video/soc_camera 0x3b0d261b soc_camera_video_stop +EXPORT_SYMBOL drivers/media/video/soc_camera 0x91dab7ab soc_camera_device_register +EXPORT_SYMBOL drivers/media/video/soc_camera 0xbf2e793e soc_camera_video_start +EXPORT_SYMBOL drivers/media/video/tveeprom 0x47997527 tveeprom_read +EXPORT_SYMBOL drivers/media/video/tveeprom 0xc7688f36 tveeprom_hauppauge_analog +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x16a2915c RingQueue_Dequeue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x1f8d78a7 usbvideo_TestPattern +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x3dd29cbd usbvideo_Deregister +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x407a321c RingQueue_WakeUpInterruptible +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x46d9e15a usbvideo_AllocateDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x852af129 usbvideo_DeinterlaceFrame +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x8d69204b usbvideo_register +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xb756bc2b usbvideo_RegisterVideoDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xddecac6d RingQueue_Enqueue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xf5011f67 RingQueue_Flush +EXPORT_SYMBOL drivers/media/video/v4l1-compat 0x7654a1ce v4l_compat_translate_ioctl +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x03165a85 v4l2_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x0dfb5e57 v4l2_prio_max +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x1c427ecb v4l2_ctrl_query_fill +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2de2b633 v4l2_prio_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2e9a955d v4l2_prio_close +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x42c8e001 v4l2_ctrl_next +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x57abfbd8 v4l2_chip_match_host +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x5fef1b4a v4l2_ctrl_query_fill_std +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x662d0e08 v4l2_chip_ident_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x942892ab v4l2_prio_open +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x94d3dd7b v4l2_chip_match_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xb2d1e17e v4l2_prio_change +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xc369097d v4l2_ctrl_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xd464e760 v4l2_ctrl_query_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xe330bce9 v4l2_prio_init +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xfcd2b56f v4l2_i2c_attach +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0x3b38986a videobuf_dvb_unregister +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0x9f271de4 videobuf_dvb_register +EXPORT_SYMBOL drivers/media/video/videocodec 0x1cef83e6 videocodec_detach +EXPORT_SYMBOL drivers/media/video/videocodec 0x1fa1a848 videocodec_unregister +EXPORT_SYMBOL drivers/media/video/videocodec 0x7124aaa6 videocodec_attach +EXPORT_SYMBOL drivers/media/video/videocodec 0xb1088af6 videocodec_register +EXPORT_SYMBOL drivers/media/video/videodev 0x0c4762b4 video_device_release +EXPORT_SYMBOL drivers/media/video/videodev 0x123959a1 v4l2_type_names +EXPORT_SYMBOL drivers/media/video/videodev 0x223430ec video_devdata +EXPORT_SYMBOL drivers/media/video/videodev 0x28ee084b video_ioctl2 +EXPORT_SYMBOL drivers/media/video/videodev 0x3495bb68 video_register_device +EXPORT_SYMBOL drivers/media/video/videodev 0x3adbd595 v4l2_field_names +EXPORT_SYMBOL drivers/media/video/videodev 0x5242fca7 video_register_device_index +EXPORT_SYMBOL drivers/media/video/videodev 0x5ebefe4b v4l_printk_ioctl +EXPORT_SYMBOL drivers/media/video/videodev 0xae86a3e9 video_exclusive_open +EXPORT_SYMBOL drivers/media/video/videodev 0xbc211eb8 video_usercopy +EXPORT_SYMBOL drivers/media/video/videodev 0xe1682b09 video_device_alloc +EXPORT_SYMBOL drivers/media/video/videodev 0xe1f10b23 video_unregister_device +EXPORT_SYMBOL drivers/media/video/videodev 0xe2b92059 v4l2_video_std_construct +EXPORT_SYMBOL drivers/media/video/videodev 0xee1076f2 video_exclusive_release +EXPORT_SYMBOL drivers/media/video/videodev 0xf3251e7b v4l2_norm_to_name +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x0c99314d mpt_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x105d4f47 mpt_add_sge +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x2f16defb mpt_free_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x2f80f5f9 mptbase_sas_persist_operation +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x304b9c68 mpt_alloc_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x3109e6a5 mpt_free_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x35174349 mpt_attach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x3c368b63 mpt_HardResetHandler +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4526289b mpt_event_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4ea7ab21 mpt_put_msg_frame_hi_pri +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x8220d246 mpt_get_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x8fa31005 mpt_suspend +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x923de435 mpt_detach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x95cfa048 mpt_GetIocState +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x964b2ceb mpt_verify_adapter +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xa980f3b8 mpt_reset_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xb4250c9e mpt_resume +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc0e69f82 mpt_device_driver_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc47c22e8 mpt_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd45190a7 mpt_print_ioc_summary +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd4867f27 mpt_findImVolumes +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd9a92a75 mpt_reset_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdd805159 ioc_list +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe1137a1e mpt_config +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe5770ccc mpt_send_handshake_request +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xeb853fd7 mpt_device_driver_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xee556142 mpt_raid_phys_disk_pg0 +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xf0c7cbbb mpt_event_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xf649023a mpt_put_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x06867bcf mptscsih_bios_param +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x1dfb1146 mptscsih_bus_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x2ef94c87 mptscsih_slave_destroy +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x30570756 mptscsih_scandv_complete +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x313630ed mptscsih_proc_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x3bc1b970 mptscsih_qcmd +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x40e04ef0 mptscsih_io_done +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x51e8a2d8 mptscsih_TMHandler +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x53661a50 mptscsih_slave_configure +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x59e3e168 mptscsih_host_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6ec3fe5f mptscsih_shutdown +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6f087264 mptscsih_dev_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x714d2d1d mptscsih_host_attrs +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x71fef407 mptscsih_remove +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x764ddf1a mptscsih_timer_expired +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x7732cd97 mptscsih_abort +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x79bbcb9c mptscsih_raid_id_to_num +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xb576d2fe mptscsih_resume +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xb87fd587 mptscsih_event_process +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xbaf9bcef mptscsih_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xc0564663 mptscsih_is_phys_disk +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe20ed894 mptscsih_change_queue_depth +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe452c9e8 mptscsih_suspend +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xedc93803 mptscsih_ioc_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xf7b68589 mptscsih_taskmgmt_complete +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x0db26b8f i2o_driver_notify_device_remove_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x1aba1919 i2o_parm_field_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x23520576 i2o_parm_table_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x260a3d8f i2o_parm_issue +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2a843bef i2o_dump_message +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x377b7d21 i2o_cntxt_list_get_ptr +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x3ad6d0cf i2o_driver_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x3e589e94 i2o_driver_unregister +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x42987e0b i2o_driver_notify_controller_remove_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x4fe04c5e i2o_msg_post_wait_mem +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x53545de1 i2o_find_iop +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x69d4cc55 i2o_device_claim +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x9e354057 i2o_iop_find_device +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xa271b0ad i2o_cntxt_list_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xa9425d95 i2o_cntxt_list_remove +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb21ce57b i2o_exec_lct_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb4c00dcf i2o_controllers +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xbb697865 i2o_msg_get_wait +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xc1814fb6 i2o_event_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xd6228d6e i2o_device_claim_release +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xd75cf121 i2o_status_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xe172b1ab i2o_driver_notify_device_add_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xeb70c8f2 i2o_cntxt_list_add +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xf37fcea1 i2o_driver_notify_controller_add_all +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x0f51d084 pasic3_write_register +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x6e41ded3 pasic3_read_register +EXPORT_SYMBOL drivers/misc/ioc4 0x4dc73f77 ioc4_unregister_submodule +EXPORT_SYMBOL drivers/misc/ioc4 0x545c5bb5 ioc4_register_submodule +EXPORT_SYMBOL drivers/misc/sony-laptop 0x5bb1e117 sony_pic_camera_command +EXPORT_SYMBOL drivers/misc/tifm_core 0x102c481d tifm_free_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0x3e9fa511 tifm_free_device +EXPORT_SYMBOL drivers/misc/tifm_core 0x3ef4f81f tifm_unmap_sg +EXPORT_SYMBOL drivers/misc/tifm_core 0x4660af57 tifm_remove_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0x805fdc5a tifm_alloc_device +EXPORT_SYMBOL drivers/misc/tifm_core 0xa63a3d65 tifm_add_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0xa65404aa tifm_map_sg +EXPORT_SYMBOL drivers/misc/tifm_core 0xa8c2ec46 tifm_queue_work +EXPORT_SYMBOL drivers/misc/tifm_core 0xac825ebe tifm_eject +EXPORT_SYMBOL drivers/misc/tifm_core 0xb3e8bc33 tifm_register_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0xd903f0e4 tifm_has_ms_pif +EXPORT_SYMBOL drivers/misc/tifm_core 0xe902efc7 tifm_unregister_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0xf53ccd64 tifm_alloc_adapter +EXPORT_SYMBOL drivers/mmc/card/mmc_block 0x4f9350d0 mmc_cleanup_queue +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x0593b08d mmc_resume_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x186f189a mmc_wait_for_req +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x1aa7bc4b mmc_unregister_driver +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x2bde8859 mmc_suspend_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x2eb32e3f mmc_align_data_size +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x46208123 mmc_remove_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x52a0d94b mmc_set_data_timeout +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x58ba654b mmc_free_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x5a3adf4c __mmc_claim_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x609e45d4 mmc_wait_for_app_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x6b1bcf5f mmc_add_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x928ee936 mmc_detect_change +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x9f914436 mmc_request_done +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xaf5f226c mmc_wait_for_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xb2aef807 mmc_alloc_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xde098a48 mmc_release_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xf86a6aa2 mmc_register_driver +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x2b685181 cfi_fixup +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x87e37c41 cfi_varsize_frob +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0xf07bfaa7 cfi_read_pri +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x6d01b9fa map_destroy +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xb34366f0 do_map_probe +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xc9da98fe unregister_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xea12a65f register_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/gen_probe 0xe6a9a89f mtd_do_chip_probe +EXPORT_SYMBOL drivers/mtd/maps/map_funcs 0xf493222a simple_map_init +EXPORT_SYMBOL drivers/mtd/mtd 0xc5ea1aa7 add_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtd 0xf3edb1e3 del_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtdconcat 0x3f62ef94 mtd_concat_destroy +EXPORT_SYMBOL drivers/mtd/mtdconcat 0xb0d26226 mtd_concat_create +EXPORT_SYMBOL drivers/mtd/nand/nand 0x4a05f8be nand_scan_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand 0xc3af03b0 nand_default_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x254f230c nand_calculate_ecc +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x87406d9d nand_correct_data +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0x836bdb72 nand_flash_ids +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0xa336feb7 nand_manuf_ids +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0x9926269f onenand_default_bbt +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xda3a6e1b onenand_scan_bbt +EXPORT_SYMBOL drivers/net/8390 0x1ef83b21 ei_poll +EXPORT_SYMBOL drivers/net/8390 0x3a61b49a ei_open +EXPORT_SYMBOL drivers/net/8390 0x7d7e0dbc ei_interrupt +EXPORT_SYMBOL drivers/net/8390 0xa709106e __alloc_ei_netdev +EXPORT_SYMBOL drivers/net/8390 0xd300acec NS8390_init +EXPORT_SYMBOL drivers/net/8390 0xdd4045fc ei_close +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x17761137 arc_bcast_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x2fb353f8 arc_proto_map +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4641bd7d arcnet_interrupt +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4baed961 arcnet_unregister_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x6534792a arcnet_debug +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xa55ffed1 alloc_arcdev +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xa9f9359d arc_proto_default +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xd22ab221 arc_raw_proto +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x0b4b9a33 com20020_found +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x488ef2ac com20020_check +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x1e209750 cxgb3_insert_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x221eb01d t3_l2t_get +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x24dfd24f cxgb3_remove_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x306cfa95 cxgb3_alloc_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x470f52d0 t3_l2t_send_slow +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x4796f0a3 cxgb3_ofld_send +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x51e09827 t3_l2e_free +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x63054854 cxgb3_unregister_client +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x744f76c9 cxgb3_free_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8b7b1f57 cxgb3_free_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8e0a1e3b t3_register_cpl_handler +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x98f460c1 dev2t3cdev +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xb813480d t3_l2t_send_event +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xc91b78a6 cxgb3_alloc_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xd3fb3028 cxgb3_queue_tid_release +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xf78c8e0b cxgb3_register_client +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x3424801c hdlcdrv_transmitter +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x9079baf8 hdlcdrv_unregister +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x9b594ea0 hdlcdrv_receiver +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xc72bca8f hdlcdrv_register +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xfe3aa16a hdlcdrv_arbitrate +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x01bd46bc sirdev_write_complete +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x095545f9 sirdev_raw_write +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x105de418 irda_unregister_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x2cb62110 sirdev_get_instance +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x9b594077 sirdev_set_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x9deffbe7 irda_register_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xbd94bb98 sirdev_put_instance +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xbed04329 sirdev_raw_read +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xd70a73fd sirdev_receive +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf6f49d0e sirdev_set_dtr_rts +EXPORT_SYMBOL drivers/net/mii 0x2848f244 generic_mii_ioctl +EXPORT_SYMBOL drivers/net/mii 0x6249df60 mii_check_media +EXPORT_SYMBOL drivers/net/mii 0x7c4fbfe8 mii_check_link +EXPORT_SYMBOL drivers/net/mii 0x86f7a969 mii_nway_restart +EXPORT_SYMBOL drivers/net/mii 0x9b9e1ccf mii_ethtool_sset +EXPORT_SYMBOL drivers/net/mii 0xb496f252 mii_check_gmii_support +EXPORT_SYMBOL drivers/net/mii 0xc2475d92 mii_ethtool_gset +EXPORT_SYMBOL drivers/net/mii 0xe64abc8a mii_link_ok +EXPORT_SYMBOL drivers/net/phy/libphy 0x21959176 phy_device_create +EXPORT_SYMBOL drivers/net/phy/libphy 0x2f6ce079 phy_write +EXPORT_SYMBOL drivers/net/phy/libphy 0x320fe178 phy_stop_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x3839b61c genphy_config_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0x3d2cd3d5 phy_register_fixup_for_uid +EXPORT_SYMBOL drivers/net/phy/libphy 0x405df8ed phy_disconnect +EXPORT_SYMBOL drivers/net/phy/libphy 0x42b91e7c phy_disable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x479c38ed phy_stop +EXPORT_SYMBOL drivers/net/phy/libphy 0x4d233e89 phy_driver_unregister +EXPORT_SYMBOL drivers/net/phy/libphy 0x4f272b5a get_phy_id +EXPORT_SYMBOL drivers/net/phy/libphy 0x55870ae0 phy_mii_ioctl +EXPORT_SYMBOL drivers/net/phy/libphy 0x5a021596 phy_scan_fixups +EXPORT_SYMBOL drivers/net/phy/libphy 0x5fed0a60 genphy_update_link +EXPORT_SYMBOL drivers/net/phy/libphy 0x687cd8fe phy_print_status +EXPORT_SYMBOL drivers/net/phy/libphy 0x69a8ae1d phy_driver_register +EXPORT_SYMBOL drivers/net/phy/libphy 0x6b174600 phy_ethtool_gset +EXPORT_SYMBOL drivers/net/phy/libphy 0x7455a58a phy_register_fixup +EXPORT_SYMBOL drivers/net/phy/libphy 0x8c8198b0 phy_attach +EXPORT_SYMBOL drivers/net/phy/libphy 0x952aff79 mdiobus_register +EXPORT_SYMBOL drivers/net/phy/libphy 0x97150601 mdio_bus_type +EXPORT_SYMBOL drivers/net/phy/libphy 0x9d9e6ab6 phy_start +EXPORT_SYMBOL drivers/net/phy/libphy 0xa2e83f0a phy_enable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0xa3ddee4d genphy_read_status +EXPORT_SYMBOL drivers/net/phy/libphy 0xa4c7df96 phy_sanitize_settings +EXPORT_SYMBOL drivers/net/phy/libphy 0xa71e789f phy_register_fixup_for_id +EXPORT_SYMBOL drivers/net/phy/libphy 0xbc102371 genphy_config_advert +EXPORT_SYMBOL drivers/net/phy/libphy 0xca6d7038 phy_read +EXPORT_SYMBOL drivers/net/phy/libphy 0xcef8c767 phy_start_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0xe7edfe08 phy_start_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0xed7bef1e phy_detach +EXPORT_SYMBOL drivers/net/phy/libphy 0xf17cec8a phy_ethtool_sset +EXPORT_SYMBOL drivers/net/phy/libphy 0xfe6ecdce phy_connect +EXPORT_SYMBOL drivers/net/phy/libphy 0xfff8715d mdiobus_unregister +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x024be098 free_mdio_bitbang +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0xcd11f89d alloc_mdio_bitbang +EXPORT_SYMBOL drivers/net/ppp_generic 0x3a8aa663 ppp_register_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0x5319c35b ppp_channel_index +EXPORT_SYMBOL drivers/net/ppp_generic 0x93424a59 ppp_unit_number +EXPORT_SYMBOL drivers/net/ppp_generic 0x936d9373 ppp_unregister_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0xa42e5fbc ppp_unregister_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0xa7838c80 ppp_register_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0xdd1c61be ppp_input +EXPORT_SYMBOL drivers/net/ppp_generic 0xe27e0fc7 ppp_output_wakeup +EXPORT_SYMBOL drivers/net/ppp_generic 0xf373c5e4 ppp_input_error +EXPORT_SYMBOL drivers/net/pppox 0x6233f183 pppox_unbind_sock +EXPORT_SYMBOL drivers/net/pppox 0x76bbf10d pppox_ioctl +EXPORT_SYMBOL drivers/net/pppox 0xe0ff7a18 unregister_pppox_proto +EXPORT_SYMBOL drivers/net/pppox 0xfaa0101f register_pppox_proto +EXPORT_SYMBOL drivers/net/slhc 0x0ff2b602 slhc_compress +EXPORT_SYMBOL drivers/net/slhc 0x23c8f257 slhc_uncompress +EXPORT_SYMBOL drivers/net/slhc 0xa63d85ab slhc_remember +EXPORT_SYMBOL drivers/net/slhc 0xb5ca1c46 slhc_free +EXPORT_SYMBOL drivers/net/slhc 0xdfc5169b slhc_init +EXPORT_SYMBOL drivers/net/slhc 0xe8794ce1 slhc_toss +EXPORT_SYMBOL drivers/net/sungem_phy 0x67bd82e2 mii_phy_probe +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x518fcbfb tms380tr_interrupt +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x7b3a9942 tms380tr_open +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xadeea5c6 tmsdev_init +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd2328794 tms380tr_wait +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd9ccfda2 tms380tr_close +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xe77a2924 tmsdev_term +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x38da4725 cycx_intr +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x62be23ea cycx_setup +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x66a4c4e6 cycx_down +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x968458a6 cycx_peek +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xb6f383de cycx_poke +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xfe7cd576 cycx_exec +EXPORT_SYMBOL drivers/net/wan/hdlc 0x168b67dc hdlc_ioctl +EXPORT_SYMBOL drivers/net/wan/hdlc 0x313180e2 unregister_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x44985964 unregister_hdlc_device +EXPORT_SYMBOL drivers/net/wan/hdlc 0x6c8cbed7 attach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x764be7d6 alloc_hdlcdev +EXPORT_SYMBOL drivers/net/wan/hdlc 0x929e55a2 hdlc_open +EXPORT_SYMBOL drivers/net/wan/hdlc 0xdabbbb1a register_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xf1c2c3b3 detach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xf5cb1410 hdlc_close +EXPORT_SYMBOL drivers/net/wan/syncppp 0x25afcc18 sppp_close +EXPORT_SYMBOL drivers/net/wan/syncppp 0x43f173d0 sppp_detach +EXPORT_SYMBOL drivers/net/wan/syncppp 0xa1835f19 sppp_open +EXPORT_SYMBOL drivers/net/wan/syncppp 0xb1d72514 sppp_attach +EXPORT_SYMBOL drivers/net/wan/syncppp 0xb2e41e15 sppp_do_ioctl +EXPORT_SYMBOL drivers/net/wan/syncppp 0xcd786ec4 sppp_reopen +EXPORT_SYMBOL drivers/net/wireless/airo 0x52c53545 stop_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0x7a9b1ba7 reset_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0xcc89e58c init_airo_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0x4e560edf init_atmel_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0x8feecae0 atmel_open +EXPORT_SYMBOL drivers/net/wireless/atmel 0xb204b860 stop_atmel_card +EXPORT_SYMBOL drivers/net/wireless/hermes 0x4196c38b hermes_write_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xc60b5e9e hermes_bap_pwrite +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd38d8ae2 hermes_read_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd3f714e5 hermes_bap_pread +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5168829 hermes_allocate +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5336e5d hermes_init +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd54e219d hermes_docmd_wait +EXPORT_SYMBOL drivers/net/wireless/hermes 0xed47b224 hermes_struct_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x07dab74b hostap_get_porttype +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1723ac32 hostap_set_multicast_list_queue +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x19beae3b hostap_80211_ops +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1e7e25ac hostap_setup_dev +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x206810aa hostap_set_hostapd +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x2c8e4f1c hostap_check_sta_fw_version +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x2ce7d503 hostap_remove_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x32b6f51a hostap_set_encryption +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x3b14fe60 prism2_update_comms_qual +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x3b685886 hostap_init_ap_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x5f24c0ca hostap_set_auth_algs +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x61b1589f hostap_info_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x62afc3ff hostap_80211_rx +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x64ee20d7 hostap_remove_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x6903f16c hostap_80211_get_hdrlen +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x8322c644 hostap_info_process +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x97bd26b4 hostap_init_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x9a95a55d hostap_add_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xa12ad27f hostap_dump_tx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xac1fd987 hostap_init_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb2a945e0 hostap_dump_rx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb465c923 hostap_handle_sta_tx_exc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb91c7434 hostap_master_start_xmit +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xbbab053a hostap_set_string +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xcc2acea3 hostap_get_stats +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xcecb4d9b hostap_free_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xd3a94bbb hostap_set_hostapd_sta +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xde83b774 hostap_set_antsel +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xe8e3ae57 hostap_set_word +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xef4374f0 hostap_set_roaming +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0135ca34 iwlcore_eeprom_verify_signature +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x01adaa66 iwl_eeprom_check_version +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x03748154 iwlcore_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x04694b5b iwl_dump_nic_error_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x07a9165d iwl_set_rxon_channel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0a29c0aa iwl_get_ra_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0a95b247 iwl_rx_queue_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x11df399d iwl_rxq_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1d77b399 iwl_bcast_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1fc0dc90 iwl_send_cmd_pdu +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x23d039ec iwl_find_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x261c6c99 iwl_sta_modify_enable_tid_tx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2c16665e iwl_init_sensitivity +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2cb2b346 iwl_power_initialize +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2d62f769 iwl_rx_queue_restock +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2dff3694 iwl_set_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2f578647 iwl_dump_nic_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2f922f63 iwl_power_set_system_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x302ada75 iwl_init_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x34bb0e7c iwl_scan_initiate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x37f0008a iwl_hw_detect +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x394b37d2 iwl_rx_queue_reset +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x39fddf1a iwl_set_tx_power +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x3b7aa44e iwl_setup_rx_scan_handlers +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x41dc3260 iwl_rx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4231e9b3 iwl_scan_cancel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4272aaf8 iwl_rx_reply_rx_phy +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x46db6e10 iwl_send_statistics_request +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4826c886 iwl_rfkill_set_hw_state +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x482cad8e iwl_rfkill_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4cbcbbbc iwl_set_hw_params +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x524ea92c iwl_reset_qos +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5519e0bc iwl_hw_nic_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x577bb379 iwl_hw_txq_free_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5a0875cd iwl_send_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5bb57fdb iwl_rfkill_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5c9922bb iwl_set_rxon_ht +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5d6836b1 iwl_tx_cmd_complete +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5e901399 iwl_txq_ctx_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5e96742b iwl_eeprom_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5ea18796 iwl_remove_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x60774702 iwl_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x60830157 iwlcore_eeprom_release_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6210ae51 iwl_power_disable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x64b9825f iwl_verify_ucode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6724128d iwl_rx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x705f7f82 iwlcore_eeprom_acquire_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x746a58d7 iwl_eeprom_get_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x761c875a iwl_send_static_wepkey_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x79a660f2 iwl_txq_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7ea29677 iwl_eeprom_query16 +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7f6d9336 iwl_leds_register +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7f9c9613 iwl_rx_missed_beacon_notif +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7fe66bb5 iwl_rx_queue_alloc +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x816388e4 iwl_print_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x81a72aef iwl_tx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x81bfef37 iwl_send_cmd_sync +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x82ff5d6a iwl_power_set_user_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8320b217 iwl_power_temperature_change +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x83613cb5 iwl_set_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8670273d iwl_hwrate_to_plcp_idx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x87be01d8 iwl_remove_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x898c4a82 iwl_rx_statistics +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8bfba80c iwl_send_cmd_pdu_async +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x92e02888 iwl_txq_check_empty +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x93a8e5f9 iwl_get_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9d00da6f iwl_power_enable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9ed43f1a iwl_rx_reply_compressed_ba +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa09e6339 iwl_eeprom_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa356e249 iwl_rx_allocate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xabd98677 iwl_tx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb1231cf2 iwl_tx_skb +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb22ad505 iwl_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb2b511f6 iwl_rxon_add_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb38a1e41 iwl_escape_essid +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb42ccae2 iwl_setup_scan_deferred_work +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb56e4d4c iwl_hwrate_to_tx_control +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb932f2e8 iwl_radio_kill_sw_enable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc282e72d iwl_free_calib_results +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc4242b45 iwl_radio_kill_sw_disable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc59af457 iwl_rx_reply_rx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc64b528f iwl_send_add_sta +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc741d151 iwl_uninit_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc81a2fdb iwl_remove_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc8f29f24 iwl_scan_cancel_timeout +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcabc5050 iwl_power_update_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcae98c25 iwl_alloc_all +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcbaf4931 get_cmd_string +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcddee4fa iwl_leds_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xce299d66 iwl_is_fat_tx_allowed +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd4572b93 iwl_set_rxon_chain +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xda7dbf63 iwl_get_channel_info +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdbc2fe15 iwl_reset_run_time_calib +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdebe1c6c iwl_rf_kill_ct_config +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdfc2a675 iwl_init_channel_map +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe0996307 iwl_rx_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe1417de9 iwl_sensitivity_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe1a4f563 iwl_clear_stations_table +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe30ce6d0 iwl_tx_queue_reclaim +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe7ce5d70 iwl_rates +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe81caeac iwl_add_station_flags +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xecba6dba iwl_send_lq_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xed1ea679 iwl_hw_txq_attach_buf_to_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf0a152b9 iwl_chain_noise_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf3f1212a iwl_rx_replenish +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfc379829 iwl_rx_queue_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfc5028c2 iwl_setup_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfd0577e7 iwl_hw_txq_ctx_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfd7795d9 iwl_leds_background +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x08e5d024 free_orinocodev +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x099c818d __orinoco_up +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x1131a8cc orinoco_reinit_firmware +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x1a9d334a orinoco_interrupt +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xa5e061bb __orinoco_down +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xbc301f55 alloc_orinocodev +EXPORT_SYMBOL drivers/parport/parport 0x01da3f33 parport_get_port +EXPORT_SYMBOL drivers/parport/parport 0x07c3058b parport_wait_event +EXPORT_SYMBOL drivers/parport/parport 0x106d36b3 parport_remove_port +EXPORT_SYMBOL drivers/parport/parport 0x170fab7e parport_announce_port +EXPORT_SYMBOL drivers/parport/parport 0x1dbe8d84 parport_irq_handler +EXPORT_SYMBOL drivers/parport/parport 0x1ea6ca0c parport_ieee1284_epp_read_addr +EXPORT_SYMBOL drivers/parport/parport 0x21512774 parport_ieee1284_epp_write_data +EXPORT_SYMBOL drivers/parport/parport 0x25235d0c parport_ieee1284_write_compat +EXPORT_SYMBOL drivers/parport/parport 0x2e8f7fe4 parport_unregister_device +EXPORT_SYMBOL drivers/parport/parport 0x3b750726 parport_ieee1284_ecp_write_data +EXPORT_SYMBOL drivers/parport/parport 0x440a8813 parport_ieee1284_ecp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0x4823910a parport_negotiate +EXPORT_SYMBOL drivers/parport/parport 0x4a6f510c parport_write +EXPORT_SYMBOL drivers/parport/parport 0x4c59e0a9 parport_unregister_driver +EXPORT_SYMBOL drivers/parport/parport 0x4d2a941b parport_ieee1284_interrupt +EXPORT_SYMBOL drivers/parport/parport 0x4d2b97b2 parport_find_base +EXPORT_SYMBOL drivers/parport/parport 0x517bfccb parport_claim +EXPORT_SYMBOL drivers/parport/parport 0x5e2ea841 parport_ieee1284_epp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0x75315cd6 parport_register_device +EXPORT_SYMBOL drivers/parport/parport 0x75718816 parport_ieee1284_epp_read_data +EXPORT_SYMBOL drivers/parport/parport 0x842f8e92 parport_read +EXPORT_SYMBOL drivers/parport/parport 0x875f7f20 parport_register_driver +EXPORT_SYMBOL drivers/parport/parport 0xa352a87f parport_wait_peripheral +EXPORT_SYMBOL drivers/parport/parport 0xade28868 parport_put_port +EXPORT_SYMBOL drivers/parport/parport 0xb38a2817 parport_release +EXPORT_SYMBOL drivers/parport/parport 0xb77b755b parport_ieee1284_ecp_read_data +EXPORT_SYMBOL drivers/parport/parport 0xbeaea3ab parport_find_number +EXPORT_SYMBOL drivers/parport/parport 0xd2f75fe1 parport_register_port +EXPORT_SYMBOL drivers/parport/parport 0xd96f9dd1 parport_ieee1284_read_nibble +EXPORT_SYMBOL drivers/parport/parport 0xde31b620 parport_ieee1284_read_byte +EXPORT_SYMBOL drivers/parport/parport 0xdfa3aae0 parport_claim_or_block +EXPORT_SYMBOL drivers/parport/parport 0xf5d0a225 parport_set_timeout +EXPORT_SYMBOL drivers/parport/parport_pc 0x8e8e369d parport_pc_probe_port +EXPORT_SYMBOL drivers/parport/parport_pc 0xb96b90a2 parport_pc_unregister_port +EXPORT_SYMBOL drivers/pci/hotplug/pci_hotplug 0xa8b32752 acpi_get_hp_hw_control_from_firmware +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x1afd903d pcmcia_release_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x5818bb87 pcmcia_modify_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x5885e727 pcmcia_request_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x5af01c8f cs_error +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x622f29a8 pcmcia_get_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x650c7270 pcmcia_request_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x80b5b39f pcmcia_get_configuration_info +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x833ea096 pcmcia_map_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x8a57fdbe pcmcia_dev_present +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa4cd3270 pcmcia_unregister_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa58f872e pcmcia_disable_device +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xd4ce007e pcmcia_get_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xd795491b pcmcia_request_io +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xda549c83 pcmcia_access_configuration_register +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xe769eebd pcmcia_register_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf1d52cda pcmcia_request_irq +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x013f7e7d pcmcia_suspend_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x08725dfa pccard_static_ops +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0cffb5cd pcmcia_register_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0e3c978f pcmcia_read_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x1962608d pcmcia_insert_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x212db8d2 pcmcia_socket_list +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x245ac0ec pcmcia_replace_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x26016f30 pccard_reset_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2f7bbea9 pccard_read_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x465436dd pcmcia_find_io_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x4f5b6900 pcmcia_unregister_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x500d7c55 release_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x51f754ea pccard_validate_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x5d33573b pcmcia_find_mem_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x748e1ffe pccard_register_pcmcia +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7b4b4878 pcmcia_write_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7be51a3a pcmcia_put_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7d38b250 pcmcia_eject_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x85886a77 pcmcia_get_socket_by_nr +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x8e6c9b6e pcmcia_parse_events +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x9426c54c pcmcia_validate_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x96311081 pcmcia_get_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x984fec08 pccard_get_tuple_data +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x9c20f5cc destroy_cis_cache +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa8df65b6 pcmcia_socket_list_rwsem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xac4393d6 pccard_get_first_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xb07305fc pcmcia_resume_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xb88ee4f8 pccard_get_next_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc701d244 pcmcia_adjust_io_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc9bd9f33 pcmcia_socket_dev_suspend +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcd2ac1c1 pccard_parse_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcf97f3bd dead_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xd99a9d91 pcmcia_socket_dev_resume +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xef98210c pcmcia_socket_class +EXPORT_SYMBOL drivers/pcmcia/rsrc_nonstatic 0x3dc632bb pccard_nonstatic_ops +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x2250c66e mraid_mm_adapter_app_handle +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x43a9a2fb mraid_mm_register_adp +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x512c956d mraid_mm_unregister_adp +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x0dceb204 qlogicfas408_disable_ints +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x2df4b8d2 qlogicfas408_abort +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x3fd8cd71 qlogicfas408_detect +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x5cd179e6 qlogicfas408_ihandl +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x98f5cb5f qlogicfas408_biosparam +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xa031bf80 qlogicfas408_queuecommand +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xbb493a86 qlogicfas408_info +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xdd2e6ee7 qlogicfas408_bus_reset +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xe76b3b20 qlogicfas408_get_chip_type +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xf2b95199 qlogicfas408_setup +EXPORT_SYMBOL drivers/scsi/raid_class 0x74521d97 raid_component_add +EXPORT_SYMBOL drivers/scsi/raid_class 0xb9d43cea raid_class_attach +EXPORT_SYMBOL drivers/scsi/raid_class 0xc81a5e2e raid_class_release +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0029528d scsi_req_abort_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x05b47c78 scsi_get_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0732beee scsi_release_buffers +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0b61bee9 __scsi_iterate_devices +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c65e73c scsi_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c6dc352 scsi_execute_req +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c8c9e99 scsi_show_extd_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0d603017 scsi_prep_state_check +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0e3220dc scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x11267875 scsi_extd_sense_format +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x178ffca2 __starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1877df5f scsi_bios_ptable +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1b9e0ff1 scsilun_to_int +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x22d373e2 scsi_set_medium_removal +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x23867cab scsi_dma_map +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x247e1e63 scsi_dma_unmap +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28a2ed02 scsi_build_sense_buffer +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2b0ba2b0 scsi_sense_desc_find +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2d89342a scsi_show_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2e0f998e scsi_cmd_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x300eafda scsi_add_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3066aeb7 scsi_block_when_processing_errors +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x344931fd scsi_setup_blk_pc_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x369df429 scsi_unblock_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x374e73da scsi_report_device_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x38b656aa scsi_execute +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3aea5e7c scsi_setup_fs_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x42de46df scsi_host_alloc +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x448c3b41 scsi_init_io +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x488afd76 scsi_eh_prep_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x48eecc07 scsi_free_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4afe9a77 scsi_partsize +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4be7b9f8 scsi_register +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4e9049ce scsi_device_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x52099a4a scsi_reset_provider +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x528b8942 scsi_get_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x52f15eca scsi_remove_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5628aa5f scsi_host_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x56c8799d scsi_kunmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x57307ab2 __scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x581d96f8 scsi_device_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5a306f55 scsi_eh_finish_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5a6aba68 scsi_target_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5d494632 __scsi_alloc_queue +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5dced60c scsi_is_target_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x624e347f scsi_rescan_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x668f4b87 scsi_device_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x66a8035c scsi_calculate_bounce_limit +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x670c19a8 scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x69d38ed9 __scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6a179967 scsi_register_interface +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6e9243a8 __scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72ea7b2d scsi_device_type +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x73e00570 scsi_host_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x74b10717 scsi_prep_return +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x77aaf6d6 scsi_free_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x796fc5ce scsi_get_sense_info_fld +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7a254164 scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7c6dac5b scsi_is_host_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7e95964d scsi_report_bus_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8480f33f scsi_block_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x89434821 scsi_adjust_queue_depth +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8fe88d6b scsi_eh_restore_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9005ff20 scsi_nonblockable_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x90c875e5 scsi_allocate_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9458e4fa starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96cd2b04 scsi_sense_key_string +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96e11a1e scsi_unregister +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x97ab7091 scsi_finish_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x990f9219 scsi_target_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9965476d scsi_command_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9c2becab scsi_print_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9cfd56c5 scsi_print_status +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9d8f2500 scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xae5fdbb9 scsi_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaf3dd7dc scsi_logging_level +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb2c19721 scsi_device_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb6c5a973 scsi_show_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb885c3e5 scsi_is_sdev_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbe2b257f scsi_register_driver +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc0461e47 scsi_track_queue_full +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc670568b scsi_test_unit_ready +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc718d81c __scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xca5dbc50 scsi_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xcd07ce23 scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd469399b scsi_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd7490608 scsi_remove_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd88bb189 scsi_scan_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe0f4f326 scsi_scan_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe698a699 scsi_host_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe9803ee9 scsi_device_get +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xea10212a int_to_scsilun +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xec60d9f3 scsicam_bios_param +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf00e540e scsi_mode_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf0297ef6 scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf4528073 scsi_kmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf811e69d scsi_eh_flush_done_q +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfadc0bb9 __scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfef96e23 __scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xff0f9365 scsi_host_get +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x0c20beb9 fc_vport_terminate +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x207967ef fc_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x24704f72 scsi_is_fc_vport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x298eacb4 fc_host_post_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x57ad192a scsi_is_fc_rport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x5da94aa1 fc_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x62ab4f57 fc_host_post_vendor_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x6a55c908 fc_remote_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x745f3ec6 fc_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x7954b1ea fc_get_event_number +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x80f130dd fc_remote_port_rolechg +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xb52616fe fc_remote_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x17fa5fba sas_port_add_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x184f2be1 sas_read_port_mode_page +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x25f04b11 sas_phy_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x44a32979 sas_phy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x4e1b054a sas_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x5cfbfed5 sas_end_device_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x60f26003 sas_port_mark_backlink +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x69493d8c sas_phy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x72ea52da sas_rphy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x7723d240 sas_remove_children +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x8684aaf0 sas_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x938ec9af sas_phy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x96682ec8 sas_rphy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x9dda2a6d sas_rphy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x9e1c94ff scsi_is_sas_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xa564007a sas_port_alloc_num +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xacc29bfd sas_rphy_remove +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xaf87b2bd sas_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xb2d45380 sas_expander_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xc9109ef9 sas_port_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xd1d98df5 scsi_is_sas_port +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xe2c96944 scsi_is_sas_rphy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xee9ae46f sas_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf018857f sas_port_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf36915fa sas_port_delete_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf6e59904 sas_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x04a9f029 spi_display_xfer_agreement +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x1c93783f spi_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x3686ea09 spi_print_msg +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xac639ccf spi_schedule_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xb20e3d70 spi_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xb50dbd9c spi_release_transport +EXPORT_SYMBOL drivers/ssb/ssb 0x11755805 __ssb_driver_register +EXPORT_SYMBOL drivers/ssb/ssb 0x1df7733c ssb_dma_alloc_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0x2c6c218f ssb_pcicore_dev_irqvecs_enable +EXPORT_SYMBOL drivers/ssb/ssb 0x4150a0a8 ssb_dma_translation +EXPORT_SYMBOL drivers/ssb/ssb 0x4b2d7d25 ssb_dma_free_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0x5d9b9ccb ssb_bus_powerup +EXPORT_SYMBOL drivers/ssb/ssb 0x62ba21e1 ssb_device_disable +EXPORT_SYMBOL drivers/ssb/ssb 0x6c1cc26e ssb_bus_may_powerdown +EXPORT_SYMBOL drivers/ssb/ssb 0x82d8b1fc ssb_clockspeed +EXPORT_SYMBOL drivers/ssb/ssb 0x96518487 ssb_driver_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0x9bf48d18 ssb_device_is_enabled +EXPORT_SYMBOL drivers/ssb/ssb 0xa5884ab9 ssb_dma_set_mask +EXPORT_SYMBOL drivers/ssb/ssb 0xac6d68a5 ssb_bus_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0xb5c1d190 ssb_device_enable +EXPORT_SYMBOL drivers/ssb/ssb 0xc0512e0f ssb_admatch_base +EXPORT_SYMBOL drivers/ssb/ssb 0xc523c4af ssb_set_devtypedata +EXPORT_SYMBOL drivers/ssb/ssb 0xca268be1 ssb_bus_suspend +EXPORT_SYMBOL drivers/ssb/ssb 0xd481192b ssb_admatch_size +EXPORT_SYMBOL drivers/ssb/ssb 0xdb368a39 ssb_pcihost_register +EXPORT_SYMBOL drivers/ssb/ssb 0xe467d159 ssb_bus_resume +EXPORT_SYMBOL drivers/ssb/ssb 0xeda86a81 ssb_bus_pcibus_register +EXPORT_SYMBOL drivers/telephony/ixj 0xdf7bffa2 ixj_pcmcia_probe +EXPORT_SYMBOL drivers/telephony/phonedev 0xbd41682f phone_unregister_device +EXPORT_SYMBOL drivers/telephony/phonedev 0xc87ed38f phone_register_device +EXPORT_SYMBOL drivers/usb/gadget/net2280 0x43f049d1 usb_gadget_unregister_driver +EXPORT_SYMBOL drivers/usb/gadget/net2280 0xc824e761 usb_gadget_register_driver +EXPORT_SYMBOL drivers/usb/gadget/net2280 0xecb8a987 net2280_set_fifo_mode +EXPORT_SYMBOL drivers/usb/host/sl811-hcd 0x7af6ecc6 sl811h_driver +EXPORT_SYMBOL drivers/usb/serial/usbserial 0x182ea30f usb_serial_resume +EXPORT_SYMBOL drivers/usb/serial/usbserial 0x2fcf7bb2 usb_serial_suspend +EXPORT_SYMBOL drivers/video/backlight/corgi_bl 0xc86baa7c corgibl_limit_intensity +EXPORT_SYMBOL drivers/video/backlight/lcd 0x15d3a075 lcd_device_unregister +EXPORT_SYMBOL drivers/video/backlight/lcd 0x55d0cd14 lcd_device_register +EXPORT_SYMBOL drivers/video/console/bitblit 0xafc935fc fbcon_set_bitops +EXPORT_SYMBOL drivers/video/console/font 0x09c8eb55 font_vga_8x16 +EXPORT_SYMBOL drivers/video/console/font 0xbb99125c get_default_font +EXPORT_SYMBOL drivers/video/console/font 0xf7584a9c find_font +EXPORT_SYMBOL drivers/video/console/softcursor 0x3f16bfb7 soft_cursor +EXPORT_SYMBOL drivers/video/console/tileblit 0x444d5d22 fbcon_set_tileops +EXPORT_SYMBOL drivers/video/cyber2000fb 0x0cc3ede5 cyber2000fb_detach +EXPORT_SYMBOL drivers/video/cyber2000fb 0x2666e329 cyber2000fb_enable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0x45c0f565 cyber2000fb_disable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0x50ffc488 cyber2000fb_get_fb_var +EXPORT_SYMBOL drivers/video/cyber2000fb 0xefb5bae4 cyber2000fb_attach +EXPORT_SYMBOL drivers/video/display/display 0x0a72c73a display_device_unregister +EXPORT_SYMBOL drivers/video/display/display 0x9c5117c6 display_device_register +EXPORT_SYMBOL drivers/video/macmodes 0x08ed0b62 mac_vmode_to_var +EXPORT_SYMBOL drivers/video/macmodes 0x31898a77 mac_find_mode +EXPORT_SYMBOL drivers/video/macmodes 0xe2304303 mac_map_monitor_sense +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x3b00873b matroxfb_g450_setclk +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x51ca34ec g450_mnp2f +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x878fa7f2 matroxfb_g450_setpll_cond +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x185cb0d7 matrox_mystique +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x2972630b matrox_G100 +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xb55b6a10 DAC1064_global_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xe77dfead DAC1064_global_restore +EXPORT_SYMBOL drivers/video/matrox/matroxfb_Ti3026 0x56c4d649 matrox_millennium +EXPORT_SYMBOL drivers/video/matrox/matroxfb_accel 0x9aba1999 matrox_cfbX_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x174f91b9 matroxfb_unregister_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x843547be matroxfb_register_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xafffd247 matroxfb_wait_for_sync +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xfb31ba10 matroxfb_enable_irq +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x34974c30 matroxfb_g450_shutdown +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0xab3605bb matroxfb_g450_connect +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x161c794b matroxfb_vgaHWrestore +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x25cf8049 matroxfb_PLL_calcclock +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x3a0d557d matroxfb_vgaHWinit +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x6cd16961 matroxfb_DAC_in +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x9a396892 matroxfb_DAC_out +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xabd8e427 matroxfb_var2my +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xfd58e69e matroxfb_read_pins +EXPORT_SYMBOL drivers/video/output 0xb2100689 video_output_unregister +EXPORT_SYMBOL drivers/video/output 0xdd202b9e video_output_register +EXPORT_SYMBOL drivers/video/sis/sisfb 0x3037658e sis_malloc +EXPORT_SYMBOL drivers/video/sis/sisfb 0x454a3cf0 sis_free +EXPORT_SYMBOL drivers/video/svgalib 0x00d1fce9 svga_set_default_seq_regs +EXPORT_SYMBOL drivers/video/svgalib 0x07b3da30 svga_wseq_multi +EXPORT_SYMBOL drivers/video/svgalib 0x1b95c56a svga_check_timings +EXPORT_SYMBOL drivers/video/svgalib 0x38cf5f5f svga_tilecopy +EXPORT_SYMBOL drivers/video/svgalib 0x63e898d1 svga_set_default_crt_regs +EXPORT_SYMBOL drivers/video/svgalib 0x7a3ae959 svga_wcrt_multi +EXPORT_SYMBOL drivers/video/svgalib 0x80408443 svga_set_timings +EXPORT_SYMBOL drivers/video/svgalib 0x849d0aed svga_tileblit +EXPORT_SYMBOL drivers/video/svgalib 0x8fa8438b svga_set_textmode_vga_regs +EXPORT_SYMBOL drivers/video/svgalib 0xa4f9b78c svga_get_caps +EXPORT_SYMBOL drivers/video/svgalib 0xab3b22ad svga_set_default_gfx_regs +EXPORT_SYMBOL drivers/video/svgalib 0xb87a2c50 svga_settile +EXPORT_SYMBOL drivers/video/svgalib 0xbd1b6420 svga_tilefill +EXPORT_SYMBOL drivers/video/svgalib 0xdad682b1 svga_set_default_atc_regs +EXPORT_SYMBOL drivers/video/svgalib 0xec83c473 svga_match_format +EXPORT_SYMBOL drivers/video/svgalib 0xef774f5d svga_compute_pll +EXPORT_SYMBOL drivers/video/svgalib 0xf03a2ade svga_get_tilemax +EXPORT_SYMBOL drivers/video/svgalib 0xf68bee68 svga_tilecursor +EXPORT_SYMBOL drivers/video/syscopyarea 0xd62472cb sys_copyarea +EXPORT_SYMBOL drivers/video/sysfillrect 0xeab8161b sys_fillrect +EXPORT_SYMBOL drivers/video/sysimgblt 0x6581f331 sys_imageblit +EXPORT_SYMBOL drivers/video/vgastate 0x686de290 restore_vga +EXPORT_SYMBOL drivers/video/vgastate 0xe7a2620e save_vga +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x6036e6b3 w1_ds2760_read +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x73b3cf34 w1_ds2760_write +EXPORT_SYMBOL drivers/w1/wire 0x8cf61660 w1_add_master_device +EXPORT_SYMBOL drivers/w1/wire 0xb10f92e8 w1_register_family +EXPORT_SYMBOL drivers/w1/wire 0xb959d36f w1_unregister_family +EXPORT_SYMBOL drivers/w1/wire 0xcda061c0 w1_remove_master_device +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x04e133fc iTCO_vendor_check_noreboot_on +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x672c9d44 iTCO_vendor_pre_keepalive +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa78bd894 iTCO_vendor_pre_set_heartbeat +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa8d6daac iTCO_vendor_pre_start +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xd0efe320 iTCO_vendor_pre_stop +EXPORT_SYMBOL fs/configfs/configfs 0x24517370 config_item_put +EXPORT_SYMBOL fs/configfs/configfs 0x27e53180 config_group_find_item +EXPORT_SYMBOL fs/configfs/configfs 0x687e9fa1 configfs_depend_item +EXPORT_SYMBOL fs/configfs/configfs 0x778209f5 config_group_init +EXPORT_SYMBOL fs/configfs/configfs 0x7e16609c configfs_register_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0x9290e281 config_item_init +EXPORT_SYMBOL fs/configfs/configfs 0x9397eb44 configfs_unregister_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0xa2501a2c config_item_set_name +EXPORT_SYMBOL fs/configfs/configfs 0xae812660 config_group_init_type_name +EXPORT_SYMBOL fs/configfs/configfs 0xb06f4821 config_item_get +EXPORT_SYMBOL fs/configfs/configfs 0xd1279084 config_item_init_type_name +EXPORT_SYMBOL fs/configfs/configfs 0xe873e298 configfs_undepend_item +EXPORT_SYMBOL fs/jbd/jbd 0x00dac50b journal_dirty_data +EXPORT_SYMBOL fs/jbd/jbd 0x01bb16e9 journal_forget +EXPORT_SYMBOL fs/jbd/jbd 0x1c39270a journal_clear_err +EXPORT_SYMBOL fs/jbd/jbd 0x1e073f22 journal_check_used_features +EXPORT_SYMBOL fs/jbd/jbd 0x1f3057e5 journal_force_commit +EXPORT_SYMBOL fs/jbd/jbd 0x2863e016 journal_ack_err +EXPORT_SYMBOL fs/jbd/jbd 0x2e39226f journal_stop +EXPORT_SYMBOL fs/jbd/jbd 0x31abbba9 journal_update_format +EXPORT_SYMBOL fs/jbd/jbd 0x37f663a5 journal_init_inode +EXPORT_SYMBOL fs/jbd/jbd 0x39bf3327 journal_load +EXPORT_SYMBOL fs/jbd/jbd 0x555537cc journal_lock_updates +EXPORT_SYMBOL fs/jbd/jbd 0x57e0be96 journal_extend +EXPORT_SYMBOL fs/jbd/jbd 0x5882cc65 journal_blocks_per_page +EXPORT_SYMBOL fs/jbd/jbd 0x5954a9cf journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd/jbd 0x610026ae journal_abort +EXPORT_SYMBOL fs/jbd/jbd 0x672e1587 journal_get_undo_access +EXPORT_SYMBOL fs/jbd/jbd 0x67d37f16 journal_start_commit +EXPORT_SYMBOL fs/jbd/jbd 0x766991a5 journal_get_create_access +EXPORT_SYMBOL fs/jbd/jbd 0x78aaecbd journal_dirty_metadata +EXPORT_SYMBOL fs/jbd/jbd 0x7b362adc journal_force_commit_nested +EXPORT_SYMBOL fs/jbd/jbd 0x83fa644f journal_restart +EXPORT_SYMBOL fs/jbd/jbd 0x8787e2c1 journal_set_features +EXPORT_SYMBOL fs/jbd/jbd 0x8bfbfdc7 journal_start +EXPORT_SYMBOL fs/jbd/jbd 0x9899aa58 journal_init_dev +EXPORT_SYMBOL fs/jbd/jbd 0x9cd3309e journal_check_available_features +EXPORT_SYMBOL fs/jbd/jbd 0x9d0c96a8 journal_release_buffer +EXPORT_SYMBOL fs/jbd/jbd 0x9ee58688 journal_invalidatepage +EXPORT_SYMBOL fs/jbd/jbd 0xa9a29255 journal_flush +EXPORT_SYMBOL fs/jbd/jbd 0xb7a774c9 journal_errno +EXPORT_SYMBOL fs/jbd/jbd 0xc0da59a2 log_wait_commit +EXPORT_SYMBOL fs/jbd/jbd 0xc63871c0 journal_get_write_access +EXPORT_SYMBOL fs/jbd/jbd 0xc896970f journal_unlock_updates +EXPORT_SYMBOL fs/jbd/jbd 0xcbd5fe6b journal_create +EXPORT_SYMBOL fs/jbd/jbd 0xdbe8d97a journal_revoke +EXPORT_SYMBOL fs/jbd/jbd 0xe5b1585d journal_destroy +EXPORT_SYMBOL fs/jbd/jbd 0xfa682948 journal_wipe +EXPORT_SYMBOL fs/jbd2/jbd2 0x01fb8f55 jbd2_journal_check_used_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x0974a3c4 jbd2_journal_init_dev +EXPORT_SYMBOL fs/jbd2/jbd2 0x0dc9ad99 jbd2_journal_force_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x13b5ef9e jbd2_journal_invalidatepage +EXPORT_SYMBOL fs/jbd2/jbd2 0x14059e51 jbd2_journal_force_commit_nested +EXPORT_SYMBOL fs/jbd2/jbd2 0x1bffe5df jbd2_journal_release_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x1ff4f5f3 jbd2_journal_stop +EXPORT_SYMBOL fs/jbd2/jbd2 0x221930b3 jbd2_journal_abort +EXPORT_SYMBOL fs/jbd2/jbd2 0x28d587eb jbd2_journal_get_write_access +EXPORT_SYMBOL fs/jbd2/jbd2 0x28f3fbf5 jbd2_journal_start +EXPORT_SYMBOL fs/jbd2/jbd2 0x306d08eb jbd2_journal_begin_ordered_truncate +EXPORT_SYMBOL fs/jbd2/jbd2 0x356dcbc9 jbd2_journal_lock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0x41de345a jbd2_journal_forget +EXPORT_SYMBOL fs/jbd2/jbd2 0x5cc50e9c jbd2_journal_init_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x68eb85c8 jbd2_journal_set_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x78812e6a jbd2_journal_check_available_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x78cd649e jbd2_journal_file_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x7df2d281 jbd2_journal_update_format +EXPORT_SYMBOL fs/jbd2/jbd2 0x7f7a0056 jbd2_journal_release_buffer +EXPORT_SYMBOL fs/jbd2/jbd2 0x8787db36 jbd2_journal_start_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x8c7a6d67 jbd2_journal_load +EXPORT_SYMBOL fs/jbd2/jbd2 0x9b41cf42 jbd2_journal_errno +EXPORT_SYMBOL fs/jbd2/jbd2 0xa613479b jbd2_journal_destroy +EXPORT_SYMBOL fs/jbd2/jbd2 0xa85b996c jbd2_journal_extend +EXPORT_SYMBOL fs/jbd2/jbd2 0xb211420d jbd2_journal_ack_err +EXPORT_SYMBOL fs/jbd2/jbd2 0xb2abd8e8 jbd2_journal_init_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0xb8919682 jbd2_journal_wipe +EXPORT_SYMBOL fs/jbd2/jbd2 0xb937ca8d jbd2_journal_flush +EXPORT_SYMBOL fs/jbd2/jbd2 0xba79ad64 jbd2_journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd2/jbd2 0xc6b756ef jbd2_journal_get_create_access +EXPORT_SYMBOL fs/jbd2/jbd2 0xc80311f8 jbd2_journal_clear_features +EXPORT_SYMBOL fs/jbd2/jbd2 0xca5ab178 jbd2_journal_dirty_metadata +EXPORT_SYMBOL fs/jbd2/jbd2 0xd6f64fed jbd2_journal_get_undo_access +EXPORT_SYMBOL fs/jbd2/jbd2 0xe2167d62 jbd2_journal_restart +EXPORT_SYMBOL fs/jbd2/jbd2 0xe33f15f4 jbd2_journal_unlock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0xeb72ed29 jbd2_journal_revoke +EXPORT_SYMBOL fs/jbd2/jbd2 0xed36ee95 jbd2_journal_clear_err +EXPORT_SYMBOL fs/jbd2/jbd2 0xf346a7e4 jbd2_journal_create +EXPORT_SYMBOL fs/jbd2/jbd2 0xfa72d811 jbd2_log_wait_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0xff6b6d9c jbd2_journal_blocks_per_page +EXPORT_SYMBOL fs/lockd/lockd 0x976e539e lockd_up +EXPORT_SYMBOL fs/lockd/lockd 0xa7b91a7b lockd_down +EXPORT_SYMBOL fs/lockd/lockd 0xad09c2db get_nfs_grace_period +EXPORT_SYMBOL fs/lockd/lockd 0xd332bd97 nlmsvc_ops +EXPORT_SYMBOL fs/mbcache 0x5752bb80 mb_cache_entry_alloc +EXPORT_SYMBOL fs/mbcache 0x5d19a21e mb_cache_entry_release +EXPORT_SYMBOL fs/mbcache 0x6c063a3f mb_cache_create +EXPORT_SYMBOL fs/mbcache 0x7b506b1d mb_cache_entry_find_first +EXPORT_SYMBOL fs/mbcache 0x86d1898b mb_cache_entry_insert +EXPORT_SYMBOL fs/mbcache 0x911efa55 mb_cache_entry_get +EXPORT_SYMBOL fs/mbcache 0x92ee083e mb_cache_entry_free +EXPORT_SYMBOL fs/mbcache 0xc8bb75df mb_cache_shrink +EXPORT_SYMBOL fs/mbcache 0xd5263820 mb_cache_destroy +EXPORT_SYMBOL fs/mbcache 0xedfe7ce7 mb_cache_entry_find_next +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0x33f37cff nfsacl_decode +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0x9fb9ee63 nfsacl_encode +EXPORT_SYMBOL fs/nfsd/nfsd 0x23f0a2c8 nfs4_acl_nfsv4_to_posix +EXPORT_SYMBOL fs/nfsd/nfsd 0x35e33c1e nfs4_acl_write_who +EXPORT_SYMBOL fs/nfsd/nfsd 0x46ffdc39 nfs4_acl_posix_to_nfsv4 +EXPORT_SYMBOL fs/nfsd/nfsd 0x5a157ae4 nfs4_acl_get_whotype +EXPORT_SYMBOL fs/nfsd/nfsd 0x96ce9bb4 nfs4_acl_new +EXPORT_SYMBOL fs/xfs/xfs 0xe8aac5be xfs_qmcore_xfs +EXPORT_SYMBOL lib/crc-ccitt 0x651c2313 crc_ccitt +EXPORT_SYMBOL lib/crc-ccitt 0x75811312 crc_ccitt_table +EXPORT_SYMBOL lib/crc-itu-t 0x276c7e62 crc_itu_t +EXPORT_SYMBOL lib/crc-itu-t 0xd29b009f crc_itu_t_table +EXPORT_SYMBOL lib/crc-t10dif 0x782acba5 crc_t10dif +EXPORT_SYMBOL lib/crc16 0x02a6ce5a crc16_table +EXPORT_SYMBOL lib/crc16 0x9aabc564 crc16 +EXPORT_SYMBOL lib/crc7 0xc086bfba crc7 +EXPORT_SYMBOL lib/crc7 0xd80c3603 crc7_syndrome_table +EXPORT_SYMBOL lib/libcrc32c 0x13c0c38e crc32c_le +EXPORT_SYMBOL lib/libcrc32c 0x41bcd8b3 crc32c_be +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x315c65fd zlib_deflateInit2 +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x48034724 zlib_deflateReset +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xaf64ad0d zlib_deflate +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf0caf44b zlib_deflate_workspacesize +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf741c793 zlib_deflateEnd +EXPORT_SYMBOL net/802/p8023 0x98df3c71 make_8023_client +EXPORT_SYMBOL net/802/p8023 0xaf85fb43 destroy_8023_client +EXPORT_SYMBOL net/9p/9pnet 0x00a6e1a5 p9_create_tclunk +EXPORT_SYMBOL net/9p/9pnet 0x0106a185 p9_create_tstat +EXPORT_SYMBOL net/9p/9pnet 0x088f914e p9_client_write +EXPORT_SYMBOL net/9p/9pnet 0x09745f8a p9_client_readn +EXPORT_SYMBOL net/9p/9pnet 0x0b26ff5a v9fs_unregister_trans +EXPORT_SYMBOL net/9p/9pnet 0x15779868 p9_set_tag +EXPORT_SYMBOL net/9p/9pnet 0x16a4e75b p9_client_stat +EXPORT_SYMBOL net/9p/9pnet 0x18d53221 p9_idpool_get +EXPORT_SYMBOL net/9p/9pnet 0x21523da9 p9_create_tattach +EXPORT_SYMBOL net/9p/9pnet 0x309767d8 p9_deserialize_stat +EXPORT_SYMBOL net/9p/9pnet 0x327cc194 p9_client_dirread +EXPORT_SYMBOL net/9p/9pnet 0x3303cfe4 p9_client_attach +EXPORT_SYMBOL net/9p/9pnet 0x34132d0a p9_idpool_put +EXPORT_SYMBOL net/9p/9pnet 0x342f88f4 p9_client_uwrite +EXPORT_SYMBOL net/9p/9pnet 0x35a2aa3c p9_idpool_create +EXPORT_SYMBOL net/9p/9pnet 0x3915524a p9_client_disconnect +EXPORT_SYMBOL net/9p/9pnet 0x3ba009e4 p9_client_clunk +EXPORT_SYMBOL net/9p/9pnet 0x3d73a797 p9_errstr2errno +EXPORT_SYMBOL net/9p/9pnet 0x465c4e6f p9_printfcall +EXPORT_SYMBOL net/9p/9pnet 0x507c9d70 p9_create_tauth +EXPORT_SYMBOL net/9p/9pnet 0x53db0a3c p9_client_create +EXPORT_SYMBOL net/9p/9pnet 0x570f8eba p9_client_walk +EXPORT_SYMBOL net/9p/9pnet 0x6461b8de p9_create_twrite +EXPORT_SYMBOL net/9p/9pnet 0x6f11c5c3 p9_create_twrite_u +EXPORT_SYMBOL net/9p/9pnet 0x71c7537d p9_create_tcreate +EXPORT_SYMBOL net/9p/9pnet 0x791bb250 p9_client_remove +EXPORT_SYMBOL net/9p/9pnet 0x81247f39 p9_create_tread +EXPORT_SYMBOL net/9p/9pnet 0x8432c83f p9_deserialize_fcall +EXPORT_SYMBOL net/9p/9pnet 0x94b7d5f8 p9_client_wstat +EXPORT_SYMBOL net/9p/9pnet 0x950e6b03 p9_create_twstat +EXPORT_SYMBOL net/9p/9pnet 0x9579c2fa p9_client_auth +EXPORT_SYMBOL net/9p/9pnet 0xa1998338 p9_client_read +EXPORT_SYMBOL net/9p/9pnet 0xa9536064 p9_create_tversion +EXPORT_SYMBOL net/9p/9pnet 0xadfd597a p9_create_tremove +EXPORT_SYMBOL net/9p/9pnet 0xbb0bb702 v9fs_get_trans_by_name +EXPORT_SYMBOL net/9p/9pnet 0xc1468893 p9_client_open +EXPORT_SYMBOL net/9p/9pnet 0xc3277dfd p9_idpool_destroy +EXPORT_SYMBOL net/9p/9pnet 0xdc894ac7 p9_create_twalk +EXPORT_SYMBOL net/9p/9pnet 0xe0c59d41 p9_client_destroy +EXPORT_SYMBOL net/9p/9pnet 0xe58a3360 p9_error_init +EXPORT_SYMBOL net/9p/9pnet 0xe6238993 v9fs_get_default_trans +EXPORT_SYMBOL net/9p/9pnet 0xf09b3efa p9_create_topen +EXPORT_SYMBOL net/9p/9pnet 0xf41bffb5 p9_client_uread +EXPORT_SYMBOL net/9p/9pnet 0xf85870ff v9fs_register_trans +EXPORT_SYMBOL net/9p/9pnet 0xfdbd83e3 p9_client_fcreate +EXPORT_SYMBOL net/9p/9pnet 0xff12c0b5 p9_idpool_check +EXPORT_SYMBOL net/9p/9pnet 0xfff27930 p9_create_tflush +EXPORT_SYMBOL net/appletalk/appletalk 0x095ef0cb atalk_find_dev_addr +EXPORT_SYMBOL net/appletalk/appletalk 0x0d8c69ba alloc_ltalkdev +EXPORT_SYMBOL net/appletalk/appletalk 0x3a21acba atrtr_get_dev +EXPORT_SYMBOL net/appletalk/appletalk 0xa744535e aarp_send_ddp +EXPORT_SYMBOL net/ax25/ax25 0x0479d44f ax25_findbyuid +EXPORT_SYMBOL net/ax25/ax25 0x06b81681 ax25_listen_register +EXPORT_SYMBOL net/ax25/ax25 0x10c1a07c ax25_rebuild_header +EXPORT_SYMBOL net/ax25/ax25 0x1681ad87 ax25_linkfail_release +EXPORT_SYMBOL net/ax25/ax25 0x1d7e38f9 ax25_hard_header +EXPORT_SYMBOL net/ax25/ax25 0x1ee6d5f5 ax25_send_frame +EXPORT_SYMBOL net/ax25/ax25 0x242852b9 ax25_uid_policy +EXPORT_SYMBOL net/ax25/ax25 0x3d2d82ec ax25_display_timer +EXPORT_SYMBOL net/ax25/ax25 0x4502c65a asc2ax +EXPORT_SYMBOL net/ax25/ax25 0x53dea1ff ax2asc +EXPORT_SYMBOL net/ax25/ax25 0x8ede9e26 ax25_protocol_release +EXPORT_SYMBOL net/ax25/ax25 0xc1444946 ax25cmp +EXPORT_SYMBOL net/ax25/ax25 0xc7b8aa0a ax25_listen_release +EXPORT_SYMBOL net/ax25/ax25 0xd271e5d5 ax25_linkfail_register +EXPORT_SYMBOL net/ax25/ax25 0xd43ecbf1 null_ax25_address +EXPORT_SYMBOL net/ax25/ax25 0xdd84f5c9 ax25_header_ops +EXPORT_SYMBOL net/ax25/ax25 0xee3bb3cf ax25_find_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0x038497df hci_register_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x05ef3f44 bt_sock_wait_state +EXPORT_SYMBOL net/bluetooth/bluetooth 0x0d2eaf0b hci_send_sco +EXPORT_SYMBOL net/bluetooth/bluetooth 0x1d268e4c bt_sock_register +EXPORT_SYMBOL net/bluetooth/bluetooth 0x27241618 hci_conn_encrypt +EXPORT_SYMBOL net/bluetooth/bluetooth 0x2eb51c2b hci_resume_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x4d9fc26b hci_unregister_proto +EXPORT_SYMBOL net/bluetooth/bluetooth 0x54fdef52 bt_sock_ioctl +EXPORT_SYMBOL net/bluetooth/bluetooth 0x57a538ea bt_accept_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0x58b6718d hci_conn_auth +EXPORT_SYMBOL net/bluetooth/bluetooth 0x5eafe9d5 bt_sock_poll +EXPORT_SYMBOL net/bluetooth/bluetooth 0x63941f93 hci_unregister_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6403d8bd hci_free_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6bfd4bbb bt_sock_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6c7c5c54 hci_suspend_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6d2bdf31 hci_alloc_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x7094f8ae bt_err +EXPORT_SYMBOL net/bluetooth/bluetooth 0x789c4247 hci_conn_change_link_key +EXPORT_SYMBOL net/bluetooth/bluetooth 0x7ec71991 bt_sock_link +EXPORT_SYMBOL net/bluetooth/bluetooth 0x9acb42c7 hci_recv_fragment +EXPORT_SYMBOL net/bluetooth/bluetooth 0x9c1c1d14 bt_accept_dequeue +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb75cdb2d bt_accept_enqueue +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb91ceb55 bt_sock_recvmsg +EXPORT_SYMBOL net/bluetooth/bluetooth 0xbceec2b5 hci_connect +EXPORT_SYMBOL net/bluetooth/bluetooth 0xc2066af0 batostr +EXPORT_SYMBOL net/bluetooth/bluetooth 0xcc1fb551 baswap +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe152e57a hci_register_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe679537c hci_send_acl +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe6fa0c83 hci_conn_switch_role +EXPORT_SYMBOL net/bluetooth/bluetooth 0xef0b516f hci_unregister_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf19294db bt_sock_unregister +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf1c0a40b hci_conn_check_link_mode +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf63251ef hci_get_route +EXPORT_SYMBOL net/bluetooth/bluetooth 0xfa1cf7a6 hci_register_proto +EXPORT_SYMBOL net/bluetooth/l2cap 0xfc31fe88 l2cap_load +EXPORT_SYMBOL net/bridge/bridge 0xabf5cde0 br_should_route_hook +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x29517baa ebt_register_watcher +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x2aa6073e ebt_unregister_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x46f147ea ebt_register_match +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x52beff71 ebt_unregister_watcher +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x80cc4b50 ebt_register_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x8bb86fcc ebt_register_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xa803b6fe ebt_unregister_match +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xcf18603c ebt_do_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xed463622 ebt_unregister_table +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1b0ba625 ieee80211_get_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1b859565 free_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1c978c78 ieee80211_wx_set_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1cebfbb2 ieee80211_channel_to_index +EXPORT_SYMBOL net/ieee80211/ieee80211 0x21cbe34f alloc_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0x227bbfb0 ieee80211_wx_get_scan +EXPORT_SYMBOL net/ieee80211/ieee80211 0x29f4b971 ieee80211_wx_get_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0x2b166f35 ieee80211_wx_set_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0x31837a27 ieee80211_channel_to_freq +EXPORT_SYMBOL net/ieee80211/ieee80211 0x378e1a24 ieee80211_get_channel_flags +EXPORT_SYMBOL net/ieee80211/ieee80211 0x3be20415 ieee80211_freq_to_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x5ade4306 ieee80211_get_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0xa9fb135f escape_essid +EXPORT_SYMBOL net/ieee80211/ieee80211 0xc4faef45 ieee80211_txb_free +EXPORT_SYMBOL net/ieee80211/ieee80211 0xcb7e3e55 ieee80211_rx_mgt +EXPORT_SYMBOL net/ieee80211/ieee80211 0xcc4fe16c ieee80211_rx +EXPORT_SYMBOL net/ieee80211/ieee80211 0xce841d66 ieee80211_is_valid_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0xd7d10093 ieee80211_set_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0xf26248ab ieee80211_wx_get_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x063fcd53 ieee80211_crypt_delayed_deinit +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x279e265f ieee80211_crypt_deinit_handler +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x443366e9 ieee80211_crypt_deinit_entries +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x5c6b905b ieee80211_get_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x92408820 ieee80211_register_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x98dd59fb ieee80211_unregister_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0xb13b48c6 ieee80211_crypt_quiescing +EXPORT_SYMBOL net/ipv4/inet_lro 0x22cd7629 lro_vlan_hwaccel_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0x377ff295 lro_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0x55baf200 lro_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0x8a074a7f lro_flush_pkt +EXPORT_SYMBOL net/ipv4/inet_lro 0x9dbc62c3 lro_vlan_hwaccel_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0xae62b68a lro_flush_all +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x0b4cba4a ip_vs_tcp_conn_listen +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x2d096edc ip_vs_conn_out_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x4682726f ip_vs_conn_put +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x65b6facb ip_vs_conn_in_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x663f76c9 ip_vs_conn_new +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x979eeeab unregister_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xa1dbc2d8 ip_vs_proto_name +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xbc899c49 register_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xbf70b8bc ip_vs_skb_replace +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xd9354bbc register_ip_vs_app_inc +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xf32ef3fb unregister_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xfb19a0b6 register_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x671f68de arpt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x69ee09e0 arpt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0xfc097145 arpt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x1584d27e ipt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x16bdebc4 ipt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x91cbce6f ipt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x093387d2 nf_nat_setup_info +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x1a54ca27 nf_nat_follow_master +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x3cb45a8b nf_nat_mangle_tcp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x4034cdee nf_nat_mangle_udp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x562ffd0d nf_nat_protocol_unregister +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xaa5f941a nf_nat_protocol_register +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xcf5f7ac6 nf_nat_used_tuple +EXPORT_SYMBOL net/ipv4/tunnel4 0x59a53238 xfrm4_tunnel_deregister +EXPORT_SYMBOL net/ipv4/tunnel4 0xf108afcb xfrm4_tunnel_register +EXPORT_SYMBOL net/ipv6/ipv6 0x01122150 inet6_ioctl +EXPORT_SYMBOL net/ipv6/ipv6 0x03db631c ipv6_getsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x05abd895 ipv6_chk_prefix +EXPORT_SYMBOL net/ipv6/ipv6 0x0ad0d02d icmpv6_send +EXPORT_SYMBOL net/ipv6/ipv6 0x203fde1f inet6_del_protocol +EXPORT_SYMBOL net/ipv6/ipv6 0x30123eb5 icmpv6_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0x31db235c xfrm6_input_addr +EXPORT_SYMBOL net/ipv6/ipv6 0x45caf022 xfrm6_find_1stfragopt +EXPORT_SYMBOL net/ipv6/ipv6 0x4a233e0f ip6_frag_init +EXPORT_SYMBOL net/ipv6/ipv6 0x538383c0 unregister_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0x55347044 ndisc_mc_map +EXPORT_SYMBOL net/ipv6/ipv6 0x5b6f2d59 xfrm6_rcv_spi +EXPORT_SYMBOL net/ipv6/ipv6 0x5be4aad6 rt6_lookup +EXPORT_SYMBOL net/ipv6/ipv6 0x636782ae inet6_getname +EXPORT_SYMBOL net/ipv6/ipv6 0x6536aa78 inet6_unregister_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0x67c9cad8 inet6_bind +EXPORT_SYMBOL net/ipv6/ipv6 0x6d8a65a5 compat_ipv6_getsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x6e134c94 ip6_route_me_harder +EXPORT_SYMBOL net/ipv6/ipv6 0x79a4eab3 nf_ip6_checksum +EXPORT_SYMBOL net/ipv6/ipv6 0x7c82a4c9 ipv6_dev_get_saddr +EXPORT_SYMBOL net/ipv6/ipv6 0x7f499f05 compat_ipv6_setsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x8a9d08dc xfrm6_prepare_output +EXPORT_SYMBOL net/ipv6/ipv6 0x964a4a3e ipv6_push_nfrag_opts +EXPORT_SYMBOL net/ipv6/ipv6 0xa7ac9e94 in6_dev_finish_destroy +EXPORT_SYMBOL net/ipv6/ipv6 0xafb7bd1a inet6_register_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0xb7919eda inet6_release +EXPORT_SYMBOL net/ipv6/ipv6 0xb905ad82 icmpv6_err_convert +EXPORT_SYMBOL net/ipv6/ipv6 0xb98994a1 inet6_add_protocol +EXPORT_SYMBOL net/ipv6/ipv6 0xbd20a440 ip6_frag_match +EXPORT_SYMBOL net/ipv6/ipv6 0xca46c664 ipv6_setsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0xce19bac5 register_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0xd4a62844 xfrm6_rcv +EXPORT_SYMBOL net/ipv6/ipv6 0xe1a81c3a icmpv6msg_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0xe690b8fd __ipv6_isatap_ifid +EXPORT_SYMBOL net/ipv6/ipv6 0xf14d638a ip6_route_output +EXPORT_SYMBOL net/ipv6/ipv6 0xf2580bf0 ip6_xmit +EXPORT_SYMBOL net/ipv6/ipv6 0xfbef045f ipv6_chk_addr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x1b34cbe0 ip6t_register_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x5ea20186 ip6t_do_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xa5abd6cf ip6t_unregister_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xb8bddf33 ip6t_ext_hdr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xe173f955 ipv6_find_hdr +EXPORT_SYMBOL net/ipv6/tunnel6 0x2b7d2ce6 xfrm6_tunnel_deregister +EXPORT_SYMBOL net/ipv6/tunnel6 0x9daa7e31 xfrm6_tunnel_register +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0x9cd013f2 xfrm6_tunnel_alloc_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xab14e193 xfrm6_tunnel_free_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xdb1b42d1 xfrm6_tunnel_spi_lookup +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x1f8c4c0e ircomm_control_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x26cdb332 ircomm_close +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x38b5acd8 ircomm_open +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x7e654f44 ircomm_connect_response +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xb1d2cf8a ircomm_data_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xb32bd596 ircomm_disconnect_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xca057ca9 ircomm_connect_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xf739607b ircomm_flow_request +EXPORT_SYMBOL net/irda/irda 0x01d1fcdb hashbin_delete +EXPORT_SYMBOL net/irda/irda 0x06a3ee58 irias_new_integer_value +EXPORT_SYMBOL net/irda/irda 0x072e026f irias_add_octseq_attrib +EXPORT_SYMBOL net/irda/irda 0x07d3647c irlmp_register_service +EXPORT_SYMBOL net/irda/irda 0x12df9f01 irda_notify_init +EXPORT_SYMBOL net/irda/irda 0x1a6c4e98 iriap_open +EXPORT_SYMBOL net/irda/irda 0x1b5fc2b0 irttp_udata_request +EXPORT_SYMBOL net/irda/irda 0x1f7c64ca irlmp_connect_request +EXPORT_SYMBOL net/irda/irda 0x2036ad06 irda_param_insert +EXPORT_SYMBOL net/irda/irda 0x226b9c3a irlmp_data_request +EXPORT_SYMBOL net/irda/irda 0x28e945c2 irlmp_close_lsap +EXPORT_SYMBOL net/irda/irda 0x2e39a064 irttp_open_tsap +EXPORT_SYMBOL net/irda/irda 0x31c90dea irttp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0x3462950f hashbin_remove +EXPORT_SYMBOL net/irda/irda 0x38a20e5b irda_debug +EXPORT_SYMBOL net/irda/irda 0x3f4d0058 irlap_open +EXPORT_SYMBOL net/irda/irda 0x42fc899a irttp_close_tsap +EXPORT_SYMBOL net/irda/irda 0x448b8aaa irda_qos_bits_to_value +EXPORT_SYMBOL net/irda/irda 0x460fcf5f irda_device_set_media_busy +EXPORT_SYMBOL net/irda/irda 0x46c1c4a2 irlmp_unregister_service +EXPORT_SYMBOL net/irda/irda 0x59f0cb0f iriap_close +EXPORT_SYMBOL net/irda/irda 0x5a62f87a irttp_data_request +EXPORT_SYMBOL net/irda/irda 0x5b6d1eaa alloc_irdadev +EXPORT_SYMBOL net/irda/irda 0x615f6e12 irlmp_connect_response +EXPORT_SYMBOL net/irda/irda 0x6758f8ac irias_new_object +EXPORT_SYMBOL net/irda/irda 0x68b7447c hashbin_find +EXPORT_SYMBOL net/irda/irda 0x6ab7675c async_wrap_skb +EXPORT_SYMBOL net/irda/irda 0x6b043eba irda_init_max_qos_capabilies +EXPORT_SYMBOL net/irda/irda 0x7042bc54 irlmp_register_client +EXPORT_SYMBOL net/irda/irda 0x70d576d6 irttp_connect_response +EXPORT_SYMBOL net/irda/irda 0x747d6779 irias_delete_object +EXPORT_SYMBOL net/irda/irda 0x7621e908 hashbin_insert +EXPORT_SYMBOL net/irda/irda 0x76243bc9 irias_insert_object +EXPORT_SYMBOL net/irda/irda 0x763e54a4 irlmp_unregister_client +EXPORT_SYMBOL net/irda/irda 0x781e2db5 irias_find_object +EXPORT_SYMBOL net/irda/irda 0x7957f728 irlmp_update_client +EXPORT_SYMBOL net/irda/irda 0x7a57b6f3 hashbin_remove_this +EXPORT_SYMBOL net/irda/irda 0x7c33601b irlap_close +EXPORT_SYMBOL net/irda/irda 0x866a7dd4 irlmp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0x91815586 irda_param_pack +EXPORT_SYMBOL net/irda/irda 0x94a40001 proc_irda +EXPORT_SYMBOL net/irda/irda 0x993ad14b irda_param_extract_all +EXPORT_SYMBOL net/irda/irda 0x9c44e3c3 async_unwrap_char +EXPORT_SYMBOL net/irda/irda 0xb4cbf708 irttp_dup +EXPORT_SYMBOL net/irda/irda 0xb9394173 irias_delete_value +EXPORT_SYMBOL net/irda/irda 0xbcd3ef13 irias_object_change_attribute +EXPORT_SYMBOL net/irda/irda 0xbe40ace9 irlmp_discovery_request +EXPORT_SYMBOL net/irda/irda 0xc14e9b6a hashbin_get_next +EXPORT_SYMBOL net/irda/irda 0xc3f4fe15 irttp_flow_request +EXPORT_SYMBOL net/irda/irda 0xc62dc6b2 irlmp_open_lsap +EXPORT_SYMBOL net/irda/irda 0xcb599590 iriap_getvaluebyclass_request +EXPORT_SYMBOL net/irda/irda 0xcd41236c hashbin_new +EXPORT_SYMBOL net/irda/irda 0xd6deeaae irda_setup_dma +EXPORT_SYMBOL net/irda/irda 0xd7172ff4 hashbin_get_first +EXPORT_SYMBOL net/irda/irda 0xd8bfb6d4 hashbin_lock_find +EXPORT_SYMBOL net/irda/irda 0xdda6747f irttp_connect_request +EXPORT_SYMBOL net/irda/irda 0xde4c6b3c irlmp_service_to_hint +EXPORT_SYMBOL net/irda/irda 0xe5260e0e irias_add_integer_attrib +EXPORT_SYMBOL net/irda/irda 0xec41fe7f irias_add_string_attrib +EXPORT_SYMBOL net/irda/irda 0xedd521c2 irlmp_get_discoveries +EXPORT_SYMBOL net/lapb/lapb 0x0483e3d8 lapb_register +EXPORT_SYMBOL net/lapb/lapb 0x04e095f9 lapb_data_request +EXPORT_SYMBOL net/lapb/lapb 0x9de9338f lapb_connect_request +EXPORT_SYMBOL net/lapb/lapb 0xc757fe28 lapb_getparms +EXPORT_SYMBOL net/lapb/lapb 0xc8f5da54 lapb_disconnect_request +EXPORT_SYMBOL net/lapb/lapb 0xd001e376 lapb_data_received +EXPORT_SYMBOL net/lapb/lapb 0xd435884f lapb_setparms +EXPORT_SYMBOL net/lapb/lapb 0xf01d1ab2 lapb_unregister +EXPORT_SYMBOL net/mac80211/mac80211 0x02966e4b ieee80211_rts_get +EXPORT_SYMBOL net/mac80211/mac80211 0x0a8ed1d4 ieee80211_scan_completed +EXPORT_SYMBOL net/mac80211/mac80211 0x0bfd6249 ieee80211_stop_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0x10480ced sta_info_get +EXPORT_SYMBOL net/mac80211/mac80211 0x348653eb ieee80211_tx_status_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x35e8e02a __ieee80211_rx +EXPORT_SYMBOL net/mac80211/mac80211 0x3df78e8c ieee80211_ctstoself_get +EXPORT_SYMBOL net/mac80211/mac80211 0x4721f1c7 ieee80211_ctstoself_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x4762cfe1 ieee80211_generic_frame_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x47ac2cfd ieee80211_rx_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x49ef338b ieee80211_get_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x4cad1306 ieee80211_stop_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x5061b68d ieee80211_start_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x5110a491 ieee80211_stop_queue +EXPORT_SYMBOL net/mac80211/mac80211 0x56808db7 __ieee80211_get_rx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x6107faaf __ieee80211_get_assoc_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x65934f6c ieee80211_stop_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x6f67cdaf ieee80211_stop_queues +EXPORT_SYMBOL net/mac80211/mac80211 0x791a6f6f ieee80211_start_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x798426c8 ieee80211_register_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x7d8bea01 ieee80211_start_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0x7e8cf9bb ieee80211_get_buffered_bc +EXPORT_SYMBOL net/mac80211/mac80211 0x8588ef14 __ieee80211_get_radio_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x8c35d732 ieee80211_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x972ff836 ieee80211_free_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xa8bf44c2 ieee80211_rts_duration +EXPORT_SYMBOL net/mac80211/mac80211 0xabef9696 ieee80211_beacon_get +EXPORT_SYMBOL net/mac80211/mac80211 0xad56935a ieee80211_rate_control_unregister +EXPORT_SYMBOL net/mac80211/mac80211 0xaefdfd66 ieee80211_notify_mac +EXPORT_SYMBOL net/mac80211/mac80211 0xb641c503 ieee80211_get_tkip_key +EXPORT_SYMBOL net/mac80211/mac80211 0xb65dd0eb ieee80211_tx_status +EXPORT_SYMBOL net/mac80211/mac80211 0xbdc6afcc ieee80211_alloc_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xc5d11351 ieee80211_get_hdrlen_from_skb +EXPORT_SYMBOL net/mac80211/mac80211 0xdc3248fb ieee80211_wake_queues +EXPORT_SYMBOL net/mac80211/mac80211 0xdc9d3eaf ieee80211_unregister_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xe39b9ab3 ieee80211_wake_queue +EXPORT_SYMBOL net/mac80211/mac80211 0xec8e3b9c ieee80211_rate_control_register +EXPORT_SYMBOL net/mac80211/mac80211 0xfd77d9be __ieee80211_get_tx_led_name +EXPORT_SYMBOL net/netfilter/nf_conntrack 0x8fb4ee7a __nf_ct_ext_destroy +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xe372c1b6 __nf_ct_ext_add +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xed23741c per_cpu__nf_conntrack_stat +EXPORT_SYMBOL net/netfilter/nf_conntrack_proto_gre 0x82f94e40 nf_ct_gre_keymap_flush +EXPORT_SYMBOL net/netfilter/x_tables 0x058606dd xt_unregister_matches +EXPORT_SYMBOL net/netfilter/x_tables 0x0fc50a43 xt_unregister_match +EXPORT_SYMBOL net/netfilter/x_tables 0x3dcd58c5 xt_alloc_table_info +EXPORT_SYMBOL net/netfilter/x_tables 0x4b9e7a21 xt_register_targets +EXPORT_SYMBOL net/netfilter/x_tables 0x4e971552 xt_find_match +EXPORT_SYMBOL net/netfilter/x_tables 0x6a2bcb35 xt_find_target +EXPORT_SYMBOL net/netfilter/x_tables 0x77b483bb xt_register_matches +EXPORT_SYMBOL net/netfilter/x_tables 0xaf641f7b xt_register_match +EXPORT_SYMBOL net/netfilter/x_tables 0xb8da48ae xt_unregister_target +EXPORT_SYMBOL net/netfilter/x_tables 0xcf63b93f xt_register_target +EXPORT_SYMBOL net/netfilter/x_tables 0xef78e7ef xt_unregister_targets +EXPORT_SYMBOL net/netfilter/x_tables 0xf7037dc6 xt_free_table_info +EXPORT_SYMBOL net/rfkill/rfkill 0x00caa4dc rfkill_switch_all +EXPORT_SYMBOL net/rfkill/rfkill 0x39b8d0b4 rfkill_force_state +EXPORT_SYMBOL net/rfkill/rfkill 0x922403d1 rfkill_register +EXPORT_SYMBOL net/rfkill/rfkill 0x970421d5 rfkill_allocate +EXPORT_SYMBOL net/rfkill/rfkill 0xa8ca9fb3 rfkill_free +EXPORT_SYMBOL net/rfkill/rfkill 0xffe113fb rfkill_unregister +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x039ff6c4 rxrpc_kernel_accept_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x1699af2a rxrpc_kernel_end_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x1e050a28 key_type_rxrpc +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x3ec009ae rxrpc_kernel_data_delivered +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x4479dd43 rxrpc_kernel_reject_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x4af943e7 rxrpc_kernel_get_error_number +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x61d5a4f5 rxrpc_get_server_data_key +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x6a211871 rxrpc_kernel_is_data_last +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x92db01ed rxrpc_kernel_abort_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x962925f5 rxrpc_kernel_intercept_rx_messages +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xae046a2a rxrpc_get_null_key +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xcfa2b0ad rxrpc_kernel_begin_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xe9e0e3f9 rxrpc_kernel_get_abort_code +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xef2f33a1 rxrpc_kernel_free_skb +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xf7c601e8 rxrpc_kernel_send_data +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x00c52ef5 g_make_token_header +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x452ec7b9 gss_mech_get_by_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x48f84627 gss_mech_register +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x51d66cd3 gss_service_to_auth_domain_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x5486480e gss_pseudoflavor_to_service +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x63620bc7 gss_mech_get_by_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x8d1a827e svcauth_gss_register_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x92672848 gss_mech_get +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xa305512f gss_mech_put +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xb0e17bd4 gss_svc_to_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xb5dea7ef g_token_size +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xc31bb181 svcauth_gss_flavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xee2edf46 gss_mech_unregister +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xf8b2ff6e g_verify_token_header +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0085f236 sunrpc_cache_update +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0372abd5 auth_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0x05e807a9 xdr_encode_string +EXPORT_SYMBOL net/sunrpc/sunrpc 0x065994f1 xdr_encode_opaque_fixed +EXPORT_SYMBOL net/sunrpc/sunrpc 0x09bb139b svc_sock_names +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0a2f867b xdr_buf_from_iov +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0cae649a xdr_init_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0f668ba9 svc_auth_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x1241d4d9 svc_set_num_threads +EXPORT_SYMBOL net/sunrpc/sunrpc 0x12e280e3 svc_proc_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x152877f6 read_bytes_from_xdr_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x20672151 xdr_buf_read_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2919b156 xdr_decode_string_inplace +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2eec63c9 xdr_encode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2f71f67a svc_create +EXPORT_SYMBOL net/sunrpc/sunrpc 0x305e86f0 xdr_read_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x32cd3f21 auth_domain_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x35985b95 auth_unix_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3718d724 xdr_write_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x39a4c5c1 xdr_encode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3de44b43 svc_process +EXPORT_SYMBOL net/sunrpc/sunrpc 0x4631620b svc_reserve +EXPORT_SYMBOL net/sunrpc/sunrpc 0x52e30c35 xdr_encode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0x54ca3745 xdr_inline_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5b45f4e3 svc_create_pooled +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5e1a9773 svc_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5f286359 svc_prepare_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0x66b754ca svc_wake_up +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6eea229d svcauth_unix_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0x70e4cd4e svc_sock_update_bufs +EXPORT_SYMBOL net/sunrpc/sunrpc 0x71e08d9a cache_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x71fa908a cache_flush +EXPORT_SYMBOL net/sunrpc/sunrpc 0x82b381ca xdr_enter_page +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8a1e42e1 svc_recv +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8ba38497 xdr_buf_subsegment +EXPORT_SYMBOL net/sunrpc/sunrpc 0x93df893f xdr_process_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x945ee224 sunrpc_cache_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9467b84c svcauth_unix_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0x962f99e0 unix_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9661dfe8 svc_seq_show +EXPORT_SYMBOL net/sunrpc/sunrpc 0xb7acd895 xdr_decode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0xb8f982a2 xdr_init_encode +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbb409557 cache_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbbd33984 svc_auth_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbc53fe75 svc_destroy +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbff3d537 auth_domain_put +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc2da29c8 auth_unix_add_addr +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc3880471 xdr_decode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc8e96dea qword_addhex +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd0bab8fd cache_check +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd1e656f1 xdr_decode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd8fb4109 cache_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd93413cc xdr_reserve_space +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd98af402 xdr_encode_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0xdacabb5f xdr_shift_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe5919cb1 xdr_encode_opaque +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe8bd8bb1 svc_exit_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe97f4ce5 qword_get +EXPORT_SYMBOL net/sunrpc/sunrpc 0xedcf6be4 qword_add +EXPORT_SYMBOL net/sunrpc/sunrpc 0xf799fdcd xdr_inline_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfa22f364 rpc_queue_upcall +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfb347954 rpc_unlink +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfc152260 rpc_mkpipe +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfcf63714 svc_proc_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfe6d65cf auth_unix_forget_old +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfe756272 svc_drop +EXPORT_SYMBOL net/sunrpc/sunrpc 0xffed9443 svc_authenticate +EXPORT_SYMBOL net/tipc/tipc 0x06c430a8 tipc_send_buf2port +EXPORT_SYMBOL net/tipc/tipc 0x08acf310 tipc_available_nodes +EXPORT_SYMBOL net/tipc/tipc 0x0b074a7b tipc_multicast +EXPORT_SYMBOL net/tipc/tipc 0x10d40fcd tipc_isconnected +EXPORT_SYMBOL net/tipc/tipc 0x1472b270 tipc_disconnect +EXPORT_SYMBOL net/tipc/tipc 0x1479cb03 tipc_deleteport +EXPORT_SYMBOL net/tipc/tipc 0x14d417ab tipc_reject_msg +EXPORT_SYMBOL net/tipc/tipc 0x15b5ecde tipc_set_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x16f27683 tipc_block_bearer +EXPORT_SYMBOL net/tipc/tipc 0x23daecbd tipc_send +EXPORT_SYMBOL net/tipc/tipc 0x259b74f9 tipc_acknowledge +EXPORT_SYMBOL net/tipc/tipc 0x310d1bc9 tipc_detach +EXPORT_SYMBOL net/tipc/tipc 0x3712e340 tipc_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x3976041f tipc_set_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x419b02fc tipc_send2port +EXPORT_SYMBOL net/tipc/tipc 0x4b2243c6 tipc_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x538b228a tipc_withdraw +EXPORT_SYMBOL net/tipc/tipc 0x5637ed44 tipc_get_mode +EXPORT_SYMBOL net/tipc/tipc 0x56e52bc1 tipc_continue +EXPORT_SYMBOL net/tipc/tipc 0x5b951051 tipc_forward_buf2name +EXPORT_SYMBOL net/tipc/tipc 0x5c0d4b5c tipc_ref_valid +EXPORT_SYMBOL net/tipc/tipc 0x62a681a3 tipc_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0x66e9c3ff tipc_send_buf +EXPORT_SYMBOL net/tipc/tipc 0x84eda213 tipc_send_buf2name +EXPORT_SYMBOL net/tipc/tipc 0x86f8f2df tipc_createport_raw +EXPORT_SYMBOL net/tipc/tipc 0x88b73627 tipc_get_addr +EXPORT_SYMBOL net/tipc/tipc 0x9c45558e tipc_enable_bearer +EXPORT_SYMBOL net/tipc/tipc 0xa1b42d32 tipc_forward2port +EXPORT_SYMBOL net/tipc/tipc 0xa30962e9 tipc_send_buf_fast +EXPORT_SYMBOL net/tipc/tipc 0xa936a24b tipc_get_port +EXPORT_SYMBOL net/tipc/tipc 0xadd203d0 tipc_connect2port +EXPORT_SYMBOL net/tipc/tipc 0xae0103c3 tipc_shutdown +EXPORT_SYMBOL net/tipc/tipc 0xb1f8eacc tipc_send2name +EXPORT_SYMBOL net/tipc/tipc 0xb35b672c tipc_publish +EXPORT_SYMBOL net/tipc/tipc 0xbc9e0e2c tipc_createport +EXPORT_SYMBOL net/tipc/tipc 0xcec8514a tipc_set_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0xcee290be tipc_forward2name +EXPORT_SYMBOL net/tipc/tipc 0xd17d954e tipc_recv_msg +EXPORT_SYMBOL net/tipc/tipc 0xd44731e5 tipc_ownidentity +EXPORT_SYMBOL net/tipc/tipc 0xd708ca84 tipc_forward_buf2port +EXPORT_SYMBOL net/tipc/tipc 0xda7f9d3f tipc_attach +EXPORT_SYMBOL net/tipc/tipc 0xdf5008fc tipc_peer +EXPORT_SYMBOL net/tipc/tipc 0xe7aece47 tipc_ispublished +EXPORT_SYMBOL net/tipc/tipc 0xea703c36 tipc_register_media +EXPORT_SYMBOL net/tipc/tipc 0xeefd49b3 tipc_get_handle +EXPORT_SYMBOL net/tipc/tipc 0xef50a1ef tipc_disable_bearer +EXPORT_SYMBOL net/wanrouter/wanrouter 0x0ebe03d1 unregister_wan_device +EXPORT_SYMBOL net/wanrouter/wanrouter 0x87487a8e register_wan_device +EXPORT_SYMBOL net/wireless/cfg80211 0x07e7ac5a ieee80211_radiotap_iterator_init +EXPORT_SYMBOL net/wireless/cfg80211 0x09c64fbd ieee80211_frequency_to_channel +EXPORT_SYMBOL net/wireless/cfg80211 0x288f266b wiphy_new +EXPORT_SYMBOL net/wireless/cfg80211 0x47d44dd8 wiphy_register +EXPORT_SYMBOL net/wireless/cfg80211 0x58561e2f wiphy_unregister +EXPORT_SYMBOL net/wireless/cfg80211 0x63eab0c5 wiphy_free +EXPORT_SYMBOL net/wireless/cfg80211 0xbcb4137e __ieee80211_get_channel +EXPORT_SYMBOL net/wireless/cfg80211 0xc4e85ec5 ieee80211_radiotap_iterator_next +EXPORT_SYMBOL net/wireless/cfg80211 0xccc291b3 ieee80211_channel_to_frequency +EXPORT_SYMBOL sound/ac97_bus 0xa370459a ac97_bus_type +EXPORT_SYMBOL sound/core/oss/snd-mixer-oss 0xeea74dd5 snd_mixer_oss_ioctl_card +EXPORT_SYMBOL sound/core/seq/snd-seq 0x1a724fcc snd_seq_kernel_client_ctl +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3061c52d snd_use_lock_sync_helper +EXPORT_SYMBOL sound/core/seq/snd-seq 0x32ceb3dd snd_seq_event_port_attach +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3fb4d161 snd_seq_kernel_client_dispatch +EXPORT_SYMBOL sound/core/seq/snd-seq 0x4579a750 snd_seq_kernel_client_write_poll +EXPORT_SYMBOL sound/core/seq/snd-seq 0x6bb71038 snd_seq_delete_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7ac2f329 snd_seq_expand_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7b8699eb snd_seq_event_port_detach +EXPORT_SYMBOL sound/core/seq/snd-seq 0xb8e448a0 snd_seq_set_queue_tempo +EXPORT_SYMBOL sound/core/seq/snd-seq 0xbc037875 snd_seq_kernel_client_enqueue_blocking +EXPORT_SYMBOL sound/core/seq/snd-seq 0xc5a3315d snd_seq_create_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq 0xcac0a3be snd_seq_kernel_client_enqueue +EXPORT_SYMBOL sound/core/seq/snd-seq 0xe934da1d snd_seq_dump_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x2cfa236f snd_seq_device_new +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x3a57f235 snd_seq_autoload_unlock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x6339b6d0 snd_seq_device_load_drivers +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x74a6dff0 snd_seq_device_register_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xb90668b2 snd_seq_autoload_lock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xc622fb29 snd_seq_device_unregister_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x6ea09972 snd_midi_channel_alloc_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x833a3e07 snd_midi_channel_set_clear +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xb9948d2c snd_midi_channel_free_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xf0a1fdb3 snd_midi_process_event +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x17c15809 snd_midi_event_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x4ad3f518 snd_midi_event_reset_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x62384d3a snd_midi_event_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x8a348811 snd_midi_event_reset_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x9df7af8b snd_midi_event_free +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xc482499d snd_midi_event_new +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xd9072e1a snd_midi_event_no_status +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xe6df29c7 snd_midi_event_encode_byte +EXPORT_SYMBOL sound/core/seq/snd-seq-virmidi 0x40586a84 snd_virmidi_new +EXPORT_SYMBOL sound/core/snd 0x024545c3 snd_info_create_card_entry +EXPORT_SYMBOL sound/core/snd 0x0e02a142 snd_ctl_remove_id +EXPORT_SYMBOL sound/core/snd 0x1090b32e snd_ctl_find_numid +EXPORT_SYMBOL sound/core/snd 0x18e1683f snd_dma_program +EXPORT_SYMBOL sound/core/snd 0x191e88cf snd_dma_pointer +EXPORT_SYMBOL sound/core/snd 0x198788b4 snd_lookup_oss_minor_data +EXPORT_SYMBOL sound/core/snd 0x1f898c13 snd_add_device_sysfs_file +EXPORT_SYMBOL sound/core/snd 0x23d31632 snd_ctl_rename_id +EXPORT_SYMBOL sound/core/snd 0x24a94b26 snd_info_get_line +EXPORT_SYMBOL sound/core/snd 0x252dadd3 snd_pci_quirk_lookup +EXPORT_SYMBOL sound/core/snd 0x274b75ea snd_device_free +EXPORT_SYMBOL sound/core/snd 0x2b1e91c5 snd_info_create_module_entry +EXPORT_SYMBOL sound/core/snd 0x2d3c8322 snd_card_free +EXPORT_SYMBOL sound/core/snd 0x2fa6dc2d snd_card_register +EXPORT_SYMBOL sound/core/snd 0x36e4fc29 snd_ctl_find_id +EXPORT_SYMBOL sound/core/snd 0x376e04bf release_and_free_resource +EXPORT_SYMBOL sound/core/snd 0x3971b4df snd_ecards_limit +EXPORT_SYMBOL sound/core/snd 0x427f598f snd_ctl_add +EXPORT_SYMBOL sound/core/snd 0x4a3ea5c0 snd_request_card +EXPORT_SYMBOL sound/core/snd 0x518bb7f8 copy_from_user_toio +EXPORT_SYMBOL sound/core/snd 0x53828a7c snd_ctl_new1 +EXPORT_SYMBOL sound/core/snd 0x569fe16d snd_component_add +EXPORT_SYMBOL sound/core/snd 0x5ae75510 snd_ctl_unregister_ioctl_compat +EXPORT_SYMBOL sound/core/snd 0x5ee12a00 snd_unregister_device +EXPORT_SYMBOL sound/core/snd 0x62a9d369 snd_card_file_add +EXPORT_SYMBOL sound/core/snd 0x665692e3 snd_card_proc_new +EXPORT_SYMBOL sound/core/snd 0x69c588c3 snd_card_new +EXPORT_SYMBOL sound/core/snd 0x6bfa26da snd_mixer_oss_notify_callback +EXPORT_SYMBOL sound/core/snd 0x70c15ac1 snd_dma_disable +EXPORT_SYMBOL sound/core/snd 0x73ce1f0b snd_ctl_make_virtual_master +EXPORT_SYMBOL sound/core/snd 0x77946522 snd_cards +EXPORT_SYMBOL sound/core/snd 0x7b4dd75e snd_ctl_remove +EXPORT_SYMBOL sound/core/snd 0x815c8be0 snd_unregister_oss_device +EXPORT_SYMBOL sound/core/snd 0x844f1ad0 snd_ctl_add_slave +EXPORT_SYMBOL sound/core/snd 0x85f78f61 snd_ctl_register_ioctl +EXPORT_SYMBOL sound/core/snd 0x8df3789f snd_oss_info_register +EXPORT_SYMBOL sound/core/snd 0x8f595b11 snd_major +EXPORT_SYMBOL sound/core/snd 0x9d012cfc snd_register_oss_device +EXPORT_SYMBOL sound/core/snd 0xa5f86527 snd_card_free_when_closed +EXPORT_SYMBOL sound/core/snd 0xa753f500 snd_ctl_free_one +EXPORT_SYMBOL sound/core/snd 0xa95a38f5 snd_info_register +EXPORT_SYMBOL sound/core/snd 0xb08daa80 snd_power_wait +EXPORT_SYMBOL sound/core/snd 0xb213fe8b snd_info_get_str +EXPORT_SYMBOL sound/core/snd 0xb2e5ae4a snd_lookup_minor_data +EXPORT_SYMBOL sound/core/snd 0xb50bc653 snd_card_file_remove +EXPORT_SYMBOL sound/core/snd 0xc0e7adf3 snd_ctl_boolean_stereo_info +EXPORT_SYMBOL sound/core/snd 0xc98a86cf snd_card_disconnect +EXPORT_SYMBOL sound/core/snd 0xcca3063a snd_register_device_for_dev +EXPORT_SYMBOL sound/core/snd 0xcf5f7fb8 snd_ctl_boolean_mono_info +EXPORT_SYMBOL sound/core/snd 0xd1351d08 snd_device_new +EXPORT_SYMBOL sound/core/snd 0xe06047f7 snd_info_free_entry +EXPORT_SYMBOL sound/core/snd 0xe147ca89 snd_seq_root +EXPORT_SYMBOL sound/core/snd 0xe243dde3 copy_to_user_fromio +EXPORT_SYMBOL sound/core/snd 0xe4854cea snd_iprintf +EXPORT_SYMBOL sound/core/snd 0xedfe624d snd_ctl_register_ioctl_compat +EXPORT_SYMBOL sound/core/snd 0xf4393bc5 snd_ctl_unregister_ioctl +EXPORT_SYMBOL sound/core/snd 0xf6fe9c18 snd_ctl_notify +EXPORT_SYMBOL sound/core/snd 0xfedc9c4f snd_device_register +EXPORT_SYMBOL sound/core/snd-hwdep 0xf8f241ed snd_hwdep_new +EXPORT_SYMBOL sound/core/snd-page-alloc 0x17e7ccaf snd_dma_alloc_pages_fallback +EXPORT_SYMBOL sound/core/snd-page-alloc 0x19cc2ce3 snd_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x682905e9 snd_dma_alloc_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x7b7daac3 snd_dma_reserve_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x929f75da snd_dma_get_reserved_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x97070bfa snd_dma_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0xc6829020 snd_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x009153fc snd_pcm_release_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x04cda566 snd_interval_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x05c2a781 snd_pcm_hw_rule_add +EXPORT_SYMBOL sound/core/snd-pcm 0x1431e211 snd_pcm_suspend +EXPORT_SYMBOL sound/core/snd-pcm 0x15bc4603 snd_pcm_kernel_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x1d027e4b snd_pcm_format_signed +EXPORT_SYMBOL sound/core/snd-pcm 0x1fe5b895 snd_pcm_notify +EXPORT_SYMBOL sound/core/snd-pcm 0x21c523f4 snd_pcm_suspend_all +EXPORT_SYMBOL sound/core/snd-pcm 0x36d7768c snd_pcm_hw_constraint_list +EXPORT_SYMBOL sound/core/snd-pcm 0x3796bdcc snd_pcm_format_little_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x4bdb8624 snd_pcm_lib_preallocate_pages_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x4f816e9b snd_pcm_format_big_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x56cdd711 snd_pcm_new +EXPORT_SYMBOL sound/core/snd-pcm 0x5e7f4920 snd_pcm_format_set_silence +EXPORT_SYMBOL sound/core/snd-pcm 0x60b53754 snd_pcm_lib_preallocate_free_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x650f8603 snd_pcm_format_silence_64 +EXPORT_SYMBOL sound/core/snd-pcm 0x68a24153 snd_pcm_format_physical_width +EXPORT_SYMBOL sound/core/snd-pcm 0x6ef8fcd8 snd_pcm_format_linear +EXPORT_SYMBOL sound/core/snd-pcm 0x71ac123d snd_pcm_hw_param_last +EXPORT_SYMBOL sound/core/snd-pcm 0x753d1b0d snd_pcm_lib_write +EXPORT_SYMBOL sound/core/snd-pcm 0x7c5cec98 _snd_pcm_hw_params_any +EXPORT_SYMBOL sound/core/snd-pcm 0x7c8f614a snd_pcm_hw_constraint_integer +EXPORT_SYMBOL sound/core/snd-pcm 0x80a182d4 snd_pcm_lib_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x8518e788 snd_pcm_hw_param_first +EXPORT_SYMBOL sound/core/snd-pcm 0x88cc66cc snd_pcm_link_rwlock +EXPORT_SYMBOL sound/core/snd-pcm 0x89a31a56 _snd_pcm_hw_param_setempty +EXPORT_SYMBOL sound/core/snd-pcm 0x8ff35032 snd_pcm_new_stream +EXPORT_SYMBOL sound/core/snd-pcm 0x931b522a snd_pcm_set_ops +EXPORT_SYMBOL sound/core/snd-pcm 0x9d06d4d5 snd_pcm_hw_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x9d5a1f7c snd_pcm_period_elapsed +EXPORT_SYMBOL sound/core/snd-pcm 0x9f3a7d28 snd_pcm_hw_constraint_ratdens +EXPORT_SYMBOL sound/core/snd-pcm 0x9fdea959 snd_pcm_hw_param_value +EXPORT_SYMBOL sound/core/snd-pcm 0xa0be1c54 snd_pcm_hw_constraint_minmax +EXPORT_SYMBOL sound/core/snd-pcm 0xa61aa028 snd_pcm_format_unsigned +EXPORT_SYMBOL sound/core/snd-pcm 0xadda757e snd_pcm_hw_constraint_ratnums +EXPORT_SYMBOL sound/core/snd-pcm 0xaea473a2 snd_pcm_stop +EXPORT_SYMBOL sound/core/snd-pcm 0xaf3264e7 snd_pcm_lib_readv +EXPORT_SYMBOL sound/core/snd-pcm 0xb0ac081e snd_pcm_lib_mmap_iomem +EXPORT_SYMBOL sound/core/snd-pcm 0xb162acc0 snd_pcm_hw_constraint_pow2 +EXPORT_SYMBOL sound/core/snd-pcm 0xb53afc28 snd_pcm_hw_constraint_msbits +EXPORT_SYMBOL sound/core/snd-pcm 0xb7347a6a snd_pcm_hw_constraint_step +EXPORT_SYMBOL sound/core/snd-pcm 0xb9638db4 snd_pcm_rate_to_rate_bit +EXPORT_SYMBOL sound/core/snd-pcm 0xc1f2e0a9 snd_pcm_mmap_data +EXPORT_SYMBOL sound/core/snd-pcm 0xc6b5bc99 snd_pcm_lib_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0xca639d7c snd_pcm_lib_free_pages +EXPORT_SYMBOL sound/core/snd-pcm 0xd0b9b8b8 snd_interval_list +EXPORT_SYMBOL sound/core/snd-pcm 0xd4d84cde snd_pcm_lib_read +EXPORT_SYMBOL sound/core/snd-pcm 0xd7acd80c snd_pcm_set_sync +EXPORT_SYMBOL sound/core/snd-pcm 0xd948182f snd_pcm_lib_preallocate_pages +EXPORT_SYMBOL sound/core/snd-pcm 0xe51a1c64 snd_pcm_format_size +EXPORT_SYMBOL sound/core/snd-pcm 0xe56a9336 snd_pcm_format_width +EXPORT_SYMBOL sound/core/snd-pcm 0xe79f2170 snd_pcm_limit_hw_rates +EXPORT_SYMBOL sound/core/snd-pcm 0xf3797152 snd_interval_ratnum +EXPORT_SYMBOL sound/core/snd-pcm 0xfa222410 snd_pcm_open_substream +EXPORT_SYMBOL sound/core/snd-pcm 0xfc174fdc snd_pcm_sgbuf_ops_page +EXPORT_SYMBOL sound/core/snd-pcm 0xff45a66d snd_pcm_lib_writev +EXPORT_SYMBOL sound/core/snd-rawmidi 0x06434470 snd_rawmidi_set_ops +EXPORT_SYMBOL sound/core/snd-rawmidi 0x2dcc2380 snd_rawmidi_transmit_peek +EXPORT_SYMBOL sound/core/snd-rawmidi 0x31a124b4 snd_rawmidi_transmit_ack +EXPORT_SYMBOL sound/core/snd-rawmidi 0x3afebe24 snd_rawmidi_new +EXPORT_SYMBOL sound/core/snd-rawmidi 0x63094fe8 snd_rawmidi_kernel_write +EXPORT_SYMBOL sound/core/snd-rawmidi 0x76590f19 snd_rawmidi_output_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0x865782ad snd_rawmidi_kernel_release +EXPORT_SYMBOL sound/core/snd-rawmidi 0x9fc5fd61 snd_rawmidi_kernel_open +EXPORT_SYMBOL sound/core/snd-rawmidi 0xbda532f3 snd_rawmidi_transmit_empty +EXPORT_SYMBOL sound/core/snd-rawmidi 0xd9e4ebc3 snd_rawmidi_input_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0xdaaffd84 snd_rawmidi_receive +EXPORT_SYMBOL sound/core/snd-rawmidi 0xe88b760c snd_rawmidi_kernel_read +EXPORT_SYMBOL sound/core/snd-rawmidi 0xe8fdf5a4 snd_rawmidi_transmit +EXPORT_SYMBOL sound/core/snd-rawmidi 0xec8e7988 snd_rawmidi_drop_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0xeeb53120 snd_rawmidi_info_select +EXPORT_SYMBOL sound/core/snd-rawmidi 0xf3e58169 snd_rawmidi_drain_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0xff6b8875 snd_rawmidi_drain_input +EXPORT_SYMBOL sound/core/snd-timer 0x0327f43b snd_timer_stop +EXPORT_SYMBOL sound/core/snd-timer 0x0721c98b snd_timer_open +EXPORT_SYMBOL sound/core/snd-timer 0x1474e889 snd_timer_global_free +EXPORT_SYMBOL sound/core/snd-timer 0x1509f1ed snd_timer_interrupt +EXPORT_SYMBOL sound/core/snd-timer 0x26ee9530 snd_timer_global_new +EXPORT_SYMBOL sound/core/snd-timer 0x2ee29886 snd_timer_pause +EXPORT_SYMBOL sound/core/snd-timer 0x3465a203 snd_timer_global_register +EXPORT_SYMBOL sound/core/snd-timer 0x3cb60416 snd_timer_new +EXPORT_SYMBOL sound/core/snd-timer 0x452201c4 snd_timer_close +EXPORT_SYMBOL sound/core/snd-timer 0x5a24df20 snd_timer_start +EXPORT_SYMBOL sound/core/snd-timer 0x6034ad38 snd_timer_resolution +EXPORT_SYMBOL sound/core/snd-timer 0x757ab090 snd_timer_notify +EXPORT_SYMBOL sound/core/snd-timer 0xd91d532d snd_timer_continue +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x73c4c993 snd_mpu401_uart_interrupt_tx +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xcdb9942b snd_mpu401_uart_new +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xfe618b58 snd_mpu401_uart_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x05060a19 snd_opl3_regmap +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x195b928b snd_opl3_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x29dd600c snd_opl3_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x2fddcf77 snd_opl3_timer_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x7ca87361 snd_opl3_reset +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x9c4badd2 snd_opl3_find_patch +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xabcfd06e snd_opl3_init +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xb8d932bb snd_opl3_create +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xd80eab03 snd_opl3_load_patch +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xdb324c7e snd_opl3_hwdep_new +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x1cadb14b snd_vx_irq_handler +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x4e3a6118 snd_vx_load_boot_image +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x51880703 snd_vx_check_reg_bit +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x77415395 snd_vx_create +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x82283bb7 snd_vx_suspend +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x86deeb66 snd_vx_dsp_boot +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xc21a2e5d snd_vx_resume +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xc6c02ea9 snd_vx_free_firmware +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xcbf3aa95 snd_vx_dsp_load +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xcc69dd55 snd_vx_setup_firmware +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x0c2b5588 snd_ak4114_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x46fe5cb9 snd_ak4114_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x76804437 snd_ak4114_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x838459a4 snd_ak4114_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xacf75ad2 snd_ak4114_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xf4ed143d snd_ak4114_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x00c33391 snd_ak4117_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x3a0df681 snd_ak4117_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x3efbbba8 snd_ak4117_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x5ba1e093 snd_ak4117_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x9534f614 snd_ak4117_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xb7800efe snd_ak4117_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x4cc2b626 snd_akm4xxx_reset +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x5e8beaab snd_akm4xxx_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x9e59774e snd_akm4xxx_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xbd4f26b4 snd_akm4xxx_init +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x077a3820 snd_pt2258_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0xb13b7e1b snd_pt2258_reset +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0x1cfc0a30 snd_tea575x_exit +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0xa52ff270 snd_tea575x_init +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x3972febf snd_cs8427_reg_write +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xb344bac0 snd_cs8427_iec958_pcm +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xd361c63f snd_cs8427_iec958_build +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xf07a262e snd_cs8427_iec958_active +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xf8122bee snd_cs8427_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0x19a34414 snd_i2c_bus_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0x999a5a72 snd_i2c_device_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0xdc11f015 snd_i2c_readbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0xe2b39b2f snd_i2c_sendbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0xe6aa7caa snd_i2c_device_free +EXPORT_SYMBOL sound/i2c/snd-i2c 0xf992f403 snd_i2c_probeaddr +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x11284bad snd_sbmixer_new +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x476e2833 snd_sbdsp_create +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x4ef10019 snd_sbdsp_reset +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x5f390f9b snd_sbmixer_add_ctl +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x61338009 snd_sbmixer_suspend +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x86fc4784 snd_sbmixer_read +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x884579e7 snd_sbdsp_get_byte +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x93958b46 snd_sbmixer_resume +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x9cf7a561 snd_sbmixer_write +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xf5de8c93 snd_sbdsp_command +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x0ba4ef1d snd_sb16dsp_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x2ced3235 snd_sb16dsp_pcm +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x849369c2 snd_sb16dsp_get_pcm_ops +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x991a557a snd_sb16dsp_configure +EXPORT_SYMBOL sound/oss/ad1848 0x10e7c768 attach_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x7aa41a6d ad1848_init +EXPORT_SYMBOL sound/oss/ad1848 0x9839a618 probe_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x9bf1cc62 ad1848_unload +EXPORT_SYMBOL sound/oss/ad1848 0xb29a9148 unload_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0xc04f6f67 ad1848_control +EXPORT_SYMBOL sound/oss/ad1848 0xf06eb004 ad1848_detect +EXPORT_SYMBOL sound/oss/mpu401 0x3c4d8646 attach_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0x5febf284 unload_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0x8874e39a probe_mpu401 +EXPORT_SYMBOL sound/oss/sb_lib 0x3628ca3b sb_dsp_init +EXPORT_SYMBOL sound/oss/sb_lib 0x382ea9dd probe_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0x42424109 sb_be_quiet +EXPORT_SYMBOL sound/oss/sb_lib 0x450f9aea smw_free +EXPORT_SYMBOL sound/oss/sb_lib 0x74afd69c unload_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0xc4884969 sb_dsp_unload +EXPORT_SYMBOL sound/oss/sb_lib 0xd8a2731c sb_dsp_detect +EXPORT_SYMBOL sound/oss/sound 0x04c87ec8 compute_finetune +EXPORT_SYMBOL sound/oss/sound 0x06339815 sound_unload_synthdev +EXPORT_SYMBOL sound/oss/sound 0x0f280035 conf_printf +EXPORT_SYMBOL sound/oss/sound 0x17ba231d seq_input_event +EXPORT_SYMBOL sound/oss/sound 0x1b3df3cf sound_alloc_mixerdev +EXPORT_SYMBOL sound/oss/sound 0x1f395686 MIDIbuf_avail +EXPORT_SYMBOL sound/oss/sound 0x2161d5e8 sound_timer_init +EXPORT_SYMBOL sound/oss/sound 0x242f0eb6 sound_install_audiodrv +EXPORT_SYMBOL sound/oss/sound 0x2aa31695 midi_synth_kill_note +EXPORT_SYMBOL sound/oss/sound 0x362b1ad1 synth_devs +EXPORT_SYMBOL sound/oss/sound 0x394cb088 sound_free_dma +EXPORT_SYMBOL sound/oss/sound 0x418f5fbe sound_close_dma +EXPORT_SYMBOL sound/oss/sound 0x4cd01bdd num_audiodevs +EXPORT_SYMBOL sound/oss/sound 0x4ff47e9d midi_synth_setup_voice +EXPORT_SYMBOL sound/oss/sound 0x51e354b2 sound_alloc_timerdev +EXPORT_SYMBOL sound/oss/sound 0x56504ca2 midi_synth_reset +EXPORT_SYMBOL sound/oss/sound 0x5d986fc9 note_to_freq +EXPORT_SYMBOL sound/oss/sound 0x6e2864a5 audio_devs +EXPORT_SYMBOL sound/oss/sound 0x7679ee76 seq_copy_to_input +EXPORT_SYMBOL sound/oss/sound 0x7bdf0907 conf_printf2 +EXPORT_SYMBOL sound/oss/sound 0x892093e0 midi_synth_controller +EXPORT_SYMBOL sound/oss/sound 0x8a760bd6 mixer_devs +EXPORT_SYMBOL sound/oss/sound 0x90bd9714 sequencer_timer +EXPORT_SYMBOL sound/oss/sound 0x987bcf12 DMAbuf_outputintr +EXPORT_SYMBOL sound/oss/sound 0x9a95733f sound_alloc_dma +EXPORT_SYMBOL sound/oss/sound 0x9bdaf24d midi_synth_start_note +EXPORT_SYMBOL sound/oss/sound 0x9d845b18 num_mixers +EXPORT_SYMBOL sound/oss/sound 0xa1d5f04f load_mixer_volumes +EXPORT_SYMBOL sound/oss/sound 0xa1eae7cf num_midis +EXPORT_SYMBOL sound/oss/sound 0xa41ead5f sound_unload_timerdev +EXPORT_SYMBOL sound/oss/sound 0xa51c913b sound_unload_mixerdev +EXPORT_SYMBOL sound/oss/sound 0xa6bb414c sound_unload_mididev +EXPORT_SYMBOL sound/oss/sound 0xa948751e sound_unload_audiodev +EXPORT_SYMBOL sound/oss/sound 0xad45df73 midi_synth_close +EXPORT_SYMBOL sound/oss/sound 0xaef743b2 midi_synth_ioctl +EXPORT_SYMBOL sound/oss/sound 0xb14b22cd midi_synth_hw_control +EXPORT_SYMBOL sound/oss/sound 0xb51587f6 do_midi_msg +EXPORT_SYMBOL sound/oss/sound 0xb5a13106 midi_devs +EXPORT_SYMBOL sound/oss/sound 0xba413f87 sound_alloc_mididev +EXPORT_SYMBOL sound/oss/sound 0xba7dd041 midi_synth_bender +EXPORT_SYMBOL sound/oss/sound 0xc748d109 sound_alloc_synthdev +EXPORT_SYMBOL sound/oss/sound 0xcc4b8797 sound_open_dma +EXPORT_SYMBOL sound/oss/sound 0xd85be938 midi_synth_set_instr +EXPORT_SYMBOL sound/oss/sound 0xdb400afa midi_synth_panning +EXPORT_SYMBOL sound/oss/sound 0xdc54a0f5 sound_timer_devs +EXPORT_SYMBOL sound/oss/sound 0xe056b71c DMAbuf_start_dma +EXPORT_SYMBOL sound/oss/sound 0xe0f063ea sound_install_mixer +EXPORT_SYMBOL sound/oss/sound 0xe2675a79 sound_timer_interrupt +EXPORT_SYMBOL sound/oss/sound 0xeb315d99 DMAbuf_inputintr +EXPORT_SYMBOL sound/oss/sound 0xf1ea8a20 midi_synth_aftertouch +EXPORT_SYMBOL sound/oss/sound 0xf6b3a2fb midi_synth_open +EXPORT_SYMBOL sound/oss/sound 0xf7426da3 midi_synth_load_patch +EXPORT_SYMBOL sound/oss/sound 0xf78f6363 sequencer_init +EXPORT_SYMBOL sound/oss/sound 0xfa6871be sound_timer_syncinterval +EXPORT_SYMBOL sound/oss/sound 0xfddcbfb3 midi_synth_send_sysex +EXPORT_SYMBOL sound/oss/uart401 0x28aba148 probe_uart401 +EXPORT_SYMBOL sound/oss/uart401 0x46248c57 uart401intr +EXPORT_SYMBOL sound/oss/uart401 0xecfdd9c9 unload_uart401 +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x0459ac6f snd_ac97_update_bits +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x06ed3fe3 snd_ac97_set_rate +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x22a04d77 snd_ac97_mixer +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x37ffb04c snd_ac97_resume +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3859aa60 snd_ac97_pcm_double_rate_rules +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x49ca5dba snd_ac97_pcm_close +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x73a28e6d snd_ac97_bus +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x77e164ca snd_ac97_pcm_open +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x87404342 snd_ac97_update_power +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xa83cfca1 snd_ac97_pcm_assign +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xadb1b2ef snd_ac97_read +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xbb092a3d snd_ac97_write +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xc7f12f9f snd_ac97_update +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xca8746cb snd_ac97_write_cache +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xdf335ee4 snd_ac97_tune_hardware +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xe0a5c28d snd_ac97_suspend +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xe78031a0 snd_ac97_get_short_name +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x36d80be7 snd_emu10k1_synth_copy_from_user +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x3757c5fd snd_emu10k1_synth_alloc +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x4921492e snd_emu10k1_synth_free +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x7078a816 snd_emu10k1_ptr_write +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x7510c5aa snd_emu10k1_ptr_read +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x7bc212d2 snd_emu10k1_synth_bzero +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x9888139a snd_emu10k1_voice_free +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xa4ddd955 snd_emu10k1_memblk_map +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xe5089c95 snd_emu10k1_voice_alloc +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x2e5fc550 snd_ice1712_akm4xxx_free +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x8b01dd15 snd_ice1712_akm4xxx_build_controls +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x9b2a7973 snd_ice1712_akm4xxx_init +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x01d25c42 oxygen_read_ac97 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x0af697ee oxygen_write16_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x17224882 oxygen_write8_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x18012730 oxygen_write_i2c +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x2718e02a oxygen_write32_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x27cb218c oxygen_read8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x3d2ce0c4 oxygen_write_spi +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x3d8f644b oxygen_write32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x763d94bf oxygen_write16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x7c6b3621 oxygen_write_ac97 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x991cd0ad oxygen_pci_suspend +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xa49b8aec oxygen_read32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xabde90c5 oxygen_write8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xb936d39e oxygen_pci_probe +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xbd31e7c7 oxygen_write_ac97_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xc31b43ee oxygen_read16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xf12c708d oxygen_pci_remove +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xfae00a53 oxygen_pci_resume +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x0ced31d6 snd_trident_write_voice_regs +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x294843b3 snd_trident_stop_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x3583b7db snd_trident_alloc_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x3ece73b6 snd_trident_start_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0xfc12f22c snd_trident_free_voice +EXPORT_SYMBOL sound/sound_firmware 0x39e3dd23 mod_firmware_load +EXPORT_SYMBOL sound/soundcore 0x3938f613 register_sound_special_device +EXPORT_SYMBOL sound/soundcore 0x7afc9d8a unregister_sound_mixer +EXPORT_SYMBOL sound/soundcore 0x7b5cd1d0 register_sound_special +EXPORT_SYMBOL sound/soundcore 0x99c95fa5 unregister_sound_special +EXPORT_SYMBOL sound/soundcore 0xa95947c7 register_sound_mixer +EXPORT_SYMBOL sound/soundcore 0xc677eb49 register_sound_midi +EXPORT_SYMBOL sound/soundcore 0xcd083b10 unregister_sound_dsp +EXPORT_SYMBOL sound/soundcore 0xe0a9de2a sound_class +EXPORT_SYMBOL sound/soundcore 0xed861ae5 register_sound_dsp +EXPORT_SYMBOL sound/soundcore 0xfdab6de3 unregister_sound_midi +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x23684a6b snd_emux_lock_voice +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x51aea698 snd_emux_free +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x655cb202 snd_sf_linear_to_log +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xa1ec4bb0 snd_emux_unlock_voice +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xa1f20f8a snd_emux_terminate_all +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xd6a2fe7c snd_emux_register +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xdcc693c1 snd_emux_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0x20d65978 snd_util_memhdr_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x24886293 __snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0x569d614e snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x7a007343 snd_util_memhdr_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd197c5db __snd_util_memblk_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd34b56e4 __snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd8b55e81 snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0xf158252c snd_util_mem_avail +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x16756dc0 snd_usbmidi_input_start +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x37ff5894 snd_usb_create_midi_interface +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x63343b1d snd_usbmidi_input_stop +EXPORT_SYMBOL sound/usb/snd-usb-lib 0xd9d2bb03 snd_usbmidi_disconnect +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x53e9f657 dm_mem_cache_free +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x6f511415 dm_mem_cache_grow +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x89c6c8fe dm_mem_cache_client_destroy +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xcff2664e dm_mem_cache_shrink +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xe4172878 dm_mem_cache_alloc +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xf58b1b88 dm_mem_cache_client_create +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-message 0x920a7a41 dm_message_parse +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x0050f52c rh_get_region_key +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x0a3e284e rh_delay_by_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x275fdd04 rh_recovery_start +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x29e53a6b rh_dec +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x307f9cb7 rh_bio_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x3d1568a3 rh_delay +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x5c2a0632 rh_recovery_end +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x62842029 rh_flush +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x69f1df07 rh_init +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x83baca27 rh_state +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x87d45b9d rh_get_region_size +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xa923d788 rh_start_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xac274ed3 rh_stop_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xb513be98 rh_update_states +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xbb748327 rh_reg_set_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xbd3452f9 rh_sector_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4fdf256 rh_recovery_prepare +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4ff7745 rh_reg_get_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc57bafec rh_exit +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xce64fdd5 rh_inc_pending +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xe9f7f71a rh_region_to_sector +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xf3e0a2b0 rh_inc +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x29c887a9 set_tx_channels +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x7789312a cmdir_write +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0xf4c689aa cmdir_read +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x2f627e53 lirc_register_plugin +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x3af3b290 lirc_get_pdata +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0xe96379eb lirc_unregister_plugin +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0x5718c3b5 ov511_register_decomp_module +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0x7db9be3c ov511_deregister_decomp_module +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x01071e7e unregister_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x08ba5546 p80211netdev_hwremoved +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x2a4f3019 wlan_setup +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x65c7945e p80211netdev_rx +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x754cb318 p80211wext_event_associated +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x9a90a7a3 register_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xaa5a99b7 p80211_suspend +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb0af0799 wlan_wext_write +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb1ccd405 p80211_resume +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xcc211f66 p80211_allow_ioctls +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xd792c3ff p80211skb_rxmeta_attach +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xe42ae844 p80211skb_free +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xe94e5349 wlan_unsetup +EXPORT_SYMBOL vmlinux 0x00160db7 pid_task +EXPORT_SYMBOL vmlinux 0x004e4fed icmp_send +EXPORT_SYMBOL vmlinux 0x00801678 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x0080fcd6 tcf_hash_release +EXPORT_SYMBOL vmlinux 0x00928ae0 bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0x00983b3b lease_modify +EXPORT_SYMBOL vmlinux 0x009d258f _write_lock +EXPORT_SYMBOL vmlinux 0x00b6829d sync_inode +EXPORT_SYMBOL vmlinux 0x01000e51 schedule +EXPORT_SYMBOL vmlinux 0x010e220c dquot_commit_info +EXPORT_SYMBOL vmlinux 0x014e2714 blkdev_get +EXPORT_SYMBOL vmlinux 0x0164bf6a generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0x01836f06 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0x0186d073 percpu_counter_set +EXPORT_SYMBOL vmlinux 0x01902adf netpoll_trap +EXPORT_SYMBOL vmlinux 0x01a4aab6 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x01bbb111 blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0x01d19038 acpi_enable_subsystem +EXPORT_SYMBOL vmlinux 0x02124474 ip_send_check +EXPORT_SYMBOL vmlinux 0x02138f9d bioset_integrity_create +EXPORT_SYMBOL vmlinux 0x0237b57a arch_unregister_cpu +EXPORT_SYMBOL vmlinux 0x023e1f0e __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0x0256389f bit_waitqueue +EXPORT_SYMBOL vmlinux 0x02649054 security_sock_rcv_skb +EXPORT_SYMBOL vmlinux 0x02861259 unlock_page +EXPORT_SYMBOL vmlinux 0x029444f0 native_read_tsc +EXPORT_SYMBOL vmlinux 0x02a18c74 nf_conntrack_destroy +EXPORT_SYMBOL vmlinux 0x02aff2f4 acpi_install_gpe_handler +EXPORT_SYMBOL vmlinux 0x02b59c84 neigh_seq_next +EXPORT_SYMBOL vmlinux 0x02bf18fa sock_no_listen +EXPORT_SYMBOL vmlinux 0x02d81845 audit_log_task_context +EXPORT_SYMBOL vmlinux 0x02e84d1b per_cpu__cpu_sibling_map +EXPORT_SYMBOL vmlinux 0x030c7514 input_get_keycode +EXPORT_SYMBOL vmlinux 0x03265651 dma_async_memcpy_pg_to_pg +EXPORT_SYMBOL vmlinux 0x0334da4e scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x0377231e __mpage_writepage +EXPORT_SYMBOL vmlinux 0x037a0cba kfree +EXPORT_SYMBOL vmlinux 0x039989e6 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0x03a99c3b rb_prev +EXPORT_SYMBOL vmlinux 0x03c06156 bitmap_fold +EXPORT_SYMBOL vmlinux 0x0422fe4a inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x0426914f simple_rmdir +EXPORT_SYMBOL vmlinux 0x042e3eed vfs_mkdir +EXPORT_SYMBOL vmlinux 0x044fbf49 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x0480612b tcp_sync_mss +EXPORT_SYMBOL vmlinux 0x0487f831 fb_find_best_display +EXPORT_SYMBOL vmlinux 0x049b4c0a tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0x04d8c750 release_perfctr_nmi +EXPORT_SYMBOL vmlinux 0x05747129 agp_free_page_array +EXPORT_SYMBOL vmlinux 0x058c75d9 acpi_get_pci_id +EXPORT_SYMBOL vmlinux 0x05adcbc2 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0x05cb8481 skb_pull +EXPORT_SYMBOL vmlinux 0x05eaa0d4 __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x05ebc344 pci_set_dma_mask +EXPORT_SYMBOL vmlinux 0x05faca83 bio_put +EXPORT_SYMBOL vmlinux 0x060378a0 open_by_devnum +EXPORT_SYMBOL vmlinux 0x061651be strcat +EXPORT_SYMBOL vmlinux 0x06339d04 mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x063b4a6a __inc_zone_page_state +EXPORT_SYMBOL vmlinux 0x067d8d35 security_release_secctx +EXPORT_SYMBOL vmlinux 0x06a485f2 __krealloc +EXPORT_SYMBOL vmlinux 0x06ba49ea blk_requeue_request +EXPORT_SYMBOL vmlinux 0x06d728b1 tcp_parse_md5sig_option +EXPORT_SYMBOL vmlinux 0x06e99340 ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0x06fadcba migrate_page +EXPORT_SYMBOL vmlinux 0x06fe2d74 sock_get_timestamp +EXPORT_SYMBOL vmlinux 0x06fe3b14 default_grn +EXPORT_SYMBOL vmlinux 0x070d6317 ps2_handle_response +EXPORT_SYMBOL vmlinux 0x0727c4f3 iowrite8 +EXPORT_SYMBOL vmlinux 0x07382a1b blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0x073dfa12 generate_resume_trace +EXPORT_SYMBOL vmlinux 0x075468bf vc_resize +EXPORT_SYMBOL vmlinux 0x0768dea5 nonseekable_open +EXPORT_SYMBOL vmlinux 0x0784ef79 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0x078ee80c idr_for_each +EXPORT_SYMBOL vmlinux 0x07923d1c kill_anon_super +EXPORT_SYMBOL vmlinux 0x0799aca4 local_bh_enable +EXPORT_SYMBOL vmlinux 0x079cd7f1 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x07a890c8 fb_alloc_cmap +EXPORT_SYMBOL vmlinux 0x07cc4a5d printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x082c3213 pci_root_buses +EXPORT_SYMBOL vmlinux 0x082f4056 nobh_write_begin +EXPORT_SYMBOL vmlinux 0x08a57919 init_file +EXPORT_SYMBOL vmlinux 0x08ad30e1 dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x08b3fab5 input_unregister_handle +EXPORT_SYMBOL vmlinux 0x08ffa95a locks_init_lock +EXPORT_SYMBOL vmlinux 0x0925f9eb d_prune_aliases +EXPORT_SYMBOL vmlinux 0x0933aae1 efi_enabled +EXPORT_SYMBOL vmlinux 0x0948cde9 num_physpages +EXPORT_SYMBOL vmlinux 0x09554a68 dma_set_mask +EXPORT_SYMBOL vmlinux 0x09775cdc kref_get +EXPORT_SYMBOL vmlinux 0x098431ba acpi_get_current_resources +EXPORT_SYMBOL vmlinux 0x098b71c6 fb_dealloc_cmap +EXPORT_SYMBOL vmlinux 0x0994c7c6 xfrm_state_add +EXPORT_SYMBOL vmlinux 0x09ad3994 create_empty_buffers +EXPORT_SYMBOL vmlinux 0x09c55cec schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x09cc758d keyring_search +EXPORT_SYMBOL vmlinux 0x09d29dff key_link +EXPORT_SYMBOL vmlinux 0x09d44df9 in_lock_functions +EXPORT_SYMBOL vmlinux 0x0a0377c8 bdi_register +EXPORT_SYMBOL vmlinux 0x0a2487e0 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x0a3cee20 netif_device_attach +EXPORT_SYMBOL vmlinux 0x0a6a8551 dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x0ab8ae31 __scm_send +EXPORT_SYMBOL vmlinux 0x0abc4abc dget_locked +EXPORT_SYMBOL vmlinux 0x0acb1a3c __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x0aed429b get_fs_type +EXPORT_SYMBOL vmlinux 0x0b14e5e1 sget +EXPORT_SYMBOL vmlinux 0x0b15192a seq_printf +EXPORT_SYMBOL vmlinux 0x0b1529b2 netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0x0b1beb31 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x0b240dcf elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0x0b52756f tty_unregister_driver +EXPORT_SYMBOL vmlinux 0x0b597f09 input_free_device +EXPORT_SYMBOL vmlinux 0x0b742fd7 simple_strtol +EXPORT_SYMBOL vmlinux 0x0b9206d0 bio_integrity_clone +EXPORT_SYMBOL vmlinux 0x0b9ccddf kill_pid +EXPORT_SYMBOL vmlinux 0x0ba1135a llc_mac_hdr_init +EXPORT_SYMBOL vmlinux 0x0bb4b0d6 dev_remove_pack +EXPORT_SYMBOL vmlinux 0x0bc87dda sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0x0be254a2 fsync_bdev +EXPORT_SYMBOL vmlinux 0x0beed7a6 unmap_mapping_range +EXPORT_SYMBOL vmlinux 0x0bf0751c nobh_truncate_page +EXPORT_SYMBOL vmlinux 0x0c00905e tcp_sendpage +EXPORT_SYMBOL vmlinux 0x0c5c69e3 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x0c5ef91b per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x0c6e297d nla_put +EXPORT_SYMBOL vmlinux 0x0c87c756 bio_split_pool +EXPORT_SYMBOL vmlinux 0x0cce1058 d_alloc_anon +EXPORT_SYMBOL vmlinux 0x0d076569 misc_deregister +EXPORT_SYMBOL vmlinux 0x0d26a76d _write_lock_irq +EXPORT_SYMBOL vmlinux 0x0d299512 acpi_bus_generate_proc_event +EXPORT_SYMBOL vmlinux 0x0d336c4c mpage_writepages +EXPORT_SYMBOL vmlinux 0x0d391c1b arp_create +EXPORT_SYMBOL vmlinux 0x0d3dda14 acpi_get_type +EXPORT_SYMBOL vmlinux 0x0d43e72f tcf_em_tree_destroy +EXPORT_SYMBOL vmlinux 0x0d542439 __ipv6_addr_type +EXPORT_SYMBOL vmlinux 0x0d8ab500 param_set_copystring +EXPORT_SYMBOL vmlinux 0x0da10ec3 security_sock_graft +EXPORT_SYMBOL vmlinux 0x0db3ca1d agp_create_memory +EXPORT_SYMBOL vmlinux 0x0ddab262 agp_generic_remove_memory +EXPORT_SYMBOL vmlinux 0x0e0252ec downgrade_write +EXPORT_SYMBOL vmlinux 0x0e175a77 block_write_full_page +EXPORT_SYMBOL vmlinux 0x0e52592a panic +EXPORT_SYMBOL vmlinux 0x0e580b38 tty_name +EXPORT_SYMBOL vmlinux 0x0e762d6e request_module +EXPORT_SYMBOL vmlinux 0x0e8094a2 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x0ea3a10a ip_setsockopt +EXPORT_SYMBOL vmlinux 0x0eb17dc8 new_inode +EXPORT_SYMBOL vmlinux 0x0f55cadd agp_generic_enable +EXPORT_SYMBOL vmlinux 0x0f7e8965 nf_unregister_hook +EXPORT_SYMBOL vmlinux 0x0f908a1f simple_lookup +EXPORT_SYMBOL vmlinux 0x0fae4315 kmem_cache_name +EXPORT_SYMBOL vmlinux 0x0faef0ed __tasklet_schedule +EXPORT_SYMBOL vmlinux 0x0fc5e8eb radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0x0fcf77c3 aio_put_req +EXPORT_SYMBOL vmlinux 0x0fd00a68 acpi_clear_event +EXPORT_SYMBOL vmlinux 0x0fe6b264 sock_release +EXPORT_SYMBOL vmlinux 0x10217991 rtnl_unicast +EXPORT_SYMBOL vmlinux 0x1027a012 inet_bind +EXPORT_SYMBOL vmlinux 0x103ede79 touch_atime +EXPORT_SYMBOL vmlinux 0x1055db10 pci_back_from_sleep +EXPORT_SYMBOL vmlinux 0x1072a394 csum_partial_copy_from_user +EXPORT_SYMBOL vmlinux 0x109f5dce inet_frag_find +EXPORT_SYMBOL vmlinux 0x10a96082 sock_register +EXPORT_SYMBOL vmlinux 0x10abb1c0 d_move +EXPORT_SYMBOL vmlinux 0x10ee20bb default_blu +EXPORT_SYMBOL vmlinux 0x10eece91 neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x111e09e4 input_set_keycode +EXPORT_SYMBOL vmlinux 0x114f7de3 dev_queue_xmit +EXPORT_SYMBOL vmlinux 0x11554b5e pci_scan_slot +EXPORT_SYMBOL vmlinux 0x116240db key_instantiate_and_link +EXPORT_SYMBOL vmlinux 0x1163f0a7 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x117093be qdisc_class_hash_init +EXPORT_SYMBOL vmlinux 0x117b13da skb_kill_datagram +EXPORT_SYMBOL vmlinux 0x11895b48 llc_sap_find +EXPORT_SYMBOL vmlinux 0x118f01ea putname +EXPORT_SYMBOL vmlinux 0x11a18b14 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x11b1fada sk_filter +EXPORT_SYMBOL vmlinux 0x11bc94cc sock_recvmsg +EXPORT_SYMBOL vmlinux 0x11dab346 __down_read +EXPORT_SYMBOL vmlinux 0x11f1d563 security_sb_clone_mnt_opts +EXPORT_SYMBOL vmlinux 0x1234bbb5 xfrm_register_km +EXPORT_SYMBOL vmlinux 0x125fbca7 cad_pid +EXPORT_SYMBOL vmlinux 0x1264546d nf_hook_slow +EXPORT_SYMBOL vmlinux 0x126970ed param_set_uint +EXPORT_SYMBOL vmlinux 0x12a891ca tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x12f2e8a8 agp_bind_memory +EXPORT_SYMBOL vmlinux 0x12f99022 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x130c44a7 alloc_disk_node +EXPORT_SYMBOL vmlinux 0x130da0e0 kmem_cache_create +EXPORT_SYMBOL vmlinux 0x132f45f2 cookie_check_timestamp +EXPORT_SYMBOL vmlinux 0x132ff366 unlock_rename +EXPORT_SYMBOL vmlinux 0x134cc7c7 blk_get_request +EXPORT_SYMBOL vmlinux 0x135169e4 skb_gso_segment +EXPORT_SYMBOL vmlinux 0x138c9f8b write_one_page +EXPORT_SYMBOL vmlinux 0x139350c1 vfs_permission +EXPORT_SYMBOL vmlinux 0x13d2c499 neigh_create +EXPORT_SYMBOL vmlinux 0x13d42874 wireless_spy_update +EXPORT_SYMBOL vmlinux 0x13ddb0bd pci_bus_write_config_word +EXPORT_SYMBOL vmlinux 0x13f1e33b end_request +EXPORT_SYMBOL vmlinux 0x13f71731 tcf_hash_lookup +EXPORT_SYMBOL vmlinux 0x1402791a agp_alloc_bridge +EXPORT_SYMBOL vmlinux 0x141a8542 pcie_port_service_register +EXPORT_SYMBOL vmlinux 0x14276ed3 skb_queue_purge +EXPORT_SYMBOL vmlinux 0x1430e6e0 unregister_acpi_notifier +EXPORT_SYMBOL vmlinux 0x14524d84 tcp_v4_md5_do_add +EXPORT_SYMBOL vmlinux 0x149acfdb blk_integrity_unregister +EXPORT_SYMBOL vmlinux 0x14abcddc vfs_link +EXPORT_SYMBOL vmlinux 0x14ad564d deactivate_super +EXPORT_SYMBOL vmlinux 0x14aee23d __xfrm_lookup +EXPORT_SYMBOL vmlinux 0x14af0cf7 gen_pool_destroy +EXPORT_SYMBOL vmlinux 0x14c326a5 bio_integrity_trim +EXPORT_SYMBOL vmlinux 0x14c87fe5 __tcp_get_md5sig_pool +EXPORT_SYMBOL vmlinux 0x14d375d2 eth_type_trans +EXPORT_SYMBOL vmlinux 0x1544aad4 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x1551dc51 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x1553522b compat_mc_getsockopt +EXPORT_SYMBOL vmlinux 0x15598dbc pagecache_write_end +EXPORT_SYMBOL vmlinux 0x15a3f0cf input_register_device +EXPORT_SYMBOL vmlinux 0x15a5bc68 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x15ecf610 _cpu_pda +EXPORT_SYMBOL vmlinux 0x15ef2dd9 kfifo_free +EXPORT_SYMBOL vmlinux 0x1611517c blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0x16175304 udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0x16381a1d bio_integrity_advance +EXPORT_SYMBOL vmlinux 0x16517eb7 pci_iounmap +EXPORT_SYMBOL vmlinux 0x1675606f bad_dma_address +EXPORT_SYMBOL vmlinux 0x167e7f9d __get_user_1 +EXPORT_SYMBOL vmlinux 0x169aef06 xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0x16a35878 _read_unlock +EXPORT_SYMBOL vmlinux 0x16ab954c ether_setup +EXPORT_SYMBOL vmlinux 0x16fd31ca stop_tty +EXPORT_SYMBOL vmlinux 0x1700fb1d tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0x170563e5 compat_nf_setsockopt +EXPORT_SYMBOL vmlinux 0x170a2bc3 pnp_unregister_card_driver +EXPORT_SYMBOL vmlinux 0x170c25ee acpi_get_next_object +EXPORT_SYMBOL vmlinux 0x1716e149 __getblk +EXPORT_SYMBOL vmlinux 0x1728580b bio_uncopy_user +EXPORT_SYMBOL vmlinux 0x172ed4d7 __vmalloc +EXPORT_SYMBOL vmlinux 0x173c990e iw_handler_set_thrspy +EXPORT_SYMBOL vmlinux 0x17737e63 proc_net_netfilter +EXPORT_SYMBOL vmlinux 0x17970e49 neigh_table_init +EXPORT_SYMBOL vmlinux 0x17a76e71 rb_first +EXPORT_SYMBOL vmlinux 0x17c85a66 radix_tree_tagged +EXPORT_SYMBOL vmlinux 0x17df17bc sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x17edced3 task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x17fd15cd call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0x181ae030 agp_flush_chipset +EXPORT_SYMBOL vmlinux 0x181b6ff2 mempool_resize +EXPORT_SYMBOL vmlinux 0x183fa88b mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x185219bf swiotlb_free_coherent +EXPORT_SYMBOL vmlinux 0x18857637 dentry_open +EXPORT_SYMBOL vmlinux 0x189b6bac memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x189eeb75 generic_getxattr +EXPORT_SYMBOL vmlinux 0x18ad0b56 tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0x18f47107 d_path +EXPORT_SYMBOL vmlinux 0x18f5188a key_put +EXPORT_SYMBOL vmlinux 0x1920b112 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x192576c1 tcf_destroy_chain +EXPORT_SYMBOL vmlinux 0x1930ddff inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0x1938fbf8 generic_file_open +EXPORT_SYMBOL vmlinux 0x19391763 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x19414812 skb_copy_bits +EXPORT_SYMBOL vmlinux 0x1985ed3c prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0x199e695b tc_classify +EXPORT_SYMBOL vmlinux 0x199ed0cd net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x19b3b457 generic_fillattr +EXPORT_SYMBOL vmlinux 0x19cdb332 __locks_copy_lock +EXPORT_SYMBOL vmlinux 0x19d5d20a acpi_walk_namespace +EXPORT_SYMBOL vmlinux 0x19e9a0bd tcf_exts_dump +EXPORT_SYMBOL vmlinux 0x19f6a3a5 blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0x19fc92bc netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0x1a1ab15d tty_mutex +EXPORT_SYMBOL vmlinux 0x1a3c1fdc neigh_lookup +EXPORT_SYMBOL vmlinux 0x1a45cb6c acpi_disabled +EXPORT_SYMBOL vmlinux 0x1a75caa3 _read_lock +EXPORT_SYMBOL vmlinux 0x1a760325 ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x1a8a845e idle_nomwait +EXPORT_SYMBOL vmlinux 0x1a9802d2 dquot_release +EXPORT_SYMBOL vmlinux 0x1ace138d bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x1ad156a8 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0x1adc4b23 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0x1ae8d7dc param_set_invbool +EXPORT_SYMBOL vmlinux 0x1b015d25 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x1b02f1bc pci_bus_alloc_resource +EXPORT_SYMBOL vmlinux 0x1b1384f6 kobject_add +EXPORT_SYMBOL vmlinux 0x1b198a2c uart_suspend_port +EXPORT_SYMBOL vmlinux 0x1b19a0ea pci_scan_bridge +EXPORT_SYMBOL vmlinux 0x1b3b863c pci_set_consistent_dma_mask +EXPORT_SYMBOL vmlinux 0x1b3c678a gen_new_estimator +EXPORT_SYMBOL vmlinux 0x1b6314fd in_aton +EXPORT_SYMBOL vmlinux 0x1b818707 dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x1b89419f add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x1b9981cc set_irq_wake +EXPORT_SYMBOL vmlinux 0x1b9b7d8c kernel_getsockopt +EXPORT_SYMBOL vmlinux 0x1baa9c86 node_to_cpumask_map +EXPORT_SYMBOL vmlinux 0x1baf49ef call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0x1bb84d7a vfs_rename +EXPORT_SYMBOL vmlinux 0x1bbac7cf dquot_acquire +EXPORT_SYMBOL vmlinux 0x1bc21a27 agp_generic_type_to_mask_type +EXPORT_SYMBOL vmlinux 0x1c054b1f sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x1c19fec9 register_con_driver +EXPORT_SYMBOL vmlinux 0x1c4a113f seq_putc +EXPORT_SYMBOL vmlinux 0x1c5f1b98 pci_find_capability +EXPORT_SYMBOL vmlinux 0x1c85a77a pcie_set_readrq +EXPORT_SYMBOL vmlinux 0x1c9b7c3b rtnl_create_link +EXPORT_SYMBOL vmlinux 0x1cb38de6 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0x1cc6719a register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x1cefe352 wait_for_completion +EXPORT_SYMBOL vmlinux 0x1cf3709f acpi_evaluate_integer +EXPORT_SYMBOL vmlinux 0x1d121e14 qdisc_destroy +EXPORT_SYMBOL vmlinux 0x1d264e30 swiotlb_dma_mapping_error +EXPORT_SYMBOL vmlinux 0x1d568e72 skb_put +EXPORT_SYMBOL vmlinux 0x1d830520 cpu_possible_map +EXPORT_SYMBOL vmlinux 0x1d842074 proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x1d866576 invalidate_partition +EXPORT_SYMBOL vmlinux 0x1db7706b __copy_user_nocache +EXPORT_SYMBOL vmlinux 0x1dc36131 fb_destroy_modedb +EXPORT_SYMBOL vmlinux 0x1dd571e6 fb_copy_cmap +EXPORT_SYMBOL vmlinux 0x1de03d0f blk_queue_ordered +EXPORT_SYMBOL vmlinux 0x1e02b03d generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x1e142e48 arch_acpi_processor_init_pdc +EXPORT_SYMBOL vmlinux 0x1e1fc55f pci_map_rom +EXPORT_SYMBOL vmlinux 0x1e2f5175 agp_generic_destroy_page +EXPORT_SYMBOL vmlinux 0x1e5b562e pci_bus_write_config_dword +EXPORT_SYMBOL vmlinux 0x1e5e5ec0 ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x1e6d26a8 strstr +EXPORT_SYMBOL vmlinux 0x1e7d41ce atm_dev_deregister +EXPORT_SYMBOL vmlinux 0x1e937dfd sock_wmalloc +EXPORT_SYMBOL vmlinux 0x1e963075 filp_open +EXPORT_SYMBOL vmlinux 0x1e9deb0d udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0x1edc77f8 kobject_set_name +EXPORT_SYMBOL vmlinux 0x1efe283f __cap_full_set +EXPORT_SYMBOL vmlinux 0x1f04966f complete_request_key +EXPORT_SYMBOL vmlinux 0x1f27d6d7 _write_unlock +EXPORT_SYMBOL vmlinux 0x1f3eacb7 xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0x1f7d9f83 get_sb_nodev +EXPORT_SYMBOL vmlinux 0x1f8249da generic_file_llseek +EXPORT_SYMBOL vmlinux 0x1f8b36d2 dma_pool_create +EXPORT_SYMBOL vmlinux 0x1f94f8a0 pci_enable_msi +EXPORT_SYMBOL vmlinux 0x1fa341be redraw_screen +EXPORT_SYMBOL vmlinux 0x1fceecfc iput +EXPORT_SYMBOL vmlinux 0x1fd59104 proc_dostring +EXPORT_SYMBOL vmlinux 0x20000329 simple_strtoul +EXPORT_SYMBOL vmlinux 0x2005e68a acpi_remove_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x20092385 acpi_enter_sleep_state_s4bios +EXPORT_SYMBOL vmlinux 0x2010469a dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0x20183f50 serio_unregister_port +EXPORT_SYMBOL vmlinux 0x203e7022 pci_request_selected_regions +EXPORT_SYMBOL vmlinux 0x2056f318 ida_get_new +EXPORT_SYMBOL vmlinux 0x205ed65d bdevname +EXPORT_SYMBOL vmlinux 0x208739f6 acpi_load_table +EXPORT_SYMBOL vmlinux 0x20a099e9 thermal_zone_bind_cooling_device +EXPORT_SYMBOL vmlinux 0x20c74d9f kobject_put +EXPORT_SYMBOL vmlinux 0x20c8fc33 pci_osc_control_set +EXPORT_SYMBOL vmlinux 0x20eadeb6 ip_compute_csum +EXPORT_SYMBOL vmlinux 0x21033e88 pnp_disable_dev +EXPORT_SYMBOL vmlinux 0x214701b5 agp3_generic_tlbflush +EXPORT_SYMBOL vmlinux 0x215ebd78 bitrev16 +EXPORT_SYMBOL vmlinux 0x21731ef2 security_task_getsecid +EXPORT_SYMBOL vmlinux 0x21a52974 iget_locked +EXPORT_SYMBOL vmlinux 0x21e0ea22 acpi_get_id +EXPORT_SYMBOL vmlinux 0x21e5679c copy_user_generic +EXPORT_SYMBOL vmlinux 0x222e7ce2 sysfs_streq +EXPORT_SYMBOL vmlinux 0x2253c959 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0x22599c74 vfs_rmdir +EXPORT_SYMBOL vmlinux 0x226e86a9 audit_log +EXPORT_SYMBOL vmlinux 0x2288378f system_state +EXPORT_SYMBOL vmlinux 0x228ae3b6 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0x228c214f serio_unregister_child_port +EXPORT_SYMBOL vmlinux 0x22a73912 __tcp_put_md5sig_pool +EXPORT_SYMBOL vmlinux 0x22b325d5 kd_mksound +EXPORT_SYMBOL vmlinux 0x22b33054 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x22b6533b xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x22cede8e brioctl_set +EXPORT_SYMBOL vmlinux 0x22e9512e swiotlb_sync_sg_for_device +EXPORT_SYMBOL vmlinux 0x22f429fa atm_proc_root +EXPORT_SYMBOL vmlinux 0x23191475 dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x231f3a66 __kfifo_put +EXPORT_SYMBOL vmlinux 0x23269a13 strict_strtoul +EXPORT_SYMBOL vmlinux 0x23388d20 generic_ro_fops +EXPORT_SYMBOL vmlinux 0x234509f3 strncat +EXPORT_SYMBOL vmlinux 0x236c8c64 memcpy +EXPORT_SYMBOL vmlinux 0x2395d028 get_unmapped_area +EXPORT_SYMBOL vmlinux 0x2398f7d0 pci_find_slot +EXPORT_SYMBOL vmlinux 0x23a794dc in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x23a7a3bd maps_protect +EXPORT_SYMBOL vmlinux 0x23b6a266 dev_change_flags +EXPORT_SYMBOL vmlinux 0x23b99e92 node_states +EXPORT_SYMBOL vmlinux 0x23f282dc netif_receive_skb +EXPORT_SYMBOL vmlinux 0x23f2d36f memparse +EXPORT_SYMBOL vmlinux 0x23fd3028 vmalloc_node +EXPORT_SYMBOL vmlinux 0x2424fa4e udp_disconnect +EXPORT_SYMBOL vmlinux 0x24428be5 strncpy_from_user +EXPORT_SYMBOL vmlinux 0x2459bbcc console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x2464c1f8 dev_unicast_add +EXPORT_SYMBOL vmlinux 0x247bfc2d km_policy_notify +EXPORT_SYMBOL vmlinux 0x24a1ce10 xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0x24fdac79 wake_bit_function +EXPORT_SYMBOL vmlinux 0x2508da33 register_netdev +EXPORT_SYMBOL vmlinux 0x2517a3aa dma_async_client_register +EXPORT_SYMBOL vmlinux 0x253114ac set_bdi_congested +EXPORT_SYMBOL vmlinux 0x255e4499 netif_carrier_off +EXPORT_SYMBOL vmlinux 0x25612803 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0x256887e1 warn_slowpath +EXPORT_SYMBOL vmlinux 0x256d641a netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x25820c64 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x258355b4 fb_find_best_mode +EXPORT_SYMBOL vmlinux 0x25911183 netlink_dump_start +EXPORT_SYMBOL vmlinux 0x259c6c01 dma_pool_destroy +EXPORT_SYMBOL vmlinux 0x25bd4aae skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x25d8ae18 skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0x25ec1b28 strlen +EXPORT_SYMBOL vmlinux 0x26112ede mpage_bio_submit +EXPORT_SYMBOL vmlinux 0x263782b5 cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0x266689e2 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x2685c3d7 __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x268a9d70 neigh_parms_release +EXPORT_SYMBOL vmlinux 0x268d0793 put_filp +EXPORT_SYMBOL vmlinux 0x26c0315c grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0x26c16dc1 tcp_tso_segment +EXPORT_SYMBOL vmlinux 0x26cac698 dquot_mark_dquot_dirty +EXPORT_SYMBOL vmlinux 0x26e76fb8 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x26ef08d4 pci_find_next_bus +EXPORT_SYMBOL vmlinux 0x272d394e mtrr_del +EXPORT_SYMBOL vmlinux 0x272e7488 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x273f066e _write_unlock_irq +EXPORT_SYMBOL vmlinux 0x27513339 km_query +EXPORT_SYMBOL vmlinux 0x277d99db __next_cpu +EXPORT_SYMBOL vmlinux 0x27802a95 acpi_bus_get_status +EXPORT_SYMBOL vmlinux 0x279c8bf9 kthread_create +EXPORT_SYMBOL vmlinux 0x27a9a7eb ns_to_timespec +EXPORT_SYMBOL vmlinux 0x27ba7feb arp_send +EXPORT_SYMBOL vmlinux 0x27bbf221 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x27c33efe csum_ipv6_magic +EXPORT_SYMBOL vmlinux 0x27c61ece qdisc_put_stab +EXPORT_SYMBOL vmlinux 0x281b8c5c nf_ct_attach +EXPORT_SYMBOL vmlinux 0x285ac517 strict_strtoll +EXPORT_SYMBOL vmlinux 0x2876a6d3 memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x288ab8fd blk_queue_bounce +EXPORT_SYMBOL vmlinux 0x2896f1d5 inet_put_port +EXPORT_SYMBOL vmlinux 0x28dcf25c udplite_hash +EXPORT_SYMBOL vmlinux 0x2906d2ea follow_up +EXPORT_SYMBOL vmlinux 0x290e52c6 tcp_alloc_md5sig_pool +EXPORT_SYMBOL vmlinux 0x29161825 blk_register_region +EXPORT_SYMBOL vmlinux 0x292931d8 write_cache_pages +EXPORT_SYMBOL vmlinux 0x29384519 seq_release +EXPORT_SYMBOL vmlinux 0x2949b436 ip_fragment +EXPORT_SYMBOL vmlinux 0x29537c9e alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x29688a32 kernel_listen +EXPORT_SYMBOL vmlinux 0x296f3ccc idr_remove_all +EXPORT_SYMBOL vmlinux 0x299066aa pci_get_slot +EXPORT_SYMBOL vmlinux 0x29a138a7 do_SAK +EXPORT_SYMBOL vmlinux 0x29bd4c46 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x29e7efdf bdev_read_only +EXPORT_SYMBOL vmlinux 0x2a303d4d check_signature +EXPORT_SYMBOL vmlinux 0x2a4832c4 sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x2a8986ba thermal_cooling_device_unregister +EXPORT_SYMBOL vmlinux 0x2a8b5483 pci_do_scan_bus +EXPORT_SYMBOL vmlinux 0x2a94d9f0 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0x2aae0e76 pci_dev_put +EXPORT_SYMBOL vmlinux 0x2ad296d3 sock_no_connect +EXPORT_SYMBOL vmlinux 0x2ae23eb9 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0x2aeb2800 mempool_create_node +EXPORT_SYMBOL vmlinux 0x2b0b412a pcibios_align_resource +EXPORT_SYMBOL vmlinux 0x2b12cb05 security_sk_classify_flow +EXPORT_SYMBOL vmlinux 0x2b39eb1e fb_show_logo +EXPORT_SYMBOL vmlinux 0x2b3e8182 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0x2b6aac8c tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x2ba476ec security_inode_init_security +EXPORT_SYMBOL vmlinux 0x2ba707a8 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x2bb0ad10 agp_unbind_memory +EXPORT_SYMBOL vmlinux 0x2bb55d6e acpi_remove_notify_handler +EXPORT_SYMBOL vmlinux 0x2bd3f983 boot_cpu_data +EXPORT_SYMBOL vmlinux 0x2be09893 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x2bf710b5 set_blocksize +EXPORT_SYMBOL vmlinux 0x2bfeb410 acpi_get_handle +EXPORT_SYMBOL vmlinux 0x2c53fea2 init_buffer +EXPORT_SYMBOL vmlinux 0x2c5749e6 acpi_clear_gpe +EXPORT_SYMBOL vmlinux 0x2c861f98 misc_register +EXPORT_SYMBOL vmlinux 0x2cb426c5 netpoll_cleanup +EXPORT_SYMBOL vmlinux 0x2cc2d52d vcc_hash +EXPORT_SYMBOL vmlinux 0x2cd9e459 param_set_short +EXPORT_SYMBOL vmlinux 0x2cf190e3 request_irq +EXPORT_SYMBOL vmlinux 0x2d18799d blk_free_tags +EXPORT_SYMBOL vmlinux 0x2d4613ec register_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0x2d5528c9 sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0x2d8320d1 register_framebuffer +EXPORT_SYMBOL vmlinux 0x2d933cf6 netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0x2d9fce67 skb_over_panic +EXPORT_SYMBOL vmlinux 0x2dc1cc4a fd_install +EXPORT_SYMBOL vmlinux 0x2dc7a5fb ip_route_me_harder +EXPORT_SYMBOL vmlinux 0x2dd16564 arch_register_cpu +EXPORT_SYMBOL vmlinux 0x2ddbfdc2 tcp_poll +EXPORT_SYMBOL vmlinux 0x2de9f66f param_get_long +EXPORT_SYMBOL vmlinux 0x2dedc4c2 acpi_format_exception +EXPORT_SYMBOL vmlinux 0x2def7f76 rtc_cmos_write +EXPORT_SYMBOL vmlinux 0x2df5173d skb_copy_expand +EXPORT_SYMBOL vmlinux 0x2e10c1b1 tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0x2e21643d compat_mc_setsockopt +EXPORT_SYMBOL vmlinux 0x2e2ce9e0 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x2e36655e swiotlb_map_single_attrs +EXPORT_SYMBOL vmlinux 0x2e41952c bio_clone +EXPORT_SYMBOL vmlinux 0x2e4a39f8 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x2e972b59 flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0x2ea86135 generic_read_dir +EXPORT_SYMBOL vmlinux 0x2eb16618 neigh_event_ns +EXPORT_SYMBOL vmlinux 0x2eb9a0e8 _read_lock_irq +EXPORT_SYMBOL vmlinux 0x2ebed99b skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0x2edd8d00 pci_bus_assign_resources +EXPORT_SYMBOL vmlinux 0x2f227565 tcp_v4_md5_do_del +EXPORT_SYMBOL vmlinux 0x2f2f0209 get_sb_bdev +EXPORT_SYMBOL vmlinux 0x2f35f31b block_prepare_write +EXPORT_SYMBOL vmlinux 0x2f547582 dev_getbyhwaddr +EXPORT_SYMBOL vmlinux 0x2f580481 input_register_handler +EXPORT_SYMBOL vmlinux 0x2f607d84 acpi_bus_start +EXPORT_SYMBOL vmlinux 0x2f70ba03 vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x2f80be75 check_disk_change +EXPORT_SYMBOL vmlinux 0x2f853cb5 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x2fa5a500 memcmp +EXPORT_SYMBOL vmlinux 0x2fb30cbd simple_write_begin +EXPORT_SYMBOL vmlinux 0x2fd24c19 bio_integrity_alloc_bioset +EXPORT_SYMBOL vmlinux 0x2fd4f7c3 blk_rq_map_user +EXPORT_SYMBOL vmlinux 0x2fdd6221 sysctl_jiffies +EXPORT_SYMBOL vmlinux 0x2ff063b5 acpi_get_name +EXPORT_SYMBOL vmlinux 0x2ff24d79 dquot_alloc_inode +EXPORT_SYMBOL vmlinux 0x2ff7efaa tcf_hash_new_index +EXPORT_SYMBOL vmlinux 0x300db8e0 thermal_zone_device_register +EXPORT_SYMBOL vmlinux 0x301cdbff user_revoke +EXPORT_SYMBOL vmlinux 0x30226ddf agp_device_command +EXPORT_SYMBOL vmlinux 0x302466e2 neigh_seq_start +EXPORT_SYMBOL vmlinux 0x306bd3c3 vfs_fstat +EXPORT_SYMBOL vmlinux 0x30896043 __any_online_cpu +EXPORT_SYMBOL vmlinux 0x30a94c37 pci_reenable_device +EXPORT_SYMBOL vmlinux 0x30c2b783 vfs_readv +EXPORT_SYMBOL vmlinux 0x30c5ac52 pnp_unregister_driver +EXPORT_SYMBOL vmlinux 0x30de8b2e copy_io_context +EXPORT_SYMBOL vmlinux 0x30e74134 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x30f3a5ef make_EII_client +EXPORT_SYMBOL vmlinux 0x30fe83a7 pci_remove_bus +EXPORT_SYMBOL vmlinux 0x312a789d vfs_symlink +EXPORT_SYMBOL vmlinux 0x3132f872 load_nls +EXPORT_SYMBOL vmlinux 0x3140217b blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0x3145216f pci_dev_present +EXPORT_SYMBOL vmlinux 0x3147857d default_red +EXPORT_SYMBOL vmlinux 0x3147c6ef dev_set_mtu +EXPORT_SYMBOL vmlinux 0x31616d67 textsearch_find_continuous +EXPORT_SYMBOL vmlinux 0x31b31f5c csum_partial_copy_nocheck +EXPORT_SYMBOL vmlinux 0x31c5a4c0 dcache_readdir +EXPORT_SYMBOL vmlinux 0x31d53936 bdi_destroy +EXPORT_SYMBOL vmlinux 0x31ebadcd in_group_p +EXPORT_SYMBOL vmlinux 0x322fe5bb pci_release_region +EXPORT_SYMBOL vmlinux 0x323d3887 tcp_v4_connect +EXPORT_SYMBOL vmlinux 0x326ba0c4 km_report +EXPORT_SYMBOL vmlinux 0x32a2988b filemap_flush +EXPORT_SYMBOL vmlinux 0x32b00695 sock_i_uid +EXPORT_SYMBOL vmlinux 0x32b0ac0b dquot_alloc_space +EXPORT_SYMBOL vmlinux 0x32b5e86d bio_init +EXPORT_SYMBOL vmlinux 0x32d01fec acpi_attach_data +EXPORT_SYMBOL vmlinux 0x32ee1827 pci_add_new_bus +EXPORT_SYMBOL vmlinux 0x32f87920 inet_frag_kill +EXPORT_SYMBOL vmlinux 0x32ff5757 agp_put_bridge +EXPORT_SYMBOL vmlinux 0x330d1c6a simple_getattr +EXPORT_SYMBOL vmlinux 0x330d556f gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0x3360a963 param_set_ulong +EXPORT_SYMBOL vmlinux 0x33619d38 ip_route_input +EXPORT_SYMBOL vmlinux 0x33a92a0d read_dev_sector +EXPORT_SYMBOL vmlinux 0x33af1a28 compat_sock_get_timestamp +EXPORT_SYMBOL vmlinux 0x33b70512 set_page_dirty +EXPORT_SYMBOL vmlinux 0x33b84f74 copy_page +EXPORT_SYMBOL vmlinux 0x33cda660 posix_acl_from_mode +EXPORT_SYMBOL vmlinux 0x33d92f9a prepare_to_wait +EXPORT_SYMBOL vmlinux 0x33dc1681 mark_info_dirty +EXPORT_SYMBOL vmlinux 0x33ef5176 arp_broken_ops +EXPORT_SYMBOL vmlinux 0x3421272c efi +EXPORT_SYMBOL vmlinux 0x3448a9e8 ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0x34722573 ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0x349cba85 strchr +EXPORT_SYMBOL vmlinux 0x34c1babf swiotlb_sync_sg_for_cpu +EXPORT_SYMBOL vmlinux 0x34c5b8c4 compat_sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x34c65500 llc_build_and_send_ui_pkt +EXPORT_SYMBOL vmlinux 0x34e42850 update_region +EXPORT_SYMBOL vmlinux 0x3509f037 pci_choose_state +EXPORT_SYMBOL vmlinux 0x35924bba atm_dev_register +EXPORT_SYMBOL vmlinux 0x35a07e32 vfs_stat +EXPORT_SYMBOL vmlinux 0x35a6dda2 register_8022_client +EXPORT_SYMBOL vmlinux 0x35b0650f vsnprintf +EXPORT_SYMBOL vmlinux 0x35c2ba9e refrigerator +EXPORT_SYMBOL vmlinux 0x35c51a8e blk_stop_queue +EXPORT_SYMBOL vmlinux 0x35e1a1ca pskb_expand_head +EXPORT_SYMBOL vmlinux 0x35f0e1d3 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0x360b1afe probe_irq_mask +EXPORT_SYMBOL vmlinux 0x3613049b ipv6_skip_exthdr +EXPORT_SYMBOL vmlinux 0x36139a51 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x361bab89 vfs_set_dqinfo +EXPORT_SYMBOL vmlinux 0x3624f4fa bio_unmap_user +EXPORT_SYMBOL vmlinux 0x363ad247 cap_set_effective +EXPORT_SYMBOL vmlinux 0x36556ac0 register_console +EXPORT_SYMBOL vmlinux 0x3656bf5a lock_kernel +EXPORT_SYMBOL vmlinux 0x366875b2 vfs_follow_link +EXPORT_SYMBOL vmlinux 0x366ba4ce register_filesystem +EXPORT_SYMBOL vmlinux 0x36a2cb07 thaw_bdev +EXPORT_SYMBOL vmlinux 0x3701a196 csum_partial_copy_to_user +EXPORT_SYMBOL vmlinux 0x3744cf36 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x374ed338 tty_write_room +EXPORT_SYMBOL vmlinux 0x37536590 bd_claim +EXPORT_SYMBOL vmlinux 0x375465a7 radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x3754efc4 acpi_bus_get_device +EXPORT_SYMBOL vmlinux 0x3773cb56 d_lookup +EXPORT_SYMBOL vmlinux 0x3777c625 __mod_zone_page_state +EXPORT_SYMBOL vmlinux 0x379d7e0e nf_register_hooks +EXPORT_SYMBOL vmlinux 0x37a8852f vfs_quota_sync +EXPORT_SYMBOL vmlinux 0x37b3ac06 posix_acl_permission +EXPORT_SYMBOL vmlinux 0x37befc70 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x37ee23ca datagram_poll +EXPORT_SYMBOL vmlinux 0x3850337f swiotlb_unmap_single +EXPORT_SYMBOL vmlinux 0x385bab81 blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x387b9f28 fb_pan_display +EXPORT_SYMBOL vmlinux 0x38987045 dput +EXPORT_SYMBOL vmlinux 0x38b92846 llc_remove_pack +EXPORT_SYMBOL vmlinux 0x38ea10b8 neigh_compat_output +EXPORT_SYMBOL vmlinux 0x38f33bed dump_fpu +EXPORT_SYMBOL vmlinux 0x38fc72ee compute_creds +EXPORT_SYMBOL vmlinux 0x39170a6c acpi_check_resource_conflict +EXPORT_SYMBOL vmlinux 0x396d2893 __page_symlink +EXPORT_SYMBOL vmlinux 0x3980aac1 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x39a5cad6 ida_destroy +EXPORT_SYMBOL vmlinux 0x39a6ea6f proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0x39c16f1e release_firmware +EXPORT_SYMBOL vmlinux 0x39c6d8fa mnt_unpin +EXPORT_SYMBOL vmlinux 0x39cd891a __down_write_trylock +EXPORT_SYMBOL vmlinux 0x3a114600 xfrm_register_type +EXPORT_SYMBOL vmlinux 0x3a1a367e d_alloc_root +EXPORT_SYMBOL vmlinux 0x3a2204c6 security_netlink_recv +EXPORT_SYMBOL vmlinux 0x3a2b2c17 dentry_unhash +EXPORT_SYMBOL vmlinux 0x3a63a8f8 dec_zone_page_state +EXPORT_SYMBOL vmlinux 0x3a72f51b request_firmware +EXPORT_SYMBOL vmlinux 0x3a7b7620 bdput +EXPORT_SYMBOL vmlinux 0x3a8ad091 generic_write_checks +EXPORT_SYMBOL vmlinux 0x3a9b6fb9 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x3a9bfe96 scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0x3aa1dbcf _spin_unlock_bh +EXPORT_SYMBOL vmlinux 0x3ab4d55b skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0x3b06bc64 pcim_iomap_table +EXPORT_SYMBOL vmlinux 0x3b241c39 pcie_port_service_unregister +EXPORT_SYMBOL vmlinux 0x3b3016d3 cpufreq_unregister_notifier +EXPORT_SYMBOL vmlinux 0x3b67cbbf __init_rwsem +EXPORT_SYMBOL vmlinux 0x3b758985 igrab +EXPORT_SYMBOL vmlinux 0x3b8b497a vcc_insert_socket +EXPORT_SYMBOL vmlinux 0x3b99acf1 blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0x3bb11fed unregister_framebuffer +EXPORT_SYMBOL vmlinux 0x3bcba798 gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0x3bd1b1f6 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x3bf4a7d8 __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x3c0cba13 set_pages_uc +EXPORT_SYMBOL vmlinux 0x3c2c5af5 sprintf +EXPORT_SYMBOL vmlinux 0x3c476e6f call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0x3c7227bf complete_all +EXPORT_SYMBOL vmlinux 0x3ca6dd26 udp_sendmsg +EXPORT_SYMBOL vmlinux 0x3cafe875 __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0x3cb8a495 param_get_string +EXPORT_SYMBOL vmlinux 0x3cc0a3bb xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x3cc233a8 security_d_instantiate +EXPORT_SYMBOL vmlinux 0x3cd49281 set_trace_device +EXPORT_SYMBOL vmlinux 0x3ce4ca6f disable_irq +EXPORT_SYMBOL vmlinux 0x3d02b406 generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0x3d5edc82 write_inode_now +EXPORT_SYMBOL vmlinux 0x3d6f4f80 pci_save_state +EXPORT_SYMBOL vmlinux 0x3d808ab6 fail_migrate_page +EXPORT_SYMBOL vmlinux 0x3d93363a inet_del_protocol +EXPORT_SYMBOL vmlinux 0x3d9ee9f0 clear_page +EXPORT_SYMBOL vmlinux 0x3da171f9 pci_mem_start +EXPORT_SYMBOL vmlinux 0x3da5eb6d kfifo_alloc +EXPORT_SYMBOL vmlinux 0x3db2e258 radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x3e1f073d wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x3e219de6 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x3e2427a1 acpi_check_region +EXPORT_SYMBOL vmlinux 0x3e2abd0d inode_double_unlock +EXPORT_SYMBOL vmlinux 0x3e2ae3a8 acpi_release_global_lock +EXPORT_SYMBOL vmlinux 0x3e427531 pnp_device_detach +EXPORT_SYMBOL vmlinux 0x3e4445f5 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x3e45e9ff register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x3e9700f2 agp_generic_alloc_by_type +EXPORT_SYMBOL vmlinux 0x3ec79280 poll_initwait +EXPORT_SYMBOL vmlinux 0x3ed63055 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x3f0546a8 ioread32_rep +EXPORT_SYMBOL vmlinux 0x3f054767 hippi_type_trans +EXPORT_SYMBOL vmlinux 0x3f1899f1 up +EXPORT_SYMBOL vmlinux 0x3f4547a7 put_unused_fd +EXPORT_SYMBOL vmlinux 0x3f72147c skb_queue_tail +EXPORT_SYMBOL vmlinux 0x3f7d72a1 flush_old_exec +EXPORT_SYMBOL vmlinux 0x3fa913da strspn +EXPORT_SYMBOL vmlinux 0x3faa8457 pci_request_region +EXPORT_SYMBOL vmlinux 0x3fbcddc3 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x3fec048f sg_next +EXPORT_SYMBOL vmlinux 0x3ff186a3 sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0x3ff62317 local_bh_disable +EXPORT_SYMBOL vmlinux 0x401e1c5f lock_rename +EXPORT_SYMBOL vmlinux 0x4039dd0c bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x405c1144 get_seconds +EXPORT_SYMBOL vmlinux 0x4074cbd6 request_firmware_nowait +EXPORT_SYMBOL vmlinux 0x408285f4 sk_stream_write_space +EXPORT_SYMBOL vmlinux 0x40935dc8 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0x409873e3 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x40a92a4b __pci_register_driver +EXPORT_SYMBOL vmlinux 0x40c89d46 acpi_get_table_by_index +EXPORT_SYMBOL vmlinux 0x40ef87a0 blk_unplug +EXPORT_SYMBOL vmlinux 0x4108e69a fb_match_mode +EXPORT_SYMBOL vmlinux 0x41315bc7 submit_bio +EXPORT_SYMBOL vmlinux 0x413818b1 put_tty_driver +EXPORT_SYMBOL vmlinux 0x41482d8b strndup_user +EXPORT_SYMBOL vmlinux 0x41711c46 seq_puts +EXPORT_SYMBOL vmlinux 0x4188d439 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x41a7c227 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x41a9c68d _spin_trylock_bh +EXPORT_SYMBOL vmlinux 0x41b3f40c dst_alloc +EXPORT_SYMBOL vmlinux 0x41ccc474 security_req_classify_flow +EXPORT_SYMBOL vmlinux 0x4211c3c1 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x42224298 sscanf +EXPORT_SYMBOL vmlinux 0x4225b265 tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x422c05d0 acpi_get_data +EXPORT_SYMBOL vmlinux 0x42a4bdf2 in_egroup_p +EXPORT_SYMBOL vmlinux 0x42b4db52 nf_register_queue_handler +EXPORT_SYMBOL vmlinux 0x42b9976b fb_blank +EXPORT_SYMBOL vmlinux 0x42d53a7f secpath_dup +EXPORT_SYMBOL vmlinux 0x4302d0eb free_pages +EXPORT_SYMBOL vmlinux 0x430a0ef3 set_user_nice +EXPORT_SYMBOL vmlinux 0x431c6b9d dev_alloc_name +EXPORT_SYMBOL vmlinux 0x4327f0d5 memset_io +EXPORT_SYMBOL vmlinux 0x43385ad9 acpi_pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x434fa55c release_console_sem +EXPORT_SYMBOL vmlinux 0x435b566d _spin_unlock +EXPORT_SYMBOL vmlinux 0x436bd315 posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0x436c2179 iowrite32 +EXPORT_SYMBOL vmlinux 0x437c50f7 end_dequeued_request +EXPORT_SYMBOL vmlinux 0x43ba7d6c backlight_device_register +EXPORT_SYMBOL vmlinux 0x43bdd372 request_resource +EXPORT_SYMBOL vmlinux 0x43be8bf3 pci_prepare_to_sleep +EXPORT_SYMBOL vmlinux 0x43ec913a put_cmsg +EXPORT_SYMBOL vmlinux 0x43f476c1 xfrm_state_update +EXPORT_SYMBOL vmlinux 0x44161c19 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x441b9b68 skb_make_writable +EXPORT_SYMBOL vmlinux 0x4423ea64 tty_hangup +EXPORT_SYMBOL vmlinux 0x4425ef6f skb_checksum_help +EXPORT_SYMBOL vmlinux 0x444779c4 nla_find +EXPORT_SYMBOL vmlinux 0x44531844 pskb_copy +EXPORT_SYMBOL vmlinux 0x4463a537 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0x44758928 proto_register +EXPORT_SYMBOL vmlinux 0x449b606c sync_blockdev +EXPORT_SYMBOL vmlinux 0x44aaf30f tsc_khz +EXPORT_SYMBOL vmlinux 0x44b911c3 rb_replace_node +EXPORT_SYMBOL vmlinux 0x44c8ac54 simple_readpage +EXPORT_SYMBOL vmlinux 0x44caa35e sk_wait_data +EXPORT_SYMBOL vmlinux 0x44ce93fd blk_recount_segments +EXPORT_SYMBOL vmlinux 0x44d560e3 init_level4_pgt +EXPORT_SYMBOL vmlinux 0x4506ed53 n_tty_ioctl +EXPORT_SYMBOL vmlinux 0x451e69a1 posix_test_lock +EXPORT_SYMBOL vmlinux 0x4520be77 deregister_atm_ioctl +EXPORT_SYMBOL vmlinux 0x4550ba8a register_cpu_notifier +EXPORT_SYMBOL vmlinux 0x455fd57d acpi_set_register +EXPORT_SYMBOL vmlinux 0x45704798 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x4572534c key_payload_reserve +EXPORT_SYMBOL vmlinux 0x459af11a give_up_console +EXPORT_SYMBOL vmlinux 0x45bb123e try_to_del_timer_sync +EXPORT_SYMBOL vmlinux 0x45c66ac4 dquot_free_inode +EXPORT_SYMBOL vmlinux 0x45d11c43 down_interruptible +EXPORT_SYMBOL vmlinux 0x45d597c0 pci_enable_bridges +EXPORT_SYMBOL vmlinux 0x45f786f7 idr_pre_get +EXPORT_SYMBOL vmlinux 0x465e1b57 km_new_mapping +EXPORT_SYMBOL vmlinux 0x466c14a7 __delay +EXPORT_SYMBOL vmlinux 0x46a70451 bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0x46c47fb6 __node_distance +EXPORT_SYMBOL vmlinux 0x46cddd4e agp_collect_device_status +EXPORT_SYMBOL vmlinux 0x46fb4ef3 input_event +EXPORT_SYMBOL vmlinux 0x46fd86c3 vfs_dq_quota_on_remount +EXPORT_SYMBOL vmlinux 0x4710a5d1 d_instantiate_unique +EXPORT_SYMBOL vmlinux 0x473f0d94 bio_copy_user +EXPORT_SYMBOL vmlinux 0x475100c2 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x475f010b acpi_purge_cached_objects +EXPORT_SYMBOL vmlinux 0x475f05af acpi_set_firmware_waking_vector +EXPORT_SYMBOL vmlinux 0x478d10b2 ht_destroy_irq +EXPORT_SYMBOL vmlinux 0x47939e0d __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x479c3c86 find_next_zero_bit +EXPORT_SYMBOL vmlinux 0x47e01089 simple_pin_fs +EXPORT_SYMBOL vmlinux 0x481cb9ab acpi_enter_sleep_state_prep +EXPORT_SYMBOL vmlinux 0x481dbe03 key_task_permission +EXPORT_SYMBOL vmlinux 0x4826a5a6 vfs_quota_on_mount +EXPORT_SYMBOL vmlinux 0x483af8d0 pci_iomap +EXPORT_SYMBOL vmlinux 0x4859b8bb rtc_year_days +EXPORT_SYMBOL vmlinux 0x486b6407 hweight64 +EXPORT_SYMBOL vmlinux 0x48a8a9c4 swiotlb_sync_single_for_cpu +EXPORT_SYMBOL vmlinux 0x48c3d32a file_permission +EXPORT_SYMBOL vmlinux 0x48fc80fe take_over_console +EXPORT_SYMBOL vmlinux 0x492331f8 add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0x493e25e1 udp_hash +EXPORT_SYMBOL vmlinux 0x4959ba7b km_state_notify +EXPORT_SYMBOL vmlinux 0x49603fb8 security_sb_copy_data +EXPORT_SYMBOL vmlinux 0x497f989e input_close_device +EXPORT_SYMBOL vmlinux 0x4993ebd9 fb_set_var +EXPORT_SYMBOL vmlinux 0x49bb588e blk_init_tags +EXPORT_SYMBOL vmlinux 0x49da9a9a _read_unlock_bh +EXPORT_SYMBOL vmlinux 0x4a0290f1 acpi_lock_ac_dir +EXPORT_SYMBOL vmlinux 0x4a1380ff skb_dequeue +EXPORT_SYMBOL vmlinux 0x4a358252 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x4a5ebc6a ida_get_new_above +EXPORT_SYMBOL vmlinux 0x4b07e779 _spin_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x4b085dbf agp3_generic_configure +EXPORT_SYMBOL vmlinux 0x4b146d28 drop_super +EXPORT_SYMBOL vmlinux 0x4b298689 vmtruncate +EXPORT_SYMBOL vmlinux 0x4b2f14b4 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x4b77c0d1 tcf_hash_insert +EXPORT_SYMBOL vmlinux 0x4ba5baa0 load_gs_index +EXPORT_SYMBOL vmlinux 0x4ba8d55f inet_sock_destruct +EXPORT_SYMBOL vmlinux 0x4bbac957 dev_mc_delete +EXPORT_SYMBOL vmlinux 0x4bbc3e5f pm_flags +EXPORT_SYMBOL vmlinux 0x4bc0ba45 task_session_nr_ns +EXPORT_SYMBOL vmlinux 0x4c1182cb bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x4c2a0e63 alloc_file +EXPORT_SYMBOL vmlinux 0x4c309d6b scm_detach_fds +EXPORT_SYMBOL vmlinux 0x4c30bc72 splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0x4c3718c9 xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x4c3af445 __request_region +EXPORT_SYMBOL vmlinux 0x4c4c956e nla_memcmp +EXPORT_SYMBOL vmlinux 0x4c52ecc4 sock_kfree_s +EXPORT_SYMBOL vmlinux 0x4c74fd13 page_symlink +EXPORT_SYMBOL vmlinux 0x4c828a6e clear_bdi_congested +EXPORT_SYMBOL vmlinux 0x4c84ba63 sockfd_lookup +EXPORT_SYMBOL vmlinux 0x4c95ccf5 cdev_init +EXPORT_SYMBOL vmlinux 0x4ca4981f __inet6_lookup_established +EXPORT_SYMBOL vmlinux 0x4cab9dbd sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0x4cabd657 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x4cbbd171 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x4cc392b5 register_sysctl_table +EXPORT_SYMBOL vmlinux 0x4ce5b556 current_fs_time +EXPORT_SYMBOL vmlinux 0x4d62488f dev_disable_lro +EXPORT_SYMBOL vmlinux 0x4d63ed76 vfs_set_dqblk +EXPORT_SYMBOL vmlinux 0x4d82fb7a put_page +EXPORT_SYMBOL vmlinux 0x4dada75d input_open_device +EXPORT_SYMBOL vmlinux 0x4db1e1d4 posix_acl_equiv_mode +EXPORT_SYMBOL vmlinux 0x4db2f931 directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0x4dda726b match_strlcpy +EXPORT_SYMBOL vmlinux 0x4ddc4b9f utf8_mbtowc +EXPORT_SYMBOL vmlinux 0x4df119fa __bitmap_parse +EXPORT_SYMBOL vmlinux 0x4df47e9f xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x4e0fec2a xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0x4e100f60 _spin_unlock_irq +EXPORT_SYMBOL vmlinux 0x4e2eb05a framebuffer_alloc +EXPORT_SYMBOL vmlinux 0x4e3567f7 match_int +EXPORT_SYMBOL vmlinux 0x4e6e8ea7 fg_console +EXPORT_SYMBOL vmlinux 0x4e7ce052 tcf_exts_change +EXPORT_SYMBOL vmlinux 0x4e969241 iw_handler_get_thrspy +EXPORT_SYMBOL vmlinux 0x4edd72f7 block_all_signals +EXPORT_SYMBOL vmlinux 0x4f43133d tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x4f515289 sock_wfree +EXPORT_SYMBOL vmlinux 0x4f5438c1 idle_halt +EXPORT_SYMBOL vmlinux 0x4f7d14bb sb_set_blocksize +EXPORT_SYMBOL vmlinux 0x4f82feb3 __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x4f917bd0 atm_init_aal5 +EXPORT_SYMBOL vmlinux 0x4f97e8c0 acpi_unlock_ac_dir +EXPORT_SYMBOL vmlinux 0x4fa71b5d end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0x4fa75270 inet_frags_fini +EXPORT_SYMBOL vmlinux 0x4fcee107 __up_read +EXPORT_SYMBOL vmlinux 0x4fdee897 i8042_command +EXPORT_SYMBOL vmlinux 0x4fe20744 bio_add_page +EXPORT_SYMBOL vmlinux 0x5003d626 d_validate +EXPORT_SYMBOL vmlinux 0x50152bb4 agp_backend_release +EXPORT_SYMBOL vmlinux 0x50211ee3 tcp_free_md5sig_pool +EXPORT_SYMBOL vmlinux 0x5031dfff registered_fb +EXPORT_SYMBOL vmlinux 0x503a3efe pci_unmap_rom +EXPORT_SYMBOL vmlinux 0x5045c92d compat_sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x50af6d2d arp_xmit +EXPORT_SYMBOL vmlinux 0x50ba769a kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0x5118c382 secure_dccp_sequence_number +EXPORT_SYMBOL vmlinux 0x511a070e pnp_release_card_device +EXPORT_SYMBOL vmlinux 0x511e1375 fb_class +EXPORT_SYMBOL vmlinux 0x512e7cdc generic_unplug_device +EXPORT_SYMBOL vmlinux 0x513b4f21 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0x5195fba7 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0x51cf6d2d ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0x51d12d4e acpi_pci_disabled +EXPORT_SYMBOL vmlinux 0x51d7a776 acpi_detach_data +EXPORT_SYMBOL vmlinux 0x51dd9ad9 netdev_set_master +EXPORT_SYMBOL vmlinux 0x51edcf11 dma_pool_free +EXPORT_SYMBOL vmlinux 0x52026cdf security_sb_parse_opts_str +EXPORT_SYMBOL vmlinux 0x5212317c pci_set_dma_seg_boundary +EXPORT_SYMBOL vmlinux 0x521d63ec wait_for_key_construction +EXPORT_SYMBOL vmlinux 0x522f5573 pv_irq_ops +EXPORT_SYMBOL vmlinux 0x5252f304 __memcpy_toio +EXPORT_SYMBOL vmlinux 0x52979c21 bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0x52a58c24 ifla_policy +EXPORT_SYMBOL vmlinux 0x52af9451 search_binary_handler +EXPORT_SYMBOL vmlinux 0x52d7b2fd llc_sap_list +EXPORT_SYMBOL vmlinux 0x530b1e98 pm_suspend +EXPORT_SYMBOL vmlinux 0x532f2924 param_get_byte +EXPORT_SYMBOL vmlinux 0x53326531 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x5367bd63 find_or_create_page +EXPORT_SYMBOL vmlinux 0x539385d7 kernel_accept +EXPORT_SYMBOL vmlinux 0x53c0767c sk_chk_filter +EXPORT_SYMBOL vmlinux 0x53df2682 serio_reconnect +EXPORT_SYMBOL vmlinux 0x53f87323 struct_module +EXPORT_SYMBOL vmlinux 0x53ff09fb pci_find_parent_resource +EXPORT_SYMBOL vmlinux 0x54290dc9 nla_validate +EXPORT_SYMBOL vmlinux 0x543affb5 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x54907126 sk_common_release +EXPORT_SYMBOL vmlinux 0x54b81541 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0x54c4110e lock_may_read +EXPORT_SYMBOL vmlinux 0x54ca1955 init_special_inode +EXPORT_SYMBOL vmlinux 0x54cc0bda devm_ioremap +EXPORT_SYMBOL vmlinux 0x54e6fcdd net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x550f8ade groups_alloc +EXPORT_SYMBOL vmlinux 0x555385e6 sk_stop_timer +EXPORT_SYMBOL vmlinux 0x5594be03 bitmap_remap +EXPORT_SYMBOL vmlinux 0x55bc9303 netpoll_setup +EXPORT_SYMBOL vmlinux 0x55c68172 tcp_splice_read +EXPORT_SYMBOL vmlinux 0x55ee518a kfree_skb +EXPORT_SYMBOL vmlinux 0x55f151fe cap_netlink_recv +EXPORT_SYMBOL vmlinux 0x5600904f fb_get_color_depth +EXPORT_SYMBOL vmlinux 0x5635a60a vmalloc_user +EXPORT_SYMBOL vmlinux 0x56571e89 sg_miter_stop +EXPORT_SYMBOL vmlinux 0x56a1951c kset_unregister +EXPORT_SYMBOL vmlinux 0x56b7ccf0 blk_start_queueing +EXPORT_SYMBOL vmlinux 0x56bcadeb pci_bus_read_config_byte +EXPORT_SYMBOL vmlinux 0x56dba97c dma_async_client_chan_request +EXPORT_SYMBOL vmlinux 0x56f494e0 smp_call_function +EXPORT_SYMBOL vmlinux 0x5721d24e __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x572e85d4 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x57376558 skb_split +EXPORT_SYMBOL vmlinux 0x57516471 tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0x576d8804 freeze_bdev +EXPORT_SYMBOL vmlinux 0x577cc638 mutex_unlock +EXPORT_SYMBOL vmlinux 0x57ca0485 rtnl_notify +EXPORT_SYMBOL vmlinux 0x57d9ac16 tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0x57fa779f __blk_run_queue +EXPORT_SYMBOL vmlinux 0x580eda72 nf_unregister_sockopt +EXPORT_SYMBOL vmlinux 0x5810f6f2 put_io_context +EXPORT_SYMBOL vmlinux 0x583721b5 try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x5838f6c9 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x584738f9 rdmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x584c8bd8 page_put_link +EXPORT_SYMBOL vmlinux 0x5857b225 ioread16_rep +EXPORT_SYMBOL vmlinux 0x589f51b1 blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0x58a6f270 tty_check_change +EXPORT_SYMBOL vmlinux 0x58ccb675 no_llseek +EXPORT_SYMBOL vmlinux 0x58e45b27 kthread_stop +EXPORT_SYMBOL vmlinux 0x5927bfbc tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x5933ebe5 release_sock +EXPORT_SYMBOL vmlinux 0x5934392b fb_register_client +EXPORT_SYMBOL vmlinux 0x594bf15b ioport_map +EXPORT_SYMBOL vmlinux 0x59862e04 elv_rb_find +EXPORT_SYMBOL vmlinux 0x59a6ff40 pnp_activate_dev +EXPORT_SYMBOL vmlinux 0x59d696b6 register_module_notifier +EXPORT_SYMBOL vmlinux 0x59da3c6f pci_enable_device_io +EXPORT_SYMBOL vmlinux 0x5a0cddd4 prepare_binprm +EXPORT_SYMBOL vmlinux 0x5a0d4358 free_task +EXPORT_SYMBOL vmlinux 0x5a30bb45 remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0x5a34a45c __kmalloc +EXPORT_SYMBOL vmlinux 0x5a433740 skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0x5a43a90e get_user_pages +EXPORT_SYMBOL vmlinux 0x5a4896a8 __put_user_2 +EXPORT_SYMBOL vmlinux 0x5a5e7ea3 simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x5a69219f __up_write +EXPORT_SYMBOL vmlinux 0x5a744b86 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x5a772174 dev_set_mac_address +EXPORT_SYMBOL vmlinux 0x5aa76213 cpufreq_get_policy +EXPORT_SYMBOL vmlinux 0x5ac376a5 acpi_install_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x5ad41249 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0x5af17dc1 generic_permission +EXPORT_SYMBOL vmlinux 0x5b0945b6 pnp_register_card_driver +EXPORT_SYMBOL vmlinux 0x5b112f78 xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0x5b51c6a7 acpi_walk_resources +EXPORT_SYMBOL vmlinux 0x5b77ddc8 blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0x5bae2eac acpi_extract_package +EXPORT_SYMBOL vmlinux 0x5bbcafba pci_bus_type +EXPORT_SYMBOL vmlinux 0x5bec44cb __down_write +EXPORT_SYMBOL vmlinux 0x5c2375e8 destroy_EII_client +EXPORT_SYMBOL vmlinux 0x5c385150 xfrm_user_policy +EXPORT_SYMBOL vmlinux 0x5c46b6fa posix_acl_chmod_masq +EXPORT_SYMBOL vmlinux 0x5c4e7ab0 xfrm_nl +EXPORT_SYMBOL vmlinux 0x5c65d7f6 register_nls +EXPORT_SYMBOL vmlinux 0x5c6ad800 console_stop +EXPORT_SYMBOL vmlinux 0x5c70c2db generic_write_end +EXPORT_SYMBOL vmlinux 0x5c7505cd save_mount_options +EXPORT_SYMBOL vmlinux 0x5c87da2c blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0x5c8db279 inc_zone_page_state +EXPORT_SYMBOL vmlinux 0x5c9a6c03 swiotlb_map_sg_attrs +EXPORT_SYMBOL vmlinux 0x5ca0000d schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0x5ca0ed91 test_set_page_writeback +EXPORT_SYMBOL vmlinux 0x5ca264a5 per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0x5cb2c222 dev_mc_sync +EXPORT_SYMBOL vmlinux 0x5cba1497 agp_free_memory +EXPORT_SYMBOL vmlinux 0x5cc8e015 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0x5cfaefdf task_nice +EXPORT_SYMBOL vmlinux 0x5d113035 vm_stat +EXPORT_SYMBOL vmlinux 0x5d370f3f __free_pages +EXPORT_SYMBOL vmlinux 0x5d5c4ff0 vfs_dq_drop +EXPORT_SYMBOL vmlinux 0x5d73b5f8 km_waitq +EXPORT_SYMBOL vmlinux 0x5d7e09de alloc_hippi_dev +EXPORT_SYMBOL vmlinux 0x5da8e6de xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x5dafd05c netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0x5dbcfa4f boot_cpu_physical_apicid +EXPORT_SYMBOL vmlinux 0x5de8aa28 file_remove_suid +EXPORT_SYMBOL vmlinux 0x5decbfcd set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x5e0f7602 pcix_set_mmrbc +EXPORT_SYMBOL vmlinux 0x5e14fa11 ilookup +EXPORT_SYMBOL vmlinux 0x5e744305 llc_sap_open +EXPORT_SYMBOL vmlinux 0x5e79ebec gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x5e8d5534 ps2_handle_ack +EXPORT_SYMBOL vmlinux 0x5e91de37 dev_unicast_delete +EXPORT_SYMBOL vmlinux 0x5e9f09df get_io_context +EXPORT_SYMBOL vmlinux 0x5ea520c5 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x5eab426c serio_open +EXPORT_SYMBOL vmlinux 0x5eb8690c single_open +EXPORT_SYMBOL vmlinux 0x5ec0d148 may_umount_tree +EXPORT_SYMBOL vmlinux 0x5ed040b0 pm_set_vt_switch +EXPORT_SYMBOL vmlinux 0x5edd0762 bin2bcd +EXPORT_SYMBOL vmlinux 0x5f06ca2f skb_copy +EXPORT_SYMBOL vmlinux 0x5f085fe4 __netif_schedule +EXPORT_SYMBOL vmlinux 0x5f5b50ab ps2_init +EXPORT_SYMBOL vmlinux 0x5f627089 tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0x5f8dc294 dcache_dir_close +EXPORT_SYMBOL vmlinux 0x5fabae42 udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0x600683d3 do_unblank_screen +EXPORT_SYMBOL vmlinux 0x60278305 vcc_release_async +EXPORT_SYMBOL vmlinux 0x6037ae52 pcim_pin_device +EXPORT_SYMBOL vmlinux 0x603a6656 br_handle_frame_hook +EXPORT_SYMBOL vmlinux 0x60400b7f pv_lock_ops +EXPORT_SYMBOL vmlinux 0x605c8bde radix_tree_delete +EXPORT_SYMBOL vmlinux 0x606a5bca tcf_hash_check +EXPORT_SYMBOL vmlinux 0x608c2831 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x609f1c7e synchronize_net +EXPORT_SYMBOL vmlinux 0x60a32ea9 pm_power_off +EXPORT_SYMBOL vmlinux 0x60d550eb __dec_zone_page_state +EXPORT_SYMBOL vmlinux 0x6111e1bc init_timer +EXPORT_SYMBOL vmlinux 0x612390ad netpoll_set_trap +EXPORT_SYMBOL vmlinux 0x6159c44d request_key_async +EXPORT_SYMBOL vmlinux 0x615bb0a3 open_bdev_excl +EXPORT_SYMBOL vmlinux 0x61619723 agp_allocate_memory +EXPORT_SYMBOL vmlinux 0x61799c93 __seq_open_private +EXPORT_SYMBOL vmlinux 0x618d8299 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x61abb458 pci_dev_get +EXPORT_SYMBOL vmlinux 0x61b7b126 simple_strtoull +EXPORT_SYMBOL vmlinux 0x61c1c365 unregister_key_type +EXPORT_SYMBOL vmlinux 0x62049256 acpi_disable +EXPORT_SYMBOL vmlinux 0x6237f6b5 acpi_enable_event +EXPORT_SYMBOL vmlinux 0x624fb85c blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x62737e1d sock_unregister +EXPORT_SYMBOL vmlinux 0x62748e70 acpi_set_current_resources +EXPORT_SYMBOL vmlinux 0x62827bec security_secctx_to_secid +EXPORT_SYMBOL vmlinux 0x62d9975e vfs_quota_on +EXPORT_SYMBOL vmlinux 0x631bb5e8 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0x633354e6 atm_charge +EXPORT_SYMBOL vmlinux 0x633b7084 acpi_unlock_battery_dir +EXPORT_SYMBOL vmlinux 0x63499009 pci_assign_resource +EXPORT_SYMBOL vmlinux 0x6361b125 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0x63694ce7 key_unlink +EXPORT_SYMBOL vmlinux 0x636a5691 acpi_register_ioapic +EXPORT_SYMBOL vmlinux 0x636b5eb7 generic_setlease +EXPORT_SYMBOL vmlinux 0x638675b4 swiotlb_sync_single_for_device +EXPORT_SYMBOL vmlinux 0x63b8dd20 end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0x63cd7b2f alloc_fcdev +EXPORT_SYMBOL vmlinux 0x63e79481 dst_destroy +EXPORT_SYMBOL vmlinux 0x63ecad53 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x63ed4f65 ioremap_cache +EXPORT_SYMBOL vmlinux 0x63f1d58f request_key_async_with_auxdata +EXPORT_SYMBOL vmlinux 0x63fc232f strlen_user +EXPORT_SYMBOL vmlinux 0x6403e338 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x640f9821 vfs_dq_transfer +EXPORT_SYMBOL vmlinux 0x642e54ac __wake_up +EXPORT_SYMBOL vmlinux 0x6451294b posix_acl_valid +EXPORT_SYMBOL vmlinux 0x6451b5af blk_rq_init +EXPORT_SYMBOL vmlinux 0x645735fb blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x6466a1e6 mempool_alloc +EXPORT_SYMBOL vmlinux 0x647708aa __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0x6478134c ec_burst_enable +EXPORT_SYMBOL vmlinux 0x647e1678 skb_trim +EXPORT_SYMBOL vmlinux 0x6482dd65 pci_bus_size_bridges +EXPORT_SYMBOL vmlinux 0x64999478 congestion_wait +EXPORT_SYMBOL vmlinux 0x64b491e5 inode_add_bytes +EXPORT_SYMBOL vmlinux 0x64cd5d16 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x64f824dc sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x64f8e672 bio_pair_release +EXPORT_SYMBOL vmlinux 0x650128e7 br_fdb_get_hook +EXPORT_SYMBOL vmlinux 0x650fb346 add_wait_queue +EXPORT_SYMBOL vmlinux 0x6516cb0c skb_truesize_bug +EXPORT_SYMBOL vmlinux 0x651e497c nf_afinfo +EXPORT_SYMBOL vmlinux 0x653fb40b devm_request_irq +EXPORT_SYMBOL vmlinux 0x65408378 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x65414e67 dev_valid_name +EXPORT_SYMBOL vmlinux 0x65930cce pcim_enable_device +EXPORT_SYMBOL vmlinux 0x65b5ad18 d_genocide +EXPORT_SYMBOL vmlinux 0x65f5ef5e xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0x6601f37b qdisc_class_hash_grow +EXPORT_SYMBOL vmlinux 0x661a4ccf sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0x668da8d5 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x669c2832 blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0x66b17ac4 lock_may_write +EXPORT_SYMBOL vmlinux 0x66ec4db9 skb_unlink +EXPORT_SYMBOL vmlinux 0x66f5b237 km_state_expired +EXPORT_SYMBOL vmlinux 0x66f9bb0c d_splice_alias +EXPORT_SYMBOL vmlinux 0x672144bd strlcpy +EXPORT_SYMBOL vmlinux 0x6729d3df __get_user_4 +EXPORT_SYMBOL vmlinux 0x673f815e agp_bridges +EXPORT_SYMBOL vmlinux 0x674598ca bmap +EXPORT_SYMBOL vmlinux 0x674f95b7 sk_run_filter +EXPORT_SYMBOL vmlinux 0x6768497e pcim_iomap_regions +EXPORT_SYMBOL vmlinux 0x678907d2 skb_append +EXPORT_SYMBOL vmlinux 0x679db766 sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x67a10240 k8_northbridges +EXPORT_SYMBOL vmlinux 0x67b27ec1 tty_std_termios +EXPORT_SYMBOL vmlinux 0x67e71b77 __mutex_init +EXPORT_SYMBOL vmlinux 0x680b08cc kmem_cache_size +EXPORT_SYMBOL vmlinux 0x681cd4c1 posix_lock_file +EXPORT_SYMBOL vmlinux 0x684f5e71 textsearch_unregister +EXPORT_SYMBOL vmlinux 0x6882e91a sysctl_data +EXPORT_SYMBOL vmlinux 0x68ea763e console_start +EXPORT_SYMBOL vmlinux 0x68fb5a1f lease_get_mtime +EXPORT_SYMBOL vmlinux 0x68fc3e02 tty_devnum +EXPORT_SYMBOL vmlinux 0x69192b5a iommu_num_pages +EXPORT_SYMBOL vmlinux 0x69263f03 llc_set_station_handler +EXPORT_SYMBOL vmlinux 0x693a0827 input_allocate_device +EXPORT_SYMBOL vmlinux 0x695c9799 vm_insert_mixed +EXPORT_SYMBOL vmlinux 0x69682087 blk_start_queue +EXPORT_SYMBOL vmlinux 0x69703221 sock_no_sendpage +EXPORT_SYMBOL vmlinux 0x6971447a rtc_month_days +EXPORT_SYMBOL vmlinux 0x69927dff try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x69a0ca7d iowrite16be +EXPORT_SYMBOL vmlinux 0x6a035a02 sk_dst_check +EXPORT_SYMBOL vmlinux 0x6a037cf1 mempool_kfree +EXPORT_SYMBOL vmlinux 0x6a26ed8a vfs_getattr +EXPORT_SYMBOL vmlinux 0x6a47571d __set_personality +EXPORT_SYMBOL vmlinux 0x6a5fa363 sigprocmask +EXPORT_SYMBOL vmlinux 0x6a847e81 xfrm_input_resume +EXPORT_SYMBOL vmlinux 0x6a9ca5db kobject_get +EXPORT_SYMBOL vmlinux 0x6acb973d iowrite32be +EXPORT_SYMBOL vmlinux 0x6add5c9a dmi_find_device +EXPORT_SYMBOL vmlinux 0x6aff05df inetdev_by_index +EXPORT_SYMBOL vmlinux 0x6b1b67d3 __bdevname +EXPORT_SYMBOL vmlinux 0x6b266982 agp_generic_free_by_type +EXPORT_SYMBOL vmlinux 0x6b2dc060 dump_stack +EXPORT_SYMBOL vmlinux 0x6b3d87aa __page_cache_alloc +EXPORT_SYMBOL vmlinux 0x6b4e5a52 radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x6b9b88f3 sleep_on +EXPORT_SYMBOL vmlinux 0x6b9e09fb skb_clone +EXPORT_SYMBOL vmlinux 0x6bafbced mod_timer +EXPORT_SYMBOL vmlinux 0x6bc56c67 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x6bd16613 sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x6bdcfd99 qdisc_class_hash_remove +EXPORT_SYMBOL vmlinux 0x6c389761 acpi_bus_get_private_data +EXPORT_SYMBOL vmlinux 0x6c61ce70 num_registered_fb +EXPORT_SYMBOL vmlinux 0x6c702af7 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x6c8c3150 udp_lib_get_port +EXPORT_SYMBOL vmlinux 0x6c8c3ecd generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0x6cbe7632 posix_acl_to_xattr +EXPORT_SYMBOL vmlinux 0x6cd21961 simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x6cf1cc92 cdev_alloc +EXPORT_SYMBOL vmlinux 0x6d046044 tcp_disconnect +EXPORT_SYMBOL vmlinux 0x6d0da34c param_get_short +EXPORT_SYMBOL vmlinux 0x6d1ced27 vcc_sklist_lock +EXPORT_SYMBOL vmlinux 0x6d27ef64 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x6d294e43 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x6d334118 __get_user_8 +EXPORT_SYMBOL vmlinux 0x6d340f64 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x6d47d90d groups_free +EXPORT_SYMBOL vmlinux 0x6d6bd3fe blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0x6d7c124e read_cache_pages +EXPORT_SYMBOL vmlinux 0x6dc0c24b complete_and_exit +EXPORT_SYMBOL vmlinux 0x6ddd0b1a handle_sysrq +EXPORT_SYMBOL vmlinux 0x6de6bf83 radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x6def2db2 half_md4_transform +EXPORT_SYMBOL vmlinux 0x6e07a54e acpi_get_gpe_status +EXPORT_SYMBOL vmlinux 0x6e121cf3 proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x6e1a4bbb udp_hash_lock +EXPORT_SYMBOL vmlinux 0x6e3b7ab9 d_find_alias +EXPORT_SYMBOL vmlinux 0x6e49ec96 truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0x6e5c88b0 kobject_del +EXPORT_SYMBOL vmlinux 0x6e720ff2 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x6e7791a8 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0x6e9dd606 __symbol_put +EXPORT_SYMBOL vmlinux 0x6e9fa9ba udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x6ead242b cond_resched_lock +EXPORT_SYMBOL vmlinux 0x6eb8d32e blk_put_request +EXPORT_SYMBOL vmlinux 0x6ebde183 vm_insert_page +EXPORT_SYMBOL vmlinux 0x6edd2a99 sock_create_kern +EXPORT_SYMBOL vmlinux 0x6f02af52 compat_nf_getsockopt +EXPORT_SYMBOL vmlinux 0x6f0625da eth_rebuild_header +EXPORT_SYMBOL vmlinux 0x6f526d25 acpi_bus_unregister_driver +EXPORT_SYMBOL vmlinux 0x6f6231d1 bdget +EXPORT_SYMBOL vmlinux 0x6f84946c kmem_cache_alloc_node +EXPORT_SYMBOL vmlinux 0x6fa0fdcf call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0x6fab79fc inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0x6fcb87a1 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x6ff1fdd5 vfs_mknod +EXPORT_SYMBOL vmlinux 0x7008a9b7 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x7018c8ab __neigh_event_send +EXPORT_SYMBOL vmlinux 0x702b97ec sock_get_timestampns +EXPORT_SYMBOL vmlinux 0x702c87c0 inet_getname +EXPORT_SYMBOL vmlinux 0x704c1c13 read_cache_page +EXPORT_SYMBOL vmlinux 0x7054a3e4 request_dma +EXPORT_SYMBOL vmlinux 0x70b868b5 sk_alloc +EXPORT_SYMBOL vmlinux 0x70d8ab82 acpi_acquire_global_lock +EXPORT_SYMBOL vmlinux 0x70f0d3c2 generic_file_mmap +EXPORT_SYMBOL vmlinux 0x70fdce13 dma_async_client_unregister +EXPORT_SYMBOL vmlinux 0x711e84da inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0x7129e5f8 hex_asc +EXPORT_SYMBOL vmlinux 0x712aa29b _spin_lock_irqsave +EXPORT_SYMBOL vmlinux 0x71356fba remove_wait_queue +EXPORT_SYMBOL vmlinux 0x7152a78f ip_defrag +EXPORT_SYMBOL vmlinux 0x7171121c overflowgid +EXPORT_SYMBOL vmlinux 0x718c46a3 sock_init_data +EXPORT_SYMBOL vmlinux 0x71a50dbc register_blkdev +EXPORT_SYMBOL vmlinux 0x71d7819e ilookup5 +EXPORT_SYMBOL vmlinux 0x71dbe933 kernel_recvmsg +EXPORT_SYMBOL vmlinux 0x71e62871 agp_copy_info +EXPORT_SYMBOL vmlinux 0x71f6eb38 sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0x72270e35 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x7242e96d strnchr +EXPORT_SYMBOL vmlinux 0x724df501 vfs_quota_on_path +EXPORT_SYMBOL vmlinux 0x726ef074 bio_integrity_prep +EXPORT_SYMBOL vmlinux 0x72886bbc __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0x7295ff60 tty_throttle +EXPORT_SYMBOL vmlinux 0x72b243d4 free_dma +EXPORT_SYMBOL vmlinux 0x72ba443c wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0x72bf2140 mtrr_add +EXPORT_SYMBOL vmlinux 0x72d2d9de acpi_root_dir +EXPORT_SYMBOL vmlinux 0x72d45bc3 unregister_filesystem +EXPORT_SYMBOL vmlinux 0x72e02b50 netlink_ack +EXPORT_SYMBOL vmlinux 0x72ed7bec kill_fasync +EXPORT_SYMBOL vmlinux 0x7304a357 set_disk_ro +EXPORT_SYMBOL vmlinux 0x73112117 unlock_super +EXPORT_SYMBOL vmlinux 0x735a0bd5 native_io_delay +EXPORT_SYMBOL vmlinux 0x7389c9a8 acpi_bus_get_power +EXPORT_SYMBOL vmlinux 0x7397568c xfrm_find_acq +EXPORT_SYMBOL vmlinux 0x739ee22d gen_pool_add +EXPORT_SYMBOL vmlinux 0x740a1b95 reserve_evntsel_nmi +EXPORT_SYMBOL vmlinux 0x74202777 ioremap_prot +EXPORT_SYMBOL vmlinux 0x743cefec locks_mandatory_area +EXPORT_SYMBOL vmlinux 0x7485e15e unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x748caf40 down +EXPORT_SYMBOL vmlinux 0x74af9abf netif_carrier_on +EXPORT_SYMBOL vmlinux 0x74cc1cbe unregister_cpu_notifier +EXPORT_SYMBOL vmlinux 0x74cc238d current_kernel_time +EXPORT_SYMBOL vmlinux 0x7538b132 agp_off +EXPORT_SYMBOL vmlinux 0x754251ef bio_phys_segments +EXPORT_SYMBOL vmlinux 0x756e6992 strnicmp +EXPORT_SYMBOL vmlinux 0x759d60ae xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0x75bdea12 iommu_area_alloc +EXPORT_SYMBOL vmlinux 0x75ea9531 key_negate_and_link +EXPORT_SYMBOL vmlinux 0x75fec8c2 generic_make_request +EXPORT_SYMBOL vmlinux 0x760a0f4f yield +EXPORT_SYMBOL vmlinux 0x760b437a unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x7621bbf3 uart_write_wakeup +EXPORT_SYMBOL vmlinux 0x763fe03e alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0x7642b041 tty_set_operations +EXPORT_SYMBOL vmlinux 0x764383fe simple_sync_file +EXPORT_SYMBOL vmlinux 0x76477963 start_tty +EXPORT_SYMBOL vmlinux 0x764a61ac kernel_bind +EXPORT_SYMBOL vmlinux 0x76548acf tcf_exts_destroy +EXPORT_SYMBOL vmlinux 0x7662a2a4 single_release +EXPORT_SYMBOL vmlinux 0x766a6b7e block_invalidatepage +EXPORT_SYMBOL vmlinux 0x7676f928 filp_close +EXPORT_SYMBOL vmlinux 0x767dd8fd acpi_get_irq_routing_table +EXPORT_SYMBOL vmlinux 0x767ddb02 set_memory_wc +EXPORT_SYMBOL vmlinux 0x767fb41e netlink_kernel_release +EXPORT_SYMBOL vmlinux 0x768231ce sysctl_intvec +EXPORT_SYMBOL vmlinux 0x76bf656d __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x76d3cd60 laptop_mode +EXPORT_SYMBOL vmlinux 0x76d55c94 netlink_broadcast +EXPORT_SYMBOL vmlinux 0x76f3f8a5 num_k8_northbridges +EXPORT_SYMBOL vmlinux 0x7733d5dc input_release_device +EXPORT_SYMBOL vmlinux 0x77489bd3 register_key_type +EXPORT_SYMBOL vmlinux 0x7791a6c7 qdisc_tree_decrease_qlen +EXPORT_SYMBOL vmlinux 0x77a108df _write_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x77bc1f77 pci_dev_driver +EXPORT_SYMBOL vmlinux 0x77e0d1fb ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x77ecac9f zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x77f53abc acpi_get_vendor_resource +EXPORT_SYMBOL vmlinux 0x77f708fe nobh_writepage +EXPORT_SYMBOL vmlinux 0x782d973d neigh_update +EXPORT_SYMBOL vmlinux 0x7837c129 agp_generic_free_gatt_table +EXPORT_SYMBOL vmlinux 0x788e3aa4 filemap_fault +EXPORT_SYMBOL vmlinux 0x78a484c9 _read_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x78ae6073 init_net +EXPORT_SYMBOL vmlinux 0x78df6bd7 no_pci_devices +EXPORT_SYMBOL vmlinux 0x78e37d20 elv_next_request +EXPORT_SYMBOL vmlinux 0x78ee99be eth_header_cache_update +EXPORT_SYMBOL vmlinux 0x78f914ee file_fsync +EXPORT_SYMBOL vmlinux 0x794c1398 dmi_check_system +EXPORT_SYMBOL vmlinux 0x795d0d00 __f_setown +EXPORT_SYMBOL vmlinux 0x79656409 cpu_online_map +EXPORT_SYMBOL vmlinux 0x799b0338 dev_driver_string +EXPORT_SYMBOL vmlinux 0x79aa04a2 get_random_bytes +EXPORT_SYMBOL vmlinux 0x79aa05a8 match_token +EXPORT_SYMBOL vmlinux 0x79be9827 uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x79ce4d5c arp_find +EXPORT_SYMBOL vmlinux 0x79cf399a agp_bridge +EXPORT_SYMBOL vmlinux 0x79d78989 set_irq_chip +EXPORT_SYMBOL vmlinux 0x7a054d2b __sk_dst_check +EXPORT_SYMBOL vmlinux 0x7a18b1b7 __napi_schedule +EXPORT_SYMBOL vmlinux 0x7a2a837d strict_strtol +EXPORT_SYMBOL vmlinux 0x7a3e9202 sock_map_fd +EXPORT_SYMBOL vmlinux 0x7a4bded8 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0x7a848702 _read_lock_irqsave +EXPORT_SYMBOL vmlinux 0x7a93abaf __nla_put +EXPORT_SYMBOL vmlinux 0x7a9a60cc tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0x7ae73de1 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0x7aec9089 clear_user +EXPORT_SYMBOL vmlinux 0x7b0c84c4 acpi_remove_table_handler +EXPORT_SYMBOL vmlinux 0x7b351aec bd_set_size +EXPORT_SYMBOL vmlinux 0x7b52a859 wrmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x7b8f4c40 key_create_or_update +EXPORT_SYMBOL vmlinux 0x7bc3102f do_munmap +EXPORT_SYMBOL vmlinux 0x7bc316a9 dquot_initialize +EXPORT_SYMBOL vmlinux 0x7be3fc60 tcf_action_exec +EXPORT_SYMBOL vmlinux 0x7bff3be7 iov_iter_advance +EXPORT_SYMBOL vmlinux 0x7c125b72 get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x7c46233a cpufreq_quick_get +EXPORT_SYMBOL vmlinux 0x7c5bb12b __ip_select_ident +EXPORT_SYMBOL vmlinux 0x7c5c18d5 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0x7c60d66e getname +EXPORT_SYMBOL vmlinux 0x7c6eb1d1 nf_setsockopt +EXPORT_SYMBOL vmlinux 0x7c8c1c36 module_put +EXPORT_SYMBOL vmlinux 0x7c904ded unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x7cb1ae69 cpu_down +EXPORT_SYMBOL vmlinux 0x7cfdec4d remove_inode_hash +EXPORT_SYMBOL vmlinux 0x7d047e7e acpi_ut_exception +EXPORT_SYMBOL vmlinux 0x7d11c268 jiffies +EXPORT_SYMBOL vmlinux 0x7d698583 swiotlb_unmap_single_attrs +EXPORT_SYMBOL vmlinux 0x7d6e5a2e pci_set_power_state +EXPORT_SYMBOL vmlinux 0x7d850612 utf8_mbstowcs +EXPORT_SYMBOL vmlinux 0x7d91c347 inode_sub_bytes +EXPORT_SYMBOL vmlinux 0x7d94f746 acpi_os_write_port +EXPORT_SYMBOL vmlinux 0x7d9c08c0 fb_set_suspend +EXPORT_SYMBOL vmlinux 0x7da56a06 alloc_pci_dev +EXPORT_SYMBOL vmlinux 0x7dceceac capable +EXPORT_SYMBOL vmlinux 0x7e449e41 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0x7e489097 input_flush_device +EXPORT_SYMBOL vmlinux 0x7e7d2f30 bio_integrity_split +EXPORT_SYMBOL vmlinux 0x7e9ebb05 kernel_thread +EXPORT_SYMBOL vmlinux 0x7ec812a2 blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0x7ec9bfbc strncpy +EXPORT_SYMBOL vmlinux 0x7ee91c1d _spin_trylock +EXPORT_SYMBOL vmlinux 0x7efbe560 per_cpu__cpu_core_map +EXPORT_SYMBOL vmlinux 0x7f0f15b5 vfs_statfs +EXPORT_SYMBOL vmlinux 0x7f24de73 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x7f32d10b pci_get_bus_and_slot +EXPORT_SYMBOL vmlinux 0x7f37467a clip_tbl_hook +EXPORT_SYMBOL vmlinux 0x7f5db472 pci_fixup_device +EXPORT_SYMBOL vmlinux 0x7f6c369c vfs_create +EXPORT_SYMBOL vmlinux 0x7f8723bd pcie_mch_quirk +EXPORT_SYMBOL vmlinux 0x7fb1b4ba __break_lease +EXPORT_SYMBOL vmlinux 0x7fc2d4b1 unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0x7fd555d6 sock_rfree +EXPORT_SYMBOL vmlinux 0x802b909f simple_rename +EXPORT_SYMBOL vmlinux 0x8032c4a2 __module_put_and_exit +EXPORT_SYMBOL vmlinux 0x8071959b con_is_bound +EXPORT_SYMBOL vmlinux 0x80ac1460 file_update_time +EXPORT_SYMBOL vmlinux 0x80c0de6f kernel_sendpage +EXPORT_SYMBOL vmlinux 0x81114f3b kill_pgrp +EXPORT_SYMBOL vmlinux 0x81472677 acpi_get_table +EXPORT_SYMBOL vmlinux 0x814c8ac8 __grab_cache_page +EXPORT_SYMBOL vmlinux 0x814e7730 nf_ct_destroy +EXPORT_SYMBOL vmlinux 0x815b5dd4 match_octal +EXPORT_SYMBOL vmlinux 0x815f2897 empty_zero_page +EXPORT_SYMBOL vmlinux 0x816494b1 seq_release_private +EXPORT_SYMBOL vmlinux 0x8173dcc5 is_container_init +EXPORT_SYMBOL vmlinux 0x8193ab31 bio_copy_kern +EXPORT_SYMBOL vmlinux 0x8193e36c call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x81a7f431 seq_open_private +EXPORT_SYMBOL vmlinux 0x81b7fbe6 ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0x81e6b37f dmi_get_system_info +EXPORT_SYMBOL vmlinux 0x81eaaa73 block_truncate_page +EXPORT_SYMBOL vmlinux 0x82072614 tasklet_kill +EXPORT_SYMBOL vmlinux 0x820d225f print_mac +EXPORT_SYMBOL vmlinux 0x82479ccb nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x8251bc21 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x8251bcc3 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x825a5b55 unregister_8022_client +EXPORT_SYMBOL vmlinux 0x825f0ccf sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x828261fe buffer_migrate_page +EXPORT_SYMBOL vmlinux 0x82b40820 swiotlb_unmap_sg_attrs +EXPORT_SYMBOL vmlinux 0x82e9c083 csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x8317e20a completion_done +EXPORT_SYMBOL vmlinux 0x8363c3d4 smp_call_function_mask +EXPORT_SYMBOL vmlinux 0x8373e6eb sg_miter_start +EXPORT_SYMBOL vmlinux 0x83800bfa kref_init +EXPORT_SYMBOL vmlinux 0x83a476ce bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x83b3425c wireless_send_event +EXPORT_SYMBOL vmlinux 0x83d2d1e2 idr_init +EXPORT_SYMBOL vmlinux 0x83d3193c page_follow_link_light +EXPORT_SYMBOL vmlinux 0x84005c54 pcim_iounmap_regions +EXPORT_SYMBOL vmlinux 0x840a8858 unregister_console +EXPORT_SYMBOL vmlinux 0x845d2b15 mpage_readpage +EXPORT_SYMBOL vmlinux 0x848d208d xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x84a513a2 inet_stream_connect +EXPORT_SYMBOL vmlinux 0x84aa9d21 tcf_em_tree_dump +EXPORT_SYMBOL vmlinux 0x84c43444 find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0x84d7f055 gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x84f822ff xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0x85670f1d rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x8570c8bf bio_integrity_enabled +EXPORT_SYMBOL vmlinux 0x85a60da9 inet_add_protocol +EXPORT_SYMBOL vmlinux 0x85abc85f strncmp +EXPORT_SYMBOL vmlinux 0x85b8d6c9 blk_insert_request +EXPORT_SYMBOL vmlinux 0x85dcab62 ___pskb_trim +EXPORT_SYMBOL vmlinux 0x85df9b6c strsep +EXPORT_SYMBOL vmlinux 0x85f116c7 udp_ioctl +EXPORT_SYMBOL vmlinux 0x8631f188 radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0x8636aa3a acpi_lock_battery_dir +EXPORT_SYMBOL vmlinux 0x863cb91a utf8_wcstombs +EXPORT_SYMBOL vmlinux 0x865e579c udplite_prot +EXPORT_SYMBOL vmlinux 0x8660b36c pagecache_write_begin +EXPORT_SYMBOL vmlinux 0x8661ce80 bio_integrity_endio +EXPORT_SYMBOL vmlinux 0x8664f62e cpufreq_update_policy +EXPORT_SYMBOL vmlinux 0x866fd903 nobh_write_end +EXPORT_SYMBOL vmlinux 0x86713cd3 keyring_clear +EXPORT_SYMBOL vmlinux 0x86730307 idr_get_new +EXPORT_SYMBOL vmlinux 0x868acba5 get_options +EXPORT_SYMBOL vmlinux 0x86af09d2 poll_freewait +EXPORT_SYMBOL vmlinux 0x86b48a77 page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0x86b9ed11 __scm_destroy +EXPORT_SYMBOL vmlinux 0x86d89bb7 del_gendisk +EXPORT_SYMBOL vmlinux 0x86de0e05 nf_unregister_hooks +EXPORT_SYMBOL vmlinux 0x86f62caf page_readlink +EXPORT_SYMBOL vmlinux 0x86fb9b05 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x8733e9a3 sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x87428312 elv_add_request +EXPORT_SYMBOL vmlinux 0x876dafc3 ec_write +EXPORT_SYMBOL vmlinux 0x8785725d param_set_charp +EXPORT_SYMBOL vmlinux 0x878615a0 swiotlb_map_sg +EXPORT_SYMBOL vmlinux 0x878ab3ce sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x878f5820 netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0x879065a7 skb_push +EXPORT_SYMBOL vmlinux 0x8794e0ce __devm_release_region +EXPORT_SYMBOL vmlinux 0x87a69bdc cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0x87d4017e module_refcount +EXPORT_SYMBOL vmlinux 0x87de107d tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x881039d0 zlib_inflate +EXPORT_SYMBOL vmlinux 0x8814d07c agp_generic_mask_memory +EXPORT_SYMBOL vmlinux 0x88158d39 f_setown +EXPORT_SYMBOL vmlinux 0x8830ed3f dma_async_memcpy_buf_to_pg +EXPORT_SYMBOL vmlinux 0x883346a5 blk_verify_command +EXPORT_SYMBOL vmlinux 0x883ac942 dev_get_by_name +EXPORT_SYMBOL vmlinux 0x8850fd31 devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0x886ea253 swiotlb_alloc_coherent +EXPORT_SYMBOL vmlinux 0x8882a9bf dcache_dir_open +EXPORT_SYMBOL vmlinux 0x88987949 call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0x88b1fad2 audit_log_format +EXPORT_SYMBOL vmlinux 0x891debfe __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x892b26a0 set_memory_nx +EXPORT_SYMBOL vmlinux 0x8934cf1f sock_wake_async +EXPORT_SYMBOL vmlinux 0x8953bb27 del_timer +EXPORT_SYMBOL vmlinux 0x897473df mktime +EXPORT_SYMBOL vmlinux 0x898b1fec mutex_trylock +EXPORT_SYMBOL vmlinux 0x898bd037 vfs_unlink +EXPORT_SYMBOL vmlinux 0x89949018 down_timeout +EXPORT_SYMBOL vmlinux 0x89d5538d fb_pad_aligned_buffer +EXPORT_SYMBOL vmlinux 0x89d66811 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x8a2cb1c7 d_invalidate +EXPORT_SYMBOL vmlinux 0x8a2f1c85 skb_seq_read +EXPORT_SYMBOL vmlinux 0x8a3eabf0 __wait_on_bit +EXPORT_SYMBOL vmlinux 0x8a44f4b4 __vlan_hwaccel_rx +EXPORT_SYMBOL vmlinux 0x8a6a8448 register_snap_client +EXPORT_SYMBOL vmlinux 0x8a7ae42b vfs_path_lookup +EXPORT_SYMBOL vmlinux 0x8a7d1c31 high_memory +EXPORT_SYMBOL vmlinux 0x8a90d932 allocate_resource +EXPORT_SYMBOL vmlinux 0x8a99a016 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x8aaf8654 mutex_lock +EXPORT_SYMBOL vmlinux 0x8ac40297 iommu_area_free +EXPORT_SYMBOL vmlinux 0x8ae787b3 mapping_tagged +EXPORT_SYMBOL vmlinux 0x8af8cada truncate_inode_pages +EXPORT_SYMBOL vmlinux 0x8b04bd64 ip_ct_attach +EXPORT_SYMBOL vmlinux 0x8b1b27c3 send_sig +EXPORT_SYMBOL vmlinux 0x8b35e873 sg_last +EXPORT_SYMBOL vmlinux 0x8b3ca835 cpu_present_map +EXPORT_SYMBOL vmlinux 0x8b409b40 vfs_write +EXPORT_SYMBOL vmlinux 0x8b50bd1c udp_memory_allocated +EXPORT_SYMBOL vmlinux 0x8b618d08 overflowuid +EXPORT_SYMBOL vmlinux 0x8b64d28b tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0x8b6a8e48 fput +EXPORT_SYMBOL vmlinux 0x8b78435f ida_remove +EXPORT_SYMBOL vmlinux 0x8b7fe311 kmemdup +EXPORT_SYMBOL vmlinux 0x8b922c0f __strnlen_user +EXPORT_SYMBOL vmlinux 0x8b966b63 sn_rtc_cycles_per_second +EXPORT_SYMBOL vmlinux 0x8b989cf9 acpi_bus_can_wakeup +EXPORT_SYMBOL vmlinux 0x8bae864c sock_no_bind +EXPORT_SYMBOL vmlinux 0x8bb33e7d __release_region +EXPORT_SYMBOL vmlinux 0x8bb7bbf5 create_proc_entry +EXPORT_SYMBOL vmlinux 0x8c183cbe iowrite16 +EXPORT_SYMBOL vmlinux 0x8c4d4549 sk_free +EXPORT_SYMBOL vmlinux 0x8c5a89bf netlink_unicast +EXPORT_SYMBOL vmlinux 0x8c7a7214 neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0x8cc79cab iowrite16_rep +EXPORT_SYMBOL vmlinux 0x8cd5c450 inode_double_lock +EXPORT_SYMBOL vmlinux 0x8cfbf01d __brelse +EXPORT_SYMBOL vmlinux 0x8d1c903f nf_register_sockopt +EXPORT_SYMBOL vmlinux 0x8d277f07 netpoll_parse_options +EXPORT_SYMBOL vmlinux 0x8d3894f2 _ctype +EXPORT_SYMBOL vmlinux 0x8d551bef sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x8d5adba2 generic_osync_inode +EXPORT_SYMBOL vmlinux 0x8d80fcb1 alloc_trdev +EXPORT_SYMBOL vmlinux 0x8d85bf61 ip_nat_decode_session +EXPORT_SYMBOL vmlinux 0x8d8d96c6 acpi_get_sleep_type_data +EXPORT_SYMBOL vmlinux 0x8d90ba67 skb_find_text +EXPORT_SYMBOL vmlinux 0x8dd61b71 inet_select_addr +EXPORT_SYMBOL vmlinux 0x8dece091 read_cache_page_async +EXPORT_SYMBOL vmlinux 0x8e002cda acpi_remove_gpe_block +EXPORT_SYMBOL vmlinux 0x8e0637ba i8253_lock +EXPORT_SYMBOL vmlinux 0x8e0b7743 ipv6_ext_hdr +EXPORT_SYMBOL vmlinux 0x8e1855e5 pci_find_bus +EXPORT_SYMBOL vmlinux 0x8e3c9cc3 vprintk +EXPORT_SYMBOL vmlinux 0x8e45732c unregister_quota_format +EXPORT_SYMBOL vmlinux 0x8e6fe131 unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0x8e725985 nf_log_unregister_pf +EXPORT_SYMBOL vmlinux 0x8e78393d uart_get_divisor +EXPORT_SYMBOL vmlinux 0x8e90a388 genl_unregister_ops +EXPORT_SYMBOL vmlinux 0x8ea74ad0 pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x8ee61ef0 cpufreq_gov_performance +EXPORT_SYMBOL vmlinux 0x8f00eafe xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0x8f0f29e2 try_to_release_page +EXPORT_SYMBOL vmlinux 0x8f20d4fc dev_load +EXPORT_SYMBOL vmlinux 0x8f39f14b dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0x8f65041e compat_tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x8f6b7950 set_irq_data +EXPORT_SYMBOL vmlinux 0x8f9083d0 d_delete +EXPORT_SYMBOL vmlinux 0x8f9c199c __get_user_2 +EXPORT_SYMBOL vmlinux 0x8fda3d08 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0x8ff999d1 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0x90022b44 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x90035333 secure_tcpv6_sequence_number +EXPORT_SYMBOL vmlinux 0x9028bc52 serio_close +EXPORT_SYMBOL vmlinux 0x903f4949 sock_i_ino +EXPORT_SYMBOL vmlinux 0x904b213c simple_statfs +EXPORT_SYMBOL vmlinux 0x904c118b tcf_hash_create +EXPORT_SYMBOL vmlinux 0x9070b3f2 ioport_resource +EXPORT_SYMBOL vmlinux 0x9086ea4f simple_fill_super +EXPORT_SYMBOL vmlinux 0x90a943ba nmi_active +EXPORT_SYMBOL vmlinux 0x90ac0a02 unregister_netdev +EXPORT_SYMBOL vmlinux 0x90cfcd66 fget +EXPORT_SYMBOL vmlinux 0x90fa0830 generic_listxattr +EXPORT_SYMBOL vmlinux 0x9144a8e2 ec_burst_disable +EXPORT_SYMBOL vmlinux 0x91481982 __ratelimit +EXPORT_SYMBOL vmlinux 0x91607d95 set_memory_wb +EXPORT_SYMBOL vmlinux 0x918682e2 iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0x91906b9b d_alloc_name +EXPORT_SYMBOL vmlinux 0x91bd49a0 tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0x91ca8959 acpi_get_register +EXPORT_SYMBOL vmlinux 0x91cc2fe8 setup_arg_pages +EXPORT_SYMBOL vmlinux 0x91d180d4 blk_queue_make_request +EXPORT_SYMBOL vmlinux 0x91e0d14a xfrm_init_state +EXPORT_SYMBOL vmlinux 0x9206ff46 kernel_getpeername +EXPORT_SYMBOL vmlinux 0x9212a1d7 pcix_get_max_mmrbc +EXPORT_SYMBOL vmlinux 0x9215b107 generic_setxattr +EXPORT_SYMBOL vmlinux 0x9217d3c6 dump_trace +EXPORT_SYMBOL vmlinux 0x92392cd9 iov_shorten +EXPORT_SYMBOL vmlinux 0x925e802c tcp_v4_md5_lookup +EXPORT_SYMBOL vmlinux 0x92694346 nla_append +EXPORT_SYMBOL vmlinux 0x9272e6c9 vfs_readdir +EXPORT_SYMBOL vmlinux 0x927e989f gen_pool_alloc +EXPORT_SYMBOL vmlinux 0x92bf8b77 dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x92c3b20e sync_page_range +EXPORT_SYMBOL vmlinux 0x92ea4ae4 crc32_le +EXPORT_SYMBOL vmlinux 0x92ec8c1d add_disk +EXPORT_SYMBOL vmlinux 0x92fe4055 pci_release_selected_regions +EXPORT_SYMBOL vmlinux 0x93056f39 pci_bus_add_devices +EXPORT_SYMBOL vmlinux 0x9305f8e6 cpufreq_get +EXPORT_SYMBOL vmlinux 0x930ca954 serio_interrupt +EXPORT_SYMBOL vmlinux 0x9321ce16 netpoll_send_udp +EXPORT_SYMBOL vmlinux 0x93a6e0b2 io_schedule +EXPORT_SYMBOL vmlinux 0x93ab4a28 cancel_dirty_page +EXPORT_SYMBOL vmlinux 0x93afa72e vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x93b8ef56 mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0x93c69acf param_set_byte +EXPORT_SYMBOL vmlinux 0x93c8df0a udp_prot +EXPORT_SYMBOL vmlinux 0x93cbd1ec _spin_lock_bh +EXPORT_SYMBOL vmlinux 0x93e06b54 set_binfmt +EXPORT_SYMBOL vmlinux 0x93fca811 __get_free_pages +EXPORT_SYMBOL vmlinux 0x94039590 simple_link +EXPORT_SYMBOL vmlinux 0x940ec91b textsearch_register +EXPORT_SYMBOL vmlinux 0x9425b596 block_commit_write +EXPORT_SYMBOL vmlinux 0x943a1a54 unbind_con_driver +EXPORT_SYMBOL vmlinux 0x9450108b bio_map_user +EXPORT_SYMBOL vmlinux 0x945bc6a7 copy_from_user +EXPORT_SYMBOL vmlinux 0x94883ab2 gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0x94961283 vunmap +EXPORT_SYMBOL vmlinux 0x94ae5f25 __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0x94b7d9bb nf_log_register +EXPORT_SYMBOL vmlinux 0x94be63db cdev_del +EXPORT_SYMBOL vmlinux 0x94cabdfe pci_get_class +EXPORT_SYMBOL vmlinux 0x94e39d40 lookup_bdev +EXPORT_SYMBOL vmlinux 0x94fcf08e bioset_create +EXPORT_SYMBOL vmlinux 0x9502843e dev_get_flags +EXPORT_SYMBOL vmlinux 0x950cd5e6 find_lock_page +EXPORT_SYMBOL vmlinux 0x954488a4 syncookie_secret +EXPORT_SYMBOL vmlinux 0x9545af6d tasklet_init +EXPORT_SYMBOL vmlinux 0x95477ba0 ps2_cmd_aborted +EXPORT_SYMBOL vmlinux 0x954cbb26 vsprintf +EXPORT_SYMBOL vmlinux 0x95ba1d86 thermal_zone_unbind_cooling_device +EXPORT_SYMBOL vmlinux 0x95ceb864 key_update +EXPORT_SYMBOL vmlinux 0x95d7bcf8 blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x95dd999a gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0x960f28a5 tty_register_driver +EXPORT_SYMBOL vmlinux 0x961d724a unregister_netdevice +EXPORT_SYMBOL vmlinux 0x963bb6a1 pci_set_master +EXPORT_SYMBOL vmlinux 0x96481cc7 per_cpu__x86_cpu_to_apicid +EXPORT_SYMBOL vmlinux 0x96487928 fb_get_buffer_offset +EXPORT_SYMBOL vmlinux 0x96747a0d have_submounts +EXPORT_SYMBOL vmlinux 0x96768064 ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0x9696d326 unregister_nls +EXPORT_SYMBOL vmlinux 0x96f33400 up_read +EXPORT_SYMBOL vmlinux 0x972fdec1 serial8250_register_port +EXPORT_SYMBOL vmlinux 0x973873ab _spin_lock +EXPORT_SYMBOL vmlinux 0x9754ec10 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x97699985 blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x97861e40 ethtool_op_get_tx_csum +EXPORT_SYMBOL vmlinux 0x97de0ddd acpi_install_gpe_block +EXPORT_SYMBOL vmlinux 0x980a0cad dma_sync_wait +EXPORT_SYMBOL vmlinux 0x980b88a9 iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0x980faed4 vmap +EXPORT_SYMBOL vmlinux 0x98126584 remove_proc_entry +EXPORT_SYMBOL vmlinux 0x983a7e66 generic_writepages +EXPORT_SYMBOL vmlinux 0x9864c1a6 idr_find +EXPORT_SYMBOL vmlinux 0x986e6135 fb_pad_unaligned_buffer +EXPORT_SYMBOL vmlinux 0x988ed85d set_memory_x +EXPORT_SYMBOL vmlinux 0x9893b195 sock_kmalloc +EXPORT_SYMBOL vmlinux 0x98afdeed llc_sap_close +EXPORT_SYMBOL vmlinux 0x997b86d6 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x9994c0ca ps2_is_keyboard_id +EXPORT_SYMBOL vmlinux 0x999e8297 vfree +EXPORT_SYMBOL vmlinux 0x99aadb21 param_get_ulong +EXPORT_SYMBOL vmlinux 0x99bfbe39 get_unused_fd +EXPORT_SYMBOL vmlinux 0x99cdc86b sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x99d87919 security_sb_set_mnt_opts +EXPORT_SYMBOL vmlinux 0x99e8e8af names_cachep +EXPORT_SYMBOL vmlinux 0x99ea12ce panic_blink +EXPORT_SYMBOL vmlinux 0x9a1dfd65 strpbrk +EXPORT_SYMBOL vmlinux 0x9a21b6be zero_fill_bio +EXPORT_SYMBOL vmlinux 0x9a57977b elevator_exit +EXPORT_SYMBOL vmlinux 0x9a58e3c2 pci_set_mwi +EXPORT_SYMBOL vmlinux 0x9a9985be percpu_counter_destroy +EXPORT_SYMBOL vmlinux 0x9ae280a8 blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0x9b388444 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x9b5abb9f xfrm_lookup +EXPORT_SYMBOL vmlinux 0x9b6408d6 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0x9b815a18 mod_zone_page_state +EXPORT_SYMBOL vmlinux 0x9b8fcd82 cont_write_begin +EXPORT_SYMBOL vmlinux 0x9b97745c mnt_pin +EXPORT_SYMBOL vmlinux 0x9ba7089d argv_split +EXPORT_SYMBOL vmlinux 0x9bb58b22 inet_addr_type +EXPORT_SYMBOL vmlinux 0x9bc565c5 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x9bf5cd88 sock_create_lite +EXPORT_SYMBOL vmlinux 0x9c012508 fb_parse_edid +EXPORT_SYMBOL vmlinux 0x9c0ea3cd memscan +EXPORT_SYMBOL vmlinux 0x9c17c94a udp_proc_register +EXPORT_SYMBOL vmlinux 0x9c395b38 tcf_generic_walker +EXPORT_SYMBOL vmlinux 0x9c3c13c6 do_sync_read +EXPORT_SYMBOL vmlinux 0x9c491f60 sg_alloc_table +EXPORT_SYMBOL vmlinux 0x9c55ed15 tcp_md5_hash_header +EXPORT_SYMBOL vmlinux 0x9c8e2966 mem_section +EXPORT_SYMBOL vmlinux 0x9ca95a0e sort +EXPORT_SYMBOL vmlinux 0x9cb96e92 qdisc_put_rtab +EXPORT_SYMBOL vmlinux 0x9cc6f545 flush_signals +EXPORT_SYMBOL vmlinux 0x9ccb2622 finish_wait +EXPORT_SYMBOL vmlinux 0x9ccf93a0 tcp_hashinfo +EXPORT_SYMBOL vmlinux 0x9ce5afa9 mpage_readpages +EXPORT_SYMBOL vmlinux 0x9ced38aa down_trylock +EXPORT_SYMBOL vmlinux 0x9ced7f1c ip_xfrm_me_harder +EXPORT_SYMBOL vmlinux 0x9cf7bac0 km_policy_expired +EXPORT_SYMBOL vmlinux 0x9d328aa0 free_netdev +EXPORT_SYMBOL vmlinux 0x9d33ef5e acpi_enable +EXPORT_SYMBOL vmlinux 0x9d3741aa filemap_fdatawait +EXPORT_SYMBOL vmlinux 0x9d57084d nf_reinject +EXPORT_SYMBOL vmlinux 0x9d69a91b tcf_action_dump_1 +EXPORT_SYMBOL vmlinux 0x9d711f1f percpu_counter_init +EXPORT_SYMBOL vmlinux 0x9d96246f neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x9d9e5add elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0x9db04cdb elv_dequeue_request +EXPORT_SYMBOL vmlinux 0x9db21624 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x9dd299bf pneigh_enqueue +EXPORT_SYMBOL vmlinux 0x9e1c6037 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0x9e329281 bio_integrity_free +EXPORT_SYMBOL vmlinux 0x9e535888 acpi_get_physical_device +EXPORT_SYMBOL vmlinux 0x9e6201db idr_remove +EXPORT_SYMBOL vmlinux 0x9e64fbfe rtc_cmos_read +EXPORT_SYMBOL vmlinux 0x9e7d6bd0 __udelay +EXPORT_SYMBOL vmlinux 0x9e9426c0 sock_no_accept +EXPORT_SYMBOL vmlinux 0x9ea0ad49 __sg_free_table +EXPORT_SYMBOL vmlinux 0x9ea28ec7 acpi_evaluate_object +EXPORT_SYMBOL vmlinux 0x9edbecae snprintf +EXPORT_SYMBOL vmlinux 0x9eecde16 do_brk +EXPORT_SYMBOL vmlinux 0x9ef452c0 ipv4_specific +EXPORT_SYMBOL vmlinux 0x9ef749e2 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x9f0b3309 elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0x9f100139 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x9f2bdaac __bitmap_or +EXPORT_SYMBOL vmlinux 0x9f6b6587 inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0x9f984513 strrchr +EXPORT_SYMBOL vmlinux 0x9fa274b4 dq_data_lock +EXPORT_SYMBOL vmlinux 0x9fd779e3 udp_poll +EXPORT_SYMBOL vmlinux 0x9fde60f0 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x9feaf287 sonet_subtract_stats +EXPORT_SYMBOL vmlinux 0xa00554c4 d_rehash +EXPORT_SYMBOL vmlinux 0xa0139c09 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0xa01dbff6 user_path_at +EXPORT_SYMBOL vmlinux 0xa03523d5 security_unix_stream_connect +EXPORT_SYMBOL vmlinux 0xa04a01bd qdisc_class_hash_insert +EXPORT_SYMBOL vmlinux 0xa05c03df mempool_kmalloc +EXPORT_SYMBOL vmlinux 0xa0605033 get_sb_single +EXPORT_SYMBOL vmlinux 0xa0965fe2 unload_nls +EXPORT_SYMBOL vmlinux 0xa09ff7b3 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0xa0b04675 vmalloc_32 +EXPORT_SYMBOL vmlinux 0xa0ceef51 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0xa0cf56e0 ida_pre_get +EXPORT_SYMBOL vmlinux 0xa0fbac79 wake_up_bit +EXPORT_SYMBOL vmlinux 0xa0fd9496 kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0xa108eb4d sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0xa120d33c tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0xa13798f8 printk_ratelimit +EXPORT_SYMBOL vmlinux 0xa13c0faf nla_reserve +EXPORT_SYMBOL vmlinux 0xa1b759ce fb_add_videomode +EXPORT_SYMBOL vmlinux 0xa1c76e0a _cond_resched +EXPORT_SYMBOL vmlinux 0xa1d013fe skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0xa1ecf921 kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0xa20abf2f find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0xa20ce1b8 net_msg_warn +EXPORT_SYMBOL vmlinux 0xa216d1b2 blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0xa23ac2f9 register_sysrq_key +EXPORT_SYMBOL vmlinux 0xa25b79aa xfrm_state_delete +EXPORT_SYMBOL vmlinux 0xa26d33a7 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0xa28056f5 ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0xa2a1e5c9 _write_lock_bh +EXPORT_SYMBOL vmlinux 0xa2a5fd77 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0xa2da39ac ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0xa2ead877 uart_add_one_port +EXPORT_SYMBOL vmlinux 0xa30904a3 uart_register_driver +EXPORT_SYMBOL vmlinux 0xa31f172d __copy_from_user_inatomic +EXPORT_SYMBOL vmlinux 0xa329d77b unregister_binfmt +EXPORT_SYMBOL vmlinux 0xa329f07e register_shrinker +EXPORT_SYMBOL vmlinux 0xa33f7c7c nla_strlcpy +EXPORT_SYMBOL vmlinux 0xa3420d61 __percpu_counter_sum +EXPORT_SYMBOL vmlinux 0xa35de80f ipv4_config +EXPORT_SYMBOL vmlinux 0xa37f26bd ip_mc_join_group +EXPORT_SYMBOL vmlinux 0xa3a5be95 memmove +EXPORT_SYMBOL vmlinux 0xa3aa23b3 invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0xa3b7fd8b blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0xa3bbcd80 acpi_set_gpe_type +EXPORT_SYMBOL vmlinux 0xa4366b2e find_get_pages_tag +EXPORT_SYMBOL vmlinux 0xa44072fc posix_acl_alloc +EXPORT_SYMBOL vmlinux 0xa44ad274 wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0xa4501cd1 pnp_request_card_device +EXPORT_SYMBOL vmlinux 0xa47635df redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0xa4b94fea iowrite8_rep +EXPORT_SYMBOL vmlinux 0xa4cd897e force_sig +EXPORT_SYMBOL vmlinux 0xa4d4f0e6 global_cache_flush +EXPORT_SYMBOL vmlinux 0xa4df1151 kref_set +EXPORT_SYMBOL vmlinux 0xa4f46824 con_copy_unimap +EXPORT_SYMBOL vmlinux 0xa4f51e82 __invalidate_device +EXPORT_SYMBOL vmlinux 0xa519b3c1 input_unregister_handler +EXPORT_SYMBOL vmlinux 0xa5240753 __lock_buffer +EXPORT_SYMBOL vmlinux 0xa5423cc4 param_get_int +EXPORT_SYMBOL vmlinux 0xa548fbdc blk_init_queue +EXPORT_SYMBOL vmlinux 0xa5693df7 posix_acl_clone +EXPORT_SYMBOL vmlinux 0xa56f1315 mempool_free +EXPORT_SYMBOL vmlinux 0xa57064d0 iunique +EXPORT_SYMBOL vmlinux 0xa58b6804 nla_parse +EXPORT_SYMBOL vmlinux 0xa5922bb1 kfifo_init +EXPORT_SYMBOL vmlinux 0xa598e29c vesa_modes +EXPORT_SYMBOL vmlinux 0xa5a10753 __lock_page +EXPORT_SYMBOL vmlinux 0xa5a161cd tcp_sendmsg +EXPORT_SYMBOL vmlinux 0xa5a905c8 elv_rb_former_request +EXPORT_SYMBOL vmlinux 0xa5af8af3 blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0xa6040c0c __serio_register_driver +EXPORT_SYMBOL vmlinux 0xa605cb35 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0xa63ab9b8 fb_get_mode +EXPORT_SYMBOL vmlinux 0xa68124fa hweight8 +EXPORT_SYMBOL vmlinux 0xa681fe88 generate_random_uuid +EXPORT_SYMBOL vmlinux 0xa699db51 pci_bus_read_config_dword +EXPORT_SYMBOL vmlinux 0xa6c16c21 inet_sendmsg +EXPORT_SYMBOL vmlinux 0xa6d3873e pci_get_device +EXPORT_SYMBOL vmlinux 0xa6dcc773 rb_insert_color +EXPORT_SYMBOL vmlinux 0xa6f1591a skb_checksum +EXPORT_SYMBOL vmlinux 0xa70fabbe release_evntsel_nmi +EXPORT_SYMBOL vmlinux 0xa744d533 agp_find_bridge +EXPORT_SYMBOL vmlinux 0xa7502f48 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0xa77b1e2c unregister_exec_domain +EXPORT_SYMBOL vmlinux 0xa7944385 sk_stream_error +EXPORT_SYMBOL vmlinux 0xa7c35c6b getnstimeofday +EXPORT_SYMBOL vmlinux 0xa7c391c9 nf_register_hook +EXPORT_SYMBOL vmlinux 0xa7cba39d bio_integrity_set_tag +EXPORT_SYMBOL vmlinux 0xa7e85708 inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0xa816c525 schedule_work_on +EXPORT_SYMBOL vmlinux 0xa822dae7 down_read +EXPORT_SYMBOL vmlinux 0xa82e5551 ip_getsockopt +EXPORT_SYMBOL vmlinux 0xa876ab52 pci_bus_write_config_byte +EXPORT_SYMBOL vmlinux 0xa886a958 krealloc +EXPORT_SYMBOL vmlinux 0xa89e7ea9 ip_dev_find +EXPORT_SYMBOL vmlinux 0xa89f085a __kill_fasync +EXPORT_SYMBOL vmlinux 0xa8ba38e0 blkdev_put +EXPORT_SYMBOL vmlinux 0xa8c7574d arch_debugfs_dir +EXPORT_SYMBOL vmlinux 0xa8ec460f __nla_reserve +EXPORT_SYMBOL vmlinux 0xa8f102af thermal_cooling_device_register +EXPORT_SYMBOL vmlinux 0xa8fef7bb security_unix_may_send +EXPORT_SYMBOL vmlinux 0xa907b898 bio_integrity_alloc +EXPORT_SYMBOL vmlinux 0xa925899a param_set_bool +EXPORT_SYMBOL vmlinux 0xa9780166 input_unregister_device +EXPORT_SYMBOL vmlinux 0xa9a4fa29 unregister_snap_client +EXPORT_SYMBOL vmlinux 0xa9be76e8 clocksource_register +EXPORT_SYMBOL vmlinux 0xa9d4832a close_bdev_excl +EXPORT_SYMBOL vmlinux 0xa9d943dd fb_find_mode +EXPORT_SYMBOL vmlinux 0xa9daa720 init_task +EXPORT_SYMBOL vmlinux 0xa9fcf31d wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0xaa024146 sonet_copy_stats +EXPORT_SYMBOL vmlinux 0xaa110fd6 simple_set_mnt +EXPORT_SYMBOL vmlinux 0xaa3bb13d sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0xaa84a8ae acpi_processor_power_init_bm_check +EXPORT_SYMBOL vmlinux 0xaa932ac5 tcp_check_req +EXPORT_SYMBOL vmlinux 0xaa9a5fce xfrm4_rcv +EXPORT_SYMBOL vmlinux 0xaab06af8 _write_lock_irqsave +EXPORT_SYMBOL vmlinux 0xaad76f42 kthread_bind +EXPORT_SYMBOL vmlinux 0xaae80a67 xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0xaae8ab0e acpi_bus_power_manageable +EXPORT_SYMBOL vmlinux 0xaafdc258 strcasecmp +EXPORT_SYMBOL vmlinux 0xaaffb9a5 acpi_bus_private_data_handler +EXPORT_SYMBOL vmlinux 0xab06fc26 proc_mkdir +EXPORT_SYMBOL vmlinux 0xab39e129 inode_setattr +EXPORT_SYMBOL vmlinux 0xab3e615c __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0xab471003 param_array_set +EXPORT_SYMBOL vmlinux 0xab565120 devm_ioport_map +EXPORT_SYMBOL vmlinux 0xab600421 probe_irq_off +EXPORT_SYMBOL vmlinux 0xab65ed80 set_memory_uc +EXPORT_SYMBOL vmlinux 0xabccf7af tcp_make_synack +EXPORT_SYMBOL vmlinux 0xabcd913c tcp_connect +EXPORT_SYMBOL vmlinux 0xabd0b574 path_put +EXPORT_SYMBOL vmlinux 0xabd0c91c rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0xabf2078d ll_rw_block +EXPORT_SYMBOL vmlinux 0xac07c4a6 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0xac0bbfa8 _proxy_pda +EXPORT_SYMBOL vmlinux 0xac0f51a1 lock_super +EXPORT_SYMBOL vmlinux 0xac189757 blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0xac2c5047 blk_execute_rq +EXPORT_SYMBOL vmlinux 0xac383451 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0xac3b3cee __bitmap_and +EXPORT_SYMBOL vmlinux 0xac5709f7 per_cpu__x86_cpu_to_node_map +EXPORT_SYMBOL vmlinux 0xac58ea5e acpi_unload_table_id +EXPORT_SYMBOL vmlinux 0xac6606fb inode_get_bytes +EXPORT_SYMBOL vmlinux 0xacb5a561 iget_failed +EXPORT_SYMBOL vmlinux 0xacc6e252 copy_strings_kernel +EXPORT_SYMBOL vmlinux 0xaccabc6a in4_pton +EXPORT_SYMBOL vmlinux 0xacd65f4c simple_unlink +EXPORT_SYMBOL vmlinux 0xace26990 __bread +EXPORT_SYMBOL vmlinux 0xacf16ca2 agp_generic_alloc_user +EXPORT_SYMBOL vmlinux 0xacf4d843 match_strdup +EXPORT_SYMBOL vmlinux 0xacf8525f bd_release +EXPORT_SYMBOL vmlinux 0xad0413d4 match_hex +EXPORT_SYMBOL vmlinux 0xad07fcc5 __first_cpu +EXPORT_SYMBOL vmlinux 0xad127ef4 serio_rescan +EXPORT_SYMBOL vmlinux 0xad13c689 acpi_os_execute +EXPORT_SYMBOL vmlinux 0xad248fbf __dev_remove_pack +EXPORT_SYMBOL vmlinux 0xad25fb12 __memcpy +EXPORT_SYMBOL vmlinux 0xad4582bb xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0xad4a5208 send_sig_info +EXPORT_SYMBOL vmlinux 0xad5c09d2 wake_up_process +EXPORT_SYMBOL vmlinux 0xad74c46b scm_fp_dup +EXPORT_SYMBOL vmlinux 0xad8de1b3 acpi_remove_address_space_handler +EXPORT_SYMBOL vmlinux 0xada00a91 skb_insert +EXPORT_SYMBOL vmlinux 0xadaa2657 cpufreq_register_notifier +EXPORT_SYMBOL vmlinux 0xadb3cf5d neigh_ifdown +EXPORT_SYMBOL vmlinux 0xae0fb495 blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0xae14b37d register_exec_domain +EXPORT_SYMBOL vmlinux 0xae1548b4 swiotlb_unmap_sg +EXPORT_SYMBOL vmlinux 0xae49b2ab dquot_transfer +EXPORT_SYMBOL vmlinux 0xae844307 register_quota_format +EXPORT_SYMBOL vmlinux 0xae966f8b __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0xae97b15a blk_rq_count_integrity_sg +EXPORT_SYMBOL vmlinux 0xaee86f84 block_read_full_page +EXPORT_SYMBOL vmlinux 0xaeedc45b __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0xaf1ce299 ip_route_output_key +EXPORT_SYMBOL vmlinux 0xaf52c2d3 iommu_bio_merge +EXPORT_SYMBOL vmlinux 0xaf5c9d5d sk_send_sigurg +EXPORT_SYMBOL vmlinux 0xafe82e10 strcspn +EXPORT_SYMBOL vmlinux 0xaff94bbb input_set_capability +EXPORT_SYMBOL vmlinux 0xaffe5af4 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0xb02da982 path_lookup +EXPORT_SYMBOL vmlinux 0xb04ea8f0 agp_rebind_memory +EXPORT_SYMBOL vmlinux 0xb07dfb3d acpi_remove_gpe_handler +EXPORT_SYMBOL vmlinux 0xb0b5fb56 __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0xb0b847ac __bitmap_full +EXPORT_SYMBOL vmlinux 0xb0bb6329 fb_validate_mode +EXPORT_SYMBOL vmlinux 0xb0c7ed2b iw_handler_set_spy +EXPORT_SYMBOL vmlinux 0xb0d731ff __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0xb0e10781 get_option +EXPORT_SYMBOL vmlinux 0xb0f4a169 nlmsg_notify +EXPORT_SYMBOL vmlinux 0xb0fbe2e9 pci_try_set_mwi +EXPORT_SYMBOL vmlinux 0xb116807f vfs_lstat +EXPORT_SYMBOL vmlinux 0xb11fa1ce strlcat +EXPORT_SYMBOL vmlinux 0xb121390a probe_irq_on +EXPORT_SYMBOL vmlinux 0xb1577f2d elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0xb1645a2e sg_free_table +EXPORT_SYMBOL vmlinux 0xb18bd0b8 mpage_writepage +EXPORT_SYMBOL vmlinux 0xb18e02c3 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0xb19760c3 bitmap_onto +EXPORT_SYMBOL vmlinux 0xb1acfd47 kset_register +EXPORT_SYMBOL vmlinux 0xb1c3a01a oops_in_progress +EXPORT_SYMBOL vmlinux 0xb1cd9d4b __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0xb1cfad22 rdmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xb1f975aa unlock_kernel +EXPORT_SYMBOL vmlinux 0xb2017c1d per_cpu__x86_bios_cpu_apicid +EXPORT_SYMBOL vmlinux 0xb21e9ddb pci_enable_device +EXPORT_SYMBOL vmlinux 0xb22f6a87 ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0xb2355823 generic_block_bmap +EXPORT_SYMBOL vmlinux 0xb24a57af mntput_no_expire +EXPORT_SYMBOL vmlinux 0xb2648962 vfs_read +EXPORT_SYMBOL vmlinux 0xb26c561d tcf_em_register +EXPORT_SYMBOL vmlinux 0xb2731886 kill_block_super +EXPORT_SYMBOL vmlinux 0xb2bd21e1 generic_file_splice_read +EXPORT_SYMBOL vmlinux 0xb2be638a dma_chan_cleanup +EXPORT_SYMBOL vmlinux 0xb2fabb8b simple_release_fs +EXPORT_SYMBOL vmlinux 0xb2fd5ceb __put_user_4 +EXPORT_SYMBOL vmlinux 0xb3205415 wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0xb3260577 skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0xb3284531 acpi_dbg_layer +EXPORT_SYMBOL vmlinux 0xb3318ded __down_read_trylock +EXPORT_SYMBOL vmlinux 0xb34d4c2e acpi_terminate +EXPORT_SYMBOL vmlinux 0xb352177e find_first_bit +EXPORT_SYMBOL vmlinux 0xb3670c96 free_buffer_head +EXPORT_SYMBOL vmlinux 0xb3692eb4 ioremap_wc +EXPORT_SYMBOL vmlinux 0xb3725096 xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0xb3766790 linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0xb3863f9b eth_header +EXPORT_SYMBOL vmlinux 0xb3950635 skb_pad +EXPORT_SYMBOL vmlinux 0xb3a307c6 si_meminfo +EXPORT_SYMBOL vmlinux 0xb3bffa55 clear_inode +EXPORT_SYMBOL vmlinux 0xb3c2cab2 __generic_unplug_device +EXPORT_SYMBOL vmlinux 0xb3d16821 __kfree_skb +EXPORT_SYMBOL vmlinux 0xb3de2b5e tcp_rcv_established +EXPORT_SYMBOL vmlinux 0xb3fee994 sock_no_getname +EXPORT_SYMBOL vmlinux 0xb3ff1f69 free_pages_exact +EXPORT_SYMBOL vmlinux 0xb401e8ab __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0xb423dba1 console_blanked +EXPORT_SYMBOL vmlinux 0xb4390f9a mcount +EXPORT_SYMBOL vmlinux 0xb43b7a5b xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0xb45b24f6 k8_nb_ids +EXPORT_SYMBOL vmlinux 0xb46b5275 netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0xb489604c may_umount +EXPORT_SYMBOL vmlinux 0xb494e82a br_fdb_put_hook +EXPORT_SYMBOL vmlinux 0xb4ca9447 __kfifo_get +EXPORT_SYMBOL vmlinux 0xb5044271 vsscanf +EXPORT_SYMBOL vmlinux 0xb51ccefa uart_update_timeout +EXPORT_SYMBOL vmlinux 0xb54533f7 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0xb56fb81d set_pages_x +EXPORT_SYMBOL vmlinux 0xb5a459dc unregister_blkdev +EXPORT_SYMBOL vmlinux 0xb5c128e2 d_instantiate +EXPORT_SYMBOL vmlinux 0xb5c7eb57 sb_min_blocksize +EXPORT_SYMBOL vmlinux 0xb5d52c27 ec_transaction +EXPORT_SYMBOL vmlinux 0xb60e34a8 nla_memcpy +EXPORT_SYMBOL vmlinux 0xb6244511 sg_init_one +EXPORT_SYMBOL vmlinux 0xb678366f int_sqrt +EXPORT_SYMBOL vmlinux 0xb6a61a86 qdisc_get_rtab +EXPORT_SYMBOL vmlinux 0xb6afca19 pneigh_lookup +EXPORT_SYMBOL vmlinux 0xb6ba8bc6 pci_select_bars +EXPORT_SYMBOL vmlinux 0xb6cbe886 acpi_get_node +EXPORT_SYMBOL vmlinux 0xb6e227aa rtc_lock +EXPORT_SYMBOL vmlinux 0xb6eca461 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0xb6eefc18 swiotlb_dma_supported +EXPORT_SYMBOL vmlinux 0xb714a981 console_print +EXPORT_SYMBOL vmlinux 0xb7414af7 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0xb7484990 dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0xb752c93f tr_type_trans +EXPORT_SYMBOL vmlinux 0xb7555f12 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0xb758b225 acpi_disable_event +EXPORT_SYMBOL vmlinux 0xb774fe07 __pagevec_release +EXPORT_SYMBOL vmlinux 0xb77d80bd tcf_unregister_action +EXPORT_SYMBOL vmlinux 0xb7907551 vfs_writev +EXPORT_SYMBOL vmlinux 0xb799f240 pagevec_lookup +EXPORT_SYMBOL vmlinux 0xb7e63bec llc_add_pack +EXPORT_SYMBOL vmlinux 0xb7e718a7 posix_unblock_lock +EXPORT_SYMBOL vmlinux 0xb7ee3f25 inet_frag_destroy +EXPORT_SYMBOL vmlinux 0xb7f762a2 follow_down +EXPORT_SYMBOL vmlinux 0xb824f854 neigh_resolve_output +EXPORT_SYMBOL vmlinux 0xb86e4ab9 random32 +EXPORT_SYMBOL vmlinux 0xb89af9bf srandom32 +EXPORT_SYMBOL vmlinux 0xb8e7ce2c __put_user_8 +EXPORT_SYMBOL vmlinux 0xb8f96a6c eth_header_parse +EXPORT_SYMBOL vmlinux 0xb93437f2 acpi_notifier_call_chain +EXPORT_SYMBOL vmlinux 0xb969b002 pfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0xb9805b0c down_read_trylock +EXPORT_SYMBOL vmlinux 0xb985a2ec dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0xb98a0185 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0xb9c74bf1 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0xb9e34f7a blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0xb9f9e613 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0xb9fd2205 add_efi_memmap +EXPORT_SYMBOL vmlinux 0xba2d8594 ec_read +EXPORT_SYMBOL vmlinux 0xba497f13 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0xba6c9c04 tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0xba9c9ab8 inet_accept +EXPORT_SYMBOL vmlinux 0xbaa2782a kstrndup +EXPORT_SYMBOL vmlinux 0xbaec9362 inet_release +EXPORT_SYMBOL vmlinux 0xbb167766 fb_var_to_videomode +EXPORT_SYMBOL vmlinux 0xbb189cad disallow_signal +EXPORT_SYMBOL vmlinux 0xbb5d343d xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0xbb656def audit_log_end +EXPORT_SYMBOL vmlinux 0xbb83bd29 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0xbbb9a03f netdev_state_change +EXPORT_SYMBOL vmlinux 0xbbc8e804 param_set_ushort +EXPORT_SYMBOL vmlinux 0xbbe10e4a fifo_create_dflt +EXPORT_SYMBOL vmlinux 0xbc0c0161 d_namespace_path +EXPORT_SYMBOL vmlinux 0xbc3a1bcb I_BDEV +EXPORT_SYMBOL vmlinux 0xbc5f5f88 vc_cons +EXPORT_SYMBOL vmlinux 0xbc64a92f find_get_page +EXPORT_SYMBOL vmlinux 0xbc958848 alloc_pages_current +EXPORT_SYMBOL vmlinux 0xbcb40125 dma_async_device_register +EXPORT_SYMBOL vmlinux 0xbcc308bb strnlen_user +EXPORT_SYMBOL vmlinux 0xbcc4c5e1 tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0xbccad5b2 tc_classify_compat +EXPORT_SYMBOL vmlinux 0xbce0cf6f fasync_helper +EXPORT_SYMBOL vmlinux 0xbce21d86 seq_open +EXPORT_SYMBOL vmlinux 0xbcf148cf inet_frag_evictor +EXPORT_SYMBOL vmlinux 0xbcf58436 nf_getsockopt +EXPORT_SYMBOL vmlinux 0xbd2c7090 kernel_read +EXPORT_SYMBOL vmlinux 0xbd402bf0 devm_free_irq +EXPORT_SYMBOL vmlinux 0xbd52ad11 inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0xbd5e09b6 proto_unregister +EXPORT_SYMBOL vmlinux 0xbd9c99cf idr_get_new_above +EXPORT_SYMBOL vmlinux 0xbda8c24d ps2_sendbyte +EXPORT_SYMBOL vmlinux 0xbdaf5b07 acpi_os_read_port +EXPORT_SYMBOL vmlinux 0xbe499d81 copy_to_user +EXPORT_SYMBOL vmlinux 0xbe4e40ae pci_match_id +EXPORT_SYMBOL vmlinux 0xbef43296 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0xbefee397 acpi_get_object_info +EXPORT_SYMBOL vmlinux 0xbf493e2b tcf_em_unregister +EXPORT_SYMBOL vmlinux 0xbf63c9e7 dmam_pool_create +EXPORT_SYMBOL vmlinux 0xbf7fd2f5 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0xbf8e6bb4 tcp_prot +EXPORT_SYMBOL vmlinux 0xbf9bcc8d __cap_empty_set +EXPORT_SYMBOL vmlinux 0xbfbe9466 dev_alloc_skb +EXPORT_SYMBOL vmlinux 0xbfc177bc iowrite32_rep +EXPORT_SYMBOL vmlinux 0xc003c637 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0xc01172c8 dma_async_device_unregister +EXPORT_SYMBOL vmlinux 0xc01b3fa0 set_bh_page +EXPORT_SYMBOL vmlinux 0xc01d7ed4 end_queued_request +EXPORT_SYMBOL vmlinux 0xc020d456 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0xc045ad4e timespec_trunc +EXPORT_SYMBOL vmlinux 0xc04f26ae ida_init +EXPORT_SYMBOL vmlinux 0xc0580937 rb_erase +EXPORT_SYMBOL vmlinux 0xc062482f tcp_md5_hash_key +EXPORT_SYMBOL vmlinux 0xc07d43ae acpi_evaluate_reference +EXPORT_SYMBOL vmlinux 0xc09651d9 crc32_be +EXPORT_SYMBOL vmlinux 0xc0a3d105 find_next_bit +EXPORT_SYMBOL vmlinux 0xc0b25677 serio_unregister_driver +EXPORT_SYMBOL vmlinux 0xc0defa41 elv_rb_add +EXPORT_SYMBOL vmlinux 0xc0ef2966 fifo_set_limit +EXPORT_SYMBOL vmlinux 0xc1022067 invalidate_bdev +EXPORT_SYMBOL vmlinux 0xc12264ac pci_release_regions +EXPORT_SYMBOL vmlinux 0xc13d7e4c __downgrade_write +EXPORT_SYMBOL vmlinux 0xc167d2b3 sock_no_mmap +EXPORT_SYMBOL vmlinux 0xc17b259d register_binfmt +EXPORT_SYMBOL vmlinux 0xc18d879a sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0xc1ceb4f7 ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0xc1d428ce atm_alloc_charge +EXPORT_SYMBOL vmlinux 0xc1d508ec pci_enable_msix +EXPORT_SYMBOL vmlinux 0xc1efbe5b textsearch_prepare +EXPORT_SYMBOL vmlinux 0xc20f651e blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0xc2282b29 generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0xc23abc1f nf_unregister_queue_handler +EXPORT_SYMBOL vmlinux 0xc2424641 agp3_generic_cleanup +EXPORT_SYMBOL vmlinux 0xc24422d3 xfrm_register_mode +EXPORT_SYMBOL vmlinux 0xc24883b4 pcim_iomap_regions_request_all +EXPORT_SYMBOL vmlinux 0xc254af48 dcache_lock +EXPORT_SYMBOL vmlinux 0xc256e762 __bitmap_equal +EXPORT_SYMBOL vmlinux 0xc2bc4746 input_register_handle +EXPORT_SYMBOL vmlinux 0xc2e2682b neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0xc2e587d1 reset_devices +EXPORT_SYMBOL vmlinux 0xc2ea31bd kmem_cache_free +EXPORT_SYMBOL vmlinux 0xc33f6f4c on_each_cpu +EXPORT_SYMBOL vmlinux 0xc364dd5a sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0xc3696aa9 pnp_is_active +EXPORT_SYMBOL vmlinux 0xc3879f26 block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0xc38e5923 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0xc3a0c629 task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0xc3aaf0a9 __put_user_1 +EXPORT_SYMBOL vmlinux 0xc3bdac42 tcf_em_tree_validate +EXPORT_SYMBOL vmlinux 0xc3e40924 skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0xc402cc99 register_acpi_notifier +EXPORT_SYMBOL vmlinux 0xc457ae00 skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0xc4585a91 dquot_free_space +EXPORT_SYMBOL vmlinux 0xc468f0c5 pcix_get_mmrbc +EXPORT_SYMBOL vmlinux 0xc489da34 dma_ops +EXPORT_SYMBOL vmlinux 0xc499ae1e kstrdup +EXPORT_SYMBOL vmlinux 0xc49b280f generic_file_splice_write +EXPORT_SYMBOL vmlinux 0xc4d489e9 up_write +EXPORT_SYMBOL vmlinux 0xc4d9ec05 bio_map_kern +EXPORT_SYMBOL vmlinux 0xc4e107c1 bio_free +EXPORT_SYMBOL vmlinux 0xc4ece29b cdev_add +EXPORT_SYMBOL vmlinux 0xc52f5714 fb_videomode_to_var +EXPORT_SYMBOL vmlinux 0xc5518739 xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0xc5534d64 ioread16 +EXPORT_SYMBOL vmlinux 0xc558530d profile_pc +EXPORT_SYMBOL vmlinux 0xc55f7dc7 _write_trylock +EXPORT_SYMBOL vmlinux 0xc56daa1e inode_needs_sync +EXPORT_SYMBOL vmlinux 0xc5a4c8a3 inet_register_protosw +EXPORT_SYMBOL vmlinux 0xc5d9c46c agp_try_unsupported_boot +EXPORT_SYMBOL vmlinux 0xc5e29365 pci_clear_mwi +EXPORT_SYMBOL vmlinux 0xc5e67eb9 sk_release_kernel +EXPORT_SYMBOL vmlinux 0xc5eaf5b3 generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0xc61bfd48 dev_open +EXPORT_SYMBOL vmlinux 0xc62fbb46 sock_sendmsg +EXPORT_SYMBOL vmlinux 0xc6487984 nla_put_nohdr +EXPORT_SYMBOL vmlinux 0xc65abeb7 agp3_generic_sizes +EXPORT_SYMBOL vmlinux 0xc65d6442 make_bad_inode +EXPORT_SYMBOL vmlinux 0xc67b57c6 pci_target_state +EXPORT_SYMBOL vmlinux 0xc6821530 tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0xc6aa160c sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0xc7208c3a serial8250_resume_port +EXPORT_SYMBOL vmlinux 0xc72336af unregister_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0xc7240444 compat_ip_getsockopt +EXPORT_SYMBOL vmlinux 0xc727994d qdisc_calculate_pkt_len +EXPORT_SYMBOL vmlinux 0xc732eeb8 skb_under_panic +EXPORT_SYMBOL vmlinux 0xc740c64a memchr +EXPORT_SYMBOL vmlinux 0xc75289a6 dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0xc7a24d76 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0xc7a4fbed rtnl_lock +EXPORT_SYMBOL vmlinux 0xc7b840c2 tcp_v4_md5_hash_skb +EXPORT_SYMBOL vmlinux 0xc7b935e4 remove_arg_zero +EXPORT_SYMBOL vmlinux 0xc7ca1dfc __ht_create_irq +EXPORT_SYMBOL vmlinux 0xc7e8d4e9 inet_listen +EXPORT_SYMBOL vmlinux 0xc7fc4c3e per_cpu__cpu_info +EXPORT_SYMBOL vmlinux 0xc80d1184 path_permission +EXPORT_SYMBOL vmlinux 0xc828bcb0 blk_run_queue +EXPORT_SYMBOL vmlinux 0xc85f7f9c generic_show_options +EXPORT_SYMBOL vmlinux 0xc897c382 sg_init_table +EXPORT_SYMBOL vmlinux 0xc8b57c27 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0xc8ca3e25 acpi_get_child +EXPORT_SYMBOL vmlinux 0xc8e94ef8 key_validate +EXPORT_SYMBOL vmlinux 0xc90aa50c locks_copy_lock +EXPORT_SYMBOL vmlinux 0xc9219a63 bio_hw_segments +EXPORT_SYMBOL vmlinux 0xc9437ede __down_write_nested +EXPORT_SYMBOL vmlinux 0xc94b9742 tty_port_init +EXPORT_SYMBOL vmlinux 0xc95493ee netdev_class_create_file +EXPORT_SYMBOL vmlinux 0xc97fa32b __inet6_hash +EXPORT_SYMBOL vmlinux 0xc998d641 icmp_err_convert +EXPORT_SYMBOL vmlinux 0xc9ab2eef acpi_os_wait_events_complete +EXPORT_SYMBOL vmlinux 0xc9c0cd17 gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0xc9c8fd20 qdisc_watchdog_init +EXPORT_SYMBOL vmlinux 0xc9cc7b0f devm_iounmap +EXPORT_SYMBOL vmlinux 0xc9ecdaf1 pnp_possible_config +EXPORT_SYMBOL vmlinux 0xc9f9f3a3 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0xca248fe9 blk_integrity_compare +EXPORT_SYMBOL vmlinux 0xca660ca0 generic_removexattr +EXPORT_SYMBOL vmlinux 0xca8abced request_key_with_auxdata +EXPORT_SYMBOL vmlinux 0xca8acc78 acpi_dbg_level +EXPORT_SYMBOL vmlinux 0xca96b5d3 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0xcaaf9d43 swiotlb_map_single +EXPORT_SYMBOL vmlinux 0xcb2ee31f netdev_features_change +EXPORT_SYMBOL vmlinux 0xcb32da10 param_set_int +EXPORT_SYMBOL vmlinux 0xcb4e312e tty_hung_up_p +EXPORT_SYMBOL vmlinux 0xcb6afc6c skb_queue_head +EXPORT_SYMBOL vmlinux 0xcb6beb40 hweight32 +EXPORT_SYMBOL vmlinux 0xcb7131fb fb_get_options +EXPORT_SYMBOL vmlinux 0xcb729b95 register_atm_ioctl +EXPORT_SYMBOL vmlinux 0xcb733bf2 acpi_bus_set_power +EXPORT_SYMBOL vmlinux 0xcb9d4339 tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0xcbb510b2 rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0xcbc35def wait_on_page_bit +EXPORT_SYMBOL vmlinux 0xcbe4ba8e bio_alloc +EXPORT_SYMBOL vmlinux 0xcbf991dd simple_transaction_get +EXPORT_SYMBOL vmlinux 0xcc07af75 strnlen +EXPORT_SYMBOL vmlinux 0xcc07e53a tcf_exts_dump_stats +EXPORT_SYMBOL vmlinux 0xcc248d26 serial8250_suspend_port +EXPORT_SYMBOL vmlinux 0xcc2b71e6 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0xcc36f32e fb_unregister_client +EXPORT_SYMBOL vmlinux 0xcc5005fe msleep_interruptible +EXPORT_SYMBOL vmlinux 0xcc51ee50 dma_spin_lock +EXPORT_SYMBOL vmlinux 0xcc533358 __insert_inode_hash +EXPORT_SYMBOL vmlinux 0xcc7f8443 pnp_start_dev +EXPORT_SYMBOL vmlinux 0xcc7fa952 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0xcc86b510 tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0xcc9237ea pci_remove_behind_bridge +EXPORT_SYMBOL vmlinux 0xccd7051f do_sync_write +EXPORT_SYMBOL vmlinux 0xcd34ba20 tty_unthrottle +EXPORT_SYMBOL vmlinux 0xcd3650b5 xrlim_allow +EXPORT_SYMBOL vmlinux 0xcd5d0802 blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0xcd8da5da blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0xcdd2ad45 inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0xce00efdd path_get +EXPORT_SYMBOL vmlinux 0xce09d896 noop_qdisc +EXPORT_SYMBOL vmlinux 0xce226ab1 kill_litter_super +EXPORT_SYMBOL vmlinux 0xce30a07f skb_store_bits +EXPORT_SYMBOL vmlinux 0xce36ded6 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0xce4904a4 acpi_leave_sleep_state +EXPORT_SYMBOL vmlinux 0xce5ac24f zlib_inflate_workspacesize +EXPORT_SYMBOL vmlinux 0xce6c5e46 xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0xce7b1047 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0xce905f0c dquot_commit +EXPORT_SYMBOL vmlinux 0xce9126a8 vfs_quota_off +EXPORT_SYMBOL vmlinux 0xced089cc vfs_get_dqblk +EXPORT_SYMBOL vmlinux 0xced99a51 kmem_ptr_validate +EXPORT_SYMBOL vmlinux 0xcee5a6ff backlight_device_unregister +EXPORT_SYMBOL vmlinux 0xcefcd99a serial8250_unregister_port +EXPORT_SYMBOL vmlinux 0xcf047c83 acpi_disable_gpe +EXPORT_SYMBOL vmlinux 0xcf191485 set_pages_nx +EXPORT_SYMBOL vmlinux 0xcf3cf9d6 uart_match_port +EXPORT_SYMBOL vmlinux 0xcf62e9dc ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0xcf6c9afc tcp_shutdown +EXPORT_SYMBOL vmlinux 0xcf8e3881 set_anon_super +EXPORT_SYMBOL vmlinux 0xcf8e9c00 block_sync_page +EXPORT_SYMBOL vmlinux 0xcfa28b8d inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0xcfadd723 __percpu_counter_add +EXPORT_SYMBOL vmlinux 0xcfcc7608 find_task_by_vpid +EXPORT_SYMBOL vmlinux 0xcfd3018e set_normalized_timespec +EXPORT_SYMBOL vmlinux 0xcfe0930a dev_get_by_flags +EXPORT_SYMBOL vmlinux 0xd005a7d0 tty_vhangup +EXPORT_SYMBOL vmlinux 0xd0181f4f __bitmap_xor +EXPORT_SYMBOL vmlinux 0xd02cc869 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0xd02db6fa textsearch_destroy +EXPORT_SYMBOL vmlinux 0xd0657672 xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0xd08197fa acpi_load_tables +EXPORT_SYMBOL vmlinux 0xd0b63b3f audit_log_start +EXPORT_SYMBOL vmlinux 0xd0b817f2 cfb_copyarea +EXPORT_SYMBOL vmlinux 0xd0c4fe96 fddi_type_trans +EXPORT_SYMBOL vmlinux 0xd0ee38b8 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0xd0fef3b2 agp_free_key +EXPORT_SYMBOL vmlinux 0xd11eda6a blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0xd1472061 acpi_pci_register_driver +EXPORT_SYMBOL vmlinux 0xd1729338 tcp_md5_hash_skb_data +EXPORT_SYMBOL vmlinux 0xd18b6eb2 acpi_unmap_lsapic +EXPORT_SYMBOL vmlinux 0xd19bb294 acpi_install_address_space_handler +EXPORT_SYMBOL vmlinux 0xd19c7f38 ht_create_irq +EXPORT_SYMBOL vmlinux 0xd1ef84e5 nf_log_unregister +EXPORT_SYMBOL vmlinux 0xd1f6c5f3 smp_num_siblings +EXPORT_SYMBOL vmlinux 0xd1f91bcd dev_base_lock +EXPORT_SYMBOL vmlinux 0xd23a8f76 netpoll_poll +EXPORT_SYMBOL vmlinux 0xd251d7b0 security_socket_getpeersec_dgram +EXPORT_SYMBOL vmlinux 0xd2555f19 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0xd25d4f74 console_blank_hook +EXPORT_SYMBOL vmlinux 0xd267d42c down_killable +EXPORT_SYMBOL vmlinux 0xd2965f6f kthread_should_stop +EXPORT_SYMBOL vmlinux 0xd296ab14 pci_bus_read_config_word +EXPORT_SYMBOL vmlinux 0xd2c2664e qdisc_reset +EXPORT_SYMBOL vmlinux 0xd3354d0e tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0xd341b78d bio_endio +EXPORT_SYMBOL vmlinux 0xd34f0c62 gen_pool_create +EXPORT_SYMBOL vmlinux 0xd3951da4 acpi_resource_to_address64 +EXPORT_SYMBOL vmlinux 0xd3957a6d __find_get_block +EXPORT_SYMBOL vmlinux 0xd39c08c4 thermal_zone_device_unregister +EXPORT_SYMBOL vmlinux 0xd3bc846e __inode_dir_notify +EXPORT_SYMBOL vmlinux 0xd3c1877c should_remove_suid +EXPORT_SYMBOL vmlinux 0xd3f74cf1 interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0xd41e42bf d_alloc +EXPORT_SYMBOL vmlinux 0xd42b7232 _write_unlock_bh +EXPORT_SYMBOL vmlinux 0xd465e8df do_splice_from +EXPORT_SYMBOL vmlinux 0xd46f6149 proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0xd47c8fea unregister_con_driver +EXPORT_SYMBOL vmlinux 0xd4839248 inet_ioctl +EXPORT_SYMBOL vmlinux 0xd48c68b0 agp_generic_insert_memory +EXPORT_SYMBOL vmlinux 0xd4970481 pnp_get_resource +EXPORT_SYMBOL vmlinux 0xd4ba7b13 __dev_get_by_index +EXPORT_SYMBOL vmlinux 0xd516f04b unregister_qdisc +EXPORT_SYMBOL vmlinux 0xd558133a blk_complete_request +EXPORT_SYMBOL vmlinux 0xd568308e __devm_request_region +EXPORT_SYMBOL vmlinux 0xd56dc70f framebuffer_release +EXPORT_SYMBOL vmlinux 0xd5797488 kobject_init +EXPORT_SYMBOL vmlinux 0xd5b037e1 kref_put +EXPORT_SYMBOL vmlinux 0xd5b455da tcp_child_process +EXPORT_SYMBOL vmlinux 0xd5c5e059 xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0xd5da8037 pv_mmu_ops +EXPORT_SYMBOL vmlinux 0xd6035574 do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0xd6035d05 do_settimeofday +EXPORT_SYMBOL vmlinux 0xd6234508 sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0xd62c833f schedule_timeout +EXPORT_SYMBOL vmlinux 0xd65169e6 idr_destroy +EXPORT_SYMBOL vmlinux 0xd65a1d0f sg_miter_next +EXPORT_SYMBOL vmlinux 0xd6a78d08 smp_call_function_single +EXPORT_SYMBOL vmlinux 0xd6b33026 cpu_khz +EXPORT_SYMBOL vmlinux 0xd6ee688f vmalloc +EXPORT_SYMBOL vmlinux 0xd6f6be4a end_page_writeback +EXPORT_SYMBOL vmlinux 0xd741c3fa generic_readlink +EXPORT_SYMBOL vmlinux 0xd757a60c netpoll_print_options +EXPORT_SYMBOL vmlinux 0xd758111a blk_alloc_queue +EXPORT_SYMBOL vmlinux 0xd760aa26 pcim_iomap +EXPORT_SYMBOL vmlinux 0xd798d298 dev_unicast_sync +EXPORT_SYMBOL vmlinux 0xd79b5a02 allow_signal +EXPORT_SYMBOL vmlinux 0xd7a4cf23 inet_csk_accept +EXPORT_SYMBOL vmlinux 0xd7a6fafa panic_notifier_list +EXPORT_SYMBOL vmlinux 0xd7a99075 d_add_ci +EXPORT_SYMBOL vmlinux 0xd7dd777b reserve_perfctr_nmi +EXPORT_SYMBOL vmlinux 0xd828ab3b alloc_disk +EXPORT_SYMBOL vmlinux 0xd82c9fb0 filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0xd8792b97 register_qdisc +EXPORT_SYMBOL vmlinux 0xd88f695a __mod_timer +EXPORT_SYMBOL vmlinux 0xd89da37f movable_zone +EXPORT_SYMBOL vmlinux 0xd89fe226 proc_symlink +EXPORT_SYMBOL vmlinux 0xd8e484f0 register_chrdev_region +EXPORT_SYMBOL vmlinux 0xd8eeabff bfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0xd9091363 acpi_install_notify_handler +EXPORT_SYMBOL vmlinux 0xd9197536 __secpath_destroy +EXPORT_SYMBOL vmlinux 0xd985dc99 mempool_free_pages +EXPORT_SYMBOL vmlinux 0xd9a3cce8 pci_disable_msi +EXPORT_SYMBOL vmlinux 0xd9f752c4 xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0xd9ff05f8 neigh_for_each +EXPORT_SYMBOL vmlinux 0xda0a6b0e acpi_map_lsapic +EXPORT_SYMBOL vmlinux 0xda1a7335 kasprintf +EXPORT_SYMBOL vmlinux 0xda416fdb acpi_bus_register_driver +EXPORT_SYMBOL vmlinux 0xda4629e4 radix_tree_insert +EXPORT_SYMBOL vmlinux 0xda72fe1a acpi_check_mem_region +EXPORT_SYMBOL vmlinux 0xda73a1d0 __check_region +EXPORT_SYMBOL vmlinux 0xda7ca6cb fb_mode_is_equal +EXPORT_SYMBOL vmlinux 0xda86cd71 nf_ip_checksum +EXPORT_SYMBOL vmlinux 0xda8af7ad fb_find_nearest_mode +EXPORT_SYMBOL vmlinux 0xda8c22ca cfb_imageblit +EXPORT_SYMBOL vmlinux 0xda928914 nmi_watchdog +EXPORT_SYMBOL vmlinux 0xdad137ac bio_integrity_add_page +EXPORT_SYMBOL vmlinux 0xdadf5b37 inode_change_ok +EXPORT_SYMBOL vmlinux 0xdae0dc74 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0xdb1560d5 iw_handler_get_spy +EXPORT_SYMBOL vmlinux 0xdb336833 fb_set_cmap +EXPORT_SYMBOL vmlinux 0xdb3e4ab4 set_device_ro +EXPORT_SYMBOL vmlinux 0xdb7c30be pnp_register_driver +EXPORT_SYMBOL vmlinux 0xdbac11fe bdi_unregister +EXPORT_SYMBOL vmlinux 0xdbcd416e sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0xdc14eda7 pci_pci_problems +EXPORT_SYMBOL vmlinux 0xdc2adb35 add_taint +EXPORT_SYMBOL vmlinux 0xdc3eaf70 iomem_resource +EXPORT_SYMBOL vmlinux 0xdc43a9c8 daemonize +EXPORT_SYMBOL vmlinux 0xdc4f3db5 dev_get_by_index +EXPORT_SYMBOL vmlinux 0xdc7ff918 ps2_drain +EXPORT_SYMBOL vmlinux 0xdc873a70 screen_info +EXPORT_SYMBOL vmlinux 0xdc9d4b50 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0xdca844a3 tcf_hash_search +EXPORT_SYMBOL vmlinux 0xdcb0349b sys_close +EXPORT_SYMBOL vmlinux 0xdccdb114 alloc_fddidev +EXPORT_SYMBOL vmlinux 0xdcdd40ff pci_request_regions +EXPORT_SYMBOL vmlinux 0xdce1a197 bio_integrity_tag_size +EXPORT_SYMBOL vmlinux 0xdcf85fed notify_change +EXPORT_SYMBOL vmlinux 0xdd0905a1 call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0xdd7ddfcd proc_create_data +EXPORT_SYMBOL vmlinux 0xddc09646 dma_supported +EXPORT_SYMBOL vmlinux 0xddc1ac11 bioset_integrity_free +EXPORT_SYMBOL vmlinux 0xde0bdcff memset +EXPORT_SYMBOL vmlinux 0xde11f960 unlock_new_inode +EXPORT_SYMBOL vmlinux 0xde293d86 acpi_match_device_ids +EXPORT_SYMBOL vmlinux 0xde2ed938 tcp_close +EXPORT_SYMBOL vmlinux 0xde2f86cf __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0xde44a927 find_vma +EXPORT_SYMBOL vmlinux 0xde588ff5 sock_no_shutdown +EXPORT_SYMBOL vmlinux 0xde645c95 neigh_table_clear +EXPORT_SYMBOL vmlinux 0xde682433 pci_scan_single_device +EXPORT_SYMBOL vmlinux 0xde68d2f7 simple_transaction_read +EXPORT_SYMBOL vmlinux 0xde72b41d pci_bus_find_capability +EXPORT_SYMBOL vmlinux 0xde75b689 set_irq_type +EXPORT_SYMBOL vmlinux 0xde9360ba totalram_pages +EXPORT_SYMBOL vmlinux 0xde99db47 blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0xde9b17ed agp3_generic_fetch_size +EXPORT_SYMBOL vmlinux 0xdeb35219 pci_disable_msix +EXPORT_SYMBOL vmlinux 0xdecfb024 genl_register_ops +EXPORT_SYMBOL vmlinux 0xdefbb5bf generic_file_aio_read +EXPORT_SYMBOL vmlinux 0xdf0da3cc acpi_get_devices +EXPORT_SYMBOL vmlinux 0xdf2589f5 register_chrdev +EXPORT_SYMBOL vmlinux 0xdf2a62ca pci_remove_bus_device +EXPORT_SYMBOL vmlinux 0xdf53d671 get_empty_filp +EXPORT_SYMBOL vmlinux 0xdf5435fe inet_dgram_connect +EXPORT_SYMBOL vmlinux 0xdf5adb00 sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0xdf5d209d find_inode_number +EXPORT_SYMBOL vmlinux 0xdf60cc27 __print_symbol +EXPORT_SYMBOL vmlinux 0xdf8c695a __ndelay +EXPORT_SYMBOL vmlinux 0xdf929370 fs_overflowgid +EXPORT_SYMBOL vmlinux 0xdfd40a52 neigh_connected_output +EXPORT_SYMBOL vmlinux 0xdff98cc2 default_llseek +EXPORT_SYMBOL vmlinux 0xe00d6d59 qdisc_watchdog_cancel +EXPORT_SYMBOL vmlinux 0xe00fb238 release_resource +EXPORT_SYMBOL vmlinux 0xe040f79b is_bad_inode +EXPORT_SYMBOL vmlinux 0xe050cdcc default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0xe0607bfe submit_bh +EXPORT_SYMBOL vmlinux 0xe075d6eb iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0xe0ac8bd2 acpi_bus_generate_netlink_event +EXPORT_SYMBOL vmlinux 0xe0b13336 argv_free +EXPORT_SYMBOL vmlinux 0xe0b5502d adjust_resource +EXPORT_SYMBOL vmlinux 0xe0c8fe0c agp_backend_acquire +EXPORT_SYMBOL vmlinux 0xe0d625aa pci_setup_cardbus +EXPORT_SYMBOL vmlinux 0xe113bbbc csum_partial +EXPORT_SYMBOL vmlinux 0xe11de77c tty_unregister_device +EXPORT_SYMBOL vmlinux 0xe12f5809 invalidate_inodes +EXPORT_SYMBOL vmlinux 0xe13cd8a7 dmi_name_in_vendors +EXPORT_SYMBOL vmlinux 0xe173d1ed __dst_free +EXPORT_SYMBOL vmlinux 0xe1761617 security_inet_conn_request +EXPORT_SYMBOL vmlinux 0xe1883329 __bio_clone +EXPORT_SYMBOL vmlinux 0xe1bbc7cf elv_rb_del +EXPORT_SYMBOL vmlinux 0xe1c65518 filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0xe1c95314 node_data +EXPORT_SYMBOL vmlinux 0xe1cd28b7 __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0xe1d3f441 set_pages_wb +EXPORT_SYMBOL vmlinux 0xe1e5a758 bh_submit_read +EXPORT_SYMBOL vmlinux 0xe1ffff77 put_disk +EXPORT_SYMBOL vmlinux 0xe20d59ab pnp_stop_dev +EXPORT_SYMBOL vmlinux 0xe2205739 blk_sync_queue +EXPORT_SYMBOL vmlinux 0xe24050c7 scnprintf +EXPORT_SYMBOL vmlinux 0xe24d3a97 jiffies_64 +EXPORT_SYMBOL vmlinux 0xe26ec842 inet_stream_ops +EXPORT_SYMBOL vmlinux 0xe27e9ae7 register_gifconf +EXPORT_SYMBOL vmlinux 0xe28be5e6 elevator_init +EXPORT_SYMBOL vmlinux 0xe2a17e0f dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0xe2b6a172 tty_register_device +EXPORT_SYMBOL vmlinux 0xe2d5255a strcmp +EXPORT_SYMBOL vmlinux 0xe2e43630 blk_integrity_register +EXPORT_SYMBOL vmlinux 0xe2e4e39b agp_alloc_page_array +EXPORT_SYMBOL vmlinux 0xe2ea1661 ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0xe32bb9b3 __lookup_hash +EXPORT_SYMBOL vmlinux 0xe3375fb6 register_netdevice +EXPORT_SYMBOL vmlinux 0xe351633f genl_register_family +EXPORT_SYMBOL vmlinux 0xe353b6c9 agp_enable +EXPORT_SYMBOL vmlinux 0xe385fd34 pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0xe3b0192b vscnprintf +EXPORT_SYMBOL vmlinux 0xe3b71d93 kick_iocb +EXPORT_SYMBOL vmlinux 0xe3d8bc54 seq_path +EXPORT_SYMBOL vmlinux 0xe3fbe148 acpi_install_table_handler +EXPORT_SYMBOL vmlinux 0xe4025e1f blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0xe417f658 proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0xe420a824 bio_split +EXPORT_SYMBOL vmlinux 0xe43617f7 acpi_gbl_FADT +EXPORT_SYMBOL vmlinux 0xe456bd3a complete +EXPORT_SYMBOL vmlinux 0xe484e35f ioread32 +EXPORT_SYMBOL vmlinux 0xe4870354 _read_trylock +EXPORT_SYMBOL vmlinux 0xe4c1df3e _read_lock_bh +EXPORT_SYMBOL vmlinux 0xe5122890 flow_cache_genid +EXPORT_SYMBOL vmlinux 0xe523ad75 synchronize_irq +EXPORT_SYMBOL vmlinux 0xe52947e7 __phys_addr +EXPORT_SYMBOL vmlinux 0xe52d7b4e mark_page_accessed +EXPORT_SYMBOL vmlinux 0xe5347ed7 __bforget +EXPORT_SYMBOL vmlinux 0xe55484ce neigh_seq_stop +EXPORT_SYMBOL vmlinux 0xe55704ab nf_hooks +EXPORT_SYMBOL vmlinux 0xe570cb79 qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0xe57878a1 in6_pton +EXPORT_SYMBOL vmlinux 0xe58477f0 dma_async_tx_descriptor_init +EXPORT_SYMBOL vmlinux 0xe5867808 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0xe58db769 agp_generic_create_gatt_table +EXPORT_SYMBOL vmlinux 0xe5b6fa6a blk_plug_device +EXPORT_SYMBOL vmlinux 0xe5c78a99 do_blank_screen +EXPORT_SYMBOL vmlinux 0xe5ee813b __breadahead +EXPORT_SYMBOL vmlinux 0xe631d3aa sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0xe66510a4 simple_prepare_write +EXPORT_SYMBOL vmlinux 0xe66d1b60 __serio_register_port +EXPORT_SYMBOL vmlinux 0xe681042e tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0xe68fc2e8 sock_setsockopt +EXPORT_SYMBOL vmlinux 0xe694cc8a set_current_groups +EXPORT_SYMBOL vmlinux 0xe6ae4e8c generic_delete_inode +EXPORT_SYMBOL vmlinux 0xe6ddfb27 input_inject_event +EXPORT_SYMBOL vmlinux 0xe6e13a8a tcf_exts_validate +EXPORT_SYMBOL vmlinux 0xe6fbe430 can_do_mlock +EXPORT_SYMBOL vmlinux 0xe716baed acpi_unregister_ioapic +EXPORT_SYMBOL vmlinux 0xe748b416 simple_transaction_release +EXPORT_SYMBOL vmlinux 0xe75eb914 block_write_end +EXPORT_SYMBOL vmlinux 0xe7619460 atm_dev_lookup +EXPORT_SYMBOL vmlinux 0xe77f5770 locks_remove_posix +EXPORT_SYMBOL vmlinux 0xe7871d4b register_sysctl_paths +EXPORT_SYMBOL vmlinux 0xe7923a32 ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0xe7d4daac seq_list_next +EXPORT_SYMBOL vmlinux 0xe7f640d6 eth_header_cache +EXPORT_SYMBOL vmlinux 0xe80ce219 sysctl_tcp_dma_copybreak +EXPORT_SYMBOL vmlinux 0xe8116e08 __kmalloc_node +EXPORT_SYMBOL vmlinux 0xe812d9d0 pci_find_device +EXPORT_SYMBOL vmlinux 0xe816c40f kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0xe8583614 posix_acl_from_xattr +EXPORT_SYMBOL vmlinux 0xe85e6a39 dst_discard +EXPORT_SYMBOL vmlinux 0xe89e97fe vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0xe8b12750 idr_replace +EXPORT_SYMBOL vmlinux 0xe8cd902e hweight16 +EXPORT_SYMBOL vmlinux 0xe910b532 del_timer_sync +EXPORT_SYMBOL vmlinux 0xe914e41e strcpy +EXPORT_SYMBOL vmlinux 0xe9456a5a sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0xe9593d32 qdisc_list_del +EXPORT_SYMBOL vmlinux 0xe9694add tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0xe997667b wrmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xe9da9019 vfs_get_dqinfo +EXPORT_SYMBOL vmlinux 0xe9f44cb5 pci_enable_device_mem +EXPORT_SYMBOL vmlinux 0xea10655a __bitmap_intersects +EXPORT_SYMBOL vmlinux 0xea147363 printk +EXPORT_SYMBOL vmlinux 0xea44461f key_type_keyring +EXPORT_SYMBOL vmlinux 0xea5478ab simple_empty +EXPORT_SYMBOL vmlinux 0xea656635 __tcf_em_tree_match +EXPORT_SYMBOL vmlinux 0xea6fcdaa genl_unregister_family +EXPORT_SYMBOL vmlinux 0xea757d9e inet_frags_init +EXPORT_SYMBOL vmlinux 0xeab4ae92 dst_release +EXPORT_SYMBOL vmlinux 0xeab79909 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0xead58fb9 print_hex_dump +EXPORT_SYMBOL vmlinux 0xeae3dfd6 __const_udelay +EXPORT_SYMBOL vmlinux 0xeb1fabf6 interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0xeb228272 posix_acl_create_masq +EXPORT_SYMBOL vmlinux 0xeb395084 param_get_invbool +EXPORT_SYMBOL vmlinux 0xeb48fc84 remap_pfn_range +EXPORT_SYMBOL vmlinux 0xeb6a7743 netif_device_detach +EXPORT_SYMBOL vmlinux 0xeb745b7c tcp_mtup_init +EXPORT_SYMBOL vmlinux 0xeb8f54b3 strstrip +EXPORT_SYMBOL vmlinux 0xeba41430 xfrm_input +EXPORT_SYMBOL vmlinux 0xebb09431 shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0xebbb2b9c inode_set_bytes +EXPORT_SYMBOL vmlinux 0xebbf1dba strncasecmp +EXPORT_SYMBOL vmlinux 0xebd273a6 strict_strtoull +EXPORT_SYMBOL vmlinux 0xebea0954 bio_integrity_get_tag +EXPORT_SYMBOL vmlinux 0xec247322 cfb_fillrect +EXPORT_SYMBOL vmlinux 0xec860422 bioset_free +EXPORT_SYMBOL vmlinux 0xec8ceac1 get_super +EXPORT_SYMBOL vmlinux 0xecde1418 _spin_lock_irq +EXPORT_SYMBOL vmlinux 0xed05d127 kernel_getsockname +EXPORT_SYMBOL vmlinux 0xed07c44c tcp_getsockopt +EXPORT_SYMBOL vmlinux 0xed166093 blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0xed926d18 compat_tcp_getsockopt +EXPORT_SYMBOL vmlinux 0xeda0abe2 inet_shutdown +EXPORT_SYMBOL vmlinux 0xedbaee5e nla_strcmp +EXPORT_SYMBOL vmlinux 0xedc03953 iounmap +EXPORT_SYMBOL vmlinux 0xedd14538 param_get_uint +EXPORT_SYMBOL vmlinux 0xee138752 nf_log_packet +EXPORT_SYMBOL vmlinux 0xee218dc2 sock_no_poll +EXPORT_SYMBOL vmlinux 0xee2d0fc7 _local_bh_enable +EXPORT_SYMBOL vmlinux 0xee7eb9e1 pnp_platform_devices +EXPORT_SYMBOL vmlinux 0xeea37c7f vfs_llseek +EXPORT_SYMBOL vmlinux 0xeea9dbaf bitmap_bitremap +EXPORT_SYMBOL vmlinux 0xeeb1717c param_array_get +EXPORT_SYMBOL vmlinux 0xeecaea22 down_write_trylock +EXPORT_SYMBOL vmlinux 0xeed56f88 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0xef10e2dc __alloc_skb +EXPORT_SYMBOL vmlinux 0xef4f7783 pci_pme_capable +EXPORT_SYMBOL vmlinux 0xef652a23 generic_file_direct_write +EXPORT_SYMBOL vmlinux 0xef663308 dma_async_memcpy_buf_to_buf +EXPORT_SYMBOL vmlinux 0xef6deb6f deny_write_access +EXPORT_SYMBOL vmlinux 0xef958205 inet_dgram_ops +EXPORT_SYMBOL vmlinux 0xef9aedfc boot_option_idle_override +EXPORT_SYMBOL vmlinux 0xefdd70ce security_secid_to_secctx +EXPORT_SYMBOL vmlinux 0xefe099c3 acpi_get_event_status +EXPORT_SYMBOL vmlinux 0xefea9b0d netif_rx_ni +EXPORT_SYMBOL vmlinux 0xeff62008 pci_restore_state +EXPORT_SYMBOL vmlinux 0xeffb322f __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0xeffc6220 agp_generic_alloc_page +EXPORT_SYMBOL vmlinux 0xf0009fee put_pages_list +EXPORT_SYMBOL vmlinux 0xf02ff9ef uart_remove_one_port +EXPORT_SYMBOL vmlinux 0xf05cb6e3 lookup_one_len +EXPORT_SYMBOL vmlinux 0xf0622901 kernel_connect +EXPORT_SYMBOL vmlinux 0xf065f629 ioread16be +EXPORT_SYMBOL vmlinux 0xf093a81a tcp_ioctl +EXPORT_SYMBOL vmlinux 0xf0b57c68 param_set_long +EXPORT_SYMBOL vmlinux 0xf0f1246c kvasprintf +EXPORT_SYMBOL vmlinux 0xf10de535 ioread8 +EXPORT_SYMBOL vmlinux 0xf11543ff find_first_zero_bit +EXPORT_SYMBOL vmlinux 0xf116d4b5 copy_in_user +EXPORT_SYMBOL vmlinux 0xf15f09ef rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0xf162fe2d sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0xf170eb6f alloc_tty_driver +EXPORT_SYMBOL vmlinux 0xf174ed48 acquire_console_sem +EXPORT_SYMBOL vmlinux 0xf195c682 fb_invert_cmaps +EXPORT_SYMBOL vmlinux 0xf1aba93a pci_enable_wake +EXPORT_SYMBOL vmlinux 0xf1e98c74 avenrun +EXPORT_SYMBOL vmlinux 0xf1eed002 qdisc_watchdog_schedule +EXPORT_SYMBOL vmlinux 0xf20dabd8 free_irq +EXPORT_SYMBOL vmlinux 0xf246de13 tcf_hash_destroy +EXPORT_SYMBOL vmlinux 0xf24e6dea do_splice_to +EXPORT_SYMBOL vmlinux 0xf2997713 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0xf2a6d2bf xfrm_policy_count +EXPORT_SYMBOL vmlinux 0xf2afa595 param_get_charp +EXPORT_SYMBOL vmlinux 0xf30dc211 tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0xf313da4e sha_transform +EXPORT_SYMBOL vmlinux 0xf3180c25 kmalloc_caches +EXPORT_SYMBOL vmlinux 0xf3258dca get_disk +EXPORT_SYMBOL vmlinux 0xf3341268 __clear_user +EXPORT_SYMBOL vmlinux 0xf338d4c3 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0xf34236da pci_disable_device +EXPORT_SYMBOL vmlinux 0xf343dcb3 __rta_fill +EXPORT_SYMBOL vmlinux 0xf346231f seq_list_start_head +EXPORT_SYMBOL vmlinux 0xf38cd527 dev_set_allmulti +EXPORT_SYMBOL vmlinux 0xf3bf0bce __bitmap_complement +EXPORT_SYMBOL vmlinux 0xf3f66641 blk_remove_plug +EXPORT_SYMBOL vmlinux 0xf3fa114b fib_default_rule_add +EXPORT_SYMBOL vmlinux 0xf4063d28 sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0xf441ac43 ioread8_rep +EXPORT_SYMBOL vmlinux 0xf4628e71 xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0xf4699d43 clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0xf46eb251 bdi_init +EXPORT_SYMBOL vmlinux 0xf47d47e0 acpi_enable_gpe +EXPORT_SYMBOL vmlinux 0xf49a4eae tcp_parse_options +EXPORT_SYMBOL vmlinux 0xf49bc67a atm_pcr_goal +EXPORT_SYMBOL vmlinux 0xf4a5c213 avail_to_resrv_perfctr_nmi_bit +EXPORT_SYMBOL vmlinux 0xf4f14de6 rtnl_trylock +EXPORT_SYMBOL vmlinux 0xf4f52f93 dqstats +EXPORT_SYMBOL vmlinux 0xf51ae235 touch_nmi_watchdog +EXPORT_SYMBOL vmlinux 0xf52252fc simple_write_end +EXPORT_SYMBOL vmlinux 0xf53d4c26 qdisc_class_hash_destroy +EXPORT_SYMBOL vmlinux 0xf547bce8 elv_queue_empty +EXPORT_SYMBOL vmlinux 0xf5816c58 fb_firmware_edid +EXPORT_SYMBOL vmlinux 0xf58890d6 con_set_default_unimap +EXPORT_SYMBOL vmlinux 0xf5bf9616 proc_dointvec +EXPORT_SYMBOL vmlinux 0xf5ce9811 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0xf5f0b7cd pci_set_dma_max_seg_size +EXPORT_SYMBOL vmlinux 0xf6231091 iget5_locked +EXPORT_SYMBOL vmlinux 0xf666cbb3 __memcpy_fromio +EXPORT_SYMBOL vmlinux 0xf678cdea tcf_register_action +EXPORT_SYMBOL vmlinux 0xf6bb4729 color_table +EXPORT_SYMBOL vmlinux 0xf6c5a56b get_agp_version +EXPORT_SYMBOL vmlinux 0xf6cdb69b key_revoke +EXPORT_SYMBOL vmlinux 0xf6ebc03b net_ratelimit +EXPORT_SYMBOL vmlinux 0xf6ff21f1 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0xf749534a gen_pool_free +EXPORT_SYMBOL vmlinux 0xf78d04ab netlink_register_notifier +EXPORT_SYMBOL vmlinux 0xf7924178 arp_tbl +EXPORT_SYMBOL vmlinux 0xf8045795 sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0xf80d9017 dma_free_coherent +EXPORT_SYMBOL vmlinux 0xf8216cb3 sock_create +EXPORT_SYMBOL vmlinux 0xf82abc1d isa_dma_bridge_buggy +EXPORT_SYMBOL vmlinux 0xf82e3d47 acpi_initialize_objects +EXPORT_SYMBOL vmlinux 0xf82f1109 utf8_wctomb +EXPORT_SYMBOL vmlinux 0xf8434a48 netif_rx +EXPORT_SYMBOL vmlinux 0xf849d06c blk_rq_map_integrity_sg +EXPORT_SYMBOL vmlinux 0xf86172fe compat_ip_setsockopt +EXPORT_SYMBOL vmlinux 0xf8624b3f sysctl_string +EXPORT_SYMBOL vmlinux 0xf87bb36e acpi_bus_add +EXPORT_SYMBOL vmlinux 0xf8814f73 rb_last +EXPORT_SYMBOL vmlinux 0xf88e0ee2 acpi_get_table_header +EXPORT_SYMBOL vmlinux 0xf890fe7f pm_idle +EXPORT_SYMBOL vmlinux 0xf89843f9 schedule_work +EXPORT_SYMBOL vmlinux 0xf8aa47ae mutex_lock_killable +EXPORT_SYMBOL vmlinux 0xf8aefa7b tcp_read_sock +EXPORT_SYMBOL vmlinux 0xf8b30e93 mempool_create +EXPORT_SYMBOL vmlinux 0xf8fbb8ef neigh_destroy +EXPORT_SYMBOL vmlinux 0xf943f0de seq_escape +EXPORT_SYMBOL vmlinux 0xf9718f6f tcp_proc_register +EXPORT_SYMBOL vmlinux 0xf97a76a6 pv_cpu_ops +EXPORT_SYMBOL vmlinux 0xf981110b pci_get_subsys +EXPORT_SYMBOL vmlinux 0xf9a482f9 msleep +EXPORT_SYMBOL vmlinux 0xf9bd9171 vfs_readlink +EXPORT_SYMBOL vmlinux 0xfa0564fc __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfa19c69e pci_scan_bus_parented +EXPORT_SYMBOL vmlinux 0xfa6252e3 inode_permission +EXPORT_SYMBOL vmlinux 0xfa842fdc down_write +EXPORT_SYMBOL vmlinux 0xfab96681 load_nls_default +EXPORT_SYMBOL vmlinux 0xfaf98462 bitrev32 +EXPORT_SYMBOL vmlinux 0xfb0443fb acpi_get_parent +EXPORT_SYMBOL vmlinux 0xfb0cf2e9 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0xfb0db878 aio_complete +EXPORT_SYMBOL vmlinux 0xfb328ba8 seq_lseek +EXPORT_SYMBOL vmlinux 0xfb6af58d recalc_sigpending +EXPORT_SYMBOL vmlinux 0xfb76c014 dev_add_pack +EXPORT_SYMBOL vmlinux 0xfba0c2e0 llc_sap_list_lock +EXPORT_SYMBOL vmlinux 0xfba3c8cc sk_receive_skb +EXPORT_SYMBOL vmlinux 0xfbed20d8 ioremap_nocache +EXPORT_SYMBOL vmlinux 0xfbf92453 param_get_bool +EXPORT_SYMBOL vmlinux 0xfbfa1247 uart_resume_port +EXPORT_SYMBOL vmlinux 0xfc02b7ad sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0xfc1a4250 bdi_register_dev +EXPORT_SYMBOL vmlinux 0xfc20c87b compat_sock_get_timestampns +EXPORT_SYMBOL vmlinux 0xfc383907 pcim_iounmap +EXPORT_SYMBOL vmlinux 0xfc39e32f ioport_unmap +EXPORT_SYMBOL vmlinux 0xfc470c05 lock_sock_nested +EXPORT_SYMBOL vmlinux 0xfc52c08c pcie_get_readrq +EXPORT_SYMBOL vmlinux 0xfc7f7aae dquot_drop +EXPORT_SYMBOL vmlinux 0xfc8b429c devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0xfcaa04a0 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfcb97d2f pnp_device_attach +EXPORT_SYMBOL vmlinux 0xfcdc8352 key_alloc +EXPORT_SYMBOL vmlinux 0xfcdd8cf6 param_get_ushort +EXPORT_SYMBOL vmlinux 0xfcec0987 enable_irq +EXPORT_SYMBOL vmlinux 0xfcf0018c open_exec +EXPORT_SYMBOL vmlinux 0xfcfa03ff fb_videomode_to_modelist +EXPORT_SYMBOL vmlinux 0xfd1c92a8 per_cpu____irq_regs +EXPORT_SYMBOL vmlinux 0xfd2f4c28 unlock_buffer +EXPORT_SYMBOL vmlinux 0xfd3135e7 get_write_access +EXPORT_SYMBOL vmlinux 0xfd98879a rb_next +EXPORT_SYMBOL vmlinux 0xfdb9b629 ioread32be +EXPORT_SYMBOL vmlinux 0xfdcc26dd dev_close +EXPORT_SYMBOL vmlinux 0xfde2145a boot_tvec_bases +EXPORT_SYMBOL vmlinux 0xfdf2d800 pci_pme_active +EXPORT_SYMBOL vmlinux 0xfe047ce6 acpi_enter_sleep_state +EXPORT_SYMBOL vmlinux 0xfe0f5e62 request_key +EXPORT_SYMBOL vmlinux 0xfe11ea2b skb_free_datagram +EXPORT_SYMBOL vmlinux 0xfe26fc7c nr_node_ids +EXPORT_SYMBOL vmlinux 0xfe392bcd generic_segment_checks +EXPORT_SYMBOL vmlinux 0xfe5d4bb2 sys_tz +EXPORT_SYMBOL vmlinux 0xfe769456 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0xfe7c27c1 dev_mc_add +EXPORT_SYMBOL vmlinux 0xfe7c4287 nr_cpu_ids +EXPORT_SYMBOL vmlinux 0xfe8eb0aa alloc_buffer_head +EXPORT_SYMBOL vmlinux 0xfe917b88 ps2_command +EXPORT_SYMBOL vmlinux 0xfea14b4d seq_read +EXPORT_SYMBOL vmlinux 0xfebc0cbf __wait_on_buffer +EXPORT_SYMBOL vmlinux 0xfec3c2f2 bcd2bin +EXPORT_SYMBOL vmlinux 0xfedd35fc console_suspend_enabled +EXPORT_SYMBOL vmlinux 0xfee4892b genl_sock +EXPORT_SYMBOL vmlinux 0xfeec104b xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0xff1e9dd8 seq_list_start +EXPORT_SYMBOL vmlinux 0xff48f7cc inode_init_once +EXPORT_SYMBOL vmlinux 0xff6878cf fb_default_cmap +EXPORT_SYMBOL vmlinux 0xff6c9439 block_write_begin +EXPORT_SYMBOL vmlinux 0xff708fd3 mempool_destroy +EXPORT_SYMBOL vmlinux 0xff779fe6 input_grab_device +EXPORT_SYMBOL vmlinux 0xff7f47ac __elv_add_request +EXPORT_SYMBOL vmlinux 0xff9ca065 fb_edid_to_monspecs +EXPORT_SYMBOL vmlinux 0xffafdc5c _read_unlock_irq +EXPORT_SYMBOL vmlinux 0xffbb77f0 sk_reset_timer +EXPORT_SYMBOL vmlinux 0xffd5a395 default_wake_function +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x00aaf935 kvm_disable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x05b20bc7 kvm_lapic_enabled +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x07a37517 kvm_get_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x094ac8f4 kvm_get_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0aba6308 kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0ca96fb1 kvm_inject_pending_timer_irqs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0edba703 kvm_release_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0f041d40 kvm_lapic_find_highest_irr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1099fb94 kvm_mmu_reset_context +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x12d1b23b kvm_release_pfn_clean +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x14edd812 kvm_get_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x15ecd2cd kvm_read_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x193e07e9 kvm_task_switch +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1aa41982 kvm_set_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1c06df86 kvm_mmu_load +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1e4580bb kvm_release_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x21284d29 kvm_set_cr0 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2322e039 kvm_set_pfn_accessed +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x240daead kvm_lapic_set_tpr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x24ccfc74 kvm_write_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x26ca07eb emulator_write_emulated +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x27046576 kvm_exit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2ab72290 kvm_lapic_get_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2eaf780e kvm_emulate_pio +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x317f9e6b kvm_enable_efer_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x361792d0 load_pdptrs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x372633f3 kvm_queue_exception +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3961dec9 gfn_to_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3abb7213 kvm_lapic_reset +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3e268086 kvm_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x434355d3 kvm_report_emulation_failure +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4a7cbe69 is_error_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4d14c883 fx_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4f242e83 kvm_lapic_get_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x52ed2d0b emulate_instruction +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x541ee4c8 kvm_set_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x65432d3b kvm_mmu_page_fault +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x65bd9021 kvm_resched +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x65f32ddf kvm_vcpu_cache +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x67b37172 kvm_set_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x71168123 kvm_get_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x74a041ac is_error_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7571bb84 kvm_emulate_hypercall +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7e240dde kvm_create_lapic +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7e8cec18 kvm_mmu_unprotect_page_virt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7f715335 kvm_set_cr3 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x814e512a kvm_set_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8ce4f3ab kvm_enable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8e7f9b47 segment_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x942d9225 gfn_to_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x99d1e49a kvm_cpu_get_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9ddaef22 kvm_cpu_has_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa361bc65 kvm_set_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa65f67a6 kvm_clear_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa80cf3ab kvm_read_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xad2b4e9b gfn_to_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xad700ed7 __kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xaf4af07a kvm_get_cs_db_l_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xb927e761 kvm_inject_nmi +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xba40a11e kvm_timer_intr_post +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd15c2bf kvm_emulate_cpuid +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd377dc9 kvm_mmu_set_nonpresent_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd86163a kvm_handle_fault_on_reboot +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd94103b kvm_mmu_set_base_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbdbc8990 kvm_queue_exception_e +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbdf0d859 kvm_lmsw +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbf717296 kvm_clear_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xca6c1580 kvm_vcpu_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xcb1ceecf kvm_emulate_halt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xcd0b66b7 kvm_is_visible_gfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd0b2727a kvm_mmu_set_mask_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd296def9 kvm_is_error_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdbfb5fb4 kvm_vcpu_uninit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdd5675f0 kvm_put_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xe2c691e1 kvm_release_page_clean +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xef3fffe8 kvm_get_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf080d298 emulator_read_std +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf5103889 kvm_put_guest_fpu +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf60b9af9 kvm_set_cr4 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf9070561 kvm_emulate_pio_string +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xfbe77a16 kvm_load_guest_fpu +EXPORT_SYMBOL_GPL crypto/aead 0x0581052d crypto_aead_setauthsize +EXPORT_SYMBOL_GPL crypto/aead 0x0f92a6e0 crypto_alloc_aead +EXPORT_SYMBOL_GPL crypto/aead 0x1b66d742 aead_geniv_alloc +EXPORT_SYMBOL_GPL crypto/aead 0x233b951d aead_geniv_init +EXPORT_SYMBOL_GPL crypto/aead 0x4fc1268e aead_geniv_exit +EXPORT_SYMBOL_GPL crypto/aead 0x78a83d3b crypto_nivaead_type +EXPORT_SYMBOL_GPL crypto/aead 0x7b104b9d aead_geniv_free +EXPORT_SYMBOL_GPL crypto/aead 0xe47aa47c crypto_aead_type +EXPORT_SYMBOL_GPL crypto/aead 0xe882a0f2 crypto_grab_aead +EXPORT_SYMBOL_GPL crypto/aes_generic 0x1381bf2d crypto_ft_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x22894d94 crypto_il_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x465dc396 crypto_aes_set_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5f943003 crypto_it_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5fe743de crypto_aes_expand_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x6e9cc2ba crypto_fl_tab +EXPORT_SYMBOL_GPL crypto/async_tx/async_memcpy 0x215fd546 async_memcpy +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x2be84c9b async_tx_run_dependencies +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x59a79343 __async_tx_find_channel +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x6b4a6db2 async_tx_issue_pending_all +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xcd654cc9 async_tx_submit +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xd9d1c50e async_tx_quiesce +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xdad23b28 dma_wait_for_async_tx +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xf22d0802 async_trigger_callback +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0x69d18617 async_xor_zero_sum +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0xafa1af85 async_xor +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x02b231e1 skcipher_geniv_free +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x02d5c96b blkcipher_walk_done +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x2b556b76 crypto_ablkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x2c889fbf skcipher_geniv_alloc +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x7128dac8 blkcipher_walk_virt_block +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x8017ac74 blkcipher_walk_virt +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x9929c619 crypto_blkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xa3382896 crypto_grab_skcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xbfdf79fb crypto_alloc_ablkcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xc5abe22a skcipher_geniv_init +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xdd26d05b crypto_givcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xfa8c2322 blkcipher_walk_phys +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xfb673bd4 skcipher_geniv_exit +EXPORT_SYMBOL_GPL crypto/des_generic 0xcfd9a2c0 des_ekey +EXPORT_SYMBOL_GPL crypto/twofish_common 0x97065ba1 twofish_setkey +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x100c48a2 unregister_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x2611fbee register_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x318920b1 register_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xbd506a46 unregister_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xcc6ab305 is_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x0ad5c33f acpi_smbus_register_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x158c2ad0 acpi_smbus_unregister_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x526b867a acpi_smbus_read +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0xb3d5e527 acpi_smbus_write +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x3ecf6cfc wmi_install_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x561c634a wmi_evaluate_method +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x876d29f1 wmi_get_event_data +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xb5a6ebe2 wmi_remove_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xc9d4d6d1 wmi_has_guid +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xda29f8b0 wmi_set_block +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xfb882fb7 wmi_query_block +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0067df75 ata_tf_from_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x00ebcb5d ata_id_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0x012c766c ata_bmdma_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0x01391ea8 ata_acpi_gtm +EXPORT_SYMBOL_GPL drivers/ata/libata 0x01fb13c0 ata_do_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0x03ba3e91 sata_sff_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x03e3686c ata_timing_cycle2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0531dcb8 ata_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0646ccc9 ata_pci_remove_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0x070a3bbf ata_sff_data_xfer_noirq +EXPORT_SYMBOL_GPL drivers/ata/libata 0x07ab611e ata_base_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0e1dbf2b ata_link_offline +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0f7d2436 ata_dev_pair +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1078f700 ata_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x10d0eb08 ata_port_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x13b8d67c ata_link_online +EXPORT_SYMBOL_GPL drivers/ata/libata 0x14823ec4 ata_sff_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1532fa01 ata_port_probe +EXPORT_SYMBOL_GPL drivers/ata/libata 0x16e75724 ata_port_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0x17472a33 ata_acpi_stm +EXPORT_SYMBOL_GPL drivers/ata/libata 0x19d24843 ata_sff_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1ed118d6 ata_sff_check_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0x22b915b9 ata_host_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0x25de9164 ata_eh_freeze_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0x29294a81 ata_bmdma_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2dbd9a13 ata_std_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2e2e959c ata_sas_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2fa81e56 ata_sff_qc_issue +EXPORT_SYMBOL_GPL drivers/ata/libata 0x30273d2a ata_eh_analyze_ncq_error +EXPORT_SYMBOL_GPL drivers/ata/libata 0x30df3010 ata_eh_thaw_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0x338edecb sata_async_notification +EXPORT_SYMBOL_GPL drivers/ata/libata 0x33b3917f ata_do_dev_read_id +EXPORT_SYMBOL_GPL drivers/ata/libata 0x34be1a69 ata_cable_40wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0x354b59e9 ata_pci_bmdma_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x387a5c7e __ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3a898234 ata_cable_ignore +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3e1ff10c ata_eh_qc_retry +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3eb9c430 ata_dummy_port_info +EXPORT_SYMBOL_GPL drivers/ata/libata 0x40af0dec ata_xfer_mode2mask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x41ff54ed ata_sff_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4369f6ff ata_sff_tf_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0x43f56e82 ata_xfer_mode2shift +EXPORT_SYMBOL_GPL drivers/ata/libata 0x45d3e4ea sata_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x468a3a70 ata_bmdma_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x46bbea94 ata_host_activate +EXPORT_SYMBOL_GPL drivers/ata/libata 0x46e8751a sata_link_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4a5bcc10 ata_sff_dev_select +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4af06d8f ata_dev_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4b2dcd88 ata_sff_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4d5b7b05 ata_sff_busy_sleep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4e2944b0 ata_sas_port_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4f10b51c ata_timing_compute +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4f2650fa ata_port_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fabe64e ata_sff_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fdc945d sata_deb_timing_normal +EXPORT_SYMBOL_GPL drivers/ata/libata 0x50559e06 ata_sas_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x50923106 ata_sff_dumb_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x531faf27 ata_sff_irq_clear +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5333d70a dev_attr_link_power_management_policy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x57f05500 ata_sff_thaw +EXPORT_SYMBOL_GPL drivers/ata/libata 0x58cbb27f ata_host_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5b01d551 ata_host_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5d2e9ab4 sata_pmp_qc_defer_cmd_switch +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5e859671 sata_link_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5ebfbc0d ata_eh_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5ee48632 ata_host_detach +EXPORT_SYMBOL_GPL drivers/ata/libata 0x605ff91c ata_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6089d973 ata_port_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0x649399fc sata_scr_write +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6521683d ata_pci_sff_init_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0x69e9a2cb ata_scsi_slave_config +EXPORT_SYMBOL_GPL drivers/ata/libata 0x69f72c86 ata_bmdma_mode_filter +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6c5abcd4 ata_sff_qc_fill_rtf +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6e247fe0 ata_sff_softreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x707ff1bb ata_xfer_mask2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x71872a25 ata_pio_need_iordy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x733e4115 ata_std_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a437f4 ata_qc_complete_multiple +EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a48b4a ata_sff_std_ports +EXPORT_SYMBOL_GPL drivers/ata/libata 0x743a165e ata_pack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7640795f ata_sff_irq_on +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7680959c ata_port_schedule_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0x77dc2389 ata_pci_bmdma_clear_simplex +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7a0b9bb0 ata_sff_dma_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7a6acc1c ata_sff_post_internal_cmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7c0aa664 ata_link_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7f73b635 ata_pci_device_do_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0x81c3555c ata_bmdma_setup +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8316a798 ata_acpi_gtm_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x844121d6 sata_pmp_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8888c39b ata_host_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0x89ec587b ata_bmdma_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b752ac1 ata_tf_to_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8c397ec9 sata_scr_write_flush +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8d9271fc ata_do_set_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8dc4252a ata_std_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8e2de209 sata_scr_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8f3b8399 ata_host_alloc_pinfo +EXPORT_SYMBOL_GPL drivers/ata/libata 0x91102b35 ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94a68723 ata_scsi_slave_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94dc62d2 ata_scsi_ioctl +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98520864 ata_pci_device_do_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9862bf0c ata_sff_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98796db3 ata_cable_unknown +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98c6b6bd ata_sas_port_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9961389a ata_std_bios_param +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9c4fcc15 dev_attr_sw_activity +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9e2fcf57 ata_scsi_simulate +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9f4861c8 ata_sff_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa4cf7245 ata_sg_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0xab01ac2f ata_sff_exec_command +EXPORT_SYMBOL_GPL drivers/ata/libata 0xafa680e6 ata_sas_slave_configure +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb174100b sata_pmp_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb1b6e95d sata_link_debounce +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb4c964a5 ata_sff_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6aeb661 ata_id_c_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb92e4abe ata_host_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xba7bc4e9 dev_attr_em_message +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbbf57dd2 ata_port_pbar_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbc0482e3 sata_std_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbcd975cd ata_acpi_cbl_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbd578b54 ata_sas_port_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe1887e4 ata_unpack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbf839350 ata_sff_tf_load +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbfa9f977 ata_cable_sata +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbfd7b9b6 ata_sff_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc21b8e22 ata_scsi_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc3f6ccc2 ata_sff_hsm_move +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc428068d sata_deb_timing_long +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc48b7ccf ata_mode_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc4acf318 ata_pci_sff_init_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc5ae2ef4 ata_bus_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc673e23e ata_scsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc8441306 ata_sff_wait_ready +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcb432b16 dev_attr_em_message_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcccfb2fa sata_deb_timing_hotplug +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcf101579 ata_pci_device_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd3fe7b4e ata_pci_sff_activate_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd6f752bd ata_std_qc_defer +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd7f468c9 ata_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd84cd7f4 ata_timing_find_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdbfcf27f ata_pci_device_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0xde889f2b ata_sff_host_intr +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdf3022b2 ata_sff_interrupt +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe15c8821 ata_dummy_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe49ff3b0 ata_wait_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0xea242048 ata_pci_sff_prepare_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0xea418e0f atapi_cmd_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf0f75776 ata_sff_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf370316f ata_sff_data_xfer +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf3d5cc13 ata_timing_merge +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf5e9c680 ata_sas_port_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf6535fdb ata_host_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf70f9fe3 pci_test_config_bits +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf712879c ata_ehi_clear_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8f3a0fb ata_ratelimit +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf95c875b ata_noop_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf9ca3160 ata_id_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfc6db3aa ata_cable_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfec4786a sata_set_spd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xff949b4c sata_scr_valid +EXPORT_SYMBOL_GPL drivers/ata/pata_sis 0x83c06bf9 sis_info133_for_sata +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x02ff9464 cfag12864b_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x0ecb2e5d cfag12864b_disable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x305dc3c6 cfag12864b_isenabled +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x3389f926 cfag12864b_enable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x9522a342 cfag12864b_getrate +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0xc48e9d95 cfag12864b_buffer +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x14102f23 ks0108_displaystate +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x48a70518 ks0108_writedata +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x4f506333 ks0108_startline +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x6edae968 ks0108_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xbf4774db ks0108_writecontrol +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xedde6df2 ks0108_page +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xfee8ef7b ks0108_address +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x1ff2fdd8 tpm_show_active +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x1ffd54f1 tpm_calc_ordinal_duration +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x36b852f4 tpm_remove_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x44ec43e2 tpm_show_temp_deactivated +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x4a2d5ec4 tpm_write +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x4c86db04 tpm_gen_interrupt +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x57647f9c tpm_release +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x63aa28f5 tpm_show_caps_1_2 +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7ce459ad tpm_show_enabled +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x8a6bc58b tpm_store_cancel +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9243fada tpm_get_timeouts +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9f02eb96 tpm_register_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9f2288ba tpm_show_pcrs +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc42620a6 tpm_continue_selftest +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc95ea356 tpm_show_owned +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xd3d6f28b tpm_read +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xe8ada778 tpm_open +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xe8b0e3e5 tpm_pm_resume +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xe9876d63 tpm_show_caps +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xf4bd91d0 tpm_pm_suspend +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xf9784d9a tpm_show_pubek +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0xbf67b76f tpm_bios_log_setup +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0xd941eec8 tpm_bios_log_teardown +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x01b354b4 cpufreq_frequency_table_target +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x2f47d8c7 cpufreq_frequency_get_table +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x3361319f cpufreq_frequency_table_cpuinfo +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x706b3a33 cpufreq_frequency_table_get_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x7ae1ae8e cpufreq_frequency_table_put_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x7bc780a5 cpufreq_frequency_table_verify +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0xa861f3b5 cpufreq_freq_attr_scaling_available_freqs +EXPORT_SYMBOL_GPL drivers/dca/dca 0x05b3551e unregister_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0x2cd03ed5 register_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0x2e471f01 dca_register_notify +EXPORT_SYMBOL_GPL drivers/dca/dca 0x31a2c8df dca_get_tag +EXPORT_SYMBOL_GPL drivers/dca/dca 0x4324d628 dca3_get_tag +EXPORT_SYMBOL_GPL drivers/dca/dca 0x48ac0971 dca_add_requester +EXPORT_SYMBOL_GPL drivers/dca/dca 0x652621dc dca_remove_requester +EXPORT_SYMBOL_GPL drivers/dca/dca 0x8006c614 dca_unregister_notify +EXPORT_SYMBOL_GPL drivers/dca/dca 0xc58266af alloc_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0xda71046d free_dca_provider +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x061fa43e edac_device_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1460af9e edac_device_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1633927b edac_pci_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x199112a6 edac_device_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1c167262 edac_device_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x30e51ae0 edac_device_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x34a50ad4 edac_pci_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x3cee3db2 edac_pci_handle_pe +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x4b4f08bd edac_mc_del_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x51d31e05 edac_mc_handle_ce_no_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x656183a9 edac_pci_release_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x6eb4b537 edac_mc_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa839fbc5 edac_mc_free +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa95712fe edac_mc_add_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xb7d74f03 edac_pci_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xbed0e378 edac_pci_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcf44d6ae edac_mc_alloc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcf90c047 edac_mc_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xd124389c edac_mc_handle_ue_no_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xd68dd31f edac_pci_reset_delay_period +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xd719df73 edac_mc_find_csrow_by_page +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xdfcbae5e edac_pci_create_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xe6d5635c edac_device_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xf8cb7a17 edac_pci_handle_npe +EXPORT_SYMBOL_GPL drivers/hid/hid 0x008e49bd hid_free_device +EXPORT_SYMBOL_GPL drivers/hid/hid 0x22e05021 hid_parse_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x3bc82e74 hid_input_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x3d2d8e93 hid_output_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x5f3a6dfd hidraw_disconnect +EXPORT_SYMBOL_GPL drivers/hid/hid 0x651305a3 hidraw_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0x8d40c384 hidinput_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0xab7ec347 hid_set_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xb640f303 hidraw_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0xe99b408a hidinput_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0xecededa1 hidinput_find_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xf7d08585 hidinput_disconnect +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x01fd453e usbhid_lookup_quirk +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0xadd2b06d hiddev_hid_event +EXPORT_SYMBOL_GPL drivers/i2c/busses/i2c-nforce2 0x42fa7e2e nforce2_smbus +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x224aba8b i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x50144523 i2c_new_dummy +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x6daff9c8 i2c_bus_type +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x9f414307 i2c_new_probed_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xbe26bf5b i2c_unregister_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xdd9438fd i2c_new_device +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xc8ae0e78 hpsb_config_rom_ip1394_remove +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xdbd22690 hpsb_config_rom_ip1394_add +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xec8d18cf hpsb_disable_irm +EXPORT_SYMBOL_GPL drivers/infiniband/hw/ipath/ib_ipath 0x1514b2b2 ipath_debug +EXPORT_SYMBOL_GPL drivers/input/ff-memless 0xe6f33025 input_ff_create_memless +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x05809a9f wm97xx_read_aux_adc +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x173c5303 wm97xx_reg_read +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x2fe0a29c wm97xx_set_suspend_mode +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x4b576377 wm9712_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x5247f50a wm97xx_config_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x56e97e2d wm9705_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x661c45f2 wm97xx_get_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x81949c43 wm97xx_unregister_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x87fd63e9 wm9713_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xb3c6a551 wm97xx_register_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xd7298039 wm97xx_set_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xdded962a wm97xx_reg_write +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x12f163d3 gigaset_stop +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x1d78ae71 gigaset_blockdriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x2c0979ce gigaset_dbg_buffer +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x3c0ceb0c gigaset_add_event +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x3dcb0999 gigaset_freedriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x454aa44f gigaset_debuglevel +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x4df10ddd gigaset_initcs +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x53dc0905 gigaset_shutdown +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x57bd1155 gigaset_m10x_input +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x5f8548bb gigaset_freecs +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x63b2a1f0 gigaset_fill_inbuf +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x8a09f8ec gigaset_if_receive +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xd3cf7ee6 gigaset_start +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xd74382a6 gigaset_handle_modem_response +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xe98d15a3 gigaset_skb_sent +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xf00279a0 gigaset_m10x_send_skb +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xf03b749d gigaset_initdriver +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x3dbc6938 led_classdev_unregister +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x606f5703 led_classdev_resume +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x748348da led_classdev_suspend +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x96910d35 led_classdev_register +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x0b0ca530 dm_put +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x63bb15c0 dm_set_device_limits +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x67ebd785 dm_noflush_suspending +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x89f73ccf dm_device_name +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x8a1e1f75 dm_disk +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xcbd33995 dm_send_uevents +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xe6699033 dm_path_uevent +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0x64fb57ce dm_unregister_path_selector +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xdacffadc dm_register_path_selector +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x06f33595 md_allow_write +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x1597102b sync_page_io +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x56fb30ed md_do_sync +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x64a4b440 md_new_event +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x04662e0f ir_codes_fusionhdtv_mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x07e92917 ir_codes_avermedia_a16d +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x083661f9 ir_codes_avertv_303 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x088631b9 ir_codes_behold +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x1cb148f5 ir_extract_bits +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2456e513 ir_decode_pulsedistance +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2a4852cc ir_codes_dntv_live_dvb_t +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2af1a608 ir_codes_proteus_2309 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x3811daea ir_codes_manli +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x43c89ef4 ir_decode_biphase +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x45b08f68 ir_codes_pinnacle_grey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4740e7a3 ir_codes_empty +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4ea698a2 ir_codes_purpletv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x55338dda ir_codes_pixelview_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x589cad50 ir_codes_apac_viewcomp +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x5db13554 ir_codes_encore_enltv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x659a9ac0 ir_input_init +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6606596a ir_rc5_timer_keyup +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6a06e2d5 ir_input_keydown +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6adc476d ir_codes_powercolor_real_angel +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6aefdbea ir_codes_npgtech +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6b87c69d ir_codes_iodata_bctv7e +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6d6511e7 ir_dump_samples +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6e2a1870 ir_codes_adstech_dvb_t_pci +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x7277973d ir_codes_pctv_sedna +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x75e89cc3 ir_codes_flydvb +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x772a30a2 ir_codes_nebula +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x85d37490 ir_codes_dntv_live_dvbt_pro +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x89cc1189 ir_codes_winfast +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x902a3cd2 ir_codes_hauppauge_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x933d0bb3 ir_codes_msi_tvanywhere +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x9451e232 ir_codes_behold_columbus +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x96470cab ir_codes_cinergy +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb1f4eb35 ir_codes_avermedia_dvbt +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb6cd4666 ir_codes_eztv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xbdce6594 ir_codes_tt_1500 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc1fea0c1 ir_codes_pv951 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc42bd037 ir_codes_budget_ci_old +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc4b85b21 ir_input_nokey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc6c5a7a1 ir_codes_em_terratec +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd1e0258a ir_codes_flyvideo +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd55e6891 ir_codes_gotview7135 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd9c7f010 ir_codes_rc5_tv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdaa041ad ir_codes_cinergy_1400 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdfcf23df ir_codes_norwood +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xee2f5e0e ir_codes_pinnacle_pctv_hd +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf07533a1 ir_codes_videomate_tv_pvr +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf0fc9374 ir_codes_avermedia +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf2b421aa ir_codes_genius_tvgo_a11mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf4f7a4d6 ir_rc5_timer_end +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfa177653 ir_codes_pixelview +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfb981300 ir_codes_pinnacle_color +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfc54a5cd ir_codes_asus_pc39 +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x0e0dd318 saa7146_vfree_destroy_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x369fcaaa saa7146_register_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x505110d7 saa7146_pgtable_build_single +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x613ef2d5 saa7146_unregister_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x62fe733d saa7146_vmalloc_build_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x7fc10aec saa7146_wait_for_debi_done +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xa6a95506 saa7146_pgtable_alloc +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xc653ebf1 saa7146_pgtable_free +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xc98faf20 saa7146_devices_lock +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xcf683cf2 saa7146_devices +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xe3cd9b5c saa7146_debug +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xf67f44c1 saa7146_i2c_adapter_prepare +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xfb4cc614 saa7146_setgpio +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x166ce5f6 saa7146_start_preview +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x168ab67f saa7146_register_device +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x2d61c0f2 saa7146_set_hps_source_and_sync +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x3da661c3 saa7146_vv_release +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x555ea70d saa7146_vv_init +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xc0508cd0 saa7146_stop_preview +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xf47ff7ce saa7146_unregister_device +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mt20xx 0xe10cf6e5 microtune_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mxl5007t 0x3969c476 mxl5007t_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda18271 0xcc761724 tda18271_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda827x 0x7f949f23 tda827x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0x827abc8a tda829x_probe +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0xfb444527 tda829x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda9887 0x8c267f8e tda9887_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xd28977eb tea5761_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xea33988b tea5761_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0x98adfbad tea5767_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0xb87bf8ef tea5767_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tuner-simple 0xf2219b3d simple_tuner_attach +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x36d74737 ttpci_budget_init_hooks +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x458244a5 ttpci_budget_debiwrite +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x7948c222 budget_debug +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x8a0268c2 ttpci_budget_irq10_handler +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xeb99fba8 ttpci_budget_debiread +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xfc7c6d0f ttpci_budget_init +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xfd4d95a6 ttpci_budget_deinit +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xffe72a99 ttpci_budget_set_video_port +EXPORT_SYMBOL_GPL drivers/media/video/compat_ioctl32 0x893bfe61 v4l_compat_ioctl32 +EXPORT_SYMBOL_GPL drivers/media/video/cx88/cx88xx 0x89d41f6e cx88_setup_xc3028 +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x0c4c71e0 em28xx_audio_analog_set +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x44fd2c62 em28xx_set_mode +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x7a02e48d em28xx_init_isoc +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xd22c24eb em28xx_tuner_callback +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xfdc356fc em28xx_uninit_isoc +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0x4e1a168f saa7134_queryctrl +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xb3966707 saa7134_ts_qops +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xe0f69cdd saa7134_g_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xff18210b saa7134_s_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0x84ce8ac6 v4l2_int_device_register +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0xb1391645 v4l2_int_device_unregister +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x03f836f1 videobuf_read_start +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x0be28bab videobuf_cgmbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x11cfe7c7 videobuf_next_field +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x14f199df videobuf_queue_to_vmalloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x15215c65 videobuf_querybuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x1789f253 videobuf_queue_core_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x1b5b18a8 videobuf_mmap_mapper +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x26b59630 videobuf_streamoff +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x2ea9f980 videobuf_dqbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x38a327f6 videobuf_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x3cbe5805 videobuf_waiton +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x4ac67b8b videobuf_read_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x4f3a0596 videobuf_queue_is_busy +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x7e030034 videobuf_streamon +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x815fb430 __videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xab4cf250 videobuf_qbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xace184b4 videobuf_poll_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xb9022b31 videobuf_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xbcfc774e videobuf_reqbufs +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xc0333f56 videobuf_mmap_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xc6a0ecaf videobuf_queue_cancel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xde5b3079 videobuf_iolock +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xf758bd89 videobuf_read_one +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xfb558667 videobuf_read_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xfea30721 videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x08806486 videobuf_to_dma_contig +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x540a17c2 videobuf_queue_dma_contig_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x8442a313 videobuf_dma_contig_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x26ecaf68 videobuf_sg_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x4b27f806 videobuf_dma_sync +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x531feace videobuf_dma_init_overlay +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x5c7aa182 videobuf_dma_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x7bb4206b videobuf_to_dma +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x7fb2a9bb videobuf_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x933dfb43 videobuf_vmalloc_to_sg +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa0f23e54 videobuf_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa2e0f975 videobuf_dma_init_kernel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa38faed2 videobuf_sg_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xaf1ada19 videobuf_dma_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xc1538b00 videobuf_queue_sg_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xcc1823f5 videobuf_sg_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xdd17fe73 videobuf_dma_init_user +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x4e5d83fd videobuf_to_vmalloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x7bf1fbc6 videobuf_vmalloc_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0xbb02da22 videobuf_queue_vmalloc_init +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x3085b131 sm501_set_clock +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x42a27726 sm501_unit_power +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x494ea35e sm501_find_clock +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x897e1f68 sm501_misc_control +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xed934be3 sm501_modify_reg +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x2df115d4 eeprom_93cx6_multiread +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x63d14d2f eeprom_93cx6_read +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x58a17c64 enclosure_remove_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x6c13472f enclosure_add_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x958b1da4 enclosure_register +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x9ab6f7fd enclosure_component_register +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xc1339762 enclosure_find +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xd359f806 enclosure_unregister +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xf342e30f enclosure_for_each_device +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x2293c8e0 gru_get_next_message +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x5927a880 gru_send_message_gpa +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x7e83f3fc gru_free_message +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x81b3b8e3 gru_create_message_queue +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x9c7283a1 gru_copy_gpa +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x345c9217 xpc_disconnect +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x39046c7a xpc_clear_interface +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x43a01eea xpc_registrations +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x6285dfe8 xp_cpu_to_nasid +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x64ba5017 xp_pa +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x76e36d39 xp_region_size +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x9823adb0 xpc_set_interface +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x9acd8cf8 xpc_interface +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xba3694f3 xp_remote_memcpy +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xead4f7fe xp_max_npartitions +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xf3b47f67 xp_partition_id +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xfe709b6c xpc_connect +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x010aa9b0 sdio_writew +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x19d9fd23 sdio_readsb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x278c21a1 sdio_memcpy_toio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x3054cf5a sdio_writesb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x4932e60a sdio_readw +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x61b4227c sdio_f0_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x67a47346 sdio_f0_readb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x6cb9965e sdio_enable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x6decc1ad sdio_claim_host +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x774329d4 sdio_set_block_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x86627cbf sdio_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x92fc74f8 sdio_disable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xa1ec87c9 sdio_writel +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xa36c1583 sdio_memcpy_fromio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xac2d0856 sdio_register_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xb343754c sdio_readb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xc07ee1ec sdio_align_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xcc636b3d sdio_release_host +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe16309d5 sdio_claim_irq +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe4175d44 sdio_readl +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe97886b0 sdio_unregister_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xf89d0372 sdio_release_irq +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x33daefe9 sdhci_remove_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x4d1e0d44 sdhci_alloc_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x5b119295 sdhci_resume_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x69145b6f sdhci_free_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xa574644d sdhci_add_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xf443c5e8 sdhci_suspend_host +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x25561522 cfi_cmdset_0200 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x4e5fd7f3 cfi_cmdset_0003 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0xd71bae7f cfi_cmdset_0001 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0002 0x02fdeb35 cfi_cmdset_0002 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0020 0x7f2e19cb cfi_cmdset_0020 +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2000 0xeb8297d7 DoC2k_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001 0x92b52cc0 DoCMil_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001plus 0xf4b38d40 DoCMilPlus_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/docecc 0x45937659 doc_decode_ecc +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x0525ab69 put_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x161d03a0 default_mtd_writev +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x29d6c9a9 get_mtd_device_nm +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x36491db8 register_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x3768ddcc kill_mtd_super +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x45df5301 get_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x49cc76d0 deregister_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x57b7ae07 add_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x730c66fe del_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x8da91b7c unregister_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x9a150064 parse_mtd_partitions +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x9b039828 mtd_table +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x9da027f6 get_sb_mtd +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xaac99e1c mtd_erase_callback +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xc23c70d9 register_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xeff64be1 mtd_table_mutex +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x13e48577 add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x1dfbda04 deregister_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x9b6f6fa8 register_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xc29da60e del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x74577927 nand_wait_ready +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x7811a42d nand_release +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xa3fe39be nand_scan_ident +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xa5828772 nand_scan +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xe1deae73 nand_scan_tail +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x37b0aae5 onenand_release +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x862512ea onenand_scan +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x00d9def6 ubi_get_volume_info +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x1a4a34e3 ubi_leb_read +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x24c6c65f ubi_leb_unmap +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x42801d20 ubi_sync +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x56fb237d ubi_is_mapped +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x5c3fbf0e ubi_leb_erase +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x5dfd73af ubi_open_volume_nm +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x5ff86b78 ubi_leb_write +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x6fc6b57b ubi_close_volume +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x9113391e ubi_leb_map +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xb1bfd6b3 ubi_open_volume +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbbbb6481 ubi_leb_change +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbc505df4 ubi_get_device_info +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0b537f8b mlx4_CLOSE_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x181a0565 mlx4_free_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1c6fc717 mlx4_mtt_init +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1d446d71 mlx4_qp_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2099e7bc __mlx4_cmd +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x23e9bb54 mlx4_fmr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2a45b47f mlx4_srq_arm +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2be82087 mlx4_srq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x382df159 mlx4_buf_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3ff35ec7 mlx4_srq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4b608888 mlx4_map_phys_fmr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4f374ab5 mlx4_srq_query +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x51905ba0 mlx4_SYNC_TPT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x51cad764 mlx4_fmr_unmap +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x53b279de mlx4_buf_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5539058a mlx4_alloc_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5a35efa4 mlx4_pd_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x629799b1 mlx4_mr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x64a55b21 mlx4_cq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x65675603 mlx4_fmr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x68817f39 mlx4_qp_query +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x688e38e9 mlx4_uar_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6a6fb149 mlx4_alloc_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6b287334 mlx4_cq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x73c823aa mlx4_mtt_addr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x776de6a8 mlx4_free_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7892ca3b mlx4_multicast_detach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x799fd415 mlx4_cq_resize +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x8265350f mlx4_pd_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x82e97ece mlx4_qp_remove +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x8c32de27 mlx4_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb327fbc8 mlx4_db_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb59c6d9b mlx4_buf_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb7663a4e mlx4_register_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbaaaff31 mlx4_mtt_cleanup +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbbc28468 mlx4_fmr_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbfcd1b47 mlx4_uar_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc228bc16 mlx4_qp_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc94cf72b mlx4_db_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xd0709200 mlx4_INIT_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdb8ebd86 mlx4_mr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdc7295b8 mlx4_cq_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xde3317b1 mlx4_qp_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe30641f3 mlx4_multicast_attach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xea6077c6 mlx4_qp_to_ready +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xed747120 mlx4_unregister_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf0bb0ffb mlx4_mr_alloc +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0x10619d5f usbnet_generic_cdc_bind +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0xa3323d54 usbnet_cdc_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x324a2444 rndis_status +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x3867554e rndis_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x64497bed generic_rndis_bind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x82657718 rndis_rx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x8cd5edc4 rndis_tx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xfcadc84e rndis_command +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x0603a904 usbnet_suspend +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x263e0ade usbnet_get_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x310249f1 usbnet_get_drvinfo +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x4f683447 usbnet_set_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x5393b378 usbnet_get_settings +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x55e358e0 usbnet_disconnect +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x61375469 usbnet_unlink_rx_urbs +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x6ca51229 usbnet_nway_reset +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x73abac0b usbnet_get_link +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x9938fdd6 usbnet_probe +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x9ae262a6 usbnet_get_endpoints +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x9dd79457 usbnet_skb_return +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xa2c803fa usbnet_resume +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xc19ffd9b usbnet_set_settings +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xe7efe826 usbnet_defer_kevent +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x0350ec69 __lbs_cmd +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x0a8048fd lbs_remove_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x19195f70 lbs_host_sleep_cfg +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x2def2262 lbs_start_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x42254e0f lbs_stop_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x4a203d94 lbs_send_tx_feedback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x69f79d72 lbs_notify_command_response +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x71ce25c8 lbs_add_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x844a0eba lbs_cmd_copyback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x9878f7a1 lbs_host_to_card_done +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x9d3b0691 lbs_queue_event +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xcb34bcc6 lbs_process_rxed_packet +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xd33e3467 lbs_cmd_802_11_rate_adapt_rateset +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xda0bc68d lbs_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xe8593545 lbs_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xf64277de lbs_debug +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x540d9f8b p54_init_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x753f4c71 p54_free_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x80a99f67 p54_parse_firmware +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xaa748adb p54_fill_eeprom_readback +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xb12b29ea p54_parse_eeprom +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xe032c996 p54_rx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x065977ef rt2x00mac_remove_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x0bede017 rt2x00mac_get_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1ca071e6 rt2x00lib_beacondone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1e9d8a88 rt2x00mac_get_tx_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x2d3d5154 rt2x00mac_add_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x446ee68e rt2x00mac_conf_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x4e189bb7 rt2x00mac_configure_filter +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5333a6ed rt2x00mac_config_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5bdf8921 rt2x00lib_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x6fc69c20 rt2x00lib_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x80b05909 rt2x00lib_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x882ed30a rt2x00queue_get_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x8ce6d87e rt2x00mac_config +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x93eab81b rt2x00mac_bss_info_changed +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x97637a96 rt2x00mac_start +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xa290d166 rt2x00lib_txdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xb3e16082 rt2x00lib_probe_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xc932f203 rt2x00queue_map_txskb +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xd3fb503d rt2x00lib_remove_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xe1e0a93b rt2x00queue_get_entry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xeb138258 rt2x00mac_stop +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xf4341f1c rt2x00mac_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x8b4c77f7 rt2x00pci_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x94705b97 rt2x00pci_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xaff2ecf0 rt2x00pci_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xb7e7c387 rt2x00pci_remove +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xc261bd0e rt2x00pci_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xcccebec7 rt2x00pci_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xcead6bbd rt2x00pci_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xf22e75dc rt2x00pci_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x19442568 rt2x00usb_init_txentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x292ee901 rt2x00usb_vendor_req_buff_lock +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x3a2db448 rt2x00usb_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x6851b543 rt2x00usb_init_rxentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x6e58639a rt2x00usb_kick_tx_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x6f5aa012 rt2x00usb_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x77a7363d rt2x00usb_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x839667c1 rt2x00usb_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x9d593c95 rt2x00usb_vendor_request +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xa82a0e75 rt2x00usb_vendor_request_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xbbedc3b6 rt2x00usb_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xc61ac19d rt2x00usb_disconnect +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xcfde11d8 rt2x00usb_vendor_request_large_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xdfece2ba rt2x00usb_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xecdc9b7e rt2x00usb_disable_radio +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0x6c438f6d acpiphp_unregister_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0x93adf1ab acpiphp_register_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x1ad3b491 acpi_root_bridge +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x32140aea cpci_hp_unregister_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x379e7f4b cpci_hp_unregister_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x6a8441be cpci_hp_start +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x8cc0e47b pci_hp_change_slot_info +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x8f6ee199 cpci_hp_register_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x91967b92 pci_hp_deregister +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x94ef4d05 cpci_hp_stop +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xb1a5a811 cpci_hp_register_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xc74ae2c8 acpi_get_hp_params_from_firmware +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xe36a6d0c pci_hp_register +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x593a36c2 scsi_dh_handler_exist +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x59554196 scsi_register_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x6a938091 scsi_unregister_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x84219f11 scsi_dh_attach +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xa62c1095 scsi_dh_detach +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xe30102fb scsi_dh_activate +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0233f349 iscsi_pool_init +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0427498b iscsi_conn_start +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x06acd281 iscsi_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0d8ff697 iscsi_conn_send_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0f89362c iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x1995dbf7 iscsi_session_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x232912a5 iscsi_requeue_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x26478b75 iscsi_host_remove +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x278d9903 iscsi_conn_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x28a46dbf iscsi_session_setup +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x2c0eb8eb iscsi_eh_host_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x347cc80a iscsi_suspend_tx +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3a9f152d iscsi_conn_setup +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3d7d3eb4 __iscsi_get_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3ea127e2 iscsi_update_cmdsn +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x41ba1d14 iscsi_pool_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x47e85621 iscsi_itt_to_ctask +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x4b2d2c02 iscsi_prep_unsolicit_data_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x51cf6c47 iscsi_conn_stop +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x5b4ee575 iscsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x6137fda6 iscsi_host_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x8c91a9d9 iscsi_host_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x9591b7b1 iscsi_host_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x9ecd0951 __iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa2751fff iscsi_put_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa91072d9 iscsi_eh_device_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb47376a4 iscsi_host_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc00693c2 iscsi_host_add +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc3c7e132 iscsi_session_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc5048a26 iscsi_conn_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd1fb33a5 iscsi_session_recovery_timedout +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd60bebce iscsi_conn_bind +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe8acee35 iscsi_verify_itt +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe96609f6 iscsi_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xee248e40 iscsi_eh_abort +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf401b9e1 iscsi_conn_failure +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x19172af1 sas_domain_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x1fbe7eb1 sas_phy_reset +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x24d541f4 sas_eh_device_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x270bfa25 sas_target_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x328c3744 sas_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x340f68b4 sas_eh_bus_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x383e1d91 sas_slave_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x42738b6b sas_unregister_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x5a014a6b sas_register_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x64f3f1bd sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x6a9a0fe2 sas_domain_attach_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x70190dfd sas_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x7d1bb3c3 sas_ioctl +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x879cf949 sas_bios_param +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x87c6a48f sas_slave_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xa0bcb683 sas_find_local_phy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xb0be0358 sas_phy_enable +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xbfe2de6b __sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xc6c68dea sas_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xca8e290f sas_slave_configure +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xcf5b0300 sas_request_addr +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xdefc0368 sas_ssp_task_response +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xf0e63336 sas_change_queue_type +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x0382f64b srp_iu_put +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x607f406d srp_target_free +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x6946c06e srp_iu_get +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xb16ab5bb srp_cmd_queue +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xdd0846b8 srp_transfer_data +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xffa183fc srp_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x1d3dc709 scsi_flush_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x213fc9f1 scsi_execute_async +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x26c90ea4 scsi_eh_get_sense +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x3435a25e scsi_internal_device_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x35d8c94a sdev_evt_alloc +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x3830d533 scsi_bus_type +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x3ae46ef9 scsi_mode_select +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x5f48d4ee scsi_nl_sock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x60926379 scsi_queue_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x671f0a37 sdev_evt_send_simple +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7ade9df0 scsi_eh_ready_devs +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7e275ea8 scsi_complete_async_scans +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xaac5219a scsi_internal_device_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd4c700d5 scsi_schedule_eh +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd606abaa scsi_target_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd61a829d scsi_target_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xe8a6393e sdev_evt_send +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xeff2d09a __scsi_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x002cc17f scsi_tgt_it_nexus_create +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x0ef6dee3 scsi_tgt_tsk_mgmt_request +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x17e15093 scsi_tgt_free_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x4bedafd8 scsi_host_put_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x50759b7c scsi_host_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x95408aa6 scsi_tgt_alloc_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xbba40bf9 scsi_tgt_it_nexus_destroy +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xe865d562 scsi_tgt_queue_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xefd7681b scsi_tgt_cmd_to_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x329fe04d iscsi_create_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x3d13bbb9 iscsi_unblock_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x41b0d952 iscsi_create_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x45be2779 iscsi_block_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x565d4c0b iscsi_destroy_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x5963f157 iscsi_scan_finished +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x68ba7b65 iscsi_add_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x6bd185a5 iscsi_register_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xa0838c39 iscsi_recv_pdu +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xb2871103 iscsi_lookup_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xba1c55e0 iscsi_session_chkready +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xbac1b6b7 iscsi_destroy_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xbd693705 iscsi_host_for_each_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xc090ca73 iscsi_alloc_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xdad69694 iscsi_remove_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xdfbc55d2 iscsi_conn_error +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe043f42f iscsi_session_event +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe0dbe958 iscsi_destroy_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe81f0c65 iscsi_free_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xee0ee01e iscsi_create_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xfca4c51e iscsi_unregister_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0x0ef06974 spi_populate_ppr_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xa0c71dac spi_populate_sync_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xcffa2aff spi_populate_width_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x43429377 srp_attach_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x9a415c9a srp_remove_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xbd9ebb7a srp_rport_add +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xdac096c1 srp_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xf9edbf7f srp_rport_del +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x0316cff1 spi_bitbang_start +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x06639431 spi_bitbang_transfer +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x21bf81c2 spi_bitbang_setup +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x556ca9a1 spi_bitbang_cleanup +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xd9e8339d spi_bitbang_setup_transfer +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xdec48b01 spi_bitbang_stop +EXPORT_SYMBOL_GPL drivers/uio/uio 0x02cda0a5 uio_unregister_device +EXPORT_SYMBOL_GPL drivers/uio/uio 0x24a139c8 uio_event_notify +EXPORT_SYMBOL_GPL drivers/uio/uio 0x807777f1 __uio_register_device +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0x8909ee33 usbatm_usb_probe +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0xa0d92993 usbatm_usb_disconnect +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x04c79745 usb_get_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0d281a4b usb_ep0_reinit +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x18706a09 usb_register_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x18ada175 usb_driver_release_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x19a304ba usb_disabled +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1d369e1e usb_get_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x241cbe42 usb_buffer_unmap_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x249d0af1 usb_unlink_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x252e5cd7 usb_unanchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x294aaa77 usb_hcd_pci_suspend +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x2b9b7438 usb_reset_device +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3470443c usb_submit_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x35738fc5 usb_interrupt_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x391592eb usb_hcd_pci_probe +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x396551eb usb_hcd_pci_remove +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3a5c7b03 usb_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3b0535a0 usb_get_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3be89d3c usb_register_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x41654fb3 usb_put_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x428bfa84 usb_register_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x47bd5692 usb_anchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x491efdff usb_hcd_pci_resume +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4c8eeab8 usb_put_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5202224b usb_match_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5634a0c4 usb_hcd_pci_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x56e649bf usb_get_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5792a642 usb_kill_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x61d5a263 usb_reset_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x629ea18f usb_clear_halt +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x63d61914 usb_get_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x646ee7b4 usb_deregister +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x68618b3c usb_get_current_frame_number +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6a40c9d3 usb_hcd_unlink_urb_from_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6c6066cf usb_hcd_platform_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6dce94bf usb_bus_list_lock +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x75535712 usb_alloc_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7ddeaedf usb_bulk_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7e64181d usb_calc_bus_time +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x828582ad usb_init_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8566b389 usb_driver_set_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x87efb515 usb_get_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x88432bf3 usb_register_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8d4d9705 usb_find_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8ebc1348 usb_hub_tt_clear_buffer +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x980191b6 usb_sg_wait +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9924c496 __usb_get_extra_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9ef7037d usb_buffer_free +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa12d019d usb_control_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa9deb580 usb_altnum_to_altsetting +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xaa049b1a usb_free_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xaaf844e0 usb_add_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xac113b09 usb_autopm_put_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xace5c0fc usb_bus_list +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xae5514c0 usb_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xafb40978 usb_hcd_poll_rh_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb5c87f1f usb_driver_claim_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb848c501 usb_string +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb98a8623 usb_deregister_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbc3a242f usb_wait_anchor_empty_timeout +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbcd5e088 usb_deregister_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbf787af1 usb_hc_died +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc060b093 usb_autopm_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc0f1f4c7 usb_put_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc139f1bb usb_sg_init +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc17515d7 usb_hcds_loaded +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc750657b usb_sg_cancel +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcab4c7c9 usb_store_new_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcd837cf0 usb_mon_register +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcdacb960 usb_hcd_resume_root_hub +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd3289e3e usb_hcd_link_urb_to_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd4faf8db usb_lock_device_for_reset +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xdb49a388 usb_buffer_map_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe276a327 usb_remove_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe3875d2a usb_kill_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe6ebb2d4 usb_buffer_alloc +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9587909 usb_unregister_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xeaa3659d usb_hcd_giveback_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xed0690a5 ehci_cf_port_reset_rwsem +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf2eeaa35 usb_autopm_get_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf474a0b2 usb_root_hub_lost_power +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfa7336ae usb_ifnum_to_if +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfc2f8f1b usb_hcd_check_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfd6c579b usb_match_one_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfea68d87 usb_create_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfed11ed1 usb_mon_deregister +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x19d547ee usb_ftdi_elan_edset_setup +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x91e63787 usb_ftdi_elan_read_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xa05c3763 usb_ftdi_elan_edset_output +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xb348351d usb_ftdi_elan_edset_input +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xbdb133fd usb_ftdi_elan_edset_flush +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xd663f5e4 usb_ftdi_elan_edset_empty +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xe1ad07c7 usb_ftdi_elan_edset_single +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xe49488ee usb_ftdi_elan_write_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xf69ca1a0 ftdi_elan_gone_away +EXPORT_SYMBOL_GPL drivers/usb/misc/phidget 0x87f7008c phidget_class +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x309d1ce3 usb_serial_port_softint +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x358c5e55 usb_serial_deregister +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x761931b5 ezusb_writememory +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x83f4c770 ezusb_set_reset +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x8ca43184 usb_serial_generic_write_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x8ffb2305 usb_serial_register +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xa341c82b usb_serial_disconnect +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xab44f8d9 usb_serial_generic_read_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xce55fb5f usb_serial_probe +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xe4a9ba00 usb_serial_generic_open +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x3edad223 usb_usual_clear_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x89d4dbaf usb_usual_check_type +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xcd9991a9 usb_usual_set_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xde134c69 storage_usb_ids +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x200ca72a ili9320_suspend +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x29330374 ili9320_write_regs +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x2f908eae ili9320_shutdown +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x62246e1a ili9320_remove +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x87d3dbca ili9320_probe_spi +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x9084d36f ili9320_write +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xd8a9f8d1 ili9320_resume +EXPORT_SYMBOL_GPL drivers/video/fb_ddc 0xf114a454 fb_ddc_read +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x2221a647 fb_sys_write +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x5d56af5c fb_sys_read +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0xae1d4bd1 sis_free_new +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0xdaca72c3 sis_malloc_new +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x016e6c20 vmlfb_unregister_subsys +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x90c018c6 vmlfb_register_subsys +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x0f191ab7 register_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x16f5900f virtio_check_driver_offered_feature +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x7aaa1838 unregister_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xa9973f03 register_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xbab696b5 unregister_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x03c4687d vring_interrupt +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x11a51fb2 vring_transport_features +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0xaf7c0454 vring_del_virtqueue +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0xc0e0aa23 vring_new_virtqueue +EXPORT_SYMBOL_GPL drivers/w1/wire 0x225e421c w1_write_block +EXPORT_SYMBOL_GPL drivers/w1/wire 0x6af5326e w1_reset_select_slave +EXPORT_SYMBOL_GPL drivers/w1/wire 0x7c2f2afb w1_calc_crc8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0x82b56f84 w1_write_8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0xcf6a6b2d w1_reset_bus +EXPORT_SYMBOL_GPL drivers/w1/wire 0xda0c6759 w1_read_block +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x6e5fdc6e dlm_posix_get +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x9321df95 dlm_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x9a2591e4 dlm_posix_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xc3ecfbd6 dlm_posix_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xcf9f3328 dlm_release_lockspace +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdc583c08 dlm_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdf3c14de dlm_new_lockspace +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0xf8c6e865 exportfs_encode_fh +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0xffc95b42 exportfs_decode_fh +EXPORT_SYMBOL_GPL fs/fat/fat 0x12db78c9 fat_detach +EXPORT_SYMBOL_GPL fs/fat/fat 0x1fdd8d21 fat_search_long +EXPORT_SYMBOL_GPL fs/fat/fat 0x26807f8e fat_dir_empty +EXPORT_SYMBOL_GPL fs/fat/fat 0x2b077c82 fat_fs_panic +EXPORT_SYMBOL_GPL fs/fat/fat 0x32f558f4 fat_scan +EXPORT_SYMBOL_GPL fs/fat/fat 0x575d7c72 fat_alloc_new_dir +EXPORT_SYMBOL_GPL fs/fat/fat 0x72c6fb0b fat_sync_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0x76d5a3ca fat_get_dotdot_entry +EXPORT_SYMBOL_GPL fs/fat/fat 0x84505e1c fat_flush_inodes +EXPORT_SYMBOL_GPL fs/fat/fat 0x8b196d71 fat_fill_super +EXPORT_SYMBOL_GPL fs/fat/fat 0x9c6db1fb fat_attach +EXPORT_SYMBOL_GPL fs/fat/fat 0xb0304d19 fat_build_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0xb68ea16d fat_date_unix2dos +EXPORT_SYMBOL_GPL fs/fat/fat 0xca2879fe fat_setattr +EXPORT_SYMBOL_GPL fs/fat/fat 0xcb38e9ad fat_add_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0xdc4d4558 fat_remove_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0xeb556ccf fat_free_clusters +EXPORT_SYMBOL_GPL fs/fat/fat 0xec1c5ec4 fat_getattr +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0x3c17e93f gfs2_register_lockproto +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0xa1c3a001 gfs2_unregister_lockproto +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x1a618932 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x38028873 nlmclnt_proc +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x9908eb0b nlmclnt_init +EXPORT_SYMBOL_GPL fs/lockd/lockd 0xb0441369 nlmclnt_done +EXPORT_SYMBOL_GPL fs/lockd/lockd 0xb74bbd5c nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x0cfc7bbe o2hb_register_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1ab8c993 o2nm_node_get +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1b89c6ee o2hb_fill_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1c78e047 o2nm_get_node_by_num +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1d747ce3 o2hb_check_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x36418553 o2net_send_message +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x41f89018 o2hb_setup_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4900035b o2hb_stop_all_regions +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x521e0726 o2net_send_message_vec +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x81a17396 mlog_and_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa82a8645 o2nm_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa87bc9e7 o2nm_configured_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xae808bac o2net_register_handler +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xb7c9736b o2hb_unregister_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xb7e600fa o2nm_node_put +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xbaeb4700 o2hb_check_node_heartbeating_from_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xd60f2c6c o2hb_check_local_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf1a5611d o2net_unregister_handler_list +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf56c2017 mlog_not_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xfdb7f09d o2nm_get_node_by_ip +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x63c1fb00 dlm_register_domain +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x788bedf6 dlm_unregister_domain +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x7a1211f8 dlm_setup_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xbe0ba09a dlmlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xc998900c dlm_register_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xcbc0b1f5 dlm_print_one_lock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd7ba575e dlm_errmsg +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd8fa57a6 dlm_unregister_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xf02781f1 dlmunlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xfb86b96f dlm_errname +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0562c415 ocfs2_cluster_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0a831369 ocfs2_stack_glue_unregister +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0e27f909 ocfs2_dlm_lock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x21db5b88 ocfs2_cluster_disconnect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4a1f6fe9 ocfs2_cluster_connect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4d3af7fa ocfs2_cluster_hangup +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x81c85a68 ocfs2_dlm_lock_status +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x91fab465 ocfs2_dlm_lvb +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x9456503c ocfs2_stack_glue_register +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x963932a3 ocfs2_stack_glue_set_locking_protocol +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xa7d5c1c0 ocfs2_dlm_unlock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xd066711e ocfs2_dlm_dump_lksb +EXPORT_SYMBOL_GPL lib/lzo/lzo_compress 0x2e1d43cf lzo1x_1_compress +EXPORT_SYMBOL_GPL lib/lzo/lzo_decompress 0x2a1538ca lzo1x_decompress_safe +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x300d7e57 free_rs +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x6fbb3bd9 init_rs_non_canonical +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xabda1e2e decode_rs16 +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xb050f329 init_rs +EXPORT_SYMBOL_GPL net/802/garp 0x5390e9aa garp_init_applicant +EXPORT_SYMBOL_GPL net/802/garp 0xacdaa5be garp_unregister_application +EXPORT_SYMBOL_GPL net/802/garp 0xc459ed0b garp_request_leave +EXPORT_SYMBOL_GPL net/802/garp 0xc50c64d5 garp_register_application +EXPORT_SYMBOL_GPL net/802/garp 0xd851a0c1 garp_uninit_applicant +EXPORT_SYMBOL_GPL net/802/garp 0xed262279 garp_request_join +EXPORT_SYMBOL_GPL net/802/stp 0x8367ce99 stp_proto_register +EXPORT_SYMBOL_GPL net/802/stp 0xb0987f16 stp_proto_unregister +EXPORT_SYMBOL_GPL net/ax25/ax25 0xac93ae05 ax25_bcast +EXPORT_SYMBOL_GPL net/ax25/ax25 0xaeb7451e ax25_defaddr +EXPORT_SYMBOL_GPL net/ax25/ax25 0xc4345232 ax25_register_pid +EXPORT_SYMBOL_GPL net/bluetooth/bluetooth 0x3be999e7 bt_class +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x09c5ed3c tfrc_tx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x0a487ea5 tfrc_calc_x +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x106fe6d3 tfrc_tx_hist_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x50997d99 tfrc_lh_update_i_mean +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x69ec5731 tfrc_tx_hist_add +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x6a083f17 tfrc_rx_hist_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x6c252d29 tfrc_calc_x_reverse_lookup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x8352c487 tfrc_rx_hist_add_packet +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x839a08a3 tfrc_rx_handle_loss +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x902206f0 tfrc_lh_cleanup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x92285650 tfrc_rx_hist_alloc +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xae24ff74 tfrc_rx_hist_duplicate +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xc612a5b6 tfrc_rx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xf5adfac6 tfrc_lh_interval_add +EXPORT_SYMBOL_GPL net/dccp/dccp 0x00d51b1c ccid_unregister +EXPORT_SYMBOL_GPL net/dccp/dccp 0x03e42f30 dccp_setsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x0f76d3db dccp_parse_options +EXPORT_SYMBOL_GPL net/dccp/dccp 0x0fadbd93 dccp_poll +EXPORT_SYMBOL_GPL net/dccp/dccp 0x11aefd84 dccp_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x12575686 dccp_rcv_state_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0x1d99d49a dccp_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0x2f4381af ccid_hc_rx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3b2bd61e dccp_feat_change_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3b3c0b1b dccp_feat_clean +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3fbd3a43 dccp_ctl_make_reset +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4161105e dccp_sync_mss +EXPORT_SYMBOL_GPL net/dccp/dccp 0x440f04c7 ccid_register +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4e79c81c dccp_create_openreq_child +EXPORT_SYMBOL_GPL net/dccp/dccp 0x54329e84 dccp_feat_clone +EXPORT_SYMBOL_GPL net/dccp/dccp 0x56ea266a dccp_state_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x5d5e3ee7 dccp_feat_confirm_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0x5f084755 dccp_death_row +EXPORT_SYMBOL_GPL net/dccp/dccp 0x674cb8ee dccp_shutdown +EXPORT_SYMBOL_GPL net/dccp/dccp 0x753be288 dccp_recvmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0x7d683c5d dccp_reqsk_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0x80c96bff compat_dccp_setsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x82c53ec9 dccp_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0x83da9cb1 dccp_getsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x86be7924 dccp_packet_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8a838f1c ccid_hc_rx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b7d8caf dccp_statistics +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8e454528 dccp_hashinfo +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9d6a3846 dccp_orphan_count +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9f60cdb4 dccp_insert_option_elapsed_time +EXPORT_SYMBOL_GPL net/dccp/dccp 0xa04710f0 dccp_close +EXPORT_SYMBOL_GPL net/dccp/dccp 0xab6cc89b dccp_set_state +EXPORT_SYMBOL_GPL net/dccp/dccp 0xab901309 dccp_make_response +EXPORT_SYMBOL_GPL net/dccp/dccp 0xb170f1c7 dccp_child_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0xb4c6a335 dccp_check_req +EXPORT_SYMBOL_GPL net/dccp/dccp 0xb74319bc dccp_destroy_sock +EXPORT_SYMBOL_GPL net/dccp/dccp 0xba716f47 ccid_hc_tx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbc2141a5 dccp_insert_option_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe095194 compat_dccp_getsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe4cf010 dccp_feat_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbf6b58ba dccp_feat_change +EXPORT_SYMBOL_GPL net/dccp/dccp 0xca7f11ff inet_dccp_listen +EXPORT_SYMBOL_GPL net/dccp/dccp 0xcd4f3d04 dccp_rcv_established +EXPORT_SYMBOL_GPL net/dccp/dccp 0xd8f0422e dccp_insert_option +EXPORT_SYMBOL_GPL net/dccp/dccp 0xdc4d1fb7 dccp_reqsk_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0xde10789c dccp_sendmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0xe7ed85f8 ccid_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0xecf24a7c dccp_ioctl +EXPORT_SYMBOL_GPL net/dccp/dccp 0xee176740 dccp_send_sync +EXPORT_SYMBOL_GPL net/dccp/dccp 0xef0e188d ccid_hc_tx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf15b541a dccp_connect +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf271c7ea dccp_done +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf745b069 dccp_disconnect +EXPORT_SYMBOL_GPL net/dccp/dccp 0xfd53d694 dccp_init_sock +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x1db2e318 dccp_v4_do_rcv +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x337650da dccp_v4_conn_request +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x691faebe dccp_v4_request_recv_sock +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x6ed7a1f5 dccp_v4_connect +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x9433529a dccp_invalid_packet +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xa2eb0e1d dccp_v4_send_check +EXPORT_SYMBOL_GPL net/ieee80211/ieee80211 0x38729481 ieee80211_rx_any +EXPORT_SYMBOL_GPL net/ipv4/ipvs/ip_vs 0xe6476b4a net_vs_ctl_path +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x6d40a921 need_ipv4_conntrack +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0xdbb115c4 nf_nat_seq_adjust_hook +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x07ae60b6 nf_nat_proto_in_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x4046e7ee nf_nat_icmp_reply_translation +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x551a642f nf_nat_proto_find_get +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x59c3072f nf_nat_proto_unique_tuple +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x7ce95842 nf_nat_proto_range_to_nlattr +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x80c9e3b2 nf_nat_packet +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x94a08134 nf_nat_proto_nlattr_to_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xdad709e0 nf_nat_proto_put +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat_proto_gre 0x636b12c8 nf_nat_need_gre +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x1ab3ff31 tcp_vegas_get_info +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x20175b96 tcp_vegas_pkts_acked +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x3a92e57d tcp_vegas_state +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x5ab027a0 tcp_vegas_init +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xd82d99d0 tcp_vegas_cwnd_event +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x08a3e5d1 net_ipv6_ctl_path +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x0cac312c ip6_dst_blackhole +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x2fb257f7 inet6_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3b0e3627 ip6_sk_dst_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x47d8520b ip6_dst_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x5851c92a inet6_destroy_sock +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x5d53a85f inet6_csk_search_req +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x7bcd9f81 inet6_csk_addr2sockaddr +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x7c544e2b inet6_csk_xmit +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xabb17bfe ipv6_find_tlv +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xaf8b8bb5 ipv6_dup_options +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xaf8de9d0 fl6_sock_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xb7a882b5 inet6_csk_bind_conflict +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xcebd956b inet6_sk_rebuild_header +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xd5df0d23 ip6_local_out +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xe100980b ipv6_opt_accepted +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x7d306376 ieee80211_iterate_active_interfaces +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0xa13cc5ce ieee80211_iterate_active_interfaces_atomic +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x02b360a1 __nf_ct_kill_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x041013fd nf_conntrack_lock +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x04123954 __nf_conntrack_confirm +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x045072cd nf_ct_port_nla_policy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x06cfbe0a nf_ct_l4proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0e091ecc nf_ct_l3proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0ea4f6dc nf_ct_iterate_cleanup +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1283d711 nf_ct_expect_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x15c10b0b nf_conntrack_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1619842c nf_conntrack_l4proto_udp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x19ff5837 nf_ct_expect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1be68013 nf_ct_port_tuple_to_nlattr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x242fe6ae nf_conntrack_l4proto_udp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x248d7f93 nf_conntrack_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x25e649f2 nf_ct_log_invalid +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2b9580cb nf_conntrack_flush +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2debb004 nf_ct_get_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x34d23e2e __nf_conntrack_helper_find_byname +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3609de81 nf_conntrack_count +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x374308f5 nf_ct_get_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38630158 nf_conntrack_tuple_taken +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38c9440b nf_ct_extend_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3f5b1415 nf_ct_port_nlattr_to_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x40387ccf __nf_ct_event_cache_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x40dd9bb5 print_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x45e3c6ac nf_ct_expect_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x474327c1 __nf_ct_expect_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4d17d977 nf_ct_unexpect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x501d6b4b nf_conntrack_l4proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x580acbf5 nf_conntrack_l4proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5e964972 nf_ct_l3protos +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x67219ea3 nf_ct_expect_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6cd91ee0 per_cpu__nf_conntrack_ecache +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6d12bbae nf_conntrack_l3proto_generic +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6e224a7a need_conntrack +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x700d1765 seq_print_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x72836f4a nf_conntrack_free +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x77aadb54 nf_conntrack_alter_reply +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x78f9b710 nf_ct_l3proto_try_module_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x79c9e83c nf_ct_helper_ext_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x79ca2e53 nf_ct_expect_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x809d9b38 __nf_ct_refresh_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x82217ca6 nf_conntrack_l3proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x882ba59d nf_ct_l4proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8f3646d7 nf_ct_expect_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8ffe7e89 nf_conntrack_htable_size +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x90ff6c9f nf_ct_invert_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x93241c9c nf_ct_invert_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x977f46d0 nf_conntrack_helper_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9c2f9624 nf_ct_unlink_expect +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9f326ae9 __nf_ct_l4proto_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa6f62ec0 nf_conntrack_set_hashsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xace98352 nf_conntrack_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaf57e66f nf_ct_extend_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb13d7e38 nf_ct_l3proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb602c57e nf_ct_l3proto_module_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb76accc2 __nf_conntrack_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb89ef25e nf_conntrack_in +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb9e30797 nf_ct_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbb4b7871 nf_conntrack_tcp_update +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbc887e16 nf_ct_expect_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbd7daec1 nf_ct_expect_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbe3f2939 nf_conntrack_checksum +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc044befe nf_ct_free_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc18ac88d nf_ct_expect_hsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc35a7a3e nf_conntrack_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc7b64d79 nf_conntrack_hash_insert +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcbf7fd2a nf_conntrack_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcdaaa7ae __nf_ct_helper_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd50a96a2 nf_ct_alloc_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd7c683c4 nf_conntrack_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd9efb053 nf_ct_deliver_cached_events +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xdbb856ac nf_conntrack_l4proto_tcp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xdd70187f nf_conntrack_helper_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe98e342e nf_conntrack_l4proto_tcp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xec8beba6 nf_ct_expect_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf67f4947 nf_conntrack_l3proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf9ae81a1 nf_conntrack_max +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfa169dac nf_conntrack_untracked +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfb839673 nf_ct_remove_expectations +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_amanda 0x6025a5a7 nf_nat_amanda_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_ftp 0xf62878b8 nf_nat_ftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x12a1139f nat_q931_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x264c0cf3 get_h225_addr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x3ea43ec4 set_h245_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x642009c3 set_h225_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x6e3ee0f2 set_sig_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x7be3b6fd set_ras_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x9011501f nat_callforwarding_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xb96c2ad4 nat_t120_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xbcdfad0b nat_h245_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xcf417210 nat_rtp_rtcp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_irc 0x814ae120 nf_nat_irc_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x24d99602 nf_nat_pptp_hook_exp_gre +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x4ebfbaad nf_nat_pptp_hook_expectfn +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x5e95cfd0 nf_nat_pptp_hook_outbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xdc68232a nf_nat_pptp_hook_inbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x05f8e58c nf_ct_gre_keymap_destroy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x6f59d77c nf_ct_gre_keymap_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x13169b79 ct_sip_parse_request +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x23c7d1f5 nf_nat_sdp_session_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x3c2058a6 ct_sip_parse_numerical_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x42edf11a nf_nat_sdp_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x48d65cde nf_nat_sip_expect_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5333cb69 ct_sip_parse_header_uri +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5343611e ct_sip_get_sdp_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x56ad8f6e ct_sip_parse_address_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x669b6845 nf_nat_sip_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x66d81dae nf_nat_sdp_media_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x681bd415 nf_nat_sdp_port_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf8b610ea ct_sip_get_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_tftp 0x7dda2926 nf_nat_tftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x00ec2d6b nfnetlink_unicast +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x69e5b174 nfnetlink_send +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xc1b8d12c nfnetlink_subsys_register +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xcd07a4ae nfnetlink_subsys_unregister +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xeca95329 nfnetlink_has_listeners +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x16901a0e xt_compat_match_offset +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x21e221d6 xt_proto_fini +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x2baf1084 xt_compat_target_from_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x2f32d4da xt_compat_lock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x3ad8a68d xt_request_find_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x50d7f1aa xt_compat_calc_jump +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x5643ed60 xt_proto_init +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x6239c30f xt_compat_add_offset +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x63f05053 xt_find_revision +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x65c90716 xt_register_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x69033eb4 xt_compat_match_to_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x696109ee xt_compat_flush_offsets +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7bbb50ff xt_table_unlock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7e38ad84 xt_check_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7eac0af4 xt_compat_target_offset +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x8f6ae92a xt_compat_target_to_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xa4bdc3db xt_find_table_lock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xaa30704f xt_compat_match_from_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xaf93611a xt_check_match +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xdbaf6e11 xt_unregister_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xe53911a2 xt_compat_unlock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xe960c06e xt_replace_table +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xc177bee0 xt_rateest_put +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xdb8418cc xt_rateest_lookup +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x83b2e956 register_rfkill_notifier +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x86c722f8 rfkill_epo +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0xa6f4320d unregister_rfkill_notifier +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0x27a3a70d rxrpc_register_security +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0x5a021c03 rxrpc_unregister_security +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x03fe44b3 rpc_clone_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1058549b rpc_call_sync +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x11ac9869 xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x169c6486 rpc_delay +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1f5f6a05 xprt_disconnect_done +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x205032c2 svc_xprt_enqueue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x24cd585a xprt_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x263fe740 xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x26949256 rpc_force_rebind +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x26ce108c xprt_release_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x27ec7fa9 rpc_proc_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2a57ffbe rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2aa17774 rpc_free_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2b0dfc31 rpc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2ba78ca4 rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2fe3b08c rpc_run_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x31a89d59 rpc_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x325a923d xprt_release_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x35240e07 svc_print_addr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3a945a3b xprt_register_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3eed5dee rpc_call_start +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4a1131e8 rpcauth_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4a5a0457 svc_xprt_put +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4bd5692f xprt_unregister_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4cc6cbc2 rpc_exit_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x51655ee5 xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x53445f68 nlm_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x550547a3 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bd26000 rpc_proc_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5dc49f3d rpc_peeraddr2str +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x664e1a97 svc_close_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x686fb7d0 rpc_print_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x69af4b4e rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6a8827b7 xprt_write_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c34a330 rpc_restart_call +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c5304c5 rpcb_getport_sync +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x731aff9f rpc_malloc +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7444f38c rpc_shutdown_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x776cad69 svc_reg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7de53067 rpc_init_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x860a671d rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x86ca4bb0 svc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8eeda8c0 rpc_lookup_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x916c72c1 rpc_put_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9786f2bd rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9c1283f7 rpcauth_init_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9f672042 put_rpccred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa02d5818 svc_xprt_names +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa6797a3e rpc_wake_up_next +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaa6a0927 rpc_peeraddr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xabf8191e svc_xprt_init +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xace7fbc6 rpcauth_init_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf5bf6ef nfs_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb0697b60 rpc_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb0f80ad9 rpc_bind_new_program +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb387b246 rpc_wake_up_status +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb7a91ea0 rpc_sleep_on +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbab68e43 rpc_alloc_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbb529870 svc_addsock +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbcedeaeb rpcb_getport_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf00ee4a rpcauth_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf9d1b96 nfsd_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc12435e3 rpc_calc_rto +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc36ca95f svc_unreg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc38e4545 rpc_call_null +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc828c2ec xprt_release_rqst_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcc05fe03 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xceade5b3 svc_xprt_received +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd46c9f8f svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd5185c36 rpc_setbufsize +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd82c728e rpc_init_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd9f115c6 xprt_reserve_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdab91036 rpc_killall_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdeb2a2ab xdr_skb_read_bits +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdf3ab43e xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe79dbbd3 xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xea19d536 csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedd1ba52 rpc_wake_up +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xee56922d svc_create_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xeeacab69 rpc_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf0efaba5 rpcauth_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf28441b5 xprt_adjust_cwnd +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf3522702 xprt_complete_rqst +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf5a0cd0a rpc_call_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf7ea5937 __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf9d1164c rpc_free +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfb8ffb15 svc_find_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfc088b6d xprt_lookup_rqst +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x77a3e570 ipcomp_output +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x8f004b13 ipcomp_init_state +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x9fed1041 ipcomp_destroy +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xce7b93ad ipcomp_input +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0510f4ab snd_soc_dapm_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0587f358 snd_soc_test_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x090c2393 snd_soc_register_card +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0fbe82ad snd_soc_free_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x153e5b05 snd_soc_dapm_stream_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x154e6e57 snd_soc_dapm_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1d1ae7e3 snd_soc_cnew +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x20451b67 snd_soc_dai_set_tristate +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x27069147 snd_soc_dapm_enable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3807b23f snd_soc_put_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3e1a1350 snd_soc_dapm_connect_input +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3f324e2f snd_soc_dapm_new_controls +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x4224382e snd_soc_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x428d7758 dapm_reg_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5249a7c8 snd_soc_get_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x60138880 snd_soc_dapm_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x69d05a8d snd_soc_update_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x717cf8a7 snd_soc_set_runtime_hwparams +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x85b7295d snd_soc_new_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x86107b2b snd_soc_info_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x86d42c93 snd_soc_new_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8ca9319b snd_soc_dapm_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x90a67d96 snd_soc_dapm_sync +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x94f12da4 snd_soc_dapm_disable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa27d8ecb snd_soc_dai_set_fmt +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa306bd9b snd_soc_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa3ffebc2 snd_soc_get_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb8c2f6a6 snd_soc_dapm_add_routes +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbc82211d snd_soc_info_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc3cb51dd snd_soc_info_volsw_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc605c1b0 snd_soc_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc912c965 snd_soc_dai_set_sysclk +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc9b1fe35 snd_soc_put_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xcc68a02f snd_soc_dai_set_clkdiv +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd260363f snd_soc_free_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd7adffd5 snd_soc_info_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdaafff6d snd_soc_dapm_free +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdbc367e2 snd_soc_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe1d48e74 snd_soc_dai_set_tdm_slot +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe4292769 snd_soc_dapm_new_widgets +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe4be33fa snd_soc_info_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe9f49e1d snd_soc_dapm_new_control +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf0ad6870 snd_soc_info_enum_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf2ab703f snd_soc_dai_set_pll +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf8309917 snd_soc_dai_digital_mute +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfe01e555 snd_soc_dapm_get_pin_status +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x0d93d0e1 tlsf_create_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x1584fdb9 tlsf_destroy_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x2c383ca4 tlsf_calloc +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x54064cb9 tlsf_get_used_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x60d233a6 tlsf_malloc +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xbe77d1fe tlsf_get_total_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xe6acc368 tlsf_free +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x02500586 thinkpad_ec_unlock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x0dc7484e thinkpad_ec_try_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x2552d213 thinkpad_ec_lock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x3dbfef12 thinkpad_ec_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x8dbbd831 thinkpad_ec_invalidate +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xa3042743 thinkpad_ec_prefetch_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xfb5aa917 thinkpad_ec_try_lock +EXPORT_SYMBOL_GPL vmlinux 0x001d97c6 crypto_hash_type +EXPORT_SYMBOL_GPL vmlinux 0x00566d8f inotify_get_cookie +EXPORT_SYMBOL_GPL vmlinux 0x006d7cad srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00b8ecf8 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x01848a8e local_apic_timer_c2_ok +EXPORT_SYMBOL_GPL vmlinux 0x01a4ea6d unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x01b2e09f tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x01e1a8de kgdb_breakpoint +EXPORT_SYMBOL_GPL vmlinux 0x028e6f97 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x02a9ac14 user_update +EXPORT_SYMBOL_GPL vmlinux 0x02b029b5 relay_buf_full +EXPORT_SYMBOL_GPL vmlinux 0x02cb1b8a __cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0x02ccea56 lock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x0343bdf1 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x0361b93b xenbus_map_ring_valloc +EXPORT_SYMBOL_GPL vmlinux 0x03fe2cca flush_work +EXPORT_SYMBOL_GPL vmlinux 0x0427901f transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0x0447d159 raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0x04486e88 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x0454860a blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0x04566c7f init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x04c3f2c1 gnttab_empty_grant_references +EXPORT_SYMBOL_GPL vmlinux 0x04e628cd leds_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x04ea8706 __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0x054e550b kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x05e835d3 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0x064db9a5 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x06d222f8 device_resume +EXPORT_SYMBOL_GPL vmlinux 0x074a3aab device_initialize +EXPORT_SYMBOL_GPL vmlinux 0x07a708b2 pci_find_next_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x07b52e38 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x07bc9dae xenbus_grant_ring +EXPORT_SYMBOL_GPL vmlinux 0x07ff4aea xenbus_scanf +EXPORT_SYMBOL_GPL vmlinux 0x0871083f sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x08a3fe89 spi_new_device +EXPORT_SYMBOL_GPL vmlinux 0x091eb9b4 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x0962349a uhci_check_and_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x09b5fba5 user_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x0b42ff5b bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0x0b724197 xfrm_audit_state_icvfail +EXPORT_SYMBOL_GPL vmlinux 0x0bc151e5 klist_init +EXPORT_SYMBOL_GPL vmlinux 0x0c17e274 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x0c4717f7 srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0x0c6fdf20 zap_vma_ptes +EXPORT_SYMBOL_GPL vmlinux 0x0d1cf84e tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0x0d20656a class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0d5ce501 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x0de6697e led_trigger_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0e10d0df fb_deferred_io_open +EXPORT_SYMBOL_GPL vmlinux 0x0e5cdd79 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0x0ec210b8 xen_start_info +EXPORT_SYMBOL_GPL vmlinux 0x0ef84c65 hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x0fe2d570 xenbus_directory +EXPORT_SYMBOL_GPL vmlinux 0x0fed7cc4 queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x10151db2 inotify_remove_watch_locked +EXPORT_SYMBOL_GPL vmlinux 0x1050bc52 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x109294b5 inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0x10b10ab3 pci_find_ext_capability +EXPORT_SYMBOL_GPL vmlinux 0x115b72be find_vpid +EXPORT_SYMBOL_GPL vmlinux 0x1180cd29 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0x11862c34 __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x11fcdf4d device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0x12463b2f crypto_register_instance +EXPORT_SYMBOL_GPL vmlinux 0x124f2056 crypto_get_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x1251d30f call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x12721e94 tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0x12e285ec is_uv_system +EXPORT_SYMBOL_GPL vmlinux 0x12ff7edb tty_find_polling_driver +EXPORT_SYMBOL_GPL vmlinux 0x138b472b __percpu_alloc_mask +EXPORT_SYMBOL_GPL vmlinux 0x13afaf8f inet_diag_unregister +EXPORT_SYMBOL_GPL vmlinux 0x13b2a946 register_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x13d66968 securityfs_remove +EXPORT_SYMBOL_GPL vmlinux 0x145eebd0 device_power_up +EXPORT_SYMBOL_GPL vmlinux 0x146bee29 spi_register_master +EXPORT_SYMBOL_GPL vmlinux 0x149db923 selinux_string_to_sid +EXPORT_SYMBOL_GPL vmlinux 0x14d5425d bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0x14f12eb5 audit_log_untrustedstring +EXPORT_SYMBOL_GPL vmlinux 0x1534ba7a bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1598dc9d unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x1598ef3e devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x15b0606e e820_any_mapped +EXPORT_SYMBOL_GPL vmlinux 0x15cd14db crypto_unregister_template +EXPORT_SYMBOL_GPL vmlinux 0x166b6ad5 spi_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x168f5aac tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x16a5b4c8 key_type_user +EXPORT_SYMBOL_GPL vmlinux 0x16b6e800 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x16f7ca84 xenbus_unmap_ring_vfree +EXPORT_SYMBOL_GPL vmlinux 0x178d5019 page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x1800d735 debugfs_remove_recursive +EXPORT_SYMBOL_GPL vmlinux 0x187551b2 spi_write_then_read +EXPORT_SYMBOL_GPL vmlinux 0x1878f62b edac_err_assert +EXPORT_SYMBOL_GPL vmlinux 0x1895293e crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0x18d53420 kgdb_register_io_module +EXPORT_SYMBOL_GPL vmlinux 0x18f83fab gnttab_grant_foreign_access_ref +EXPORT_SYMBOL_GPL vmlinux 0x19b179d0 fib_rules_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1a10607f unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x1a83d250 elv_register +EXPORT_SYMBOL_GPL vmlinux 0x1a938737 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x1aad289d __xenbus_register_frontend +EXPORT_SYMBOL_GPL vmlinux 0x1acda5b2 atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1b4b86ac fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0x1b9aca3f jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x1cac9211 get_driver +EXPORT_SYMBOL_GPL vmlinux 0x1dd70100 dmi_walk +EXPORT_SYMBOL_GPL vmlinux 0x1ddf95ba sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0x1de5332b xenbus_watch_path +EXPORT_SYMBOL_GPL vmlinux 0x1e053cb0 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0x1e7bbcb3 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x1eaa9c56 crypto_hash_walk_done +EXPORT_SYMBOL_GPL vmlinux 0x1eb9516e round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x1ebae765 spi_sync +EXPORT_SYMBOL_GPL vmlinux 0x1ededf6e cpufreq_cpu_put +EXPORT_SYMBOL_GPL vmlinux 0x1f5c95f5 platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x1f696624 pci_unblock_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x1f8ec1b3 acpi_get_pci_rootbridge_handle +EXPORT_SYMBOL_GPL vmlinux 0x1f9a0fbf hpet_unregister_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x1fcece42 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x2029099d inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0x20577ea2 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x2068f3e5 cpuidle_enable_device +EXPORT_SYMBOL_GPL vmlinux 0x2074c42e bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x20b82470 hpet_register_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x20bc3470 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x21d192f9 input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0x21db7fc8 xenbus_unmap_ring +EXPORT_SYMBOL_GPL vmlinux 0x21f9011b transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x221c727e inotify_init +EXPORT_SYMBOL_GPL vmlinux 0x2240d211 unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x22472bf4 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x2265d0e4 debugfs_create_blob +EXPORT_SYMBOL_GPL vmlinux 0x226f4e93 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0x2296c00d crypto_attr_u32 +EXPORT_SYMBOL_GPL vmlinux 0x22a4c758 class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x22d50fc4 vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0x2305365b register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x23864ce7 cpuset_mem_spread_node +EXPORT_SYMBOL_GPL vmlinux 0x2396620c seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0x23bbb214 devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x24196ba2 init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x2447533c ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0x24c7698a xenbus_write +EXPORT_SYMBOL_GPL vmlinux 0x24eb7e32 leds_list +EXPORT_SYMBOL_GPL vmlinux 0x2502a974 pci_find_next_capability +EXPORT_SYMBOL_GPL vmlinux 0x251e6fd6 input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0x2545c170 unregister_xenbus_watch +EXPORT_SYMBOL_GPL vmlinux 0x257e29cf spi_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x25f141e7 driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x266ad049 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x26a8bd98 input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x26b712d3 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0x26d00d08 hvc_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x2714c98c klist_del +EXPORT_SYMBOL_GPL vmlinux 0x27bd158c unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x27dc68f1 __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0x28088f0f pv_time_ops +EXPORT_SYMBOL_GPL vmlinux 0x2832f007 blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x28b5e778 rtc_read_time +EXPORT_SYMBOL_GPL vmlinux 0x28d664ff __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x28e23139 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x297231ba agp_remove_bridge +EXPORT_SYMBOL_GPL vmlinux 0x2a31b0dc mmput +EXPORT_SYMBOL_GPL vmlinux 0x2a678a13 __suspend_report_result +EXPORT_SYMBOL_GPL vmlinux 0x2a9c0745 crypto_lookup_template +EXPORT_SYMBOL_GPL vmlinux 0x2b24e4a0 uv_blade_info +EXPORT_SYMBOL_GPL vmlinux 0x2b3e8dfb platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0x2b9f8e23 nf_net_ipv4_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x2bc8c51b nf_unregister_afinfo +EXPORT_SYMBOL_GPL vmlinux 0x2c13521d register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x2c16ed76 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x2c203645 crypto_dequeue_request +EXPORT_SYMBOL_GPL vmlinux 0x2c3e556c vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0x2cb3d996 inotify_find_watch +EXPORT_SYMBOL_GPL vmlinux 0x2d088e2b led_trigger_set +EXPORT_SYMBOL_GPL vmlinux 0x2d59c954 edac_handlers +EXPORT_SYMBOL_GPL vmlinux 0x2d9f2ce3 sched_clock_idle_wakeup_event +EXPORT_SYMBOL_GPL vmlinux 0x2db5758a register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x2e6e7aee smp_ops +EXPORT_SYMBOL_GPL vmlinux 0x2e71723a skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0x2e998f83 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x2eafd72f sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x2ec92012 scatterwalk_copychunks +EXPORT_SYMBOL_GPL vmlinux 0x2ece9f66 __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x2ef539b7 copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0x2f1d6c37 led_trigger_show +EXPORT_SYMBOL_GPL vmlinux 0x2ff30af9 crypto_alloc_instance +EXPORT_SYMBOL_GPL vmlinux 0x30e76706 tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0x30ec9492 dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0x319791c0 rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0x31d53891 nf_unregister_queue_handlers +EXPORT_SYMBOL_GPL vmlinux 0x325e677c gnttab_grant_foreign_transfer_ref +EXPORT_SYMBOL_GPL vmlinux 0x3441c3d6 gpio_set_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x34817801 cpuidle_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0x359f7313 pci_enable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0x35ba78ac user_match +EXPORT_SYMBOL_GPL vmlinux 0x35c8d41a fib_rules_lookup +EXPORT_SYMBOL_GPL vmlinux 0x361e2bcc save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x3621a014 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x36288501 inet6_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x362e23ec call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x369860f1 mmu_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0x370290af skb_morph +EXPORT_SYMBOL_GPL vmlinux 0x370acd10 tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x37a12431 inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0x37b8e076 __mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x37e37f25 inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0x385c571d cpufreq_register_governor +EXPORT_SYMBOL_GPL vmlinux 0x3895233b srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x38fc47e5 platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0x3a0edd1f input_class +EXPORT_SYMBOL_GPL vmlinux 0x3a26cd2d inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x3a311560 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x3a7bdbf8 sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x3a7f8b86 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x3a865912 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0x3acbd18d posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0x3af3d91a tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0x3b1446fb platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0x3b4ec75d platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x3bc12515 class_find_device +EXPORT_SYMBOL_GPL vmlinux 0x3bc13dac devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x3be7af02 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x3c5b8103 debugfs_create_u16 +EXPORT_SYMBOL_GPL vmlinux 0x3c942368 profile_event_unregister +EXPORT_SYMBOL_GPL vmlinux 0x3cd06035 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x3cfedb3f register_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x3d0b02ec sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x3d29867d per_cpu__gdt_page +EXPORT_SYMBOL_GPL vmlinux 0x3d5f392d acpi_os_unmap_memory +EXPORT_SYMBOL_GPL vmlinux 0x3d7ea99a gnttab_grant_foreign_transfer +EXPORT_SYMBOL_GPL vmlinux 0x3d86deb4 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x3e31a810 platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0x3efb35c9 get_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0x3f238101 dcookie_register +EXPORT_SYMBOL_GPL vmlinux 0x3f641ed4 fb_deferred_io_fsync +EXPORT_SYMBOL_GPL vmlinux 0x3f84d4c9 gnttab_release_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x3f8d883a swiotlb_sync_single_range_for_cpu +EXPORT_SYMBOL_GPL vmlinux 0x4077d573 rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0x409cf031 acpi_ec_remove_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x40c39cff acpi_ec_add_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x4181a7aa xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0x41f3cc90 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x424acc6d scatterwalk_done +EXPORT_SYMBOL_GPL vmlinux 0x425508d3 stop_machine +EXPORT_SYMBOL_GPL vmlinux 0x4270efa2 xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0x42bd2bbe free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x42d7fd00 pciserial_remove_ports +EXPORT_SYMBOL_GPL vmlinux 0x42fbc4c8 crypto_attr_alg +EXPORT_SYMBOL_GPL vmlinux 0x432969ec devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0x432fd7f6 __gpio_set_value +EXPORT_SYMBOL_GPL vmlinux 0x44a65d5c lock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x44eb5026 sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x454a14a4 transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0x457594fa crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x45ae553d tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0x45bf1ff3 crypto_inc +EXPORT_SYMBOL_GPL vmlinux 0x45d14bdf hypercall_page +EXPORT_SYMBOL_GPL vmlinux 0x460f31aa rodata_test_data +EXPORT_SYMBOL_GPL vmlinux 0x46e3d644 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x4712e4ca xenbus_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0x47229b5c gpio_request +EXPORT_SYMBOL_GPL vmlinux 0x480b145e inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0x4900e0fa __audit_inode_child +EXPORT_SYMBOL_GPL vmlinux 0x499043d3 crypto_init_queue +EXPORT_SYMBOL_GPL vmlinux 0x49a8e75f xenbus_free_evtchn +EXPORT_SYMBOL_GPL vmlinux 0x4a11a4fb bind_virq_to_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0x4a1e706f put_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x4a227f2f simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x4a7e30d9 marker_probe_unregister_private_data +EXPORT_SYMBOL_GPL vmlinux 0x4aaa9d65 fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0x4ab25168 spi_add_device +EXPORT_SYMBOL_GPL vmlinux 0x4aeaf238 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x4b762828 start_thread +EXPORT_SYMBOL_GPL vmlinux 0x4bc83227 sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x4bdcd7c2 blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0x4c6ed311 bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0x4c759827 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x4caa501d pci_cleanup_aer_uncorrect_error_status +EXPORT_SYMBOL_GPL vmlinux 0x4d22afcb __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0x4d4edc3d xenbus_bind_evtchn +EXPORT_SYMBOL_GPL vmlinux 0x4e7e7923 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x4ea6ff75 rtc_class_close +EXPORT_SYMBOL_GPL vmlinux 0x4eb25b04 vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0x4ec6a70b device_create +EXPORT_SYMBOL_GPL vmlinux 0x4eee4bc0 crypto_tfm_in_queue +EXPORT_SYMBOL_GPL vmlinux 0x4f9cb883 sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x4fc28000 macvlan_handle_frame_hook +EXPORT_SYMBOL_GPL vmlinux 0x4fd86323 inotify_add_watch +EXPORT_SYMBOL_GPL vmlinux 0x500e47f3 sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0x50156d61 map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x50b319ce cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0x50b67174 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x50e7193a __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x514aa93b tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0x518c2fc6 hpet_rtc_dropped_irq +EXPORT_SYMBOL_GPL vmlinux 0x51921120 default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0x51a4c094 unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x51dd6488 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x52d111ea pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x53039405 pci_block_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x53986488 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x53c2d13a platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0x541dc502 rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x546ea25e destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x5493a797 preempt_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0x54e01330 inotify_destroy +EXPORT_SYMBOL_GPL vmlinux 0x55526907 xen_features +EXPORT_SYMBOL_GPL vmlinux 0x56398615 mark_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5641485b tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x567e7a9a rtc_irq_unregister +EXPORT_SYMBOL_GPL vmlinux 0x56b79a74 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0x56c05c3d sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0x575c5f94 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0x5779d445 xenbus_exists +EXPORT_SYMBOL_GPL vmlinux 0x579e0bf5 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x57fcd32d __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0x58013efe class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0x58a200ee uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0x58ae69b9 tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x595cbe8f driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x5975549a debugfs_create_u64 +EXPORT_SYMBOL_GPL vmlinux 0x597f3bc3 marker_get_private_data +EXPORT_SYMBOL_GPL vmlinux 0x5a2b1b67 gnttab_free_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x5ac7273e rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0x5af03a28 gnttab_claim_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x5b392b04 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0x5b3be9a1 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0x5b5ff40b power_supply_changed +EXPORT_SYMBOL_GPL vmlinux 0x5bb44a32 klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x5bc48f8b get_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x5bfc03c3 unregister_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5cf03dd7 security_inode_permission +EXPORT_SYMBOL_GPL vmlinux 0x5cfcf0f1 percpu_free +EXPORT_SYMBOL_GPL vmlinux 0x5d0f6f57 kbd_table +EXPORT_SYMBOL_GPL vmlinux 0x5d366dec gnttab_cancel_free_callback +EXPORT_SYMBOL_GPL vmlinux 0x5d730e7b raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5dd67618 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5e916cdb platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x5eb05848 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x5f10e819 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0x5f2da8c4 check_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5f3bc2ce input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x5f408bac klist_next +EXPORT_SYMBOL_GPL vmlinux 0x5f586bc1 relay_file_operations +EXPORT_SYMBOL_GPL vmlinux 0x5fd23a46 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0x5fe069c2 unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x5fea940b hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x6030e181 crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x6091797f synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x60a13e90 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x61361cfd __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x614b116b device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x622e683b bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0x62843a48 class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x629637b6 platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0x6326f4df skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0x633bba21 inet6_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x634cc62d xfrm_audit_state_add +EXPORT_SYMBOL_GPL vmlinux 0x6357ca29 fib_rules_register +EXPORT_SYMBOL_GPL vmlinux 0x63a4f36e inet_diag_register +EXPORT_SYMBOL_GPL vmlinux 0x63ae27d6 add_nops +EXPORT_SYMBOL_GPL vmlinux 0x643f782a tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0x6485d13c devres_add +EXPORT_SYMBOL_GPL vmlinux 0x65ccb6f0 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x65d6d0f0 gpio_direction_input +EXPORT_SYMBOL_GPL vmlinux 0x660f5598 sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0x6610ad99 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x661601de sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x664d14f7 platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x66b2a859 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x66bc7b5f sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x66d87d38 symbol_put_addr +EXPORT_SYMBOL_GPL vmlinux 0x674faff4 tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x67955ce6 profile_hits +EXPORT_SYMBOL_GPL vmlinux 0x6834cc83 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x6838c066 __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x684fddfd __trace_note_message +EXPORT_SYMBOL_GPL vmlinux 0x6861bc42 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x686c703f xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x6892088c unregister_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x689822cc devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x68b38221 xenbus_dev_error +EXPORT_SYMBOL_GPL vmlinux 0x691884ef pv_apic_ops +EXPORT_SYMBOL_GPL vmlinux 0x6a2c4941 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0x6a86b01f xenbus_map_ring +EXPORT_SYMBOL_GPL vmlinux 0x6a9638e9 tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0x6b07a368 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0x6b10495b devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0x6b3e5d57 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x6b9178b3 xenbus_strstate +EXPORT_SYMBOL_GPL vmlinux 0x6b93bf60 inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x6be62dfd probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x6c11059b __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x6c49c4f2 clockevents_notify +EXPORT_SYMBOL_GPL vmlinux 0x6c82e92f x86_bios_freq_base +EXPORT_SYMBOL_GPL vmlinux 0x6c8d5ae8 __gpio_get_value +EXPORT_SYMBOL_GPL vmlinux 0x6c99674d kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0x6cb6b12f put_device +EXPORT_SYMBOL_GPL vmlinux 0x6d13c6bb __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x6d5b11f4 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0x6db7b6f0 __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0x6e563010 relay_reset +EXPORT_SYMBOL_GPL vmlinux 0x6e58ddf0 gnttab_end_foreign_transfer_ref +EXPORT_SYMBOL_GPL vmlinux 0x6f57bc36 do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x6f893983 register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x6f9c2efe marker_probe_cb +EXPORT_SYMBOL_GPL vmlinux 0x6ff928e2 xfrm_audit_state_notfound +EXPORT_SYMBOL_GPL vmlinux 0x6ffb5b60 klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x70075cb1 led_trigger_remove +EXPORT_SYMBOL_GPL vmlinux 0x7026555a screen_glyph +EXPORT_SYMBOL_GPL vmlinux 0x7037d79d k8_flush_garts +EXPORT_SYMBOL_GPL vmlinux 0x7146a180 generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0x71c8bc95 kgdb_unregister_io_module +EXPORT_SYMBOL_GPL vmlinux 0x71cea111 put_driver +EXPORT_SYMBOL_GPL vmlinux 0x71d9d73c tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x7278d328 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x72943605 crypto_spawn_tfm +EXPORT_SYMBOL_GPL vmlinux 0x72c412c4 debugfs_create_u32 +EXPORT_SYMBOL_GPL vmlinux 0x731433ee unregister_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0x73201149 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0x733cddd2 xenbus_frontend_closed +EXPORT_SYMBOL_GPL vmlinux 0x73b1f76d do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x741ceb5a relay_open +EXPORT_SYMBOL_GPL vmlinux 0x742e7e37 mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0x7489ac58 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x749bb70f page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0x74abdafa task_handoff_register +EXPORT_SYMBOL_GPL vmlinux 0x74d61a4d get_dcookie +EXPORT_SYMBOL_GPL vmlinux 0x74db3a61 raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0x7521afb6 leave_mm +EXPORT_SYMBOL_GPL vmlinux 0x75c91110 rtc_read_alarm +EXPORT_SYMBOL_GPL vmlinux 0x75ce259a sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x75e8f3c3 crypto_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x761b0b49 cpufreq_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x762d809c net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x7638b63c rtc_irq_register +EXPORT_SYMBOL_GPL vmlinux 0x7656d86f mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x7677c2dc fb_deferred_io_cleanup +EXPORT_SYMBOL_GPL vmlinux 0x7712771a unbind_from_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0x776112af bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x77620316 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x781832f2 cpufreq_cpu_get +EXPORT_SYMBOL_GPL vmlinux 0x78fa77c7 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0x79629583 cpuidle_register_device +EXPORT_SYMBOL_GPL vmlinux 0x7a0c257c bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0x7a4c1438 pv_info +EXPORT_SYMBOL_GPL vmlinux 0x7ac10ebc uv_node_to_blade +EXPORT_SYMBOL_GPL vmlinux 0x7b1d544d edac_handler_set +EXPORT_SYMBOL_GPL vmlinux 0x7b6cbb67 device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x7b92a840 __blk_add_trace +EXPORT_SYMBOL_GPL vmlinux 0x7bb558db fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0x7c6b16b1 platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x7c6d7605 blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x7cba8809 fb_deferred_io_init +EXPORT_SYMBOL_GPL vmlinux 0x7da8d037 marker_probe_register +EXPORT_SYMBOL_GPL vmlinux 0x7dc5d0b6 crypto_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x7ecf642e single_release_net +EXPORT_SYMBOL_GPL vmlinux 0x7f19a9bf spi_unregister_master +EXPORT_SYMBOL_GPL vmlinux 0x7f19c836 unlock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x7feba00a inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x7ff10ccf raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x8039d043 selinux_secmark_relabel_packet_permission +EXPORT_SYMBOL_GPL vmlinux 0x80746a64 pci_disable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0x8088d5ba led_trigger_set_default +EXPORT_SYMBOL_GPL vmlinux 0x80ee55c3 selinux_secmark_refcount_inc +EXPORT_SYMBOL_GPL vmlinux 0x8157f0a5 elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x81ae30e7 tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0x81e6fa78 bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x822512fa debugfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x8226642f __gpio_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x826360fd do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x827805c5 cpufreq_unregister_governor +EXPORT_SYMBOL_GPL vmlinux 0x82af6582 platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x82cd19f3 register_xenstore_notifier +EXPORT_SYMBOL_GPL vmlinux 0x82cd83b2 kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0x82d79b51 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x82f776b7 gpio_export +EXPORT_SYMBOL_GPL vmlinux 0x8315abb2 raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0x83afa919 register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x83cdf073 skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0x83f5d687 sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x83f6b2d2 dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x844c499e crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0x8556153e rtc_set_mmss +EXPORT_SYMBOL_GPL vmlinux 0x85c10896 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x85d7edfd hpet_set_periodic_freq +EXPORT_SYMBOL_GPL vmlinux 0x85d86844 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0x85e5a3db ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x862cab14 rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0x863ef2b4 inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0x86623fd7 notify_remote_via_irq +EXPORT_SYMBOL_GPL vmlinux 0x868784cb __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x86a51007 gnttab_end_foreign_transfer +EXPORT_SYMBOL_GPL vmlinux 0x86b1667d hwrng_unregister +EXPORT_SYMBOL_GPL vmlinux 0x86b33713 acpi_bus_trim +EXPORT_SYMBOL_GPL vmlinux 0x871a9910 register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x873fbaea edac_atomic_assert_error +EXPORT_SYMBOL_GPL vmlinux 0x8758c537 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0x87754115 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x87f2cf3a blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0x880b189a __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x8810ad5e crypto_xor +EXPORT_SYMBOL_GPL vmlinux 0x885142a6 nf_net_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x88f0db24 cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x89a81636 transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0x89bae393 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x89bb6728 __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0x8abed13d xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x8af295fd inotify_inode_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x8afc1caf dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0x8afe8053 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0x8b0f003d device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x8b65ecc8 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8b9200fd lookup_address +EXPORT_SYMBOL_GPL vmlinux 0x8c06a108 xenbus_transaction_start +EXPORT_SYMBOL_GPL vmlinux 0x8c38074a unregister_xenstore_notifier +EXPORT_SYMBOL_GPL vmlinux 0x8e72b2a1 __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8eb58c6e __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0x8ede7e0f skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x8ef4891e device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x8f6cee77 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x9009602a acpi_bus_get_ejd +EXPORT_SYMBOL_GPL vmlinux 0x906b805e srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x90a1004a crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x90bfc439 pci_intx +EXPORT_SYMBOL_GPL vmlinux 0x90f94ef8 led_trigger_unregister_simple +EXPORT_SYMBOL_GPL vmlinux 0x9107183c init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x9159b9d6 profile_event_register +EXPORT_SYMBOL_GPL vmlinux 0x917445dc power_supply_unregister +EXPORT_SYMBOL_GPL vmlinux 0x9192b8fe gpiochip_remove +EXPORT_SYMBOL_GPL vmlinux 0x91b3f5a9 apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0x91dacaa2 acpi_processor_ffh_cstate_probe +EXPORT_SYMBOL_GPL vmlinux 0x91fd4fb8 device_rename +EXPORT_SYMBOL_GPL vmlinux 0x92183295 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x92238352 led_trigger_store +EXPORT_SYMBOL_GPL vmlinux 0x9241c3ee device_power_down +EXPORT_SYMBOL_GPL vmlinux 0x92445aee hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x929e4dba queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x92fb217b dcookie_unregister +EXPORT_SYMBOL_GPL vmlinux 0x933ec255 inotify_dentry_parent_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x93d2422d snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x942c1704 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x94d742f6 pcie_port_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x952450c6 xfrm_audit_policy_add +EXPORT_SYMBOL_GPL vmlinux 0x952664c5 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x9552df38 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x956a91ba gpio_get_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x9577271c hpet_rtc_interrupt +EXPORT_SYMBOL_GPL vmlinux 0x961a8cd3 unlock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x964d5c39 acpi_os_map_memory +EXPORT_SYMBOL_GPL vmlinux 0x9668892f blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0x966d7352 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x96cbcf31 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x96f42d51 blk_trace_setup +EXPORT_SYMBOL_GPL vmlinux 0x97028da3 led_trigger_register +EXPORT_SYMBOL_GPL vmlinux 0x9795720e bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x9833bc0c hvc_kick +EXPORT_SYMBOL_GPL vmlinux 0x988b642c device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x98c03b3e tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0x98d4982a uhci_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x9917234d inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0x992b442a inverse_translate +EXPORT_SYMBOL_GPL vmlinux 0x9957ef07 crypto_enqueue_request +EXPORT_SYMBOL_GPL vmlinux 0x995c76e9 xfrm_audit_state_replay_overflow +EXPORT_SYMBOL_GPL vmlinux 0x995d1071 prof_on +EXPORT_SYMBOL_GPL vmlinux 0x9a11a0fc crypto_attr_alg_name +EXPORT_SYMBOL_GPL vmlinux 0x9a398f5c xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x9ba0501e unregister_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x9c8dfc3a do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0x9ca7708c rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x9cb74740 crypto_drop_spawn +EXPORT_SYMBOL_GPL vmlinux 0x9cb8037b xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x9d029355 unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x9d06688b register_xenbus_watch +EXPORT_SYMBOL_GPL vmlinux 0x9d3273dd sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0x9d3850e1 gnttab_alloc_grant_references +EXPORT_SYMBOL_GPL vmlinux 0x9e711ad2 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x9e7d3442 xenbus_resume +EXPORT_SYMBOL_GPL vmlinux 0x9e9662ab user_describe +EXPORT_SYMBOL_GPL vmlinux 0x9ec89e3f d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x9f51582e pci_find_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x9fc90b8d __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0x9fce80db fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xa01d72c3 raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0xa0255440 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0xa045c69b debugfs_create_symlink +EXPORT_SYMBOL_GPL vmlinux 0xa0a612a0 device_del +EXPORT_SYMBOL_GPL vmlinux 0xa1596d98 acpi_processor_ffh_cstate_enter +EXPORT_SYMBOL_GPL vmlinux 0xa1ba3bb8 netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0xa1c27ac5 skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0xa1f90571 platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0xa2937953 inotify_rm_watch +EXPORT_SYMBOL_GPL vmlinux 0xa2a79abd proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0xa2c03841 bind_evtchn_to_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0xa2e67f08 acpi_bus_generate_proc_event4 +EXPORT_SYMBOL_GPL vmlinux 0xa2e8bac5 lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0xa2f1e19f class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xa3499aec get_device +EXPORT_SYMBOL_GPL vmlinux 0xa353fffc xenbus_rm +EXPORT_SYMBOL_GPL vmlinux 0xa3a7c178 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0xa3fc96f0 marker_probe_cb_noarg +EXPORT_SYMBOL_GPL vmlinux 0xa452c297 hpet_mask_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa4d58669 math_state_restore +EXPORT_SYMBOL_GPL vmlinux 0xa5614615 rtc_device_register +EXPORT_SYMBOL_GPL vmlinux 0xa5622624 power_supply_register +EXPORT_SYMBOL_GPL vmlinux 0xa5a63c40 inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0xa5bf5c3e pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0xa5c36cec inotify_unmount_inodes +EXPORT_SYMBOL_GPL vmlinux 0xa712d99f __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0xa73c7a4a fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0xa7564542 vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0xa780889d tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0xa815dda5 gpiochip_add +EXPORT_SYMBOL_GPL vmlinux 0xa83415d1 pciserial_resume_ports +EXPORT_SYMBOL_GPL vmlinux 0xa8590407 inet_hash +EXPORT_SYMBOL_GPL vmlinux 0xa8afdfd0 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0xa8f59416 gpio_direction_output +EXPORT_SYMBOL_GPL vmlinux 0xa9126bff hpet_set_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa963f49c tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0xa97d49dc xenbus_switch_state +EXPORT_SYMBOL_GPL vmlinux 0xa9c530b8 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xaa1b769e cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0xaa429881 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0xaa587725 nf_register_afinfo +EXPORT_SYMBOL_GPL vmlinux 0xaa86cfb5 uv_possible_blades +EXPORT_SYMBOL_GPL vmlinux 0xaa8c4696 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0xaaac6483 audit_log_vformat +EXPORT_SYMBOL_GPL vmlinux 0xab01acbe gnttab_request_free_callback +EXPORT_SYMBOL_GPL vmlinux 0xab9ea5f3 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0xaba749b6 simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0xabc28976 force_evtchn_callback +EXPORT_SYMBOL_GPL vmlinux 0xabe65286 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0xabec8c68 ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0xac1ee37d sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0xac352657 xfrm_audit_state_delete +EXPORT_SYMBOL_GPL vmlinux 0xacc19485 ibft_addr +EXPORT_SYMBOL_GPL vmlinux 0xad096363 xenbus_printf +EXPORT_SYMBOL_GPL vmlinux 0xad150e63 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0xad1b5443 crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0xad4f248a rtc_irq_set_freq +EXPORT_SYMBOL_GPL vmlinux 0xad63a24e per_cpu____uv_hub_info +EXPORT_SYMBOL_GPL vmlinux 0xadffe1cf alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0xae0c87ee pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0xae22fdd0 inet6_lookup +EXPORT_SYMBOL_GPL vmlinux 0xae3982f5 k_handler +EXPORT_SYMBOL_GPL vmlinux 0xae9e08e7 vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0xaec245ed sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0xaf35b9db driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0xafae3c4b pci_stop_bus_device +EXPORT_SYMBOL_GPL vmlinux 0xafc88469 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0xafdfa5ff platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0xafedb308 security_inode_setattr +EXPORT_SYMBOL_GPL vmlinux 0xb04a2413 pci_find_aer_capability +EXPORT_SYMBOL_GPL vmlinux 0xb0889179 swiotlb_sync_single_range_for_device +EXPORT_SYMBOL_GPL vmlinux 0xb10d55bc cn_netlink_send +EXPORT_SYMBOL_GPL vmlinux 0xb120ab95 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0xb1acbcce rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0xb2196033 gpiochip_is_requested +EXPORT_SYMBOL_GPL vmlinux 0xb221ee72 pci_destroy_slot +EXPORT_SYMBOL_GPL vmlinux 0xb27005f5 device_suspend +EXPORT_SYMBOL_GPL vmlinux 0xb3180a78 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0xb3253ed9 hpet_rtc_timer_init +EXPORT_SYMBOL_GPL vmlinux 0xb37474a4 power_supply_class +EXPORT_SYMBOL_GPL vmlinux 0xb3b080fa seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0xb3e0b0f0 devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0xb46c54ab hwmon_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xb4e14553 gnttab_query_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xb4ea7cf7 kgdb_connected +EXPORT_SYMBOL_GPL vmlinux 0xb51cd6a6 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0xb51fbd64 edac_op_state +EXPORT_SYMBOL_GPL vmlinux 0xb53ae573 cpu_idle_wait +EXPORT_SYMBOL_GPL vmlinux 0xb53defa6 rtc_set_alarm +EXPORT_SYMBOL_GPL vmlinux 0xb612444d snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0xb61c5c63 platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0xb6230f1f gnttab_grant_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xb63550f5 __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0xb65091b3 selinux_secmark_refcount_dec +EXPORT_SYMBOL_GPL vmlinux 0xb6536723 cpufreq_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0xb6e62bbb __class_register +EXPORT_SYMBOL_GPL vmlinux 0xb6ffd038 debugfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0xb74920ad console_drivers +EXPORT_SYMBOL_GPL vmlinux 0xb7a0c77c ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0xb7b443de sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0xb7d7c12e hpet_set_alarm_time +EXPORT_SYMBOL_GPL vmlinux 0xb8048d50 securityfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0xb808c909 tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0xb903674c scatterwalk_map_and_copy +EXPORT_SYMBOL_GPL vmlinux 0xb93288e7 securityfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0xb9368b32 rtc_set_time +EXPORT_SYMBOL_GPL vmlinux 0xb97e6c02 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0xb992461e pskb_put +EXPORT_SYMBOL_GPL vmlinux 0xb99d5837 xenbus_read +EXPORT_SYMBOL_GPL vmlinux 0xb9eb3aa9 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0xb9efc967 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xba4de1dd sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0xba58775c blk_trace_startstop +EXPORT_SYMBOL_GPL vmlinux 0xbabfe4e2 xfrm_audit_policy_delete +EXPORT_SYMBOL_GPL vmlinux 0xbb324330 debugfs_create_x16 +EXPORT_SYMBOL_GPL vmlinux 0xbb3ecb11 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0xbb7295b5 power_supply_am_i_supplied +EXPORT_SYMBOL_GPL vmlinux 0xbbb98859 edid_info +EXPORT_SYMBOL_GPL vmlinux 0xbbd1e034 device_register +EXPORT_SYMBOL_GPL vmlinux 0xbbdc1c82 kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0xbc089f3b __class_create +EXPORT_SYMBOL_GPL vmlinux 0xbc301681 pciserial_suspend_ports +EXPORT_SYMBOL_GPL vmlinux 0xbcc27560 inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0xbce2f3ce driver_attach +EXPORT_SYMBOL_GPL vmlinux 0xbcf59b30 generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0xbd8f3be3 blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0xbdb535b6 inotify_inode_is_dead +EXPORT_SYMBOL_GPL vmlinux 0xbe7ef09b pci_set_pcie_reset_state +EXPORT_SYMBOL_GPL vmlinux 0xbe95831f pci_create_slot +EXPORT_SYMBOL_GPL vmlinux 0xbf00a09b spi_busnum_to_master +EXPORT_SYMBOL_GPL vmlinux 0xbf32cb64 sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0xbf74eb20 probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0xc097eb8e hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0xc0b3ca1f pci_restore_msi_state +EXPORT_SYMBOL_GPL vmlinux 0xc0ce6b54 cpuidle_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0xc1133988 led_trigger_event +EXPORT_SYMBOL_GPL vmlinux 0xc18ad2c1 devres_find +EXPORT_SYMBOL_GPL vmlinux 0xc26351f8 bind_evtchn_to_irq +EXPORT_SYMBOL_GPL vmlinux 0xc26aba23 firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0xc2945138 bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xc29fd93f proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0xc2fed832 hvc_alloc +EXPORT_SYMBOL_GPL vmlinux 0xc33f7617 blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0xc34efe27 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0xc381378c blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0xc3a81873 xenbus_watch_pathfmt +EXPORT_SYMBOL_GPL vmlinux 0xc3d31607 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0xc415525f rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0xc42f2f94 xenbus_read_driver_state +EXPORT_SYMBOL_GPL vmlinux 0xc4330bb4 pciserial_init_ports +EXPORT_SYMBOL_GPL vmlinux 0xc4f6be38 crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0xc512626a __supported_pte_mask +EXPORT_SYMBOL_GPL vmlinux 0xc5397da6 xenbus_mkdir +EXPORT_SYMBOL_GPL vmlinux 0xc54e6ff9 anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0xc5680dac bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0xc5696360 put_pid +EXPORT_SYMBOL_GPL vmlinux 0xc5adc89d __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0xc5c74f1b pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0xc5f3a277 rtc_irq_set_state +EXPORT_SYMBOL_GPL vmlinux 0xc66663fd vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0xc68976a8 spi_alloc_device +EXPORT_SYMBOL_GPL vmlinux 0xc6f50d38 tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0xc70898c0 simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0xc7535af9 kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0xc7ec11f6 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xc7f72be0 relay_close +EXPORT_SYMBOL_GPL vmlinux 0xc81be572 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0xc81d40a6 hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0xc82ddb06 crypto_init_spawn +EXPORT_SYMBOL_GPL vmlinux 0xc8544cf1 get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0xc87c1f84 ktime_get +EXPORT_SYMBOL_GPL vmlinux 0xc87e487a sched_clock_idle_sleep_event +EXPORT_SYMBOL_GPL vmlinux 0xc926b833 vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0xc9561772 fb_destroy_modelist +EXPORT_SYMBOL_GPL vmlinux 0xca360989 disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0xca81ea9a xenbus_transaction_end +EXPORT_SYMBOL_GPL vmlinux 0xcabe04de cpuidle_resume_and_unlock +EXPORT_SYMBOL_GPL vmlinux 0xcbc31b5a invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0xcbc8088d relay_switch_subbuf +EXPORT_SYMBOL_GPL vmlinux 0xcbf20127 klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0xcc018d9c register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0xcc1f1c3d inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0xcc5299e9 register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0xcc8c382b sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0xcc944571 inotify_init_watch +EXPORT_SYMBOL_GPL vmlinux 0xcd9a04b7 crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0xcda73000 devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0xcde9679b cpuidle_register_driver +EXPORT_SYMBOL_GPL vmlinux 0xce1b86ba audit_log_d_path +EXPORT_SYMBOL_GPL vmlinux 0xce324c37 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0xced8b807 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0xcedf435b page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0xcf389571 debugfs_remove +EXPORT_SYMBOL_GPL vmlinux 0xcfcc83ad register_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0xd027a07d marker_probe_unregister +EXPORT_SYMBOL_GPL vmlinux 0xd03c7700 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0xd0c05159 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0xd10c15cd pci_scan_child_bus +EXPORT_SYMBOL_GPL vmlinux 0xd120d9b9 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0xd161986b tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0xd16712f3 crypto_check_attr_type +EXPORT_SYMBOL_GPL vmlinux 0xd1aed017 crypto_unregister_alg +EXPORT_SYMBOL_GPL vmlinux 0xd1ee0737 device_add +EXPORT_SYMBOL_GPL vmlinux 0xd247edb4 rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0xd264f899 vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0xd29b5ad2 sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0xd373624f kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0xd3b78da3 xenbus_suspend_cancel +EXPORT_SYMBOL_GPL vmlinux 0xd3ef4639 transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0xd40660a9 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0xd44250e1 crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0xd516bffd platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0xd6f77c33 find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0xd6feefa5 agp_num_entries +EXPORT_SYMBOL_GPL vmlinux 0xd7d79132 put_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0xd82f8964 devres_get +EXPORT_SYMBOL_GPL vmlinux 0xd855aca2 mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0xd9042fa8 scatterwalk_map +EXPORT_SYMBOL_GPL vmlinux 0xd9f8681a attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0xdaaa88c2 hwmon_device_register +EXPORT_SYMBOL_GPL vmlinux 0xdae86172 blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0xdaf4dfb3 fb_mode_option +EXPORT_SYMBOL_GPL vmlinux 0xdb57931e fib_rules_cleanup_ops +EXPORT_SYMBOL_GPL vmlinux 0xdb7569a9 preempt_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0xdbee78fe spi_alloc_master +EXPORT_SYMBOL_GPL vmlinux 0xdc1f8f2e register_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0xdc7f2de2 inet_csk_compat_setsockopt +EXPORT_SYMBOL_GPL vmlinux 0xdc9fdf45 kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0xdcf11e37 __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0xdd5c4942 srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0xddb6d1c1 bus_register +EXPORT_SYMBOL_GPL vmlinux 0xddbe0e71 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0xde162625 __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xde7ed175 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0xdeb750be generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0xdeda859b inet_csk_compat_getsockopt +EXPORT_SYMBOL_GPL vmlinux 0xdf2159ad inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0xdf3c19ec cn_add_callback +EXPORT_SYMBOL_GPL vmlinux 0xdfbd9126 rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0xe089cfcc agp_memory_reserved +EXPORT_SYMBOL_GPL vmlinux 0xe09033e4 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0xe1d1f8bb crypto_register_template +EXPORT_SYMBOL_GPL vmlinux 0xe24ff917 blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0xe25ccd06 relay_subbufs_consumed +EXPORT_SYMBOL_GPL vmlinux 0xe295c0ff is_hpet_enabled +EXPORT_SYMBOL_GPL vmlinux 0xe2dbd55a led_trigger_register_simple +EXPORT_SYMBOL_GPL vmlinux 0xe2e3f4a1 pci_slots_kset +EXPORT_SYMBOL_GPL vmlinux 0xe348c249 unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xe34db7f2 sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0xe35759ff tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0xe36cb7c3 tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0xe3c99b8d uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0xe3e7ba4a user_read +EXPORT_SYMBOL_GPL vmlinux 0xe3ee4899 rtc_class_open +EXPORT_SYMBOL_GPL vmlinux 0xe411465e pci_bus_add_device +EXPORT_SYMBOL_GPL vmlinux 0xe513afc0 cache_k8_northbridges +EXPORT_SYMBOL_GPL vmlinux 0xe52742ae debugfs_create_u8 +EXPORT_SYMBOL_GPL vmlinux 0xe527c9ac simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0xe530071c pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0xe57963a0 platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xe61a6d2f gpio_unexport +EXPORT_SYMBOL_GPL vmlinux 0xe6488b47 cpufreq_notify_transition +EXPORT_SYMBOL_GPL vmlinux 0xe651c0b7 crypto_hash_walk_first +EXPORT_SYMBOL_GPL vmlinux 0xe66df9c8 driver_register +EXPORT_SYMBOL_GPL vmlinux 0xe674a5cb srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0xe6d6addd tcp_done +EXPORT_SYMBOL_GPL vmlinux 0xe6e8253e crypto_ahash_type +EXPORT_SYMBOL_GPL vmlinux 0xe72778d7 alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xe79c2957 register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0xe7de7122 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0xe7fa47ad srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0xe81af31a crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0xe83aafab mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0xe841d957 xenbus_dev_fatal +EXPORT_SYMBOL_GPL vmlinux 0xe8583fc1 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0xe8f9dfaf uv_cpu_to_blade +EXPORT_SYMBOL_GPL vmlinux 0xe90bac06 debugfs_create_bool +EXPORT_SYMBOL_GPL vmlinux 0xe93e49c3 devres_free +EXPORT_SYMBOL_GPL vmlinux 0xe94fefd7 inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0xe9dd844d bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0xea065e01 task_handoff_unregister +EXPORT_SYMBOL_GPL vmlinux 0xeb27d352 pci_update_slot_number +EXPORT_SYMBOL_GPL vmlinux 0xeb864b6e bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0xec8db6d0 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0xecc85c8c device_attach +EXPORT_SYMBOL_GPL vmlinux 0xed26fb0f rtc_update_irq +EXPORT_SYMBOL_GPL vmlinux 0xed636046 inotify_rm_wd +EXPORT_SYMBOL_GPL vmlinux 0xed907658 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0xedb103ec sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0xedbc6f67 gnttab_end_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xedc013bb get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0xee59b408 invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0xee8e29e3 blk_trace_remove +EXPORT_SYMBOL_GPL vmlinux 0xeecfb193 set_cpus_allowed_ptr +EXPORT_SYMBOL_GPL vmlinux 0xef35dd65 cpuidle_disable_device +EXPORT_SYMBOL_GPL vmlinux 0xef390070 debugfs_create_x8 +EXPORT_SYMBOL_GPL vmlinux 0xef67109f pci_bus_max_busnr +EXPORT_SYMBOL_GPL vmlinux 0xefb66434 fb_bl_default_curve +EXPORT_SYMBOL_GPL vmlinux 0xefdf3189 save_stack_trace_tsk +EXPORT_SYMBOL_GPL vmlinux 0xefecadf7 device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xf0809b34 driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xf0cd7362 vlan_dev_vlan_id +EXPORT_SYMBOL_GPL vmlinux 0xf11c3ce2 tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0xf16fc662 debugfs_rename +EXPORT_SYMBOL_GPL vmlinux 0xf184d189 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0xf1d928c3 class_destroy +EXPORT_SYMBOL_GPL vmlinux 0xf259eb08 driver_find +EXPORT_SYMBOL_GPL vmlinux 0xf2a906c3 xfrm_audit_state_notfound_simple +EXPORT_SYMBOL_GPL vmlinux 0xf2b34905 blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0xf2fca922 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0xf3a6af55 register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0xf3d1bb7a __cpufreq_driver_getavg +EXPORT_SYMBOL_GPL vmlinux 0xf3f2b2ef crypto_register_alg +EXPORT_SYMBOL_GPL vmlinux 0xf41e1eac proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0xf4762ccb vlan_dev_real_dev +EXPORT_SYMBOL_GPL vmlinux 0xf4831126 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0xf499fdb2 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0xf4aebdc3 xenbus_suspend +EXPORT_SYMBOL_GPL vmlinux 0xf4d78b52 get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0xf553318d cpuidle_pause_and_lock +EXPORT_SYMBOL_GPL vmlinux 0xf5945bac gnttab_free_grant_references +EXPORT_SYMBOL_GPL vmlinux 0xf5a691cd invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0xf5add0f7 debugfs_create_x32 +EXPORT_SYMBOL_GPL vmlinux 0xf5d148a1 user_destroy +EXPORT_SYMBOL_GPL vmlinux 0xf6511c1f xenbus_alloc_evtchn +EXPORT_SYMBOL_GPL vmlinux 0xf67ae112 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0xf6bb0e24 tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0xf6bcbd73 hwrng_register +EXPORT_SYMBOL_GPL vmlinux 0xf6c9b9bc queue_work +EXPORT_SYMBOL_GPL vmlinux 0xf7016530 xenbus_gather +EXPORT_SYMBOL_GPL vmlinux 0xf7427c4c register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0xf7a3d27f __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0xf7e5dad8 inotify_find_update_watch +EXPORT_SYMBOL_GPL vmlinux 0xf865b5dd agp_add_bridge +EXPORT_SYMBOL_GPL vmlinux 0xf873e73c relay_flush +EXPORT_SYMBOL_GPL vmlinux 0xf8802492 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0xf90a737d __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xf94ef36d sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0xf97c4aae klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0xf99bb136 register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xf9a054b5 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0xfa1f4662 scatterwalk_start +EXPORT_SYMBOL_GPL vmlinux 0xfa48716d hvc_poll +EXPORT_SYMBOL_GPL vmlinux 0xfbc016de blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xfbc9a360 rtc_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xfbcaf457 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0xfbf9be5d register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xfc992a43 device_move +EXPORT_SYMBOL_GPL vmlinux 0xfcc5b4d7 exit_fs +EXPORT_SYMBOL_GPL vmlinux 0xfd51b281 gnttab_end_foreign_access_ref +EXPORT_SYMBOL_GPL vmlinux 0xfd721947 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0xfde0b92c crypto_larval_error +EXPORT_SYMBOL_GPL vmlinux 0xfdf7fcbf kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0xfe727411 get_phys_to_machine +EXPORT_SYMBOL_GPL vmlinux 0xfe990052 gpio_free +EXPORT_SYMBOL_GPL vmlinux 0xfec35820 queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0xfecbff96 __mark_empty_function +EXPORT_SYMBOL_GPL vmlinux 0xff27b0ef inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0xff4af680 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0xff5a8cfe cn_del_callback +EXPORT_SYMBOL_GPL vmlinux 0xff793790 sysdev_class_create_file +EXPORT_UNUSED_SYMBOL vmlinux 0x00000000 init_mm --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/amd64/server.modules +++ linux-2.6.27/debian/abi/2.6.27-8.17/amd64/server.modules @@ -0,0 +1,2072 @@ +3c359 +3c574_cs +3c589_cs +3c59x +3w-9xxx +3w-xxxx +6pack +8021q +8139cp +8139too +8390 +9p +9pnet +9pnet_virtio +a100u2w +a3d +aacraid +abituguru +abituguru3 +abyss +ac +ac97_bus +acecad +acenic +acer-wmi +acpi-cpufreq +acpiphp +acpiphp_ibm +acquirewdt +act200l-sir +act_gact +act_ipt +actisys-sir +act_mirred +act_nat +act_pedit +act_police +act_simple +acx +ad1848 +ad7414 +ad7418 +adcxx +adfs +adi +adm1021 +adm1025 +adm1026 +adm1029 +adm1031 +adm8211 +adm9240 +ads7828 +ads7846 +adt7470 +adt7473 +adutux +adv7170 +adv7175 +advansys +advantechwdt +aead +aedsp16 +aes_generic +aes-x86_64 +affs +af_key +af_packet +af-rxrpc +ah4 +ah6 +ahci +aic79xx +aic7xxx +aic94xx +aiptek +aircable +airo +airo_cs +alauda +ali-ircc +alim1535_wdt +alim7101_wdt +ambassador +amd76xrom +amd8111e +amd-rng +analog +anubis +aoe +appledisplay +appleir +applesmc +appletalk +appletouch +applicom +ar7part +arc4 +arcfb +arcmsr +arcnet +arc-rawmode +arc-rimi +ark3116 +arkfb +arptable_filter +arp_tables +arpt_mangle +asb100 +asix +asus-laptop +async_memcpy +async_tx +async_xor +at24 +at25 +at76_usb +ata_generic +ata_piix +aten +ath9k +ati_remote +ati_remote2 +atl1 +atl1e +atl2 +atlas_btns +atmel +atmel_cs +atmel_pci +atmtcp +atp +atp870u +atxp1 +aty128fb +atyfb +au0828 +au8522 +aufs +authenc +auth_rpcgss +autofs +autofs4 +av5100 +avma1_cs +avm_cs +ax25 +axnet_cs +b1 +b1dma +b1pci +b1pcmcia +b2c2-flexcop +b2c2-flexcop-pci +b2c2-flexcop-usb +b43 +b43legacy +b44 +bas_gigaset +battery +bay +baycom_par +baycom_ser_fdx +baycom_ser_hdx +bcm203x +bcm3510 +bcm5974 +befs +belkin_sa +berry_charge +bfs +bfusb +binfmt_misc +bitblit +block2mtd +blowfish +bluecard_cs +bluetooth +bnep +bnx2 +bnx2x +bonding +bpa10x +bpck +bpqether +br2684 +bridge +broadcom +bsd_comp +bt3c_cs +bt819 +bt856 +bt878 +btcx-risc +btsdio +bttv +btuart_cs +btusb +budget +budget-av +budget-ci +budget-core +budget-patch +BusLogic +button +bw-qcam +c4 +c67x00 +cafe_ccic +cafe_nand +camellia +capi +capidrv +capifs +capmode +carminefb +cassini +cast5 +cast6 +catc +cbc +cciss +ccm +cdc-acm +cdc_ether +cdc_subset +cdc-wdm +cdrom +cfag12864b +cfag12864bfb +cfg80211 +cfi_cmdset_0001 +cfi_cmdset_0002 +cfi_cmdset_0020 +cfi_probe +cfi_util +ch +ch341 +chipreg +cicada +cifs +cinergyT2 +cirrusfb +ck804xrom +cls_basic +cls_fw +cls_route +cls_rsvp +cls_rsvp6 +cls_tcindex +cls_u32 +cm4000_cs +cm4040_cs +cmtp +cobra +coda +com20020 +com20020_cs +com20020-pci +com90io +com90xx +comm +commandir +compal-laptop +compat_ioctl32 +compcache +configfs +container +coretemp +corgi_bl +cp2101 +cpcihp_generic +cpcihp_zt5550 +cpia +cpia2 +cpia_pp +cpia_usb +cpqarray +cpu5wdt +cpufreq_conservative +cpufreq_ondemand +cpufreq_powersave +cpufreq_stats +cpufreq_userspace +cpuid +c-qcam +cr_bllcd +crc16 +crc32c +crc7 +crc-ccitt +crc-itu-t +crc-t10dif +crvml +cryptd +crypto_blkcipher +cryptoloop +crypto_null +cs5345 +cs53l32a +ct82c710 +ctr +cts +cx18 +cx22700 +cx22702 +cx2341x +cx23885 +cx24110 +cx24123 +cx25840 +cx8800 +cx8802 +cx88-alsa +cx88-blackbird +cx88-dvb +cx88-vp3054-i2c +cx88xx +cxacru +cxgb +cxgb3 +cyber2000fb +cyberjack +cyclades +cyclomx +cycx_drv +cypress_cy7c63 +cypress_m8 +cytherm +DAC960 +davicom +db9 +dc395x +dca +dccp +dccp_ccid2 +dccp_ccid3 +dccp_diag +dccp_ipv4 +dccp_ipv6 +dccp_probe +dccp_tfrc_lib +dcdbas +de2104x +de4x5 +de600 +de620 +decnet +deflate +defxx +dell_rbu +des_generic +dib0070 +dib3000mb +dib3000mc +dib7000m +dib7000p +dibx000_common +digi_acceleport +dilnetpc +diskonchip +display +divacapi +divadidd +diva_idi +diva_mnt +divas +dlci +dlm +dm9601 +dm-bbr +dm-crypt +dme1737 +dmfe +dm-log +dm-loop +dm-mem-cache +dm-message +dm-mirror +dm-mod +dm-multipath +dm-raid4-5 +dm-region_hash +dm-round-robin +dm-snapshot +dmx3191d +dm-zero +dn_rtmsg +doc2000 +doc2001 +doc2001plus +docecc +dock +docprobe +dpc7146 +dpt_i2o +drbd +drm +drx397xD +ds1621 +ds1682 +ds2482 +ds2490 +ds2760_battery +dsbr100 +dscc4 +dss1_divert +dst +dst_ca +dstr +dtl1_cs +dummy +dv1394 +dvb-bt8xx +dvb-core +dvb-pll +dvb-ttpci +dvb-ttusb-budget +dvb-usb +dvb-usb-a800 +dvb-usb-af9005 +dvb-usb-af9005-remote +dvb-usb-anysee +dvb-usb-au6610 +dvb-usb-cxusb +dvb-usb-dib0700 +dvb-usb-dibusb-common +dvb-usb-dibusb-mb +dvb-usb-dibusb-mc +dvb-usb-digitv +dvb-usb-dtt200u +dvb-usb-dw2102 +dvb-usb-gl861 +dvb-usb-gp8psk +dvb-usb-m920x +dvb-usb-nova-t-usb2 +dvb-usb-opera +dvb-usb-ttusb2 +dvb-usb-umt-010 +dvb-usb-vp702x +dvb-usb-vp7045 +e100 +e1000 +e1000e +e752x_edac +eata +ebt_802_3 +ebtable_broute +ebtable_filter +ebtable_nat +ebtables +ebt_among +ebt_arp +ebt_arpreply +ebt_dnat +ebt_ip +ebt_ip6 +ebt_limit +ebt_log +ebt_mark +ebt_mark_m +ebt_nflog +ebt_pkttype +ebt_redirect +ebt_snat +ebt_stp +ebt_ulog +ebt_vlan +ecb +econet +ecryptfs +edac_core +eeepc-laptop +eepro100 +eeprom +eeprom_93cx6 +efs +ehci-hcd +elo +elsa_cs +em28xx +em28xx-alsa +em28xx-dvb +em_cmp +emi26 +emi62 +em_meta +em_nbyte +empeg +em_text +emu10k1-gp +em_u32 +enclosure +eni +epat +epca +epia +epic100 +eql +esb2rom +esi-sir +esp4 +esp6 +et131x +et61x251 +eth1394 +eurotechwdt +evbug +evdev +exportfs +ext2 +ext3 +ext4dev +f71805f +f71882fg +f75375s +fakephp +fan +farsync +fat +faulty +fbcon +fb_ddc +fb_sys_fops +fcrypt +fdomain +fdomain_cs +fealnx +ff-memless +firestream +fit2 +fit3 +floppy +fm801-gp +fmvj18x_cs +font +forcedeth +fore_200e +freevxfs +freq_table +friq +frpw +fsam7400 +fscher +fschmd +fscpos +ftdi-elan +ftdi_sio +ftl +fujitsu-laptop +fujitsu_ts +funsoft +fuse +g450_pll +gadgetfs +gamecon +gameport +garmin_gps +garp +g_cdc +gcm +gdth +generic_serial +gen_probe +g_ether +gf128mul +gf2k +g_file_storage +gfs +gfs2 +gigaset +girbil-sir +gl518sm +gl520sm +gl620a +gnbd +gpio_keys +gpio_mouse +grip +grip_mp +gru +g_serial +gspca_conex +gspca_etoms +gspca_main +gspca_mars +gspca_ov519 +gspca_pac207 +gspca_pac7311 +gspca_sonixb +gspca_sonixj +gspca_spca500 +gspca_spca501 +gspca_spca505 +gspca_spca506 +gspca_spca508 +gspca_spca561 +gspca_stk014 +gspca_sunplus +gspca_t613 +gspca_tv8532 +gspca_vc032x +gspca_zc3xx +gtco +guillemot +gunze +gx1fb +gxfb +g_zero +hamachi +hangcheck-timer +hci_uart +hci_vhci +hdaps +hdlc +hdlc_cisco +hdlcdrv +hdlc_fr +hdlc_ppp +hdlc_raw +hdlc_raw_eth +hdlc_x25 +he +heci +hecubafb +hermes +hexium_gemini +hexium_orion +hfc4s8s_l1 +hfcmulti +hfcpci +hfc_usb +hfs +hfsplus +hgafb +hid +hidp +hifn_795x +hisax +hisax_fcpcipnp +hisax_isac +hisax_st5481 +horizon +hostap +hostap_cs +hostap_pci +hostap_plx +hp100 +hp4x +hpfs +hpilo +hptiop +hp-wmi +hso +htc-pasic3 +hwmon-vid +hysdn +i2c-algo-bit +i2c-algo-pca +i2c-algo-pcf +i2c-ali1535 +i2c-ali1563 +i2c-ali15x3 +i2c-amd756 +i2c-amd756-s4882 +i2c-amd8111 +i2c-core +i2c-dev +i2c-gpio +i2c-i801 +i2c-isch +i2c-matroxfb +i2c-nforce2 +i2c-nforce2-s4985 +i2c-ocores +i2c-parport +i2c-parport-light +i2c-pca-platform +i2c-piix4 +i2c-simtec +i2c-sis5595 +i2c-sis630 +i2c-sis96x +i2c-stub +i2c-taos-evm +i2c-tiny-usb +i2c-via +i2c-viapro +i2c-voodoo3 +i2o_block +i2o_bus +i2o_config +i2o_core +i2o_proc +i2o_scsi +i3000_edac +i5000_edac +i5100_edac +i5k_amb +i6300esb +i810 +i82092 +i82975x_edac +i830 +i8k +i915 +ia32_aout +ib700wdt +ib_addr +ib_cm +ib_core +ib_ipath +ib_ipoib +ib_iser +ib_mad +ibmaem +ibmasm +ibmasr +ibmcam +ibmpex +ib_mthca +ib_sa +ib_srp +ib_ucm +ib_umad +ib_uverbs +ichxrom +icplus +idmouse +idt77252 +ieee1394 +ieee80211 +ieee80211_crypt +ieee80211_crypt_ccmp +ieee80211_crypt_tkip +ieee80211_crypt_wep +ifb +iforce +igb +ili9320 +imm +inet_lro +inexio +inftl +initio +input-polldev +intel-agp +intelfb +intel_menlow +intel-rng +intel_vr_nor +interact +ioatdma +ioc4 +io_edgeport +io_ti +iowarrior +ip2 +ip6_queue +ip6table_filter +ip6table_mangle +ip6table_raw +ip6_tables +ip6table_security +ip6t_ah +ip6t_eui64 +ip6t_frag +ip6t_hbh +ip6t_hl +ip6t_HL +ip6t_ipv6header +ip6t_LOG +ip6t_mh +ip6t_REJECT +ip6t_rt +ip6_tunnel +ipaq +ipcomp +ipcomp6 +ipddp +ipg +ip_gre +iphase +ipip +ipmi_devintf +ipmi_msghandler +ipmi_poweroff +ipmi_si +ipmi_watchdog +ip_queue +ipr +ips +iptable_filter +iptable_mangle +iptable_nat +iptable_raw +ip_tables +iptable_security +ipt_addrtype +ipt_ah +ipt_CLUSTERIP +ipt_ecn +ipt_ECN +ipt_LOG +ipt_MASQUERADE +ipt_NETMAP +ipt_recent +ipt_REDIRECT +ipt_REJECT +ipt_ttl +ipt_TTL +ipt_ULOG +ipv6 +ip_vs +ip_vs_dh +ip_vs_ftp +ip_vs_lblc +ip_vs_lblcr +ip_vs_lc +ip_vs_nq +ip_vs_rr +ip_vs_sed +ip_vs_sh +ip_vs_wlc +ip_vs_wrr +ipw +ipw2100 +ipw2200 +ipwireless +ipx +ircomm +ir-common +ircomm-tty +irda +irda-usb +ir-kbd-i2c +irlan +irnet +irtty-sir +iscsi_ibft +iscsi_tcp +iscsi_trgt +isdn +isdn_bsdcomp +isdnhdlc +isight_firmware +isl6405 +isl6421 +isofs +isp116x-hcd +isp1760 +it87 +it8712f_wdt +iTCO_vendor_support +iTCO_wdt +itd1000 +ivtv +ivtvfb +iw_c2 +iw_cm +iw_cxgb3 +iwl3945 +iwlagn +iwlcore +ixgb +ixgbe +ixj +ixj_pcmcia +jbd +jbd2 +jedec_probe +jffs2 +jfs +joydev +joydump +jsm +k8temp +kafs +kahlua +kaweth +kbic +kbtab +kernelcapi +keyspan +keyspan_pda +keyspan_remote +khazad +kingsun-sir +kl5kusb105 +kobil_sct +konicawc +ks0108 +ks0127 +ks959-sir +ksdazzle-sir +ktti +kvm +kvm-amd +kvm-intel +kyrofb +l1oip +l2cap +l440gx +l64781 +lanai +lapb +lapbether +lcd +ldusb +lec +led-class +leds-gpio +leds-pca9532 +leds-pca955x +ledtrig-default-on +ledtrig-heartbeat +ledtrig-timer +legousbtower +lgdt330x +libata +libcrc32c +libertas +libertas_cs +libertas_sdio +libiscsi +libphy +libsas +libsrp +libusual +lightning +linear +lirc_atiusb +lirc_bt829 +lirc_cmdir +lirc_dev +lirc_i2c +lirc_igorplugusb +lirc_imon +lirc_it87 +lirc_mceusb +lirc_mceusb2 +lirc_pvr150 +lirc_sasem +lirc_serial +lirc_serial_igor +lirc_sir +lirc_streamzap +lirc_ttusbir +litelink-sir +lkkbd +llc2 +lm63 +lm70 +lm75 +lm77 +lm78 +lm80 +lm83 +lm85 +lm87 +lm90 +lm92 +lm93 +lmc +lmpcm_usb +lnbp21 +lockd +lock_dlm +loop +lp +lpfc +lrw +ltv350qv +lxfb +lxt +lzo +lzo_compress +lzo_decompress +m25p80 +m52790 +ma600-sir +mac80211 +machzwd +macmodes +macvlan +magellan +map_absent +map_funcs +map_ram +map_rom +marvell +matroxfb_accel +matroxfb_base +matroxfb_crtc2 +matroxfb_DAC1064 +matroxfb_g450 +matroxfb_maven +matroxfb_misc +matroxfb_Ti3026 +matrox_w1 +max1619 +max6650 +max6875 +max7301 +max732x +mbcache +mbp_nvidia_bl +mcp2120-sir +mcp23s08 +mcs7780 +mcs7830 +mct_u232 +md4 +mdc800 +mdio-bitbang +md-mod +megaraid +megaraid_mbox +megaraid_mm +megaraid_sas +meye +mga +michael_mic +microcode +microtek +mii +minix +mISDN_core +mISDN_dsp +mk712 +mkiss +mlx4_core +mlx4_ib +mmc_block +mmc_core +mmc_spi +mos7720 +mos7840 +moto_modem +moxa +mpoa +mptbase +mptctl +mptfc +mptlan +mptsas +mptscsih +mptspi +mpu401 +msdos +msi-laptop +msp3400 +msr +mt2060 +mt20xx +mt2131 +mt2266 +mt312 +mt352 +mt9m001 +mt9v022 +mtd +mtd_blkdevs +mtdblock +mtdblock_ro +mtdchar +mtdconcat +mtd_dataflash +mtdoops +mtdram +mtouch +multipath +mwave +mxb +mxl5005s +mxl5007t +mxser +myri10ge +nand +nand_ecc +nand_ids +nandsim +natsemi +navman +nbd +ncpfs +ndiswrapper +ne2k-pci +neofb +net1080 +net2280 +netconsole +netrom +netsc520 +nettel +netwave_cs +netxen_nic +newtonkbd +nf_conntrack +nf_conntrack_amanda +nf_conntrack_ftp +nf_conntrack_h323 +nf_conntrack_ipv4 +nf_conntrack_ipv6 +nf_conntrack_irc +nf_conntrack_netbios_ns +nf_conntrack_netlink +nf_conntrack_pptp +nf_conntrack_proto_gre +nf_conntrack_proto_sctp +nf_conntrack_proto_udplite +nf_conntrack_sip +nf_conntrack_tftp +nf_nat +nf_nat_amanda +nf_nat_ftp +nf_nat_h323 +nf_nat_irc +nf_nat_pptp +nf_nat_proto_gre +nf_nat_proto_sctp +nf_nat_proto_udplite +nf_nat_sip +nf_nat_snmp_basic +nf_nat_tftp +nfnetlink +nfnetlink_log +nfnetlink_queue +nfs +nfs_acl +nfsd +nftl +n_hdlc +niu +nls_ascii +nls_cp1250 +nls_cp1251 +nls_cp1255 +nls_cp437 +nls_cp737 +nls_cp775 +nls_cp850 +nls_cp852 +nls_cp855 +nls_cp857 +nls_cp860 +nls_cp861 +nls_cp862 +nls_cp863 +nls_cp864 +nls_cp865 +nls_cp866 +nls_cp869 +nls_cp874 +nls_cp932 +nls_cp936 +nls_cp949 +nls_cp950 +nls_euc-jp +nls_iso8859-1 +nls_iso8859-13 +nls_iso8859-14 +nls_iso8859-15 +nls_iso8859-2 +nls_iso8859-3 +nls_iso8859-4 +nls_iso8859-5 +nls_iso8859-6 +nls_iso8859-7 +nls_iso8859-9 +nls_koi8-r +nls_koi8-ru +nls_koi8-u +nls_utf8 +nmclan_cs +nozomi +n_r3964 +ns558 +ns83820 +nsc_gpio +nsc-ircc +ntfs +nvidiafb +nvram +nxt200x +nxt6000 +ocfs2 +ocfs2_dlm +ocfs2_dlmfs +ocfs2_nodemanager +ocfs2_stackglue +ocfs2_stack_o2cb +ocfs2_stack_user +ohci1394 +ohci-hcd +old_belkin-sir +olympic +omfs +omninet +on20 +on26 +onenand +onenand_sim +opl3 +oprofile +option +or51132 +or51211 +orinoco +orinoco_cs +orinoco_nortel +orinoco_pci +orinoco_plx +orinoco_tmd +osst +oti6858 +output +ov511 +ov511_decomp +ov518_decomp +ov7670 +ovcamchip +p54common +p54pci +p54usb +p80211 +p8023 +paride +parkbd +parport +parport_ax88796 +parport_cs +parport_pc +parport_serial +pas2 +pata_acpi +pata_ali +pata_amd +pata_artop +pata_atiixp +pata_cmd64x +pata_cs5520 +pata_cs5530 +pata_efar +pata_hpt366 +pata_hpt37x +pata_hpt3x3 +pata_it8213 +pata_it821x +pata_jmicron +pata_marvell +pata_mpiix +pata_netcell +pata_ninja32 +pata_ns87410 +pata_ns87415 +pata_oldpiix +pata_pcmcia +pata_pdc2027x +pata_pdc202xx_old +pata_rz1000 +pata_sch +pata_serverworks +pata_sil680 +pata_sis +pata_sl82c105 +pata_triflex +pata_via +pbe5 +pc300 +pc87360 +pc8736x_gpio +pc87413_wdt +pc87427 +pca953x +pcbc +pcd +pcf857x +pcf8591 +pci +pci200syn +pciehp +pci_hotplug +pcilynx +pcips2 +pci_slot +pcmcia +pcmcia_core +pcnet32 +pcnet_cs +pcspkr +pcwd_pci +pcwd_usb +pd +pd6729 +pda_power +pdc_adma +pegasus +penmount +pf +pg +phantom +phidget +phidgetkit +phidgetmotorcontrol +phidgetservo +phonedev +phram +physmap +pktcdvd +pktgen +pl2303 +platform_lcd +plat_nand +plat-ram +plip +plusb +pluto2 +pm2fb +pm3fb +pmc551 +powermate +powernow-k8 +ppa +ppdev +ppp_async +ppp_deflate +ppp_generic +ppp_mppe +pppoatm +pppoe +pppol2tp +pppox +ppp_synctty +prism2_usb +prism54 +processor +progear_bl +psmouse +pss +pt +pvrusb2 +pwc +qla1280 +qla2xxx +qla3xxx +qla4xxx +qlogic_cs +qlogicfas408 +qnx4 +qsemi +qt1010 +quickcam +quickcam_messenger +quota_v1 +quota_v2 +r128 +r8169 +r8a66597-hcd +radeon +radeonfb +radio-gemtek-pci +radio-maestro +radio-maxiradio +radio-si470x +raid0 +raid1 +raid10 +raid456 +raid_class +raw +raw1394 +ray_cs +rdma_cm +rdma_ucm +redboot +reed_solomon +reiserfs +rfc1051 +rfc1201 +rfcomm +rfd_ftl +rfkill +rfkill-input +ricoh_mmc +rio +rio500 +riscom8 +rivafb +rmd128 +rmd160 +rmd256 +rmd320 +rndis_host +rndis_wlan +rocket +romfs +rose +rpcsec_gss_krb5 +rpcsec_gss_spkm3 +rrunner +rsrc_nonstatic +rt2400pci +rt2500pci +rt2500usb +rt2x00lib +rt2x00pci +rt2x00usb +rt61pci +rt73usb +rtc-ds1305 +rtc-ds1307 +rtc-ds1374 +rtc-ds1553 +rtc-ds1672 +rtc-ds1742 +rtc-fm3130 +rtc-isl1208 +rtc-m41t80 +rtc-m41t94 +rtc-m48t59 +rtc-m48t86 +rtc-max6900 +rtc-max6902 +rtc-pcf8563 +rtc-pcf8583 +rtc-rs5c348 +rtc-rs5c372 +rtc-stk17ta8 +rtc-test +rtc-v3020 +rtc-x1205 +rtl8150 +rtl8180 +rtl8187 +rxkad +s1d13xxxfb +s2255drv +s2io +s3fb +s5h1409 +s5h1411 +s5h1420 +saa5246a +saa5249 +saa6588 +saa6752hs +saa7110 +saa7111 +saa7114 +saa7115 +saa7127 +saa7134 +saa7134-alsa +saa7134-dvb +saa7134-empress +saa7146 +saa7146_vv +saa717x +saa7185 +safe_serial +salsa20_generic +salsa20-x86_64 +sata_inic162x +sata_mv +sata_nv +sata_promise +sata_qstor +sata_sil +sata_sil24 +sata_sis +sata_svw +sata_sx4 +sata_uli +sata_via +sata_vsc +savage +savagefb +sb +sb1000 +sbc60xxwdt +sbc8360 +sbc_epx_c3 +sbc_gxx +sb_lib +sbni +sbp2 +sbs +sbshc +sc1200wdt +sc520cdp +sc520_wdt +sc92031 +scb2_flash +sch_atm +sch_cbq +sch_dsmark +sch_gred +sch_hfsc +sch_htb +sch_ingress +sch_netem +sch_prio +sch_red +sch_sfq +sch_tbf +sch_teql +sco +scsi_debug +scsi_dh +scsi_dh_alua +scsi_dh_emc +scsi_dh_hp_sw +scsi_dh_rdac +scsi_mod +scsi_tgt +scsi_transport_fc +scsi_transport_iscsi +scsi_transport_sas +scsi_transport_spi +scsi_transport_srp +scsi_wait_scan +sctp +sdhci +sdhci-pci +sdio_uart +sd_mod +sdricoh_cs +se401 +sedlbauer_cs +seed +seqiv +ser_gigaset +serial_cs +serio_raw +sermouse +serpent +serport +ses +sfc +sg +sha1_generic +sha256_generic +sha512_generic +sh_mobile_ceu_camera +shpchp +sidewinder +sierra +sir-dev +sis +sis190 +sis5595 +sis900 +sis-agp +sisfb +sisusbvga +sit +skfp +skge +sky2 +sl811_cs +sl811-hcd +slhc +slip +slram +sm501 +sm501fb +smbfs +smc91c92_cs +sms1xxx +smsc +smsc37b787_wdt +smsc47b397 +smsc47m1 +smsc47m192 +smsc-ircc2 +sn9c102 +snd +snd-ac97-codec +snd-ad1889 +snd-ak4114 +snd-ak4117 +snd-ak4xxx-adda +snd-ali5451 +snd-als300 +snd-als4000 +snd-atiixp +snd-atiixp-modem +snd-au8810 +snd-au8820 +snd-au8830 +snd-aw2 +snd-azt3328 +snd-bt87x +snd-bt-sco +snd-ca0106 +snd-cmipci +snd-cs4281 +snd-cs46xx +snd-cs5530 +snd-cs8427 +snd-darla20 +snd-darla24 +snd-dummy +snd-echo3g +snd-emu10k1 +snd-emu10k1-synth +snd-emu10k1x +snd-emux-synth +snd-ens1370 +snd-ens1371 +snd-es1938 +snd-es1968 +snd-fm801 +snd-gina20 +snd-gina24 +snd-hda-intel +snd-hdsp +snd-hdspm +snd-hifier +snd-hwdep +snd-i2c +snd-ice1712 +snd-ice1724 +snd-ice17xx-ak4xxx +snd-indigo +snd-indigodj +snd-indigoio +snd-intel8x0 +snd-intel8x0m +snd-korg1212 +snd-layla20 +snd-layla24 +snd-maestro3 +snd-mia +snd-mixart +snd-mixer-oss +snd-mona +snd-mpu401 +snd-mpu401-uart +snd-mtpav +snd-mts64 +snd-nm256 +snd-opl3-lib +snd-opl3-synth +snd-oxygen +snd-oxygen-lib +snd-page-alloc +snd-pcm +snd-pcm-oss +snd-pcsp +snd-pcxhr +snd-pdaudiocf +snd-portman2x4 +snd-pt2258 +snd-rawmidi +snd-riptide +snd-rme32 +snd-rme96 +snd-rme9652 +snd-sb16-dsp +snd-sb-common +snd-seq +snd-seq-device +snd-seq-dummy +snd-seq-midi +snd-seq-midi-emul +snd-seq-midi-event +snd-seq-oss +snd-seq-virmidi +snd-serial-u16550 +snd-soc-core +snd-sonicvibes +snd-tea575x-tuner +snd-timer +snd-trident +snd-usb-audio +snd-usb-caiaq +snd-usb-lib +snd-usb-usx2y +snd-util-mem +snd-via82xx +snd-via82xx-modem +snd-virmidi +snd-virtuoso +snd-vx222 +snd-vx-lib +snd-vxpocket +snd-ymfpci +soc_camera +soc_camera_platform +softcursor +softdog +sony-laptop +sound +soundcore +sound_firmware +sp8870 +sp887x +spaceball +spaceorb +spcp8x5 +specialix +spectrum_cs +speedtch +spi_bitbang +spi_butterfly +spidev +spi_lm70llp +squashfs +sr_mod +ssb +sscape +ssfdc +sstfb +st +starfire +stex +stinger +stir4200 +stkwebcam +stowaway +stp +stradis +strip +stv0297 +stv0299 +stv680 +sundance +sungem +sungem_phy +sunhme +suni +sunkbd +sunrpc +svcrdma +svgalib +sx +sx8 +sym53c500_cs +sym53c8xx +synclink +synclink_cs +synclink_gt +synclinkmp +syncppp +syscopyarea +sysfillrect +sysimgblt +sysv +t1pci +tcp_bic +tcp_highspeed +tcp_htcp +tcp_hybla +tcp_illinois +tcp_lp +tcp_probe +tcp_scalable +tcp_vegas +tcp_veno +tcp_westwood +tcp_yeah +tcrypt +tda10021 +tda10023 +tda10048 +tda1004x +tda10086 +tda18271 +tda7432 +tda8083 +tda826x +tda827x +tda8290 +tda9840 +tda9875 +tda9887 +tdfx +tdfxfb +tea +tea5761 +tea5767 +tea6415c +tea6420 +tehuti +tekram-sir +teles_cs +tg3 +tgr192 +thermal +thinkpad_acpi +thinkpad_ec +thmc50 +tifm_7xx1 +tifm_core +tifm_sd +tileblit +tipc +ti_usb_3410_5052 +tlan +tlclk +tle62x0 +tlsf +tlsup +tmdc +tms380tr +tmscsim +tmspci +touchit213 +touchright +touchwin +tpm +tpm_atmel +tpm_bios +tpm_infineon +tpm_nsc +tpm_tis +tps65010 +tp_smapi +trancevibrator +tridentfb +trix +ts5500_flash +ts_bm +ts_fsm +ts_kmp +tsl2550 +ttpci-eeprom +ttusb_dec +ttusbdecfe +tua6100 +tulip +tun +tuner +tuner-3036 +tuner-simple +tuner-types +tuner-xc2028 +tunnel4 +tunnel6 +turbografx +tvaudio +tveeprom +tvp5150 +twidjoy +twofish +twofish_common +twofish-x86_64 +typhoon +u132-hcd +uart401 +uart6850 +ub +ubi +ubifs +ucb1400_ts +udf +ueagle-atm +ufs +uhci-hcd +uinput +uio +uio_cif +uio_pdrv +uio_pdrv_genirq +uio_smx +uli526x +ultracam +umem +unionfs +upd64031a +upd64083 +uPD98402 +usb8xxx +usbatm +usbcore +usb_debug +usb_gigaset +usbhid +usbkbd +usblcd +usbled +usblp +usbmon +usbmouse +usbnet +usbserial +usb-storage +usbtouchscreen +usbvideo +usbvision +uss720 +uvcvideo +uvesafb +v4l1-compat +v4l2-common +v4l2-int-device +ves1820 +ves1x93 +vesafb +veth +vfat +vga16fb +vgastate +vgg2432a4 +via +via686a +via-agp +via_chrome9 +via-ircc +via-rhine +via-velocity +vicam +video +video1394 +videobuf-core +videobuf-dma-contig +videobuf-dma-sg +videobuf-dvb +videobuf-vmalloc +videocodec +videodev +virtio +virtio_balloon +virtio_blk +virtio_console +virtio_net +virtio_pci +virtio_ring +virtio-rng +visor +vitesse +vivi +vlsi_ir +v_midi +vmlfb +vp27smpx +vpx3220 +vsxxxaa +vt1211 +vt8231 +vt8623fb +w1_ds2433 +w1_ds2760 +w1-gpio +w1_smem +w1_therm +w83627ehf +w83627hf +w83627hf_wdt +w83697hf_wdt +w83781d +w83791d +w83792d +w83793 +w83877f_wdt +w83977af_ir +w83977f_wdt +w83l785ts +w83l786ng +w9966 +w9968cf +wacom +wafer5823wdt +wanrouter +wanxl +warrior +wavelan_cs +wbsd +wdt_pci +whiteheat +winbond-840 +wire +wl3501_cs +wm8739 +wm8775 +wm97xx-ts +wmi +wp512 +x25 +x25_asy +xc5000 +xcbc +xen-blkfront +xen-fbfront +xen-kbdfront +xen-netfront +xfrm4_mode_beet +xfrm4_mode_transport +xfrm4_mode_tunnel +xfrm4_tunnel +xfrm6_mode_beet +xfrm6_mode_ro +xfrm6_mode_transport +xfrm6_mode_tunnel +xfrm6_tunnel +xfrm_ipcomp +xfrm_user +xfs +xirc2ps_cs +xircom_cb +xor +xp +xpad +xpc +xpnet +xprtrdma +x_tables +xt_CLASSIFY +xt_comment +xt_connbytes +xt_connlimit +xt_connmark +xt_CONNMARK +xt_CONNSECMARK +xt_conntrack +xt_dccp +xt_dscp +xt_DSCP +xt_esp +xt_hashlimit +xt_helper +xt_iprange +xtkbd +xt_length +xt_limit +xt_mac +xt_mark +xt_MARK +xt_multiport +xt_NFLOG +xt_NFQUEUE +xt_NOTRACK +xt_owner +xt_physdev +xt_pkttype +xt_policy +xt_quota +xt_rateest +xt_RATEEST +xt_realm +xts +xt_sctp +xt_SECMARK +xt_state +xt_statistic +xt_string +xt_tcpmss +xt_TCPMSS +xt_tcpudp +xt_time +xt_TRACE +xt_u32 +xusbatm +yam +yealink +yellowfin +yenta_socket +zatm +zaurus +zc0301 +zd1201 +zd1211rw +zhenhua +zl10353 +zlib_deflate +zr36016 +zr36050 +zr36060 +zr36067 +zr364xx --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/amd64/generic.modules +++ linux-2.6.27/debian/abi/2.6.27-8.17/amd64/generic.modules @@ -0,0 +1,2072 @@ +3c359 +3c574_cs +3c589_cs +3c59x +3w-9xxx +3w-xxxx +6pack +8021q +8139cp +8139too +8390 +9p +9pnet +9pnet_virtio +a100u2w +a3d +aacraid +abituguru +abituguru3 +abyss +ac +ac97_bus +acecad +acenic +acer-wmi +acpi-cpufreq +acpiphp +acpiphp_ibm +acquirewdt +act200l-sir +act_gact +act_ipt +actisys-sir +act_mirred +act_nat +act_pedit +act_police +act_simple +acx +ad1848 +ad7414 +ad7418 +adcxx +adfs +adi +adm1021 +adm1025 +adm1026 +adm1029 +adm1031 +adm8211 +adm9240 +ads7828 +ads7846 +adt7470 +adt7473 +adutux +adv7170 +adv7175 +advansys +advantechwdt +aead +aedsp16 +aes_generic +aes-x86_64 +affs +af_key +af_packet +af-rxrpc +ah4 +ah6 +ahci +aic79xx +aic7xxx +aic94xx +aiptek +aircable +airo +airo_cs +alauda +ali-ircc +alim1535_wdt +alim7101_wdt +ambassador +amd76xrom +amd8111e +amd-rng +analog +anubis +aoe +appledisplay +appleir +applesmc +appletalk +appletouch +applicom +ar7part +arc4 +arcfb +arcmsr +arcnet +arc-rawmode +arc-rimi +ark3116 +arkfb +arptable_filter +arp_tables +arpt_mangle +asb100 +asix +asus-laptop +async_memcpy +async_tx +async_xor +at24 +at25 +at76_usb +ata_generic +ata_piix +aten +ath9k +ati_remote +ati_remote2 +atl1 +atl1e +atl2 +atlas_btns +atmel +atmel_cs +atmel_pci +atmtcp +atp +atp870u +atxp1 +aty128fb +atyfb +au0828 +au8522 +aufs +authenc +auth_rpcgss +autofs +autofs4 +av5100 +avma1_cs +avm_cs +ax25 +axnet_cs +b1 +b1dma +b1pci +b1pcmcia +b2c2-flexcop +b2c2-flexcop-pci +b2c2-flexcop-usb +b43 +b43legacy +b44 +bas_gigaset +battery +bay +baycom_par +baycom_ser_fdx +baycom_ser_hdx +bcm203x +bcm3510 +bcm5974 +befs +belkin_sa +berry_charge +bfs +bfusb +binfmt_misc +bitblit +block2mtd +blowfish +bluecard_cs +bluetooth +bnep +bnx2 +bnx2x +bonding +bpa10x +bpck +bpqether +br2684 +bridge +broadcom +bsd_comp +bt3c_cs +bt819 +bt856 +bt878 +btcx-risc +btsdio +bttv +btuart_cs +btusb +budget +budget-av +budget-ci +budget-core +budget-patch +BusLogic +button +bw-qcam +c4 +c67x00 +cafe_ccic +cafe_nand +camellia +capi +capidrv +capifs +capmode +carminefb +cassini +cast5 +cast6 +catc +cbc +cciss +ccm +cdc-acm +cdc_ether +cdc_subset +cdc-wdm +cdrom +cfag12864b +cfag12864bfb +cfg80211 +cfi_cmdset_0001 +cfi_cmdset_0002 +cfi_cmdset_0020 +cfi_probe +cfi_util +ch +ch341 +chipreg +cicada +cifs +cinergyT2 +cirrusfb +ck804xrom +cls_basic +cls_fw +cls_route +cls_rsvp +cls_rsvp6 +cls_tcindex +cls_u32 +cm4000_cs +cm4040_cs +cmtp +cobra +coda +com20020 +com20020_cs +com20020-pci +com90io +com90xx +comm +commandir +compal-laptop +compat_ioctl32 +compcache +configfs +container +coretemp +corgi_bl +cp2101 +cpcihp_generic +cpcihp_zt5550 +cpia +cpia2 +cpia_pp +cpia_usb +cpqarray +cpu5wdt +cpufreq_conservative +cpufreq_ondemand +cpufreq_powersave +cpufreq_stats +cpufreq_userspace +cpuid +c-qcam +cr_bllcd +crc16 +crc32c +crc7 +crc-ccitt +crc-itu-t +crc-t10dif +crvml +cryptd +crypto_blkcipher +cryptoloop +crypto_null +cs5345 +cs53l32a +ct82c710 +ctr +cts +cx18 +cx22700 +cx22702 +cx2341x +cx23885 +cx24110 +cx24123 +cx25840 +cx8800 +cx8802 +cx88-alsa +cx88-blackbird +cx88-dvb +cx88-vp3054-i2c +cx88xx +cxacru +cxgb +cxgb3 +cyber2000fb +cyberjack +cyclades +cyclomx +cycx_drv +cypress_cy7c63 +cypress_m8 +cytherm +DAC960 +davicom +db9 +dc395x +dca +dccp +dccp_ccid2 +dccp_ccid3 +dccp_diag +dccp_ipv4 +dccp_ipv6 +dccp_probe +dccp_tfrc_lib +dcdbas +de2104x +de4x5 +de600 +de620 +decnet +deflate +defxx +dell_rbu +des_generic +dib0070 +dib3000mb +dib3000mc +dib7000m +dib7000p +dibx000_common +digi_acceleport +dilnetpc +diskonchip +display +divacapi +divadidd +diva_idi +diva_mnt +divas +dlci +dlm +dm9601 +dm-bbr +dm-crypt +dme1737 +dmfe +dm-log +dm-loop +dm-mem-cache +dm-message +dm-mirror +dm-mod +dm-multipath +dm-raid4-5 +dm-region_hash +dm-round-robin +dm-snapshot +dmx3191d +dm-zero +dn_rtmsg +doc2000 +doc2001 +doc2001plus +docecc +dock +docprobe +dpc7146 +dpt_i2o +drbd +drm +drx397xD +ds1621 +ds1682 +ds2482 +ds2490 +ds2760_battery +dsbr100 +dscc4 +dss1_divert +dst +dst_ca +dstr +dtl1_cs +dummy +dv1394 +dvb-bt8xx +dvb-core +dvb-pll +dvb-ttpci +dvb-ttusb-budget +dvb-usb +dvb-usb-a800 +dvb-usb-af9005 +dvb-usb-af9005-remote +dvb-usb-anysee +dvb-usb-au6610 +dvb-usb-cxusb +dvb-usb-dib0700 +dvb-usb-dibusb-common +dvb-usb-dibusb-mb +dvb-usb-dibusb-mc +dvb-usb-digitv +dvb-usb-dtt200u +dvb-usb-dw2102 +dvb-usb-gl861 +dvb-usb-gp8psk +dvb-usb-m920x +dvb-usb-nova-t-usb2 +dvb-usb-opera +dvb-usb-ttusb2 +dvb-usb-umt-010 +dvb-usb-vp702x +dvb-usb-vp7045 +e100 +e1000 +e1000e +e752x_edac +eata +ebt_802_3 +ebtable_broute +ebtable_filter +ebtable_nat +ebtables +ebt_among +ebt_arp +ebt_arpreply +ebt_dnat +ebt_ip +ebt_ip6 +ebt_limit +ebt_log +ebt_mark +ebt_mark_m +ebt_nflog +ebt_pkttype +ebt_redirect +ebt_snat +ebt_stp +ebt_ulog +ebt_vlan +ecb +econet +ecryptfs +edac_core +eeepc-laptop +eepro100 +eeprom +eeprom_93cx6 +efs +ehci-hcd +elo +elsa_cs +em28xx +em28xx-alsa +em28xx-dvb +em_cmp +emi26 +emi62 +em_meta +em_nbyte +empeg +em_text +emu10k1-gp +em_u32 +enclosure +eni +epat +epca +epia +epic100 +eql +esb2rom +esi-sir +esp4 +esp6 +et131x +et61x251 +eth1394 +eurotechwdt +evbug +evdev +exportfs +ext2 +ext3 +ext4dev +f71805f +f71882fg +f75375s +fakephp +fan +farsync +fat +faulty +fbcon +fb_ddc +fb_sys_fops +fcrypt +fdomain +fdomain_cs +fealnx +ff-memless +firestream +fit2 +fit3 +floppy +fm801-gp +fmvj18x_cs +font +forcedeth +fore_200e +freevxfs +freq_table +friq +frpw +fsam7400 +fscher +fschmd +fscpos +ftdi-elan +ftdi_sio +ftl +fujitsu-laptop +fujitsu_ts +funsoft +fuse +g450_pll +gadgetfs +gamecon +gameport +garmin_gps +garp +g_cdc +gcm +gdth +generic_serial +gen_probe +g_ether +gf128mul +gf2k +g_file_storage +gfs +gfs2 +gigaset +girbil-sir +gl518sm +gl520sm +gl620a +gnbd +gpio_keys +gpio_mouse +grip +grip_mp +gru +g_serial +gspca_conex +gspca_etoms +gspca_main +gspca_mars +gspca_ov519 +gspca_pac207 +gspca_pac7311 +gspca_sonixb +gspca_sonixj +gspca_spca500 +gspca_spca501 +gspca_spca505 +gspca_spca506 +gspca_spca508 +gspca_spca561 +gspca_stk014 +gspca_sunplus +gspca_t613 +gspca_tv8532 +gspca_vc032x +gspca_zc3xx +gtco +guillemot +gunze +gx1fb +gxfb +g_zero +hamachi +hangcheck-timer +hci_uart +hci_vhci +hdaps +hdlc +hdlc_cisco +hdlcdrv +hdlc_fr +hdlc_ppp +hdlc_raw +hdlc_raw_eth +hdlc_x25 +he +heci +hecubafb +hermes +hexium_gemini +hexium_orion +hfc4s8s_l1 +hfcmulti +hfcpci +hfc_usb +hfs +hfsplus +hgafb +hid +hidp +hifn_795x +hisax +hisax_fcpcipnp +hisax_isac +hisax_st5481 +horizon +hostap +hostap_cs +hostap_pci +hostap_plx +hp100 +hp4x +hpfs +hpilo +hptiop +hp-wmi +hso +htc-pasic3 +hwmon-vid +hysdn +i2c-algo-bit +i2c-algo-pca +i2c-algo-pcf +i2c-ali1535 +i2c-ali1563 +i2c-ali15x3 +i2c-amd756 +i2c-amd756-s4882 +i2c-amd8111 +i2c-core +i2c-dev +i2c-gpio +i2c-i801 +i2c-isch +i2c-matroxfb +i2c-nforce2 +i2c-nforce2-s4985 +i2c-ocores +i2c-parport +i2c-parport-light +i2c-pca-platform +i2c-piix4 +i2c-simtec +i2c-sis5595 +i2c-sis630 +i2c-sis96x +i2c-stub +i2c-taos-evm +i2c-tiny-usb +i2c-via +i2c-viapro +i2c-voodoo3 +i2o_block +i2o_bus +i2o_config +i2o_core +i2o_proc +i2o_scsi +i3000_edac +i5000_edac +i5100_edac +i5k_amb +i6300esb +i810 +i82092 +i82975x_edac +i830 +i8k +i915 +ia32_aout +ib700wdt +ib_addr +ib_cm +ib_core +ib_ipath +ib_ipoib +ib_iser +ib_mad +ibmaem +ibmasm +ibmasr +ibmcam +ibmpex +ib_mthca +ib_sa +ib_srp +ib_ucm +ib_umad +ib_uverbs +ichxrom +icplus +idmouse +idt77252 +ieee1394 +ieee80211 +ieee80211_crypt +ieee80211_crypt_ccmp +ieee80211_crypt_tkip +ieee80211_crypt_wep +ifb +iforce +igb +ili9320 +imm +inet_lro +inexio +inftl +initio +input-polldev +intel-agp +intelfb +intel_menlow +intel-rng +intel_vr_nor +interact +ioatdma +ioc4 +io_edgeport +io_ti +iowarrior +ip2 +ip6_queue +ip6table_filter +ip6table_mangle +ip6table_raw +ip6_tables +ip6table_security +ip6t_ah +ip6t_eui64 +ip6t_frag +ip6t_hbh +ip6t_hl +ip6t_HL +ip6t_ipv6header +ip6t_LOG +ip6t_mh +ip6t_REJECT +ip6t_rt +ip6_tunnel +ipaq +ipcomp +ipcomp6 +ipddp +ipg +ip_gre +iphase +ipip +ipmi_devintf +ipmi_msghandler +ipmi_poweroff +ipmi_si +ipmi_watchdog +ip_queue +ipr +ips +iptable_filter +iptable_mangle +iptable_nat +iptable_raw +ip_tables +iptable_security +ipt_addrtype +ipt_ah +ipt_CLUSTERIP +ipt_ecn +ipt_ECN +ipt_LOG +ipt_MASQUERADE +ipt_NETMAP +ipt_recent +ipt_REDIRECT +ipt_REJECT +ipt_ttl +ipt_TTL +ipt_ULOG +ipv6 +ip_vs +ip_vs_dh +ip_vs_ftp +ip_vs_lblc +ip_vs_lblcr +ip_vs_lc +ip_vs_nq +ip_vs_rr +ip_vs_sed +ip_vs_sh +ip_vs_wlc +ip_vs_wrr +ipw +ipw2100 +ipw2200 +ipwireless +ipx +ircomm +ir-common +ircomm-tty +irda +irda-usb +ir-kbd-i2c +irlan +irnet +irtty-sir +iscsi_ibft +iscsi_tcp +iscsi_trgt +isdn +isdn_bsdcomp +isdnhdlc +isight_firmware +isl6405 +isl6421 +isofs +isp116x-hcd +isp1760 +it87 +it8712f_wdt +iTCO_vendor_support +iTCO_wdt +itd1000 +ivtv +ivtvfb +iw_c2 +iw_cm +iw_cxgb3 +iwl3945 +iwlagn +iwlcore +ixgb +ixgbe +ixj +ixj_pcmcia +jbd +jbd2 +jedec_probe +jffs2 +jfs +joydev +joydump +jsm +k8temp +kafs +kahlua +kaweth +kbic +kbtab +kernelcapi +keyspan +keyspan_pda +keyspan_remote +khazad +kingsun-sir +kl5kusb105 +kobil_sct +konicawc +ks0108 +ks0127 +ks959-sir +ksdazzle-sir +ktti +kvm +kvm-amd +kvm-intel +kyrofb +l1oip +l2cap +l440gx +l64781 +lanai +lapb +lapbether +lcd +ldusb +lec +led-class +leds-gpio +leds-pca9532 +leds-pca955x +ledtrig-default-on +ledtrig-heartbeat +ledtrig-timer +legousbtower +lgdt330x +libata +libcrc32c +libertas +libertas_cs +libertas_sdio +libiscsi +libphy +libsas +libsrp +libusual +lightning +linear +lirc_atiusb +lirc_bt829 +lirc_cmdir +lirc_dev +lirc_i2c +lirc_igorplugusb +lirc_imon +lirc_it87 +lirc_mceusb +lirc_mceusb2 +lirc_pvr150 +lirc_sasem +lirc_serial +lirc_serial_igor +lirc_sir +lirc_streamzap +lirc_ttusbir +litelink-sir +lkkbd +llc2 +lm63 +lm70 +lm75 +lm77 +lm78 +lm80 +lm83 +lm85 +lm87 +lm90 +lm92 +lm93 +lmc +lmpcm_usb +lnbp21 +lockd +lock_dlm +loop +lp +lpfc +lrw +ltv350qv +lxfb +lxt +lzo +lzo_compress +lzo_decompress +m25p80 +m52790 +ma600-sir +mac80211 +machzwd +macmodes +macvlan +magellan +map_absent +map_funcs +map_ram +map_rom +marvell +matroxfb_accel +matroxfb_base +matroxfb_crtc2 +matroxfb_DAC1064 +matroxfb_g450 +matroxfb_maven +matroxfb_misc +matroxfb_Ti3026 +matrox_w1 +max1619 +max6650 +max6875 +max7301 +max732x +mbcache +mbp_nvidia_bl +mcp2120-sir +mcp23s08 +mcs7780 +mcs7830 +mct_u232 +md4 +mdc800 +mdio-bitbang +md-mod +megaraid +megaraid_mbox +megaraid_mm +megaraid_sas +meye +mga +michael_mic +microcode +microtek +mii +minix +mISDN_core +mISDN_dsp +mk712 +mkiss +mlx4_core +mlx4_ib +mmc_block +mmc_core +mmc_spi +mos7720 +mos7840 +moto_modem +moxa +mpoa +mptbase +mptctl +mptfc +mptlan +mptsas +mptscsih +mptspi +mpu401 +msdos +msi-laptop +msp3400 +msr +mt2060 +mt20xx +mt2131 +mt2266 +mt312 +mt352 +mt9m001 +mt9v022 +mtd +mtd_blkdevs +mtdblock +mtdblock_ro +mtdchar +mtdconcat +mtd_dataflash +mtdoops +mtdram +mtouch +multipath +mwave +mxb +mxl5005s +mxl5007t +mxser +myri10ge +nand +nand_ecc +nand_ids +nandsim +natsemi +navman +nbd +ncpfs +ndiswrapper +ne2k-pci +neofb +net1080 +net2280 +netconsole +netrom +netsc520 +nettel +netwave_cs +netxen_nic +newtonkbd +nf_conntrack +nf_conntrack_amanda +nf_conntrack_ftp +nf_conntrack_h323 +nf_conntrack_ipv4 +nf_conntrack_ipv6 +nf_conntrack_irc +nf_conntrack_netbios_ns +nf_conntrack_netlink +nf_conntrack_pptp +nf_conntrack_proto_gre +nf_conntrack_proto_sctp +nf_conntrack_proto_udplite +nf_conntrack_sip +nf_conntrack_tftp +nf_nat +nf_nat_amanda +nf_nat_ftp +nf_nat_h323 +nf_nat_irc +nf_nat_pptp +nf_nat_proto_gre +nf_nat_proto_sctp +nf_nat_proto_udplite +nf_nat_sip +nf_nat_snmp_basic +nf_nat_tftp +nfnetlink +nfnetlink_log +nfnetlink_queue +nfs +nfs_acl +nfsd +nftl +n_hdlc +niu +nls_ascii +nls_cp1250 +nls_cp1251 +nls_cp1255 +nls_cp437 +nls_cp737 +nls_cp775 +nls_cp850 +nls_cp852 +nls_cp855 +nls_cp857 +nls_cp860 +nls_cp861 +nls_cp862 +nls_cp863 +nls_cp864 +nls_cp865 +nls_cp866 +nls_cp869 +nls_cp874 +nls_cp932 +nls_cp936 +nls_cp949 +nls_cp950 +nls_euc-jp +nls_iso8859-1 +nls_iso8859-13 +nls_iso8859-14 +nls_iso8859-15 +nls_iso8859-2 +nls_iso8859-3 +nls_iso8859-4 +nls_iso8859-5 +nls_iso8859-6 +nls_iso8859-7 +nls_iso8859-9 +nls_koi8-r +nls_koi8-ru +nls_koi8-u +nls_utf8 +nmclan_cs +nozomi +n_r3964 +ns558 +ns83820 +nsc_gpio +nsc-ircc +ntfs +nvidiafb +nvram +nxt200x +nxt6000 +ocfs2 +ocfs2_dlm +ocfs2_dlmfs +ocfs2_nodemanager +ocfs2_stackglue +ocfs2_stack_o2cb +ocfs2_stack_user +ohci1394 +ohci-hcd +old_belkin-sir +olympic +omfs +omninet +on20 +on26 +onenand +onenand_sim +opl3 +oprofile +option +or51132 +or51211 +orinoco +orinoco_cs +orinoco_nortel +orinoco_pci +orinoco_plx +orinoco_tmd +osst +oti6858 +output +ov511 +ov511_decomp +ov518_decomp +ov7670 +ovcamchip +p54common +p54pci +p54usb +p80211 +p8023 +paride +parkbd +parport +parport_ax88796 +parport_cs +parport_pc +parport_serial +pas2 +pata_acpi +pata_ali +pata_amd +pata_artop +pata_atiixp +pata_cmd64x +pata_cs5520 +pata_cs5530 +pata_efar +pata_hpt366 +pata_hpt37x +pata_hpt3x3 +pata_it8213 +pata_it821x +pata_jmicron +pata_marvell +pata_mpiix +pata_netcell +pata_ninja32 +pata_ns87410 +pata_ns87415 +pata_oldpiix +pata_pcmcia +pata_pdc2027x +pata_pdc202xx_old +pata_rz1000 +pata_sch +pata_serverworks +pata_sil680 +pata_sis +pata_sl82c105 +pata_triflex +pata_via +pbe5 +pc300 +pc87360 +pc8736x_gpio +pc87413_wdt +pc87427 +pca953x +pcbc +pcd +pcf857x +pcf8591 +pci +pci200syn +pciehp +pci_hotplug +pcilynx +pcips2 +pci_slot +pcmcia +pcmcia_core +pcnet32 +pcnet_cs +pcspkr +pcwd_pci +pcwd_usb +pd +pd6729 +pda_power +pdc_adma +pegasus +penmount +pf +pg +phantom +phidget +phidgetkit +phidgetmotorcontrol +phidgetservo +phonedev +phram +physmap +pktcdvd +pktgen +pl2303 +platform_lcd +plat_nand +plat-ram +plip +plusb +pluto2 +pm2fb +pm3fb +pmc551 +powermate +powernow-k8 +ppa +ppdev +ppp_async +ppp_deflate +ppp_generic +ppp_mppe +pppoatm +pppoe +pppol2tp +pppox +ppp_synctty +prism2_usb +prism54 +processor +progear_bl +psmouse +pss +pt +pvrusb2 +pwc +qla1280 +qla2xxx +qla3xxx +qla4xxx +qlogic_cs +qlogicfas408 +qnx4 +qsemi +qt1010 +quickcam +quickcam_messenger +quota_v1 +quota_v2 +r128 +r8169 +r8a66597-hcd +radeon +radeonfb +radio-gemtek-pci +radio-maestro +radio-maxiradio +radio-si470x +raid0 +raid1 +raid10 +raid456 +raid_class +raw +raw1394 +ray_cs +rdma_cm +rdma_ucm +redboot +reed_solomon +reiserfs +rfc1051 +rfc1201 +rfcomm +rfd_ftl +rfkill +rfkill-input +ricoh_mmc +rio +rio500 +riscom8 +rivafb +rmd128 +rmd160 +rmd256 +rmd320 +rndis_host +rndis_wlan +rocket +romfs +rose +rpcsec_gss_krb5 +rpcsec_gss_spkm3 +rrunner +rsrc_nonstatic +rt2400pci +rt2500pci +rt2500usb +rt2x00lib +rt2x00pci +rt2x00usb +rt61pci +rt73usb +rtc-ds1305 +rtc-ds1307 +rtc-ds1374 +rtc-ds1553 +rtc-ds1672 +rtc-ds1742 +rtc-fm3130 +rtc-isl1208 +rtc-m41t80 +rtc-m41t94 +rtc-m48t59 +rtc-m48t86 +rtc-max6900 +rtc-max6902 +rtc-pcf8563 +rtc-pcf8583 +rtc-rs5c348 +rtc-rs5c372 +rtc-stk17ta8 +rtc-test +rtc-v3020 +rtc-x1205 +rtl8150 +rtl8180 +rtl8187 +rxkad +s1d13xxxfb +s2255drv +s2io +s3fb +s5h1409 +s5h1411 +s5h1420 +saa5246a +saa5249 +saa6588 +saa6752hs +saa7110 +saa7111 +saa7114 +saa7115 +saa7127 +saa7134 +saa7134-alsa +saa7134-dvb +saa7134-empress +saa7146 +saa7146_vv +saa717x +saa7185 +safe_serial +salsa20_generic +salsa20-x86_64 +sata_inic162x +sata_mv +sata_nv +sata_promise +sata_qstor +sata_sil +sata_sil24 +sata_sis +sata_svw +sata_sx4 +sata_uli +sata_via +sata_vsc +savage +savagefb +sb +sb1000 +sbc60xxwdt +sbc8360 +sbc_epx_c3 +sbc_gxx +sb_lib +sbni +sbp2 +sbs +sbshc +sc1200wdt +sc520cdp +sc520_wdt +sc92031 +scb2_flash +sch_atm +sch_cbq +sch_dsmark +sch_gred +sch_hfsc +sch_htb +sch_ingress +sch_netem +sch_prio +sch_red +sch_sfq +sch_tbf +sch_teql +sco +scsi_debug +scsi_dh +scsi_dh_alua +scsi_dh_emc +scsi_dh_hp_sw +scsi_dh_rdac +scsi_mod +scsi_tgt +scsi_transport_fc +scsi_transport_iscsi +scsi_transport_sas +scsi_transport_spi +scsi_transport_srp +scsi_wait_scan +sctp +sdhci +sdhci-pci +sdio_uart +sd_mod +sdricoh_cs +se401 +sedlbauer_cs +seed +seqiv +ser_gigaset +serial_cs +serio_raw +sermouse +serpent +serport +ses +sfc +sg +sha1_generic +sha256_generic +sha512_generic +sh_mobile_ceu_camera +shpchp +sidewinder +sierra +sir-dev +sis +sis190 +sis5595 +sis900 +sis-agp +sisfb +sisusbvga +sit +skfp +skge +sky2 +sl811_cs +sl811-hcd +slhc +slip +slram +sm501 +sm501fb +smbfs +smc91c92_cs +sms1xxx +smsc +smsc37b787_wdt +smsc47b397 +smsc47m1 +smsc47m192 +smsc-ircc2 +sn9c102 +snd +snd-ac97-codec +snd-ad1889 +snd-ak4114 +snd-ak4117 +snd-ak4xxx-adda +snd-ali5451 +snd-als300 +snd-als4000 +snd-atiixp +snd-atiixp-modem +snd-au8810 +snd-au8820 +snd-au8830 +snd-aw2 +snd-azt3328 +snd-bt87x +snd-bt-sco +snd-ca0106 +snd-cmipci +snd-cs4281 +snd-cs46xx +snd-cs5530 +snd-cs8427 +snd-darla20 +snd-darla24 +snd-dummy +snd-echo3g +snd-emu10k1 +snd-emu10k1-synth +snd-emu10k1x +snd-emux-synth +snd-ens1370 +snd-ens1371 +snd-es1938 +snd-es1968 +snd-fm801 +snd-gina20 +snd-gina24 +snd-hda-intel +snd-hdsp +snd-hdspm +snd-hifier +snd-hwdep +snd-i2c +snd-ice1712 +snd-ice1724 +snd-ice17xx-ak4xxx +snd-indigo +snd-indigodj +snd-indigoio +snd-intel8x0 +snd-intel8x0m +snd-korg1212 +snd-layla20 +snd-layla24 +snd-maestro3 +snd-mia +snd-mixart +snd-mixer-oss +snd-mona +snd-mpu401 +snd-mpu401-uart +snd-mtpav +snd-mts64 +snd-nm256 +snd-opl3-lib +snd-opl3-synth +snd-oxygen +snd-oxygen-lib +snd-page-alloc +snd-pcm +snd-pcm-oss +snd-pcsp +snd-pcxhr +snd-pdaudiocf +snd-portman2x4 +snd-pt2258 +snd-rawmidi +snd-riptide +snd-rme32 +snd-rme96 +snd-rme9652 +snd-sb16-dsp +snd-sb-common +snd-seq +snd-seq-device +snd-seq-dummy +snd-seq-midi +snd-seq-midi-emul +snd-seq-midi-event +snd-seq-oss +snd-seq-virmidi +snd-serial-u16550 +snd-soc-core +snd-sonicvibes +snd-tea575x-tuner +snd-timer +snd-trident +snd-usb-audio +snd-usb-caiaq +snd-usb-lib +snd-usb-usx2y +snd-util-mem +snd-via82xx +snd-via82xx-modem +snd-virmidi +snd-virtuoso +snd-vx222 +snd-vx-lib +snd-vxpocket +snd-ymfpci +soc_camera +soc_camera_platform +softcursor +softdog +sony-laptop +sound +soundcore +sound_firmware +sp8870 +sp887x +spaceball +spaceorb +spcp8x5 +specialix +spectrum_cs +speedtch +spi_bitbang +spi_butterfly +spidev +spi_lm70llp +squashfs +sr_mod +ssb +sscape +ssfdc +sstfb +st +starfire +stex +stinger +stir4200 +stkwebcam +stowaway +stp +stradis +strip +stv0297 +stv0299 +stv680 +sundance +sungem +sungem_phy +sunhme +suni +sunkbd +sunrpc +svcrdma +svgalib +sx +sx8 +sym53c500_cs +sym53c8xx +synclink +synclink_cs +synclink_gt +synclinkmp +syncppp +syscopyarea +sysfillrect +sysimgblt +sysv +t1pci +tcp_bic +tcp_highspeed +tcp_htcp +tcp_hybla +tcp_illinois +tcp_lp +tcp_probe +tcp_scalable +tcp_vegas +tcp_veno +tcp_westwood +tcp_yeah +tcrypt +tda10021 +tda10023 +tda10048 +tda1004x +tda10086 +tda18271 +tda7432 +tda8083 +tda826x +tda827x +tda8290 +tda9840 +tda9875 +tda9887 +tdfx +tdfxfb +tea +tea5761 +tea5767 +tea6415c +tea6420 +tehuti +tekram-sir +teles_cs +tg3 +tgr192 +thermal +thinkpad_acpi +thinkpad_ec +thmc50 +tifm_7xx1 +tifm_core +tifm_sd +tileblit +tipc +ti_usb_3410_5052 +tlan +tlclk +tle62x0 +tlsf +tlsup +tmdc +tms380tr +tmscsim +tmspci +touchit213 +touchright +touchwin +tpm +tpm_atmel +tpm_bios +tpm_infineon +tpm_nsc +tpm_tis +tps65010 +tp_smapi +trancevibrator +tridentfb +trix +ts5500_flash +ts_bm +ts_fsm +ts_kmp +tsl2550 +ttpci-eeprom +ttusb_dec +ttusbdecfe +tua6100 +tulip +tun +tuner +tuner-3036 +tuner-simple +tuner-types +tuner-xc2028 +tunnel4 +tunnel6 +turbografx +tvaudio +tveeprom +tvp5150 +twidjoy +twofish +twofish_common +twofish-x86_64 +typhoon +u132-hcd +uart401 +uart6850 +ub +ubi +ubifs +ucb1400_ts +udf +ueagle-atm +ufs +uhci-hcd +uinput +uio +uio_cif +uio_pdrv +uio_pdrv_genirq +uio_smx +uli526x +ultracam +umem +unionfs +upd64031a +upd64083 +uPD98402 +usb8xxx +usbatm +usbcore +usb_debug +usb_gigaset +usbhid +usbkbd +usblcd +usbled +usblp +usbmon +usbmouse +usbnet +usbserial +usb-storage +usbtouchscreen +usbvideo +usbvision +uss720 +uvcvideo +uvesafb +v4l1-compat +v4l2-common +v4l2-int-device +ves1820 +ves1x93 +vesafb +veth +vfat +vga16fb +vgastate +vgg2432a4 +via +via686a +via-agp +via_chrome9 +via-ircc +via-rhine +via-velocity +vicam +video +video1394 +videobuf-core +videobuf-dma-contig +videobuf-dma-sg +videobuf-dvb +videobuf-vmalloc +videocodec +videodev +virtio +virtio_balloon +virtio_blk +virtio_console +virtio_net +virtio_pci +virtio_ring +virtio-rng +visor +vitesse +vivi +vlsi_ir +v_midi +vmlfb +vp27smpx +vpx3220 +vsxxxaa +vt1211 +vt8231 +vt8623fb +w1_ds2433 +w1_ds2760 +w1-gpio +w1_smem +w1_therm +w83627ehf +w83627hf +w83627hf_wdt +w83697hf_wdt +w83781d +w83791d +w83792d +w83793 +w83877f_wdt +w83977af_ir +w83977f_wdt +w83l785ts +w83l786ng +w9966 +w9968cf +wacom +wafer5823wdt +wanrouter +wanxl +warrior +wavelan_cs +wbsd +wdt_pci +whiteheat +winbond-840 +wire +wl3501_cs +wm8739 +wm8775 +wm97xx-ts +wmi +wp512 +x25 +x25_asy +xc5000 +xcbc +xen-blkfront +xen-fbfront +xen-kbdfront +xen-netfront +xfrm4_mode_beet +xfrm4_mode_transport +xfrm4_mode_tunnel +xfrm4_tunnel +xfrm6_mode_beet +xfrm6_mode_ro +xfrm6_mode_transport +xfrm6_mode_tunnel +xfrm6_tunnel +xfrm_ipcomp +xfrm_user +xfs +xirc2ps_cs +xircom_cb +xor +xp +xpad +xpc +xpnet +xprtrdma +x_tables +xt_CLASSIFY +xt_comment +xt_connbytes +xt_connlimit +xt_connmark +xt_CONNMARK +xt_CONNSECMARK +xt_conntrack +xt_dccp +xt_dscp +xt_DSCP +xt_esp +xt_hashlimit +xt_helper +xt_iprange +xtkbd +xt_length +xt_limit +xt_mac +xt_mark +xt_MARK +xt_multiport +xt_NFLOG +xt_NFQUEUE +xt_NOTRACK +xt_owner +xt_physdev +xt_pkttype +xt_policy +xt_quota +xt_rateest +xt_RATEEST +xt_realm +xts +xt_sctp +xt_SECMARK +xt_state +xt_statistic +xt_string +xt_tcpmss +xt_TCPMSS +xt_tcpudp +xt_time +xt_TRACE +xt_u32 +xusbatm +yam +yealink +yellowfin +yenta_socket +zatm +zaurus +zc0301 +zd1201 +zd1211rw +zhenhua +zl10353 +zlib_deflate +zr36016 +zr36050 +zr36060 +zr36067 +zr364xx --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/amd64/generic +++ linux-2.6.27/debian/abi/2.6.27-8.17/amd64/generic @@ -0,0 +1,8114 @@ +EXPORT_SYMBOL arch/x86/kvm/kvm 0xb6a40fbf kvm_cpu_has_pending_timer +EXPORT_SYMBOL arch/x86/kvm/kvm 0xd3a6cf78 kvm_read_guest_atomic +EXPORT_SYMBOL crypto/gf128mul 0x0c2f123f gf128mul_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x1068004b gf128mul_bbe +EXPORT_SYMBOL crypto/gf128mul 0x2f2889a0 gf128mul_init_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0x3755f990 gf128mul_init_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x384ef9ce gf128mul_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x56af0dbd gf128mul_x_ble +EXPORT_SYMBOL crypto/gf128mul 0x83581089 gf128mul_init_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0x9b2560b9 gf128mul_init_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x9e13f6f6 gf128mul_lle +EXPORT_SYMBOL crypto/gf128mul 0xbd17a0df gf128mul_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0xc0890413 gf128mul_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0xd60736ec gf128mul_free_64k +EXPORT_SYMBOL crypto/xor 0x5b6c00e6 xor_blocks +EXPORT_SYMBOL drivers/acpi/processor 0x0603377d acpi_processor_preregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0x8461fbfe acpi_processor_unregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0xcc337eed acpi_processor_notify_smm +EXPORT_SYMBOL drivers/acpi/processor 0xd78b77e1 acpi_processor_register_performance +EXPORT_SYMBOL drivers/acpi/processor 0xe8a3605f acpi_processor_set_thermal_limit +EXPORT_SYMBOL drivers/atm/suni 0xd3e7299a suni_init +EXPORT_SYMBOL drivers/atm/uPD98402 0x3edc4815 uPD98402_init +EXPORT_SYMBOL drivers/block/loop 0xbfee3ad5 loop_unregister_transfer +EXPORT_SYMBOL drivers/block/loop 0xcf881fae loop_register_transfer +EXPORT_SYMBOL drivers/block/paride/paride 0x25013aa1 pi_do_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0x38ed437c pi_release +EXPORT_SYMBOL drivers/block/paride/paride 0x50e50d6f pi_write_regr +EXPORT_SYMBOL drivers/block/paride/paride 0x53c0dbe1 pi_disconnect +EXPORT_SYMBOL drivers/block/paride/paride 0x77812371 paride_register +EXPORT_SYMBOL drivers/block/paride/paride 0x970aeb81 pi_init +EXPORT_SYMBOL drivers/block/paride/paride 0x9a585316 pi_read_regr +EXPORT_SYMBOL drivers/block/paride/paride 0xaa7a3854 pi_write_block +EXPORT_SYMBOL drivers/block/paride/paride 0xbf431b76 pi_schedule_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0xbfe35d8a pi_read_block +EXPORT_SYMBOL drivers/block/paride/paride 0xd3e5cea5 paride_unregister +EXPORT_SYMBOL drivers/block/paride/paride 0xe3890807 pi_connect +EXPORT_SYMBOL drivers/cdrom/cdrom 0x0b3fe3b7 cdrom_release +EXPORT_SYMBOL drivers/cdrom/cdrom 0x0c9ee323 cdrom_mode_sense +EXPORT_SYMBOL drivers/cdrom/cdrom 0x296214bd unregister_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0x45074893 register_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0x49284050 cdrom_get_media_event +EXPORT_SYMBOL drivers/cdrom/cdrom 0x4f476e96 init_cdrom_command +EXPORT_SYMBOL drivers/cdrom/cdrom 0xa467e472 cdrom_media_changed +EXPORT_SYMBOL drivers/cdrom/cdrom 0xa5283b53 cdrom_get_last_written +EXPORT_SYMBOL drivers/cdrom/cdrom 0xd210662e cdrom_mode_select +EXPORT_SYMBOL drivers/cdrom/cdrom 0xd242062a cdrom_open +EXPORT_SYMBOL drivers/cdrom/cdrom 0xde511722 cdrom_ioctl +EXPORT_SYMBOL drivers/cdrom/cdrom 0xf2108d74 cdrom_number_of_slots +EXPORT_SYMBOL drivers/char/generic_serial 0x0e049d30 gs_getserial +EXPORT_SYMBOL drivers/char/generic_serial 0x1a5c53a2 gs_flush_chars +EXPORT_SYMBOL drivers/char/generic_serial 0x20a17646 gs_write +EXPORT_SYMBOL drivers/char/generic_serial 0x265c1076 gs_got_break +EXPORT_SYMBOL drivers/char/generic_serial 0x2bed6446 gs_stop +EXPORT_SYMBOL drivers/char/generic_serial 0x41b705bc gs_put_char +EXPORT_SYMBOL drivers/char/generic_serial 0x4474023f gs_flush_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0x4a2144b3 gs_set_termios +EXPORT_SYMBOL drivers/char/generic_serial 0x515108b3 gs_chars_in_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0x935000f0 gs_setserial +EXPORT_SYMBOL drivers/char/generic_serial 0xb26a97f8 gs_close +EXPORT_SYMBOL drivers/char/generic_serial 0xb4c08446 gs_write_room +EXPORT_SYMBOL drivers/char/generic_serial 0xbb1e63b4 gs_block_til_ready +EXPORT_SYMBOL drivers/char/generic_serial 0xd30e7394 gs_hangup +EXPORT_SYMBOL drivers/char/generic_serial 0xf9207b39 gs_init_port +EXPORT_SYMBOL drivers/char/generic_serial 0xffed6eda gs_start +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0715ad27 ipmi_get_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0a6a132b ipmi_get_version +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x1ba3dad4 ipmi_set_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x1ce3dc1d ipmi_register_smi +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x25e9b58c ipmi_register_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x265a1b39 ipmi_smi_watchdog_pretimeout +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2d8686f4 ipmi_destroy_user +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x33138598 ipmi_set_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x3d93bbe9 ipmi_get_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x40f2b10c ipmi_alloc_smi_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x5a8a109b ipmi_smi_watcher_register +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x61d07c83 ipmi_set_gets_events +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x65aa95bd ipmi_request_supply_msgs +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x804f922a ipmi_addr_length +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x80c3ea9b ipmi_set_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x81d46def ipmi_request_settime +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x84c0526b ipmi_free_recv_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x9bb1e851 ipmi_unregister_smi +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xa1b909ac ipmi_smi_msg_received +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc0cbe7eb ipmi_unregister_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc85b64e9 ipmi_get_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xd559bd4d ipmi_create_user +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4c8ba05 ipmi_smi_add_proc_entry +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4f4665b ipmi_validate_addr +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe9675869 ipmi_smi_watcher_unregister +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xec361bb7 ipmi_poll_interface +EXPORT_SYMBOL drivers/char/nsc_gpio 0x207290f0 nsc_gpio_read +EXPORT_SYMBOL drivers/char/nsc_gpio 0x3c090386 nsc_gpio_dump +EXPORT_SYMBOL drivers/char/nsc_gpio 0x911cceae nsc_gpio_write +EXPORT_SYMBOL drivers/char/nvram 0x0f28cb91 nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x17ff2c1d __nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x2adec1e0 __nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x7da28f12 nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x9ce3f83f nvram_write_byte +EXPORT_SYMBOL drivers/char/nvram 0xa8813189 __nvram_write_byte +EXPORT_SYMBOL drivers/cpufreq/cpufreq_conservative 0x434e2f5f cpufreq_gov_conservative +EXPORT_SYMBOL drivers/cpufreq/cpufreq_ondemand 0x6a9cfc28 cpufreq_gov_ondemand +EXPORT_SYMBOL drivers/cpufreq/cpufreq_powersave 0xcd36ab09 cpufreq_gov_powersave +EXPORT_SYMBOL drivers/cpufreq/cpufreq_userspace 0x1df831c7 cpufreq_gov_userspace +EXPORT_SYMBOL drivers/edac/edac_core 0x2f92104e edac_mc_find +EXPORT_SYMBOL drivers/edac/edac_core 0xc1ead374 edac_mc_handle_fbd_ue +EXPORT_SYMBOL drivers/edac/edac_core 0xf6bde75d edac_mc_handle_fbd_ce +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0836695c drm_sman_takedown +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0c7eac99 drm_agp_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0x20645642 drm_debug +EXPORT_SYMBOL drivers/gpu/drm/drm 0x21451ac4 drm_sman_owner_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x232bdc50 drm_core_get_reg_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2916bf63 drm_sman_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2eb2f903 drm_sman_free_key +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2f8ade0a drm_pci_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3074f033 drm_order +EXPORT_SYMBOL drivers/gpu/drm/drm 0x30942ecd drm_mmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0x33bc76b3 drm_ioctl +EXPORT_SYMBOL drivers/gpu/drm/drm 0x369b254c drm_get_resource_start +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3d159d00 drm_core_reclaim_buffers +EXPORT_SYMBOL drivers/gpu/drm/drm 0x48a40a8b drm_pci_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0x5012ed9e drm_addbufs_agp +EXPORT_SYMBOL drivers/gpu/drm/drm 0x5221e3fd drm_agp_bind +EXPORT_SYMBOL drivers/gpu/drm/drm 0x55ca413a drm_idlelock_take +EXPORT_SYMBOL drivers/gpu/drm/drm 0x55f060ee drm_sman_set_range +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6b6bd23e drm_addbufs_pci +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6f8944c2 drm_fasync +EXPORT_SYMBOL drivers/gpu/drm/drm 0x709c286c drm_ati_pcigart_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x70d433ed drm_get_resource_len +EXPORT_SYMBOL drivers/gpu/drm/drm 0x75cd47f6 drm_vbl_send_signals +EXPORT_SYMBOL drivers/gpu/drm/drm 0x780c53f2 drm_agp_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0x8610a9dd drm_sg_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9a8543a7 drm_core_ioremapfree +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9b76add4 drm_compat_ioctl +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9c25b192 drm_core_get_map_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa36653d2 drm_core_ioremap_wc +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa6d94ca2 drm_core_ioremap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa6e04a07 drm_get_drawable_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0xaa4b8d96 drm_agp_enable +EXPORT_SYMBOL drivers/gpu/drm/drm 0xaf29788e drm_sman_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb23a0242 drm_exit +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb3ef7ffc drm_irq_uninstall +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb72e49ae drm_open +EXPORT_SYMBOL drivers/gpu/drm/drm 0xba33c377 drm_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc35f9568 drm_agp_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc913c1b5 drm_poll +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc99537f1 drm_addmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd2433566 drm_i_have_hw_lock +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3028e75 drm_sman_set_manager +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd924975e drm_getsarea +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe06ea6cc drm_idlelock_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe267fedc drm_agp_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe919dd5c drm_sman_owner_clean +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf1b10877 drm_rmmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf315470a drm_agp_acquire +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf3e5d708 drm_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf4341077 drm_ati_pcigart_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfcf5182c drm_locked_tasklet +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdc9b1b9 drm_agp_unbind +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdfbad19 drm_sman_alloc +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0x0903c239 vid_from_reg +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0xef1c781c vid_which_vrm +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x83bfe513 i2c_bit_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0xf27847d8 i2c_bit_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0x4f0e1244 i2c_pca_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0xee24900a i2c_pca_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pcf 0xbff8a04f i2c_pcf_add_bus +EXPORT_SYMBOL drivers/i2c/busses/i2c-amd756 0xb6ce3bf1 amd756_smbus +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x02d4ad0f tps65013_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x28485130 tps65010_config_vregs1 +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x33739de7 tps65010_set_vib +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x9fd44c69 tps65010_set_led +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xb14080cc tps65010_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xd5bb106d tps65010_set_vbus_draw +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xe99b3f36 tps65010_set_gpio_out_value +EXPORT_SYMBOL drivers/i2c/i2c-core 0x11eb5952 i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x35864ff2 i2c_master_send +EXPORT_SYMBOL drivers/i2c/i2c-core 0x45c4b342 i2c_smbus_read_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x55994d78 i2c_smbus_write_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x57489085 i2c_transfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0x5cd68967 i2c_smbus_read_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6773a7bb i2c_master_recv +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6e1900ac i2c_verify_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6e4db592 i2c_smbus_write_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x71d8d9f2 i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x8e6d4b75 i2c_register_driver +EXPORT_SYMBOL drivers/i2c/i2c-core 0x8ead13cf i2c_smbus_write_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x920cdf0a i2c_smbus_write_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0x9e0148bb i2c_detach_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x9e04ec05 i2c_smbus_read_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0xaa0ddde6 i2c_attach_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xb0b2d96a i2c_del_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xb6726786 i2c_get_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xba5956d4 i2c_put_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xbdcb6ad5 i2c_smbus_xfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0xd558294d i2c_add_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xd6939282 i2c_smbus_read_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0xde8be4f9 i2c_probe +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe06645a6 i2c_clients_command +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe14c53b7 i2c_use_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xeb8c4694 i2c_release_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xee914b23 i2c_del_driver +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x04680630 hpsb_destroy_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x056be1ac hpsb_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x088df759 hpsb_iso_recv_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0b234c4e dma_prog_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0c6da941 csr1212_release_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0d8e68a8 hpsb_unregister_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0e5a659c csr1212_new_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x110394aa hpsb_iso_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x11dd6ce9 hpsb_get_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x13b4a268 csr1212_attach_keyval_to_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x158ac548 dma_region_offset_to_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x168d2706 hpsb_alloc_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x18148340 hpsb_iso_n_ready +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x19f1f97b csr1212_parse_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1e931cb5 hpsb_get_hostinfo_bykey +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x20063a05 hpsb_resume_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2933cfc1 hpsb_create_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2b4eeacb hpsb_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2dd29f75 csr1212_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ebf6e5a dma_prog_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x31008801 hpsb_protocol_class +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3191c974 hpsb_iso_recv_release_packets +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x320a6985 hpsb_send_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x35a4916e hpsb_free_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3784fb59 hpsb_remove_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3e41541a hpsb_make_writepacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x416666b0 hpsb_unregister_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x484826b3 hpsb_register_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4a75c152 hpsb_set_packet_complete_task +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4fdbb421 hpsb_alloc_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x552ad218 hpsb_iso_stop +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x57dcc69f hpsb_update_config_rom_image +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5a689d9d hpsb_reset_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x625026a1 hpsb_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x672ad148 dma_region_sync_for_device +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6757ae29 hpsb_bus_reset +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x68561125 hpsb_node_fill_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6dabd92e hpsb_make_readpacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6e9920e8 hpsb_iso_recv_unlisten_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7328028c hpsb_iso_recv_flush +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x76bc1a5c dma_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7714ebd6 hpsb_iso_recv_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x79530b08 csr1212_get_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7f59d84b hpsb_iso_xmit_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8154a494 hpsb_node_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8879f8f0 dma_region_sync_for_cpu +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8ec2b312 dma_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x91da8413 hpsb_make_streampacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x978e8124 hpsb_set_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9b523756 hpsb_read_cycle_timer +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9e716efe hpsb_selfid_complete +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa0fdfb0c hpsb_unregister_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa4cfaefa hpsb_get_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa8fdd974 hpsb_iso_recv_listen_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa90de565 hpsb_iso_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaf7ce172 hpsb_allocate_and_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb4873145 hpsb_make_phypacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb5c9357b dma_region_mmap +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb68cb47a hpsb_packet_success +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xbf7cc767 hpsb_iso_shutdown +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc0cef6d2 hpsb_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc21c4ebc hpsb_update_config_rom +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc4ac84e2 hpsb_set_hostinfo_key +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc669a4d3 csr1212_detach_keyval_from_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcb1690bd hpsb_free_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcd9e772b dma_prog_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xce2d1f9c hpsb_iso_xmit_queue_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd376c0be hpsb_iso_wake +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd4875fa9 hpsb_iso_xmit_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xdd3630bf hpsb_make_lock64packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe356788e hpsb_add_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe608d4eb hpsb_selfid_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe72adfa1 hpsb_make_lockpacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xea4152ff dma_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xec68b660 __hpsb_register_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xef8afa96 hpsb_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xf1093281 hpsb_iso_recv_set_channel_mask +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfba57f51 hpsb_speedto_str +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfe5541c0 hpsb_iso_xmit_sync +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x187d5594 ohci1394_register_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x4ed04bc8 ohci1394_stop_context +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x7bff34a7 ohci1394_unregister_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xb37ab086 ohci1394_init_iso_tasklet +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x27ce491b rdma_translate_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x6aaa2fad rdma_addr_cancel +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x6e0915f2 rdma_resolve_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x71de06c2 rdma_addr_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x843c5216 rdma_copy_addr +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xbe81bb46 rdma_addr_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x04b169a8 ib_send_cm_rtu +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x0654b8e3 ib_send_cm_sidr_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x146dc20b ib_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x1544b3dc cm_class +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x2bacdf05 ib_send_cm_mra +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x42822045 ib_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x5adfd5c2 ib_cm_notify +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x65c20fdb ib_send_cm_lap +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x66a28bcc ib_send_cm_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x7f3a8018 ib_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x7fc620fb ib_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x8b0e79d8 ib_send_cm_apr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x8c411d0c ib_send_cm_rej +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x904a28e2 ib_send_cm_dreq +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xca836be5 ib_send_cm_sidr_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xde90e767 ib_send_cm_drep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xff2118be ib_send_cm_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x004d2a70 ib_umem_get +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x06830b9a ib_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0964c4da ib_modify_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0b248c8d ib_find_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0f957906 ib_query_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x10122270 ib_destroy_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1561cfce ib_fmr_pool_unmap +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1921fc61 ib_query_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1e491a04 ib_unmap_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1f58ecc1 ib_get_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x231a6e93 ib_alloc_fast_reg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x259834f1 ib_init_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2b8f6d54 ib_get_cached_lmc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2d345739 ib_fmr_pool_map_phys +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3506abbb ib_set_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x36848662 ib_register_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x373c6da1 ib_detach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3b5e707b ib_query_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3eb9d53f ib_query_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3f7567fd ib_rate_to_mult +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x4432c666 ib_rereg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x474ca838 ib_register_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x588a0061 ib_dealloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x592ca5ce ib_create_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x68882ef6 ib_umem_page_count +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6a2bb8f9 ib_destroy_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6b10f6ab ib_modify_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x704e804b ib_dereg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7235ee5d ib_destroy_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x728d4eea ib_modify_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x731b6898 ib_alloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x78b45481 ib_create_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7967e26e ib_dealloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7cf9419d ib_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x855a57ca ib_find_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x856dc8ae ib_get_dma_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8640eaeb ib_modify_qp_is_ok +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x86dc4a4c ib_create_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x87b614d8 ib_ud_header_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x95b6837c ib_create_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x960f762c ib_umem_release +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x96ce6c46 rdma_node_get_transport +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x99a2094a ib_dealloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d804fa1 mult_to_ib_rate +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa17c4d91 ib_query_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa5984d7b ib_alloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa73cb4ca ib_alloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xaa34acf0 ib_flush_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xab693bd0 ib_dealloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xadd9225d ib_get_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb07c55e4 ib_dispatch_event +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb3004b57 ib_modify_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb774bb9f ib_reg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb7b1f331 ib_query_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xbc1f0063 ib_find_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xc0e27f25 ib_destroy_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcabf41af ib_alloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcbad2f74 ib_destroy_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcfe26f98 ib_create_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd17ba9d1 ib_ud_header_init +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd77f8f39 ib_modify_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd93d3258 ib_attach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdc93a1f7 ib_unregister_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xddc775a0 ib_query_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdeda17d2 ib_get_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe3374fd3 ib_free_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe44a6d2b ib_unregister_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe4b25a7c ib_find_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe9ba86dd ib_alloc_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe9fd8052 ib_modify_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xed5ed015 ib_resize_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xee72ba70 ib_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf2d2bcae ib_query_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf36498b9 ib_ud_header_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf3e1ace5 ib_create_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf96fc9de ib_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x0fc9cca2 ib_modify_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x267035d0 ib_register_mad_snoop +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x3750239d ib_process_mad_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x4ac70f4f ib_unregister_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x52d45043 ib_create_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x56343a94 ib_redirect_mad_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6b63e17b ib_cancel_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6ef787ed ib_response_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6f077fcf ib_get_mad_data_offset +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x7b5d4b7a ib_is_mad_class_rmpp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xb13fd774 ib_get_rmpp_segment +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xe06ea7bd ib_register_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xe0916d6b ib_post_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xf1109a13 ib_free_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xf6ac6a5d ib_free_recv_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x12d2f9c2 ib_init_ah_from_mcmember +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x16199856 ib_sa_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x1f8df4ab ib_init_ah_from_path +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x3672be1b ib_sa_get_mcmember_rec +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x512ba124 ib_sa_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x576fdbac ib_sa_free_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xa3a2ff6e ib_sa_cancel_query +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xa487a41c ib_sa_service_rec_query +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xb99bf08c ib_sa_path_rec_get +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xd6315f72 ib_sa_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x02f847bc ib_copy_path_rec_from_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x07cf5a51 ib_copy_ah_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x18382f6a ib_copy_path_rec_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x184f3575 ib_copy_qp_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x0164358a iw_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x1422c606 iw_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x22d3f0a2 iw_cm_disconnect +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x54b8b621 iw_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x5c059721 iw_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x6cb1270b iw_cm_accept +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x838bc8ee iw_cm_reject +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xb77a1dd0 iw_cm_connect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x0419a7ca rdma_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x14fb7a11 rdma_create_qp +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x16e788b0 rdma_reject +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x2f7a2430 rdma_set_service_type +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x4446f20b rdma_resolve_route +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x595c6cc8 rdma_accept +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x5db2ff4b rdma_destroy_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x613ef179 rdma_set_ib_paths +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x724a2455 rdma_connect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x8032f06f rdma_disconnect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x9fb1b1aa rdma_notify +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xa8458c14 rdma_listen +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xae0f3e91 rdma_leave_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb11329f9 rdma_resolve_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb5c01a61 rdma_bind_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xcdf54013 rdma_create_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd31d1f0f rdma_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xf08ffdae rdma_destroy_qp +EXPORT_SYMBOL drivers/input/gameport/gameport 0x035e26b4 gameport_unregister_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0x3b5ec2eb gameport_unregister_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0x4898e54e __gameport_register_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0x710a1f30 gameport_close +EXPORT_SYMBOL drivers/input/gameport/gameport 0x988f0129 gameport_set_phys +EXPORT_SYMBOL drivers/input/gameport/gameport 0xab086f17 __gameport_register_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0xaf1e25bf gameport_open +EXPORT_SYMBOL drivers/input/gameport/gameport 0xe7cd08fa gameport_start_polling +EXPORT_SYMBOL drivers/input/gameport/gameport 0xf3dfecac gameport_stop_polling +EXPORT_SYMBOL drivers/input/input-polldev 0x566472e2 input_free_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xcfaebc0d input_unregister_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xf459885c input_allocate_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xfe1f83ab input_register_polled_device +EXPORT_SYMBOL drivers/isdn/capi/capifs 0x2c54c957 capifs_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/capifs 0xd0bc06ce capifs_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x04403fcf unregister_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x14f2aa5a capi20_get_version +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2b8eab1f capilib_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2baa6586 capilib_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x31c24aa4 capi20_isinstalled +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x3b3578ff capi_ctr_handle_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x47d3fc51 capi_info2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x47dbfa0a capi_message2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x50b33ca4 capi_cmsg2message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x56d99518 capi20_set_callback +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6057c6f3 capi_message2cmsg +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x62e32d43 capilib_data_b3_conf +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6d970af8 detach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6ed9b03f capi_ctr_suspend_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x71e8d5ba capilib_data_b3_req +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x788d398c capi_cmsg2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7a33596c capi20_get_serial +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7e6f1307 capi20_get_manufacturer +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x83092047 capi_ctr_ready +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8f699913 capilib_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8f71ada9 capi20_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x9f823278 register_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xaa165d27 capilib_release_appl +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xac3dc7a4 capi_ctr_reseted +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xada5fb07 capi20_put_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb19fda8d capi_cmd2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb60e5e5f capi_cmsg_header +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xc5327ee3 capi20_register +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xd5a982ef capi_ctr_resume_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe19a11ac capi20_get_profile +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe9640a93 attach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe9f62f29 cdebbuf_free +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xed061606 capi20_manufacturer +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x4fc40c21 b1_alloc_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x65f35e4f b1_getrevision +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x7efa651c b1_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x829bf3fe avmcard_dma_alloc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x85f09690 b1_irq_table +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x8af9867e b1_free_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x96f9d2f4 b1_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x9cc15157 b1_load_t4file +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xa372a74c b1_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xb6d6b17c avmcard_dma_free +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xc56b349e b1ctl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xce4e5aaf b1_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xcf7222b0 b1_load_config +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xd56d5012 b1_parse_version +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xd5fb157a b1_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xdfd28376 b1_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xf5ce1f3f b1_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xfb16ad93 b1_loaded +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x1675c45a t1pci_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x288f3c4a b1dma_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x295e6c95 b1dma_reset +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x2a386384 b1dma_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x317a5e50 b1dma_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x3bcaac3e b1pciv4_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x5ed0119d b1dma_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x7cfc0478 b1dmactl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x96274fce b1dma_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xe0181ac8 b1dma_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0x29562993 b1pcmcia_delcard +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xaec3240e b1pcmcia_addcard_m1 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xea620116 b1pcmcia_addcard_m2 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xf14bf8b1 b1pcmcia_addcard_b1 +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0x2974ead1 DIVA_DIDD_Read +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0xff3b8318 proc_net_eicon +EXPORT_SYMBOL drivers/isdn/hardware/mISDN/hfcmulti 0x5293ed86 plx_lock +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x07f4f2ce hisax_unregister +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x148f0c99 FsmFree +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x212b184f hisax_init_pcmcia +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x2844a899 FsmInitTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x93a64734 FsmChangeState +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x9df0cd27 FsmEvent +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xc0c558f9 FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xd94696e8 FsmDelTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xee93522c hisax_register +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xf0a16657 FsmNew +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xfc27303b HiSax_closecard +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x0b689858 isac_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x183005f8 isacsx_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x3f3b323a isac_d_l2l1 +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x49c0338f isac_init +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x935bbd27 isacsx_irq +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0xf874594e isac_irq +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x1ee629e2 isdnhdlc_rcv_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x95aed401 isdnhdlc_decode +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x9ffc8215 isdnhdlc_out_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0xf5c8131d isdnhdlc_encode +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x0f59ec6f isdn_ppp_register_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x1c49efa2 register_isdn +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xc6eb3fd3 isdn_ppp_unregister_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xfa06820f isdn_register_divert +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x0cda05e8 recv_Dchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x121a2d2b queue_ch_frame +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x2322ba99 mISDN_unregister_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x2348cc3c mISDN_FsmFree +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x305dcb83 get_next_dframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3e3bf4c2 get_next_bframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3e957c8a dchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3ea336fd mISDN_FsmAddTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x429129f2 mISDN_FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x469429f1 recv_Bchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x50c2230c mISDN_FsmChangeState +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6752033b mISDN_initdchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6b758763 mISDN_unregister_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6e23e131 recv_Bchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x7ec9c982 mISDN_register_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x81a3910d mISDN_freebchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x97863efb l1_event +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x996595fc mISDN_initbchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xace35cae mISDN_FsmDelTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xbbf229b8 mISDN_register_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xc15267d9 confirm_Bsend +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd5145151 mISDN_FsmEvent +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd9a7fbfd mISDN_FsmInitTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xe6ab7be9 mISDN_freedchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xe9d81796 recv_Dchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xf9e7832f mISDN_FsmNew +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xfdedee71 create_l1 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xfe88aa5a bchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x4c2ec443 mISDN_dsp_element_register +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x60721da7 dsp_audio_law_to_s32 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xa215f1b2 dsp_audio_s16_to_law +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xd3a023b8 mISDN_dsp_element_unregister +EXPORT_SYMBOL drivers/md/dm-log 0x1f3b2d7a dm_dirty_log_create +EXPORT_SYMBOL drivers/md/dm-log 0x38ec0daf dm_dirty_log_type_unregister +EXPORT_SYMBOL drivers/md/dm-log 0x4d1f6694 dm_dirty_log_type_register +EXPORT_SYMBOL drivers/md/dm-log 0x83efade3 dm_dirty_log_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x0056bbab dm_kcopyd_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0x15eb4b5a dm_unregister_target +EXPORT_SYMBOL drivers/md/dm-mod 0x1a1d7bed dm_io_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0x29a5385b dm_table_unplug_all +EXPORT_SYMBOL drivers/md/dm-mod 0x2a73bda8 dm_register_target +EXPORT_SYMBOL drivers/md/dm-mod 0x2d885944 dm_kcopyd_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x3103523c dm_table_get_md +EXPORT_SYMBOL drivers/md/dm-mod 0x44be23dc dm_table_get_size +EXPORT_SYMBOL drivers/md/dm-mod 0x59794a46 dm_get_device +EXPORT_SYMBOL drivers/md/dm-mod 0x62068ecb dm_get_mapinfo +EXPORT_SYMBOL drivers/md/dm-mod 0x6a94470c dm_table_get +EXPORT_SYMBOL drivers/md/dm-mod 0x82f65633 dm_io_client_resize +EXPORT_SYMBOL drivers/md/dm-mod 0x954c8af3 dm_io_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x9ae2adaa dm_table_event +EXPORT_SYMBOL drivers/md/dm-mod 0xa0115881 dm_io +EXPORT_SYMBOL drivers/md/dm-mod 0xbb7efdd2 dm_put_device +EXPORT_SYMBOL drivers/md/dm-mod 0xc79bcd36 dm_vcalloc +EXPORT_SYMBOL drivers/md/dm-mod 0xd92d6965 dm_table_put +EXPORT_SYMBOL drivers/md/dm-mod 0xdafb5eca dm_table_get_mode +EXPORT_SYMBOL drivers/md/dm-mod 0xf13c0837 dm_kcopyd_copy +EXPORT_SYMBOL drivers/md/md-mod 0x01a71c55 md_check_recovery +EXPORT_SYMBOL drivers/md/md-mod 0x0fc585b2 md_register_thread +EXPORT_SYMBOL drivers/md/md-mod 0x103b5521 md_wait_for_blocked_rdev +EXPORT_SYMBOL drivers/md/md-mod 0x1e383a74 bitmap_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0x47da3943 unregister_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0x51409eca bitmap_cond_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0x69d57564 md_unregister_thread +EXPORT_SYMBOL drivers/md/md-mod 0x707f756d bitmap_close_sync +EXPORT_SYMBOL drivers/md/md-mod 0x792bc41f md_write_start +EXPORT_SYMBOL drivers/md/md-mod 0x813010a2 register_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0x87791895 bitmap_startwrite +EXPORT_SYMBOL drivers/md/md-mod 0x8dc820c4 md_write_end +EXPORT_SYMBOL drivers/md/md-mod 0xa8b4d6e7 md_wakeup_thread +EXPORT_SYMBOL drivers/md/md-mod 0xb4a22f80 md_error +EXPORT_SYMBOL drivers/md/md-mod 0xb6cfb1af bitmap_unplug +EXPORT_SYMBOL drivers/md/md-mod 0xdb97ec5a md_done_sync +EXPORT_SYMBOL drivers/md/md-mod 0xe911c42e bitmap_endwrite +EXPORT_SYMBOL drivers/md/md-mod 0xfba3b7d9 bitmap_start_sync +EXPORT_SYMBOL drivers/media/common/tuners/mt2060 0xd204cfe7 mt2060_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2131 0x243892f9 mt2131_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2266 0x185fe6b8 mt2266_attach +EXPORT_SYMBOL drivers/media/common/tuners/mxl5005s 0x11312dbd mxl5005s_attach +EXPORT_SYMBOL drivers/media/common/tuners/qt1010 0x1d5e4d0b qt1010_attach +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0x0cb4b189 tuners +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0xc2821775 tuner_count +EXPORT_SYMBOL drivers/media/common/tuners/tuner-xc2028 0x49514733 xc2028_attach +EXPORT_SYMBOL drivers/media/common/tuners/xc5000 0x81e28a78 xc5000_attach +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x17628635 flexcop_device_kfree +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x1daae7bf flexcop_sram_ctrl +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x21cac457 flexcop_pass_dmx_data +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x2f0e883a flexcop_dma_xfer_control +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x333d6e39 flexcop_dma_control_timer_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x41b5c418 flexcop_dma_config_timer +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x44f568f5 flexcop_i2c_request +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x739a05be flexcop_eeprom_check_mac_addr +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x73f18b61 flexcop_dma_config +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x87ccfaaf flexcop_wan_set_speed +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xac037ec9 flexcop_sram_set_dest +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb28406dc flexcop_dma_control_size_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb44b47a1 flexcop_device_exit +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xd3a43db4 flexcop_pass_dmx_packets +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xdb151ded flexcop_device_initialize +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xdfa01aba flexcop_dump_reg +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xe1c483ff flexcop_dma_free +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xed6ea3b9 flexcop_device_kmalloc +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xf13e7f3e flexcop_dma_allocate +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x6ee7dc0f bt878 +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x8224583f bt878_start +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xd5d0bdef bt878_num +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xe9ef946a bt878_stop +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xedcc728d bt878_device_control +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x3ec95d82 dst_wait_dst_ready +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x441dc5c5 dst_attach +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x48154fc1 dst_error_bailout +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x49f20f68 dst_pio_disable +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x82af4f48 dst_comm_init +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xc4afd7b2 read_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xc9339448 dst_error_recovery +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xd686600b rdc_reset_state +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xe17ab117 write_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xe94b8c9c dst_check_sum +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst_ca 0x4574500f dst_ca_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x06a66320 dvb_net_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x0bccd3ae dvb_frontend_detach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x0c457c5c dvb_ringbuffer_flush_spinlock_wakeup +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x0f4b1233 dvb_register_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x10ba1261 dvb_unregister_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x1a4cb6dc dvb_generic_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x36c8ea1f dvb_frontend_sleep_until +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x42e01d94 dvb_ca_en50221_camchange_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x4db3899f dvb_dmx_swfilter_packets +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x50958ad4 dvb_unregister_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x51f3767c dvb_ringbuffer_read +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x55d0c68f dvb_frontend_reinitialise +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x5649dcda dvb_ca_en50221_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6988f784 dvb_ringbuffer_read_user +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6bbb7d7d dvb_unregister_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x74a5a698 dvb_filter_pes2ts_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x7c2c3da5 dvb_dmxdev_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x7c8f903a dvb_net_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x80e3832d dvb_filter_get_ac3info +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x8b49a23f timeval_usec_diff +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x93a76e15 dvb_generic_open +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xa0774422 dvb_dmxdev_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xaa72b6c5 dvb_register_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xac4ca1b0 intlog2 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb07f9a51 dvb_ca_en50221_frda_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xba2c8ee1 dvb_ca_en50221_camready_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xbb5605bb dvb_register_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc324b69b dvb_dmx_swfilter_204 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc80754c1 dvb_dmx_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xcb89fc7d dvb_ringbuffer_free +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xcca08cb5 dvb_ringbuffer_avail +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xcce0eeed dvb_ringbuffer_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xd05d3fee dvb_generic_ioctl +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xd639b9bc dvb_ringbuffer_write +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xd7765e69 dvb_ringbuffer_empty +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe3234dd3 dvb_ca_en50221_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe5ae8707 intlog10 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xee73de0a dvb_dmx_swfilter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xf826deb0 dvb_filter_pes2ts +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xf86f20c5 dvb_dmx_init +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x0393b31f dvb_usb_generic_write +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x58e20f63 dvb_usb_device_init +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x5e22deb3 dvb_usb_generic_rw +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x5f075c06 usb_cypress_load_firmware +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x6d6f0fc2 dvb_usb_nec_rc_key_to_event +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x8a412dc2 dvb_usb_get_hexline +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0xa16f8e1c dvb_usb_device_exit +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0x2edc4728 af9005_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0xc1f33b40 af9005_rc_decode +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0xd3383957 af9005_rc_keys_size +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x0fee6893 dibusb_read_eeprom_byte +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x1406e352 dibusb2_0_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x150d0e5f dibusb_rc_query +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x77fb0393 dibusb_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xad10b6a8 dibusb_pid_filter_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xb130eedc dibusb_dib3000mc_tuner_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xb5905684 dibusb_dib3000mc_frontend_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xbf166b2e dibusb2_0_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xcdc1bfc5 dibusb_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd1674eea dibusb_pid_filter +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd4d3dddc dibusb_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xfa3163c5 dibusb_i2c_algo +EXPORT_SYMBOL drivers/media/dvb/frontends/au8522 0x462bd9a0 au8522_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/bcm3510 0x03339406 bcm3510_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22700 0x2ee5db72 cx22700_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22702 0x566c0b0b cx22702_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24110 0xa5087cef cx24110_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0x0a1b40d8 cx24123_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0xaf799b2e cx24123_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0x5b236b1c dib0070_wbd_offset +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0x9c1e1e48 dib0070_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mb 0x5b12ac26 dib3000mb_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x4bdecef8 dib3000mc_pid_parse +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x518f0fb2 dib3000mc_set_config +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x578986b2 dib3000mc_pid_control +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x91b72971 dib3000mc_get_tuner_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xafe12325 dib3000mc_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xca05f5e2 dib3000mc_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x02ae9036 dib7000m_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x59b7af96 dib7000m_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0xac6e3024 dib7000m_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x5a9caab5 dib7000p_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x869ac61d dib7000pc_detection +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x9c6c5b88 dib7000p_set_gpio +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xa80250e4 dib7000p_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xb3820e97 dib7000p_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xd7e7873f dib7000p_set_wbd_ref +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0x42db0787 dibx000_init_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0xc8b22238 dibx000_get_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0xe6c25eb0 dibx000_exit_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/drx397xD 0xfd457fec drx397xD_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dvb-pll 0xd8023134 dvb_pll_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6405 0xe6a9182d isl6405_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6421 0x71298970 isl6421_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/itd1000 0x90a1a44f itd1000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/l64781 0x74f72efd l64781_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lgdt330x 0xa7e9c290 lgdt330x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lnbp21 0x29ea6a22 lnbp21_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt312 0x24230799 mt312_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt352 0x3817324b mt352_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt200x 0x5c1aa564 nxt200x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt6000 0xa71ee2c8 nxt6000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51132 0x83bbfb46 or51132_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51211 0xcacad09b or51211_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1409 0xfe684200 s5h1409_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1411 0x7eabc6c6 s5h1411_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0x5b253a53 s5h1420_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0xf2ee342c s5h1420_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/sp8870 0x352596b8 sp8870_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/sp887x 0xd637a724 sp887x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0297 0xab836214 stv0297_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0299 0xaf176d95 stv0299_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10021 0x922f9b10 tda10021_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10023 0xd7eda584 tda10023_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10048 0x434d855d tda10048_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0x086a0e5d tda10046_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0x739af687 tda10045_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10086 0x5f3405b8 tda10086_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda8083 0xec992d6d tda8083_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda826x 0xfc7008e9 tda826x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tua6100 0x11338e8a tua6100_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1820 0xb7bc5cb3 ves1820_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1x93 0x5c576a65 ves1x93_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/zl10353 0xbf104be5 zl10353_attach +EXPORT_SYMBOL drivers/media/dvb/ttpci/ttpci-eeprom 0x257acc92 ttpci_eeprom_parse_mac +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0x8489e335 ttusbdecfe_dvbs_attach +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0xaf4ee2ff ttusbdecfe_dvbt_attach +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x11dc4b6d bttv_gpio_enable +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x507622bd bttv_sub_register +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x76c9d789 bttv_sub_unregister +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x8ecf4acc bttv_write_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xbcf2d2fb bttv_read_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xbf4b1101 bttv_get_pcidev +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x3456dd5f btcx_riscmem_alloc +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x495e4b0c btcx_calc_skips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xad2fe38b btcx_sort_clips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xc368f8e6 btcx_align +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xcda0ded2 btcx_screen_clips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xfd39dc3a btcx_riscmem_free +EXPORT_SYMBOL drivers/media/video/cpia 0x69a120ae cpia_unregister_camera +EXPORT_SYMBOL drivers/media/video/cpia 0x857c4e49 cpia_register_camera +EXPORT_SYMBOL drivers/media/video/cx18/cx18 0x2cdea06d cx18_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/cx2341x 0x0224a947 cx2341x_update +EXPORT_SYMBOL drivers/media/video/cx2341x 0x3559ba71 cx2341x_ext_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0x8fdbede1 cx2341x_fill_defaults +EXPORT_SYMBOL drivers/media/video/cx2341x 0xcf8b77a4 cx2341x_mpeg_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0xde1da524 cx2341x_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx2341x 0xeacc6fab cx2341x_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/cx2341x 0xfb8bd71f cx2341x_log_status +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x3663d3c7 cx23885_get_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x3a4da341 cx23885_enum_input +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x440aeaa0 cx23885_set_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xe12fa84c cx23885_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xe19b1f2f cx23885_set_freq +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xfb885537 cx23885_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xfd7f4d0d cx23885_video_mux +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0x2dbcaf56 vp3054_i2c_probe +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0xd4d17f23 vp3054_i2c_remove +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x0666bc48 cx88_enum_input +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xa3304d11 cx88_set_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xac4e53b9 cx88_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xbd6e9fbb cx88_set_freq +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xbdbc79f5 cx8800_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xf71c10fe cx88_get_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xfd0effc2 cx88_video_mux +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x15845a8a cx8802_buf_queue +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x2636cd8e cx8802_buf_prepare +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x482c62db cx8802_get_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x56493b0b cx8802_cancel_buffers +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x676c2010 cx8802_register_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x796c6bb6 cx8802_unregister_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x89e30243 cx8802_get_device +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x08d19264 cx88_set_scale +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x09751616 cx88_set_tvnorm +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x1446d23b cx88_core_get +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x1662b45e cx88_vdev_init +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x275abcb5 cx88_core_irq +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x27ab4c7c cx88_shutdown +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x550c54c5 cx88_newstation +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x5bf81fb8 cx88_free_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7b5cdee1 cx88_tuner_callback +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7c704e69 cx88_get_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7d101d8a cx88_wakeup +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x904b8696 cx88_audio_thread +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x918b9c59 cx88_call_i2c_clients +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x96d77e91 cx88_risc_databuffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x974d1ab5 cx88_ir_start +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x9b140fff cx88_sram_channels +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xb3c7685f cx88_sram_channel_dump +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xb47f6cda cx88_print_irqbits +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xba1db23d cx88_set_tvaudio +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc2c78eaf cx88_core_put +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc77d3330 cx88_risc_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc9c953c5 cx88_ir_stop +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xcde42a36 cx88_set_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xe446f703 cx88_sram_channel_setup +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xf80f8637 cx88_risc_stopper +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xfd79e873 cx88_reset +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0x102de5d5 em28xx_register_extension +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0xf6552203 em28xx_unregister_extension +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x2797ecf1 gspca_dev_probe +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x2ed1b17e gspca_disconnect +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x5401a38e gspca_auto_gain_n_exposure +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x8df8ff77 gspca_frame_add +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x9670af2c gspca_debug +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0xa099de0c gspca_resume +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0xa87382c8 gspca_suspend +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0538e449 ivtv_cards_lock +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0924162b ivtv_api +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x14f67530 ivtv_debug +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x175fce32 ivtv_udma_alloc +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x24e38fe2 ivtv_cards +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x2d96c803 ivtv_udma_setup +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x2effad37 ivtv_vapi_result +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x70196ffb ivtv_cards_active +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xa771c06a ivtv_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xb19959a6 ivtv_set_irq_mask +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xb539197e ivtv_vapi +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xbd35b4a7 ivtv_init_on_first_open +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xd8e6bcdc ivtv_udma_unmap +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xddea26f3 ivtv_udma_prepare +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xecfbe7bc ivtv_clear_irq_mask +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x1211df5d saa7134_devlist +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x1773055d saa7134_tvaudio_setmute +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x2fba9bf6 saa7134_pgtable_build +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x5684a2eb saa7134_set_gpio +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x62bf6ca1 saa7134_pgtable_alloc +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x64b7c43d saa7134_dmasound_exit +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x67ffe4a7 saa7134_dmasound_init +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x6f342cb6 saa7134_pgtable_free +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x8122ea45 saa7134_set_dmabits +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x85593767 saa7134_tuner_callback +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x98af79c1 saa7134_boards +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xb16b1c09 saa7134_ts_unregister +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xe4dab64a saa7134_ts_register +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xf6bd440a saa_dsp_writel +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xf9b5bb04 saa7134_i2c_call_clients +EXPORT_SYMBOL drivers/media/video/soc_camera 0x01c40d5c soc_camera_device_unregister +EXPORT_SYMBOL drivers/media/video/soc_camera 0x0e4d94ee soc_camera_host_unregister +EXPORT_SYMBOL drivers/media/video/soc_camera 0x24de4198 soc_camera_host_register +EXPORT_SYMBOL drivers/media/video/soc_camera 0x3b0d261b soc_camera_video_stop +EXPORT_SYMBOL drivers/media/video/soc_camera 0x91dab7ab soc_camera_device_register +EXPORT_SYMBOL drivers/media/video/soc_camera 0xbf2e793e soc_camera_video_start +EXPORT_SYMBOL drivers/media/video/tveeprom 0x47997527 tveeprom_read +EXPORT_SYMBOL drivers/media/video/tveeprom 0xc7688f36 tveeprom_hauppauge_analog +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x16a2915c RingQueue_Dequeue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x1f8d78a7 usbvideo_TestPattern +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x3dd29cbd usbvideo_Deregister +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x407a321c RingQueue_WakeUpInterruptible +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x46d9e15a usbvideo_AllocateDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x852af129 usbvideo_DeinterlaceFrame +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x8d69204b usbvideo_register +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xb756bc2b usbvideo_RegisterVideoDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xddecac6d RingQueue_Enqueue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xf5011f67 RingQueue_Flush +EXPORT_SYMBOL drivers/media/video/v4l1-compat 0x7654a1ce v4l_compat_translate_ioctl +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x03165a85 v4l2_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x0dfb5e57 v4l2_prio_max +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x1c427ecb v4l2_ctrl_query_fill +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2de2b633 v4l2_prio_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2e9a955d v4l2_prio_close +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x42c8e001 v4l2_ctrl_next +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x57abfbd8 v4l2_chip_match_host +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x5fef1b4a v4l2_ctrl_query_fill_std +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x662d0e08 v4l2_chip_ident_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x942892ab v4l2_prio_open +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x94d3dd7b v4l2_chip_match_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xb2d1e17e v4l2_prio_change +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xc369097d v4l2_ctrl_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xd464e760 v4l2_ctrl_query_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xe330bce9 v4l2_prio_init +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xfcd2b56f v4l2_i2c_attach +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0x3b38986a videobuf_dvb_unregister +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0x9f271de4 videobuf_dvb_register +EXPORT_SYMBOL drivers/media/video/videocodec 0x1cef83e6 videocodec_detach +EXPORT_SYMBOL drivers/media/video/videocodec 0x1fa1a848 videocodec_unregister +EXPORT_SYMBOL drivers/media/video/videocodec 0x7124aaa6 videocodec_attach +EXPORT_SYMBOL drivers/media/video/videocodec 0xb1088af6 videocodec_register +EXPORT_SYMBOL drivers/media/video/videodev 0x0c4762b4 video_device_release +EXPORT_SYMBOL drivers/media/video/videodev 0x123959a1 v4l2_type_names +EXPORT_SYMBOL drivers/media/video/videodev 0x223430ec video_devdata +EXPORT_SYMBOL drivers/media/video/videodev 0x28ee084b video_ioctl2 +EXPORT_SYMBOL drivers/media/video/videodev 0x3495bb68 video_register_device +EXPORT_SYMBOL drivers/media/video/videodev 0x3adbd595 v4l2_field_names +EXPORT_SYMBOL drivers/media/video/videodev 0x5242fca7 video_register_device_index +EXPORT_SYMBOL drivers/media/video/videodev 0x5ebefe4b v4l_printk_ioctl +EXPORT_SYMBOL drivers/media/video/videodev 0xae86a3e9 video_exclusive_open +EXPORT_SYMBOL drivers/media/video/videodev 0xbc211eb8 video_usercopy +EXPORT_SYMBOL drivers/media/video/videodev 0xe1682b09 video_device_alloc +EXPORT_SYMBOL drivers/media/video/videodev 0xe1f10b23 video_unregister_device +EXPORT_SYMBOL drivers/media/video/videodev 0xe2b92059 v4l2_video_std_construct +EXPORT_SYMBOL drivers/media/video/videodev 0xee1076f2 video_exclusive_release +EXPORT_SYMBOL drivers/media/video/videodev 0xf3251e7b v4l2_norm_to_name +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x0c99314d mpt_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x105d4f47 mpt_add_sge +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x2f16defb mpt_free_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x2f80f5f9 mptbase_sas_persist_operation +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x304b9c68 mpt_alloc_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x3109e6a5 mpt_free_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x35174349 mpt_attach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x3c368b63 mpt_HardResetHandler +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4526289b mpt_event_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4ea7ab21 mpt_put_msg_frame_hi_pri +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x8220d246 mpt_get_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x8fa31005 mpt_suspend +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x923de435 mpt_detach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x95cfa048 mpt_GetIocState +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x964b2ceb mpt_verify_adapter +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xa980f3b8 mpt_reset_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xb4250c9e mpt_resume +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc0e69f82 mpt_device_driver_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc47c22e8 mpt_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd45190a7 mpt_print_ioc_summary +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd4867f27 mpt_findImVolumes +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd9a92a75 mpt_reset_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdd805159 ioc_list +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe1137a1e mpt_config +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe5770ccc mpt_send_handshake_request +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xeb853fd7 mpt_device_driver_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xee556142 mpt_raid_phys_disk_pg0 +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xf0c7cbbb mpt_event_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xf649023a mpt_put_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x06867bcf mptscsih_bios_param +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x1dfb1146 mptscsih_bus_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x2ef94c87 mptscsih_slave_destroy +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x30570756 mptscsih_scandv_complete +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x313630ed mptscsih_proc_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x3bc1b970 mptscsih_qcmd +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x40e04ef0 mptscsih_io_done +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x51e8a2d8 mptscsih_TMHandler +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x53661a50 mptscsih_slave_configure +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x59e3e168 mptscsih_host_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6ec3fe5f mptscsih_shutdown +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6f087264 mptscsih_dev_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x714d2d1d mptscsih_host_attrs +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x71fef407 mptscsih_remove +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x764ddf1a mptscsih_timer_expired +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x7732cd97 mptscsih_abort +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x79bbcb9c mptscsih_raid_id_to_num +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xb576d2fe mptscsih_resume +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xb87fd587 mptscsih_event_process +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xbaf9bcef mptscsih_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xc0564663 mptscsih_is_phys_disk +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe20ed894 mptscsih_change_queue_depth +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe452c9e8 mptscsih_suspend +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xedc93803 mptscsih_ioc_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xf7b68589 mptscsih_taskmgmt_complete +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x0db26b8f i2o_driver_notify_device_remove_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x1aba1919 i2o_parm_field_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x23520576 i2o_parm_table_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x260a3d8f i2o_parm_issue +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2a843bef i2o_dump_message +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x377b7d21 i2o_cntxt_list_get_ptr +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x3ad6d0cf i2o_driver_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x3e589e94 i2o_driver_unregister +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x42987e0b i2o_driver_notify_controller_remove_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x4fe04c5e i2o_msg_post_wait_mem +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x53545de1 i2o_find_iop +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x69d4cc55 i2o_device_claim +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x9e354057 i2o_iop_find_device +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xa271b0ad i2o_cntxt_list_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xa9425d95 i2o_cntxt_list_remove +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb21ce57b i2o_exec_lct_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb4c00dcf i2o_controllers +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xbb697865 i2o_msg_get_wait +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xc1814fb6 i2o_event_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xd6228d6e i2o_device_claim_release +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xd75cf121 i2o_status_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xe172b1ab i2o_driver_notify_device_add_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xeb70c8f2 i2o_cntxt_list_add +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xf37fcea1 i2o_driver_notify_controller_add_all +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x0f51d084 pasic3_write_register +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x6e41ded3 pasic3_read_register +EXPORT_SYMBOL drivers/misc/ioc4 0x4dc73f77 ioc4_unregister_submodule +EXPORT_SYMBOL drivers/misc/ioc4 0x545c5bb5 ioc4_register_submodule +EXPORT_SYMBOL drivers/misc/sony-laptop 0x5bb1e117 sony_pic_camera_command +EXPORT_SYMBOL drivers/misc/tifm_core 0x102c481d tifm_free_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0x3e9fa511 tifm_free_device +EXPORT_SYMBOL drivers/misc/tifm_core 0x3ef4f81f tifm_unmap_sg +EXPORT_SYMBOL drivers/misc/tifm_core 0x4660af57 tifm_remove_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0x805fdc5a tifm_alloc_device +EXPORT_SYMBOL drivers/misc/tifm_core 0xa63a3d65 tifm_add_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0xa65404aa tifm_map_sg +EXPORT_SYMBOL drivers/misc/tifm_core 0xa8c2ec46 tifm_queue_work +EXPORT_SYMBOL drivers/misc/tifm_core 0xac825ebe tifm_eject +EXPORT_SYMBOL drivers/misc/tifm_core 0xb3e8bc33 tifm_register_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0xd903f0e4 tifm_has_ms_pif +EXPORT_SYMBOL drivers/misc/tifm_core 0xe902efc7 tifm_unregister_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0xf53ccd64 tifm_alloc_adapter +EXPORT_SYMBOL drivers/mmc/card/mmc_block 0x4f9350d0 mmc_cleanup_queue +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x0593b08d mmc_resume_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x186f189a mmc_wait_for_req +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x1aa7bc4b mmc_unregister_driver +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x2bde8859 mmc_suspend_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x2eb32e3f mmc_align_data_size +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x46208123 mmc_remove_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x52a0d94b mmc_set_data_timeout +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x58ba654b mmc_free_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x5a3adf4c __mmc_claim_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x609e45d4 mmc_wait_for_app_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x6b1bcf5f mmc_add_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x928ee936 mmc_detect_change +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x9f914436 mmc_request_done +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xaf5f226c mmc_wait_for_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xb2aef807 mmc_alloc_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xde098a48 mmc_release_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xf86a6aa2 mmc_register_driver +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x2b685181 cfi_fixup +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x87e37c41 cfi_varsize_frob +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0xf07bfaa7 cfi_read_pri +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x6d01b9fa map_destroy +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xb34366f0 do_map_probe +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xc9da98fe unregister_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xea12a65f register_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/gen_probe 0xe6a9a89f mtd_do_chip_probe +EXPORT_SYMBOL drivers/mtd/maps/map_funcs 0xf493222a simple_map_init +EXPORT_SYMBOL drivers/mtd/mtd 0xc5ea1aa7 add_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtd 0xf3edb1e3 del_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtdconcat 0x3f62ef94 mtd_concat_destroy +EXPORT_SYMBOL drivers/mtd/mtdconcat 0xb0d26226 mtd_concat_create +EXPORT_SYMBOL drivers/mtd/nand/nand 0x4a05f8be nand_scan_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand 0xc3af03b0 nand_default_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x254f230c nand_calculate_ecc +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x87406d9d nand_correct_data +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0x836bdb72 nand_flash_ids +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0xa336feb7 nand_manuf_ids +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0x9926269f onenand_default_bbt +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xda3a6e1b onenand_scan_bbt +EXPORT_SYMBOL drivers/net/8390 0x1ef83b21 ei_poll +EXPORT_SYMBOL drivers/net/8390 0x3a61b49a ei_open +EXPORT_SYMBOL drivers/net/8390 0x7d7e0dbc ei_interrupt +EXPORT_SYMBOL drivers/net/8390 0xa709106e __alloc_ei_netdev +EXPORT_SYMBOL drivers/net/8390 0xd300acec NS8390_init +EXPORT_SYMBOL drivers/net/8390 0xdd4045fc ei_close +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x17761137 arc_bcast_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x2fb353f8 arc_proto_map +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4641bd7d arcnet_interrupt +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4baed961 arcnet_unregister_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x6534792a arcnet_debug +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xa55ffed1 alloc_arcdev +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xa9f9359d arc_proto_default +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xd22ab221 arc_raw_proto +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x0b4b9a33 com20020_found +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x488ef2ac com20020_check +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x1e209750 cxgb3_insert_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x221eb01d t3_l2t_get +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x24dfd24f cxgb3_remove_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x306cfa95 cxgb3_alloc_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x470f52d0 t3_l2t_send_slow +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x4796f0a3 cxgb3_ofld_send +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x51e09827 t3_l2e_free +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x63054854 cxgb3_unregister_client +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x744f76c9 cxgb3_free_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8b7b1f57 cxgb3_free_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8e0a1e3b t3_register_cpl_handler +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x98f460c1 dev2t3cdev +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xb813480d t3_l2t_send_event +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xc91b78a6 cxgb3_alloc_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xd3fb3028 cxgb3_queue_tid_release +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xf78c8e0b cxgb3_register_client +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x3424801c hdlcdrv_transmitter +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x9079baf8 hdlcdrv_unregister +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x9b594ea0 hdlcdrv_receiver +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xc72bca8f hdlcdrv_register +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xfe3aa16a hdlcdrv_arbitrate +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x01bd46bc sirdev_write_complete +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x095545f9 sirdev_raw_write +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x105de418 irda_unregister_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x2cb62110 sirdev_get_instance +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x9b594077 sirdev_set_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x9deffbe7 irda_register_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xbd94bb98 sirdev_put_instance +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xbed04329 sirdev_raw_read +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xd70a73fd sirdev_receive +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf6f49d0e sirdev_set_dtr_rts +EXPORT_SYMBOL drivers/net/mii 0x2848f244 generic_mii_ioctl +EXPORT_SYMBOL drivers/net/mii 0x6249df60 mii_check_media +EXPORT_SYMBOL drivers/net/mii 0x7c4fbfe8 mii_check_link +EXPORT_SYMBOL drivers/net/mii 0x86f7a969 mii_nway_restart +EXPORT_SYMBOL drivers/net/mii 0x9b9e1ccf mii_ethtool_sset +EXPORT_SYMBOL drivers/net/mii 0xb496f252 mii_check_gmii_support +EXPORT_SYMBOL drivers/net/mii 0xc2475d92 mii_ethtool_gset +EXPORT_SYMBOL drivers/net/mii 0xe64abc8a mii_link_ok +EXPORT_SYMBOL drivers/net/phy/libphy 0x21959176 phy_device_create +EXPORT_SYMBOL drivers/net/phy/libphy 0x2f6ce079 phy_write +EXPORT_SYMBOL drivers/net/phy/libphy 0x320fe178 phy_stop_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x3839b61c genphy_config_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0x3d2cd3d5 phy_register_fixup_for_uid +EXPORT_SYMBOL drivers/net/phy/libphy 0x405df8ed phy_disconnect +EXPORT_SYMBOL drivers/net/phy/libphy 0x42b91e7c phy_disable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x479c38ed phy_stop +EXPORT_SYMBOL drivers/net/phy/libphy 0x4d233e89 phy_driver_unregister +EXPORT_SYMBOL drivers/net/phy/libphy 0x4f272b5a get_phy_id +EXPORT_SYMBOL drivers/net/phy/libphy 0x55870ae0 phy_mii_ioctl +EXPORT_SYMBOL drivers/net/phy/libphy 0x5a021596 phy_scan_fixups +EXPORT_SYMBOL drivers/net/phy/libphy 0x5fed0a60 genphy_update_link +EXPORT_SYMBOL drivers/net/phy/libphy 0x687cd8fe phy_print_status +EXPORT_SYMBOL drivers/net/phy/libphy 0x69a8ae1d phy_driver_register +EXPORT_SYMBOL drivers/net/phy/libphy 0x6b174600 phy_ethtool_gset +EXPORT_SYMBOL drivers/net/phy/libphy 0x7455a58a phy_register_fixup +EXPORT_SYMBOL drivers/net/phy/libphy 0x8c8198b0 phy_attach +EXPORT_SYMBOL drivers/net/phy/libphy 0x952aff79 mdiobus_register +EXPORT_SYMBOL drivers/net/phy/libphy 0x97150601 mdio_bus_type +EXPORT_SYMBOL drivers/net/phy/libphy 0x9d9e6ab6 phy_start +EXPORT_SYMBOL drivers/net/phy/libphy 0xa2e83f0a phy_enable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0xa3ddee4d genphy_read_status +EXPORT_SYMBOL drivers/net/phy/libphy 0xa4c7df96 phy_sanitize_settings +EXPORT_SYMBOL drivers/net/phy/libphy 0xa71e789f phy_register_fixup_for_id +EXPORT_SYMBOL drivers/net/phy/libphy 0xbc102371 genphy_config_advert +EXPORT_SYMBOL drivers/net/phy/libphy 0xca6d7038 phy_read +EXPORT_SYMBOL drivers/net/phy/libphy 0xcef8c767 phy_start_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0xe7edfe08 phy_start_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0xed7bef1e phy_detach +EXPORT_SYMBOL drivers/net/phy/libphy 0xf17cec8a phy_ethtool_sset +EXPORT_SYMBOL drivers/net/phy/libphy 0xfe6ecdce phy_connect +EXPORT_SYMBOL drivers/net/phy/libphy 0xfff8715d mdiobus_unregister +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x024be098 free_mdio_bitbang +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0xcd11f89d alloc_mdio_bitbang +EXPORT_SYMBOL drivers/net/ppp_generic 0x3a8aa663 ppp_register_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0x5319c35b ppp_channel_index +EXPORT_SYMBOL drivers/net/ppp_generic 0x93424a59 ppp_unit_number +EXPORT_SYMBOL drivers/net/ppp_generic 0x936d9373 ppp_unregister_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0xa42e5fbc ppp_unregister_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0xa7838c80 ppp_register_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0xdd1c61be ppp_input +EXPORT_SYMBOL drivers/net/ppp_generic 0xe27e0fc7 ppp_output_wakeup +EXPORT_SYMBOL drivers/net/ppp_generic 0xf373c5e4 ppp_input_error +EXPORT_SYMBOL drivers/net/pppox 0x6233f183 pppox_unbind_sock +EXPORT_SYMBOL drivers/net/pppox 0x76bbf10d pppox_ioctl +EXPORT_SYMBOL drivers/net/pppox 0xe0ff7a18 unregister_pppox_proto +EXPORT_SYMBOL drivers/net/pppox 0xfaa0101f register_pppox_proto +EXPORT_SYMBOL drivers/net/slhc 0x0ff2b602 slhc_compress +EXPORT_SYMBOL drivers/net/slhc 0x23c8f257 slhc_uncompress +EXPORT_SYMBOL drivers/net/slhc 0xa63d85ab slhc_remember +EXPORT_SYMBOL drivers/net/slhc 0xb5ca1c46 slhc_free +EXPORT_SYMBOL drivers/net/slhc 0xdfc5169b slhc_init +EXPORT_SYMBOL drivers/net/slhc 0xe8794ce1 slhc_toss +EXPORT_SYMBOL drivers/net/sungem_phy 0x67bd82e2 mii_phy_probe +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x518fcbfb tms380tr_interrupt +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x7b3a9942 tms380tr_open +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xadeea5c6 tmsdev_init +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd2328794 tms380tr_wait +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd9ccfda2 tms380tr_close +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xe77a2924 tmsdev_term +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x38da4725 cycx_intr +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x62be23ea cycx_setup +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x66a4c4e6 cycx_down +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x968458a6 cycx_peek +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xb6f383de cycx_poke +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xfe7cd576 cycx_exec +EXPORT_SYMBOL drivers/net/wan/hdlc 0x168b67dc hdlc_ioctl +EXPORT_SYMBOL drivers/net/wan/hdlc 0x313180e2 unregister_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x44985964 unregister_hdlc_device +EXPORT_SYMBOL drivers/net/wan/hdlc 0x6c8cbed7 attach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x764be7d6 alloc_hdlcdev +EXPORT_SYMBOL drivers/net/wan/hdlc 0x929e55a2 hdlc_open +EXPORT_SYMBOL drivers/net/wan/hdlc 0xdabbbb1a register_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xf1c2c3b3 detach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xf5cb1410 hdlc_close +EXPORT_SYMBOL drivers/net/wan/syncppp 0x25afcc18 sppp_close +EXPORT_SYMBOL drivers/net/wan/syncppp 0x43f173d0 sppp_detach +EXPORT_SYMBOL drivers/net/wan/syncppp 0xa1835f19 sppp_open +EXPORT_SYMBOL drivers/net/wan/syncppp 0xb1d72514 sppp_attach +EXPORT_SYMBOL drivers/net/wan/syncppp 0xb2e41e15 sppp_do_ioctl +EXPORT_SYMBOL drivers/net/wan/syncppp 0xcd786ec4 sppp_reopen +EXPORT_SYMBOL drivers/net/wireless/airo 0x52c53545 stop_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0x7a9b1ba7 reset_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0xcc89e58c init_airo_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0x4e560edf init_atmel_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0x8feecae0 atmel_open +EXPORT_SYMBOL drivers/net/wireless/atmel 0xb204b860 stop_atmel_card +EXPORT_SYMBOL drivers/net/wireless/hermes 0x4196c38b hermes_write_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xc60b5e9e hermes_bap_pwrite +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd38d8ae2 hermes_read_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd3f714e5 hermes_bap_pread +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5168829 hermes_allocate +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5336e5d hermes_init +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd54e219d hermes_docmd_wait +EXPORT_SYMBOL drivers/net/wireless/hermes 0xed47b224 hermes_struct_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x07dab74b hostap_get_porttype +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1723ac32 hostap_set_multicast_list_queue +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x19beae3b hostap_80211_ops +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1e7e25ac hostap_setup_dev +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x206810aa hostap_set_hostapd +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x2c8e4f1c hostap_check_sta_fw_version +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x2ce7d503 hostap_remove_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x32b6f51a hostap_set_encryption +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x3b14fe60 prism2_update_comms_qual +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x3b685886 hostap_init_ap_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x5f24c0ca hostap_set_auth_algs +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x61b1589f hostap_info_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x62afc3ff hostap_80211_rx +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x64ee20d7 hostap_remove_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x6903f16c hostap_80211_get_hdrlen +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x8322c644 hostap_info_process +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x97bd26b4 hostap_init_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x9a95a55d hostap_add_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xa12ad27f hostap_dump_tx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xac1fd987 hostap_init_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb2a945e0 hostap_dump_rx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb465c923 hostap_handle_sta_tx_exc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb91c7434 hostap_master_start_xmit +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xbbab053a hostap_set_string +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xcc2acea3 hostap_get_stats +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xcecb4d9b hostap_free_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xd3a94bbb hostap_set_hostapd_sta +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xde83b774 hostap_set_antsel +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xe8e3ae57 hostap_set_word +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xef4374f0 hostap_set_roaming +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0135ca34 iwlcore_eeprom_verify_signature +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x01adaa66 iwl_eeprom_check_version +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x03748154 iwlcore_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x04694b5b iwl_dump_nic_error_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x07a9165d iwl_set_rxon_channel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0a29c0aa iwl_get_ra_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0a95b247 iwl_rx_queue_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x11df399d iwl_rxq_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1d77b399 iwl_bcast_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1fc0dc90 iwl_send_cmd_pdu +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x23d039ec iwl_find_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x261c6c99 iwl_sta_modify_enable_tid_tx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2c16665e iwl_init_sensitivity +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2cb2b346 iwl_power_initialize +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2d62f769 iwl_rx_queue_restock +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2dff3694 iwl_set_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2f578647 iwl_dump_nic_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2f922f63 iwl_power_set_system_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x302ada75 iwl_init_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x34bb0e7c iwl_scan_initiate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x37f0008a iwl_hw_detect +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x394b37d2 iwl_rx_queue_reset +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x39fddf1a iwl_set_tx_power +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x3b7aa44e iwl_setup_rx_scan_handlers +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x41dc3260 iwl_rx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4231e9b3 iwl_scan_cancel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4272aaf8 iwl_rx_reply_rx_phy +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x46db6e10 iwl_send_statistics_request +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4826c886 iwl_rfkill_set_hw_state +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x482cad8e iwl_rfkill_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4cbcbbbc iwl_set_hw_params +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x524ea92c iwl_reset_qos +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5519e0bc iwl_hw_nic_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x577bb379 iwl_hw_txq_free_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5a0875cd iwl_send_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5bb57fdb iwl_rfkill_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5c9922bb iwl_set_rxon_ht +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5d6836b1 iwl_tx_cmd_complete +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5e901399 iwl_txq_ctx_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5e96742b iwl_eeprom_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5ea18796 iwl_remove_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x60774702 iwl_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x60830157 iwlcore_eeprom_release_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6210ae51 iwl_power_disable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x64b9825f iwl_verify_ucode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6724128d iwl_rx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x705f7f82 iwlcore_eeprom_acquire_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x746a58d7 iwl_eeprom_get_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x761c875a iwl_send_static_wepkey_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x79a660f2 iwl_txq_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7ea29677 iwl_eeprom_query16 +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7f6d9336 iwl_leds_register +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7f9c9613 iwl_rx_missed_beacon_notif +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7fe66bb5 iwl_rx_queue_alloc +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x816388e4 iwl_print_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x81a72aef iwl_tx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x81bfef37 iwl_send_cmd_sync +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x82ff5d6a iwl_power_set_user_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8320b217 iwl_power_temperature_change +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x83613cb5 iwl_set_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8670273d iwl_hwrate_to_plcp_idx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x87be01d8 iwl_remove_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x898c4a82 iwl_rx_statistics +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8bfba80c iwl_send_cmd_pdu_async +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x92e02888 iwl_txq_check_empty +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x93a8e5f9 iwl_get_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9d00da6f iwl_power_enable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9ed43f1a iwl_rx_reply_compressed_ba +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa09e6339 iwl_eeprom_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa356e249 iwl_rx_allocate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xabd98677 iwl_tx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb1231cf2 iwl_tx_skb +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb22ad505 iwl_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb2b511f6 iwl_rxon_add_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb38a1e41 iwl_escape_essid +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb42ccae2 iwl_setup_scan_deferred_work +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb56e4d4c iwl_hwrate_to_tx_control +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb932f2e8 iwl_radio_kill_sw_enable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc282e72d iwl_free_calib_results +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc4242b45 iwl_radio_kill_sw_disable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc59af457 iwl_rx_reply_rx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc64b528f iwl_send_add_sta +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc741d151 iwl_uninit_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc81a2fdb iwl_remove_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc8f29f24 iwl_scan_cancel_timeout +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcabc5050 iwl_power_update_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcae98c25 iwl_alloc_all +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcbaf4931 get_cmd_string +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcddee4fa iwl_leds_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xce299d66 iwl_is_fat_tx_allowed +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd4572b93 iwl_set_rxon_chain +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xda7dbf63 iwl_get_channel_info +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdbc2fe15 iwl_reset_run_time_calib +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdebe1c6c iwl_rf_kill_ct_config +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdfc2a675 iwl_init_channel_map +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe0996307 iwl_rx_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe1417de9 iwl_sensitivity_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe1a4f563 iwl_clear_stations_table +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe30ce6d0 iwl_tx_queue_reclaim +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe7ce5d70 iwl_rates +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe81caeac iwl_add_station_flags +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xecba6dba iwl_send_lq_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xed1ea679 iwl_hw_txq_attach_buf_to_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf0a152b9 iwl_chain_noise_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf3f1212a iwl_rx_replenish +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfc379829 iwl_rx_queue_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfc5028c2 iwl_setup_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfd0577e7 iwl_hw_txq_ctx_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfd7795d9 iwl_leds_background +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x08e5d024 free_orinocodev +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x099c818d __orinoco_up +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x1131a8cc orinoco_reinit_firmware +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x1a9d334a orinoco_interrupt +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xa5e061bb __orinoco_down +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xbc301f55 alloc_orinocodev +EXPORT_SYMBOL drivers/parport/parport 0x01da3f33 parport_get_port +EXPORT_SYMBOL drivers/parport/parport 0x07c3058b parport_wait_event +EXPORT_SYMBOL drivers/parport/parport 0x106d36b3 parport_remove_port +EXPORT_SYMBOL drivers/parport/parport 0x170fab7e parport_announce_port +EXPORT_SYMBOL drivers/parport/parport 0x1dbe8d84 parport_irq_handler +EXPORT_SYMBOL drivers/parport/parport 0x1ea6ca0c parport_ieee1284_epp_read_addr +EXPORT_SYMBOL drivers/parport/parport 0x21512774 parport_ieee1284_epp_write_data +EXPORT_SYMBOL drivers/parport/parport 0x25235d0c parport_ieee1284_write_compat +EXPORT_SYMBOL drivers/parport/parport 0x2e8f7fe4 parport_unregister_device +EXPORT_SYMBOL drivers/parport/parport 0x3b750726 parport_ieee1284_ecp_write_data +EXPORT_SYMBOL drivers/parport/parport 0x440a8813 parport_ieee1284_ecp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0x4823910a parport_negotiate +EXPORT_SYMBOL drivers/parport/parport 0x4a6f510c parport_write +EXPORT_SYMBOL drivers/parport/parport 0x4c59e0a9 parport_unregister_driver +EXPORT_SYMBOL drivers/parport/parport 0x4d2a941b parport_ieee1284_interrupt +EXPORT_SYMBOL drivers/parport/parport 0x4d2b97b2 parport_find_base +EXPORT_SYMBOL drivers/parport/parport 0x517bfccb parport_claim +EXPORT_SYMBOL drivers/parport/parport 0x5e2ea841 parport_ieee1284_epp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0x75315cd6 parport_register_device +EXPORT_SYMBOL drivers/parport/parport 0x75718816 parport_ieee1284_epp_read_data +EXPORT_SYMBOL drivers/parport/parport 0x842f8e92 parport_read +EXPORT_SYMBOL drivers/parport/parport 0x875f7f20 parport_register_driver +EXPORT_SYMBOL drivers/parport/parport 0xa352a87f parport_wait_peripheral +EXPORT_SYMBOL drivers/parport/parport 0xade28868 parport_put_port +EXPORT_SYMBOL drivers/parport/parport 0xb38a2817 parport_release +EXPORT_SYMBOL drivers/parport/parport 0xb77b755b parport_ieee1284_ecp_read_data +EXPORT_SYMBOL drivers/parport/parport 0xbeaea3ab parport_find_number +EXPORT_SYMBOL drivers/parport/parport 0xd2f75fe1 parport_register_port +EXPORT_SYMBOL drivers/parport/parport 0xd96f9dd1 parport_ieee1284_read_nibble +EXPORT_SYMBOL drivers/parport/parport 0xde31b620 parport_ieee1284_read_byte +EXPORT_SYMBOL drivers/parport/parport 0xdfa3aae0 parport_claim_or_block +EXPORT_SYMBOL drivers/parport/parport 0xf5d0a225 parport_set_timeout +EXPORT_SYMBOL drivers/parport/parport_pc 0x8e8e369d parport_pc_probe_port +EXPORT_SYMBOL drivers/parport/parport_pc 0xb96b90a2 parport_pc_unregister_port +EXPORT_SYMBOL drivers/pci/hotplug/pci_hotplug 0xa8b32752 acpi_get_hp_hw_control_from_firmware +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x1afd903d pcmcia_release_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x5818bb87 pcmcia_modify_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x5885e727 pcmcia_request_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x5af01c8f cs_error +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x622f29a8 pcmcia_get_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x650c7270 pcmcia_request_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x80b5b39f pcmcia_get_configuration_info +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x833ea096 pcmcia_map_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x8a57fdbe pcmcia_dev_present +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa4cd3270 pcmcia_unregister_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa58f872e pcmcia_disable_device +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xd4ce007e pcmcia_get_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xd795491b pcmcia_request_io +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xda549c83 pcmcia_access_configuration_register +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xe769eebd pcmcia_register_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf1d52cda pcmcia_request_irq +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x013f7e7d pcmcia_suspend_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x08725dfa pccard_static_ops +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0cffb5cd pcmcia_register_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0e3c978f pcmcia_read_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x1962608d pcmcia_insert_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x212db8d2 pcmcia_socket_list +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x245ac0ec pcmcia_replace_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x26016f30 pccard_reset_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2f7bbea9 pccard_read_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x465436dd pcmcia_find_io_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x4f5b6900 pcmcia_unregister_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x500d7c55 release_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x51f754ea pccard_validate_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x5d33573b pcmcia_find_mem_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x748e1ffe pccard_register_pcmcia +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7b4b4878 pcmcia_write_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7be51a3a pcmcia_put_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7d38b250 pcmcia_eject_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x85886a77 pcmcia_get_socket_by_nr +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x8e6c9b6e pcmcia_parse_events +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x9426c54c pcmcia_validate_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x96311081 pcmcia_get_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x984fec08 pccard_get_tuple_data +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x9c20f5cc destroy_cis_cache +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa8df65b6 pcmcia_socket_list_rwsem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xac4393d6 pccard_get_first_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xb07305fc pcmcia_resume_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xb88ee4f8 pccard_get_next_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc701d244 pcmcia_adjust_io_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc9bd9f33 pcmcia_socket_dev_suspend +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcd2ac1c1 pccard_parse_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcf97f3bd dead_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xd99a9d91 pcmcia_socket_dev_resume +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xef98210c pcmcia_socket_class +EXPORT_SYMBOL drivers/pcmcia/rsrc_nonstatic 0x3dc632bb pccard_nonstatic_ops +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x2250c66e mraid_mm_adapter_app_handle +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x43a9a2fb mraid_mm_register_adp +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x512c956d mraid_mm_unregister_adp +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x0dceb204 qlogicfas408_disable_ints +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x2df4b8d2 qlogicfas408_abort +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x3fd8cd71 qlogicfas408_detect +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x5cd179e6 qlogicfas408_ihandl +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x98f5cb5f qlogicfas408_biosparam +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xa031bf80 qlogicfas408_queuecommand +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xbb493a86 qlogicfas408_info +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xdd2e6ee7 qlogicfas408_bus_reset +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xe76b3b20 qlogicfas408_get_chip_type +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xf2b95199 qlogicfas408_setup +EXPORT_SYMBOL drivers/scsi/raid_class 0x74521d97 raid_component_add +EXPORT_SYMBOL drivers/scsi/raid_class 0xb9d43cea raid_class_attach +EXPORT_SYMBOL drivers/scsi/raid_class 0xc81a5e2e raid_class_release +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0029528d scsi_req_abort_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x05b47c78 scsi_get_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0732beee scsi_release_buffers +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0b61bee9 __scsi_iterate_devices +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c65e73c scsi_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c6dc352 scsi_execute_req +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c8c9e99 scsi_show_extd_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0d603017 scsi_prep_state_check +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0e3220dc scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x11267875 scsi_extd_sense_format +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x178ffca2 __starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1877df5f scsi_bios_ptable +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1b9e0ff1 scsilun_to_int +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x22d373e2 scsi_set_medium_removal +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x23867cab scsi_dma_map +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x247e1e63 scsi_dma_unmap +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28a2ed02 scsi_build_sense_buffer +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2b0ba2b0 scsi_sense_desc_find +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2d89342a scsi_show_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2e0f998e scsi_cmd_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x300eafda scsi_add_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3066aeb7 scsi_block_when_processing_errors +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x344931fd scsi_setup_blk_pc_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x369df429 scsi_unblock_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x374e73da scsi_report_device_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x38b656aa scsi_execute +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3aea5e7c scsi_setup_fs_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x42de46df scsi_host_alloc +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x448c3b41 scsi_init_io +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x488afd76 scsi_eh_prep_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x48eecc07 scsi_free_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4afe9a77 scsi_partsize +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4be7b9f8 scsi_register +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4e9049ce scsi_device_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x52099a4a scsi_reset_provider +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x528b8942 scsi_get_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x52f15eca scsi_remove_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5628aa5f scsi_host_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x56c8799d scsi_kunmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x57307ab2 __scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x581d96f8 scsi_device_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5a306f55 scsi_eh_finish_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5a6aba68 scsi_target_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5d494632 __scsi_alloc_queue +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5dced60c scsi_is_target_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x624e347f scsi_rescan_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x668f4b87 scsi_device_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x66a8035c scsi_calculate_bounce_limit +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x670c19a8 scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x69d38ed9 __scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6a179967 scsi_register_interface +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6e9243a8 __scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72ea7b2d scsi_device_type +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x73e00570 scsi_host_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x74b10717 scsi_prep_return +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x77aaf6d6 scsi_free_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x796fc5ce scsi_get_sense_info_fld +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7a254164 scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7c6dac5b scsi_is_host_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7e95964d scsi_report_bus_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8480f33f scsi_block_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x89434821 scsi_adjust_queue_depth +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8fe88d6b scsi_eh_restore_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9005ff20 scsi_nonblockable_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x90c875e5 scsi_allocate_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9458e4fa starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96cd2b04 scsi_sense_key_string +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96e11a1e scsi_unregister +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x97ab7091 scsi_finish_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x990f9219 scsi_target_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9965476d scsi_command_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9c2becab scsi_print_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9cfd56c5 scsi_print_status +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9d8f2500 scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xae5fdbb9 scsi_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaf3dd7dc scsi_logging_level +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb2c19721 scsi_device_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb6c5a973 scsi_show_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb885c3e5 scsi_is_sdev_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbe2b257f scsi_register_driver +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc0461e47 scsi_track_queue_full +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc670568b scsi_test_unit_ready +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc718d81c __scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xca5dbc50 scsi_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xcd07ce23 scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd469399b scsi_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd7490608 scsi_remove_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd88bb189 scsi_scan_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe0f4f326 scsi_scan_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe698a699 scsi_host_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe9803ee9 scsi_device_get +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xea10212a int_to_scsilun +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xec60d9f3 scsicam_bios_param +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf00e540e scsi_mode_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf0297ef6 scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf4528073 scsi_kmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf811e69d scsi_eh_flush_done_q +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfadc0bb9 __scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfef96e23 __scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xff0f9365 scsi_host_get +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x0c20beb9 fc_vport_terminate +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x207967ef fc_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x24704f72 scsi_is_fc_vport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x298eacb4 fc_host_post_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x57ad192a scsi_is_fc_rport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x5da94aa1 fc_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x62ab4f57 fc_host_post_vendor_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x6a55c908 fc_remote_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x745f3ec6 fc_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x7954b1ea fc_get_event_number +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x80f130dd fc_remote_port_rolechg +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xb52616fe fc_remote_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x17fa5fba sas_port_add_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x184f2be1 sas_read_port_mode_page +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x25f04b11 sas_phy_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x44a32979 sas_phy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x4e1b054a sas_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x5cfbfed5 sas_end_device_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x60f26003 sas_port_mark_backlink +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x69493d8c sas_phy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x72ea52da sas_rphy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x7723d240 sas_remove_children +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x8684aaf0 sas_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x938ec9af sas_phy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x96682ec8 sas_rphy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x9dda2a6d sas_rphy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x9e1c94ff scsi_is_sas_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xa564007a sas_port_alloc_num +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xacc29bfd sas_rphy_remove +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xaf87b2bd sas_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xb2d45380 sas_expander_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xc9109ef9 sas_port_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xd1d98df5 scsi_is_sas_port +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xe2c96944 scsi_is_sas_rphy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xee9ae46f sas_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf018857f sas_port_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf36915fa sas_port_delete_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf6e59904 sas_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x04a9f029 spi_display_xfer_agreement +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x1c93783f spi_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x3686ea09 spi_print_msg +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xac639ccf spi_schedule_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xb20e3d70 spi_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xb50dbd9c spi_release_transport +EXPORT_SYMBOL drivers/ssb/ssb 0x11755805 __ssb_driver_register +EXPORT_SYMBOL drivers/ssb/ssb 0x1df7733c ssb_dma_alloc_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0x2c6c218f ssb_pcicore_dev_irqvecs_enable +EXPORT_SYMBOL drivers/ssb/ssb 0x4150a0a8 ssb_dma_translation +EXPORT_SYMBOL drivers/ssb/ssb 0x4b2d7d25 ssb_dma_free_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0x5d9b9ccb ssb_bus_powerup +EXPORT_SYMBOL drivers/ssb/ssb 0x62ba21e1 ssb_device_disable +EXPORT_SYMBOL drivers/ssb/ssb 0x6c1cc26e ssb_bus_may_powerdown +EXPORT_SYMBOL drivers/ssb/ssb 0x82d8b1fc ssb_clockspeed +EXPORT_SYMBOL drivers/ssb/ssb 0x96518487 ssb_driver_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0x9bf48d18 ssb_device_is_enabled +EXPORT_SYMBOL drivers/ssb/ssb 0xa5884ab9 ssb_dma_set_mask +EXPORT_SYMBOL drivers/ssb/ssb 0xac6d68a5 ssb_bus_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0xb5c1d190 ssb_device_enable +EXPORT_SYMBOL drivers/ssb/ssb 0xc0512e0f ssb_admatch_base +EXPORT_SYMBOL drivers/ssb/ssb 0xc523c4af ssb_set_devtypedata +EXPORT_SYMBOL drivers/ssb/ssb 0xca268be1 ssb_bus_suspend +EXPORT_SYMBOL drivers/ssb/ssb 0xd481192b ssb_admatch_size +EXPORT_SYMBOL drivers/ssb/ssb 0xdb368a39 ssb_pcihost_register +EXPORT_SYMBOL drivers/ssb/ssb 0xe467d159 ssb_bus_resume +EXPORT_SYMBOL drivers/ssb/ssb 0xeda86a81 ssb_bus_pcibus_register +EXPORT_SYMBOL drivers/telephony/ixj 0xdf7bffa2 ixj_pcmcia_probe +EXPORT_SYMBOL drivers/telephony/phonedev 0xbd41682f phone_unregister_device +EXPORT_SYMBOL drivers/telephony/phonedev 0xc87ed38f phone_register_device +EXPORT_SYMBOL drivers/usb/gadget/net2280 0x43f049d1 usb_gadget_unregister_driver +EXPORT_SYMBOL drivers/usb/gadget/net2280 0xc824e761 usb_gadget_register_driver +EXPORT_SYMBOL drivers/usb/gadget/net2280 0xecb8a987 net2280_set_fifo_mode +EXPORT_SYMBOL drivers/usb/host/sl811-hcd 0x7af6ecc6 sl811h_driver +EXPORT_SYMBOL drivers/usb/serial/usbserial 0x182ea30f usb_serial_resume +EXPORT_SYMBOL drivers/usb/serial/usbserial 0x2fcf7bb2 usb_serial_suspend +EXPORT_SYMBOL drivers/video/backlight/corgi_bl 0xc86baa7c corgibl_limit_intensity +EXPORT_SYMBOL drivers/video/backlight/lcd 0x15d3a075 lcd_device_unregister +EXPORT_SYMBOL drivers/video/backlight/lcd 0x55d0cd14 lcd_device_register +EXPORT_SYMBOL drivers/video/console/bitblit 0xafc935fc fbcon_set_bitops +EXPORT_SYMBOL drivers/video/console/font 0x09c8eb55 font_vga_8x16 +EXPORT_SYMBOL drivers/video/console/font 0xbb99125c get_default_font +EXPORT_SYMBOL drivers/video/console/font 0xf7584a9c find_font +EXPORT_SYMBOL drivers/video/console/softcursor 0x3f16bfb7 soft_cursor +EXPORT_SYMBOL drivers/video/console/tileblit 0x444d5d22 fbcon_set_tileops +EXPORT_SYMBOL drivers/video/cyber2000fb 0x0cc3ede5 cyber2000fb_detach +EXPORT_SYMBOL drivers/video/cyber2000fb 0x2666e329 cyber2000fb_enable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0x45c0f565 cyber2000fb_disable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0x50ffc488 cyber2000fb_get_fb_var +EXPORT_SYMBOL drivers/video/cyber2000fb 0xefb5bae4 cyber2000fb_attach +EXPORT_SYMBOL drivers/video/display/display 0x0a72c73a display_device_unregister +EXPORT_SYMBOL drivers/video/display/display 0x9c5117c6 display_device_register +EXPORT_SYMBOL drivers/video/macmodes 0x08ed0b62 mac_vmode_to_var +EXPORT_SYMBOL drivers/video/macmodes 0x31898a77 mac_find_mode +EXPORT_SYMBOL drivers/video/macmodes 0xe2304303 mac_map_monitor_sense +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x3b00873b matroxfb_g450_setclk +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x51ca34ec g450_mnp2f +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x878fa7f2 matroxfb_g450_setpll_cond +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x185cb0d7 matrox_mystique +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x2972630b matrox_G100 +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xb55b6a10 DAC1064_global_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xe77dfead DAC1064_global_restore +EXPORT_SYMBOL drivers/video/matrox/matroxfb_Ti3026 0x56c4d649 matrox_millennium +EXPORT_SYMBOL drivers/video/matrox/matroxfb_accel 0x9aba1999 matrox_cfbX_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x174f91b9 matroxfb_unregister_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x843547be matroxfb_register_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xafffd247 matroxfb_wait_for_sync +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xfb31ba10 matroxfb_enable_irq +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x34974c30 matroxfb_g450_shutdown +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0xab3605bb matroxfb_g450_connect +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x161c794b matroxfb_vgaHWrestore +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x25cf8049 matroxfb_PLL_calcclock +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x3a0d557d matroxfb_vgaHWinit +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x6cd16961 matroxfb_DAC_in +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x9a396892 matroxfb_DAC_out +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xabd8e427 matroxfb_var2my +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xfd58e69e matroxfb_read_pins +EXPORT_SYMBOL drivers/video/output 0xb2100689 video_output_unregister +EXPORT_SYMBOL drivers/video/output 0xdd202b9e video_output_register +EXPORT_SYMBOL drivers/video/sis/sisfb 0x3037658e sis_malloc +EXPORT_SYMBOL drivers/video/sis/sisfb 0x454a3cf0 sis_free +EXPORT_SYMBOL drivers/video/svgalib 0x00d1fce9 svga_set_default_seq_regs +EXPORT_SYMBOL drivers/video/svgalib 0x07b3da30 svga_wseq_multi +EXPORT_SYMBOL drivers/video/svgalib 0x1b95c56a svga_check_timings +EXPORT_SYMBOL drivers/video/svgalib 0x38cf5f5f svga_tilecopy +EXPORT_SYMBOL drivers/video/svgalib 0x63e898d1 svga_set_default_crt_regs +EXPORT_SYMBOL drivers/video/svgalib 0x7a3ae959 svga_wcrt_multi +EXPORT_SYMBOL drivers/video/svgalib 0x80408443 svga_set_timings +EXPORT_SYMBOL drivers/video/svgalib 0x849d0aed svga_tileblit +EXPORT_SYMBOL drivers/video/svgalib 0x8fa8438b svga_set_textmode_vga_regs +EXPORT_SYMBOL drivers/video/svgalib 0xa4f9b78c svga_get_caps +EXPORT_SYMBOL drivers/video/svgalib 0xab3b22ad svga_set_default_gfx_regs +EXPORT_SYMBOL drivers/video/svgalib 0xb87a2c50 svga_settile +EXPORT_SYMBOL drivers/video/svgalib 0xbd1b6420 svga_tilefill +EXPORT_SYMBOL drivers/video/svgalib 0xdad682b1 svga_set_default_atc_regs +EXPORT_SYMBOL drivers/video/svgalib 0xec83c473 svga_match_format +EXPORT_SYMBOL drivers/video/svgalib 0xef774f5d svga_compute_pll +EXPORT_SYMBOL drivers/video/svgalib 0xf03a2ade svga_get_tilemax +EXPORT_SYMBOL drivers/video/svgalib 0xf68bee68 svga_tilecursor +EXPORT_SYMBOL drivers/video/syscopyarea 0xd62472cb sys_copyarea +EXPORT_SYMBOL drivers/video/sysfillrect 0xeab8161b sys_fillrect +EXPORT_SYMBOL drivers/video/sysimgblt 0x6581f331 sys_imageblit +EXPORT_SYMBOL drivers/video/vgastate 0x686de290 restore_vga +EXPORT_SYMBOL drivers/video/vgastate 0xe7a2620e save_vga +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x6036e6b3 w1_ds2760_read +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x73b3cf34 w1_ds2760_write +EXPORT_SYMBOL drivers/w1/wire 0x8cf61660 w1_add_master_device +EXPORT_SYMBOL drivers/w1/wire 0xb10f92e8 w1_register_family +EXPORT_SYMBOL drivers/w1/wire 0xb959d36f w1_unregister_family +EXPORT_SYMBOL drivers/w1/wire 0xcda061c0 w1_remove_master_device +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x04e133fc iTCO_vendor_check_noreboot_on +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x672c9d44 iTCO_vendor_pre_keepalive +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa78bd894 iTCO_vendor_pre_set_heartbeat +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa8d6daac iTCO_vendor_pre_start +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xd0efe320 iTCO_vendor_pre_stop +EXPORT_SYMBOL fs/configfs/configfs 0x24517370 config_item_put +EXPORT_SYMBOL fs/configfs/configfs 0x27e53180 config_group_find_item +EXPORT_SYMBOL fs/configfs/configfs 0x687e9fa1 configfs_depend_item +EXPORT_SYMBOL fs/configfs/configfs 0x778209f5 config_group_init +EXPORT_SYMBOL fs/configfs/configfs 0x7e16609c configfs_register_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0x9290e281 config_item_init +EXPORT_SYMBOL fs/configfs/configfs 0x9397eb44 configfs_unregister_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0xa2501a2c config_item_set_name +EXPORT_SYMBOL fs/configfs/configfs 0xae812660 config_group_init_type_name +EXPORT_SYMBOL fs/configfs/configfs 0xb06f4821 config_item_get +EXPORT_SYMBOL fs/configfs/configfs 0xd1279084 config_item_init_type_name +EXPORT_SYMBOL fs/configfs/configfs 0xe873e298 configfs_undepend_item +EXPORT_SYMBOL fs/jbd/jbd 0x00dac50b journal_dirty_data +EXPORT_SYMBOL fs/jbd/jbd 0x01bb16e9 journal_forget +EXPORT_SYMBOL fs/jbd/jbd 0x1c39270a journal_clear_err +EXPORT_SYMBOL fs/jbd/jbd 0x1e073f22 journal_check_used_features +EXPORT_SYMBOL fs/jbd/jbd 0x1f3057e5 journal_force_commit +EXPORT_SYMBOL fs/jbd/jbd 0x2863e016 journal_ack_err +EXPORT_SYMBOL fs/jbd/jbd 0x2e39226f journal_stop +EXPORT_SYMBOL fs/jbd/jbd 0x31abbba9 journal_update_format +EXPORT_SYMBOL fs/jbd/jbd 0x37f663a5 journal_init_inode +EXPORT_SYMBOL fs/jbd/jbd 0x39bf3327 journal_load +EXPORT_SYMBOL fs/jbd/jbd 0x555537cc journal_lock_updates +EXPORT_SYMBOL fs/jbd/jbd 0x57e0be96 journal_extend +EXPORT_SYMBOL fs/jbd/jbd 0x5882cc65 journal_blocks_per_page +EXPORT_SYMBOL fs/jbd/jbd 0x5954a9cf journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd/jbd 0x610026ae journal_abort +EXPORT_SYMBOL fs/jbd/jbd 0x672e1587 journal_get_undo_access +EXPORT_SYMBOL fs/jbd/jbd 0x67d37f16 journal_start_commit +EXPORT_SYMBOL fs/jbd/jbd 0x766991a5 journal_get_create_access +EXPORT_SYMBOL fs/jbd/jbd 0x78aaecbd journal_dirty_metadata +EXPORT_SYMBOL fs/jbd/jbd 0x7b362adc journal_force_commit_nested +EXPORT_SYMBOL fs/jbd/jbd 0x83fa644f journal_restart +EXPORT_SYMBOL fs/jbd/jbd 0x8787e2c1 journal_set_features +EXPORT_SYMBOL fs/jbd/jbd 0x8bfbfdc7 journal_start +EXPORT_SYMBOL fs/jbd/jbd 0x9899aa58 journal_init_dev +EXPORT_SYMBOL fs/jbd/jbd 0x9cd3309e journal_check_available_features +EXPORT_SYMBOL fs/jbd/jbd 0x9d0c96a8 journal_release_buffer +EXPORT_SYMBOL fs/jbd/jbd 0x9ee58688 journal_invalidatepage +EXPORT_SYMBOL fs/jbd/jbd 0xa9a29255 journal_flush +EXPORT_SYMBOL fs/jbd/jbd 0xb7a774c9 journal_errno +EXPORT_SYMBOL fs/jbd/jbd 0xc0da59a2 log_wait_commit +EXPORT_SYMBOL fs/jbd/jbd 0xc63871c0 journal_get_write_access +EXPORT_SYMBOL fs/jbd/jbd 0xc896970f journal_unlock_updates +EXPORT_SYMBOL fs/jbd/jbd 0xcbd5fe6b journal_create +EXPORT_SYMBOL fs/jbd/jbd 0xdbe8d97a journal_revoke +EXPORT_SYMBOL fs/jbd/jbd 0xe5b1585d journal_destroy +EXPORT_SYMBOL fs/jbd/jbd 0xfa682948 journal_wipe +EXPORT_SYMBOL fs/jbd2/jbd2 0x01fb8f55 jbd2_journal_check_used_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x0974a3c4 jbd2_journal_init_dev +EXPORT_SYMBOL fs/jbd2/jbd2 0x0dc9ad99 jbd2_journal_force_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x13b5ef9e jbd2_journal_invalidatepage +EXPORT_SYMBOL fs/jbd2/jbd2 0x14059e51 jbd2_journal_force_commit_nested +EXPORT_SYMBOL fs/jbd2/jbd2 0x1bffe5df jbd2_journal_release_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x1ff4f5f3 jbd2_journal_stop +EXPORT_SYMBOL fs/jbd2/jbd2 0x221930b3 jbd2_journal_abort +EXPORT_SYMBOL fs/jbd2/jbd2 0x28d587eb jbd2_journal_get_write_access +EXPORT_SYMBOL fs/jbd2/jbd2 0x28f3fbf5 jbd2_journal_start +EXPORT_SYMBOL fs/jbd2/jbd2 0x306d08eb jbd2_journal_begin_ordered_truncate +EXPORT_SYMBOL fs/jbd2/jbd2 0x356dcbc9 jbd2_journal_lock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0x41de345a jbd2_journal_forget +EXPORT_SYMBOL fs/jbd2/jbd2 0x5cc50e9c jbd2_journal_init_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x68eb85c8 jbd2_journal_set_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x78812e6a jbd2_journal_check_available_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x78cd649e jbd2_journal_file_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x7df2d281 jbd2_journal_update_format +EXPORT_SYMBOL fs/jbd2/jbd2 0x7f7a0056 jbd2_journal_release_buffer +EXPORT_SYMBOL fs/jbd2/jbd2 0x8787db36 jbd2_journal_start_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x8c7a6d67 jbd2_journal_load +EXPORT_SYMBOL fs/jbd2/jbd2 0x9b41cf42 jbd2_journal_errno +EXPORT_SYMBOL fs/jbd2/jbd2 0xa613479b jbd2_journal_destroy +EXPORT_SYMBOL fs/jbd2/jbd2 0xa85b996c jbd2_journal_extend +EXPORT_SYMBOL fs/jbd2/jbd2 0xb211420d jbd2_journal_ack_err +EXPORT_SYMBOL fs/jbd2/jbd2 0xb2abd8e8 jbd2_journal_init_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0xb8919682 jbd2_journal_wipe +EXPORT_SYMBOL fs/jbd2/jbd2 0xb937ca8d jbd2_journal_flush +EXPORT_SYMBOL fs/jbd2/jbd2 0xba79ad64 jbd2_journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd2/jbd2 0xc6b756ef jbd2_journal_get_create_access +EXPORT_SYMBOL fs/jbd2/jbd2 0xc80311f8 jbd2_journal_clear_features +EXPORT_SYMBOL fs/jbd2/jbd2 0xca5ab178 jbd2_journal_dirty_metadata +EXPORT_SYMBOL fs/jbd2/jbd2 0xd6f64fed jbd2_journal_get_undo_access +EXPORT_SYMBOL fs/jbd2/jbd2 0xe2167d62 jbd2_journal_restart +EXPORT_SYMBOL fs/jbd2/jbd2 0xe33f15f4 jbd2_journal_unlock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0xeb72ed29 jbd2_journal_revoke +EXPORT_SYMBOL fs/jbd2/jbd2 0xed36ee95 jbd2_journal_clear_err +EXPORT_SYMBOL fs/jbd2/jbd2 0xf346a7e4 jbd2_journal_create +EXPORT_SYMBOL fs/jbd2/jbd2 0xfa72d811 jbd2_log_wait_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0xff6b6d9c jbd2_journal_blocks_per_page +EXPORT_SYMBOL fs/lockd/lockd 0x976e539e lockd_up +EXPORT_SYMBOL fs/lockd/lockd 0xa7b91a7b lockd_down +EXPORT_SYMBOL fs/lockd/lockd 0xad09c2db get_nfs_grace_period +EXPORT_SYMBOL fs/lockd/lockd 0xd332bd97 nlmsvc_ops +EXPORT_SYMBOL fs/mbcache 0x5752bb80 mb_cache_entry_alloc +EXPORT_SYMBOL fs/mbcache 0x5d19a21e mb_cache_entry_release +EXPORT_SYMBOL fs/mbcache 0x6c063a3f mb_cache_create +EXPORT_SYMBOL fs/mbcache 0x7b506b1d mb_cache_entry_find_first +EXPORT_SYMBOL fs/mbcache 0x86d1898b mb_cache_entry_insert +EXPORT_SYMBOL fs/mbcache 0x911efa55 mb_cache_entry_get +EXPORT_SYMBOL fs/mbcache 0x92ee083e mb_cache_entry_free +EXPORT_SYMBOL fs/mbcache 0xc8bb75df mb_cache_shrink +EXPORT_SYMBOL fs/mbcache 0xd5263820 mb_cache_destroy +EXPORT_SYMBOL fs/mbcache 0xedfe7ce7 mb_cache_entry_find_next +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0x33f37cff nfsacl_decode +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0x9fb9ee63 nfsacl_encode +EXPORT_SYMBOL fs/nfsd/nfsd 0x23f0a2c8 nfs4_acl_nfsv4_to_posix +EXPORT_SYMBOL fs/nfsd/nfsd 0x35e33c1e nfs4_acl_write_who +EXPORT_SYMBOL fs/nfsd/nfsd 0x46ffdc39 nfs4_acl_posix_to_nfsv4 +EXPORT_SYMBOL fs/nfsd/nfsd 0x5a157ae4 nfs4_acl_get_whotype +EXPORT_SYMBOL fs/nfsd/nfsd 0x96ce9bb4 nfs4_acl_new +EXPORT_SYMBOL fs/xfs/xfs 0xe8aac5be xfs_qmcore_xfs +EXPORT_SYMBOL lib/crc-ccitt 0x651c2313 crc_ccitt +EXPORT_SYMBOL lib/crc-ccitt 0x75811312 crc_ccitt_table +EXPORT_SYMBOL lib/crc-itu-t 0x276c7e62 crc_itu_t +EXPORT_SYMBOL lib/crc-itu-t 0xd29b009f crc_itu_t_table +EXPORT_SYMBOL lib/crc-t10dif 0x782acba5 crc_t10dif +EXPORT_SYMBOL lib/crc16 0x02a6ce5a crc16_table +EXPORT_SYMBOL lib/crc16 0x9aabc564 crc16 +EXPORT_SYMBOL lib/crc7 0xc086bfba crc7 +EXPORT_SYMBOL lib/crc7 0xd80c3603 crc7_syndrome_table +EXPORT_SYMBOL lib/libcrc32c 0x13c0c38e crc32c_le +EXPORT_SYMBOL lib/libcrc32c 0x41bcd8b3 crc32c_be +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x315c65fd zlib_deflateInit2 +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x48034724 zlib_deflateReset +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xaf64ad0d zlib_deflate +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf0caf44b zlib_deflate_workspacesize +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf741c793 zlib_deflateEnd +EXPORT_SYMBOL net/802/p8023 0x98df3c71 make_8023_client +EXPORT_SYMBOL net/802/p8023 0xaf85fb43 destroy_8023_client +EXPORT_SYMBOL net/9p/9pnet 0x00a6e1a5 p9_create_tclunk +EXPORT_SYMBOL net/9p/9pnet 0x0106a185 p9_create_tstat +EXPORT_SYMBOL net/9p/9pnet 0x088f914e p9_client_write +EXPORT_SYMBOL net/9p/9pnet 0x09745f8a p9_client_readn +EXPORT_SYMBOL net/9p/9pnet 0x0b26ff5a v9fs_unregister_trans +EXPORT_SYMBOL net/9p/9pnet 0x15779868 p9_set_tag +EXPORT_SYMBOL net/9p/9pnet 0x16a4e75b p9_client_stat +EXPORT_SYMBOL net/9p/9pnet 0x18d53221 p9_idpool_get +EXPORT_SYMBOL net/9p/9pnet 0x21523da9 p9_create_tattach +EXPORT_SYMBOL net/9p/9pnet 0x309767d8 p9_deserialize_stat +EXPORT_SYMBOL net/9p/9pnet 0x327cc194 p9_client_dirread +EXPORT_SYMBOL net/9p/9pnet 0x3303cfe4 p9_client_attach +EXPORT_SYMBOL net/9p/9pnet 0x34132d0a p9_idpool_put +EXPORT_SYMBOL net/9p/9pnet 0x342f88f4 p9_client_uwrite +EXPORT_SYMBOL net/9p/9pnet 0x35a2aa3c p9_idpool_create +EXPORT_SYMBOL net/9p/9pnet 0x3915524a p9_client_disconnect +EXPORT_SYMBOL net/9p/9pnet 0x3ba009e4 p9_client_clunk +EXPORT_SYMBOL net/9p/9pnet 0x3d73a797 p9_errstr2errno +EXPORT_SYMBOL net/9p/9pnet 0x465c4e6f p9_printfcall +EXPORT_SYMBOL net/9p/9pnet 0x507c9d70 p9_create_tauth +EXPORT_SYMBOL net/9p/9pnet 0x53db0a3c p9_client_create +EXPORT_SYMBOL net/9p/9pnet 0x570f8eba p9_client_walk +EXPORT_SYMBOL net/9p/9pnet 0x6461b8de p9_create_twrite +EXPORT_SYMBOL net/9p/9pnet 0x6f11c5c3 p9_create_twrite_u +EXPORT_SYMBOL net/9p/9pnet 0x71c7537d p9_create_tcreate +EXPORT_SYMBOL net/9p/9pnet 0x791bb250 p9_client_remove +EXPORT_SYMBOL net/9p/9pnet 0x81247f39 p9_create_tread +EXPORT_SYMBOL net/9p/9pnet 0x8432c83f p9_deserialize_fcall +EXPORT_SYMBOL net/9p/9pnet 0x94b7d5f8 p9_client_wstat +EXPORT_SYMBOL net/9p/9pnet 0x950e6b03 p9_create_twstat +EXPORT_SYMBOL net/9p/9pnet 0x9579c2fa p9_client_auth +EXPORT_SYMBOL net/9p/9pnet 0xa1998338 p9_client_read +EXPORT_SYMBOL net/9p/9pnet 0xa9536064 p9_create_tversion +EXPORT_SYMBOL net/9p/9pnet 0xadfd597a p9_create_tremove +EXPORT_SYMBOL net/9p/9pnet 0xbb0bb702 v9fs_get_trans_by_name +EXPORT_SYMBOL net/9p/9pnet 0xc1468893 p9_client_open +EXPORT_SYMBOL net/9p/9pnet 0xc3277dfd p9_idpool_destroy +EXPORT_SYMBOL net/9p/9pnet 0xdc894ac7 p9_create_twalk +EXPORT_SYMBOL net/9p/9pnet 0xe0c59d41 p9_client_destroy +EXPORT_SYMBOL net/9p/9pnet 0xe58a3360 p9_error_init +EXPORT_SYMBOL net/9p/9pnet 0xe6238993 v9fs_get_default_trans +EXPORT_SYMBOL net/9p/9pnet 0xf09b3efa p9_create_topen +EXPORT_SYMBOL net/9p/9pnet 0xf41bffb5 p9_client_uread +EXPORT_SYMBOL net/9p/9pnet 0xf85870ff v9fs_register_trans +EXPORT_SYMBOL net/9p/9pnet 0xfdbd83e3 p9_client_fcreate +EXPORT_SYMBOL net/9p/9pnet 0xff12c0b5 p9_idpool_check +EXPORT_SYMBOL net/9p/9pnet 0xfff27930 p9_create_tflush +EXPORT_SYMBOL net/appletalk/appletalk 0x095ef0cb atalk_find_dev_addr +EXPORT_SYMBOL net/appletalk/appletalk 0x0d8c69ba alloc_ltalkdev +EXPORT_SYMBOL net/appletalk/appletalk 0x3a21acba atrtr_get_dev +EXPORT_SYMBOL net/appletalk/appletalk 0xa744535e aarp_send_ddp +EXPORT_SYMBOL net/ax25/ax25 0x0479d44f ax25_findbyuid +EXPORT_SYMBOL net/ax25/ax25 0x06b81681 ax25_listen_register +EXPORT_SYMBOL net/ax25/ax25 0x10c1a07c ax25_rebuild_header +EXPORT_SYMBOL net/ax25/ax25 0x1681ad87 ax25_linkfail_release +EXPORT_SYMBOL net/ax25/ax25 0x1d7e38f9 ax25_hard_header +EXPORT_SYMBOL net/ax25/ax25 0x1ee6d5f5 ax25_send_frame +EXPORT_SYMBOL net/ax25/ax25 0x242852b9 ax25_uid_policy +EXPORT_SYMBOL net/ax25/ax25 0x3d2d82ec ax25_display_timer +EXPORT_SYMBOL net/ax25/ax25 0x4502c65a asc2ax +EXPORT_SYMBOL net/ax25/ax25 0x53dea1ff ax2asc +EXPORT_SYMBOL net/ax25/ax25 0x8ede9e26 ax25_protocol_release +EXPORT_SYMBOL net/ax25/ax25 0xc1444946 ax25cmp +EXPORT_SYMBOL net/ax25/ax25 0xc7b8aa0a ax25_listen_release +EXPORT_SYMBOL net/ax25/ax25 0xd271e5d5 ax25_linkfail_register +EXPORT_SYMBOL net/ax25/ax25 0xd43ecbf1 null_ax25_address +EXPORT_SYMBOL net/ax25/ax25 0xdd84f5c9 ax25_header_ops +EXPORT_SYMBOL net/ax25/ax25 0xee3bb3cf ax25_find_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0x038497df hci_register_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x05ef3f44 bt_sock_wait_state +EXPORT_SYMBOL net/bluetooth/bluetooth 0x0d2eaf0b hci_send_sco +EXPORT_SYMBOL net/bluetooth/bluetooth 0x1d268e4c bt_sock_register +EXPORT_SYMBOL net/bluetooth/bluetooth 0x27241618 hci_conn_encrypt +EXPORT_SYMBOL net/bluetooth/bluetooth 0x2eb51c2b hci_resume_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x4d9fc26b hci_unregister_proto +EXPORT_SYMBOL net/bluetooth/bluetooth 0x54fdef52 bt_sock_ioctl +EXPORT_SYMBOL net/bluetooth/bluetooth 0x57a538ea bt_accept_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0x58b6718d hci_conn_auth +EXPORT_SYMBOL net/bluetooth/bluetooth 0x5eafe9d5 bt_sock_poll +EXPORT_SYMBOL net/bluetooth/bluetooth 0x63941f93 hci_unregister_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6403d8bd hci_free_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6bfd4bbb bt_sock_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6c7c5c54 hci_suspend_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6d2bdf31 hci_alloc_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x7094f8ae bt_err +EXPORT_SYMBOL net/bluetooth/bluetooth 0x789c4247 hci_conn_change_link_key +EXPORT_SYMBOL net/bluetooth/bluetooth 0x7ec71991 bt_sock_link +EXPORT_SYMBOL net/bluetooth/bluetooth 0x9acb42c7 hci_recv_fragment +EXPORT_SYMBOL net/bluetooth/bluetooth 0x9c1c1d14 bt_accept_dequeue +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb75cdb2d bt_accept_enqueue +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb91ceb55 bt_sock_recvmsg +EXPORT_SYMBOL net/bluetooth/bluetooth 0xbceec2b5 hci_connect +EXPORT_SYMBOL net/bluetooth/bluetooth 0xc2066af0 batostr +EXPORT_SYMBOL net/bluetooth/bluetooth 0xcc1fb551 baswap +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe152e57a hci_register_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe679537c hci_send_acl +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe6fa0c83 hci_conn_switch_role +EXPORT_SYMBOL net/bluetooth/bluetooth 0xef0b516f hci_unregister_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf19294db bt_sock_unregister +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf1c0a40b hci_conn_check_link_mode +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf63251ef hci_get_route +EXPORT_SYMBOL net/bluetooth/bluetooth 0xfa1cf7a6 hci_register_proto +EXPORT_SYMBOL net/bluetooth/l2cap 0xfc31fe88 l2cap_load +EXPORT_SYMBOL net/bridge/bridge 0xabf5cde0 br_should_route_hook +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x29517baa ebt_register_watcher +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x2aa6073e ebt_unregister_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x46f147ea ebt_register_match +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x52beff71 ebt_unregister_watcher +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x80cc4b50 ebt_register_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x8bb86fcc ebt_register_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xa803b6fe ebt_unregister_match +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xcf18603c ebt_do_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xed463622 ebt_unregister_table +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1b0ba625 ieee80211_get_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1b859565 free_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1c978c78 ieee80211_wx_set_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1cebfbb2 ieee80211_channel_to_index +EXPORT_SYMBOL net/ieee80211/ieee80211 0x21cbe34f alloc_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0x227bbfb0 ieee80211_wx_get_scan +EXPORT_SYMBOL net/ieee80211/ieee80211 0x29f4b971 ieee80211_wx_get_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0x2b166f35 ieee80211_wx_set_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0x31837a27 ieee80211_channel_to_freq +EXPORT_SYMBOL net/ieee80211/ieee80211 0x378e1a24 ieee80211_get_channel_flags +EXPORT_SYMBOL net/ieee80211/ieee80211 0x3be20415 ieee80211_freq_to_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x5ade4306 ieee80211_get_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0xa9fb135f escape_essid +EXPORT_SYMBOL net/ieee80211/ieee80211 0xc4faef45 ieee80211_txb_free +EXPORT_SYMBOL net/ieee80211/ieee80211 0xcb7e3e55 ieee80211_rx_mgt +EXPORT_SYMBOL net/ieee80211/ieee80211 0xcc4fe16c ieee80211_rx +EXPORT_SYMBOL net/ieee80211/ieee80211 0xce841d66 ieee80211_is_valid_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0xd7d10093 ieee80211_set_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0xf26248ab ieee80211_wx_get_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x063fcd53 ieee80211_crypt_delayed_deinit +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x279e265f ieee80211_crypt_deinit_handler +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x443366e9 ieee80211_crypt_deinit_entries +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x5c6b905b ieee80211_get_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x92408820 ieee80211_register_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x98dd59fb ieee80211_unregister_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0xb13b48c6 ieee80211_crypt_quiescing +EXPORT_SYMBOL net/ipv4/inet_lro 0x22cd7629 lro_vlan_hwaccel_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0x377ff295 lro_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0x55baf200 lro_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0x8a074a7f lro_flush_pkt +EXPORT_SYMBOL net/ipv4/inet_lro 0x9dbc62c3 lro_vlan_hwaccel_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0xae62b68a lro_flush_all +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x0b4cba4a ip_vs_tcp_conn_listen +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x2d096edc ip_vs_conn_out_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x4682726f ip_vs_conn_put +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x65b6facb ip_vs_conn_in_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x663f76c9 ip_vs_conn_new +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x979eeeab unregister_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xa1dbc2d8 ip_vs_proto_name +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xbc899c49 register_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xbf70b8bc ip_vs_skb_replace +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xd9354bbc register_ip_vs_app_inc +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xf32ef3fb unregister_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xfb19a0b6 register_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x671f68de arpt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x69ee09e0 arpt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0xfc097145 arpt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x1584d27e ipt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x16bdebc4 ipt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x91cbce6f ipt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x093387d2 nf_nat_setup_info +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x1a54ca27 nf_nat_follow_master +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x3cb45a8b nf_nat_mangle_tcp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x4034cdee nf_nat_mangle_udp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x562ffd0d nf_nat_protocol_unregister +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xaa5f941a nf_nat_protocol_register +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xcf5f7ac6 nf_nat_used_tuple +EXPORT_SYMBOL net/ipv4/tunnel4 0x59a53238 xfrm4_tunnel_deregister +EXPORT_SYMBOL net/ipv4/tunnel4 0xf108afcb xfrm4_tunnel_register +EXPORT_SYMBOL net/ipv6/ipv6 0x01122150 inet6_ioctl +EXPORT_SYMBOL net/ipv6/ipv6 0x03db631c ipv6_getsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x05abd895 ipv6_chk_prefix +EXPORT_SYMBOL net/ipv6/ipv6 0x0ad0d02d icmpv6_send +EXPORT_SYMBOL net/ipv6/ipv6 0x203fde1f inet6_del_protocol +EXPORT_SYMBOL net/ipv6/ipv6 0x30123eb5 icmpv6_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0x31db235c xfrm6_input_addr +EXPORT_SYMBOL net/ipv6/ipv6 0x45caf022 xfrm6_find_1stfragopt +EXPORT_SYMBOL net/ipv6/ipv6 0x4a233e0f ip6_frag_init +EXPORT_SYMBOL net/ipv6/ipv6 0x538383c0 unregister_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0x55347044 ndisc_mc_map +EXPORT_SYMBOL net/ipv6/ipv6 0x5b6f2d59 xfrm6_rcv_spi +EXPORT_SYMBOL net/ipv6/ipv6 0x5be4aad6 rt6_lookup +EXPORT_SYMBOL net/ipv6/ipv6 0x636782ae inet6_getname +EXPORT_SYMBOL net/ipv6/ipv6 0x6536aa78 inet6_unregister_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0x67c9cad8 inet6_bind +EXPORT_SYMBOL net/ipv6/ipv6 0x6d8a65a5 compat_ipv6_getsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x6e134c94 ip6_route_me_harder +EXPORT_SYMBOL net/ipv6/ipv6 0x79a4eab3 nf_ip6_checksum +EXPORT_SYMBOL net/ipv6/ipv6 0x7c82a4c9 ipv6_dev_get_saddr +EXPORT_SYMBOL net/ipv6/ipv6 0x7f499f05 compat_ipv6_setsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x8a9d08dc xfrm6_prepare_output +EXPORT_SYMBOL net/ipv6/ipv6 0x964a4a3e ipv6_push_nfrag_opts +EXPORT_SYMBOL net/ipv6/ipv6 0xa7ac9e94 in6_dev_finish_destroy +EXPORT_SYMBOL net/ipv6/ipv6 0xafb7bd1a inet6_register_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0xb7919eda inet6_release +EXPORT_SYMBOL net/ipv6/ipv6 0xb905ad82 icmpv6_err_convert +EXPORT_SYMBOL net/ipv6/ipv6 0xb98994a1 inet6_add_protocol +EXPORT_SYMBOL net/ipv6/ipv6 0xbd20a440 ip6_frag_match +EXPORT_SYMBOL net/ipv6/ipv6 0xca46c664 ipv6_setsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0xce19bac5 register_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0xd4a62844 xfrm6_rcv +EXPORT_SYMBOL net/ipv6/ipv6 0xe1a81c3a icmpv6msg_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0xe690b8fd __ipv6_isatap_ifid +EXPORT_SYMBOL net/ipv6/ipv6 0xf14d638a ip6_route_output +EXPORT_SYMBOL net/ipv6/ipv6 0xf2580bf0 ip6_xmit +EXPORT_SYMBOL net/ipv6/ipv6 0xfbef045f ipv6_chk_addr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x1b34cbe0 ip6t_register_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x5ea20186 ip6t_do_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xa5abd6cf ip6t_unregister_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xb8bddf33 ip6t_ext_hdr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xe173f955 ipv6_find_hdr +EXPORT_SYMBOL net/ipv6/tunnel6 0x2b7d2ce6 xfrm6_tunnel_deregister +EXPORT_SYMBOL net/ipv6/tunnel6 0x9daa7e31 xfrm6_tunnel_register +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0x9cd013f2 xfrm6_tunnel_alloc_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xab14e193 xfrm6_tunnel_free_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xdb1b42d1 xfrm6_tunnel_spi_lookup +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x1f8c4c0e ircomm_control_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x26cdb332 ircomm_close +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x38b5acd8 ircomm_open +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x7e654f44 ircomm_connect_response +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xb1d2cf8a ircomm_data_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xb32bd596 ircomm_disconnect_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xca057ca9 ircomm_connect_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xf739607b ircomm_flow_request +EXPORT_SYMBOL net/irda/irda 0x01d1fcdb hashbin_delete +EXPORT_SYMBOL net/irda/irda 0x06a3ee58 irias_new_integer_value +EXPORT_SYMBOL net/irda/irda 0x072e026f irias_add_octseq_attrib +EXPORT_SYMBOL net/irda/irda 0x07d3647c irlmp_register_service +EXPORT_SYMBOL net/irda/irda 0x12df9f01 irda_notify_init +EXPORT_SYMBOL net/irda/irda 0x1a6c4e98 iriap_open +EXPORT_SYMBOL net/irda/irda 0x1b5fc2b0 irttp_udata_request +EXPORT_SYMBOL net/irda/irda 0x1f7c64ca irlmp_connect_request +EXPORT_SYMBOL net/irda/irda 0x2036ad06 irda_param_insert +EXPORT_SYMBOL net/irda/irda 0x226b9c3a irlmp_data_request +EXPORT_SYMBOL net/irda/irda 0x28e945c2 irlmp_close_lsap +EXPORT_SYMBOL net/irda/irda 0x2e39a064 irttp_open_tsap +EXPORT_SYMBOL net/irda/irda 0x31c90dea irttp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0x3462950f hashbin_remove +EXPORT_SYMBOL net/irda/irda 0x38a20e5b irda_debug +EXPORT_SYMBOL net/irda/irda 0x3f4d0058 irlap_open +EXPORT_SYMBOL net/irda/irda 0x42fc899a irttp_close_tsap +EXPORT_SYMBOL net/irda/irda 0x448b8aaa irda_qos_bits_to_value +EXPORT_SYMBOL net/irda/irda 0x460fcf5f irda_device_set_media_busy +EXPORT_SYMBOL net/irda/irda 0x46c1c4a2 irlmp_unregister_service +EXPORT_SYMBOL net/irda/irda 0x59f0cb0f iriap_close +EXPORT_SYMBOL net/irda/irda 0x5a62f87a irttp_data_request +EXPORT_SYMBOL net/irda/irda 0x5b6d1eaa alloc_irdadev +EXPORT_SYMBOL net/irda/irda 0x615f6e12 irlmp_connect_response +EXPORT_SYMBOL net/irda/irda 0x6758f8ac irias_new_object +EXPORT_SYMBOL net/irda/irda 0x68b7447c hashbin_find +EXPORT_SYMBOL net/irda/irda 0x6ab7675c async_wrap_skb +EXPORT_SYMBOL net/irda/irda 0x6b043eba irda_init_max_qos_capabilies +EXPORT_SYMBOL net/irda/irda 0x7042bc54 irlmp_register_client +EXPORT_SYMBOL net/irda/irda 0x70d576d6 irttp_connect_response +EXPORT_SYMBOL net/irda/irda 0x747d6779 irias_delete_object +EXPORT_SYMBOL net/irda/irda 0x7621e908 hashbin_insert +EXPORT_SYMBOL net/irda/irda 0x76243bc9 irias_insert_object +EXPORT_SYMBOL net/irda/irda 0x763e54a4 irlmp_unregister_client +EXPORT_SYMBOL net/irda/irda 0x781e2db5 irias_find_object +EXPORT_SYMBOL net/irda/irda 0x7957f728 irlmp_update_client +EXPORT_SYMBOL net/irda/irda 0x7a57b6f3 hashbin_remove_this +EXPORT_SYMBOL net/irda/irda 0x7c33601b irlap_close +EXPORT_SYMBOL net/irda/irda 0x866a7dd4 irlmp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0x91815586 irda_param_pack +EXPORT_SYMBOL net/irda/irda 0x94a40001 proc_irda +EXPORT_SYMBOL net/irda/irda 0x993ad14b irda_param_extract_all +EXPORT_SYMBOL net/irda/irda 0x9c44e3c3 async_unwrap_char +EXPORT_SYMBOL net/irda/irda 0xb4cbf708 irttp_dup +EXPORT_SYMBOL net/irda/irda 0xb9394173 irias_delete_value +EXPORT_SYMBOL net/irda/irda 0xbcd3ef13 irias_object_change_attribute +EXPORT_SYMBOL net/irda/irda 0xbe40ace9 irlmp_discovery_request +EXPORT_SYMBOL net/irda/irda 0xc14e9b6a hashbin_get_next +EXPORT_SYMBOL net/irda/irda 0xc3f4fe15 irttp_flow_request +EXPORT_SYMBOL net/irda/irda 0xc62dc6b2 irlmp_open_lsap +EXPORT_SYMBOL net/irda/irda 0xcb599590 iriap_getvaluebyclass_request +EXPORT_SYMBOL net/irda/irda 0xcd41236c hashbin_new +EXPORT_SYMBOL net/irda/irda 0xd6deeaae irda_setup_dma +EXPORT_SYMBOL net/irda/irda 0xd7172ff4 hashbin_get_first +EXPORT_SYMBOL net/irda/irda 0xd8bfb6d4 hashbin_lock_find +EXPORT_SYMBOL net/irda/irda 0xdda6747f irttp_connect_request +EXPORT_SYMBOL net/irda/irda 0xde4c6b3c irlmp_service_to_hint +EXPORT_SYMBOL net/irda/irda 0xe5260e0e irias_add_integer_attrib +EXPORT_SYMBOL net/irda/irda 0xec41fe7f irias_add_string_attrib +EXPORT_SYMBOL net/irda/irda 0xedd521c2 irlmp_get_discoveries +EXPORT_SYMBOL net/lapb/lapb 0x0483e3d8 lapb_register +EXPORT_SYMBOL net/lapb/lapb 0x04e095f9 lapb_data_request +EXPORT_SYMBOL net/lapb/lapb 0x9de9338f lapb_connect_request +EXPORT_SYMBOL net/lapb/lapb 0xc757fe28 lapb_getparms +EXPORT_SYMBOL net/lapb/lapb 0xc8f5da54 lapb_disconnect_request +EXPORT_SYMBOL net/lapb/lapb 0xd001e376 lapb_data_received +EXPORT_SYMBOL net/lapb/lapb 0xd435884f lapb_setparms +EXPORT_SYMBOL net/lapb/lapb 0xf01d1ab2 lapb_unregister +EXPORT_SYMBOL net/mac80211/mac80211 0x02966e4b ieee80211_rts_get +EXPORT_SYMBOL net/mac80211/mac80211 0x0a8ed1d4 ieee80211_scan_completed +EXPORT_SYMBOL net/mac80211/mac80211 0x0bfd6249 ieee80211_stop_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0x10480ced sta_info_get +EXPORT_SYMBOL net/mac80211/mac80211 0x348653eb ieee80211_tx_status_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x35e8e02a __ieee80211_rx +EXPORT_SYMBOL net/mac80211/mac80211 0x3df78e8c ieee80211_ctstoself_get +EXPORT_SYMBOL net/mac80211/mac80211 0x4721f1c7 ieee80211_ctstoself_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x4762cfe1 ieee80211_generic_frame_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x47ac2cfd ieee80211_rx_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x49ef338b ieee80211_get_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x4cad1306 ieee80211_stop_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x5061b68d ieee80211_start_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x5110a491 ieee80211_stop_queue +EXPORT_SYMBOL net/mac80211/mac80211 0x56808db7 __ieee80211_get_rx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x6107faaf __ieee80211_get_assoc_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x65934f6c ieee80211_stop_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x6f67cdaf ieee80211_stop_queues +EXPORT_SYMBOL net/mac80211/mac80211 0x791a6f6f ieee80211_start_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x798426c8 ieee80211_register_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x7d8bea01 ieee80211_start_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0x7e8cf9bb ieee80211_get_buffered_bc +EXPORT_SYMBOL net/mac80211/mac80211 0x8588ef14 __ieee80211_get_radio_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x8c35d732 ieee80211_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x972ff836 ieee80211_free_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xa8bf44c2 ieee80211_rts_duration +EXPORT_SYMBOL net/mac80211/mac80211 0xabef9696 ieee80211_beacon_get +EXPORT_SYMBOL net/mac80211/mac80211 0xad56935a ieee80211_rate_control_unregister +EXPORT_SYMBOL net/mac80211/mac80211 0xaefdfd66 ieee80211_notify_mac +EXPORT_SYMBOL net/mac80211/mac80211 0xb641c503 ieee80211_get_tkip_key +EXPORT_SYMBOL net/mac80211/mac80211 0xb65dd0eb ieee80211_tx_status +EXPORT_SYMBOL net/mac80211/mac80211 0xbdc6afcc ieee80211_alloc_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xc5d11351 ieee80211_get_hdrlen_from_skb +EXPORT_SYMBOL net/mac80211/mac80211 0xdc3248fb ieee80211_wake_queues +EXPORT_SYMBOL net/mac80211/mac80211 0xdc9d3eaf ieee80211_unregister_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xe39b9ab3 ieee80211_wake_queue +EXPORT_SYMBOL net/mac80211/mac80211 0xec8e3b9c ieee80211_rate_control_register +EXPORT_SYMBOL net/mac80211/mac80211 0xfd77d9be __ieee80211_get_tx_led_name +EXPORT_SYMBOL net/netfilter/nf_conntrack 0x8fb4ee7a __nf_ct_ext_destroy +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xe372c1b6 __nf_ct_ext_add +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xed23741c per_cpu__nf_conntrack_stat +EXPORT_SYMBOL net/netfilter/nf_conntrack_proto_gre 0x82f94e40 nf_ct_gre_keymap_flush +EXPORT_SYMBOL net/netfilter/x_tables 0x058606dd xt_unregister_matches +EXPORT_SYMBOL net/netfilter/x_tables 0x0fc50a43 xt_unregister_match +EXPORT_SYMBOL net/netfilter/x_tables 0x3dcd58c5 xt_alloc_table_info +EXPORT_SYMBOL net/netfilter/x_tables 0x4b9e7a21 xt_register_targets +EXPORT_SYMBOL net/netfilter/x_tables 0x4e971552 xt_find_match +EXPORT_SYMBOL net/netfilter/x_tables 0x6a2bcb35 xt_find_target +EXPORT_SYMBOL net/netfilter/x_tables 0x77b483bb xt_register_matches +EXPORT_SYMBOL net/netfilter/x_tables 0xaf641f7b xt_register_match +EXPORT_SYMBOL net/netfilter/x_tables 0xb8da48ae xt_unregister_target +EXPORT_SYMBOL net/netfilter/x_tables 0xcf63b93f xt_register_target +EXPORT_SYMBOL net/netfilter/x_tables 0xef78e7ef xt_unregister_targets +EXPORT_SYMBOL net/netfilter/x_tables 0xf7037dc6 xt_free_table_info +EXPORT_SYMBOL net/rfkill/rfkill 0x00caa4dc rfkill_switch_all +EXPORT_SYMBOL net/rfkill/rfkill 0x39b8d0b4 rfkill_force_state +EXPORT_SYMBOL net/rfkill/rfkill 0x922403d1 rfkill_register +EXPORT_SYMBOL net/rfkill/rfkill 0x970421d5 rfkill_allocate +EXPORT_SYMBOL net/rfkill/rfkill 0xa8ca9fb3 rfkill_free +EXPORT_SYMBOL net/rfkill/rfkill 0xffe113fb rfkill_unregister +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x039ff6c4 rxrpc_kernel_accept_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x1699af2a rxrpc_kernel_end_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x1e050a28 key_type_rxrpc +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x3ec009ae rxrpc_kernel_data_delivered +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x4479dd43 rxrpc_kernel_reject_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x4af943e7 rxrpc_kernel_get_error_number +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x61d5a4f5 rxrpc_get_server_data_key +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x6a211871 rxrpc_kernel_is_data_last +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x92db01ed rxrpc_kernel_abort_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x962925f5 rxrpc_kernel_intercept_rx_messages +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xae046a2a rxrpc_get_null_key +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xcfa2b0ad rxrpc_kernel_begin_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xe9e0e3f9 rxrpc_kernel_get_abort_code +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xef2f33a1 rxrpc_kernel_free_skb +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xf7c601e8 rxrpc_kernel_send_data +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x00c52ef5 g_make_token_header +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x452ec7b9 gss_mech_get_by_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x48f84627 gss_mech_register +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x51d66cd3 gss_service_to_auth_domain_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x5486480e gss_pseudoflavor_to_service +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x63620bc7 gss_mech_get_by_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x8d1a827e svcauth_gss_register_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x92672848 gss_mech_get +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xa305512f gss_mech_put +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xb0e17bd4 gss_svc_to_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xb5dea7ef g_token_size +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xc31bb181 svcauth_gss_flavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xee2edf46 gss_mech_unregister +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xf8b2ff6e g_verify_token_header +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0085f236 sunrpc_cache_update +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0372abd5 auth_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0x05e807a9 xdr_encode_string +EXPORT_SYMBOL net/sunrpc/sunrpc 0x065994f1 xdr_encode_opaque_fixed +EXPORT_SYMBOL net/sunrpc/sunrpc 0x09bb139b svc_sock_names +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0a2f867b xdr_buf_from_iov +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0cae649a xdr_init_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0f668ba9 svc_auth_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x1241d4d9 svc_set_num_threads +EXPORT_SYMBOL net/sunrpc/sunrpc 0x12e280e3 svc_proc_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x152877f6 read_bytes_from_xdr_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x20672151 xdr_buf_read_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2919b156 xdr_decode_string_inplace +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2eec63c9 xdr_encode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2f71f67a svc_create +EXPORT_SYMBOL net/sunrpc/sunrpc 0x305e86f0 xdr_read_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x32cd3f21 auth_domain_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x35985b95 auth_unix_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3718d724 xdr_write_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x39a4c5c1 xdr_encode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3de44b43 svc_process +EXPORT_SYMBOL net/sunrpc/sunrpc 0x4631620b svc_reserve +EXPORT_SYMBOL net/sunrpc/sunrpc 0x52e30c35 xdr_encode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0x54ca3745 xdr_inline_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5b45f4e3 svc_create_pooled +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5e1a9773 svc_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5f286359 svc_prepare_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0x66b754ca svc_wake_up +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6eea229d svcauth_unix_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0x70e4cd4e svc_sock_update_bufs +EXPORT_SYMBOL net/sunrpc/sunrpc 0x71e08d9a cache_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x71fa908a cache_flush +EXPORT_SYMBOL net/sunrpc/sunrpc 0x82b381ca xdr_enter_page +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8a1e42e1 svc_recv +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8ba38497 xdr_buf_subsegment +EXPORT_SYMBOL net/sunrpc/sunrpc 0x93df893f xdr_process_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x945ee224 sunrpc_cache_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9467b84c svcauth_unix_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0x962f99e0 unix_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9661dfe8 svc_seq_show +EXPORT_SYMBOL net/sunrpc/sunrpc 0xb7acd895 xdr_decode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0xb8f982a2 xdr_init_encode +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbb409557 cache_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbbd33984 svc_auth_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbc53fe75 svc_destroy +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbff3d537 auth_domain_put +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc2da29c8 auth_unix_add_addr +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc3880471 xdr_decode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc8e96dea qword_addhex +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd0bab8fd cache_check +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd1e656f1 xdr_decode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd8fb4109 cache_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd93413cc xdr_reserve_space +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd98af402 xdr_encode_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0xdacabb5f xdr_shift_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe5919cb1 xdr_encode_opaque +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe8bd8bb1 svc_exit_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe97f4ce5 qword_get +EXPORT_SYMBOL net/sunrpc/sunrpc 0xedcf6be4 qword_add +EXPORT_SYMBOL net/sunrpc/sunrpc 0xf799fdcd xdr_inline_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfa22f364 rpc_queue_upcall +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfb347954 rpc_unlink +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfc152260 rpc_mkpipe +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfcf63714 svc_proc_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfe6d65cf auth_unix_forget_old +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfe756272 svc_drop +EXPORT_SYMBOL net/sunrpc/sunrpc 0xffed9443 svc_authenticate +EXPORT_SYMBOL net/tipc/tipc 0x06c430a8 tipc_send_buf2port +EXPORT_SYMBOL net/tipc/tipc 0x08acf310 tipc_available_nodes +EXPORT_SYMBOL net/tipc/tipc 0x0b074a7b tipc_multicast +EXPORT_SYMBOL net/tipc/tipc 0x10d40fcd tipc_isconnected +EXPORT_SYMBOL net/tipc/tipc 0x1472b270 tipc_disconnect +EXPORT_SYMBOL net/tipc/tipc 0x1479cb03 tipc_deleteport +EXPORT_SYMBOL net/tipc/tipc 0x14d417ab tipc_reject_msg +EXPORT_SYMBOL net/tipc/tipc 0x15b5ecde tipc_set_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x16f27683 tipc_block_bearer +EXPORT_SYMBOL net/tipc/tipc 0x23daecbd tipc_send +EXPORT_SYMBOL net/tipc/tipc 0x259b74f9 tipc_acknowledge +EXPORT_SYMBOL net/tipc/tipc 0x310d1bc9 tipc_detach +EXPORT_SYMBOL net/tipc/tipc 0x3712e340 tipc_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x3976041f tipc_set_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x419b02fc tipc_send2port +EXPORT_SYMBOL net/tipc/tipc 0x4b2243c6 tipc_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x538b228a tipc_withdraw +EXPORT_SYMBOL net/tipc/tipc 0x5637ed44 tipc_get_mode +EXPORT_SYMBOL net/tipc/tipc 0x56e52bc1 tipc_continue +EXPORT_SYMBOL net/tipc/tipc 0x5b951051 tipc_forward_buf2name +EXPORT_SYMBOL net/tipc/tipc 0x5c0d4b5c tipc_ref_valid +EXPORT_SYMBOL net/tipc/tipc 0x62a681a3 tipc_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0x66e9c3ff tipc_send_buf +EXPORT_SYMBOL net/tipc/tipc 0x84eda213 tipc_send_buf2name +EXPORT_SYMBOL net/tipc/tipc 0x86f8f2df tipc_createport_raw +EXPORT_SYMBOL net/tipc/tipc 0x88b73627 tipc_get_addr +EXPORT_SYMBOL net/tipc/tipc 0x9c45558e tipc_enable_bearer +EXPORT_SYMBOL net/tipc/tipc 0xa1b42d32 tipc_forward2port +EXPORT_SYMBOL net/tipc/tipc 0xa30962e9 tipc_send_buf_fast +EXPORT_SYMBOL net/tipc/tipc 0xa936a24b tipc_get_port +EXPORT_SYMBOL net/tipc/tipc 0xadd203d0 tipc_connect2port +EXPORT_SYMBOL net/tipc/tipc 0xae0103c3 tipc_shutdown +EXPORT_SYMBOL net/tipc/tipc 0xb1f8eacc tipc_send2name +EXPORT_SYMBOL net/tipc/tipc 0xb35b672c tipc_publish +EXPORT_SYMBOL net/tipc/tipc 0xbc9e0e2c tipc_createport +EXPORT_SYMBOL net/tipc/tipc 0xcec8514a tipc_set_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0xcee290be tipc_forward2name +EXPORT_SYMBOL net/tipc/tipc 0xd17d954e tipc_recv_msg +EXPORT_SYMBOL net/tipc/tipc 0xd44731e5 tipc_ownidentity +EXPORT_SYMBOL net/tipc/tipc 0xd708ca84 tipc_forward_buf2port +EXPORT_SYMBOL net/tipc/tipc 0xda7f9d3f tipc_attach +EXPORT_SYMBOL net/tipc/tipc 0xdf5008fc tipc_peer +EXPORT_SYMBOL net/tipc/tipc 0xe7aece47 tipc_ispublished +EXPORT_SYMBOL net/tipc/tipc 0xea703c36 tipc_register_media +EXPORT_SYMBOL net/tipc/tipc 0xeefd49b3 tipc_get_handle +EXPORT_SYMBOL net/tipc/tipc 0xef50a1ef tipc_disable_bearer +EXPORT_SYMBOL net/wanrouter/wanrouter 0x0ebe03d1 unregister_wan_device +EXPORT_SYMBOL net/wanrouter/wanrouter 0x87487a8e register_wan_device +EXPORT_SYMBOL net/wireless/cfg80211 0x07e7ac5a ieee80211_radiotap_iterator_init +EXPORT_SYMBOL net/wireless/cfg80211 0x09c64fbd ieee80211_frequency_to_channel +EXPORT_SYMBOL net/wireless/cfg80211 0x288f266b wiphy_new +EXPORT_SYMBOL net/wireless/cfg80211 0x47d44dd8 wiphy_register +EXPORT_SYMBOL net/wireless/cfg80211 0x58561e2f wiphy_unregister +EXPORT_SYMBOL net/wireless/cfg80211 0x63eab0c5 wiphy_free +EXPORT_SYMBOL net/wireless/cfg80211 0xbcb4137e __ieee80211_get_channel +EXPORT_SYMBOL net/wireless/cfg80211 0xc4e85ec5 ieee80211_radiotap_iterator_next +EXPORT_SYMBOL net/wireless/cfg80211 0xccc291b3 ieee80211_channel_to_frequency +EXPORT_SYMBOL sound/ac97_bus 0xa370459a ac97_bus_type +EXPORT_SYMBOL sound/core/oss/snd-mixer-oss 0xeea74dd5 snd_mixer_oss_ioctl_card +EXPORT_SYMBOL sound/core/seq/snd-seq 0x1a724fcc snd_seq_kernel_client_ctl +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3061c52d snd_use_lock_sync_helper +EXPORT_SYMBOL sound/core/seq/snd-seq 0x32ceb3dd snd_seq_event_port_attach +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3fb4d161 snd_seq_kernel_client_dispatch +EXPORT_SYMBOL sound/core/seq/snd-seq 0x4579a750 snd_seq_kernel_client_write_poll +EXPORT_SYMBOL sound/core/seq/snd-seq 0x6bb71038 snd_seq_delete_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7ac2f329 snd_seq_expand_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7b8699eb snd_seq_event_port_detach +EXPORT_SYMBOL sound/core/seq/snd-seq 0xb8e448a0 snd_seq_set_queue_tempo +EXPORT_SYMBOL sound/core/seq/snd-seq 0xbc037875 snd_seq_kernel_client_enqueue_blocking +EXPORT_SYMBOL sound/core/seq/snd-seq 0xc5a3315d snd_seq_create_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq 0xcac0a3be snd_seq_kernel_client_enqueue +EXPORT_SYMBOL sound/core/seq/snd-seq 0xe934da1d snd_seq_dump_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x2cfa236f snd_seq_device_new +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x3a57f235 snd_seq_autoload_unlock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x6339b6d0 snd_seq_device_load_drivers +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x74a6dff0 snd_seq_device_register_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xb90668b2 snd_seq_autoload_lock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xc622fb29 snd_seq_device_unregister_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x6ea09972 snd_midi_channel_alloc_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x833a3e07 snd_midi_channel_set_clear +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xb9948d2c snd_midi_channel_free_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xf0a1fdb3 snd_midi_process_event +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x17c15809 snd_midi_event_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x4ad3f518 snd_midi_event_reset_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x62384d3a snd_midi_event_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x8a348811 snd_midi_event_reset_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x9df7af8b snd_midi_event_free +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xc482499d snd_midi_event_new +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xd9072e1a snd_midi_event_no_status +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xe6df29c7 snd_midi_event_encode_byte +EXPORT_SYMBOL sound/core/seq/snd-seq-virmidi 0x40586a84 snd_virmidi_new +EXPORT_SYMBOL sound/core/snd 0x024545c3 snd_info_create_card_entry +EXPORT_SYMBOL sound/core/snd 0x0e02a142 snd_ctl_remove_id +EXPORT_SYMBOL sound/core/snd 0x1090b32e snd_ctl_find_numid +EXPORT_SYMBOL sound/core/snd 0x18e1683f snd_dma_program +EXPORT_SYMBOL sound/core/snd 0x191e88cf snd_dma_pointer +EXPORT_SYMBOL sound/core/snd 0x198788b4 snd_lookup_oss_minor_data +EXPORT_SYMBOL sound/core/snd 0x1f898c13 snd_add_device_sysfs_file +EXPORT_SYMBOL sound/core/snd 0x23d31632 snd_ctl_rename_id +EXPORT_SYMBOL sound/core/snd 0x24a94b26 snd_info_get_line +EXPORT_SYMBOL sound/core/snd 0x252dadd3 snd_pci_quirk_lookup +EXPORT_SYMBOL sound/core/snd 0x274b75ea snd_device_free +EXPORT_SYMBOL sound/core/snd 0x2b1e91c5 snd_info_create_module_entry +EXPORT_SYMBOL sound/core/snd 0x2d3c8322 snd_card_free +EXPORT_SYMBOL sound/core/snd 0x2fa6dc2d snd_card_register +EXPORT_SYMBOL sound/core/snd 0x36e4fc29 snd_ctl_find_id +EXPORT_SYMBOL sound/core/snd 0x376e04bf release_and_free_resource +EXPORT_SYMBOL sound/core/snd 0x3971b4df snd_ecards_limit +EXPORT_SYMBOL sound/core/snd 0x427f598f snd_ctl_add +EXPORT_SYMBOL sound/core/snd 0x4a3ea5c0 snd_request_card +EXPORT_SYMBOL sound/core/snd 0x518bb7f8 copy_from_user_toio +EXPORT_SYMBOL sound/core/snd 0x53828a7c snd_ctl_new1 +EXPORT_SYMBOL sound/core/snd 0x569fe16d snd_component_add +EXPORT_SYMBOL sound/core/snd 0x5ae75510 snd_ctl_unregister_ioctl_compat +EXPORT_SYMBOL sound/core/snd 0x5ee12a00 snd_unregister_device +EXPORT_SYMBOL sound/core/snd 0x62a9d369 snd_card_file_add +EXPORT_SYMBOL sound/core/snd 0x665692e3 snd_card_proc_new +EXPORT_SYMBOL sound/core/snd 0x69c588c3 snd_card_new +EXPORT_SYMBOL sound/core/snd 0x6bfa26da snd_mixer_oss_notify_callback +EXPORT_SYMBOL sound/core/snd 0x70c15ac1 snd_dma_disable +EXPORT_SYMBOL sound/core/snd 0x73ce1f0b snd_ctl_make_virtual_master +EXPORT_SYMBOL sound/core/snd 0x77946522 snd_cards +EXPORT_SYMBOL sound/core/snd 0x7b4dd75e snd_ctl_remove +EXPORT_SYMBOL sound/core/snd 0x815c8be0 snd_unregister_oss_device +EXPORT_SYMBOL sound/core/snd 0x844f1ad0 snd_ctl_add_slave +EXPORT_SYMBOL sound/core/snd 0x85f78f61 snd_ctl_register_ioctl +EXPORT_SYMBOL sound/core/snd 0x8df3789f snd_oss_info_register +EXPORT_SYMBOL sound/core/snd 0x8f595b11 snd_major +EXPORT_SYMBOL sound/core/snd 0x9d012cfc snd_register_oss_device +EXPORT_SYMBOL sound/core/snd 0xa5f86527 snd_card_free_when_closed +EXPORT_SYMBOL sound/core/snd 0xa753f500 snd_ctl_free_one +EXPORT_SYMBOL sound/core/snd 0xa95a38f5 snd_info_register +EXPORT_SYMBOL sound/core/snd 0xb08daa80 snd_power_wait +EXPORT_SYMBOL sound/core/snd 0xb213fe8b snd_info_get_str +EXPORT_SYMBOL sound/core/snd 0xb2e5ae4a snd_lookup_minor_data +EXPORT_SYMBOL sound/core/snd 0xb50bc653 snd_card_file_remove +EXPORT_SYMBOL sound/core/snd 0xc0e7adf3 snd_ctl_boolean_stereo_info +EXPORT_SYMBOL sound/core/snd 0xc98a86cf snd_card_disconnect +EXPORT_SYMBOL sound/core/snd 0xcca3063a snd_register_device_for_dev +EXPORT_SYMBOL sound/core/snd 0xcf5f7fb8 snd_ctl_boolean_mono_info +EXPORT_SYMBOL sound/core/snd 0xd1351d08 snd_device_new +EXPORT_SYMBOL sound/core/snd 0xe06047f7 snd_info_free_entry +EXPORT_SYMBOL sound/core/snd 0xe147ca89 snd_seq_root +EXPORT_SYMBOL sound/core/snd 0xe243dde3 copy_to_user_fromio +EXPORT_SYMBOL sound/core/snd 0xe4854cea snd_iprintf +EXPORT_SYMBOL sound/core/snd 0xedfe624d snd_ctl_register_ioctl_compat +EXPORT_SYMBOL sound/core/snd 0xf4393bc5 snd_ctl_unregister_ioctl +EXPORT_SYMBOL sound/core/snd 0xf6fe9c18 snd_ctl_notify +EXPORT_SYMBOL sound/core/snd 0xfedc9c4f snd_device_register +EXPORT_SYMBOL sound/core/snd-hwdep 0xf8f241ed snd_hwdep_new +EXPORT_SYMBOL sound/core/snd-page-alloc 0x17e7ccaf snd_dma_alloc_pages_fallback +EXPORT_SYMBOL sound/core/snd-page-alloc 0x19cc2ce3 snd_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x682905e9 snd_dma_alloc_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x7b7daac3 snd_dma_reserve_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x929f75da snd_dma_get_reserved_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x97070bfa snd_dma_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0xc6829020 snd_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x009153fc snd_pcm_release_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x04cda566 snd_interval_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x05c2a781 snd_pcm_hw_rule_add +EXPORT_SYMBOL sound/core/snd-pcm 0x1431e211 snd_pcm_suspend +EXPORT_SYMBOL sound/core/snd-pcm 0x15bc4603 snd_pcm_kernel_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x1d027e4b snd_pcm_format_signed +EXPORT_SYMBOL sound/core/snd-pcm 0x1fe5b895 snd_pcm_notify +EXPORT_SYMBOL sound/core/snd-pcm 0x21c523f4 snd_pcm_suspend_all +EXPORT_SYMBOL sound/core/snd-pcm 0x36d7768c snd_pcm_hw_constraint_list +EXPORT_SYMBOL sound/core/snd-pcm 0x3796bdcc snd_pcm_format_little_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x4bdb8624 snd_pcm_lib_preallocate_pages_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x4f816e9b snd_pcm_format_big_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x56cdd711 snd_pcm_new +EXPORT_SYMBOL sound/core/snd-pcm 0x5e7f4920 snd_pcm_format_set_silence +EXPORT_SYMBOL sound/core/snd-pcm 0x60b53754 snd_pcm_lib_preallocate_free_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x650f8603 snd_pcm_format_silence_64 +EXPORT_SYMBOL sound/core/snd-pcm 0x68a24153 snd_pcm_format_physical_width +EXPORT_SYMBOL sound/core/snd-pcm 0x6ef8fcd8 snd_pcm_format_linear +EXPORT_SYMBOL sound/core/snd-pcm 0x71ac123d snd_pcm_hw_param_last +EXPORT_SYMBOL sound/core/snd-pcm 0x753d1b0d snd_pcm_lib_write +EXPORT_SYMBOL sound/core/snd-pcm 0x7c5cec98 _snd_pcm_hw_params_any +EXPORT_SYMBOL sound/core/snd-pcm 0x7c8f614a snd_pcm_hw_constraint_integer +EXPORT_SYMBOL sound/core/snd-pcm 0x80a182d4 snd_pcm_lib_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x8518e788 snd_pcm_hw_param_first +EXPORT_SYMBOL sound/core/snd-pcm 0x88cc66cc snd_pcm_link_rwlock +EXPORT_SYMBOL sound/core/snd-pcm 0x89a31a56 _snd_pcm_hw_param_setempty +EXPORT_SYMBOL sound/core/snd-pcm 0x8ff35032 snd_pcm_new_stream +EXPORT_SYMBOL sound/core/snd-pcm 0x931b522a snd_pcm_set_ops +EXPORT_SYMBOL sound/core/snd-pcm 0x9d06d4d5 snd_pcm_hw_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x9d5a1f7c snd_pcm_period_elapsed +EXPORT_SYMBOL sound/core/snd-pcm 0x9f3a7d28 snd_pcm_hw_constraint_ratdens +EXPORT_SYMBOL sound/core/snd-pcm 0x9fdea959 snd_pcm_hw_param_value +EXPORT_SYMBOL sound/core/snd-pcm 0xa0be1c54 snd_pcm_hw_constraint_minmax +EXPORT_SYMBOL sound/core/snd-pcm 0xa61aa028 snd_pcm_format_unsigned +EXPORT_SYMBOL sound/core/snd-pcm 0xadda757e snd_pcm_hw_constraint_ratnums +EXPORT_SYMBOL sound/core/snd-pcm 0xaea473a2 snd_pcm_stop +EXPORT_SYMBOL sound/core/snd-pcm 0xaf3264e7 snd_pcm_lib_readv +EXPORT_SYMBOL sound/core/snd-pcm 0xb0ac081e snd_pcm_lib_mmap_iomem +EXPORT_SYMBOL sound/core/snd-pcm 0xb162acc0 snd_pcm_hw_constraint_pow2 +EXPORT_SYMBOL sound/core/snd-pcm 0xb53afc28 snd_pcm_hw_constraint_msbits +EXPORT_SYMBOL sound/core/snd-pcm 0xb7347a6a snd_pcm_hw_constraint_step +EXPORT_SYMBOL sound/core/snd-pcm 0xb9638db4 snd_pcm_rate_to_rate_bit +EXPORT_SYMBOL sound/core/snd-pcm 0xc1f2e0a9 snd_pcm_mmap_data +EXPORT_SYMBOL sound/core/snd-pcm 0xc6b5bc99 snd_pcm_lib_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0xca639d7c snd_pcm_lib_free_pages +EXPORT_SYMBOL sound/core/snd-pcm 0xd0b9b8b8 snd_interval_list +EXPORT_SYMBOL sound/core/snd-pcm 0xd4d84cde snd_pcm_lib_read +EXPORT_SYMBOL sound/core/snd-pcm 0xd7acd80c snd_pcm_set_sync +EXPORT_SYMBOL sound/core/snd-pcm 0xd948182f snd_pcm_lib_preallocate_pages +EXPORT_SYMBOL sound/core/snd-pcm 0xe51a1c64 snd_pcm_format_size +EXPORT_SYMBOL sound/core/snd-pcm 0xe56a9336 snd_pcm_format_width +EXPORT_SYMBOL sound/core/snd-pcm 0xe79f2170 snd_pcm_limit_hw_rates +EXPORT_SYMBOL sound/core/snd-pcm 0xf3797152 snd_interval_ratnum +EXPORT_SYMBOL sound/core/snd-pcm 0xfa222410 snd_pcm_open_substream +EXPORT_SYMBOL sound/core/snd-pcm 0xfc174fdc snd_pcm_sgbuf_ops_page +EXPORT_SYMBOL sound/core/snd-pcm 0xff45a66d snd_pcm_lib_writev +EXPORT_SYMBOL sound/core/snd-rawmidi 0x06434470 snd_rawmidi_set_ops +EXPORT_SYMBOL sound/core/snd-rawmidi 0x2dcc2380 snd_rawmidi_transmit_peek +EXPORT_SYMBOL sound/core/snd-rawmidi 0x31a124b4 snd_rawmidi_transmit_ack +EXPORT_SYMBOL sound/core/snd-rawmidi 0x3afebe24 snd_rawmidi_new +EXPORT_SYMBOL sound/core/snd-rawmidi 0x63094fe8 snd_rawmidi_kernel_write +EXPORT_SYMBOL sound/core/snd-rawmidi 0x76590f19 snd_rawmidi_output_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0x865782ad snd_rawmidi_kernel_release +EXPORT_SYMBOL sound/core/snd-rawmidi 0x9fc5fd61 snd_rawmidi_kernel_open +EXPORT_SYMBOL sound/core/snd-rawmidi 0xbda532f3 snd_rawmidi_transmit_empty +EXPORT_SYMBOL sound/core/snd-rawmidi 0xd9e4ebc3 snd_rawmidi_input_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0xdaaffd84 snd_rawmidi_receive +EXPORT_SYMBOL sound/core/snd-rawmidi 0xe88b760c snd_rawmidi_kernel_read +EXPORT_SYMBOL sound/core/snd-rawmidi 0xe8fdf5a4 snd_rawmidi_transmit +EXPORT_SYMBOL sound/core/snd-rawmidi 0xec8e7988 snd_rawmidi_drop_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0xeeb53120 snd_rawmidi_info_select +EXPORT_SYMBOL sound/core/snd-rawmidi 0xf3e58169 snd_rawmidi_drain_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0xff6b8875 snd_rawmidi_drain_input +EXPORT_SYMBOL sound/core/snd-timer 0x0327f43b snd_timer_stop +EXPORT_SYMBOL sound/core/snd-timer 0x0721c98b snd_timer_open +EXPORT_SYMBOL sound/core/snd-timer 0x1474e889 snd_timer_global_free +EXPORT_SYMBOL sound/core/snd-timer 0x1509f1ed snd_timer_interrupt +EXPORT_SYMBOL sound/core/snd-timer 0x26ee9530 snd_timer_global_new +EXPORT_SYMBOL sound/core/snd-timer 0x2ee29886 snd_timer_pause +EXPORT_SYMBOL sound/core/snd-timer 0x3465a203 snd_timer_global_register +EXPORT_SYMBOL sound/core/snd-timer 0x3cb60416 snd_timer_new +EXPORT_SYMBOL sound/core/snd-timer 0x452201c4 snd_timer_close +EXPORT_SYMBOL sound/core/snd-timer 0x5a24df20 snd_timer_start +EXPORT_SYMBOL sound/core/snd-timer 0x6034ad38 snd_timer_resolution +EXPORT_SYMBOL sound/core/snd-timer 0x757ab090 snd_timer_notify +EXPORT_SYMBOL sound/core/snd-timer 0xd91d532d snd_timer_continue +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x73c4c993 snd_mpu401_uart_interrupt_tx +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xcdb9942b snd_mpu401_uart_new +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xfe618b58 snd_mpu401_uart_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x05060a19 snd_opl3_regmap +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x195b928b snd_opl3_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x29dd600c snd_opl3_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x2fddcf77 snd_opl3_timer_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x7ca87361 snd_opl3_reset +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x9c4badd2 snd_opl3_find_patch +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xabcfd06e snd_opl3_init +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xb8d932bb snd_opl3_create +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xd80eab03 snd_opl3_load_patch +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xdb324c7e snd_opl3_hwdep_new +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x1cadb14b snd_vx_irq_handler +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x4e3a6118 snd_vx_load_boot_image +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x51880703 snd_vx_check_reg_bit +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x77415395 snd_vx_create +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x82283bb7 snd_vx_suspend +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x86deeb66 snd_vx_dsp_boot +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xc21a2e5d snd_vx_resume +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xc6c02ea9 snd_vx_free_firmware +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xcbf3aa95 snd_vx_dsp_load +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xcc69dd55 snd_vx_setup_firmware +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x0c2b5588 snd_ak4114_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x46fe5cb9 snd_ak4114_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x76804437 snd_ak4114_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x838459a4 snd_ak4114_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xacf75ad2 snd_ak4114_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xf4ed143d snd_ak4114_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x00c33391 snd_ak4117_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x3a0df681 snd_ak4117_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x3efbbba8 snd_ak4117_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x5ba1e093 snd_ak4117_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x9534f614 snd_ak4117_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xb7800efe snd_ak4117_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x4cc2b626 snd_akm4xxx_reset +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x5e8beaab snd_akm4xxx_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x9e59774e snd_akm4xxx_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xbd4f26b4 snd_akm4xxx_init +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x077a3820 snd_pt2258_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0xb13b7e1b snd_pt2258_reset +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0x1cfc0a30 snd_tea575x_exit +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0xa52ff270 snd_tea575x_init +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x3972febf snd_cs8427_reg_write +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xb344bac0 snd_cs8427_iec958_pcm +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xd361c63f snd_cs8427_iec958_build +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xf07a262e snd_cs8427_iec958_active +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xf8122bee snd_cs8427_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0x19a34414 snd_i2c_bus_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0x999a5a72 snd_i2c_device_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0xdc11f015 snd_i2c_readbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0xe2b39b2f snd_i2c_sendbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0xe6aa7caa snd_i2c_device_free +EXPORT_SYMBOL sound/i2c/snd-i2c 0xf992f403 snd_i2c_probeaddr +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x11284bad snd_sbmixer_new +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x476e2833 snd_sbdsp_create +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x4ef10019 snd_sbdsp_reset +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x5f390f9b snd_sbmixer_add_ctl +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x61338009 snd_sbmixer_suspend +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x86fc4784 snd_sbmixer_read +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x884579e7 snd_sbdsp_get_byte +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x93958b46 snd_sbmixer_resume +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x9cf7a561 snd_sbmixer_write +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xf5de8c93 snd_sbdsp_command +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x0ba4ef1d snd_sb16dsp_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x2ced3235 snd_sb16dsp_pcm +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x849369c2 snd_sb16dsp_get_pcm_ops +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x991a557a snd_sb16dsp_configure +EXPORT_SYMBOL sound/oss/ad1848 0x10e7c768 attach_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x7aa41a6d ad1848_init +EXPORT_SYMBOL sound/oss/ad1848 0x9839a618 probe_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x9bf1cc62 ad1848_unload +EXPORT_SYMBOL sound/oss/ad1848 0xb29a9148 unload_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0xc04f6f67 ad1848_control +EXPORT_SYMBOL sound/oss/ad1848 0xf06eb004 ad1848_detect +EXPORT_SYMBOL sound/oss/mpu401 0x3c4d8646 attach_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0x5febf284 unload_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0x8874e39a probe_mpu401 +EXPORT_SYMBOL sound/oss/sb_lib 0x3628ca3b sb_dsp_init +EXPORT_SYMBOL sound/oss/sb_lib 0x382ea9dd probe_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0x42424109 sb_be_quiet +EXPORT_SYMBOL sound/oss/sb_lib 0x450f9aea smw_free +EXPORT_SYMBOL sound/oss/sb_lib 0x74afd69c unload_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0xc4884969 sb_dsp_unload +EXPORT_SYMBOL sound/oss/sb_lib 0xd8a2731c sb_dsp_detect +EXPORT_SYMBOL sound/oss/sound 0x04c87ec8 compute_finetune +EXPORT_SYMBOL sound/oss/sound 0x06339815 sound_unload_synthdev +EXPORT_SYMBOL sound/oss/sound 0x0f280035 conf_printf +EXPORT_SYMBOL sound/oss/sound 0x17ba231d seq_input_event +EXPORT_SYMBOL sound/oss/sound 0x1b3df3cf sound_alloc_mixerdev +EXPORT_SYMBOL sound/oss/sound 0x1f395686 MIDIbuf_avail +EXPORT_SYMBOL sound/oss/sound 0x2161d5e8 sound_timer_init +EXPORT_SYMBOL sound/oss/sound 0x242f0eb6 sound_install_audiodrv +EXPORT_SYMBOL sound/oss/sound 0x2aa31695 midi_synth_kill_note +EXPORT_SYMBOL sound/oss/sound 0x362b1ad1 synth_devs +EXPORT_SYMBOL sound/oss/sound 0x394cb088 sound_free_dma +EXPORT_SYMBOL sound/oss/sound 0x418f5fbe sound_close_dma +EXPORT_SYMBOL sound/oss/sound 0x4cd01bdd num_audiodevs +EXPORT_SYMBOL sound/oss/sound 0x4ff47e9d midi_synth_setup_voice +EXPORT_SYMBOL sound/oss/sound 0x51e354b2 sound_alloc_timerdev +EXPORT_SYMBOL sound/oss/sound 0x56504ca2 midi_synth_reset +EXPORT_SYMBOL sound/oss/sound 0x5d986fc9 note_to_freq +EXPORT_SYMBOL sound/oss/sound 0x6e2864a5 audio_devs +EXPORT_SYMBOL sound/oss/sound 0x7679ee76 seq_copy_to_input +EXPORT_SYMBOL sound/oss/sound 0x7bdf0907 conf_printf2 +EXPORT_SYMBOL sound/oss/sound 0x892093e0 midi_synth_controller +EXPORT_SYMBOL sound/oss/sound 0x8a760bd6 mixer_devs +EXPORT_SYMBOL sound/oss/sound 0x90bd9714 sequencer_timer +EXPORT_SYMBOL sound/oss/sound 0x987bcf12 DMAbuf_outputintr +EXPORT_SYMBOL sound/oss/sound 0x9a95733f sound_alloc_dma +EXPORT_SYMBOL sound/oss/sound 0x9bdaf24d midi_synth_start_note +EXPORT_SYMBOL sound/oss/sound 0x9d845b18 num_mixers +EXPORT_SYMBOL sound/oss/sound 0xa1d5f04f load_mixer_volumes +EXPORT_SYMBOL sound/oss/sound 0xa1eae7cf num_midis +EXPORT_SYMBOL sound/oss/sound 0xa41ead5f sound_unload_timerdev +EXPORT_SYMBOL sound/oss/sound 0xa51c913b sound_unload_mixerdev +EXPORT_SYMBOL sound/oss/sound 0xa6bb414c sound_unload_mididev +EXPORT_SYMBOL sound/oss/sound 0xa948751e sound_unload_audiodev +EXPORT_SYMBOL sound/oss/sound 0xad45df73 midi_synth_close +EXPORT_SYMBOL sound/oss/sound 0xaef743b2 midi_synth_ioctl +EXPORT_SYMBOL sound/oss/sound 0xb14b22cd midi_synth_hw_control +EXPORT_SYMBOL sound/oss/sound 0xb51587f6 do_midi_msg +EXPORT_SYMBOL sound/oss/sound 0xb5a13106 midi_devs +EXPORT_SYMBOL sound/oss/sound 0xba413f87 sound_alloc_mididev +EXPORT_SYMBOL sound/oss/sound 0xba7dd041 midi_synth_bender +EXPORT_SYMBOL sound/oss/sound 0xc748d109 sound_alloc_synthdev +EXPORT_SYMBOL sound/oss/sound 0xcc4b8797 sound_open_dma +EXPORT_SYMBOL sound/oss/sound 0xd85be938 midi_synth_set_instr +EXPORT_SYMBOL sound/oss/sound 0xdb400afa midi_synth_panning +EXPORT_SYMBOL sound/oss/sound 0xdc54a0f5 sound_timer_devs +EXPORT_SYMBOL sound/oss/sound 0xe056b71c DMAbuf_start_dma +EXPORT_SYMBOL sound/oss/sound 0xe0f063ea sound_install_mixer +EXPORT_SYMBOL sound/oss/sound 0xe2675a79 sound_timer_interrupt +EXPORT_SYMBOL sound/oss/sound 0xeb315d99 DMAbuf_inputintr +EXPORT_SYMBOL sound/oss/sound 0xf1ea8a20 midi_synth_aftertouch +EXPORT_SYMBOL sound/oss/sound 0xf6b3a2fb midi_synth_open +EXPORT_SYMBOL sound/oss/sound 0xf7426da3 midi_synth_load_patch +EXPORT_SYMBOL sound/oss/sound 0xf78f6363 sequencer_init +EXPORT_SYMBOL sound/oss/sound 0xfa6871be sound_timer_syncinterval +EXPORT_SYMBOL sound/oss/sound 0xfddcbfb3 midi_synth_send_sysex +EXPORT_SYMBOL sound/oss/uart401 0x28aba148 probe_uart401 +EXPORT_SYMBOL sound/oss/uart401 0x46248c57 uart401intr +EXPORT_SYMBOL sound/oss/uart401 0xecfdd9c9 unload_uart401 +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x0459ac6f snd_ac97_update_bits +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x06ed3fe3 snd_ac97_set_rate +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x22a04d77 snd_ac97_mixer +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x37ffb04c snd_ac97_resume +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3859aa60 snd_ac97_pcm_double_rate_rules +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x49ca5dba snd_ac97_pcm_close +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x73a28e6d snd_ac97_bus +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x77e164ca snd_ac97_pcm_open +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x87404342 snd_ac97_update_power +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xa83cfca1 snd_ac97_pcm_assign +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xadb1b2ef snd_ac97_read +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xbb092a3d snd_ac97_write +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xc7f12f9f snd_ac97_update +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xca8746cb snd_ac97_write_cache +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xdf335ee4 snd_ac97_tune_hardware +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xe0a5c28d snd_ac97_suspend +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xe78031a0 snd_ac97_get_short_name +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x36d80be7 snd_emu10k1_synth_copy_from_user +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x3757c5fd snd_emu10k1_synth_alloc +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x4921492e snd_emu10k1_synth_free +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x7078a816 snd_emu10k1_ptr_write +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x7510c5aa snd_emu10k1_ptr_read +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x7bc212d2 snd_emu10k1_synth_bzero +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x9888139a snd_emu10k1_voice_free +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xa4ddd955 snd_emu10k1_memblk_map +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xe5089c95 snd_emu10k1_voice_alloc +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x2e5fc550 snd_ice1712_akm4xxx_free +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x8b01dd15 snd_ice1712_akm4xxx_build_controls +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x9b2a7973 snd_ice1712_akm4xxx_init +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x01d25c42 oxygen_read_ac97 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x0af697ee oxygen_write16_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x17224882 oxygen_write8_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x18012730 oxygen_write_i2c +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x2718e02a oxygen_write32_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x27cb218c oxygen_read8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x3d2ce0c4 oxygen_write_spi +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x3d8f644b oxygen_write32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x763d94bf oxygen_write16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x7c6b3621 oxygen_write_ac97 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x991cd0ad oxygen_pci_suspend +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xa49b8aec oxygen_read32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xabde90c5 oxygen_write8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xb936d39e oxygen_pci_probe +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xbd31e7c7 oxygen_write_ac97_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xc31b43ee oxygen_read16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xf12c708d oxygen_pci_remove +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xfae00a53 oxygen_pci_resume +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x0ced31d6 snd_trident_write_voice_regs +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x294843b3 snd_trident_stop_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x3583b7db snd_trident_alloc_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x3ece73b6 snd_trident_start_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0xfc12f22c snd_trident_free_voice +EXPORT_SYMBOL sound/sound_firmware 0x39e3dd23 mod_firmware_load +EXPORT_SYMBOL sound/soundcore 0x3938f613 register_sound_special_device +EXPORT_SYMBOL sound/soundcore 0x7afc9d8a unregister_sound_mixer +EXPORT_SYMBOL sound/soundcore 0x7b5cd1d0 register_sound_special +EXPORT_SYMBOL sound/soundcore 0x99c95fa5 unregister_sound_special +EXPORT_SYMBOL sound/soundcore 0xa95947c7 register_sound_mixer +EXPORT_SYMBOL sound/soundcore 0xc677eb49 register_sound_midi +EXPORT_SYMBOL sound/soundcore 0xcd083b10 unregister_sound_dsp +EXPORT_SYMBOL sound/soundcore 0xe0a9de2a sound_class +EXPORT_SYMBOL sound/soundcore 0xed861ae5 register_sound_dsp +EXPORT_SYMBOL sound/soundcore 0xfdab6de3 unregister_sound_midi +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x23684a6b snd_emux_lock_voice +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x51aea698 snd_emux_free +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x655cb202 snd_sf_linear_to_log +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xa1ec4bb0 snd_emux_unlock_voice +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xa1f20f8a snd_emux_terminate_all +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xd6a2fe7c snd_emux_register +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xdcc693c1 snd_emux_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0x20d65978 snd_util_memhdr_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x24886293 __snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0x569d614e snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x7a007343 snd_util_memhdr_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd197c5db __snd_util_memblk_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd34b56e4 __snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd8b55e81 snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0xf158252c snd_util_mem_avail +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x16756dc0 snd_usbmidi_input_start +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x37ff5894 snd_usb_create_midi_interface +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x63343b1d snd_usbmidi_input_stop +EXPORT_SYMBOL sound/usb/snd-usb-lib 0xd9d2bb03 snd_usbmidi_disconnect +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x53e9f657 dm_mem_cache_free +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x6f511415 dm_mem_cache_grow +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x89c6c8fe dm_mem_cache_client_destroy +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xcff2664e dm_mem_cache_shrink +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xe4172878 dm_mem_cache_alloc +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xf58b1b88 dm_mem_cache_client_create +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-message 0x920a7a41 dm_message_parse +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x0050f52c rh_get_region_key +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x0a3e284e rh_delay_by_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x275fdd04 rh_recovery_start +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x29e53a6b rh_dec +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x307f9cb7 rh_bio_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x3d1568a3 rh_delay +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x5c2a0632 rh_recovery_end +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x62842029 rh_flush +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x69f1df07 rh_init +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x83baca27 rh_state +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x87d45b9d rh_get_region_size +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xa923d788 rh_start_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xac274ed3 rh_stop_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xb513be98 rh_update_states +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xbb748327 rh_reg_set_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xbd3452f9 rh_sector_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4fdf256 rh_recovery_prepare +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4ff7745 rh_reg_get_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc57bafec rh_exit +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xce64fdd5 rh_inc_pending +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xe9f7f71a rh_region_to_sector +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xf3e0a2b0 rh_inc +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x29c887a9 set_tx_channels +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x7789312a cmdir_write +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0xf4c689aa cmdir_read +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x2f627e53 lirc_register_plugin +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x3af3b290 lirc_get_pdata +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0xe96379eb lirc_unregister_plugin +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0x5718c3b5 ov511_register_decomp_module +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0x7db9be3c ov511_deregister_decomp_module +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x01071e7e unregister_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x08ba5546 p80211netdev_hwremoved +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x2a4f3019 wlan_setup +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x65c7945e p80211netdev_rx +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x754cb318 p80211wext_event_associated +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x9a90a7a3 register_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xaa5a99b7 p80211_suspend +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb0af0799 wlan_wext_write +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb1ccd405 p80211_resume +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xcc211f66 p80211_allow_ioctls +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xd792c3ff p80211skb_rxmeta_attach +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xe42ae844 p80211skb_free +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xe94e5349 wlan_unsetup +EXPORT_SYMBOL vmlinux 0x00160db7 pid_task +EXPORT_SYMBOL vmlinux 0x004e4fed icmp_send +EXPORT_SYMBOL vmlinux 0x00801678 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x0080fcd6 tcf_hash_release +EXPORT_SYMBOL vmlinux 0x00928ae0 bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0x00983b3b lease_modify +EXPORT_SYMBOL vmlinux 0x009d258f _write_lock +EXPORT_SYMBOL vmlinux 0x00b6829d sync_inode +EXPORT_SYMBOL vmlinux 0x01000e51 schedule +EXPORT_SYMBOL vmlinux 0x010e220c dquot_commit_info +EXPORT_SYMBOL vmlinux 0x014e2714 blkdev_get +EXPORT_SYMBOL vmlinux 0x0164bf6a generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0x01836f06 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0x0186d073 percpu_counter_set +EXPORT_SYMBOL vmlinux 0x01902adf netpoll_trap +EXPORT_SYMBOL vmlinux 0x01a4aab6 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x01bbb111 blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0x01d19038 acpi_enable_subsystem +EXPORT_SYMBOL vmlinux 0x02124474 ip_send_check +EXPORT_SYMBOL vmlinux 0x02138f9d bioset_integrity_create +EXPORT_SYMBOL vmlinux 0x0237b57a arch_unregister_cpu +EXPORT_SYMBOL vmlinux 0x023e1f0e __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0x0256389f bit_waitqueue +EXPORT_SYMBOL vmlinux 0x02649054 security_sock_rcv_skb +EXPORT_SYMBOL vmlinux 0x02861259 unlock_page +EXPORT_SYMBOL vmlinux 0x029444f0 native_read_tsc +EXPORT_SYMBOL vmlinux 0x02a18c74 nf_conntrack_destroy +EXPORT_SYMBOL vmlinux 0x02aff2f4 acpi_install_gpe_handler +EXPORT_SYMBOL vmlinux 0x02b59c84 neigh_seq_next +EXPORT_SYMBOL vmlinux 0x02bf18fa sock_no_listen +EXPORT_SYMBOL vmlinux 0x02d81845 audit_log_task_context +EXPORT_SYMBOL vmlinux 0x02e84d1b per_cpu__cpu_sibling_map +EXPORT_SYMBOL vmlinux 0x030c7514 input_get_keycode +EXPORT_SYMBOL vmlinux 0x03265651 dma_async_memcpy_pg_to_pg +EXPORT_SYMBOL vmlinux 0x0334da4e scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x0377231e __mpage_writepage +EXPORT_SYMBOL vmlinux 0x037a0cba kfree +EXPORT_SYMBOL vmlinux 0x039989e6 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0x03a99c3b rb_prev +EXPORT_SYMBOL vmlinux 0x03c06156 bitmap_fold +EXPORT_SYMBOL vmlinux 0x0422fe4a inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x0426914f simple_rmdir +EXPORT_SYMBOL vmlinux 0x042e3eed vfs_mkdir +EXPORT_SYMBOL vmlinux 0x044fbf49 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x0480612b tcp_sync_mss +EXPORT_SYMBOL vmlinux 0x0487f831 fb_find_best_display +EXPORT_SYMBOL vmlinux 0x049b4c0a tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0x04d8c750 release_perfctr_nmi +EXPORT_SYMBOL vmlinux 0x05747129 agp_free_page_array +EXPORT_SYMBOL vmlinux 0x058c75d9 acpi_get_pci_id +EXPORT_SYMBOL vmlinux 0x05adcbc2 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0x05cb8481 skb_pull +EXPORT_SYMBOL vmlinux 0x05eaa0d4 __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x05ebc344 pci_set_dma_mask +EXPORT_SYMBOL vmlinux 0x05faca83 bio_put +EXPORT_SYMBOL vmlinux 0x060378a0 open_by_devnum +EXPORT_SYMBOL vmlinux 0x061651be strcat +EXPORT_SYMBOL vmlinux 0x06339d04 mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x063b4a6a __inc_zone_page_state +EXPORT_SYMBOL vmlinux 0x067d8d35 security_release_secctx +EXPORT_SYMBOL vmlinux 0x06a485f2 __krealloc +EXPORT_SYMBOL vmlinux 0x06ba49ea blk_requeue_request +EXPORT_SYMBOL vmlinux 0x06d728b1 tcp_parse_md5sig_option +EXPORT_SYMBOL vmlinux 0x06e99340 ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0x06fadcba migrate_page +EXPORT_SYMBOL vmlinux 0x06fe2d74 sock_get_timestamp +EXPORT_SYMBOL vmlinux 0x06fe3b14 default_grn +EXPORT_SYMBOL vmlinux 0x070d6317 ps2_handle_response +EXPORT_SYMBOL vmlinux 0x0727c4f3 iowrite8 +EXPORT_SYMBOL vmlinux 0x07382a1b blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0x073dfa12 generate_resume_trace +EXPORT_SYMBOL vmlinux 0x075468bf vc_resize +EXPORT_SYMBOL vmlinux 0x0768dea5 nonseekable_open +EXPORT_SYMBOL vmlinux 0x0784ef79 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0x078ee80c idr_for_each +EXPORT_SYMBOL vmlinux 0x07923d1c kill_anon_super +EXPORT_SYMBOL vmlinux 0x0799aca4 local_bh_enable +EXPORT_SYMBOL vmlinux 0x079cd7f1 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x07a890c8 fb_alloc_cmap +EXPORT_SYMBOL vmlinux 0x07cc4a5d printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x082c3213 pci_root_buses +EXPORT_SYMBOL vmlinux 0x082f4056 nobh_write_begin +EXPORT_SYMBOL vmlinux 0x08a57919 init_file +EXPORT_SYMBOL vmlinux 0x08ad30e1 dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x08b3fab5 input_unregister_handle +EXPORT_SYMBOL vmlinux 0x08ffa95a locks_init_lock +EXPORT_SYMBOL vmlinux 0x0925f9eb d_prune_aliases +EXPORT_SYMBOL vmlinux 0x0933aae1 efi_enabled +EXPORT_SYMBOL vmlinux 0x0948cde9 num_physpages +EXPORT_SYMBOL vmlinux 0x09554a68 dma_set_mask +EXPORT_SYMBOL vmlinux 0x09775cdc kref_get +EXPORT_SYMBOL vmlinux 0x098431ba acpi_get_current_resources +EXPORT_SYMBOL vmlinux 0x098b71c6 fb_dealloc_cmap +EXPORT_SYMBOL vmlinux 0x0994c7c6 xfrm_state_add +EXPORT_SYMBOL vmlinux 0x09ad3994 create_empty_buffers +EXPORT_SYMBOL vmlinux 0x09c55cec schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x09cc758d keyring_search +EXPORT_SYMBOL vmlinux 0x09d29dff key_link +EXPORT_SYMBOL vmlinux 0x09d44df9 in_lock_functions +EXPORT_SYMBOL vmlinux 0x0a0377c8 bdi_register +EXPORT_SYMBOL vmlinux 0x0a2487e0 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x0a3cee20 netif_device_attach +EXPORT_SYMBOL vmlinux 0x0a6a8551 dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x0ab8ae31 __scm_send +EXPORT_SYMBOL vmlinux 0x0abc4abc dget_locked +EXPORT_SYMBOL vmlinux 0x0acb1a3c __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x0aed429b get_fs_type +EXPORT_SYMBOL vmlinux 0x0b14e5e1 sget +EXPORT_SYMBOL vmlinux 0x0b15192a seq_printf +EXPORT_SYMBOL vmlinux 0x0b1529b2 netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0x0b1beb31 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x0b240dcf elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0x0b52756f tty_unregister_driver +EXPORT_SYMBOL vmlinux 0x0b597f09 input_free_device +EXPORT_SYMBOL vmlinux 0x0b742fd7 simple_strtol +EXPORT_SYMBOL vmlinux 0x0b9206d0 bio_integrity_clone +EXPORT_SYMBOL vmlinux 0x0b9ccddf kill_pid +EXPORT_SYMBOL vmlinux 0x0ba1135a llc_mac_hdr_init +EXPORT_SYMBOL vmlinux 0x0bb4b0d6 dev_remove_pack +EXPORT_SYMBOL vmlinux 0x0bc87dda sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0x0be254a2 fsync_bdev +EXPORT_SYMBOL vmlinux 0x0beed7a6 unmap_mapping_range +EXPORT_SYMBOL vmlinux 0x0bf0751c nobh_truncate_page +EXPORT_SYMBOL vmlinux 0x0c00905e tcp_sendpage +EXPORT_SYMBOL vmlinux 0x0c5c69e3 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x0c5ef91b per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x0c6e297d nla_put +EXPORT_SYMBOL vmlinux 0x0c87c756 bio_split_pool +EXPORT_SYMBOL vmlinux 0x0cce1058 d_alloc_anon +EXPORT_SYMBOL vmlinux 0x0d076569 misc_deregister +EXPORT_SYMBOL vmlinux 0x0d26a76d _write_lock_irq +EXPORT_SYMBOL vmlinux 0x0d299512 acpi_bus_generate_proc_event +EXPORT_SYMBOL vmlinux 0x0d336c4c mpage_writepages +EXPORT_SYMBOL vmlinux 0x0d391c1b arp_create +EXPORT_SYMBOL vmlinux 0x0d3dda14 acpi_get_type +EXPORT_SYMBOL vmlinux 0x0d43e72f tcf_em_tree_destroy +EXPORT_SYMBOL vmlinux 0x0d542439 __ipv6_addr_type +EXPORT_SYMBOL vmlinux 0x0d8ab500 param_set_copystring +EXPORT_SYMBOL vmlinux 0x0da10ec3 security_sock_graft +EXPORT_SYMBOL vmlinux 0x0db3ca1d agp_create_memory +EXPORT_SYMBOL vmlinux 0x0ddab262 agp_generic_remove_memory +EXPORT_SYMBOL vmlinux 0x0e0252ec downgrade_write +EXPORT_SYMBOL vmlinux 0x0e175a77 block_write_full_page +EXPORT_SYMBOL vmlinux 0x0e52592a panic +EXPORT_SYMBOL vmlinux 0x0e580b38 tty_name +EXPORT_SYMBOL vmlinux 0x0e762d6e request_module +EXPORT_SYMBOL vmlinux 0x0e8094a2 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x0ea3a10a ip_setsockopt +EXPORT_SYMBOL vmlinux 0x0eb17dc8 new_inode +EXPORT_SYMBOL vmlinux 0x0f55cadd agp_generic_enable +EXPORT_SYMBOL vmlinux 0x0f7e8965 nf_unregister_hook +EXPORT_SYMBOL vmlinux 0x0f908a1f simple_lookup +EXPORT_SYMBOL vmlinux 0x0fae4315 kmem_cache_name +EXPORT_SYMBOL vmlinux 0x0faef0ed __tasklet_schedule +EXPORT_SYMBOL vmlinux 0x0fc5e8eb radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0x0fcf77c3 aio_put_req +EXPORT_SYMBOL vmlinux 0x0fd00a68 acpi_clear_event +EXPORT_SYMBOL vmlinux 0x0fe6b264 sock_release +EXPORT_SYMBOL vmlinux 0x10217991 rtnl_unicast +EXPORT_SYMBOL vmlinux 0x1027a012 inet_bind +EXPORT_SYMBOL vmlinux 0x103ede79 touch_atime +EXPORT_SYMBOL vmlinux 0x1055db10 pci_back_from_sleep +EXPORT_SYMBOL vmlinux 0x1072a394 csum_partial_copy_from_user +EXPORT_SYMBOL vmlinux 0x109f5dce inet_frag_find +EXPORT_SYMBOL vmlinux 0x10a96082 sock_register +EXPORT_SYMBOL vmlinux 0x10abb1c0 d_move +EXPORT_SYMBOL vmlinux 0x10ee20bb default_blu +EXPORT_SYMBOL vmlinux 0x10eece91 neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x111e09e4 input_set_keycode +EXPORT_SYMBOL vmlinux 0x114f7de3 dev_queue_xmit +EXPORT_SYMBOL vmlinux 0x11554b5e pci_scan_slot +EXPORT_SYMBOL vmlinux 0x116240db key_instantiate_and_link +EXPORT_SYMBOL vmlinux 0x1163f0a7 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x117093be qdisc_class_hash_init +EXPORT_SYMBOL vmlinux 0x117b13da skb_kill_datagram +EXPORT_SYMBOL vmlinux 0x11895b48 llc_sap_find +EXPORT_SYMBOL vmlinux 0x118f01ea putname +EXPORT_SYMBOL vmlinux 0x11a18b14 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x11b1fada sk_filter +EXPORT_SYMBOL vmlinux 0x11bc94cc sock_recvmsg +EXPORT_SYMBOL vmlinux 0x11dab346 __down_read +EXPORT_SYMBOL vmlinux 0x11f1d563 security_sb_clone_mnt_opts +EXPORT_SYMBOL vmlinux 0x1234bbb5 xfrm_register_km +EXPORT_SYMBOL vmlinux 0x125fbca7 cad_pid +EXPORT_SYMBOL vmlinux 0x1264546d nf_hook_slow +EXPORT_SYMBOL vmlinux 0x126970ed param_set_uint +EXPORT_SYMBOL vmlinux 0x12a891ca tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x12f2e8a8 agp_bind_memory +EXPORT_SYMBOL vmlinux 0x12f99022 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x130c44a7 alloc_disk_node +EXPORT_SYMBOL vmlinux 0x130da0e0 kmem_cache_create +EXPORT_SYMBOL vmlinux 0x132f45f2 cookie_check_timestamp +EXPORT_SYMBOL vmlinux 0x132ff366 unlock_rename +EXPORT_SYMBOL vmlinux 0x134cc7c7 blk_get_request +EXPORT_SYMBOL vmlinux 0x135169e4 skb_gso_segment +EXPORT_SYMBOL vmlinux 0x138c9f8b write_one_page +EXPORT_SYMBOL vmlinux 0x139350c1 vfs_permission +EXPORT_SYMBOL vmlinux 0x13d2c499 neigh_create +EXPORT_SYMBOL vmlinux 0x13d42874 wireless_spy_update +EXPORT_SYMBOL vmlinux 0x13ddb0bd pci_bus_write_config_word +EXPORT_SYMBOL vmlinux 0x13f1e33b end_request +EXPORT_SYMBOL vmlinux 0x13f71731 tcf_hash_lookup +EXPORT_SYMBOL vmlinux 0x1402791a agp_alloc_bridge +EXPORT_SYMBOL vmlinux 0x141a8542 pcie_port_service_register +EXPORT_SYMBOL vmlinux 0x14276ed3 skb_queue_purge +EXPORT_SYMBOL vmlinux 0x1430e6e0 unregister_acpi_notifier +EXPORT_SYMBOL vmlinux 0x14524d84 tcp_v4_md5_do_add +EXPORT_SYMBOL vmlinux 0x149acfdb blk_integrity_unregister +EXPORT_SYMBOL vmlinux 0x14abcddc vfs_link +EXPORT_SYMBOL vmlinux 0x14ad564d deactivate_super +EXPORT_SYMBOL vmlinux 0x14aee23d __xfrm_lookup +EXPORT_SYMBOL vmlinux 0x14af0cf7 gen_pool_destroy +EXPORT_SYMBOL vmlinux 0x14c326a5 bio_integrity_trim +EXPORT_SYMBOL vmlinux 0x14c87fe5 __tcp_get_md5sig_pool +EXPORT_SYMBOL vmlinux 0x14d375d2 eth_type_trans +EXPORT_SYMBOL vmlinux 0x1544aad4 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x1551dc51 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x1553522b compat_mc_getsockopt +EXPORT_SYMBOL vmlinux 0x15598dbc pagecache_write_end +EXPORT_SYMBOL vmlinux 0x15a3f0cf input_register_device +EXPORT_SYMBOL vmlinux 0x15a5bc68 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x15ecf610 _cpu_pda +EXPORT_SYMBOL vmlinux 0x15ef2dd9 kfifo_free +EXPORT_SYMBOL vmlinux 0x1611517c blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0x16175304 udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0x16381a1d bio_integrity_advance +EXPORT_SYMBOL vmlinux 0x16517eb7 pci_iounmap +EXPORT_SYMBOL vmlinux 0x1675606f bad_dma_address +EXPORT_SYMBOL vmlinux 0x167e7f9d __get_user_1 +EXPORT_SYMBOL vmlinux 0x169aef06 xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0x16a35878 _read_unlock +EXPORT_SYMBOL vmlinux 0x16ab954c ether_setup +EXPORT_SYMBOL vmlinux 0x16fd31ca stop_tty +EXPORT_SYMBOL vmlinux 0x1700fb1d tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0x170563e5 compat_nf_setsockopt +EXPORT_SYMBOL vmlinux 0x170a2bc3 pnp_unregister_card_driver +EXPORT_SYMBOL vmlinux 0x170c25ee acpi_get_next_object +EXPORT_SYMBOL vmlinux 0x1716e149 __getblk +EXPORT_SYMBOL vmlinux 0x1728580b bio_uncopy_user +EXPORT_SYMBOL vmlinux 0x172ed4d7 __vmalloc +EXPORT_SYMBOL vmlinux 0x173c990e iw_handler_set_thrspy +EXPORT_SYMBOL vmlinux 0x17737e63 proc_net_netfilter +EXPORT_SYMBOL vmlinux 0x17970e49 neigh_table_init +EXPORT_SYMBOL vmlinux 0x17a76e71 rb_first +EXPORT_SYMBOL vmlinux 0x17c85a66 radix_tree_tagged +EXPORT_SYMBOL vmlinux 0x17df17bc sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x17edced3 task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x17fd15cd call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0x181ae030 agp_flush_chipset +EXPORT_SYMBOL vmlinux 0x181b6ff2 mempool_resize +EXPORT_SYMBOL vmlinux 0x183fa88b mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x185219bf swiotlb_free_coherent +EXPORT_SYMBOL vmlinux 0x18857637 dentry_open +EXPORT_SYMBOL vmlinux 0x189b6bac memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x189eeb75 generic_getxattr +EXPORT_SYMBOL vmlinux 0x18ad0b56 tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0x18f47107 d_path +EXPORT_SYMBOL vmlinux 0x18f5188a key_put +EXPORT_SYMBOL vmlinux 0x1920b112 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x192576c1 tcf_destroy_chain +EXPORT_SYMBOL vmlinux 0x1930ddff inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0x1938fbf8 generic_file_open +EXPORT_SYMBOL vmlinux 0x19391763 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x19414812 skb_copy_bits +EXPORT_SYMBOL vmlinux 0x1985ed3c prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0x199e695b tc_classify +EXPORT_SYMBOL vmlinux 0x199ed0cd net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x19b3b457 generic_fillattr +EXPORT_SYMBOL vmlinux 0x19cdb332 __locks_copy_lock +EXPORT_SYMBOL vmlinux 0x19d5d20a acpi_walk_namespace +EXPORT_SYMBOL vmlinux 0x19e9a0bd tcf_exts_dump +EXPORT_SYMBOL vmlinux 0x19f6a3a5 blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0x19fc92bc netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0x1a1ab15d tty_mutex +EXPORT_SYMBOL vmlinux 0x1a3c1fdc neigh_lookup +EXPORT_SYMBOL vmlinux 0x1a45cb6c acpi_disabled +EXPORT_SYMBOL vmlinux 0x1a75caa3 _read_lock +EXPORT_SYMBOL vmlinux 0x1a760325 ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x1a8a845e idle_nomwait +EXPORT_SYMBOL vmlinux 0x1a9802d2 dquot_release +EXPORT_SYMBOL vmlinux 0x1ace138d bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x1ad156a8 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0x1adc4b23 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0x1ae8d7dc param_set_invbool +EXPORT_SYMBOL vmlinux 0x1b015d25 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x1b02f1bc pci_bus_alloc_resource +EXPORT_SYMBOL vmlinux 0x1b1384f6 kobject_add +EXPORT_SYMBOL vmlinux 0x1b198a2c uart_suspend_port +EXPORT_SYMBOL vmlinux 0x1b19a0ea pci_scan_bridge +EXPORT_SYMBOL vmlinux 0x1b3b863c pci_set_consistent_dma_mask +EXPORT_SYMBOL vmlinux 0x1b3c678a gen_new_estimator +EXPORT_SYMBOL vmlinux 0x1b6314fd in_aton +EXPORT_SYMBOL vmlinux 0x1b818707 dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x1b89419f add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x1b9981cc set_irq_wake +EXPORT_SYMBOL vmlinux 0x1b9b7d8c kernel_getsockopt +EXPORT_SYMBOL vmlinux 0x1baa9c86 node_to_cpumask_map +EXPORT_SYMBOL vmlinux 0x1baf49ef call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0x1bb84d7a vfs_rename +EXPORT_SYMBOL vmlinux 0x1bbac7cf dquot_acquire +EXPORT_SYMBOL vmlinux 0x1bc21a27 agp_generic_type_to_mask_type +EXPORT_SYMBOL vmlinux 0x1c054b1f sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x1c19fec9 register_con_driver +EXPORT_SYMBOL vmlinux 0x1c4a113f seq_putc +EXPORT_SYMBOL vmlinux 0x1c5f1b98 pci_find_capability +EXPORT_SYMBOL vmlinux 0x1c85a77a pcie_set_readrq +EXPORT_SYMBOL vmlinux 0x1c9b7c3b rtnl_create_link +EXPORT_SYMBOL vmlinux 0x1cb38de6 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0x1cc6719a register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x1cefe352 wait_for_completion +EXPORT_SYMBOL vmlinux 0x1cf3709f acpi_evaluate_integer +EXPORT_SYMBOL vmlinux 0x1d121e14 qdisc_destroy +EXPORT_SYMBOL vmlinux 0x1d264e30 swiotlb_dma_mapping_error +EXPORT_SYMBOL vmlinux 0x1d568e72 skb_put +EXPORT_SYMBOL vmlinux 0x1d830520 cpu_possible_map +EXPORT_SYMBOL vmlinux 0x1d842074 proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x1d866576 invalidate_partition +EXPORT_SYMBOL vmlinux 0x1db7706b __copy_user_nocache +EXPORT_SYMBOL vmlinux 0x1dc36131 fb_destroy_modedb +EXPORT_SYMBOL vmlinux 0x1dd571e6 fb_copy_cmap +EXPORT_SYMBOL vmlinux 0x1de03d0f blk_queue_ordered +EXPORT_SYMBOL vmlinux 0x1e02b03d generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x1e142e48 arch_acpi_processor_init_pdc +EXPORT_SYMBOL vmlinux 0x1e1fc55f pci_map_rom +EXPORT_SYMBOL vmlinux 0x1e2f5175 agp_generic_destroy_page +EXPORT_SYMBOL vmlinux 0x1e5b562e pci_bus_write_config_dword +EXPORT_SYMBOL vmlinux 0x1e5e5ec0 ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x1e6d26a8 strstr +EXPORT_SYMBOL vmlinux 0x1e7d41ce atm_dev_deregister +EXPORT_SYMBOL vmlinux 0x1e937dfd sock_wmalloc +EXPORT_SYMBOL vmlinux 0x1e963075 filp_open +EXPORT_SYMBOL vmlinux 0x1e9deb0d udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0x1edc77f8 kobject_set_name +EXPORT_SYMBOL vmlinux 0x1efe283f __cap_full_set +EXPORT_SYMBOL vmlinux 0x1f04966f complete_request_key +EXPORT_SYMBOL vmlinux 0x1f27d6d7 _write_unlock +EXPORT_SYMBOL vmlinux 0x1f3eacb7 xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0x1f7d9f83 get_sb_nodev +EXPORT_SYMBOL vmlinux 0x1f8249da generic_file_llseek +EXPORT_SYMBOL vmlinux 0x1f8b36d2 dma_pool_create +EXPORT_SYMBOL vmlinux 0x1f94f8a0 pci_enable_msi +EXPORT_SYMBOL vmlinux 0x1fa341be redraw_screen +EXPORT_SYMBOL vmlinux 0x1fceecfc iput +EXPORT_SYMBOL vmlinux 0x1fd59104 proc_dostring +EXPORT_SYMBOL vmlinux 0x20000329 simple_strtoul +EXPORT_SYMBOL vmlinux 0x2005e68a acpi_remove_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x20092385 acpi_enter_sleep_state_s4bios +EXPORT_SYMBOL vmlinux 0x2010469a dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0x20183f50 serio_unregister_port +EXPORT_SYMBOL vmlinux 0x203e7022 pci_request_selected_regions +EXPORT_SYMBOL vmlinux 0x2056f318 ida_get_new +EXPORT_SYMBOL vmlinux 0x205ed65d bdevname +EXPORT_SYMBOL vmlinux 0x208739f6 acpi_load_table +EXPORT_SYMBOL vmlinux 0x20a099e9 thermal_zone_bind_cooling_device +EXPORT_SYMBOL vmlinux 0x20c74d9f kobject_put +EXPORT_SYMBOL vmlinux 0x20c8fc33 pci_osc_control_set +EXPORT_SYMBOL vmlinux 0x20eadeb6 ip_compute_csum +EXPORT_SYMBOL vmlinux 0x21033e88 pnp_disable_dev +EXPORT_SYMBOL vmlinux 0x214701b5 agp3_generic_tlbflush +EXPORT_SYMBOL vmlinux 0x215ebd78 bitrev16 +EXPORT_SYMBOL vmlinux 0x21731ef2 security_task_getsecid +EXPORT_SYMBOL vmlinux 0x21a52974 iget_locked +EXPORT_SYMBOL vmlinux 0x21e0ea22 acpi_get_id +EXPORT_SYMBOL vmlinux 0x21e5679c copy_user_generic +EXPORT_SYMBOL vmlinux 0x222e7ce2 sysfs_streq +EXPORT_SYMBOL vmlinux 0x2253c959 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0x22599c74 vfs_rmdir +EXPORT_SYMBOL vmlinux 0x226e86a9 audit_log +EXPORT_SYMBOL vmlinux 0x2288378f system_state +EXPORT_SYMBOL vmlinux 0x228ae3b6 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0x228c214f serio_unregister_child_port +EXPORT_SYMBOL vmlinux 0x22a73912 __tcp_put_md5sig_pool +EXPORT_SYMBOL vmlinux 0x22b325d5 kd_mksound +EXPORT_SYMBOL vmlinux 0x22b33054 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x22b6533b xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x22cede8e brioctl_set +EXPORT_SYMBOL vmlinux 0x22e9512e swiotlb_sync_sg_for_device +EXPORT_SYMBOL vmlinux 0x22f429fa atm_proc_root +EXPORT_SYMBOL vmlinux 0x23191475 dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x231f3a66 __kfifo_put +EXPORT_SYMBOL vmlinux 0x23269a13 strict_strtoul +EXPORT_SYMBOL vmlinux 0x23388d20 generic_ro_fops +EXPORT_SYMBOL vmlinux 0x234509f3 strncat +EXPORT_SYMBOL vmlinux 0x236c8c64 memcpy +EXPORT_SYMBOL vmlinux 0x2395d028 get_unmapped_area +EXPORT_SYMBOL vmlinux 0x2398f7d0 pci_find_slot +EXPORT_SYMBOL vmlinux 0x23a794dc in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x23a7a3bd maps_protect +EXPORT_SYMBOL vmlinux 0x23b6a266 dev_change_flags +EXPORT_SYMBOL vmlinux 0x23b99e92 node_states +EXPORT_SYMBOL vmlinux 0x23f282dc netif_receive_skb +EXPORT_SYMBOL vmlinux 0x23f2d36f memparse +EXPORT_SYMBOL vmlinux 0x23fd3028 vmalloc_node +EXPORT_SYMBOL vmlinux 0x2424fa4e udp_disconnect +EXPORT_SYMBOL vmlinux 0x24428be5 strncpy_from_user +EXPORT_SYMBOL vmlinux 0x2459bbcc console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x2464c1f8 dev_unicast_add +EXPORT_SYMBOL vmlinux 0x247bfc2d km_policy_notify +EXPORT_SYMBOL vmlinux 0x24a1ce10 xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0x24fdac79 wake_bit_function +EXPORT_SYMBOL vmlinux 0x2508da33 register_netdev +EXPORT_SYMBOL vmlinux 0x2517a3aa dma_async_client_register +EXPORT_SYMBOL vmlinux 0x253114ac set_bdi_congested +EXPORT_SYMBOL vmlinux 0x255e4499 netif_carrier_off +EXPORT_SYMBOL vmlinux 0x25612803 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0x256887e1 warn_slowpath +EXPORT_SYMBOL vmlinux 0x256d641a netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x25820c64 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x258355b4 fb_find_best_mode +EXPORT_SYMBOL vmlinux 0x25911183 netlink_dump_start +EXPORT_SYMBOL vmlinux 0x259c6c01 dma_pool_destroy +EXPORT_SYMBOL vmlinux 0x25bd4aae skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x25d8ae18 skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0x25ec1b28 strlen +EXPORT_SYMBOL vmlinux 0x26112ede mpage_bio_submit +EXPORT_SYMBOL vmlinux 0x263782b5 cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0x266689e2 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x2685c3d7 __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x268a9d70 neigh_parms_release +EXPORT_SYMBOL vmlinux 0x268d0793 put_filp +EXPORT_SYMBOL vmlinux 0x26c0315c grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0x26c16dc1 tcp_tso_segment +EXPORT_SYMBOL vmlinux 0x26cac698 dquot_mark_dquot_dirty +EXPORT_SYMBOL vmlinux 0x26e76fb8 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x26ef08d4 pci_find_next_bus +EXPORT_SYMBOL vmlinux 0x272d394e mtrr_del +EXPORT_SYMBOL vmlinux 0x272e7488 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x273f066e _write_unlock_irq +EXPORT_SYMBOL vmlinux 0x27513339 km_query +EXPORT_SYMBOL vmlinux 0x277d99db __next_cpu +EXPORT_SYMBOL vmlinux 0x27802a95 acpi_bus_get_status +EXPORT_SYMBOL vmlinux 0x279c8bf9 kthread_create +EXPORT_SYMBOL vmlinux 0x27a9a7eb ns_to_timespec +EXPORT_SYMBOL vmlinux 0x27ba7feb arp_send +EXPORT_SYMBOL vmlinux 0x27bbf221 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x27c33efe csum_ipv6_magic +EXPORT_SYMBOL vmlinux 0x27c61ece qdisc_put_stab +EXPORT_SYMBOL vmlinux 0x281b8c5c nf_ct_attach +EXPORT_SYMBOL vmlinux 0x285ac517 strict_strtoll +EXPORT_SYMBOL vmlinux 0x2876a6d3 memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x288ab8fd blk_queue_bounce +EXPORT_SYMBOL vmlinux 0x2896f1d5 inet_put_port +EXPORT_SYMBOL vmlinux 0x28dcf25c udplite_hash +EXPORT_SYMBOL vmlinux 0x2906d2ea follow_up +EXPORT_SYMBOL vmlinux 0x290e52c6 tcp_alloc_md5sig_pool +EXPORT_SYMBOL vmlinux 0x29161825 blk_register_region +EXPORT_SYMBOL vmlinux 0x292931d8 write_cache_pages +EXPORT_SYMBOL vmlinux 0x29384519 seq_release +EXPORT_SYMBOL vmlinux 0x2949b436 ip_fragment +EXPORT_SYMBOL vmlinux 0x29537c9e alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x29688a32 kernel_listen +EXPORT_SYMBOL vmlinux 0x296f3ccc idr_remove_all +EXPORT_SYMBOL vmlinux 0x299066aa pci_get_slot +EXPORT_SYMBOL vmlinux 0x29a138a7 do_SAK +EXPORT_SYMBOL vmlinux 0x29bd4c46 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x29e7efdf bdev_read_only +EXPORT_SYMBOL vmlinux 0x2a303d4d check_signature +EXPORT_SYMBOL vmlinux 0x2a4832c4 sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x2a8986ba thermal_cooling_device_unregister +EXPORT_SYMBOL vmlinux 0x2a8b5483 pci_do_scan_bus +EXPORT_SYMBOL vmlinux 0x2a94d9f0 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0x2aae0e76 pci_dev_put +EXPORT_SYMBOL vmlinux 0x2ad296d3 sock_no_connect +EXPORT_SYMBOL vmlinux 0x2ae23eb9 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0x2aeb2800 mempool_create_node +EXPORT_SYMBOL vmlinux 0x2b0b412a pcibios_align_resource +EXPORT_SYMBOL vmlinux 0x2b12cb05 security_sk_classify_flow +EXPORT_SYMBOL vmlinux 0x2b39eb1e fb_show_logo +EXPORT_SYMBOL vmlinux 0x2b3e8182 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0x2b6aac8c tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x2ba476ec security_inode_init_security +EXPORT_SYMBOL vmlinux 0x2ba707a8 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x2bb0ad10 agp_unbind_memory +EXPORT_SYMBOL vmlinux 0x2bb55d6e acpi_remove_notify_handler +EXPORT_SYMBOL vmlinux 0x2bd3f983 boot_cpu_data +EXPORT_SYMBOL vmlinux 0x2be09893 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x2bf710b5 set_blocksize +EXPORT_SYMBOL vmlinux 0x2bfeb410 acpi_get_handle +EXPORT_SYMBOL vmlinux 0x2c53fea2 init_buffer +EXPORT_SYMBOL vmlinux 0x2c5749e6 acpi_clear_gpe +EXPORT_SYMBOL vmlinux 0x2c861f98 misc_register +EXPORT_SYMBOL vmlinux 0x2cb426c5 netpoll_cleanup +EXPORT_SYMBOL vmlinux 0x2cc2d52d vcc_hash +EXPORT_SYMBOL vmlinux 0x2cd9e459 param_set_short +EXPORT_SYMBOL vmlinux 0x2cf190e3 request_irq +EXPORT_SYMBOL vmlinux 0x2d18799d blk_free_tags +EXPORT_SYMBOL vmlinux 0x2d4613ec register_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0x2d5528c9 sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0x2d8320d1 register_framebuffer +EXPORT_SYMBOL vmlinux 0x2d933cf6 netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0x2d9fce67 skb_over_panic +EXPORT_SYMBOL vmlinux 0x2dc1cc4a fd_install +EXPORT_SYMBOL vmlinux 0x2dc7a5fb ip_route_me_harder +EXPORT_SYMBOL vmlinux 0x2dd16564 arch_register_cpu +EXPORT_SYMBOL vmlinux 0x2ddbfdc2 tcp_poll +EXPORT_SYMBOL vmlinux 0x2de9f66f param_get_long +EXPORT_SYMBOL vmlinux 0x2dedc4c2 acpi_format_exception +EXPORT_SYMBOL vmlinux 0x2def7f76 rtc_cmos_write +EXPORT_SYMBOL vmlinux 0x2df5173d skb_copy_expand +EXPORT_SYMBOL vmlinux 0x2e10c1b1 tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0x2e21643d compat_mc_setsockopt +EXPORT_SYMBOL vmlinux 0x2e2ce9e0 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x2e36655e swiotlb_map_single_attrs +EXPORT_SYMBOL vmlinux 0x2e41952c bio_clone +EXPORT_SYMBOL vmlinux 0x2e4a39f8 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x2e972b59 flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0x2ea86135 generic_read_dir +EXPORT_SYMBOL vmlinux 0x2eb16618 neigh_event_ns +EXPORT_SYMBOL vmlinux 0x2eb9a0e8 _read_lock_irq +EXPORT_SYMBOL vmlinux 0x2ebed99b skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0x2edd8d00 pci_bus_assign_resources +EXPORT_SYMBOL vmlinux 0x2f227565 tcp_v4_md5_do_del +EXPORT_SYMBOL vmlinux 0x2f2f0209 get_sb_bdev +EXPORT_SYMBOL vmlinux 0x2f35f31b block_prepare_write +EXPORT_SYMBOL vmlinux 0x2f547582 dev_getbyhwaddr +EXPORT_SYMBOL vmlinux 0x2f580481 input_register_handler +EXPORT_SYMBOL vmlinux 0x2f607d84 acpi_bus_start +EXPORT_SYMBOL vmlinux 0x2f70ba03 vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x2f80be75 check_disk_change +EXPORT_SYMBOL vmlinux 0x2f853cb5 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x2fa5a500 memcmp +EXPORT_SYMBOL vmlinux 0x2fb30cbd simple_write_begin +EXPORT_SYMBOL vmlinux 0x2fd24c19 bio_integrity_alloc_bioset +EXPORT_SYMBOL vmlinux 0x2fd4f7c3 blk_rq_map_user +EXPORT_SYMBOL vmlinux 0x2fdd6221 sysctl_jiffies +EXPORT_SYMBOL vmlinux 0x2ff063b5 acpi_get_name +EXPORT_SYMBOL vmlinux 0x2ff24d79 dquot_alloc_inode +EXPORT_SYMBOL vmlinux 0x2ff7efaa tcf_hash_new_index +EXPORT_SYMBOL vmlinux 0x300db8e0 thermal_zone_device_register +EXPORT_SYMBOL vmlinux 0x301cdbff user_revoke +EXPORT_SYMBOL vmlinux 0x30226ddf agp_device_command +EXPORT_SYMBOL vmlinux 0x302466e2 neigh_seq_start +EXPORT_SYMBOL vmlinux 0x306bd3c3 vfs_fstat +EXPORT_SYMBOL vmlinux 0x30896043 __any_online_cpu +EXPORT_SYMBOL vmlinux 0x30a94c37 pci_reenable_device +EXPORT_SYMBOL vmlinux 0x30c2b783 vfs_readv +EXPORT_SYMBOL vmlinux 0x30c5ac52 pnp_unregister_driver +EXPORT_SYMBOL vmlinux 0x30de8b2e copy_io_context +EXPORT_SYMBOL vmlinux 0x30e74134 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x30f3a5ef make_EII_client +EXPORT_SYMBOL vmlinux 0x30fe83a7 pci_remove_bus +EXPORT_SYMBOL vmlinux 0x312a789d vfs_symlink +EXPORT_SYMBOL vmlinux 0x3132f872 load_nls +EXPORT_SYMBOL vmlinux 0x3140217b blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0x3145216f pci_dev_present +EXPORT_SYMBOL vmlinux 0x3147857d default_red +EXPORT_SYMBOL vmlinux 0x3147c6ef dev_set_mtu +EXPORT_SYMBOL vmlinux 0x31616d67 textsearch_find_continuous +EXPORT_SYMBOL vmlinux 0x31b31f5c csum_partial_copy_nocheck +EXPORT_SYMBOL vmlinux 0x31c5a4c0 dcache_readdir +EXPORT_SYMBOL vmlinux 0x31d53936 bdi_destroy +EXPORT_SYMBOL vmlinux 0x31ebadcd in_group_p +EXPORT_SYMBOL vmlinux 0x322fe5bb pci_release_region +EXPORT_SYMBOL vmlinux 0x323d3887 tcp_v4_connect +EXPORT_SYMBOL vmlinux 0x326ba0c4 km_report +EXPORT_SYMBOL vmlinux 0x32a2988b filemap_flush +EXPORT_SYMBOL vmlinux 0x32b00695 sock_i_uid +EXPORT_SYMBOL vmlinux 0x32b0ac0b dquot_alloc_space +EXPORT_SYMBOL vmlinux 0x32b5e86d bio_init +EXPORT_SYMBOL vmlinux 0x32d01fec acpi_attach_data +EXPORT_SYMBOL vmlinux 0x32ee1827 pci_add_new_bus +EXPORT_SYMBOL vmlinux 0x32f87920 inet_frag_kill +EXPORT_SYMBOL vmlinux 0x32ff5757 agp_put_bridge +EXPORT_SYMBOL vmlinux 0x330d1c6a simple_getattr +EXPORT_SYMBOL vmlinux 0x330d556f gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0x3360a963 param_set_ulong +EXPORT_SYMBOL vmlinux 0x33619d38 ip_route_input +EXPORT_SYMBOL vmlinux 0x33a92a0d read_dev_sector +EXPORT_SYMBOL vmlinux 0x33af1a28 compat_sock_get_timestamp +EXPORT_SYMBOL vmlinux 0x33b70512 set_page_dirty +EXPORT_SYMBOL vmlinux 0x33b84f74 copy_page +EXPORT_SYMBOL vmlinux 0x33cda660 posix_acl_from_mode +EXPORT_SYMBOL vmlinux 0x33d92f9a prepare_to_wait +EXPORT_SYMBOL vmlinux 0x33dc1681 mark_info_dirty +EXPORT_SYMBOL vmlinux 0x33ef5176 arp_broken_ops +EXPORT_SYMBOL vmlinux 0x3421272c efi +EXPORT_SYMBOL vmlinux 0x3448a9e8 ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0x34722573 ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0x349cba85 strchr +EXPORT_SYMBOL vmlinux 0x34c1babf swiotlb_sync_sg_for_cpu +EXPORT_SYMBOL vmlinux 0x34c5b8c4 compat_sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x34c65500 llc_build_and_send_ui_pkt +EXPORT_SYMBOL vmlinux 0x34e42850 update_region +EXPORT_SYMBOL vmlinux 0x3509f037 pci_choose_state +EXPORT_SYMBOL vmlinux 0x35924bba atm_dev_register +EXPORT_SYMBOL vmlinux 0x35a07e32 vfs_stat +EXPORT_SYMBOL vmlinux 0x35a6dda2 register_8022_client +EXPORT_SYMBOL vmlinux 0x35b0650f vsnprintf +EXPORT_SYMBOL vmlinux 0x35c2ba9e refrigerator +EXPORT_SYMBOL vmlinux 0x35c51a8e blk_stop_queue +EXPORT_SYMBOL vmlinux 0x35e1a1ca pskb_expand_head +EXPORT_SYMBOL vmlinux 0x35f0e1d3 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0x360b1afe probe_irq_mask +EXPORT_SYMBOL vmlinux 0x3613049b ipv6_skip_exthdr +EXPORT_SYMBOL vmlinux 0x36139a51 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x361bab89 vfs_set_dqinfo +EXPORT_SYMBOL vmlinux 0x3624f4fa bio_unmap_user +EXPORT_SYMBOL vmlinux 0x363ad247 cap_set_effective +EXPORT_SYMBOL vmlinux 0x36556ac0 register_console +EXPORT_SYMBOL vmlinux 0x3656bf5a lock_kernel +EXPORT_SYMBOL vmlinux 0x366875b2 vfs_follow_link +EXPORT_SYMBOL vmlinux 0x366ba4ce register_filesystem +EXPORT_SYMBOL vmlinux 0x36a2cb07 thaw_bdev +EXPORT_SYMBOL vmlinux 0x3701a196 csum_partial_copy_to_user +EXPORT_SYMBOL vmlinux 0x3744cf36 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x374ed338 tty_write_room +EXPORT_SYMBOL vmlinux 0x37536590 bd_claim +EXPORT_SYMBOL vmlinux 0x375465a7 radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x3754efc4 acpi_bus_get_device +EXPORT_SYMBOL vmlinux 0x3773cb56 d_lookup +EXPORT_SYMBOL vmlinux 0x3777c625 __mod_zone_page_state +EXPORT_SYMBOL vmlinux 0x379d7e0e nf_register_hooks +EXPORT_SYMBOL vmlinux 0x37a8852f vfs_quota_sync +EXPORT_SYMBOL vmlinux 0x37b3ac06 posix_acl_permission +EXPORT_SYMBOL vmlinux 0x37befc70 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x37ee23ca datagram_poll +EXPORT_SYMBOL vmlinux 0x3850337f swiotlb_unmap_single +EXPORT_SYMBOL vmlinux 0x385bab81 blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x387b9f28 fb_pan_display +EXPORT_SYMBOL vmlinux 0x38987045 dput +EXPORT_SYMBOL vmlinux 0x38b92846 llc_remove_pack +EXPORT_SYMBOL vmlinux 0x38ea10b8 neigh_compat_output +EXPORT_SYMBOL vmlinux 0x38f33bed dump_fpu +EXPORT_SYMBOL vmlinux 0x38fc72ee compute_creds +EXPORT_SYMBOL vmlinux 0x39170a6c acpi_check_resource_conflict +EXPORT_SYMBOL vmlinux 0x396d2893 __page_symlink +EXPORT_SYMBOL vmlinux 0x3980aac1 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x39a5cad6 ida_destroy +EXPORT_SYMBOL vmlinux 0x39a6ea6f proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0x39c16f1e release_firmware +EXPORT_SYMBOL vmlinux 0x39c6d8fa mnt_unpin +EXPORT_SYMBOL vmlinux 0x39cd891a __down_write_trylock +EXPORT_SYMBOL vmlinux 0x3a114600 xfrm_register_type +EXPORT_SYMBOL vmlinux 0x3a1a367e d_alloc_root +EXPORT_SYMBOL vmlinux 0x3a2204c6 security_netlink_recv +EXPORT_SYMBOL vmlinux 0x3a2b2c17 dentry_unhash +EXPORT_SYMBOL vmlinux 0x3a63a8f8 dec_zone_page_state +EXPORT_SYMBOL vmlinux 0x3a72f51b request_firmware +EXPORT_SYMBOL vmlinux 0x3a7b7620 bdput +EXPORT_SYMBOL vmlinux 0x3a8ad091 generic_write_checks +EXPORT_SYMBOL vmlinux 0x3a9b6fb9 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x3a9bfe96 scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0x3aa1dbcf _spin_unlock_bh +EXPORT_SYMBOL vmlinux 0x3ab4d55b skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0x3b06bc64 pcim_iomap_table +EXPORT_SYMBOL vmlinux 0x3b241c39 pcie_port_service_unregister +EXPORT_SYMBOL vmlinux 0x3b3016d3 cpufreq_unregister_notifier +EXPORT_SYMBOL vmlinux 0x3b67cbbf __init_rwsem +EXPORT_SYMBOL vmlinux 0x3b758985 igrab +EXPORT_SYMBOL vmlinux 0x3b8b497a vcc_insert_socket +EXPORT_SYMBOL vmlinux 0x3b99acf1 blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0x3bb11fed unregister_framebuffer +EXPORT_SYMBOL vmlinux 0x3bcba798 gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0x3bd1b1f6 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x3bf4a7d8 __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x3c0cba13 set_pages_uc +EXPORT_SYMBOL vmlinux 0x3c2c5af5 sprintf +EXPORT_SYMBOL vmlinux 0x3c476e6f call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0x3c7227bf complete_all +EXPORT_SYMBOL vmlinux 0x3ca6dd26 udp_sendmsg +EXPORT_SYMBOL vmlinux 0x3cafe875 __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0x3cb8a495 param_get_string +EXPORT_SYMBOL vmlinux 0x3cc0a3bb xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x3cc233a8 security_d_instantiate +EXPORT_SYMBOL vmlinux 0x3cd49281 set_trace_device +EXPORT_SYMBOL vmlinux 0x3ce4ca6f disable_irq +EXPORT_SYMBOL vmlinux 0x3d02b406 generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0x3d5edc82 write_inode_now +EXPORT_SYMBOL vmlinux 0x3d6f4f80 pci_save_state +EXPORT_SYMBOL vmlinux 0x3d808ab6 fail_migrate_page +EXPORT_SYMBOL vmlinux 0x3d93363a inet_del_protocol +EXPORT_SYMBOL vmlinux 0x3d9ee9f0 clear_page +EXPORT_SYMBOL vmlinux 0x3da171f9 pci_mem_start +EXPORT_SYMBOL vmlinux 0x3da5eb6d kfifo_alloc +EXPORT_SYMBOL vmlinux 0x3db2e258 radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x3e1f073d wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x3e219de6 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x3e2427a1 acpi_check_region +EXPORT_SYMBOL vmlinux 0x3e2abd0d inode_double_unlock +EXPORT_SYMBOL vmlinux 0x3e2ae3a8 acpi_release_global_lock +EXPORT_SYMBOL vmlinux 0x3e427531 pnp_device_detach +EXPORT_SYMBOL vmlinux 0x3e4445f5 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x3e45e9ff register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x3e9700f2 agp_generic_alloc_by_type +EXPORT_SYMBOL vmlinux 0x3ec79280 poll_initwait +EXPORT_SYMBOL vmlinux 0x3ed63055 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x3f0546a8 ioread32_rep +EXPORT_SYMBOL vmlinux 0x3f054767 hippi_type_trans +EXPORT_SYMBOL vmlinux 0x3f1899f1 up +EXPORT_SYMBOL vmlinux 0x3f4547a7 put_unused_fd +EXPORT_SYMBOL vmlinux 0x3f72147c skb_queue_tail +EXPORT_SYMBOL vmlinux 0x3f7d72a1 flush_old_exec +EXPORT_SYMBOL vmlinux 0x3fa913da strspn +EXPORT_SYMBOL vmlinux 0x3faa8457 pci_request_region +EXPORT_SYMBOL vmlinux 0x3fbcddc3 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x3fec048f sg_next +EXPORT_SYMBOL vmlinux 0x3ff186a3 sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0x3ff62317 local_bh_disable +EXPORT_SYMBOL vmlinux 0x401e1c5f lock_rename +EXPORT_SYMBOL vmlinux 0x4039dd0c bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x405c1144 get_seconds +EXPORT_SYMBOL vmlinux 0x4074cbd6 request_firmware_nowait +EXPORT_SYMBOL vmlinux 0x408285f4 sk_stream_write_space +EXPORT_SYMBOL vmlinux 0x40935dc8 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0x409873e3 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x40a92a4b __pci_register_driver +EXPORT_SYMBOL vmlinux 0x40c89d46 acpi_get_table_by_index +EXPORT_SYMBOL vmlinux 0x40ef87a0 blk_unplug +EXPORT_SYMBOL vmlinux 0x4108e69a fb_match_mode +EXPORT_SYMBOL vmlinux 0x41315bc7 submit_bio +EXPORT_SYMBOL vmlinux 0x413818b1 put_tty_driver +EXPORT_SYMBOL vmlinux 0x41482d8b strndup_user +EXPORT_SYMBOL vmlinux 0x41711c46 seq_puts +EXPORT_SYMBOL vmlinux 0x4188d439 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x41a7c227 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x41a9c68d _spin_trylock_bh +EXPORT_SYMBOL vmlinux 0x41b3f40c dst_alloc +EXPORT_SYMBOL vmlinux 0x41ccc474 security_req_classify_flow +EXPORT_SYMBOL vmlinux 0x4211c3c1 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x42224298 sscanf +EXPORT_SYMBOL vmlinux 0x4225b265 tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x422c05d0 acpi_get_data +EXPORT_SYMBOL vmlinux 0x42a4bdf2 in_egroup_p +EXPORT_SYMBOL vmlinux 0x42b4db52 nf_register_queue_handler +EXPORT_SYMBOL vmlinux 0x42b9976b fb_blank +EXPORT_SYMBOL vmlinux 0x42d53a7f secpath_dup +EXPORT_SYMBOL vmlinux 0x4302d0eb free_pages +EXPORT_SYMBOL vmlinux 0x430a0ef3 set_user_nice +EXPORT_SYMBOL vmlinux 0x431c6b9d dev_alloc_name +EXPORT_SYMBOL vmlinux 0x4327f0d5 memset_io +EXPORT_SYMBOL vmlinux 0x43385ad9 acpi_pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x434fa55c release_console_sem +EXPORT_SYMBOL vmlinux 0x435b566d _spin_unlock +EXPORT_SYMBOL vmlinux 0x436bd315 posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0x436c2179 iowrite32 +EXPORT_SYMBOL vmlinux 0x437c50f7 end_dequeued_request +EXPORT_SYMBOL vmlinux 0x43ba7d6c backlight_device_register +EXPORT_SYMBOL vmlinux 0x43bdd372 request_resource +EXPORT_SYMBOL vmlinux 0x43be8bf3 pci_prepare_to_sleep +EXPORT_SYMBOL vmlinux 0x43ec913a put_cmsg +EXPORT_SYMBOL vmlinux 0x43f476c1 xfrm_state_update +EXPORT_SYMBOL vmlinux 0x44161c19 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x441b9b68 skb_make_writable +EXPORT_SYMBOL vmlinux 0x4423ea64 tty_hangup +EXPORT_SYMBOL vmlinux 0x4425ef6f skb_checksum_help +EXPORT_SYMBOL vmlinux 0x444779c4 nla_find +EXPORT_SYMBOL vmlinux 0x44531844 pskb_copy +EXPORT_SYMBOL vmlinux 0x4463a537 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0x44758928 proto_register +EXPORT_SYMBOL vmlinux 0x449b606c sync_blockdev +EXPORT_SYMBOL vmlinux 0x44aaf30f tsc_khz +EXPORT_SYMBOL vmlinux 0x44b911c3 rb_replace_node +EXPORT_SYMBOL vmlinux 0x44c8ac54 simple_readpage +EXPORT_SYMBOL vmlinux 0x44caa35e sk_wait_data +EXPORT_SYMBOL vmlinux 0x44ce93fd blk_recount_segments +EXPORT_SYMBOL vmlinux 0x44d560e3 init_level4_pgt +EXPORT_SYMBOL vmlinux 0x4506ed53 n_tty_ioctl +EXPORT_SYMBOL vmlinux 0x451e69a1 posix_test_lock +EXPORT_SYMBOL vmlinux 0x4520be77 deregister_atm_ioctl +EXPORT_SYMBOL vmlinux 0x4550ba8a register_cpu_notifier +EXPORT_SYMBOL vmlinux 0x455fd57d acpi_set_register +EXPORT_SYMBOL vmlinux 0x45704798 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x4572534c key_payload_reserve +EXPORT_SYMBOL vmlinux 0x459af11a give_up_console +EXPORT_SYMBOL vmlinux 0x45bb123e try_to_del_timer_sync +EXPORT_SYMBOL vmlinux 0x45c66ac4 dquot_free_inode +EXPORT_SYMBOL vmlinux 0x45d11c43 down_interruptible +EXPORT_SYMBOL vmlinux 0x45d597c0 pci_enable_bridges +EXPORT_SYMBOL vmlinux 0x45f786f7 idr_pre_get +EXPORT_SYMBOL vmlinux 0x465e1b57 km_new_mapping +EXPORT_SYMBOL vmlinux 0x466c14a7 __delay +EXPORT_SYMBOL vmlinux 0x46a70451 bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0x46c47fb6 __node_distance +EXPORT_SYMBOL vmlinux 0x46cddd4e agp_collect_device_status +EXPORT_SYMBOL vmlinux 0x46fb4ef3 input_event +EXPORT_SYMBOL vmlinux 0x46fd86c3 vfs_dq_quota_on_remount +EXPORT_SYMBOL vmlinux 0x4710a5d1 d_instantiate_unique +EXPORT_SYMBOL vmlinux 0x473f0d94 bio_copy_user +EXPORT_SYMBOL vmlinux 0x475100c2 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x475f010b acpi_purge_cached_objects +EXPORT_SYMBOL vmlinux 0x475f05af acpi_set_firmware_waking_vector +EXPORT_SYMBOL vmlinux 0x478d10b2 ht_destroy_irq +EXPORT_SYMBOL vmlinux 0x47939e0d __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x479c3c86 find_next_zero_bit +EXPORT_SYMBOL vmlinux 0x47e01089 simple_pin_fs +EXPORT_SYMBOL vmlinux 0x481cb9ab acpi_enter_sleep_state_prep +EXPORT_SYMBOL vmlinux 0x481dbe03 key_task_permission +EXPORT_SYMBOL vmlinux 0x4826a5a6 vfs_quota_on_mount +EXPORT_SYMBOL vmlinux 0x483af8d0 pci_iomap +EXPORT_SYMBOL vmlinux 0x4859b8bb rtc_year_days +EXPORT_SYMBOL vmlinux 0x486b6407 hweight64 +EXPORT_SYMBOL vmlinux 0x48a8a9c4 swiotlb_sync_single_for_cpu +EXPORT_SYMBOL vmlinux 0x48c3d32a file_permission +EXPORT_SYMBOL vmlinux 0x48fc80fe take_over_console +EXPORT_SYMBOL vmlinux 0x492331f8 add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0x493e25e1 udp_hash +EXPORT_SYMBOL vmlinux 0x4959ba7b km_state_notify +EXPORT_SYMBOL vmlinux 0x49603fb8 security_sb_copy_data +EXPORT_SYMBOL vmlinux 0x497f989e input_close_device +EXPORT_SYMBOL vmlinux 0x4993ebd9 fb_set_var +EXPORT_SYMBOL vmlinux 0x49bb588e blk_init_tags +EXPORT_SYMBOL vmlinux 0x49da9a9a _read_unlock_bh +EXPORT_SYMBOL vmlinux 0x4a0290f1 acpi_lock_ac_dir +EXPORT_SYMBOL vmlinux 0x4a1380ff skb_dequeue +EXPORT_SYMBOL vmlinux 0x4a358252 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x4a5ebc6a ida_get_new_above +EXPORT_SYMBOL vmlinux 0x4b07e779 _spin_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x4b085dbf agp3_generic_configure +EXPORT_SYMBOL vmlinux 0x4b146d28 drop_super +EXPORT_SYMBOL vmlinux 0x4b298689 vmtruncate +EXPORT_SYMBOL vmlinux 0x4b2f14b4 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x4b77c0d1 tcf_hash_insert +EXPORT_SYMBOL vmlinux 0x4ba5baa0 load_gs_index +EXPORT_SYMBOL vmlinux 0x4ba8d55f inet_sock_destruct +EXPORT_SYMBOL vmlinux 0x4bbac957 dev_mc_delete +EXPORT_SYMBOL vmlinux 0x4bbc3e5f pm_flags +EXPORT_SYMBOL vmlinux 0x4bc0ba45 task_session_nr_ns +EXPORT_SYMBOL vmlinux 0x4c1182cb bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x4c2a0e63 alloc_file +EXPORT_SYMBOL vmlinux 0x4c309d6b scm_detach_fds +EXPORT_SYMBOL vmlinux 0x4c30bc72 splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0x4c3718c9 xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x4c3af445 __request_region +EXPORT_SYMBOL vmlinux 0x4c4c956e nla_memcmp +EXPORT_SYMBOL vmlinux 0x4c52ecc4 sock_kfree_s +EXPORT_SYMBOL vmlinux 0x4c74fd13 page_symlink +EXPORT_SYMBOL vmlinux 0x4c828a6e clear_bdi_congested +EXPORT_SYMBOL vmlinux 0x4c84ba63 sockfd_lookup +EXPORT_SYMBOL vmlinux 0x4c95ccf5 cdev_init +EXPORT_SYMBOL vmlinux 0x4ca4981f __inet6_lookup_established +EXPORT_SYMBOL vmlinux 0x4cab9dbd sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0x4cabd657 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x4cbbd171 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x4cc392b5 register_sysctl_table +EXPORT_SYMBOL vmlinux 0x4ce5b556 current_fs_time +EXPORT_SYMBOL vmlinux 0x4d62488f dev_disable_lro +EXPORT_SYMBOL vmlinux 0x4d63ed76 vfs_set_dqblk +EXPORT_SYMBOL vmlinux 0x4d82fb7a put_page +EXPORT_SYMBOL vmlinux 0x4dada75d input_open_device +EXPORT_SYMBOL vmlinux 0x4db1e1d4 posix_acl_equiv_mode +EXPORT_SYMBOL vmlinux 0x4db2f931 directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0x4dda726b match_strlcpy +EXPORT_SYMBOL vmlinux 0x4ddc4b9f utf8_mbtowc +EXPORT_SYMBOL vmlinux 0x4df119fa __bitmap_parse +EXPORT_SYMBOL vmlinux 0x4df47e9f xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x4e0fec2a xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0x4e100f60 _spin_unlock_irq +EXPORT_SYMBOL vmlinux 0x4e2eb05a framebuffer_alloc +EXPORT_SYMBOL vmlinux 0x4e3567f7 match_int +EXPORT_SYMBOL vmlinux 0x4e6e8ea7 fg_console +EXPORT_SYMBOL vmlinux 0x4e7ce052 tcf_exts_change +EXPORT_SYMBOL vmlinux 0x4e969241 iw_handler_get_thrspy +EXPORT_SYMBOL vmlinux 0x4edd72f7 block_all_signals +EXPORT_SYMBOL vmlinux 0x4f43133d tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x4f515289 sock_wfree +EXPORT_SYMBOL vmlinux 0x4f5438c1 idle_halt +EXPORT_SYMBOL vmlinux 0x4f7d14bb sb_set_blocksize +EXPORT_SYMBOL vmlinux 0x4f82feb3 __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x4f917bd0 atm_init_aal5 +EXPORT_SYMBOL vmlinux 0x4f97e8c0 acpi_unlock_ac_dir +EXPORT_SYMBOL vmlinux 0x4fa71b5d end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0x4fa75270 inet_frags_fini +EXPORT_SYMBOL vmlinux 0x4fcee107 __up_read +EXPORT_SYMBOL vmlinux 0x4fdee897 i8042_command +EXPORT_SYMBOL vmlinux 0x4fe20744 bio_add_page +EXPORT_SYMBOL vmlinux 0x5003d626 d_validate +EXPORT_SYMBOL vmlinux 0x50152bb4 agp_backend_release +EXPORT_SYMBOL vmlinux 0x50211ee3 tcp_free_md5sig_pool +EXPORT_SYMBOL vmlinux 0x5031dfff registered_fb +EXPORT_SYMBOL vmlinux 0x503a3efe pci_unmap_rom +EXPORT_SYMBOL vmlinux 0x5045c92d compat_sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x50af6d2d arp_xmit +EXPORT_SYMBOL vmlinux 0x50ba769a kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0x5118c382 secure_dccp_sequence_number +EXPORT_SYMBOL vmlinux 0x511a070e pnp_release_card_device +EXPORT_SYMBOL vmlinux 0x511e1375 fb_class +EXPORT_SYMBOL vmlinux 0x512e7cdc generic_unplug_device +EXPORT_SYMBOL vmlinux 0x513b4f21 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0x5195fba7 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0x51cf6d2d ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0x51d12d4e acpi_pci_disabled +EXPORT_SYMBOL vmlinux 0x51d7a776 acpi_detach_data +EXPORT_SYMBOL vmlinux 0x51dd9ad9 netdev_set_master +EXPORT_SYMBOL vmlinux 0x51edcf11 dma_pool_free +EXPORT_SYMBOL vmlinux 0x52026cdf security_sb_parse_opts_str +EXPORT_SYMBOL vmlinux 0x5212317c pci_set_dma_seg_boundary +EXPORT_SYMBOL vmlinux 0x521d63ec wait_for_key_construction +EXPORT_SYMBOL vmlinux 0x522f5573 pv_irq_ops +EXPORT_SYMBOL vmlinux 0x5252f304 __memcpy_toio +EXPORT_SYMBOL vmlinux 0x52979c21 bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0x52a58c24 ifla_policy +EXPORT_SYMBOL vmlinux 0x52af9451 search_binary_handler +EXPORT_SYMBOL vmlinux 0x52d7b2fd llc_sap_list +EXPORT_SYMBOL vmlinux 0x530b1e98 pm_suspend +EXPORT_SYMBOL vmlinux 0x532f2924 param_get_byte +EXPORT_SYMBOL vmlinux 0x53326531 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x5367bd63 find_or_create_page +EXPORT_SYMBOL vmlinux 0x539385d7 kernel_accept +EXPORT_SYMBOL vmlinux 0x53c0767c sk_chk_filter +EXPORT_SYMBOL vmlinux 0x53df2682 serio_reconnect +EXPORT_SYMBOL vmlinux 0x53f87323 struct_module +EXPORT_SYMBOL vmlinux 0x53ff09fb pci_find_parent_resource +EXPORT_SYMBOL vmlinux 0x54290dc9 nla_validate +EXPORT_SYMBOL vmlinux 0x543affb5 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x54907126 sk_common_release +EXPORT_SYMBOL vmlinux 0x54b81541 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0x54c4110e lock_may_read +EXPORT_SYMBOL vmlinux 0x54ca1955 init_special_inode +EXPORT_SYMBOL vmlinux 0x54cc0bda devm_ioremap +EXPORT_SYMBOL vmlinux 0x54e6fcdd net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x550f8ade groups_alloc +EXPORT_SYMBOL vmlinux 0x555385e6 sk_stop_timer +EXPORT_SYMBOL vmlinux 0x5594be03 bitmap_remap +EXPORT_SYMBOL vmlinux 0x55bc9303 netpoll_setup +EXPORT_SYMBOL vmlinux 0x55c68172 tcp_splice_read +EXPORT_SYMBOL vmlinux 0x55ee518a kfree_skb +EXPORT_SYMBOL vmlinux 0x55f151fe cap_netlink_recv +EXPORT_SYMBOL vmlinux 0x5600904f fb_get_color_depth +EXPORT_SYMBOL vmlinux 0x5635a60a vmalloc_user +EXPORT_SYMBOL vmlinux 0x56571e89 sg_miter_stop +EXPORT_SYMBOL vmlinux 0x56a1951c kset_unregister +EXPORT_SYMBOL vmlinux 0x56b7ccf0 blk_start_queueing +EXPORT_SYMBOL vmlinux 0x56bcadeb pci_bus_read_config_byte +EXPORT_SYMBOL vmlinux 0x56dba97c dma_async_client_chan_request +EXPORT_SYMBOL vmlinux 0x56f494e0 smp_call_function +EXPORT_SYMBOL vmlinux 0x5721d24e __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x572e85d4 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x57376558 skb_split +EXPORT_SYMBOL vmlinux 0x57516471 tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0x576d8804 freeze_bdev +EXPORT_SYMBOL vmlinux 0x577cc638 mutex_unlock +EXPORT_SYMBOL vmlinux 0x57ca0485 rtnl_notify +EXPORT_SYMBOL vmlinux 0x57d9ac16 tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0x57fa779f __blk_run_queue +EXPORT_SYMBOL vmlinux 0x580eda72 nf_unregister_sockopt +EXPORT_SYMBOL vmlinux 0x5810f6f2 put_io_context +EXPORT_SYMBOL vmlinux 0x583721b5 try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x5838f6c9 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x584738f9 rdmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x584c8bd8 page_put_link +EXPORT_SYMBOL vmlinux 0x5857b225 ioread16_rep +EXPORT_SYMBOL vmlinux 0x589f51b1 blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0x58a6f270 tty_check_change +EXPORT_SYMBOL vmlinux 0x58ccb675 no_llseek +EXPORT_SYMBOL vmlinux 0x58e45b27 kthread_stop +EXPORT_SYMBOL vmlinux 0x5927bfbc tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x5933ebe5 release_sock +EXPORT_SYMBOL vmlinux 0x5934392b fb_register_client +EXPORT_SYMBOL vmlinux 0x594bf15b ioport_map +EXPORT_SYMBOL vmlinux 0x59862e04 elv_rb_find +EXPORT_SYMBOL vmlinux 0x59a6ff40 pnp_activate_dev +EXPORT_SYMBOL vmlinux 0x59d696b6 register_module_notifier +EXPORT_SYMBOL vmlinux 0x59da3c6f pci_enable_device_io +EXPORT_SYMBOL vmlinux 0x5a0cddd4 prepare_binprm +EXPORT_SYMBOL vmlinux 0x5a0d4358 free_task +EXPORT_SYMBOL vmlinux 0x5a30bb45 remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0x5a34a45c __kmalloc +EXPORT_SYMBOL vmlinux 0x5a433740 skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0x5a43a90e get_user_pages +EXPORT_SYMBOL vmlinux 0x5a4896a8 __put_user_2 +EXPORT_SYMBOL vmlinux 0x5a5e7ea3 simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x5a69219f __up_write +EXPORT_SYMBOL vmlinux 0x5a744b86 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x5a772174 dev_set_mac_address +EXPORT_SYMBOL vmlinux 0x5aa76213 cpufreq_get_policy +EXPORT_SYMBOL vmlinux 0x5ac376a5 acpi_install_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x5ad41249 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0x5af17dc1 generic_permission +EXPORT_SYMBOL vmlinux 0x5b0945b6 pnp_register_card_driver +EXPORT_SYMBOL vmlinux 0x5b112f78 xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0x5b51c6a7 acpi_walk_resources +EXPORT_SYMBOL vmlinux 0x5b77ddc8 blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0x5bae2eac acpi_extract_package +EXPORT_SYMBOL vmlinux 0x5bbcafba pci_bus_type +EXPORT_SYMBOL vmlinux 0x5bec44cb __down_write +EXPORT_SYMBOL vmlinux 0x5c2375e8 destroy_EII_client +EXPORT_SYMBOL vmlinux 0x5c385150 xfrm_user_policy +EXPORT_SYMBOL vmlinux 0x5c46b6fa posix_acl_chmod_masq +EXPORT_SYMBOL vmlinux 0x5c4e7ab0 xfrm_nl +EXPORT_SYMBOL vmlinux 0x5c65d7f6 register_nls +EXPORT_SYMBOL vmlinux 0x5c6ad800 console_stop +EXPORT_SYMBOL vmlinux 0x5c70c2db generic_write_end +EXPORT_SYMBOL vmlinux 0x5c7505cd save_mount_options +EXPORT_SYMBOL vmlinux 0x5c87da2c blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0x5c8db279 inc_zone_page_state +EXPORT_SYMBOL vmlinux 0x5c9a6c03 swiotlb_map_sg_attrs +EXPORT_SYMBOL vmlinux 0x5ca0000d schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0x5ca0ed91 test_set_page_writeback +EXPORT_SYMBOL vmlinux 0x5ca264a5 per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0x5cb2c222 dev_mc_sync +EXPORT_SYMBOL vmlinux 0x5cba1497 agp_free_memory +EXPORT_SYMBOL vmlinux 0x5cc8e015 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0x5cfaefdf task_nice +EXPORT_SYMBOL vmlinux 0x5d113035 vm_stat +EXPORT_SYMBOL vmlinux 0x5d370f3f __free_pages +EXPORT_SYMBOL vmlinux 0x5d5c4ff0 vfs_dq_drop +EXPORT_SYMBOL vmlinux 0x5d73b5f8 km_waitq +EXPORT_SYMBOL vmlinux 0x5d7e09de alloc_hippi_dev +EXPORT_SYMBOL vmlinux 0x5da8e6de xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x5dafd05c netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0x5dbcfa4f boot_cpu_physical_apicid +EXPORT_SYMBOL vmlinux 0x5de8aa28 file_remove_suid +EXPORT_SYMBOL vmlinux 0x5decbfcd set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x5e0f7602 pcix_set_mmrbc +EXPORT_SYMBOL vmlinux 0x5e14fa11 ilookup +EXPORT_SYMBOL vmlinux 0x5e744305 llc_sap_open +EXPORT_SYMBOL vmlinux 0x5e79ebec gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x5e8d5534 ps2_handle_ack +EXPORT_SYMBOL vmlinux 0x5e91de37 dev_unicast_delete +EXPORT_SYMBOL vmlinux 0x5e9f09df get_io_context +EXPORT_SYMBOL vmlinux 0x5ea520c5 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x5eab426c serio_open +EXPORT_SYMBOL vmlinux 0x5eb8690c single_open +EXPORT_SYMBOL vmlinux 0x5ec0d148 may_umount_tree +EXPORT_SYMBOL vmlinux 0x5ed040b0 pm_set_vt_switch +EXPORT_SYMBOL vmlinux 0x5edd0762 bin2bcd +EXPORT_SYMBOL vmlinux 0x5f06ca2f skb_copy +EXPORT_SYMBOL vmlinux 0x5f085fe4 __netif_schedule +EXPORT_SYMBOL vmlinux 0x5f5b50ab ps2_init +EXPORT_SYMBOL vmlinux 0x5f627089 tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0x5f8dc294 dcache_dir_close +EXPORT_SYMBOL vmlinux 0x5fabae42 udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0x600683d3 do_unblank_screen +EXPORT_SYMBOL vmlinux 0x60278305 vcc_release_async +EXPORT_SYMBOL vmlinux 0x6037ae52 pcim_pin_device +EXPORT_SYMBOL vmlinux 0x603a6656 br_handle_frame_hook +EXPORT_SYMBOL vmlinux 0x60400b7f pv_lock_ops +EXPORT_SYMBOL vmlinux 0x605c8bde radix_tree_delete +EXPORT_SYMBOL vmlinux 0x606a5bca tcf_hash_check +EXPORT_SYMBOL vmlinux 0x608c2831 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x609f1c7e synchronize_net +EXPORT_SYMBOL vmlinux 0x60a32ea9 pm_power_off +EXPORT_SYMBOL vmlinux 0x60d550eb __dec_zone_page_state +EXPORT_SYMBOL vmlinux 0x6111e1bc init_timer +EXPORT_SYMBOL vmlinux 0x612390ad netpoll_set_trap +EXPORT_SYMBOL vmlinux 0x6159c44d request_key_async +EXPORT_SYMBOL vmlinux 0x615bb0a3 open_bdev_excl +EXPORT_SYMBOL vmlinux 0x61619723 agp_allocate_memory +EXPORT_SYMBOL vmlinux 0x61799c93 __seq_open_private +EXPORT_SYMBOL vmlinux 0x618d8299 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x61abb458 pci_dev_get +EXPORT_SYMBOL vmlinux 0x61b7b126 simple_strtoull +EXPORT_SYMBOL vmlinux 0x61c1c365 unregister_key_type +EXPORT_SYMBOL vmlinux 0x62049256 acpi_disable +EXPORT_SYMBOL vmlinux 0x6237f6b5 acpi_enable_event +EXPORT_SYMBOL vmlinux 0x624fb85c blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x62737e1d sock_unregister +EXPORT_SYMBOL vmlinux 0x62748e70 acpi_set_current_resources +EXPORT_SYMBOL vmlinux 0x62827bec security_secctx_to_secid +EXPORT_SYMBOL vmlinux 0x62d9975e vfs_quota_on +EXPORT_SYMBOL vmlinux 0x631bb5e8 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0x633354e6 atm_charge +EXPORT_SYMBOL vmlinux 0x633b7084 acpi_unlock_battery_dir +EXPORT_SYMBOL vmlinux 0x63499009 pci_assign_resource +EXPORT_SYMBOL vmlinux 0x6361b125 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0x63694ce7 key_unlink +EXPORT_SYMBOL vmlinux 0x636a5691 acpi_register_ioapic +EXPORT_SYMBOL vmlinux 0x636b5eb7 generic_setlease +EXPORT_SYMBOL vmlinux 0x638675b4 swiotlb_sync_single_for_device +EXPORT_SYMBOL vmlinux 0x63b8dd20 end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0x63cd7b2f alloc_fcdev +EXPORT_SYMBOL vmlinux 0x63e79481 dst_destroy +EXPORT_SYMBOL vmlinux 0x63ecad53 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x63ed4f65 ioremap_cache +EXPORT_SYMBOL vmlinux 0x63f1d58f request_key_async_with_auxdata +EXPORT_SYMBOL vmlinux 0x63fc232f strlen_user +EXPORT_SYMBOL vmlinux 0x6403e338 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x640f9821 vfs_dq_transfer +EXPORT_SYMBOL vmlinux 0x642e54ac __wake_up +EXPORT_SYMBOL vmlinux 0x6451294b posix_acl_valid +EXPORT_SYMBOL vmlinux 0x6451b5af blk_rq_init +EXPORT_SYMBOL vmlinux 0x645735fb blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x6466a1e6 mempool_alloc +EXPORT_SYMBOL vmlinux 0x647708aa __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0x6478134c ec_burst_enable +EXPORT_SYMBOL vmlinux 0x647e1678 skb_trim +EXPORT_SYMBOL vmlinux 0x6482dd65 pci_bus_size_bridges +EXPORT_SYMBOL vmlinux 0x64999478 congestion_wait +EXPORT_SYMBOL vmlinux 0x64b491e5 inode_add_bytes +EXPORT_SYMBOL vmlinux 0x64cd5d16 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x64f824dc sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x64f8e672 bio_pair_release +EXPORT_SYMBOL vmlinux 0x650128e7 br_fdb_get_hook +EXPORT_SYMBOL vmlinux 0x650fb346 add_wait_queue +EXPORT_SYMBOL vmlinux 0x6516cb0c skb_truesize_bug +EXPORT_SYMBOL vmlinux 0x651e497c nf_afinfo +EXPORT_SYMBOL vmlinux 0x653fb40b devm_request_irq +EXPORT_SYMBOL vmlinux 0x65408378 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x65414e67 dev_valid_name +EXPORT_SYMBOL vmlinux 0x65930cce pcim_enable_device +EXPORT_SYMBOL vmlinux 0x65b5ad18 d_genocide +EXPORT_SYMBOL vmlinux 0x65f5ef5e xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0x6601f37b qdisc_class_hash_grow +EXPORT_SYMBOL vmlinux 0x661a4ccf sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0x668da8d5 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x669c2832 blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0x66b17ac4 lock_may_write +EXPORT_SYMBOL vmlinux 0x66ec4db9 skb_unlink +EXPORT_SYMBOL vmlinux 0x66f5b237 km_state_expired +EXPORT_SYMBOL vmlinux 0x66f9bb0c d_splice_alias +EXPORT_SYMBOL vmlinux 0x672144bd strlcpy +EXPORT_SYMBOL vmlinux 0x6729d3df __get_user_4 +EXPORT_SYMBOL vmlinux 0x673f815e agp_bridges +EXPORT_SYMBOL vmlinux 0x674598ca bmap +EXPORT_SYMBOL vmlinux 0x674f95b7 sk_run_filter +EXPORT_SYMBOL vmlinux 0x6768497e pcim_iomap_regions +EXPORT_SYMBOL vmlinux 0x678907d2 skb_append +EXPORT_SYMBOL vmlinux 0x679db766 sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x67a10240 k8_northbridges +EXPORT_SYMBOL vmlinux 0x67b27ec1 tty_std_termios +EXPORT_SYMBOL vmlinux 0x67e71b77 __mutex_init +EXPORT_SYMBOL vmlinux 0x680b08cc kmem_cache_size +EXPORT_SYMBOL vmlinux 0x681cd4c1 posix_lock_file +EXPORT_SYMBOL vmlinux 0x684f5e71 textsearch_unregister +EXPORT_SYMBOL vmlinux 0x6882e91a sysctl_data +EXPORT_SYMBOL vmlinux 0x68ea763e console_start +EXPORT_SYMBOL vmlinux 0x68fb5a1f lease_get_mtime +EXPORT_SYMBOL vmlinux 0x68fc3e02 tty_devnum +EXPORT_SYMBOL vmlinux 0x69192b5a iommu_num_pages +EXPORT_SYMBOL vmlinux 0x69263f03 llc_set_station_handler +EXPORT_SYMBOL vmlinux 0x693a0827 input_allocate_device +EXPORT_SYMBOL vmlinux 0x695c9799 vm_insert_mixed +EXPORT_SYMBOL vmlinux 0x69682087 blk_start_queue +EXPORT_SYMBOL vmlinux 0x69703221 sock_no_sendpage +EXPORT_SYMBOL vmlinux 0x6971447a rtc_month_days +EXPORT_SYMBOL vmlinux 0x69927dff try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x69a0ca7d iowrite16be +EXPORT_SYMBOL vmlinux 0x6a035a02 sk_dst_check +EXPORT_SYMBOL vmlinux 0x6a037cf1 mempool_kfree +EXPORT_SYMBOL vmlinux 0x6a26ed8a vfs_getattr +EXPORT_SYMBOL vmlinux 0x6a47571d __set_personality +EXPORT_SYMBOL vmlinux 0x6a5fa363 sigprocmask +EXPORT_SYMBOL vmlinux 0x6a847e81 xfrm_input_resume +EXPORT_SYMBOL vmlinux 0x6a9ca5db kobject_get +EXPORT_SYMBOL vmlinux 0x6acb973d iowrite32be +EXPORT_SYMBOL vmlinux 0x6add5c9a dmi_find_device +EXPORT_SYMBOL vmlinux 0x6aff05df inetdev_by_index +EXPORT_SYMBOL vmlinux 0x6b1b67d3 __bdevname +EXPORT_SYMBOL vmlinux 0x6b266982 agp_generic_free_by_type +EXPORT_SYMBOL vmlinux 0x6b2dc060 dump_stack +EXPORT_SYMBOL vmlinux 0x6b3d87aa __page_cache_alloc +EXPORT_SYMBOL vmlinux 0x6b4e5a52 radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x6b9b88f3 sleep_on +EXPORT_SYMBOL vmlinux 0x6b9e09fb skb_clone +EXPORT_SYMBOL vmlinux 0x6bafbced mod_timer +EXPORT_SYMBOL vmlinux 0x6bc56c67 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x6bd16613 sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x6bdcfd99 qdisc_class_hash_remove +EXPORT_SYMBOL vmlinux 0x6c389761 acpi_bus_get_private_data +EXPORT_SYMBOL vmlinux 0x6c61ce70 num_registered_fb +EXPORT_SYMBOL vmlinux 0x6c702af7 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x6c8c3150 udp_lib_get_port +EXPORT_SYMBOL vmlinux 0x6c8c3ecd generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0x6cbe7632 posix_acl_to_xattr +EXPORT_SYMBOL vmlinux 0x6cd21961 simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x6cf1cc92 cdev_alloc +EXPORT_SYMBOL vmlinux 0x6d046044 tcp_disconnect +EXPORT_SYMBOL vmlinux 0x6d0da34c param_get_short +EXPORT_SYMBOL vmlinux 0x6d1ced27 vcc_sklist_lock +EXPORT_SYMBOL vmlinux 0x6d27ef64 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x6d294e43 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x6d334118 __get_user_8 +EXPORT_SYMBOL vmlinux 0x6d340f64 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x6d47d90d groups_free +EXPORT_SYMBOL vmlinux 0x6d6bd3fe blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0x6d7c124e read_cache_pages +EXPORT_SYMBOL vmlinux 0x6dc0c24b complete_and_exit +EXPORT_SYMBOL vmlinux 0x6ddd0b1a handle_sysrq +EXPORT_SYMBOL vmlinux 0x6de6bf83 radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x6def2db2 half_md4_transform +EXPORT_SYMBOL vmlinux 0x6e07a54e acpi_get_gpe_status +EXPORT_SYMBOL vmlinux 0x6e121cf3 proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x6e1a4bbb udp_hash_lock +EXPORT_SYMBOL vmlinux 0x6e3b7ab9 d_find_alias +EXPORT_SYMBOL vmlinux 0x6e49ec96 truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0x6e5c88b0 kobject_del +EXPORT_SYMBOL vmlinux 0x6e720ff2 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x6e7791a8 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0x6e9dd606 __symbol_put +EXPORT_SYMBOL vmlinux 0x6e9fa9ba udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x6ead242b cond_resched_lock +EXPORT_SYMBOL vmlinux 0x6eb8d32e blk_put_request +EXPORT_SYMBOL vmlinux 0x6ebde183 vm_insert_page +EXPORT_SYMBOL vmlinux 0x6edd2a99 sock_create_kern +EXPORT_SYMBOL vmlinux 0x6f02af52 compat_nf_getsockopt +EXPORT_SYMBOL vmlinux 0x6f0625da eth_rebuild_header +EXPORT_SYMBOL vmlinux 0x6f526d25 acpi_bus_unregister_driver +EXPORT_SYMBOL vmlinux 0x6f6231d1 bdget +EXPORT_SYMBOL vmlinux 0x6f84946c kmem_cache_alloc_node +EXPORT_SYMBOL vmlinux 0x6fa0fdcf call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0x6fab79fc inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0x6fcb87a1 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x6ff1fdd5 vfs_mknod +EXPORT_SYMBOL vmlinux 0x7008a9b7 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x7018c8ab __neigh_event_send +EXPORT_SYMBOL vmlinux 0x702b97ec sock_get_timestampns +EXPORT_SYMBOL vmlinux 0x702c87c0 inet_getname +EXPORT_SYMBOL vmlinux 0x704c1c13 read_cache_page +EXPORT_SYMBOL vmlinux 0x7054a3e4 request_dma +EXPORT_SYMBOL vmlinux 0x70b868b5 sk_alloc +EXPORT_SYMBOL vmlinux 0x70d8ab82 acpi_acquire_global_lock +EXPORT_SYMBOL vmlinux 0x70f0d3c2 generic_file_mmap +EXPORT_SYMBOL vmlinux 0x70fdce13 dma_async_client_unregister +EXPORT_SYMBOL vmlinux 0x711e84da inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0x7129e5f8 hex_asc +EXPORT_SYMBOL vmlinux 0x712aa29b _spin_lock_irqsave +EXPORT_SYMBOL vmlinux 0x71356fba remove_wait_queue +EXPORT_SYMBOL vmlinux 0x7152a78f ip_defrag +EXPORT_SYMBOL vmlinux 0x7171121c overflowgid +EXPORT_SYMBOL vmlinux 0x718c46a3 sock_init_data +EXPORT_SYMBOL vmlinux 0x71a50dbc register_blkdev +EXPORT_SYMBOL vmlinux 0x71d7819e ilookup5 +EXPORT_SYMBOL vmlinux 0x71dbe933 kernel_recvmsg +EXPORT_SYMBOL vmlinux 0x71e62871 agp_copy_info +EXPORT_SYMBOL vmlinux 0x71f6eb38 sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0x72270e35 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x7242e96d strnchr +EXPORT_SYMBOL vmlinux 0x724df501 vfs_quota_on_path +EXPORT_SYMBOL vmlinux 0x726ef074 bio_integrity_prep +EXPORT_SYMBOL vmlinux 0x72886bbc __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0x7295ff60 tty_throttle +EXPORT_SYMBOL vmlinux 0x72b243d4 free_dma +EXPORT_SYMBOL vmlinux 0x72ba443c wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0x72bf2140 mtrr_add +EXPORT_SYMBOL vmlinux 0x72d2d9de acpi_root_dir +EXPORT_SYMBOL vmlinux 0x72d45bc3 unregister_filesystem +EXPORT_SYMBOL vmlinux 0x72e02b50 netlink_ack +EXPORT_SYMBOL vmlinux 0x72ed7bec kill_fasync +EXPORT_SYMBOL vmlinux 0x7304a357 set_disk_ro +EXPORT_SYMBOL vmlinux 0x73112117 unlock_super +EXPORT_SYMBOL vmlinux 0x735a0bd5 native_io_delay +EXPORT_SYMBOL vmlinux 0x7389c9a8 acpi_bus_get_power +EXPORT_SYMBOL vmlinux 0x7397568c xfrm_find_acq +EXPORT_SYMBOL vmlinux 0x739ee22d gen_pool_add +EXPORT_SYMBOL vmlinux 0x740a1b95 reserve_evntsel_nmi +EXPORT_SYMBOL vmlinux 0x74202777 ioremap_prot +EXPORT_SYMBOL vmlinux 0x743cefec locks_mandatory_area +EXPORT_SYMBOL vmlinux 0x7485e15e unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x748caf40 down +EXPORT_SYMBOL vmlinux 0x74af9abf netif_carrier_on +EXPORT_SYMBOL vmlinux 0x74cc1cbe unregister_cpu_notifier +EXPORT_SYMBOL vmlinux 0x74cc238d current_kernel_time +EXPORT_SYMBOL vmlinux 0x7538b132 agp_off +EXPORT_SYMBOL vmlinux 0x754251ef bio_phys_segments +EXPORT_SYMBOL vmlinux 0x756e6992 strnicmp +EXPORT_SYMBOL vmlinux 0x759d60ae xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0x75bdea12 iommu_area_alloc +EXPORT_SYMBOL vmlinux 0x75ea9531 key_negate_and_link +EXPORT_SYMBOL vmlinux 0x75fec8c2 generic_make_request +EXPORT_SYMBOL vmlinux 0x760a0f4f yield +EXPORT_SYMBOL vmlinux 0x760b437a unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x7621bbf3 uart_write_wakeup +EXPORT_SYMBOL vmlinux 0x763fe03e alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0x7642b041 tty_set_operations +EXPORT_SYMBOL vmlinux 0x764383fe simple_sync_file +EXPORT_SYMBOL vmlinux 0x76477963 start_tty +EXPORT_SYMBOL vmlinux 0x764a61ac kernel_bind +EXPORT_SYMBOL vmlinux 0x76548acf tcf_exts_destroy +EXPORT_SYMBOL vmlinux 0x7662a2a4 single_release +EXPORT_SYMBOL vmlinux 0x766a6b7e block_invalidatepage +EXPORT_SYMBOL vmlinux 0x7676f928 filp_close +EXPORT_SYMBOL vmlinux 0x767dd8fd acpi_get_irq_routing_table +EXPORT_SYMBOL vmlinux 0x767ddb02 set_memory_wc +EXPORT_SYMBOL vmlinux 0x767fb41e netlink_kernel_release +EXPORT_SYMBOL vmlinux 0x768231ce sysctl_intvec +EXPORT_SYMBOL vmlinux 0x76bf656d __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x76d3cd60 laptop_mode +EXPORT_SYMBOL vmlinux 0x76d55c94 netlink_broadcast +EXPORT_SYMBOL vmlinux 0x76f3f8a5 num_k8_northbridges +EXPORT_SYMBOL vmlinux 0x7733d5dc input_release_device +EXPORT_SYMBOL vmlinux 0x77489bd3 register_key_type +EXPORT_SYMBOL vmlinux 0x7791a6c7 qdisc_tree_decrease_qlen +EXPORT_SYMBOL vmlinux 0x77a108df _write_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x77bc1f77 pci_dev_driver +EXPORT_SYMBOL vmlinux 0x77e0d1fb ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x77ecac9f zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x77f53abc acpi_get_vendor_resource +EXPORT_SYMBOL vmlinux 0x77f708fe nobh_writepage +EXPORT_SYMBOL vmlinux 0x782d973d neigh_update +EXPORT_SYMBOL vmlinux 0x7837c129 agp_generic_free_gatt_table +EXPORT_SYMBOL vmlinux 0x788e3aa4 filemap_fault +EXPORT_SYMBOL vmlinux 0x78a484c9 _read_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x78ae6073 init_net +EXPORT_SYMBOL vmlinux 0x78df6bd7 no_pci_devices +EXPORT_SYMBOL vmlinux 0x78e37d20 elv_next_request +EXPORT_SYMBOL vmlinux 0x78ee99be eth_header_cache_update +EXPORT_SYMBOL vmlinux 0x78f914ee file_fsync +EXPORT_SYMBOL vmlinux 0x794c1398 dmi_check_system +EXPORT_SYMBOL vmlinux 0x795d0d00 __f_setown +EXPORT_SYMBOL vmlinux 0x79656409 cpu_online_map +EXPORT_SYMBOL vmlinux 0x799b0338 dev_driver_string +EXPORT_SYMBOL vmlinux 0x79aa04a2 get_random_bytes +EXPORT_SYMBOL vmlinux 0x79aa05a8 match_token +EXPORT_SYMBOL vmlinux 0x79be9827 uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x79ce4d5c arp_find +EXPORT_SYMBOL vmlinux 0x79cf399a agp_bridge +EXPORT_SYMBOL vmlinux 0x79d78989 set_irq_chip +EXPORT_SYMBOL vmlinux 0x7a054d2b __sk_dst_check +EXPORT_SYMBOL vmlinux 0x7a18b1b7 __napi_schedule +EXPORT_SYMBOL vmlinux 0x7a2a837d strict_strtol +EXPORT_SYMBOL vmlinux 0x7a3e9202 sock_map_fd +EXPORT_SYMBOL vmlinux 0x7a4bded8 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0x7a848702 _read_lock_irqsave +EXPORT_SYMBOL vmlinux 0x7a93abaf __nla_put +EXPORT_SYMBOL vmlinux 0x7a9a60cc tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0x7ae73de1 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0x7aec9089 clear_user +EXPORT_SYMBOL vmlinux 0x7b0c84c4 acpi_remove_table_handler +EXPORT_SYMBOL vmlinux 0x7b351aec bd_set_size +EXPORT_SYMBOL vmlinux 0x7b52a859 wrmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x7b8f4c40 key_create_or_update +EXPORT_SYMBOL vmlinux 0x7bc3102f do_munmap +EXPORT_SYMBOL vmlinux 0x7bc316a9 dquot_initialize +EXPORT_SYMBOL vmlinux 0x7be3fc60 tcf_action_exec +EXPORT_SYMBOL vmlinux 0x7bff3be7 iov_iter_advance +EXPORT_SYMBOL vmlinux 0x7c125b72 get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x7c46233a cpufreq_quick_get +EXPORT_SYMBOL vmlinux 0x7c5bb12b __ip_select_ident +EXPORT_SYMBOL vmlinux 0x7c5c18d5 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0x7c60d66e getname +EXPORT_SYMBOL vmlinux 0x7c6eb1d1 nf_setsockopt +EXPORT_SYMBOL vmlinux 0x7c8c1c36 module_put +EXPORT_SYMBOL vmlinux 0x7c904ded unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x7cb1ae69 cpu_down +EXPORT_SYMBOL vmlinux 0x7cfdec4d remove_inode_hash +EXPORT_SYMBOL vmlinux 0x7d047e7e acpi_ut_exception +EXPORT_SYMBOL vmlinux 0x7d11c268 jiffies +EXPORT_SYMBOL vmlinux 0x7d698583 swiotlb_unmap_single_attrs +EXPORT_SYMBOL vmlinux 0x7d6e5a2e pci_set_power_state +EXPORT_SYMBOL vmlinux 0x7d850612 utf8_mbstowcs +EXPORT_SYMBOL vmlinux 0x7d91c347 inode_sub_bytes +EXPORT_SYMBOL vmlinux 0x7d94f746 acpi_os_write_port +EXPORT_SYMBOL vmlinux 0x7d9c08c0 fb_set_suspend +EXPORT_SYMBOL vmlinux 0x7da56a06 alloc_pci_dev +EXPORT_SYMBOL vmlinux 0x7dceceac capable +EXPORT_SYMBOL vmlinux 0x7e449e41 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0x7e489097 input_flush_device +EXPORT_SYMBOL vmlinux 0x7e7d2f30 bio_integrity_split +EXPORT_SYMBOL vmlinux 0x7e9ebb05 kernel_thread +EXPORT_SYMBOL vmlinux 0x7ec812a2 blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0x7ec9bfbc strncpy +EXPORT_SYMBOL vmlinux 0x7ee91c1d _spin_trylock +EXPORT_SYMBOL vmlinux 0x7efbe560 per_cpu__cpu_core_map +EXPORT_SYMBOL vmlinux 0x7f0f15b5 vfs_statfs +EXPORT_SYMBOL vmlinux 0x7f24de73 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x7f32d10b pci_get_bus_and_slot +EXPORT_SYMBOL vmlinux 0x7f37467a clip_tbl_hook +EXPORT_SYMBOL vmlinux 0x7f5db472 pci_fixup_device +EXPORT_SYMBOL vmlinux 0x7f6c369c vfs_create +EXPORT_SYMBOL vmlinux 0x7f8723bd pcie_mch_quirk +EXPORT_SYMBOL vmlinux 0x7fb1b4ba __break_lease +EXPORT_SYMBOL vmlinux 0x7fc2d4b1 unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0x7fd555d6 sock_rfree +EXPORT_SYMBOL vmlinux 0x802b909f simple_rename +EXPORT_SYMBOL vmlinux 0x8032c4a2 __module_put_and_exit +EXPORT_SYMBOL vmlinux 0x8071959b con_is_bound +EXPORT_SYMBOL vmlinux 0x80ac1460 file_update_time +EXPORT_SYMBOL vmlinux 0x80c0de6f kernel_sendpage +EXPORT_SYMBOL vmlinux 0x81114f3b kill_pgrp +EXPORT_SYMBOL vmlinux 0x81472677 acpi_get_table +EXPORT_SYMBOL vmlinux 0x814c8ac8 __grab_cache_page +EXPORT_SYMBOL vmlinux 0x814e7730 nf_ct_destroy +EXPORT_SYMBOL vmlinux 0x815b5dd4 match_octal +EXPORT_SYMBOL vmlinux 0x815f2897 empty_zero_page +EXPORT_SYMBOL vmlinux 0x816494b1 seq_release_private +EXPORT_SYMBOL vmlinux 0x8173dcc5 is_container_init +EXPORT_SYMBOL vmlinux 0x8193ab31 bio_copy_kern +EXPORT_SYMBOL vmlinux 0x8193e36c call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x81a7f431 seq_open_private +EXPORT_SYMBOL vmlinux 0x81b7fbe6 ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0x81e6b37f dmi_get_system_info +EXPORT_SYMBOL vmlinux 0x81eaaa73 block_truncate_page +EXPORT_SYMBOL vmlinux 0x82072614 tasklet_kill +EXPORT_SYMBOL vmlinux 0x820d225f print_mac +EXPORT_SYMBOL vmlinux 0x82479ccb nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x8251bc21 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x8251bcc3 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x825a5b55 unregister_8022_client +EXPORT_SYMBOL vmlinux 0x825f0ccf sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x828261fe buffer_migrate_page +EXPORT_SYMBOL vmlinux 0x82b40820 swiotlb_unmap_sg_attrs +EXPORT_SYMBOL vmlinux 0x82e9c083 csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x8317e20a completion_done +EXPORT_SYMBOL vmlinux 0x8363c3d4 smp_call_function_mask +EXPORT_SYMBOL vmlinux 0x8373e6eb sg_miter_start +EXPORT_SYMBOL vmlinux 0x83800bfa kref_init +EXPORT_SYMBOL vmlinux 0x83a476ce bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x83b3425c wireless_send_event +EXPORT_SYMBOL vmlinux 0x83d2d1e2 idr_init +EXPORT_SYMBOL vmlinux 0x83d3193c page_follow_link_light +EXPORT_SYMBOL vmlinux 0x84005c54 pcim_iounmap_regions +EXPORT_SYMBOL vmlinux 0x840a8858 unregister_console +EXPORT_SYMBOL vmlinux 0x845d2b15 mpage_readpage +EXPORT_SYMBOL vmlinux 0x848d208d xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x84a513a2 inet_stream_connect +EXPORT_SYMBOL vmlinux 0x84aa9d21 tcf_em_tree_dump +EXPORT_SYMBOL vmlinux 0x84c43444 find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0x84d7f055 gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x84f822ff xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0x85670f1d rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x8570c8bf bio_integrity_enabled +EXPORT_SYMBOL vmlinux 0x85a60da9 inet_add_protocol +EXPORT_SYMBOL vmlinux 0x85abc85f strncmp +EXPORT_SYMBOL vmlinux 0x85b8d6c9 blk_insert_request +EXPORT_SYMBOL vmlinux 0x85dcab62 ___pskb_trim +EXPORT_SYMBOL vmlinux 0x85df9b6c strsep +EXPORT_SYMBOL vmlinux 0x85f116c7 udp_ioctl +EXPORT_SYMBOL vmlinux 0x8631f188 radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0x8636aa3a acpi_lock_battery_dir +EXPORT_SYMBOL vmlinux 0x863cb91a utf8_wcstombs +EXPORT_SYMBOL vmlinux 0x865e579c udplite_prot +EXPORT_SYMBOL vmlinux 0x8660b36c pagecache_write_begin +EXPORT_SYMBOL vmlinux 0x8661ce80 bio_integrity_endio +EXPORT_SYMBOL vmlinux 0x8664f62e cpufreq_update_policy +EXPORT_SYMBOL vmlinux 0x866fd903 nobh_write_end +EXPORT_SYMBOL vmlinux 0x86713cd3 keyring_clear +EXPORT_SYMBOL vmlinux 0x86730307 idr_get_new +EXPORT_SYMBOL vmlinux 0x868acba5 get_options +EXPORT_SYMBOL vmlinux 0x86af09d2 poll_freewait +EXPORT_SYMBOL vmlinux 0x86b48a77 page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0x86b9ed11 __scm_destroy +EXPORT_SYMBOL vmlinux 0x86d89bb7 del_gendisk +EXPORT_SYMBOL vmlinux 0x86de0e05 nf_unregister_hooks +EXPORT_SYMBOL vmlinux 0x86f62caf page_readlink +EXPORT_SYMBOL vmlinux 0x86fb9b05 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x8733e9a3 sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x87428312 elv_add_request +EXPORT_SYMBOL vmlinux 0x876dafc3 ec_write +EXPORT_SYMBOL vmlinux 0x8785725d param_set_charp +EXPORT_SYMBOL vmlinux 0x878615a0 swiotlb_map_sg +EXPORT_SYMBOL vmlinux 0x878ab3ce sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x878f5820 netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0x879065a7 skb_push +EXPORT_SYMBOL vmlinux 0x8794e0ce __devm_release_region +EXPORT_SYMBOL vmlinux 0x87a69bdc cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0x87d4017e module_refcount +EXPORT_SYMBOL vmlinux 0x87de107d tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x881039d0 zlib_inflate +EXPORT_SYMBOL vmlinux 0x8814d07c agp_generic_mask_memory +EXPORT_SYMBOL vmlinux 0x88158d39 f_setown +EXPORT_SYMBOL vmlinux 0x8830ed3f dma_async_memcpy_buf_to_pg +EXPORT_SYMBOL vmlinux 0x883346a5 blk_verify_command +EXPORT_SYMBOL vmlinux 0x883ac942 dev_get_by_name +EXPORT_SYMBOL vmlinux 0x8850fd31 devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0x886ea253 swiotlb_alloc_coherent +EXPORT_SYMBOL vmlinux 0x8882a9bf dcache_dir_open +EXPORT_SYMBOL vmlinux 0x88987949 call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0x88b1fad2 audit_log_format +EXPORT_SYMBOL vmlinux 0x891debfe __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x892b26a0 set_memory_nx +EXPORT_SYMBOL vmlinux 0x8934cf1f sock_wake_async +EXPORT_SYMBOL vmlinux 0x8953bb27 del_timer +EXPORT_SYMBOL vmlinux 0x897473df mktime +EXPORT_SYMBOL vmlinux 0x898b1fec mutex_trylock +EXPORT_SYMBOL vmlinux 0x898bd037 vfs_unlink +EXPORT_SYMBOL vmlinux 0x89949018 down_timeout +EXPORT_SYMBOL vmlinux 0x89d5538d fb_pad_aligned_buffer +EXPORT_SYMBOL vmlinux 0x89d66811 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x8a2cb1c7 d_invalidate +EXPORT_SYMBOL vmlinux 0x8a2f1c85 skb_seq_read +EXPORT_SYMBOL vmlinux 0x8a3eabf0 __wait_on_bit +EXPORT_SYMBOL vmlinux 0x8a44f4b4 __vlan_hwaccel_rx +EXPORT_SYMBOL vmlinux 0x8a6a8448 register_snap_client +EXPORT_SYMBOL vmlinux 0x8a7ae42b vfs_path_lookup +EXPORT_SYMBOL vmlinux 0x8a7d1c31 high_memory +EXPORT_SYMBOL vmlinux 0x8a90d932 allocate_resource +EXPORT_SYMBOL vmlinux 0x8a99a016 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x8aaf8654 mutex_lock +EXPORT_SYMBOL vmlinux 0x8ac40297 iommu_area_free +EXPORT_SYMBOL vmlinux 0x8ae787b3 mapping_tagged +EXPORT_SYMBOL vmlinux 0x8af8cada truncate_inode_pages +EXPORT_SYMBOL vmlinux 0x8b04bd64 ip_ct_attach +EXPORT_SYMBOL vmlinux 0x8b1b27c3 send_sig +EXPORT_SYMBOL vmlinux 0x8b35e873 sg_last +EXPORT_SYMBOL vmlinux 0x8b3ca835 cpu_present_map +EXPORT_SYMBOL vmlinux 0x8b409b40 vfs_write +EXPORT_SYMBOL vmlinux 0x8b50bd1c udp_memory_allocated +EXPORT_SYMBOL vmlinux 0x8b618d08 overflowuid +EXPORT_SYMBOL vmlinux 0x8b64d28b tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0x8b6a8e48 fput +EXPORT_SYMBOL vmlinux 0x8b78435f ida_remove +EXPORT_SYMBOL vmlinux 0x8b7fe311 kmemdup +EXPORT_SYMBOL vmlinux 0x8b922c0f __strnlen_user +EXPORT_SYMBOL vmlinux 0x8b966b63 sn_rtc_cycles_per_second +EXPORT_SYMBOL vmlinux 0x8b989cf9 acpi_bus_can_wakeup +EXPORT_SYMBOL vmlinux 0x8bae864c sock_no_bind +EXPORT_SYMBOL vmlinux 0x8bb33e7d __release_region +EXPORT_SYMBOL vmlinux 0x8bb7bbf5 create_proc_entry +EXPORT_SYMBOL vmlinux 0x8c183cbe iowrite16 +EXPORT_SYMBOL vmlinux 0x8c4d4549 sk_free +EXPORT_SYMBOL vmlinux 0x8c5a89bf netlink_unicast +EXPORT_SYMBOL vmlinux 0x8c7a7214 neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0x8cc79cab iowrite16_rep +EXPORT_SYMBOL vmlinux 0x8cd5c450 inode_double_lock +EXPORT_SYMBOL vmlinux 0x8cfbf01d __brelse +EXPORT_SYMBOL vmlinux 0x8d1c903f nf_register_sockopt +EXPORT_SYMBOL vmlinux 0x8d277f07 netpoll_parse_options +EXPORT_SYMBOL vmlinux 0x8d3894f2 _ctype +EXPORT_SYMBOL vmlinux 0x8d551bef sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x8d5adba2 generic_osync_inode +EXPORT_SYMBOL vmlinux 0x8d80fcb1 alloc_trdev +EXPORT_SYMBOL vmlinux 0x8d85bf61 ip_nat_decode_session +EXPORT_SYMBOL vmlinux 0x8d8d96c6 acpi_get_sleep_type_data +EXPORT_SYMBOL vmlinux 0x8d90ba67 skb_find_text +EXPORT_SYMBOL vmlinux 0x8dd61b71 inet_select_addr +EXPORT_SYMBOL vmlinux 0x8dece091 read_cache_page_async +EXPORT_SYMBOL vmlinux 0x8e002cda acpi_remove_gpe_block +EXPORT_SYMBOL vmlinux 0x8e0637ba i8253_lock +EXPORT_SYMBOL vmlinux 0x8e0b7743 ipv6_ext_hdr +EXPORT_SYMBOL vmlinux 0x8e1855e5 pci_find_bus +EXPORT_SYMBOL vmlinux 0x8e3c9cc3 vprintk +EXPORT_SYMBOL vmlinux 0x8e45732c unregister_quota_format +EXPORT_SYMBOL vmlinux 0x8e6fe131 unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0x8e725985 nf_log_unregister_pf +EXPORT_SYMBOL vmlinux 0x8e78393d uart_get_divisor +EXPORT_SYMBOL vmlinux 0x8e90a388 genl_unregister_ops +EXPORT_SYMBOL vmlinux 0x8ea74ad0 pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x8ee61ef0 cpufreq_gov_performance +EXPORT_SYMBOL vmlinux 0x8f00eafe xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0x8f0f29e2 try_to_release_page +EXPORT_SYMBOL vmlinux 0x8f20d4fc dev_load +EXPORT_SYMBOL vmlinux 0x8f39f14b dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0x8f65041e compat_tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x8f6b7950 set_irq_data +EXPORT_SYMBOL vmlinux 0x8f9083d0 d_delete +EXPORT_SYMBOL vmlinux 0x8f9c199c __get_user_2 +EXPORT_SYMBOL vmlinux 0x8fda3d08 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0x8ff999d1 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0x90022b44 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x90035333 secure_tcpv6_sequence_number +EXPORT_SYMBOL vmlinux 0x9028bc52 serio_close +EXPORT_SYMBOL vmlinux 0x903f4949 sock_i_ino +EXPORT_SYMBOL vmlinux 0x904b213c simple_statfs +EXPORT_SYMBOL vmlinux 0x904c118b tcf_hash_create +EXPORT_SYMBOL vmlinux 0x9070b3f2 ioport_resource +EXPORT_SYMBOL vmlinux 0x9086ea4f simple_fill_super +EXPORT_SYMBOL vmlinux 0x90a943ba nmi_active +EXPORT_SYMBOL vmlinux 0x90ac0a02 unregister_netdev +EXPORT_SYMBOL vmlinux 0x90cfcd66 fget +EXPORT_SYMBOL vmlinux 0x90fa0830 generic_listxattr +EXPORT_SYMBOL vmlinux 0x9144a8e2 ec_burst_disable +EXPORT_SYMBOL vmlinux 0x91481982 __ratelimit +EXPORT_SYMBOL vmlinux 0x91607d95 set_memory_wb +EXPORT_SYMBOL vmlinux 0x918682e2 iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0x91906b9b d_alloc_name +EXPORT_SYMBOL vmlinux 0x91bd49a0 tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0x91ca8959 acpi_get_register +EXPORT_SYMBOL vmlinux 0x91cc2fe8 setup_arg_pages +EXPORT_SYMBOL vmlinux 0x91d180d4 blk_queue_make_request +EXPORT_SYMBOL vmlinux 0x91e0d14a xfrm_init_state +EXPORT_SYMBOL vmlinux 0x9206ff46 kernel_getpeername +EXPORT_SYMBOL vmlinux 0x9212a1d7 pcix_get_max_mmrbc +EXPORT_SYMBOL vmlinux 0x9215b107 generic_setxattr +EXPORT_SYMBOL vmlinux 0x9217d3c6 dump_trace +EXPORT_SYMBOL vmlinux 0x92392cd9 iov_shorten +EXPORT_SYMBOL vmlinux 0x925e802c tcp_v4_md5_lookup +EXPORT_SYMBOL vmlinux 0x92694346 nla_append +EXPORT_SYMBOL vmlinux 0x9272e6c9 vfs_readdir +EXPORT_SYMBOL vmlinux 0x927e989f gen_pool_alloc +EXPORT_SYMBOL vmlinux 0x92bf8b77 dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x92c3b20e sync_page_range +EXPORT_SYMBOL vmlinux 0x92ea4ae4 crc32_le +EXPORT_SYMBOL vmlinux 0x92ec8c1d add_disk +EXPORT_SYMBOL vmlinux 0x92fe4055 pci_release_selected_regions +EXPORT_SYMBOL vmlinux 0x93056f39 pci_bus_add_devices +EXPORT_SYMBOL vmlinux 0x9305f8e6 cpufreq_get +EXPORT_SYMBOL vmlinux 0x930ca954 serio_interrupt +EXPORT_SYMBOL vmlinux 0x9321ce16 netpoll_send_udp +EXPORT_SYMBOL vmlinux 0x93a6e0b2 io_schedule +EXPORT_SYMBOL vmlinux 0x93ab4a28 cancel_dirty_page +EXPORT_SYMBOL vmlinux 0x93afa72e vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x93b8ef56 mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0x93c69acf param_set_byte +EXPORT_SYMBOL vmlinux 0x93c8df0a udp_prot +EXPORT_SYMBOL vmlinux 0x93cbd1ec _spin_lock_bh +EXPORT_SYMBOL vmlinux 0x93e06b54 set_binfmt +EXPORT_SYMBOL vmlinux 0x93fca811 __get_free_pages +EXPORT_SYMBOL vmlinux 0x94039590 simple_link +EXPORT_SYMBOL vmlinux 0x940ec91b textsearch_register +EXPORT_SYMBOL vmlinux 0x9425b596 block_commit_write +EXPORT_SYMBOL vmlinux 0x943a1a54 unbind_con_driver +EXPORT_SYMBOL vmlinux 0x9450108b bio_map_user +EXPORT_SYMBOL vmlinux 0x945bc6a7 copy_from_user +EXPORT_SYMBOL vmlinux 0x94883ab2 gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0x94961283 vunmap +EXPORT_SYMBOL vmlinux 0x94ae5f25 __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0x94b7d9bb nf_log_register +EXPORT_SYMBOL vmlinux 0x94be63db cdev_del +EXPORT_SYMBOL vmlinux 0x94cabdfe pci_get_class +EXPORT_SYMBOL vmlinux 0x94e39d40 lookup_bdev +EXPORT_SYMBOL vmlinux 0x94fcf08e bioset_create +EXPORT_SYMBOL vmlinux 0x9502843e dev_get_flags +EXPORT_SYMBOL vmlinux 0x950cd5e6 find_lock_page +EXPORT_SYMBOL vmlinux 0x954488a4 syncookie_secret +EXPORT_SYMBOL vmlinux 0x9545af6d tasklet_init +EXPORT_SYMBOL vmlinux 0x95477ba0 ps2_cmd_aborted +EXPORT_SYMBOL vmlinux 0x954cbb26 vsprintf +EXPORT_SYMBOL vmlinux 0x95ba1d86 thermal_zone_unbind_cooling_device +EXPORT_SYMBOL vmlinux 0x95ceb864 key_update +EXPORT_SYMBOL vmlinux 0x95d7bcf8 blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x95dd999a gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0x960f28a5 tty_register_driver +EXPORT_SYMBOL vmlinux 0x961d724a unregister_netdevice +EXPORT_SYMBOL vmlinux 0x963bb6a1 pci_set_master +EXPORT_SYMBOL vmlinux 0x96481cc7 per_cpu__x86_cpu_to_apicid +EXPORT_SYMBOL vmlinux 0x96487928 fb_get_buffer_offset +EXPORT_SYMBOL vmlinux 0x96747a0d have_submounts +EXPORT_SYMBOL vmlinux 0x96768064 ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0x9696d326 unregister_nls +EXPORT_SYMBOL vmlinux 0x96f33400 up_read +EXPORT_SYMBOL vmlinux 0x972fdec1 serial8250_register_port +EXPORT_SYMBOL vmlinux 0x973873ab _spin_lock +EXPORT_SYMBOL vmlinux 0x9754ec10 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x97699985 blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x97861e40 ethtool_op_get_tx_csum +EXPORT_SYMBOL vmlinux 0x97de0ddd acpi_install_gpe_block +EXPORT_SYMBOL vmlinux 0x980a0cad dma_sync_wait +EXPORT_SYMBOL vmlinux 0x980b88a9 iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0x980faed4 vmap +EXPORT_SYMBOL vmlinux 0x98126584 remove_proc_entry +EXPORT_SYMBOL vmlinux 0x983a7e66 generic_writepages +EXPORT_SYMBOL vmlinux 0x9864c1a6 idr_find +EXPORT_SYMBOL vmlinux 0x986e6135 fb_pad_unaligned_buffer +EXPORT_SYMBOL vmlinux 0x988ed85d set_memory_x +EXPORT_SYMBOL vmlinux 0x9893b195 sock_kmalloc +EXPORT_SYMBOL vmlinux 0x98afdeed llc_sap_close +EXPORT_SYMBOL vmlinux 0x997b86d6 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x9994c0ca ps2_is_keyboard_id +EXPORT_SYMBOL vmlinux 0x999e8297 vfree +EXPORT_SYMBOL vmlinux 0x99aadb21 param_get_ulong +EXPORT_SYMBOL vmlinux 0x99bfbe39 get_unused_fd +EXPORT_SYMBOL vmlinux 0x99cdc86b sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x99d87919 security_sb_set_mnt_opts +EXPORT_SYMBOL vmlinux 0x99e8e8af names_cachep +EXPORT_SYMBOL vmlinux 0x99ea12ce panic_blink +EXPORT_SYMBOL vmlinux 0x9a1dfd65 strpbrk +EXPORT_SYMBOL vmlinux 0x9a21b6be zero_fill_bio +EXPORT_SYMBOL vmlinux 0x9a57977b elevator_exit +EXPORT_SYMBOL vmlinux 0x9a58e3c2 pci_set_mwi +EXPORT_SYMBOL vmlinux 0x9a9985be percpu_counter_destroy +EXPORT_SYMBOL vmlinux 0x9ae280a8 blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0x9b388444 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x9b5abb9f xfrm_lookup +EXPORT_SYMBOL vmlinux 0x9b6408d6 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0x9b815a18 mod_zone_page_state +EXPORT_SYMBOL vmlinux 0x9b8fcd82 cont_write_begin +EXPORT_SYMBOL vmlinux 0x9b97745c mnt_pin +EXPORT_SYMBOL vmlinux 0x9ba7089d argv_split +EXPORT_SYMBOL vmlinux 0x9bb58b22 inet_addr_type +EXPORT_SYMBOL vmlinux 0x9bc565c5 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x9bf5cd88 sock_create_lite +EXPORT_SYMBOL vmlinux 0x9c012508 fb_parse_edid +EXPORT_SYMBOL vmlinux 0x9c0ea3cd memscan +EXPORT_SYMBOL vmlinux 0x9c17c94a udp_proc_register +EXPORT_SYMBOL vmlinux 0x9c395b38 tcf_generic_walker +EXPORT_SYMBOL vmlinux 0x9c3c13c6 do_sync_read +EXPORT_SYMBOL vmlinux 0x9c491f60 sg_alloc_table +EXPORT_SYMBOL vmlinux 0x9c55ed15 tcp_md5_hash_header +EXPORT_SYMBOL vmlinux 0x9c8e2966 mem_section +EXPORT_SYMBOL vmlinux 0x9ca95a0e sort +EXPORT_SYMBOL vmlinux 0x9cb96e92 qdisc_put_rtab +EXPORT_SYMBOL vmlinux 0x9cc6f545 flush_signals +EXPORT_SYMBOL vmlinux 0x9ccb2622 finish_wait +EXPORT_SYMBOL vmlinux 0x9ccf93a0 tcp_hashinfo +EXPORT_SYMBOL vmlinux 0x9ce5afa9 mpage_readpages +EXPORT_SYMBOL vmlinux 0x9ced38aa down_trylock +EXPORT_SYMBOL vmlinux 0x9ced7f1c ip_xfrm_me_harder +EXPORT_SYMBOL vmlinux 0x9cf7bac0 km_policy_expired +EXPORT_SYMBOL vmlinux 0x9d328aa0 free_netdev +EXPORT_SYMBOL vmlinux 0x9d33ef5e acpi_enable +EXPORT_SYMBOL vmlinux 0x9d3741aa filemap_fdatawait +EXPORT_SYMBOL vmlinux 0x9d57084d nf_reinject +EXPORT_SYMBOL vmlinux 0x9d69a91b tcf_action_dump_1 +EXPORT_SYMBOL vmlinux 0x9d711f1f percpu_counter_init +EXPORT_SYMBOL vmlinux 0x9d96246f neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x9d9e5add elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0x9db04cdb elv_dequeue_request +EXPORT_SYMBOL vmlinux 0x9db21624 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x9dd299bf pneigh_enqueue +EXPORT_SYMBOL vmlinux 0x9e1c6037 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0x9e329281 bio_integrity_free +EXPORT_SYMBOL vmlinux 0x9e535888 acpi_get_physical_device +EXPORT_SYMBOL vmlinux 0x9e6201db idr_remove +EXPORT_SYMBOL vmlinux 0x9e64fbfe rtc_cmos_read +EXPORT_SYMBOL vmlinux 0x9e7d6bd0 __udelay +EXPORT_SYMBOL vmlinux 0x9e9426c0 sock_no_accept +EXPORT_SYMBOL vmlinux 0x9ea0ad49 __sg_free_table +EXPORT_SYMBOL vmlinux 0x9ea28ec7 acpi_evaluate_object +EXPORT_SYMBOL vmlinux 0x9edbecae snprintf +EXPORT_SYMBOL vmlinux 0x9eecde16 do_brk +EXPORT_SYMBOL vmlinux 0x9ef452c0 ipv4_specific +EXPORT_SYMBOL vmlinux 0x9ef749e2 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x9f0b3309 elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0x9f100139 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x9f2bdaac __bitmap_or +EXPORT_SYMBOL vmlinux 0x9f6b6587 inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0x9f984513 strrchr +EXPORT_SYMBOL vmlinux 0x9fa274b4 dq_data_lock +EXPORT_SYMBOL vmlinux 0x9fd779e3 udp_poll +EXPORT_SYMBOL vmlinux 0x9fde60f0 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x9feaf287 sonet_subtract_stats +EXPORT_SYMBOL vmlinux 0xa00554c4 d_rehash +EXPORT_SYMBOL vmlinux 0xa0139c09 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0xa01dbff6 user_path_at +EXPORT_SYMBOL vmlinux 0xa03523d5 security_unix_stream_connect +EXPORT_SYMBOL vmlinux 0xa04a01bd qdisc_class_hash_insert +EXPORT_SYMBOL vmlinux 0xa05c03df mempool_kmalloc +EXPORT_SYMBOL vmlinux 0xa0605033 get_sb_single +EXPORT_SYMBOL vmlinux 0xa0965fe2 unload_nls +EXPORT_SYMBOL vmlinux 0xa09ff7b3 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0xa0b04675 vmalloc_32 +EXPORT_SYMBOL vmlinux 0xa0ceef51 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0xa0cf56e0 ida_pre_get +EXPORT_SYMBOL vmlinux 0xa0fbac79 wake_up_bit +EXPORT_SYMBOL vmlinux 0xa0fd9496 kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0xa108eb4d sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0xa120d33c tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0xa13798f8 printk_ratelimit +EXPORT_SYMBOL vmlinux 0xa13c0faf nla_reserve +EXPORT_SYMBOL vmlinux 0xa1b759ce fb_add_videomode +EXPORT_SYMBOL vmlinux 0xa1c76e0a _cond_resched +EXPORT_SYMBOL vmlinux 0xa1d013fe skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0xa1ecf921 kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0xa20abf2f find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0xa20ce1b8 net_msg_warn +EXPORT_SYMBOL vmlinux 0xa216d1b2 blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0xa23ac2f9 register_sysrq_key +EXPORT_SYMBOL vmlinux 0xa25b79aa xfrm_state_delete +EXPORT_SYMBOL vmlinux 0xa26d33a7 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0xa28056f5 ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0xa2a1e5c9 _write_lock_bh +EXPORT_SYMBOL vmlinux 0xa2a5fd77 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0xa2da39ac ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0xa2ead877 uart_add_one_port +EXPORT_SYMBOL vmlinux 0xa30904a3 uart_register_driver +EXPORT_SYMBOL vmlinux 0xa31f172d __copy_from_user_inatomic +EXPORT_SYMBOL vmlinux 0xa329d77b unregister_binfmt +EXPORT_SYMBOL vmlinux 0xa329f07e register_shrinker +EXPORT_SYMBOL vmlinux 0xa33f7c7c nla_strlcpy +EXPORT_SYMBOL vmlinux 0xa3420d61 __percpu_counter_sum +EXPORT_SYMBOL vmlinux 0xa35de80f ipv4_config +EXPORT_SYMBOL vmlinux 0xa37f26bd ip_mc_join_group +EXPORT_SYMBOL vmlinux 0xa3a5be95 memmove +EXPORT_SYMBOL vmlinux 0xa3aa23b3 invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0xa3b7fd8b blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0xa3bbcd80 acpi_set_gpe_type +EXPORT_SYMBOL vmlinux 0xa4366b2e find_get_pages_tag +EXPORT_SYMBOL vmlinux 0xa44072fc posix_acl_alloc +EXPORT_SYMBOL vmlinux 0xa44ad274 wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0xa4501cd1 pnp_request_card_device +EXPORT_SYMBOL vmlinux 0xa47635df redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0xa4b94fea iowrite8_rep +EXPORT_SYMBOL vmlinux 0xa4cd897e force_sig +EXPORT_SYMBOL vmlinux 0xa4d4f0e6 global_cache_flush +EXPORT_SYMBOL vmlinux 0xa4df1151 kref_set +EXPORT_SYMBOL vmlinux 0xa4f46824 con_copy_unimap +EXPORT_SYMBOL vmlinux 0xa4f51e82 __invalidate_device +EXPORT_SYMBOL vmlinux 0xa519b3c1 input_unregister_handler +EXPORT_SYMBOL vmlinux 0xa5240753 __lock_buffer +EXPORT_SYMBOL vmlinux 0xa5423cc4 param_get_int +EXPORT_SYMBOL vmlinux 0xa548fbdc blk_init_queue +EXPORT_SYMBOL vmlinux 0xa5693df7 posix_acl_clone +EXPORT_SYMBOL vmlinux 0xa56f1315 mempool_free +EXPORT_SYMBOL vmlinux 0xa57064d0 iunique +EXPORT_SYMBOL vmlinux 0xa58b6804 nla_parse +EXPORT_SYMBOL vmlinux 0xa5922bb1 kfifo_init +EXPORT_SYMBOL vmlinux 0xa598e29c vesa_modes +EXPORT_SYMBOL vmlinux 0xa5a10753 __lock_page +EXPORT_SYMBOL vmlinux 0xa5a161cd tcp_sendmsg +EXPORT_SYMBOL vmlinux 0xa5a905c8 elv_rb_former_request +EXPORT_SYMBOL vmlinux 0xa5af8af3 blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0xa6040c0c __serio_register_driver +EXPORT_SYMBOL vmlinux 0xa605cb35 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0xa63ab9b8 fb_get_mode +EXPORT_SYMBOL vmlinux 0xa68124fa hweight8 +EXPORT_SYMBOL vmlinux 0xa681fe88 generate_random_uuid +EXPORT_SYMBOL vmlinux 0xa699db51 pci_bus_read_config_dword +EXPORT_SYMBOL vmlinux 0xa6c16c21 inet_sendmsg +EXPORT_SYMBOL vmlinux 0xa6d3873e pci_get_device +EXPORT_SYMBOL vmlinux 0xa6dcc773 rb_insert_color +EXPORT_SYMBOL vmlinux 0xa6f1591a skb_checksum +EXPORT_SYMBOL vmlinux 0xa70fabbe release_evntsel_nmi +EXPORT_SYMBOL vmlinux 0xa744d533 agp_find_bridge +EXPORT_SYMBOL vmlinux 0xa7502f48 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0xa77b1e2c unregister_exec_domain +EXPORT_SYMBOL vmlinux 0xa7944385 sk_stream_error +EXPORT_SYMBOL vmlinux 0xa7c35c6b getnstimeofday +EXPORT_SYMBOL vmlinux 0xa7c391c9 nf_register_hook +EXPORT_SYMBOL vmlinux 0xa7cba39d bio_integrity_set_tag +EXPORT_SYMBOL vmlinux 0xa7e85708 inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0xa816c525 schedule_work_on +EXPORT_SYMBOL vmlinux 0xa822dae7 down_read +EXPORT_SYMBOL vmlinux 0xa82e5551 ip_getsockopt +EXPORT_SYMBOL vmlinux 0xa876ab52 pci_bus_write_config_byte +EXPORT_SYMBOL vmlinux 0xa886a958 krealloc +EXPORT_SYMBOL vmlinux 0xa89e7ea9 ip_dev_find +EXPORT_SYMBOL vmlinux 0xa89f085a __kill_fasync +EXPORT_SYMBOL vmlinux 0xa8ba38e0 blkdev_put +EXPORT_SYMBOL vmlinux 0xa8c7574d arch_debugfs_dir +EXPORT_SYMBOL vmlinux 0xa8ec460f __nla_reserve +EXPORT_SYMBOL vmlinux 0xa8f102af thermal_cooling_device_register +EXPORT_SYMBOL vmlinux 0xa8fef7bb security_unix_may_send +EXPORT_SYMBOL vmlinux 0xa907b898 bio_integrity_alloc +EXPORT_SYMBOL vmlinux 0xa925899a param_set_bool +EXPORT_SYMBOL vmlinux 0xa9780166 input_unregister_device +EXPORT_SYMBOL vmlinux 0xa9a4fa29 unregister_snap_client +EXPORT_SYMBOL vmlinux 0xa9be76e8 clocksource_register +EXPORT_SYMBOL vmlinux 0xa9d4832a close_bdev_excl +EXPORT_SYMBOL vmlinux 0xa9d943dd fb_find_mode +EXPORT_SYMBOL vmlinux 0xa9daa720 init_task +EXPORT_SYMBOL vmlinux 0xa9fcf31d wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0xaa024146 sonet_copy_stats +EXPORT_SYMBOL vmlinux 0xaa110fd6 simple_set_mnt +EXPORT_SYMBOL vmlinux 0xaa3bb13d sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0xaa84a8ae acpi_processor_power_init_bm_check +EXPORT_SYMBOL vmlinux 0xaa932ac5 tcp_check_req +EXPORT_SYMBOL vmlinux 0xaa9a5fce xfrm4_rcv +EXPORT_SYMBOL vmlinux 0xaab06af8 _write_lock_irqsave +EXPORT_SYMBOL vmlinux 0xaad76f42 kthread_bind +EXPORT_SYMBOL vmlinux 0xaae80a67 xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0xaae8ab0e acpi_bus_power_manageable +EXPORT_SYMBOL vmlinux 0xaafdc258 strcasecmp +EXPORT_SYMBOL vmlinux 0xaaffb9a5 acpi_bus_private_data_handler +EXPORT_SYMBOL vmlinux 0xab06fc26 proc_mkdir +EXPORT_SYMBOL vmlinux 0xab39e129 inode_setattr +EXPORT_SYMBOL vmlinux 0xab3e615c __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0xab471003 param_array_set +EXPORT_SYMBOL vmlinux 0xab565120 devm_ioport_map +EXPORT_SYMBOL vmlinux 0xab600421 probe_irq_off +EXPORT_SYMBOL vmlinux 0xab65ed80 set_memory_uc +EXPORT_SYMBOL vmlinux 0xabccf7af tcp_make_synack +EXPORT_SYMBOL vmlinux 0xabcd913c tcp_connect +EXPORT_SYMBOL vmlinux 0xabd0b574 path_put +EXPORT_SYMBOL vmlinux 0xabd0c91c rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0xabf2078d ll_rw_block +EXPORT_SYMBOL vmlinux 0xac07c4a6 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0xac0bbfa8 _proxy_pda +EXPORT_SYMBOL vmlinux 0xac0f51a1 lock_super +EXPORT_SYMBOL vmlinux 0xac189757 blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0xac2c5047 blk_execute_rq +EXPORT_SYMBOL vmlinux 0xac383451 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0xac3b3cee __bitmap_and +EXPORT_SYMBOL vmlinux 0xac5709f7 per_cpu__x86_cpu_to_node_map +EXPORT_SYMBOL vmlinux 0xac58ea5e acpi_unload_table_id +EXPORT_SYMBOL vmlinux 0xac6606fb inode_get_bytes +EXPORT_SYMBOL vmlinux 0xacb5a561 iget_failed +EXPORT_SYMBOL vmlinux 0xacc6e252 copy_strings_kernel +EXPORT_SYMBOL vmlinux 0xaccabc6a in4_pton +EXPORT_SYMBOL vmlinux 0xacd65f4c simple_unlink +EXPORT_SYMBOL vmlinux 0xace26990 __bread +EXPORT_SYMBOL vmlinux 0xacf16ca2 agp_generic_alloc_user +EXPORT_SYMBOL vmlinux 0xacf4d843 match_strdup +EXPORT_SYMBOL vmlinux 0xacf8525f bd_release +EXPORT_SYMBOL vmlinux 0xad0413d4 match_hex +EXPORT_SYMBOL vmlinux 0xad07fcc5 __first_cpu +EXPORT_SYMBOL vmlinux 0xad127ef4 serio_rescan +EXPORT_SYMBOL vmlinux 0xad13c689 acpi_os_execute +EXPORT_SYMBOL vmlinux 0xad248fbf __dev_remove_pack +EXPORT_SYMBOL vmlinux 0xad25fb12 __memcpy +EXPORT_SYMBOL vmlinux 0xad4582bb xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0xad4a5208 send_sig_info +EXPORT_SYMBOL vmlinux 0xad5c09d2 wake_up_process +EXPORT_SYMBOL vmlinux 0xad74c46b scm_fp_dup +EXPORT_SYMBOL vmlinux 0xad8de1b3 acpi_remove_address_space_handler +EXPORT_SYMBOL vmlinux 0xada00a91 skb_insert +EXPORT_SYMBOL vmlinux 0xadaa2657 cpufreq_register_notifier +EXPORT_SYMBOL vmlinux 0xadb3cf5d neigh_ifdown +EXPORT_SYMBOL vmlinux 0xae0fb495 blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0xae14b37d register_exec_domain +EXPORT_SYMBOL vmlinux 0xae1548b4 swiotlb_unmap_sg +EXPORT_SYMBOL vmlinux 0xae49b2ab dquot_transfer +EXPORT_SYMBOL vmlinux 0xae844307 register_quota_format +EXPORT_SYMBOL vmlinux 0xae966f8b __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0xae97b15a blk_rq_count_integrity_sg +EXPORT_SYMBOL vmlinux 0xaee86f84 block_read_full_page +EXPORT_SYMBOL vmlinux 0xaeedc45b __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0xaf1ce299 ip_route_output_key +EXPORT_SYMBOL vmlinux 0xaf52c2d3 iommu_bio_merge +EXPORT_SYMBOL vmlinux 0xaf5c9d5d sk_send_sigurg +EXPORT_SYMBOL vmlinux 0xafe82e10 strcspn +EXPORT_SYMBOL vmlinux 0xaff94bbb input_set_capability +EXPORT_SYMBOL vmlinux 0xaffe5af4 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0xb02da982 path_lookup +EXPORT_SYMBOL vmlinux 0xb04ea8f0 agp_rebind_memory +EXPORT_SYMBOL vmlinux 0xb07dfb3d acpi_remove_gpe_handler +EXPORT_SYMBOL vmlinux 0xb0b5fb56 __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0xb0b847ac __bitmap_full +EXPORT_SYMBOL vmlinux 0xb0bb6329 fb_validate_mode +EXPORT_SYMBOL vmlinux 0xb0c7ed2b iw_handler_set_spy +EXPORT_SYMBOL vmlinux 0xb0d731ff __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0xb0e10781 get_option +EXPORT_SYMBOL vmlinux 0xb0f4a169 nlmsg_notify +EXPORT_SYMBOL vmlinux 0xb0fbe2e9 pci_try_set_mwi +EXPORT_SYMBOL vmlinux 0xb116807f vfs_lstat +EXPORT_SYMBOL vmlinux 0xb11fa1ce strlcat +EXPORT_SYMBOL vmlinux 0xb121390a probe_irq_on +EXPORT_SYMBOL vmlinux 0xb1577f2d elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0xb1645a2e sg_free_table +EXPORT_SYMBOL vmlinux 0xb18bd0b8 mpage_writepage +EXPORT_SYMBOL vmlinux 0xb18e02c3 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0xb19760c3 bitmap_onto +EXPORT_SYMBOL vmlinux 0xb1acfd47 kset_register +EXPORT_SYMBOL vmlinux 0xb1c3a01a oops_in_progress +EXPORT_SYMBOL vmlinux 0xb1cd9d4b __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0xb1cfad22 rdmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xb1f975aa unlock_kernel +EXPORT_SYMBOL vmlinux 0xb2017c1d per_cpu__x86_bios_cpu_apicid +EXPORT_SYMBOL vmlinux 0xb21e9ddb pci_enable_device +EXPORT_SYMBOL vmlinux 0xb22f6a87 ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0xb2355823 generic_block_bmap +EXPORT_SYMBOL vmlinux 0xb24a57af mntput_no_expire +EXPORT_SYMBOL vmlinux 0xb2648962 vfs_read +EXPORT_SYMBOL vmlinux 0xb26c561d tcf_em_register +EXPORT_SYMBOL vmlinux 0xb2731886 kill_block_super +EXPORT_SYMBOL vmlinux 0xb2bd21e1 generic_file_splice_read +EXPORT_SYMBOL vmlinux 0xb2be638a dma_chan_cleanup +EXPORT_SYMBOL vmlinux 0xb2fabb8b simple_release_fs +EXPORT_SYMBOL vmlinux 0xb2fd5ceb __put_user_4 +EXPORT_SYMBOL vmlinux 0xb3205415 wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0xb3260577 skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0xb3284531 acpi_dbg_layer +EXPORT_SYMBOL vmlinux 0xb3318ded __down_read_trylock +EXPORT_SYMBOL vmlinux 0xb34d4c2e acpi_terminate +EXPORT_SYMBOL vmlinux 0xb352177e find_first_bit +EXPORT_SYMBOL vmlinux 0xb3670c96 free_buffer_head +EXPORT_SYMBOL vmlinux 0xb3692eb4 ioremap_wc +EXPORT_SYMBOL vmlinux 0xb3725096 xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0xb3766790 linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0xb3863f9b eth_header +EXPORT_SYMBOL vmlinux 0xb3950635 skb_pad +EXPORT_SYMBOL vmlinux 0xb3a307c6 si_meminfo +EXPORT_SYMBOL vmlinux 0xb3bffa55 clear_inode +EXPORT_SYMBOL vmlinux 0xb3c2cab2 __generic_unplug_device +EXPORT_SYMBOL vmlinux 0xb3d16821 __kfree_skb +EXPORT_SYMBOL vmlinux 0xb3de2b5e tcp_rcv_established +EXPORT_SYMBOL vmlinux 0xb3fee994 sock_no_getname +EXPORT_SYMBOL vmlinux 0xb3ff1f69 free_pages_exact +EXPORT_SYMBOL vmlinux 0xb401e8ab __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0xb423dba1 console_blanked +EXPORT_SYMBOL vmlinux 0xb4390f9a mcount +EXPORT_SYMBOL vmlinux 0xb43b7a5b xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0xb45b24f6 k8_nb_ids +EXPORT_SYMBOL vmlinux 0xb46b5275 netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0xb489604c may_umount +EXPORT_SYMBOL vmlinux 0xb494e82a br_fdb_put_hook +EXPORT_SYMBOL vmlinux 0xb4ca9447 __kfifo_get +EXPORT_SYMBOL vmlinux 0xb5044271 vsscanf +EXPORT_SYMBOL vmlinux 0xb51ccefa uart_update_timeout +EXPORT_SYMBOL vmlinux 0xb54533f7 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0xb56fb81d set_pages_x +EXPORT_SYMBOL vmlinux 0xb5a459dc unregister_blkdev +EXPORT_SYMBOL vmlinux 0xb5c128e2 d_instantiate +EXPORT_SYMBOL vmlinux 0xb5c7eb57 sb_min_blocksize +EXPORT_SYMBOL vmlinux 0xb5d52c27 ec_transaction +EXPORT_SYMBOL vmlinux 0xb60e34a8 nla_memcpy +EXPORT_SYMBOL vmlinux 0xb6244511 sg_init_one +EXPORT_SYMBOL vmlinux 0xb678366f int_sqrt +EXPORT_SYMBOL vmlinux 0xb6a61a86 qdisc_get_rtab +EXPORT_SYMBOL vmlinux 0xb6afca19 pneigh_lookup +EXPORT_SYMBOL vmlinux 0xb6ba8bc6 pci_select_bars +EXPORT_SYMBOL vmlinux 0xb6cbe886 acpi_get_node +EXPORT_SYMBOL vmlinux 0xb6e227aa rtc_lock +EXPORT_SYMBOL vmlinux 0xb6eca461 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0xb6eefc18 swiotlb_dma_supported +EXPORT_SYMBOL vmlinux 0xb714a981 console_print +EXPORT_SYMBOL vmlinux 0xb7414af7 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0xb7484990 dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0xb752c93f tr_type_trans +EXPORT_SYMBOL vmlinux 0xb7555f12 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0xb758b225 acpi_disable_event +EXPORT_SYMBOL vmlinux 0xb774fe07 __pagevec_release +EXPORT_SYMBOL vmlinux 0xb77d80bd tcf_unregister_action +EXPORT_SYMBOL vmlinux 0xb7907551 vfs_writev +EXPORT_SYMBOL vmlinux 0xb799f240 pagevec_lookup +EXPORT_SYMBOL vmlinux 0xb7e63bec llc_add_pack +EXPORT_SYMBOL vmlinux 0xb7e718a7 posix_unblock_lock +EXPORT_SYMBOL vmlinux 0xb7ee3f25 inet_frag_destroy +EXPORT_SYMBOL vmlinux 0xb7f762a2 follow_down +EXPORT_SYMBOL vmlinux 0xb824f854 neigh_resolve_output +EXPORT_SYMBOL vmlinux 0xb86e4ab9 random32 +EXPORT_SYMBOL vmlinux 0xb89af9bf srandom32 +EXPORT_SYMBOL vmlinux 0xb8e7ce2c __put_user_8 +EXPORT_SYMBOL vmlinux 0xb8f96a6c eth_header_parse +EXPORT_SYMBOL vmlinux 0xb93437f2 acpi_notifier_call_chain +EXPORT_SYMBOL vmlinux 0xb969b002 pfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0xb9805b0c down_read_trylock +EXPORT_SYMBOL vmlinux 0xb985a2ec dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0xb98a0185 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0xb9c74bf1 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0xb9e34f7a blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0xb9f9e613 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0xb9fd2205 add_efi_memmap +EXPORT_SYMBOL vmlinux 0xba2d8594 ec_read +EXPORT_SYMBOL vmlinux 0xba497f13 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0xba6c9c04 tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0xba9c9ab8 inet_accept +EXPORT_SYMBOL vmlinux 0xbaa2782a kstrndup +EXPORT_SYMBOL vmlinux 0xbaec9362 inet_release +EXPORT_SYMBOL vmlinux 0xbb167766 fb_var_to_videomode +EXPORT_SYMBOL vmlinux 0xbb189cad disallow_signal +EXPORT_SYMBOL vmlinux 0xbb5d343d xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0xbb656def audit_log_end +EXPORT_SYMBOL vmlinux 0xbb83bd29 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0xbbb9a03f netdev_state_change +EXPORT_SYMBOL vmlinux 0xbbc8e804 param_set_ushort +EXPORT_SYMBOL vmlinux 0xbbe10e4a fifo_create_dflt +EXPORT_SYMBOL vmlinux 0xbc0c0161 d_namespace_path +EXPORT_SYMBOL vmlinux 0xbc3a1bcb I_BDEV +EXPORT_SYMBOL vmlinux 0xbc5f5f88 vc_cons +EXPORT_SYMBOL vmlinux 0xbc64a92f find_get_page +EXPORT_SYMBOL vmlinux 0xbc958848 alloc_pages_current +EXPORT_SYMBOL vmlinux 0xbcb40125 dma_async_device_register +EXPORT_SYMBOL vmlinux 0xbcc308bb strnlen_user +EXPORT_SYMBOL vmlinux 0xbcc4c5e1 tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0xbccad5b2 tc_classify_compat +EXPORT_SYMBOL vmlinux 0xbce0cf6f fasync_helper +EXPORT_SYMBOL vmlinux 0xbce21d86 seq_open +EXPORT_SYMBOL vmlinux 0xbcf148cf inet_frag_evictor +EXPORT_SYMBOL vmlinux 0xbcf58436 nf_getsockopt +EXPORT_SYMBOL vmlinux 0xbd2c7090 kernel_read +EXPORT_SYMBOL vmlinux 0xbd402bf0 devm_free_irq +EXPORT_SYMBOL vmlinux 0xbd52ad11 inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0xbd5e09b6 proto_unregister +EXPORT_SYMBOL vmlinux 0xbd9c99cf idr_get_new_above +EXPORT_SYMBOL vmlinux 0xbda8c24d ps2_sendbyte +EXPORT_SYMBOL vmlinux 0xbdaf5b07 acpi_os_read_port +EXPORT_SYMBOL vmlinux 0xbe499d81 copy_to_user +EXPORT_SYMBOL vmlinux 0xbe4e40ae pci_match_id +EXPORT_SYMBOL vmlinux 0xbef43296 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0xbefee397 acpi_get_object_info +EXPORT_SYMBOL vmlinux 0xbf493e2b tcf_em_unregister +EXPORT_SYMBOL vmlinux 0xbf63c9e7 dmam_pool_create +EXPORT_SYMBOL vmlinux 0xbf7fd2f5 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0xbf8e6bb4 tcp_prot +EXPORT_SYMBOL vmlinux 0xbf9bcc8d __cap_empty_set +EXPORT_SYMBOL vmlinux 0xbfbe9466 dev_alloc_skb +EXPORT_SYMBOL vmlinux 0xbfc177bc iowrite32_rep +EXPORT_SYMBOL vmlinux 0xc003c637 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0xc01172c8 dma_async_device_unregister +EXPORT_SYMBOL vmlinux 0xc01b3fa0 set_bh_page +EXPORT_SYMBOL vmlinux 0xc01d7ed4 end_queued_request +EXPORT_SYMBOL vmlinux 0xc020d456 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0xc045ad4e timespec_trunc +EXPORT_SYMBOL vmlinux 0xc04f26ae ida_init +EXPORT_SYMBOL vmlinux 0xc0580937 rb_erase +EXPORT_SYMBOL vmlinux 0xc062482f tcp_md5_hash_key +EXPORT_SYMBOL vmlinux 0xc07d43ae acpi_evaluate_reference +EXPORT_SYMBOL vmlinux 0xc09651d9 crc32_be +EXPORT_SYMBOL vmlinux 0xc0a3d105 find_next_bit +EXPORT_SYMBOL vmlinux 0xc0b25677 serio_unregister_driver +EXPORT_SYMBOL vmlinux 0xc0defa41 elv_rb_add +EXPORT_SYMBOL vmlinux 0xc0ef2966 fifo_set_limit +EXPORT_SYMBOL vmlinux 0xc1022067 invalidate_bdev +EXPORT_SYMBOL vmlinux 0xc12264ac pci_release_regions +EXPORT_SYMBOL vmlinux 0xc13d7e4c __downgrade_write +EXPORT_SYMBOL vmlinux 0xc167d2b3 sock_no_mmap +EXPORT_SYMBOL vmlinux 0xc17b259d register_binfmt +EXPORT_SYMBOL vmlinux 0xc18d879a sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0xc1ceb4f7 ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0xc1d428ce atm_alloc_charge +EXPORT_SYMBOL vmlinux 0xc1d508ec pci_enable_msix +EXPORT_SYMBOL vmlinux 0xc1efbe5b textsearch_prepare +EXPORT_SYMBOL vmlinux 0xc20f651e blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0xc2282b29 generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0xc23abc1f nf_unregister_queue_handler +EXPORT_SYMBOL vmlinux 0xc2424641 agp3_generic_cleanup +EXPORT_SYMBOL vmlinux 0xc24422d3 xfrm_register_mode +EXPORT_SYMBOL vmlinux 0xc24883b4 pcim_iomap_regions_request_all +EXPORT_SYMBOL vmlinux 0xc254af48 dcache_lock +EXPORT_SYMBOL vmlinux 0xc256e762 __bitmap_equal +EXPORT_SYMBOL vmlinux 0xc2bc4746 input_register_handle +EXPORT_SYMBOL vmlinux 0xc2e2682b neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0xc2e587d1 reset_devices +EXPORT_SYMBOL vmlinux 0xc2ea31bd kmem_cache_free +EXPORT_SYMBOL vmlinux 0xc33f6f4c on_each_cpu +EXPORT_SYMBOL vmlinux 0xc364dd5a sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0xc3696aa9 pnp_is_active +EXPORT_SYMBOL vmlinux 0xc3879f26 block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0xc38e5923 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0xc3a0c629 task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0xc3aaf0a9 __put_user_1 +EXPORT_SYMBOL vmlinux 0xc3bdac42 tcf_em_tree_validate +EXPORT_SYMBOL vmlinux 0xc3e40924 skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0xc402cc99 register_acpi_notifier +EXPORT_SYMBOL vmlinux 0xc457ae00 skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0xc4585a91 dquot_free_space +EXPORT_SYMBOL vmlinux 0xc468f0c5 pcix_get_mmrbc +EXPORT_SYMBOL vmlinux 0xc489da34 dma_ops +EXPORT_SYMBOL vmlinux 0xc499ae1e kstrdup +EXPORT_SYMBOL vmlinux 0xc49b280f generic_file_splice_write +EXPORT_SYMBOL vmlinux 0xc4d489e9 up_write +EXPORT_SYMBOL vmlinux 0xc4d9ec05 bio_map_kern +EXPORT_SYMBOL vmlinux 0xc4e107c1 bio_free +EXPORT_SYMBOL vmlinux 0xc4ece29b cdev_add +EXPORT_SYMBOL vmlinux 0xc52f5714 fb_videomode_to_var +EXPORT_SYMBOL vmlinux 0xc5518739 xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0xc5534d64 ioread16 +EXPORT_SYMBOL vmlinux 0xc558530d profile_pc +EXPORT_SYMBOL vmlinux 0xc55f7dc7 _write_trylock +EXPORT_SYMBOL vmlinux 0xc56daa1e inode_needs_sync +EXPORT_SYMBOL vmlinux 0xc5a4c8a3 inet_register_protosw +EXPORT_SYMBOL vmlinux 0xc5d9c46c agp_try_unsupported_boot +EXPORT_SYMBOL vmlinux 0xc5e29365 pci_clear_mwi +EXPORT_SYMBOL vmlinux 0xc5e67eb9 sk_release_kernel +EXPORT_SYMBOL vmlinux 0xc5eaf5b3 generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0xc61bfd48 dev_open +EXPORT_SYMBOL vmlinux 0xc62fbb46 sock_sendmsg +EXPORT_SYMBOL vmlinux 0xc6487984 nla_put_nohdr +EXPORT_SYMBOL vmlinux 0xc65abeb7 agp3_generic_sizes +EXPORT_SYMBOL vmlinux 0xc65d6442 make_bad_inode +EXPORT_SYMBOL vmlinux 0xc67b57c6 pci_target_state +EXPORT_SYMBOL vmlinux 0xc6821530 tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0xc6aa160c sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0xc7208c3a serial8250_resume_port +EXPORT_SYMBOL vmlinux 0xc72336af unregister_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0xc7240444 compat_ip_getsockopt +EXPORT_SYMBOL vmlinux 0xc727994d qdisc_calculate_pkt_len +EXPORT_SYMBOL vmlinux 0xc732eeb8 skb_under_panic +EXPORT_SYMBOL vmlinux 0xc740c64a memchr +EXPORT_SYMBOL vmlinux 0xc75289a6 dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0xc7a24d76 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0xc7a4fbed rtnl_lock +EXPORT_SYMBOL vmlinux 0xc7b840c2 tcp_v4_md5_hash_skb +EXPORT_SYMBOL vmlinux 0xc7b935e4 remove_arg_zero +EXPORT_SYMBOL vmlinux 0xc7ca1dfc __ht_create_irq +EXPORT_SYMBOL vmlinux 0xc7e8d4e9 inet_listen +EXPORT_SYMBOL vmlinux 0xc7fc4c3e per_cpu__cpu_info +EXPORT_SYMBOL vmlinux 0xc80d1184 path_permission +EXPORT_SYMBOL vmlinux 0xc828bcb0 blk_run_queue +EXPORT_SYMBOL vmlinux 0xc85f7f9c generic_show_options +EXPORT_SYMBOL vmlinux 0xc897c382 sg_init_table +EXPORT_SYMBOL vmlinux 0xc8b57c27 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0xc8ca3e25 acpi_get_child +EXPORT_SYMBOL vmlinux 0xc8e94ef8 key_validate +EXPORT_SYMBOL vmlinux 0xc90aa50c locks_copy_lock +EXPORT_SYMBOL vmlinux 0xc9219a63 bio_hw_segments +EXPORT_SYMBOL vmlinux 0xc9437ede __down_write_nested +EXPORT_SYMBOL vmlinux 0xc94b9742 tty_port_init +EXPORT_SYMBOL vmlinux 0xc95493ee netdev_class_create_file +EXPORT_SYMBOL vmlinux 0xc97fa32b __inet6_hash +EXPORT_SYMBOL vmlinux 0xc998d641 icmp_err_convert +EXPORT_SYMBOL vmlinux 0xc9ab2eef acpi_os_wait_events_complete +EXPORT_SYMBOL vmlinux 0xc9c0cd17 gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0xc9c8fd20 qdisc_watchdog_init +EXPORT_SYMBOL vmlinux 0xc9cc7b0f devm_iounmap +EXPORT_SYMBOL vmlinux 0xc9ecdaf1 pnp_possible_config +EXPORT_SYMBOL vmlinux 0xc9f9f3a3 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0xca248fe9 blk_integrity_compare +EXPORT_SYMBOL vmlinux 0xca660ca0 generic_removexattr +EXPORT_SYMBOL vmlinux 0xca8abced request_key_with_auxdata +EXPORT_SYMBOL vmlinux 0xca8acc78 acpi_dbg_level +EXPORT_SYMBOL vmlinux 0xca96b5d3 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0xcaaf9d43 swiotlb_map_single +EXPORT_SYMBOL vmlinux 0xcb2ee31f netdev_features_change +EXPORT_SYMBOL vmlinux 0xcb32da10 param_set_int +EXPORT_SYMBOL vmlinux 0xcb4e312e tty_hung_up_p +EXPORT_SYMBOL vmlinux 0xcb6afc6c skb_queue_head +EXPORT_SYMBOL vmlinux 0xcb6beb40 hweight32 +EXPORT_SYMBOL vmlinux 0xcb7131fb fb_get_options +EXPORT_SYMBOL vmlinux 0xcb729b95 register_atm_ioctl +EXPORT_SYMBOL vmlinux 0xcb733bf2 acpi_bus_set_power +EXPORT_SYMBOL vmlinux 0xcb9d4339 tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0xcbb510b2 rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0xcbc35def wait_on_page_bit +EXPORT_SYMBOL vmlinux 0xcbe4ba8e bio_alloc +EXPORT_SYMBOL vmlinux 0xcbf991dd simple_transaction_get +EXPORT_SYMBOL vmlinux 0xcc07af75 strnlen +EXPORT_SYMBOL vmlinux 0xcc07e53a tcf_exts_dump_stats +EXPORT_SYMBOL vmlinux 0xcc248d26 serial8250_suspend_port +EXPORT_SYMBOL vmlinux 0xcc2b71e6 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0xcc36f32e fb_unregister_client +EXPORT_SYMBOL vmlinux 0xcc5005fe msleep_interruptible +EXPORT_SYMBOL vmlinux 0xcc51ee50 dma_spin_lock +EXPORT_SYMBOL vmlinux 0xcc533358 __insert_inode_hash +EXPORT_SYMBOL vmlinux 0xcc7f8443 pnp_start_dev +EXPORT_SYMBOL vmlinux 0xcc7fa952 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0xcc86b510 tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0xcc9237ea pci_remove_behind_bridge +EXPORT_SYMBOL vmlinux 0xccd7051f do_sync_write +EXPORT_SYMBOL vmlinux 0xcd34ba20 tty_unthrottle +EXPORT_SYMBOL vmlinux 0xcd3650b5 xrlim_allow +EXPORT_SYMBOL vmlinux 0xcd5d0802 blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0xcd8da5da blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0xcdd2ad45 inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0xce00efdd path_get +EXPORT_SYMBOL vmlinux 0xce09d896 noop_qdisc +EXPORT_SYMBOL vmlinux 0xce226ab1 kill_litter_super +EXPORT_SYMBOL vmlinux 0xce30a07f skb_store_bits +EXPORT_SYMBOL vmlinux 0xce36ded6 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0xce4904a4 acpi_leave_sleep_state +EXPORT_SYMBOL vmlinux 0xce5ac24f zlib_inflate_workspacesize +EXPORT_SYMBOL vmlinux 0xce6c5e46 xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0xce7b1047 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0xce905f0c dquot_commit +EXPORT_SYMBOL vmlinux 0xce9126a8 vfs_quota_off +EXPORT_SYMBOL vmlinux 0xced089cc vfs_get_dqblk +EXPORT_SYMBOL vmlinux 0xced99a51 kmem_ptr_validate +EXPORT_SYMBOL vmlinux 0xcee5a6ff backlight_device_unregister +EXPORT_SYMBOL vmlinux 0xcefcd99a serial8250_unregister_port +EXPORT_SYMBOL vmlinux 0xcf047c83 acpi_disable_gpe +EXPORT_SYMBOL vmlinux 0xcf191485 set_pages_nx +EXPORT_SYMBOL vmlinux 0xcf3cf9d6 uart_match_port +EXPORT_SYMBOL vmlinux 0xcf62e9dc ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0xcf6c9afc tcp_shutdown +EXPORT_SYMBOL vmlinux 0xcf8e3881 set_anon_super +EXPORT_SYMBOL vmlinux 0xcf8e9c00 block_sync_page +EXPORT_SYMBOL vmlinux 0xcfa28b8d inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0xcfadd723 __percpu_counter_add +EXPORT_SYMBOL vmlinux 0xcfcc7608 find_task_by_vpid +EXPORT_SYMBOL vmlinux 0xcfd3018e set_normalized_timespec +EXPORT_SYMBOL vmlinux 0xcfe0930a dev_get_by_flags +EXPORT_SYMBOL vmlinux 0xd005a7d0 tty_vhangup +EXPORT_SYMBOL vmlinux 0xd0181f4f __bitmap_xor +EXPORT_SYMBOL vmlinux 0xd02cc869 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0xd02db6fa textsearch_destroy +EXPORT_SYMBOL vmlinux 0xd0657672 xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0xd08197fa acpi_load_tables +EXPORT_SYMBOL vmlinux 0xd0b63b3f audit_log_start +EXPORT_SYMBOL vmlinux 0xd0b817f2 cfb_copyarea +EXPORT_SYMBOL vmlinux 0xd0c4fe96 fddi_type_trans +EXPORT_SYMBOL vmlinux 0xd0ee38b8 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0xd0fef3b2 agp_free_key +EXPORT_SYMBOL vmlinux 0xd11eda6a blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0xd1472061 acpi_pci_register_driver +EXPORT_SYMBOL vmlinux 0xd1729338 tcp_md5_hash_skb_data +EXPORT_SYMBOL vmlinux 0xd18b6eb2 acpi_unmap_lsapic +EXPORT_SYMBOL vmlinux 0xd19bb294 acpi_install_address_space_handler +EXPORT_SYMBOL vmlinux 0xd19c7f38 ht_create_irq +EXPORT_SYMBOL vmlinux 0xd1ef84e5 nf_log_unregister +EXPORT_SYMBOL vmlinux 0xd1f6c5f3 smp_num_siblings +EXPORT_SYMBOL vmlinux 0xd1f91bcd dev_base_lock +EXPORT_SYMBOL vmlinux 0xd23a8f76 netpoll_poll +EXPORT_SYMBOL vmlinux 0xd251d7b0 security_socket_getpeersec_dgram +EXPORT_SYMBOL vmlinux 0xd2555f19 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0xd25d4f74 console_blank_hook +EXPORT_SYMBOL vmlinux 0xd267d42c down_killable +EXPORT_SYMBOL vmlinux 0xd2965f6f kthread_should_stop +EXPORT_SYMBOL vmlinux 0xd296ab14 pci_bus_read_config_word +EXPORT_SYMBOL vmlinux 0xd2c2664e qdisc_reset +EXPORT_SYMBOL vmlinux 0xd3354d0e tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0xd341b78d bio_endio +EXPORT_SYMBOL vmlinux 0xd34f0c62 gen_pool_create +EXPORT_SYMBOL vmlinux 0xd3951da4 acpi_resource_to_address64 +EXPORT_SYMBOL vmlinux 0xd3957a6d __find_get_block +EXPORT_SYMBOL vmlinux 0xd39c08c4 thermal_zone_device_unregister +EXPORT_SYMBOL vmlinux 0xd3bc846e __inode_dir_notify +EXPORT_SYMBOL vmlinux 0xd3c1877c should_remove_suid +EXPORT_SYMBOL vmlinux 0xd3f74cf1 interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0xd41e42bf d_alloc +EXPORT_SYMBOL vmlinux 0xd42b7232 _write_unlock_bh +EXPORT_SYMBOL vmlinux 0xd465e8df do_splice_from +EXPORT_SYMBOL vmlinux 0xd46f6149 proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0xd47c8fea unregister_con_driver +EXPORT_SYMBOL vmlinux 0xd4839248 inet_ioctl +EXPORT_SYMBOL vmlinux 0xd48c68b0 agp_generic_insert_memory +EXPORT_SYMBOL vmlinux 0xd4970481 pnp_get_resource +EXPORT_SYMBOL vmlinux 0xd4ba7b13 __dev_get_by_index +EXPORT_SYMBOL vmlinux 0xd516f04b unregister_qdisc +EXPORT_SYMBOL vmlinux 0xd558133a blk_complete_request +EXPORT_SYMBOL vmlinux 0xd568308e __devm_request_region +EXPORT_SYMBOL vmlinux 0xd56dc70f framebuffer_release +EXPORT_SYMBOL vmlinux 0xd5797488 kobject_init +EXPORT_SYMBOL vmlinux 0xd5b037e1 kref_put +EXPORT_SYMBOL vmlinux 0xd5b455da tcp_child_process +EXPORT_SYMBOL vmlinux 0xd5c5e059 xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0xd5da8037 pv_mmu_ops +EXPORT_SYMBOL vmlinux 0xd6035574 do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0xd6035d05 do_settimeofday +EXPORT_SYMBOL vmlinux 0xd6234508 sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0xd62c833f schedule_timeout +EXPORT_SYMBOL vmlinux 0xd65169e6 idr_destroy +EXPORT_SYMBOL vmlinux 0xd65a1d0f sg_miter_next +EXPORT_SYMBOL vmlinux 0xd6a78d08 smp_call_function_single +EXPORT_SYMBOL vmlinux 0xd6b33026 cpu_khz +EXPORT_SYMBOL vmlinux 0xd6ee688f vmalloc +EXPORT_SYMBOL vmlinux 0xd6f6be4a end_page_writeback +EXPORT_SYMBOL vmlinux 0xd741c3fa generic_readlink +EXPORT_SYMBOL vmlinux 0xd757a60c netpoll_print_options +EXPORT_SYMBOL vmlinux 0xd758111a blk_alloc_queue +EXPORT_SYMBOL vmlinux 0xd760aa26 pcim_iomap +EXPORT_SYMBOL vmlinux 0xd798d298 dev_unicast_sync +EXPORT_SYMBOL vmlinux 0xd79b5a02 allow_signal +EXPORT_SYMBOL vmlinux 0xd7a4cf23 inet_csk_accept +EXPORT_SYMBOL vmlinux 0xd7a6fafa panic_notifier_list +EXPORT_SYMBOL vmlinux 0xd7a99075 d_add_ci +EXPORT_SYMBOL vmlinux 0xd7dd777b reserve_perfctr_nmi +EXPORT_SYMBOL vmlinux 0xd828ab3b alloc_disk +EXPORT_SYMBOL vmlinux 0xd82c9fb0 filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0xd8792b97 register_qdisc +EXPORT_SYMBOL vmlinux 0xd88f695a __mod_timer +EXPORT_SYMBOL vmlinux 0xd89da37f movable_zone +EXPORT_SYMBOL vmlinux 0xd89fe226 proc_symlink +EXPORT_SYMBOL vmlinux 0xd8e484f0 register_chrdev_region +EXPORT_SYMBOL vmlinux 0xd8eeabff bfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0xd9091363 acpi_install_notify_handler +EXPORT_SYMBOL vmlinux 0xd9197536 __secpath_destroy +EXPORT_SYMBOL vmlinux 0xd985dc99 mempool_free_pages +EXPORT_SYMBOL vmlinux 0xd9a3cce8 pci_disable_msi +EXPORT_SYMBOL vmlinux 0xd9f752c4 xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0xd9ff05f8 neigh_for_each +EXPORT_SYMBOL vmlinux 0xda0a6b0e acpi_map_lsapic +EXPORT_SYMBOL vmlinux 0xda1a7335 kasprintf +EXPORT_SYMBOL vmlinux 0xda416fdb acpi_bus_register_driver +EXPORT_SYMBOL vmlinux 0xda4629e4 radix_tree_insert +EXPORT_SYMBOL vmlinux 0xda72fe1a acpi_check_mem_region +EXPORT_SYMBOL vmlinux 0xda73a1d0 __check_region +EXPORT_SYMBOL vmlinux 0xda7ca6cb fb_mode_is_equal +EXPORT_SYMBOL vmlinux 0xda86cd71 nf_ip_checksum +EXPORT_SYMBOL vmlinux 0xda8af7ad fb_find_nearest_mode +EXPORT_SYMBOL vmlinux 0xda8c22ca cfb_imageblit +EXPORT_SYMBOL vmlinux 0xda928914 nmi_watchdog +EXPORT_SYMBOL vmlinux 0xdad137ac bio_integrity_add_page +EXPORT_SYMBOL vmlinux 0xdadf5b37 inode_change_ok +EXPORT_SYMBOL vmlinux 0xdae0dc74 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0xdb1560d5 iw_handler_get_spy +EXPORT_SYMBOL vmlinux 0xdb336833 fb_set_cmap +EXPORT_SYMBOL vmlinux 0xdb3e4ab4 set_device_ro +EXPORT_SYMBOL vmlinux 0xdb7c30be pnp_register_driver +EXPORT_SYMBOL vmlinux 0xdbac11fe bdi_unregister +EXPORT_SYMBOL vmlinux 0xdbcd416e sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0xdc14eda7 pci_pci_problems +EXPORT_SYMBOL vmlinux 0xdc2adb35 add_taint +EXPORT_SYMBOL vmlinux 0xdc3eaf70 iomem_resource +EXPORT_SYMBOL vmlinux 0xdc43a9c8 daemonize +EXPORT_SYMBOL vmlinux 0xdc4f3db5 dev_get_by_index +EXPORT_SYMBOL vmlinux 0xdc7ff918 ps2_drain +EXPORT_SYMBOL vmlinux 0xdc873a70 screen_info +EXPORT_SYMBOL vmlinux 0xdc9d4b50 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0xdca844a3 tcf_hash_search +EXPORT_SYMBOL vmlinux 0xdcb0349b sys_close +EXPORT_SYMBOL vmlinux 0xdccdb114 alloc_fddidev +EXPORT_SYMBOL vmlinux 0xdcdd40ff pci_request_regions +EXPORT_SYMBOL vmlinux 0xdce1a197 bio_integrity_tag_size +EXPORT_SYMBOL vmlinux 0xdcf85fed notify_change +EXPORT_SYMBOL vmlinux 0xdd0905a1 call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0xdd7ddfcd proc_create_data +EXPORT_SYMBOL vmlinux 0xddc09646 dma_supported +EXPORT_SYMBOL vmlinux 0xddc1ac11 bioset_integrity_free +EXPORT_SYMBOL vmlinux 0xde0bdcff memset +EXPORT_SYMBOL vmlinux 0xde11f960 unlock_new_inode +EXPORT_SYMBOL vmlinux 0xde293d86 acpi_match_device_ids +EXPORT_SYMBOL vmlinux 0xde2ed938 tcp_close +EXPORT_SYMBOL vmlinux 0xde2f86cf __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0xde44a927 find_vma +EXPORT_SYMBOL vmlinux 0xde588ff5 sock_no_shutdown +EXPORT_SYMBOL vmlinux 0xde645c95 neigh_table_clear +EXPORT_SYMBOL vmlinux 0xde682433 pci_scan_single_device +EXPORT_SYMBOL vmlinux 0xde68d2f7 simple_transaction_read +EXPORT_SYMBOL vmlinux 0xde72b41d pci_bus_find_capability +EXPORT_SYMBOL vmlinux 0xde75b689 set_irq_type +EXPORT_SYMBOL vmlinux 0xde9360ba totalram_pages +EXPORT_SYMBOL vmlinux 0xde99db47 blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0xde9b17ed agp3_generic_fetch_size +EXPORT_SYMBOL vmlinux 0xdeb35219 pci_disable_msix +EXPORT_SYMBOL vmlinux 0xdecfb024 genl_register_ops +EXPORT_SYMBOL vmlinux 0xdefbb5bf generic_file_aio_read +EXPORT_SYMBOL vmlinux 0xdf0da3cc acpi_get_devices +EXPORT_SYMBOL vmlinux 0xdf2589f5 register_chrdev +EXPORT_SYMBOL vmlinux 0xdf2a62ca pci_remove_bus_device +EXPORT_SYMBOL vmlinux 0xdf53d671 get_empty_filp +EXPORT_SYMBOL vmlinux 0xdf5435fe inet_dgram_connect +EXPORT_SYMBOL vmlinux 0xdf5adb00 sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0xdf5d209d find_inode_number +EXPORT_SYMBOL vmlinux 0xdf60cc27 __print_symbol +EXPORT_SYMBOL vmlinux 0xdf8c695a __ndelay +EXPORT_SYMBOL vmlinux 0xdf929370 fs_overflowgid +EXPORT_SYMBOL vmlinux 0xdfd40a52 neigh_connected_output +EXPORT_SYMBOL vmlinux 0xdff98cc2 default_llseek +EXPORT_SYMBOL vmlinux 0xe00d6d59 qdisc_watchdog_cancel +EXPORT_SYMBOL vmlinux 0xe00fb238 release_resource +EXPORT_SYMBOL vmlinux 0xe040f79b is_bad_inode +EXPORT_SYMBOL vmlinux 0xe050cdcc default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0xe0607bfe submit_bh +EXPORT_SYMBOL vmlinux 0xe075d6eb iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0xe0ac8bd2 acpi_bus_generate_netlink_event +EXPORT_SYMBOL vmlinux 0xe0b13336 argv_free +EXPORT_SYMBOL vmlinux 0xe0b5502d adjust_resource +EXPORT_SYMBOL vmlinux 0xe0c8fe0c agp_backend_acquire +EXPORT_SYMBOL vmlinux 0xe0d625aa pci_setup_cardbus +EXPORT_SYMBOL vmlinux 0xe113bbbc csum_partial +EXPORT_SYMBOL vmlinux 0xe11de77c tty_unregister_device +EXPORT_SYMBOL vmlinux 0xe12f5809 invalidate_inodes +EXPORT_SYMBOL vmlinux 0xe13cd8a7 dmi_name_in_vendors +EXPORT_SYMBOL vmlinux 0xe173d1ed __dst_free +EXPORT_SYMBOL vmlinux 0xe1761617 security_inet_conn_request +EXPORT_SYMBOL vmlinux 0xe1883329 __bio_clone +EXPORT_SYMBOL vmlinux 0xe1bbc7cf elv_rb_del +EXPORT_SYMBOL vmlinux 0xe1c65518 filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0xe1c95314 node_data +EXPORT_SYMBOL vmlinux 0xe1cd28b7 __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0xe1d3f441 set_pages_wb +EXPORT_SYMBOL vmlinux 0xe1e5a758 bh_submit_read +EXPORT_SYMBOL vmlinux 0xe1ffff77 put_disk +EXPORT_SYMBOL vmlinux 0xe20d59ab pnp_stop_dev +EXPORT_SYMBOL vmlinux 0xe2205739 blk_sync_queue +EXPORT_SYMBOL vmlinux 0xe24050c7 scnprintf +EXPORT_SYMBOL vmlinux 0xe24d3a97 jiffies_64 +EXPORT_SYMBOL vmlinux 0xe26ec842 inet_stream_ops +EXPORT_SYMBOL vmlinux 0xe27e9ae7 register_gifconf +EXPORT_SYMBOL vmlinux 0xe28be5e6 elevator_init +EXPORT_SYMBOL vmlinux 0xe2a17e0f dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0xe2b6a172 tty_register_device +EXPORT_SYMBOL vmlinux 0xe2d5255a strcmp +EXPORT_SYMBOL vmlinux 0xe2e43630 blk_integrity_register +EXPORT_SYMBOL vmlinux 0xe2e4e39b agp_alloc_page_array +EXPORT_SYMBOL vmlinux 0xe2ea1661 ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0xe32bb9b3 __lookup_hash +EXPORT_SYMBOL vmlinux 0xe3375fb6 register_netdevice +EXPORT_SYMBOL vmlinux 0xe351633f genl_register_family +EXPORT_SYMBOL vmlinux 0xe353b6c9 agp_enable +EXPORT_SYMBOL vmlinux 0xe385fd34 pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0xe3b0192b vscnprintf +EXPORT_SYMBOL vmlinux 0xe3b71d93 kick_iocb +EXPORT_SYMBOL vmlinux 0xe3d8bc54 seq_path +EXPORT_SYMBOL vmlinux 0xe3fbe148 acpi_install_table_handler +EXPORT_SYMBOL vmlinux 0xe4025e1f blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0xe417f658 proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0xe420a824 bio_split +EXPORT_SYMBOL vmlinux 0xe43617f7 acpi_gbl_FADT +EXPORT_SYMBOL vmlinux 0xe456bd3a complete +EXPORT_SYMBOL vmlinux 0xe484e35f ioread32 +EXPORT_SYMBOL vmlinux 0xe4870354 _read_trylock +EXPORT_SYMBOL vmlinux 0xe4c1df3e _read_lock_bh +EXPORT_SYMBOL vmlinux 0xe5122890 flow_cache_genid +EXPORT_SYMBOL vmlinux 0xe523ad75 synchronize_irq +EXPORT_SYMBOL vmlinux 0xe52947e7 __phys_addr +EXPORT_SYMBOL vmlinux 0xe52d7b4e mark_page_accessed +EXPORT_SYMBOL vmlinux 0xe5347ed7 __bforget +EXPORT_SYMBOL vmlinux 0xe55484ce neigh_seq_stop +EXPORT_SYMBOL vmlinux 0xe55704ab nf_hooks +EXPORT_SYMBOL vmlinux 0xe570cb79 qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0xe57878a1 in6_pton +EXPORT_SYMBOL vmlinux 0xe58477f0 dma_async_tx_descriptor_init +EXPORT_SYMBOL vmlinux 0xe5867808 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0xe58db769 agp_generic_create_gatt_table +EXPORT_SYMBOL vmlinux 0xe5b6fa6a blk_plug_device +EXPORT_SYMBOL vmlinux 0xe5c78a99 do_blank_screen +EXPORT_SYMBOL vmlinux 0xe5ee813b __breadahead +EXPORT_SYMBOL vmlinux 0xe631d3aa sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0xe66510a4 simple_prepare_write +EXPORT_SYMBOL vmlinux 0xe66d1b60 __serio_register_port +EXPORT_SYMBOL vmlinux 0xe681042e tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0xe68fc2e8 sock_setsockopt +EXPORT_SYMBOL vmlinux 0xe694cc8a set_current_groups +EXPORT_SYMBOL vmlinux 0xe6ae4e8c generic_delete_inode +EXPORT_SYMBOL vmlinux 0xe6ddfb27 input_inject_event +EXPORT_SYMBOL vmlinux 0xe6e13a8a tcf_exts_validate +EXPORT_SYMBOL vmlinux 0xe6fbe430 can_do_mlock +EXPORT_SYMBOL vmlinux 0xe716baed acpi_unregister_ioapic +EXPORT_SYMBOL vmlinux 0xe748b416 simple_transaction_release +EXPORT_SYMBOL vmlinux 0xe75eb914 block_write_end +EXPORT_SYMBOL vmlinux 0xe7619460 atm_dev_lookup +EXPORT_SYMBOL vmlinux 0xe77f5770 locks_remove_posix +EXPORT_SYMBOL vmlinux 0xe7871d4b register_sysctl_paths +EXPORT_SYMBOL vmlinux 0xe7923a32 ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0xe7d4daac seq_list_next +EXPORT_SYMBOL vmlinux 0xe7f640d6 eth_header_cache +EXPORT_SYMBOL vmlinux 0xe80ce219 sysctl_tcp_dma_copybreak +EXPORT_SYMBOL vmlinux 0xe8116e08 __kmalloc_node +EXPORT_SYMBOL vmlinux 0xe812d9d0 pci_find_device +EXPORT_SYMBOL vmlinux 0xe816c40f kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0xe8583614 posix_acl_from_xattr +EXPORT_SYMBOL vmlinux 0xe85e6a39 dst_discard +EXPORT_SYMBOL vmlinux 0xe89e97fe vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0xe8b12750 idr_replace +EXPORT_SYMBOL vmlinux 0xe8cd902e hweight16 +EXPORT_SYMBOL vmlinux 0xe910b532 del_timer_sync +EXPORT_SYMBOL vmlinux 0xe914e41e strcpy +EXPORT_SYMBOL vmlinux 0xe9456a5a sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0xe9593d32 qdisc_list_del +EXPORT_SYMBOL vmlinux 0xe9694add tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0xe997667b wrmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xe9da9019 vfs_get_dqinfo +EXPORT_SYMBOL vmlinux 0xe9f44cb5 pci_enable_device_mem +EXPORT_SYMBOL vmlinux 0xea10655a __bitmap_intersects +EXPORT_SYMBOL vmlinux 0xea147363 printk +EXPORT_SYMBOL vmlinux 0xea44461f key_type_keyring +EXPORT_SYMBOL vmlinux 0xea5478ab simple_empty +EXPORT_SYMBOL vmlinux 0xea656635 __tcf_em_tree_match +EXPORT_SYMBOL vmlinux 0xea6fcdaa genl_unregister_family +EXPORT_SYMBOL vmlinux 0xea757d9e inet_frags_init +EXPORT_SYMBOL vmlinux 0xeab4ae92 dst_release +EXPORT_SYMBOL vmlinux 0xeab79909 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0xead58fb9 print_hex_dump +EXPORT_SYMBOL vmlinux 0xeae3dfd6 __const_udelay +EXPORT_SYMBOL vmlinux 0xeb1fabf6 interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0xeb228272 posix_acl_create_masq +EXPORT_SYMBOL vmlinux 0xeb395084 param_get_invbool +EXPORT_SYMBOL vmlinux 0xeb48fc84 remap_pfn_range +EXPORT_SYMBOL vmlinux 0xeb6a7743 netif_device_detach +EXPORT_SYMBOL vmlinux 0xeb745b7c tcp_mtup_init +EXPORT_SYMBOL vmlinux 0xeb8f54b3 strstrip +EXPORT_SYMBOL vmlinux 0xeba41430 xfrm_input +EXPORT_SYMBOL vmlinux 0xebb09431 shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0xebbb2b9c inode_set_bytes +EXPORT_SYMBOL vmlinux 0xebbf1dba strncasecmp +EXPORT_SYMBOL vmlinux 0xebd273a6 strict_strtoull +EXPORT_SYMBOL vmlinux 0xebea0954 bio_integrity_get_tag +EXPORT_SYMBOL vmlinux 0xec247322 cfb_fillrect +EXPORT_SYMBOL vmlinux 0xec860422 bioset_free +EXPORT_SYMBOL vmlinux 0xec8ceac1 get_super +EXPORT_SYMBOL vmlinux 0xecde1418 _spin_lock_irq +EXPORT_SYMBOL vmlinux 0xed05d127 kernel_getsockname +EXPORT_SYMBOL vmlinux 0xed07c44c tcp_getsockopt +EXPORT_SYMBOL vmlinux 0xed166093 blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0xed926d18 compat_tcp_getsockopt +EXPORT_SYMBOL vmlinux 0xeda0abe2 inet_shutdown +EXPORT_SYMBOL vmlinux 0xedbaee5e nla_strcmp +EXPORT_SYMBOL vmlinux 0xedc03953 iounmap +EXPORT_SYMBOL vmlinux 0xedd14538 param_get_uint +EXPORT_SYMBOL vmlinux 0xee138752 nf_log_packet +EXPORT_SYMBOL vmlinux 0xee218dc2 sock_no_poll +EXPORT_SYMBOL vmlinux 0xee2d0fc7 _local_bh_enable +EXPORT_SYMBOL vmlinux 0xee7eb9e1 pnp_platform_devices +EXPORT_SYMBOL vmlinux 0xeea37c7f vfs_llseek +EXPORT_SYMBOL vmlinux 0xeea9dbaf bitmap_bitremap +EXPORT_SYMBOL vmlinux 0xeeb1717c param_array_get +EXPORT_SYMBOL vmlinux 0xeecaea22 down_write_trylock +EXPORT_SYMBOL vmlinux 0xeed56f88 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0xef10e2dc __alloc_skb +EXPORT_SYMBOL vmlinux 0xef4f7783 pci_pme_capable +EXPORT_SYMBOL vmlinux 0xef652a23 generic_file_direct_write +EXPORT_SYMBOL vmlinux 0xef663308 dma_async_memcpy_buf_to_buf +EXPORT_SYMBOL vmlinux 0xef6deb6f deny_write_access +EXPORT_SYMBOL vmlinux 0xef958205 inet_dgram_ops +EXPORT_SYMBOL vmlinux 0xef9aedfc boot_option_idle_override +EXPORT_SYMBOL vmlinux 0xefdd70ce security_secid_to_secctx +EXPORT_SYMBOL vmlinux 0xefe099c3 acpi_get_event_status +EXPORT_SYMBOL vmlinux 0xefea9b0d netif_rx_ni +EXPORT_SYMBOL vmlinux 0xeff62008 pci_restore_state +EXPORT_SYMBOL vmlinux 0xeffb322f __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0xeffc6220 agp_generic_alloc_page +EXPORT_SYMBOL vmlinux 0xf0009fee put_pages_list +EXPORT_SYMBOL vmlinux 0xf02ff9ef uart_remove_one_port +EXPORT_SYMBOL vmlinux 0xf05cb6e3 lookup_one_len +EXPORT_SYMBOL vmlinux 0xf0622901 kernel_connect +EXPORT_SYMBOL vmlinux 0xf065f629 ioread16be +EXPORT_SYMBOL vmlinux 0xf093a81a tcp_ioctl +EXPORT_SYMBOL vmlinux 0xf0b57c68 param_set_long +EXPORT_SYMBOL vmlinux 0xf0f1246c kvasprintf +EXPORT_SYMBOL vmlinux 0xf10de535 ioread8 +EXPORT_SYMBOL vmlinux 0xf11543ff find_first_zero_bit +EXPORT_SYMBOL vmlinux 0xf116d4b5 copy_in_user +EXPORT_SYMBOL vmlinux 0xf15f09ef rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0xf162fe2d sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0xf170eb6f alloc_tty_driver +EXPORT_SYMBOL vmlinux 0xf174ed48 acquire_console_sem +EXPORT_SYMBOL vmlinux 0xf195c682 fb_invert_cmaps +EXPORT_SYMBOL vmlinux 0xf1aba93a pci_enable_wake +EXPORT_SYMBOL vmlinux 0xf1e98c74 avenrun +EXPORT_SYMBOL vmlinux 0xf1eed002 qdisc_watchdog_schedule +EXPORT_SYMBOL vmlinux 0xf20dabd8 free_irq +EXPORT_SYMBOL vmlinux 0xf246de13 tcf_hash_destroy +EXPORT_SYMBOL vmlinux 0xf24e6dea do_splice_to +EXPORT_SYMBOL vmlinux 0xf2997713 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0xf2a6d2bf xfrm_policy_count +EXPORT_SYMBOL vmlinux 0xf2afa595 param_get_charp +EXPORT_SYMBOL vmlinux 0xf30dc211 tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0xf313da4e sha_transform +EXPORT_SYMBOL vmlinux 0xf3180c25 kmalloc_caches +EXPORT_SYMBOL vmlinux 0xf3258dca get_disk +EXPORT_SYMBOL vmlinux 0xf3341268 __clear_user +EXPORT_SYMBOL vmlinux 0xf338d4c3 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0xf34236da pci_disable_device +EXPORT_SYMBOL vmlinux 0xf343dcb3 __rta_fill +EXPORT_SYMBOL vmlinux 0xf346231f seq_list_start_head +EXPORT_SYMBOL vmlinux 0xf38cd527 dev_set_allmulti +EXPORT_SYMBOL vmlinux 0xf3bf0bce __bitmap_complement +EXPORT_SYMBOL vmlinux 0xf3f66641 blk_remove_plug +EXPORT_SYMBOL vmlinux 0xf3fa114b fib_default_rule_add +EXPORT_SYMBOL vmlinux 0xf4063d28 sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0xf441ac43 ioread8_rep +EXPORT_SYMBOL vmlinux 0xf4628e71 xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0xf4699d43 clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0xf46eb251 bdi_init +EXPORT_SYMBOL vmlinux 0xf47d47e0 acpi_enable_gpe +EXPORT_SYMBOL vmlinux 0xf49a4eae tcp_parse_options +EXPORT_SYMBOL vmlinux 0xf49bc67a atm_pcr_goal +EXPORT_SYMBOL vmlinux 0xf4a5c213 avail_to_resrv_perfctr_nmi_bit +EXPORT_SYMBOL vmlinux 0xf4f14de6 rtnl_trylock +EXPORT_SYMBOL vmlinux 0xf4f52f93 dqstats +EXPORT_SYMBOL vmlinux 0xf51ae235 touch_nmi_watchdog +EXPORT_SYMBOL vmlinux 0xf52252fc simple_write_end +EXPORT_SYMBOL vmlinux 0xf53d4c26 qdisc_class_hash_destroy +EXPORT_SYMBOL vmlinux 0xf547bce8 elv_queue_empty +EXPORT_SYMBOL vmlinux 0xf5816c58 fb_firmware_edid +EXPORT_SYMBOL vmlinux 0xf58890d6 con_set_default_unimap +EXPORT_SYMBOL vmlinux 0xf5bf9616 proc_dointvec +EXPORT_SYMBOL vmlinux 0xf5ce9811 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0xf5f0b7cd pci_set_dma_max_seg_size +EXPORT_SYMBOL vmlinux 0xf6231091 iget5_locked +EXPORT_SYMBOL vmlinux 0xf666cbb3 __memcpy_fromio +EXPORT_SYMBOL vmlinux 0xf678cdea tcf_register_action +EXPORT_SYMBOL vmlinux 0xf6bb4729 color_table +EXPORT_SYMBOL vmlinux 0xf6c5a56b get_agp_version +EXPORT_SYMBOL vmlinux 0xf6cdb69b key_revoke +EXPORT_SYMBOL vmlinux 0xf6ebc03b net_ratelimit +EXPORT_SYMBOL vmlinux 0xf6ff21f1 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0xf749534a gen_pool_free +EXPORT_SYMBOL vmlinux 0xf78d04ab netlink_register_notifier +EXPORT_SYMBOL vmlinux 0xf7924178 arp_tbl +EXPORT_SYMBOL vmlinux 0xf8045795 sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0xf80d9017 dma_free_coherent +EXPORT_SYMBOL vmlinux 0xf8216cb3 sock_create +EXPORT_SYMBOL vmlinux 0xf82abc1d isa_dma_bridge_buggy +EXPORT_SYMBOL vmlinux 0xf82e3d47 acpi_initialize_objects +EXPORT_SYMBOL vmlinux 0xf82f1109 utf8_wctomb +EXPORT_SYMBOL vmlinux 0xf8434a48 netif_rx +EXPORT_SYMBOL vmlinux 0xf849d06c blk_rq_map_integrity_sg +EXPORT_SYMBOL vmlinux 0xf86172fe compat_ip_setsockopt +EXPORT_SYMBOL vmlinux 0xf8624b3f sysctl_string +EXPORT_SYMBOL vmlinux 0xf87bb36e acpi_bus_add +EXPORT_SYMBOL vmlinux 0xf8814f73 rb_last +EXPORT_SYMBOL vmlinux 0xf88e0ee2 acpi_get_table_header +EXPORT_SYMBOL vmlinux 0xf890fe7f pm_idle +EXPORT_SYMBOL vmlinux 0xf89843f9 schedule_work +EXPORT_SYMBOL vmlinux 0xf8aa47ae mutex_lock_killable +EXPORT_SYMBOL vmlinux 0xf8aefa7b tcp_read_sock +EXPORT_SYMBOL vmlinux 0xf8b30e93 mempool_create +EXPORT_SYMBOL vmlinux 0xf8fbb8ef neigh_destroy +EXPORT_SYMBOL vmlinux 0xf943f0de seq_escape +EXPORT_SYMBOL vmlinux 0xf9718f6f tcp_proc_register +EXPORT_SYMBOL vmlinux 0xf97a76a6 pv_cpu_ops +EXPORT_SYMBOL vmlinux 0xf981110b pci_get_subsys +EXPORT_SYMBOL vmlinux 0xf9a482f9 msleep +EXPORT_SYMBOL vmlinux 0xf9bd9171 vfs_readlink +EXPORT_SYMBOL vmlinux 0xfa0564fc __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfa19c69e pci_scan_bus_parented +EXPORT_SYMBOL vmlinux 0xfa6252e3 inode_permission +EXPORT_SYMBOL vmlinux 0xfa842fdc down_write +EXPORT_SYMBOL vmlinux 0xfab96681 load_nls_default +EXPORT_SYMBOL vmlinux 0xfaf98462 bitrev32 +EXPORT_SYMBOL vmlinux 0xfb0443fb acpi_get_parent +EXPORT_SYMBOL vmlinux 0xfb0cf2e9 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0xfb0db878 aio_complete +EXPORT_SYMBOL vmlinux 0xfb328ba8 seq_lseek +EXPORT_SYMBOL vmlinux 0xfb6af58d recalc_sigpending +EXPORT_SYMBOL vmlinux 0xfb76c014 dev_add_pack +EXPORT_SYMBOL vmlinux 0xfba0c2e0 llc_sap_list_lock +EXPORT_SYMBOL vmlinux 0xfba3c8cc sk_receive_skb +EXPORT_SYMBOL vmlinux 0xfbed20d8 ioremap_nocache +EXPORT_SYMBOL vmlinux 0xfbf92453 param_get_bool +EXPORT_SYMBOL vmlinux 0xfbfa1247 uart_resume_port +EXPORT_SYMBOL vmlinux 0xfc02b7ad sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0xfc1a4250 bdi_register_dev +EXPORT_SYMBOL vmlinux 0xfc20c87b compat_sock_get_timestampns +EXPORT_SYMBOL vmlinux 0xfc383907 pcim_iounmap +EXPORT_SYMBOL vmlinux 0xfc39e32f ioport_unmap +EXPORT_SYMBOL vmlinux 0xfc470c05 lock_sock_nested +EXPORT_SYMBOL vmlinux 0xfc52c08c pcie_get_readrq +EXPORT_SYMBOL vmlinux 0xfc7f7aae dquot_drop +EXPORT_SYMBOL vmlinux 0xfc8b429c devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0xfcaa04a0 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfcb97d2f pnp_device_attach +EXPORT_SYMBOL vmlinux 0xfcdc8352 key_alloc +EXPORT_SYMBOL vmlinux 0xfcdd8cf6 param_get_ushort +EXPORT_SYMBOL vmlinux 0xfcec0987 enable_irq +EXPORT_SYMBOL vmlinux 0xfcf0018c open_exec +EXPORT_SYMBOL vmlinux 0xfcfa03ff fb_videomode_to_modelist +EXPORT_SYMBOL vmlinux 0xfd1c92a8 per_cpu____irq_regs +EXPORT_SYMBOL vmlinux 0xfd2f4c28 unlock_buffer +EXPORT_SYMBOL vmlinux 0xfd3135e7 get_write_access +EXPORT_SYMBOL vmlinux 0xfd98879a rb_next +EXPORT_SYMBOL vmlinux 0xfdb9b629 ioread32be +EXPORT_SYMBOL vmlinux 0xfdcc26dd dev_close +EXPORT_SYMBOL vmlinux 0xfde2145a boot_tvec_bases +EXPORT_SYMBOL vmlinux 0xfdf2d800 pci_pme_active +EXPORT_SYMBOL vmlinux 0xfe047ce6 acpi_enter_sleep_state +EXPORT_SYMBOL vmlinux 0xfe0f5e62 request_key +EXPORT_SYMBOL vmlinux 0xfe11ea2b skb_free_datagram +EXPORT_SYMBOL vmlinux 0xfe26fc7c nr_node_ids +EXPORT_SYMBOL vmlinux 0xfe392bcd generic_segment_checks +EXPORT_SYMBOL vmlinux 0xfe5d4bb2 sys_tz +EXPORT_SYMBOL vmlinux 0xfe769456 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0xfe7c27c1 dev_mc_add +EXPORT_SYMBOL vmlinux 0xfe7c4287 nr_cpu_ids +EXPORT_SYMBOL vmlinux 0xfe8eb0aa alloc_buffer_head +EXPORT_SYMBOL vmlinux 0xfe917b88 ps2_command +EXPORT_SYMBOL vmlinux 0xfea14b4d seq_read +EXPORT_SYMBOL vmlinux 0xfebc0cbf __wait_on_buffer +EXPORT_SYMBOL vmlinux 0xfec3c2f2 bcd2bin +EXPORT_SYMBOL vmlinux 0xfedd35fc console_suspend_enabled +EXPORT_SYMBOL vmlinux 0xfee4892b genl_sock +EXPORT_SYMBOL vmlinux 0xfeec104b xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0xff1e9dd8 seq_list_start +EXPORT_SYMBOL vmlinux 0xff48f7cc inode_init_once +EXPORT_SYMBOL vmlinux 0xff6878cf fb_default_cmap +EXPORT_SYMBOL vmlinux 0xff6c9439 block_write_begin +EXPORT_SYMBOL vmlinux 0xff708fd3 mempool_destroy +EXPORT_SYMBOL vmlinux 0xff779fe6 input_grab_device +EXPORT_SYMBOL vmlinux 0xff7f47ac __elv_add_request +EXPORT_SYMBOL vmlinux 0xff9ca065 fb_edid_to_monspecs +EXPORT_SYMBOL vmlinux 0xffafdc5c _read_unlock_irq +EXPORT_SYMBOL vmlinux 0xffbb77f0 sk_reset_timer +EXPORT_SYMBOL vmlinux 0xffd5a395 default_wake_function +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x00aaf935 kvm_disable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x05b20bc7 kvm_lapic_enabled +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x07a37517 kvm_get_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x094ac8f4 kvm_get_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0aba6308 kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0ca96fb1 kvm_inject_pending_timer_irqs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0edba703 kvm_release_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0f041d40 kvm_lapic_find_highest_irr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1099fb94 kvm_mmu_reset_context +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x12d1b23b kvm_release_pfn_clean +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x14edd812 kvm_get_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x15ecd2cd kvm_read_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x193e07e9 kvm_task_switch +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1aa41982 kvm_set_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1c06df86 kvm_mmu_load +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1e4580bb kvm_release_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x21284d29 kvm_set_cr0 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2322e039 kvm_set_pfn_accessed +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x240daead kvm_lapic_set_tpr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x24ccfc74 kvm_write_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x26ca07eb emulator_write_emulated +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x27046576 kvm_exit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2ab72290 kvm_lapic_get_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2eaf780e kvm_emulate_pio +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x317f9e6b kvm_enable_efer_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x361792d0 load_pdptrs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x372633f3 kvm_queue_exception +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3961dec9 gfn_to_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3abb7213 kvm_lapic_reset +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3e268086 kvm_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x434355d3 kvm_report_emulation_failure +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4a7cbe69 is_error_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4d14c883 fx_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4f242e83 kvm_lapic_get_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x52ed2d0b emulate_instruction +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x541ee4c8 kvm_set_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x65432d3b kvm_mmu_page_fault +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x65bd9021 kvm_resched +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x65f32ddf kvm_vcpu_cache +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x67b37172 kvm_set_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x71168123 kvm_get_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x74a041ac is_error_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7571bb84 kvm_emulate_hypercall +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7e240dde kvm_create_lapic +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7e8cec18 kvm_mmu_unprotect_page_virt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7f715335 kvm_set_cr3 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x814e512a kvm_set_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8ce4f3ab kvm_enable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8e7f9b47 segment_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x942d9225 gfn_to_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x99d1e49a kvm_cpu_get_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9ddaef22 kvm_cpu_has_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa361bc65 kvm_set_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa65f67a6 kvm_clear_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa80cf3ab kvm_read_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xad2b4e9b gfn_to_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xad700ed7 __kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xaf4af07a kvm_get_cs_db_l_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xb927e761 kvm_inject_nmi +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xba40a11e kvm_timer_intr_post +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd15c2bf kvm_emulate_cpuid +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd377dc9 kvm_mmu_set_nonpresent_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd86163a kvm_handle_fault_on_reboot +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd94103b kvm_mmu_set_base_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbdbc8990 kvm_queue_exception_e +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbdf0d859 kvm_lmsw +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbf717296 kvm_clear_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xca6c1580 kvm_vcpu_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xcb1ceecf kvm_emulate_halt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xcd0b66b7 kvm_is_visible_gfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd0b2727a kvm_mmu_set_mask_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd296def9 kvm_is_error_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdbfb5fb4 kvm_vcpu_uninit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdd5675f0 kvm_put_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xe2c691e1 kvm_release_page_clean +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xef3fffe8 kvm_get_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf080d298 emulator_read_std +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf5103889 kvm_put_guest_fpu +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf60b9af9 kvm_set_cr4 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf9070561 kvm_emulate_pio_string +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xfbe77a16 kvm_load_guest_fpu +EXPORT_SYMBOL_GPL crypto/aead 0x0581052d crypto_aead_setauthsize +EXPORT_SYMBOL_GPL crypto/aead 0x0f92a6e0 crypto_alloc_aead +EXPORT_SYMBOL_GPL crypto/aead 0x1b66d742 aead_geniv_alloc +EXPORT_SYMBOL_GPL crypto/aead 0x233b951d aead_geniv_init +EXPORT_SYMBOL_GPL crypto/aead 0x4fc1268e aead_geniv_exit +EXPORT_SYMBOL_GPL crypto/aead 0x78a83d3b crypto_nivaead_type +EXPORT_SYMBOL_GPL crypto/aead 0x7b104b9d aead_geniv_free +EXPORT_SYMBOL_GPL crypto/aead 0xe47aa47c crypto_aead_type +EXPORT_SYMBOL_GPL crypto/aead 0xe882a0f2 crypto_grab_aead +EXPORT_SYMBOL_GPL crypto/aes_generic 0x1381bf2d crypto_ft_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x22894d94 crypto_il_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x465dc396 crypto_aes_set_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5f943003 crypto_it_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5fe743de crypto_aes_expand_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x6e9cc2ba crypto_fl_tab +EXPORT_SYMBOL_GPL crypto/async_tx/async_memcpy 0x215fd546 async_memcpy +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x2be84c9b async_tx_run_dependencies +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x59a79343 __async_tx_find_channel +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x6b4a6db2 async_tx_issue_pending_all +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xcd654cc9 async_tx_submit +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xd9d1c50e async_tx_quiesce +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xdad23b28 dma_wait_for_async_tx +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xf22d0802 async_trigger_callback +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0x69d18617 async_xor_zero_sum +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0xafa1af85 async_xor +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x02b231e1 skcipher_geniv_free +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x02d5c96b blkcipher_walk_done +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x2b556b76 crypto_ablkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x2c889fbf skcipher_geniv_alloc +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x7128dac8 blkcipher_walk_virt_block +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x8017ac74 blkcipher_walk_virt +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x9929c619 crypto_blkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xa3382896 crypto_grab_skcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xbfdf79fb crypto_alloc_ablkcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xc5abe22a skcipher_geniv_init +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xdd26d05b crypto_givcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xfa8c2322 blkcipher_walk_phys +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xfb673bd4 skcipher_geniv_exit +EXPORT_SYMBOL_GPL crypto/des_generic 0xcfd9a2c0 des_ekey +EXPORT_SYMBOL_GPL crypto/twofish_common 0x97065ba1 twofish_setkey +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x100c48a2 unregister_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x2611fbee register_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x318920b1 register_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xbd506a46 unregister_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xcc6ab305 is_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x0ad5c33f acpi_smbus_register_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x158c2ad0 acpi_smbus_unregister_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x526b867a acpi_smbus_read +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0xb3d5e527 acpi_smbus_write +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x3ecf6cfc wmi_install_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x561c634a wmi_evaluate_method +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x876d29f1 wmi_get_event_data +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xb5a6ebe2 wmi_remove_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xc9d4d6d1 wmi_has_guid +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xda29f8b0 wmi_set_block +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xfb882fb7 wmi_query_block +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0067df75 ata_tf_from_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x00ebcb5d ata_id_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0x012c766c ata_bmdma_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0x01391ea8 ata_acpi_gtm +EXPORT_SYMBOL_GPL drivers/ata/libata 0x01fb13c0 ata_do_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0x03ba3e91 sata_sff_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x03e3686c ata_timing_cycle2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0531dcb8 ata_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0646ccc9 ata_pci_remove_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0x070a3bbf ata_sff_data_xfer_noirq +EXPORT_SYMBOL_GPL drivers/ata/libata 0x07ab611e ata_base_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0e1dbf2b ata_link_offline +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0f7d2436 ata_dev_pair +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1078f700 ata_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x10d0eb08 ata_port_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x13b8d67c ata_link_online +EXPORT_SYMBOL_GPL drivers/ata/libata 0x14823ec4 ata_sff_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1532fa01 ata_port_probe +EXPORT_SYMBOL_GPL drivers/ata/libata 0x16e75724 ata_port_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0x17472a33 ata_acpi_stm +EXPORT_SYMBOL_GPL drivers/ata/libata 0x19d24843 ata_sff_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1ed118d6 ata_sff_check_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0x22b915b9 ata_host_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0x25de9164 ata_eh_freeze_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0x29294a81 ata_bmdma_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2dbd9a13 ata_std_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2e2e959c ata_sas_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2fa81e56 ata_sff_qc_issue +EXPORT_SYMBOL_GPL drivers/ata/libata 0x30273d2a ata_eh_analyze_ncq_error +EXPORT_SYMBOL_GPL drivers/ata/libata 0x30df3010 ata_eh_thaw_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0x338edecb sata_async_notification +EXPORT_SYMBOL_GPL drivers/ata/libata 0x33b3917f ata_do_dev_read_id +EXPORT_SYMBOL_GPL drivers/ata/libata 0x34be1a69 ata_cable_40wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0x354b59e9 ata_pci_bmdma_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x387a5c7e __ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3a898234 ata_cable_ignore +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3e1ff10c ata_eh_qc_retry +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3eb9c430 ata_dummy_port_info +EXPORT_SYMBOL_GPL drivers/ata/libata 0x40af0dec ata_xfer_mode2mask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x41ff54ed ata_sff_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4369f6ff ata_sff_tf_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0x43f56e82 ata_xfer_mode2shift +EXPORT_SYMBOL_GPL drivers/ata/libata 0x45d3e4ea sata_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x468a3a70 ata_bmdma_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x46bbea94 ata_host_activate +EXPORT_SYMBOL_GPL drivers/ata/libata 0x46e8751a sata_link_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4a5bcc10 ata_sff_dev_select +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4af06d8f ata_dev_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4b2dcd88 ata_sff_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4d5b7b05 ata_sff_busy_sleep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4e2944b0 ata_sas_port_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4f10b51c ata_timing_compute +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4f2650fa ata_port_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fabe64e ata_sff_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fdc945d sata_deb_timing_normal +EXPORT_SYMBOL_GPL drivers/ata/libata 0x50559e06 ata_sas_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x50923106 ata_sff_dumb_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x531faf27 ata_sff_irq_clear +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5333d70a dev_attr_link_power_management_policy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x57f05500 ata_sff_thaw +EXPORT_SYMBOL_GPL drivers/ata/libata 0x58cbb27f ata_host_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5b01d551 ata_host_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5d2e9ab4 sata_pmp_qc_defer_cmd_switch +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5e859671 sata_link_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5ebfbc0d ata_eh_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5ee48632 ata_host_detach +EXPORT_SYMBOL_GPL drivers/ata/libata 0x605ff91c ata_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6089d973 ata_port_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0x649399fc sata_scr_write +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6521683d ata_pci_sff_init_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0x69e9a2cb ata_scsi_slave_config +EXPORT_SYMBOL_GPL drivers/ata/libata 0x69f72c86 ata_bmdma_mode_filter +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6c5abcd4 ata_sff_qc_fill_rtf +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6e247fe0 ata_sff_softreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x707ff1bb ata_xfer_mask2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x71872a25 ata_pio_need_iordy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x733e4115 ata_std_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a437f4 ata_qc_complete_multiple +EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a48b4a ata_sff_std_ports +EXPORT_SYMBOL_GPL drivers/ata/libata 0x743a165e ata_pack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7640795f ata_sff_irq_on +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7680959c ata_port_schedule_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0x77dc2389 ata_pci_bmdma_clear_simplex +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7a0b9bb0 ata_sff_dma_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7a6acc1c ata_sff_post_internal_cmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7c0aa664 ata_link_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7f73b635 ata_pci_device_do_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0x81c3555c ata_bmdma_setup +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8316a798 ata_acpi_gtm_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x844121d6 sata_pmp_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8888c39b ata_host_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0x89ec587b ata_bmdma_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b752ac1 ata_tf_to_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8c397ec9 sata_scr_write_flush +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8d9271fc ata_do_set_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8dc4252a ata_std_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8e2de209 sata_scr_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8f3b8399 ata_host_alloc_pinfo +EXPORT_SYMBOL_GPL drivers/ata/libata 0x91102b35 ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94a68723 ata_scsi_slave_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94dc62d2 ata_scsi_ioctl +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98520864 ata_pci_device_do_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9862bf0c ata_sff_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98796db3 ata_cable_unknown +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98c6b6bd ata_sas_port_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9961389a ata_std_bios_param +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9c4fcc15 dev_attr_sw_activity +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9e2fcf57 ata_scsi_simulate +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9f4861c8 ata_sff_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa4cf7245 ata_sg_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0xab01ac2f ata_sff_exec_command +EXPORT_SYMBOL_GPL drivers/ata/libata 0xafa680e6 ata_sas_slave_configure +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb174100b sata_pmp_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb1b6e95d sata_link_debounce +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb4c964a5 ata_sff_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6aeb661 ata_id_c_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb92e4abe ata_host_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xba7bc4e9 dev_attr_em_message +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbbf57dd2 ata_port_pbar_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbc0482e3 sata_std_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbcd975cd ata_acpi_cbl_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbd578b54 ata_sas_port_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe1887e4 ata_unpack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbf839350 ata_sff_tf_load +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbfa9f977 ata_cable_sata +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbfd7b9b6 ata_sff_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc21b8e22 ata_scsi_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc3f6ccc2 ata_sff_hsm_move +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc428068d sata_deb_timing_long +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc48b7ccf ata_mode_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc4acf318 ata_pci_sff_init_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc5ae2ef4 ata_bus_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc673e23e ata_scsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc8441306 ata_sff_wait_ready +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcb432b16 dev_attr_em_message_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcccfb2fa sata_deb_timing_hotplug +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcf101579 ata_pci_device_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd3fe7b4e ata_pci_sff_activate_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd6f752bd ata_std_qc_defer +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd7f468c9 ata_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd84cd7f4 ata_timing_find_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdbfcf27f ata_pci_device_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0xde889f2b ata_sff_host_intr +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdf3022b2 ata_sff_interrupt +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe15c8821 ata_dummy_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe49ff3b0 ata_wait_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0xea242048 ata_pci_sff_prepare_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0xea418e0f atapi_cmd_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf0f75776 ata_sff_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf370316f ata_sff_data_xfer +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf3d5cc13 ata_timing_merge +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf5e9c680 ata_sas_port_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf6535fdb ata_host_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf70f9fe3 pci_test_config_bits +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf712879c ata_ehi_clear_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8f3a0fb ata_ratelimit +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf95c875b ata_noop_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf9ca3160 ata_id_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfc6db3aa ata_cable_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfec4786a sata_set_spd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xff949b4c sata_scr_valid +EXPORT_SYMBOL_GPL drivers/ata/pata_sis 0x83c06bf9 sis_info133_for_sata +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x02ff9464 cfag12864b_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x0ecb2e5d cfag12864b_disable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x305dc3c6 cfag12864b_isenabled +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x3389f926 cfag12864b_enable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x9522a342 cfag12864b_getrate +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0xc48e9d95 cfag12864b_buffer +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x14102f23 ks0108_displaystate +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x48a70518 ks0108_writedata +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x4f506333 ks0108_startline +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x6edae968 ks0108_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xbf4774db ks0108_writecontrol +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xedde6df2 ks0108_page +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xfee8ef7b ks0108_address +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x1ff2fdd8 tpm_show_active +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x1ffd54f1 tpm_calc_ordinal_duration +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x36b852f4 tpm_remove_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x44ec43e2 tpm_show_temp_deactivated +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x4a2d5ec4 tpm_write +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x4c86db04 tpm_gen_interrupt +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x57647f9c tpm_release +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x63aa28f5 tpm_show_caps_1_2 +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7ce459ad tpm_show_enabled +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x8a6bc58b tpm_store_cancel +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9243fada tpm_get_timeouts +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9f02eb96 tpm_register_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9f2288ba tpm_show_pcrs +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc42620a6 tpm_continue_selftest +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc95ea356 tpm_show_owned +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xd3d6f28b tpm_read +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xe8ada778 tpm_open +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xe8b0e3e5 tpm_pm_resume +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xe9876d63 tpm_show_caps +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xf4bd91d0 tpm_pm_suspend +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xf9784d9a tpm_show_pubek +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0xbf67b76f tpm_bios_log_setup +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0xd941eec8 tpm_bios_log_teardown +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x01b354b4 cpufreq_frequency_table_target +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x2f47d8c7 cpufreq_frequency_get_table +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x3361319f cpufreq_frequency_table_cpuinfo +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x706b3a33 cpufreq_frequency_table_get_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x7ae1ae8e cpufreq_frequency_table_put_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x7bc780a5 cpufreq_frequency_table_verify +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0xa861f3b5 cpufreq_freq_attr_scaling_available_freqs +EXPORT_SYMBOL_GPL drivers/dca/dca 0x05b3551e unregister_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0x2cd03ed5 register_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0x2e471f01 dca_register_notify +EXPORT_SYMBOL_GPL drivers/dca/dca 0x31a2c8df dca_get_tag +EXPORT_SYMBOL_GPL drivers/dca/dca 0x4324d628 dca3_get_tag +EXPORT_SYMBOL_GPL drivers/dca/dca 0x48ac0971 dca_add_requester +EXPORT_SYMBOL_GPL drivers/dca/dca 0x652621dc dca_remove_requester +EXPORT_SYMBOL_GPL drivers/dca/dca 0x8006c614 dca_unregister_notify +EXPORT_SYMBOL_GPL drivers/dca/dca 0xc58266af alloc_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0xda71046d free_dca_provider +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x061fa43e edac_device_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1460af9e edac_device_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1633927b edac_pci_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x199112a6 edac_device_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1c167262 edac_device_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x30e51ae0 edac_device_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x34a50ad4 edac_pci_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x3cee3db2 edac_pci_handle_pe +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x4b4f08bd edac_mc_del_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x51d31e05 edac_mc_handle_ce_no_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x656183a9 edac_pci_release_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x6eb4b537 edac_mc_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa839fbc5 edac_mc_free +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa95712fe edac_mc_add_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xb7d74f03 edac_pci_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xbed0e378 edac_pci_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcf44d6ae edac_mc_alloc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcf90c047 edac_mc_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xd124389c edac_mc_handle_ue_no_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xd68dd31f edac_pci_reset_delay_period +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xd719df73 edac_mc_find_csrow_by_page +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xdfcbae5e edac_pci_create_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xe6d5635c edac_device_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xf8cb7a17 edac_pci_handle_npe +EXPORT_SYMBOL_GPL drivers/hid/hid 0x008e49bd hid_free_device +EXPORT_SYMBOL_GPL drivers/hid/hid 0x22e05021 hid_parse_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x3bc82e74 hid_input_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x3d2d8e93 hid_output_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x5f3a6dfd hidraw_disconnect +EXPORT_SYMBOL_GPL drivers/hid/hid 0x651305a3 hidraw_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0x8d40c384 hidinput_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0xab7ec347 hid_set_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xb640f303 hidraw_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0xe99b408a hidinput_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0xecededa1 hidinput_find_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xf7d08585 hidinput_disconnect +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x01fd453e usbhid_lookup_quirk +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0xadd2b06d hiddev_hid_event +EXPORT_SYMBOL_GPL drivers/i2c/busses/i2c-nforce2 0x42fa7e2e nforce2_smbus +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x224aba8b i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x50144523 i2c_new_dummy +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x6daff9c8 i2c_bus_type +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x9f414307 i2c_new_probed_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xbe26bf5b i2c_unregister_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xdd9438fd i2c_new_device +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xc8ae0e78 hpsb_config_rom_ip1394_remove +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xdbd22690 hpsb_config_rom_ip1394_add +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xec8d18cf hpsb_disable_irm +EXPORT_SYMBOL_GPL drivers/infiniband/hw/ipath/ib_ipath 0x1514b2b2 ipath_debug +EXPORT_SYMBOL_GPL drivers/input/ff-memless 0xe6f33025 input_ff_create_memless +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x05809a9f wm97xx_read_aux_adc +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x173c5303 wm97xx_reg_read +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x2fe0a29c wm97xx_set_suspend_mode +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x4b576377 wm9712_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x5247f50a wm97xx_config_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x56e97e2d wm9705_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x661c45f2 wm97xx_get_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x81949c43 wm97xx_unregister_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x87fd63e9 wm9713_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xb3c6a551 wm97xx_register_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xd7298039 wm97xx_set_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xdded962a wm97xx_reg_write +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x12f163d3 gigaset_stop +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x1d78ae71 gigaset_blockdriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x2c0979ce gigaset_dbg_buffer +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x3c0ceb0c gigaset_add_event +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x3dcb0999 gigaset_freedriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x454aa44f gigaset_debuglevel +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x4df10ddd gigaset_initcs +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x53dc0905 gigaset_shutdown +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x57bd1155 gigaset_m10x_input +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x5f8548bb gigaset_freecs +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x63b2a1f0 gigaset_fill_inbuf +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x8a09f8ec gigaset_if_receive +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xd3cf7ee6 gigaset_start +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xd74382a6 gigaset_handle_modem_response +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xe98d15a3 gigaset_skb_sent +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xf00279a0 gigaset_m10x_send_skb +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xf03b749d gigaset_initdriver +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x3dbc6938 led_classdev_unregister +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x606f5703 led_classdev_resume +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x748348da led_classdev_suspend +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x96910d35 led_classdev_register +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x0b0ca530 dm_put +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x63bb15c0 dm_set_device_limits +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x67ebd785 dm_noflush_suspending +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x89f73ccf dm_device_name +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x8a1e1f75 dm_disk +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xcbd33995 dm_send_uevents +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xe6699033 dm_path_uevent +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0x64fb57ce dm_unregister_path_selector +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xdacffadc dm_register_path_selector +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x06f33595 md_allow_write +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x1597102b sync_page_io +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x56fb30ed md_do_sync +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x64a4b440 md_new_event +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x04662e0f ir_codes_fusionhdtv_mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x07e92917 ir_codes_avermedia_a16d +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x083661f9 ir_codes_avertv_303 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x088631b9 ir_codes_behold +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x1cb148f5 ir_extract_bits +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2456e513 ir_decode_pulsedistance +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2a4852cc ir_codes_dntv_live_dvb_t +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2af1a608 ir_codes_proteus_2309 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x3811daea ir_codes_manli +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x43c89ef4 ir_decode_biphase +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x45b08f68 ir_codes_pinnacle_grey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4740e7a3 ir_codes_empty +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4ea698a2 ir_codes_purpletv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x55338dda ir_codes_pixelview_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x589cad50 ir_codes_apac_viewcomp +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x5db13554 ir_codes_encore_enltv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x659a9ac0 ir_input_init +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6606596a ir_rc5_timer_keyup +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6a06e2d5 ir_input_keydown +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6adc476d ir_codes_powercolor_real_angel +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6aefdbea ir_codes_npgtech +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6b87c69d ir_codes_iodata_bctv7e +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6d6511e7 ir_dump_samples +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6e2a1870 ir_codes_adstech_dvb_t_pci +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x7277973d ir_codes_pctv_sedna +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x75e89cc3 ir_codes_flydvb +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x772a30a2 ir_codes_nebula +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x85d37490 ir_codes_dntv_live_dvbt_pro +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x89cc1189 ir_codes_winfast +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x902a3cd2 ir_codes_hauppauge_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x933d0bb3 ir_codes_msi_tvanywhere +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x9451e232 ir_codes_behold_columbus +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x96470cab ir_codes_cinergy +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb1f4eb35 ir_codes_avermedia_dvbt +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb6cd4666 ir_codes_eztv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xbdce6594 ir_codes_tt_1500 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc1fea0c1 ir_codes_pv951 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc42bd037 ir_codes_budget_ci_old +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc4b85b21 ir_input_nokey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc6c5a7a1 ir_codes_em_terratec +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd1e0258a ir_codes_flyvideo +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd55e6891 ir_codes_gotview7135 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd9c7f010 ir_codes_rc5_tv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdaa041ad ir_codes_cinergy_1400 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdfcf23df ir_codes_norwood +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xee2f5e0e ir_codes_pinnacle_pctv_hd +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf07533a1 ir_codes_videomate_tv_pvr +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf0fc9374 ir_codes_avermedia +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf2b421aa ir_codes_genius_tvgo_a11mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf4f7a4d6 ir_rc5_timer_end +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfa177653 ir_codes_pixelview +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfb981300 ir_codes_pinnacle_color +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfc54a5cd ir_codes_asus_pc39 +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x0e0dd318 saa7146_vfree_destroy_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x369fcaaa saa7146_register_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x505110d7 saa7146_pgtable_build_single +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x613ef2d5 saa7146_unregister_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x62fe733d saa7146_vmalloc_build_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x7fc10aec saa7146_wait_for_debi_done +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xa6a95506 saa7146_pgtable_alloc +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xc653ebf1 saa7146_pgtable_free +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xc98faf20 saa7146_devices_lock +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xcf683cf2 saa7146_devices +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xe3cd9b5c saa7146_debug +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xf67f44c1 saa7146_i2c_adapter_prepare +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xfb4cc614 saa7146_setgpio +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x166ce5f6 saa7146_start_preview +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x168ab67f saa7146_register_device +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x2d61c0f2 saa7146_set_hps_source_and_sync +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x3da661c3 saa7146_vv_release +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x555ea70d saa7146_vv_init +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xc0508cd0 saa7146_stop_preview +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xf47ff7ce saa7146_unregister_device +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mt20xx 0xe10cf6e5 microtune_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mxl5007t 0x3969c476 mxl5007t_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda18271 0xcc761724 tda18271_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda827x 0x7f949f23 tda827x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0x827abc8a tda829x_probe +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0xfb444527 tda829x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda9887 0x8c267f8e tda9887_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xd28977eb tea5761_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xea33988b tea5761_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0x98adfbad tea5767_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0xb87bf8ef tea5767_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tuner-simple 0xf2219b3d simple_tuner_attach +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x36d74737 ttpci_budget_init_hooks +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x458244a5 ttpci_budget_debiwrite +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x7948c222 budget_debug +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x8a0268c2 ttpci_budget_irq10_handler +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xeb99fba8 ttpci_budget_debiread +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xfc7c6d0f ttpci_budget_init +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xfd4d95a6 ttpci_budget_deinit +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xffe72a99 ttpci_budget_set_video_port +EXPORT_SYMBOL_GPL drivers/media/video/compat_ioctl32 0x893bfe61 v4l_compat_ioctl32 +EXPORT_SYMBOL_GPL drivers/media/video/cx88/cx88xx 0x89d41f6e cx88_setup_xc3028 +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x0c4c71e0 em28xx_audio_analog_set +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x44fd2c62 em28xx_set_mode +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x7a02e48d em28xx_init_isoc +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xd22c24eb em28xx_tuner_callback +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xfdc356fc em28xx_uninit_isoc +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0x4e1a168f saa7134_queryctrl +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xb3966707 saa7134_ts_qops +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xe0f69cdd saa7134_g_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xff18210b saa7134_s_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0x84ce8ac6 v4l2_int_device_register +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0xb1391645 v4l2_int_device_unregister +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x03f836f1 videobuf_read_start +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x0be28bab videobuf_cgmbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x11cfe7c7 videobuf_next_field +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x14f199df videobuf_queue_to_vmalloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x15215c65 videobuf_querybuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x1789f253 videobuf_queue_core_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x1b5b18a8 videobuf_mmap_mapper +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x26b59630 videobuf_streamoff +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x2ea9f980 videobuf_dqbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x38a327f6 videobuf_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x3cbe5805 videobuf_waiton +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x4ac67b8b videobuf_read_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x4f3a0596 videobuf_queue_is_busy +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x7e030034 videobuf_streamon +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x815fb430 __videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xab4cf250 videobuf_qbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xace184b4 videobuf_poll_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xb9022b31 videobuf_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xbcfc774e videobuf_reqbufs +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xc0333f56 videobuf_mmap_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xc6a0ecaf videobuf_queue_cancel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xde5b3079 videobuf_iolock +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xf758bd89 videobuf_read_one +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xfb558667 videobuf_read_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xfea30721 videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x08806486 videobuf_to_dma_contig +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x540a17c2 videobuf_queue_dma_contig_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x8442a313 videobuf_dma_contig_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x26ecaf68 videobuf_sg_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x4b27f806 videobuf_dma_sync +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x531feace videobuf_dma_init_overlay +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x5c7aa182 videobuf_dma_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x7bb4206b videobuf_to_dma +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x7fb2a9bb videobuf_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x933dfb43 videobuf_vmalloc_to_sg +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa0f23e54 videobuf_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa2e0f975 videobuf_dma_init_kernel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa38faed2 videobuf_sg_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xaf1ada19 videobuf_dma_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xc1538b00 videobuf_queue_sg_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xcc1823f5 videobuf_sg_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xdd17fe73 videobuf_dma_init_user +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x4e5d83fd videobuf_to_vmalloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x7bf1fbc6 videobuf_vmalloc_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0xbb02da22 videobuf_queue_vmalloc_init +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x3085b131 sm501_set_clock +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x42a27726 sm501_unit_power +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x494ea35e sm501_find_clock +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x897e1f68 sm501_misc_control +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xed934be3 sm501_modify_reg +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x2df115d4 eeprom_93cx6_multiread +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x63d14d2f eeprom_93cx6_read +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x58a17c64 enclosure_remove_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x6c13472f enclosure_add_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x958b1da4 enclosure_register +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x9ab6f7fd enclosure_component_register +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xc1339762 enclosure_find +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xd359f806 enclosure_unregister +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xf342e30f enclosure_for_each_device +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x2293c8e0 gru_get_next_message +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x5927a880 gru_send_message_gpa +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x7e83f3fc gru_free_message +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x81b3b8e3 gru_create_message_queue +EXPORT_SYMBOL_GPL drivers/misc/sgi-gru/gru 0x9c7283a1 gru_copy_gpa +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x345c9217 xpc_disconnect +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x39046c7a xpc_clear_interface +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x43a01eea xpc_registrations +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x6285dfe8 xp_cpu_to_nasid +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x64ba5017 xp_pa +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x76e36d39 xp_region_size +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x9823adb0 xpc_set_interface +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0x9acd8cf8 xpc_interface +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xba3694f3 xp_remote_memcpy +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xead4f7fe xp_max_npartitions +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xf3b47f67 xp_partition_id +EXPORT_SYMBOL_GPL drivers/misc/sgi-xp/xp 0xfe709b6c xpc_connect +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x010aa9b0 sdio_writew +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x19d9fd23 sdio_readsb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x278c21a1 sdio_memcpy_toio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x3054cf5a sdio_writesb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x4932e60a sdio_readw +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x61b4227c sdio_f0_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x67a47346 sdio_f0_readb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x6cb9965e sdio_enable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x6decc1ad sdio_claim_host +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x774329d4 sdio_set_block_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x86627cbf sdio_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x92fc74f8 sdio_disable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xa1ec87c9 sdio_writel +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xa36c1583 sdio_memcpy_fromio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xac2d0856 sdio_register_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xb343754c sdio_readb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xc07ee1ec sdio_align_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xcc636b3d sdio_release_host +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe16309d5 sdio_claim_irq +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe4175d44 sdio_readl +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe97886b0 sdio_unregister_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xf89d0372 sdio_release_irq +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x33daefe9 sdhci_remove_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x4d1e0d44 sdhci_alloc_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x5b119295 sdhci_resume_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x69145b6f sdhci_free_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xa574644d sdhci_add_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xf443c5e8 sdhci_suspend_host +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x25561522 cfi_cmdset_0200 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x4e5fd7f3 cfi_cmdset_0003 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0xd71bae7f cfi_cmdset_0001 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0002 0x02fdeb35 cfi_cmdset_0002 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0020 0x7f2e19cb cfi_cmdset_0020 +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2000 0xeb8297d7 DoC2k_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001 0x92b52cc0 DoCMil_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001plus 0xf4b38d40 DoCMilPlus_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/docecc 0x45937659 doc_decode_ecc +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x0525ab69 put_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x161d03a0 default_mtd_writev +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x29d6c9a9 get_mtd_device_nm +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x36491db8 register_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x3768ddcc kill_mtd_super +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x45df5301 get_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x49cc76d0 deregister_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x57b7ae07 add_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x730c66fe del_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x8da91b7c unregister_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x9a150064 parse_mtd_partitions +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x9b039828 mtd_table +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x9da027f6 get_sb_mtd +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xaac99e1c mtd_erase_callback +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xc23c70d9 register_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xeff64be1 mtd_table_mutex +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x13e48577 add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x1dfbda04 deregister_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x9b6f6fa8 register_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xc29da60e del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x74577927 nand_wait_ready +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x7811a42d nand_release +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xa3fe39be nand_scan_ident +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xa5828772 nand_scan +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xe1deae73 nand_scan_tail +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x37b0aae5 onenand_release +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x862512ea onenand_scan +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x00d9def6 ubi_get_volume_info +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x1a4a34e3 ubi_leb_read +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x24c6c65f ubi_leb_unmap +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x42801d20 ubi_sync +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x56fb237d ubi_is_mapped +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x5c3fbf0e ubi_leb_erase +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x5dfd73af ubi_open_volume_nm +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x5ff86b78 ubi_leb_write +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x6fc6b57b ubi_close_volume +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x9113391e ubi_leb_map +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xb1bfd6b3 ubi_open_volume +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbbbb6481 ubi_leb_change +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbc505df4 ubi_get_device_info +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0b537f8b mlx4_CLOSE_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x181a0565 mlx4_free_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1c6fc717 mlx4_mtt_init +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1d446d71 mlx4_qp_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2099e7bc __mlx4_cmd +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x23e9bb54 mlx4_fmr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2a45b47f mlx4_srq_arm +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2be82087 mlx4_srq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x382df159 mlx4_buf_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3ff35ec7 mlx4_srq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4b608888 mlx4_map_phys_fmr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4f374ab5 mlx4_srq_query +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x51905ba0 mlx4_SYNC_TPT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x51cad764 mlx4_fmr_unmap +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x53b279de mlx4_buf_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5539058a mlx4_alloc_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5a35efa4 mlx4_pd_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x629799b1 mlx4_mr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x64a55b21 mlx4_cq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x65675603 mlx4_fmr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x68817f39 mlx4_qp_query +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x688e38e9 mlx4_uar_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6a6fb149 mlx4_alloc_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6b287334 mlx4_cq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x73c823aa mlx4_mtt_addr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x776de6a8 mlx4_free_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7892ca3b mlx4_multicast_detach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x799fd415 mlx4_cq_resize +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x8265350f mlx4_pd_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x82e97ece mlx4_qp_remove +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x8c32de27 mlx4_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb327fbc8 mlx4_db_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb59c6d9b mlx4_buf_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb7663a4e mlx4_register_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbaaaff31 mlx4_mtt_cleanup +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbbc28468 mlx4_fmr_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbfcd1b47 mlx4_uar_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc228bc16 mlx4_qp_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc94cf72b mlx4_db_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xd0709200 mlx4_INIT_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdb8ebd86 mlx4_mr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdc7295b8 mlx4_cq_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xde3317b1 mlx4_qp_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe30641f3 mlx4_multicast_attach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xea6077c6 mlx4_qp_to_ready +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xed747120 mlx4_unregister_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf0bb0ffb mlx4_mr_alloc +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0x10619d5f usbnet_generic_cdc_bind +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0xa3323d54 usbnet_cdc_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x324a2444 rndis_status +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x3867554e rndis_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x64497bed generic_rndis_bind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x82657718 rndis_rx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x8cd5edc4 rndis_tx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xfcadc84e rndis_command +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x0603a904 usbnet_suspend +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x263e0ade usbnet_get_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x310249f1 usbnet_get_drvinfo +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x4f683447 usbnet_set_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x5393b378 usbnet_get_settings +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x55e358e0 usbnet_disconnect +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x61375469 usbnet_unlink_rx_urbs +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x6ca51229 usbnet_nway_reset +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x73abac0b usbnet_get_link +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x9938fdd6 usbnet_probe +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x9ae262a6 usbnet_get_endpoints +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x9dd79457 usbnet_skb_return +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xa2c803fa usbnet_resume +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xc19ffd9b usbnet_set_settings +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xe7efe826 usbnet_defer_kevent +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x0350ec69 __lbs_cmd +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x0a8048fd lbs_remove_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x19195f70 lbs_host_sleep_cfg +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x2def2262 lbs_start_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x42254e0f lbs_stop_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x4a203d94 lbs_send_tx_feedback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x69f79d72 lbs_notify_command_response +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x71ce25c8 lbs_add_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x844a0eba lbs_cmd_copyback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x9878f7a1 lbs_host_to_card_done +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x9d3b0691 lbs_queue_event +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xcb34bcc6 lbs_process_rxed_packet +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xd33e3467 lbs_cmd_802_11_rate_adapt_rateset +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xda0bc68d lbs_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xe8593545 lbs_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xf64277de lbs_debug +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x540d9f8b p54_init_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x753f4c71 p54_free_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x80a99f67 p54_parse_firmware +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xaa748adb p54_fill_eeprom_readback +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xb12b29ea p54_parse_eeprom +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xe032c996 p54_rx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x065977ef rt2x00mac_remove_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x0bede017 rt2x00mac_get_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1ca071e6 rt2x00lib_beacondone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1e9d8a88 rt2x00mac_get_tx_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x2d3d5154 rt2x00mac_add_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x446ee68e rt2x00mac_conf_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x4e189bb7 rt2x00mac_configure_filter +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5333a6ed rt2x00mac_config_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5bdf8921 rt2x00lib_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x6fc69c20 rt2x00lib_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x80b05909 rt2x00lib_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x882ed30a rt2x00queue_get_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x8ce6d87e rt2x00mac_config +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x93eab81b rt2x00mac_bss_info_changed +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x97637a96 rt2x00mac_start +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xa290d166 rt2x00lib_txdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xb3e16082 rt2x00lib_probe_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xc932f203 rt2x00queue_map_txskb +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xd3fb503d rt2x00lib_remove_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xe1e0a93b rt2x00queue_get_entry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xeb138258 rt2x00mac_stop +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xf4341f1c rt2x00mac_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x8b4c77f7 rt2x00pci_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x94705b97 rt2x00pci_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xaff2ecf0 rt2x00pci_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xb7e7c387 rt2x00pci_remove +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xc261bd0e rt2x00pci_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xcccebec7 rt2x00pci_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xcead6bbd rt2x00pci_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xf22e75dc rt2x00pci_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x19442568 rt2x00usb_init_txentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x292ee901 rt2x00usb_vendor_req_buff_lock +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x3a2db448 rt2x00usb_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x6851b543 rt2x00usb_init_rxentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x6e58639a rt2x00usb_kick_tx_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x6f5aa012 rt2x00usb_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x77a7363d rt2x00usb_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x839667c1 rt2x00usb_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x9d593c95 rt2x00usb_vendor_request +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xa82a0e75 rt2x00usb_vendor_request_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xbbedc3b6 rt2x00usb_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xc61ac19d rt2x00usb_disconnect +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xcfde11d8 rt2x00usb_vendor_request_large_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xdfece2ba rt2x00usb_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xecdc9b7e rt2x00usb_disable_radio +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0x6c438f6d acpiphp_unregister_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0x93adf1ab acpiphp_register_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x1ad3b491 acpi_root_bridge +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x32140aea cpci_hp_unregister_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x379e7f4b cpci_hp_unregister_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x6a8441be cpci_hp_start +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x8cc0e47b pci_hp_change_slot_info +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x8f6ee199 cpci_hp_register_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x91967b92 pci_hp_deregister +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x94ef4d05 cpci_hp_stop +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xb1a5a811 cpci_hp_register_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xc74ae2c8 acpi_get_hp_params_from_firmware +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xe36a6d0c pci_hp_register +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x593a36c2 scsi_dh_handler_exist +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x59554196 scsi_register_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x6a938091 scsi_unregister_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x84219f11 scsi_dh_attach +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xa62c1095 scsi_dh_detach +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xe30102fb scsi_dh_activate +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0233f349 iscsi_pool_init +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0427498b iscsi_conn_start +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x06acd281 iscsi_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0d8ff697 iscsi_conn_send_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0f89362c iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x1995dbf7 iscsi_session_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x232912a5 iscsi_requeue_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x26478b75 iscsi_host_remove +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x278d9903 iscsi_conn_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x28a46dbf iscsi_session_setup +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x2c0eb8eb iscsi_eh_host_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x347cc80a iscsi_suspend_tx +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3a9f152d iscsi_conn_setup +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3d7d3eb4 __iscsi_get_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3ea127e2 iscsi_update_cmdsn +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x41ba1d14 iscsi_pool_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x47e85621 iscsi_itt_to_ctask +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x4b2d2c02 iscsi_prep_unsolicit_data_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x51cf6c47 iscsi_conn_stop +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x5b4ee575 iscsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x6137fda6 iscsi_host_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x8c91a9d9 iscsi_host_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x9591b7b1 iscsi_host_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x9ecd0951 __iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa2751fff iscsi_put_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa91072d9 iscsi_eh_device_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb47376a4 iscsi_host_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc00693c2 iscsi_host_add +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc3c7e132 iscsi_session_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc5048a26 iscsi_conn_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd1fb33a5 iscsi_session_recovery_timedout +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd60bebce iscsi_conn_bind +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe8acee35 iscsi_verify_itt +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe96609f6 iscsi_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xee248e40 iscsi_eh_abort +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf401b9e1 iscsi_conn_failure +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x19172af1 sas_domain_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x1fbe7eb1 sas_phy_reset +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x24d541f4 sas_eh_device_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x270bfa25 sas_target_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x328c3744 sas_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x340f68b4 sas_eh_bus_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x383e1d91 sas_slave_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x42738b6b sas_unregister_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x5a014a6b sas_register_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x64f3f1bd sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x6a9a0fe2 sas_domain_attach_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x70190dfd sas_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x7d1bb3c3 sas_ioctl +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x879cf949 sas_bios_param +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x87c6a48f sas_slave_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xa0bcb683 sas_find_local_phy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xb0be0358 sas_phy_enable +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xbfe2de6b __sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xc6c68dea sas_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xca8e290f sas_slave_configure +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xcf5b0300 sas_request_addr +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xdefc0368 sas_ssp_task_response +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xf0e63336 sas_change_queue_type +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x0382f64b srp_iu_put +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x607f406d srp_target_free +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x6946c06e srp_iu_get +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xb16ab5bb srp_cmd_queue +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xdd0846b8 srp_transfer_data +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xffa183fc srp_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x1d3dc709 scsi_flush_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x213fc9f1 scsi_execute_async +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x26c90ea4 scsi_eh_get_sense +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x3435a25e scsi_internal_device_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x35d8c94a sdev_evt_alloc +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x3830d533 scsi_bus_type +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x3ae46ef9 scsi_mode_select +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x5f48d4ee scsi_nl_sock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x60926379 scsi_queue_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x671f0a37 sdev_evt_send_simple +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7ade9df0 scsi_eh_ready_devs +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7e275ea8 scsi_complete_async_scans +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xaac5219a scsi_internal_device_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd4c700d5 scsi_schedule_eh +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd606abaa scsi_target_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd61a829d scsi_target_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xe8a6393e sdev_evt_send +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xeff2d09a __scsi_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x002cc17f scsi_tgt_it_nexus_create +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x0ef6dee3 scsi_tgt_tsk_mgmt_request +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x17e15093 scsi_tgt_free_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x4bedafd8 scsi_host_put_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x50759b7c scsi_host_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x95408aa6 scsi_tgt_alloc_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xbba40bf9 scsi_tgt_it_nexus_destroy +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xe865d562 scsi_tgt_queue_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xefd7681b scsi_tgt_cmd_to_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x329fe04d iscsi_create_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x3d13bbb9 iscsi_unblock_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x41b0d952 iscsi_create_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x45be2779 iscsi_block_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x565d4c0b iscsi_destroy_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x5963f157 iscsi_scan_finished +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x68ba7b65 iscsi_add_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x6bd185a5 iscsi_register_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xa0838c39 iscsi_recv_pdu +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xb2871103 iscsi_lookup_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xba1c55e0 iscsi_session_chkready +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xbac1b6b7 iscsi_destroy_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xbd693705 iscsi_host_for_each_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xc090ca73 iscsi_alloc_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xdad69694 iscsi_remove_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xdfbc55d2 iscsi_conn_error +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe043f42f iscsi_session_event +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe0dbe958 iscsi_destroy_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe81f0c65 iscsi_free_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xee0ee01e iscsi_create_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xfca4c51e iscsi_unregister_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0x0ef06974 spi_populate_ppr_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xa0c71dac spi_populate_sync_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xcffa2aff spi_populate_width_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x43429377 srp_attach_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x9a415c9a srp_remove_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xbd9ebb7a srp_rport_add +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xdac096c1 srp_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xf9edbf7f srp_rport_del +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x0316cff1 spi_bitbang_start +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x06639431 spi_bitbang_transfer +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x21bf81c2 spi_bitbang_setup +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x556ca9a1 spi_bitbang_cleanup +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xd9e8339d spi_bitbang_setup_transfer +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xdec48b01 spi_bitbang_stop +EXPORT_SYMBOL_GPL drivers/uio/uio 0x02cda0a5 uio_unregister_device +EXPORT_SYMBOL_GPL drivers/uio/uio 0x24a139c8 uio_event_notify +EXPORT_SYMBOL_GPL drivers/uio/uio 0x807777f1 __uio_register_device +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0x8909ee33 usbatm_usb_probe +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0xa0d92993 usbatm_usb_disconnect +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x04c79745 usb_get_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0d281a4b usb_ep0_reinit +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x18706a09 usb_register_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x18ada175 usb_driver_release_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x19a304ba usb_disabled +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1d369e1e usb_get_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x241cbe42 usb_buffer_unmap_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x249d0af1 usb_unlink_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x252e5cd7 usb_unanchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x294aaa77 usb_hcd_pci_suspend +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x2b9b7438 usb_reset_device +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3470443c usb_submit_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x35738fc5 usb_interrupt_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x391592eb usb_hcd_pci_probe +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x396551eb usb_hcd_pci_remove +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3a5c7b03 usb_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3b0535a0 usb_get_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3be89d3c usb_register_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x41654fb3 usb_put_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x428bfa84 usb_register_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x47bd5692 usb_anchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x491efdff usb_hcd_pci_resume +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4c8eeab8 usb_put_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5202224b usb_match_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5634a0c4 usb_hcd_pci_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x56e649bf usb_get_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5792a642 usb_kill_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x61d5a263 usb_reset_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x629ea18f usb_clear_halt +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x63d61914 usb_get_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x646ee7b4 usb_deregister +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x68618b3c usb_get_current_frame_number +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6a40c9d3 usb_hcd_unlink_urb_from_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6c6066cf usb_hcd_platform_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6dce94bf usb_bus_list_lock +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x75535712 usb_alloc_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7ddeaedf usb_bulk_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7e64181d usb_calc_bus_time +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x828582ad usb_init_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8566b389 usb_driver_set_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x87efb515 usb_get_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x88432bf3 usb_register_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8d4d9705 usb_find_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8ebc1348 usb_hub_tt_clear_buffer +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x980191b6 usb_sg_wait +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9924c496 __usb_get_extra_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9ef7037d usb_buffer_free +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa12d019d usb_control_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa9deb580 usb_altnum_to_altsetting +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xaa049b1a usb_free_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xaaf844e0 usb_add_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xac113b09 usb_autopm_put_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xace5c0fc usb_bus_list +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xae5514c0 usb_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xafb40978 usb_hcd_poll_rh_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb5c87f1f usb_driver_claim_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb848c501 usb_string +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb98a8623 usb_deregister_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbc3a242f usb_wait_anchor_empty_timeout +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbcd5e088 usb_deregister_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbf787af1 usb_hc_died +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc060b093 usb_autopm_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc0f1f4c7 usb_put_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc139f1bb usb_sg_init +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc17515d7 usb_hcds_loaded +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc750657b usb_sg_cancel +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcab4c7c9 usb_store_new_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcd837cf0 usb_mon_register +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcdacb960 usb_hcd_resume_root_hub +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd3289e3e usb_hcd_link_urb_to_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd4faf8db usb_lock_device_for_reset +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xdb49a388 usb_buffer_map_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe276a327 usb_remove_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe3875d2a usb_kill_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe6ebb2d4 usb_buffer_alloc +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9587909 usb_unregister_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xeaa3659d usb_hcd_giveback_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xed0690a5 ehci_cf_port_reset_rwsem +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf2eeaa35 usb_autopm_get_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf474a0b2 usb_root_hub_lost_power +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfa7336ae usb_ifnum_to_if +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfc2f8f1b usb_hcd_check_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfd6c579b usb_match_one_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfea68d87 usb_create_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfed11ed1 usb_mon_deregister +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x19d547ee usb_ftdi_elan_edset_setup +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x91e63787 usb_ftdi_elan_read_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xa05c3763 usb_ftdi_elan_edset_output +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xb348351d usb_ftdi_elan_edset_input +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xbdb133fd usb_ftdi_elan_edset_flush +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xd663f5e4 usb_ftdi_elan_edset_empty +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xe1ad07c7 usb_ftdi_elan_edset_single +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xe49488ee usb_ftdi_elan_write_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xf69ca1a0 ftdi_elan_gone_away +EXPORT_SYMBOL_GPL drivers/usb/misc/phidget 0x87f7008c phidget_class +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x309d1ce3 usb_serial_port_softint +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x358c5e55 usb_serial_deregister +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x761931b5 ezusb_writememory +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x83f4c770 ezusb_set_reset +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x8ca43184 usb_serial_generic_write_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x8ffb2305 usb_serial_register +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xa341c82b usb_serial_disconnect +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xab44f8d9 usb_serial_generic_read_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xce55fb5f usb_serial_probe +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xe4a9ba00 usb_serial_generic_open +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x3edad223 usb_usual_clear_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x89d4dbaf usb_usual_check_type +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xcd9991a9 usb_usual_set_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xde134c69 storage_usb_ids +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x200ca72a ili9320_suspend +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x29330374 ili9320_write_regs +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x2f908eae ili9320_shutdown +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x62246e1a ili9320_remove +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x87d3dbca ili9320_probe_spi +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x9084d36f ili9320_write +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xd8a9f8d1 ili9320_resume +EXPORT_SYMBOL_GPL drivers/video/fb_ddc 0xf114a454 fb_ddc_read +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x2221a647 fb_sys_write +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x5d56af5c fb_sys_read +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0xae1d4bd1 sis_free_new +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0xdaca72c3 sis_malloc_new +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x016e6c20 vmlfb_unregister_subsys +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x90c018c6 vmlfb_register_subsys +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x0f191ab7 register_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x16f5900f virtio_check_driver_offered_feature +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x7aaa1838 unregister_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xa9973f03 register_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xbab696b5 unregister_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x03c4687d vring_interrupt +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x11a51fb2 vring_transport_features +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0xaf7c0454 vring_del_virtqueue +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0xc0e0aa23 vring_new_virtqueue +EXPORT_SYMBOL_GPL drivers/w1/wire 0x225e421c w1_write_block +EXPORT_SYMBOL_GPL drivers/w1/wire 0x6af5326e w1_reset_select_slave +EXPORT_SYMBOL_GPL drivers/w1/wire 0x7c2f2afb w1_calc_crc8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0x82b56f84 w1_write_8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0xcf6a6b2d w1_reset_bus +EXPORT_SYMBOL_GPL drivers/w1/wire 0xda0c6759 w1_read_block +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x6e5fdc6e dlm_posix_get +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x9321df95 dlm_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x9a2591e4 dlm_posix_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xc3ecfbd6 dlm_posix_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xcf9f3328 dlm_release_lockspace +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdc583c08 dlm_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdf3c14de dlm_new_lockspace +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0xf8c6e865 exportfs_encode_fh +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0xffc95b42 exportfs_decode_fh +EXPORT_SYMBOL_GPL fs/fat/fat 0x12db78c9 fat_detach +EXPORT_SYMBOL_GPL fs/fat/fat 0x1fdd8d21 fat_search_long +EXPORT_SYMBOL_GPL fs/fat/fat 0x26807f8e fat_dir_empty +EXPORT_SYMBOL_GPL fs/fat/fat 0x2b077c82 fat_fs_panic +EXPORT_SYMBOL_GPL fs/fat/fat 0x32f558f4 fat_scan +EXPORT_SYMBOL_GPL fs/fat/fat 0x575d7c72 fat_alloc_new_dir +EXPORT_SYMBOL_GPL fs/fat/fat 0x72c6fb0b fat_sync_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0x76d5a3ca fat_get_dotdot_entry +EXPORT_SYMBOL_GPL fs/fat/fat 0x84505e1c fat_flush_inodes +EXPORT_SYMBOL_GPL fs/fat/fat 0x8b196d71 fat_fill_super +EXPORT_SYMBOL_GPL fs/fat/fat 0x9c6db1fb fat_attach +EXPORT_SYMBOL_GPL fs/fat/fat 0xb0304d19 fat_build_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0xb68ea16d fat_date_unix2dos +EXPORT_SYMBOL_GPL fs/fat/fat 0xca2879fe fat_setattr +EXPORT_SYMBOL_GPL fs/fat/fat 0xcb38e9ad fat_add_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0xdc4d4558 fat_remove_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0xeb556ccf fat_free_clusters +EXPORT_SYMBOL_GPL fs/fat/fat 0xec1c5ec4 fat_getattr +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0x3c17e93f gfs2_register_lockproto +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0xa1c3a001 gfs2_unregister_lockproto +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x1a618932 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x38028873 nlmclnt_proc +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x9908eb0b nlmclnt_init +EXPORT_SYMBOL_GPL fs/lockd/lockd 0xb0441369 nlmclnt_done +EXPORT_SYMBOL_GPL fs/lockd/lockd 0xb74bbd5c nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x0cfc7bbe o2hb_register_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1ab8c993 o2nm_node_get +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1b89c6ee o2hb_fill_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1c78e047 o2nm_get_node_by_num +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1d747ce3 o2hb_check_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x36418553 o2net_send_message +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x41f89018 o2hb_setup_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4900035b o2hb_stop_all_regions +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x521e0726 o2net_send_message_vec +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x81a17396 mlog_and_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa82a8645 o2nm_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa87bc9e7 o2nm_configured_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xae808bac o2net_register_handler +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xb7c9736b o2hb_unregister_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xb7e600fa o2nm_node_put +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xbaeb4700 o2hb_check_node_heartbeating_from_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xd60f2c6c o2hb_check_local_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf1a5611d o2net_unregister_handler_list +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf56c2017 mlog_not_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xfdb7f09d o2nm_get_node_by_ip +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x63c1fb00 dlm_register_domain +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x788bedf6 dlm_unregister_domain +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x7a1211f8 dlm_setup_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xbe0ba09a dlmlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xc998900c dlm_register_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xcbc0b1f5 dlm_print_one_lock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd7ba575e dlm_errmsg +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd8fa57a6 dlm_unregister_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xf02781f1 dlmunlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xfb86b96f dlm_errname +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0562c415 ocfs2_cluster_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0a831369 ocfs2_stack_glue_unregister +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0e27f909 ocfs2_dlm_lock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x21db5b88 ocfs2_cluster_disconnect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4a1f6fe9 ocfs2_cluster_connect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4d3af7fa ocfs2_cluster_hangup +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x81c85a68 ocfs2_dlm_lock_status +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x91fab465 ocfs2_dlm_lvb +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x9456503c ocfs2_stack_glue_register +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x963932a3 ocfs2_stack_glue_set_locking_protocol +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xa7d5c1c0 ocfs2_dlm_unlock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xd066711e ocfs2_dlm_dump_lksb +EXPORT_SYMBOL_GPL lib/lzo/lzo_compress 0x2e1d43cf lzo1x_1_compress +EXPORT_SYMBOL_GPL lib/lzo/lzo_decompress 0x2a1538ca lzo1x_decompress_safe +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x300d7e57 free_rs +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x6fbb3bd9 init_rs_non_canonical +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xabda1e2e decode_rs16 +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xb050f329 init_rs +EXPORT_SYMBOL_GPL net/802/garp 0x5390e9aa garp_init_applicant +EXPORT_SYMBOL_GPL net/802/garp 0xacdaa5be garp_unregister_application +EXPORT_SYMBOL_GPL net/802/garp 0xc459ed0b garp_request_leave +EXPORT_SYMBOL_GPL net/802/garp 0xc50c64d5 garp_register_application +EXPORT_SYMBOL_GPL net/802/garp 0xd851a0c1 garp_uninit_applicant +EXPORT_SYMBOL_GPL net/802/garp 0xed262279 garp_request_join +EXPORT_SYMBOL_GPL net/802/stp 0x8367ce99 stp_proto_register +EXPORT_SYMBOL_GPL net/802/stp 0xb0987f16 stp_proto_unregister +EXPORT_SYMBOL_GPL net/ax25/ax25 0xac93ae05 ax25_bcast +EXPORT_SYMBOL_GPL net/ax25/ax25 0xaeb7451e ax25_defaddr +EXPORT_SYMBOL_GPL net/ax25/ax25 0xc4345232 ax25_register_pid +EXPORT_SYMBOL_GPL net/bluetooth/bluetooth 0x3be999e7 bt_class +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x09c5ed3c tfrc_tx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x0a487ea5 tfrc_calc_x +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x106fe6d3 tfrc_tx_hist_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x50997d99 tfrc_lh_update_i_mean +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x69ec5731 tfrc_tx_hist_add +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x6a083f17 tfrc_rx_hist_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x6c252d29 tfrc_calc_x_reverse_lookup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x8352c487 tfrc_rx_hist_add_packet +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x839a08a3 tfrc_rx_handle_loss +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x902206f0 tfrc_lh_cleanup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x92285650 tfrc_rx_hist_alloc +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xae24ff74 tfrc_rx_hist_duplicate +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xc612a5b6 tfrc_rx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xf5adfac6 tfrc_lh_interval_add +EXPORT_SYMBOL_GPL net/dccp/dccp 0x00d51b1c ccid_unregister +EXPORT_SYMBOL_GPL net/dccp/dccp 0x03e42f30 dccp_setsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x0f76d3db dccp_parse_options +EXPORT_SYMBOL_GPL net/dccp/dccp 0x0fadbd93 dccp_poll +EXPORT_SYMBOL_GPL net/dccp/dccp 0x11aefd84 dccp_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x12575686 dccp_rcv_state_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0x1d99d49a dccp_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0x2f4381af ccid_hc_rx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3b2bd61e dccp_feat_change_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3b3c0b1b dccp_feat_clean +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3fbd3a43 dccp_ctl_make_reset +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4161105e dccp_sync_mss +EXPORT_SYMBOL_GPL net/dccp/dccp 0x440f04c7 ccid_register +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4e79c81c dccp_create_openreq_child +EXPORT_SYMBOL_GPL net/dccp/dccp 0x54329e84 dccp_feat_clone +EXPORT_SYMBOL_GPL net/dccp/dccp 0x56ea266a dccp_state_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x5d5e3ee7 dccp_feat_confirm_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0x5f084755 dccp_death_row +EXPORT_SYMBOL_GPL net/dccp/dccp 0x674cb8ee dccp_shutdown +EXPORT_SYMBOL_GPL net/dccp/dccp 0x753be288 dccp_recvmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0x7d683c5d dccp_reqsk_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0x80c96bff compat_dccp_setsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x82c53ec9 dccp_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0x83da9cb1 dccp_getsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x86be7924 dccp_packet_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8a838f1c ccid_hc_rx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b7d8caf dccp_statistics +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8e454528 dccp_hashinfo +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9d6a3846 dccp_orphan_count +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9f60cdb4 dccp_insert_option_elapsed_time +EXPORT_SYMBOL_GPL net/dccp/dccp 0xa04710f0 dccp_close +EXPORT_SYMBOL_GPL net/dccp/dccp 0xab6cc89b dccp_set_state +EXPORT_SYMBOL_GPL net/dccp/dccp 0xab901309 dccp_make_response +EXPORT_SYMBOL_GPL net/dccp/dccp 0xb170f1c7 dccp_child_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0xb4c6a335 dccp_check_req +EXPORT_SYMBOL_GPL net/dccp/dccp 0xb74319bc dccp_destroy_sock +EXPORT_SYMBOL_GPL net/dccp/dccp 0xba716f47 ccid_hc_tx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbc2141a5 dccp_insert_option_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe095194 compat_dccp_getsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe4cf010 dccp_feat_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbf6b58ba dccp_feat_change +EXPORT_SYMBOL_GPL net/dccp/dccp 0xca7f11ff inet_dccp_listen +EXPORT_SYMBOL_GPL net/dccp/dccp 0xcd4f3d04 dccp_rcv_established +EXPORT_SYMBOL_GPL net/dccp/dccp 0xd8f0422e dccp_insert_option +EXPORT_SYMBOL_GPL net/dccp/dccp 0xdc4d1fb7 dccp_reqsk_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0xde10789c dccp_sendmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0xe7ed85f8 ccid_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0xecf24a7c dccp_ioctl +EXPORT_SYMBOL_GPL net/dccp/dccp 0xee176740 dccp_send_sync +EXPORT_SYMBOL_GPL net/dccp/dccp 0xef0e188d ccid_hc_tx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf15b541a dccp_connect +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf271c7ea dccp_done +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf745b069 dccp_disconnect +EXPORT_SYMBOL_GPL net/dccp/dccp 0xfd53d694 dccp_init_sock +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x1db2e318 dccp_v4_do_rcv +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x337650da dccp_v4_conn_request +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x691faebe dccp_v4_request_recv_sock +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x6ed7a1f5 dccp_v4_connect +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x9433529a dccp_invalid_packet +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xa2eb0e1d dccp_v4_send_check +EXPORT_SYMBOL_GPL net/ieee80211/ieee80211 0x38729481 ieee80211_rx_any +EXPORT_SYMBOL_GPL net/ipv4/ipvs/ip_vs 0xe6476b4a net_vs_ctl_path +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x6d40a921 need_ipv4_conntrack +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0xdbb115c4 nf_nat_seq_adjust_hook +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x07ae60b6 nf_nat_proto_in_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x4046e7ee nf_nat_icmp_reply_translation +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x551a642f nf_nat_proto_find_get +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x59c3072f nf_nat_proto_unique_tuple +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x7ce95842 nf_nat_proto_range_to_nlattr +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x80c9e3b2 nf_nat_packet +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x94a08134 nf_nat_proto_nlattr_to_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xdad709e0 nf_nat_proto_put +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat_proto_gre 0x636b12c8 nf_nat_need_gre +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x1ab3ff31 tcp_vegas_get_info +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x20175b96 tcp_vegas_pkts_acked +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x3a92e57d tcp_vegas_state +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x5ab027a0 tcp_vegas_init +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xd82d99d0 tcp_vegas_cwnd_event +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x08a3e5d1 net_ipv6_ctl_path +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x0cac312c ip6_dst_blackhole +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x2fb257f7 inet6_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3b0e3627 ip6_sk_dst_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x47d8520b ip6_dst_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x5851c92a inet6_destroy_sock +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x5d53a85f inet6_csk_search_req +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x7bcd9f81 inet6_csk_addr2sockaddr +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x7c544e2b inet6_csk_xmit +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xabb17bfe ipv6_find_tlv +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xaf8b8bb5 ipv6_dup_options +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xaf8de9d0 fl6_sock_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xb7a882b5 inet6_csk_bind_conflict +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xcebd956b inet6_sk_rebuild_header +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xd5df0d23 ip6_local_out +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xe100980b ipv6_opt_accepted +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x7d306376 ieee80211_iterate_active_interfaces +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0xa13cc5ce ieee80211_iterate_active_interfaces_atomic +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x02b360a1 __nf_ct_kill_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x041013fd nf_conntrack_lock +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x04123954 __nf_conntrack_confirm +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x045072cd nf_ct_port_nla_policy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x06cfbe0a nf_ct_l4proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0e091ecc nf_ct_l3proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0ea4f6dc nf_ct_iterate_cleanup +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1283d711 nf_ct_expect_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x15c10b0b nf_conntrack_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1619842c nf_conntrack_l4proto_udp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x19ff5837 nf_ct_expect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1be68013 nf_ct_port_tuple_to_nlattr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x242fe6ae nf_conntrack_l4proto_udp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x248d7f93 nf_conntrack_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x25e649f2 nf_ct_log_invalid +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2b9580cb nf_conntrack_flush +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2debb004 nf_ct_get_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x34d23e2e __nf_conntrack_helper_find_byname +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3609de81 nf_conntrack_count +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x374308f5 nf_ct_get_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38630158 nf_conntrack_tuple_taken +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38c9440b nf_ct_extend_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3f5b1415 nf_ct_port_nlattr_to_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x40387ccf __nf_ct_event_cache_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x40dd9bb5 print_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x45e3c6ac nf_ct_expect_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x474327c1 __nf_ct_expect_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4d17d977 nf_ct_unexpect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x501d6b4b nf_conntrack_l4proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x580acbf5 nf_conntrack_l4proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5e964972 nf_ct_l3protos +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x67219ea3 nf_ct_expect_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6cd91ee0 per_cpu__nf_conntrack_ecache +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6d12bbae nf_conntrack_l3proto_generic +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6e224a7a need_conntrack +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x700d1765 seq_print_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x72836f4a nf_conntrack_free +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x77aadb54 nf_conntrack_alter_reply +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x78f9b710 nf_ct_l3proto_try_module_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x79c9e83c nf_ct_helper_ext_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x79ca2e53 nf_ct_expect_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x809d9b38 __nf_ct_refresh_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x82217ca6 nf_conntrack_l3proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x882ba59d nf_ct_l4proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8f3646d7 nf_ct_expect_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8ffe7e89 nf_conntrack_htable_size +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x90ff6c9f nf_ct_invert_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x93241c9c nf_ct_invert_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x977f46d0 nf_conntrack_helper_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9c2f9624 nf_ct_unlink_expect +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9f326ae9 __nf_ct_l4proto_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa6f62ec0 nf_conntrack_set_hashsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xace98352 nf_conntrack_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaf57e66f nf_ct_extend_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb13d7e38 nf_ct_l3proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb602c57e nf_ct_l3proto_module_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb76accc2 __nf_conntrack_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb89ef25e nf_conntrack_in +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb9e30797 nf_ct_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbb4b7871 nf_conntrack_tcp_update +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbc887e16 nf_ct_expect_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbd7daec1 nf_ct_expect_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbe3f2939 nf_conntrack_checksum +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc044befe nf_ct_free_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc18ac88d nf_ct_expect_hsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc35a7a3e nf_conntrack_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc7b64d79 nf_conntrack_hash_insert +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcbf7fd2a nf_conntrack_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcdaaa7ae __nf_ct_helper_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd50a96a2 nf_ct_alloc_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd7c683c4 nf_conntrack_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd9efb053 nf_ct_deliver_cached_events +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xdbb856ac nf_conntrack_l4proto_tcp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xdd70187f nf_conntrack_helper_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe98e342e nf_conntrack_l4proto_tcp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xec8beba6 nf_ct_expect_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf67f4947 nf_conntrack_l3proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf9ae81a1 nf_conntrack_max +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfa169dac nf_conntrack_untracked +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfb839673 nf_ct_remove_expectations +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_amanda 0x6025a5a7 nf_nat_amanda_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_ftp 0xf62878b8 nf_nat_ftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x12a1139f nat_q931_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x264c0cf3 get_h225_addr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x3ea43ec4 set_h245_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x642009c3 set_h225_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x6e3ee0f2 set_sig_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x7be3b6fd set_ras_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x9011501f nat_callforwarding_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xb96c2ad4 nat_t120_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xbcdfad0b nat_h245_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xcf417210 nat_rtp_rtcp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_irc 0x814ae120 nf_nat_irc_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x24d99602 nf_nat_pptp_hook_exp_gre +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x4ebfbaad nf_nat_pptp_hook_expectfn +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x5e95cfd0 nf_nat_pptp_hook_outbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xdc68232a nf_nat_pptp_hook_inbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x05f8e58c nf_ct_gre_keymap_destroy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x6f59d77c nf_ct_gre_keymap_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x13169b79 ct_sip_parse_request +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x23c7d1f5 nf_nat_sdp_session_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x3c2058a6 ct_sip_parse_numerical_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x42edf11a nf_nat_sdp_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x48d65cde nf_nat_sip_expect_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5333cb69 ct_sip_parse_header_uri +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5343611e ct_sip_get_sdp_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x56ad8f6e ct_sip_parse_address_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x669b6845 nf_nat_sip_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x66d81dae nf_nat_sdp_media_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x681bd415 nf_nat_sdp_port_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf8b610ea ct_sip_get_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_tftp 0x7dda2926 nf_nat_tftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x00ec2d6b nfnetlink_unicast +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x69e5b174 nfnetlink_send +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xc1b8d12c nfnetlink_subsys_register +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xcd07a4ae nfnetlink_subsys_unregister +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xeca95329 nfnetlink_has_listeners +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x16901a0e xt_compat_match_offset +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x21e221d6 xt_proto_fini +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x2baf1084 xt_compat_target_from_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x2f32d4da xt_compat_lock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x3ad8a68d xt_request_find_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x50d7f1aa xt_compat_calc_jump +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x5643ed60 xt_proto_init +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x6239c30f xt_compat_add_offset +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x63f05053 xt_find_revision +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x65c90716 xt_register_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x69033eb4 xt_compat_match_to_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x696109ee xt_compat_flush_offsets +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7bbb50ff xt_table_unlock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7e38ad84 xt_check_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7eac0af4 xt_compat_target_offset +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x8f6ae92a xt_compat_target_to_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xa4bdc3db xt_find_table_lock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xaa30704f xt_compat_match_from_user +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xaf93611a xt_check_match +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xdbaf6e11 xt_unregister_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xe53911a2 xt_compat_unlock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xe960c06e xt_replace_table +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xc177bee0 xt_rateest_put +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xdb8418cc xt_rateest_lookup +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x83b2e956 register_rfkill_notifier +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x86c722f8 rfkill_epo +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0xa6f4320d unregister_rfkill_notifier +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0x27a3a70d rxrpc_register_security +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0x5a021c03 rxrpc_unregister_security +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x03fe44b3 rpc_clone_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1058549b rpc_call_sync +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x11ac9869 xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x169c6486 rpc_delay +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1f5f6a05 xprt_disconnect_done +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x205032c2 svc_xprt_enqueue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x24cd585a xprt_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x263fe740 xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x26949256 rpc_force_rebind +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x26ce108c xprt_release_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x27ec7fa9 rpc_proc_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2a57ffbe rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2aa17774 rpc_free_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2b0dfc31 rpc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2ba78ca4 rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2fe3b08c rpc_run_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x31a89d59 rpc_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x325a923d xprt_release_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x35240e07 svc_print_addr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3a945a3b xprt_register_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3eed5dee rpc_call_start +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4a1131e8 rpcauth_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4a5a0457 svc_xprt_put +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4bd5692f xprt_unregister_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4cc6cbc2 rpc_exit_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x51655ee5 xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x53445f68 nlm_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x550547a3 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bd26000 rpc_proc_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5dc49f3d rpc_peeraddr2str +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x664e1a97 svc_close_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x686fb7d0 rpc_print_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x69af4b4e rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6a8827b7 xprt_write_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c34a330 rpc_restart_call +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c5304c5 rpcb_getport_sync +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x731aff9f rpc_malloc +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7444f38c rpc_shutdown_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x776cad69 svc_reg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7de53067 rpc_init_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x860a671d rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x86ca4bb0 svc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8eeda8c0 rpc_lookup_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x916c72c1 rpc_put_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9786f2bd rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9c1283f7 rpcauth_init_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9f672042 put_rpccred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa02d5818 svc_xprt_names +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa6797a3e rpc_wake_up_next +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaa6a0927 rpc_peeraddr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xabf8191e svc_xprt_init +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xace7fbc6 rpcauth_init_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf5bf6ef nfs_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb0697b60 rpc_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb0f80ad9 rpc_bind_new_program +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb387b246 rpc_wake_up_status +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb7a91ea0 rpc_sleep_on +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbab68e43 rpc_alloc_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbb529870 svc_addsock +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbcedeaeb rpcb_getport_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf00ee4a rpcauth_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf9d1b96 nfsd_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc12435e3 rpc_calc_rto +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc36ca95f svc_unreg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc38e4545 rpc_call_null +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc828c2ec xprt_release_rqst_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcc05fe03 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xceade5b3 svc_xprt_received +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd46c9f8f svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd5185c36 rpc_setbufsize +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd82c728e rpc_init_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd9f115c6 xprt_reserve_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdab91036 rpc_killall_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdeb2a2ab xdr_skb_read_bits +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdf3ab43e xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe79dbbd3 xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xea19d536 csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedd1ba52 rpc_wake_up +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xee56922d svc_create_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xeeacab69 rpc_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf0efaba5 rpcauth_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf28441b5 xprt_adjust_cwnd +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf3522702 xprt_complete_rqst +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf5a0cd0a rpc_call_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf7ea5937 __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf9d1164c rpc_free +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfb8ffb15 svc_find_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfc088b6d xprt_lookup_rqst +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x77a3e570 ipcomp_output +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x8f004b13 ipcomp_init_state +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x9fed1041 ipcomp_destroy +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xce7b93ad ipcomp_input +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0510f4ab snd_soc_dapm_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0587f358 snd_soc_test_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x090c2393 snd_soc_register_card +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0fbe82ad snd_soc_free_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x153e5b05 snd_soc_dapm_stream_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x154e6e57 snd_soc_dapm_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1d1ae7e3 snd_soc_cnew +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x20451b67 snd_soc_dai_set_tristate +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x27069147 snd_soc_dapm_enable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3807b23f snd_soc_put_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3e1a1350 snd_soc_dapm_connect_input +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3f324e2f snd_soc_dapm_new_controls +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x4224382e snd_soc_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x428d7758 dapm_reg_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5249a7c8 snd_soc_get_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x60138880 snd_soc_dapm_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x69d05a8d snd_soc_update_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x717cf8a7 snd_soc_set_runtime_hwparams +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x85b7295d snd_soc_new_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x86107b2b snd_soc_info_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x86d42c93 snd_soc_new_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8ca9319b snd_soc_dapm_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x90a67d96 snd_soc_dapm_sync +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x94f12da4 snd_soc_dapm_disable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa27d8ecb snd_soc_dai_set_fmt +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa306bd9b snd_soc_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa3ffebc2 snd_soc_get_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb8c2f6a6 snd_soc_dapm_add_routes +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbc82211d snd_soc_info_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc3cb51dd snd_soc_info_volsw_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc605c1b0 snd_soc_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc912c965 snd_soc_dai_set_sysclk +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc9b1fe35 snd_soc_put_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xcc68a02f snd_soc_dai_set_clkdiv +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd260363f snd_soc_free_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd7adffd5 snd_soc_info_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdaafff6d snd_soc_dapm_free +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdbc367e2 snd_soc_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe1d48e74 snd_soc_dai_set_tdm_slot +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe4292769 snd_soc_dapm_new_widgets +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe4be33fa snd_soc_info_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe9f49e1d snd_soc_dapm_new_control +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf0ad6870 snd_soc_info_enum_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf2ab703f snd_soc_dai_set_pll +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf8309917 snd_soc_dai_digital_mute +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfe01e555 snd_soc_dapm_get_pin_status +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x0d93d0e1 tlsf_create_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x1584fdb9 tlsf_destroy_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x2c383ca4 tlsf_calloc +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x54064cb9 tlsf_get_used_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x60d233a6 tlsf_malloc +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xbe77d1fe tlsf_get_total_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xe6acc368 tlsf_free +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x02500586 thinkpad_ec_unlock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x0dc7484e thinkpad_ec_try_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x2552d213 thinkpad_ec_lock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x3dbfef12 thinkpad_ec_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x8dbbd831 thinkpad_ec_invalidate +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xa3042743 thinkpad_ec_prefetch_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xfb5aa917 thinkpad_ec_try_lock +EXPORT_SYMBOL_GPL vmlinux 0x001d97c6 crypto_hash_type +EXPORT_SYMBOL_GPL vmlinux 0x00566d8f inotify_get_cookie +EXPORT_SYMBOL_GPL vmlinux 0x006d7cad srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00b8ecf8 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x01848a8e local_apic_timer_c2_ok +EXPORT_SYMBOL_GPL vmlinux 0x01a4ea6d unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x01b2e09f tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x01e1a8de kgdb_breakpoint +EXPORT_SYMBOL_GPL vmlinux 0x028e6f97 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x02a9ac14 user_update +EXPORT_SYMBOL_GPL vmlinux 0x02b029b5 relay_buf_full +EXPORT_SYMBOL_GPL vmlinux 0x02cb1b8a __cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0x02ccea56 lock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x0343bdf1 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x0361b93b xenbus_map_ring_valloc +EXPORT_SYMBOL_GPL vmlinux 0x03fe2cca flush_work +EXPORT_SYMBOL_GPL vmlinux 0x0427901f transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0x0447d159 raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0x04486e88 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x0454860a blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0x04566c7f init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x04c3f2c1 gnttab_empty_grant_references +EXPORT_SYMBOL_GPL vmlinux 0x04e628cd leds_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x04ea8706 __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0x054e550b kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x05e835d3 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0x064db9a5 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x06d222f8 device_resume +EXPORT_SYMBOL_GPL vmlinux 0x074a3aab device_initialize +EXPORT_SYMBOL_GPL vmlinux 0x07a708b2 pci_find_next_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x07b52e38 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x07bc9dae xenbus_grant_ring +EXPORT_SYMBOL_GPL vmlinux 0x07ff4aea xenbus_scanf +EXPORT_SYMBOL_GPL vmlinux 0x0871083f sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x08a3fe89 spi_new_device +EXPORT_SYMBOL_GPL vmlinux 0x091eb9b4 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x0962349a uhci_check_and_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x09b5fba5 user_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x0b42ff5b bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0x0b724197 xfrm_audit_state_icvfail +EXPORT_SYMBOL_GPL vmlinux 0x0bc151e5 klist_init +EXPORT_SYMBOL_GPL vmlinux 0x0c17e274 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x0c4717f7 srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0x0c6fdf20 zap_vma_ptes +EXPORT_SYMBOL_GPL vmlinux 0x0d1cf84e tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0x0d20656a class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0d5ce501 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x0de6697e led_trigger_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0e10d0df fb_deferred_io_open +EXPORT_SYMBOL_GPL vmlinux 0x0e5cdd79 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0x0ec210b8 xen_start_info +EXPORT_SYMBOL_GPL vmlinux 0x0ef84c65 hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x0fe2d570 xenbus_directory +EXPORT_SYMBOL_GPL vmlinux 0x0fed7cc4 queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x10151db2 inotify_remove_watch_locked +EXPORT_SYMBOL_GPL vmlinux 0x1050bc52 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x109294b5 inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0x10b10ab3 pci_find_ext_capability +EXPORT_SYMBOL_GPL vmlinux 0x115b72be find_vpid +EXPORT_SYMBOL_GPL vmlinux 0x1180cd29 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0x11862c34 __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x11fcdf4d device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0x12463b2f crypto_register_instance +EXPORT_SYMBOL_GPL vmlinux 0x124f2056 crypto_get_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x1251d30f call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x12721e94 tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0x12e285ec is_uv_system +EXPORT_SYMBOL_GPL vmlinux 0x12ff7edb tty_find_polling_driver +EXPORT_SYMBOL_GPL vmlinux 0x138b472b __percpu_alloc_mask +EXPORT_SYMBOL_GPL vmlinux 0x13afaf8f inet_diag_unregister +EXPORT_SYMBOL_GPL vmlinux 0x13b2a946 register_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x13d66968 securityfs_remove +EXPORT_SYMBOL_GPL vmlinux 0x145eebd0 device_power_up +EXPORT_SYMBOL_GPL vmlinux 0x146bee29 spi_register_master +EXPORT_SYMBOL_GPL vmlinux 0x149db923 selinux_string_to_sid +EXPORT_SYMBOL_GPL vmlinux 0x14d5425d bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0x14f12eb5 audit_log_untrustedstring +EXPORT_SYMBOL_GPL vmlinux 0x1534ba7a bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1598dc9d unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x1598ef3e devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x15b0606e e820_any_mapped +EXPORT_SYMBOL_GPL vmlinux 0x15cd14db crypto_unregister_template +EXPORT_SYMBOL_GPL vmlinux 0x166b6ad5 spi_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x168f5aac tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x16a5b4c8 key_type_user +EXPORT_SYMBOL_GPL vmlinux 0x16b6e800 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x16f7ca84 xenbus_unmap_ring_vfree +EXPORT_SYMBOL_GPL vmlinux 0x178d5019 page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x1800d735 debugfs_remove_recursive +EXPORT_SYMBOL_GPL vmlinux 0x187551b2 spi_write_then_read +EXPORT_SYMBOL_GPL vmlinux 0x1878f62b edac_err_assert +EXPORT_SYMBOL_GPL vmlinux 0x1895293e crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0x18d53420 kgdb_register_io_module +EXPORT_SYMBOL_GPL vmlinux 0x18f83fab gnttab_grant_foreign_access_ref +EXPORT_SYMBOL_GPL vmlinux 0x19b179d0 fib_rules_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1a10607f unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x1a83d250 elv_register +EXPORT_SYMBOL_GPL vmlinux 0x1a938737 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x1aad289d __xenbus_register_frontend +EXPORT_SYMBOL_GPL vmlinux 0x1acda5b2 atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1b4b86ac fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0x1b9aca3f jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x1cac9211 get_driver +EXPORT_SYMBOL_GPL vmlinux 0x1dd70100 dmi_walk +EXPORT_SYMBOL_GPL vmlinux 0x1ddf95ba sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0x1de5332b xenbus_watch_path +EXPORT_SYMBOL_GPL vmlinux 0x1e053cb0 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0x1e7bbcb3 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x1eaa9c56 crypto_hash_walk_done +EXPORT_SYMBOL_GPL vmlinux 0x1eb9516e round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x1ebae765 spi_sync +EXPORT_SYMBOL_GPL vmlinux 0x1ededf6e cpufreq_cpu_put +EXPORT_SYMBOL_GPL vmlinux 0x1f5c95f5 platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x1f696624 pci_unblock_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x1f8ec1b3 acpi_get_pci_rootbridge_handle +EXPORT_SYMBOL_GPL vmlinux 0x1f9a0fbf hpet_unregister_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x1fcece42 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x2029099d inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0x20577ea2 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x2068f3e5 cpuidle_enable_device +EXPORT_SYMBOL_GPL vmlinux 0x2074c42e bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x20b82470 hpet_register_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x20bc3470 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x21d192f9 input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0x21db7fc8 xenbus_unmap_ring +EXPORT_SYMBOL_GPL vmlinux 0x21f9011b transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x221c727e inotify_init +EXPORT_SYMBOL_GPL vmlinux 0x2240d211 unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x22472bf4 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x2265d0e4 debugfs_create_blob +EXPORT_SYMBOL_GPL vmlinux 0x226f4e93 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0x2296c00d crypto_attr_u32 +EXPORT_SYMBOL_GPL vmlinux 0x22a4c758 class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x22d50fc4 vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0x2305365b register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x23864ce7 cpuset_mem_spread_node +EXPORT_SYMBOL_GPL vmlinux 0x2396620c seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0x23bbb214 devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x24196ba2 init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x2447533c ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0x24c7698a xenbus_write +EXPORT_SYMBOL_GPL vmlinux 0x24eb7e32 leds_list +EXPORT_SYMBOL_GPL vmlinux 0x2502a974 pci_find_next_capability +EXPORT_SYMBOL_GPL vmlinux 0x251e6fd6 input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0x2545c170 unregister_xenbus_watch +EXPORT_SYMBOL_GPL vmlinux 0x257e29cf spi_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x25f141e7 driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x266ad049 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x26a8bd98 input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x26b712d3 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0x26d00d08 hvc_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x2714c98c klist_del +EXPORT_SYMBOL_GPL vmlinux 0x27bd158c unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x27dc68f1 __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0x28088f0f pv_time_ops +EXPORT_SYMBOL_GPL vmlinux 0x2832f007 blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x28b5e778 rtc_read_time +EXPORT_SYMBOL_GPL vmlinux 0x28d664ff __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x28e23139 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x297231ba agp_remove_bridge +EXPORT_SYMBOL_GPL vmlinux 0x2a31b0dc mmput +EXPORT_SYMBOL_GPL vmlinux 0x2a678a13 __suspend_report_result +EXPORT_SYMBOL_GPL vmlinux 0x2a9c0745 crypto_lookup_template +EXPORT_SYMBOL_GPL vmlinux 0x2b24e4a0 uv_blade_info +EXPORT_SYMBOL_GPL vmlinux 0x2b3e8dfb platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0x2b9f8e23 nf_net_ipv4_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x2bc8c51b nf_unregister_afinfo +EXPORT_SYMBOL_GPL vmlinux 0x2c13521d register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x2c16ed76 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x2c203645 crypto_dequeue_request +EXPORT_SYMBOL_GPL vmlinux 0x2c3e556c vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0x2cb3d996 inotify_find_watch +EXPORT_SYMBOL_GPL vmlinux 0x2d088e2b led_trigger_set +EXPORT_SYMBOL_GPL vmlinux 0x2d59c954 edac_handlers +EXPORT_SYMBOL_GPL vmlinux 0x2d9f2ce3 sched_clock_idle_wakeup_event +EXPORT_SYMBOL_GPL vmlinux 0x2db5758a register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x2e6e7aee smp_ops +EXPORT_SYMBOL_GPL vmlinux 0x2e71723a skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0x2e998f83 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x2eafd72f sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x2ec92012 scatterwalk_copychunks +EXPORT_SYMBOL_GPL vmlinux 0x2ece9f66 __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x2ef539b7 copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0x2f1d6c37 led_trigger_show +EXPORT_SYMBOL_GPL vmlinux 0x2ff30af9 crypto_alloc_instance +EXPORT_SYMBOL_GPL vmlinux 0x30e76706 tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0x30ec9492 dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0x319791c0 rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0x31d53891 nf_unregister_queue_handlers +EXPORT_SYMBOL_GPL vmlinux 0x325e677c gnttab_grant_foreign_transfer_ref +EXPORT_SYMBOL_GPL vmlinux 0x3441c3d6 gpio_set_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x34817801 cpuidle_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0x359f7313 pci_enable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0x35ba78ac user_match +EXPORT_SYMBOL_GPL vmlinux 0x35c8d41a fib_rules_lookup +EXPORT_SYMBOL_GPL vmlinux 0x361e2bcc save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x3621a014 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x36288501 inet6_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x362e23ec call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x369860f1 mmu_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0x370290af skb_morph +EXPORT_SYMBOL_GPL vmlinux 0x370acd10 tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x37a12431 inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0x37b8e076 __mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x37e37f25 inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0x385c571d cpufreq_register_governor +EXPORT_SYMBOL_GPL vmlinux 0x3895233b srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x38fc47e5 platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0x3a0edd1f input_class +EXPORT_SYMBOL_GPL vmlinux 0x3a26cd2d inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x3a311560 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x3a7bdbf8 sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x3a7f8b86 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x3a865912 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0x3acbd18d posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0x3af3d91a tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0x3b1446fb platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0x3b4ec75d platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x3bc12515 class_find_device +EXPORT_SYMBOL_GPL vmlinux 0x3bc13dac devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x3be7af02 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x3c5b8103 debugfs_create_u16 +EXPORT_SYMBOL_GPL vmlinux 0x3c942368 profile_event_unregister +EXPORT_SYMBOL_GPL vmlinux 0x3cd06035 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x3cfedb3f register_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x3d0b02ec sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x3d29867d per_cpu__gdt_page +EXPORT_SYMBOL_GPL vmlinux 0x3d5f392d acpi_os_unmap_memory +EXPORT_SYMBOL_GPL vmlinux 0x3d7ea99a gnttab_grant_foreign_transfer +EXPORT_SYMBOL_GPL vmlinux 0x3d86deb4 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x3e31a810 platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0x3efb35c9 get_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0x3f238101 dcookie_register +EXPORT_SYMBOL_GPL vmlinux 0x3f641ed4 fb_deferred_io_fsync +EXPORT_SYMBOL_GPL vmlinux 0x3f84d4c9 gnttab_release_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x3f8d883a swiotlb_sync_single_range_for_cpu +EXPORT_SYMBOL_GPL vmlinux 0x4077d573 rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0x409cf031 acpi_ec_remove_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x40c39cff acpi_ec_add_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x4181a7aa xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0x41f3cc90 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x424acc6d scatterwalk_done +EXPORT_SYMBOL_GPL vmlinux 0x425508d3 stop_machine +EXPORT_SYMBOL_GPL vmlinux 0x4270efa2 xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0x42bd2bbe free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x42d7fd00 pciserial_remove_ports +EXPORT_SYMBOL_GPL vmlinux 0x42fbc4c8 crypto_attr_alg +EXPORT_SYMBOL_GPL vmlinux 0x432969ec devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0x432fd7f6 __gpio_set_value +EXPORT_SYMBOL_GPL vmlinux 0x44a65d5c lock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x44eb5026 sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x454a14a4 transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0x457594fa crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x45ae553d tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0x45bf1ff3 crypto_inc +EXPORT_SYMBOL_GPL vmlinux 0x45d14bdf hypercall_page +EXPORT_SYMBOL_GPL vmlinux 0x460f31aa rodata_test_data +EXPORT_SYMBOL_GPL vmlinux 0x46e3d644 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x4712e4ca xenbus_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0x47229b5c gpio_request +EXPORT_SYMBOL_GPL vmlinux 0x480b145e inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0x4900e0fa __audit_inode_child +EXPORT_SYMBOL_GPL vmlinux 0x499043d3 crypto_init_queue +EXPORT_SYMBOL_GPL vmlinux 0x49a8e75f xenbus_free_evtchn +EXPORT_SYMBOL_GPL vmlinux 0x4a11a4fb bind_virq_to_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0x4a1e706f put_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x4a227f2f simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x4a7e30d9 marker_probe_unregister_private_data +EXPORT_SYMBOL_GPL vmlinux 0x4aaa9d65 fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0x4ab25168 spi_add_device +EXPORT_SYMBOL_GPL vmlinux 0x4aeaf238 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x4b762828 start_thread +EXPORT_SYMBOL_GPL vmlinux 0x4bc83227 sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x4bdcd7c2 blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0x4c6ed311 bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0x4c759827 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x4caa501d pci_cleanup_aer_uncorrect_error_status +EXPORT_SYMBOL_GPL vmlinux 0x4d22afcb __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0x4d4edc3d xenbus_bind_evtchn +EXPORT_SYMBOL_GPL vmlinux 0x4e7e7923 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x4ea6ff75 rtc_class_close +EXPORT_SYMBOL_GPL vmlinux 0x4eb25b04 vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0x4ec6a70b device_create +EXPORT_SYMBOL_GPL vmlinux 0x4eee4bc0 crypto_tfm_in_queue +EXPORT_SYMBOL_GPL vmlinux 0x4f9cb883 sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x4fc28000 macvlan_handle_frame_hook +EXPORT_SYMBOL_GPL vmlinux 0x4fd86323 inotify_add_watch +EXPORT_SYMBOL_GPL vmlinux 0x500e47f3 sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0x50156d61 map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x50b319ce cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0x50b67174 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x50e7193a __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x514aa93b tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0x518c2fc6 hpet_rtc_dropped_irq +EXPORT_SYMBOL_GPL vmlinux 0x51921120 default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0x51a4c094 unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x51dd6488 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x52d111ea pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x53039405 pci_block_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x53986488 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x53c2d13a platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0x541dc502 rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x546ea25e destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x5493a797 preempt_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0x54e01330 inotify_destroy +EXPORT_SYMBOL_GPL vmlinux 0x55526907 xen_features +EXPORT_SYMBOL_GPL vmlinux 0x56398615 mark_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5641485b tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x567e7a9a rtc_irq_unregister +EXPORT_SYMBOL_GPL vmlinux 0x56b79a74 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0x56c05c3d sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0x575c5f94 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0x5779d445 xenbus_exists +EXPORT_SYMBOL_GPL vmlinux 0x579e0bf5 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x57fcd32d __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0x58013efe class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0x58a200ee uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0x58ae69b9 tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x595cbe8f driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x5975549a debugfs_create_u64 +EXPORT_SYMBOL_GPL vmlinux 0x597f3bc3 marker_get_private_data +EXPORT_SYMBOL_GPL vmlinux 0x5a2b1b67 gnttab_free_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x5ac7273e rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0x5af03a28 gnttab_claim_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x5b392b04 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0x5b3be9a1 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0x5b5ff40b power_supply_changed +EXPORT_SYMBOL_GPL vmlinux 0x5bb44a32 klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x5bc48f8b get_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x5bfc03c3 unregister_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5cf03dd7 security_inode_permission +EXPORT_SYMBOL_GPL vmlinux 0x5cfcf0f1 percpu_free +EXPORT_SYMBOL_GPL vmlinux 0x5d0f6f57 kbd_table +EXPORT_SYMBOL_GPL vmlinux 0x5d366dec gnttab_cancel_free_callback +EXPORT_SYMBOL_GPL vmlinux 0x5d730e7b raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5dd67618 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5e916cdb platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x5eb05848 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x5f10e819 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0x5f2da8c4 check_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5f3bc2ce input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x5f408bac klist_next +EXPORT_SYMBOL_GPL vmlinux 0x5f586bc1 relay_file_operations +EXPORT_SYMBOL_GPL vmlinux 0x5fd23a46 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0x5fe069c2 unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x5fea940b hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x6030e181 crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x6091797f synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x60a13e90 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x61361cfd __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x614b116b device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x622e683b bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0x62843a48 class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x629637b6 platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0x6326f4df skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0x633bba21 inet6_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x634cc62d xfrm_audit_state_add +EXPORT_SYMBOL_GPL vmlinux 0x6357ca29 fib_rules_register +EXPORT_SYMBOL_GPL vmlinux 0x63a4f36e inet_diag_register +EXPORT_SYMBOL_GPL vmlinux 0x63ae27d6 add_nops +EXPORT_SYMBOL_GPL vmlinux 0x643f782a tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0x6485d13c devres_add +EXPORT_SYMBOL_GPL vmlinux 0x65ccb6f0 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x65d6d0f0 gpio_direction_input +EXPORT_SYMBOL_GPL vmlinux 0x660f5598 sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0x6610ad99 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x661601de sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x664d14f7 platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x66b2a859 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x66bc7b5f sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x66d87d38 symbol_put_addr +EXPORT_SYMBOL_GPL vmlinux 0x674faff4 tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x67955ce6 profile_hits +EXPORT_SYMBOL_GPL vmlinux 0x6834cc83 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x6838c066 __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x684fddfd __trace_note_message +EXPORT_SYMBOL_GPL vmlinux 0x6861bc42 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x686c703f xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x6892088c unregister_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x689822cc devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x68b38221 xenbus_dev_error +EXPORT_SYMBOL_GPL vmlinux 0x691884ef pv_apic_ops +EXPORT_SYMBOL_GPL vmlinux 0x6a2c4941 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0x6a86b01f xenbus_map_ring +EXPORT_SYMBOL_GPL vmlinux 0x6a9638e9 tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0x6b07a368 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0x6b10495b devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0x6b3e5d57 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x6b9178b3 xenbus_strstate +EXPORT_SYMBOL_GPL vmlinux 0x6b93bf60 inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x6be62dfd probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x6c11059b __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x6c49c4f2 clockevents_notify +EXPORT_SYMBOL_GPL vmlinux 0x6c82e92f x86_bios_freq_base +EXPORT_SYMBOL_GPL vmlinux 0x6c8d5ae8 __gpio_get_value +EXPORT_SYMBOL_GPL vmlinux 0x6c99674d kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0x6cb6b12f put_device +EXPORT_SYMBOL_GPL vmlinux 0x6d13c6bb __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x6d5b11f4 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0x6db7b6f0 __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0x6e563010 relay_reset +EXPORT_SYMBOL_GPL vmlinux 0x6e58ddf0 gnttab_end_foreign_transfer_ref +EXPORT_SYMBOL_GPL vmlinux 0x6f57bc36 do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x6f893983 register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x6f9c2efe marker_probe_cb +EXPORT_SYMBOL_GPL vmlinux 0x6ff928e2 xfrm_audit_state_notfound +EXPORT_SYMBOL_GPL vmlinux 0x6ffb5b60 klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x70075cb1 led_trigger_remove +EXPORT_SYMBOL_GPL vmlinux 0x7026555a screen_glyph +EXPORT_SYMBOL_GPL vmlinux 0x7037d79d k8_flush_garts +EXPORT_SYMBOL_GPL vmlinux 0x7146a180 generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0x71c8bc95 kgdb_unregister_io_module +EXPORT_SYMBOL_GPL vmlinux 0x71cea111 put_driver +EXPORT_SYMBOL_GPL vmlinux 0x71d9d73c tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x7278d328 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x72943605 crypto_spawn_tfm +EXPORT_SYMBOL_GPL vmlinux 0x72c412c4 debugfs_create_u32 +EXPORT_SYMBOL_GPL vmlinux 0x731433ee unregister_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0x73201149 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0x733cddd2 xenbus_frontend_closed +EXPORT_SYMBOL_GPL vmlinux 0x73b1f76d do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x741ceb5a relay_open +EXPORT_SYMBOL_GPL vmlinux 0x742e7e37 mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0x7489ac58 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x749bb70f page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0x74abdafa task_handoff_register +EXPORT_SYMBOL_GPL vmlinux 0x74d61a4d get_dcookie +EXPORT_SYMBOL_GPL vmlinux 0x74db3a61 raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0x7521afb6 leave_mm +EXPORT_SYMBOL_GPL vmlinux 0x75c91110 rtc_read_alarm +EXPORT_SYMBOL_GPL vmlinux 0x75ce259a sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x75e8f3c3 crypto_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x761b0b49 cpufreq_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x762d809c net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x7638b63c rtc_irq_register +EXPORT_SYMBOL_GPL vmlinux 0x7656d86f mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x7677c2dc fb_deferred_io_cleanup +EXPORT_SYMBOL_GPL vmlinux 0x7712771a unbind_from_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0x776112af bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x77620316 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x781832f2 cpufreq_cpu_get +EXPORT_SYMBOL_GPL vmlinux 0x78fa77c7 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0x79629583 cpuidle_register_device +EXPORT_SYMBOL_GPL vmlinux 0x7a0c257c bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0x7a4c1438 pv_info +EXPORT_SYMBOL_GPL vmlinux 0x7ac10ebc uv_node_to_blade +EXPORT_SYMBOL_GPL vmlinux 0x7b1d544d edac_handler_set +EXPORT_SYMBOL_GPL vmlinux 0x7b6cbb67 device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x7b92a840 __blk_add_trace +EXPORT_SYMBOL_GPL vmlinux 0x7bb558db fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0x7c6b16b1 platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x7c6d7605 blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x7cba8809 fb_deferred_io_init +EXPORT_SYMBOL_GPL vmlinux 0x7da8d037 marker_probe_register +EXPORT_SYMBOL_GPL vmlinux 0x7dc5d0b6 crypto_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x7ecf642e single_release_net +EXPORT_SYMBOL_GPL vmlinux 0x7f19a9bf spi_unregister_master +EXPORT_SYMBOL_GPL vmlinux 0x7f19c836 unlock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x7feba00a inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x7ff10ccf raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x8039d043 selinux_secmark_relabel_packet_permission +EXPORT_SYMBOL_GPL vmlinux 0x80746a64 pci_disable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0x8088d5ba led_trigger_set_default +EXPORT_SYMBOL_GPL vmlinux 0x80ee55c3 selinux_secmark_refcount_inc +EXPORT_SYMBOL_GPL vmlinux 0x8157f0a5 elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x81ae30e7 tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0x81e6fa78 bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x822512fa debugfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x8226642f __gpio_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x826360fd do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x827805c5 cpufreq_unregister_governor +EXPORT_SYMBOL_GPL vmlinux 0x82af6582 platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x82cd19f3 register_xenstore_notifier +EXPORT_SYMBOL_GPL vmlinux 0x82cd83b2 kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0x82d79b51 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x82f776b7 gpio_export +EXPORT_SYMBOL_GPL vmlinux 0x8315abb2 raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0x83afa919 register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x83cdf073 skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0x83f5d687 sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x83f6b2d2 dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x844c499e crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0x8556153e rtc_set_mmss +EXPORT_SYMBOL_GPL vmlinux 0x85c10896 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x85d7edfd hpet_set_periodic_freq +EXPORT_SYMBOL_GPL vmlinux 0x85d86844 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0x85e5a3db ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x862cab14 rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0x863ef2b4 inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0x86623fd7 notify_remote_via_irq +EXPORT_SYMBOL_GPL vmlinux 0x868784cb __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x86a51007 gnttab_end_foreign_transfer +EXPORT_SYMBOL_GPL vmlinux 0x86b1667d hwrng_unregister +EXPORT_SYMBOL_GPL vmlinux 0x86b33713 acpi_bus_trim +EXPORT_SYMBOL_GPL vmlinux 0x871a9910 register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x873fbaea edac_atomic_assert_error +EXPORT_SYMBOL_GPL vmlinux 0x8758c537 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0x87754115 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x87f2cf3a blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0x880b189a __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x8810ad5e crypto_xor +EXPORT_SYMBOL_GPL vmlinux 0x885142a6 nf_net_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x88f0db24 cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x89a81636 transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0x89bae393 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x89bb6728 __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0x8abed13d xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x8af295fd inotify_inode_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x8afc1caf dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0x8afe8053 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0x8b0f003d device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x8b65ecc8 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8b9200fd lookup_address +EXPORT_SYMBOL_GPL vmlinux 0x8c06a108 xenbus_transaction_start +EXPORT_SYMBOL_GPL vmlinux 0x8c38074a unregister_xenstore_notifier +EXPORT_SYMBOL_GPL vmlinux 0x8e72b2a1 __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8eb58c6e __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0x8ede7e0f skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x8ef4891e device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x8f6cee77 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x9009602a acpi_bus_get_ejd +EXPORT_SYMBOL_GPL vmlinux 0x906b805e srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x90a1004a crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x90bfc439 pci_intx +EXPORT_SYMBOL_GPL vmlinux 0x90f94ef8 led_trigger_unregister_simple +EXPORT_SYMBOL_GPL vmlinux 0x9107183c init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x9159b9d6 profile_event_register +EXPORT_SYMBOL_GPL vmlinux 0x917445dc power_supply_unregister +EXPORT_SYMBOL_GPL vmlinux 0x9192b8fe gpiochip_remove +EXPORT_SYMBOL_GPL vmlinux 0x91b3f5a9 apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0x91dacaa2 acpi_processor_ffh_cstate_probe +EXPORT_SYMBOL_GPL vmlinux 0x91fd4fb8 device_rename +EXPORT_SYMBOL_GPL vmlinux 0x92183295 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x92238352 led_trigger_store +EXPORT_SYMBOL_GPL vmlinux 0x9241c3ee device_power_down +EXPORT_SYMBOL_GPL vmlinux 0x92445aee hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x929e4dba queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x92fb217b dcookie_unregister +EXPORT_SYMBOL_GPL vmlinux 0x933ec255 inotify_dentry_parent_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x93d2422d snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x942c1704 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x94d742f6 pcie_port_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x952450c6 xfrm_audit_policy_add +EXPORT_SYMBOL_GPL vmlinux 0x952664c5 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x9552df38 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x956a91ba gpio_get_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x9577271c hpet_rtc_interrupt +EXPORT_SYMBOL_GPL vmlinux 0x961a8cd3 unlock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x964d5c39 acpi_os_map_memory +EXPORT_SYMBOL_GPL vmlinux 0x9668892f blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0x966d7352 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x96cbcf31 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x96f42d51 blk_trace_setup +EXPORT_SYMBOL_GPL vmlinux 0x97028da3 led_trigger_register +EXPORT_SYMBOL_GPL vmlinux 0x9795720e bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x9833bc0c hvc_kick +EXPORT_SYMBOL_GPL vmlinux 0x988b642c device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x98c03b3e tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0x98d4982a uhci_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x9917234d inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0x992b442a inverse_translate +EXPORT_SYMBOL_GPL vmlinux 0x9957ef07 crypto_enqueue_request +EXPORT_SYMBOL_GPL vmlinux 0x995c76e9 xfrm_audit_state_replay_overflow +EXPORT_SYMBOL_GPL vmlinux 0x995d1071 prof_on +EXPORT_SYMBOL_GPL vmlinux 0x9a11a0fc crypto_attr_alg_name +EXPORT_SYMBOL_GPL vmlinux 0x9a398f5c xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x9ba0501e unregister_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x9c8dfc3a do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0x9ca7708c rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x9cb74740 crypto_drop_spawn +EXPORT_SYMBOL_GPL vmlinux 0x9cb8037b xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x9d029355 unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x9d06688b register_xenbus_watch +EXPORT_SYMBOL_GPL vmlinux 0x9d3273dd sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0x9d3850e1 gnttab_alloc_grant_references +EXPORT_SYMBOL_GPL vmlinux 0x9e711ad2 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x9e7d3442 xenbus_resume +EXPORT_SYMBOL_GPL vmlinux 0x9e9662ab user_describe +EXPORT_SYMBOL_GPL vmlinux 0x9ec89e3f d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x9f51582e pci_find_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x9fc90b8d __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0x9fce80db fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xa01d72c3 raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0xa0255440 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0xa045c69b debugfs_create_symlink +EXPORT_SYMBOL_GPL vmlinux 0xa0a612a0 device_del +EXPORT_SYMBOL_GPL vmlinux 0xa1596d98 acpi_processor_ffh_cstate_enter +EXPORT_SYMBOL_GPL vmlinux 0xa1ba3bb8 netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0xa1c27ac5 skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0xa1f90571 platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0xa2937953 inotify_rm_watch +EXPORT_SYMBOL_GPL vmlinux 0xa2a79abd proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0xa2c03841 bind_evtchn_to_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0xa2e67f08 acpi_bus_generate_proc_event4 +EXPORT_SYMBOL_GPL vmlinux 0xa2e8bac5 lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0xa2f1e19f class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xa3499aec get_device +EXPORT_SYMBOL_GPL vmlinux 0xa353fffc xenbus_rm +EXPORT_SYMBOL_GPL vmlinux 0xa3a7c178 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0xa3fc96f0 marker_probe_cb_noarg +EXPORT_SYMBOL_GPL vmlinux 0xa452c297 hpet_mask_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa4d58669 math_state_restore +EXPORT_SYMBOL_GPL vmlinux 0xa5614615 rtc_device_register +EXPORT_SYMBOL_GPL vmlinux 0xa5622624 power_supply_register +EXPORT_SYMBOL_GPL vmlinux 0xa5a63c40 inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0xa5bf5c3e pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0xa5c36cec inotify_unmount_inodes +EXPORT_SYMBOL_GPL vmlinux 0xa712d99f __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0xa73c7a4a fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0xa7564542 vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0xa780889d tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0xa815dda5 gpiochip_add +EXPORT_SYMBOL_GPL vmlinux 0xa83415d1 pciserial_resume_ports +EXPORT_SYMBOL_GPL vmlinux 0xa8590407 inet_hash +EXPORT_SYMBOL_GPL vmlinux 0xa8afdfd0 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0xa8f59416 gpio_direction_output +EXPORT_SYMBOL_GPL vmlinux 0xa9126bff hpet_set_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa963f49c tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0xa97d49dc xenbus_switch_state +EXPORT_SYMBOL_GPL vmlinux 0xa9c530b8 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xaa1b769e cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0xaa429881 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0xaa587725 nf_register_afinfo +EXPORT_SYMBOL_GPL vmlinux 0xaa86cfb5 uv_possible_blades +EXPORT_SYMBOL_GPL vmlinux 0xaa8c4696 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0xaaac6483 audit_log_vformat +EXPORT_SYMBOL_GPL vmlinux 0xab01acbe gnttab_request_free_callback +EXPORT_SYMBOL_GPL vmlinux 0xab9ea5f3 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0xaba749b6 simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0xabc28976 force_evtchn_callback +EXPORT_SYMBOL_GPL vmlinux 0xabe65286 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0xabec8c68 ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0xac1ee37d sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0xac352657 xfrm_audit_state_delete +EXPORT_SYMBOL_GPL vmlinux 0xacc19485 ibft_addr +EXPORT_SYMBOL_GPL vmlinux 0xad096363 xenbus_printf +EXPORT_SYMBOL_GPL vmlinux 0xad150e63 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0xad1b5443 crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0xad4f248a rtc_irq_set_freq +EXPORT_SYMBOL_GPL vmlinux 0xad63a24e per_cpu____uv_hub_info +EXPORT_SYMBOL_GPL vmlinux 0xadffe1cf alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0xae0c87ee pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0xae22fdd0 inet6_lookup +EXPORT_SYMBOL_GPL vmlinux 0xae3982f5 k_handler +EXPORT_SYMBOL_GPL vmlinux 0xae9e08e7 vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0xaec245ed sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0xaf35b9db driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0xafae3c4b pci_stop_bus_device +EXPORT_SYMBOL_GPL vmlinux 0xafc88469 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0xafdfa5ff platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0xafedb308 security_inode_setattr +EXPORT_SYMBOL_GPL vmlinux 0xb04a2413 pci_find_aer_capability +EXPORT_SYMBOL_GPL vmlinux 0xb0889179 swiotlb_sync_single_range_for_device +EXPORT_SYMBOL_GPL vmlinux 0xb10d55bc cn_netlink_send +EXPORT_SYMBOL_GPL vmlinux 0xb120ab95 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0xb1acbcce rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0xb2196033 gpiochip_is_requested +EXPORT_SYMBOL_GPL vmlinux 0xb221ee72 pci_destroy_slot +EXPORT_SYMBOL_GPL vmlinux 0xb27005f5 device_suspend +EXPORT_SYMBOL_GPL vmlinux 0xb3180a78 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0xb3253ed9 hpet_rtc_timer_init +EXPORT_SYMBOL_GPL vmlinux 0xb37474a4 power_supply_class +EXPORT_SYMBOL_GPL vmlinux 0xb3b080fa seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0xb3e0b0f0 devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0xb46c54ab hwmon_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xb4e14553 gnttab_query_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xb4ea7cf7 kgdb_connected +EXPORT_SYMBOL_GPL vmlinux 0xb51cd6a6 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0xb51fbd64 edac_op_state +EXPORT_SYMBOL_GPL vmlinux 0xb53ae573 cpu_idle_wait +EXPORT_SYMBOL_GPL vmlinux 0xb53defa6 rtc_set_alarm +EXPORT_SYMBOL_GPL vmlinux 0xb612444d snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0xb61c5c63 platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0xb6230f1f gnttab_grant_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xb63550f5 __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0xb65091b3 selinux_secmark_refcount_dec +EXPORT_SYMBOL_GPL vmlinux 0xb6536723 cpufreq_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0xb6e62bbb __class_register +EXPORT_SYMBOL_GPL vmlinux 0xb6ffd038 debugfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0xb74920ad console_drivers +EXPORT_SYMBOL_GPL vmlinux 0xb7a0c77c ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0xb7b443de sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0xb7d7c12e hpet_set_alarm_time +EXPORT_SYMBOL_GPL vmlinux 0xb8048d50 securityfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0xb808c909 tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0xb903674c scatterwalk_map_and_copy +EXPORT_SYMBOL_GPL vmlinux 0xb93288e7 securityfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0xb9368b32 rtc_set_time +EXPORT_SYMBOL_GPL vmlinux 0xb97e6c02 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0xb992461e pskb_put +EXPORT_SYMBOL_GPL vmlinux 0xb99d5837 xenbus_read +EXPORT_SYMBOL_GPL vmlinux 0xb9eb3aa9 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0xb9efc967 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xba4de1dd sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0xba58775c blk_trace_startstop +EXPORT_SYMBOL_GPL vmlinux 0xbabfe4e2 xfrm_audit_policy_delete +EXPORT_SYMBOL_GPL vmlinux 0xbb324330 debugfs_create_x16 +EXPORT_SYMBOL_GPL vmlinux 0xbb3ecb11 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0xbb7295b5 power_supply_am_i_supplied +EXPORT_SYMBOL_GPL vmlinux 0xbbb98859 edid_info +EXPORT_SYMBOL_GPL vmlinux 0xbbd1e034 device_register +EXPORT_SYMBOL_GPL vmlinux 0xbbdc1c82 kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0xbc089f3b __class_create +EXPORT_SYMBOL_GPL vmlinux 0xbc301681 pciserial_suspend_ports +EXPORT_SYMBOL_GPL vmlinux 0xbcc27560 inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0xbce2f3ce driver_attach +EXPORT_SYMBOL_GPL vmlinux 0xbcf59b30 generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0xbd8f3be3 blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0xbdb535b6 inotify_inode_is_dead +EXPORT_SYMBOL_GPL vmlinux 0xbe7ef09b pci_set_pcie_reset_state +EXPORT_SYMBOL_GPL vmlinux 0xbe95831f pci_create_slot +EXPORT_SYMBOL_GPL vmlinux 0xbf00a09b spi_busnum_to_master +EXPORT_SYMBOL_GPL vmlinux 0xbf32cb64 sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0xbf74eb20 probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0xc097eb8e hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0xc0b3ca1f pci_restore_msi_state +EXPORT_SYMBOL_GPL vmlinux 0xc0ce6b54 cpuidle_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0xc1133988 led_trigger_event +EXPORT_SYMBOL_GPL vmlinux 0xc18ad2c1 devres_find +EXPORT_SYMBOL_GPL vmlinux 0xc26351f8 bind_evtchn_to_irq +EXPORT_SYMBOL_GPL vmlinux 0xc26aba23 firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0xc2945138 bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xc29fd93f proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0xc2fed832 hvc_alloc +EXPORT_SYMBOL_GPL vmlinux 0xc33f7617 blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0xc34efe27 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0xc381378c blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0xc3a81873 xenbus_watch_pathfmt +EXPORT_SYMBOL_GPL vmlinux 0xc3d31607 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0xc415525f rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0xc42f2f94 xenbus_read_driver_state +EXPORT_SYMBOL_GPL vmlinux 0xc4330bb4 pciserial_init_ports +EXPORT_SYMBOL_GPL vmlinux 0xc4f6be38 crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0xc512626a __supported_pte_mask +EXPORT_SYMBOL_GPL vmlinux 0xc5397da6 xenbus_mkdir +EXPORT_SYMBOL_GPL vmlinux 0xc54e6ff9 anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0xc5680dac bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0xc5696360 put_pid +EXPORT_SYMBOL_GPL vmlinux 0xc5adc89d __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0xc5c74f1b pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0xc5f3a277 rtc_irq_set_state +EXPORT_SYMBOL_GPL vmlinux 0xc66663fd vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0xc68976a8 spi_alloc_device +EXPORT_SYMBOL_GPL vmlinux 0xc6f50d38 tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0xc70898c0 simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0xc7535af9 kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0xc7ec11f6 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xc7f72be0 relay_close +EXPORT_SYMBOL_GPL vmlinux 0xc81be572 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0xc81d40a6 hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0xc82ddb06 crypto_init_spawn +EXPORT_SYMBOL_GPL vmlinux 0xc8544cf1 get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0xc87c1f84 ktime_get +EXPORT_SYMBOL_GPL vmlinux 0xc87e487a sched_clock_idle_sleep_event +EXPORT_SYMBOL_GPL vmlinux 0xc926b833 vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0xc9561772 fb_destroy_modelist +EXPORT_SYMBOL_GPL vmlinux 0xca360989 disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0xca81ea9a xenbus_transaction_end +EXPORT_SYMBOL_GPL vmlinux 0xcabe04de cpuidle_resume_and_unlock +EXPORT_SYMBOL_GPL vmlinux 0xcbc31b5a invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0xcbc8088d relay_switch_subbuf +EXPORT_SYMBOL_GPL vmlinux 0xcbf20127 klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0xcc018d9c register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0xcc1f1c3d inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0xcc5299e9 register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0xcc8c382b sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0xcc944571 inotify_init_watch +EXPORT_SYMBOL_GPL vmlinux 0xcd9a04b7 crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0xcda73000 devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0xcde9679b cpuidle_register_driver +EXPORT_SYMBOL_GPL vmlinux 0xce1b86ba audit_log_d_path +EXPORT_SYMBOL_GPL vmlinux 0xce324c37 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0xced8b807 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0xcedf435b page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0xcf389571 debugfs_remove +EXPORT_SYMBOL_GPL vmlinux 0xcfcc83ad register_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0xd027a07d marker_probe_unregister +EXPORT_SYMBOL_GPL vmlinux 0xd03c7700 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0xd0c05159 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0xd10c15cd pci_scan_child_bus +EXPORT_SYMBOL_GPL vmlinux 0xd120d9b9 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0xd161986b tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0xd16712f3 crypto_check_attr_type +EXPORT_SYMBOL_GPL vmlinux 0xd1aed017 crypto_unregister_alg +EXPORT_SYMBOL_GPL vmlinux 0xd1ee0737 device_add +EXPORT_SYMBOL_GPL vmlinux 0xd247edb4 rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0xd264f899 vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0xd29b5ad2 sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0xd373624f kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0xd3b78da3 xenbus_suspend_cancel +EXPORT_SYMBOL_GPL vmlinux 0xd3ef4639 transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0xd40660a9 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0xd44250e1 crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0xd516bffd platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0xd6f77c33 find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0xd6feefa5 agp_num_entries +EXPORT_SYMBOL_GPL vmlinux 0xd7d79132 put_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0xd82f8964 devres_get +EXPORT_SYMBOL_GPL vmlinux 0xd855aca2 mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0xd9042fa8 scatterwalk_map +EXPORT_SYMBOL_GPL vmlinux 0xd9f8681a attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0xdaaa88c2 hwmon_device_register +EXPORT_SYMBOL_GPL vmlinux 0xdae86172 blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0xdaf4dfb3 fb_mode_option +EXPORT_SYMBOL_GPL vmlinux 0xdb57931e fib_rules_cleanup_ops +EXPORT_SYMBOL_GPL vmlinux 0xdb7569a9 preempt_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0xdbee78fe spi_alloc_master +EXPORT_SYMBOL_GPL vmlinux 0xdc1f8f2e register_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0xdc7f2de2 inet_csk_compat_setsockopt +EXPORT_SYMBOL_GPL vmlinux 0xdc9fdf45 kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0xdcf11e37 __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0xdd5c4942 srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0xddb6d1c1 bus_register +EXPORT_SYMBOL_GPL vmlinux 0xddbe0e71 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0xde162625 __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xde7ed175 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0xdeb750be generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0xdeda859b inet_csk_compat_getsockopt +EXPORT_SYMBOL_GPL vmlinux 0xdf2159ad inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0xdf3c19ec cn_add_callback +EXPORT_SYMBOL_GPL vmlinux 0xdfbd9126 rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0xe089cfcc agp_memory_reserved +EXPORT_SYMBOL_GPL vmlinux 0xe09033e4 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0xe1d1f8bb crypto_register_template +EXPORT_SYMBOL_GPL vmlinux 0xe24ff917 blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0xe25ccd06 relay_subbufs_consumed +EXPORT_SYMBOL_GPL vmlinux 0xe295c0ff is_hpet_enabled +EXPORT_SYMBOL_GPL vmlinux 0xe2dbd55a led_trigger_register_simple +EXPORT_SYMBOL_GPL vmlinux 0xe2e3f4a1 pci_slots_kset +EXPORT_SYMBOL_GPL vmlinux 0xe348c249 unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xe34db7f2 sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0xe35759ff tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0xe36cb7c3 tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0xe3c99b8d uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0xe3e7ba4a user_read +EXPORT_SYMBOL_GPL vmlinux 0xe3ee4899 rtc_class_open +EXPORT_SYMBOL_GPL vmlinux 0xe411465e pci_bus_add_device +EXPORT_SYMBOL_GPL vmlinux 0xe513afc0 cache_k8_northbridges +EXPORT_SYMBOL_GPL vmlinux 0xe52742ae debugfs_create_u8 +EXPORT_SYMBOL_GPL vmlinux 0xe527c9ac simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0xe530071c pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0xe57963a0 platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xe61a6d2f gpio_unexport +EXPORT_SYMBOL_GPL vmlinux 0xe6488b47 cpufreq_notify_transition +EXPORT_SYMBOL_GPL vmlinux 0xe651c0b7 crypto_hash_walk_first +EXPORT_SYMBOL_GPL vmlinux 0xe66df9c8 driver_register +EXPORT_SYMBOL_GPL vmlinux 0xe674a5cb srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0xe6d6addd tcp_done +EXPORT_SYMBOL_GPL vmlinux 0xe6e8253e crypto_ahash_type +EXPORT_SYMBOL_GPL vmlinux 0xe72778d7 alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xe79c2957 register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0xe7de7122 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0xe7fa47ad srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0xe81af31a crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0xe83aafab mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0xe841d957 xenbus_dev_fatal +EXPORT_SYMBOL_GPL vmlinux 0xe8583fc1 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0xe8f9dfaf uv_cpu_to_blade +EXPORT_SYMBOL_GPL vmlinux 0xe90bac06 debugfs_create_bool +EXPORT_SYMBOL_GPL vmlinux 0xe93e49c3 devres_free +EXPORT_SYMBOL_GPL vmlinux 0xe94fefd7 inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0xe9dd844d bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0xea065e01 task_handoff_unregister +EXPORT_SYMBOL_GPL vmlinux 0xeb27d352 pci_update_slot_number +EXPORT_SYMBOL_GPL vmlinux 0xeb864b6e bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0xec8db6d0 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0xecc85c8c device_attach +EXPORT_SYMBOL_GPL vmlinux 0xed26fb0f rtc_update_irq +EXPORT_SYMBOL_GPL vmlinux 0xed636046 inotify_rm_wd +EXPORT_SYMBOL_GPL vmlinux 0xed907658 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0xedb103ec sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0xedbc6f67 gnttab_end_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xedc013bb get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0xee59b408 invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0xee8e29e3 blk_trace_remove +EXPORT_SYMBOL_GPL vmlinux 0xeecfb193 set_cpus_allowed_ptr +EXPORT_SYMBOL_GPL vmlinux 0xef35dd65 cpuidle_disable_device +EXPORT_SYMBOL_GPL vmlinux 0xef390070 debugfs_create_x8 +EXPORT_SYMBOL_GPL vmlinux 0xef67109f pci_bus_max_busnr +EXPORT_SYMBOL_GPL vmlinux 0xefb66434 fb_bl_default_curve +EXPORT_SYMBOL_GPL vmlinux 0xefdf3189 save_stack_trace_tsk +EXPORT_SYMBOL_GPL vmlinux 0xefecadf7 device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xf0809b34 driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xf0cd7362 vlan_dev_vlan_id +EXPORT_SYMBOL_GPL vmlinux 0xf11c3ce2 tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0xf16fc662 debugfs_rename +EXPORT_SYMBOL_GPL vmlinux 0xf184d189 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0xf1d928c3 class_destroy +EXPORT_SYMBOL_GPL vmlinux 0xf259eb08 driver_find +EXPORT_SYMBOL_GPL vmlinux 0xf2a906c3 xfrm_audit_state_notfound_simple +EXPORT_SYMBOL_GPL vmlinux 0xf2b34905 blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0xf2fca922 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0xf3a6af55 register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0xf3d1bb7a __cpufreq_driver_getavg +EXPORT_SYMBOL_GPL vmlinux 0xf3f2b2ef crypto_register_alg +EXPORT_SYMBOL_GPL vmlinux 0xf41e1eac proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0xf4762ccb vlan_dev_real_dev +EXPORT_SYMBOL_GPL vmlinux 0xf4831126 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0xf499fdb2 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0xf4aebdc3 xenbus_suspend +EXPORT_SYMBOL_GPL vmlinux 0xf4d78b52 get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0xf553318d cpuidle_pause_and_lock +EXPORT_SYMBOL_GPL vmlinux 0xf5945bac gnttab_free_grant_references +EXPORT_SYMBOL_GPL vmlinux 0xf5a691cd invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0xf5add0f7 debugfs_create_x32 +EXPORT_SYMBOL_GPL vmlinux 0xf5d148a1 user_destroy +EXPORT_SYMBOL_GPL vmlinux 0xf6511c1f xenbus_alloc_evtchn +EXPORT_SYMBOL_GPL vmlinux 0xf67ae112 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0xf6bb0e24 tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0xf6bcbd73 hwrng_register +EXPORT_SYMBOL_GPL vmlinux 0xf6c9b9bc queue_work +EXPORT_SYMBOL_GPL vmlinux 0xf7016530 xenbus_gather +EXPORT_SYMBOL_GPL vmlinux 0xf7427c4c register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0xf7a3d27f __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0xf7e5dad8 inotify_find_update_watch +EXPORT_SYMBOL_GPL vmlinux 0xf865b5dd agp_add_bridge +EXPORT_SYMBOL_GPL vmlinux 0xf873e73c relay_flush +EXPORT_SYMBOL_GPL vmlinux 0xf8802492 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0xf90a737d __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xf94ef36d sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0xf97c4aae klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0xf99bb136 register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xf9a054b5 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0xfa1f4662 scatterwalk_start +EXPORT_SYMBOL_GPL vmlinux 0xfa48716d hvc_poll +EXPORT_SYMBOL_GPL vmlinux 0xfbc016de blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xfbc9a360 rtc_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xfbcaf457 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0xfbf9be5d register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xfc992a43 device_move +EXPORT_SYMBOL_GPL vmlinux 0xfcc5b4d7 exit_fs +EXPORT_SYMBOL_GPL vmlinux 0xfd51b281 gnttab_end_foreign_access_ref +EXPORT_SYMBOL_GPL vmlinux 0xfd721947 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0xfde0b92c crypto_larval_error +EXPORT_SYMBOL_GPL vmlinux 0xfdf7fcbf kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0xfe727411 get_phys_to_machine +EXPORT_SYMBOL_GPL vmlinux 0xfe990052 gpio_free +EXPORT_SYMBOL_GPL vmlinux 0xfec35820 queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0xfecbff96 __mark_empty_function +EXPORT_SYMBOL_GPL vmlinux 0xff27b0ef inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0xff4af680 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0xff5a8cfe cn_del_callback +EXPORT_SYMBOL_GPL vmlinux 0xff793790 sysdev_class_create_file +EXPORT_UNUSED_SYMBOL vmlinux 0x00000000 init_mm --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/armel/orion5x +++ linux-2.6.27/debian/abi/2.6.27-8.17/armel/orion5x @@ -0,0 +1,3342 @@ +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_get_last_written +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_get_media_event +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_ioctl +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_media_changed +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_mode_select +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_mode_sense +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_number_of_slots +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_open +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 cdrom_release +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 init_cdrom_command +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 register_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0x00000000 unregister_cdrom +EXPORT_SYMBOL lib/crc-itu-t 0x00000000 crc_itu_t +EXPORT_SYMBOL lib/crc-itu-t 0x00000000 crc_itu_t_table +EXPORT_SYMBOL vmlinux 0x00000000 I_BDEV +EXPORT_SYMBOL vmlinux 0x00000000 ___pskb_trim +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_idiv +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_idivmod +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_lasr +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_llsl +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_llsr +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_lmul +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_uidiv +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_uidivmod +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_ulcmp +EXPORT_SYMBOL vmlinux 0x00000000 __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x00000000 __alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 __arm_ioremap +EXPORT_SYMBOL vmlinux 0x00000000 __arm_ioremap_pfn +EXPORT_SYMBOL vmlinux 0x00000000 __ashldi3 +EXPORT_SYMBOL vmlinux 0x00000000 __ashrdi3 +EXPORT_SYMBOL vmlinux 0x00000000 __backtrace +EXPORT_SYMBOL vmlinux 0x00000000 __bad_xchg +EXPORT_SYMBOL vmlinux 0x00000000 __bdevname +EXPORT_SYMBOL vmlinux 0x00000000 __bforget +EXPORT_SYMBOL vmlinux 0x00000000 __bio_clone +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_and +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_complement +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_equal +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_full +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_intersects +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_or +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_parse +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_xor +EXPORT_SYMBOL vmlinux 0x00000000 __blk_run_queue +EXPORT_SYMBOL vmlinux 0x00000000 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0x00000000 __bread +EXPORT_SYMBOL vmlinux 0x00000000 __breadahead +EXPORT_SYMBOL vmlinux 0x00000000 __break_lease +EXPORT_SYMBOL vmlinux 0x00000000 __brelse +EXPORT_SYMBOL vmlinux 0x00000000 __bug +EXPORT_SYMBOL vmlinux 0x00000000 __cap_empty_set +EXPORT_SYMBOL vmlinux 0x00000000 __cap_full_set +EXPORT_SYMBOL vmlinux 0x00000000 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x00000000 __check_region +EXPORT_SYMBOL vmlinux 0x00000000 __clear_user +EXPORT_SYMBOL vmlinux 0x00000000 __const_udelay +EXPORT_SYMBOL vmlinux 0x00000000 __copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 __copy_to_user +EXPORT_SYMBOL vmlinux 0x00000000 __csum_ipv6_magic +EXPORT_SYMBOL vmlinux 0x00000000 __dev_get_by_index +EXPORT_SYMBOL vmlinux 0x00000000 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0x00000000 __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x00000000 __dev_remove_pack +EXPORT_SYMBOL vmlinux 0x00000000 __devm_release_region +EXPORT_SYMBOL vmlinux 0x00000000 __devm_request_region +EXPORT_SYMBOL vmlinux 0x00000000 __div0 +EXPORT_SYMBOL vmlinux 0x00000000 __div64_32 +EXPORT_SYMBOL vmlinux 0x00000000 __divsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __do_div64 +EXPORT_SYMBOL vmlinux 0x00000000 __down_read +EXPORT_SYMBOL vmlinux 0x00000000 __down_read_trylock +EXPORT_SYMBOL vmlinux 0x00000000 __down_write +EXPORT_SYMBOL vmlinux 0x00000000 __down_write_nested +EXPORT_SYMBOL vmlinux 0x00000000 __down_write_trylock +EXPORT_SYMBOL vmlinux 0x00000000 __downgrade_write +EXPORT_SYMBOL vmlinux 0x00000000 __dst_free +EXPORT_SYMBOL vmlinux 0x00000000 __elv_add_request +EXPORT_SYMBOL vmlinux 0x00000000 __f_setown +EXPORT_SYMBOL vmlinux 0x00000000 __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0x00000000 __find_get_block +EXPORT_SYMBOL vmlinux 0x00000000 __free_pages +EXPORT_SYMBOL vmlinux 0x00000000 __generic_unplug_device +EXPORT_SYMBOL vmlinux 0x00000000 __get_free_pages +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_1 +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_2 +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_4 +EXPORT_SYMBOL vmlinux 0x00000000 __getblk +EXPORT_SYMBOL vmlinux 0x00000000 __grab_cache_page +EXPORT_SYMBOL vmlinux 0x00000000 __init_rwsem +EXPORT_SYMBOL vmlinux 0x00000000 __inode_dir_notify +EXPORT_SYMBOL vmlinux 0x00000000 __insert_inode_hash +EXPORT_SYMBOL vmlinux 0x00000000 __invalidate_device +EXPORT_SYMBOL vmlinux 0x00000000 __iounmap +EXPORT_SYMBOL vmlinux 0x00000000 __ip_select_ident +EXPORT_SYMBOL vmlinux 0x00000000 __kfifo_get +EXPORT_SYMBOL vmlinux 0x00000000 __kfifo_put +EXPORT_SYMBOL vmlinux 0x00000000 __kfree_skb +EXPORT_SYMBOL vmlinux 0x00000000 __kill_fasync +EXPORT_SYMBOL vmlinux 0x00000000 __kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 __krealloc +EXPORT_SYMBOL vmlinux 0x00000000 __lock_buffer +EXPORT_SYMBOL vmlinux 0x00000000 __lock_page +EXPORT_SYMBOL vmlinux 0x00000000 __locks_copy_lock +EXPORT_SYMBOL vmlinux 0x00000000 __lookup_hash +EXPORT_SYMBOL vmlinux 0x00000000 __lshrdi3 +EXPORT_SYMBOL vmlinux 0x00000000 __machine_arch_type +EXPORT_SYMBOL vmlinux 0x00000000 __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0x00000000 __memzero +EXPORT_SYMBOL vmlinux 0x00000000 __mod_timer +EXPORT_SYMBOL vmlinux 0x00000000 __modsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __module_put_and_exit +EXPORT_SYMBOL vmlinux 0x00000000 __mpage_writepage +EXPORT_SYMBOL vmlinux 0x00000000 __muldi3 +EXPORT_SYMBOL vmlinux 0x00000000 __mutex_init +EXPORT_SYMBOL vmlinux 0x00000000 __napi_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __neigh_event_send +EXPORT_SYMBOL vmlinux 0x00000000 __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0x00000000 __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 __netif_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __nla_put +EXPORT_SYMBOL vmlinux 0x00000000 __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 __nla_reserve +EXPORT_SYMBOL vmlinux 0x00000000 __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 __page_symlink +EXPORT_SYMBOL vmlinux 0x00000000 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0x00000000 __pagevec_release +EXPORT_SYMBOL vmlinux 0x00000000 __pci_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 __print_symbol +EXPORT_SYMBOL vmlinux 0x00000000 __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_1 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_2 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_4 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_8 +EXPORT_SYMBOL vmlinux 0x00000000 __ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsb +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsl +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsw +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesb +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesl +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesw +EXPORT_SYMBOL vmlinux 0x00000000 __readwrite_bug +EXPORT_SYMBOL vmlinux 0x00000000 __release_region +EXPORT_SYMBOL vmlinux 0x00000000 __request_region +EXPORT_SYMBOL vmlinux 0x00000000 __rta_fill +EXPORT_SYMBOL vmlinux 0x00000000 __scm_destroy +EXPORT_SYMBOL vmlinux 0x00000000 __scm_send +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_add_device +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_alloc_queue +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_device_lookup +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_device_lookup_by_target +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_iterate_devices +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_print_command +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_print_sense +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_put_command +EXPORT_SYMBOL vmlinux 0x00000000 __secpath_destroy +EXPORT_SYMBOL vmlinux 0x00000000 __seq_open_private +EXPORT_SYMBOL vmlinux 0x00000000 __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0x00000000 __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0x00000000 __set_personality +EXPORT_SYMBOL vmlinux 0x00000000 __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x00000000 __sg_free_table +EXPORT_SYMBOL vmlinux 0x00000000 __sk_dst_check +EXPORT_SYMBOL vmlinux 0x00000000 __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0x00000000 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0x00000000 __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0x00000000 __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x00000000 __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0x00000000 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0x00000000 __starget_for_each_device +EXPORT_SYMBOL vmlinux 0x00000000 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 __strnlen_user +EXPORT_SYMBOL vmlinux 0x00000000 __symbol_put +EXPORT_SYMBOL vmlinux 0x00000000 __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __tasklet_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __ucmpdi2 +EXPORT_SYMBOL vmlinux 0x00000000 __udelay +EXPORT_SYMBOL vmlinux 0x00000000 __udivsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __umodsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __up_read +EXPORT_SYMBOL vmlinux 0x00000000 __up_write +EXPORT_SYMBOL vmlinux 0x00000000 __vmalloc +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_bit +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_buffer +EXPORT_SYMBOL vmlinux 0x00000000 __wake_up +EXPORT_SYMBOL vmlinux 0x00000000 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_lookup +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x00000000 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x00000000 _change_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _clear_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _cond_resched +EXPORT_SYMBOL vmlinux 0x00000000 _ctype +EXPORT_SYMBOL vmlinux 0x00000000 _find_first_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_first_zero_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_next_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_next_zero_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _local_bh_enable +EXPORT_SYMBOL vmlinux 0x00000000 _memcpy_fromio +EXPORT_SYMBOL vmlinux 0x00000000 _memcpy_toio +EXPORT_SYMBOL vmlinux 0x00000000 _memset_io +EXPORT_SYMBOL vmlinux 0x00000000 _set_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_change_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_clear_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_set_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 abort +EXPORT_SYMBOL vmlinux 0x00000000 acquire_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 add_disk +EXPORT_SYMBOL vmlinux 0x00000000 add_mtd_partitions +EXPORT_SYMBOL vmlinux 0x00000000 add_preempt_count +EXPORT_SYMBOL vmlinux 0x00000000 add_taint +EXPORT_SYMBOL vmlinux 0x00000000 add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0x00000000 add_wait_queue +EXPORT_SYMBOL vmlinux 0x00000000 add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x00000000 adjust_resource +EXPORT_SYMBOL vmlinux 0x00000000 aio_complete +EXPORT_SYMBOL vmlinux 0x00000000 aio_put_req +EXPORT_SYMBOL vmlinux 0x00000000 alloc_buffer_head +EXPORT_SYMBOL vmlinux 0x00000000 alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 alloc_disk +EXPORT_SYMBOL vmlinux 0x00000000 alloc_disk_node +EXPORT_SYMBOL vmlinux 0x00000000 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0x00000000 alloc_file +EXPORT_SYMBOL vmlinux 0x00000000 alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0x00000000 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0x00000000 alloc_pci_dev +EXPORT_SYMBOL vmlinux 0x00000000 alloc_tty_driver +EXPORT_SYMBOL vmlinux 0x00000000 allocate_resource +EXPORT_SYMBOL vmlinux 0x00000000 allow_signal +EXPORT_SYMBOL vmlinux 0x00000000 argv_free +EXPORT_SYMBOL vmlinux 0x00000000 argv_split +EXPORT_SYMBOL vmlinux 0x00000000 arp_broken_ops +EXPORT_SYMBOL vmlinux 0x00000000 arp_create +EXPORT_SYMBOL vmlinux 0x00000000 arp_find +EXPORT_SYMBOL vmlinux 0x00000000 arp_send +EXPORT_SYMBOL vmlinux 0x00000000 arp_tbl +EXPORT_SYMBOL vmlinux 0x00000000 arp_xmit +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_find +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_lookup +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_put +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_add_addr +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_forget_old +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_lookup +EXPORT_SYMBOL vmlinux 0x00000000 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0x00000000 avenrun +EXPORT_SYMBOL vmlinux 0x00000000 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0x00000000 bcd2bin +EXPORT_SYMBOL vmlinux 0x00000000 bd_claim +EXPORT_SYMBOL vmlinux 0x00000000 bd_release +EXPORT_SYMBOL vmlinux 0x00000000 bd_set_size +EXPORT_SYMBOL vmlinux 0x00000000 bdev_read_only +EXPORT_SYMBOL vmlinux 0x00000000 bdevname +EXPORT_SYMBOL vmlinux 0x00000000 bdget +EXPORT_SYMBOL vmlinux 0x00000000 bdi_destroy +EXPORT_SYMBOL vmlinux 0x00000000 bdi_init +EXPORT_SYMBOL vmlinux 0x00000000 bdi_register +EXPORT_SYMBOL vmlinux 0x00000000 bdi_register_dev +EXPORT_SYMBOL vmlinux 0x00000000 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0x00000000 bdi_unregister +EXPORT_SYMBOL vmlinux 0x00000000 bdput +EXPORT_SYMBOL vmlinux 0x00000000 bh_submit_read +EXPORT_SYMBOL vmlinux 0x00000000 bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0x00000000 bin2bcd +EXPORT_SYMBOL vmlinux 0x00000000 bio_add_page +EXPORT_SYMBOL vmlinux 0x00000000 bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x00000000 bio_alloc +EXPORT_SYMBOL vmlinux 0x00000000 bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0x00000000 bio_clone +EXPORT_SYMBOL vmlinux 0x00000000 bio_copy_kern +EXPORT_SYMBOL vmlinux 0x00000000 bio_copy_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_endio +EXPORT_SYMBOL vmlinux 0x00000000 bio_free +EXPORT_SYMBOL vmlinux 0x00000000 bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0x00000000 bio_hw_segments +EXPORT_SYMBOL vmlinux 0x00000000 bio_init +EXPORT_SYMBOL vmlinux 0x00000000 bio_map_kern +EXPORT_SYMBOL vmlinux 0x00000000 bio_map_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_pair_release +EXPORT_SYMBOL vmlinux 0x00000000 bio_phys_segments +EXPORT_SYMBOL vmlinux 0x00000000 bio_put +EXPORT_SYMBOL vmlinux 0x00000000 bio_split +EXPORT_SYMBOL vmlinux 0x00000000 bio_split_pool +EXPORT_SYMBOL vmlinux 0x00000000 bio_uncopy_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_unmap_user +EXPORT_SYMBOL vmlinux 0x00000000 bioset_create +EXPORT_SYMBOL vmlinux 0x00000000 bioset_free +EXPORT_SYMBOL vmlinux 0x00000000 bit_waitqueue +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_bitremap +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_fold +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_onto +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_remap +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x00000000 bitrev16 +EXPORT_SYMBOL vmlinux 0x00000000 bitrev32 +EXPORT_SYMBOL vmlinux 0x00000000 blk_alloc_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0x00000000 blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_complete_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0x00000000 blk_execute_rq +EXPORT_SYMBOL vmlinux 0x00000000 blk_free_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0x00000000 blk_get_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_insert_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x00000000 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x00000000 blk_plug_device +EXPORT_SYMBOL vmlinux 0x00000000 blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x00000000 blk_put_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_bounce +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_make_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_ordered +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0x00000000 blk_recount_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_register_region +EXPORT_SYMBOL vmlinux 0x00000000 blk_remove_plug +EXPORT_SYMBOL vmlinux 0x00000000 blk_requeue_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_init +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_user +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0x00000000 blk_run_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_start_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_start_queueing +EXPORT_SYMBOL vmlinux 0x00000000 blk_stop_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_sync_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_unplug +EXPORT_SYMBOL vmlinux 0x00000000 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x00000000 blk_verify_command +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_get +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_put +EXPORT_SYMBOL vmlinux 0x00000000 block_all_signals +EXPORT_SYMBOL vmlinux 0x00000000 block_commit_write +EXPORT_SYMBOL vmlinux 0x00000000 block_invalidatepage +EXPORT_SYMBOL vmlinux 0x00000000 block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0x00000000 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0x00000000 block_prepare_write +EXPORT_SYMBOL vmlinux 0x00000000 block_read_full_page +EXPORT_SYMBOL vmlinux 0x00000000 block_sync_page +EXPORT_SYMBOL vmlinux 0x00000000 block_truncate_page +EXPORT_SYMBOL vmlinux 0x00000000 block_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 block_write_end +EXPORT_SYMBOL vmlinux 0x00000000 block_write_full_page +EXPORT_SYMBOL vmlinux 0x00000000 bmap +EXPORT_SYMBOL vmlinux 0x00000000 boot_tvec_bases +EXPORT_SYMBOL vmlinux 0x00000000 brioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x00000000 cache_check +EXPORT_SYMBOL vmlinux 0x00000000 cache_flush +EXPORT_SYMBOL vmlinux 0x00000000 cache_purge +EXPORT_SYMBOL vmlinux 0x00000000 cache_register +EXPORT_SYMBOL vmlinux 0x00000000 cache_unregister +EXPORT_SYMBOL vmlinux 0x00000000 cad_pid +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0x00000000 can_do_mlock +EXPORT_SYMBOL vmlinux 0x00000000 cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0x00000000 cancel_dirty_page +EXPORT_SYMBOL vmlinux 0x00000000 cap_netlink_recv +EXPORT_SYMBOL vmlinux 0x00000000 cap_set_effective +EXPORT_SYMBOL vmlinux 0x00000000 capable +EXPORT_SYMBOL vmlinux 0x00000000 cdev_add +EXPORT_SYMBOL vmlinux 0x00000000 cdev_alloc +EXPORT_SYMBOL vmlinux 0x00000000 cdev_del +EXPORT_SYMBOL vmlinux 0x00000000 cdev_init +EXPORT_SYMBOL vmlinux 0x00000000 cfi_fixup +EXPORT_SYMBOL vmlinux 0x00000000 cfi_read_pri +EXPORT_SYMBOL vmlinux 0x00000000 cfi_varsize_frob +EXPORT_SYMBOL vmlinux 0x00000000 check_disk_change +EXPORT_SYMBOL vmlinux 0x00000000 clear_bdi_congested +EXPORT_SYMBOL vmlinux 0x00000000 clear_inode +EXPORT_SYMBOL vmlinux 0x00000000 clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0x00000000 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 clocksource_register +EXPORT_SYMBOL vmlinux 0x00000000 close_bdev_excl +EXPORT_SYMBOL vmlinux 0x00000000 complete +EXPORT_SYMBOL vmlinux 0x00000000 complete_all +EXPORT_SYMBOL vmlinux 0x00000000 complete_and_exit +EXPORT_SYMBOL vmlinux 0x00000000 completion_done +EXPORT_SYMBOL vmlinux 0x00000000 compute_creds +EXPORT_SYMBOL vmlinux 0x00000000 cond_resched_lock +EXPORT_SYMBOL vmlinux 0x00000000 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x00000000 congestion_wait +EXPORT_SYMBOL vmlinux 0x00000000 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0x00000000 console_print +EXPORT_SYMBOL vmlinux 0x00000000 console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x00000000 console_start +EXPORT_SYMBOL vmlinux 0x00000000 console_stop +EXPORT_SYMBOL vmlinux 0x00000000 console_suspend_enabled +EXPORT_SYMBOL vmlinux 0x00000000 cont_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 contig_page_data +EXPORT_SYMBOL vmlinux 0x00000000 copy_io_context +EXPORT_SYMBOL vmlinux 0x00000000 copy_page +EXPORT_SYMBOL vmlinux 0x00000000 copy_strings_kernel +EXPORT_SYMBOL vmlinux 0x00000000 cpu_cache +EXPORT_SYMBOL vmlinux 0x00000000 cpu_feroceon_dcache_clean_area +EXPORT_SYMBOL vmlinux 0x00000000 cpu_feroceon_set_pte_ext +EXPORT_SYMBOL vmlinux 0x00000000 cpu_online_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_possible_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_present_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0x00000000 crc32_be +EXPORT_SYMBOL vmlinux 0x00000000 crc32_le +EXPORT_SYMBOL vmlinux 0x00000000 crc_t10dif +EXPORT_SYMBOL vmlinux 0x00000000 create_empty_buffers +EXPORT_SYMBOL vmlinux 0x00000000 create_proc_entry +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_nocheck +EXPORT_SYMBOL vmlinux 0x00000000 current_fs_time +EXPORT_SYMBOL vmlinux 0x00000000 current_kernel_time +EXPORT_SYMBOL vmlinux 0x00000000 d_add_ci +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_anon +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_name +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_root +EXPORT_SYMBOL vmlinux 0x00000000 d_delete +EXPORT_SYMBOL vmlinux 0x00000000 d_find_alias +EXPORT_SYMBOL vmlinux 0x00000000 d_genocide +EXPORT_SYMBOL vmlinux 0x00000000 d_instantiate +EXPORT_SYMBOL vmlinux 0x00000000 d_instantiate_unique +EXPORT_SYMBOL vmlinux 0x00000000 d_invalidate +EXPORT_SYMBOL vmlinux 0x00000000 d_lookup +EXPORT_SYMBOL vmlinux 0x00000000 d_move +EXPORT_SYMBOL vmlinux 0x00000000 d_namespace_path +EXPORT_SYMBOL vmlinux 0x00000000 d_path +EXPORT_SYMBOL vmlinux 0x00000000 d_prune_aliases +EXPORT_SYMBOL vmlinux 0x00000000 d_rehash +EXPORT_SYMBOL vmlinux 0x00000000 d_splice_alias +EXPORT_SYMBOL vmlinux 0x00000000 d_validate +EXPORT_SYMBOL vmlinux 0x00000000 daemonize +EXPORT_SYMBOL vmlinux 0x00000000 datagram_poll +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_close +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_open +EXPORT_SYMBOL vmlinux 0x00000000 dcache_lock +EXPORT_SYMBOL vmlinux 0x00000000 dcache_readdir +EXPORT_SYMBOL vmlinux 0x00000000 deactivate_super +EXPORT_SYMBOL vmlinux 0x00000000 debug_smp_processor_id +EXPORT_SYMBOL vmlinux 0x00000000 default_llseek +EXPORT_SYMBOL vmlinux 0x00000000 default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0x00000000 default_wake_function +EXPORT_SYMBOL vmlinux 0x00000000 del_gendisk +EXPORT_SYMBOL vmlinux 0x00000000 del_mtd_partitions +EXPORT_SYMBOL vmlinux 0x00000000 del_timer +EXPORT_SYMBOL vmlinux 0x00000000 dentry_open +EXPORT_SYMBOL vmlinux 0x00000000 dentry_unhash +EXPORT_SYMBOL vmlinux 0x00000000 deny_write_access +EXPORT_SYMBOL vmlinux 0x00000000 dev_add_pack +EXPORT_SYMBOL vmlinux 0x00000000 dev_alloc_name +EXPORT_SYMBOL vmlinux 0x00000000 dev_alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 dev_base_lock +EXPORT_SYMBOL vmlinux 0x00000000 dev_change_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_close +EXPORT_SYMBOL vmlinux 0x00000000 dev_disable_lro +EXPORT_SYMBOL vmlinux 0x00000000 dev_driver_string +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_index +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_name +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_getbyhwaddr +EXPORT_SYMBOL vmlinux 0x00000000 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x00000000 dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0x00000000 dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x00000000 dev_load +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_add +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_delete +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_sync +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x00000000 dev_open +EXPORT_SYMBOL vmlinux 0x00000000 dev_queue_xmit +EXPORT_SYMBOL vmlinux 0x00000000 dev_remove_pack +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_allmulti +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_mac_address +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_mtu +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_add +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_delete +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_sync +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0x00000000 dev_valid_name +EXPORT_SYMBOL vmlinux 0x00000000 devm_free_irq +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioport_map +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioremap +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0x00000000 devm_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 devm_request_irq +EXPORT_SYMBOL vmlinux 0x00000000 dget_locked +EXPORT_SYMBOL vmlinux 0x00000000 directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0x00000000 disable_hlt +EXPORT_SYMBOL vmlinux 0x00000000 disable_irq +EXPORT_SYMBOL vmlinux 0x00000000 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x00000000 disallow_signal +EXPORT_SYMBOL vmlinux 0x00000000 div64_u64 +EXPORT_SYMBOL vmlinux 0x00000000 div_s64_rem +EXPORT_SYMBOL vmlinux 0x00000000 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_alloc_writecombine +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_client_chan_request +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_client_register +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_client_unregister +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_device_register +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_device_unregister +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_memcpy_buf_to_buf +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_memcpy_buf_to_pg +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_memcpy_pg_to_pg +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_tx_descriptor_init +EXPORT_SYMBOL vmlinux 0x00000000 dma_cache_maint +EXPORT_SYMBOL vmlinux 0x00000000 dma_chan_cleanup +EXPORT_SYMBOL vmlinux 0x00000000 dma_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x00000000 dma_free_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_mark_declared_memory_occupied +EXPORT_SYMBOL vmlinux 0x00000000 dma_mmap_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_mmap_writecombine +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_create +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_free +EXPORT_SYMBOL vmlinux 0x00000000 dma_release_declared_memory +EXPORT_SYMBOL vmlinux 0x00000000 dma_sync_wait +EXPORT_SYMBOL vmlinux 0x00000000 dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x00000000 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_pool_create +EXPORT_SYMBOL vmlinux 0x00000000 dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dmam_release_declared_memory +EXPORT_SYMBOL vmlinux 0x00000000 do_SAK +EXPORT_SYMBOL vmlinux 0x00000000 do_brk +EXPORT_SYMBOL vmlinux 0x00000000 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x00000000 do_map_probe +EXPORT_SYMBOL vmlinux 0x00000000 do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0x00000000 do_munmap +EXPORT_SYMBOL vmlinux 0x00000000 do_settimeofday +EXPORT_SYMBOL vmlinux 0x00000000 do_splice_from +EXPORT_SYMBOL vmlinux 0x00000000 do_splice_to +EXPORT_SYMBOL vmlinux 0x00000000 do_sync_read +EXPORT_SYMBOL vmlinux 0x00000000 do_sync_write +EXPORT_SYMBOL vmlinux 0x00000000 down +EXPORT_SYMBOL vmlinux 0x00000000 down_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 down_killable +EXPORT_SYMBOL vmlinux 0x00000000 down_read +EXPORT_SYMBOL vmlinux 0x00000000 down_read_trylock +EXPORT_SYMBOL vmlinux 0x00000000 down_timeout +EXPORT_SYMBOL vmlinux 0x00000000 down_trylock +EXPORT_SYMBOL vmlinux 0x00000000 down_write +EXPORT_SYMBOL vmlinux 0x00000000 down_write_trylock +EXPORT_SYMBOL vmlinux 0x00000000 downgrade_write +EXPORT_SYMBOL vmlinux 0x00000000 dput +EXPORT_SYMBOL vmlinux 0x00000000 drop_super +EXPORT_SYMBOL vmlinux 0x00000000 dst_alloc +EXPORT_SYMBOL vmlinux 0x00000000 dst_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dst_discard +EXPORT_SYMBOL vmlinux 0x00000000 dst_release +EXPORT_SYMBOL vmlinux 0x00000000 dump_fpu +EXPORT_SYMBOL vmlinux 0x00000000 dump_stack +EXPORT_SYMBOL vmlinux 0x00000000 elevator_exit +EXPORT_SYMBOL vmlinux 0x00000000 elevator_init +EXPORT_SYMBOL vmlinux 0x00000000 elf_hwcap +EXPORT_SYMBOL vmlinux 0x00000000 elf_platform +EXPORT_SYMBOL vmlinux 0x00000000 elv_add_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_dequeue_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0x00000000 elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0x00000000 elv_next_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_queue_empty +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_add +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_del +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_find +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_former_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0x00000000 empty_zero_page +EXPORT_SYMBOL vmlinux 0x00000000 enable_hlt +EXPORT_SYMBOL vmlinux 0x00000000 enable_irq +EXPORT_SYMBOL vmlinux 0x00000000 end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0x00000000 end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0x00000000 end_dequeued_request +EXPORT_SYMBOL vmlinux 0x00000000 end_page_writeback +EXPORT_SYMBOL vmlinux 0x00000000 end_queued_request +EXPORT_SYMBOL vmlinux 0x00000000 end_request +EXPORT_SYMBOL vmlinux 0x00000000 eth_header +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_cache +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_cache_update +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_parse +EXPORT_SYMBOL vmlinux 0x00000000 eth_rebuild_header +EXPORT_SYMBOL vmlinux 0x00000000 eth_type_trans +EXPORT_SYMBOL vmlinux 0x00000000 ether_setup +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_tx_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0x00000000 f_setown +EXPORT_SYMBOL vmlinux 0x00000000 fasync_helper +EXPORT_SYMBOL vmlinux 0x00000000 fb_register_client +EXPORT_SYMBOL vmlinux 0x00000000 fb_unregister_client +EXPORT_SYMBOL vmlinux 0x00000000 fd_install +EXPORT_SYMBOL vmlinux 0x00000000 feroceon_clear_user_page +EXPORT_SYMBOL vmlinux 0x00000000 feroceon_copy_user_page +EXPORT_SYMBOL vmlinux 0x00000000 fget +EXPORT_SYMBOL vmlinux 0x00000000 file_fsync +EXPORT_SYMBOL vmlinux 0x00000000 file_permission +EXPORT_SYMBOL vmlinux 0x00000000 file_remove_suid +EXPORT_SYMBOL vmlinux 0x00000000 file_update_time +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fault +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawait +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0x00000000 filemap_flush +EXPORT_SYMBOL vmlinux 0x00000000 filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0x00000000 filp_close +EXPORT_SYMBOL vmlinux 0x00000000 filp_open +EXPORT_SYMBOL vmlinux 0x00000000 find_get_page +EXPORT_SYMBOL vmlinux 0x00000000 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0x00000000 find_get_pages_tag +EXPORT_SYMBOL vmlinux 0x00000000 find_inode_number +EXPORT_SYMBOL vmlinux 0x00000000 find_lock_page +EXPORT_SYMBOL vmlinux 0x00000000 find_or_create_page +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_vpid +EXPORT_SYMBOL vmlinux 0x00000000 find_vma +EXPORT_SYMBOL vmlinux 0x00000000 finish_wait +EXPORT_SYMBOL vmlinux 0x00000000 flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0x00000000 flow_cache_genid +EXPORT_SYMBOL vmlinux 0x00000000 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x00000000 flush_dcache_page +EXPORT_SYMBOL vmlinux 0x00000000 flush_old_exec +EXPORT_SYMBOL vmlinux 0x00000000 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x00000000 flush_signals +EXPORT_SYMBOL vmlinux 0x00000000 follow_down +EXPORT_SYMBOL vmlinux 0x00000000 follow_up +EXPORT_SYMBOL vmlinux 0x00000000 force_sig +EXPORT_SYMBOL vmlinux 0x00000000 fp_printk +EXPORT_SYMBOL vmlinux 0x00000000 fp_send_sig +EXPORT_SYMBOL vmlinux 0x00000000 fput +EXPORT_SYMBOL vmlinux 0x00000000 free_buffer_head +EXPORT_SYMBOL vmlinux 0x00000000 free_irq +EXPORT_SYMBOL vmlinux 0x00000000 free_netdev +EXPORT_SYMBOL vmlinux 0x00000000 free_pages +EXPORT_SYMBOL vmlinux 0x00000000 free_pages_exact +EXPORT_SYMBOL vmlinux 0x00000000 free_task +EXPORT_SYMBOL vmlinux 0x00000000 freeze_bdev +EXPORT_SYMBOL vmlinux 0x00000000 fs_overflowgid +EXPORT_SYMBOL vmlinux 0x00000000 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x00000000 fsync_bdev +EXPORT_SYMBOL vmlinux 0x00000000 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0x00000000 gen_new_estimator +EXPORT_SYMBOL vmlinux 0x00000000 gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x00000000 generate_random_uuid +EXPORT_SYMBOL vmlinux 0x00000000 generic_block_bmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0x00000000 generic_delete_inode +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_read +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_direct_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_llseek +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_mmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_open +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_read +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0x00000000 generic_fillattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_getxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_listxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_make_request +EXPORT_SYMBOL vmlinux 0x00000000 generic_mii_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 generic_osync_inode +EXPORT_SYMBOL vmlinux 0x00000000 generic_permission +EXPORT_SYMBOL vmlinux 0x00000000 generic_read_dir +EXPORT_SYMBOL vmlinux 0x00000000 generic_readlink +EXPORT_SYMBOL vmlinux 0x00000000 generic_removexattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_ro_fops +EXPORT_SYMBOL vmlinux 0x00000000 generic_segment_checks +EXPORT_SYMBOL vmlinux 0x00000000 generic_setlease +EXPORT_SYMBOL vmlinux 0x00000000 generic_setxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_show_options +EXPORT_SYMBOL vmlinux 0x00000000 generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x00000000 generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 generic_unplug_device +EXPORT_SYMBOL vmlinux 0x00000000 generic_write_checks +EXPORT_SYMBOL vmlinux 0x00000000 generic_write_end +EXPORT_SYMBOL vmlinux 0x00000000 generic_writepages +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_family +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_ops +EXPORT_SYMBOL vmlinux 0x00000000 genl_sock +EXPORT_SYMBOL vmlinux 0x00000000 genl_unregister_family +EXPORT_SYMBOL vmlinux 0x00000000 genl_unregister_ops +EXPORT_SYMBOL vmlinux 0x00000000 get_disk +EXPORT_SYMBOL vmlinux 0x00000000 get_empty_filp +EXPORT_SYMBOL vmlinux 0x00000000 get_fs_type +EXPORT_SYMBOL vmlinux 0x00000000 get_io_context +EXPORT_SYMBOL vmlinux 0x00000000 get_jiffies_64 +EXPORT_SYMBOL vmlinux 0x00000000 get_nfs_grace_period +EXPORT_SYMBOL vmlinux 0x00000000 get_option +EXPORT_SYMBOL vmlinux 0x00000000 get_options +EXPORT_SYMBOL vmlinux 0x00000000 get_random_bytes +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_bdev +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_nodev +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_single +EXPORT_SYMBOL vmlinux 0x00000000 get_seconds +EXPORT_SYMBOL vmlinux 0x00000000 get_super +EXPORT_SYMBOL vmlinux 0x00000000 get_unmapped_area +EXPORT_SYMBOL vmlinux 0x00000000 get_unused_fd +EXPORT_SYMBOL vmlinux 0x00000000 get_user_pages +EXPORT_SYMBOL vmlinux 0x00000000 get_write_access +EXPORT_SYMBOL vmlinux 0x00000000 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x00000000 getname +EXPORT_SYMBOL vmlinux 0x00000000 getnstimeofday +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x00000000 gpio_direction_input +EXPORT_SYMBOL vmlinux 0x00000000 gpio_direction_output +EXPORT_SYMBOL vmlinux 0x00000000 gpio_free +EXPORT_SYMBOL vmlinux 0x00000000 gpio_get_value +EXPORT_SYMBOL vmlinux 0x00000000 gpio_request +EXPORT_SYMBOL vmlinux 0x00000000 gpio_set_value +EXPORT_SYMBOL vmlinux 0x00000000 grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0x00000000 groups_alloc +EXPORT_SYMBOL vmlinux 0x00000000 groups_free +EXPORT_SYMBOL vmlinux 0x00000000 half_md4_transform +EXPORT_SYMBOL vmlinux 0x00000000 handle_sysrq +EXPORT_SYMBOL vmlinux 0x00000000 have_submounts +EXPORT_SYMBOL vmlinux 0x00000000 hex_asc +EXPORT_SYMBOL vmlinux 0x00000000 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x00000000 high_memory +EXPORT_SYMBOL vmlinux 0x00000000 hweight16 +EXPORT_SYMBOL vmlinux 0x00000000 hweight32 +EXPORT_SYMBOL vmlinux 0x00000000 hweight64 +EXPORT_SYMBOL vmlinux 0x00000000 hweight8 +EXPORT_SYMBOL vmlinux 0x00000000 i2c_add_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_attach_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_clients_command +EXPORT_SYMBOL vmlinux 0x00000000 i2c_del_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_del_driver +EXPORT_SYMBOL vmlinux 0x00000000 i2c_detach_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_get_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_master_recv +EXPORT_SYMBOL vmlinux 0x00000000 i2c_master_send +EXPORT_SYMBOL vmlinux 0x00000000 i2c_probe +EXPORT_SYMBOL vmlinux 0x00000000 i2c_put_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 i2c_release_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_byte +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_byte_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_word_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_byte +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_byte_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_word_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_xfer +EXPORT_SYMBOL vmlinux 0x00000000 i2c_transfer +EXPORT_SYMBOL vmlinux 0x00000000 i2c_use_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_verify_client +EXPORT_SYMBOL vmlinux 0x00000000 icmp_err_convert +EXPORT_SYMBOL vmlinux 0x00000000 icmp_send +EXPORT_SYMBOL vmlinux 0x00000000 ida_destroy +EXPORT_SYMBOL vmlinux 0x00000000 ida_get_new +EXPORT_SYMBOL vmlinux 0x00000000 ida_get_new_above +EXPORT_SYMBOL vmlinux 0x00000000 ida_init +EXPORT_SYMBOL vmlinux 0x00000000 ida_pre_get +EXPORT_SYMBOL vmlinux 0x00000000 ida_remove +EXPORT_SYMBOL vmlinux 0x00000000 idr_destroy +EXPORT_SYMBOL vmlinux 0x00000000 idr_find +EXPORT_SYMBOL vmlinux 0x00000000 idr_for_each +EXPORT_SYMBOL vmlinux 0x00000000 idr_get_new +EXPORT_SYMBOL vmlinux 0x00000000 idr_get_new_above +EXPORT_SYMBOL vmlinux 0x00000000 idr_init +EXPORT_SYMBOL vmlinux 0x00000000 idr_pre_get +EXPORT_SYMBOL vmlinux 0x00000000 idr_remove +EXPORT_SYMBOL vmlinux 0x00000000 idr_remove_all +EXPORT_SYMBOL vmlinux 0x00000000 idr_replace +EXPORT_SYMBOL vmlinux 0x00000000 ifla_policy +EXPORT_SYMBOL vmlinux 0x00000000 iget5_locked +EXPORT_SYMBOL vmlinux 0x00000000 iget_failed +EXPORT_SYMBOL vmlinux 0x00000000 iget_locked +EXPORT_SYMBOL vmlinux 0x00000000 igrab +EXPORT_SYMBOL vmlinux 0x00000000 ilookup +EXPORT_SYMBOL vmlinux 0x00000000 ilookup5 +EXPORT_SYMBOL vmlinux 0x00000000 ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x00000000 in4_pton +EXPORT_SYMBOL vmlinux 0x00000000 in6_pton +EXPORT_SYMBOL vmlinux 0x00000000 in_aton +EXPORT_SYMBOL vmlinux 0x00000000 in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x00000000 in_egroup_p +EXPORT_SYMBOL vmlinux 0x00000000 in_group_p +EXPORT_SYMBOL vmlinux 0x00000000 inet_accept +EXPORT_SYMBOL vmlinux 0x00000000 inet_add_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet_addr_type +EXPORT_SYMBOL vmlinux 0x00000000 inet_bind +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_accept +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x00000000 inet_del_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0x00000000 inet_dgram_connect +EXPORT_SYMBOL vmlinux 0x00000000 inet_dgram_ops +EXPORT_SYMBOL vmlinux 0x00000000 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_destroy +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_evictor +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_find +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_kill +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_fini +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_init +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x00000000 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x00000000 inet_getname +EXPORT_SYMBOL vmlinux 0x00000000 inet_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 inet_listen +EXPORT_SYMBOL vmlinux 0x00000000 inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0x00000000 inet_put_port +EXPORT_SYMBOL vmlinux 0x00000000 inet_register_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inet_release +EXPORT_SYMBOL vmlinux 0x00000000 inet_select_addr +EXPORT_SYMBOL vmlinux 0x00000000 inet_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 inet_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0x00000000 inet_sock_destruct +EXPORT_SYMBOL vmlinux 0x00000000 inet_stream_connect +EXPORT_SYMBOL vmlinux 0x00000000 inet_stream_ops +EXPORT_SYMBOL vmlinux 0x00000000 inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0x00000000 inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inetdev_by_index +EXPORT_SYMBOL vmlinux 0x00000000 init_buffer +EXPORT_SYMBOL vmlinux 0x00000000 init_file +EXPORT_SYMBOL vmlinux 0x00000000 init_mm +EXPORT_SYMBOL vmlinux 0x00000000 init_net +EXPORT_SYMBOL vmlinux 0x00000000 init_special_inode +EXPORT_SYMBOL vmlinux 0x00000000 init_task +EXPORT_SYMBOL vmlinux 0x00000000 init_timer +EXPORT_SYMBOL vmlinux 0x00000000 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0x00000000 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x00000000 inode_add_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_change_ok +EXPORT_SYMBOL vmlinux 0x00000000 inode_double_lock +EXPORT_SYMBOL vmlinux 0x00000000 inode_double_unlock +EXPORT_SYMBOL vmlinux 0x00000000 inode_get_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_init_once +EXPORT_SYMBOL vmlinux 0x00000000 inode_needs_sync +EXPORT_SYMBOL vmlinux 0x00000000 inode_permission +EXPORT_SYMBOL vmlinux 0x00000000 inode_set_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_setattr +EXPORT_SYMBOL vmlinux 0x00000000 inode_sub_bytes +EXPORT_SYMBOL vmlinux 0x00000000 input_allocate_device +EXPORT_SYMBOL vmlinux 0x00000000 input_close_device +EXPORT_SYMBOL vmlinux 0x00000000 input_event +EXPORT_SYMBOL vmlinux 0x00000000 input_flush_device +EXPORT_SYMBOL vmlinux 0x00000000 input_free_device +EXPORT_SYMBOL vmlinux 0x00000000 input_get_keycode +EXPORT_SYMBOL vmlinux 0x00000000 input_grab_device +EXPORT_SYMBOL vmlinux 0x00000000 input_inject_event +EXPORT_SYMBOL vmlinux 0x00000000 input_open_device +EXPORT_SYMBOL vmlinux 0x00000000 input_register_device +EXPORT_SYMBOL vmlinux 0x00000000 input_register_handle +EXPORT_SYMBOL vmlinux 0x00000000 input_register_handler +EXPORT_SYMBOL vmlinux 0x00000000 input_release_device +EXPORT_SYMBOL vmlinux 0x00000000 input_set_capability +EXPORT_SYMBOL vmlinux 0x00000000 input_set_keycode +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_device +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_handle +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_handler +EXPORT_SYMBOL vmlinux 0x00000000 int_sqrt +EXPORT_SYMBOL vmlinux 0x00000000 int_to_scsilun +EXPORT_SYMBOL vmlinux 0x00000000 interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0x00000000 interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_bdev +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_inodes +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_partition +EXPORT_SYMBOL vmlinux 0x00000000 io_schedule +EXPORT_SYMBOL vmlinux 0x00000000 ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x00000000 iomem_resource +EXPORT_SYMBOL vmlinux 0x00000000 ioport_map +EXPORT_SYMBOL vmlinux 0x00000000 ioport_resource +EXPORT_SYMBOL vmlinux 0x00000000 ioport_unmap +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_advance +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0x00000000 iov_shorten +EXPORT_SYMBOL vmlinux 0x00000000 ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0x00000000 ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0x00000000 ip_defrag +EXPORT_SYMBOL vmlinux 0x00000000 ip_dev_find +EXPORT_SYMBOL vmlinux 0x00000000 ip_fragment +EXPORT_SYMBOL vmlinux 0x00000000 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0x00000000 ip_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_join_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0x00000000 ip_route_input +EXPORT_SYMBOL vmlinux 0x00000000 ip_route_output_key +EXPORT_SYMBOL vmlinux 0x00000000 ip_send_check +EXPORT_SYMBOL vmlinux 0x00000000 ip_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 iput +EXPORT_SYMBOL vmlinux 0x00000000 ipv4_config +EXPORT_SYMBOL vmlinux 0x00000000 ipv4_specific +EXPORT_SYMBOL vmlinux 0x00000000 irq_stat +EXPORT_SYMBOL vmlinux 0x00000000 is_bad_inode +EXPORT_SYMBOL vmlinux 0x00000000 is_container_init +EXPORT_SYMBOL vmlinux 0x00000000 isa_dma_bridge_buggy +EXPORT_SYMBOL vmlinux 0x00000000 iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0x00000000 iunique +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_get_spy +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_get_thrspy +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_set_spy +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_set_thrspy +EXPORT_SYMBOL vmlinux 0x00000000 jiffies +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_64 +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x00000000 journal_abort +EXPORT_SYMBOL vmlinux 0x00000000 journal_ack_err +EXPORT_SYMBOL vmlinux 0x00000000 journal_blocks_per_page +EXPORT_SYMBOL vmlinux 0x00000000 journal_check_available_features +EXPORT_SYMBOL vmlinux 0x00000000 journal_check_used_features +EXPORT_SYMBOL vmlinux 0x00000000 journal_clear_err +EXPORT_SYMBOL vmlinux 0x00000000 journal_create +EXPORT_SYMBOL vmlinux 0x00000000 journal_destroy +EXPORT_SYMBOL vmlinux 0x00000000 journal_dirty_data +EXPORT_SYMBOL vmlinux 0x00000000 journal_dirty_metadata +EXPORT_SYMBOL vmlinux 0x00000000 journal_errno +EXPORT_SYMBOL vmlinux 0x00000000 journal_extend +EXPORT_SYMBOL vmlinux 0x00000000 journal_flush +EXPORT_SYMBOL vmlinux 0x00000000 journal_force_commit +EXPORT_SYMBOL vmlinux 0x00000000 journal_force_commit_nested +EXPORT_SYMBOL vmlinux 0x00000000 journal_forget +EXPORT_SYMBOL vmlinux 0x00000000 journal_get_create_access +EXPORT_SYMBOL vmlinux 0x00000000 journal_get_undo_access +EXPORT_SYMBOL vmlinux 0x00000000 journal_get_write_access +EXPORT_SYMBOL vmlinux 0x00000000 journal_init_dev +EXPORT_SYMBOL vmlinux 0x00000000 journal_init_inode +EXPORT_SYMBOL vmlinux 0x00000000 journal_invalidatepage +EXPORT_SYMBOL vmlinux 0x00000000 journal_load +EXPORT_SYMBOL vmlinux 0x00000000 journal_lock_updates +EXPORT_SYMBOL vmlinux 0x00000000 journal_release_buffer +EXPORT_SYMBOL vmlinux 0x00000000 journal_restart +EXPORT_SYMBOL vmlinux 0x00000000 journal_revoke +EXPORT_SYMBOL vmlinux 0x00000000 journal_set_features +EXPORT_SYMBOL vmlinux 0x00000000 journal_start +EXPORT_SYMBOL vmlinux 0x00000000 journal_start_commit +EXPORT_SYMBOL vmlinux 0x00000000 journal_stop +EXPORT_SYMBOL vmlinux 0x00000000 journal_try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x00000000 journal_unlock_updates +EXPORT_SYMBOL vmlinux 0x00000000 journal_update_format +EXPORT_SYMBOL vmlinux 0x00000000 journal_wipe +EXPORT_SYMBOL vmlinux 0x00000000 kasprintf +EXPORT_SYMBOL vmlinux 0x00000000 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0x00000000 kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0x00000000 kern_fp_enter +EXPORT_SYMBOL vmlinux 0x00000000 kernel_accept +EXPORT_SYMBOL vmlinux 0x00000000 kernel_bind +EXPORT_SYMBOL vmlinux 0x00000000 kernel_connect +EXPORT_SYMBOL vmlinux 0x00000000 kernel_execve +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getpeername +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getsockname +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 kernel_listen +EXPORT_SYMBOL vmlinux 0x00000000 kernel_read +EXPORT_SYMBOL vmlinux 0x00000000 kernel_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 kernel_thread +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_alloc +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_free +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_init +EXPORT_SYMBOL vmlinux 0x00000000 kfree +EXPORT_SYMBOL vmlinux 0x00000000 kfree_skb +EXPORT_SYMBOL vmlinux 0x00000000 kick_iocb +EXPORT_SYMBOL vmlinux 0x00000000 kill_anon_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_block_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_fasync +EXPORT_SYMBOL vmlinux 0x00000000 kill_litter_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_pgrp +EXPORT_SYMBOL vmlinux 0x00000000 kill_pid +EXPORT_SYMBOL vmlinux 0x00000000 km_new_mapping +EXPORT_SYMBOL vmlinux 0x00000000 km_policy_expired +EXPORT_SYMBOL vmlinux 0x00000000 km_policy_notify +EXPORT_SYMBOL vmlinux 0x00000000 km_query +EXPORT_SYMBOL vmlinux 0x00000000 km_report +EXPORT_SYMBOL vmlinux 0x00000000 km_state_expired +EXPORT_SYMBOL vmlinux 0x00000000 km_state_notify +EXPORT_SYMBOL vmlinux 0x00000000 km_waitq +EXPORT_SYMBOL vmlinux 0x00000000 kmalloc_caches +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_create +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_free +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_name +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_size +EXPORT_SYMBOL vmlinux 0x00000000 kmem_ptr_validate +EXPORT_SYMBOL vmlinux 0x00000000 kmemdup +EXPORT_SYMBOL vmlinux 0x00000000 kobject_add +EXPORT_SYMBOL vmlinux 0x00000000 kobject_del +EXPORT_SYMBOL vmlinux 0x00000000 kobject_get +EXPORT_SYMBOL vmlinux 0x00000000 kobject_init +EXPORT_SYMBOL vmlinux 0x00000000 kobject_put +EXPORT_SYMBOL vmlinux 0x00000000 kobject_set_name +EXPORT_SYMBOL vmlinux 0x00000000 krealloc +EXPORT_SYMBOL vmlinux 0x00000000 kref_get +EXPORT_SYMBOL vmlinux 0x00000000 kref_init +EXPORT_SYMBOL vmlinux 0x00000000 kref_put +EXPORT_SYMBOL vmlinux 0x00000000 kref_set +EXPORT_SYMBOL vmlinux 0x00000000 kset_register +EXPORT_SYMBOL vmlinux 0x00000000 kset_unregister +EXPORT_SYMBOL vmlinux 0x00000000 kstrdup +EXPORT_SYMBOL vmlinux 0x00000000 kstrndup +EXPORT_SYMBOL vmlinux 0x00000000 kthread_bind +EXPORT_SYMBOL vmlinux 0x00000000 kthread_create +EXPORT_SYMBOL vmlinux 0x00000000 kthread_should_stop +EXPORT_SYMBOL vmlinux 0x00000000 kthread_stop +EXPORT_SYMBOL vmlinux 0x00000000 kvasprintf +EXPORT_SYMBOL vmlinux 0x00000000 laptop_mode +EXPORT_SYMBOL vmlinux 0x00000000 lease_get_mtime +EXPORT_SYMBOL vmlinux 0x00000000 lease_modify +EXPORT_SYMBOL vmlinux 0x00000000 leds_event +EXPORT_SYMBOL vmlinux 0x00000000 linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0x00000000 ll_rw_block +EXPORT_SYMBOL vmlinux 0x00000000 load_nls +EXPORT_SYMBOL vmlinux 0x00000000 load_nls_default +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_disable +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_enable +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0x00000000 lock_kernel +EXPORT_SYMBOL vmlinux 0x00000000 lock_may_read +EXPORT_SYMBOL vmlinux 0x00000000 lock_may_write +EXPORT_SYMBOL vmlinux 0x00000000 lock_rename +EXPORT_SYMBOL vmlinux 0x00000000 lock_sock_nested +EXPORT_SYMBOL vmlinux 0x00000000 lock_super +EXPORT_SYMBOL vmlinux 0x00000000 lockd_down +EXPORT_SYMBOL vmlinux 0x00000000 lockd_up +EXPORT_SYMBOL vmlinux 0x00000000 locks_copy_lock +EXPORT_SYMBOL vmlinux 0x00000000 locks_init_lock +EXPORT_SYMBOL vmlinux 0x00000000 locks_mandatory_area +EXPORT_SYMBOL vmlinux 0x00000000 locks_remove_posix +EXPORT_SYMBOL vmlinux 0x00000000 log_wait_commit +EXPORT_SYMBOL vmlinux 0x00000000 lookup_bdev +EXPORT_SYMBOL vmlinux 0x00000000 lookup_one_len +EXPORT_SYMBOL vmlinux 0x00000000 loop_register_transfer +EXPORT_SYMBOL vmlinux 0x00000000 loop_unregister_transfer +EXPORT_SYMBOL vmlinux 0x00000000 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0x00000000 make_bad_inode +EXPORT_SYMBOL vmlinux 0x00000000 map_destroy +EXPORT_SYMBOL vmlinux 0x00000000 mapping_tagged +EXPORT_SYMBOL vmlinux 0x00000000 maps_protect +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x00000000 mark_page_accessed +EXPORT_SYMBOL vmlinux 0x00000000 match_hex +EXPORT_SYMBOL vmlinux 0x00000000 match_int +EXPORT_SYMBOL vmlinux 0x00000000 match_octal +EXPORT_SYMBOL vmlinux 0x00000000 match_strdup +EXPORT_SYMBOL vmlinux 0x00000000 match_strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 match_token +EXPORT_SYMBOL vmlinux 0x00000000 max_mapnr +EXPORT_SYMBOL vmlinux 0x00000000 may_umount +EXPORT_SYMBOL vmlinux 0x00000000 may_umount_tree +EXPORT_SYMBOL vmlinux 0x00000000 mem_map +EXPORT_SYMBOL vmlinux 0x00000000 memchr +EXPORT_SYMBOL vmlinux 0x00000000 memcmp +EXPORT_SYMBOL vmlinux 0x00000000 memcpy +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x00000000 memmove +EXPORT_SYMBOL vmlinux 0x00000000 memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 memparse +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x00000000 mempool_create +EXPORT_SYMBOL vmlinux 0x00000000 mempool_create_node +EXPORT_SYMBOL vmlinux 0x00000000 mempool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free_pages +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kfree +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_resize +EXPORT_SYMBOL vmlinux 0x00000000 memscan +EXPORT_SYMBOL vmlinux 0x00000000 memset +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_gmii_support +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_link +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_media +EXPORT_SYMBOL vmlinux 0x00000000 mii_ethtool_gset +EXPORT_SYMBOL vmlinux 0x00000000 mii_ethtool_sset +EXPORT_SYMBOL vmlinux 0x00000000 mii_link_ok +EXPORT_SYMBOL vmlinux 0x00000000 mii_nway_restart +EXPORT_SYMBOL vmlinux 0x00000000 misc_deregister +EXPORT_SYMBOL vmlinux 0x00000000 misc_register +EXPORT_SYMBOL vmlinux 0x00000000 mktime +EXPORT_SYMBOL vmlinux 0x00000000 mnt_pin +EXPORT_SYMBOL vmlinux 0x00000000 mnt_unpin +EXPORT_SYMBOL vmlinux 0x00000000 mntput_no_expire +EXPORT_SYMBOL vmlinux 0x00000000 mod_timer +EXPORT_SYMBOL vmlinux 0x00000000 module_put +EXPORT_SYMBOL vmlinux 0x00000000 module_refcount +EXPORT_SYMBOL vmlinux 0x00000000 mpage_bio_submit +EXPORT_SYMBOL vmlinux 0x00000000 mpage_readpage +EXPORT_SYMBOL vmlinux 0x00000000 mpage_readpages +EXPORT_SYMBOL vmlinux 0x00000000 mpage_writepage +EXPORT_SYMBOL vmlinux 0x00000000 mpage_writepages +EXPORT_SYMBOL vmlinux 0x00000000 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 msleep +EXPORT_SYMBOL vmlinux 0x00000000 msleep_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 mtd_do_chip_probe +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock_killable +EXPORT_SYMBOL vmlinux 0x00000000 mutex_trylock +EXPORT_SYMBOL vmlinux 0x00000000 mutex_unlock +EXPORT_SYMBOL vmlinux 0x00000000 n_tty_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 names_cachep +EXPORT_SYMBOL vmlinux 0x00000000 nand_calculate_ecc +EXPORT_SYMBOL vmlinux 0x00000000 nand_correct_data +EXPORT_SYMBOL vmlinux 0x00000000 nand_default_bbt +EXPORT_SYMBOL vmlinux 0x00000000 nand_flash_ids +EXPORT_SYMBOL vmlinux 0x00000000 nand_manuf_ids +EXPORT_SYMBOL vmlinux 0x00000000 nand_scan_bbt +EXPORT_SYMBOL vmlinux 0x00000000 neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x00000000 neigh_compat_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_connected_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_create +EXPORT_SYMBOL vmlinux 0x00000000 neigh_destroy +EXPORT_SYMBOL vmlinux 0x00000000 neigh_event_ns +EXPORT_SYMBOL vmlinux 0x00000000 neigh_for_each +EXPORT_SYMBOL vmlinux 0x00000000 neigh_ifdown +EXPORT_SYMBOL vmlinux 0x00000000 neigh_lookup +EXPORT_SYMBOL vmlinux 0x00000000 neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x00000000 neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0x00000000 neigh_parms_release +EXPORT_SYMBOL vmlinux 0x00000000 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x00000000 neigh_resolve_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_next +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_start +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_stop +EXPORT_SYMBOL vmlinux 0x00000000 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0x00000000 neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_clear +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_init +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0x00000000 neigh_update +EXPORT_SYMBOL vmlinux 0x00000000 net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 net_msg_warn +EXPORT_SYMBOL vmlinux 0x00000000 net_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0x00000000 netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0x00000000 netdev_class_create_file +EXPORT_SYMBOL vmlinux 0x00000000 netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0x00000000 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x00000000 netdev_features_change +EXPORT_SYMBOL vmlinux 0x00000000 netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0x00000000 netdev_set_master +EXPORT_SYMBOL vmlinux 0x00000000 netdev_state_change +EXPORT_SYMBOL vmlinux 0x00000000 netif_carrier_off +EXPORT_SYMBOL vmlinux 0x00000000 netif_carrier_on +EXPORT_SYMBOL vmlinux 0x00000000 netif_device_attach +EXPORT_SYMBOL vmlinux 0x00000000 netif_device_detach +EXPORT_SYMBOL vmlinux 0x00000000 netif_receive_skb +EXPORT_SYMBOL vmlinux 0x00000000 netif_rx +EXPORT_SYMBOL vmlinux 0x00000000 netif_rx_ni +EXPORT_SYMBOL vmlinux 0x00000000 netlink_ack +EXPORT_SYMBOL vmlinux 0x00000000 netlink_broadcast +EXPORT_SYMBOL vmlinux 0x00000000 netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0x00000000 netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0x00000000 netlink_dump_start +EXPORT_SYMBOL vmlinux 0x00000000 netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x00000000 netlink_kernel_release +EXPORT_SYMBOL vmlinux 0x00000000 netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0x00000000 netlink_register_notifier +EXPORT_SYMBOL vmlinux 0x00000000 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x00000000 netlink_unicast +EXPORT_SYMBOL vmlinux 0x00000000 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0x00000000 new_inode +EXPORT_SYMBOL vmlinux 0x00000000 nla_append +EXPORT_SYMBOL vmlinux 0x00000000 nla_find +EXPORT_SYMBOL vmlinux 0x00000000 nla_memcmp +EXPORT_SYMBOL vmlinux 0x00000000 nla_memcpy +EXPORT_SYMBOL vmlinux 0x00000000 nla_parse +EXPORT_SYMBOL vmlinux 0x00000000 nla_put +EXPORT_SYMBOL vmlinux 0x00000000 nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 nla_reserve +EXPORT_SYMBOL vmlinux 0x00000000 nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 nla_strcmp +EXPORT_SYMBOL vmlinux 0x00000000 nla_strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 nla_validate +EXPORT_SYMBOL vmlinux 0x00000000 nlmsg_notify +EXPORT_SYMBOL vmlinux 0x00000000 nlmsvc_ops +EXPORT_SYMBOL vmlinux 0x00000000 no_llseek +EXPORT_SYMBOL vmlinux 0x00000000 no_pci_devices +EXPORT_SYMBOL vmlinux 0x00000000 nobh_truncate_page +EXPORT_SYMBOL vmlinux 0x00000000 nobh_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 nobh_write_end +EXPORT_SYMBOL vmlinux 0x00000000 nobh_writepage +EXPORT_SYMBOL vmlinux 0x00000000 node_states +EXPORT_SYMBOL vmlinux 0x00000000 nonseekable_open +EXPORT_SYMBOL vmlinux 0x00000000 noop_qdisc +EXPORT_SYMBOL vmlinux 0x00000000 notify_change +EXPORT_SYMBOL vmlinux 0x00000000 ns_to_timespec +EXPORT_SYMBOL vmlinux 0x00000000 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x00000000 num_physpages +EXPORT_SYMBOL vmlinux 0x00000000 oops_in_progress +EXPORT_SYMBOL vmlinux 0x00000000 open_bdev_excl +EXPORT_SYMBOL vmlinux 0x00000000 open_by_devnum +EXPORT_SYMBOL vmlinux 0x00000000 open_exec +EXPORT_SYMBOL vmlinux 0x00000000 orion5x_gpio_set_blink +EXPORT_SYMBOL vmlinux 0x00000000 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0x00000000 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0x00000000 overflowgid +EXPORT_SYMBOL vmlinux 0x00000000 overflowuid +EXPORT_SYMBOL vmlinux 0x00000000 page_follow_link_light +EXPORT_SYMBOL vmlinux 0x00000000 page_put_link +EXPORT_SYMBOL vmlinux 0x00000000 page_readlink +EXPORT_SYMBOL vmlinux 0x00000000 page_symlink +EXPORT_SYMBOL vmlinux 0x00000000 page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0x00000000 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0x00000000 pagecache_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 pagecache_write_end +EXPORT_SYMBOL vmlinux 0x00000000 pagevec_lookup +EXPORT_SYMBOL vmlinux 0x00000000 pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0x00000000 panic +EXPORT_SYMBOL vmlinux 0x00000000 panic_blink +EXPORT_SYMBOL vmlinux 0x00000000 panic_notifier_list +EXPORT_SYMBOL vmlinux 0x00000000 param_array_get +EXPORT_SYMBOL vmlinux 0x00000000 param_array_set +EXPORT_SYMBOL vmlinux 0x00000000 param_get_bool +EXPORT_SYMBOL vmlinux 0x00000000 param_get_byte +EXPORT_SYMBOL vmlinux 0x00000000 param_get_charp +EXPORT_SYMBOL vmlinux 0x00000000 param_get_int +EXPORT_SYMBOL vmlinux 0x00000000 param_get_invbool +EXPORT_SYMBOL vmlinux 0x00000000 param_get_long +EXPORT_SYMBOL vmlinux 0x00000000 param_get_short +EXPORT_SYMBOL vmlinux 0x00000000 param_get_string +EXPORT_SYMBOL vmlinux 0x00000000 param_get_uint +EXPORT_SYMBOL vmlinux 0x00000000 param_get_ulong +EXPORT_SYMBOL vmlinux 0x00000000 param_get_ushort +EXPORT_SYMBOL vmlinux 0x00000000 param_set_bool +EXPORT_SYMBOL vmlinux 0x00000000 param_set_byte +EXPORT_SYMBOL vmlinux 0x00000000 param_set_charp +EXPORT_SYMBOL vmlinux 0x00000000 param_set_copystring +EXPORT_SYMBOL vmlinux 0x00000000 param_set_int +EXPORT_SYMBOL vmlinux 0x00000000 param_set_invbool +EXPORT_SYMBOL vmlinux 0x00000000 param_set_long +EXPORT_SYMBOL vmlinux 0x00000000 param_set_short +EXPORT_SYMBOL vmlinux 0x00000000 param_set_uint +EXPORT_SYMBOL vmlinux 0x00000000 param_set_ulong +EXPORT_SYMBOL vmlinux 0x00000000 param_set_ushort +EXPORT_SYMBOL vmlinux 0x00000000 path_get +EXPORT_SYMBOL vmlinux 0x00000000 path_lookup +EXPORT_SYMBOL vmlinux 0x00000000 path_permission +EXPORT_SYMBOL vmlinux 0x00000000 path_put +EXPORT_SYMBOL vmlinux 0x00000000 pci_add_new_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_assign_resource +EXPORT_SYMBOL vmlinux 0x00000000 pci_back_from_sleep +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_add_devices +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_alloc_resource +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_assign_resources +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_find_capability +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_read_config_byte +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_read_config_dword +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_read_config_word +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_size_bridges +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_type +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_write_config_byte +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_write_config_dword +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_write_config_word +EXPORT_SYMBOL vmlinux 0x00000000 pci_choose_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_clear_mwi +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_driver +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_get +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_present +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_put +EXPORT_SYMBOL vmlinux 0x00000000 pci_disable_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_bridges +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_device_io +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_device_mem +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_wake +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_capability +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_next_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_parent_resource +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_fixup_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_bus_and_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_class +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_subsys +EXPORT_SYMBOL vmlinux 0x00000000 pci_iomap +EXPORT_SYMBOL vmlinux 0x00000000 pci_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 pci_map_rom +EXPORT_SYMBOL vmlinux 0x00000000 pci_match_id +EXPORT_SYMBOL vmlinux 0x00000000 pci_pci_problems +EXPORT_SYMBOL vmlinux 0x00000000 pci_pme_active +EXPORT_SYMBOL vmlinux 0x00000000 pci_pme_capable +EXPORT_SYMBOL vmlinux 0x00000000 pci_prepare_to_sleep +EXPORT_SYMBOL vmlinux 0x00000000 pci_reenable_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_release_region +EXPORT_SYMBOL vmlinux 0x00000000 pci_release_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_release_selected_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_remove_behind_bridge +EXPORT_SYMBOL vmlinux 0x00000000 pci_remove_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_remove_bus_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_request_region +EXPORT_SYMBOL vmlinux 0x00000000 pci_request_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_request_selected_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_restore_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_root_buses +EXPORT_SYMBOL vmlinux 0x00000000 pci_save_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_bridge +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_bus_parented +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_single_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_select_bars +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_consistent_dma_mask +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_dma_mask +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_dma_max_seg_size +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_dma_seg_boundary +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_master +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_mwi +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_power_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_setup_cardbus +EXPORT_SYMBOL vmlinux 0x00000000 pci_target_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_try_set_mwi +EXPORT_SYMBOL vmlinux 0x00000000 pci_unmap_rom +EXPORT_SYMBOL vmlinux 0x00000000 pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 pcibios_bus_to_resource +EXPORT_SYMBOL vmlinux 0x00000000 pcibios_fixup_bus +EXPORT_SYMBOL vmlinux 0x00000000 pcibios_resource_to_bus +EXPORT_SYMBOL vmlinux 0x00000000 pcie_get_readrq +EXPORT_SYMBOL vmlinux 0x00000000 pcie_mch_quirk +EXPORT_SYMBOL vmlinux 0x00000000 pcie_set_readrq +EXPORT_SYMBOL vmlinux 0x00000000 pcim_enable_device +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap_regions +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap_regions_request_all +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap_table +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iounmap_regions +EXPORT_SYMBOL vmlinux 0x00000000 pcim_pin_device +EXPORT_SYMBOL vmlinux 0x00000000 pcix_get_max_mmrbc +EXPORT_SYMBOL vmlinux 0x00000000 pcix_get_mmrbc +EXPORT_SYMBOL vmlinux 0x00000000 pcix_set_mmrbc +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu____irq_regs +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x00000000 pgprot_kernel +EXPORT_SYMBOL vmlinux 0x00000000 pgprot_user +EXPORT_SYMBOL vmlinux 0x00000000 pid_task +EXPORT_SYMBOL vmlinux 0x00000000 pm_idle +EXPORT_SYMBOL vmlinux 0x00000000 pm_power_off +EXPORT_SYMBOL vmlinux 0x00000000 pneigh_enqueue +EXPORT_SYMBOL vmlinux 0x00000000 pneigh_lookup +EXPORT_SYMBOL vmlinux 0x00000000 poll_freewait +EXPORT_SYMBOL vmlinux 0x00000000 poll_initwait +EXPORT_SYMBOL vmlinux 0x00000000 posix_lock_file +EXPORT_SYMBOL vmlinux 0x00000000 posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0x00000000 posix_test_lock +EXPORT_SYMBOL vmlinux 0x00000000 posix_unblock_lock +EXPORT_SYMBOL vmlinux 0x00000000 preempt_schedule +EXPORT_SYMBOL vmlinux 0x00000000 prepare_binprm +EXPORT_SYMBOL vmlinux 0x00000000 prepare_to_wait +EXPORT_SYMBOL vmlinux 0x00000000 prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0x00000000 print_hex_dump +EXPORT_SYMBOL vmlinux 0x00000000 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x00000000 print_mac +EXPORT_SYMBOL vmlinux 0x00000000 printk +EXPORT_SYMBOL vmlinux 0x00000000 printk_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_mask +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_off +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_on +EXPORT_SYMBOL vmlinux 0x00000000 proc_create_data +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dostring +EXPORT_SYMBOL vmlinux 0x00000000 proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_mkdir +EXPORT_SYMBOL vmlinux 0x00000000 proc_symlink +EXPORT_SYMBOL vmlinux 0x00000000 processor_id +EXPORT_SYMBOL vmlinux 0x00000000 proto_register +EXPORT_SYMBOL vmlinux 0x00000000 proto_unregister +EXPORT_SYMBOL vmlinux 0x00000000 pskb_copy +EXPORT_SYMBOL vmlinux 0x00000000 pskb_expand_head +EXPORT_SYMBOL vmlinux 0x00000000 put_cmsg +EXPORT_SYMBOL vmlinux 0x00000000 put_disk +EXPORT_SYMBOL vmlinux 0x00000000 put_filp +EXPORT_SYMBOL vmlinux 0x00000000 put_io_context +EXPORT_SYMBOL vmlinux 0x00000000 put_page +EXPORT_SYMBOL vmlinux 0x00000000 put_pages_list +EXPORT_SYMBOL vmlinux 0x00000000 put_tty_driver +EXPORT_SYMBOL vmlinux 0x00000000 put_unused_fd +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_destroy +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_reset +EXPORT_SYMBOL vmlinux 0x00000000 qword_add +EXPORT_SYMBOL vmlinux 0x00000000 qword_addhex +EXPORT_SYMBOL vmlinux 0x00000000 qword_get +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_delete +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_insert +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tagged +EXPORT_SYMBOL vmlinux 0x00000000 random32 +EXPORT_SYMBOL vmlinux 0x00000000 rb_erase +EXPORT_SYMBOL vmlinux 0x00000000 rb_first +EXPORT_SYMBOL vmlinux 0x00000000 rb_insert_color +EXPORT_SYMBOL vmlinux 0x00000000 rb_last +EXPORT_SYMBOL vmlinux 0x00000000 rb_next +EXPORT_SYMBOL vmlinux 0x00000000 rb_prev +EXPORT_SYMBOL vmlinux 0x00000000 rb_replace_node +EXPORT_SYMBOL vmlinux 0x00000000 read_bytes_from_xdr_buf +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_page +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_page_async +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_pages +EXPORT_SYMBOL vmlinux 0x00000000 read_dev_sector +EXPORT_SYMBOL vmlinux 0x00000000 recalc_sigpending +EXPORT_SYMBOL vmlinux 0x00000000 redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0x00000000 register_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 register_blkdev +EXPORT_SYMBOL vmlinux 0x00000000 register_chrdev +EXPORT_SYMBOL vmlinux 0x00000000 register_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 register_console +EXPORT_SYMBOL vmlinux 0x00000000 register_exec_domain +EXPORT_SYMBOL vmlinux 0x00000000 register_filesystem +EXPORT_SYMBOL vmlinux 0x00000000 register_gifconf +EXPORT_SYMBOL vmlinux 0x00000000 register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_module_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x00000000 register_netdev +EXPORT_SYMBOL vmlinux 0x00000000 register_netdevice +EXPORT_SYMBOL vmlinux 0x00000000 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_nls +EXPORT_SYMBOL vmlinux 0x00000000 register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_shrinker +EXPORT_SYMBOL vmlinux 0x00000000 register_sysctl_paths +EXPORT_SYMBOL vmlinux 0x00000000 register_sysctl_table +EXPORT_SYMBOL vmlinux 0x00000000 register_sysrq_key +EXPORT_SYMBOL vmlinux 0x00000000 release_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 release_firmware +EXPORT_SYMBOL vmlinux 0x00000000 release_resource +EXPORT_SYMBOL vmlinux 0x00000000 release_sock +EXPORT_SYMBOL vmlinux 0x00000000 remap_pfn_range +EXPORT_SYMBOL vmlinux 0x00000000 remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0x00000000 remove_arg_zero +EXPORT_SYMBOL vmlinux 0x00000000 remove_inode_hash +EXPORT_SYMBOL vmlinux 0x00000000 remove_proc_entry +EXPORT_SYMBOL vmlinux 0x00000000 remove_wait_queue +EXPORT_SYMBOL vmlinux 0x00000000 request_firmware +EXPORT_SYMBOL vmlinux 0x00000000 request_firmware_nowait +EXPORT_SYMBOL vmlinux 0x00000000 request_irq +EXPORT_SYMBOL vmlinux 0x00000000 request_module +EXPORT_SYMBOL vmlinux 0x00000000 request_resource +EXPORT_SYMBOL vmlinux 0x00000000 reset_devices +EXPORT_SYMBOL vmlinux 0x00000000 restore_time_delta +EXPORT_SYMBOL vmlinux 0x00000000 rpc_mkpipe +EXPORT_SYMBOL vmlinux 0x00000000 rpc_queue_upcall +EXPORT_SYMBOL vmlinux 0x00000000 rpc_unlink +EXPORT_SYMBOL vmlinux 0x00000000 rtc_month_days +EXPORT_SYMBOL vmlinux 0x00000000 rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0x00000000 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0x00000000 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x00000000 rtc_year_days +EXPORT_SYMBOL vmlinux 0x00000000 rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_create_link +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_lock +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_notify +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_trylock +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_unicast +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x00000000 save_mount_options +EXPORT_SYMBOL vmlinux 0x00000000 save_time_delta +EXPORT_SYMBOL vmlinux 0x00000000 sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0x00000000 sb_min_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 sb_set_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 schedule +EXPORT_SYMBOL vmlinux 0x00000000 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x00000000 schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0x00000000 schedule_work +EXPORT_SYMBOL vmlinux 0x00000000 schedule_work_on +EXPORT_SYMBOL vmlinux 0x00000000 scm_detach_fds +EXPORT_SYMBOL vmlinux 0x00000000 scm_fp_dup +EXPORT_SYMBOL vmlinux 0x00000000 scnprintf +EXPORT_SYMBOL vmlinux 0x00000000 scsi_add_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_add_host +EXPORT_SYMBOL vmlinux 0x00000000 scsi_adjust_queue_depth +EXPORT_SYMBOL vmlinux 0x00000000 scsi_allocate_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_bios_ptable +EXPORT_SYMBOL vmlinux 0x00000000 scsi_block_requests +EXPORT_SYMBOL vmlinux 0x00000000 scsi_block_when_processing_errors +EXPORT_SYMBOL vmlinux 0x00000000 scsi_build_sense_buffer +EXPORT_SYMBOL vmlinux 0x00000000 scsi_calculate_bounce_limit +EXPORT_SYMBOL vmlinux 0x00000000 scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_cmd_print_sense_hdr +EXPORT_SYMBOL vmlinux 0x00000000 scsi_command_normalize_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_get +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_lookup +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_lookup_by_target +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_put +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_quiesce +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_resume +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_set_state +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_type +EXPORT_SYMBOL vmlinux 0x00000000 scsi_dma_map +EXPORT_SYMBOL vmlinux 0x00000000 scsi_dma_unmap +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_finish_cmd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_flush_done_q +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_prep_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_restore_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_execute +EXPORT_SYMBOL vmlinux 0x00000000 scsi_execute_req +EXPORT_SYMBOL vmlinux 0x00000000 scsi_extd_sense_format +EXPORT_SYMBOL vmlinux 0x00000000 scsi_finish_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_free_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_free_host_dev +EXPORT_SYMBOL vmlinux 0x00000000 scsi_get_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_get_host_dev +EXPORT_SYMBOL vmlinux 0x00000000 scsi_get_sense_info_fld +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_alloc +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_get +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_lookup +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_put +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_set_state +EXPORT_SYMBOL vmlinux 0x00000000 scsi_init_io +EXPORT_SYMBOL vmlinux 0x00000000 scsi_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_is_host_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_is_sdev_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_is_target_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_kmap_atomic_sg +EXPORT_SYMBOL vmlinux 0x00000000 scsi_kunmap_atomic_sg +EXPORT_SYMBOL vmlinux 0x00000000 scsi_mode_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_nonblockable_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_normalize_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_partsize +EXPORT_SYMBOL vmlinux 0x00000000 scsi_prep_return +EXPORT_SYMBOL vmlinux 0x00000000 scsi_prep_state_check +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_result +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_sense_hdr +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_status +EXPORT_SYMBOL vmlinux 0x00000000 scsi_put_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_register +EXPORT_SYMBOL vmlinux 0x00000000 scsi_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 scsi_register_interface +EXPORT_SYMBOL vmlinux 0x00000000 scsi_release_buffers +EXPORT_SYMBOL vmlinux 0x00000000 scsi_remove_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_remove_host +EXPORT_SYMBOL vmlinux 0x00000000 scsi_remove_target +EXPORT_SYMBOL vmlinux 0x00000000 scsi_report_bus_reset +EXPORT_SYMBOL vmlinux 0x00000000 scsi_report_device_reset +EXPORT_SYMBOL vmlinux 0x00000000 scsi_req_abort_cmd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_rescan_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_reset_provider +EXPORT_SYMBOL vmlinux 0x00000000 scsi_scan_host +EXPORT_SYMBOL vmlinux 0x00000000 scsi_scan_target +EXPORT_SYMBOL vmlinux 0x00000000 scsi_sense_desc_find +EXPORT_SYMBOL vmlinux 0x00000000 scsi_sense_key_string +EXPORT_SYMBOL vmlinux 0x00000000 scsi_set_medium_removal +EXPORT_SYMBOL vmlinux 0x00000000 scsi_setup_blk_pc_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_setup_fs_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_show_extd_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_show_result +EXPORT_SYMBOL vmlinux 0x00000000 scsi_show_sense_hdr +EXPORT_SYMBOL vmlinux 0x00000000 scsi_target_quiesce +EXPORT_SYMBOL vmlinux 0x00000000 scsi_target_resume +EXPORT_SYMBOL vmlinux 0x00000000 scsi_test_unit_ready +EXPORT_SYMBOL vmlinux 0x00000000 scsi_track_queue_full +EXPORT_SYMBOL vmlinux 0x00000000 scsi_unblock_requests +EXPORT_SYMBOL vmlinux 0x00000000 scsi_unregister +EXPORT_SYMBOL vmlinux 0x00000000 scsicam_bios_param +EXPORT_SYMBOL vmlinux 0x00000000 scsilun_to_int +EXPORT_SYMBOL vmlinux 0x00000000 search_binary_handler +EXPORT_SYMBOL vmlinux 0x00000000 secpath_dup +EXPORT_SYMBOL vmlinux 0x00000000 send_sig +EXPORT_SYMBOL vmlinux 0x00000000 send_sig_info +EXPORT_SYMBOL vmlinux 0x00000000 seq_escape +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_next +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_start +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_start_head +EXPORT_SYMBOL vmlinux 0x00000000 seq_lseek +EXPORT_SYMBOL vmlinux 0x00000000 seq_open +EXPORT_SYMBOL vmlinux 0x00000000 seq_open_private +EXPORT_SYMBOL vmlinux 0x00000000 seq_path +EXPORT_SYMBOL vmlinux 0x00000000 seq_printf +EXPORT_SYMBOL vmlinux 0x00000000 seq_putc +EXPORT_SYMBOL vmlinux 0x00000000 seq_puts +EXPORT_SYMBOL vmlinux 0x00000000 seq_read +EXPORT_SYMBOL vmlinux 0x00000000 seq_release +EXPORT_SYMBOL vmlinux 0x00000000 seq_release_private +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_register_port +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_resume_port +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_suspend_port +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_unregister_port +EXPORT_SYMBOL vmlinux 0x00000000 set_anon_super +EXPORT_SYMBOL vmlinux 0x00000000 set_bdi_congested +EXPORT_SYMBOL vmlinux 0x00000000 set_bh_page +EXPORT_SYMBOL vmlinux 0x00000000 set_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 set_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 set_current_groups +EXPORT_SYMBOL vmlinux 0x00000000 set_device_ro +EXPORT_SYMBOL vmlinux 0x00000000 set_disk_ro +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_chip +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_data +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_type +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_wake +EXPORT_SYMBOL vmlinux 0x00000000 set_normalized_timespec +EXPORT_SYMBOL vmlinux 0x00000000 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x00000000 set_page_dirty +EXPORT_SYMBOL vmlinux 0x00000000 set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x00000000 set_user_nice +EXPORT_SYMBOL vmlinux 0x00000000 setup_arg_pages +EXPORT_SYMBOL vmlinux 0x00000000 sg_alloc_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sg_free_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_init_one +EXPORT_SYMBOL vmlinux 0x00000000 sg_init_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_last +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_next +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_start +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_stop +EXPORT_SYMBOL vmlinux 0x00000000 sg_next +EXPORT_SYMBOL vmlinux 0x00000000 sget +EXPORT_SYMBOL vmlinux 0x00000000 sha_transform +EXPORT_SYMBOL vmlinux 0x00000000 should_remove_suid +EXPORT_SYMBOL vmlinux 0x00000000 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0x00000000 shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0x00000000 si_meminfo +EXPORT_SYMBOL vmlinux 0x00000000 sigprocmask +EXPORT_SYMBOL vmlinux 0x00000000 simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x00000000 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x00000000 simple_empty +EXPORT_SYMBOL vmlinux 0x00000000 simple_fill_super +EXPORT_SYMBOL vmlinux 0x00000000 simple_getattr +EXPORT_SYMBOL vmlinux 0x00000000 simple_link +EXPORT_SYMBOL vmlinux 0x00000000 simple_lookup +EXPORT_SYMBOL vmlinux 0x00000000 simple_pin_fs +EXPORT_SYMBOL vmlinux 0x00000000 simple_prepare_write +EXPORT_SYMBOL vmlinux 0x00000000 simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 simple_readpage +EXPORT_SYMBOL vmlinux 0x00000000 simple_release_fs +EXPORT_SYMBOL vmlinux 0x00000000 simple_rename +EXPORT_SYMBOL vmlinux 0x00000000 simple_rmdir +EXPORT_SYMBOL vmlinux 0x00000000 simple_set_mnt +EXPORT_SYMBOL vmlinux 0x00000000 simple_statfs +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtol +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtoul +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtoull +EXPORT_SYMBOL vmlinux 0x00000000 simple_sync_file +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_get +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_read +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_release +EXPORT_SYMBOL vmlinux 0x00000000 simple_unlink +EXPORT_SYMBOL vmlinux 0x00000000 simple_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 simple_write_end +EXPORT_SYMBOL vmlinux 0x00000000 single_open +EXPORT_SYMBOL vmlinux 0x00000000 single_release +EXPORT_SYMBOL vmlinux 0x00000000 sk_alloc +EXPORT_SYMBOL vmlinux 0x00000000 sk_chk_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_common_release +EXPORT_SYMBOL vmlinux 0x00000000 sk_dst_check +EXPORT_SYMBOL vmlinux 0x00000000 sk_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_free +EXPORT_SYMBOL vmlinux 0x00000000 sk_receive_skb +EXPORT_SYMBOL vmlinux 0x00000000 sk_release_kernel +EXPORT_SYMBOL vmlinux 0x00000000 sk_reset_timer +EXPORT_SYMBOL vmlinux 0x00000000 sk_run_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_send_sigurg +EXPORT_SYMBOL vmlinux 0x00000000 sk_stop_timer +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_error +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_write_space +EXPORT_SYMBOL vmlinux 0x00000000 sk_wait_data +EXPORT_SYMBOL vmlinux 0x00000000 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_append +EXPORT_SYMBOL vmlinux 0x00000000 skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0x00000000 skb_checksum +EXPORT_SYMBOL vmlinux 0x00000000 skb_checksum_help +EXPORT_SYMBOL vmlinux 0x00000000 skb_clone +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_expand +EXPORT_SYMBOL vmlinux 0x00000000 skb_dequeue +EXPORT_SYMBOL vmlinux 0x00000000 skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0x00000000 skb_find_text +EXPORT_SYMBOL vmlinux 0x00000000 skb_free_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_gso_segment +EXPORT_SYMBOL vmlinux 0x00000000 skb_insert +EXPORT_SYMBOL vmlinux 0x00000000 skb_kill_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_over_panic +EXPORT_SYMBOL vmlinux 0x00000000 skb_pad +EXPORT_SYMBOL vmlinux 0x00000000 skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_pull +EXPORT_SYMBOL vmlinux 0x00000000 skb_push +EXPORT_SYMBOL vmlinux 0x00000000 skb_put +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_head +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_purge +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_tail +EXPORT_SYMBOL vmlinux 0x00000000 skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0x00000000 skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_split +EXPORT_SYMBOL vmlinux 0x00000000 skb_store_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_trim +EXPORT_SYMBOL vmlinux 0x00000000 skb_truesize_bug +EXPORT_SYMBOL vmlinux 0x00000000 skb_under_panic +EXPORT_SYMBOL vmlinux 0x00000000 skb_unlink +EXPORT_SYMBOL vmlinux 0x00000000 sleep_on +EXPORT_SYMBOL vmlinux 0x00000000 sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x00000000 snprintf +EXPORT_SYMBOL vmlinux 0x00000000 sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_create +EXPORT_SYMBOL vmlinux 0x00000000 sock_create_kern +EXPORT_SYMBOL vmlinux 0x00000000 sock_create_lite +EXPORT_SYMBOL vmlinux 0x00000000 sock_get_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 sock_get_timestampns +EXPORT_SYMBOL vmlinux 0x00000000 sock_i_ino +EXPORT_SYMBOL vmlinux 0x00000000 sock_i_uid +EXPORT_SYMBOL vmlinux 0x00000000 sock_init_data +EXPORT_SYMBOL vmlinux 0x00000000 sock_kfree_s +EXPORT_SYMBOL vmlinux 0x00000000 sock_kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 sock_map_fd +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_accept +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_bind +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_connect +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_getname +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_listen +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_mmap +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_poll +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x00000000 sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x00000000 sock_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_register +EXPORT_SYMBOL vmlinux 0x00000000 sock_release +EXPORT_SYMBOL vmlinux 0x00000000 sock_rfree +EXPORT_SYMBOL vmlinux 0x00000000 sock_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_unregister +EXPORT_SYMBOL vmlinux 0x00000000 sock_wake_async +EXPORT_SYMBOL vmlinux 0x00000000 sock_wfree +EXPORT_SYMBOL vmlinux 0x00000000 sock_wmalloc +EXPORT_SYMBOL vmlinux 0x00000000 sockfd_lookup +EXPORT_SYMBOL vmlinux 0x00000000 sort +EXPORT_SYMBOL vmlinux 0x00000000 splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0x00000000 sprintf +EXPORT_SYMBOL vmlinux 0x00000000 srandom32 +EXPORT_SYMBOL vmlinux 0x00000000 sscanf +EXPORT_SYMBOL vmlinux 0x00000000 starget_for_each_device +EXPORT_SYMBOL vmlinux 0x00000000 start_tty +EXPORT_SYMBOL vmlinux 0x00000000 stop_tty +EXPORT_SYMBOL vmlinux 0x00000000 strcasecmp +EXPORT_SYMBOL vmlinux 0x00000000 strcat +EXPORT_SYMBOL vmlinux 0x00000000 strchr +EXPORT_SYMBOL vmlinux 0x00000000 strcmp +EXPORT_SYMBOL vmlinux 0x00000000 strcpy +EXPORT_SYMBOL vmlinux 0x00000000 strcspn +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtol +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoll +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoul +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoull +EXPORT_SYMBOL vmlinux 0x00000000 strlcat +EXPORT_SYMBOL vmlinux 0x00000000 strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 strlen +EXPORT_SYMBOL vmlinux 0x00000000 strncasecmp +EXPORT_SYMBOL vmlinux 0x00000000 strncat +EXPORT_SYMBOL vmlinux 0x00000000 strnchr +EXPORT_SYMBOL vmlinux 0x00000000 strncmp +EXPORT_SYMBOL vmlinux 0x00000000 strncpy +EXPORT_SYMBOL vmlinux 0x00000000 strndup_user +EXPORT_SYMBOL vmlinux 0x00000000 strnicmp +EXPORT_SYMBOL vmlinux 0x00000000 strnlen +EXPORT_SYMBOL vmlinux 0x00000000 strpbrk +EXPORT_SYMBOL vmlinux 0x00000000 strrchr +EXPORT_SYMBOL vmlinux 0x00000000 strsep +EXPORT_SYMBOL vmlinux 0x00000000 strspn +EXPORT_SYMBOL vmlinux 0x00000000 strstr +EXPORT_SYMBOL vmlinux 0x00000000 strstrip +EXPORT_SYMBOL vmlinux 0x00000000 sub_preempt_count +EXPORT_SYMBOL vmlinux 0x00000000 submit_bh +EXPORT_SYMBOL vmlinux 0x00000000 submit_bio +EXPORT_SYMBOL vmlinux 0x00000000 sunrpc_cache_lookup +EXPORT_SYMBOL vmlinux 0x00000000 sunrpc_cache_update +EXPORT_SYMBOL vmlinux 0x00000000 svc_auth_register +EXPORT_SYMBOL vmlinux 0x00000000 svc_auth_unregister +EXPORT_SYMBOL vmlinux 0x00000000 svc_authenticate +EXPORT_SYMBOL vmlinux 0x00000000 svc_create +EXPORT_SYMBOL vmlinux 0x00000000 svc_create_pooled +EXPORT_SYMBOL vmlinux 0x00000000 svc_destroy +EXPORT_SYMBOL vmlinux 0x00000000 svc_drop +EXPORT_SYMBOL vmlinux 0x00000000 svc_exit_thread +EXPORT_SYMBOL vmlinux 0x00000000 svc_prepare_thread +EXPORT_SYMBOL vmlinux 0x00000000 svc_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 svc_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 svc_process +EXPORT_SYMBOL vmlinux 0x00000000 svc_recv +EXPORT_SYMBOL vmlinux 0x00000000 svc_reserve +EXPORT_SYMBOL vmlinux 0x00000000 svc_seq_show +EXPORT_SYMBOL vmlinux 0x00000000 svc_set_client +EXPORT_SYMBOL vmlinux 0x00000000 svc_set_num_threads +EXPORT_SYMBOL vmlinux 0x00000000 svc_sock_names +EXPORT_SYMBOL vmlinux 0x00000000 svc_sock_update_bufs +EXPORT_SYMBOL vmlinux 0x00000000 svc_wake_up +EXPORT_SYMBOL vmlinux 0x00000000 svcauth_unix_purge +EXPORT_SYMBOL vmlinux 0x00000000 svcauth_unix_set_client +EXPORT_SYMBOL vmlinux 0x00000000 sync_blockdev +EXPORT_SYMBOL vmlinux 0x00000000 sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sync_inode +EXPORT_SYMBOL vmlinux 0x00000000 sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0x00000000 sync_page_range +EXPORT_SYMBOL vmlinux 0x00000000 sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0x00000000 synchronize_net +EXPORT_SYMBOL vmlinux 0x00000000 sys_close +EXPORT_SYMBOL vmlinux 0x00000000 sys_tz +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_data +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_intvec +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_string +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0x00000000 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0x00000000 sysfs_streq +EXPORT_SYMBOL vmlinux 0x00000000 system_rev +EXPORT_SYMBOL vmlinux 0x00000000 system_serial_high +EXPORT_SYMBOL vmlinux 0x00000000 system_serial_low +EXPORT_SYMBOL vmlinux 0x00000000 system_state +EXPORT_SYMBOL vmlinux 0x00000000 task_nice +EXPORT_SYMBOL vmlinux 0x00000000 task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_session_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 tasklet_init +EXPORT_SYMBOL vmlinux 0x00000000 tasklet_kill +EXPORT_SYMBOL vmlinux 0x00000000 tcp_check_req +EXPORT_SYMBOL vmlinux 0x00000000 tcp_child_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_close +EXPORT_SYMBOL vmlinux 0x00000000 tcp_connect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0x00000000 tcp_disconnect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0x00000000 tcp_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 tcp_hashinfo +EXPORT_SYMBOL vmlinux 0x00000000 tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0x00000000 tcp_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 tcp_make_synack +EXPORT_SYMBOL vmlinux 0x00000000 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0x00000000 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x00000000 tcp_mtup_init +EXPORT_SYMBOL vmlinux 0x00000000 tcp_parse_options +EXPORT_SYMBOL vmlinux 0x00000000 tcp_poll +EXPORT_SYMBOL vmlinux 0x00000000 tcp_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 tcp_prot +EXPORT_SYMBOL vmlinux 0x00000000 tcp_rcv_established +EXPORT_SYMBOL vmlinux 0x00000000 tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_read_sock +EXPORT_SYMBOL vmlinux 0x00000000 tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 tcp_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x00000000 tcp_splice_read +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sync_mss +EXPORT_SYMBOL vmlinux 0x00000000 tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_tso_segment +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_connect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0x00000000 test_set_page_writeback +EXPORT_SYMBOL vmlinux 0x00000000 thaw_bdev +EXPORT_SYMBOL vmlinux 0x00000000 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 timespec_trunc +EXPORT_SYMBOL vmlinux 0x00000000 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 totalram_pages +EXPORT_SYMBOL vmlinux 0x00000000 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0x00000000 touch_atime +EXPORT_SYMBOL vmlinux 0x00000000 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x00000000 truncate_inode_pages +EXPORT_SYMBOL vmlinux 0x00000000 truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0x00000000 try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x00000000 try_to_release_page +EXPORT_SYMBOL vmlinux 0x00000000 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x00000000 tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0x00000000 tty_check_change +EXPORT_SYMBOL vmlinux 0x00000000 tty_devnum +EXPORT_SYMBOL vmlinux 0x00000000 tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0x00000000 tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0x00000000 tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_hangup +EXPORT_SYMBOL vmlinux 0x00000000 tty_hung_up_p +EXPORT_SYMBOL vmlinux 0x00000000 tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0x00000000 tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0x00000000 tty_mutex +EXPORT_SYMBOL vmlinux 0x00000000 tty_name +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_init +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_device +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x00000000 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0x00000000 tty_set_operations +EXPORT_SYMBOL vmlinux 0x00000000 tty_std_termios +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_throttle +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_device +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0x00000000 tty_unthrottle +EXPORT_SYMBOL vmlinux 0x00000000 tty_vhangup +EXPORT_SYMBOL vmlinux 0x00000000 tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0x00000000 tty_write_room +EXPORT_SYMBOL vmlinux 0x00000000 uart_add_one_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 uart_get_divisor +EXPORT_SYMBOL vmlinux 0x00000000 uart_match_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 uart_remove_one_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_resume_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_suspend_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 uart_update_timeout +EXPORT_SYMBOL vmlinux 0x00000000 uart_write_wakeup +EXPORT_SYMBOL vmlinux 0x00000000 udp_disconnect +EXPORT_SYMBOL vmlinux 0x00000000 udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0x00000000 udp_hash +EXPORT_SYMBOL vmlinux 0x00000000 udp_hash_lock +EXPORT_SYMBOL vmlinux 0x00000000 udp_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_get_port +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 udp_memory_allocated +EXPORT_SYMBOL vmlinux 0x00000000 udp_poll +EXPORT_SYMBOL vmlinux 0x00000000 udp_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 udp_prot +EXPORT_SYMBOL vmlinux 0x00000000 udp_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0x00000000 udplite_hash +EXPORT_SYMBOL vmlinux 0x00000000 udplite_prot +EXPORT_SYMBOL vmlinux 0x00000000 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x00000000 unix_domain_find +EXPORT_SYMBOL vmlinux 0x00000000 unload_nls +EXPORT_SYMBOL vmlinux 0x00000000 unlock_buffer +EXPORT_SYMBOL vmlinux 0x00000000 unlock_kernel +EXPORT_SYMBOL vmlinux 0x00000000 unlock_new_inode +EXPORT_SYMBOL vmlinux 0x00000000 unlock_page +EXPORT_SYMBOL vmlinux 0x00000000 unlock_rename +EXPORT_SYMBOL vmlinux 0x00000000 unlock_super +EXPORT_SYMBOL vmlinux 0x00000000 unmap_mapping_range +EXPORT_SYMBOL vmlinux 0x00000000 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0x00000000 unregister_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 unregister_blkdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 unregister_console +EXPORT_SYMBOL vmlinux 0x00000000 unregister_exec_domain +EXPORT_SYMBOL vmlinux 0x00000000 unregister_filesystem +EXPORT_SYMBOL vmlinux 0x00000000 unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdevice +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_nls +EXPORT_SYMBOL vmlinux 0x00000000 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0x00000000 up +EXPORT_SYMBOL vmlinux 0x00000000 up_read +EXPORT_SYMBOL vmlinux 0x00000000 up_write +EXPORT_SYMBOL vmlinux 0x00000000 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 user_path_at +EXPORT_SYMBOL vmlinux 0x00000000 utf8_mbstowcs +EXPORT_SYMBOL vmlinux 0x00000000 utf8_mbtowc +EXPORT_SYMBOL vmlinux 0x00000000 utf8_wcstombs +EXPORT_SYMBOL vmlinux 0x00000000 utf8_wctomb +EXPORT_SYMBOL vmlinux 0x00000000 vfree +EXPORT_SYMBOL vmlinux 0x00000000 vfs_create +EXPORT_SYMBOL vmlinux 0x00000000 vfs_follow_link +EXPORT_SYMBOL vmlinux 0x00000000 vfs_fstat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_getattr +EXPORT_SYMBOL vmlinux 0x00000000 vfs_link +EXPORT_SYMBOL vmlinux 0x00000000 vfs_llseek +EXPORT_SYMBOL vmlinux 0x00000000 vfs_lstat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_mkdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_mknod +EXPORT_SYMBOL vmlinux 0x00000000 vfs_path_lookup +EXPORT_SYMBOL vmlinux 0x00000000 vfs_permission +EXPORT_SYMBOL vmlinux 0x00000000 vfs_read +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readv +EXPORT_SYMBOL vmlinux 0x00000000 vfs_rename +EXPORT_SYMBOL vmlinux 0x00000000 vfs_rmdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_stat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_statfs +EXPORT_SYMBOL vmlinux 0x00000000 vfs_symlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_unlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_write +EXPORT_SYMBOL vmlinux 0x00000000 vfs_writev +EXPORT_SYMBOL vmlinux 0x00000000 vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_mixed +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_page +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0x00000000 vm_stat +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_32 +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_node +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_user +EXPORT_SYMBOL vmlinux 0x00000000 vmap +EXPORT_SYMBOL vmlinux 0x00000000 vmtruncate +EXPORT_SYMBOL vmlinux 0x00000000 vprintk +EXPORT_SYMBOL vmlinux 0x00000000 vscnprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsnprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsscanf +EXPORT_SYMBOL vmlinux 0x00000000 vunmap +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x00000000 wait_on_page_bit +EXPORT_SYMBOL vmlinux 0x00000000 wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0x00000000 wake_bit_function +EXPORT_SYMBOL vmlinux 0x00000000 wake_up_bit +EXPORT_SYMBOL vmlinux 0x00000000 wake_up_process +EXPORT_SYMBOL vmlinux 0x00000000 walk_stackframe +EXPORT_SYMBOL vmlinux 0x00000000 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x00000000 warn_slowpath +EXPORT_SYMBOL vmlinux 0x00000000 wireless_send_event +EXPORT_SYMBOL vmlinux 0x00000000 wireless_spy_update +EXPORT_SYMBOL vmlinux 0x00000000 write_cache_pages +EXPORT_SYMBOL vmlinux 0x00000000 write_inode_now +EXPORT_SYMBOL vmlinux 0x00000000 write_one_page +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_from_iov +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_read_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_subsegment +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_array2 +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_string_inplace +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_word +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_array2 +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_opaque +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_opaque_fixed +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_string +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_word +EXPORT_SYMBOL vmlinux 0x00000000 xdr_enter_page +EXPORT_SYMBOL vmlinux 0x00000000 xdr_init_decode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_init_encode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_inline_decode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_inline_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_process_buf +EXPORT_SYMBOL vmlinux 0x00000000 xdr_read_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_reserve_space +EXPORT_SYMBOL vmlinux 0x00000000 xdr_shift_buf +EXPORT_SYMBOL vmlinux 0x00000000 xdr_write_pages +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_rcv +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_find_acq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_init_state +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_input +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_input_resume +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_lookup +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_nl +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_count +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_km +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_mode +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_type +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_add +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_update +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_user_policy +EXPORT_SYMBOL vmlinux 0x00000000 xrlim_allow +EXPORT_SYMBOL vmlinux 0x00000000 yield +EXPORT_SYMBOL vmlinux 0x00000000 zero_fill_bio +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflate +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateEnd +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateInit2 +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateReset +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflate_workspacesize +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate_workspacesize +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_alloc_instance +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_attr_alg +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_attr_alg_name +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_attr_u32 +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_check_attr_type +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_dequeue_request +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_drop_spawn +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_enqueue_request +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_get_attr_type +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_inc +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_init_queue +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_init_spawn +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_larval_error +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_lookup_template +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_register_alg +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_register_instance +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_register_notifier +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_register_template +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_spawn_tfm +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_tfm_in_queue +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_unregister_alg +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_unregister_notifier +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_unregister_template +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 crypto_xor +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 scatterwalk_copychunks +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 scatterwalk_done +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 scatterwalk_map +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 scatterwalk_map_and_copy +EXPORT_SYMBOL_GPL crypto/crypto_algapi 0x00000000 scatterwalk_start +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_done +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_phys +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_virt +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_virt_block +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_ablkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_alloc_ablkcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_blkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_givcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_grab_skcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_alloc +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_exit +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_free +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __async_tx_find_channel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __ata_ehi_push_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __class_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __scsi_get_command +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __usb_get_extra_descriptor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0x00000000 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x00000000 alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 arm_pm_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_trigger_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_issue_pending_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_quiesce +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_run_dependencies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_submit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_base_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_mode_filter +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_setup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bus_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_40wire +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_80wire +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_ignore +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_sata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_unknown +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dev_classify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dev_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dev_pair +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_do_dev_read_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_do_eh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_do_set_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dummy_port_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dummy_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_analyze_ncq_error +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_freeze_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_qc_complete +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_qc_retry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_thaw_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_ehi_clear_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_ehi_push_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_activate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_alloc_pinfo +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_detach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_id_c_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_id_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_id_xfermask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_link_abort +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_link_offline +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_link_online +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_mode_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_noop_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pack_xfermask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_bmdma_clear_simplex +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_bmdma_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_remove_one +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_activate_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_init_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_init_one +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_prepare_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pio_need_iordy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_abort +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_freeze +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_pbar_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_probe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_schedule_eh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_qc_complete +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_qc_complete_multiple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_ratelimit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_queuecmd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_slave_configure +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_change_queue_depth +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_queuecmd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_simulate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_slave_config +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_slave_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_busy_sleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_check_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_data_xfer +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_data_xfer_noirq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dev_classify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dev_select +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dma_pause +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dumb_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_error_handler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_exec_command +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_freeze +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_host_intr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_hsm_move +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_interrupt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_irq_clear +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_irq_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_pause +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_port_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_post_internal_cmd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_postreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_prereset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_qc_fill_rtf +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_qc_issue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_softreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_std_ports +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_tf_load +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_tf_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_thaw +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_wait_after_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_wait_ready +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sg_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_bios_param +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_error_handler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_postreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_prereset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_qc_defer +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_tf_from_fis +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_tf_to_fis +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_compute +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_cycle2mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_find_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_merge +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_unpack_xfermask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_wait_after_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_wait_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_xfer_mask2mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_xfer_mode2mask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_xfer_mode2shift +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atapi_cmd_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0001 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0002 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0003 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0200 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 clockevents_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 console_drivers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dcookie_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dcookie_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 default_mtd_writev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 del_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0x00000000 deregister_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 deregister_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0x00000000 destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_em_message +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_em_message_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_link_power_management_policy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_sw_activity +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_attach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_initialize +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_move +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_rename +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_find +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dma_wait_for_async_tx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_attach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_find +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ehci_cf_port_reset_rwsem +EXPORT_SYMBOL_GPL vmlinux 0x00000000 elv_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0x00000000 exit_fs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_add_entries +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_alloc_new_dir +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_attach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_build_inode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_date_unix2dos +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_detach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_dir_empty +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_fill_super +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_flush_inodes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_free_clusters +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_fs_panic +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_get_dotdot_entry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_getattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_remove_entries +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_scan +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_search_long +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_setattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fat_sync_inode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_vpid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 flush_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0x00000000 free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_dcookie +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_mtd_device_nm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_sb_mtd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_free_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_input_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_output_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_parse_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_set_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_connect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_disconnect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_find_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_report_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hwmon_device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hwmon_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_dummy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_probed_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_diag_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_diag_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_hash +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_add_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_dentry_parent_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_find_update_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_find_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_get_cookie +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_init_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_inode_is_dead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_inode_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_remove_watch_locked +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_rm_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_rm_wd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_unmount_inodes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0x00000000 jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kill_mtd_super +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_add_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_sub_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_classdev_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_classdev_resume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_classdev_suspend +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_classdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_set +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_set_default +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_show +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_store +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_unregister_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 leds_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 leds_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mmput +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_erase_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_table_mutex +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nand_release +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nand_scan +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nand_scan_ident +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nand_scan_tail +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nand_wait_ready +EXPORT_SYMBOL_GPL vmlinux 0x00000000 net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x00000000 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0x00000000 netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nfs_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nfsd_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlm_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_proc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x00000000 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0x00000000 parse_mtd_partitions +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_block_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_bus_add_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_bus_max_busnr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_create_slot +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_destroy_slot +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_ext_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_next_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_next_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_intx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_scan_child_bus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_set_pcie_reset_state +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_slots_kset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_stop_bus_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_test_config_bits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_unblock_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_update_slot_number +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x00000000 probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 prof_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 profile_event_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 profile_event_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 profile_hits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_pid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_rpccred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0x00000000 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_alloc_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_bind_new_program +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_calc_rto +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_null +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_clone_client +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_delay +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_exit_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_force_rebind +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_free_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_init_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_init_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_killall_tasks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_lookup_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_malloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_peeraddr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_peeraddr2str +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_print_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_proc_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_proc_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_put_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_restart_call +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_run_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_setbufsize +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_shutdown_client +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_sleep_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_init_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_init_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcb_getport_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcb_getport_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_class_close +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_class_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_set_freq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_set_state +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_read_alarm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_read_time +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_set_alarm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_set_mmss +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_set_time +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_update_irq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_async_notification +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_deb_timing_hotplug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_deb_timing_long +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_deb_timing_normal +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_link_debounce +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_link_hardreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_link_resume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_pmp_error_handler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_pmp_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_pmp_qc_defer_cmd_switch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_valid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_write_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_set_spd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_sff_hardreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_std_hardreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_complete_async_scans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_eh_get_sense +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_eh_ready_devs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_execute_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_flush_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_internal_device_block +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_internal_device_unblock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_mode_select +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_queue_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_schedule_eh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_target_block +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_target_unblock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdev_evt_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdev_evt_send +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdev_evt_send_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0x00000000 seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 single_release_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_morph +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_addsock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_close_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_create_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_find_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_print_addr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_reg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_unreg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_enqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_names +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_received +EXPORT_SYMBOL_GPL vmlinux 0x00000000 symbol_put_addr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 task_handoff_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 task_handoff_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x00000000 thread_notify_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uhci_check_and_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uhci_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_add_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_alloc_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_altnum_to_altsetting +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_anchor_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_map_sg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_unmap_sg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_bulk_msg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_bus_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_bus_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_calc_bus_time +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_clear_halt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_control_msg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_create_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_deregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_deregister_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_deregister_device_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_disabled +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_driver_claim_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_driver_release_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_driver_set_configuration +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_ep0_reinit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_find_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_free_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_current_frame_number +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_descriptor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_intf +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hc_died +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_check_unlink_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_giveback_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_link_urb_to_ep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_pci_probe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_pci_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_pci_shutdown +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_platform_shutdown +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_poll_rh_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_unlink_urb_from_ep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcds_loaded +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hub_tt_clear_buffer +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_ifnum_to_if +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_init_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_interrupt_msg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_kill_anchored_urbs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_kill_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_lock_device_for_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_match_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_match_one_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_put_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_put_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_put_intf +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_device_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_remove_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_reset_configuration +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_reset_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_set_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_sg_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_sg_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_sg_wait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_store_new_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_submit_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unanchor_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unlink_anchored_urbs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unlink_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unregister_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_wait_anchor_empty_timeout +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usbhid_lookup_quirk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xdr_skb_read_bits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_adjust_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_complete_rqst +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_disconnect_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_lookup_rqst +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_register_transport +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_rqst_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_reserve_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_unregister_transport +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_write_space +EXPORT_SYMBOL_GPL vmlinux 0x00000000 zap_vma_ptes --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/armel/ixp4xx +++ linux-2.6.27/debian/abi/2.6.27-8.17/armel/ixp4xx @@ -0,0 +1,3595 @@ +EXPORT_SYMBOL drivers/mtd/nand/nand 0x8ffb28bd nand_scan_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand 0xf0144061 nand_default_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x254f230c nand_calculate_ecc +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x87406d9d nand_correct_data +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0x836bdb72 nand_flash_ids +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0xa336feb7 nand_manuf_ids +EXPORT_SYMBOL drivers/net/wan/hdlc 0x0fa79abb attach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x1519d42d detach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x3913cee7 hdlc_open +EXPORT_SYMBOL drivers/net/wan/hdlc 0x5f712cba register_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x8ad3b8e8 hdlc_close +EXPORT_SYMBOL drivers/net/wan/hdlc 0x9988996e hdlc_ioctl +EXPORT_SYMBOL drivers/net/wan/hdlc 0xb2b49754 alloc_hdlcdev +EXPORT_SYMBOL drivers/net/wan/hdlc 0xcda178e3 unregister_hdlc_device +EXPORT_SYMBOL drivers/net/wan/hdlc 0xeb4aad5a unregister_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/syncppp 0x428b105a sppp_reopen +EXPORT_SYMBOL drivers/net/wan/syncppp 0x64ce1153 sppp_detach +EXPORT_SYMBOL drivers/net/wan/syncppp 0x75ad92e3 sppp_close +EXPORT_SYMBOL drivers/net/wan/syncppp 0x802d706f sppp_attach +EXPORT_SYMBOL drivers/net/wan/syncppp 0x8ace1d2e sppp_do_ioctl +EXPORT_SYMBOL drivers/net/wan/syncppp 0xf0e28a4c sppp_open +EXPORT_SYMBOL net/802/p8022 0xbfd6fa0e unregister_8022_client +EXPORT_SYMBOL net/802/p8022 0xdca3cd8f register_8022_client +EXPORT_SYMBOL net/802/p8023 0xe2302b3a make_8023_client +EXPORT_SYMBOL net/802/p8023 0xf018a4cc destroy_8023_client +EXPORT_SYMBOL net/802/psnap 0x960a8fd3 unregister_snap_client +EXPORT_SYMBOL net/802/psnap 0xb7f727c6 register_snap_client +EXPORT_SYMBOL net/appletalk/appletalk 0x41e6bf7e atalk_find_dev_addr +EXPORT_SYMBOL net/appletalk/appletalk 0x5450ddec aarp_send_ddp +EXPORT_SYMBOL net/appletalk/appletalk 0x78d89c0f alloc_ltalkdev +EXPORT_SYMBOL net/appletalk/appletalk 0x80551faa atrtr_get_dev +EXPORT_SYMBOL net/bridge/bridge 0x80a768f7 br_should_route_hook +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x2911f8a8 ip_vs_conn_put +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x2fd601d6 register_ip_vs_app_inc +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x340cb029 register_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x411b092d ip_vs_skb_replace +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x4b262b56 unregister_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x57bc8b20 ip_vs_conn_new +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x64ebde9d register_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x6ac04c73 unregister_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x7176a134 ip_vs_get_debug_level +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xa1dbc2d8 ip_vs_proto_name +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xd7985392 ip_vs_conn_out_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xfbb6d7d5 ip_vs_conn_in_get +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x1c87afd1 arpt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x371440c7 arpt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x3c6e8a32 arpt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x0ae86bd7 ipt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x9158c41c ipt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0xe8e11649 ipt_do_table +EXPORT_SYMBOL net/lapb/lapb 0x1f3a9fc3 lapb_getparms +EXPORT_SYMBOL net/lapb/lapb 0x3c5369db lapb_data_received +EXPORT_SYMBOL net/lapb/lapb 0x91a0ef81 lapb_register +EXPORT_SYMBOL net/lapb/lapb 0x9915e7cf lapb_setparms +EXPORT_SYMBOL net/lapb/lapb 0xcc00c938 lapb_unregister +EXPORT_SYMBOL net/lapb/lapb 0xd49b2ef5 lapb_connect_request +EXPORT_SYMBOL net/lapb/lapb 0xdacc4c3c lapb_data_request +EXPORT_SYMBOL net/lapb/lapb 0xe7ec9ff6 lapb_disconnect_request +EXPORT_SYMBOL net/llc/llc 0x211c0038 llc_set_station_handler +EXPORT_SYMBOL net/llc/llc 0x2b082c42 llc_add_pack +EXPORT_SYMBOL net/llc/llc 0x38b92846 llc_remove_pack +EXPORT_SYMBOL net/llc/llc 0x43b6cc77 llc_sap_find +EXPORT_SYMBOL net/llc/llc 0x52d7b2fd llc_sap_list +EXPORT_SYMBOL net/llc/llc 0x556643e3 llc_sap_list_lock +EXPORT_SYMBOL net/llc/llc 0x9140edcb llc_mac_hdr_init +EXPORT_SYMBOL net/llc/llc 0xa50a6509 llc_sap_open +EXPORT_SYMBOL net/llc/llc 0xbbed657f llc_sap_close +EXPORT_SYMBOL net/llc/llc 0xbdf4258f llc_build_and_send_ui_pkt +EXPORT_SYMBOL net/netfilter/x_tables 0x02cee29a xt_register_match +EXPORT_SYMBOL net/netfilter/x_tables 0x19489e01 xt_register_matches +EXPORT_SYMBOL net/netfilter/x_tables 0x3dcd58c5 xt_alloc_table_info +EXPORT_SYMBOL net/netfilter/x_tables 0x5404de2e xt_find_match +EXPORT_SYMBOL net/netfilter/x_tables 0x7a2ef5ad xt_unregister_match +EXPORT_SYMBOL net/netfilter/x_tables 0x8417b7b3 xt_register_target +EXPORT_SYMBOL net/netfilter/x_tables 0x9ecc65bb xt_unregister_targets +EXPORT_SYMBOL net/netfilter/x_tables 0xa86f3985 xt_find_target +EXPORT_SYMBOL net/netfilter/x_tables 0xce79970d xt_unregister_matches +EXPORT_SYMBOL net/netfilter/x_tables 0xe57fa8c7 xt_unregister_target +EXPORT_SYMBOL net/netfilter/x_tables 0xe9905433 xt_register_targets +EXPORT_SYMBOL net/netfilter/x_tables 0xf7037dc6 xt_free_table_info +EXPORT_SYMBOL net/wanrouter/wanrouter 0x0ebe03d1 unregister_wan_device +EXPORT_SYMBOL net/wanrouter/wanrouter 0xae8c4d7c register_wan_device +EXPORT_SYMBOL vmlinux 0x00000000 fp_printk +EXPORT_SYMBOL vmlinux 0x00000000 fp_send_sig +EXPORT_SYMBOL vmlinux 0x00000000 kern_fp_enter +EXPORT_SYMBOL vmlinux 0x0020296e i2c_detach_client +EXPORT_SYMBOL vmlinux 0x003ed0d6 bdi_init +EXPORT_SYMBOL vmlinux 0x00801678 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x0087bb0b __secpath_destroy +EXPORT_SYMBOL vmlinux 0x00c6b7c0 read_cache_page +EXPORT_SYMBOL vmlinux 0x00cabaaf xdr_init_decode +EXPORT_SYMBOL vmlinux 0x00cfd7ad nf_hook_slow +EXPORT_SYMBOL vmlinux 0x00e8097b csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x01000e51 schedule +EXPORT_SYMBOL vmlinux 0x01139ffc max_mapnr +EXPORT_SYMBOL vmlinux 0x0125952f pci_scan_single_device +EXPORT_SYMBOL vmlinux 0x013872fc kmem_cache_name +EXPORT_SYMBOL vmlinux 0x01a4aab6 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x01c3df03 input_release_device +EXPORT_SYMBOL vmlinux 0x020ca21d inet_getname +EXPORT_SYMBOL vmlinux 0x02196324 __aeabi_idiv +EXPORT_SYMBOL vmlinux 0x021dc8e2 freeze_bdev +EXPORT_SYMBOL vmlinux 0x02858e55 npe_send_recv_message +EXPORT_SYMBOL vmlinux 0x02e4f35c sunrpc_cache_lookup +EXPORT_SYMBOL vmlinux 0x02ee26c1 free_pages_exact +EXPORT_SYMBOL vmlinux 0x0334da4e scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x03436250 scsi_host_alloc +EXPORT_SYMBOL vmlinux 0x035037cb kmem_cache_size +EXPORT_SYMBOL vmlinux 0x0350e2f4 up_read +EXPORT_SYMBOL vmlinux 0x0357eca2 alloc_disk_node +EXPORT_SYMBOL vmlinux 0x037a0cba kfree +EXPORT_SYMBOL vmlinux 0x03a99c3b rb_prev +EXPORT_SYMBOL vmlinux 0x03c06156 bitmap_fold +EXPORT_SYMBOL vmlinux 0x03dcaf92 xrlim_allow +EXPORT_SYMBOL vmlinux 0x03f4afcd qmgr_disable_irq +EXPORT_SYMBOL vmlinux 0x0422fe4a inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x0424a4e0 mntput_no_expire +EXPORT_SYMBOL vmlinux 0x043b8483 __kfifo_get +EXPORT_SYMBOL vmlinux 0x044fbf49 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x046a0624 fsync_bdev +EXPORT_SYMBOL vmlinux 0x04a14725 sysctl_string +EXPORT_SYMBOL vmlinux 0x04a1ec7f kill_pgrp +EXPORT_SYMBOL vmlinux 0x04b1c3b3 generic_file_aio_read +EXPORT_SYMBOL vmlinux 0x04b68627 pci_get_subsys +EXPORT_SYMBOL vmlinux 0x04e21469 sock_no_sendpage +EXPORT_SYMBOL vmlinux 0x04f2bf2e tcf_hash_new_index +EXPORT_SYMBOL vmlinux 0x052b2967 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0x0560cdeb xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x0578f3ca i2c_smbus_read_byte +EXPORT_SYMBOL vmlinux 0x057ce975 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x05a6727b pci_find_capability +EXPORT_SYMBOL vmlinux 0x05c1baf1 console_stop +EXPORT_SYMBOL vmlinux 0x05e807a9 xdr_encode_string +EXPORT_SYMBOL vmlinux 0x05feb0d5 idr_init +EXPORT_SYMBOL vmlinux 0x06090de7 __sg_free_table +EXPORT_SYMBOL vmlinux 0x061651be strcat +EXPORT_SYMBOL vmlinux 0x0618e633 dump_fpu +EXPORT_SYMBOL vmlinux 0x061da12a __module_put_and_exit +EXPORT_SYMBOL vmlinux 0x062aba95 mempool_free +EXPORT_SYMBOL vmlinux 0x064446d2 ip_getsockopt +EXPORT_SYMBOL vmlinux 0x065994f1 xdr_encode_opaque_fixed +EXPORT_SYMBOL vmlinux 0x066ccc6e pci_target_state +EXPORT_SYMBOL vmlinux 0x066d57a5 i2c_smbus_write_byte_data +EXPORT_SYMBOL vmlinux 0x067147dd bio_uncopy_user +EXPORT_SYMBOL vmlinux 0x0686026e pci_dev_get +EXPORT_SYMBOL vmlinux 0x06ad9a34 set_binfmt +EXPORT_SYMBOL vmlinux 0x06cb34e5 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x06e85566 tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0x0703ced5 svc_wake_up +EXPORT_SYMBOL vmlinux 0x071d1016 kernel_recvmsg +EXPORT_SYMBOL vmlinux 0x078f4d75 pci_select_bars +EXPORT_SYMBOL vmlinux 0x0795f4ef blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0x0799aca4 local_bh_enable +EXPORT_SYMBOL vmlinux 0x079cd7f1 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x07cc4a5d printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x07cef0f9 tcp_sendmsg +EXPORT_SYMBOL vmlinux 0x07d1bcac gpio_to_irq +EXPORT_SYMBOL vmlinux 0x0807c3e9 simple_set_mnt +EXPORT_SYMBOL vmlinux 0x082c3213 pci_root_buses +EXPORT_SYMBOL vmlinux 0x08428a01 dev_mc_add +EXPORT_SYMBOL vmlinux 0x0844803a dma_pool_free +EXPORT_SYMBOL vmlinux 0x085f2ac7 mapping_tagged +EXPORT_SYMBOL vmlinux 0x08607bfe dput +EXPORT_SYMBOL vmlinux 0x0860f1aa generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0x08711f86 vfs_unlink +EXPORT_SYMBOL vmlinux 0x08f9c631 map_destroy +EXPORT_SYMBOL vmlinux 0x0903c239 vid_from_reg +EXPORT_SYMBOL vmlinux 0x092b007a sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x09317840 page_symlink +EXPORT_SYMBOL vmlinux 0x09455d4f blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0x0948cde9 num_physpages +EXPORT_SYMBOL vmlinux 0x095bf722 __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x0985ab10 qdisc_class_hash_grow +EXPORT_SYMBOL vmlinux 0x0997b868 kernel_read +EXPORT_SYMBOL vmlinux 0x09c55cec schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x09d18f2f starget_for_each_device +EXPORT_SYMBOL vmlinux 0x09d45c21 down_timeout +EXPORT_SYMBOL vmlinux 0x09ed87c0 sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0x09fc4743 d_namespace_path +EXPORT_SYMBOL vmlinux 0x0a1bebc5 kernel_execve +EXPORT_SYMBOL vmlinux 0x0a1c6051 sock_kfree_s +EXPORT_SYMBOL vmlinux 0x0a2487e0 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x0a29e17b blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0x0a3131f6 strnchr +EXPORT_SYMBOL vmlinux 0x0a4db202 nf_log_unregister +EXPORT_SYMBOL vmlinux 0x0a59c7ca unregister_console +EXPORT_SYMBOL vmlinux 0x0a73536e clear_bdi_congested +EXPORT_SYMBOL vmlinux 0x0a802a9b dev_set_mac_address +EXPORT_SYMBOL vmlinux 0x0aa13d05 __raw_readsw +EXPORT_SYMBOL vmlinux 0x0abbda27 i2c_smbus_write_block_data +EXPORT_SYMBOL vmlinux 0x0acb1a3c __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x0b1beb31 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x0b3096d7 generic_listxattr +EXPORT_SYMBOL vmlinux 0x0b5f2d2c sg_next +EXPORT_SYMBOL vmlinux 0x0b742fd7 simple_strtol +EXPORT_SYMBOL vmlinux 0x0b7fbbe6 blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0x0bb05f1e pskb_expand_head +EXPORT_SYMBOL vmlinux 0x0bb997f2 struct_module +EXPORT_SYMBOL vmlinux 0x0bc5d909 xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0x0c33cbcd xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0x0c5ef91b per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x0c65e73c scsi_normalize_sense +EXPORT_SYMBOL vmlinux 0x0c8b120d set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x0c8c9e99 scsi_show_extd_sense +EXPORT_SYMBOL vmlinux 0x0cfff15f xdr_encode_word +EXPORT_SYMBOL vmlinux 0x0d3f57a2 _find_next_bit_le +EXPORT_SYMBOL vmlinux 0x0d6cba21 posix_lock_file +EXPORT_SYMBOL vmlinux 0x0d730ee6 inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x0d8116ad proc_dointvec +EXPORT_SYMBOL vmlinux 0x0d8ab500 param_set_copystring +EXPORT_SYMBOL vmlinux 0x0dcdb69c scsi_get_command +EXPORT_SYMBOL vmlinux 0x0dd7eca0 ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0x0ddba3b7 nf_unregister_hook +EXPORT_SYMBOL vmlinux 0x0e2430a4 mii_check_gmii_support +EXPORT_SYMBOL vmlinux 0x0e41e3f9 set_anon_super +EXPORT_SYMBOL vmlinux 0x0e47a119 netlink_kernel_release +EXPORT_SYMBOL vmlinux 0x0e52592a panic +EXPORT_SYMBOL vmlinux 0x0e762d6e request_module +EXPORT_SYMBOL vmlinux 0x0f09a4eb ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0x0f1ef871 posix_acl_alloc +EXPORT_SYMBOL vmlinux 0x0f638d65 simple_transaction_read +EXPORT_SYMBOL vmlinux 0x0f668ba9 svc_auth_unregister +EXPORT_SYMBOL vmlinux 0x0f96ca97 __scm_send +EXPORT_SYMBOL vmlinux 0x0f9753e8 d_rehash +EXPORT_SYMBOL vmlinux 0x0fa2a45e __memzero +EXPORT_SYMBOL vmlinux 0x0fc586ba down_trylock +EXPORT_SYMBOL vmlinux 0x0fcccd29 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x0feeb16c bio_add_page +EXPORT_SYMBOL vmlinux 0x0ff178f6 __aeabi_idivmod +EXPORT_SYMBOL vmlinux 0x100c7ca4 vmtruncate +EXPORT_SYMBOL vmlinux 0x104bb6ec ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0x10579454 sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0x1060aadc __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x10689c82 find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0x1072a394 csum_partial_copy_from_user +EXPORT_SYMBOL vmlinux 0x10ac61dd blk_plug_device +EXPORT_SYMBOL vmlinux 0x10e5c759 inetdev_by_index +EXPORT_SYMBOL vmlinux 0x111bcb2c groups_free +EXPORT_SYMBOL vmlinux 0x111bd4fc tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0x111ee93a flush_signals +EXPORT_SYMBOL vmlinux 0x11267875 scsi_extd_sense_format +EXPORT_SYMBOL vmlinux 0x114bacf6 xfrm_nl +EXPORT_SYMBOL vmlinux 0x1163f0a7 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x117093be qdisc_class_hash_init +EXPORT_SYMBOL vmlinux 0x117af8e2 ip_dev_find +EXPORT_SYMBOL vmlinux 0x117e5b5a skb_copy_bits +EXPORT_SYMBOL vmlinux 0x1196e2fc inet_add_protocol +EXPORT_SYMBOL vmlinux 0x11c5438b idr_get_new +EXPORT_SYMBOL vmlinux 0x11d999e8 xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0x1210ea9b dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x1242839a tty_hangup +EXPORT_SYMBOL vmlinux 0x126970ed param_set_uint +EXPORT_SYMBOL vmlinux 0x129b1d15 bio_split +EXPORT_SYMBOL vmlinux 0x12a092cd neigh_for_each +EXPORT_SYMBOL vmlinux 0x12da5bb2 __kmalloc +EXPORT_SYMBOL vmlinux 0x12e280e3 svc_proc_unregister +EXPORT_SYMBOL vmlinux 0x12ebd1ab aio_put_req +EXPORT_SYMBOL vmlinux 0x12f3610e vm_insert_page +EXPORT_SYMBOL vmlinux 0x12f8922b ide_end_request +EXPORT_SYMBOL vmlinux 0x1308a364 page_readlink +EXPORT_SYMBOL vmlinux 0x13150728 ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0x13266092 put_io_context +EXPORT_SYMBOL vmlinux 0x1326c386 __insert_inode_hash +EXPORT_SYMBOL vmlinux 0x132f45f2 cookie_check_timestamp +EXPORT_SYMBOL vmlinux 0x13930d00 pci_pme_capable +EXPORT_SYMBOL vmlinux 0x139e6cf3 scsi_dma_unmap +EXPORT_SYMBOL vmlinux 0x13be4c3e ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0x13bf31fa nlmsvc_ops +EXPORT_SYMBOL vmlinux 0x13d4dd9d netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0x1411f7b9 inet_release +EXPORT_SYMBOL vmlinux 0x143d0087 blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0x144ed3a1 dev_base_lock +EXPORT_SYMBOL vmlinux 0x149ab966 dentry_open +EXPORT_SYMBOL vmlinux 0x14b2a5f2 follow_down +EXPORT_SYMBOL vmlinux 0x14c2170b scm_fp_dup +EXPORT_SYMBOL vmlinux 0x14e828cd blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x1502d40d xscale_flush_user_cache_range +EXPORT_SYMBOL vmlinux 0x15083eb9 invalidate_bdev +EXPORT_SYMBOL vmlinux 0x152888d8 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x1544aad4 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x1551dc51 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x15526561 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0x1561d743 proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0x157e80a4 uart_update_timeout +EXPORT_SYMBOL vmlinux 0x15b656be __dev_get_by_index +EXPORT_SYMBOL vmlinux 0x15c9e7be bfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0x15d13694 task_nice +EXPORT_SYMBOL vmlinux 0x15da5622 bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0x15fdbf79 fifo_create_dflt +EXPORT_SYMBOL vmlinux 0x161d5a3f do_splice_from +EXPORT_SYMBOL vmlinux 0x16281bf6 in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x16479e8f panic_notifier_list +EXPORT_SYMBOL vmlinux 0x168cc71c blk_free_tags +EXPORT_SYMBOL vmlinux 0x169623ed journal_set_features +EXPORT_SYMBOL vmlinux 0x169c6d83 kick_iocb +EXPORT_SYMBOL vmlinux 0x16ed4e42 simple_prepare_write +EXPORT_SYMBOL vmlinux 0x1766078f compute_creds +EXPORT_SYMBOL vmlinux 0x178367a0 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0x17893e44 xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0x17a76e71 rb_first +EXPORT_SYMBOL vmlinux 0x17b53e17 journal_restart +EXPORT_SYMBOL vmlinux 0x17cdb346 xdr_read_pages +EXPORT_SYMBOL vmlinux 0x17df17bc sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x183fa88b mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x1883f5d0 input_unregister_handle +EXPORT_SYMBOL vmlinux 0x188e3a23 inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0x18a544e7 udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0x18be740c simple_statfs +EXPORT_SYMBOL vmlinux 0x18d294af block_sync_page +EXPORT_SYMBOL vmlinux 0x18f32f80 tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x18f94a8e scsi_mode_sense +EXPORT_SYMBOL vmlinux 0x192cfe76 bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0x199b5b9d generic_show_options +EXPORT_SYMBOL vmlinux 0x199ed0cd net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x19b96912 xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0x19bdd26b file_fsync +EXPORT_SYMBOL vmlinux 0x19db2229 bdi_destroy +EXPORT_SYMBOL vmlinux 0x1a24e5e2 sonet_subtract_stats +EXPORT_SYMBOL vmlinux 0x1a65f4ad __arm_ioremap_pfn +EXPORT_SYMBOL vmlinux 0x1a67607f call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0x1a6a3971 eth_header_cache +EXPORT_SYMBOL vmlinux 0x1a7f2f94 proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x1a85d2e6 block_commit_write +EXPORT_SYMBOL vmlinux 0x1ab694a3 __ip_select_ident +EXPORT_SYMBOL vmlinux 0x1ac2519a __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0x1ace138d bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x1ad1f2e7 _memcpy_fromio +EXPORT_SYMBOL vmlinux 0x1ad2709f seq_lseek +EXPORT_SYMBOL vmlinux 0x1ad9164e vfs_readlink +EXPORT_SYMBOL vmlinux 0x1ae8d7dc param_set_invbool +EXPORT_SYMBOL vmlinux 0x1b015d25 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x1b4cc6b1 scsi_cmd_print_sense_hdr +EXPORT_SYMBOL vmlinux 0x1b6314fd in_aton +EXPORT_SYMBOL vmlinux 0x1b641b1a sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0x1b9981cc set_irq_wake +EXPORT_SYMBOL vmlinux 0x1b9e0ff1 scsilun_to_int +EXPORT_SYMBOL vmlinux 0x1bb2a3a9 inet_frag_find +EXPORT_SYMBOL vmlinux 0x1bc8c00a __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x1c096162 uart_suspend_port +EXPORT_SYMBOL vmlinux 0x1c1eaed0 atm_dev_deregister +EXPORT_SYMBOL vmlinux 0x1c27390e skb_unlink +EXPORT_SYMBOL vmlinux 0x1c59a8fb scsi_register +EXPORT_SYMBOL vmlinux 0x1c59c12c fput +EXPORT_SYMBOL vmlinux 0x1c71b505 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0x1c723b86 seq_puts +EXPORT_SYMBOL vmlinux 0x1c783fb8 sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0x1c80de9c ip_send_check +EXPORT_SYMBOL vmlinux 0x1cc6719a register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x1cd03394 uart_register_driver +EXPORT_SYMBOL vmlinux 0x1d0aaf41 scsi_kmap_atomic_sg +EXPORT_SYMBOL vmlinux 0x1d3af021 qdisc_reset +EXPORT_SYMBOL vmlinux 0x1d495681 __ide_dma_end +EXPORT_SYMBOL vmlinux 0x1d69132c kthread_create +EXPORT_SYMBOL vmlinux 0x1d82bbfb _set_bit_be +EXPORT_SYMBOL vmlinux 0x1db3af02 __lock_buffer +EXPORT_SYMBOL vmlinux 0x1dbe739e cpu_possible_map +EXPORT_SYMBOL vmlinux 0x1e165b43 sock_no_listen +EXPORT_SYMBOL vmlinux 0x1e49daa8 sg_init_one +EXPORT_SYMBOL vmlinux 0x1e646e6d submit_bh +EXPORT_SYMBOL vmlinux 0x1e6d26a8 strstr +EXPORT_SYMBOL vmlinux 0x1ea617ba pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0x1ecb9943 posix_acl_to_xattr +EXPORT_SYMBOL vmlinux 0x1edc9598 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x1eecfd23 input_allocate_device +EXPORT_SYMBOL vmlinux 0x1efe283f __cap_full_set +EXPORT_SYMBOL vmlinux 0x1f042a0c svc_set_client +EXPORT_SYMBOL vmlinux 0x1f49f489 inode_get_bytes +EXPORT_SYMBOL vmlinux 0x1f70d32d dma_cache_maint +EXPORT_SYMBOL vmlinux 0x1f75b6c3 tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x1f75fe3b neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x1f7cc628 mempool_create +EXPORT_SYMBOL vmlinux 0x1f7d91a9 tcf_destroy_chain +EXPORT_SYMBOL vmlinux 0x1f9cfe83 iomem_resource +EXPORT_SYMBOL vmlinux 0x1f9eb1ae __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0x1fa957c2 sync_inode +EXPORT_SYMBOL vmlinux 0x1fae7a0b wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x1fae8c03 ide_proc_register_driver +EXPORT_SYMBOL vmlinux 0x1fc91fb2 request_irq +EXPORT_SYMBOL vmlinux 0x1ff2e3f8 dma_sync_sg_for_device +EXPORT_SYMBOL vmlinux 0x20000329 simple_strtoul +EXPORT_SYMBOL vmlinux 0x203f7c55 pci_release_selected_regions +EXPORT_SYMBOL vmlinux 0x204256b4 nf_register_hooks +EXPORT_SYMBOL vmlinux 0x206116c0 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0x20873e29 inode_add_bytes +EXPORT_SYMBOL vmlinux 0x20900e33 blk_requeue_request +EXPORT_SYMBOL vmlinux 0x20976d01 kernel_sendpage +EXPORT_SYMBOL vmlinux 0x20b3cd9f dev_mc_delete +EXPORT_SYMBOL vmlinux 0x20b59a63 mb_cache_entry_get +EXPORT_SYMBOL vmlinux 0x20c09691 dma_alloc_writecombine +EXPORT_SYMBOL vmlinux 0x20e30a67 generic_write_checks +EXPORT_SYMBOL vmlinux 0x211331fa __divsi3 +EXPORT_SYMBOL vmlinux 0x215ebd78 bitrev16 +EXPORT_SYMBOL vmlinux 0x21aa1598 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x21d5d09e dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0x21dc58e3 __sk_dst_check +EXPORT_SYMBOL vmlinux 0x220f5c4b svc_sock_update_bufs +EXPORT_SYMBOL vmlinux 0x222e7ce2 sysfs_streq +EXPORT_SYMBOL vmlinux 0x2288378f system_state +EXPORT_SYMBOL vmlinux 0x2299199d __nla_put +EXPORT_SYMBOL vmlinux 0x229cfd5b gen_new_estimator +EXPORT_SYMBOL vmlinux 0x229da967 dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x22b6533b xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x22ef73cb put_disk +EXPORT_SYMBOL vmlinux 0x22fbb98d vfs_writev +EXPORT_SYMBOL vmlinux 0x22ffeb92 pci_set_dma_seg_boundary +EXPORT_SYMBOL vmlinux 0x230e227a pci_dev_driver +EXPORT_SYMBOL vmlinux 0x231cf494 up_write +EXPORT_SYMBOL vmlinux 0x231e2644 datagram_poll +EXPORT_SYMBOL vmlinux 0x23269a13 strict_strtoul +EXPORT_SYMBOL vmlinux 0x2338f10e ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0x23479e03 seq_open +EXPORT_SYMBOL vmlinux 0x2348984e adjust_resource +EXPORT_SYMBOL vmlinux 0x23838107 __down_write +EXPORT_SYMBOL vmlinux 0x23858db4 npe_request +EXPORT_SYMBOL vmlinux 0x23962cb4 simple_unlink +EXPORT_SYMBOL vmlinux 0x23a7a3bd maps_protect +EXPORT_SYMBOL vmlinux 0x23bc3f86 current_fs_time +EXPORT_SYMBOL vmlinux 0x23ce759a pci_try_set_mwi +EXPORT_SYMBOL vmlinux 0x23f0b1e2 bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0x23f2d36f memparse +EXPORT_SYMBOL vmlinux 0x23fd3028 vmalloc_node +EXPORT_SYMBOL vmlinux 0x240e2eee fasync_helper +EXPORT_SYMBOL vmlinux 0x2436488a request_firmware_nowait +EXPORT_SYMBOL vmlinux 0x243db079 blkdev_get +EXPORT_SYMBOL vmlinux 0x2443a967 scsi_finish_command +EXPORT_SYMBOL vmlinux 0x2455c156 __clear_user +EXPORT_SYMBOL vmlinux 0x2459bbcc console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x24e54936 register_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x24fdac79 wake_bit_function +EXPORT_SYMBOL vmlinux 0x250113b4 memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x25054b34 vfs_llseek +EXPORT_SYMBOL vmlinux 0x250571d1 netif_device_attach +EXPORT_SYMBOL vmlinux 0x2537bacb tcf_hash_destroy +EXPORT_SYMBOL vmlinux 0x25597641 d_invalidate +EXPORT_SYMBOL vmlinux 0x256887e1 warn_slowpath +EXPORT_SYMBOL vmlinux 0x256a20f7 sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x256b20b8 xfrm4_rcv +EXPORT_SYMBOL vmlinux 0x25728935 unlock_page +EXPORT_SYMBOL vmlinux 0x25820c64 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x25928c63 gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x25ba121c mempool_resize +EXPORT_SYMBOL vmlinux 0x25de155f neigh_create +EXPORT_SYMBOL vmlinux 0x25f2e118 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0x25fa6f17 wait_for_completion +EXPORT_SYMBOL vmlinux 0x261c1766 __backtrace +EXPORT_SYMBOL vmlinux 0x26218151 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0x26477c07 __vmalloc +EXPORT_SYMBOL vmlinux 0x267fc65b __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x26e76fb8 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x2700d88a bio_hw_segments +EXPORT_SYMBOL vmlinux 0x272ce9ae block_invalidatepage +EXPORT_SYMBOL vmlinux 0x272d9e03 bd_release +EXPORT_SYMBOL vmlinux 0x272e7488 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x2783d9cd pci_enable_bridges +EXPORT_SYMBOL vmlinux 0x27a147a8 kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0x27a27993 elv_rb_add +EXPORT_SYMBOL vmlinux 0x27a9a7eb ns_to_timespec +EXPORT_SYMBOL vmlinux 0x27b47413 bio_split_pool +EXPORT_SYMBOL vmlinux 0x27bbf221 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x27c61ece qdisc_put_stab +EXPORT_SYMBOL vmlinux 0x27cf6cc5 block_prepare_write +EXPORT_SYMBOL vmlinux 0x27dadc0f inet_bind +EXPORT_SYMBOL vmlinux 0x27dde4d3 posix_test_lock +EXPORT_SYMBOL vmlinux 0x27ece5c1 qmgr_regs +EXPORT_SYMBOL vmlinux 0x27ee2d84 generic_read_dir +EXPORT_SYMBOL vmlinux 0x28118cb6 __get_user_1 +EXPORT_SYMBOL vmlinux 0x2812a79d tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0x282eca43 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0x28320e64 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0x284bb95a elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0x284ca0e3 tcp_close +EXPORT_SYMBOL vmlinux 0x285a27df netlink_ack +EXPORT_SYMBOL vmlinux 0x285ac517 strict_strtoll +EXPORT_SYMBOL vmlinux 0x28686bfc generic_setxattr +EXPORT_SYMBOL vmlinux 0x287e1a9e unregister_binfmt +EXPORT_SYMBOL vmlinux 0x287f06a1 ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0x289e0549 journal_update_format +EXPORT_SYMBOL vmlinux 0x28a2ed02 scsi_build_sense_buffer +EXPORT_SYMBOL vmlinux 0x28a47378 pci_enable_wake +EXPORT_SYMBOL vmlinux 0x28b8cfd2 free_netdev +EXPORT_SYMBOL vmlinux 0x28dcf25c udplite_hash +EXPORT_SYMBOL vmlinux 0x29148969 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x2919b156 xdr_decode_string_inplace +EXPORT_SYMBOL vmlinux 0x291f071e skb_gso_segment +EXPORT_SYMBOL vmlinux 0x293b59ed qmgr_request_queue +EXPORT_SYMBOL vmlinux 0x29537c9e alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x296ef5fd generic_ide_ioctl +EXPORT_SYMBOL vmlinux 0x298d1160 sk_filter +EXPORT_SYMBOL vmlinux 0x29bd4c46 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x2a0634a9 neigh_event_ns +EXPORT_SYMBOL vmlinux 0x2a2a55a8 skb_checksum +EXPORT_SYMBOL vmlinux 0x2a3d9b19 skb_queue_head +EXPORT_SYMBOL vmlinux 0x2a57bc3a simple_pin_fs +EXPORT_SYMBOL vmlinux 0x2aa0e4fc strncasecmp +EXPORT_SYMBOL vmlinux 0x2ae2ddc1 kernel_listen +EXPORT_SYMBOL vmlinux 0x2ae87183 input_inject_event +EXPORT_SYMBOL vmlinux 0x2af4f738 dev_close +EXPORT_SYMBOL vmlinux 0x2b0b04f1 sk_receive_skb +EXPORT_SYMBOL vmlinux 0x2b0ba2b0 scsi_sense_desc_find +EXPORT_SYMBOL vmlinux 0x2b10fe94 scsi_print_command +EXPORT_SYMBOL vmlinux 0x2b40baff __down_write_nested +EXPORT_SYMBOL vmlinux 0x2ba707a8 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x2bf54a43 pcim_iounmap_regions +EXPORT_SYMBOL vmlinux 0x2c049637 blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0x2c16ae37 proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0x2c30ce1a neigh_lookup +EXPORT_SYMBOL vmlinux 0x2c898f9c netlink_unicast +EXPORT_SYMBOL vmlinux 0x2cc2d52d vcc_hash +EXPORT_SYMBOL vmlinux 0x2cd52702 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x2cd9e459 param_set_short +EXPORT_SYMBOL vmlinux 0x2ce48aad generic_permission +EXPORT_SYMBOL vmlinux 0x2d35b603 generic_file_splice_read +EXPORT_SYMBOL vmlinux 0x2d6507b5 _find_next_zero_bit_le +EXPORT_SYMBOL vmlinux 0x2d7184ab atm_dev_register +EXPORT_SYMBOL vmlinux 0x2d89342a scsi_show_sense_hdr +EXPORT_SYMBOL vmlinux 0x2dacdd85 blk_init_tags +EXPORT_SYMBOL vmlinux 0x2dd188a4 skb_over_panic +EXPORT_SYMBOL vmlinux 0x2de6162c blk_complete_request +EXPORT_SYMBOL vmlinux 0x2de9f66f param_get_long +EXPORT_SYMBOL vmlinux 0x2e2ce9e0 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x2e4a39f8 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x2ee02ffb km_query +EXPORT_SYMBOL vmlinux 0x2eec63c9 xdr_encode_netobj +EXPORT_SYMBOL vmlinux 0x2ef7e5a9 pci_set_consistent_dma_mask +EXPORT_SYMBOL vmlinux 0x2f3c24c5 get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x2f7c7fe0 pci_remove_bus +EXPORT_SYMBOL vmlinux 0x2f82b95b __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0x2fb0b623 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0x300062b6 gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x3001e207 scm_detach_fds +EXPORT_SYMBOL vmlinux 0x30033835 tty_register_device +EXPORT_SYMBOL vmlinux 0x30450454 tcf_exts_change +EXPORT_SYMBOL vmlinux 0x3053e9a7 netdev_set_master +EXPORT_SYMBOL vmlinux 0x3053ec4b dev_load +EXPORT_SYMBOL vmlinux 0x30802e13 sk_alloc +EXPORT_SYMBOL vmlinux 0x309c4761 unregister_netdev +EXPORT_SYMBOL vmlinux 0x30e0624a unregister_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x30e74134 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x310917fe sort +EXPORT_SYMBOL vmlinux 0x313341a3 _set_bit_le +EXPORT_SYMBOL vmlinux 0x3145216f pci_dev_present +EXPORT_SYMBOL vmlinux 0x315aae5b create_empty_buffers +EXPORT_SYMBOL vmlinux 0x315c65fd zlib_deflateInit2 +EXPORT_SYMBOL vmlinux 0x315ff3d1 vfs_mknod +EXPORT_SYMBOL vmlinux 0x31714ea0 __wait_on_buffer +EXPORT_SYMBOL vmlinux 0x31ade8a0 dev_get_by_index +EXPORT_SYMBOL vmlinux 0x31b31f5c csum_partial_copy_nocheck +EXPORT_SYMBOL vmlinux 0x31eb46b9 vcc_sklist_lock +EXPORT_SYMBOL vmlinux 0x320b365b misc_register +EXPORT_SYMBOL vmlinux 0x32201673 xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0x322c6fc2 __check_region +EXPORT_SYMBOL vmlinux 0x32305457 end_queued_request +EXPORT_SYMBOL vmlinux 0x323222ba mutex_unlock +EXPORT_SYMBOL vmlinux 0x32536463 seq_release_private +EXPORT_SYMBOL vmlinux 0x328a05f1 strncpy +EXPORT_SYMBOL vmlinux 0x32b83605 pci_bus_write_config_word +EXPORT_SYMBOL vmlinux 0x32ce623a sg_last +EXPORT_SYMBOL vmlinux 0x32ff68fe i2c_release_client +EXPORT_SYMBOL vmlinux 0x330df383 svc_exit_thread +EXPORT_SYMBOL vmlinux 0x334d6a5c skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0x335d909e sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0x3360a963 param_set_ulong +EXPORT_SYMBOL vmlinux 0x3368bfa4 tcf_unregister_action +EXPORT_SYMBOL vmlinux 0x337979a2 follow_up +EXPORT_SYMBOL vmlinux 0x337d0193 pci_choose_state +EXPORT_SYMBOL vmlinux 0x33958039 idr_find +EXPORT_SYMBOL vmlinux 0x33c8af53 ida_get_new +EXPORT_SYMBOL vmlinux 0x33d9dc98 bio_pair_release +EXPORT_SYMBOL vmlinux 0x33fad2e7 start_tty +EXPORT_SYMBOL vmlinux 0x341dfb54 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0x341f63a4 set_device_ro +EXPORT_SYMBOL vmlinux 0x342fa83e neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x344f2c87 idr_for_each +EXPORT_SYMBOL vmlinux 0x3473ec15 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0x348e8140 dcache_readdir +EXPORT_SYMBOL vmlinux 0x34908c14 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x3493b6d2 bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x349cba85 strchr +EXPORT_SYMBOL vmlinux 0x349d5d0b ip_fragment +EXPORT_SYMBOL vmlinux 0x34c72492 scsi_device_set_state +EXPORT_SYMBOL vmlinux 0x34f78606 blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0x35059e42 blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0x351a2c00 check_disk_change +EXPORT_SYMBOL vmlinux 0x351e64f2 put_filp +EXPORT_SYMBOL vmlinux 0x3531502a cancel_dirty_page +EXPORT_SYMBOL vmlinux 0x353838e9 find_inode_number +EXPORT_SYMBOL vmlinux 0x353e3fa5 __get_user_4 +EXPORT_SYMBOL vmlinux 0x359103fe bioset_create +EXPORT_SYMBOL vmlinux 0x35a233eb generic_delete_inode +EXPORT_SYMBOL vmlinux 0x35a94464 __devm_release_region +EXPORT_SYMBOL vmlinux 0x360b1afe probe_irq_mask +EXPORT_SYMBOL vmlinux 0x3630122b __grab_cache_page +EXPORT_SYMBOL vmlinux 0x363ad247 cap_set_effective +EXPORT_SYMBOL vmlinux 0x366bdeaa init_timer +EXPORT_SYMBOL vmlinux 0x3671982c pci_get_device +EXPORT_SYMBOL vmlinux 0x36877b71 get_sb_nodev +EXPORT_SYMBOL vmlinux 0x3697b4da journal_get_create_access +EXPORT_SYMBOL vmlinux 0x36b66815 arp_xmit +EXPORT_SYMBOL vmlinux 0x36e47222 remove_wait_queue +EXPORT_SYMBOL vmlinux 0x36f0d75b tcf_register_action +EXPORT_SYMBOL vmlinux 0x370e1c4c inet_dgram_ops +EXPORT_SYMBOL vmlinux 0x3739f266 tcf_hash_create +EXPORT_SYMBOL vmlinux 0x3744cf36 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x374ed073 scnprintf +EXPORT_SYMBOL vmlinux 0x37574848 sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x376676bd ide_do_drive_cmd +EXPORT_SYMBOL vmlinux 0x378b861e set_irq_chip +EXPORT_SYMBOL vmlinux 0x37b57db1 pci_bus_write_config_byte +EXPORT_SYMBOL vmlinux 0x37b9eb08 register_chrdev +EXPORT_SYMBOL vmlinux 0x37befc70 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x37ccb959 nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x37e5807c scsi_command_normalize_sense +EXPORT_SYMBOL vmlinux 0x37e74642 get_jiffies_64 +EXPORT_SYMBOL vmlinux 0x380f7606 mb_cache_entry_insert +EXPORT_SYMBOL vmlinux 0x38544c2d truncate_inode_pages +EXPORT_SYMBOL vmlinux 0x387c0967 vfs_lstat +EXPORT_SYMBOL vmlinux 0x3881bac6 journal_lock_updates +EXPORT_SYMBOL vmlinux 0x38af8a05 call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0x38dd8d91 nf_register_hook +EXPORT_SYMBOL vmlinux 0x38e8378d pgprot_kernel +EXPORT_SYMBOL vmlinux 0x38fb3772 scsi_prep_state_check +EXPORT_SYMBOL vmlinux 0x3913a539 proc_net_netfilter +EXPORT_SYMBOL vmlinux 0x3920dbda find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0x394eb094 pcibios_bus_to_resource +EXPORT_SYMBOL vmlinux 0x39516569 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x395a1585 block_read_full_page +EXPORT_SYMBOL vmlinux 0x3980aac1 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x3983bb32 idr_get_new_above +EXPORT_SYMBOL vmlinux 0x3a0965f2 bdput +EXPORT_SYMBOL vmlinux 0x3a13adcc block_write_begin +EXPORT_SYMBOL vmlinux 0x3a16733a kmem_cache_create +EXPORT_SYMBOL vmlinux 0x3a2759a0 __getblk +EXPORT_SYMBOL vmlinux 0x3a2e30c2 copy_io_context +EXPORT_SYMBOL vmlinux 0x3a9b6fb9 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x3aa4b5cb inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0x3ab2d174 down_killable +EXPORT_SYMBOL vmlinux 0x3adc15b9 posix_acl_from_mode +EXPORT_SYMBOL vmlinux 0x3ae831b6 kref_init +EXPORT_SYMBOL vmlinux 0x3afe27a4 get_unmapped_area +EXPORT_SYMBOL vmlinux 0x3afe92b9 ilookup5 +EXPORT_SYMBOL vmlinux 0x3b1fe197 pcix_set_mmrbc +EXPORT_SYMBOL vmlinux 0x3b8749cd scsi_is_target_device +EXPORT_SYMBOL vmlinux 0x3bd1b1f6 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x3bd934fa xdr_buf_subsegment +EXPORT_SYMBOL vmlinux 0x3c29224f d_move +EXPORT_SYMBOL vmlinux 0x3c2c5af5 sprintf +EXPORT_SYMBOL vmlinux 0x3c56b731 __scsi_device_lookup +EXPORT_SYMBOL vmlinux 0x3c7354ac inet_stream_connect +EXPORT_SYMBOL vmlinux 0x3c756785 dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0x3cb8a495 param_get_string +EXPORT_SYMBOL vmlinux 0x3cc0a3bb xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x3ce4ca6f disable_irq +EXPORT_SYMBOL vmlinux 0x3d3c540f elf_hwcap +EXPORT_SYMBOL vmlinux 0x3d68bd4b flow_cache_genid +EXPORT_SYMBOL vmlinux 0x3d99cd70 sk_send_sigurg +EXPORT_SYMBOL vmlinux 0x3da5a2ab _find_next_bit_be +EXPORT_SYMBOL vmlinux 0x3da8e9d0 xfrm_init_state +EXPORT_SYMBOL vmlinux 0x3dd3685b udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0x3de23f97 dma_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x3df7e240 rtnl_notify +EXPORT_SYMBOL vmlinux 0x3dfe754f km_new_mapping +EXPORT_SYMBOL vmlinux 0x3e360ad4 inet_ioctl +EXPORT_SYMBOL vmlinux 0x3e45e9ff register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x3e5b686e pci_unmap_rom +EXPORT_SYMBOL vmlinux 0x3e6b77ec scsi_test_unit_ready +EXPORT_SYMBOL vmlinux 0x3e6caebd add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x3ed63055 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x3f4176ed __seq_open_private +EXPORT_SYMBOL vmlinux 0x3f4547a7 put_unused_fd +EXPORT_SYMBOL vmlinux 0x3f5988f2 kernel_connect +EXPORT_SYMBOL vmlinux 0x3f640f68 idr_remove +EXPORT_SYMBOL vmlinux 0x3f921ec3 nf_ip_checksum +EXPORT_SYMBOL vmlinux 0x3fbcddc3 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x3fbdc140 npe_names +EXPORT_SYMBOL vmlinux 0x3ff62317 local_bh_disable +EXPORT_SYMBOL vmlinux 0x404b7c13 filp_close +EXPORT_SYMBOL vmlinux 0x4054525c dmam_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x4059792f print_hex_dump +EXPORT_SYMBOL vmlinux 0x405c1144 get_seconds +EXPORT_SYMBOL vmlinux 0x4067bcde del_mtd_partitions +EXPORT_SYMBOL vmlinux 0x407136b1 __put_user_8 +EXPORT_SYMBOL vmlinux 0x407d912a pci_bus_alloc_resource +EXPORT_SYMBOL vmlinux 0x4083b03a skb_put +EXPORT_SYMBOL vmlinux 0x40875c21 inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0x4097e79b tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0x409873e3 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x40a6f522 __arm_ioremap +EXPORT_SYMBOL vmlinux 0x40e65a12 tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x40f07981 __ashldi3 +EXPORT_SYMBOL vmlinux 0x4101a975 ide_fixstring +EXPORT_SYMBOL vmlinux 0x410a121c journal_check_used_features +EXPORT_SYMBOL vmlinux 0x41166725 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x411f4cd8 pcibios_resource_to_bus +EXPORT_SYMBOL vmlinux 0x412ddc0c dcache_lock +EXPORT_SYMBOL vmlinux 0x41482d8b strndup_user +EXPORT_SYMBOL vmlinux 0x4156c131 simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x4185cf4b radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x4188d439 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x418fc919 locks_copy_lock +EXPORT_SYMBOL vmlinux 0x41ab1f8a setup_arg_pages +EXPORT_SYMBOL vmlinux 0x41fc47ea blk_start_queue +EXPORT_SYMBOL vmlinux 0x4211c3c1 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x42196f69 xdr_init_encode +EXPORT_SYMBOL vmlinux 0x42224298 sscanf +EXPORT_SYMBOL vmlinux 0x426b598f xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0x426cc5dc _find_first_bit_be +EXPORT_SYMBOL vmlinux 0x428b64c7 tty_unregister_device +EXPORT_SYMBOL vmlinux 0x429907ef handle_sysrq +EXPORT_SYMBOL vmlinux 0x42b99429 scsi_allocate_command +EXPORT_SYMBOL vmlinux 0x42c00e9e unregister_qdisc +EXPORT_SYMBOL vmlinux 0x42ca7553 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x42d48009 icmp_send +EXPORT_SYMBOL vmlinux 0x42f43e76 remove_inode_hash +EXPORT_SYMBOL vmlinux 0x42fd4a59 do_map_probe +EXPORT_SYMBOL vmlinux 0x42ff0a50 tcf_action_dump_1 +EXPORT_SYMBOL vmlinux 0x430205aa __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x4302d0eb free_pages +EXPORT_SYMBOL vmlinux 0x431c7ac1 svc_create_pooled +EXPORT_SYMBOL vmlinux 0x431cbfe7 ide_raw_taskfile +EXPORT_SYMBOL vmlinux 0x43227acf pcibios_fixup_bus +EXPORT_SYMBOL vmlinux 0x434fa55c release_console_sem +EXPORT_SYMBOL vmlinux 0x4360fd76 sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0x4377cdea seq_release +EXPORT_SYMBOL vmlinux 0x43cf7c79 i2c_transfer +EXPORT_SYMBOL vmlinux 0x43de65bc blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x43e533fe pskb_copy +EXPORT_SYMBOL vmlinux 0x43f3b01f pci_setup_cardbus +EXPORT_SYMBOL vmlinux 0x43fb7ecd netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0x44161c19 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x441f4b33 mtd_do_chip_probe +EXPORT_SYMBOL vmlinux 0x44314efb radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x443ab49b neigh_table_init +EXPORT_SYMBOL vmlinux 0x444779c4 nla_find +EXPORT_SYMBOL vmlinux 0x446119a7 no_llseek +EXPORT_SYMBOL vmlinux 0x44643b93 __aeabi_lmul +EXPORT_SYMBOL vmlinux 0x4465c2ec inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0x4469a33e bio_free +EXPORT_SYMBOL vmlinux 0x44b911c3 rb_replace_node +EXPORT_SYMBOL vmlinux 0x44c214d1 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x44d2ba51 dst_release +EXPORT_SYMBOL vmlinux 0x44da5d0f __csum_ipv6_magic +EXPORT_SYMBOL vmlinux 0x44eb291f rpc_queue_upcall +EXPORT_SYMBOL vmlinux 0x44f02e0d tcp_ioctl +EXPORT_SYMBOL vmlinux 0x44f88d0b scsi_bios_ptable +EXPORT_SYMBOL vmlinux 0x453bb0f9 mii_link_ok +EXPORT_SYMBOL vmlinux 0x45419d6b ether_setup +EXPORT_SYMBOL vmlinux 0x45430c64 inet_frag_kill +EXPORT_SYMBOL vmlinux 0x45528349 unlock_rename +EXPORT_SYMBOL vmlinux 0x45765c85 dev_disable_lro +EXPORT_SYMBOL vmlinux 0x45819a5e input_grab_device +EXPORT_SYMBOL vmlinux 0x45a55ec8 __iounmap +EXPORT_SYMBOL vmlinux 0x45bda0d5 system_serial_low +EXPORT_SYMBOL vmlinux 0x45d448d2 netlink_dump_start +EXPORT_SYMBOL vmlinux 0x460b1a35 i2c_verify_client +EXPORT_SYMBOL vmlinux 0x460d02af thaw_bdev +EXPORT_SYMBOL vmlinux 0x4615f62e filemap_fault +EXPORT_SYMBOL vmlinux 0x462a2e75 match_strlcpy +EXPORT_SYMBOL vmlinux 0x464c759a skb_split +EXPORT_SYMBOL vmlinux 0x464e74ab __kfree_skb +EXPORT_SYMBOL vmlinux 0x4676ff60 allocate_resource +EXPORT_SYMBOL vmlinux 0x467b9140 neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0x46ab3ca3 journal_blocks_per_page +EXPORT_SYMBOL vmlinux 0x46d3b28c __div0 +EXPORT_SYMBOL vmlinux 0x46fecdb3 scsi_scan_target +EXPORT_SYMBOL vmlinux 0x47012998 file_permission +EXPORT_SYMBOL vmlinux 0x4719ba4e kfifo_free +EXPORT_SYMBOL vmlinux 0x472d2a9a radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x475100c2 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x47533112 __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0x47823835 proc_dostring +EXPORT_SYMBOL vmlinux 0x4791a39b km_state_expired +EXPORT_SYMBOL vmlinux 0x47948b06 __bio_clone +EXPORT_SYMBOL vmlinux 0x47c62d70 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x47d1f4dd __starget_for_each_device +EXPORT_SYMBOL vmlinux 0x47edcc14 netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0x47f04dee cfi_varsize_frob +EXPORT_SYMBOL vmlinux 0x47f50c3b blk_run_queue +EXPORT_SYMBOL vmlinux 0x47f757de elf_platform +EXPORT_SYMBOL vmlinux 0x48034724 zlib_deflateReset +EXPORT_SYMBOL vmlinux 0x484bf9b4 scsi_adjust_queue_depth +EXPORT_SYMBOL vmlinux 0x4859b8bb rtc_year_days +EXPORT_SYMBOL vmlinux 0x486b6407 hweight64 +EXPORT_SYMBOL vmlinux 0x48a5b067 __machine_arch_type +EXPORT_SYMBOL vmlinux 0x48ab6d5f pci_get_bus_and_slot +EXPORT_SYMBOL vmlinux 0x48bba52e proto_register +EXPORT_SYMBOL vmlinux 0x48be498f flush_old_exec +EXPORT_SYMBOL vmlinux 0x48f9f12d complete_all +EXPORT_SYMBOL vmlinux 0x492cd709 udp_proc_register +EXPORT_SYMBOL vmlinux 0x493cbf88 wake_up_process +EXPORT_SYMBOL vmlinux 0x493e25e1 udp_hash +EXPORT_SYMBOL vmlinux 0x49734834 ___pskb_trim +EXPORT_SYMBOL vmlinux 0x4990f73a inet_accept +EXPORT_SYMBOL vmlinux 0x49fa47dd idr_destroy +EXPORT_SYMBOL vmlinux 0x4a1f05f8 neigh_ifdown +EXPORT_SYMBOL vmlinux 0x4a358252 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x4a42f6ca blk_queue_bounce +EXPORT_SYMBOL vmlinux 0x4a4343aa generic_mii_ioctl +EXPORT_SYMBOL vmlinux 0x4a518cf9 set_blocksize +EXPORT_SYMBOL vmlinux 0x4a75e986 journal_invalidatepage +EXPORT_SYMBOL vmlinux 0x4a7bc9ac __inode_dir_notify +EXPORT_SYMBOL vmlinux 0x4a964f20 pci_get_slot +EXPORT_SYMBOL vmlinux 0x4a971ec7 radix_tree_delete +EXPORT_SYMBOL vmlinux 0x4a9f6b64 input_set_capability +EXPORT_SYMBOL vmlinux 0x4aa5c776 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0x4ac6681a pcim_iomap_regions +EXPORT_SYMBOL vmlinux 0x4acfd8ad down_interruptible +EXPORT_SYMBOL vmlinux 0x4ad9a6fe xscale_mc_copy_user_page +EXPORT_SYMBOL vmlinux 0x4ae2222c netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0x4aea4791 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0x4afe9a77 scsi_partsize +EXPORT_SYMBOL vmlinux 0x4afeecc6 generic_getxattr +EXPORT_SYMBOL vmlinux 0x4b2f14b4 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x4b32ff5b tcp_sync_mss +EXPORT_SYMBOL vmlinux 0x4b34fbf5 block_all_signals +EXPORT_SYMBOL vmlinux 0x4b87babb arp_create +EXPORT_SYMBOL vmlinux 0x4b8edde9 complete_and_exit +EXPORT_SYMBOL vmlinux 0x4b9f3684 kfifo_init +EXPORT_SYMBOL vmlinux 0x4ba097f5 ixp4xx_pci_write +EXPORT_SYMBOL vmlinux 0x4ba51401 create_proc_entry +EXPORT_SYMBOL vmlinux 0x4bab0c5b elv_queue_empty +EXPORT_SYMBOL vmlinux 0x4bb296ad udp_ioctl +EXPORT_SYMBOL vmlinux 0x4c01e860 scsi_prep_return +EXPORT_SYMBOL vmlinux 0x4c1182cb bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x4c212b72 dev_change_flags +EXPORT_SYMBOL vmlinux 0x4c7a33ef inode_double_unlock +EXPORT_SYMBOL vmlinux 0x4cbbd171 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x4cef7f9a skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0x4d0d163d copy_page +EXPORT_SYMBOL vmlinux 0x4d1692f7 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0x4d3c153f sigprocmask +EXPORT_SYMBOL vmlinux 0x4d6214d7 boot_tvec_bases +EXPORT_SYMBOL vmlinux 0x4da2c466 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0x4da78068 mb_cache_entry_free +EXPORT_SYMBOL vmlinux 0x4db2647a i2c_del_driver +EXPORT_SYMBOL vmlinux 0x4dbb710b get_sb_single +EXPORT_SYMBOL vmlinux 0x4dec6038 memscan +EXPORT_SYMBOL vmlinux 0x4df119fa __bitmap_parse +EXPORT_SYMBOL vmlinux 0x4e07f8ef npe_load_firmware +EXPORT_SYMBOL vmlinux 0x4e0f8420 i2c_probe +EXPORT_SYMBOL vmlinux 0x4e23d990 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0x4e3567f7 match_int +EXPORT_SYMBOL vmlinux 0x4e705a76 __devm_request_region +EXPORT_SYMBOL vmlinux 0x4e830a3e strnicmp +EXPORT_SYMBOL vmlinux 0x4e8914cf sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0x4ea1295c __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0x4f088bbb nlmsg_notify +EXPORT_SYMBOL vmlinux 0x4f0ea0c0 up +EXPORT_SYMBOL vmlinux 0x4f12f085 kobject_get +EXPORT_SYMBOL vmlinux 0x4f5651c3 tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x4f71e471 deregister_atm_ioctl +EXPORT_SYMBOL vmlinux 0x4f7c6920 scsi_ioctl +EXPORT_SYMBOL vmlinux 0x4fd0f8dd set_bdi_congested +EXPORT_SYMBOL vmlinux 0x4ff4357a skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0x4ff73f4b register_qdisc +EXPORT_SYMBOL vmlinux 0x500564ed atm_proc_root +EXPORT_SYMBOL vmlinux 0x5061c779 xdr_process_buf +EXPORT_SYMBOL vmlinux 0x508af892 __scsi_device_lookup_by_target +EXPORT_SYMBOL vmlinux 0x5093fa82 _clear_bit_le +EXPORT_SYMBOL vmlinux 0x50ab8451 blk_queue_ordered +EXPORT_SYMBOL vmlinux 0x50fbd8df kill_fasync +EXPORT_SYMBOL vmlinux 0x50fed6f7 proc_ide_read_geometry +EXPORT_SYMBOL vmlinux 0x51058325 blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0x5112fafb tcf_exts_dump_stats +EXPORT_SYMBOL vmlinux 0x5136c0ee scsi_req_abort_cmd +EXPORT_SYMBOL vmlinux 0x5142cba3 dev_remove_pack +EXPORT_SYMBOL vmlinux 0x51493d94 finish_wait +EXPORT_SYMBOL vmlinux 0x5180be75 generic_setlease +EXPORT_SYMBOL vmlinux 0x51908eb8 __raw_writesl +EXPORT_SYMBOL vmlinux 0x51cd47e2 groups_alloc +EXPORT_SYMBOL vmlinux 0x51cea937 inet_put_port +EXPORT_SYMBOL vmlinux 0x51d63d79 __neigh_event_send +EXPORT_SYMBOL vmlinux 0x51e1f67f sock_no_mmap +EXPORT_SYMBOL vmlinux 0x51ef33b8 kstrndup +EXPORT_SYMBOL vmlinux 0x51fa9056 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0x521c1862 auth_domain_put +EXPORT_SYMBOL vmlinux 0x521d86ec scsi_set_medium_removal +EXPORT_SYMBOL vmlinux 0x521efaa1 send_sig +EXPORT_SYMBOL vmlinux 0x52354a0b mutex_trylock +EXPORT_SYMBOL vmlinux 0x52825224 have_submounts +EXPORT_SYMBOL vmlinux 0x528c709d simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x52a58c24 ifla_policy +EXPORT_SYMBOL vmlinux 0x52aed211 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0x52b507c6 xdr_buf_from_iov +EXPORT_SYMBOL vmlinux 0x531cfe0a journal_force_commit_nested +EXPORT_SYMBOL vmlinux 0x532f2924 param_get_byte +EXPORT_SYMBOL vmlinux 0x53326531 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x53371497 bio_map_kern +EXPORT_SYMBOL vmlinux 0x536dd9f5 blk_remove_plug +EXPORT_SYMBOL vmlinux 0x538772be blk_register_region +EXPORT_SYMBOL vmlinux 0x53c0767c sk_chk_filter +EXPORT_SYMBOL vmlinux 0x54290dc9 nla_validate +EXPORT_SYMBOL vmlinux 0x543c5da7 __scsi_add_device +EXPORT_SYMBOL vmlinux 0x5467fc34 pagecache_write_end +EXPORT_SYMBOL vmlinux 0x548f7edb pci_set_dma_mask +EXPORT_SYMBOL vmlinux 0x5499fae5 unregister_filesystem +EXPORT_SYMBOL vmlinux 0x54d358d1 new_inode +EXPORT_SYMBOL vmlinux 0x54e6fcdd net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x55016fd2 ide_stall_queue +EXPORT_SYMBOL vmlinux 0x55104c0b blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0x55746ec2 get_sb_bdev +EXPORT_SYMBOL vmlinux 0x5594be03 bitmap_remap +EXPORT_SYMBOL vmlinux 0x559cdc76 scsi_report_device_reset +EXPORT_SYMBOL vmlinux 0x55bac72f alloc_tty_driver +EXPORT_SYMBOL vmlinux 0x55e5db91 scsi_add_host +EXPORT_SYMBOL vmlinux 0x5600af8f xfrm_state_update +EXPORT_SYMBOL vmlinux 0x56071f0c pci_release_regions +EXPORT_SYMBOL vmlinux 0x56327152 pci_find_device +EXPORT_SYMBOL vmlinux 0x5635a60a vmalloc_user +EXPORT_SYMBOL vmlinux 0x566aef2f iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0x56863f8f kernel_bind +EXPORT_SYMBOL vmlinux 0x56a035ab nla_append +EXPORT_SYMBOL vmlinux 0x56c8799d scsi_kunmap_atomic_sg +EXPORT_SYMBOL vmlinux 0x56d340b6 submit_bio +EXPORT_SYMBOL vmlinux 0x56f47864 tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0x570b7cec tcp_sendpage +EXPORT_SYMBOL vmlinux 0x5718946b lease_modify +EXPORT_SYMBOL vmlinux 0x571f03c6 cpu_xscale_set_pte_ext +EXPORT_SYMBOL vmlinux 0x572e85d4 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x576713e0 __xfrm_lookup +EXPORT_SYMBOL vmlinux 0x57806f2f per_cpu____irq_regs +EXPORT_SYMBOL vmlinux 0x579d8078 vcc_release_async +EXPORT_SYMBOL vmlinux 0x57a6504e vsnprintf +EXPORT_SYMBOL vmlinux 0x57e6e6da xdr_decode_word +EXPORT_SYMBOL vmlinux 0x5838f6c9 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x5863965c skb_truesize_bug +EXPORT_SYMBOL vmlinux 0x586e586a auth_domain_find +EXPORT_SYMBOL vmlinux 0x58a76d71 skb_queue_purge +EXPORT_SYMBOL vmlinux 0x5934392b fb_register_client +EXPORT_SYMBOL vmlinux 0x594e1317 __modsi3 +EXPORT_SYMBOL vmlinux 0x5964714c xfrm_input +EXPORT_SYMBOL vmlinux 0x5985434c inet_csk_accept +EXPORT_SYMBOL vmlinux 0x598bf44d inode_permission +EXPORT_SYMBOL vmlinux 0x598d2411 xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x598f7621 qmgr_enable_irq +EXPORT_SYMBOL vmlinux 0x59b8a011 ide_execute_command +EXPORT_SYMBOL vmlinux 0x59bca3f9 truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0x59d553b5 bio_unmap_user +EXPORT_SYMBOL vmlinux 0x59d696b6 register_module_notifier +EXPORT_SYMBOL vmlinux 0x59e5070d __do_div64 +EXPORT_SYMBOL vmlinux 0x59eae4e5 arp_find +EXPORT_SYMBOL vmlinux 0x5a6c80c1 find_lock_page +EXPORT_SYMBOL vmlinux 0x5a744b86 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x5adaee45 blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0x5ae1c838 kernel_getpeername +EXPORT_SYMBOL vmlinux 0x5ae94341 svc_reserve +EXPORT_SYMBOL vmlinux 0x5b19634d div_s64_rem +EXPORT_SYMBOL vmlinux 0x5b334264 svc_drop +EXPORT_SYMBOL vmlinux 0x5b4cb032 skb_queue_tail +EXPORT_SYMBOL vmlinux 0x5b57a9e4 journal_wipe +EXPORT_SYMBOL vmlinux 0x5b963681 search_binary_handler +EXPORT_SYMBOL vmlinux 0x5bcbbbb7 netif_receive_skb +EXPORT_SYMBOL vmlinux 0x5bec5805 scsi_target_quiesce +EXPORT_SYMBOL vmlinux 0x5c1e72db blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x5c28c726 sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x5c484ab2 inet_frags_fini +EXPORT_SYMBOL vmlinux 0x5c673bc8 tty_mutex +EXPORT_SYMBOL vmlinux 0x5c9284a0 processor_id +EXPORT_SYMBOL vmlinux 0x5c997aa2 scsi_track_queue_full +EXPORT_SYMBOL vmlinux 0x5ccacb90 pcim_iomap_table +EXPORT_SYMBOL vmlinux 0x5d0782d2 seq_escape +EXPORT_SYMBOL vmlinux 0x5d2d92b0 inode_needs_sync +EXPORT_SYMBOL vmlinux 0x5d35176c __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0x5d459b44 svc_authenticate +EXPORT_SYMBOL vmlinux 0x5d4f93a8 scsi_execute_req +EXPORT_SYMBOL vmlinux 0x5d689503 pneigh_lookup +EXPORT_SYMBOL vmlinux 0x5d795875 gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0x5da79a68 open_by_devnum +EXPORT_SYMBOL vmlinux 0x5e371928 ip_defrag +EXPORT_SYMBOL vmlinux 0x5e4fb91e skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0x5e5adadc netif_carrier_on +EXPORT_SYMBOL vmlinux 0x5e69ce1e tcp_getsockopt +EXPORT_SYMBOL vmlinux 0x5e772c04 tcf_exts_validate +EXPORT_SYMBOL vmlinux 0x5e78f29f pci_scan_bridge +EXPORT_SYMBOL vmlinux 0x5ea520c5 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x5ebb56fb down_read +EXPORT_SYMBOL vmlinux 0x5ec13579 i2c_clients_command +EXPORT_SYMBOL vmlinux 0x5edd0762 bin2bcd +EXPORT_SYMBOL vmlinux 0x5ef1c079 ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x5f3ea15d pcie_get_readrq +EXPORT_SYMBOL vmlinux 0x5f754e5a memset +EXPORT_SYMBOL vmlinux 0x5f8c9839 alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0x5fd3b953 neigh_update +EXPORT_SYMBOL vmlinux 0x5fe63c9f ip_route_output_key +EXPORT_SYMBOL vmlinux 0x5fff8759 vfs_statfs +EXPORT_SYMBOL vmlinux 0x600291c1 nf_setsockopt +EXPORT_SYMBOL vmlinux 0x60041b11 input_free_device +EXPORT_SYMBOL vmlinux 0x601610c5 pci_clear_mwi +EXPORT_SYMBOL vmlinux 0x602d47c0 cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0x603468a0 sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0x60674ea7 cdev_add +EXPORT_SYMBOL vmlinux 0x608c2831 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x6098c0de rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0x609f1c7e synchronize_net +EXPORT_SYMBOL vmlinux 0x60a32ea9 pm_power_off +EXPORT_SYMBOL vmlinux 0x60ad11e7 set_disk_ro +EXPORT_SYMBOL vmlinux 0x60b167be journal_unlock_updates +EXPORT_SYMBOL vmlinux 0x60ba7688 xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0x610d4e28 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x61258f48 journal_errno +EXPORT_SYMBOL vmlinux 0x61593b72 __mod_timer +EXPORT_SYMBOL vmlinux 0x61764034 i2c_get_adapter +EXPORT_SYMBOL vmlinux 0x618d8299 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x619f1d1c ida_destroy +EXPORT_SYMBOL vmlinux 0x61b7b126 simple_strtoull +EXPORT_SYMBOL vmlinux 0x61c9e746 dma_sync_single_range_for_cpu +EXPORT_SYMBOL vmlinux 0x625b06f5 filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0x62737e1d sock_unregister +EXPORT_SYMBOL vmlinux 0x6285a00b simple_write_begin +EXPORT_SYMBOL vmlinux 0x628f353c tcp_read_sock +EXPORT_SYMBOL vmlinux 0x628fc68c proc_symlink +EXPORT_SYMBOL vmlinux 0x62972bcb tty_register_driver +EXPORT_SYMBOL vmlinux 0x62f04bb9 idr_pre_get +EXPORT_SYMBOL vmlinux 0x639a2b3c do_munmap +EXPORT_SYMBOL vmlinux 0x63a27099 journal_dirty_metadata +EXPORT_SYMBOL vmlinux 0x63ecad53 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x63f19e6d vfs_write +EXPORT_SYMBOL vmlinux 0x6402aaff release_resource +EXPORT_SYMBOL vmlinux 0x6403e338 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x640a7078 posix_acl_create_masq +EXPORT_SYMBOL vmlinux 0x640a8afd eth_header_cache_update +EXPORT_SYMBOL vmlinux 0x641e181e drop_super +EXPORT_SYMBOL vmlinux 0x6439b601 __netif_schedule +EXPORT_SYMBOL vmlinux 0x6440acc8 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0x64461a52 seq_printf +EXPORT_SYMBOL vmlinux 0x645ff1a1 send_sig_info +EXPORT_SYMBOL vmlinux 0x64999478 congestion_wait +EXPORT_SYMBOL vmlinux 0x64b5c85a sock_kmalloc +EXPORT_SYMBOL vmlinux 0x64cdc77a dma_sync_single_range_for_device +EXPORT_SYMBOL vmlinux 0x64e829ae linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0x650128e7 br_fdb_get_hook +EXPORT_SYMBOL vmlinux 0x6509661a sb_min_blocksize +EXPORT_SYMBOL vmlinux 0x65408378 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x65414e67 dev_valid_name +EXPORT_SYMBOL vmlinux 0x65493a77 kset_unregister +EXPORT_SYMBOL vmlinux 0x6567aad1 contig_page_data +EXPORT_SYMBOL vmlinux 0x659619f6 scsi_eh_restore_cmnd +EXPORT_SYMBOL vmlinux 0x65ba0114 sock_i_ino +EXPORT_SYMBOL vmlinux 0x65f34a4b bd_claim +EXPORT_SYMBOL vmlinux 0x661e6ec8 bioset_free +EXPORT_SYMBOL vmlinux 0x661ed2dc dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x666592b2 dev_get_by_flags +EXPORT_SYMBOL vmlinux 0x6679e297 journal_dirty_data +EXPORT_SYMBOL vmlinux 0x667ea34d poll_initwait +EXPORT_SYMBOL vmlinux 0x668da8d5 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x66a41719 find_get_page +EXPORT_SYMBOL vmlinux 0x66c1e276 write_cache_pages +EXPORT_SYMBOL vmlinux 0x66c73159 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0x66d9b6ec ilookup +EXPORT_SYMBOL vmlinux 0x6737cbe4 tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0x67b27ec1 tty_std_termios +EXPORT_SYMBOL vmlinux 0x67c19637 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x67c2fa54 __copy_to_user +EXPORT_SYMBOL vmlinux 0x67f055a0 cont_write_begin +EXPORT_SYMBOL vmlinux 0x681b67a7 cache_purge +EXPORT_SYMBOL vmlinux 0x681cacc8 pci_disable_device +EXPORT_SYMBOL vmlinux 0x68240a91 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0x68476277 scsi_remove_target +EXPORT_SYMBOL vmlinux 0x687ba39b journal_get_undo_access +EXPORT_SYMBOL vmlinux 0x687f743a block_write_full_page +EXPORT_SYMBOL vmlinux 0x6886cdb4 unlock_new_inode +EXPORT_SYMBOL vmlinux 0x6898a756 sg_init_table +EXPORT_SYMBOL vmlinux 0x68a764e8 kill_anon_super +EXPORT_SYMBOL vmlinux 0x68b76a4d i2c_use_client +EXPORT_SYMBOL vmlinux 0x68b845be input_open_device +EXPORT_SYMBOL vmlinux 0x68f21dd1 inode_init_once +EXPORT_SYMBOL vmlinux 0x69249d18 do_splice_to +EXPORT_SYMBOL vmlinux 0x6933e246 skb_trim +EXPORT_SYMBOL vmlinux 0x69350296 vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x6941f503 simple_release_fs +EXPORT_SYMBOL vmlinux 0x69496641 mod_timer +EXPORT_SYMBOL vmlinux 0x6971447a rtc_month_days +EXPORT_SYMBOL vmlinux 0x6975b54b flush_dcache_page +EXPORT_SYMBOL vmlinux 0x69927dff try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x699f4476 kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0x69b7acbd inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0x69b7adc0 fd_install +EXPORT_SYMBOL vmlinux 0x69b86606 lock_may_write +EXPORT_SYMBOL vmlinux 0x69d38ed9 __scsi_print_sense +EXPORT_SYMBOL vmlinux 0x6a037cf1 mempool_kfree +EXPORT_SYMBOL vmlinux 0x6a47571d __set_personality +EXPORT_SYMBOL vmlinux 0x6ac45c28 __up_write +EXPORT_SYMBOL vmlinux 0x6b097cd9 sock_wmalloc +EXPORT_SYMBOL vmlinux 0x6b1b67d3 __bdevname +EXPORT_SYMBOL vmlinux 0x6b2dc060 dump_stack +EXPORT_SYMBOL vmlinux 0x6b6ae9cf sock_release +EXPORT_SYMBOL vmlinux 0x6b72cabc pcix_get_mmrbc +EXPORT_SYMBOL vmlinux 0x6bdcfd99 qdisc_class_hash_remove +EXPORT_SYMBOL vmlinux 0x6bf115f7 zero_fill_bio +EXPORT_SYMBOL vmlinux 0x6c0456f3 xscale_mc_clear_user_page +EXPORT_SYMBOL vmlinux 0x6c1ce5ce strcspn +EXPORT_SYMBOL vmlinux 0x6c2061d5 genl_unregister_ops +EXPORT_SYMBOL vmlinux 0x6c282241 skb_clone +EXPORT_SYMBOL vmlinux 0x6c36a5c1 __mutex_init +EXPORT_SYMBOL vmlinux 0x6c702af7 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x6c83f713 ide_dma_lost_irq +EXPORT_SYMBOL vmlinux 0x6c845be8 tcp_shutdown +EXPORT_SYMBOL vmlinux 0x6c9c5cfb xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x6cdc5c6b nla_strlcpy +EXPORT_SYMBOL vmlinux 0x6cef247f __strnlen_user +EXPORT_SYMBOL vmlinux 0x6d0da34c param_get_short +EXPORT_SYMBOL vmlinux 0x6d12ab65 xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x6d27ef64 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x6d288375 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x6d294e43 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x6d340f64 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x6d4ede15 vfs_getattr +EXPORT_SYMBOL vmlinux 0x6d662533 _find_first_bit_le +EXPORT_SYMBOL vmlinux 0x6da4667e scsi_device_get +EXPORT_SYMBOL vmlinux 0x6de11098 sock_rfree +EXPORT_SYMBOL vmlinux 0x6de463ce nf_log_packet +EXPORT_SYMBOL vmlinux 0x6def2db2 half_md4_transform +EXPORT_SYMBOL vmlinux 0x6e0eebcc pci_set_dma_max_seg_size +EXPORT_SYMBOL vmlinux 0x6e1d3d15 nf_register_sockopt +EXPORT_SYMBOL vmlinux 0x6e210c92 vfs_readv +EXPORT_SYMBOL vmlinux 0x6e21f6d7 skb_kill_datagram +EXPORT_SYMBOL vmlinux 0x6e27a537 init_special_inode +EXPORT_SYMBOL vmlinux 0x6e429e97 irq_to_gpio +EXPORT_SYMBOL vmlinux 0x6e440b58 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x6e720ff2 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x6e783a09 sock_create_lite +EXPORT_SYMBOL vmlinux 0x6e84a85c save_time_delta +EXPORT_SYMBOL vmlinux 0x6ea3c7d8 alloc_buffer_head +EXPORT_SYMBOL vmlinux 0x6ecff451 blk_verify_command +EXPORT_SYMBOL vmlinux 0x6ed81852 ida_remove +EXPORT_SYMBOL vmlinux 0x6eea229d svcauth_unix_purge +EXPORT_SYMBOL vmlinux 0x6f2572b0 kobject_set_name +EXPORT_SYMBOL vmlinux 0x6fc96a95 ip_mc_join_group +EXPORT_SYMBOL vmlinux 0x6fc9d183 register_sysctl_table +EXPORT_SYMBOL vmlinux 0x6fcb87a1 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x6fe2cae0 skb_under_panic +EXPORT_SYMBOL vmlinux 0x6ff681cd cfi_read_pri +EXPORT_SYMBOL vmlinux 0x6ff948df proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x7008a9b7 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x700cf747 generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0x701d0ebd snprintf +EXPORT_SYMBOL vmlinux 0x70499561 tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0x706f4b46 blk_rq_map_user +EXPORT_SYMBOL vmlinux 0x707a3ee3 svcauth_unix_set_client +EXPORT_SYMBOL vmlinux 0x70acc1ed npe_release +EXPORT_SYMBOL vmlinux 0x70c8cff0 bio_map_user +EXPORT_SYMBOL vmlinux 0x70ccbd16 ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0x70f31764 journal_clear_err +EXPORT_SYMBOL vmlinux 0x7129e5f8 hex_asc +EXPORT_SYMBOL vmlinux 0x714e4595 alloc_disk +EXPORT_SYMBOL vmlinux 0x7171121c overflowgid +EXPORT_SYMBOL vmlinux 0x71740f25 blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0x7197050c nobh_writepage +EXPORT_SYMBOL vmlinux 0x71a50dbc register_blkdev +EXPORT_SYMBOL vmlinux 0x71c90087 memcmp +EXPORT_SYMBOL vmlinux 0x71cbd8ee mb_cache_entry_find_first +EXPORT_SYMBOL vmlinux 0x71e4e8b8 gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0x71fa908a cache_flush +EXPORT_SYMBOL vmlinux 0x7221cb39 input_register_handler +EXPORT_SYMBOL vmlinux 0x72243acd ip_route_input +EXPORT_SYMBOL vmlinux 0x72270e35 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x7254c994 netdev_features_change +EXPORT_SYMBOL vmlinux 0x7272970a __elv_add_request +EXPORT_SYMBOL vmlinux 0x72c57187 cache_unregister +EXPORT_SYMBOL vmlinux 0x72d5af61 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x72ea7b2d scsi_device_type +EXPORT_SYMBOL vmlinux 0x72fbae28 set_current_groups +EXPORT_SYMBOL vmlinux 0x7300be7b simple_rmdir +EXPORT_SYMBOL vmlinux 0x735a2d7c neigh_seq_stop +EXPORT_SYMBOL vmlinux 0x73837689 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x738a0a1d sock_no_shutdown +EXPORT_SYMBOL vmlinux 0x73cb5b48 add_disk +EXPORT_SYMBOL vmlinux 0x73e20c1c strlcpy +EXPORT_SYMBOL vmlinux 0x744efc43 pfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0x7456ee47 tcp_parse_options +EXPORT_SYMBOL vmlinux 0x7485e15e unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x749e9db5 auth_unix_lookup +EXPORT_SYMBOL vmlinux 0x74a157c8 elevator_init +EXPORT_SYMBOL vmlinux 0x74ca8007 i2c_smbus_write_byte +EXPORT_SYMBOL vmlinux 0x74cc238d current_kernel_time +EXPORT_SYMBOL vmlinux 0x74d55e89 qdisc_calculate_pkt_len +EXPORT_SYMBOL vmlinux 0x74eaf769 d_splice_alias +EXPORT_SYMBOL vmlinux 0x75124983 dma_map_sg +EXPORT_SYMBOL vmlinux 0x755729c2 input_close_device +EXPORT_SYMBOL vmlinux 0x75987f48 sock_wfree +EXPORT_SYMBOL vmlinux 0x75d76a55 ide_end_drive_cmd +EXPORT_SYMBOL vmlinux 0x75fee7fd __raw_writesb +EXPORT_SYMBOL vmlinux 0x76041f53 tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x760a0f4f yield +EXPORT_SYMBOL vmlinux 0x760b437a unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x76119967 set_user_nice +EXPORT_SYMBOL vmlinux 0x7625b0ba generic_make_request +EXPORT_SYMBOL vmlinux 0x765f75fb pgprot_user +EXPORT_SYMBOL vmlinux 0x767578f2 ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x7679c034 names_cachep +EXPORT_SYMBOL vmlinux 0x76a174ab dev_add_pack +EXPORT_SYMBOL vmlinux 0x76b1bc46 neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0x76bf656d __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x76c013fd dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x76cf47f6 __aeabi_llsl +EXPORT_SYMBOL vmlinux 0x76d3cd60 laptop_mode +EXPORT_SYMBOL vmlinux 0x76e8204e page_follow_link_light +EXPORT_SYMBOL vmlinux 0x77170db8 seq_read +EXPORT_SYMBOL vmlinux 0x771879e7 simple_transaction_get +EXPORT_SYMBOL vmlinux 0x774d0cb9 xfrm_register_type +EXPORT_SYMBOL vmlinux 0x77a79920 generic_file_mmap +EXPORT_SYMBOL vmlinux 0x77c0aaf6 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0x77ecac9f zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x7800fd08 tcp_tso_segment +EXPORT_SYMBOL vmlinux 0x780ae479 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0x78297024 tty_name +EXPORT_SYMBOL vmlinux 0x782c9162 pci_prepare_to_sleep +EXPORT_SYMBOL vmlinux 0x78429bd4 journal_extend +EXPORT_SYMBOL vmlinux 0x7872c714 sock_map_fd +EXPORT_SYMBOL vmlinux 0x787c3495 ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x7881f807 journal_init_dev +EXPORT_SYMBOL vmlinux 0x788d1c7b kobject_del +EXPORT_SYMBOL vmlinux 0x78df6bd7 no_pci_devices +EXPORT_SYMBOL vmlinux 0x78f7a453 qdisc_watchdog_schedule +EXPORT_SYMBOL vmlinux 0x79023869 inet_select_addr +EXPORT_SYMBOL vmlinux 0x794487ee disable_hlt +EXPORT_SYMBOL vmlinux 0x79600d4a wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0x796fc5ce scsi_get_sense_info_fld +EXPORT_SYMBOL vmlinux 0x798fb459 scsi_rescan_device +EXPORT_SYMBOL vmlinux 0x79aa04a2 get_random_bytes +EXPORT_SYMBOL vmlinux 0x79aa05a8 match_token +EXPORT_SYMBOL vmlinux 0x79ad224b tasklet_kill +EXPORT_SYMBOL vmlinux 0x79bc7b60 inet_sendmsg +EXPORT_SYMBOL vmlinux 0x79d0bf2e journal_init_inode +EXPORT_SYMBOL vmlinux 0x79ec0b87 __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0x79f0b541 may_umount_tree +EXPORT_SYMBOL vmlinux 0x7a02b10d mark_page_accessed +EXPORT_SYMBOL vmlinux 0x7a2a837d strict_strtol +EXPORT_SYMBOL vmlinux 0x7a480928 sock_no_poll +EXPORT_SYMBOL vmlinux 0x7a7f8237 iget_locked +EXPORT_SYMBOL vmlinux 0x7a975528 generic_removexattr +EXPORT_SYMBOL vmlinux 0x7ac07607 generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x7ac5515d scsi_device_quiesce +EXPORT_SYMBOL vmlinux 0x7af7f16c dev_open +EXPORT_SYMBOL vmlinux 0x7b1b4f60 xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0x7b3b0650 xfrm_state_add +EXPORT_SYMBOL vmlinux 0x7b761cea generic_readlink +EXPORT_SYMBOL vmlinux 0x7b898c3c may_umount +EXPORT_SYMBOL vmlinux 0x7b9a19e0 dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x7b9d4058 svc_process +EXPORT_SYMBOL vmlinux 0x7bd8f145 km_policy_expired +EXPORT_SYMBOL vmlinux 0x7c1373bf simple_lookup +EXPORT_SYMBOL vmlinux 0x7c13aee7 sock_create_kern +EXPORT_SYMBOL vmlinux 0x7c1c9e7c directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0x7c2200da _clear_bit_be +EXPORT_SYMBOL vmlinux 0x7c5f6444 qdisc_watchdog_init +EXPORT_SYMBOL vmlinux 0x7c60d66e getname +EXPORT_SYMBOL vmlinux 0x7c75287b input_register_device +EXPORT_SYMBOL vmlinux 0x7c8811aa pci_bus_assign_resources +EXPORT_SYMBOL vmlinux 0x7c904ded unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x7cabedba i2c_smbus_read_word_data +EXPORT_SYMBOL vmlinux 0x7cc035a7 __ucmpdi2 +EXPORT_SYMBOL vmlinux 0x7cd832aa mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x7ce41af4 ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0x7cf4654d blk_recount_segments +EXPORT_SYMBOL vmlinux 0x7d11c268 jiffies +EXPORT_SYMBOL vmlinux 0x7d191032 __nla_reserve +EXPORT_SYMBOL vmlinux 0x7d361d56 register_netdev +EXPORT_SYMBOL vmlinux 0x7d50000f scsi_remove_device +EXPORT_SYMBOL vmlinux 0x7d6769ec find_get_pages_tag +EXPORT_SYMBOL vmlinux 0x7d7c8154 rpc_unlink +EXPORT_SYMBOL vmlinux 0x7d860b57 lease_get_mtime +EXPORT_SYMBOL vmlinux 0x7dceceac capable +EXPORT_SYMBOL vmlinux 0x7ddacfb5 xdr_decode_array2 +EXPORT_SYMBOL vmlinux 0x7e058bfb xscale_coherent_kern_range +EXPORT_SYMBOL vmlinux 0x7e531cde del_timer +EXPORT_SYMBOL vmlinux 0x7e55ee49 scsi_is_host_device +EXPORT_SYMBOL vmlinux 0x7e673f3a sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x7e785d29 set_page_dirty +EXPORT_SYMBOL vmlinux 0x7e9596c2 __generic_unplug_device +EXPORT_SYMBOL vmlinux 0x7e9ebb05 kernel_thread +EXPORT_SYMBOL vmlinux 0x7eb39b60 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x7f24de73 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x7f25c131 filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0x7f5ee0af netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0x7f63b31e _memcpy_toio +EXPORT_SYMBOL vmlinux 0x7f68164d simple_link +EXPORT_SYMBOL vmlinux 0x7f7a694f unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0x7f8723bd pcie_mch_quirk +EXPORT_SYMBOL vmlinux 0x7f8b78cb blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x7fd44ff1 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0x7ffc8817 xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0x800e4ffa __muldi3 +EXPORT_SYMBOL vmlinux 0x8015846e bdget +EXPORT_SYMBOL vmlinux 0x80322f60 __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x80579ec9 __ide_dma_bad_drive +EXPORT_SYMBOL vmlinux 0x8063f83d radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x80683c7e mii_ethtool_gset +EXPORT_SYMBOL vmlinux 0x807f80d9 default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0x8085c7b1 prepare_to_wait +EXPORT_SYMBOL vmlinux 0x8091b01c ide_dump_status +EXPORT_SYMBOL vmlinux 0x809f3cb5 igrab +EXPORT_SYMBOL vmlinux 0x80a78b43 pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x80d7607d tty_vhangup +EXPORT_SYMBOL vmlinux 0x80e4ad8a poll_freewait +EXPORT_SYMBOL vmlinux 0x813e674d fib_default_rule_add +EXPORT_SYMBOL vmlinux 0x815b5dd4 match_octal +EXPORT_SYMBOL vmlinux 0x816da62e mnt_pin +EXPORT_SYMBOL vmlinux 0x8175dbf1 dma_free_coherent +EXPORT_SYMBOL vmlinux 0x81799cee vscnprintf +EXPORT_SYMBOL vmlinux 0x81bec3f0 unregister_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0x820d225f print_mac +EXPORT_SYMBOL vmlinux 0x8213d320 scsi_remove_host +EXPORT_SYMBOL vmlinux 0x82188776 __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0x82519b08 sock_create +EXPORT_SYMBOL vmlinux 0x8251bcc3 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x82692209 kref_set +EXPORT_SYMBOL vmlinux 0x8282e451 eth_type_trans +EXPORT_SYMBOL vmlinux 0x828811f9 journal_force_commit +EXPORT_SYMBOL vmlinux 0x82aa261e task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x82b4cfaa _find_first_zero_bit_be +EXPORT_SYMBOL vmlinux 0x82cbfeb0 udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x82e5a238 vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x830331b3 kobject_add +EXPORT_SYMBOL vmlinux 0x8320bea8 __umodsi3 +EXPORT_SYMBOL vmlinux 0x83234f28 stop_tty +EXPORT_SYMBOL vmlinux 0x834b097f pci_pme_active +EXPORT_SYMBOL vmlinux 0x83589db6 unlock_super +EXPORT_SYMBOL vmlinux 0x836e1fd7 __scsi_alloc_queue +EXPORT_SYMBOL vmlinux 0x838352a2 lock_super +EXPORT_SYMBOL vmlinux 0x83a476ce bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x83cf978c blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0x83f667ec qdisc_watchdog_cancel +EXPORT_SYMBOL vmlinux 0x83fc8ad2 ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0x8429ae7e neigh_seq_next +EXPORT_SYMBOL vmlinux 0x8429c64c pci_reenable_device +EXPORT_SYMBOL vmlinux 0x845111df read_dev_sector +EXPORT_SYMBOL vmlinux 0x84b183ae strncmp +EXPORT_SYMBOL vmlinux 0x84bc9ae1 scsi_free_host_dev +EXPORT_SYMBOL vmlinux 0x84e7e834 xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0x84f31234 tty_unthrottle +EXPORT_SYMBOL vmlinux 0x8500a45a tty_throttle +EXPORT_SYMBOL vmlinux 0x852abecf __request_region +EXPORT_SYMBOL vmlinux 0x8533511f xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x854d6f81 dcache_dir_close +EXPORT_SYMBOL vmlinux 0x85670f1d rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x85818045 elv_next_request +EXPORT_SYMBOL vmlinux 0x85a01f8e svc_auth_register +EXPORT_SYMBOL vmlinux 0x85ac7f10 posix_acl_from_xattr +EXPORT_SYMBOL vmlinux 0x85b6ba29 block_write_end +EXPORT_SYMBOL vmlinux 0x85cb26de do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0x85df9b6c strsep +EXPORT_SYMBOL vmlinux 0x85e7deb2 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x86035fca elevator_exit +EXPORT_SYMBOL vmlinux 0x8645d353 dmabounce_register_dev +EXPORT_SYMBOL vmlinux 0x86564f90 __kill_fasync +EXPORT_SYMBOL vmlinux 0x868acba5 get_options +EXPORT_SYMBOL vmlinux 0x86a59caf unregister_exec_domain +EXPORT_SYMBOL vmlinux 0x86be1a91 sysctl_data +EXPORT_SYMBOL vmlinux 0x86f54e1c pci_bus_add_devices +EXPORT_SYMBOL vmlinux 0x86f9d8b4 generic_osync_inode +EXPORT_SYMBOL vmlinux 0x86fb9b05 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x871dd361 dentry_unhash +EXPORT_SYMBOL vmlinux 0x873e24de _find_next_zero_bit_be +EXPORT_SYMBOL vmlinux 0x875990ee blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x8785725d param_set_charp +EXPORT_SYMBOL vmlinux 0x878a35f4 xdr_buf_read_netobj +EXPORT_SYMBOL vmlinux 0x878ab3ce sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x878ee640 alloc_file +EXPORT_SYMBOL vmlinux 0x87b61127 generic_file_splice_write +EXPORT_SYMBOL vmlinux 0x87d04a08 pci_bus_write_config_dword +EXPORT_SYMBOL vmlinux 0x881039d0 zlib_inflate +EXPORT_SYMBOL vmlinux 0x887c83f0 ipv4_specific +EXPORT_SYMBOL vmlinux 0x887db1e1 lock_rename +EXPORT_SYMBOL vmlinux 0x88b1e5c1 input_unregister_handler +EXPORT_SYMBOL vmlinux 0x88c2ec42 vfs_permission +EXPORT_SYMBOL vmlinux 0x88e0d938 mb_cache_create +EXPORT_SYMBOL vmlinux 0x890034fe simple_transaction_release +EXPORT_SYMBOL vmlinux 0x891909aa i2c_register_driver +EXPORT_SYMBOL vmlinux 0x89195dc3 sonet_copy_stats +EXPORT_SYMBOL vmlinux 0x891e32b8 wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0x8922e4c8 xfrm_input_resume +EXPORT_SYMBOL vmlinux 0x896b96df tcf_hash_lookup +EXPORT_SYMBOL vmlinux 0x897473df mktime +EXPORT_SYMBOL vmlinux 0x89790144 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0x89d66811 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x89f1998d nf_afinfo +EXPORT_SYMBOL vmlinux 0x89ff0f02 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0x8a1203a9 kref_get +EXPORT_SYMBOL vmlinux 0x8a1799d8 bdev_read_only +EXPORT_SYMBOL vmlinux 0x8a413dd4 sysctl_intvec +EXPORT_SYMBOL vmlinux 0x8a46fb47 tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0x8a4fa83b __aeabi_llsr +EXPORT_SYMBOL vmlinux 0x8a6133fc invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0x8a790f70 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0x8a7d1c31 high_memory +EXPORT_SYMBOL vmlinux 0x8a82b6e0 npe_running +EXPORT_SYMBOL vmlinux 0x8a99a016 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x8acfbe40 pci_fixup_device +EXPORT_SYMBOL vmlinux 0x8ad292b6 pci_iounmap +EXPORT_SYMBOL vmlinux 0x8add3d3f scsi_calculate_bounce_limit +EXPORT_SYMBOL vmlinux 0x8ae1910f idr_remove_all +EXPORT_SYMBOL vmlinux 0x8ae352cc clear_inode +EXPORT_SYMBOL vmlinux 0x8b23ba62 npe_send_message +EXPORT_SYMBOL vmlinux 0x8b618d08 overflowuid +EXPORT_SYMBOL vmlinux 0x8bba6bed sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x8bdad1ad devm_iounmap +EXPORT_SYMBOL vmlinux 0x8be1cc9d blk_rq_init +EXPORT_SYMBOL vmlinux 0x8c84069c restore_time_delta +EXPORT_SYMBOL vmlinux 0x8ce8a6c1 init_buffer +EXPORT_SYMBOL vmlinux 0x8d2ea80c unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0x8d34435f write_inode_now +EXPORT_SYMBOL vmlinux 0x8d3894f2 _ctype +EXPORT_SYMBOL vmlinux 0x8d4f4aeb journal_load +EXPORT_SYMBOL vmlinux 0x8d551bef sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x8d5642fc wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0x8d6f81b4 __div64_32 +EXPORT_SYMBOL vmlinux 0x8d8a325a ip_route_me_harder +EXPORT_SYMBOL vmlinux 0x8dbddc91 tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0x8dce94cd bio_put +EXPORT_SYMBOL vmlinux 0x8df22991 genl_register_ops +EXPORT_SYMBOL vmlinux 0x8df2c404 bio_alloc +EXPORT_SYMBOL vmlinux 0x8e3c9cc3 vprintk +EXPORT_SYMBOL vmlinux 0x8e4f3202 destroy_EII_client +EXPORT_SYMBOL vmlinux 0x8e725985 nf_log_unregister_pf +EXPORT_SYMBOL vmlinux 0x8ec80e54 blk_insert_request +EXPORT_SYMBOL vmlinux 0x8ed25b8a i2c_put_adapter +EXPORT_SYMBOL vmlinux 0x8f07d8ca __wait_on_bit +EXPORT_SYMBOL vmlinux 0x8f1cbf5f i2c_master_send +EXPORT_SYMBOL vmlinux 0x8f6b7950 set_irq_data +EXPORT_SYMBOL vmlinux 0x8f9b86b2 kfifo_alloc +EXPORT_SYMBOL vmlinux 0x8f9f3432 copy_strings_kernel +EXPORT_SYMBOL vmlinux 0x8fc97333 pci_add_new_bus +EXPORT_SYMBOL vmlinux 0x8fe12013 __lock_page +EXPORT_SYMBOL vmlinux 0x900eec19 tcp_connect +EXPORT_SYMBOL vmlinux 0x9017eabf i2c_add_adapter +EXPORT_SYMBOL vmlinux 0x90896184 __invalidate_device +EXPORT_SYMBOL vmlinux 0x90b01af9 simple_fill_super +EXPORT_SYMBOL vmlinux 0x90c7ebe7 tcp_make_synack +EXPORT_SYMBOL vmlinux 0x90e8ff21 blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0x91481982 __ratelimit +EXPORT_SYMBOL vmlinux 0x9150e257 tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0x9151863d __vlan_hwaccel_rx +EXPORT_SYMBOL vmlinux 0x9175cbb9 get_user_pages +EXPORT_SYMBOL vmlinux 0x919029aa __readwrite_bug +EXPORT_SYMBOL vmlinux 0x91c0567a ide_proc_unregister_driver +EXPORT_SYMBOL vmlinux 0x91fc23fb skb_dequeue +EXPORT_SYMBOL vmlinux 0x9228f726 skb_find_text +EXPORT_SYMBOL vmlinux 0x92405573 neigh_parms_release +EXPORT_SYMBOL vmlinux 0x924900da I_BDEV +EXPORT_SYMBOL vmlinux 0x925ad4a3 register_sysrq_key +EXPORT_SYMBOL vmlinux 0x926401f2 sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0x92a061b3 pci_release_region +EXPORT_SYMBOL vmlinux 0x9352962b scsi_device_put +EXPORT_SYMBOL vmlinux 0x9369aec9 blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0x939240f1 blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0x93a0c8b2 locks_mandatory_area +EXPORT_SYMBOL vmlinux 0x93a6e0b2 io_schedule +EXPORT_SYMBOL vmlinux 0x93c51d3d generic_unplug_device +EXPORT_SYMBOL vmlinux 0x93c69acf param_set_byte +EXPORT_SYMBOL vmlinux 0x93e88efb pci_bus_read_config_word +EXPORT_SYMBOL vmlinux 0x93f1daa9 iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0x93fca811 __get_free_pages +EXPORT_SYMBOL vmlinux 0x9417b481 pci_bus_type +EXPORT_SYMBOL vmlinux 0x94300910 svc_create +EXPORT_SYMBOL vmlinux 0x948b11e7 pci_scan_bus_parented +EXPORT_SYMBOL vmlinux 0x94961283 vunmap +EXPORT_SYMBOL vmlinux 0x949743c0 xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0x94b19638 kill_block_super +EXPORT_SYMBOL vmlinux 0x94eff7c7 skb_checksum_help +EXPORT_SYMBOL vmlinux 0x94fb7f33 scsi_reset_provider +EXPORT_SYMBOL vmlinux 0x9501d078 __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0x95215351 netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x954488a4 syncookie_secret +EXPORT_SYMBOL vmlinux 0x954cbb26 vsprintf +EXPORT_SYMBOL vmlinux 0x954de910 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x955805c7 d_alloc_root +EXPORT_SYMBOL vmlinux 0x95dbe078 __get_user_2 +EXPORT_SYMBOL vmlinux 0x95f61c41 rtnl_unicast +EXPORT_SYMBOL vmlinux 0x96245c50 input_get_keycode +EXPORT_SYMBOL vmlinux 0x96254a65 elv_add_request +EXPORT_SYMBOL vmlinux 0x96898769 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0x96a2b069 sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x96bed019 blk_get_request +EXPORT_SYMBOL vmlinux 0x96cd2b04 scsi_sense_key_string +EXPORT_SYMBOL vmlinux 0x96db1bd4 netdev_state_change +EXPORT_SYMBOL vmlinux 0x96df5482 walk_stackframe +EXPORT_SYMBOL vmlinux 0x9702c0e6 scsi_setup_blk_pc_cmnd +EXPORT_SYMBOL vmlinux 0x97255bdf strlen +EXPORT_SYMBOL vmlinux 0x9732ca64 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0x973aa7aa pci_enable_device_io +EXPORT_SYMBOL vmlinux 0x9754ec10 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x976e539e lockd_up +EXPORT_SYMBOL vmlinux 0x9777787e xdr_inline_decode +EXPORT_SYMBOL vmlinux 0x97a87b88 pci_iomap +EXPORT_SYMBOL vmlinux 0x97be1c5d register_gifconf +EXPORT_SYMBOL vmlinux 0x97c9d69d dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0x981026f6 km_report +EXPORT_SYMBOL vmlinux 0x985e86cf dma_mmap_coherent +EXPORT_SYMBOL vmlinux 0x987758cb simple_map_init +EXPORT_SYMBOL vmlinux 0x988d2fa1 scsi_target_resume +EXPORT_SYMBOL vmlinux 0x9896cc76 km_policy_notify +EXPORT_SYMBOL vmlinux 0x98c3c5cc save_mount_options +EXPORT_SYMBOL vmlinux 0x98e9972c dmabounce_unregister_dev +EXPORT_SYMBOL vmlinux 0x98ed083f init_mm +EXPORT_SYMBOL vmlinux 0x98f05c08 nla_put +EXPORT_SYMBOL vmlinux 0x98fa58a7 gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0x990f1644 atm_init_aal5 +EXPORT_SYMBOL vmlinux 0x9911be3b sg_miter_next +EXPORT_SYMBOL vmlinux 0x993629ec udplite_prot +EXPORT_SYMBOL vmlinux 0x995fe247 svc_recv +EXPORT_SYMBOL vmlinux 0x99693dbe uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x99758f5e devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0x999c3148 __raw_readsb +EXPORT_SYMBOL vmlinux 0x999e8297 vfree +EXPORT_SYMBOL vmlinux 0x99aadb21 param_get_ulong +EXPORT_SYMBOL vmlinux 0x99bb8806 memmove +EXPORT_SYMBOL vmlinux 0x99bfbe39 get_unused_fd +EXPORT_SYMBOL vmlinux 0x99c3c0b0 vfs_fstat +EXPORT_SYMBOL vmlinux 0x99c4d1e9 pci_get_class +EXPORT_SYMBOL vmlinux 0x99cdc86b sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x99dd9835 neigh_table_clear +EXPORT_SYMBOL vmlinux 0x99df97d2 i2c_smbus_read_byte_data +EXPORT_SYMBOL vmlinux 0x99ea12ce panic_blink +EXPORT_SYMBOL vmlinux 0x9a108cd3 tcf_hash_release +EXPORT_SYMBOL vmlinux 0x9a1dfd65 strpbrk +EXPORT_SYMBOL vmlinux 0x9a54c870 ide_wait_stat +EXPORT_SYMBOL vmlinux 0x9a8f985d dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0x9acb67a3 pci_map_rom +EXPORT_SYMBOL vmlinux 0x9acbe18d inode_change_ok +EXPORT_SYMBOL vmlinux 0x9ae1d5ce prepare_binprm +EXPORT_SYMBOL vmlinux 0x9aebffc1 scsi_nonblockable_ioctl +EXPORT_SYMBOL vmlinux 0x9aee117f udp_poll +EXPORT_SYMBOL vmlinux 0x9af1c2ea elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0x9b139f23 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0x9b213bb8 auth_unix_forget_old +EXPORT_SYMBOL vmlinux 0x9b388444 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x9b38e73c inet_frags_init +EXPORT_SYMBOL vmlinux 0x9b479dea dma_map_single +EXPORT_SYMBOL vmlinux 0x9b88a672 end_request +EXPORT_SYMBOL vmlinux 0x9ba7089d argv_split +EXPORT_SYMBOL vmlinux 0x9be7402a ide_spin_wait_hwgroup +EXPORT_SYMBOL vmlinux 0x9bfe467c netif_rx +EXPORT_SYMBOL vmlinux 0x9c08158c journal_release_buffer +EXPORT_SYMBOL vmlinux 0x9c2571f4 __down_read +EXPORT_SYMBOL vmlinux 0x9c28a65c blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0x9c7077bd enable_hlt +EXPORT_SYMBOL vmlinux 0x9c75d37b cache_register +EXPORT_SYMBOL vmlinux 0x9c97cec4 inet_dgram_connect +EXPORT_SYMBOL vmlinux 0x9c9b4fa7 vfs_path_lookup +EXPORT_SYMBOL vmlinux 0x9cb96e92 qdisc_put_rtab +EXPORT_SYMBOL vmlinux 0x9cc1d965 udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0x9ce8510d call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x9ceb163c memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x9cfd56c5 scsi_print_status +EXPORT_SYMBOL vmlinux 0x9d2a1311 nf_unregister_queue_handler +EXPORT_SYMBOL vmlinux 0x9d43755c request_resource +EXPORT_SYMBOL vmlinux 0x9d5bf0af dev_mc_sync +EXPORT_SYMBOL vmlinux 0x9d5c1529 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0x9d6620b1 sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0x9d669763 memcpy +EXPORT_SYMBOL vmlinux 0x9d760cab pci_set_master +EXPORT_SYMBOL vmlinux 0x9dac7fdc dev_set_mtu +EXPORT_SYMBOL vmlinux 0x9dacd9c5 unregister_netdevice +EXPORT_SYMBOL vmlinux 0x9df61709 scsi_scan_host +EXPORT_SYMBOL vmlinux 0x9e2b904d put_tty_driver +EXPORT_SYMBOL vmlinux 0x9e7d6bd0 __udelay +EXPORT_SYMBOL vmlinux 0x9ebd2b11 path_permission +EXPORT_SYMBOL vmlinux 0x9ec34254 register_sysctl_paths +EXPORT_SYMBOL vmlinux 0x9eced984 lock_may_read +EXPORT_SYMBOL vmlinux 0x9ed685ee iov_iter_advance +EXPORT_SYMBOL vmlinux 0x9edec594 ide_dma_off_quietly +EXPORT_SYMBOL vmlinux 0x9eecde16 do_brk +EXPORT_SYMBOL vmlinux 0x9ef749e2 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x9f100139 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x9f2bdaac __bitmap_or +EXPORT_SYMBOL vmlinux 0x9f2bf98f single_open +EXPORT_SYMBOL vmlinux 0x9f81924c cfi_fixup +EXPORT_SYMBOL vmlinux 0x9f984513 strrchr +EXPORT_SYMBOL vmlinux 0x9f9ed6b8 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0x9fb3dd30 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x9fb50d6f __bread +EXPORT_SYMBOL vmlinux 0x9fd6de04 skb_seq_read +EXPORT_SYMBOL vmlinux 0x9fe8f68e pci_save_state +EXPORT_SYMBOL vmlinux 0xa0038408 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0xa04a01bd qdisc_class_hash_insert +EXPORT_SYMBOL vmlinux 0xa04bd823 inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0xa05768a3 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0xa05c03df mempool_kmalloc +EXPORT_SYMBOL vmlinux 0xa07a8d22 sleep_on +EXPORT_SYMBOL vmlinux 0xa07ac24b irq_stat +EXPORT_SYMBOL vmlinux 0xa0856378 kill_pid +EXPORT_SYMBOL vmlinux 0xa0b04675 vmalloc_32 +EXPORT_SYMBOL vmlinux 0xa0b6e10d __pci_register_driver +EXPORT_SYMBOL vmlinux 0xa0caf631 call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0xa0ceef51 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0xa0e0e047 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0xa0ef76d9 d_alloc +EXPORT_SYMBOL vmlinux 0xa0fbac79 wake_up_bit +EXPORT_SYMBOL vmlinux 0xa108eb4d sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0xa11ce6ef task_session_nr_ns +EXPORT_SYMBOL vmlinux 0xa120d33c tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0xa129393e bio_copy_user +EXPORT_SYMBOL vmlinux 0xa12b940c kthread_bind +EXPORT_SYMBOL vmlinux 0xa13798f8 printk_ratelimit +EXPORT_SYMBOL vmlinux 0xa13cd270 d_delete +EXPORT_SYMBOL vmlinux 0xa14ab13c call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0xa182b4b1 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0xa1c76e0a _cond_resched +EXPORT_SYMBOL vmlinux 0xa20ce1b8 net_msg_warn +EXPORT_SYMBOL vmlinux 0xa218bf61 complete +EXPORT_SYMBOL vmlinux 0xa228b53e dma_sync_sg_for_cpu +EXPORT_SYMBOL vmlinux 0xa2351c00 d_lookup +EXPORT_SYMBOL vmlinux 0xa23e2363 __free_pages +EXPORT_SYMBOL vmlinux 0xa2600c9a vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0xa268907b scsi_eh_finish_cmd +EXPORT_SYMBOL vmlinux 0xa29b1708 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0xa2a5fd77 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0xa2d1b58e tty_unregister_driver +EXPORT_SYMBOL vmlinux 0xa2f53a8d posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0xa2f86529 f_setown +EXPORT_SYMBOL vmlinux 0xa304a664 fifo_set_limit +EXPORT_SYMBOL vmlinux 0xa329f07e register_shrinker +EXPORT_SYMBOL vmlinux 0xa34f1ef5 crc32_le +EXPORT_SYMBOL vmlinux 0xa35ce718 simple_readpage +EXPORT_SYMBOL vmlinux 0xa35de80f ipv4_config +EXPORT_SYMBOL vmlinux 0xa35e04fc __alloc_skb +EXPORT_SYMBOL vmlinux 0xa369ef5f __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0xa37f548e skb_append +EXPORT_SYMBOL vmlinux 0xa38c23e1 d_alloc_anon +EXPORT_SYMBOL vmlinux 0xa3a4ed03 cond_resched_lock +EXPORT_SYMBOL vmlinux 0xa3ebd7d7 uart_add_one_port +EXPORT_SYMBOL vmlinux 0xa464d3f7 scsi_device_lookup +EXPORT_SYMBOL vmlinux 0xa4e4d361 elv_rb_find +EXPORT_SYMBOL vmlinux 0xa5117e48 dev_unicast_add +EXPORT_SYMBOL vmlinux 0xa511d5d4 do_SAK +EXPORT_SYMBOL vmlinux 0xa53cb808 vfs_create +EXPORT_SYMBOL vmlinux 0xa5423cc4 param_get_int +EXPORT_SYMBOL vmlinux 0xa5808bbf tasklet_init +EXPORT_SYMBOL vmlinux 0xa58b6804 nla_parse +EXPORT_SYMBOL vmlinux 0xa5fe7905 dget_locked +EXPORT_SYMBOL vmlinux 0xa62674df sk_wait_data +EXPORT_SYMBOL vmlinux 0xa629abf5 mb_cache_entry_alloc +EXPORT_SYMBOL vmlinux 0xa632e257 scsi_add_device +EXPORT_SYMBOL vmlinux 0xa64830c0 dev_alloc_name +EXPORT_SYMBOL vmlinux 0xa663e3d7 ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0xa68124fa hweight8 +EXPORT_SYMBOL vmlinux 0xa681fe88 generate_random_uuid +EXPORT_SYMBOL vmlinux 0xa6dcc773 rb_insert_color +EXPORT_SYMBOL vmlinux 0xa7502f48 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0xa76c3ab1 kmalloc_caches +EXPORT_SYMBOL vmlinux 0xa777f91f block_truncate_page +EXPORT_SYMBOL vmlinux 0xa779e007 release_sock +EXPORT_SYMBOL vmlinux 0xa78fc7a3 vfs_rename +EXPORT_SYMBOL vmlinux 0xa7b91a7b lockd_down +EXPORT_SYMBOL vmlinux 0xa7c35c6b getnstimeofday +EXPORT_SYMBOL vmlinux 0xa7c36907 tcp_prot +EXPORT_SYMBOL vmlinux 0xa7d7b455 pci_enable_device_mem +EXPORT_SYMBOL vmlinux 0xa823b8aa mpage_readpage +EXPORT_SYMBOL vmlinux 0xa832dd90 pcie_set_readrq +EXPORT_SYMBOL vmlinux 0xa8fb16f8 call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0xa925899a param_set_bool +EXPORT_SYMBOL vmlinux 0xa945b257 inet_register_protosw +EXPORT_SYMBOL vmlinux 0xa987885e remove_arg_zero +EXPORT_SYMBOL vmlinux 0xa9a45dde write_one_page +EXPORT_SYMBOL vmlinux 0xa9bb0676 block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0xa9e8c8ec blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0xa9f1ed23 bit_waitqueue +EXPORT_SYMBOL vmlinux 0xaa09ef49 nla_put_nohdr +EXPORT_SYMBOL vmlinux 0xaa1b9f9d tcf_exts_destroy +EXPORT_SYMBOL vmlinux 0xaa48f915 dev_unicast_sync +EXPORT_SYMBOL vmlinux 0xaa527612 __kfifo_put +EXPORT_SYMBOL vmlinux 0xaa9be967 elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0xaaa4306e scsi_block_requests +EXPORT_SYMBOL vmlinux 0xaae77a5d __find_get_block +EXPORT_SYMBOL vmlinux 0xaafdc258 strcasecmp +EXPORT_SYMBOL vmlinux 0xab1107fd sk_stream_error +EXPORT_SYMBOL vmlinux 0xab3f15c1 __bforget +EXPORT_SYMBOL vmlinux 0xab471003 param_array_set +EXPORT_SYMBOL vmlinux 0xab53b0a8 mempool_alloc +EXPORT_SYMBOL vmlinux 0xab57d98f put_page +EXPORT_SYMBOL vmlinux 0xab600421 probe_irq_off +EXPORT_SYMBOL vmlinux 0xab64527d mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0xab680c96 __down_read_trylock +EXPORT_SYMBOL vmlinux 0xab8036b1 nf_unregister_sockopt +EXPORT_SYMBOL vmlinux 0xabad83d7 udp_hash_lock +EXPORT_SYMBOL vmlinux 0xabd0c91c rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0xabe9aed7 generic_block_bmap +EXPORT_SYMBOL vmlinux 0xabfdb44c kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0xabfe4db7 __rta_fill +EXPORT_SYMBOL vmlinux 0xac3b3cee __bitmap_and +EXPORT_SYMBOL vmlinux 0xac54fc9f mempool_destroy +EXPORT_SYMBOL vmlinux 0xac6c34d5 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0xac9b2a53 clocksource_register +EXPORT_SYMBOL vmlinux 0xacb405f7 tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0xacc7aa1d sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0xaccabc6a in4_pton +EXPORT_SYMBOL vmlinux 0xacf4d843 match_strdup +EXPORT_SYMBOL vmlinux 0xad0413d4 match_hex +EXPORT_SYMBOL vmlinux 0xad09c2db get_nfs_grace_period +EXPORT_SYMBOL vmlinux 0xad18e44c dmam_pool_create +EXPORT_SYMBOL vmlinux 0xad224d2f close_bdev_excl +EXPORT_SYMBOL vmlinux 0xad313645 i2c_master_recv +EXPORT_SYMBOL vmlinux 0xad36d2c9 ide_dma_timeout +EXPORT_SYMBOL vmlinux 0xad5f2380 simple_sync_file +EXPORT_SYMBOL vmlinux 0xad804627 dev_getbyhwaddr +EXPORT_SYMBOL vmlinux 0xad8712b7 unmap_mapping_range +EXPORT_SYMBOL vmlinux 0xadb792c2 prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0xadc952f6 blk_queue_make_request +EXPORT_SYMBOL vmlinux 0xadedc28f xfrm_find_acq +EXPORT_SYMBOL vmlinux 0xae094bd6 ip_setsockopt +EXPORT_SYMBOL vmlinux 0xae928067 sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0xae9e5cd6 devm_ioremap +EXPORT_SYMBOL vmlinux 0xaeb7072b remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0xaec655c7 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0xaed013b9 posix_acl_valid +EXPORT_SYMBOL vmlinux 0xaf0282ea invalidate_inodes +EXPORT_SYMBOL vmlinux 0xaf2d1c2b bdevname +EXPORT_SYMBOL vmlinux 0xaf64ad0d zlib_deflate +EXPORT_SYMBOL vmlinux 0xaf6599bf qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0xaf7c41e2 pcix_get_max_mmrbc +EXPORT_SYMBOL vmlinux 0xaf846849 unlock_buffer +EXPORT_SYMBOL vmlinux 0xaf8aa518 system_rev +EXPORT_SYMBOL vmlinux 0xaf8e7058 inode_sub_bytes +EXPORT_SYMBOL vmlinux 0xafb863cf dst_alloc +EXPORT_SYMBOL vmlinux 0xafdcef97 pci_find_next_bus +EXPORT_SYMBOL vmlinux 0xafee659a i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL vmlinux 0xaff32cc3 __dst_free +EXPORT_SYMBOL vmlinux 0xb0006757 sock_no_accept +EXPORT_SYMBOL vmlinux 0xb014f300 blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0xb0887734 deny_write_access +EXPORT_SYMBOL vmlinux 0xb0b0ef2e blk_sync_queue +EXPORT_SYMBOL vmlinux 0xb0b847ac __bitmap_full +EXPORT_SYMBOL vmlinux 0xb0e10781 get_option +EXPORT_SYMBOL vmlinux 0xb0e2607e console_start +EXPORT_SYMBOL vmlinux 0xb10f9777 udp_prot +EXPORT_SYMBOL vmlinux 0xb11b6ef8 eth_header +EXPORT_SYMBOL vmlinux 0xb121390a probe_irq_on +EXPORT_SYMBOL vmlinux 0xb138f0d3 vfs_readdir +EXPORT_SYMBOL vmlinux 0xb17a2790 register_filesystem +EXPORT_SYMBOL vmlinux 0xb17b1412 __break_lease +EXPORT_SYMBOL vmlinux 0xb18f3f06 ide_xfer_verbose +EXPORT_SYMBOL vmlinux 0xb19760c3 bitmap_onto +EXPORT_SYMBOL vmlinux 0xb1c3a01a oops_in_progress +EXPORT_SYMBOL vmlinux 0xb1e03f06 register_exec_domain +EXPORT_SYMBOL vmlinux 0xb2031dd9 wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0xb21fd0c4 find_task_by_vpid +EXPORT_SYMBOL vmlinux 0xb229a0f7 nla_reserve +EXPORT_SYMBOL vmlinux 0xb2bf1312 __up_read +EXPORT_SYMBOL vmlinux 0xb2cdaec0 simple_rename +EXPORT_SYMBOL vmlinux 0xb2d34538 sk_common_release +EXPORT_SYMBOL vmlinux 0xb34a699d scsi_setup_fs_cmnd +EXPORT_SYMBOL vmlinux 0xb352cf51 free_task +EXPORT_SYMBOL vmlinux 0xb3610a94 dev_set_allmulti +EXPORT_SYMBOL vmlinux 0xb376d79d radix_tree_tagged +EXPORT_SYMBOL vmlinux 0xb384ba77 skb_store_bits +EXPORT_SYMBOL vmlinux 0xb39d383c task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0xb39dbb87 netif_rx_ni +EXPORT_SYMBOL vmlinux 0xb3a307c6 si_meminfo +EXPORT_SYMBOL vmlinux 0xb3a8d59d pci_request_regions +EXPORT_SYMBOL vmlinux 0xb3fe02b1 down_write +EXPORT_SYMBOL vmlinux 0xb407b205 ioport_resource +EXPORT_SYMBOL vmlinux 0xb4386774 journal_create +EXPORT_SYMBOL vmlinux 0xb46f8269 __f_setown +EXPORT_SYMBOL vmlinux 0xb4923196 devm_request_irq +EXPORT_SYMBOL vmlinux 0xb494e82a br_fdb_put_hook +EXPORT_SYMBOL vmlinux 0xb4955b27 blk_put_request +EXPORT_SYMBOL vmlinux 0xb4a0e989 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0xb5044271 vsscanf +EXPORT_SYMBOL vmlinux 0xb506fdc1 scsi_register_driver +EXPORT_SYMBOL vmlinux 0xb51b687a dcache_dir_open +EXPORT_SYMBOL vmlinux 0xb534763c sg_free_table +EXPORT_SYMBOL vmlinux 0xb54533f7 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0xb5692da5 neigh_seq_start +EXPORT_SYMBOL vmlinux 0xb5a459dc unregister_blkdev +EXPORT_SYMBOL vmlinux 0xb5be4664 make_EII_client +EXPORT_SYMBOL vmlinux 0xb5e5d73b i2c_smbus_xfer +EXPORT_SYMBOL vmlinux 0xb60e34a8 nla_memcpy +EXPORT_SYMBOL vmlinux 0xb64a1635 cpu_present_map +EXPORT_SYMBOL vmlinux 0xb664a26d scsi_unblock_requests +EXPORT_SYMBOL vmlinux 0xb66fea4e scsi_device_resume +EXPORT_SYMBOL vmlinux 0xb678366f int_sqrt +EXPORT_SYMBOL vmlinux 0xb68a3bb0 kmem_ptr_validate +EXPORT_SYMBOL vmlinux 0xb68bcadd remove_proc_entry +EXPORT_SYMBOL vmlinux 0xb6a61a86 qdisc_get_rtab +EXPORT_SYMBOL vmlinux 0xb6aea6fd register_binfmt +EXPORT_SYMBOL vmlinux 0xb6c4756c filp_open +EXPORT_SYMBOL vmlinux 0xb6c5a973 scsi_show_result +EXPORT_SYMBOL vmlinux 0xb6c70a7d __wake_up +EXPORT_SYMBOL vmlinux 0xb703911e release_firmware +EXPORT_SYMBOL vmlinux 0xb714a981 console_print +EXPORT_SYMBOL vmlinux 0xb714fbec tcp_rcv_established +EXPORT_SYMBOL vmlinux 0xb7555f12 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0xb776f7f3 bio_copy_kern +EXPORT_SYMBOL vmlinux 0xb77b2ecf ip_nat_decode_session +EXPORT_SYMBOL vmlinux 0xb78a43ba do_sync_read +EXPORT_SYMBOL vmlinux 0xb798898c __napi_schedule +EXPORT_SYMBOL vmlinux 0xb7a99d4e end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0xb7aa1ee1 get_io_context +EXPORT_SYMBOL vmlinux 0xb7b61546 crc32_be +EXPORT_SYMBOL vmlinux 0xb7b63a46 mem_map +EXPORT_SYMBOL vmlinux 0xb7bb1ff0 journal_get_write_access +EXPORT_SYMBOL vmlinux 0xb7c7e897 generic_fillattr +EXPORT_SYMBOL vmlinux 0xb7fd6711 ide_do_reset +EXPORT_SYMBOL vmlinux 0xb8196830 unix_domain_find +EXPORT_SYMBOL vmlinux 0xb85081b9 free_buffer_head +EXPORT_SYMBOL vmlinux 0xb859f38b krealloc +EXPORT_SYMBOL vmlinux 0xb86e4ab9 random32 +EXPORT_SYMBOL vmlinux 0xb89187f9 drive_is_ready +EXPORT_SYMBOL vmlinux 0xb89af9bf srandom32 +EXPORT_SYMBOL vmlinux 0xb8b8d8d9 bdi_register +EXPORT_SYMBOL vmlinux 0xb8e0b1be request_firmware +EXPORT_SYMBOL vmlinux 0xb912a9b3 kobject_init +EXPORT_SYMBOL vmlinux 0xb92742ed pcim_enable_device +EXPORT_SYMBOL vmlinux 0xb92c2c97 register_console +EXPORT_SYMBOL vmlinux 0xb93a0f1d scsi_free_command +EXPORT_SYMBOL vmlinux 0xb95f98d6 _memset_io +EXPORT_SYMBOL vmlinux 0xb97d4c9c mutex_lock +EXPORT_SYMBOL vmlinux 0xb98a0185 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0xb98ef804 vm_stat +EXPORT_SYMBOL vmlinux 0xb9acd3d9 __put_user_2 +EXPORT_SYMBOL vmlinux 0xb9c74bf1 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0xb9efdcda bio_clone +EXPORT_SYMBOL vmlinux 0xba075d6d tc_classify +EXPORT_SYMBOL vmlinux 0xba0b9422 lock_sock_nested +EXPORT_SYMBOL vmlinux 0xba3bda2a __downgrade_write +EXPORT_SYMBOL vmlinux 0xba3f45a3 dev_driver_string +EXPORT_SYMBOL vmlinux 0xba497f13 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0xba5078fd xscale_flush_kern_cache_all +EXPORT_SYMBOL vmlinux 0xba59d405 input_register_handle +EXPORT_SYMBOL vmlinux 0xba686732 sock_no_getname +EXPORT_SYMBOL vmlinux 0xba6ba3cd xdr_shift_buf +EXPORT_SYMBOL vmlinux 0xba8f8b68 completion_done +EXPORT_SYMBOL vmlinux 0xba9336e4 page_put_link +EXPORT_SYMBOL vmlinux 0xbb189cad disallow_signal +EXPORT_SYMBOL vmlinux 0xbb282c4e dev_alloc_skb +EXPORT_SYMBOL vmlinux 0xbb3525f8 skb_pad +EXPORT_SYMBOL vmlinux 0xbb387dea should_remove_suid +EXPORT_SYMBOL vmlinux 0xbb5d343d xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0xbb72d4fe __put_user_1 +EXPORT_SYMBOL vmlinux 0xbb95999d dma_mark_declared_memory_occupied +EXPORT_SYMBOL vmlinux 0xbba61c16 ixp4xx_pci_read +EXPORT_SYMBOL vmlinux 0xbba7f706 sock_get_timestampns +EXPORT_SYMBOL vmlinux 0xbbc8e804 param_set_ushort +EXPORT_SYMBOL vmlinux 0xbbd46860 ida_pre_get +EXPORT_SYMBOL vmlinux 0xbbfd74a1 __scm_destroy +EXPORT_SYMBOL vmlinux 0xbc08a9b9 svc_prepare_thread +EXPORT_SYMBOL vmlinux 0xbc10dd97 __put_user_4 +EXPORT_SYMBOL vmlinux 0xbc12fc06 sk_dst_check +EXPORT_SYMBOL vmlinux 0xbc16fde2 svc_set_num_threads +EXPORT_SYMBOL vmlinux 0xbc38b2a1 scsi_print_result +EXPORT_SYMBOL vmlinux 0xbc8a5288 kernel_getsockname +EXPORT_SYMBOL vmlinux 0xbc8eb6ee pci_request_selected_regions +EXPORT_SYMBOL vmlinux 0xbca11f0c xdr_encode_array2 +EXPORT_SYMBOL vmlinux 0xbcfb34c9 ll_rw_block +EXPORT_SYMBOL vmlinux 0xbd19620a bio_phys_segments +EXPORT_SYMBOL vmlinux 0xbd2bcce4 blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0xbd8aeed4 mpage_writepage +EXPORT_SYMBOL vmlinux 0xbda6fdc1 filemap_flush +EXPORT_SYMBOL vmlinux 0xbdb4c66d generic_writepages +EXPORT_SYMBOL vmlinux 0xbdde283f touch_atime +EXPORT_SYMBOL vmlinux 0xbdf2580d __raw_readsl +EXPORT_SYMBOL vmlinux 0xbdfc8bc0 pci_enable_device +EXPORT_SYMBOL vmlinux 0xbe0e5118 nla_memcmp +EXPORT_SYMBOL vmlinux 0xbe41e4a1 tty_check_change +EXPORT_SYMBOL vmlinux 0xbe7ff8f7 tty_devnum +EXPORT_SYMBOL vmlinux 0xbe82135b cad_pid +EXPORT_SYMBOL vmlinux 0xbe973bdc netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0xbebfbd04 add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0xbee49c30 kobject_put +EXPORT_SYMBOL vmlinux 0xbef43296 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0xbf177e8a cache_check +EXPORT_SYMBOL vmlinux 0xbf202e22 register_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0xbf6130ae end_page_writeback +EXPORT_SYMBOL vmlinux 0xbf7fd2f5 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0xbf9bcc8d __cap_empty_set +EXPORT_SYMBOL vmlinux 0xbf9eeb23 atm_charge +EXPORT_SYMBOL vmlinux 0xbfad081a blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0xbfc8c448 xdr_reserve_space +EXPORT_SYMBOL vmlinux 0xbfee3ad5 loop_unregister_transfer +EXPORT_SYMBOL vmlinux 0xc0404fd0 i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL vmlinux 0xc045ad4e timespec_trunc +EXPORT_SYMBOL vmlinux 0xc0580937 rb_erase +EXPORT_SYMBOL vmlinux 0xc05b7630 brioctl_set +EXPORT_SYMBOL vmlinux 0xc05cb01c kset_register +EXPORT_SYMBOL vmlinux 0xc0618703 neigh_destroy +EXPORT_SYMBOL vmlinux 0xc0c1952b tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0xc0d89cb2 qmgr_set_irq +EXPORT_SYMBOL vmlinux 0xc0dc5213 pid_task +EXPORT_SYMBOL vmlinux 0xc111a62a ide_dma_off +EXPORT_SYMBOL vmlinux 0xc119a498 scsi_device_lookup_by_target +EXPORT_SYMBOL vmlinux 0xc11d8093 iov_shorten +EXPORT_SYMBOL vmlinux 0xc12c8feb generic_ro_fops +EXPORT_SYMBOL vmlinux 0xc14e9a22 sk_reset_timer +EXPORT_SYMBOL vmlinux 0xc15934cc rtnl_create_link +EXPORT_SYMBOL vmlinux 0xc1601a4f _change_bit_le +EXPORT_SYMBOL vmlinux 0xc161dca7 ida_get_new_above +EXPORT_SYMBOL vmlinux 0xc1777aac sock_i_uid +EXPORT_SYMBOL vmlinux 0xc1794900 d_find_alias +EXPORT_SYMBOL vmlinux 0xc19f00f4 sync_blockdev +EXPORT_SYMBOL vmlinux 0xc1fc4511 _test_and_change_bit_le +EXPORT_SYMBOL vmlinux 0xc22616f1 __init_rwsem +EXPORT_SYMBOL vmlinux 0xc2399be8 sk_stop_timer +EXPORT_SYMBOL vmlinux 0xc256e762 __bitmap_equal +EXPORT_SYMBOL vmlinux 0xc27487dd __bug +EXPORT_SYMBOL vmlinux 0xc2da2658 xfrm_lookup +EXPORT_SYMBOL vmlinux 0xc2e587d1 reset_devices +EXPORT_SYMBOL vmlinux 0xc2e923ac sb_set_blocksize +EXPORT_SYMBOL vmlinux 0xc2fd7cc8 tcf_exts_dump +EXPORT_SYMBOL vmlinux 0xc3027e16 misc_deregister +EXPORT_SYMBOL vmlinux 0xc345af7f init_file +EXPORT_SYMBOL vmlinux 0xc34f16c4 arp_tbl +EXPORT_SYMBOL vmlinux 0xc359fb65 abort +EXPORT_SYMBOL vmlinux 0xc3880471 xdr_decode_netobj +EXPORT_SYMBOL vmlinux 0xc38e5923 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0xc3b37a69 blk_unplug +EXPORT_SYMBOL vmlinux 0xc3bb2c23 gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0xc3c824dd xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0xc3cf1128 in_group_p +EXPORT_SYMBOL vmlinux 0xc3e5c695 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0xc3f614dc add_mtd_partitions +EXPORT_SYMBOL vmlinux 0xc3f7b43b get_write_access +EXPORT_SYMBOL vmlinux 0xc41bc7e3 scsi_init_io +EXPORT_SYMBOL vmlinux 0xc43e06a8 atm_dev_lookup +EXPORT_SYMBOL vmlinux 0xc440c451 sg_alloc_table +EXPORT_SYMBOL vmlinux 0xc48a566e read_bytes_from_xdr_buf +EXPORT_SYMBOL vmlinux 0xc499ae1e kstrdup +EXPORT_SYMBOL vmlinux 0xc4c5363b dmam_release_declared_memory +EXPORT_SYMBOL vmlinux 0xc4def760 generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0xc51446df __scsi_iterate_devices +EXPORT_SYMBOL vmlinux 0xc524f0cd scsi_host_lookup +EXPORT_SYMBOL vmlinux 0xc556a9b0 auth_domain_lookup +EXPORT_SYMBOL vmlinux 0xc56582c3 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0xc568d1a5 __page_symlink +EXPORT_SYMBOL vmlinux 0xc5b3e6ec skb_make_writable +EXPORT_SYMBOL vmlinux 0xc5ce0c18 input_set_keycode +EXPORT_SYMBOL vmlinux 0xc625d2b9 ixp4xx_exp_bus_size +EXPORT_SYMBOL vmlinux 0xc633495b schedule_work +EXPORT_SYMBOL vmlinux 0xc64d84a0 devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0xc65ce3cf skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0xc663f978 nf_getsockopt +EXPORT_SYMBOL vmlinux 0xc68c4eb3 tcp_child_process +EXPORT_SYMBOL vmlinux 0xc6972da0 tcp_disconnect +EXPORT_SYMBOL vmlinux 0xc6aaca02 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0xc6ae532b elv_dequeue_request +EXPORT_SYMBOL vmlinux 0xc6eb86ce pci_set_power_state +EXPORT_SYMBOL vmlinux 0xc6f2052f qdisc_list_del +EXPORT_SYMBOL vmlinux 0xc71c60b8 d_prune_aliases +EXPORT_SYMBOL vmlinux 0xc7208c3a serial8250_resume_port +EXPORT_SYMBOL vmlinux 0xc722227e posix_acl_clone +EXPORT_SYMBOL vmlinux 0xc72e240c xdr_encode_pages +EXPORT_SYMBOL vmlinux 0xc72fec53 grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0xc745bae6 uart_write_wakeup +EXPORT_SYMBOL vmlinux 0xc76bfd87 svc_seq_show +EXPORT_SYMBOL vmlinux 0xc79c82bb sk_stream_write_space +EXPORT_SYMBOL vmlinux 0xc7a4fbed rtnl_lock +EXPORT_SYMBOL vmlinux 0xc7dd46d6 tcp_splice_read +EXPORT_SYMBOL vmlinux 0xc7e02230 ide_add_setting +EXPORT_SYMBOL vmlinux 0xc7ec6c27 strspn +EXPORT_SYMBOL vmlinux 0xc80de694 down_write_trylock +EXPORT_SYMBOL vmlinux 0xc878d24a inode_set_bytes +EXPORT_SYMBOL vmlinux 0xc8a41e98 read_cache_page_async +EXPORT_SYMBOL vmlinux 0xc8b14568 test_set_page_writeback +EXPORT_SYMBOL vmlinux 0xc8b57c27 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0xc8e96dea qword_addhex +EXPORT_SYMBOL vmlinux 0xc8fadc6a pci_find_bus +EXPORT_SYMBOL vmlinux 0xc920cf0b pci_remove_behind_bridge +EXPORT_SYMBOL vmlinux 0xc96b3552 km_state_notify +EXPORT_SYMBOL vmlinux 0xc998d641 icmp_err_convert +EXPORT_SYMBOL vmlinux 0xca5dbc50 scsi_print_sense_hdr +EXPORT_SYMBOL vmlinux 0xca8e3b43 xfrm_state_delete +EXPORT_SYMBOL vmlinux 0xca9c334e scsi_release_buffers +EXPORT_SYMBOL vmlinux 0xcabe682b read_cache_pages +EXPORT_SYMBOL vmlinux 0xcadfd5b5 register_netdevice +EXPORT_SYMBOL vmlinux 0xcb164f39 d_instantiate +EXPORT_SYMBOL vmlinux 0xcb32da10 param_set_int +EXPORT_SYMBOL vmlinux 0xcb5b74d1 br_handle_frame_hook +EXPORT_SYMBOL vmlinux 0xcb5e9b26 scsi_print_sense +EXPORT_SYMBOL vmlinux 0xcb61e7db kfree_skb +EXPORT_SYMBOL vmlinux 0xcb6beb40 hweight32 +EXPORT_SYMBOL vmlinux 0xcbb95279 vfs_follow_link +EXPORT_SYMBOL vmlinux 0xcbd905fe shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0xcc1fc530 inet_listen +EXPORT_SYMBOL vmlinux 0xcc248d26 serial8250_suspend_port +EXPORT_SYMBOL vmlinux 0xcc36f32e fb_unregister_client +EXPORT_SYMBOL vmlinux 0xcc3db364 tcp_proc_register +EXPORT_SYMBOL vmlinux 0xcc47d0cf input_flush_device +EXPORT_SYMBOL vmlinux 0xcc497cc7 neigh_resolve_output +EXPORT_SYMBOL vmlinux 0xcc5005fe msleep_interruptible +EXPORT_SYMBOL vmlinux 0xcc78fea4 skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0xcc7fa952 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0xcc88ef3d register_atm_ioctl +EXPORT_SYMBOL vmlinux 0xcccca482 _test_and_clear_bit_le +EXPORT_SYMBOL vmlinux 0xccdc7b9c sock_no_connect +EXPORT_SYMBOL vmlinux 0xccfb7128 nf_reinject +EXPORT_SYMBOL vmlinux 0xcd143754 file_remove_suid +EXPORT_SYMBOL vmlinux 0xcd15303d __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0xcd63c845 __aeabi_lasr +EXPORT_SYMBOL vmlinux 0xcd78c9f8 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0xcd8f5913 ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0xcd909ff3 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0xcda4377e xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0xcdb089d9 kernel_getsockopt +EXPORT_SYMBOL vmlinux 0xcdf9ee38 pci_match_id +EXPORT_SYMBOL vmlinux 0xcdfa91ab inet_frag_evictor +EXPORT_SYMBOL vmlinux 0xce36ded6 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0xce4d7884 path_put +EXPORT_SYMBOL vmlinux 0xce526308 dev_get_by_name +EXPORT_SYMBOL vmlinux 0xce5ac24f zlib_inflate_workspacesize +EXPORT_SYMBOL vmlinux 0xce6ac382 is_bad_inode +EXPORT_SYMBOL vmlinux 0xce6e8fda generic_file_llseek +EXPORT_SYMBOL vmlinux 0xce75b661 nf_log_register +EXPORT_SYMBOL vmlinux 0xce861db7 skb_insert +EXPORT_SYMBOL vmlinux 0xce867728 init_net +EXPORT_SYMBOL vmlinux 0xcea59b69 get_fs_type +EXPORT_SYMBOL vmlinux 0xcebcad65 bd_set_size +EXPORT_SYMBOL vmlinux 0xcecb0f2e pci_bus_find_capability +EXPORT_SYMBOL vmlinux 0xcefcd99a serial8250_unregister_port +EXPORT_SYMBOL vmlinux 0xcf3eba6b qdisc_destroy +EXPORT_SYMBOL vmlinux 0xcf40c0af __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0xcf461fe1 __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0xcfb1e3f9 notify_change +EXPORT_SYMBOL vmlinux 0xcfd3018e set_normalized_timespec +EXPORT_SYMBOL vmlinux 0xcff53400 kref_put +EXPORT_SYMBOL vmlinux 0xd0025529 dst_destroy +EXPORT_SYMBOL vmlinux 0xd0181f4f __bitmap_xor +EXPORT_SYMBOL vmlinux 0xd02cc869 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0xd038179f scsi_execute +EXPORT_SYMBOL vmlinux 0xd03e2d2e serial8250_register_port +EXPORT_SYMBOL vmlinux 0xd0445baf wait_on_page_bit +EXPORT_SYMBOL vmlinux 0xd076cb4a seq_open_private +EXPORT_SYMBOL vmlinux 0xd09d661a kthread_stop +EXPORT_SYMBOL vmlinux 0xd0ed232d bdi_unregister +EXPORT_SYMBOL vmlinux 0xd0ee38b8 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0xd168d8b9 cpu_xscale_dcache_clean_area +EXPORT_SYMBOL vmlinux 0xd171560a xdr_inline_pages +EXPORT_SYMBOL vmlinux 0xd17e79ae eth_header_parse +EXPORT_SYMBOL vmlinux 0xd1e55b43 init_task +EXPORT_SYMBOL vmlinux 0xd2435857 sysctl_jiffies +EXPORT_SYMBOL vmlinux 0xd24a2d66 __lookup_hash +EXPORT_SYMBOL vmlinux 0xd2510b07 sg_miter_stop +EXPORT_SYMBOL vmlinux 0xd2555f19 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0xd272129a blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0xd2788692 aio_complete +EXPORT_SYMBOL vmlinux 0xd28d9bad try_to_release_page +EXPORT_SYMBOL vmlinux 0xd2965f6f kthread_should_stop +EXPORT_SYMBOL vmlinux 0xd2985d62 bio_init +EXPORT_SYMBOL vmlinux 0xd2ae4fe9 journal_forget +EXPORT_SYMBOL vmlinux 0xd2b0e068 xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0xd2c728b8 inode_double_lock +EXPORT_SYMBOL vmlinux 0xd2cbc52c get_disk +EXPORT_SYMBOL vmlinux 0xd2d21bb5 invalidate_partition +EXPORT_SYMBOL vmlinux 0xd2d45b10 qmgr_release_queue +EXPORT_SYMBOL vmlinux 0xd2eb289f inet_shutdown +EXPORT_SYMBOL vmlinux 0xd2fa41ac sock_sendmsg +EXPORT_SYMBOL vmlinux 0xd316eef5 journal_revoke +EXPORT_SYMBOL vmlinux 0xd31edd58 n_tty_ioctl +EXPORT_SYMBOL vmlinux 0xd32e52c7 posix_acl_chmod_masq +EXPORT_SYMBOL vmlinux 0xd340cbc7 simple_getattr +EXPORT_SYMBOL vmlinux 0xd3427f73 mempool_create_node +EXPORT_SYMBOL vmlinux 0xd34fcd8b dma_pool_create +EXPORT_SYMBOL vmlinux 0xd3aa595e pci_restore_state +EXPORT_SYMBOL vmlinux 0xd3aec78e end_dequeued_request +EXPORT_SYMBOL vmlinux 0xd3b4edd2 pcim_iomap_regions_request_all +EXPORT_SYMBOL vmlinux 0xd3c58f0d kill_litter_super +EXPORT_SYMBOL vmlinux 0xd3cc70b7 neigh_compat_output +EXPORT_SYMBOL vmlinux 0xd3dbfbc4 _find_first_zero_bit_le +EXPORT_SYMBOL vmlinux 0xd3f9d97c scsi_host_put +EXPORT_SYMBOL vmlinux 0xd450338d redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0xd493b046 scsi_block_when_processing_errors +EXPORT_SYMBOL vmlinux 0xd4b00aa9 xfrm_user_policy +EXPORT_SYMBOL vmlinux 0xd5263820 mb_cache_destroy +EXPORT_SYMBOL vmlinux 0xd5349810 locks_remove_posix +EXPORT_SYMBOL vmlinux 0xd56800e6 input_event +EXPORT_SYMBOL vmlinux 0xd5688a7a radix_tree_insert +EXPORT_SYMBOL vmlinux 0xd56dc5ad arp_send +EXPORT_SYMBOL vmlinux 0xd58edc38 svc_destroy +EXPORT_SYMBOL vmlinux 0xd5959b9b uart_resume_port +EXPORT_SYMBOL vmlinux 0xd5afaf21 cdev_init +EXPORT_SYMBOL vmlinux 0xd6035d05 do_settimeofday +EXPORT_SYMBOL vmlinux 0xd61d293f user_path_at +EXPORT_SYMBOL vmlinux 0xd6237cf5 scsi_register_interface +EXPORT_SYMBOL vmlinux 0xd627480b strncat +EXPORT_SYMBOL vmlinux 0xd629e246 __blk_run_queue +EXPORT_SYMBOL vmlinux 0xd62c833f schedule_timeout +EXPORT_SYMBOL vmlinux 0xd66c6228 down_read_trylock +EXPORT_SYMBOL vmlinux 0xd682bb14 posix_unblock_lock +EXPORT_SYMBOL vmlinux 0xd6bbb8fb vfs_rmdir +EXPORT_SYMBOL vmlinux 0xd6ee688f vmalloc +EXPORT_SYMBOL vmlinux 0xd6f83a84 scsicam_bios_param +EXPORT_SYMBOL vmlinux 0xd70bc587 bio_endio +EXPORT_SYMBOL vmlinux 0xd71fea67 file_update_time +EXPORT_SYMBOL vmlinux 0xd74eb36c cpu_online_map +EXPORT_SYMBOL vmlinux 0xd7703c6b inet_frag_destroy +EXPORT_SYMBOL vmlinux 0xd7784e2f mii_check_media +EXPORT_SYMBOL vmlinux 0xd79b5a02 allow_signal +EXPORT_SYMBOL vmlinux 0xd7bbc8ab pci_back_from_sleep +EXPORT_SYMBOL vmlinux 0xd7c51bc4 deactivate_super +EXPORT_SYMBOL vmlinux 0xd8099f1a tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0xd8159d47 tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0xd8282ff0 posix_acl_equiv_mode +EXPORT_SYMBOL vmlinux 0xd865624c sock_register +EXPORT_SYMBOL vmlinux 0xd8a2ab95 in_egroup_p +EXPORT_SYMBOL vmlinux 0xd8e35077 tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0xd8e484f0 register_chrdev_region +EXPORT_SYMBOL vmlinux 0xd8f4a09d inet_del_protocol +EXPORT_SYMBOL vmlinux 0xd9184dfd scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0xd92bde4d splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0xd979a9d9 bmap +EXPORT_SYMBOL vmlinux 0xd985dc99 mempool_free_pages +EXPORT_SYMBOL vmlinux 0xd993d939 tty_hung_up_p +EXPORT_SYMBOL vmlinux 0xd9ce8f0c strnlen +EXPORT_SYMBOL vmlinux 0xd9d03f64 pcim_iomap +EXPORT_SYMBOL vmlinux 0xd9f772c1 pci_find_parent_resource +EXPORT_SYMBOL vmlinux 0xd9f9a569 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0xda1a7335 kasprintf +EXPORT_SYMBOL vmlinux 0xda47a9f0 path_get +EXPORT_SYMBOL vmlinux 0xda5ea696 _test_and_set_bit_le +EXPORT_SYMBOL vmlinux 0xda8b5096 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0xdab4147d d_add_ci +EXPORT_SYMBOL vmlinux 0xdad5bcbd alloc_pci_dev +EXPORT_SYMBOL vmlinux 0xdafe19ee pci_bus_read_config_dword +EXPORT_SYMBOL vmlinux 0xdb1fc5fd qdisc_tree_decrease_qlen +EXPORT_SYMBOL vmlinux 0xdb2f3e68 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0xdb36c048 sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0xdb41a43f dev_queue_xmit +EXPORT_SYMBOL vmlinux 0xdb48a5ce ethtool_op_get_tx_csum +EXPORT_SYMBOL vmlinux 0xdb864d65 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0xdb9ed304 blk_init_queue +EXPORT_SYMBOL vmlinux 0xdbcd416e sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0xdbd93209 uart_get_divisor +EXPORT_SYMBOL vmlinux 0xdbe4594f pci_request_region +EXPORT_SYMBOL vmlinux 0xdbe6f653 get_super +EXPORT_SYMBOL vmlinux 0xdc053205 udp_memory_allocated +EXPORT_SYMBOL vmlinux 0xdc14eda7 pci_pci_problems +EXPORT_SYMBOL vmlinux 0xdc2adb35 add_taint +EXPORT_SYMBOL vmlinux 0xdc43a9c8 daemonize +EXPORT_SYMBOL vmlinux 0xdc6f1dc2 devm_ioport_map +EXPORT_SYMBOL vmlinux 0xdc75ff4f get_empty_filp +EXPORT_SYMBOL vmlinux 0xdcb0349b sys_close +EXPORT_SYMBOL vmlinux 0xdcb6fab6 dev_unicast_delete +EXPORT_SYMBOL vmlinux 0xdcc2cace ip_xfrm_me_harder +EXPORT_SYMBOL vmlinux 0xdd0a2ba2 strlcat +EXPORT_SYMBOL vmlinux 0xdd27fa87 memchr +EXPORT_SYMBOL vmlinux 0xdd376324 skb_push +EXPORT_SYMBOL vmlinux 0xdd5937fd tcf_generic_walker +EXPORT_SYMBOL vmlinux 0xdd6bfccd radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0xdd74b28b tty_port_init +EXPORT_SYMBOL vmlinux 0xdd9b9a38 pci_dev_put +EXPORT_SYMBOL vmlinux 0xdddb2d97 mpage_bio_submit +EXPORT_SYMBOL vmlinux 0xddeef053 vfs_stat +EXPORT_SYMBOL vmlinux 0xddf1422b elv_rb_former_request +EXPORT_SYMBOL vmlinux 0xde75b689 set_irq_type +EXPORT_SYMBOL vmlinux 0xde8def3d scsi_is_sdev_device +EXPORT_SYMBOL vmlinux 0xde9360ba totalram_pages +EXPORT_SYMBOL vmlinux 0xdec54246 find_vma +EXPORT_SYMBOL vmlinux 0xdee24704 tcf_hash_check +EXPORT_SYMBOL vmlinux 0xdf15965d proc_mkdir +EXPORT_SYMBOL vmlinux 0xdf24011f d_instantiate_unique +EXPORT_SYMBOL vmlinux 0xdf55f06f xdr_write_pages +EXPORT_SYMBOL vmlinux 0xdf60cc27 __print_symbol +EXPORT_SYMBOL vmlinux 0xdf8aebb6 gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0xdf929370 fs_overflowgid +EXPORT_SYMBOL vmlinux 0xdff0b2e0 sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0xdffe94a2 d_validate +EXPORT_SYMBOL vmlinux 0xe02136f8 blk_execute_rq +EXPORT_SYMBOL vmlinux 0xe075d6eb iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0xe076c8cb dst_discard +EXPORT_SYMBOL vmlinux 0xe07c37f3 seq_path +EXPORT_SYMBOL vmlinux 0xe07d5eda _test_and_clear_bit_be +EXPORT_SYMBOL vmlinux 0xe07ecccb tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0xe0878bfe __krealloc +EXPORT_SYMBOL vmlinux 0xe0ae02ba tcp_v4_connect +EXPORT_SYMBOL vmlinux 0xe0b13336 argv_free +EXPORT_SYMBOL vmlinux 0xe0d21ec6 find_or_create_page +EXPORT_SYMBOL vmlinux 0xe0fbaf96 xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0xe1089cc6 sock_recvmsg +EXPORT_SYMBOL vmlinux 0xe113bbbc csum_partial +EXPORT_SYMBOL vmlinux 0xe1147f7a mpage_readpages +EXPORT_SYMBOL vmlinux 0xe125c858 pneigh_enqueue +EXPORT_SYMBOL vmlinux 0xe133f874 bh_submit_read +EXPORT_SYMBOL vmlinux 0xe1412f3c sock_no_bind +EXPORT_SYMBOL vmlinux 0xe19d6d57 scsi_host_get +EXPORT_SYMBOL vmlinux 0xe1c546bc netif_device_detach +EXPORT_SYMBOL vmlinux 0xe1c8342c udp_sendmsg +EXPORT_SYMBOL vmlinux 0xe1f3f52d generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0xe21d431c clip_tbl_hook +EXPORT_SYMBOL vmlinux 0xe24d3a97 jiffies_64 +EXPORT_SYMBOL vmlinux 0xe2742408 idr_replace +EXPORT_SYMBOL vmlinux 0xe277984f tcp_mtup_init +EXPORT_SYMBOL vmlinux 0xe28a07b8 svc_proc_register +EXPORT_SYMBOL vmlinux 0xe2d5255a strcmp +EXPORT_SYMBOL vmlinux 0xe2fae716 kmemdup +EXPORT_SYMBOL vmlinux 0xe334eba2 cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0xe351633f genl_register_family +EXPORT_SYMBOL vmlinux 0xe38181e2 journal_check_available_features +EXPORT_SYMBOL vmlinux 0xe382891f __pagevec_release +EXPORT_SYMBOL vmlinux 0xe387c453 mb_cache_entry_release +EXPORT_SYMBOL vmlinux 0xe3880f53 genl_sock +EXPORT_SYMBOL vmlinux 0xe389ccdc udp_lib_get_port +EXPORT_SYMBOL vmlinux 0xe3c69927 i2c_attach_client +EXPORT_SYMBOL vmlinux 0xe3ce774c nf_unregister_hooks +EXPORT_SYMBOL vmlinux 0xe4463490 tc_classify_compat +EXPORT_SYMBOL vmlinux 0xe4583f3c rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0xe499833b vfs_link +EXPORT_SYMBOL vmlinux 0xe4a97c71 __down_write_trylock +EXPORT_SYMBOL vmlinux 0xe4e0de69 fget +EXPORT_SYMBOL vmlinux 0xe4f197b9 skb_recv_datagram +EXPORT_SYMBOL vmlinux 0xe55704ab nf_hooks +EXPORT_SYMBOL vmlinux 0xe57878a1 in6_pton +EXPORT_SYMBOL vmlinux 0xe5867808 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0xe586e71c try_to_free_buffers +EXPORT_SYMBOL vmlinux 0xe5919cb1 xdr_encode_opaque +EXPORT_SYMBOL vmlinux 0xe594093d pcim_pin_device +EXPORT_SYMBOL vmlinux 0xe5c2372a __mpage_writepage +EXPORT_SYMBOL vmlinux 0xe5ca4f4b flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0xe5ddb500 default_llseek +EXPORT_SYMBOL vmlinux 0xe5ddce12 journal_abort +EXPORT_SYMBOL vmlinux 0xe6040885 mb_cache_entry_find_next +EXPORT_SYMBOL vmlinux 0xe643afda netif_carrier_off +EXPORT_SYMBOL vmlinux 0xe64f7f67 locks_init_lock +EXPORT_SYMBOL vmlinux 0xe6687eee scsi_report_bus_reset +EXPORT_SYMBOL vmlinux 0xe69dbc5d clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0xe6ac64ec svc_sock_names +EXPORT_SYMBOL vmlinux 0xe6b35aba open_exec +EXPORT_SYMBOL vmlinux 0xe6bcd78c __locks_copy_lock +EXPORT_SYMBOL vmlinux 0xe6c3ebb0 __raw_writesw +EXPORT_SYMBOL vmlinux 0xe6d04585 posix_acl_permission +EXPORT_SYMBOL vmlinux 0xe6fbe430 can_do_mlock +EXPORT_SYMBOL vmlinux 0xe707d823 __aeabi_uidiv +EXPORT_SYMBOL vmlinux 0xe71a1769 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0xe721cf6f ide_set_handler +EXPORT_SYMBOL vmlinux 0xe749a99f dma_pool_destroy +EXPORT_SYMBOL vmlinux 0xe75374ea elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0xe755b6c7 scsi_get_host_dev +EXPORT_SYMBOL vmlinux 0xe777bc92 journal_ack_err +EXPORT_SYMBOL vmlinux 0xe7b97c97 blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0xe7d4daac seq_list_next +EXPORT_SYMBOL vmlinux 0xe80b0496 journal_destroy +EXPORT_SYMBOL vmlinux 0xe81f3af6 schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0xe83051d3 nobh_write_end +EXPORT_SYMBOL vmlinux 0xe840349c rpc_mkpipe +EXPORT_SYMBOL vmlinux 0xe879ad98 loop_register_transfer +EXPORT_SYMBOL vmlinux 0xe8c0d8d9 dma_unmap_single +EXPORT_SYMBOL vmlinux 0xe8cd902e hweight16 +EXPORT_SYMBOL vmlinux 0xe8dabc00 pci_scan_slot +EXPORT_SYMBOL vmlinux 0xe8e696a4 blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0xe8eae286 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0xe8fa6f72 skb_pull +EXPORT_SYMBOL vmlinux 0xe9084705 pcim_iounmap +EXPORT_SYMBOL vmlinux 0xe90ac3e3 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0xe90ead92 d_genocide +EXPORT_SYMBOL vmlinux 0xe914e41e strcpy +EXPORT_SYMBOL vmlinux 0xe9187307 d_alloc_name +EXPORT_SYMBOL vmlinux 0xe9187c8e eth_rebuild_header +EXPORT_SYMBOL vmlinux 0xe93dbf35 lookup_bdev +EXPORT_SYMBOL vmlinux 0xe9456a5a sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0xe97ad1f6 skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0xe97f4ce5 qword_get +EXPORT_SYMBOL vmlinux 0xe98962fc d_path +EXPORT_SYMBOL vmlinux 0xe9fd90e2 empty_zero_page +EXPORT_SYMBOL vmlinux 0xea10212a int_to_scsilun +EXPORT_SYMBOL vmlinux 0xea10655a __bitmap_intersects +EXPORT_SYMBOL vmlinux 0xea147363 printk +EXPORT_SYMBOL vmlinux 0xea1e279c blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0xea2d33a2 radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0xea46ccef vm_insert_mixed +EXPORT_SYMBOL vmlinux 0xea63253b vfs_symlink +EXPORT_SYMBOL vmlinux 0xea6fcdaa genl_unregister_family +EXPORT_SYMBOL vmlinux 0xea83ab09 scsi_unregister +EXPORT_SYMBOL vmlinux 0xea858cb5 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0xea9ce183 bdi_register_dev +EXPORT_SYMBOL vmlinux 0xead7d913 __brelse +EXPORT_SYMBOL vmlinux 0xeae3dfd6 __const_udelay +EXPORT_SYMBOL vmlinux 0xeb279cd8 cdev_del +EXPORT_SYMBOL vmlinux 0xeb33a589 ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0xeb395084 param_get_invbool +EXPORT_SYMBOL vmlinux 0xeb418ce5 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0xeb700744 xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0xeb8f54b3 strstrip +EXPORT_SYMBOL vmlinux 0xeb969060 netlink_broadcast +EXPORT_SYMBOL vmlinux 0xeba27f16 mii_nway_restart +EXPORT_SYMBOL vmlinux 0xebd24147 proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0xebd273a6 strict_strtoull +EXPORT_SYMBOL vmlinux 0xebeda0b7 skb_copy_expand +EXPORT_SYMBOL vmlinux 0xebfdcbdf system_serial_high +EXPORT_SYMBOL vmlinux 0xec1aa39d arp_broken_ops +EXPORT_SYMBOL vmlinux 0xec41d59b generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0xec5ac21e seq_putc +EXPORT_SYMBOL vmlinux 0xec950cf5 journal_flush +EXPORT_SYMBOL vmlinux 0xecd4ef95 __dev_remove_pack +EXPORT_SYMBOL vmlinux 0xecf21583 pci_find_slot +EXPORT_SYMBOL vmlinux 0xecfa0261 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0xed0f8ee8 pci_bus_size_bridges +EXPORT_SYMBOL vmlinux 0xed1de3e5 sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0xed4dbf49 _test_and_change_bit_be +EXPORT_SYMBOL vmlinux 0xed766b86 auth_unix_add_addr +EXPORT_SYMBOL vmlinux 0xed8ae19d mnt_unpin +EXPORT_SYMBOL vmlinux 0xedb6aae8 inet_stream_ops +EXPORT_SYMBOL vmlinux 0xedbaee5e nla_strcmp +EXPORT_SYMBOL vmlinux 0xedc483f5 journal_try_to_free_buffers +EXPORT_SYMBOL vmlinux 0xedc6f723 tcp_check_req +EXPORT_SYMBOL vmlinux 0xedcf6be4 qword_add +EXPORT_SYMBOL vmlinux 0xedd14538 param_get_uint +EXPORT_SYMBOL vmlinux 0xedd1e017 _change_bit_be +EXPORT_SYMBOL vmlinux 0xedd9106d __ashrdi3 +EXPORT_SYMBOL vmlinux 0xee0400d4 lookup_one_len +EXPORT_SYMBOL vmlinux 0xee0ef63e tty_set_operations +EXPORT_SYMBOL vmlinux 0xee1eb1b6 simple_write_end +EXPORT_SYMBOL vmlinux 0xee2b2983 dma_mmap_writecombine +EXPORT_SYMBOL vmlinux 0xee2d0fc7 _local_bh_enable +EXPORT_SYMBOL vmlinux 0xee3181a9 simple_empty +EXPORT_SYMBOL vmlinux 0xee3f69c7 dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0xee4c77bc proc_create_data +EXPORT_SYMBOL vmlinux 0xee67060c path_lookup +EXPORT_SYMBOL vmlinux 0xeea51256 netdev_class_create_file +EXPORT_SYMBOL vmlinux 0xeea9dbaf bitmap_bitremap +EXPORT_SYMBOL vmlinux 0xeeb1717c param_array_get +EXPORT_SYMBOL vmlinux 0xeee5c2cc kernel_accept +EXPORT_SYMBOL vmlinux 0xeeeca48a npe_recv_message +EXPORT_SYMBOL vmlinux 0xef0b847a mii_check_link +EXPORT_SYMBOL vmlinux 0xef12bae6 sk_release_kernel +EXPORT_SYMBOL vmlinux 0xef1a1668 km_waitq +EXPORT_SYMBOL vmlinux 0xef1c781c vid_which_vrm +EXPORT_SYMBOL vmlinux 0xef62d1fc force_sig +EXPORT_SYMBOL vmlinux 0xef6cf784 sock_wake_async +EXPORT_SYMBOL vmlinux 0xef79ac56 __release_region +EXPORT_SYMBOL vmlinux 0xef9e109b sunrpc_cache_update +EXPORT_SYMBOL vmlinux 0xeff9a0c5 proto_unregister +EXPORT_SYMBOL vmlinux 0xf0009fee put_pages_list +EXPORT_SYMBOL vmlinux 0xf01d79b1 tcf_hash_insert +EXPORT_SYMBOL vmlinux 0xf02a3240 is_container_init +EXPORT_SYMBOL vmlinux 0xf05ec66d tcf_hash_search +EXPORT_SYMBOL vmlinux 0xf07c8199 input_unregister_device +EXPORT_SYMBOL vmlinux 0xf0b57c68 param_set_long +EXPORT_SYMBOL vmlinux 0xf0caf44b zlib_deflate_workspacesize +EXPORT_SYMBOL vmlinux 0xf0d36c09 pagecache_write_begin +EXPORT_SYMBOL vmlinux 0xf0d83768 tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0xf0f1246c kvasprintf +EXPORT_SYMBOL vmlinux 0xf127d215 sock_setsockopt +EXPORT_SYMBOL vmlinux 0xf13e7996 __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0xf1481a11 nobh_write_begin +EXPORT_SYMBOL vmlinux 0xf15f3626 make_bad_inode +EXPORT_SYMBOL vmlinux 0xf161f873 blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0xf162fe2d sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0xf174ed48 acquire_console_sem +EXPORT_SYMBOL vmlinux 0xf1c06c12 sock_get_timestamp +EXPORT_SYMBOL vmlinux 0xf1dc92f3 scsi_eh_prep_cmnd +EXPORT_SYMBOL vmlinux 0xf1dced4c ide_lock +EXPORT_SYMBOL vmlinux 0xf1deabf2 div64_u64 +EXPORT_SYMBOL vmlinux 0xf1e29c13 journal_stop +EXPORT_SYMBOL vmlinux 0xf1e52979 sock_init_data +EXPORT_SYMBOL vmlinux 0xf1e98c74 avenrun +EXPORT_SYMBOL vmlinux 0xf1f74d4a devm_free_irq +EXPORT_SYMBOL vmlinux 0xf20dabd8 free_irq +EXPORT_SYMBOL vmlinux 0xf20ecd78 blk_start_queueing +EXPORT_SYMBOL vmlinux 0xf213b908 skb_free_datagram +EXPORT_SYMBOL vmlinux 0xf21d30b4 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0xf2228b58 noop_qdisc +EXPORT_SYMBOL vmlinux 0xf223ae36 dev_get_flags +EXPORT_SYMBOL vmlinux 0xf2267cf5 generic_file_open +EXPORT_SYMBOL vmlinux 0xf246a18b page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0xf2665232 iget_failed +EXPORT_SYMBOL vmlinux 0xf26b1638 inet_addr_type +EXPORT_SYMBOL vmlinux 0xf27e8d99 __breadahead +EXPORT_SYMBOL vmlinux 0xf27fe85b sg_miter_start +EXPORT_SYMBOL vmlinux 0xf2997713 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0xf2a42785 atm_alloc_charge +EXPORT_SYMBOL vmlinux 0xf2a6d2bf xfrm_policy_count +EXPORT_SYMBOL vmlinux 0xf2afa595 param_get_charp +EXPORT_SYMBOL vmlinux 0xf2b3260b skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0xf2f24da5 inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0xf3097b97 inet_sock_destruct +EXPORT_SYMBOL vmlinux 0xf30b246e blk_alloc_queue +EXPORT_SYMBOL vmlinux 0xf313da4e sha_transform +EXPORT_SYMBOL vmlinux 0xf333cf8a i2c_smbus_read_block_data +EXPORT_SYMBOL vmlinux 0xf338d4c3 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0xf346231f seq_list_start_head +EXPORT_SYMBOL vmlinux 0xf36945b1 __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0xf3879ba0 xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0xf397b9aa __tasklet_schedule +EXPORT_SYMBOL vmlinux 0xf39b3475 pci_bus_read_config_byte +EXPORT_SYMBOL vmlinux 0xf39bf4d9 put_cmsg +EXPORT_SYMBOL vmlinux 0xf3bf0bce __bitmap_complement +EXPORT_SYMBOL vmlinux 0xf3c1b895 filemap_fdatawait +EXPORT_SYMBOL vmlinux 0xf40104c9 sync_page_range +EXPORT_SYMBOL vmlinux 0xf43439ea single_release +EXPORT_SYMBOL vmlinux 0xf44c7c77 dma_release_declared_memory +EXPORT_SYMBOL vmlinux 0xf4613754 do_sync_write +EXPORT_SYMBOL vmlinux 0xf46a3cc2 vmap +EXPORT_SYMBOL vmlinux 0xf476f175 nonseekable_open +EXPORT_SYMBOL vmlinux 0xf497ad70 cap_netlink_recv +EXPORT_SYMBOL vmlinux 0xf49bc67a atm_pcr_goal +EXPORT_SYMBOL vmlinux 0xf4dd6560 pci_assign_resource +EXPORT_SYMBOL vmlinux 0xf4f14de6 rtnl_trylock +EXPORT_SYMBOL vmlinux 0xf5164f58 i2c_smbus_write_word_data +EXPORT_SYMBOL vmlinux 0xf51c639f interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0xf53d4c26 qdisc_class_hash_destroy +EXPORT_SYMBOL vmlinux 0xf542f726 mii_ethtool_sset +EXPORT_SYMBOL vmlinux 0xf55f2f8d tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0xf564412a __aeabi_ulcmp +EXPORT_SYMBOL vmlinux 0xf5789b77 __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0xf593d229 blkdev_put +EXPORT_SYMBOL vmlinux 0xf5c05914 generic_segment_checks +EXPORT_SYMBOL vmlinux 0xf5ceb54e xfrm_register_mode +EXPORT_SYMBOL vmlinux 0xf5cf5d59 __scsi_put_command +EXPORT_SYMBOL vmlinux 0xf6cc6809 iget5_locked +EXPORT_SYMBOL vmlinux 0xf6d26fe8 elv_rb_del +EXPORT_SYMBOL vmlinux 0xf6ebc03b net_ratelimit +EXPORT_SYMBOL vmlinux 0xf6ef5cce _test_and_set_bit_be +EXPORT_SYMBOL vmlinux 0xf7384f52 downgrade_write +EXPORT_SYMBOL vmlinux 0xf741c793 zlib_deflateEnd +EXPORT_SYMBOL vmlinux 0xf747f980 sockfd_lookup +EXPORT_SYMBOL vmlinux 0xf7623914 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0xf7802486 __aeabi_uidivmod +EXPORT_SYMBOL vmlinux 0xf78d04ab netlink_register_notifier +EXPORT_SYMBOL vmlinux 0xf799023b tcf_action_exec +EXPORT_SYMBOL vmlinux 0xf7994968 iunique +EXPORT_SYMBOL vmlinux 0xf7b36d7f ledtrig_ide_activity +EXPORT_SYMBOL vmlinux 0xf7cfdf86 dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0xf7da95ca set_bh_page +EXPORT_SYMBOL vmlinux 0xf811e69d scsi_eh_flush_done_q +EXPORT_SYMBOL vmlinux 0xf8152bf6 scsi_dma_map +EXPORT_SYMBOL vmlinux 0xf81f9d33 remap_pfn_range +EXPORT_SYMBOL vmlinux 0xf8229caa open_bdev_excl +EXPORT_SYMBOL vmlinux 0xf82abc1d isa_dma_bridge_buggy +EXPORT_SYMBOL vmlinux 0xf8326cc0 inode_setattr +EXPORT_SYMBOL vmlinux 0xf8814f73 rb_last +EXPORT_SYMBOL vmlinux 0xf890fe7f pm_idle +EXPORT_SYMBOL vmlinux 0xf8a2bc6b del_gendisk +EXPORT_SYMBOL vmlinux 0xf8b6477b secpath_dup +EXPORT_SYMBOL vmlinux 0xf8fbb4f0 __bad_xchg +EXPORT_SYMBOL vmlinux 0xf903420e uart_match_port +EXPORT_SYMBOL vmlinux 0xf91a6a4a vfs_mkdir +EXPORT_SYMBOL vmlinux 0xf9475001 tty_write_room +EXPORT_SYMBOL vmlinux 0xf94aceda xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0xf983218d i2c_del_adapter +EXPORT_SYMBOL vmlinux 0xf9a482f9 msleep +EXPORT_SYMBOL vmlinux 0xf9b28bac interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0xf9c1a63e neigh_connected_output +EXPORT_SYMBOL vmlinux 0xf9f87467 ida_init +EXPORT_SYMBOL vmlinux 0xfa1d49de scsi_host_set_state +EXPORT_SYMBOL vmlinux 0xfa374ff0 mpage_writepages +EXPORT_SYMBOL vmlinux 0xfa382246 tcp_poll +EXPORT_SYMBOL vmlinux 0xfa452d08 scsi_put_command +EXPORT_SYMBOL vmlinux 0xfa603979 vcc_insert_socket +EXPORT_SYMBOL vmlinux 0xfa663436 nf_register_queue_handler +EXPORT_SYMBOL vmlinux 0xfa6e9928 journal_start +EXPORT_SYMBOL vmlinux 0xfa7daa6c xdr_enter_page +EXPORT_SYMBOL vmlinux 0xfaaa3448 blk_stop_queue +EXPORT_SYMBOL vmlinux 0xfaccdaa2 uart_remove_one_port +EXPORT_SYMBOL vmlinux 0xfad96a75 tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0xfaf98462 bitrev32 +EXPORT_SYMBOL vmlinux 0xfb0a3e0b kmem_cache_free +EXPORT_SYMBOL vmlinux 0xfb0cf2e9 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0xfb326a5d down +EXPORT_SYMBOL vmlinux 0xfb366067 pagevec_lookup +EXPORT_SYMBOL vmlinux 0xfb4c5c04 nobh_truncate_page +EXPORT_SYMBOL vmlinux 0xfb6af58d recalc_sigpending +EXPORT_SYMBOL vmlinux 0xfb72f638 xscale_flush_user_cache_all +EXPORT_SYMBOL vmlinux 0xfb7d9c45 __udivsi3 +EXPORT_SYMBOL vmlinux 0xfbc63880 generic_write_end +EXPORT_SYMBOL vmlinux 0xfbc74f64 __copy_from_user +EXPORT_SYMBOL vmlinux 0xfbd57aa3 sk_free +EXPORT_SYMBOL vmlinux 0xfbd78d24 journal_start_commit +EXPORT_SYMBOL vmlinux 0xfbd9dc10 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0xfbdde612 call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0xfbf92453 param_get_bool +EXPORT_SYMBOL vmlinux 0xfc02b7ad sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0xfc533f85 schedule_work_on +EXPORT_SYMBOL vmlinux 0xfc8394c7 sk_run_filter +EXPORT_SYMBOL vmlinux 0xfcaa04a0 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfcc26834 kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0xfcd0e6c0 skb_copy +EXPORT_SYMBOL vmlinux 0xfcda63a3 node_states +EXPORT_SYMBOL vmlinux 0xfcdd8cf6 param_get_ushort +EXPORT_SYMBOL vmlinux 0xfcec0987 enable_irq +EXPORT_SYMBOL vmlinux 0xfd2bb592 per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0xfd2e9f50 end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0xfd8dba4c add_wait_queue +EXPORT_SYMBOL vmlinux 0xfd98879a rb_next +EXPORT_SYMBOL vmlinux 0xfda529be iput +EXPORT_SYMBOL vmlinux 0xfdd28416 tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0xfdda9bbe __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0xfde2f94a mb_cache_shrink +EXPORT_SYMBOL vmlinux 0xfde59a1d tcp_hashinfo +EXPORT_SYMBOL vmlinux 0xfdf4ecb5 log_wait_commit +EXPORT_SYMBOL vmlinux 0xfdff44dc dma_unmap_sg +EXPORT_SYMBOL vmlinux 0xfe0b09a8 pci_set_mwi +EXPORT_SYMBOL vmlinux 0xfe271510 mutex_lock_killable +EXPORT_SYMBOL vmlinux 0xfe5d4bb2 sys_tz +EXPORT_SYMBOL vmlinux 0xfe653939 sget +EXPORT_SYMBOL vmlinux 0xfe7216dc pci_remove_bus_device +EXPORT_SYMBOL vmlinux 0xfe769456 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0xfead6577 cdev_alloc +EXPORT_SYMBOL vmlinux 0xfebbfdbb udp_disconnect +EXPORT_SYMBOL vmlinux 0xfec3c2f2 bcd2bin +EXPORT_SYMBOL vmlinux 0xfedd35fc console_suspend_enabled +EXPORT_SYMBOL vmlinux 0xfef96e23 __scsi_print_command +EXPORT_SYMBOL vmlinux 0xff1e9dd8 seq_list_start +EXPORT_SYMBOL vmlinux 0xff67b37f __lshrdi3 +EXPORT_SYMBOL vmlinux 0xff69db99 generic_file_direct_write +EXPORT_SYMBOL vmlinux 0xff6f96dc xfrm_register_km +EXPORT_SYMBOL vmlinux 0xffbbc1a7 vfs_read +EXPORT_SYMBOL vmlinux 0xffd5a395 default_wake_function +EXPORT_SYMBOL_GPL drivers/char/hw_random/rng-core 0x86b1667d hwrng_unregister +EXPORT_SYMBOL_GPL drivers/char/hw_random/rng-core 0xf6bcbd73 hwrng_register +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x1bdae0dd nand_scan_tail +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x45f01775 nand_wait_ready +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xc583e17b nand_release +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xe3d12879 nand_scan +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xfc89b282 nand_scan_ident +EXPORT_SYMBOL_GPL net/802/stp 0x0f3a3890 stp_proto_register +EXPORT_SYMBOL_GPL net/802/stp 0xe2f205b1 stp_proto_unregister +EXPORT_SYMBOL_GPL net/ipv4/ipvs/ip_vs 0xe6476b4a net_vs_ctl_path +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x06f291d5 xt_replace_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x1790942a xt_unregister_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x18d3a81b xt_request_find_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x32d340ef xt_table_unlock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x520af18a xt_proto_fini +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x63f05053 xt_find_revision +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x665c7667 xt_register_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x787ea87e xt_proto_init +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x80e76b91 xt_find_table_lock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xb49884e7 xt_check_match +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xc22dfcd9 xt_check_target +EXPORT_SYMBOL_GPL vmlinux 0x00518dcd regulator_set_mode +EXPORT_SYMBOL_GPL vmlinux 0x00566d8f inotify_get_cookie +EXPORT_SYMBOL_GPL vmlinux 0x0067df75 ata_tf_from_fis +EXPORT_SYMBOL_GPL vmlinux 0x00bee21a ata_sff_host_intr +EXPORT_SYMBOL_GPL vmlinux 0x00d75618 scsi_target_block +EXPORT_SYMBOL_GPL vmlinux 0x00e65be6 platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x00ebcb5d ata_id_string +EXPORT_SYMBOL_GPL vmlinux 0x00ef002e ata_std_prereset +EXPORT_SYMBOL_GPL vmlinux 0x01003a3b rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL vmlinux 0x01312905 usb_get_hcd +EXPORT_SYMBOL_GPL vmlinux 0x01a4ea6d unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x01dcfec2 hid_parse_report +EXPORT_SYMBOL_GPL vmlinux 0x01fd453e usbhid_lookup_quirk +EXPORT_SYMBOL_GPL vmlinux 0x020fda80 ata_ehi_clear_desc +EXPORT_SYMBOL_GPL vmlinux 0x027a878d simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0x0343bdf1 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x03582a5c ide_setting_mtx +EXPORT_SYMBOL_GPL vmlinux 0x03e3686c ata_timing_cycle2mode +EXPORT_SYMBOL_GPL vmlinux 0x043a4416 tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x04486e88 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x044b2f89 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x0474d800 tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0x04a9b286 nf_unregister_queue_handlers +EXPORT_SYMBOL_GPL vmlinux 0x0531dcb8 ata_dev_classify +EXPORT_SYMBOL_GPL vmlinux 0x054e550b kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x059091a9 rpc_call_null +EXPORT_SYMBOL_GPL vmlinux 0x05b7c5d2 inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x05f0952b platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x064db9a5 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x06a749c6 led_classdev_register +EXPORT_SYMBOL_GPL vmlinux 0x06d7fe22 nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL vmlinux 0x06ea8464 devres_find +EXPORT_SYMBOL_GPL vmlinux 0x06f2581d usb_deregister_device_driver +EXPORT_SYMBOL_GPL vmlinux 0x06fc3af1 d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x0745c37b hidinput_connect +EXPORT_SYMBOL_GPL vmlinux 0x0785c22f platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x079df025 sata_scr_write +EXPORT_SYMBOL_GPL vmlinux 0x07b52e38 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x07e4b4ea fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0x0905d2b3 inet_hash +EXPORT_SYMBOL_GPL vmlinux 0x091eb9b4 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x099deea5 usb_store_new_id +EXPORT_SYMBOL_GPL vmlinux 0x09e2b179 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0x0a594b67 driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x0abb8a7f input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x0aea07fd hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0x0aeeeca0 register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x0b60c263 map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x0bca7bc9 tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0x0bd31d4f __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0x0c17e274 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x0c20fe81 skb_morph +EXPORT_SYMBOL_GPL vmlinux 0x0c42a338 del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x0c585d10 rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0c71d997 unregister_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x0d47b89a devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0x0dff8d0b usb_bulk_msg +EXPORT_SYMBOL_GPL vmlinux 0x0e1cc1d8 generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0x0e2be8af exit_fs +EXPORT_SYMBOL_GPL vmlinux 0x0e5e1b26 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0x0e8f326a rtc_update_irq +EXPORT_SYMBOL_GPL vmlinux 0x0edee040 inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0x0efbf4cd ide_pci_set_master +EXPORT_SYMBOL_GPL vmlinux 0x0f192147 sata_link_resume +EXPORT_SYMBOL_GPL vmlinux 0x0f5ff299 register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x0f6430e2 usb_buffer_unmap_sg +EXPORT_SYMBOL_GPL vmlinux 0x0f7f491a uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0x0f9f62b0 xprt_release_xprt +EXPORT_SYMBOL_GPL vmlinux 0x103209eb ide_port_unregister_devices +EXPORT_SYMBOL_GPL vmlinux 0x10a8a7f3 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x10e5faf7 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x112bcc28 led_classdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1130861a inotify_destroy +EXPORT_SYMBOL_GPL vmlinux 0x1131f3a5 xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0x11dc22d2 sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x11ec537f platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0x11f994cb pciserial_init_ports +EXPORT_SYMBOL_GPL vmlinux 0x1251c27e hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x1251d30f call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x1279b754 ide_undecoded_slave +EXPORT_SYMBOL_GPL vmlinux 0x12aa2da2 __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x12b7cc82 inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0x1339e324 sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x1341f438 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0x1352e9e0 rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0x139f8473 ata_sff_hsm_move +EXPORT_SYMBOL_GPL vmlinux 0x14194df9 sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0x146b3e16 usb_hcd_link_urb_to_ep +EXPORT_SYMBOL_GPL vmlinux 0x14971bd3 devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x1544d0ce usb_get_status +EXPORT_SYMBOL_GPL vmlinux 0x1598dc9d unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x15b3e4d4 hid_output_report +EXPORT_SYMBOL_GPL vmlinux 0x16087b08 pci_update_slot_number +EXPORT_SYMBOL_GPL vmlinux 0x165bc7a3 rpc_malloc +EXPORT_SYMBOL_GPL vmlinux 0x16c863f7 platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0x16f76869 probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x17279023 get_mtd_device_nm +EXPORT_SYMBOL_GPL vmlinux 0x174ce867 __class_register +EXPORT_SYMBOL_GPL vmlinux 0x1750796f rtc_class_close +EXPORT_SYMBOL_GPL vmlinux 0x1820ac5e regulator_set_current_limit +EXPORT_SYMBOL_GPL vmlinux 0x18619969 ide_host_alloc +EXPORT_SYMBOL_GPL vmlinux 0x188b5744 simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0x18da3072 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x191fb096 srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x1957fdf6 class_destroy +EXPORT_SYMBOL_GPL vmlinux 0x196067fb mtd_table +EXPORT_SYMBOL_GPL vmlinux 0x197146bb ata_sas_port_start +EXPORT_SYMBOL_GPL vmlinux 0x199a2c1c proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0x19a304ba usb_disabled +EXPORT_SYMBOL_GPL vmlinux 0x19c8c646 put_driver +EXPORT_SYMBOL_GPL vmlinux 0x19cf65a5 fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0x1a309d8f sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0x1a314d7e ata_eh_qc_complete +EXPORT_SYMBOL_GPL vmlinux 0x1a618932 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL vmlinux 0x1abcd33b ata_do_eh +EXPORT_SYMBOL_GPL vmlinux 0x1ac855f6 inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0x1b51d324 do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0x1b86b563 ata_sff_pause +EXPORT_SYMBOL_GPL vmlinux 0x1b975656 xprt_release_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x1b9aca3f jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x1bf8cce6 pci_find_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x1c1447b2 do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x1c6f87bf ata_sff_qc_fill_rtf +EXPORT_SYMBOL_GPL vmlinux 0x1c82d112 class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1d86ba90 __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0x1d903e32 tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x1da3941a __ide_error +EXPORT_SYMBOL_GPL vmlinux 0x1dac36d4 ata_sas_port_stop +EXPORT_SYMBOL_GPL vmlinux 0x1de1662e register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0x1dfcd16d rtc_irq_set_state +EXPORT_SYMBOL_GPL vmlinux 0x1e0b68da device_move +EXPORT_SYMBOL_GPL vmlinux 0x1e7bbcb3 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x1ea03cae put_pid +EXPORT_SYMBOL_GPL vmlinux 0x1eb9516e round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x1efc1cdd sata_scr_valid +EXPORT_SYMBOL_GPL vmlinux 0x1f127608 ata_pci_sff_init_one +EXPORT_SYMBOL_GPL vmlinux 0x1f66cfa7 __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0x1fa8a93a usb_buffer_map_sg +EXPORT_SYMBOL_GPL vmlinux 0x1fc0875f rpc_bind_new_program +EXPORT_SYMBOL_GPL vmlinux 0x1fcece42 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x20577ea2 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x20583cd3 vlan_dev_vlan_id +EXPORT_SYMBOL_GPL vmlinux 0x20bc3470 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x21393646 ide_set_irq +EXPORT_SYMBOL_GPL vmlinux 0x2197b386 default_mtd_writev +EXPORT_SYMBOL_GPL vmlinux 0x21d4bad8 blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x21ea1c65 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0x22472bf4 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x22a21b84 inotify_inode_is_dead +EXPORT_SYMBOL_GPL vmlinux 0x22e2c20b atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x2345bca9 ata_eh_freeze_port +EXPORT_SYMBOL_GPL vmlinux 0x23679939 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x23869dc7 cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x23928601 sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0x23b13b57 ata_sff_prereset +EXPORT_SYMBOL_GPL vmlinux 0x23fc87d0 ide_timing_find_mode +EXPORT_SYMBOL_GPL vmlinux 0x2407e3a3 xprt_unregister_transport +EXPORT_SYMBOL_GPL vmlinux 0x243ee6f0 sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x2498b64e ata_pci_sff_activate_host +EXPORT_SYMBOL_GPL vmlinux 0x24be80ec platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0x24cda041 ide_vlb_clk +EXPORT_SYMBOL_GPL vmlinux 0x24eb7e32 leds_list +EXPORT_SYMBOL_GPL vmlinux 0x25433b44 ide_dma_host_set +EXPORT_SYMBOL_GPL vmlinux 0x254ee013 ata_sff_dev_select +EXPORT_SYMBOL_GPL vmlinux 0x255af719 regulator_get +EXPORT_SYMBOL_GPL vmlinux 0x25694a8a usb_reset_device +EXPORT_SYMBOL_GPL vmlinux 0x264ea108 destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x265492a5 device_create +EXPORT_SYMBOL_GPL vmlinux 0x26a1f12e usb_create_hcd +EXPORT_SYMBOL_GPL vmlinux 0x26c90ea4 scsi_eh_get_sense +EXPORT_SYMBOL_GPL vmlinux 0x26f599c9 sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0x26fb8dd7 crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0x2754fdbc kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x27bba5ce usb_altnum_to_altsetting +EXPORT_SYMBOL_GPL vmlinux 0x27c17183 sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x27d753a0 driver_register +EXPORT_SYMBOL_GPL vmlinux 0x2888858e svc_xprt_enqueue +EXPORT_SYMBOL_GPL vmlinux 0x28b2cc80 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x28b4d289 inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0x28d664ff __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x28e23139 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x29461a1e pci_find_ext_capability +EXPORT_SYMBOL_GPL vmlinux 0x2978aa55 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x29faf4af driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x29fbfad0 xprt_release_rqst_cong +EXPORT_SYMBOL_GPL vmlinux 0x2a13aa9d dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x2aa17774 rpc_free_iostats +EXPORT_SYMBOL_GPL vmlinux 0x2ac20416 __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x2b4e7ec9 class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x2b607170 ktime_sub_ns +EXPORT_SYMBOL_GPL vmlinux 0x2b9f8e23 nf_net_ipv4_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x2bb5bc9f __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x2bcf5477 ata_bmdma_mode_filter +EXPORT_SYMBOL_GPL vmlinux 0x2bd4c12f ide_port_scan +EXPORT_SYMBOL_GPL vmlinux 0x2c16ed76 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x2c9c3f37 mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0x2ca064d6 inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0x2cd3a4fb klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0x2d19c4d5 regulator_enable +EXPORT_SYMBOL_GPL vmlinux 0x2d205c7d queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x2d6d1003 uhci_check_and_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x2d9656d8 transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x2dd14d43 ata_sff_dev_classify +EXPORT_SYMBOL_GPL vmlinux 0x2e3d08b9 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x2e9487e6 deregister_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x2f1f815d inotify_rm_watch +EXPORT_SYMBOL_GPL vmlinux 0x2f2aba42 usb_get_descriptor +EXPORT_SYMBOL_GPL vmlinux 0x2fbbf868 xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL vmlinux 0x304ddee6 xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x308bcc35 ide_read_sff_dma_status +EXPORT_SYMBOL_GPL vmlinux 0x30c6a121 tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0x31020054 driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0x311ae936 ata_sff_irq_on +EXPORT_SYMBOL_GPL vmlinux 0x31a89d59 rpc_debug +EXPORT_SYMBOL_GPL vmlinux 0x31bfc3b5 xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0x3239dfa4 rpc_wake_up_status +EXPORT_SYMBOL_GPL vmlinux 0x323d37a6 input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x32799a31 pci_test_config_bits +EXPORT_SYMBOL_GPL vmlinux 0x32dffb11 fib_rules_cleanup_ops +EXPORT_SYMBOL_GPL vmlinux 0x3317c67a get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0x3328c0f4 __ide_pci_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x333fc673 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0x3356218a regulator_bulk_enable +EXPORT_SYMBOL_GPL vmlinux 0x33ff249b hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x35135bad usb_wait_anchor_empty_timeout +EXPORT_SYMBOL_GPL vmlinux 0x353db172 ide_input_data +EXPORT_SYMBOL_GPL vmlinux 0x356907a5 inet_diag_register +EXPORT_SYMBOL_GPL vmlinux 0x35cf63ff rpc_init_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0x35d8c94a sdev_evt_alloc +EXPORT_SYMBOL_GPL vmlinux 0x35e49f92 cfi_cmdset_0200 +EXPORT_SYMBOL_GPL vmlinux 0x35f82d2c platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x360a4b0f ata_do_dev_read_id +EXPORT_SYMBOL_GPL vmlinux 0x361e2bcc save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x362e23ec call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x36385770 usb_ep0_reinit +EXPORT_SYMBOL_GPL vmlinux 0x366aef0a rtc_read_time +EXPORT_SYMBOL_GPL vmlinux 0x3695951d device_attach +EXPORT_SYMBOL_GPL vmlinux 0x36cb60e4 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0x36d74f73 tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0x36e9575c ide_host_remove +EXPORT_SYMBOL_GPL vmlinux 0x3747fe2f ide_in_drive_list +EXPORT_SYMBOL_GPL vmlinux 0x3777e2f3 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0x37a52bbf platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0x3807576e bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x3841542b led_trigger_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x389652c1 hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0x38aaf2e1 driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0x38e455c4 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x39109473 inotify_inode_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x3911e102 generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0x3933e095 rpcauth_unregister +EXPORT_SYMBOL_GPL vmlinux 0x393bd2c9 simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x395e7837 rpcauth_create +EXPORT_SYMBOL_GPL vmlinux 0x3972fb71 skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0x39819646 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x398e0efa xprt_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0x3a432bd1 pciserial_remove_ports +EXPORT_SYMBOL_GPL vmlinux 0x3a49f930 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x3a7f8b86 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x3ac1a298 scsi_target_unblock +EXPORT_SYMBOL_GPL vmlinux 0x3af5146c usb_get_intf +EXPORT_SYMBOL_GPL vmlinux 0x3b12e81c crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0x3b77b751 rpc_restart_call +EXPORT_SYMBOL_GPL vmlinux 0x3b8cae1f get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0x3bc33f65 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x3bd3266b proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0x3bd51c5a inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0x3be60fa0 ide_get_best_pio_mode +EXPORT_SYMBOL_GPL vmlinux 0x3be7af02 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x3be89d3c usb_register_notify +EXPORT_SYMBOL_GPL vmlinux 0x3c80eb1f rpcauth_init_cred +EXPORT_SYMBOL_GPL vmlinux 0x3cd06035 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x3ce1c1f2 scsi_internal_device_unblock +EXPORT_SYMBOL_GPL vmlinux 0x3d43e2a4 rpc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0x3d7d8c0e ide_dma_setup +EXPORT_SYMBOL_GPL vmlinux 0x3d80a960 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x3d9468f7 device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0x3de00394 rpc_force_rebind +EXPORT_SYMBOL_GPL vmlinux 0x3e0a6597 dev_attr_sw_activity +EXPORT_SYMBOL_GPL vmlinux 0x3e1104a9 ata_port_schedule_eh +EXPORT_SYMBOL_GPL vmlinux 0x3e8da574 xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL vmlinux 0x3ef07a9b usb_unlink_anchored_urbs +EXPORT_SYMBOL_GPL vmlinux 0x3ef54874 ide_get_lba_addr +EXPORT_SYMBOL_GPL vmlinux 0x3f01570a probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0x3f0da9e1 led_classdev_resume +EXPORT_SYMBOL_GPL vmlinux 0x3fc84a9e bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0x3fd57834 fib_rules_lookup +EXPORT_SYMBOL_GPL vmlinux 0x3fe6b5a2 ata_bmdma_setup +EXPORT_SYMBOL_GPL vmlinux 0x403e4344 rpcauth_init_credcache +EXPORT_SYMBOL_GPL vmlinux 0x4056fd55 svc_xprt_init +EXPORT_SYMBOL_GPL vmlinux 0x40661822 ata_sff_check_status +EXPORT_SYMBOL_GPL vmlinux 0x40965601 led_trigger_show +EXPORT_SYMBOL_GPL vmlinux 0x40af0dec ata_xfer_mode2mask +EXPORT_SYMBOL_GPL vmlinux 0x40c83e50 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x40fa0ea9 register_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x4118db11 rtc_class_open +EXPORT_SYMBOL_GPL vmlinux 0x415c4df9 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0x415d2b04 sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x41b516ff ide_pad_transfer +EXPORT_SYMBOL_GPL vmlinux 0x41ee4ea7 ata_sff_wait_after_reset +EXPORT_SYMBOL_GPL vmlinux 0x41f3cc90 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x41f4df1b ide_read_altstatus +EXPORT_SYMBOL_GPL vmlinux 0x423a5e34 fib_rules_unregister +EXPORT_SYMBOL_GPL vmlinux 0x423e7032 xprt_reserve_xprt +EXPORT_SYMBOL_GPL vmlinux 0x4283b58b kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0x42a521a0 pci_find_next_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x42b6c668 ata_bmdma_start +EXPORT_SYMBOL_GPL vmlinux 0x42ebac1f ata_bmdma_stop +EXPORT_SYMBOL_GPL vmlinux 0x437ba7d2 copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0x439ca6b7 add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x43f56e82 ata_xfer_mode2shift +EXPORT_SYMBOL_GPL vmlinux 0x4455aee6 free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x447bc108 zap_vma_ptes +EXPORT_SYMBOL_GPL vmlinux 0x44ae3df7 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0x45657b78 rpc_wake_up +EXPORT_SYMBOL_GPL vmlinux 0x457594fa crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x461ea45b ata_link_abort +EXPORT_SYMBOL_GPL vmlinux 0x46960b31 ata_do_set_mode +EXPORT_SYMBOL_GPL vmlinux 0x46b2a30d proc_ide_read_capacity +EXPORT_SYMBOL_GPL vmlinux 0x46c72860 usb_bus_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x47589094 __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0x47601acb scsi_schedule_eh +EXPORT_SYMBOL_GPL vmlinux 0x4851109d queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x4859ab3a device_del +EXPORT_SYMBOL_GPL vmlinux 0x486c2721 sdev_evt_send_simple +EXPORT_SYMBOL_GPL vmlinux 0x4873cd7e mmput +EXPORT_SYMBOL_GPL vmlinux 0x48d70761 devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x491377a3 nf_unregister_afinfo +EXPORT_SYMBOL_GPL vmlinux 0x4926f8f3 usb_hcd_check_unlink_urb +EXPORT_SYMBOL_GPL vmlinux 0x49318d9b unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x49538616 scsi_eh_ready_devs +EXPORT_SYMBOL_GPL vmlinux 0x4a172394 ata_std_error_handler +EXPORT_SYMBOL_GPL vmlinux 0x4a7277ba pci_scan_child_bus +EXPORT_SYMBOL_GPL vmlinux 0x4a7c7866 bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0x4b2296ed led_trigger_event +EXPORT_SYMBOL_GPL vmlinux 0x4bbbd2ed rtc_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x4c2cab98 sata_scr_read +EXPORT_SYMBOL_GPL vmlinux 0x4c3abf91 ide_tf_load +EXPORT_SYMBOL_GPL vmlinux 0x4c759827 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x4d695afd usb_hc_died +EXPORT_SYMBOL_GPL vmlinux 0x4dad959e posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0x4dcdcdeb ata_eh_thaw_port +EXPORT_SYMBOL_GPL vmlinux 0x4def7296 svc_print_addr +EXPORT_SYMBOL_GPL vmlinux 0x4e1a8b99 tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x4e38b089 ide_host_alloc_all +EXPORT_SYMBOL_GPL vmlinux 0x4e6c0c4b device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x4ead9688 regulator_set_optimum_mode +EXPORT_SYMBOL_GPL vmlinux 0x4ee7af79 register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x4f2b4ce4 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x4f802798 regulator_bulk_get +EXPORT_SYMBOL_GPL vmlinux 0x4fd0181d seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0x4fdc945d sata_deb_timing_normal +EXPORT_SYMBOL_GPL vmlinux 0x502a5e28 mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0x506e1ca8 rtc_irq_set_freq +EXPORT_SYMBOL_GPL vmlinux 0x509ceb8f vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0x50b39df4 ide_init_sg_cmd +EXPORT_SYMBOL_GPL vmlinux 0x50b67174 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x50c19ec3 device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x50e7193a __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x515a86c6 register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x516dbe50 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x518fb318 tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x51dd6488 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x52d111ea pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x52f24bf9 usb_register_dev +EXPORT_SYMBOL_GPL vmlinux 0x53445f68 nlm_debug +EXPORT_SYMBOL_GPL vmlinux 0x534fc5a8 rpc_alloc_iostats +EXPORT_SYMBOL_GPL vmlinux 0x535b5097 ide_pci_init_two +EXPORT_SYMBOL_GPL vmlinux 0x5376214c ata_sff_wait_ready +EXPORT_SYMBOL_GPL vmlinux 0x53986488 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x53bcac24 device_register +EXPORT_SYMBOL_GPL vmlinux 0x53dbaa6b usb_put_intf +EXPORT_SYMBOL_GPL vmlinux 0x54011a7a inotify_init_watch +EXPORT_SYMBOL_GPL vmlinux 0x5456259f sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x54609723 ide_pci_remove +EXPORT_SYMBOL_GPL vmlinux 0x54994f4a blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0x55407ef5 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5542b913 cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0x55546df5 ide_read_error +EXPORT_SYMBOL_GPL vmlinux 0x55b1e7e1 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x55c46fbe rpc_wake_up_next +EXPORT_SYMBOL_GPL vmlinux 0x563e6588 usb_sg_wait +EXPORT_SYMBOL_GPL vmlinux 0x5640fa34 ata_host_register +EXPORT_SYMBOL_GPL vmlinux 0x5641485b tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x56716d9b ata_std_bios_param +EXPORT_SYMBOL_GPL vmlinux 0x5678c3f1 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL vmlinux 0x56b0bd44 regulator_get_supply +EXPORT_SYMBOL_GPL vmlinux 0x56d42418 thread_notify_head +EXPORT_SYMBOL_GPL vmlinux 0x56d56c3a ata_sas_port_destroy +EXPORT_SYMBOL_GPL vmlinux 0x576bdc1b rtc_irq_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5788ba4c ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0x578cad3a rpc_print_iostats +EXPORT_SYMBOL_GPL vmlinux 0x579e0bf5 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x57bf6a93 bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x585ac2fb ata_host_alloc +EXPORT_SYMBOL_GPL vmlinux 0x58e6ae58 i2c_new_device +EXPORT_SYMBOL_GPL vmlinux 0x5905ec47 ata_pci_sff_init_host +EXPORT_SYMBOL_GPL vmlinux 0x590a21f5 nlmclnt_proc +EXPORT_SYMBOL_GPL vmlinux 0x593c0ea8 bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x5995c96c get_driver +EXPORT_SYMBOL_GPL vmlinux 0x59b178f4 ata_pci_bmdma_clear_simplex +EXPORT_SYMBOL_GPL vmlinux 0x59ca3224 inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x59e74b19 __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x5a9d98d6 regulator_set_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x5b3af9cb mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0x5b664584 ata_sas_port_alloc +EXPORT_SYMBOL_GPL vmlinux 0x5b7dae12 ehci_cf_port_reset_rwsem +EXPORT_SYMBOL_GPL vmlinux 0x5bcd60a7 platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0x5bd26000 rpc_proc_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5c41ec99 __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0x5c58fa9e regulator_get_mode +EXPORT_SYMBOL_GPL vmlinux 0x5cb4a5e2 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x5d3f6fad ata_sff_thaw +EXPORT_SYMBOL_GPL vmlinux 0x5d730e7b raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5d82730d register_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x5db8841d nlmclnt_init +EXPORT_SYMBOL_GPL vmlinux 0x5dd67618 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5eed5d43 cfi_cmdset_0003 +EXPORT_SYMBOL_GPL vmlinux 0x5eeefeb9 rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0x5f354889 sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5f82e27c sff_dma_ops +EXPORT_SYMBOL_GPL vmlinux 0x6012595d register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x60129c72 register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0x6091797f synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x60a13e90 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x60a31882 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0x60ad9ade ide_setup_pci_noise +EXPORT_SYMBOL_GPL vmlinux 0x60d3fd52 ide_execute_pkt_cmd +EXPORT_SYMBOL_GPL vmlinux 0x60f6bb05 ide_host_add +EXPORT_SYMBOL_GPL vmlinux 0x61352cb9 rtc_set_mmss +EXPORT_SYMBOL_GPL vmlinux 0x6139c1b0 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0x6143dbb9 blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x61486f6d ide_end_dequeued_request +EXPORT_SYMBOL_GPL vmlinux 0x616f272e ata_port_abort +EXPORT_SYMBOL_GPL vmlinux 0x61e6e779 sata_set_spd +EXPORT_SYMBOL_GPL vmlinux 0x622b3e2c srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0x623f4a64 xprt_lookup_rqst +EXPORT_SYMBOL_GPL vmlinux 0x623fbf84 xdr_skb_read_bits +EXPORT_SYMBOL_GPL vmlinux 0x625d0571 ide_map_sg +EXPORT_SYMBOL_GPL vmlinux 0x62a93185 raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0x62aea728 regulator_bulk_disable +EXPORT_SYMBOL_GPL vmlinux 0x62bb4b56 scsi_execute_async +EXPORT_SYMBOL_GPL vmlinux 0x62d78c07 ide_pio_cycle_time +EXPORT_SYMBOL_GPL vmlinux 0x62e9f785 ata_scsi_queuecmd +EXPORT_SYMBOL_GPL vmlinux 0x62fb1cd8 ata_link_online +EXPORT_SYMBOL_GPL vmlinux 0x634759bf ide_build_dmatable +EXPORT_SYMBOL_GPL vmlinux 0x63b491ff svc_xprt_put +EXPORT_SYMBOL_GPL vmlinux 0x63b7a6a4 ata_port_desc +EXPORT_SYMBOL_GPL vmlinux 0x63bee838 ata_sff_postreset +EXPORT_SYMBOL_GPL vmlinux 0x642a386d ide_host_register +EXPORT_SYMBOL_GPL vmlinux 0x649d81e4 rpc_peeraddr +EXPORT_SYMBOL_GPL vmlinux 0x64af2d6b regulator_register +EXPORT_SYMBOL_GPL vmlinux 0x6508ed9c usb_unanchor_urb +EXPORT_SYMBOL_GPL vmlinux 0x651f5472 ata_port_start +EXPORT_SYMBOL_GPL vmlinux 0x65774397 __class_create +EXPORT_SYMBOL_GPL vmlinux 0x6585509c regulator_disable +EXPORT_SYMBOL_GPL vmlinux 0x65ccb6f0 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x65f43343 driver_find +EXPORT_SYMBOL_GPL vmlinux 0x65ff44c5 svc_create_xprt +EXPORT_SYMBOL_GPL vmlinux 0x660cbc06 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0x661601de sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x666fdfd0 ide_legacy_device_add +EXPORT_SYMBOL_GPL vmlinux 0x66b2a859 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x66e7e338 device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x66ee9657 do_rw_taskfile +EXPORT_SYMBOL_GPL vmlinux 0x6759a5cb devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x677cfd53 usb_driver_set_configuration +EXPORT_SYMBOL_GPL vmlinux 0x678799d4 usb_alloc_urb +EXPORT_SYMBOL_GPL vmlinux 0x67b4a020 led_trigger_unregister_simple +EXPORT_SYMBOL_GPL vmlinux 0x67c8b1f2 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0x67cf8ab6 skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0x686c703f xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x6889db6c kill_mtd_super +EXPORT_SYMBOL_GPL vmlinux 0x68917a4a pci_slots_kset +EXPORT_SYMBOL_GPL vmlinux 0x68a1c650 usb_buffer_free +EXPORT_SYMBOL_GPL vmlinux 0x699733dc xprt_adjust_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x69e9a2cb ata_scsi_slave_config +EXPORT_SYMBOL_GPL vmlinux 0x6a22797f device_rename +EXPORT_SYMBOL_GPL vmlinux 0x6ad404b5 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0x6b00ccff elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x6b00e100 pci_bus_add_device +EXPORT_SYMBOL_GPL vmlinux 0x6b135033 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0x6b3da76d regulator_set_device_supply +EXPORT_SYMBOL_GPL vmlinux 0x6b78e970 regulator_is_enabled +EXPORT_SYMBOL_GPL vmlinux 0x6bee7de2 crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0x6bf43f05 inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0x6c037cf0 ata_dummy_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x6c340230 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x6c49c4f2 clockevents_notify +EXPORT_SYMBOL_GPL vmlinux 0x6c5304c5 rpcb_getport_sync +EXPORT_SYMBOL_GPL vmlinux 0x6ca3e7e3 __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0x6d631b9d led_trigger_unregister +EXPORT_SYMBOL_GPL vmlinux 0x6d632f02 class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x6e1748fd blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0x6e39528a usb_find_interface +EXPORT_SYMBOL_GPL vmlinux 0x6e974701 proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0x6ec40bfb page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x6ef8ba88 inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x6f0b24ed inotify_find_watch +EXPORT_SYMBOL_GPL vmlinux 0x6f5819be ata_host_detach +EXPORT_SYMBOL_GPL vmlinux 0x6f8622ee rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0x6fd7c733 ata_cable_80wire +EXPORT_SYMBOL_GPL vmlinux 0x7011c8da rpc_setbufsize +EXPORT_SYMBOL_GPL vmlinux 0x70776716 vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0x707ff1bb ata_xfer_mask2mode +EXPORT_SYMBOL_GPL vmlinux 0x70db021d tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0x71196147 tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0x71215c7f inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0x714701a1 sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x71aff191 netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0x71c5cd4a rpcauth_register +EXPORT_SYMBOL_GPL vmlinux 0x71f9246a leds_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x7278d328 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x7283882e xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL vmlinux 0x72c5fbce ata_sff_tf_read +EXPORT_SYMBOL_GPL vmlinux 0x730f34d8 device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x733e1d25 ide_dma_test_irq +EXPORT_SYMBOL_GPL vmlinux 0x73a48b4a ata_sff_std_ports +EXPORT_SYMBOL_GPL vmlinux 0x73b1f76d do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x73ff88c2 regulator_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x740001bc rpc_call_async +EXPORT_SYMBOL_GPL vmlinux 0x743a165e ata_pack_xfermask +EXPORT_SYMBOL_GPL vmlinux 0x7486289a init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x74ebe363 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x7623c2c8 platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x7624e517 hidinput_find_field +EXPORT_SYMBOL_GPL vmlinux 0x7648d3a9 ide_tf_read +EXPORT_SYMBOL_GPL vmlinux 0x76826b28 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x779abb7c __ata_ehi_push_desc +EXPORT_SYMBOL_GPL vmlinux 0x77aa8ae6 elv_register +EXPORT_SYMBOL_GPL vmlinux 0x77e1cbff rtc_set_time +EXPORT_SYMBOL_GPL vmlinux 0x784493cf usb_lock_device_for_reset +EXPORT_SYMBOL_GPL vmlinux 0x78af7c8f init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x78d5843b usb_register_device_driver +EXPORT_SYMBOL_GPL vmlinux 0x78e647ae scsi_queue_work +EXPORT_SYMBOL_GPL vmlinux 0x79443881 usb_set_interface +EXPORT_SYMBOL_GPL vmlinux 0x7948d109 srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0x79b9aeed ide_build_sglist +EXPORT_SYMBOL_GPL vmlinux 0x79d09c6d input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0x7a698ed2 ata_bmdma_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x7aa5cc6d platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x7ad2bf5a usb_sg_init +EXPORT_SYMBOL_GPL vmlinux 0x7b4ec6a0 ide_pktcmd_tf_load +EXPORT_SYMBOL_GPL vmlinux 0x7b65e0f1 ata_dev_pair +EXPORT_SYMBOL_GPL vmlinux 0x7c769263 ata_sff_busy_sleep +EXPORT_SYMBOL_GPL vmlinux 0x7c7c76a9 ide_pci_setup_ports +EXPORT_SYMBOL_GPL vmlinux 0x7d2f01d2 rpc_lookup_cred +EXPORT_SYMBOL_GPL vmlinux 0x7dc4ab36 rpc_killall_tasks +EXPORT_SYMBOL_GPL vmlinux 0x7de53067 rpc_init_rtt +EXPORT_SYMBOL_GPL vmlinux 0x7e110847 usb_get_urb +EXPORT_SYMBOL_GPL vmlinux 0x7e275ea8 scsi_complete_async_scans +EXPORT_SYMBOL_GPL vmlinux 0x7e2d29ec ide_pci_clk +EXPORT_SYMBOL_GPL vmlinux 0x7e389d40 pci_intx +EXPORT_SYMBOL_GPL vmlinux 0x7e64181d usb_calc_bus_time +EXPORT_SYMBOL_GPL vmlinux 0x7e6e31dc ata_port_probe +EXPORT_SYMBOL_GPL vmlinux 0x7eb25b75 devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x7f18e306 svc_addsock +EXPORT_SYMBOL_GPL vmlinux 0x7f1fef30 sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0x7f31fa36 register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x7f6df687 svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL vmlinux 0x7f9470c5 ata_sas_queuecmd +EXPORT_SYMBOL_GPL vmlinux 0x7fa25179 device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x7ff10ccf raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x80741e92 device_add +EXPORT_SYMBOL_GPL vmlinux 0x8095ef1b unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x80a7b35b ata_cable_sata +EXPORT_SYMBOL_GPL vmlinux 0x80be42f1 ata_base_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x819714c9 usb_hcd_platform_shutdown +EXPORT_SYMBOL_GPL vmlinux 0x81ac87e0 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0x81c6a017 regulator_set_machine_constraints +EXPORT_SYMBOL_GPL vmlinux 0x820e4ea0 ide_no_data_taskfile +EXPORT_SYMBOL_GPL vmlinux 0x826360fd do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x82d79b51 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x8300d215 usb_put_hcd +EXPORT_SYMBOL_GPL vmlinux 0x8360e0bc pci_stop_bus_device +EXPORT_SYMBOL_GPL vmlinux 0x836d2cc9 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x83932c8e get_device +EXPORT_SYMBOL_GPL vmlinux 0x8412d74f __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0x8412e3c5 srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x84a1bc7c klist_del +EXPORT_SYMBOL_GPL vmlinux 0x84bc26e5 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x84f758bd sata_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x84f79056 tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0x85413d16 regulator_put +EXPORT_SYMBOL_GPL vmlinux 0x8568e14b usb_driver_release_interface +EXPORT_SYMBOL_GPL vmlinux 0x85c10896 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x85e5a3db ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x8644bbac vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0x8653c00c attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0x86686cbe usb_interrupt_msg +EXPORT_SYMBOL_GPL vmlinux 0x868784cb __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x87421699 ide_dma_intr +EXPORT_SYMBOL_GPL vmlinux 0x8747ff63 i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL vmlinux 0x87754115 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x8789a34c inet_diag_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8836d16a usb_hub_tt_clear_buffer +EXPORT_SYMBOL_GPL vmlinux 0x885142a6 nf_net_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x885d48da rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0x88fb2a79 tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x89578b6b klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x8959be5e pci_block_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x896855b5 skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x8999d999 ata_sff_freeze +EXPORT_SYMBOL_GPL vmlinux 0x89b9996d ide_unregister_region +EXPORT_SYMBOL_GPL vmlinux 0x89c4e8be ata_cable_unknown +EXPORT_SYMBOL_GPL vmlinux 0x89cae7a8 usb_unlink_urb +EXPORT_SYMBOL_GPL vmlinux 0x8abed13d xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x8ad7cc6f unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x8b752ac1 ata_tf_to_fis +EXPORT_SYMBOL_GPL vmlinux 0x8c2553b3 uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0x8c3b018a put_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x8c458859 sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0x8d11dc09 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x8d16080c ide_read_status +EXPORT_SYMBOL_GPL vmlinux 0x8d1a3c7d usb_ifnum_to_if +EXPORT_SYMBOL_GPL vmlinux 0x8d4f9ba8 net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x8d8139e8 usb_hcd_unlink_urb_from_ep +EXPORT_SYMBOL_GPL vmlinux 0x8e6a62b6 ata_sff_data_xfer +EXPORT_SYMBOL_GPL vmlinux 0x8ea26469 xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL vmlinux 0x8ebe9a82 usb_clear_halt +EXPORT_SYMBOL_GPL vmlinux 0x8eefc2e6 skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0x8f6cee77 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x8f77e68a ata_pio_need_iordy +EXPORT_SYMBOL_GPL vmlinux 0x8f7b74e0 sata_async_notification +EXPORT_SYMBOL_GPL vmlinux 0x8f88618f uhci_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x8fbf4bf8 platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0x9058c644 ata_qc_complete_multiple +EXPORT_SYMBOL_GPL vmlinux 0x90a0f737 usb_hcd_poll_rh_status +EXPORT_SYMBOL_GPL vmlinux 0x90a1004a crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x91039769 ata_ehi_push_desc +EXPORT_SYMBOL_GPL vmlinux 0x91115867 usb_hcd_pci_shutdown +EXPORT_SYMBOL_GPL vmlinux 0x915acc1f klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x9181645f sata_std_hardreset +EXPORT_SYMBOL_GPL vmlinux 0x92445aee hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x929199b3 xprt_disconnect_done +EXPORT_SYMBOL_GPL vmlinux 0x92a4317f usb_driver_claim_interface +EXPORT_SYMBOL_GPL vmlinux 0x92f7bc6a rpc_call_start +EXPORT_SYMBOL_GPL vmlinux 0x933b23d2 input_class +EXPORT_SYMBOL_GPL vmlinux 0x933d79df __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x934c75df kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0x93d2422d snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x9415fdeb ata_sff_dma_pause +EXPORT_SYMBOL_GPL vmlinux 0x945711d5 ata_sff_data_xfer_noirq +EXPORT_SYMBOL_GPL vmlinux 0x94a68723 ata_scsi_slave_destroy +EXPORT_SYMBOL_GPL vmlinux 0x94dab835 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0x94dc62d2 ata_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x952664c5 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x953d613b crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x954f9cfa bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0x956c0fec blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0x95d12fa2 vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x96154266 ata_cable_ignore +EXPORT_SYMBOL_GPL vmlinux 0x96371026 svc_find_xprt +EXPORT_SYMBOL_GPL vmlinux 0x9670fa56 inotify_add_watch +EXPORT_SYMBOL_GPL vmlinux 0x96cbcf31 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x9784e6b4 register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x97eeb2f6 register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x98196f5b blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x9835b4a0 vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0x98928893 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0x98a0e956 pci_find_next_capability +EXPORT_SYMBOL_GPL vmlinux 0x98a334ca dev_attr_em_message +EXPORT_SYMBOL_GPL vmlinux 0x98ce3566 svc_unreg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0x98ea01cc deregister_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0x991779f5 ata_bmdma_status +EXPORT_SYMBOL_GPL vmlinux 0x9924c496 __usb_get_extra_descriptor +EXPORT_SYMBOL_GPL vmlinux 0x993f5d74 ata_noop_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0x99b82416 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0x99d8574a ide_read_bcount_and_ireason +EXPORT_SYMBOL_GPL vmlinux 0x99f9c8a5 tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0x9a398f5c xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x9a3a3efb ata_wait_after_reset +EXPORT_SYMBOL_GPL vmlinux 0x9aa25095 sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0x9aa6f550 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x9b91960d rtc_read_alarm +EXPORT_SYMBOL_GPL vmlinux 0x9b9fb999 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x9bfef3d0 platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0x9c61f153 ide_register_region +EXPORT_SYMBOL_GPL vmlinux 0x9c8ee173 ata_scsi_simulate +EXPORT_SYMBOL_GPL vmlinux 0x9caa6c84 tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x9cb8037b xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x9cc47378 usb_add_hcd +EXPORT_SYMBOL_GPL vmlinux 0x9d05ffbd crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0x9d888904 pci_set_pcie_reset_state +EXPORT_SYMBOL_GPL vmlinux 0x9d97f84c regulator_get_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x9e31615e platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x9e3ba753 bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x9e711ad2 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x9e81af83 ata_sas_slave_configure +EXPORT_SYMBOL_GPL vmlinux 0x9ea2eecb klist_init +EXPORT_SYMBOL_GPL vmlinux 0x9f32d9ad sata_link_debounce +EXPORT_SYMBOL_GPL vmlinux 0x9f36ffd1 fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0x9fa5808a ata_cable_40wire +EXPORT_SYMBOL_GPL vmlinux 0x9fce80db fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x9ff4ffc9 dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0xa0255440 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0xa02b20f3 pci_unblock_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0xa0441f0a del_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0xa0a3d6a7 unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0xa12991d9 blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0xa130a0b5 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0xa1644f6b mtd_erase_callback +EXPORT_SYMBOL_GPL vmlinux 0xa170f596 hidinput_report_event +EXPORT_SYMBOL_GPL vmlinux 0xa1a07bd3 ide_dma_exec_cmd +EXPORT_SYMBOL_GPL vmlinux 0xa1e02dfb queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0xa214dc52 tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0xa2aa1a94 bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0xa3020f05 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0xa31c9c79 rtc_set_alarm +EXPORT_SYMBOL_GPL vmlinux 0xa357d56e ktime_get +EXPORT_SYMBOL_GPL vmlinux 0xa3611194 svc_close_xprt +EXPORT_SYMBOL_GPL vmlinux 0xa3c48e3c default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0xa3e837a8 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0xa45253ad tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0xa4d1e73e ata_sff_error_handler +EXPORT_SYMBOL_GPL vmlinux 0xa4f09479 arm_pm_restart +EXPORT_SYMBOL_GPL vmlinux 0xa5bf5c3e pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0xa5c36cec inotify_unmount_inodes +EXPORT_SYMBOL_GPL vmlinux 0xa66024bf hid_set_field +EXPORT_SYMBOL_GPL vmlinux 0xa6714829 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0xa6919031 rpc_shutdown_client +EXPORT_SYMBOL_GPL vmlinux 0xa6923523 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0xa75f49f7 vlan_dev_real_dev +EXPORT_SYMBOL_GPL vmlinux 0xa7ede859 sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0xa8186b79 sata_link_hardreset +EXPORT_SYMBOL_GPL vmlinux 0xa81aef4d sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xa893d110 rtc_irq_register +EXPORT_SYMBOL_GPL vmlinux 0xa894148a rpc_call_sync +EXPORT_SYMBOL_GPL vmlinux 0xa8dc375a devres_get +EXPORT_SYMBOL_GPL vmlinux 0xa9c530b8 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xa9d096ce svc_xprt_received +EXPORT_SYMBOL_GPL vmlinux 0xa9e16265 hidinput_disconnect +EXPORT_SYMBOL_GPL vmlinux 0xaa2a72bf __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0xaa46f6d2 vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0xaa83aa43 ide_host_free +EXPORT_SYMBOL_GPL vmlinux 0xaa8c4696 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0xaaddf7d8 tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0xab189fc8 ide_device_put +EXPORT_SYMBOL_GPL vmlinux 0xab363ac2 bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0xab725041 regulator_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0xabc00cdf usb_deregister_dev +EXPORT_SYMBOL_GPL vmlinux 0xabf9cee6 ide_device_get +EXPORT_SYMBOL_GPL vmlinux 0xac4d8dea devres_add +EXPORT_SYMBOL_GPL vmlinux 0xacd47106 ata_qc_complete +EXPORT_SYMBOL_GPL vmlinux 0xace16d4d regulator_set_voltage +EXPORT_SYMBOL_GPL vmlinux 0xace5c0fc usb_bus_list +EXPORT_SYMBOL_GPL vmlinux 0xad8f4038 put_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0xadddde57 kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0xae0c87ee pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0xae58ff7f ata_sff_qc_issue +EXPORT_SYMBOL_GPL vmlinux 0xaee6bd6d ide_destroy_dmatable +EXPORT_SYMBOL_GPL vmlinux 0xaf5bf6ef nfs_debug +EXPORT_SYMBOL_GPL vmlinux 0xafac94a0 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0xb0648499 sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0xb06b648a usb_match_one_id +EXPORT_SYMBOL_GPL vmlinux 0xb0999489 rpc_put_task +EXPORT_SYMBOL_GPL vmlinux 0xb09bdae6 devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0xb0b4ef44 __scsi_get_command +EXPORT_SYMBOL_GPL vmlinux 0xb0ccbe9d rpc_delay +EXPORT_SYMBOL_GPL vmlinux 0xb170e5bc __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0xb1acbcce rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0xb1c519a1 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0xb1d20c39 inotify_dentry_parent_queue_event +EXPORT_SYMBOL_GPL vmlinux 0xb2a716f0 ata_port_pbar_desc +EXPORT_SYMBOL_GPL vmlinux 0xb2b53105 put_device +EXPORT_SYMBOL_GPL vmlinux 0xb39ae7cb register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0xb3b621b4 ata_host_start +EXPORT_SYMBOL_GPL vmlinux 0xb3dc6ee3 fib_rules_register +EXPORT_SYMBOL_GPL vmlinux 0xb3ed25b8 usb_sg_cancel +EXPORT_SYMBOL_GPL vmlinux 0xb43122b1 usb_match_id +EXPORT_SYMBOL_GPL vmlinux 0xb449ed11 mtd_table_mutex +EXPORT_SYMBOL_GPL vmlinux 0xb44e5d8f firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0xb45cab98 nlmclnt_done +EXPORT_SYMBOL_GPL vmlinux 0xb4a4b9fb blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0xb4b83c95 apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0xb4d64e3c klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0xb4ee262c usb_hcd_giveback_urb +EXPORT_SYMBOL_GPL vmlinux 0xb52b8c0c kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0xb55725ac parse_mtd_partitions +EXPORT_SYMBOL_GPL vmlinux 0xb56532ff blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0xb5d73719 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0xb634e6c4 bus_register +EXPORT_SYMBOL_GPL vmlinux 0xb63f9ef5 ata_sff_irq_clear +EXPORT_SYMBOL_GPL vmlinux 0xb6aeb661 ata_id_c_string +EXPORT_SYMBOL_GPL vmlinux 0xb6b22753 rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0xb70b292b transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0xb71cd8c0 inotify_find_update_watch +EXPORT_SYMBOL_GPL vmlinux 0xb78bbb69 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0xb78d6556 usb_string +EXPORT_SYMBOL_GPL vmlinux 0xb7b846ed inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0xb7c5b6fe platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0xb7e91780 usb_remove_hcd +EXPORT_SYMBOL_GPL vmlinux 0xb8759c2c srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0xb87802e1 unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0xb87a5117 ata_sff_port_start +EXPORT_SYMBOL_GPL vmlinux 0xb886b687 raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0xb8d1490a driver_attach +EXPORT_SYMBOL_GPL vmlinux 0xb8fee532 blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0xb91011ce class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xb9eb3aa9 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0xba089e13 ide_error +EXPORT_SYMBOL_GPL vmlinux 0xba549831 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0xba556dab usb_get_dev +EXPORT_SYMBOL_GPL vmlinux 0xbc443bfa rpcb_getport_async +EXPORT_SYMBOL_GPL vmlinux 0xbc45638d unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xbcd99501 usb_submit_urb +EXPORT_SYMBOL_GPL vmlinux 0xbce9a603 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0xbd7a97a8 led_trigger_remove +EXPORT_SYMBOL_GPL vmlinux 0xbd990855 ide_pci_dma_base +EXPORT_SYMBOL_GPL vmlinux 0xbde0e75e regulator_force_disable +EXPORT_SYMBOL_GPL vmlinux 0xbe1887e4 ata_unpack_xfermask +EXPORT_SYMBOL_GPL vmlinux 0xbe5cf789 ide_output_data +EXPORT_SYMBOL_GPL vmlinux 0xbe877944 tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0xbead1ce6 rpc_create +EXPORT_SYMBOL_GPL vmlinux 0xbee6e768 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0xbeea7a2b srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0xbf597eec ide_pci_init_one +EXPORT_SYMBOL_GPL vmlinux 0xbf9d1b96 nfsd_debug +EXPORT_SYMBOL_GPL vmlinux 0xc02c04a7 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0xc0429bb2 bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0xc04dc819 device_initialize +EXPORT_SYMBOL_GPL vmlinux 0xc06841d6 sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0xc0b24881 blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0xc0bbd111 ata_timing_compute +EXPORT_SYMBOL_GPL vmlinux 0xc12435e3 rpc_calc_rto +EXPORT_SYMBOL_GPL vmlinux 0xc13a7ad1 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0xc15fb989 generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0xc17515d7 usb_hcds_loaded +EXPORT_SYMBOL_GPL vmlinux 0xc1e52112 tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0xc27276b5 transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0xc27c0b16 ata_sff_exec_command +EXPORT_SYMBOL_GPL vmlinux 0xc29400dd usb_anchor_urb +EXPORT_SYMBOL_GPL vmlinux 0xc2cd721e rpc_sleep_on +EXPORT_SYMBOL_GPL vmlinux 0xc34efe27 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0xc3c887ff usb_control_msg +EXPORT_SYMBOL_GPL vmlinux 0xc40f55c5 pci_create_slot +EXPORT_SYMBOL_GPL vmlinux 0xc428068d sata_deb_timing_long +EXPORT_SYMBOL_GPL vmlinux 0xc450a003 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0xc48b7ccf ata_mode_string +EXPORT_SYMBOL_GPL vmlinux 0xc5718161 inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0xc5ae9ec2 ata_link_offline +EXPORT_SYMBOL_GPL vmlinux 0xc5c6f187 transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0xc5f116a7 bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0xc5feaa65 ata_port_disable +EXPORT_SYMBOL_GPL vmlinux 0xc63c15fb inotify_init +EXPORT_SYMBOL_GPL vmlinux 0xc65c14fe usb_kill_urb +EXPORT_SYMBOL_GPL vmlinux 0xc673e23e ata_scsi_change_queue_depth +EXPORT_SYMBOL_GPL vmlinux 0xc6abcaba ata_port_freeze +EXPORT_SYMBOL_GPL vmlinux 0xc6bcd92b ata_dummy_port_info +EXPORT_SYMBOL_GPL vmlinux 0xc6e787e8 add_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0xc6f97a86 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0xc73122be alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xc75ca921 ata_sff_dumb_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0xc76e6159 ide_wait_not_busy +EXPORT_SYMBOL_GPL vmlinux 0xc7a924cf cfi_cmdset_0001 +EXPORT_SYMBOL_GPL vmlinux 0xc7f41618 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xc877a40c rpc_peeraddr2str +EXPORT_SYMBOL_GPL vmlinux 0xc8a30cc6 vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0xc8ef362e __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0xc91fea35 kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0xc99c1d9f tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0xca32a2aa ide_timing_merge +EXPORT_SYMBOL_GPL vmlinux 0xca7cbab2 vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0xcb0c2ebf __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xcb2f4c87 ata_host_alloc_pinfo +EXPORT_SYMBOL_GPL vmlinux 0xcb51b43c rpc_exit_task +EXPORT_SYMBOL_GPL vmlinux 0xcbbe56b5 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0xcbfe8c6b usb_kill_anchored_urbs +EXPORT_SYMBOL_GPL vmlinux 0xcc1f1c3d inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0xcc9839af kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0xcc9d32df rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL vmlinux 0xcccfb2fa sata_deb_timing_hotplug +EXPORT_SYMBOL_GPL vmlinux 0xcd13b73b ata_host_activate +EXPORT_SYMBOL_GPL vmlinux 0xcd181214 scsi_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xcd6bd0fa anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0xcd7cc1df tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0xcdb01877 ktime_add_ns +EXPORT_SYMBOL_GPL vmlinux 0xcdb16117 ata_sff_softreset +EXPORT_SYMBOL_GPL vmlinux 0xcdd60e27 bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xce11ec8c raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0xce3e071e regulator_unregister +EXPORT_SYMBOL_GPL vmlinux 0xceb90828 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0xcecc7ece transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0xcecef764 ide_exec_command +EXPORT_SYMBOL_GPL vmlinux 0xced2720a regulator_set_supply +EXPORT_SYMBOL_GPL vmlinux 0xcf883556 simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0xcf969ca7 rpc_proc_register +EXPORT_SYMBOL_GPL vmlinux 0xcfeaf5f7 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0xd03c7700 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0xd059f1dd page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0xd07955c8 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0xd0c05159 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0xd1828c16 usb_init_urb +EXPORT_SYMBOL_GPL vmlinux 0xd18d9155 tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0xd19ff360 usb_free_urb +EXPORT_SYMBOL_GPL vmlinux 0xd1ed26ea crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0xd20454d2 fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0xd241a219 rpc_run_task +EXPORT_SYMBOL_GPL vmlinux 0xd2703661 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xd330a313 invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0xd39f4022 ide_allocate_dma_engine +EXPORT_SYMBOL_GPL vmlinux 0xd3b4ccf3 ata_sff_tf_load +EXPORT_SYMBOL_GPL vmlinux 0xd3cdb022 skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0xd455c201 regulator_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0xd4628776 inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0xd47df65e ata_dev_disable +EXPORT_SYMBOL_GPL vmlinux 0xd4f0c5b3 usb_hcd_pci_probe +EXPORT_SYMBOL_GPL vmlinux 0xd4fbf112 blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0xd5038233 ide_init_disk +EXPORT_SYMBOL_GPL vmlinux 0xd52524de ide_set_dma_mode +EXPORT_SYMBOL_GPL vmlinux 0xd54290d7 __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0xd578d111 tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0xd5dd30ac klist_next +EXPORT_SYMBOL_GPL vmlinux 0xd624a7bc get_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0xd637af83 rtc_device_register +EXPORT_SYMBOL_GPL vmlinux 0xd6915626 rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL vmlinux 0xd691c1bf hid_free_device +EXPORT_SYMBOL_GPL vmlinux 0xd6b67e97 rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL vmlinux 0xd731d97d ata_bus_reset +EXPORT_SYMBOL_GPL vmlinux 0xd741cfcf blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xd7435c8a ide_set_pio +EXPORT_SYMBOL_GPL vmlinux 0xd758ec0e crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0xd76631c1 register_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0xd83c48a2 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0xd84651fb ata_sas_port_init +EXPORT_SYMBOL_GPL vmlinux 0xd84cd7f4 ata_timing_find_mode +EXPORT_SYMBOL_GPL vmlinux 0xd86cae86 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xd872d858 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0xd8f0a61f tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0xd90763fb ide_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xd911f043 pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0xd9205b9c get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0xd949930f devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0xd9c00231 rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0xda171b36 sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0xdb204a72 register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0xdbda37f3 invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0xdbf1c197 rdev_get_drvdata +EXPORT_SYMBOL_GPL vmlinux 0xdc2666f9 hwmon_device_register +EXPORT_SYMBOL_GPL vmlinux 0xdc5a3f76 i2c_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0xdc9fb141 inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0xdca879fc __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xdd457d90 rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0xde61a0b9 usb_register_driver +EXPORT_SYMBOL_GPL vmlinux 0xdf3022b2 ata_sff_interrupt +EXPORT_SYMBOL_GPL vmlinux 0xdf95644e disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0xdfe6d7f8 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0xe09fd88e __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL vmlinux 0xe1123393 pci_bus_max_busnr +EXPORT_SYMBOL_GPL vmlinux 0xe12e335f usb_put_dev +EXPORT_SYMBOL_GPL vmlinux 0xe1f62f3e usb_get_current_frame_number +EXPORT_SYMBOL_GPL vmlinux 0xe21fd60f tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0xe22cdb81 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0xe236a98a led_trigger_register +EXPORT_SYMBOL_GPL vmlinux 0xe2a0e28c platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xe2f45654 i2c_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xe3067d18 ide_timing_compute +EXPORT_SYMBOL_GPL vmlinux 0xe360da35 usb_buffer_alloc +EXPORT_SYMBOL_GPL vmlinux 0xe3f9139c ata_sff_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0xe3fbc28b regulator_get_voltage +EXPORT_SYMBOL_GPL vmlinux 0xe424cef2 ata_std_qc_defer +EXPORT_SYMBOL_GPL vmlinux 0xe45e1a43 __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0xe49ff3b0 ata_wait_register +EXPORT_SYMBOL_GPL vmlinux 0xe4f7b79b rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL vmlinux 0xe530071c pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0xe56de7f5 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0xe61ef7b3 init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0xe6585ad1 inotify_rm_wd +EXPORT_SYMBOL_GPL vmlinux 0xe684ee73 sdev_evt_send +EXPORT_SYMBOL_GPL vmlinux 0xe6a831d7 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0xe6d90403 ata_eh_analyze_ncq_error +EXPORT_SYMBOL_GPL vmlinux 0xe6f4aae1 ata_pci_sff_prepare_host +EXPORT_SYMBOL_GPL vmlinux 0xe77dadf6 ide_find_dma_mode +EXPORT_SYMBOL_GPL vmlinux 0xe7f0ef5c put_rpccred +EXPORT_SYMBOL_GPL vmlinux 0xe7f33ef0 bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0xe7f53ee4 rdev_get_id +EXPORT_SYMBOL_GPL vmlinux 0xe7f9bfe5 alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0xe8243482 scsi_internal_device_block +EXPORT_SYMBOL_GPL vmlinux 0xe87e1357 xprt_write_space +EXPORT_SYMBOL_GPL vmlinux 0xe93e49c3 devres_free +EXPORT_SYMBOL_GPL vmlinux 0xe94f0d40 bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0xe9587909 usb_unregister_notify +EXPORT_SYMBOL_GPL vmlinux 0xe9780e98 find_vpid +EXPORT_SYMBOL_GPL vmlinux 0xe995cea9 led_trigger_set +EXPORT_SYMBOL_GPL vmlinux 0xea418e0f atapi_cmd_type +EXPORT_SYMBOL_GPL vmlinux 0xea42e998 dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0xea4a9122 sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0xea4d8b61 platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0xead204dd sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0xeb627f24 lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0xebae256a ata_sff_port_ops +EXPORT_SYMBOL_GPL vmlinux 0xebe66003 console_drivers +EXPORT_SYMBOL_GPL vmlinux 0xec068b5c unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0xec1b043e regulator_suspend_prepare +EXPORT_SYMBOL_GPL vmlinux 0xec3e3ef4 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0xed51fe1e ata_pci_remove_one +EXPORT_SYMBOL_GPL vmlinux 0xed92c646 sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xedc2994d ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0xeea3da5a devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0xeeacab69 rpc_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0xeeb55a6a led_trigger_set_default +EXPORT_SYMBOL_GPL vmlinux 0xeeb571bf led_trigger_store +EXPORT_SYMBOL_GPL vmlinux 0xef1b1566 input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0xef233ba3 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0xef329b16 hid_input_report +EXPORT_SYMBOL_GPL vmlinux 0xef4e963e __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xef6c4acd dev_attr_em_message_type +EXPORT_SYMBOL_GPL vmlinux 0xef82fdba srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0xefe21106 snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0xeff9531d page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0xf01b11db ata_pci_bmdma_init +EXPORT_SYMBOL_GPL vmlinux 0xf07e4e85 usb_hcd_pci_remove +EXPORT_SYMBOL_GPL vmlinux 0xf0e848f2 nf_register_afinfo +EXPORT_SYMBOL_GPL vmlinux 0xf13e6f48 scsi_mode_select +EXPORT_SYMBOL_GPL vmlinux 0xf1463412 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0xf1569339 sata_sff_hardreset +EXPORT_SYMBOL_GPL vmlinux 0xf15fd043 sata_scr_write_flush +EXPORT_SYMBOL_GPL vmlinux 0xf17129df get_sb_mtd +EXPORT_SYMBOL_GPL vmlinux 0xf184d189 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0xf1b6aa2c get_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0xf1bb94f5 svc_reg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0xf1cbdb4a ide_pci_check_simplex +EXPORT_SYMBOL_GPL vmlinux 0xf24c7726 pciserial_resume_ports +EXPORT_SYMBOL_GPL vmlinux 0xf2921925 inotify_remove_watch_locked +EXPORT_SYMBOL_GPL vmlinux 0xf2a9991a usb_reset_configuration +EXPORT_SYMBOL_GPL vmlinux 0xf2fca922 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0xf34ef13b rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0xf3725b51 xprt_register_transport +EXPORT_SYMBOL_GPL vmlinux 0xf38323df class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0xf3d5cc13 ata_timing_merge +EXPORT_SYMBOL_GPL vmlinux 0xf499fdb2 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0xf4ecc9d2 ide_dma_start +EXPORT_SYMBOL_GPL vmlinux 0xf553052a sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0xf57542e3 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0xf598f39b queue_work +EXPORT_SYMBOL_GPL vmlinux 0xf5a691cd invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0xf5b10a7f find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0xf65dc583 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0xf6c29c69 seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0xf72053b6 rpc_clone_client +EXPORT_SYMBOL_GPL vmlinux 0xf7af1402 i2c_new_dummy +EXPORT_SYMBOL_GPL vmlinux 0xf7f0aa69 led_classdev_suspend +EXPORT_SYMBOL_GPL vmlinux 0xf85adc81 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0xf863e82a flush_work +EXPORT_SYMBOL_GPL vmlinux 0xf87360fe scsi_flush_work +EXPORT_SYMBOL_GPL vmlinux 0xf87c79b9 pciserial_suspend_ports +EXPORT_SYMBOL_GPL vmlinux 0xf87f685c csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL vmlinux 0xf8802492 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0xf89106ff usb_deregister +EXPORT_SYMBOL_GPL vmlinux 0xf8f3a0fb ata_ratelimit +EXPORT_SYMBOL_GPL vmlinux 0xf8f64c37 ata_std_postreset +EXPORT_SYMBOL_GPL vmlinux 0xf913e8b0 device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xf929effc __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0xf9a054b5 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0xf9a1c758 crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0xf9b86b7e ata_sg_init +EXPORT_SYMBOL_GPL vmlinux 0xf9bf0c9a __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0xf9ca3160 ata_id_xfermask +EXPORT_SYMBOL_GPL vmlinux 0xf9d1164c rpc_free +EXPORT_SYMBOL_GPL vmlinux 0xfab69523 single_release_net +EXPORT_SYMBOL_GPL vmlinux 0xfada6891 hwmon_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xfb41bab5 raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0xfb49d4c5 ata_host_init +EXPORT_SYMBOL_GPL vmlinux 0xfb5f8d3a svc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0xfbf9be5d register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xfc28d54f ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0xfce76c4c regulator_get_current_limit +EXPORT_SYMBOL_GPL vmlinux 0xfd29119e regulator_bulk_free +EXPORT_SYMBOL_GPL vmlinux 0xfd3f8213 dev_attr_link_power_management_policy +EXPORT_SYMBOL_GPL vmlinux 0xfd5d579e ata_sff_post_internal_cmd +EXPORT_SYMBOL_GPL vmlinux 0xfde55150 pci_destroy_slot +EXPORT_SYMBOL_GPL vmlinux 0xfde7b58c sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0xfe8c5640 svc_xprt_names +EXPORT_SYMBOL_GPL vmlinux 0xff46a569 xprt_complete_rqst +EXPORT_SYMBOL_GPL vmlinux 0xff541234 ata_eh_qc_retry +EXPORT_SYMBOL_GPL vmlinux 0xff541b21 sysdev_class_create_file +EXPORT_SYMBOL_GPL vmlinux 0xffa2753c tcp_done +EXPORT_SYMBOL_GPL vmlinux 0xffaf7bbb __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0xffdfbf59 i2c_new_probed_device +EXPORT_SYMBOL_GPL vmlinux 0xfffe447d class_find_device --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/armel/ignore.modules +++ linux-2.6.27/debian/abi/2.6.27-8.17/armel/ignore.modules @@ -0,0 +1 @@ +1 --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/armel/versatile +++ linux-2.6.27/debian/abi/2.6.27-8.17/armel/versatile @@ -0,0 +1,3229 @@ +EXPORT_SYMBOL drivers/serial/8250 0x00000000 serial8250_register_port +EXPORT_SYMBOL drivers/serial/8250 0x00000000 serial8250_resume_port +EXPORT_SYMBOL drivers/serial/8250 0x00000000 serial8250_suspend_port +EXPORT_SYMBOL drivers/serial/8250 0x00000000 serial8250_unregister_port +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 load_nls +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 load_nls_default +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 register_nls +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 unload_nls +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 unregister_nls +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 utf8_mbstowcs +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 utf8_mbtowc +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 utf8_wcstombs +EXPORT_SYMBOL fs/nls/nls_base 0x00000000 utf8_wctomb +EXPORT_SYMBOL net/ipv4/inet_lro 0x00000000 lro_flush_all +EXPORT_SYMBOL net/ipv4/inet_lro 0x00000000 lro_flush_pkt +EXPORT_SYMBOL net/ipv4/inet_lro 0x00000000 lro_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0x00000000 lro_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0x00000000 lro_vlan_hwaccel_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0x00000000 lro_vlan_hwaccel_receive_skb +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 __ieee80211_get_assoc_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 __ieee80211_get_radio_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 __ieee80211_get_rx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 __ieee80211_get_tx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 __ieee80211_rx +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_alloc_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_beacon_get +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_ctstoself_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_ctstoself_get +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_free_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_generic_frame_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_get_buffered_bc +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_get_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_get_hdrlen_from_skb +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_get_tkip_key +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_notify_mac +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_rate_control_register +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_rate_control_unregister +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_register_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_rts_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_rts_get +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_rx_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_scan_completed +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_start_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_start_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_start_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_stop_queue +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_stop_queues +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_stop_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_stop_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_stop_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_tx_status +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_tx_status_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_unregister_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_wake_queue +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 ieee80211_wake_queues +EXPORT_SYMBOL net/mac80211/mac80211 0x00000000 sta_info_get +EXPORT_SYMBOL net/rfkill/rfkill 0x00000000 rfkill_allocate +EXPORT_SYMBOL net/rfkill/rfkill 0x00000000 rfkill_force_state +EXPORT_SYMBOL net/rfkill/rfkill 0x00000000 rfkill_free +EXPORT_SYMBOL net/rfkill/rfkill 0x00000000 rfkill_register +EXPORT_SYMBOL net/rfkill/rfkill 0x00000000 rfkill_switch_all +EXPORT_SYMBOL net/rfkill/rfkill 0x00000000 rfkill_unregister +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 __ieee80211_get_channel +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 ieee80211_channel_to_frequency +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 ieee80211_frequency_to_channel +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 ieee80211_radiotap_iterator_init +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 ieee80211_radiotap_iterator_next +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 wiphy_free +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 wiphy_new +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 wiphy_register +EXPORT_SYMBOL net/wireless/cfg80211 0x00000000 wiphy_unregister +EXPORT_SYMBOL sound/ac97_bus 0x00000000 ac97_bus_type +EXPORT_SYMBOL sound/core/oss/snd-mixer-oss 0x00000000 snd_mixer_oss_ioctl_card +EXPORT_SYMBOL sound/core/snd 0x00000000 copy_from_user_toio +EXPORT_SYMBOL sound/core/snd 0x00000000 copy_to_user_fromio +EXPORT_SYMBOL sound/core/snd 0x00000000 release_and_free_resource +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_add_device_sysfs_file +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_disconnect +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_file_add +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_file_remove +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_free +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_free_when_closed +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_new +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_proc_new +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_card_register +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_cards +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_component_add +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_add +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_add_slave +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_boolean_mono_info +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_boolean_stereo_info +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_find_id +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_find_numid +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_free_one +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_make_virtual_master +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_new1 +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_notify +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_register_ioctl +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_remove +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_remove_id +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_rename_id +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ctl_unregister_ioctl +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_device_free +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_device_new +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_device_register +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_ecards_limit +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_info_create_card_entry +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_info_create_module_entry +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_info_free_entry +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_info_get_line +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_info_get_str +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_info_register +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_iprintf +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_lookup_minor_data +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_lookup_oss_minor_data +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_major +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_mixer_oss_notify_callback +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_oss_info_register +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_power_wait +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_register_device_for_dev +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_register_oss_device +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_request_card +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_seq_root +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_unregister_device +EXPORT_SYMBOL sound/core/snd 0x00000000 snd_unregister_oss_device +EXPORT_SYMBOL sound/core/snd-page-alloc 0x00000000 snd_dma_alloc_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x00000000 snd_dma_alloc_pages_fallback +EXPORT_SYMBOL sound/core/snd-page-alloc 0x00000000 snd_dma_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x00000000 snd_dma_get_reserved_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x00000000 snd_dma_reserve_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x00000000 snd_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x00000000 snd_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 _snd_pcm_hw_param_setempty +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 _snd_pcm_hw_params_any +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_interval_list +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_interval_ratnum +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_interval_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_big_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_linear +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_little_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_physical_width +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_set_silence +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_signed +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_silence_64 +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_size +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_unsigned +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_format_width +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_integer +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_list +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_minmax +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_msbits +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_pow2 +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_ratdens +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_ratnums +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_constraint_step +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_param_first +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_param_last +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_param_value +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_hw_rule_add +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_kernel_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_free_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_preallocate_free_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_preallocate_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_preallocate_pages_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_read +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_readv +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_write +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_lib_writev +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_limit_hw_rates +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_link_rwlock +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_mmap_data +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_new +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_new_stream +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_notify +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_open_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_period_elapsed +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_rate_to_rate_bit +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_release_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_set_ops +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_set_sync +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_sgbuf_ops_page +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_stop +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_suspend +EXPORT_SYMBOL sound/core/snd-pcm 0x00000000 snd_pcm_suspend_all +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_close +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_continue +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_global_free +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_global_new +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_global_register +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_interrupt +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_new +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_notify +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_open +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_pause +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_resolution +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_start +EXPORT_SYMBOL sound/core/snd-timer 0x00000000 snd_timer_stop +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_bus +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_get_short_name +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_mixer +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_pcm_assign +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_pcm_close +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_pcm_double_rate_rules +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_pcm_open +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_read +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_resume +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_set_rate +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_suspend +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_tune_hardware +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_update +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_update_bits +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_write +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x00000000 snd_ac97_write_cache +EXPORT_SYMBOL vmlinux 0x00000000 I_BDEV +EXPORT_SYMBOL vmlinux 0x00000000 ___pskb_trim +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_idiv +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_idivmod +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_lasr +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_llsl +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_llsr +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_lmul +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_uidiv +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_uidivmod +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_ulcmp +EXPORT_SYMBOL vmlinux 0x00000000 __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x00000000 __alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 __arm_ioremap +EXPORT_SYMBOL vmlinux 0x00000000 __arm_ioremap_pfn +EXPORT_SYMBOL vmlinux 0x00000000 __ashldi3 +EXPORT_SYMBOL vmlinux 0x00000000 __ashrdi3 +EXPORT_SYMBOL vmlinux 0x00000000 __backtrace +EXPORT_SYMBOL vmlinux 0x00000000 __bad_xchg +EXPORT_SYMBOL vmlinux 0x00000000 __bdevname +EXPORT_SYMBOL vmlinux 0x00000000 __bforget +EXPORT_SYMBOL vmlinux 0x00000000 __bio_clone +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_and +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_complement +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_equal +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_full +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_intersects +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_or +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_parse +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_xor +EXPORT_SYMBOL vmlinux 0x00000000 __blk_run_queue +EXPORT_SYMBOL vmlinux 0x00000000 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0x00000000 __bread +EXPORT_SYMBOL vmlinux 0x00000000 __breadahead +EXPORT_SYMBOL vmlinux 0x00000000 __break_lease +EXPORT_SYMBOL vmlinux 0x00000000 __brelse +EXPORT_SYMBOL vmlinux 0x00000000 __bug +EXPORT_SYMBOL vmlinux 0x00000000 __cap_empty_set +EXPORT_SYMBOL vmlinux 0x00000000 __cap_full_set +EXPORT_SYMBOL vmlinux 0x00000000 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x00000000 __check_region +EXPORT_SYMBOL vmlinux 0x00000000 __clear_user +EXPORT_SYMBOL vmlinux 0x00000000 __const_udelay +EXPORT_SYMBOL vmlinux 0x00000000 __copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 __copy_to_user +EXPORT_SYMBOL vmlinux 0x00000000 __csum_ipv6_magic +EXPORT_SYMBOL vmlinux 0x00000000 __dev_get_by_index +EXPORT_SYMBOL vmlinux 0x00000000 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0x00000000 __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x00000000 __dev_remove_pack +EXPORT_SYMBOL vmlinux 0x00000000 __devm_release_region +EXPORT_SYMBOL vmlinux 0x00000000 __devm_request_region +EXPORT_SYMBOL vmlinux 0x00000000 __div0 +EXPORT_SYMBOL vmlinux 0x00000000 __div64_32 +EXPORT_SYMBOL vmlinux 0x00000000 __divsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __do_div64 +EXPORT_SYMBOL vmlinux 0x00000000 __down_read +EXPORT_SYMBOL vmlinux 0x00000000 __down_read_trylock +EXPORT_SYMBOL vmlinux 0x00000000 __down_write +EXPORT_SYMBOL vmlinux 0x00000000 __down_write_nested +EXPORT_SYMBOL vmlinux 0x00000000 __down_write_trylock +EXPORT_SYMBOL vmlinux 0x00000000 __downgrade_write +EXPORT_SYMBOL vmlinux 0x00000000 __dst_free +EXPORT_SYMBOL vmlinux 0x00000000 __elv_add_request +EXPORT_SYMBOL vmlinux 0x00000000 __f_setown +EXPORT_SYMBOL vmlinux 0x00000000 __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0x00000000 __find_get_block +EXPORT_SYMBOL vmlinux 0x00000000 __free_pages +EXPORT_SYMBOL vmlinux 0x00000000 __generic_unplug_device +EXPORT_SYMBOL vmlinux 0x00000000 __get_free_pages +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_1 +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_2 +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_4 +EXPORT_SYMBOL vmlinux 0x00000000 __getblk +EXPORT_SYMBOL vmlinux 0x00000000 __grab_cache_page +EXPORT_SYMBOL vmlinux 0x00000000 __init_rwsem +EXPORT_SYMBOL vmlinux 0x00000000 __inode_dir_notify +EXPORT_SYMBOL vmlinux 0x00000000 __insert_inode_hash +EXPORT_SYMBOL vmlinux 0x00000000 __invalidate_device +EXPORT_SYMBOL vmlinux 0x00000000 __iounmap +EXPORT_SYMBOL vmlinux 0x00000000 __ip_select_ident +EXPORT_SYMBOL vmlinux 0x00000000 __kfifo_get +EXPORT_SYMBOL vmlinux 0x00000000 __kfifo_put +EXPORT_SYMBOL vmlinux 0x00000000 __kfree_skb +EXPORT_SYMBOL vmlinux 0x00000000 __kill_fasync +EXPORT_SYMBOL vmlinux 0x00000000 __kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 __krealloc +EXPORT_SYMBOL vmlinux 0x00000000 __lock_buffer +EXPORT_SYMBOL vmlinux 0x00000000 __lock_page +EXPORT_SYMBOL vmlinux 0x00000000 __locks_copy_lock +EXPORT_SYMBOL vmlinux 0x00000000 __lookup_hash +EXPORT_SYMBOL vmlinux 0x00000000 __lshrdi3 +EXPORT_SYMBOL vmlinux 0x00000000 __machine_arch_type +EXPORT_SYMBOL vmlinux 0x00000000 __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0x00000000 __memzero +EXPORT_SYMBOL vmlinux 0x00000000 __mmc_claim_host +EXPORT_SYMBOL vmlinux 0x00000000 __mod_timer +EXPORT_SYMBOL vmlinux 0x00000000 __modsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __module_put_and_exit +EXPORT_SYMBOL vmlinux 0x00000000 __mpage_writepage +EXPORT_SYMBOL vmlinux 0x00000000 __muldi3 +EXPORT_SYMBOL vmlinux 0x00000000 __mutex_init +EXPORT_SYMBOL vmlinux 0x00000000 __napi_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __neigh_event_send +EXPORT_SYMBOL vmlinux 0x00000000 __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0x00000000 __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 __netif_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __nla_put +EXPORT_SYMBOL vmlinux 0x00000000 __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 __nla_reserve +EXPORT_SYMBOL vmlinux 0x00000000 __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 __page_symlink +EXPORT_SYMBOL vmlinux 0x00000000 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0x00000000 __pagevec_release +EXPORT_SYMBOL vmlinux 0x00000000 __print_symbol +EXPORT_SYMBOL vmlinux 0x00000000 __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_1 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_2 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_4 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_8 +EXPORT_SYMBOL vmlinux 0x00000000 __ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsb +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsl +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsw +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesb +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesl +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesw +EXPORT_SYMBOL vmlinux 0x00000000 __readwrite_bug +EXPORT_SYMBOL vmlinux 0x00000000 __release_region +EXPORT_SYMBOL vmlinux 0x00000000 __request_region +EXPORT_SYMBOL vmlinux 0x00000000 __rta_fill +EXPORT_SYMBOL vmlinux 0x00000000 __scm_destroy +EXPORT_SYMBOL vmlinux 0x00000000 __scm_send +EXPORT_SYMBOL vmlinux 0x00000000 __secpath_destroy +EXPORT_SYMBOL vmlinux 0x00000000 __seq_open_private +EXPORT_SYMBOL vmlinux 0x00000000 __serio_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 __serio_register_port +EXPORT_SYMBOL vmlinux 0x00000000 __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0x00000000 __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0x00000000 __set_personality +EXPORT_SYMBOL vmlinux 0x00000000 __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x00000000 __sg_free_table +EXPORT_SYMBOL vmlinux 0x00000000 __sk_dst_check +EXPORT_SYMBOL vmlinux 0x00000000 __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0x00000000 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0x00000000 __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0x00000000 __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x00000000 __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0x00000000 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0x00000000 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 __strnlen_user +EXPORT_SYMBOL vmlinux 0x00000000 __symbol_put +EXPORT_SYMBOL vmlinux 0x00000000 __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __tasklet_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __ucmpdi2 +EXPORT_SYMBOL vmlinux 0x00000000 __udelay +EXPORT_SYMBOL vmlinux 0x00000000 __udivsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __umodsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __up_read +EXPORT_SYMBOL vmlinux 0x00000000 __up_write +EXPORT_SYMBOL vmlinux 0x00000000 __vmalloc +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_bit +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_buffer +EXPORT_SYMBOL vmlinux 0x00000000 __wake_up +EXPORT_SYMBOL vmlinux 0x00000000 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_lookup +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x00000000 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x00000000 _change_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _clear_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _cond_resched +EXPORT_SYMBOL vmlinux 0x00000000 _ctype +EXPORT_SYMBOL vmlinux 0x00000000 _find_first_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_first_zero_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_next_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_next_zero_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _local_bh_enable +EXPORT_SYMBOL vmlinux 0x00000000 _memcpy_fromio +EXPORT_SYMBOL vmlinux 0x00000000 _memcpy_toio +EXPORT_SYMBOL vmlinux 0x00000000 _memset_io +EXPORT_SYMBOL vmlinux 0x00000000 _set_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_change_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_clear_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_set_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 abort +EXPORT_SYMBOL vmlinux 0x00000000 acquire_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 add_disk +EXPORT_SYMBOL vmlinux 0x00000000 add_mtd_partitions +EXPORT_SYMBOL vmlinux 0x00000000 add_taint +EXPORT_SYMBOL vmlinux 0x00000000 add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0x00000000 add_wait_queue +EXPORT_SYMBOL vmlinux 0x00000000 add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x00000000 adjust_resource +EXPORT_SYMBOL vmlinux 0x00000000 aio_complete +EXPORT_SYMBOL vmlinux 0x00000000 aio_put_req +EXPORT_SYMBOL vmlinux 0x00000000 alloc_buffer_head +EXPORT_SYMBOL vmlinux 0x00000000 alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 alloc_disk +EXPORT_SYMBOL vmlinux 0x00000000 alloc_disk_node +EXPORT_SYMBOL vmlinux 0x00000000 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0x00000000 alloc_file +EXPORT_SYMBOL vmlinux 0x00000000 alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0x00000000 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0x00000000 alloc_tty_driver +EXPORT_SYMBOL vmlinux 0x00000000 allocate_resource +EXPORT_SYMBOL vmlinux 0x00000000 allow_signal +EXPORT_SYMBOL vmlinux 0x00000000 amba_device_register +EXPORT_SYMBOL vmlinux 0x00000000 amba_device_unregister +EXPORT_SYMBOL vmlinux 0x00000000 amba_driver_register +EXPORT_SYMBOL vmlinux 0x00000000 amba_driver_unregister +EXPORT_SYMBOL vmlinux 0x00000000 amba_find_device +EXPORT_SYMBOL vmlinux 0x00000000 amba_release_regions +EXPORT_SYMBOL vmlinux 0x00000000 amba_request_regions +EXPORT_SYMBOL vmlinux 0x00000000 argv_free +EXPORT_SYMBOL vmlinux 0x00000000 argv_split +EXPORT_SYMBOL vmlinux 0x00000000 arm926_coherent_kern_range +EXPORT_SYMBOL vmlinux 0x00000000 arm926_flush_kern_cache_all +EXPORT_SYMBOL vmlinux 0x00000000 arm926_flush_user_cache_all +EXPORT_SYMBOL vmlinux 0x00000000 arm926_flush_user_cache_range +EXPORT_SYMBOL vmlinux 0x00000000 arp_broken_ops +EXPORT_SYMBOL vmlinux 0x00000000 arp_create +EXPORT_SYMBOL vmlinux 0x00000000 arp_find +EXPORT_SYMBOL vmlinux 0x00000000 arp_send +EXPORT_SYMBOL vmlinux 0x00000000 arp_tbl +EXPORT_SYMBOL vmlinux 0x00000000 arp_xmit +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_find +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_lookup +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_put +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_add_addr +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_forget_old +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_lookup +EXPORT_SYMBOL vmlinux 0x00000000 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0x00000000 avenrun +EXPORT_SYMBOL vmlinux 0x00000000 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0x00000000 bcd2bin +EXPORT_SYMBOL vmlinux 0x00000000 bd_claim +EXPORT_SYMBOL vmlinux 0x00000000 bd_release +EXPORT_SYMBOL vmlinux 0x00000000 bd_set_size +EXPORT_SYMBOL vmlinux 0x00000000 bdev_read_only +EXPORT_SYMBOL vmlinux 0x00000000 bdevname +EXPORT_SYMBOL vmlinux 0x00000000 bdget +EXPORT_SYMBOL vmlinux 0x00000000 bdi_destroy +EXPORT_SYMBOL vmlinux 0x00000000 bdi_init +EXPORT_SYMBOL vmlinux 0x00000000 bdi_register +EXPORT_SYMBOL vmlinux 0x00000000 bdi_register_dev +EXPORT_SYMBOL vmlinux 0x00000000 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0x00000000 bdi_unregister +EXPORT_SYMBOL vmlinux 0x00000000 bdput +EXPORT_SYMBOL vmlinux 0x00000000 bh_submit_read +EXPORT_SYMBOL vmlinux 0x00000000 bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0x00000000 bin2bcd +EXPORT_SYMBOL vmlinux 0x00000000 bio_add_page +EXPORT_SYMBOL vmlinux 0x00000000 bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x00000000 bio_alloc +EXPORT_SYMBOL vmlinux 0x00000000 bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0x00000000 bio_clone +EXPORT_SYMBOL vmlinux 0x00000000 bio_copy_kern +EXPORT_SYMBOL vmlinux 0x00000000 bio_copy_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_endio +EXPORT_SYMBOL vmlinux 0x00000000 bio_free +EXPORT_SYMBOL vmlinux 0x00000000 bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0x00000000 bio_hw_segments +EXPORT_SYMBOL vmlinux 0x00000000 bio_init +EXPORT_SYMBOL vmlinux 0x00000000 bio_map_kern +EXPORT_SYMBOL vmlinux 0x00000000 bio_map_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_pair_release +EXPORT_SYMBOL vmlinux 0x00000000 bio_phys_segments +EXPORT_SYMBOL vmlinux 0x00000000 bio_put +EXPORT_SYMBOL vmlinux 0x00000000 bio_split +EXPORT_SYMBOL vmlinux 0x00000000 bio_split_pool +EXPORT_SYMBOL vmlinux 0x00000000 bio_uncopy_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_unmap_user +EXPORT_SYMBOL vmlinux 0x00000000 bioset_create +EXPORT_SYMBOL vmlinux 0x00000000 bioset_free +EXPORT_SYMBOL vmlinux 0x00000000 bit_waitqueue +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_bitremap +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_fold +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_onto +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_remap +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x00000000 bitrev16 +EXPORT_SYMBOL vmlinux 0x00000000 bitrev32 +EXPORT_SYMBOL vmlinux 0x00000000 blk_alloc_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0x00000000 blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_complete_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0x00000000 blk_execute_rq +EXPORT_SYMBOL vmlinux 0x00000000 blk_free_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0x00000000 blk_get_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_insert_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x00000000 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x00000000 blk_plug_device +EXPORT_SYMBOL vmlinux 0x00000000 blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x00000000 blk_put_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_bounce +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_make_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_ordered +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0x00000000 blk_recount_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_register_region +EXPORT_SYMBOL vmlinux 0x00000000 blk_remove_plug +EXPORT_SYMBOL vmlinux 0x00000000 blk_requeue_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_init +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_user +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0x00000000 blk_run_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_start_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_start_queueing +EXPORT_SYMBOL vmlinux 0x00000000 blk_stop_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_sync_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_unplug +EXPORT_SYMBOL vmlinux 0x00000000 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x00000000 blk_verify_command +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_get +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_put +EXPORT_SYMBOL vmlinux 0x00000000 block_all_signals +EXPORT_SYMBOL vmlinux 0x00000000 block_commit_write +EXPORT_SYMBOL vmlinux 0x00000000 block_invalidatepage +EXPORT_SYMBOL vmlinux 0x00000000 block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0x00000000 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0x00000000 block_prepare_write +EXPORT_SYMBOL vmlinux 0x00000000 block_read_full_page +EXPORT_SYMBOL vmlinux 0x00000000 block_sync_page +EXPORT_SYMBOL vmlinux 0x00000000 block_truncate_page +EXPORT_SYMBOL vmlinux 0x00000000 block_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 block_write_end +EXPORT_SYMBOL vmlinux 0x00000000 block_write_full_page +EXPORT_SYMBOL vmlinux 0x00000000 bmap +EXPORT_SYMBOL vmlinux 0x00000000 boot_tvec_bases +EXPORT_SYMBOL vmlinux 0x00000000 brioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x00000000 cache_check +EXPORT_SYMBOL vmlinux 0x00000000 cache_flush +EXPORT_SYMBOL vmlinux 0x00000000 cache_purge +EXPORT_SYMBOL vmlinux 0x00000000 cache_register +EXPORT_SYMBOL vmlinux 0x00000000 cache_unregister +EXPORT_SYMBOL vmlinux 0x00000000 cad_pid +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0x00000000 can_do_mlock +EXPORT_SYMBOL vmlinux 0x00000000 cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0x00000000 cancel_dirty_page +EXPORT_SYMBOL vmlinux 0x00000000 cap_netlink_recv +EXPORT_SYMBOL vmlinux 0x00000000 cap_set_effective +EXPORT_SYMBOL vmlinux 0x00000000 capable +EXPORT_SYMBOL vmlinux 0x00000000 cdev_add +EXPORT_SYMBOL vmlinux 0x00000000 cdev_alloc +EXPORT_SYMBOL vmlinux 0x00000000 cdev_del +EXPORT_SYMBOL vmlinux 0x00000000 cdev_init +EXPORT_SYMBOL vmlinux 0x00000000 cfb_copyarea +EXPORT_SYMBOL vmlinux 0x00000000 cfb_fillrect +EXPORT_SYMBOL vmlinux 0x00000000 cfb_imageblit +EXPORT_SYMBOL vmlinux 0x00000000 cfi_fixup +EXPORT_SYMBOL vmlinux 0x00000000 cfi_read_pri +EXPORT_SYMBOL vmlinux 0x00000000 cfi_varsize_frob +EXPORT_SYMBOL vmlinux 0x00000000 check_disk_change +EXPORT_SYMBOL vmlinux 0x00000000 clear_bdi_congested +EXPORT_SYMBOL vmlinux 0x00000000 clear_inode +EXPORT_SYMBOL vmlinux 0x00000000 clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0x00000000 clk_disable +EXPORT_SYMBOL vmlinux 0x00000000 clk_enable +EXPORT_SYMBOL vmlinux 0x00000000 clk_get +EXPORT_SYMBOL vmlinux 0x00000000 clk_get_rate +EXPORT_SYMBOL vmlinux 0x00000000 clk_put +EXPORT_SYMBOL vmlinux 0x00000000 clk_register +EXPORT_SYMBOL vmlinux 0x00000000 clk_round_rate +EXPORT_SYMBOL vmlinux 0x00000000 clk_set_rate +EXPORT_SYMBOL vmlinux 0x00000000 clk_unregister +EXPORT_SYMBOL vmlinux 0x00000000 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 clocksource_register +EXPORT_SYMBOL vmlinux 0x00000000 close_bdev_excl +EXPORT_SYMBOL vmlinux 0x00000000 color_table +EXPORT_SYMBOL vmlinux 0x00000000 complete +EXPORT_SYMBOL vmlinux 0x00000000 complete_all +EXPORT_SYMBOL vmlinux 0x00000000 complete_and_exit +EXPORT_SYMBOL vmlinux 0x00000000 completion_done +EXPORT_SYMBOL vmlinux 0x00000000 compute_creds +EXPORT_SYMBOL vmlinux 0x00000000 con_copy_unimap +EXPORT_SYMBOL vmlinux 0x00000000 con_is_bound +EXPORT_SYMBOL vmlinux 0x00000000 con_set_default_unimap +EXPORT_SYMBOL vmlinux 0x00000000 cond_resched_lock +EXPORT_SYMBOL vmlinux 0x00000000 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x00000000 congestion_wait +EXPORT_SYMBOL vmlinux 0x00000000 console_blank_hook +EXPORT_SYMBOL vmlinux 0x00000000 console_blanked +EXPORT_SYMBOL vmlinux 0x00000000 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0x00000000 console_print +EXPORT_SYMBOL vmlinux 0x00000000 console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x00000000 console_start +EXPORT_SYMBOL vmlinux 0x00000000 console_stop +EXPORT_SYMBOL vmlinux 0x00000000 console_suspend_enabled +EXPORT_SYMBOL vmlinux 0x00000000 cont_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 contig_page_data +EXPORT_SYMBOL vmlinux 0x00000000 copy_io_context +EXPORT_SYMBOL vmlinux 0x00000000 copy_page +EXPORT_SYMBOL vmlinux 0x00000000 copy_strings_kernel +EXPORT_SYMBOL vmlinux 0x00000000 cpu_arm926_dcache_clean_area +EXPORT_SYMBOL vmlinux 0x00000000 cpu_arm926_set_pte_ext +EXPORT_SYMBOL vmlinux 0x00000000 cpu_online_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_possible_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_present_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0x00000000 crc16 +EXPORT_SYMBOL vmlinux 0x00000000 crc16_table +EXPORT_SYMBOL vmlinux 0x00000000 crc32_be +EXPORT_SYMBOL vmlinux 0x00000000 crc32_le +EXPORT_SYMBOL vmlinux 0x00000000 create_empty_buffers +EXPORT_SYMBOL vmlinux 0x00000000 create_proc_entry +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_nocheck +EXPORT_SYMBOL vmlinux 0x00000000 current_fs_time +EXPORT_SYMBOL vmlinux 0x00000000 current_kernel_time +EXPORT_SYMBOL vmlinux 0x00000000 d_add_ci +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_anon +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_name +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_root +EXPORT_SYMBOL vmlinux 0x00000000 d_delete +EXPORT_SYMBOL vmlinux 0x00000000 d_find_alias +EXPORT_SYMBOL vmlinux 0x00000000 d_genocide +EXPORT_SYMBOL vmlinux 0x00000000 d_instantiate +EXPORT_SYMBOL vmlinux 0x00000000 d_instantiate_unique +EXPORT_SYMBOL vmlinux 0x00000000 d_invalidate +EXPORT_SYMBOL vmlinux 0x00000000 d_lookup +EXPORT_SYMBOL vmlinux 0x00000000 d_move +EXPORT_SYMBOL vmlinux 0x00000000 d_namespace_path +EXPORT_SYMBOL vmlinux 0x00000000 d_path +EXPORT_SYMBOL vmlinux 0x00000000 d_prune_aliases +EXPORT_SYMBOL vmlinux 0x00000000 d_rehash +EXPORT_SYMBOL vmlinux 0x00000000 d_splice_alias +EXPORT_SYMBOL vmlinux 0x00000000 d_validate +EXPORT_SYMBOL vmlinux 0x00000000 daemonize +EXPORT_SYMBOL vmlinux 0x00000000 datagram_poll +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_close +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_open +EXPORT_SYMBOL vmlinux 0x00000000 dcache_lock +EXPORT_SYMBOL vmlinux 0x00000000 dcache_readdir +EXPORT_SYMBOL vmlinux 0x00000000 deactivate_super +EXPORT_SYMBOL vmlinux 0x00000000 default_blu +EXPORT_SYMBOL vmlinux 0x00000000 default_grn +EXPORT_SYMBOL vmlinux 0x00000000 default_llseek +EXPORT_SYMBOL vmlinux 0x00000000 default_red +EXPORT_SYMBOL vmlinux 0x00000000 default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0x00000000 default_wake_function +EXPORT_SYMBOL vmlinux 0x00000000 del_gendisk +EXPORT_SYMBOL vmlinux 0x00000000 del_mtd_partitions +EXPORT_SYMBOL vmlinux 0x00000000 del_timer +EXPORT_SYMBOL vmlinux 0x00000000 dentry_open +EXPORT_SYMBOL vmlinux 0x00000000 dentry_unhash +EXPORT_SYMBOL vmlinux 0x00000000 deny_write_access +EXPORT_SYMBOL vmlinux 0x00000000 dev_add_pack +EXPORT_SYMBOL vmlinux 0x00000000 dev_alloc_name +EXPORT_SYMBOL vmlinux 0x00000000 dev_alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 dev_base_lock +EXPORT_SYMBOL vmlinux 0x00000000 dev_change_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_close +EXPORT_SYMBOL vmlinux 0x00000000 dev_disable_lro +EXPORT_SYMBOL vmlinux 0x00000000 dev_driver_string +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_index +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_name +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_getbyhwaddr +EXPORT_SYMBOL vmlinux 0x00000000 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x00000000 dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0x00000000 dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x00000000 dev_load +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_add +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_delete +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_sync +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x00000000 dev_open +EXPORT_SYMBOL vmlinux 0x00000000 dev_queue_xmit +EXPORT_SYMBOL vmlinux 0x00000000 dev_remove_pack +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_allmulti +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_mac_address +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_mtu +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_add +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_delete +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_sync +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0x00000000 dev_valid_name +EXPORT_SYMBOL vmlinux 0x00000000 devm_free_irq +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioport_map +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioremap +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0x00000000 devm_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 devm_request_irq +EXPORT_SYMBOL vmlinux 0x00000000 dget_locked +EXPORT_SYMBOL vmlinux 0x00000000 directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0x00000000 disable_hlt +EXPORT_SYMBOL vmlinux 0x00000000 disable_irq +EXPORT_SYMBOL vmlinux 0x00000000 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x00000000 disallow_signal +EXPORT_SYMBOL vmlinux 0x00000000 div64_u64 +EXPORT_SYMBOL vmlinux 0x00000000 div_s64_rem +EXPORT_SYMBOL vmlinux 0x00000000 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_alloc_writecombine +EXPORT_SYMBOL vmlinux 0x00000000 dma_cache_maint +EXPORT_SYMBOL vmlinux 0x00000000 dma_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x00000000 dma_free_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_mark_declared_memory_occupied +EXPORT_SYMBOL vmlinux 0x00000000 dma_mmap_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_mmap_writecombine +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_create +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_free +EXPORT_SYMBOL vmlinux 0x00000000 dma_release_declared_memory +EXPORT_SYMBOL vmlinux 0x00000000 dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x00000000 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_pool_create +EXPORT_SYMBOL vmlinux 0x00000000 dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dmam_release_declared_memory +EXPORT_SYMBOL vmlinux 0x00000000 do_SAK +EXPORT_SYMBOL vmlinux 0x00000000 do_blank_screen +EXPORT_SYMBOL vmlinux 0x00000000 do_brk +EXPORT_SYMBOL vmlinux 0x00000000 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x00000000 do_map_probe +EXPORT_SYMBOL vmlinux 0x00000000 do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0x00000000 do_munmap +EXPORT_SYMBOL vmlinux 0x00000000 do_settimeofday +EXPORT_SYMBOL vmlinux 0x00000000 do_splice_from +EXPORT_SYMBOL vmlinux 0x00000000 do_splice_to +EXPORT_SYMBOL vmlinux 0x00000000 do_sync_read +EXPORT_SYMBOL vmlinux 0x00000000 do_sync_write +EXPORT_SYMBOL vmlinux 0x00000000 do_unblank_screen +EXPORT_SYMBOL vmlinux 0x00000000 down +EXPORT_SYMBOL vmlinux 0x00000000 down_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 down_killable +EXPORT_SYMBOL vmlinux 0x00000000 down_read +EXPORT_SYMBOL vmlinux 0x00000000 down_read_trylock +EXPORT_SYMBOL vmlinux 0x00000000 down_timeout +EXPORT_SYMBOL vmlinux 0x00000000 down_trylock +EXPORT_SYMBOL vmlinux 0x00000000 down_write +EXPORT_SYMBOL vmlinux 0x00000000 down_write_trylock +EXPORT_SYMBOL vmlinux 0x00000000 downgrade_write +EXPORT_SYMBOL vmlinux 0x00000000 dput +EXPORT_SYMBOL vmlinux 0x00000000 drop_super +EXPORT_SYMBOL vmlinux 0x00000000 dst_alloc +EXPORT_SYMBOL vmlinux 0x00000000 dst_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dst_discard +EXPORT_SYMBOL vmlinux 0x00000000 dst_release +EXPORT_SYMBOL vmlinux 0x00000000 dump_fpu +EXPORT_SYMBOL vmlinux 0x00000000 dump_stack +EXPORT_SYMBOL vmlinux 0x00000000 elevator_exit +EXPORT_SYMBOL vmlinux 0x00000000 elevator_init +EXPORT_SYMBOL vmlinux 0x00000000 elf_hwcap +EXPORT_SYMBOL vmlinux 0x00000000 elf_platform +EXPORT_SYMBOL vmlinux 0x00000000 elv_add_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_dequeue_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0x00000000 elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0x00000000 elv_next_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_queue_empty +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_add +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_del +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_find +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_former_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0x00000000 empty_zero_page +EXPORT_SYMBOL vmlinux 0x00000000 enable_hlt +EXPORT_SYMBOL vmlinux 0x00000000 enable_irq +EXPORT_SYMBOL vmlinux 0x00000000 end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0x00000000 end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0x00000000 end_dequeued_request +EXPORT_SYMBOL vmlinux 0x00000000 end_page_writeback +EXPORT_SYMBOL vmlinux 0x00000000 end_queued_request +EXPORT_SYMBOL vmlinux 0x00000000 end_request +EXPORT_SYMBOL vmlinux 0x00000000 eth_header +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_cache +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_cache_update +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_parse +EXPORT_SYMBOL vmlinux 0x00000000 eth_rebuild_header +EXPORT_SYMBOL vmlinux 0x00000000 eth_type_trans +EXPORT_SYMBOL vmlinux 0x00000000 ether_setup +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_tx_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0x00000000 f_setown +EXPORT_SYMBOL vmlinux 0x00000000 fasync_helper +EXPORT_SYMBOL vmlinux 0x00000000 fb_add_videomode +EXPORT_SYMBOL vmlinux 0x00000000 fb_alloc_cmap +EXPORT_SYMBOL vmlinux 0x00000000 fb_blank +EXPORT_SYMBOL vmlinux 0x00000000 fb_class +EXPORT_SYMBOL vmlinux 0x00000000 fb_copy_cmap +EXPORT_SYMBOL vmlinux 0x00000000 fb_dealloc_cmap +EXPORT_SYMBOL vmlinux 0x00000000 fb_default_cmap +EXPORT_SYMBOL vmlinux 0x00000000 fb_destroy_modedb +EXPORT_SYMBOL vmlinux 0x00000000 fb_edid_to_monspecs +EXPORT_SYMBOL vmlinux 0x00000000 fb_find_best_display +EXPORT_SYMBOL vmlinux 0x00000000 fb_find_best_mode +EXPORT_SYMBOL vmlinux 0x00000000 fb_find_mode +EXPORT_SYMBOL vmlinux 0x00000000 fb_find_nearest_mode +EXPORT_SYMBOL vmlinux 0x00000000 fb_firmware_edid +EXPORT_SYMBOL vmlinux 0x00000000 fb_get_buffer_offset +EXPORT_SYMBOL vmlinux 0x00000000 fb_get_color_depth +EXPORT_SYMBOL vmlinux 0x00000000 fb_get_mode +EXPORT_SYMBOL vmlinux 0x00000000 fb_get_options +EXPORT_SYMBOL vmlinux 0x00000000 fb_invert_cmaps +EXPORT_SYMBOL vmlinux 0x00000000 fb_match_mode +EXPORT_SYMBOL vmlinux 0x00000000 fb_mode_is_equal +EXPORT_SYMBOL vmlinux 0x00000000 fb_pad_aligned_buffer +EXPORT_SYMBOL vmlinux 0x00000000 fb_pad_unaligned_buffer +EXPORT_SYMBOL vmlinux 0x00000000 fb_pan_display +EXPORT_SYMBOL vmlinux 0x00000000 fb_parse_edid +EXPORT_SYMBOL vmlinux 0x00000000 fb_register_client +EXPORT_SYMBOL vmlinux 0x00000000 fb_set_cmap +EXPORT_SYMBOL vmlinux 0x00000000 fb_set_suspend +EXPORT_SYMBOL vmlinux 0x00000000 fb_set_var +EXPORT_SYMBOL vmlinux 0x00000000 fb_show_logo +EXPORT_SYMBOL vmlinux 0x00000000 fb_unregister_client +EXPORT_SYMBOL vmlinux 0x00000000 fb_validate_mode +EXPORT_SYMBOL vmlinux 0x00000000 fb_var_to_videomode +EXPORT_SYMBOL vmlinux 0x00000000 fb_videomode_to_modelist +EXPORT_SYMBOL vmlinux 0x00000000 fb_videomode_to_var +EXPORT_SYMBOL vmlinux 0x00000000 fbcon_set_bitops +EXPORT_SYMBOL vmlinux 0x00000000 fd_install +EXPORT_SYMBOL vmlinux 0x00000000 fg_console +EXPORT_SYMBOL vmlinux 0x00000000 fget +EXPORT_SYMBOL vmlinux 0x00000000 file_fsync +EXPORT_SYMBOL vmlinux 0x00000000 file_permission +EXPORT_SYMBOL vmlinux 0x00000000 file_remove_suid +EXPORT_SYMBOL vmlinux 0x00000000 file_update_time +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fault +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawait +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0x00000000 filemap_flush +EXPORT_SYMBOL vmlinux 0x00000000 filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0x00000000 filp_close +EXPORT_SYMBOL vmlinux 0x00000000 filp_open +EXPORT_SYMBOL vmlinux 0x00000000 find_font +EXPORT_SYMBOL vmlinux 0x00000000 find_get_page +EXPORT_SYMBOL vmlinux 0x00000000 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0x00000000 find_get_pages_tag +EXPORT_SYMBOL vmlinux 0x00000000 find_inode_number +EXPORT_SYMBOL vmlinux 0x00000000 find_lock_page +EXPORT_SYMBOL vmlinux 0x00000000 find_or_create_page +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_vpid +EXPORT_SYMBOL vmlinux 0x00000000 find_vma +EXPORT_SYMBOL vmlinux 0x00000000 finish_wait +EXPORT_SYMBOL vmlinux 0x00000000 flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0x00000000 flow_cache_genid +EXPORT_SYMBOL vmlinux 0x00000000 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x00000000 flush_dcache_page +EXPORT_SYMBOL vmlinux 0x00000000 flush_old_exec +EXPORT_SYMBOL vmlinux 0x00000000 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x00000000 flush_signals +EXPORT_SYMBOL vmlinux 0x00000000 follow_down +EXPORT_SYMBOL vmlinux 0x00000000 follow_up +EXPORT_SYMBOL vmlinux 0x00000000 force_sig +EXPORT_SYMBOL vmlinux 0x00000000 fp_printk +EXPORT_SYMBOL vmlinux 0x00000000 fp_send_sig +EXPORT_SYMBOL vmlinux 0x00000000 fput +EXPORT_SYMBOL vmlinux 0x00000000 framebuffer_alloc +EXPORT_SYMBOL vmlinux 0x00000000 framebuffer_release +EXPORT_SYMBOL vmlinux 0x00000000 free_buffer_head +EXPORT_SYMBOL vmlinux 0x00000000 free_irq +EXPORT_SYMBOL vmlinux 0x00000000 free_netdev +EXPORT_SYMBOL vmlinux 0x00000000 free_pages +EXPORT_SYMBOL vmlinux 0x00000000 free_pages_exact +EXPORT_SYMBOL vmlinux 0x00000000 free_task +EXPORT_SYMBOL vmlinux 0x00000000 freeze_bdev +EXPORT_SYMBOL vmlinux 0x00000000 fs_overflowgid +EXPORT_SYMBOL vmlinux 0x00000000 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x00000000 fsync_bdev +EXPORT_SYMBOL vmlinux 0x00000000 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0x00000000 gen_new_estimator +EXPORT_SYMBOL vmlinux 0x00000000 gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x00000000 generate_random_uuid +EXPORT_SYMBOL vmlinux 0x00000000 generic_block_bmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0x00000000 generic_delete_inode +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_read +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_direct_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_llseek +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_mmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_open +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_read +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0x00000000 generic_fillattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_getxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_listxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_make_request +EXPORT_SYMBOL vmlinux 0x00000000 generic_mii_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 generic_osync_inode +EXPORT_SYMBOL vmlinux 0x00000000 generic_permission +EXPORT_SYMBOL vmlinux 0x00000000 generic_read_dir +EXPORT_SYMBOL vmlinux 0x00000000 generic_readlink +EXPORT_SYMBOL vmlinux 0x00000000 generic_removexattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_ro_fops +EXPORT_SYMBOL vmlinux 0x00000000 generic_segment_checks +EXPORT_SYMBOL vmlinux 0x00000000 generic_setlease +EXPORT_SYMBOL vmlinux 0x00000000 generic_setxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_show_options +EXPORT_SYMBOL vmlinux 0x00000000 generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x00000000 generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 generic_unplug_device +EXPORT_SYMBOL vmlinux 0x00000000 generic_write_checks +EXPORT_SYMBOL vmlinux 0x00000000 generic_write_end +EXPORT_SYMBOL vmlinux 0x00000000 generic_writepages +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_family +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_ops +EXPORT_SYMBOL vmlinux 0x00000000 genl_sock +EXPORT_SYMBOL vmlinux 0x00000000 genl_unregister_family +EXPORT_SYMBOL vmlinux 0x00000000 genl_unregister_ops +EXPORT_SYMBOL vmlinux 0x00000000 get_default_font +EXPORT_SYMBOL vmlinux 0x00000000 get_disk +EXPORT_SYMBOL vmlinux 0x00000000 get_empty_filp +EXPORT_SYMBOL vmlinux 0x00000000 get_fs_type +EXPORT_SYMBOL vmlinux 0x00000000 get_io_context +EXPORT_SYMBOL vmlinux 0x00000000 get_jiffies_64 +EXPORT_SYMBOL vmlinux 0x00000000 get_nfs_grace_period +EXPORT_SYMBOL vmlinux 0x00000000 get_option +EXPORT_SYMBOL vmlinux 0x00000000 get_options +EXPORT_SYMBOL vmlinux 0x00000000 get_random_bytes +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_bdev +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_nodev +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_single +EXPORT_SYMBOL vmlinux 0x00000000 get_seconds +EXPORT_SYMBOL vmlinux 0x00000000 get_super +EXPORT_SYMBOL vmlinux 0x00000000 get_unmapped_area +EXPORT_SYMBOL vmlinux 0x00000000 get_unused_fd +EXPORT_SYMBOL vmlinux 0x00000000 get_user_pages +EXPORT_SYMBOL vmlinux 0x00000000 get_write_access +EXPORT_SYMBOL vmlinux 0x00000000 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x00000000 getname +EXPORT_SYMBOL vmlinux 0x00000000 getnstimeofday +EXPORT_SYMBOL vmlinux 0x00000000 give_up_console +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x00000000 grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0x00000000 groups_alloc +EXPORT_SYMBOL vmlinux 0x00000000 groups_free +EXPORT_SYMBOL vmlinux 0x00000000 half_md4_transform +EXPORT_SYMBOL vmlinux 0x00000000 handle_sysrq +EXPORT_SYMBOL vmlinux 0x00000000 have_submounts +EXPORT_SYMBOL vmlinux 0x00000000 hex_asc +EXPORT_SYMBOL vmlinux 0x00000000 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x00000000 high_memory +EXPORT_SYMBOL vmlinux 0x00000000 hweight16 +EXPORT_SYMBOL vmlinux 0x00000000 hweight32 +EXPORT_SYMBOL vmlinux 0x00000000 hweight64 +EXPORT_SYMBOL vmlinux 0x00000000 hweight8 +EXPORT_SYMBOL vmlinux 0x00000000 i2c_add_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_attach_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_bit_add_bus +EXPORT_SYMBOL vmlinux 0x00000000 i2c_bit_add_numbered_bus +EXPORT_SYMBOL vmlinux 0x00000000 i2c_clients_command +EXPORT_SYMBOL vmlinux 0x00000000 i2c_del_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_del_driver +EXPORT_SYMBOL vmlinux 0x00000000 i2c_detach_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_get_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_master_recv +EXPORT_SYMBOL vmlinux 0x00000000 i2c_master_send +EXPORT_SYMBOL vmlinux 0x00000000 i2c_probe +EXPORT_SYMBOL vmlinux 0x00000000 i2c_put_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 i2c_release_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_byte +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_byte_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_word_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_byte +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_byte_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_word_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_xfer +EXPORT_SYMBOL vmlinux 0x00000000 i2c_transfer +EXPORT_SYMBOL vmlinux 0x00000000 i2c_use_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_verify_client +EXPORT_SYMBOL vmlinux 0x00000000 icmp_err_convert +EXPORT_SYMBOL vmlinux 0x00000000 icmp_send +EXPORT_SYMBOL vmlinux 0x00000000 icst307_khz +EXPORT_SYMBOL vmlinux 0x00000000 icst307_khz_to_vco +EXPORT_SYMBOL vmlinux 0x00000000 icst307_ps_to_vco +EXPORT_SYMBOL vmlinux 0x00000000 ida_destroy +EXPORT_SYMBOL vmlinux 0x00000000 ida_get_new +EXPORT_SYMBOL vmlinux 0x00000000 ida_get_new_above +EXPORT_SYMBOL vmlinux 0x00000000 ida_init +EXPORT_SYMBOL vmlinux 0x00000000 ida_pre_get +EXPORT_SYMBOL vmlinux 0x00000000 ida_remove +EXPORT_SYMBOL vmlinux 0x00000000 idr_destroy +EXPORT_SYMBOL vmlinux 0x00000000 idr_find +EXPORT_SYMBOL vmlinux 0x00000000 idr_for_each +EXPORT_SYMBOL vmlinux 0x00000000 idr_get_new +EXPORT_SYMBOL vmlinux 0x00000000 idr_get_new_above +EXPORT_SYMBOL vmlinux 0x00000000 idr_init +EXPORT_SYMBOL vmlinux 0x00000000 idr_pre_get +EXPORT_SYMBOL vmlinux 0x00000000 idr_remove +EXPORT_SYMBOL vmlinux 0x00000000 idr_remove_all +EXPORT_SYMBOL vmlinux 0x00000000 idr_replace +EXPORT_SYMBOL vmlinux 0x00000000 ifla_policy +EXPORT_SYMBOL vmlinux 0x00000000 iget5_locked +EXPORT_SYMBOL vmlinux 0x00000000 iget_failed +EXPORT_SYMBOL vmlinux 0x00000000 iget_locked +EXPORT_SYMBOL vmlinux 0x00000000 igrab +EXPORT_SYMBOL vmlinux 0x00000000 ilookup +EXPORT_SYMBOL vmlinux 0x00000000 ilookup5 +EXPORT_SYMBOL vmlinux 0x00000000 ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x00000000 in4_pton +EXPORT_SYMBOL vmlinux 0x00000000 in6_pton +EXPORT_SYMBOL vmlinux 0x00000000 in_aton +EXPORT_SYMBOL vmlinux 0x00000000 in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x00000000 in_egroup_p +EXPORT_SYMBOL vmlinux 0x00000000 in_group_p +EXPORT_SYMBOL vmlinux 0x00000000 inet_accept +EXPORT_SYMBOL vmlinux 0x00000000 inet_add_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet_addr_type +EXPORT_SYMBOL vmlinux 0x00000000 inet_bind +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_accept +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x00000000 inet_del_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0x00000000 inet_dgram_connect +EXPORT_SYMBOL vmlinux 0x00000000 inet_dgram_ops +EXPORT_SYMBOL vmlinux 0x00000000 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_destroy +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_evictor +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_find +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_kill +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_fini +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_init +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x00000000 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x00000000 inet_getname +EXPORT_SYMBOL vmlinux 0x00000000 inet_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 inet_listen +EXPORT_SYMBOL vmlinux 0x00000000 inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0x00000000 inet_put_port +EXPORT_SYMBOL vmlinux 0x00000000 inet_register_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inet_release +EXPORT_SYMBOL vmlinux 0x00000000 inet_select_addr +EXPORT_SYMBOL vmlinux 0x00000000 inet_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 inet_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0x00000000 inet_sock_destruct +EXPORT_SYMBOL vmlinux 0x00000000 inet_stream_connect +EXPORT_SYMBOL vmlinux 0x00000000 inet_stream_ops +EXPORT_SYMBOL vmlinux 0x00000000 inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0x00000000 inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inetdev_by_index +EXPORT_SYMBOL vmlinux 0x00000000 init_buffer +EXPORT_SYMBOL vmlinux 0x00000000 init_file +EXPORT_SYMBOL vmlinux 0x00000000 init_mm +EXPORT_SYMBOL vmlinux 0x00000000 init_net +EXPORT_SYMBOL vmlinux 0x00000000 init_special_inode +EXPORT_SYMBOL vmlinux 0x00000000 init_task +EXPORT_SYMBOL vmlinux 0x00000000 init_timer +EXPORT_SYMBOL vmlinux 0x00000000 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0x00000000 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x00000000 inode_add_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_change_ok +EXPORT_SYMBOL vmlinux 0x00000000 inode_double_lock +EXPORT_SYMBOL vmlinux 0x00000000 inode_double_unlock +EXPORT_SYMBOL vmlinux 0x00000000 inode_get_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_init_once +EXPORT_SYMBOL vmlinux 0x00000000 inode_needs_sync +EXPORT_SYMBOL vmlinux 0x00000000 inode_permission +EXPORT_SYMBOL vmlinux 0x00000000 inode_set_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_setattr +EXPORT_SYMBOL vmlinux 0x00000000 inode_sub_bytes +EXPORT_SYMBOL vmlinux 0x00000000 input_allocate_device +EXPORT_SYMBOL vmlinux 0x00000000 input_close_device +EXPORT_SYMBOL vmlinux 0x00000000 input_event +EXPORT_SYMBOL vmlinux 0x00000000 input_flush_device +EXPORT_SYMBOL vmlinux 0x00000000 input_free_device +EXPORT_SYMBOL vmlinux 0x00000000 input_get_keycode +EXPORT_SYMBOL vmlinux 0x00000000 input_grab_device +EXPORT_SYMBOL vmlinux 0x00000000 input_inject_event +EXPORT_SYMBOL vmlinux 0x00000000 input_open_device +EXPORT_SYMBOL vmlinux 0x00000000 input_register_device +EXPORT_SYMBOL vmlinux 0x00000000 input_register_handle +EXPORT_SYMBOL vmlinux 0x00000000 input_register_handler +EXPORT_SYMBOL vmlinux 0x00000000 input_release_device +EXPORT_SYMBOL vmlinux 0x00000000 input_set_capability +EXPORT_SYMBOL vmlinux 0x00000000 input_set_keycode +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_device +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_handle +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_handler +EXPORT_SYMBOL vmlinux 0x00000000 int_sqrt +EXPORT_SYMBOL vmlinux 0x00000000 interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0x00000000 interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_bdev +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_inodes +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_partition +EXPORT_SYMBOL vmlinux 0x00000000 io_schedule +EXPORT_SYMBOL vmlinux 0x00000000 ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x00000000 iomem_resource +EXPORT_SYMBOL vmlinux 0x00000000 ioport_map +EXPORT_SYMBOL vmlinux 0x00000000 ioport_resource +EXPORT_SYMBOL vmlinux 0x00000000 ioport_unmap +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_advance +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0x00000000 iov_shorten +EXPORT_SYMBOL vmlinux 0x00000000 ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0x00000000 ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0x00000000 ip_defrag +EXPORT_SYMBOL vmlinux 0x00000000 ip_dev_find +EXPORT_SYMBOL vmlinux 0x00000000 ip_fragment +EXPORT_SYMBOL vmlinux 0x00000000 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0x00000000 ip_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_join_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0x00000000 ip_route_input +EXPORT_SYMBOL vmlinux 0x00000000 ip_route_output_key +EXPORT_SYMBOL vmlinux 0x00000000 ip_send_check +EXPORT_SYMBOL vmlinux 0x00000000 ip_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 iput +EXPORT_SYMBOL vmlinux 0x00000000 ipv4_config +EXPORT_SYMBOL vmlinux 0x00000000 ipv4_specific +EXPORT_SYMBOL vmlinux 0x00000000 irq_stat +EXPORT_SYMBOL vmlinux 0x00000000 is_bad_inode +EXPORT_SYMBOL vmlinux 0x00000000 is_container_init +EXPORT_SYMBOL vmlinux 0x00000000 iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0x00000000 iunique +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_get_spy +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_get_thrspy +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_set_spy +EXPORT_SYMBOL vmlinux 0x00000000 iw_handler_set_thrspy +EXPORT_SYMBOL vmlinux 0x00000000 jiffies +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_64 +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x00000000 kasprintf +EXPORT_SYMBOL vmlinux 0x00000000 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0x00000000 kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0x00000000 kd_mksound +EXPORT_SYMBOL vmlinux 0x00000000 kern_fp_enter +EXPORT_SYMBOL vmlinux 0x00000000 kernel_accept +EXPORT_SYMBOL vmlinux 0x00000000 kernel_bind +EXPORT_SYMBOL vmlinux 0x00000000 kernel_connect +EXPORT_SYMBOL vmlinux 0x00000000 kernel_execve +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getpeername +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getsockname +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 kernel_listen +EXPORT_SYMBOL vmlinux 0x00000000 kernel_read +EXPORT_SYMBOL vmlinux 0x00000000 kernel_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 kernel_thread +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_alloc +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_free +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_init +EXPORT_SYMBOL vmlinux 0x00000000 kfree +EXPORT_SYMBOL vmlinux 0x00000000 kfree_skb +EXPORT_SYMBOL vmlinux 0x00000000 kick_iocb +EXPORT_SYMBOL vmlinux 0x00000000 kill_anon_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_block_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_fasync +EXPORT_SYMBOL vmlinux 0x00000000 kill_litter_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_pgrp +EXPORT_SYMBOL vmlinux 0x00000000 kill_pid +EXPORT_SYMBOL vmlinux 0x00000000 km_new_mapping +EXPORT_SYMBOL vmlinux 0x00000000 km_policy_expired +EXPORT_SYMBOL vmlinux 0x00000000 km_policy_notify +EXPORT_SYMBOL vmlinux 0x00000000 km_query +EXPORT_SYMBOL vmlinux 0x00000000 km_report +EXPORT_SYMBOL vmlinux 0x00000000 km_state_expired +EXPORT_SYMBOL vmlinux 0x00000000 km_state_notify +EXPORT_SYMBOL vmlinux 0x00000000 km_waitq +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_create +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_free +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_size +EXPORT_SYMBOL vmlinux 0x00000000 kmemdup +EXPORT_SYMBOL vmlinux 0x00000000 kobject_add +EXPORT_SYMBOL vmlinux 0x00000000 kobject_del +EXPORT_SYMBOL vmlinux 0x00000000 kobject_get +EXPORT_SYMBOL vmlinux 0x00000000 kobject_init +EXPORT_SYMBOL vmlinux 0x00000000 kobject_put +EXPORT_SYMBOL vmlinux 0x00000000 kobject_set_name +EXPORT_SYMBOL vmlinux 0x00000000 krealloc +EXPORT_SYMBOL vmlinux 0x00000000 kref_get +EXPORT_SYMBOL vmlinux 0x00000000 kref_init +EXPORT_SYMBOL vmlinux 0x00000000 kref_put +EXPORT_SYMBOL vmlinux 0x00000000 kref_set +EXPORT_SYMBOL vmlinux 0x00000000 kset_register +EXPORT_SYMBOL vmlinux 0x00000000 kset_unregister +EXPORT_SYMBOL vmlinux 0x00000000 kstrdup +EXPORT_SYMBOL vmlinux 0x00000000 kstrndup +EXPORT_SYMBOL vmlinux 0x00000000 kthread_bind +EXPORT_SYMBOL vmlinux 0x00000000 kthread_create +EXPORT_SYMBOL vmlinux 0x00000000 kthread_should_stop +EXPORT_SYMBOL vmlinux 0x00000000 kthread_stop +EXPORT_SYMBOL vmlinux 0x00000000 kvasprintf +EXPORT_SYMBOL vmlinux 0x00000000 laptop_mode +EXPORT_SYMBOL vmlinux 0x00000000 lease_get_mtime +EXPORT_SYMBOL vmlinux 0x00000000 lease_modify +EXPORT_SYMBOL vmlinux 0x00000000 leds_event +EXPORT_SYMBOL vmlinux 0x00000000 linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0x00000000 ll_rw_block +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_disable +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_enable +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0x00000000 lock_may_read +EXPORT_SYMBOL vmlinux 0x00000000 lock_may_write +EXPORT_SYMBOL vmlinux 0x00000000 lock_rename +EXPORT_SYMBOL vmlinux 0x00000000 lock_sock_nested +EXPORT_SYMBOL vmlinux 0x00000000 lock_super +EXPORT_SYMBOL vmlinux 0x00000000 lockd_down +EXPORT_SYMBOL vmlinux 0x00000000 lockd_up +EXPORT_SYMBOL vmlinux 0x00000000 locks_copy_lock +EXPORT_SYMBOL vmlinux 0x00000000 locks_init_lock +EXPORT_SYMBOL vmlinux 0x00000000 locks_mandatory_area +EXPORT_SYMBOL vmlinux 0x00000000 locks_remove_posix +EXPORT_SYMBOL vmlinux 0x00000000 lookup_bdev +EXPORT_SYMBOL vmlinux 0x00000000 lookup_one_len +EXPORT_SYMBOL vmlinux 0x00000000 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0x00000000 make_bad_inode +EXPORT_SYMBOL vmlinux 0x00000000 malloc_sizes +EXPORT_SYMBOL vmlinux 0x00000000 map_destroy +EXPORT_SYMBOL vmlinux 0x00000000 mapping_tagged +EXPORT_SYMBOL vmlinux 0x00000000 maps_protect +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x00000000 mark_page_accessed +EXPORT_SYMBOL vmlinux 0x00000000 match_hex +EXPORT_SYMBOL vmlinux 0x00000000 match_int +EXPORT_SYMBOL vmlinux 0x00000000 match_octal +EXPORT_SYMBOL vmlinux 0x00000000 match_strdup +EXPORT_SYMBOL vmlinux 0x00000000 match_strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 match_token +EXPORT_SYMBOL vmlinux 0x00000000 max_mapnr +EXPORT_SYMBOL vmlinux 0x00000000 may_umount +EXPORT_SYMBOL vmlinux 0x00000000 may_umount_tree +EXPORT_SYMBOL vmlinux 0x00000000 mem_map +EXPORT_SYMBOL vmlinux 0x00000000 memchr +EXPORT_SYMBOL vmlinux 0x00000000 memcmp +EXPORT_SYMBOL vmlinux 0x00000000 memcpy +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x00000000 memmove +EXPORT_SYMBOL vmlinux 0x00000000 memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 memparse +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x00000000 mempool_create +EXPORT_SYMBOL vmlinux 0x00000000 mempool_create_node +EXPORT_SYMBOL vmlinux 0x00000000 mempool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free_pages +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kfree +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_resize +EXPORT_SYMBOL vmlinux 0x00000000 memscan +EXPORT_SYMBOL vmlinux 0x00000000 memset +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_gmii_support +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_link +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_media +EXPORT_SYMBOL vmlinux 0x00000000 mii_ethtool_gset +EXPORT_SYMBOL vmlinux 0x00000000 mii_ethtool_sset +EXPORT_SYMBOL vmlinux 0x00000000 mii_link_ok +EXPORT_SYMBOL vmlinux 0x00000000 mii_nway_restart +EXPORT_SYMBOL vmlinux 0x00000000 misc_deregister +EXPORT_SYMBOL vmlinux 0x00000000 misc_register +EXPORT_SYMBOL vmlinux 0x00000000 mktime +EXPORT_SYMBOL vmlinux 0x00000000 mmc_add_host +EXPORT_SYMBOL vmlinux 0x00000000 mmc_align_data_size +EXPORT_SYMBOL vmlinux 0x00000000 mmc_alloc_host +EXPORT_SYMBOL vmlinux 0x00000000 mmc_cleanup_queue +EXPORT_SYMBOL vmlinux 0x00000000 mmc_detect_change +EXPORT_SYMBOL vmlinux 0x00000000 mmc_free_host +EXPORT_SYMBOL vmlinux 0x00000000 mmc_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 mmc_release_host +EXPORT_SYMBOL vmlinux 0x00000000 mmc_remove_host +EXPORT_SYMBOL vmlinux 0x00000000 mmc_request_done +EXPORT_SYMBOL vmlinux 0x00000000 mmc_resume_host +EXPORT_SYMBOL vmlinux 0x00000000 mmc_set_data_timeout +EXPORT_SYMBOL vmlinux 0x00000000 mmc_suspend_host +EXPORT_SYMBOL vmlinux 0x00000000 mmc_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 mmc_wait_for_app_cmd +EXPORT_SYMBOL vmlinux 0x00000000 mmc_wait_for_cmd +EXPORT_SYMBOL vmlinux 0x00000000 mmc_wait_for_req +EXPORT_SYMBOL vmlinux 0x00000000 mnt_pin +EXPORT_SYMBOL vmlinux 0x00000000 mnt_unpin +EXPORT_SYMBOL vmlinux 0x00000000 mntput_no_expire +EXPORT_SYMBOL vmlinux 0x00000000 mod_timer +EXPORT_SYMBOL vmlinux 0x00000000 module_put +EXPORT_SYMBOL vmlinux 0x00000000 module_refcount +EXPORT_SYMBOL vmlinux 0x00000000 mpage_bio_submit +EXPORT_SYMBOL vmlinux 0x00000000 mpage_readpage +EXPORT_SYMBOL vmlinux 0x00000000 mpage_readpages +EXPORT_SYMBOL vmlinux 0x00000000 mpage_writepage +EXPORT_SYMBOL vmlinux 0x00000000 mpage_writepages +EXPORT_SYMBOL vmlinux 0x00000000 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 msleep +EXPORT_SYMBOL vmlinux 0x00000000 msleep_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 mtd_do_chip_probe +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock_killable +EXPORT_SYMBOL vmlinux 0x00000000 mutex_trylock +EXPORT_SYMBOL vmlinux 0x00000000 mutex_unlock +EXPORT_SYMBOL vmlinux 0x00000000 n_tty_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 names_cachep +EXPORT_SYMBOL vmlinux 0x00000000 neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x00000000 neigh_compat_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_connected_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_create +EXPORT_SYMBOL vmlinux 0x00000000 neigh_destroy +EXPORT_SYMBOL vmlinux 0x00000000 neigh_event_ns +EXPORT_SYMBOL vmlinux 0x00000000 neigh_for_each +EXPORT_SYMBOL vmlinux 0x00000000 neigh_ifdown +EXPORT_SYMBOL vmlinux 0x00000000 neigh_lookup +EXPORT_SYMBOL vmlinux 0x00000000 neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x00000000 neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0x00000000 neigh_parms_release +EXPORT_SYMBOL vmlinux 0x00000000 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x00000000 neigh_resolve_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_next +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_start +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_stop +EXPORT_SYMBOL vmlinux 0x00000000 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0x00000000 neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_clear +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_init +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0x00000000 neigh_update +EXPORT_SYMBOL vmlinux 0x00000000 net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 net_msg_warn +EXPORT_SYMBOL vmlinux 0x00000000 net_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0x00000000 netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0x00000000 netdev_class_create_file +EXPORT_SYMBOL vmlinux 0x00000000 netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0x00000000 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x00000000 netdev_features_change +EXPORT_SYMBOL vmlinux 0x00000000 netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0x00000000 netdev_set_master +EXPORT_SYMBOL vmlinux 0x00000000 netdev_state_change +EXPORT_SYMBOL vmlinux 0x00000000 netif_carrier_off +EXPORT_SYMBOL vmlinux 0x00000000 netif_carrier_on +EXPORT_SYMBOL vmlinux 0x00000000 netif_device_attach +EXPORT_SYMBOL vmlinux 0x00000000 netif_device_detach +EXPORT_SYMBOL vmlinux 0x00000000 netif_receive_skb +EXPORT_SYMBOL vmlinux 0x00000000 netif_rx +EXPORT_SYMBOL vmlinux 0x00000000 netif_rx_ni +EXPORT_SYMBOL vmlinux 0x00000000 netlink_ack +EXPORT_SYMBOL vmlinux 0x00000000 netlink_broadcast +EXPORT_SYMBOL vmlinux 0x00000000 netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0x00000000 netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0x00000000 netlink_dump_start +EXPORT_SYMBOL vmlinux 0x00000000 netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x00000000 netlink_kernel_release +EXPORT_SYMBOL vmlinux 0x00000000 netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0x00000000 netlink_register_notifier +EXPORT_SYMBOL vmlinux 0x00000000 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x00000000 netlink_unicast +EXPORT_SYMBOL vmlinux 0x00000000 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0x00000000 new_inode +EXPORT_SYMBOL vmlinux 0x00000000 nla_append +EXPORT_SYMBOL vmlinux 0x00000000 nla_find +EXPORT_SYMBOL vmlinux 0x00000000 nla_memcmp +EXPORT_SYMBOL vmlinux 0x00000000 nla_memcpy +EXPORT_SYMBOL vmlinux 0x00000000 nla_parse +EXPORT_SYMBOL vmlinux 0x00000000 nla_put +EXPORT_SYMBOL vmlinux 0x00000000 nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 nla_reserve +EXPORT_SYMBOL vmlinux 0x00000000 nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 nla_strcmp +EXPORT_SYMBOL vmlinux 0x00000000 nla_strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 nla_validate +EXPORT_SYMBOL vmlinux 0x00000000 nlmsg_notify +EXPORT_SYMBOL vmlinux 0x00000000 nlmsvc_ops +EXPORT_SYMBOL vmlinux 0x00000000 no_llseek +EXPORT_SYMBOL vmlinux 0x00000000 nobh_truncate_page +EXPORT_SYMBOL vmlinux 0x00000000 nobh_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 nobh_write_end +EXPORT_SYMBOL vmlinux 0x00000000 nobh_writepage +EXPORT_SYMBOL vmlinux 0x00000000 node_states +EXPORT_SYMBOL vmlinux 0x00000000 nonseekable_open +EXPORT_SYMBOL vmlinux 0x00000000 noop_qdisc +EXPORT_SYMBOL vmlinux 0x00000000 notify_change +EXPORT_SYMBOL vmlinux 0x00000000 ns_to_timespec +EXPORT_SYMBOL vmlinux 0x00000000 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x00000000 num_physpages +EXPORT_SYMBOL vmlinux 0x00000000 num_registered_fb +EXPORT_SYMBOL vmlinux 0x00000000 oops_in_progress +EXPORT_SYMBOL vmlinux 0x00000000 open_bdev_excl +EXPORT_SYMBOL vmlinux 0x00000000 open_by_devnum +EXPORT_SYMBOL vmlinux 0x00000000 open_exec +EXPORT_SYMBOL vmlinux 0x00000000 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0x00000000 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0x00000000 overflowgid +EXPORT_SYMBOL vmlinux 0x00000000 overflowuid +EXPORT_SYMBOL vmlinux 0x00000000 page_follow_link_light +EXPORT_SYMBOL vmlinux 0x00000000 page_put_link +EXPORT_SYMBOL vmlinux 0x00000000 page_readlink +EXPORT_SYMBOL vmlinux 0x00000000 page_symlink +EXPORT_SYMBOL vmlinux 0x00000000 page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0x00000000 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0x00000000 pagecache_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 pagecache_write_end +EXPORT_SYMBOL vmlinux 0x00000000 pagevec_lookup +EXPORT_SYMBOL vmlinux 0x00000000 pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0x00000000 panic +EXPORT_SYMBOL vmlinux 0x00000000 panic_blink +EXPORT_SYMBOL vmlinux 0x00000000 panic_notifier_list +EXPORT_SYMBOL vmlinux 0x00000000 param_array_get +EXPORT_SYMBOL vmlinux 0x00000000 param_array_set +EXPORT_SYMBOL vmlinux 0x00000000 param_get_bool +EXPORT_SYMBOL vmlinux 0x00000000 param_get_byte +EXPORT_SYMBOL vmlinux 0x00000000 param_get_charp +EXPORT_SYMBOL vmlinux 0x00000000 param_get_int +EXPORT_SYMBOL vmlinux 0x00000000 param_get_invbool +EXPORT_SYMBOL vmlinux 0x00000000 param_get_long +EXPORT_SYMBOL vmlinux 0x00000000 param_get_short +EXPORT_SYMBOL vmlinux 0x00000000 param_get_string +EXPORT_SYMBOL vmlinux 0x00000000 param_get_uint +EXPORT_SYMBOL vmlinux 0x00000000 param_get_ulong +EXPORT_SYMBOL vmlinux 0x00000000 param_get_ushort +EXPORT_SYMBOL vmlinux 0x00000000 param_set_bool +EXPORT_SYMBOL vmlinux 0x00000000 param_set_byte +EXPORT_SYMBOL vmlinux 0x00000000 param_set_charp +EXPORT_SYMBOL vmlinux 0x00000000 param_set_copystring +EXPORT_SYMBOL vmlinux 0x00000000 param_set_int +EXPORT_SYMBOL vmlinux 0x00000000 param_set_invbool +EXPORT_SYMBOL vmlinux 0x00000000 param_set_long +EXPORT_SYMBOL vmlinux 0x00000000 param_set_short +EXPORT_SYMBOL vmlinux 0x00000000 param_set_uint +EXPORT_SYMBOL vmlinux 0x00000000 param_set_ulong +EXPORT_SYMBOL vmlinux 0x00000000 param_set_ushort +EXPORT_SYMBOL vmlinux 0x00000000 path_get +EXPORT_SYMBOL vmlinux 0x00000000 path_lookup +EXPORT_SYMBOL vmlinux 0x00000000 path_permission +EXPORT_SYMBOL vmlinux 0x00000000 path_put +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu____irq_regs +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x00000000 pgprot_kernel +EXPORT_SYMBOL vmlinux 0x00000000 pgprot_user +EXPORT_SYMBOL vmlinux 0x00000000 pid_task +EXPORT_SYMBOL vmlinux 0x00000000 pm_flags +EXPORT_SYMBOL vmlinux 0x00000000 pm_idle +EXPORT_SYMBOL vmlinux 0x00000000 pm_power_off +EXPORT_SYMBOL vmlinux 0x00000000 pm_set_vt_switch +EXPORT_SYMBOL vmlinux 0x00000000 pm_suspend +EXPORT_SYMBOL vmlinux 0x00000000 pneigh_enqueue +EXPORT_SYMBOL vmlinux 0x00000000 pneigh_lookup +EXPORT_SYMBOL vmlinux 0x00000000 poll_freewait +EXPORT_SYMBOL vmlinux 0x00000000 poll_initwait +EXPORT_SYMBOL vmlinux 0x00000000 posix_lock_file +EXPORT_SYMBOL vmlinux 0x00000000 posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0x00000000 posix_test_lock +EXPORT_SYMBOL vmlinux 0x00000000 posix_unblock_lock +EXPORT_SYMBOL vmlinux 0x00000000 prepare_binprm +EXPORT_SYMBOL vmlinux 0x00000000 prepare_to_wait +EXPORT_SYMBOL vmlinux 0x00000000 prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0x00000000 print_hex_dump +EXPORT_SYMBOL vmlinux 0x00000000 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x00000000 print_mac +EXPORT_SYMBOL vmlinux 0x00000000 printk +EXPORT_SYMBOL vmlinux 0x00000000 printk_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_mask +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_off +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_on +EXPORT_SYMBOL vmlinux 0x00000000 proc_create_data +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dostring +EXPORT_SYMBOL vmlinux 0x00000000 proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_mkdir +EXPORT_SYMBOL vmlinux 0x00000000 proc_symlink +EXPORT_SYMBOL vmlinux 0x00000000 processor_id +EXPORT_SYMBOL vmlinux 0x00000000 proto_register +EXPORT_SYMBOL vmlinux 0x00000000 proto_unregister +EXPORT_SYMBOL vmlinux 0x00000000 ps2_cmd_aborted +EXPORT_SYMBOL vmlinux 0x00000000 ps2_command +EXPORT_SYMBOL vmlinux 0x00000000 ps2_drain +EXPORT_SYMBOL vmlinux 0x00000000 ps2_handle_ack +EXPORT_SYMBOL vmlinux 0x00000000 ps2_handle_response +EXPORT_SYMBOL vmlinux 0x00000000 ps2_init +EXPORT_SYMBOL vmlinux 0x00000000 ps2_is_keyboard_id +EXPORT_SYMBOL vmlinux 0x00000000 ps2_sendbyte +EXPORT_SYMBOL vmlinux 0x00000000 pskb_copy +EXPORT_SYMBOL vmlinux 0x00000000 pskb_expand_head +EXPORT_SYMBOL vmlinux 0x00000000 put_cmsg +EXPORT_SYMBOL vmlinux 0x00000000 put_disk +EXPORT_SYMBOL vmlinux 0x00000000 put_filp +EXPORT_SYMBOL vmlinux 0x00000000 put_io_context +EXPORT_SYMBOL vmlinux 0x00000000 put_page +EXPORT_SYMBOL vmlinux 0x00000000 put_pages_list +EXPORT_SYMBOL vmlinux 0x00000000 put_tty_driver +EXPORT_SYMBOL vmlinux 0x00000000 put_unused_fd +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_destroy +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_reset +EXPORT_SYMBOL vmlinux 0x00000000 qword_add +EXPORT_SYMBOL vmlinux 0x00000000 qword_addhex +EXPORT_SYMBOL vmlinux 0x00000000 qword_get +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_delete +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_insert +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tagged +EXPORT_SYMBOL vmlinux 0x00000000 random32 +EXPORT_SYMBOL vmlinux 0x00000000 rb_erase +EXPORT_SYMBOL vmlinux 0x00000000 rb_first +EXPORT_SYMBOL vmlinux 0x00000000 rb_insert_color +EXPORT_SYMBOL vmlinux 0x00000000 rb_last +EXPORT_SYMBOL vmlinux 0x00000000 rb_next +EXPORT_SYMBOL vmlinux 0x00000000 rb_prev +EXPORT_SYMBOL vmlinux 0x00000000 rb_replace_node +EXPORT_SYMBOL vmlinux 0x00000000 read_bytes_from_xdr_buf +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_page +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_page_async +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_pages +EXPORT_SYMBOL vmlinux 0x00000000 read_dev_sector +EXPORT_SYMBOL vmlinux 0x00000000 recalc_sigpending +EXPORT_SYMBOL vmlinux 0x00000000 redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0x00000000 redraw_screen +EXPORT_SYMBOL vmlinux 0x00000000 refrigerator +EXPORT_SYMBOL vmlinux 0x00000000 register_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 register_blkdev +EXPORT_SYMBOL vmlinux 0x00000000 register_chrdev +EXPORT_SYMBOL vmlinux 0x00000000 register_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 register_con_driver +EXPORT_SYMBOL vmlinux 0x00000000 register_console +EXPORT_SYMBOL vmlinux 0x00000000 register_exec_domain +EXPORT_SYMBOL vmlinux 0x00000000 register_filesystem +EXPORT_SYMBOL vmlinux 0x00000000 register_framebuffer +EXPORT_SYMBOL vmlinux 0x00000000 register_gifconf +EXPORT_SYMBOL vmlinux 0x00000000 register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_module_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x00000000 register_netdev +EXPORT_SYMBOL vmlinux 0x00000000 register_netdevice +EXPORT_SYMBOL vmlinux 0x00000000 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_shrinker +EXPORT_SYMBOL vmlinux 0x00000000 register_sound_dsp +EXPORT_SYMBOL vmlinux 0x00000000 register_sound_midi +EXPORT_SYMBOL vmlinux 0x00000000 register_sound_mixer +EXPORT_SYMBOL vmlinux 0x00000000 register_sound_special +EXPORT_SYMBOL vmlinux 0x00000000 register_sound_special_device +EXPORT_SYMBOL vmlinux 0x00000000 register_sysctl_paths +EXPORT_SYMBOL vmlinux 0x00000000 register_sysctl_table +EXPORT_SYMBOL vmlinux 0x00000000 register_sysrq_key +EXPORT_SYMBOL vmlinux 0x00000000 registered_fb +EXPORT_SYMBOL vmlinux 0x00000000 release_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 release_firmware +EXPORT_SYMBOL vmlinux 0x00000000 release_resource +EXPORT_SYMBOL vmlinux 0x00000000 release_sock +EXPORT_SYMBOL vmlinux 0x00000000 remap_pfn_range +EXPORT_SYMBOL vmlinux 0x00000000 remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0x00000000 remove_arg_zero +EXPORT_SYMBOL vmlinux 0x00000000 remove_inode_hash +EXPORT_SYMBOL vmlinux 0x00000000 remove_proc_entry +EXPORT_SYMBOL vmlinux 0x00000000 remove_wait_queue +EXPORT_SYMBOL vmlinux 0x00000000 request_firmware +EXPORT_SYMBOL vmlinux 0x00000000 request_firmware_nowait +EXPORT_SYMBOL vmlinux 0x00000000 request_irq +EXPORT_SYMBOL vmlinux 0x00000000 request_module +EXPORT_SYMBOL vmlinux 0x00000000 request_resource +EXPORT_SYMBOL vmlinux 0x00000000 reset_devices +EXPORT_SYMBOL vmlinux 0x00000000 restore_time_delta +EXPORT_SYMBOL vmlinux 0x00000000 rpc_mkpipe +EXPORT_SYMBOL vmlinux 0x00000000 rpc_queue_upcall +EXPORT_SYMBOL vmlinux 0x00000000 rpc_unlink +EXPORT_SYMBOL vmlinux 0x00000000 rtc_month_days +EXPORT_SYMBOL vmlinux 0x00000000 rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0x00000000 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0x00000000 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x00000000 rtc_year_days +EXPORT_SYMBOL vmlinux 0x00000000 rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_create_link +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_lock +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_notify +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_trylock +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_unicast +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x00000000 save_mount_options +EXPORT_SYMBOL vmlinux 0x00000000 save_time_delta +EXPORT_SYMBOL vmlinux 0x00000000 sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0x00000000 sb_min_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 sb_set_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 schedule +EXPORT_SYMBOL vmlinux 0x00000000 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x00000000 schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0x00000000 schedule_work +EXPORT_SYMBOL vmlinux 0x00000000 schedule_work_on +EXPORT_SYMBOL vmlinux 0x00000000 scm_detach_fds +EXPORT_SYMBOL vmlinux 0x00000000 scm_fp_dup +EXPORT_SYMBOL vmlinux 0x00000000 scnprintf +EXPORT_SYMBOL vmlinux 0x00000000 scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x00000000 search_binary_handler +EXPORT_SYMBOL vmlinux 0x00000000 secpath_dup +EXPORT_SYMBOL vmlinux 0x00000000 send_sig +EXPORT_SYMBOL vmlinux 0x00000000 send_sig_info +EXPORT_SYMBOL vmlinux 0x00000000 seq_escape +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_next +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_start +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_start_head +EXPORT_SYMBOL vmlinux 0x00000000 seq_lseek +EXPORT_SYMBOL vmlinux 0x00000000 seq_open +EXPORT_SYMBOL vmlinux 0x00000000 seq_open_private +EXPORT_SYMBOL vmlinux 0x00000000 seq_path +EXPORT_SYMBOL vmlinux 0x00000000 seq_printf +EXPORT_SYMBOL vmlinux 0x00000000 seq_putc +EXPORT_SYMBOL vmlinux 0x00000000 seq_puts +EXPORT_SYMBOL vmlinux 0x00000000 seq_read +EXPORT_SYMBOL vmlinux 0x00000000 seq_release +EXPORT_SYMBOL vmlinux 0x00000000 seq_release_private +EXPORT_SYMBOL vmlinux 0x00000000 serio_close +EXPORT_SYMBOL vmlinux 0x00000000 serio_interrupt +EXPORT_SYMBOL vmlinux 0x00000000 serio_open +EXPORT_SYMBOL vmlinux 0x00000000 serio_reconnect +EXPORT_SYMBOL vmlinux 0x00000000 serio_rescan +EXPORT_SYMBOL vmlinux 0x00000000 serio_unregister_child_port +EXPORT_SYMBOL vmlinux 0x00000000 serio_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 serio_unregister_port +EXPORT_SYMBOL vmlinux 0x00000000 set_anon_super +EXPORT_SYMBOL vmlinux 0x00000000 set_bdi_congested +EXPORT_SYMBOL vmlinux 0x00000000 set_bh_page +EXPORT_SYMBOL vmlinux 0x00000000 set_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 set_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 set_current_groups +EXPORT_SYMBOL vmlinux 0x00000000 set_device_ro +EXPORT_SYMBOL vmlinux 0x00000000 set_disk_ro +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_chip +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_data +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_type +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_wake +EXPORT_SYMBOL vmlinux 0x00000000 set_normalized_timespec +EXPORT_SYMBOL vmlinux 0x00000000 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x00000000 set_page_dirty +EXPORT_SYMBOL vmlinux 0x00000000 set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x00000000 set_user_nice +EXPORT_SYMBOL vmlinux 0x00000000 setup_arg_pages +EXPORT_SYMBOL vmlinux 0x00000000 sg_alloc_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sg_free_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_init_one +EXPORT_SYMBOL vmlinux 0x00000000 sg_init_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_last +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_next +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_start +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_stop +EXPORT_SYMBOL vmlinux 0x00000000 sg_next +EXPORT_SYMBOL vmlinux 0x00000000 sget +EXPORT_SYMBOL vmlinux 0x00000000 sha_transform +EXPORT_SYMBOL vmlinux 0x00000000 should_remove_suid +EXPORT_SYMBOL vmlinux 0x00000000 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0x00000000 shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0x00000000 si_meminfo +EXPORT_SYMBOL vmlinux 0x00000000 sigprocmask +EXPORT_SYMBOL vmlinux 0x00000000 simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x00000000 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x00000000 simple_empty +EXPORT_SYMBOL vmlinux 0x00000000 simple_fill_super +EXPORT_SYMBOL vmlinux 0x00000000 simple_getattr +EXPORT_SYMBOL vmlinux 0x00000000 simple_link +EXPORT_SYMBOL vmlinux 0x00000000 simple_lookup +EXPORT_SYMBOL vmlinux 0x00000000 simple_pin_fs +EXPORT_SYMBOL vmlinux 0x00000000 simple_prepare_write +EXPORT_SYMBOL vmlinux 0x00000000 simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 simple_readpage +EXPORT_SYMBOL vmlinux 0x00000000 simple_release_fs +EXPORT_SYMBOL vmlinux 0x00000000 simple_rename +EXPORT_SYMBOL vmlinux 0x00000000 simple_rmdir +EXPORT_SYMBOL vmlinux 0x00000000 simple_set_mnt +EXPORT_SYMBOL vmlinux 0x00000000 simple_statfs +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtol +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtoul +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtoull +EXPORT_SYMBOL vmlinux 0x00000000 simple_sync_file +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_get +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_read +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_release +EXPORT_SYMBOL vmlinux 0x00000000 simple_unlink +EXPORT_SYMBOL vmlinux 0x00000000 simple_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 simple_write_end +EXPORT_SYMBOL vmlinux 0x00000000 single_open +EXPORT_SYMBOL vmlinux 0x00000000 single_release +EXPORT_SYMBOL vmlinux 0x00000000 sk_alloc +EXPORT_SYMBOL vmlinux 0x00000000 sk_chk_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_common_release +EXPORT_SYMBOL vmlinux 0x00000000 sk_dst_check +EXPORT_SYMBOL vmlinux 0x00000000 sk_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_free +EXPORT_SYMBOL vmlinux 0x00000000 sk_receive_skb +EXPORT_SYMBOL vmlinux 0x00000000 sk_release_kernel +EXPORT_SYMBOL vmlinux 0x00000000 sk_reset_timer +EXPORT_SYMBOL vmlinux 0x00000000 sk_run_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_send_sigurg +EXPORT_SYMBOL vmlinux 0x00000000 sk_stop_timer +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_error +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_write_space +EXPORT_SYMBOL vmlinux 0x00000000 sk_wait_data +EXPORT_SYMBOL vmlinux 0x00000000 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_append +EXPORT_SYMBOL vmlinux 0x00000000 skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0x00000000 skb_checksum +EXPORT_SYMBOL vmlinux 0x00000000 skb_checksum_help +EXPORT_SYMBOL vmlinux 0x00000000 skb_clone +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_expand +EXPORT_SYMBOL vmlinux 0x00000000 skb_dequeue +EXPORT_SYMBOL vmlinux 0x00000000 skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0x00000000 skb_find_text +EXPORT_SYMBOL vmlinux 0x00000000 skb_free_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_gso_segment +EXPORT_SYMBOL vmlinux 0x00000000 skb_insert +EXPORT_SYMBOL vmlinux 0x00000000 skb_kill_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_over_panic +EXPORT_SYMBOL vmlinux 0x00000000 skb_pad +EXPORT_SYMBOL vmlinux 0x00000000 skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_pull +EXPORT_SYMBOL vmlinux 0x00000000 skb_push +EXPORT_SYMBOL vmlinux 0x00000000 skb_put +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_head +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_purge +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_tail +EXPORT_SYMBOL vmlinux 0x00000000 skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0x00000000 skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_split +EXPORT_SYMBOL vmlinux 0x00000000 skb_store_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_trim +EXPORT_SYMBOL vmlinux 0x00000000 skb_truesize_bug +EXPORT_SYMBOL vmlinux 0x00000000 skb_under_panic +EXPORT_SYMBOL vmlinux 0x00000000 skb_unlink +EXPORT_SYMBOL vmlinux 0x00000000 sleep_on +EXPORT_SYMBOL vmlinux 0x00000000 sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x00000000 snprintf +EXPORT_SYMBOL vmlinux 0x00000000 sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_create +EXPORT_SYMBOL vmlinux 0x00000000 sock_create_kern +EXPORT_SYMBOL vmlinux 0x00000000 sock_create_lite +EXPORT_SYMBOL vmlinux 0x00000000 sock_get_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 sock_get_timestampns +EXPORT_SYMBOL vmlinux 0x00000000 sock_i_ino +EXPORT_SYMBOL vmlinux 0x00000000 sock_i_uid +EXPORT_SYMBOL vmlinux 0x00000000 sock_init_data +EXPORT_SYMBOL vmlinux 0x00000000 sock_kfree_s +EXPORT_SYMBOL vmlinux 0x00000000 sock_kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 sock_map_fd +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_accept +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_bind +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_connect +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_getname +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_listen +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_mmap +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_poll +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x00000000 sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x00000000 sock_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_register +EXPORT_SYMBOL vmlinux 0x00000000 sock_release +EXPORT_SYMBOL vmlinux 0x00000000 sock_rfree +EXPORT_SYMBOL vmlinux 0x00000000 sock_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_unregister +EXPORT_SYMBOL vmlinux 0x00000000 sock_wake_async +EXPORT_SYMBOL vmlinux 0x00000000 sock_wfree +EXPORT_SYMBOL vmlinux 0x00000000 sock_wmalloc +EXPORT_SYMBOL vmlinux 0x00000000 sockfd_lookup +EXPORT_SYMBOL vmlinux 0x00000000 soft_cursor +EXPORT_SYMBOL vmlinux 0x00000000 sort +EXPORT_SYMBOL vmlinux 0x00000000 sound_class +EXPORT_SYMBOL vmlinux 0x00000000 splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0x00000000 sprintf +EXPORT_SYMBOL vmlinux 0x00000000 srandom32 +EXPORT_SYMBOL vmlinux 0x00000000 sscanf +EXPORT_SYMBOL vmlinux 0x00000000 start_tty +EXPORT_SYMBOL vmlinux 0x00000000 stop_tty +EXPORT_SYMBOL vmlinux 0x00000000 strcasecmp +EXPORT_SYMBOL vmlinux 0x00000000 strcat +EXPORT_SYMBOL vmlinux 0x00000000 strchr +EXPORT_SYMBOL vmlinux 0x00000000 strcmp +EXPORT_SYMBOL vmlinux 0x00000000 strcpy +EXPORT_SYMBOL vmlinux 0x00000000 strcspn +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtol +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoll +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoul +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoull +EXPORT_SYMBOL vmlinux 0x00000000 strlcat +EXPORT_SYMBOL vmlinux 0x00000000 strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 strlen +EXPORT_SYMBOL vmlinux 0x00000000 strncasecmp +EXPORT_SYMBOL vmlinux 0x00000000 strncat +EXPORT_SYMBOL vmlinux 0x00000000 strnchr +EXPORT_SYMBOL vmlinux 0x00000000 strncmp +EXPORT_SYMBOL vmlinux 0x00000000 strncpy +EXPORT_SYMBOL vmlinux 0x00000000 strndup_user +EXPORT_SYMBOL vmlinux 0x00000000 strnicmp +EXPORT_SYMBOL vmlinux 0x00000000 strnlen +EXPORT_SYMBOL vmlinux 0x00000000 strpbrk +EXPORT_SYMBOL vmlinux 0x00000000 strrchr +EXPORT_SYMBOL vmlinux 0x00000000 strsep +EXPORT_SYMBOL vmlinux 0x00000000 strspn +EXPORT_SYMBOL vmlinux 0x00000000 strstr +EXPORT_SYMBOL vmlinux 0x00000000 strstrip +EXPORT_SYMBOL vmlinux 0x00000000 submit_bh +EXPORT_SYMBOL vmlinux 0x00000000 submit_bio +EXPORT_SYMBOL vmlinux 0x00000000 sunrpc_cache_lookup +EXPORT_SYMBOL vmlinux 0x00000000 sunrpc_cache_update +EXPORT_SYMBOL vmlinux 0x00000000 svc_auth_register +EXPORT_SYMBOL vmlinux 0x00000000 svc_auth_unregister +EXPORT_SYMBOL vmlinux 0x00000000 svc_authenticate +EXPORT_SYMBOL vmlinux 0x00000000 svc_create +EXPORT_SYMBOL vmlinux 0x00000000 svc_create_pooled +EXPORT_SYMBOL vmlinux 0x00000000 svc_destroy +EXPORT_SYMBOL vmlinux 0x00000000 svc_drop +EXPORT_SYMBOL vmlinux 0x00000000 svc_exit_thread +EXPORT_SYMBOL vmlinux 0x00000000 svc_prepare_thread +EXPORT_SYMBOL vmlinux 0x00000000 svc_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 svc_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 svc_process +EXPORT_SYMBOL vmlinux 0x00000000 svc_recv +EXPORT_SYMBOL vmlinux 0x00000000 svc_reserve +EXPORT_SYMBOL vmlinux 0x00000000 svc_seq_show +EXPORT_SYMBOL vmlinux 0x00000000 svc_set_client +EXPORT_SYMBOL vmlinux 0x00000000 svc_set_num_threads +EXPORT_SYMBOL vmlinux 0x00000000 svc_sock_names +EXPORT_SYMBOL vmlinux 0x00000000 svc_sock_update_bufs +EXPORT_SYMBOL vmlinux 0x00000000 svc_wake_up +EXPORT_SYMBOL vmlinux 0x00000000 svcauth_unix_purge +EXPORT_SYMBOL vmlinux 0x00000000 svcauth_unix_set_client +EXPORT_SYMBOL vmlinux 0x00000000 sync_blockdev +EXPORT_SYMBOL vmlinux 0x00000000 sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sync_inode +EXPORT_SYMBOL vmlinux 0x00000000 sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0x00000000 sync_page_range +EXPORT_SYMBOL vmlinux 0x00000000 sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0x00000000 synchronize_net +EXPORT_SYMBOL vmlinux 0x00000000 sys_close +EXPORT_SYMBOL vmlinux 0x00000000 sys_tz +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_data +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_intvec +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_string +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0x00000000 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0x00000000 sysfs_streq +EXPORT_SYMBOL vmlinux 0x00000000 system_rev +EXPORT_SYMBOL vmlinux 0x00000000 system_serial_high +EXPORT_SYMBOL vmlinux 0x00000000 system_serial_low +EXPORT_SYMBOL vmlinux 0x00000000 system_state +EXPORT_SYMBOL vmlinux 0x00000000 take_over_console +EXPORT_SYMBOL vmlinux 0x00000000 task_nice +EXPORT_SYMBOL vmlinux 0x00000000 task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_session_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 tasklet_init +EXPORT_SYMBOL vmlinux 0x00000000 tasklet_kill +EXPORT_SYMBOL vmlinux 0x00000000 tcp_check_req +EXPORT_SYMBOL vmlinux 0x00000000 tcp_child_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_close +EXPORT_SYMBOL vmlinux 0x00000000 tcp_connect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0x00000000 tcp_disconnect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0x00000000 tcp_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 tcp_hashinfo +EXPORT_SYMBOL vmlinux 0x00000000 tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0x00000000 tcp_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 tcp_make_synack +EXPORT_SYMBOL vmlinux 0x00000000 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0x00000000 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x00000000 tcp_mtup_init +EXPORT_SYMBOL vmlinux 0x00000000 tcp_parse_options +EXPORT_SYMBOL vmlinux 0x00000000 tcp_poll +EXPORT_SYMBOL vmlinux 0x00000000 tcp_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 tcp_prot +EXPORT_SYMBOL vmlinux 0x00000000 tcp_rcv_established +EXPORT_SYMBOL vmlinux 0x00000000 tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_read_sock +EXPORT_SYMBOL vmlinux 0x00000000 tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 tcp_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x00000000 tcp_splice_read +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sync_mss +EXPORT_SYMBOL vmlinux 0x00000000 tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_tso_segment +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_connect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0x00000000 test_set_page_writeback +EXPORT_SYMBOL vmlinux 0x00000000 thaw_bdev +EXPORT_SYMBOL vmlinux 0x00000000 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 timespec_trunc +EXPORT_SYMBOL vmlinux 0x00000000 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 totalram_pages +EXPORT_SYMBOL vmlinux 0x00000000 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0x00000000 touch_atime +EXPORT_SYMBOL vmlinux 0x00000000 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x00000000 truncate_inode_pages +EXPORT_SYMBOL vmlinux 0x00000000 truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0x00000000 try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x00000000 try_to_release_page +EXPORT_SYMBOL vmlinux 0x00000000 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x00000000 tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0x00000000 tty_check_change +EXPORT_SYMBOL vmlinux 0x00000000 tty_devnum +EXPORT_SYMBOL vmlinux 0x00000000 tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0x00000000 tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0x00000000 tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_hangup +EXPORT_SYMBOL vmlinux 0x00000000 tty_hung_up_p +EXPORT_SYMBOL vmlinux 0x00000000 tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0x00000000 tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0x00000000 tty_mutex +EXPORT_SYMBOL vmlinux 0x00000000 tty_name +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_init +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_device +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x00000000 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0x00000000 tty_set_operations +EXPORT_SYMBOL vmlinux 0x00000000 tty_std_termios +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_throttle +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_device +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0x00000000 tty_unthrottle +EXPORT_SYMBOL vmlinux 0x00000000 tty_vhangup +EXPORT_SYMBOL vmlinux 0x00000000 tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0x00000000 tty_write_room +EXPORT_SYMBOL vmlinux 0x00000000 uart_add_one_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 uart_get_divisor +EXPORT_SYMBOL vmlinux 0x00000000 uart_match_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 uart_remove_one_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_resume_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_suspend_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 uart_update_timeout +EXPORT_SYMBOL vmlinux 0x00000000 uart_write_wakeup +EXPORT_SYMBOL vmlinux 0x00000000 udp_disconnect +EXPORT_SYMBOL vmlinux 0x00000000 udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0x00000000 udp_hash +EXPORT_SYMBOL vmlinux 0x00000000 udp_hash_lock +EXPORT_SYMBOL vmlinux 0x00000000 udp_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_get_port +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 udp_memory_allocated +EXPORT_SYMBOL vmlinux 0x00000000 udp_poll +EXPORT_SYMBOL vmlinux 0x00000000 udp_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 udp_prot +EXPORT_SYMBOL vmlinux 0x00000000 udp_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0x00000000 udplite_hash +EXPORT_SYMBOL vmlinux 0x00000000 udplite_prot +EXPORT_SYMBOL vmlinux 0x00000000 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x00000000 unix_domain_find +EXPORT_SYMBOL vmlinux 0x00000000 unlock_buffer +EXPORT_SYMBOL vmlinux 0x00000000 unlock_new_inode +EXPORT_SYMBOL vmlinux 0x00000000 unlock_page +EXPORT_SYMBOL vmlinux 0x00000000 unlock_rename +EXPORT_SYMBOL vmlinux 0x00000000 unlock_super +EXPORT_SYMBOL vmlinux 0x00000000 unmap_mapping_range +EXPORT_SYMBOL vmlinux 0x00000000 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0x00000000 unregister_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 unregister_blkdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 unregister_con_driver +EXPORT_SYMBOL vmlinux 0x00000000 unregister_console +EXPORT_SYMBOL vmlinux 0x00000000 unregister_exec_domain +EXPORT_SYMBOL vmlinux 0x00000000 unregister_filesystem +EXPORT_SYMBOL vmlinux 0x00000000 unregister_framebuffer +EXPORT_SYMBOL vmlinux 0x00000000 unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdevice +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sound_dsp +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sound_midi +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sound_mixer +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sound_special +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0x00000000 up +EXPORT_SYMBOL vmlinux 0x00000000 up_read +EXPORT_SYMBOL vmlinux 0x00000000 up_write +EXPORT_SYMBOL vmlinux 0x00000000 update_region +EXPORT_SYMBOL vmlinux 0x00000000 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 user_path_at +EXPORT_SYMBOL vmlinux 0x00000000 v4wb_clear_user_page +EXPORT_SYMBOL vmlinux 0x00000000 v4wb_copy_user_page +EXPORT_SYMBOL vmlinux 0x00000000 vc_cons +EXPORT_SYMBOL vmlinux 0x00000000 vc_resize +EXPORT_SYMBOL vmlinux 0x00000000 vfree +EXPORT_SYMBOL vmlinux 0x00000000 vfs_create +EXPORT_SYMBOL vmlinux 0x00000000 vfs_follow_link +EXPORT_SYMBOL vmlinux 0x00000000 vfs_fstat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_getattr +EXPORT_SYMBOL vmlinux 0x00000000 vfs_link +EXPORT_SYMBOL vmlinux 0x00000000 vfs_llseek +EXPORT_SYMBOL vmlinux 0x00000000 vfs_lstat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_mkdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_mknod +EXPORT_SYMBOL vmlinux 0x00000000 vfs_path_lookup +EXPORT_SYMBOL vmlinux 0x00000000 vfs_permission +EXPORT_SYMBOL vmlinux 0x00000000 vfs_read +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readv +EXPORT_SYMBOL vmlinux 0x00000000 vfs_rename +EXPORT_SYMBOL vmlinux 0x00000000 vfs_rmdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_stat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_statfs +EXPORT_SYMBOL vmlinux 0x00000000 vfs_symlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_unlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_write +EXPORT_SYMBOL vmlinux 0x00000000 vfs_writev +EXPORT_SYMBOL vmlinux 0x00000000 vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_mixed +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_page +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0x00000000 vm_stat +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_32 +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_node +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_user +EXPORT_SYMBOL vmlinux 0x00000000 vmap +EXPORT_SYMBOL vmlinux 0x00000000 vmtruncate +EXPORT_SYMBOL vmlinux 0x00000000 vprintk +EXPORT_SYMBOL vmlinux 0x00000000 vscnprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsnprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsscanf +EXPORT_SYMBOL vmlinux 0x00000000 vunmap +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x00000000 wait_on_page_bit +EXPORT_SYMBOL vmlinux 0x00000000 wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0x00000000 wake_bit_function +EXPORT_SYMBOL vmlinux 0x00000000 wake_up_bit +EXPORT_SYMBOL vmlinux 0x00000000 wake_up_process +EXPORT_SYMBOL vmlinux 0x00000000 walk_stackframe +EXPORT_SYMBOL vmlinux 0x00000000 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x00000000 warn_slowpath +EXPORT_SYMBOL vmlinux 0x00000000 wireless_send_event +EXPORT_SYMBOL vmlinux 0x00000000 wireless_spy_update +EXPORT_SYMBOL vmlinux 0x00000000 write_cache_pages +EXPORT_SYMBOL vmlinux 0x00000000 write_inode_now +EXPORT_SYMBOL vmlinux 0x00000000 write_one_page +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_from_iov +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_read_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_subsegment +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_array2 +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_string_inplace +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_word +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_array2 +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_opaque +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_opaque_fixed +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_string +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_word +EXPORT_SYMBOL vmlinux 0x00000000 xdr_enter_page +EXPORT_SYMBOL vmlinux 0x00000000 xdr_init_decode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_init_encode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_inline_decode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_inline_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_process_buf +EXPORT_SYMBOL vmlinux 0x00000000 xdr_read_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_reserve_space +EXPORT_SYMBOL vmlinux 0x00000000 xdr_shift_buf +EXPORT_SYMBOL vmlinux 0x00000000 xdr_write_pages +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_rcv +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_find_acq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_init_state +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_input +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_input_resume +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_lookup +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_nl +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_count +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_km +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_mode +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_type +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_add +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_update +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_user_policy +EXPORT_SYMBOL vmlinux 0x00000000 xrlim_allow +EXPORT_SYMBOL vmlinux 0x00000000 yield +EXPORT_SYMBOL vmlinux 0x00000000 zero_fill_bio +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflate +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateEnd +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateInit2 +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateReset +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflate_workspacesize +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate_workspacesize +EXPORT_SYMBOL_GPL crypto/aes_generic 0x00000000 crypto_aes_expand_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x00000000 crypto_aes_set_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x00000000 crypto_fl_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x00000000 crypto_ft_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x00000000 crypto_il_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x00000000 crypto_it_tab +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_done +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_phys +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_virt +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 blkcipher_walk_virt_block +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_ablkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_alloc_ablkcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_blkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_givcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 crypto_grab_skcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_alloc +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_exit +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_free +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x00000000 skcipher_geniv_init +EXPORT_SYMBOL_GPL drivers/char/hw_random/rng-core 0x00000000 hwrng_register +EXPORT_SYMBOL_GPL drivers/char/hw_random/rng-core 0x00000000 hwrng_unregister +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_add_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_alloc_new_dir +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_attach +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_build_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_date_unix2dos +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_detach +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_dir_empty +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_fill_super +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_flush_inodes +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_free_clusters +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_fs_panic +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_get_dotdot_entry +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_getattr +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_remove_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_scan +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_search_long +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_setattr +EXPORT_SYMBOL_GPL fs/fat/fat 0x00000000 fat_sync_inode +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x00000000 ieee80211_iterate_active_interfaces +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x00000000 ieee80211_iterate_active_interfaces_atomic +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x00000000 register_rfkill_notifier +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x00000000 rfkill_epo +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x00000000 unregister_rfkill_notifier +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 dapm_reg_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_cnew +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dai_digital_mute +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dai_set_clkdiv +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dai_set_fmt +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dai_set_pll +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dai_set_sysclk +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dai_set_tdm_slot +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dai_set_tristate +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_add_routes +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_connect_input +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_disable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_enable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_free +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_get_pin_status +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_new_control +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_new_controls +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_new_widgets +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_stream_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_dapm_sync +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_free_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_free_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_get_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_get_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_info_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_info_enum_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_info_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_info_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_info_volsw_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_info_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_new_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_new_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_put_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_put_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_register_card +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_set_runtime_hwparams +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_test_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x00000000 snd_soc_update_bits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __class_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __suspend_report_result +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0x00000000 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x00000000 alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 arm_pm_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0001 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0003 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0200 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 clockevents_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 console_drivers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alloc_instance +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_attr_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_attr_alg_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_attr_u32 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_check_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_dequeue_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_drop_spawn +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_enqueue_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_get_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_inc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_init_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_init_spawn +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_error +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_lookup_template +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_instance +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_template +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_spawn_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_tfm_in_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_unregister_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_unregister_template +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_xor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x00000000 default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 default_mtd_writev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 del_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0x00000000 deregister_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 deregister_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0x00000000 destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_attach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_initialize +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_move +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_power_down +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_power_up +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_rename +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_resume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_suspend +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_find +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_attach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_find +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0x00000000 elv_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0x00000000 exit_fs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 exportfs_decode_fh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 exportfs_encode_fh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fb_destroy_modelist +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fb_mode_option +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_vpid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 flush_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0x00000000 free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_mtd_device_nm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_sb_mtd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_free_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_input_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_output_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_parse_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_set_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_connect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_disconnect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_find_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_report_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_dummy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_probed_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_hash +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inverse_translate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0x00000000 jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x00000000 k_handler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kbd_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kill_mtd_super +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kmem_cache_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_add_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_sub_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_set +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_set_default +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_show +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_store +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 led_trigger_unregister_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 leds_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 leds_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lzo1x_1_compress +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lzo1x_decompress_safe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mmput +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_erase_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_table_mutex +EXPORT_SYMBOL_GPL vmlinux 0x00000000 net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x00000000 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0x00000000 netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nfs_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nfsd_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlm_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_proc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x00000000 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0x00000000 parse_mtd_partitions +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x00000000 probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_pid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_rpccred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rdev_get_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rdev_get_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_enable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_enable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_force_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_current_limit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_supply +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_voltage +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_is_enabled +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_current_limit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_device_supply +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_machine_constraints +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_optimum_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_supply +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_voltage +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_suspend_prepare +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_alloc_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_bind_new_program +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_calc_rto +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_null +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_clone_client +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_delay +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_exit_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_force_rebind +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_free_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_init_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_init_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_killall_tasks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_lookup_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_malloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_peeraddr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_peeraddr2str +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_print_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_proc_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_proc_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_put_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_restart_call +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_run_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_setbufsize +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_shutdown_client +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_sleep_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_init_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_init_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcb_getport_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcb_getport_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_copychunks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_map +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_map_and_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 screen_glyph +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_align_size +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_claim_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_claim_irq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_disable_func +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_enable_func +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_f0_readb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_f0_writeb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_memcpy_fromio +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_memcpy_toio +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_readb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_readl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_readsb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_readw +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_release_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_release_irq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_set_block_size +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_writeb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_writel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_writesb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdio_writew +EXPORT_SYMBOL_GPL vmlinux 0x00000000 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0x00000000 seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 single_release_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_morph +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_addsock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_close_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_create_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_find_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_print_addr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_reg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_unreg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_enqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_names +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_received +EXPORT_SYMBOL_GPL vmlinux 0x00000000 symbol_put_addr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x00000000 thread_notify_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_close_volume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_get_device_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_get_volume_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_is_mapped +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_leb_change +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_leb_erase +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_leb_map +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_leb_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_leb_unmap +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_leb_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_open_volume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_open_volume_nm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ubi_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xdr_skb_read_bits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_adjust_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_complete_rqst +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_disconnect_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_lookup_rqst +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_register_transport +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_rqst_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_reserve_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_unregister_transport +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_write_space +EXPORT_SYMBOL_GPL vmlinux 0x00000000 zap_vma_ptes --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/armel/iop32x +++ linux-2.6.27/debian/abi/2.6.27-8.17/armel/iop32x @@ -0,0 +1,3507 @@ +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x00000000 i2c_bit_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x00000000 i2c_bit_add_numbered_bus +EXPORT_SYMBOL vmlinux 0x00000000 I_BDEV +EXPORT_SYMBOL vmlinux 0x00000000 ___pskb_trim +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_idiv +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_idivmod +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_lasr +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_llsl +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_llsr +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_lmul +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_uidiv +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_uidivmod +EXPORT_SYMBOL vmlinux 0x00000000 __aeabi_ulcmp +EXPORT_SYMBOL vmlinux 0x00000000 __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x00000000 __alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 __arm_ioremap +EXPORT_SYMBOL vmlinux 0x00000000 __arm_ioremap_pfn +EXPORT_SYMBOL vmlinux 0x00000000 __ashldi3 +EXPORT_SYMBOL vmlinux 0x00000000 __ashrdi3 +EXPORT_SYMBOL vmlinux 0x00000000 __backtrace +EXPORT_SYMBOL vmlinux 0x00000000 __bad_xchg +EXPORT_SYMBOL vmlinux 0x00000000 __bdevname +EXPORT_SYMBOL vmlinux 0x00000000 __bforget +EXPORT_SYMBOL vmlinux 0x00000000 __bio_clone +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_and +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_complement +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_equal +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_full +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_intersects +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_or +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_parse +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x00000000 __bitmap_xor +EXPORT_SYMBOL vmlinux 0x00000000 __blk_run_queue +EXPORT_SYMBOL vmlinux 0x00000000 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0x00000000 __bread +EXPORT_SYMBOL vmlinux 0x00000000 __breadahead +EXPORT_SYMBOL vmlinux 0x00000000 __break_lease +EXPORT_SYMBOL vmlinux 0x00000000 __brelse +EXPORT_SYMBOL vmlinux 0x00000000 __bug +EXPORT_SYMBOL vmlinux 0x00000000 __cap_empty_set +EXPORT_SYMBOL vmlinux 0x00000000 __cap_full_set +EXPORT_SYMBOL vmlinux 0x00000000 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x00000000 __check_region +EXPORT_SYMBOL vmlinux 0x00000000 __clear_user +EXPORT_SYMBOL vmlinux 0x00000000 __const_udelay +EXPORT_SYMBOL vmlinux 0x00000000 __copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 __copy_to_user +EXPORT_SYMBOL vmlinux 0x00000000 __csum_ipv6_magic +EXPORT_SYMBOL vmlinux 0x00000000 __dev_get_by_index +EXPORT_SYMBOL vmlinux 0x00000000 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0x00000000 __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x00000000 __dev_remove_pack +EXPORT_SYMBOL vmlinux 0x00000000 __devm_release_region +EXPORT_SYMBOL vmlinux 0x00000000 __devm_request_region +EXPORT_SYMBOL vmlinux 0x00000000 __div0 +EXPORT_SYMBOL vmlinux 0x00000000 __div64_32 +EXPORT_SYMBOL vmlinux 0x00000000 __divsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __do_div64 +EXPORT_SYMBOL vmlinux 0x00000000 __down_read +EXPORT_SYMBOL vmlinux 0x00000000 __down_read_trylock +EXPORT_SYMBOL vmlinux 0x00000000 __down_write +EXPORT_SYMBOL vmlinux 0x00000000 __down_write_nested +EXPORT_SYMBOL vmlinux 0x00000000 __down_write_trylock +EXPORT_SYMBOL vmlinux 0x00000000 __downgrade_write +EXPORT_SYMBOL vmlinux 0x00000000 __dst_free +EXPORT_SYMBOL vmlinux 0x00000000 __elv_add_request +EXPORT_SYMBOL vmlinux 0x00000000 __f_setown +EXPORT_SYMBOL vmlinux 0x00000000 __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0x00000000 __find_get_block +EXPORT_SYMBOL vmlinux 0x00000000 __free_pages +EXPORT_SYMBOL vmlinux 0x00000000 __generic_unplug_device +EXPORT_SYMBOL vmlinux 0x00000000 __get_free_pages +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_1 +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_2 +EXPORT_SYMBOL vmlinux 0x00000000 __get_user_4 +EXPORT_SYMBOL vmlinux 0x00000000 __getblk +EXPORT_SYMBOL vmlinux 0x00000000 __grab_cache_page +EXPORT_SYMBOL vmlinux 0x00000000 __inet6_hash +EXPORT_SYMBOL vmlinux 0x00000000 __inet6_lookup_established +EXPORT_SYMBOL vmlinux 0x00000000 __init_rwsem +EXPORT_SYMBOL vmlinux 0x00000000 __inode_dir_notify +EXPORT_SYMBOL vmlinux 0x00000000 __insert_inode_hash +EXPORT_SYMBOL vmlinux 0x00000000 __invalidate_device +EXPORT_SYMBOL vmlinux 0x00000000 __iop3xx_ioremap +EXPORT_SYMBOL vmlinux 0x00000000 __iop3xx_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 __iounmap +EXPORT_SYMBOL vmlinux 0x00000000 __ip_select_ident +EXPORT_SYMBOL vmlinux 0x00000000 __ipv6_addr_type +EXPORT_SYMBOL vmlinux 0x00000000 __ipv6_isatap_ifid +EXPORT_SYMBOL vmlinux 0x00000000 __kfifo_get +EXPORT_SYMBOL vmlinux 0x00000000 __kfifo_put +EXPORT_SYMBOL vmlinux 0x00000000 __kfree_skb +EXPORT_SYMBOL vmlinux 0x00000000 __kill_fasync +EXPORT_SYMBOL vmlinux 0x00000000 __kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 __krealloc +EXPORT_SYMBOL vmlinux 0x00000000 __lock_buffer +EXPORT_SYMBOL vmlinux 0x00000000 __lock_page +EXPORT_SYMBOL vmlinux 0x00000000 __locks_copy_lock +EXPORT_SYMBOL vmlinux 0x00000000 __lookup_hash +EXPORT_SYMBOL vmlinux 0x00000000 __lshrdi3 +EXPORT_SYMBOL vmlinux 0x00000000 __machine_arch_type +EXPORT_SYMBOL vmlinux 0x00000000 __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0x00000000 __memzero +EXPORT_SYMBOL vmlinux 0x00000000 __mod_timer +EXPORT_SYMBOL vmlinux 0x00000000 __modsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __module_put_and_exit +EXPORT_SYMBOL vmlinux 0x00000000 __mpage_writepage +EXPORT_SYMBOL vmlinux 0x00000000 __muldi3 +EXPORT_SYMBOL vmlinux 0x00000000 __mutex_init +EXPORT_SYMBOL vmlinux 0x00000000 __napi_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __neigh_event_send +EXPORT_SYMBOL vmlinux 0x00000000 __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0x00000000 __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 __netif_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __nla_put +EXPORT_SYMBOL vmlinux 0x00000000 __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 __nla_reserve +EXPORT_SYMBOL vmlinux 0x00000000 __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 __page_symlink +EXPORT_SYMBOL vmlinux 0x00000000 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0x00000000 __pagevec_release +EXPORT_SYMBOL vmlinux 0x00000000 __pci_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 __print_symbol +EXPORT_SYMBOL vmlinux 0x00000000 __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_1 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_2 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_4 +EXPORT_SYMBOL vmlinux 0x00000000 __put_user_8 +EXPORT_SYMBOL vmlinux 0x00000000 __ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsb +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsl +EXPORT_SYMBOL vmlinux 0x00000000 __raw_readsw +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesb +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesl +EXPORT_SYMBOL vmlinux 0x00000000 __raw_writesw +EXPORT_SYMBOL vmlinux 0x00000000 __readwrite_bug +EXPORT_SYMBOL vmlinux 0x00000000 __release_region +EXPORT_SYMBOL vmlinux 0x00000000 __request_region +EXPORT_SYMBOL vmlinux 0x00000000 __rta_fill +EXPORT_SYMBOL vmlinux 0x00000000 __scm_destroy +EXPORT_SYMBOL vmlinux 0x00000000 __scm_send +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_add_device +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_alloc_queue +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_device_lookup +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_device_lookup_by_target +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_iterate_devices +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_print_command +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_print_sense +EXPORT_SYMBOL vmlinux 0x00000000 __scsi_put_command +EXPORT_SYMBOL vmlinux 0x00000000 __secpath_destroy +EXPORT_SYMBOL vmlinux 0x00000000 __seq_open_private +EXPORT_SYMBOL vmlinux 0x00000000 __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0x00000000 __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0x00000000 __set_personality +EXPORT_SYMBOL vmlinux 0x00000000 __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x00000000 __sg_free_table +EXPORT_SYMBOL vmlinux 0x00000000 __sk_dst_check +EXPORT_SYMBOL vmlinux 0x00000000 __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0x00000000 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0x00000000 __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0x00000000 __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x00000000 __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0x00000000 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0x00000000 __starget_for_each_device +EXPORT_SYMBOL vmlinux 0x00000000 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 __strnlen_user +EXPORT_SYMBOL vmlinux 0x00000000 __symbol_put +EXPORT_SYMBOL vmlinux 0x00000000 __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __tasklet_schedule +EXPORT_SYMBOL vmlinux 0x00000000 __ucmpdi2 +EXPORT_SYMBOL vmlinux 0x00000000 __udelay +EXPORT_SYMBOL vmlinux 0x00000000 __udivsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __umodsi3 +EXPORT_SYMBOL vmlinux 0x00000000 __up_read +EXPORT_SYMBOL vmlinux 0x00000000 __up_write +EXPORT_SYMBOL vmlinux 0x00000000 __vmalloc +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_bit +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0x00000000 __wait_on_buffer +EXPORT_SYMBOL vmlinux 0x00000000 __wake_up +EXPORT_SYMBOL vmlinux 0x00000000 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_lookup +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x00000000 __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x00000000 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x00000000 _change_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _clear_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _cond_resched +EXPORT_SYMBOL vmlinux 0x00000000 _ctype +EXPORT_SYMBOL vmlinux 0x00000000 _find_first_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_first_zero_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_next_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _find_next_zero_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _local_bh_enable +EXPORT_SYMBOL vmlinux 0x00000000 _memcpy_fromio +EXPORT_SYMBOL vmlinux 0x00000000 _memcpy_toio +EXPORT_SYMBOL vmlinux 0x00000000 _memset_io +EXPORT_SYMBOL vmlinux 0x00000000 _set_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_change_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_clear_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 _test_and_set_bit_le +EXPORT_SYMBOL vmlinux 0x00000000 abort +EXPORT_SYMBOL vmlinux 0x00000000 acquire_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 add_disk +EXPORT_SYMBOL vmlinux 0x00000000 add_mtd_partitions +EXPORT_SYMBOL vmlinux 0x00000000 add_taint +EXPORT_SYMBOL vmlinux 0x00000000 add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0x00000000 add_wait_queue +EXPORT_SYMBOL vmlinux 0x00000000 add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x00000000 adjust_resource +EXPORT_SYMBOL vmlinux 0x00000000 aio_complete +EXPORT_SYMBOL vmlinux 0x00000000 aio_put_req +EXPORT_SYMBOL vmlinux 0x00000000 alloc_buffer_head +EXPORT_SYMBOL vmlinux 0x00000000 alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 alloc_disk +EXPORT_SYMBOL vmlinux 0x00000000 alloc_disk_node +EXPORT_SYMBOL vmlinux 0x00000000 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0x00000000 alloc_file +EXPORT_SYMBOL vmlinux 0x00000000 alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0x00000000 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0x00000000 alloc_pci_dev +EXPORT_SYMBOL vmlinux 0x00000000 alloc_tty_driver +EXPORT_SYMBOL vmlinux 0x00000000 allocate_resource +EXPORT_SYMBOL vmlinux 0x00000000 allow_signal +EXPORT_SYMBOL vmlinux 0x00000000 argv_free +EXPORT_SYMBOL vmlinux 0x00000000 argv_split +EXPORT_SYMBOL vmlinux 0x00000000 arp_broken_ops +EXPORT_SYMBOL vmlinux 0x00000000 arp_create +EXPORT_SYMBOL vmlinux 0x00000000 arp_find +EXPORT_SYMBOL vmlinux 0x00000000 arp_send +EXPORT_SYMBOL vmlinux 0x00000000 arp_tbl +EXPORT_SYMBOL vmlinux 0x00000000 arp_xmit +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_find +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_lookup +EXPORT_SYMBOL vmlinux 0x00000000 auth_domain_put +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_add_addr +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_forget_old +EXPORT_SYMBOL vmlinux 0x00000000 auth_unix_lookup +EXPORT_SYMBOL vmlinux 0x00000000 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0x00000000 avenrun +EXPORT_SYMBOL vmlinux 0x00000000 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0x00000000 bcd2bin +EXPORT_SYMBOL vmlinux 0x00000000 bd_claim +EXPORT_SYMBOL vmlinux 0x00000000 bd_release +EXPORT_SYMBOL vmlinux 0x00000000 bd_set_size +EXPORT_SYMBOL vmlinux 0x00000000 bdev_read_only +EXPORT_SYMBOL vmlinux 0x00000000 bdevname +EXPORT_SYMBOL vmlinux 0x00000000 bdget +EXPORT_SYMBOL vmlinux 0x00000000 bdi_destroy +EXPORT_SYMBOL vmlinux 0x00000000 bdi_init +EXPORT_SYMBOL vmlinux 0x00000000 bdi_register +EXPORT_SYMBOL vmlinux 0x00000000 bdi_register_dev +EXPORT_SYMBOL vmlinux 0x00000000 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0x00000000 bdi_unregister +EXPORT_SYMBOL vmlinux 0x00000000 bdput +EXPORT_SYMBOL vmlinux 0x00000000 bh_submit_read +EXPORT_SYMBOL vmlinux 0x00000000 bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0x00000000 bin2bcd +EXPORT_SYMBOL vmlinux 0x00000000 bio_add_page +EXPORT_SYMBOL vmlinux 0x00000000 bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x00000000 bio_alloc +EXPORT_SYMBOL vmlinux 0x00000000 bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0x00000000 bio_clone +EXPORT_SYMBOL vmlinux 0x00000000 bio_copy_kern +EXPORT_SYMBOL vmlinux 0x00000000 bio_copy_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_endio +EXPORT_SYMBOL vmlinux 0x00000000 bio_free +EXPORT_SYMBOL vmlinux 0x00000000 bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0x00000000 bio_hw_segments +EXPORT_SYMBOL vmlinux 0x00000000 bio_init +EXPORT_SYMBOL vmlinux 0x00000000 bio_map_kern +EXPORT_SYMBOL vmlinux 0x00000000 bio_map_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_pair_release +EXPORT_SYMBOL vmlinux 0x00000000 bio_phys_segments +EXPORT_SYMBOL vmlinux 0x00000000 bio_put +EXPORT_SYMBOL vmlinux 0x00000000 bio_split +EXPORT_SYMBOL vmlinux 0x00000000 bio_split_pool +EXPORT_SYMBOL vmlinux 0x00000000 bio_uncopy_user +EXPORT_SYMBOL vmlinux 0x00000000 bio_unmap_user +EXPORT_SYMBOL vmlinux 0x00000000 bioset_create +EXPORT_SYMBOL vmlinux 0x00000000 bioset_free +EXPORT_SYMBOL vmlinux 0x00000000 bit_waitqueue +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_bitremap +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_close_sync +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_cond_end_sync +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_end_sync +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_endwrite +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_fold +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_onto +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_remap +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_start_sync +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_startwrite +EXPORT_SYMBOL vmlinux 0x00000000 bitmap_unplug +EXPORT_SYMBOL vmlinux 0x00000000 bitrev16 +EXPORT_SYMBOL vmlinux 0x00000000 bitrev32 +EXPORT_SYMBOL vmlinux 0x00000000 blk_alloc_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0x00000000 blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_complete_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0x00000000 blk_execute_rq +EXPORT_SYMBOL vmlinux 0x00000000 blk_free_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0x00000000 blk_get_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x00000000 blk_init_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_insert_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x00000000 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x00000000 blk_plug_device +EXPORT_SYMBOL vmlinux 0x00000000 blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x00000000 blk_put_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_bounce +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_make_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_ordered +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0x00000000 blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0x00000000 blk_recount_segments +EXPORT_SYMBOL vmlinux 0x00000000 blk_register_region +EXPORT_SYMBOL vmlinux 0x00000000 blk_remove_plug +EXPORT_SYMBOL vmlinux 0x00000000 blk_requeue_request +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_init +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_map_user +EXPORT_SYMBOL vmlinux 0x00000000 blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0x00000000 blk_run_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_start_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_start_queueing +EXPORT_SYMBOL vmlinux 0x00000000 blk_stop_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_sync_queue +EXPORT_SYMBOL vmlinux 0x00000000 blk_unplug +EXPORT_SYMBOL vmlinux 0x00000000 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x00000000 blk_verify_command +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_get +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x00000000 blkdev_put +EXPORT_SYMBOL vmlinux 0x00000000 block_all_signals +EXPORT_SYMBOL vmlinux 0x00000000 block_commit_write +EXPORT_SYMBOL vmlinux 0x00000000 block_invalidatepage +EXPORT_SYMBOL vmlinux 0x00000000 block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0x00000000 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0x00000000 block_prepare_write +EXPORT_SYMBOL vmlinux 0x00000000 block_read_full_page +EXPORT_SYMBOL vmlinux 0x00000000 block_sync_page +EXPORT_SYMBOL vmlinux 0x00000000 block_truncate_page +EXPORT_SYMBOL vmlinux 0x00000000 block_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 block_write_end +EXPORT_SYMBOL vmlinux 0x00000000 block_write_full_page +EXPORT_SYMBOL vmlinux 0x00000000 bmap +EXPORT_SYMBOL vmlinux 0x00000000 boot_tvec_bases +EXPORT_SYMBOL vmlinux 0x00000000 brioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x00000000 cache_check +EXPORT_SYMBOL vmlinux 0x00000000 cache_flush +EXPORT_SYMBOL vmlinux 0x00000000 cache_purge +EXPORT_SYMBOL vmlinux 0x00000000 cache_register +EXPORT_SYMBOL vmlinux 0x00000000 cache_unregister +EXPORT_SYMBOL vmlinux 0x00000000 cad_pid +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0x00000000 call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0x00000000 can_do_mlock +EXPORT_SYMBOL vmlinux 0x00000000 cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0x00000000 cancel_dirty_page +EXPORT_SYMBOL vmlinux 0x00000000 cap_netlink_recv +EXPORT_SYMBOL vmlinux 0x00000000 cap_set_effective +EXPORT_SYMBOL vmlinux 0x00000000 capable +EXPORT_SYMBOL vmlinux 0x00000000 cdev_add +EXPORT_SYMBOL vmlinux 0x00000000 cdev_alloc +EXPORT_SYMBOL vmlinux 0x00000000 cdev_del +EXPORT_SYMBOL vmlinux 0x00000000 cdev_init +EXPORT_SYMBOL vmlinux 0x00000000 cfi_fixup +EXPORT_SYMBOL vmlinux 0x00000000 cfi_read_pri +EXPORT_SYMBOL vmlinux 0x00000000 cfi_varsize_frob +EXPORT_SYMBOL vmlinux 0x00000000 check_disk_change +EXPORT_SYMBOL vmlinux 0x00000000 clear_bdi_congested +EXPORT_SYMBOL vmlinux 0x00000000 clear_inode +EXPORT_SYMBOL vmlinux 0x00000000 clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0x00000000 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 clocksource_register +EXPORT_SYMBOL vmlinux 0x00000000 close_bdev_excl +EXPORT_SYMBOL vmlinux 0x00000000 color_table +EXPORT_SYMBOL vmlinux 0x00000000 complete +EXPORT_SYMBOL vmlinux 0x00000000 complete_all +EXPORT_SYMBOL vmlinux 0x00000000 complete_and_exit +EXPORT_SYMBOL vmlinux 0x00000000 complete_request_key +EXPORT_SYMBOL vmlinux 0x00000000 completion_done +EXPORT_SYMBOL vmlinux 0x00000000 compute_creds +EXPORT_SYMBOL vmlinux 0x00000000 con_copy_unimap +EXPORT_SYMBOL vmlinux 0x00000000 con_is_bound +EXPORT_SYMBOL vmlinux 0x00000000 con_set_default_unimap +EXPORT_SYMBOL vmlinux 0x00000000 cond_resched_lock +EXPORT_SYMBOL vmlinux 0x00000000 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x00000000 congestion_wait +EXPORT_SYMBOL vmlinux 0x00000000 console_blank_hook +EXPORT_SYMBOL vmlinux 0x00000000 console_blanked +EXPORT_SYMBOL vmlinux 0x00000000 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0x00000000 console_print +EXPORT_SYMBOL vmlinux 0x00000000 console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x00000000 console_start +EXPORT_SYMBOL vmlinux 0x00000000 console_stop +EXPORT_SYMBOL vmlinux 0x00000000 console_suspend_enabled +EXPORT_SYMBOL vmlinux 0x00000000 cont_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 contig_page_data +EXPORT_SYMBOL vmlinux 0x00000000 copy_io_context +EXPORT_SYMBOL vmlinux 0x00000000 copy_page +EXPORT_SYMBOL vmlinux 0x00000000 copy_strings_kernel +EXPORT_SYMBOL vmlinux 0x00000000 cpu_online_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_possible_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_present_map +EXPORT_SYMBOL vmlinux 0x00000000 cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0x00000000 cpu_xscale_dcache_clean_area +EXPORT_SYMBOL vmlinux 0x00000000 cpu_xscale_set_pte_ext +EXPORT_SYMBOL vmlinux 0x00000000 crc32_be +EXPORT_SYMBOL vmlinux 0x00000000 crc32_le +EXPORT_SYMBOL vmlinux 0x00000000 crc32c_be +EXPORT_SYMBOL vmlinux 0x00000000 crc32c_le +EXPORT_SYMBOL vmlinux 0x00000000 create_empty_buffers +EXPORT_SYMBOL vmlinux 0x00000000 create_proc_entry +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x00000000 csum_partial_copy_nocheck +EXPORT_SYMBOL vmlinux 0x00000000 current_fs_time +EXPORT_SYMBOL vmlinux 0x00000000 current_kernel_time +EXPORT_SYMBOL vmlinux 0x00000000 d_add_ci +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_anon +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_name +EXPORT_SYMBOL vmlinux 0x00000000 d_alloc_root +EXPORT_SYMBOL vmlinux 0x00000000 d_delete +EXPORT_SYMBOL vmlinux 0x00000000 d_find_alias +EXPORT_SYMBOL vmlinux 0x00000000 d_genocide +EXPORT_SYMBOL vmlinux 0x00000000 d_instantiate +EXPORT_SYMBOL vmlinux 0x00000000 d_instantiate_unique +EXPORT_SYMBOL vmlinux 0x00000000 d_invalidate +EXPORT_SYMBOL vmlinux 0x00000000 d_lookup +EXPORT_SYMBOL vmlinux 0x00000000 d_move +EXPORT_SYMBOL vmlinux 0x00000000 d_namespace_path +EXPORT_SYMBOL vmlinux 0x00000000 d_path +EXPORT_SYMBOL vmlinux 0x00000000 d_prune_aliases +EXPORT_SYMBOL vmlinux 0x00000000 d_rehash +EXPORT_SYMBOL vmlinux 0x00000000 d_splice_alias +EXPORT_SYMBOL vmlinux 0x00000000 d_validate +EXPORT_SYMBOL vmlinux 0x00000000 daemonize +EXPORT_SYMBOL vmlinux 0x00000000 datagram_poll +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_close +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0x00000000 dcache_dir_open +EXPORT_SYMBOL vmlinux 0x00000000 dcache_lock +EXPORT_SYMBOL vmlinux 0x00000000 dcache_readdir +EXPORT_SYMBOL vmlinux 0x00000000 deactivate_super +EXPORT_SYMBOL vmlinux 0x00000000 default_blu +EXPORT_SYMBOL vmlinux 0x00000000 default_grn +EXPORT_SYMBOL vmlinux 0x00000000 default_llseek +EXPORT_SYMBOL vmlinux 0x00000000 default_red +EXPORT_SYMBOL vmlinux 0x00000000 default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0x00000000 default_wake_function +EXPORT_SYMBOL vmlinux 0x00000000 del_gendisk +EXPORT_SYMBOL vmlinux 0x00000000 del_mtd_partitions +EXPORT_SYMBOL vmlinux 0x00000000 del_timer +EXPORT_SYMBOL vmlinux 0x00000000 dentry_open +EXPORT_SYMBOL vmlinux 0x00000000 dentry_unhash +EXPORT_SYMBOL vmlinux 0x00000000 deny_write_access +EXPORT_SYMBOL vmlinux 0x00000000 dev_add_pack +EXPORT_SYMBOL vmlinux 0x00000000 dev_alloc_name +EXPORT_SYMBOL vmlinux 0x00000000 dev_alloc_skb +EXPORT_SYMBOL vmlinux 0x00000000 dev_base_lock +EXPORT_SYMBOL vmlinux 0x00000000 dev_change_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_close +EXPORT_SYMBOL vmlinux 0x00000000 dev_disable_lro +EXPORT_SYMBOL vmlinux 0x00000000 dev_driver_string +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_index +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_by_name +EXPORT_SYMBOL vmlinux 0x00000000 dev_get_flags +EXPORT_SYMBOL vmlinux 0x00000000 dev_getbyhwaddr +EXPORT_SYMBOL vmlinux 0x00000000 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x00000000 dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0x00000000 dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x00000000 dev_load +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_add +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_delete +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_sync +EXPORT_SYMBOL vmlinux 0x00000000 dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x00000000 dev_open +EXPORT_SYMBOL vmlinux 0x00000000 dev_queue_xmit +EXPORT_SYMBOL vmlinux 0x00000000 dev_remove_pack +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_allmulti +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_mac_address +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_mtu +EXPORT_SYMBOL vmlinux 0x00000000 dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_add +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_delete +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_sync +EXPORT_SYMBOL vmlinux 0x00000000 dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0x00000000 dev_valid_name +EXPORT_SYMBOL vmlinux 0x00000000 devm_free_irq +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioport_map +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioremap +EXPORT_SYMBOL vmlinux 0x00000000 devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0x00000000 devm_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 devm_request_irq +EXPORT_SYMBOL vmlinux 0x00000000 dget_locked +EXPORT_SYMBOL vmlinux 0x00000000 directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0x00000000 disable_hlt +EXPORT_SYMBOL vmlinux 0x00000000 disable_irq +EXPORT_SYMBOL vmlinux 0x00000000 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x00000000 disallow_signal +EXPORT_SYMBOL vmlinux 0x00000000 div64_u64 +EXPORT_SYMBOL vmlinux 0x00000000 div_s64_rem +EXPORT_SYMBOL vmlinux 0x00000000 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 dm_get_device +EXPORT_SYMBOL vmlinux 0x00000000 dm_get_mapinfo +EXPORT_SYMBOL vmlinux 0x00000000 dm_io +EXPORT_SYMBOL vmlinux 0x00000000 dm_io_client_create +EXPORT_SYMBOL vmlinux 0x00000000 dm_io_client_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dm_io_client_resize +EXPORT_SYMBOL vmlinux 0x00000000 dm_kcopyd_client_create +EXPORT_SYMBOL vmlinux 0x00000000 dm_kcopyd_client_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dm_kcopyd_copy +EXPORT_SYMBOL vmlinux 0x00000000 dm_put_device +EXPORT_SYMBOL vmlinux 0x00000000 dm_register_target +EXPORT_SYMBOL vmlinux 0x00000000 dm_table_event +EXPORT_SYMBOL vmlinux 0x00000000 dm_table_get +EXPORT_SYMBOL vmlinux 0x00000000 dm_table_get_md +EXPORT_SYMBOL vmlinux 0x00000000 dm_table_get_mode +EXPORT_SYMBOL vmlinux 0x00000000 dm_table_get_size +EXPORT_SYMBOL vmlinux 0x00000000 dm_table_put +EXPORT_SYMBOL vmlinux 0x00000000 dm_table_unplug_all +EXPORT_SYMBOL vmlinux 0x00000000 dm_unregister_target +EXPORT_SYMBOL vmlinux 0x00000000 dm_vcalloc +EXPORT_SYMBOL vmlinux 0x00000000 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_alloc_writecombine +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_client_chan_request +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_client_register +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_client_unregister +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_device_register +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_device_unregister +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_memcpy_buf_to_buf +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_memcpy_buf_to_pg +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_memcpy_pg_to_pg +EXPORT_SYMBOL vmlinux 0x00000000 dma_async_tx_descriptor_init +EXPORT_SYMBOL vmlinux 0x00000000 dma_cache_maint +EXPORT_SYMBOL vmlinux 0x00000000 dma_chan_cleanup +EXPORT_SYMBOL vmlinux 0x00000000 dma_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x00000000 dma_free_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_mark_declared_memory_occupied +EXPORT_SYMBOL vmlinux 0x00000000 dma_mmap_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dma_mmap_writecombine +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_create +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dma_pool_free +EXPORT_SYMBOL vmlinux 0x00000000 dma_release_declared_memory +EXPORT_SYMBOL vmlinux 0x00000000 dma_sync_wait +EXPORT_SYMBOL vmlinux 0x00000000 dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x00000000 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0x00000000 dmam_pool_create +EXPORT_SYMBOL vmlinux 0x00000000 dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dmam_release_declared_memory +EXPORT_SYMBOL vmlinux 0x00000000 do_SAK +EXPORT_SYMBOL vmlinux 0x00000000 do_blank_screen +EXPORT_SYMBOL vmlinux 0x00000000 do_brk +EXPORT_SYMBOL vmlinux 0x00000000 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x00000000 do_map_probe +EXPORT_SYMBOL vmlinux 0x00000000 do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0x00000000 do_munmap +EXPORT_SYMBOL vmlinux 0x00000000 do_settimeofday +EXPORT_SYMBOL vmlinux 0x00000000 do_splice_from +EXPORT_SYMBOL vmlinux 0x00000000 do_splice_to +EXPORT_SYMBOL vmlinux 0x00000000 do_sync_read +EXPORT_SYMBOL vmlinux 0x00000000 do_sync_write +EXPORT_SYMBOL vmlinux 0x00000000 do_unblank_screen +EXPORT_SYMBOL vmlinux 0x00000000 down +EXPORT_SYMBOL vmlinux 0x00000000 down_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 down_killable +EXPORT_SYMBOL vmlinux 0x00000000 down_read +EXPORT_SYMBOL vmlinux 0x00000000 down_read_trylock +EXPORT_SYMBOL vmlinux 0x00000000 down_timeout +EXPORT_SYMBOL vmlinux 0x00000000 down_trylock +EXPORT_SYMBOL vmlinux 0x00000000 down_write +EXPORT_SYMBOL vmlinux 0x00000000 down_write_trylock +EXPORT_SYMBOL vmlinux 0x00000000 downgrade_write +EXPORT_SYMBOL vmlinux 0x00000000 dput +EXPORT_SYMBOL vmlinux 0x00000000 drop_super +EXPORT_SYMBOL vmlinux 0x00000000 dst_alloc +EXPORT_SYMBOL vmlinux 0x00000000 dst_destroy +EXPORT_SYMBOL vmlinux 0x00000000 dst_discard +EXPORT_SYMBOL vmlinux 0x00000000 dst_release +EXPORT_SYMBOL vmlinux 0x00000000 dump_fpu +EXPORT_SYMBOL vmlinux 0x00000000 dump_stack +EXPORT_SYMBOL vmlinux 0x00000000 elevator_exit +EXPORT_SYMBOL vmlinux 0x00000000 elevator_init +EXPORT_SYMBOL vmlinux 0x00000000 elf_hwcap +EXPORT_SYMBOL vmlinux 0x00000000 elf_platform +EXPORT_SYMBOL vmlinux 0x00000000 elv_add_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_dequeue_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0x00000000 elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0x00000000 elv_next_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_queue_empty +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_add +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_del +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_find +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_former_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0x00000000 elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0x00000000 empty_zero_page +EXPORT_SYMBOL vmlinux 0x00000000 enable_hlt +EXPORT_SYMBOL vmlinux 0x00000000 enable_irq +EXPORT_SYMBOL vmlinux 0x00000000 end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0x00000000 end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0x00000000 end_dequeued_request +EXPORT_SYMBOL vmlinux 0x00000000 end_page_writeback +EXPORT_SYMBOL vmlinux 0x00000000 end_queued_request +EXPORT_SYMBOL vmlinux 0x00000000 end_request +EXPORT_SYMBOL vmlinux 0x00000000 eth_header +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_cache +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_cache_update +EXPORT_SYMBOL vmlinux 0x00000000 eth_header_parse +EXPORT_SYMBOL vmlinux 0x00000000 eth_rebuild_header +EXPORT_SYMBOL vmlinux 0x00000000 eth_type_trans +EXPORT_SYMBOL vmlinux 0x00000000 ether_setup +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_tx_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0x00000000 ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0x00000000 f_setown +EXPORT_SYMBOL vmlinux 0x00000000 fasync_helper +EXPORT_SYMBOL vmlinux 0x00000000 fb_register_client +EXPORT_SYMBOL vmlinux 0x00000000 fb_unregister_client +EXPORT_SYMBOL vmlinux 0x00000000 fd_install +EXPORT_SYMBOL vmlinux 0x00000000 fg_console +EXPORT_SYMBOL vmlinux 0x00000000 fget +EXPORT_SYMBOL vmlinux 0x00000000 file_fsync +EXPORT_SYMBOL vmlinux 0x00000000 file_permission +EXPORT_SYMBOL vmlinux 0x00000000 file_remove_suid +EXPORT_SYMBOL vmlinux 0x00000000 file_update_time +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fault +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawait +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0x00000000 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0x00000000 filemap_flush +EXPORT_SYMBOL vmlinux 0x00000000 filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0x00000000 filp_close +EXPORT_SYMBOL vmlinux 0x00000000 filp_open +EXPORT_SYMBOL vmlinux 0x00000000 find_get_page +EXPORT_SYMBOL vmlinux 0x00000000 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0x00000000 find_get_pages_tag +EXPORT_SYMBOL vmlinux 0x00000000 find_inode_number +EXPORT_SYMBOL vmlinux 0x00000000 find_lock_page +EXPORT_SYMBOL vmlinux 0x00000000 find_or_create_page +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0x00000000 find_task_by_vpid +EXPORT_SYMBOL vmlinux 0x00000000 find_vma +EXPORT_SYMBOL vmlinux 0x00000000 finish_wait +EXPORT_SYMBOL vmlinux 0x00000000 flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0x00000000 flow_cache_genid +EXPORT_SYMBOL vmlinux 0x00000000 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x00000000 flush_dcache_page +EXPORT_SYMBOL vmlinux 0x00000000 flush_old_exec +EXPORT_SYMBOL vmlinux 0x00000000 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x00000000 flush_signals +EXPORT_SYMBOL vmlinux 0x00000000 follow_down +EXPORT_SYMBOL vmlinux 0x00000000 follow_up +EXPORT_SYMBOL vmlinux 0x00000000 force_sig +EXPORT_SYMBOL vmlinux 0x00000000 fp_printk +EXPORT_SYMBOL vmlinux 0x00000000 fp_send_sig +EXPORT_SYMBOL vmlinux 0x00000000 fput +EXPORT_SYMBOL vmlinux 0x00000000 free_buffer_head +EXPORT_SYMBOL vmlinux 0x00000000 free_irq +EXPORT_SYMBOL vmlinux 0x00000000 free_netdev +EXPORT_SYMBOL vmlinux 0x00000000 free_pages +EXPORT_SYMBOL vmlinux 0x00000000 free_pages_exact +EXPORT_SYMBOL vmlinux 0x00000000 free_task +EXPORT_SYMBOL vmlinux 0x00000000 freeze_bdev +EXPORT_SYMBOL vmlinux 0x00000000 fs_overflowgid +EXPORT_SYMBOL vmlinux 0x00000000 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x00000000 fsync_bdev +EXPORT_SYMBOL vmlinux 0x00000000 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0x00000000 gen_new_estimator +EXPORT_SYMBOL vmlinux 0x00000000 gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x00000000 generate_random_uuid +EXPORT_SYMBOL vmlinux 0x00000000 generic_block_bmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0x00000000 generic_delete_inode +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_read +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_direct_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_llseek +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_mmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_open +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_read +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_write +EXPORT_SYMBOL vmlinux 0x00000000 generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0x00000000 generic_fillattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_getxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_listxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_make_request +EXPORT_SYMBOL vmlinux 0x00000000 generic_mii_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 generic_osync_inode +EXPORT_SYMBOL vmlinux 0x00000000 generic_permission +EXPORT_SYMBOL vmlinux 0x00000000 generic_read_dir +EXPORT_SYMBOL vmlinux 0x00000000 generic_readlink +EXPORT_SYMBOL vmlinux 0x00000000 generic_removexattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_ro_fops +EXPORT_SYMBOL vmlinux 0x00000000 generic_segment_checks +EXPORT_SYMBOL vmlinux 0x00000000 generic_setlease +EXPORT_SYMBOL vmlinux 0x00000000 generic_setxattr +EXPORT_SYMBOL vmlinux 0x00000000 generic_show_options +EXPORT_SYMBOL vmlinux 0x00000000 generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x00000000 generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 generic_unplug_device +EXPORT_SYMBOL vmlinux 0x00000000 generic_write_checks +EXPORT_SYMBOL vmlinux 0x00000000 generic_write_end +EXPORT_SYMBOL vmlinux 0x00000000 generic_writepages +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_family +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x00000000 genl_register_ops +EXPORT_SYMBOL vmlinux 0x00000000 genl_sock +EXPORT_SYMBOL vmlinux 0x00000000 genl_unregister_family +EXPORT_SYMBOL vmlinux 0x00000000 genl_unregister_ops +EXPORT_SYMBOL vmlinux 0x00000000 get_disk +EXPORT_SYMBOL vmlinux 0x00000000 get_empty_filp +EXPORT_SYMBOL vmlinux 0x00000000 get_fs_type +EXPORT_SYMBOL vmlinux 0x00000000 get_io_context +EXPORT_SYMBOL vmlinux 0x00000000 get_iop_tick_rate +EXPORT_SYMBOL vmlinux 0x00000000 get_jiffies_64 +EXPORT_SYMBOL vmlinux 0x00000000 get_nfs_grace_period +EXPORT_SYMBOL vmlinux 0x00000000 get_option +EXPORT_SYMBOL vmlinux 0x00000000 get_options +EXPORT_SYMBOL vmlinux 0x00000000 get_random_bytes +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_bdev +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_nodev +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x00000000 get_sb_single +EXPORT_SYMBOL vmlinux 0x00000000 get_seconds +EXPORT_SYMBOL vmlinux 0x00000000 get_super +EXPORT_SYMBOL vmlinux 0x00000000 get_unmapped_area +EXPORT_SYMBOL vmlinux 0x00000000 get_unused_fd +EXPORT_SYMBOL vmlinux 0x00000000 get_user_pages +EXPORT_SYMBOL vmlinux 0x00000000 get_write_access +EXPORT_SYMBOL vmlinux 0x00000000 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x00000000 getname +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_4k_bbe +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_4k_lle +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_64k_bbe +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_64k_lle +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_bbe +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_free_64k +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_init_4k_bbe +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_init_4k_lle +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_init_64k_bbe +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_init_64k_lle +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_lle +EXPORT_SYMBOL vmlinux 0x00000000 gf128mul_x_ble +EXPORT_SYMBOL vmlinux 0x00000000 give_up_console +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0x00000000 gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x00000000 gpio_line_config +EXPORT_SYMBOL vmlinux 0x00000000 gpio_line_get +EXPORT_SYMBOL vmlinux 0x00000000 gpio_line_set +EXPORT_SYMBOL vmlinux 0x00000000 grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0x00000000 groups_alloc +EXPORT_SYMBOL vmlinux 0x00000000 groups_free +EXPORT_SYMBOL vmlinux 0x00000000 half_md4_transform +EXPORT_SYMBOL vmlinux 0x00000000 handle_sysrq +EXPORT_SYMBOL vmlinux 0x00000000 have_submounts +EXPORT_SYMBOL vmlinux 0x00000000 hex_asc +EXPORT_SYMBOL vmlinux 0x00000000 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x00000000 high_memory +EXPORT_SYMBOL vmlinux 0x00000000 hweight16 +EXPORT_SYMBOL vmlinux 0x00000000 hweight32 +EXPORT_SYMBOL vmlinux 0x00000000 hweight64 +EXPORT_SYMBOL vmlinux 0x00000000 hweight8 +EXPORT_SYMBOL vmlinux 0x00000000 i2c_add_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_attach_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_clients_command +EXPORT_SYMBOL vmlinux 0x00000000 i2c_del_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_del_driver +EXPORT_SYMBOL vmlinux 0x00000000 i2c_detach_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_get_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_master_recv +EXPORT_SYMBOL vmlinux 0x00000000 i2c_master_send +EXPORT_SYMBOL vmlinux 0x00000000 i2c_probe +EXPORT_SYMBOL vmlinux 0x00000000 i2c_put_adapter +EXPORT_SYMBOL vmlinux 0x00000000 i2c_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 i2c_release_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_byte +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_byte_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_read_word_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_byte +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_byte_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_write_word_data +EXPORT_SYMBOL vmlinux 0x00000000 i2c_smbus_xfer +EXPORT_SYMBOL vmlinux 0x00000000 i2c_transfer +EXPORT_SYMBOL vmlinux 0x00000000 i2c_use_client +EXPORT_SYMBOL vmlinux 0x00000000 i2c_verify_client +EXPORT_SYMBOL vmlinux 0x00000000 icmp_err_convert +EXPORT_SYMBOL vmlinux 0x00000000 icmp_send +EXPORT_SYMBOL vmlinux 0x00000000 icmpv6_err_convert +EXPORT_SYMBOL vmlinux 0x00000000 icmpv6_send +EXPORT_SYMBOL vmlinux 0x00000000 icmpv6_statistics +EXPORT_SYMBOL vmlinux 0x00000000 icmpv6msg_statistics +EXPORT_SYMBOL vmlinux 0x00000000 ida_destroy +EXPORT_SYMBOL vmlinux 0x00000000 ida_get_new +EXPORT_SYMBOL vmlinux 0x00000000 ida_get_new_above +EXPORT_SYMBOL vmlinux 0x00000000 ida_init +EXPORT_SYMBOL vmlinux 0x00000000 ida_pre_get +EXPORT_SYMBOL vmlinux 0x00000000 ida_remove +EXPORT_SYMBOL vmlinux 0x00000000 idr_destroy +EXPORT_SYMBOL vmlinux 0x00000000 idr_find +EXPORT_SYMBOL vmlinux 0x00000000 idr_for_each +EXPORT_SYMBOL vmlinux 0x00000000 idr_get_new +EXPORT_SYMBOL vmlinux 0x00000000 idr_get_new_above +EXPORT_SYMBOL vmlinux 0x00000000 idr_init +EXPORT_SYMBOL vmlinux 0x00000000 idr_pre_get +EXPORT_SYMBOL vmlinux 0x00000000 idr_remove +EXPORT_SYMBOL vmlinux 0x00000000 idr_remove_all +EXPORT_SYMBOL vmlinux 0x00000000 idr_replace +EXPORT_SYMBOL vmlinux 0x00000000 ifla_policy +EXPORT_SYMBOL vmlinux 0x00000000 iget5_locked +EXPORT_SYMBOL vmlinux 0x00000000 iget_failed +EXPORT_SYMBOL vmlinux 0x00000000 iget_locked +EXPORT_SYMBOL vmlinux 0x00000000 igrab +EXPORT_SYMBOL vmlinux 0x00000000 ilookup +EXPORT_SYMBOL vmlinux 0x00000000 ilookup5 +EXPORT_SYMBOL vmlinux 0x00000000 ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x00000000 in4_pton +EXPORT_SYMBOL vmlinux 0x00000000 in6_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x00000000 in6_pton +EXPORT_SYMBOL vmlinux 0x00000000 in_aton +EXPORT_SYMBOL vmlinux 0x00000000 in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x00000000 in_egroup_p +EXPORT_SYMBOL vmlinux 0x00000000 in_group_p +EXPORT_SYMBOL vmlinux 0x00000000 inet6_add_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet6_bind +EXPORT_SYMBOL vmlinux 0x00000000 inet6_del_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet6_getname +EXPORT_SYMBOL vmlinux 0x00000000 inet6_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 inet6_register_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inet6_release +EXPORT_SYMBOL vmlinux 0x00000000 inet6_unregister_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inet_accept +EXPORT_SYMBOL vmlinux 0x00000000 inet_add_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet_addr_type +EXPORT_SYMBOL vmlinux 0x00000000 inet_bind +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_accept +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0x00000000 inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x00000000 inet_del_protocol +EXPORT_SYMBOL vmlinux 0x00000000 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0x00000000 inet_dgram_connect +EXPORT_SYMBOL vmlinux 0x00000000 inet_dgram_ops +EXPORT_SYMBOL vmlinux 0x00000000 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_destroy +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_evictor +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_find +EXPORT_SYMBOL vmlinux 0x00000000 inet_frag_kill +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_fini +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_init +EXPORT_SYMBOL vmlinux 0x00000000 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x00000000 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x00000000 inet_getname +EXPORT_SYMBOL vmlinux 0x00000000 inet_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 inet_listen +EXPORT_SYMBOL vmlinux 0x00000000 inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0x00000000 inet_put_port +EXPORT_SYMBOL vmlinux 0x00000000 inet_register_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inet_release +EXPORT_SYMBOL vmlinux 0x00000000 inet_select_addr +EXPORT_SYMBOL vmlinux 0x00000000 inet_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 inet_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0x00000000 inet_sock_destruct +EXPORT_SYMBOL vmlinux 0x00000000 inet_stream_connect +EXPORT_SYMBOL vmlinux 0x00000000 inet_stream_ops +EXPORT_SYMBOL vmlinux 0x00000000 inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0x00000000 inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0x00000000 inetdev_by_index +EXPORT_SYMBOL vmlinux 0x00000000 init_buffer +EXPORT_SYMBOL vmlinux 0x00000000 init_file +EXPORT_SYMBOL vmlinux 0x00000000 init_mm +EXPORT_SYMBOL vmlinux 0x00000000 init_net +EXPORT_SYMBOL vmlinux 0x00000000 init_special_inode +EXPORT_SYMBOL vmlinux 0x00000000 init_task +EXPORT_SYMBOL vmlinux 0x00000000 init_timer +EXPORT_SYMBOL vmlinux 0x00000000 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0x00000000 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x00000000 inode_add_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_change_ok +EXPORT_SYMBOL vmlinux 0x00000000 inode_double_lock +EXPORT_SYMBOL vmlinux 0x00000000 inode_double_unlock +EXPORT_SYMBOL vmlinux 0x00000000 inode_get_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_init_once +EXPORT_SYMBOL vmlinux 0x00000000 inode_needs_sync +EXPORT_SYMBOL vmlinux 0x00000000 inode_permission +EXPORT_SYMBOL vmlinux 0x00000000 inode_set_bytes +EXPORT_SYMBOL vmlinux 0x00000000 inode_setattr +EXPORT_SYMBOL vmlinux 0x00000000 inode_sub_bytes +EXPORT_SYMBOL vmlinux 0x00000000 input_allocate_device +EXPORT_SYMBOL vmlinux 0x00000000 input_close_device +EXPORT_SYMBOL vmlinux 0x00000000 input_event +EXPORT_SYMBOL vmlinux 0x00000000 input_flush_device +EXPORT_SYMBOL vmlinux 0x00000000 input_free_device +EXPORT_SYMBOL vmlinux 0x00000000 input_get_keycode +EXPORT_SYMBOL vmlinux 0x00000000 input_grab_device +EXPORT_SYMBOL vmlinux 0x00000000 input_inject_event +EXPORT_SYMBOL vmlinux 0x00000000 input_open_device +EXPORT_SYMBOL vmlinux 0x00000000 input_register_device +EXPORT_SYMBOL vmlinux 0x00000000 input_register_handle +EXPORT_SYMBOL vmlinux 0x00000000 input_register_handler +EXPORT_SYMBOL vmlinux 0x00000000 input_release_device +EXPORT_SYMBOL vmlinux 0x00000000 input_set_capability +EXPORT_SYMBOL vmlinux 0x00000000 input_set_keycode +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_device +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_handle +EXPORT_SYMBOL vmlinux 0x00000000 input_unregister_handler +EXPORT_SYMBOL vmlinux 0x00000000 int_sqrt +EXPORT_SYMBOL vmlinux 0x00000000 int_to_scsilun +EXPORT_SYMBOL vmlinux 0x00000000 interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0x00000000 interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_bdev +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_inodes +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0x00000000 invalidate_partition +EXPORT_SYMBOL vmlinux 0x00000000 io_schedule +EXPORT_SYMBOL vmlinux 0x00000000 ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x00000000 iomem_resource +EXPORT_SYMBOL vmlinux 0x00000000 ioport_map +EXPORT_SYMBOL vmlinux 0x00000000 ioport_resource +EXPORT_SYMBOL vmlinux 0x00000000 ioport_unmap +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_advance +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x00000000 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0x00000000 iov_shorten +EXPORT_SYMBOL vmlinux 0x00000000 ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0x00000000 ip6_frag_init +EXPORT_SYMBOL vmlinux 0x00000000 ip6_frag_match +EXPORT_SYMBOL vmlinux 0x00000000 ip6_route_output +EXPORT_SYMBOL vmlinux 0x00000000 ip6_xmit +EXPORT_SYMBOL vmlinux 0x00000000 ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0x00000000 ip_defrag +EXPORT_SYMBOL vmlinux 0x00000000 ip_dev_find +EXPORT_SYMBOL vmlinux 0x00000000 ip_fragment +EXPORT_SYMBOL vmlinux 0x00000000 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0x00000000 ip_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_join_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0x00000000 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0x00000000 ip_route_input +EXPORT_SYMBOL vmlinux 0x00000000 ip_route_output_key +EXPORT_SYMBOL vmlinux 0x00000000 ip_send_check +EXPORT_SYMBOL vmlinux 0x00000000 ip_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 iput +EXPORT_SYMBOL vmlinux 0x00000000 ipv4_config +EXPORT_SYMBOL vmlinux 0x00000000 ipv4_specific +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_chk_addr +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_chk_prefix +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_dev_get_saddr +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_ext_hdr +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_push_nfrag_opts +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 ipv6_skip_exthdr +EXPORT_SYMBOL vmlinux 0x00000000 irq_stat +EXPORT_SYMBOL vmlinux 0x00000000 is_bad_inode +EXPORT_SYMBOL vmlinux 0x00000000 is_container_init +EXPORT_SYMBOL vmlinux 0x00000000 isa_dma_bridge_buggy +EXPORT_SYMBOL vmlinux 0x00000000 iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0x00000000 iunique +EXPORT_SYMBOL vmlinux 0x00000000 jiffies +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_64 +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0x00000000 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x00000000 journal_abort +EXPORT_SYMBOL vmlinux 0x00000000 journal_ack_err +EXPORT_SYMBOL vmlinux 0x00000000 journal_blocks_per_page +EXPORT_SYMBOL vmlinux 0x00000000 journal_check_available_features +EXPORT_SYMBOL vmlinux 0x00000000 journal_check_used_features +EXPORT_SYMBOL vmlinux 0x00000000 journal_clear_err +EXPORT_SYMBOL vmlinux 0x00000000 journal_create +EXPORT_SYMBOL vmlinux 0x00000000 journal_destroy +EXPORT_SYMBOL vmlinux 0x00000000 journal_dirty_data +EXPORT_SYMBOL vmlinux 0x00000000 journal_dirty_metadata +EXPORT_SYMBOL vmlinux 0x00000000 journal_errno +EXPORT_SYMBOL vmlinux 0x00000000 journal_extend +EXPORT_SYMBOL vmlinux 0x00000000 journal_flush +EXPORT_SYMBOL vmlinux 0x00000000 journal_force_commit +EXPORT_SYMBOL vmlinux 0x00000000 journal_force_commit_nested +EXPORT_SYMBOL vmlinux 0x00000000 journal_forget +EXPORT_SYMBOL vmlinux 0x00000000 journal_get_create_access +EXPORT_SYMBOL vmlinux 0x00000000 journal_get_undo_access +EXPORT_SYMBOL vmlinux 0x00000000 journal_get_write_access +EXPORT_SYMBOL vmlinux 0x00000000 journal_init_dev +EXPORT_SYMBOL vmlinux 0x00000000 journal_init_inode +EXPORT_SYMBOL vmlinux 0x00000000 journal_invalidatepage +EXPORT_SYMBOL vmlinux 0x00000000 journal_load +EXPORT_SYMBOL vmlinux 0x00000000 journal_lock_updates +EXPORT_SYMBOL vmlinux 0x00000000 journal_release_buffer +EXPORT_SYMBOL vmlinux 0x00000000 journal_restart +EXPORT_SYMBOL vmlinux 0x00000000 journal_revoke +EXPORT_SYMBOL vmlinux 0x00000000 journal_set_features +EXPORT_SYMBOL vmlinux 0x00000000 journal_start +EXPORT_SYMBOL vmlinux 0x00000000 journal_start_commit +EXPORT_SYMBOL vmlinux 0x00000000 journal_stop +EXPORT_SYMBOL vmlinux 0x00000000 journal_try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x00000000 journal_unlock_updates +EXPORT_SYMBOL vmlinux 0x00000000 journal_update_format +EXPORT_SYMBOL vmlinux 0x00000000 journal_wipe +EXPORT_SYMBOL vmlinux 0x00000000 kasprintf +EXPORT_SYMBOL vmlinux 0x00000000 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0x00000000 kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0x00000000 kd_mksound +EXPORT_SYMBOL vmlinux 0x00000000 kern_fp_enter +EXPORT_SYMBOL vmlinux 0x00000000 kernel_accept +EXPORT_SYMBOL vmlinux 0x00000000 kernel_bind +EXPORT_SYMBOL vmlinux 0x00000000 kernel_connect +EXPORT_SYMBOL vmlinux 0x00000000 kernel_execve +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getpeername +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getsockname +EXPORT_SYMBOL vmlinux 0x00000000 kernel_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 kernel_listen +EXPORT_SYMBOL vmlinux 0x00000000 kernel_read +EXPORT_SYMBOL vmlinux 0x00000000 kernel_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 kernel_thread +EXPORT_SYMBOL vmlinux 0x00000000 key_alloc +EXPORT_SYMBOL vmlinux 0x00000000 key_create_or_update +EXPORT_SYMBOL vmlinux 0x00000000 key_instantiate_and_link +EXPORT_SYMBOL vmlinux 0x00000000 key_link +EXPORT_SYMBOL vmlinux 0x00000000 key_negate_and_link +EXPORT_SYMBOL vmlinux 0x00000000 key_payload_reserve +EXPORT_SYMBOL vmlinux 0x00000000 key_put +EXPORT_SYMBOL vmlinux 0x00000000 key_revoke +EXPORT_SYMBOL vmlinux 0x00000000 key_task_permission +EXPORT_SYMBOL vmlinux 0x00000000 key_type_keyring +EXPORT_SYMBOL vmlinux 0x00000000 key_unlink +EXPORT_SYMBOL vmlinux 0x00000000 key_update +EXPORT_SYMBOL vmlinux 0x00000000 key_validate +EXPORT_SYMBOL vmlinux 0x00000000 keyring_clear +EXPORT_SYMBOL vmlinux 0x00000000 keyring_search +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_alloc +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_free +EXPORT_SYMBOL vmlinux 0x00000000 kfifo_init +EXPORT_SYMBOL vmlinux 0x00000000 kfree +EXPORT_SYMBOL vmlinux 0x00000000 kfree_skb +EXPORT_SYMBOL vmlinux 0x00000000 kick_iocb +EXPORT_SYMBOL vmlinux 0x00000000 kill_anon_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_block_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_fasync +EXPORT_SYMBOL vmlinux 0x00000000 kill_litter_super +EXPORT_SYMBOL vmlinux 0x00000000 kill_pgrp +EXPORT_SYMBOL vmlinux 0x00000000 kill_pid +EXPORT_SYMBOL vmlinux 0x00000000 km_new_mapping +EXPORT_SYMBOL vmlinux 0x00000000 km_policy_expired +EXPORT_SYMBOL vmlinux 0x00000000 km_policy_notify +EXPORT_SYMBOL vmlinux 0x00000000 km_query +EXPORT_SYMBOL vmlinux 0x00000000 km_report +EXPORT_SYMBOL vmlinux 0x00000000 km_state_expired +EXPORT_SYMBOL vmlinux 0x00000000 km_state_notify +EXPORT_SYMBOL vmlinux 0x00000000 km_waitq +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_create +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_free +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0x00000000 kmem_cache_size +EXPORT_SYMBOL vmlinux 0x00000000 kmemdup +EXPORT_SYMBOL vmlinux 0x00000000 kobject_add +EXPORT_SYMBOL vmlinux 0x00000000 kobject_del +EXPORT_SYMBOL vmlinux 0x00000000 kobject_get +EXPORT_SYMBOL vmlinux 0x00000000 kobject_init +EXPORT_SYMBOL vmlinux 0x00000000 kobject_put +EXPORT_SYMBOL vmlinux 0x00000000 kobject_set_name +EXPORT_SYMBOL vmlinux 0x00000000 krealloc +EXPORT_SYMBOL vmlinux 0x00000000 kref_get +EXPORT_SYMBOL vmlinux 0x00000000 kref_init +EXPORT_SYMBOL vmlinux 0x00000000 kref_put +EXPORT_SYMBOL vmlinux 0x00000000 kref_set +EXPORT_SYMBOL vmlinux 0x00000000 kset_register +EXPORT_SYMBOL vmlinux 0x00000000 kset_unregister +EXPORT_SYMBOL vmlinux 0x00000000 kstrdup +EXPORT_SYMBOL vmlinux 0x00000000 kstrndup +EXPORT_SYMBOL vmlinux 0x00000000 kthread_bind +EXPORT_SYMBOL vmlinux 0x00000000 kthread_create +EXPORT_SYMBOL vmlinux 0x00000000 kthread_should_stop +EXPORT_SYMBOL vmlinux 0x00000000 kthread_stop +EXPORT_SYMBOL vmlinux 0x00000000 kvasprintf +EXPORT_SYMBOL vmlinux 0x00000000 laptop_mode +EXPORT_SYMBOL vmlinux 0x00000000 lease_get_mtime +EXPORT_SYMBOL vmlinux 0x00000000 lease_modify +EXPORT_SYMBOL vmlinux 0x00000000 linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0x00000000 ll_rw_block +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_disable +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_enable +EXPORT_SYMBOL vmlinux 0x00000000 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0x00000000 lock_may_read +EXPORT_SYMBOL vmlinux 0x00000000 lock_may_write +EXPORT_SYMBOL vmlinux 0x00000000 lock_rename +EXPORT_SYMBOL vmlinux 0x00000000 lock_sock_nested +EXPORT_SYMBOL vmlinux 0x00000000 lock_super +EXPORT_SYMBOL vmlinux 0x00000000 lockd_down +EXPORT_SYMBOL vmlinux 0x00000000 lockd_up +EXPORT_SYMBOL vmlinux 0x00000000 locks_copy_lock +EXPORT_SYMBOL vmlinux 0x00000000 locks_init_lock +EXPORT_SYMBOL vmlinux 0x00000000 locks_mandatory_area +EXPORT_SYMBOL vmlinux 0x00000000 locks_remove_posix +EXPORT_SYMBOL vmlinux 0x00000000 log_wait_commit +EXPORT_SYMBOL vmlinux 0x00000000 lookup_bdev +EXPORT_SYMBOL vmlinux 0x00000000 lookup_one_len +EXPORT_SYMBOL vmlinux 0x00000000 loop_register_transfer +EXPORT_SYMBOL vmlinux 0x00000000 loop_unregister_transfer +EXPORT_SYMBOL vmlinux 0x00000000 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0x00000000 make_bad_inode +EXPORT_SYMBOL vmlinux 0x00000000 malloc_sizes +EXPORT_SYMBOL vmlinux 0x00000000 map_destroy +EXPORT_SYMBOL vmlinux 0x00000000 mapping_tagged +EXPORT_SYMBOL vmlinux 0x00000000 maps_protect +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0x00000000 mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x00000000 mark_page_accessed +EXPORT_SYMBOL vmlinux 0x00000000 match_hex +EXPORT_SYMBOL vmlinux 0x00000000 match_int +EXPORT_SYMBOL vmlinux 0x00000000 match_octal +EXPORT_SYMBOL vmlinux 0x00000000 match_strdup +EXPORT_SYMBOL vmlinux 0x00000000 match_strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 match_token +EXPORT_SYMBOL vmlinux 0x00000000 max_mapnr +EXPORT_SYMBOL vmlinux 0x00000000 may_umount +EXPORT_SYMBOL vmlinux 0x00000000 may_umount_tree +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_create +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_destroy +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_entry_alloc +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_entry_find_first +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_entry_find_next +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_entry_free +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_entry_get +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_entry_insert +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_entry_release +EXPORT_SYMBOL vmlinux 0x00000000 mb_cache_shrink +EXPORT_SYMBOL vmlinux 0x00000000 md_check_recovery +EXPORT_SYMBOL vmlinux 0x00000000 md_done_sync +EXPORT_SYMBOL vmlinux 0x00000000 md_error +EXPORT_SYMBOL vmlinux 0x00000000 md_register_thread +EXPORT_SYMBOL vmlinux 0x00000000 md_unregister_thread +EXPORT_SYMBOL vmlinux 0x00000000 md_wait_for_blocked_rdev +EXPORT_SYMBOL vmlinux 0x00000000 md_wakeup_thread +EXPORT_SYMBOL vmlinux 0x00000000 md_write_end +EXPORT_SYMBOL vmlinux 0x00000000 md_write_start +EXPORT_SYMBOL vmlinux 0x00000000 mem_map +EXPORT_SYMBOL vmlinux 0x00000000 memchr +EXPORT_SYMBOL vmlinux 0x00000000 memcmp +EXPORT_SYMBOL vmlinux 0x00000000 memcpy +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x00000000 memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x00000000 memmove +EXPORT_SYMBOL vmlinux 0x00000000 memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 memparse +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x00000000 mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x00000000 mempool_create +EXPORT_SYMBOL vmlinux 0x00000000 mempool_create_node +EXPORT_SYMBOL vmlinux 0x00000000 mempool_destroy +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free_pages +EXPORT_SYMBOL vmlinux 0x00000000 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kfree +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x00000000 mempool_resize +EXPORT_SYMBOL vmlinux 0x00000000 memscan +EXPORT_SYMBOL vmlinux 0x00000000 memset +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_gmii_support +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_link +EXPORT_SYMBOL vmlinux 0x00000000 mii_check_media +EXPORT_SYMBOL vmlinux 0x00000000 mii_ethtool_gset +EXPORT_SYMBOL vmlinux 0x00000000 mii_ethtool_sset +EXPORT_SYMBOL vmlinux 0x00000000 mii_link_ok +EXPORT_SYMBOL vmlinux 0x00000000 mii_nway_restart +EXPORT_SYMBOL vmlinux 0x00000000 misc_deregister +EXPORT_SYMBOL vmlinux 0x00000000 misc_register +EXPORT_SYMBOL vmlinux 0x00000000 mktime +EXPORT_SYMBOL vmlinux 0x00000000 mnt_pin +EXPORT_SYMBOL vmlinux 0x00000000 mnt_unpin +EXPORT_SYMBOL vmlinux 0x00000000 mntput_no_expire +EXPORT_SYMBOL vmlinux 0x00000000 mod_timer +EXPORT_SYMBOL vmlinux 0x00000000 module_put +EXPORT_SYMBOL vmlinux 0x00000000 module_refcount +EXPORT_SYMBOL vmlinux 0x00000000 mpage_bio_submit +EXPORT_SYMBOL vmlinux 0x00000000 mpage_readpage +EXPORT_SYMBOL vmlinux 0x00000000 mpage_readpages +EXPORT_SYMBOL vmlinux 0x00000000 mpage_writepage +EXPORT_SYMBOL vmlinux 0x00000000 mpage_writepages +EXPORT_SYMBOL vmlinux 0x00000000 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 msleep +EXPORT_SYMBOL vmlinux 0x00000000 msleep_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 mtd_do_chip_probe +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 mutex_lock_killable +EXPORT_SYMBOL vmlinux 0x00000000 mutex_trylock +EXPORT_SYMBOL vmlinux 0x00000000 mutex_unlock +EXPORT_SYMBOL vmlinux 0x00000000 n_tty_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 names_cachep +EXPORT_SYMBOL vmlinux 0x00000000 ndisc_mc_map +EXPORT_SYMBOL vmlinux 0x00000000 neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x00000000 neigh_compat_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_connected_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_create +EXPORT_SYMBOL vmlinux 0x00000000 neigh_destroy +EXPORT_SYMBOL vmlinux 0x00000000 neigh_event_ns +EXPORT_SYMBOL vmlinux 0x00000000 neigh_for_each +EXPORT_SYMBOL vmlinux 0x00000000 neigh_ifdown +EXPORT_SYMBOL vmlinux 0x00000000 neigh_lookup +EXPORT_SYMBOL vmlinux 0x00000000 neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x00000000 neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0x00000000 neigh_parms_release +EXPORT_SYMBOL vmlinux 0x00000000 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x00000000 neigh_resolve_output +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_next +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_start +EXPORT_SYMBOL vmlinux 0x00000000 neigh_seq_stop +EXPORT_SYMBOL vmlinux 0x00000000 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0x00000000 neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_clear +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_init +EXPORT_SYMBOL vmlinux 0x00000000 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0x00000000 neigh_update +EXPORT_SYMBOL vmlinux 0x00000000 net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 net_msg_warn +EXPORT_SYMBOL vmlinux 0x00000000 net_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0x00000000 netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0x00000000 netdev_class_create_file +EXPORT_SYMBOL vmlinux 0x00000000 netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0x00000000 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x00000000 netdev_features_change +EXPORT_SYMBOL vmlinux 0x00000000 netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0x00000000 netdev_set_master +EXPORT_SYMBOL vmlinux 0x00000000 netdev_state_change +EXPORT_SYMBOL vmlinux 0x00000000 netif_carrier_off +EXPORT_SYMBOL vmlinux 0x00000000 netif_carrier_on +EXPORT_SYMBOL vmlinux 0x00000000 netif_device_attach +EXPORT_SYMBOL vmlinux 0x00000000 netif_device_detach +EXPORT_SYMBOL vmlinux 0x00000000 netif_receive_skb +EXPORT_SYMBOL vmlinux 0x00000000 netif_rx +EXPORT_SYMBOL vmlinux 0x00000000 netif_rx_ni +EXPORT_SYMBOL vmlinux 0x00000000 netlink_ack +EXPORT_SYMBOL vmlinux 0x00000000 netlink_broadcast +EXPORT_SYMBOL vmlinux 0x00000000 netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0x00000000 netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0x00000000 netlink_dump_start +EXPORT_SYMBOL vmlinux 0x00000000 netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x00000000 netlink_kernel_release +EXPORT_SYMBOL vmlinux 0x00000000 netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0x00000000 netlink_register_notifier +EXPORT_SYMBOL vmlinux 0x00000000 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x00000000 netlink_unicast +EXPORT_SYMBOL vmlinux 0x00000000 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0x00000000 new_inode +EXPORT_SYMBOL vmlinux 0x00000000 nla_append +EXPORT_SYMBOL vmlinux 0x00000000 nla_find +EXPORT_SYMBOL vmlinux 0x00000000 nla_memcmp +EXPORT_SYMBOL vmlinux 0x00000000 nla_memcpy +EXPORT_SYMBOL vmlinux 0x00000000 nla_parse +EXPORT_SYMBOL vmlinux 0x00000000 nla_put +EXPORT_SYMBOL vmlinux 0x00000000 nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 nla_reserve +EXPORT_SYMBOL vmlinux 0x00000000 nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x00000000 nla_strcmp +EXPORT_SYMBOL vmlinux 0x00000000 nla_strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 nla_validate +EXPORT_SYMBOL vmlinux 0x00000000 nlmsg_notify +EXPORT_SYMBOL vmlinux 0x00000000 nlmsvc_ops +EXPORT_SYMBOL vmlinux 0x00000000 no_llseek +EXPORT_SYMBOL vmlinux 0x00000000 no_pci_devices +EXPORT_SYMBOL vmlinux 0x00000000 nobh_truncate_page +EXPORT_SYMBOL vmlinux 0x00000000 nobh_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 nobh_write_end +EXPORT_SYMBOL vmlinux 0x00000000 nobh_writepage +EXPORT_SYMBOL vmlinux 0x00000000 node_states +EXPORT_SYMBOL vmlinux 0x00000000 nonseekable_open +EXPORT_SYMBOL vmlinux 0x00000000 noop_qdisc +EXPORT_SYMBOL vmlinux 0x00000000 notify_change +EXPORT_SYMBOL vmlinux 0x00000000 ns_to_timespec +EXPORT_SYMBOL vmlinux 0x00000000 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x00000000 num_physpages +EXPORT_SYMBOL vmlinux 0x00000000 oops_in_progress +EXPORT_SYMBOL vmlinux 0x00000000 open_bdev_excl +EXPORT_SYMBOL vmlinux 0x00000000 open_by_devnum +EXPORT_SYMBOL vmlinux 0x00000000 open_exec +EXPORT_SYMBOL vmlinux 0x00000000 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0x00000000 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0x00000000 overflowgid +EXPORT_SYMBOL vmlinux 0x00000000 overflowuid +EXPORT_SYMBOL vmlinux 0x00000000 page_follow_link_light +EXPORT_SYMBOL vmlinux 0x00000000 page_put_link +EXPORT_SYMBOL vmlinux 0x00000000 page_readlink +EXPORT_SYMBOL vmlinux 0x00000000 page_symlink +EXPORT_SYMBOL vmlinux 0x00000000 page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0x00000000 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0x00000000 pagecache_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 pagecache_write_end +EXPORT_SYMBOL vmlinux 0x00000000 pagevec_lookup +EXPORT_SYMBOL vmlinux 0x00000000 pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0x00000000 panic +EXPORT_SYMBOL vmlinux 0x00000000 panic_blink +EXPORT_SYMBOL vmlinux 0x00000000 panic_notifier_list +EXPORT_SYMBOL vmlinux 0x00000000 param_array_get +EXPORT_SYMBOL vmlinux 0x00000000 param_array_set +EXPORT_SYMBOL vmlinux 0x00000000 param_get_bool +EXPORT_SYMBOL vmlinux 0x00000000 param_get_byte +EXPORT_SYMBOL vmlinux 0x00000000 param_get_charp +EXPORT_SYMBOL vmlinux 0x00000000 param_get_int +EXPORT_SYMBOL vmlinux 0x00000000 param_get_invbool +EXPORT_SYMBOL vmlinux 0x00000000 param_get_long +EXPORT_SYMBOL vmlinux 0x00000000 param_get_short +EXPORT_SYMBOL vmlinux 0x00000000 param_get_string +EXPORT_SYMBOL vmlinux 0x00000000 param_get_uint +EXPORT_SYMBOL vmlinux 0x00000000 param_get_ulong +EXPORT_SYMBOL vmlinux 0x00000000 param_get_ushort +EXPORT_SYMBOL vmlinux 0x00000000 param_set_bool +EXPORT_SYMBOL vmlinux 0x00000000 param_set_byte +EXPORT_SYMBOL vmlinux 0x00000000 param_set_charp +EXPORT_SYMBOL vmlinux 0x00000000 param_set_copystring +EXPORT_SYMBOL vmlinux 0x00000000 param_set_int +EXPORT_SYMBOL vmlinux 0x00000000 param_set_invbool +EXPORT_SYMBOL vmlinux 0x00000000 param_set_long +EXPORT_SYMBOL vmlinux 0x00000000 param_set_short +EXPORT_SYMBOL vmlinux 0x00000000 param_set_uint +EXPORT_SYMBOL vmlinux 0x00000000 param_set_ulong +EXPORT_SYMBOL vmlinux 0x00000000 param_set_ushort +EXPORT_SYMBOL vmlinux 0x00000000 path_get +EXPORT_SYMBOL vmlinux 0x00000000 path_lookup +EXPORT_SYMBOL vmlinux 0x00000000 path_permission +EXPORT_SYMBOL vmlinux 0x00000000 path_put +EXPORT_SYMBOL vmlinux 0x00000000 pci_add_new_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_assign_resource +EXPORT_SYMBOL vmlinux 0x00000000 pci_back_from_sleep +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_add_devices +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_alloc_resource +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_assign_resources +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_find_capability +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_read_config_byte +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_read_config_dword +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_read_config_word +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_size_bridges +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_type +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_write_config_byte +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_write_config_dword +EXPORT_SYMBOL vmlinux 0x00000000 pci_bus_write_config_word +EXPORT_SYMBOL vmlinux 0x00000000 pci_choose_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_clear_mwi +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_driver +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_get +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_present +EXPORT_SYMBOL vmlinux 0x00000000 pci_dev_put +EXPORT_SYMBOL vmlinux 0x00000000 pci_disable_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_bridges +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_device_io +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_device_mem +EXPORT_SYMBOL vmlinux 0x00000000 pci_enable_wake +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_capability +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_next_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_parent_resource +EXPORT_SYMBOL vmlinux 0x00000000 pci_find_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_fixup_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_bus_and_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_class +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_get_subsys +EXPORT_SYMBOL vmlinux 0x00000000 pci_iomap +EXPORT_SYMBOL vmlinux 0x00000000 pci_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 pci_map_rom +EXPORT_SYMBOL vmlinux 0x00000000 pci_match_id +EXPORT_SYMBOL vmlinux 0x00000000 pci_pci_problems +EXPORT_SYMBOL vmlinux 0x00000000 pci_pme_active +EXPORT_SYMBOL vmlinux 0x00000000 pci_pme_capable +EXPORT_SYMBOL vmlinux 0x00000000 pci_prepare_to_sleep +EXPORT_SYMBOL vmlinux 0x00000000 pci_reenable_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_release_region +EXPORT_SYMBOL vmlinux 0x00000000 pci_release_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_release_selected_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_remove_behind_bridge +EXPORT_SYMBOL vmlinux 0x00000000 pci_remove_bus +EXPORT_SYMBOL vmlinux 0x00000000 pci_remove_bus_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_request_region +EXPORT_SYMBOL vmlinux 0x00000000 pci_request_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_request_selected_regions +EXPORT_SYMBOL vmlinux 0x00000000 pci_restore_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_root_buses +EXPORT_SYMBOL vmlinux 0x00000000 pci_save_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_bridge +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_bus_parented +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_single_device +EXPORT_SYMBOL vmlinux 0x00000000 pci_scan_slot +EXPORT_SYMBOL vmlinux 0x00000000 pci_select_bars +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_consistent_dma_mask +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_dma_mask +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_dma_max_seg_size +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_dma_seg_boundary +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_master +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_mwi +EXPORT_SYMBOL vmlinux 0x00000000 pci_set_power_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_setup_cardbus +EXPORT_SYMBOL vmlinux 0x00000000 pci_target_state +EXPORT_SYMBOL vmlinux 0x00000000 pci_try_set_mwi +EXPORT_SYMBOL vmlinux 0x00000000 pci_unmap_rom +EXPORT_SYMBOL vmlinux 0x00000000 pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 pcibios_bus_to_resource +EXPORT_SYMBOL vmlinux 0x00000000 pcibios_fixup_bus +EXPORT_SYMBOL vmlinux 0x00000000 pcibios_resource_to_bus +EXPORT_SYMBOL vmlinux 0x00000000 pcie_get_readrq +EXPORT_SYMBOL vmlinux 0x00000000 pcie_mch_quirk +EXPORT_SYMBOL vmlinux 0x00000000 pcie_set_readrq +EXPORT_SYMBOL vmlinux 0x00000000 pcim_enable_device +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap_regions +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap_regions_request_all +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iomap_table +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iounmap +EXPORT_SYMBOL vmlinux 0x00000000 pcim_iounmap_regions +EXPORT_SYMBOL vmlinux 0x00000000 pcim_pin_device +EXPORT_SYMBOL vmlinux 0x00000000 pcix_get_max_mmrbc +EXPORT_SYMBOL vmlinux 0x00000000 pcix_get_mmrbc +EXPORT_SYMBOL vmlinux 0x00000000 pcix_set_mmrbc +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu____irq_regs +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0x00000000 per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x00000000 pgprot_kernel +EXPORT_SYMBOL vmlinux 0x00000000 pgprot_user +EXPORT_SYMBOL vmlinux 0x00000000 pid_task +EXPORT_SYMBOL vmlinux 0x00000000 pm_idle +EXPORT_SYMBOL vmlinux 0x00000000 pm_power_off +EXPORT_SYMBOL vmlinux 0x00000000 pneigh_enqueue +EXPORT_SYMBOL vmlinux 0x00000000 pneigh_lookup +EXPORT_SYMBOL vmlinux 0x00000000 poll_freewait +EXPORT_SYMBOL vmlinux 0x00000000 poll_initwait +EXPORT_SYMBOL vmlinux 0x00000000 posix_lock_file +EXPORT_SYMBOL vmlinux 0x00000000 posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0x00000000 posix_test_lock +EXPORT_SYMBOL vmlinux 0x00000000 posix_unblock_lock +EXPORT_SYMBOL vmlinux 0x00000000 prepare_binprm +EXPORT_SYMBOL vmlinux 0x00000000 prepare_to_wait +EXPORT_SYMBOL vmlinux 0x00000000 prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0x00000000 print_hex_dump +EXPORT_SYMBOL vmlinux 0x00000000 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x00000000 print_mac +EXPORT_SYMBOL vmlinux 0x00000000 printk +EXPORT_SYMBOL vmlinux 0x00000000 printk_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_mask +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_off +EXPORT_SYMBOL vmlinux 0x00000000 probe_irq_on +EXPORT_SYMBOL vmlinux 0x00000000 proc_create_data +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 proc_dostring +EXPORT_SYMBOL vmlinux 0x00000000 proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0x00000000 proc_mkdir +EXPORT_SYMBOL vmlinux 0x00000000 proc_symlink +EXPORT_SYMBOL vmlinux 0x00000000 processor_id +EXPORT_SYMBOL vmlinux 0x00000000 proto_register +EXPORT_SYMBOL vmlinux 0x00000000 proto_unregister +EXPORT_SYMBOL vmlinux 0x00000000 pskb_copy +EXPORT_SYMBOL vmlinux 0x00000000 pskb_expand_head +EXPORT_SYMBOL vmlinux 0x00000000 put_cmsg +EXPORT_SYMBOL vmlinux 0x00000000 put_disk +EXPORT_SYMBOL vmlinux 0x00000000 put_filp +EXPORT_SYMBOL vmlinux 0x00000000 put_io_context +EXPORT_SYMBOL vmlinux 0x00000000 put_page +EXPORT_SYMBOL vmlinux 0x00000000 put_pages_list +EXPORT_SYMBOL vmlinux 0x00000000 put_tty_driver +EXPORT_SYMBOL vmlinux 0x00000000 put_unused_fd +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_destroy +EXPORT_SYMBOL vmlinux 0x00000000 qdisc_reset +EXPORT_SYMBOL vmlinux 0x00000000 qword_add +EXPORT_SYMBOL vmlinux 0x00000000 qword_addhex +EXPORT_SYMBOL vmlinux 0x00000000 qword_get +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_delete +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_insert +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0x00000000 radix_tree_tagged +EXPORT_SYMBOL vmlinux 0x00000000 random32 +EXPORT_SYMBOL vmlinux 0x00000000 rb_erase +EXPORT_SYMBOL vmlinux 0x00000000 rb_first +EXPORT_SYMBOL vmlinux 0x00000000 rb_insert_color +EXPORT_SYMBOL vmlinux 0x00000000 rb_last +EXPORT_SYMBOL vmlinux 0x00000000 rb_next +EXPORT_SYMBOL vmlinux 0x00000000 rb_prev +EXPORT_SYMBOL vmlinux 0x00000000 rb_replace_node +EXPORT_SYMBOL vmlinux 0x00000000 read_bytes_from_xdr_buf +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_page +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_page_async +EXPORT_SYMBOL vmlinux 0x00000000 read_cache_pages +EXPORT_SYMBOL vmlinux 0x00000000 read_dev_sector +EXPORT_SYMBOL vmlinux 0x00000000 recalc_sigpending +EXPORT_SYMBOL vmlinux 0x00000000 redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0x00000000 redraw_screen +EXPORT_SYMBOL vmlinux 0x00000000 register_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 register_blkdev +EXPORT_SYMBOL vmlinux 0x00000000 register_chrdev +EXPORT_SYMBOL vmlinux 0x00000000 register_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 register_con_driver +EXPORT_SYMBOL vmlinux 0x00000000 register_console +EXPORT_SYMBOL vmlinux 0x00000000 register_exec_domain +EXPORT_SYMBOL vmlinux 0x00000000 register_filesystem +EXPORT_SYMBOL vmlinux 0x00000000 register_gifconf +EXPORT_SYMBOL vmlinux 0x00000000 register_inet6addr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_key_type +EXPORT_SYMBOL vmlinux 0x00000000 register_md_personality +EXPORT_SYMBOL vmlinux 0x00000000 register_module_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x00000000 register_netdev +EXPORT_SYMBOL vmlinux 0x00000000 register_netdevice +EXPORT_SYMBOL vmlinux 0x00000000 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x00000000 register_shrinker +EXPORT_SYMBOL vmlinux 0x00000000 register_sysctl_paths +EXPORT_SYMBOL vmlinux 0x00000000 register_sysctl_table +EXPORT_SYMBOL vmlinux 0x00000000 register_sysrq_key +EXPORT_SYMBOL vmlinux 0x00000000 release_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 release_firmware +EXPORT_SYMBOL vmlinux 0x00000000 release_resource +EXPORT_SYMBOL vmlinux 0x00000000 release_sock +EXPORT_SYMBOL vmlinux 0x00000000 remap_pfn_range +EXPORT_SYMBOL vmlinux 0x00000000 remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0x00000000 remove_arg_zero +EXPORT_SYMBOL vmlinux 0x00000000 remove_inode_hash +EXPORT_SYMBOL vmlinux 0x00000000 remove_proc_entry +EXPORT_SYMBOL vmlinux 0x00000000 remove_wait_queue +EXPORT_SYMBOL vmlinux 0x00000000 request_firmware +EXPORT_SYMBOL vmlinux 0x00000000 request_firmware_nowait +EXPORT_SYMBOL vmlinux 0x00000000 request_irq +EXPORT_SYMBOL vmlinux 0x00000000 request_key +EXPORT_SYMBOL vmlinux 0x00000000 request_key_async +EXPORT_SYMBOL vmlinux 0x00000000 request_key_async_with_auxdata +EXPORT_SYMBOL vmlinux 0x00000000 request_key_with_auxdata +EXPORT_SYMBOL vmlinux 0x00000000 request_module +EXPORT_SYMBOL vmlinux 0x00000000 request_resource +EXPORT_SYMBOL vmlinux 0x00000000 reset_devices +EXPORT_SYMBOL vmlinux 0x00000000 restore_time_delta +EXPORT_SYMBOL vmlinux 0x00000000 rpc_mkpipe +EXPORT_SYMBOL vmlinux 0x00000000 rpc_queue_upcall +EXPORT_SYMBOL vmlinux 0x00000000 rpc_unlink +EXPORT_SYMBOL vmlinux 0x00000000 rt6_lookup +EXPORT_SYMBOL vmlinux 0x00000000 rtc_month_days +EXPORT_SYMBOL vmlinux 0x00000000 rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0x00000000 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0x00000000 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x00000000 rtc_year_days +EXPORT_SYMBOL vmlinux 0x00000000 rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_create_link +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_lock +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_notify +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_trylock +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_unicast +EXPORT_SYMBOL vmlinux 0x00000000 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x00000000 save_mount_options +EXPORT_SYMBOL vmlinux 0x00000000 save_time_delta +EXPORT_SYMBOL vmlinux 0x00000000 sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0x00000000 sb_min_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 sb_set_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 schedule +EXPORT_SYMBOL vmlinux 0x00000000 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x00000000 schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0x00000000 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0x00000000 schedule_work +EXPORT_SYMBOL vmlinux 0x00000000 schedule_work_on +EXPORT_SYMBOL vmlinux 0x00000000 scm_detach_fds +EXPORT_SYMBOL vmlinux 0x00000000 scm_fp_dup +EXPORT_SYMBOL vmlinux 0x00000000 scnprintf +EXPORT_SYMBOL vmlinux 0x00000000 scsi_add_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_add_host +EXPORT_SYMBOL vmlinux 0x00000000 scsi_adjust_queue_depth +EXPORT_SYMBOL vmlinux 0x00000000 scsi_allocate_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_bios_ptable +EXPORT_SYMBOL vmlinux 0x00000000 scsi_block_requests +EXPORT_SYMBOL vmlinux 0x00000000 scsi_block_when_processing_errors +EXPORT_SYMBOL vmlinux 0x00000000 scsi_build_sense_buffer +EXPORT_SYMBOL vmlinux 0x00000000 scsi_calculate_bounce_limit +EXPORT_SYMBOL vmlinux 0x00000000 scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_cmd_print_sense_hdr +EXPORT_SYMBOL vmlinux 0x00000000 scsi_command_normalize_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_get +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_lookup +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_lookup_by_target +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_put +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_quiesce +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_resume +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_set_state +EXPORT_SYMBOL vmlinux 0x00000000 scsi_device_type +EXPORT_SYMBOL vmlinux 0x00000000 scsi_dma_map +EXPORT_SYMBOL vmlinux 0x00000000 scsi_dma_unmap +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_finish_cmd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_flush_done_q +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_prep_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_eh_restore_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_execute +EXPORT_SYMBOL vmlinux 0x00000000 scsi_execute_req +EXPORT_SYMBOL vmlinux 0x00000000 scsi_extd_sense_format +EXPORT_SYMBOL vmlinux 0x00000000 scsi_finish_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_free_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_free_host_dev +EXPORT_SYMBOL vmlinux 0x00000000 scsi_get_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_get_host_dev +EXPORT_SYMBOL vmlinux 0x00000000 scsi_get_sense_info_fld +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_alloc +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_get +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_lookup +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_put +EXPORT_SYMBOL vmlinux 0x00000000 scsi_host_set_state +EXPORT_SYMBOL vmlinux 0x00000000 scsi_init_io +EXPORT_SYMBOL vmlinux 0x00000000 scsi_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_is_host_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_is_sdev_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_is_target_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_kmap_atomic_sg +EXPORT_SYMBOL vmlinux 0x00000000 scsi_kunmap_atomic_sg +EXPORT_SYMBOL vmlinux 0x00000000 scsi_mode_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_nonblockable_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 scsi_normalize_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_partsize +EXPORT_SYMBOL vmlinux 0x00000000 scsi_prep_return +EXPORT_SYMBOL vmlinux 0x00000000 scsi_prep_state_check +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_result +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_sense_hdr +EXPORT_SYMBOL vmlinux 0x00000000 scsi_print_status +EXPORT_SYMBOL vmlinux 0x00000000 scsi_put_command +EXPORT_SYMBOL vmlinux 0x00000000 scsi_register +EXPORT_SYMBOL vmlinux 0x00000000 scsi_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 scsi_register_interface +EXPORT_SYMBOL vmlinux 0x00000000 scsi_release_buffers +EXPORT_SYMBOL vmlinux 0x00000000 scsi_remove_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_remove_host +EXPORT_SYMBOL vmlinux 0x00000000 scsi_remove_target +EXPORT_SYMBOL vmlinux 0x00000000 scsi_report_bus_reset +EXPORT_SYMBOL vmlinux 0x00000000 scsi_report_device_reset +EXPORT_SYMBOL vmlinux 0x00000000 scsi_req_abort_cmd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_rescan_device +EXPORT_SYMBOL vmlinux 0x00000000 scsi_reset_provider +EXPORT_SYMBOL vmlinux 0x00000000 scsi_scan_host +EXPORT_SYMBOL vmlinux 0x00000000 scsi_scan_target +EXPORT_SYMBOL vmlinux 0x00000000 scsi_sense_desc_find +EXPORT_SYMBOL vmlinux 0x00000000 scsi_sense_key_string +EXPORT_SYMBOL vmlinux 0x00000000 scsi_set_medium_removal +EXPORT_SYMBOL vmlinux 0x00000000 scsi_setup_blk_pc_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_setup_fs_cmnd +EXPORT_SYMBOL vmlinux 0x00000000 scsi_show_extd_sense +EXPORT_SYMBOL vmlinux 0x00000000 scsi_show_result +EXPORT_SYMBOL vmlinux 0x00000000 scsi_show_sense_hdr +EXPORT_SYMBOL vmlinux 0x00000000 scsi_target_quiesce +EXPORT_SYMBOL vmlinux 0x00000000 scsi_target_resume +EXPORT_SYMBOL vmlinux 0x00000000 scsi_test_unit_ready +EXPORT_SYMBOL vmlinux 0x00000000 scsi_track_queue_full +EXPORT_SYMBOL vmlinux 0x00000000 scsi_unblock_requests +EXPORT_SYMBOL vmlinux 0x00000000 scsi_unregister +EXPORT_SYMBOL vmlinux 0x00000000 scsicam_bios_param +EXPORT_SYMBOL vmlinux 0x00000000 scsilun_to_int +EXPORT_SYMBOL vmlinux 0x00000000 search_binary_handler +EXPORT_SYMBOL vmlinux 0x00000000 secpath_dup +EXPORT_SYMBOL vmlinux 0x00000000 secure_tcpv6_sequence_number +EXPORT_SYMBOL vmlinux 0x00000000 send_sig +EXPORT_SYMBOL vmlinux 0x00000000 send_sig_info +EXPORT_SYMBOL vmlinux 0x00000000 seq_escape +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_next +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_start +EXPORT_SYMBOL vmlinux 0x00000000 seq_list_start_head +EXPORT_SYMBOL vmlinux 0x00000000 seq_lseek +EXPORT_SYMBOL vmlinux 0x00000000 seq_open +EXPORT_SYMBOL vmlinux 0x00000000 seq_open_private +EXPORT_SYMBOL vmlinux 0x00000000 seq_path +EXPORT_SYMBOL vmlinux 0x00000000 seq_printf +EXPORT_SYMBOL vmlinux 0x00000000 seq_putc +EXPORT_SYMBOL vmlinux 0x00000000 seq_puts +EXPORT_SYMBOL vmlinux 0x00000000 seq_read +EXPORT_SYMBOL vmlinux 0x00000000 seq_release +EXPORT_SYMBOL vmlinux 0x00000000 seq_release_private +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_register_port +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_resume_port +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_suspend_port +EXPORT_SYMBOL vmlinux 0x00000000 serial8250_unregister_port +EXPORT_SYMBOL vmlinux 0x00000000 set_anon_super +EXPORT_SYMBOL vmlinux 0x00000000 set_bdi_congested +EXPORT_SYMBOL vmlinux 0x00000000 set_bh_page +EXPORT_SYMBOL vmlinux 0x00000000 set_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 set_blocksize +EXPORT_SYMBOL vmlinux 0x00000000 set_current_groups +EXPORT_SYMBOL vmlinux 0x00000000 set_device_ro +EXPORT_SYMBOL vmlinux 0x00000000 set_disk_ro +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_chip +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_data +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_type +EXPORT_SYMBOL vmlinux 0x00000000 set_irq_wake +EXPORT_SYMBOL vmlinux 0x00000000 set_normalized_timespec +EXPORT_SYMBOL vmlinux 0x00000000 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x00000000 set_page_dirty +EXPORT_SYMBOL vmlinux 0x00000000 set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x00000000 set_user_nice +EXPORT_SYMBOL vmlinux 0x00000000 setup_arg_pages +EXPORT_SYMBOL vmlinux 0x00000000 sg_alloc_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sg_free_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_init_one +EXPORT_SYMBOL vmlinux 0x00000000 sg_init_table +EXPORT_SYMBOL vmlinux 0x00000000 sg_last +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_next +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_start +EXPORT_SYMBOL vmlinux 0x00000000 sg_miter_stop +EXPORT_SYMBOL vmlinux 0x00000000 sg_next +EXPORT_SYMBOL vmlinux 0x00000000 sget +EXPORT_SYMBOL vmlinux 0x00000000 sha_transform +EXPORT_SYMBOL vmlinux 0x00000000 should_remove_suid +EXPORT_SYMBOL vmlinux 0x00000000 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0x00000000 shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0x00000000 si_meminfo +EXPORT_SYMBOL vmlinux 0x00000000 sigprocmask +EXPORT_SYMBOL vmlinux 0x00000000 simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x00000000 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x00000000 simple_empty +EXPORT_SYMBOL vmlinux 0x00000000 simple_fill_super +EXPORT_SYMBOL vmlinux 0x00000000 simple_getattr +EXPORT_SYMBOL vmlinux 0x00000000 simple_link +EXPORT_SYMBOL vmlinux 0x00000000 simple_lookup +EXPORT_SYMBOL vmlinux 0x00000000 simple_pin_fs +EXPORT_SYMBOL vmlinux 0x00000000 simple_prepare_write +EXPORT_SYMBOL vmlinux 0x00000000 simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x00000000 simple_readpage +EXPORT_SYMBOL vmlinux 0x00000000 simple_release_fs +EXPORT_SYMBOL vmlinux 0x00000000 simple_rename +EXPORT_SYMBOL vmlinux 0x00000000 simple_rmdir +EXPORT_SYMBOL vmlinux 0x00000000 simple_set_mnt +EXPORT_SYMBOL vmlinux 0x00000000 simple_statfs +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtol +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtoul +EXPORT_SYMBOL vmlinux 0x00000000 simple_strtoull +EXPORT_SYMBOL vmlinux 0x00000000 simple_sync_file +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_get +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_read +EXPORT_SYMBOL vmlinux 0x00000000 simple_transaction_release +EXPORT_SYMBOL vmlinux 0x00000000 simple_unlink +EXPORT_SYMBOL vmlinux 0x00000000 simple_write_begin +EXPORT_SYMBOL vmlinux 0x00000000 simple_write_end +EXPORT_SYMBOL vmlinux 0x00000000 single_open +EXPORT_SYMBOL vmlinux 0x00000000 single_release +EXPORT_SYMBOL vmlinux 0x00000000 sk_alloc +EXPORT_SYMBOL vmlinux 0x00000000 sk_chk_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_common_release +EXPORT_SYMBOL vmlinux 0x00000000 sk_dst_check +EXPORT_SYMBOL vmlinux 0x00000000 sk_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_free +EXPORT_SYMBOL vmlinux 0x00000000 sk_receive_skb +EXPORT_SYMBOL vmlinux 0x00000000 sk_release_kernel +EXPORT_SYMBOL vmlinux 0x00000000 sk_reset_timer +EXPORT_SYMBOL vmlinux 0x00000000 sk_run_filter +EXPORT_SYMBOL vmlinux 0x00000000 sk_send_sigurg +EXPORT_SYMBOL vmlinux 0x00000000 sk_stop_timer +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_error +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0x00000000 sk_stream_write_space +EXPORT_SYMBOL vmlinux 0x00000000 sk_wait_data +EXPORT_SYMBOL vmlinux 0x00000000 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_append +EXPORT_SYMBOL vmlinux 0x00000000 skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0x00000000 skb_checksum +EXPORT_SYMBOL vmlinux 0x00000000 skb_checksum_help +EXPORT_SYMBOL vmlinux 0x00000000 skb_clone +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0x00000000 skb_copy_expand +EXPORT_SYMBOL vmlinux 0x00000000 skb_dequeue +EXPORT_SYMBOL vmlinux 0x00000000 skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0x00000000 skb_find_text +EXPORT_SYMBOL vmlinux 0x00000000 skb_free_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_gso_segment +EXPORT_SYMBOL vmlinux 0x00000000 skb_insert +EXPORT_SYMBOL vmlinux 0x00000000 skb_kill_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_over_panic +EXPORT_SYMBOL vmlinux 0x00000000 skb_pad +EXPORT_SYMBOL vmlinux 0x00000000 skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_pull +EXPORT_SYMBOL vmlinux 0x00000000 skb_push +EXPORT_SYMBOL vmlinux 0x00000000 skb_put +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_head +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_purge +EXPORT_SYMBOL vmlinux 0x00000000 skb_queue_tail +EXPORT_SYMBOL vmlinux 0x00000000 skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0x00000000 skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x00000000 skb_seq_read +EXPORT_SYMBOL vmlinux 0x00000000 skb_split +EXPORT_SYMBOL vmlinux 0x00000000 skb_store_bits +EXPORT_SYMBOL vmlinux 0x00000000 skb_trim +EXPORT_SYMBOL vmlinux 0x00000000 skb_truesize_bug +EXPORT_SYMBOL vmlinux 0x00000000 skb_under_panic +EXPORT_SYMBOL vmlinux 0x00000000 skb_unlink +EXPORT_SYMBOL vmlinux 0x00000000 sleep_on +EXPORT_SYMBOL vmlinux 0x00000000 sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x00000000 snprintf +EXPORT_SYMBOL vmlinux 0x00000000 sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_create +EXPORT_SYMBOL vmlinux 0x00000000 sock_create_kern +EXPORT_SYMBOL vmlinux 0x00000000 sock_create_lite +EXPORT_SYMBOL vmlinux 0x00000000 sock_get_timestamp +EXPORT_SYMBOL vmlinux 0x00000000 sock_get_timestampns +EXPORT_SYMBOL vmlinux 0x00000000 sock_i_ino +EXPORT_SYMBOL vmlinux 0x00000000 sock_i_uid +EXPORT_SYMBOL vmlinux 0x00000000 sock_init_data +EXPORT_SYMBOL vmlinux 0x00000000 sock_kfree_s +EXPORT_SYMBOL vmlinux 0x00000000 sock_kmalloc +EXPORT_SYMBOL vmlinux 0x00000000 sock_map_fd +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_accept +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_bind +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_connect +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_getname +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_listen +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_mmap +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_poll +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x00000000 sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x00000000 sock_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_register +EXPORT_SYMBOL vmlinux 0x00000000 sock_release +EXPORT_SYMBOL vmlinux 0x00000000 sock_rfree +EXPORT_SYMBOL vmlinux 0x00000000 sock_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 sock_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 sock_unregister +EXPORT_SYMBOL vmlinux 0x00000000 sock_wake_async +EXPORT_SYMBOL vmlinux 0x00000000 sock_wfree +EXPORT_SYMBOL vmlinux 0x00000000 sock_wmalloc +EXPORT_SYMBOL vmlinux 0x00000000 sockfd_lookup +EXPORT_SYMBOL vmlinux 0x00000000 sort +EXPORT_SYMBOL vmlinux 0x00000000 splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0x00000000 sprintf +EXPORT_SYMBOL vmlinux 0x00000000 srandom32 +EXPORT_SYMBOL vmlinux 0x00000000 sscanf +EXPORT_SYMBOL vmlinux 0x00000000 starget_for_each_device +EXPORT_SYMBOL vmlinux 0x00000000 start_tty +EXPORT_SYMBOL vmlinux 0x00000000 stop_tty +EXPORT_SYMBOL vmlinux 0x00000000 strcasecmp +EXPORT_SYMBOL vmlinux 0x00000000 strcat +EXPORT_SYMBOL vmlinux 0x00000000 strchr +EXPORT_SYMBOL vmlinux 0x00000000 strcmp +EXPORT_SYMBOL vmlinux 0x00000000 strcpy +EXPORT_SYMBOL vmlinux 0x00000000 strcspn +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtol +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoll +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoul +EXPORT_SYMBOL vmlinux 0x00000000 strict_strtoull +EXPORT_SYMBOL vmlinux 0x00000000 strlcat +EXPORT_SYMBOL vmlinux 0x00000000 strlcpy +EXPORT_SYMBOL vmlinux 0x00000000 strlen +EXPORT_SYMBOL vmlinux 0x00000000 strncasecmp +EXPORT_SYMBOL vmlinux 0x00000000 strncat +EXPORT_SYMBOL vmlinux 0x00000000 strnchr +EXPORT_SYMBOL vmlinux 0x00000000 strncmp +EXPORT_SYMBOL vmlinux 0x00000000 strncpy +EXPORT_SYMBOL vmlinux 0x00000000 strndup_user +EXPORT_SYMBOL vmlinux 0x00000000 strnicmp +EXPORT_SYMBOL vmlinux 0x00000000 strnlen +EXPORT_SYMBOL vmlinux 0x00000000 strpbrk +EXPORT_SYMBOL vmlinux 0x00000000 strrchr +EXPORT_SYMBOL vmlinux 0x00000000 strsep +EXPORT_SYMBOL vmlinux 0x00000000 strspn +EXPORT_SYMBOL vmlinux 0x00000000 strstr +EXPORT_SYMBOL vmlinux 0x00000000 strstrip +EXPORT_SYMBOL vmlinux 0x00000000 submit_bh +EXPORT_SYMBOL vmlinux 0x00000000 submit_bio +EXPORT_SYMBOL vmlinux 0x00000000 sunrpc_cache_lookup +EXPORT_SYMBOL vmlinux 0x00000000 sunrpc_cache_update +EXPORT_SYMBOL vmlinux 0x00000000 svc_auth_register +EXPORT_SYMBOL vmlinux 0x00000000 svc_auth_unregister +EXPORT_SYMBOL vmlinux 0x00000000 svc_authenticate +EXPORT_SYMBOL vmlinux 0x00000000 svc_create +EXPORT_SYMBOL vmlinux 0x00000000 svc_create_pooled +EXPORT_SYMBOL vmlinux 0x00000000 svc_destroy +EXPORT_SYMBOL vmlinux 0x00000000 svc_drop +EXPORT_SYMBOL vmlinux 0x00000000 svc_exit_thread +EXPORT_SYMBOL vmlinux 0x00000000 svc_prepare_thread +EXPORT_SYMBOL vmlinux 0x00000000 svc_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 svc_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 svc_process +EXPORT_SYMBOL vmlinux 0x00000000 svc_recv +EXPORT_SYMBOL vmlinux 0x00000000 svc_reserve +EXPORT_SYMBOL vmlinux 0x00000000 svc_seq_show +EXPORT_SYMBOL vmlinux 0x00000000 svc_set_client +EXPORT_SYMBOL vmlinux 0x00000000 svc_set_num_threads +EXPORT_SYMBOL vmlinux 0x00000000 svc_sock_names +EXPORT_SYMBOL vmlinux 0x00000000 svc_sock_update_bufs +EXPORT_SYMBOL vmlinux 0x00000000 svc_wake_up +EXPORT_SYMBOL vmlinux 0x00000000 svcauth_unix_purge +EXPORT_SYMBOL vmlinux 0x00000000 svcauth_unix_set_client +EXPORT_SYMBOL vmlinux 0x00000000 sync_blockdev +EXPORT_SYMBOL vmlinux 0x00000000 sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0x00000000 sync_inode +EXPORT_SYMBOL vmlinux 0x00000000 sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0x00000000 sync_page_range +EXPORT_SYMBOL vmlinux 0x00000000 sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0x00000000 synchronize_net +EXPORT_SYMBOL vmlinux 0x00000000 sys_close +EXPORT_SYMBOL vmlinux 0x00000000 sys_tz +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_data +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_intvec +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_string +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_dma_copybreak +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0x00000000 sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0x00000000 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0x00000000 sysfs_streq +EXPORT_SYMBOL vmlinux 0x00000000 system_rev +EXPORT_SYMBOL vmlinux 0x00000000 system_serial_high +EXPORT_SYMBOL vmlinux 0x00000000 system_serial_low +EXPORT_SYMBOL vmlinux 0x00000000 system_state +EXPORT_SYMBOL vmlinux 0x00000000 take_over_console +EXPORT_SYMBOL vmlinux 0x00000000 task_nice +EXPORT_SYMBOL vmlinux 0x00000000 task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_session_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0x00000000 tasklet_init +EXPORT_SYMBOL vmlinux 0x00000000 tasklet_kill +EXPORT_SYMBOL vmlinux 0x00000000 tcp_check_req +EXPORT_SYMBOL vmlinux 0x00000000 tcp_child_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_close +EXPORT_SYMBOL vmlinux 0x00000000 tcp_connect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0x00000000 tcp_disconnect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0x00000000 tcp_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 tcp_hashinfo +EXPORT_SYMBOL vmlinux 0x00000000 tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x00000000 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0x00000000 tcp_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 tcp_make_synack +EXPORT_SYMBOL vmlinux 0x00000000 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0x00000000 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x00000000 tcp_mtup_init +EXPORT_SYMBOL vmlinux 0x00000000 tcp_parse_options +EXPORT_SYMBOL vmlinux 0x00000000 tcp_poll +EXPORT_SYMBOL vmlinux 0x00000000 tcp_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 tcp_prot +EXPORT_SYMBOL vmlinux 0x00000000 tcp_rcv_established +EXPORT_SYMBOL vmlinux 0x00000000 tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_read_sock +EXPORT_SYMBOL vmlinux 0x00000000 tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x00000000 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sendpage +EXPORT_SYMBOL vmlinux 0x00000000 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 tcp_shutdown +EXPORT_SYMBOL vmlinux 0x00000000 tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x00000000 tcp_splice_read +EXPORT_SYMBOL vmlinux 0x00000000 tcp_sync_mss +EXPORT_SYMBOL vmlinux 0x00000000 tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0x00000000 tcp_tso_segment +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_connect +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0x00000000 tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0x00000000 test_set_page_writeback +EXPORT_SYMBOL vmlinux 0x00000000 thaw_bdev +EXPORT_SYMBOL vmlinux 0x00000000 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 timespec_trunc +EXPORT_SYMBOL vmlinux 0x00000000 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 totalram_pages +EXPORT_SYMBOL vmlinux 0x00000000 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0x00000000 touch_atime +EXPORT_SYMBOL vmlinux 0x00000000 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x00000000 truncate_inode_pages +EXPORT_SYMBOL vmlinux 0x00000000 truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0x00000000 try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x00000000 try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x00000000 try_to_release_page +EXPORT_SYMBOL vmlinux 0x00000000 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x00000000 tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0x00000000 tty_check_change +EXPORT_SYMBOL vmlinux 0x00000000 tty_devnum +EXPORT_SYMBOL vmlinux 0x00000000 tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0x00000000 tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0x00000000 tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_hangup +EXPORT_SYMBOL vmlinux 0x00000000 tty_hung_up_p +EXPORT_SYMBOL vmlinux 0x00000000 tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0x00000000 tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0x00000000 tty_mutex +EXPORT_SYMBOL vmlinux 0x00000000 tty_name +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0x00000000 tty_port_init +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_device +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x00000000 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0x00000000 tty_set_operations +EXPORT_SYMBOL vmlinux 0x00000000 tty_std_termios +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0x00000000 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 tty_throttle +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_device +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0x00000000 tty_unthrottle +EXPORT_SYMBOL vmlinux 0x00000000 tty_vhangup +EXPORT_SYMBOL vmlinux 0x00000000 tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0x00000000 tty_write_room +EXPORT_SYMBOL vmlinux 0x00000000 uart_add_one_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0x00000000 uart_get_divisor +EXPORT_SYMBOL vmlinux 0x00000000 uart_match_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_register_driver +EXPORT_SYMBOL vmlinux 0x00000000 uart_remove_one_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_resume_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_suspend_port +EXPORT_SYMBOL vmlinux 0x00000000 uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x00000000 uart_update_timeout +EXPORT_SYMBOL vmlinux 0x00000000 uart_write_wakeup +EXPORT_SYMBOL vmlinux 0x00000000 udp_disconnect +EXPORT_SYMBOL vmlinux 0x00000000 udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0x00000000 udp_hash +EXPORT_SYMBOL vmlinux 0x00000000 udp_hash_lock +EXPORT_SYMBOL vmlinux 0x00000000 udp_ioctl +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_get_port +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0x00000000 udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0x00000000 udp_memory_allocated +EXPORT_SYMBOL vmlinux 0x00000000 udp_poll +EXPORT_SYMBOL vmlinux 0x00000000 udp_proc_register +EXPORT_SYMBOL vmlinux 0x00000000 udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x00000000 udp_prot +EXPORT_SYMBOL vmlinux 0x00000000 udp_sendmsg +EXPORT_SYMBOL vmlinux 0x00000000 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0x00000000 udplite_hash +EXPORT_SYMBOL vmlinux 0x00000000 udplite_prot +EXPORT_SYMBOL vmlinux 0x00000000 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x00000000 unix_domain_find +EXPORT_SYMBOL vmlinux 0x00000000 unlock_buffer +EXPORT_SYMBOL vmlinux 0x00000000 unlock_new_inode +EXPORT_SYMBOL vmlinux 0x00000000 unlock_page +EXPORT_SYMBOL vmlinux 0x00000000 unlock_rename +EXPORT_SYMBOL vmlinux 0x00000000 unlock_super +EXPORT_SYMBOL vmlinux 0x00000000 unmap_mapping_range +EXPORT_SYMBOL vmlinux 0x00000000 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0x00000000 unregister_binfmt +EXPORT_SYMBOL vmlinux 0x00000000 unregister_blkdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x00000000 unregister_con_driver +EXPORT_SYMBOL vmlinux 0x00000000 unregister_console +EXPORT_SYMBOL vmlinux 0x00000000 unregister_exec_domain +EXPORT_SYMBOL vmlinux 0x00000000 unregister_filesystem +EXPORT_SYMBOL vmlinux 0x00000000 unregister_inet6addr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_key_type +EXPORT_SYMBOL vmlinux 0x00000000 unregister_md_personality +EXPORT_SYMBOL vmlinux 0x00000000 unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_mtd_chip_driver +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdev +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdevice +EXPORT_SYMBOL vmlinux 0x00000000 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x00000000 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0x00000000 unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0x00000000 up +EXPORT_SYMBOL vmlinux 0x00000000 up_read +EXPORT_SYMBOL vmlinux 0x00000000 up_write +EXPORT_SYMBOL vmlinux 0x00000000 update_region +EXPORT_SYMBOL vmlinux 0x00000000 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x00000000 user_path_at +EXPORT_SYMBOL vmlinux 0x00000000 user_revoke +EXPORT_SYMBOL vmlinux 0x00000000 vc_cons +EXPORT_SYMBOL vmlinux 0x00000000 vc_resize +EXPORT_SYMBOL vmlinux 0x00000000 vfree +EXPORT_SYMBOL vmlinux 0x00000000 vfs_create +EXPORT_SYMBOL vmlinux 0x00000000 vfs_follow_link +EXPORT_SYMBOL vmlinux 0x00000000 vfs_fstat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_getattr +EXPORT_SYMBOL vmlinux 0x00000000 vfs_link +EXPORT_SYMBOL vmlinux 0x00000000 vfs_llseek +EXPORT_SYMBOL vmlinux 0x00000000 vfs_lstat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_mkdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_mknod +EXPORT_SYMBOL vmlinux 0x00000000 vfs_path_lookup +EXPORT_SYMBOL vmlinux 0x00000000 vfs_permission +EXPORT_SYMBOL vmlinux 0x00000000 vfs_read +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_readv +EXPORT_SYMBOL vmlinux 0x00000000 vfs_rename +EXPORT_SYMBOL vmlinux 0x00000000 vfs_rmdir +EXPORT_SYMBOL vmlinux 0x00000000 vfs_stat +EXPORT_SYMBOL vmlinux 0x00000000 vfs_statfs +EXPORT_SYMBOL vmlinux 0x00000000 vfs_symlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_unlink +EXPORT_SYMBOL vmlinux 0x00000000 vfs_write +EXPORT_SYMBOL vmlinux 0x00000000 vfs_writev +EXPORT_SYMBOL vmlinux 0x00000000 vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0x00000000 vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_mixed +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_page +EXPORT_SYMBOL vmlinux 0x00000000 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0x00000000 vm_stat +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_32 +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_node +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x00000000 vmalloc_user +EXPORT_SYMBOL vmlinux 0x00000000 vmap +EXPORT_SYMBOL vmlinux 0x00000000 vmtruncate +EXPORT_SYMBOL vmlinux 0x00000000 vprintk +EXPORT_SYMBOL vmlinux 0x00000000 vscnprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsnprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsprintf +EXPORT_SYMBOL vmlinux 0x00000000 vsscanf +EXPORT_SYMBOL vmlinux 0x00000000 vunmap +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x00000000 wait_for_key_construction +EXPORT_SYMBOL vmlinux 0x00000000 wait_on_page_bit +EXPORT_SYMBOL vmlinux 0x00000000 wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0x00000000 wake_bit_function +EXPORT_SYMBOL vmlinux 0x00000000 wake_up_bit +EXPORT_SYMBOL vmlinux 0x00000000 wake_up_process +EXPORT_SYMBOL vmlinux 0x00000000 walk_stackframe +EXPORT_SYMBOL vmlinux 0x00000000 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x00000000 warn_slowpath +EXPORT_SYMBOL vmlinux 0x00000000 write_cache_pages +EXPORT_SYMBOL vmlinux 0x00000000 write_inode_now +EXPORT_SYMBOL vmlinux 0x00000000 write_one_page +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_from_iov +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_read_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_buf_subsegment +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_array2 +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_string_inplace +EXPORT_SYMBOL vmlinux 0x00000000 xdr_decode_word +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_array2 +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_netobj +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_opaque +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_opaque_fixed +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_string +EXPORT_SYMBOL vmlinux 0x00000000 xdr_encode_word +EXPORT_SYMBOL vmlinux 0x00000000 xdr_enter_page +EXPORT_SYMBOL vmlinux 0x00000000 xdr_init_decode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_init_encode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_inline_decode +EXPORT_SYMBOL vmlinux 0x00000000 xdr_inline_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_process_buf +EXPORT_SYMBOL vmlinux 0x00000000 xdr_read_pages +EXPORT_SYMBOL vmlinux 0x00000000 xdr_reserve_space +EXPORT_SYMBOL vmlinux 0x00000000 xdr_shift_buf +EXPORT_SYMBOL vmlinux 0x00000000 xdr_write_pages +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_rcv +EXPORT_SYMBOL vmlinux 0x00000000 xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x00000000 xfrm6_find_1stfragopt +EXPORT_SYMBOL vmlinux 0x00000000 xfrm6_input_addr +EXPORT_SYMBOL vmlinux 0x00000000 xfrm6_prepare_output +EXPORT_SYMBOL vmlinux 0x00000000 xfrm6_rcv +EXPORT_SYMBOL vmlinux 0x00000000 xfrm6_rcv_spi +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_find_acq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_init_state +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_input +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_input_resume +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_lookup +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_nl +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_count +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_km +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_mode +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_register_type +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_add +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_update +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x00000000 xfrm_user_policy +EXPORT_SYMBOL vmlinux 0x00000000 xor_blocks +EXPORT_SYMBOL vmlinux 0x00000000 xrlim_allow +EXPORT_SYMBOL vmlinux 0x00000000 xscale_coherent_kern_range +EXPORT_SYMBOL vmlinux 0x00000000 xscale_flush_kern_cache_all +EXPORT_SYMBOL vmlinux 0x00000000 xscale_flush_user_cache_all +EXPORT_SYMBOL vmlinux 0x00000000 xscale_flush_user_cache_range +EXPORT_SYMBOL vmlinux 0x00000000 xscale_mc_clear_user_page +EXPORT_SYMBOL vmlinux 0x00000000 xscale_mc_copy_user_page +EXPORT_SYMBOL vmlinux 0x00000000 yield +EXPORT_SYMBOL vmlinux 0x00000000 zero_fill_bio +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflate +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateEnd +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateInit2 +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflateReset +EXPORT_SYMBOL vmlinux 0x00000000 zlib_deflate_workspacesize +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x00000000 zlib_inflate_workspacesize +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __async_tx_find_channel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __ata_ehi_push_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __class_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __gpio_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __gpio_get_value +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __gpio_set_value +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __scsi_get_command +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __usb_get_extra_descriptor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0x00000000 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x00000000 alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 arm_pm_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_memcpy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_trigger_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_issue_pending_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_quiesce +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_run_dependencies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_tx_submit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_xor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 async_xor_zero_sum +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_base_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_mode_filter +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_setup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bmdma_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_bus_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_40wire +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_80wire +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_ignore +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_sata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_cable_unknown +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dev_classify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dev_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dev_pair +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_do_dev_read_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_do_eh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_do_set_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dummy_port_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_dummy_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_analyze_ncq_error +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_freeze_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_qc_complete +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_qc_retry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_eh_thaw_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_ehi_clear_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_ehi_push_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_activate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_alloc_pinfo +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_detach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_host_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_id_c_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_id_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_id_xfermask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_link_abort +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_link_offline +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_link_online +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_mode_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_noop_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pack_xfermask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_bmdma_clear_simplex +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_bmdma_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_remove_one +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_activate_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_init_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_init_one +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pci_sff_prepare_host +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_pio_need_iordy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_abort +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_freeze +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_pbar_desc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_probe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_schedule_eh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_port_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_qc_complete +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_qc_complete_multiple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_ratelimit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_port_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_queuecmd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sas_slave_configure +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_change_queue_depth +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_queuecmd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_simulate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_slave_config +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_scsi_slave_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_busy_sleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_check_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_data_xfer +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_data_xfer_noirq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dev_classify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dev_select +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dma_pause +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_dumb_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_error_handler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_exec_command +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_freeze +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_host_intr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_hsm_move +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_interrupt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_irq_clear +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_irq_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_pause +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_port_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_post_internal_cmd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_postreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_prereset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_qc_fill_rtf +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_qc_issue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_qc_prep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_softreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_std_ports +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_tf_load +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_tf_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_thaw +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_wait_after_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sff_wait_ready +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_sg_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_bios_param +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_error_handler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_postreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_prereset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_std_qc_defer +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_tf_from_fis +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_tf_to_fis +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_compute +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_cycle2mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_find_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_timing_merge +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_unpack_xfermask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_wait_after_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_wait_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_xfer_mask2mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_xfer_mode2mask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ata_xfer_mode2shift +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atapi_cmd_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkcipher_walk_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkcipher_walk_phys +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkcipher_walk_virt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkcipher_walk_virt_block +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0001 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0003 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cfi_cmdset_0200 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 console_drivers +EXPORT_SYMBOL_GPL vmlinux 0x00000000 copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0x00000000 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_ablkcipher_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_aes_expand_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_aes_set_key +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_ahash_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alloc_ablkcipher +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_alloc_instance +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_attr_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_attr_alg_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_attr_u32 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_blkcipher_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_check_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_dequeue_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_drop_spawn +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_enqueue_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_fl_tab +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_ft_tab +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_get_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_givcipher_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_grab_skcipher +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_hash_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_hash_walk_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_hash_walk_first +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_il_tab +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_inc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_init_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_init_spawn +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_it_tab +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_error +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_lookup_template +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_instance +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_register_template +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_spawn_tfm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_tfm_in_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_unregister_alg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_unregister_template +EXPORT_SYMBOL_GPL vmlinux 0x00000000 crypto_xor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x00000000 default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 default_mtd_writev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 del_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0x00000000 deregister_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 deregister_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0x00000000 des_ekey +EXPORT_SYMBOL_GPL vmlinux 0x00000000 destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_em_message +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_em_message_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_link_power_management_policy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_attr_sw_activity +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_attach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_initialize +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_move +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_rename +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x00000000 device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_find +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dm_device_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dm_disk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dm_noflush_suspending +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dm_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dm_set_device_limits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dma_wait_for_async_tx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x00000000 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_attach +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_find +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ehci_cf_port_reset_rwsem +EXPORT_SYMBOL_GPL vmlinux 0x00000000 elv_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0x00000000 exit_fs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 exportfs_decode_fh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 exportfs_encode_fh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 find_vpid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fl6_sock_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 flush_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0x00000000 free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_mtd_device_nm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_sb_mtd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0x00000000 getnstimeofday +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_direction_input +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_direction_output +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_export +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_get_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_request +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_set_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpio_unexport +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpiochip_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpiochip_is_requested +EXPORT_SYMBOL_GPL vmlinux 0x00000000 gpiochip_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_free_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_input_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_output_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_parse_report +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hid_set_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_connect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_disconnect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_find_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hidinput_report_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hwmon_device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hwmon_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hwrng_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 hwrng_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_dummy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_new_probed_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 i2c_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_csk_xmit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_destroy_sock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet6_sk_rebuild_header +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_diag_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_diag_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_hash +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_add_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_dentry_parent_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_find_update_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_find_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_get_cookie +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_init_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_inode_is_dead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_inode_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_remove_watch_locked +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_rm_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_rm_wd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inotify_unmount_inodes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0x00000000 invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0x00000000 inverse_translate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip6_dst_blackhole +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip6_dst_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip6_local_out +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip6_sk_dst_lookup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ipv6_dup_options +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ipv6_find_tlv +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ipv6_opt_accepted +EXPORT_SYMBOL_GPL vmlinux 0x00000000 jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x00000000 k_handler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kbd_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x00000000 key_type_user +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kill_mtd_super +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0x00000000 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kmem_cache_name +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0x00000000 kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_add_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x00000000 ktime_sub_ns +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x00000000 md_allow_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 md_do_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 md_new_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mmput +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_erase_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 mtd_table_mutex +EXPORT_SYMBOL_GPL vmlinux 0x00000000 net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x00000000 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0x00000000 net_ipv6_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0x00000000 netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nfs_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nfsd_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlm_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmclnt_proc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x00000000 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0x00000000 page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0x00000000 parse_mtd_partitions +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_block_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_bus_add_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_bus_max_busnr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_create_slot +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_destroy_slot +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_ext_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_next_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_find_next_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_intx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_scan_child_bus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_set_pcie_reset_state +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_slots_kset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_stop_bus_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_test_config_bits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_unblock_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pci_update_slot_number +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pciserial_init_ports +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pciserial_remove_ports +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pciserial_resume_ports +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pciserial_suspend_ports +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0x00000000 platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x00000000 posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0x00000000 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x00000000 probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0x00000000 proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_mtd_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_pid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 put_rpccred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0x00000000 raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rdev_get_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rdev_get_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_blktrans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_parser +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 register_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_enable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_bulk_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_enable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_force_disable +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_current_limit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_supply +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_get_voltage +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_is_enabled +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_current_limit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_device_supply +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_drvdata +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_machine_constraints +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_optimum_mode +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_supply +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_set_voltage +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_suspend_prepare +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 regulator_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x00000000 round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_alloc_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_bind_new_program +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_calc_rto +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_null +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_call_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_clone_client +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_debug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_delay +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_exit_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_force_rebind +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_free_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_init_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_init_wait_queue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_killall_tasks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_lookup_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_malloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_peeraddr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_peeraddr2str +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_print_iostats +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_proc_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_proc_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_put_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_restart_call +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_run_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_setbufsize +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_shutdown_client +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_sleep_on +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_next +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpc_wake_up_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_create +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_init_cred +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_init_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcauth_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcb_getport_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rpcb_getport_sync +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_class_close +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_class_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_device_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_set_freq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_set_state +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_irq_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_read_alarm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_read_time +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_set_alarm +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_set_mmss +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_set_time +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtc_update_irq +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_async_notification +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_deb_timing_hotplug +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_deb_timing_long +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_deb_timing_normal +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_link_debounce +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_link_hardreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_link_resume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_port_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_valid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_scr_write_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_set_spd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_sff_hardreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sata_std_hardreset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_copychunks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_map +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_map_and_copy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scatterwalk_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0x00000000 screen_glyph +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_complete_async_scans +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_eh_get_sense +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_eh_ready_devs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_execute_async +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_flush_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_internal_device_block +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_internal_device_unblock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_mode_select +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_queue_work +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_schedule_eh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_target_block +EXPORT_SYMBOL_GPL vmlinux 0x00000000 scsi_target_unblock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdev_evt_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdev_evt_send +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sdev_evt_send_simple +EXPORT_SYMBOL_GPL vmlinux 0x00000000 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0x00000000 seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0x00000000 simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 single_release_net +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_morph +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skcipher_geniv_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skcipher_geniv_exit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skcipher_geniv_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 skcipher_geniv_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_addsock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_close_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_create_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_find_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_max_payload +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_print_addr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_reg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_unreg_xprt_class +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_enqueue +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_names +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_put +EXPORT_SYMBOL_GPL vmlinux 0x00000000 svc_xprt_received +EXPORT_SYMBOL_GPL vmlinux 0x00000000 symbol_put_addr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sync_page_io +EXPORT_SYMBOL_GPL vmlinux 0x00000000 synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x00000000 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x00000000 thread_notify_head +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0x00000000 twofish_setkey +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uhci_check_and_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 uhci_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_mtd_user +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x00000000 unregister_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_add_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_alloc_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_altnum_to_altsetting +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_anchor_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_alloc +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_free +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_map_sg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_buffer_unmap_sg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_bulk_msg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_bus_list +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_bus_list_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_calc_bus_time +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_clear_halt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_control_msg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_create_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_deregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_deregister_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_deregister_device_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_disabled +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_driver_claim_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_driver_release_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_driver_set_configuration +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_ep0_reinit +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_find_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_free_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_current_frame_number +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_descriptor +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_intf +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_get_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hc_died +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_check_unlink_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_giveback_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_link_urb_to_ep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_pci_probe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_pci_remove +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_pci_shutdown +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_platform_shutdown +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_poll_rh_status +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcd_unlink_urb_from_ep +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hcds_loaded +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_hub_tt_clear_buffer +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_ifnum_to_if +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_init_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_interrupt_msg +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_kill_anchored_urbs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_kill_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_lock_device_for_reset +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_match_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_match_one_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_mon_deregister +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_mon_register +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_put_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_put_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_put_intf +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_dev +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_device_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_register_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_remove_hcd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_reset_configuration +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_reset_device +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_set_interface +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_sg_cancel +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_sg_init +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_sg_wait +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_store_new_id +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_string +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_submit_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unanchor_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unlink_anchored_urbs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unlink_urb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_unregister_notify +EXPORT_SYMBOL_GPL vmlinux 0x00000000 usb_wait_anchor_empty_timeout +EXPORT_SYMBOL_GPL vmlinux 0x00000000 user_describe +EXPORT_SYMBOL_GPL vmlinux 0x00000000 user_destroy +EXPORT_SYMBOL_GPL vmlinux 0x00000000 user_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x00000000 user_match +EXPORT_SYMBOL_GPL vmlinux 0x00000000 user_read +EXPORT_SYMBOL_GPL vmlinux 0x00000000 user_update +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0x00000000 vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xdr_skb_read_bits +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_adjust_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_complete_rqst +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_disconnect_done +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_lookup_rqst +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_register_transport +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_rqst_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_release_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_reserve_xprt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_unregister_transport +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_update_rtt +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL vmlinux 0x00000000 xprt_write_space +EXPORT_SYMBOL_GPL vmlinux 0x00000000 zap_vma_ptes --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/armel/ignore +++ linux-2.6.27/debian/abi/2.6.27-8.17/armel/ignore @@ -0,0 +1 @@ +1 --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/i386/server +++ linux-2.6.27/debian/abi/2.6.27-8.17/i386/server @@ -0,0 +1,8194 @@ +EXPORT_SYMBOL arch/x86/kernel/scx200 0x254e5667 scx200_gpio_base +EXPORT_SYMBOL arch/x86/kernel/scx200 0x35a3c008 scx200_gpio_configure +EXPORT_SYMBOL arch/x86/kernel/scx200 0x8cfa375c scx200_gpio_shadow +EXPORT_SYMBOL arch/x86/kernel/scx200 0x907665bd scx200_cb_base +EXPORT_SYMBOL arch/x86/kvm/kvm 0xc2004b14 kvm_cpu_has_pending_timer +EXPORT_SYMBOL arch/x86/kvm/kvm 0xdde96d90 kvm_read_guest_atomic +EXPORT_SYMBOL crypto/gf128mul 0x0c2f123f gf128mul_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x1068004b gf128mul_bbe +EXPORT_SYMBOL crypto/gf128mul 0x2f2889a0 gf128mul_init_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0x3755f990 gf128mul_init_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x384ef9ce gf128mul_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x56af0dbd gf128mul_x_ble +EXPORT_SYMBOL crypto/gf128mul 0x83581089 gf128mul_init_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0x9b2560b9 gf128mul_init_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x9e13f6f6 gf128mul_lle +EXPORT_SYMBOL crypto/gf128mul 0xbd17a0df gf128mul_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0xc0890413 gf128mul_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0xd60736ec gf128mul_free_64k +EXPORT_SYMBOL crypto/xor 0x5b6c00e6 xor_blocks +EXPORT_SYMBOL drivers/acpi/processor 0x0603377d acpi_processor_preregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0x8461fbfe acpi_processor_unregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0xd78b77e1 acpi_processor_register_performance +EXPORT_SYMBOL drivers/acpi/processor 0xe420d26f acpi_processor_notify_smm +EXPORT_SYMBOL drivers/acpi/processor 0xe8a3605f acpi_processor_set_thermal_limit +EXPORT_SYMBOL drivers/atm/suni 0x074325b8 suni_init +EXPORT_SYMBOL drivers/atm/uPD98402 0x65326e91 uPD98402_init +EXPORT_SYMBOL drivers/block/loop 0xa86449c3 loop_register_transfer +EXPORT_SYMBOL drivers/block/loop 0xbfee3ad5 loop_unregister_transfer +EXPORT_SYMBOL drivers/block/paride/paride 0x349d9f96 paride_unregister +EXPORT_SYMBOL drivers/block/paride/paride 0x361e9597 pi_connect +EXPORT_SYMBOL drivers/block/paride/paride 0x64904242 pi_init +EXPORT_SYMBOL drivers/block/paride/paride 0x664815a3 pi_do_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0x807ec49d pi_schedule_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0x907297fc pi_write_block +EXPORT_SYMBOL drivers/block/paride/paride 0x9137f9b3 pi_release +EXPORT_SYMBOL drivers/block/paride/paride 0xafcfc58a paride_register +EXPORT_SYMBOL drivers/block/paride/paride 0xc52a209c pi_read_block +EXPORT_SYMBOL drivers/block/paride/paride 0xe1458d91 pi_write_regr +EXPORT_SYMBOL drivers/block/paride/paride 0xebdc6257 pi_disconnect +EXPORT_SYMBOL drivers/block/paride/paride 0xfc48ad65 pi_read_regr +EXPORT_SYMBOL drivers/cdrom/cdrom 0x05cc8aab cdrom_number_of_slots +EXPORT_SYMBOL drivers/cdrom/cdrom 0x2086977e cdrom_mode_sense +EXPORT_SYMBOL drivers/cdrom/cdrom 0x2d9e1b0c unregister_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0x4f476e96 init_cdrom_command +EXPORT_SYMBOL drivers/cdrom/cdrom 0x665fbcb4 cdrom_release +EXPORT_SYMBOL drivers/cdrom/cdrom 0x87e218fc cdrom_ioctl +EXPORT_SYMBOL drivers/cdrom/cdrom 0xa091e2a8 cdrom_media_changed +EXPORT_SYMBOL drivers/cdrom/cdrom 0xaf980837 cdrom_mode_select +EXPORT_SYMBOL drivers/cdrom/cdrom 0xc696c59f cdrom_get_last_written +EXPORT_SYMBOL drivers/cdrom/cdrom 0xcb80c8b4 register_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0xda0269b2 cdrom_get_media_event +EXPORT_SYMBOL drivers/cdrom/cdrom 0xf80c41ea cdrom_open +EXPORT_SYMBOL drivers/char/agp/agpgart 0x04064b56 agp_backend_release +EXPORT_SYMBOL drivers/char/agp/agpgart 0x12d1c60f agp_find_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0x1995ce1f agp_generic_free_by_type +EXPORT_SYMBOL drivers/char/agp/agpgart 0x1bdf032d agp_enable +EXPORT_SYMBOL drivers/char/agp/agpgart 0x1ce9cd05 agp_free_page_array +EXPORT_SYMBOL drivers/char/agp/agpgart 0x1e2f5175 agp_generic_destroy_page +EXPORT_SYMBOL drivers/char/agp/agpgart 0x21c15340 agp_generic_mask_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x22a6c91a agp_alloc_page_array +EXPORT_SYMBOL drivers/char/agp/agpgart 0x28364d71 agp_free_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x301c7ee2 agp_generic_create_gatt_table +EXPORT_SYMBOL drivers/char/agp/agpgart 0x30226ddf agp_device_command +EXPORT_SYMBOL drivers/char/agp/agpgart 0x34957f27 agp_generic_alloc_by_type +EXPORT_SYMBOL drivers/char/agp/agpgart 0x360ea9c3 agp_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0x36e7f038 agp_generic_enable +EXPORT_SYMBOL drivers/char/agp/agpgart 0x4b085dbf agp3_generic_configure +EXPORT_SYMBOL drivers/char/agp/agpgart 0x5bcd56a8 agp_collect_device_status +EXPORT_SYMBOL drivers/char/agp/agpgart 0x673f815e agp_bridges +EXPORT_SYMBOL drivers/char/agp/agpgart 0x6dc875b7 agp_generic_free_gatt_table +EXPORT_SYMBOL drivers/char/agp/agpgart 0x7538b132 agp_off +EXPORT_SYMBOL drivers/char/agp/agpgart 0x767d2376 agp3_generic_tlbflush +EXPORT_SYMBOL drivers/char/agp/agpgart 0x7aef3c2b agp_create_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x7c08c894 agp_generic_remove_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x7c69be5c agp_unbind_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x8bae1c71 agp_alloc_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0x9378bd4d agp_put_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0xa4d4f0e6 global_cache_flush +EXPORT_SYMBOL drivers/char/agp/agpgart 0xabba529c agp_copy_info +EXPORT_SYMBOL drivers/char/agp/agpgart 0xabcc63bb agp_generic_alloc_page +EXPORT_SYMBOL drivers/char/agp/agpgart 0xabf6b513 agp_generic_alloc_user +EXPORT_SYMBOL drivers/char/agp/agpgart 0xb04ea8f0 agp_rebind_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xb4983adf agp_allocate_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc2424641 agp3_generic_cleanup +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc5d9c46c agp_try_unsupported_boot +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc65abeb7 agp3_generic_sizes +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc6faa043 get_agp_version +EXPORT_SYMBOL drivers/char/agp/agpgart 0xd0fef3b2 agp_free_key +EXPORT_SYMBOL drivers/char/agp/agpgart 0xd9cefbae agp_flush_chipset +EXPORT_SYMBOL drivers/char/agp/agpgart 0xde9b17ed agp3_generic_fetch_size +EXPORT_SYMBOL drivers/char/agp/agpgart 0xe3993621 agp_backend_acquire +EXPORT_SYMBOL drivers/char/agp/agpgart 0xf5178a4f agp_generic_insert_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xfe216d61 agp_generic_type_to_mask_type +EXPORT_SYMBOL drivers/char/agp/agpgart 0xfe73bf86 agp_bind_memory +EXPORT_SYMBOL drivers/char/generic_serial 0x1b2e2128 gs_getserial +EXPORT_SYMBOL drivers/char/generic_serial 0x204a8c75 gs_put_char +EXPORT_SYMBOL drivers/char/generic_serial 0x3da6a909 gs_got_break +EXPORT_SYMBOL drivers/char/generic_serial 0x3ee3a1fb gs_close +EXPORT_SYMBOL drivers/char/generic_serial 0x416736a9 gs_stop +EXPORT_SYMBOL drivers/char/generic_serial 0x5a03a228 gs_write_room +EXPORT_SYMBOL drivers/char/generic_serial 0x678b83fd gs_start +EXPORT_SYMBOL drivers/char/generic_serial 0x6c025a62 gs_flush_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0x70721be6 gs_chars_in_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0x8cd37ae0 gs_flush_chars +EXPORT_SYMBOL drivers/char/generic_serial 0x9ac8d95e gs_write +EXPORT_SYMBOL drivers/char/generic_serial 0xc883cb7d gs_block_til_ready +EXPORT_SYMBOL drivers/char/generic_serial 0xda969561 gs_init_port +EXPORT_SYMBOL drivers/char/generic_serial 0xdf122249 gs_set_termios +EXPORT_SYMBOL drivers/char/generic_serial 0xeb55ec2a gs_setserial +EXPORT_SYMBOL drivers/char/generic_serial 0xf1642f13 gs_hangup +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0026ef2e ipmi_smi_watchdog_pretimeout +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0d59e7a1 ipmi_unregister_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x104c8802 ipmi_set_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x1d63851a ipmi_get_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2beb1128 ipmi_set_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2d0df23d ipmi_request_supply_msgs +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x40f2b10c ipmi_alloc_smi_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x462549fa ipmi_smi_msg_received +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x4f64bf1c ipmi_poll_interface +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x522e1a58 ipmi_get_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x66b151a1 ipmi_register_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x6ec4fed6 ipmi_get_version +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x7c2492b5 ipmi_register_smi +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x7e00efd0 ipmi_set_gets_events +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x7e89202e ipmi_destroy_user +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x804f922a ipmi_addr_length +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x85363e4b ipmi_smi_watcher_unregister +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x871fdfdd ipmi_free_recv_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x8decbe47 ipmi_get_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xaa290b89 ipmi_smi_add_proc_entry +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xb46611f6 ipmi_set_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xb526d613 ipmi_unregister_smi +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4f4665b ipmi_validate_addr +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xf3449055 ipmi_request_settime +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xfa261a12 ipmi_smi_watcher_register +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xfae2b2ec ipmi_create_user +EXPORT_SYMBOL drivers/char/nsc_gpio 0x22771650 nsc_gpio_dump +EXPORT_SYMBOL drivers/char/nsc_gpio 0x7d208905 nsc_gpio_write +EXPORT_SYMBOL drivers/char/nsc_gpio 0xf31a245e nsc_gpio_read +EXPORT_SYMBOL drivers/char/nvram 0x0f28cb91 nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x17ff2c1d __nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x2adec1e0 __nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x7da28f12 nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x9ce3f83f nvram_write_byte +EXPORT_SYMBOL drivers/char/nvram 0xa8813189 __nvram_write_byte +EXPORT_SYMBOL drivers/cpufreq/cpufreq_conservative 0xe3ec86b8 cpufreq_gov_conservative +EXPORT_SYMBOL drivers/cpufreq/cpufreq_ondemand 0x83a131ed cpufreq_gov_ondemand +EXPORT_SYMBOL drivers/cpufreq/cpufreq_powersave 0x26d1a0fb cpufreq_gov_powersave +EXPORT_SYMBOL drivers/cpufreq/cpufreq_userspace 0x2b5041de cpufreq_gov_userspace +EXPORT_SYMBOL drivers/edac/edac_core 0x5763876f edac_mc_handle_fbd_ue +EXPORT_SYMBOL drivers/edac/edac_core 0xb5c62933 edac_mc_find +EXPORT_SYMBOL drivers/edac/edac_core 0xfa5e9115 edac_mc_handle_fbd_ce +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0836695c drm_sman_takedown +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0da2fe19 drm_idlelock_take +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0ff71da8 drm_agp_enable +EXPORT_SYMBOL drivers/gpu/drm/drm 0x121ab731 drm_ati_pcigart_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0x12e0ee22 drm_rmmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0x19b0ae8d drm_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0x1cf8b0b9 drm_exit +EXPORT_SYMBOL drivers/gpu/drm/drm 0x20645642 drm_debug +EXPORT_SYMBOL drivers/gpu/drm/drm 0x21451ac4 drm_sman_owner_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x25210080 drm_open +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2916bf63 drm_sman_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2b7b7821 drm_agp_acquire +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2d0850b7 drm_sg_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2de5379a drm_locked_tasklet +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2eb2f903 drm_sman_free_key +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3074f033 drm_order +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3527a3f0 drm_poll +EXPORT_SYMBOL drivers/gpu/drm/drm 0x46ab1b5d drm_i_have_hw_lock +EXPORT_SYMBOL drivers/gpu/drm/drm 0x49aec2dc drm_get_resource_len +EXPORT_SYMBOL drivers/gpu/drm/drm 0x53aefc86 drm_addmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0x55f060ee drm_sman_set_range +EXPORT_SYMBOL drivers/gpu/drm/drm 0x5d89e7f1 drm_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0x60625196 drm_agp_unbind +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6168ef1b drm_core_ioremap +EXPORT_SYMBOL drivers/gpu/drm/drm 0x68e63d08 drm_agp_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x68fed66e drm_addbufs_agp +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6c68d7bb drm_ioctl +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6c7ebf05 drm_pci_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0x78b6e377 drm_pci_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x7e8180f4 drm_agp_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0x8df3352d drm_core_ioremap_wc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9210a724 drm_get_drawable_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9c25b192 drm_core_get_map_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa70a9316 drm_vbl_send_signals +EXPORT_SYMBOL drivers/gpu/drm/drm 0xacad82d4 drm_core_reclaim_buffers +EXPORT_SYMBOL drivers/gpu/drm/drm 0xaf29788e drm_sman_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb97e3fed drm_core_ioremapfree +EXPORT_SYMBOL drivers/gpu/drm/drm 0xbac7056e drm_getsarea +EXPORT_SYMBOL drivers/gpu/drm/drm 0xbc33eef3 drm_agp_bind +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc50ec7d0 drm_agp_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc9272617 drm_fasync +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3028e75 drm_sman_set_manager +EXPORT_SYMBOL drivers/gpu/drm/drm 0xdd498846 drm_idlelock_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xdfff9854 drm_core_get_reg_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe57b8ef8 drm_get_resource_start +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe6d4ff59 drm_ati_pcigart_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe87e751e drm_agp_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe919dd5c drm_sman_owner_clean +EXPORT_SYMBOL drivers/gpu/drm/drm 0xed98b2ff drm_irq_uninstall +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf5b02642 drm_addbufs_pci +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf5f95f19 drm_mmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdfbad19 drm_sman_alloc +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0x0903c239 vid_from_reg +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0xef1c781c vid_which_vrm +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0xc391e77c i2c_bit_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0xfd7ad3d0 i2c_bit_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0x4c0097c2 i2c_pca_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0xdbe3c70e i2c_pca_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pcf 0x8ce4addf i2c_pcf_add_bus +EXPORT_SYMBOL drivers/i2c/busses/i2c-amd756 0x690227cc amd756_smbus +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x02d4ad0f tps65013_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x28485130 tps65010_config_vregs1 +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x33739de7 tps65010_set_vib +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x9fd44c69 tps65010_set_led +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xb14080cc tps65010_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xd5bb106d tps65010_set_vbus_draw +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xe99b3f36 tps65010_set_gpio_out_value +EXPORT_SYMBOL drivers/i2c/i2c-core 0x12aad27c i2c_transfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0x144fbe33 i2c_smbus_read_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0x2796f546 i2c_attach_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x2ac86853 i2c_register_driver +EXPORT_SYMBOL drivers/i2c/i2c-core 0x346531f9 i2c_smbus_write_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x3d79e0ff i2c_smbus_read_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x3e2691e5 i2c_master_send +EXPORT_SYMBOL drivers/i2c/i2c-core 0x3f50016a i2c_release_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x3f733af8 i2c_add_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0x406e4ce9 i2c_get_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0x4a9daa82 i2c_del_driver +EXPORT_SYMBOL drivers/i2c/i2c-core 0x5420623f i2c_smbus_write_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6c9fbe74 i2c_smbus_write_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6fe5f14a i2c_master_recv +EXPORT_SYMBOL drivers/i2c/i2c-core 0x7dc0913e i2c_smbus_read_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x83a358c5 i2c_smbus_xfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0x95df9d85 i2c_probe +EXPORT_SYMBOL drivers/i2c/i2c-core 0x9cbd2f13 i2c_verify_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xa1a9664b i2c_smbus_read_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0xba605985 i2c_use_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xdcdca37f i2c_del_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe383249e i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe47ad574 i2c_put_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe6cb7f3f i2c_clients_command +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe80e6eda i2c_smbus_write_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0xf150c8df i2c_detach_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xfa475afb i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x026a6c3b hpsb_get_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x052b717b hpsb_iso_xmit_sync +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x087919dc hpsb_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0b234c4e dma_prog_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0c6da941 csr1212_release_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0dfa3255 hpsb_iso_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0e5a659c csr1212_new_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0fd461bb hpsb_resume_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x121b040d hpsb_iso_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x12908f16 dma_region_mmap +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x130707b9 hpsb_free_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x13b4a268 csr1212_attach_keyval_to_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x158ac548 dma_region_offset_to_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1eedbc78 hpsb_unregister_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2752b9a8 csr1212_get_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x29139a99 hpsb_iso_xmit_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2e19a379 hpsb_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2e5f628a hpsb_iso_recv_set_channel_mask +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ebf6e5a dma_prog_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x307936ed hpsb_update_config_rom_image +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3396180b hpsb_register_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x37a736c9 csr1212_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x39c585d7 hpsb_make_readpacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3c1727b2 hpsb_bus_reset +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3df73103 hpsb_iso_stop +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4b6357ac hpsb_free_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x535f45d7 hpsb_unregister_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x53a6722e hpsb_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5a6beea4 hpsb_make_lock64packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5e3329be hpsb_get_hostinfo_bykey +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x64d5a1ca hpsb_iso_recv_flush +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x672ad148 dma_region_sync_for_device +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6864763f hpsb_get_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6c600015 hpsb_iso_recv_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7046e886 csr1212_parse_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x722c04c8 hpsb_iso_recv_release_packets +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x767a964b hpsb_set_hostinfo_key +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x76bc1a5c dma_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x791d624c hpsb_make_streampacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x80240469 __hpsb_register_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x804c69f2 hpsb_allocate_and_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x806ef059 hpsb_send_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8180f6a7 hpsb_packet_success +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x82f9c17e hpsb_alloc_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8879f8f0 dma_region_sync_for_cpu +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8c7b6422 hpsb_iso_n_ready +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8cb319b0 hpsb_iso_shutdown +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8ec2b312 dma_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x920ddaae hpsb_update_config_rom +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9531c600 hpsb_selfid_complete +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9a6cf99b hpsb_iso_xmit_queue_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9b04f754 hpsb_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9ba81456 hpsb_unregister_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9bdecb2a hpsb_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa7bfc8e3 hpsb_selfid_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xad01fc52 hpsb_set_packet_complete_task +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xad8a706e hpsb_iso_recv_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaeecc58a hpsb_remove_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb0cbe631 hpsb_set_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc460abd3 hpsb_create_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc669a4d3 csr1212_detach_keyval_from_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc67e844f hpsb_make_writepacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc68aea2a hpsb_alloc_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcd85d9b7 hpsb_protocol_class +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcd9e772b dma_prog_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xce5bb635 hpsb_add_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xce5d32e0 hpsb_node_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd6ef9010 hpsb_node_fill_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xda5e5f7c hpsb_iso_xmit_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xdc478fa2 hpsb_make_lockpacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xdded4ae0 hpsb_iso_recv_unlisten_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe28cf075 hpsb_read_cycle_timer +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe46d9117 hpsb_iso_recv_listen_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe4a1a80b hpsb_destroy_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xea4152ff dma_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xf17f5aeb hpsb_reset_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfb0f8711 hpsb_iso_wake +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfba57f51 hpsb_speedto_str +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xffdfc9ba hpsb_make_phypacket +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x29d731e7 ohci1394_register_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x3b846bfc ohci1394_stop_context +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xb32e12ac ohci1394_unregister_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xb37ab086 ohci1394_init_iso_tasklet +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x527394fe rdma_resolve_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x71de06c2 rdma_addr_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x9cfd479b rdma_translate_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xb8c6fa05 rdma_addr_cancel +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xbe81bb46 rdma_addr_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xd3f5f687 rdma_copy_addr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x126afed8 ib_send_cm_lap +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x19270e20 ib_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x31321137 ib_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x32784367 ib_send_cm_drep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x34a6d400 ib_send_cm_sidr_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x429be84d ib_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x50d49dcd ib_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x6597ed3a ib_send_cm_sidr_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x66a978b0 ib_send_cm_dreq +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x68b0695f ib_send_cm_rtu +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x74e5878b ib_cm_notify +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x7a3411d1 ib_send_cm_mra +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x8579bbdc ib_send_cm_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xabd5c4bf ib_send_cm_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xbef1779d ib_send_cm_rej +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xf5154832 ib_send_cm_apr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xf9e9265f cm_class +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x06532d82 ib_alloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0924d0cf ib_alloc_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0ce2082a ib_query_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1260a569 ib_query_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x18e8fe09 ib_fmr_pool_map_phys +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1ae5f013 ib_umem_get +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1e491a04 ib_unmap_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x21098589 ib_create_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x23eb1835 ib_modify_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x26788ca7 ib_find_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x28479567 ib_dealloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2bacca82 ib_create_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2eef17f7 ib_find_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x345f0083 ib_detach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x357d6bd8 ib_alloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x362e7796 ib_destroy_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x395ccc4f ib_modify_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3af0c5ee ib_find_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3f7567fd ib_rate_to_mult +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x44b3ed7f ib_query_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x4929164f ib_modify_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x4c5def16 ib_create_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x520b2638 ib_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x595943e6 ib_umem_page_count +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5bd945dc ib_alloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5def6673 ib_register_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x63230df6 ib_query_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6426747c ib_unregister_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x65d169a5 ib_dealloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x66f33ef6 ib_destroy_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x68bdc6a3 ib_register_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6c10e679 ib_query_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x75298f08 ib_modify_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7b5e152b ib_alloc_fast_reg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7e368d4f ib_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7f91c819 ib_query_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8640eaeb ib_modify_qp_is_ok +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8742cc90 ib_init_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x87b614d8 ib_ud_header_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8c24b3a9 ib_get_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8ff1051d ib_fmr_pool_unmap +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x909c4fb4 ib_destroy_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9396b865 ib_query_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x96ce6c46 rdma_node_get_transport +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x98fbb6ca ib_reg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d044e31 ib_destroy_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d08a088 ib_unregister_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d804fa1 mult_to_ib_rate +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9ee17103 ib_free_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa2ed04d6 ib_resize_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb1a312e1 ib_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb3f56ba4 ib_find_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb65aa07d ib_flush_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb7cc0d63 ib_get_cached_lmc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xbf47ed12 ib_get_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcf9f4538 ib_get_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd17ba9d1 ib_ud_header_init +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd3194807 ib_umem_release +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd3f2f398 ib_rereg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd4fa10a1 ib_modify_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd5c4672a ib_set_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd815c0cc ib_attach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd9d59e50 ib_create_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdf777f4e ib_alloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe0ac7923 ib_create_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe0d3cc87 ib_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe14aeffd ib_create_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe84a1b0d ib_get_dma_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf0cd4236 ib_dereg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf26aa560 ib_dealloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf36498b9 ib_ud_header_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf3970ec8 ib_query_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf57d99ae ib_modify_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf6a5fabc ib_dispatch_event +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf8860d68 ib_destroy_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xffb64290 ib_dealloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x085faafd ib_redirect_mad_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x13b242ae ib_cancel_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x215ab834 ib_get_rmpp_segment +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x67e24293 ib_modify_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6cc3d7ac ib_free_recv_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6ef787ed ib_response_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6f077fcf ib_get_mad_data_offset +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x732afafa ib_free_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x7338290d ib_process_mad_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x7b5d4b7a ib_is_mad_class_rmpp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x8ea605c8 ib_create_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xb5c70139 ib_post_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xc12d8d71 ib_register_mad_snoop +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xd8c312a6 ib_register_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xe05d0de8 ib_unregister_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x0c9f6475 ib_sa_path_rec_get +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x16199856 ib_sa_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x28a87240 ib_sa_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x512ba124 ib_sa_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x56900d30 ib_init_ah_from_mcmember +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x576fdbac ib_sa_free_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x5f7c13fc ib_init_ah_from_path +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x9b4ebfa8 ib_sa_service_rec_query +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xbce80898 ib_sa_get_mcmember_rec +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xfddb508e ib_sa_cancel_query +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x02f847bc ib_copy_path_rec_from_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x07cf5a51 ib_copy_ah_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x18382f6a ib_copy_path_rec_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x184f3575 ib_copy_qp_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x01f891ce iw_cm_reject +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x0da1823c iw_cm_disconnect +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x5514dce2 iw_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x672f3f32 iw_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x67b8d192 iw_cm_accept +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x6dd06244 iw_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xc330bc12 iw_cm_connect +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xfcabb5ed iw_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x0624130f rdma_set_service_type +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x09ff9cd4 rdma_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x1c4a99dd rdma_destroy_qp +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x214031dc rdma_disconnect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x272f966e rdma_resolve_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x61e3bca5 rdma_connect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x65f5b673 rdma_accept +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x6950c618 rdma_reject +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x74dbac7c rdma_bind_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x769e7365 rdma_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x94c49cfa rdma_create_qp +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb516e242 rdma_listen +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xc9ca7ac8 rdma_set_ib_paths +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd1dc1017 rdma_destroy_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd3b3dac4 rdma_create_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xec5533b3 rdma_leave_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xf37a632b rdma_resolve_route +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xf7a5da4a rdma_notify +EXPORT_SYMBOL drivers/input/gameport/gameport 0x1079d6f9 gameport_unregister_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0x23ed80a0 __gameport_register_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0x27541722 gameport_open +EXPORT_SYMBOL drivers/input/gameport/gameport 0x2d8bf038 gameport_set_phys +EXPORT_SYMBOL drivers/input/gameport/gameport 0x529511b0 gameport_start_polling +EXPORT_SYMBOL drivers/input/gameport/gameport 0x5598c731 __gameport_register_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0x675567a5 gameport_unregister_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0xdcd841cb gameport_stop_polling +EXPORT_SYMBOL drivers/input/gameport/gameport 0xe1aafca2 gameport_close +EXPORT_SYMBOL drivers/input/input-polldev 0x2fc04871 input_allocate_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0x4cf45a2c input_register_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0x7cc79789 input_free_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xb14bebe0 input_unregister_polled_device +EXPORT_SYMBOL drivers/isdn/capi/capifs 0x2c54c957 capifs_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/capifs 0xd0bc06ce capifs_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x04403fcf unregister_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x053fbed7 capi_ctr_handle_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x14f2aa5a capi20_get_version +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2b8eab1f capilib_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2baa6586 capilib_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x31c24aa4 capi20_isinstalled +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x47d3fc51 capi_info2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x50b33ca4 capi_cmsg2message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6057c6f3 capi_message2cmsg +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x62e32d43 capilib_data_b3_conf +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x706d60e4 capi_ctr_ready +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x71e8d5ba capilib_data_b3_req +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7a33596c capi20_get_serial +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7e6f1307 capi20_get_manufacturer +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7efdd77d capi_ctr_reseted +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x80040f82 capi_ctr_suspend_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8c98a11d capi_ctr_resume_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8e422e7f capi20_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8f699913 capilib_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x9f823278 register_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xa7c4fd6c capi_message2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xaa165d27 capilib_release_appl +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xac67f4e1 capi20_register +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb19fda8d capi_cmd2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb60e5e5f capi_cmsg_header +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xbc795c59 capi20_put_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xc10fe128 cdebbuf_free +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xc553f2a8 attach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe19a11ac capi20_get_profile +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe5a84c80 detach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe8ad9bd1 capi_cmsg2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xed061606 capi20_manufacturer +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xfad5ab53 capi20_set_callback +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x00a31195 b1_load_t4file +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x05001214 b1_free_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x0ce0db74 avmcard_dma_free +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x184a8690 b1ctl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x392793ad b1_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x54bf8cc6 b1_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x7d97ac6c b1_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x85f09690 b1_irq_table +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x96f9d2f4 b1_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xa500bbe2 b1_alloc_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xb6253a3c b1_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xbe15c80c avmcard_dma_alloc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xc49776c5 b1_parse_version +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xdfd28376 b1_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xe151810e b1_getrevision +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xedb46731 b1_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xf2752bd5 b1_load_config +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xf72277fb b1_loaded +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x2a386384 b1dma_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x2d1de722 b1dma_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x3a82a84d t1pci_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x57bd42d2 b1dmactl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x6bd55e28 b1dma_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x7a77f455 b1dma_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x7efdb1e5 b1dma_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xb64b662f b1pciv4_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xdecadb49 b1dma_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xf848b439 b1dma_reset +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0x29562993 b1pcmcia_delcard +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xaec3240e b1pcmcia_addcard_m1 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xea620116 b1pcmcia_addcard_m2 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xf14bf8b1 b1pcmcia_addcard_b1 +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0x2974ead1 DIVA_DIDD_Read +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0x9bdde6b9 proc_net_eicon +EXPORT_SYMBOL drivers/isdn/hardware/mISDN/hfcmulti 0x5293ed86 plx_lock +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x07f4f2ce hisax_unregister +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x148f0c99 FsmFree +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x2844a899 FsmInitTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x51cb9915 hisax_init_pcmcia +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x93a64734 FsmChangeState +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x9df0cd27 FsmEvent +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xc0c558f9 FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xd94696e8 FsmDelTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xee93522c hisax_register +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xf0a16657 FsmNew +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xfc27303b HiSax_closecard +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x3f3b323a isac_d_l2l1 +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x4020c023 isac_irq +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x9951054b isacsx_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0xa4b76038 isac_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0xd410bfa0 isac_init +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0xdef37ec4 isacsx_irq +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x1ee629e2 isdnhdlc_rcv_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x95aed401 isdnhdlc_decode +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x9ffc8215 isdnhdlc_out_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0xf5c8131d isdnhdlc_encode +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x399a2980 register_isdn +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xdf01d853 isdn_ppp_unregister_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xe19a4581 isdn_ppp_register_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xfa06820f isdn_register_divert +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x0d969ba7 mISDN_unregister_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x11f23a09 queue_ch_frame +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x13647082 recv_Dchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x2348cc3c mISDN_FsmFree +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3ea336fd mISDN_FsmAddTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x429129f2 mISDN_FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x50c2230c mISDN_FsmChangeState +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x55e3abb2 create_l1 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x55e53732 recv_Dchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x5928e1d7 mISDN_register_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x59321756 mISDN_freebchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x5b8ae6cc mISDN_unregister_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6506fbdb get_next_dframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x6c67a681 mISDN_initbchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x7662b0b3 get_next_bframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x7baec0b3 l1_event +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x8579edf5 dchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x88786349 mISDN_initdchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xa44ce62f mISDN_register_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xaae34852 recv_Bchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xace35cae mISDN_FsmDelTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xb0f4d030 mISDN_freedchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xbfd13093 confirm_Bsend +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd5145151 mISDN_FsmEvent +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd9a7fbfd mISDN_FsmInitTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xec878233 recv_Bchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xf9e7832f mISDN_FsmNew +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xfa6a48a1 bchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x4c2ec443 mISDN_dsp_element_register +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x60721da7 dsp_audio_law_to_s32 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xa215f1b2 dsp_audio_s16_to_law +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xd3a023b8 mISDN_dsp_element_unregister +EXPORT_SYMBOL drivers/md/dm-log 0x0e6fd6a0 dm_dirty_log_type_register +EXPORT_SYMBOL drivers/md/dm-log 0x1c60642e dm_dirty_log_create +EXPORT_SYMBOL drivers/md/dm-log 0x95e77191 dm_dirty_log_type_unregister +EXPORT_SYMBOL drivers/md/dm-log 0xb7d0e3c6 dm_dirty_log_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x066efe37 dm_table_get +EXPORT_SYMBOL drivers/md/dm-mod 0x1130b215 dm_kcopyd_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0x13a6e2ea dm_register_target +EXPORT_SYMBOL drivers/md/dm-mod 0x1a1d7bed dm_io_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0x24656c2a dm_table_get_size +EXPORT_SYMBOL drivers/md/dm-mod 0x279a008b dm_put_device +EXPORT_SYMBOL drivers/md/dm-mod 0x384e0f96 dm_io +EXPORT_SYMBOL drivers/md/dm-mod 0x3a202d92 dm_table_get_mode +EXPORT_SYMBOL drivers/md/dm-mod 0x55f3b15a dm_get_device +EXPORT_SYMBOL drivers/md/dm-mod 0x5ae88d64 dm_kcopyd_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x66961562 dm_table_event +EXPORT_SYMBOL drivers/md/dm-mod 0x6b2134af dm_table_get_md +EXPORT_SYMBOL drivers/md/dm-mod 0x6bd30939 dm_get_mapinfo +EXPORT_SYMBOL drivers/md/dm-mod 0x7203a829 dm_unregister_target +EXPORT_SYMBOL drivers/md/dm-mod 0x82f65633 dm_io_client_resize +EXPORT_SYMBOL drivers/md/dm-mod 0x954c8af3 dm_io_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x96d95732 dm_kcopyd_copy +EXPORT_SYMBOL drivers/md/dm-mod 0xbec67b9c dm_table_put +EXPORT_SYMBOL drivers/md/dm-mod 0xc79bcd36 dm_vcalloc +EXPORT_SYMBOL drivers/md/dm-mod 0xd8f4fa19 dm_table_unplug_all +EXPORT_SYMBOL drivers/md/md-mod 0x09e480f1 bitmap_close_sync +EXPORT_SYMBOL drivers/md/md-mod 0x255560de md_error +EXPORT_SYMBOL drivers/md/md-mod 0x3e693e8a md_unregister_thread +EXPORT_SYMBOL drivers/md/md-mod 0x4202d364 md_wait_for_blocked_rdev +EXPORT_SYMBOL drivers/md/md-mod 0x4b4d01ff bitmap_cond_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0x4dc03532 register_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0x74cf739c bitmap_unplug +EXPORT_SYMBOL drivers/md/md-mod 0x78749c14 bitmap_endwrite +EXPORT_SYMBOL drivers/md/md-mod 0x7c7ec787 bitmap_startwrite +EXPORT_SYMBOL drivers/md/md-mod 0x83b14f00 md_write_start +EXPORT_SYMBOL drivers/md/md-mod 0x8a3e69e1 md_check_recovery +EXPORT_SYMBOL drivers/md/md-mod 0x910e9c5e md_wakeup_thread +EXPORT_SYMBOL drivers/md/md-mod 0x92dfcd07 md_register_thread +EXPORT_SYMBOL drivers/md/md-mod 0x951784ee bitmap_start_sync +EXPORT_SYMBOL drivers/md/md-mod 0xb0b54c56 md_done_sync +EXPORT_SYMBOL drivers/md/md-mod 0xb39b70c2 unregister_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0xd767f1c9 bitmap_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0xde0ba790 md_write_end +EXPORT_SYMBOL drivers/media/common/tuners/mt2060 0x437d67e8 mt2060_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2131 0xb5413af6 mt2131_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2266 0xf94b0852 mt2266_attach +EXPORT_SYMBOL drivers/media/common/tuners/mxl5005s 0xb49aeac5 mxl5005s_attach +EXPORT_SYMBOL drivers/media/common/tuners/qt1010 0xfc4aa3e1 qt1010_attach +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0x0cb4b189 tuners +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0xc2821775 tuner_count +EXPORT_SYMBOL drivers/media/common/tuners/tuner-xc2028 0xe6d4f14a xc2028_attach +EXPORT_SYMBOL drivers/media/common/tuners/xc5000 0xab438372 xc5000_attach +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x288f57f7 flexcop_sram_ctrl +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x2e326d61 flexcop_dma_control_timer_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x43499c27 flexcop_dma_config_timer +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x49fda6a0 flexcop_pass_dmx_data +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x5f2f0c05 flexcop_device_kfree +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x8143a720 flexcop_pass_dmx_packets +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x936a09b6 flexcop_i2c_request +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x94e21b1c flexcop_dma_xfer_control +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x96b29ec7 flexcop_device_kmalloc +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xa062e08c flexcop_eeprom_check_mac_addr +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xaec77c77 flexcop_dma_allocate +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb0c4a3ec flexcop_device_initialize +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb11187e3 flexcop_wan_set_speed +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb9538810 flexcop_sram_set_dest +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xbd5e3110 flexcop_dma_control_size_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xcccd840f flexcop_device_exit +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xd8afe704 flexcop_dump_reg +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xdaac13b1 flexcop_dma_free +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xf5fe9637 flexcop_dma_config +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x00d75138 bt878_start +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x0e23d333 bt878_device_control +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x3312df16 bt878_stop +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xd2fe260a bt878 +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xd5d0bdef bt878_num +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x02c0d697 write_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x0aa50bd6 dst_error_bailout +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x0ede4eff dst_comm_init +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x1f1742f1 dst_error_recovery +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x565a632d dst_attach +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x818e7d37 dst_pio_disable +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x825e751e read_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xe801ea2b rdc_reset_state +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xe94b8c9c dst_check_sum +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xeee336b5 dst_wait_dst_ready +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst_ca 0x6c962830 dst_ca_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x10571c70 dvb_ca_en50221_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x14eb630c dvb_ringbuffer_free +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x19efa23b dvb_net_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x1a0cdc4f dvb_ca_en50221_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x204fcb34 dvb_unregister_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x3261e353 dvb_generic_open +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x36c8ea1f dvb_frontend_sleep_until +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x3bcf6f80 dvb_unregister_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x635eb40e dvb_dmx_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6858fa69 dvb_ca_en50221_camready_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6f7f7d73 dvb_ringbuffer_empty +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6f9c72e3 dvb_ringbuffer_read +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x74a5a698 dvb_filter_pes2ts_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x80e3832d dvb_filter_get_ac3info +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x877013a2 dvb_dmxdev_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x8b49a23f timeval_usec_diff +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x923aa88e dvb_ringbuffer_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x93c23e81 dvb_ca_en50221_camchange_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x93eef919 dvb_dmxdev_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x9cbff999 dvb_dmx_swfilter_204 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xac4ca1b0 intlog2 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb1184a1e dvb_unregister_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb2db2592 dvb_ringbuffer_write +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb56f0404 dvb_dmx_swfilter_packets +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb5b95805 dvb_ringbuffer_read_user +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb9919b65 dvb_generic_ioctl +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xbc96ba9b dvb_frontend_reinitialise +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xbed559e1 dvb_dmx_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc938e566 dvb_dmx_swfilter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xcd512eb5 dvb_net_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe1019e0a dvb_register_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe3fcbb05 dvb_register_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe488145f dvb_register_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe5ae8707 intlog10 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe7949e59 dvb_ringbuffer_flush_spinlock_wakeup +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xeb7daf80 dvb_ringbuffer_avail +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xf826deb0 dvb_filter_pes2ts +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xfcf66c90 dvb_ca_en50221_frda_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xfd090e25 dvb_frontend_detach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xfda6950c dvb_generic_release +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x10388a39 usb_cypress_load_firmware +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x5efd9f54 dvb_usb_generic_write +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x62ad06d1 dvb_usb_get_hexline +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x853060ba dvb_usb_device_init +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x94822d72 dvb_usb_nec_rc_key_to_event +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x9e85a6d8 dvb_usb_generic_rw +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0xfbb74861 dvb_usb_device_exit +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0x2edc4728 af9005_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0x69f78277 af9005_rc_decode +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0xd3383957 af9005_rc_keys_size +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x40bad2bc dibusb2_0_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x4777eb80 dibusb_dib3000mc_tuner_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x4d2fa644 dibusb_pid_filter +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x733455b9 dibusb_pid_filter_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x804e6bf9 dibusb_dib3000mc_frontend_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x8e519366 dibusb_rc_query +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xb7e4f134 dibusb_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd2665737 dibusb2_0_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd4d3dddc dibusb_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd801cce4 dibusb_i2c_algo +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xdca8d874 dibusb_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xeda94d83 dibusb_read_eeprom_byte +EXPORT_SYMBOL drivers/media/dvb/frontends/au8522 0x9edbd617 au8522_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/bcm3510 0xe266287a bcm3510_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22700 0x906ddb3c cx22700_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22702 0x283e5483 cx22702_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24110 0x1b807ca1 cx24110_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0x26066bcd cx24123_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0x93925005 cx24123_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0x636d994c dib0070_wbd_offset +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0xf0a29d86 dib0070_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mb 0x2272127f dib3000mb_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x101e0aee dib3000mc_set_config +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x18bf3810 dib3000mc_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x1b629751 dib3000mc_pid_parse +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x6fe01c8f dib3000mc_pid_control +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xc2db1bb7 dib3000mc_get_tuner_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xc3f42512 dib3000mc_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x2776f98b dib7000m_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x9b3da023 dib7000m_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0xa39f2d5d dib7000m_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x231a994b dib7000p_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x2351d51e dib7000p_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x39d0c7e9 dib7000p_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x428cea20 dib7000pc_detection +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x810ee79c dib7000p_set_wbd_ref +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xf000e422 dib7000p_set_gpio +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0x5c85b431 dibx000_get_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0xd041a0c6 dibx000_exit_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0xfff69d8f dibx000_init_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/drx397xD 0x182f06ab drx397xD_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dvb-pll 0x2b5c1c50 dvb_pll_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6405 0xef36dae9 isl6405_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6421 0x78b64bb4 isl6421_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/itd1000 0x73829142 itd1000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/l64781 0xb72c9bea l64781_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lgdt330x 0x60e8de1d lgdt330x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lnbp21 0x0b30fa58 lnbp21_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt312 0x701f941e mt312_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt352 0x12b63b41 mt352_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt200x 0x289eab82 nxt200x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt6000 0xf5f912ab nxt6000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51132 0xf73ff5a0 or51132_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51211 0xb3aa6ec2 or51211_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1409 0xf2a3dd95 s5h1409_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1411 0x3dd1a2b1 s5h1411_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0xce05ff07 s5h1420_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0xed8e9d01 s5h1420_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/sp8870 0xcfefc007 sp8870_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/sp887x 0x2cfdf19b sp887x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0297 0x9e5f1e97 stv0297_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0299 0x80cc44cf stv0299_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10021 0x9aa1bb64 tda10021_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10023 0xd65a527e tda10023_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10048 0xf51eeb7b tda10048_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0x191a2bde tda10046_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0x62ead304 tda10045_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10086 0xd08963b1 tda10086_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda8083 0x52112d23 tda8083_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda826x 0xb251549d tda826x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tua6100 0x47e7ccd0 tua6100_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1820 0x592460e0 ves1820_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1x93 0x208388ac ves1x93_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/zl10353 0xf60d88a6 zl10353_attach +EXPORT_SYMBOL drivers/media/dvb/ttpci/ttpci-eeprom 0x28c4fa92 ttpci_eeprom_parse_mac +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0x10ab80b8 ttusbdecfe_dvbt_attach +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0x3b6c8172 ttusbdecfe_dvbs_attach +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x11dc4b6d bttv_gpio_enable +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x629965ba bttv_sub_register +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x8ecf4acc bttv_write_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xb643a68a bttv_get_pcidev +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xbcf2d2fb bttv_read_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xe98b12d9 bttv_sub_unregister +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x11ce7525 btcx_riscmem_alloc +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x495e4b0c btcx_calc_skips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xad2fe38b btcx_sort_clips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xbe360233 btcx_riscmem_free +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xc368f8e6 btcx_align +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xcda0ded2 btcx_screen_clips +EXPORT_SYMBOL drivers/media/video/cpia 0x83f9af0d cpia_register_camera +EXPORT_SYMBOL drivers/media/video/cpia 0x89ea6cab cpia_unregister_camera +EXPORT_SYMBOL drivers/media/video/cx18/cx18 0x2cdea06d cx18_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/cx2341x 0x0224a947 cx2341x_update +EXPORT_SYMBOL drivers/media/video/cx2341x 0x3559ba71 cx2341x_ext_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0x8fdbede1 cx2341x_fill_defaults +EXPORT_SYMBOL drivers/media/video/cx2341x 0xcf8b77a4 cx2341x_mpeg_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0xde1da524 cx2341x_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx2341x 0xeacc6fab cx2341x_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/cx2341x 0xfb8bd71f cx2341x_log_status +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x0a723954 cx23885_get_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x2767a46b cx23885_set_freq +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x62454bf1 cx23885_enum_input +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xb5c4d1ca cx23885_video_mux +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xd0cf2336 cx23885_set_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xe12fa84c cx23885_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xfb885537 cx23885_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0x429b30e6 vp3054_i2c_probe +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0xa88cb203 vp3054_i2c_remove +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x11207fd5 cx88_get_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x1232700d cx8800_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x5fd83f51 cx88_set_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xa8aa4539 cx88_set_freq +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xac4e53b9 cx88_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xc6b68346 cx88_enum_input +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xf3a3a061 cx88_video_mux +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x08e8306a cx8802_unregister_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x13e2a1e9 cx8802_get_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x3252721a cx8802_buf_queue +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x78fe6dc9 cx8802_cancel_buffers +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x7f8bb3df cx8802_buf_prepare +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x84b19d45 cx8802_register_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0xd279c07b cx8802_get_device +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x30665292 cx88_vdev_init +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x344d5f88 cx88_call_i2c_clients +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x3e64ebd9 cx88_sram_channel_dump +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x49a7e513 cx88_free_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x6586d36a cx88_set_tvaudio +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x6768f3f3 cx88_newstation +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x77c9da78 cx88_get_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7b5cdee1 cx88_tuner_callback +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x86c71df6 cx88_core_irq +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x8bea7fd6 cx88_ir_start +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x8ecea3a5 cx88_set_tvnorm +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x904b8696 cx88_audio_thread +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x95a15a13 cx88_risc_databuffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x9b140fff cx88_sram_channels +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xa3b40edb cx88_core_get +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xb47f6cda cx88_print_irqbits +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xbaa73fd2 cx88_risc_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xbaec4dad cx88_risc_stopper +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc2035c56 cx88_core_put +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc9b78ac0 cx88_sram_channel_setup +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xd23d39c4 cx88_wakeup +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xe63c2511 cx88_ir_stop +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xe9f7ceec cx88_shutdown +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xf145c8ce cx88_set_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xf3c35cab cx88_set_scale +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xfbead84c cx88_reset +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0x0576e87c em28xx_unregister_extension +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0xa8dafbfb em28xx_register_extension +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x2f92ad7b gspca_dev_probe +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x3f3f7e2b gspca_suspend +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x585073b6 gspca_disconnect +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x9670af2c gspca_debug +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x9a39b6dd gspca_auto_gain_n_exposure +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0xeb1e535b gspca_resume +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0xee4a0118 gspca_frame_add +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0538e449 ivtv_cards_lock +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x1164f9d8 ivtv_udma_setup +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x14f67530 ivtv_debug +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x1551627e ivtv_vapi_result +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x2c80679f ivtv_init_on_first_open +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x3014a4fb ivtv_clear_irq_mask +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x383824db ivtv_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x65d9dd13 ivtv_cards +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x6d86966b ivtv_api +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x70196ffb ivtv_cards_active +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x8734c73c ivtv_set_irq_mask +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x8944dfca ivtv_udma_alloc +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xc0b64535 ivtv_udma_prepare +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xe3ec9092 ivtv_udma_unmap +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xf407f6b6 ivtv_vapi +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x0a57a2bd saa7134_ts_register +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x1211df5d saa7134_devlist +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x566aa162 saa7134_set_gpio +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x6aa2bb1f saa_dsp_writel +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x6aa686da saa7134_ts_unregister +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x6e3b4a4c saa7134_pgtable_build +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x7b6836eb saa7134_pgtable_alloc +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x85593767 saa7134_tuner_callback +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x9419acd0 saa7134_dmasound_exit +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x98af79c1 saa7134_boards +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xa536095c saa7134_i2c_call_clients +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xc2704613 saa7134_set_dmabits +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xd0ab4d52 saa7134_dmasound_init +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xdda9891d saa7134_pgtable_free +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xdf1a3ef1 saa7134_tvaudio_setmute +EXPORT_SYMBOL drivers/media/video/soc_camera 0x1f426215 soc_camera_host_unregister +EXPORT_SYMBOL drivers/media/video/soc_camera 0x77956a6a soc_camera_video_start +EXPORT_SYMBOL drivers/media/video/soc_camera 0xa938eccd soc_camera_host_register +EXPORT_SYMBOL drivers/media/video/soc_camera 0xb7b983dd soc_camera_device_register +EXPORT_SYMBOL drivers/media/video/soc_camera 0xc950f943 soc_camera_video_stop +EXPORT_SYMBOL drivers/media/video/soc_camera 0xca3a3d72 soc_camera_device_unregister +EXPORT_SYMBOL drivers/media/video/tveeprom 0x2c753969 tveeprom_hauppauge_analog +EXPORT_SYMBOL drivers/media/video/tveeprom 0xd9b2456e tveeprom_read +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x0eb0fb4e usbvideo_DeinterlaceFrame +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x16554232 usbvideo_TestPattern +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x16a2915c RingQueue_Dequeue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x207e8d01 usbvideo_RegisterVideoDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x24e7a6b7 usbvideo_register +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x407a321c RingQueue_WakeUpInterruptible +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x601c08d0 usbvideo_Deregister +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x9f339db3 usbvideo_AllocateDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xddecac6d RingQueue_Enqueue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xf5011f67 RingQueue_Flush +EXPORT_SYMBOL drivers/media/video/v4l1-compat 0x5252f63c v4l_compat_translate_ioctl +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x03165a85 v4l2_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x0dfb5e57 v4l2_prio_max +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x1c427ecb v4l2_ctrl_query_fill +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2de2b633 v4l2_prio_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2e9a955d v4l2_prio_close +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x42c8e001 v4l2_ctrl_next +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x57abfbd8 v4l2_chip_match_host +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x5b31ed02 v4l2_chip_match_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x5fef1b4a v4l2_ctrl_query_fill_std +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x942892ab v4l2_prio_open +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xb2d1e17e v4l2_prio_change +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xc369097d v4l2_ctrl_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xd464e760 v4l2_ctrl_query_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xdbb2cf5c v4l2_i2c_attach +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xddac6716 v4l2_chip_ident_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xe330bce9 v4l2_prio_init +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0x87fb0e36 videobuf_dvb_unregister +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0xe377f3de videobuf_dvb_register +EXPORT_SYMBOL drivers/media/video/videocodec 0x02ef66f1 videocodec_register +EXPORT_SYMBOL drivers/media/video/videocodec 0x7eae4aa3 videocodec_attach +EXPORT_SYMBOL drivers/media/video/videocodec 0xc32950f9 videocodec_unregister +EXPORT_SYMBOL drivers/media/video/videocodec 0xe40bb4f6 videocodec_detach +EXPORT_SYMBOL drivers/media/video/videodev 0x049f702f video_device_release +EXPORT_SYMBOL drivers/media/video/videodev 0x123959a1 v4l2_type_names +EXPORT_SYMBOL drivers/media/video/videodev 0x142b9a3c video_unregister_device +EXPORT_SYMBOL drivers/media/video/videodev 0x36afbae6 video_device_alloc +EXPORT_SYMBOL drivers/media/video/videodev 0x3adbd595 v4l2_field_names +EXPORT_SYMBOL drivers/media/video/videodev 0x3b637d6b video_usercopy +EXPORT_SYMBOL drivers/media/video/videodev 0x421713f6 video_register_device +EXPORT_SYMBOL drivers/media/video/videodev 0x5ebefe4b v4l_printk_ioctl +EXPORT_SYMBOL drivers/media/video/videodev 0xaa515bbb video_exclusive_open +EXPORT_SYMBOL drivers/media/video/videodev 0xc8a71292 video_ioctl2 +EXPORT_SYMBOL drivers/media/video/videodev 0xccf5b5bb video_devdata +EXPORT_SYMBOL drivers/media/video/videodev 0xe2b92059 v4l2_video_std_construct +EXPORT_SYMBOL drivers/media/video/videodev 0xea318f47 video_register_device_index +EXPORT_SYMBOL drivers/media/video/videodev 0xf3251e7b v4l2_norm_to_name +EXPORT_SYMBOL drivers/media/video/videodev 0xfa91d9a8 video_exclusive_release +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x105d4f47 mpt_add_sge +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x11a70a5b mpt_free_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x120e3b20 mpt_GetIocState +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x130f2952 mpt_config +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x18520031 mpt_alloc_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x1f13d87a mpt_put_msg_frame_hi_pri +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x27eb041e mpt_verify_adapter +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x2d5c988e mpt_resume +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4095c391 mpt_put_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4526289b mpt_event_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x5ff5ddc4 mpt_send_handshake_request +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x61e15b06 mpt_suspend +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x6ab56cc2 mpt_HardResetHandler +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x7491a752 mpt_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x84aae17d mpt_event_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x87063f0a mptbase_sas_persist_operation +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x909ce6e9 mpt_findImVolumes +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x9a517b0d mpt_attach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xab7d0d40 mpt_free_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xb04b8b48 mpt_detach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xb6fa3ba5 mpt_device_driver_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc0e69f82 mpt_device_driver_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc47c22e8 mpt_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xcde3a785 mpt_reset_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd5ae60a6 mpt_get_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd9a92a75 mpt_reset_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdb774ec3 mpt_raid_phys_disk_pg0 +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdd805159 ioc_list +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe230953a mpt_print_ioc_summary +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x028881fd mptscsih_qcmd +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x0518d64e mptscsih_resume +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x10809603 mptscsih_TMHandler +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x1ccc7695 mptscsih_taskmgmt_complete +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x32b2b673 mptscsih_slave_destroy +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x4b6ec372 mptscsih_host_attrs +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x4e701717 mptscsih_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x5d701847 mptscsih_event_process +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6721a343 mptscsih_remove +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x764ddf1a mptscsih_timer_expired +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x7926b8de mptscsih_is_phys_disk +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x7f4eab66 mptscsih_bios_param +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x8582c372 mptscsih_suspend +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x90eec3f7 mptscsih_shutdown +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x9654831d mptscsih_host_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x97a6e4ec mptscsih_ioc_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x9c1b2bfe mptscsih_slave_configure +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xae4ec60e mptscsih_raid_id_to_num +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xb7d874e3 mptscsih_abort +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xbefa7bd7 mptscsih_change_queue_depth +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xc6141a0a mptscsih_proc_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xcc789097 mptscsih_io_done +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xcc8e99fd mptscsih_bus_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xf61186f3 mptscsih_scandv_complete +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xf6b24d1a mptscsih_dev_reset +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x06313bed i2o_parm_table_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x106799e3 i2o_parm_field_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x147f9e79 i2o_status_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2a843bef i2o_dump_message +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2d03d6af i2o_device_claim_release +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x3c311288 i2o_driver_unregister +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x4654cba5 i2o_driver_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x72eac3e3 i2o_driver_notify_controller_add_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x7633578a i2o_event_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x7cb3f49c i2o_msg_get_wait +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x7cfcf526 i2o_driver_notify_device_remove_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x81026c79 i2o_device_claim +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x8250230b i2o_parm_issue +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x91e40a49 i2o_find_iop +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb44e0b10 i2o_msg_post_wait_mem +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb4c00dcf i2o_controllers +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb56abc8d i2o_driver_notify_device_add_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xcb8698e7 i2o_exec_lct_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xcd6a4e47 i2o_iop_find_device +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xfc411041 i2o_driver_notify_controller_remove_all +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x82dbd02e pasic3_read_register +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0xcfebdb2b pasic3_write_register +EXPORT_SYMBOL drivers/misc/ioc4 0x96d23371 ioc4_register_submodule +EXPORT_SYMBOL drivers/misc/ioc4 0xa23e7a36 ioc4_unregister_submodule +EXPORT_SYMBOL drivers/misc/sony-laptop 0x5bb1e117 sony_pic_camera_command +EXPORT_SYMBOL drivers/misc/tifm_core 0x11431f29 tifm_remove_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0x2adfb58d tifm_unregister_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0x39f86aa1 tifm_queue_work +EXPORT_SYMBOL drivers/misc/tifm_core 0x416c81d8 tifm_register_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0x52841baa tifm_free_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0x56255045 tifm_free_device +EXPORT_SYMBOL drivers/misc/tifm_core 0x68f749db tifm_map_sg +EXPORT_SYMBOL drivers/misc/tifm_core 0x8ba9d2d5 tifm_unmap_sg +EXPORT_SYMBOL drivers/misc/tifm_core 0x8bb33bfc tifm_alloc_device +EXPORT_SYMBOL drivers/misc/tifm_core 0x8e15257a tifm_has_ms_pif +EXPORT_SYMBOL drivers/misc/tifm_core 0x9526b0c5 tifm_eject +EXPORT_SYMBOL drivers/misc/tifm_core 0x9b2f31ad tifm_add_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0xe0ea4ad4 tifm_alloc_adapter +EXPORT_SYMBOL drivers/mmc/card/mmc_block 0xd541225c mmc_cleanup_queue +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x142a4589 mmc_release_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x24d58420 mmc_alloc_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x24f522a1 mmc_align_data_size +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x2e2252c0 mmc_wait_for_req +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x31a9b114 mmc_add_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x5bb04318 mmc_unregister_driver +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x66a95258 mmc_free_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x76dc389b mmc_register_driver +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x82a7b2a1 mmc_wait_for_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x909f7371 mmc_wait_for_app_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xa9617161 mmc_resume_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xb5bfffed mmc_remove_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xc19774b0 mmc_set_data_timeout +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xc27f577f mmc_suspend_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xd2c63c15 __mmc_claim_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xd88197b5 mmc_detect_change +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xf077d195 mmc_request_done +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x01eb9c6c cfi_read_pri +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x0f9b4a47 cfi_fixup +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0xb25bfd6a cfi_varsize_frob +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x25921fa5 do_map_probe +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x3cafeabe map_destroy +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x46953602 unregister_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x995d3f76 register_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/gen_probe 0x34aead14 mtd_do_chip_probe +EXPORT_SYMBOL drivers/mtd/maps/map_funcs 0xac500447 simple_map_init +EXPORT_SYMBOL drivers/mtd/mtd 0x7bc41ba7 add_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtd 0x8ee6a061 del_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtdconcat 0x25877ab8 mtd_concat_create +EXPORT_SYMBOL drivers/mtd/mtdconcat 0x9157f5d3 mtd_concat_destroy +EXPORT_SYMBOL drivers/mtd/nand/nand 0x2907fd32 nand_default_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand 0xbf69d4c6 nand_scan_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x254f230c nand_calculate_ecc +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x87406d9d nand_correct_data +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0x836bdb72 nand_flash_ids +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0xa336feb7 nand_manuf_ids +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0x1ceeb563 onenand_default_bbt +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xf8532292 onenand_scan_bbt +EXPORT_SYMBOL drivers/net/8390 0x230dd614 NS8390_init +EXPORT_SYMBOL drivers/net/8390 0x4f479fcc __alloc_ei_netdev +EXPORT_SYMBOL drivers/net/8390 0x4fddaa56 ei_poll +EXPORT_SYMBOL drivers/net/8390 0x7d7e0dbc ei_interrupt +EXPORT_SYMBOL drivers/net/8390 0xc38e6434 ei_close +EXPORT_SYMBOL drivers/net/8390 0xe05b0f5e ei_open +EXPORT_SYMBOL drivers/net/8390p 0x27c102ff NS8390p_init +EXPORT_SYMBOL drivers/net/8390p 0x29d30248 eip_poll +EXPORT_SYMBOL drivers/net/8390p 0x51d23827 __alloc_eip_netdev +EXPORT_SYMBOL drivers/net/8390p 0x841bc69f eip_interrupt +EXPORT_SYMBOL drivers/net/8390p 0xd0e5c2ec eip_open +EXPORT_SYMBOL drivers/net/8390p 0xe6d10859 eip_close +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x19e805d7 arc_proto_default +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x1f1405e7 alloc_arcdev +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x2de99b51 arcnet_unregister_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4641bd7d arcnet_interrupt +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x6534792a arcnet_debug +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x67c99ead arc_proto_map +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xde03c009 arc_bcast_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xff2a6528 arc_raw_proto +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x3689af6c com20020_found +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x37550068 com20020_check +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x2371c357 cxgb3_register_client +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x32b2c21d t3_l2t_send_event +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x3e23d7a6 cxgb3_alloc_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x432510f8 cxgb3_ofld_send +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x624cb60f t3_l2t_send_slow +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x85b177f8 cxgb3_insert_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8691588d cxgb3_alloc_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x90b2b116 cxgb3_remove_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x9643e9ea cxgb3_unregister_client +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xa3ebdda0 dev2t3cdev +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xa9c566ce cxgb3_free_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xce29f200 t3_register_cpl_handler +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xd9b567fd cxgb3_queue_tid_release +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xe2597f8d t3_l2e_free +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xed5cfe8f cxgb3_free_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xf8f7b93d t3_l2t_get +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x051cc9c4 hdlcdrv_transmitter +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x1dda0f9f hdlcdrv_receiver +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xa510e996 hdlcdrv_arbitrate +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xbf7fb7a5 hdlcdrv_unregister +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xdbd6f718 hdlcdrv_register +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x082ae47f sirdev_get_instance +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x35f8a617 sirdev_raw_write +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x6e883ba7 sirdev_set_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x707b8f3a irda_register_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x739eff93 sirdev_put_instance +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x91c67cf8 irda_unregister_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x91d85fd0 sirdev_raw_read +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xb7cdf2ce sirdev_write_complete +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xc37bad4f sirdev_set_dtr_rts +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf68896b5 sirdev_receive +EXPORT_SYMBOL drivers/net/mii 0x00182a76 mii_ethtool_sset +EXPORT_SYMBOL drivers/net/mii 0x033ec618 mii_check_gmii_support +EXPORT_SYMBOL drivers/net/mii 0x20277aa4 mii_check_media +EXPORT_SYMBOL drivers/net/mii 0x51075b72 mii_link_ok +EXPORT_SYMBOL drivers/net/mii 0x62718cf6 mii_ethtool_gset +EXPORT_SYMBOL drivers/net/mii 0x9477396b mii_nway_restart +EXPORT_SYMBOL drivers/net/mii 0xd555ffe6 mii_check_link +EXPORT_SYMBOL drivers/net/mii 0xf4399027 generic_mii_ioctl +EXPORT_SYMBOL drivers/net/phy/libphy 0x0c12652b phy_mii_ioctl +EXPORT_SYMBOL drivers/net/phy/libphy 0x0caf0210 phy_read +EXPORT_SYMBOL drivers/net/phy/libphy 0x0f175545 genphy_config_advert +EXPORT_SYMBOL drivers/net/phy/libphy 0x10bdc3a4 phy_ethtool_gset +EXPORT_SYMBOL drivers/net/phy/libphy 0x2283b36f phy_start_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x26653a76 phy_stop +EXPORT_SYMBOL drivers/net/phy/libphy 0x2abee1d1 phy_disable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x2be0f9da phy_connect +EXPORT_SYMBOL drivers/net/phy/libphy 0x2fe395e5 genphy_config_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0x37ad5134 phy_stop_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x3dc17814 phy_register_fixup_for_id +EXPORT_SYMBOL drivers/net/phy/libphy 0x3fa75683 phy_start +EXPORT_SYMBOL drivers/net/phy/libphy 0x4888b3e4 phy_register_fixup_for_uid +EXPORT_SYMBOL drivers/net/phy/libphy 0x4f8d5dc1 phy_start_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0x54d0867c phy_print_status +EXPORT_SYMBOL drivers/net/phy/libphy 0x6251cfc9 get_phy_id +EXPORT_SYMBOL drivers/net/phy/libphy 0x664136a2 mdiobus_register +EXPORT_SYMBOL drivers/net/phy/libphy 0x6c9fe287 phy_ethtool_sset +EXPORT_SYMBOL drivers/net/phy/libphy 0x6d457ffe genphy_read_status +EXPORT_SYMBOL drivers/net/phy/libphy 0xadcb8607 phy_register_fixup +EXPORT_SYMBOL drivers/net/phy/libphy 0xba89a39a phy_detach +EXPORT_SYMBOL drivers/net/phy/libphy 0xc70f2f7c phy_write +EXPORT_SYMBOL drivers/net/phy/libphy 0xc7bfa413 phy_disconnect +EXPORT_SYMBOL drivers/net/phy/libphy 0xce9a94be phy_scan_fixups +EXPORT_SYMBOL drivers/net/phy/libphy 0xcee8f311 phy_driver_register +EXPORT_SYMBOL drivers/net/phy/libphy 0xd199ed2d phy_attach +EXPORT_SYMBOL drivers/net/phy/libphy 0xd5874b26 mdio_bus_type +EXPORT_SYMBOL drivers/net/phy/libphy 0xe803d91a phy_device_create +EXPORT_SYMBOL drivers/net/phy/libphy 0xe9806615 phy_sanitize_settings +EXPORT_SYMBOL drivers/net/phy/libphy 0xea0e9b6a phy_driver_unregister +EXPORT_SYMBOL drivers/net/phy/libphy 0xf850e838 genphy_update_link +EXPORT_SYMBOL drivers/net/phy/libphy 0xfd78a8df phy_enable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0xfda28a54 mdiobus_unregister +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x3a46f4ae free_mdio_bitbang +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0xbd5c59a2 alloc_mdio_bitbang +EXPORT_SYMBOL drivers/net/ppp_generic 0x098fd37a ppp_register_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0x0a36c0ae ppp_unregister_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0x34fdde47 ppp_channel_index +EXPORT_SYMBOL drivers/net/ppp_generic 0x35a91fc5 ppp_register_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0x8cec60ee ppp_input +EXPORT_SYMBOL drivers/net/ppp_generic 0xa3fdd919 ppp_unit_number +EXPORT_SYMBOL drivers/net/ppp_generic 0xac88c3e5 ppp_unregister_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0xddbbf23b ppp_input_error +EXPORT_SYMBOL drivers/net/ppp_generic 0xe18b1c60 ppp_output_wakeup +EXPORT_SYMBOL drivers/net/pppox 0x194bc9d7 pppox_unbind_sock +EXPORT_SYMBOL drivers/net/pppox 0x27ff4486 register_pppox_proto +EXPORT_SYMBOL drivers/net/pppox 0xe0ff7a18 unregister_pppox_proto +EXPORT_SYMBOL drivers/net/pppox 0xe16ff21c pppox_ioctl +EXPORT_SYMBOL drivers/net/slhc 0x0ff2b602 slhc_compress +EXPORT_SYMBOL drivers/net/slhc 0x23c8f257 slhc_uncompress +EXPORT_SYMBOL drivers/net/slhc 0xa63d85ab slhc_remember +EXPORT_SYMBOL drivers/net/slhc 0xb5ca1c46 slhc_free +EXPORT_SYMBOL drivers/net/slhc 0xdfc5169b slhc_init +EXPORT_SYMBOL drivers/net/slhc 0xe8794ce1 slhc_toss +EXPORT_SYMBOL drivers/net/sungem_phy 0x3ce47653 mii_phy_probe +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x4170a3ae tmsdev_term +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x4bcc621d tms380tr_open +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x4f134ba8 tmsdev_init +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x518fcbfb tms380tr_interrupt +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd2328794 tms380tr_wait +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xdb2912ea tms380tr_close +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x38da4725 cycx_intr +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x62be23ea cycx_setup +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x66a4c4e6 cycx_down +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x968458a6 cycx_peek +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xb6f383de cycx_poke +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xfe7cd576 cycx_exec +EXPORT_SYMBOL drivers/net/wan/hdlc 0x017cc0de unregister_hdlc_device +EXPORT_SYMBOL drivers/net/wan/hdlc 0x02d62bb1 hdlc_open +EXPORT_SYMBOL drivers/net/wan/hdlc 0x0cca2793 detach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x23ca7fe5 hdlc_close +EXPORT_SYMBOL drivers/net/wan/hdlc 0x41217e38 hdlc_ioctl +EXPORT_SYMBOL drivers/net/wan/hdlc 0x5c0778cf attach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x6eb682af register_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xab2dd604 unregister_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xf01ee7d2 alloc_hdlcdev +EXPORT_SYMBOL drivers/net/wan/syncppp 0x063753ad sppp_do_ioctl +EXPORT_SYMBOL drivers/net/wan/syncppp 0x1ce45530 sppp_detach +EXPORT_SYMBOL drivers/net/wan/syncppp 0x35f733aa sppp_open +EXPORT_SYMBOL drivers/net/wan/syncppp 0x8e520f94 sppp_close +EXPORT_SYMBOL drivers/net/wan/syncppp 0xb7bcb5d9 sppp_attach +EXPORT_SYMBOL drivers/net/wan/syncppp 0xda617315 sppp_reopen +EXPORT_SYMBOL drivers/net/wan/z85230 0x085bdc12 z8530_sync_close +EXPORT_SYMBOL drivers/net/wan/z85230 0x10c78988 z8530_dead_port +EXPORT_SYMBOL drivers/net/wan/z85230 0x1b395e3b z8530_shutdown +EXPORT_SYMBOL drivers/net/wan/z85230 0x283e799e z8530_interrupt +EXPORT_SYMBOL drivers/net/wan/z85230 0x3894da0c z8530_dma_sync +EXPORT_SYMBOL drivers/net/wan/z85230 0x38ea3c64 z8530_sync_dma_open +EXPORT_SYMBOL drivers/net/wan/z85230 0x49faf4d6 z8530_sync_txdma_close +EXPORT_SYMBOL drivers/net/wan/z85230 0x5cd24d29 z8530_hdlc_kilostream +EXPORT_SYMBOL drivers/net/wan/z85230 0x613d2dc0 z8530_sync_open +EXPORT_SYMBOL drivers/net/wan/z85230 0x7076e3e2 z8530_null_rx +EXPORT_SYMBOL drivers/net/wan/z85230 0xa9d3f3a9 z8530_queue_xmit +EXPORT_SYMBOL drivers/net/wan/z85230 0xb460b342 z8530_channel_load +EXPORT_SYMBOL drivers/net/wan/z85230 0xb5a66ba1 z8530_sync +EXPORT_SYMBOL drivers/net/wan/z85230 0xc243c0a9 z8530_describe +EXPORT_SYMBOL drivers/net/wan/z85230 0xc46f896b z8530_sync_txdma_open +EXPORT_SYMBOL drivers/net/wan/z85230 0xc8087493 z8530_init +EXPORT_SYMBOL drivers/net/wan/z85230 0xd9b96cf2 z8530_sync_dma_close +EXPORT_SYMBOL drivers/net/wan/z85230 0xe0bef6e7 z8530_txdma_sync +EXPORT_SYMBOL drivers/net/wan/z85230 0xe3d80064 z8530_hdlc_kilostream_85230 +EXPORT_SYMBOL drivers/net/wan/z85230 0xf8829fce z8530_nop +EXPORT_SYMBOL drivers/net/wireless/airo 0x1407871d init_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0x22328dea stop_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0x99de6a42 reset_airo_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0x287e6b67 atmel_open +EXPORT_SYMBOL drivers/net/wireless/atmel 0x6aff61f0 stop_atmel_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0xb0f3299e init_atmel_card +EXPORT_SYMBOL drivers/net/wireless/hermes 0x4196c38b hermes_write_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xc60b5e9e hermes_bap_pwrite +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd38d8ae2 hermes_read_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd3f714e5 hermes_bap_pread +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5168829 hermes_allocate +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5336e5d hermes_init +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd54e219d hermes_docmd_wait +EXPORT_SYMBOL drivers/net/wireless/hermes 0xed47b224 hermes_struct_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x046c4caa hostap_get_porttype +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x0ad69602 hostap_set_multicast_list_queue +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x0c841cf9 hostap_set_string +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1040a89f hostap_setup_dev +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x10838473 hostap_set_roaming +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1770efd0 hostap_init_ap_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1a5eb38e hostap_set_auth_algs +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x1cb706b7 hostap_set_encryption +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x216f180b hostap_set_word +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x2331a35b hostap_info_process +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x28036d57 hostap_set_hostapd_sta +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x3d61996d hostap_add_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x490e5392 hostap_init_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x4d455ca3 hostap_set_antsel +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x6903f16c hostap_80211_get_hdrlen +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x6ca14e38 hostap_set_hostapd +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x75d7d465 hostap_init_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x7a9827ce prism2_update_comms_qual +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x7f67edbd hostap_info_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x83bd2d48 hostap_master_start_xmit +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x8fb18124 hostap_remove_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x96f90d5a hostap_remove_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xa12ad27f hostap_dump_tx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xaac43eca hostap_handle_sta_tx_exc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xaadf0ad8 hostap_get_stats +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb2a945e0 hostap_dump_rx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xc64fd32a hostap_80211_rx +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xcd0c9f29 hostap_free_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xdafe8173 hostap_check_sta_fw_version +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xed722ebd hostap_80211_ops +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x03bd148a iwl_tx_queue_reclaim +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x04b3971a iwl_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0a2c1129 iwl_radio_kill_sw_enable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0a44f8c7 iwl_eeprom_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0a7a88b1 iwl_power_temperature_change +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0cc8a133 iwl_tx_cmd_complete +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1035f148 iwl_set_hw_params +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x105b3de6 iwl_send_static_wepkey_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x11f11bc2 iwl_rf_kill_ct_config +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x172fcfc7 iwlcore_eeprom_verify_signature +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x18a27a6c iwl_hw_detect +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1d77b399 iwl_bcast_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1e2ba7ec iwl_init_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1ff6ab46 iwl_set_rxon_chain +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x20d3afb2 iwl_setup_scan_deferred_work +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x248e68b3 iwl_rx_reply_compressed_ba +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2515e57f iwl_rx_queue_restock +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x254f2f05 iwl_init_sensitivity +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x25a41a5d iwl_rxon_add_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x28c9986f iwl_add_station_flags +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2917bde1 iwl_remove_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x294a0c9c iwl_tx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x294af4ac iwl_power_set_system_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2c6aa613 iwl_txq_ctx_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x31a23990 iwl_send_lq_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x34eebe35 iwl_init_channel_map +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x3ed9566a iwl_rx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x415a33b2 iwl_rx_queue_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4519d629 iwl_eeprom_check_version +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x48508afd iwl_rx_queue_alloc +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x488f846e iwl_verify_ucode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4c2d694f iwl_rx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x51efcc87 iwl_setup_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5553013d iwl_rx_reply_rx_phy +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x57b98367 iwl_set_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5a833366 iwl_power_initialize +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5de8e40a iwlcore_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5e07081e iwl_rx_replenish +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5e31f94e iwl_free_calib_results +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x60774702 iwl_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6baf95a3 iwl_send_cmd_sync +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6f9772f1 iwl_sta_modify_enable_tid_tx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7177d1dd iwlcore_eeprom_acquire_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x723df728 iwl_send_cmd_pdu_async +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x72b4ab2d iwl_reset_qos +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x73906119 iwl_sensitivity_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x76dc5df4 iwl_hw_txq_ctx_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7bc124d6 iwl_eeprom_get_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7ccd772c iwl_uninit_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7e4d34e3 iwl_rxq_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7e770f8b iwl_set_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7ee26782 iwl_remove_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x80878b3e iwl_rx_queue_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x81cb7fec iwl_tx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x81e9d317 iwl_dump_nic_error_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x85196307 iwl_set_tx_power +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x85e6bce8 iwl_tx_skb +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8670273d iwl_hwrate_to_plcp_idx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8816d2bd iwl_rfkill_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x894351d7 iwl_get_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8c77a653 iwl_eeprom_query16 +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8d0b9a03 iwl_power_enable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8ea5d646 iwl_hwrate_to_tx_control +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x90331018 iwl_power_set_user_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x919b9d39 iwl_rx_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x92f47835 iwl_hw_txq_free_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x95002614 iwl_reset_run_time_calib +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x95d41894 iwl_power_update_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x961e4503 iwl_send_statistics_request +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x97266eb0 iwl_rx_missed_beacon_notif +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x97cefbf7 iwl_send_add_sta +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x986554a9 iwl_hw_txq_attach_buf_to_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x99e23006 iwl_radio_kill_sw_disable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9ce4363d iwl_scan_initiate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9f63bb51 iwl_leds_register +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa5adf126 iwl_rx_allocate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa81b476d iwl_set_rxon_ht +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa8f143e7 iwl_dump_nic_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa8fa4779 iwl_hw_nic_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xaa8e79b9 iwl_rx_queue_reset +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xac569eb2 iwl_clear_stations_table +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb0106411 iwl_rfkill_set_hw_state +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb38a1e41 iwl_escape_essid +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb5481c6d iwl_chain_noise_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb9b24789 iwl_setup_rx_scan_handlers +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xbb1f99a8 iwlcore_eeprom_release_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xbcdc9fd5 iwl_rx_reply_rx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc3016c52 iwl_txq_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc3239663 iwl_power_disable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcbaf4931 get_cmd_string +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcc3f3476 iwl_find_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xce40b1ad iwl_txq_check_empty +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd12a95ea iwl_print_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd23a678d iwl_alloc_all +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd2c9e206 iwl_set_rxon_channel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd98c7d6b iwl_scan_cancel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdb116bd8 iwl_leds_background +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe1384671 iwl_eeprom_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe588e99e iwl_scan_cancel_timeout +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe7ce5d70 iwl_rates +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe93ae450 iwl_get_channel_info +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xebcd06a3 iwl_rx_statistics +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xee87178a iwl_send_cmd_pdu +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf1a92268 iwl_leds_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf4d72398 iwl_is_fat_tx_allowed +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfa896b93 iwl_remove_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfb03e2d2 iwl_send_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfcf5294f iwl_get_ra_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfd7c796a iwl_rfkill_init +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x1a9d334a orinoco_interrupt +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x27d2cf69 free_orinocodev +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x41d0a541 __orinoco_up +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xb998b551 __orinoco_down +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xcf962e03 alloc_orinocodev +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xf261a939 orinoco_reinit_firmware +EXPORT_SYMBOL drivers/parport/parport 0x1dbe8d84 parport_irq_handler +EXPORT_SYMBOL drivers/parport/parport 0x23f03535 parport_unregister_driver +EXPORT_SYMBOL drivers/parport/parport 0x24f80194 parport_register_driver +EXPORT_SYMBOL drivers/parport/parport 0x3618541d parport_get_port +EXPORT_SYMBOL drivers/parport/parport 0x4d2a941b parport_ieee1284_interrupt +EXPORT_SYMBOL drivers/parport/parport 0x6164f282 parport_register_port +EXPORT_SYMBOL drivers/parport/parport 0x7470e47c parport_wait_event +EXPORT_SYMBOL drivers/parport/parport 0x807f07a9 parport_claim +EXPORT_SYMBOL drivers/parport/parport 0x82ee3376 parport_ieee1284_ecp_read_data +EXPORT_SYMBOL drivers/parport/parport 0x83944bda parport_set_timeout +EXPORT_SYMBOL drivers/parport/parport 0x86c76bd9 parport_put_port +EXPORT_SYMBOL drivers/parport/parport 0x8a55708f parport_write +EXPORT_SYMBOL drivers/parport/parport 0x8c783aea parport_ieee1284_read_byte +EXPORT_SYMBOL drivers/parport/parport 0x9006cdbb parport_ieee1284_epp_write_data +EXPORT_SYMBOL drivers/parport/parport 0x9d09de9b parport_find_number +EXPORT_SYMBOL drivers/parport/parport 0xa04de30e parport_announce_port +EXPORT_SYMBOL drivers/parport/parport 0xb1fcbd6e parport_wait_peripheral +EXPORT_SYMBOL drivers/parport/parport 0xb5658820 parport_read +EXPORT_SYMBOL drivers/parport/parport 0xb8e4307d parport_ieee1284_epp_read_data +EXPORT_SYMBOL drivers/parport/parport 0xbeded507 parport_ieee1284_epp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0xbfd7c3fd parport_ieee1284_write_compat +EXPORT_SYMBOL drivers/parport/parport 0xc1b3eb8b parport_ieee1284_ecp_write_data +EXPORT_SYMBOL drivers/parport/parport 0xc425771c parport_release +EXPORT_SYMBOL drivers/parport/parport 0xc72101a6 parport_find_base +EXPORT_SYMBOL drivers/parport/parport 0xde0081d3 parport_unregister_device +EXPORT_SYMBOL drivers/parport/parport 0xde60f79f parport_ieee1284_epp_read_addr +EXPORT_SYMBOL drivers/parport/parport 0xe2881df8 parport_ieee1284_read_nibble +EXPORT_SYMBOL drivers/parport/parport 0xe320064e parport_register_device +EXPORT_SYMBOL drivers/parport/parport 0xe4673441 parport_claim_or_block +EXPORT_SYMBOL drivers/parport/parport 0xee587ccd parport_remove_port +EXPORT_SYMBOL drivers/parport/parport 0xef6bf337 parport_ieee1284_ecp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0xf7fece72 parport_negotiate +EXPORT_SYMBOL drivers/parport/parport_pc 0x915aa79b parport_pc_unregister_port +EXPORT_SYMBOL drivers/parport/parport_pc 0xace2c333 parport_pc_probe_port +EXPORT_SYMBOL drivers/pci/hotplug/pci_hotplug 0xe5b7236d acpi_get_hp_hw_control_from_firmware +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x00f4fae1 pcmcia_get_configuration_info +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x01780662 pcmcia_unregister_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x05e08224 pcmcia_request_io +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x09882f37 pcmcia_dev_present +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x1435e229 pcmcia_request_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x23c83ea7 pcmcia_map_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x3e78db08 pcmcia_get_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x40568bf0 pcmcia_disable_device +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x493de1dd pcmcia_release_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x559316c5 pcmcia_request_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x5a2a72ec pcmcia_request_irq +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x921b34f4 pcmcia_modify_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x9782d1cb pcmcia_register_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa84b81db pcmcia_get_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xb189c69a pcmcia_access_configuration_register +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xd0b83610 cs_error +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x06f1320a pccard_static_ops +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0a7de149 pcmcia_write_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0abf5659 pcmcia_validate_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x1470b1af pccard_get_next_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x212db8d2 pcmcia_socket_list +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x21c76830 pccard_validate_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x28955812 pcmcia_resume_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2e59383e pccard_get_first_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x36d91114 pcmcia_socket_dev_suspend +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x3bd1d850 pcmcia_find_mem_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x3e80089e pcmcia_read_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x42f6ffee pccard_read_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x464cb670 pcmcia_suspend_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x61728a7d pcmcia_insert_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x68fecee3 pcmcia_eject_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x6b6e4a1c pcmcia_replace_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x71dccff1 pcmcia_find_io_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7267bfe7 release_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x76bc9342 pccard_register_pcmcia +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7f7952b0 pcmcia_register_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x88b88feb pcmcia_get_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x8bf9177a destroy_cis_cache +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x90420130 pcmcia_get_socket_by_nr +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x9be794be pcmcia_socket_dev_resume +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x9c7d8602 pccard_reset_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xae405222 pcmcia_put_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xaecccf30 pcmcia_adjust_io_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc368f687 pcmcia_socket_list_rwsem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc408fb86 pccard_get_tuple_data +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcd2ac1c1 pccard_parse_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcf97f3bd dead_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcfd2adf3 pcmcia_parse_events +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xe9838519 pcmcia_unregister_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xee11c82e pcmcia_socket_class +EXPORT_SYMBOL drivers/pcmcia/rsrc_nonstatic 0x1ed6e497 pccard_nonstatic_ops +EXPORT_SYMBOL drivers/scsi/53c700 0x2e01c321 NCR_700_release +EXPORT_SYMBOL drivers/scsi/53c700 0x5175c0f0 NCR_700_intr +EXPORT_SYMBOL drivers/scsi/53c700 0xd12bd30f NCR_700_detect +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x2250c66e mraid_mm_adapter_app_handle +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x512c956d mraid_mm_unregister_adp +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x530a2d58 mraid_mm_register_adp +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x2ff1853e qlogicfas408_queuecommand +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x34af2726 qlogicfas408_disable_ints +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x3fd8cd71 qlogicfas408_detect +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x46e62008 qlogicfas408_bus_reset +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x5cd179e6 qlogicfas408_ihandl +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xae9f74d8 qlogicfas408_abort +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xc989af08 qlogicfas408_biosparam +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xc98c154f qlogicfas408_info +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xe76b3b20 qlogicfas408_get_chip_type +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xf2b95199 qlogicfas408_setup +EXPORT_SYMBOL drivers/scsi/raid_class 0x18b725c6 raid_class_attach +EXPORT_SYMBOL drivers/scsi/raid_class 0x524dea31 raid_component_add +EXPORT_SYMBOL drivers/scsi/raid_class 0x8f97802b raid_class_release +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x005d60a0 scsi_print_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x00db159f scsi_free_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x03a2e4ec scsi_setup_blk_pc_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x03a4fc06 __starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x04fa1041 scsi_block_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x05f3df1a scsi_target_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x087c3c79 scsi_unblock_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x091f00c4 scsi_req_abort_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c65e73c scsi_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c8c9e99 scsi_show_extd_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0d50babc scsi_host_get +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x105fc1ab scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x110e5f83 scsi_nonblockable_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x11267875 scsi_extd_sense_format +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x18f5af49 scsi_register +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1a13e6b3 scsi_eh_restore_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1b9e0ff1 scsilun_to_int +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x22821be1 scsi_track_queue_full +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x23d1b196 scsi_reset_provider +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x23d27736 scsi_device_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x24ab261a __scsi_alloc_queue +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x25583fd0 scsi_device_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x26e22316 scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28a2ed02 scsi_build_sense_buffer +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2ae54860 scsi_cmd_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2b0ba2b0 scsi_sense_desc_find +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2bbbbcf4 scsi_get_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2cff1d01 scsi_add_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2d89342a scsi_show_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3440e377 scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x34d59d63 scsi_register_interface +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x36086461 scsi_calculate_bounce_limit +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3b92c3a4 scsi_report_device_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3d6adcd4 scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x40c7b9de scsi_scan_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x416508e9 scsi_dma_unmap +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4746bccc scsi_remove_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4afe9a77 scsi_partsize +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4bd43f65 scsi_host_alloc +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4cf6d4f6 __scsi_iterate_devices +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4f6b11a4 scsi_prep_return +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x51b17301 scsi_allocate_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x52011d73 scsi_host_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x56c8799d scsi_kunmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x578fd41b scsi_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5bbc9119 scsi_report_bus_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x62a80ef9 scsi_target_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x62f962ea scsi_eh_prep_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6565d33f scsi_kmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x68d25496 scsi_finish_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x69d38ed9 __scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6a023e37 scsi_execute +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6b013d0c scsi_host_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6dc26376 scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6dd7f256 scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72ea7b2d scsi_device_type +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x73fcc431 scsi_device_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x76dac2aa scsi_is_sdev_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x796fc5ce scsi_get_sense_info_fld +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7ca4945c scsi_free_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x81319442 scsi_device_get +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x82a6f194 scsi_unregister +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x857da51c scsi_bios_ptable +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x882d2a74 scsi_get_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x919c6d15 starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x92833345 scsi_set_medium_removal +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x951c2990 scsi_is_target_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96cd2b04 scsi_sense_key_string +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9939d933 __scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9cd6af7a scsi_eh_finish_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9cfd56c5 scsi_print_status +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa34ca500 scsi_host_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa7b2638b scsi_device_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa97e3ebd __scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa9de2004 scsi_adjust_queue_depth +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaa0722d7 scsi_is_host_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaf3dd7dc scsi_logging_level +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb6c5a973 scsi_show_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xba3e33f4 scsi_setup_fs_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbf6cafab scsi_block_when_processing_errors +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc65e9676 scsi_prep_state_check +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc723e374 __scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xca5dbc50 scsi_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xcd2a676c scsi_command_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xcfd0cf31 scsi_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd56d9471 scsi_rescan_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd8e8c44d scsi_test_unit_ready +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe15e9e29 scsi_execute_req +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe1faa274 scsi_dma_map +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe4c02343 scsi_release_buffers +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe8e081bc scsi_remove_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe94d8782 scsi_init_io +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xea10212a int_to_scsilun +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xeca66002 scsi_register_driver +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf240647e scsi_scan_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf811e69d scsi_eh_flush_done_q +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf911f424 scsicam_bios_param +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfef96e23 __scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xff018124 __scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xffa6522c scsi_mode_sense +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x17b85535 fc_remote_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x1ea2d87e fc_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x3ab2ce80 fc_remote_port_rolechg +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x40ae79d3 fc_vport_terminate +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x4982b4da scsi_is_fc_rport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x4a79c3e1 fc_host_post_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x6b1ff841 fc_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x7954b1ea fc_get_event_number +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xb703d7ee fc_remote_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xd354c01a fc_host_post_vendor_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xf2bad470 scsi_is_fc_vport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xf5f70f04 fc_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x1b65ad2b sas_phy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x27b17078 scsi_is_sas_port +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x28bc19f1 sas_remove_children +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x2deae953 sas_phy_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x2fe78f94 sas_rphy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x344beb2f sas_phy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x481f044f sas_port_add_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x57c2851f sas_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x58b3864c sas_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x629f868e sas_port_alloc_num +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x65f6b537 sas_phy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x6b5547c6 sas_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x7c08c0b1 sas_port_mark_backlink +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x7ff56022 sas_rphy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x8283002a sas_rphy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xa171006b sas_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xa974c376 scsi_is_sas_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xb0b2596e scsi_is_sas_rphy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xb41e2125 sas_rphy_remove +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xbd1b5bae sas_port_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xbfd48c22 sas_port_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xd37fae4f sas_end_device_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xec63e252 sas_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf39986bc sas_read_port_mode_page +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf4e648ac sas_expander_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xfbbbe666 sas_port_delete_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x3686ea09 spi_print_msg +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x424a4837 spi_schedule_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x86eff9ff spi_display_xfer_agreement +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x95bd1ef3 spi_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xd3c54e41 spi_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xe3597e68 spi_release_transport +EXPORT_SYMBOL drivers/ssb/ssb 0x0192c2d5 ssb_device_is_enabled +EXPORT_SYMBOL drivers/ssb/ssb 0x0b17036d ssb_dma_translation +EXPORT_SYMBOL drivers/ssb/ssb 0x0cf98d44 ssb_dma_set_mask +EXPORT_SYMBOL drivers/ssb/ssb 0x0debec89 ssb_clockspeed +EXPORT_SYMBOL drivers/ssb/ssb 0x26640bf9 ssb_device_enable +EXPORT_SYMBOL drivers/ssb/ssb 0x3f7da1d3 ssb_bus_resume +EXPORT_SYMBOL drivers/ssb/ssb 0x5fdf0494 ssb_pcihost_register +EXPORT_SYMBOL drivers/ssb/ssb 0x644709a4 ssb_set_devtypedata +EXPORT_SYMBOL drivers/ssb/ssb 0x6ebed914 ssb_bus_pcibus_register +EXPORT_SYMBOL drivers/ssb/ssb 0x6f1434bf __ssb_driver_register +EXPORT_SYMBOL drivers/ssb/ssb 0x78d8e8bc ssb_bus_may_powerdown +EXPORT_SYMBOL drivers/ssb/ssb 0x8eaec377 ssb_driver_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0x9fd9b53b ssb_bus_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0xa032e5e7 ssb_pcicore_dev_irqvecs_enable +EXPORT_SYMBOL drivers/ssb/ssb 0xb4e794d3 ssb_bus_powerup +EXPORT_SYMBOL drivers/ssb/ssb 0xc0512e0f ssb_admatch_base +EXPORT_SYMBOL drivers/ssb/ssb 0xd481192b ssb_admatch_size +EXPORT_SYMBOL drivers/ssb/ssb 0xd7658872 ssb_bus_suspend +EXPORT_SYMBOL drivers/ssb/ssb 0xebf1a563 ssb_dma_alloc_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0xf1071c9d ssb_dma_free_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0xf8536c08 ssb_device_disable +EXPORT_SYMBOL drivers/telephony/ixj 0x20a8bd9d ixj_pcmcia_probe +EXPORT_SYMBOL drivers/telephony/phonedev 0x7db4e5d3 phone_register_device +EXPORT_SYMBOL drivers/telephony/phonedev 0x997822cd phone_unregister_device +EXPORT_SYMBOL drivers/usb/gadget/net2280 0x490bf765 usb_gadget_unregister_driver +EXPORT_SYMBOL drivers/usb/gadget/net2280 0x86637842 net2280_set_fifo_mode +EXPORT_SYMBOL drivers/usb/gadget/net2280 0xa028ca59 usb_gadget_register_driver +EXPORT_SYMBOL drivers/usb/host/sl811-hcd 0xe4e3fb9d sl811h_driver +EXPORT_SYMBOL drivers/usb/serial/usbserial 0x82d2f07d usb_serial_suspend +EXPORT_SYMBOL drivers/usb/serial/usbserial 0xe774352e usb_serial_resume +EXPORT_SYMBOL drivers/video/backlight/corgi_bl 0xc86baa7c corgibl_limit_intensity +EXPORT_SYMBOL drivers/video/backlight/lcd 0x13fa6c0f lcd_device_register +EXPORT_SYMBOL drivers/video/backlight/lcd 0x18578089 lcd_device_unregister +EXPORT_SYMBOL drivers/video/console/bitblit 0x5ce81493 fbcon_set_bitops +EXPORT_SYMBOL drivers/video/console/font 0x09c8eb55 font_vga_8x16 +EXPORT_SYMBOL drivers/video/console/font 0xbb99125c get_default_font +EXPORT_SYMBOL drivers/video/console/font 0xf7584a9c find_font +EXPORT_SYMBOL drivers/video/console/softcursor 0xad12173d soft_cursor +EXPORT_SYMBOL drivers/video/console/tileblit 0xc057456c fbcon_set_tileops +EXPORT_SYMBOL drivers/video/cyber2000fb 0x0cc3ede5 cyber2000fb_detach +EXPORT_SYMBOL drivers/video/cyber2000fb 0x1dee9208 cyber2000fb_enable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0xa39fbf8d cyber2000fb_get_fb_var +EXPORT_SYMBOL drivers/video/cyber2000fb 0xde758135 cyber2000fb_disable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0xf7ca059d cyber2000fb_attach +EXPORT_SYMBOL drivers/video/display/display 0xa0745a39 display_device_register +EXPORT_SYMBOL drivers/video/display/display 0xc7f4b880 display_device_unregister +EXPORT_SYMBOL drivers/video/macmodes 0x08ed0b62 mac_vmode_to_var +EXPORT_SYMBOL drivers/video/macmodes 0x65bfac9a mac_find_mode +EXPORT_SYMBOL drivers/video/macmodes 0xe2304303 mac_map_monitor_sense +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x73f88e37 matroxfb_g450_setclk +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0xd4c81bda g450_mnp2f +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0xdac6999e matroxfb_g450_setpll_cond +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x0eb8d223 DAC1064_global_restore +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x44af852a matrox_G100 +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xaa287229 matrox_mystique +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xffeea833 DAC1064_global_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_Ti3026 0xa9910b92 matrox_millennium +EXPORT_SYMBOL drivers/video/matrox/matroxfb_accel 0x9942b4e2 matrox_cfbX_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x18705282 matroxfb_enable_irq +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x2530c726 matroxfb_register_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x78acfbc2 matroxfb_unregister_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xd7ab523f matroxfb_wait_for_sync +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x03797344 matroxfb_g450_connect +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x8741227d matroxfb_g450_shutdown +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x082d5116 matroxfb_vgaHWrestore +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x1a2d0f75 matroxfb_DAC_out +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x25cf8049 matroxfb_PLL_calcclock +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x5a4a6d94 matroxfb_read_pins +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x7f7a5c07 matroxfb_DAC_in +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xabd8e427 matroxfb_var2my +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xbb6fdd8e matroxfb_vgaHWinit +EXPORT_SYMBOL drivers/video/output 0x0948c179 video_output_unregister +EXPORT_SYMBOL drivers/video/output 0x81ec7b94 video_output_register +EXPORT_SYMBOL drivers/video/sis/sisfb 0x3037658e sis_malloc +EXPORT_SYMBOL drivers/video/sis/sisfb 0x454a3cf0 sis_free +EXPORT_SYMBOL drivers/video/svgalib 0x00d1fce9 svga_set_default_seq_regs +EXPORT_SYMBOL drivers/video/svgalib 0x07b3da30 svga_wseq_multi +EXPORT_SYMBOL drivers/video/svgalib 0x1b95c56a svga_check_timings +EXPORT_SYMBOL drivers/video/svgalib 0x27f81af0 svga_tileblit +EXPORT_SYMBOL drivers/video/svgalib 0x4e8abef4 svga_tilecopy +EXPORT_SYMBOL drivers/video/svgalib 0x63e898d1 svga_set_default_crt_regs +EXPORT_SYMBOL drivers/video/svgalib 0x732ce02c svga_get_tilemax +EXPORT_SYMBOL drivers/video/svgalib 0x7a3ae959 svga_wcrt_multi +EXPORT_SYMBOL drivers/video/svgalib 0x80408443 svga_set_timings +EXPORT_SYMBOL drivers/video/svgalib 0x8fa8438b svga_set_textmode_vga_regs +EXPORT_SYMBOL drivers/video/svgalib 0xab3b22ad svga_set_default_gfx_regs +EXPORT_SYMBOL drivers/video/svgalib 0xba7e6656 svga_tilefill +EXPORT_SYMBOL drivers/video/svgalib 0xc8dd39fe svga_get_caps +EXPORT_SYMBOL drivers/video/svgalib 0xd108964b svga_settile +EXPORT_SYMBOL drivers/video/svgalib 0xdad682b1 svga_set_default_atc_regs +EXPORT_SYMBOL drivers/video/svgalib 0xe727301b svga_tilecursor +EXPORT_SYMBOL drivers/video/svgalib 0xec83c473 svga_match_format +EXPORT_SYMBOL drivers/video/svgalib 0xef774f5d svga_compute_pll +EXPORT_SYMBOL drivers/video/syscopyarea 0x37d0bd53 sys_copyarea +EXPORT_SYMBOL drivers/video/sysfillrect 0x4fc5dda5 sys_fillrect +EXPORT_SYMBOL drivers/video/sysimgblt 0x8a72b9fc sys_imageblit +EXPORT_SYMBOL drivers/video/vgastate 0x686de290 restore_vga +EXPORT_SYMBOL drivers/video/vgastate 0xe7a2620e save_vga +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x0a241503 w1_ds2760_read +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x84bcae12 w1_ds2760_write +EXPORT_SYMBOL drivers/w1/wire 0x7385a0ce w1_unregister_family +EXPORT_SYMBOL drivers/w1/wire 0x8cf61660 w1_add_master_device +EXPORT_SYMBOL drivers/w1/wire 0xcda061c0 w1_remove_master_device +EXPORT_SYMBOL drivers/w1/wire 0xdd8ecca7 w1_register_family +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x04e133fc iTCO_vendor_check_noreboot_on +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x672c9d44 iTCO_vendor_pre_keepalive +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa78bd894 iTCO_vendor_pre_set_heartbeat +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa8d6daac iTCO_vendor_pre_start +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xd0efe320 iTCO_vendor_pre_stop +EXPORT_SYMBOL fs/configfs/configfs 0x0e00306b config_item_set_name +EXPORT_SYMBOL fs/configfs/configfs 0x1d090a29 configfs_unregister_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0x24127e1c config_item_put +EXPORT_SYMBOL fs/configfs/configfs 0x2c00ed3b configfs_undepend_item +EXPORT_SYMBOL fs/configfs/configfs 0x344260fd configfs_depend_item +EXPORT_SYMBOL fs/configfs/configfs 0x3f60a85a config_group_find_item +EXPORT_SYMBOL fs/configfs/configfs 0x43f02542 config_group_init +EXPORT_SYMBOL fs/configfs/configfs 0x4f09d1d8 config_item_init_type_name +EXPORT_SYMBOL fs/configfs/configfs 0x652e9f04 config_item_init +EXPORT_SYMBOL fs/configfs/configfs 0x93933882 configfs_register_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0xc63a33b9 config_item_get +EXPORT_SYMBOL fs/configfs/configfs 0xfd1a572d config_group_init_type_name +EXPORT_SYMBOL fs/jbd/jbd 0x016e1e49 journal_restart +EXPORT_SYMBOL fs/jbd/jbd 0x1460c466 journal_ack_err +EXPORT_SYMBOL fs/jbd/jbd 0x15aa916a journal_blocks_per_page +EXPORT_SYMBOL fs/jbd/jbd 0x1d653145 journal_abort +EXPORT_SYMBOL fs/jbd/jbd 0x200e89d1 journal_update_format +EXPORT_SYMBOL fs/jbd/jbd 0x2395b6ad journal_revoke +EXPORT_SYMBOL fs/jbd/jbd 0x348a2ec6 journal_dirty_data +EXPORT_SYMBOL fs/jbd/jbd 0x37b22c06 journal_get_undo_access +EXPORT_SYMBOL fs/jbd/jbd 0x3927f6a9 journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd/jbd 0x3f15d0f3 journal_check_used_features +EXPORT_SYMBOL fs/jbd/jbd 0x46bb857e journal_forget +EXPORT_SYMBOL fs/jbd/jbd 0x4935c59e journal_invalidatepage +EXPORT_SYMBOL fs/jbd/jbd 0x51f8e463 journal_init_inode +EXPORT_SYMBOL fs/jbd/jbd 0x559bb229 journal_flush +EXPORT_SYMBOL fs/jbd/jbd 0x56848500 journal_destroy +EXPORT_SYMBOL fs/jbd/jbd 0x587e4140 journal_dirty_metadata +EXPORT_SYMBOL fs/jbd/jbd 0x5ae937bc journal_check_available_features +EXPORT_SYMBOL fs/jbd/jbd 0x5b276ec9 journal_extend +EXPORT_SYMBOL fs/jbd/jbd 0x5d73af05 journal_unlock_updates +EXPORT_SYMBOL fs/jbd/jbd 0x737adbc6 journal_get_write_access +EXPORT_SYMBOL fs/jbd/jbd 0x77c9c1be journal_start_commit +EXPORT_SYMBOL fs/jbd/jbd 0x92bfdd0f journal_load +EXPORT_SYMBOL fs/jbd/jbd 0xac6735b1 log_wait_commit +EXPORT_SYMBOL fs/jbd/jbd 0xb013bf35 journal_set_features +EXPORT_SYMBOL fs/jbd/jbd 0xb9776b1a journal_force_commit +EXPORT_SYMBOL fs/jbd/jbd 0xbbb301d2 journal_create +EXPORT_SYMBOL fs/jbd/jbd 0xc100810c journal_force_commit_nested +EXPORT_SYMBOL fs/jbd/jbd 0xc12c6a34 journal_stop +EXPORT_SYMBOL fs/jbd/jbd 0xc419eb1c journal_start +EXPORT_SYMBOL fs/jbd/jbd 0xc782b02c journal_init_dev +EXPORT_SYMBOL fs/jbd/jbd 0xcb853ae7 journal_get_create_access +EXPORT_SYMBOL fs/jbd/jbd 0xd584acb7 journal_release_buffer +EXPORT_SYMBOL fs/jbd/jbd 0xd70af4f6 journal_lock_updates +EXPORT_SYMBOL fs/jbd/jbd 0xe64ca93f journal_wipe +EXPORT_SYMBOL fs/jbd/jbd 0xeb75224c journal_errno +EXPORT_SYMBOL fs/jbd/jbd 0xf3c758b8 journal_clear_err +EXPORT_SYMBOL fs/jbd2/jbd2 0x0bb4b8f8 jbd2_journal_init_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x1fda2108 jbd2_journal_forget +EXPORT_SYMBOL fs/jbd2/jbd2 0x250a46f9 jbd2_journal_update_format +EXPORT_SYMBOL fs/jbd2/jbd2 0x2ba3c285 jbd2_journal_set_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x2dfa9147 jbd2_journal_get_undo_access +EXPORT_SYMBOL fs/jbd2/jbd2 0x306b1507 jbd2_journal_extend +EXPORT_SYMBOL fs/jbd2/jbd2 0x3a631ab3 jbd2_journal_invalidatepage +EXPORT_SYMBOL fs/jbd2/jbd2 0x3abfa737 jbd2_journal_flush +EXPORT_SYMBOL fs/jbd2/jbd2 0x3d2ba50c jbd2_journal_init_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x4165a6ef jbd2_journal_create +EXPORT_SYMBOL fs/jbd2/jbd2 0x426b75b6 jbd2_journal_start_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x4b723532 jbd2_journal_get_write_access +EXPORT_SYMBOL fs/jbd2/jbd2 0x4bf7e091 jbd2_log_wait_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x4cc01b5d jbd2_journal_blocks_per_page +EXPORT_SYMBOL fs/jbd2/jbd2 0x4f8dae74 jbd2_journal_ack_err +EXPORT_SYMBOL fs/jbd2/jbd2 0x5dd03867 jbd2_journal_start +EXPORT_SYMBOL fs/jbd2/jbd2 0x78847054 jbd2_journal_force_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x7abccd34 jbd2_journal_init_dev +EXPORT_SYMBOL fs/jbd2/jbd2 0x80574da2 jbd2_journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd2/jbd2 0x847913bf jbd2_journal_release_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x864d6344 jbd2_journal_unlock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0x98656c4a jbd2_journal_abort +EXPORT_SYMBOL fs/jbd2/jbd2 0x9a97314a jbd2_journal_errno +EXPORT_SYMBOL fs/jbd2/jbd2 0xa28a629f jbd2_journal_clear_features +EXPORT_SYMBOL fs/jbd2/jbd2 0xabade652 jbd2_journal_check_used_features +EXPORT_SYMBOL fs/jbd2/jbd2 0xad0bae87 jbd2_journal_begin_ordered_truncate +EXPORT_SYMBOL fs/jbd2/jbd2 0xba6e9654 jbd2_journal_force_commit_nested +EXPORT_SYMBOL fs/jbd2/jbd2 0xc1866f4e jbd2_journal_revoke +EXPORT_SYMBOL fs/jbd2/jbd2 0xc23024d6 jbd2_journal_restart +EXPORT_SYMBOL fs/jbd2/jbd2 0xc230c242 jbd2_journal_lock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0xc418a973 jbd2_journal_file_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0xd12ecf25 jbd2_journal_destroy +EXPORT_SYMBOL fs/jbd2/jbd2 0xd542debd jbd2_journal_stop +EXPORT_SYMBOL fs/jbd2/jbd2 0xd85f240a jbd2_journal_get_create_access +EXPORT_SYMBOL fs/jbd2/jbd2 0xdcd5de56 jbd2_journal_load +EXPORT_SYMBOL fs/jbd2/jbd2 0xe377a064 jbd2_journal_wipe +EXPORT_SYMBOL fs/jbd2/jbd2 0xe4c47d95 jbd2_journal_check_available_features +EXPORT_SYMBOL fs/jbd2/jbd2 0xef7e0d4d jbd2_journal_clear_err +EXPORT_SYMBOL fs/jbd2/jbd2 0xef9ccebb jbd2_journal_dirty_metadata +EXPORT_SYMBOL fs/jbd2/jbd2 0xf0fb7bd1 jbd2_journal_release_buffer +EXPORT_SYMBOL fs/lockd/lockd 0x2f360fa5 nlmsvc_ops +EXPORT_SYMBOL fs/lockd/lockd 0x976e539e lockd_up +EXPORT_SYMBOL fs/lockd/lockd 0xa7b91a7b lockd_down +EXPORT_SYMBOL fs/lockd/lockd 0xad09c2db get_nfs_grace_period +EXPORT_SYMBOL fs/mbcache 0x071edf63 mb_cache_entry_alloc +EXPORT_SYMBOL fs/mbcache 0x3ba28212 mb_cache_entry_release +EXPORT_SYMBOL fs/mbcache 0x84aa695a mb_cache_entry_insert +EXPORT_SYMBOL fs/mbcache 0x9166d679 mb_cache_entry_find_first +EXPORT_SYMBOL fs/mbcache 0x949fb87b mb_cache_create +EXPORT_SYMBOL fs/mbcache 0xa8239d07 mb_cache_entry_free +EXPORT_SYMBOL fs/mbcache 0xd5263820 mb_cache_destroy +EXPORT_SYMBOL fs/mbcache 0xd540a003 mb_cache_entry_get +EXPORT_SYMBOL fs/mbcache 0xdf906884 mb_cache_shrink +EXPORT_SYMBOL fs/mbcache 0xea23b969 mb_cache_entry_find_next +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0x094de6c0 nfsacl_encode +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0xbaaca1be nfsacl_decode +EXPORT_SYMBOL fs/nfsd/nfsd 0x0f3e6e01 nfs4_acl_nfsv4_to_posix +EXPORT_SYMBOL fs/nfsd/nfsd 0x2095976a nfs4_acl_new +EXPORT_SYMBOL fs/nfsd/nfsd 0x35e33c1e nfs4_acl_write_who +EXPORT_SYMBOL fs/nfsd/nfsd 0x5a157ae4 nfs4_acl_get_whotype +EXPORT_SYMBOL fs/nfsd/nfsd 0x7ee78c79 nfs4_acl_posix_to_nfsv4 +EXPORT_SYMBOL fs/xfs/xfs 0xcf41096a xfs_qmcore_xfs +EXPORT_SYMBOL lib/crc-ccitt 0x3771b461 crc_ccitt +EXPORT_SYMBOL lib/crc-ccitt 0x75811312 crc_ccitt_table +EXPORT_SYMBOL lib/crc-itu-t 0xd29b009f crc_itu_t_table +EXPORT_SYMBOL lib/crc-itu-t 0xf5b4a948 crc_itu_t +EXPORT_SYMBOL lib/crc-t10dif 0xb6896671 crc_t10dif +EXPORT_SYMBOL lib/crc16 0x02a6ce5a crc16_table +EXPORT_SYMBOL lib/crc16 0x8ffdb3b8 crc16 +EXPORT_SYMBOL lib/crc7 0xa7587646 crc7 +EXPORT_SYMBOL lib/crc7 0xd80c3603 crc7_syndrome_table +EXPORT_SYMBOL lib/libcrc32c 0x2329b292 crc32c_be +EXPORT_SYMBOL lib/libcrc32c 0x37d0b921 crc32c_le +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x315c65fd zlib_deflateInit2 +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x48034724 zlib_deflateReset +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xaf64ad0d zlib_deflate +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf0caf44b zlib_deflate_workspacesize +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf741c793 zlib_deflateEnd +EXPORT_SYMBOL net/802/p8023 0x3f620b17 destroy_8023_client +EXPORT_SYMBOL net/802/p8023 0x957ffa02 make_8023_client +EXPORT_SYMBOL net/9p/9pnet 0x00a6e1a5 p9_create_tclunk +EXPORT_SYMBOL net/9p/9pnet 0x0106a185 p9_create_tstat +EXPORT_SYMBOL net/9p/9pnet 0x0d2d1c7d p9_client_destroy +EXPORT_SYMBOL net/9p/9pnet 0x1307683c p9_client_fcreate +EXPORT_SYMBOL net/9p/9pnet 0x15779868 p9_set_tag +EXPORT_SYMBOL net/9p/9pnet 0x1cd6e5be p9_idpool_get +EXPORT_SYMBOL net/9p/9pnet 0x1f377405 p9_client_read +EXPORT_SYMBOL net/9p/9pnet 0x1f79fdcd p9_client_uwrite +EXPORT_SYMBOL net/9p/9pnet 0x21523da9 p9_create_tattach +EXPORT_SYMBOL net/9p/9pnet 0x22ab689b p9_client_stat +EXPORT_SYMBOL net/9p/9pnet 0x28551a4f p9_client_clunk +EXPORT_SYMBOL net/9p/9pnet 0x3010fa95 p9_idpool_put +EXPORT_SYMBOL net/9p/9pnet 0x309767d8 p9_deserialize_stat +EXPORT_SYMBOL net/9p/9pnet 0x32e01f91 p9_client_open +EXPORT_SYMBOL net/9p/9pnet 0x3d73a797 p9_errstr2errno +EXPORT_SYMBOL net/9p/9pnet 0x465c4e6f p9_printfcall +EXPORT_SYMBOL net/9p/9pnet 0x47f2a66e v9fs_register_trans +EXPORT_SYMBOL net/9p/9pnet 0x4a35db3c p9_client_dirread +EXPORT_SYMBOL net/9p/9pnet 0x507c9d70 p9_create_tauth +EXPORT_SYMBOL net/9p/9pnet 0x52c450c4 p9_client_readn +EXPORT_SYMBOL net/9p/9pnet 0x5b4ee9e6 p9_client_attach +EXPORT_SYMBOL net/9p/9pnet 0x6146a046 v9fs_get_default_trans +EXPORT_SYMBOL net/9p/9pnet 0x6461b8de p9_create_twrite +EXPORT_SYMBOL net/9p/9pnet 0x64c69ae9 p9_client_disconnect +EXPORT_SYMBOL net/9p/9pnet 0x69e9d7f1 v9fs_get_trans_by_name +EXPORT_SYMBOL net/9p/9pnet 0x6f11c5c3 p9_create_twrite_u +EXPORT_SYMBOL net/9p/9pnet 0x71c7537d p9_create_tcreate +EXPORT_SYMBOL net/9p/9pnet 0x7fb83e97 p9_client_wstat +EXPORT_SYMBOL net/9p/9pnet 0x81247f39 p9_create_tread +EXPORT_SYMBOL net/9p/9pnet 0x8432c83f p9_deserialize_fcall +EXPORT_SYMBOL net/9p/9pnet 0x88128345 p9_client_auth +EXPORT_SYMBOL net/9p/9pnet 0x906dda57 p9_client_walk +EXPORT_SYMBOL net/9p/9pnet 0x950e6b03 p9_create_twstat +EXPORT_SYMBOL net/9p/9pnet 0xa5148987 p9_client_remove +EXPORT_SYMBOL net/9p/9pnet 0xa9536064 p9_create_tversion +EXPORT_SYMBOL net/9p/9pnet 0xadfd597a p9_create_tremove +EXPORT_SYMBOL net/9p/9pnet 0xb671b7eb p9_idpool_create +EXPORT_SYMBOL net/9p/9pnet 0xc724aa62 p9_idpool_destroy +EXPORT_SYMBOL net/9p/9pnet 0xcda72e50 p9_client_write +EXPORT_SYMBOL net/9p/9pnet 0xd9ae87c5 p9_client_uread +EXPORT_SYMBOL net/9p/9pnet 0xdc894ac7 p9_create_twalk +EXPORT_SYMBOL net/9p/9pnet 0xdf690635 p9_client_create +EXPORT_SYMBOL net/9p/9pnet 0xe58a3360 p9_error_init +EXPORT_SYMBOL net/9p/9pnet 0xf09b3efa p9_create_topen +EXPORT_SYMBOL net/9p/9pnet 0xfa096122 v9fs_unregister_trans +EXPORT_SYMBOL net/9p/9pnet 0xfb11172a p9_idpool_check +EXPORT_SYMBOL net/9p/9pnet 0xfff27930 p9_create_tflush +EXPORT_SYMBOL net/appletalk/appletalk 0x01af7bd8 atrtr_get_dev +EXPORT_SYMBOL net/appletalk/appletalk 0x50660285 aarp_send_ddp +EXPORT_SYMBOL net/appletalk/appletalk 0x7ce7b8b0 atalk_find_dev_addr +EXPORT_SYMBOL net/appletalk/appletalk 0x8139a13e alloc_ltalkdev +EXPORT_SYMBOL net/ax25/ax25 0x0020ed15 ax25_hard_header +EXPORT_SYMBOL net/ax25/ax25 0x242852b9 ax25_uid_policy +EXPORT_SYMBOL net/ax25/ax25 0x27ecb983 ax25_header_ops +EXPORT_SYMBOL net/ax25/ax25 0x2a39f956 ax25_find_cb +EXPORT_SYMBOL net/ax25/ax25 0x3d2d82ec ax25_display_timer +EXPORT_SYMBOL net/ax25/ax25 0x4502c65a asc2ax +EXPORT_SYMBOL net/ax25/ax25 0x49ab5314 ax25_findbyuid +EXPORT_SYMBOL net/ax25/ax25 0x53dea1ff ax2asc +EXPORT_SYMBOL net/ax25/ax25 0x8ede9e26 ax25_protocol_release +EXPORT_SYMBOL net/ax25/ax25 0xa111de1c ax25_linkfail_release +EXPORT_SYMBOL net/ax25/ax25 0xa8f54ae7 ax25_send_frame +EXPORT_SYMBOL net/ax25/ax25 0xbfdb44c4 ax25_rebuild_header +EXPORT_SYMBOL net/ax25/ax25 0xc1444946 ax25cmp +EXPORT_SYMBOL net/ax25/ax25 0xc2f578d3 ax25_listen_release +EXPORT_SYMBOL net/ax25/ax25 0xc3ee5657 ax25_listen_register +EXPORT_SYMBOL net/ax25/ax25 0xd43ecbf1 null_ax25_address +EXPORT_SYMBOL net/ax25/ax25 0xffca92ba ax25_linkfail_register +EXPORT_SYMBOL net/bluetooth/bluetooth 0x02bd44d6 bt_sock_wait_state +EXPORT_SYMBOL net/bluetooth/bluetooth 0x03b7df61 hci_send_sco +EXPORT_SYMBOL net/bluetooth/bluetooth 0x0a9451cd hci_unregister_proto +EXPORT_SYMBOL net/bluetooth/bluetooth 0x13ea08de bt_sock_register +EXPORT_SYMBOL net/bluetooth/bluetooth 0x36e346c5 bt_sock_recvmsg +EXPORT_SYMBOL net/bluetooth/bluetooth 0x39705932 bt_accept_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0x49d8b11d hci_alloc_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x54f9524d hci_connect +EXPORT_SYMBOL net/bluetooth/bluetooth 0x567a4739 hci_free_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x5aec7086 hci_register_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0x5f285d20 hci_send_acl +EXPORT_SYMBOL net/bluetooth/bluetooth 0x64229f24 bt_accept_dequeue +EXPORT_SYMBOL net/bluetooth/bluetooth 0x7094f8ae bt_err +EXPORT_SYMBOL net/bluetooth/bluetooth 0x7f7f1e97 hci_conn_check_link_mode +EXPORT_SYMBOL net/bluetooth/bluetooth 0x803584a0 hci_get_route +EXPORT_SYMBOL net/bluetooth/bluetooth 0x8626d74b hci_register_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x88007dfc bt_sock_poll +EXPORT_SYMBOL net/bluetooth/bluetooth 0xa07a4462 hci_conn_encrypt +EXPORT_SYMBOL net/bluetooth/bluetooth 0xa3034628 hci_conn_switch_role +EXPORT_SYMBOL net/bluetooth/bluetooth 0xa5c8b877 hci_resume_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0xac3d92f3 bt_sock_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0xadc9453d hci_conn_auth +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb1c65e12 hci_register_proto +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb5aeb8c1 hci_conn_change_link_key +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb8501266 hci_unregister_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0xc029a7bf hci_unregister_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0xc2066af0 batostr +EXPORT_SYMBOL net/bluetooth/bluetooth 0xc989cfe8 hci_recv_fragment +EXPORT_SYMBOL net/bluetooth/bluetooth 0xcc1fb551 baswap +EXPORT_SYMBOL net/bluetooth/bluetooth 0xceb54642 bt_accept_enqueue +EXPORT_SYMBOL net/bluetooth/bluetooth 0xd61f1db0 bt_sock_link +EXPORT_SYMBOL net/bluetooth/bluetooth 0xed4343c7 hci_suspend_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf19294db bt_sock_unregister +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf3183388 bt_sock_ioctl +EXPORT_SYMBOL net/bluetooth/l2cap 0xfc31fe88 l2cap_load +EXPORT_SYMBOL net/bridge/bridge 0xd774e546 br_should_route_hook +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x019b15c0 ebt_unregister_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x24b23982 ebt_register_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x2cc1cfa3 ebt_register_match +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x42a338a3 ebt_register_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xaba17079 ebt_register_watcher +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xb3bf02ca ebt_unregister_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xb481ba01 ebt_do_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xb494b3c7 ebt_unregister_match +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xd4510086 ebt_unregister_watcher +EXPORT_SYMBOL net/ieee80211/ieee80211 0x1061dcd9 ieee80211_get_channel_flags +EXPORT_SYMBOL net/ieee80211/ieee80211 0x2dfc3a82 ieee80211_is_valid_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x36913400 ieee80211_freq_to_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x3bb0488d ieee80211_get_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0x42a78652 ieee80211_wx_set_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211 0x5457cb91 ieee80211_wx_get_scan +EXPORT_SYMBOL net/ieee80211/ieee80211 0x6b16560a free_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0x70dd0c93 ieee80211_get_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x7612fdd8 ieee80211_wx_set_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0x82b5f9a1 ieee80211_channel_to_index +EXPORT_SYMBOL net/ieee80211/ieee80211 0x8a05d3a1 ieee80211_channel_to_freq +EXPORT_SYMBOL net/ieee80211/ieee80211 0x907fe44e ieee80211_wx_get_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211 0x925b4950 ieee80211_rx_mgt +EXPORT_SYMBOL net/ieee80211/ieee80211 0xa9fb135f escape_essid +EXPORT_SYMBOL net/ieee80211/ieee80211 0xcb19cbcd alloc_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0xd14f39f0 ieee80211_rx +EXPORT_SYMBOL net/ieee80211/ieee80211 0xddb8acfa ieee80211_set_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0xde730d49 ieee80211_wx_get_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0xf12a0201 ieee80211_txb_free +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x1298e6b8 ieee80211_crypt_quiescing +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x1b677409 ieee80211_crypt_deinit_entries +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x279e265f ieee80211_crypt_deinit_handler +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x294d97d0 ieee80211_unregister_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x53ec1a17 ieee80211_crypt_delayed_deinit +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x7048760e ieee80211_register_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0xfef971f7 ieee80211_get_crypto_ops +EXPORT_SYMBOL net/ipv4/inet_lro 0x6ee775ca lro_vlan_hwaccel_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0x8bad1b0a lro_flush_pkt +EXPORT_SYMBOL net/ipv4/inet_lro 0x91eea978 lro_vlan_hwaccel_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0xbb4d139a lro_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0xf6bafb69 lro_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0xfdb8b85d lro_flush_all +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x0f47f69b ip_vs_conn_out_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x115a4916 register_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x2938047d ip_vs_conn_in_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x38763240 unregister_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x3acdce19 ip_vs_conn_new +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x6ffb4562 register_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x721dcb48 register_ip_vs_app_inc +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x7345efc5 ip_vs_conn_put +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x9076bf40 ip_vs_skb_replace +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xa1dbc2d8 ip_vs_proto_name +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xa4a1e25f unregister_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xa8bdce8a ip_vs_tcp_conn_listen +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x3222f9de arpt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x33dd3d0d arpt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x8bb310c8 arpt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x6e9fd803 ipt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0xeb9a912b ipt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0xf084b2ca ipt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x052f940a nf_nat_protocol_register +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x06b06513 nf_nat_mangle_udp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x093387d2 nf_nat_setup_info +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x668d4422 nf_nat_follow_master +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x7ae2ed3d nf_nat_mangle_tcp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xcf5f7ac6 nf_nat_used_tuple +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xf029da75 nf_nat_protocol_unregister +EXPORT_SYMBOL net/ipv4/tunnel4 0x9faf0224 xfrm4_tunnel_deregister +EXPORT_SYMBOL net/ipv4/tunnel4 0xc2ae7986 xfrm4_tunnel_register +EXPORT_SYMBOL net/ipv6/ipv6 0x00b534c0 xfrm6_find_1stfragopt +EXPORT_SYMBOL net/ipv6/ipv6 0x19291335 ipv6_push_nfrag_opts +EXPORT_SYMBOL net/ipv6/ipv6 0x2415700e xfrm6_rcv_spi +EXPORT_SYMBOL net/ipv6/ipv6 0x30123eb5 icmpv6_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0x32f00996 in6_dev_finish_destroy +EXPORT_SYMBOL net/ipv6/ipv6 0x457c791b inet6_release +EXPORT_SYMBOL net/ipv6/ipv6 0x4fa3450a ipv6_chk_prefix +EXPORT_SYMBOL net/ipv6/ipv6 0x521084ab inet6_unregister_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0x538383c0 unregister_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0x571f8e4c ip6_xmit +EXPORT_SYMBOL net/ipv6/ipv6 0x59cef371 inet6_bind +EXPORT_SYMBOL net/ipv6/ipv6 0x63272a16 ip6_frag_match +EXPORT_SYMBOL net/ipv6/ipv6 0x6392a1db inet6_getname +EXPORT_SYMBOL net/ipv6/ipv6 0x6548eedd inet6_ioctl +EXPORT_SYMBOL net/ipv6/ipv6 0x6fda60b5 ipv6_chk_addr +EXPORT_SYMBOL net/ipv6/ipv6 0x7232bc7b ipv6_getsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x7d582800 ip6_frag_init +EXPORT_SYMBOL net/ipv6/ipv6 0x834f2826 xfrm6_prepare_output +EXPORT_SYMBOL net/ipv6/ipv6 0x96543d84 xfrm6_input_addr +EXPORT_SYMBOL net/ipv6/ipv6 0x99dba779 rt6_lookup +EXPORT_SYMBOL net/ipv6/ipv6 0xa9342768 ipv6_dev_get_saddr +EXPORT_SYMBOL net/ipv6/ipv6 0xb905ad82 icmpv6_err_convert +EXPORT_SYMBOL net/ipv6/ipv6 0xbf250142 inet6_del_protocol +EXPORT_SYMBOL net/ipv6/ipv6 0xbfa78bf8 icmpv6_send +EXPORT_SYMBOL net/ipv6/ipv6 0xc9dea977 ipv6_setsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0xcd439822 ip6_route_output +EXPORT_SYMBOL net/ipv6/ipv6 0xce19bac5 register_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0xd1359f62 inet6_add_protocol +EXPORT_SYMBOL net/ipv6/ipv6 0xd2e411f8 inet6_register_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0xdb7e7793 ndisc_mc_map +EXPORT_SYMBOL net/ipv6/ipv6 0xe1a81c3a icmpv6msg_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0xe4af4e13 nf_ip6_checksum +EXPORT_SYMBOL net/ipv6/ipv6 0xe690b8fd __ipv6_isatap_ifid +EXPORT_SYMBOL net/ipv6/ipv6 0xf3e185ee ip6_route_me_harder +EXPORT_SYMBOL net/ipv6/ipv6 0xfe77ec94 xfrm6_rcv +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x04422d6d ipv6_find_hdr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x68a87c81 ip6t_do_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xacf479da ip6t_unregister_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xb8bddf33 ip6t_ext_hdr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xfc69ee9e ip6t_register_table +EXPORT_SYMBOL net/ipv6/tunnel6 0x432504ac xfrm6_tunnel_deregister +EXPORT_SYMBOL net/ipv6/tunnel6 0x94163be3 xfrm6_tunnel_register +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0x9cd013f2 xfrm6_tunnel_alloc_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xab14e193 xfrm6_tunnel_free_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xdb1b42d1 xfrm6_tunnel_spi_lookup +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x2de863f2 ircomm_disconnect_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x2f84df35 ircomm_data_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x3666443b ircomm_connect_response +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x510eabce ircomm_open +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x6f0c82ba ircomm_connect_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x95afc0a3 ircomm_close +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xa33b9ed7 ircomm_flow_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xe2421fcf ircomm_control_request +EXPORT_SYMBOL net/irda/irda 0x01d1fcdb hashbin_delete +EXPORT_SYMBOL net/irda/irda 0x0334c03a irda_device_set_media_busy +EXPORT_SYMBOL net/irda/irda 0x06a3ee58 irias_new_integer_value +EXPORT_SYMBOL net/irda/irda 0x072e026f irias_add_octseq_attrib +EXPORT_SYMBOL net/irda/irda 0x07d3647c irlmp_register_service +EXPORT_SYMBOL net/irda/irda 0x08cb54d1 irlmp_close_lsap +EXPORT_SYMBOL net/irda/irda 0x1f3a732a irda_notify_init +EXPORT_SYMBOL net/irda/irda 0x2036ad06 irda_param_insert +EXPORT_SYMBOL net/irda/irda 0x3462950f hashbin_remove +EXPORT_SYMBOL net/irda/irda 0x38a20e5b irda_debug +EXPORT_SYMBOL net/irda/irda 0x3ebce7d8 irlap_open +EXPORT_SYMBOL net/irda/irda 0x448b8aaa irda_qos_bits_to_value +EXPORT_SYMBOL net/irda/irda 0x44ec3c2b irttp_flow_request +EXPORT_SYMBOL net/irda/irda 0x458badbd irttp_udata_request +EXPORT_SYMBOL net/irda/irda 0x4695fd77 irlmp_connect_request +EXPORT_SYMBOL net/irda/irda 0x46c1c4a2 irlmp_unregister_service +EXPORT_SYMBOL net/irda/irda 0x4d85a640 proc_irda +EXPORT_SYMBOL net/irda/irda 0x539dfd7a irlmp_open_lsap +EXPORT_SYMBOL net/irda/irda 0x5e2b1ce5 irttp_connect_request +EXPORT_SYMBOL net/irda/irda 0x6758f8ac irias_new_object +EXPORT_SYMBOL net/irda/irda 0x68b7447c hashbin_find +EXPORT_SYMBOL net/irda/irda 0x6b043eba irda_init_max_qos_capabilies +EXPORT_SYMBOL net/irda/irda 0x6f0e4128 irlmp_data_request +EXPORT_SYMBOL net/irda/irda 0x7042bc54 irlmp_register_client +EXPORT_SYMBOL net/irda/irda 0x747d6779 irias_delete_object +EXPORT_SYMBOL net/irda/irda 0x7621e908 hashbin_insert +EXPORT_SYMBOL net/irda/irda 0x76243bc9 irias_insert_object +EXPORT_SYMBOL net/irda/irda 0x763e54a4 irlmp_unregister_client +EXPORT_SYMBOL net/irda/irda 0x7707ec08 iriap_open +EXPORT_SYMBOL net/irda/irda 0x781e2db5 irias_find_object +EXPORT_SYMBOL net/irda/irda 0x7957f728 irlmp_update_client +EXPORT_SYMBOL net/irda/irda 0x7a57b6f3 hashbin_remove_this +EXPORT_SYMBOL net/irda/irda 0x84a6d9aa irttp_connect_response +EXPORT_SYMBOL net/irda/irda 0x8b8ba349 irttp_open_tsap +EXPORT_SYMBOL net/irda/irda 0x8dd8b274 async_unwrap_char +EXPORT_SYMBOL net/irda/irda 0x91815586 irda_param_pack +EXPORT_SYMBOL net/irda/irda 0x993ad14b irda_param_extract_all +EXPORT_SYMBOL net/irda/irda 0x9b1ffcaa irttp_dup +EXPORT_SYMBOL net/irda/irda 0xa16c4bcf irttp_close_tsap +EXPORT_SYMBOL net/irda/irda 0xb12c6740 async_wrap_skb +EXPORT_SYMBOL net/irda/irda 0xb220db6f irlap_close +EXPORT_SYMBOL net/irda/irda 0xb2bae28c irttp_data_request +EXPORT_SYMBOL net/irda/irda 0xb9394173 irias_delete_value +EXPORT_SYMBOL net/irda/irda 0xbb8d952d alloc_irdadev +EXPORT_SYMBOL net/irda/irda 0xbcd3ef13 irias_object_change_attribute +EXPORT_SYMBOL net/irda/irda 0xbe40ace9 irlmp_discovery_request +EXPORT_SYMBOL net/irda/irda 0xc14e9b6a hashbin_get_next +EXPORT_SYMBOL net/irda/irda 0xc14eec71 irttp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0xcd41236c hashbin_new +EXPORT_SYMBOL net/irda/irda 0xcd6ab48a iriap_getvaluebyclass_request +EXPORT_SYMBOL net/irda/irda 0xcf4af06f irlmp_connect_response +EXPORT_SYMBOL net/irda/irda 0xd6deeaae irda_setup_dma +EXPORT_SYMBOL net/irda/irda 0xd7172ff4 hashbin_get_first +EXPORT_SYMBOL net/irda/irda 0xd8bfb6d4 hashbin_lock_find +EXPORT_SYMBOL net/irda/irda 0xde4c6b3c irlmp_service_to_hint +EXPORT_SYMBOL net/irda/irda 0xe5260e0e irias_add_integer_attrib +EXPORT_SYMBOL net/irda/irda 0xe70adc2d iriap_close +EXPORT_SYMBOL net/irda/irda 0xe7ba2751 irlmp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0xec41fe7f irias_add_string_attrib +EXPORT_SYMBOL net/irda/irda 0xedd521c2 irlmp_get_discoveries +EXPORT_SYMBOL net/lapb/lapb 0x2d4767c8 lapb_data_request +EXPORT_SYMBOL net/lapb/lapb 0x2eeeefde lapb_getparms +EXPORT_SYMBOL net/lapb/lapb 0x70e084ba lapb_data_received +EXPORT_SYMBOL net/lapb/lapb 0x78477bc9 lapb_connect_request +EXPORT_SYMBOL net/lapb/lapb 0xbe40e364 lapb_register +EXPORT_SYMBOL net/lapb/lapb 0xe7bc73fc lapb_unregister +EXPORT_SYMBOL net/lapb/lapb 0xf8c3332c lapb_setparms +EXPORT_SYMBOL net/lapb/lapb 0xf8c86fd2 lapb_disconnect_request +EXPORT_SYMBOL net/mac80211/mac80211 0x00452d50 ieee80211_ctstoself_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x004abb17 ieee80211_tx_status +EXPORT_SYMBOL net/mac80211/mac80211 0x03bce564 ieee80211_rate_control_register +EXPORT_SYMBOL net/mac80211/mac80211 0x0bb71f5e ieee80211_beacon_get +EXPORT_SYMBOL net/mac80211/mac80211 0x1307e3b6 ieee80211_scan_completed +EXPORT_SYMBOL net/mac80211/mac80211 0x15695f34 ieee80211_rts_get +EXPORT_SYMBOL net/mac80211/mac80211 0x47759f0e sta_info_get +EXPORT_SYMBOL net/mac80211/mac80211 0x49ef338b ieee80211_get_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x4bcaea71 ieee80211_rate_control_unregister +EXPORT_SYMBOL net/mac80211/mac80211 0x504bfe0e ieee80211_stop_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x58078c4e ieee80211_start_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0x592686e4 ieee80211_wake_queue +EXPORT_SYMBOL net/mac80211/mac80211 0x5e7c8e69 ieee80211_register_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x5f2783a8 ieee80211_start_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x74df2be4 __ieee80211_get_rx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x751e9038 __ieee80211_get_radio_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x7da28cc3 ieee80211_stop_queue +EXPORT_SYMBOL net/mac80211/mac80211 0x84c61139 ieee80211_stop_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x8969b028 __ieee80211_rx +EXPORT_SYMBOL net/mac80211/mac80211 0x8a70fe93 ieee80211_start_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0x8a7fe0d3 ieee80211_tx_status_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x8c35d732 ieee80211_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x8e8e3ae5 ieee80211_generic_frame_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x977d1eb0 ieee80211_wake_queues +EXPORT_SYMBOL net/mac80211/mac80211 0x99ee6e0b __ieee80211_get_assoc_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0xabf999cf ieee80211_rts_duration +EXPORT_SYMBOL net/mac80211/mac80211 0xb36c0eb3 ieee80211_notify_mac +EXPORT_SYMBOL net/mac80211/mac80211 0xba885b66 ieee80211_ctstoself_get +EXPORT_SYMBOL net/mac80211/mac80211 0xbc85ff53 ieee80211_free_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xcf9a5657 ieee80211_alloc_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xd6e27fcc __ieee80211_get_tx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0xd8074325 ieee80211_get_tkip_key +EXPORT_SYMBOL net/mac80211/mac80211 0xda482b03 ieee80211_get_hdrlen_from_skb +EXPORT_SYMBOL net/mac80211/mac80211 0xe4d11c56 ieee80211_stop_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0xe5b6ba63 ieee80211_rx_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0xe5e4bfd4 ieee80211_unregister_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xfb1060f1 ieee80211_get_buffered_bc +EXPORT_SYMBOL net/mac80211/mac80211 0xff0bd204 ieee80211_stop_queues +EXPORT_SYMBOL net/netfilter/nf_conntrack 0x8fb4ee7a __nf_ct_ext_destroy +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xe372c1b6 __nf_ct_ext_add +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xed23741c per_cpu__nf_conntrack_stat +EXPORT_SYMBOL net/netfilter/nf_conntrack_proto_gre 0x82f94e40 nf_ct_gre_keymap_flush +EXPORT_SYMBOL net/netfilter/x_tables 0x0697ed58 xt_find_match +EXPORT_SYMBOL net/netfilter/x_tables 0x180700f6 xt_register_target +EXPORT_SYMBOL net/netfilter/x_tables 0x3dcd58c5 xt_alloc_table_info +EXPORT_SYMBOL net/netfilter/x_tables 0x3eeedb0d xt_register_targets +EXPORT_SYMBOL net/netfilter/x_tables 0x647be03c xt_register_matches +EXPORT_SYMBOL net/netfilter/x_tables 0xaeb88683 xt_register_match +EXPORT_SYMBOL net/netfilter/x_tables 0xc030a177 xt_unregister_match +EXPORT_SYMBOL net/netfilter/x_tables 0xd5d948c8 xt_unregister_targets +EXPORT_SYMBOL net/netfilter/x_tables 0xe5c5a7f5 xt_unregister_matches +EXPORT_SYMBOL net/netfilter/x_tables 0xf1ba52a3 xt_find_target +EXPORT_SYMBOL net/netfilter/x_tables 0xf7037dc6 xt_free_table_info +EXPORT_SYMBOL net/netfilter/x_tables 0xfec2ff5c xt_unregister_target +EXPORT_SYMBOL net/rfkill/rfkill 0x00caa4dc rfkill_switch_all +EXPORT_SYMBOL net/rfkill/rfkill 0x06fd7395 rfkill_force_state +EXPORT_SYMBOL net/rfkill/rfkill 0x382b61b2 rfkill_register +EXPORT_SYMBOL net/rfkill/rfkill 0x4fa781e3 rfkill_free +EXPORT_SYMBOL net/rfkill/rfkill 0x8002093b rfkill_allocate +EXPORT_SYMBOL net/rfkill/rfkill 0xeee38826 rfkill_unregister +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x0de22655 rxrpc_kernel_abort_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x11f186df rxrpc_kernel_reject_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x133f137d rxrpc_kernel_accept_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x1d156851 rxrpc_kernel_begin_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x22311b80 rxrpc_kernel_intercept_rx_messages +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x223501be rxrpc_kernel_data_delivered +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x240e7910 rxrpc_get_null_key +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x330de65d rxrpc_kernel_end_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x525baaa8 rxrpc_kernel_send_data +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x620ef1a6 rxrpc_kernel_is_data_last +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x7fde29c7 rxrpc_kernel_get_error_number +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x9c804eb1 rxrpc_kernel_free_skb +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xbf659992 key_type_rxrpc +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xdac1e45b rxrpc_kernel_get_abort_code +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xe1fd4df3 rxrpc_get_server_data_key +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x00c52ef5 g_make_token_header +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x0eaaf5d4 gss_mech_unregister +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x1e4da796 gss_mech_register +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x3deb76a1 svcauth_gss_flavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x5eeb53ea gss_mech_put +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x620b1118 gss_service_to_auth_domain_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x8d1a827e svcauth_gss_register_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x96e1ca38 gss_mech_get_by_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xa89b045b gss_pseudoflavor_to_service +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xb5dea7ef g_token_size +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xbf904404 gss_mech_get +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xc92b6fee gss_mech_get_by_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xf881d82b gss_svc_to_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xf8b2ff6e g_verify_token_header +EXPORT_SYMBOL net/sunrpc/sunrpc 0x05e59b2b cache_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0x05e807a9 xdr_encode_string +EXPORT_SYMBOL net/sunrpc/sunrpc 0x065994f1 xdr_encode_opaque_fixed +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0748feb1 auth_domain_put +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0f668ba9 svc_auth_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x12e280e3 svc_proc_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x14ef0b6b rpc_queue_upcall +EXPORT_SYMBOL net/sunrpc/sunrpc 0x1c827e04 xdr_process_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x1deb8967 svc_proc_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0x1e6d92b9 auth_unix_add_addr +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2373a466 svc_create_pooled +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2919b156 xdr_decode_string_inplace +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2d56ffa9 svc_reserve +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2eec63c9 xdr_encode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0x321afa90 xdr_reserve_space +EXPORT_SYMBOL net/sunrpc/sunrpc 0x328cc772 svc_seq_show +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3651592b xdr_init_encode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x37ea451e cache_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3a070b18 xdr_write_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x42545e3b svc_create +EXPORT_SYMBOL net/sunrpc/sunrpc 0x454ee0f4 xdr_inline_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x45ea556c xdr_read_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x4ad8640b cache_check +EXPORT_SYMBOL net/sunrpc/sunrpc 0x4adf1731 xdr_inline_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x51cc7e05 xdr_encode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0x536b9707 svc_process +EXPORT_SYMBOL net/sunrpc/sunrpc 0x536f64bb svc_sock_update_bufs +EXPORT_SYMBOL net/sunrpc/sunrpc 0x538aaa14 svc_sock_names +EXPORT_SYMBOL net/sunrpc/sunrpc 0x548a4937 cache_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5fd34f0f auth_unix_forget_old +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6509be92 svc_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6762a624 rpc_unlink +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6dbef246 svc_wake_up +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6eea229d svcauth_unix_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0x710d0314 xdr_encode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0x71fa908a cache_flush +EXPORT_SYMBOL net/sunrpc/sunrpc 0x74bc1755 auth_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0x751f30fc svc_exit_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0x77961efe svc_auth_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0x853a0757 auth_domain_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8d6b1ac1 xdr_buf_subsegment +EXPORT_SYMBOL net/sunrpc/sunrpc 0x92bccb27 sunrpc_cache_update +EXPORT_SYMBOL net/sunrpc/sunrpc 0x99aae824 xdr_shift_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9cb0c7b0 read_bytes_from_xdr_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9dd2e85a unix_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0xa09cbd72 xdr_encode_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0xa29fba0b xdr_buf_read_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0xabe4abaf auth_unix_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0xadc8cf58 xdr_buf_from_iov +EXPORT_SYMBOL net/sunrpc/sunrpc 0xaea52881 xdr_decode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0xb481e258 svc_drop +EXPORT_SYMBOL net/sunrpc/sunrpc 0xb70f746b xdr_init_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0xbbbbb32e svc_recv +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc2ffa516 svc_set_num_threads +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc3880471 xdr_decode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc8e96dea qword_addhex +EXPORT_SYMBOL net/sunrpc/sunrpc 0xcb42d3a5 rpc_mkpipe +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd86be5e6 svc_prepare_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0xda1734a7 svc_authenticate +EXPORT_SYMBOL net/sunrpc/sunrpc 0xdfef41c3 svc_destroy +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe5919cb1 xdr_encode_opaque +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe97f4ce5 qword_get +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe98a1caa svcauth_unix_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0xedcf6be4 qword_add +EXPORT_SYMBOL net/sunrpc/sunrpc 0xef2c3894 xdr_decode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0xf4c9da93 xdr_enter_page +EXPORT_SYMBOL net/sunrpc/sunrpc 0xf68b0c5d sunrpc_cache_lookup +EXPORT_SYMBOL net/tipc/tipc 0x08acf310 tipc_available_nodes +EXPORT_SYMBOL net/tipc/tipc 0x10d40fcd tipc_isconnected +EXPORT_SYMBOL net/tipc/tipc 0x1472b270 tipc_disconnect +EXPORT_SYMBOL net/tipc/tipc 0x1479cb03 tipc_deleteport +EXPORT_SYMBOL net/tipc/tipc 0x15b5ecde tipc_set_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x16f27683 tipc_block_bearer +EXPORT_SYMBOL net/tipc/tipc 0x1f6dd40e tipc_forward_buf2port +EXPORT_SYMBOL net/tipc/tipc 0x259b74f9 tipc_acknowledge +EXPORT_SYMBOL net/tipc/tipc 0x27d8bb58 tipc_send2port +EXPORT_SYMBOL net/tipc/tipc 0x310d1bc9 tipc_detach +EXPORT_SYMBOL net/tipc/tipc 0x3712e340 tipc_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x3976041f tipc_set_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x4b2243c6 tipc_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x4ba3cfc8 tipc_send2name +EXPORT_SYMBOL net/tipc/tipc 0x538b228a tipc_withdraw +EXPORT_SYMBOL net/tipc/tipc 0x5637ed44 tipc_get_mode +EXPORT_SYMBOL net/tipc/tipc 0x56e52bc1 tipc_continue +EXPORT_SYMBOL net/tipc/tipc 0x5c0d4b5c tipc_ref_valid +EXPORT_SYMBOL net/tipc/tipc 0x5d2c312e tipc_send_buf2name +EXPORT_SYMBOL net/tipc/tipc 0x62a681a3 tipc_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0x64357d3c tipc_multicast +EXPORT_SYMBOL net/tipc/tipc 0x763a46e8 tipc_register_media +EXPORT_SYMBOL net/tipc/tipc 0x8001e3d7 tipc_forward2port +EXPORT_SYMBOL net/tipc/tipc 0x83dea151 tipc_createport_raw +EXPORT_SYMBOL net/tipc/tipc 0x869b781f tipc_recv_msg +EXPORT_SYMBOL net/tipc/tipc 0x88b73627 tipc_get_addr +EXPORT_SYMBOL net/tipc/tipc 0x9c45558e tipc_enable_bearer +EXPORT_SYMBOL net/tipc/tipc 0xa8509fe7 tipc_reject_msg +EXPORT_SYMBOL net/tipc/tipc 0xa936a24b tipc_get_port +EXPORT_SYMBOL net/tipc/tipc 0xadd203d0 tipc_connect2port +EXPORT_SYMBOL net/tipc/tipc 0xae0103c3 tipc_shutdown +EXPORT_SYMBOL net/tipc/tipc 0xb01ffc2c tipc_forward2name +EXPORT_SYMBOL net/tipc/tipc 0xb35b672c tipc_publish +EXPORT_SYMBOL net/tipc/tipc 0xb8e3a3b1 tipc_send_buf2port +EXPORT_SYMBOL net/tipc/tipc 0xb93cab15 tipc_send_buf +EXPORT_SYMBOL net/tipc/tipc 0xbb2b2504 tipc_send +EXPORT_SYMBOL net/tipc/tipc 0xbf568a9d tipc_createport +EXPORT_SYMBOL net/tipc/tipc 0xcc7bb70c tipc_send_buf_fast +EXPORT_SYMBOL net/tipc/tipc 0xcec8514a tipc_set_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0xd44731e5 tipc_ownidentity +EXPORT_SYMBOL net/tipc/tipc 0xda7f9d3f tipc_attach +EXPORT_SYMBOL net/tipc/tipc 0xdf5008fc tipc_peer +EXPORT_SYMBOL net/tipc/tipc 0xdff21acd tipc_forward_buf2name +EXPORT_SYMBOL net/tipc/tipc 0xe7aece47 tipc_ispublished +EXPORT_SYMBOL net/tipc/tipc 0xeefd49b3 tipc_get_handle +EXPORT_SYMBOL net/tipc/tipc 0xef50a1ef tipc_disable_bearer +EXPORT_SYMBOL net/wanrouter/wanrouter 0x0ebe03d1 unregister_wan_device +EXPORT_SYMBOL net/wanrouter/wanrouter 0xb5560b84 register_wan_device +EXPORT_SYMBOL net/wireless/cfg80211 0x05c05ffa wiphy_new +EXPORT_SYMBOL net/wireless/cfg80211 0x07e7ac5a ieee80211_radiotap_iterator_init +EXPORT_SYMBOL net/wireless/cfg80211 0x09c64fbd ieee80211_frequency_to_channel +EXPORT_SYMBOL net/wireless/cfg80211 0x5397d03e __ieee80211_get_channel +EXPORT_SYMBOL net/wireless/cfg80211 0x5c292037 wiphy_register +EXPORT_SYMBOL net/wireless/cfg80211 0xa8e1607b wiphy_free +EXPORT_SYMBOL net/wireless/cfg80211 0xc4e85ec5 ieee80211_radiotap_iterator_next +EXPORT_SYMBOL net/wireless/cfg80211 0xccc291b3 ieee80211_channel_to_frequency +EXPORT_SYMBOL net/wireless/cfg80211 0xd67900ca wiphy_unregister +EXPORT_SYMBOL sound/ac97_bus 0xb65a27a1 ac97_bus_type +EXPORT_SYMBOL sound/core/oss/snd-mixer-oss 0xbfea2026 snd_mixer_oss_ioctl_card +EXPORT_SYMBOL sound/core/seq/snd-seq 0x1a724fcc snd_seq_kernel_client_ctl +EXPORT_SYMBOL sound/core/seq/snd-seq 0x22f94577 snd_seq_event_port_attach +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3061c52d snd_use_lock_sync_helper +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3fb4d161 snd_seq_kernel_client_dispatch +EXPORT_SYMBOL sound/core/seq/snd-seq 0x4063fb5d snd_seq_kernel_client_write_poll +EXPORT_SYMBOL sound/core/seq/snd-seq 0x6bb71038 snd_seq_delete_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7ac2f329 snd_seq_expand_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7b8699eb snd_seq_event_port_detach +EXPORT_SYMBOL sound/core/seq/snd-seq 0x970ddfc1 snd_seq_kernel_client_enqueue_blocking +EXPORT_SYMBOL sound/core/seq/snd-seq 0xb8e448a0 snd_seq_set_queue_tempo +EXPORT_SYMBOL sound/core/seq/snd-seq 0xcac0a3be snd_seq_kernel_client_enqueue +EXPORT_SYMBOL sound/core/seq/snd-seq 0xe934da1d snd_seq_dump_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq 0xf7685acd snd_seq_create_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x1f20a9ae snd_seq_device_new +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x3a57f235 snd_seq_autoload_unlock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x6339b6d0 snd_seq_device_load_drivers +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x823a701b snd_seq_device_register_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xb90668b2 snd_seq_autoload_lock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xc622fb29 snd_seq_device_unregister_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x6ea09972 snd_midi_channel_alloc_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x833a3e07 snd_midi_channel_set_clear +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xb9948d2c snd_midi_channel_free_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xf0a1fdb3 snd_midi_process_event +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x17c15809 snd_midi_event_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x4ad3f518 snd_midi_event_reset_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x62384d3a snd_midi_event_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x8a348811 snd_midi_event_reset_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x9df7af8b snd_midi_event_free +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xc482499d snd_midi_event_new +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xd9072e1a snd_midi_event_no_status +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xe6df29c7 snd_midi_event_encode_byte +EXPORT_SYMBOL sound/core/seq/snd-seq-virmidi 0x7365b60b snd_virmidi_new +EXPORT_SYMBOL sound/core/snd 0x0339a77c snd_device_register +EXPORT_SYMBOL sound/core/snd 0x0431bdea snd_component_add +EXPORT_SYMBOL sound/core/snd 0x05afad4d snd_ctl_remove +EXPORT_SYMBOL sound/core/snd 0x0d17f0fd snd_power_wait +EXPORT_SYMBOL sound/core/snd 0x0ea40646 snd_card_register +EXPORT_SYMBOL sound/core/snd 0x18e1683f snd_dma_program +EXPORT_SYMBOL sound/core/snd 0x191e88cf snd_dma_pointer +EXPORT_SYMBOL sound/core/snd 0x198788b4 snd_lookup_oss_minor_data +EXPORT_SYMBOL sound/core/snd 0x1b558db2 snd_card_proc_new +EXPORT_SYMBOL sound/core/snd 0x1c6b3ed5 snd_info_create_card_entry +EXPORT_SYMBOL sound/core/snd 0x24a94b26 snd_info_get_line +EXPORT_SYMBOL sound/core/snd 0x3050d3cb snd_ctl_unregister_ioctl +EXPORT_SYMBOL sound/core/snd 0x3530ead3 snd_info_create_module_entry +EXPORT_SYMBOL sound/core/snd 0x376e04bf release_and_free_resource +EXPORT_SYMBOL sound/core/snd 0x3971b4df snd_ecards_limit +EXPORT_SYMBOL sound/core/snd 0x3b2c95cc snd_card_free +EXPORT_SYMBOL sound/core/snd 0x468c1ebc snd_seq_root +EXPORT_SYMBOL sound/core/snd 0x47d5265d snd_ctl_register_ioctl +EXPORT_SYMBOL sound/core/snd 0x4a3ea5c0 snd_request_card +EXPORT_SYMBOL sound/core/snd 0x4b8fbb47 snd_ctl_make_virtual_master +EXPORT_SYMBOL sound/core/snd 0x4bfd7a70 snd_register_oss_device +EXPORT_SYMBOL sound/core/snd 0x4fd78a46 snd_ctl_rename_id +EXPORT_SYMBOL sound/core/snd 0x552cf4d5 snd_ctl_add_slave +EXPORT_SYMBOL sound/core/snd 0x5f6a06fe snd_card_disconnect +EXPORT_SYMBOL sound/core/snd 0x602c96f0 copy_to_user_fromio +EXPORT_SYMBOL sound/core/snd 0x6839b787 snd_unregister_device +EXPORT_SYMBOL sound/core/snd 0x6af3cae7 snd_ctl_notify +EXPORT_SYMBOL sound/core/snd 0x6c0597a8 snd_card_file_add +EXPORT_SYMBOL sound/core/snd 0x6dc40ee6 snd_device_new +EXPORT_SYMBOL sound/core/snd 0x6f9288b9 snd_card_file_remove +EXPORT_SYMBOL sound/core/snd 0x7086351a snd_ctl_remove_id +EXPORT_SYMBOL sound/core/snd 0x70c15ac1 snd_dma_disable +EXPORT_SYMBOL sound/core/snd 0x723e993a snd_ctl_add +EXPORT_SYMBOL sound/core/snd 0x7e627ea3 snd_ctl_boolean_stereo_info +EXPORT_SYMBOL sound/core/snd 0x85460ab9 snd_card_new +EXPORT_SYMBOL sound/core/snd 0x886a59f2 snd_ctl_free_one +EXPORT_SYMBOL sound/core/snd 0x88b16e6f snd_card_free_when_closed +EXPORT_SYMBOL sound/core/snd 0x8dcbe7d3 snd_info_free_entry +EXPORT_SYMBOL sound/core/snd 0x8df3789f snd_oss_info_register +EXPORT_SYMBOL sound/core/snd 0x8f595b11 snd_major +EXPORT_SYMBOL sound/core/snd 0xa601d24e snd_device_free +EXPORT_SYMBOL sound/core/snd 0xb213fe8b snd_info_get_str +EXPORT_SYMBOL sound/core/snd 0xb226956d snd_pci_quirk_lookup +EXPORT_SYMBOL sound/core/snd 0xb22b7129 snd_mixer_oss_notify_callback +EXPORT_SYMBOL sound/core/snd 0xb2e5ae4a snd_lookup_minor_data +EXPORT_SYMBOL sound/core/snd 0xb3861d73 snd_ctl_boolean_mono_info +EXPORT_SYMBOL sound/core/snd 0xbb0856c4 snd_register_device_for_dev +EXPORT_SYMBOL sound/core/snd 0xc2ec97c0 snd_cards +EXPORT_SYMBOL sound/core/snd 0xcd1fc7ec snd_unregister_oss_device +EXPORT_SYMBOL sound/core/snd 0xce3ca308 copy_from_user_toio +EXPORT_SYMBOL sound/core/snd 0xd4e51128 snd_add_device_sysfs_file +EXPORT_SYMBOL sound/core/snd 0xd5470247 snd_ctl_find_numid +EXPORT_SYMBOL sound/core/snd 0xdec4a971 snd_ctl_new1 +EXPORT_SYMBOL sound/core/snd 0xe4854cea snd_iprintf +EXPORT_SYMBOL sound/core/snd 0xf1f9a019 snd_info_register +EXPORT_SYMBOL sound/core/snd 0xf339af23 snd_ctl_find_id +EXPORT_SYMBOL sound/core/snd-hwdep 0x9708744c snd_hwdep_new +EXPORT_SYMBOL sound/core/snd-page-alloc 0x16c34e9a snd_dma_reserve_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x346e1919 snd_dma_alloc_pages_fallback +EXPORT_SYMBOL sound/core/snd-page-alloc 0x3b91f3af snd_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x668992a5 snd_dma_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x79676aa9 snd_dma_get_reserved_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0xade88e76 snd_malloc_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0xf676ccd2 snd_dma_alloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x02e81e49 snd_pcm_kernel_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x04cda566 snd_interval_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x0715321f snd_pcm_hw_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x07b596d0 snd_pcm_hw_constraint_ratdens +EXPORT_SYMBOL sound/core/snd-pcm 0x0b97e6fb snd_pcm_lib_free_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x0d34e2d3 snd_pcm_period_elapsed +EXPORT_SYMBOL sound/core/snd-pcm 0x119d7189 snd_pcm_lib_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x1519aa4f snd_pcm_hw_constraint_list +EXPORT_SYMBOL sound/core/snd-pcm 0x1a952539 snd_pcm_lib_mmap_iomem +EXPORT_SYMBOL sound/core/snd-pcm 0x1d027e4b snd_pcm_format_signed +EXPORT_SYMBOL sound/core/snd-pcm 0x1e5f63ed snd_pcm_suspend +EXPORT_SYMBOL sound/core/snd-pcm 0x3796bdcc snd_pcm_format_little_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x3b48766b snd_pcm_lib_write +EXPORT_SYMBOL sound/core/snd-pcm 0x3c58c98b snd_pcm_release_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x46127251 snd_pcm_limit_hw_rates +EXPORT_SYMBOL sound/core/snd-pcm 0x48258e30 snd_pcm_notify +EXPORT_SYMBOL sound/core/snd-pcm 0x498f8c6c snd_pcm_lib_preallocate_pages_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x4b0bdca8 snd_pcm_hw_constraint_step +EXPORT_SYMBOL sound/core/snd-pcm 0x4d9b6d35 snd_pcm_format_size +EXPORT_SYMBOL sound/core/snd-pcm 0x4f816e9b snd_pcm_format_big_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x5621b6ae snd_pcm_set_sync +EXPORT_SYMBOL sound/core/snd-pcm 0x5ad7cd01 snd_pcm_new +EXPORT_SYMBOL sound/core/snd-pcm 0x5e7f4920 snd_pcm_format_set_silence +EXPORT_SYMBOL sound/core/snd-pcm 0x5f4bd26d snd_pcm_sgbuf_ops_page +EXPORT_SYMBOL sound/core/snd-pcm 0x63ffc1c3 snd_pcm_hw_constraint_ratnums +EXPORT_SYMBOL sound/core/snd-pcm 0x650f8603 snd_pcm_format_silence_64 +EXPORT_SYMBOL sound/core/snd-pcm 0x67d42cdd snd_pcm_lib_writev +EXPORT_SYMBOL sound/core/snd-pcm 0x68a24153 snd_pcm_format_physical_width +EXPORT_SYMBOL sound/core/snd-pcm 0x6d9d64b4 snd_pcm_hw_rule_add +EXPORT_SYMBOL sound/core/snd-pcm 0x6e9cfbb4 snd_pcm_open_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x6ef8fcd8 snd_pcm_format_linear +EXPORT_SYMBOL sound/core/snd-pcm 0x7499b48d snd_pcm_hw_constraint_pow2 +EXPORT_SYMBOL sound/core/snd-pcm 0x7c5cec98 _snd_pcm_hw_params_any +EXPORT_SYMBOL sound/core/snd-pcm 0x7cbc1a78 snd_pcm_lib_read +EXPORT_SYMBOL sound/core/snd-pcm 0x82a6ae22 snd_pcm_suspend_all +EXPORT_SYMBOL sound/core/snd-pcm 0x88cc66cc snd_pcm_link_rwlock +EXPORT_SYMBOL sound/core/snd-pcm 0x89a31a56 _snd_pcm_hw_param_setempty +EXPORT_SYMBOL sound/core/snd-pcm 0x9bcf746c snd_pcm_hw_constraint_msbits +EXPORT_SYMBOL sound/core/snd-pcm 0x9fdea959 snd_pcm_hw_param_value +EXPORT_SYMBOL sound/core/snd-pcm 0x9ff62d54 snd_pcm_hw_constraint_integer +EXPORT_SYMBOL sound/core/snd-pcm 0xa61aa028 snd_pcm_format_unsigned +EXPORT_SYMBOL sound/core/snd-pcm 0xad1d2962 snd_pcm_set_ops +EXPORT_SYMBOL sound/core/snd-pcm 0xb93009d9 snd_pcm_lib_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0xb9638db4 snd_pcm_rate_to_rate_bit +EXPORT_SYMBOL sound/core/snd-pcm 0xc156e049 snd_pcm_hw_param_first +EXPORT_SYMBOL sound/core/snd-pcm 0xc243a105 snd_pcm_lib_preallocate_free_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0xc6887960 snd_pcm_stop +EXPORT_SYMBOL sound/core/snd-pcm 0xd0b9b8b8 snd_interval_list +EXPORT_SYMBOL sound/core/snd-pcm 0xd4619ca1 snd_pcm_hw_constraint_minmax +EXPORT_SYMBOL sound/core/snd-pcm 0xd8b0b923 snd_pcm_hw_param_last +EXPORT_SYMBOL sound/core/snd-pcm 0xdecff01b snd_pcm_lib_preallocate_pages +EXPORT_SYMBOL sound/core/snd-pcm 0xe2ef270d snd_pcm_new_stream +EXPORT_SYMBOL sound/core/snd-pcm 0xe56a9336 snd_pcm_format_width +EXPORT_SYMBOL sound/core/snd-pcm 0xf3797152 snd_interval_ratnum +EXPORT_SYMBOL sound/core/snd-pcm 0xf5b18d2a snd_pcm_mmap_data +EXPORT_SYMBOL sound/core/snd-pcm 0xfe8bdc87 snd_pcm_lib_readv +EXPORT_SYMBOL sound/core/snd-rawmidi 0x072a4929 snd_rawmidi_kernel_read +EXPORT_SYMBOL sound/core/snd-rawmidi 0x1454ce17 snd_rawmidi_kernel_open +EXPORT_SYMBOL sound/core/snd-rawmidi 0x20583371 snd_rawmidi_transmit_empty +EXPORT_SYMBOL sound/core/snd-rawmidi 0x20bde7e8 snd_rawmidi_drain_input +EXPORT_SYMBOL sound/core/snd-rawmidi 0x280f3bfe snd_rawmidi_info_select +EXPORT_SYMBOL sound/core/snd-rawmidi 0x2fd98fad snd_rawmidi_drain_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0x43575623 snd_rawmidi_new +EXPORT_SYMBOL sound/core/snd-rawmidi 0x478e7837 snd_rawmidi_transmit +EXPORT_SYMBOL sound/core/snd-rawmidi 0x57fef475 snd_rawmidi_input_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0x7ed7d58b snd_rawmidi_receive +EXPORT_SYMBOL sound/core/snd-rawmidi 0x935e7545 snd_rawmidi_drop_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0xac49f2cb snd_rawmidi_set_ops +EXPORT_SYMBOL sound/core/snd-rawmidi 0xd780484b snd_rawmidi_kernel_write +EXPORT_SYMBOL sound/core/snd-rawmidi 0xe3a85b0b snd_rawmidi_output_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0xf4244725 snd_rawmidi_transmit_ack +EXPORT_SYMBOL sound/core/snd-rawmidi 0xfc032e34 snd_rawmidi_kernel_release +EXPORT_SYMBOL sound/core/snd-rawmidi 0xfc41825b snd_rawmidi_transmit_peek +EXPORT_SYMBOL sound/core/snd-timer 0x0582823b snd_timer_pause +EXPORT_SYMBOL sound/core/snd-timer 0x5a253aaf snd_timer_start +EXPORT_SYMBOL sound/core/snd-timer 0x76d65588 snd_timer_global_new +EXPORT_SYMBOL sound/core/snd-timer 0x788df822 snd_timer_stop +EXPORT_SYMBOL sound/core/snd-timer 0x803cd902 snd_timer_global_register +EXPORT_SYMBOL sound/core/snd-timer 0x8accd15c snd_timer_open +EXPORT_SYMBOL sound/core/snd-timer 0x90f5a63d snd_timer_notify +EXPORT_SYMBOL sound/core/snd-timer 0xb4b355c1 snd_timer_resolution +EXPORT_SYMBOL sound/core/snd-timer 0xb7f515b9 snd_timer_continue +EXPORT_SYMBOL sound/core/snd-timer 0xcd2c3ccd snd_timer_interrupt +EXPORT_SYMBOL sound/core/snd-timer 0xeade7880 snd_timer_global_free +EXPORT_SYMBOL sound/core/snd-timer 0xf455979f snd_timer_new +EXPORT_SYMBOL sound/core/snd-timer 0xfe585e63 snd_timer_close +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x5854d923 snd_mpu401_uart_new +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x73c4c993 snd_mpu401_uart_interrupt_tx +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xfe618b58 snd_mpu401_uart_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x05060a19 snd_opl3_regmap +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x109a7fa9 snd_opl3_init +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x16f53424 snd_opl3_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x20b5a623 snd_opl3_timer_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x2ab23858 snd_opl3_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x2d536ed5 snd_opl3_reset +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x328663c9 snd_opl3_create +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x40a1969d snd_opl3_find_patch +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xb37fdbbf snd_opl3_hwdep_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xc9628d77 snd_opl3_load_patch +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0x0a5eb1ab snd_opl4_read_memory +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0x2f78577d snd_opl4_write +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0x50e1076c snd_opl4_read +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0xda28d117 snd_opl4_create +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0xe387543c snd_opl4_write_memory +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x0efa15d7 snd_vx_suspend +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x1cadb14b snd_vx_irq_handler +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x24b1276c snd_vx_free_firmware +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x26f7bda8 snd_vx_create +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x3a13feb9 snd_vx_setup_firmware +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x5a1cc882 snd_vx_dsp_load +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x8545d7b5 snd_vx_resume +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xd06c87ae snd_vx_load_boot_image +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xe7c91d82 snd_vx_check_reg_bit +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xea8ffeb6 snd_vx_dsp_boot +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x0fcba403 snd_ak4114_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x1e2db36b snd_ak4114_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x513d9e6e snd_ak4114_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x5f63613a snd_ak4114_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x70119587 snd_ak4114_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x93bdf3ed snd_ak4114_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x0f959e7e snd_ak4117_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x469d995f snd_ak4117_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x6e3f9490 snd_ak4117_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xa9b0f527 snd_ak4117_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xc252cd47 snd_ak4117_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xde7b024f snd_ak4117_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x4e76a156 snd_akm4xxx_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xa2b4e69a snd_akm4xxx_init +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xaeae3b2e snd_akm4xxx_reset +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xc4053dbf snd_akm4xxx_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x07912905 snd_pt2258_reset +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0xe218883a snd_pt2258_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0xa6e833a6 snd_tea575x_exit +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0xefea511a snd_tea575x_init +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x0ba695de snd_cs8427_create +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x2577f80d snd_cs8427_iec958_build +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x913272da snd_cs8427_iec958_active +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xa4bd5c67 snd_cs8427_reg_write +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xd56ff3e5 snd_cs8427_iec958_pcm +EXPORT_SYMBOL sound/i2c/snd-i2c 0x2c1663bd snd_i2c_readbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0x2facca9b snd_i2c_sendbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0x9989058b snd_i2c_probeaddr +EXPORT_SYMBOL sound/i2c/snd-i2c 0xb7a8f1f3 snd_i2c_device_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0xebf79f22 snd_i2c_device_free +EXPORT_SYMBOL sound/i2c/snd-i2c 0xfe4753b8 snd_i2c_bus_create +EXPORT_SYMBOL sound/i2c/snd-tea6330t 0x1cea74ea snd_tea6330t_update_mixer +EXPORT_SYMBOL sound/i2c/snd-tea6330t 0xa79a972d snd_tea6330t_detect +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0x13cb0ae3 snd_ad1848_out +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0x28a5230a snd_ad1848_pcm +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0x5f838022 snd_ad1848_mixer +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0x73d603ee snd_ad1848_create +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0x95c39804 snd_ad1848_add_ctl_elem +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0xf9efd1e1 snd_ad1848_get_pcm_ops +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x06f745eb snd_cs4231_mce_down +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x08549ed3 snd_cs4231_out +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x0e73e085 snd_cs4231_mce_up +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x12846a53 snd_cs4231_create +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x28991323 snd_cs4231_timer +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x2f6150e1 snd_cs4231_get_single +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x36efa398 snd_cs4231_overrange +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x44d3980d snd_cs4231_mixer +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x74cddcba snd_cs4236_ext_in +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x777d643a snd_cs4231_get_double +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x8afd6f78 snd_cs4236_ext_out +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xaf311988 snd_cs4231_info_double +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xb0ac3180 snd_cs4231_in +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xb7ecccd3 snd_cs4231_put_single +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xbb38a9aa snd_cs4231_interrupt +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xd3f1ec9a snd_cs4231_pcm +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xdb49d3b5 snd_cs4231_info_single +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xdf609d26 snd_cs4231_chip_id +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xeff0f808 snd_cs4231_put_double +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4236-lib 0x613be950 snd_cs4236_create +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4236-lib 0x85e3816f snd_cs4236_pcm +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4236-lib 0xacb08f3e snd_cs4236_mixer +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0x663b662d snd_es1688_pcm +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0x8f9b5631 snd_es1688_create +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0xa03d46a7 snd_es1688_mixer_write +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0xd7d22dfb snd_es1688_mixer +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x030db040 snd_gf1_pcm_new +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x03b9c317 snd_gf1_i_write8 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x18e27b61 snd_gf1_write_addr +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x38e8313d snd_gf1_poke +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x43da0c01 snd_gf1_look16 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x46db8d67 snd_gf1_lvol_to_gvol_raw +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x476ce67f snd_gf1_stop_voice +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x529c42bc snd_gf1_i_look8 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x58ac85ce snd_gus_use_inc +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x8188f247 snd_gus_initialize +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x8e4cfa55 snd_gf1_i_look16 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x90ea7d75 snd_gus_dram_read +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x96b93c4e snd_gf1_alloc_voice +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x96df572d snd_gf1_rawmidi_new +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xa209dd9d snd_gf1_write16 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xa40a06d7 snd_gf1_peek +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xa504af0c snd_gf1_write8 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xa9fbfa5a snd_gf1_free_voice +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xaa723cd8 snd_gus_create +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xb70c1fa3 snd_gf1_ctrl_stop +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xbcc6f4d8 snd_gf1_delay +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xbec2f74b snd_gf1_new_mixer +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xc31af61d snd_gf1_mem_alloc +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xc43a5527 snd_gf1_atten_table +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xd057820b snd_gf1_dram_addr +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xd85053ba snd_gf1_mem_free +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xdb252880 snd_gf1_mem_xfree +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xdffb67e0 snd_gus_use_dec +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xe57371a9 snd_gf1_translate_freq +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xeca2dd3e snd_gf1_mem_lock +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xf0da270a snd_gus_dram_write +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xf963a997 snd_gus_interrupt +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xfa6136d4 snd_gf1_look8 +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x1e58c1ff snd_sbmixer_read +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x2633ccae snd_sbdsp_command +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x2f038c08 snd_sbdsp_get_byte +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x3fdc1919 snd_sbmixer_resume +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x5fa03025 snd_sbmixer_new +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x7f973533 snd_sbmixer_write +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x8c7ef03b snd_sbdsp_create +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xb76f99ce snd_sbdsp_reset +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xd6dc638f snd_sbmixer_suspend +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xef71df77 snd_sbmixer_add_ctl +EXPORT_SYMBOL sound/isa/sb/snd-sb16-csp 0x3296cb41 snd_sb_csp_new +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x0ba4ef1d snd_sb16dsp_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x5f3c2a45 snd_sb16dsp_get_pcm_ops +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0xb3bef224 snd_sb16dsp_configure +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0xf5f5a582 snd_sb16dsp_pcm +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0x27f92665 snd_sb8dsp_pcm +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0x50ac65cb snd_sb8dsp_midi +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0x747f8b7b snd_sb8dsp_midi_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0xc875dc02 snd_sb8dsp_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x215a3c53 snd_emu8000_peek_dw +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x35c19648 snd_emu8000_dma_chan +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x399a5330 snd_emu8000_poke +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x487f2aff snd_emu8000_load_chorus_fx +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x49658a83 snd_emu8000_load_reverb_fx +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x64b2d34d snd_emu8000_peek +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x7cc75467 snd_emu8000_update_chorus_mode +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x8adfb2c1 snd_emu8000_poke_dw +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xc10ba452 snd_emu8000_update_equalizer +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xd708eb0b snd_emu8000_init_fm +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xe9d8d05b snd_emu8000_update_reverb_mode +EXPORT_SYMBOL sound/oss/ad1848 0x7db48b83 ad1848_init +EXPORT_SYMBOL sound/oss/ad1848 0x7e4087f8 attach_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x9839a618 probe_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x9bf1cc62 ad1848_unload +EXPORT_SYMBOL sound/oss/ad1848 0xb29a9148 unload_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0xc04f6f67 ad1848_control +EXPORT_SYMBOL sound/oss/ad1848 0xf06eb004 ad1848_detect +EXPORT_SYMBOL sound/oss/mpu401 0x19946573 attach_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0x5febf284 unload_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0x8874e39a probe_mpu401 +EXPORT_SYMBOL sound/oss/msnd 0x1186f48f msnd_fifo_read +EXPORT_SYMBOL sound/oss/msnd 0x340a3ddf msnd_init_queue +EXPORT_SYMBOL sound/oss/msnd 0x3867b382 msnd_send_dsp_cmd +EXPORT_SYMBOL sound/oss/msnd 0x54230dc1 msnd_fifo_write +EXPORT_SYMBOL sound/oss/msnd 0x6601493b msnd_fifo_make_empty +EXPORT_SYMBOL sound/oss/msnd 0x8192a440 msnd_register +EXPORT_SYMBOL sound/oss/msnd 0x92098b5b msnd_send_word +EXPORT_SYMBOL sound/oss/msnd 0x9274d677 msnd_fifo_free +EXPORT_SYMBOL sound/oss/msnd 0x986ccb79 msnd_unregister +EXPORT_SYMBOL sound/oss/msnd 0xa0075e9f msnd_enable_irq +EXPORT_SYMBOL sound/oss/msnd 0xade99e25 msnd_fifo_alloc +EXPORT_SYMBOL sound/oss/msnd 0xb3520772 msnd_fifo_init +EXPORT_SYMBOL sound/oss/msnd 0xb46680d3 msnd_upload_host +EXPORT_SYMBOL sound/oss/msnd 0xc266c2da msnd_disable_irq +EXPORT_SYMBOL sound/oss/msnd 0xdf0f59eb msnd_fifo_write_io +EXPORT_SYMBOL sound/oss/msnd 0xf4c4f662 msnd_fifo_read_io +EXPORT_SYMBOL sound/oss/sb_lib 0x04890ef7 sb_dsp_init +EXPORT_SYMBOL sound/oss/sb_lib 0x42424109 sb_be_quiet +EXPORT_SYMBOL sound/oss/sb_lib 0x450f9aea smw_free +EXPORT_SYMBOL sound/oss/sb_lib 0x74afd69c unload_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0xc4884969 sb_dsp_unload +EXPORT_SYMBOL sound/oss/sb_lib 0xcd1f0051 probe_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0xd8a2731c sb_dsp_detect +EXPORT_SYMBOL sound/oss/sound 0x04c87ec8 compute_finetune +EXPORT_SYMBOL sound/oss/sound 0x06339815 sound_unload_synthdev +EXPORT_SYMBOL sound/oss/sound 0x0b080003 sound_install_mixer +EXPORT_SYMBOL sound/oss/sound 0x0f280035 conf_printf +EXPORT_SYMBOL sound/oss/sound 0x17ba231d seq_input_event +EXPORT_SYMBOL sound/oss/sound 0x1b3df3cf sound_alloc_mixerdev +EXPORT_SYMBOL sound/oss/sound 0x1f395686 MIDIbuf_avail +EXPORT_SYMBOL sound/oss/sound 0x2161d5e8 sound_timer_init +EXPORT_SYMBOL sound/oss/sound 0x2aa31695 midi_synth_kill_note +EXPORT_SYMBOL sound/oss/sound 0x394cb088 sound_free_dma +EXPORT_SYMBOL sound/oss/sound 0x418f5fbe sound_close_dma +EXPORT_SYMBOL sound/oss/sound 0x4cd01bdd num_audiodevs +EXPORT_SYMBOL sound/oss/sound 0x4f0e1591 sound_timer_devs +EXPORT_SYMBOL sound/oss/sound 0x4ff47e9d midi_synth_setup_voice +EXPORT_SYMBOL sound/oss/sound 0x51e354b2 sound_alloc_timerdev +EXPORT_SYMBOL sound/oss/sound 0x5569229b mixer_devs +EXPORT_SYMBOL sound/oss/sound 0x56504ca2 midi_synth_reset +EXPORT_SYMBOL sound/oss/sound 0x5d986fc9 note_to_freq +EXPORT_SYMBOL sound/oss/sound 0x7679ee76 seq_copy_to_input +EXPORT_SYMBOL sound/oss/sound 0x7bdf0907 conf_printf2 +EXPORT_SYMBOL sound/oss/sound 0x892093e0 midi_synth_controller +EXPORT_SYMBOL sound/oss/sound 0x8aba7e7e sound_install_audiodrv +EXPORT_SYMBOL sound/oss/sound 0x90bd9714 sequencer_timer +EXPORT_SYMBOL sound/oss/sound 0x987bcf12 DMAbuf_outputintr +EXPORT_SYMBOL sound/oss/sound 0x9a95733f sound_alloc_dma +EXPORT_SYMBOL sound/oss/sound 0x9bdaf24d midi_synth_start_note +EXPORT_SYMBOL sound/oss/sound 0x9d845b18 num_mixers +EXPORT_SYMBOL sound/oss/sound 0xa0d62079 midi_devs +EXPORT_SYMBOL sound/oss/sound 0xa1d5f04f load_mixer_volumes +EXPORT_SYMBOL sound/oss/sound 0xa1eae7cf num_midis +EXPORT_SYMBOL sound/oss/sound 0xa41ead5f sound_unload_timerdev +EXPORT_SYMBOL sound/oss/sound 0xa51c913b sound_unload_mixerdev +EXPORT_SYMBOL sound/oss/sound 0xa6bb414c sound_unload_mididev +EXPORT_SYMBOL sound/oss/sound 0xa948751e sound_unload_audiodev +EXPORT_SYMBOL sound/oss/sound 0xad45df73 midi_synth_close +EXPORT_SYMBOL sound/oss/sound 0xaef743b2 midi_synth_ioctl +EXPORT_SYMBOL sound/oss/sound 0xb14b22cd midi_synth_hw_control +EXPORT_SYMBOL sound/oss/sound 0xb51587f6 do_midi_msg +EXPORT_SYMBOL sound/oss/sound 0xba413f87 sound_alloc_mididev +EXPORT_SYMBOL sound/oss/sound 0xba7dd041 midi_synth_bender +EXPORT_SYMBOL sound/oss/sound 0xc748d109 sound_alloc_synthdev +EXPORT_SYMBOL sound/oss/sound 0xcc4b8797 sound_open_dma +EXPORT_SYMBOL sound/oss/sound 0xd85be938 midi_synth_set_instr +EXPORT_SYMBOL sound/oss/sound 0xd9752104 synth_devs +EXPORT_SYMBOL sound/oss/sound 0xdb400afa midi_synth_panning +EXPORT_SYMBOL sound/oss/sound 0xe056b71c DMAbuf_start_dma +EXPORT_SYMBOL sound/oss/sound 0xe1e207fa audio_devs +EXPORT_SYMBOL sound/oss/sound 0xe2675a79 sound_timer_interrupt +EXPORT_SYMBOL sound/oss/sound 0xeb315d99 DMAbuf_inputintr +EXPORT_SYMBOL sound/oss/sound 0xf1ea8a20 midi_synth_aftertouch +EXPORT_SYMBOL sound/oss/sound 0xf6b3a2fb midi_synth_open +EXPORT_SYMBOL sound/oss/sound 0xf7426da3 midi_synth_load_patch +EXPORT_SYMBOL sound/oss/sound 0xf78f6363 sequencer_init +EXPORT_SYMBOL sound/oss/sound 0xfa6871be sound_timer_syncinterval +EXPORT_SYMBOL sound/oss/sound 0xfddcbfb3 midi_synth_send_sysex +EXPORT_SYMBOL sound/oss/uart401 0x46248c57 uart401intr +EXPORT_SYMBOL sound/oss/uart401 0xb30fd89d probe_uart401 +EXPORT_SYMBOL sound/oss/uart401 0xecfdd9c9 unload_uart401 +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x0bb9e50b snd_ac97_resume +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x2d62c740 snd_ac97_update +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x351fa812 snd_ac97_pcm_assign +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3c9ee747 snd_ac97_mixer +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x41c2fc3c snd_ac97_write_cache +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x48c57850 snd_ac97_write +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x49ca1cf1 snd_ac97_pcm_open +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x97ce656f snd_ac97_suspend +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xa6fe73b3 snd_ac97_update_bits +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xa776d2e4 snd_ac97_get_short_name +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xa81b4779 snd_ac97_set_rate +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xb13aba87 snd_ac97_tune_hardware +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xbdd53996 snd_ac97_pcm_double_rate_rules +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xc08a7e95 snd_ac97_bus +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xe38e9029 snd_ac97_read +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xe7c304ba snd_ac97_pcm_close +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xfe896ce7 snd_ac97_update_power +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x15f1caad snd_emu10k1_synth_copy_from_user +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x86063009 snd_emu10k1_synth_alloc +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x9e8ebafa snd_emu10k1_voice_alloc +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xa877e3e9 snd_emu10k1_ptr_write +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xbe928037 snd_emu10k1_synth_free +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xc307296e snd_emu10k1_ptr_read +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xd032e89b snd_emu10k1_memblk_map +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xdb953b82 snd_emu10k1_synth_bzero +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xe2199248 snd_emu10k1_voice_free +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x65df4b58 snd_ice1712_akm4xxx_build_controls +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x952708b8 snd_ice1712_akm4xxx_free +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xb4c4d6a3 snd_ice1712_akm4xxx_init +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x0c59b761 oxygen_read16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x144c56c3 oxygen_pci_resume +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x1ab3b1ec oxygen_write_ac97_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x4b7e5557 oxygen_write8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x53aa61f1 oxygen_write_spi +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x5605e01b oxygen_pci_probe +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x60450304 oxygen_write16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x6b3ff4ab oxygen_write16_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x734b7b3a oxygen_read32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x80b5b6a6 oxygen_write_ac97 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x8148a400 oxygen_write_i2c +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x81c3c01c oxygen_write8_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x8e44aec7 oxygen_read8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x96c5b523 oxygen_write32_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x9e5d0262 oxygen_write32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xa180de10 oxygen_pci_remove +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xdeb5ffe6 oxygen_pci_suspend +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xe777dbc5 oxygen_read_ac97 +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x17cff9c8 snd_trident_alloc_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x54f834f2 snd_trident_free_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0xb1f6e9fc snd_trident_start_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0xd02f842f snd_trident_stop_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0xff7113a4 snd_trident_write_voice_regs +EXPORT_SYMBOL sound/sound_firmware 0x39e3dd23 mod_firmware_load +EXPORT_SYMBOL sound/soundcore 0x09cfb10c sound_class +EXPORT_SYMBOL sound/soundcore 0x13b69f5c register_sound_dsp +EXPORT_SYMBOL sound/soundcore 0x49a964a0 register_sound_special +EXPORT_SYMBOL sound/soundcore 0x69aa05aa register_sound_midi +EXPORT_SYMBOL sound/soundcore 0x7afc9d8a unregister_sound_mixer +EXPORT_SYMBOL sound/soundcore 0x99c95fa5 unregister_sound_special +EXPORT_SYMBOL sound/soundcore 0xcd083b10 unregister_sound_dsp +EXPORT_SYMBOL sound/soundcore 0xce25278a register_sound_mixer +EXPORT_SYMBOL sound/soundcore 0xf6a9ca1a register_sound_special_device +EXPORT_SYMBOL sound/soundcore 0xfdab6de3 unregister_sound_midi +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x02902c9c snd_emux_unlock_voice +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x08e4c036 snd_emux_terminate_all +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x3cb694b6 snd_emux_new +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x5872d46d snd_emux_free +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x655cb202 snd_sf_linear_to_log +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x6a4c2ed6 snd_emux_register +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x7ff4817b snd_emux_lock_voice +EXPORT_SYMBOL sound/synth/snd-util-mem 0x20d65978 snd_util_memhdr_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x24886293 __snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0x569d614e snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x7a007343 snd_util_memhdr_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd197c5db __snd_util_memblk_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd34b56e4 __snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd8b55e81 snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0xf158252c snd_util_mem_avail +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x16756dc0 snd_usbmidi_input_start +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x237ac3fc snd_usb_create_midi_interface +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x63343b1d snd_usbmidi_input_stop +EXPORT_SYMBOL sound/usb/snd-usb-lib 0xd9d2bb03 snd_usbmidi_disconnect +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x07dece38 dm_mem_cache_client_create +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x09326c52 dm_mem_cache_free +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x84b4125c dm_mem_cache_alloc +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x966cf67a dm_mem_cache_shrink +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xb8302c42 dm_mem_cache_client_destroy +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xc545b82b dm_mem_cache_grow +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-message 0x920a7a41 dm_message_parse +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x0329d132 rh_sector_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x108f2649 rh_dec +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x275fdd04 rh_recovery_start +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x332307bf rh_delay_by_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x35496306 rh_delay +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x3a171a36 rh_inc_pending +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x5c2a0632 rh_recovery_end +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x62842029 rh_flush +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x689603bd rh_bio_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x804d8032 rh_init +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x8252ef05 rh_state +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x8821f9a7 rh_region_to_sector +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xa4a7321f rh_get_region_key +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xa923d788 rh_start_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xac274ed3 rh_stop_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xb513be98 rh_update_states +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xbb748327 rh_reg_set_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4fdf256 rh_recovery_prepare +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4ff7745 rh_reg_get_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc57bafec rh_exit +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xd99f0978 rh_inc +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xda581f7b rh_get_region_size +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x29c887a9 set_tx_channels +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x60b2e316 cmdir_read +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x7789312a cmdir_write +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x65c7dc56 lirc_get_pdata +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0xdfcdea7e lirc_register_plugin +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0xe96379eb lirc_unregister_plugin +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0x7db9be3c ov511_deregister_decomp_module +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0xc3e2de59 ov511_register_decomp_module +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x308c7650 wlan_unsetup +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x39600dfc p80211_suspend +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x6278d8b0 p80211netdev_hwremoved +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x67c0c175 p80211_allow_ioctls +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x723b8f18 p80211wext_event_associated +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x7e192f00 wlan_setup +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x9b651949 unregister_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xa78988a0 p80211skb_rxmeta_attach +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xaa82f917 register_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb0af0799 wlan_wext_write +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb1083ccf p80211netdev_rx +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xf62637fc p80211_resume +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xfc9aa17f p80211skb_free +EXPORT_SYMBOL vmlinux 0x0003f993 uart_resume_port +EXPORT_SYMBOL vmlinux 0x000455b6 init_buffer +EXPORT_SYMBOL vmlinux 0x00112f51 groups_alloc +EXPORT_SYMBOL vmlinux 0x003a1fbf neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0x0043767b blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x005b88b4 qdisc_list_del +EXPORT_SYMBOL vmlinux 0x00694db2 pci_do_scan_bus +EXPORT_SYMBOL vmlinux 0x00701c0f put_io_context +EXPORT_SYMBOL vmlinux 0x00801678 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x0080fcd6 tcf_hash_release +EXPORT_SYMBOL vmlinux 0x008915d9 pci_enable_device_io +EXPORT_SYMBOL vmlinux 0x009d258f _write_lock +EXPORT_SYMBOL vmlinux 0x00b5fd86 tcp_rcv_established +EXPORT_SYMBOL vmlinux 0x00d28184 backlight_device_register +EXPORT_SYMBOL vmlinux 0x00e8097b csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x00ee9f4d __dst_free +EXPORT_SYMBOL vmlinux 0x01139ffc max_mapnr +EXPORT_SYMBOL vmlinux 0x0168e612 bio_copy_kern +EXPORT_SYMBOL vmlinux 0x016d27ea sock_kmalloc +EXPORT_SYMBOL vmlinux 0x0170d2ec alloc_pci_dev +EXPORT_SYMBOL vmlinux 0x0186d073 percpu_counter_set +EXPORT_SYMBOL vmlinux 0x01902adf netpoll_trap +EXPORT_SYMBOL vmlinux 0x01971da3 qdisc_class_hash_grow +EXPORT_SYMBOL vmlinux 0x0197de1e generic_readlink +EXPORT_SYMBOL vmlinux 0x01a4aab6 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x01ccc7e0 pci_release_selected_regions +EXPORT_SYMBOL vmlinux 0x01d19038 acpi_enable_subsystem +EXPORT_SYMBOL vmlinux 0x0210507a sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x02124474 ip_send_check +EXPORT_SYMBOL vmlinux 0x02138f9d bioset_integrity_create +EXPORT_SYMBOL vmlinux 0x0237b57a arch_unregister_cpu +EXPORT_SYMBOL vmlinux 0x023ea78a __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0x025277f6 profile_pc +EXPORT_SYMBOL vmlinux 0x0255d799 elv_add_request +EXPORT_SYMBOL vmlinux 0x0256389f bit_waitqueue +EXPORT_SYMBOL vmlinux 0x02649054 security_sock_rcv_skb +EXPORT_SYMBOL vmlinux 0x026aac61 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0x02890cea netdev_set_master +EXPORT_SYMBOL vmlinux 0x029444f0 native_read_tsc +EXPORT_SYMBOL vmlinux 0x02a18c74 nf_conntrack_destroy +EXPORT_SYMBOL vmlinux 0x02aff2f4 acpi_install_gpe_handler +EXPORT_SYMBOL vmlinux 0x02d14144 vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x02d81845 audit_log_task_context +EXPORT_SYMBOL vmlinux 0x02e84d1b per_cpu__cpu_sibling_map +EXPORT_SYMBOL vmlinux 0x02e9d0d8 sysctl_data +EXPORT_SYMBOL vmlinux 0x02ee26c1 free_pages_exact +EXPORT_SYMBOL vmlinux 0x030e5882 blk_execute_rq +EXPORT_SYMBOL vmlinux 0x0334da4e scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x03409d62 arch_debugfs_dir +EXPORT_SYMBOL vmlinux 0x037a0cba kfree +EXPORT_SYMBOL vmlinux 0x03a99c3b rb_prev +EXPORT_SYMBOL vmlinux 0x03c06156 bitmap_fold +EXPORT_SYMBOL vmlinux 0x03fd3a25 nla_append +EXPORT_SYMBOL vmlinux 0x0413dd33 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0x041ef0c5 dev_change_flags +EXPORT_SYMBOL vmlinux 0x0422fe4a inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x04483862 flush_signals +EXPORT_SYMBOL vmlinux 0x044fbf49 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x045bfd4b free_buffer_head +EXPORT_SYMBOL vmlinux 0x0487f831 fb_find_best_display +EXPORT_SYMBOL vmlinux 0x04a428a0 sk_run_filter +EXPORT_SYMBOL vmlinux 0x04a8e453 iget_failed +EXPORT_SYMBOL vmlinux 0x04d8c750 release_perfctr_nmi +EXPORT_SYMBOL vmlinux 0x05171e62 hippi_type_trans +EXPORT_SYMBOL vmlinux 0x0548560d unregister_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0x05609ecc pskb_expand_head +EXPORT_SYMBOL vmlinux 0x0560cdeb xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x0572494d neigh_compat_output +EXPORT_SYMBOL vmlinux 0x057ce975 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x057d9d34 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0x058c75d9 acpi_get_pci_id +EXPORT_SYMBOL vmlinux 0x05dda31d wireless_send_event +EXPORT_SYMBOL vmlinux 0x05e4c7e6 tty_hung_up_p +EXPORT_SYMBOL vmlinux 0x061651be strcat +EXPORT_SYMBOL vmlinux 0x06375762 seq_open_private +EXPORT_SYMBOL vmlinux 0x0646f1b4 tty_unregister_driver +EXPORT_SYMBOL vmlinux 0x0662a365 tcp_v4_connect +EXPORT_SYMBOL vmlinux 0x067d8d35 security_release_secctx +EXPORT_SYMBOL vmlinux 0x06c27ca0 sync_blockdev +EXPORT_SYMBOL vmlinux 0x06d728b1 tcp_parse_md5sig_option +EXPORT_SYMBOL vmlinux 0x06fbbf1d update_region +EXPORT_SYMBOL vmlinux 0x06fe3b14 default_grn +EXPORT_SYMBOL vmlinux 0x0727c4f3 iowrite8 +EXPORT_SYMBOL vmlinux 0x073dfa12 generate_resume_trace +EXPORT_SYMBOL vmlinux 0x07608604 acpi_get_vendor_resource +EXPORT_SYMBOL vmlinux 0x077059bd bfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0x0786158a tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0x078d3729 netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x0797ecda kernel_sendpage +EXPORT_SYMBOL vmlinux 0x0799aca4 local_bh_enable +EXPORT_SYMBOL vmlinux 0x079cd7f1 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x07a890c8 fb_alloc_cmap +EXPORT_SYMBOL vmlinux 0x07cc4a5d printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x07d50a24 csum_partial +EXPORT_SYMBOL vmlinux 0x081012af nobh_write_end +EXPORT_SYMBOL vmlinux 0x082c3213 pci_root_buses +EXPORT_SYMBOL vmlinux 0x0841ff6e find_task_by_vpid +EXPORT_SYMBOL vmlinux 0x08b9a305 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x08d7b5b8 input_unregister_device +EXPORT_SYMBOL vmlinux 0x09052c0c kset_unregister +EXPORT_SYMBOL vmlinux 0x0933aae1 efi_enabled +EXPORT_SYMBOL vmlinux 0x093e947e posix_acl_create_masq +EXPORT_SYMBOL vmlinux 0x0948cde9 num_physpages +EXPORT_SYMBOL vmlinux 0x0972f067 remove_arg_zero +EXPORT_SYMBOL vmlinux 0x097753b2 bdi_register +EXPORT_SYMBOL vmlinux 0x09775cdc kref_get +EXPORT_SYMBOL vmlinux 0x098aa766 pci_bus_add_devices +EXPORT_SYMBOL vmlinux 0x098b71c6 fb_dealloc_cmap +EXPORT_SYMBOL vmlinux 0x09c55cec schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x09d051fe default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0x09d44df9 in_lock_functions +EXPORT_SYMBOL vmlinux 0x09de227e alloc_file +EXPORT_SYMBOL vmlinux 0x0a22175d xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x0a2487e0 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x0a3131f6 strnchr +EXPORT_SYMBOL vmlinux 0x0a3cb807 poll_initwait +EXPORT_SYMBOL vmlinux 0x0a54487d clip_tbl_hook +EXPORT_SYMBOL vmlinux 0x0a5eff80 inet_addr_type +EXPORT_SYMBOL vmlinux 0x0aaa1cca set_pages_nx +EXPORT_SYMBOL vmlinux 0x0acb1a3c __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x0aef9243 pci_get_bus_and_slot +EXPORT_SYMBOL vmlinux 0x0af116f1 pci_dev_put +EXPORT_SYMBOL vmlinux 0x0af423b3 tcp_connect +EXPORT_SYMBOL vmlinux 0x0b0defb2 remap_pfn_range +EXPORT_SYMBOL vmlinux 0x0b1beb31 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x0b27c931 blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0x0b28ca0c dump_trace +EXPORT_SYMBOL vmlinux 0x0b5b9322 pci_request_region +EXPORT_SYMBOL vmlinux 0x0b742fd7 simple_strtol +EXPORT_SYMBOL vmlinux 0x0ba6cb38 netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0x0bf1e87a ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0x0c2bada9 gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x0c5c69e3 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x0c5d5713 dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x0c5ef91b per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x0c87c756 bio_split_pool +EXPORT_SYMBOL vmlinux 0x0cfee8f8 acpi_bus_get_status +EXPORT_SYMBOL vmlinux 0x0d0d2458 make_bad_inode +EXPORT_SYMBOL vmlinux 0x0d26a76d _write_lock_irq +EXPORT_SYMBOL vmlinux 0x0d384c76 inet_frag_evictor +EXPORT_SYMBOL vmlinux 0x0d3dda14 acpi_get_type +EXPORT_SYMBOL vmlinux 0x0d4b77b7 gen_pool_add +EXPORT_SYMBOL vmlinux 0x0d542439 __ipv6_addr_type +EXPORT_SYMBOL vmlinux 0x0d6c963c copy_from_user +EXPORT_SYMBOL vmlinux 0x0d8ab500 param_set_copystring +EXPORT_SYMBOL vmlinux 0x0da10ec3 security_sock_graft +EXPORT_SYMBOL vmlinux 0x0da4df32 dmam_pool_create +EXPORT_SYMBOL vmlinux 0x0dc8c255 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0x0de60fa3 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0x0deff780 pci_add_new_bus +EXPORT_SYMBOL vmlinux 0x0e2e7335 do_SAK +EXPORT_SYMBOL vmlinux 0x0e49afa6 blk_rq_count_integrity_sg +EXPORT_SYMBOL vmlinux 0x0e52592a panic +EXPORT_SYMBOL vmlinux 0x0e762d6e request_module +EXPORT_SYMBOL vmlinux 0x0e9b0240 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x0ed115da get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x0ed5cffd unregister_exec_domain +EXPORT_SYMBOL vmlinux 0x0f13a884 udp_ioctl +EXPORT_SYMBOL vmlinux 0x0f20077a ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0x0f5363ab destroy_EII_client +EXPORT_SYMBOL vmlinux 0x0fa53ca5 iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0x0faef0ed __tasklet_schedule +EXPORT_SYMBOL vmlinux 0x0fd00a68 acpi_clear_event +EXPORT_SYMBOL vmlinux 0x0fe58e26 create_empty_buffers +EXPORT_SYMBOL vmlinux 0x1001b549 dmam_release_declared_memory +EXPORT_SYMBOL vmlinux 0x10073c27 blk_complete_request +EXPORT_SYMBOL vmlinux 0x100ec1d6 dma_mark_declared_memory_occupied +EXPORT_SYMBOL vmlinux 0x10284c46 blk_stop_queue +EXPORT_SYMBOL vmlinux 0x1039683b dst_discard +EXPORT_SYMBOL vmlinux 0x10429a54 fb_validate_mode +EXPORT_SYMBOL vmlinux 0x104e5bde idr_find +EXPORT_SYMBOL vmlinux 0x1094ea38 mapping_tagged +EXPORT_SYMBOL vmlinux 0x10a13294 datagram_poll +EXPORT_SYMBOL vmlinux 0x10b26ab4 elv_rb_former_request +EXPORT_SYMBOL vmlinux 0x10cf6de1 inet_frags_init +EXPORT_SYMBOL vmlinux 0x10ee20bb default_blu +EXPORT_SYMBOL vmlinux 0x115468dd ida_init +EXPORT_SYMBOL vmlinux 0x1156582d pci_bus_read_config_word +EXPORT_SYMBOL vmlinux 0x1163f0a7 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x117093be qdisc_class_hash_init +EXPORT_SYMBOL vmlinux 0x11745c6d get_write_access +EXPORT_SYMBOL vmlinux 0x118f01ea putname +EXPORT_SYMBOL vmlinux 0x11932e34 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x11a18b14 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x121ffc3b nf_hook_slow +EXPORT_SYMBOL vmlinux 0x125fbca7 cad_pid +EXPORT_SYMBOL vmlinux 0x126970ed param_set_uint +EXPORT_SYMBOL vmlinux 0x1275e89d fb_class +EXPORT_SYMBOL vmlinux 0x12870ff6 kernel_getsockname +EXPORT_SYMBOL vmlinux 0x12da5bb2 __kmalloc +EXPORT_SYMBOL vmlinux 0x12f99022 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x131e836b inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0x132f45f2 cookie_check_timestamp +EXPORT_SYMBOL vmlinux 0x1348857a cfb_fillrect +EXPORT_SYMBOL vmlinux 0x136bbb44 tty_hangup +EXPORT_SYMBOL vmlinux 0x13781784 gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0x138bf51d flush_tlb_page +EXPORT_SYMBOL vmlinux 0x13b8ab68 dquot_free_inode +EXPORT_SYMBOL vmlinux 0x13f71731 tcf_hash_lookup +EXPORT_SYMBOL vmlinux 0x13ff24b7 dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0x141222e9 ip_setsockopt +EXPORT_SYMBOL vmlinux 0x141bb0f9 input_inject_event +EXPORT_SYMBOL vmlinux 0x1430e6e0 unregister_acpi_notifier +EXPORT_SYMBOL vmlinux 0x143f59d3 d_move +EXPORT_SYMBOL vmlinux 0x14753d04 __page_symlink +EXPORT_SYMBOL vmlinux 0x14af0cf7 gen_pool_destroy +EXPORT_SYMBOL vmlinux 0x14ba7b88 ip_defrag +EXPORT_SYMBOL vmlinux 0x14f332ea up_read +EXPORT_SYMBOL vmlinux 0x150073ad scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0x15231f87 ip_xfrm_me_harder +EXPORT_SYMBOL vmlinux 0x1544aad4 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x1551dc51 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x1596b1a9 generic_unplug_device +EXPORT_SYMBOL vmlinux 0x15af2c17 noop_qdisc +EXPORT_SYMBOL vmlinux 0x15b05c06 genl_register_ops +EXPORT_SYMBOL vmlinux 0x15ef2dd9 kfifo_free +EXPORT_SYMBOL vmlinux 0x162dc35a sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x16489ba3 idr_remove +EXPORT_SYMBOL vmlinux 0x165c3007 sock_create +EXPORT_SYMBOL vmlinux 0x1672785e vc_resize +EXPORT_SYMBOL vmlinux 0x1675606f bad_dma_address +EXPORT_SYMBOL vmlinux 0x167879ce xfrm_input_resume +EXPORT_SYMBOL vmlinux 0x167e7f9d __get_user_1 +EXPORT_SYMBOL vmlinux 0x1688abfd iw_handler_set_thrspy +EXPORT_SYMBOL vmlinux 0x16a35878 _read_unlock +EXPORT_SYMBOL vmlinux 0x16eeec74 pci_set_master +EXPORT_SYMBOL vmlinux 0x1702a217 neigh_update +EXPORT_SYMBOL vmlinux 0x170c25ee acpi_get_next_object +EXPORT_SYMBOL vmlinux 0x173786de sock_setsockopt +EXPORT_SYMBOL vmlinux 0x173d4443 xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0x175a298d acpi_set_firmware_waking_vector +EXPORT_SYMBOL vmlinux 0x17636433 alloc_disk +EXPORT_SYMBOL vmlinux 0x1796555c find_lock_page +EXPORT_SYMBOL vmlinux 0x17a76e71 rb_first +EXPORT_SYMBOL vmlinux 0x17c10190 nobh_truncate_page +EXPORT_SYMBOL vmlinux 0x17c4ace5 qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0x17df17bc sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x180031d7 dev_set_mtu +EXPORT_SYMBOL vmlinux 0x181015c9 con_is_bound +EXPORT_SYMBOL vmlinux 0x181b6ff2 mempool_resize +EXPORT_SYMBOL vmlinux 0x183fa88b mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x186581c0 neigh_seq_start +EXPORT_SYMBOL vmlinux 0x187aaee5 inet_add_protocol +EXPORT_SYMBOL vmlinux 0x1889782d sock_wmalloc +EXPORT_SYMBOL vmlinux 0x1892be51 linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0x1898fdf1 contig_page_data +EXPORT_SYMBOL vmlinux 0x189aeda5 mca_register_driver +EXPORT_SYMBOL vmlinux 0x18d06bcb serial8250_register_port +EXPORT_SYMBOL vmlinux 0x18f1246f security_inode_init_security +EXPORT_SYMBOL vmlinux 0x193ae564 fb_set_cmap +EXPORT_SYMBOL vmlinux 0x19462497 skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0x1985ed3c prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0x199ed0cd net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x19afb86b mca_device_set_claim +EXPORT_SYMBOL vmlinux 0x19c74cbb input_register_handler +EXPORT_SYMBOL vmlinux 0x19d5d20a acpi_walk_namespace +EXPORT_SYMBOL vmlinux 0x19e34e75 serio_unregister_child_port +EXPORT_SYMBOL vmlinux 0x1a137cbf keyring_clear +EXPORT_SYMBOL vmlinux 0x1a1ab15d tty_mutex +EXPORT_SYMBOL vmlinux 0x1a1fc898 arp_broken_ops +EXPORT_SYMBOL vmlinux 0x1a45cb6c acpi_disabled +EXPORT_SYMBOL vmlinux 0x1a5b29dd kick_iocb +EXPORT_SYMBOL vmlinux 0x1a705080 bio_integrity_alloc +EXPORT_SYMBOL vmlinux 0x1a75caa3 _read_lock +EXPORT_SYMBOL vmlinux 0x1a854228 get_io_context +EXPORT_SYMBOL vmlinux 0x1a8a845e idle_nomwait +EXPORT_SYMBOL vmlinux 0x1aa8b67a touch_atime +EXPORT_SYMBOL vmlinux 0x1ace138d bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x1acff019 __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0x1ae8d7dc param_set_invbool +EXPORT_SYMBOL vmlinux 0x1aef1674 tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x1af80066 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0x1b015d25 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x1b3c678a gen_new_estimator +EXPORT_SYMBOL vmlinux 0x1b47c4e4 init_special_inode +EXPORT_SYMBOL vmlinux 0x1b6314fd in_aton +EXPORT_SYMBOL vmlinux 0x1b89419f add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x1b9981cc set_irq_wake +EXPORT_SYMBOL vmlinux 0x1bbcfca8 tcf_em_tree_validate +EXPORT_SYMBOL vmlinux 0x1be90844 kernel_listen +EXPORT_SYMBOL vmlinux 0x1c196fef poll_freewait +EXPORT_SYMBOL vmlinux 0x1c45a2b8 secpath_dup +EXPORT_SYMBOL vmlinux 0x1c5bc324 sg_miter_start +EXPORT_SYMBOL vmlinux 0x1caa801c generic_setxattr +EXPORT_SYMBOL vmlinux 0x1cbe85cd textsearch_register +EXPORT_SYMBOL vmlinux 0x1cc0ba73 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0x1cc6719a register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x1cefe352 wait_for_completion +EXPORT_SYMBOL vmlinux 0x1d30b70c rwsem_wake +EXPORT_SYMBOL vmlinux 0x1d4292b4 qdisc_tree_decrease_qlen +EXPORT_SYMBOL vmlinux 0x1d830520 cpu_possible_map +EXPORT_SYMBOL vmlinux 0x1dc36131 fb_destroy_modedb +EXPORT_SYMBOL vmlinux 0x1dd571e6 fb_copy_cmap +EXPORT_SYMBOL vmlinux 0x1de5bc35 create_proc_entry +EXPORT_SYMBOL vmlinux 0x1e012e8a blk_get_request +EXPORT_SYMBOL vmlinux 0x1e01fb38 registered_fb +EXPORT_SYMBOL vmlinux 0x1e0582a0 pci_get_slot +EXPORT_SYMBOL vmlinux 0x1e6d26a8 strstr +EXPORT_SYMBOL vmlinux 0x1e79c75d acpi_bus_generate_proc_event +EXPORT_SYMBOL vmlinux 0x1e9c1870 input_grab_device +EXPORT_SYMBOL vmlinux 0x1eb922a3 IO_APIC_get_PCI_irq_vector +EXPORT_SYMBOL vmlinux 0x1eb94677 dma_free_coherent +EXPORT_SYMBOL vmlinux 0x1ec15b92 inode_set_bytes +EXPORT_SYMBOL vmlinux 0x1efe283f __cap_full_set +EXPORT_SYMBOL vmlinux 0x1f219b12 pci_bus_assign_resources +EXPORT_SYMBOL vmlinux 0x1f27d6d7 _write_unlock +EXPORT_SYMBOL vmlinux 0x1f405803 call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x1f86737f dev_disable_lro +EXPORT_SYMBOL vmlinux 0x1fa4dd27 kill_pgrp +EXPORT_SYMBOL vmlinux 0x1fd6edce sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x1fe5ede6 per_cpu__irq_stat +EXPORT_SYMBOL vmlinux 0x20000329 simple_strtoul +EXPORT_SYMBOL vmlinux 0x2005e68a acpi_remove_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x200e1d23 fifo_set_limit +EXPORT_SYMBOL vmlinux 0x2027a96e vfs_llseek +EXPORT_SYMBOL vmlinux 0x20289476 ether_setup +EXPORT_SYMBOL vmlinux 0x208739f6 acpi_load_table +EXPORT_SYMBOL vmlinux 0x20a1981c pnp_stop_dev +EXPORT_SYMBOL vmlinux 0x20adc0f9 names_cachep +EXPORT_SYMBOL vmlinux 0x20c8fc33 pci_osc_control_set +EXPORT_SYMBOL vmlinux 0x20e7e8c5 block_truncate_page +EXPORT_SYMBOL vmlinux 0x212aecca __alloc_skb +EXPORT_SYMBOL vmlinux 0x215ebd78 bitrev16 +EXPORT_SYMBOL vmlinux 0x216bac28 tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x217399cb inet_del_protocol +EXPORT_SYMBOL vmlinux 0x218865f0 pci_disable_msi +EXPORT_SYMBOL vmlinux 0x219b6e83 sock_map_fd +EXPORT_SYMBOL vmlinux 0x21b64164 pneigh_enqueue +EXPORT_SYMBOL vmlinux 0x21e0ea22 acpi_get_id +EXPORT_SYMBOL vmlinux 0x222e7ce2 sysfs_streq +EXPORT_SYMBOL vmlinux 0x226e86a9 audit_log +EXPORT_SYMBOL vmlinux 0x22747d10 tcf_em_tree_destroy +EXPORT_SYMBOL vmlinux 0x2275c0b4 inet_dgram_connect +EXPORT_SYMBOL vmlinux 0x2284c28d vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x2288378f system_state +EXPORT_SYMBOL vmlinux 0x22a73912 __tcp_put_md5sig_pool +EXPORT_SYMBOL vmlinux 0x22b325d5 kd_mksound +EXPORT_SYMBOL vmlinux 0x22b6533b xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x22bcbe1f inet_put_port +EXPORT_SYMBOL vmlinux 0x22e6575e block_prepare_write +EXPORT_SYMBOL vmlinux 0x22ed6c80 filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0x23081d81 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x231042e5 simple_prepare_write +EXPORT_SYMBOL vmlinux 0x231f3a66 __kfifo_put +EXPORT_SYMBOL vmlinux 0x23269a13 strict_strtoul +EXPORT_SYMBOL vmlinux 0x2348da64 generic_read_dir +EXPORT_SYMBOL vmlinux 0x2364214a qdisc_calculate_pkt_len +EXPORT_SYMBOL vmlinux 0x236665af skb_store_bits +EXPORT_SYMBOL vmlinux 0x2368be6d posix_acl_to_xattr +EXPORT_SYMBOL vmlinux 0x23a7a3bd maps_protect +EXPORT_SYMBOL vmlinux 0x23ad070a set_current_groups +EXPORT_SYMBOL vmlinux 0x23f2d36f memparse +EXPORT_SYMBOL vmlinux 0x23f38b58 pnp_unregister_driver +EXPORT_SYMBOL vmlinux 0x23fd3028 vmalloc_node +EXPORT_SYMBOL vmlinux 0x24133bee unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0x24428be5 strncpy_from_user +EXPORT_SYMBOL vmlinux 0x244fa61f __serio_register_port +EXPORT_SYMBOL vmlinux 0x2459bbcc console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x2491a746 neigh_for_each +EXPORT_SYMBOL vmlinux 0x24c1ef2b acpi_evaluate_integer +EXPORT_SYMBOL vmlinux 0x24c6f7f8 d_prune_aliases +EXPORT_SYMBOL vmlinux 0x24fdac79 wake_bit_function +EXPORT_SYMBOL vmlinux 0x250113b4 memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x250c3bd0 task_nice +EXPORT_SYMBOL vmlinux 0x25597bf5 serio_unregister_port +EXPORT_SYMBOL vmlinux 0x2566948d textsearch_prepare +EXPORT_SYMBOL vmlinux 0x256887e1 warn_slowpath +EXPORT_SYMBOL vmlinux 0x25820c64 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x258355b4 fb_find_best_mode +EXPORT_SYMBOL vmlinux 0x25854b5a bdi_register_dev +EXPORT_SYMBOL vmlinux 0x25d81960 posix_acl_equiv_mode +EXPORT_SYMBOL vmlinux 0x25dff875 bio_integrity_enabled +EXPORT_SYMBOL vmlinux 0x25e9629b simple_rmdir +EXPORT_SYMBOL vmlinux 0x2622c3d2 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0x2655b89d nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x266d59d6 nonseekable_open +EXPORT_SYMBOL vmlinux 0x2676c219 dquot_transfer +EXPORT_SYMBOL vmlinux 0x2685c3d7 __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x268cc6a2 sys_close +EXPORT_SYMBOL vmlinux 0x26972d1a unload_nls +EXPORT_SYMBOL vmlinux 0x269de5a3 ps2_handle_ack +EXPORT_SYMBOL vmlinux 0x26c7bfbf inet_register_protosw +EXPORT_SYMBOL vmlinux 0x26e76fb8 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x26f3ac58 proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x270f519c __free_pages +EXPORT_SYMBOL vmlinux 0x271b38a0 cdev_init +EXPORT_SYMBOL vmlinux 0x272d394e mtrr_del +EXPORT_SYMBOL vmlinux 0x272e7488 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x27377c7c pci_disable_msix +EXPORT_SYMBOL vmlinux 0x2739a0d3 locks_remove_posix +EXPORT_SYMBOL vmlinux 0x273a9802 pci_enable_device +EXPORT_SYMBOL vmlinux 0x273f066e _write_unlock_irq +EXPORT_SYMBOL vmlinux 0x27536608 mpage_writepages +EXPORT_SYMBOL vmlinux 0x2764239d kmap +EXPORT_SYMBOL vmlinux 0x277d99db __next_cpu +EXPORT_SYMBOL vmlinux 0x279cc587 find_get_pages_tag +EXPORT_SYMBOL vmlinux 0x27a9a7eb ns_to_timespec +EXPORT_SYMBOL vmlinux 0x27af178c udp_disconnect +EXPORT_SYMBOL vmlinux 0x27bbf221 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x27c61ece qdisc_put_stab +EXPORT_SYMBOL vmlinux 0x280faa98 seq_release +EXPORT_SYMBOL vmlinux 0x283a4a3a filemap_flush +EXPORT_SYMBOL vmlinux 0x285ac517 strict_strtoll +EXPORT_SYMBOL vmlinux 0x2860c966 ida_get_new_above +EXPORT_SYMBOL vmlinux 0x289842fc d_namespace_path +EXPORT_SYMBOL vmlinux 0x28a83ff9 __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x28b715a6 isapnp_cfg_end +EXPORT_SYMBOL vmlinux 0x28dcf25c udplite_hash +EXPORT_SYMBOL vmlinux 0x28f7e6a9 dev_close +EXPORT_SYMBOL vmlinux 0x2911eb5a cpufreq_get_policy +EXPORT_SYMBOL vmlinux 0x291fbed2 wait_on_page_bit +EXPORT_SYMBOL vmlinux 0x2946ffdf deny_write_access +EXPORT_SYMBOL vmlinux 0x29537c9e alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x2959dbad nf_getsockopt +EXPORT_SYMBOL vmlinux 0x29747557 bdi_init +EXPORT_SYMBOL vmlinux 0x297fd498 netlink_unicast +EXPORT_SYMBOL vmlinux 0x29915c85 pci_release_regions +EXPORT_SYMBOL vmlinux 0x29ab5a18 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x29af8d2d generic_file_direct_write +EXPORT_SYMBOL vmlinux 0x29bd4c46 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x29e17d99 unregister_framebuffer +EXPORT_SYMBOL vmlinux 0x2a105c75 elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0x2a303d4d check_signature +EXPORT_SYMBOL vmlinux 0x2a615c96 path_put +EXPORT_SYMBOL vmlinux 0x2a830ad4 __dev_remove_pack +EXPORT_SYMBOL vmlinux 0x2aa0e4fc strncasecmp +EXPORT_SYMBOL vmlinux 0x2acfd069 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0x2add9ee4 fb_get_buffer_offset +EXPORT_SYMBOL vmlinux 0x2aeb2800 mempool_create_node +EXPORT_SYMBOL vmlinux 0x2af136cc register_filesystem +EXPORT_SYMBOL vmlinux 0x2af94582 __inode_dir_notify +EXPORT_SYMBOL vmlinux 0x2b0b412a pcibios_align_resource +EXPORT_SYMBOL vmlinux 0x2b12cb05 security_sk_classify_flow +EXPORT_SYMBOL vmlinux 0x2b5c16be lock_may_write +EXPORT_SYMBOL vmlinux 0x2b6aac8c tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x2b7a0463 serio_interrupt +EXPORT_SYMBOL vmlinux 0x2b86a602 mca_device_transform_memory +EXPORT_SYMBOL vmlinux 0x2ba707a8 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x2bb55d6e acpi_remove_notify_handler +EXPORT_SYMBOL vmlinux 0x2bc95bd4 memset +EXPORT_SYMBOL vmlinux 0x2be09893 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x2bec12d2 remove_inode_hash +EXPORT_SYMBOL vmlinux 0x2bfeb410 acpi_get_handle +EXPORT_SYMBOL vmlinux 0x2c0227a9 xfrm_find_acq +EXPORT_SYMBOL vmlinux 0x2c4c18a3 skb_pad +EXPORT_SYMBOL vmlinux 0x2c5749e6 acpi_clear_gpe +EXPORT_SYMBOL vmlinux 0x2c5b2440 uart_register_driver +EXPORT_SYMBOL vmlinux 0x2c7d7c36 sock_create_lite +EXPORT_SYMBOL vmlinux 0x2c89bc37 request_key +EXPORT_SYMBOL vmlinux 0x2c8f5989 acpi_remove_address_space_handler +EXPORT_SYMBOL vmlinux 0x2cada761 bh_submit_read +EXPORT_SYMBOL vmlinux 0x2cc2d52d vcc_hash +EXPORT_SYMBOL vmlinux 0x2cd9e459 param_set_short +EXPORT_SYMBOL vmlinux 0x2cf190e3 request_irq +EXPORT_SYMBOL vmlinux 0x2dd16564 arch_register_cpu +EXPORT_SYMBOL vmlinux 0x2de9f66f param_get_long +EXPORT_SYMBOL vmlinux 0x2dedc4c2 acpi_format_exception +EXPORT_SYMBOL vmlinux 0x2def7f76 rtc_cmos_write +EXPORT_SYMBOL vmlinux 0x2e10d279 find_get_page +EXPORT_SYMBOL vmlinux 0x2e2450f2 tty_devnum +EXPORT_SYMBOL vmlinux 0x2e2ce9e0 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x2e45edc9 proc_mkdir +EXPORT_SYMBOL vmlinux 0x2e4a39f8 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x2e60bace memcpy +EXPORT_SYMBOL vmlinux 0x2e85b79b ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0x2e97859f rwsem_downgrade_wake +EXPORT_SYMBOL vmlinux 0x2e9e6b3a dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0x2ea73a82 fb_set_var +EXPORT_SYMBOL vmlinux 0x2eb1c338 idr_get_new_above +EXPORT_SYMBOL vmlinux 0x2eb1d3bc vfs_statfs +EXPORT_SYMBOL vmlinux 0x2eb9a0e8 _read_lock_irq +EXPORT_SYMBOL vmlinux 0x2ebf0b55 blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0x2ec81ea4 vfs_follow_link +EXPORT_SYMBOL vmlinux 0x2eeed6e2 keyring_search +EXPORT_SYMBOL vmlinux 0x2f287f0d copy_to_user +EXPORT_SYMBOL vmlinux 0x2f503d95 qdisc_watchdog_schedule +EXPORT_SYMBOL vmlinux 0x2f6133d5 d_rehash +EXPORT_SYMBOL vmlinux 0x2f786157 unregister_qdisc +EXPORT_SYMBOL vmlinux 0x2f85910f kernel_bind +EXPORT_SYMBOL vmlinux 0x2f9e3d9a seq_puts +EXPORT_SYMBOL vmlinux 0x2fc375e1 pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x2ff7efaa tcf_hash_new_index +EXPORT_SYMBOL vmlinux 0x302c7996 mca_register_driver_integrated +EXPORT_SYMBOL vmlinux 0x30896043 __any_online_cpu +EXPORT_SYMBOL vmlinux 0x30e74134 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x310917fe sort +EXPORT_SYMBOL vmlinux 0x31328cea pci_bus_read_config_byte +EXPORT_SYMBOL vmlinux 0x3145216f pci_dev_present +EXPORT_SYMBOL vmlinux 0x3147857d default_red +EXPORT_SYMBOL vmlinux 0x314bd78b bd_set_size +EXPORT_SYMBOL vmlinux 0x3168f8f9 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x3184791e dcache_dir_open +EXPORT_SYMBOL vmlinux 0x3191f109 __krealloc +EXPORT_SYMBOL vmlinux 0x31b466c1 kernel_connect +EXPORT_SYMBOL vmlinux 0x31e76b57 recalibrate_cpu_khz +EXPORT_SYMBOL vmlinux 0x31ede7fe nf_register_sockopt +EXPORT_SYMBOL vmlinux 0x31ff0182 neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0x3216e44e vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0x321a58d6 tcp_v4_md5_hash_skb +EXPORT_SYMBOL vmlinux 0x32248911 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0x324121e1 pnp_unregister_card_driver +EXPORT_SYMBOL vmlinux 0x32683b8a inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0x32888bcc pci_bus_find_capability +EXPORT_SYMBOL vmlinux 0x32d01fec acpi_attach_data +EXPORT_SYMBOL vmlinux 0x32d61a91 qdisc_reset +EXPORT_SYMBOL vmlinux 0x3301f296 seq_path +EXPORT_SYMBOL vmlinux 0x331be0cd tr_type_trans +EXPORT_SYMBOL vmlinux 0x3360a963 param_set_ulong +EXPORT_SYMBOL vmlinux 0x3367d7ae isapnp_protocol +EXPORT_SYMBOL vmlinux 0x337d351b dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x3385c8cb per_cpu__this_cpu_off +EXPORT_SYMBOL vmlinux 0x338ace6e block_write_end +EXPORT_SYMBOL vmlinux 0x33d891b8 netdev_class_create_file +EXPORT_SYMBOL vmlinux 0x33d92f9a prepare_to_wait +EXPORT_SYMBOL vmlinux 0x33dd92e1 vfs_quota_sync +EXPORT_SYMBOL vmlinux 0x3421272c efi +EXPORT_SYMBOL vmlinux 0x342f60fe apm_info +EXPORT_SYMBOL vmlinux 0x3432cc1b skb_truesize_bug +EXPORT_SYMBOL vmlinux 0x3469d2bf eth_type_trans +EXPORT_SYMBOL vmlinux 0x3489a7f0 follow_up +EXPORT_SYMBOL vmlinux 0x34908c14 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x349cba85 strchr +EXPORT_SYMBOL vmlinux 0x34d637a5 tcp_alloc_md5sig_pool +EXPORT_SYMBOL vmlinux 0x34de66eb fasync_helper +EXPORT_SYMBOL vmlinux 0x34f035dc get_sb_single +EXPORT_SYMBOL vmlinux 0x3535147e lookup_one_len +EXPORT_SYMBOL vmlinux 0x357674b5 skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0x357f538c bio_integrity_add_page +EXPORT_SYMBOL vmlinux 0x35a44450 vc_cons +EXPORT_SYMBOL vmlinux 0x35c2ba9e refrigerator +EXPORT_SYMBOL vmlinux 0x35cd0681 sock_register +EXPORT_SYMBOL vmlinux 0x35d15265 kthread_bind +EXPORT_SYMBOL vmlinux 0x35ef0e50 llc_sap_close +EXPORT_SYMBOL vmlinux 0x35f0faa2 acpi_evaluate_object +EXPORT_SYMBOL vmlinux 0x360b1afe probe_irq_mask +EXPORT_SYMBOL vmlinux 0x36215a9e xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0x36240865 tty_set_operations +EXPORT_SYMBOL vmlinux 0x3627aa6b fib_default_rule_add +EXPORT_SYMBOL vmlinux 0x3628429d nf_unregister_hook +EXPORT_SYMBOL vmlinux 0x3632e1a1 pagecache_write_end +EXPORT_SYMBOL vmlinux 0x363ad247 cap_set_effective +EXPORT_SYMBOL vmlinux 0x3656bf5a lock_kernel +EXPORT_SYMBOL vmlinux 0x3665b802 sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0x3692dcc6 sock_no_sendpage +EXPORT_SYMBOL vmlinux 0x369f455e alloc_hippi_dev +EXPORT_SYMBOL vmlinux 0x36ba38c5 arp_create +EXPORT_SYMBOL vmlinux 0x37136188 tcp_v4_md5_lookup +EXPORT_SYMBOL vmlinux 0x37406abc tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x3744cf36 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x374ed073 scnprintf +EXPORT_SYMBOL vmlinux 0x377dde7d inet_sock_destruct +EXPORT_SYMBOL vmlinux 0x37874e46 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0x378bd80e sk_wait_data +EXPORT_SYMBOL vmlinux 0x378dab1d pci_setup_cardbus +EXPORT_SYMBOL vmlinux 0x379a2ced elv_queue_empty +EXPORT_SYMBOL vmlinux 0x379d65f5 gen_pool_alloc +EXPORT_SYMBOL vmlinux 0x37befc70 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x37e74642 get_jiffies_64 +EXPORT_SYMBOL vmlinux 0x38203ca1 __init_rwsem +EXPORT_SYMBOL vmlinux 0x383cfdb1 br_handle_frame_hook +EXPORT_SYMBOL vmlinux 0x384c76f5 user_revoke +EXPORT_SYMBOL vmlinux 0x3853fd42 skb_push +EXPORT_SYMBOL vmlinux 0x386123fc simple_getattr +EXPORT_SYMBOL vmlinux 0x387c0967 vfs_lstat +EXPORT_SYMBOL vmlinux 0x38859cc8 acpi_bus_register_driver +EXPORT_SYMBOL vmlinux 0x38b92846 llc_remove_pack +EXPORT_SYMBOL vmlinux 0x39170a6c acpi_check_resource_conflict +EXPORT_SYMBOL vmlinux 0x395108ef mem_map +EXPORT_SYMBOL vmlinux 0x395344ec arp_tbl +EXPORT_SYMBOL vmlinux 0x3980aac1 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x39b06b11 page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0x39b77ad7 llc_set_station_handler +EXPORT_SYMBOL vmlinux 0x39c645a2 schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0x39e180da tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0x3a2204c6 security_netlink_recv +EXPORT_SYMBOL vmlinux 0x3a6dbaa6 dquot_commit +EXPORT_SYMBOL vmlinux 0x3a9b6fb9 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x3a9d23ce sk_common_release +EXPORT_SYMBOL vmlinux 0x3aa1dbcf _spin_unlock_bh +EXPORT_SYMBOL vmlinux 0x3aa608ac register_gifconf +EXPORT_SYMBOL vmlinux 0x3ac69b1c seq_escape +EXPORT_SYMBOL vmlinux 0x3b003f3f ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x3b21f083 inode_get_bytes +EXPORT_SYMBOL vmlinux 0x3b2624ca seq_putc +EXPORT_SYMBOL vmlinux 0x3b3016d3 cpufreq_unregister_notifier +EXPORT_SYMBOL vmlinux 0x3b396bd7 ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0x3b6a3058 tcf_exts_dump +EXPORT_SYMBOL vmlinux 0x3b856ab6 inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0x3b9afc44 skb_copy +EXPORT_SYMBOL vmlinux 0x3bb8d02a unlock_super +EXPORT_SYMBOL vmlinux 0x3bd1b1f6 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x3c0c2f86 module_refcount +EXPORT_SYMBOL vmlinux 0x3c11193f neigh_ifdown +EXPORT_SYMBOL vmlinux 0x3c2c5af5 sprintf +EXPORT_SYMBOL vmlinux 0x3c3f0e32 blk_init_queue +EXPORT_SYMBOL vmlinux 0x3c414643 generic_ro_fops +EXPORT_SYMBOL vmlinux 0x3c7227bf complete_all +EXPORT_SYMBOL vmlinux 0x3cb3931b sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0x3cb8a495 param_get_string +EXPORT_SYMBOL vmlinux 0x3cbc779e do_splice_to +EXPORT_SYMBOL vmlinux 0x3cc0a3bb xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x3ce4ca6f disable_irq +EXPORT_SYMBOL vmlinux 0x3cf1f863 pnp_device_detach +EXPORT_SYMBOL vmlinux 0x3d1b65d7 uart_suspend_port +EXPORT_SYMBOL vmlinux 0x3d1f86d6 idr_remove_all +EXPORT_SYMBOL vmlinux 0x3d225b36 blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0x3d6402ae arp_find +EXPORT_SYMBOL vmlinux 0x3d693970 clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0x3da171f9 pci_mem_start +EXPORT_SYMBOL vmlinux 0x3da5eb6d kfifo_alloc +EXPORT_SYMBOL vmlinux 0x3daac7da register_atm_ioctl +EXPORT_SYMBOL vmlinux 0x3db22d90 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0x3dde240c nf_register_hooks +EXPORT_SYMBOL vmlinux 0x3e0bb6e1 tcp_poll +EXPORT_SYMBOL vmlinux 0x3e12025f dquot_free_space +EXPORT_SYMBOL vmlinux 0x3e19ba9e sk_reset_timer +EXPORT_SYMBOL vmlinux 0x3e1f073d wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x3e219de6 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x3e2427a1 acpi_check_region +EXPORT_SYMBOL vmlinux 0x3e2ae3a8 acpi_release_global_lock +EXPORT_SYMBOL vmlinux 0x3e2cf854 bio_put +EXPORT_SYMBOL vmlinux 0x3e3288b7 generic_permission +EXPORT_SYMBOL vmlinux 0x3e45e9ff register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x3e680037 bio_pair_release +EXPORT_SYMBOL vmlinux 0x3e6e5eac blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x3e9ea38b __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0x3ea1601f input_free_device +EXPORT_SYMBOL vmlinux 0x3ed63055 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x3ed9c1d2 d_genocide +EXPORT_SYMBOL vmlinux 0x3f03e43e neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x3f044b3b generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x3f0546a8 ioread32_rep +EXPORT_SYMBOL vmlinux 0x3f1899f1 up +EXPORT_SYMBOL vmlinux 0x3f39b162 up_write +EXPORT_SYMBOL vmlinux 0x3f39c4ec xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0x3f3c1abd new_inode +EXPORT_SYMBOL vmlinux 0x3f4547a7 put_unused_fd +EXPORT_SYMBOL vmlinux 0x3f63a5c4 vfs_readlink +EXPORT_SYMBOL vmlinux 0x3fbcddc3 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x3fbeafa0 cpufreq_gov_performance +EXPORT_SYMBOL vmlinux 0x3fec048f sg_next +EXPORT_SYMBOL vmlinux 0x3ff62317 local_bh_disable +EXPORT_SYMBOL vmlinux 0x3ff62477 dev_mc_sync +EXPORT_SYMBOL vmlinux 0x3fff4c1c save_mount_options +EXPORT_SYMBOL vmlinux 0x40576b02 acpi_get_physical_device +EXPORT_SYMBOL vmlinux 0x4059792f print_hex_dump +EXPORT_SYMBOL vmlinux 0x405c1144 get_seconds +EXPORT_SYMBOL vmlinux 0x408d862a xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0x409873e3 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x40ba7837 blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0x40c89d46 acpi_get_table_by_index +EXPORT_SYMBOL vmlinux 0x40f1148d blk_unplug +EXPORT_SYMBOL vmlinux 0x4108e69a fb_match_mode +EXPORT_SYMBOL vmlinux 0x41482d8b strndup_user +EXPORT_SYMBOL vmlinux 0x4185cf4b radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x4188d439 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x4193e4c0 pci_bus_read_config_dword +EXPORT_SYMBOL vmlinux 0x419c1f6c set_binfmt +EXPORT_SYMBOL vmlinux 0x41a9c68d _spin_trylock_bh +EXPORT_SYMBOL vmlinux 0x41ccc474 security_req_classify_flow +EXPORT_SYMBOL vmlinux 0x41e97da1 register_sysctl_table +EXPORT_SYMBOL vmlinux 0x42111c06 have_submounts +EXPORT_SYMBOL vmlinux 0x4211c3c1 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x42224298 sscanf +EXPORT_SYMBOL vmlinux 0x42288c0b path_lookup +EXPORT_SYMBOL vmlinux 0x422c05d0 acpi_get_data +EXPORT_SYMBOL vmlinux 0x424cb1dd tcf_action_dump_1 +EXPORT_SYMBOL vmlinux 0x426ef71b inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0x4274086b sock_no_shutdown +EXPORT_SYMBOL vmlinux 0x4284d71f kmem_cache_name +EXPORT_SYMBOL vmlinux 0x4286824a udp_prot +EXPORT_SYMBOL vmlinux 0x4291b59f pci_bus_write_config_dword +EXPORT_SYMBOL vmlinux 0x4292364c schedule +EXPORT_SYMBOL vmlinux 0x42c23d55 generic_make_request +EXPORT_SYMBOL vmlinux 0x42f7e6f0 pci_get_subsys +EXPORT_SYMBOL vmlinux 0x4302d0eb free_pages +EXPORT_SYMBOL vmlinux 0x43385ad9 acpi_pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x4343c7dc fd_install +EXPORT_SYMBOL vmlinux 0x434f15f9 tcp_make_synack +EXPORT_SYMBOL vmlinux 0x434fa55c release_console_sem +EXPORT_SYMBOL vmlinux 0x435b566d _spin_unlock +EXPORT_SYMBOL vmlinux 0x436c2179 iowrite32 +EXPORT_SYMBOL vmlinux 0x436d7291 proc_symlink +EXPORT_SYMBOL vmlinux 0x43b40de7 kunmap_atomic +EXPORT_SYMBOL vmlinux 0x43bdd372 request_resource +EXPORT_SYMBOL vmlinux 0x440e2ef8 security_sb_set_mnt_opts +EXPORT_SYMBOL vmlinux 0x44161c19 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x44314efb radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x444779c4 nla_find +EXPORT_SYMBOL vmlinux 0x446f888b simple_empty +EXPORT_SYMBOL vmlinux 0x44a2b544 skb_copy_expand +EXPORT_SYMBOL vmlinux 0x44aaf30f tsc_khz +EXPORT_SYMBOL vmlinux 0x44b74265 cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0x44b911c3 rb_replace_node +EXPORT_SYMBOL vmlinux 0x44df810b filemap_fault +EXPORT_SYMBOL vmlinux 0x44f6bc33 start_tty +EXPORT_SYMBOL vmlinux 0x450d752c sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0x4550ba8a register_cpu_notifier +EXPORT_SYMBOL vmlinux 0x455fd57d acpi_set_register +EXPORT_SYMBOL vmlinux 0x457310a3 sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x45a8d997 blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0x45bb123e try_to_del_timer_sync +EXPORT_SYMBOL vmlinux 0x45c0aa18 tcp_prot +EXPORT_SYMBOL vmlinux 0x45d11c43 down_interruptible +EXPORT_SYMBOL vmlinux 0x461f5c6e simple_sync_file +EXPORT_SYMBOL vmlinux 0x462a2e75 match_strlcpy +EXPORT_SYMBOL vmlinux 0x463f04f0 sockfd_lookup +EXPORT_SYMBOL vmlinux 0x466c14a7 __delay +EXPORT_SYMBOL vmlinux 0x4671e6ee sock_no_mmap +EXPORT_SYMBOL vmlinux 0x468fda1f blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0x46d804f4 serio_unregister_driver +EXPORT_SYMBOL vmlinux 0x472d2a9a radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x47327f34 netif_device_detach +EXPORT_SYMBOL vmlinux 0x473d6f87 tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x4742b3c9 skb_trim +EXPORT_SYMBOL vmlinux 0x475100c2 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x475f010b acpi_purge_cached_objects +EXPORT_SYMBOL vmlinux 0x476f7137 __break_lease +EXPORT_SYMBOL vmlinux 0x478d10b2 ht_destroy_irq +EXPORT_SYMBOL vmlinux 0x47939e0d __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x479c3c86 find_next_zero_bit +EXPORT_SYMBOL vmlinux 0x47b9d512 bdput +EXPORT_SYMBOL vmlinux 0x47c62d70 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x481cb9ab acpi_enter_sleep_state_prep +EXPORT_SYMBOL vmlinux 0x481e387d send_sig +EXPORT_SYMBOL vmlinux 0x4859b8bb rtc_year_days +EXPORT_SYMBOL vmlinux 0x486b6407 hweight64 +EXPORT_SYMBOL vmlinux 0x487baf5b sock_i_uid +EXPORT_SYMBOL vmlinux 0x488c320e sock_release +EXPORT_SYMBOL vmlinux 0x48a3a4e3 block_write_full_page +EXPORT_SYMBOL vmlinux 0x48bc95d1 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0x493e25e1 udp_hash +EXPORT_SYMBOL vmlinux 0x49541336 uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x49603fb8 security_sb_copy_data +EXPORT_SYMBOL vmlinux 0x498c98a2 pci_enable_device_mem +EXPORT_SYMBOL vmlinux 0x49d6751b mca_device_claimed +EXPORT_SYMBOL vmlinux 0x49da9a9a _read_unlock_bh +EXPORT_SYMBOL vmlinux 0x49db34fd __getblk +EXPORT_SYMBOL vmlinux 0x49fa7591 __elv_add_request +EXPORT_SYMBOL vmlinux 0x4a16b3d4 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0x4a358252 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x4a519b9f tcp_proc_register +EXPORT_SYMBOL vmlinux 0x4a545eaf llc_mac_hdr_init +EXPORT_SYMBOL vmlinux 0x4a7e7337 bio_integrity_get_tag +EXPORT_SYMBOL vmlinux 0x4a90ff06 acpi_match_device_ids +EXPORT_SYMBOL vmlinux 0x4a971ec7 radix_tree_delete +EXPORT_SYMBOL vmlinux 0x4af04b5d mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x4b07e779 _spin_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x4b2f14b4 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x4b2f1ad7 skb_free_datagram +EXPORT_SYMBOL vmlinux 0x4b33b1fe ip_getsockopt +EXPORT_SYMBOL vmlinux 0x4b34fbf5 block_all_signals +EXPORT_SYMBOL vmlinux 0x4b77c0d1 tcf_hash_insert +EXPORT_SYMBOL vmlinux 0x4bbc3e5f pm_flags +EXPORT_SYMBOL vmlinux 0x4c073a95 __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0x4c1182cb bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x4c3af445 __request_region +EXPORT_SYMBOL vmlinux 0x4c9f691e tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0x4ca9023a gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0x4cbbd171 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x4cc7c4a4 pci_choose_state +EXPORT_SYMBOL vmlinux 0x4cd5b691 pci_dev_get +EXPORT_SYMBOL vmlinux 0x4d2dc830 acpi_get_object_info +EXPORT_SYMBOL vmlinux 0x4d383e29 skb_queue_tail +EXPORT_SYMBOL vmlinux 0x4d3c153f sigprocmask +EXPORT_SYMBOL vmlinux 0x4d5f3b0d lease_get_mtime +EXPORT_SYMBOL vmlinux 0x4d64d9ef skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0x4dc510ff idr_for_each +EXPORT_SYMBOL vmlinux 0x4dd53cd5 input_allocate_device +EXPORT_SYMBOL vmlinux 0x4ddc4b9f utf8_mbtowc +EXPORT_SYMBOL vmlinux 0x4ddd16d9 truncate_inode_pages +EXPORT_SYMBOL vmlinux 0x4df119fa __bitmap_parse +EXPORT_SYMBOL vmlinux 0x4e0eddd4 tcp_child_process +EXPORT_SYMBOL vmlinux 0x4e100f60 _spin_unlock_irq +EXPORT_SYMBOL vmlinux 0x4e3567f7 match_int +EXPORT_SYMBOL vmlinux 0x4e4ceadd netif_carrier_on +EXPORT_SYMBOL vmlinux 0x4e621c85 neigh_event_ns +EXPORT_SYMBOL vmlinux 0x4e6e8ea7 fg_console +EXPORT_SYMBOL vmlinux 0x4e803053 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0x4e830a3e strnicmp +EXPORT_SYMBOL vmlinux 0x4e8ee14f elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0x4edac99d input_flush_device +EXPORT_SYMBOL vmlinux 0x4f0124c2 dput +EXPORT_SYMBOL vmlinux 0x4f4e2e69 simple_transaction_release +EXPORT_SYMBOL vmlinux 0x4f5438c1 idle_halt +EXPORT_SYMBOL vmlinux 0x4f5ee8b7 read_cache_page +EXPORT_SYMBOL vmlinux 0x4f7fc44c audit_log_format +EXPORT_SYMBOL vmlinux 0x4f9a7349 xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0x4f9e5432 uart_remove_one_port +EXPORT_SYMBOL vmlinux 0x4fb02059 blk_rq_init +EXPORT_SYMBOL vmlinux 0x4fb0730d vm_insert_mixed +EXPORT_SYMBOL vmlinux 0x4fd853db pci_pme_active +EXPORT_SYMBOL vmlinux 0x4fdee897 i8042_command +EXPORT_SYMBOL vmlinux 0x4ffedae2 __lock_page +EXPORT_SYMBOL vmlinux 0x50211ee3 tcp_free_md5sig_pool +EXPORT_SYMBOL vmlinux 0x50351572 pnpbios_protocol +EXPORT_SYMBOL vmlinux 0x5035cdc4 pci_dev_driver +EXPORT_SYMBOL vmlinux 0x5058cdc6 neigh_parms_release +EXPORT_SYMBOL vmlinux 0x50945c5f write_one_page +EXPORT_SYMBOL vmlinux 0x50a57c5b dev_set_allmulti +EXPORT_SYMBOL vmlinux 0x50e62287 neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x50f76eee inet_sendmsg +EXPORT_SYMBOL vmlinux 0x5118c382 secure_dccp_sequence_number +EXPORT_SYMBOL vmlinux 0x51220aa7 blk_verify_command +EXPORT_SYMBOL vmlinux 0x51272cf9 bio_hw_segments +EXPORT_SYMBOL vmlinux 0x5152e605 memcmp +EXPORT_SYMBOL vmlinux 0x5163b277 fb_show_logo +EXPORT_SYMBOL vmlinux 0x518eb764 per_cpu__cpu_number +EXPORT_SYMBOL vmlinux 0x5195ffe8 inet_stream_connect +EXPORT_SYMBOL vmlinux 0x51cca00b nla_reserve +EXPORT_SYMBOL vmlinux 0x51d12d4e acpi_pci_disabled +EXPORT_SYMBOL vmlinux 0x51d7a776 acpi_detach_data +EXPORT_SYMBOL vmlinux 0x51e77b5c ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0x51ef33b8 kstrndup +EXPORT_SYMBOL vmlinux 0x51fb84ae __rta_fill +EXPORT_SYMBOL vmlinux 0x52026cdf security_sb_parse_opts_str +EXPORT_SYMBOL vmlinux 0x5240833f skb_under_panic +EXPORT_SYMBOL vmlinux 0x5287f212 __find_get_block +EXPORT_SYMBOL vmlinux 0x528c709d simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x5295b8d6 ip_route_me_harder +EXPORT_SYMBOL vmlinux 0x52a58c24 ifla_policy +EXPORT_SYMBOL vmlinux 0x52c6b336 vfs_set_dqblk +EXPORT_SYMBOL vmlinux 0x52d7b2fd llc_sap_list +EXPORT_SYMBOL vmlinux 0x52e24296 key_validate +EXPORT_SYMBOL vmlinux 0x530b1e98 pm_suspend +EXPORT_SYMBOL vmlinux 0x532f2924 param_get_byte +EXPORT_SYMBOL vmlinux 0x53326531 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x5366a56e nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x5367fe98 generic_setlease +EXPORT_SYMBOL vmlinux 0x537ed137 nf_setsockopt +EXPORT_SYMBOL vmlinux 0x53c0767c sk_chk_filter +EXPORT_SYMBOL vmlinux 0x53e3acce lease_modify +EXPORT_SYMBOL vmlinux 0x53efb4cf set_anon_super +EXPORT_SYMBOL vmlinux 0x54116b78 netlink_ack +EXPORT_SYMBOL vmlinux 0x54162dc5 __f_setown +EXPORT_SYMBOL vmlinux 0x542356df tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0x54290dc9 nla_validate +EXPORT_SYMBOL vmlinux 0x5438c3ac inet_shutdown +EXPORT_SYMBOL vmlinux 0x5448ff10 tcf_exts_destroy +EXPORT_SYMBOL vmlinux 0x54935666 acpi_os_read_port +EXPORT_SYMBOL vmlinux 0x54b81541 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0x54d401ed ilookup +EXPORT_SYMBOL vmlinux 0x54e6fcdd net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x553b3565 dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x553f9dd3 down_read_trylock +EXPORT_SYMBOL vmlinux 0x559497ca neigh_create +EXPORT_SYMBOL vmlinux 0x5594be03 bitmap_remap +EXPORT_SYMBOL vmlinux 0x55ba9252 udp_proc_register +EXPORT_SYMBOL vmlinux 0x5600904f fb_get_color_depth +EXPORT_SYMBOL vmlinux 0x561b0089 proc_dointvec +EXPORT_SYMBOL vmlinux 0x561ea146 simple_write_end +EXPORT_SYMBOL vmlinux 0x562ec9b2 __nla_put +EXPORT_SYMBOL vmlinux 0x5635a60a vmalloc_user +EXPORT_SYMBOL vmlinux 0x563952a3 kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0x563b1ec6 vm_insert_page +EXPORT_SYMBOL vmlinux 0x5648c740 dst_release +EXPORT_SYMBOL vmlinux 0x56f494e0 smp_call_function +EXPORT_SYMBOL vmlinux 0x572e85d4 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x57759316 blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x5777aff1 sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0x577cc638 mutex_unlock +EXPORT_SYMBOL vmlinux 0x57a54070 blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0x57a6504e vsnprintf +EXPORT_SYMBOL vmlinux 0x582ee598 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0x5838f6c9 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x584738f9 rdmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x584bcc61 prepare_binprm +EXPORT_SYMBOL vmlinux 0x5857b225 ioread16_rep +EXPORT_SYMBOL vmlinux 0x58586d95 set_bdi_congested +EXPORT_SYMBOL vmlinux 0x58919c5e pagevec_lookup +EXPORT_SYMBOL vmlinux 0x58d05802 udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0x58fef6f8 ist_info +EXPORT_SYMBOL vmlinux 0x5911f22e xfrm_state_add +EXPORT_SYMBOL vmlinux 0x5934392b fb_register_client +EXPORT_SYMBOL vmlinux 0x594bf15b ioport_map +EXPORT_SYMBOL vmlinux 0x594d2b1a dma_pool_destroy +EXPORT_SYMBOL vmlinux 0x59c8e49e set_pages_uc +EXPORT_SYMBOL vmlinux 0x59d1cc4f framebuffer_release +EXPORT_SYMBOL vmlinux 0x59d696b6 register_module_notifier +EXPORT_SYMBOL vmlinux 0x59d83a5f pcim_iomap +EXPORT_SYMBOL vmlinux 0x59ef0012 page_follow_link_light +EXPORT_SYMBOL vmlinux 0x59fada1a tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0x5a203af2 try_to_free_buffers +EXPORT_SYMBOL vmlinux 0x5a2273df blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x5a42deb0 __pci_register_driver +EXPORT_SYMBOL vmlinux 0x5a4896a8 __put_user_2 +EXPORT_SYMBOL vmlinux 0x5a744b86 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x5a9926ad get_fs_type +EXPORT_SYMBOL vmlinux 0x5ab70adb dev_driver_string +EXPORT_SYMBOL vmlinux 0x5ac376a5 acpi_install_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x5b00cd93 call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0x5b04634f pnp_find_card +EXPORT_SYMBOL vmlinux 0x5b19634d div_s64_rem +EXPORT_SYMBOL vmlinux 0x5b3764f2 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0x5b3cd88f file_remove_suid +EXPORT_SYMBOL vmlinux 0x5b51c6a7 acpi_walk_resources +EXPORT_SYMBOL vmlinux 0x5b8ff2bc blk_remove_plug +EXPORT_SYMBOL vmlinux 0x5bccbe37 xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0x5c095371 atm_alloc_charge +EXPORT_SYMBOL vmlinux 0x5c320339 filemap_fdatawait +EXPORT_SYMBOL vmlinux 0x5c335a6e blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0x5c3ca0a7 netif_carrier_off +EXPORT_SYMBOL vmlinux 0x5c68705b mca_read_pos +EXPORT_SYMBOL vmlinux 0x5c7a4c8f neigh_lookup +EXPORT_SYMBOL vmlinux 0x5c9aa822 devm_ioport_map +EXPORT_SYMBOL vmlinux 0x5cee23e5 kobject_init +EXPORT_SYMBOL vmlinux 0x5ceeee5a dma_pool_free +EXPORT_SYMBOL vmlinux 0x5d18fb94 pcie_port_service_unregister +EXPORT_SYMBOL vmlinux 0x5d1e7f3e input_register_device +EXPORT_SYMBOL vmlinux 0x5d31c62e kmap_atomic +EXPORT_SYMBOL vmlinux 0x5d73b5f8 km_waitq +EXPORT_SYMBOL vmlinux 0x5d782dbd seq_read +EXPORT_SYMBOL vmlinux 0x5d92f21f pci_disable_device +EXPORT_SYMBOL vmlinux 0x5d991093 inet_frags_fini +EXPORT_SYMBOL vmlinux 0x5dbcfa4f boot_cpu_physical_apicid +EXPORT_SYMBOL vmlinux 0x5dcdb878 igrab +EXPORT_SYMBOL vmlinux 0x5ddd65c7 pci_set_mwi +EXPORT_SYMBOL vmlinux 0x5e35ddbb nobh_write_begin +EXPORT_SYMBOL vmlinux 0x5e79ebec gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x5ea520c5 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x5eab1c90 sysctl_string +EXPORT_SYMBOL vmlinux 0x5ed040b0 pm_set_vt_switch +EXPORT_SYMBOL vmlinux 0x5edd0762 bin2bcd +EXPORT_SYMBOL vmlinux 0x5f19d313 cont_write_begin +EXPORT_SYMBOL vmlinux 0x5f1bd579 mca_find_adapter +EXPORT_SYMBOL vmlinux 0x5f635081 submit_bh +EXPORT_SYMBOL vmlinux 0x5f6836a6 thaw_bdev +EXPORT_SYMBOL vmlinux 0x5f7e7265 unregister_binfmt +EXPORT_SYMBOL vmlinux 0x5f8af9a3 pcix_get_mmrbc +EXPORT_SYMBOL vmlinux 0x5f8fdc81 blk_integrity_compare +EXPORT_SYMBOL vmlinux 0x5fec014a mpage_readpage +EXPORT_SYMBOL vmlinux 0x600683d3 do_unblank_screen +EXPORT_SYMBOL vmlinux 0x600d46c5 netdev_state_change +EXPORT_SYMBOL vmlinux 0x60400b7f pv_lock_ops +EXPORT_SYMBOL vmlinux 0x607c31e8 get_disk +EXPORT_SYMBOL vmlinux 0x608c2831 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x609f1c7e synchronize_net +EXPORT_SYMBOL vmlinux 0x60a32ea9 pm_power_off +EXPORT_SYMBOL vmlinux 0x60c71296 posix_lock_file +EXPORT_SYMBOL vmlinux 0x60dabe72 blk_insert_request +EXPORT_SYMBOL vmlinux 0x6111e1bc init_timer +EXPORT_SYMBOL vmlinux 0x612390ad netpoll_set_trap +EXPORT_SYMBOL vmlinux 0x615221f3 generic_osync_inode +EXPORT_SYMBOL vmlinux 0x6164bef4 seq_lseek +EXPORT_SYMBOL vmlinux 0x618d8299 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x61aae7ac call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0x61b7b126 simple_strtoull +EXPORT_SYMBOL vmlinux 0x61c6449d bio_endio +EXPORT_SYMBOL vmlinux 0x61cfc09f sock_recvmsg +EXPORT_SYMBOL vmlinux 0x62049256 acpi_disable +EXPORT_SYMBOL vmlinux 0x6232cf62 may_umount +EXPORT_SYMBOL vmlinux 0x6237f6b5 acpi_enable_event +EXPORT_SYMBOL vmlinux 0x6241a2ab __copy_from_user_ll_nocache +EXPORT_SYMBOL vmlinux 0x6241fd2c acpi_install_address_space_handler +EXPORT_SYMBOL vmlinux 0x62737e1d sock_unregister +EXPORT_SYMBOL vmlinux 0x62806459 end_dequeued_request +EXPORT_SYMBOL vmlinux 0x62827bec security_secctx_to_secid +EXPORT_SYMBOL vmlinux 0x62b09f37 pcim_iounmap_regions +EXPORT_SYMBOL vmlinux 0x62c729ec input_set_keycode +EXPORT_SYMBOL vmlinux 0x62dc139d __grab_cache_page +EXPORT_SYMBOL vmlinux 0x62e1ce66 pci_fixup_device +EXPORT_SYMBOL vmlinux 0x63114ace skb_insert +EXPORT_SYMBOL vmlinux 0x631267ba ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0x631eeaf8 open_by_devnum +EXPORT_SYMBOL vmlinux 0x632999c8 dquot_alloc_space +EXPORT_SYMBOL vmlinux 0x63498c20 kill_fasync +EXPORT_SYMBOL vmlinux 0x63529c94 blkdev_get +EXPORT_SYMBOL vmlinux 0x636a5691 acpi_register_ioapic +EXPORT_SYMBOL vmlinux 0x638676ba dma_release_declared_memory +EXPORT_SYMBOL vmlinux 0x639ce954 bio_integrity_endio +EXPORT_SYMBOL vmlinux 0x63da8048 tcp_read_sock +EXPORT_SYMBOL vmlinux 0x63ecad53 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x63ed4f65 ioremap_cache +EXPORT_SYMBOL vmlinux 0x63eea69a vfs_quota_on +EXPORT_SYMBOL vmlinux 0x6403e338 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x641275c3 load_nls_default +EXPORT_SYMBOL vmlinux 0x642e54ac __wake_up +EXPORT_SYMBOL vmlinux 0x644f4e23 skb_seq_read +EXPORT_SYMBOL vmlinux 0x6451294b posix_acl_valid +EXPORT_SYMBOL vmlinux 0x6458234e fb_is_primary_device +EXPORT_SYMBOL vmlinux 0x6460f8e0 fsync_bdev +EXPORT_SYMBOL vmlinux 0x6466a1e6 mempool_alloc +EXPORT_SYMBOL vmlinux 0x6478134c ec_burst_enable +EXPORT_SYMBOL vmlinux 0x647c26ed fb_get_mode +EXPORT_SYMBOL vmlinux 0x64868efe xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x64999478 congestion_wait +EXPORT_SYMBOL vmlinux 0x649baac9 dst_alloc +EXPORT_SYMBOL vmlinux 0x649e9b4c search_binary_handler +EXPORT_SYMBOL vmlinux 0x64bd72df bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x64cd5d16 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x64f0adc4 __blk_run_queue +EXPORT_SYMBOL vmlinux 0x650128e7 br_fdb_get_hook +EXPORT_SYMBOL vmlinux 0x650fb346 add_wait_queue +EXPORT_SYMBOL vmlinux 0x65408378 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x65414e67 dev_valid_name +EXPORT_SYMBOL vmlinux 0x655090f2 vmtruncate +EXPORT_SYMBOL vmlinux 0x65532686 simple_set_mnt +EXPORT_SYMBOL vmlinux 0x656ce83d filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0x6581a3d4 blk_plug_device +EXPORT_SYMBOL vmlinux 0x65821c22 find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0x6584d7d2 eisa_driver_unregister +EXPORT_SYMBOL vmlinux 0x6596cb6b dma_pool_create +EXPORT_SYMBOL vmlinux 0x6596f162 boot_cpu_data +EXPORT_SYMBOL vmlinux 0x659d9a47 neigh_connected_output +EXPORT_SYMBOL vmlinux 0x65cf7cc5 pci_find_slot +EXPORT_SYMBOL vmlinux 0x65db980c generic_show_options +EXPORT_SYMBOL vmlinux 0x66292211 llc_sap_find +EXPORT_SYMBOL vmlinux 0x665187f5 blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0x668da8d5 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x66b36209 kmem_cache_size +EXPORT_SYMBOL vmlinux 0x66f74240 pfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0x671309ef sk_stream_write_space +EXPORT_SYMBOL vmlinux 0x671849e1 skb_checksum +EXPORT_SYMBOL vmlinux 0x67230335 input_unregister_handler +EXPORT_SYMBOL vmlinux 0x6729d3df __get_user_4 +EXPORT_SYMBOL vmlinux 0x672fbcab acpi_lock_battery_dir +EXPORT_SYMBOL vmlinux 0x6730a642 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0x675a3383 kthread_create +EXPORT_SYMBOL vmlinux 0x6770827f security_task_getsecid +EXPORT_SYMBOL vmlinux 0x677ba3f0 xfrm_register_km +EXPORT_SYMBOL vmlinux 0x67b27ec1 tty_std_termios +EXPORT_SYMBOL vmlinux 0x67e71b77 __mutex_init +EXPORT_SYMBOL vmlinux 0x67f2784d read_cache_page_async +EXPORT_SYMBOL vmlinux 0x67f7318a kset_register +EXPORT_SYMBOL vmlinux 0x67fc7fbd devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0x68b60aa2 tc_classify_compat +EXPORT_SYMBOL vmlinux 0x68e18c1c kernel_recvmsg +EXPORT_SYMBOL vmlinux 0x690d442b simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x6912150f sysctl_jiffies +EXPORT_SYMBOL vmlinux 0x6962c0f8 ip_dev_find +EXPORT_SYMBOL vmlinux 0x6971447a rtc_month_days +EXPORT_SYMBOL vmlinux 0x6973e034 xfrm_init_state +EXPORT_SYMBOL vmlinux 0x6976c490 km_state_expired +EXPORT_SYMBOL vmlinux 0x69806cab mca_bus_type +EXPORT_SYMBOL vmlinux 0x69927dff try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x69a0ca7d iowrite16be +EXPORT_SYMBOL vmlinux 0x69a4632c register_netdevice +EXPORT_SYMBOL vmlinux 0x6a037cf1 mempool_kfree +EXPORT_SYMBOL vmlinux 0x6a27bfce csum_partial_copy_generic +EXPORT_SYMBOL vmlinux 0x6a3d470e thermal_zone_device_register +EXPORT_SYMBOL vmlinux 0x6a47571d __set_personality +EXPORT_SYMBOL vmlinux 0x6a6cc4bb key_payload_reserve +EXPORT_SYMBOL vmlinux 0x6a9e96ab kernel_read +EXPORT_SYMBOL vmlinux 0x6a9f201d set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x6aae09de gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0x6ac83d9d skb_make_writable +EXPORT_SYMBOL vmlinux 0x6acb973d iowrite32be +EXPORT_SYMBOL vmlinux 0x6add5c9a dmi_find_device +EXPORT_SYMBOL vmlinux 0x6af86b31 pci_bus_alloc_resource +EXPORT_SYMBOL vmlinux 0x6b1b67d3 __bdevname +EXPORT_SYMBOL vmlinux 0x6b2dc060 dump_stack +EXPORT_SYMBOL vmlinux 0x6b2dd8fe blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0x6b35cf5e inet_frag_kill +EXPORT_SYMBOL vmlinux 0x6b5de58c cfb_copyarea +EXPORT_SYMBOL vmlinux 0x6b8c2ea8 xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x6b937ffb mca_mark_as_used +EXPORT_SYMBOL vmlinux 0x6b991652 ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x6b9a9719 ps2_drain +EXPORT_SYMBOL vmlinux 0x6b9b88f3 sleep_on +EXPORT_SYMBOL vmlinux 0x6bafbced mod_timer +EXPORT_SYMBOL vmlinux 0x6bbe98c4 init_file +EXPORT_SYMBOL vmlinux 0x6bdcfd99 qdisc_class_hash_remove +EXPORT_SYMBOL vmlinux 0x6bf95612 fifo_create_dflt +EXPORT_SYMBOL vmlinux 0x6bfe4d49 kernel_accept +EXPORT_SYMBOL vmlinux 0x6c1150ca vfs_mknod +EXPORT_SYMBOL vmlinux 0x6c1ce5ce strcspn +EXPORT_SYMBOL vmlinux 0x6c28a2dd ll_rw_block +EXPORT_SYMBOL vmlinux 0x6c2e3320 strncmp +EXPORT_SYMBOL vmlinux 0x6c389761 acpi_bus_get_private_data +EXPORT_SYMBOL vmlinux 0x6c61ce70 num_registered_fb +EXPORT_SYMBOL vmlinux 0x6c702af7 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x6c918766 llc_sap_open +EXPORT_SYMBOL vmlinux 0x6cb2f5d4 tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0x6ccf405f tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x6cd9f57e mca_device_read_stored_pos +EXPORT_SYMBOL vmlinux 0x6cdc5c6b nla_strlcpy +EXPORT_SYMBOL vmlinux 0x6cf07914 zero_fill_bio +EXPORT_SYMBOL vmlinux 0x6cf18467 pci_target_state +EXPORT_SYMBOL vmlinux 0x6cfb0b0e tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0x6d0da34c param_get_short +EXPORT_SYMBOL vmlinux 0x6d10832b key_put +EXPORT_SYMBOL vmlinux 0x6d1ced27 vcc_sklist_lock +EXPORT_SYMBOL vmlinux 0x6d27ef64 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x6d288375 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x6d294e43 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x6d340f64 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x6d717971 proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x6d9e82aa pv_mmu_ops +EXPORT_SYMBOL vmlinux 0x6dc0c24b complete_and_exit +EXPORT_SYMBOL vmlinux 0x6dec47d7 request_firmware_nowait +EXPORT_SYMBOL vmlinux 0x6dee7be5 dump_fpu +EXPORT_SYMBOL vmlinux 0x6def2db2 half_md4_transform +EXPORT_SYMBOL vmlinux 0x6e07a54e acpi_get_gpe_status +EXPORT_SYMBOL vmlinux 0x6e1a4bbb udp_hash_lock +EXPORT_SYMBOL vmlinux 0x6e429c29 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0x6e440b58 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x6e720ff2 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x6e9dd606 __symbol_put +EXPORT_SYMBOL vmlinux 0x6ead242b cond_resched_lock +EXPORT_SYMBOL vmlinux 0x6ef98516 pci_pme_capable +EXPORT_SYMBOL vmlinux 0x6f2c515a __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x6fa9e95f pci_scan_single_device +EXPORT_SYMBOL vmlinux 0x6facd6f0 inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x6fb767e5 input_get_keycode +EXPORT_SYMBOL vmlinux 0x6fcb87a1 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x6fdb9c87 pci_set_dma_mask +EXPORT_SYMBOL vmlinux 0x7008a9b7 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x701d0ebd snprintf +EXPORT_SYMBOL vmlinux 0x703912c2 dma_ops +EXPORT_SYMBOL vmlinux 0x70461a22 key_revoke +EXPORT_SYMBOL vmlinux 0x7052386f __ip_select_ident +EXPORT_SYMBOL vmlinux 0x7054a3e4 request_dma +EXPORT_SYMBOL vmlinux 0x7065b920 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0x7073add6 __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0x70885c1f del_gendisk +EXPORT_SYMBOL vmlinux 0x70943430 __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x70b4c3a3 sk_filter +EXPORT_SYMBOL vmlinux 0x70cd195d tty_register_driver +EXPORT_SYMBOL vmlinux 0x70d1f8f3 strncat +EXPORT_SYMBOL vmlinux 0x70d330d2 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x70d8ab82 acpi_acquire_global_lock +EXPORT_SYMBOL vmlinux 0x7129e5f8 hex_asc +EXPORT_SYMBOL vmlinux 0x712aa29b _spin_lock_irqsave +EXPORT_SYMBOL vmlinux 0x71356fba remove_wait_queue +EXPORT_SYMBOL vmlinux 0x71631abd xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0x7171121c overflowgid +EXPORT_SYMBOL vmlinux 0x71a50dbc register_blkdev +EXPORT_SYMBOL vmlinux 0x71befdb9 ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0x71e94cda bdev_read_only +EXPORT_SYMBOL vmlinux 0x72270e35 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x72b243d4 free_dma +EXPORT_SYMBOL vmlinux 0x72b2aac3 nf_unregister_sockopt +EXPORT_SYMBOL vmlinux 0x72bf2140 mtrr_add +EXPORT_SYMBOL vmlinux 0x72c1153e bio_phys_segments +EXPORT_SYMBOL vmlinux 0x73073d4d ps2_sendbyte +EXPORT_SYMBOL vmlinux 0x73293e28 filp_open +EXPORT_SYMBOL vmlinux 0x7333cd14 sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x735a0bd5 native_io_delay +EXPORT_SYMBOL vmlinux 0x73713ca5 d_invalidate +EXPORT_SYMBOL vmlinux 0x73734eed ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0x7373bf16 neigh_seq_stop +EXPORT_SYMBOL vmlinux 0x738803e6 strnlen +EXPORT_SYMBOL vmlinux 0x7389c9a8 acpi_bus_get_power +EXPORT_SYMBOL vmlinux 0x73e20c1c strlcpy +EXPORT_SYMBOL vmlinux 0x7404cf59 iw_handler_set_spy +EXPORT_SYMBOL vmlinux 0x740a1b95 reserve_evntsel_nmi +EXPORT_SYMBOL vmlinux 0x7413793a EISA_bus +EXPORT_SYMBOL vmlinux 0x74181a55 sb_min_blocksize +EXPORT_SYMBOL vmlinux 0x74183294 get_super +EXPORT_SYMBOL vmlinux 0x74202777 ioremap_prot +EXPORT_SYMBOL vmlinux 0x7428c104 pci_get_class +EXPORT_SYMBOL vmlinux 0x7485e15e unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x748caf40 down +EXPORT_SYMBOL vmlinux 0x7490d8a8 atm_proc_root +EXPORT_SYMBOL vmlinux 0x749e586e invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0x74a0f33b mca_device_set_name +EXPORT_SYMBOL vmlinux 0x74caef85 alloc_trdev +EXPORT_SYMBOL vmlinux 0x74cc1cbe unregister_cpu_notifier +EXPORT_SYMBOL vmlinux 0x74cc238d current_kernel_time +EXPORT_SYMBOL vmlinux 0x74f1cdec ht_create_irq +EXPORT_SYMBOL vmlinux 0x75271716 save_processor_state +EXPORT_SYMBOL vmlinux 0x753c1911 cdev_alloc +EXPORT_SYMBOL vmlinux 0x75566739 complete_request_key +EXPORT_SYMBOL vmlinux 0x7561dd3e follow_down +EXPORT_SYMBOL vmlinux 0x75764157 udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x7579f09b tcp_parse_options +EXPORT_SYMBOL vmlinux 0x758a15ba register_key_type +EXPORT_SYMBOL vmlinux 0x75986126 mca_unregister_driver +EXPORT_SYMBOL vmlinux 0x75c6ab7d call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0x75d7b496 bio_map_user +EXPORT_SYMBOL vmlinux 0x760913cb generic_delete_inode +EXPORT_SYMBOL vmlinux 0x760a0f4f yield +EXPORT_SYMBOL vmlinux 0x760b437a unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x76241aa2 netlink_broadcast +EXPORT_SYMBOL vmlinux 0x767ddb02 set_memory_wc +EXPORT_SYMBOL vmlinux 0x76845676 thermal_cooling_device_register +EXPORT_SYMBOL vmlinux 0x76889d0f skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x76bf656d __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x76d3cd60 laptop_mode +EXPORT_SYMBOL vmlinux 0x76f3f8a5 num_k8_northbridges +EXPORT_SYMBOL vmlinux 0x76fb47e8 unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0x76fb5dcf dev_remove_pack +EXPORT_SYMBOL vmlinux 0x770a0036 isapnp_cfg_begin +EXPORT_SYMBOL vmlinux 0x7758ccfa skb_append +EXPORT_SYMBOL vmlinux 0x77687d0e path_permission +EXPORT_SYMBOL vmlinux 0x776cb445 __dev_get_by_index +EXPORT_SYMBOL vmlinux 0x77a108df _write_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x77a40c71 find_or_create_page +EXPORT_SYMBOL vmlinux 0x77a6211f sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x77b1a740 proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0x77b37235 set_pages_x +EXPORT_SYMBOL vmlinux 0x77ecac9f zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x7802f7b2 lock_rename +EXPORT_SYMBOL vmlinux 0x781d22ad pci_scan_bus_parented +EXPORT_SYMBOL vmlinux 0x7823e8e7 inet_dgram_ops +EXPORT_SYMBOL vmlinux 0x7827ee6a invalidate_bdev +EXPORT_SYMBOL vmlinux 0x7828f30e ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x78302582 blk_free_tags +EXPORT_SYMBOL vmlinux 0x7843fe0a generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0x78668083 tcp_sendpage +EXPORT_SYMBOL vmlinux 0x787ac739 __secpath_destroy +EXPORT_SYMBOL vmlinux 0x78874d21 sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0x78a484c9 _read_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x78cb2783 down_write_trylock +EXPORT_SYMBOL vmlinux 0x78df6bd7 no_pci_devices +EXPORT_SYMBOL vmlinux 0x78fc2207 eth_header_parse +EXPORT_SYMBOL vmlinux 0x78fc345f dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x790454ff ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0x79188250 do_munmap +EXPORT_SYMBOL vmlinux 0x794439a0 mca_device_transform_ioport +EXPORT_SYMBOL vmlinux 0x794487ee disable_hlt +EXPORT_SYMBOL vmlinux 0x794c1398 dmi_check_system +EXPORT_SYMBOL vmlinux 0x796445a8 blk_run_queue +EXPORT_SYMBOL vmlinux 0x79656409 cpu_online_map +EXPORT_SYMBOL vmlinux 0x79aa04a2 get_random_bytes +EXPORT_SYMBOL vmlinux 0x79aa05a8 match_token +EXPORT_SYMBOL vmlinux 0x79d3fe30 skb_put +EXPORT_SYMBOL vmlinux 0x79d78989 set_irq_chip +EXPORT_SYMBOL vmlinux 0x79ec7e64 kfree_skb +EXPORT_SYMBOL vmlinux 0x7a14dff9 redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0x7a26db4d netif_receive_skb +EXPORT_SYMBOL vmlinux 0x7a2a837d strict_strtol +EXPORT_SYMBOL vmlinux 0x7a64b477 bio_add_page +EXPORT_SYMBOL vmlinux 0x7a848702 _read_lock_irqsave +EXPORT_SYMBOL vmlinux 0x7aa2c022 __lock_buffer +EXPORT_SYMBOL vmlinux 0x7ab61308 vfs_readv +EXPORT_SYMBOL vmlinux 0x7abb58c4 kunmap +EXPORT_SYMBOL vmlinux 0x7aec9089 clear_user +EXPORT_SYMBOL vmlinux 0x7b0c84c4 acpi_remove_table_handler +EXPORT_SYMBOL vmlinux 0x7b134ddf acpi_get_name +EXPORT_SYMBOL vmlinux 0x7b52a859 wrmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x7b5f1b93 cdev_del +EXPORT_SYMBOL vmlinux 0x7b69467e posix_acl_from_xattr +EXPORT_SYMBOL vmlinux 0x7b7e3165 pci_unmap_rom +EXPORT_SYMBOL vmlinux 0x7b8ecc8c blk_start_queue +EXPORT_SYMBOL vmlinux 0x7b9c1cc0 tty_register_device +EXPORT_SYMBOL vmlinux 0x7bc2a5c1 proc_dostring +EXPORT_SYMBOL vmlinux 0x7bdb6152 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0x7be753bb mpage_bio_submit +EXPORT_SYMBOL vmlinux 0x7c1e72d6 d_path +EXPORT_SYMBOL vmlinux 0x7c46233a cpufreq_quick_get +EXPORT_SYMBOL vmlinux 0x7c60d66e getname +EXPORT_SYMBOL vmlinux 0x7c64aeac mark_info_dirty +EXPORT_SYMBOL vmlinux 0x7c904ded unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x7cb1ae69 cpu_down +EXPORT_SYMBOL vmlinux 0x7cd70813 audit_log_end +EXPORT_SYMBOL vmlinux 0x7cfe97d8 pnp_start_dev +EXPORT_SYMBOL vmlinux 0x7d047e7e acpi_ut_exception +EXPORT_SYMBOL vmlinux 0x7d11c268 jiffies +EXPORT_SYMBOL vmlinux 0x7d1ac686 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0x7d79a978 request_key_with_auxdata +EXPORT_SYMBOL vmlinux 0x7d80925e pci_find_capability +EXPORT_SYMBOL vmlinux 0x7d850612 utf8_mbstowcs +EXPORT_SYMBOL vmlinux 0x7d8f71a9 unlock_buffer +EXPORT_SYMBOL vmlinux 0x7d948097 load_nls +EXPORT_SYMBOL vmlinux 0x7d9cb739 __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x7dae0b96 unregister_console +EXPORT_SYMBOL vmlinux 0x7dc5d3de file_update_time +EXPORT_SYMBOL vmlinux 0x7dceceac capable +EXPORT_SYMBOL vmlinux 0x7dd6fe8a register_sysctl_paths +EXPORT_SYMBOL vmlinux 0x7de763a1 km_new_mapping +EXPORT_SYMBOL vmlinux 0x7df70fc4 in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x7e11e248 skb_over_panic +EXPORT_SYMBOL vmlinux 0x7e4afe07 block_read_full_page +EXPORT_SYMBOL vmlinux 0x7e9ac274 tty_write_room +EXPORT_SYMBOL vmlinux 0x7e9ebb05 kernel_thread +EXPORT_SYMBOL vmlinux 0x7e9f9865 sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0x7ee91c1d _spin_trylock +EXPORT_SYMBOL vmlinux 0x7ef3eb6f bd_claim +EXPORT_SYMBOL vmlinux 0x7efbe560 per_cpu__cpu_core_map +EXPORT_SYMBOL vmlinux 0x7f24de73 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x7f4cfeb1 pnp_request_card_device +EXPORT_SYMBOL vmlinux 0x7f50857f kmalloc_caches +EXPORT_SYMBOL vmlinux 0x7f5728af key_type_keyring +EXPORT_SYMBOL vmlinux 0x7f7ef931 unlock_rename +EXPORT_SYMBOL vmlinux 0x7f8723bd pcie_mch_quirk +EXPORT_SYMBOL vmlinux 0x7fab220a iget_locked +EXPORT_SYMBOL vmlinux 0x7fae92a3 input_open_device +EXPORT_SYMBOL vmlinux 0x7fec42da nf_ct_attach +EXPORT_SYMBOL vmlinux 0x801cc62e pcix_get_max_mmrbc +EXPORT_SYMBOL vmlinux 0x802a2a23 generic_file_mmap +EXPORT_SYMBOL vmlinux 0x8063f83d radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x80b1237e inet_getname +EXPORT_SYMBOL vmlinux 0x81224a2e bio_integrity_prep +EXPORT_SYMBOL vmlinux 0x813f6f1a __nla_reserve +EXPORT_SYMBOL vmlinux 0x81472677 acpi_get_table +EXPORT_SYMBOL vmlinux 0x814ac959 simple_statfs +EXPORT_SYMBOL vmlinux 0x814e4102 free_task +EXPORT_SYMBOL vmlinux 0x814e7730 nf_ct_destroy +EXPORT_SYMBOL vmlinux 0x815b5dd4 match_octal +EXPORT_SYMBOL vmlinux 0x815f2897 empty_zero_page +EXPORT_SYMBOL vmlinux 0x816dc8cd fb_find_mode +EXPORT_SYMBOL vmlinux 0x81799cee vscnprintf +EXPORT_SYMBOL vmlinux 0x817c9341 set_page_dirty +EXPORT_SYMBOL vmlinux 0x818e1b63 acpi_bus_unregister_driver +EXPORT_SYMBOL vmlinux 0x81e6b37f dmi_get_system_info +EXPORT_SYMBOL vmlinux 0x81efcb62 pcie_get_readrq +EXPORT_SYMBOL vmlinux 0x81f2fe3d ipv4_specific +EXPORT_SYMBOL vmlinux 0x8205e1eb kill_litter_super +EXPORT_SYMBOL vmlinux 0x82072614 tasklet_kill +EXPORT_SYMBOL vmlinux 0x820d225f print_mac +EXPORT_SYMBOL vmlinux 0x8221f241 elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0x8235805b memmove +EXPORT_SYMBOL vmlinux 0x8239d4f1 tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0x8251bcc3 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x82673561 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x828f6b2b request_key_async +EXPORT_SYMBOL vmlinux 0x82b931fd blk_integrity_unregister +EXPORT_SYMBOL vmlinux 0x82f27c59 dev_load +EXPORT_SYMBOL vmlinux 0x82f7d4f7 tcp_v4_md5_do_del +EXPORT_SYMBOL vmlinux 0x8310ef2a dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0x8317e20a completion_done +EXPORT_SYMBOL vmlinux 0x831a3ec3 idr_get_new +EXPORT_SYMBOL vmlinux 0x835f2437 pci_request_regions +EXPORT_SYMBOL vmlinux 0x8363c3d4 smp_call_function_mask +EXPORT_SYMBOL vmlinux 0x83715d45 copy_strings_kernel +EXPORT_SYMBOL vmlinux 0x83800bfa kref_init +EXPORT_SYMBOL vmlinux 0x83a476ce bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x83c188cc set_pages_wb +EXPORT_SYMBOL vmlinux 0x84473470 tc_classify +EXPORT_SYMBOL vmlinux 0x8447d357 blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0x845b79c4 bio_integrity_clone +EXPORT_SYMBOL vmlinux 0x84a41ec3 idr_replace +EXPORT_SYMBOL vmlinux 0x84d80ce3 ilookup5 +EXPORT_SYMBOL vmlinux 0x84daffa0 fb_set_suspend +EXPORT_SYMBOL vmlinux 0x84ea69d6 do_splice_from +EXPORT_SYMBOL vmlinux 0x84f892dc pagecache_write_begin +EXPORT_SYMBOL vmlinux 0x853740e0 posix_acl_permission +EXPORT_SYMBOL vmlinux 0x8545fafb notify_change +EXPORT_SYMBOL vmlinux 0x854e8e18 skb_pull +EXPORT_SYMBOL vmlinux 0x85670f1d rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x859ca7cf simple_pin_fs +EXPORT_SYMBOL vmlinux 0x85a06739 xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0x85b2e987 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x85df9b6c strsep +EXPORT_SYMBOL vmlinux 0x85e7deb2 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x863cb91a utf8_wcstombs +EXPORT_SYMBOL vmlinux 0x865dee29 check_disk_change +EXPORT_SYMBOL vmlinux 0x8664f62e cpufreq_update_policy +EXPORT_SYMBOL vmlinux 0x866ab042 vfs_link +EXPORT_SYMBOL vmlinux 0x868acba5 get_options +EXPORT_SYMBOL vmlinux 0x86cdb19b pcim_iomap_table +EXPORT_SYMBOL vmlinux 0x86e97ffb nf_register_hook +EXPORT_SYMBOL vmlinux 0x86ed41ae textsearch_destroy +EXPORT_SYMBOL vmlinux 0x86fb9b05 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x870015b2 mnt_unpin +EXPORT_SYMBOL vmlinux 0x8710df81 sock_init_data +EXPORT_SYMBOL vmlinux 0x8710f9a1 bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0x8726a30a skb_checksum_help +EXPORT_SYMBOL vmlinux 0x87334d88 generic_removexattr +EXPORT_SYMBOL vmlinux 0x8733e9a3 sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x876ce3c4 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x876dafc3 ec_write +EXPORT_SYMBOL vmlinux 0x8770d8e4 dev_unicast_delete +EXPORT_SYMBOL vmlinux 0x8785725d param_set_charp +EXPORT_SYMBOL vmlinux 0x878ab3ce sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x87975602 open_exec +EXPORT_SYMBOL vmlinux 0x879a1a13 vfs_dq_quota_on_remount +EXPORT_SYMBOL vmlinux 0x87d92897 sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0x881039d0 zlib_inflate +EXPORT_SYMBOL vmlinux 0x8822ff19 bio_alloc +EXPORT_SYMBOL vmlinux 0x88674393 misc_register +EXPORT_SYMBOL vmlinux 0x8868a7a5 neigh_resolve_output +EXPORT_SYMBOL vmlinux 0x8884e1c3 d_alloc +EXPORT_SYMBOL vmlinux 0x88ad42a7 register_8022_client +EXPORT_SYMBOL vmlinux 0x891c1166 kmem_ptr_validate +EXPORT_SYMBOL vmlinux 0x892b26a0 set_memory_nx +EXPORT_SYMBOL vmlinux 0x89304c9c devm_iounmap +EXPORT_SYMBOL vmlinux 0x8931445a qdisc_destroy +EXPORT_SYMBOL vmlinux 0x8931b32a init_net +EXPORT_SYMBOL vmlinux 0x8949858b schedule_work +EXPORT_SYMBOL vmlinux 0x89527db9 inode_needs_sync +EXPORT_SYMBOL vmlinux 0x8953bb27 del_timer +EXPORT_SYMBOL vmlinux 0x895d48b3 genl_sock +EXPORT_SYMBOL vmlinux 0x896a050a arch_acpi_processor_init_pdc +EXPORT_SYMBOL vmlinux 0x897473df mktime +EXPORT_SYMBOL vmlinux 0x898b1fec mutex_trylock +EXPORT_SYMBOL vmlinux 0x898eda8b gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0x89949018 down_timeout +EXPORT_SYMBOL vmlinux 0x89d5538d fb_pad_aligned_buffer +EXPORT_SYMBOL vmlinux 0x89d66811 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x89fb0a41 elevator_init +EXPORT_SYMBOL vmlinux 0x8a221a32 dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x8a3eabf0 __wait_on_bit +EXPORT_SYMBOL vmlinux 0x8a52884b release_sock +EXPORT_SYMBOL vmlinux 0x8a5a9171 tcf_em_register +EXPORT_SYMBOL vmlinux 0x8a5bb9ee netif_device_attach +EXPORT_SYMBOL vmlinux 0x8a77fa7b xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0x8a7d1c31 high_memory +EXPORT_SYMBOL vmlinux 0x8a827d5c block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0x8a90d932 allocate_resource +EXPORT_SYMBOL vmlinux 0x8a99a016 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x8aa5f92c bio_integrity_tag_size +EXPORT_SYMBOL vmlinux 0x8aaf8654 mutex_lock +EXPORT_SYMBOL vmlinux 0x8b18496f __copy_to_user_ll +EXPORT_SYMBOL vmlinux 0x8b35e873 sg_last +EXPORT_SYMBOL vmlinux 0x8b3ca835 cpu_present_map +EXPORT_SYMBOL vmlinux 0x8b50bd1c udp_memory_allocated +EXPORT_SYMBOL vmlinux 0x8b618d08 overflowuid +EXPORT_SYMBOL vmlinux 0x8b77a2ce kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0x8b7d1fe0 inet_bind +EXPORT_SYMBOL vmlinux 0x8b989cf9 acpi_bus_can_wakeup +EXPORT_SYMBOL vmlinux 0x8bb2ff12 d_instantiate_unique +EXPORT_SYMBOL vmlinux 0x8bb33e7d __release_region +EXPORT_SYMBOL vmlinux 0x8be4a95c kmap_high +EXPORT_SYMBOL vmlinux 0x8bf3996f eisa_driver_register +EXPORT_SYMBOL vmlinux 0x8c0f3294 tcp_sendmsg +EXPORT_SYMBOL vmlinux 0x8c183cbe iowrite16 +EXPORT_SYMBOL vmlinux 0x8c2f3656 add_disk +EXPORT_SYMBOL vmlinux 0x8c520273 netif_rx_ni +EXPORT_SYMBOL vmlinux 0x8c78590d simple_rename +EXPORT_SYMBOL vmlinux 0x8c86981b pci_bus_write_config_word +EXPORT_SYMBOL vmlinux 0x8c963e9b dev_add_pack +EXPORT_SYMBOL vmlinux 0x8cb51a6e blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0x8cb8e419 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x8cc79cab iowrite16_rep +EXPORT_SYMBOL vmlinux 0x8ccdde21 elv_next_request +EXPORT_SYMBOL vmlinux 0x8d156db9 textsearch_unregister +EXPORT_SYMBOL vmlinux 0x8d3894f2 _ctype +EXPORT_SYMBOL vmlinux 0x8d3e9d9d input_unregister_handle +EXPORT_SYMBOL vmlinux 0x8d453162 send_sig_info +EXPORT_SYMBOL vmlinux 0x8d551bef sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x8d6ede06 pcie_set_readrq +EXPORT_SYMBOL vmlinux 0x8d6f81b4 __div64_32 +EXPORT_SYMBOL vmlinux 0x8d774e8b call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0x8d8d96c6 acpi_get_sleep_type_data +EXPORT_SYMBOL vmlinux 0x8dbd82e3 fb_firmware_edid +EXPORT_SYMBOL vmlinux 0x8dbd8f63 kernel_getpeername +EXPORT_SYMBOL vmlinux 0x8dc6e564 restore_processor_state +EXPORT_SYMBOL vmlinux 0x8e002cda acpi_remove_gpe_block +EXPORT_SYMBOL vmlinux 0x8e0637ba i8253_lock +EXPORT_SYMBOL vmlinux 0x8e0b7743 ipv6_ext_hdr +EXPORT_SYMBOL vmlinux 0x8e10a33a unregister_filesystem +EXPORT_SYMBOL vmlinux 0x8e1457a2 ip_ct_attach +EXPORT_SYMBOL vmlinux 0x8e5291fe pci_reenable_device +EXPORT_SYMBOL vmlinux 0x8e5b714a seq_release_private +EXPORT_SYMBOL vmlinux 0x8e725985 nf_log_unregister_pf +EXPORT_SYMBOL vmlinux 0x8e99cf65 mca_device_write_pos +EXPORT_SYMBOL vmlinux 0x8ec03159 vfs_write +EXPORT_SYMBOL vmlinux 0x8ed48220 elv_rb_add +EXPORT_SYMBOL vmlinux 0x8f0c83e9 llc_add_pack +EXPORT_SYMBOL vmlinux 0x8f1445f9 sock_get_timestampns +EXPORT_SYMBOL vmlinux 0x8f6b7950 set_irq_data +EXPORT_SYMBOL vmlinux 0x8f9c199c __get_user_2 +EXPORT_SYMBOL vmlinux 0x8fe4b45a pci_select_bars +EXPORT_SYMBOL vmlinux 0x8ffcb38e k8_northbridges +EXPORT_SYMBOL vmlinux 0x90035333 secure_tcpv6_sequence_number +EXPORT_SYMBOL vmlinux 0x9070b3f2 ioport_resource +EXPORT_SYMBOL vmlinux 0x9085b53d blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x90a92cbc generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0x90a943ba nmi_active +EXPORT_SYMBOL vmlinux 0x90e1f81e sg_miter_next +EXPORT_SYMBOL vmlinux 0x90fda4fe tcf_exts_change +EXPORT_SYMBOL vmlinux 0x9144a8e2 ec_burst_disable +EXPORT_SYMBOL vmlinux 0x91481982 __ratelimit +EXPORT_SYMBOL vmlinux 0x915106d6 tcp_shutdown +EXPORT_SYMBOL vmlinux 0x91607d95 set_memory_wb +EXPORT_SYMBOL vmlinux 0x91b57bac set_bh_page +EXPORT_SYMBOL vmlinux 0x91ca8959 acpi_get_register +EXPORT_SYMBOL vmlinux 0x92284576 sk_free +EXPORT_SYMBOL vmlinux 0x924dd802 unregister_netdev +EXPORT_SYMBOL vmlinux 0x92897e3d default_idle +EXPORT_SYMBOL vmlinux 0x930075fd scm_fp_dup +EXPORT_SYMBOL vmlinux 0x9305f8e6 cpufreq_get +EXPORT_SYMBOL vmlinux 0x9320ffb6 current_fs_time +EXPORT_SYMBOL vmlinux 0x935b27bc fput +EXPORT_SYMBOL vmlinux 0x938990c9 iunique +EXPORT_SYMBOL vmlinux 0x93a6e0b2 io_schedule +EXPORT_SYMBOL vmlinux 0x93b8ef56 mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0x93bb249b xfrm_register_type +EXPORT_SYMBOL vmlinux 0x93c69acf param_set_byte +EXPORT_SYMBOL vmlinux 0x93cbd1ec _spin_lock_bh +EXPORT_SYMBOL vmlinux 0x93dac966 tty_unthrottle +EXPORT_SYMBOL vmlinux 0x93fca811 __get_free_pages +EXPORT_SYMBOL vmlinux 0x940dcb45 iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0x944fc5b6 locks_copy_lock +EXPORT_SYMBOL vmlinux 0x947563f1 request_firmware +EXPORT_SYMBOL vmlinux 0x94961283 vunmap +EXPORT_SYMBOL vmlinux 0x94badd50 generic_file_splice_write +EXPORT_SYMBOL vmlinux 0x94c57dbb sk_alloc +EXPORT_SYMBOL vmlinux 0x94fcf08e bioset_create +EXPORT_SYMBOL vmlinux 0x950151cb pid_task +EXPORT_SYMBOL vmlinux 0x953429af nobh_writepage +EXPORT_SYMBOL vmlinux 0x953b02eb put_page +EXPORT_SYMBOL vmlinux 0x954488a4 syncookie_secret +EXPORT_SYMBOL vmlinux 0x9545af6d tasklet_init +EXPORT_SYMBOL vmlinux 0x954cbb26 vsprintf +EXPORT_SYMBOL vmlinux 0x954e6dd7 n_tty_ioctl +EXPORT_SYMBOL vmlinux 0x95b4da4a idr_pre_get +EXPORT_SYMBOL vmlinux 0x95c13926 nf_unregister_queue_handler +EXPORT_SYMBOL vmlinux 0x95c9e47e task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x95daef01 drop_super +EXPORT_SYMBOL vmlinux 0x95dc095a set_disk_ro +EXPORT_SYMBOL vmlinux 0x95df0a59 find_inode_number +EXPORT_SYMBOL vmlinux 0x95f638d5 posix_acl_chmod_masq +EXPORT_SYMBOL vmlinux 0x96481cc7 per_cpu__x86_cpu_to_apicid +EXPORT_SYMBOL vmlinux 0x9662c4b0 dev_mc_delete +EXPORT_SYMBOL vmlinux 0x966c8286 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0x96898769 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0x96939c04 pv_cpu_ops +EXPORT_SYMBOL vmlinux 0x96a441c1 simple_transaction_read +EXPORT_SYMBOL vmlinux 0x96bc8b20 rtnl_create_link +EXPORT_SYMBOL vmlinux 0x96ec0782 generic_listxattr +EXPORT_SYMBOL vmlinux 0x96f5169a truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0x9706e8dd pcim_pin_device +EXPORT_SYMBOL vmlinux 0x9708e864 lock_super +EXPORT_SYMBOL vmlinux 0x973873ab _spin_lock +EXPORT_SYMBOL vmlinux 0x9747742c key_alloc +EXPORT_SYMBOL vmlinux 0x9754ec10 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x97a26bf8 idr_init +EXPORT_SYMBOL vmlinux 0x97ad43d3 register_snap_client +EXPORT_SYMBOL vmlinux 0x97b5f917 mpage_readpages +EXPORT_SYMBOL vmlinux 0x97c2bf73 pci_prepare_to_sleep +EXPORT_SYMBOL vmlinux 0x97de0ddd acpi_install_gpe_block +EXPORT_SYMBOL vmlinux 0x981026f6 km_report +EXPORT_SYMBOL vmlinux 0x982426a0 udp_sendmsg +EXPORT_SYMBOL vmlinux 0x983de3b4 pneigh_lookup +EXPORT_SYMBOL vmlinux 0x9855868c pcibios_set_irq_routing +EXPORT_SYMBOL vmlinux 0x9865599f pcix_set_mmrbc +EXPORT_SYMBOL vmlinux 0x986e6135 fb_pad_unaligned_buffer +EXPORT_SYMBOL vmlinux 0x987d3617 tcf_em_tree_dump +EXPORT_SYMBOL vmlinux 0x988ed85d set_memory_x +EXPORT_SYMBOL vmlinux 0x9897bf7c __vlan_hwaccel_rx +EXPORT_SYMBOL vmlinux 0x98b0fff8 aio_put_req +EXPORT_SYMBOL vmlinux 0x98c76c06 dev_alloc_skb +EXPORT_SYMBOL vmlinux 0x98f1c538 dget_locked +EXPORT_SYMBOL vmlinux 0x98fe6a0a sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0x99052a84 acpi_os_write_port +EXPORT_SYMBOL vmlinux 0x9929d935 inet_listen +EXPORT_SYMBOL vmlinux 0x992eec54 udplite_prot +EXPORT_SYMBOL vmlinux 0x9970d656 __ht_create_irq +EXPORT_SYMBOL vmlinux 0x9994c0ca ps2_is_keyboard_id +EXPORT_SYMBOL vmlinux 0x999e8297 vfree +EXPORT_SYMBOL vmlinux 0x99aadb21 param_get_ulong +EXPORT_SYMBOL vmlinux 0x99bfbe39 get_unused_fd +EXPORT_SYMBOL vmlinux 0x99c3c0b0 vfs_fstat +EXPORT_SYMBOL vmlinux 0x99c9a465 block_invalidatepage +EXPORT_SYMBOL vmlinux 0x99cdc86b sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x99ea12ce panic_blink +EXPORT_SYMBOL vmlinux 0x99ed1a7d ip_mc_join_group +EXPORT_SYMBOL vmlinux 0x9a1dfd65 strpbrk +EXPORT_SYMBOL vmlinux 0x9a24633a d_instantiate +EXPORT_SYMBOL vmlinux 0x9a3350f7 xfrm_state_update +EXPORT_SYMBOL vmlinux 0x9a4bb9de generic_fillattr +EXPORT_SYMBOL vmlinux 0x9a642eaa uart_write_wakeup +EXPORT_SYMBOL vmlinux 0x9a6a83f9 cmos_lock +EXPORT_SYMBOL vmlinux 0x9a87681b alloc_fcdev +EXPORT_SYMBOL vmlinux 0x9a9985be percpu_counter_destroy +EXPORT_SYMBOL vmlinux 0x9aa67e87 sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0x9add2ce3 generic_write_end +EXPORT_SYMBOL vmlinux 0x9afad9ef tcf_hash_create +EXPORT_SYMBOL vmlinux 0x9b03a217 bio_unmap_user +EXPORT_SYMBOL vmlinux 0x9b1cf57a tcp_splice_read +EXPORT_SYMBOL vmlinux 0x9b2b3b94 tcp_md5_hash_header +EXPORT_SYMBOL vmlinux 0x9b388444 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x9ba7089d argv_split +EXPORT_SYMBOL vmlinux 0x9bb0b221 __scm_send +EXPORT_SYMBOL vmlinux 0x9c012508 fb_parse_edid +EXPORT_SYMBOL vmlinux 0x9c2c944a __copy_from_user_ll_nocache_nozero +EXPORT_SYMBOL vmlinux 0x9c491f60 sg_alloc_table +EXPORT_SYMBOL vmlinux 0x9c7077bd enable_hlt +EXPORT_SYMBOL vmlinux 0x9c727019 skb_gso_segment +EXPORT_SYMBOL vmlinux 0x9c913790 dquot_release +EXPORT_SYMBOL vmlinux 0x9c9ba8f8 km_policy_notify +EXPORT_SYMBOL vmlinux 0x9cb96e92 qdisc_put_rtab +EXPORT_SYMBOL vmlinux 0x9cc49a4a netpoll_parse_options +EXPORT_SYMBOL vmlinux 0x9ccb2622 finish_wait +EXPORT_SYMBOL vmlinux 0x9cd88abd nlmsg_notify +EXPORT_SYMBOL vmlinux 0x9ce5635c pskb_copy +EXPORT_SYMBOL vmlinux 0x9ceb163c memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x9ced38aa down_trylock +EXPORT_SYMBOL vmlinux 0x9cee540a generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0x9d211cb3 xfrm4_rcv +EXPORT_SYMBOL vmlinux 0x9d33ef5e acpi_enable +EXPORT_SYMBOL vmlinux 0x9d711f1f percpu_counter_init +EXPORT_SYMBOL vmlinux 0x9d71787a d_lookup +EXPORT_SYMBOL vmlinux 0x9d78799b alloc_tty_driver +EXPORT_SYMBOL vmlinux 0x9d983a13 simple_readpage +EXPORT_SYMBOL vmlinux 0x9d9c3524 pcie_port_service_register +EXPORT_SYMBOL vmlinux 0x9d9f0d41 rwsem_down_write_failed +EXPORT_SYMBOL vmlinux 0x9de67ac1 pci_restore_state +EXPORT_SYMBOL vmlinux 0x9dfdbdb7 file_permission +EXPORT_SYMBOL vmlinux 0x9e26f1a2 key_unlink +EXPORT_SYMBOL vmlinux 0x9e3bc716 grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0x9e4b3747 sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0x9e64fbfe rtc_cmos_read +EXPORT_SYMBOL vmlinux 0x9e7d6bd0 __udelay +EXPORT_SYMBOL vmlinux 0x9e839fdc d_alloc_anon +EXPORT_SYMBOL vmlinux 0x9ea0ad49 __sg_free_table +EXPORT_SYMBOL vmlinux 0x9eb6cf81 netpoll_setup +EXPORT_SYMBOL vmlinux 0x9ed685ee iov_iter_advance +EXPORT_SYMBOL vmlinux 0x9eecde16 do_brk +EXPORT_SYMBOL vmlinux 0x9ef749e2 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x9f100139 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x9f17758e eth_header_cache_update +EXPORT_SYMBOL vmlinux 0x9f2bdaac __bitmap_or +EXPORT_SYMBOL vmlinux 0x9f3c4d51 unregister_nls +EXPORT_SYMBOL vmlinux 0x9f5439a4 pcim_iomap_regions +EXPORT_SYMBOL vmlinux 0x9f7122ef nf_unregister_hooks +EXPORT_SYMBOL vmlinux 0x9f841815 __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0x9f877b24 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x9f984513 strrchr +EXPORT_SYMBOL vmlinux 0x9fa01c1b inode_sub_bytes +EXPORT_SYMBOL vmlinux 0x9fa274b4 dq_data_lock +EXPORT_SYMBOL vmlinux 0x9fb3dd30 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x9fd16fd6 vfs_dq_drop +EXPORT_SYMBOL vmlinux 0x9fe4241a sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x9feaf287 sonet_subtract_stats +EXPORT_SYMBOL vmlinux 0x9ff53988 __inet6_hash +EXPORT_SYMBOL vmlinux 0x9ffd5c59 neigh_seq_next +EXPORT_SYMBOL vmlinux 0xa008ce9c dma_supported +EXPORT_SYMBOL vmlinux 0xa015bba2 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0xa024f729 tcp_mtup_init +EXPORT_SYMBOL vmlinux 0xa03523d5 security_unix_stream_connect +EXPORT_SYMBOL vmlinux 0xa03e8eee cap_netlink_recv +EXPORT_SYMBOL vmlinux 0xa04a01bd qdisc_class_hash_insert +EXPORT_SYMBOL vmlinux 0xa058401c kill_block_super +EXPORT_SYMBOL vmlinux 0xa05c03df mempool_kmalloc +EXPORT_SYMBOL vmlinux 0xa0b04675 vmalloc_32 +EXPORT_SYMBOL vmlinux 0xa0ceef51 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0xa0eaf377 dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0xa0fbac79 wake_up_bit +EXPORT_SYMBOL vmlinux 0xa108eb4d sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0xa113b842 lock_may_read +EXPORT_SYMBOL vmlinux 0xa120d33c tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0xa12d3729 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0xa13798f8 printk_ratelimit +EXPORT_SYMBOL vmlinux 0xa1581500 inet_select_addr +EXPORT_SYMBOL vmlinux 0xa170dd4b serio_rescan +EXPORT_SYMBOL vmlinux 0xa18c920a bdget +EXPORT_SYMBOL vmlinux 0xa19021e7 __invalidate_device +EXPORT_SYMBOL vmlinux 0xa19cb24d __xfrm_lookup +EXPORT_SYMBOL vmlinux 0xa1a438ca struct_module +EXPORT_SYMBOL vmlinux 0xa1ad3fa1 sget +EXPORT_SYMBOL vmlinux 0xa1b759ce fb_add_videomode +EXPORT_SYMBOL vmlinux 0xa1bc7796 inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0xa1c569d3 __seq_open_private +EXPORT_SYMBOL vmlinux 0xa1c76e0a _cond_resched +EXPORT_SYMBOL vmlinux 0xa1d6b0e8 block_sync_page +EXPORT_SYMBOL vmlinux 0xa1f39910 blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0xa20b39c2 simple_write_begin +EXPORT_SYMBOL vmlinux 0xa20ce1b8 net_msg_warn +EXPORT_SYMBOL vmlinux 0xa27b61ed __wait_on_buffer +EXPORT_SYMBOL vmlinux 0xa2a1e5c9 _write_lock_bh +EXPORT_SYMBOL vmlinux 0xa2a5fd77 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0xa2de6ef5 pci_map_rom +EXPORT_SYMBOL vmlinux 0xa2eaa797 kill_pid +EXPORT_SYMBOL vmlinux 0xa2f989ce vfs_read +EXPORT_SYMBOL vmlinux 0xa329f07e register_shrinker +EXPORT_SYMBOL vmlinux 0xa3420d61 __percpu_counter_sum +EXPORT_SYMBOL vmlinux 0xa34dada4 dev_get_by_index +EXPORT_SYMBOL vmlinux 0xa34f1ef5 crc32_le +EXPORT_SYMBOL vmlinux 0xa35c1f05 acpi_extract_package +EXPORT_SYMBOL vmlinux 0xa35de80f ipv4_config +EXPORT_SYMBOL vmlinux 0xa363f4ea tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0xa38a5dcd xfrm_input +EXPORT_SYMBOL vmlinux 0xa3bbcd80 acpi_set_gpe_type +EXPORT_SYMBOL vmlinux 0xa3fcdfef open_bdev_excl +EXPORT_SYMBOL vmlinux 0xa422887d blk_sync_queue +EXPORT_SYMBOL vmlinux 0xa44072fc posix_acl_alloc +EXPORT_SYMBOL vmlinux 0xa44ad274 wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0xa44f457c tcp_close +EXPORT_SYMBOL vmlinux 0xa45bfe06 ipv6_skip_exthdr +EXPORT_SYMBOL vmlinux 0xa4700d0f alloc_fddidev +EXPORT_SYMBOL vmlinux 0xa47cc300 pci_enable_msi +EXPORT_SYMBOL vmlinux 0xa49be1d3 mca_device_read_pos +EXPORT_SYMBOL vmlinux 0xa4b94fea iowrite8_rep +EXPORT_SYMBOL vmlinux 0xa4df1151 kref_set +EXPORT_SYMBOL vmlinux 0xa51cdfe8 __FIXADDR_TOP +EXPORT_SYMBOL vmlinux 0xa5384233 pci_clear_mwi +EXPORT_SYMBOL vmlinux 0xa5423cc4 param_get_int +EXPORT_SYMBOL vmlinux 0xa5693df7 posix_acl_clone +EXPORT_SYMBOL vmlinux 0xa56f1315 mempool_free +EXPORT_SYMBOL vmlinux 0xa58b6804 nla_parse +EXPORT_SYMBOL vmlinux 0xa5922bb1 kfifo_init +EXPORT_SYMBOL vmlinux 0xa598e29c vesa_modes +EXPORT_SYMBOL vmlinux 0xa5cba052 blk_integrity_register +EXPORT_SYMBOL vmlinux 0xa5da0abd acpi_enter_sleep_state_s4bios +EXPORT_SYMBOL vmlinux 0xa5f3d68d netlink_dump_start +EXPORT_SYMBOL vmlinux 0xa5f9bf5f add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0xa5fd0a2d pci_find_next_bus +EXPORT_SYMBOL vmlinux 0xa60b8898 sock_wake_async +EXPORT_SYMBOL vmlinux 0xa60d6b71 pnp_activate_dev +EXPORT_SYMBOL vmlinux 0xa621254f iommu_bio_merge +EXPORT_SYMBOL vmlinux 0xa666e9ef ip_route_output_key +EXPORT_SYMBOL vmlinux 0xa680aed0 ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0xa68124fa hweight8 +EXPORT_SYMBOL vmlinux 0xa6814433 groups_free +EXPORT_SYMBOL vmlinux 0xa681fe88 generate_random_uuid +EXPORT_SYMBOL vmlinux 0xa693b117 pnp_register_driver +EXPORT_SYMBOL vmlinux 0xa6bb968e sk_stream_error +EXPORT_SYMBOL vmlinux 0xa6dcc773 rb_insert_color +EXPORT_SYMBOL vmlinux 0xa6e6d5eb kernel_getsockopt +EXPORT_SYMBOL vmlinux 0xa6f6c96b __dec_zone_page_state +EXPORT_SYMBOL vmlinux 0xa7046549 vprintk +EXPORT_SYMBOL vmlinux 0xa70ed09d mod_zone_page_state +EXPORT_SYMBOL vmlinux 0xa70fabbe release_evntsel_nmi +EXPORT_SYMBOL vmlinux 0xa70fc142 register_con_driver +EXPORT_SYMBOL vmlinux 0xa7135886 blk_queue_ordered +EXPORT_SYMBOL vmlinux 0xa732a6b4 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0xa7375ea9 register_chrdev +EXPORT_SYMBOL vmlinux 0xa7502f48 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0xa75cf2a6 tcp_check_req +EXPORT_SYMBOL vmlinux 0xa766c5e3 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0xa770b803 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0xa781d8aa dmam_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0xa7c35c6b getnstimeofday +EXPORT_SYMBOL vmlinux 0xa7cc04ab pci_set_power_state +EXPORT_SYMBOL vmlinux 0xa7e492e1 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0xa857b9fa d_alloc_root +EXPORT_SYMBOL vmlinux 0xa89acbb3 acpi_evaluate_reference +EXPORT_SYMBOL vmlinux 0xa8b9d6d9 sock_create_kern +EXPORT_SYMBOL vmlinux 0xa8fef7bb security_unix_may_send +EXPORT_SYMBOL vmlinux 0xa925899a param_set_bool +EXPORT_SYMBOL vmlinux 0xa961d35a tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0xa96e83ca freeze_bdev +EXPORT_SYMBOL vmlinux 0xa97a7370 dec_zone_page_state +EXPORT_SYMBOL vmlinux 0xa98816c9 bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0xa9930fb1 read_cache_pages +EXPORT_SYMBOL vmlinux 0xa9a14377 unregister_key_type +EXPORT_SYMBOL vmlinux 0xa9be76e8 clocksource_register +EXPORT_SYMBOL vmlinux 0xa9bec86c xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0xa9c8b9c5 dev_get_flags +EXPORT_SYMBOL vmlinux 0xa9ebab33 pci_enable_msix +EXPORT_SYMBOL vmlinux 0xa9fcf31d wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0xaa024146 sonet_copy_stats +EXPORT_SYMBOL vmlinux 0xaa0bf949 do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0xaa545de8 vfs_create +EXPORT_SYMBOL vmlinux 0xaa7a7846 tcp_sync_mss +EXPORT_SYMBOL vmlinux 0xaa84a8ae acpi_processor_power_init_bm_check +EXPORT_SYMBOL vmlinux 0xaaa13fec locks_mandatory_area +EXPORT_SYMBOL vmlinux 0xaaac233e d_splice_alias +EXPORT_SYMBOL vmlinux 0xaab06af8 _write_lock_irqsave +EXPORT_SYMBOL vmlinux 0xaaba3979 blk_rq_map_integrity_sg +EXPORT_SYMBOL vmlinux 0xaacabeab tcf_hash_check +EXPORT_SYMBOL vmlinux 0xaae7eae0 __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0xaae8ab0e acpi_bus_power_manageable +EXPORT_SYMBOL vmlinux 0xaaebe34f mca_write_pos +EXPORT_SYMBOL vmlinux 0xaafdc258 strcasecmp +EXPORT_SYMBOL vmlinux 0xaaffb9a5 acpi_bus_private_data_handler +EXPORT_SYMBOL vmlinux 0xab11433d dev_set_mac_address +EXPORT_SYMBOL vmlinux 0xab20741f rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0xab471003 param_array_set +EXPORT_SYMBOL vmlinux 0xab5e05d5 register_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0xab600421 probe_irq_off +EXPORT_SYMBOL vmlinux 0xab65ed80 set_memory_uc +EXPORT_SYMBOL vmlinux 0xab7da49c dev_queue_xmit +EXPORT_SYMBOL vmlinux 0xaba6eed7 tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0xabd0c91c rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0xac2bb96d blk_register_region +EXPORT_SYMBOL vmlinux 0xac3b3cee __bitmap_and +EXPORT_SYMBOL vmlinux 0xac4c7610 splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0xac58ea5e acpi_unload_table_id +EXPORT_SYMBOL vmlinux 0xac62a4ec wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0xac66538c single_release +EXPORT_SYMBOL vmlinux 0xac69477b security_sb_clone_mnt_opts +EXPORT_SYMBOL vmlinux 0xac7b398f sg_miter_stop +EXPORT_SYMBOL vmlinux 0xac8b80c6 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0xac999c50 devm_ioremap +EXPORT_SYMBOL vmlinux 0xacbef639 end_queued_request +EXPORT_SYMBOL vmlinux 0xaccabc6a in4_pton +EXPORT_SYMBOL vmlinux 0xacd3c3f4 mntput_no_expire +EXPORT_SYMBOL vmlinux 0xace41768 vfs_path_lookup +EXPORT_SYMBOL vmlinux 0xace5f7b6 unregister_quota_format +EXPORT_SYMBOL vmlinux 0xacf4d843 match_strdup +EXPORT_SYMBOL vmlinux 0xacfdfd7c inet_stream_ops +EXPORT_SYMBOL vmlinux 0xad0413d4 match_hex +EXPORT_SYMBOL vmlinux 0xad07fcc5 __first_cpu +EXPORT_SYMBOL vmlinux 0xad13c689 acpi_os_execute +EXPORT_SYMBOL vmlinux 0xad2e5c63 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0xad810a03 remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0xada88d05 elv_rb_find +EXPORT_SYMBOL vmlinux 0xadaa2657 cpufreq_register_notifier +EXPORT_SYMBOL vmlinux 0xadd6922c __insert_inode_hash +EXPORT_SYMBOL vmlinux 0xaddfb111 kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0xae4bc2fd tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0xae74b0d0 pnp_is_active +EXPORT_SYMBOL vmlinux 0xae9ce659 deactivate_super +EXPORT_SYMBOL vmlinux 0xaea23db8 udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0xaeb446e2 f_setown +EXPORT_SYMBOL vmlinux 0xaec655c7 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0xaeecdd2f dev_alloc_name +EXPORT_SYMBOL vmlinux 0xaf11edd9 __mpage_writepage +EXPORT_SYMBOL vmlinux 0xaf28d5ee blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0xaf4b1540 acpi_get_irq_routing_table +EXPORT_SYMBOL vmlinux 0xaf5c1dd3 acpi_lock_ac_dir +EXPORT_SYMBOL vmlinux 0xafc3fae7 __bforget +EXPORT_SYMBOL vmlinux 0xafd8cc15 ___pskb_trim +EXPORT_SYMBOL vmlinux 0xafe01377 down_read +EXPORT_SYMBOL vmlinux 0xaffa7ec6 kmem_cache_create +EXPORT_SYMBOL vmlinux 0xb011b30c sock_no_accept +EXPORT_SYMBOL vmlinux 0xb0686d28 pnp_device_attach +EXPORT_SYMBOL vmlinux 0xb077ef32 acpi_enter_sleep_state +EXPORT_SYMBOL vmlinux 0xb0795ec4 bio_integrity_alloc_bioset +EXPORT_SYMBOL vmlinux 0xb07dfb3d acpi_remove_gpe_handler +EXPORT_SYMBOL vmlinux 0xb08f76ad gen_pool_free +EXPORT_SYMBOL vmlinux 0xb092f043 key_task_permission +EXPORT_SYMBOL vmlinux 0xb0b847ac __bitmap_full +EXPORT_SYMBOL vmlinux 0xb0e10781 get_option +EXPORT_SYMBOL vmlinux 0xb121390a probe_irq_on +EXPORT_SYMBOL vmlinux 0xb12b4b3a blk_start_queueing +EXPORT_SYMBOL vmlinux 0xb13c4dba down_write +EXPORT_SYMBOL vmlinux 0xb148715f dev_open +EXPORT_SYMBOL vmlinux 0xb14d92c2 dev_get_by_flags +EXPORT_SYMBOL vmlinux 0xb1645a2e sg_free_table +EXPORT_SYMBOL vmlinux 0xb1906837 devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0xb19227d6 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0xb1972b34 simple_link +EXPORT_SYMBOL vmlinux 0xb19760c3 bitmap_onto +EXPORT_SYMBOL vmlinux 0xb1b0917c tcp_ioctl +EXPORT_SYMBOL vmlinux 0xb1c1da88 sock_rfree +EXPORT_SYMBOL vmlinux 0xb1c3a01a oops_in_progress +EXPORT_SYMBOL vmlinux 0xb1c7c5b5 atm_dev_deregister +EXPORT_SYMBOL vmlinux 0xb1cfad22 rdmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xb1d11b11 xfrm_lookup +EXPORT_SYMBOL vmlinux 0xb1eeb226 netif_rx +EXPORT_SYMBOL vmlinux 0xb1f975aa unlock_kernel +EXPORT_SYMBOL vmlinux 0xb200336e deregister_atm_ioctl +EXPORT_SYMBOL vmlinux 0xb2017c1d per_cpu__x86_bios_cpu_apicid +EXPORT_SYMBOL vmlinux 0xb224de48 alloc_buffer_head +EXPORT_SYMBOL vmlinux 0xb2e81c7a inetdev_by_index +EXPORT_SYMBOL vmlinux 0xb2efb6be mca_read_stored_pos +EXPORT_SYMBOL vmlinux 0xb2fd5ceb __put_user_4 +EXPORT_SYMBOL vmlinux 0xb30753f1 xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0xb30c9be8 sock_no_listen +EXPORT_SYMBOL vmlinux 0xb314b77b ps2_command +EXPORT_SYMBOL vmlinux 0xb3205415 wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0xb3284531 acpi_dbg_layer +EXPORT_SYMBOL vmlinux 0xb32872e3 skb_clone +EXPORT_SYMBOL vmlinux 0xb34b7e88 tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0xb34d4c2e acpi_terminate +EXPORT_SYMBOL vmlinux 0xb34ee1c7 bio_init +EXPORT_SYMBOL vmlinux 0xb352177e find_first_bit +EXPORT_SYMBOL vmlinux 0xb3658815 register_exec_domain +EXPORT_SYMBOL vmlinux 0xb3692eb4 ioremap_wc +EXPORT_SYMBOL vmlinux 0xb36c7677 pci_back_from_sleep +EXPORT_SYMBOL vmlinux 0xb376d79d radix_tree_tagged +EXPORT_SYMBOL vmlinux 0xb3889e03 kill_anon_super +EXPORT_SYMBOL vmlinux 0xb38ebd21 bio_map_kern +EXPORT_SYMBOL vmlinux 0xb3a11525 sync_inode +EXPORT_SYMBOL vmlinux 0xb3a307c6 si_meminfo +EXPORT_SYMBOL vmlinux 0xb3adfb10 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0xb3e0590d acpi_set_current_resources +EXPORT_SYMBOL vmlinux 0xb3f44049 tcf_exts_dump_stats +EXPORT_SYMBOL vmlinux 0xb42346f9 register_framebuffer +EXPORT_SYMBOL vmlinux 0xb423dba1 console_blanked +EXPORT_SYMBOL vmlinux 0xb429410a posix_acl_from_mode +EXPORT_SYMBOL vmlinux 0xb4390f9a mcount +EXPORT_SYMBOL vmlinux 0xb44072eb dcache_readdir +EXPORT_SYMBOL vmlinux 0xb45578b8 memscan +EXPORT_SYMBOL vmlinux 0xb455f652 invalidate_partition +EXPORT_SYMBOL vmlinux 0xb45b24f6 k8_nb_ids +EXPORT_SYMBOL vmlinux 0xb460caff alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0xb494e82a br_fdb_put_hook +EXPORT_SYMBOL vmlinux 0xb4c2c13d posix_test_lock +EXPORT_SYMBOL vmlinux 0xb4c8d74b force_sig +EXPORT_SYMBOL vmlinux 0xb4ca9447 __kfifo_get +EXPORT_SYMBOL vmlinux 0xb4d3eaaf pnp_release_card_device +EXPORT_SYMBOL vmlinux 0xb4d592c9 inet_ioctl +EXPORT_SYMBOL vmlinux 0xb4fcc69d close_bdev_excl +EXPORT_SYMBOL vmlinux 0xb4fe3067 xfrm_nl +EXPORT_SYMBOL vmlinux 0xb5044271 vsscanf +EXPORT_SYMBOL vmlinux 0xb54533f7 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0xb55454e8 pnp_find_dev +EXPORT_SYMBOL vmlinux 0xb59dacf6 tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0xb5a459dc unregister_blkdev +EXPORT_SYMBOL vmlinux 0xb5ad3c1e serio_close +EXPORT_SYMBOL vmlinux 0xb5c5e656 __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0xb5d52c27 ec_transaction +EXPORT_SYMBOL vmlinux 0xb5f4dd2e udp_poll +EXPORT_SYMBOL vmlinux 0xb6052d25 atm_dev_register +EXPORT_SYMBOL vmlinux 0xb60e34a8 nla_memcpy +EXPORT_SYMBOL vmlinux 0xb61de36c inode_double_unlock +EXPORT_SYMBOL vmlinux 0xb6244511 sg_init_one +EXPORT_SYMBOL vmlinux 0xb6301202 call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0xb63e51ee uart_add_one_port +EXPORT_SYMBOL vmlinux 0xb644538d inode_double_lock +EXPORT_SYMBOL vmlinux 0xb678366f int_sqrt +EXPORT_SYMBOL vmlinux 0xb6a61a86 qdisc_get_rtab +EXPORT_SYMBOL vmlinux 0xb6e227aa rtc_lock +EXPORT_SYMBOL vmlinux 0xb6ed1e53 strncpy +EXPORT_SYMBOL vmlinux 0xb703911e release_firmware +EXPORT_SYMBOL vmlinux 0xb703f71d bio_uncopy_user +EXPORT_SYMBOL vmlinux 0xb7043b26 pcim_enable_device +EXPORT_SYMBOL vmlinux 0xb714a981 console_print +EXPORT_SYMBOL vmlinux 0xb72397d5 printk +EXPORT_SYMBOL vmlinux 0xb7260992 wireless_spy_update +EXPORT_SYMBOL vmlinux 0xb7265215 get_user_pages +EXPORT_SYMBOL vmlinux 0xb7290e2c tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0xb7555f12 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0xb758b225 acpi_disable_event +EXPORT_SYMBOL vmlinux 0xb775afc0 generic_file_llseek +EXPORT_SYMBOL vmlinux 0xb778b3c5 bio_integrity_trim +EXPORT_SYMBOL vmlinux 0xb7aa633e sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0xb7b61546 crc32_be +EXPORT_SYMBOL vmlinux 0xb7c5205a dev_unicast_sync +EXPORT_SYMBOL vmlinux 0xb7d26df9 netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0xb804e868 iget5_locked +EXPORT_SYMBOL vmlinux 0xb811ba0e __vmalloc +EXPORT_SYMBOL vmlinux 0xb85b2bac vm_stat +EXPORT_SYMBOL vmlinux 0xb86e4ab9 random32 +EXPORT_SYMBOL vmlinux 0xb894926d schedule_work_on +EXPORT_SYMBOL vmlinux 0xb89af9bf srandom32 +EXPORT_SYMBOL vmlinux 0xb8b65c5a pcim_iomap_regions_request_all +EXPORT_SYMBOL vmlinux 0xb8e7ce2c __put_user_8 +EXPORT_SYMBOL vmlinux 0xb8fd39fe page_put_link +EXPORT_SYMBOL vmlinux 0xb8fe6ba2 simple_release_fs +EXPORT_SYMBOL vmlinux 0xb940ff04 pnp_disable_dev +EXPORT_SYMBOL vmlinux 0xb94fc509 blk_queue_bounce +EXPORT_SYMBOL vmlinux 0xb98a0185 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0xb9b3330b __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0xb9babb06 skb_queue_head +EXPORT_SYMBOL vmlinux 0xb9c74bf1 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0xb9ed741f sk_receive_skb +EXPORT_SYMBOL vmlinux 0xb9edca6a pnp_get_resource +EXPORT_SYMBOL vmlinux 0xb9f23154 tcp_md5_hash_key +EXPORT_SYMBOL vmlinux 0xb9f69e21 bio_integrity_free +EXPORT_SYMBOL vmlinux 0xb9fd2205 add_efi_memmap +EXPORT_SYMBOL vmlinux 0xba2d8594 ec_read +EXPORT_SYMBOL vmlinux 0xba405a70 register_quota_format +EXPORT_SYMBOL vmlinux 0xba497f13 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0xba4a3ebf tty_throttle +EXPORT_SYMBOL vmlinux 0xba74baa7 page_address +EXPORT_SYMBOL vmlinux 0xba8eeacd tcp_tso_segment +EXPORT_SYMBOL vmlinux 0xbab045b0 sk_stop_timer +EXPORT_SYMBOL vmlinux 0xbb03444f eth_rebuild_header +EXPORT_SYMBOL vmlinux 0xbb167766 fb_var_to_videomode +EXPORT_SYMBOL vmlinux 0xbb189cad disallow_signal +EXPORT_SYMBOL vmlinux 0xbb2bbf2a input_register_handle +EXPORT_SYMBOL vmlinux 0xbb5d343d xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0xbb83bd29 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0xbb8eb53c bio_integrity_advance +EXPORT_SYMBOL vmlinux 0xbbc0eb91 posix_unblock_lock +EXPORT_SYMBOL vmlinux 0xbbc8e804 param_set_ushort +EXPORT_SYMBOL vmlinux 0xbbcba05a give_up_console +EXPORT_SYMBOL vmlinux 0xbbfcf0a1 __devm_request_region +EXPORT_SYMBOL vmlinux 0xbbfe98b0 kobject_add +EXPORT_SYMBOL vmlinux 0xbc1aeb4b __generic_unplug_device +EXPORT_SYMBOL vmlinux 0xbc554bef compute_creds +EXPORT_SYMBOL vmlinux 0xbc5cb1bb bdi_unregister +EXPORT_SYMBOL vmlinux 0xbc94f66d per_cpu__cpu_info +EXPORT_SYMBOL vmlinux 0xbcae55c6 blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0xbcbce4f3 rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0xbcc308bb strnlen_user +EXPORT_SYMBOL vmlinux 0xbcc8a7ce tty_unregister_device +EXPORT_SYMBOL vmlinux 0xbd563df0 xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0xbd5cf8a0 vfs_unlink +EXPORT_SYMBOL vmlinux 0xbdd9bf30 acpi_bus_add +EXPORT_SYMBOL vmlinux 0xbe0e5118 nla_memcmp +EXPORT_SYMBOL vmlinux 0xbe946264 lock_sock_nested +EXPORT_SYMBOL vmlinux 0xbef43296 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0xbef8e090 blk_queue_make_request +EXPORT_SYMBOL vmlinux 0xbf0032ef end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0xbf130f88 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0xbf13b163 rwsem_down_read_failed +EXPORT_SYMBOL vmlinux 0xbf1ae51e __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0xbf59d34e nf_log_register +EXPORT_SYMBOL vmlinux 0xbf59fea5 unlock_page +EXPORT_SYMBOL vmlinux 0xbf6ba3fa blk_rq_map_user +EXPORT_SYMBOL vmlinux 0xbf7fd2f5 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0xbf8b39e9 isapnp_present +EXPORT_SYMBOL vmlinux 0xbf9bcc8d __cap_empty_set +EXPORT_SYMBOL vmlinux 0xbfc0209c netpoll_print_options +EXPORT_SYMBOL vmlinux 0xbfc177bc iowrite32_rep +EXPORT_SYMBOL vmlinux 0xbfc58b54 unregister_con_driver +EXPORT_SYMBOL vmlinux 0xbfced3e8 __bread +EXPORT_SYMBOL vmlinux 0xc003c637 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0xc01eed33 __copy_from_user_ll_nozero +EXPORT_SYMBOL vmlinux 0xc045ad4e timespec_trunc +EXPORT_SYMBOL vmlinux 0xc0580937 rb_erase +EXPORT_SYMBOL vmlinux 0xc0994f58 register_nls +EXPORT_SYMBOL vmlinux 0xc0a3d105 find_next_bit +EXPORT_SYMBOL vmlinux 0xc0e23754 d_validate +EXPORT_SYMBOL vmlinux 0xc0f65988 machine_real_restart +EXPORT_SYMBOL vmlinux 0xc11d8093 iov_shorten +EXPORT_SYMBOL vmlinux 0xc11f880a generic_file_splice_read +EXPORT_SYMBOL vmlinux 0xc1eba2e1 filp_close +EXPORT_SYMBOL vmlinux 0xc221d3fc idr_destroy +EXPORT_SYMBOL vmlinux 0xc254af48 dcache_lock +EXPORT_SYMBOL vmlinux 0xc255a509 gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0xc256e762 __bitmap_equal +EXPORT_SYMBOL vmlinux 0xc280a525 __copy_from_user_ll +EXPORT_SYMBOL vmlinux 0xc2887f7b generic_file_aio_read +EXPORT_SYMBOL vmlinux 0xc291a078 pcim_iounmap +EXPORT_SYMBOL vmlinux 0xc2a9d3d7 dev_unicast_add +EXPORT_SYMBOL vmlinux 0xc2aa3368 sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0xc2d711e1 krealloc +EXPORT_SYMBOL vmlinux 0xc2dc82ea blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0xc2e587d1 reset_devices +EXPORT_SYMBOL vmlinux 0xc2efd8d2 vfs_readdir +EXPORT_SYMBOL vmlinux 0xc30305ff put_disk +EXPORT_SYMBOL vmlinux 0xc3211abc ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0xc33f6f4c on_each_cpu +EXPORT_SYMBOL vmlinux 0xc3457aba nf_reinject +EXPORT_SYMBOL vmlinux 0xc34eb9db key_link +EXPORT_SYMBOL vmlinux 0xc38e5923 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0xc394ea46 llc_build_and_send_ui_pkt +EXPORT_SYMBOL vmlinux 0xc3a74635 __sk_dst_check +EXPORT_SYMBOL vmlinux 0xc3aaf0a9 __put_user_1 +EXPORT_SYMBOL vmlinux 0xc3cf1128 in_group_p +EXPORT_SYMBOL vmlinux 0xc3f6e67f end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0xc3fa6a59 memchr +EXPORT_SYMBOL vmlinux 0xc402cc99 register_acpi_notifier +EXPORT_SYMBOL vmlinux 0xc445bd4a proto_register +EXPORT_SYMBOL vmlinux 0xc475c1e7 proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0xc493bda5 vfs_quota_on_path +EXPORT_SYMBOL vmlinux 0xc499ae1e kstrdup +EXPORT_SYMBOL vmlinux 0xc4b23940 invalidate_inodes +EXPORT_SYMBOL vmlinux 0xc4becfd3 dst_destroy +EXPORT_SYMBOL vmlinux 0xc4fcd131 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0xc5014dac generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0xc52ca214 security_d_instantiate +EXPORT_SYMBOL vmlinux 0xc52f5714 fb_videomode_to_var +EXPORT_SYMBOL vmlinux 0xc5430dd0 pci_bus_type +EXPORT_SYMBOL vmlinux 0xc54ce3e4 xfrm_register_mode +EXPORT_SYMBOL vmlinux 0xc5534d64 ioread16 +EXPORT_SYMBOL vmlinux 0xc55f7dc7 _write_trylock +EXPORT_SYMBOL vmlinux 0xc5844fb8 __per_cpu_offset +EXPORT_SYMBOL vmlinux 0xc60f4c14 write_cache_pages +EXPORT_SYMBOL vmlinux 0xc61960ce default_llseek +EXPORT_SYMBOL vmlinux 0xc6276d68 audit_log_start +EXPORT_SYMBOL vmlinux 0xc68377fa vfs_getattr +EXPORT_SYMBOL vmlinux 0xc697e0de lookup_bdev +EXPORT_SYMBOL vmlinux 0xc6b6d891 vmap +EXPORT_SYMBOL vmlinux 0xc6f2e002 textsearch_find_continuous +EXPORT_SYMBOL vmlinux 0xc6f9a789 dentry_unhash +EXPORT_SYMBOL vmlinux 0xc70c454d get_empty_filp +EXPORT_SYMBOL vmlinux 0xc71bc033 ip_fragment +EXPORT_SYMBOL vmlinux 0xc7208c3a serial8250_resume_port +EXPORT_SYMBOL vmlinux 0xc79cd7c2 put_filp +EXPORT_SYMBOL vmlinux 0xc7a4fbed rtnl_lock +EXPORT_SYMBOL vmlinux 0xc7ad92e6 devm_request_irq +EXPORT_SYMBOL vmlinux 0xc7bd1792 inet_frag_find +EXPORT_SYMBOL vmlinux 0xc7c9a421 bio_clone +EXPORT_SYMBOL vmlinux 0xc7ec6c27 strspn +EXPORT_SYMBOL vmlinux 0xc829914e dquot_commit_info +EXPORT_SYMBOL vmlinux 0xc8450a24 proc_net_netfilter +EXPORT_SYMBOL vmlinux 0xc845a169 user_path_at +EXPORT_SYMBOL vmlinux 0xc862d5db iw_handler_get_thrspy +EXPORT_SYMBOL vmlinux 0xc86753d1 km_query +EXPORT_SYMBOL vmlinux 0xc86998aa xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0xc897c382 sg_init_table +EXPORT_SYMBOL vmlinux 0xc89ce177 unlock_new_inode +EXPORT_SYMBOL vmlinux 0xc89de40b netpoll_cleanup +EXPORT_SYMBOL vmlinux 0xc8b57c27 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0xc8ca3e25 acpi_get_child +EXPORT_SYMBOL vmlinux 0xc8cde211 inode_change_ok +EXPORT_SYMBOL vmlinux 0xc95da1a0 seq_printf +EXPORT_SYMBOL vmlinux 0xc98852cf stop_tty +EXPORT_SYMBOL vmlinux 0xc998d641 icmp_err_convert +EXPORT_SYMBOL vmlinux 0xc9ab2eef acpi_os_wait_events_complete +EXPORT_SYMBOL vmlinux 0xc9e70562 sk_release_kernel +EXPORT_SYMBOL vmlinux 0xca093ea2 pci_bus_write_config_byte +EXPORT_SYMBOL vmlinux 0xca0b951e xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0xca8acc78 acpi_dbg_level +EXPORT_SYMBOL vmlinux 0xca8c6ab5 directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0xcaa8c830 __serio_register_driver +EXPORT_SYMBOL vmlinux 0xcab1b20d cdev_add +EXPORT_SYMBOL vmlinux 0xcad73182 skb_copy_bits +EXPORT_SYMBOL vmlinux 0xcadcff37 netpoll_poll +EXPORT_SYMBOL vmlinux 0xcae26d6d register_netdev +EXPORT_SYMBOL vmlinux 0xcaec643d xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0xcaf86510 submit_bio +EXPORT_SYMBOL vmlinux 0xcb32da10 param_set_int +EXPORT_SYMBOL vmlinux 0xcb39cffe ida_get_new +EXPORT_SYMBOL vmlinux 0xcb4b127b blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0xcb5b3e6d pci_match_id +EXPORT_SYMBOL vmlinux 0xcb6beb40 hweight32 +EXPORT_SYMBOL vmlinux 0xcb7131fb fb_get_options +EXPORT_SYMBOL vmlinux 0xcb733bf2 acpi_bus_set_power +EXPORT_SYMBOL vmlinux 0xcb94242f netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0xcb96883b vcc_insert_socket +EXPORT_SYMBOL vmlinux 0xcba8489a __kfree_skb +EXPORT_SYMBOL vmlinux 0xcc0cc26d blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0xcc248d26 serial8250_suspend_port +EXPORT_SYMBOL vmlinux 0xcc2cc10c bdi_destroy +EXPORT_SYMBOL vmlinux 0xcc36f32e fb_unregister_client +EXPORT_SYMBOL vmlinux 0xcc5005fe msleep_interruptible +EXPORT_SYMBOL vmlinux 0xcc51ee50 dma_spin_lock +EXPORT_SYMBOL vmlinux 0xcc732931 proto_unregister +EXPORT_SYMBOL vmlinux 0xcc7dd533 vfs_quota_on_mount +EXPORT_SYMBOL vmlinux 0xcc7fa952 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0xcc94df08 find_vma +EXPORT_SYMBOL vmlinux 0xcc9a02d9 I_BDEV +EXPORT_SYMBOL vmlinux 0xccc2b70c per_cpu__current_task +EXPORT_SYMBOL vmlinux 0xccc88f01 test_set_page_writeback +EXPORT_SYMBOL vmlinux 0xcd0f7017 page_readlink +EXPORT_SYMBOL vmlinux 0xcd39f5d3 tcp_disconnect +EXPORT_SYMBOL vmlinux 0xcd3e7939 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0xcd5a4a68 bdevname +EXPORT_SYMBOL vmlinux 0xcd70490a skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0xcd9b0898 tcf_hash_search +EXPORT_SYMBOL vmlinux 0xcd9f373b con_copy_unimap +EXPORT_SYMBOL vmlinux 0xce1524c4 atm_dev_lookup +EXPORT_SYMBOL vmlinux 0xce337fa8 proc_create_data +EXPORT_SYMBOL vmlinux 0xce36ded6 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0xce4904a4 acpi_leave_sleep_state +EXPORT_SYMBOL vmlinux 0xce5ac24f zlib_inflate_workspacesize +EXPORT_SYMBOL vmlinux 0xce612ea4 file_fsync +EXPORT_SYMBOL vmlinux 0xce723cc8 blk_init_tags +EXPORT_SYMBOL vmlinux 0xce88367d ida_pre_get +EXPORT_SYMBOL vmlinux 0xce9e72a3 module_put +EXPORT_SYMBOL vmlinux 0xceeb549c blk_put_request +EXPORT_SYMBOL vmlinux 0xceef4e24 atm_charge +EXPORT_SYMBOL vmlinux 0xcefcd99a serial8250_unregister_port +EXPORT_SYMBOL vmlinux 0xcf047c83 acpi_disable_gpe +EXPORT_SYMBOL vmlinux 0xcf08452e iput +EXPORT_SYMBOL vmlinux 0xcf150d95 tty_vhangup +EXPORT_SYMBOL vmlinux 0xcf3e0968 sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0xcfa894d9 netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0xcfadd723 __percpu_counter_add +EXPORT_SYMBOL vmlinux 0xcfd3018e set_normalized_timespec +EXPORT_SYMBOL vmlinux 0xd0181f4f __bitmap_xor +EXPORT_SYMBOL vmlinux 0xd018a27d bmap +EXPORT_SYMBOL vmlinux 0xd027eb39 acpi_unlock_battery_dir +EXPORT_SYMBOL vmlinux 0xd02cc869 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0xd0350e3c simple_transaction_get +EXPORT_SYMBOL vmlinux 0xd03868f5 nf_log_packet +EXPORT_SYMBOL vmlinux 0xd04b6661 sysctl_intvec +EXPORT_SYMBOL vmlinux 0xd04b9cd3 unbind_con_driver +EXPORT_SYMBOL vmlinux 0xd08197fa acpi_load_tables +EXPORT_SYMBOL vmlinux 0xd08c24cd scm_detach_fds +EXPORT_SYMBOL vmlinux 0xd098727e __brelse +EXPORT_SYMBOL vmlinux 0xd0a8d4dc thermal_zone_unbind_cooling_device +EXPORT_SYMBOL vmlinux 0xd0d8621b strlen +EXPORT_SYMBOL vmlinux 0xd0dbe9d8 posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0xd0ee38b8 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0xd1182380 pci_remove_bus_device +EXPORT_SYMBOL vmlinux 0xd11e5af8 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0xd1347e34 inode_add_bytes +EXPORT_SYMBOL vmlinux 0xd1472061 acpi_pci_register_driver +EXPORT_SYMBOL vmlinux 0xd18615e8 pci_remove_behind_bridge +EXPORT_SYMBOL vmlinux 0xd18b6eb2 acpi_unmap_lsapic +EXPORT_SYMBOL vmlinux 0xd19ee9fe console_start +EXPORT_SYMBOL vmlinux 0xd1c080d6 no_llseek +EXPORT_SYMBOL vmlinux 0xd1d82a95 ip_nat_decode_session +EXPORT_SYMBOL vmlinux 0xd1eaafc7 skb_queue_purge +EXPORT_SYMBOL vmlinux 0xd1f6c5f3 smp_num_siblings +EXPORT_SYMBOL vmlinux 0xd1f91bcd dev_base_lock +EXPORT_SYMBOL vmlinux 0xd20b4b98 pci_get_device +EXPORT_SYMBOL vmlinux 0xd22954e6 vfs_get_dqinfo +EXPORT_SYMBOL vmlinux 0xd2460501 skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0xd251d7b0 security_socket_getpeersec_dgram +EXPORT_SYMBOL vmlinux 0xd2555f19 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0xd25d4f74 console_blank_hook +EXPORT_SYMBOL vmlinux 0xd267d42c down_killable +EXPORT_SYMBOL vmlinux 0xd2965f6f kthread_should_stop +EXPORT_SYMBOL vmlinux 0xd2981b51 request_key_async_with_auxdata +EXPORT_SYMBOL vmlinux 0xd2d92c24 xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0xd2dd257b blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0xd2f85739 nf_ip_checksum +EXPORT_SYMBOL vmlinux 0xd319ac2c sock_wfree +EXPORT_SYMBOL vmlinux 0xd34f0c62 gen_pool_create +EXPORT_SYMBOL vmlinux 0xd3639e28 skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0xd3951da4 acpi_resource_to_address64 +EXPORT_SYMBOL vmlinux 0xd3956fd1 aio_complete +EXPORT_SYMBOL vmlinux 0xd3a9c08c sock_no_getname +EXPORT_SYMBOL vmlinux 0xd3b94175 tcp_v4_md5_do_add +EXPORT_SYMBOL vmlinux 0xd3f74cf1 interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0xd408955a blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0xd4186e38 get_sb_bdev +EXPORT_SYMBOL vmlinux 0xd42b7232 _write_unlock_bh +EXPORT_SYMBOL vmlinux 0xd42cdd09 vfs_quota_off +EXPORT_SYMBOL vmlinux 0xd45e94fb sk_dst_check +EXPORT_SYMBOL vmlinux 0xd48115c6 vfs_dq_transfer +EXPORT_SYMBOL vmlinux 0xd4ce4757 netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0xd4ce7ad8 single_open +EXPORT_SYMBOL vmlinux 0xd4d4dbe0 udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0xd5539d00 blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0xd5688a7a radix_tree_insert +EXPORT_SYMBOL vmlinux 0xd5b037e1 kref_put +EXPORT_SYMBOL vmlinux 0xd5fbb0b5 pci_set_consistent_dma_mask +EXPORT_SYMBOL vmlinux 0xd6035d05 do_settimeofday +EXPORT_SYMBOL vmlinux 0xd61689b3 simple_fill_super +EXPORT_SYMBOL vmlinux 0xd62c833f schedule_timeout +EXPORT_SYMBOL vmlinux 0xd630c1d9 sock_no_connect +EXPORT_SYMBOL vmlinux 0xd65231ba sb_set_blocksize +EXPORT_SYMBOL vmlinux 0xd6644216 pci_find_bus +EXPORT_SYMBOL vmlinux 0xd682c6d5 path_get +EXPORT_SYMBOL vmlinux 0xd6a5d3a2 inode_permission +EXPORT_SYMBOL vmlinux 0xd6a78d08 smp_call_function_single +EXPORT_SYMBOL vmlinux 0xd6afd583 __scm_destroy +EXPORT_SYMBOL vmlinux 0xd6b33026 cpu_khz +EXPORT_SYMBOL vmlinux 0xd6b9ba7d nf_register_queue_handler +EXPORT_SYMBOL vmlinux 0xd6ded91b cfb_imageblit +EXPORT_SYMBOL vmlinux 0xd6ee688f vmalloc +EXPORT_SYMBOL vmlinux 0xd73dd6a8 sock_i_ino +EXPORT_SYMBOL vmlinux 0xd741c0b1 tcp_md5_hash_skb_data +EXPORT_SYMBOL vmlinux 0xd769cb4a ps2_handle_response +EXPORT_SYMBOL vmlinux 0xd7776d62 tcf_unregister_action +EXPORT_SYMBOL vmlinux 0xd77a2498 mca_device_status +EXPORT_SYMBOL vmlinux 0xd77e8ec3 elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0xd7818f8f __bio_clone +EXPORT_SYMBOL vmlinux 0xd7927633 __module_put_and_exit +EXPORT_SYMBOL vmlinux 0xd79b5a02 allow_signal +EXPORT_SYMBOL vmlinux 0xd7a4eb12 inet_csk_accept +EXPORT_SYMBOL vmlinux 0xd7a6fafa panic_notifier_list +EXPORT_SYMBOL vmlinux 0xd7c61352 register_qdisc +EXPORT_SYMBOL vmlinux 0xd7c7a1ca fb_blank +EXPORT_SYMBOL vmlinux 0xd7d307c1 pci_find_device +EXPORT_SYMBOL vmlinux 0xd7dd777b reserve_perfctr_nmi +EXPORT_SYMBOL vmlinux 0xd86222ae acpi_root_dir +EXPORT_SYMBOL vmlinux 0xd88f695a __mod_timer +EXPORT_SYMBOL vmlinux 0xd89da37f movable_zone +EXPORT_SYMBOL vmlinux 0xd89e09cf kobject_del +EXPORT_SYMBOL vmlinux 0xd8a2ab95 in_egroup_p +EXPORT_SYMBOL vmlinux 0xd8c5185c pci_iounmap +EXPORT_SYMBOL vmlinux 0xd8e484f0 register_chrdev_region +EXPORT_SYMBOL vmlinux 0xd8e50a73 __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0xd9091363 acpi_install_notify_handler +EXPORT_SYMBOL vmlinux 0xd90bbaa8 mpage_writepage +EXPORT_SYMBOL vmlinux 0xd915e501 bio_copy_user +EXPORT_SYMBOL vmlinux 0xd9233794 uart_get_divisor +EXPORT_SYMBOL vmlinux 0xd937a5df generic_getxattr +EXPORT_SYMBOL vmlinux 0xd985dc99 mempool_free_pages +EXPORT_SYMBOL vmlinux 0xd9c272aa mca_mark_as_unused +EXPORT_SYMBOL vmlinux 0xd9dc2880 cpu_mask_all +EXPORT_SYMBOL vmlinux 0xd9f8bb83 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0xda08c0d7 pcibios_get_irq_routing_table +EXPORT_SYMBOL vmlinux 0xda0a6b0e acpi_map_lsapic +EXPORT_SYMBOL vmlinux 0xda0cdc16 bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0xda1a7335 kasprintf +EXPORT_SYMBOL vmlinux 0xda34a416 inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0xda60a3d7 task_session_nr_ns +EXPORT_SYMBOL vmlinux 0xda72fe1a acpi_check_mem_region +EXPORT_SYMBOL vmlinux 0xda73a1d0 __check_region +EXPORT_SYMBOL vmlinux 0xda7ca6cb fb_mode_is_equal +EXPORT_SYMBOL vmlinux 0xda8af7ad fb_find_nearest_mode +EXPORT_SYMBOL vmlinux 0xda8fd495 isapnp_write_byte +EXPORT_SYMBOL vmlinux 0xda928914 nmi_watchdog +EXPORT_SYMBOL vmlinux 0xda9a9084 sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0xdaa2d809 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0xdaa57ec3 totalhigh_pages +EXPORT_SYMBOL vmlinux 0xdac8c655 tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0xdacb38a4 skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0xdad96e87 thermal_cooling_device_unregister +EXPORT_SYMBOL vmlinux 0xdadb70ca arp_send +EXPORT_SYMBOL vmlinux 0xdadbcf4d kthread_stop +EXPORT_SYMBOL vmlinux 0xdb2a9948 vfs_rename +EXPORT_SYMBOL vmlinux 0xdb3eb001 set_user_nice +EXPORT_SYMBOL vmlinux 0xdb5616f8 elv_dequeue_request +EXPORT_SYMBOL vmlinux 0xdb566581 __breadahead +EXPORT_SYMBOL vmlinux 0xdb6ce750 copy_io_context +EXPORT_SYMBOL vmlinux 0xdb864d65 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0xdb8aa9e9 unmap_mapping_range +EXPORT_SYMBOL vmlinux 0xdbafd492 dquot_alloc_inode +EXPORT_SYMBOL vmlinux 0xdbcd416e sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0xdc14eda7 pci_pci_problems +EXPORT_SYMBOL vmlinux 0xdc2adb35 add_taint +EXPORT_SYMBOL vmlinux 0xdc3eaf70 iomem_resource +EXPORT_SYMBOL vmlinux 0xdc43a9c8 daemonize +EXPORT_SYMBOL vmlinux 0xdc6466cb tcp_getsockopt +EXPORT_SYMBOL vmlinux 0xdc64f382 put_tty_driver +EXPORT_SYMBOL vmlinux 0xdc6b8fd3 bio_split +EXPORT_SYMBOL vmlinux 0xdc6bb01c blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0xdc7f204c do_sync_write +EXPORT_SYMBOL vmlinux 0xdc873a70 screen_info +EXPORT_SYMBOL vmlinux 0xdc992a0b d_add_ci +EXPORT_SYMBOL vmlinux 0xdd0a2ba2 strlcat +EXPORT_SYMBOL vmlinux 0xdd3e7f85 pci_save_state +EXPORT_SYMBOL vmlinux 0xdd434f0b unregister_snap_client +EXPORT_SYMBOL vmlinux 0xdd647a28 fddi_type_trans +EXPORT_SYMBOL vmlinux 0xdd6bfccd radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0xddc1ac11 bioset_integrity_free +EXPORT_SYMBOL vmlinux 0xddd724d4 get_sb_nodev +EXPORT_SYMBOL vmlinux 0xddeef053 vfs_stat +EXPORT_SYMBOL vmlinux 0xde02175d __tcp_get_md5sig_pool +EXPORT_SYMBOL vmlinux 0xde09950a genl_unregister_ops +EXPORT_SYMBOL vmlinux 0xde1a80af km_state_notify +EXPORT_SYMBOL vmlinux 0xde343396 dquot_acquire +EXPORT_SYMBOL vmlinux 0xde3e397e ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0xde75b689 set_irq_type +EXPORT_SYMBOL vmlinux 0xde9360ba totalram_pages +EXPORT_SYMBOL vmlinux 0xde9b9de5 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0xdec1df47 register_binfmt +EXPORT_SYMBOL vmlinux 0xdef9885a vcc_release_async +EXPORT_SYMBOL vmlinux 0xdf0da3cc acpi_get_devices +EXPORT_SYMBOL vmlinux 0xdf3a388f alloc_disk_node +EXPORT_SYMBOL vmlinux 0xdf60cc27 __print_symbol +EXPORT_SYMBOL vmlinux 0xdf6870a5 bio_integrity_split +EXPORT_SYMBOL vmlinux 0xdf73f0f8 eth_header +EXPORT_SYMBOL vmlinux 0xdf8c695a __ndelay +EXPORT_SYMBOL vmlinux 0xdf8f40aa dentry_open +EXPORT_SYMBOL vmlinux 0xdf929370 fs_overflowgid +EXPORT_SYMBOL vmlinux 0xdfbbd7c2 dquot_mark_dquot_dirty +EXPORT_SYMBOL vmlinux 0xdfc50947 __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0xdfce2fef blk_requeue_request +EXPORT_SYMBOL vmlinux 0xdff6866a eisa_bus_type +EXPORT_SYMBOL vmlinux 0xdffd2210 generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0xe00b7945 __kill_fasync +EXPORT_SYMBOL vmlinux 0xe00fb238 release_resource +EXPORT_SYMBOL vmlinux 0xe01239e7 get_unmapped_area +EXPORT_SYMBOL vmlinux 0xe0222c02 skb_kill_datagram +EXPORT_SYMBOL vmlinux 0xe06b4431 wait_for_key_construction +EXPORT_SYMBOL vmlinux 0xe075d6eb iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0xe07fb1b9 __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0xe0ac8bd2 acpi_bus_generate_netlink_event +EXPORT_SYMBOL vmlinux 0xe0ae4bf3 acpi_bus_start +EXPORT_SYMBOL vmlinux 0xe0b13336 argv_free +EXPORT_SYMBOL vmlinux 0xe0b5502d adjust_resource +EXPORT_SYMBOL vmlinux 0xe0b94d92 xfrm_user_policy +EXPORT_SYMBOL vmlinux 0xe13cd8a7 dmi_name_in_vendors +EXPORT_SYMBOL vmlinux 0xe15aeee2 downgrade_write +EXPORT_SYMBOL vmlinux 0xe16f8a79 per_cpu__irq_regs +EXPORT_SYMBOL vmlinux 0xe173771d __tcf_em_tree_match +EXPORT_SYMBOL vmlinux 0xe1761617 security_inet_conn_request +EXPORT_SYMBOL vmlinux 0xe17f063f netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0xe1815c4b vfs_permission +EXPORT_SYMBOL vmlinux 0xe1a958de dev_get_by_name +EXPORT_SYMBOL vmlinux 0xe1aa5d89 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0xe1adb9d7 end_page_writeback +EXPORT_SYMBOL vmlinux 0xe1b5d63c input_close_device +EXPORT_SYMBOL vmlinux 0xe1f9b589 nf_log_unregister +EXPORT_SYMBOL vmlinux 0xe23aaf25 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0xe244dbfa vfs_set_dqinfo +EXPORT_SYMBOL vmlinux 0xe24d3a97 jiffies_64 +EXPORT_SYMBOL vmlinux 0xe2500be9 skb_unlink +EXPORT_SYMBOL vmlinux 0xe2819ad5 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0xe2a955ae is_bad_inode +EXPORT_SYMBOL vmlinux 0xe2c7ac24 acpi_unlock_ac_dir +EXPORT_SYMBOL vmlinux 0xe2c83555 may_umount_tree +EXPORT_SYMBOL vmlinux 0xe2d5255a strcmp +EXPORT_SYMBOL vmlinux 0xe2fae716 kmemdup +EXPORT_SYMBOL vmlinux 0xe328560d seq_open +EXPORT_SYMBOL vmlinux 0xe351633f genl_register_family +EXPORT_SYMBOL vmlinux 0xe36a824c serio_open +EXPORT_SYMBOL vmlinux 0xe3b260c9 try_to_release_page +EXPORT_SYMBOL vmlinux 0xe3fbe148 acpi_install_table_handler +EXPORT_SYMBOL vmlinux 0xe42acb6e init_task +EXPORT_SYMBOL vmlinux 0xe43617f7 acpi_gbl_FADT +EXPORT_SYMBOL vmlinux 0xe4398a07 __devm_release_region +EXPORT_SYMBOL vmlinux 0xe44762ee dquot_drop +EXPORT_SYMBOL vmlinux 0xe456bd3a complete +EXPORT_SYMBOL vmlinux 0xe466d75a take_over_console +EXPORT_SYMBOL vmlinux 0xe484e35f ioread32 +EXPORT_SYMBOL vmlinux 0xe4870354 _read_trylock +EXPORT_SYMBOL vmlinux 0xe499aa3d kobject_put +EXPORT_SYMBOL vmlinux 0xe4c1df3e _read_lock_bh +EXPORT_SYMBOL vmlinux 0xe4ed3217 tcf_generic_walker +EXPORT_SYMBOL vmlinux 0xe4f7e8ff mnt_pin +EXPORT_SYMBOL vmlinux 0xe5122890 flow_cache_genid +EXPORT_SYMBOL vmlinux 0xe51a6a74 dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0xe523ad75 synchronize_irq +EXPORT_SYMBOL vmlinux 0xe5279b40 inode_init_once +EXPORT_SYMBOL vmlinux 0xe55704ab nf_hooks +EXPORT_SYMBOL vmlinux 0xe56b3a42 register_console +EXPORT_SYMBOL vmlinux 0xe57878a1 in6_pton +EXPORT_SYMBOL vmlinux 0xe5867808 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0xe5c78a99 do_blank_screen +EXPORT_SYMBOL vmlinux 0xe5c8826a tty_check_change +EXPORT_SYMBOL vmlinux 0xe5d4e748 set_device_ro +EXPORT_SYMBOL vmlinux 0xe5f44a70 tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0xe5f7f7ea tcf_destroy_chain +EXPORT_SYMBOL vmlinux 0xe65db9e5 find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0xe660d6b0 brioctl_set +EXPORT_SYMBOL vmlinux 0xe68f09e6 kobject_set_name +EXPORT_SYMBOL vmlinux 0xe6ba7a57 pci_bus_size_bridges +EXPORT_SYMBOL vmlinux 0xe6ebc016 key_create_or_update +EXPORT_SYMBOL vmlinux 0xe6fbe430 can_do_mlock +EXPORT_SYMBOL vmlinux 0xe716baed acpi_unregister_ioapic +EXPORT_SYMBOL vmlinux 0xe7300f3a eth_header_cache +EXPORT_SYMBOL vmlinux 0xe77b96fb cancel_dirty_page +EXPORT_SYMBOL vmlinux 0xe7838b4d per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0xe7a200c0 key_negate_and_link +EXPORT_SYMBOL vmlinux 0xe7c7477a sock_get_timestamp +EXPORT_SYMBOL vmlinux 0xe7d4daac seq_list_next +EXPORT_SYMBOL vmlinux 0xe814a831 __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0xe8299988 netlink_kernel_release +EXPORT_SYMBOL vmlinux 0xe84f9e13 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0xe8548307 block_commit_write +EXPORT_SYMBOL vmlinux 0xe87933d1 simple_unlink +EXPORT_SYMBOL vmlinux 0xe8a87110 bio_integrity_set_tag +EXPORT_SYMBOL vmlinux 0xe8be84a5 ida_destroy +EXPORT_SYMBOL vmlinux 0xe8cd902e hweight16 +EXPORT_SYMBOL vmlinux 0xe8e57025 blkdev_put +EXPORT_SYMBOL vmlinux 0xe8ec656c udp_lib_get_port +EXPORT_SYMBOL vmlinux 0xe910b532 del_timer_sync +EXPORT_SYMBOL vmlinux 0xe91130ba bio_free +EXPORT_SYMBOL vmlinux 0xe914e41e strcpy +EXPORT_SYMBOL vmlinux 0xe92f06db sk_send_sigurg +EXPORT_SYMBOL vmlinux 0xe9456a5a sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0xe959b7fc kmem_cache_free +EXPORT_SYMBOL vmlinux 0xe96bd70d read_dev_sector +EXPORT_SYMBOL vmlinux 0xe997667b wrmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xe99b4cb8 km_policy_expired +EXPORT_SYMBOL vmlinux 0xe9ec0b40 inet_frag_destroy +EXPORT_SYMBOL vmlinux 0xea064ef3 blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0xea10655a __bitmap_intersects +EXPORT_SYMBOL vmlinux 0xea2d33a2 radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0xea4aa23a skb_split +EXPORT_SYMBOL vmlinux 0xea507731 sock_no_poll +EXPORT_SYMBOL vmlinux 0xea5e5581 ida_remove +EXPORT_SYMBOL vmlinux 0xea6fcdaa genl_unregister_family +EXPORT_SYMBOL vmlinux 0xea7987f1 key_update +EXPORT_SYMBOL vmlinux 0xea858cb5 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0xea91d087 rtnl_unicast +EXPORT_SYMBOL vmlinux 0xeadb7ac6 inode_setattr +EXPORT_SYMBOL vmlinux 0xeae3dfd6 __const_udelay +EXPORT_SYMBOL vmlinux 0xeae64ddf shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0xeb0013fb xfrm_state_delete +EXPORT_SYMBOL vmlinux 0xeb1fabf6 interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0xeb395084 param_get_invbool +EXPORT_SYMBOL vmlinux 0xeb3e04ca task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0xeb59bdf3 flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0xeb6b0c32 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0xeb8f54b3 strstrip +EXPORT_SYMBOL vmlinux 0xeb99e2cf acpi_notifier_call_chain +EXPORT_SYMBOL vmlinux 0xebc23a99 pci_remove_bus +EXPORT_SYMBOL vmlinux 0xebd273a6 strict_strtoull +EXPORT_SYMBOL vmlinux 0xebeb702a page_symlink +EXPORT_SYMBOL vmlinux 0xec10ab36 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0xec2a526e pnp_register_card_driver +EXPORT_SYMBOL vmlinux 0xec4d6b11 uart_update_timeout +EXPORT_SYMBOL vmlinux 0xec815df3 tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0xec860422 bioset_free +EXPORT_SYMBOL vmlinux 0xec872413 do_sync_read +EXPORT_SYMBOL vmlinux 0xeca64575 locks_init_lock +EXPORT_SYMBOL vmlinux 0xecc088c7 pci_try_set_mwi +EXPORT_SYMBOL vmlinux 0xecc0f464 pci_enable_wake +EXPORT_SYMBOL vmlinux 0xecde1418 _spin_lock_irq +EXPORT_SYMBOL vmlinux 0xeceb08bd __locks_copy_lock +EXPORT_SYMBOL vmlinux 0xecef08c5 __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0xecf7a003 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0xed311d95 clear_inode +EXPORT_SYMBOL vmlinux 0xed4d2540 ps2_cmd_aborted +EXPORT_SYMBOL vmlinux 0xed5cc4ed nla_put +EXPORT_SYMBOL vmlinux 0xed633abc pv_irq_ops +EXPORT_SYMBOL vmlinux 0xed7be9b1 inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0xedbaee5e nla_strcmp +EXPORT_SYMBOL vmlinux 0xedc03953 iounmap +EXPORT_SYMBOL vmlinux 0xedcab7dd dma_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0xedd14538 param_get_uint +EXPORT_SYMBOL vmlinux 0xedfbb839 pci_assign_resource +EXPORT_SYMBOL vmlinux 0xee298049 flush_old_exec +EXPORT_SYMBOL vmlinux 0xee2d0fc7 _local_bh_enable +EXPORT_SYMBOL vmlinux 0xee5a4854 netpoll_send_udp +EXPORT_SYMBOL vmlinux 0xee7eb9e1 pnp_platform_devices +EXPORT_SYMBOL vmlinux 0xee8c30ad dev_getbyhwaddr +EXPORT_SYMBOL vmlinux 0xeea5b28a ps2_init +EXPORT_SYMBOL vmlinux 0xeea9dbaf bitmap_bitremap +EXPORT_SYMBOL vmlinux 0xeeb1717c param_array_get +EXPORT_SYMBOL vmlinux 0xef3bd862 mca_find_unused_adapter +EXPORT_SYMBOL vmlinux 0xef5145aa pci_enable_bridges +EXPORT_SYMBOL vmlinux 0xef58dbae devm_free_irq +EXPORT_SYMBOL vmlinux 0xef611cb4 sock_kfree_s +EXPORT_SYMBOL vmlinux 0xef8e7263 qdisc_watchdog_cancel +EXPORT_SYMBOL vmlinux 0xef9aedfc boot_option_idle_override +EXPORT_SYMBOL vmlinux 0xefa8ee7f mark_page_accessed +EXPORT_SYMBOL vmlinux 0xefdd70ce security_secid_to_secctx +EXPORT_SYMBOL vmlinux 0xefe099c3 acpi_get_event_status +EXPORT_SYMBOL vmlinux 0xefe33ee0 vfs_rmdir +EXPORT_SYMBOL vmlinux 0xf0009fee put_pages_list +EXPORT_SYMBOL vmlinux 0xf0196793 dquot_initialize +EXPORT_SYMBOL vmlinux 0xf0272b2b atm_init_aal5 +EXPORT_SYMBOL vmlinux 0xf030220d __inc_zone_page_state +EXPORT_SYMBOL vmlinux 0xf0653234 thermal_zone_device_unregister +EXPORT_SYMBOL vmlinux 0xf065f629 ioread16be +EXPORT_SYMBOL vmlinux 0xf070e96e pci_scan_slot +EXPORT_SYMBOL vmlinux 0xf0b57c68 param_set_long +EXPORT_SYMBOL vmlinux 0xf0e34e49 wake_up_process +EXPORT_SYMBOL vmlinux 0xf0ed7bac unregister_8022_client +EXPORT_SYMBOL vmlinux 0xf0ef603d skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0xf0f1246c kvasprintf +EXPORT_SYMBOL vmlinux 0xf0f78e82 generic_write_checks +EXPORT_SYMBOL vmlinux 0xf10de535 ioread8 +EXPORT_SYMBOL vmlinux 0xf10f68ed pci_scan_bridge +EXPORT_SYMBOL vmlinux 0xf11543ff find_first_zero_bit +EXPORT_SYMBOL vmlinux 0xf13532a1 tcf_action_exec +EXPORT_SYMBOL vmlinux 0xf138c1be call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0xf1434257 skb_dequeue +EXPORT_SYMBOL vmlinux 0xf15735e2 pnp_possible_config +EXPORT_SYMBOL vmlinux 0xf162fe2d sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0xf1713ed4 write_inode_now +EXPORT_SYMBOL vmlinux 0xf174ed48 acquire_console_sem +EXPORT_SYMBOL vmlinux 0xf19119aa pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0xf195c682 fb_invert_cmaps +EXPORT_SYMBOL vmlinux 0xf1ad68d7 serio_reconnect +EXPORT_SYMBOL vmlinux 0xf1ad817e blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0xf1bd5e71 framebuffer_alloc +EXPORT_SYMBOL vmlinux 0xf1d294f5 input_event +EXPORT_SYMBOL vmlinux 0xf1deabf2 div64_u64 +EXPORT_SYMBOL vmlinux 0xf1e98c74 avenrun +EXPORT_SYMBOL vmlinux 0xf1f95741 kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0xf20dabd8 free_irq +EXPORT_SYMBOL vmlinux 0xf246de13 tcf_hash_destroy +EXPORT_SYMBOL vmlinux 0xf2997713 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0xf2a6d2bf xfrm_policy_count +EXPORT_SYMBOL vmlinux 0xf2afa595 param_get_charp +EXPORT_SYMBOL vmlinux 0xf2bdd5e9 neigh_table_init +EXPORT_SYMBOL vmlinux 0xf2e60896 __inet6_lookup_established +EXPORT_SYMBOL vmlinux 0xf2e74040 mca_set_adapter_name +EXPORT_SYMBOL vmlinux 0xf313da4e sha_transform +EXPORT_SYMBOL vmlinux 0xf33140d3 fb_pan_display +EXPORT_SYMBOL vmlinux 0xf3341268 __clear_user +EXPORT_SYMBOL vmlinux 0xf338d4c3 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0xf346231f seq_list_start_head +EXPORT_SYMBOL vmlinux 0xf36a0c33 xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0xf375015b elv_rb_del +EXPORT_SYMBOL vmlinux 0xf378f4e3 tcf_em_unregister +EXPORT_SYMBOL vmlinux 0xf3792421 __netif_schedule +EXPORT_SYMBOL vmlinux 0xf37de52d inet_accept +EXPORT_SYMBOL vmlinux 0xf37e57bd blk_alloc_queue +EXPORT_SYMBOL vmlinux 0xf39bf4d9 put_cmsg +EXPORT_SYMBOL vmlinux 0xf39c0363 ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0xf39c337d tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0xf39d8651 tty_port_init +EXPORT_SYMBOL vmlinux 0xf3ad6dbf __neigh_event_send +EXPORT_SYMBOL vmlinux 0xf3bf0bce __bitmap_complement +EXPORT_SYMBOL vmlinux 0xf3ef7c1c elevator_exit +EXPORT_SYMBOL vmlinux 0xf441ac43 ioread8_rep +EXPORT_SYMBOL vmlinux 0xf47d47e0 acpi_enable_gpe +EXPORT_SYMBOL vmlinux 0xf48a2c4c MCA_bus +EXPORT_SYMBOL vmlinux 0xf49bc67a atm_pcr_goal +EXPORT_SYMBOL vmlinux 0xf4a5c213 avail_to_resrv_perfctr_nmi_bit +EXPORT_SYMBOL vmlinux 0xf4e10c23 nf_afinfo +EXPORT_SYMBOL vmlinux 0xf4e53016 dcache_dir_close +EXPORT_SYMBOL vmlinux 0xf4f14de6 rtnl_trylock +EXPORT_SYMBOL vmlinux 0xf4f52f93 dqstats +EXPORT_SYMBOL vmlinux 0xf502d273 acpi_get_current_resources +EXPORT_SYMBOL vmlinux 0xf5030b04 backlight_device_unregister +EXPORT_SYMBOL vmlinux 0xf50e57ea vfs_symlink +EXPORT_SYMBOL vmlinux 0xf51ae235 touch_nmi_watchdog +EXPORT_SYMBOL vmlinux 0xf51dbefa vfs_writev +EXPORT_SYMBOL vmlinux 0xf524ae30 dev_mc_add +EXPORT_SYMBOL vmlinux 0xf53d4c26 qdisc_class_hash_destroy +EXPORT_SYMBOL vmlinux 0xf54e0dee rtnl_notify +EXPORT_SYMBOL vmlinux 0xf58036a6 skb_find_text +EXPORT_SYMBOL vmlinux 0xf5919af3 pci_set_dma_seg_boundary +EXPORT_SYMBOL vmlinux 0xf5c05914 generic_segment_checks +EXPORT_SYMBOL vmlinux 0xf5ce9811 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0xf5d2600f key_instantiate_and_link +EXPORT_SYMBOL vmlinux 0xf5d9369b kobject_get +EXPORT_SYMBOL vmlinux 0xf5f1a441 neigh_destroy +EXPORT_SYMBOL vmlinux 0xf5f40bed unregister_netdevice +EXPORT_SYMBOL vmlinux 0xf5f63aa2 xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0xf61784d8 generic_writepages +EXPORT_SYMBOL vmlinux 0xf633d68b __pagevec_release +EXPORT_SYMBOL vmlinux 0xf6bb4729 color_table +EXPORT_SYMBOL vmlinux 0xf6cf7da3 dma_set_mask +EXPORT_SYMBOL vmlinux 0xf6da16bc simple_lookup +EXPORT_SYMBOL vmlinux 0xf6de26c7 uart_match_port +EXPORT_SYMBOL vmlinux 0xf6e792ed blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0xf6ebc03b net_ratelimit +EXPORT_SYMBOL vmlinux 0xf6fbf60b misc_deregister +EXPORT_SYMBOL vmlinux 0xf71a9153 pci_request_selected_regions +EXPORT_SYMBOL vmlinux 0xf73502da bd_release +EXPORT_SYMBOL vmlinux 0xf75c62c5 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0xf7623914 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0xf76faf30 arp_xmit +EXPORT_SYMBOL vmlinux 0xf78d04ab netlink_register_notifier +EXPORT_SYMBOL vmlinux 0xf7b8f31d pci_find_parent_resource +EXPORT_SYMBOL vmlinux 0xf7ee849b mca_device_transform_irq +EXPORT_SYMBOL vmlinux 0xf82abc1d isa_dma_bridge_buggy +EXPORT_SYMBOL vmlinux 0xf82e3d47 acpi_initialize_objects +EXPORT_SYMBOL vmlinux 0xf82ee120 input_set_capability +EXPORT_SYMBOL vmlinux 0xf82f1109 utf8_wctomb +EXPORT_SYMBOL vmlinux 0xf8439cdb vfs_get_dqblk +EXPORT_SYMBOL vmlinux 0xf85c5d9b sock_no_bind +EXPORT_SYMBOL vmlinux 0xf878cf3a inet_release +EXPORT_SYMBOL vmlinux 0xf8814f73 rb_last +EXPORT_SYMBOL vmlinux 0xf88b174f vfs_mkdir +EXPORT_SYMBOL vmlinux 0xf88e0ee2 acpi_get_table_header +EXPORT_SYMBOL vmlinux 0xf890fe7f pm_idle +EXPORT_SYMBOL vmlinux 0xf8aa47ae mutex_lock_killable +EXPORT_SYMBOL vmlinux 0xf8b30e93 mempool_create +EXPORT_SYMBOL vmlinux 0xf8d2e4e6 set_trace_device +EXPORT_SYMBOL vmlinux 0xf8fee43d qdisc_watchdog_init +EXPORT_SYMBOL vmlinux 0xf9296dc3 xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0xf950d92e pci_set_dma_max_seg_size +EXPORT_SYMBOL vmlinux 0xf99c05c9 acpi_bus_get_device +EXPORT_SYMBOL vmlinux 0xf9a425be iw_handler_get_spy +EXPORT_SYMBOL vmlinux 0xf9a482f9 msleep +EXPORT_SYMBOL vmlinux 0xf9c73e20 free_netdev +EXPORT_SYMBOL vmlinux 0xf9e91159 should_remove_suid +EXPORT_SYMBOL vmlinux 0xfa0564fc __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfa5ec6b8 tcf_register_action +EXPORT_SYMBOL vmlinux 0xfaa13525 tcp_hashinfo +EXPORT_SYMBOL vmlinux 0xfaa66680 netdev_features_change +EXPORT_SYMBOL vmlinux 0xfaaff9e7 console_stop +EXPORT_SYMBOL vmlinux 0xfab2db2e generic_block_bmap +EXPORT_SYMBOL vmlinux 0xfab7f745 tty_name +EXPORT_SYMBOL vmlinux 0xfaf98462 bitrev32 +EXPORT_SYMBOL vmlinux 0xfb0443fb acpi_get_parent +EXPORT_SYMBOL vmlinux 0xfb0cf2e9 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0xfb247d8d kunmap_high +EXPORT_SYMBOL vmlinux 0xfb343846 neigh_table_clear +EXPORT_SYMBOL vmlinux 0xfb6af58d recalc_sigpending +EXPORT_SYMBOL vmlinux 0xfb774ee7 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0xfb901191 set_blocksize +EXPORT_SYMBOL vmlinux 0xfba0c2e0 llc_sap_list_lock +EXPORT_SYMBOL vmlinux 0xfbc075be d_delete +EXPORT_SYMBOL vmlinux 0xfbd8886a __lookup_hash +EXPORT_SYMBOL vmlinux 0xfbed20d8 ioremap_nocache +EXPORT_SYMBOL vmlinux 0xfbeef185 remove_proc_entry +EXPORT_SYMBOL vmlinux 0xfbf92453 param_get_bool +EXPORT_SYMBOL vmlinux 0xfc02b7ad sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0xfc135425 is_container_init +EXPORT_SYMBOL vmlinux 0xfc27dbda blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0xfc309c3e cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0xfc3175cb proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0xfc39e32f ioport_unmap +EXPORT_SYMBOL vmlinux 0xfc502921 fget +EXPORT_SYMBOL vmlinux 0xfc76f53d d_find_alias +EXPORT_SYMBOL vmlinux 0xfc926eee blk_recount_segments +EXPORT_SYMBOL vmlinux 0xfcaa04a0 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfcbe8a97 con_set_default_unimap +EXPORT_SYMBOL vmlinux 0xfcda63a3 node_states +EXPORT_SYMBOL vmlinux 0xfcdd8cf6 param_get_ushort +EXPORT_SYMBOL vmlinux 0xfcec0987 enable_irq +EXPORT_SYMBOL vmlinux 0xfcfa03ff fb_videomode_to_modelist +EXPORT_SYMBOL vmlinux 0xfcfa6399 __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0xfd243d45 d_alloc_name +EXPORT_SYMBOL vmlinux 0xfd5fe865 make_EII_client +EXPORT_SYMBOL vmlinux 0xfd6fd4ea sock_sendmsg +EXPORT_SYMBOL vmlinux 0xfd8d8320 register_sysrq_key +EXPORT_SYMBOL vmlinux 0xfd98879a rb_next +EXPORT_SYMBOL vmlinux 0xfda44aef icmp_send +EXPORT_SYMBOL vmlinux 0xfdb9b629 ioread32be +EXPORT_SYMBOL vmlinux 0xfdc5fefa pci_iomap +EXPORT_SYMBOL vmlinux 0xfdce7c3e clear_bdi_congested +EXPORT_SYMBOL vmlinux 0xfddf976b sync_page_range +EXPORT_SYMBOL vmlinux 0xfde2145a boot_tvec_bases +EXPORT_SYMBOL vmlinux 0xfde5cda7 input_release_device +EXPORT_SYMBOL vmlinux 0xfdf33ba8 thermal_zone_bind_cooling_device +EXPORT_SYMBOL vmlinux 0xfe3255b6 __napi_schedule +EXPORT_SYMBOL vmlinux 0xfe383d4a xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0xfe4c67c0 ip_route_input +EXPORT_SYMBOL vmlinux 0xfe5d4bb2 sys_tz +EXPORT_SYMBOL vmlinux 0xfe62b4a8 pci_release_region +EXPORT_SYMBOL vmlinux 0xfe769456 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0xfe7c4287 nr_cpu_ids +EXPORT_SYMBOL vmlinux 0xfec00e03 redraw_screen +EXPORT_SYMBOL vmlinux 0xfec3c2f2 bcd2bin +EXPORT_SYMBOL vmlinux 0xfedd35fc console_suspend_enabled +EXPORT_SYMBOL vmlinux 0xfee445a5 xrlim_allow +EXPORT_SYMBOL vmlinux 0xff1e9dd8 seq_list_start +EXPORT_SYMBOL vmlinux 0xff31a484 setup_arg_pages +EXPORT_SYMBOL vmlinux 0xff53fc5f tcf_exts_validate +EXPORT_SYMBOL vmlinux 0xff5c17e6 __mod_zone_page_state +EXPORT_SYMBOL vmlinux 0xff67d682 block_write_begin +EXPORT_SYMBOL vmlinux 0xff6878cf fb_default_cmap +EXPORT_SYMBOL vmlinux 0xff708fd3 mempool_destroy +EXPORT_SYMBOL vmlinux 0xff8dbc58 end_request +EXPORT_SYMBOL vmlinux 0xff9ca065 fb_edid_to_monspecs +EXPORT_SYMBOL vmlinux 0xffafdc5c _read_unlock_irq +EXPORT_SYMBOL vmlinux 0xffbc9816 inc_zone_page_state +EXPORT_SYMBOL vmlinux 0xffc906f0 handle_sysrq +EXPORT_SYMBOL vmlinux 0xffd5a395 default_wake_function +EXPORT_SYMBOL vmlinux 0xffe18ec8 dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0xfff465c2 generic_file_open +EXPORT_SYMBOL vmlinux 0xffff3a1f ethtool_op_get_tx_csum +EXPORT_SYMBOL_GPL arch/x86/kernel/cpu/cpufreq/speedstep-lib 0x16836e04 speedstep_detect_processor +EXPORT_SYMBOL_GPL arch/x86/kernel/cpu/cpufreq/speedstep-lib 0x4cdb4bd0 speedstep_get_processor_frequency +EXPORT_SYMBOL_GPL arch/x86/kernel/cpu/cpufreq/speedstep-lib 0xd494ee54 speedstep_get_freqs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x00aaf935 kvm_disable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x06cae626 kvm_lapic_get_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x094ac8f4 kvm_get_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0be632f1 kvm_get_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0d76e2a2 kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x0d827c12 kvm_task_switch +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1010f63d kvm_timer_intr_post +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x12d1b23b kvm_release_pfn_clean +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x13ee32c6 kvm_cpu_has_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x14ba3088 kvm_queue_exception_e +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x178c54b4 kvm_set_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1c341204 kvm_cpu_get_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1d5d3092 kvm_emulate_cpuid +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1e4580bb kvm_release_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1fb50177 kvm_lmsw +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2322e039 kvm_set_pfn_accessed +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2328285f is_error_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2424b9f1 kvm_get_cs_db_l_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x25c2996e gfn_to_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x27046576 kvm_exit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2cff5753 kvm_vcpu_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2d865b68 kvm_inject_nmi +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2fa5cafd kvm_emulate_pio +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x317f9e6b kvm_enable_efer_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3a32d903 kvm_read_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3b7fdb0c kvm_read_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x470c0ae9 kvm_set_cr3 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x478d95e5 kvm_put_guest_fpu +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x481ea10e kvm_emulate_hypercall +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4a7cbe69 is_error_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4cc7933c kvm_write_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x50336367 kvm_emulate_halt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x5090d004 kvm_mmu_load +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x5575d066 kvm_emulate_pio_string +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x599086dd kvm_handle_fault_on_reboot +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x5f4b8670 emulate_instruction +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x628edc4d kvm_lapic_get_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6495dd8b kvm_queue_exception +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x65fbba53 kvm_lapic_find_highest_irr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6a4c63a0 kvm_mmu_unprotect_page_virt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6a7d6b96 gfn_to_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x711f479d gfn_to_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x71c337ac kvm_lapic_set_tpr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x795efc9e kvm_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7e7a3099 kvm_put_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x806e9df4 kvm_is_visible_gfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x80722853 emulator_read_std +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x83433aeb kvm_lapic_enabled +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x87dd6b2e emulator_write_emulated +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8cb8796b kvm_mmu_reset_context +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8ce4f3ab kvm_enable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8d0329aa kvm_report_emulation_failure +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8e7f9b47 segment_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8f84aea2 kvm_get_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8fc7d1b0 kvm_mmu_page_fault +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x945c541c kvm_inject_pending_timer_irqs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9543eb3c kvm_release_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa361bc65 kvm_set_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa7b01b2f kvm_create_lapic +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xabb82930 fx_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xac8d094b kvm_resched +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xb7cb8d04 kvm_clear_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xb9d7f1e9 kvm_set_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd377dc9 kvm_mmu_set_nonpresent_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd94103b kvm_mmu_set_base_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xc5b0fd35 kvm_release_page_clean +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xc62eecb7 kvm_load_guest_fpu +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xcb0e8b7f __kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xcf06b01b kvm_set_cr0 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd09be649 kvm_clear_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd0b2727a kvm_mmu_set_mask_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd296def9 kvm_is_error_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd4f4a8a2 kvm_vcpu_cache +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdba0d08d load_pdptrs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xe72bf6c6 kvm_set_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf46e10e2 kvm_set_cr4 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf6772aaa kvm_set_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xfaa69284 kvm_vcpu_uninit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xfb432937 kvm_get_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xfcfbef36 kvm_lapic_reset +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xfff0f377 kvm_get_cr8 +EXPORT_SYMBOL_GPL crypto/aead 0x0ecff5e6 aead_geniv_alloc +EXPORT_SYMBOL_GPL crypto/aead 0x1437a6f0 aead_geniv_init +EXPORT_SYMBOL_GPL crypto/aead 0x6c1e618c aead_geniv_free +EXPORT_SYMBOL_GPL crypto/aead 0x78943a94 crypto_grab_aead +EXPORT_SYMBOL_GPL crypto/aead 0x8f12a681 crypto_aead_setauthsize +EXPORT_SYMBOL_GPL crypto/aead 0x9d002f2e crypto_alloc_aead +EXPORT_SYMBOL_GPL crypto/aead 0xb0de4643 crypto_aead_type +EXPORT_SYMBOL_GPL crypto/aead 0xc087b7c8 aead_geniv_exit +EXPORT_SYMBOL_GPL crypto/aead 0xea6c695d crypto_nivaead_type +EXPORT_SYMBOL_GPL crypto/aes_generic 0x1381bf2d crypto_ft_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x22894d94 crypto_il_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5f943003 crypto_it_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5fe743de crypto_aes_expand_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x6e9cc2ba crypto_fl_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x959d1946 crypto_aes_set_key +EXPORT_SYMBOL_GPL crypto/async_tx/async_memcpy 0x3a73d5df async_memcpy +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x17665c21 async_tx_submit +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xa5248480 async_tx_quiesce +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xac1537c3 async_trigger_callback +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0x198fdb3a async_xor +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0x92abec38 async_xor_zero_sum +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x0dc5dc8b skcipher_geniv_free +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x0f95b4d8 blkcipher_walk_virt_block +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x2b205425 skcipher_geniv_init +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x2e1be41f crypto_blkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x35f280e9 skcipher_geniv_exit +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x6a14f25d crypto_givcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x8ae20ef9 skcipher_geniv_alloc +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x9bdda218 crypto_alloc_ablkcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xc18bd10e blkcipher_walk_done +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xc281fc61 crypto_ablkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xd37cc9bb crypto_grab_skcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xe8f40599 blkcipher_walk_virt +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xeed10635 blkcipher_walk_phys +EXPORT_SYMBOL_GPL crypto/des_generic 0xcfd9a2c0 des_ekey +EXPORT_SYMBOL_GPL crypto/twofish_common 0xcb3f501c twofish_setkey +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x100c48a2 unregister_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x2611fbee register_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x318920b1 register_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xbd506a46 unregister_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xcc6ab305 is_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x0ad5c33f acpi_smbus_register_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x158c2ad0 acpi_smbus_unregister_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x526b867a acpi_smbus_read +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0xb3d5e527 acpi_smbus_write +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x3ecf6cfc wmi_install_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x64ebe677 wmi_query_block +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xa9b7afd8 wmi_set_block +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xb5a6ebe2 wmi_remove_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xc5e3dddf wmi_get_event_data +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xc9d4d6d1 wmi_has_guid +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xe2426710 wmi_evaluate_method +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0067df75 ata_tf_from_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x00ebcb5d ata_id_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0x03e3686c ata_timing_cycle2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x04519f77 ata_host_alloc_pinfo +EXPORT_SYMBOL_GPL drivers/ata/libata 0x04cd9775 ata_sff_dumb_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0531dcb8 ata_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0x053f0981 dev_attr_link_power_management_policy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x06d94910 ata_port_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0x08777e49 ata_pci_device_do_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0979cb91 ata_sff_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0aad6181 sata_std_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0ad56dd7 ata_link_offline +EXPORT_SYMBOL_GPL drivers/ata/libata 0x144d84dc ata_sff_post_internal_cmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x16245e16 ata_eh_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1697ed92 ata_bmdma_mode_filter +EXPORT_SYMBOL_GPL drivers/ata/libata 0x17a4bc37 ata_pci_device_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1b2a7549 ata_sff_data_xfer_noirq +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2595fdca ata_std_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x27aded88 ata_port_probe +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2815f318 ata_bmdma_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0x288c1795 ata_sas_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x29e43503 ata_std_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0x306b0c0d ata_std_bios_param +EXPORT_SYMBOL_GPL drivers/ata/libata 0x32677440 sata_sff_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x32be50d1 ata_port_schedule_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0x32d30379 ata_pci_bmdma_clear_simplex +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3ad496a4 sata_scr_valid +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3b163953 ata_scsi_simulate +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3b87e3b5 ata_cable_unknown +EXPORT_SYMBOL_GPL drivers/ata/libata 0x40386ea7 ata_sff_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0x40a0bee7 ata_host_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x40af0dec ata_xfer_mode2mask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x40bb21cb sata_pmp_qc_defer_cmd_switch +EXPORT_SYMBOL_GPL drivers/ata/libata 0x42cc7a87 __ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4392da8c ata_cable_sata +EXPORT_SYMBOL_GPL drivers/ata/libata 0x43f56e82 ata_xfer_mode2shift +EXPORT_SYMBOL_GPL drivers/ata/libata 0x44844cb7 ata_sff_dev_select +EXPORT_SYMBOL_GPL drivers/ata/libata 0x47091ca6 ata_ehi_clear_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x48055b89 ata_sff_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4997b791 ata_acpi_gtm_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x49e95c73 ata_dummy_port_info +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4b4ce45f ata_sff_tf_load +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4b8945c1 ata_qc_complete_multiple +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4f1fffa0 ata_pci_sff_prepare_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fdc945d sata_deb_timing_normal +EXPORT_SYMBOL_GPL drivers/ata/libata 0x505d94c8 ata_do_dev_read_id +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5152b738 ata_sff_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5235ae77 ata_sff_irq_clear +EXPORT_SYMBOL_GPL drivers/ata/libata 0x581fc3bc ata_sff_qc_issue +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5c01d711 ata_sff_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5c1fd4f2 ata_sas_port_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5d4fa03b ata_sff_exec_command +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5e854539 ata_pci_sff_init_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5f6b7c95 ata_std_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x65985bae ata_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x673c0345 ata_sff_check_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0x699ba01a ata_pci_sff_init_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0x69e9a2cb ata_scsi_slave_config +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6a4010d2 ata_sas_port_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6c1b68f2 ata_host_detach +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6d7e1d84 ata_sff_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6dcb33f9 ata_noop_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6e36ba67 ata_port_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6ebb683f ata_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6fbbfb82 sata_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x707ff1bb ata_xfer_mask2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x719853fc ata_do_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0x72bdf1e9 ata_sff_tf_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a48b4a ata_sff_std_ports +EXPORT_SYMBOL_GPL drivers/ata/libata 0x743a165e ata_pack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x757e818d ata_bus_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x76c3727c ata_host_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7b242659 ata_acpi_gtm +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7b95812b ata_scsi_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7e3b39eb ata_eh_qc_retry +EXPORT_SYMBOL_GPL drivers/ata/libata 0x80606acd ata_pio_need_iordy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x85defd0f ata_host_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x86287081 ata_sff_qc_fill_rtf +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8737c7c3 ata_bmdma_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b752ac1 ata_tf_to_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8d87b123 ata_sas_port_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8ecc1416 sata_scr_write +EXPORT_SYMBOL_GPL drivers/ata/libata 0x912693af ata_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x91cfbd6f ata_cable_ignore +EXPORT_SYMBOL_GPL drivers/ata/libata 0x92966efe ata_bmdma_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x92f40394 dev_attr_sw_activity +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94a68723 ata_scsi_slave_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94dc62d2 ata_scsi_ioctl +EXPORT_SYMBOL_GPL drivers/ata/libata 0x977b2871 ata_acpi_cbl_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98dc72c6 ata_base_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x993771eb ata_port_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9b65bfcb pci_test_config_bits +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9d3d0c0e ata_port_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9e39248a ata_cable_40wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9fbe0b72 sata_scr_write_flush +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa07d3e5c ata_pci_sff_activate_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa164d2bd sata_async_notification +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa771f2b1 ata_bmdma_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0xaa74cf24 ata_do_set_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0xadadac05 sata_scr_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6539f9d ata_link_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6620de6 ata_bmdma_setup +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6aeb661 ata_id_c_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xba2ff010 sata_link_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xba926e09 ata_pci_remove_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbb00be4b ata_pci_device_do_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbb4d4f0c ata_dev_pair +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbb742845 ata_sg_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbb7c0283 ata_std_qc_defer +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbc7c4067 sata_link_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbcfe803b ata_sff_dma_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe1887e4 ata_unpack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbf45e80f ata_dummy_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc03ea8f0 ata_sff_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc19b6c28 ata_sff_wait_ready +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc25b3d06 ata_sff_host_intr +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc428068d sata_deb_timing_long +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc48b7ccf ata_mode_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc611bfee ata_sff_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc65b2ee8 ata_eh_freeze_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc673e23e ata_scsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc8e9f277 ata_sff_busy_sleep +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcc368196 ata_sff_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcccfb2fa sata_deb_timing_hotplug +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcdd6ec35 ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xce990790 ata_acpi_stm +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd076a58b ata_sas_slave_configure +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd40fce8d ata_dev_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd5d6a02f ata_cable_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd6b97d51 ata_sas_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd84cd7f4 ata_timing_find_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0xda3c77e1 dev_attr_em_message +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdbe30182 ata_port_pbar_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdd057370 ata_timing_compute +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdeaf6d3c ata_eh_thaw_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdec25d6a ata_sff_thaw +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdf3022b2 ata_sff_interrupt +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe1aeeef9 sata_set_spd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe49ff3b0 ata_wait_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe4dc7141 dev_attr_em_message_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe5490702 ata_host_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe75a1875 ata_sff_data_xfer +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe910a85a sata_pmp_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe98a0aec ata_pci_device_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0xea418e0f atapi_cmd_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xeb89390a ata_sas_port_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0xec4e6af8 ata_link_online +EXPORT_SYMBOL_GPL drivers/ata/libata 0xee292049 ata_host_activate +EXPORT_SYMBOL_GPL drivers/ata/libata 0xeec310a3 ata_host_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf0be9a4c ata_sff_hsm_move +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf13b316e ata_eh_analyze_ncq_error +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf2bc10d4 ata_pci_bmdma_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf3d5cc13 ata_timing_merge +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf812d2f1 ata_host_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8c0943d sata_link_debounce +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8f3a0fb ata_ratelimit +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf9a5dbc2 ata_sff_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf9ca3160 ata_id_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfa4d5cef ata_sff_irq_on +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfaced1e0 ata_sff_softreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xffd2df83 sata_pmp_port_ops +EXPORT_SYMBOL_GPL drivers/ata/pata_sis 0x285b5a6a sis_info133_for_sata +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x02ff9464 cfag12864b_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x0ecb2e5d cfag12864b_disable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x305dc3c6 cfag12864b_isenabled +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x3389f926 cfag12864b_enable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x9522a342 cfag12864b_getrate +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0xc48e9d95 cfag12864b_buffer +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x14102f23 ks0108_displaystate +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x48a70518 ks0108_writedata +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x4f506333 ks0108_startline +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x6edae968 ks0108_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xbf4774db ks0108_writecontrol +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xedde6df2 ks0108_page +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xfee8ef7b ks0108_address +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0x3d33b817 agp_remove_bridge +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xa1e94538 agp_add_bridge +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xd6feefa5 agp_num_entries +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xe089cfcc agp_memory_reserved +EXPORT_SYMBOL_GPL drivers/char/scx200_gpio 0x316a35c2 scx200_gpio_ops +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x1948e951 tpm_show_caps +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x3165f53e tpm_show_owned +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x3734e9c1 tpm_get_timeouts +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x3968e375 tpm_remove_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x3cfb7518 tpm_pm_resume +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x442d9b54 tpm_gen_interrupt +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x44eee246 tpm_show_pcrs +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x4d8d4d22 tpm_release +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x620326f5 tpm_show_enabled +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x712d7714 tpm_write +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7c98e614 tpm_calc_ordinal_duration +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7f8ee864 tpm_show_caps_1_2 +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7f8fb685 tpm_open +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x8417ef33 tpm_show_temp_deactivated +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x884e2750 tpm_register_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x8d6e236e tpm_pm_suspend +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xcf9ccd22 tpm_show_pubek +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xcfea85ab tpm_store_cancel +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xdf099a5e tpm_show_active +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xedc739fe tpm_continue_selftest +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xfa52b4ab tpm_read +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0x31463447 tpm_bios_log_teardown +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0x3934bf7c tpm_bios_log_setup +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x07146b6f cpufreq_frequency_table_verify +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x2f47d8c7 cpufreq_frequency_get_table +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x5dcfc85f cpufreq_frequency_table_target +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x5e9329f1 cpufreq_freq_attr_scaling_available_freqs +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x706b3a33 cpufreq_frequency_table_get_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x7ae1ae8e cpufreq_frequency_table_put_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0xa26344c7 cpufreq_frequency_table_cpuinfo +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0001ee05 edac_device_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0678d905 edac_pci_reset_delay_period +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0c61833c edac_mc_handle_ce_no_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x169db7bc edac_mc_alloc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x2d387158 edac_mc_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x2f3b8185 edac_pci_release_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x3ede9d0a edac_device_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x434eefe3 edac_mc_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x50fce8fa edac_mc_add_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x5436725e edac_device_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x79ab94c0 edac_mc_find_csrow_by_page +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x7c16266d edac_device_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x7d67ac89 edac_pci_create_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x7f002101 edac_device_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x8ea47e89 edac_pci_handle_npe +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x9243518f edac_pci_handle_pe +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x92f3e4c7 edac_mc_del_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa900151a edac_pci_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xacbddd6d edac_pci_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xb80ff9bd edac_pci_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcd3d5c04 edac_device_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcf1c4518 edac_mc_handle_ue_no_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xe1ac2ce8 edac_pci_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xf10d01ac edac_mc_free +EXPORT_SYMBOL_GPL drivers/hid/hid 0x038e430d hidinput_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0x0bced099 hid_input_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x198af023 hidraw_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0x3f36ce6e hidraw_disconnect +EXPORT_SYMBOL_GPL drivers/hid/hid 0x4a44057d hid_free_device +EXPORT_SYMBOL_GPL drivers/hid/hid 0x5b40c80e hidinput_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0x6cccc739 hid_output_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0xaba5c3fb hidraw_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0xc1657ce7 hidinput_find_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xe729eba9 hidinput_disconnect +EXPORT_SYMBOL_GPL drivers/hid/hid 0xf81971db hid_set_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xfa0f47dc hid_parse_report +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x01fd453e usbhid_lookup_quirk +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x62e90570 hiddev_hid_event +EXPORT_SYMBOL_GPL drivers/i2c/busses/i2c-nforce2 0x1aecdbf4 nforce2_smbus +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x419106e1 i2c_new_probed_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x6645b9f3 i2c_bus_type +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x855a2a32 i2c_new_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xa9223284 i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xd91b2af3 i2c_new_dummy +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xe0044360 i2c_unregister_device +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0x007f8f66 hpsb_config_rom_ip1394_remove +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xaeacd718 hpsb_config_rom_ip1394_add +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xec8d18cf hpsb_disable_irm +EXPORT_SYMBOL_GPL drivers/input/ff-memless 0xfbfe4291 input_ff_create_memless +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x02856a87 wm97xx_set_suspend_mode +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x2a23dfc3 wm97xx_config_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x3182f91e wm97xx_register_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x4853897f wm9705_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x55ed9425 wm9712_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x6cf195c0 wm97xx_unregister_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x994794bb wm9713_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xc4289759 wm97xx_read_aux_adc +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xcf6d2c78 wm97xx_reg_write +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xd1de6c65 wm97xx_set_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xd8116f82 wm97xx_reg_read +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xdd733266 wm97xx_get_gpio +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x0b52600f gigaset_freedriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x23e754ea gigaset_m10x_input +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x454aa44f gigaset_debuglevel +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x4e792275 gigaset_dbg_buffer +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x59f664b5 gigaset_add_event +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x5da859dc gigaset_if_receive +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x5f650c92 gigaset_start +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x6cf2fb40 gigaset_handle_modem_response +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x775d6113 gigaset_skb_sent +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x7d2b6f84 gigaset_fill_inbuf +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xad2e1716 gigaset_blockdriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xb147339d gigaset_initcs +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xc6e14627 gigaset_stop +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xc8c52bf4 gigaset_m10x_send_skb +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xd3183ab5 gigaset_initdriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xf4893b58 gigaset_shutdown +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xfb3dba43 gigaset_freecs +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x101a6020 led_classdev_suspend +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x435e4e53 led_classdev_register +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x6fefed35 led_classdev_unregister +EXPORT_SYMBOL_GPL drivers/leds/led-class 0xbec5e11f led_classdev_resume +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x0c06553a dm_path_uevent +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x13b5f8af dm_device_name +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x647fdef3 dm_noflush_suspending +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xa8e1c35e dm_put +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xc2c1b625 dm_send_uevents +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xd71bd76d dm_set_device_limits +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xf70581e7 dm_disk +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0x30d6371b dm_register_path_selector +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xecb55625 dm_unregister_path_selector +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x24ce519a md_allow_write +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x2c20eba4 md_new_event +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x6477ce6d md_do_sync +EXPORT_SYMBOL_GPL drivers/md/md-mod 0xd210e1c1 sync_page_io +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x04662e0f ir_codes_fusionhdtv_mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x07e92917 ir_codes_avermedia_a16d +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x083661f9 ir_codes_avertv_303 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x088631b9 ir_codes_behold +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x1cb148f5 ir_extract_bits +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2456e513 ir_decode_pulsedistance +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2a4852cc ir_codes_dntv_live_dvb_t +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2af1a608 ir_codes_proteus_2309 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x3811daea ir_codes_manli +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x43c89ef4 ir_decode_biphase +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x45b08f68 ir_codes_pinnacle_grey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4740e7a3 ir_codes_empty +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4ea698a2 ir_codes_purpletv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x55338dda ir_codes_pixelview_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x589cad50 ir_codes_apac_viewcomp +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x5db13554 ir_codes_encore_enltv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6606596a ir_rc5_timer_keyup +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6adc476d ir_codes_powercolor_real_angel +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6aefdbea ir_codes_npgtech +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6b87c69d ir_codes_iodata_bctv7e +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6d6511e7 ir_dump_samples +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6e2a1870 ir_codes_adstech_dvb_t_pci +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x7277973d ir_codes_pctv_sedna +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x75e89cc3 ir_codes_flydvb +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x772a30a2 ir_codes_nebula +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x85d37490 ir_codes_dntv_live_dvbt_pro +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x89cc1189 ir_codes_winfast +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x902a3cd2 ir_codes_hauppauge_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x933d0bb3 ir_codes_msi_tvanywhere +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x9451e232 ir_codes_behold_columbus +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x96470cab ir_codes_cinergy +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb1f4eb35 ir_codes_avermedia_dvbt +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb6cd4666 ir_codes_eztv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xbdce6594 ir_codes_tt_1500 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc1fea0c1 ir_codes_pv951 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc42bd037 ir_codes_budget_ci_old +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc6c5a7a1 ir_codes_em_terratec +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc9e27e17 ir_input_nokey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd1e0258a ir_codes_flyvideo +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd55e6891 ir_codes_gotview7135 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd9c7f010 ir_codes_rc5_tv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdaa041ad ir_codes_cinergy_1400 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdfcf23df ir_codes_norwood +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xe24d802e ir_input_init +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xee2f5e0e ir_codes_pinnacle_pctv_hd +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf07533a1 ir_codes_videomate_tv_pvr +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf0fc9374 ir_codes_avermedia +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf2b421aa ir_codes_genius_tvgo_a11mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf4f7a4d6 ir_rc5_timer_end +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfa177653 ir_codes_pixelview +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfb981300 ir_codes_pinnacle_color +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfc537d66 ir_input_keydown +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfc54a5cd ir_codes_asus_pc39 +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x0495c26a saa7146_register_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x2f4dd641 saa7146_pgtable_build_single +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x38717e8f saa7146_pgtable_alloc +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x7a916056 saa7146_wait_for_debi_done +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x89e50798 saa7146_unregister_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x8a4e2f96 saa7146_vmalloc_build_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x9ae3b760 saa7146_pgtable_free +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xb571d336 saa7146_setgpio +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xc98faf20 saa7146_devices_lock +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xcf683cf2 saa7146_devices +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xd20f9dd0 saa7146_i2c_adapter_prepare +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xe3cd9b5c saa7146_debug +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xf4f05783 saa7146_vfree_destroy_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x4b91bb9c saa7146_stop_preview +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x5b1b5b69 saa7146_register_device +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x9c049bc5 saa7146_vv_init +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xa062360d saa7146_start_preview +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xafb50d34 saa7146_set_hps_source_and_sync +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xee6fca50 saa7146_unregister_device +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xf4958f5b saa7146_vv_release +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mt20xx 0x6ae49a4d microtune_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mxl5007t 0xbcf91bc9 mxl5007t_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda18271 0xdc2fb144 tda18271_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda827x 0xc28745c8 tda827x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0x9984664e tda829x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0xf2de10f9 tda829x_probe +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda9887 0xeba006bb tda9887_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xb50f0ede tea5761_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xe7389d51 tea5761_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0x5a0d8c34 tea5767_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0xff2b8298 tea5767_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tuner-simple 0x767cfda6 simple_tuner_attach +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x11207357 ttpci_budget_debiwrite +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x37128851 ttpci_budget_init_hooks +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x6f60cade ttpci_budget_init +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x7948c222 budget_debug +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xac4b9e08 ttpci_budget_deinit +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xbf25ad18 ttpci_budget_debiread +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xc0af051e ttpci_budget_set_video_port +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xd1abda89 ttpci_budget_irq10_handler +EXPORT_SYMBOL_GPL drivers/media/video/compat_ioctl32 0x6d5e7ea4 v4l_compat_ioctl32 +EXPORT_SYMBOL_GPL drivers/media/video/cx88/cx88xx 0xc080b818 cx88_setup_xc3028 +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x10dd9916 em28xx_init_isoc +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x3e5d51b2 em28xx_set_mode +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xc9180f61 em28xx_uninit_isoc +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xd22c24eb em28xx_tuner_callback +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xfc2eae88 em28xx_audio_analog_set +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0x404ff5e3 saa7134_queryctrl +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0x57755298 saa7134_g_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0x709abe12 saa7134_ts_qops +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xa1f40b9c saa7134_s_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0x00ae80dc v4l2_int_device_unregister +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0xb87dc217 v4l2_int_device_register +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x044724dc videobuf_next_field +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x0540f975 videobuf_iolock +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x1301de56 __videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x208a8411 videobuf_qbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x23742368 videobuf_streamon +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x33de1274 videobuf_read_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x36eed424 videobuf_queue_core_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x3d35502e videobuf_cgmbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x40e21684 videobuf_read_one +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x42ae1a91 videobuf_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x53c31d23 videobuf_streamoff +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x56b1f1b4 videobuf_queue_cancel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x58fcb8f6 videobuf_mmap_mapper +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x6c0897f9 videobuf_read_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x826da15a videobuf_queue_is_busy +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x92cc532c videobuf_read_start +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x9733f1d6 videobuf_reqbufs +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xafda8360 videobuf_poll_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xb6cbcaf7 videobuf_dqbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xbfd78c04 videobuf_mmap_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xcb4d2fc6 videobuf_querybuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xef1980b9 videobuf_waiton +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xf144f87b videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xf38ee783 videobuf_queue_to_vmalloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xfe7a84a9 videobuf_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x07cfb65e videobuf_to_dma_contig +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x98c6ded4 videobuf_queue_dma_contig_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0xcee1a38a videobuf_dma_contig_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x3faecbbc videobuf_to_dma +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x3ffe935b videobuf_dma_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x5680fbb1 videobuf_dma_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x6f82b568 videobuf_dma_init_user +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x8a811433 videobuf_sg_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x933dfb43 videobuf_vmalloc_to_sg +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa825c75b videobuf_sg_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xaa550ce0 videobuf_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xac9bad5b videobuf_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xbb45a5f8 videobuf_queue_sg_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xc98f4509 videobuf_dma_sync +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xd60d29e1 videobuf_sg_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xf1941304 videobuf_dma_init_kernel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xf763e913 videobuf_dma_init_overlay +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x2097204b videobuf_to_vmalloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x3a5230fc videobuf_queue_vmalloc_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x9524c001 videobuf_vmalloc_free +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x3b299ab6 sm501_modify_reg +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x98fd8127 sm501_misc_control +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xc2eb347a sm501_find_clock +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xd4453b97 sm501_unit_power +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xeef5d9e5 sm501_set_clock +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x2df115d4 eeprom_93cx6_multiread +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x63d14d2f eeprom_93cx6_read +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x2a842dfa enclosure_register +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x339fc797 enclosure_unregister +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x42801409 enclosure_remove_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x573cdf34 enclosure_find +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x7733a083 enclosure_for_each_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xc10c71e9 enclosure_add_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xdc2306b9 enclosure_component_register +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x02080311 sdio_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x0e0305bb sdio_disable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x110ba948 sdio_readw +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x1719a8aa sdio_set_block_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x1cd88add sdio_register_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x3ea6c1de sdio_memcpy_fromio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x4b3a85e4 sdio_release_irq +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x5cac79ab sdio_writel +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x5d277dbb sdio_claim_irq +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x639dcaf6 sdio_enable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x7d8b8701 sdio_readsb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x8a7409b4 sdio_memcpy_toio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xaaa1066c sdio_f0_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xc43216c8 sdio_readl +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xcbf95ae3 sdio_unregister_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xd83a690e sdio_writew +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xd9d6604f sdio_claim_host +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe3b0d3d5 sdio_writesb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe6639cdc sdio_align_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe9c3b8a4 sdio_release_host +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xec73a40c sdio_readb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xf0b9e54c sdio_f0_readb +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x6843a7ba sdhci_suspend_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x86a45190 sdhci_add_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x9f008bdf sdhci_resume_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xbfbd0f20 sdhci_remove_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xcf6e3c62 sdhci_alloc_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xde6ebd0b sdhci_free_host +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x043d07fb cfi_cmdset_0001 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x9d797e77 cfi_cmdset_0003 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0xf670bca6 cfi_cmdset_0200 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0002 0xd1db42b1 cfi_cmdset_0002 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0020 0xac08b04f cfi_cmdset_0020 +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2000 0x62e7be42 DoC2k_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001 0xe06bbfe3 DoCMil_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001plus 0xcfac3f5b DoCMilPlus_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/docecc 0x45937659 doc_decode_ecc +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x006797ba unregister_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x0c460482 get_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x1bf2528f add_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x1c3c1c40 deregister_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x1f0229d5 register_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x5c350faf parse_mtd_partitions +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x7da157b0 register_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x8603768d get_sb_mtd +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xab6e0d20 get_mtd_device_nm +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xaba5e70d default_mtd_writev +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xbf6fcd1f put_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xcb20e8d1 mtd_erase_callback +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xd7293a2a del_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xeff64be1 mtd_table_mutex +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xf8042814 kill_mtd_super +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xfdf318ff mtd_table +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xafe3d6db del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xcdd7f1fd deregister_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xdda007a8 register_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xe3740b11 add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x0125e78f nand_scan_ident +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x48bdd99b nand_wait_ready +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x81d104d2 nand_scan +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x95ee05a5 nand_scan_tail +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xbc46d4de nand_release +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x496b48f9 onenand_release +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x6023ba31 onenand_scan +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x2cd20c06 ubi_leb_unmap +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x3f1ca516 ubi_leb_map +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x42801d20 ubi_sync +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x476fa52f ubi_leb_erase +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x55ad89ba ubi_leb_change +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x671baf7b ubi_leb_read +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xa21de434 ubi_close_volume +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xae71cfeb ubi_get_volume_info +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbc505df4 ubi_get_device_info +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xcaae5076 ubi_leb_write +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xd0930047 ubi_open_volume +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xe3e5f285 ubi_open_volume_nm +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xe49ebf05 ubi_is_mapped +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x037413d2 mlx4_cq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0504a5ca mlx4_srq_query +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x15b45de5 mlx4_mr_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1a0eb5c4 mlx4_srq_arm +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1bc44bfe mlx4_fmr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1f3984c4 mlx4_srq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1f39db4b mlx4_db_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x221eeca3 mlx4_alloc_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2a469a6e mlx4_cq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2d8098b1 mlx4_CLOSE_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2f502628 mlx4_register_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3052ceff mlx4_qp_remove +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x31474c21 mlx4_SYNC_TPT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x34ad7bba mlx4_mr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3c56667f mlx4_qp_query +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3c94ce97 mlx4_srq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x40bf391b mlx4_map_phys_fmr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5b49d321 mlx4_cq_resize +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5f1be58e mlx4_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6e26647c mlx4_qp_to_ready +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7204ef85 mlx4_mtt_init +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7457f705 mlx4_pd_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x760352b3 mlx4_fmr_unmap +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x796b5a53 mlx4_uar_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7a248c74 mlx4_unregister_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x817d0458 mlx4_INIT_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x86add686 mlx4_qp_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9b519851 mlx4_fmr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb45ac3a3 mlx4_buf_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb49a0794 mlx4_fmr_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb7d8a5b8 mlx4_uar_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb94d957a mlx4_db_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbac23a85 __mlx4_cmd +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc7f6f900 mlx4_qp_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xce8fbebf mlx4_pd_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xd2b131c7 mlx4_mtt_addr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xd664c308 mlx4_mr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xd91e79d5 mlx4_free_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdd148490 mlx4_free_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdf4235a4 mlx4_multicast_attach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe6680ae6 mlx4_qp_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xef57b85a mlx4_buf_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xef9ed595 mlx4_cq_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf22be5b1 mlx4_alloc_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf6e08fd4 mlx4_mtt_cleanup +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf88e9cf4 mlx4_multicast_detach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xfac7186c mlx4_buf_alloc +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0xe492a607 usbnet_generic_cdc_bind +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0xe50f7da2 usbnet_cdc_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x0a950c7f rndis_command +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x137fc6af rndis_tx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x4083dd4c rndis_status +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x914c0a75 generic_rndis_bind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xcbc130fc rndis_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xd7fedfad rndis_rx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x063f5d7d usbnet_get_settings +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x160b08ca usbnet_get_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x299a60e4 usbnet_skb_return +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x33023f93 usbnet_suspend +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x39d4fe59 usbnet_get_link +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x42804794 usbnet_disconnect +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x4730f3a8 usbnet_get_drvinfo +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x8b88a9d0 usbnet_defer_kevent +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x9d6267c3 usbnet_set_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xd0b7550d usbnet_resume +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xd49c41c7 usbnet_probe +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xd8cc6624 usbnet_nway_reset +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xdc4b9cf2 usbnet_get_endpoints +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xf59aab26 usbnet_unlink_rx_urbs +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xfb0b6110 usbnet_set_settings +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x00346612 lbs_add_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x179c3463 lbs_remove_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x23fd1d9e lbs_host_to_card_done +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x37b82916 lbs_host_sleep_cfg +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x419869e7 lbs_queue_event +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x4dcb81c9 lbs_process_rxed_packet +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x80f6ad3d lbs_send_tx_feedback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x83103032 lbs_cmd_copyback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x8eb3074d __lbs_cmd +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x9ce13341 lbs_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xb6e21245 lbs_stop_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xc03c882e lbs_notify_command_response +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xce358712 lbs_start_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xe0b31cc3 lbs_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xeb135b97 lbs_cmd_802_11_rate_adapt_rateset +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xf64277de lbs_debug +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x1448a19e p54_parse_eeprom +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x15220908 p54_init_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x1d124383 p54_rx +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x92073a43 p54_free_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xaa748adb p54_fill_eeprom_readback +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xcc94b88d p54_parse_firmware +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1364d52a rt2x00mac_get_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1628e4ca rt2x00lib_probe_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1866ca2a rt2x00queue_map_txskb +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x2dfad695 rt2x00mac_conf_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x3b104d87 rt2x00mac_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x3e1e6949 rt2x00lib_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x43856432 rt2x00lib_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x48211815 rt2x00mac_remove_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5628485d rt2x00queue_get_entry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x57716f9c rt2x00mac_add_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5c515810 rt2x00mac_config +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5ee70559 rt2x00mac_config_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x6dbd5b42 rt2x00mac_stop +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x82fbcf5e rt2x00mac_configure_filter +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x8d8064be rt2x00mac_get_tx_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xb123867f rt2x00lib_beacondone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xd07b7317 rt2x00mac_bss_info_changed +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xd5cc0942 rt2x00queue_get_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xe61fe8e8 rt2x00lib_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xed0d6c7b rt2x00lib_remove_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xf846cca9 rt2x00mac_start +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xfb547def rt2x00lib_txdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x8d9f05bf rt2x00pci_remove +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x96edcf9b rt2x00pci_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xc25f2b55 rt2x00pci_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xceb1d710 rt2x00pci_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xd8318d85 rt2x00pci_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xf8da7c69 rt2x00pci_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xfbae3f57 rt2x00pci_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xfd811ca2 rt2x00pci_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x168a8088 rt2x00usb_kick_tx_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x3b7d270f rt2x00usb_vendor_request_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x48b34f93 rt2x00usb_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x585efb66 rt2x00usb_vendor_request +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x78ee921c rt2x00usb_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x790327e9 rt2x00usb_init_rxentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x818920f4 rt2x00usb_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x9cdbec43 rt2x00usb_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xa4c7fc4a rt2x00usb_vendor_req_buff_lock +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xbac05f99 rt2x00usb_disconnect +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xc9044164 rt2x00usb_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xd2e8ba04 rt2x00usb_init_txentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xdb067ed6 rt2x00usb_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xdea67e1c rt2x00usb_vendor_request_large_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xfa1fa19f rt2x00usb_disable_radio +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0x7e1ecb64 acpiphp_register_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0xb9c88af1 acpiphp_unregister_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x028a486c pci_hp_change_slot_info +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x1ad3b491 acpi_root_bridge +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x21be7794 cpci_hp_unregister_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x2767de98 acpi_get_hp_params_from_firmware +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x62ad9d36 cpci_hp_register_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x6a8441be cpci_hp_start +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x94ef4d05 cpci_hp_stop +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xbb370e8d cpci_hp_unregister_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xd60d1fe5 pci_hp_register +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xf138a351 cpci_hp_register_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xfd8e8876 pci_hp_deregister +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x09be48eb scsi_unregister_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x23039582 scsi_dh_attach +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x35daa612 scsi_dh_activate +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x3e7777d7 scsi_register_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x593a36c2 scsi_dh_handler_exist +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x65dafafc scsi_dh_detach +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0233f349 iscsi_pool_init +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x02606883 iscsi_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0e094b26 iscsi_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x19c64c60 iscsi_put_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x2f9e24a3 iscsi_host_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x354c0351 iscsi_eh_abort +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x35ade811 __iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3b84d7bb iscsi_eh_device_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3f5890e6 iscsi_session_recovery_timedout +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x41ba1d14 iscsi_pool_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x44f048ea iscsi_session_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x4a1a91f1 iscsi_host_add +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x65255e9b iscsi_conn_stop +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x6d83421e iscsi_host_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x6fd76706 iscsi_requeue_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x7f8e3345 iscsi_session_setup +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x843abf78 iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x85b1f54a iscsi_conn_failure +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x871e8c2e iscsi_host_remove +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x999d6eb3 iscsi_host_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa5ee373d iscsi_conn_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xad1d7ca0 iscsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb3b23402 iscsi_itt_to_ctask +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb6705952 iscsi_eh_host_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb6aa4029 iscsi_host_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb73808c9 iscsi_prep_unsolicit_data_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xbb3288dc iscsi_conn_start +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc1d40135 iscsi_verify_itt +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc4a80c5c iscsi_session_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xceb6b961 __iscsi_get_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd758391c iscsi_suspend_tx +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xde2212d4 iscsi_conn_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe11e175a iscsi_update_cmdsn +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe62fb45e iscsi_conn_send_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xec7a0981 iscsi_conn_bind +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf860225a iscsi_conn_setup +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x15abe7e1 sas_target_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x2e77549c sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x3175854f sas_slave_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x58215069 sas_ioctl +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x58c07771 sas_phy_reset +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x59043c6a sas_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x5cd9aad0 sas_phy_enable +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x638d9bf0 sas_eh_bus_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x7836d482 sas_eh_device_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x80111eb9 __sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x87eb7d34 sas_slave_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x8a8cf1c2 sas_domain_attach_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x900c9c50 sas_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x9244a7a3 sas_bios_param +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x97ba5990 sas_unregister_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x98d0cf53 sas_domain_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x9d7559e0 sas_find_local_phy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xb9ce49ec sas_request_addr +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xc33d6bce sas_change_queue_type +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xcf5b90d9 sas_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xd8f16ba3 sas_slave_configure +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xe8e6bc8c sas_ssp_task_response +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xfeff4626 sas_register_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x4a642b97 srp_transfer_data +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x5afc2622 srp_iu_put +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x6186609c srp_iu_get +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x6a408cc7 srp_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xba9b8e7f srp_cmd_queue +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xe91b6474 srp_target_free +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x012df1c7 sdev_evt_send_simple +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x03a369b6 sdev_evt_send +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x1acfb7ef scsi_target_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x26c90ea4 scsi_eh_get_sense +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x355473ac __scsi_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x35d8c94a sdev_evt_alloc +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x4144070b scsi_schedule_eh +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7012512e scsi_eh_ready_devs +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7e275ea8 scsi_complete_async_scans +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x86a2eb07 scsi_internal_device_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xa030b861 scsi_queue_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xa8e987d2 scsi_mode_select +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xcc14d0f6 scsi_nl_sock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xceb01b2c scsi_execute_async +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd67c56a1 scsi_internal_device_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xea8dc0ea scsi_bus_type +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xf3b5dbe4 scsi_target_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xf97f577c scsi_flush_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x0225fbb3 scsi_tgt_tsk_mgmt_request +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x0305ac13 scsi_tgt_alloc_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x2ed853fc scsi_host_put_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x35164412 scsi_host_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x58369009 scsi_tgt_it_nexus_destroy +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x6703fc45 scsi_tgt_cmd_to_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x7c57105b scsi_tgt_it_nexus_create +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xb6e3e24c scsi_tgt_free_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xc84ee981 scsi_tgt_queue_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x02810e53 iscsi_destroy_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x11deb2e2 iscsi_session_chkready +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x152877d7 iscsi_add_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x20c02b84 iscsi_session_event +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x232689a2 iscsi_block_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x44136533 iscsi_create_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x4f22cd24 iscsi_host_for_each_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x6a78e16a iscsi_conn_error +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x75f48260 iscsi_unregister_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x964c0a8e iscsi_unblock_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xa4b479a1 iscsi_remove_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xa9609983 iscsi_create_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xb9da5009 iscsi_alloc_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xc40b947d iscsi_lookup_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xd4490e16 iscsi_register_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe02d3ce5 iscsi_destroy_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xeace0667 iscsi_destroy_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xf21f056c iscsi_free_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xf47fa329 iscsi_scan_finished +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xf6ad7fdd iscsi_recv_pdu +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xfdfe21bd iscsi_create_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0x0ef06974 spi_populate_ppr_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xa0c71dac spi_populate_sync_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xcffa2aff spi_populate_width_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x2b47920d srp_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x6e3b2a46 srp_rport_add +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x6e5c77b9 srp_remove_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xe3c57458 srp_rport_del +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xf34eb9b3 srp_attach_transport +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x4846c39c spi_bitbang_setup +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x661bc752 spi_bitbang_stop +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x74d5e2da spi_bitbang_start +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x7c4a66e6 spi_bitbang_setup_transfer +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x9ee9c0d0 spi_bitbang_transfer +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xe84ca4be spi_bitbang_cleanup +EXPORT_SYMBOL_GPL drivers/uio/uio 0x81dfac33 uio_event_notify +EXPORT_SYMBOL_GPL drivers/uio/uio 0x96e9f3ba __uio_register_device +EXPORT_SYMBOL_GPL drivers/uio/uio 0xc026731b uio_unregister_device +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0xa344bd17 usbatm_usb_disconnect +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0xc913dcc3 usbatm_usb_probe +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0114f8e1 usb_driver_claim_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x09458dd3 usb_deregister +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x09a4f430 usb_find_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x09ce6c49 usb_sg_init +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0a344247 usb_lock_device_for_reset +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0a4dd2a4 usb_clear_halt +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0ba0d242 usb_register_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0c31ef15 usb_hcd_pci_suspend +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x105bd075 usb_match_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x114f9d29 usb_deregister_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x13327fa0 usb_create_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x13f89761 usb_remove_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x17318e1e usb_sg_cancel +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x19a304ba usb_disabled +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1b951775 usb_reset_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1f5b63af usb_root_hub_lost_power +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x2245cf8a usb_anchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x249d0af1 usb_unlink_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x2725a6e2 usb_control_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x2ba558c3 usb_alloc_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x35c04166 usb_get_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x36f1548f usb_add_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x37a104b9 usb_hcd_platform_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x39bf5137 usb_buffer_alloc +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3be89d3c usb_register_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4a186815 usb_hcd_pci_remove +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4dbeb450 usb_reset_device +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x514368db usb_store_new_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x566100c4 usb_register_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x576dd0bc usb_sg_wait +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x590e3ab3 usb_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x59bba3fe usb_get_current_frame_number +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5d5efaf3 usb_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x60ec4c45 usb_get_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6acd277c usb_ep0_reinit +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6d36fb0e usb_get_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6dce94bf usb_bus_list_lock +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x738b5b2b usb_get_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x793ad49b usb_autopm_put_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7d043570 usb_deregister_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7e64181d usb_calc_bus_time +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7ee47796 usb_autopm_get_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x85acc8d7 usb_hcd_pci_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x86776fe0 usb_init_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x86b10394 ehci_cf_port_reset_rwsem +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x885cc311 usb_string +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8b1f97ea usb_free_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8b2439ba usb_buffer_map_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8b8d30ca usb_mon_register +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x94b0a65f usb_buffer_unmap_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9924c496 __usb_get_extra_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9b7b1927 usb_unanchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9ccf638c usb_buffer_free +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9ffa9b17 usb_hcd_giveback_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa19cf9e5 usb_put_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa6e927d8 usb_altnum_to_altsetting +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xaa4b6aad usb_driver_release_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xace5c0fc usb_bus_list +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xad69889e usb_hcd_pci_probe +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb168f6be usb_driver_set_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xba73157e usb_hub_tt_clear_buffer +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbc3a242f usb_wait_anchor_empty_timeout +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbe8efbe6 usb_ifnum_to_if +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc17515d7 usb_hcds_loaded +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc2fe0461 usb_hcd_unlink_urb_from_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc35577d7 usb_hcd_check_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc5efeb55 usb_hcd_poll_rh_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc8026bba usb_put_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcb0bf90a usb_hcd_pci_resume +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcd71c348 usb_hc_died +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd38ef1c5 usb_match_one_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd933f6ea usb_register_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xdae2f03a usb_autopm_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xdea16bed usb_get_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe3875d2a usb_kill_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9457eed usb_submit_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9587909 usb_unregister_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xebca2ed8 usb_hcd_link_urb_to_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xec3117f8 usb_kill_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xec32e66d usb_put_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf8cc17bb usb_hcd_resume_root_hub +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf94d6872 usb_interrupt_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfa3e5296 usb_bulk_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfbba7d5c usb_get_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfed11ed1 usb_mon_deregister +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x252ba976 usb_ftdi_elan_write_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x402e24c5 usb_ftdi_elan_edset_setup +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x6187edff usb_ftdi_elan_edset_flush +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xb9e7cf83 usb_ftdi_elan_edset_single +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xc161fa8d ftdi_elan_gone_away +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xd59ad4ce usb_ftdi_elan_edset_output +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xd7af6e81 usb_ftdi_elan_edset_input +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xe374cf8f usb_ftdi_elan_edset_empty +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xff8358e7 usb_ftdi_elan_read_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/phidget 0x5bfbf2b8 phidget_class +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x152a7773 ezusb_set_reset +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x38e4d5d1 usb_serial_generic_read_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xb8f28bcc ezusb_writememory +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xbfa0c144 usb_serial_probe +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xc95b015a usb_serial_port_softint +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xcb754ea8 usb_serial_register +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xe19f5246 usb_serial_disconnect +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xf1689f69 usb_serial_deregister +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xf469f14d usb_serial_generic_open +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xfe6df49d usb_serial_generic_write_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x3edad223 usb_usual_clear_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x89d4dbaf usb_usual_check_type +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xcd9991a9 usb_usual_set_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xde134c69 storage_usb_ids +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x486815d3 ili9320_write_regs +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x5da7b7e6 ili9320_write +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x7eb0f68e ili9320_resume +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x93193793 ili9320_probe_spi +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xd792ceac ili9320_remove +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xea0deb63 ili9320_suspend +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xf72627d2 ili9320_shutdown +EXPORT_SYMBOL_GPL drivers/video/fb_ddc 0x67714876 fb_ddc_read +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x32ed4198 fb_sys_read +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x8c5f223e fb_sys_write +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x028bd655 sis_malloc_new +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x1b4a2188 sis_free_new +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x016e6c20 vmlfb_unregister_subsys +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x90c018c6 vmlfb_register_subsys +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x261fa192 unregister_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x476cefc7 unregister_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x9e98f739 virtio_check_driver_offered_feature +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xb6ae15f8 register_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xe7b28da8 register_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x03c4687d vring_interrupt +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x45a846b3 vring_del_virtqueue +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x65495d2c vring_transport_features +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0xcea361be vring_new_virtqueue +EXPORT_SYMBOL_GPL drivers/w1/wire 0x50c66761 w1_write_8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0x7c2f2afb w1_calc_crc8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0x9a5a25aa w1_write_block +EXPORT_SYMBOL_GPL drivers/w1/wire 0xa3ad80c5 w1_reset_bus +EXPORT_SYMBOL_GPL drivers/w1/wire 0xb50662cb w1_read_block +EXPORT_SYMBOL_GPL drivers/w1/wire 0xf1fc3c6b w1_reset_select_slave +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x11d8e5e7 dlm_posix_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x274e45b9 dlm_posix_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x9321df95 dlm_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xa7eb5097 dlm_posix_get +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xcf9f3328 dlm_release_lockspace +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdc583c08 dlm_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdf3c14de dlm_new_lockspace +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0x46cd4302 exportfs_decode_fh +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0x7c3f7774 exportfs_encode_fh +EXPORT_SYMBOL_GPL fs/fat/fat 0x0cfe4f9c fat_scan +EXPORT_SYMBOL_GPL fs/fat/fat 0x208fc907 fat_fill_super +EXPORT_SYMBOL_GPL fs/fat/fat 0x2bdf3dd9 fat_attach +EXPORT_SYMBOL_GPL fs/fat/fat 0x39ba8695 fat_detach +EXPORT_SYMBOL_GPL fs/fat/fat 0x672a809a fat_setattr +EXPORT_SYMBOL_GPL fs/fat/fat 0x7619a0de fat_alloc_new_dir +EXPORT_SYMBOL_GPL fs/fat/fat 0x7a0ce7a1 fat_add_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0x831cd4eb fat_dir_empty +EXPORT_SYMBOL_GPL fs/fat/fat 0x8a210219 fat_sync_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0x958855c5 fat_getattr +EXPORT_SYMBOL_GPL fs/fat/fat 0x963334ab fat_fs_panic +EXPORT_SYMBOL_GPL fs/fat/fat 0x9a2ea991 fat_build_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0xa8306caa fat_search_long +EXPORT_SYMBOL_GPL fs/fat/fat 0xb68ea16d fat_date_unix2dos +EXPORT_SYMBOL_GPL fs/fat/fat 0xbc5ce3c3 fat_flush_inodes +EXPORT_SYMBOL_GPL fs/fat/fat 0xc62a2a1b fat_free_clusters +EXPORT_SYMBOL_GPL fs/fat/fat 0xedcc4459 fat_get_dotdot_entry +EXPORT_SYMBOL_GPL fs/fat/fat 0xee886172 fat_remove_entries +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0x74874ab1 gfs2_register_lockproto +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0x9d06d7cf gfs2_unregister_lockproto +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x1a618932 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x3b3a1b03 nlmclnt_done +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x4ac693a7 nlmclnt_proc +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x63f47916 nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x8814fbcf nlmclnt_init +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x06d14494 o2nm_get_node_by_ip +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1b89c6ee o2hb_fill_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1cb231d0 mlog_not_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1d747ce3 o2hb_check_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x35546f28 o2nm_node_get +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x36418553 o2net_send_message +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4900035b o2hb_stop_all_regions +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x687f6251 mlog_and_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa4532c6a o2nm_get_node_by_num +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa82a8645 o2nm_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa87bc9e7 o2nm_configured_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa9f5379a o2net_send_message_vec +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xae808bac o2net_register_handler +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xbaeb4700 o2hb_check_node_heartbeating_from_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xd60f2c6c o2hb_check_local_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xe2ecb879 o2nm_node_put +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xe85e99e9 o2hb_register_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf18d0543 o2hb_setup_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf1a5611d o2net_unregister_handler_list +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf9339d5d o2hb_unregister_callback +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x2b036579 dlmunlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x450b53dc dlm_unregister_domain +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x72786243 dlmlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x7a1211f8 dlm_setup_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x9af0413e dlm_register_domain +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xcbc0b1f5 dlm_print_one_lock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xcd165d4b dlm_register_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd7ba575e dlm_errmsg +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd8fa57a6 dlm_unregister_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xfb86b96f dlm_errname +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0562c415 ocfs2_cluster_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0e27f909 ocfs2_dlm_lock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x21db5b88 ocfs2_cluster_disconnect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4a1f6fe9 ocfs2_cluster_connect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4d3af7fa ocfs2_cluster_hangup +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x59602db7 ocfs2_stack_glue_register +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x5b14c343 ocfs2_stack_glue_unregister +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x81c85a68 ocfs2_dlm_lock_status +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x91fab465 ocfs2_dlm_lvb +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x963932a3 ocfs2_stack_glue_set_locking_protocol +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xa7d5c1c0 ocfs2_dlm_unlock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xd066711e ocfs2_dlm_dump_lksb +EXPORT_SYMBOL_GPL lib/lzo/lzo_compress 0x56b63670 lzo1x_1_compress +EXPORT_SYMBOL_GPL lib/lzo/lzo_decompress 0xf30fda27 lzo1x_decompress_safe +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x300d7e57 free_rs +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x6fbb3bd9 init_rs_non_canonical +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xabda1e2e decode_rs16 +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xb050f329 init_rs +EXPORT_SYMBOL_GPL net/802/garp 0x4fcac1ba garp_request_join +EXPORT_SYMBOL_GPL net/802/garp 0x55fdab13 garp_init_applicant +EXPORT_SYMBOL_GPL net/802/garp 0x8f02ef7f garp_unregister_application +EXPORT_SYMBOL_GPL net/802/garp 0x9340c635 garp_register_application +EXPORT_SYMBOL_GPL net/802/garp 0xd7963aeb garp_request_leave +EXPORT_SYMBOL_GPL net/802/garp 0xffede249 garp_uninit_applicant +EXPORT_SYMBOL_GPL net/802/stp 0xea57f5b6 stp_proto_unregister +EXPORT_SYMBOL_GPL net/802/stp 0xfb70f5e1 stp_proto_register +EXPORT_SYMBOL_GPL net/ax25/ax25 0xa3180543 ax25_register_pid +EXPORT_SYMBOL_GPL net/ax25/ax25 0xac93ae05 ax25_bcast +EXPORT_SYMBOL_GPL net/ax25/ax25 0xaeb7451e ax25_defaddr +EXPORT_SYMBOL_GPL net/bluetooth/bluetooth 0xf7ef7058 bt_class +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x09c5ed3c tfrc_tx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x0a487ea5 tfrc_calc_x +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x0b25c56b tfrc_rx_hist_add_packet +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x106fe6d3 tfrc_tx_hist_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x24ea9306 tfrc_rx_hist_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x49205e86 tfrc_rx_handle_loss +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x62b1351b tfrc_rx_hist_duplicate +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x69ec5731 tfrc_tx_hist_add +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x6c252d29 tfrc_calc_x_reverse_lookup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x902206f0 tfrc_lh_cleanup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x92285650 tfrc_rx_hist_alloc +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xc3c27769 tfrc_lh_update_i_mean +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xc612a5b6 tfrc_rx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xdc5e2c5f tfrc_lh_interval_add +EXPORT_SYMBOL_GPL net/dccp/dccp 0x11022a68 dccp_getsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x13f15c21 dccp_hashinfo +EXPORT_SYMBOL_GPL net/dccp/dccp 0x1a4e6a90 dccp_feat_change_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0x1d99d49a dccp_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0x2ac4eb4c dccp_recvmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0x2e43f32a dccp_rcv_established +EXPORT_SYMBOL_GPL net/dccp/dccp 0x2e7afd56 dccp_sendmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3a7b06d7 dccp_poll +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3b3c0b1b dccp_feat_clean +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4c4d0b3a dccp_feat_confirm_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4d1ef0e3 dccp_reqsk_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4e42cfdd ccid_hc_rx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0x56ea266a dccp_state_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x58afaf6b inet_dccp_listen +EXPORT_SYMBOL_GPL net/dccp/dccp 0x5efb3919 ccid_hc_tx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0x60705c0f dccp_check_req +EXPORT_SYMBOL_GPL net/dccp/dccp 0x655e0871 dccp_set_state +EXPORT_SYMBOL_GPL net/dccp/dccp 0x671c02a3 ccid_register +EXPORT_SYMBOL_GPL net/dccp/dccp 0x6feea4a9 dccp_init_sock +EXPORT_SYMBOL_GPL net/dccp/dccp 0x7c8e1094 dccp_disconnect +EXPORT_SYMBOL_GPL net/dccp/dccp 0x7e85ef5a dccp_child_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0x86be7924 dccp_packet_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x86eccb8a ccid_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0x874be11a dccp_close +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b7d8caf dccp_statistics +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8f4c4523 dccp_insert_option_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8fe44f56 ccid_unregister +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9b155e80 dccp_parse_options +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9b55303f dccp_create_openreq_child +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9d6a3846 dccp_orphan_count +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9f11f593 dccp_done +EXPORT_SYMBOL_GPL net/dccp/dccp 0xa3472050 dccp_insert_option +EXPORT_SYMBOL_GPL net/dccp/dccp 0xa9bd9246 dccp_reqsk_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0xae4682fe dccp_insert_option_elapsed_time +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbca3f677 dccp_shutdown +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe4cf010 dccp_feat_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbf6b58ba dccp_feat_change +EXPORT_SYMBOL_GPL net/dccp/dccp 0xc1861a32 dccp_connect +EXPORT_SYMBOL_GPL net/dccp/dccp 0xc29caf9a dccp_sync_mss +EXPORT_SYMBOL_GPL net/dccp/dccp 0xc31971a5 dccp_feat_clone +EXPORT_SYMBOL_GPL net/dccp/dccp 0xc3636473 dccp_ctl_make_reset +EXPORT_SYMBOL_GPL net/dccp/dccp 0xc612bedc dccp_destroy_sock +EXPORT_SYMBOL_GPL net/dccp/dccp 0xcafe9c63 dccp_ioctl +EXPORT_SYMBOL_GPL net/dccp/dccp 0xd652b4af dccp_rcv_state_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0xdb580217 dccp_make_response +EXPORT_SYMBOL_GPL net/dccp/dccp 0xdb702135 ccid_hc_tx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0xdeb19aa5 dccp_send_sync +EXPORT_SYMBOL_GPL net/dccp/dccp 0xe13c9369 ccid_hc_rx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0xe3738b5f dccp_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf7da1dda dccp_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf8c55119 dccp_death_row +EXPORT_SYMBOL_GPL net/dccp/dccp 0xfa44f36a dccp_setsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x019ea1d7 dccp_invalid_packet +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x986ca797 dccp_v4_connect +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xac7a57e7 dccp_v4_send_check +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xb403c153 dccp_v4_request_recv_sock +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xf70ac153 dccp_v4_conn_request +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xfd266c35 dccp_v4_do_rcv +EXPORT_SYMBOL_GPL net/ieee80211/ieee80211 0x2456938e ieee80211_rx_any +EXPORT_SYMBOL_GPL net/ipv4/ipvs/ip_vs 0xe6476b4a net_vs_ctl_path +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x6d40a921 need_ipv4_conntrack +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0xcc311efc nf_nat_seq_adjust_hook +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x07ae60b6 nf_nat_proto_in_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x100b4646 nf_nat_proto_put +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x24b178e1 nf_nat_packet +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x59c3072f nf_nat_proto_unique_tuple +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x85bbf8d4 nf_nat_proto_range_to_nlattr +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x92cdf520 nf_nat_proto_find_get +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x94a08134 nf_nat_proto_nlattr_to_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x986a9c98 nf_nat_icmp_reply_translation +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat_proto_gre 0x636b12c8 nf_nat_need_gre +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x4f4f8f38 tcp_vegas_pkts_acked +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x67dbebb8 tcp_vegas_init +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xc2aebbfc tcp_vegas_cwnd_event +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xeae3348e tcp_vegas_get_info +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xf20ebe2a tcp_vegas_state +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x08a3e5d1 net_ipv6_ctl_path +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x0a3fb207 inet6_csk_xmit +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x1c4942dc ip6_dst_blackhole +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x1e4fb932 inet6_csk_bind_conflict +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x223b381e ipv6_dup_options +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x227eb2e7 inet6_csk_addr2sockaddr +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x40b1f362 ip6_sk_dst_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x42f63b31 inet6_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x4a89d4c6 inet6_sk_rebuild_header +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x4fc48d9f inet6_destroy_sock +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x77562c77 ipv6_find_tlv +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x96aa95c5 ip6_local_out +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xaa370b15 ipv6_opt_accepted +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xb806c1ab inet6_csk_search_req +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xc61e434a fl6_sock_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xff0ec8f4 ip6_dst_lookup +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x2fe0c3a8 ieee80211_iterate_active_interfaces_atomic +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x45c1672d ieee80211_iterate_active_interfaces +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x011139ff nf_ct_get_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x01b4dd49 nf_ct_port_tuple_to_nlattr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x041013fd nf_conntrack_lock +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x045072cd nf_ct_port_nla_policy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0629b4ee nf_conntrack_l4proto_udp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0948fb1b nf_conntrack_l3proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0ea4f6dc nf_ct_iterate_cleanup +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1283d711 nf_ct_expect_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x13892ce2 nf_ct_l4proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x15c10b0b nf_conntrack_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1c181a46 nf_conntrack_tcp_update +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1c71bfa6 nf_ct_expect_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x22271bb5 nf_conntrack_l4proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x231707df __nf_ct_expect_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x248d7f93 nf_conntrack_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x25e649f2 nf_ct_log_invalid +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2987eae6 __nf_conntrack_confirm +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x29959e2d __nf_ct_l4proto_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2b9580cb nf_conntrack_flush +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x307dce8a nf_ct_helper_ext_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x341fd66c nf_conntrack_l4proto_udp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3609de81 nf_conntrack_count +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38630158 nf_conntrack_tuple_taken +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38c9440b nf_ct_extend_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3f5b1415 nf_ct_port_nlattr_to_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x40387ccf __nf_ct_event_cache_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4850fb4d nf_ct_l3proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4bd594b9 __nf_conntrack_helper_find_byname +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4fe4a947 nf_conntrack_l4proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5dae2fb1 nf_conntrack_l3proto_generic +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x63ec2e47 nf_ct_l4proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6cd91ee0 per_cpu__nf_conntrack_ecache +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6e224a7a need_conntrack +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x70bac156 nf_ct_get_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x72836f4a nf_conntrack_free +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x77aadb54 nf_conntrack_alter_reply +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x78f9b710 nf_ct_l3proto_try_module_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x7923cd42 nf_conntrack_l3proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x79ca2e53 nf_ct_expect_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x7e472667 nf_ct_unexpect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x819f7145 nf_ct_l3proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x880ee5e0 nf_ct_expect_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x886a1333 seq_print_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8b25ae89 nf_ct_expect_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8ffe7e89 nf_conntrack_htable_size +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9026b703 nf_conntrack_helper_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x90ff6c9f nf_ct_invert_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa371daa3 nf_ct_expect_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa378ec98 nf_conntrack_helper_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa6f62ec0 nf_conntrack_set_hashsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa8a55bbf __nf_ct_kill_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xace98352 nf_conntrack_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaf57e66f nf_ct_extend_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb602c57e nf_ct_l3proto_module_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb76accc2 __nf_conntrack_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb9e30797 nf_ct_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbc887e16 nf_ct_expect_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbe3f2939 nf_conntrack_checksum +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc044befe nf_ct_free_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc18ac88d nf_ct_expect_hsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc35a7a3e nf_conntrack_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc5ece8ee nf_ct_unlink_expect +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc79fb36d nf_ct_expect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc7b64d79 nf_conntrack_hash_insert +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcbf7fd2a nf_conntrack_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xccd22839 nf_ct_invert_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd0f2bef6 nf_ct_l3protos +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd486660d nf_conntrack_l4proto_tcp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd50a96a2 nf_ct_alloc_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd7c683c4 nf_conntrack_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd9efb053 nf_ct_deliver_cached_events +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xde3eb14e __nf_ct_helper_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe6b0048f nf_conntrack_l4proto_tcp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe93358f0 nf_conntrack_in +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xec8beba6 nf_ct_expect_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf1959d72 print_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf9ae81a1 nf_conntrack_max +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfa169dac nf_conntrack_untracked +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfb839673 nf_ct_remove_expectations +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xffdd92dd __nf_ct_refresh_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_amanda 0x8985442a nf_nat_amanda_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_ftp 0xd72700d7 nf_nat_ftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x14769c73 nat_h245_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x264c0cf3 get_h225_addr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x3f5dfa2d nat_t120_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x4cd82898 nat_callforwarding_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x7f15eae6 set_h245_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x84082c68 set_ras_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x95240696 nat_rtp_rtcp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xac664f1f set_h225_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xb3b1ff49 nat_q931_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xf34b471b set_sig_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_irc 0xcf4109d5 nf_nat_irc_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x135e3ba6 nf_nat_pptp_hook_inbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x1f5589d8 nf_nat_pptp_hook_exp_gre +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x47ac644f nf_nat_pptp_hook_expectfn +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xa0f0bc13 nf_nat_pptp_hook_outbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x05f8e58c nf_ct_gre_keymap_destroy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x6f59d77c nf_ct_gre_keymap_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x13169b79 ct_sip_parse_request +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x3c2058a6 ct_sip_parse_numerical_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5333cb69 ct_sip_parse_header_uri +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5343611e ct_sip_get_sdp_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x56ad8f6e ct_sip_parse_address_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x60665807 nf_nat_sdp_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x6b2f69f5 nf_nat_sip_expect_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xc3bce97b nf_nat_sdp_port_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xd59cbb29 nf_nat_sip_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xde43d65d nf_nat_sdp_session_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf7accabb nf_nat_sdp_media_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf8b610ea ct_sip_get_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_tftp 0x04add747 nf_nat_tftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x304765b9 nfnetlink_subsys_register +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x5150b647 nfnetlink_unicast +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x53c8cd14 nfnetlink_subsys_unregister +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xcc55b2b6 nfnetlink_send +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xeca95329 nfnetlink_has_listeners +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x23e9a848 xt_table_unlock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x29a12f5e xt_check_match +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x3d85fb93 xt_check_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x63f05053 xt_find_revision +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x6d8b86fd xt_register_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x771cb09a xt_replace_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x836dcf3b xt_proto_init +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x97061934 xt_proto_fini +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x9d0d1af2 xt_unregister_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xc171bf34 xt_find_table_lock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xd98bfbf3 xt_request_find_target +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xc177bee0 xt_rateest_put +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xdb8418cc xt_rateest_lookup +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x83b2e956 register_rfkill_notifier +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x86c722f8 rfkill_epo +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0xa6f4320d unregister_rfkill_notifier +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0x7f4b19a1 rxrpc_register_security +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0xfaba7aff rxrpc_unregister_security +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0233c975 xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x065c35f0 rpc_print_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x08073774 rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0c9c505c rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x108a3d03 xprt_complete_rqst +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x169e8f76 rpc_peeraddr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x175da6e0 svc_xprt_put +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1eb7537b rpc_clone_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x22734c86 put_rpccred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x234b2c53 rpc_bind_new_program +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x25cc7733 xprt_disconnect_done +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x27a6cfd7 rpc_killall_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2aa17774 rpc_free_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2ee94484 rpc_run_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3083c152 svc_reg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x31a89d59 rpc_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x331ba103 xprt_release_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x33f845b0 rpc_proc_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x36117330 rpc_call_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x375cdf47 svc_unreg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x44f4c916 rpc_malloc +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x45d85917 rpc_shutdown_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4b87c8a3 rpc_call_null +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x521f9597 xprt_release_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x53445f68 nlm_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5395cc00 xprt_adjust_cwnd +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x550547a3 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x57aafdf9 rpc_restart_call +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x58c99f43 rpc_alloc_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5959335e svc_print_addr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5aee6e79 rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bd26000 rpc_proc_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x61af8d3e svc_addsock +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x62b3fcbb svc_close_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x67d9578a rpc_call_start +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x69419e17 rpc_lookup_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6abcee89 xprt_write_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c5304c5 rpcb_getport_sync +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6cc4cb84 xdr_skb_read_bits +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6d2608f6 rpc_delay +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7de53067 rpc_init_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x840e54c8 xprt_lookup_rqst +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8a181c0a rpc_sleep_on +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8b61c428 rpc_wake_up_next +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9711eb6c rpcauth_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x99ec1743 rpc_exit_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9ad4e521 rpc_force_rebind +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9bb18600 svc_find_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9dde8e43 rpcauth_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9ef82924 xprt_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9fdb6a6d svc_create_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa18e18cb xprt_unregister_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa5573e2d rpc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa6a643a0 rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa96556fb rpcb_getport_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xad3167a8 rpc_call_sync +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xadff5a67 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf5bf6ef nfs_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf68fdfe svc_xprt_names +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf8f24f6 svc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb2aaf53b xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb387b246 rpc_wake_up_status +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb84bc8df svc_xprt_init +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb98900f2 xprt_reserve_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbe8edb0a svc_xprt_received +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbea988b9 svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf9d1b96 nfsd_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc12435e3 rpc_calc_rto +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc2ad1a26 rpcauth_init_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcb6379b2 xprt_register_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xceedb9cd xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd153492a svc_xprt_enqueue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd1fb8428 rpcauth_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd82c728e rpc_init_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe022ac5d rpcauth_init_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe0585788 rpc_setbufsize +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe52830fa rpc_peeraddr2str +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedd1ba52 rpc_wake_up +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xee37796d xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xeeacab69 rpc_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf0f17b02 __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf46c7464 rpc_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf4c79f3d rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf9d1164c rpc_free +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfa03b3fe xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfc11512e xprt_release_rqst_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfc262d5b rpc_put_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfe245d4e csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x469a94c1 ipcomp_destroy +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x64fd80ee ipcomp_output +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x7ad71cc5 ipcomp_input +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x956292b5 ipcomp_init_state +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0370790d snd_soc_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x197a8217 snd_soc_dai_set_clkdiv +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1b04a19f snd_soc_dapm_stream_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1ea4260e snd_soc_get_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1eef1cae snd_soc_info_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x2891526c snd_soc_dapm_new_widgets +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x309c64ac snd_soc_dai_digital_mute +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x33620fcf snd_soc_dapm_new_control +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x338e42e3 snd_soc_dapm_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x37b6ad71 snd_soc_dapm_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3958747e snd_soc_put_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x405b6236 snd_soc_info_volsw_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x44aedf29 dapm_reg_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x4ed4e582 snd_soc_cnew +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x521e28fe snd_soc_dapm_disable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x59abf7df snd_soc_update_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x63301909 snd_soc_dai_set_tdm_slot +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x65f2182f snd_soc_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6ea8630d snd_soc_dai_set_fmt +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x7f859039 snd_soc_test_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8091fedb snd_soc_dapm_new_controls +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8add9480 snd_soc_dai_set_pll +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8da1e5a2 snd_soc_info_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x969da25a snd_soc_dapm_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x9bf5bef4 snd_soc_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x9d448523 snd_soc_set_runtime_hwparams +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x9df1d3f8 snd_soc_register_card +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa5b6d274 snd_soc_dai_set_tristate +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa66399b4 snd_soc_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbb16d21b snd_soc_new_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbd8522d1 snd_soc_info_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbdfa2ae1 snd_soc_info_enum_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc20b976a snd_soc_info_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc9b10baa snd_soc_dapm_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd84adaa8 snd_soc_dapm_sync +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdb129154 snd_soc_free_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdc215912 snd_soc_new_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdebd209d snd_soc_get_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe58a2861 snd_soc_dapm_get_pin_status +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xecbdd617 snd_soc_dapm_add_routes +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xed0e29f2 snd_soc_dapm_free +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf94172ed snd_soc_put_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfc37bc79 snd_soc_dai_set_sysclk +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfd03f658 snd_soc_dapm_enable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xffc38bfa snd_soc_dapm_connect_input +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xffd5b1ed snd_soc_free_ac97_codec +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x1584fdb9 tlsf_destroy_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x42a50f11 tlsf_malloc +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x66da3d8f tlsf_create_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xe6acc368 tlsf_free +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xee6c65c9 tlsf_get_used_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xeec8caeb tlsf_get_total_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xf9805f1b tlsf_calloc +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x02500586 thinkpad_ec_unlock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x0dc7484e thinkpad_ec_try_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x2552d213 thinkpad_ec_lock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x3dbfef12 thinkpad_ec_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x8dbbd831 thinkpad_ec_invalidate +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xa3042743 thinkpad_ec_prefetch_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xfb5aa917 thinkpad_ec_try_lock +EXPORT_SYMBOL_GPL vmlinux 0x00566d8f inotify_get_cookie +EXPORT_SYMBOL_GPL vmlinux 0x006482d9 bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x006d7cad srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x01032b44 get_device +EXPORT_SYMBOL_GPL vmlinux 0x011a8b72 platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x0134a9de debugfs_create_bool +EXPORT_SYMBOL_GPL vmlinux 0x01848a8e local_apic_timer_c2_ok +EXPORT_SYMBOL_GPL vmlinux 0x01a43c5d pci_find_next_capability +EXPORT_SYMBOL_GPL vmlinux 0x01a4ea6d unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x01e1a8de kgdb_breakpoint +EXPORT_SYMBOL_GPL vmlinux 0x02055af3 pci_enable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0x021d2682 xenbus_frontend_closed +EXPORT_SYMBOL_GPL vmlinux 0x02249d2f tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0x0279ccb2 spi_add_device +EXPORT_SYMBOL_GPL vmlinux 0x02ab1f28 sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x02ccea56 lock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x033b297c inotify_destroy +EXPORT_SYMBOL_GPL vmlinux 0x0343bdf1 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x0362601d platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x03f94469 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x042362b1 seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0x042910c2 rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x04486e88 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x04566c7f init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x04b6ed97 crypto_hash_type +EXPORT_SYMBOL_GPL vmlinux 0x04c3f2c1 gnttab_empty_grant_references +EXPORT_SYMBOL_GPL vmlinux 0x051e6a25 blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0x0520f7f4 crypto_register_instance +EXPORT_SYMBOL_GPL vmlinux 0x054e550b kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x05e835d3 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0x0611db94 __blk_add_trace +EXPORT_SYMBOL_GPL vmlinux 0x064db9a5 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x06ca400e pciserial_init_ports +EXPORT_SYMBOL_GPL vmlinux 0x06d222f8 device_resume +EXPORT_SYMBOL_GPL vmlinux 0x0764906c devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x07775032 get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0x07b52e38 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x07ff4aea xenbus_scanf +EXPORT_SYMBOL_GPL vmlinux 0x081d4735 cpufreq_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x081d6558 vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0x08addb1a __audit_inode_child +EXPORT_SYMBOL_GPL vmlinux 0x08c93552 tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0x08dd6364 xfrm_audit_state_notfound +EXPORT_SYMBOL_GPL vmlinux 0x08e7a6cb device_move +EXPORT_SYMBOL_GPL vmlinux 0x08ebd45f device_initialize +EXPORT_SYMBOL_GPL vmlinux 0x091eb9b4 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x09be9767 page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0x0a99d81b inet_hash +EXPORT_SYMBOL_GPL vmlinux 0x0a9d0bf7 bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x0acf090d driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0x0b9e724f class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0bc151e5 klist_init +EXPORT_SYMBOL_GPL vmlinux 0x0c17e274 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x0c408ae9 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0x0c4717f7 srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0x0c56d31a fb_bl_default_curve +EXPORT_SYMBOL_GPL vmlinux 0x0d18d070 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x0d868b14 inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0x0d8df545 __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0x0e2cff45 __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0x0e9b87d3 inotify_add_watch +EXPORT_SYMBOL_GPL vmlinux 0x0eaf4f8f page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x0ec210b8 xen_start_info +EXPORT_SYMBOL_GPL vmlinux 0x0ef84c65 hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x0f0d238a key_type_user +EXPORT_SYMBOL_GPL vmlinux 0x0f38d94e cpufreq_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0x0f561dd6 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0x0f5953cc sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0fe2d570 xenbus_directory +EXPORT_SYMBOL_GPL vmlinux 0x10018797 sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0x1050bc52 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x10836bba pci_set_pcie_reset_state +EXPORT_SYMBOL_GPL vmlinux 0x10b17493 led_trigger_set +EXPORT_SYMBOL_GPL vmlinux 0x110fe2c0 platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0x11382702 user_match +EXPORT_SYMBOL_GPL vmlinux 0x11a28075 page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0x12242726 cpuidle_disable_device +EXPORT_SYMBOL_GPL vmlinux 0x124f2056 crypto_get_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x1251d30f call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x1269c99f platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0x127a90e7 tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0x129275f3 hvc_alloc +EXPORT_SYMBOL_GPL vmlinux 0x13664e90 find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x13b2a946 register_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x145eebd0 device_power_up +EXPORT_SYMBOL_GPL vmlinux 0x149db923 selinux_string_to_sid +EXPORT_SYMBOL_GPL vmlinux 0x1510eb16 crypto_init_spawn +EXPORT_SYMBOL_GPL vmlinux 0x15568631 lookup_address +EXPORT_SYMBOL_GPL vmlinux 0x1598dc9d unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x15999001 audit_log_d_path +EXPORT_SYMBOL_GPL vmlinux 0x159eb256 blk_trace_setup +EXPORT_SYMBOL_GPL vmlinux 0x15b0606e e820_any_mapped +EXPORT_SYMBOL_GPL vmlinux 0x163efd34 sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0x16c8d8b3 crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x16d768b6 device_attach +EXPORT_SYMBOL_GPL vmlinux 0x16f76869 probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x172e72d4 vdso_enabled +EXPORT_SYMBOL_GPL vmlinux 0x1769f2c6 user_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x1786d8b0 __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x17c06b47 register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x17c1bd2b driver_register +EXPORT_SYMBOL_GPL vmlinux 0x1878f62b edac_err_assert +EXPORT_SYMBOL_GPL vmlinux 0x18a7c4b1 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x18d53420 kgdb_register_io_module +EXPORT_SYMBOL_GPL vmlinux 0x18e818f0 xenbus_watch_path +EXPORT_SYMBOL_GPL vmlinux 0x18f83fab gnttab_grant_foreign_access_ref +EXPORT_SYMBOL_GPL vmlinux 0x1971deef xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0x19f063e2 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0x1a43c332 unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x1a938737 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x1acda5b2 atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1b0bab4b inotify_rm_watch +EXPORT_SYMBOL_GPL vmlinux 0x1b60d688 sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0x1b8cdb1f debugfs_create_symlink +EXPORT_SYMBOL_GPL vmlinux 0x1b9aca3f jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x1d328a18 rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0x1dd70100 dmi_walk +EXPORT_SYMBOL_GPL vmlinux 0x1e7bbcb3 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x1ea4dcc0 inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0x1eb9516e round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x1f8ec1b3 acpi_get_pci_rootbridge_handle +EXPORT_SYMBOL_GPL vmlinux 0x1f9a0fbf hpet_unregister_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x1fcece42 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x20577ea2 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x20b82470 hpet_register_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x20bc3470 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x20e4484f class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x20e9da37 securityfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x21003add posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0x21379645 rtc_class_close +EXPORT_SYMBOL_GPL vmlinux 0x22472bf4 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x2296c00d crypto_attr_u32 +EXPORT_SYMBOL_GPL vmlinux 0x2296e3e6 security_inode_setattr +EXPORT_SYMBOL_GPL vmlinux 0x22d98f2c power_supply_unregister +EXPORT_SYMBOL_GPL vmlinux 0x23282308 elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x23679939 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x23864ce7 cpuset_mem_spread_node +EXPORT_SYMBOL_GPL vmlinux 0x24196ba2 init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x2447533c ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0x2452da74 tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0x24c7698a xenbus_write +EXPORT_SYMBOL_GPL vmlinux 0x24eb7e32 leds_list +EXPORT_SYMBOL_GPL vmlinux 0x24ff0338 __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x2542d1d3 rtc_set_alarm +EXPORT_SYMBOL_GPL vmlinux 0x2545c170 unregister_xenbus_watch +EXPORT_SYMBOL_GPL vmlinux 0x25a61e06 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x25dc7f43 device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x25e6a7c5 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0x26325fec pskb_put +EXPORT_SYMBOL_GPL vmlinux 0x26b1df2d console_drivers +EXPORT_SYMBOL_GPL vmlinux 0x26b2d364 sysdev_class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x26dfc5e5 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0x2712cce3 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0x2714c98c klist_del +EXPORT_SYMBOL_GPL vmlinux 0x2778785a inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0x27db53eb __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0x28088f0f pv_time_ops +EXPORT_SYMBOL_GPL vmlinux 0x2819e4a9 mmput +EXPORT_SYMBOL_GPL vmlinux 0x28d664ff __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x28e23139 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x28e58314 __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0x28f8be71 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0x292892ac platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x295394e2 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x296bb955 skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0x2a0efc1c disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0x2a678a13 __suspend_report_result +EXPORT_SYMBOL_GPL vmlinux 0x2a680d4a spi_new_device +EXPORT_SYMBOL_GPL vmlinux 0x2b63a7e0 rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0x2b802d1a pciserial_resume_ports +EXPORT_SYMBOL_GPL vmlinux 0x2b9f8e23 nf_net_ipv4_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x2bb96119 preempt_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x2bfdeb4e sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x2c16ed76 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x2cd5db51 inotify_init +EXPORT_SYMBOL_GPL vmlinux 0x2d1053c1 destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x2d244092 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0x2d448233 debugfs_create_blob +EXPORT_SYMBOL_GPL vmlinux 0x2d45bcda crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0x2d59c954 edac_handlers +EXPORT_SYMBOL_GPL vmlinux 0x2d9f2ce3 sched_clock_idle_wakeup_event +EXPORT_SYMBOL_GPL vmlinux 0x2e3815fd tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x2e3df23f lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0x2e6e7aee smp_ops +EXPORT_SYMBOL_GPL vmlinux 0x2ed92ddb spi_sync +EXPORT_SYMBOL_GPL vmlinux 0x2f870319 __class_register +EXPORT_SYMBOL_GPL vmlinux 0x2fa72e6d securityfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0x2fc2cdbb xenbus_alloc_evtchn +EXPORT_SYMBOL_GPL vmlinux 0x30d276a3 inotify_inode_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x30eb2fd9 fib_rules_lookup +EXPORT_SYMBOL_GPL vmlinux 0x30ff2afe fib_rules_register +EXPORT_SYMBOL_GPL vmlinux 0x313d1f48 fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0x3167f035 class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x316d9888 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x31ee4370 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x32542a25 hvc_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x325e677c gnttab_grant_foreign_transfer_ref +EXPORT_SYMBOL_GPL vmlinux 0x32924a4d scatterwalk_copychunks +EXPORT_SYMBOL_GPL vmlinux 0x32a69202 pciserial_remove_ports +EXPORT_SYMBOL_GPL vmlinux 0x32b0eb3e led_trigger_set_default +EXPORT_SYMBOL_GPL vmlinux 0x3392b1b1 inet6_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x3441c3d6 gpio_set_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x34441299 xfrm_audit_state_icvfail +EXPORT_SYMBOL_GPL vmlinux 0x3504572d debugfs_remove_recursive +EXPORT_SYMBOL_GPL vmlinux 0x3609b38b kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x361e2bcc save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x362e23ec call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x363a73ee device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x367f00e2 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0x3729c9a4 crypto_register_template +EXPORT_SYMBOL_GPL vmlinux 0x37467c96 tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x379880a8 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0x37d17fb7 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x3807021d cpufreq_cpu_get +EXPORT_SYMBOL_GPL vmlinux 0x3849155c nf_unregister_queue_handlers +EXPORT_SYMBOL_GPL vmlinux 0x3872b576 pci_unblock_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0x3895233b srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x39093e3f sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x392d9412 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0x3978db3a vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0x3997afb4 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x39c4207b screen_glyph +EXPORT_SYMBOL_GPL vmlinux 0x39d154f4 led_trigger_register +EXPORT_SYMBOL_GPL vmlinux 0x3a45d338 rtc_irq_set_state +EXPORT_SYMBOL_GPL vmlinux 0x3a7f8b86 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x3a903b8a exit_fs +EXPORT_SYMBOL_GPL vmlinux 0x3a9a440d gpiochip_add +EXPORT_SYMBOL_GPL vmlinux 0x3ac27421 tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x3ac3d8d2 unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x3b11d736 pci_disable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0x3be7af02 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x3c0f156a generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0x3c23e37f spi_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x3c63c935 dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x3c942368 profile_event_unregister +EXPORT_SYMBOL_GPL vmlinux 0x3c9432cb sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x3cd06035 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x3ce3a877 debugfs_create_x16 +EXPORT_SYMBOL_GPL vmlinux 0x3cfedb3f register_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x3d59f18c platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0x3d711cb9 sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x3d7ea99a gnttab_grant_foreign_transfer +EXPORT_SYMBOL_GPL vmlinux 0x3dbf6dd9 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0x3de96356 sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x3ea9f1de __class_create +EXPORT_SYMBOL_GPL vmlinux 0x3eb4e2dc inet_diag_unregister +EXPORT_SYMBOL_GPL vmlinux 0x3efb35c9 get_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0x3f01570a probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0x3f0734e2 spi_write_then_read +EXPORT_SYMBOL_GPL vmlinux 0x3f238101 dcookie_register +EXPORT_SYMBOL_GPL vmlinux 0x3f3f97f8 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0x3f84d4c9 gnttab_release_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x3f925642 __xenbus_register_frontend +EXPORT_SYMBOL_GPL vmlinux 0x404feb30 devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0x409cf031 acpi_ec_remove_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x40c39cff acpi_ec_add_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x411ede32 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0x41aad989 led_trigger_store +EXPORT_SYMBOL_GPL vmlinux 0x41f3cc90 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x424acc6d scatterwalk_done +EXPORT_SYMBOL_GPL vmlinux 0x425291b8 isa_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0x425508d3 stop_machine +EXPORT_SYMBOL_GPL vmlinux 0x430686f6 xenbus_dev_error +EXPORT_SYMBOL_GPL vmlinux 0x432fd7f6 __gpio_set_value +EXPORT_SYMBOL_GPL vmlinux 0x43b42e81 __cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0x43cdbbca __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0x4419e85e pci_cleanup_aer_uncorrect_error_status +EXPORT_SYMBOL_GPL vmlinux 0x44a65d5c lock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x44ab0c7a gpiochip_remove +EXPORT_SYMBOL_GPL vmlinux 0x45276055 get_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x452c04a4 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x453ccdb3 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0x457594fa crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x45b3f548 inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0x45bf1ff3 crypto_inc +EXPORT_SYMBOL_GPL vmlinux 0x45d14bdf hypercall_page +EXPORT_SYMBOL_GPL vmlinux 0x460bc759 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x460f31aa rodata_test_data +EXPORT_SYMBOL_GPL vmlinux 0x46a5bc57 fb_deferred_io_cleanup +EXPORT_SYMBOL_GPL vmlinux 0x46df52eb bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0x47229b5c gpio_request +EXPORT_SYMBOL_GPL vmlinux 0x48c2d8da inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0x4911f424 security_inode_permission +EXPORT_SYMBOL_GPL vmlinux 0x499043d3 crypto_init_queue +EXPORT_SYMBOL_GPL vmlinux 0x49d7c2dc input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x49e0c23c relay_flush +EXPORT_SYMBOL_GPL vmlinux 0x4a11a4fb bind_virq_to_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0x4a7e30d9 marker_probe_unregister_private_data +EXPORT_SYMBOL_GPL vmlinux 0x4ace6f42 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x4b6ec686 device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x4c3f74b4 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0x4c4418c3 platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x4c759827 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x4ccdfb16 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0x4ebac9a7 put_pid +EXPORT_SYMBOL_GPL vmlinux 0x4edaf7be inotify_dentry_parent_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x501cea2a fb_deferred_io_open +EXPORT_SYMBOL_GPL vmlinux 0x50634025 net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x50b67174 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x50e7193a __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x5108b3fc acpi_os_map_memory +EXPORT_SYMBOL_GPL vmlinux 0x51521bc6 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0x5164146c do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x51743bea pci_restore_msi_state +EXPORT_SYMBOL_GPL vmlinux 0x5174e076 invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0x518c2fc6 hpet_rtc_dropped_irq +EXPORT_SYMBOL_GPL vmlinux 0x51dd6488 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x5258d129 proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0x526ac4fc d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x52d111ea pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x5300fef6 simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0x53096224 crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0x53986488 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x547666cb vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0x548e06b3 vlan_dev_real_dev +EXPORT_SYMBOL_GPL vmlinux 0x54e12f5a tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0x55526907 xen_features +EXPORT_SYMBOL_GPL vmlinux 0x55c883dc inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x55e45dba blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0x56079bd2 input_class +EXPORT_SYMBOL_GPL vmlinux 0x56398615 mark_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5641485b tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x56680517 skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x5672998c sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x56c7a39f inet6_lookup +EXPORT_SYMBOL_GPL vmlinux 0x56db169e simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x5709e714 platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0x577105c3 xfrm_audit_policy_delete +EXPORT_SYMBOL_GPL vmlinux 0x5779d445 xenbus_exists +EXPORT_SYMBOL_GPL vmlinux 0x579e0bf5 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x57cf2a3b save_stack_trace_tsk +EXPORT_SYMBOL_GPL vmlinux 0x585c3d0c devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x587516a5 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x58b18ffe simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0x594ce7d5 bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0x597f3bc3 marker_get_private_data +EXPORT_SYMBOL_GPL vmlinux 0x59b56fb9 generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0x59c0b84a pci_update_slot_number +EXPORT_SYMBOL_GPL vmlinux 0x5a2b1b67 gnttab_free_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x5a7dd8da invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0x5ab467a9 fib_rules_cleanup_ops +EXPORT_SYMBOL_GPL vmlinux 0x5ac8c6b7 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x5af03a28 gnttab_claim_grant_reference +EXPORT_SYMBOL_GPL vmlinux 0x5b1df48e xenbus_unmap_ring_vfree +EXPORT_SYMBOL_GPL vmlinux 0x5b392b04 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0x5b5114f9 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x5bb44a32 klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x5bef3fdb __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x5bfc03c3 unregister_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5c25345e crypto_spawn_tfm +EXPORT_SYMBOL_GPL vmlinux 0x5c5094e9 zap_vma_ptes +EXPORT_SYMBOL_GPL vmlinux 0x5cfcf0f1 percpu_free +EXPORT_SYMBOL_GPL vmlinux 0x5d0f6f57 kbd_table +EXPORT_SYMBOL_GPL vmlinux 0x5d366dec gnttab_cancel_free_callback +EXPORT_SYMBOL_GPL vmlinux 0x5d57f956 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0x5d730e7b raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5d7a1f54 mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x5dd67618 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5e047c90 hwmon_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5e689ef4 sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0x5e701a3f __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x5e866417 default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0x5eb46970 xfrm_audit_state_notfound_simple +EXPORT_SYMBOL_GPL vmlinux 0x5f2da8c4 check_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5f316348 device_register +EXPORT_SYMBOL_GPL vmlinux 0x5f408bac klist_next +EXPORT_SYMBOL_GPL vmlinux 0x5f69e7d2 tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0x5f85f4b2 fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0x5fea940b hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x6091797f synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x60949b71 nf_unregister_afinfo +EXPORT_SYMBOL_GPL vmlinux 0x60a13e90 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x60c6355a devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x614b4801 rtc_read_alarm +EXPORT_SYMBOL_GPL vmlinux 0x61e6c5aa inotify_init_watch +EXPORT_SYMBOL_GPL vmlinux 0x62772690 platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x633f14ca transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0x63ae27d6 add_nops +EXPORT_SYMBOL_GPL vmlinux 0x63d34a7f __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x644cf8d9 spi_unregister_master +EXPORT_SYMBOL_GPL vmlinux 0x647324ed ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0x64a52b7f devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x64fd27e0 devres_find +EXPORT_SYMBOL_GPL vmlinux 0x650eba97 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0x6586ae3b crypto_register_alg +EXPORT_SYMBOL_GPL vmlinux 0x65ccb6f0 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x65d6d0f0 gpio_direction_input +EXPORT_SYMBOL_GPL vmlinux 0x6610ad99 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x66114346 platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x661601de sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x66b2a859 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x66d7fe89 tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0x66d87d38 symbol_put_addr +EXPORT_SYMBOL_GPL vmlinux 0x671de6cb input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x676a66c7 tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0x67955ce6 profile_hits +EXPORT_SYMBOL_GPL vmlinux 0x67b2db11 sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x67ccc34a blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0x67da9753 fb_deferred_io_init +EXPORT_SYMBOL_GPL vmlinux 0x67fc7e64 devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0x6807e8fc unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x6834cc83 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x683e0bf4 pci_slots_kset +EXPORT_SYMBOL_GPL vmlinux 0x6866966d tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x686c703f xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x6873e326 blk_trace_remove +EXPORT_SYMBOL_GPL vmlinux 0x6892088c unregister_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x69064c59 bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x691884ef pv_apic_ops +EXPORT_SYMBOL_GPL vmlinux 0x69364db9 xfrm_audit_state_delete +EXPORT_SYMBOL_GPL vmlinux 0x6a73a650 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0x6a99047f isa_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x6ab66e2f __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0x6b07a368 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0x6b3573da raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0x6b9178b3 xenbus_strstate +EXPORT_SYMBOL_GPL vmlinux 0x6bdb1702 blk_trace_startstop +EXPORT_SYMBOL_GPL vmlinux 0x6c11059b __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x6c49c4f2 clockevents_notify +EXPORT_SYMBOL_GPL vmlinux 0x6c5f7292 securityfs_remove +EXPORT_SYMBOL_GPL vmlinux 0x6c8d5ae8 __gpio_get_value +EXPORT_SYMBOL_GPL vmlinux 0x6d41ba19 inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0x6e2d0b3e xfrm_audit_state_add +EXPORT_SYMBOL_GPL vmlinux 0x6e58ddf0 gnttab_end_foreign_transfer_ref +EXPORT_SYMBOL_GPL vmlinux 0x6e8497a1 uhci_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x6ebe305d raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0x6f9c2efe marker_probe_cb +EXPORT_SYMBOL_GPL vmlinux 0x6ffb5b60 klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x7037d79d k8_flush_garts +EXPORT_SYMBOL_GPL vmlinux 0x715e41d6 xfrm_audit_policy_add +EXPORT_SYMBOL_GPL vmlinux 0x71c8bc95 kgdb_unregister_io_module +EXPORT_SYMBOL_GPL vmlinux 0x71f64d99 debugfs_create_x8 +EXPORT_SYMBOL_GPL vmlinux 0x71f76970 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0x720ed6e3 queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0x7278d328 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x727c3bb0 debugfs_create_x32 +EXPORT_SYMBOL_GPL vmlinux 0x72e6ea6b __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x72f6d346 tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0x73201149 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0x736d6a0e tty_find_polling_driver +EXPORT_SYMBOL_GPL vmlinux 0x73b1f76d do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x73b25f99 blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x73dda7b8 vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0x74740576 sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x74abdafa task_handoff_register +EXPORT_SYMBOL_GPL vmlinux 0x74d61a4d get_dcookie +EXPORT_SYMBOL_GPL vmlinux 0x74deb10c used_vectors +EXPORT_SYMBOL_GPL vmlinux 0x7503aa65 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x7521afb6 leave_mm +EXPORT_SYMBOL_GPL vmlinux 0x75272289 __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0x7543a836 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0x7568b92e register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x75c00c51 driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x75c8a11c inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x75e8f3c3 crypto_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x7626e1ac bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x7702c3b0 mmu_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0x7712771a unbind_from_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0x77c6d7dd platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0x77e4d0fe vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x798ff1c6 rtc_set_mmss +EXPORT_SYMBOL_GPL vmlinux 0x7a4c1438 pv_info +EXPORT_SYMBOL_GPL vmlinux 0x7a707e1b vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0x7ae8f9bb inverse_translate +EXPORT_SYMBOL_GPL vmlinux 0x7b0b4551 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x7b1d544d edac_handler_set +EXPORT_SYMBOL_GPL vmlinux 0x7bbc7544 crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0x7be80f47 debugfs_create_u8 +EXPORT_SYMBOL_GPL vmlinux 0x7c7bcf38 register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x7cd551b3 led_trigger_show +EXPORT_SYMBOL_GPL vmlinux 0x7cfc08c4 device_del +EXPORT_SYMBOL_GPL vmlinux 0x7d28f410 firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0x7d36b42d xfrm_audit_state_replay_overflow +EXPORT_SYMBOL_GPL vmlinux 0x7d646fd6 put_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0x7da8d037 marker_probe_register +EXPORT_SYMBOL_GPL vmlinux 0x7dc37d96 device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x7dc5d0b6 crypto_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x7dd3e4bd devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0x7deee94d pci_find_next_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x7df73575 kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0x7e084cb6 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x7e698a51 unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x7e805590 crypto_alloc_instance +EXPORT_SYMBOL_GPL vmlinux 0x7e8b0c0c blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x7ecbd4fc sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0x7f19c836 unlock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x7f9af2f3 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x7fb06fa4 inet_diag_register +EXPORT_SYMBOL_GPL vmlinux 0x7ff10ccf raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x80353106 gpiochip_is_requested +EXPORT_SYMBOL_GPL vmlinux 0x8039d043 selinux_secmark_relabel_packet_permission +EXPORT_SYMBOL_GPL vmlinux 0x8093e65f kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0x80ee55c3 selinux_secmark_refcount_inc +EXPORT_SYMBOL_GPL vmlinux 0x81e634d0 class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0x8226642f __gpio_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x8235efda pci_bus_add_device +EXPORT_SYMBOL_GPL vmlinux 0x826360fd do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x82bb7d1d map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x82cd19f3 register_xenstore_notifier +EXPORT_SYMBOL_GPL vmlinux 0x82d79b51 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x82f5273b register_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0x82f776b7 gpio_export +EXPORT_SYMBOL_GPL vmlinux 0x836faf96 tcp_done +EXPORT_SYMBOL_GPL vmlinux 0x8499b19e crypto_drop_spawn +EXPORT_SYMBOL_GPL vmlinux 0x84b5cd6f tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x84f004d7 led_trigger_remove +EXPORT_SYMBOL_GPL vmlinux 0x852d8010 fib_rules_unregister +EXPORT_SYMBOL_GPL vmlinux 0x85b0539f single_release_net +EXPORT_SYMBOL_GPL vmlinux 0x85c10896 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x85d7edfd hpet_set_periodic_freq +EXPORT_SYMBOL_GPL vmlinux 0x85e5a3db ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x86623fd7 notify_remote_via_irq +EXPORT_SYMBOL_GPL vmlinux 0x868784cb __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x86a51007 gnttab_end_foreign_transfer +EXPORT_SYMBOL_GPL vmlinux 0x86b1667d hwrng_unregister +EXPORT_SYMBOL_GPL vmlinux 0x86d9791b sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x870404b8 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x873fbaea edac_atomic_assert_error +EXPORT_SYMBOL_GPL vmlinux 0x8767b3e0 rtc_read_time +EXPORT_SYMBOL_GPL vmlinux 0x876b550b spi_register_master +EXPORT_SYMBOL_GPL vmlinux 0x87754115 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x879ddbd1 netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0x880b189a __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x8810ad5e crypto_xor +EXPORT_SYMBOL_GPL vmlinux 0x885142a6 nf_net_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x885507b8 platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0x886736fc olpc_platform_info +EXPORT_SYMBOL_GPL vmlinux 0x88999593 queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x88b40bd7 apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0x88e7dcc6 cpuidle_enable_device +EXPORT_SYMBOL_GPL vmlinux 0x89d887ad device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8a47275b sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x8abed13d xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x8ad70c28 blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x8bb09051 rtc_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8bd72ab0 skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0x8c06a108 xenbus_transaction_start +EXPORT_SYMBOL_GPL vmlinux 0x8c38074a unregister_xenstore_notifier +EXPORT_SYMBOL_GPL vmlinux 0x8c73c861 cpuidle_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0x8d5d1bd1 user_update +EXPORT_SYMBOL_GPL vmlinux 0x8dae67be crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0x8dd78d25 blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x8dd7fe52 uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0x8e11ebc4 vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0x8e6d9a0a user_read +EXPORT_SYMBOL_GPL vmlinux 0x8eb58c6e __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0x8f2bdd46 crypto_unregister_alg +EXPORT_SYMBOL_GPL vmlinux 0x8f6cee77 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x8f7dfe7e proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0x8f879dfc rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x8fd5c28c devres_get +EXPORT_SYMBOL_GPL vmlinux 0x8ff8dbcd blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0x9009602a acpi_bus_get_ejd +EXPORT_SYMBOL_GPL vmlinux 0x902909e8 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x902ec68f vlan_dev_vlan_id +EXPORT_SYMBOL_GPL vmlinux 0x906b805e srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x906f3d05 crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0x908fe039 pci_create_slot +EXPORT_SYMBOL_GPL vmlinux 0x90a1004a crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x9146276a device_add +EXPORT_SYMBOL_GPL vmlinux 0x91464a76 led_trigger_unregister_simple +EXPORT_SYMBOL_GPL vmlinux 0x9159b9d6 profile_event_register +EXPORT_SYMBOL_GPL vmlinux 0x9178ea58 rtc_class_open +EXPORT_SYMBOL_GPL vmlinux 0x91c9a0d4 attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0x91dacaa2 acpi_processor_ffh_cstate_probe +EXPORT_SYMBOL_GPL vmlinux 0x9241c3ee device_power_down +EXPORT_SYMBOL_GPL vmlinux 0x92445aee hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x926bcccd driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x9278d704 crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0x9281281e anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0x928706c1 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0x92fb217b dcookie_unregister +EXPORT_SYMBOL_GPL vmlinux 0x933740ca cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x939dbe6f simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0x93d2422d snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x9427af45 register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0x942c1704 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x94951ff6 inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0x94bb45c3 debugfs_remove +EXPORT_SYMBOL_GPL vmlinux 0x952664c5 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x954499b6 register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0x95559aa3 inotify_rm_wd +EXPORT_SYMBOL_GPL vmlinux 0x956a91ba gpio_get_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x9577271c hpet_rtc_interrupt +EXPORT_SYMBOL_GPL vmlinux 0x95e5cc54 blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0x961643d8 kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0x961a8cd3 unlock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x96cbcf31 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x96febb46 relay_subbufs_consumed +EXPORT_SYMBOL_GPL vmlinux 0x97ddbfff dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0x9833bc0c hvc_kick +EXPORT_SYMBOL_GPL vmlinux 0x9939a3db input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0x995d1071 prof_on +EXPORT_SYMBOL_GPL vmlinux 0x99699225 crypto_hash_walk_first +EXPORT_SYMBOL_GPL vmlinux 0x99c2e487 rtc_irq_set_freq +EXPORT_SYMBOL_GPL vmlinux 0x9a11a0fc crypto_attr_alg_name +EXPORT_SYMBOL_GPL vmlinux 0x9a398f5c xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x9a6fe509 rtc_set_time +EXPORT_SYMBOL_GPL vmlinux 0x9a827d2c __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0x9ad311d4 crypto_ahash_type +EXPORT_SYMBOL_GPL vmlinux 0x9b3765c1 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0x9b55ad18 tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x9ba0501e unregister_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x9c0f5818 kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0x9c372fbe preempt_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0x9c696d53 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0x9c6ab991 crypto_tfm_in_queue +EXPORT_SYMBOL_GPL vmlinux 0x9cb8037b xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x9cc3c762 sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0x9d06688b register_xenbus_watch +EXPORT_SYMBOL_GPL vmlinux 0x9d3850e1 gnttab_alloc_grant_references +EXPORT_SYMBOL_GPL vmlinux 0x9d957902 bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0x9dc0e3ed tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x9dcd5ca4 driver_attach +EXPORT_SYMBOL_GPL vmlinux 0x9e711ad2 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x9e7d3442 xenbus_resume +EXPORT_SYMBOL_GPL vmlinux 0x9eae490d device_create +EXPORT_SYMBOL_GPL vmlinux 0x9edd2b61 input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0x9f0fb427 register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x9f2c42fc queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x9fce80db fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x9ffe62a5 class_find_device +EXPORT_SYMBOL_GPL vmlinux 0xa0255440 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0xa089f7f8 bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0xa09d6f3e acpi_bus_trim +EXPORT_SYMBOL_GPL vmlinux 0xa0ea56d1 alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xa1596d98 acpi_processor_ffh_cstate_enter +EXPORT_SYMBOL_GPL vmlinux 0xa1d3746d tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0xa2c03841 bind_evtchn_to_irqhandler +EXPORT_SYMBOL_GPL vmlinux 0xa2e1bb99 register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0xa2e67f08 acpi_bus_generate_proc_event4 +EXPORT_SYMBOL_GPL vmlinux 0xa31a4117 blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0xa353fffc xenbus_rm +EXPORT_SYMBOL_GPL vmlinux 0xa39d98e7 led_trigger_event +EXPORT_SYMBOL_GPL vmlinux 0xa3b48cad macvlan_handle_frame_hook +EXPORT_SYMBOL_GPL vmlinux 0xa3fc96f0 marker_probe_cb_noarg +EXPORT_SYMBOL_GPL vmlinux 0xa452c297 hpet_mask_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa5bf5c3e pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0xa5c36cec inotify_unmount_inodes +EXPORT_SYMBOL_GPL vmlinux 0xa6c6af78 tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0xa7038ad8 pci_find_aer_capability +EXPORT_SYMBOL_GPL vmlinux 0xa7a15c6d mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0xa7e8065e xenbus_unmap_ring +EXPORT_SYMBOL_GPL vmlinux 0xa8ca8718 sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0xa8f59416 gpio_direction_output +EXPORT_SYMBOL_GPL vmlinux 0xa90c0934 kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0xa9126bff hpet_set_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa956a362 register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0xa963f49c tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0xa9686f53 xenbus_map_ring +EXPORT_SYMBOL_GPL vmlinux 0xa993675e elv_register +EXPORT_SYMBOL_GPL vmlinux 0xa9c530b8 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xa9eabac9 platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0xa9fc6d8b spi_busnum_to_master +EXPORT_SYMBOL_GPL vmlinux 0xaa2a72bf __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0xaa8c4696 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0xab01acbe gnttab_request_free_callback +EXPORT_SYMBOL_GPL vmlinux 0xabc28976 force_evtchn_callback +EXPORT_SYMBOL_GPL vmlinux 0xabe950c7 tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0xac0292be blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0xac241063 platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xacc19485 ibft_addr +EXPORT_SYMBOL_GPL vmlinux 0xaccfc678 cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0xad02b701 cpufreq_register_governor +EXPORT_SYMBOL_GPL vmlinux 0xad096363 xenbus_printf +EXPORT_SYMBOL_GPL vmlinux 0xad533f2b cpufreq_cpu_put +EXPORT_SYMBOL_GPL vmlinux 0xae0c87ee pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0xae7c3b8f xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0xaea771da inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0xaeb7f977 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xaed036a3 register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xaef7265c crypto_attr_alg +EXPORT_SYMBOL_GPL vmlinux 0xaf00f091 pci_destroy_slot +EXPORT_SYMBOL_GPL vmlinux 0xaf0c8ffe crypto_unregister_template +EXPORT_SYMBOL_GPL vmlinux 0xaf16ec38 cpuidle_register_driver +EXPORT_SYMBOL_GPL vmlinux 0xaf735e0f sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0xafc23904 pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0xaff907ca debugfs_rename +EXPORT_SYMBOL_GPL vmlinux 0xb021c3d3 devres_add +EXPORT_SYMBOL_GPL vmlinux 0xb07c8d3c crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0xb0ab9f8c flush_work +EXPORT_SYMBOL_GPL vmlinux 0xb0cb6ae1 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0xb10d55bc cn_netlink_send +EXPORT_SYMBOL_GPL vmlinux 0xb120ab95 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0xb1969acf hvc_poll +EXPORT_SYMBOL_GPL vmlinux 0xb1acbcce rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0xb22efdc2 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0xb26db190 bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0xb27005f5 device_suspend +EXPORT_SYMBOL_GPL vmlinux 0xb28c5cad raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0xb305fa4b bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xb313a59e unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0xb3253ed9 hpet_rtc_timer_init +EXPORT_SYMBOL_GPL vmlinux 0xb3d73345 audit_log_untrustedstring +EXPORT_SYMBOL_GPL vmlinux 0xb4c3ea18 bus_register +EXPORT_SYMBOL_GPL vmlinux 0xb4e14553 gnttab_query_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xb4ea7cf7 kgdb_connected +EXPORT_SYMBOL_GPL vmlinux 0xb4eafd4a blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0xb51fbd64 edac_op_state +EXPORT_SYMBOL_GPL vmlinux 0xb53ae573 cpu_idle_wait +EXPORT_SYMBOL_GPL vmlinux 0xb5472d1d sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xb586ed03 xenbus_watch_pathfmt +EXPORT_SYMBOL_GPL vmlinux 0xb58e0b2b unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xb5df81d5 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0xb5ea5a70 xenbus_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0xb6230f1f gnttab_grant_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xb63550f5 __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0xb646b5ea rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0xb65091b3 selinux_secmark_refcount_dec +EXPORT_SYMBOL_GPL vmlinux 0xb6bc49a9 __supported_pte_mask +EXPORT_SYMBOL_GPL vmlinux 0xb75d96a3 relay_buf_full +EXPORT_SYMBOL_GPL vmlinux 0xb7d7c12e hpet_set_alarm_time +EXPORT_SYMBOL_GPL vmlinux 0xb9012d87 sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0xb903674c scatterwalk_map_and_copy +EXPORT_SYMBOL_GPL vmlinux 0xb99d5837 xenbus_read +EXPORT_SYMBOL_GPL vmlinux 0xb9d31c94 relay_reset +EXPORT_SYMBOL_GPL vmlinux 0xb9eb3aa9 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0xba402c15 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0xba4b8bbd rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0xba9b3a6f class_destroy +EXPORT_SYMBOL_GPL vmlinux 0xbb502333 mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0xbb8a6a44 debugfs_create_u16 +EXPORT_SYMBOL_GPL vmlinux 0xbbb50c8b rtc_update_irq +EXPORT_SYMBOL_GPL vmlinux 0xbbb98859 edid_info +EXPORT_SYMBOL_GPL vmlinux 0xbbf5e0e1 fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0xbc08ac35 do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0xbc223517 nf_register_afinfo +EXPORT_SYMBOL_GPL vmlinux 0xbc2eb3a5 power_supply_am_i_supplied +EXPORT_SYMBOL_GPL vmlinux 0xbc7616df inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0xbc771ac5 pci_stop_bus_device +EXPORT_SYMBOL_GPL vmlinux 0xbce5a619 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0xbdcce1b1 register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0xbe4cd677 inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0xbfbfa16c tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0xbfc0e78c pci_find_ext_capability +EXPORT_SYMBOL_GPL vmlinux 0xbfd1996d class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xc00d4fd2 mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0xc06bcadb spi_alloc_device +EXPORT_SYMBOL_GPL vmlinux 0xc097eb8e hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0xc0a6150d tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0xc0ad7da5 copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0xc0ed34aa bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0xc1369437 raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0xc1b9670d leds_list_lock +EXPORT_SYMBOL_GPL vmlinux 0xc211b4cf skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0xc26351f8 bind_evtchn_to_irq +EXPORT_SYMBOL_GPL vmlinux 0xc2f5c042 platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0xc3181ff0 skb_morph +EXPORT_SYMBOL_GPL vmlinux 0xc31be7c8 put_device +EXPORT_SYMBOL_GPL vmlinux 0xc34efe27 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0xc36420ce transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0xc3d1787f audit_log_vformat +EXPORT_SYMBOL_GPL vmlinux 0xc41d0d09 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0xc42f2f94 xenbus_read_driver_state +EXPORT_SYMBOL_GPL vmlinux 0xc42f6e72 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xc5070adf generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0xc5397da6 xenbus_mkdir +EXPORT_SYMBOL_GPL vmlinux 0xc56c45b4 pci_intx +EXPORT_SYMBOL_GPL vmlinux 0xc574fd8a transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0xc5a69565 xenbus_dev_fatal +EXPORT_SYMBOL_GPL vmlinux 0xc63db010 unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0xc6b402e5 __percpu_alloc_mask +EXPORT_SYMBOL_GPL vmlinux 0xc6cabb03 device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xc7762579 inotify_inode_is_dead +EXPORT_SYMBOL_GPL vmlinux 0xc7ec11f6 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xc81d40a6 hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0xc84dec8f cpuidle_register_device +EXPORT_SYMBOL_GPL vmlinux 0xc87c1f84 ktime_get +EXPORT_SYMBOL_GPL vmlinux 0xc87e487a sched_clock_idle_sleep_event +EXPORT_SYMBOL_GPL vmlinux 0xc9561772 fb_destroy_modelist +EXPORT_SYMBOL_GPL vmlinux 0xc9f4fa54 xenbus_free_evtchn +EXPORT_SYMBOL_GPL vmlinux 0xca2c043a rtc_irq_register +EXPORT_SYMBOL_GPL vmlinux 0xca3f5e31 xenbus_switch_state +EXPORT_SYMBOL_GPL vmlinux 0xca5f4668 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0xca81ea9a xenbus_transaction_end +EXPORT_SYMBOL_GPL vmlinux 0xcabe04de cpuidle_resume_and_unlock +EXPORT_SYMBOL_GPL vmlinux 0xcbdbf956 device_rename +EXPORT_SYMBOL_GPL vmlinux 0xcbf02c5a crypto_hash_walk_done +EXPORT_SYMBOL_GPL vmlinux 0xcbf20127 klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0xcc1f1c3d inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0xcd512d3d inotify_find_update_watch +EXPORT_SYMBOL_GPL vmlinux 0xcd9fa7b9 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0xcda7a1d4 __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xcdd6550e register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0xce941826 init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0xceca7420 __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0xcf0bfd12 start_thread +EXPORT_SYMBOL_GPL vmlinux 0xcf47859c inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0xcf5d3b7b pciserial_suspend_ports +EXPORT_SYMBOL_GPL vmlinux 0xcfcc83ad register_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0xd027a07d marker_probe_unregister +EXPORT_SYMBOL_GPL vmlinux 0xd03c7700 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0xd0838b42 inotify_remove_watch_locked +EXPORT_SYMBOL_GPL vmlinux 0xd0c05159 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0xd124e095 pcie_port_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xd12ac59b olpc_ec_cmd +EXPORT_SYMBOL_GPL vmlinux 0xd16712f3 crypto_check_attr_type +EXPORT_SYMBOL_GPL vmlinux 0xd177204e spi_alloc_master +EXPORT_SYMBOL_GPL vmlinux 0xd1aabf25 device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0xd1c0de74 pci_bus_max_busnr +EXPORT_SYMBOL_GPL vmlinux 0xd1c672a1 hwmon_device_register +EXPORT_SYMBOL_GPL vmlinux 0xd1eeba84 dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0xd1f8dee0 bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0xd247ade0 pci_block_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0xd2547f8f find_vpid +EXPORT_SYMBOL_GPL vmlinux 0xd31013f1 debugfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0xd3b78da3 xenbus_suspend_cancel +EXPORT_SYMBOL_GPL vmlinux 0xd4a5c874 xenbus_bind_evtchn +EXPORT_SYMBOL_GPL vmlinux 0xd5143147 bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0xd53b7ffa inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0xd5d2f027 platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0xd76fa3ab relay_open +EXPORT_SYMBOL_GPL vmlinux 0xd7d0159d power_supply_register +EXPORT_SYMBOL_GPL vmlinux 0xd7d70bf5 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0xd7d79132 put_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0xd89f2217 bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0xd9042fa8 scatterwalk_map +EXPORT_SYMBOL_GPL vmlinux 0xd9d39fcb tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0xda27b569 relay_file_operations +EXPORT_SYMBOL_GPL vmlinux 0xdaf4dfb3 fb_mode_option +EXPORT_SYMBOL_GPL vmlinux 0xdb2a1107 get_driver +EXPORT_SYMBOL_GPL vmlinux 0xdba957bb pci_scan_child_bus +EXPORT_SYMBOL_GPL vmlinux 0xdbaf10b1 power_supply_changed +EXPORT_SYMBOL_GPL vmlinux 0xdbeff2e5 alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0xdc046069 driver_find +EXPORT_SYMBOL_GPL vmlinux 0xdcba7b09 inotify_find_watch +EXPORT_SYMBOL_GPL vmlinux 0xdce1a9d5 __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0xdd5c4942 srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0xdda1ef34 skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0xddba2a95 pci_find_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0xdea4bfdd debugfs_create_u64 +EXPORT_SYMBOL_GPL vmlinux 0xdf3c19ec cn_add_callback +EXPORT_SYMBOL_GPL vmlinux 0xdf5fd4c5 inet6_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0xdf936f4d platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0xdfce25b4 seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0xdfd82f8d k_handler +EXPORT_SYMBOL_GPL vmlinux 0xe0406b5a blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xe17a0741 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0xe191bb16 vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0xe28a61c7 xenbus_map_ring_valloc +EXPORT_SYMBOL_GPL vmlinux 0xe295c0ff is_hpet_enabled +EXPORT_SYMBOL_GPL vmlinux 0xe2e73e68 sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0xe3039085 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0xe31dd69a crypto_dequeue_request +EXPORT_SYMBOL_GPL vmlinux 0xe3687db4 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0xe373f8b9 relay_switch_subbuf +EXPORT_SYMBOL_GPL vmlinux 0xe40b876f cpufreq_unregister_governor +EXPORT_SYMBOL_GPL vmlinux 0xe4c331b6 acpi_os_unmap_memory +EXPORT_SYMBOL_GPL vmlinux 0xe513afc0 cache_k8_northbridges +EXPORT_SYMBOL_GPL vmlinux 0xe530071c pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0xe5feb9fb sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0xe61a6d2f gpio_unexport +EXPORT_SYMBOL_GPL vmlinux 0xe6241888 spi_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xe6488b47 cpufreq_notify_transition +EXPORT_SYMBOL_GPL vmlinux 0xe674a5cb srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0xe6fca095 proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0xe7344f6b rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0xe786a7cd get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0xe79672f0 crypto_enqueue_request +EXPORT_SYMBOL_GPL vmlinux 0xe7fa47ad srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0xe892c370 rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0xe892ddea __trace_note_message +EXPORT_SYMBOL_GPL vmlinux 0xe8bb067a put_driver +EXPORT_SYMBOL_GPL vmlinux 0xe8e0d379 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0xe93e49c3 devres_free +EXPORT_SYMBOL_GPL vmlinux 0xe9df60aa devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0xea065e01 task_handoff_unregister +EXPORT_SYMBOL_GPL vmlinux 0xea0d8fab led_trigger_register_simple +EXPORT_SYMBOL_GPL vmlinux 0xea30b37b uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0xea893117 __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0xeb8f624c debugfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0xebd1c556 free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xec0dc814 rtc_device_register +EXPORT_SYMBOL_GPL vmlinux 0xece6ae04 relay_close +EXPORT_SYMBOL_GPL vmlinux 0xed188f32 inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0xed72c1d0 transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0xedbc6f67 gnttab_end_foreign_access +EXPORT_SYMBOL_GPL vmlinux 0xede1c668 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0xede65e13 transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0xee784f3c __mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0xef2dc7b9 power_supply_class +EXPORT_SYMBOL_GPL vmlinux 0xefbd4974 xenbus_grant_ring +EXPORT_SYMBOL_GPL vmlinux 0xefe21106 snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0xf02172e3 set_cpus_allowed_ptr +EXPORT_SYMBOL_GPL vmlinux 0xf086097a fb_deferred_io_fsync +EXPORT_SYMBOL_GPL vmlinux 0xf1676b41 user_describe +EXPORT_SYMBOL_GPL vmlinux 0xf184d189 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0xf18fa97a register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0xf26bb8b1 tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0xf2fca922 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0xf43529e1 __cpufreq_driver_getavg +EXPORT_SYMBOL_GPL vmlinux 0xf4683b6e fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0xf4841f48 led_trigger_unregister +EXPORT_SYMBOL_GPL vmlinux 0xf499fdb2 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0xf4aebdc3 xenbus_suspend +EXPORT_SYMBOL_GPL vmlinux 0xf515f983 debugfs_create_u32 +EXPORT_SYMBOL_GPL vmlinux 0xf553318d cpuidle_pause_and_lock +EXPORT_SYMBOL_GPL vmlinux 0xf584f26d kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0xf5945bac gnttab_free_grant_references +EXPORT_SYMBOL_GPL vmlinux 0xf5a691cd invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0xf5bcc731 uhci_check_and_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0xf63b757c driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xf688d31f cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0xf6bcbd73 hwrng_register +EXPORT_SYMBOL_GPL vmlinux 0xf7016530 xenbus_gather +EXPORT_SYMBOL_GPL vmlinux 0xf76ed109 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0xf779cc02 cpuidle_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0xf77c41f5 get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0xf7c4fb67 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0xf82f16b3 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0xf8802492 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0xf9238304 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0xf97c4aae klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0xf9a054b5 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0xfa1f4662 scatterwalk_start +EXPORT_SYMBOL_GPL vmlinux 0xfaac139b queue_work +EXPORT_SYMBOL_GPL vmlinux 0xfb05779a rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0xfb2a3293 math_state_restore +EXPORT_SYMBOL_GPL vmlinux 0xfbf9be5d register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xfcfc4b4d tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0xfd29a86a ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0xfd3930d7 unregister_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0xfd475650 crypto_lookup_template +EXPORT_SYMBOL_GPL vmlinux 0xfd51b281 gnttab_end_foreign_access_ref +EXPORT_SYMBOL_GPL vmlinux 0xfda74e28 user_destroy +EXPORT_SYMBOL_GPL vmlinux 0xfde0b92c crypto_larval_error +EXPORT_SYMBOL_GPL vmlinux 0xfdf1c041 per_cpu__gdt_page +EXPORT_SYMBOL_GPL vmlinux 0xfe0cd248 sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0xfe727411 get_phys_to_machine +EXPORT_SYMBOL_GPL vmlinux 0xfe990052 gpio_free +EXPORT_SYMBOL_GPL vmlinux 0xfecbff96 __mark_empty_function +EXPORT_SYMBOL_GPL vmlinux 0xff5a8cfe cn_del_callback +EXPORT_SYMBOL_GPL vmlinux 0xff7c4381 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0xff91b442 rtc_irq_unregister +EXPORT_UNUSED_SYMBOL vmlinux 0x00000000 init_mm --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/i386/server.modules +++ linux-2.6.27/debian/abi/2.6.27-8.17/i386/server.modules @@ -0,0 +1,2288 @@ +3c359 +3c501 +3c503 +3c505 +3c507 +3c509 +3c515 +3c523 +3c527 +3c574_cs +3c589_cs +3c59x +3w-9xxx +3w-xxxx +53c700 +6pack +8021q +8139cp +8139too +8250_accent +8250_boca +8250_exar_st16c554 +8250_fourport +8250_hub6 +8250_mca +82596 +8390 +8390p +9p +9pnet +9pnet_virtio +a100u2w +a3d +aacraid +abituguru +abituguru3 +abyss +ac +ac3200 +ac97_bus +acecad +acenic +acerhk +acer-wmi +acpi-cpufreq +acpiphp +acpiphp_ibm +acquirewdt +act2000 +act200l-sir +act_gact +act_ipt +actisys-sir +act_mirred +act_nat +act_pedit +act_police +act_simple +acx +ad1848 +ad7414 +ad7418 +adcxx +adfs +adi +adm1021 +adm1025 +adm1026 +adm1029 +adm1031 +adm8211 +adm9240 +ads7828 +ads7846 +adt7470 +adt7473 +adutux +adv7170 +adv7175 +advansys +advantechwdt +aead +aedsp16 +aes_generic +aes-i586 +affs +af_key +af_packet +af-rxrpc +agpgart +ah4 +ah6 +aha152x +aha152x_cs +aha1542 +aha1740 +ahci +aic79xx +aic7xxx +aic94xx +aiptek +aircable +airo +airo_cs +alauda +ali-agp +ali-ircc +alim1535_wdt +alim7101_wdt +ambassador +amd64-agp +amd76x_edac +amd76xrom +amd8111e +amd-k7-agp +amd-rng +analog +anubis +aoe +apm +appledisplay +appleir +applesmc +appletalk +appletouch +applicom +ar7part +arc4 +arcfb +arcmsr +arcnet +arc-rawmode +arc-rimi +ark3116 +arkfb +arlan +arptable_filter +arp_tables +arpt_mangle +asb100 +asix +asus-laptop +async_memcpy +async_tx +async_xor +at1700 +at24 +at25 +at76_usb +ata_generic +ata_piix +aten +ath9k +ati-agp +ati_remote +ati_remote2 +atl1 +atl1e +atl2 +atlas_btns +atmel +atmel_cs +atmel_pci +atmtcp +atp +atp870u +atxp1 +aty128fb +atyfb +au0828 +au8522 +aufs +authenc +auth_rpcgss +autofs +autofs4 +av5100 +avma1_cs +avm_cs +ax25 +axnet_cs +b1 +b1dma +b1isa +b1pci +b1pcmcia +b2c2-flexcop +b2c2-flexcop-pci +b2c2-flexcop-usb +b43 +b43legacy +b44 +bas_gigaset +battery +bay +baycom_epp +baycom_par +baycom_ser_fdx +baycom_ser_hdx +bcm203x +bcm3510 +bcm5974 +befs +belkin_sa +berry_charge +bfs +bfusb +binfmt_aout +binfmt_misc +bitblit +block2mtd +blowfish +bluecard_cs +bluetooth +bnep +bnx2 +bnx2x +bonding +bpa10x +bpck +bpck6 +bpqether +br2684 +bridge +broadcom +bsd_comp +bt3c_cs +bt819 +bt856 +bt878 +btcx-risc +btsdio +bttv +btuart_cs +btusb +budget +budget-av +budget-ci +budget-core +budget-patch +BusLogic +button +bw-qcam +c101 +c4 +c67x00 +cafe_ccic +cafe_nand +camellia +capi +capidrv +capifs +capmode +carminefb +cassini +cast5 +cast6 +catc +cbc +cciss +ccm +cdc-acm +cdc_ether +cdc_subset +cdc-wdm +cdrom +cfag12864b +cfag12864bfb +cfg80211 +cfi_cmdset_0001 +cfi_cmdset_0002 +cfi_cmdset_0020 +cfi_probe +cfi_util +ch +ch341 +chipreg +cicada +cifs +cinergyT2 +cirrusfb +ck804xrom +cls_basic +cls_fw +cls_route +cls_rsvp +cls_rsvp6 +cls_tcindex +cls_u32 +cm4000_cs +cm4040_cs +cmtp +cobra +coda +com20020 +com20020_cs +com20020-isa +com20020-pci +com90io +com90xx +comm +commandir +compal-laptop +compat_ioctl32 +compcache +configfs +container +coretemp +corgi_bl +cosa +cp2101 +cpcihp_generic +cpcihp_zt5550 +cpia +cpia2 +cpia_pp +cpia_usb +cpqarray +cpqphp +cpu5wdt +cpufreq_conservative +cpufreq-nforce2 +cpufreq_ondemand +cpufreq_powersave +cpufreq_stats +cpufreq_userspace +cpuid +c-qcam +cr_bllcd +crc16 +crc32c +crc7 +crc-ccitt +crc-itu-t +crc-t10dif +crvml +cryptd +crypto_blkcipher +cryptoloop +crypto_null +cs5345 +cs53l32a +cs5535_gpio +cs553x_nand +cs89x0 +ct82c710 +ctr +cts +cx18 +cx22700 +cx22702 +cx2341x +cx23885 +cx24110 +cx24123 +cx25840 +cx8800 +cx8802 +cx88-alsa +cx88-blackbird +cx88-dvb +cx88-vp3054-i2c +cx88xx +cxacru +cxgb +cxgb3 +cyber2000fb +cyberjack +cyblafb +cyclades +cyclomx +cycx_drv +cypress_cy7c63 +cypress_m8 +cytherm +DAC960 +davicom +db9 +dc395x +dccp +dccp_ccid2 +dccp_ccid3 +dccp_diag +dccp_ipv4 +dccp_ipv6 +dccp_probe +dccp_tfrc_lib +dcdbas +de2104x +de4x5 +de600 +de620 +decnet +deflate +defxx +dell_rbu +depca +des_generic +dib0070 +dib3000mb +dib3000mc +dib7000m +dib7000p +dibx000_common +digi_acceleport +dilnetpc +diskonchip +display +divacapi +divadidd +diva_idi +diva_mnt +divas +dlci +dlm +dm9601 +dm-bbr +dm-crypt +dme1737 +dmfe +dm-log +dm-loop +dm-mem-cache +dm-message +dm-mirror +dm-mod +dm-multipath +dm-raid4-5 +dm-region_hash +dm-round-robin +dm-snapshot +dmx3191d +dm-zero +dn_rtmsg +doc2000 +doc2001 +doc2001plus +docecc +dock +docprobe +donauboe +dpc7146 +dpt_i2o +drbd +drm +drx397xD +ds1621 +ds1682 +ds2482 +ds2490 +ds2760_battery +dsbr100 +dscc4 +dss1_divert +dst +dst_ca +dstr +dtc +dtl1_cs +dtlk +dummy +dv1394 +dvb-bt8xx +dvb-core +dvb-pll +dvb-ttpci +dvb-ttusb-budget +dvb-usb +dvb-usb-a800 +dvb-usb-af9005 +dvb-usb-af9005-remote +dvb-usb-anysee +dvb-usb-au6610 +dvb-usb-cxusb +dvb-usb-dib0700 +dvb-usb-dibusb-common +dvb-usb-dibusb-mb +dvb-usb-dibusb-mc +dvb-usb-digitv +dvb-usb-dtt200u +dvb-usb-dw2102 +dvb-usb-gl861 +dvb-usb-gp8psk +dvb-usb-m920x +dvb-usb-nova-t-usb2 +dvb-usb-opera +dvb-usb-ttusb2 +dvb-usb-umt-010 +dvb-usb-vp702x +dvb-usb-vp7045 +e100 +e1000 +e1000e +e2100 +e752x_edac +e7xxx_edac +eata +ebt_802_3 +ebtable_broute +ebtable_filter +ebtable_nat +ebtables +ebt_among +ebt_arp +ebt_arpreply +ebt_dnat +ebt_ip +ebt_ip6 +ebt_limit +ebt_log +ebt_mark +ebt_mark_m +ebt_nflog +ebt_pkttype +ebt_redirect +ebt_snat +ebt_stp +ebt_ulog +ebt_vlan +ecb +econet +ecryptfs +edac_core +eeepc-laptop +eepro +eepro100 +eeprom +eeprom_93cx6 +eexpress +efficeon-agp +efs +ehci-hcd +elo +elsa_cs +em28xx +em28xx-alsa +em28xx-dvb +em_cmp +emi26 +emi62 +em_meta +em_nbyte +empeg +em_text +emu10k1-gp +em_u32 +enclosure +eni +epat +epca +epia +epic100 +eql +es3210 +esb2rom +esi-sir +esp +esp4 +esp6 +et131x +et61x251 +eth1394 +eth16i +eurotechwdt +evbug +evdev +ewrk3 +exportfs +ext2 +ext3 +ext4dev +f71805f +f71882fg +f75375s +fakephp +fan +farsync +fat +faulty +fbcon +fb_ddc +fb_sys_fops +fcrypt +fd_mcs +fdomain +fdomain_cs +fealnx +ff-memless +firestream +fit2 +fit3 +floppy +fm801-gp +fmvj18x_cs +font +forcedeth +fore_200e +freevxfs +freq_table +friq +frpw +fsam7400 +fscher +fschmd +fscpos +ftdi-elan +ftdi_sio +ftl +fujitsu-laptop +fujitsu_ts +funsoft +fuse +g450_pll +gadgetfs +gamecon +gameport +garmin_gps +garp +g_cdc +gcm +gdth +generic_serial +gen_probe +geode-aes +geode-rng +g_ether +gf128mul +gf2k +g_file_storage +gfs +gfs2 +gigaset +girbil-sir +gl518sm +gl520sm +gl620a +gnbd +g_NCR5380 +g_NCR5380_mmio +gpio_keys +gpio_mouse +grip +grip_mp +g_serial +gspca_conex +gspca_etoms +gspca_main +gspca_mars +gspca_ov519 +gspca_pac207 +gspca_pac7311 +gspca_sonixb +gspca_sonixj +gspca_spca500 +gspca_spca501 +gspca_spca505 +gspca_spca506 +gspca_spca508 +gspca_spca561 +gspca_stk014 +gspca_sunplus +gspca_t613 +gspca_tv8532 +gspca_vc032x +gspca_zc3xx +gtco +guillemot +gunze +gx1fb +gxfb +gx-suspmod +g_zero +hamachi +hangcheck-timer +hci_uart +hci_vhci +hdaps +hdlc +hdlc_cisco +hdlcdrv +hdlc_fr +hdlc_ppp +hdlc_raw +hdlc_raw_eth +hdlc_x25 +he +heci +hecubafb +hermes +hexium_gemini +hexium_orion +hfc4s8s_l1 +hfcmulti +hfcpci +hfc_usb +hfs +hfsplus +hgafb +hid +hidp +hifn_795x +hisax +hisax_fcpcipnp +hisax_isac +hisax_st5481 +horizon +hostap +hostap_cs +hostap_pci +hostap_plx +hostess_sv11 +hp +hp100 +hp4x +hpfs +hpilo +hp-plus +hptiop +hp-wmi +hso +htc-pasic3 +htcpen +hwmon-vid +hysdn +i2c-algo-bit +i2c-algo-pca +i2c-algo-pcf +i2c-ali1535 +i2c-ali1563 +i2c-ali15x3 +i2c-amd756 +i2c-amd756-s4882 +i2c-amd8111 +i2c-core +i2c-dev +i2c-gpio +i2c-i801 +i2c-isch +i2c-matroxfb +i2c-nforce2 +i2c-nforce2-s4985 +i2c-ocores +i2c-parport +i2c-parport-light +i2c-pca-isa +i2c-pca-platform +i2c-piix4 +i2c-simtec +i2c-sis5595 +i2c-sis630 +i2c-sis96x +i2c-stub +i2c-taos-evm +i2c-tiny-usb +i2c-via +i2c-viapro +i2c-voodoo3 +i2o_block +i2o_bus +i2o_config +i2o_core +i2o_proc +i2o_scsi +i3000_edac +i5000_edac +i5100_edac +i5k_amb +i6300esb +i810 +i810fb +i82092 +i82365 +i82860_edac +i82875p_edac +i82975x_edac +i830 +i8k +i915 +ib700wdt +ib_addr +ib_cm +ib_core +ib_ipoib +ib_iser +ib_mad +ibmaem +ibmasm +ibmasr +ibmcam +ibmlana +ibmmca +ibmpex +ibmphp +ib_mthca +ibmtr +ibmtr_cs +ib_sa +ib_srp +ib_ucm +ib_umad +ib_uverbs +ichxrom +icn +icplus +idmouse +idt77252 +ieee1394 +ieee80211 +ieee80211_crypt +ieee80211_crypt_ccmp +ieee80211_crypt_tkip +ieee80211_crypt_wep +ifb +iforce +igb +ili9320 +imm +in2000 +inet_lro +inexio +inftl +initio +inport +input-polldev +intel-agp +intelfb +intel_menlow +intel-rng +intel_vr_nor +interact +ioc4 +io_edgeport +io_ti +iowarrior +ip2 +ip6_queue +ip6table_filter +ip6table_mangle +ip6table_raw +ip6_tables +ip6table_security +ip6t_ah +ip6t_eui64 +ip6t_frag +ip6t_hbh +ip6t_hl +ip6t_HL +ip6t_ipv6header +ip6t_LOG +ip6t_mh +ip6t_REJECT +ip6t_rt +ip6_tunnel +ipaq +ipcomp +ipcomp6 +ipddp +ipg +ip_gre +iphase +ipip +ipmi_devintf +ipmi_msghandler +ipmi_poweroff +ipmi_si +ipmi_watchdog +ip_queue +ipr +ips +iptable_filter +iptable_mangle +iptable_nat +iptable_raw +ip_tables +iptable_security +ipt_addrtype +ipt_ah +ipt_CLUSTERIP +ipt_ecn +ipt_ECN +ipt_LOG +ipt_MASQUERADE +ipt_NETMAP +ipt_recent +ipt_REDIRECT +ipt_REJECT +ipt_ttl +ipt_TTL +ipt_ULOG +ipv6 +ip_vs +ip_vs_dh +ip_vs_ftp +ip_vs_lblc +ip_vs_lblcr +ip_vs_lc +ip_vs_nq +ip_vs_rr +ip_vs_sed +ip_vs_sh +ip_vs_wlc +ip_vs_wrr +ipw +ipw2100 +ipw2200 +ipwireless +ipx +ircomm +ir-common +ircomm-tty +irda +irda-usb +ir-kbd-i2c +irlan +irnet +irtty-sir +iscsi_ibft +iscsi_tcp +iscsi_trgt +isdn +isdn_bsdcomp +isdnhdlc +isight_firmware +isl6405 +isl6421 +isofs +isp116x-hcd +isp1760 +it87 +it8712f_wdt +iTCO_vendor_support +iTCO_wdt +itd1000 +ivtv +ivtvfb +iw_c2 +iw_cm +iw_cxgb3 +iwl3945 +iwlagn +iwlcore +ixgb +ixgbe +ixj +ixj_pcmcia +jbd +jbd2 +jedec_probe +jffs2 +jfs +joydev +joydump +jsm +k8temp +kafs +kahlua +kaweth +kbic +kbtab +kernelcapi +keyspan +keyspan_pda +keyspan_remote +khazad +kingsun-sir +kl5kusb105 +kobil_sct +konicawc +ks0108 +ks0127 +ks959-sir +ksdazzle-sir +ktti +kvm +kvm-amd +kvm-intel +kyrofb +l1oip +l2cap +l440gx +l64781 +lanai +lance +lanstreamer +lapb +lapbether +lcd +ldusb +lec +led-class +leds-gpio +leds-net48xx +leds-pca9532 +leds-pca955x +leds-wrap +ledtrig-default-on +ledtrig-heartbeat +ledtrig-timer +legousbtower +lgdt330x +libata +libcrc32c +libertas +libertas_cs +libertas_sdio +libiscsi +libphy +libsas +libsrp +libusual +lightning +linear +lirc_atiusb +lirc_bt829 +lirc_cmdir +lirc_dev +lirc_i2c +lirc_igorplugusb +lirc_imon +lirc_it87 +lirc_mceusb +lirc_mceusb2 +lirc_pvr150 +lirc_sasem +lirc_serial +lirc_serial_igor +lirc_sir +lirc_streamzap +lirc_ttusbir +litelink-sir +lkkbd +llc2 +lm63 +lm70 +lm75 +lm77 +lm78 +lm80 +lm83 +lm85 +lm87 +lm90 +lm92 +lm93 +lmc +lmpcm_usb +lnbp21 +lne390 +lockd +lock_dlm +logibm +longhaul +longrun +loop +lp +lp486e +lpfc +lrw +ltpc +ltv350qv +lxfb +lxt +lzo +lzo_compress +lzo_decompress +m25p80 +m52790 +ma600-sir +mac80211 +machzwd +macmodes +macvlan +madgemc +magellan +map_absent +map_funcs +map_ram +map_rom +marvell +matroxfb_accel +matroxfb_base +matroxfb_crtc2 +matroxfb_DAC1064 +matroxfb_g450 +matroxfb_maven +matroxfb_misc +matroxfb_Ti3026 +matrox_w1 +max1619 +max6650 +max6875 +max7301 +max732x +mbcache +mbp_nvidia_bl +mcp2120-sir +mcp23s08 +mcs7780 +mcs7830 +mct_u232 +md4 +mdacon +mdc800 +mdio-bitbang +md-mod +megaraid +megaraid_mbox +megaraid_mm +megaraid_sas +meye +mga +michael_mic +microcode +microtek +mii +minix +mISDN_core +mISDN_dsp +mixcomwd +mk712 +mkiss +mlx4_core +mlx4_ib +mmc_block +mmc_core +mos7720 +mos7840 +moto_modem +moxa +mpoa +mptbase +mptctl +mptfc +mptlan +mptsas +mptscsih +mptspi +mpu401 +msdos +msi-laptop +msnd +msnd_classic +msnd_pinnacle +msp3400 +msr +mt2060 +mt20xx +mt2131 +mt2266 +mt312 +mt352 +mt9m001 +mt9v022 +mtd +mtd_blkdevs +mtdblock +mtdblock_ro +mtdchar +mtdconcat +mtd_dataflash +mtdoops +mtdram +mtouch +multipath +mwave +mxb +mxl5005s +mxl5007t +mxser +myri10ge +n2 +nand +nand_ecc +nand_ids +nandsim +natsemi +navman +nbd +ncpfs +NCR53c406a +NCR_D700 +NCR_Q720_mod +ndiswrapper +ne +ne2 +ne2k-pci +ne3210 +neofb +net1080 +net2280 +netconsole +netrom +netsc520 +nettel +netwave_cs +netxen_nic +newtonkbd +nf_conntrack +nf_conntrack_amanda +nf_conntrack_ftp +nf_conntrack_h323 +nf_conntrack_ipv4 +nf_conntrack_ipv6 +nf_conntrack_irc +nf_conntrack_netbios_ns +nf_conntrack_netlink +nf_conntrack_pptp +nf_conntrack_proto_gre +nf_conntrack_proto_sctp +nf_conntrack_proto_udplite +nf_conntrack_sip +nf_conntrack_tftp +nf_nat +nf_nat_amanda +nf_nat_ftp +nf_nat_h323 +nf_nat_irc +nf_nat_pptp +nf_nat_proto_gre +nf_nat_proto_sctp +nf_nat_proto_udplite +nf_nat_sip +nf_nat_snmp_basic +nf_nat_tftp +nfnetlink +nfnetlink_log +nfnetlink_queue +nfs +nfs_acl +nfsd +nftl +n_hdlc +ni52 +ni65 +nicstar +niu +nls_ascii +nls_cp1250 +nls_cp1251 +nls_cp1255 +nls_cp437 +nls_cp737 +nls_cp775 +nls_cp850 +nls_cp852 +nls_cp855 +nls_cp857 +nls_cp860 +nls_cp861 +nls_cp862 +nls_cp863 +nls_cp864 +nls_cp865 +nls_cp866 +nls_cp869 +nls_cp874 +nls_cp932 +nls_cp936 +nls_cp949 +nls_cp950 +nls_euc-jp +nls_iso8859-1 +nls_iso8859-13 +nls_iso8859-14 +nls_iso8859-15 +nls_iso8859-2 +nls_iso8859-3 +nls_iso8859-4 +nls_iso8859-5 +nls_iso8859-6 +nls_iso8859-7 +nls_iso8859-9 +nls_koi8-r +nls_koi8-ru +nls_koi8-u +nls_utf8 +nmclan_cs +nozomi +n_r3964 +ns558 +ns83820 +nsc_gpio +nsc-ircc +nsp32 +nsp_cs +ntfs +nvidia-agp +nvidiafb +nvram +nxt200x +nxt6000 +ocfs2 +ocfs2_dlm +ocfs2_dlmfs +ocfs2_nodemanager +ocfs2_stackglue +ocfs2_stack_o2cb +ocfs2_stack_user +ohci1394 +ohci-hcd +old_belkin-sir +olpc_battery +olympic +omfs +omninet +on20 +on26 +onenand +onenand_sim +opl3 +oprofile +option +or51132 +or51211 +orinoco +orinoco_cs +orinoco_nortel +orinoco_pci +orinoco_plx +orinoco_tmd +osst +oti6858 +output +ov511 +ov511_decomp +ov518_decomp +ov7670 +ovcamchip +p4-clockmod +p54common +p54pci +p54usb +p80211 +p8023 +padlock-aes +padlock-sha +paride +parkbd +parport +parport_ax88796 +parport_cs +parport_pc +parport_serial +pas16 +pas2 +pata_acpi +pata_ali +pata_amd +pata_artop +pata_atiixp +pata_cmd64x +pata_cs5520 +pata_cs5530 +pata_cs5535 +pata_cs5536 +pata_efar +pata_hpt366 +pata_hpt37x +pata_hpt3x3 +pata_it8213 +pata_it821x +pata_jmicron +pata_legacy +pata_marvell +pata_mpiix +pata_netcell +pata_ninja32 +pata_ns87410 +pata_ns87415 +pata_oldpiix +pata_pcmcia +pata_pdc2027x +pata_pdc202xx_old +pata_qdi +pata_rz1000 +pata_sch +pata_serverworks +pata_sil680 +pata_sis +pata_sl82c105 +pata_triflex +pata_via +pata_winbond +pbe5 +pc110pad +pc300 +pc87360 +pc8736x_gpio +pc87413_wdt +pc87427 +pca953x +pcbc +pcbit +pcd +pcf857x +pcf8591 +pci +pci200syn +pciehp +pci_hotplug +pcilynx +pcips2 +pci_slot +pcmcia +pcmcia_core +pcnet32 +pcnet_cs +pcspkr +pcwd +pcwd_pci +pcwd_usb +pd +pd6729 +pda_power +pdc_adma +pegasus +penmount +pf +pg +phantom +phidget +phidgetkit +phidgetmotorcontrol +phidgetservo +phonedev +phram +physmap +pktcdvd +pktgen +pl2303 +platform_lcd +plat_nand +plat-ram +plip +plusb +pluto2 +pm2fb +pm3fb +pmc551 +pms +powermate +powernow-k6 +powernow-k7 +powernow-k8 +ppa +ppdev +ppp_async +ppp_deflate +ppp_generic +ppp_mppe +pppoatm +pppoe +pppol2tp +pppox +ppp_synctty +prism2_usb +prism54 +processor +progear_bl +proteon +psmouse +pss +pt +pvrusb2 +pwc +qla1280 +qla2xxx +qla3xxx +qla4xxx +qlogic_cs +qlogicfas +qlogicfas408 +qnx4 +qsemi +qt1010 +quickcam +quickcam_messenger +quota_v1 +quota_v2 +r128 +r8169 +r82600_edac +r8a66597-hcd +radeon +radeonfb +radio-aimslab +radio-aztech +radio-cadet +radio-gemtek +radio-gemtek-pci +radio-maestro +radio-maxiradio +radio-rtrack2 +radio-sf16fmi +radio-sf16fmr2 +radio-si470x +radio-terratec +radio-trust +radio-typhoon +radio-zoltrix +raid0 +raid1 +raid10 +raid456 +raid_class +raw +raw1394 +ray_cs +rdma_cm +rdma_ucm +redboot +reed_solomon +reiserfs +rfc1051 +rfc1201 +rfcomm +rfd_ftl +rfkill +rfkill-input +ricoh_mmc +rio +rio500 +riscom8 +rivafb +rmd128 +rmd160 +rmd256 +rmd320 +rndis_host +rndis_wlan +rocket +romfs +rose +rpcsec_gss_krb5 +rpcsec_gss_spkm3 +rrunner +rsrc_nonstatic +rt2400pci +rt2500pci +rt2500usb +rt2x00lib +rt2x00pci +rt2x00usb +rt61pci +rt73usb +rtc-ds1305 +rtc-ds1307 +rtc-ds1374 +rtc-ds1553 +rtc-ds1672 +rtc-ds1742 +rtc-fm3130 +rtc-isl1208 +rtc-m41t80 +rtc-m41t94 +rtc-m48t59 +rtc-m48t86 +rtc-max6900 +rtc-max6902 +rtc-pcf8563 +rtc-pcf8583 +rtc-rs5c348 +rtc-rs5c372 +rtc-stk17ta8 +rtc-test +rtc-v3020 +rtc-x1205 +rtl8150 +rtl8180 +rtl8187 +rxkad +s1d13xxxfb +s2255drv +s2io +s3fb +s5h1409 +s5h1411 +s5h1420 +saa5246a +saa5249 +saa6588 +saa6752hs +saa7110 +saa7111 +saa7114 +saa7115 +saa7127 +saa7134 +saa7134-alsa +saa7134-dvb +saa7134-empress +saa7146 +saa7146_vv +saa717x +saa7185 +safe_serial +salsa20_generic +salsa20-i586 +sata_inic162x +sata_mv +sata_nv +sata_promise +sata_qstor +sata_sil +sata_sil24 +sata_sis +sata_svw +sata_sx4 +sata_uli +sata_via +sata_vsc +savage +savagefb +sb +sb1000 +sbc60xxwdt +sbc7240_wdt +sbc8360 +sbc_epx_c3 +sbc_gxx +sb_lib +sbni +sbp2 +sbs +sbshc +sc +sc1200wdt +sc520cdp +sc520_wdt +sc92031 +scb2_flash +scc +sch_atm +sch_cbq +sch_dsmark +sch_gred +sch_hfsc +sch_htb +sch_ingress +sch_netem +sch_prio +sch_red +sch_sfq +sch_tbf +sch_teql +sco +scsi_debug +scsi_dh +scsi_dh_alua +scsi_dh_emc +scsi_dh_hp_sw +scsi_dh_rdac +scsi_mod +scsi_tgt +scsi_transport_fc +scsi_transport_iscsi +scsi_transport_sas +scsi_transport_spi +scsi_transport_srp +scsi_wait_scan +sctp +scx200 +scx200_acb +scx200_docflash +scx200_gpio +scx200_hrt +scx200_i2c +scx200_wdt +sdhci +sdhci-pci +sdio_uart +sdla +sd_mod +sdricoh_cs +se401 +sealevel +sedlbauer_cs +seed +seeq8005 +seqiv +ser_gigaset +serial_cs +serio_raw +sermouse +serpent +serport +ses +sfc +sg +sha1_generic +sha256_generic +sha512_generic +sh_mobile_ceu_camera +shpchp +sidewinder +sierra +sim710 +sir-dev +sis +sis190 +sis5595 +sis900 +sis-agp +sisfb +sisusbvga +sit +skfp +skge +skisa +sky2 +sl811_cs +sl811-hcd +slhc +slip +slram +sm501 +sm501fb +smbfs +smc9194 +smc91c92_cs +smc-mca +smctr +smc-ultra +smc-ultra32 +sms1xxx +smsc +smsc37b787_wdt +smsc47b397 +smsc47m1 +smsc47m192 +smsc-ircc2 +sn9c102 +snd +snd-ac97-codec +snd-ad1816a +snd-ad1848 +snd-ad1848-lib +snd-ad1889 +snd-adlib +snd-ak4114 +snd-ak4117 +snd-ak4xxx-adda +snd-ali5451 +snd-als100 +snd-als300 +snd-als4000 +snd-atiixp +snd-atiixp-modem +snd-au8810 +snd-au8820 +snd-au8830 +snd-aw2 +snd-azt2320 +snd-azt3328 +snd-bt87x +snd-bt-sco +snd-ca0106 +snd-cmi8330 +snd-cmipci +snd-cs4231 +snd-cs4231-lib +snd-cs4232 +snd-cs4236 +snd-cs4236-lib +snd-cs4281 +snd-cs46xx +snd-cs5530 +snd-cs5535audio +snd-cs8427 +snd-darla20 +snd-darla24 +snd-dt019x +snd-dummy +snd-echo3g +snd-emu10k1 +snd-emu10k1-synth +snd-emu10k1x +snd-emu8000-synth +snd-emux-synth +snd-ens1370 +snd-ens1371 +snd-es1688 +snd-es1688-lib +snd-es18xx +snd-es1938 +snd-es1968 +snd-es968 +snd-fm801 +snd-gina20 +snd-gina24 +snd-gusclassic +snd-gusextreme +snd-gus-lib +snd-gusmax +snd-hda-intel +snd-hdsp +snd-hdspm +snd-hifier +snd-hwdep +snd-i2c +snd-ice1712 +snd-ice1724 +snd-ice17xx-ak4xxx +snd-indigo +snd-indigodj +snd-indigoio +snd-intel8x0 +snd-intel8x0m +snd-interwave +snd-interwave-stb +snd-korg1212 +snd-layla20 +snd-layla24 +snd-maestro3 +snd-mia +snd-miro +snd-mixart +snd-mixer-oss +snd-mona +snd-mpu401 +snd-mpu401-uart +snd-mtpav +snd-mts64 +snd-nm256 +snd-opl3-lib +snd-opl3sa2 +snd-opl3-synth +snd-opl4-lib +snd-opl4-synth +snd-opti92x-ad1848 +snd-opti92x-cs4231 +snd-opti93x +snd-oxygen +snd-oxygen-lib +snd-page-alloc +snd-pcm +snd-pcm-oss +snd-pcsp +snd-pcxhr +snd-pdaudiocf +snd-portman2x4 +snd-pt2258 +snd-rawmidi +snd-riptide +snd-rme32 +snd-rme96 +snd-rme9652 +snd-sb16 +snd-sb16-csp +snd-sb16-dsp +snd-sb8 +snd-sb8-dsp +snd-sbawe +snd-sb-common +snd-sc6000 +snd-seq +snd-seq-device +snd-seq-dummy +snd-seq-midi +snd-seq-midi-emul +snd-seq-midi-event +snd-seq-oss +snd-seq-virmidi +snd-serial-u16550 +snd-sgalaxy +snd-sis7019 +snd-soc-core +snd-sonicvibes +snd-sscape +snd-tea575x-tuner +snd-tea6330t +snd-timer +snd-trident +snd-usb-audio +snd-usb-caiaq +snd-usb-lib +snd-usb-usx2y +snd-util-mem +snd-via82xx +snd-via82xx-modem +snd-virmidi +snd-virtuoso +snd-vx222 +snd-vx-lib +snd-vxpocket +snd-wavefront +snd-ymfpci +soc_camera +soc_camera_platform +softcursor +softdog +sony-laptop +sonypi +sound +soundcore +sound_firmware +sp8870 +sp887x +spaceball +spaceorb +spcp8x5 +specialix +spectrum_cs +speedstep-centrino +speedstep-ich +speedstep-lib +speedstep-smi +speedtch +spi_bitbang +spi_butterfly +spidev +spi_lm70llp +squashfs +sr_mod +ssb +sscape +ssfdc +sstfb +st +starfire +stex +stinger +stir4200 +stkwebcam +stowaway +stp +stradis +strip +stv0297 +stv0299 +stv680 +sundance +sungem +sungem_phy +sunhme +suni +sunkbd +sunrpc +svcrdma +svgalib +sworks-agp +sx +sx8 +sym53c416 +sym53c500_cs +sym53c8xx +synclink +synclink_cs +synclink_gt +synclinkmp +syncppp +syscopyarea +sysfillrect +sysimgblt +sysv +t128 +t1isa +t1pci +tc1100-wmi +tcic +tcp_bic +tcp_highspeed +tcp_htcp +tcp_hybla +tcp_illinois +tcp_lp +tcp_probe +tcp_scalable +tcp_vegas +tcp_veno +tcp_westwood +tcp_yeah +tcrypt +tda10021 +tda10023 +tda10048 +tda1004x +tda10086 +tda18271 +tda7432 +tda8083 +tda826x +tda827x +tda8290 +tda9840 +tda9875 +tda9887 +tdfx +tdfxfb +tea +tea5761 +tea5767 +tea6415c +tea6420 +tehuti +tekram-sir +teles_cs +tg3 +tgr192 +thermal +thinkpad_acpi +thinkpad_ec +thmc50 +tifm_7xx1 +tifm_core +tifm_sd +tileblit +tipc +ti_usb_3410_5052 +tlan +tlclk +tle62x0 +tlsf +tlsup +tmdc +tms380tr +tmscsim +tmspci +touchit213 +touchright +touchwin +tpm +tpm_atmel +tpm_bios +tpm_infineon +tpm_nsc +tpm_tis +tps65010 +tp_smapi +trancevibrator +tridentfb +trix +ts5500_flash +ts_bm +ts_fsm +ts_kmp +tsl2550 +ttpci-eeprom +ttusb_dec +ttusbdecfe +tua6100 +tulip +tun +tuner +tuner-3036 +tuner-simple +tuner-types +tuner-xc2028 +tunnel4 +tunnel6 +turbografx +tvaudio +tveeprom +tvp5150 +twidjoy +twofish +twofish_common +twofish-i586 +typhoon +u132-hcd +u14-34f +uart401 +uart6850 +ub +ubi +ubifs +ucb1400_ts +udf +ueagle-atm +ufs +uhci-hcd +uinput +uio +uio_cif +uio_pdrv +uio_pdrv_genirq +uio_smx +uli526x +ultracam +ultrastor +umem +unionfs +upd64031a +upd64083 +uPD98402 +usb8xxx +usbatm +usbcore +usb_debug +usb_gigaset +usbhid +usbkbd +usblcd +usbled +usblp +usbmon +usbmouse +usbnet +usbserial +usb-storage +usbtouchscreen +usbvideo +usbvision +uss720 +uvcvideo +uvesafb +v4l1-compat +v4l2-common +v4l2-int-device +ves1820 +ves1x93 +vesafb +veth +vfat +vga16fb +vgastate +vgg2432a4 +via +via686a +via-agp +via_chrome9 +via-ircc +via-rhine +via-rng +via-velocity +vicam +video +video1394 +videobuf-core +videobuf-dma-contig +videobuf-dma-sg +videobuf-dvb +videobuf-vmalloc +videocodec +videodev +virtio +virtio_balloon +virtio_blk +virtio_console +virtio_net +virtio_pci +virtio_ring +virtio-rng +visor +vitesse +vivi +vlsi_ir +v_midi +vmlfb +vp27smpx +vpx3220 +vsxxxaa +vt1211 +vt8231 +vt8623fb +w1_ds2433 +w1_ds2760 +w1-gpio +w1_smem +w1_therm +w83627ehf +w83627hf +w83627hf_wdt +w83697hf_wdt +w83781d +w83791d +w83792d +w83793 +w83877f_wdt +w83977af_ir +w83977f_wdt +w83l785ts +w83l786ng +w9966 +w9968cf +wacom +wafer5823wdt +wanrouter +wanxl +warrior +wavelan +wavelan_cs +wbsd +wd +wd7000 +wdt +wdt_pci +whiteheat +winbond-840 +wire +wistron_btns +wl3501_cs +wm8739 +wm8775 +wm97xx-ts +wmi +wp512 +x25 +x25_asy +xc5000 +xcbc +xen-blkfront +xen-fbfront +xen-kbdfront +xen-netfront +xfrm4_mode_beet +xfrm4_mode_transport +xfrm4_mode_tunnel +xfrm4_tunnel +xfrm6_mode_beet +xfrm6_mode_ro +xfrm6_mode_transport +xfrm6_mode_tunnel +xfrm6_tunnel +xfrm_ipcomp +xfrm_user +xfs +xirc2ps_cs +xircom_cb +xor +xpad +xprtrdma +x_tables +xt_CLASSIFY +xt_comment +xt_connbytes +xt_connlimit +xt_connmark +xt_CONNMARK +xt_CONNSECMARK +xt_conntrack +xt_dccp +xt_dscp +xt_DSCP +xt_esp +xt_hashlimit +xt_helper +xt_iprange +xtkbd +xt_length +xt_limit +xt_mac +xt_mark +xt_MARK +xt_multiport +xt_NFLOG +xt_NFQUEUE +xt_NOTRACK +xt_owner +xt_physdev +xt_pkttype +xt_policy +xt_quota +xt_rateest +xt_RATEEST +xt_realm +xts +xt_sctp +xt_SECMARK +xt_state +xt_statistic +xt_string +xt_tcpmss +xt_TCPMSS +xt_tcpudp +xt_time +xt_TRACE +xt_u32 +xusbatm +yam +yealink +yellowfin +yenta_socket +z85230 +zatm +zaurus +zc0301 +zd1201 +zd1211rw +zhenhua +zl10353 +zlib_deflate +znet +zr36016 +zr36050 +zr36060 +zr36067 +zr364xx --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/i386/generic.modules +++ linux-2.6.27/debian/abi/2.6.27-8.17/i386/generic.modules @@ -0,0 +1,2286 @@ +3c359 +3c501 +3c503 +3c505 +3c507 +3c509 +3c515 +3c523 +3c527 +3c574_cs +3c589_cs +3c59x +3w-9xxx +3w-xxxx +53c700 +6pack +8021q +8139cp +8139too +8250_accent +8250_boca +8250_exar_st16c554 +8250_fourport +8250_hub6 +8250_mca +82596 +8390 +8390p +9p +9pnet +9pnet_virtio +a100u2w +a3d +aacraid +abituguru +abituguru3 +abyss +ac +ac3200 +ac97_bus +acecad +acenic +acerhk +acer-wmi +acpi-cpufreq +acpiphp +acpiphp_ibm +acquirewdt +act2000 +act200l-sir +act_gact +act_ipt +actisys-sir +act_mirred +act_nat +act_pedit +act_police +act_simple +acx +ad1848 +ad7414 +ad7418 +adcxx +adfs +adi +adm1021 +adm1025 +adm1026 +adm1029 +adm1031 +adm8211 +adm9240 +ads7828 +ads7846 +adt7470 +adt7473 +adutux +adv7170 +adv7175 +advansys +advantechwdt +aead +aedsp16 +aes_generic +aes-i586 +affs +af_key +af_packet +af-rxrpc +agpgart +ah4 +ah6 +aha152x +aha152x_cs +aha1542 +aha1740 +ahci +aic79xx +aic7xxx +aic94xx +aiptek +aircable +airo +airo_cs +alauda +ali-agp +ali-ircc +alim1535_wdt +alim7101_wdt +ambassador +amd64-agp +amd76x_edac +amd76xrom +amd8111e +amd-k7-agp +amd-rng +analog +anubis +aoe +apm +appledisplay +appleir +applesmc +appletalk +appletouch +applicom +ar7part +arc4 +arcfb +arcmsr +arcnet +arc-rawmode +arc-rimi +ark3116 +arkfb +arlan +arptable_filter +arp_tables +arpt_mangle +asb100 +asix +asus-laptop +async_memcpy +async_tx +async_xor +at1700 +at24 +at25 +at76_usb +ata_generic +ata_piix +aten +ath9k +ati-agp +ati_remote +ati_remote2 +atl1 +atl1e +atl2 +atlas_btns +atmel +atmel_cs +atmel_pci +atmtcp +atp +atp870u +atxp1 +aty128fb +atyfb +au0828 +au8522 +aufs +authenc +auth_rpcgss +autofs +autofs4 +av5100 +avma1_cs +avm_cs +ax25 +axnet_cs +b1 +b1dma +b1isa +b1pci +b1pcmcia +b2c2-flexcop +b2c2-flexcop-pci +b2c2-flexcop-usb +b43 +b43legacy +b44 +bas_gigaset +battery +bay +baycom_epp +baycom_par +baycom_ser_fdx +baycom_ser_hdx +bcm203x +bcm3510 +bcm5974 +befs +belkin_sa +berry_charge +bfs +bfusb +binfmt_aout +binfmt_misc +bitblit +block2mtd +blowfish +bluecard_cs +bluetooth +bnep +bnx2 +bnx2x +bonding +bpa10x +bpck +bpck6 +bpqether +br2684 +bridge +broadcom +bsd_comp +bt3c_cs +bt819 +bt856 +bt878 +btcx-risc +btsdio +bttv +btuart_cs +btusb +budget +budget-av +budget-ci +budget-core +budget-patch +BusLogic +button +bw-qcam +c101 +c4 +c67x00 +cafe_ccic +cafe_nand +camellia +capi +capidrv +capifs +capmode +carminefb +cassini +cast5 +cast6 +catc +cbc +cciss +ccm +cdc-acm +cdc_ether +cdc_subset +cdc-wdm +cdrom +cfag12864b +cfag12864bfb +cfg80211 +cfi_cmdset_0001 +cfi_cmdset_0002 +cfi_cmdset_0020 +cfi_probe +cfi_util +ch +ch341 +chipreg +cicada +cifs +cinergyT2 +cirrusfb +ck804xrom +cls_basic +cls_fw +cls_route +cls_rsvp +cls_rsvp6 +cls_tcindex +cls_u32 +cm4000_cs +cm4040_cs +cmtp +cobra +coda +com20020 +com20020_cs +com20020-isa +com20020-pci +com90io +com90xx +comm +commandir +compal-laptop +compat_ioctl32 +compcache +configfs +container +coretemp +corgi_bl +cosa +cp2101 +cpcihp_generic +cpcihp_zt5550 +cpia +cpia2 +cpia_pp +cpia_usb +cpqarray +cpqphp +cpu5wdt +cpufreq_conservative +cpufreq-nforce2 +cpufreq_ondemand +cpufreq_powersave +cpufreq_stats +cpufreq_userspace +cpuid +c-qcam +cr_bllcd +crc16 +crc32c +crc7 +crc-ccitt +crc-itu-t +crc-t10dif +crvml +cryptd +crypto_blkcipher +cryptoloop +crypto_null +cs5345 +cs53l32a +cs5535_gpio +cs553x_nand +cs89x0 +ct82c710 +ctr +cts +cx18 +cx22700 +cx22702 +cx2341x +cx23885 +cx24110 +cx24123 +cx25840 +cx8800 +cx8802 +cx88-alsa +cx88-blackbird +cx88-dvb +cx88-vp3054-i2c +cx88xx +cxacru +cxgb +cxgb3 +cyber2000fb +cyberjack +cyblafb +cyclades +cyclomx +cycx_drv +cypress_cy7c63 +cypress_m8 +cytherm +DAC960 +davicom +db9 +dc395x +dca +dccp +dccp_ccid2 +dccp_ccid3 +dccp_diag +dccp_ipv4 +dccp_ipv6 +dccp_probe +dccp_tfrc_lib +dcdbas +de2104x +de4x5 +de600 +de620 +decnet +deflate +defxx +dell_rbu +depca +des_generic +dib0070 +dib3000mb +dib3000mc +dib7000m +dib7000p +dibx000_common +digi_acceleport +dilnetpc +diskonchip +display +divacapi +divadidd +diva_idi +diva_mnt +divas +dlci +dlm +dm9601 +dm-bbr +dm-crypt +dme1737 +dmfe +dm-log +dm-loop +dm-mem-cache +dm-message +dm-mirror +dm-mod +dm-multipath +dm-raid4-5 +dm-region_hash +dm-round-robin +dm-snapshot +dmx3191d +dm-zero +dn_rtmsg +doc2000 +doc2001 +doc2001plus +docecc +dock +docprobe +donauboe +dpc7146 +dpt_i2o +drbd +drm +drx397xD +ds1621 +ds1682 +ds2482 +ds2490 +ds2760_battery +dsbr100 +dscc4 +dss1_divert +dst +dst_ca +dstr +dtc +dtl1_cs +dtlk +dummy +dv1394 +dvb-bt8xx +dvb-core +dvb-pll +dvb-ttpci +dvb-ttusb-budget +dvb-usb +dvb-usb-a800 +dvb-usb-af9005 +dvb-usb-af9005-remote +dvb-usb-anysee +dvb-usb-au6610 +dvb-usb-cxusb +dvb-usb-dib0700 +dvb-usb-dibusb-common +dvb-usb-dibusb-mb +dvb-usb-dibusb-mc +dvb-usb-digitv +dvb-usb-dtt200u +dvb-usb-dw2102 +dvb-usb-gl861 +dvb-usb-gp8psk +dvb-usb-m920x +dvb-usb-nova-t-usb2 +dvb-usb-opera +dvb-usb-ttusb2 +dvb-usb-umt-010 +dvb-usb-vp702x +dvb-usb-vp7045 +e100 +e1000 +e1000e +e2100 +e752x_edac +e7xxx_edac +eata +ebt_802_3 +ebtable_broute +ebtable_filter +ebtable_nat +ebtables +ebt_among +ebt_arp +ebt_arpreply +ebt_dnat +ebt_ip +ebt_ip6 +ebt_limit +ebt_log +ebt_mark +ebt_mark_m +ebt_nflog +ebt_pkttype +ebt_redirect +ebt_snat +ebt_stp +ebt_ulog +ebt_vlan +ecb +econet +ecryptfs +edac_core +eeepc-laptop +eepro +eepro100 +eeprom +eeprom_93cx6 +eexpress +efficeon-agp +efs +ehci-hcd +elo +elsa_cs +em28xx +em28xx-alsa +em28xx-dvb +em_cmp +emi26 +emi62 +em_meta +em_nbyte +empeg +em_text +emu10k1-gp +em_u32 +enclosure +eni +epat +epca +epia +epic100 +eql +es3210 +esb2rom +esi-sir +esp +esp4 +esp6 +et131x +et61x251 +eth1394 +eth16i +eurotechwdt +evbug +evdev +ewrk3 +exportfs +ext2 +ext3 +ext4dev +f71805f +f71882fg +f75375s +fakephp +fan +farsync +fat +faulty +fbcon +fb_ddc +fb_sys_fops +fcrypt +fd_mcs +fdomain +fdomain_cs +fealnx +ff-memless +firestream +fit2 +fit3 +floppy +fm801-gp +fmvj18x_cs +font +forcedeth +fore_200e +freevxfs +freq_table +friq +frpw +fsam7400 +fscher +fschmd +fscpos +ftdi-elan +ftdi_sio +ftl +fujitsu-laptop +fujitsu_ts +funsoft +fuse +g450_pll +gadgetfs +gamecon +gameport +garmin_gps +garp +g_cdc +gcm +gdth +generic_serial +gen_probe +geode-aes +geode-rng +g_ether +gf128mul +gf2k +g_file_storage +gfs +gfs2 +gigaset +girbil-sir +gl518sm +gl520sm +gl620a +gnbd +g_NCR5380 +g_NCR5380_mmio +gpio_keys +gpio_mouse +grip +grip_mp +g_serial +gspca_conex +gspca_etoms +gspca_main +gspca_mars +gspca_ov519 +gspca_pac207 +gspca_pac7311 +gspca_sonixb +gspca_sonixj +gspca_spca500 +gspca_spca501 +gspca_spca505 +gspca_spca506 +gspca_spca508 +gspca_spca561 +gspca_stk014 +gspca_sunplus +gspca_t613 +gspca_tv8532 +gspca_vc032x +gspca_zc3xx +gtco +guillemot +gunze +gx1fb +gxfb +gx-suspmod +g_zero +hamachi +hangcheck-timer +hci_uart +hci_vhci +hdaps +hdlc +hdlc_cisco +hdlcdrv +hdlc_fr +hdlc_ppp +hdlc_raw +hdlc_raw_eth +hdlc_x25 +he +heci +hecubafb +hermes +hexium_gemini +hexium_orion +hfc4s8s_l1 +hfcmulti +hfcpci +hfc_usb +hfs +hfsplus +hgafb +hid +hidp +hifn_795x +hisax +hisax_fcpcipnp +hisax_isac +hisax_st5481 +horizon +hostap +hostap_cs +hostap_pci +hostap_plx +hostess_sv11 +hp +hp100 +hp4x +hpfs +hpilo +hp-plus +hptiop +hp-wmi +hso +htc-pasic3 +htcpen +hwmon-vid +hysdn +i2c-algo-bit +i2c-algo-pca +i2c-algo-pcf +i2c-ali1535 +i2c-ali1563 +i2c-ali15x3 +i2c-amd756 +i2c-amd756-s4882 +i2c-amd8111 +i2c-core +i2c-dev +i2c-gpio +i2c-i801 +i2c-isch +i2c-matroxfb +i2c-nforce2 +i2c-nforce2-s4985 +i2c-ocores +i2c-parport +i2c-parport-light +i2c-pca-isa +i2c-pca-platform +i2c-piix4 +i2c-simtec +i2c-sis5595 +i2c-sis630 +i2c-sis96x +i2c-stub +i2c-taos-evm +i2c-tiny-usb +i2c-via +i2c-viapro +i2c-voodoo3 +i2o_block +i2o_bus +i2o_config +i2o_core +i2o_proc +i2o_scsi +i3000_edac +i5000_edac +i5100_edac +i5k_amb +i6300esb +i810 +i810fb +i82092 +i82365 +i82860_edac +i82875p_edac +i82975x_edac +i830 +i8k +i915 +ib700wdt +ib_addr +ib_cm +ib_core +ib_ipoib +ib_iser +ib_mad +ibmaem +ibmasm +ibmasr +ibmcam +ibmlana +ibmmca +ibmpex +ibmphp +ib_mthca +ibmtr +ibmtr_cs +ib_sa +ib_srp +ib_ucm +ib_umad +ib_uverbs +ichxrom +icn +icplus +idmouse +idt77252 +ieee1394 +ieee80211 +ieee80211_crypt +ieee80211_crypt_ccmp +ieee80211_crypt_tkip +ieee80211_crypt_wep +ifb +iforce +igb +ili9320 +imm +in2000 +inet_lro +inexio +inftl +initio +inport +input-polldev +intel-agp +intelfb +intel_menlow +intel-rng +intel_vr_nor +interact +ioatdma +ioc4 +io_edgeport +io_ti +iowarrior +ip2 +ip6_queue +ip6table_filter +ip6table_mangle +ip6table_raw +ip6_tables +ip6table_security +ip6t_ah +ip6t_eui64 +ip6t_frag +ip6t_hbh +ip6t_hl +ip6t_HL +ip6t_ipv6header +ip6t_LOG +ip6t_mh +ip6t_REJECT +ip6t_rt +ip6_tunnel +ipaq +ipcomp +ipcomp6 +ipddp +ipg +ip_gre +iphase +ipip +ipmi_devintf +ipmi_msghandler +ipmi_poweroff +ipmi_si +ipmi_watchdog +ip_queue +ipr +ips +iptable_filter +iptable_mangle +iptable_nat +iptable_raw +ip_tables +iptable_security +ipt_addrtype +ipt_ah +ipt_CLUSTERIP +ipt_ecn +ipt_ECN +ipt_LOG +ipt_MASQUERADE +ipt_NETMAP +ipt_recent +ipt_REDIRECT +ipt_REJECT +ipt_ttl +ipt_TTL +ipt_ULOG +ipv6 +ip_vs +ip_vs_dh +ip_vs_ftp +ip_vs_lblc +ip_vs_lblcr +ip_vs_lc +ip_vs_nq +ip_vs_rr +ip_vs_sed +ip_vs_sh +ip_vs_wlc +ip_vs_wrr +ipw +ipw2100 +ipw2200 +ipwireless +ipx +ircomm +ir-common +ircomm-tty +irda +irda-usb +ir-kbd-i2c +irlan +irnet +irtty-sir +iscsi_ibft +iscsi_tcp +iscsi_trgt +isdn +isdn_bsdcomp +isdnhdlc +isight_firmware +isl6405 +isl6421 +isofs +isp116x-hcd +isp1760 +it87 +it8712f_wdt +iTCO_vendor_support +iTCO_wdt +itd1000 +ivtv +ivtvfb +iw_c2 +iw_cm +iw_cxgb3 +iwl3945 +iwlagn +iwlcore +ixgb +ixgbe +ixj +ixj_pcmcia +jbd +jbd2 +jedec_probe +jffs2 +jfs +joydev +joydump +jsm +k8temp +kafs +kahlua +kaweth +kbic +kbtab +kernelcapi +keyspan +keyspan_pda +keyspan_remote +khazad +kingsun-sir +kl5kusb105 +kobil_sct +konicawc +ks0108 +ks0127 +ks959-sir +ksdazzle-sir +ktti +kvm +kvm-amd +kvm-intel +kyrofb +l1oip +l2cap +l440gx +l64781 +lanai +lance +lanstreamer +lapb +lapbether +lcd +ldusb +lec +led-class +leds-gpio +leds-net48xx +leds-pca9532 +leds-pca955x +leds-wrap +ledtrig-default-on +ledtrig-heartbeat +ledtrig-timer +legousbtower +lgdt330x +libata +libcrc32c +libertas +libertas_cs +libertas_sdio +libiscsi +libphy +libsas +libsrp +libusual +lightning +linear +lirc_atiusb +lirc_bt829 +lirc_cmdir +lirc_dev +lirc_i2c +lirc_igorplugusb +lirc_imon +lirc_it87 +lirc_mceusb +lirc_mceusb2 +lirc_pvr150 +lirc_sasem +lirc_serial +lirc_serial_igor +lirc_sir +lirc_streamzap +lirc_ttusbir +litelink-sir +lkkbd +llc2 +lm63 +lm70 +lm75 +lm77 +lm78 +lm80 +lm83 +lm85 +lm87 +lm90 +lm92 +lm93 +lmc +lmpcm_usb +lnbp21 +lne390 +lockd +lock_dlm +logibm +longhaul +longrun +loop +lp +lp486e +lpfc +lrw +ltpc +ltv350qv +lxfb +lxt +lzo +lzo_compress +lzo_decompress +m25p80 +m52790 +ma600-sir +mac80211 +machzwd +macmodes +macvlan +madgemc +magellan +map_absent +map_funcs +map_ram +map_rom +marvell +matroxfb_accel +matroxfb_base +matroxfb_crtc2 +matroxfb_DAC1064 +matroxfb_g450 +matroxfb_maven +matroxfb_misc +matroxfb_Ti3026 +matrox_w1 +max1619 +max6650 +max6875 +max7301 +max732x +mbcache +mbp_nvidia_bl +mcp2120-sir +mcp23s08 +mcs7780 +mcs7830 +mct_u232 +md4 +mdacon +mdc800 +mdio-bitbang +md-mod +megaraid +megaraid_mbox +megaraid_mm +megaraid_sas +meye +mga +michael_mic +microcode +microtek +mii +minix +mISDN_core +mISDN_dsp +mixcomwd +mk712 +mkiss +mlx4_core +mlx4_ib +mmc_block +mmc_core +mos7720 +mos7840 +moto_modem +moxa +mpoa +mptbase +mptctl +mptfc +mptlan +mptsas +mptscsih +mptspi +mpu401 +msdos +msi-laptop +msnd +msnd_classic +msnd_pinnacle +msp3400 +msr +mt2060 +mt20xx +mt2131 +mt2266 +mt312 +mt352 +mt9m001 +mt9v022 +mtd +mtd_blkdevs +mtdblock +mtdblock_ro +mtdchar +mtdconcat +mtd_dataflash +mtdoops +mtdram +mtouch +multipath +mwave +mxb +mxl5005s +mxl5007t +mxser +myri10ge +n2 +nand +nand_ecc +nand_ids +nandsim +natsemi +navman +nbd +ncpfs +NCR53c406a +NCR_D700 +NCR_Q720_mod +ndiswrapper +ne +ne2 +ne2k-pci +ne3210 +neofb +net1080 +net2280 +netconsole +netrom +netsc520 +nettel +netwave_cs +netxen_nic +newtonkbd +nf_conntrack +nf_conntrack_amanda +nf_conntrack_ftp +nf_conntrack_h323 +nf_conntrack_ipv4 +nf_conntrack_ipv6 +nf_conntrack_irc +nf_conntrack_netbios_ns +nf_conntrack_netlink +nf_conntrack_pptp +nf_conntrack_proto_gre +nf_conntrack_proto_sctp +nf_conntrack_proto_udplite +nf_conntrack_sip +nf_conntrack_tftp +nf_nat +nf_nat_amanda +nf_nat_ftp +nf_nat_h323 +nf_nat_irc +nf_nat_pptp +nf_nat_proto_gre +nf_nat_proto_sctp +nf_nat_proto_udplite +nf_nat_sip +nf_nat_snmp_basic +nf_nat_tftp +nfnetlink +nfnetlink_log +nfnetlink_queue +nfs +nfs_acl +nfsd +nftl +n_hdlc +ni52 +ni65 +nicstar +niu +nls_ascii +nls_cp1250 +nls_cp1251 +nls_cp1255 +nls_cp437 +nls_cp737 +nls_cp775 +nls_cp850 +nls_cp852 +nls_cp855 +nls_cp857 +nls_cp860 +nls_cp861 +nls_cp862 +nls_cp863 +nls_cp864 +nls_cp865 +nls_cp866 +nls_cp869 +nls_cp874 +nls_cp932 +nls_cp936 +nls_cp949 +nls_cp950 +nls_euc-jp +nls_iso8859-1 +nls_iso8859-13 +nls_iso8859-14 +nls_iso8859-15 +nls_iso8859-2 +nls_iso8859-3 +nls_iso8859-4 +nls_iso8859-5 +nls_iso8859-6 +nls_iso8859-7 +nls_iso8859-9 +nls_koi8-r +nls_koi8-ru +nls_koi8-u +nls_utf8 +nmclan_cs +nozomi +n_r3964 +ns558 +ns83820 +nsc_gpio +nsc-ircc +nsp32 +nsp_cs +ntfs +nvidia-agp +nvidiafb +nvram +nxt200x +nxt6000 +ocfs2 +ocfs2_dlm +ocfs2_dlmfs +ocfs2_nodemanager +ocfs2_stackglue +ocfs2_stack_o2cb +ocfs2_stack_user +ohci1394 +ohci-hcd +old_belkin-sir +olpc_battery +olympic +omfs +omninet +on20 +on26 +onenand +onenand_sim +opl3 +oprofile +option +or51132 +or51211 +orinoco +orinoco_cs +orinoco_nortel +orinoco_pci +orinoco_plx +orinoco_tmd +osst +oti6858 +output +ov511 +ov511_decomp +ov518_decomp +ov7670 +ovcamchip +p4-clockmod +p54common +p54pci +p54usb +p80211 +p8023 +padlock-aes +padlock-sha +paride +parkbd +parport +parport_ax88796 +parport_cs +parport_pc +parport_serial +pas16 +pas2 +pata_acpi +pata_ali +pata_amd +pata_artop +pata_atiixp +pata_cmd64x +pata_cs5520 +pata_cs5530 +pata_cs5535 +pata_cs5536 +pata_efar +pata_hpt366 +pata_hpt37x +pata_hpt3x3 +pata_it8213 +pata_it821x +pata_jmicron +pata_legacy +pata_marvell +pata_mpiix +pata_netcell +pata_ninja32 +pata_ns87410 +pata_ns87415 +pata_oldpiix +pata_pcmcia +pata_pdc2027x +pata_pdc202xx_old +pata_qdi +pata_rz1000 +pata_sch +pata_serverworks +pata_sil680 +pata_sis +pata_sl82c105 +pata_triflex +pata_via +pata_winbond +pbe5 +pc110pad +pc300 +pc87360 +pc8736x_gpio +pc87413_wdt +pc87427 +pca953x +pcbc +pcbit +pcd +pcf857x +pcf8591 +pci +pci200syn +pciehp +pci_hotplug +pcilynx +pcips2 +pci_slot +pcmcia +pcmcia_core +pcnet32 +pcnet_cs +pcspkr +pcwd +pcwd_pci +pcwd_usb +pd +pd6729 +pda_power +pdc_adma +pegasus +penmount +pf +pg +phantom +phidget +phidgetkit +phidgetmotorcontrol +phidgetservo +phonedev +phram +physmap +pktcdvd +pktgen +pl2303 +platform_lcd +plat_nand +plat-ram +plip +plusb +pluto2 +pm2fb +pm3fb +pmc551 +pms +powermate +powernow-k6 +powernow-k7 +powernow-k8 +ppa +ppdev +ppp_async +ppp_deflate +ppp_generic +ppp_mppe +pppoatm +pppoe +pppol2tp +pppox +ppp_synctty +prism2_usb +prism54 +processor +progear_bl +proteon +psmouse +pss +pt +pvrusb2 +pwc +qla1280 +qla2xxx +qla3xxx +qla4xxx +qlogic_cs +qlogicfas +qlogicfas408 +qnx4 +qsemi +qt1010 +quickcam +quickcam_messenger +quota_v1 +quota_v2 +r128 +r8169 +r82600_edac +r8a66597-hcd +radeon +radeonfb +radio-aimslab +radio-aztech +radio-cadet +radio-gemtek +radio-gemtek-pci +radio-maestro +radio-maxiradio +radio-rtrack2 +radio-sf16fmi +radio-sf16fmr2 +radio-si470x +radio-terratec +radio-trust +radio-typhoon +radio-zoltrix +raid0 +raid1 +raid10 +raid456 +raid_class +raw +raw1394 +ray_cs +rdma_cm +rdma_ucm +redboot +reed_solomon +reiserfs +rfc1051 +rfc1201 +rfcomm +rfd_ftl +rfkill +rfkill-input +ricoh_mmc +rio +rio500 +riscom8 +rivafb +rmd128 +rmd160 +rmd256 +rmd320 +rndis_host +rndis_wlan +rocket +romfs +rose +rpcsec_gss_krb5 +rpcsec_gss_spkm3 +rrunner +rsrc_nonstatic +rt2400pci +rt2500pci +rt2500usb +rt2x00lib +rt2x00pci +rt2x00usb +rt61pci +rt73usb +rtc-ds1305 +rtc-ds1307 +rtc-ds1374 +rtc-ds1553 +rtc-ds1672 +rtc-ds1742 +rtc-fm3130 +rtc-isl1208 +rtc-m41t80 +rtc-m41t94 +rtc-m48t59 +rtc-m48t86 +rtc-max6900 +rtc-max6902 +rtc-pcf8563 +rtc-pcf8583 +rtc-rs5c348 +rtc-rs5c372 +rtc-stk17ta8 +rtc-test +rtc-v3020 +rtc-x1205 +rtl8150 +rtl8180 +rtl8187 +rxkad +s1d13xxxfb +s2255drv +s2io +s3fb +s5h1409 +s5h1411 +s5h1420 +saa5246a +saa5249 +saa6588 +saa6752hs +saa7110 +saa7111 +saa7114 +saa7115 +saa7127 +saa7134 +saa7134-alsa +saa7134-dvb +saa7134-empress +saa7146 +saa7146_vv +saa717x +saa7185 +safe_serial +salsa20_generic +salsa20-i586 +sata_inic162x +sata_mv +sata_nv +sata_promise +sata_qstor +sata_sil +sata_sil24 +sata_sis +sata_svw +sata_sx4 +sata_uli +sata_via +sata_vsc +savage +savagefb +sb +sb1000 +sbc60xxwdt +sbc7240_wdt +sbc8360 +sbc_epx_c3 +sbc_gxx +sb_lib +sbni +sbp2 +sbs +sbshc +sc +sc1200wdt +sc520cdp +sc520_wdt +sc92031 +scb2_flash +scc +sch_atm +sch_cbq +sch_dsmark +sch_gred +sch_hfsc +sch_htb +sch_ingress +sch_netem +sch_prio +sch_red +sch_sfq +sch_tbf +sch_teql +sco +scsi_debug +scsi_dh +scsi_dh_alua +scsi_dh_emc +scsi_dh_hp_sw +scsi_dh_rdac +scsi_mod +scsi_tgt +scsi_transport_fc +scsi_transport_iscsi +scsi_transport_sas +scsi_transport_spi +scsi_transport_srp +scsi_wait_scan +sctp +scx200 +scx200_acb +scx200_docflash +scx200_gpio +scx200_hrt +scx200_i2c +scx200_wdt +sdhci +sdhci-pci +sdio_uart +sdla +sd_mod +sdricoh_cs +se401 +sealevel +sedlbauer_cs +seed +seeq8005 +seqiv +ser_gigaset +serial_cs +serio_raw +sermouse +serpent +serport +ses +sfc +sg +sha1_generic +sha256_generic +sha512_generic +sh_mobile_ceu_camera +shpchp +sidewinder +sierra +sim710 +sir-dev +sis +sis190 +sis5595 +sis900 +sis-agp +sisfb +sisusbvga +sit +skfp +skge +skisa +sky2 +sl811_cs +sl811-hcd +slhc +slip +slram +sm501 +sm501fb +smbfs +smc9194 +smc91c92_cs +smc-mca +smctr +smc-ultra +smc-ultra32 +sms1xxx +smsc +smsc37b787_wdt +smsc47b397 +smsc47m1 +smsc47m192 +smsc-ircc2 +sn9c102 +snd +snd-ac97-codec +snd-ad1816a +snd-ad1848 +snd-ad1848-lib +snd-ad1889 +snd-adlib +snd-ak4114 +snd-ak4117 +snd-ak4xxx-adda +snd-ali5451 +snd-als100 +snd-als300 +snd-als4000 +snd-atiixp +snd-atiixp-modem +snd-au8810 +snd-au8820 +snd-au8830 +snd-aw2 +snd-azt2320 +snd-azt3328 +snd-bt87x +snd-bt-sco +snd-ca0106 +snd-cmi8330 +snd-cmipci +snd-cs4231 +snd-cs4231-lib +snd-cs4232 +snd-cs4236 +snd-cs4236-lib +snd-cs4281 +snd-cs46xx +snd-cs5530 +snd-cs5535audio +snd-cs8427 +snd-darla20 +snd-darla24 +snd-dt019x +snd-dummy +snd-echo3g +snd-emu10k1 +snd-emu10k1-synth +snd-emu10k1x +snd-emu8000-synth +snd-emux-synth +snd-ens1370 +snd-ens1371 +snd-es1688 +snd-es1688-lib +snd-es18xx +snd-es1938 +snd-es1968 +snd-es968 +snd-fm801 +snd-gina20 +snd-gina24 +snd-gusclassic +snd-gusextreme +snd-gus-lib +snd-gusmax +snd-hda-intel +snd-hdsp +snd-hdspm +snd-hifier +snd-hwdep +snd-i2c +snd-ice1712 +snd-ice1724 +snd-ice17xx-ak4xxx +snd-indigo +snd-indigodj +snd-indigoio +snd-intel8x0 +snd-intel8x0m +snd-interwave +snd-interwave-stb +snd-korg1212 +snd-layla20 +snd-layla24 +snd-maestro3 +snd-mia +snd-miro +snd-mixart +snd-mixer-oss +snd-mona +snd-mpu401 +snd-mpu401-uart +snd-mtpav +snd-mts64 +snd-nm256 +snd-opl3-lib +snd-opl3sa2 +snd-opl3-synth +snd-opl4-lib +snd-opl4-synth +snd-opti92x-ad1848 +snd-opti92x-cs4231 +snd-opti93x +snd-oxygen +snd-oxygen-lib +snd-page-alloc +snd-pcm +snd-pcm-oss +snd-pcsp +snd-pcxhr +snd-pdaudiocf +snd-portman2x4 +snd-pt2258 +snd-rawmidi +snd-riptide +snd-rme32 +snd-rme96 +snd-rme9652 +snd-sb16 +snd-sb16-csp +snd-sb16-dsp +snd-sb8 +snd-sb8-dsp +snd-sbawe +snd-sb-common +snd-sc6000 +snd-seq +snd-seq-device +snd-seq-dummy +snd-seq-midi +snd-seq-midi-emul +snd-seq-midi-event +snd-seq-oss +snd-seq-virmidi +snd-serial-u16550 +snd-sgalaxy +snd-sis7019 +snd-soc-core +snd-sonicvibes +snd-sscape +snd-tea575x-tuner +snd-tea6330t +snd-timer +snd-trident +snd-usb-audio +snd-usb-caiaq +snd-usb-lib +snd-usb-usx2y +snd-util-mem +snd-via82xx +snd-via82xx-modem +snd-virmidi +snd-virtuoso +snd-vx222 +snd-vx-lib +snd-vxpocket +snd-wavefront +snd-ymfpci +soc_camera +soc_camera_platform +softcursor +softdog +sony-laptop +sonypi +sound +soundcore +sound_firmware +sp8870 +sp887x +spaceball +spaceorb +spcp8x5 +specialix +spectrum_cs +speedstep-centrino +speedstep-ich +speedstep-lib +speedstep-smi +speedtch +spi_bitbang +spi_butterfly +spidev +spi_lm70llp +squashfs +sr_mod +ssb +sscape +ssfdc +sstfb +st +starfire +stex +stinger +stir4200 +stkwebcam +stowaway +stp +stradis +strip +stv0297 +stv0299 +stv680 +sundance +sungem +sungem_phy +sunhme +suni +sunkbd +sunrpc +svcrdma +svgalib +sworks-agp +sx +sx8 +sym53c416 +sym53c500_cs +sym53c8xx +synclink +synclink_cs +synclink_gt +synclinkmp +syncppp +syscopyarea +sysfillrect +sysimgblt +sysv +t128 +t1isa +t1pci +tc1100-wmi +tcic +tcp_bic +tcp_highspeed +tcp_htcp +tcp_hybla +tcp_illinois +tcp_lp +tcp_probe +tcp_scalable +tcp_vegas +tcp_veno +tcp_westwood +tcp_yeah +tcrypt +tda10021 +tda10023 +tda10048 +tda1004x +tda10086 +tda18271 +tda7432 +tda8083 +tda826x +tda827x +tda8290 +tda9840 +tda9875 +tda9887 +tdfx +tdfxfb +tea +tea5761 +tea5767 +tea6415c +tea6420 +tehuti +tekram-sir +teles_cs +tg3 +tgr192 +thermal +thinkpad_acpi +thinkpad_ec +thmc50 +tifm_7xx1 +tifm_core +tifm_sd +tileblit +tipc +ti_usb_3410_5052 +tlan +tlclk +tle62x0 +tlsf +tlsup +tmdc +tms380tr +tmscsim +tmspci +touchit213 +touchright +touchwin +tpm +tpm_atmel +tpm_bios +tpm_infineon +tpm_nsc +tpm_tis +tps65010 +tp_smapi +trancevibrator +tridentfb +trix +ts5500_flash +ts_bm +ts_fsm +ts_kmp +tsl2550 +ttpci-eeprom +ttusb_dec +ttusbdecfe +tua6100 +tulip +tun +tuner +tuner-3036 +tuner-simple +tuner-types +tuner-xc2028 +tunnel4 +tunnel6 +turbografx +tvaudio +tveeprom +tvp5150 +twidjoy +twofish +twofish_common +twofish-i586 +typhoon +u132-hcd +u14-34f +uart401 +uart6850 +ub +ubi +ubifs +ucb1400_ts +udf +ueagle-atm +ufs +uhci-hcd +uinput +uio +uio_cif +uio_pdrv +uio_pdrv_genirq +uio_smx +uli526x +ultracam +ultrastor +umem +unionfs +upd64031a +upd64083 +uPD98402 +usb8xxx +usbatm +usbcore +usb_debug +usb_gigaset +usbhid +usbkbd +usblcd +usbled +usblp +usbmon +usbmouse +usbnet +usbserial +usb-storage +usbtouchscreen +usbvideo +usbvision +uss720 +uvcvideo +uvesafb +v4l1-compat +v4l2-common +v4l2-int-device +ves1820 +ves1x93 +vesafb +veth +vfat +vga16fb +vgastate +vgg2432a4 +via +via686a +via-agp +via_chrome9 +via-ircc +via-rhine +via-rng +via-velocity +vicam +video +video1394 +videobuf-core +videobuf-dma-contig +videobuf-dma-sg +videobuf-dvb +videobuf-vmalloc +videocodec +videodev +virtio +virtio_balloon +virtio_blk +virtio_console +virtio_net +virtio_pci +virtio_ring +virtio-rng +visor +vitesse +vivi +vlsi_ir +v_midi +vmlfb +vp27smpx +vpx3220 +vsxxxaa +vt1211 +vt8231 +vt8623fb +w1_ds2433 +w1_ds2760 +w1-gpio +w1_smem +w1_therm +w83627ehf +w83627hf +w83627hf_wdt +w83697hf_wdt +w83781d +w83791d +w83792d +w83793 +w83877f_wdt +w83977af_ir +w83977f_wdt +w83l785ts +w83l786ng +w9966 +w9968cf +wacom +wafer5823wdt +wanrouter +wanxl +warrior +wavelan +wavelan_cs +wbsd +wd +wd7000 +wdt +wdt_pci +whiteheat +winbond-840 +wire +wistron_btns +wl3501_cs +wm8739 +wm8775 +wm97xx-ts +wmi +wp512 +x25 +x25_asy +xc5000 +xcbc +xfrm4_mode_beet +xfrm4_mode_transport +xfrm4_mode_tunnel +xfrm4_tunnel +xfrm6_mode_beet +xfrm6_mode_ro +xfrm6_mode_transport +xfrm6_mode_tunnel +xfrm6_tunnel +xfrm_ipcomp +xfrm_user +xfs +xirc2ps_cs +xircom_cb +xor +xpad +xprtrdma +x_tables +xt_CLASSIFY +xt_comment +xt_connbytes +xt_connlimit +xt_connmark +xt_CONNMARK +xt_CONNSECMARK +xt_conntrack +xt_dccp +xt_dscp +xt_DSCP +xt_esp +xt_hashlimit +xt_helper +xt_iprange +xtkbd +xt_length +xt_limit +xt_mac +xt_mark +xt_MARK +xt_multiport +xt_NFLOG +xt_NFQUEUE +xt_NOTRACK +xt_owner +xt_physdev +xt_pkttype +xt_policy +xt_quota +xt_rateest +xt_RATEEST +xt_realm +xts +xt_sctp +xt_SECMARK +xt_state +xt_statistic +xt_string +xt_tcpmss +xt_TCPMSS +xt_tcpudp +xt_time +xt_TRACE +xt_u32 +xusbatm +yam +yealink +yellowfin +yenta_socket +z85230 +zatm +zaurus +zc0301 +zd1201 +zd1211rw +zhenhua +zl10353 +zlib_deflate +znet +zr36016 +zr36050 +zr36060 +zr36067 +zr364xx --- linux-2.6.27.orig/debian/abi/2.6.27-8.17/i386/generic +++ linux-2.6.27/debian/abi/2.6.27-8.17/i386/generic @@ -0,0 +1,8158 @@ +EXPORT_SYMBOL arch/x86/kernel/scx200 0x254e5667 scx200_gpio_base +EXPORT_SYMBOL arch/x86/kernel/scx200 0x35a3c008 scx200_gpio_configure +EXPORT_SYMBOL arch/x86/kernel/scx200 0x8cfa375c scx200_gpio_shadow +EXPORT_SYMBOL arch/x86/kernel/scx200 0x907665bd scx200_cb_base +EXPORT_SYMBOL arch/x86/kvm/kvm 0x12065b3a kvm_read_guest_atomic +EXPORT_SYMBOL arch/x86/kvm/kvm 0xc3516b5f kvm_cpu_has_pending_timer +EXPORT_SYMBOL crypto/gf128mul 0x0c2f123f gf128mul_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x1068004b gf128mul_bbe +EXPORT_SYMBOL crypto/gf128mul 0x2f2889a0 gf128mul_init_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0x3755f990 gf128mul_init_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x384ef9ce gf128mul_64k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x56af0dbd gf128mul_x_ble +EXPORT_SYMBOL crypto/gf128mul 0x83581089 gf128mul_init_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0x9b2560b9 gf128mul_init_4k_bbe +EXPORT_SYMBOL crypto/gf128mul 0x9e13f6f6 gf128mul_lle +EXPORT_SYMBOL crypto/gf128mul 0xbd17a0df gf128mul_4k_lle +EXPORT_SYMBOL crypto/gf128mul 0xc0890413 gf128mul_64k_lle +EXPORT_SYMBOL crypto/gf128mul 0xd60736ec gf128mul_free_64k +EXPORT_SYMBOL crypto/xor 0x5b6c00e6 xor_blocks +EXPORT_SYMBOL drivers/acpi/processor 0x0603377d acpi_processor_preregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0x8461fbfe acpi_processor_unregister_performance +EXPORT_SYMBOL drivers/acpi/processor 0xd78b77e1 acpi_processor_register_performance +EXPORT_SYMBOL drivers/acpi/processor 0xe420d26f acpi_processor_notify_smm +EXPORT_SYMBOL drivers/acpi/processor 0xe8a3605f acpi_processor_set_thermal_limit +EXPORT_SYMBOL drivers/atm/suni 0x86592541 suni_init +EXPORT_SYMBOL drivers/atm/uPD98402 0x5704842f uPD98402_init +EXPORT_SYMBOL drivers/block/loop 0xbfee3ad5 loop_unregister_transfer +EXPORT_SYMBOL drivers/block/loop 0xf0fa1d04 loop_register_transfer +EXPORT_SYMBOL drivers/block/paride/paride 0x0a3471f2 paride_unregister +EXPORT_SYMBOL drivers/block/paride/paride 0x20923a76 pi_do_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0x21d07f26 pi_read_regr +EXPORT_SYMBOL drivers/block/paride/paride 0x2515485c pi_release +EXPORT_SYMBOL drivers/block/paride/paride 0x4b2c1672 pi_write_block +EXPORT_SYMBOL drivers/block/paride/paride 0x9282dd3a pi_init +EXPORT_SYMBOL drivers/block/paride/paride 0x93362a1e paride_register +EXPORT_SYMBOL drivers/block/paride/paride 0xbc076a1b pi_read_block +EXPORT_SYMBOL drivers/block/paride/paride 0xc32d7656 pi_schedule_claimed +EXPORT_SYMBOL drivers/block/paride/paride 0xcad23e71 pi_write_regr +EXPORT_SYMBOL drivers/block/paride/paride 0xebb95cd1 pi_connect +EXPORT_SYMBOL drivers/block/paride/paride 0xee4627d7 pi_disconnect +EXPORT_SYMBOL drivers/cdrom/cdrom 0x4f476e96 init_cdrom_command +EXPORT_SYMBOL drivers/cdrom/cdrom 0x6555ba83 cdrom_number_of_slots +EXPORT_SYMBOL drivers/cdrom/cdrom 0x6d57df36 cdrom_mode_sense +EXPORT_SYMBOL drivers/cdrom/cdrom 0x9b2f765b cdrom_ioctl +EXPORT_SYMBOL drivers/cdrom/cdrom 0xa0a70571 cdrom_release +EXPORT_SYMBOL drivers/cdrom/cdrom 0xa36fe512 cdrom_get_media_event +EXPORT_SYMBOL drivers/cdrom/cdrom 0xafd586fd cdrom_media_changed +EXPORT_SYMBOL drivers/cdrom/cdrom 0xc02ad4be register_cdrom +EXPORT_SYMBOL drivers/cdrom/cdrom 0xc2560a04 cdrom_open +EXPORT_SYMBOL drivers/cdrom/cdrom 0xcb5f536b cdrom_get_last_written +EXPORT_SYMBOL drivers/cdrom/cdrom 0xcf20ba60 cdrom_mode_select +EXPORT_SYMBOL drivers/cdrom/cdrom 0xf2e455aa unregister_cdrom +EXPORT_SYMBOL drivers/char/agp/agpgart 0x0281b263 get_agp_version +EXPORT_SYMBOL drivers/char/agp/agpgart 0x03a7ceda agp_backend_acquire +EXPORT_SYMBOL drivers/char/agp/agpgart 0x09e58f4c agp_generic_insert_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x14d087a8 agp_free_page_array +EXPORT_SYMBOL drivers/char/agp/agpgart 0x161c7669 agp_alloc_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0x1e2f5175 agp_generic_destroy_page +EXPORT_SYMBOL drivers/char/agp/agpgart 0x1ee0016b agp_enable +EXPORT_SYMBOL drivers/char/agp/agpgart 0x216a0bd4 agp_generic_free_by_type +EXPORT_SYMBOL drivers/char/agp/agpgart 0x2a16cf36 agp_put_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0x2cac9711 agp_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0x30226ddf agp_device_command +EXPORT_SYMBOL drivers/char/agp/agpgart 0x3f44f77f agp_unbind_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x451aa245 agp_generic_free_gatt_table +EXPORT_SYMBOL drivers/char/agp/agpgart 0x45bb6efd agp_copy_info +EXPORT_SYMBOL drivers/char/agp/agpgart 0x47372a91 agp_generic_alloc_by_type +EXPORT_SYMBOL drivers/char/agp/agpgart 0x4b085dbf agp3_generic_configure +EXPORT_SYMBOL drivers/char/agp/agpgart 0x53e461a5 agp_generic_alloc_page +EXPORT_SYMBOL drivers/char/agp/agpgart 0x55c5d657 agp_alloc_page_array +EXPORT_SYMBOL drivers/char/agp/agpgart 0x56ff6469 agp_find_bridge +EXPORT_SYMBOL drivers/char/agp/agpgart 0x673f815e agp_bridges +EXPORT_SYMBOL drivers/char/agp/agpgart 0x7538b132 agp_off +EXPORT_SYMBOL drivers/char/agp/agpgart 0x781da021 agp_generic_create_gatt_table +EXPORT_SYMBOL drivers/char/agp/agpgart 0x80ccf640 agp_generic_alloc_user +EXPORT_SYMBOL drivers/char/agp/agpgart 0x892e0d40 agp_free_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0x9cd77347 agp_generic_type_to_mask_type +EXPORT_SYMBOL drivers/char/agp/agpgart 0x9e498213 agp_generic_mask_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xa4d4f0e6 global_cache_flush +EXPORT_SYMBOL drivers/char/agp/agpgart 0xad06d177 agp_flush_chipset +EXPORT_SYMBOL drivers/char/agp/agpgart 0xb04ea8f0 agp_rebind_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xb941af3d agp_allocate_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xbf0202b7 agp_generic_remove_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc185ede9 agp_bind_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc2424641 agp3_generic_cleanup +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc5d9c46c agp_try_unsupported_boot +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc65abeb7 agp3_generic_sizes +EXPORT_SYMBOL drivers/char/agp/agpgart 0xc9706c91 agp_create_memory +EXPORT_SYMBOL drivers/char/agp/agpgart 0xcc8c5e52 agp_generic_enable +EXPORT_SYMBOL drivers/char/agp/agpgart 0xd0fef3b2 agp_free_key +EXPORT_SYMBOL drivers/char/agp/agpgart 0xdaab2501 agp_backend_release +EXPORT_SYMBOL drivers/char/agp/agpgart 0xdbf22068 agp3_generic_tlbflush +EXPORT_SYMBOL drivers/char/agp/agpgart 0xde9b17ed agp3_generic_fetch_size +EXPORT_SYMBOL drivers/char/agp/agpgart 0xeea6eda8 agp_collect_device_status +EXPORT_SYMBOL drivers/char/generic_serial 0x016b689f gs_block_til_ready +EXPORT_SYMBOL drivers/char/generic_serial 0x0563e9f4 gs_chars_in_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0x09b38530 gs_write_room +EXPORT_SYMBOL drivers/char/generic_serial 0x0da83e61 gs_close +EXPORT_SYMBOL drivers/char/generic_serial 0x1da610ec gs_set_termios +EXPORT_SYMBOL drivers/char/generic_serial 0x2462b399 gs_getserial +EXPORT_SYMBOL drivers/char/generic_serial 0x26fcc30d gs_put_char +EXPORT_SYMBOL drivers/char/generic_serial 0x29a682d3 gs_stop +EXPORT_SYMBOL drivers/char/generic_serial 0x4b818235 gs_hangup +EXPORT_SYMBOL drivers/char/generic_serial 0x54ed3a39 gs_got_break +EXPORT_SYMBOL drivers/char/generic_serial 0x59faac81 gs_write +EXPORT_SYMBOL drivers/char/generic_serial 0x6a71ebdf gs_flush_chars +EXPORT_SYMBOL drivers/char/generic_serial 0xa923456a gs_init_port +EXPORT_SYMBOL drivers/char/generic_serial 0xe41983ef gs_setserial +EXPORT_SYMBOL drivers/char/generic_serial 0xf1b44b95 gs_flush_buffer +EXPORT_SYMBOL drivers/char/generic_serial 0xffe6a864 gs_start +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0a5f1245 ipmi_request_supply_msgs +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0b2088fc ipmi_smi_watcher_register +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x176e73c6 ipmi_unregister_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x1ef3e657 ipmi_set_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x23e8d8e1 ipmi_get_my_address +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x24b8dee5 ipmi_smi_add_proc_entry +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x266f6078 ipmi_create_user +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2a7f1331 ipmi_get_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2b3f7be6 ipmi_smi_msg_received +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2f086a91 ipmi_get_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x35eba4d1 ipmi_smi_watchdog_pretimeout +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x40f2b10c ipmi_alloc_smi_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x49441931 ipmi_free_recv_msg +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x4cbdc5c6 ipmi_set_gets_events +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x65dbb473 ipmi_smi_watcher_unregister +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x6c649ade ipmi_register_smi +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x7be58da0 ipmi_poll_interface +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x804f922a ipmi_addr_length +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x8582f468 ipmi_destroy_user +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x8dbb4fd0 ipmi_set_maintenance_mode +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x8f5bae05 ipmi_set_my_LUN +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x915b0c61 ipmi_get_version +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xbdfb2e52 ipmi_register_for_cmd +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc5609a10 ipmi_request_settime +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4f4665b ipmi_validate_addr +EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe5d50572 ipmi_unregister_smi +EXPORT_SYMBOL drivers/char/nsc_gpio 0x22771650 nsc_gpio_dump +EXPORT_SYMBOL drivers/char/nsc_gpio 0x7d208905 nsc_gpio_write +EXPORT_SYMBOL drivers/char/nsc_gpio 0xf31a245e nsc_gpio_read +EXPORT_SYMBOL drivers/char/nvram 0x0f28cb91 nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x17ff2c1d __nvram_read_byte +EXPORT_SYMBOL drivers/char/nvram 0x2adec1e0 __nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x7da28f12 nvram_check_checksum +EXPORT_SYMBOL drivers/char/nvram 0x9ce3f83f nvram_write_byte +EXPORT_SYMBOL drivers/char/nvram 0xa8813189 __nvram_write_byte +EXPORT_SYMBOL drivers/cpufreq/cpufreq_conservative 0x5c6fc6c5 cpufreq_gov_conservative +EXPORT_SYMBOL drivers/cpufreq/cpufreq_ondemand 0x83a131ed cpufreq_gov_ondemand +EXPORT_SYMBOL drivers/cpufreq/cpufreq_powersave 0x26d1a0fb cpufreq_gov_powersave +EXPORT_SYMBOL drivers/cpufreq/cpufreq_userspace 0x0aaa53f2 cpufreq_gov_userspace +EXPORT_SYMBOL drivers/edac/edac_core 0x0c518617 edac_mc_handle_fbd_ue +EXPORT_SYMBOL drivers/edac/edac_core 0x721283ec edac_mc_find +EXPORT_SYMBOL drivers/edac/edac_core 0xb7716609 edac_mc_handle_fbd_ce +EXPORT_SYMBOL drivers/gpu/drm/drm 0x005637af drm_get_resource_start +EXPORT_SYMBOL drivers/gpu/drm/drm 0x00e858b3 drm_agp_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0x03821817 drm_ioctl +EXPORT_SYMBOL drivers/gpu/drm/drm 0x073c4096 drm_i_have_hw_lock +EXPORT_SYMBOL drivers/gpu/drm/drm 0x0836695c drm_sman_takedown +EXPORT_SYMBOL drivers/gpu/drm/drm 0x14817b79 drm_agp_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0x16a6bb9a drm_rmmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0x1a18d3cf drm_sg_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x20645642 drm_debug +EXPORT_SYMBOL drivers/gpu/drm/drm 0x20f58aec drm_getsarea +EXPORT_SYMBOL drivers/gpu/drm/drm 0x21451ac4 drm_sman_owner_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x22877a47 drm_agp_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0x260e4aef drm_get_resource_len +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2916bf63 drm_sman_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x2eb2f903 drm_sman_free_key +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3074f033 drm_order +EXPORT_SYMBOL drivers/gpu/drm/drm 0x32c9a18b drm_ati_pcigart_cleanup +EXPORT_SYMBOL drivers/gpu/drm/drm 0x35b927df drm_fasync +EXPORT_SYMBOL drivers/gpu/drm/drm 0x36586cf3 drm_core_reclaim_buffers +EXPORT_SYMBOL drivers/gpu/drm/drm 0x3bd62817 drm_agp_enable +EXPORT_SYMBOL drivers/gpu/drm/drm 0x5183eff4 drm_core_ioremap_wc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x55f060ee drm_sman_set_range +EXPORT_SYMBOL drivers/gpu/drm/drm 0x5b0fc5c0 drm_irq_uninstall +EXPORT_SYMBOL drivers/gpu/drm/drm 0x6444d0b5 drm_ati_pcigart_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0x65a5b198 drm_core_ioremapfree +EXPORT_SYMBOL drivers/gpu/drm/drm 0x703f5e1b drm_agp_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0x7844c7d5 drm_agp_bind +EXPORT_SYMBOL drivers/gpu/drm/drm 0x80e44f9f drm_poll +EXPORT_SYMBOL drivers/gpu/drm/drm 0x8e7d21fe drm_agp_unbind +EXPORT_SYMBOL drivers/gpu/drm/drm 0x96d1e658 drm_get_drawable_info +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9c25b192 drm_core_get_map_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0x9d9226fa drm_addbufs_agp +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa220cc44 drm_exit +EXPORT_SYMBOL drivers/gpu/drm/drm 0xa8cada8b drm_core_get_reg_ofs +EXPORT_SYMBOL drivers/gpu/drm/drm 0xaa44a112 drm_addbufs_pci +EXPORT_SYMBOL drivers/gpu/drm/drm 0xaf29788e drm_sman_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb50c9b4e drm_addmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb5ec0013 drm_agp_acquire +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb5f43b93 drm_open +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb6f980ca drm_mmap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xb7baa049 drm_core_ioremap +EXPORT_SYMBOL drivers/gpu/drm/drm 0xc03b5a3a drm_locked_tasklet +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd2c83814 drm_idlelock_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3028e75 drm_sman_set_manager +EXPORT_SYMBOL drivers/gpu/drm/drm 0xda9783fd drm_idlelock_take +EXPORT_SYMBOL drivers/gpu/drm/drm 0xde539843 drm_pci_free +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe2ad6a97 drm_init +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe83d4a42 drm_release +EXPORT_SYMBOL drivers/gpu/drm/drm 0xe919dd5c drm_sman_owner_clean +EXPORT_SYMBOL drivers/gpu/drm/drm 0xf94233ec drm_pci_alloc +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfc5605fe drm_vbl_send_signals +EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdfbad19 drm_sman_alloc +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0x0903c239 vid_from_reg +EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0xef1c781c vid_which_vrm +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x5e517b0a i2c_bit_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0xec651894 i2c_bit_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0x0f0cbd82 i2c_pca_add_numbered_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0xf2106a1c i2c_pca_add_bus +EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pcf 0xb48a11ab i2c_pcf_add_bus +EXPORT_SYMBOL drivers/i2c/busses/i2c-amd756 0x21c7420e amd756_smbus +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x02d4ad0f tps65013_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x28485130 tps65010_config_vregs1 +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x33739de7 tps65010_set_vib +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0x9fd44c69 tps65010_set_led +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xb14080cc tps65010_set_low_pwr +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xd5bb106d tps65010_set_vbus_draw +EXPORT_SYMBOL drivers/i2c/chips/tps65010 0xe99b3f36 tps65010_set_gpio_out_value +EXPORT_SYMBOL drivers/i2c/i2c-core 0x03d2ad9f i2c_use_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x09a8693d i2c_smbus_read_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x13cb2e14 i2c_smbus_read_i2c_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x1b7b5310 i2c_register_driver +EXPORT_SYMBOL drivers/i2c/i2c-core 0x2d20a242 i2c_smbus_write_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x302a0ec5 i2c_clients_command +EXPORT_SYMBOL drivers/i2c/i2c-core 0x36b402fa i2c_smbus_write_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x3cfb240d i2c_smbus_xfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0x3d5d0434 i2c_add_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0x3f4a9fba i2c_smbus_read_byte_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x489d3c65 i2c_verify_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0x54208fca i2c_smbus_read_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0x6b7cfea0 i2c_probe +EXPORT_SYMBOL drivers/i2c/i2c-core 0x7f59a1b7 i2c_del_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0x898cdf3e i2c_get_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0x8a121bbd i2c_smbus_write_word_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0x8a8a96c7 i2c_put_adapter +EXPORT_SYMBOL drivers/i2c/i2c-core 0xb05331b2 i2c_transfer +EXPORT_SYMBOL drivers/i2c/i2c-core 0xc0a7ab74 i2c_smbus_read_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0xc3ea202f i2c_detach_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xd24d3a0a i2c_smbus_write_i2c_block_data +EXPORT_SYMBOL drivers/i2c/i2c-core 0xd61fb41d i2c_release_client +EXPORT_SYMBOL drivers/i2c/i2c-core 0xd95297ad i2c_master_send +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe045e9d4 i2c_del_driver +EXPORT_SYMBOL drivers/i2c/i2c-core 0xe6e3ad12 i2c_master_recv +EXPORT_SYMBOL drivers/i2c/i2c-core 0xfcf853e1 i2c_smbus_write_byte +EXPORT_SYMBOL drivers/i2c/i2c-core 0xffb951fe i2c_attach_client +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x01fac573 hpsb_iso_xmit_sync +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x08404650 hpsb_set_packet_complete_task +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0c6da941 csr1212_release_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0e5a659c csr1212_new_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x11837d4d hpsb_make_writepacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1188a5db hpsb_reset_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x13b4a268 csr1212_attach_keyval_to_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x176efbe7 hpsb_iso_xmit_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1877dfa7 hpsb_update_config_rom_image +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1bad51d8 hpsb_iso_xmit_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1e6804e7 hpsb_read_cycle_timer +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1e88ad6f hpsb_bus_reset +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1f51019d hpsb_iso_recv_start +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1f75079b hpsb_remove_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x219cbabe dma_region_offset_to_bus +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2541de03 dma_region_mmap +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2752b9a8 csr1212_get_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x28967c48 hpsb_set_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x35da9341 hpsb_send_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x35eaf7b8 hpsb_create_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x37a736c9 csr1212_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3806dcaa hpsb_allocate_and_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x384108f1 hpsb_free_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x406c2e6e hpsb_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x430f6228 hpsb_iso_shutdown +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x43c3d0ed hpsb_unregister_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4a016ced hpsb_alloc_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4ea4f649 hpsb_iso_n_ready +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x514d34b9 hpsb_alloc_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5870b5d5 hpsb_iso_packet_sent +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x60bad4f5 hpsb_iso_recv_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x63d0203c hpsb_iso_recv_listen_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6435bbd2 hpsb_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x66fcb4e4 hpsb_add_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x672ad148 dma_region_sync_for_device +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6c374104 hpsb_register_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7046e886 csr1212_parse_keyval +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x72b94c66 hpsb_update_config_rom +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x75f52521 hpsb_selfid_complete +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x76bc1a5c dma_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7a82bf1d hpsb_get_hostinfo_bykey +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x806e8971 hpsb_make_streampacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x84af83de hpsb_read +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x882d2346 hpsb_get_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8879f8f0 dma_region_sync_for_cpu +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8ec2b312 dma_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x93ee8f84 hpsb_protocol_class +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x940e92e3 hpsb_unregister_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x979b3052 dma_prog_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9da3495a hpsb_node_fill_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa00d68d6 hpsb_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa2e81c20 hpsb_resume_host +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa4cc3b3d hpsb_get_tlabel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa924dac6 dma_prog_region_alloc +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaa44c076 hpsb_set_hostinfo_key +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xac5134bc __hpsb_register_protocol +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xbb60b648 hpsb_iso_recv_flush +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xbba70620 dma_prog_region_free +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xbe24c03e hpsb_iso_recv_unlisten_channel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xbee0ef34 hpsb_iso_packet_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc2e63f3a hpsb_packet_success +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc50c34a9 hpsb_register_addrspace +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc669a4d3 csr1212_detach_keyval_from_directory +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcb0a2f93 hpsb_destroy_hostinfo +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcf1a751e hpsb_iso_wake +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd1300fea hpsb_node_write +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd2892f4f hpsb_iso_recv_set_channel_mask +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd95789d4 hpsb_iso_xmit_queue_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xdafdd122 hpsb_make_phypacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xde645d74 hpsb_selfid_received +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe41dd512 hpsb_iso_recv_release_packets +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe7b5f33b hpsb_iso_stop +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe8988a9b hpsb_make_lock64packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xea4152ff dma_region_init +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xed2308a8 hpsb_free_packet +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xf7afa9ef hpsb_unregister_highlevel +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfaf256a8 hpsb_make_readpacket +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfba57f51 hpsb_speedto_str +EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfd5d5e5b hpsb_make_lockpacket +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x39e004f4 ohci1394_register_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x84b4fe93 ohci1394_stop_context +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xb37ab086 ohci1394_init_iso_tasklet +EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xbb4928cf ohci1394_unregister_iso_tasklet +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x3bdf3bff rdma_addr_cancel +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x4eb5b815 rdma_translate_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x71de06c2 rdma_addr_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xb6d5b72d rdma_copy_addr +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xbe81bb46 rdma_addr_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xc2e60dc9 rdma_resolve_ip +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x1b8cac52 ib_send_cm_rej +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x246e873b ib_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x34d1803e ib_send_cm_sidr_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x41ef1634 ib_send_cm_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x45b849e3 cm_class +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x4889b2d3 ib_send_cm_rep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x4a8b35a6 ib_cm_notify +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x5a65d444 ib_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x61f2d8e7 ib_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x763d1eca ib_send_cm_lap +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x82df942b ib_send_cm_sidr_req +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x9283df06 ib_send_cm_dreq +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xbe3143e6 ib_send_cm_drep +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xc9be7f8b ib_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xd6d7569d ib_send_cm_apr +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xecbed6f5 ib_send_cm_mra +EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xf9cd1827 ib_send_cm_rtu +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0abd0439 ib_register_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0f087eaf ib_unregister_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x12d3854f ib_modify_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x16609ad5 ib_dealloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1985bedd ib_attach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1c9dafee ib_dereg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1e491a04 ib_unmap_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x23033d8c ib_umem_release +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2b823d78 ib_query_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x317c8222 ib_set_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x327ecbeb ib_query_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x36e31176 ib_get_dma_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3a1cf218 ib_alloc_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3e00c04c ib_flush_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3f7567fd ib_rate_to_mult +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x47a1ec7b ib_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x520b2638 ib_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x55980089 ib_alloc_fmr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5af8df3f ib_modify_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5b344fa9 ib_modify_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5c27f061 ib_create_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5dbb2d1c ib_get_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5f3a53b6 ib_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x60364d3a ib_alloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x65cc3b0d ib_rereg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6b37891e ib_query_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7284d669 ib_query_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x73821bca ib_detach_mcast +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7479118e ib_query_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x798d6152 ib_query_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7a86034e ib_query_port +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7b83977d ib_alloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7f1b0d06 ib_destroy_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x82a8e504 ib_query_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8640eaeb ib_modify_qp_is_ok +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x87b614d8 ib_ud_header_pack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8c5a84f9 ib_dispatch_event +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8f1681d1 ib_alloc_fast_reg_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x90ef4005 ib_get_cached_lmc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x917969c8 ib_dealloc_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9401753b ib_create_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x96ce6c46 rdma_node_get_transport +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9701941f ib_create_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x997d3197 ib_unregister_device +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9a4b4906 ib_umem_page_count +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d804fa1 mult_to_ib_rate +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9ed68464 ib_init_ah_from_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa0fc8ce7 ib_free_fast_reg_page_list +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa1096824 ib_alloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa1c2c830 ib_get_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa475933b ib_get_client_data +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa4ab99d6 ib_find_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xab04115a ib_destroy_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xae844dd4 ib_destroy_ah +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xaf83a13f ib_dealloc_mw +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb1a312e1 ib_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb4128a48 ib_find_cached_gid +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb6b7f64e ib_fmr_pool_map_phys +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xc66d588d ib_destroy_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xca16dec8 ib_dealloc_pd +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xcbb8134b ib_resize_cq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xce78afc7 ib_fmr_pool_unmap +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xce7fd731 ib_find_cached_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd064d78b ib_modify_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd17ba9d1 ib_ud_header_init +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd4fb2330 ib_create_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xda6fdea1 ib_find_pkey +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdfe430b9 ib_create_fmr_pool +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe0dd6ec8 ib_destroy_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf0e14520 ib_umem_get +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf36498b9 ib_ud_header_unpack +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xfca5222b ib_create_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xfe3c7788 ib_register_event_handler +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xfebbcd73 ib_modify_srq +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xfee611d6 ib_reg_phys_mr +EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xfef863ff ib_modify_device +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x26b144c5 ib_register_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x4b4601f9 ib_unregister_mad_agent +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x4b941086 ib_free_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x4c71a941 ib_create_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x58532d87 ib_modify_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6ef787ed ib_response_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6f077fcf ib_get_mad_data_offset +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x782474af ib_redirect_mad_qp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x7b5d4b7a ib_is_mad_class_rmpp +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x80d7baed ib_post_send_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x81c54f40 ib_free_recv_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xcfd92daa ib_cancel_mad +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xd3f5bc9d ib_get_rmpp_segment +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xeb0b6d81 ib_process_mad_wc +EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xec5683de ib_register_mad_snoop +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x05d3e961 ib_sa_cancel_query +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x16199856 ib_sa_register_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x3d21864a ib_init_ah_from_mcmember +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x512ba124 ib_sa_unregister_client +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x576fdbac ib_sa_free_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x99b39d3f ib_sa_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xac45fca2 ib_init_ah_from_path +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xc685f2ae ib_sa_get_mcmember_rec +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xcdba81ea ib_sa_service_rec_query +EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xe6fe560b ib_sa_path_rec_get +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x02f847bc ib_copy_path_rec_from_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x07cf5a51 ib_copy_ah_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x18382f6a ib_copy_path_rec_to_user +EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x184f3575 ib_copy_qp_attr_to_user +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x207b729c iw_cm_reject +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xa1c4c729 iw_cm_accept +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xa893a63c iw_cm_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xb0101569 iw_cm_disconnect +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xc79b2720 iw_cm_listen +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xc88f1b56 iw_cm_connect +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xca31828d iw_create_cm_id +EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xe921a4fc iw_destroy_cm_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x0a7497fc rdma_destroy_qp +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x255e7612 rdma_disconnect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x28e50324 rdma_create_qp +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x6a456fbe rdma_set_service_type +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x6d695016 rdma_listen +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x74cec268 rdma_resolve_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x7662b5d5 rdma_reject +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x7c357fee rdma_join_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x9085f308 rdma_bind_addr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x99274b04 rdma_resolve_route +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x9af16f4e rdma_accept +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xa1e1de85 rdma_notify +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xaf86b94a rdma_set_ib_paths +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb6bcbefb rdma_connect +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb6c84c04 rdma_create_id +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd0927a6a rdma_leave_multicast +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd8cc85ed rdma_init_qp_attr +EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd920169e rdma_destroy_id +EXPORT_SYMBOL drivers/input/gameport/gameport 0x06a1303e __gameport_register_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0x40a47397 gameport_unregister_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0x633cc719 gameport_stop_polling +EXPORT_SYMBOL drivers/input/gameport/gameport 0x72485c8e gameport_start_polling +EXPORT_SYMBOL drivers/input/gameport/gameport 0x7254b178 gameport_open +EXPORT_SYMBOL drivers/input/gameport/gameport 0x7d16420e __gameport_register_driver +EXPORT_SYMBOL drivers/input/gameport/gameport 0x85ac5c7b gameport_unregister_port +EXPORT_SYMBOL drivers/input/gameport/gameport 0xca9ac24a gameport_set_phys +EXPORT_SYMBOL drivers/input/gameport/gameport 0xcb8828df gameport_close +EXPORT_SYMBOL drivers/input/input-polldev 0x2fc04871 input_allocate_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0x4cf45a2c input_register_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0x7cc79789 input_free_polled_device +EXPORT_SYMBOL drivers/input/input-polldev 0xb14bebe0 input_unregister_polled_device +EXPORT_SYMBOL drivers/isdn/capi/capifs 0x2c54c957 capifs_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/capifs 0xd0bc06ce capifs_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x0220f1f6 detach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x04403fcf unregister_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x0485ca1e capi_ctr_handle_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x14f2aa5a capi20_get_version +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2b8eab1f capilib_free_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x2baa6586 capilib_new_ncci +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x31c24aa4 capi20_isinstalled +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x3515dfe9 capi_ctr_resume_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x37ff1972 capi_ctr_reseted +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x3a63f766 capi20_put_message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x47d3fc51 capi_info2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x50b33ca4 capi_cmsg2message +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x5c61eeb8 capi_ctr_ready +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x6057c6f3 capi_message2cmsg +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x62e32d43 capilib_data_b3_conf +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x71e8d5ba capilib_data_b3_req +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x756995e7 capi20_register +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7a33596c capi20_get_serial +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x7e6f1307 capi20_get_manufacturer +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8cc1d275 capi20_set_callback +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x8f699913 capilib_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x9bef1b44 capi20_release +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0x9f823278 register_capi_driver +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xa51aaa66 attach_capi_ctr +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xa7c4fd6c capi_message2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xaa165d27 capilib_release_appl +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb19fda8d capi_cmd2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xb60e5e5f capi_cmsg_header +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xc10fe128 cdebbuf_free +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xc45900b4 capi_ctr_suspend_output +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe19a11ac capi20_get_profile +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xe8ad9bd1 capi_cmsg2str +EXPORT_SYMBOL drivers/isdn/capi/kernelcapi 0xed061606 capi20_manufacturer +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x1eb37dd1 b1_parse_version +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x23ecfd12 b1_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x31456c93 b1_load_config +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x322d25b0 b1_getrevision +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x5da56bc0 b1ctl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x610c1462 b1_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x65d15ddd b1_alloc_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x69383af4 b1_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x7b992791 avmcard_dma_alloc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x85f09690 b1_irq_table +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x96f9d2f4 b1_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0x9882112e b1_loaded +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xa066f0b7 avmcard_dma_free +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xaf296bc9 b1_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xb4dc7306 b1_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xb6857262 b1_free_card +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xd8a17124 b1_load_t4file +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1 0xdfd28376 b1_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x000d48d0 b1dma_reset +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x0791bd66 t1pci_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x1832f097 b1dma_load_firmware +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x2a386384 b1dma_interrupt +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x2b86cc54 b1dmactl_read_proc +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0x9d83dc62 b1dma_release_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xb3fc872d b1pciv4_detect +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xc0e94d3a b1dma_reset_ctr +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xce4d8433 b1dma_register_appl +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1dma 0xe999662f b1dma_send_message +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0x29562993 b1pcmcia_delcard +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xaec3240e b1pcmcia_addcard_m1 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xea620116 b1pcmcia_addcard_m2 +EXPORT_SYMBOL drivers/isdn/hardware/avm/b1pcmcia 0xf14bf8b1 b1pcmcia_addcard_b1 +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0x2974ead1 DIVA_DIDD_Read +EXPORT_SYMBOL drivers/isdn/hardware/eicon/divadidd 0x53680b44 proc_net_eicon +EXPORT_SYMBOL drivers/isdn/hardware/mISDN/hfcmulti 0x5293ed86 plx_lock +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x07f4f2ce hisax_unregister +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x148f0c99 FsmFree +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x2844a899 FsmInitTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x93a64734 FsmChangeState +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0x9df0cd27 FsmEvent +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xa5c29ba8 hisax_init_pcmcia +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xc0c558f9 FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xd94696e8 FsmDelTimer +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xee93522c hisax_register +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xf0a16657 FsmNew +EXPORT_SYMBOL drivers/isdn/hisax/hisax 0xfc27303b HiSax_closecard +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x0ea26d6a isacsx_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x3f3b323a isac_d_l2l1 +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x8518c1d5 isac_init +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x8de61c11 isac_irq +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0x99a1568a isac_setup +EXPORT_SYMBOL drivers/isdn/hisax/hisax_isac 0xd4e9e6b5 isacsx_irq +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x1ee629e2 isdnhdlc_rcv_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x95aed401 isdnhdlc_decode +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0x9ffc8215 isdnhdlc_out_init +EXPORT_SYMBOL drivers/isdn/hisax/isdnhdlc 0xf5c8131d isdnhdlc_encode +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x0d9a4807 isdn_ppp_register_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x3e2810a7 register_isdn +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0x5572168b isdn_ppp_unregister_compressor +EXPORT_SYMBOL drivers/isdn/i4l/isdn 0xfa06820f isdn_register_divert +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x05021179 mISDN_unregister_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x0c3a94ad create_l1 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x1c2ccdf9 get_next_bframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x2348cc3c mISDN_FsmFree +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x27cdf4dd recv_Dchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x3ea336fd mISDN_FsmAddTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x429129f2 mISDN_FsmRestartTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x44240073 mISDN_freebchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x50c2230c mISDN_FsmChangeState +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x5f4a6d0f recv_Dchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x650007f3 recv_Bchannel_skb +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x7129f1e6 mISDN_initbchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x815e6fc9 mISDN_register_device +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0x9d395d71 l1_event +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xaaa52db6 mISDN_freedchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xace35cae mISDN_FsmDelTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xaeb8889e bchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xb805b62e mISDN_initdchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xc185a544 mISDN_unregister_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xcb8d1ca2 confirm_Bsend +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xcdab705c queue_ch_frame +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd5145151 mISDN_FsmEvent +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xd9a7fbfd mISDN_FsmInitTimer +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xe3341996 get_next_dframe +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xe9154c91 dchannel_senddata +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xf7be0b63 recv_Bchannel +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xf9e7832f mISDN_FsmNew +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_core 0xff7ebd2e mISDN_register_Bprotocol +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x4c2ec443 mISDN_dsp_element_register +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0x60721da7 dsp_audio_law_to_s32 +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xa215f1b2 dsp_audio_s16_to_law +EXPORT_SYMBOL drivers/isdn/mISDN/mISDN_dsp 0xd3a023b8 mISDN_dsp_element_unregister +EXPORT_SYMBOL drivers/md/dm-log 0x2df72eed dm_dirty_log_type_register +EXPORT_SYMBOL drivers/md/dm-log 0x6f2314c5 dm_dirty_log_destroy +EXPORT_SYMBOL drivers/md/dm-log 0xe56cc588 dm_dirty_log_type_unregister +EXPORT_SYMBOL drivers/md/dm-log 0xf4ca1103 dm_dirty_log_create +EXPORT_SYMBOL drivers/md/dm-mod 0x00b6736a dm_table_get_mode +EXPORT_SYMBOL drivers/md/dm-mod 0x085eae2e dm_unregister_target +EXPORT_SYMBOL drivers/md/dm-mod 0x1a1d7bed dm_io_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0x2a775799 dm_register_target +EXPORT_SYMBOL drivers/md/dm-mod 0x32769bb6 dm_table_get +EXPORT_SYMBOL drivers/md/dm-mod 0x3759ab8b dm_kcopyd_copy +EXPORT_SYMBOL drivers/md/dm-mod 0x445655d8 dm_put_device +EXPORT_SYMBOL drivers/md/dm-mod 0x54809a4f dm_table_put +EXPORT_SYMBOL drivers/md/dm-mod 0x78f0889f dm_kcopyd_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x82f65633 dm_io_client_resize +EXPORT_SYMBOL drivers/md/dm-mod 0x8d24980b dm_get_mapinfo +EXPORT_SYMBOL drivers/md/dm-mod 0x941f1211 dm_table_event +EXPORT_SYMBOL drivers/md/dm-mod 0x954c8af3 dm_io_client_destroy +EXPORT_SYMBOL drivers/md/dm-mod 0x98a666aa dm_get_device +EXPORT_SYMBOL drivers/md/dm-mod 0x9e4e02c6 dm_table_get_size +EXPORT_SYMBOL drivers/md/dm-mod 0xa33fa915 dm_table_get_md +EXPORT_SYMBOL drivers/md/dm-mod 0xc79bcd36 dm_vcalloc +EXPORT_SYMBOL drivers/md/dm-mod 0xf16b3101 dm_io +EXPORT_SYMBOL drivers/md/dm-mod 0xfa7e5429 dm_kcopyd_client_create +EXPORT_SYMBOL drivers/md/dm-mod 0xfbe83dd9 dm_table_unplug_all +EXPORT_SYMBOL drivers/md/md-mod 0x000b6bdd md_error +EXPORT_SYMBOL drivers/md/md-mod 0x05c67657 md_check_recovery +EXPORT_SYMBOL drivers/md/md-mod 0x1040b1c4 unregister_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0x1a2e3382 md_done_sync +EXPORT_SYMBOL drivers/md/md-mod 0x2062767e bitmap_startwrite +EXPORT_SYMBOL drivers/md/md-mod 0x31146959 register_md_personality +EXPORT_SYMBOL drivers/md/md-mod 0x42076a4e md_write_end +EXPORT_SYMBOL drivers/md/md-mod 0x5be56222 md_register_thread +EXPORT_SYMBOL drivers/md/md-mod 0x74be727f bitmap_unplug +EXPORT_SYMBOL drivers/md/md-mod 0x77ba351e bitmap_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0x7af9dd3f bitmap_close_sync +EXPORT_SYMBOL drivers/md/md-mod 0x7f244a4e md_wait_for_blocked_rdev +EXPORT_SYMBOL drivers/md/md-mod 0x8a548e71 bitmap_start_sync +EXPORT_SYMBOL drivers/md/md-mod 0x8a6c48cc md_unregister_thread +EXPORT_SYMBOL drivers/md/md-mod 0xa92f2bd1 md_write_start +EXPORT_SYMBOL drivers/md/md-mod 0xafc03775 bitmap_cond_end_sync +EXPORT_SYMBOL drivers/md/md-mod 0xc45b401e bitmap_endwrite +EXPORT_SYMBOL drivers/md/md-mod 0xe62748cc md_wakeup_thread +EXPORT_SYMBOL drivers/media/common/tuners/mt2060 0x0e9358d8 mt2060_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2131 0xf8af05c6 mt2131_attach +EXPORT_SYMBOL drivers/media/common/tuners/mt2266 0x65a1df14 mt2266_attach +EXPORT_SYMBOL drivers/media/common/tuners/mxl5005s 0xcf8fad4d mxl5005s_attach +EXPORT_SYMBOL drivers/media/common/tuners/qt1010 0x60a074a7 qt1010_attach +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0x0cb4b189 tuners +EXPORT_SYMBOL drivers/media/common/tuners/tuner-types 0xc2821775 tuner_count +EXPORT_SYMBOL drivers/media/common/tuners/tuner-xc2028 0xa4035e83 xc2028_attach +EXPORT_SYMBOL drivers/media/common/tuners/xc5000 0x69944093 xc5000_attach +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x1ab4336d flexcop_device_exit +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x30c66bc6 flexcop_pass_dmx_packets +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x323925e1 flexcop_dump_reg +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x54c568ea flexcop_i2c_request +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0x66d213b1 flexcop_sram_set_dest +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xa189d5af flexcop_device_initialize +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xa29915cf flexcop_dma_allocate +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xa97e6165 flexcop_device_kfree +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xaa23f11d flexcop_device_kmalloc +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xb2c5d1c4 flexcop_dma_control_size_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xbf41dc46 flexcop_dma_control_timer_irq +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xc9523de4 flexcop_dma_xfer_control +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xc9903536 flexcop_dma_free +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xcbf3d13e flexcop_sram_ctrl +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xe4853699 flexcop_pass_dmx_data +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xf51d3575 flexcop_eeprom_check_mac_addr +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xf6fd21f7 flexcop_wan_set_speed +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xf9211cae flexcop_dma_config +EXPORT_SYMBOL drivers/media/dvb/b2c2/b2c2-flexcop 0xfa128589 flexcop_dma_config_timer +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x2f500f9a bt878_device_control +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x5735e825 bt878_stop +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0x8d0780c9 bt878_start +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xc311ec44 bt878 +EXPORT_SYMBOL drivers/media/dvb/bt8xx/bt878 0xd5d0bdef bt878_num +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x379ca206 dst_wait_dst_ready +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x3a346675 read_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x71d8b189 dst_comm_init +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x7660f716 rdc_reset_state +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0x95d380b8 write_dst +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xa17aa01a dst_attach +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xa7adad0d dst_error_bailout +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xccba98f3 dst_pio_disable +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xe94b8c9c dst_check_sum +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst 0xf4fb36bb dst_error_recovery +EXPORT_SYMBOL drivers/media/dvb/bt8xx/dst_ca 0xd37cd8ab dst_ca_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x021f0c91 dvb_dmxdev_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x14eb630c dvb_ringbuffer_free +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x1b079b49 dvb_dmxdev_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x2f56f3de dvb_unregister_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x326600be dvb_register_adapter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x36c8ea1f dvb_frontend_sleep_until +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x53f96f8e dvb_register_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x614d0eba dvb_generic_open +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x635eb40e dvb_dmx_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x66817207 dvb_ca_en50221_camchange_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6f7f7d73 dvb_ringbuffer_empty +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x6f9c72e3 dvb_ringbuffer_read +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x74a5a698 dvb_filter_pes2ts_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x75599a1e dvb_ca_en50221_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x80e3832d dvb_filter_get_ac3info +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x8401a1d9 dvb_net_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x8b49a23f timeval_usec_diff +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x923aa88e dvb_ringbuffer_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x9268ac1f dvb_unregister_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x98e30933 dvb_net_release +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0x9cbff999 dvb_dmx_swfilter_204 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xa38332a1 dvb_ca_en50221_camready_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xa7f60cb0 dvb_register_device +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xaba4e68d dvb_frontend_detach +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xac4ca1b0 intlog2 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb2db2592 dvb_ringbuffer_write +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb56f0404 dvb_dmx_swfilter_packets +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xb5b95805 dvb_ringbuffer_read_user +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xbed559e1 dvb_dmx_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc938e566 dvb_dmx_swfilter +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc97f3e02 dvb_frontend_reinitialise +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xc9b4e292 dvb_generic_ioctl +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xce23804d dvb_unregister_frontend +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xdd54bc08 dvb_ca_en50221_init +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xdf56156a dvb_ca_en50221_frda_irq +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe5ae8707 intlog10 +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xe7949e59 dvb_ringbuffer_flush_spinlock_wakeup +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xeb7daf80 dvb_ringbuffer_avail +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xf826deb0 dvb_filter_pes2ts +EXPORT_SYMBOL drivers/media/dvb/dvb-core/dvb-core 0xf97edec1 dvb_generic_release +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x12a978b4 dvb_usb_nec_rc_key_to_event +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x22edf304 dvb_usb_generic_write +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x522338fd dvb_usb_device_exit +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0x62ad06d1 dvb_usb_get_hexline +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0xb6c855fd dvb_usb_generic_rw +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0xbfe87f43 usb_cypress_load_firmware +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb 0xc9f59ae5 dvb_usb_device_init +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0x2edc4728 af9005_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0xd3383957 af9005_rc_keys_size +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote 0xe9dc0025 af9005_rc_decode +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x00ec41db dibusb2_0_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x1b10c044 dibusb_dib3000mc_tuner_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x213960af dibusb_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x622d0d01 dibusb_pid_filter_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x77646865 dibusb_read_eeprom_byte +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0x893ece4b dibusb_dib3000mc_frontend_attach +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xaa16e138 dibusb_power_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xb59ed90a dibusb_pid_filter +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xd4d3dddc dibusb_rc_keys +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xdccaed9f dibusb_rc_query +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xef9d66c0 dibusb2_0_streaming_ctrl +EXPORT_SYMBOL drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common 0xfe804c68 dibusb_i2c_algo +EXPORT_SYMBOL drivers/media/dvb/frontends/au8522 0x2d212698 au8522_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/bcm3510 0xedeb2bdc bcm3510_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22700 0x4c4ffc69 cx22700_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx22702 0xd28ffdd3 cx22702_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24110 0xc7a25bf4 cx24110_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0x48ed7dcf cx24123_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/cx24123 0xcb111c38 cx24123_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0xb64f768a dib0070_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib0070 0xbfeb2620 dib0070_wbd_offset +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mb 0xf26f348c dib3000mb_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x115d992d dib3000mc_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x21c40189 dib3000mc_set_config +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x9811aae3 dib3000mc_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0x9b53841c dib3000mc_get_tuner_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xbc72fc2d dib3000mc_pid_control +EXPORT_SYMBOL drivers/media/dvb/frontends/dib3000mc 0xdd7b402b dib3000mc_pid_parse +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x09ab0155 dib7000m_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0x6a4147a6 dib7000m_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000m 0xc1114ea0 dib7000m_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x0dc76195 dib7000p_get_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x3808770e dib7000pc_detection +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x3bf2a8fb dib7000p_i2c_enumeration +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x3d957d4e dib7000p_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0x5e26a854 dib7000p_set_gpio +EXPORT_SYMBOL drivers/media/dvb/frontends/dib7000p 0xfd0d3478 dib7000p_set_wbd_ref +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0x13951ebe dibx000_init_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0x6be18708 dibx000_get_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/dibx000_common 0xd4419523 dibx000_exit_i2c_master +EXPORT_SYMBOL drivers/media/dvb/frontends/drx397xD 0x1b77758a drx397xD_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/dvb-pll 0xeb4d4cc8 dvb_pll_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6405 0x8c2962f3 isl6405_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/isl6421 0x1ba9f3ae isl6421_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/itd1000 0xcd16a25c itd1000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/l64781 0x4903e4fc l64781_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lgdt330x 0xf530314d lgdt330x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/lnbp21 0x5dcb58ca lnbp21_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt312 0xcaf80f9e mt312_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/mt352 0xd061f8a0 mt352_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt200x 0xd707be15 nxt200x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/nxt6000 0xa1fefffc nxt6000_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51132 0x08a6e037 or51132_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/or51211 0x63b74831 or51211_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1409 0xb49a2395 s5h1409_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1411 0x01971eb1 s5h1411_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0x157ad2cd s5h1420_get_tuner_i2c_adapter +EXPORT_SYMBOL drivers/media/dvb/frontends/s5h1420 0xe3be3564 s5h1420_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/sp8870 0x3d707c18 sp8870_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/sp887x 0xde624d84 sp887x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0297 0x0820f94e stv0297_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/stv0299 0x280d8574 stv0299_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10021 0x8f1007cd tda10021_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10023 0x03601603 tda10023_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10048 0xea3b36f6 tda10048_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0x8af1a7e4 tda10046_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda1004x 0xf1015f3e tda10045_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda10086 0xbdb65cc5 tda10086_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda8083 0x8e330a76 tda8083_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tda826x 0xfa98cdaa tda826x_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/tua6100 0x7ba989b3 tua6100_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1820 0xf06930ac ves1820_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/ves1x93 0x553d8c47 ves1x93_attach +EXPORT_SYMBOL drivers/media/dvb/frontends/zl10353 0x98991754 zl10353_attach +EXPORT_SYMBOL drivers/media/dvb/ttpci/ttpci-eeprom 0x51abea26 ttpci_eeprom_parse_mac +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0x53cdaf04 ttusbdecfe_dvbs_attach +EXPORT_SYMBOL drivers/media/dvb/ttusb-dec/ttusbdecfe 0x780aaece ttusbdecfe_dvbt_attach +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x11dc4b6d bttv_gpio_enable +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x8b028bac bttv_sub_unregister +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x8ecf4acc bttv_write_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0x9bb591d7 bttv_get_pcidev +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xbcf2d2fb bttv_read_gpio +EXPORT_SYMBOL drivers/media/video/bt8xx/bttv 0xec7eb6a1 bttv_sub_register +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x495e4b0c btcx_calc_skips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0x5446074c btcx_riscmem_free +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xad2fe38b btcx_sort_clips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xc368f8e6 btcx_align +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xcda0ded2 btcx_screen_clips +EXPORT_SYMBOL drivers/media/video/btcx-risc 0xf3004982 btcx_riscmem_alloc +EXPORT_SYMBOL drivers/media/video/cpia 0x734b4107 cpia_unregister_camera +EXPORT_SYMBOL drivers/media/video/cpia 0xfbbf55b6 cpia_register_camera +EXPORT_SYMBOL drivers/media/video/cx18/cx18 0x2cdea06d cx18_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/cx2341x 0x0224a947 cx2341x_update +EXPORT_SYMBOL drivers/media/video/cx2341x 0x3559ba71 cx2341x_ext_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0x8fdbede1 cx2341x_fill_defaults +EXPORT_SYMBOL drivers/media/video/cx2341x 0xcf8b77a4 cx2341x_mpeg_ctrls +EXPORT_SYMBOL drivers/media/video/cx2341x 0xde1da524 cx2341x_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx2341x 0xeacc6fab cx2341x_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/cx2341x 0xfb8bd71f cx2341x_log_status +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x53a2852c cx23885_set_freq +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x54a718d5 cx23885_enum_input +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0x74138fbe cx23885_get_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xe12fa84c cx23885_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xf7c35382 cx23885_set_control +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xfb885537 cx23885_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx23885/cx23885 0xfe603e28 cx23885_video_mux +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0xc6f3dc94 vp3054_i2c_probe +EXPORT_SYMBOL drivers/media/video/cx88/cx88-vp3054-i2c 0xd0fea167 vp3054_i2c_remove +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x09baa99c cx88_get_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x24e79dbb cx88_video_mux +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x28180715 cx88_set_control +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0x4abbebd1 cx88_set_freq +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xac4e53b9 cx88_user_ctrls +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xf78b6ae4 cx88_enum_input +EXPORT_SYMBOL drivers/media/video/cx88/cx8800 0xfb8eb11c cx8800_ctrl_query +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x6e8a0da2 cx8802_get_device +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x7a9140a8 cx8802_buf_prepare +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x88b7c5af cx8802_cancel_buffers +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0x963ea034 cx8802_buf_queue +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0xb98c7abe cx8802_get_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0xd2413c8f cx8802_register_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx8802 0xf35181b5 cx8802_unregister_driver +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x0840dabb cx88_get_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x0c4048c8 cx88_newstation +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x1f0bd61c cx88_risc_databuffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x27104c97 cx88_set_stereo +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x301778d3 cx88_set_scale +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x38c5cae9 cx88_vdev_init +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x4abac376 cx88_core_irq +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x65ba787e cx88_free_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x6721cf8c cx88_core_put +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7b5cdee1 cx88_tuner_callback +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x7f344972 cx88_reset +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x8cbe40b6 cx88_set_tvnorm +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x904b8696 cx88_audio_thread +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x90d671c0 cx88_ir_start +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0x9b140fff cx88_sram_channels +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xa91ab549 cx88_wakeup +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xb47f6cda cx88_print_irqbits +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xbee6dfdd cx88_risc_stopper +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xc188b426 cx88_set_tvaudio +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xcccd9e20 cx88_ir_stop +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xe1aa492d cx88_call_i2c_clients +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xe3ba4f80 cx88_shutdown +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xe4e4a06b cx88_sram_channel_dump +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xf48048f5 cx88_core_get +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xf9c20a1d cx88_risc_buffer +EXPORT_SYMBOL drivers/media/video/cx88/cx88xx 0xfd3d5b24 cx88_sram_channel_setup +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0x08e723f8 em28xx_unregister_extension +EXPORT_SYMBOL drivers/media/video/em28xx/em28xx 0x5b03055f em28xx_register_extension +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x02edf661 gspca_suspend +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x12149aa2 gspca_frame_add +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x3c55d352 gspca_resume +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x8eb44d2d gspca_auto_gain_n_exposure +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x9101e352 gspca_dev_probe +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x9670af2c gspca_debug +EXPORT_SYMBOL drivers/media/video/gspca/gspca_main 0x9b314ad8 gspca_disconnect +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0477f604 ivtv_reset_ir_gpio +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0538e449 ivtv_cards_lock +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x0f9a0da5 ivtv_api +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x14f67530 ivtv_debug +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x167053e0 ivtv_clear_irq_mask +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x18b7c243 ivtv_udma_alloc +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x3fbac5dd ivtv_init_on_first_open +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x5aedfd1c ivtv_cards +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x6a7aa93b ivtv_udma_prepare +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x70196ffb ivtv_cards_active +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x7fb33bac ivtv_vapi_result +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x8bf2b533 ivtv_udma_setup +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0x9f4dadc8 ivtv_set_irq_mask +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xd64ec021 ivtv_vapi +EXPORT_SYMBOL drivers/media/video/ivtv/ivtv 0xfb701dce ivtv_udma_unmap +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x1211df5d saa7134_devlist +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x191129ae saa7134_set_dmabits +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x1e9b20af saa7134_pgtable_build +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x539b52e3 saa7134_ts_register +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x6386c7ac saa7134_i2c_call_clients +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x6e203bdb saa7134_set_gpio +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x85593767 saa7134_tuner_callback +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x89e50cd8 saa7134_tvaudio_setmute +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0x98af79c1 saa7134_boards +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xa3aa48b0 saa7134_ts_unregister +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xb510919e saa7134_dmasound_exit +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xcf6863d3 saa_dsp_writel +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xe0cb76e3 saa7134_pgtable_free +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xe43c9db8 saa7134_pgtable_alloc +EXPORT_SYMBOL drivers/media/video/saa7134/saa7134 0xe5d69c19 saa7134_dmasound_init +EXPORT_SYMBOL drivers/media/video/soc_camera 0x077fa08b soc_camera_video_start +EXPORT_SYMBOL drivers/media/video/soc_camera 0x747b4fc2 soc_camera_host_unregister +EXPORT_SYMBOL drivers/media/video/soc_camera 0xa6a49a09 soc_camera_host_register +EXPORT_SYMBOL drivers/media/video/soc_camera 0xfa84b8d1 soc_camera_device_unregister +EXPORT_SYMBOL drivers/media/video/soc_camera 0xfd7c1778 soc_camera_video_stop +EXPORT_SYMBOL drivers/media/video/soc_camera 0xfe5b0d8d soc_camera_device_register +EXPORT_SYMBOL drivers/media/video/tveeprom 0x07ef8b93 tveeprom_hauppauge_analog +EXPORT_SYMBOL drivers/media/video/tveeprom 0xaaa1bf12 tveeprom_read +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x16a2915c RingQueue_Dequeue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x20a9044a usbvideo_AllocateDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x28ea52bd usbvideo_Deregister +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x407a321c RingQueue_WakeUpInterruptible +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x5488b743 usbvideo_RegisterVideoDevice +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x69fc0c76 usbvideo_DeinterlaceFrame +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0x7654babf usbvideo_register +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xdcd51e95 usbvideo_TestPattern +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xddecac6d RingQueue_Enqueue +EXPORT_SYMBOL drivers/media/video/usbvideo/usbvideo 0xf5011f67 RingQueue_Flush +EXPORT_SYMBOL drivers/media/video/v4l1-compat 0x0a7ee450 v4l_compat_translate_ioctl +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x03165a85 v4l2_ctrl_get_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x0dfb5e57 v4l2_prio_max +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x1c427ecb v4l2_ctrl_query_fill +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2de2b633 v4l2_prio_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x2e9a955d v4l2_prio_close +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x3c125569 v4l2_chip_ident_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x42c8e001 v4l2_ctrl_next +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x48e078dc v4l2_i2c_attach +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x57abfbd8 v4l2_chip_match_host +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x5fef1b4a v4l2_ctrl_query_fill_std +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x7dd84b1d v4l2_chip_match_i2c_client +EXPORT_SYMBOL drivers/media/video/v4l2-common 0x942892ab v4l2_prio_open +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xb2d1e17e v4l2_prio_change +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xc369097d v4l2_ctrl_check +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xd464e760 v4l2_ctrl_query_menu +EXPORT_SYMBOL drivers/media/video/v4l2-common 0xe330bce9 v4l2_prio_init +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0x12812973 videobuf_dvb_unregister +EXPORT_SYMBOL drivers/media/video/videobuf-dvb 0x1d384b1e videobuf_dvb_register +EXPORT_SYMBOL drivers/media/video/videocodec 0x02ef66f1 videocodec_register +EXPORT_SYMBOL drivers/media/video/videocodec 0x7eae4aa3 videocodec_attach +EXPORT_SYMBOL drivers/media/video/videocodec 0xc32950f9 videocodec_unregister +EXPORT_SYMBOL drivers/media/video/videocodec 0xe40bb4f6 videocodec_detach +EXPORT_SYMBOL drivers/media/video/videodev 0x0a834279 video_device_alloc +EXPORT_SYMBOL drivers/media/video/videodev 0x123959a1 v4l2_type_names +EXPORT_SYMBOL drivers/media/video/videodev 0x2c8ca6aa video_register_device +EXPORT_SYMBOL drivers/media/video/videodev 0x3adbd595 v4l2_field_names +EXPORT_SYMBOL drivers/media/video/videodev 0x5ebefe4b v4l_printk_ioctl +EXPORT_SYMBOL drivers/media/video/videodev 0x6002bcd7 video_ioctl2 +EXPORT_SYMBOL drivers/media/video/videodev 0x643f2058 video_unregister_device +EXPORT_SYMBOL drivers/media/video/videodev 0x66afd37d video_device_release +EXPORT_SYMBOL drivers/media/video/videodev 0x6f3026cd video_exclusive_release +EXPORT_SYMBOL drivers/media/video/videodev 0x845f7108 video_devdata +EXPORT_SYMBOL drivers/media/video/videodev 0x89575e25 video_usercopy +EXPORT_SYMBOL drivers/media/video/videodev 0x900b74eb video_exclusive_open +EXPORT_SYMBOL drivers/media/video/videodev 0xc0858de2 video_register_device_index +EXPORT_SYMBOL drivers/media/video/videodev 0xe2b92059 v4l2_video_std_construct +EXPORT_SYMBOL drivers/media/video/videodev 0xf3251e7b v4l2_norm_to_name +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x04184585 mpt_GetIocState +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x0cb24233 mpt_print_ioc_summary +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x0d2d762e mpt_detach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x1444a8b6 mpt_send_handshake_request +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x17fd1199 mpt_resume +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x31fa744f mpt_config +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x375d8126 mpt_add_sge +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x3caa2f7b mpt_HardResetHandler +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4526289b mpt_event_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x59937905 mpt_raid_phys_disk_pg0 +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x629df657 mpt_device_driver_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x6f8174bc mpt_attach +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x7b7e3617 mpt_put_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x7c1e1fe4 mpt_findImVolumes +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x8557178c mpt_free_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x8cd0532f mpt_event_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x959a176f mpt_get_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0x98ce2820 mpt_put_msg_frame_hi_pri +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xa19ca22f mpt_suspend +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xa47389ff mpt_alloc_fw_memory +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xaa32bafe mpt_verify_adapter +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc042e0d9 mptbase_sas_persist_operation +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc0e69f82 mpt_device_driver_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc1a06c81 mpt_free_msg_frame +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc47c22e8 mpt_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd9a92a75 mpt_reset_deregister +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdd805159 ioc_list +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xebfff223 mpt_register +EXPORT_SYMBOL drivers/message/fusion/mptbase 0xfca0bc1c mpt_reset_register +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x06ede0f8 mptscsih_scandv_complete +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x12dfebf5 mptscsih_bios_param +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x13724d6e mptscsih_slave_destroy +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x176d428a mptscsih_suspend +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x20b70fe0 mptscsih_host_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x2e0acb8c mptscsih_abort +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x353dc032 mptscsih_remove +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x54fdfaa5 mptscsih_event_process +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x5aeeb309 mptscsih_bus_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x5ccb710b mptscsih_TMHandler +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6169703a mptscsih_qcmd +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x764ddf1a mptscsih_timer_expired +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x7dbeb2fb mptscsih_taskmgmt_complete +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x8db77bab mptscsih_change_queue_depth +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x9c2f8f13 mptscsih_is_phys_disk +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x9da4410c mptscsih_shutdown +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xa3096dfd mptscsih_ioc_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xae8f3f52 mptscsih_slave_configure +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xb34acae8 mptscsih_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xb6ae4ec7 mptscsih_dev_reset +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xbea753a4 mptscsih_host_attrs +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xde420a7e mptscsih_proc_info +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe917d11f mptscsih_resume +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xeec05eda mptscsih_raid_id_to_num +EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xfd8c6fc6 mptscsih_io_done +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x15bdbff2 i2o_driver_unregister +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2516a54d i2o_parm_field_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x26853593 i2o_msg_get_wait +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2a843bef i2o_dump_message +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x32f957aa i2o_driver_notify_device_remove_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x454118f3 i2o_driver_notify_controller_add_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x4ef5ee51 i2o_parm_table_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x5167ddae i2o_status_get +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x557ef7ef i2o_find_iop +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x60db5d56 i2o_event_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x6cdde922 i2o_driver_notify_controller_remove_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x78abeba4 i2o_device_claim_release +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x7ee094f6 i2o_device_claim +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x9450eb74 i2o_iop_find_device +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb4c00dcf i2o_controllers +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xd6401921 i2o_msg_post_wait_mem +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xda43b622 i2o_parm_issue +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xea0581dd i2o_driver_notify_device_add_all +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xf6a1c366 i2o_driver_register +EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xf76d1843 i2o_exec_lct_get +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x49535091 pasic3_write_register +EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x827482b6 pasic3_read_register +EXPORT_SYMBOL drivers/misc/ioc4 0x957be955 ioc4_register_submodule +EXPORT_SYMBOL drivers/misc/ioc4 0xcd2f45b6 ioc4_unregister_submodule +EXPORT_SYMBOL drivers/misc/sony-laptop 0x5bb1e117 sony_pic_camera_command +EXPORT_SYMBOL drivers/misc/tifm_core 0x1a7579e4 tifm_unregister_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0x39f86aa1 tifm_queue_work +EXPORT_SYMBOL drivers/misc/tifm_core 0x7fe9e780 tifm_remove_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0x927082da tifm_eject +EXPORT_SYMBOL drivers/misc/tifm_core 0x9b9e899c tifm_add_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0xa9cd4571 tifm_free_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0xc070bfc5 tifm_alloc_device +EXPORT_SYMBOL drivers/misc/tifm_core 0xc9087eeb tifm_register_driver +EXPORT_SYMBOL drivers/misc/tifm_core 0xd1098f0d tifm_map_sg +EXPORT_SYMBOL drivers/misc/tifm_core 0xdc7f7537 tifm_alloc_adapter +EXPORT_SYMBOL drivers/misc/tifm_core 0xe4dab5ff tifm_free_device +EXPORT_SYMBOL drivers/misc/tifm_core 0xf3459334 tifm_has_ms_pif +EXPORT_SYMBOL drivers/misc/tifm_core 0xfca5458f tifm_unmap_sg +EXPORT_SYMBOL drivers/mmc/card/mmc_block 0xb7219a53 mmc_cleanup_queue +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x0664a875 mmc_set_data_timeout +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x09bf1a5b mmc_wait_for_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x376d7f75 mmc_resume_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x58230d23 mmc_free_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x5a02fda0 mmc_register_driver +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x79e4511d mmc_detect_change +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x86a3d4d9 mmc_add_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x8b4ceaee mmc_unregister_driver +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x8c172311 mmc_align_data_size +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0x93c3fdb7 __mmc_claim_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xa1a413ff mmc_request_done +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xa73c1442 mmc_wait_for_req +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xbac1072b mmc_wait_for_app_cmd +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xd12896bb mmc_suspend_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xd218943f mmc_alloc_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xe4779979 mmc_release_host +EXPORT_SYMBOL drivers/mmc/core/mmc_core 0xea02d43d mmc_remove_host +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x0854ef01 cfi_varsize_frob +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x75eb75f1 cfi_read_pri +EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0xd9f02852 cfi_fixup +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x02eca375 map_destroy +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x0d4c6563 do_map_probe +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x1201f0d0 register_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x270fbeaf unregister_mtd_chip_driver +EXPORT_SYMBOL drivers/mtd/chips/gen_probe 0xf21a7879 mtd_do_chip_probe +EXPORT_SYMBOL drivers/mtd/maps/map_funcs 0x636ea062 simple_map_init +EXPORT_SYMBOL drivers/mtd/mtd 0xd1893294 del_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtd 0xd6914863 add_mtd_partitions +EXPORT_SYMBOL drivers/mtd/mtdconcat 0x6807c264 mtd_concat_destroy +EXPORT_SYMBOL drivers/mtd/mtdconcat 0xd3789ce0 mtd_concat_create +EXPORT_SYMBOL drivers/mtd/nand/nand 0xa608fba6 nand_scan_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand 0xe78a9f93 nand_default_bbt +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x254f230c nand_calculate_ecc +EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x87406d9d nand_correct_data +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0x836bdb72 nand_flash_ids +EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0xa336feb7 nand_manuf_ids +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0x611b59a2 onenand_scan_bbt +EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xeb4392a2 onenand_default_bbt +EXPORT_SYMBOL drivers/net/8390 0x156d3583 NS8390_init +EXPORT_SYMBOL drivers/net/8390 0x4e7b2e6c ei_open +EXPORT_SYMBOL drivers/net/8390 0x4f77062b __alloc_ei_netdev +EXPORT_SYMBOL drivers/net/8390 0x7d7e0dbc ei_interrupt +EXPORT_SYMBOL drivers/net/8390 0xbecab569 ei_close +EXPORT_SYMBOL drivers/net/8390 0xfd531da1 ei_poll +EXPORT_SYMBOL drivers/net/8390p 0x11de131f eip_open +EXPORT_SYMBOL drivers/net/8390p 0x6fbc7f65 __alloc_eip_netdev +EXPORT_SYMBOL drivers/net/8390p 0x76f9d229 eip_poll +EXPORT_SYMBOL drivers/net/8390p 0x779930d2 eip_close +EXPORT_SYMBOL drivers/net/8390p 0x841bc69f eip_interrupt +EXPORT_SYMBOL drivers/net/8390p 0xee4ac18e NS8390p_init +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x084bdbf7 arc_raw_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4641bd7d arcnet_interrupt +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x6534792a arcnet_debug +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xbb97cf8c alloc_arcdev +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xd6c76cf8 arcnet_unregister_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xf1029e52 arc_proto_map +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xf47a7033 arc_bcast_proto +EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xf720425b arc_proto_default +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x03e86fb4 com20020_check +EXPORT_SYMBOL drivers/net/arcnet/com20020 0x4598cb8e com20020_found +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x0407e851 t3_register_cpl_handler +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x08cc9b44 cxgb3_free_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x0e24fd33 cxgb3_remove_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x19f848c4 cxgb3_unregister_client +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x38637738 cxgb3_register_client +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x536e394d t3_l2t_send_event +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x6470bbf3 cxgb3_alloc_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x674968ac cxgb3_free_atid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x7ca3f7eb dev2t3cdev +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x9d71f309 cxgb3_ofld_send +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xa007c24a t3_l2t_get +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xc0ff6eb4 t3_l2t_send_slow +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xc6f33170 cxgb3_alloc_stid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xd2826835 t3_l2e_free +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xfbb76a0a cxgb3_insert_tid +EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xfed86185 cxgb3_queue_tid_release +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x29c5b21f hdlcdrv_transmitter +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x5c95627e hdlcdrv_unregister +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x5e50b97c hdlcdrv_register +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x868d08fc hdlcdrv_receiver +EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xe821c759 hdlcdrv_arbitrate +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x07a10693 irda_register_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x209ab465 sirdev_raw_write +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x30ddefd7 sirdev_write_complete +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x45398993 sirdev_receive +EXPORT_SYMBOL drivers/net/irda/sir-dev 0x75ba0ae3 sirdev_set_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xd24ac13a sirdev_set_dtr_rts +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xd4cc2896 sirdev_put_instance +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xe5224b5e sirdev_raw_read +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf27d0894 irda_unregister_dongle +EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf6bfd09d sirdev_get_instance +EXPORT_SYMBOL drivers/net/mii 0x1a9405b4 mii_nway_restart +EXPORT_SYMBOL drivers/net/mii 0x6009729a generic_mii_ioctl +EXPORT_SYMBOL drivers/net/mii 0x8ed2f98c mii_ethtool_sset +EXPORT_SYMBOL drivers/net/mii 0x98684ea1 mii_check_link +EXPORT_SYMBOL drivers/net/mii 0x9d823f43 mii_check_gmii_support +EXPORT_SYMBOL drivers/net/mii 0xc0eccce1 mii_ethtool_gset +EXPORT_SYMBOL drivers/net/mii 0xc7042a23 mii_check_media +EXPORT_SYMBOL drivers/net/mii 0xdcfea39c mii_link_ok +EXPORT_SYMBOL drivers/net/phy/libphy 0x02788521 phy_stop_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x07c3e34d phy_driver_register +EXPORT_SYMBOL drivers/net/phy/libphy 0x0a7dcd7c phy_register_fixup_for_id +EXPORT_SYMBOL drivers/net/phy/libphy 0x0f4f7a46 phy_stop +EXPORT_SYMBOL drivers/net/phy/libphy 0x10977700 phy_attach +EXPORT_SYMBOL drivers/net/phy/libphy 0x1ca2be8f phy_sanitize_settings +EXPORT_SYMBOL drivers/net/phy/libphy 0x27cc0cde phy_device_create +EXPORT_SYMBOL drivers/net/phy/libphy 0x34248dda phy_detach +EXPORT_SYMBOL drivers/net/phy/libphy 0x37b6a24d phy_enable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x45650974 phy_driver_unregister +EXPORT_SYMBOL drivers/net/phy/libphy 0x46bb751e genphy_read_status +EXPORT_SYMBOL drivers/net/phy/libphy 0x473cf6f2 genphy_update_link +EXPORT_SYMBOL drivers/net/phy/libphy 0x491c007f phy_start_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x55ac2489 phy_ethtool_gset +EXPORT_SYMBOL drivers/net/phy/libphy 0x7c06f414 phy_register_fixup_for_uid +EXPORT_SYMBOL drivers/net/phy/libphy 0x7fdc7809 mdiobus_register +EXPORT_SYMBOL drivers/net/phy/libphy 0x844b2df1 phy_mii_ioctl +EXPORT_SYMBOL drivers/net/phy/libphy 0x8521f751 phy_read +EXPORT_SYMBOL drivers/net/phy/libphy 0x8798bc56 phy_disconnect +EXPORT_SYMBOL drivers/net/phy/libphy 0x89e1c4b5 mdio_bus_type +EXPORT_SYMBOL drivers/net/phy/libphy 0x8c69b340 phy_disable_interrupts +EXPORT_SYMBOL drivers/net/phy/libphy 0x95067e96 get_phy_id +EXPORT_SYMBOL drivers/net/phy/libphy 0x99494712 phy_scan_fixups +EXPORT_SYMBOL drivers/net/phy/libphy 0x9e819ae2 phy_print_status +EXPORT_SYMBOL drivers/net/phy/libphy 0xa09b1436 genphy_config_advert +EXPORT_SYMBOL drivers/net/phy/libphy 0xa96eb3b4 phy_start +EXPORT_SYMBOL drivers/net/phy/libphy 0xab35c254 phy_write +EXPORT_SYMBOL drivers/net/phy/libphy 0xb981bd44 phy_connect +EXPORT_SYMBOL drivers/net/phy/libphy 0xd0fac8be mdiobus_unregister +EXPORT_SYMBOL drivers/net/phy/libphy 0xd869a695 phy_start_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0xdda80ae1 genphy_config_aneg +EXPORT_SYMBOL drivers/net/phy/libphy 0xe3f4250f phy_register_fixup +EXPORT_SYMBOL drivers/net/phy/libphy 0xf50ee9c4 phy_ethtool_sset +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x3a46f4ae free_mdio_bitbang +EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0xbd5c59a2 alloc_mdio_bitbang +EXPORT_SYMBOL drivers/net/ppp_generic 0x00bf8d61 ppp_channel_index +EXPORT_SYMBOL drivers/net/ppp_generic 0x25417e7f ppp_output_wakeup +EXPORT_SYMBOL drivers/net/ppp_generic 0x2685faaa ppp_unit_number +EXPORT_SYMBOL drivers/net/ppp_generic 0x3c9d8d1c ppp_register_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0x617601c6 ppp_unregister_channel +EXPORT_SYMBOL drivers/net/ppp_generic 0x6a38d548 ppp_unregister_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0x794da132 ppp_register_compressor +EXPORT_SYMBOL drivers/net/ppp_generic 0xa222876b ppp_input +EXPORT_SYMBOL drivers/net/ppp_generic 0xb9858942 ppp_input_error +EXPORT_SYMBOL drivers/net/pppox 0x2c58b963 register_pppox_proto +EXPORT_SYMBOL drivers/net/pppox 0x402a902d pppox_unbind_sock +EXPORT_SYMBOL drivers/net/pppox 0xc4dd47a9 pppox_ioctl +EXPORT_SYMBOL drivers/net/pppox 0xe0ff7a18 unregister_pppox_proto +EXPORT_SYMBOL drivers/net/slhc 0x0ff2b602 slhc_compress +EXPORT_SYMBOL drivers/net/slhc 0x23c8f257 slhc_uncompress +EXPORT_SYMBOL drivers/net/slhc 0xa63d85ab slhc_remember +EXPORT_SYMBOL drivers/net/slhc 0xb5ca1c46 slhc_free +EXPORT_SYMBOL drivers/net/slhc 0xdfc5169b slhc_init +EXPORT_SYMBOL drivers/net/slhc 0xe8794ce1 slhc_toss +EXPORT_SYMBOL drivers/net/sungem_phy 0xbef89393 mii_phy_probe +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x518fcbfb tms380tr_interrupt +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x5e626186 tmsdev_term +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x76f0617b tms380tr_open +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xb92fe183 tmsdev_init +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd2328794 tms380tr_wait +EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xfe8061ff tms380tr_close +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x38da4725 cycx_intr +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x62be23ea cycx_setup +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x66a4c4e6 cycx_down +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x968458a6 cycx_peek +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xb6f383de cycx_poke +EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xfe7cd576 cycx_exec +EXPORT_SYMBOL drivers/net/wan/hdlc 0x2c63efec unregister_hdlc_device +EXPORT_SYMBOL drivers/net/wan/hdlc 0x580d4aef alloc_hdlcdev +EXPORT_SYMBOL drivers/net/wan/hdlc 0x64777605 attach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0x9ba86136 hdlc_open +EXPORT_SYMBOL drivers/net/wan/hdlc 0xb71925d0 hdlc_close +EXPORT_SYMBOL drivers/net/wan/hdlc 0xc1276755 unregister_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xd0373bdf detach_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xd4f42cc9 register_hdlc_protocol +EXPORT_SYMBOL drivers/net/wan/hdlc 0xf608637a hdlc_ioctl +EXPORT_SYMBOL drivers/net/wan/syncppp 0x0005ffe0 sppp_reopen +EXPORT_SYMBOL drivers/net/wan/syncppp 0x106fc441 sppp_detach +EXPORT_SYMBOL drivers/net/wan/syncppp 0x22d593f6 sppp_open +EXPORT_SYMBOL drivers/net/wan/syncppp 0x6dddbb90 sppp_close +EXPORT_SYMBOL drivers/net/wan/syncppp 0xa11cc90a sppp_do_ioctl +EXPORT_SYMBOL drivers/net/wan/syncppp 0xa32886fd sppp_attach +EXPORT_SYMBOL drivers/net/wan/z85230 0x05c34450 z8530_describe +EXPORT_SYMBOL drivers/net/wan/z85230 0x10c78988 z8530_dead_port +EXPORT_SYMBOL drivers/net/wan/z85230 0x1d339b22 z8530_sync_dma_close +EXPORT_SYMBOL drivers/net/wan/z85230 0x283e799e z8530_interrupt +EXPORT_SYMBOL drivers/net/wan/z85230 0x28e4c736 z8530_dma_sync +EXPORT_SYMBOL drivers/net/wan/z85230 0x2a805dfc z8530_null_rx +EXPORT_SYMBOL drivers/net/wan/z85230 0x3cc740d5 z8530_sync_txdma_close +EXPORT_SYMBOL drivers/net/wan/z85230 0x40c13c70 z8530_sync +EXPORT_SYMBOL drivers/net/wan/z85230 0x5cd24d29 z8530_hdlc_kilostream +EXPORT_SYMBOL drivers/net/wan/z85230 0x60e1fcb9 z8530_sync_close +EXPORT_SYMBOL drivers/net/wan/z85230 0x7f670dcb z8530_sync_open +EXPORT_SYMBOL drivers/net/wan/z85230 0x830aaa53 z8530_init +EXPORT_SYMBOL drivers/net/wan/z85230 0x8c5fdc15 z8530_channel_load +EXPORT_SYMBOL drivers/net/wan/z85230 0x8d9d184a z8530_queue_xmit +EXPORT_SYMBOL drivers/net/wan/z85230 0x90111999 z8530_nop +EXPORT_SYMBOL drivers/net/wan/z85230 0xa6115437 z8530_txdma_sync +EXPORT_SYMBOL drivers/net/wan/z85230 0xaa9e2744 z8530_sync_dma_open +EXPORT_SYMBOL drivers/net/wan/z85230 0xceb8add9 z8530_shutdown +EXPORT_SYMBOL drivers/net/wan/z85230 0xe3d80064 z8530_hdlc_kilostream_85230 +EXPORT_SYMBOL drivers/net/wan/z85230 0xeab16570 z8530_sync_txdma_open +EXPORT_SYMBOL drivers/net/wireless/airo 0x1660a8d8 reset_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0x5187a96c init_airo_card +EXPORT_SYMBOL drivers/net/wireless/airo 0x77e936df stop_airo_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0x15cbf754 stop_atmel_card +EXPORT_SYMBOL drivers/net/wireless/atmel 0x1b38edaa atmel_open +EXPORT_SYMBOL drivers/net/wireless/atmel 0xf136fb65 init_atmel_card +EXPORT_SYMBOL drivers/net/wireless/hermes 0x4196c38b hermes_write_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xc60b5e9e hermes_bap_pwrite +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd38d8ae2 hermes_read_ltv +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd3f714e5 hermes_bap_pread +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5168829 hermes_allocate +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd5336e5d hermes_init +EXPORT_SYMBOL drivers/net/wireless/hermes 0xd54e219d hermes_docmd_wait +EXPORT_SYMBOL drivers/net/wireless/hermes 0xed47b224 hermes_struct_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x0269a86a hostap_add_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x0ad69602 hostap_set_multicast_list_queue +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x12bef736 hostap_init_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x17ea5515 hostap_free_data +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x277137c6 hostap_set_hostapd_sta +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x2a02e836 hostap_set_roaming +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x2bafeeed hostap_get_porttype +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x34c78744 hostap_get_stats +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x43414e04 hostap_80211_rx +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x4d75fefb hostap_set_antsel +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x5a9d99fb hostap_set_word +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x5c015d52 hostap_check_sta_fw_version +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x64acd397 hostap_setup_dev +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x65d0287e hostap_set_hostapd +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x6903f16c hostap_80211_get_hdrlen +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x89fc66d5 hostap_info_init +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x8a53cd4e hostap_set_string +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x9555ad0d hostap_info_process +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0x9a4f778f hostap_set_auth_algs +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xa12ad27f hostap_dump_tx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xaf15e159 hostap_handle_sta_tx_exc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xafc5ba42 hostap_remove_interface +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb0d47a6d hostap_init_ap_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb2a945e0 hostap_dump_rx_header +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xb3ba2c0d hostap_remove_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xc0c3a5d2 hostap_master_start_xmit +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xc30ea351 hostap_init_proc +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xcf841137 hostap_80211_ops +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xe98633d1 hostap_set_encryption +EXPORT_SYMBOL drivers/net/wireless/hostap/hostap 0xf10be5b2 prism2_update_comms_qual +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0049d058 iwl_find_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x024a565c iwl_txq_check_empty +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0349b5ac iwl_rx_queue_alloc +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x0386aadd iwl_get_channel_info +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x03b8e576 iwl_print_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x045a396c iwl_eeprom_query16 +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x06320b80 iwl_dump_nic_event_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x111dc2f9 iwl_rfkill_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1458a1a9 iwl_rxon_add_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x18e0135e iwl_power_enable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x1d77b399 iwl_bcast_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x2ad8a556 iwl_send_static_wepkey_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x30350cb1 iwl_tx_cmd_complete +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x311f32ae iwl_rx_replenish +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x325103fd iwl_rxq_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x344daae1 iwl_chain_noise_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x35511014 iwl_tx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x358d14a1 iwl_remove_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x35ce4723 iwl_scan_cancel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x382e5b4d iwl_init_sensitivity +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x3b285e09 iwl_hw_detect +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x3db97650 iwl_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x3fd96023 iwl_radio_kill_sw_disable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x420669db iwl_setup_scan_deferred_work +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x49ac3dfa iwl_tx_skb +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4dbe2f5f iwl_hw_txq_ctx_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x4e5d4429 iwl_rx_missed_beacon_notif +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x55c6912d iwl_power_disable_management +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5980210a iwlcore_eeprom_release_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5cc0fa0e iwl_sensitivity_calibration +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5eada419 iwl_send_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x5f8866f6 iwl_rx_queue_restock +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6406a9ee iwl_power_set_user_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x64f31aad iwl_power_initialize +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x65fb6559 iwl_rf_kill_ct_config +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6c4d62a5 iwl_send_cmd_sync +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6caea2d7 iwl_init_channel_map +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x6d859de9 iwl_tx_queue_reclaim +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x70092d9d iwl_send_statistics_request +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x70c8400d iwl_hwrate_to_tx_control +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7796ddd5 iwl_rx_reply_rx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7cf14072 iwl_eeprom_check_version +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x7f3dd1a0 iwl_power_set_system_mode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x808eceab iwl_add_station_flags +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x84d48867 iwlcore_eeprom_query_addr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x85e4abb2 iwl_power_temperature_change +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8670273d iwl_hwrate_to_plcp_idx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x867a0601 iwl_alloc_all +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x893907a9 iwl_get_ra_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8ab06de7 iwl_init_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8b2dc538 iwl_rx_reply_compressed_ba +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8bc53c25 iwl_hw_nic_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8c8cdc8f iwl_send_cmd_pdu +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x8ed14e64 iwl_eeprom_init +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x91b8d8e5 iwl_clear_stations_table +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x924d87bc iwl_scan_cancel_timeout +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x92fbdc67 iwl_txq_ctx_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x93c22efb iwl_setup_rx_scan_handlers +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x95b56854 iwl_rx_queue_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9649b505 iwl_verify_ucode +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x968e5c51 iwl_rx_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x96e59e60 iwl_leds_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x97cf286d iwl_set_tx_power +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x97f4f038 iwl_rx_allocate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x999493c4 iwl_is_fat_tx_allowed +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9cd05265 iwl_sta_modify_enable_tid_tx +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9cde1f24 iwl_queue_space +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9e294e1f iwl_rfkill_set_hw_state +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0x9ec071c9 iwl_free_calib_results +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa2955772 iwl_set_hw_params +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa5158df1 iwl_rfkill_unregister +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa7ac43db iwlcore_eeprom_acquire_semaphore +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xa999a761 iwl_get_sta_id +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xad44808d iwl_leds_background +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xad7d33c5 iwl_send_lq_cmd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xae8d3df6 iwl_tx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xaec79fcc iwl_leds_register +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xafadffd0 iwl_eeprom_get_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb21efb97 iwl_rx_agg_start +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb330f32b iwl_rx_statistics +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb37a94ee iwl_set_dynamic_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb38a1e41 iwl_escape_essid +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb6055085 iwl_eeprom_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xb607e44b iwl_send_add_sta +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xbaaa68eb iwl_reset_run_time_calib +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xbbaf36e5 iwl_dump_nic_error_log +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xbe97a02f iwl_rx_reply_rx_phy +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xc4d13957 iwl_send_cmd_pdu_async +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcbaf4931 get_cmd_string +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcc59cff4 iwl_uninit_drv +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xcec8252e iwl_rx_agg_stop +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd1fc8635 iwl_set_rxon_ht +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xd5aef410 iwl_rx_queue_free +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdd180516 iwl_remove_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xdf5b112a iwl_set_rxon_chain +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe2663589 iwl_set_rxon_channel +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe4233d8c iwl_remove_station +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe52be58f iwlcore_eeprom_verify_signature +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe5ad4ff8 iwl_hw_txq_free_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe5c89a69 iwl_hw_txq_attach_buf_to_tfd +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe723262e iwl_txq_update_write_ptr +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xe7ce5d70 iwl_rates +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xedc08ce4 iwl_radio_kill_sw_enable_radio +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xef806393 iwl_rx_queue_reset +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf2a751db iwl_setup_mac +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf64dc9ed iwl_scan_initiate +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf774ae01 iwl_reset_qos +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xf94a9ec6 iwl_set_default_wep_key +EXPORT_SYMBOL drivers/net/wireless/iwlwifi/iwlcore 0xfea3775b iwl_power_update_mode +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x1a9d334a orinoco_interrupt +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x3742661e free_orinocodev +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x5ff5b9d8 orinoco_reinit_firmware +EXPORT_SYMBOL drivers/net/wireless/orinoco 0x78d950f6 __orinoco_down +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xa2597f4b __orinoco_up +EXPORT_SYMBOL drivers/net/wireless/orinoco 0xd0f4767b alloc_orinocodev +EXPORT_SYMBOL drivers/parport/parport 0x01bd63ae parport_ieee1284_ecp_write_data +EXPORT_SYMBOL drivers/parport/parport 0x0568fac6 parport_claim_or_block +EXPORT_SYMBOL drivers/parport/parport 0x19a3b4c0 parport_release +EXPORT_SYMBOL drivers/parport/parport 0x1b306d51 parport_ieee1284_ecp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0x1dbe8d84 parport_irq_handler +EXPORT_SYMBOL drivers/parport/parport 0x1dd59e15 parport_register_driver +EXPORT_SYMBOL drivers/parport/parport 0x1ff79313 parport_register_port +EXPORT_SYMBOL drivers/parport/parport 0x2e7e01c4 parport_negotiate +EXPORT_SYMBOL drivers/parport/parport 0x36b17ab1 parport_wait_peripheral +EXPORT_SYMBOL drivers/parport/parport 0x3d413814 parport_ieee1284_epp_read_data +EXPORT_SYMBOL drivers/parport/parport 0x47364a53 parport_announce_port +EXPORT_SYMBOL drivers/parport/parport 0x48dbaea6 parport_wait_event +EXPORT_SYMBOL drivers/parport/parport 0x4d2a941b parport_ieee1284_interrupt +EXPORT_SYMBOL drivers/parport/parport 0x5213d22b parport_write +EXPORT_SYMBOL drivers/parport/parport 0x5435fb02 parport_get_port +EXPORT_SYMBOL drivers/parport/parport 0x5f4f901b parport_ieee1284_epp_read_addr +EXPORT_SYMBOL drivers/parport/parport 0x73c9d527 parport_claim +EXPORT_SYMBOL drivers/parport/parport 0x7a721936 parport_find_base +EXPORT_SYMBOL drivers/parport/parport 0x8aac8b97 parport_find_number +EXPORT_SYMBOL drivers/parport/parport 0xaa6132aa parport_remove_port +EXPORT_SYMBOL drivers/parport/parport 0xac8ae761 parport_ieee1284_write_compat +EXPORT_SYMBOL drivers/parport/parport 0xae97bffc parport_ieee1284_epp_write_addr +EXPORT_SYMBOL drivers/parport/parport 0xb41ab103 parport_ieee1284_epp_write_data +EXPORT_SYMBOL drivers/parport/parport 0xb53e9494 parport_ieee1284_ecp_read_data +EXPORT_SYMBOL drivers/parport/parport 0xbe74c4f6 parport_put_port +EXPORT_SYMBOL drivers/parport/parport 0xd8f7c95d parport_unregister_device +EXPORT_SYMBOL drivers/parport/parport 0xe274acc6 parport_register_device +EXPORT_SYMBOL drivers/parport/parport 0xe2d227cf parport_unregister_driver +EXPORT_SYMBOL drivers/parport/parport 0xef9cdc86 parport_ieee1284_read_nibble +EXPORT_SYMBOL drivers/parport/parport 0xf5e17e55 parport_read +EXPORT_SYMBOL drivers/parport/parport 0xfaba1b94 parport_set_timeout +EXPORT_SYMBOL drivers/parport/parport 0xfcec2121 parport_ieee1284_read_byte +EXPORT_SYMBOL drivers/parport/parport_pc 0x3872fc15 parport_pc_unregister_port +EXPORT_SYMBOL drivers/parport/parport_pc 0x5cd4b144 parport_pc_probe_port +EXPORT_SYMBOL drivers/pci/hotplug/pci_hotplug 0x3e36b2fa acpi_get_hp_hw_control_from_firmware +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x1a91e4f2 pcmcia_map_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x36dcf952 pcmcia_modify_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x3d999fca pcmcia_request_io +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x4c02c478 pcmcia_request_irq +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x7db947c0 pcmcia_request_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x9df85dbd pcmcia_release_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x9f32ce44 pcmcia_get_configuration_info +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa1c665b0 pcmcia_get_mem_page +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa33622eb pcmcia_disable_device +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa9cdaee0 pcmcia_request_configuration +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xab0182cc pcmcia_unregister_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xc596aac3 cs_error +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xd3baa9fd pcmcia_register_driver +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xeeda6507 pcmcia_access_configuration_register +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf4b82955 pcmcia_get_window +EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xfb3d2322 pcmcia_dev_present +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0fda0c83 pcmcia_eject_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x13aec48d pccard_validate_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x159c1d08 pcmcia_socket_dev_suspend +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x1cea9ba5 pcmcia_unregister_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x212db8d2 pcmcia_socket_list +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x22723429 pccard_get_first_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2405fc61 pcmcia_socket_class +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2489464b destroy_cis_cache +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2513c818 pcmcia_write_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x26eb75e8 pccard_get_next_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x31f72050 pccard_read_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x5497a154 pcmcia_replace_cis +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x612ff9e5 pcmcia_parse_events +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x6451b094 pcmcia_register_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x6483fffd pccard_get_tuple_data +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x6b6eeece pccard_static_ops +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x82edfbb4 pcmcia_validate_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x833c6fee pccard_reset_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x8ab03178 release_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x8b14cb4f pcmcia_read_cis_mem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x92c16697 pcmcia_adjust_io_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x9d5b1a52 pcmcia_resume_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa8acfc65 pcmcia_socket_dev_resume +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xbaa90f24 pccard_register_pcmcia +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc368f687 pcmcia_socket_list_rwsem +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcd2ac1c1 pccard_parse_tuple +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcf97f3bd dead_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xd9732df6 pcmcia_put_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xe001da14 pcmcia_get_socket +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xe8887fd4 pcmcia_get_socket_by_nr +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xea515671 pcmcia_insert_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xedf6b5b5 pcmcia_suspend_card +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xf0228fcd pcmcia_find_mem_region +EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xf086367e pcmcia_find_io_region +EXPORT_SYMBOL drivers/pcmcia/rsrc_nonstatic 0xc54ddea0 pccard_nonstatic_ops +EXPORT_SYMBOL drivers/scsi/53c700 0x5175c0f0 NCR_700_intr +EXPORT_SYMBOL drivers/scsi/53c700 0x5ab26374 NCR_700_detect +EXPORT_SYMBOL drivers/scsi/53c700 0xe217e5cc NCR_700_release +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x2250c66e mraid_mm_adapter_app_handle +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x512c956d mraid_mm_unregister_adp +EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0xa2ae4327 mraid_mm_register_adp +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x16231db4 qlogicfas408_queuecommand +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x342ebab3 qlogicfas408_info +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x3fd8cd71 qlogicfas408_detect +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x5cd179e6 qlogicfas408_ihandl +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x61dba1d4 qlogicfas408_disable_ints +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x645c6559 qlogicfas408_bus_reset +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x73a3ab5b qlogicfas408_abort +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xe373c2ec qlogicfas408_biosparam +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xe76b3b20 qlogicfas408_get_chip_type +EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xf2b95199 qlogicfas408_setup +EXPORT_SYMBOL drivers/scsi/raid_class 0x038b5540 raid_class_attach +EXPORT_SYMBOL drivers/scsi/raid_class 0x066e6073 raid_class_release +EXPORT_SYMBOL drivers/scsi/raid_class 0x97390461 raid_component_add +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c65e73c scsi_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c8c9e99 scsi_show_extd_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0d514a71 scsi_device_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0de4c13e __scsi_iterate_devices +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x10e54fb7 scsi_bios_ptable +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x11267875 scsi_extd_sense_format +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x14fd1858 scsi_free_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x15d56efb scsi_rescan_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1978a364 scsi_host_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1b9e0ff1 scsilun_to_int +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1d5a9670 __scsi_alloc_queue +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2220d24e scsi_scan_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28257369 scsi_nonblockable_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28a2ed02 scsi_build_sense_buffer +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2b0ba2b0 scsi_sense_desc_find +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2ba04fca scsi_register +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2d89342a scsi_show_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2ed149fd scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3457bc82 __scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x352f29b1 scsi_setup_blk_pc_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3f1c3b7a scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x427e3ad1 scsi_register_driver +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x44e22d02 scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4afe9a77 scsi_partsize +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4e4b2a48 scsi_host_get +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4e7bfa1b scsi_reset_provider +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4f40247d __scsi_device_lookup_by_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4f95ae67 scsi_track_queue_full +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x56c8799d scsi_kunmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x59679a6c scsi_print_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5f33e940 scsi_put_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x610bad0e scsi_device_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x63cf67e1 scsi_get_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x667d1f22 scsi_host_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x67df5eb3 scsi_execute +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x69b5fa5b scsi_finish_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x69d38ed9 __scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6a9b57e7 scsi_mode_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6ad5d927 __scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6afe9bc9 scsi_block_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6d1f10d4 scsi_adjust_queue_depth +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6d9db47a scsi_free_host_dev +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6ebd451c scsi_calculate_bounce_limit +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6f3a2491 scsi_target_resume +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72a80e67 __scsi_add_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72d47140 scsi_block_when_processing_errors +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72ea7b2d scsi_device_type +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x75da7aae scsi_cmd_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x796fc5ce scsi_get_sense_info_fld +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x84c158a8 scsi_remove_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x85888d2d scsi_is_host_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8de98c12 scsi_prep_state_check +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9567c34d scsi_release_buffers +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9575a2ce scsi_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96cd2b04 scsi_sense_key_string +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x98cd7ed6 scsi_eh_finish_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9982b6bf scsi_ioctl +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9cfd56c5 scsi_print_status +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9e058c77 scsi_host_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9e672ff6 scsi_kmap_atomic_sg +EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9ebf1764 scsicam_bios_param +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa1ebc8f6 scsi_is_sdev_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa419d9ae scsi_get_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa7da13a6 scsi_dma_unmap +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xad512213 scsi_target_quiesce +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaf3dd7dc scsi_logging_level +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xafdb0b69 scsi_prep_return +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb6c5a973 scsi_show_result +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb8aef73e scsi_setup_fs_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb993824a scsi_eh_prep_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb9a4acd1 scsi_dma_map +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbbae0f18 scsi_device_lookup +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc0e8bbb2 starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc41ab1c9 scsi_remove_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xca5dbc50 scsi_print_sense_hdr +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xcc63b629 __starget_for_each_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xce34e089 scsi_device_get +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xce767c31 scsi_test_unit_ready +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xcfc89a3b scsi_allocate_command +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd14d3f4c scsi_add_host +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd2699863 scsi_req_abort_cmd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd73120e2 scsi_print_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd7c7a7a0 scsi_is_target_device +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xdccd02c3 scsi_report_bus_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xde163732 scsi_report_device_reset +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe6a5d755 scsi_unregister +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xea10212a int_to_scsilun +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xec637b72 scsi_command_normalize_sense +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xed35d3f9 scsi_execute_req +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xef55943d scsi_set_medium_removal +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf06faa04 scsi_device_set_state +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf47c2510 scsi_register_interface +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf68e85c4 scsi_scan_target +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf811e69d scsi_eh_flush_done_q +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf9c0156c scsi_init_io +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfb525a2d scsi_eh_restore_cmnd +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfb7025c0 scsi_host_alloc +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfe5de273 scsi_unblock_requests +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfee50e4b scsi_device_put +EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfef96e23 __scsi_print_command +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x199fde8c fc_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x246a7b0d fc_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x261fbd8c fc_host_post_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x391a2d1a fc_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x4b256233 fc_remote_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x7954b1ea fc_get_event_number +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x8926996f fc_remote_port_rolechg +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x90e9ce7a fc_remote_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xd153793a fc_vport_terminate +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xdc9fb6f4 fc_host_post_vendor_event +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xe8e037b9 scsi_is_fc_vport +EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xf73423cd scsi_is_fc_rport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x13c96688 sas_phy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x22cfc4ab scsi_is_sas_rphy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x2cd1f074 sas_port_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x42c16db2 sas_expander_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x47772023 sas_phy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x49b61871 sas_rphy_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x5cba618f sas_port_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x5d4fd221 sas_read_port_mode_page +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x74b88266 sas_port_alloc_num +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x750487d7 sas_phy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x8b7fc76c sas_attach_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x8f3c2116 sas_rphy_add +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x92497bae sas_phy_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x99a0f037 sas_port_delete_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xaa278c9a sas_end_device_alloc +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xb473dabb sas_rphy_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xb48d1250 sas_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xc1343234 sas_port_free +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xc7e976d6 scsi_is_sas_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xca8fbc29 sas_remove_children +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xd42a4a66 sas_port_delete +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xd42f352b sas_rphy_remove +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xd6a8bb09 sas_port_add_phy +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xd924ea2e scsi_is_sas_port +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xda872ed3 sas_port_mark_backlink +EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xee048327 sas_remove_host +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x0ecaccb9 spi_schedule_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x3686ea09 spi_print_msg +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x550e82cd spi_display_xfer_agreement +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x8b9c286c spi_dv_device +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xc60a1bf5 spi_release_transport +EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xc7e26ebc spi_attach_transport +EXPORT_SYMBOL drivers/ssb/ssb 0x0269f1d9 ssb_pcicore_dev_irqvecs_enable +EXPORT_SYMBOL drivers/ssb/ssb 0x220af654 ssb_dma_free_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0x2f0f0bd0 ssb_bus_suspend +EXPORT_SYMBOL drivers/ssb/ssb 0x496bbbbe ssb_device_disable +EXPORT_SYMBOL drivers/ssb/ssb 0x4e5b0052 ssb_clockspeed +EXPORT_SYMBOL drivers/ssb/ssb 0x5156f445 ssb_set_devtypedata +EXPORT_SYMBOL drivers/ssb/ssb 0x664079e6 __ssb_driver_register +EXPORT_SYMBOL drivers/ssb/ssb 0x7a3f6bee ssb_bus_powerup +EXPORT_SYMBOL drivers/ssb/ssb 0x7ffa3d34 ssb_bus_may_powerdown +EXPORT_SYMBOL drivers/ssb/ssb 0x8af9ab20 ssb_device_enable +EXPORT_SYMBOL drivers/ssb/ssb 0x8f4b60b2 ssb_bus_pcibus_register +EXPORT_SYMBOL drivers/ssb/ssb 0x9a87cada ssb_bus_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0xbe1235bd ssb_device_is_enabled +EXPORT_SYMBOL drivers/ssb/ssb 0xc0512e0f ssb_admatch_base +EXPORT_SYMBOL drivers/ssb/ssb 0xc6c20514 ssb_dma_set_mask +EXPORT_SYMBOL drivers/ssb/ssb 0xc7d98e3d ssb_driver_unregister +EXPORT_SYMBOL drivers/ssb/ssb 0xca44b412 ssb_dma_translation +EXPORT_SYMBOL drivers/ssb/ssb 0xd481192b ssb_admatch_size +EXPORT_SYMBOL drivers/ssb/ssb 0xd529ea14 ssb_bus_resume +EXPORT_SYMBOL drivers/ssb/ssb 0xdb9f3206 ssb_dma_alloc_consistent +EXPORT_SYMBOL drivers/ssb/ssb 0xfc8f4d18 ssb_pcihost_register +EXPORT_SYMBOL drivers/telephony/ixj 0xb61679d4 ixj_pcmcia_probe +EXPORT_SYMBOL drivers/telephony/phonedev 0x66d49e7f phone_unregister_device +EXPORT_SYMBOL drivers/telephony/phonedev 0xf92afef2 phone_register_device +EXPORT_SYMBOL drivers/usb/gadget/net2280 0x462623c8 usb_gadget_register_driver +EXPORT_SYMBOL drivers/usb/gadget/net2280 0x6b0aa387 net2280_set_fifo_mode +EXPORT_SYMBOL drivers/usb/gadget/net2280 0x72d84545 usb_gadget_unregister_driver +EXPORT_SYMBOL drivers/usb/host/sl811-hcd 0xe0b7999c sl811h_driver +EXPORT_SYMBOL drivers/usb/serial/usbserial 0x9bbb7f7b usb_serial_resume +EXPORT_SYMBOL drivers/usb/serial/usbserial 0xeb8fac04 usb_serial_suspend +EXPORT_SYMBOL drivers/video/backlight/corgi_bl 0xc86baa7c corgibl_limit_intensity +EXPORT_SYMBOL drivers/video/backlight/lcd 0x21f76e2f lcd_device_register +EXPORT_SYMBOL drivers/video/backlight/lcd 0xe9ac26f9 lcd_device_unregister +EXPORT_SYMBOL drivers/video/console/bitblit 0xbed1c22b fbcon_set_bitops +EXPORT_SYMBOL drivers/video/console/font 0x09c8eb55 font_vga_8x16 +EXPORT_SYMBOL drivers/video/console/font 0xbb99125c get_default_font +EXPORT_SYMBOL drivers/video/console/font 0xf7584a9c find_font +EXPORT_SYMBOL drivers/video/console/softcursor 0xec6da845 soft_cursor +EXPORT_SYMBOL drivers/video/console/tileblit 0x3b9b15cd fbcon_set_tileops +EXPORT_SYMBOL drivers/video/cyber2000fb 0x0cc3ede5 cyber2000fb_detach +EXPORT_SYMBOL drivers/video/cyber2000fb 0x570d3963 cyber2000fb_enable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0x623d452c cyber2000fb_disable_extregs +EXPORT_SYMBOL drivers/video/cyber2000fb 0xd5152c15 cyber2000fb_get_fb_var +EXPORT_SYMBOL drivers/video/cyber2000fb 0xe1971f28 cyber2000fb_attach +EXPORT_SYMBOL drivers/video/display/display 0xa0745a39 display_device_register +EXPORT_SYMBOL drivers/video/display/display 0xc7f4b880 display_device_unregister +EXPORT_SYMBOL drivers/video/macmodes 0x08ed0b62 mac_vmode_to_var +EXPORT_SYMBOL drivers/video/macmodes 0x9ed62133 mac_find_mode +EXPORT_SYMBOL drivers/video/macmodes 0xe2304303 mac_map_monitor_sense +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0xb4c9fcd6 matroxfb_g450_setclk +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0xbeaf2a0c g450_mnp2f +EXPORT_SYMBOL drivers/video/matrox/g450_pll 0xfb553a2a matroxfb_g450_setpll_cond +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x008b7631 matrox_G100 +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x1aeb0b11 matrox_mystique +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xc3955efc DAC1064_global_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xe54411be DAC1064_global_restore +EXPORT_SYMBOL drivers/video/matrox/matroxfb_Ti3026 0x97d7ce32 matrox_millennium +EXPORT_SYMBOL drivers/video/matrox/matroxfb_accel 0x6e4f2cd8 matrox_cfbX_init +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x31955cfb matroxfb_enable_irq +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x49393d05 matroxfb_wait_for_sync +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x817e9cf5 matroxfb_unregister_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x9af106ec matroxfb_register_driver +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x8f670d9d matroxfb_g450_shutdown +EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0xa979ea3e matroxfb_g450_connect +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x224bcda3 matroxfb_read_pins +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x25cf8049 matroxfb_PLL_calcclock +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x32d97323 matroxfb_DAC_out +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x7b3c14f3 matroxfb_vgaHWinit +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x8c63e39a matroxfb_DAC_in +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xabd8e427 matroxfb_var2my +EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xceb50800 matroxfb_vgaHWrestore +EXPORT_SYMBOL drivers/video/output 0x0948c179 video_output_unregister +EXPORT_SYMBOL drivers/video/output 0x81ec7b94 video_output_register +EXPORT_SYMBOL drivers/video/sis/sisfb 0x3037658e sis_malloc +EXPORT_SYMBOL drivers/video/sis/sisfb 0x454a3cf0 sis_free +EXPORT_SYMBOL drivers/video/svgalib 0x00d1fce9 svga_set_default_seq_regs +EXPORT_SYMBOL drivers/video/svgalib 0x07b3da30 svga_wseq_multi +EXPORT_SYMBOL drivers/video/svgalib 0x1b95c56a svga_check_timings +EXPORT_SYMBOL drivers/video/svgalib 0x36d70a65 svga_tilecursor +EXPORT_SYMBOL drivers/video/svgalib 0x53ac999d svga_get_caps +EXPORT_SYMBOL drivers/video/svgalib 0x63e898d1 svga_set_default_crt_regs +EXPORT_SYMBOL drivers/video/svgalib 0x7a3ae959 svga_wcrt_multi +EXPORT_SYMBOL drivers/video/svgalib 0x7a6cc315 svga_tilefill +EXPORT_SYMBOL drivers/video/svgalib 0x80408443 svga_set_timings +EXPORT_SYMBOL drivers/video/svgalib 0x8a862ad9 svga_tileblit +EXPORT_SYMBOL drivers/video/svgalib 0x8fa8438b svga_set_textmode_vga_regs +EXPORT_SYMBOL drivers/video/svgalib 0x9690c999 svga_get_tilemax +EXPORT_SYMBOL drivers/video/svgalib 0xab3b22ad svga_set_default_gfx_regs +EXPORT_SYMBOL drivers/video/svgalib 0xdad682b1 svga_set_default_atc_regs +EXPORT_SYMBOL drivers/video/svgalib 0xec83c473 svga_match_format +EXPORT_SYMBOL drivers/video/svgalib 0xef774f5d svga_compute_pll +EXPORT_SYMBOL drivers/video/svgalib 0xf10df336 svga_settile +EXPORT_SYMBOL drivers/video/svgalib 0xf922225a svga_tilecopy +EXPORT_SYMBOL drivers/video/syscopyarea 0xec8c716f sys_copyarea +EXPORT_SYMBOL drivers/video/sysfillrect 0xf7de36ad sys_fillrect +EXPORT_SYMBOL drivers/video/sysimgblt 0x0b75e4d5 sys_imageblit +EXPORT_SYMBOL drivers/video/vgastate 0x686de290 restore_vga +EXPORT_SYMBOL drivers/video/vgastate 0xe7a2620e save_vga +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x0a241503 w1_ds2760_read +EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x84bcae12 w1_ds2760_write +EXPORT_SYMBOL drivers/w1/wire 0x8cf61660 w1_add_master_device +EXPORT_SYMBOL drivers/w1/wire 0xb6b9f24f w1_register_family +EXPORT_SYMBOL drivers/w1/wire 0xc2981717 w1_unregister_family +EXPORT_SYMBOL drivers/w1/wire 0xcda061c0 w1_remove_master_device +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x04e133fc iTCO_vendor_check_noreboot_on +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x672c9d44 iTCO_vendor_pre_keepalive +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa78bd894 iTCO_vendor_pre_set_heartbeat +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa8d6daac iTCO_vendor_pre_start +EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xd0efe320 iTCO_vendor_pre_stop +EXPORT_SYMBOL fs/configfs/configfs 0x0e00306b config_item_set_name +EXPORT_SYMBOL fs/configfs/configfs 0x1d090a29 configfs_unregister_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0x24127e1c config_item_put +EXPORT_SYMBOL fs/configfs/configfs 0x2c00ed3b configfs_undepend_item +EXPORT_SYMBOL fs/configfs/configfs 0x344260fd configfs_depend_item +EXPORT_SYMBOL fs/configfs/configfs 0x3f60a85a config_group_find_item +EXPORT_SYMBOL fs/configfs/configfs 0x43f02542 config_group_init +EXPORT_SYMBOL fs/configfs/configfs 0x4f09d1d8 config_item_init_type_name +EXPORT_SYMBOL fs/configfs/configfs 0x652e9f04 config_item_init +EXPORT_SYMBOL fs/configfs/configfs 0x93933882 configfs_register_subsystem +EXPORT_SYMBOL fs/configfs/configfs 0xc63a33b9 config_item_get +EXPORT_SYMBOL fs/configfs/configfs 0xfd1a572d config_group_init_type_name +EXPORT_SYMBOL fs/jbd/jbd 0x01512ccf journal_check_available_features +EXPORT_SYMBOL fs/jbd/jbd 0x055a30b7 journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd/jbd 0x08d3039d journal_invalidatepage +EXPORT_SYMBOL fs/jbd/jbd 0x09a6e4e3 journal_get_write_access +EXPORT_SYMBOL fs/jbd/jbd 0x0db65799 journal_load +EXPORT_SYMBOL fs/jbd/jbd 0x0f24859e journal_check_used_features +EXPORT_SYMBOL fs/jbd/jbd 0x2acc2bd4 journal_flush +EXPORT_SYMBOL fs/jbd/jbd 0x2ee0dcda journal_force_commit_nested +EXPORT_SYMBOL fs/jbd/jbd 0x32f50b39 journal_stop +EXPORT_SYMBOL fs/jbd/jbd 0x35c64c2d journal_errno +EXPORT_SYMBOL fs/jbd/jbd 0x3962a086 journal_lock_updates +EXPORT_SYMBOL fs/jbd/jbd 0x3c32f38a journal_destroy +EXPORT_SYMBOL fs/jbd/jbd 0x3f5bc2cb journal_abort +EXPORT_SYMBOL fs/jbd/jbd 0x3ff33720 journal_init_dev +EXPORT_SYMBOL fs/jbd/jbd 0x49439905 journal_blocks_per_page +EXPORT_SYMBOL fs/jbd/jbd 0x580c795b journal_revoke +EXPORT_SYMBOL fs/jbd/jbd 0x6c6facf3 journal_force_commit +EXPORT_SYMBOL fs/jbd/jbd 0x7256ca13 journal_create +EXPORT_SYMBOL fs/jbd/jbd 0x783dc9c1 journal_update_format +EXPORT_SYMBOL fs/jbd/jbd 0x7f8e2242 journal_unlock_updates +EXPORT_SYMBOL fs/jbd/jbd 0x82b330d2 journal_dirty_metadata +EXPORT_SYMBOL fs/jbd/jbd 0x8c205bbf journal_extend +EXPORT_SYMBOL fs/jbd/jbd 0x8f6fb03b journal_set_features +EXPORT_SYMBOL fs/jbd/jbd 0xa450b4ca journal_get_create_access +EXPORT_SYMBOL fs/jbd/jbd 0xa5aaf1f8 journal_restart +EXPORT_SYMBOL fs/jbd/jbd 0xa90b11b3 journal_start_commit +EXPORT_SYMBOL fs/jbd/jbd 0xb758521e log_wait_commit +EXPORT_SYMBOL fs/jbd/jbd 0xc30808c2 journal_init_inode +EXPORT_SYMBOL fs/jbd/jbd 0xc68dfed6 journal_ack_err +EXPORT_SYMBOL fs/jbd/jbd 0xcf247b49 journal_dirty_data +EXPORT_SYMBOL fs/jbd/jbd 0xd2b78c22 journal_get_undo_access +EXPORT_SYMBOL fs/jbd/jbd 0xdcc680ba journal_release_buffer +EXPORT_SYMBOL fs/jbd/jbd 0xe989764e journal_wipe +EXPORT_SYMBOL fs/jbd/jbd 0xf3d8b9eb journal_clear_err +EXPORT_SYMBOL fs/jbd/jbd 0xf4e666cf journal_start +EXPORT_SYMBOL fs/jbd/jbd 0xf9692fec journal_forget +EXPORT_SYMBOL fs/jbd2/jbd2 0x0273fcbc jbd2_journal_force_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x05e2c4ef jbd2_journal_release_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x06e16046 jbd2_journal_force_commit_nested +EXPORT_SYMBOL fs/jbd2/jbd2 0x06fb6fcd jbd2_journal_create +EXPORT_SYMBOL fs/jbd2/jbd2 0x07758a78 jbd2_log_wait_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x0bf3a727 jbd2_journal_flush +EXPORT_SYMBOL fs/jbd2/jbd2 0x11f525a8 jbd2_journal_init_jbd_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x2158993b jbd2_journal_unlock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0x255cd396 jbd2_journal_stop +EXPORT_SYMBOL fs/jbd2/jbd2 0x264edb49 jbd2_journal_forget +EXPORT_SYMBOL fs/jbd2/jbd2 0x322bd87c jbd2_journal_abort +EXPORT_SYMBOL fs/jbd2/jbd2 0x3e745271 jbd2_journal_begin_ordered_truncate +EXPORT_SYMBOL fs/jbd2/jbd2 0x3fcefc95 jbd2_journal_clear_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x479d719f jbd2_journal_invalidatepage +EXPORT_SYMBOL fs/jbd2/jbd2 0x4af7b622 jbd2_journal_set_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x4afbfe08 jbd2_journal_start_commit +EXPORT_SYMBOL fs/jbd2/jbd2 0x50af79b3 jbd2_journal_destroy +EXPORT_SYMBOL fs/jbd2/jbd2 0x5fc3754e jbd2_journal_get_create_access +EXPORT_SYMBOL fs/jbd2/jbd2 0x61d4417a jbd2_journal_check_available_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x70761d40 jbd2_journal_get_undo_access +EXPORT_SYMBOL fs/jbd2/jbd2 0x78d22476 jbd2_journal_init_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0x7931f939 jbd2_journal_check_used_features +EXPORT_SYMBOL fs/jbd2/jbd2 0x7aefef60 jbd2_journal_blocks_per_page +EXPORT_SYMBOL fs/jbd2/jbd2 0x7c0e76a6 jbd2_journal_load +EXPORT_SYMBOL fs/jbd2/jbd2 0x8277d867 jbd2_journal_start +EXPORT_SYMBOL fs/jbd2/jbd2 0x82da07a8 jbd2_journal_update_format +EXPORT_SYMBOL fs/jbd2/jbd2 0x8bf16ef9 jbd2_journal_init_dev +EXPORT_SYMBOL fs/jbd2/jbd2 0xa9ca7a72 jbd2_journal_ack_err +EXPORT_SYMBOL fs/jbd2/jbd2 0xac289d4a jbd2_journal_get_write_access +EXPORT_SYMBOL fs/jbd2/jbd2 0xad2512fc jbd2_journal_clear_err +EXPORT_SYMBOL fs/jbd2/jbd2 0xb8d7fdd5 jbd2_journal_errno +EXPORT_SYMBOL fs/jbd2/jbd2 0xbe0c9f22 jbd2_journal_restart +EXPORT_SYMBOL fs/jbd2/jbd2 0xc0e7305d jbd2_journal_dirty_metadata +EXPORT_SYMBOL fs/jbd2/jbd2 0xd4d8f536 jbd2_journal_try_to_free_buffers +EXPORT_SYMBOL fs/jbd2/jbd2 0xda81336a jbd2_journal_lock_updates +EXPORT_SYMBOL fs/jbd2/jbd2 0xe47de877 jbd2_journal_extend +EXPORT_SYMBOL fs/jbd2/jbd2 0xf4351891 jbd2_journal_file_inode +EXPORT_SYMBOL fs/jbd2/jbd2 0xf71b6fcf jbd2_journal_revoke +EXPORT_SYMBOL fs/jbd2/jbd2 0xfcb60afd jbd2_journal_wipe +EXPORT_SYMBOL fs/jbd2/jbd2 0xfe9d1016 jbd2_journal_release_buffer +EXPORT_SYMBOL fs/lockd/lockd 0x81549143 nlmsvc_ops +EXPORT_SYMBOL fs/lockd/lockd 0x976e539e lockd_up +EXPORT_SYMBOL fs/lockd/lockd 0xa7b91a7b lockd_down +EXPORT_SYMBOL fs/lockd/lockd 0xad09c2db get_nfs_grace_period +EXPORT_SYMBOL fs/mbcache 0x0e777b2a mb_cache_entry_release +EXPORT_SYMBOL fs/mbcache 0x2a98f4a5 mb_cache_entry_free +EXPORT_SYMBOL fs/mbcache 0x419c3d39 mb_cache_entry_find_first +EXPORT_SYMBOL fs/mbcache 0x51cd530d mb_cache_entry_insert +EXPORT_SYMBOL fs/mbcache 0x7eaf8a30 mb_cache_entry_get +EXPORT_SYMBOL fs/mbcache 0x85fa0116 mb_cache_shrink +EXPORT_SYMBOL fs/mbcache 0x8ac51400 mb_cache_entry_find_next +EXPORT_SYMBOL fs/mbcache 0x9c217563 mb_cache_entry_alloc +EXPORT_SYMBOL fs/mbcache 0xa27028b8 mb_cache_create +EXPORT_SYMBOL fs/mbcache 0xd5263820 mb_cache_destroy +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0x61ec5dc9 nfsacl_decode +EXPORT_SYMBOL fs/nfs_common/nfs_acl 0xa98f7a6b nfsacl_encode +EXPORT_SYMBOL fs/nfsd/nfsd 0x0f3e6e01 nfs4_acl_nfsv4_to_posix +EXPORT_SYMBOL fs/nfsd/nfsd 0x2095976a nfs4_acl_new +EXPORT_SYMBOL fs/nfsd/nfsd 0x35e33c1e nfs4_acl_write_who +EXPORT_SYMBOL fs/nfsd/nfsd 0x5a157ae4 nfs4_acl_get_whotype +EXPORT_SYMBOL fs/nfsd/nfsd 0x7ee78c79 nfs4_acl_posix_to_nfsv4 +EXPORT_SYMBOL fs/xfs/xfs 0x930a0621 xfs_qmcore_xfs +EXPORT_SYMBOL lib/crc-ccitt 0x3771b461 crc_ccitt +EXPORT_SYMBOL lib/crc-ccitt 0x75811312 crc_ccitt_table +EXPORT_SYMBOL lib/crc-itu-t 0xd29b009f crc_itu_t_table +EXPORT_SYMBOL lib/crc-itu-t 0xf5b4a948 crc_itu_t +EXPORT_SYMBOL lib/crc-t10dif 0xb6896671 crc_t10dif +EXPORT_SYMBOL lib/crc16 0x02a6ce5a crc16_table +EXPORT_SYMBOL lib/crc16 0x8ffdb3b8 crc16 +EXPORT_SYMBOL lib/crc7 0xa7587646 crc7 +EXPORT_SYMBOL lib/crc7 0xd80c3603 crc7_syndrome_table +EXPORT_SYMBOL lib/libcrc32c 0x2329b292 crc32c_be +EXPORT_SYMBOL lib/libcrc32c 0x37d0b921 crc32c_le +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x315c65fd zlib_deflateInit2 +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x48034724 zlib_deflateReset +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xaf64ad0d zlib_deflate +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf0caf44b zlib_deflate_workspacesize +EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf741c793 zlib_deflateEnd +EXPORT_SYMBOL net/802/p8023 0x9d54b176 make_8023_client +EXPORT_SYMBOL net/802/p8023 0xf2b3fcbc destroy_8023_client +EXPORT_SYMBOL net/9p/9pnet 0x00a6e1a5 p9_create_tclunk +EXPORT_SYMBOL net/9p/9pnet 0x0106a185 p9_create_tstat +EXPORT_SYMBOL net/9p/9pnet 0x15779868 p9_set_tag +EXPORT_SYMBOL net/9p/9pnet 0x1b326005 p9_client_uwrite +EXPORT_SYMBOL net/9p/9pnet 0x1cd6e5be p9_idpool_get +EXPORT_SYMBOL net/9p/9pnet 0x1def9003 p9_client_walk +EXPORT_SYMBOL net/9p/9pnet 0x21523da9 p9_create_tattach +EXPORT_SYMBOL net/9p/9pnet 0x2bcc16f2 p9_client_auth +EXPORT_SYMBOL net/9p/9pnet 0x2f1865b3 p9_client_open +EXPORT_SYMBOL net/9p/9pnet 0x3010fa95 p9_idpool_put +EXPORT_SYMBOL net/9p/9pnet 0x309767d8 p9_deserialize_stat +EXPORT_SYMBOL net/9p/9pnet 0x3d73a797 p9_errstr2errno +EXPORT_SYMBOL net/9p/9pnet 0x465c4e6f p9_printfcall +EXPORT_SYMBOL net/9p/9pnet 0x47f2a66e v9fs_register_trans +EXPORT_SYMBOL net/9p/9pnet 0x507c9d70 p9_create_tauth +EXPORT_SYMBOL net/9p/9pnet 0x514f4b08 p9_client_dirread +EXPORT_SYMBOL net/9p/9pnet 0x6146a046 v9fs_get_default_trans +EXPORT_SYMBOL net/9p/9pnet 0x6461b8de p9_create_twrite +EXPORT_SYMBOL net/9p/9pnet 0x69e9d7f1 v9fs_get_trans_by_name +EXPORT_SYMBOL net/9p/9pnet 0x6f11c5c3 p9_create_twrite_u +EXPORT_SYMBOL net/9p/9pnet 0x70c49c17 p9_client_stat +EXPORT_SYMBOL net/9p/9pnet 0x71c7537d p9_create_tcreate +EXPORT_SYMBOL net/9p/9pnet 0x78c5e071 p9_client_attach +EXPORT_SYMBOL net/9p/9pnet 0x81247f39 p9_create_tread +EXPORT_SYMBOL net/9p/9pnet 0x8432c83f p9_deserialize_fcall +EXPORT_SYMBOL net/9p/9pnet 0x8831c6e9 p9_client_destroy +EXPORT_SYMBOL net/9p/9pnet 0x8a64c122 p9_client_uread +EXPORT_SYMBOL net/9p/9pnet 0x950e6b03 p9_create_twstat +EXPORT_SYMBOL net/9p/9pnet 0x9b2eac70 p9_client_readn +EXPORT_SYMBOL net/9p/9pnet 0xa82c6077 p9_client_wstat +EXPORT_SYMBOL net/9p/9pnet 0xa9536064 p9_create_tversion +EXPORT_SYMBOL net/9p/9pnet 0xadd165b7 p9_client_read +EXPORT_SYMBOL net/9p/9pnet 0xadfd597a p9_create_tremove +EXPORT_SYMBOL net/9p/9pnet 0xb671b7eb p9_idpool_create +EXPORT_SYMBOL net/9p/9pnet 0xc09e248f p9_client_clunk +EXPORT_SYMBOL net/9p/9pnet 0xc724aa62 p9_idpool_destroy +EXPORT_SYMBOL net/9p/9pnet 0xcb7e1ddd p9_client_create +EXPORT_SYMBOL net/9p/9pnet 0xd4556ff2 p9_client_write +EXPORT_SYMBOL net/9p/9pnet 0xd4a4d98f p9_client_remove +EXPORT_SYMBOL net/9p/9pnet 0xdc894ac7 p9_create_twalk +EXPORT_SYMBOL net/9p/9pnet 0xe58a3360 p9_error_init +EXPORT_SYMBOL net/9p/9pnet 0xec029b96 p9_client_disconnect +EXPORT_SYMBOL net/9p/9pnet 0xf09b3efa p9_create_topen +EXPORT_SYMBOL net/9p/9pnet 0xfa096122 v9fs_unregister_trans +EXPORT_SYMBOL net/9p/9pnet 0xfb11172a p9_idpool_check +EXPORT_SYMBOL net/9p/9pnet 0xfd028d69 p9_client_fcreate +EXPORT_SYMBOL net/9p/9pnet 0xfff27930 p9_create_tflush +EXPORT_SYMBOL net/appletalk/appletalk 0x53453cfe aarp_send_ddp +EXPORT_SYMBOL net/appletalk/appletalk 0xba998a43 atrtr_get_dev +EXPORT_SYMBOL net/appletalk/appletalk 0xbb774a6c alloc_ltalkdev +EXPORT_SYMBOL net/appletalk/appletalk 0xc856c18c atalk_find_dev_addr +EXPORT_SYMBOL net/ax25/ax25 0x1ee790bf ax25_header_ops +EXPORT_SYMBOL net/ax25/ax25 0x242852b9 ax25_uid_policy +EXPORT_SYMBOL net/ax25/ax25 0x378c17ba ax25_listen_register +EXPORT_SYMBOL net/ax25/ax25 0x3d2d82ec ax25_display_timer +EXPORT_SYMBOL net/ax25/ax25 0x400bb56c ax25_listen_release +EXPORT_SYMBOL net/ax25/ax25 0x40f189fe ax25_rebuild_header +EXPORT_SYMBOL net/ax25/ax25 0x4502c65a asc2ax +EXPORT_SYMBOL net/ax25/ax25 0x49ab5314 ax25_findbyuid +EXPORT_SYMBOL net/ax25/ax25 0x53dea1ff ax2asc +EXPORT_SYMBOL net/ax25/ax25 0x55627b20 ax25_send_frame +EXPORT_SYMBOL net/ax25/ax25 0x883bca97 ax25_linkfail_register +EXPORT_SYMBOL net/ax25/ax25 0x8ede9e26 ax25_protocol_release +EXPORT_SYMBOL net/ax25/ax25 0x8f7740a2 ax25_hard_header +EXPORT_SYMBOL net/ax25/ax25 0xa78fee9c ax25_linkfail_release +EXPORT_SYMBOL net/ax25/ax25 0xb13c8071 ax25_find_cb +EXPORT_SYMBOL net/ax25/ax25 0xc1444946 ax25cmp +EXPORT_SYMBOL net/ax25/ax25 0xd43ecbf1 null_ax25_address +EXPORT_SYMBOL net/bluetooth/bluetooth 0x00484d62 bt_sock_poll +EXPORT_SYMBOL net/bluetooth/bluetooth 0x05e9ad61 hci_register_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0x0b5172ad hci_register_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x0ec7bbf1 hci_free_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0x141674fb hci_conn_auth +EXPORT_SYMBOL net/bluetooth/bluetooth 0x201649dd bt_accept_enqueue +EXPORT_SYMBOL net/bluetooth/bluetooth 0x23a8c539 hci_conn_encrypt +EXPORT_SYMBOL net/bluetooth/bluetooth 0x25fecb70 bt_sock_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0x26dfa072 hci_connect +EXPORT_SYMBOL net/bluetooth/bluetooth 0x35d82079 hci_get_route +EXPORT_SYMBOL net/bluetooth/bluetooth 0x3ac489c2 hci_send_sco +EXPORT_SYMBOL net/bluetooth/bluetooth 0x3d9522b7 hci_unregister_proto +EXPORT_SYMBOL net/bluetooth/bluetooth 0x6792013d hci_conn_check_link_mode +EXPORT_SYMBOL net/bluetooth/bluetooth 0x68cd7028 bt_accept_unlink +EXPORT_SYMBOL net/bluetooth/bluetooth 0x7094f8ae bt_err +EXPORT_SYMBOL net/bluetooth/bluetooth 0x85f5c568 bt_sock_wait_state +EXPORT_SYMBOL net/bluetooth/bluetooth 0x89c7e388 hci_register_proto +EXPORT_SYMBOL net/bluetooth/bluetooth 0x8d3a8e2f bt_accept_dequeue +EXPORT_SYMBOL net/bluetooth/bluetooth 0x9f7f5d59 bt_sock_link +EXPORT_SYMBOL net/bluetooth/bluetooth 0xad12c804 hci_conn_switch_role +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb21f34a9 hci_suspend_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0xb80a02c8 hci_unregister_cb +EXPORT_SYMBOL net/bluetooth/bluetooth 0xbd4f04f3 bt_sock_recvmsg +EXPORT_SYMBOL net/bluetooth/bluetooth 0xc2066af0 batostr +EXPORT_SYMBOL net/bluetooth/bluetooth 0xcc1fb551 baswap +EXPORT_SYMBOL net/bluetooth/bluetooth 0xcd18b035 hci_conn_change_link_key +EXPORT_SYMBOL net/bluetooth/bluetooth 0xda395243 bt_sock_ioctl +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe1843d4c hci_unregister_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe3de7326 hci_send_acl +EXPORT_SYMBOL net/bluetooth/bluetooth 0xe4a1b2e8 hci_resume_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0xef188855 hci_recv_fragment +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf19294db bt_sock_unregister +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf2702a9c hci_alloc_dev +EXPORT_SYMBOL net/bluetooth/bluetooth 0xf51ad307 bt_sock_register +EXPORT_SYMBOL net/bluetooth/l2cap 0xfc31fe88 l2cap_load +EXPORT_SYMBOL net/bridge/bridge 0x0237ccfe br_should_route_hook +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x18a5080f ebt_do_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x25617110 ebt_unregister_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x2e13b614 ebt_unregister_watcher +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x3f0a905d ebt_register_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x5cfe80ef ebt_register_target +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x79395e1f ebt_unregister_table +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xa6aafb77 ebt_register_match +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xc189857c ebt_register_watcher +EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xf8156f9e ebt_unregister_match +EXPORT_SYMBOL net/ieee80211/ieee80211 0x05807c68 ieee80211_channel_to_freq +EXPORT_SYMBOL net/ieee80211/ieee80211 0x064f969d ieee80211_rx_mgt +EXPORT_SYMBOL net/ieee80211/ieee80211 0x26fd733a ieee80211_wx_set_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0x2d39e0a7 ieee80211_get_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x34b8fc19 ieee80211_wx_get_encode +EXPORT_SYMBOL net/ieee80211/ieee80211 0x3b52427c ieee80211_get_channel_flags +EXPORT_SYMBOL net/ieee80211/ieee80211 0x59bfd0aa ieee80211_wx_get_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211 0x809a7e71 ieee80211_txb_free +EXPORT_SYMBOL net/ieee80211/ieee80211 0x81fe9591 ieee80211_freq_to_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0x9015c9b6 ieee80211_get_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0x92b55c14 alloc_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0x9dcbc2e8 ieee80211_set_geo +EXPORT_SYMBOL net/ieee80211/ieee80211 0xa3e77e57 ieee80211_rx +EXPORT_SYMBOL net/ieee80211/ieee80211 0xa9fb135f escape_essid +EXPORT_SYMBOL net/ieee80211/ieee80211 0xcad06921 ieee80211_wx_get_scan +EXPORT_SYMBOL net/ieee80211/ieee80211 0xd919199a ieee80211_wx_set_encodeext +EXPORT_SYMBOL net/ieee80211/ieee80211 0xde91f9de ieee80211_is_valid_channel +EXPORT_SYMBOL net/ieee80211/ieee80211 0xe42794af free_ieee80211 +EXPORT_SYMBOL net/ieee80211/ieee80211 0xfff04f83 ieee80211_channel_to_index +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x1956c0ea ieee80211_unregister_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x279e265f ieee80211_crypt_deinit_handler +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x28d26338 ieee80211_get_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x49e7124a ieee80211_crypt_delayed_deinit +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0x81c31fb0 ieee80211_register_crypto_ops +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0xcf35b9b7 ieee80211_crypt_quiescing +EXPORT_SYMBOL net/ieee80211/ieee80211_crypt 0xe88496d4 ieee80211_crypt_deinit_entries +EXPORT_SYMBOL net/ipv4/inet_lro 0x2bef0605 lro_vlan_hwaccel_receive_skb +EXPORT_SYMBOL net/ipv4/inet_lro 0x3f463ab1 lro_flush_all +EXPORT_SYMBOL net/ipv4/inet_lro 0xd3e7b6a8 lro_flush_pkt +EXPORT_SYMBOL net/ipv4/inet_lro 0xe5266565 lro_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0xebb7f759 lro_vlan_hwaccel_receive_frags +EXPORT_SYMBOL net/ipv4/inet_lro 0xfee0b727 lro_receive_skb +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x4a9c588b ip_vs_tcp_conn_listen +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x509121a7 unregister_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x6a624439 ip_vs_skb_replace +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x78bbefb2 ip_vs_conn_out_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0x9a963f6f register_ip_vs_scheduler +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xa1dbc2d8 ip_vs_proto_name +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xaa7e062e register_ip_vs_app_inc +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xab91504f register_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xc20fcf9f unregister_ip_vs_app +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xd211bb7c ip_vs_conn_in_get +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xd46eda50 ip_vs_conn_put +EXPORT_SYMBOL net/ipv4/ipvs/ip_vs 0xdb89a08a ip_vs_conn_new +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x13a70cdf arpt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x22bcd4f9 arpt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x4045080f arpt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x119e3bc2 ipt_register_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x145a2375 ipt_unregister_table +EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x8ce5a4fc ipt_do_table +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x03762a7e nf_nat_mangle_tcp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x052c8177 nf_nat_protocol_register +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x093387d2 nf_nat_setup_info +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x21e973e7 nf_nat_mangle_udp_packet +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x22826266 nf_nat_protocol_unregister +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x354f4eb2 nf_nat_follow_master +EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xcf5f7ac6 nf_nat_used_tuple +EXPORT_SYMBOL net/ipv4/tunnel4 0xaecd4b92 xfrm4_tunnel_register +EXPORT_SYMBOL net/ipv4/tunnel4 0xcaa0cc34 xfrm4_tunnel_deregister +EXPORT_SYMBOL net/ipv6/ipv6 0x04d53552 inet6_unregister_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0x05035f44 inet6_getname +EXPORT_SYMBOL net/ipv6/ipv6 0x0761d00a nf_ip6_checksum +EXPORT_SYMBOL net/ipv6/ipv6 0x144089ad in6_dev_finish_destroy +EXPORT_SYMBOL net/ipv6/ipv6 0x1873feaa inet6_bind +EXPORT_SYMBOL net/ipv6/ipv6 0x19550127 rt6_lookup +EXPORT_SYMBOL net/ipv6/ipv6 0x1d953acb ipv6_getsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x262e2e0c ipv6_push_nfrag_opts +EXPORT_SYMBOL net/ipv6/ipv6 0x30123eb5 icmpv6_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0x31cc4eb7 ip6_frag_init +EXPORT_SYMBOL net/ipv6/ipv6 0x39d8d764 ipv6_setsockopt +EXPORT_SYMBOL net/ipv6/ipv6 0x3a4b2c8c ipv6_dev_get_saddr +EXPORT_SYMBOL net/ipv6/ipv6 0x5018c1f3 ip6_frag_match +EXPORT_SYMBOL net/ipv6/ipv6 0x52d0ef0b inet6_ioctl +EXPORT_SYMBOL net/ipv6/ipv6 0x538383c0 unregister_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0x619ffae5 xfrm6_input_addr +EXPORT_SYMBOL net/ipv6/ipv6 0x7092366e ipv6_chk_prefix +EXPORT_SYMBOL net/ipv6/ipv6 0x7b4f778e ip6_xmit +EXPORT_SYMBOL net/ipv6/ipv6 0x92ee2127 ipv6_chk_addr +EXPORT_SYMBOL net/ipv6/ipv6 0x94dfecbe icmpv6_send +EXPORT_SYMBOL net/ipv6/ipv6 0xa1aef526 inet6_add_protocol +EXPORT_SYMBOL net/ipv6/ipv6 0xa995b916 ip6_route_output +EXPORT_SYMBOL net/ipv6/ipv6 0xabed9ae1 ndisc_mc_map +EXPORT_SYMBOL net/ipv6/ipv6 0xaf90300f inet6_register_protosw +EXPORT_SYMBOL net/ipv6/ipv6 0xb905ad82 icmpv6_err_convert +EXPORT_SYMBOL net/ipv6/ipv6 0xc8b3bb64 xfrm6_prepare_output +EXPORT_SYMBOL net/ipv6/ipv6 0xce19bac5 register_inet6addr_notifier +EXPORT_SYMBOL net/ipv6/ipv6 0xce86eaf5 xfrm6_rcv_spi +EXPORT_SYMBOL net/ipv6/ipv6 0xdae5a8a9 xfrm6_find_1stfragopt +EXPORT_SYMBOL net/ipv6/ipv6 0xe1a81c3a icmpv6msg_statistics +EXPORT_SYMBOL net/ipv6/ipv6 0xe576c952 xfrm6_rcv +EXPORT_SYMBOL net/ipv6/ipv6 0xe690b8fd __ipv6_isatap_ifid +EXPORT_SYMBOL net/ipv6/ipv6 0xebed9cf5 ip6_route_me_harder +EXPORT_SYMBOL net/ipv6/ipv6 0xed03d0c2 inet6_release +EXPORT_SYMBOL net/ipv6/ipv6 0xf29647cc inet6_del_protocol +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x9f152794 ip6t_unregister_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xa113d3a6 ip6t_register_table +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xb8bddf33 ip6t_ext_hdr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xd9b0c359 ipv6_find_hdr +EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xfe24eddf ip6t_do_table +EXPORT_SYMBOL net/ipv6/tunnel6 0x4a7f4b53 xfrm6_tunnel_deregister +EXPORT_SYMBOL net/ipv6/tunnel6 0x77ab7906 xfrm6_tunnel_register +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0x9cd013f2 xfrm6_tunnel_alloc_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xab14e193 xfrm6_tunnel_free_spi +EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xdb1b42d1 xfrm6_tunnel_spi_lookup +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x258b9907 ircomm_connect_response +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x2603dfb9 ircomm_control_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x5a6c4af5 ircomm_open +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x61ec1ffd ircomm_close +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x6d89a2c3 ircomm_flow_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0x7fc4ea7f ircomm_disconnect_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xde0da967 ircomm_data_request +EXPORT_SYMBOL net/irda/ircomm/ircomm 0xe3dac5cd ircomm_connect_request +EXPORT_SYMBOL net/irda/irda 0x01d1fcdb hashbin_delete +EXPORT_SYMBOL net/irda/irda 0x06a3ee58 irias_new_integer_value +EXPORT_SYMBOL net/irda/irda 0x072e026f irias_add_octseq_attrib +EXPORT_SYMBOL net/irda/irda 0x07d3647c irlmp_register_service +EXPORT_SYMBOL net/irda/irda 0x09edab53 async_wrap_skb +EXPORT_SYMBOL net/irda/irda 0x10a0c82d irlmp_close_lsap +EXPORT_SYMBOL net/irda/irda 0x115aef33 proc_irda +EXPORT_SYMBOL net/irda/irda 0x1491b56f irlmp_connect_response +EXPORT_SYMBOL net/irda/irda 0x15678b57 irttp_data_request +EXPORT_SYMBOL net/irda/irda 0x2036ad06 irda_param_insert +EXPORT_SYMBOL net/irda/irda 0x226f3fb4 irttp_connect_request +EXPORT_SYMBOL net/irda/irda 0x2ac38656 irlmp_open_lsap +EXPORT_SYMBOL net/irda/irda 0x3462950f hashbin_remove +EXPORT_SYMBOL net/irda/irda 0x38a20e5b irda_debug +EXPORT_SYMBOL net/irda/irda 0x3b379110 irttp_udata_request +EXPORT_SYMBOL net/irda/irda 0x448b8aaa irda_qos_bits_to_value +EXPORT_SYMBOL net/irda/irda 0x44d9b6fb iriap_close +EXPORT_SYMBOL net/irda/irda 0x46c1c4a2 irlmp_unregister_service +EXPORT_SYMBOL net/irda/irda 0x471b8986 iriap_open +EXPORT_SYMBOL net/irda/irda 0x524931f9 irlmp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0x5ccc0ac6 irlap_open +EXPORT_SYMBOL net/irda/irda 0x614eaa29 irttp_connect_response +EXPORT_SYMBOL net/irda/irda 0x6758f8ac irias_new_object +EXPORT_SYMBOL net/irda/irda 0x68b7447c hashbin_find +EXPORT_SYMBOL net/irda/irda 0x6b043eba irda_init_max_qos_capabilies +EXPORT_SYMBOL net/irda/irda 0x7042bc54 irlmp_register_client +EXPORT_SYMBOL net/irda/irda 0x747d6779 irias_delete_object +EXPORT_SYMBOL net/irda/irda 0x7621e908 hashbin_insert +EXPORT_SYMBOL net/irda/irda 0x76243bc9 irias_insert_object +EXPORT_SYMBOL net/irda/irda 0x763e54a4 irlmp_unregister_client +EXPORT_SYMBOL net/irda/irda 0x765322ee irlmp_connect_request +EXPORT_SYMBOL net/irda/irda 0x77b63e76 irttp_open_tsap +EXPORT_SYMBOL net/irda/irda 0x781e2db5 irias_find_object +EXPORT_SYMBOL net/irda/irda 0x7957f728 irlmp_update_client +EXPORT_SYMBOL net/irda/irda 0x7a57b6f3 hashbin_remove_this +EXPORT_SYMBOL net/irda/irda 0x908c1911 irttp_disconnect_request +EXPORT_SYMBOL net/irda/irda 0x91815586 irda_param_pack +EXPORT_SYMBOL net/irda/irda 0x929d1ac1 async_unwrap_char +EXPORT_SYMBOL net/irda/irda 0x993ad14b irda_param_extract_all +EXPORT_SYMBOL net/irda/irda 0xa14daa3b irlap_close +EXPORT_SYMBOL net/irda/irda 0xa7497a91 alloc_irdadev +EXPORT_SYMBOL net/irda/irda 0xaa7de899 irttp_close_tsap +EXPORT_SYMBOL net/irda/irda 0xb46d56c5 irlmp_data_request +EXPORT_SYMBOL net/irda/irda 0xb9394173 irias_delete_value +EXPORT_SYMBOL net/irda/irda 0xbcd3ef13 irias_object_change_attribute +EXPORT_SYMBOL net/irda/irda 0xbe40ace9 irlmp_discovery_request +EXPORT_SYMBOL net/irda/irda 0xc14e9b6a hashbin_get_next +EXPORT_SYMBOL net/irda/irda 0xcd41236c hashbin_new +EXPORT_SYMBOL net/irda/irda 0xd30a18b4 irda_notify_init +EXPORT_SYMBOL net/irda/irda 0xd4514ea8 irda_device_set_media_busy +EXPORT_SYMBOL net/irda/irda 0xd7172ff4 hashbin_get_first +EXPORT_SYMBOL net/irda/irda 0xd8bfb6d4 hashbin_lock_find +EXPORT_SYMBOL net/irda/irda 0xde4c6b3c irlmp_service_to_hint +EXPORT_SYMBOL net/irda/irda 0xe1c54a77 irttp_flow_request +EXPORT_SYMBOL net/irda/irda 0xe5260e0e irias_add_integer_attrib +EXPORT_SYMBOL net/irda/irda 0xec41fe7f irias_add_string_attrib +EXPORT_SYMBOL net/irda/irda 0xedd521c2 irlmp_get_discoveries +EXPORT_SYMBOL net/irda/irda 0xf39b7fe0 irda_setup_dma +EXPORT_SYMBOL net/irda/irda 0xf5a128cd irttp_dup +EXPORT_SYMBOL net/irda/irda 0xfefe8dbb iriap_getvaluebyclass_request +EXPORT_SYMBOL net/lapb/lapb 0x2326e18d lapb_unregister +EXPORT_SYMBOL net/lapb/lapb 0x32dfafd9 lapb_data_received +EXPORT_SYMBOL net/lapb/lapb 0x6ff6a1a2 lapb_data_request +EXPORT_SYMBOL net/lapb/lapb 0x7af64b5d lapb_connect_request +EXPORT_SYMBOL net/lapb/lapb 0xd9266330 lapb_getparms +EXPORT_SYMBOL net/lapb/lapb 0xdb643041 lapb_setparms +EXPORT_SYMBOL net/lapb/lapb 0xddd8562c lapb_disconnect_request +EXPORT_SYMBOL net/lapb/lapb 0xf6cf3a74 lapb_register +EXPORT_SYMBOL net/mac80211/mac80211 0x0cb9aed1 __ieee80211_rx +EXPORT_SYMBOL net/mac80211/mac80211 0x2161762f ieee80211_start_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x28240eef ieee80211_get_buffered_bc +EXPORT_SYMBOL net/mac80211/mac80211 0x2c9a5775 ieee80211_register_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x3083cafd ieee80211_stop_queues +EXPORT_SYMBOL net/mac80211/mac80211 0x4849477c ieee80211_unregister_hw +EXPORT_SYMBOL net/mac80211/mac80211 0x49ef338b ieee80211_get_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x4bed4321 ieee80211_rx_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x56097977 ieee80211_rate_control_register +EXPORT_SYMBOL net/mac80211/mac80211 0x62cacfaf __ieee80211_get_radio_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x6e149c3d ieee80211_notify_mac +EXPORT_SYMBOL net/mac80211/mac80211 0x76015c7a __ieee80211_get_rx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x7870d442 ieee80211_get_hdrlen_from_skb +EXPORT_SYMBOL net/mac80211/mac80211 0x7a8990c5 __ieee80211_get_assoc_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x7dcd6e2c ieee80211_ctstoself_get +EXPORT_SYMBOL net/mac80211/mac80211 0x82ad8fb3 ieee80211_tx_status_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0x86594215 __ieee80211_get_tx_led_name +EXPORT_SYMBOL net/mac80211/mac80211 0x86fa5c02 ieee80211_rts_duration +EXPORT_SYMBOL net/mac80211/mac80211 0x8a948ee4 ieee80211_wake_queues +EXPORT_SYMBOL net/mac80211/mac80211 0x8c35d732 ieee80211_hdrlen +EXPORT_SYMBOL net/mac80211/mac80211 0x8c99f3ab ieee80211_tx_status +EXPORT_SYMBOL net/mac80211/mac80211 0x9db690cb ieee80211_wake_queue +EXPORT_SYMBOL net/mac80211/mac80211 0xa171df2c ieee80211_get_tkip_key +EXPORT_SYMBOL net/mac80211/mac80211 0xa1adbae1 ieee80211_rts_get +EXPORT_SYMBOL net/mac80211/mac80211 0xaccc4b0e ieee80211_free_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xb1f2a120 ieee80211_beacon_get +EXPORT_SYMBOL net/mac80211/mac80211 0xc1a33097 ieee80211_alloc_hw +EXPORT_SYMBOL net/mac80211/mac80211 0xc2875bbf ieee80211_start_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0xc92a4788 ieee80211_scan_completed +EXPORT_SYMBOL net/mac80211/mac80211 0xca828840 ieee80211_start_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0xcb5ea89e ieee80211_stop_tx_ba_cb +EXPORT_SYMBOL net/mac80211/mac80211 0xd135f880 ieee80211_stop_tx_ba_cb_irqsafe +EXPORT_SYMBOL net/mac80211/mac80211 0xd73fc92d ieee80211_ctstoself_duration +EXPORT_SYMBOL net/mac80211/mac80211 0xe3735995 ieee80211_stop_queue +EXPORT_SYMBOL net/mac80211/mac80211 0xef17eedc ieee80211_rate_control_unregister +EXPORT_SYMBOL net/mac80211/mac80211 0xf61176b6 sta_info_get +EXPORT_SYMBOL net/mac80211/mac80211 0xfaa23d79 ieee80211_stop_tx_ba_session +EXPORT_SYMBOL net/mac80211/mac80211 0xfaa87be7 ieee80211_generic_frame_duration +EXPORT_SYMBOL net/netfilter/nf_conntrack 0x8fb4ee7a __nf_ct_ext_destroy +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xe372c1b6 __nf_ct_ext_add +EXPORT_SYMBOL net/netfilter/nf_conntrack 0xed23741c per_cpu__nf_conntrack_stat +EXPORT_SYMBOL net/netfilter/nf_conntrack_proto_gre 0x82f94e40 nf_ct_gre_keymap_flush +EXPORT_SYMBOL net/netfilter/x_tables 0x1bddfdb1 xt_find_target +EXPORT_SYMBOL net/netfilter/x_tables 0x3dcd58c5 xt_alloc_table_info +EXPORT_SYMBOL net/netfilter/x_tables 0x660e192e xt_register_matches +EXPORT_SYMBOL net/netfilter/x_tables 0x6824b62a xt_unregister_target +EXPORT_SYMBOL net/netfilter/x_tables 0x7b01df52 xt_register_match +EXPORT_SYMBOL net/netfilter/x_tables 0x894dff8e xt_register_targets +EXPORT_SYMBOL net/netfilter/x_tables 0x98143021 xt_unregister_match +EXPORT_SYMBOL net/netfilter/x_tables 0xa4ace551 xt_unregister_targets +EXPORT_SYMBOL net/netfilter/x_tables 0xbe5cef44 xt_unregister_matches +EXPORT_SYMBOL net/netfilter/x_tables 0xcff93b8f xt_find_match +EXPORT_SYMBOL net/netfilter/x_tables 0xf7037dc6 xt_free_table_info +EXPORT_SYMBOL net/netfilter/x_tables 0xfdaed5af xt_register_target +EXPORT_SYMBOL net/rfkill/rfkill 0x00caa4dc rfkill_switch_all +EXPORT_SYMBOL net/rfkill/rfkill 0x06fd7395 rfkill_force_state +EXPORT_SYMBOL net/rfkill/rfkill 0x382b61b2 rfkill_register +EXPORT_SYMBOL net/rfkill/rfkill 0x4fa781e3 rfkill_free +EXPORT_SYMBOL net/rfkill/rfkill 0x8002093b rfkill_allocate +EXPORT_SYMBOL net/rfkill/rfkill 0xeee38826 rfkill_unregister +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x240e7910 rxrpc_get_null_key +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x340a724a rxrpc_kernel_is_data_last +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x562eb640 rxrpc_kernel_data_delivered +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x5c7f3820 rxrpc_kernel_accept_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x5e257901 rxrpc_kernel_send_data +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x7b4decd1 rxrpc_kernel_get_error_number +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x888613fa rxrpc_get_server_data_key +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x99f080f2 rxrpc_kernel_reject_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xb33ad92e rxrpc_kernel_free_skb +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xbf659992 key_type_rxrpc +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xc9541949 rxrpc_kernel_begin_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xd5632256 rxrpc_kernel_get_abort_code +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xdce56092 rxrpc_kernel_end_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xec05e648 rxrpc_kernel_abort_call +EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xf032e072 rxrpc_kernel_intercept_rx_messages +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x00c52ef5 g_make_token_header +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x1725cf30 gss_mech_get +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x44b5ab95 gss_mech_get_by_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x51775c0f gss_pseudoflavor_to_service +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x725766c1 gss_mech_put +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x8d1a827e svcauth_gss_register_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x8f49195f svcauth_gss_flavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0x90cf3fc8 gss_mech_get_by_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xaf1449d7 gss_mech_unregister +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xb3c0ccbf gss_service_to_auth_domain_name +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xb5dea7ef g_token_size +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xc503f356 gss_mech_register +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xcc167d3c gss_svc_to_pseudoflavor +EXPORT_SYMBOL net/sunrpc/auth_gss/auth_rpcgss 0xf8b2ff6e g_verify_token_header +EXPORT_SYMBOL net/sunrpc/sunrpc 0x05e807a9 xdr_encode_string +EXPORT_SYMBOL net/sunrpc/sunrpc 0x065994f1 xdr_encode_opaque_fixed +EXPORT_SYMBOL net/sunrpc/sunrpc 0x0f668ba9 svc_auth_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x12e280e3 svc_proc_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x141c8148 svcauth_unix_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0x14a711c5 cache_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0x19a165ee svc_create_pooled +EXPORT_SYMBOL net/sunrpc/sunrpc 0x283340ad xdr_decode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2919b156 xdr_decode_string_inplace +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2d09dc79 xdr_buf_read_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2ed61249 xdr_encode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0x2eec63c9 xdr_encode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3b606c8d svc_create +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3d45920d svc_sock_names +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3d87c2ed rpc_unlink +EXPORT_SYMBOL net/sunrpc/sunrpc 0x3ea4bb4f xdr_encode_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x42268fd4 xdr_write_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x4bbdd57a cache_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0x4ce8bc3b svc_destroy +EXPORT_SYMBOL net/sunrpc/sunrpc 0x505f697c xdr_buf_subsegment +EXPORT_SYMBOL net/sunrpc/sunrpc 0x51cead92 cache_check +EXPORT_SYMBOL net/sunrpc/sunrpc 0x52f0122d svc_prepare_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0x5f58da4a svc_set_num_threads +EXPORT_SYMBOL net/sunrpc/sunrpc 0x661fe881 sunrpc_cache_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0x699af76a xdr_init_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6edc238a xdr_inline_decode +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6eea229d svcauth_unix_purge +EXPORT_SYMBOL net/sunrpc/sunrpc 0x6f5addcd svc_auth_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0x70cc5557 xdr_read_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0x71fa908a cache_flush +EXPORT_SYMBOL net/sunrpc/sunrpc 0x89030074 read_bytes_from_xdr_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8a0de064 svc_reserve +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8a54690e auth_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8bb99749 rpc_queue_upcall +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8ca712cb svc_recv +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8cd0ca35 svc_sock_update_bufs +EXPORT_SYMBOL net/sunrpc/sunrpc 0x8e80bc38 cache_unregister +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9ca302db svc_authenticate +EXPORT_SYMBOL net/sunrpc/sunrpc 0x9f274e63 auth_unix_forget_old +EXPORT_SYMBOL net/sunrpc/sunrpc 0xab1c6cfc svc_drop +EXPORT_SYMBOL net/sunrpc/sunrpc 0xae353443 sunrpc_cache_update +EXPORT_SYMBOL net/sunrpc/sunrpc 0xb36deaa2 xdr_decode_word +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc2f6be82 xdr_enter_page +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc3880471 xdr_decode_netobj +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc4bf1835 rpc_mkpipe +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc889ed37 auth_unix_add_addr +EXPORT_SYMBOL net/sunrpc/sunrpc 0xc8e96dea qword_addhex +EXPORT_SYMBOL net/sunrpc/sunrpc 0xcc06bc95 svc_process +EXPORT_SYMBOL net/sunrpc/sunrpc 0xcc9520ae xdr_process_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0xcdd1894c xdr_inline_pages +EXPORT_SYMBOL net/sunrpc/sunrpc 0xceb8ac53 xdr_reserve_space +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd5832f10 xdr_shift_buf +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd698628a xdr_encode_array2 +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd81787e9 unix_domain_find +EXPORT_SYMBOL net/sunrpc/sunrpc 0xd9cc29dc auth_domain_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0xdba76c09 svc_set_client +EXPORT_SYMBOL net/sunrpc/sunrpc 0xdcb1e37c svc_wake_up +EXPORT_SYMBOL net/sunrpc/sunrpc 0xde4c665e auth_unix_lookup +EXPORT_SYMBOL net/sunrpc/sunrpc 0xdf11dad4 svc_seq_show +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe5919cb1 xdr_encode_opaque +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe7bbdf4a svc_exit_thread +EXPORT_SYMBOL net/sunrpc/sunrpc 0xe97f4ce5 qword_get +EXPORT_SYMBOL net/sunrpc/sunrpc 0xec3bdb87 svc_proc_register +EXPORT_SYMBOL net/sunrpc/sunrpc 0xedcf6be4 qword_add +EXPORT_SYMBOL net/sunrpc/sunrpc 0xee4a80a2 auth_domain_put +EXPORT_SYMBOL net/sunrpc/sunrpc 0xf061ad40 xdr_buf_from_iov +EXPORT_SYMBOL net/sunrpc/sunrpc 0xfde48f0d xdr_init_encode +EXPORT_SYMBOL net/tipc/tipc 0x08acf310 tipc_available_nodes +EXPORT_SYMBOL net/tipc/tipc 0x1056b9ed tipc_forward_buf2port +EXPORT_SYMBOL net/tipc/tipc 0x10d40fcd tipc_isconnected +EXPORT_SYMBOL net/tipc/tipc 0x1472b270 tipc_disconnect +EXPORT_SYMBOL net/tipc/tipc 0x1479cb03 tipc_deleteport +EXPORT_SYMBOL net/tipc/tipc 0x15b5ecde tipc_set_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x16f27683 tipc_block_bearer +EXPORT_SYMBOL net/tipc/tipc 0x259b74f9 tipc_acknowledge +EXPORT_SYMBOL net/tipc/tipc 0x27d8bb58 tipc_send2port +EXPORT_SYMBOL net/tipc/tipc 0x285062df tipc_register_media +EXPORT_SYMBOL net/tipc/tipc 0x310d1bc9 tipc_detach +EXPORT_SYMBOL net/tipc/tipc 0x31e225ef tipc_send_buf2name +EXPORT_SYMBOL net/tipc/tipc 0x3712e340 tipc_portunreliable +EXPORT_SYMBOL net/tipc/tipc 0x3976041f tipc_set_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x4b2243c6 tipc_portimportance +EXPORT_SYMBOL net/tipc/tipc 0x4ba3cfc8 tipc_send2name +EXPORT_SYMBOL net/tipc/tipc 0x538b228a tipc_withdraw +EXPORT_SYMBOL net/tipc/tipc 0x5637ed44 tipc_get_mode +EXPORT_SYMBOL net/tipc/tipc 0x56e52bc1 tipc_continue +EXPORT_SYMBOL net/tipc/tipc 0x5bbbd542 tipc_send_buf2port +EXPORT_SYMBOL net/tipc/tipc 0x5c0d4b5c tipc_ref_valid +EXPORT_SYMBOL net/tipc/tipc 0x62a681a3 tipc_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0x64357d3c tipc_multicast +EXPORT_SYMBOL net/tipc/tipc 0x8001e3d7 tipc_forward2port +EXPORT_SYMBOL net/tipc/tipc 0x87916983 tipc_send_buf +EXPORT_SYMBOL net/tipc/tipc 0x88b73627 tipc_get_addr +EXPORT_SYMBOL net/tipc/tipc 0x8a73eacd tipc_recv_msg +EXPORT_SYMBOL net/tipc/tipc 0x9c45558e tipc_enable_bearer +EXPORT_SYMBOL net/tipc/tipc 0x9f5f0b43 tipc_createport_raw +EXPORT_SYMBOL net/tipc/tipc 0xa936a24b tipc_get_port +EXPORT_SYMBOL net/tipc/tipc 0xadd203d0 tipc_connect2port +EXPORT_SYMBOL net/tipc/tipc 0xae0103c3 tipc_shutdown +EXPORT_SYMBOL net/tipc/tipc 0xb01ffc2c tipc_forward2name +EXPORT_SYMBOL net/tipc/tipc 0xb35b672c tipc_publish +EXPORT_SYMBOL net/tipc/tipc 0xbb2b2504 tipc_send +EXPORT_SYMBOL net/tipc/tipc 0xcbcde34f tipc_reject_msg +EXPORT_SYMBOL net/tipc/tipc 0xcec8514a tipc_set_portunreturnable +EXPORT_SYMBOL net/tipc/tipc 0xd44731e5 tipc_ownidentity +EXPORT_SYMBOL net/tipc/tipc 0xda7f9d3f tipc_attach +EXPORT_SYMBOL net/tipc/tipc 0xdbcabe3e tipc_forward_buf2name +EXPORT_SYMBOL net/tipc/tipc 0xdf5008fc tipc_peer +EXPORT_SYMBOL net/tipc/tipc 0xe7aece47 tipc_ispublished +EXPORT_SYMBOL net/tipc/tipc 0xeefd49b3 tipc_get_handle +EXPORT_SYMBOL net/tipc/tipc 0xef50a1ef tipc_disable_bearer +EXPORT_SYMBOL net/tipc/tipc 0xf779453a tipc_send_buf_fast +EXPORT_SYMBOL net/tipc/tipc 0xfd710518 tipc_createport +EXPORT_SYMBOL net/wanrouter/wanrouter 0x0ebe03d1 unregister_wan_device +EXPORT_SYMBOL net/wanrouter/wanrouter 0x8315fef2 register_wan_device +EXPORT_SYMBOL net/wireless/cfg80211 0x07e7ac5a ieee80211_radiotap_iterator_init +EXPORT_SYMBOL net/wireless/cfg80211 0x09c64fbd ieee80211_frequency_to_channel +EXPORT_SYMBOL net/wireless/cfg80211 0x8941d44a wiphy_register +EXPORT_SYMBOL net/wireless/cfg80211 0x8c00bf26 wiphy_free +EXPORT_SYMBOL net/wireless/cfg80211 0x923d8a66 wiphy_new +EXPORT_SYMBOL net/wireless/cfg80211 0x982ff3d2 __ieee80211_get_channel +EXPORT_SYMBOL net/wireless/cfg80211 0xa129872e wiphy_unregister +EXPORT_SYMBOL net/wireless/cfg80211 0xc4e85ec5 ieee80211_radiotap_iterator_next +EXPORT_SYMBOL net/wireless/cfg80211 0xccc291b3 ieee80211_channel_to_frequency +EXPORT_SYMBOL sound/ac97_bus 0xb65a27a1 ac97_bus_type +EXPORT_SYMBOL sound/core/oss/snd-mixer-oss 0xb02c73b7 snd_mixer_oss_ioctl_card +EXPORT_SYMBOL sound/core/seq/snd-seq 0x1a724fcc snd_seq_kernel_client_ctl +EXPORT_SYMBOL sound/core/seq/snd-seq 0x294967c1 snd_seq_event_port_attach +EXPORT_SYMBOL sound/core/seq/snd-seq 0x29fb6a07 snd_seq_create_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3061c52d snd_use_lock_sync_helper +EXPORT_SYMBOL sound/core/seq/snd-seq 0x3fb4d161 snd_seq_kernel_client_dispatch +EXPORT_SYMBOL sound/core/seq/snd-seq 0x5819832c snd_seq_kernel_client_enqueue_blocking +EXPORT_SYMBOL sound/core/seq/snd-seq 0x6bb71038 snd_seq_delete_kernel_client +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7ac2f329 snd_seq_expand_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq 0x7b8699eb snd_seq_event_port_detach +EXPORT_SYMBOL sound/core/seq/snd-seq 0x840f7d06 snd_seq_kernel_client_write_poll +EXPORT_SYMBOL sound/core/seq/snd-seq 0xb8e448a0 snd_seq_set_queue_tempo +EXPORT_SYMBOL sound/core/seq/snd-seq 0xcac0a3be snd_seq_kernel_client_enqueue +EXPORT_SYMBOL sound/core/seq/snd-seq 0xe934da1d snd_seq_dump_var_event +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x347b8cdc snd_seq_device_new +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x3a57f235 snd_seq_autoload_unlock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x6339b6d0 snd_seq_device_load_drivers +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x8fb2ba56 snd_seq_device_register_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xb90668b2 snd_seq_autoload_lock +EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xc622fb29 snd_seq_device_unregister_driver +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x6ea09972 snd_midi_channel_alloc_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x833a3e07 snd_midi_channel_set_clear +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xb9948d2c snd_midi_channel_free_set +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xf0a1fdb3 snd_midi_process_event +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x17c15809 snd_midi_event_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x4ad3f518 snd_midi_event_reset_decode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x62384d3a snd_midi_event_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x8a348811 snd_midi_event_reset_encode +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x9df7af8b snd_midi_event_free +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xc482499d snd_midi_event_new +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xd9072e1a snd_midi_event_no_status +EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xe6df29c7 snd_midi_event_encode_byte +EXPORT_SYMBOL sound/core/seq/snd-seq-virmidi 0xd69424c7 snd_virmidi_new +EXPORT_SYMBOL sound/core/snd 0x01a894df snd_device_register +EXPORT_SYMBOL sound/core/snd 0x079f51e5 snd_ctl_find_numid +EXPORT_SYMBOL sound/core/snd 0x0b357c42 snd_ctl_notify +EXPORT_SYMBOL sound/core/snd 0x18e1683f snd_dma_program +EXPORT_SYMBOL sound/core/snd 0x191e88cf snd_dma_pointer +EXPORT_SYMBOL sound/core/snd 0x198788b4 snd_lookup_oss_minor_data +EXPORT_SYMBOL sound/core/snd 0x24a94b26 snd_info_get_line +EXPORT_SYMBOL sound/core/snd 0x2518016a snd_ctl_find_id +EXPORT_SYMBOL sound/core/snd 0x281df21f snd_unregister_oss_device +EXPORT_SYMBOL sound/core/snd 0x2e7c49f0 snd_cards +EXPORT_SYMBOL sound/core/snd 0x3971b4df snd_ecards_limit +EXPORT_SYMBOL sound/core/snd 0x3c5ef203 snd_register_device_for_dev +EXPORT_SYMBOL sound/core/snd 0x3dd6809d snd_ctl_add +EXPORT_SYMBOL sound/core/snd 0x44aae89b snd_card_file_remove +EXPORT_SYMBOL sound/core/snd 0x44d82d88 snd_register_oss_device +EXPORT_SYMBOL sound/core/snd 0x4a3ea5c0 snd_request_card +EXPORT_SYMBOL sound/core/snd 0x4cb3f2b5 snd_pci_quirk_lookup +EXPORT_SYMBOL sound/core/snd 0x4ef23268 snd_info_create_card_entry +EXPORT_SYMBOL sound/core/snd 0x52fe113d release_and_free_resource +EXPORT_SYMBOL sound/core/snd 0x54d1cfe9 snd_ctl_rename_id +EXPORT_SYMBOL sound/core/snd 0x56d4b287 snd_ctl_new1 +EXPORT_SYMBOL sound/core/snd 0x602c96f0 copy_to_user_fromio +EXPORT_SYMBOL sound/core/snd 0x637497ed snd_info_free_entry +EXPORT_SYMBOL sound/core/snd 0x67a9e66e snd_info_create_module_entry +EXPORT_SYMBOL sound/core/snd 0x69b320b3 snd_ctl_unregister_ioctl +EXPORT_SYMBOL sound/core/snd 0x6a043086 snd_device_new +EXPORT_SYMBOL sound/core/snd 0x70c15ac1 snd_dma_disable +EXPORT_SYMBOL sound/core/snd 0x732d6a4b snd_device_free +EXPORT_SYMBOL sound/core/snd 0x79a47d3d snd_card_disconnect +EXPORT_SYMBOL sound/core/snd 0x7bbb774a snd_component_add +EXPORT_SYMBOL sound/core/snd 0x7c32de02 snd_ctl_boolean_stereo_info +EXPORT_SYMBOL sound/core/snd 0x7e1e2967 snd_unregister_device +EXPORT_SYMBOL sound/core/snd 0x8df3789f snd_oss_info_register +EXPORT_SYMBOL sound/core/snd 0x8f595b11 snd_major +EXPORT_SYMBOL sound/core/snd 0xa1477059 snd_seq_root +EXPORT_SYMBOL sound/core/snd 0xa3aa3e45 snd_card_file_add +EXPORT_SYMBOL sound/core/snd 0xa4e124a1 snd_card_proc_new +EXPORT_SYMBOL sound/core/snd 0xb213fe8b snd_info_get_str +EXPORT_SYMBOL sound/core/snd 0xb2cfb89e snd_ctl_make_virtual_master +EXPORT_SYMBOL sound/core/snd 0xb2e5ae4a snd_lookup_minor_data +EXPORT_SYMBOL sound/core/snd 0xb44597ed snd_ctl_register_ioctl +EXPORT_SYMBOL sound/core/snd 0xb5cea32f snd_card_register +EXPORT_SYMBOL sound/core/snd 0xb5ee92ef snd_mixer_oss_notify_callback +EXPORT_SYMBOL sound/core/snd 0xbb028949 snd_add_device_sysfs_file +EXPORT_SYMBOL sound/core/snd 0xbd5b7d51 snd_ctl_boolean_mono_info +EXPORT_SYMBOL sound/core/snd 0xc020e1fe snd_ctl_free_one +EXPORT_SYMBOL sound/core/snd 0xc46b67ec snd_ctl_remove_id +EXPORT_SYMBOL sound/core/snd 0xc888135d snd_card_new +EXPORT_SYMBOL sound/core/snd 0xce3ca308 copy_from_user_toio +EXPORT_SYMBOL sound/core/snd 0xd7492948 snd_card_free +EXPORT_SYMBOL sound/core/snd 0xe242d876 snd_card_free_when_closed +EXPORT_SYMBOL sound/core/snd 0xe442838a snd_ctl_remove +EXPORT_SYMBOL sound/core/snd 0xe4854cea snd_iprintf +EXPORT_SYMBOL sound/core/snd 0xeaa883c8 snd_ctl_add_slave +EXPORT_SYMBOL sound/core/snd 0xeac39903 snd_info_register +EXPORT_SYMBOL sound/core/snd 0xf959134b snd_power_wait +EXPORT_SYMBOL sound/core/snd-hwdep 0x85dd5bd7 snd_hwdep_new +EXPORT_SYMBOL sound/core/snd-page-alloc 0x3af99a85 snd_dma_alloc_pages_fallback +EXPORT_SYMBOL sound/core/snd-page-alloc 0x3b91f3af snd_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x3cd381af snd_dma_alloc_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0x5958e14e snd_dma_reserve_buf +EXPORT_SYMBOL sound/core/snd-page-alloc 0x90b76857 snd_dma_free_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0xade88e76 snd_malloc_pages +EXPORT_SYMBOL sound/core/snd-page-alloc 0xee322055 snd_dma_get_reserved_buf +EXPORT_SYMBOL sound/core/snd-pcm 0x02f77bbf snd_pcm_lib_malloc_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x04cda566 snd_interval_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x065015b7 snd_pcm_lib_writev +EXPORT_SYMBOL sound/core/snd-pcm 0x06cd3d9e snd_pcm_suspend_all +EXPORT_SYMBOL sound/core/snd-pcm 0x14b932f0 snd_pcm_hw_constraint_ratnums +EXPORT_SYMBOL sound/core/snd-pcm 0x17871a3c snd_pcm_set_sync +EXPORT_SYMBOL sound/core/snd-pcm 0x1c14d983 snd_pcm_suspend +EXPORT_SYMBOL sound/core/snd-pcm 0x1d027e4b snd_pcm_format_signed +EXPORT_SYMBOL sound/core/snd-pcm 0x1ff5770c snd_pcm_hw_constraint_minmax +EXPORT_SYMBOL sound/core/snd-pcm 0x2c3cde07 snd_pcm_hw_constraint_integer +EXPORT_SYMBOL sound/core/snd-pcm 0x2c8f84ed snd_pcm_limit_hw_rates +EXPORT_SYMBOL sound/core/snd-pcm 0x3796bdcc snd_pcm_format_little_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x3afc6846 snd_pcm_hw_constraint_ratdens +EXPORT_SYMBOL sound/core/snd-pcm 0x4a8dddf4 snd_pcm_hw_param_last +EXPORT_SYMBOL sound/core/snd-pcm 0x4c90fb3d snd_pcm_hw_refine +EXPORT_SYMBOL sound/core/snd-pcm 0x4d9b6d35 snd_pcm_format_size +EXPORT_SYMBOL sound/core/snd-pcm 0x4f816e9b snd_pcm_format_big_endian +EXPORT_SYMBOL sound/core/snd-pcm 0x5bd0bbe4 snd_pcm_lib_preallocate_pages +EXPORT_SYMBOL sound/core/snd-pcm 0x5e7f4920 snd_pcm_format_set_silence +EXPORT_SYMBOL sound/core/snd-pcm 0x62ce7977 snd_pcm_hw_constraint_step +EXPORT_SYMBOL sound/core/snd-pcm 0x648ab414 snd_pcm_kernel_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x650f8603 snd_pcm_format_silence_64 +EXPORT_SYMBOL sound/core/snd-pcm 0x68a24153 snd_pcm_format_physical_width +EXPORT_SYMBOL sound/core/snd-pcm 0x6d02a922 snd_pcm_release_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x6d6a2e6a snd_pcm_mmap_data +EXPORT_SYMBOL sound/core/snd-pcm 0x6e5520d5 snd_pcm_hw_constraint_msbits +EXPORT_SYMBOL sound/core/snd-pcm 0x6ef8fcd8 snd_pcm_format_linear +EXPORT_SYMBOL sound/core/snd-pcm 0x7302946e snd_pcm_stop +EXPORT_SYMBOL sound/core/snd-pcm 0x7bc96f8a snd_pcm_lib_ioctl +EXPORT_SYMBOL sound/core/snd-pcm 0x7c5cec98 _snd_pcm_hw_params_any +EXPORT_SYMBOL sound/core/snd-pcm 0x83ae48dc snd_pcm_hw_param_first +EXPORT_SYMBOL sound/core/snd-pcm 0x8845ad13 snd_pcm_lib_read +EXPORT_SYMBOL sound/core/snd-pcm 0x88cc66cc snd_pcm_link_rwlock +EXPORT_SYMBOL sound/core/snd-pcm 0x89a31a56 _snd_pcm_hw_param_setempty +EXPORT_SYMBOL sound/core/snd-pcm 0x8d5a4085 snd_pcm_lib_preallocate_pages_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0x91bf4380 snd_pcm_open_substream +EXPORT_SYMBOL sound/core/snd-pcm 0x9fdea959 snd_pcm_hw_param_value +EXPORT_SYMBOL sound/core/snd-pcm 0xa41a6de8 snd_pcm_lib_mmap_iomem +EXPORT_SYMBOL sound/core/snd-pcm 0xa4a9b795 snd_pcm_hw_constraint_pow2 +EXPORT_SYMBOL sound/core/snd-pcm 0xa61aa028 snd_pcm_format_unsigned +EXPORT_SYMBOL sound/core/snd-pcm 0xb0d67511 snd_pcm_new_stream +EXPORT_SYMBOL sound/core/snd-pcm 0xb4e01518 snd_pcm_hw_constraint_list +EXPORT_SYMBOL sound/core/snd-pcm 0xb9638db4 snd_pcm_rate_to_rate_bit +EXPORT_SYMBOL sound/core/snd-pcm 0xbbb6cd42 snd_pcm_lib_free_pages +EXPORT_SYMBOL sound/core/snd-pcm 0xbbd0ac48 snd_pcm_hw_rule_add +EXPORT_SYMBOL sound/core/snd-pcm 0xbe54ffea snd_pcm_notify +EXPORT_SYMBOL sound/core/snd-pcm 0xc89e9984 snd_pcm_lib_readv +EXPORT_SYMBOL sound/core/snd-pcm 0xcc347c60 snd_pcm_lib_preallocate_free_for_all +EXPORT_SYMBOL sound/core/snd-pcm 0xce20964d snd_pcm_set_ops +EXPORT_SYMBOL sound/core/snd-pcm 0xd0b9b8b8 snd_interval_list +EXPORT_SYMBOL sound/core/snd-pcm 0xd22a21bf snd_pcm_sgbuf_ops_page +EXPORT_SYMBOL sound/core/snd-pcm 0xe56a9336 snd_pcm_format_width +EXPORT_SYMBOL sound/core/snd-pcm 0xecf24805 snd_pcm_period_elapsed +EXPORT_SYMBOL sound/core/snd-pcm 0xeffbfb1e snd_pcm_new +EXPORT_SYMBOL sound/core/snd-pcm 0xf1bbba07 snd_pcm_lib_write +EXPORT_SYMBOL sound/core/snd-pcm 0xf3797152 snd_interval_ratnum +EXPORT_SYMBOL sound/core/snd-rawmidi 0x00dfc502 snd_rawmidi_set_ops +EXPORT_SYMBOL sound/core/snd-rawmidi 0x0ef6d536 snd_rawmidi_drain_input +EXPORT_SYMBOL sound/core/snd-rawmidi 0x1b80ff5d snd_rawmidi_transmit_ack +EXPORT_SYMBOL sound/core/snd-rawmidi 0x250e0759 snd_rawmidi_transmit_peek +EXPORT_SYMBOL sound/core/snd-rawmidi 0x289cbc09 snd_rawmidi_info_select +EXPORT_SYMBOL sound/core/snd-rawmidi 0x3d75a6f7 snd_rawmidi_output_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0x478fee4f snd_rawmidi_drop_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0x51227bb2 snd_rawmidi_receive +EXPORT_SYMBOL sound/core/snd-rawmidi 0x58480e05 snd_rawmidi_drain_output +EXPORT_SYMBOL sound/core/snd-rawmidi 0x7e61597f snd_rawmidi_input_params +EXPORT_SYMBOL sound/core/snd-rawmidi 0x929bee41 snd_rawmidi_transmit +EXPORT_SYMBOL sound/core/snd-rawmidi 0x9cfb9dfc snd_rawmidi_new +EXPORT_SYMBOL sound/core/snd-rawmidi 0xb37b753e snd_rawmidi_kernel_release +EXPORT_SYMBOL sound/core/snd-rawmidi 0xbef042ca snd_rawmidi_kernel_open +EXPORT_SYMBOL sound/core/snd-rawmidi 0xca1b5d62 snd_rawmidi_kernel_write +EXPORT_SYMBOL sound/core/snd-rawmidi 0xd850ea2d snd_rawmidi_kernel_read +EXPORT_SYMBOL sound/core/snd-rawmidi 0xfd149e6d snd_rawmidi_transmit_empty +EXPORT_SYMBOL sound/core/snd-timer 0x07450fb9 snd_timer_stop +EXPORT_SYMBOL sound/core/snd-timer 0x33f083cc snd_timer_start +EXPORT_SYMBOL sound/core/snd-timer 0x33fafd5f snd_timer_open +EXPORT_SYMBOL sound/core/snd-timer 0x5f4986bb snd_timer_global_free +EXPORT_SYMBOL sound/core/snd-timer 0x694ed29e snd_timer_global_new +EXPORT_SYMBOL sound/core/snd-timer 0x6f8c6039 snd_timer_new +EXPORT_SYMBOL sound/core/snd-timer 0x7fbdfcd5 snd_timer_resolution +EXPORT_SYMBOL sound/core/snd-timer 0x87c70a16 snd_timer_continue +EXPORT_SYMBOL sound/core/snd-timer 0x98bc5302 snd_timer_global_register +EXPORT_SYMBOL sound/core/snd-timer 0x9a913a23 snd_timer_pause +EXPORT_SYMBOL sound/core/snd-timer 0xb594e640 snd_timer_close +EXPORT_SYMBOL sound/core/snd-timer 0xe8abeb1d snd_timer_notify +EXPORT_SYMBOL sound/core/snd-timer 0xfd28675e snd_timer_interrupt +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x73c4c993 snd_mpu401_uart_interrupt_tx +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xb5c3f4e7 snd_mpu401_uart_new +EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xfe618b58 snd_mpu401_uart_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x05060a19 snd_opl3_regmap +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x3b9859f3 snd_opl3_timer_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x4d7beb24 snd_opl3_reset +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x5286b03c snd_opl3_init +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x547f4f16 snd_opl3_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x7fe37468 snd_opl3_hwdep_new +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x95d17484 snd_opl3_create +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x9ea02fe9 snd_opl3_find_patch +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xb49962b9 snd_opl3_interrupt +EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xeca6de46 snd_opl3_load_patch +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0x3c6da47d snd_opl4_write_memory +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0x8ad143a7 snd_opl4_read_memory +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0xbca6a08a snd_opl4_write +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0xd8d624d6 snd_opl4_read +EXPORT_SYMBOL sound/drivers/opl4/snd-opl4-lib 0xf546f1f5 snd_opl4_create +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x1cadb14b snd_vx_irq_handler +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x35e34024 snd_vx_create +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x539e6a78 snd_vx_dsp_load +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x5c5da137 snd_vx_suspend +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x6925b5df snd_vx_check_reg_bit +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x876464d8 snd_vx_setup_firmware +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xa6633b96 snd_vx_dsp_boot +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xa8b539ae snd_vx_free_firmware +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xcbff3571 snd_vx_resume +EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xd50bfd87 snd_vx_load_boot_image +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x01c958fe snd_ak4114_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x586a4d45 snd_ak4114_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xa321b377 snd_ak4114_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xabbc5b5f snd_ak4114_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xb3282a20 snd_ak4114_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xc10185f0 snd_ak4114_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x037cf520 snd_ak4117_reg_write +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x2e559e1a snd_ak4117_check_rate_and_errors +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x41a1dce5 snd_ak4117_create +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x58770fa7 snd_ak4117_external_rate +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x5b486591 snd_ak4117_build +EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x92a23e2c snd_ak4117_reinit +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x3691ffeb snd_akm4xxx_init +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x38ce79f7 snd_akm4xxx_reset +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x8f46bfef snd_akm4xxx_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xd4bef113 snd_akm4xxx_write +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x1db61411 snd_pt2258_reset +EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x9bcb3f04 snd_pt2258_build_controls +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0x20fb9b6c snd_tea575x_init +EXPORT_SYMBOL sound/i2c/other/snd-tea575x-tuner 0x441a0be2 snd_tea575x_exit +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x00c53f2d snd_cs8427_iec958_active +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x2cb11956 snd_cs8427_iec958_pcm +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x603b1cbd snd_cs8427_iec958_build +EXPORT_SYMBOL sound/i2c/snd-cs8427 0x7e748da3 snd_cs8427_create +EXPORT_SYMBOL sound/i2c/snd-cs8427 0xd6aafa26 snd_cs8427_reg_write +EXPORT_SYMBOL sound/i2c/snd-i2c 0x1d12f2ca snd_i2c_readbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0x6eedd547 snd_i2c_device_free +EXPORT_SYMBOL sound/i2c/snd-i2c 0x7d8a902f snd_i2c_sendbytes +EXPORT_SYMBOL sound/i2c/snd-i2c 0x9129e15c snd_i2c_probeaddr +EXPORT_SYMBOL sound/i2c/snd-i2c 0xa504e760 snd_i2c_bus_create +EXPORT_SYMBOL sound/i2c/snd-i2c 0xe7de23c0 snd_i2c_device_create +EXPORT_SYMBOL sound/i2c/snd-tea6330t 0x36e380cb snd_tea6330t_detect +EXPORT_SYMBOL sound/i2c/snd-tea6330t 0xbc47f50a snd_tea6330t_update_mixer +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0x4d879638 snd_ad1848_create +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0x61b150ac snd_ad1848_mixer +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0xcfb640ae snd_ad1848_out +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0xdf59c968 snd_ad1848_add_ctl_elem +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0xe73c2365 snd_ad1848_get_pcm_ops +EXPORT_SYMBOL sound/isa/ad1848/snd-ad1848-lib 0xf867748f snd_ad1848_pcm +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x1a45cf5e snd_cs4231_info_double +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x1e8acf81 snd_cs4231_put_single +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x35a7ce29 snd_cs4231_info_single +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x415bbbeb snd_cs4231_chip_id +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x51e9857f snd_cs4231_get_single +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x6302aa57 snd_cs4231_mce_up +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x6aef77cf snd_cs4231_in +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x71e0b894 snd_cs4231_create +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x78006466 snd_cs4231_mixer +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x94324cca snd_cs4231_mce_down +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x98184ad4 snd_cs4231_overrange +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x9d2d09ee snd_cs4236_ext_in +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0x9fa783e1 snd_cs4231_get_double +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xae5f2a81 snd_cs4236_ext_out +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xb50f33b3 snd_cs4231_pcm +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xbb38a9aa snd_cs4231_interrupt +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xbd834593 snd_cs4231_out +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xc7182ce6 snd_cs4231_timer +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4231-lib 0xd0c4c91f snd_cs4231_put_double +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4236-lib 0x56dba489 snd_cs4236_mixer +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4236-lib 0xa0458ea1 snd_cs4236_pcm +EXPORT_SYMBOL sound/isa/cs423x/snd-cs4236-lib 0xfbd19891 snd_cs4236_create +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0x0138b414 snd_es1688_mixer_write +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0x19d094b6 snd_es1688_mixer +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0xb2bf73ed snd_es1688_pcm +EXPORT_SYMBOL sound/isa/es1688/snd-es1688-lib 0xfce8460a snd_es1688_create +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x02553a01 snd_gf1_pcm_new +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x02771d28 snd_gf1_peek +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x0d360518 snd_gf1_translate_freq +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x2183e660 snd_gus_use_dec +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x273a3452 snd_gf1_ctrl_stop +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x2af4227f snd_gf1_i_look16 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x2ece7301 snd_gus_initialize +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x46db8d67 snd_gf1_lvol_to_gvol_raw +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x48b0282e snd_gus_use_inc +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x4a099f5c snd_gus_dram_write +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x4e62d6a3 snd_gus_create +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x65487980 snd_gus_dram_read +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x6cceb441 snd_gf1_dram_addr +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x6f0d62b8 snd_gf1_i_look8 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x86149ce6 snd_gf1_alloc_voice +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0x940aeeed snd_gf1_new_mixer +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xa0ee271c snd_gf1_i_write8 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xaae3e36d snd_gf1_look8 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xabd50473 snd_gf1_free_voice +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xb5e4bb72 snd_gf1_look16 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xb8401160 snd_gf1_rawmidi_new +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xc31af61d snd_gf1_mem_alloc +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xc43a5527 snd_gf1_atten_table +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xcc568946 snd_gf1_delay +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xce1536ce snd_gf1_write_addr +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xd85053ba snd_gf1_mem_free +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xdaed1492 snd_gf1_stop_voice +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xdb252880 snd_gf1_mem_xfree +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xe1ed0967 snd_gf1_poke +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xe4211e42 snd_gf1_write8 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xeca2dd3e snd_gf1_mem_lock +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xf1333c89 snd_gf1_write16 +EXPORT_SYMBOL sound/isa/gus/snd-gus-lib 0xf963a997 snd_gus_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x3b99aab1 snd_sbmixer_new +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x4b380be7 snd_sbmixer_add_ctl +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x4c263df1 snd_sbmixer_resume +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x7970289a snd_sbdsp_create +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x98e9a50e snd_sbmixer_write +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x9c51e094 snd_sbmixer_read +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xa535349e snd_sbdsp_get_byte +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xdedd1ff9 snd_sbdsp_command +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xe2285390 snd_sbdsp_reset +EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xee36e954 snd_sbmixer_suspend +EXPORT_SYMBOL sound/isa/sb/snd-sb16-csp 0x3ee873ae snd_sb_csp_new +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x081033d0 snd_sb16dsp_configure +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x0ba4ef1d snd_sb16dsp_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x30bac7d1 snd_sb16dsp_pcm +EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0xaeb25e10 snd_sb16dsp_get_pcm_ops +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0x34e4eef0 snd_sb8dsp_midi +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0x5a18a4a8 snd_sb8dsp_midi_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0x7df183bc snd_sb8dsp_interrupt +EXPORT_SYMBOL sound/isa/sb/snd-sb8-dsp 0xc5576451 snd_sb8dsp_pcm +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x61e6ff5d snd_emu8000_update_chorus_mode +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x6b39b186 snd_emu8000_peek_dw +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x8ef7cdfa snd_emu8000_load_chorus_fx +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x8fc1fd10 snd_emu8000_poke +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x903ece8e snd_emu8000_dma_chan +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0x951657b9 snd_emu8000_load_reverb_fx +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xb2a0eeaa snd_emu8000_init_fm +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xba3caa43 snd_emu8000_update_reverb_mode +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xcb56819c snd_emu8000_update_equalizer +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xd71c8cc3 snd_emu8000_peek +EXPORT_SYMBOL sound/isa/sb/snd-sbawe 0xe679351a snd_emu8000_poke_dw +EXPORT_SYMBOL sound/oss/ad1848 0x0c6d8a08 attach_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x57f2b9e0 ad1848_detect +EXPORT_SYMBOL sound/oss/ad1848 0x8d660e70 probe_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0x9bf1cc62 ad1848_unload +EXPORT_SYMBOL sound/oss/ad1848 0xafe6684f ad1848_init +EXPORT_SYMBOL sound/oss/ad1848 0xb29a9148 unload_ms_sound +EXPORT_SYMBOL sound/oss/ad1848 0xc04f6f67 ad1848_control +EXPORT_SYMBOL sound/oss/mpu401 0x5febf284 unload_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0x813a35f5 probe_mpu401 +EXPORT_SYMBOL sound/oss/mpu401 0xd72c8220 attach_mpu401 +EXPORT_SYMBOL sound/oss/msnd 0x1186f48f msnd_fifo_read +EXPORT_SYMBOL sound/oss/msnd 0x340a3ddf msnd_init_queue +EXPORT_SYMBOL sound/oss/msnd 0x3867b382 msnd_send_dsp_cmd +EXPORT_SYMBOL sound/oss/msnd 0x54230dc1 msnd_fifo_write +EXPORT_SYMBOL sound/oss/msnd 0x6601493b msnd_fifo_make_empty +EXPORT_SYMBOL sound/oss/msnd 0x8192a440 msnd_register +EXPORT_SYMBOL sound/oss/msnd 0x92098b5b msnd_send_word +EXPORT_SYMBOL sound/oss/msnd 0x9274d677 msnd_fifo_free +EXPORT_SYMBOL sound/oss/msnd 0x986ccb79 msnd_unregister +EXPORT_SYMBOL sound/oss/msnd 0xa0075e9f msnd_enable_irq +EXPORT_SYMBOL sound/oss/msnd 0xade99e25 msnd_fifo_alloc +EXPORT_SYMBOL sound/oss/msnd 0xb3520772 msnd_fifo_init +EXPORT_SYMBOL sound/oss/msnd 0xb46680d3 msnd_upload_host +EXPORT_SYMBOL sound/oss/msnd 0xc266c2da msnd_disable_irq +EXPORT_SYMBOL sound/oss/msnd 0xdf0f59eb msnd_fifo_write_io +EXPORT_SYMBOL sound/oss/msnd 0xf4c4f662 msnd_fifo_read_io +EXPORT_SYMBOL sound/oss/sb_lib 0x42424109 sb_be_quiet +EXPORT_SYMBOL sound/oss/sb_lib 0x450f9aea smw_free +EXPORT_SYMBOL sound/oss/sb_lib 0x74afd69c unload_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0x82373660 probe_sbmpu +EXPORT_SYMBOL sound/oss/sb_lib 0xc4884969 sb_dsp_unload +EXPORT_SYMBOL sound/oss/sb_lib 0xd8a2731c sb_dsp_detect +EXPORT_SYMBOL sound/oss/sb_lib 0xebac81d9 sb_dsp_init +EXPORT_SYMBOL sound/oss/sound 0x04c87ec8 compute_finetune +EXPORT_SYMBOL sound/oss/sound 0x06339815 sound_unload_synthdev +EXPORT_SYMBOL sound/oss/sound 0x0f280035 conf_printf +EXPORT_SYMBOL sound/oss/sound 0x17ba231d seq_input_event +EXPORT_SYMBOL sound/oss/sound 0x1b3df3cf sound_alloc_mixerdev +EXPORT_SYMBOL sound/oss/sound 0x1f395686 MIDIbuf_avail +EXPORT_SYMBOL sound/oss/sound 0x2161d5e8 sound_timer_init +EXPORT_SYMBOL sound/oss/sound 0x2aa31695 midi_synth_kill_note +EXPORT_SYMBOL sound/oss/sound 0x394cb088 sound_free_dma +EXPORT_SYMBOL sound/oss/sound 0x418f5fbe sound_close_dma +EXPORT_SYMBOL sound/oss/sound 0x4cd01bdd num_audiodevs +EXPORT_SYMBOL sound/oss/sound 0x4ff47e9d midi_synth_setup_voice +EXPORT_SYMBOL sound/oss/sound 0x51e354b2 sound_alloc_timerdev +EXPORT_SYMBOL sound/oss/sound 0x56504ca2 midi_synth_reset +EXPORT_SYMBOL sound/oss/sound 0x5d986fc9 note_to_freq +EXPORT_SYMBOL sound/oss/sound 0x6013f1d7 mixer_devs +EXPORT_SYMBOL sound/oss/sound 0x6259e861 sound_install_audiodrv +EXPORT_SYMBOL sound/oss/sound 0x674dec3c sound_timer_devs +EXPORT_SYMBOL sound/oss/sound 0x7679ee76 seq_copy_to_input +EXPORT_SYMBOL sound/oss/sound 0x7bdf0907 conf_printf2 +EXPORT_SYMBOL sound/oss/sound 0x892093e0 midi_synth_controller +EXPORT_SYMBOL sound/oss/sound 0x8a7d4d81 sound_install_mixer +EXPORT_SYMBOL sound/oss/sound 0x90bd9714 sequencer_timer +EXPORT_SYMBOL sound/oss/sound 0x9517ef88 synth_devs +EXPORT_SYMBOL sound/oss/sound 0x987bcf12 DMAbuf_outputintr +EXPORT_SYMBOL sound/oss/sound 0x9a95733f sound_alloc_dma +EXPORT_SYMBOL sound/oss/sound 0x9bdaf24d midi_synth_start_note +EXPORT_SYMBOL sound/oss/sound 0x9d845b18 num_mixers +EXPORT_SYMBOL sound/oss/sound 0xa062459f audio_devs +EXPORT_SYMBOL sound/oss/sound 0xa1d5f04f load_mixer_volumes +EXPORT_SYMBOL sound/oss/sound 0xa1eae7cf num_midis +EXPORT_SYMBOL sound/oss/sound 0xa41ead5f sound_unload_timerdev +EXPORT_SYMBOL sound/oss/sound 0xa51c913b sound_unload_mixerdev +EXPORT_SYMBOL sound/oss/sound 0xa6bb414c sound_unload_mididev +EXPORT_SYMBOL sound/oss/sound 0xa948751e sound_unload_audiodev +EXPORT_SYMBOL sound/oss/sound 0xad45df73 midi_synth_close +EXPORT_SYMBOL sound/oss/sound 0xaef743b2 midi_synth_ioctl +EXPORT_SYMBOL sound/oss/sound 0xb14b22cd midi_synth_hw_control +EXPORT_SYMBOL sound/oss/sound 0xb51587f6 do_midi_msg +EXPORT_SYMBOL sound/oss/sound 0xba413f87 sound_alloc_mididev +EXPORT_SYMBOL sound/oss/sound 0xba7dd041 midi_synth_bender +EXPORT_SYMBOL sound/oss/sound 0xc35ff4ed midi_devs +EXPORT_SYMBOL sound/oss/sound 0xc748d109 sound_alloc_synthdev +EXPORT_SYMBOL sound/oss/sound 0xcc4b8797 sound_open_dma +EXPORT_SYMBOL sound/oss/sound 0xd85be938 midi_synth_set_instr +EXPORT_SYMBOL sound/oss/sound 0xdb400afa midi_synth_panning +EXPORT_SYMBOL sound/oss/sound 0xe056b71c DMAbuf_start_dma +EXPORT_SYMBOL sound/oss/sound 0xe2675a79 sound_timer_interrupt +EXPORT_SYMBOL sound/oss/sound 0xeb315d99 DMAbuf_inputintr +EXPORT_SYMBOL sound/oss/sound 0xf1ea8a20 midi_synth_aftertouch +EXPORT_SYMBOL sound/oss/sound 0xf6b3a2fb midi_synth_open +EXPORT_SYMBOL sound/oss/sound 0xf7426da3 midi_synth_load_patch +EXPORT_SYMBOL sound/oss/sound 0xf78f6363 sequencer_init +EXPORT_SYMBOL sound/oss/sound 0xfa6871be sound_timer_syncinterval +EXPORT_SYMBOL sound/oss/sound 0xfddcbfb3 midi_synth_send_sysex +EXPORT_SYMBOL sound/oss/uart401 0x46248c57 uart401intr +EXPORT_SYMBOL sound/oss/uart401 0xc9c193bb probe_uart401 +EXPORT_SYMBOL sound/oss/uart401 0xecfdd9c9 unload_uart401 +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x039c0b61 snd_ac97_read +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x0aa4aeb3 snd_ac97_update +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x357617ec snd_ac97_pcm_assign +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x371dfda7 snd_ac97_get_short_name +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3b707c4e snd_ac97_pcm_close +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x44fb3985 snd_ac97_pcm_open +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x46cf30b1 snd_ac97_update_bits +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x52e0dcff snd_ac97_pcm_double_rate_rules +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x5890b18a snd_ac97_mixer +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x73640f6d snd_ac97_update_power +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x785a3fd4 snd_ac97_suspend +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x8f6e1a40 snd_ac97_bus +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x93215828 snd_ac97_resume +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x9362e941 snd_ac97_write +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x9cb17fbc snd_ac97_write_cache +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xb25d7310 snd_ac97_set_rate +EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xea12e24a snd_ac97_tune_hardware +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x0e3f3cf9 snd_emu10k1_synth_copy_from_user +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x231cceb8 snd_emu10k1_memblk_map +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x251fd0c2 snd_emu10k1_ptr_write +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x8efb7464 snd_emu10k1_synth_free +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xbb2f33de snd_emu10k1_synth_bzero +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xc2951fd5 snd_emu10k1_synth_alloc +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xcb550ea8 snd_emu10k1_voice_free +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xdde25f2d snd_emu10k1_ptr_read +EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xf8e3c1e4 snd_emu10k1_voice_alloc +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xb0001f18 snd_ice1712_akm4xxx_build_controls +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xb4c11cf6 snd_ice1712_akm4xxx_free +EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xc02f5d63 snd_ice1712_akm4xxx_init +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x1c1581a5 oxygen_read8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x4c0a0619 oxygen_read32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x54108304 oxygen_pci_resume +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x662139a5 oxygen_write16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x7e533f7f oxygen_write8 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x846d52a4 oxygen_write16_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x8f67a668 oxygen_write_i2c +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xa909230c oxygen_pci_remove +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xac11d929 oxygen_write_ac97_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xaec04027 oxygen_pci_probe +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xb0c8a719 oxygen_write32 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xc5c4919c oxygen_write8_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xd55909e7 oxygen_read_ac97 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xe0a48189 oxygen_write32_masked +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xe84bf24e oxygen_write_spi +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xe881a443 oxygen_read16 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xeae89c6f oxygen_write_ac97 +EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xf7a25e75 oxygen_pci_suspend +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x37364249 snd_trident_start_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x4cf200c6 snd_trident_stop_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0x8d7a666b snd_trident_free_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0xb51d69ae snd_trident_alloc_voice +EXPORT_SYMBOL sound/pci/trident/snd-trident 0xc7101eb6 snd_trident_write_voice_regs +EXPORT_SYMBOL sound/sound_firmware 0x39e3dd23 mod_firmware_load +EXPORT_SYMBOL sound/soundcore 0x40faa2c8 register_sound_midi +EXPORT_SYMBOL sound/soundcore 0x62d0f003 sound_class +EXPORT_SYMBOL sound/soundcore 0x6fa4f70a register_sound_special +EXPORT_SYMBOL sound/soundcore 0x709da22a register_sound_special_device +EXPORT_SYMBOL sound/soundcore 0x7afc9d8a unregister_sound_mixer +EXPORT_SYMBOL sound/soundcore 0x99c95fa5 unregister_sound_special +EXPORT_SYMBOL sound/soundcore 0xcd083b10 unregister_sound_dsp +EXPORT_SYMBOL sound/soundcore 0xe49f4596 register_sound_mixer +EXPORT_SYMBOL sound/soundcore 0xf06ee81f register_sound_dsp +EXPORT_SYMBOL sound/soundcore 0xfdab6de3 unregister_sound_midi +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x55286f49 snd_emux_free +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x62adc648 snd_emux_lock_voice +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x655cb202 snd_sf_linear_to_log +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x8ced337f snd_emux_terminate_all +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xd257b9b0 snd_emux_register +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xd6cb9ca6 snd_emux_unlock_voice +EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xe9545d46 snd_emux_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0x20d65978 snd_util_memhdr_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x24886293 __snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0x569d614e snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0x7a007343 snd_util_memhdr_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd197c5db __snd_util_memblk_new +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd34b56e4 __snd_util_mem_free +EXPORT_SYMBOL sound/synth/snd-util-mem 0xd8b55e81 snd_util_mem_alloc +EXPORT_SYMBOL sound/synth/snd-util-mem 0xf158252c snd_util_mem_avail +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x16756dc0 snd_usbmidi_input_start +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x492d8941 snd_usb_create_midi_interface +EXPORT_SYMBOL sound/usb/snd-usb-lib 0x63343b1d snd_usbmidi_input_stop +EXPORT_SYMBOL sound/usb/snd-usb-lib 0xd9d2bb03 snd_usbmidi_disconnect +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x1faf386f dm_mem_cache_free +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x2eda663f dm_mem_cache_shrink +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0x81752d89 dm_mem_cache_client_create +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xac717d98 dm_mem_cache_client_destroy +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xb59e9e75 dm_mem_cache_alloc +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-mem-cache 0xfb3eab24 dm_mem_cache_grow +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-message 0x920a7a41 dm_message_parse +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x0329d132 rh_sector_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x04c69211 rh_inc_pending +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x108f2649 rh_dec +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x275fdd04 rh_recovery_start +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x31678605 rh_delay +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x5c2a0632 rh_recovery_end +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x62842029 rh_flush +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x6dc10d49 rh_bio_to_region +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x8252ef05 rh_state +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x8821f9a7 rh_region_to_sector +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0x968f3642 rh_init +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xa4a7321f rh_get_region_key +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xa923d788 rh_start_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xac274ed3 rh_stop_recovery +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xb513be98 rh_update_states +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xbb748327 rh_reg_set_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4fdf256 rh_recovery_prepare +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc4ff7745 rh_reg_get_context +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xc57bafec rh_exit +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xd99f0978 rh_inc +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xda581f7b rh_get_region_size +EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-region_hash 0xea4cdb97 rh_delay_by_region +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x29c887a9 set_tx_channels +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x60b2e316 cmdir_read +EXPORT_SYMBOL ubuntu/lirc/lirc_cmdir/commandir 0x7789312a cmdir_write +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x17ba1288 lirc_register_plugin +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x3ce347c8 lirc_get_pdata +EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0xe96379eb lirc_unregister_plugin +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0x7db9be3c ov511_deregister_decomp_module +EXPORT_SYMBOL ubuntu/misc/media/ov511/ov511 0x8282c5de ov511_register_decomp_module +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x403c43b3 p80211skb_rxmeta_attach +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x5662c1b0 wlan_unsetup +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x6fd677f6 p80211_suspend +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x8d93a766 p80211wext_event_associated +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0x8e06e5bf wlan_setup +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xa2d26eda p80211_resume +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xaed0d692 p80211_allow_ioctls +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb0af0799 wlan_wext_write +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xb0ff7349 p80211netdev_hwremoved +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xde875dff p80211skb_free +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xea7c7e0f register_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xf7d8db59 unregister_wlandev +EXPORT_SYMBOL ubuntu/misc/wireless/p80211/p80211 0xfd3298a8 p80211netdev_rx +EXPORT_SYMBOL vmlinux 0x00112f51 groups_alloc +EXPORT_SYMBOL vmlinux 0x0027e289 __inode_dir_notify +EXPORT_SYMBOL vmlinux 0x0034736e __lock_buffer +EXPORT_SYMBOL vmlinux 0x0055a1d8 register_netdev +EXPORT_SYMBOL vmlinux 0x005c945c get_super +EXPORT_SYMBOL vmlinux 0x00701c0f put_io_context +EXPORT_SYMBOL vmlinux 0x00801678 flush_scheduled_work +EXPORT_SYMBOL vmlinux 0x0080fcd6 tcf_hash_release +EXPORT_SYMBOL vmlinux 0x0087888d ps2_handle_ack +EXPORT_SYMBOL vmlinux 0x00905f76 dev_set_promiscuity +EXPORT_SYMBOL vmlinux 0x00925f05 mpage_readpage +EXPORT_SYMBOL vmlinux 0x009d258f _write_lock +EXPORT_SYMBOL vmlinux 0x00b0412d kill_fasync +EXPORT_SYMBOL vmlinux 0x00e8097b csum_partial_copy_fromiovecend +EXPORT_SYMBOL vmlinux 0x0102389b netpoll_cleanup +EXPORT_SYMBOL vmlinux 0x0110a644 xrlim_allow +EXPORT_SYMBOL vmlinux 0x01139ffc max_mapnr +EXPORT_SYMBOL vmlinux 0x0122c61c pid_task +EXPORT_SYMBOL vmlinux 0x015f7d04 serio_unregister_child_port +EXPORT_SYMBOL vmlinux 0x0186d073 percpu_counter_set +EXPORT_SYMBOL vmlinux 0x018a91ff pnpbios_protocol +EXPORT_SYMBOL vmlinux 0x01902adf netpoll_trap +EXPORT_SYMBOL vmlinux 0x01a4aab6 set_irq_chip_data +EXPORT_SYMBOL vmlinux 0x01bc6e36 vfs_dq_quota_on_remount +EXPORT_SYMBOL vmlinux 0x01bd8d7a inode_add_bytes +EXPORT_SYMBOL vmlinux 0x01d19038 acpi_enable_subsystem +EXPORT_SYMBOL vmlinux 0x01d214f9 __xfrm_policy_check +EXPORT_SYMBOL vmlinux 0x01d2a828 neigh_update +EXPORT_SYMBOL vmlinux 0x01e3dfd8 pci_bus_read_config_byte +EXPORT_SYMBOL vmlinux 0x01fc8bde add_to_page_cache_locked +EXPORT_SYMBOL vmlinux 0x0203f97c serio_unregister_port +EXPORT_SYMBOL vmlinux 0x02124474 ip_send_check +EXPORT_SYMBOL vmlinux 0x02138f9d bioset_integrity_create +EXPORT_SYMBOL vmlinux 0x022c5371 atm_alloc_charge +EXPORT_SYMBOL vmlinux 0x022dc2ad blk_get_request +EXPORT_SYMBOL vmlinux 0x0237b57a arch_unregister_cpu +EXPORT_SYMBOL vmlinux 0x025277f6 profile_pc +EXPORT_SYMBOL vmlinux 0x02535379 sock_init_data +EXPORT_SYMBOL vmlinux 0x0254e828 acpi_bus_start +EXPORT_SYMBOL vmlinux 0x0256389f bit_waitqueue +EXPORT_SYMBOL vmlinux 0x02635772 dev_queue_xmit +EXPORT_SYMBOL vmlinux 0x02649054 security_sock_rcv_skb +EXPORT_SYMBOL vmlinux 0x029444f0 native_read_tsc +EXPORT_SYMBOL vmlinux 0x02a18c74 nf_conntrack_destroy +EXPORT_SYMBOL vmlinux 0x02aff2f4 acpi_install_gpe_handler +EXPORT_SYMBOL vmlinux 0x02cdf7a9 ip_dev_find +EXPORT_SYMBOL vmlinux 0x02d81845 audit_log_task_context +EXPORT_SYMBOL vmlinux 0x02e84d1b per_cpu__cpu_sibling_map +EXPORT_SYMBOL vmlinux 0x02ee26c1 free_pages_exact +EXPORT_SYMBOL vmlinux 0x0334da4e scsi_command_size_tbl +EXPORT_SYMBOL vmlinux 0x035f09c5 flush_old_exec +EXPORT_SYMBOL vmlinux 0x037a0cba kfree +EXPORT_SYMBOL vmlinux 0x038855d5 udp_poll +EXPORT_SYMBOL vmlinux 0x03a99c3b rb_prev +EXPORT_SYMBOL vmlinux 0x03bf0b40 dev_mc_unsync +EXPORT_SYMBOL vmlinux 0x03c06156 bitmap_fold +EXPORT_SYMBOL vmlinux 0x041fddcf pci_map_rom +EXPORT_SYMBOL vmlinux 0x0422fe4a inet_csk_timer_bug_msg +EXPORT_SYMBOL vmlinux 0x044a3ea3 dma_async_client_unregister +EXPORT_SYMBOL vmlinux 0x044fbf49 mempool_kzalloc +EXPORT_SYMBOL vmlinux 0x0451351c input_release_device +EXPORT_SYMBOL vmlinux 0x0469c5be ip_nat_decode_session +EXPORT_SYMBOL vmlinux 0x0487f831 fb_find_best_display +EXPORT_SYMBOL vmlinux 0x04d8c750 release_perfctr_nmi +EXPORT_SYMBOL vmlinux 0x05150a88 udp_flush_pending_frames +EXPORT_SYMBOL vmlinux 0x051c6d2c pci_reenable_device +EXPORT_SYMBOL vmlinux 0x053f7a29 km_policy_notify +EXPORT_SYMBOL vmlinux 0x055156cd xfrm4_rcv_encap +EXPORT_SYMBOL vmlinux 0x0560cdeb xfrm_state_flush +EXPORT_SYMBOL vmlinux 0x057ce975 hex_dump_to_buffer +EXPORT_SYMBOL vmlinux 0x058c75d9 acpi_get_pci_id +EXPORT_SYMBOL vmlinux 0x05a737f4 tcp_poll +EXPORT_SYMBOL vmlinux 0x061651be strcat +EXPORT_SYMBOL vmlinux 0x0621eba4 dcache_dir_open +EXPORT_SYMBOL vmlinux 0x06375762 seq_open_private +EXPORT_SYMBOL vmlinux 0x0664a5d6 skb_under_panic +EXPORT_SYMBOL vmlinux 0x0665ae22 acpi_bus_get_device +EXPORT_SYMBOL vmlinux 0x067d8d35 security_release_secctx +EXPORT_SYMBOL vmlinux 0x06b014fe cpu_sysdev_class +EXPORT_SYMBOL vmlinux 0x06d728b1 tcp_parse_md5sig_option +EXPORT_SYMBOL vmlinux 0x06e85798 fput +EXPORT_SYMBOL vmlinux 0x06fe3b14 default_grn +EXPORT_SYMBOL vmlinux 0x0727c4f3 iowrite8 +EXPORT_SYMBOL vmlinux 0x073dfa12 generate_resume_trace +EXPORT_SYMBOL vmlinux 0x07608604 acpi_get_vendor_resource +EXPORT_SYMBOL vmlinux 0x078d588d acpi_bus_get_status +EXPORT_SYMBOL vmlinux 0x0799aca4 local_bh_enable +EXPORT_SYMBOL vmlinux 0x079cd7f1 ns_to_timeval +EXPORT_SYMBOL vmlinux 0x07a890c8 fb_alloc_cmap +EXPORT_SYMBOL vmlinux 0x07cc4a5d printk_timed_ratelimit +EXPORT_SYMBOL vmlinux 0x07d50a24 csum_partial +EXPORT_SYMBOL vmlinux 0x0817be44 ps2_sendbyte +EXPORT_SYMBOL vmlinux 0x082a0e4a blk_queue_invalidate_tags +EXPORT_SYMBOL vmlinux 0x082c3213 pci_root_buses +EXPORT_SYMBOL vmlinux 0x082f5a1d blk_queue_dma_alignment +EXPORT_SYMBOL vmlinux 0x083a9b18 register_con_driver +EXPORT_SYMBOL vmlinux 0x08a6d6ed mem_map +EXPORT_SYMBOL vmlinux 0x08de0f33 ht_create_irq +EXPORT_SYMBOL vmlinux 0x08fd2b3d __inc_zone_page_state +EXPORT_SYMBOL vmlinux 0x09052c0c kset_unregister +EXPORT_SYMBOL vmlinux 0x0933aae1 efi_enabled +EXPORT_SYMBOL vmlinux 0x093e947e posix_acl_create_masq +EXPORT_SYMBOL vmlinux 0x0944bc4c netpoll_poll +EXPORT_SYMBOL vmlinux 0x0948cde9 num_physpages +EXPORT_SYMBOL vmlinux 0x09775cdc kref_get +EXPORT_SYMBOL vmlinux 0x0977d453 udp_proc_unregister +EXPORT_SYMBOL vmlinux 0x097a0f1f __mpage_writepage +EXPORT_SYMBOL vmlinux 0x098b71c6 fb_dealloc_cmap +EXPORT_SYMBOL vmlinux 0x098bcad4 xfrm_state_delete_tunnel +EXPORT_SYMBOL vmlinux 0x09c50f12 give_up_console +EXPORT_SYMBOL vmlinux 0x09c55cec schedule_timeout_interruptible +EXPORT_SYMBOL vmlinux 0x09c8b637 fib_default_rule_add +EXPORT_SYMBOL vmlinux 0x09d44df9 in_lock_functions +EXPORT_SYMBOL vmlinux 0x09fe94d6 pci_release_region +EXPORT_SYMBOL vmlinux 0x0a2487e0 unblock_all_signals +EXPORT_SYMBOL vmlinux 0x0a3131f6 strnchr +EXPORT_SYMBOL vmlinux 0x0a93119f input_grab_device +EXPORT_SYMBOL vmlinux 0x0aa94892 tcp_v4_md5_lookup +EXPORT_SYMBOL vmlinux 0x0acb1a3c __bitmap_shift_right +EXPORT_SYMBOL vmlinux 0x0ad7cb4c tty_wait_until_sent +EXPORT_SYMBOL vmlinux 0x0ad88a4c __neigh_for_each_release +EXPORT_SYMBOL vmlinux 0x0b161e80 simple_pin_fs +EXPORT_SYMBOL vmlinux 0x0b1beb31 vmalloc_32_user +EXPORT_SYMBOL vmlinux 0x0b289ce2 inet_del_protocol +EXPORT_SYMBOL vmlinux 0x0b742fd7 simple_strtol +EXPORT_SYMBOL vmlinux 0x0bad0f35 tcp_tso_segment +EXPORT_SYMBOL vmlinux 0x0bb18f1a tty_name +EXPORT_SYMBOL vmlinux 0x0bb9d5b4 proc_dointvec_ms_jiffies +EXPORT_SYMBOL vmlinux 0x0bccd098 create_proc_entry +EXPORT_SYMBOL vmlinux 0x0bf93258 sb_set_blocksize +EXPORT_SYMBOL vmlinux 0x0c2fa293 elv_rb_former_request +EXPORT_SYMBOL vmlinux 0x0c3a26c3 udp_ioctl +EXPORT_SYMBOL vmlinux 0x0c5c69e3 flow_cache_lookup +EXPORT_SYMBOL vmlinux 0x0c5ef91b per_cpu__vm_event_states +EXPORT_SYMBOL vmlinux 0x0c6cbe82 __mark_inode_dirty +EXPORT_SYMBOL vmlinux 0x0c712b13 ip_setsockopt +EXPORT_SYMBOL vmlinux 0x0c87c756 bio_split_pool +EXPORT_SYMBOL vmlinux 0x0c882192 kmem_cache_create +EXPORT_SYMBOL vmlinux 0x0cb152dd call_usermodehelper_freeinfo +EXPORT_SYMBOL vmlinux 0x0cb7cc9a sock_common_recvmsg +EXPORT_SYMBOL vmlinux 0x0cbfb4aa inet_csk_clear_xmit_timers +EXPORT_SYMBOL vmlinux 0x0cceb94b vcc_insert_socket +EXPORT_SYMBOL vmlinux 0x0ccefe9e __kfree_skb +EXPORT_SYMBOL vmlinux 0x0cd7190b sysctl_intvec +EXPORT_SYMBOL vmlinux 0x0d014593 remove_proc_entry +EXPORT_SYMBOL vmlinux 0x0d237d18 xfrm_find_acq +EXPORT_SYMBOL vmlinux 0x0d26a76d _write_lock_irq +EXPORT_SYMBOL vmlinux 0x0d379711 security_task_getsecid +EXPORT_SYMBOL vmlinux 0x0d3dda14 acpi_get_type +EXPORT_SYMBOL vmlinux 0x0d4b77b7 gen_pool_add +EXPORT_SYMBOL vmlinux 0x0d5421f9 vfs_readv +EXPORT_SYMBOL vmlinux 0x0d542439 __ipv6_addr_type +EXPORT_SYMBOL vmlinux 0x0d6c963c copy_from_user +EXPORT_SYMBOL vmlinux 0x0d8ab500 param_set_copystring +EXPORT_SYMBOL vmlinux 0x0da010bf read_cache_pages +EXPORT_SYMBOL vmlinux 0x0da10ec3 security_sock_graft +EXPORT_SYMBOL vmlinux 0x0dc4aa42 qdisc_destroy +EXPORT_SYMBOL vmlinux 0x0de03e5b zero_fill_bio +EXPORT_SYMBOL vmlinux 0x0def1299 sock_release +EXPORT_SYMBOL vmlinux 0x0e1da049 dev_close +EXPORT_SYMBOL vmlinux 0x0e3f8ac2 key_alloc +EXPORT_SYMBOL vmlinux 0x0e52592a panic +EXPORT_SYMBOL vmlinux 0x0e762d6e request_module +EXPORT_SYMBOL vmlinux 0x0e8a02c0 tty_unregister_device +EXPORT_SYMBOL vmlinux 0x0e9b0240 per_cpu__kstat +EXPORT_SYMBOL vmlinux 0x0ea4ee71 ip_mc_inc_group +EXPORT_SYMBOL vmlinux 0x0ec2a26d ethtool_op_get_tx_csum +EXPORT_SYMBOL vmlinux 0x0ec7ccd4 sk_stream_kill_queues +EXPORT_SYMBOL vmlinux 0x0f0748f7 tty_unregister_driver +EXPORT_SYMBOL vmlinux 0x0f09fe50 __dec_zone_page_state +EXPORT_SYMBOL vmlinux 0x0f3b87df xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x0f74d2cd sync_blockdev +EXPORT_SYMBOL vmlinux 0x0faef0ed __tasklet_schedule +EXPORT_SYMBOL vmlinux 0x0fd00a68 acpi_clear_event +EXPORT_SYMBOL vmlinux 0x0ff3bce5 generic_cont_expand_simple +EXPORT_SYMBOL vmlinux 0x1001b549 dmam_release_declared_memory +EXPORT_SYMBOL vmlinux 0x10296d04 find_lock_page +EXPORT_SYMBOL vmlinux 0x104e5bde idr_find +EXPORT_SYMBOL vmlinux 0x10ab54bf mpage_writepage +EXPORT_SYMBOL vmlinux 0x10b064b1 pcim_iounmap +EXPORT_SYMBOL vmlinux 0x10b9c2a5 generic_setxattr +EXPORT_SYMBOL vmlinux 0x10e0fd86 qdisc_list_del +EXPORT_SYMBOL vmlinux 0x10ee20bb default_blu +EXPORT_SYMBOL vmlinux 0x113eecf0 dev_set_mtu +EXPORT_SYMBOL vmlinux 0x115468dd ida_init +EXPORT_SYMBOL vmlinux 0x1163f0a7 blk_max_low_pfn +EXPORT_SYMBOL vmlinux 0x116c27a7 simple_link +EXPORT_SYMBOL vmlinux 0x117093be qdisc_class_hash_init +EXPORT_SYMBOL vmlinux 0x118f01ea putname +EXPORT_SYMBOL vmlinux 0x11a18b14 __wake_up_bit +EXPORT_SYMBOL vmlinux 0x11e6b497 qdisc_tree_decrease_qlen +EXPORT_SYMBOL vmlinux 0x125fbca7 cad_pid +EXPORT_SYMBOL vmlinux 0x126970ed param_set_uint +EXPORT_SYMBOL vmlinux 0x12a537d4 udp_proc_register +EXPORT_SYMBOL vmlinux 0x12c6381f input_close_device +EXPORT_SYMBOL vmlinux 0x12da5bb2 __kmalloc +EXPORT_SYMBOL vmlinux 0x12f99022 inet_frags_init_net +EXPORT_SYMBOL vmlinux 0x13144ed1 vm_insert_mixed +EXPORT_SYMBOL vmlinux 0x132155e1 pci_get_subsys +EXPORT_SYMBOL vmlinux 0x132f45f2 cookie_check_timestamp +EXPORT_SYMBOL vmlinux 0x1330dbbb neigh_changeaddr +EXPORT_SYMBOL vmlinux 0x134c70c2 dcache_dir_close +EXPORT_SYMBOL vmlinux 0x1352898b register_console +EXPORT_SYMBOL vmlinux 0x13a17d31 filemap_flush +EXPORT_SYMBOL vmlinux 0x13c35770 __dev_remove_pack +EXPORT_SYMBOL vmlinux 0x13f71731 tcf_hash_lookup +EXPORT_SYMBOL vmlinux 0x140c8a23 misc_register +EXPORT_SYMBOL vmlinux 0x142a4c1a rtnl_create_link +EXPORT_SYMBOL vmlinux 0x1430e6e0 unregister_acpi_notifier +EXPORT_SYMBOL vmlinux 0x14313f7d skb_realloc_headroom +EXPORT_SYMBOL vmlinux 0x14316619 generic_show_options +EXPORT_SYMBOL vmlinux 0x14713419 inet_release +EXPORT_SYMBOL vmlinux 0x1494dbb9 blk_integrity_unregister +EXPORT_SYMBOL vmlinux 0x14af0cf7 gen_pool_destroy +EXPORT_SYMBOL vmlinux 0x14cc0324 nla_reserve +EXPORT_SYMBOL vmlinux 0x14f332ea up_read +EXPORT_SYMBOL vmlinux 0x150e3cdd simple_empty +EXPORT_SYMBOL vmlinux 0x1544aad4 genl_register_mc_group +EXPORT_SYMBOL vmlinux 0x1551dc51 bitmap_find_free_region +EXPORT_SYMBOL vmlinux 0x158ca53f blk_queue_start_tag +EXPORT_SYMBOL vmlinux 0x15a17dfe unlock_page +EXPORT_SYMBOL vmlinux 0x15b7cdf8 fget +EXPORT_SYMBOL vmlinux 0x15bc1847 xfrm_nl +EXPORT_SYMBOL vmlinux 0x15df1734 neigh_destroy +EXPORT_SYMBOL vmlinux 0x15ef2dd9 kfifo_free +EXPORT_SYMBOL vmlinux 0x16057678 pv_mmu_ops +EXPORT_SYMBOL vmlinux 0x16489ba3 idr_remove +EXPORT_SYMBOL vmlinux 0x164cde7b tcp_v4_send_check +EXPORT_SYMBOL vmlinux 0x166cd68d netlink_broadcast +EXPORT_SYMBOL vmlinux 0x167e7f9d __get_user_1 +EXPORT_SYMBOL vmlinux 0x16977979 blk_queue_end_tag +EXPORT_SYMBOL vmlinux 0x16a35878 _read_unlock +EXPORT_SYMBOL vmlinux 0x16af701b neigh_connected_output +EXPORT_SYMBOL vmlinux 0x16f7985b bdi_register +EXPORT_SYMBOL vmlinux 0x170c25ee acpi_get_next_object +EXPORT_SYMBOL vmlinux 0x172ed4d7 __vmalloc +EXPORT_SYMBOL vmlinux 0x175a298d acpi_set_firmware_waking_vector +EXPORT_SYMBOL vmlinux 0x17789945 arp_tbl +EXPORT_SYMBOL vmlinux 0x17868241 skb_kill_datagram +EXPORT_SYMBOL vmlinux 0x17969f8e inet_csk_destroy_sock +EXPORT_SYMBOL vmlinux 0x17999c19 pagevec_lookup +EXPORT_SYMBOL vmlinux 0x17a76e71 rb_first +EXPORT_SYMBOL vmlinux 0x17df17bc sysctl_tcp_ecn +EXPORT_SYMBOL vmlinux 0x181b6ff2 mempool_resize +EXPORT_SYMBOL vmlinux 0x183fa88b mempool_alloc_slab +EXPORT_SYMBOL vmlinux 0x1888833b vlan_ioctl_set +EXPORT_SYMBOL vmlinux 0x189aeda5 mca_register_driver +EXPORT_SYMBOL vmlinux 0x18a739ab find_or_create_page +EXPORT_SYMBOL vmlinux 0x18af4bab sg_miter_stop +EXPORT_SYMBOL vmlinux 0x18d55592 fsync_bdev +EXPORT_SYMBOL vmlinux 0x18e4c457 path_get +EXPORT_SYMBOL vmlinux 0x192d0a33 kernel_sendpage +EXPORT_SYMBOL vmlinux 0x1985ed3c prepare_to_wait_exclusive +EXPORT_SYMBOL vmlinux 0x19955718 tcp_proc_unregister +EXPORT_SYMBOL vmlinux 0x199a6793 invalidate_mapping_pages +EXPORT_SYMBOL vmlinux 0x199ed0cd net_disable_timestamp +EXPORT_SYMBOL vmlinux 0x19afb86b mca_device_set_claim +EXPORT_SYMBOL vmlinux 0x19d5d20a acpi_walk_namespace +EXPORT_SYMBOL vmlinux 0x19ec69ac vfs_quota_sync +EXPORT_SYMBOL vmlinux 0x1a137cbf keyring_clear +EXPORT_SYMBOL vmlinux 0x1a1744a0 generic_file_llseek_unlocked +EXPORT_SYMBOL vmlinux 0x1a1ab15d tty_mutex +EXPORT_SYMBOL vmlinux 0x1a3cd1e5 __brelse +EXPORT_SYMBOL vmlinux 0x1a45cb6c acpi_disabled +EXPORT_SYMBOL vmlinux 0x1a6e12a6 may_umount_tree +EXPORT_SYMBOL vmlinux 0x1a75caa3 _read_lock +EXPORT_SYMBOL vmlinux 0x1a854228 get_io_context +EXPORT_SYMBOL vmlinux 0x1a8a845e idle_nomwait +EXPORT_SYMBOL vmlinux 0x1ace138d bitmap_allocate_region +EXPORT_SYMBOL vmlinux 0x1ae8d7dc param_set_invbool +EXPORT_SYMBOL vmlinux 0x1b015d25 bitmap_parselist +EXPORT_SYMBOL vmlinux 0x1b02d258 mark_buffer_dirty_inode +EXPORT_SYMBOL vmlinux 0x1b0e2597 bio_add_page +EXPORT_SYMBOL vmlinux 0x1b3c678a gen_new_estimator +EXPORT_SYMBOL vmlinux 0x1b6314fd in_aton +EXPORT_SYMBOL vmlinux 0x1b732877 __alloc_pages_internal +EXPORT_SYMBOL vmlinux 0x1b89419f add_wait_queue_exclusive +EXPORT_SYMBOL vmlinux 0x1b9981cc set_irq_wake +EXPORT_SYMBOL vmlinux 0x1bcf83d3 pci_do_scan_bus +EXPORT_SYMBOL vmlinux 0x1c2657cd udplite_prot +EXPORT_SYMBOL vmlinux 0x1c3b899e bio_integrity_get_tag +EXPORT_SYMBOL vmlinux 0x1c4a3830 tcf_action_exec +EXPORT_SYMBOL vmlinux 0x1c4e7b82 tcf_em_tree_dump +EXPORT_SYMBOL vmlinux 0x1c7f37fd devm_free_irq +EXPORT_SYMBOL vmlinux 0x1c939a4e send_sig_info +EXPORT_SYMBOL vmlinux 0x1cad54b4 get_sb_pseudo +EXPORT_SYMBOL vmlinux 0x1cb2ebaa bio_integrity_free +EXPORT_SYMBOL vmlinux 0x1cbe85cd textsearch_register +EXPORT_SYMBOL vmlinux 0x1cc6719a register_reboot_notifier +EXPORT_SYMBOL vmlinux 0x1cd47340 sysctl_ms_jiffies +EXPORT_SYMBOL vmlinux 0x1cebc281 sk_reset_timer +EXPORT_SYMBOL vmlinux 0x1cecc7ab sk_receive_skb +EXPORT_SYMBOL vmlinux 0x1cefe352 wait_for_completion +EXPORT_SYMBOL vmlinux 0x1cf6c6a2 dma_pool_free +EXPORT_SYMBOL vmlinux 0x1d30b70c rwsem_wake +EXPORT_SYMBOL vmlinux 0x1d54d471 registered_fb +EXPORT_SYMBOL vmlinux 0x1d830520 cpu_possible_map +EXPORT_SYMBOL vmlinux 0x1da7f17f mnt_unpin +EXPORT_SYMBOL vmlinux 0x1dc36131 fb_destroy_modedb +EXPORT_SYMBOL vmlinux 0x1dd571e6 fb_copy_cmap +EXPORT_SYMBOL vmlinux 0x1e2cbb22 block_page_mkwrite +EXPORT_SYMBOL vmlinux 0x1e4ae87a remap_pfn_range +EXPORT_SYMBOL vmlinux 0x1e5c451e pci_enable_bridges +EXPORT_SYMBOL vmlinux 0x1e6cce15 bdput +EXPORT_SYMBOL vmlinux 0x1e6d26a8 strstr +EXPORT_SYMBOL vmlinux 0x1eb922a3 IO_APIC_get_PCI_irq_vector +EXPORT_SYMBOL vmlinux 0x1efe283f __cap_full_set +EXPORT_SYMBOL vmlinux 0x1f1df73a pfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0x1f202fed simple_transaction_release +EXPORT_SYMBOL vmlinux 0x1f27d6d7 _write_unlock +EXPORT_SYMBOL vmlinux 0x1f7fdd01 sock_no_ioctl +EXPORT_SYMBOL vmlinux 0x1f8f062a dev_alloc_skb +EXPORT_SYMBOL vmlinux 0x1f9cfe83 iomem_resource +EXPORT_SYMBOL vmlinux 0x1fa94776 bio_copy_user +EXPORT_SYMBOL vmlinux 0x1fcb2802 fb_validate_mode +EXPORT_SYMBOL vmlinux 0x1fcea05f skb_append_datato_frags +EXPORT_SYMBOL vmlinux 0x1fe5ede6 per_cpu__irq_stat +EXPORT_SYMBOL vmlinux 0x20000329 simple_strtoul +EXPORT_SYMBOL vmlinux 0x2005e68a acpi_remove_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x206cb584 d_splice_alias +EXPORT_SYMBOL vmlinux 0x208739f6 acpi_load_table +EXPORT_SYMBOL vmlinux 0x209bd58e inet_csk_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x209c69de kthread_bind +EXPORT_SYMBOL vmlinux 0x20a1981c pnp_stop_dev +EXPORT_SYMBOL vmlinux 0x20b2db3d generic_setlease +EXPORT_SYMBOL vmlinux 0x20c8fc33 pci_osc_control_set +EXPORT_SYMBOL vmlinux 0x20c98fe5 inet_frag_find +EXPORT_SYMBOL vmlinux 0x20db4c71 ethtool_op_set_tx_hw_csum +EXPORT_SYMBOL vmlinux 0x20e7a0b2 unregister_qdisc +EXPORT_SYMBOL vmlinux 0x20f038cb xfrm_unregister_type +EXPORT_SYMBOL vmlinux 0x210b2b02 read_cache_page_async +EXPORT_SYMBOL vmlinux 0x21238837 sock_common_setsockopt +EXPORT_SYMBOL vmlinux 0x21325ab8 find_inode_number +EXPORT_SYMBOL vmlinux 0x215729d0 ip_defrag +EXPORT_SYMBOL vmlinux 0x215ebd78 bitrev16 +EXPORT_SYMBOL vmlinux 0x2163288f netif_carrier_on +EXPORT_SYMBOL vmlinux 0x21b99c1a unlock_super +EXPORT_SYMBOL vmlinux 0x21c19ae8 __serio_register_port +EXPORT_SYMBOL vmlinux 0x21e0ea22 acpi_get_id +EXPORT_SYMBOL vmlinux 0x21e7bd08 vfs_get_dqblk +EXPORT_SYMBOL vmlinux 0x222e7ce2 sysfs_streq +EXPORT_SYMBOL vmlinux 0x223282ce input_register_handle +EXPORT_SYMBOL vmlinux 0x226d6245 xfrm_state_lookup_byaddr +EXPORT_SYMBOL vmlinux 0x226e86a9 audit_log +EXPORT_SYMBOL vmlinux 0x2288378f system_state +EXPORT_SYMBOL vmlinux 0x228c1899 dma_async_client_chan_request +EXPORT_SYMBOL vmlinux 0x22a73912 __tcp_put_md5sig_pool +EXPORT_SYMBOL vmlinux 0x22b325d5 kd_mksound +EXPORT_SYMBOL vmlinux 0x22b51b07 llc_sap_close +EXPORT_SYMBOL vmlinux 0x22b6264a framebuffer_alloc +EXPORT_SYMBOL vmlinux 0x22b6533b xfrm_sad_getinfo +EXPORT_SYMBOL vmlinux 0x230c4875 pci_set_dma_max_seg_size +EXPORT_SYMBOL vmlinux 0x231f3a66 __kfifo_put +EXPORT_SYMBOL vmlinux 0x23269a13 strict_strtoul +EXPORT_SYMBOL vmlinux 0x23341c80 inet_ioctl +EXPORT_SYMBOL vmlinux 0x2348984e adjust_resource +EXPORT_SYMBOL vmlinux 0x2368be6d posix_acl_to_xattr +EXPORT_SYMBOL vmlinux 0x2377e74d dquot_free_space +EXPORT_SYMBOL vmlinux 0x238e55f3 try_to_release_page +EXPORT_SYMBOL vmlinux 0x23a7a3bd maps_protect +EXPORT_SYMBOL vmlinux 0x23ad070a set_current_groups +EXPORT_SYMBOL vmlinux 0x23b5988f del_gendisk +EXPORT_SYMBOL vmlinux 0x23c17214 inet_dgram_ops +EXPORT_SYMBOL vmlinux 0x23f2d36f memparse +EXPORT_SYMBOL vmlinux 0x23f38b58 pnp_unregister_driver +EXPORT_SYMBOL vmlinux 0x23fd3028 vmalloc_node +EXPORT_SYMBOL vmlinux 0x24115311 __netdev_alloc_skb +EXPORT_SYMBOL vmlinux 0x2415344c bio_integrity_enabled +EXPORT_SYMBOL vmlinux 0x2432b227 call_usermodehelper_setcleanup +EXPORT_SYMBOL vmlinux 0x24428be5 strncpy_from_user +EXPORT_SYMBOL vmlinux 0x2451bb21 vm_insert_pfn +EXPORT_SYMBOL vmlinux 0x2459bbcc console_set_on_cmdline +EXPORT_SYMBOL vmlinux 0x246ecf61 simple_readpage +EXPORT_SYMBOL vmlinux 0x24739c70 linkwatch_fire_event +EXPORT_SYMBOL vmlinux 0x24b84de1 per_cpu__current_task +EXPORT_SYMBOL vmlinux 0x24c1ef2b acpi_evaluate_integer +EXPORT_SYMBOL vmlinux 0x24fdac79 wake_bit_function +EXPORT_SYMBOL vmlinux 0x250113b4 memory_read_from_buffer +EXPORT_SYMBOL vmlinux 0x2566948d textsearch_prepare +EXPORT_SYMBOL vmlinux 0x256887e1 warn_slowpath +EXPORT_SYMBOL vmlinux 0x25820c64 fs_overflowuid +EXPORT_SYMBOL vmlinux 0x258355b4 fb_find_best_mode +EXPORT_SYMBOL vmlinux 0x259efa16 pcim_enable_device +EXPORT_SYMBOL vmlinux 0x25ad42b1 write_one_page +EXPORT_SYMBOL vmlinux 0x25bedf6f kunmap +EXPORT_SYMBOL vmlinux 0x25d81960 posix_acl_equiv_mode +EXPORT_SYMBOL vmlinux 0x25d8d6d0 proc_net_netfilter +EXPORT_SYMBOL vmlinux 0x25db5df8 tcp_rcv_established +EXPORT_SYMBOL vmlinux 0x2631b910 mark_buffer_async_write +EXPORT_SYMBOL vmlinux 0x2637628f blk_free_tags +EXPORT_SYMBOL vmlinux 0x265b5e6c dma_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0x266e2f72 bio_clone +EXPORT_SYMBOL vmlinux 0x268cc6a2 sys_close +EXPORT_SYMBOL vmlinux 0x26972d1a unload_nls +EXPORT_SYMBOL vmlinux 0x26b7d6a1 init_task +EXPORT_SYMBOL vmlinux 0x26cdc4bf inet_register_protosw +EXPORT_SYMBOL vmlinux 0x26db3130 register_exec_domain +EXPORT_SYMBOL vmlinux 0x26e76fb8 sysctl_udp_wmem_min +EXPORT_SYMBOL vmlinux 0x272790e1 iget_locked +EXPORT_SYMBOL vmlinux 0x272d394e mtrr_del +EXPORT_SYMBOL vmlinux 0x272e7488 cond_resched_softirq +EXPORT_SYMBOL vmlinux 0x273ec516 task_tgid_nr_ns +EXPORT_SYMBOL vmlinux 0x273f066e _write_unlock_irq +EXPORT_SYMBOL vmlinux 0x274b8f54 cdev_alloc +EXPORT_SYMBOL vmlinux 0x274d7128 pcibios_align_resource +EXPORT_SYMBOL vmlinux 0x277d99db __next_cpu +EXPORT_SYMBOL vmlinux 0x27a2cc7b tty_check_change +EXPORT_SYMBOL vmlinux 0x27a9a7eb ns_to_timespec +EXPORT_SYMBOL vmlinux 0x27bbf221 disable_irq_nosync +EXPORT_SYMBOL vmlinux 0x27c61ece qdisc_put_stab +EXPORT_SYMBOL vmlinux 0x27db73d2 lease_get_mtime +EXPORT_SYMBOL vmlinux 0x27dbeed6 tcf_unregister_action +EXPORT_SYMBOL vmlinux 0x280c35cc call_usermodehelper_stdinpipe +EXPORT_SYMBOL vmlinux 0x280ca995 block_write_end +EXPORT_SYMBOL vmlinux 0x280faa98 seq_release +EXPORT_SYMBOL vmlinux 0x281b51cc do_sync_read +EXPORT_SYMBOL vmlinux 0x285ac517 strict_strtoll +EXPORT_SYMBOL vmlinux 0x2860c966 ida_get_new_above +EXPORT_SYMBOL vmlinux 0x28a1f3ab iw_handler_set_thrspy +EXPORT_SYMBOL vmlinux 0x28a729c9 ip_route_me_harder +EXPORT_SYMBOL vmlinux 0x28ac86fd sock_kmalloc +EXPORT_SYMBOL vmlinux 0x28b715a6 isapnp_cfg_end +EXPORT_SYMBOL vmlinux 0x28dcf25c udplite_hash +EXPORT_SYMBOL vmlinux 0x28e6e36e vmalloc_to_page +EXPORT_SYMBOL vmlinux 0x2916a310 dev_get_flags +EXPORT_SYMBOL vmlinux 0x2925ccb9 d_instantiate +EXPORT_SYMBOL vmlinux 0x292c328d bdi_unregister +EXPORT_SYMBOL vmlinux 0x29319889 input_flush_device +EXPORT_SYMBOL vmlinux 0x29537c9e alloc_chrdev_region +EXPORT_SYMBOL vmlinux 0x2958537a kernel_sock_ioctl +EXPORT_SYMBOL vmlinux 0x2986c053 ethtool_op_set_ufo +EXPORT_SYMBOL vmlinux 0x2988e17e blk_init_queue +EXPORT_SYMBOL vmlinux 0x299b055c pci_bus_type +EXPORT_SYMBOL vmlinux 0x29b1c366 __sg_alloc_table +EXPORT_SYMBOL vmlinux 0x29bb0067 nf_ip_checksum +EXPORT_SYMBOL vmlinux 0x29bd4c46 __cap_init_eff_set +EXPORT_SYMBOL vmlinux 0x29c5ad77 nobh_write_end +EXPORT_SYMBOL vmlinux 0x29f4cc30 simple_set_mnt +EXPORT_SYMBOL vmlinux 0x29f92193 pci_set_power_state +EXPORT_SYMBOL vmlinux 0x2a1c5a1a misc_deregister +EXPORT_SYMBOL vmlinux 0x2a29c3d8 no_llseek +EXPORT_SYMBOL vmlinux 0x2a303d4d check_signature +EXPORT_SYMBOL vmlinux 0x2a5c7b5d tcp_v4_remember_stamp +EXPORT_SYMBOL vmlinux 0x2a6899b4 audit_log_format +EXPORT_SYMBOL vmlinux 0x2a7840cb request_firmware +EXPORT_SYMBOL vmlinux 0x2a813a45 blk_rq_map_user +EXPORT_SYMBOL vmlinux 0x2a8623be ipv6_skip_exthdr +EXPORT_SYMBOL vmlinux 0x2a8bb436 follow_up +EXPORT_SYMBOL vmlinux 0x2a9b0de7 sock_queue_rcv_skb +EXPORT_SYMBOL vmlinux 0x2aa0e4fc strncasecmp +EXPORT_SYMBOL vmlinux 0x2ad7696e bio_map_kern +EXPORT_SYMBOL vmlinux 0x2ae4d9c8 freeze_bdev +EXPORT_SYMBOL vmlinux 0x2aeb2800 mempool_create_node +EXPORT_SYMBOL vmlinux 0x2af136cc register_filesystem +EXPORT_SYMBOL vmlinux 0x2af97004 xfrm_state_check_expire +EXPORT_SYMBOL vmlinux 0x2aff910d blk_verify_command +EXPORT_SYMBOL vmlinux 0x2b12cb05 security_sk_classify_flow +EXPORT_SYMBOL vmlinux 0x2b152348 arch_debugfs_dir +EXPORT_SYMBOL vmlinux 0x2b33d7c4 km_state_expired +EXPORT_SYMBOL vmlinux 0x2b4e15d7 blk_init_queue_node +EXPORT_SYMBOL vmlinux 0x2b6aac8c tcp_sockets_allocated +EXPORT_SYMBOL vmlinux 0x2b70d546 __getblk +EXPORT_SYMBOL vmlinux 0x2b72f735 __skb_warn_lro_forwarding +EXPORT_SYMBOL vmlinux 0x2b7d732b fasync_helper +EXPORT_SYMBOL vmlinux 0x2b86a602 mca_device_transform_memory +EXPORT_SYMBOL vmlinux 0x2ba707a8 sysctl_tcp_low_latency +EXPORT_SYMBOL vmlinux 0x2bb55d6e acpi_remove_notify_handler +EXPORT_SYMBOL vmlinux 0x2bc95bd4 memset +EXPORT_SYMBOL vmlinux 0x2be09893 _atomic_dec_and_lock +EXPORT_SYMBOL vmlinux 0x2bfeb410 acpi_get_handle +EXPORT_SYMBOL vmlinux 0x2c3ce34f uart_get_divisor +EXPORT_SYMBOL vmlinux 0x2c55907f gnet_stats_copy_queue +EXPORT_SYMBOL vmlinux 0x2c5749e6 acpi_clear_gpe +EXPORT_SYMBOL vmlinux 0x2c89bc37 request_key +EXPORT_SYMBOL vmlinux 0x2c8f5989 acpi_remove_address_space_handler +EXPORT_SYMBOL vmlinux 0x2c9a445d register_sysrq_key +EXPORT_SYMBOL vmlinux 0x2cc2d52d vcc_hash +EXPORT_SYMBOL vmlinux 0x2cc8177d uart_unregister_driver +EXPORT_SYMBOL vmlinux 0x2cd8947f pci_remove_bus_device +EXPORT_SYMBOL vmlinux 0x2cd9e459 param_set_short +EXPORT_SYMBOL vmlinux 0x2cea8a2b fb_get_buffer_offset +EXPORT_SYMBOL vmlinux 0x2cf190e3 request_irq +EXPORT_SYMBOL vmlinux 0x2cfcb5fe pci_set_dma_seg_boundary +EXPORT_SYMBOL vmlinux 0x2cfd8728 unregister_netdev +EXPORT_SYMBOL vmlinux 0x2d256c3b skb_seq_read +EXPORT_SYMBOL vmlinux 0x2d92a584 sk_run_filter +EXPORT_SYMBOL vmlinux 0x2dbb7d03 blk_alloc_queue_node +EXPORT_SYMBOL vmlinux 0x2dc42a74 nf_afinfo +EXPORT_SYMBOL vmlinux 0x2dd16564 arch_register_cpu +EXPORT_SYMBOL vmlinux 0x2de08ee8 tcf_destroy_chain +EXPORT_SYMBOL vmlinux 0x2de9f66f param_get_long +EXPORT_SYMBOL vmlinux 0x2dedc4c2 acpi_format_exception +EXPORT_SYMBOL vmlinux 0x2def7f76 rtc_cmos_write +EXPORT_SYMBOL vmlinux 0x2e2ce9e0 sysctl_tcp_syncookies +EXPORT_SYMBOL vmlinux 0x2e4027a6 inet_put_port +EXPORT_SYMBOL vmlinux 0x2e4a39f8 sysctl_udp_mem +EXPORT_SYMBOL vmlinux 0x2e60bace memcpy +EXPORT_SYMBOL vmlinux 0x2e97859f rwsem_downgrade_wake +EXPORT_SYMBOL vmlinux 0x2eb1c338 idr_get_new_above +EXPORT_SYMBOL vmlinux 0x2eb9a0e8 _read_lock_irq +EXPORT_SYMBOL vmlinux 0x2edcabaf blk_plug_device +EXPORT_SYMBOL vmlinux 0x2eeed6e2 keyring_search +EXPORT_SYMBOL vmlinux 0x2ef32133 inet_accept +EXPORT_SYMBOL vmlinux 0x2f287f0d copy_to_user +EXPORT_SYMBOL vmlinux 0x2f371a8b uart_remove_one_port +EXPORT_SYMBOL vmlinux 0x2f844f67 xfrm_prepare_input +EXPORT_SYMBOL vmlinux 0x2f8d3198 xfrm_register_type +EXPORT_SYMBOL vmlinux 0x2f973ef0 dma_async_device_unregister +EXPORT_SYMBOL vmlinux 0x2f9e3d9a seq_puts +EXPORT_SYMBOL vmlinux 0x2fae06be filemap_fdatawait +EXPORT_SYMBOL vmlinux 0x2fc8831c sock_setsockopt +EXPORT_SYMBOL vmlinux 0x2feeafcc vfs_llseek +EXPORT_SYMBOL vmlinux 0x2ff7efaa tcf_hash_new_index +EXPORT_SYMBOL vmlinux 0x30089f0e scm_detach_fds +EXPORT_SYMBOL vmlinux 0x302c7996 mca_register_driver_integrated +EXPORT_SYMBOL vmlinux 0x30896043 __any_online_cpu +EXPORT_SYMBOL vmlinux 0x3091f49d get_empty_filp +EXPORT_SYMBOL vmlinux 0x30d45405 ioremap_prot +EXPORT_SYMBOL vmlinux 0x30d9be26 blk_get_backing_dev_info +EXPORT_SYMBOL vmlinux 0x30e4de72 cap_netlink_recv +EXPORT_SYMBOL vmlinux 0x30e73e32 uart_add_one_port +EXPORT_SYMBOL vmlinux 0x30e74134 tty_termios_copy_hw +EXPORT_SYMBOL vmlinux 0x30eee2c3 poll_initwait +EXPORT_SYMBOL vmlinux 0x310917fe sort +EXPORT_SYMBOL vmlinux 0x3145216f pci_dev_present +EXPORT_SYMBOL vmlinux 0x3147857d default_red +EXPORT_SYMBOL vmlinux 0x31789ef2 tcp_mtup_init +EXPORT_SYMBOL vmlinux 0x3191f109 __krealloc +EXPORT_SYMBOL vmlinux 0x319ffaae tc_classify +EXPORT_SYMBOL vmlinux 0x31a639aa __nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x31a8a8be sync_inode +EXPORT_SYMBOL vmlinux 0x31a8bfb1 kunmap_high +EXPORT_SYMBOL vmlinux 0x31b2b007 blk_queue_hardsect_size +EXPORT_SYMBOL vmlinux 0x31b9c0ba generic_writepages +EXPORT_SYMBOL vmlinux 0x31c8b07d __bforget +EXPORT_SYMBOL vmlinux 0x31d65ca3 find_task_by_vpid +EXPORT_SYMBOL vmlinux 0x31e76b57 recalibrate_cpu_khz +EXPORT_SYMBOL vmlinux 0x3204a602 dev_open +EXPORT_SYMBOL vmlinux 0x321ba81d ip_ct_attach +EXPORT_SYMBOL vmlinux 0x322c6fc2 __check_region +EXPORT_SYMBOL vmlinux 0x324121e1 pnp_unregister_card_driver +EXPORT_SYMBOL vmlinux 0x32431264 tcp_make_synack +EXPORT_SYMBOL vmlinux 0x324a6c65 simple_rmdir +EXPORT_SYMBOL vmlinux 0x32670dcf tcp_getsockopt +EXPORT_SYMBOL vmlinux 0x327ef596 __elv_add_request +EXPORT_SYMBOL vmlinux 0x32810d69 simple_transaction_get +EXPORT_SYMBOL vmlinux 0x32812e73 dev_kfree_skb_any +EXPORT_SYMBOL vmlinux 0x32d01fec acpi_attach_data +EXPORT_SYMBOL vmlinux 0x3301f296 seq_path +EXPORT_SYMBOL vmlinux 0x3308e20f init_buffer +EXPORT_SYMBOL vmlinux 0x334e2859 elv_dequeue_request +EXPORT_SYMBOL vmlinux 0x33597376 get_unmapped_area +EXPORT_SYMBOL vmlinux 0x3360a963 param_set_ulong +EXPORT_SYMBOL vmlinux 0x3367d7ae isapnp_protocol +EXPORT_SYMBOL vmlinux 0x338529de atm_proc_root +EXPORT_SYMBOL vmlinux 0x3385c8cb per_cpu__this_cpu_off +EXPORT_SYMBOL vmlinux 0x33a491b9 bio_uncopy_user +EXPORT_SYMBOL vmlinux 0x33d92f9a prepare_to_wait +EXPORT_SYMBOL vmlinux 0x33f29598 sock_i_ino +EXPORT_SYMBOL vmlinux 0x340e9e25 dev_get_by_name +EXPORT_SYMBOL vmlinux 0x341ea3d0 kill_litter_super +EXPORT_SYMBOL vmlinux 0x3421272c efi +EXPORT_SYMBOL vmlinux 0x342cb8bd tc_classify_compat +EXPORT_SYMBOL vmlinux 0x342f60fe apm_info +EXPORT_SYMBOL vmlinux 0x344928b3 __xfrm_state_delete +EXPORT_SYMBOL vmlinux 0x344e4473 tcf_exts_dump_stats +EXPORT_SYMBOL vmlinux 0x34908c14 print_hex_dump_bytes +EXPORT_SYMBOL vmlinux 0x349cba85 strchr +EXPORT_SYMBOL vmlinux 0x34a71520 neigh_sysctl_register +EXPORT_SYMBOL vmlinux 0x34fe1145 vfs_rename +EXPORT_SYMBOL vmlinux 0x3505a50c init_special_inode +EXPORT_SYMBOL vmlinux 0x3587dc46 find_get_pages_contig +EXPORT_SYMBOL vmlinux 0x358ff653 hippi_type_trans +EXPORT_SYMBOL vmlinux 0x35a453f6 clear_page_dirty_for_io +EXPORT_SYMBOL vmlinux 0x35bafef4 xfrm_policy_walk +EXPORT_SYMBOL vmlinux 0x35c2ba9e refrigerator +EXPORT_SYMBOL vmlinux 0x35c32863 generic_shutdown_super +EXPORT_SYMBOL vmlinux 0x35f0faa2 acpi_evaluate_object +EXPORT_SYMBOL vmlinux 0x35f5bb05 kill_anon_super +EXPORT_SYMBOL vmlinux 0x360b1afe probe_irq_mask +EXPORT_SYMBOL vmlinux 0x363ad247 cap_set_effective +EXPORT_SYMBOL vmlinux 0x3656bf5a lock_kernel +EXPORT_SYMBOL vmlinux 0x368a6ebb pci_disable_msix +EXPORT_SYMBOL vmlinux 0x368d9452 elv_rb_latter_request +EXPORT_SYMBOL vmlinux 0x368ee979 acpi_bus_register_driver +EXPORT_SYMBOL vmlinux 0x36944bad tty_port_init +EXPORT_SYMBOL vmlinux 0x369cfc23 pci_bus_alloc_resource +EXPORT_SYMBOL vmlinux 0x36b037f3 mark_page_accessed +EXPORT_SYMBOL vmlinux 0x36be6895 vfs_set_dqinfo +EXPORT_SYMBOL vmlinux 0x36dfff42 generic_file_open +EXPORT_SYMBOL vmlinux 0x36ee4a52 tcp_ioctl +EXPORT_SYMBOL vmlinux 0x36f19362 qdisc_watchdog_cancel +EXPORT_SYMBOL vmlinux 0x36fd2a79 xfrm_register_km +EXPORT_SYMBOL vmlinux 0x37095eb8 acpi_bus_generate_proc_event +EXPORT_SYMBOL vmlinux 0x371e5b55 sock_no_shutdown +EXPORT_SYMBOL vmlinux 0x3725ffc5 inet_frag_kill +EXPORT_SYMBOL vmlinux 0x3744cf36 vmalloc_to_pfn +EXPORT_SYMBOL vmlinux 0x374ed073 scnprintf +EXPORT_SYMBOL vmlinux 0x3771b022 ps2_drain +EXPORT_SYMBOL vmlinux 0x379ccc94 nf_getsockopt +EXPORT_SYMBOL vmlinux 0x379d65f5 gen_pool_alloc +EXPORT_SYMBOL vmlinux 0x37befc70 jiffies_to_msecs +EXPORT_SYMBOL vmlinux 0x37d4ba2e pci_find_capability +EXPORT_SYMBOL vmlinux 0x37d686a1 sock_wake_async +EXPORT_SYMBOL vmlinux 0x37e74642 get_jiffies_64 +EXPORT_SYMBOL vmlinux 0x37f24e6a inet_sock_destruct +EXPORT_SYMBOL vmlinux 0x380e0a11 wake_up_process +EXPORT_SYMBOL vmlinux 0x38203ca1 __init_rwsem +EXPORT_SYMBOL vmlinux 0x384c76f5 user_revoke +EXPORT_SYMBOL vmlinux 0x384cb969 sock_no_socketpair +EXPORT_SYMBOL vmlinux 0x387c0967 vfs_lstat +EXPORT_SYMBOL vmlinux 0x389c3158 netpoll_print_options +EXPORT_SYMBOL vmlinux 0x38b92846 llc_remove_pack +EXPORT_SYMBOL vmlinux 0x38d1401e register_atm_ioctl +EXPORT_SYMBOL vmlinux 0x392d5b55 dma_async_memcpy_buf_to_buf +EXPORT_SYMBOL vmlinux 0x39378179 neigh_table_init +EXPORT_SYMBOL vmlinux 0x3966ea96 bio_hw_segments +EXPORT_SYMBOL vmlinux 0x3967cc0e pci_enable_device_mem +EXPORT_SYMBOL vmlinux 0x3969786b sock_sendmsg +EXPORT_SYMBOL vmlinux 0x396c1049 netdev_class_create_file +EXPORT_SYMBOL vmlinux 0x3980aac1 unregister_reboot_notifier +EXPORT_SYMBOL vmlinux 0x398d801d proc_dostring +EXPORT_SYMBOL vmlinux 0x39c645a2 schedule_delayed_work_on +EXPORT_SYMBOL vmlinux 0x3a092820 sk_stream_error +EXPORT_SYMBOL vmlinux 0x3a111c48 sk_stop_timer +EXPORT_SYMBOL vmlinux 0x3a2204c6 security_netlink_recv +EXPORT_SYMBOL vmlinux 0x3a50bc2e locks_copy_lock +EXPORT_SYMBOL vmlinux 0x3a538cdd tcf_hash_search +EXPORT_SYMBOL vmlinux 0x3a981660 skb_copy_datagram_iovec +EXPORT_SYMBOL vmlinux 0x3a9b6fb9 blk_unregister_region +EXPORT_SYMBOL vmlinux 0x3aa1dbcf _spin_unlock_bh +EXPORT_SYMBOL vmlinux 0x3ac69b1c seq_escape +EXPORT_SYMBOL vmlinux 0x3afce872 skb_copy_bits +EXPORT_SYMBOL vmlinux 0x3b02dedd ps2_handle_response +EXPORT_SYMBOL vmlinux 0x3b0775af inet_dgram_connect +EXPORT_SYMBOL vmlinux 0x3b1d8967 unregister_8022_client +EXPORT_SYMBOL vmlinux 0x3b2624ca seq_putc +EXPORT_SYMBOL vmlinux 0x3b27255d sock_no_poll +EXPORT_SYMBOL vmlinux 0x3b3016d3 cpufreq_unregister_notifier +EXPORT_SYMBOL vmlinux 0x3b673473 pci_assign_resource +EXPORT_SYMBOL vmlinux 0x3b79d477 fb_show_logo +EXPORT_SYMBOL vmlinux 0x3b895413 noop_qdisc +EXPORT_SYMBOL vmlinux 0x3bcd96da vfs_link +EXPORT_SYMBOL vmlinux 0x3bd1b1f6 msecs_to_jiffies +EXPORT_SYMBOL vmlinux 0x3bd4e01b invalidate_inodes +EXPORT_SYMBOL vmlinux 0x3bd564fc names_cachep +EXPORT_SYMBOL vmlinux 0x3c055f0e __pagevec_release +EXPORT_SYMBOL vmlinux 0x3c133e7a dev_unicast_delete +EXPORT_SYMBOL vmlinux 0x3c2c5af5 sprintf +EXPORT_SYMBOL vmlinux 0x3c34af43 kill_pid +EXPORT_SYMBOL vmlinux 0x3c379249 udp_lib_get_port +EXPORT_SYMBOL vmlinux 0x3c517d4f tcp_md5_hash_key +EXPORT_SYMBOL vmlinux 0x3c65846d tcp_v4_md5_hash_skb +EXPORT_SYMBOL vmlinux 0x3c7227bf complete_all +EXPORT_SYMBOL vmlinux 0x3c8fbdb1 set_bh_page +EXPORT_SYMBOL vmlinux 0x3c9c8e73 backlight_device_unregister +EXPORT_SYMBOL vmlinux 0x3c9ecdda input_set_keycode +EXPORT_SYMBOL vmlinux 0x3cb8a495 param_get_string +EXPORT_SYMBOL vmlinux 0x3cc0a3bb xfrm_spd_getinfo +EXPORT_SYMBOL vmlinux 0x3ce4ca6f disable_irq +EXPORT_SYMBOL vmlinux 0x3cf1f863 pnp_device_detach +EXPORT_SYMBOL vmlinux 0x3cf8b579 simple_fill_super +EXPORT_SYMBOL vmlinux 0x3d0549fb pci_unmap_rom +EXPORT_SYMBOL vmlinux 0x3d1f86d6 idr_remove_all +EXPORT_SYMBOL vmlinux 0x3d87b792 nla_reserve_nohdr +EXPORT_SYMBOL vmlinux 0x3da171f9 pci_mem_start +EXPORT_SYMBOL vmlinux 0x3da5eb6d kfifo_alloc +EXPORT_SYMBOL vmlinux 0x3dba295b tcp_shutdown +EXPORT_SYMBOL vmlinux 0x3e1f073d wait_for_completion_timeout +EXPORT_SYMBOL vmlinux 0x3e219de6 try_wait_for_completion +EXPORT_SYMBOL vmlinux 0x3e2ae3a8 acpi_release_global_lock +EXPORT_SYMBOL vmlinux 0x3e2f4ed9 dmam_pool_create +EXPORT_SYMBOL vmlinux 0x3e2fef9b tty_register_ldisc +EXPORT_SYMBOL vmlinux 0x3e3c0f54 dquot_transfer +EXPORT_SYMBOL vmlinux 0x3e400d8b sock_no_getsockopt +EXPORT_SYMBOL vmlinux 0x3e45e9ff register_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x3e6f5b80 blk_queue_dma_pad +EXPORT_SYMBOL vmlinux 0x3ea81a55 nf_reinject +EXPORT_SYMBOL vmlinux 0x3eb4218d dquot_release +EXPORT_SYMBOL vmlinux 0x3ed1f517 sock_map_fd +EXPORT_SYMBOL vmlinux 0x3ed63055 zlib_inflateReset +EXPORT_SYMBOL vmlinux 0x3ee0d646 dma_async_memcpy_buf_to_pg +EXPORT_SYMBOL vmlinux 0x3f020b03 mpage_readpages +EXPORT_SYMBOL vmlinux 0x3f03214a set_user_nice +EXPORT_SYMBOL vmlinux 0x3f0546a8 ioread32_rep +EXPORT_SYMBOL vmlinux 0x3f1899f1 up +EXPORT_SYMBOL vmlinux 0x3f39b162 up_write +EXPORT_SYMBOL vmlinux 0x3f4547a7 put_unused_fd +EXPORT_SYMBOL vmlinux 0x3f609851 dev_disable_lro +EXPORT_SYMBOL vmlinux 0x3f698445 fb_set_suspend +EXPORT_SYMBOL vmlinux 0x3fbcddc3 netdev_compute_features +EXPORT_SYMBOL vmlinux 0x3fbeafa0 cpufreq_gov_performance +EXPORT_SYMBOL vmlinux 0x3ff62317 local_bh_disable +EXPORT_SYMBOL vmlinux 0x403543f9 eth_rebuild_header +EXPORT_SYMBOL vmlinux 0x40576b02 acpi_get_physical_device +EXPORT_SYMBOL vmlinux 0x40595efc genl_sock +EXPORT_SYMBOL vmlinux 0x4059792f print_hex_dump +EXPORT_SYMBOL vmlinux 0x405c1144 get_seconds +EXPORT_SYMBOL vmlinux 0x40723c70 vfs_quota_off +EXPORT_SYMBOL vmlinux 0x40733864 pci_bus_read_config_dword +EXPORT_SYMBOL vmlinux 0x40897141 xfrm_input +EXPORT_SYMBOL vmlinux 0x409873e3 tty_termios_baud_rate +EXPORT_SYMBOL vmlinux 0x40a7e3f8 udp_prot +EXPORT_SYMBOL vmlinux 0x40c89d46 acpi_get_table_by_index +EXPORT_SYMBOL vmlinux 0x40face73 blk_execute_rq +EXPORT_SYMBOL vmlinux 0x4108e69a fb_match_mode +EXPORT_SYMBOL vmlinux 0x4124cfa0 skb_pull +EXPORT_SYMBOL vmlinux 0x412bd759 elv_dispatch_sort +EXPORT_SYMBOL vmlinux 0x41482d8b strndup_user +EXPORT_SYMBOL vmlinux 0x41579e95 tty_write_room +EXPORT_SYMBOL vmlinux 0x41723c20 skb_abort_seq_read +EXPORT_SYMBOL vmlinux 0x4185cf4b radix_tree_lookup_slot +EXPORT_SYMBOL vmlinux 0x4188d439 neigh_rand_reach_time +EXPORT_SYMBOL vmlinux 0x4194b0ab kick_iocb +EXPORT_SYMBOL vmlinux 0x41a9c68d _spin_trylock_bh +EXPORT_SYMBOL vmlinux 0x41ccc474 security_req_classify_flow +EXPORT_SYMBOL vmlinux 0x41eaa612 serial8250_register_port +EXPORT_SYMBOL vmlinux 0x41fcb36f pci_scan_bus_parented +EXPORT_SYMBOL vmlinux 0x4211c3c1 zlib_inflateInit2 +EXPORT_SYMBOL vmlinux 0x42172a26 touch_atime +EXPORT_SYMBOL vmlinux 0x42224298 sscanf +EXPORT_SYMBOL vmlinux 0x422c05d0 acpi_get_data +EXPORT_SYMBOL vmlinux 0x4292364c schedule +EXPORT_SYMBOL vmlinux 0x42c1ced1 pci_get_bus_and_slot +EXPORT_SYMBOL vmlinux 0x42d51a7d neigh_event_ns +EXPORT_SYMBOL vmlinux 0x4302d0eb free_pages +EXPORT_SYMBOL vmlinux 0x43146948 __secpath_destroy +EXPORT_SYMBOL vmlinux 0x43204e09 xfrm_init_state +EXPORT_SYMBOL vmlinux 0x4332f40a netif_rx_ni +EXPORT_SYMBOL vmlinux 0x43385ad9 acpi_pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x434fa55c release_console_sem +EXPORT_SYMBOL vmlinux 0x435b566d _spin_unlock +EXPORT_SYMBOL vmlinux 0x436c2179 iowrite32 +EXPORT_SYMBOL vmlinux 0x437026c9 __fatal_signal_pending +EXPORT_SYMBOL vmlinux 0x43890209 tcp_sync_mss +EXPORT_SYMBOL vmlinux 0x43b2f24d inet_proto_csum_replace4 +EXPORT_SYMBOL vmlinux 0x43b40de7 kunmap_atomic +EXPORT_SYMBOL vmlinux 0x43d30f0d path_lookup +EXPORT_SYMBOL vmlinux 0x43df9a5a genl_register_ops +EXPORT_SYMBOL vmlinux 0x44161c19 unregister_shrinker +EXPORT_SYMBOL vmlinux 0x44314efb radix_tree_gang_lookup_tag_slot +EXPORT_SYMBOL vmlinux 0x44469d39 inet_csk_accept +EXPORT_SYMBOL vmlinux 0x444779c4 nla_find +EXPORT_SYMBOL vmlinux 0x444d5f8c ilookup +EXPORT_SYMBOL vmlinux 0x444ef9f6 file_update_time +EXPORT_SYMBOL vmlinux 0x44aaf30f tsc_khz +EXPORT_SYMBOL vmlinux 0x44ad8d07 __xfrm_state_destroy +EXPORT_SYMBOL vmlinux 0x44b911c3 rb_replace_node +EXPORT_SYMBOL vmlinux 0x44d6e4c0 fb_get_mode +EXPORT_SYMBOL vmlinux 0x44e5c668 vc_cons +EXPORT_SYMBOL vmlinux 0x4504408b dma_free_coherent +EXPORT_SYMBOL vmlinux 0x450d3785 sk_wait_data +EXPORT_SYMBOL vmlinux 0x45246dd2 block_invalidatepage +EXPORT_SYMBOL vmlinux 0x4550ba8a register_cpu_notifier +EXPORT_SYMBOL vmlinux 0x455fd57d acpi_set_register +EXPORT_SYMBOL vmlinux 0x45613411 take_over_console +EXPORT_SYMBOL vmlinux 0x459dba12 pci_bus_find_capability +EXPORT_SYMBOL vmlinux 0x45a12563 tty_driver_flush_buffer +EXPORT_SYMBOL vmlinux 0x45bb123e try_to_del_timer_sync +EXPORT_SYMBOL vmlinux 0x45d11c43 down_interruptible +EXPORT_SYMBOL vmlinux 0x45f43677 bmap +EXPORT_SYMBOL vmlinux 0x460bdf1a pci_bus_size_bridges +EXPORT_SYMBOL vmlinux 0x4613862b blk_stop_queue +EXPORT_SYMBOL vmlinux 0x46266066 inet_bind +EXPORT_SYMBOL vmlinux 0x462a2e75 match_strlcpy +EXPORT_SYMBOL vmlinux 0x46368dd2 update_region +EXPORT_SYMBOL vmlinux 0x466c14a7 __delay +EXPORT_SYMBOL vmlinux 0x4676ff60 allocate_resource +EXPORT_SYMBOL vmlinux 0x4685bcec d_path +EXPORT_SYMBOL vmlinux 0x46fae925 module_refcount +EXPORT_SYMBOL vmlinux 0x472d2a9a radix_tree_lookup +EXPORT_SYMBOL vmlinux 0x475100c2 inet_get_local_port_range +EXPORT_SYMBOL vmlinux 0x475f010b acpi_purge_cached_objects +EXPORT_SYMBOL vmlinux 0x478d10b2 ht_destroy_irq +EXPORT_SYMBOL vmlinux 0x47939e0d __tasklet_hi_schedule +EXPORT_SYMBOL vmlinux 0x479c3c86 find_next_zero_bit +EXPORT_SYMBOL vmlinux 0x47ba7c7b cancel_dirty_page +EXPORT_SYMBOL vmlinux 0x47c62d70 xfrm_policy_flush +EXPORT_SYMBOL vmlinux 0x47cb99be sock_no_getname +EXPORT_SYMBOL vmlinux 0x47f6f74f bio_integrity_clone +EXPORT_SYMBOL vmlinux 0x4818227e dev_load +EXPORT_SYMBOL vmlinux 0x481cb9ab acpi_enter_sleep_state_prep +EXPORT_SYMBOL vmlinux 0x4825d8e9 ip_mc_dec_group +EXPORT_SYMBOL vmlinux 0x4832d529 rtnetlink_put_metrics +EXPORT_SYMBOL vmlinux 0x483ca089 skb_dequeue +EXPORT_SYMBOL vmlinux 0x4843bc75 read_dev_sector +EXPORT_SYMBOL vmlinux 0x4844ed0f tcp_splice_read +EXPORT_SYMBOL vmlinux 0x48550bf5 invalidate_partition +EXPORT_SYMBOL vmlinux 0x4859b8bb rtc_year_days +EXPORT_SYMBOL vmlinux 0x486b6407 hweight64 +EXPORT_SYMBOL vmlinux 0x487a2eee drop_super +EXPORT_SYMBOL vmlinux 0x48c10629 netlink_clear_multicast_users +EXPORT_SYMBOL vmlinux 0x4923f45f netif_device_detach +EXPORT_SYMBOL vmlinux 0x493e25e1 udp_hash +EXPORT_SYMBOL vmlinux 0x49603fb8 security_sb_copy_data +EXPORT_SYMBOL vmlinux 0x49ca212c fb_blank +EXPORT_SYMBOL vmlinux 0x49d6751b mca_device_claimed +EXPORT_SYMBOL vmlinux 0x49da9a9a _read_unlock_bh +EXPORT_SYMBOL vmlinux 0x49f2fe55 bdget +EXPORT_SYMBOL vmlinux 0x4a358252 __bitmap_subset +EXPORT_SYMBOL vmlinux 0x4a3e2835 pci_restore_state +EXPORT_SYMBOL vmlinux 0x4a52ca57 elv_next_request +EXPORT_SYMBOL vmlinux 0x4a971ec7 radix_tree_delete +EXPORT_SYMBOL vmlinux 0x4acd2b75 locks_mandatory_area +EXPORT_SYMBOL vmlinux 0x4b07e779 _spin_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x4b2f14b4 jiffies_to_timespec +EXPORT_SYMBOL vmlinux 0x4b34fbf5 block_all_signals +EXPORT_SYMBOL vmlinux 0x4b77c0d1 tcf_hash_insert +EXPORT_SYMBOL vmlinux 0x4baa586f d_namespace_path +EXPORT_SYMBOL vmlinux 0x4bb018b7 llc_sap_open +EXPORT_SYMBOL vmlinux 0x4bbc3e5f pm_flags +EXPORT_SYMBOL vmlinux 0x4c1182cb bitmap_scnprintf +EXPORT_SYMBOL vmlinux 0x4c327e74 __grab_cache_page +EXPORT_SYMBOL vmlinux 0x4c7573a0 skb_checksum +EXPORT_SYMBOL vmlinux 0x4cbbd171 __bitmap_weight +EXPORT_SYMBOL vmlinux 0x4ccd8caa set_binfmt +EXPORT_SYMBOL vmlinux 0x4d15865b generic_readlink +EXPORT_SYMBOL vmlinux 0x4d1c1c8f arp_create +EXPORT_SYMBOL vmlinux 0x4d1f896b tcp_md5_hash_skb_data +EXPORT_SYMBOL vmlinux 0x4d23e025 pcix_get_max_mmrbc +EXPORT_SYMBOL vmlinux 0x4d2dc830 acpi_get_object_info +EXPORT_SYMBOL vmlinux 0x4d2f92a7 inet_csk_reset_keepalive_timer +EXPORT_SYMBOL vmlinux 0x4d3c153f sigprocmask +EXPORT_SYMBOL vmlinux 0x4d541763 lookup_bdev +EXPORT_SYMBOL vmlinux 0x4d8b7b27 netdev_rx_csum_fault +EXPORT_SYMBOL vmlinux 0x4dc510ff idr_for_each +EXPORT_SYMBOL vmlinux 0x4ddc4b9f utf8_mbtowc +EXPORT_SYMBOL vmlinux 0x4df119fa __bitmap_parse +EXPORT_SYMBOL vmlinux 0x4e100f60 _spin_unlock_irq +EXPORT_SYMBOL vmlinux 0x4e17b492 pci_scan_slot +EXPORT_SYMBOL vmlinux 0x4e1c8b51 pci_dev_put +EXPORT_SYMBOL vmlinux 0x4e2c75c1 inode_set_bytes +EXPORT_SYMBOL vmlinux 0x4e3567f7 match_int +EXPORT_SYMBOL vmlinux 0x4e6e8ea7 fg_console +EXPORT_SYMBOL vmlinux 0x4e830a3e strnicmp +EXPORT_SYMBOL vmlinux 0x4e9632b8 kmap +EXPORT_SYMBOL vmlinux 0x4ed54391 __skb_checksum_complete_head +EXPORT_SYMBOL vmlinux 0x4f5438c1 idle_halt +EXPORT_SYMBOL vmlinux 0x4f5e48bc tcp_close +EXPORT_SYMBOL vmlinux 0x4f6efb8f page_symlink_inode_operations +EXPORT_SYMBOL vmlinux 0x4fac343d blk_queue_prep_rq +EXPORT_SYMBOL vmlinux 0x4fdee897 i8042_command +EXPORT_SYMBOL vmlinux 0x4fe60f81 blk_plug_device_unlocked +EXPORT_SYMBOL vmlinux 0x50211ee3 tcp_free_md5sig_pool +EXPORT_SYMBOL vmlinux 0x505b166f proc_doulongvec_minmax +EXPORT_SYMBOL vmlinux 0x50f1943b igrab +EXPORT_SYMBOL vmlinux 0x510c1a67 __skb_checksum_complete +EXPORT_SYMBOL vmlinux 0x511878b9 uart_get_baud_rate +EXPORT_SYMBOL vmlinux 0x5118c382 secure_dccp_sequence_number +EXPORT_SYMBOL vmlinux 0x5152e605 memcmp +EXPORT_SYMBOL vmlinux 0x517afaa9 __invalidate_device +EXPORT_SYMBOL vmlinux 0x517c6561 generic_file_buffered_write +EXPORT_SYMBOL vmlinux 0x518eb764 per_cpu__cpu_number +EXPORT_SYMBOL vmlinux 0x51a64147 pagecache_write_begin +EXPORT_SYMBOL vmlinux 0x51c25926 simple_dir_operations +EXPORT_SYMBOL vmlinux 0x51d051a7 may_umount +EXPORT_SYMBOL vmlinux 0x51d12d4e acpi_pci_disabled +EXPORT_SYMBOL vmlinux 0x51d7a776 acpi_detach_data +EXPORT_SYMBOL vmlinux 0x51e0ba7b generic_listxattr +EXPORT_SYMBOL vmlinux 0x51e3df2e unregister_netdevice +EXPORT_SYMBOL vmlinux 0x51e5b029 xfrm_state_update +EXPORT_SYMBOL vmlinux 0x51ef33b8 kstrndup +EXPORT_SYMBOL vmlinux 0x52026cdf security_sb_parse_opts_str +EXPORT_SYMBOL vmlinux 0x5243c7f1 pci_release_regions +EXPORT_SYMBOL vmlinux 0x528c709d simple_read_from_buffer +EXPORT_SYMBOL vmlinux 0x52a3f71a generic_removexattr +EXPORT_SYMBOL vmlinux 0x52a58c24 ifla_policy +EXPORT_SYMBOL vmlinux 0x52b72740 do_splice_from +EXPORT_SYMBOL vmlinux 0x52d7b2fd llc_sap_list +EXPORT_SYMBOL vmlinux 0x52d95dc8 blk_sync_queue +EXPORT_SYMBOL vmlinux 0x52e24296 key_validate +EXPORT_SYMBOL vmlinux 0x52e7e637 find_task_by_pid_ns +EXPORT_SYMBOL vmlinux 0x52f36b3a pci_pme_capable +EXPORT_SYMBOL vmlinux 0x530b1e98 pm_suspend +EXPORT_SYMBOL vmlinux 0x53138796 llc_mac_hdr_init +EXPORT_SYMBOL vmlinux 0x532ccb01 default_llseek +EXPORT_SYMBOL vmlinux 0x532f2924 param_get_byte +EXPORT_SYMBOL vmlinux 0x53326531 mempool_alloc_pages +EXPORT_SYMBOL vmlinux 0x534be91e nf_unregister_hooks +EXPORT_SYMBOL vmlinux 0x53557fa1 release_sock +EXPORT_SYMBOL vmlinux 0x535bc5b2 contig_page_data +EXPORT_SYMBOL vmlinux 0x535dd0f1 sk_stream_write_space +EXPORT_SYMBOL vmlinux 0x5371b557 bd_claim +EXPORT_SYMBOL vmlinux 0x538fd4d3 inet_addr_type +EXPORT_SYMBOL vmlinux 0x53c0767c sk_chk_filter +EXPORT_SYMBOL vmlinux 0x53de6ce0 devm_ioremap +EXPORT_SYMBOL vmlinux 0x5412ceca input_unregister_handle +EXPORT_SYMBOL vmlinux 0x541e9894 posix_test_lock +EXPORT_SYMBOL vmlinux 0x54290dc9 nla_validate +EXPORT_SYMBOL vmlinux 0x54764dae vfs_unlink +EXPORT_SYMBOL vmlinux 0x54935666 acpi_os_read_port +EXPORT_SYMBOL vmlinux 0x549f7b5e alloc_file +EXPORT_SYMBOL vmlinux 0x54a97207 iget_failed +EXPORT_SYMBOL vmlinux 0x54b4beda xfrm_user_policy +EXPORT_SYMBOL vmlinux 0x54b81541 init_timer_deferrable +EXPORT_SYMBOL vmlinux 0x54e6fcdd net_enable_timestamp +EXPORT_SYMBOL vmlinux 0x55272e7c arp_xmit +EXPORT_SYMBOL vmlinux 0x553f9dd3 down_read_trylock +EXPORT_SYMBOL vmlinux 0x554494b4 xfrm_policy_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x5594be03 bitmap_remap +EXPORT_SYMBOL vmlinux 0x559ad740 netpoll_send_udp +EXPORT_SYMBOL vmlinux 0x55c34043 nf_hook_slow +EXPORT_SYMBOL vmlinux 0x5600904f fb_get_color_depth +EXPORT_SYMBOL vmlinux 0x560e5a99 tty_hung_up_p +EXPORT_SYMBOL vmlinux 0x56216f3b tcf_hash_create +EXPORT_SYMBOL vmlinux 0x5635a60a vmalloc_user +EXPORT_SYMBOL vmlinux 0x563952a3 kblockd_schedule_work +EXPORT_SYMBOL vmlinux 0x566ccfbd pcim_iomap_regions +EXPORT_SYMBOL vmlinux 0x569697f8 sock_no_bind +EXPORT_SYMBOL vmlinux 0x56b77eb9 tcp_v4_do_rcv +EXPORT_SYMBOL vmlinux 0x56df3a56 acpi_check_region +EXPORT_SYMBOL vmlinux 0x56e48f50 skb_split +EXPORT_SYMBOL vmlinux 0x56ef7993 generic_file_aio_read +EXPORT_SYMBOL vmlinux 0x56f025de pci_pme_active +EXPORT_SYMBOL vmlinux 0x56f494e0 smp_call_function +EXPORT_SYMBOL vmlinux 0x5723ffb9 security_sb_set_mnt_opts +EXPORT_SYMBOL vmlinux 0x572e85d4 blk_lookup_devt +EXPORT_SYMBOL vmlinux 0x5735c9d3 bio_integrity_tag_size +EXPORT_SYMBOL vmlinux 0x574b87d6 bio_phys_segments +EXPORT_SYMBOL vmlinux 0x574f9c63 do_munmap +EXPORT_SYMBOL vmlinux 0x577cc638 mutex_unlock +EXPORT_SYMBOL vmlinux 0x578712aa get_write_access +EXPORT_SYMBOL vmlinux 0x57a6504e vsnprintf +EXPORT_SYMBOL vmlinux 0x57e391f7 posix_acl_permission +EXPORT_SYMBOL vmlinux 0x57ee77d0 dentry_open +EXPORT_SYMBOL vmlinux 0x57fbc34a sb_min_blocksize +EXPORT_SYMBOL vmlinux 0x5801cd0c blk_complete_request +EXPORT_SYMBOL vmlinux 0x5804d6eb neigh_table_clear +EXPORT_SYMBOL vmlinux 0x581e683f atm_init_aal5 +EXPORT_SYMBOL vmlinux 0x582cea72 pci_iounmap +EXPORT_SYMBOL vmlinux 0x5838f6c9 rtc_valid_tm +EXPORT_SYMBOL vmlinux 0x58442cc2 uart_resume_port +EXPORT_SYMBOL vmlinux 0x584738f9 rdmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x5857b225 ioread16_rep +EXPORT_SYMBOL vmlinux 0x58756e31 uart_suspend_port +EXPORT_SYMBOL vmlinux 0x58e000bb __set_page_dirty_buffers +EXPORT_SYMBOL vmlinux 0x58fcf651 get_user_pages +EXPORT_SYMBOL vmlinux 0x58fef6f8 ist_info +EXPORT_SYMBOL vmlinux 0x590755b7 read_cache_page +EXPORT_SYMBOL vmlinux 0x5934392b fb_register_client +EXPORT_SYMBOL vmlinux 0x594bf15b ioport_map +EXPORT_SYMBOL vmlinux 0x59b37a67 ilookup5_nowait +EXPORT_SYMBOL vmlinux 0x59c0d394 ip_generic_getfrag +EXPORT_SYMBOL vmlinux 0x59d696b6 register_module_notifier +EXPORT_SYMBOL vmlinux 0x5a00ca7e unlock_rename +EXPORT_SYMBOL vmlinux 0x5a061170 tr_type_trans +EXPORT_SYMBOL vmlinux 0x5a4896a8 __put_user_2 +EXPORT_SYMBOL vmlinux 0x5a5d03da kmem_cache_name +EXPORT_SYMBOL vmlinux 0x5a744b86 netlink_set_nonroot +EXPORT_SYMBOL vmlinux 0x5a8e63ea bio_endio +EXPORT_SYMBOL vmlinux 0x5a9926ad get_fs_type +EXPORT_SYMBOL vmlinux 0x5ab70adb dev_driver_string +EXPORT_SYMBOL vmlinux 0x5abe03a9 sock_no_accept +EXPORT_SYMBOL vmlinux 0x5ac376a5 acpi_install_fixed_event_handler +EXPORT_SYMBOL vmlinux 0x5aca4a63 vfs_set_dqblk +EXPORT_SYMBOL vmlinux 0x5af6e926 inet_csk_delete_keepalive_timer +EXPORT_SYMBOL vmlinux 0x5af97752 dquot_alloc_inode +EXPORT_SYMBOL vmlinux 0x5b04634f pnp_find_card +EXPORT_SYMBOL vmlinux 0x5b19634d div_s64_rem +EXPORT_SYMBOL vmlinux 0x5b50b979 qdisc_create_dflt +EXPORT_SYMBOL vmlinux 0x5b51c6a7 acpi_walk_resources +EXPORT_SYMBOL vmlinux 0x5b59e41f qdisc_watchdog_schedule +EXPORT_SYMBOL vmlinux 0x5baacfa2 mark_buffer_dirty +EXPORT_SYMBOL vmlinux 0x5bb300ca pci_disable_device +EXPORT_SYMBOL vmlinux 0x5c265cba sg_init_one +EXPORT_SYMBOL vmlinux 0x5c45a223 pcie_set_readrq +EXPORT_SYMBOL vmlinux 0x5c638b9e eth_header_cache +EXPORT_SYMBOL vmlinux 0x5c68705b mca_read_pos +EXPORT_SYMBOL vmlinux 0x5c6a8cdb blk_queue_softirq_done +EXPORT_SYMBOL vmlinux 0x5c7a07b2 get_disk +EXPORT_SYMBOL vmlinux 0x5c8a30ad ethtool_op_set_tx_ipv6_csum +EXPORT_SYMBOL vmlinux 0x5c9aa822 devm_ioport_map +EXPORT_SYMBOL vmlinux 0x5cd62c14 handle_sysrq +EXPORT_SYMBOL vmlinux 0x5cd94c7e dquot_free_inode +EXPORT_SYMBOL vmlinux 0x5cea816a proc_dointvec_minmax +EXPORT_SYMBOL vmlinux 0x5cee23e5 kobject_init +EXPORT_SYMBOL vmlinux 0x5d0fa11c simple_write_end +EXPORT_SYMBOL vmlinux 0x5d17ee37 ether_setup +EXPORT_SYMBOL vmlinux 0x5d73b5f8 km_waitq +EXPORT_SYMBOL vmlinux 0x5d772fe3 blkdev_put +EXPORT_SYMBOL vmlinux 0x5d782dbd seq_read +EXPORT_SYMBOL vmlinux 0x5dbcfa4f boot_cpu_physical_apicid +EXPORT_SYMBOL vmlinux 0x5de21406 inet_sendmsg +EXPORT_SYMBOL vmlinux 0x5e058878 iput +EXPORT_SYMBOL vmlinux 0x5e4dcf7a tcp_init_xmit_timers +EXPORT_SYMBOL vmlinux 0x5e777fdc pcix_get_mmrbc +EXPORT_SYMBOL vmlinux 0x5e79ebec gen_replace_estimator +EXPORT_SYMBOL vmlinux 0x5e91e53c sk_stream_wait_close +EXPORT_SYMBOL vmlinux 0x5ea520c5 tcp_select_initial_window +EXPORT_SYMBOL vmlinux 0x5ed040b0 pm_set_vt_switch +EXPORT_SYMBOL vmlinux 0x5ed9f67a input_get_keycode +EXPORT_SYMBOL vmlinux 0x5edd0762 bin2bcd +EXPORT_SYMBOL vmlinux 0x5f018250 netdev_set_master +EXPORT_SYMBOL vmlinux 0x5f08dc1a fb_class +EXPORT_SYMBOL vmlinux 0x5f1bd579 mca_find_adapter +EXPORT_SYMBOL vmlinux 0x5f2edb14 qdisc_reset +EXPORT_SYMBOL vmlinux 0x5f5173b4 inode_get_bytes +EXPORT_SYMBOL vmlinux 0x5f729344 generic_splice_sendpage +EXPORT_SYMBOL vmlinux 0x5fc83bf4 blk_queue_max_sectors +EXPORT_SYMBOL vmlinux 0x5fdfc7c9 sock_wfree +EXPORT_SYMBOL vmlinux 0x5fe2bf01 bio_integrity_split +EXPORT_SYMBOL vmlinux 0x6005137c inet_frags_fini +EXPORT_SYMBOL vmlinux 0x600683d3 do_unblank_screen +EXPORT_SYMBOL vmlinux 0x6010cb1c vfs_quota_on +EXPORT_SYMBOL vmlinux 0x6011fdfa dmam_alloc_noncoherent +EXPORT_SYMBOL vmlinux 0x6013f289 lookup_one_len +EXPORT_SYMBOL vmlinux 0x60224879 __nla_reserve +EXPORT_SYMBOL vmlinux 0x603bb510 ethtool_op_get_flags +EXPORT_SYMBOL vmlinux 0x60400b7f pv_lock_ops +EXPORT_SYMBOL vmlinux 0x60459249 generic_write_checks +EXPORT_SYMBOL vmlinux 0x60586b26 end_queued_request +EXPORT_SYMBOL vmlinux 0x6085d6a7 kmem_cache_size +EXPORT_SYMBOL vmlinux 0x608c2831 warn_on_slowpath +EXPORT_SYMBOL vmlinux 0x609f1c7e synchronize_net +EXPORT_SYMBOL vmlinux 0x60a32ea9 pm_power_off +EXPORT_SYMBOL vmlinux 0x60fc087e netlink_kernel_create +EXPORT_SYMBOL vmlinux 0x61079ddc vfs_write +EXPORT_SYMBOL vmlinux 0x6111e1bc init_timer +EXPORT_SYMBOL vmlinux 0x611b7990 skb_insert +EXPORT_SYMBOL vmlinux 0x612390ad netpoll_set_trap +EXPORT_SYMBOL vmlinux 0x6150b3d9 ethtool_op_get_ufo +EXPORT_SYMBOL vmlinux 0x6160c6ff bio_free +EXPORT_SYMBOL vmlinux 0x6164bef4 seq_lseek +EXPORT_SYMBOL vmlinux 0x618d8299 set_notify_swap_entry_free +EXPORT_SYMBOL vmlinux 0x61909077 tcf_register_action +EXPORT_SYMBOL vmlinux 0x61a06034 pcie_port_service_register +EXPORT_SYMBOL vmlinux 0x61b3a3d4 blk_rq_map_integrity_sg +EXPORT_SYMBOL vmlinux 0x61b7b126 simple_strtoull +EXPORT_SYMBOL vmlinux 0x61c724db inode_change_ok +EXPORT_SYMBOL vmlinux 0x61f90d6b input_set_capability +EXPORT_SYMBOL vmlinux 0x62049256 acpi_disable +EXPORT_SYMBOL vmlinux 0x6205a8c7 path_permission +EXPORT_SYMBOL vmlinux 0x620a4d1f set_page_dirty_lock +EXPORT_SYMBOL vmlinux 0x6234b92f dev_mc_add +EXPORT_SYMBOL vmlinux 0x62378340 bd_release +EXPORT_SYMBOL vmlinux 0x6237f6b5 acpi_enable_event +EXPORT_SYMBOL vmlinux 0x62387e01 blk_queue_bounce +EXPORT_SYMBOL vmlinux 0x623db2b5 dma_pool_destroy +EXPORT_SYMBOL vmlinux 0x6241a2ab __copy_from_user_ll_nocache +EXPORT_SYMBOL vmlinux 0x6241fd2c acpi_install_address_space_handler +EXPORT_SYMBOL vmlinux 0x62737e1d sock_unregister +EXPORT_SYMBOL vmlinux 0x627579cb netlink_change_ngroups +EXPORT_SYMBOL vmlinux 0x62827bec security_secctx_to_secid +EXPORT_SYMBOL vmlinux 0x62aeecc2 pagecache_write_end +EXPORT_SYMBOL vmlinux 0x6316f096 blk_queue_merge_bvec +EXPORT_SYMBOL vmlinux 0x631fd789 shrink_dcache_parent +EXPORT_SYMBOL vmlinux 0x636a5691 acpi_register_ioapic +EXPORT_SYMBOL vmlinux 0x638676ba dma_release_declared_memory +EXPORT_SYMBOL vmlinux 0x63e58632 in_dev_finish_destroy +EXPORT_SYMBOL vmlinux 0x63ecad53 register_netdevice_notifier +EXPORT_SYMBOL vmlinux 0x63fc0325 page_put_link +EXPORT_SYMBOL vmlinux 0x6402aaff release_resource +EXPORT_SYMBOL vmlinux 0x6403e338 tcp_memory_pressure +EXPORT_SYMBOL vmlinux 0x6405ec75 call_usermodehelper_pipe +EXPORT_SYMBOL vmlinux 0x640b5ce9 kernel_sendmsg +EXPORT_SYMBOL vmlinux 0x6411cc45 put_disk +EXPORT_SYMBOL vmlinux 0x641275c3 load_nls_default +EXPORT_SYMBOL vmlinux 0x642e54ac __wake_up +EXPORT_SYMBOL vmlinux 0x6451294b posix_acl_valid +EXPORT_SYMBOL vmlinux 0x6466a1e6 mempool_alloc +EXPORT_SYMBOL vmlinux 0x6478134c ec_burst_enable +EXPORT_SYMBOL vmlinux 0x6496881c serio_unregister_driver +EXPORT_SYMBOL vmlinux 0x64999478 congestion_wait +EXPORT_SYMBOL vmlinux 0x64cd5d16 init_waitqueue_head +EXPORT_SYMBOL vmlinux 0x64fe7528 inode_setattr +EXPORT_SYMBOL vmlinux 0x650128e7 br_fdb_get_hook +EXPORT_SYMBOL vmlinux 0x6507d812 blk_register_region +EXPORT_SYMBOL vmlinux 0x650fb346 add_wait_queue +EXPORT_SYMBOL vmlinux 0x65408378 zlib_inflate_blob +EXPORT_SYMBOL vmlinux 0x65414e67 dev_valid_name +EXPORT_SYMBOL vmlinux 0x65623747 block_commit_write +EXPORT_SYMBOL vmlinux 0x6584d7d2 eisa_driver_unregister +EXPORT_SYMBOL vmlinux 0x658a15f3 sock_no_listen +EXPORT_SYMBOL vmlinux 0x6596f162 boot_cpu_data +EXPORT_SYMBOL vmlinux 0x659e32ac inode_double_unlock +EXPORT_SYMBOL vmlinux 0x65ac078e inet_add_protocol +EXPORT_SYMBOL vmlinux 0x65e6a097 xfrm_policy_alloc +EXPORT_SYMBOL vmlinux 0x666d14d7 bdev_read_only +EXPORT_SYMBOL vmlinux 0x6674ca6c pci_request_selected_regions +EXPORT_SYMBOL vmlinux 0x668da8d5 zlib_inflateIncomp +EXPORT_SYMBOL vmlinux 0x66d8b2cf clip_tbl_hook +EXPORT_SYMBOL vmlinux 0x671c39a6 vfs_read +EXPORT_SYMBOL vmlinux 0x6729d3df __get_user_4 +EXPORT_SYMBOL vmlinux 0x672fbcab acpi_lock_battery_dir +EXPORT_SYMBOL vmlinux 0x673cfd8a inet_unregister_protosw +EXPORT_SYMBOL vmlinux 0x675b71c2 elv_rb_del +EXPORT_SYMBOL vmlinux 0x678a606f xfrm4_prepare_output +EXPORT_SYMBOL vmlinux 0x67b27ec1 tty_std_termios +EXPORT_SYMBOL vmlinux 0x67e71b77 __mutex_init +EXPORT_SYMBOL vmlinux 0x67f7318a kset_register +EXPORT_SYMBOL vmlinux 0x67fc7fbd devm_ioport_unmap +EXPORT_SYMBOL vmlinux 0x67fe1e51 block_truncate_page +EXPORT_SYMBOL vmlinux 0x68098e31 simple_sync_file +EXPORT_SYMBOL vmlinux 0x682b2570 free_task +EXPORT_SYMBOL vmlinux 0x682d3f2e __lookup_hash +EXPORT_SYMBOL vmlinux 0x6855db0f ps2_init +EXPORT_SYMBOL vmlinux 0x686f6d1e register_sysctl_paths +EXPORT_SYMBOL vmlinux 0x687a988a pci_enable_msi +EXPORT_SYMBOL vmlinux 0x68a4250c dput +EXPORT_SYMBOL vmlinux 0x68ca324d task_session_nr_ns +EXPORT_SYMBOL vmlinux 0x692b73d3 nf_register_hooks +EXPORT_SYMBOL vmlinux 0x695f2162 __dev_get_by_name +EXPORT_SYMBOL vmlinux 0x6971447a rtc_month_days +EXPORT_SYMBOL vmlinux 0x69719a71 bio_pair_release +EXPORT_SYMBOL vmlinux 0x69806cab mca_bus_type +EXPORT_SYMBOL vmlinux 0x69927dff try_acquire_console_sem +EXPORT_SYMBOL vmlinux 0x69a0ca7d iowrite16be +EXPORT_SYMBOL vmlinux 0x69c40ab1 do_splice_to +EXPORT_SYMBOL vmlinux 0x69e5082f uart_register_driver +EXPORT_SYMBOL vmlinux 0x6a037cf1 mempool_kfree +EXPORT_SYMBOL vmlinux 0x6a27bfce csum_partial_copy_generic +EXPORT_SYMBOL vmlinux 0x6a3b69e0 d_lookup +EXPORT_SYMBOL vmlinux 0x6a3d470e thermal_zone_device_register +EXPORT_SYMBOL vmlinux 0x6a47571d __set_personality +EXPORT_SYMBOL vmlinux 0x6a6cc4bb key_payload_reserve +EXPORT_SYMBOL vmlinux 0x6ac30c23 close_bdev_excl +EXPORT_SYMBOL vmlinux 0x6acb973d iowrite32be +EXPORT_SYMBOL vmlinux 0x6add5c9a dmi_find_device +EXPORT_SYMBOL vmlinux 0x6afd06b5 ip_route_input +EXPORT_SYMBOL vmlinux 0x6b1b54b8 generic_file_splice_write_nolock +EXPORT_SYMBOL vmlinux 0x6b1b67d3 __bdevname +EXPORT_SYMBOL vmlinux 0x6b2dc060 dump_stack +EXPORT_SYMBOL vmlinux 0x6b379973 elv_rb_find +EXPORT_SYMBOL vmlinux 0x6b71e4f9 check_disk_change +EXPORT_SYMBOL vmlinux 0x6b937ffb mca_mark_as_used +EXPORT_SYMBOL vmlinux 0x6b9a06f4 cdev_del +EXPORT_SYMBOL vmlinux 0x6b9b88f3 sleep_on +EXPORT_SYMBOL vmlinux 0x6ba92877 nobh_writepage +EXPORT_SYMBOL vmlinux 0x6bafbced mod_timer +EXPORT_SYMBOL vmlinux 0x6bb55447 bio_integrity_prep +EXPORT_SYMBOL vmlinux 0x6bdcfd99 qdisc_class_hash_remove +EXPORT_SYMBOL vmlinux 0x6be7818f dev_kfree_skb_irq +EXPORT_SYMBOL vmlinux 0x6bed0562 dst_discard +EXPORT_SYMBOL vmlinux 0x6c1ce5ce strcspn +EXPORT_SYMBOL vmlinux 0x6c2e3320 strncmp +EXPORT_SYMBOL vmlinux 0x6c389761 acpi_bus_get_private_data +EXPORT_SYMBOL vmlinux 0x6c4b0414 tcp_rcv_state_process +EXPORT_SYMBOL vmlinux 0x6c61ce70 num_registered_fb +EXPORT_SYMBOL vmlinux 0x6c702af7 sysctl_udp_rmem_min +EXPORT_SYMBOL vmlinux 0x6c76f7e7 pci_back_from_sleep +EXPORT_SYMBOL vmlinux 0x6cbecc2a pci_select_bars +EXPORT_SYMBOL vmlinux 0x6cd9f57e mca_device_read_stored_pos +EXPORT_SYMBOL vmlinux 0x6cdc5c6b nla_strlcpy +EXPORT_SYMBOL vmlinux 0x6d0da34c param_get_short +EXPORT_SYMBOL vmlinux 0x6d10832b key_put +EXPORT_SYMBOL vmlinux 0x6d1ced27 vcc_sklist_lock +EXPORT_SYMBOL vmlinux 0x6d27ef64 __bitmap_empty +EXPORT_SYMBOL vmlinux 0x6d288375 radix_tree_next_hole +EXPORT_SYMBOL vmlinux 0x6d294e43 clock_t_to_jiffies +EXPORT_SYMBOL vmlinux 0x6d340f64 tty_termios_input_baud_rate +EXPORT_SYMBOL vmlinux 0x6d464175 __sg_free_table +EXPORT_SYMBOL vmlinux 0x6d56994a cmpxchg_486_u64 +EXPORT_SYMBOL vmlinux 0x6dc0c24b complete_and_exit +EXPORT_SYMBOL vmlinux 0x6de23eb3 br_handle_frame_hook +EXPORT_SYMBOL vmlinux 0x6dee7be5 dump_fpu +EXPORT_SYMBOL vmlinux 0x6def2db2 half_md4_transform +EXPORT_SYMBOL vmlinux 0x6e018f51 kernel_read +EXPORT_SYMBOL vmlinux 0x6e07a54e acpi_get_gpe_status +EXPORT_SYMBOL vmlinux 0x6e1a4bbb udp_hash_lock +EXPORT_SYMBOL vmlinux 0x6e24f3dd ethtool_op_set_tx_csum +EXPORT_SYMBOL vmlinux 0x6e3b0268 simple_dir_inode_operations +EXPORT_SYMBOL vmlinux 0x6e440b58 memcpy_fromiovecend +EXPORT_SYMBOL vmlinux 0x6e65eb00 vfs_quota_on_mount +EXPORT_SYMBOL vmlinux 0x6e6a02f5 d_prune_aliases +EXPORT_SYMBOL vmlinux 0x6e720ff2 rtnl_unlock +EXPORT_SYMBOL vmlinux 0x6e7cf7db poll_freewait +EXPORT_SYMBOL vmlinux 0x6e8d08fe bd_set_size +EXPORT_SYMBOL vmlinux 0x6e9dd606 __symbol_put +EXPORT_SYMBOL vmlinux 0x6ead242b cond_resched_lock +EXPORT_SYMBOL vmlinux 0x6eced2c5 bio_init +EXPORT_SYMBOL vmlinux 0x6edcd846 sk_filter +EXPORT_SYMBOL vmlinux 0x6ee2806e posix_unblock_lock +EXPORT_SYMBOL vmlinux 0x6f0622b7 simple_release_fs +EXPORT_SYMBOL vmlinux 0x6f34eaa4 ethtool_op_get_link +EXPORT_SYMBOL vmlinux 0x6f558646 icmp_send +EXPORT_SYMBOL vmlinux 0x6f75b115 lock_sock_nested +EXPORT_SYMBOL vmlinux 0x6f7b7602 xfrm_unregister_km +EXPORT_SYMBOL vmlinux 0x6fb370b2 acpi_check_resource_conflict +EXPORT_SYMBOL vmlinux 0x6fcb87a1 touch_softlockup_watchdog +EXPORT_SYMBOL vmlinux 0x6ff1ef67 free_buffer_head +EXPORT_SYMBOL vmlinux 0x700396f9 end_page_writeback +EXPORT_SYMBOL vmlinux 0x7008a9b7 timespec_to_jiffies +EXPORT_SYMBOL vmlinux 0x701d0ebd snprintf +EXPORT_SYMBOL vmlinux 0x70359f72 blk_queue_ordered +EXPORT_SYMBOL vmlinux 0x70461a22 key_revoke +EXPORT_SYMBOL vmlinux 0x7054a3e4 request_dma +EXPORT_SYMBOL vmlinux 0x7059a489 mapping_tagged +EXPORT_SYMBOL vmlinux 0x70912b12 netif_device_attach +EXPORT_SYMBOL vmlinux 0x70b47e6a sock_create_lite +EXPORT_SYMBOL vmlinux 0x70d1f8f3 strncat +EXPORT_SYMBOL vmlinux 0x70d8ab82 acpi_acquire_global_lock +EXPORT_SYMBOL vmlinux 0x71074034 write_cache_pages +EXPORT_SYMBOL vmlinux 0x7129e5f8 hex_asc +EXPORT_SYMBOL vmlinux 0x712aa29b _spin_lock_irqsave +EXPORT_SYMBOL vmlinux 0x71356fba remove_wait_queue +EXPORT_SYMBOL vmlinux 0x716f628d tcp_alloc_md5sig_pool +EXPORT_SYMBOL vmlinux 0x7171121c overflowgid +EXPORT_SYMBOL vmlinux 0x717a3a19 blk_run_queue +EXPORT_SYMBOL vmlinux 0x71a50dbc register_blkdev +EXPORT_SYMBOL vmlinux 0x71ac053d generic_permission +EXPORT_SYMBOL vmlinux 0x71c54c10 register_8022_client +EXPORT_SYMBOL vmlinux 0x71e8064a __sk_mem_reclaim +EXPORT_SYMBOL vmlinux 0x71efbb61 __generic_unplug_device +EXPORT_SYMBOL vmlinux 0x72270e35 do_gettimeofday +EXPORT_SYMBOL vmlinux 0x724592c5 blk_queue_free_tags +EXPORT_SYMBOL vmlinux 0x7249cea5 tcf_em_unregister +EXPORT_SYMBOL vmlinux 0x725998fa simple_lookup +EXPORT_SYMBOL vmlinux 0x72b243d4 free_dma +EXPORT_SYMBOL vmlinux 0x72bf2140 mtrr_add +EXPORT_SYMBOL vmlinux 0x73166b2d sk_free +EXPORT_SYMBOL vmlinux 0x732bb9ed dma_async_device_register +EXPORT_SYMBOL vmlinux 0x73450eb1 invalidate_bdev +EXPORT_SYMBOL vmlinux 0x734b4f38 eth_type_trans +EXPORT_SYMBOL vmlinux 0x735a0bd5 native_io_delay +EXPORT_SYMBOL vmlinux 0x7373bf16 neigh_seq_stop +EXPORT_SYMBOL vmlinux 0x738803e6 strnlen +EXPORT_SYMBOL vmlinux 0x7389c9a8 acpi_bus_get_power +EXPORT_SYMBOL vmlinux 0x73a16e14 fd_install +EXPORT_SYMBOL vmlinux 0x73a8c7fe pci_remove_bus +EXPORT_SYMBOL vmlinux 0x73bd9ac6 __insert_inode_hash +EXPORT_SYMBOL vmlinux 0x73cd3430 __inet6_lookup_established +EXPORT_SYMBOL vmlinux 0x73d71db6 save_mount_options +EXPORT_SYMBOL vmlinux 0x73e20c1c strlcpy +EXPORT_SYMBOL vmlinux 0x73f9d9c7 set_pages_x +EXPORT_SYMBOL vmlinux 0x73ffd178 cdev_init +EXPORT_SYMBOL vmlinux 0x740a1b95 reserve_evntsel_nmi +EXPORT_SYMBOL vmlinux 0x7413793a EISA_bus +EXPORT_SYMBOL vmlinux 0x74353e21 alloc_trdev +EXPORT_SYMBOL vmlinux 0x74509be2 blk_remove_plug +EXPORT_SYMBOL vmlinux 0x7485e15e unregister_chrdev_region +EXPORT_SYMBOL vmlinux 0x748caf40 down +EXPORT_SYMBOL vmlinux 0x74952da0 dma_async_memcpy_pg_to_pg +EXPORT_SYMBOL vmlinux 0x74a0f33b mca_device_set_name +EXPORT_SYMBOL vmlinux 0x74b6a745 alloc_buffer_head +EXPORT_SYMBOL vmlinux 0x74c3e921 fddi_type_trans +EXPORT_SYMBOL vmlinux 0x74c8ae72 inode_needs_sync +EXPORT_SYMBOL vmlinux 0x74cc1cbe unregister_cpu_notifier +EXPORT_SYMBOL vmlinux 0x74cc238d current_kernel_time +EXPORT_SYMBOL vmlinux 0x751031a5 default_unplug_io_fn +EXPORT_SYMBOL vmlinux 0x75271716 save_processor_state +EXPORT_SYMBOL vmlinux 0x75566739 complete_request_key +EXPORT_SYMBOL vmlinux 0x758a15ba register_key_type +EXPORT_SYMBOL vmlinux 0x75986126 mca_unregister_driver +EXPORT_SYMBOL vmlinux 0x75aef528 nf_ct_attach +EXPORT_SYMBOL vmlinux 0x75e6ac43 __xfrm_route_forward +EXPORT_SYMBOL vmlinux 0x75ee3d2e blk_rq_map_kern +EXPORT_SYMBOL vmlinux 0x760a0f4f yield +EXPORT_SYMBOL vmlinux 0x760b437a unregister_inetaddr_notifier +EXPORT_SYMBOL vmlinux 0x760fb73f neigh_ifdown +EXPORT_SYMBOL vmlinux 0x76512976 acpi_notifier_call_chain +EXPORT_SYMBOL vmlinux 0x767a33af submit_bh +EXPORT_SYMBOL vmlinux 0x767ddb02 set_memory_wc +EXPORT_SYMBOL vmlinux 0x76845676 thermal_cooling_device_register +EXPORT_SYMBOL vmlinux 0x76a7b880 task_pgrp_nr_ns +EXPORT_SYMBOL vmlinux 0x76b0f8f8 bad_dma_address +EXPORT_SYMBOL vmlinux 0x76bf656d __bitmap_shift_left +EXPORT_SYMBOL vmlinux 0x76d3cd60 laptop_mode +EXPORT_SYMBOL vmlinux 0x76f3f8a5 num_k8_northbridges +EXPORT_SYMBOL vmlinux 0x7709e67d set_device_ro +EXPORT_SYMBOL vmlinux 0x770a0036 isapnp_cfg_begin +EXPORT_SYMBOL vmlinux 0x770e72ae blk_queue_max_hw_segments +EXPORT_SYMBOL vmlinux 0x774f06e7 blk_dump_rq_flags +EXPORT_SYMBOL vmlinux 0x77552824 bio_add_pc_page +EXPORT_SYMBOL vmlinux 0x77a108df _write_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x77c45f1b bio_alloc_bioset +EXPORT_SYMBOL vmlinux 0x77e2fa3d unmap_mapping_range +EXPORT_SYMBOL vmlinux 0x77ecac9f zlib_inflateEnd +EXPORT_SYMBOL vmlinux 0x7809cf8b aio_complete +EXPORT_SYMBOL vmlinux 0x780a01a5 page_readlink +EXPORT_SYMBOL vmlinux 0x780dd7d1 uart_update_timeout +EXPORT_SYMBOL vmlinux 0x783a81fe have_submounts +EXPORT_SYMBOL vmlinux 0x786d158f pcim_iomap_table +EXPORT_SYMBOL vmlinux 0x787d12fa sock_no_recvmsg +EXPORT_SYMBOL vmlinux 0x78a484c9 _read_unlock_irqrestore +EXPORT_SYMBOL vmlinux 0x78a5d710 generic_file_splice_write +EXPORT_SYMBOL vmlinux 0x78cb2783 down_write_trylock +EXPORT_SYMBOL vmlinux 0x78df6bd7 no_pci_devices +EXPORT_SYMBOL vmlinux 0x78f793d9 xfrm_policy_insert +EXPORT_SYMBOL vmlinux 0x794439a0 mca_device_transform_ioport +EXPORT_SYMBOL vmlinux 0x794487ee disable_hlt +EXPORT_SYMBOL vmlinux 0x794c1398 dmi_check_system +EXPORT_SYMBOL vmlinux 0x79528b23 xfrm4_rcv +EXPORT_SYMBOL vmlinux 0x795dbe31 skb_copy_and_csum_datagram_iovec +EXPORT_SYMBOL vmlinux 0x79656409 cpu_online_map +EXPORT_SYMBOL vmlinux 0x798b1747 ethtool_op_set_tso +EXPORT_SYMBOL vmlinux 0x79aa04a2 get_random_bytes +EXPORT_SYMBOL vmlinux 0x79aa05a8 match_token +EXPORT_SYMBOL vmlinux 0x79d78989 set_irq_chip +EXPORT_SYMBOL vmlinux 0x79e67aef lock_may_read +EXPORT_SYMBOL vmlinux 0x7a032ce2 bio_split +EXPORT_SYMBOL vmlinux 0x7a1a8252 sg_miter_start +EXPORT_SYMBOL vmlinux 0x7a2a837d strict_strtol +EXPORT_SYMBOL vmlinux 0x7a628433 flock_lock_file_wait +EXPORT_SYMBOL vmlinux 0x7a7b59e9 generic_file_direct_write +EXPORT_SYMBOL vmlinux 0x7a848702 _read_lock_irqsave +EXPORT_SYMBOL vmlinux 0x7a87611d f_setown +EXPORT_SYMBOL vmlinux 0x7aadee01 arp_find +EXPORT_SYMBOL vmlinux 0x7aaf9eee vfs_mknod +EXPORT_SYMBOL vmlinux 0x7aec9089 clear_user +EXPORT_SYMBOL vmlinux 0x7b0c84c4 acpi_remove_table_handler +EXPORT_SYMBOL vmlinux 0x7b134ddf acpi_get_name +EXPORT_SYMBOL vmlinux 0x7b52a859 wrmsr_safe_on_cpu +EXPORT_SYMBOL vmlinux 0x7b69467e posix_acl_from_xattr +EXPORT_SYMBOL vmlinux 0x7b6fec69 dec_zone_page_state +EXPORT_SYMBOL vmlinux 0x7b943a43 lock_rename +EXPORT_SYMBOL vmlinux 0x7ba93191 pci_find_bus +EXPORT_SYMBOL vmlinux 0x7bffa2fd dev_get_by_flags +EXPORT_SYMBOL vmlinux 0x7c1232bc fb_pan_display +EXPORT_SYMBOL vmlinux 0x7c3146ae __devm_request_region +EXPORT_SYMBOL vmlinux 0x7c46233a cpufreq_quick_get +EXPORT_SYMBOL vmlinux 0x7c60d66e getname +EXPORT_SYMBOL vmlinux 0x7c904ded unregister_module_notifier +EXPORT_SYMBOL vmlinux 0x7c93174c xfrm_dst_ifdown +EXPORT_SYMBOL vmlinux 0x7c9b3904 inc_zone_page_state +EXPORT_SYMBOL vmlinux 0x7ca2b7a8 vfs_statfs +EXPORT_SYMBOL vmlinux 0x7cb1ae69 cpu_down +EXPORT_SYMBOL vmlinux 0x7cc2f8d2 nf_register_sockopt +EXPORT_SYMBOL vmlinux 0x7cd73971 __inet6_hash +EXPORT_SYMBOL vmlinux 0x7cfe97d8 pnp_start_dev +EXPORT_SYMBOL vmlinux 0x7d047e7e acpi_ut_exception +EXPORT_SYMBOL vmlinux 0x7d07dcfe do_mmap_pgoff +EXPORT_SYMBOL vmlinux 0x7d11c268 jiffies +EXPORT_SYMBOL vmlinux 0x7d73f2e3 blk_put_request +EXPORT_SYMBOL vmlinux 0x7d79a978 request_key_with_auxdata +EXPORT_SYMBOL vmlinux 0x7d850612 utf8_mbstowcs +EXPORT_SYMBOL vmlinux 0x7d948097 load_nls +EXPORT_SYMBOL vmlinux 0x7d970406 tcp_connect +EXPORT_SYMBOL vmlinux 0x7dceceac capable +EXPORT_SYMBOL vmlinux 0x7e1b3e78 unregister_quota_format +EXPORT_SYMBOL vmlinux 0x7e555758 serio_open +EXPORT_SYMBOL vmlinux 0x7e65feeb netdev_class_remove_file +EXPORT_SYMBOL vmlinux 0x7e83c788 input_open_device +EXPORT_SYMBOL vmlinux 0x7e9aecc7 bfifo_qdisc_ops +EXPORT_SYMBOL vmlinux 0x7e9ddebb end_dequeued_request +EXPORT_SYMBOL vmlinux 0x7e9ebb05 kernel_thread +EXPORT_SYMBOL vmlinux 0x7edd9e65 pci_fixup_device +EXPORT_SYMBOL vmlinux 0x7ee91c1d _spin_trylock +EXPORT_SYMBOL vmlinux 0x7ef70d58 tcp_simple_retransmit +EXPORT_SYMBOL vmlinux 0x7efbe560 per_cpu__cpu_core_map +EXPORT_SYMBOL vmlinux 0x7f24de73 jiffies_to_usecs +EXPORT_SYMBOL vmlinux 0x7f2834b5 tcp_recvmsg +EXPORT_SYMBOL vmlinux 0x7f31979b set_pages_uc +EXPORT_SYMBOL vmlinux 0x7f4cfeb1 pnp_request_card_device +EXPORT_SYMBOL vmlinux 0x7f5728af key_type_keyring +EXPORT_SYMBOL vmlinux 0x7f807224 tty_devnum +EXPORT_SYMBOL vmlinux 0x7f8723bd pcie_mch_quirk +EXPORT_SYMBOL vmlinux 0x7f9e35f3 bio_integrity_alloc +EXPORT_SYMBOL vmlinux 0x7fb19061 dev_get_by_index +EXPORT_SYMBOL vmlinux 0x7ff3efc1 pci_save_state +EXPORT_SYMBOL vmlinux 0x800154ff do_SAK +EXPORT_SYMBOL vmlinux 0x80426fa2 xfrm_state_unregister_afinfo +EXPORT_SYMBOL vmlinux 0x805a8fd8 input_event +EXPORT_SYMBOL vmlinux 0x8063f83d radix_tree_gang_lookup +EXPORT_SYMBOL vmlinux 0x80e41cb9 ps2_command +EXPORT_SYMBOL vmlinux 0x81122691 scsi_cmd_ioctl +EXPORT_SYMBOL vmlinux 0x812f75d6 fb_set_cmap +EXPORT_SYMBOL vmlinux 0x81472677 acpi_get_table +EXPORT_SYMBOL vmlinux 0x814e7730 nf_ct_destroy +EXPORT_SYMBOL vmlinux 0x815b5dd4 match_octal +EXPORT_SYMBOL vmlinux 0x815f2897 empty_zero_page +EXPORT_SYMBOL vmlinux 0x81799cee vscnprintf +EXPORT_SYMBOL vmlinux 0x81bdcffc tty_throttle +EXPORT_SYMBOL vmlinux 0x81e6b37f dmi_get_system_info +EXPORT_SYMBOL vmlinux 0x82072614 tasklet_kill +EXPORT_SYMBOL vmlinux 0x820d225f print_mac +EXPORT_SYMBOL vmlinux 0x8235805b memmove +EXPORT_SYMBOL vmlinux 0x823763fa sysctl_string +EXPORT_SYMBOL vmlinux 0x8251bcc3 bitmap_release_region +EXPORT_SYMBOL vmlinux 0x82673561 schedule_delayed_work +EXPORT_SYMBOL vmlinux 0x828f6b2b request_key_async +EXPORT_SYMBOL vmlinux 0x8317e20a completion_done +EXPORT_SYMBOL vmlinux 0x831a3ec3 idr_get_new +EXPORT_SYMBOL vmlinux 0x8363c3d4 smp_call_function_mask +EXPORT_SYMBOL vmlinux 0x8375fc87 acpi_match_device_ids +EXPORT_SYMBOL vmlinux 0x83800bfa kref_init +EXPORT_SYMBOL vmlinux 0x838b3522 tty_schedule_flip +EXPORT_SYMBOL vmlinux 0x83a476ce bitmap_scnlistprintf +EXPORT_SYMBOL vmlinux 0x843f110c __skb_recv_datagram +EXPORT_SYMBOL vmlinux 0x84a41ec3 idr_replace +EXPORT_SYMBOL vmlinux 0x84afb84f xfrm_alloc_spi +EXPORT_SYMBOL vmlinux 0x84e3f7ad xfrm_state_lookup +EXPORT_SYMBOL vmlinux 0x84f409cf elevator_exit +EXPORT_SYMBOL vmlinux 0x851763dd flush_signals +EXPORT_SYMBOL vmlinux 0x852abecf __request_region +EXPORT_SYMBOL vmlinux 0x8551b841 kfree_skb +EXPORT_SYMBOL vmlinux 0x85670f1d rtnl_is_locked +EXPORT_SYMBOL vmlinux 0x85aac777 pci_request_regions +EXPORT_SYMBOL vmlinux 0x85ba5e03 __sk_dst_check +EXPORT_SYMBOL vmlinux 0x85df9b6c strsep +EXPORT_SYMBOL vmlinux 0x85e7deb2 iov_iter_fault_in_readable +EXPORT_SYMBOL vmlinux 0x863cb91a utf8_wcstombs +EXPORT_SYMBOL vmlinux 0x8664f62e cpufreq_update_policy +EXPORT_SYMBOL vmlinux 0x86893287 atm_dev_deregister +EXPORT_SYMBOL vmlinux 0x868acba5 get_options +EXPORT_SYMBOL vmlinux 0x86b16ba0 eth_header +EXPORT_SYMBOL vmlinux 0x86d08831 inetdev_by_index +EXPORT_SYMBOL vmlinux 0x86ed41ae textsearch_destroy +EXPORT_SYMBOL vmlinux 0x86fb9b05 bitmap_parse_user +EXPORT_SYMBOL vmlinux 0x87040483 netif_carrier_off +EXPORT_SYMBOL vmlinux 0x870471e5 kill_block_super +EXPORT_SYMBOL vmlinux 0x872f793b deny_write_access +EXPORT_SYMBOL vmlinux 0x8733e9a3 sleep_on_timeout +EXPORT_SYMBOL vmlinux 0x8735292f submit_bio +EXPORT_SYMBOL vmlinux 0x8750948e qdisc_watchdog_init +EXPORT_SYMBOL vmlinux 0x876004ce filemap_write_and_wait +EXPORT_SYMBOL vmlinux 0x876dafc3 ec_write +EXPORT_SYMBOL vmlinux 0x8785725d param_set_charp +EXPORT_SYMBOL vmlinux 0x878ab3ce sysctl_tcp_adv_win_scale +EXPORT_SYMBOL vmlinux 0x87ca22e1 init_file +EXPORT_SYMBOL vmlinux 0x87f61800 inode_double_lock +EXPORT_SYMBOL vmlinux 0x8801701f block_prepare_write +EXPORT_SYMBOL vmlinux 0x881039d0 zlib_inflate +EXPORT_SYMBOL vmlinux 0x8812bc40 inet_stream_ops +EXPORT_SYMBOL vmlinux 0x883d6ccf register_quota_format +EXPORT_SYMBOL vmlinux 0x88cc6001 tcp_check_req +EXPORT_SYMBOL vmlinux 0x88eac232 __dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0x88fc0c5d nf_setsockopt +EXPORT_SYMBOL vmlinux 0x88ffbf9b pci_release_selected_regions +EXPORT_SYMBOL vmlinux 0x890d2ca9 find_vma +EXPORT_SYMBOL vmlinux 0x892b26a0 set_memory_nx +EXPORT_SYMBOL vmlinux 0x89304c9c devm_iounmap +EXPORT_SYMBOL vmlinux 0x8931b32a init_net +EXPORT_SYMBOL vmlinux 0x8949858b schedule_work +EXPORT_SYMBOL vmlinux 0x8953bb27 del_timer +EXPORT_SYMBOL vmlinux 0x896a050a arch_acpi_processor_init_pdc +EXPORT_SYMBOL vmlinux 0x8973203a d_genocide +EXPORT_SYMBOL vmlinux 0x897473df mktime +EXPORT_SYMBOL vmlinux 0x89814f22 sock_no_sendmsg +EXPORT_SYMBOL vmlinux 0x898b1fec mutex_trylock +EXPORT_SYMBOL vmlinux 0x89949018 down_timeout +EXPORT_SYMBOL vmlinux 0x89befaa1 register_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0x89d5538d fb_pad_aligned_buffer +EXPORT_SYMBOL vmlinux 0x89d66811 build_ehash_secret +EXPORT_SYMBOL vmlinux 0x8a1a00a6 elv_add_request +EXPORT_SYMBOL vmlinux 0x8a1fe6bb dma_ops +EXPORT_SYMBOL vmlinux 0x8a208692 block_is_partially_uptodate +EXPORT_SYMBOL vmlinux 0x8a3eabf0 __wait_on_bit +EXPORT_SYMBOL vmlinux 0x8a7d1c31 high_memory +EXPORT_SYMBOL vmlinux 0x8a99a016 mempool_free_slab +EXPORT_SYMBOL vmlinux 0x8aaf8654 mutex_lock +EXPORT_SYMBOL vmlinux 0x8b005b81 pci_unregister_driver +EXPORT_SYMBOL vmlinux 0x8b18496f __copy_to_user_ll +EXPORT_SYMBOL vmlinux 0x8b3ca835 cpu_present_map +EXPORT_SYMBOL vmlinux 0x8b50bd1c udp_memory_allocated +EXPORT_SYMBOL vmlinux 0x8b57e096 gnet_stats_copy_app +EXPORT_SYMBOL vmlinux 0x8b618d08 overflowuid +EXPORT_SYMBOL vmlinux 0x8b61e4ce netif_receive_skb +EXPORT_SYMBOL vmlinux 0x8b989cf9 acpi_bus_can_wakeup +EXPORT_SYMBOL vmlinux 0x8ba3353a set_disk_ro +EXPORT_SYMBOL vmlinux 0x8bac0110 ethtool_op_set_sg +EXPORT_SYMBOL vmlinux 0x8bcf04fb con_set_default_unimap +EXPORT_SYMBOL vmlinux 0x8beb18d1 blk_recount_segments +EXPORT_SYMBOL vmlinux 0x8bf3996f eisa_driver_register +EXPORT_SYMBOL vmlinux 0x8c0cd329 arp_send +EXPORT_SYMBOL vmlinux 0x8c183cbe iowrite16 +EXPORT_SYMBOL vmlinux 0x8c267471 d_move +EXPORT_SYMBOL vmlinux 0x8c611294 alloc_pci_dev +EXPORT_SYMBOL vmlinux 0x8cb1d411 bdi_destroy +EXPORT_SYMBOL vmlinux 0x8cc79cab iowrite16_rep +EXPORT_SYMBOL vmlinux 0x8d156db9 textsearch_unregister +EXPORT_SYMBOL vmlinux 0x8d1dd739 serio_reconnect +EXPORT_SYMBOL vmlinux 0x8d3894f2 _ctype +EXPORT_SYMBOL vmlinux 0x8d3da668 cpufreq_get_policy +EXPORT_SYMBOL vmlinux 0x8d551bef sysctl_tcp_rmem +EXPORT_SYMBOL vmlinux 0x8d6f81b4 __div64_32 +EXPORT_SYMBOL vmlinux 0x8d7716e7 mpage_bio_submit +EXPORT_SYMBOL vmlinux 0x8d88dccd unlock_new_inode +EXPORT_SYMBOL vmlinux 0x8d8d96c6 acpi_get_sleep_type_data +EXPORT_SYMBOL vmlinux 0x8d9ea28b pci_enable_msix +EXPORT_SYMBOL vmlinux 0x8dabc3e4 km_new_mapping +EXPORT_SYMBOL vmlinux 0x8dc6e564 restore_processor_state +EXPORT_SYMBOL vmlinux 0x8ddee00d blk_queue_make_request +EXPORT_SYMBOL vmlinux 0x8de8aa9e pagevec_lookup_tag +EXPORT_SYMBOL vmlinux 0x8e002cda acpi_remove_gpe_block +EXPORT_SYMBOL vmlinux 0x8e0637ba i8253_lock +EXPORT_SYMBOL vmlinux 0x8e0b7743 ipv6_ext_hdr +EXPORT_SYMBOL vmlinux 0x8e10a33a unregister_filesystem +EXPORT_SYMBOL vmlinux 0x8e5b714a seq_release_private +EXPORT_SYMBOL vmlinux 0x8e725985 nf_log_unregister_pf +EXPORT_SYMBOL vmlinux 0x8e829b70 pci_set_consistent_dma_mask +EXPORT_SYMBOL vmlinux 0x8e99cf65 mca_device_write_pos +EXPORT_SYMBOL vmlinux 0x8ec31c77 vcc_release_async +EXPORT_SYMBOL vmlinux 0x8ef1c991 __f_setown +EXPORT_SYMBOL vmlinux 0x8f2bf526 search_binary_handler +EXPORT_SYMBOL vmlinux 0x8f54e25d sock_wmalloc +EXPORT_SYMBOL vmlinux 0x8f575c17 sock_rfree +EXPORT_SYMBOL vmlinux 0x8f69db1d inode_init_once +EXPORT_SYMBOL vmlinux 0x8f6b7950 set_irq_data +EXPORT_SYMBOL vmlinux 0x8f9c199c __get_user_2 +EXPORT_SYMBOL vmlinux 0x8fd1faa2 shrink_dcache_sb +EXPORT_SYMBOL vmlinux 0x90035333 secure_tcpv6_sequence_number +EXPORT_SYMBOL vmlinux 0x902ab96c kmap_atomic +EXPORT_SYMBOL vmlinux 0x9084c1e0 tcf_exts_destroy +EXPORT_SYMBOL vmlinux 0x909a99ee ioctl_by_bdev +EXPORT_SYMBOL vmlinux 0x90a943ba nmi_active +EXPORT_SYMBOL vmlinux 0x90da5e3f nf_unregister_hook +EXPORT_SYMBOL vmlinux 0x9144a8e2 ec_burst_disable +EXPORT_SYMBOL vmlinux 0x91481982 __ratelimit +EXPORT_SYMBOL vmlinux 0x91607d95 set_memory_wb +EXPORT_SYMBOL vmlinux 0x9173a807 xfrm_policy_byid +EXPORT_SYMBOL vmlinux 0x91b3d8fc register_sysctl_table +EXPORT_SYMBOL vmlinux 0x91c56756 set_bdi_congested +EXPORT_SYMBOL vmlinux 0x91c65d91 dquot_mark_dquot_dirty +EXPORT_SYMBOL vmlinux 0x91ca8959 acpi_get_register +EXPORT_SYMBOL vmlinux 0x91f56a6a module_put +EXPORT_SYMBOL vmlinux 0x91fab069 blkdev_issue_flush +EXPORT_SYMBOL vmlinux 0x92897e3d default_idle +EXPORT_SYMBOL vmlinux 0x929851e2 ip_mc_rejoin_group +EXPORT_SYMBOL vmlinux 0x92bd841f generic_file_aio_write_nolock +EXPORT_SYMBOL vmlinux 0x92ddacdd filp_close +EXPORT_SYMBOL vmlinux 0x9305f8e6 cpufreq_get +EXPORT_SYMBOL vmlinux 0x932d41c2 register_chrdev +EXPORT_SYMBOL vmlinux 0x9330cb9f sg_alloc_table +EXPORT_SYMBOL vmlinux 0x93706df8 blk_integrity_compare +EXPORT_SYMBOL vmlinux 0x93809fbe fb_firmware_edid +EXPORT_SYMBOL vmlinux 0x93a6e0b2 io_schedule +EXPORT_SYMBOL vmlinux 0x93afa72e vm_get_page_prot +EXPORT_SYMBOL vmlinux 0x93b1e4c7 qdisc_class_hash_grow +EXPORT_SYMBOL vmlinux 0x93b8ef56 mutex_lock_interruptible +EXPORT_SYMBOL vmlinux 0x93c69acf param_set_byte +EXPORT_SYMBOL vmlinux 0x93cbd1ec _spin_lock_bh +EXPORT_SYMBOL vmlinux 0x93fa2ee8 bdi_init +EXPORT_SYMBOL vmlinux 0x93fca811 __get_free_pages +EXPORT_SYMBOL vmlinux 0x9429da98 kernel_sock_shutdown +EXPORT_SYMBOL vmlinux 0x942f77a7 pci_set_dma_mask +EXPORT_SYMBOL vmlinux 0x94636e14 kernel_setsockopt +EXPORT_SYMBOL vmlinux 0x948e3c11 vc_resize +EXPORT_SYMBOL vmlinux 0x94961283 vunmap +EXPORT_SYMBOL vmlinux 0x949d0e06 bio_integrity_trim +EXPORT_SYMBOL vmlinux 0x94c2ddbe nf_log_unregister +EXPORT_SYMBOL vmlinux 0x94ce7bc1 kmem_ptr_validate +EXPORT_SYMBOL vmlinux 0x94fcf08e bioset_create +EXPORT_SYMBOL vmlinux 0x950fb636 neigh_table_init_no_netlink +EXPORT_SYMBOL vmlinux 0x952b15c3 generic_ro_fops +EXPORT_SYMBOL vmlinux 0x954488a4 syncookie_secret +EXPORT_SYMBOL vmlinux 0x9545af6d tasklet_init +EXPORT_SYMBOL vmlinux 0x954cbb26 vsprintf +EXPORT_SYMBOL vmlinux 0x954d764b skb_copy_and_csum_bits +EXPORT_SYMBOL vmlinux 0x95871d5d gnet_stats_start_copy_compat +EXPORT_SYMBOL vmlinux 0x95b4da4a idr_pre_get +EXPORT_SYMBOL vmlinux 0x95c7f5ec skb_prepare_seq_read +EXPORT_SYMBOL vmlinux 0x95f638d5 posix_acl_chmod_masq +EXPORT_SYMBOL vmlinux 0x9602c2ce neigh_lookup_nodev +EXPORT_SYMBOL vmlinux 0x96481cc7 per_cpu__x86_cpu_to_apicid +EXPORT_SYMBOL vmlinux 0x967d2475 kernel_bind +EXPORT_SYMBOL vmlinux 0x96898769 sysfs_format_mac +EXPORT_SYMBOL vmlinux 0x96939c04 pv_cpu_ops +EXPORT_SYMBOL vmlinux 0x96c6da6a splice_direct_to_actor +EXPORT_SYMBOL vmlinux 0x96e5890f pcie_get_readrq +EXPORT_SYMBOL vmlinux 0x96f0576c iw_handler_set_spy +EXPORT_SYMBOL vmlinux 0x97355d36 km_policy_expired +EXPORT_SYMBOL vmlinux 0x973873ab _spin_lock +EXPORT_SYMBOL vmlinux 0x973db51c vfs_path_lookup +EXPORT_SYMBOL vmlinux 0x9754ec10 radix_tree_preload +EXPORT_SYMBOL vmlinux 0x9780e385 pci_choose_state +EXPORT_SYMBOL vmlinux 0x97a26bf8 idr_init +EXPORT_SYMBOL vmlinux 0x97d8a052 simple_transaction_read +EXPORT_SYMBOL vmlinux 0x97de0ddd acpi_install_gpe_block +EXPORT_SYMBOL vmlinux 0x97df8c7e dev_set_allmulti +EXPORT_SYMBOL vmlinux 0x97f43e96 __scm_destroy +EXPORT_SYMBOL vmlinux 0x9800b9c4 simple_statfs +EXPORT_SYMBOL vmlinux 0x981026f6 km_report +EXPORT_SYMBOL vmlinux 0x983adf72 sock_common_getsockopt +EXPORT_SYMBOL vmlinux 0x98578ea8 input_free_device +EXPORT_SYMBOL vmlinux 0x986427f2 scm_fp_dup +EXPORT_SYMBOL vmlinux 0x986e6135 fb_pad_unaligned_buffer +EXPORT_SYMBOL vmlinux 0x988ed85d set_memory_x +EXPORT_SYMBOL vmlinux 0x98bb8179 con_copy_unimap +EXPORT_SYMBOL vmlinux 0x98c10d41 write_inode_now +EXPORT_SYMBOL vmlinux 0x98d5df0e pci_match_id +EXPORT_SYMBOL vmlinux 0x98e2f833 sock_no_connect +EXPORT_SYMBOL vmlinux 0x99052a84 acpi_os_write_port +EXPORT_SYMBOL vmlinux 0x995b26a7 elv_rb_add +EXPORT_SYMBOL vmlinux 0x998907a3 __dev_get_by_index +EXPORT_SYMBOL vmlinux 0x9994c0ca ps2_is_keyboard_id +EXPORT_SYMBOL vmlinux 0x999e8297 vfree +EXPORT_SYMBOL vmlinux 0x99aadb21 param_get_ulong +EXPORT_SYMBOL vmlinux 0x99bfbe39 get_unused_fd +EXPORT_SYMBOL vmlinux 0x99c3c0b0 vfs_fstat +EXPORT_SYMBOL vmlinux 0x99cdc86b sysctl_tcp_reordering +EXPORT_SYMBOL vmlinux 0x99ea12ce panic_blink +EXPORT_SYMBOL vmlinux 0x99fccc00 dev_change_flags +EXPORT_SYMBOL vmlinux 0x9a1dfd65 strpbrk +EXPORT_SYMBOL vmlinux 0x9a268782 tcp_read_sock +EXPORT_SYMBOL vmlinux 0x9a440f97 kill_pgrp +EXPORT_SYMBOL vmlinux 0x9a62169e nla_put_nohdr +EXPORT_SYMBOL vmlinux 0x9a6a83f9 cmos_lock +EXPORT_SYMBOL vmlinux 0x9a78b9bf alloc_fcdev +EXPORT_SYMBOL vmlinux 0x9a9985be percpu_counter_destroy +EXPORT_SYMBOL vmlinux 0x9ac71997 pci_bus_write_config_dword +EXPORT_SYMBOL vmlinux 0x9ac8c966 end_request +EXPORT_SYMBOL vmlinux 0x9ae3a7f8 vfs_writev +EXPORT_SYMBOL vmlinux 0x9ae8360e __vlan_hwaccel_rx +EXPORT_SYMBOL vmlinux 0x9b03f081 tcp_hashinfo +EXPORT_SYMBOL vmlinux 0x9b1c1d08 atm_dev_lookup +EXPORT_SYMBOL vmlinux 0x9b1f8361 dmam_pool_destroy +EXPORT_SYMBOL vmlinux 0x9b2ba5d2 netdev_state_change +EXPORT_SYMBOL vmlinux 0x9b355194 cdev_add +EXPORT_SYMBOL vmlinux 0x9b388444 get_zeroed_page +EXPORT_SYMBOL vmlinux 0x9b6090cf sock_get_timestampns +EXPORT_SYMBOL vmlinux 0x9b635450 tcf_exts_validate +EXPORT_SYMBOL vmlinux 0x9b8053ce generic_unplug_device +EXPORT_SYMBOL vmlinux 0x9ba7089d argv_split +EXPORT_SYMBOL vmlinux 0x9bb49b69 wireless_send_event +EXPORT_SYMBOL vmlinux 0x9bf30228 pci_enable_wake +EXPORT_SYMBOL vmlinux 0x9c012508 fb_parse_edid +EXPORT_SYMBOL vmlinux 0x9c139641 pci_find_next_bus +EXPORT_SYMBOL vmlinux 0x9c22a4b8 inet_frag_evictor +EXPORT_SYMBOL vmlinux 0x9c2c944a __copy_from_user_ll_nocache_nozero +EXPORT_SYMBOL vmlinux 0x9c6aec16 pci_prepare_to_sleep +EXPORT_SYMBOL vmlinux 0x9c7077bd enable_hlt +EXPORT_SYMBOL vmlinux 0x9c83d837 block_read_full_page +EXPORT_SYMBOL vmlinux 0x9ca57e25 __napi_schedule +EXPORT_SYMBOL vmlinux 0x9cb96e92 qdisc_put_rtab +EXPORT_SYMBOL vmlinux 0x9ccb2622 finish_wait +EXPORT_SYMBOL vmlinux 0x9ceb163c memcpy_toiovec +EXPORT_SYMBOL vmlinux 0x9ced38aa down_trylock +EXPORT_SYMBOL vmlinux 0x9cfd3aaf netlink_rcv_skb +EXPORT_SYMBOL vmlinux 0x9d17398c llc_set_station_handler +EXPORT_SYMBOL vmlinux 0x9d186782 __wait_on_buffer +EXPORT_SYMBOL vmlinux 0x9d33ef5e acpi_enable +EXPORT_SYMBOL vmlinux 0x9d43755c request_resource +EXPORT_SYMBOL vmlinux 0x9d711f1f percpu_counter_init +EXPORT_SYMBOL vmlinux 0x9d9f0d41 rwsem_down_write_failed +EXPORT_SYMBOL vmlinux 0x9dc1f05b new_inode +EXPORT_SYMBOL vmlinux 0x9dc2fe35 dma_async_tx_descriptor_init +EXPORT_SYMBOL vmlinux 0x9dcc4517 blk_queue_stack_limits +EXPORT_SYMBOL vmlinux 0x9e26f1a2 key_unlink +EXPORT_SYMBOL vmlinux 0x9e4d1172 dma_pool_alloc +EXPORT_SYMBOL vmlinux 0x9e64fbfe rtc_cmos_read +EXPORT_SYMBOL vmlinux 0x9e7d6bd0 __udelay +EXPORT_SYMBOL vmlinux 0x9e83a3e1 sock_alloc_send_skb +EXPORT_SYMBOL vmlinux 0x9e91185c vfs_rmdir +EXPORT_SYMBOL vmlinux 0x9ea614f5 ioremap_cache +EXPORT_SYMBOL vmlinux 0x9ebea808 xfrm_register_mode +EXPORT_SYMBOL vmlinux 0x9ed685ee iov_iter_advance +EXPORT_SYMBOL vmlinux 0x9eecde16 do_brk +EXPORT_SYMBOL vmlinux 0x9ef54fdc path_put +EXPORT_SYMBOL vmlinux 0x9ef749e2 unregister_chrdev +EXPORT_SYMBOL vmlinux 0x9f04e917 pcim_iounmap_regions +EXPORT_SYMBOL vmlinux 0x9f100139 jiffies_to_clock_t +EXPORT_SYMBOL vmlinux 0x9f2bdaac __bitmap_or +EXPORT_SYMBOL vmlinux 0x9f3c4d51 unregister_nls +EXPORT_SYMBOL vmlinux 0x9f8f1376 put_tty_driver +EXPORT_SYMBOL vmlinux 0x9f984513 strrchr +EXPORT_SYMBOL vmlinux 0x9fa274b4 dq_data_lock +EXPORT_SYMBOL vmlinux 0x9fb3dd30 memcpy_fromiovec +EXPORT_SYMBOL vmlinux 0x9feaf287 sonet_subtract_stats +EXPORT_SYMBOL vmlinux 0x9ff645e5 nf_register_hook +EXPORT_SYMBOL vmlinux 0x9ff92557 vfs_mkdir +EXPORT_SYMBOL vmlinux 0x9ffd5c59 neigh_seq_next +EXPORT_SYMBOL vmlinux 0xa0082321 kthread_stop +EXPORT_SYMBOL vmlinux 0xa008ce9c dma_supported +EXPORT_SYMBOL vmlinux 0xa03523d5 security_unix_stream_connect +EXPORT_SYMBOL vmlinux 0xa04a01bd qdisc_class_hash_insert +EXPORT_SYMBOL vmlinux 0xa05c03df mempool_kmalloc +EXPORT_SYMBOL vmlinux 0xa08b602c bh_submit_read +EXPORT_SYMBOL vmlinux 0xa090c0c1 __set_page_dirty_nobuffers +EXPORT_SYMBOL vmlinux 0xa0b04675 vmalloc_32 +EXPORT_SYMBOL vmlinux 0xa0ceef51 out_of_line_wait_on_bit +EXPORT_SYMBOL vmlinux 0xa0f29784 tty_unthrottle +EXPORT_SYMBOL vmlinux 0xa0fbac79 wake_up_bit +EXPORT_SYMBOL vmlinux 0xa108eb4d sysctl_optmem_max +EXPORT_SYMBOL vmlinux 0xa10d42cc sget +EXPORT_SYMBOL vmlinux 0xa120d33c tty_unregister_ldisc +EXPORT_SYMBOL vmlinux 0xa12ee269 __splice_from_pipe +EXPORT_SYMBOL vmlinux 0xa13798f8 printk_ratelimit +EXPORT_SYMBOL vmlinux 0xa14b6d3a add_disk +EXPORT_SYMBOL vmlinux 0xa14c1f73 filemap_fault +EXPORT_SYMBOL vmlinux 0xa1b759ce fb_add_videomode +EXPORT_SYMBOL vmlinux 0xa1c569d3 __seq_open_private +EXPORT_SYMBOL vmlinux 0xa1c76e0a _cond_resched +EXPORT_SYMBOL vmlinux 0xa1c9a9b7 secpath_dup +EXPORT_SYMBOL vmlinux 0xa20ce1b8 net_msg_warn +EXPORT_SYMBOL vmlinux 0xa21657f6 tty_set_operations +EXPORT_SYMBOL vmlinux 0xa257c5a3 struct_module +EXPORT_SYMBOL vmlinux 0xa27a997d file_fsync +EXPORT_SYMBOL vmlinux 0xa2929bd1 neigh_parms_alloc +EXPORT_SYMBOL vmlinux 0xa2a1e5c9 _write_lock_bh +EXPORT_SYMBOL vmlinux 0xa2a5fd77 inet_ehash_secret +EXPORT_SYMBOL vmlinux 0xa2b8cb03 uart_match_port +EXPORT_SYMBOL vmlinux 0xa3150923 llc_add_pack +EXPORT_SYMBOL vmlinux 0xa31dc680 audit_log_end +EXPORT_SYMBOL vmlinux 0xa329f07e register_shrinker +EXPORT_SYMBOL vmlinux 0xa3420d61 __percpu_counter_sum +EXPORT_SYMBOL vmlinux 0xa34c9423 pci_dev_get +EXPORT_SYMBOL vmlinux 0xa34f1ef5 crc32_le +EXPORT_SYMBOL vmlinux 0xa35c1f05 acpi_extract_package +EXPORT_SYMBOL vmlinux 0xa35de80f ipv4_config +EXPORT_SYMBOL vmlinux 0xa361dae0 nf_log_packet +EXPORT_SYMBOL vmlinux 0xa36a1add kmem_cache_alloc +EXPORT_SYMBOL vmlinux 0xa39ed96b block_write_full_page +EXPORT_SYMBOL vmlinux 0xa3bbcd80 acpi_set_gpe_type +EXPORT_SYMBOL vmlinux 0xa3d87b6e sync_dirty_buffer +EXPORT_SYMBOL vmlinux 0xa417aa57 sk_common_release +EXPORT_SYMBOL vmlinux 0xa41df38f nonseekable_open +EXPORT_SYMBOL vmlinux 0xa423d870 elevator_init +EXPORT_SYMBOL vmlinux 0xa4256a76 iget5_locked +EXPORT_SYMBOL vmlinux 0xa44072fc posix_acl_alloc +EXPORT_SYMBOL vmlinux 0xa44ad274 wait_for_completion_interruptible_timeout +EXPORT_SYMBOL vmlinux 0xa47407a5 d_rehash +EXPORT_SYMBOL vmlinux 0xa49be1d3 mca_device_read_pos +EXPORT_SYMBOL vmlinux 0xa4b94fea iowrite8_rep +EXPORT_SYMBOL vmlinux 0xa4df1151 kref_set +EXPORT_SYMBOL vmlinux 0xa4fbc8bd elv_dispatch_add_tail +EXPORT_SYMBOL vmlinux 0xa5012ae4 fb_set_var +EXPORT_SYMBOL vmlinux 0xa51cdfe8 __FIXADDR_TOP +EXPORT_SYMBOL vmlinux 0xa51d5c08 input_allocate_device +EXPORT_SYMBOL vmlinux 0xa5286855 udp_disconnect +EXPORT_SYMBOL vmlinux 0xa52d03e0 netlink_dump_start +EXPORT_SYMBOL vmlinux 0xa5423cc4 param_get_int +EXPORT_SYMBOL vmlinux 0xa5479ceb eth_header_cache_update +EXPORT_SYMBOL vmlinux 0xa5693df7 posix_acl_clone +EXPORT_SYMBOL vmlinux 0xa56f1315 mempool_free +EXPORT_SYMBOL vmlinux 0xa5764ac0 dquot_commit +EXPORT_SYMBOL vmlinux 0xa58b6804 nla_parse +EXPORT_SYMBOL vmlinux 0xa5922bb1 kfifo_init +EXPORT_SYMBOL vmlinux 0xa598e29c vesa_modes +EXPORT_SYMBOL vmlinux 0xa59fee42 netpoll_parse_options +EXPORT_SYMBOL vmlinux 0xa5a633b9 sg_last +EXPORT_SYMBOL vmlinux 0xa5ca589f pci_find_parent_resource +EXPORT_SYMBOL vmlinux 0xa5da0abd acpi_enter_sleep_state_s4bios +EXPORT_SYMBOL vmlinux 0xa60d6b71 pnp_activate_dev +EXPORT_SYMBOL vmlinux 0xa621254f iommu_bio_merge +EXPORT_SYMBOL vmlinux 0xa6646413 directly_mappable_cdev_bdi +EXPORT_SYMBOL vmlinux 0xa665332d blk_queue_segment_boundary +EXPORT_SYMBOL vmlinux 0xa68124fa hweight8 +EXPORT_SYMBOL vmlinux 0xa6814433 groups_free +EXPORT_SYMBOL vmlinux 0xa681fe88 generate_random_uuid +EXPORT_SYMBOL vmlinux 0xa693b117 pnp_register_driver +EXPORT_SYMBOL vmlinux 0xa69a07a8 pci_request_region +EXPORT_SYMBOL vmlinux 0xa6b17afb elv_rq_merge_ok +EXPORT_SYMBOL vmlinux 0xa6c0e21d datagram_poll +EXPORT_SYMBOL vmlinux 0xa6dcc773 rb_insert_color +EXPORT_SYMBOL vmlinux 0xa7046549 vprintk +EXPORT_SYMBOL vmlinux 0xa705070d dmam_alloc_coherent +EXPORT_SYMBOL vmlinux 0xa70fabbe release_evntsel_nmi +EXPORT_SYMBOL vmlinux 0xa7502f48 jiffies_to_timeval +EXPORT_SYMBOL vmlinux 0xa75e1b6a pcim_iomap +EXPORT_SYMBOL vmlinux 0xa770b803 kblockd_flush_work +EXPORT_SYMBOL vmlinux 0xa77e43af skb_copy_and_csum_dev +EXPORT_SYMBOL vmlinux 0xa78c68af skb_append +EXPORT_SYMBOL vmlinux 0xa7993532 open_exec +EXPORT_SYMBOL vmlinux 0xa7a70f68 tcf_em_register +EXPORT_SYMBOL vmlinux 0xa7aae53d tcp_prot +EXPORT_SYMBOL vmlinux 0xa7c35c6b getnstimeofday +EXPORT_SYMBOL vmlinux 0xa7ed4997 atm_dev_register +EXPORT_SYMBOL vmlinux 0xa8649f0d sock_no_setsockopt +EXPORT_SYMBOL vmlinux 0xa88c7ce4 blk_init_tags +EXPORT_SYMBOL vmlinux 0xa89a4bfb alloc_tty_driver +EXPORT_SYMBOL vmlinux 0xa89acbb3 acpi_evaluate_reference +EXPORT_SYMBOL vmlinux 0xa8c786df inode_permission +EXPORT_SYMBOL vmlinux 0xa8fef7bb security_unix_may_send +EXPORT_SYMBOL vmlinux 0xa8ff1d26 nlmsg_notify +EXPORT_SYMBOL vmlinux 0xa925899a param_set_bool +EXPORT_SYMBOL vmlinux 0xa959cd9d pci_enable_device +EXPORT_SYMBOL vmlinux 0xa95be3a3 blk_queue_bounce_limit +EXPORT_SYMBOL vmlinux 0xa96c239f sync_page_range +EXPORT_SYMBOL vmlinux 0xa9a14377 unregister_key_type +EXPORT_SYMBOL vmlinux 0xa9b733b3 __alloc_skb +EXPORT_SYMBOL vmlinux 0xa9be76e8 clocksource_register +EXPORT_SYMBOL vmlinux 0xa9e0e9e2 sb_has_dirty_inodes +EXPORT_SYMBOL vmlinux 0xa9e884c9 register_qdisc +EXPORT_SYMBOL vmlinux 0xa9fcf31d wait_for_completion_interruptible +EXPORT_SYMBOL vmlinux 0xaa024146 sonet_copy_stats +EXPORT_SYMBOL vmlinux 0xaa02f8c4 d_add_ci +EXPORT_SYMBOL vmlinux 0xaa2f84bf n_tty_ioctl +EXPORT_SYMBOL vmlinux 0xaa424349 pci_get_slot +EXPORT_SYMBOL vmlinux 0xaa6e5e90 simple_write_begin +EXPORT_SYMBOL vmlinux 0xaa7738c6 nf_register_queue_handler +EXPORT_SYMBOL vmlinux 0xaa84a8ae acpi_processor_power_init_bm_check +EXPORT_SYMBOL vmlinux 0xaab06af8 _write_lock_irqsave +EXPORT_SYMBOL vmlinux 0xaac6ccf8 dmam_free_noncoherent +EXPORT_SYMBOL vmlinux 0xaad1cb42 dev_mc_delete +EXPORT_SYMBOL vmlinux 0xaae8ab0e acpi_bus_power_manageable +EXPORT_SYMBOL vmlinux 0xaaebe34f mca_write_pos +EXPORT_SYMBOL vmlinux 0xaaf0aba4 redirty_page_for_writepage +EXPORT_SYMBOL vmlinux 0xaafdc258 strcasecmp +EXPORT_SYMBOL vmlinux 0xaaffb9a5 acpi_bus_private_data_handler +EXPORT_SYMBOL vmlinux 0xab03f099 flush_tlb_page +EXPORT_SYMBOL vmlinux 0xab1d8e96 input_unregister_device +EXPORT_SYMBOL vmlinux 0xab471003 param_array_set +EXPORT_SYMBOL vmlinux 0xab600421 probe_irq_off +EXPORT_SYMBOL vmlinux 0xab65ed80 set_memory_uc +EXPORT_SYMBOL vmlinux 0xaba0a602 __pskb_pull_tail +EXPORT_SYMBOL vmlinux 0xabd0c91c rtc_time_to_tm +EXPORT_SYMBOL vmlinux 0xabd452f2 netdev_boot_setup_check +EXPORT_SYMBOL vmlinux 0xabdcc18c request_firmware_nowait +EXPORT_SYMBOL vmlinux 0xac1065cf should_remove_suid +EXPORT_SYMBOL vmlinux 0xac1a2566 is_container_init +EXPORT_SYMBOL vmlinux 0xac383878 sync_mapping_buffers +EXPORT_SYMBOL vmlinux 0xac3b3cee __bitmap_and +EXPORT_SYMBOL vmlinux 0xac58ea5e acpi_unload_table_id +EXPORT_SYMBOL vmlinux 0xac66538c single_release +EXPORT_SYMBOL vmlinux 0xac68c796 ip_xfrm_me_harder +EXPORT_SYMBOL vmlinux 0xac816236 kmem_cache_shrink +EXPORT_SYMBOL vmlinux 0xacb38ca0 simple_unlink +EXPORT_SYMBOL vmlinux 0xaccabc6a in4_pton +EXPORT_SYMBOL vmlinux 0xacf4d843 match_strdup +EXPORT_SYMBOL vmlinux 0xacf794fd tty_chars_in_buffer +EXPORT_SYMBOL vmlinux 0xad0413d4 match_hex +EXPORT_SYMBOL vmlinux 0xad05b5c2 skb_queue_head +EXPORT_SYMBOL vmlinux 0xad07fcc5 __first_cpu +EXPORT_SYMBOL vmlinux 0xad13c689 acpi_os_execute +EXPORT_SYMBOL vmlinux 0xad1fd14d neigh_sysctl_unregister +EXPORT_SYMBOL vmlinux 0xad3e95ba nf_unregister_queue_handler +EXPORT_SYMBOL vmlinux 0xad4adc19 pci_get_class +EXPORT_SYMBOL vmlinux 0xad849a27 xfrm_input_resume +EXPORT_SYMBOL vmlinux 0xadaa2657 cpufreq_register_notifier +EXPORT_SYMBOL vmlinux 0xadbbcf41 try_to_free_buffers +EXPORT_SYMBOL vmlinux 0xadd32429 sk_alloc +EXPORT_SYMBOL vmlinux 0xaddc73f3 udp_lib_getsockopt +EXPORT_SYMBOL vmlinux 0xae1164f8 acpi_bus_add +EXPORT_SYMBOL vmlinux 0xae39693a dma_sync_wait +EXPORT_SYMBOL vmlinux 0xae3f5986 security_inode_init_security +EXPORT_SYMBOL vmlinux 0xae4e5791 unregister_tcf_proto_ops +EXPORT_SYMBOL vmlinux 0xae50e20e find_task_by_pid_type_ns +EXPORT_SYMBOL vmlinux 0xae74b0d0 pnp_is_active +EXPORT_SYMBOL vmlinux 0xaec21973 skb_over_panic +EXPORT_SYMBOL vmlinux 0xaec655c7 alloc_pages_exact +EXPORT_SYMBOL vmlinux 0xaecf8683 nla_append +EXPORT_SYMBOL vmlinux 0xaed24bb4 __scm_send +EXPORT_SYMBOL vmlinux 0xaf1442ec thaw_bdev +EXPORT_SYMBOL vmlinux 0xaf2226d0 __netif_schedule +EXPORT_SYMBOL vmlinux 0xaf3f0289 tcp_timewait_state_process +EXPORT_SYMBOL vmlinux 0xaf4b1540 acpi_get_irq_routing_table +EXPORT_SYMBOL vmlinux 0xaf5c1dd3 acpi_lock_ac_dir +EXPORT_SYMBOL vmlinux 0xaf6e10ef __break_lease +EXPORT_SYMBOL vmlinux 0xaf843694 tty_hangup +EXPORT_SYMBOL vmlinux 0xaf896cea xfrm_state_alloc +EXPORT_SYMBOL vmlinux 0xafa87278 page_address +EXPORT_SYMBOL vmlinux 0xafc11a88 setup_arg_pages +EXPORT_SYMBOL vmlinux 0xafcac6fe kmalloc_caches +EXPORT_SYMBOL vmlinux 0xafe01377 down_read +EXPORT_SYMBOL vmlinux 0xafe09070 skb_find_text +EXPORT_SYMBOL vmlinux 0xafe9bfbc sysctl_data +EXPORT_SYMBOL vmlinux 0xaff3fe69 get_sb_bdev +EXPORT_SYMBOL vmlinux 0xaff85ccd pci_remove_behind_bridge +EXPORT_SYMBOL vmlinux 0xaffdb6bc unlock_buffer +EXPORT_SYMBOL vmlinux 0xb019c37f __mod_zone_page_state +EXPORT_SYMBOL vmlinux 0xb028dafe sk_send_sigurg +EXPORT_SYMBOL vmlinux 0xb0313b4d dquot_commit_info +EXPORT_SYMBOL vmlinux 0xb0686d28 pnp_device_attach +EXPORT_SYMBOL vmlinux 0xb06fbf1c __rta_fill +EXPORT_SYMBOL vmlinux 0xb077ef32 acpi_enter_sleep_state +EXPORT_SYMBOL vmlinux 0xb07dfb3d acpi_remove_gpe_handler +EXPORT_SYMBOL vmlinux 0xb0857cf2 devm_ioremap_nocache +EXPORT_SYMBOL vmlinux 0xb08f76ad gen_pool_free +EXPORT_SYMBOL vmlinux 0xb0b847ac __bitmap_full +EXPORT_SYMBOL vmlinux 0xb0e10781 get_option +EXPORT_SYMBOL vmlinux 0xb0e76d45 tty_port_alloc_xmit_buf +EXPORT_SYMBOL vmlinux 0xb1155af4 dev_alloc_name +EXPORT_SYMBOL vmlinux 0xb121390a probe_irq_on +EXPORT_SYMBOL vmlinux 0xb13c4dba down_write +EXPORT_SYMBOL vmlinux 0xb143ab71 bdi_register_dev +EXPORT_SYMBOL vmlinux 0xb159693a skb_copy_expand +EXPORT_SYMBOL vmlinux 0xb19760c3 bitmap_onto +EXPORT_SYMBOL vmlinux 0xb1c3a01a oops_in_progress +EXPORT_SYMBOL vmlinux 0xb1cfad22 rdmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xb1e7c4ef pci_enable_device_io +EXPORT_SYMBOL vmlinux 0xb1f1244d bio_integrity_advance +EXPORT_SYMBOL vmlinux 0xb1f659a8 elv_queue_empty +EXPORT_SYMBOL vmlinux 0xb1f975aa unlock_kernel +EXPORT_SYMBOL vmlinux 0xb2017c1d per_cpu__x86_bios_cpu_apicid +EXPORT_SYMBOL vmlinux 0xb217c587 truncate_inode_pages +EXPORT_SYMBOL vmlinux 0xb27c6fa5 __serio_register_driver +EXPORT_SYMBOL vmlinux 0xb287ce6b dst_release +EXPORT_SYMBOL vmlinux 0xb2be638a dma_chan_cleanup +EXPORT_SYMBOL vmlinux 0xb2c4420c serio_close +EXPORT_SYMBOL vmlinux 0xb2e614f4 kernel_getsockopt +EXPORT_SYMBOL vmlinux 0xb2efb6be mca_read_stored_pos +EXPORT_SYMBOL vmlinux 0xb2fd5ceb __put_user_4 +EXPORT_SYMBOL vmlinux 0xb312f05a gnet_stats_finish_copy +EXPORT_SYMBOL vmlinux 0xb31526ee sg_copy_from_buffer +EXPORT_SYMBOL vmlinux 0xb31f0bd8 d_validate +EXPORT_SYMBOL vmlinux 0xb3205415 wait_for_completion_killable +EXPORT_SYMBOL vmlinux 0xb3284531 acpi_dbg_layer +EXPORT_SYMBOL vmlinux 0xb34d4c2e acpi_terminate +EXPORT_SYMBOL vmlinux 0xb351af06 xfrm_policy_delete +EXPORT_SYMBOL vmlinux 0xb352177e find_first_bit +EXPORT_SYMBOL vmlinux 0xb3692eb4 ioremap_wc +EXPORT_SYMBOL vmlinux 0xb372ca4a __nla_put +EXPORT_SYMBOL vmlinux 0xb376d79d radix_tree_tagged +EXPORT_SYMBOL vmlinux 0xb385bd74 unmap_underlying_metadata +EXPORT_SYMBOL vmlinux 0xb3a307c6 si_meminfo +EXPORT_SYMBOL vmlinux 0xb3ab0772 dump_trace +EXPORT_SYMBOL vmlinux 0xb3bdd738 sock_i_uid +EXPORT_SYMBOL vmlinux 0xb3e0590d acpi_set_current_resources +EXPORT_SYMBOL vmlinux 0xb3e6bbfe skb_copy_datagram_from_iovec +EXPORT_SYMBOL vmlinux 0xb3f0e402 xfrm_state_insert +EXPORT_SYMBOL vmlinux 0xb407b205 ioport_resource +EXPORT_SYMBOL vmlinux 0xb41f5870 alloc_etherdev_mq +EXPORT_SYMBOL vmlinux 0xb423dba1 console_blanked +EXPORT_SYMBOL vmlinux 0xb429410a posix_acl_from_mode +EXPORT_SYMBOL vmlinux 0xb42bbc7d bio_get_nr_vecs +EXPORT_SYMBOL vmlinux 0xb4390f9a mcount +EXPORT_SYMBOL vmlinux 0xb45578b8 memscan +EXPORT_SYMBOL vmlinux 0xb45b24f6 k8_nb_ids +EXPORT_SYMBOL vmlinux 0xb45ead94 rtnl_notify +EXPORT_SYMBOL vmlinux 0xb48df104 unregister_exec_domain +EXPORT_SYMBOL vmlinux 0xb494e82a br_fdb_put_hook +EXPORT_SYMBOL vmlinux 0xb4b3c93e dcache_dir_lseek +EXPORT_SYMBOL vmlinux 0xb4ca9447 __kfifo_get +EXPORT_SYMBOL vmlinux 0xb4d3eaaf pnp_release_card_device +EXPORT_SYMBOL vmlinux 0xb4f87d73 deregister_atm_ioctl +EXPORT_SYMBOL vmlinux 0xb5044271 vsscanf +EXPORT_SYMBOL vmlinux 0xb519feb6 eth_header_parse +EXPORT_SYMBOL vmlinux 0xb54533f7 usecs_to_jiffies +EXPORT_SYMBOL vmlinux 0xb55454e8 pnp_find_dev +EXPORT_SYMBOL vmlinux 0xb57b2e7e skb_truesize_bug +EXPORT_SYMBOL vmlinux 0xb5a459dc unregister_blkdev +EXPORT_SYMBOL vmlinux 0xb5d1d139 register_gifconf +EXPORT_SYMBOL vmlinux 0xb5d52c27 ec_transaction +EXPORT_SYMBOL vmlinux 0xb60a6719 ethtool_op_get_tso +EXPORT_SYMBOL vmlinux 0xb60e34a8 nla_memcpy +EXPORT_SYMBOL vmlinux 0xb62b7134 task_nice +EXPORT_SYMBOL vmlinux 0xb678366f int_sqrt +EXPORT_SYMBOL vmlinux 0xb6a61a86 qdisc_get_rtab +EXPORT_SYMBOL vmlinux 0xb6af570e tcp_v4_syn_recv_sock +EXPORT_SYMBOL vmlinux 0xb6e227aa rtc_lock +EXPORT_SYMBOL vmlinux 0xb6e334db tty_get_baud_rate +EXPORT_SYMBOL vmlinux 0xb6ed1e53 strncpy +EXPORT_SYMBOL vmlinux 0xb6f2b735 tty_insert_flip_string_flags +EXPORT_SYMBOL vmlinux 0xb6f531b8 cont_write_begin +EXPORT_SYMBOL vmlinux 0xb6fe74b7 xfrm_state_walk +EXPORT_SYMBOL vmlinux 0xb703911e release_firmware +EXPORT_SYMBOL vmlinux 0xb70d26d0 inet_twsk_deschedule +EXPORT_SYMBOL vmlinux 0xb714a981 console_print +EXPORT_SYMBOL vmlinux 0xb72397d5 printk +EXPORT_SYMBOL vmlinux 0xb746136f set_page_dirty +EXPORT_SYMBOL vmlinux 0xb747c67e I_BDEV +EXPORT_SYMBOL vmlinux 0xb74dd837 xfrm_stateonly_find +EXPORT_SYMBOL vmlinux 0xb7555f12 timeval_to_jiffies +EXPORT_SYMBOL vmlinux 0xb758b225 acpi_disable_event +EXPORT_SYMBOL vmlinux 0xb76195ea kmap_high +EXPORT_SYMBOL vmlinux 0xb7b61546 crc32_be +EXPORT_SYMBOL vmlinux 0xb7e49abd netlink_ack +EXPORT_SYMBOL vmlinux 0xb81cf914 __tcp_get_md5sig_pool +EXPORT_SYMBOL vmlinux 0xb837f7e8 skb_store_bits +EXPORT_SYMBOL vmlinux 0xb8406373 get_sb_nodev +EXPORT_SYMBOL vmlinux 0xb8414917 truncate_inode_pages_range +EXPORT_SYMBOL vmlinux 0xb84829fa stop_tty +EXPORT_SYMBOL vmlinux 0xb84b92c4 open_bdev_excl +EXPORT_SYMBOL vmlinux 0xb8576d27 framebuffer_release +EXPORT_SYMBOL vmlinux 0xb85b2bac vm_stat +EXPORT_SYMBOL vmlinux 0xb86960f1 skb_copy +EXPORT_SYMBOL vmlinux 0xb86e4ab9 random32 +EXPORT_SYMBOL vmlinux 0xb892ca4b fifo_create_dflt +EXPORT_SYMBOL vmlinux 0xb894926d schedule_work_on +EXPORT_SYMBOL vmlinux 0xb89af9bf srandom32 +EXPORT_SYMBOL vmlinux 0xb8e7ce2c __put_user_8 +EXPORT_SYMBOL vmlinux 0xb940ff04 pnp_disable_dev +EXPORT_SYMBOL vmlinux 0xb950eb69 sock_no_mmap +EXPORT_SYMBOL vmlinux 0xb9603636 kthread_create +EXPORT_SYMBOL vmlinux 0xb98a0185 rtc_tm_to_time +EXPORT_SYMBOL vmlinux 0xb9b865e6 inet_frags_init +EXPORT_SYMBOL vmlinux 0xb9c74bf1 gen_kill_estimator +EXPORT_SYMBOL vmlinux 0xb9fd2205 add_efi_memmap +EXPORT_SYMBOL vmlinux 0xba2d8594 ec_read +EXPORT_SYMBOL vmlinux 0xba42fc74 bio_alloc +EXPORT_SYMBOL vmlinux 0xba497f13 loops_per_jiffy +EXPORT_SYMBOL vmlinux 0xba742696 skb_make_writable +EXPORT_SYMBOL vmlinux 0xba850e86 unregister_console +EXPORT_SYMBOL vmlinux 0xba9b35ff proc_mkdir +EXPORT_SYMBOL vmlinux 0xbab62172 d_find_alias +EXPORT_SYMBOL vmlinux 0xbac1a6e1 acpi_bus_unregister_driver +EXPORT_SYMBOL vmlinux 0xbacab5b7 bdevname +EXPORT_SYMBOL vmlinux 0xbad5e487 dmam_declare_coherent_memory +EXPORT_SYMBOL vmlinux 0xbb167766 fb_var_to_videomode +EXPORT_SYMBOL vmlinux 0xbb189cad disallow_signal +EXPORT_SYMBOL vmlinux 0xbb29b128 make_EII_client +EXPORT_SYMBOL vmlinux 0xbb315e5a netlink_kernel_release +EXPORT_SYMBOL vmlinux 0xbb368b42 alloc_disk_node +EXPORT_SYMBOL vmlinux 0xbb5d343d xfrm_get_acqseq +EXPORT_SYMBOL vmlinux 0xbb83bd29 xfrm_cfg_mutex +EXPORT_SYMBOL vmlinux 0xbb996c6f generic_fillattr +EXPORT_SYMBOL vmlinux 0xbb99ea2d inet_shutdown +EXPORT_SYMBOL vmlinux 0xbbc0767a locks_init_lock +EXPORT_SYMBOL vmlinux 0xbbc8e804 param_set_ushort +EXPORT_SYMBOL vmlinux 0xbbfe98b0 kobject_add +EXPORT_SYMBOL vmlinux 0xbc21aa24 con_is_bound +EXPORT_SYMBOL vmlinux 0xbc40f33d pci_bus_read_config_word +EXPORT_SYMBOL vmlinux 0xbc94f66d per_cpu__cpu_info +EXPORT_SYMBOL vmlinux 0xbc972596 pci_bus_assign_resources +EXPORT_SYMBOL vmlinux 0xbc9fe26a input_register_device +EXPORT_SYMBOL vmlinux 0xbcbf5e36 free_netdev +EXPORT_SYMBOL vmlinux 0xbcc308bb strnlen_user +EXPORT_SYMBOL vmlinux 0xbcf0f4d8 k8_northbridges +EXPORT_SYMBOL vmlinux 0xbcfdfefd vmtruncate +EXPORT_SYMBOL vmlinux 0xbd583759 proc_dointvec_jiffies +EXPORT_SYMBOL vmlinux 0xbd70907f skb_push +EXPORT_SYMBOL vmlinux 0xbda82f90 proc_dointvec_userhz_jiffies +EXPORT_SYMBOL vmlinux 0xbdf83c97 __locks_copy_lock +EXPORT_SYMBOL vmlinux 0xbe0e5118 nla_memcmp +EXPORT_SYMBOL vmlinux 0xbe11f9a6 mntput_no_expire +EXPORT_SYMBOL vmlinux 0xbe1283fe mpage_writepages +EXPORT_SYMBOL vmlinux 0xbe4f3ef0 llc_sap_find +EXPORT_SYMBOL vmlinux 0xbe63b8b3 kernel_getsockname +EXPORT_SYMBOL vmlinux 0xbe67a751 proto_register +EXPORT_SYMBOL vmlinux 0xbe6aeb67 dmam_free_coherent +EXPORT_SYMBOL vmlinux 0xbe6df6ae call_usermodehelper_setkeys +EXPORT_SYMBOL vmlinux 0xbe87c275 xfrm_state_add +EXPORT_SYMBOL vmlinux 0xbec64e08 open_by_devnum +EXPORT_SYMBOL vmlinux 0xbef43296 console_conditional_schedule +EXPORT_SYMBOL vmlinux 0xbf13b163 rwsem_down_read_failed +EXPORT_SYMBOL vmlinux 0xbf282c90 pcibios_set_irq_routing +EXPORT_SYMBOL vmlinux 0xbf34b1aa sockfd_lookup +EXPORT_SYMBOL vmlinux 0xbf5e18c0 serio_interrupt +EXPORT_SYMBOL vmlinux 0xbf6b18f9 rtnl_set_sk_err +EXPORT_SYMBOL vmlinux 0xbf7fd2f5 schedule_timeout_killable +EXPORT_SYMBOL vmlinux 0xbf80f172 register_binfmt +EXPORT_SYMBOL vmlinux 0xbf854e2b pci_bus_add_devices +EXPORT_SYMBOL vmlinux 0xbf8b39e9 isapnp_present +EXPORT_SYMBOL vmlinux 0xbf9292a1 sync_page_range_nolock +EXPORT_SYMBOL vmlinux 0xbf9bcc8d __cap_empty_set +EXPORT_SYMBOL vmlinux 0xbfc177bc iowrite32_rep +EXPORT_SYMBOL vmlinux 0xbfca31b4 bio_unmap_user +EXPORT_SYMBOL vmlinux 0xbfd007dc dev_unicast_unsync +EXPORT_SYMBOL vmlinux 0xbfd77233 page_zero_new_buffers +EXPORT_SYMBOL vmlinux 0xbff1e7a7 is_bad_inode +EXPORT_SYMBOL vmlinux 0xc003c637 __strncpy_from_user +EXPORT_SYMBOL vmlinux 0xc007dc6c fifo_set_limit +EXPORT_SYMBOL vmlinux 0xc01eed33 __copy_from_user_ll_nozero +EXPORT_SYMBOL vmlinux 0xc025aa6f compute_creds +EXPORT_SYMBOL vmlinux 0xc045ad4e timespec_trunc +EXPORT_SYMBOL vmlinux 0xc04eb509 skb_recv_datagram +EXPORT_SYMBOL vmlinux 0xc0567784 fb_find_mode +EXPORT_SYMBOL vmlinux 0xc0580937 rb_erase +EXPORT_SYMBOL vmlinux 0xc0994f58 register_nls +EXPORT_SYMBOL vmlinux 0xc09d825b uart_write_wakeup +EXPORT_SYMBOL vmlinux 0xc0a3d105 find_next_bit +EXPORT_SYMBOL vmlinux 0xc0a6e715 end_buffer_write_sync +EXPORT_SYMBOL vmlinux 0xc0f65988 machine_real_restart +EXPORT_SYMBOL vmlinux 0xc11d8093 iov_shorten +EXPORT_SYMBOL vmlinux 0xc13a6c70 send_sig +EXPORT_SYMBOL vmlinux 0xc13ddd0b copy_strings_kernel +EXPORT_SYMBOL vmlinux 0xc1494938 blk_insert_request +EXPORT_SYMBOL vmlinux 0xc1ce2d53 gnet_stats_copy_basic +EXPORT_SYMBOL vmlinux 0xc1e8fdb6 genl_unregister_ops +EXPORT_SYMBOL vmlinux 0xc1f10c6f tcp_proc_register +EXPORT_SYMBOL vmlinux 0xc209a71f posix_lock_file_wait +EXPORT_SYMBOL vmlinux 0xc20ef687 kmem_cache_free +EXPORT_SYMBOL vmlinux 0xc221d3fc idr_destroy +EXPORT_SYMBOL vmlinux 0xc22e8068 __breadahead +EXPORT_SYMBOL vmlinux 0xc22fa43a neigh_compat_output +EXPORT_SYMBOL vmlinux 0xc2363fec udp_lib_setsockopt +EXPORT_SYMBOL vmlinux 0xc254af48 dcache_lock +EXPORT_SYMBOL vmlinux 0xc256e762 __bitmap_equal +EXPORT_SYMBOL vmlinux 0xc2684ef9 inet_listen +EXPORT_SYMBOL vmlinux 0xc280a525 __copy_from_user_ll +EXPORT_SYMBOL vmlinux 0xc2ca51c3 __lock_page +EXPORT_SYMBOL vmlinux 0xc2d711e1 krealloc +EXPORT_SYMBOL vmlinux 0xc2e587d1 reset_devices +EXPORT_SYMBOL vmlinux 0xc33f6f4c on_each_cpu +EXPORT_SYMBOL vmlinux 0xc34eb9db key_link +EXPORT_SYMBOL vmlinux 0xc37d42c5 pneigh_lookup +EXPORT_SYMBOL vmlinux 0xc389d4a4 skb_free_datagram +EXPORT_SYMBOL vmlinux 0xc38e5923 udp_stats_in6 +EXPORT_SYMBOL vmlinux 0xc38e82f1 d_alloc_name +EXPORT_SYMBOL vmlinux 0xc3a69105 rtnl_unicast +EXPORT_SYMBOL vmlinux 0xc3aaf0a9 __put_user_1 +EXPORT_SYMBOL vmlinux 0xc3ba7197 blk_alloc_queue +EXPORT_SYMBOL vmlinux 0xc3c3a178 sk_dst_check +EXPORT_SYMBOL vmlinux 0xc3cf1128 in_group_p +EXPORT_SYMBOL vmlinux 0xc3e2781f unregister_framebuffer +EXPORT_SYMBOL vmlinux 0xc3f64d1c bh_uptodate_or_lock +EXPORT_SYMBOL vmlinux 0xc3fa6a59 memchr +EXPORT_SYMBOL vmlinux 0xc402cc99 register_acpi_notifier +EXPORT_SYMBOL vmlinux 0xc499ae1e kstrdup +EXPORT_SYMBOL vmlinux 0xc4a90136 sysctl_jiffies +EXPORT_SYMBOL vmlinux 0xc4ac134c pskb_expand_head +EXPORT_SYMBOL vmlinux 0xc4e17929 __blockdev_direct_IO +EXPORT_SYMBOL vmlinux 0xc4e90b33 atm_charge +EXPORT_SYMBOL vmlinux 0xc4f4cd32 inet_stream_connect +EXPORT_SYMBOL vmlinux 0xc4f9cb0e tcp_sendmsg +EXPORT_SYMBOL vmlinux 0xc51db010 remove_inode_hash +EXPORT_SYMBOL vmlinux 0xc52f5714 fb_videomode_to_var +EXPORT_SYMBOL vmlinux 0xc54828b3 blk_rq_unmap_user +EXPORT_SYMBOL vmlinux 0xc54fcab0 vm_insert_page +EXPORT_SYMBOL vmlinux 0xc5534d64 ioread16 +EXPORT_SYMBOL vmlinux 0xc55f7dc7 _write_trylock +EXPORT_SYMBOL vmlinux 0xc5718627 sg_copy_to_buffer +EXPORT_SYMBOL vmlinux 0xc57a488f pci_add_new_bus +EXPORT_SYMBOL vmlinux 0xc5844fb8 __per_cpu_offset +EXPORT_SYMBOL vmlinux 0xc5d57c67 unregister_sysrq_key +EXPORT_SYMBOL vmlinux 0xc5ddeeac skb_unlink +EXPORT_SYMBOL vmlinux 0xc6550290 alloc_hippi_dev +EXPORT_SYMBOL vmlinux 0xc67296ba generic_file_llseek +EXPORT_SYMBOL vmlinux 0xc6cc8916 pci_get_device +EXPORT_SYMBOL vmlinux 0xc6f2e002 textsearch_find_continuous +EXPORT_SYMBOL vmlinux 0xc7208c3a serial8250_resume_port +EXPORT_SYMBOL vmlinux 0xc738548c ipv4_specific +EXPORT_SYMBOL vmlinux 0xc778cdcb blk_queue_max_segment_size +EXPORT_SYMBOL vmlinux 0xc782f5ee pnp_possible_config +EXPORT_SYMBOL vmlinux 0xc7a2181a pci_find_slot +EXPORT_SYMBOL vmlinux 0xc7a3668c make_bad_inode +EXPORT_SYMBOL vmlinux 0xc7a4fbed rtnl_lock +EXPORT_SYMBOL vmlinux 0xc7b8e0b4 serio_rescan +EXPORT_SYMBOL vmlinux 0xc7ec6c27 strspn +EXPORT_SYMBOL vmlinux 0xc8047a3d input_register_handler +EXPORT_SYMBOL vmlinux 0xc8a39304 sg_miter_next +EXPORT_SYMBOL vmlinux 0xc8b57c27 autoremove_wake_function +EXPORT_SYMBOL vmlinux 0xc8ca3e25 acpi_get_child +EXPORT_SYMBOL vmlinux 0xc8d997cf tcp_create_openreq_child +EXPORT_SYMBOL vmlinux 0xc8ffda6d tcf_exts_dump +EXPORT_SYMBOL vmlinux 0xc91dc29a __free_pages +EXPORT_SYMBOL vmlinux 0xc92d1dd5 current_fs_time +EXPORT_SYMBOL vmlinux 0xc932b7b4 __bread +EXPORT_SYMBOL vmlinux 0xc95da1a0 seq_printf +EXPORT_SYMBOL vmlinux 0xc98f6353 xfrm_policy_register_afinfo +EXPORT_SYMBOL vmlinux 0xc998d641 icmp_err_convert +EXPORT_SYMBOL vmlinux 0xc9ab2eef acpi_os_wait_events_complete +EXPORT_SYMBOL vmlinux 0xc9dc867b vfs_symlink +EXPORT_SYMBOL vmlinux 0xc9fa51c3 blk_queue_resize_tags +EXPORT_SYMBOL vmlinux 0xca16161d vfs_quota_on_path +EXPORT_SYMBOL vmlinux 0xca1e9159 __tcf_em_tree_match +EXPORT_SYMBOL vmlinux 0xca5172a6 sock_recvmsg +EXPORT_SYMBOL vmlinux 0xca8acc78 acpi_dbg_level +EXPORT_SYMBOL vmlinux 0xcac123b7 alloc_fddidev +EXPORT_SYMBOL vmlinux 0xcaf4323f tcp_child_process +EXPORT_SYMBOL vmlinux 0xcb228adb __xfrm_decode_session +EXPORT_SYMBOL vmlinux 0xcb32da10 param_set_int +EXPORT_SYMBOL vmlinux 0xcb39cffe ida_get_new +EXPORT_SYMBOL vmlinux 0xcb6beb40 hweight32 +EXPORT_SYMBOL vmlinux 0xcb7131fb fb_get_options +EXPORT_SYMBOL vmlinux 0xcb733bf2 acpi_bus_set_power +EXPORT_SYMBOL vmlinux 0xcb7357eb skb_pad +EXPORT_SYMBOL vmlinux 0xcbd5280a pci_bus_write_config_word +EXPORT_SYMBOL vmlinux 0xcbf62bd7 tcp_initialize_rcv_mss +EXPORT_SYMBOL vmlinux 0xcc102a0e __page_symlink +EXPORT_SYMBOL vmlinux 0xcc248d26 serial8250_suspend_port +EXPORT_SYMBOL vmlinux 0xcc36f32e fb_unregister_client +EXPORT_SYMBOL vmlinux 0xcc39edb4 dma_alloc_coherent +EXPORT_SYMBOL vmlinux 0xcc5005fe msleep_interruptible +EXPORT_SYMBOL vmlinux 0xcc51ee50 dma_spin_lock +EXPORT_SYMBOL vmlinux 0xcc72c324 generic_read_dir +EXPORT_SYMBOL vmlinux 0xcc7fa952 local_bh_enable_ip +EXPORT_SYMBOL vmlinux 0xcd527bdf dquot_acquire +EXPORT_SYMBOL vmlinux 0xcd7c19f8 bio_put +EXPORT_SYMBOL vmlinux 0xcdedc928 tcp_v4_connect +EXPORT_SYMBOL vmlinux 0xce36ded6 sysctl_tcp_mem +EXPORT_SYMBOL vmlinux 0xce4904a4 acpi_leave_sleep_state +EXPORT_SYMBOL vmlinux 0xce4b3c7d tty_insert_flip_string +EXPORT_SYMBOL vmlinux 0xce5ac24f zlib_inflate_workspacesize +EXPORT_SYMBOL vmlinux 0xce6e0571 netpoll_setup +EXPORT_SYMBOL vmlinux 0xce88367d ida_pre_get +EXPORT_SYMBOL vmlinux 0xced813bb vmap +EXPORT_SYMBOL vmlinux 0xcefcd99a serial8250_unregister_port +EXPORT_SYMBOL vmlinux 0xcf047c83 acpi_disable_gpe +EXPORT_SYMBOL vmlinux 0xcf3c1723 inet_sk_rebuild_header +EXPORT_SYMBOL vmlinux 0xcf51f028 block_write_begin +EXPORT_SYMBOL vmlinux 0xcf77dff1 simple_prepare_write +EXPORT_SYMBOL vmlinux 0xcf89a462 pci_disable_msi +EXPORT_SYMBOL vmlinux 0xcf906655 tcp_setsockopt +EXPORT_SYMBOL vmlinux 0xcfadd723 __percpu_counter_add +EXPORT_SYMBOL vmlinux 0xcfc9ee4b tcf_em_tree_destroy +EXPORT_SYMBOL vmlinux 0xcfcfbe2f bio_copy_kern +EXPORT_SYMBOL vmlinux 0xcfd3018e set_normalized_timespec +EXPORT_SYMBOL vmlinux 0xcff26cfb simple_getattr +EXPORT_SYMBOL vmlinux 0xd016961f generic_file_mmap +EXPORT_SYMBOL vmlinux 0xd0181f4f __bitmap_xor +EXPORT_SYMBOL vmlinux 0xd0250dde bio_integrity_endio +EXPORT_SYMBOL vmlinux 0xd027eb39 acpi_unlock_battery_dir +EXPORT_SYMBOL vmlinux 0xd02cc869 __bitmap_andnot +EXPORT_SYMBOL vmlinux 0xd05daf57 neigh_seq_start +EXPORT_SYMBOL vmlinux 0xd06c2c05 kernel_getpeername +EXPORT_SYMBOL vmlinux 0xd08197fa acpi_load_tables +EXPORT_SYMBOL vmlinux 0xd0a61c96 ip_fragment +EXPORT_SYMBOL vmlinux 0xd0a8d4dc thermal_zone_unbind_cooling_device +EXPORT_SYMBOL vmlinux 0xd0d8621b strlen +EXPORT_SYMBOL vmlinux 0xd0ee38b8 schedule_timeout_uninterruptible +EXPORT_SYMBOL vmlinux 0xd13090aa set_pages_wb +EXPORT_SYMBOL vmlinux 0xd1472061 acpi_pci_register_driver +EXPORT_SYMBOL vmlinux 0xd177f85f pneigh_enqueue +EXPORT_SYMBOL vmlinux 0xd18b6eb2 acpi_unmap_lsapic +EXPORT_SYMBOL vmlinux 0xd19a29f6 __module_put_and_exit +EXPORT_SYMBOL vmlinux 0xd19e94c2 pci_scan_bridge +EXPORT_SYMBOL vmlinux 0xd1ba6ae4 ip_getsockopt +EXPORT_SYMBOL vmlinux 0xd1daef2f tcf_em_tree_validate +EXPORT_SYMBOL vmlinux 0xd1f6c5f3 smp_num_siblings +EXPORT_SYMBOL vmlinux 0xd1f91bcd dev_base_lock +EXPORT_SYMBOL vmlinux 0xd251d7b0 security_socket_getpeersec_dgram +EXPORT_SYMBOL vmlinux 0xd2555f19 jiffies_64_to_clock_t +EXPORT_SYMBOL vmlinux 0xd25b5856 inet_frags_exit_net +EXPORT_SYMBOL vmlinux 0xd25d4f74 console_blank_hook +EXPORT_SYMBOL vmlinux 0xd267d42c down_killable +EXPORT_SYMBOL vmlinux 0xd2965f6f kthread_should_stop +EXPORT_SYMBOL vmlinux 0xd2981b51 request_key_async_with_auxdata +EXPORT_SYMBOL vmlinux 0xd2a941d4 sg_init_table +EXPORT_SYMBOL vmlinux 0xd2a94276 pci_setup_cardbus +EXPORT_SYMBOL vmlinux 0xd2da97a7 sk_release_kernel +EXPORT_SYMBOL vmlinux 0xd2dab5c4 start_tty +EXPORT_SYMBOL vmlinux 0xd2faf2d2 skb_clone +EXPORT_SYMBOL vmlinux 0xd302c4a2 input_unregister_handler +EXPORT_SYMBOL vmlinux 0xd33e0dd5 blk_integrity_register +EXPORT_SYMBOL vmlinux 0xd34f0c62 gen_pool_create +EXPORT_SYMBOL vmlinux 0xd365f298 call_usermodehelper_exec +EXPORT_SYMBOL vmlinux 0xd38534fa dst_destroy +EXPORT_SYMBOL vmlinux 0xd3951da4 acpi_resource_to_address64 +EXPORT_SYMBOL vmlinux 0xd3d8af9e ip_mc_join_group +EXPORT_SYMBOL vmlinux 0xd3f74cf1 interruptible_sleep_on_timeout +EXPORT_SYMBOL vmlinux 0xd42b7232 _write_unlock_bh +EXPORT_SYMBOL vmlinux 0xd47d97c4 iw_handler_get_thrspy +EXPORT_SYMBOL vmlinux 0xd48c5fbf notify_change +EXPORT_SYMBOL vmlinux 0xd4a7fe74 inet_frag_destroy +EXPORT_SYMBOL vmlinux 0xd4ce7ad8 single_open +EXPORT_SYMBOL vmlinux 0xd4d1af1a blk_queue_find_tag +EXPORT_SYMBOL vmlinux 0xd4e5edac tcf_exts_change +EXPORT_SYMBOL vmlinux 0xd4f142e3 filp_open +EXPORT_SYMBOL vmlinux 0xd4f472e1 __pci_register_driver +EXPORT_SYMBOL vmlinux 0xd551404e dquot_initialize +EXPORT_SYMBOL vmlinux 0xd55b6f37 xfrm_find_acq_byseq +EXPORT_SYMBOL vmlinux 0xd5688a7a radix_tree_insert +EXPORT_SYMBOL vmlinux 0xd58d02f8 dquot_drop +EXPORT_SYMBOL vmlinux 0xd5b037e1 kref_put +EXPORT_SYMBOL vmlinux 0xd5b52d06 alloc_disk +EXPORT_SYMBOL vmlinux 0xd5c4155e unbind_con_driver +EXPORT_SYMBOL vmlinux 0xd5eb836f generic_osync_inode +EXPORT_SYMBOL vmlinux 0xd6035d05 do_settimeofday +EXPORT_SYMBOL vmlinux 0xd62c833f schedule_timeout +EXPORT_SYMBOL vmlinux 0xd6573b69 tcf_generic_walker +EXPORT_SYMBOL vmlinux 0xd65daeaa acpi_root_dir +EXPORT_SYMBOL vmlinux 0xd68b76c5 vfs_follow_link +EXPORT_SYMBOL vmlinux 0xd6a78d08 smp_call_function_single +EXPORT_SYMBOL vmlinux 0xd6aeaaa4 nla_put +EXPORT_SYMBOL vmlinux 0xd6b33026 cpu_khz +EXPORT_SYMBOL vmlinux 0xd6d9cce1 blkdev_get +EXPORT_SYMBOL vmlinux 0xd6ee688f vmalloc +EXPORT_SYMBOL vmlinux 0xd731f295 neigh_parms_release +EXPORT_SYMBOL vmlinux 0xd765f219 balance_dirty_pages_ratelimited_nr +EXPORT_SYMBOL vmlinux 0xd77a2498 mca_device_status +EXPORT_SYMBOL vmlinux 0xd78ada57 skb_checksum_help +EXPORT_SYMBOL vmlinux 0xd79b5a02 allow_signal +EXPORT_SYMBOL vmlinux 0xd7a6fafa panic_notifier_list +EXPORT_SYMBOL vmlinux 0xd7d1c490 kernel_recvmsg +EXPORT_SYMBOL vmlinux 0xd7dd777b reserve_perfctr_nmi +EXPORT_SYMBOL vmlinux 0xd816aea7 user_path_at +EXPORT_SYMBOL vmlinux 0xd818d09a tcp_v4_conn_request +EXPORT_SYMBOL vmlinux 0xd82c28e9 locks_remove_posix +EXPORT_SYMBOL vmlinux 0xd83e495a neigh_resolve_output +EXPORT_SYMBOL vmlinux 0xd8434b93 d_alloc_anon +EXPORT_SYMBOL vmlinux 0xd873c013 generic_file_splice_read +EXPORT_SYMBOL vmlinux 0xd88f695a __mod_timer +EXPORT_SYMBOL vmlinux 0xd89da37f movable_zone +EXPORT_SYMBOL vmlinux 0xd89e09cf kobject_del +EXPORT_SYMBOL vmlinux 0xd8a2ab95 in_egroup_p +EXPORT_SYMBOL vmlinux 0xd8e0a990 key_task_permission +EXPORT_SYMBOL vmlinux 0xd8e484f0 register_chrdev_region +EXPORT_SYMBOL vmlinux 0xd9091363 acpi_install_notify_handler +EXPORT_SYMBOL vmlinux 0xd929dd9b pnp_get_resource +EXPORT_SYMBOL vmlinux 0xd9850293 d_invalidate +EXPORT_SYMBOL vmlinux 0xd985dc99 mempool_free_pages +EXPORT_SYMBOL vmlinux 0xd9967ed8 ilookup5 +EXPORT_SYMBOL vmlinux 0xd9c272aa mca_mark_as_unused +EXPORT_SYMBOL vmlinux 0xd9dc2880 cpu_mask_all +EXPORT_SYMBOL vmlinux 0xda08c0d7 pcibios_get_irq_routing_table +EXPORT_SYMBOL vmlinux 0xda0a6b0e acpi_map_lsapic +EXPORT_SYMBOL vmlinux 0xda1a7335 kasprintf +EXPORT_SYMBOL vmlinux 0xda1f7e72 xfrm_lookup +EXPORT_SYMBOL vmlinux 0xda580a14 pci_dev_driver +EXPORT_SYMBOL vmlinux 0xda7ca6cb fb_mode_is_equal +EXPORT_SYMBOL vmlinux 0xda8af7ad fb_find_nearest_mode +EXPORT_SYMBOL vmlinux 0xda8fd495 isapnp_write_byte +EXPORT_SYMBOL vmlinux 0xda928914 nmi_watchdog +EXPORT_SYMBOL vmlinux 0xdaa57ec3 totalhigh_pages +EXPORT_SYMBOL vmlinux 0xdac8b9e0 grab_cache_page_nowait +EXPORT_SYMBOL vmlinux 0xdacd632e vfs_dq_drop +EXPORT_SYMBOL vmlinux 0xdad96e87 thermal_cooling_device_unregister +EXPORT_SYMBOL vmlinux 0xdafff9b0 __bio_clone +EXPORT_SYMBOL vmlinux 0xdb0e2092 file_permission +EXPORT_SYMBOL vmlinux 0xdb2e3c5d clear_inode +EXPORT_SYMBOL vmlinux 0xdb31973b do_sync_write +EXPORT_SYMBOL vmlinux 0xdb4ea64f tty_register_driver +EXPORT_SYMBOL vmlinux 0xdb6ce750 copy_io_context +EXPORT_SYMBOL vmlinux 0xdb864d65 iov_iter_single_seg_count +EXPORT_SYMBOL vmlinux 0xdb91afc3 register_snap_client +EXPORT_SYMBOL vmlinux 0xdbb8a8ab sock_no_sendpage +EXPORT_SYMBOL vmlinux 0xdbcd416e sysctl_ip_nonlocal_bind +EXPORT_SYMBOL vmlinux 0xdbdf487d lease_modify +EXPORT_SYMBOL vmlinux 0xdc14eda7 pci_pci_problems +EXPORT_SYMBOL vmlinux 0xdc2adb35 add_taint +EXPORT_SYMBOL vmlinux 0xdc43a9c8 daemonize +EXPORT_SYMBOL vmlinux 0xdc5f130e wait_on_sync_kiocb +EXPORT_SYMBOL vmlinux 0xdc73987e set_blocksize +EXPORT_SYMBOL vmlinux 0xdc77f662 brioctl_set +EXPORT_SYMBOL vmlinux 0xdc873a70 screen_info +EXPORT_SYMBOL vmlinux 0xdcc0727d vfs_readlink +EXPORT_SYMBOL vmlinux 0xdd0a2ba2 strlcat +EXPORT_SYMBOL vmlinux 0xdd513861 blk_queue_update_dma_pad +EXPORT_SYMBOL vmlinux 0xdd5aad98 __ht_create_irq +EXPORT_SYMBOL vmlinux 0xdd6791e4 d_alloc +EXPORT_SYMBOL vmlinux 0xdd6bfccd radix_tree_tag_set +EXPORT_SYMBOL vmlinux 0xdd8652d5 register_framebuffer +EXPORT_SYMBOL vmlinux 0xddb630b3 sock_register +EXPORT_SYMBOL vmlinux 0xddc1ac11 bioset_integrity_free +EXPORT_SYMBOL vmlinux 0xddc76e24 pci_find_device +EXPORT_SYMBOL vmlinux 0xddeef053 vfs_stat +EXPORT_SYMBOL vmlinux 0xde002c40 generic_file_aio_write +EXPORT_SYMBOL vmlinux 0xde311177 dget_locked +EXPORT_SYMBOL vmlinux 0xde6cc813 km_state_notify +EXPORT_SYMBOL vmlinux 0xde75b689 set_irq_type +EXPORT_SYMBOL vmlinux 0xde9360ba totalram_pages +EXPORT_SYMBOL vmlinux 0xde98affd page_follow_link_light +EXPORT_SYMBOL vmlinux 0xdec990bb blk_queue_max_phys_segments +EXPORT_SYMBOL vmlinux 0xdece1961 dev_getfirstbyhwtype +EXPORT_SYMBOL vmlinux 0xdedccda2 blk_rq_init +EXPORT_SYMBOL vmlinux 0xdee81379 put_page +EXPORT_SYMBOL vmlinux 0xdf0da3cc acpi_get_devices +EXPORT_SYMBOL vmlinux 0xdf60cc27 __print_symbol +EXPORT_SYMBOL vmlinux 0xdf7ed4f3 filemap_fdatawrite_range +EXPORT_SYMBOL vmlinux 0xdf8c695a __ndelay +EXPORT_SYMBOL vmlinux 0xdf929370 fs_overflowgid +EXPORT_SYMBOL vmlinux 0xdff6866a eisa_bus_type +EXPORT_SYMBOL vmlinux 0xe06b4431 wait_for_key_construction +EXPORT_SYMBOL vmlinux 0xe075d6eb iter_div_u64_rem +EXPORT_SYMBOL vmlinux 0xe0868620 pci_target_state +EXPORT_SYMBOL vmlinux 0xe094ef39 sg_next +EXPORT_SYMBOL vmlinux 0xe09ba100 netdev_bonding_change +EXPORT_SYMBOL vmlinux 0xe0a5a01d blk_queue_update_dma_alignment +EXPORT_SYMBOL vmlinux 0xe0aa7a86 cfb_fillrect +EXPORT_SYMBOL vmlinux 0xe0ac8bd2 acpi_bus_generate_netlink_event +EXPORT_SYMBOL vmlinux 0xe0affdd3 call_usermodehelper_setup +EXPORT_SYMBOL vmlinux 0xe0b13336 argv_free +EXPORT_SYMBOL vmlinux 0xe11de8e4 security_d_instantiate +EXPORT_SYMBOL vmlinux 0xe12e2d57 tcp_disconnect +EXPORT_SYMBOL vmlinux 0xe13cd8a7 dmi_name_in_vendors +EXPORT_SYMBOL vmlinux 0xe15aeee2 downgrade_write +EXPORT_SYMBOL vmlinux 0xe16826eb per_cpu__softnet_data +EXPORT_SYMBOL vmlinux 0xe16ebfb5 neigh_lookup +EXPORT_SYMBOL vmlinux 0xe16f8a79 per_cpu__irq_regs +EXPORT_SYMBOL vmlinux 0xe1761617 security_inet_conn_request +EXPORT_SYMBOL vmlinux 0xe19608bb tcp_md5_hash_header +EXPORT_SYMBOL vmlinux 0xe1af38ef iov_iter_copy_from_user_atomic +EXPORT_SYMBOL vmlinux 0xe1c9f15a pcix_set_mmrbc +EXPORT_SYMBOL vmlinux 0xe20cde91 tcf_hash_check +EXPORT_SYMBOL vmlinux 0xe24d3a97 jiffies_64 +EXPORT_SYMBOL vmlinux 0xe259247b lock_may_write +EXPORT_SYMBOL vmlinux 0xe27e3934 devm_request_irq +EXPORT_SYMBOL vmlinux 0xe2ab0642 km_query +EXPORT_SYMBOL vmlinux 0xe2b46882 ll_rw_block +EXPORT_SYMBOL vmlinux 0xe2b8be6b tcp_enter_memory_pressure +EXPORT_SYMBOL vmlinux 0xe2c33dfa sock_create +EXPORT_SYMBOL vmlinux 0xe2c7ac24 acpi_unlock_ac_dir +EXPORT_SYMBOL vmlinux 0xe2d5255a strcmp +EXPORT_SYMBOL vmlinux 0xe2e5f7b6 __pagevec_lru_add +EXPORT_SYMBOL vmlinux 0xe2fae716 kmemdup +EXPORT_SYMBOL vmlinux 0xe326aabf dentry_unhash +EXPORT_SYMBOL vmlinux 0xe328560d seq_open +EXPORT_SYMBOL vmlinux 0xe351633f genl_register_family +EXPORT_SYMBOL vmlinux 0xe3694a1f blk_queue_init_tags +EXPORT_SYMBOL vmlinux 0xe3776703 security_sb_clone_mnt_opts +EXPORT_SYMBOL vmlinux 0xe3b9246a __neigh_event_send +EXPORT_SYMBOL vmlinux 0xe3d8a8cf alloc_netdev_mq +EXPORT_SYMBOL vmlinux 0xe3fbe148 acpi_install_table_handler +EXPORT_SYMBOL vmlinux 0xe42e295f pci_clear_mwi +EXPORT_SYMBOL vmlinux 0xe43617f7 acpi_gbl_FADT +EXPORT_SYMBOL vmlinux 0xe456bd3a complete +EXPORT_SYMBOL vmlinux 0xe467c12d skb_trim +EXPORT_SYMBOL vmlinux 0xe484e35f ioread32 +EXPORT_SYMBOL vmlinux 0xe4870354 _read_trylock +EXPORT_SYMBOL vmlinux 0xe499aa3d kobject_put +EXPORT_SYMBOL vmlinux 0xe49a9db8 gnet_stats_start_copy +EXPORT_SYMBOL vmlinux 0xe4af62f6 simple_rename +EXPORT_SYMBOL vmlinux 0xe4c1df3e _read_lock_bh +EXPORT_SYMBOL vmlinux 0xe5122890 flow_cache_genid +EXPORT_SYMBOL vmlinux 0xe523ad75 synchronize_irq +EXPORT_SYMBOL vmlinux 0xe52aad30 sock_get_timestamp +EXPORT_SYMBOL vmlinux 0xe5530874 nobh_write_begin +EXPORT_SYMBOL vmlinux 0xe55704ab nf_hooks +EXPORT_SYMBOL vmlinux 0xe57878a1 in6_pton +EXPORT_SYMBOL vmlinux 0xe5867808 dlci_ioctl_set +EXPORT_SYMBOL vmlinux 0xe5c78a99 do_blank_screen +EXPORT_SYMBOL vmlinux 0xe5cf8536 netdev_features_change +EXPORT_SYMBOL vmlinux 0xe6000a83 proto_unregister +EXPORT_SYMBOL vmlinux 0xe6551dca deactivate_super +EXPORT_SYMBOL vmlinux 0xe673315f dev_add_pack +EXPORT_SYMBOL vmlinux 0xe68f09e6 kobject_set_name +EXPORT_SYMBOL vmlinux 0xe6adfb96 kmem_cache_destroy +EXPORT_SYMBOL vmlinux 0xe6d2efd4 vfs_getattr +EXPORT_SYMBOL vmlinux 0xe6ebc016 key_create_or_update +EXPORT_SYMBOL vmlinux 0xe6fb8994 sk_stream_wait_memory +EXPORT_SYMBOL vmlinux 0xe6fbe430 can_do_mlock +EXPORT_SYMBOL vmlinux 0xe7075590 ethtool_op_set_flags +EXPORT_SYMBOL vmlinux 0xe716baed acpi_unregister_ioapic +EXPORT_SYMBOL vmlinux 0xe71d665e bio_integrity_set_tag +EXPORT_SYMBOL vmlinux 0xe74b6c8c inet_select_addr +EXPORT_SYMBOL vmlinux 0xe75b07b2 xfrm_unregister_mode +EXPORT_SYMBOL vmlinux 0xe78806ee inet_getname +EXPORT_SYMBOL vmlinux 0xe7997ce7 ip_queue_xmit +EXPORT_SYMBOL vmlinux 0xe7a200c0 key_negate_and_link +EXPORT_SYMBOL vmlinux 0xe7d4daac seq_list_next +EXPORT_SYMBOL vmlinux 0xe80ce219 sysctl_tcp_dma_copybreak +EXPORT_SYMBOL vmlinux 0xe85ecbf2 pci_try_set_mwi +EXPORT_SYMBOL vmlinux 0xe87d691b skb_queue_tail +EXPORT_SYMBOL vmlinux 0xe88064f0 neigh_create +EXPORT_SYMBOL vmlinux 0xe8be84a5 ida_destroy +EXPORT_SYMBOL vmlinux 0xe8cd902e hweight16 +EXPORT_SYMBOL vmlinux 0xe8eb8b5d test_set_page_writeback +EXPORT_SYMBOL vmlinux 0xe910b532 del_timer_sync +EXPORT_SYMBOL vmlinux 0xe914d009 ioremap_nocache +EXPORT_SYMBOL vmlinux 0xe914e41e strcpy +EXPORT_SYMBOL vmlinux 0xe918896f skb_put +EXPORT_SYMBOL vmlinux 0xe91cc2ef dst_alloc +EXPORT_SYMBOL vmlinux 0xe9456a5a sysctl_xfrm_aevent_rseqth +EXPORT_SYMBOL vmlinux 0xe977165a sk_stream_wait_connect +EXPORT_SYMBOL vmlinux 0xe997667b wrmsr_on_cpu +EXPORT_SYMBOL vmlinux 0xe9d68480 blk_start_queueing +EXPORT_SYMBOL vmlinux 0xe9dea4ba generic_file_readonly_mmap +EXPORT_SYMBOL vmlinux 0xea10655a __bitmap_intersects +EXPORT_SYMBOL vmlinux 0xea2d33a2 radix_tree_gang_lookup_slot +EXPORT_SYMBOL vmlinux 0xea31088c bio_integrity_alloc_bioset +EXPORT_SYMBOL vmlinux 0xea5e5581 ida_remove +EXPORT_SYMBOL vmlinux 0xea6fcdaa genl_unregister_family +EXPORT_SYMBOL vmlinux 0xea7987f1 key_update +EXPORT_SYMBOL vmlinux 0xea858cb5 radix_tree_gang_lookup_tag +EXPORT_SYMBOL vmlinux 0xea9bd44b dev_set_mac_address +EXPORT_SYMBOL vmlinux 0xeae3dfd6 __const_udelay +EXPORT_SYMBOL vmlinux 0xeb1c84a8 proc_symlink +EXPORT_SYMBOL vmlinux 0xeb1fabf6 interruptible_sleep_on +EXPORT_SYMBOL vmlinux 0xeb395084 param_get_invbool +EXPORT_SYMBOL vmlinux 0xeb87ca6d vfs_permission +EXPORT_SYMBOL vmlinux 0xeb8f1116 kernel_connect +EXPORT_SYMBOL vmlinux 0xeb8f54b3 strstrip +EXPORT_SYMBOL vmlinux 0xebd273a6 strict_strtoull +EXPORT_SYMBOL vmlinux 0xec2a526e pnp_register_card_driver +EXPORT_SYMBOL vmlinux 0xec860422 bioset_free +EXPORT_SYMBOL vmlinux 0xeca6a5c7 __sk_mem_schedule +EXPORT_SYMBOL vmlinux 0xecb08b43 follow_down +EXPORT_SYMBOL vmlinux 0xecde1418 _spin_lock_irq +EXPORT_SYMBOL vmlinux 0xece55040 __find_get_block +EXPORT_SYMBOL vmlinux 0xed1ac506 dma_pool_create +EXPORT_SYMBOL vmlinux 0xed46bd9f xfrm_policy_bysel_ctx +EXPORT_SYMBOL vmlinux 0xed633abc pv_irq_ops +EXPORT_SYMBOL vmlinux 0xed67b41a lock_super +EXPORT_SYMBOL vmlinux 0xed68a099 pci_bus_write_config_byte +EXPORT_SYMBOL vmlinux 0xed7348e0 mod_zone_page_state +EXPORT_SYMBOL vmlinux 0xeda8caba mnt_pin +EXPORT_SYMBOL vmlinux 0xedbaee5e nla_strcmp +EXPORT_SYMBOL vmlinux 0xedc03953 iounmap +EXPORT_SYMBOL vmlinux 0xedc47f12 bdi_set_max_ratio +EXPORT_SYMBOL vmlinux 0xedd14538 param_get_uint +EXPORT_SYMBOL vmlinux 0xedda7993 gnet_stats_copy_rate_est +EXPORT_SYMBOL vmlinux 0xedea96bb proc_dointvec +EXPORT_SYMBOL vmlinux 0xee20bf5f blk_start_queue +EXPORT_SYMBOL vmlinux 0xee2d0fc7 _local_bh_enable +EXPORT_SYMBOL vmlinux 0xee704314 iunique +EXPORT_SYMBOL vmlinux 0xee7a46c5 wireless_spy_update +EXPORT_SYMBOL vmlinux 0xee7eb9e1 pnp_platform_devices +EXPORT_SYMBOL vmlinux 0xee976db5 d_alloc_root +EXPORT_SYMBOL vmlinux 0xeea9dbaf bitmap_bitremap +EXPORT_SYMBOL vmlinux 0xeeb1717c param_array_get +EXPORT_SYMBOL vmlinux 0xeeb93243 audit_log_start +EXPORT_SYMBOL vmlinux 0xeebe2f8f ip4_datagram_connect +EXPORT_SYMBOL vmlinux 0xef070bd7 iw_handler_get_spy +EXPORT_SYMBOL vmlinux 0xef0ae092 redraw_screen +EXPORT_SYMBOL vmlinux 0xef1e876b __ip_select_ident +EXPORT_SYMBOL vmlinux 0xef3bd862 mca_find_unused_adapter +EXPORT_SYMBOL vmlinux 0xef6e250c filemap_fdatawrite +EXPORT_SYMBOL vmlinux 0xef79ac56 __release_region +EXPORT_SYMBOL vmlinux 0xef96c44d generic_block_bmap +EXPORT_SYMBOL vmlinux 0xef9aedfc boot_option_idle_override +EXPORT_SYMBOL vmlinux 0xefaf7fe5 bio_map_user +EXPORT_SYMBOL vmlinux 0xefdd70ce security_secid_to_secctx +EXPORT_SYMBOL vmlinux 0xefe099c3 acpi_get_event_status +EXPORT_SYMBOL vmlinux 0xefe4c160 inode_sub_bytes +EXPORT_SYMBOL vmlinux 0xefec0787 prepare_binprm +EXPORT_SYMBOL vmlinux 0xf0009fee put_pages_list +EXPORT_SYMBOL vmlinux 0xf01cf05a generic_write_end +EXPORT_SYMBOL vmlinux 0xf0653234 thermal_zone_device_unregister +EXPORT_SYMBOL vmlinux 0xf065f629 ioread16be +EXPORT_SYMBOL vmlinux 0xf0a49910 dcache_readdir +EXPORT_SYMBOL vmlinux 0xf0b57c68 param_set_long +EXPORT_SYMBOL vmlinux 0xf0c6546d __xfrm_lookup +EXPORT_SYMBOL vmlinux 0xf0ca3ba0 unregister_snap_client +EXPORT_SYMBOL vmlinux 0xf0d8daed tty_port_free_xmit_buf +EXPORT_SYMBOL vmlinux 0xf0f1246c kvasprintf +EXPORT_SYMBOL vmlinux 0xf10143d7 pci_scan_single_device +EXPORT_SYMBOL vmlinux 0xf103de0b mark_info_dirty +EXPORT_SYMBOL vmlinux 0xf1066643 pcie_port_service_unregister +EXPORT_SYMBOL vmlinux 0xf10de535 ioread8 +EXPORT_SYMBOL vmlinux 0xf11543ff find_first_zero_bit +EXPORT_SYMBOL vmlinux 0xf13adb2e ethtool_op_get_sg +EXPORT_SYMBOL vmlinux 0xf1521cf9 vfs_get_dqinfo +EXPORT_SYMBOL vmlinux 0xf15c9448 skb_queue_purge +EXPORT_SYMBOL vmlinux 0xf162fe2d sysctl_xfrm_aevent_etime +EXPORT_SYMBOL vmlinux 0xf1716504 tcp_parse_options +EXPORT_SYMBOL vmlinux 0xf174ed48 acquire_console_sem +EXPORT_SYMBOL vmlinux 0xf176b67a proc_create_data +EXPORT_SYMBOL vmlinux 0xf190ccc1 iov_iter_copy_from_user +EXPORT_SYMBOL vmlinux 0xf195c682 fb_invert_cmaps +EXPORT_SYMBOL vmlinux 0xf19cd789 dev_unicast_add +EXPORT_SYMBOL vmlinux 0xf1b7eedd kernel_listen +EXPORT_SYMBOL vmlinux 0xf1d62ffd __kill_fasync +EXPORT_SYMBOL vmlinux 0xf1deabf2 div64_u64 +EXPORT_SYMBOL vmlinux 0xf1e98c74 avenrun +EXPORT_SYMBOL vmlinux 0xf20dabd8 free_irq +EXPORT_SYMBOL vmlinux 0xf2165ba1 fb_is_primary_device +EXPORT_SYMBOL vmlinux 0xf2325646 blk_rq_append_bio +EXPORT_SYMBOL vmlinux 0xf246de13 tcf_hash_destroy +EXPORT_SYMBOL vmlinux 0xf25f7716 skb_dequeue_tail +EXPORT_SYMBOL vmlinux 0xf283fa6b tcp_v4_md5_do_del +EXPORT_SYMBOL vmlinux 0xf2997713 tty_termios_hw_change +EXPORT_SYMBOL vmlinux 0xf2a6d2bf xfrm_policy_count +EXPORT_SYMBOL vmlinux 0xf2afa595 param_get_charp +EXPORT_SYMBOL vmlinux 0xf2d74fe4 unregister_binfmt +EXPORT_SYMBOL vmlinux 0xf2e74040 mca_set_adapter_name +EXPORT_SYMBOL vmlinux 0xf307102d console_stop +EXPORT_SYMBOL vmlinux 0xf313da4e sha_transform +EXPORT_SYMBOL vmlinux 0xf3232968 inet_dev_addr_type +EXPORT_SYMBOL vmlinux 0xf3341268 __clear_user +EXPORT_SYMBOL vmlinux 0xf338d4c3 netlink_unregister_notifier +EXPORT_SYMBOL vmlinux 0xf346231f seq_list_start_head +EXPORT_SYMBOL vmlinux 0xf3503650 generic_make_request +EXPORT_SYMBOL vmlinux 0xf377725b dquot_alloc_space +EXPORT_SYMBOL vmlinux 0xf39bf4d9 put_cmsg +EXPORT_SYMBOL vmlinux 0xf3a2324e aio_put_req +EXPORT_SYMBOL vmlinux 0xf3bf0bce __bitmap_complement +EXPORT_SYMBOL vmlinux 0xf3e10161 tty_vhangup +EXPORT_SYMBOL vmlinux 0xf40e17cc set_pages_nx +EXPORT_SYMBOL vmlinux 0xf41d22d0 bio_integrity_add_page +EXPORT_SYMBOL vmlinux 0xf41e0044 destroy_EII_client +EXPORT_SYMBOL vmlinux 0xf441ac43 ioread8_rep +EXPORT_SYMBOL vmlinux 0xf44a6de1 d_instantiate_unique +EXPORT_SYMBOL vmlinux 0xf47d47e0 acpi_enable_gpe +EXPORT_SYMBOL vmlinux 0xf48a2c4c MCA_bus +EXPORT_SYMBOL vmlinux 0xf49bc67a atm_pcr_goal +EXPORT_SYMBOL vmlinux 0xf4a5c213 avail_to_resrv_perfctr_nmi_bit +EXPORT_SYMBOL vmlinux 0xf4e1b718 set_trace_device +EXPORT_SYMBOL vmlinux 0xf4f14de6 rtnl_trylock +EXPORT_SYMBOL vmlinux 0xf4f52f93 dqstats +EXPORT_SYMBOL vmlinux 0xf502d273 acpi_get_current_resources +EXPORT_SYMBOL vmlinux 0xf51ae235 touch_nmi_watchdog +EXPORT_SYMBOL vmlinux 0xf533a9ef blk_requeue_request +EXPORT_SYMBOL vmlinux 0xf53d4c26 qdisc_class_hash_destroy +EXPORT_SYMBOL vmlinux 0xf559dcfd proc_doulongvec_ms_jiffies_minmax +EXPORT_SYMBOL vmlinux 0xf58ca4fc get_sb_single +EXPORT_SYMBOL vmlinux 0xf593db28 cfb_imageblit +EXPORT_SYMBOL vmlinux 0xf5a0193b netif_rx +EXPORT_SYMBOL vmlinux 0xf5c05914 generic_segment_checks +EXPORT_SYMBOL vmlinux 0xf5ce9811 tcp_memory_allocated +EXPORT_SYMBOL vmlinux 0xf5d21953 blk_unplug +EXPORT_SYMBOL vmlinux 0xf5d2600f key_instantiate_and_link +EXPORT_SYMBOL vmlinux 0xf5d9369b kobject_get +EXPORT_SYMBOL vmlinux 0xf5e558ad skb_gso_segment +EXPORT_SYMBOL vmlinux 0xf6198daa page_symlink +EXPORT_SYMBOL vmlinux 0xf61c9610 create_empty_buffers +EXPORT_SYMBOL vmlinux 0xf61e3209 vfs_readdir +EXPORT_SYMBOL vmlinux 0xf63a7305 d_delete +EXPORT_SYMBOL vmlinux 0xf664a7fe tcp_v4_destroy_sock +EXPORT_SYMBOL vmlinux 0xf66b9c0b unregister_con_driver +EXPORT_SYMBOL vmlinux 0xf6a38c1f blk_rq_map_sg +EXPORT_SYMBOL vmlinux 0xf6bb4729 color_table +EXPORT_SYMBOL vmlinux 0xf6cf7da3 dma_set_mask +EXPORT_SYMBOL vmlinux 0xf6d43649 neigh_for_each +EXPORT_SYMBOL vmlinux 0xf6ebc03b net_ratelimit +EXPORT_SYMBOL vmlinux 0xf720e312 tcp_v4_md5_do_add +EXPORT_SYMBOL vmlinux 0xf738217e pci_set_mwi +EXPORT_SYMBOL vmlinux 0xf7612499 vfs_create +EXPORT_SYMBOL vmlinux 0xf7623914 radix_tree_tag_clear +EXPORT_SYMBOL vmlinux 0xf7742a69 blk_cleanup_queue +EXPORT_SYMBOL vmlinux 0xf78741a6 blk_rq_count_integrity_sg +EXPORT_SYMBOL vmlinux 0xf78d04ab netlink_register_notifier +EXPORT_SYMBOL vmlinux 0xf798c89f netlink_unicast +EXPORT_SYMBOL vmlinux 0xf7ac4c6e qdisc_calculate_pkt_len +EXPORT_SYMBOL vmlinux 0xf7e4d4c1 backlight_device_register +EXPORT_SYMBOL vmlinux 0xf7ee849b mca_device_transform_irq +EXPORT_SYMBOL vmlinux 0xf7f0e79f sock_kfree_s +EXPORT_SYMBOL vmlinux 0xf809df53 __dst_free +EXPORT_SYMBOL vmlinux 0xf82abc1d isa_dma_bridge_buggy +EXPORT_SYMBOL vmlinux 0xf82e3d47 acpi_initialize_objects +EXPORT_SYMBOL vmlinux 0xf82f1109 utf8_wctomb +EXPORT_SYMBOL vmlinux 0xf82f44d9 clear_bdi_congested +EXPORT_SYMBOL vmlinux 0xf8408c6e force_sig +EXPORT_SYMBOL vmlinux 0xf84cded5 kernel_accept +EXPORT_SYMBOL vmlinux 0xf86dfee5 acpi_check_mem_region +EXPORT_SYMBOL vmlinux 0xf8814f73 rb_last +EXPORT_SYMBOL vmlinux 0xf887c80f wait_on_page_bit +EXPORT_SYMBOL vmlinux 0xf88e0ee2 acpi_get_table_header +EXPORT_SYMBOL vmlinux 0xf890fe7f pm_idle +EXPORT_SYMBOL vmlinux 0xf8970c24 remove_arg_zero +EXPORT_SYMBOL vmlinux 0xf8aa47ae mutex_lock_killable +EXPORT_SYMBOL vmlinux 0xf8b30e93 mempool_create +EXPORT_SYMBOL vmlinux 0xf9168ba2 dev_unicast_sync +EXPORT_SYMBOL vmlinux 0xf987afe6 pci_iomap +EXPORT_SYMBOL vmlinux 0xf98c65d1 __devm_release_region +EXPORT_SYMBOL vmlinux 0xf9a482f9 msleep +EXPORT_SYMBOL vmlinux 0xfa0564fc __wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfa173eec tty_flip_buffer_push +EXPORT_SYMBOL vmlinux 0xfa262ae1 dev_mc_sync +EXPORT_SYMBOL vmlinux 0xfa390844 tcp_sendpage +EXPORT_SYMBOL vmlinux 0xfa7a1925 xfrm_policy_destroy +EXPORT_SYMBOL vmlinux 0xfaf98462 bitrev32 +EXPORT_SYMBOL vmlinux 0xfb0443fb acpi_get_parent +EXPORT_SYMBOL vmlinux 0xfb0cf2e9 touch_all_softlockup_watchdogs +EXPORT_SYMBOL vmlinux 0xfb67cbcd tcf_action_dump_1 +EXPORT_SYMBOL vmlinux 0xfb6af58d recalc_sigpending +EXPORT_SYMBOL vmlinux 0xfba0c2e0 llc_sap_list_lock +EXPORT_SYMBOL vmlinux 0xfba1e4ff task_pid_nr_ns +EXPORT_SYMBOL vmlinux 0xfbb3db56 llc_build_and_send_ui_pkt +EXPORT_SYMBOL vmlinux 0xfbf83d44 cfb_copyarea +EXPORT_SYMBOL vmlinux 0xfbf92453 param_get_bool +EXPORT_SYMBOL vmlinux 0xfbfbfff6 __blk_run_queue +EXPORT_SYMBOL vmlinux 0xfbff67ac udp_sendmsg +EXPORT_SYMBOL vmlinux 0xfc02b7ad sysctl_tcp_wmem +EXPORT_SYMBOL vmlinux 0xfc04c061 remap_vmalloc_range +EXPORT_SYMBOL vmlinux 0xfc1c4a68 input_inject_event +EXPORT_SYMBOL vmlinux 0xfc229332 tty_register_device +EXPORT_SYMBOL vmlinux 0xfc309c3e cancel_delayed_work_sync +EXPORT_SYMBOL vmlinux 0xfc39e32f ioport_unmap +EXPORT_SYMBOL vmlinux 0xfc4982c0 generic_getxattr +EXPORT_SYMBOL vmlinux 0xfc7983da set_anon_super +EXPORT_SYMBOL vmlinux 0xfc7f5f91 dma_async_client_register +EXPORT_SYMBOL vmlinux 0xfca7da9f pci_set_master +EXPORT_SYMBOL vmlinux 0xfcaa04a0 out_of_line_wait_on_bit_lock +EXPORT_SYMBOL vmlinux 0xfcbba8ef posix_lock_file +EXPORT_SYMBOL vmlinux 0xfcc0ad4a dev_remove_pack +EXPORT_SYMBOL vmlinux 0xfccec9b5 nobh_truncate_page +EXPORT_SYMBOL vmlinux 0xfcda63a3 node_states +EXPORT_SYMBOL vmlinux 0xfcdd8cf6 param_get_ushort +EXPORT_SYMBOL vmlinux 0xfcdf32ab unregister_sysctl_table +EXPORT_SYMBOL vmlinux 0xfce483ab pcim_iomap_regions_request_all +EXPORT_SYMBOL vmlinux 0xfcec0987 enable_irq +EXPORT_SYMBOL vmlinux 0xfcec937d find_get_page +EXPORT_SYMBOL vmlinux 0xfcfa03ff fb_videomode_to_modelist +EXPORT_SYMBOL vmlinux 0xfd37e36d pskb_copy +EXPORT_SYMBOL vmlinux 0xfd98879a rb_next +EXPORT_SYMBOL vmlinux 0xfdb9b629 ioread32be +EXPORT_SYMBOL vmlinux 0xfdc672d7 sock_create_kern +EXPORT_SYMBOL vmlinux 0xfde2145a boot_tvec_bases +EXPORT_SYMBOL vmlinux 0xfdf04255 ip_cmsg_recv +EXPORT_SYMBOL vmlinux 0xfdf33ba8 thermal_zone_bind_cooling_device +EXPORT_SYMBOL vmlinux 0xfe054973 dma_mark_declared_memory_occupied +EXPORT_SYMBOL vmlinux 0xfe1c8d96 find_get_pages_tag +EXPORT_SYMBOL vmlinux 0xfe205da2 vfs_dq_transfer +EXPORT_SYMBOL vmlinux 0xfe5d4bb2 sys_tz +EXPORT_SYMBOL vmlinux 0xfe7166e2 end_buffer_read_sync +EXPORT_SYMBOL vmlinux 0xfe7509ec ps2_cmd_aborted +EXPORT_SYMBOL vmlinux 0xfe769456 unregister_netdevice_notifier +EXPORT_SYMBOL vmlinux 0xfe785bee arp_broken_ops +EXPORT_SYMBOL vmlinux 0xfe7c4287 nr_cpu_ids +EXPORT_SYMBOL vmlinux 0xfec3c2f2 bcd2bin +EXPORT_SYMBOL vmlinux 0xfeda7962 put_filp +EXPORT_SYMBOL vmlinux 0xfedd35fc console_suspend_enabled +EXPORT_SYMBOL vmlinux 0xfef3a80c ___pskb_trim +EXPORT_SYMBOL vmlinux 0xff1e86e5 ip_route_output_key +EXPORT_SYMBOL vmlinux 0xff1e9dd8 seq_list_start +EXPORT_SYMBOL vmlinux 0xff684549 file_remove_suid +EXPORT_SYMBOL vmlinux 0xff6878cf fb_default_cmap +EXPORT_SYMBOL vmlinux 0xff708fd3 mempool_destroy +EXPORT_SYMBOL vmlinux 0xff766634 generic_delete_inode +EXPORT_SYMBOL vmlinux 0xff9ca065 fb_edid_to_monspecs +EXPORT_SYMBOL vmlinux 0xffa119df console_start +EXPORT_SYMBOL vmlinux 0xffa1d8b3 block_sync_page +EXPORT_SYMBOL vmlinux 0xffa5aad8 pcim_pin_device +EXPORT_SYMBOL vmlinux 0xffaa9b9c xfrm_state_register_afinfo +EXPORT_SYMBOL vmlinux 0xffadc143 nf_unregister_sockopt +EXPORT_SYMBOL vmlinux 0xffafdc5c _read_unlock_irq +EXPORT_SYMBOL vmlinux 0xffbe7670 __nla_put_nohdr +EXPORT_SYMBOL vmlinux 0xffd5a395 default_wake_function +EXPORT_SYMBOL vmlinux 0xffdac21c xfrm_bundle_ok +EXPORT_SYMBOL vmlinux 0xffdb82bc sg_free_table +EXPORT_SYMBOL vmlinux 0xffde1f01 nf_log_register +EXPORT_SYMBOL vmlinux 0xfff4042c register_netdevice +EXPORT_SYMBOL vmlinux 0xfff7393e dev_getbyhwaddr +EXPORT_SYMBOL_GPL arch/x86/kernel/cpu/cpufreq/speedstep-lib 0x16836e04 speedstep_detect_processor +EXPORT_SYMBOL_GPL arch/x86/kernel/cpu/cpufreq/speedstep-lib 0x4cdb4bd0 speedstep_get_processor_frequency +EXPORT_SYMBOL_GPL arch/x86/kernel/cpu/cpufreq/speedstep-lib 0xd494ee54 speedstep_get_freqs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x00aaf935 kvm_disable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x04d3cdf5 kvm_timer_intr_post +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x08eba255 kvm_mmu_page_fault +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x094ac8f4 kvm_get_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x101736f1 kvm_lmsw +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1135ec65 gfn_to_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x12d1b23b kvm_release_pfn_clean +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1430d658 kvm_task_switch +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1479315a emulator_write_emulated +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1e4580bb kvm_release_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x1f7022f5 kvm_lapic_set_tpr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x2322e039 kvm_set_pfn_accessed +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x254b3211 emulate_instruction +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x27046576 kvm_exit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x299099df kvm_resched +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x317f9e6b kvm_enable_efer_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x366daa5d kvm_cpu_has_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x398e03f9 kvm_put_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x3f1563ae gfn_to_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4233c0a2 kvm_vcpu_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4482455b kvm_release_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4605e4f8 kvm_vcpu_cache +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x4a7cbe69 is_error_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x5018164f kvm_emulate_halt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x5332e8c1 kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x538306bb kvm_set_cr0 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x55570a17 kvm_set_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x599086dd kvm_handle_fault_on_reboot +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x59e00511 kvm_create_lapic +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x5acf700b kvm_lapic_find_highest_irr +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x5f9e38da kvm_inject_nmi +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x625c35bc kvm_lapic_get_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6510f16d kvm_vcpu_uninit +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x684c42a0 kvm_lapic_enabled +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6a6c765c kvm_cpu_get_interrupt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6ba30eda kvm_inject_pending_timer_irqs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6c71c8dd fx_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6cb11a03 kvm_report_emulation_failure +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x6d7b7107 kvm_queue_exception +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x70a481c2 __kvm_set_memory_region +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7ba19817 kvm_emulate_hypercall +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7ca86031 kvm_read_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x7d44a78c kvm_put_guest_fpu +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8631df14 kvm_lapic_get_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8ce4f3ab kvm_enable_tdp +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8e362604 is_error_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8e7f9b47 segment_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x8ef8162c kvm_mmu_reset_context +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9021ec85 kvm_mmu_load +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9062ec78 gfn_to_pfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x934a4c7f kvm_set_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x93a390f0 kvm_emulate_cpuid +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9540df74 kvm_get_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x98e53e77 kvm_read_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9a30c531 kvm_get_msr_common +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0x9f601580 kvm_clear_guest +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa1a5a4e0 kvm_set_cr3 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa361bc65 kvm_set_pfn_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xa67480dc emulator_read_std +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xab2a9895 kvm_is_visible_gfn +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xae13b6dd load_pdptrs +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xae500587 kvm_emulate_pio_string +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xb1030230 kvm_set_cr8 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd23ee99 kvm_queue_exception_e +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd377dc9 kvm_mmu_set_nonpresent_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xbd94103b kvm_mmu_set_base_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xcf7b87de kvm_set_cr4 +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd0a4e817 kvm_get_cs_db_l_bits +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd0b2727a kvm_mmu_set_mask_ptes +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd296def9 kvm_is_error_hva +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xd2c9b9e3 kvm_set_page_dirty +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdc2bbe4f kvm_write_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdeb783a4 kvm_mmu_unprotect_page_virt +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xdf5cce56 kvm_emulate_pio +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xe0b865a0 kvm_load_guest_fpu +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xe6af6d15 kvm_clear_guest_page +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xeb514f49 kvm_get_apic_base +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf2c2d861 kvm_init +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf2eadcd9 kvm_lapic_reset +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf3cec2cb kvm_get_kvm +EXPORT_SYMBOL_GPL arch/x86/kvm/kvm 0xf532cb94 kvm_release_page_clean +EXPORT_SYMBOL_GPL crypto/aead 0x023baae3 crypto_aead_type +EXPORT_SYMBOL_GPL crypto/aead 0x11bf9e98 crypto_nivaead_type +EXPORT_SYMBOL_GPL crypto/aead 0x2c4d623a crypto_aead_setauthsize +EXPORT_SYMBOL_GPL crypto/aead 0x5d042f54 aead_geniv_alloc +EXPORT_SYMBOL_GPL crypto/aead 0x67404ea2 aead_geniv_exit +EXPORT_SYMBOL_GPL crypto/aead 0x7cb45ae3 crypto_alloc_aead +EXPORT_SYMBOL_GPL crypto/aead 0x9a1cca6b aead_geniv_init +EXPORT_SYMBOL_GPL crypto/aead 0xc0c7b088 aead_geniv_free +EXPORT_SYMBOL_GPL crypto/aead 0xf388fb4d crypto_grab_aead +EXPORT_SYMBOL_GPL crypto/aes_generic 0x1381bf2d crypto_ft_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x22894d94 crypto_il_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5f943003 crypto_it_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x5fe743de crypto_aes_expand_key +EXPORT_SYMBOL_GPL crypto/aes_generic 0x6e9cc2ba crypto_fl_tab +EXPORT_SYMBOL_GPL crypto/aes_generic 0x959d1946 crypto_aes_set_key +EXPORT_SYMBOL_GPL crypto/async_tx/async_memcpy 0x9f01ee19 async_memcpy +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x0b4b3710 __async_tx_find_channel +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x30f16f9d async_tx_quiesce +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x54b2c743 async_tx_run_dependencies +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x6b4a6db2 async_tx_issue_pending_all +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x765672d3 async_trigger_callback +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xbb34cf4d async_tx_submit +EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xd5829b28 dma_wait_for_async_tx +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0xa551567c async_xor_zero_sum +EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0xccb06663 async_xor +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x02639f27 skcipher_geniv_init +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x0a560223 skcipher_geniv_alloc +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x2a3551ab crypto_givcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x4d5dad7b skcipher_geniv_free +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x4f632d56 crypto_alloc_ablkcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x5a0bf9e5 crypto_grab_skcipher +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x6abac3a8 blkcipher_walk_virt +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x6e3a47e9 crypto_blkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x755f0612 blkcipher_walk_phys +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0x961f8aeb crypto_ablkcipher_type +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xcb8b80f7 skcipher_geniv_exit +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xe70de0f7 blkcipher_walk_virt_block +EXPORT_SYMBOL_GPL crypto/crypto_blkcipher 0xf243d331 blkcipher_walk_done +EXPORT_SYMBOL_GPL crypto/des_generic 0xcfd9a2c0 des_ekey +EXPORT_SYMBOL_GPL crypto/twofish_common 0xcb3f501c twofish_setkey +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x100c48a2 unregister_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x2611fbee register_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0x318920b1 register_dock_notifier +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xbd506a46 unregister_hotplug_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/dock 0xcc6ab305 is_dock_device +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x0ad5c33f acpi_smbus_register_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x158c2ad0 acpi_smbus_unregister_callback +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0x526b867a acpi_smbus_read +EXPORT_SYMBOL_GPL drivers/acpi/sbshc 0xb3d5e527 acpi_smbus_write +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x3ecf6cfc wmi_install_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0x64ebe677 wmi_query_block +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xa9b7afd8 wmi_set_block +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xb5a6ebe2 wmi_remove_notify_handler +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xc5e3dddf wmi_get_event_data +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xc9d4d6d1 wmi_has_guid +EXPORT_SYMBOL_GPL drivers/acpi/wmi 0xe2426710 wmi_evaluate_method +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0067df75 ata_tf_from_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x00ebcb5d ata_id_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0x016e0a14 dev_attr_em_message +EXPORT_SYMBOL_GPL drivers/ata/libata 0x01b700d9 ata_host_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0x02b342b9 ata_sff_host_intr +EXPORT_SYMBOL_GPL drivers/ata/libata 0x02e443db ata_pci_sff_prepare_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0x02f256b6 ata_pci_remove_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0x035ed3c3 ata_sff_qc_fill_rtf +EXPORT_SYMBOL_GPL drivers/ata/libata 0x03e3686c ata_timing_cycle2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x04ca80f3 ata_bmdma_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0531dcb8 ata_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0571cd02 ata_base_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x069abf2c ata_noop_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0737a254 ata_eh_freeze_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0779055d ata_timing_compute +EXPORT_SYMBOL_GPL drivers/ata/libata 0x07b160a0 ata_sff_dumb_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0a0326bf sata_link_debounce +EXPORT_SYMBOL_GPL drivers/ata/libata 0x0cb625ef ata_eh_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0x13a4aae6 ata_do_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0x155618c5 ata_sff_data_xfer +EXPORT_SYMBOL_GPL drivers/ata/libata 0x155b22c5 sata_scr_write +EXPORT_SYMBOL_GPL drivers/ata/libata 0x163dcdd6 ata_port_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0x171f2c43 ata_sff_irq_on +EXPORT_SYMBOL_GPL drivers/ata/libata 0x176601c8 ata_std_qc_defer +EXPORT_SYMBOL_GPL drivers/ata/libata 0x1e321fe0 ata_bus_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x25a1d0ef ata_host_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x26f14fd1 ata_sas_port_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2cd9bb67 ata_do_set_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2d787b7c sata_async_notification +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2de11d76 ata_sff_hsm_move +EXPORT_SYMBOL_GPL drivers/ata/libata 0x2edb7833 ata_sff_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3196d90b ata_host_detach +EXPORT_SYMBOL_GPL drivers/ata/libata 0x320d9206 ata_sff_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x35ba5fad ata_sg_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x38bf8d3c ata_host_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3abd985d ata_pci_device_do_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0x3e9b23ea ata_pci_sff_init_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0x40af0dec ata_xfer_mode2mask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x413a8e5c ata_std_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x43f56e82 ata_xfer_mode2shift +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4662cc45 ata_cable_ignore +EXPORT_SYMBOL_GPL drivers/ata/libata 0x48fbc0b9 ata_sas_port_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4a22b6ba sata_link_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4b95ed40 ata_sff_postreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4c0af5a3 ata_bmdma_mode_filter +EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fdc945d sata_deb_timing_normal +EXPORT_SYMBOL_GPL drivers/ata/libata 0x50b691dd ata_host_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0x523b553f ata_sff_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0x53185d9b ata_port_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0x54d3646e sata_pmp_qc_defer_cmd_switch +EXPORT_SYMBOL_GPL drivers/ata/libata 0x551fc11a ata_acpi_gtm_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x59cc3250 ata_host_activate +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5b41aa59 ata_sas_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x5ff8577a dev_attr_sw_activity +EXPORT_SYMBOL_GPL drivers/ata/libata 0x612499c5 sata_sff_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6211b39a sata_scr_valid +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6665ca5f ata_dev_pair +EXPORT_SYMBOL_GPL drivers/ata/libata 0x690e3113 ata_sff_exec_command +EXPORT_SYMBOL_GPL drivers/ata/libata 0x69e9a2cb ata_scsi_slave_config +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6a92befb ata_sff_qc_prep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6c216ca3 ata_qc_complete_multiple +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6dd0e097 ata_std_bios_param +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6e501ef7 ata_cable_unknown +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6e9cd991 ata_sff_dev_select +EXPORT_SYMBOL_GPL drivers/ata/libata 0x6fece6c7 ata_port_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7039e62e ata_eh_analyze_ncq_error +EXPORT_SYMBOL_GPL drivers/ata/libata 0x707ff1bb ata_xfer_mask2mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0x724fc9c1 ata_eh_qc_retry +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7282e922 ata_pci_bmdma_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7303cdf6 ata_host_init +EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a48b4a ata_sff_std_ports +EXPORT_SYMBOL_GPL drivers/ata/libata 0x73e35480 ata_dummy_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0x743a165e ata_pack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0x747fbb49 pci_test_config_bits +EXPORT_SYMBOL_GPL drivers/ata/libata 0x748bcad1 ata_pci_sff_activate_host +EXPORT_SYMBOL_GPL drivers/ata/libata 0x75b0d96d ata_pci_sff_init_one +EXPORT_SYMBOL_GPL drivers/ata/libata 0x77223ee6 ata_dummy_port_info +EXPORT_SYMBOL_GPL drivers/ata/libata 0x782439b0 sata_scr_write_flush +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7bcc7971 ata_port_probe +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7f0c365a ata_sff_busy_sleep +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7f5df9b8 sata_pmp_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0x7fc380fc ata_sff_thaw +EXPORT_SYMBOL_GPL drivers/ata/libata 0x83ec838e ata_host_alloc_pinfo +EXPORT_SYMBOL_GPL drivers/ata/libata 0x83fb6313 ata_port_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0x84a11bbf ata_eh_thaw_port +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8579343c ata_bmdma_setup +EXPORT_SYMBOL_GPL drivers/ata/libata 0x872e5f2c ata_sff_post_internal_cmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8aaf3f90 ata_bmdma_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b752ac1 ata_tf_to_fis +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8c80c955 ata_std_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8dd6b3c2 ata_acpi_stm +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8e3496ca ata_pio_need_iordy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x8f2d7b58 ata_sas_port_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94a68723 ata_scsi_slave_destroy +EXPORT_SYMBOL_GPL drivers/ata/libata 0x94dc62d2 ata_scsi_ioctl +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9874b099 ata_sff_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0x98c20dc2 ata_sff_softreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9c11e639 ata_do_dev_read_id +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9cf25a44 ata_link_offline +EXPORT_SYMBOL_GPL drivers/ata/libata 0x9ec54f63 ata_sff_prereset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa1df28be dev_attr_link_power_management_policy +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa214925a ata_sff_tf_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa3ed133c ata_link_online +EXPORT_SYMBOL_GPL drivers/ata/libata 0xa77b5969 ata_sff_dev_classify +EXPORT_SYMBOL_GPL drivers/ata/libata 0xaa6b185d ata_wait_after_reset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xaa945cc9 sata_pmp_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0xab4fe08b ata_pci_device_suspend +EXPORT_SYMBOL_GPL drivers/ata/libata 0xae8ae569 ata_acpi_cbl_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xaf1dc1a8 ata_cable_80wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb1a454e7 ata_scsi_simulate +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb2ff4101 ata_qc_complete +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb557cd2f sata_std_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb58b0e98 ata_sff_check_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6aeb661 ata_id_c_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbb8d3644 ata_acpi_gtm +EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe1887e4 ata_unpack_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc16409af ata_sff_irq_clear +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc428068d sata_deb_timing_long +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc484167c ata_bmdma_status +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc48b7ccf ata_mode_string +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc518fc50 ata_host_alloc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc673e23e ata_scsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc69a2204 ata_dev_disable +EXPORT_SYMBOL_GPL drivers/ata/libata 0xc97d5a0e ata_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcccfb2fa sata_deb_timing_hotplug +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcf16f45f ata_pci_device_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0xcfae64fc ata_cable_sata +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd083b67f ata_bmdma_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd0a19d9b sata_link_hardreset +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd1f02f75 ata_cable_40wire +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd55807a3 ata_sas_slave_configure +EXPORT_SYMBOL_GPL drivers/ata/libata 0xd84cd7f4 ata_timing_find_mode +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdde653d1 ata_sff_wait_ready +EXPORT_SYMBOL_GPL drivers/ata/libata 0xde0577c1 ata_link_abort +EXPORT_SYMBOL_GPL drivers/ata/libata 0xde507234 ata_pci_device_do_resume +EXPORT_SYMBOL_GPL drivers/ata/libata 0xdf3022b2 ata_sff_interrupt +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe10c25c9 ata_sas_port_start +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe2b52d81 ata_sff_data_xfer_noirq +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe49ff3b0 ata_wait_register +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe802651c ata_scsi_queuecmd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xe9686e4c ata_port_schedule_eh +EXPORT_SYMBOL_GPL drivers/ata/libata 0xea418e0f atapi_cmd_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xec1f20c9 ata_std_error_handler +EXPORT_SYMBOL_GPL drivers/ata/libata 0xee222070 ata_port_pbar_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xeeed700b sata_set_spd +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf0a93027 dev_attr_em_message_type +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf1feb3ff sata_scr_read +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf3d5cc13 ata_timing_merge +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf42f752f ata_sff_dma_pause +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf466afee ata_ehi_clear_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf4f74a1c ata_sas_port_stop +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf6620f0c ata_sff_freeze +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf664388a ata_sff_tf_load +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf6b8820c ata_sff_qc_issue +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf722c8b9 ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8808cd4 __ata_ehi_push_desc +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8e93c29 ata_pci_bmdma_clear_simplex +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8f3a0fb ata_ratelimit +EXPORT_SYMBOL_GPL drivers/ata/libata 0xf9ca3160 ata_id_xfermask +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfbf4dec3 sata_port_ops +EXPORT_SYMBOL_GPL drivers/ata/libata 0xfe74ae6c ata_sff_port_start +EXPORT_SYMBOL_GPL drivers/ata/pata_sis 0xd8c9d90c sis_info133_for_sata +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x02ff9464 cfag12864b_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x0ecb2e5d cfag12864b_disable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x305dc3c6 cfag12864b_isenabled +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x3389f926 cfag12864b_enable +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x9522a342 cfag12864b_getrate +EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0xc48e9d95 cfag12864b_buffer +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x14102f23 ks0108_displaystate +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x48a70518 ks0108_writedata +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x4f506333 ks0108_startline +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x6edae968 ks0108_isinited +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xbf4774db ks0108_writecontrol +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xedde6df2 ks0108_page +EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xfee8ef7b ks0108_address +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0x04e6eb0b agp_remove_bridge +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xa77417ca agp_add_bridge +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xd6feefa5 agp_num_entries +EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xe089cfcc agp_memory_reserved +EXPORT_SYMBOL_GPL drivers/char/scx200_gpio 0xd6165961 scx200_gpio_ops +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x005f545b tpm_show_active +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x036887ae tpm_gen_interrupt +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x175d2865 tpm_show_temp_deactivated +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x43ed0993 tpm_continue_selftest +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x448820c5 tpm_write +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x4e21ca7d tpm_get_timeouts +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x6b4f5410 tpm_store_cancel +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x6c0717a6 tpm_read +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x74377d9e tpm_show_owned +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7a60bd7b tpm_show_caps_1_2 +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7bbc2ce2 tpm_show_pubek +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x8f2b47cc tpm_register_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x8f7b5cdf tpm_show_enabled +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9445dd34 tpm_release +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xa43ed909 tpm_open +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xb279dc70 tpm_show_caps +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xbcf4f745 tpm_show_pcrs +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xcd5e1b04 tpm_pm_resume +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xd5651eea tpm_pm_suspend +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xde648e8a tpm_remove_hardware +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xf5fd1d2b tpm_calc_ordinal_duration +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0x1aa61010 tpm_bios_log_teardown +EXPORT_SYMBOL_GPL drivers/char/tpm/tpm_bios 0x8a65b943 tpm_bios_log_setup +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x07146b6f cpufreq_frequency_table_verify +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x2f47d8c7 cpufreq_frequency_get_table +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x5dcfc85f cpufreq_frequency_table_target +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x5e9329f1 cpufreq_freq_attr_scaling_available_freqs +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x706b3a33 cpufreq_frequency_table_get_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0x7ae1ae8e cpufreq_frequency_table_put_attr +EXPORT_SYMBOL_GPL drivers/cpufreq/freq_table 0xa26344c7 cpufreq_frequency_table_cpuinfo +EXPORT_SYMBOL_GPL drivers/dca/dca 0x00791e87 dca3_get_tag +EXPORT_SYMBOL_GPL drivers/dca/dca 0x2e471f01 dca_register_notify +EXPORT_SYMBOL_GPL drivers/dca/dca 0x31a2c8df dca_get_tag +EXPORT_SYMBOL_GPL drivers/dca/dca 0x36d754a2 dca_remove_requester +EXPORT_SYMBOL_GPL drivers/dca/dca 0x6394e99b register_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0x6c67dcfd unregister_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0x6fc76e0c alloc_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0x8006c614 dca_unregister_notify +EXPORT_SYMBOL_GPL drivers/dca/dca 0xdc9dab6d free_dca_provider +EXPORT_SYMBOL_GPL drivers/dca/dca 0xf341a766 dca_add_requester +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x003d8225 edac_device_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x031cadea edac_device_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0a476ee4 edac_pci_handle_npe +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x15c16b5a edac_pci_del_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x19d4d875 edac_pci_free_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1bfb0fdc edac_pci_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1dee1b89 edac_pci_create_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x349bff01 edac_device_add_device +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x3778b3db edac_pci_release_generic_ctl +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x5213cb77 edac_mc_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x5fe82f4c edac_mc_add_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x60650a28 edac_mc_handle_ue_no_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x62126c99 edac_mc_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x6564d9c1 edac_device_handle_ce +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x8143167c edac_mc_find_csrow_by_page +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x86e32984 edac_pci_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x8836f328 edac_mc_alloc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x9e7c4bea edac_mc_del_mc +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xaaf04dca edac_device_alloc_ctl_info +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xbaf39062 edac_mc_free +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xc1b8c672 edac_pci_handle_pe +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcfaa706d edac_pci_reset_delay_period +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xd7698d15 edac_device_handle_ue +EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xf022202a edac_mc_handle_ce_no_info +EXPORT_SYMBOL_GPL drivers/hid/hid 0x038e430d hidinput_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0x087e8927 hid_free_device +EXPORT_SYMBOL_GPL drivers/hid/hid 0x1c37debb hidraw_disconnect +EXPORT_SYMBOL_GPL drivers/hid/hid 0x1f440819 hid_output_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x3f3a6733 hidraw_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0x5002d05e hid_input_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x5b40c80e hidinput_connect +EXPORT_SYMBOL_GPL drivers/hid/hid 0x8b989fe8 hid_parse_report +EXPORT_SYMBOL_GPL drivers/hid/hid 0x8d8a873d hidraw_report_event +EXPORT_SYMBOL_GPL drivers/hid/hid 0xc1657ce7 hidinput_find_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xc6f465d8 hid_set_field +EXPORT_SYMBOL_GPL drivers/hid/hid 0xe729eba9 hidinput_disconnect +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x01fd453e usbhid_lookup_quirk +EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x5a8da370 hiddev_hid_event +EXPORT_SYMBOL_GPL drivers/i2c/busses/i2c-nforce2 0x7b43304f nforce2_smbus +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x00359c60 i2c_bus_type +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x11290130 i2c_unregister_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x599d0066 i2c_add_numbered_adapter +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xbb16be1d i2c_new_dummy +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xdaf28888 i2c_new_device +EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xe8086994 i2c_new_probed_device +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0x3f0322df hpsb_config_rom_ip1394_remove +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xbb1aee38 hpsb_config_rom_ip1394_add +EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xec8d18cf hpsb_disable_irm +EXPORT_SYMBOL_GPL drivers/input/ff-memless 0xfbfe4291 input_ff_create_memless +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x1c5a170a wm97xx_set_suspend_mode +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x28e1dc55 wm9712_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x2ee17665 wm97xx_read_aux_adc +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x340801eb wm97xx_unregister_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x355fc10f wm9705_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x35d1a9dc wm97xx_set_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x3987e017 wm97xx_get_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x408dcf08 wm97xx_reg_read +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x79c35cc9 wm97xx_register_mach_ops +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xbada499d wm97xx_config_gpio +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xe44bdccb wm9713_codec +EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xfe021d18 wm97xx_reg_write +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x065f1004 gigaset_fill_inbuf +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x0efd54ee gigaset_initdriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x315f994f gigaset_m10x_input +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x454aa44f gigaset_debuglevel +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x4e792275 gigaset_dbg_buffer +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x5a943224 gigaset_add_event +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x60ecf2ae gigaset_skb_sent +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x67a86a98 gigaset_m10x_send_skb +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x69a423f3 gigaset_blockdriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x76b81632 gigaset_start +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x7b594005 gigaset_if_receive +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x8187c477 gigaset_initcs +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x938377ea gigaset_handle_modem_response +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0x93df0bd7 gigaset_freedriver +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xbd8cd2e8 gigaset_shutdown +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xeb3744a6 gigaset_freecs +EXPORT_SYMBOL_GPL drivers/isdn/gigaset/gigaset 0xf985aede gigaset_stop +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x101a6020 led_classdev_suspend +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x435e4e53 led_classdev_register +EXPORT_SYMBOL_GPL drivers/leds/led-class 0x6fefed35 led_classdev_unregister +EXPORT_SYMBOL_GPL drivers/leds/led-class 0xbec5e11f led_classdev_resume +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x3c4e1a5e dm_device_name +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x67d428c5 dm_set_device_limits +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x6a10d8eb dm_noflush_suspending +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x8072860d dm_disk +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0x8f39e6be dm_path_uevent +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xcb596335 dm_put +EXPORT_SYMBOL_GPL drivers/md/dm-mod 0xfab745fe dm_send_uevents +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xd65c97b9 dm_register_path_selector +EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xe13e7796 dm_unregister_path_selector +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x761995c1 md_allow_write +EXPORT_SYMBOL_GPL drivers/md/md-mod 0x81692262 md_do_sync +EXPORT_SYMBOL_GPL drivers/md/md-mod 0xe1660723 sync_page_io +EXPORT_SYMBOL_GPL drivers/md/md-mod 0xf184d874 md_new_event +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x04662e0f ir_codes_fusionhdtv_mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x07e92917 ir_codes_avermedia_a16d +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x083661f9 ir_codes_avertv_303 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x088631b9 ir_codes_behold +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x1cb148f5 ir_extract_bits +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2456e513 ir_decode_pulsedistance +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2a4852cc ir_codes_dntv_live_dvb_t +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x2af1a608 ir_codes_proteus_2309 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x3811daea ir_codes_manli +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x43c89ef4 ir_decode_biphase +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x45b08f68 ir_codes_pinnacle_grey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4740e7a3 ir_codes_empty +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x4ea698a2 ir_codes_purpletv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x55338dda ir_codes_pixelview_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x589cad50 ir_codes_apac_viewcomp +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x5db13554 ir_codes_encore_enltv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6606596a ir_rc5_timer_keyup +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6adc476d ir_codes_powercolor_real_angel +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6aefdbea ir_codes_npgtech +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6b87c69d ir_codes_iodata_bctv7e +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6d6511e7 ir_dump_samples +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x6e2a1870 ir_codes_adstech_dvb_t_pci +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x7277973d ir_codes_pctv_sedna +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x75e89cc3 ir_codes_flydvb +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x772a30a2 ir_codes_nebula +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x85d37490 ir_codes_dntv_live_dvbt_pro +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x89cc1189 ir_codes_winfast +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x902a3cd2 ir_codes_hauppauge_new +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x933d0bb3 ir_codes_msi_tvanywhere +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x9451e232 ir_codes_behold_columbus +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0x96470cab ir_codes_cinergy +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb1f4eb35 ir_codes_avermedia_dvbt +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xb6cd4666 ir_codes_eztv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xbdce6594 ir_codes_tt_1500 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc1fea0c1 ir_codes_pv951 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc42bd037 ir_codes_budget_ci_old +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc6c5a7a1 ir_codes_em_terratec +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xc9e27e17 ir_input_nokey +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd1e0258a ir_codes_flyvideo +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd55e6891 ir_codes_gotview7135 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xd9c7f010 ir_codes_rc5_tv +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdaa041ad ir_codes_cinergy_1400 +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xdfcf23df ir_codes_norwood +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xe24d802e ir_input_init +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xee2f5e0e ir_codes_pinnacle_pctv_hd +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf07533a1 ir_codes_videomate_tv_pvr +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf0fc9374 ir_codes_avermedia +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf2b421aa ir_codes_genius_tvgo_a11mce +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xf4f7a4d6 ir_rc5_timer_end +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfa177653 ir_codes_pixelview +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfb981300 ir_codes_pinnacle_color +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfc537d66 ir_input_keydown +EXPORT_SYMBOL_GPL drivers/media/common/ir-common 0xfc54a5cd ir_codes_asus_pc39 +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x20922162 saa7146_setgpio +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x4627b60c saa7146_unregister_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x54d46810 saa7146_pgtable_alloc +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x5d25397b saa7146_vfree_destroy_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x5f1677b8 saa7146_pgtable_build_single +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x9ddb3ecb saa7146_i2c_adapter_prepare +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0x9ec6c1d8 saa7146_wait_for_debi_done +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xa0139ee4 saa7146_register_extension +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xa0ebb96a saa7146_pgtable_free +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xc98faf20 saa7146_devices_lock +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xcf683cf2 saa7146_devices +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xe3cd9b5c saa7146_debug +EXPORT_SYMBOL_GPL drivers/media/common/saa7146 0xf9cc66df saa7146_vmalloc_build_pgtable +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x23d93c35 saa7146_register_device +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x24ae0a50 saa7146_unregister_device +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x5b701086 saa7146_start_preview +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x7dac033a saa7146_set_hps_source_and_sync +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0x89bb12bc saa7146_vv_release +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xdabc18c0 saa7146_vv_init +EXPORT_SYMBOL_GPL drivers/media/common/saa7146_vv 0xe97caff1 saa7146_stop_preview +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mt20xx 0xbe63e4ea microtune_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/mxl5007t 0x499ec078 mxl5007t_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda18271 0x2d571c54 tda18271_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda827x 0x1eecd2a6 tda827x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0x247f2911 tda829x_probe +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda8290 0xc2fa7ff1 tda829x_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tda9887 0xa601b49f tda9887_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xc1b0404e tea5761_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5761 0xf8aebcfa tea5761_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0x07419dac tea5767_autodetection +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tea5767 0xb28a30bc tea5767_attach +EXPORT_SYMBOL_GPL drivers/media/common/tuners/tuner-simple 0xaa89fbfd simple_tuner_attach +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x448d9af7 ttpci_budget_irq10_handler +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x5f95bf63 ttpci_budget_debiwrite +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x7948c222 budget_debug +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0x83462c43 ttpci_budget_init +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xb90c98bb ttpci_budget_init_hooks +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xbefd811a ttpci_budget_set_video_port +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xd8d5f85a ttpci_budget_deinit +EXPORT_SYMBOL_GPL drivers/media/dvb/ttpci/budget-core 0xee5c4b13 ttpci_budget_debiread +EXPORT_SYMBOL_GPL drivers/media/video/compat_ioctl32 0xe5e13a42 v4l_compat_ioctl32 +EXPORT_SYMBOL_GPL drivers/media/video/cx88/cx88xx 0xfc43a808 cx88_setup_xc3028 +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x060abe36 em28xx_uninit_isoc +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0x61f1d249 em28xx_audio_analog_set +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xa016ff90 em28xx_init_isoc +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xb14e322f em28xx_set_mode +EXPORT_SYMBOL_GPL drivers/media/video/em28xx/em28xx 0xd22c24eb em28xx_tuner_callback +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0x0d44122a saa7134_ts_qops +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0x22b587bd saa7134_g_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xa9723961 saa7134_s_ctrl_internal +EXPORT_SYMBOL_GPL drivers/media/video/saa7134/saa7134 0xfc998597 saa7134_queryctrl +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0x376b000f v4l2_int_device_register +EXPORT_SYMBOL_GPL drivers/media/video/v4l2-int-device 0xd701a9fe v4l2_int_device_unregister +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x05186ced videobuf_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x0f341823 videobuf_reqbufs +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x30b84533 videobuf_poll_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x323d59d7 videobuf_queue_core_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x49bc803e videobuf_read_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x4cc7959e videobuf_mmap_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x585ca17c videobuf_stop +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x5efd0fed videobuf_read_one +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x6adbdca0 videobuf_read_stream +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x6cdb751e videobuf_next_field +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x6e91d9f5 videobuf_streamon +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x741efc81 videobuf_qbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x75e9fc52 videobuf_queue_is_busy +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x86953b26 videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x90b47fad videobuf_streamoff +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x929052fa videobuf_mmap_mapper +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0x984c06ff videobuf_waiton +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xa34d3405 videobuf_read_start +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xb4dc301c videobuf_querybuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xd2420d21 __videobuf_mmap_setup +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xd381737b videobuf_queue_cancel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xde5886e9 videobuf_cgmbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xe2f9d2d8 videobuf_queue_to_vmalloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xe7ac66c6 videobuf_iolock +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-core 0xfa4a0542 videobuf_dqbuf +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0x56223e60 videobuf_queue_dma_contig_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0xd8ff4de8 videobuf_to_dma_contig +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-contig 0xf8df60d8 videobuf_dma_contig_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x079d4a21 videobuf_dma_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x08d90b99 videobuf_dma_init_user +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x2c7fc0de videobuf_sg_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x31378532 videobuf_to_dma +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x370e2b3f videobuf_sg_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x74053b07 videobuf_queue_sg_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x866d6a90 videobuf_dma_init_kernel +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x8b6b302a videobuf_dma_sync +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0x8d3002d4 videobuf_dma_init_overlay +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xa825c75b videobuf_sg_alloc +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xacd61fe6 videobuf_dma_unmap +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xb4468885 videobuf_dma_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xcee722e0 videobuf_dma_map +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-dma-sg 0xe8a24336 videobuf_vmalloc_to_sg +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x38feb431 videobuf_vmalloc_free +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0x4e065d10 videobuf_queue_vmalloc_init +EXPORT_SYMBOL_GPL drivers/media/video/videobuf-vmalloc 0xeb56a55d videobuf_to_vmalloc +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x2cff7e5f sm501_unit_power +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x65bb2868 sm501_set_clock +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xaec0c5d6 sm501_modify_reg +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xb0f774ee sm501_misc_control +EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xd8907529 sm501_find_clock +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x2df115d4 eeprom_93cx6_multiread +EXPORT_SYMBOL_GPL drivers/misc/eeprom_93cx6 0x63d14d2f eeprom_93cx6_read +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x2a842dfa enclosure_register +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x339fc797 enclosure_unregister +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x42801409 enclosure_remove_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x573cdf34 enclosure_find +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x7733a083 enclosure_for_each_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xc10c71e9 enclosure_add_device +EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xdc2306b9 enclosure_component_register +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x0e172e19 sdio_disable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x14be2226 sdio_align_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x15cf221f sdio_memcpy_toio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x197e6ea3 sdio_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x1fa9f8e6 sdio_release_irq +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x1ff4307e sdio_readsb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x31e7a9fb sdio_register_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x4894c3ab sdio_set_block_size +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x7463533b sdio_unregister_driver +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x7fca4d3a sdio_f0_writeb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0x9745184f sdio_claim_irq +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xa2bb4b15 sdio_writel +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xad41a5d0 sdio_memcpy_fromio +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xb6175474 sdio_f0_readb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xbb86c455 sdio_readb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xbf7929e6 sdio_claim_host +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xcae9645f sdio_readw +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xcb92390e sdio_writew +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xcbc41969 sdio_readl +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xe1867618 sdio_enable_func +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xebff6f76 sdio_writesb +EXPORT_SYMBOL_GPL drivers/mmc/core/mmc_core 0xf7af8620 sdio_release_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x53848696 sdhci_alloc_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0x8c7d2f33 sdhci_suspend_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xb41f5ca3 sdhci_resume_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xc821ce86 sdhci_free_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xca540c85 sdhci_add_host +EXPORT_SYMBOL_GPL drivers/mmc/host/sdhci 0xdf9f6143 sdhci_remove_host +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x40536717 cfi_cmdset_0001 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0xb21edc4a cfi_cmdset_0200 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0xd9171e9b cfi_cmdset_0003 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0002 0x95b5225d cfi_cmdset_0002 +EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0020 0xe866d0a3 cfi_cmdset_0020 +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2000 0x243418e2 DoC2k_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001 0xd07625eb DoCMil_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001plus 0x30feac3b DoCMilPlus_init +EXPORT_SYMBOL_GPL drivers/mtd/devices/docecc 0x45937659 doc_decode_ecc +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x02bd7e6f mtd_erase_callback +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x0def7161 unregister_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x2b8e5826 del_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x35e2c5bf parse_mtd_partitions +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x50f167c0 deregister_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x70342574 mtd_table +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x73db554f put_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xa664607d add_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xa9862e98 get_mtd_device +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xb44d3f55 default_mtd_writev +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xb78035db get_sb_mtd +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xbfed2d3d register_mtd_parser +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xe173a222 register_mtd_user +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xe740ac67 kill_mtd_super +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xee6df196 get_mtd_device_nm +EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xeff64be1 mtd_table_mutex +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x00c8c04c del_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x394748b1 deregister_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x531ca25d add_mtd_blktrans_dev +EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x87e7e6b9 register_mtd_blktrans +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x0531447e nand_scan +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x97bc4064 nand_scan_tail +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xcc618a51 nand_wait_ready +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xd2dc4994 nand_release +EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xe2b2e302 nand_scan_ident +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0xc485d2fd onenand_release +EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0xf9df74b2 onenand_scan +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x0d2bd79e ubi_open_volume_nm +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x1570e62d ubi_leb_write +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x42801d20 ubi_sync +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x5c473053 ubi_leb_read +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x6f4d3255 ubi_close_volume +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x825c3e68 ubi_leb_unmap +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x86da88ad ubi_is_mapped +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x88d88ee7 ubi_get_volume_info +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xa9bfba93 ubi_leb_map +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbc505df4 ubi_get_device_info +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xea803e58 ubi_leb_erase +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xeb2b07cc ubi_leb_change +EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xf9a4bbb8 ubi_open_volume +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0211544b mlx4_pd_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x111520d6 mlx4_srq_arm +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1bc6a85b mlx4_multicast_detach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1c28c667 mlx4_cq_resize +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1d4738f3 mlx4_INIT_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1d928135 mlx4_fmr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1e285659 mlx4_cq_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x214e9ed1 mlx4_buf_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2e0ee29b mlx4_qp_remove +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3782c83b mlx4_srq_query +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x39a7e148 mlx4_register_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3acb4f1b mlx4_mr_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3dcf93af mlx4_alloc_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x449fb32f mlx4_mtt_init +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x44f25dcd mlx4_fmr_unmap +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4a6d90f7 mlx4_qp_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4bc69c51 mlx4_pd_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x591b8451 mlx4_cq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5d0bba6a mlx4_CLOSE_PORT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x62eaf538 mlx4_alloc_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x676d19f2 mlx4_db_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6e8a50d0 mlx4_mtt_cleanup +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x701195fd mlx4_SYNC_TPT +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x70c0650d mlx4_free_cmd_mailbox +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x72c3e9ec mlx4_buf_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7d3721e5 mlx4_multicast_attach +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x825631eb mlx4_unregister_interface +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x825d0510 mlx4_qp_to_ready +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9109a5e6 mlx4_fmr_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x98c54b3c mlx4_db_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9b613b18 mlx4_qp_modify +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9bfea6b0 mlx4_write_mtt +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xa7bc169b mlx4_map_phys_fmr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xa9b3787e mlx4_fmr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb0302bbc mlx4_uar_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb6a5731e mlx4_qp_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbada340c mlx4_cq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc1555382 mlx4_mr_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc20864ff mlx4_srq_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xcd9694ea mlx4_mr_enable +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xd1d2cb8e mlx4_srq_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xda49a34d __mlx4_cmd +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdf59c2c9 mlx4_mtt_addr +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe5962301 mlx4_buf_alloc +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xedd74102 mlx4_free_hwq_res +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf611661c mlx4_uar_free +EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xfdd6e8ba mlx4_qp_query +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0x442d5a13 usbnet_cdc_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0xc26ff162 usbnet_generic_cdc_bind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x1ee95c1a rndis_tx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x732d60e7 rndis_unbind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x75485e17 rndis_command +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xccabe9e4 generic_rndis_bind +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xd65d9b59 rndis_rx_fixup +EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xfb058d7b rndis_status +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x036a6e62 usbnet_nway_reset +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x1695ec9a usbnet_get_link +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x2efa2e94 usbnet_resume +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x387aa806 usbnet_get_settings +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x578afbee usbnet_set_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x5b2e11a4 usbnet_skb_return +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x702d1825 usbnet_defer_kevent +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x8cbeee89 usbnet_get_msglevel +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x8f0039ca usbnet_unlink_rx_urbs +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x8fce8724 usbnet_get_drvinfo +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xa7e1aed6 usbnet_probe +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xc099d2b5 usbnet_get_endpoints +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xc1d8a1b8 usbnet_set_settings +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xd1ad398c usbnet_disconnect +EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xd6235da4 usbnet_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x00f7a65b __lbs_cmd +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x063514fe lbs_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x10bfcc2f lbs_queue_event +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x15e921d8 lbs_remove_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x3eff70da lbs_process_rxed_packet +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0x9775128d lbs_host_to_card_done +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xa65296dd lbs_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xaa011f9e lbs_start_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xb6479e0c lbs_notify_command_response +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xc311670f lbs_send_tx_feedback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xdaaef5f2 lbs_cmd_copyback +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xe82f7ecd lbs_stop_card +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xf3dac548 lbs_host_sleep_cfg +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xf64277de lbs_debug +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xfdcfd032 lbs_cmd_802_11_rate_adapt_rateset +EXPORT_SYMBOL_GPL drivers/net/wireless/libertas/libertas 0xff9856b0 lbs_add_card +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x0c03ff46 p54_parse_eeprom +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x5d880142 p54_parse_firmware +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x61a11e87 p54_free_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0x7b43b6bf p54_init_common +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xaa748adb p54_fill_eeprom_readback +EXPORT_SYMBOL_GPL drivers/net/wireless/p54/p54common 0xba4a5ca0 p54_rx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x13d622d6 rt2x00mac_get_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x1954322b rt2x00mac_start +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x2862641f rt2x00mac_add_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x48d3b139 rt2x00mac_config_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x4dcbdc2b rt2x00queue_get_entry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x5fee4e6a rt2x00mac_configure_filter +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x6f19cecd rt2x00mac_stop +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x7219c5e6 rt2x00lib_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x8b0e0181 rt2x00mac_get_tx_stats +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x916332b2 rt2x00lib_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x979cd55d rt2x00mac_bss_info_changed +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0x9e02487a rt2x00lib_beacondone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xa9299769 rt2x00mac_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xb03ae017 rt2x00mac_config +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xb1e77639 rt2x00lib_txdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xbb142dc6 rt2x00lib_probe_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xcc22656a rt2x00mac_remove_interface +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xd5f621e2 rt2x00lib_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xdccef497 rt2x00queue_map_txskb +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xe63bb7cb rt2x00mac_conf_tx +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xea0d15c4 rt2x00queue_get_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00lib 0xebfca1e2 rt2x00lib_remove_dev +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x09680e2d rt2x00pci_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x141a6c4b rt2x00pci_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x5e59ae79 rt2x00pci_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x6138736a rt2x00pci_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x90f9f9be rt2x00pci_rxdone +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x96f525c4 rt2x00pci_remove +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0x993cb069 rt2x00pci_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00pci 0xd85c847a rt2x00pci_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x40027189 rt2x00usb_resume +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x4d0f92b3 rt2x00usb_suspend +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x53d2d304 rt2x00usb_vendor_req_buff_lock +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x58873424 rt2x00usb_vendor_request_large_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x60618e9d rt2x00usb_disable_radio +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x692536dd rt2x00usb_init_rxentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x81da99e2 rt2x00usb_probe +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0x978a64ec rt2x00usb_kick_tx_queue +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xa27d0d0b rt2x00usb_vendor_request_buff +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xaca4cebb rt2x00usb_init_txentry +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xb55ba25f rt2x00usb_uninitialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xcad944fe rt2x00usb_write_tx_data +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xe594b785 rt2x00usb_initialize +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xffa2b43c rt2x00usb_vendor_request +EXPORT_SYMBOL_GPL drivers/net/wireless/rt2x00/rt2x00usb 0xffba23cb rt2x00usb_disconnect +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0x249360df acpiphp_register_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/acpiphp 0xeda59392 acpiphp_unregister_attention +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x1ad3b491 acpi_root_bridge +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x3f030c1d cpci_hp_register_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x5d6d24a8 pci_hp_register +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x5ddf3372 pci_hp_deregister +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x6a8441be cpci_hp_start +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x7028e4f7 cpci_hp_unregister_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x8d9a644e cpci_hp_register_controller +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x94ef4d05 cpci_hp_stop +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xc1768d9f acpi_get_hp_params_from_firmware +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xd3e88f18 cpci_hp_unregister_bus +EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xda980548 pci_hp_change_slot_info +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x09e29d22 scsi_dh_detach +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x593a36c2 scsi_dh_handler_exist +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x5c52748b scsi_unregister_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xa07b5db8 scsi_dh_activate +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xaa38e705 scsi_dh_attach +EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xf682305e scsi_register_device_handler +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x00b3ef8b iscsi_host_add +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0233f349 iscsi_pool_init +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x15e7aec9 iscsi_conn_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x1a0346c5 iscsi_host_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x242fb536 iscsi_itt_to_ctask +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3c2be61e iscsi_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x41ba1d14 iscsi_pool_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x43283ddc iscsi_verify_itt +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x48bec90b iscsi_prep_unsolicit_data_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x493ffaaa __iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x4ead3e95 iscsi_host_remove +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x587aa244 iscsi_host_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x610a6c1c iscsi_host_set_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x6c3c64a2 __iscsi_get_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x829b3e6c iscsi_session_teardown +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x871b47b7 iscsi_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x8744f2d9 iscsi_eh_abort +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x8db87e0b iscsi_eh_host_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x9aa84a02 iscsi_conn_setup +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa311a272 iscsi_conn_bind +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa70523b5 iscsi_conn_failure +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa9153ba4 iscsi_session_recovery_timedout +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc23a6e95 iscsi_session_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc2c4d841 iscsi_conn_stop +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc416ecfb iscsi_suspend_tx +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xcc6f745a iscsi_put_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd59267cf iscsi_conn_start +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd71b0d9e iscsi_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe27a736e iscsi_conn_send_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe47acda4 iscsi_host_free +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe5819576 iscsi_conn_get_param +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe94a6728 iscsi_requeue_task +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xefcda0fb iscsi_complete_pdu +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf25a5014 iscsi_update_cmdsn +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xfb04203d iscsi_eh_device_reset +EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xfc7b4e6b iscsi_session_setup +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x0d2cc20c sas_change_queue_type +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x0fb18c33 sas_domain_attach_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x20db646c sas_slave_configure +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x26dac3a9 sas_ssp_task_response +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x32af1412 sas_change_queue_depth +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x34a7f90e sas_eh_bus_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x45fddd5e sas_unregister_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x4cec9419 sas_register_ha +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x6c84df83 sas_bios_param +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x6e73f0ef sas_ioctl +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x74854f24 sas_slave_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x8f7854b1 sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x8fd830e6 sas_phy_enable +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x99e97afb sas_domain_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xa76c7c53 sas_request_addr +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xb2af56a8 __sas_task_abort +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xb5e7226c sas_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xbdbe52fc sas_eh_device_reset_handler +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xcd6ae7f0 sas_phy_reset +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xcf53eb83 sas_target_destroy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xdfe494f0 sas_slave_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xe822fe7b sas_find_local_phy +EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xecf98822 sas_queuecommand +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x0be3f29b srp_target_alloc +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x35696480 srp_iu_put +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x68365a3a srp_transfer_data +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x8a1d6334 srp_cmd_queue +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x9acc6434 srp_iu_get +EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xe6d6ed06 srp_target_free +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x0dba1cfc scsi_flush_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x19608076 __scsi_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x1f7cce0c scsi_target_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x26c90ea4 scsi_eh_get_sense +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x35d8c94a sdev_evt_alloc +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x43c228e4 scsi_eh_ready_devs +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x4f843a36 scsi_schedule_eh +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x714ae25b sdev_evt_send +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7e275ea8 scsi_complete_async_scans +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x98ba463c sdev_evt_send_simple +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x9caede9b scsi_execute_async +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xac276b0c scsi_nl_sock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xc9771cc7 scsi_internal_device_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xcddab0bd scsi_internal_device_unblock +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd57996d3 scsi_target_block +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xe2bf56a4 scsi_mode_select +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xe3b231ad scsi_bus_type +EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xe45ee6ba scsi_queue_work +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x1347f9ed scsi_host_get_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x21f0f58f scsi_tgt_alloc_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x2838d4c6 scsi_tgt_queue_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x3e1f747e scsi_tgt_tsk_mgmt_request +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x61286a94 scsi_tgt_free_queue +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x74c5a58c scsi_tgt_cmd_to_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x9b54ef3e scsi_tgt_it_nexus_destroy +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xc632dab3 scsi_tgt_it_nexus_create +EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xebc4701a scsi_host_put_command +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x0f1c7924 iscsi_unregister_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x0f85e768 iscsi_free_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x1c263800 iscsi_create_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x3b95c8f9 iscsi_session_event +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x46facd00 iscsi_destroy_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x4d41f056 iscsi_alloc_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x594f239e iscsi_create_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x6dedb050 iscsi_create_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x71cb70d9 iscsi_conn_error +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x75a427f9 iscsi_add_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x8e325c0a iscsi_host_for_each_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x9a18ee01 iscsi_scan_finished +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x9c03d6f0 iscsi_remove_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xa8432b52 iscsi_register_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xbc6436c0 iscsi_unblock_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xc2111c62 iscsi_destroy_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xce7784e5 iscsi_block_session +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xd52c619c iscsi_destroy_conn +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xe63fe2ab iscsi_recv_pdu +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xedf5411e iscsi_lookup_endpoint +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xf9221544 iscsi_session_chkready +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0x0ef06974 spi_populate_ppr_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xa0c71dac spi_populate_sync_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xcffa2aff spi_populate_width_msg +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x1774d62f srp_release_transport +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x35f58c67 srp_rport_del +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x47b6ac16 srp_rport_add +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x64321141 srp_remove_host +EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xac992a12 srp_attach_transport +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x1570943f spi_bitbang_start +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x35f274dd spi_bitbang_stop +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x3e3ac869 spi_bitbang_cleanup +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x3f4dccce spi_bitbang_transfer +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x4910c304 spi_bitbang_setup +EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xa70c905e spi_bitbang_setup_transfer +EXPORT_SYMBOL_GPL drivers/uio/uio 0x62397d13 __uio_register_device +EXPORT_SYMBOL_GPL drivers/uio/uio 0x9fb006a3 uio_event_notify +EXPORT_SYMBOL_GPL drivers/uio/uio 0xdab3dd35 uio_unregister_device +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0x06301e1d usbatm_usb_probe +EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0xfd8c260b usbatm_usb_disconnect +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x018df175 usb_free_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0312b49d usb_bulk_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x06531c68 usb_create_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x06e2e95c usb_hcd_platform_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x162dff09 usb_register_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x19a304ba usb_disabled +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1a689c56 usb_hcd_pci_resume +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1c8b5f0f usb_unanchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1faf5ee0 usb_string +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x20b59fca usb_put_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x218fa581 usb_hcd_pci_remove +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x249d0af1 usb_unlink_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x24f618ef usb_anchor_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x277ac5df usb_ep0_reinit +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x31adab31 usb_interrupt_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3aa9d35e usb_deregister_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3b408fe4 usb_register_device_driver +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3be89d3c usb_register_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3d10bc18 usb_register_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3f477338 usb_hcd_resume_root_hub +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x42509cb8 usb_get_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x43df3f85 usb_autopm_get_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4720fb4f usb_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4822fb9b usb_remove_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4ab937cd usb_alloc_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x50e55c0d usb_altnum_to_altsetting +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x542ec0f7 usb_match_one_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x551d7a79 usb_sg_cancel +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x59643c77 usb_reset_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5fc2f0e6 usb_init_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x625c73dd usb_hcd_unlink_urb_from_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x67e2cd42 usb_hcd_link_urb_to_ep +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6dce94bf usb_bus_list_lock +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x73c4d6b9 usb_hcd_check_unlink_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7463f464 usb_get_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x760b7cac usb_buffer_map_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7a78d563 usb_clear_halt +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7e64181d usb_calc_bus_time +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x86b10394 ehci_cf_port_reset_rwsem +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x87a48ebe usb_hcd_pci_suspend +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x890bae21 usb_buffer_unmap_sg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8b492005 usb_get_current_frame_number +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8cd20623 usb_root_hub_lost_power +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8d0f082c usb_driver_set_configuration +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8dc4b1b3 usb_lock_device_for_reset +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x97fbe0ca usb_hcd_pci_probe +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x98647a3e usb_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9924c496 __usb_get_extra_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x99e2360d usb_buffer_free +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9cca0e96 usb_get_descriptor +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9cedb1cf usb_get_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa6887570 usb_kill_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa95f8405 usb_get_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xab08fed0 usb_driver_claim_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xace5c0fc usb_bus_list +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xafd88ea0 usb_sg_init +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb17bd30c usb_driver_release_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb9b9d6c3 usb_store_new_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbc3a242f usb_wait_anchor_empty_timeout +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc17515d7 usb_hcds_loaded +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xca274291 usb_ifnum_to_if +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcc71fe4e usb_match_id +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd2945969 usb_control_msg +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd46a20c3 usb_find_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd890230a usb_autopm_set_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xde557c98 usb_submit_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe091756f usb_deregister_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe3875d2a usb_kill_anchored_urbs +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe6c40a89 usb_hcd_giveback_urb +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe7b76a6d usb_add_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9587909 usb_unregister_notify +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe96aca57 usb_reset_device +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9b7b5fe usb_autopm_put_interface +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xebd041df usb_mon_register +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf1380909 usb_get_intf +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf178ede0 usb_sg_wait +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf354859f usb_deregister +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf4f8b32d usb_buffer_alloc +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf568f179 usb_hub_tt_clear_buffer +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf61ed6c0 usb_put_hcd +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfa97ad3f usb_hc_died +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfcd08ca8 usb_hcd_poll_rh_status +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfded95db usb_put_dev +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfeb3d515 usb_hcd_pci_shutdown +EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfed11ed1 usb_mon_deregister +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x27132d29 usb_ftdi_elan_edset_setup +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x5f8abf20 usb_ftdi_elan_edset_empty +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x78eba481 usb_ftdi_elan_edset_output +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x9ec9c6e0 usb_ftdi_elan_edset_single +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xa06def84 usb_ftdi_elan_edset_input +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xd2c376fb usb_ftdi_elan_edset_flush +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xfbb376e2 ftdi_elan_gone_away +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xfd46f815 usb_ftdi_elan_write_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xfe4067f3 usb_ftdi_elan_read_pcimem +EXPORT_SYMBOL_GPL drivers/usb/misc/phidget 0x5bfbf2b8 phidget_class +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x0aa54a8f usb_serial_deregister +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x1a33aecc usb_serial_probe +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x1b95a214 usb_serial_disconnect +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x3f9a6e53 ezusb_writememory +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x78dda29d usb_serial_generic_open +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x96307a70 usb_serial_generic_write_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x970ef6b9 usb_serial_generic_read_bulk_callback +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xc29adf18 ezusb_set_reset +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xce81fb27 usb_serial_port_softint +EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xf4a4f9f4 usb_serial_register +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x3edad223 usb_usual_clear_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0x89d4dbaf usb_usual_check_type +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xcd9991a9 usb_usual_set_present +EXPORT_SYMBOL_GPL drivers/usb/storage/libusual 0xde134c69 storage_usb_ids +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x10ac0ce4 ili9320_write +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x13161e9b ili9320_write_regs +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x9686ae19 ili9320_resume +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xa4f10ccb ili9320_probe_spi +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xd6b95ec2 ili9320_shutdown +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xd7d87679 ili9320_remove +EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xe861b22b ili9320_suspend +EXPORT_SYMBOL_GPL drivers/video/fb_ddc 0x4d35cf33 fb_ddc_read +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0xa4c3d542 fb_sys_write +EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0xd1733db8 fb_sys_read +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x8c36bdb0 sis_free_new +EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x98785471 sis_malloc_new +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x016e6c20 vmlfb_unregister_subsys +EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x90c018c6 vmlfb_register_subsys +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x075a1f84 unregister_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0x31090a49 unregister_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xa1b8be23 register_virtio_device +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xa7847deb register_virtio_driver +EXPORT_SYMBOL_GPL drivers/virtio/virtio 0xed3f94ed virtio_check_driver_offered_feature +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x03c4687d vring_interrupt +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0x725ff6f7 vring_transport_features +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0xa8279936 vring_new_virtqueue +EXPORT_SYMBOL_GPL drivers/virtio/virtio_ring 0xcc838a30 vring_del_virtqueue +EXPORT_SYMBOL_GPL drivers/w1/wire 0x50c66761 w1_write_8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0x7c2f2afb w1_calc_crc8 +EXPORT_SYMBOL_GPL drivers/w1/wire 0x9a5a25aa w1_write_block +EXPORT_SYMBOL_GPL drivers/w1/wire 0xa3ad80c5 w1_reset_bus +EXPORT_SYMBOL_GPL drivers/w1/wire 0xb50662cb w1_read_block +EXPORT_SYMBOL_GPL drivers/w1/wire 0xf1fc3c6b w1_reset_select_slave +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x1148ad2a dlm_posix_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0x9321df95 dlm_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xcf9f3328 dlm_release_lockspace +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdc583c08 dlm_unlock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xdf3c14de dlm_new_lockspace +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xf0d79094 dlm_posix_lock +EXPORT_SYMBOL_GPL fs/dlm/dlm 0xf2fe00cb dlm_posix_get +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0x46cd4302 exportfs_decode_fh +EXPORT_SYMBOL_GPL fs/exportfs/exportfs 0x7c3f7774 exportfs_encode_fh +EXPORT_SYMBOL_GPL fs/fat/fat 0x14bad3d6 fat_remove_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0x26053769 fat_attach +EXPORT_SYMBOL_GPL fs/fat/fat 0x34027159 fat_scan +EXPORT_SYMBOL_GPL fs/fat/fat 0x4e69827e fat_alloc_new_dir +EXPORT_SYMBOL_GPL fs/fat/fat 0x5715699e fat_add_entries +EXPORT_SYMBOL_GPL fs/fat/fat 0x582e0100 fat_build_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0x6b20cc4c fat_fs_panic +EXPORT_SYMBOL_GPL fs/fat/fat 0x8546e7ab fat_search_long +EXPORT_SYMBOL_GPL fs/fat/fat 0x96d50884 fat_detach +EXPORT_SYMBOL_GPL fs/fat/fat 0x9ee97eac fat_getattr +EXPORT_SYMBOL_GPL fs/fat/fat 0xa07bf69a fat_get_dotdot_entry +EXPORT_SYMBOL_GPL fs/fat/fat 0xb68ea16d fat_date_unix2dos +EXPORT_SYMBOL_GPL fs/fat/fat 0xb9191d24 fat_free_clusters +EXPORT_SYMBOL_GPL fs/fat/fat 0xe321191a fat_fill_super +EXPORT_SYMBOL_GPL fs/fat/fat 0xecfb84ad fat_flush_inodes +EXPORT_SYMBOL_GPL fs/fat/fat 0xed4cd84c fat_dir_empty +EXPORT_SYMBOL_GPL fs/fat/fat 0xf09052ed fat_sync_inode +EXPORT_SYMBOL_GPL fs/fat/fat 0xfbb72b92 fat_setattr +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0x461ec074 gfs2_register_lockproto +EXPORT_SYMBOL_GPL fs/gfs2/gfs2 0xc7baeb15 gfs2_unregister_lockproto +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x19806e36 nlmclnt_init +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x1a618932 nlmsvc_unlock_all_by_ip +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x55071780 nlmclnt_done +EXPORT_SYMBOL_GPL fs/lockd/lockd 0x7e72412a nlmsvc_unlock_all_by_sb +EXPORT_SYMBOL_GPL fs/lockd/lockd 0xe8d44c96 nlmclnt_proc +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x0e865502 o2nm_get_node_by_ip +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x12ab06d5 o2hb_setup_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1b89c6ee o2hb_fill_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1cb231d0 mlog_not_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1d747ce3 o2hb_check_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x36418553 o2net_send_message +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4557b938 o2hb_register_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4781f769 o2nm_get_node_by_num +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4900035b o2hb_stop_all_regions +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x687f6251 mlog_and_bits +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x9397a10b o2nm_node_put +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa82a8645 o2nm_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa87bc9e7 o2nm_configured_node_map +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa9f5379a o2net_send_message_vec +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xae808bac o2net_register_handler +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xb77df2c8 o2nm_node_get +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xbaeb4700 o2hb_check_node_heartbeating_from_callback +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xd60f2c6c o2hb_check_local_node_heartbeating +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf1a5611d o2net_unregister_handler_list +EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf78eb104 o2hb_unregister_callback +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x2f32a5b1 dlmunlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x7a1211f8 dlm_setup_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x99ddb2ec dlm_register_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x9cbe819a dlm_register_domain +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xcbc0b1f5 dlm_print_one_lock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd7ba575e dlm_errmsg +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd8fa57a6 dlm_unregister_eviction_cb +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xe714ed75 dlmlock +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xfb86b96f dlm_errname +EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xfcfe9232 dlm_unregister_domain +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0562c415 ocfs2_cluster_this_node +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0e27f909 ocfs2_dlm_lock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x21db5b88 ocfs2_cluster_disconnect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4a1f6fe9 ocfs2_cluster_connect +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4d3af7fa ocfs2_cluster_hangup +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x59602db7 ocfs2_stack_glue_register +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x5b14c343 ocfs2_stack_glue_unregister +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x81c85a68 ocfs2_dlm_lock_status +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x91fab465 ocfs2_dlm_lvb +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x963932a3 ocfs2_stack_glue_set_locking_protocol +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xa7d5c1c0 ocfs2_dlm_unlock +EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xd066711e ocfs2_dlm_dump_lksb +EXPORT_SYMBOL_GPL lib/lzo/lzo_compress 0x56b63670 lzo1x_1_compress +EXPORT_SYMBOL_GPL lib/lzo/lzo_decompress 0xf30fda27 lzo1x_decompress_safe +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x300d7e57 free_rs +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x6fbb3bd9 init_rs_non_canonical +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xabda1e2e decode_rs16 +EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xb050f329 init_rs +EXPORT_SYMBOL_GPL net/802/garp 0x52908c77 garp_register_application +EXPORT_SYMBOL_GPL net/802/garp 0x6ab54546 garp_request_join +EXPORT_SYMBOL_GPL net/802/garp 0x7c6b7588 garp_uninit_applicant +EXPORT_SYMBOL_GPL net/802/garp 0x9b2cba04 garp_request_leave +EXPORT_SYMBOL_GPL net/802/garp 0xc19fa4bc garp_unregister_application +EXPORT_SYMBOL_GPL net/802/garp 0xec4cecd7 garp_init_applicant +EXPORT_SYMBOL_GPL net/802/stp 0x69f95c89 stp_proto_unregister +EXPORT_SYMBOL_GPL net/802/stp 0xa6492a88 stp_proto_register +EXPORT_SYMBOL_GPL net/ax25/ax25 0xa686dbbe ax25_register_pid +EXPORT_SYMBOL_GPL net/ax25/ax25 0xac93ae05 ax25_bcast +EXPORT_SYMBOL_GPL net/ax25/ax25 0xaeb7451e ax25_defaddr +EXPORT_SYMBOL_GPL net/bluetooth/bluetooth 0x7c653fea bt_class +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x09c5ed3c tfrc_tx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x0a487ea5 tfrc_calc_x +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x106fe6d3 tfrc_tx_hist_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x309b941c tfrc_rx_hist_duplicate +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x41d761ae tfrc_rx_hist_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x44fa8b7e tfrc_rx_handle_loss +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x4bb9a9af tfrc_lh_interval_add +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x659e4329 tfrc_rx_hist_add_packet +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x69ec5731 tfrc_tx_hist_add +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x6c252d29 tfrc_calc_x_reverse_lookup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x902206f0 tfrc_lh_cleanup +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x92285650 tfrc_rx_hist_alloc +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0x9f07db44 tfrc_lh_update_i_mean +EXPORT_SYMBOL_GPL net/dccp/ccids/lib/dccp_tfrc_lib 0xc612a5b6 tfrc_rx_hist_purge +EXPORT_SYMBOL_GPL net/dccp/dccp 0x02f38030 dccp_feat_confirm_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0x10584572 ccid_hc_rx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0x115c60b4 dccp_insert_option +EXPORT_SYMBOL_GPL net/dccp/dccp 0x15dc68ff dccp_setsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x16b33be6 dccp_getsockopt +EXPORT_SYMBOL_GPL net/dccp/dccp 0x1d99d49a dccp_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0x25af0511 dccp_ctl_make_reset +EXPORT_SYMBOL_GPL net/dccp/dccp 0x28edfad6 dccp_check_req +EXPORT_SYMBOL_GPL net/dccp/dccp 0x2f509fba dccp_sync_mss +EXPORT_SYMBOL_GPL net/dccp/dccp 0x364803bf ccid_hc_rx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3b3c0b1b dccp_feat_clean +EXPORT_SYMBOL_GPL net/dccp/dccp 0x3f3124ae dccp_insert_option_elapsed_time +EXPORT_SYMBOL_GPL net/dccp/dccp 0x4615efab dccp_close +EXPORT_SYMBOL_GPL net/dccp/dccp 0x481dae45 dccp_shutdown +EXPORT_SYMBOL_GPL net/dccp/dccp 0x56cba50d dccp_rcv_state_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0x56ea266a dccp_state_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x5875b012 dccp_sendmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0x620b8d29 dccp_feat_clone +EXPORT_SYMBOL_GPL net/dccp/dccp 0x675c9517 dccp_recvmsg +EXPORT_SYMBOL_GPL net/dccp/dccp 0x6809ba86 dccp_parse_options +EXPORT_SYMBOL_GPL net/dccp/dccp 0x6864f329 dccp_make_response +EXPORT_SYMBOL_GPL net/dccp/dccp 0x6d7af31f dccp_destroy_sock +EXPORT_SYMBOL_GPL net/dccp/dccp 0x73e37847 ccid_register +EXPORT_SYMBOL_GPL net/dccp/dccp 0x7a1f7ce6 dccp_create_openreq_child +EXPORT_SYMBOL_GPL net/dccp/dccp 0x835d6adf dccp_send_sync +EXPORT_SYMBOL_GPL net/dccp/dccp 0x86bd9e4d dccp_reqsk_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0x86be7924 dccp_packet_name +EXPORT_SYMBOL_GPL net/dccp/dccp 0x87e1845e dccp_connect +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b7d8caf dccp_statistics +EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b971a98 dccp_done +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9b75f861 dccp_send_ack +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9c97bc19 dccp_disconnect +EXPORT_SYMBOL_GPL net/dccp/dccp 0x9d6a3846 dccp_orphan_count +EXPORT_SYMBOL_GPL net/dccp/dccp 0xa377767c dccp_death_row +EXPORT_SYMBOL_GPL net/dccp/dccp 0xa37aed57 ccid_hc_tx_new +EXPORT_SYMBOL_GPL net/dccp/dccp 0xa8fad317 dccp_init_sock +EXPORT_SYMBOL_GPL net/dccp/dccp 0xb356be34 ccid_hc_tx_delete +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbad9ce7d dccp_ioctl +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbba09321 dccp_sample_rtt +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe01122f dccp_child_process +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe4cf010 dccp_feat_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbe5699ee dccp_feat_change_recv +EXPORT_SYMBOL_GPL net/dccp/dccp 0xbf6b58ba dccp_feat_change +EXPORT_SYMBOL_GPL net/dccp/dccp 0xc22b9915 dccp_hashinfo +EXPORT_SYMBOL_GPL net/dccp/dccp 0xcc64321b ccid_unregister +EXPORT_SYMBOL_GPL net/dccp/dccp 0xd37b9865 dccp_poll +EXPORT_SYMBOL_GPL net/dccp/dccp 0xe3362bb3 dccp_set_state +EXPORT_SYMBOL_GPL net/dccp/dccp 0xe783e979 dccp_rcv_established +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf0b5e353 inet_dccp_listen +EXPORT_SYMBOL_GPL net/dccp/dccp 0xf17cc915 dccp_reqsk_init +EXPORT_SYMBOL_GPL net/dccp/dccp 0xfebf25e2 dccp_insert_option_timestamp +EXPORT_SYMBOL_GPL net/dccp/dccp 0xfee607e8 ccid_new +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x01c94bc5 dccp_v4_connect +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x28e58f8f dccp_invalid_packet +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x4ff60383 dccp_v4_request_recv_sock +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x5e1e299f dccp_v4_send_check +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xb07e54be dccp_v4_conn_request +EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xef8d221d dccp_v4_do_rcv +EXPORT_SYMBOL_GPL net/ieee80211/ieee80211 0xd0125380 ieee80211_rx_any +EXPORT_SYMBOL_GPL net/ipv4/ipvs/ip_vs 0xe6476b4a net_vs_ctl_path +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x0becfb37 nf_nat_seq_adjust_hook +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x6d40a921 need_ipv4_conntrack +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x07ae60b6 nf_nat_proto_in_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x2114f521 nf_nat_proto_find_get +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x220cb3e6 nf_nat_proto_put +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x2d53d425 nf_nat_icmp_reply_translation +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x59c3072f nf_nat_proto_unique_tuple +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x7af70ec4 nf_nat_packet +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x94a08134 nf_nat_proto_nlattr_to_range +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xff849778 nf_nat_proto_range_to_nlattr +EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat_proto_gre 0x636b12c8 nf_nat_need_gre +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x73ceae08 tcp_vegas_cwnd_event +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x9b84fc3c tcp_vegas_state +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xa6eacae7 tcp_vegas_init +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xb3b6e687 tcp_vegas_get_info +EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xb8b736ba tcp_vegas_pkts_acked +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x08a3e5d1 net_ipv6_ctl_path +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x100640c5 inet6_csk_search_req +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x25fa0874 fl6_sock_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x27122002 ipv6_opt_accepted +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3b6c266a ip6_dst_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3f00f907 inet6_csk_bind_conflict +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x477cb89c ipv6_find_tlv +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x5e562c80 inet6_destroy_sock +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x5f3f5649 ip6_sk_dst_lookup +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x7cb3a9dc inet6_csk_addr2sockaddr +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x7f3d7a9a inet6_csk_xmit +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x996dddd0 ipv6_dup_options +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xa38bd27e ip6_local_out +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xac24c8b8 inet6_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xfa414c2e ip6_dst_blackhole +EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xfdcc334d inet6_sk_rebuild_header +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x5ebaad00 ieee80211_iterate_active_interfaces_atomic +EXPORT_SYMBOL_GPL net/mac80211/mac80211 0xb8e11813 ieee80211_iterate_active_interfaces +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x041013fd nf_conntrack_lock +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x045072cd nf_ct_port_nla_policy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x08bffbea nf_ct_get_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x0ea4f6dc nf_ct_iterate_cleanup +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x12142315 nf_ct_l3proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1283d711 nf_ct_expect_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x15c10b0b nf_conntrack_unregister_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x17c3d243 nf_ct_l4proto_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x248d7f93 nf_conntrack_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x25e649f2 nf_ct_log_invalid +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2b9580cb nf_conntrack_flush +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x352e095f nf_ct_helper_ext_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3609de81 nf_conntrack_count +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x382f8467 nf_conntrack_l3proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38630158 nf_conntrack_tuple_taken +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x38c9440b nf_ct_extend_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x39a97980 nf_ct_unlink_expect +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3b1521c2 nf_ct_expect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3e70106f nf_conntrack_in +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3f5b1415 nf_ct_port_nlattr_to_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x40387ccf __nf_ct_event_cache_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x452f6894 nf_ct_expect_init +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x486cc510 nf_ct_expect_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4cefd73f print_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x51f34600 nf_conntrack_l4proto_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x55dee0d7 __nf_ct_kill_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5c2e2571 nf_conntrack_tcp_update +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5dd7836a __nf_ct_expect_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5e1630ff nf_ct_l3proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x638bb9d3 nf_ct_l4proto_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6a5aec46 nf_ct_l3protos +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6cd91ee0 per_cpu__nf_conntrack_ecache +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6e224a7a need_conntrack +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x72836f4a nf_conntrack_free +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x7690591f nf_conntrack_helper_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x77aadb54 nf_conntrack_alter_reply +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x78f9b710 nf_ct_l3proto_try_module_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x79ca2e53 nf_ct_expect_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8417d361 nf_ct_invert_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8489bd00 nf_ct_port_tuple_to_nlattr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x886a1333 seq_print_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8d23db4b __nf_conntrack_confirm +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8d594c73 nf_ct_unexpect_related +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8e72e2dc nf_conntrack_l4proto_tcp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8ffe7e89 nf_conntrack_htable_size +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x90ff6c9f nf_ct_invert_tuplepr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9372058e nf_ct_expect_alloc +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x954d8f63 __nf_ct_l4proto_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9bfab4ea nf_conntrack_l4proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa6f62ec0 nf_conntrack_set_hashsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xac030369 nf_conntrack_l3proto_register +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xace98352 nf_conntrack_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaf57e66f nf_ct_extend_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb602c57e nf_ct_l3proto_module_put +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb76accc2 __nf_conntrack_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb9e30797 nf_ct_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbc44805e nf_conntrack_l4proto_tcp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbc887e16 nf_ct_expect_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbe3f2939 nf_conntrack_checksum +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc044befe nf_ct_free_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc18ac88d nf_ct_expect_hsize +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc35a7a3e nf_conntrack_chain +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc6e656f6 nf_conntrack_l4proto_udp6 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc7b64d79 nf_conntrack_hash_insert +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcbe2d46d nf_conntrack_l3proto_generic +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcbf7fd2a nf_conntrack_register_notifier +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcd07cd85 nf_conntrack_helper_unregister +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd50a96a2 nf_ct_alloc_hashtable +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd7c683c4 nf_conntrack_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd8f9d2fa __nf_conntrack_helper_find_byname +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd918bb94 __nf_ct_helper_find +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd9efb053 nf_ct_deliver_cached_events +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xdd43a846 nf_ct_get_tuple +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe8a986c7 __nf_ct_refresh_acct +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xec8beba6 nf_ct_expect_hash +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf4d03474 nf_conntrack_l4proto_udp4 +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf9ae81a1 nf_conntrack_max +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfa169dac nf_conntrack_untracked +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfb6986e4 nf_ct_expect_find_get +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfb839673 nf_ct_remove_expectations +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_amanda 0xddc5b0d8 nf_nat_amanda_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_ftp 0xfc116275 nf_nat_ftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x09cc3d60 set_h225_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x121d5a12 nat_h245_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x264c0cf3 get_h225_addr +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x2e04baa2 set_ras_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x5555a1a8 nat_t120_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x65c4cfaf set_sig_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x74f37fc1 nat_q931_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xa0f73075 set_h245_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xbad72234 nat_callforwarding_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xd4d197a5 nat_rtp_rtcp_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_irc 0xf448b19c nf_nat_irc_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x2a44d49a nf_nat_pptp_hook_expectfn +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x4221dfa6 nf_nat_pptp_hook_exp_gre +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xe6cbbf27 nf_nat_pptp_hook_inbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xfa2f5bdf nf_nat_pptp_hook_outbound +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x05f8e58c nf_ct_gre_keymap_destroy +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x6f59d77c nf_ct_gre_keymap_add +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x13169b79 ct_sip_parse_request +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x3c2058a6 ct_sip_parse_numerical_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5333cb69 ct_sip_parse_header_uri +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x5343611e ct_sip_get_sdp_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x56ad8f6e ct_sip_parse_address_param +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x632fbab8 nf_nat_sip_expect_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x6550678b nf_nat_sdp_session_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xc9f19808 nf_nat_sdp_addr_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xe968d4dd nf_nat_sdp_media_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf496b4be nf_nat_sip_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf6943e00 nf_nat_sdp_port_hook +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf8b610ea ct_sip_get_header +EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_tftp 0x118a78a9 nf_nat_tftp_hook +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x4354b615 nfnetlink_subsys_unregister +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x8c139b0d nfnetlink_send +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x99f5cf73 nfnetlink_unicast +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x9a0e4734 nfnetlink_subsys_register +EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xeca95329 nfnetlink_has_listeners +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x21638ebe xt_request_find_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x3f03dd29 xt_unregister_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x63f05053 xt_find_revision +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x8cb4487e xt_proto_fini +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x8dbd1db9 xt_replace_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x9dd9ef24 xt_check_target +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xa2ec3484 xt_table_unlock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xc910604c xt_register_table +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xd0836cc4 xt_find_table_lock +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xd96ee14a xt_check_match +EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xfaa4de95 xt_proto_init +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xc177bee0 xt_rateest_put +EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xdb8418cc xt_rateest_lookup +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x83b2e956 register_rfkill_notifier +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0x86c722f8 rfkill_epo +EXPORT_SYMBOL_GPL net/rfkill/rfkill 0xa6f4320d unregister_rfkill_notifier +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0xeaad1717 rxrpc_register_security +EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0xf6b898d8 rxrpc_unregister_security +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x06813e9c rpcauth_lookup_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x08fb1b3d svc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0bed0a5c rpcauth_destroy_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0e01e9c4 rpc_restart_call +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0f8c6ddc put_rpccred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x11e7ca4c svc_unreg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x18f80c8d xprt_reserve_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x241ede2a xprt_register_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2434a286 csum_partial_copy_to_xdr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x24fc4f84 rpc_call_null +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x296094f7 __rpc_wait_for_completion_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2aa17774 rpc_free_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2bba7c09 rpc_clone_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2c592b77 svc_xprt_names +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x30ae116e xprt_write_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x31a89d59 rpc_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x326cafb2 rpc_run_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x34be4564 rpc_setbufsize +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x393a1c0a rpc_put_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3bf4ffd5 svc_xprt_received +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3d9cde36 xprt_set_retrans_timeout_def +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x42abb487 svc_xprt_put +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x462ff63d svc_close_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x47289662 rpc_wake_up_next +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x49fd9f7e rpc_print_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4f504ee2 rpc_lookup_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x51efd048 rpc_bind_new_program +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x53445f68 nlm_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x54982939 xdr_partial_copy_from_skb +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x54cc1bef xprt_unregister_transport +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x550547a3 rpc_destroy_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x551fbc06 rpcauth_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x55c7cedb rpc_alloc_iostats +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x595b4b56 rpc_call_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bd26000 rpc_proc_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x62e8f0c4 xprt_reserve_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c5304c5 rpcb_getport_sync +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6cb6e3de rpc_create +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6d8d148e rpc_malloc +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x70e3b1b7 rpcauth_unregister +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7322279a svc_find_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x74bc8b30 rpcb_getport_async +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7b7ac072 rpcauth_init_credcache +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7de53067 rpc_init_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7f43b9cf xprt_release_xprt_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x86a8492d rpc_wake_up_queued_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x88c8a1df xprt_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x89833cd5 svc_addsock +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8b4a520d xprt_complete_rqst +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8c03c460 svc_xprt_copy_addrs +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8ddcdf1b rpc_exit_task +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x93336bcb rpcauth_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x99dcb228 xprt_release_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9a1460eb xprt_wait_for_buffer_space +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9debc7e5 xprt_set_retrans_timeout_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa0662bbc svc_xprt_enqueue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa4b4f250 rpc_peeraddr2str +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa69478fd svc_print_addr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaa63957a xdr_skb_read_bits +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf5bf6ef nfs_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb13c8e30 svc_reg_xprt_class +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb387b246 rpc_wake_up_status +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb5f6a8ab rpc_call_start +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb794c8ef rpc_peeraddr +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb8c84ca7 xprt_release_rqst_cong +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb93c0ce0 rpcauth_generic_bind_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbb0c2594 svc_xprt_init +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbcbaf603 xprt_wake_pending_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf9d1b96 nfsd_debug +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc0ad7c88 rpc_lookup_machine_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc12435e3 rpc_calc_rto +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc12522c7 rpc_force_rebind +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc72228c3 rpc_max_payload +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc7de20f9 xprt_adjust_cwnd +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc9d6c2ff rpc_killall_tasks +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd819e526 svc_create_xprt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd82c728e rpc_init_wait_queue +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdac2bcab rpc_shutdown_client +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xde5fbcd7 rpcauth_init_cred +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe36eee5b xprt_lookup_rqst +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe68a57f0 rpc_proc_register +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xea109b9f rpc_delay +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedd1ba52 rpc_wake_up +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xeeacab69 rpc_update_rtt +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf3ccb6bc xprt_disconnect_done +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf5552851 rpc_sleep_on +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf9d1164c rpc_free +EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfdfbc8c3 rpc_call_sync +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x980b3325 ipcomp_input +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xcff15ceb ipcomp_init_state +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xd007f0c9 ipcomp_destroy +EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xee5863df ipcomp_output +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x07bb8bda snd_soc_dapm_new_controls +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x12e4668e snd_soc_test_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1a3fe22d snd_soc_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x271a40c9 snd_soc_info_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x36634b4f snd_soc_set_runtime_hwparams +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x381be863 snd_soc_dai_set_tdm_slot +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3e7c7556 snd_soc_update_bits +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x446a9285 snd_soc_put_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x558a6b47 snd_soc_dapm_free +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5cb51a25 snd_soc_get_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5d6bc4ea snd_soc_dai_set_sysclk +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5f2bd730 snd_soc_dapm_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x607280be snd_soc_dapm_sync +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6365574e snd_soc_dapm_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x645f9b37 snd_soc_dapm_get_pin_status +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x689db1b9 snd_soc_register_card +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x68aa71a5 snd_soc_dapm_get_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x791bc45e snd_soc_dai_set_pll +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x79c6fb32 snd_soc_info_enum_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8a781ad9 dapm_reg_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8b77c7b7 snd_soc_dapm_stream_event +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x91d6bc86 snd_soc_dapm_enable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x92de1c99 snd_soc_info_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x9557f261 snd_soc_info_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xaa4e57e3 snd_soc_free_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xaf56c8ec snd_soc_dai_set_clkdiv +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb01029ab snd_soc_dai_set_tristate +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb21da9ca snd_soc_info_volsw_ext +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb54a2db9 snd_soc_info_volsw_s8 +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb7bfe9fd snd_soc_dai_digital_mute +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbb6cf3fc snd_soc_dapm_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbb7b71a4 snd_soc_dapm_disable_pin +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc3bc0457 snd_soc_new_pcms +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc66ec22c snd_soc_new_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc7fda1e7 snd_soc_free_ac97_codec +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc9f96074 snd_soc_put_volsw +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xca2d17c6 snd_soc_dapm_add_routes +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xcc42d5bc snd_soc_put_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd49d5d1c snd_soc_get_volsw_2r +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd557bed1 snd_soc_cnew +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdacb3193 snd_soc_put_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe4036bf0 snd_soc_dapm_connect_input +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe685b1ed snd_soc_get_enum_double +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xeb401546 snd_soc_dai_set_fmt +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfa8cf204 snd_soc_dapm_new_widgets +EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfc48e015 snd_soc_dapm_new_control +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x1584fdb9 tlsf_destroy_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x42a50f11 tlsf_malloc +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0x66da3d8f tlsf_create_memory_pool +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xe6acc368 tlsf_free +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xee6c65c9 tlsf_get_used_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xeec8caeb tlsf_get_total_size +EXPORT_SYMBOL_GPL ubuntu/compcache/tlsf 0xf9805f1b tlsf_calloc +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x02500586 thinkpad_ec_unlock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x0dc7484e thinkpad_ec_try_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x2552d213 thinkpad_ec_lock +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x3dbfef12 thinkpad_ec_read_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0x8dbbd831 thinkpad_ec_invalidate +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xa3042743 thinkpad_ec_prefetch_row +EXPORT_SYMBOL_GPL ubuntu/misc/thinkpad_ec 0xfb5aa917 thinkpad_ec_try_lock +EXPORT_SYMBOL_GPL vmlinux 0x00566d8f inotify_get_cookie +EXPORT_SYMBOL_GPL vmlinux 0x006482d9 bus_get_device_klist +EXPORT_SYMBOL_GPL vmlinux 0x006d7cad srcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x008a6496 xfrm_audit_state_add +EXPORT_SYMBOL_GPL vmlinux 0x01032b44 get_device +EXPORT_SYMBOL_GPL vmlinux 0x011a8b72 platform_bus +EXPORT_SYMBOL_GPL vmlinux 0x01848a8e local_apic_timer_c2_ok +EXPORT_SYMBOL_GPL vmlinux 0x01a4ea6d unregister_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x01d71b6b copy_fs_struct +EXPORT_SYMBOL_GPL vmlinux 0x01e1a8de kgdb_breakpoint +EXPORT_SYMBOL_GPL vmlinux 0x022ccb93 inet_csk_clone +EXPORT_SYMBOL_GPL vmlinux 0x0279ccb2 spi_add_device +EXPORT_SYMBOL_GPL vmlinux 0x0295aa12 inotify_init_watch +EXPORT_SYMBOL_GPL vmlinux 0x02a6fbb3 kobject_uevent +EXPORT_SYMBOL_GPL vmlinux 0x02a82d18 device_release_driver +EXPORT_SYMBOL_GPL vmlinux 0x02ab1f28 sysdev_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x02be3cb3 simple_attr_open +EXPORT_SYMBOL_GPL vmlinux 0x02ccea56 lock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x0343bdf1 __i2c_board_list +EXPORT_SYMBOL_GPL vmlinux 0x03a6f99d platform_add_devices +EXPORT_SYMBOL_GPL vmlinux 0x03a7306a relay_open +EXPORT_SYMBOL_GPL vmlinux 0x03f94469 sysfs_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x0408a084 sysfs_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x0443de29 get_task_mm +EXPORT_SYMBOL_GPL vmlinux 0x04486e88 rcu_batches_completed +EXPORT_SYMBOL_GPL vmlinux 0x04566c7f init_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x0470079f generic_sync_sb_inodes +EXPORT_SYMBOL_GPL vmlinux 0x054e550b kernel_halt +EXPORT_SYMBOL_GPL vmlinux 0x05e835d3 klist_node_attached +EXPORT_SYMBOL_GPL vmlinux 0x05f2f9e4 inotify_rm_watch +EXPORT_SYMBOL_GPL vmlinux 0x061b2b8d inotify_rm_wd +EXPORT_SYMBOL_GPL vmlinux 0x062a8e79 crypto_hash_walk_first +EXPORT_SYMBOL_GPL vmlinux 0x064db9a5 mark_mounts_for_expiry +EXPORT_SYMBOL_GPL vmlinux 0x06d222f8 device_resume +EXPORT_SYMBOL_GPL vmlinux 0x0764906c devres_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x07b52e38 rtnl_unregister +EXPORT_SYMBOL_GPL vmlinux 0x08165753 debugfs_create_x32 +EXPORT_SYMBOL_GPL vmlinux 0x082c535e __mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x08969112 pci_find_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0x08c10d21 rtnl_kill_links +EXPORT_SYMBOL_GPL vmlinux 0x08e7a6cb device_move +EXPORT_SYMBOL_GPL vmlinux 0x08ebd45f device_initialize +EXPORT_SYMBOL_GPL vmlinux 0x08ff066f vlan_dev_vlan_id +EXPORT_SYMBOL_GPL vmlinux 0x091eb9b4 round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0x09afc142 fb_deferred_io_fsync +EXPORT_SYMBOL_GPL vmlinux 0x0acf090d driver_create_file +EXPORT_SYMBOL_GPL vmlinux 0x0b9e724f class_interface_unregister +EXPORT_SYMBOL_GPL vmlinux 0x0bb61443 inet_diag_register +EXPORT_SYMBOL_GPL vmlinux 0x0bc151e5 klist_init +EXPORT_SYMBOL_GPL vmlinux 0x0bd335d3 alloc_page_buffers +EXPORT_SYMBOL_GPL vmlinux 0x0c17e274 xfrm_aalg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x0c408ae9 attribute_container_register +EXPORT_SYMBOL_GPL vmlinux 0x0c4717f7 srcu_init_notifier_head +EXPORT_SYMBOL_GPL vmlinux 0x0d18d070 device_create_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x0d1ca769 tty_ldisc_ref +EXPORT_SYMBOL_GPL vmlinux 0x0d3a2872 simple_attr_release +EXPORT_SYMBOL_GPL vmlinux 0x0d9c2a54 crypto_mod_put +EXPORT_SYMBOL_GPL vmlinux 0x0ea6b449 platform_device_put +EXPORT_SYMBOL_GPL vmlinux 0x0ef83501 sched_setscheduler +EXPORT_SYMBOL_GPL vmlinux 0x0ef84c65 hrtimer_start +EXPORT_SYMBOL_GPL vmlinux 0x0f0d238a key_type_user +EXPORT_SYMBOL_GPL vmlinux 0x0f5953cc sysdev_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x10018797 sysdev_show_int +EXPORT_SYMBOL_GPL vmlinux 0x1050bc52 hrtimer_init +EXPORT_SYMBOL_GPL vmlinux 0x1079549e relay_reset +EXPORT_SYMBOL_GPL vmlinux 0x10b17493 led_trigger_set +EXPORT_SYMBOL_GPL vmlinux 0x11382702 user_match +EXPORT_SYMBOL_GPL vmlinux 0x118cc972 inet6_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0x120b41e3 fb_deferred_io_cleanup +EXPORT_SYMBOL_GPL vmlinux 0x124f2056 crypto_get_attr_type +EXPORT_SYMBOL_GPL vmlinux 0x1251d30f call_rcu +EXPORT_SYMBOL_GPL vmlinux 0x127c4d8a xfrm_audit_state_icvfail +EXPORT_SYMBOL_GPL vmlinux 0x129618e9 k_handler +EXPORT_SYMBOL_GPL vmlinux 0x12bf13bc input_ff_create +EXPORT_SYMBOL_GPL vmlinux 0x13354608 scatterwalk_map_and_copy +EXPORT_SYMBOL_GPL vmlinux 0x136e9186 anon_inode_getfd +EXPORT_SYMBOL_GPL vmlinux 0x13b2a946 register_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x13cc281a queue_work_on +EXPORT_SYMBOL_GPL vmlinux 0x145eebd0 device_power_up +EXPORT_SYMBOL_GPL vmlinux 0x149db923 selinux_string_to_sid +EXPORT_SYMBOL_GPL vmlinux 0x1503fc60 crypto_alloc_base +EXPORT_SYMBOL_GPL vmlinux 0x1598dc9d unregister_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x15b0606e e820_any_mapped +EXPORT_SYMBOL_GPL vmlinux 0x16f76869 probe_kernel_read +EXPORT_SYMBOL_GPL vmlinux 0x172e72d4 vdso_enabled +EXPORT_SYMBOL_GPL vmlinux 0x1769f2c6 user_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x17c1bd2b driver_register +EXPORT_SYMBOL_GPL vmlinux 0x1878f62b edac_err_assert +EXPORT_SYMBOL_GPL vmlinux 0x18a7c4b1 unregister_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0x18d53420 kgdb_register_io_module +EXPORT_SYMBOL_GPL vmlinux 0x190b49e9 security_inode_setattr +EXPORT_SYMBOL_GPL vmlinux 0x190cb33a __cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0x19647282 tty_ldisc_ref_wait +EXPORT_SYMBOL_GPL vmlinux 0x19af3c0f cpufreq_cpu_get +EXPORT_SYMBOL_GPL vmlinux 0x1a43c332 unregister_jprobe +EXPORT_SYMBOL_GPL vmlinux 0x1a5709e4 pci_disable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0x1a938737 atomic_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x1ab1dd4b blk_trace_setup +EXPORT_SYMBOL_GPL vmlinux 0x1acda5b2 atomic_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x1b60d688 sysfs_create_group +EXPORT_SYMBOL_GPL vmlinux 0x1b9aca3f jprobe_return +EXPORT_SYMBOL_GPL vmlinux 0x1bbe9cf2 crypto_larval_lookup +EXPORT_SYMBOL_GPL vmlinux 0x1db9b4ea save_stack_trace_tsk +EXPORT_SYMBOL_GPL vmlinux 0x1dbb53ac pci_destroy_slot +EXPORT_SYMBOL_GPL vmlinux 0x1dd70100 dmi_walk +EXPORT_SYMBOL_GPL vmlinux 0x1e0d292a rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x1e23ca6b netlink_has_listeners +EXPORT_SYMBOL_GPL vmlinux 0x1e45638a __create_workqueue_key +EXPORT_SYMBOL_GPL vmlinux 0x1e7bbcb3 kernel_restart +EXPORT_SYMBOL_GPL vmlinux 0x1eb9516e round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x1ee4ec29 pciserial_init_ports +EXPORT_SYMBOL_GPL vmlinux 0x1f8ec1b3 acpi_get_pci_rootbridge_handle +EXPORT_SYMBOL_GPL vmlinux 0x1f9a0fbf hpet_unregister_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x1fcece42 inet_twdr_twcal_tick +EXPORT_SYMBOL_GPL vmlinux 0x1ffc6da1 skb_pull_rcsum +EXPORT_SYMBOL_GPL vmlinux 0x20577ea2 xfrm_ealg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x20b82470 hpet_register_irq_handler +EXPORT_SYMBOL_GPL vmlinux 0x20bc3470 orderly_poweroff +EXPORT_SYMBOL_GPL vmlinux 0x20e4484f class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x211bb598 __audit_inode_child +EXPORT_SYMBOL_GPL vmlinux 0x21206e57 crypto_unregister_alg +EXPORT_SYMBOL_GPL vmlinux 0x212462f9 page_mkclean +EXPORT_SYMBOL_GPL vmlinux 0x22472bf4 xfrm_calg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x224a6495 blk_set_cmd_filter_defaults +EXPORT_SYMBOL_GPL vmlinux 0x2296c00d crypto_attr_u32 +EXPORT_SYMBOL_GPL vmlinux 0x22d98f2c power_supply_unregister +EXPORT_SYMBOL_GPL vmlinux 0x22f7680f rtc_set_alarm +EXPORT_SYMBOL_GPL vmlinux 0x23679939 __iowrite32_copy +EXPORT_SYMBOL_GPL vmlinux 0x23864ce7 cpuset_mem_spread_node +EXPORT_SYMBOL_GPL vmlinux 0x23b335c4 lookup_create +EXPORT_SYMBOL_GPL vmlinux 0x24196ba2 init_uts_ns +EXPORT_SYMBOL_GPL vmlinux 0x2447533c ktime_get_real +EXPORT_SYMBOL_GPL vmlinux 0x24eb7e32 leds_list +EXPORT_SYMBOL_GPL vmlinux 0x2566c667 dequeue_signal +EXPORT_SYMBOL_GPL vmlinux 0x25dc7f43 device_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x25e6a7c5 device_destroy +EXPORT_SYMBOL_GPL vmlinux 0x26b2d364 sysdev_class_create_file +EXPORT_SYMBOL_GPL vmlinux 0x26eb338b macvlan_handle_frame_hook +EXPORT_SYMBOL_GPL vmlinux 0x2712cce3 transport_setup_device +EXPORT_SYMBOL_GPL vmlinux 0x2714c98c klist_del +EXPORT_SYMBOL_GPL vmlinux 0x276412cd tcp_set_state +EXPORT_SYMBOL_GPL vmlinux 0x277b007b generic_fh_to_dentry +EXPORT_SYMBOL_GPL vmlinux 0x28088f0f pv_time_ops +EXPORT_SYMBOL_GPL vmlinux 0x28774844 rtc_class_close +EXPORT_SYMBOL_GPL vmlinux 0x28d664ff __raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x28e23139 xfrm_probe_algs +EXPORT_SYMBOL_GPL vmlinux 0x295394e2 raw_seq_next +EXPORT_SYMBOL_GPL vmlinux 0x29a24ad0 raw_unhash_sk +EXPORT_SYMBOL_GPL vmlinux 0x2a678a13 __suspend_report_result +EXPORT_SYMBOL_GPL vmlinux 0x2a680d4a spi_new_device +EXPORT_SYMBOL_GPL vmlinux 0x2b112e02 blk_end_request_callback +EXPORT_SYMBOL_GPL vmlinux 0x2b78b12d skb_icv_walk +EXPORT_SYMBOL_GPL vmlinux 0x2b9f8e23 nf_net_ipv4_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x2bb6f5ad do_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0x2bfdeb4e sysdev_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x2c16ed76 xfrm_calg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x2d244092 sysfs_remove_link +EXPORT_SYMBOL_GPL vmlinux 0x2d45bcda crypto_alg_sem +EXPORT_SYMBOL_GPL vmlinux 0x2d59c954 edac_handlers +EXPORT_SYMBOL_GPL vmlinux 0x2d8500c8 debugfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x2d92560f d_materialise_unique +EXPORT_SYMBOL_GPL vmlinux 0x2d9f2ce3 sched_clock_idle_wakeup_event +EXPORT_SYMBOL_GPL vmlinux 0x2e2f2f18 blk_execute_rq_nowait +EXPORT_SYMBOL_GPL vmlinux 0x2e6e7aee smp_ops +EXPORT_SYMBOL_GPL vmlinux 0x2e76b402 hvc_instantiate +EXPORT_SYMBOL_GPL vmlinux 0x2eb91dfe scatterwalk_map +EXPORT_SYMBOL_GPL vmlinux 0x2ed92ddb spi_sync +EXPORT_SYMBOL_GPL vmlinux 0x2f496bba inet6_lookup +EXPORT_SYMBOL_GPL vmlinux 0x2f870319 __class_register +EXPORT_SYMBOL_GPL vmlinux 0x3037813e invalidate_inode_pages2 +EXPORT_SYMBOL_GPL vmlinux 0x30b0908f inotify_remove_watch_locked +EXPORT_SYMBOL_GPL vmlinux 0x30db94f6 __get_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x3167f035 class_unregister +EXPORT_SYMBOL_GPL vmlinux 0x316d9888 device_create_vargs +EXPORT_SYMBOL_GPL vmlinux 0x3189f2bb mmu_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0x31fa1918 device_bind_driver +EXPORT_SYMBOL_GPL vmlinux 0x32b0eb3e led_trigger_set_default +EXPORT_SYMBOL_GPL vmlinux 0x3326c00b crypto_register_instance +EXPORT_SYMBOL_GPL vmlinux 0x332a7712 skb_partial_csum_set +EXPORT_SYMBOL_GPL vmlinux 0x33562f11 pskb_put +EXPORT_SYMBOL_GPL vmlinux 0x34401ab1 cpuidle_unregister_device +EXPORT_SYMBOL_GPL vmlinux 0x3441c3d6 gpio_set_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x34712b7b __blk_add_trace +EXPORT_SYMBOL_GPL vmlinux 0x34c0c038 xfrm_audit_state_notfound_simple +EXPORT_SYMBOL_GPL vmlinux 0x35a720e4 pciserial_remove_ports +EXPORT_SYMBOL_GPL vmlinux 0x35c26fd9 pci_bus_add_device +EXPORT_SYMBOL_GPL vmlinux 0x3609b38b kset_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x361e2bcc save_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0x362e23ec call_rcu_bh +EXPORT_SYMBOL_GPL vmlinux 0x363a73ee device_create_file +EXPORT_SYMBOL_GPL vmlinux 0x365d029f pciserial_suspend_ports +EXPORT_SYMBOL_GPL vmlinux 0x367f00e2 sysdev_create_file +EXPORT_SYMBOL_GPL vmlinux 0x36af7d00 nf_register_afinfo +EXPORT_SYMBOL_GPL vmlinux 0x36e70239 bd_release_from_disk +EXPORT_SYMBOL_GPL vmlinux 0x3713c787 tty_prepare_flip_string +EXPORT_SYMBOL_GPL vmlinux 0x3731d671 tty_prepare_flip_string_flags +EXPORT_SYMBOL_GPL vmlinux 0x3739aa39 sock_prot_inuse_get +EXPORT_SYMBOL_GPL vmlinux 0x37690d32 cpufreq_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0x379880a8 device_reprobe +EXPORT_SYMBOL_GPL vmlinux 0x37b61e61 sysfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x37ba8526 skb_segment +EXPORT_SYMBOL_GPL vmlinux 0x37d17fb7 anon_transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0x384d7070 debugfs_create_bool +EXPORT_SYMBOL_GPL vmlinux 0x3895233b srcu_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x39676259 platform_get_resource_byname +EXPORT_SYMBOL_GPL vmlinux 0x3997afb4 attribute_container_find_class_device +EXPORT_SYMBOL_GPL vmlinux 0x39d154f4 led_trigger_register +EXPORT_SYMBOL_GPL vmlinux 0x3a3e072e __inet_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0x3a7f8b86 __local_bh_enable +EXPORT_SYMBOL_GPL vmlinux 0x3a906bac securityfs_remove +EXPORT_SYMBOL_GPL vmlinux 0x3a9a440d gpiochip_add +EXPORT_SYMBOL_GPL vmlinux 0x3ac3d8d2 unregister_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0x3bb986e2 inet_csk_addr2sockaddr +EXPORT_SYMBOL_GPL vmlinux 0x3be7af02 get_max_files +EXPORT_SYMBOL_GPL vmlinux 0x3c23e37f spi_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x3c26bb4d kill_pid_info_as_uid +EXPORT_SYMBOL_GPL vmlinux 0x3c539e64 blk_rq_cur_bytes +EXPORT_SYMBOL_GPL vmlinux 0x3c63c935 dma_get_required_mask +EXPORT_SYMBOL_GPL vmlinux 0x3c7079cc __trace_note_message +EXPORT_SYMBOL_GPL vmlinux 0x3c942368 profile_event_unregister +EXPORT_SYMBOL_GPL vmlinux 0x3c9432cb sysdev_unregister +EXPORT_SYMBOL_GPL vmlinux 0x3cc8cd35 vfs_setlease +EXPORT_SYMBOL_GPL vmlinux 0x3cd06035 add_input_randomness +EXPORT_SYMBOL_GPL vmlinux 0x3ce5f576 proc_net_remove +EXPORT_SYMBOL_GPL vmlinux 0x3cfedb3f register_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x3d711cb9 sysdev_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x3d89b8f0 pci_find_aer_capability +EXPORT_SYMBOL_GPL vmlinux 0x3dbf6dd9 bus_find_device +EXPORT_SYMBOL_GPL vmlinux 0x3de96356 sysfs_remove_bin_file +EXPORT_SYMBOL_GPL vmlinux 0x3ea9f1de __class_create +EXPORT_SYMBOL_GPL vmlinux 0x3eae62c6 simple_attr_read +EXPORT_SYMBOL_GPL vmlinux 0x3eccd3ff apply_to_page_range +EXPORT_SYMBOL_GPL vmlinux 0x3efb35c9 get_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0x3f01570a probe_kernel_write +EXPORT_SYMBOL_GPL vmlinux 0x3f0734e2 spi_write_then_read +EXPORT_SYMBOL_GPL vmlinux 0x3f238101 dcookie_register +EXPORT_SYMBOL_GPL vmlinux 0x401a5639 sk_setup_caps +EXPORT_SYMBOL_GPL vmlinux 0x401c3fe5 bdi_writeout_inc +EXPORT_SYMBOL_GPL vmlinux 0x404feb30 devres_alloc +EXPORT_SYMBOL_GPL vmlinux 0x409cf031 acpi_ec_remove_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x40c39cff acpi_ec_add_query_handler +EXPORT_SYMBOL_GPL vmlinux 0x40ecacbd crypto_register_template +EXPORT_SYMBOL_GPL vmlinux 0x41aad989 led_trigger_store +EXPORT_SYMBOL_GPL vmlinux 0x41d0fdc2 raw_hash_sk +EXPORT_SYMBOL_GPL vmlinux 0x41eb6794 fib_rules_lookup +EXPORT_SYMBOL_GPL vmlinux 0x41f3cc90 xfrm_aalg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x425291b8 isa_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0x425508d3 stop_machine +EXPORT_SYMBOL_GPL vmlinux 0x425b3a20 sk_clone +EXPORT_SYMBOL_GPL vmlinux 0x42b364ef scatterwalk_done +EXPORT_SYMBOL_GPL vmlinux 0x42eaa9fe vfs_listxattr +EXPORT_SYMBOL_GPL vmlinux 0x4316a83c tcp_get_info +EXPORT_SYMBOL_GPL vmlinux 0x432fd7f6 __gpio_set_value +EXPORT_SYMBOL_GPL vmlinux 0x4334ab4e lookup_instantiate_filp +EXPORT_SYMBOL_GPL vmlinux 0x43d9a7e7 invalidate_inode_pages2_range +EXPORT_SYMBOL_GPL vmlinux 0x441c08df tty_get_pgrp +EXPORT_SYMBOL_GPL vmlinux 0x44a50fb3 register_posix_clock +EXPORT_SYMBOL_GPL vmlinux 0x44a65d5c lock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x44ab0c7a gpiochip_remove +EXPORT_SYMBOL_GPL vmlinux 0x44e7a7b6 rtc_irq_unregister +EXPORT_SYMBOL_GPL vmlinux 0x44f89fb0 inet_twsk_purge +EXPORT_SYMBOL_GPL vmlinux 0x452c04a4 transport_destroy_device +EXPORT_SYMBOL_GPL vmlinux 0x453ccdb3 sysdev_store_int +EXPORT_SYMBOL_GPL vmlinux 0x457594fa crypto_alg_list +EXPORT_SYMBOL_GPL vmlinux 0x45bf1ff3 crypto_inc +EXPORT_SYMBOL_GPL vmlinux 0x460f31aa rodata_test_data +EXPORT_SYMBOL_GPL vmlinux 0x4661ce03 tcp_reno_cong_avoid +EXPORT_SYMBOL_GPL vmlinux 0x46878e1b fb_deferred_io_init +EXPORT_SYMBOL_GPL vmlinux 0x4689c494 debugfs_create_x16 +EXPORT_SYMBOL_GPL vmlinux 0x46df52eb bus_create_file +EXPORT_SYMBOL_GPL vmlinux 0x46ed7ca5 exit_fs +EXPORT_SYMBOL_GPL vmlinux 0x46fbebcc cpufreq_driver_target +EXPORT_SYMBOL_GPL vmlinux 0x471ef915 fb_bl_default_curve +EXPORT_SYMBOL_GPL vmlinux 0x47229b5c gpio_request +EXPORT_SYMBOL_GPL vmlinux 0x4755f073 unregister_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x47b02bc5 inet_twsk_alloc +EXPORT_SYMBOL_GPL vmlinux 0x47bdc699 debugfs_create_x8 +EXPORT_SYMBOL_GPL vmlinux 0x48060125 crypto_spawn_tfm +EXPORT_SYMBOL_GPL vmlinux 0x499043d3 crypto_init_queue +EXPORT_SYMBOL_GPL vmlinux 0x49af14e4 unregister_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x4a14e027 bd_claim_by_disk +EXPORT_SYMBOL_GPL vmlinux 0x4a7e30d9 marker_probe_unregister_private_data +EXPORT_SYMBOL_GPL vmlinux 0x4ace6f42 platform_bus_type +EXPORT_SYMBOL_GPL vmlinux 0x4b70abf5 xfrm_audit_policy_delete +EXPORT_SYMBOL_GPL vmlinux 0x4c759827 byte_rev_table +EXPORT_SYMBOL_GPL vmlinux 0x4da38447 debugfs_create_u8 +EXPORT_SYMBOL_GPL vmlinux 0x4dce11cd find_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0x4dd67894 crypto_tfm_in_queue +EXPORT_SYMBOL_GPL vmlinux 0x4e968e44 register_net_sysctl_table +EXPORT_SYMBOL_GPL vmlinux 0x4ead40ce input_class +EXPORT_SYMBOL_GPL vmlinux 0x4ed99d22 cpufreq_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x50634025 net_assign_generic +EXPORT_SYMBOL_GPL vmlinux 0x50b67174 xfrm_ealg_get_byid +EXPORT_SYMBOL_GPL vmlinux 0x50e7193a __i2c_first_dynamic_bus_num +EXPORT_SYMBOL_GPL vmlinux 0x5108b3fc acpi_os_map_memory +EXPORT_SYMBOL_GPL vmlinux 0x518c2fc6 hpet_rtc_dropped_irq +EXPORT_SYMBOL_GPL vmlinux 0x51b7bfec __pneigh_lookup +EXPORT_SYMBOL_GPL vmlinux 0x51dd6488 xfrm_aalg_get_byidx +EXPORT_SYMBOL_GPL vmlinux 0x52a68293 inet_csk_route_req +EXPORT_SYMBOL_GPL vmlinux 0x52d111ea pm_qos_update_requirement +EXPORT_SYMBOL_GPL vmlinux 0x53986488 register_die_notifier +EXPORT_SYMBOL_GPL vmlinux 0x54a3d54c queue_delayed_work +EXPORT_SYMBOL_GPL vmlinux 0x5595a9fd generic_drop_inode +EXPORT_SYMBOL_GPL vmlinux 0x55b527c6 tcp_register_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x56398615 mark_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5641485b tty_termios_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0x575b8221 crypto_alloc_instance +EXPORT_SYMBOL_GPL vmlinux 0x579e0bf5 rtnl_unregister_all +EXPORT_SYMBOL_GPL vmlinux 0x57a20bb1 single_release_net +EXPORT_SYMBOL_GPL vmlinux 0x585c3d0c devres_close_group +EXPORT_SYMBOL_GPL vmlinux 0x587516a5 class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x593a0487 __inet_lookup_established +EXPORT_SYMBOL_GPL vmlinux 0x594ce7d5 bus_unregister +EXPORT_SYMBOL_GPL vmlinux 0x597f3bc3 marker_get_private_data +EXPORT_SYMBOL_GPL vmlinux 0x5a50353b rtc_irq_register +EXPORT_SYMBOL_GPL vmlinux 0x5ac8c6b7 unregister_kprobes +EXPORT_SYMBOL_GPL vmlinux 0x5acca663 __ip_route_output_key +EXPORT_SYMBOL_GPL vmlinux 0x5b392b04 hrtimer_try_to_cancel +EXPORT_SYMBOL_GPL vmlinux 0x5b5114f9 driver_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x5bb44a32 klist_add_head +EXPORT_SYMBOL_GPL vmlinux 0x5bfc03c3 unregister_keyboard_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5c52e193 inotify_find_watch +EXPORT_SYMBOL_GPL vmlinux 0x5ca4f946 platform_get_irq_byname +EXPORT_SYMBOL_GPL vmlinux 0x5cfcf0f1 percpu_free +EXPORT_SYMBOL_GPL vmlinux 0x5d0f6f57 kbd_table +EXPORT_SYMBOL_GPL vmlinux 0x5d51bcf7 scatterwalk_start +EXPORT_SYMBOL_GPL vmlinux 0x5d730e7b raw_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5dd67618 register_netevent_notifier +EXPORT_SYMBOL_GPL vmlinux 0x5e047c90 hwmon_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x5e180898 rt_mutex_timed_lock +EXPORT_SYMBOL_GPL vmlinux 0x5e689ef4 sysdev_store_ulong +EXPORT_SYMBOL_GPL vmlinux 0x5e770d0f relay_subbufs_consumed +EXPORT_SYMBOL_GPL vmlinux 0x5f2da8c4 check_tsc_unstable +EXPORT_SYMBOL_GPL vmlinux 0x5f316348 device_register +EXPORT_SYMBOL_GPL vmlinux 0x5f408bac klist_next +EXPORT_SYMBOL_GPL vmlinux 0x5f85f4b2 fsstack_copy_inode_size +EXPORT_SYMBOL_GPL vmlinux 0x5fea940b hrtimer_forward +EXPORT_SYMBOL_GPL vmlinux 0x6091797f synchronize_rcu +EXPORT_SYMBOL_GPL vmlinux 0x609f8684 inotify_dentry_parent_queue_event +EXPORT_SYMBOL_GPL vmlinux 0x60a13e90 rcu_barrier +EXPORT_SYMBOL_GPL vmlinux 0x60c6355a devm_kfree +EXPORT_SYMBOL_GPL vmlinux 0x60e9ccff platform_device_register_simple +EXPORT_SYMBOL_GPL vmlinux 0x6115252e __blk_put_request +EXPORT_SYMBOL_GPL vmlinux 0x61a5a2ac blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0x629592ee sg_scsi_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x62f8f675 rtc_device_register +EXPORT_SYMBOL_GPL vmlinux 0x63390149 put_pid +EXPORT_SYMBOL_GPL vmlinux 0x633f14ca transport_configure_device +EXPORT_SYMBOL_GPL vmlinux 0x63ae27d6 add_nops +EXPORT_SYMBOL_GPL vmlinux 0x641aa50e mmput +EXPORT_SYMBOL_GPL vmlinux 0x644cf8d9 spi_unregister_master +EXPORT_SYMBOL_GPL vmlinux 0x6454c354 tty_find_polling_driver +EXPORT_SYMBOL_GPL vmlinux 0x64a52b7f devres_remove +EXPORT_SYMBOL_GPL vmlinux 0x64d6f039 find_vpid +EXPORT_SYMBOL_GPL vmlinux 0x64f3e683 unregister_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0x64fd27e0 devres_find +EXPORT_SYMBOL_GPL vmlinux 0x650491e2 inet_csk_search_req +EXPORT_SYMBOL_GPL vmlinux 0x6566c9c0 __crypto_alloc_tfm +EXPORT_SYMBOL_GPL vmlinux 0x65ccb6f0 call_netevent_notifiers +EXPORT_SYMBOL_GPL vmlinux 0x65d6d0f0 gpio_direction_input +EXPORT_SYMBOL_GPL vmlinux 0x6610ad99 synchronize_srcu +EXPORT_SYMBOL_GPL vmlinux 0x661601de sprint_symbol +EXPORT_SYMBOL_GPL vmlinux 0x66b2a859 nr_free_buffer_pages +EXPORT_SYMBOL_GPL vmlinux 0x66d87d38 symbol_put_addr +EXPORT_SYMBOL_GPL vmlinux 0x67499481 tty_mode_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x67955ce6 profile_hits +EXPORT_SYMBOL_GPL vmlinux 0x6795bfaf uhci_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0x67b2db11 sysdev_class_remove_file +EXPORT_SYMBOL_GPL vmlinux 0x67fc7e64 devres_release_group +EXPORT_SYMBOL_GPL vmlinux 0x6834cc83 klist_add_after +EXPORT_SYMBOL_GPL vmlinux 0x683e0bf4 pci_slots_kset +EXPORT_SYMBOL_GPL vmlinux 0x686c703f xfrm_count_auth_supported +EXPORT_SYMBOL_GPL vmlinux 0x6892088c unregister_pm_notifier +EXPORT_SYMBOL_GPL vmlinux 0x69064c59 bus_get_kset +EXPORT_SYMBOL_GPL vmlinux 0x691884ef pv_apic_ops +EXPORT_SYMBOL_GPL vmlinux 0x691cd011 page_cache_sync_readahead +EXPORT_SYMBOL_GPL vmlinux 0x6979bcf3 kern_mount_data +EXPORT_SYMBOL_GPL vmlinux 0x698bb9e2 relay_close +EXPORT_SYMBOL_GPL vmlinux 0x69a6879c rt_mutex_lock_interruptible +EXPORT_SYMBOL_GPL vmlinux 0x6a25a804 __crypto_alg_lookup +EXPORT_SYMBOL_GPL vmlinux 0x6a36196a do_add_mount +EXPORT_SYMBOL_GPL vmlinux 0x6a4c85fa destroy_workqueue +EXPORT_SYMBOL_GPL vmlinux 0x6a73a650 attribute_container_classdev_to_container +EXPORT_SYMBOL_GPL vmlinux 0x6a99047f isa_register_driver +EXPORT_SYMBOL_GPL vmlinux 0x6b005aeb rtc_update_irq +EXPORT_SYMBOL_GPL vmlinux 0x6b07a368 klist_add_before +EXPORT_SYMBOL_GPL vmlinux 0x6bb6a731 pci_cleanup_aer_uncorrect_error_status +EXPORT_SYMBOL_GPL vmlinux 0x6bd59712 platform_device_del +EXPORT_SYMBOL_GPL vmlinux 0x6c05273e securityfs_create_file +EXPORT_SYMBOL_GPL vmlinux 0x6c11059b __srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x6c49c4f2 clockevents_notify +EXPORT_SYMBOL_GPL vmlinux 0x6c8d5ae8 __gpio_get_value +EXPORT_SYMBOL_GPL vmlinux 0x6c912da4 inet_csk_reqsk_queue_prune +EXPORT_SYMBOL_GPL vmlinux 0x6db07ec4 simple_attr_write +EXPORT_SYMBOL_GPL vmlinux 0x6e3a8f2e cpufreq_register_governor +EXPORT_SYMBOL_GPL vmlinux 0x6e6bc776 inet_csk_reqsk_queue_hash_add +EXPORT_SYMBOL_GPL vmlinux 0x6e8a6629 proc_net_mkdir +EXPORT_SYMBOL_GPL vmlinux 0x6ebe305d raw_seq_stop +EXPORT_SYMBOL_GPL vmlinux 0x6f0d8020 inet_csk_listen_stop +EXPORT_SYMBOL_GPL vmlinux 0x6f9c2efe marker_probe_cb +EXPORT_SYMBOL_GPL vmlinux 0x6ffb5b60 klist_add_tail +EXPORT_SYMBOL_GPL vmlinux 0x7037d79d k8_flush_garts +EXPORT_SYMBOL_GPL vmlinux 0x707eba47 blkdev_driver_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x70e5576f rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0x70fe51a6 kernel_kobj +EXPORT_SYMBOL_GPL vmlinux 0x716a763d input_ff_destroy +EXPORT_SYMBOL_GPL vmlinux 0x71b99c36 crypto_init_spawn +EXPORT_SYMBOL_GPL vmlinux 0x71c8bc95 kgdb_unregister_io_module +EXPORT_SYMBOL_GPL vmlinux 0x725843fb __rtnl_register +EXPORT_SYMBOL_GPL vmlinux 0x7278d328 all_vm_events +EXPORT_SYMBOL_GPL vmlinux 0x72e0a6be crypto_enqueue_request +EXPORT_SYMBOL_GPL vmlinux 0x7308cfc6 tcp_is_cwnd_limited +EXPORT_SYMBOL_GPL vmlinux 0x73201149 klist_iter_init_node +EXPORT_SYMBOL_GPL vmlinux 0x7321dc17 crypto_larval_kill +EXPORT_SYMBOL_GPL vmlinux 0x73b09385 xfrm_audit_policy_add +EXPORT_SYMBOL_GPL vmlinux 0x73b1f76d do_posix_clock_nosettime +EXPORT_SYMBOL_GPL vmlinux 0x73d01f94 platform_driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0x743d793c blk_trace_remove +EXPORT_SYMBOL_GPL vmlinux 0x744087e5 ip_route_output_flow +EXPORT_SYMBOL_GPL vmlinux 0x74740576 sysfs_remove_group +EXPORT_SYMBOL_GPL vmlinux 0x74abdafa task_handoff_register +EXPORT_SYMBOL_GPL vmlinux 0x74d61a4d get_dcookie +EXPORT_SYMBOL_GPL vmlinux 0x74deb10c used_vectors +EXPORT_SYMBOL_GPL vmlinux 0x7521afb6 leave_mm +EXPORT_SYMBOL_GPL vmlinux 0x7543a836 kobject_init_and_add +EXPORT_SYMBOL_GPL vmlinux 0x7568b92e register_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x75c00c51 driver_add_kobj +EXPORT_SYMBOL_GPL vmlinux 0x75c8a11c inet_twdr_twkill_work +EXPORT_SYMBOL_GPL vmlinux 0x75e8f3c3 crypto_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0x761e7573 relay_switch_subbuf +EXPORT_SYMBOL_GPL vmlinux 0x7626e1ac bus_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x77aae80d security_inode_permission +EXPORT_SYMBOL_GPL vmlinux 0x77dbeea8 page_cache_async_readahead +EXPORT_SYMBOL_GPL vmlinux 0x78168898 __inet_inherit_port +EXPORT_SYMBOL_GPL vmlinux 0x78e8c6b8 crypto_register_alg +EXPORT_SYMBOL_GPL vmlinux 0x7a4c1438 pv_info +EXPORT_SYMBOL_GPL vmlinux 0x7ade3e90 platform_device_add +EXPORT_SYMBOL_GPL vmlinux 0x7b0b4551 sysdev_show_ulong +EXPORT_SYMBOL_GPL vmlinux 0x7b1d544d edac_handler_set +EXPORT_SYMBOL_GPL vmlinux 0x7b34ff93 fib_rules_cleanup_ops +EXPORT_SYMBOL_GPL vmlinux 0x7c084e78 platform_device_add_data +EXPORT_SYMBOL_GPL vmlinux 0x7c7bcf38 register_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0x7cd551b3 led_trigger_show +EXPORT_SYMBOL_GPL vmlinux 0x7cfc08c4 device_del +EXPORT_SYMBOL_GPL vmlinux 0x7d0474ed queue_work +EXPORT_SYMBOL_GPL vmlinux 0x7d28f410 firmware_kobj +EXPORT_SYMBOL_GPL vmlinux 0x7d384730 debugfs_remove_recursive +EXPORT_SYMBOL_GPL vmlinux 0x7d3a1d25 seq_open_net +EXPORT_SYMBOL_GPL vmlinux 0x7da8d037 marker_probe_register +EXPORT_SYMBOL_GPL vmlinux 0x7dc37d96 device_schedule_callback_owner +EXPORT_SYMBOL_GPL vmlinux 0x7dc5d0b6 crypto_unregister_notifier +EXPORT_SYMBOL_GPL vmlinux 0x7dd3e4bd devres_open_group +EXPORT_SYMBOL_GPL vmlinux 0x7e084cb6 kobject_create_and_add +EXPORT_SYMBOL_GPL vmlinux 0x7e60611e mnt_want_write +EXPORT_SYMBOL_GPL vmlinux 0x7e698a51 unregister_jprobes +EXPORT_SYMBOL_GPL vmlinux 0x7f19c836 unlock_policy_rwsem_write +EXPORT_SYMBOL_GPL vmlinux 0x7f9af2f3 device_find_child +EXPORT_SYMBOL_GPL vmlinux 0x7fbb150d debugfs_remove +EXPORT_SYMBOL_GPL vmlinux 0x7ff10ccf raw_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x80353106 gpiochip_is_requested +EXPORT_SYMBOL_GPL vmlinux 0x8039d043 selinux_secmark_relabel_packet_permission +EXPORT_SYMBOL_GPL vmlinux 0x8093e65f kobject_get_path +EXPORT_SYMBOL_GPL vmlinux 0x80ee55c3 selinux_secmark_refcount_inc +EXPORT_SYMBOL_GPL vmlinux 0x8114870b vfs_setxattr +EXPORT_SYMBOL_GPL vmlinux 0x812f47e6 pciserial_resume_ports +EXPORT_SYMBOL_GPL vmlinux 0x814a99d6 blkdev_ioctl +EXPORT_SYMBOL_GPL vmlinux 0x818e30ec platform_driver_register +EXPORT_SYMBOL_GPL vmlinux 0x81e634d0 class_interface_register +EXPORT_SYMBOL_GPL vmlinux 0x8226642f __gpio_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x8231500b tty_buffer_request_room +EXPORT_SYMBOL_GPL vmlinux 0x826360fd do_posix_clock_nonanosleep +EXPORT_SYMBOL_GPL vmlinux 0x8288fab6 __mnt_is_readonly +EXPORT_SYMBOL_GPL vmlinux 0x82d79b51 sysctl_vfs_cache_pressure +EXPORT_SYMBOL_GPL vmlinux 0x82f5273b register_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0x82f776b7 gpio_export +EXPORT_SYMBOL_GPL vmlinux 0x84a1d49b xfrm_audit_state_notfound +EXPORT_SYMBOL_GPL vmlinux 0x84f004d7 led_trigger_remove +EXPORT_SYMBOL_GPL vmlinux 0x85c10896 rcu_batches_completed_bh +EXPORT_SYMBOL_GPL vmlinux 0x85d7edfd hpet_set_periodic_freq +EXPORT_SYMBOL_GPL vmlinux 0x85e3b9ce vfs_getxattr +EXPORT_SYMBOL_GPL vmlinux 0x85e5a3db ktime_get_ts +EXPORT_SYMBOL_GPL vmlinux 0x868784cb __symbol_get +EXPORT_SYMBOL_GPL vmlinux 0x86b1667d hwrng_unregister +EXPORT_SYMBOL_GPL vmlinux 0x86d9791b sysdev_class_register +EXPORT_SYMBOL_GPL vmlinux 0x870404b8 crypto_chain +EXPORT_SYMBOL_GPL vmlinux 0x871d7842 generic_fh_to_parent +EXPORT_SYMBOL_GPL vmlinux 0x873fbaea edac_atomic_assert_error +EXPORT_SYMBOL_GPL vmlinux 0x876b550b spi_register_master +EXPORT_SYMBOL_GPL vmlinux 0x87754115 raw_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x878398c0 driver_attach +EXPORT_SYMBOL_GPL vmlinux 0x8799a837 default_backing_dev_info +EXPORT_SYMBOL_GPL vmlinux 0x880b189a __atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x8810ad5e crypto_xor +EXPORT_SYMBOL_GPL vmlinux 0x88405dce tcp_reno_min_cwnd +EXPORT_SYMBOL_GPL vmlinux 0x885142a6 nf_net_netfilter_sysctl_path +EXPORT_SYMBOL_GPL vmlinux 0x886736fc olpc_platform_info +EXPORT_SYMBOL_GPL vmlinux 0x89c4c746 inotify_inode_is_dead +EXPORT_SYMBOL_GPL vmlinux 0x89d887ad device_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8a33d6b4 kobject_uevent_env +EXPORT_SYMBOL_GPL vmlinux 0x8abed13d xfrm_aead_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x8b07c054 rt_mutex_unlock +EXPORT_SYMBOL_GPL vmlinux 0x8b7deab3 rt_mutex_destroy +EXPORT_SYMBOL_GPL vmlinux 0x8c3b9ab8 register_kretprobe +EXPORT_SYMBOL_GPL vmlinux 0x8ceae58a pci_find_ext_capability +EXPORT_SYMBOL_GPL vmlinux 0x8d5d1bd1 user_update +EXPORT_SYMBOL_GPL vmlinux 0x8d6a3750 preempt_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0x8da17b42 scatterwalk_copychunks +EXPORT_SYMBOL_GPL vmlinux 0x8dd4ae9a tcp_init_congestion_ops +EXPORT_SYMBOL_GPL vmlinux 0x8dd78d25 blocking_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0x8e1817a0 inotify_add_watch +EXPORT_SYMBOL_GPL vmlinux 0x8e6d9a0a user_read +EXPORT_SYMBOL_GPL vmlinux 0x8e788610 __sock_recv_timestamp +EXPORT_SYMBOL_GPL vmlinux 0x8eb58c6e __wake_up_sync +EXPORT_SYMBOL_GPL vmlinux 0x8f145f94 crypto_hash_type +EXPORT_SYMBOL_GPL vmlinux 0x8f6cee77 __round_jiffies_relative +EXPORT_SYMBOL_GPL vmlinux 0x8f7f9560 debugfs_create_u32 +EXPORT_SYMBOL_GPL vmlinux 0x8fd5c28c devres_get +EXPORT_SYMBOL_GPL vmlinux 0x8ff8dbcd blocking_notifier_chain_cond_register +EXPORT_SYMBOL_GPL vmlinux 0x9009602a acpi_bus_get_ejd +EXPORT_SYMBOL_GPL vmlinux 0x906b805e srcu_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x90a1004a crypto_has_alg +EXPORT_SYMBOL_GPL vmlinux 0x90fdfbff fb_deferred_io_open +EXPORT_SYMBOL_GPL vmlinux 0x9146276a device_add +EXPORT_SYMBOL_GPL vmlinux 0x91464a76 led_trigger_unregister_simple +EXPORT_SYMBOL_GPL vmlinux 0x9159b9d6 profile_event_register +EXPORT_SYMBOL_GPL vmlinux 0x91806d66 inet_twsk_put +EXPORT_SYMBOL_GPL vmlinux 0x91c9a0d4 attribute_container_unregister +EXPORT_SYMBOL_GPL vmlinux 0x91dacaa2 acpi_processor_ffh_cstate_probe +EXPORT_SYMBOL_GPL vmlinux 0x91db4476 platform_device_add_resources +EXPORT_SYMBOL_GPL vmlinux 0x9241c3ee device_power_down +EXPORT_SYMBOL_GPL vmlinux 0x9242fda6 skb_cow_data +EXPORT_SYMBOL_GPL vmlinux 0x92445aee hrtimer_get_res +EXPORT_SYMBOL_GPL vmlinux 0x926bcccd driver_find_device +EXPORT_SYMBOL_GPL vmlinux 0x92fb217b dcookie_unregister +EXPORT_SYMBOL_GPL vmlinux 0x933740ca cancel_work_sync +EXPORT_SYMBOL_GPL vmlinux 0x93d2422d snmp_mib_free +EXPORT_SYMBOL_GPL vmlinux 0x940e412b inotify_destroy +EXPORT_SYMBOL_GPL vmlinux 0x942c1704 cleanup_srcu_struct +EXPORT_SYMBOL_GPL vmlinux 0x94d1738f set_cpus_allowed_ptr +EXPORT_SYMBOL_GPL vmlinux 0x94d6345e sysfs_schedule_callback +EXPORT_SYMBOL_GPL vmlinux 0x94e3a15d relay_buf_full +EXPORT_SYMBOL_GPL vmlinux 0x952664c5 do_exit +EXPORT_SYMBOL_GPL vmlinux 0x95665b14 fs_kobj +EXPORT_SYMBOL_GPL vmlinux 0x956a91ba gpio_get_value_cansleep +EXPORT_SYMBOL_GPL vmlinux 0x956e6a84 map_vm_area +EXPORT_SYMBOL_GPL vmlinux 0x9577271c hpet_rtc_interrupt +EXPORT_SYMBOL_GPL vmlinux 0x961758c4 pci_update_slot_number +EXPORT_SYMBOL_GPL vmlinux 0x961a8cd3 unlock_policy_rwsem_read +EXPORT_SYMBOL_GPL vmlinux 0x96436e4a rtnl_put_cacheinfo +EXPORT_SYMBOL_GPL vmlinux 0x969e37e5 find_get_pid +EXPORT_SYMBOL_GPL vmlinux 0x96cbcf31 pm_qos_add_notifier +EXPORT_SYMBOL_GPL vmlinux 0x97ddbfff dev_set_name +EXPORT_SYMBOL_GPL vmlinux 0x97f321b1 pci_bus_max_busnr +EXPORT_SYMBOL_GPL vmlinux 0x9833bc0c hvc_kick +EXPORT_SYMBOL_GPL vmlinux 0x986f95ee vlan_dev_real_dev +EXPORT_SYMBOL_GPL vmlinux 0x98927bf9 inet_csk_get_port +EXPORT_SYMBOL_GPL vmlinux 0x99029a26 crypto_mod_get +EXPORT_SYMBOL_GPL vmlinux 0x990ea66f tcp_unregister_congestion_control +EXPORT_SYMBOL_GPL vmlinux 0x99498f93 xfrm_audit_state_replay_overflow +EXPORT_SYMBOL_GPL vmlinux 0x995d1071 prof_on +EXPORT_SYMBOL_GPL vmlinux 0x998b6f7a audit_log_d_path +EXPORT_SYMBOL_GPL vmlinux 0x9a11a0fc crypto_attr_alg_name +EXPORT_SYMBOL_GPL vmlinux 0x9a2392ff acpi_bus_trim +EXPORT_SYMBOL_GPL vmlinux 0x9a398f5c xfrm_ealg_get_byname +EXPORT_SYMBOL_GPL vmlinux 0x9a665632 pci_intx +EXPORT_SYMBOL_GPL vmlinux 0x9b3765c1 init_user_ns +EXPORT_SYMBOL_GPL vmlinux 0x9b5003c4 inotify_init +EXPORT_SYMBOL_GPL vmlinux 0x9ba0501e unregister_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0x9c83b07b blk_rq_bytes +EXPORT_SYMBOL_GPL vmlinux 0x9cac8c04 proc_net_fops_create +EXPORT_SYMBOL_GPL vmlinux 0x9cb8037b xfrm_count_enc_supported +EXPORT_SYMBOL_GPL vmlinux 0x9d532b49 elv_unregister +EXPORT_SYMBOL_GPL vmlinux 0x9d957902 bus_find_device_by_name +EXPORT_SYMBOL_GPL vmlinux 0x9e0c1f3b device_attach +EXPORT_SYMBOL_GPL vmlinux 0x9e711ad2 pm_qos_requirement +EXPORT_SYMBOL_GPL vmlinux 0x9e8fcfea uart_set_options +EXPORT_SYMBOL_GPL vmlinux 0x9eae490d device_create +EXPORT_SYMBOL_GPL vmlinux 0x9f831b60 mnt_drop_write +EXPORT_SYMBOL_GPL vmlinux 0x9fce80db fb_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0x9ffe62a5 class_find_device +EXPORT_SYMBOL_GPL vmlinux 0xa0255440 net_ipv4_ctl_path +EXPORT_SYMBOL_GPL vmlinux 0xa089f7f8 bus_register_notifier +EXPORT_SYMBOL_GPL vmlinux 0xa1596d98 acpi_processor_ffh_cstate_enter +EXPORT_SYMBOL_GPL vmlinux 0xa18b5068 inet_hash_connect +EXPORT_SYMBOL_GPL vmlinux 0xa285c099 tty_wakeup +EXPORT_SYMBOL_GPL vmlinux 0xa2e1bb99 register_pernet_subsys +EXPORT_SYMBOL_GPL vmlinux 0xa2e67f08 acpi_bus_generate_proc_event4 +EXPORT_SYMBOL_GPL vmlinux 0xa3449283 blk_trace_startstop +EXPORT_SYMBOL_GPL vmlinux 0xa39d98e7 led_trigger_event +EXPORT_SYMBOL_GPL vmlinux 0xa3fc96f0 marker_probe_cb_noarg +EXPORT_SYMBOL_GPL vmlinux 0xa452c297 hpet_mask_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa4ced33e debugfs_create_u64 +EXPORT_SYMBOL_GPL vmlinux 0xa52ad62a __cpufreq_driver_getavg +EXPORT_SYMBOL_GPL vmlinux 0xa5bf5c3e pm_qos_add_requirement +EXPORT_SYMBOL_GPL vmlinux 0xa5c36cec inotify_unmount_inodes +EXPORT_SYMBOL_GPL vmlinux 0xa5dcc8a0 crypto_ahash_type +EXPORT_SYMBOL_GPL vmlinux 0xa64bd0bd cpuidle_enable_device +EXPORT_SYMBOL_GPL vmlinux 0xa8e73223 tty_encode_baud_rate +EXPORT_SYMBOL_GPL vmlinux 0xa8f59416 gpio_direction_output +EXPORT_SYMBOL_GPL vmlinux 0xa9126bff hpet_set_rtc_irq_bit +EXPORT_SYMBOL_GPL vmlinux 0xa956a362 register_jprobe +EXPORT_SYMBOL_GPL vmlinux 0xa963f49c tcp_orphan_count +EXPORT_SYMBOL_GPL vmlinux 0xa975a326 __mmdrop +EXPORT_SYMBOL_GPL vmlinux 0xa9c0ac91 pci_stop_bus_device +EXPORT_SYMBOL_GPL vmlinux 0xa9c530b8 unregister_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xa9df60c5 crypto_hash_walk_done +EXPORT_SYMBOL_GPL vmlinux 0xa9f0a2e7 vfs_removexattr +EXPORT_SYMBOL_GPL vmlinux 0xa9f3808e cpufreq_unregister_governor +EXPORT_SYMBOL_GPL vmlinux 0xa9fc6d8b spi_busnum_to_master +EXPORT_SYMBOL_GPL vmlinux 0xaa2a72bf __iowrite64_copy +EXPORT_SYMBOL_GPL vmlinux 0xaa3e2962 dnotify_parent +EXPORT_SYMBOL_GPL vmlinux 0xaa59b5cb rtc_set_time +EXPORT_SYMBOL_GPL vmlinux 0xaa8c4696 cpu_clock +EXPORT_SYMBOL_GPL vmlinux 0xab5af075 xfrm_output_resume +EXPORT_SYMBOL_GPL vmlinux 0xabe6b04f blk_end_bidi_request +EXPORT_SYMBOL_GPL vmlinux 0xac0292be blocking_notifier_chain_unregister +EXPORT_SYMBOL_GPL vmlinux 0xac2f6db2 tcp_death_row +EXPORT_SYMBOL_GPL vmlinux 0xac4915e7 disk_round_stats +EXPORT_SYMBOL_GPL vmlinux 0xac8e7e1e console_drivers +EXPORT_SYMBOL_GPL vmlinux 0xacc19485 ibft_addr +EXPORT_SYMBOL_GPL vmlinux 0xaccfc678 cpu_bit_bitmap +EXPORT_SYMBOL_GPL vmlinux 0xad0c8c9e skb_to_sgvec +EXPORT_SYMBOL_GPL vmlinux 0xad23ab7d pci_restore_msi_state +EXPORT_SYMBOL_GPL vmlinux 0xadff4867 xfrm_output +EXPORT_SYMBOL_GPL vmlinux 0xae0c87ee pm_qos_remove_notifier +EXPORT_SYMBOL_GPL vmlinux 0xaeb7f977 __blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xaef132da register_net_sysctl_rotable +EXPORT_SYMBOL_GPL vmlinux 0xaf16ec38 cpuidle_register_driver +EXPORT_SYMBOL_GPL vmlinux 0xaf3c82fb debugfs_create_symlink +EXPORT_SYMBOL_GPL vmlinux 0xaf5a02a6 securityfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0xafc430b6 zap_vma_ptes +EXPORT_SYMBOL_GPL vmlinux 0xb021c3d3 devres_add +EXPORT_SYMBOL_GPL vmlinux 0xb08cd71a screen_glyph +EXPORT_SYMBOL_GPL vmlinux 0xb0a45ce0 init_pid_ns +EXPORT_SYMBOL_GPL vmlinux 0xb0ab9f8c flush_work +EXPORT_SYMBOL_GPL vmlinux 0xb10d55bc cn_netlink_send +EXPORT_SYMBOL_GPL vmlinux 0xb120ab95 klist_remove +EXPORT_SYMBOL_GPL vmlinux 0xb1acbcce rcu_barrier_sched +EXPORT_SYMBOL_GPL vmlinux 0xb27005f5 device_suspend +EXPORT_SYMBOL_GPL vmlinux 0xb28c5cad raw_seq_start +EXPORT_SYMBOL_GPL vmlinux 0xb305fa4b bus_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xb313a59e unregister_kprobe +EXPORT_SYMBOL_GPL vmlinux 0xb3253ed9 hpet_rtc_timer_init +EXPORT_SYMBOL_GPL vmlinux 0xb4003cb8 platform_driver_probe +EXPORT_SYMBOL_GPL vmlinux 0xb45e64d3 inet_hash +EXPORT_SYMBOL_GPL vmlinux 0xb4c3ea18 bus_register +EXPORT_SYMBOL_GPL vmlinux 0xb4dad6b1 pci_unblock_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0xb4ea7cf7 kgdb_connected +EXPORT_SYMBOL_GPL vmlinux 0xb502d19c input_ff_upload +EXPORT_SYMBOL_GPL vmlinux 0xb51fbd64 edac_op_state +EXPORT_SYMBOL_GPL vmlinux 0xb53ae573 cpu_idle_wait +EXPORT_SYMBOL_GPL vmlinux 0xb58adfce crypto_shoot_alg +EXPORT_SYMBOL_GPL vmlinux 0xb5ab56f5 hvc_poll +EXPORT_SYMBOL_GPL vmlinux 0xb5c0fecd crypto_attr_alg +EXPORT_SYMBOL_GPL vmlinux 0xb5fcc060 rtc_class_open +EXPORT_SYMBOL_GPL vmlinux 0xb629c036 get_cpu_sysdev +EXPORT_SYMBOL_GPL vmlinux 0xb63550f5 __i2c_board_lock +EXPORT_SYMBOL_GPL vmlinux 0xb65091b3 selinux_secmark_refcount_dec +EXPORT_SYMBOL_GPL vmlinux 0xb7249842 platform_device_register +EXPORT_SYMBOL_GPL vmlinux 0xb7d7c12e hpet_set_alarm_time +EXPORT_SYMBOL_GPL vmlinux 0xb89da748 debugfs_rename +EXPORT_SYMBOL_GPL vmlinux 0xb9eb3aa9 add_uevent_var +EXPORT_SYMBOL_GPL vmlinux 0xba402c15 sysdev_register +EXPORT_SYMBOL_GPL vmlinux 0xba9b3a6f class_destroy +EXPORT_SYMBOL_GPL vmlinux 0xbb502333 mm_kobj +EXPORT_SYMBOL_GPL vmlinux 0xbbb98859 edid_info +EXPORT_SYMBOL_GPL vmlinux 0xbc2eb3a5 power_supply_am_i_supplied +EXPORT_SYMBOL_GPL vmlinux 0xbd415f26 rt_mutex_lock +EXPORT_SYMBOL_GPL vmlinux 0xbdcce1b1 register_kprobe +EXPORT_SYMBOL_GPL vmlinux 0xbf14bca1 crypto_drop_spawn +EXPORT_SYMBOL_GPL vmlinux 0xbfa1d5ea pci_enable_pcie_error_reporting +EXPORT_SYMBOL_GPL vmlinux 0xbfd1996d class_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xbfec1eaa register_kretprobes +EXPORT_SYMBOL_GPL vmlinux 0xc06bcadb spi_alloc_device +EXPORT_SYMBOL_GPL vmlinux 0xc097eb8e hrtimer_get_remaining +EXPORT_SYMBOL_GPL vmlinux 0xc0cb4cb6 ip_local_out +EXPORT_SYMBOL_GPL vmlinux 0xc0d73913 elv_register +EXPORT_SYMBOL_GPL vmlinux 0xc0ed34aa bus_for_each_drv +EXPORT_SYMBOL_GPL vmlinux 0xc16908d1 tty_put_char +EXPORT_SYMBOL_GPL vmlinux 0xc1b9670d leds_list_lock +EXPORT_SYMBOL_GPL vmlinux 0xc1e006a7 debugfs_create_u16 +EXPORT_SYMBOL_GPL vmlinux 0xc31be7c8 put_device +EXPORT_SYMBOL_GPL vmlinux 0xc34efe27 snmp_fold_field +EXPORT_SYMBOL_GPL vmlinux 0xc36420ce transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0xc3f2132a crypto_free_tfm +EXPORT_SYMBOL_GPL vmlinux 0xc493e76c platform_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xc512626a __supported_pte_mask +EXPORT_SYMBOL_GPL vmlinux 0xc574fd8a transport_add_device +EXPORT_SYMBOL_GPL vmlinux 0xc58cdb60 lookup_address +EXPORT_SYMBOL_GPL vmlinux 0xc63db010 unregister_pernet_device +EXPORT_SYMBOL_GPL vmlinux 0xc6b402e5 __percpu_alloc_mask +EXPORT_SYMBOL_GPL vmlinux 0xc6cabb03 device_remove_file +EXPORT_SYMBOL_GPL vmlinux 0xc6ff98e7 xattr_getsecurity +EXPORT_SYMBOL_GPL vmlinux 0xc738a05c rtc_read_time +EXPORT_SYMBOL_GPL vmlinux 0xc7ec11f6 atomic_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xc81d40a6 hrtimer_cancel +EXPORT_SYMBOL_GPL vmlinux 0xc87c1f84 ktime_get +EXPORT_SYMBOL_GPL vmlinux 0xc87e487a sched_clock_idle_sleep_event +EXPORT_SYMBOL_GPL vmlinux 0xc953f147 platform_get_resource +EXPORT_SYMBOL_GPL vmlinux 0xc9561772 fb_destroy_modelist +EXPORT_SYMBOL_GPL vmlinux 0xca23cca2 fib_rules_unregister +EXPORT_SYMBOL_GPL vmlinux 0xca262246 __blk_end_request +EXPORT_SYMBOL_GPL vmlinux 0xca655558 inet_csk_bind_conflict +EXPORT_SYMBOL_GPL vmlinux 0xcabe04de cpuidle_resume_and_unlock +EXPORT_SYMBOL_GPL vmlinux 0xcb074489 cpuidle_disable_device +EXPORT_SYMBOL_GPL vmlinux 0xcb7aca93 get_user_pages_fast +EXPORT_SYMBOL_GPL vmlinux 0xcbdbf956 device_rename +EXPORT_SYMBOL_GPL vmlinux 0xcbf20127 klist_iter_init +EXPORT_SYMBOL_GPL vmlinux 0xcc1f1c3d inet_twdr_hangman +EXPORT_SYMBOL_GPL vmlinux 0xcc442410 inet_unhash +EXPORT_SYMBOL_GPL vmlinux 0xcc9e321c __inet_hash_nolisten +EXPORT_SYMBOL_GPL vmlinux 0xcd774092 pci_block_user_cfg_access +EXPORT_SYMBOL_GPL vmlinux 0xcdd6550e register_kprobes +EXPORT_SYMBOL_GPL vmlinux 0xce0b8f2f uhci_check_and_reset_hc +EXPORT_SYMBOL_GPL vmlinux 0xce8ebc6a pci_set_pcie_reset_state +EXPORT_SYMBOL_GPL vmlinux 0xcea9282a inet6_lookup_listener +EXPORT_SYMBOL_GPL vmlinux 0xcedd5d73 rt_mutex_trylock +EXPORT_SYMBOL_GPL vmlinux 0xcef1e556 inet_diag_unregister +EXPORT_SYMBOL_GPL vmlinux 0xcf0bfd12 start_thread +EXPORT_SYMBOL_GPL vmlinux 0xcf6c7579 tcp_twsk_destructor +EXPORT_SYMBOL_GPL vmlinux 0xcfcc83ad register_vt_notifier +EXPORT_SYMBOL_GPL vmlinux 0xd027a07d marker_probe_unregister +EXPORT_SYMBOL_GPL vmlinux 0xd03c7700 secure_ipv4_port_ephemeral +EXPORT_SYMBOL_GPL vmlinux 0xd05984d5 inet_csk_listen_start +EXPORT_SYMBOL_GPL vmlinux 0xd06c4782 input_ff_event +EXPORT_SYMBOL_GPL vmlinux 0xd0c05159 emergency_restart +EXPORT_SYMBOL_GPL vmlinux 0xd0c5d2db posix_timer_event +EXPORT_SYMBOL_GPL vmlinux 0xd0fc9376 preempt_notifier_register +EXPORT_SYMBOL_GPL vmlinux 0xd124e095 pcie_port_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xd12ac59b olpc_ec_cmd +EXPORT_SYMBOL_GPL vmlinux 0xd16712f3 crypto_check_attr_type +EXPORT_SYMBOL_GPL vmlinux 0xd177204e spi_alloc_master +EXPORT_SYMBOL_GPL vmlinux 0xd1aabf25 device_for_each_child +EXPORT_SYMBOL_GPL vmlinux 0xd1c672a1 hwmon_device_register +EXPORT_SYMBOL_GPL vmlinux 0xd1f8dee0 bus_rescan_devices +EXPORT_SYMBOL_GPL vmlinux 0xd30d9094 audit_log_untrustedstring +EXPORT_SYMBOL_GPL vmlinux 0xd5831476 uart_console_write +EXPORT_SYMBOL_GPL vmlinux 0xd6ac805b inet_twsk_schedule +EXPORT_SYMBOL_GPL vmlinux 0xd7ab71cd rtc_read_alarm +EXPORT_SYMBOL_GPL vmlinux 0xd7cfd737 alloc_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xd7d0159d power_supply_register +EXPORT_SYMBOL_GPL vmlinux 0xd7d79132 put_online_cpus +EXPORT_SYMBOL_GPL vmlinux 0xd8111a87 tcp_done +EXPORT_SYMBOL_GPL vmlinux 0xd89f2217 bus_for_each_dev +EXPORT_SYMBOL_GPL vmlinux 0xd8a88de3 debugfs_create_blob +EXPORT_SYMBOL_GPL vmlinux 0xd8d07527 relay_file_operations +EXPORT_SYMBOL_GPL vmlinux 0xd94ba7dd sysfs_add_file_to_group +EXPORT_SYMBOL_GPL vmlinux 0xda050ecc inotify_find_update_watch +EXPORT_SYMBOL_GPL vmlinux 0xda6fb5f2 platform_device_alloc +EXPORT_SYMBOL_GPL vmlinux 0xdab20de6 inverse_translate +EXPORT_SYMBOL_GPL vmlinux 0xdaf4dfb3 fb_mode_option +EXPORT_SYMBOL_GPL vmlinux 0xdb2a1107 get_driver +EXPORT_SYMBOL_GPL vmlinux 0xdbaf10b1 power_supply_changed +EXPORT_SYMBOL_GPL vmlinux 0xdbeabdc8 tty_ldisc_flush +EXPORT_SYMBOL_GPL vmlinux 0xdc046069 driver_find +EXPORT_SYMBOL_GPL vmlinux 0xdcd3fbc3 pci_scan_child_bus +EXPORT_SYMBOL_GPL vmlinux 0xdcf09671 sysctl_pathname +EXPORT_SYMBOL_GPL vmlinux 0xdcf6dd93 do_sync_mapping_range +EXPORT_SYMBOL_GPL vmlinux 0xdd3f8ac7 sysfs_chmod_file +EXPORT_SYMBOL_GPL vmlinux 0xdd4c868b tcp_reno_ssthresh +EXPORT_SYMBOL_GPL vmlinux 0xdd565454 inet_ctl_sock_create +EXPORT_SYMBOL_GPL vmlinux 0xdd5c4942 srcu_notifier_chain_register +EXPORT_SYMBOL_GPL vmlinux 0xddb56121 mmu_notifier_unregister +EXPORT_SYMBOL_GPL vmlinux 0xddc7b05f tcp_twsk_unique +EXPORT_SYMBOL_GPL vmlinux 0xdf317d9f vfs_test_lock +EXPORT_SYMBOL_GPL vmlinux 0xdf3c19ec cn_add_callback +EXPORT_SYMBOL_GPL vmlinux 0xdf6e6002 vfs_lock_file +EXPORT_SYMBOL_GPL vmlinux 0xe0406b5a blocking_notifier_call_chain +EXPORT_SYMBOL_GPL vmlinux 0xe0622457 crypto_unregister_template +EXPORT_SYMBOL_GPL vmlinux 0xe0bcdba1 nf_unregister_queue_handlers +EXPORT_SYMBOL_GPL vmlinux 0xe0beaab6 cpufreq_cpu_put +EXPORT_SYMBOL_GPL vmlinux 0xe15e88d3 sysfs_remove_file_from_group +EXPORT_SYMBOL_GPL vmlinux 0xe166d126 audit_log_vformat +EXPORT_SYMBOL_GPL vmlinux 0xe17a0741 devres_destroy +EXPORT_SYMBOL_GPL vmlinux 0xe1e6bacb seq_release_net +EXPORT_SYMBOL_GPL vmlinux 0xe1f40140 get_current_tty +EXPORT_SYMBOL_GPL vmlinux 0xe21b1f63 __rtnl_link_unregister +EXPORT_SYMBOL_GPL vmlinux 0xe2272e8b cpuidle_register_device +EXPORT_SYMBOL_GPL vmlinux 0xe238f61b hvc_alloc +EXPORT_SYMBOL_GPL vmlinux 0xe295c0ff is_hpet_enabled +EXPORT_SYMBOL_GPL vmlinux 0xe3039085 kobject_rename +EXPORT_SYMBOL_GPL vmlinux 0xe3687db4 driver_unregister +EXPORT_SYMBOL_GPL vmlinux 0xe3869e51 tty_ldisc_deref +EXPORT_SYMBOL_GPL vmlinux 0xe4c331b6 acpi_os_unmap_memory +EXPORT_SYMBOL_GPL vmlinux 0xe513afc0 cache_k8_northbridges +EXPORT_SYMBOL_GPL vmlinux 0xe530071c pm_qos_remove_requirement +EXPORT_SYMBOL_GPL vmlinux 0xe618667c raw_seq_open +EXPORT_SYMBOL_GPL vmlinux 0xe61a6d2f gpio_unexport +EXPORT_SYMBOL_GPL vmlinux 0xe6241888 spi_bus_type +EXPORT_SYMBOL_GPL vmlinux 0xe6488b47 cpufreq_notify_transition +EXPORT_SYMBOL_GPL vmlinux 0xe656e505 xfrm_inner_extract_output +EXPORT_SYMBOL_GPL vmlinux 0xe6587666 rtc_irq_set_freq +EXPORT_SYMBOL_GPL vmlinux 0xe674a5cb srcu_read_lock +EXPORT_SYMBOL_GPL vmlinux 0xe69cf590 crypto_dequeue_request +EXPORT_SYMBOL_GPL vmlinux 0xe7fa47ad srcu_read_unlock +EXPORT_SYMBOL_GPL vmlinux 0xe88ba3e6 pci_find_next_ht_capability +EXPORT_SYMBOL_GPL vmlinux 0xe8b7b86b free_vm_area +EXPORT_SYMBOL_GPL vmlinux 0xe8bb067a put_driver +EXPORT_SYMBOL_GPL vmlinux 0xe91d0cdb crypto_lookup_template +EXPORT_SYMBOL_GPL vmlinux 0xe93e49c3 devres_free +EXPORT_SYMBOL_GPL vmlinux 0xe9a0f014 rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xe9b19bc9 __inet_twsk_hashdance +EXPORT_SYMBOL_GPL vmlinux 0xe9df60aa devm_kzalloc +EXPORT_SYMBOL_GPL vmlinux 0xea065e01 task_handoff_unregister +EXPORT_SYMBOL_GPL vmlinux 0xea0d8fab led_trigger_register_simple +EXPORT_SYMBOL_GPL vmlinux 0xea494bb7 skb_morph +EXPORT_SYMBOL_GPL vmlinux 0xea5ac6c3 fib_rules_register +EXPORT_SYMBOL_GPL vmlinux 0xeaa9545d fnotify_change +EXPORT_SYMBOL_GPL vmlinux 0xeb0e12a4 sysfs_notify +EXPORT_SYMBOL_GPL vmlinux 0xebd2b73e relay_flush +EXPORT_SYMBOL_GPL vmlinux 0xec33ac96 file_ra_state_init +EXPORT_SYMBOL_GPL vmlinux 0xec9ae703 flush_workqueue +EXPORT_SYMBOL_GPL vmlinux 0xed72c1d0 transport_class_register +EXPORT_SYMBOL_GPL vmlinux 0xede65e13 transport_remove_device +EXPORT_SYMBOL_GPL vmlinux 0xedf69ca6 nf_unregister_afinfo +EXPORT_SYMBOL_GPL vmlinux 0xee954077 blk_queue_dma_drain +EXPORT_SYMBOL_GPL vmlinux 0xeef2462c tcp_slow_start +EXPORT_SYMBOL_GPL vmlinux 0xef2dc7b9 power_supply_class +EXPORT_SYMBOL_GPL vmlinux 0xefba440c input_ff_erase +EXPORT_SYMBOL_GPL vmlinux 0xefe21106 snmp_mib_init +EXPORT_SYMBOL_GPL vmlinux 0xf0747dbf pci_create_slot +EXPORT_SYMBOL_GPL vmlinux 0xf1114249 pid_vnr +EXPORT_SYMBOL_GPL vmlinux 0xf1676b41 user_describe +EXPORT_SYMBOL_GPL vmlinux 0xf184d189 kernel_power_off +EXPORT_SYMBOL_GPL vmlinux 0xf18fa97a register_pernet_gen_device +EXPORT_SYMBOL_GPL vmlinux 0xf1fa4376 inotify_inode_queue_event +EXPORT_SYMBOL_GPL vmlinux 0xf2c6c985 rtc_device_unregister +EXPORT_SYMBOL_GPL vmlinux 0xf2fca922 uart_parse_options +EXPORT_SYMBOL_GPL vmlinux 0xf2fd2193 __rtnl_link_register +EXPORT_SYMBOL_GPL vmlinux 0xf4393722 crypto_alg_mod_lookup +EXPORT_SYMBOL_GPL vmlinux 0xf4683b6e fsstack_copy_attr_all +EXPORT_SYMBOL_GPL vmlinux 0xf4841f48 led_trigger_unregister +EXPORT_SYMBOL_GPL vmlinux 0xf499fdb2 rcu_barrier_bh +EXPORT_SYMBOL_GPL vmlinux 0xf5477ff4 tty_perform_flush +EXPORT_SYMBOL_GPL vmlinux 0xf553318d cpuidle_pause_and_lock +EXPORT_SYMBOL_GPL vmlinux 0xf5a691cd invalidate_bh_lrus +EXPORT_SYMBOL_GPL vmlinux 0xf61705df put_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0xf63b757c driver_for_each_device +EXPORT_SYMBOL_GPL vmlinux 0xf6bcbd73 hwrng_register +EXPORT_SYMBOL_GPL vmlinux 0xf6daf220 __rt_mutex_init +EXPORT_SYMBOL_GPL vmlinux 0xf6e8e130 pci_find_next_capability +EXPORT_SYMBOL_GPL vmlinux 0xf724ae53 vfs_kern_mount +EXPORT_SYMBOL_GPL vmlinux 0xf779cc02 cpuidle_unregister_driver +EXPORT_SYMBOL_GPL vmlinux 0xf7c4fb67 sysfs_update_group +EXPORT_SYMBOL_GPL vmlinux 0xf82f16b3 execute_in_process_context +EXPORT_SYMBOL_GPL vmlinux 0xf8802492 print_stack_trace +EXPORT_SYMBOL_GPL vmlinux 0xf8cd8eca queue_delayed_work_on +EXPORT_SYMBOL_GPL vmlinux 0xf9238304 anon_transport_class_unregister +EXPORT_SYMBOL_GPL vmlinux 0xf97c4aae klist_iter_exit +EXPORT_SYMBOL_GPL vmlinux 0xf984c92f sock_prot_inuse_add +EXPORT_SYMBOL_GPL vmlinux 0xf9a054b5 __round_jiffies +EXPORT_SYMBOL_GPL vmlinux 0xf9db7b2c xfrm_audit_state_delete +EXPORT_SYMBOL_GPL vmlinux 0xfa4d0052 ip_build_and_send_pkt +EXPORT_SYMBOL_GPL vmlinux 0xfb2a3293 math_state_restore +EXPORT_SYMBOL_GPL vmlinux 0xfb6e0678 platform_get_irq +EXPORT_SYMBOL_GPL vmlinux 0xfbf9be5d register_oom_notifier +EXPORT_SYMBOL_GPL vmlinux 0xfc043563 rtc_irq_set_state +EXPORT_SYMBOL_GPL vmlinux 0xfd26e5f3 debugfs_create_dir +EXPORT_SYMBOL_GPL vmlinux 0xfd3930d7 unregister_timer_hook +EXPORT_SYMBOL_GPL vmlinux 0xfda74e28 user_destroy +EXPORT_SYMBOL_GPL vmlinux 0xfdb1b3af vfs_cancel_lock +EXPORT_SYMBOL_GPL vmlinux 0xfde0b92c crypto_larval_error +EXPORT_SYMBOL_GPL vmlinux 0xfdf1c041 per_cpu__gdt_page +EXPORT_SYMBOL_GPL vmlinux 0xfdf3439b rtc_set_mmss +EXPORT_SYMBOL_GPL vmlinux 0xfe0cd248 sysfs_create_link +EXPORT_SYMBOL_GPL vmlinux 0xfe39d7ec get_inotify_watch +EXPORT_SYMBOL_GPL vmlinux 0xfe990052 gpio_free +EXPORT_SYMBOL_GPL vmlinux 0xfecbff96 __mark_empty_function +EXPORT_SYMBOL_GPL vmlinux 0xff2595d3 single_open_net +EXPORT_SYMBOL_GPL vmlinux 0xff3971f3 drop_file_write_access +EXPORT_SYMBOL_GPL vmlinux 0xff5a8cfe cn_del_callback +EXPORT_UNUSED_SYMBOL vmlinux 0x00000000 init_mm --- linux-2.6.27.orig/debian/d-i/kernel-versions.in +++ linux-2.6.27/debian/d-i/kernel-versions.in @@ -0,0 +1,4 @@ +# arch version flavour installedname suffix bdep +amd64 PKGVER-ABINUM generic PKGVER-ABINUM-generic - + +i386 PKGVER-ABINUM generic PKGVER-ABINUM-generic - --- linux-2.6.27.orig/debian/d-i/kernel-versions +++ linux-2.6.27/debian/d-i/kernel-versions @@ -0,0 +1,4 @@ +# arch version flavour installedname suffix bdep +amd64 2.6.27-9 generic 2.6.27-9-generic - + +i386 2.6.27-9 generic 2.6.27-9-generic - --- linux-2.6.27.orig/debian/d-i/package-list +++ linux-2.6.27/debian/d-i/package-list @@ -0,0 +1,174 @@ +Package: acpi-modules +Depends: kernel-image +Priority: standard +Description: Support for ACPI + +Package: fat-modules +Depends: kernel-image +Priority: standard +Description: FAT filesystem support + This includes Windows FAT and VFAT support. + +Package: fb-modules +Depends: kernel-image +Priority: standard +Description: Framebuffer modules + +Package: firewire-core-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: Firewire (IEEE-1394) Support + +Package: floppy-modules +Depends: kernel-image +Priority: standard +Description: Floppy driver support + +Package: fs-core-modules +Depends: kernel-image +Priority: standard +Provides: ext2-modules, ext3-modules, jfs-modules, reiserfs-modules, xfs-modules +Description: Base filesystem modules + This includes ext2, ext3, jfs, reiserfs and xfs. + +Package: fs-secondary-modules +Depends: kernel-image, fat-modules +Priority: standard +Provides: ntfs-modules, hfs-modules +Description: Extra filesystem modules + This includes support for Windows NTFS and MacOS HFS/HFSPlus + +Package: input-modules +Depends: kernel-image, usb-modules +Priority: standard +Description: Support for various input methods + +Package: ipv6-modules +Depends: kernel-image +Priority: standard +Description: Support for IPv6 networking + +Package: irda-modules +Depends: kernel-image, nic-shared-modules +Priority: standard +Description: Support for Infrared protocols + +Package: md-modules +Depends: kernel-image +Priority: standard +Description: Multi-device support (raid, device-mapper, lvm) + +Package: nic-modules +Depends: kernel-image, nic-shared-modules, virtio-modules +Priority: standard +Description: Network interface support + +Package: nic-pcmcia-modules +Depends: kernel-image, nic-shared-modules, nic-modules +Priority: standard +Description: PCMCIA network interface support + +Package: nic-usb-modules +Depends: kernel-image, nic-shared-modules, usb-modules +Priority: standard +Description: USB network interface support + +Package: parport-modules +Depends: kernel-image +Priority: standard +Description: Parallel port support + +Package: pata-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: PATA support modules + +Package: pcmcia-modules +Depends: kernel-image +Priority: standard +Description: PCMCIA Modules + +Package: pcmcia-storage-modules +Depends: kernel-image, scsi-modules +Priority: standard +Description: PCMCIA storage support + +Package: plip-modules +Depends: kernel-image, nic-shared-modules, parport-modules +Priority: standard +Description: PLIP (parallel port) networking support + +Package: ppp-modules +Depends: kernel-image, nic-shared-modules, serial-modules +Priority: standard +Description: PPP (serial port) networking support + +Package: sata-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: SATA storage support + +Package: scsi-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: SCSI storage support + +Package: serial-modules +Depends: kernel-image +Priority: standard +Description: Serial port support + +Package: storage-core-modules +Depends: kernel-image +Priority: standard +Provides: loop-modules +Description: Core storage support + Includes core SCSI, LibATA, USB-Storage. Also includes related block + devices for CD, Disk and Tape medium (and IDE Floppy). + +Package: usb-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: Core USB support + +Package: nfs-modules +Priority: standard +Depends: kernel-image +Description: NFS filesystem drivers + Includes the NFS client driver, and supporting modules. + +Package: block-modules +Priority: standard +Depends: kernel-image, storage-core-modules, parport-modules, virtio-modules +Description: Block storage devices + This package contains the block storage devices, including DAC960 and + paraide. + +Package: message-modules +Priority: standard +Depends: kernel-image, storage-core-modules, scsi-modules +Description: Fusion and i2o storage modules + This package containes the fusion and i2o storage modules. + +Package: crypto-modules +Priority: extra +Depends: kernel-image +Description: crypto modules + This package contains crypto modules. + +Package: virtio-modules +Priority: standard +Depends: kernel-image +Description: VirtIO Modules + Includes modules for VirtIO (virtual machine, generally kvm guests) + +Package: socket-modules +Depends: kernel-image +Priority: standard +Description: Unix socket support + +Package: mouse-modules +Depends: kernel-image, input-modules, usb-modules +Priority: extra +Description: Mouse support + This package contains mouse drivers for the Linux kernel. --- linux-2.6.27.orig/debian/d-i/modules/nfs-modules +++ linux-2.6.27/debian/d-i/modules/nfs-modules @@ -0,0 +1,4 @@ +nfs +nfs_acl +lockd +sunrpc --- linux-2.6.27.orig/debian/d-i/modules/ppp-modules +++ linux-2.6.27/debian/d-i/modules/ppp-modules @@ -0,0 +1,8 @@ +ppp_async +ppp_deflate +ppp_generic +ppp_mppe +pppoe +pppox +ppp_synctty +syncppp --- linux-2.6.27.orig/debian/d-i/modules/socket-modules +++ linux-2.6.27/debian/d-i/modules/socket-modules @@ -0,0 +1 @@ +af_packet --- linux-2.6.27.orig/debian/d-i/modules/fb-modules +++ linux-2.6.27/debian/d-i/modules/fb-modules @@ -0,0 +1,3 @@ +fbcon +vesafb +vga16fb --- linux-2.6.27.orig/debian/d-i/modules/pcmcia-modules +++ linux-2.6.27/debian/d-i/modules/pcmcia-modules @@ -0,0 +1,8 @@ +i82092 +i82365 ? +pcmcia +pcmcia_core +pd6729 +rsrc_nonstatic +tcic ? +yenta_socket --- linux-2.6.27.orig/debian/d-i/modules/md-modules +++ linux-2.6.27/debian/d-i/modules/md-modules @@ -0,0 +1,22 @@ +dm-crypt +dm-log +dm-mirror +dm-mod +dm-multipath +dm-raid4-5 +dm-round-robin +dm-snapshot +dm-zero +faulty +linear +md-mod +multipath +raid0 +raid1 +raid10 +raid456 + +# Extras +dm-raid4-5 +dm-loop +dm-bbr --- linux-2.6.27.orig/debian/d-i/modules/storage-core-modules +++ linux-2.6.27/debian/d-i/modules/storage-core-modules @@ -0,0 +1,17 @@ +# Core stacks +libata +scsi_mod +usbcore +usb-storage + +# Block level +cdrom +sd_mod +sr_mod + +# Loop modules +loop +cryptoloop + +# Needs to be here for better cdrom initrd layout +isofs --- linux-2.6.27.orig/debian/d-i/modules/irda-modules +++ linux-2.6.27/debian/d-i/modules/irda-modules @@ -0,0 +1,30 @@ +act200l-sir +actisys-sir +ali-ircc +donauboe ? +esi-sir +girbil-sir +ircomm +ircomm-tty +irda +irda-usb +irlan +irnet +irport ? +irtty-sir +kingsun-sir +ks959-sir +ksdazzle-sir +litelink-sir +ma600-sir +mcp2120-sir +mcs7780 +nsc-ircc +old_belkin-sir +sir-dev +smsc-ircc2 +stir4200 +tekram-sir +via-ircc +vlsi_ir +w83977af_ir --- linux-2.6.27.orig/debian/d-i/modules/usb-modules +++ linux-2.6.27/debian/d-i/modules/usb-modules @@ -0,0 +1,10 @@ +ehci-hcd +isp116x-hcd +isp1760 +ohci-hcd +r8a66597-hcd +sl811_cs +sl811-hcd +u132-hcd +uhci-hcd +usbserial --- linux-2.6.27.orig/debian/d-i/modules/sata-modules +++ linux-2.6.27/debian/d-i/modules/sata-modules @@ -0,0 +1,19 @@ +# Rerquired by sata_sis +pata_sis + +ahci +ata_piix +pdc_adma +sata_inic162x +sata_mv +sata_nv +sata_promise +sata_qstor +sata_sil +sata_sil24 +sata_sis +sata_svw +sata_sx4 +sata_uli +sata_via +sata_vsc --- linux-2.6.27.orig/debian/d-i/modules/fat-modules +++ linux-2.6.27/debian/d-i/modules/fat-modules @@ -0,0 +1,7 @@ +fat +vfat + +# Supporting modules ? +nls_cp437 ? +nls_iso8859-1 ? +nls_utf8 ? --- linux-2.6.27.orig/debian/d-i/modules/block-modules +++ linux-2.6.27/debian/d-i/modules/block-modules @@ -0,0 +1,31 @@ +aoe +aten +bpck +bpck6 ? +cciss +comm +cpqarray +DAC960 +dstr +epat +epia +fit2 +fit3 +friq +frpw +kbic +ktti +nbd +on20 +on26 +paride +pcd +pd +pf +pg +pktcdvd +pt +sx8 +ub +umem +virtio_blk ? --- linux-2.6.27.orig/debian/d-i/modules/fs-core-modules +++ linux-2.6.27/debian/d-i/modules/fs-core-modules @@ -0,0 +1,5 @@ +ext2 +ext3 +jfs +reiserfs +xfs --- linux-2.6.27.orig/debian/d-i/modules/nic-usb-modules +++ linux-2.6.27/debian/d-i/modules/nic-usb-modules @@ -0,0 +1,11 @@ +catc ? +kaweth ? +pegasus ? +prism2_usb ? +rtl8150 ? +usbnet ? +zd1211rw ? +zd1201 ? +rt2500usb ? +rt73usb ? +rt2570 ? --- linux-2.6.27.orig/debian/d-i/modules/floppy-modules +++ linux-2.6.27/debian/d-i/modules/floppy-modules @@ -0,0 +1 @@ +floppy --- linux-2.6.27.orig/debian/d-i/modules/acpi-modules +++ linux-2.6.27/debian/d-i/modules/acpi-modules @@ -0,0 +1,2 @@ +fan +thermal --- linux-2.6.27.orig/debian/d-i/modules/nic-modules +++ linux-2.6.27/debian/d-i/modules/nic-modules @@ -0,0 +1,150 @@ +3c359 ? +3c501 ? +3c503 ? +3c505 ? +3c507 ? +3c509 ? +3c515 ? +3c523 ? +3c527 ? +3c59x ? +8139cp ? +8139too ? +82596 ? +abyss ? +ac3200 ? +adm8211 ? +airo ? +airport ? +amd8111e ? +arc4 ? +arcnet ? +arc-rawmode ? +arc-rimi ? +arlan ? +at1700 ? +atl1 ? +atle ? +atl2 ? +atmel ? +atmel_pci ? +b44 ? +bcm43xx ? +bcm43xx-mac80211 ? +bmac ? +bnx2 ? +bonding ? +cassini ? +com20020 ? +com20020-pci ? +com90io ? +com90xx ? +cs89x0 ? +de2104x ? +de4x5 ? +de600 ? +de620 ? +defxx ? +depca ? +dl2k ? +dmfe ? +dummy ? +e100 ? +e1000 ? +e1000e ? +e2100 ? +eepro ? +eepro100 ? +eexpress ? +epic100 ? +eql ? +es3210 ? +eth16i ? +ewrk3 ? +fealnx ? +forcedeth ? +igb ? +ps3_gelic ? +hamachi ? +hermes ? +hp ? +hp100 ? +hp-plus ? +ibmtr ? +ipddp ? +ipw2100 ? +ipw2200 ? +ipw3945 ? +ixgb ? +lance ? +lanstreamer ? +lasi_82596 ? +lne390 ? +lp486e ? +mace ? +mv643xx_eth ? +myri_sbus ? +natsemi ? +ne ? +ne2 ? +ne2k-pci ? +ne3210 ? +netconsole ? +ni5010 ? +ni52 ? +ni65 ? +niu ? +ns83820 ? +olympic ? +orinoco ? +orinoco_pci ? +orinoco_plx ? +orinoco_tmd ? +pcnet32 ? +prism54 ? +r8169 ? +rate_control ? +rfc1051 ? +rfc1201 ? +rrunner ? +rt2400 ? +rt2500 ? +rt61pci ? +s2io ? +shaper ? +sis190 ? +sis900 ? +spidernet ? +skfp ? +skge ? +sk98lin ? +sky2 ? +smc9194 ? +smc-ultra ? +smc-ultra32 ? +starfire ? +strip ? +sunbmac ? +sundance ? +sungem ? +sungem_phy ? +sunhme ? +sunlance ? +sunqe ? +sunvnet ? +tg3 ? +tlan ? +tms380tr ? +tmspci ? +tulip ? +tun ? +typhoon ? +uli526x ? +via-rhine ? +via-velocity ? +virtio_net ? +wavelan ? +wd ? +winbond-840 ? +yellowfin ? +znet ? --- linux-2.6.27.orig/debian/d-i/modules/plip-modules +++ linux-2.6.27/debian/d-i/modules/plip-modules @@ -0,0 +1 @@ +plip --- linux-2.6.27.orig/debian/d-i/modules/input-modules +++ linux-2.6.27/debian/d-i/modules/input-modules @@ -0,0 +1,2 @@ +usbhid +usbkbd --- linux-2.6.27.orig/debian/d-i/modules/scsi-modules +++ linux-2.6.27/debian/d-i/modules/scsi-modules @@ -0,0 +1,113 @@ +# SCSI +raid_class ? +scsi_transport_spi ? +scsi_transport_fc ? +scsi_transport_iscsi ? +scsi_transport_sas ? +iscsi_tcp ? +libiscsi ? +amiga7xx ? +a3000 ? +a2091 ? +gvp11 ? +mvme147 ? +sgiwd93 ? +cyberstorm ? +cyberstormII ? +blz2060 ? +blz1230 ? +fastlane ? +oktagon_esp_mod ? +atari_scsi ? +mac_scsi ? +mac_esp ? +sun3_scsi ? +mvme16x ? +bvme6000 ? +sim710 ? +advansys ? +psi240i ? +BusLogic ? +dpt_i2o ? +u14-34f ? +ultrastor ? +aha152x ? +aha1542 ? +aha1740 ? +aic7xxx_old ? +ips ? +fd_mcs ? +fdomain ? +in2000 ? +g_NCR5380 ? +g_NCR5380_mmio ? +NCR53c406a ? +NCR_D700 ? +NCR_Q720_mod ? +sym53c416 ? +qlogicfas408 ? +qla1280 ? +pas16 ? +seagate ? +seagate ? +t128 ? +dmx3191d ? +dtc ? +zalon7xx ? +eata_pio ? +wd7000 ? +mca_53c9x ? +ibmmca ? +eata ? +dc395x ? +tmscsim ? +megaraid ? +atp870u ? +esp ? +gdth ? +initio ? +a100u2w ? +qlogicpti ? +ide-scsi ? +mesh ? +mac53c94 ? +pluto ? +dec_esp ? +3w-xxxx ? +3w-9xxx ? +ppa ? +imm ? +jazz_esp ? +sun3x_esp ? +fcal ? +lasi700 ? +nsp32 ? +ipr ? +hptiop ? +stex ? +osst ? +sg ? +ch ? +scsi_debug ? +aacraid ? +aic7xxx ? +aic79xx ? +aic94xx ? +arcmsr ? +acornscsi_mod ? +arxescsi ? +cumana_1 ? +cumana_2 ? +ecoscsi ? +oak ? +powertec ? +eesox ? +ibmvscsic ? +libsas ? +lpfc ? +megaraid_mm ? +megaraid_mbox ? +megaraid_sas ? +qla2xxx ? +sym53c8xx ? +qla4xxx ? --- linux-2.6.27.orig/debian/d-i/modules/firewire-core-modules +++ linux-2.6.27/debian/d-i/modules/firewire-core-modules @@ -0,0 +1,4 @@ +ieee1394 +ohci1394 +sbp2 +eth1394 --- linux-2.6.27.orig/debian/d-i/modules/message-modules +++ linux-2.6.27/debian/d-i/modules/message-modules @@ -0,0 +1,13 @@ +mptbase +mptctl +mptfc +mptlan +mptsas +mptscsih +mptspi +i2o_block +i2o_bus +i2o_config +i2o_core +i2o_proc +i2o_scsi --- linux-2.6.27.orig/debian/d-i/modules/crypto-modules +++ linux-2.6.27/debian/d-i/modules/crypto-modules @@ -0,0 +1,7 @@ +aes_generic +blowfish +twofish +serpent +sha256_generic +cbc +crc32c --- linux-2.6.27.orig/debian/d-i/modules/nic-pcmcia-modules +++ linux-2.6.27/debian/d-i/modules/nic-pcmcia-modules @@ -0,0 +1,19 @@ +3c574_cs ? +3c589_cs ? +airo_cs ? +atmel_cs ? +axnet_cs ? +com20020_cs ? +fmvj18x_cs ? +ibmtr_cs ? +netwave_cs ? +nmclan_cs ? +orinoco_cs ? +pcnet_cs ? +ray_cs ? +smc91c92_cs ? +wavelan_cs ? +wl3501_cs ? +xirc2ps_cs ? +xircom_cb ? +xircom_tulip_cb ? --- linux-2.6.27.orig/debian/d-i/modules/pcmcia-storage-modules +++ linux-2.6.27/debian/d-i/modules/pcmcia-storage-modules @@ -0,0 +1,6 @@ +pata_pcmcia +qlogic_cs +fdomain_cs +aha152x_cs ? +nsp_cs ? +sym53c500_cs --- linux-2.6.27.orig/debian/d-i/modules/fs-secondary-modules +++ linux-2.6.27/debian/d-i/modules/fs-secondary-modules @@ -0,0 +1,4 @@ +fuse +ntfs +hfs +hfsplus --- linux-2.6.27.orig/debian/d-i/modules/virtio-modules +++ linux-2.6.27/debian/d-i/modules/virtio-modules @@ -0,0 +1,4 @@ +virtio_balloon +virtio_pci +virtio_ring ? +virtio-rng --- linux-2.6.27.orig/debian/d-i/modules/ipv6-modules +++ linux-2.6.27/debian/d-i/modules/ipv6-modules @@ -0,0 +1 @@ +ipv6 --- linux-2.6.27.orig/debian/d-i/modules/mouse-modules +++ linux-2.6.27/debian/d-i/modules/mouse-modules @@ -0,0 +1,3 @@ +evdev +psmouse +usbmouse ? --- linux-2.6.27.orig/debian/d-i/modules/nic-shared-modules +++ linux-2.6.27/debian/d-i/modules/nic-shared-modules @@ -0,0 +1,21 @@ +# PHY +8390 +mii + +# CRC modules +crc-ccitt +crc-itu-t + +# mac80211 stuff +mac80211 +cfg80211 + +# rt2x00 lib (since rt2x00 is split across usb/pci/cb +rt2x00lib + +# Wireless 802.11 modules +ieee80211 +ieee80211_crypt +ieee80211_crypt_ccmp +ieee80211_crypt_tkip +ieee80211_crypt_wep --- linux-2.6.27.orig/debian/d-i/modules/serial-modules +++ linux-2.6.27/debian/d-i/modules/serial-modules @@ -0,0 +1,3 @@ +generic_serial +serial_cs +synclink_cs --- linux-2.6.27.orig/debian/d-i/modules/pata-modules +++ linux-2.6.27/debian/d-i/modules/pata-modules @@ -0,0 +1,32 @@ +ata_generic +pata_acpi +pata_ali +pata_amd +pata_artop +pata_atiixp +pata_cmd64x +pata_cs5520 +pata_cs5530 +pata_efar +pata_hpt366 +pata_hpt37x +pata_hpt3x3 +pata_it8213 +pata_it821x +pata_jmicron +pata_marvell +pata_mpiix +pata_netcell +pata_ninja32 +pata_ns87410 +pata_ns87415 +pata_oldpiix +pata_pdc2027x +pata_pdc202xx_old +pata_rz1000 +pata_sch +pata_serverworks +pata_sil680 +pata_sl82c105 +pata_triflex +pata_via --- linux-2.6.27.orig/debian/d-i/modules/parport-modules +++ linux-2.6.27/debian/d-i/modules/parport-modules @@ -0,0 +1,2 @@ +parport +parport_pc --- linux-2.6.27.orig/debian/control.d/flavour-control.stub +++ linux-2.6.27/debian/control.d/flavour-control.stub @@ -0,0 +1,66 @@ +# Items that get replaced: +# FLAVOUR +# DESC +# ARCH +# SUPPORTED +# TARGET +# BOOTLOADER +# =PROVIDES= +# +# Items marked with =FOO= are optional +# +# XXX: Leave the blank line before the first package!! + +Package: linux-image-PKGVER-ABINUM-FLAVOUR +Architecture: ARCH +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, =PROVIDES= +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: BOOTLOADER +Suggests: fdutils, linux-doc-PKGVER | linux-source-PKGVER +Description: Linux kernel image for version PKGVER on DESC + This package contains the Linux kernel image for version PKGVER on + DESC. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports SUPPORTED processors. + . + TARGET + . + You likely do not want to install this package directly. Instead, install + the linux-FLAVOUR meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-PKGVER-ABINUM-FLAVOUR +Architecture: ARCH +Section: devel +Priority: optional +Depends: coreutils | fileutils (>= 4.0), linux-headers-PKGVER-ABINUM, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version PKGVER on DESC + This package provides kernel header files for version PKGVER on + DESC. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-PKGVER-ABINUM/debian.README.gz for details. + +Package: linux-image-debug-PKGVER-ABINUM-FLAVOUR +Architecture: ARCH +Section: devel +Priority: optional +Provides: linux-debug +Description: Linux kernel debug image for version PKGVER on DESC + This package provides a kernel debug image for version PKGVER on + DESC. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. --- linux-2.6.27.orig/debian/control.d/vars.ixp4xx +++ linux-2.6.27/debian/control.d/vars.ixp4xx @@ -0,0 +1,8 @@ +arch="armel" +supported="IXP4xx" +desc="IXP4xx-based systems" +target="Linksys NSLU2, etc." +bootloader="" +provides="" +section_image="universe/base" +do_debug="Yes" --- linux-2.6.27.orig/debian/control.d/vars.server +++ linux-2.6.27/debian/control.d/vars.server @@ -0,0 +1,6 @@ +arch="i386 amd64" +supported="Server" +target="Geared toward server systems." +desc="x86/x86_64" +bootloader="lilo (>= 19.1) | grub" +provides="redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9" --- linux-2.6.27.orig/debian/control.d/vars.versatile +++ linux-2.6.27/debian/control.d/vars.versatile @@ -0,0 +1,8 @@ +arch="armel" +supported="Versatile" +desc="Versatile-based systems" +target="PB, AB, Qemu, etc." +bootloader="" +provides="" +section_image="universe/base" +do_debug="Yes" --- linux-2.6.27.orig/debian/control.d/vars.iop32x +++ linux-2.6.27/debian/control.d/vars.iop32x @@ -0,0 +1,8 @@ +arch="armel" +supported="IOP32x" +desc="IOP32x-based systems" +target="Thecus N2100, etc." +bootloader="" +provides="" +section_image="universe/base" +do_debug="Yes" --- linux-2.6.27.orig/debian/control.d/vars.generic +++ linux-2.6.27/debian/control.d/vars.generic @@ -0,0 +1,6 @@ +arch="i386 amd64" +supported="Generic" +target="Geared toward desktop systems." +desc="x86/x86_64" +bootloader="lilo (>= 19.1) | grub" +provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9" --- linux-2.6.27.orig/debian/control.d/vars.orion5x +++ linux-2.6.27/debian/control.d/vars.orion5x @@ -0,0 +1,8 @@ +arch="armel" +supported="Orion 5181, 5182 and 5281" +desc="Orion5x-based systems" +target="QNAP TS-109/TS-209, etc." +bootloader="" +provides="" +section_image="universe/base" +do_debug="Yes" --- linux-2.6.27.orig/debian/commit-templates/external-driver +++ linux-2.6.27/debian/commit-templates/external-driver @@ -0,0 +1,19 @@ +# Ubuntu external driver commit. +# +# NOTE: This gets reformatted for README.Ubuntu-External-Drivers and +# debian/changelog. +# +# This is only needed when a driver is added, updated or removed. It is +# not needed when patches or fixes are applied to the driver. If the +# driver is being removed, add the line: +# +# Removing: yes +# +# to the commit, and you can remove all other tags (except UBUNTU:). +# +UBUNTU: +ExternalDriver: +Description: +Url: +Mask: +Version: --- linux-2.6.27.orig/debian/commit-templates/patch +++ linux-2.6.27/debian/commit-templates/patch @@ -0,0 +1,27 @@ +# Ubuntu commit template. +# +# NOTE: This gets reformatted for debian/changelog +# +# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be +# referenced to the Author in the debian/changelog entry. +# +# The text following is the short message that will be placed in the +# changelog. Extra text on the following lines will be ignored, but left +# in the git commit. Lines with # will be ignored in the commit. +# +# OriginalAuthor allows for alternate attribution. +# +# OriginalLocation allows for a URL or description of where the patch came +# from. +# +# Bug is a reference to a Malone bug number. Be sure to include the '#' as +# part of the bug number, e.g., 'Bug: #1'. +# +# Ignore: yes will keep this commit from showing up in the changelog. +# +UBUNTU: +# OriginalAuthor: +# OriginalLocation: +# Bug: # +# Ignore: yes +# Other text below here. --- linux-2.6.27.orig/debian/commit-templates/update-configs +++ linux-2.6.27/debian/commit-templates/update-configs @@ -0,0 +1,9 @@ +UBUNTU: Updating configs +# +# This template is used for commit messages that don't need to +# show up in debian/changelog. Administrative stuff like config +# updates, ABI bumps, etc. Setting 'Ignore: yes' prevents +# 'debian/rules insertchanges' from inserting this commit meesage +# as a changelog entry. +# +Ignore: yes --- linux-2.6.27.orig/debian/commit-templates/bumpabi +++ linux-2.6.27/debian/commit-templates/bumpabi @@ -0,0 +1,2 @@ +UBUNTU: Bump ABI +Ignore: yes --- linux-2.6.27.orig/debian/commit-templates/sauce-patch +++ linux-2.6.27/debian/commit-templates/sauce-patch @@ -0,0 +1,37 @@ +# Ubuntu commit template. +# +# NOTE: This gets reformatted for debian/changelog +# +# +# SAUCE refers to the fact that this patch might not go upstream, but we need to +# carry it to successive releases. In most cases you DONOT want to use this +# template. +# +# An example of a SAUCE patch is the ACPI DSDT-in-initramfs patch which has been +# refused upstream, but still provides useful functionality to users with broken +# BIOSes. +# +#------------------------------------------------------------------------- +# +# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be +# referenced to the Author in the debian/changelog entry. +# +# The text following is the short message that will be placed in the +# changelog. Extra text on the following lines will be ignored, but left +# in the git commit. Lines with # will be ignored in the commit. +# +# OriginalAuthor allows for alternate attribution. +# +# OriginalLocation allows for a URL or description of where the patch came +# from. +# +# Bug is a reference to a Malone bug number. +# +# Ignore: yes will keep this commit from showing up in the changelog. +# +UBUNTU: SAUCE: +# OriginalAuthor: +# OriginalLocation: +# Bug: +# Ignore: yes +# Other text below here. --- linux-2.6.27.orig/debian/commit-templates/newrelease +++ linux-2.6.27/debian/commit-templates/newrelease @@ -0,0 +1,2 @@ +UBUNTU: Start new release +Ignore: yes --- linux-2.6.27.orig/debian/commit-templates/missing-modules +++ linux-2.6.27/debian/commit-templates/missing-modules @@ -0,0 +1,2 @@ +UBUNTU: build/modules: Add modules that have intentionally gone missing +Ignore: yes --- linux-2.6.27.orig/debian/tests/README +++ linux-2.6.27/debian/tests/README @@ -0,0 +1,21 @@ +Scripts placed in this directory get called one at a time by run-parts(8). +The scripts are expected to perform some sort of sanity checks on the +finished build. Scripts will be called once for each flavour. + +Some environment variables are exported to make life a little easier: + +DPKG_ARCH : The dpkg architecture (e.g. "amd64") +KERN_ARCH : The kernel architecture (e.g. "x86_64") +FLAVOUR : The specific flavour for this run (e.g. "generic") +VERSION : The full version of this build (e.g. 2.6.22-1) +REVISION : The exact revision of this build (e.g. 1.3) +PREV_REVISION : The revision prior to this one +ABI_NUM : The specific ABI number for this build (e.g. 2) +PREV_ABI_NUM : The previous ABI number. Can be the same as ABI_NUM. +BUILD_DIR : The directory where this build took place +INSTALL_DIR : The directory where the package is prepared +SOURCE_DIR : Where the main kernel source is + +Scripts are expected to have a zero exit status when no problems occur, +and non-zero when an error occurs that should stop the build. Scripts +should print whatever info they deem needed to deduce the problem. --- linux-2.6.27.orig/debian/tests/check-aliases +++ linux-2.6.27/debian/tests/check-aliases @@ -0,0 +1,24 @@ +#!/usr/bin/perl -w + +my %map; + +print "Checking for dupe aliases in $ENV{'FLAVOUR'}...\n"; + +$aliases = + "$ENV{'INSTALL_DIR'}/lib/modules/$ENV{'VERSION'}-$ENV{'FLAVOUR'}/modules.alias"; + +open(ALIASES, "< $aliases") or die "Could not open $aliases"; + +while () { + chomp; + my ($junk, $alias, $module) = split; + + if (defined($map{$alias})) { + printf("%s %20s / %-20s : %s \n", ("$map{$alias}" eq "$module") + ? "INT" : " ", $map{$alias}, $module, $alias); + } else { + $map{$alias} = $module; + } +} + +exit(0); --- linux-2.6.27.orig/debian/sub-flavours/README +++ linux-2.6.27/debian/sub-flavours/README @@ -0,0 +1,12 @@ +Sub flavours are flavours that are built based on other builds. IOW, they +are usually a subset of something else. + +Requirements: + +debian/sub-flavours/.list : The file list, uses glob syntax +debian/sub-flavours/.vars : The make vars, similar to normal flavours +debian/rules.d/.mk : Add _sub var listing the , e.g. + server_sub = virtual would mean virtual is + based on the server flavour. + +Note, the vars must include a conflicts with the flavour it was built on. --- linux-2.6.27.orig/debian/sub-flavours/virtual.list +++ linux-2.6.27/debian/sub-flavours/virtual.list @@ -0,0 +1,111 @@ +arch/*/{crypto,kernel,oprofile} +crypto/* +drivers/acpi/* +drivers/ata/ata_generic.ko +drivers/ata/ata_piix.ko +drivers/ata/libata.ko +drivers/block/virtio_blk.ko +drivers/block/nbd.ko +drivers/block/loop.ko +drivers/block/floppy.ko +drivers/block/cryptoloop.ko +drivers/block/xen-blkfront.ko +drivers/cdrom/cdrom.ko +drivers/char/hangcheck-timer.ko +drivers/char/lp.ko +drivers/char/nvram.ko +drivers/char/ppdev.ko +drivers/char/raw.ko +drivers/input/evbug.ko +drivers/input/evdev.ko +drivers/input/gameport/gameport.ko +drivers/input/mouse/psmouse.ko +drivers/input/serio/serio_raw.ko +drivers/input/serio/serport.ko +drivers/input/joydev.ko +drivers/input/misc/uinput.ko +drivers/input/touchscreen/usbtouchscreen.ko +drivers/input/xen-kbdfront.ko +drivers/md/* +drivers/message/fusion* +drivers/misc/eeprom_93cx6.ko +drivers/net/8139too.ko +drivers/net/8139cp.ko +drivers/net/appletalk/ipddp.ko +drivers/net/bonding/bonding.ko +drivers/net/bsd_comp.ko +drivers/net/dummy.ko +drivers/net/e1000/e1000.ko +drivers/net/eql.ko +drivers/net/ifb.ko +drivers/net/mii.ko +drivers/net/ne2k-pci.ko +drivers/net/netconsole.ko +drivers/net/pcnet32.ko +drivers/net/ppp_async.ko +drivers/net/ppp_deflate.ko +drivers/net/ppp_generic.ko +drivers/net/ppp_mppe.ko +drivers/net/pppoe.ko +drivers/net/pppol2tp.ko +drivers/net/pppox.ko +drivers/net/ppp_synctty.ko +drivers/net/slhc.ko +drivers/net/slip.ko +drivers/net/tun.ko +drivers/net/veth.ko +drivers/net/virtio_net.ko +drivers/net/xen-netfront.ko +drivers/parport/parport.ko +drivers/parport/parport_pc.ko +drivers/net/tulip/tulip.ko +drivers/net/virtio_net.ko +drivers/scsi/BusLogic.ko +drivers/scsi/iscsi_tcp.ko +drivers/scsi/libiscsi.ko +drivers/scsi/libsas/* +drivers/scsi/libsas/libsas.ko +drivers/scsi/qla1280.ko +drivers/scsi/raid_class.ko +drivers/scsi/scsi_mod.ko +drivers/scsi/scsi_transport_fc.ko +drivers/scsi/scsi_transport_iscsi.ko +drivers/scsi/scsi_transport_sas.ko +drivers/scsi/scsi_transport_spi.ko +drivers/scsi/scsi_wait_scan.ko +drivers/scsi/sd_mod.ko +drivers/scsi/sg.ko +drivers/scsi/sr_mod.ko +drivers/usb/core/usbcore.ko +drivers/usb/host/ehci-hcd.ko +drivers/usb/host/uhci-hcd.ko +drivers/usb/storage/usb-storage.ko +drivers/video/cirrusfb.ko +drivers/video/console/bitblit.ko +drivers/video/console/fbcon.ko +drivers/video/console/font.ko +drivers/video/console/softcursor.ko +drivers/video/console/tileblit.ko +drivers/video/output.ko +drivers/video/syscopyarea.ko +drivers/video/sysfillrect.ko +drivers/video/sysimgblt.ko +drivers/video/vesafb.ko +drivers/video/vga16fb.ko +drivers/video/vgastate.ko +drivers/video/xen-fbfront.ko +drivers/virtio/virtio_balloon.ko +drivers/virtio/virtio.ko +drivers/virtio/virtio_pci.ko +drivers/virtio/virtio_ring.ko +drivers/watchdog/softdog.ko +drivers/xen/* +fs/* +lib/* +net/* +sound/core/* +sound/pci/snd-ens1370.ko +sound/drivers/pcsp/snd-pcsp.ko +ubuntu/e1000e/e1000e.ko +ubuntu/squashfs/squashfs.ko +ubuntu/iscsitarget/iscsi_trgt.ko --- linux-2.6.27.orig/debian/sub-flavours/control.stub +++ linux-2.6.27/debian/sub-flavours/control.stub @@ -0,0 +1,39 @@ +# Items that get replaced: +# FLAVOUR +# DESC +# ARCH +# SUPPORTED +# TARGET +# BOOTLOADER +# =PROVIDES= +# =CONFLICTS= +# +# Items marked with =FOO= are optional +# +# XXX: Leave the blank line before the first package!! + +Package: linux-image-PKGVER-ABINUM-FLAVOUR +Architecture: ARCH +Section: base +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, =PROVIDES= +Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3) +Conflicts: hotplug (<< 0.0.20040105-1), =CONFLICTS= +Recommends: BOOTLOADER +Suggests: fdutils, linux-doc-PKGVER | linux-source-PKGVER +Description: Linux kernel image for version PKGVER on DESC + This package contains the Linux kernel image for version PKGVER on + DESC. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports SUPPORTED processors. + . + TARGET + . + You likely do not want to install this package directly. Instead, install + the linux-FLAVOUR meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. --- linux-2.6.27.orig/debian/sub-flavours/virtual.vars +++ linux-2.6.27/debian/sub-flavours/virtual.vars @@ -0,0 +1,11 @@ +# Based on server flavour +arch="i386 amd64" +supported="Virtual" +target="Geared toward virtual machine guests." +desc="x86/x86_64" +bootloader="lilo (>= 19.1) | grub" +is_sub="true" +based_on="server" +# The provides and conflicts are REQUIRED +provides="redhat-cluster-modules" +conflicts="linux-image-PKGVER-ABINUM-${based_on}" --- linux-2.6.27.orig/debian/scripts/link-headers +++ linux-2.6.27/debian/scripts/link-headers @@ -0,0 +1,40 @@ +#!/bin/bash -e + +hdrdir="$1" +symdir="$2" +flavour="$3" + +echo "Symlinking and copying headers for $flavour..." + +excludes='( -path ./debian -prune -o -path ./.git ) -prune -o' + +( +find . $excludes -type f \ + \( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \ + -name '*.sh' -o -name '*.pl' -o -name '*.lds' \) -print +find ./include ./scripts -name .gitignore -prune -o -type f -print +find ./include -mindepth 1 -maxdepth 1 $excludes -type d -print +) | ( +while read file; do + dir=$file + lastdir=$file + + if [ -f "$hdrdir/$file" ]; then + continue + fi + + while [ ! -e "$hdrdir/$dir" -a ! -L "$hdrdir/$dir" ]; do + lastdir=$dir + dir=`dirname $dir` + done + # If the last item to exist is a symlink we assume all is good + if [ ! -L "$hdrdir/$dir" ]; then + # Turns things like "./foo" into "../" + deref="`echo -n $lastdir | sed -e 's/^\.//' -e's,/[^/]*,../,g'`" + item="`echo -n $lastdir | sed -e 's/^\.\///'`" + ln -s $deref$symdir/$item $hdrdir/$item + fi +done +) + +exit --- linux-2.6.27.orig/debian/scripts/module-check +++ linux-2.6.27/debian/scripts/module-check @@ -0,0 +1,119 @@ +#!/usr/bin/perl -w + +$flavour = shift; +$prev_abidir = shift; +$abidir = shift; +$skipmodule = shift; + +print "II: Checking modules for $flavour..."; + +if (-f "$prev_abidir/ignore.modules" + or -f "$prev_abidir/$flavour.ignore.modules") { + print "explicitly ignoring modules\n"; + exit(0); +} + +if (not -f "$abidir/$flavour.modules" or not -f + "$prev_abidir/$flavour.modules") { + print "previous or current modules file missing!\n"; + print " $abidir/$flavour.modules\n"; + print " $prev_abidir/$flavour.modules\n"; + if (defined($skipmodule)) { + exit(0); + } else { + exit(1); + } +} + +print "\n"; + +my %modules; +my %modules_ignore; +my $missing = 0; +my $new = 0; +my $errors = 0; + +# See if we have any ignores +if (-f "$prev_abidir/../modules.ignore") { + my $ignore = 0; + open(IGNORE, "< $prev_abidir/../modules.ignore") or + die "Could not open $prev_abidir/../modules.ignore"; + print " reading modules to ignore..."; + while () { + chomp; + $modules_ignore{$_} = 1; + $ignore++; + } + close(IGNORE); + print "read $ignore modules.\n"; +} + +# Read new modules first +print " reading new modules..."; +$new_count = 0; +open(NEW, "< $abidir/$flavour.modules") or + die "Could not open $abidir/$flavour.modules"; +while () { + chomp; + $modules{$_} = 1; + $new_count++; +} +close(NEW); +print "read $new_count modules.\n"; + +# Now the old modules, checking for missing ones +print " reading old modules..."; +$old_count = 0; +open(OLD, "< $prev_abidir/$flavour.modules") or + die "Could not open $prev_abidir/$flavour.modules"; +while () { + chomp; + if (not defined($modules{$_})) { + print "\n" if not $missing; + $missing++; + if (not defined($modules_ignore{$_})) { + print " MISS: $_\n"; + $errors++; + } else { + print " MISS: $_ (ignored)\n"; + } + } else { + $modules{$_}++; + } + $old_count++; +} +close(OLD); +# Check for new modules +foreach $mod (keys(%modules)) { + if ($modules{$mod} < 2) { + print "\n" if not $missing and not $new; + print " NEW : $mod\n"; + $new++; + } +} +if ($new or $missing) { + print " read $old_count modules : new($new) missing($missing)\n"; +} else { + print "read $old_count modules.\n"; +} + + +# Let's see where we stand... +if ($errors) { + if (defined($skipmodule)) { + print "WW: Explicitly asked to ignore failures (probably not good)\n"; + } else { + print "EE: Missing modules (start begging for mercy)\n"; + exit 1 + } +} + +if ($new) { + print "II: New modules (you've been busy, wipe the poop off your nose)\n"; +} else { + print "II: No new modules (hope you're happy, slacker)\n"; +} + +print "II: Done\n"; + +exit(0); --- linux-2.6.27.orig/debian/scripts/sub-flavour +++ linux-2.6.27/debian/scripts/sub-flavour @@ -0,0 +1,30 @@ +#!/bin/bash -e + + + +echo "SUB_PROCESS $FROM => $TO" + +export from_pkg="linux-image-$ABI_RELEASE-$FROM" +export to_pkg="linux-image-$ABI_RELEASE-$TO" + +from_moddir="debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM" +to_moddir="debian/$to_pkg/lib/modules/$ABI_RELEASE-$FROM" + +install -d "debian/$to_pkg/boot" +install -m644 debian/$from_pkg/boot/{vmlinuz,System.map}-$ABI_RELEASE-$FROM \ + debian/$to_pkg/boot/ + +cat debian/sub-flavours/$TO.list | while read line; do + (cd debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM/kernel; + eval find $line -name '*.ko'); +done | while read mod; do + echo "SUB_INST $mod" + grep "^/lib/modules/$ABI_RELEASE-$FROM/kernel/$mod:" \ + $from_moddir/modules.dep | sed -e 's/://' -e 's/ /\n/g' | \ + while read m; do + test -f debian/$to_pkg/$m && continue + echo "SUB_INST $mod" + install -D -m644 debian/$from_pkg/$m \ + debian/$to_pkg/$m + done +done --- linux-2.6.27.orig/debian/scripts/control-create +++ linux-2.6.27/debian/scripts/control-create @@ -0,0 +1,23 @@ +#!/bin/bash + +vars=$1 + +. $vars + +if [ "$is_sub" = "" ]; then + flavour=$(basename $vars | sed 's/.*\.//') + stub=debian/control.d/flavour-control.stub +else + flavour=$(basename $vars .vars) + stub=debian/sub-flavours/control.stub +fi + +cat $stub | grep -v '^#' | sed \ + -e "s#FLAVOUR#$flavour#g" \ + -e "s#DESC#$desc#g" \ + -e "s#ARCH#$arch#g" \ + -e "s#SUPPORTED#$supported#g" \ + -e "s#TARGET#$target#g" \ + -e "s#BOOTLOADER#$bootloader#g" \ + -e "s#=PROVIDES=#$provides#g" \ + -e "s#=CONFLICTS=#$conflicts#g" --- linux-2.6.27.orig/debian/scripts/abi-check +++ linux-2.6.27/debian/scripts/abi-check @@ -0,0 +1,202 @@ +#!/usr/bin/perl -w + +my $flavour = shift; +my $prev_abinum = shift; +my $abinum = shift; +my $prev_abidir = shift; +my $abidir = shift; +my $skipabi = shift; + +my $fail_exit = 1; +my $EE = "EE:"; +my $errors = 0; + +my $count; + +print "II: Checking ABI for $flavour...\n"; + +if (-f "$prev_abidir/ignore" + or -f "$prev_abidir/$flavour.ignore" or "$skipabi" eq "true") { + print "WW: Explicitly asked to ignore ABI, running in no-fail mode\n"; + $fail_exit = 0; + $EE = "WW:"; +} + +if ($prev_abinum != $abinum) { + print "II: Different ABI's, running in no-fail mode\n"; + $fail_exit = 0; + $EE = "WW:"; +} + +if (not -f "$abidir/$flavour" or not -f "$prev_abidir/$flavour") { + print "EE: Previous or current ABI file missing!\n"; + print " $abidir/$flavour\n" if not -f "$abidir/$flavour"; + print " $prev_abidir/$flavour\n" if not -f "$prev_abidir/$flavour"; + # Always fail here. This is bad + exit(1); +} + +my %symbols; +my %symbols_ignore; +my %modules_ignore; +my %module_syms; + +# See if we have any ignores +my $ignore = 0; +print " Reading symbols/modules to ignore..."; + +for $file ("$prev_abidir/../blacklist", "$prev_abidir/../../perm-blacklist") { + if (-f $file) { + open(IGNORE, "< $file") or + die "Could not open $file"; + while () { + chomp; + if ($_ =~ m/M: (.*)/) { + $modules_ignore{$1} = 1; + } else { + $symbols_ignore{$_} = 1; + } + $ignore++; + } + close(IGNORE); + } +} +print "read $ignore symbols/modules.\n"; + +sub is_ignored($$) { + my ($mod, $sym) = @_; + + die "Missing module name in is_ignored()" if not defined($mod); + die "Missing symbol name in is_ignored()" if not defined($sym); + + if (defined($symbols_ignore{$sym}) or defined($modules_ignore{$mod})) { + return 1; + } + return 0; +} + +# Read new syms first +print " Reading new symbols ($abinum)..."; +$count = 0; +open(NEW, "< $abidir/$flavour") or + die "Could not open $abidir/$flavour"; +while () { + chomp; + m/^(EXPORT_.+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; + $symbols{$4}{'type'} = $1; + $symbols{$4}{'loc'} = $2; + $symbols{$4}{'hash'} = $3; + $module_syms{$2} = 0; + $count++; +} +close(NEW); +print "read $count symbols.\n"; + +# Now the old symbols, checking for missing ones +print " Reading old symbols ($prev_abinum)..."; +$count = 0; +open(OLD, "< $prev_abidir/$flavour") or + die "Could not open $prev_abidir/$flavour"; +while () { + chomp; + m/^(EXPORT_.+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; + $symbols{$4}{'old_type'} = $1; + $symbols{$4}{'old_loc'} = $2; + $symbols{$4}{'old_hash'} = $3; + $count++; +} +close(OLD); + +print "read $count symbols.\n"; + +print "II: Checking for missing symbols in new ABI..."; +$count = 0; +foreach $sym (keys(%symbols)) { + if (!defined($symbols{$sym}{'type'})) { + print "\n" if not $count; + printf(" MISS : %s%s\n", $sym, + is_ignored($symbols{$sym}{'old_loc'}, $sym) ? " (ignored)" : ""); + $count++ if !is_ignored($symbols{$sym}{'old_loc'}, $sym); + } +} +print " " if $count; +print "found $count missing symbols\n"; +if ($count) { + print "$EE Symbols gone missing (what did you do!?!)\n"; + $errors++; +} + + +print "II: Checking for new symbols in new ABI..."; +$count = 0; +foreach $sym (keys(%symbols)) { + if (!defined($symbols{$sym}{'old_type'})) { + print "\n" if not $count; + print " NEW : $sym\n"; + $count++; + } +} +print " " if $count; +print "found $count new symbols\n"; +if ($count and $prev_abinum == $abinum) { + print "WW: Found new symbols within same ABI. Not recommended\n"; +} + +print "II: Checking for changes to ABI...\n"; +$count = 0; +my $moved = 0; +my $changed_type = 0; +my $changed_hash = 0; +foreach $sym (keys(%symbols)) { + if (!defined($symbols{$sym}{'old_type'}) or + !defined($symbols{$sym}{'type'})) { + next; + } + + # Changes in location don't hurt us, but log it anyway + if ($symbols{$sym}{'loc'} ne $symbols{$sym}{'old_loc'}) { + printf(" MOVE : %-40s : %s => %s\n", $sym, $symbols{$sym}{'old_loc'}, + $symbols{$sym}{'loc'}); + $moved++; + } + + # Changes to export type are only bad if new type isn't + # EXPORT_SYMBOL. Changing things to GPL are bad. + if ($symbols{$sym}{'type'} ne $symbols{$sym}{'old_type'}) { + printf(" TYPE : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_type'}. + $symbols{$sym}{'type'}, is_ignored($symbols{$sym}{'loc'}, $sym) + ? " (ignored)" : ""); + $changed_type++ if $symbols{$sym}{'type'} ne "EXPORT_SYMBOL" + and !is_ignored($symbols{$sym}{'loc'}, $sym); + } + + # Changes to the hash are always bad + if ($symbols{$sym}{'hash'} ne $symbols{$sym}{'old_hash'}) { + printf(" HASH : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_hash'}, + $symbols{$sym}{'hash'}, is_ignored($symbols{$sym}{'loc'}, $sym) + ? " (ignored)" : ""); + $changed_hash++ if !is_ignored($symbols{$sym}{'loc'}, $sym); + $module_syms{$symbols{$sym}{'loc'}}++; + } +} + +print "WW: $moved symbols changed location\n" if $moved; +print "$EE $changed_type symbols changed export type and weren't ignored\n" if $changed_type; +print "$EE $changed_hash symbols changed hash and weren't ignored\n" if $changed_hash; + +$errors++ if $changed_hash or $changed_type; +if ($changed_hash) { + print "II: Module hash change summary...\n"; + foreach $mod (sort { $module_syms{$b} <=> $module_syms{$a} } keys %module_syms) { + next if ! $module_syms{$mod}; + printf(" %-40s: %d\n", $mod, $module_syms{$mod}); + } +} + +print "II: Done\n"; + +if ($errors) { + exit($fail_exit); +} else { + exit(0); +} --- linux-2.6.27.orig/debian/scripts/misc/oldconfig +++ linux-2.6.27/debian/scripts/misc/oldconfig @@ -0,0 +1,64 @@ +#!/bin/bash + +# We have to be in the top level kernel source directory +if [ ! -f MAINTAINERS ] || [ ! -f Makefile ]; then + echo "This does not appear to be the kernel source directory." 1>&2 + exit 1 +fi + + +# One arg, and that's it. Just pass an architecture +if [ $# -ne 1 ]; then + echo "Usage: $0 " 1>&2 + exit 1 +fi + +arch="$1" + +case "$arch" in + amd64) kernarch="x86_64" ;; + armel) kernarch="arm" ;; + *) kernarch="$arch" ;; +esac + +confdir="`pwd`/debian/config/$arch" +bindir="`pwd`/debian/scripts/misc" + +# Make sure the architecture exists +if [ ! -d $confdir ]; then + echo "Could not find config directory for $arch" 1>&2 + exit 1 +fi + +echo "Processing $arch ($kernarch) ... " + +configs=$(cd $confdir && ls config.*) + +if [ -f $confdir/config ]; then + for config in $configs; do + case $config in + *) + cat $confdir/config >> $confdir/$config + ;; + esac + done + rm -f $confdir/config +fi + +test -d build || mkdir build +cd build +for config in $configs; do + echo "Running silentoldconfig for $config ... " + + cat $confdir/$config > .config + + make -C ../ O=`pwd` silentoldconfig ARCH=$kernarch + + cat .config > $confdir/$config +done +cd .. + +echo "Running splitconfig.pl ... " +echo + +(cd $confdir ; $bindir/splitconfig.pl) --- linux-2.6.27.orig/debian/scripts/misc/ppa-cron-job +++ linux-2.6.27/debian/scripts/misc/ppa-cron-job @@ -0,0 +1,47 @@ +#!/bin/sh + +# +# Use this script as a template for the daily kernel build cron job. +# You should copy it somewhere outside of the git tree 'cause the whole +# git tree gets removed and recreated. +# +KNAME=intrepid +DAILY_BUILD_DIR=${KBDIR:=${HOME}/${KNAME}} +KERNEL_GIT_REPO=${KREPO:=/srv/kernel.ubuntu.com/git/ubuntu/ubuntu-${KNAME}.git} + +# +# Nothing works unless there is a dput configuration. +# +if [ ! -f ${HOME}/.dput.cf ] +then + echo No dput configuration. + exit 1 +fi + +if [ ! -d ${DAILY_BUILD_DIR} ] +then + rm -rf ${DAILY_BUILD_DIR} + mkdir -p ${DAILY_BUILD_DIR} +fi + +# +# Start with a fresh repo. +# +cd ${DAILY_BUILD_DIR} +rm -rf ubuntu-${KNAME} +git clone ${KERNEL_GIT_REPO} + +# +# Remember that the success of prepare-ppa depends on +# this user account having an un-passworded GPG key. +# Otherwise it requires user intervention, e.g., a +# user must enter the GPG key password. +# +rm -f *.changes +(cd ubuntu-${KNAME}; debian/scripts/misc/prepare-ppa-source) + +find . -maxdepth 1 -type f -name "*.changes" | while read f +do + echo dput my-ppa $f +done + --- linux-2.6.27.orig/debian/scripts/misc/getabis +++ linux-2.6.27/debian/scripts/misc/getabis @@ -0,0 +1,82 @@ +#!/bin/bash + +if [ "$#" != "2" ]; then + echo "Usage: $0 " 1>&2 + exit 1 +fi + +ver=$1 +revision=$2 +abi=$(echo $revision | awk -F. '{print $1}') + +verabi=$ver-$abi +verfull=$ver-$revision + +repo="http://archive.ubuntu.com/ubuntu/pool/main/l" +repo_ports="http://ports.ubuntu.com/ubuntu-ports/pool/main/l" +repo_uni="http://archive.ubuntu.com/ubuntu/pool/universe/l" + +WGET="wget --quiet -c" + +abidir="`pwd`/debian/abi/$verfull" +tmpdir="`pwd`/abi-tmp-$verfull" +origdir="`pwd`" + +test -d $tmpdir || mkdir $tmpdir + +getall() { + arch=$1 + shift + + mkdir -p $abidir/$arch + + for sub in $@; do + if [ -f $abidir/$arch/$sub ]; then + echo "Exists: $sub" + continue + fi + echo -n "Fetching $sub..." + filename=linux-image-${verabi}-${sub}_${verfull}_${arch}.deb + cd $tmpdir + if ! [ -f $filename ]; then + $WGET $repo/linux/$filename + fi + if ! [ -f $filename ]; then + $WGET $repo_ports/linux/$filename + fi + if ! [ -f $filename ]; then + $WGET $repo_uni/linux/$filename + fi + if [ "$?" = "0" ]; then + echo -n "extracting..." + dpkg-deb --extract $filename tmp + if [ -f tmp/boot/abi-* ]; then + mv tmp/boot/abi-* $abidir/$arch/$sub + else + echo -n "NO ABI FILE..." + fi + (cd tmp; find lib/modules/$verabi-$sub/kernel -name '*.ko') | \ + sed -e 's/.*\/\([^\/]*\)\.ko/\1/' | sort > \ + $abidir/$arch/$sub.modules + rm -rf tmp $filename + echo "done." + else + echo "FAILED." + fi + cd $origdir + done +} + +# MAIN + +# Setup abi directory +mkdir -p $abidir +echo $abi > $abidir/abiname + +# NOTE: The flavours are hardcoded, because they may have changed from the +# current build. + +getall amd64 generic server +getall i386 generic server + +rmdir $tmpdir --- linux-2.6.27.orig/debian/scripts/misc/insert-changes.pl +++ linux-2.6.27/debian/scripts/misc/insert-changes.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl -w + +system("make -s -f debian/rules printchanges > debian/changes"); + +open(CHANGELOG, "< debian/changelog") or die "Cannot open changelog"; +open(CHANGES, "< debian/changes") or die "Cannot open new changes"; +open(NEW, "> debian/changelog.new") or die "Cannot open new changelog"; + +$printed = 0; + +while () { + if (/^ CHANGELOG: /) { + next if $printed; + + while () { + print NEW; + } + + $printed = 1; + } else { + print NEW; + } +} + +close(NEW); +close(CHANGES); +close(CHANGELOG); + +rename("debian/changelog.new", "debian/changelog"); +unlink("debian/changes"); --- linux-2.6.27.orig/debian/scripts/misc/splitconfig.pl +++ linux-2.6.27/debian/scripts/misc/splitconfig.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl -w + +%configs = (); +%common = (); + +print "Reading config's ...\n"; + +opendir(DIR, "."); + +while (defined($config = readdir(DIR))) { + # Only config.* + next if $config !~ /^config\..*/; + # Nothing that is disabled, or remnant + next if $config =~ /.*\.(default|disabled|stub)$/; + # Server config's are standalone + #next if $config =~ /config.server-.*/; + + %{$configs{$config}} = (); + + print " processing $config ... "; + + open(CONFIG, "< $config"); + + while () { + /^#*\s*CONFIG_(\w+)[\s=](.*)$/ or next; + + ${$configs{$config}}{$1} = $2; + + $common{$1} = $2; + } + + close(CONFIG); + + print "done.\n"; +} + +closedir(DIR); + +print "\n"; + +print "Merging lists ... \n"; + +for $config (keys(%configs)) { + my %options = %{$configs{$config}}; + + print " processing $config ... "; + + for $key (keys(%common)) { + next if not defined $common{$key}; + + # If we don't have the common option, then it isn't + # common. If we do have that option, it must have the same + # value (this is where the old split.py was broken). It + # also did the common check while it was parsing files, so + # that there were cases where a non-common option was in + # common anyway (ordering). + if (not defined($options{$key})) { + undef $common{$key}; + } elsif ($common{$key} ne $options{$key}) { + undef $common{$key}; + } + } + + print "done.\n"; +} + +print "\n"; + +print "Creating common config ... "; + +open(COMMON, "> config"); +print COMMON "#\n# Common config options automatically generated by splitconfig.pl\n#\n"; + +for $key (sort(keys(%common))) { + next if not defined $common{$key}; + + if ($common{$key} eq "is not set") { + print COMMON "# CONFIG_$key is not set\n"; + } else { + print COMMON "CONFIG_$key=$common{$key}\n"; + } +} +close(COMMON); + +print "done.\n\n"; + +print "Creating stub configs ...\n"; + +for $config (keys(%configs)) { + my %options = %{$configs{$config}}; + + print " processing $config ... "; + + open(STUB, "> $config"); + print STUB "#\n# Config options for $config automatically generated by splitconfig.pl\n#\n"; + + for $key (sort(keys(%options))) { + next if defined $common{$key}; + + if ($options{$key} eq "is not set") { + print STUB "# CONFIG_$key is not set\n"; + } else { + print STUB "CONFIG_$key=$options{$key}\n"; + } + } + + close(STUB); + + print "done.\n"; +} --- linux-2.6.27.orig/debian/scripts/misc/doconfig +++ linux-2.6.27/debian/scripts/misc/doconfig @@ -0,0 +1,64 @@ +#!/bin/bash + +# We have to be in the top level kernel source directory +if [ ! -f MAINTAINERS ] || [ ! -f Makefile ]; then + echo "This does not appear to be the kernel source directory." 1>&2 + exit 1 +fi + + +# One arg, and that's it. Just pass an architecture +if [ $# -ne 1 ]; then + echo "Usage: $0 " 1>&2 + exit 1 +fi + +arch="$1" + +case "$arch" in + amd64) kernarch="x86_64" ;; + *) kernarch="$arch" ;; +esac + +confdir="`pwd`/debian/config/$arch" +bindir="`pwd`/debian/scripts/misc" + +# Make sure the architecture exists +if [ ! -d $confdir ]; then + echo "Could not find config directory for $arch" 1>&2 + exit 1 +fi + +echo "Processing $arch ($kernarch) ... " + +configs=$(cd $confdir && ls config.*) + +if [ -f $confdir/config ]; then + for config in $configs; do + case $config in + *) + cat $confdir/config >> $confdir/$config + ;; + esac + done + rm -f $confdir/config +fi + +test -d build || mkdir build +cd build +for config in $configs; do + + cat $confdir/$config > .config + + echo About to configure $arch $config + read + make -C ../ O=`pwd` ARCH=$kernarch menuconfig + + cat .config > $confdir/$config +done +cd .. + +echo "Running splitconfig.pl ... " +echo + +(cd $confdir ; $bindir/splitconfig.pl) --- linux-2.6.27.orig/debian/scripts/misc/prepare-ppa-source +++ linux-2.6.27/debian/scripts/misc/prepare-ppa-source @@ -0,0 +1,106 @@ +#!/bin/sh +# +# This script prepares a source upload for a PPA build. +# +LAST_UPLOAD=../last-ppa-upload +LAST_GIT_CHANGELOG=../last_git_changelog +LAST_PPA_CHANGELOG=../last_ppa_changelog +PPA_FILE="`make --no-print-directory -f debian/rules print-ppa-file-name`" + +if [ "$1" = "scrub" ] +then + SCRUB=1 +fi + +# +# The identity of the git committer must be known. +# +if [ ! -z "$GIT_AUTHOR_NAME" ] && [ ! -z "$GIT_AUTHOR_EMAIL" ] +then + SIGNER_NAME="$GIT_AUTHOR_NAME" + SIGNER_EMAIL="$GIT_AUTHOR_EMAIL" +elif [ ! -z "$GIT_COMMITTER_NAME" ] && [ ! -z "$GIT_COMMITTER_EMAIL" ] +then + SIGNER_NAME="$GIT_COMMITTER_NAME" + SIGNER_EMAIL="$GIT_COMMITTER_EMAIL" +else + echo Error: Unknown committer. + exit 1 +fi + +# +# git current and cleanup. +# +git checkout -f +git ls-files --others | xargs rm -rf + +# +# Don't bother if the repo hasn't changed since the last upload. +# +if [ ! -f ${LAST_UPLOAD} ] +then + touch ${LAST_UPLOAD} +fi +git log|head -n 1|sed 's/commit //' > ${LAST_UPLOAD}.tmp +if cmp ${LAST_UPLOAD} ${LAST_UPLOAD}.tmp > /dev/null +then + rm -f ${LAST_UPLOAD}.tmp + echo No upload needed. + exit 0 +fi +mv ${LAST_UPLOAD}.tmp ${LAST_UPLOAD} + +# +# The git HEAD can change without anyone updating the debian/changelog. +# However, if the changelog version is updated, then we want to work +# forward from that version. +# +cp debian/changelog changelog.sav +if [ -f ${LAST_GIT_CHANGELOG} ] && [ -f ${LAST_PPA_CHANGELOG} ] +then + # + # If the changelog has not changed, then work forward from the + # last daily build version. + # + if cmp ${LAST_GIT_CHANGELOG} debian/changelog > /dev/null + then + cp ${LAST_PPA_CHANGELOG} debian/changelog + fi +fi +mv changelog.sav ${LAST_GIT_CHANGELOG} + +# +# Notify the build scripts that this is a PPA build. +# +cp -v ${LAST_UPLOAD} ${PPA_FILE} + +# +# In order to sign the package you must override the first signer's changelog entry. +# +export DEBEMAIL="$SIGNER_EMAIL" +export DEBFULLNAME="$SIGNER_NAME" +DEBCHANGE_COMMENT="PPA Upload from git HEAD `cat ${LAST_UPLOAD}`" +debchange --increment --preserve "${DEBCHANGE_COMMENT}" +if ! head -n 1 debian/changelog | grep ubuntu > /dev/null +then + echo debchange did not work. + exit 1 +fi + +# +# Make sure the third changelog field says hardy. +# +sed -i 's/) .*;/) hardy;/1' debian/changelog + +# +# Make sure the next daily build works forward from this version if the git +# changelog has not changed. +# +cp debian/changelog ${LAST_PPA_CHANGELOG} + +rm -rf ../linux* include/config .config +dpkg-buildpackage -S -sa -rfakeroot -I.git -I.gitignore -i'\.git.*' + +rm -f ${PPA_FILE} +exit 0 + --- linux-2.6.27.orig/debian/scripts/misc/git-ubuntu-log +++ linux-2.6.27/debian/scripts/misc/git-ubuntu-log @@ -0,0 +1,220 @@ +#!/usr/bin/perl -w + +use strict; +use Text::Wrap; + +my $kernel_auth = "Upstream Kernel Changes"; + +my (%map, @reverts); +my $pstate = 1; +my $no_kern_log = 0; +my $print_shas = 0; +my $first_print = 1; + +while (@ARGV) { + my $opt = $ARGV[0]; + shift; + if ($opt eq "--no-kern-log") { + $no_kern_log = 1; + } elsif ($opt eq "--print-shas") { + $print_shas = 1; + } else { + print STDERR "Unknown options: $opt\n"; + exit(1); + } +} + +sub check_reverts($) { + my ($entry) = @_; + my ($check); + + foreach $check (reverse @reverts) { + my $desc = "Revert \"" . $entry->{'desc'} . "\""; + if ($check->{'desc'} eq $desc) { + @reverts = grep($_->{'desc'} ne $desc, @reverts); + return 1; + } + } + + return 0; +} + +sub add_entry($) { + my ($entry) = @_; + my $key = $entry->{'author'}; + + # store description in array, in email->{desc list} map + if (exists $map{$key}) { + # grab ref + my $obj = $map{$key}; + + # add desc to array + push(@$obj, $entry); + } else { + # create new array, containing 1 item + my @arr = ($entry); + + # store ref to array + $map{$key} = \@arr; + } +} + +sub shortlog_entry($$$$$) { + my ($name, $desc, $bug, $cve, $commit) = @_; + my $entry; + + $desc =~ s#/pub/scm/linux/kernel/git/#/.../#g; + $desc =~ s#\[PATCH\] ##g; + + $desc =~ s#^\s*##g; + $desc =~ s# *UBUNTU: ##g; + + $entry->{'desc'} = $desc; + $entry->{'bugno'} = $bug; + $entry->{'cve'} = $cve; + $entry->{'commit'} = $commit; + $entry->{'author'} = $name; + + if ($desc =~ /^Revert "/) { + push(@reverts, $entry); + return; + } + + return if check_reverts($entry); + + add_entry($entry); +} + +# sort comparison function +sub by_name($$) { + my ($a, $b) = @_; + + uc($a) cmp uc($b); +} + +sub shortlog_output { + my ($obj, $key, $entry); + + foreach $key (sort by_name keys %map) { + next if $key eq $kernel_auth and $no_kern_log; + + print "\n" unless $first_print; + $first_print = 0; + + # output author + printf " [ %s ]\n\n", $key; + + # output author's 1-line summaries + $obj = $map{$key}; + foreach $entry (reverse @$obj) { + print wrap(" * ", " ", $entry->{'desc'}) . "\n"; + # For non upstream changes, add other info. + if ($key ne $kernel_auth) { + if ($print_shas) { + print " - GIT-SHA " . $entry->{'commit'} . + "\n"; + } + } + if (defined($entry->{'bugno'})) { + print " - LP: #" . $entry->{'bugno'} . "\n"; + } + if (defined($entry->{'cve'})) { + print " - " . $entry->{'cve'} . "\n"; + } + } + } +} + +sub changelog_input { + my ($author, $desc, $commit, $entry, $cve); + + while () { + # get commit + if ($pstate == 1) { + next unless /^commit (.*)/; + + $commit = $1; + + $pstate++; + } + + # get author and email + elsif ($pstate == 2) { + my ($email); + + next unless /^[Aa]uthor:?\s*(.*?)\s*<(.*)>/; + + $author = $1; + $email = $2; + $desc = undef; + $cve = undef; + + # cset author fixups + if (!$author) { + $author = $email; + } + $pstate++; + } + + # skip to blank line + elsif ($pstate == 3) { + next unless /^\s*$/; + $pstate++; + } + + # skip to non-blank line + elsif ($pstate == 4) { + next unless /^\s*?(.*)/; + my $ignore = 0; + my $bug = undef; + + # skip lines that are obviously not + # a 1-line cset description + next if /^\s*From: /; + + chomp; + $desc = $1; + + if ($desc =~ /^ *(Revert "|)UBUNTU:/) { + while () { + $ignore = 1 if /^ *Ignore: yes/i; + $bug = $2 if /^ *Bug: *(#|)(.*)/; + $cve = $1 if /^ *(CVE-.*)/; + last if /^commit /; + } + } else { + $author = $kernel_auth; + $ignore = 1 if $desc =~ /Merge /; + while () { + $bug = $2 if /^ *Bug: *(#|)(.*)/; + $cve = $1 if /^ *(CVE-.*)/; + last if /^commit /; + } + } + + if (!$ignore) { + &shortlog_entry($author, $desc, $bug, + $cve, $commit, 0); + } + + $pstate = 1; + if ($_ && /^commit (.*)/) { + $commit = $1; + $pstate++; + } + } + + else { + die "invalid parse state $pstate"; + } + } + + foreach $entry (@reverts) { + add_entry($entry); + } +} + +&changelog_input; +&shortlog_output; + +exit(0); --- linux-2.6.27.orig/debian/scripts/misc/retag +++ linux-2.6.27/debian/scripts/misc/retag @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w + +open(TAGS, "git-tag -l |") or die "Could not get list of tags"; +@tags = ; +close(TAGS); + +open(LOGS, "git-log --pretty=short |") or die "ERROR: Calling git-log"; +my $commit = ""; + +while () { + my $origtag; + + if (m|^commit (.*)$|) { + $commit = $1; + next; + } + + m|\s*UBUNTU: (Ubuntu-2\.6\..*)| or next; + + $tag = $1; + + ($origtag) = grep(/^$tag.orig$/, @tags); + + if (!defined($origtag)) { + print "I: Adding original tag for $tag\n"; + system("git-tag -m $tag $tag.orig $tag"); + } + + print "I: Tagging $tag => $commit\n"; + + system("git-tag -f -m $tag $tag $commit"); +} + +close(LOGS); --- linux-2.6.27.orig/debian/stamps/keep-dir +++ linux-2.6.27/debian/stamps/keep-dir @@ -0,0 +1 @@ +Place holder --- linux-2.6.27.orig/debian/rules.d/4-checks.mk +++ linux-2.6.27/debian/rules.d/4-checks.mk @@ -0,0 +1,26 @@ +# Check ABI for package against last release (if not same abinum) +abi-%: $(abidir)/% + @# Empty for make to be happy +$(abidir)/%: $(stampdir)/stamp-build-% + install -d $(abidir) + sed -e 's/^\(.\+\)[[:space:]]\+\(.\+\)[[:space:]]\(.\+\)$$/\3 \2 \1/' \ + $(builddir)/build-$*/Module.symvers | sort > $@ + +abi-check-%: $(abidir)/% + @perl -f debian/scripts/abi-check "$*" "$(prev_abinum)" "$(abinum)" \ + "$(prev_abidir)" "$(abidir)" "$(skipabi)" + +# Check the module list against the last release (always) +module-%: $(abidir)/%.modules + @# Empty for make to be happy +$(abidir)/%.modules: $(stampdir)/stamp-build-% + install -d $(abidir) + find $(builddir)/build-$*/ -name \*.ko | \ + sed -e 's/.*\/\([^\/]*\)\.ko/\1/' | sort > $@ + +module-check-%: $(abidir)/%.modules + @perl -f debian/scripts/module-check "$*" \ + "$(prev_abidir)" "$(abidir)" $(skipmodule) + +checks-%: abi-check-% module-check-% + @# Will be calling more stuff later --- linux-2.6.27.orig/debian/rules.d/amd64.mk +++ linux-2.6.27/debian/rules.d/amd64.mk @@ -0,0 +1,12 @@ +build_arch = x86_64 +header_arch = $(build_arch) +asm_link = x86 +defconfig = defconfig +flavours = generic server +build_image = bzImage +kernel_file = arch/$(build_arch)/boot/bzImage +install_file = vmlinuz + +server_sub = virtual + +loader = grub --- linux-2.6.27.orig/debian/rules.d/2-binary-arch.mk +++ linux-2.6.27/debian/rules.d/2-binary-arch.mk @@ -0,0 +1,277 @@ +# We don't want make removing intermediary stamps +.SECONDARY : + +# Prepare the out-of-tree build directory + +prepare-%: $(stampdir)/stamp-prepare-% + @# Empty for make to be happy +$(stampdir)/stamp-prepare-%: target_flavour = $* +$(stampdir)/stamp-prepare-%: $(confdir)/config $(confdir)/config.% + @echo "Preparing $*..." + install -d $(builddir)/build-$* + touch $(builddir)/build-$*/ubuntu-build + cat $^ | sed -e 's/.*CONFIG_VERSION_SIGNATURE.*/CONFIG_VERSION_SIGNATURE="Ubuntu $(release)-$(revision)-$*"/' > $(builddir)/build-$*/.config + find $(builddir)/build-$* -name "*.ko" | xargs rm -f + $(kmake) O=$(builddir)/build-$* silentoldconfig prepare scripts + touch $@ + + +# Do the actual build, including image and modules +build-%: $(stampdir)/stamp-build-% + @# Empty for make to be happy +$(stampdir)/stamp-build-%: target_flavour = $* +$(stampdir)/stamp-build-%: $(stampdir)/stamp-prepare-% + @echo "Building $*..." + $(kmake) O=$(builddir)/build-$* $(conc_level) $(build_image) + $(kmake) O=$(builddir)/build-$* $(conc_level) modules + @touch $@ + +# Install the finished build +install-%: pkgdir = $(CURDIR)/debian/linux-image-$(abi_release)-$* +install-%: dbgpkgdir = $(CURDIR)/debian/linux-image-debug-$(abi_release)-$* +install-%: basepkg = linux-headers-$(abi_release) +install-%: hdrdir = $(CURDIR)/debian/$(basepkg)-$*/usr/src/$(basepkg)-$* +install-%: target_flavour = $* +install-%: $(stampdir)/stamp-build-% checks-% + dh_testdir + dh_testroot + dh_clean -k -plinux-image-$(abi_release)-$* + dh_clean -k -plinux-headers-$(abi_release)-$* + dh_clean -k -plinux-image-debug-$(abi_release)-$* + + # The main image + install -m644 -D $(builddir)/build-$*/$(kernel_file) \ + $(pkgdir)/boot/$(install_file)-$(abi_release)-$* + + install -m644 $(builddir)/build-$*/.config \ + $(pkgdir)/boot/config-$(abi_release)-$* + install -m644 $(abidir)/$* \ + $(pkgdir)/boot/abi-$(abi_release)-$* + install -m644 $(builddir)/build-$*/System.map \ + $(pkgdir)/boot/System.map-$(abi_release)-$* +ifeq ($(no_dumpfile),) + makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \ + -x $(builddir)/build-$*/vmlinux +endif + + $(kmake) O=$(builddir)/build-$* modules_install \ + INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$(pkgdir)/ \ + INSTALL_FW_PATH=$(pkgdir)/lib/firmware/$(abi_release)-$* + +ifeq ($(no_dumpfile),) + makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \ + -x $(builddir)/build-$*/vmlinux +endif + rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/build + rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/source + + # Some initramfs-tools specific modules + install -d $(pkgdir)/lib/modules/$(abi_release)-$*/initrd + if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko ]; then\ + ln -f $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko \ + $(pkgdir)/lib/modules/$(abi_release)-$*/initrd/; \ + fi + + # Now the image scripts + install -d $(pkgdir)/DEBIAN + for script in postinst postrm preinst prerm; do \ + sed -e 's/=V/$(abi_release)-$*/g' -e 's/=K/$(install_file)/g' \ + -e 's/=L/$(loader)/g' -e 's@=B@$(build_arch)@g' \ + debian/control-scripts/$$script > $(pkgdir)/DEBIAN/$$script; \ + chmod 755 $(pkgdir)/DEBIAN/$$script; \ + done + +ifneq ($(skipsub),true) + @set -e; for sub in $($(*)_sub); do \ + TO=$$sub FROM=$* ABI_RELEASE=$(abi_release) $(SHELL) \ + debian/scripts/sub-flavour; \ + /sbin/depmod -b debian/linux-image-$(abi_release)-$$sub \ + -ea -F debian/linux-image-$(abi_release)-$$sub/boot/System.map-$(abi_release)-$* \ + $(abi_release)-$*; \ + install -d debian/linux-image-$(abi_release)-$$sub/DEBIAN; \ + for script in postinst postrm preinst prerm; do \ + sed -e 's/=V/$(abi_release)-$*/g' \ + -e 's/=K/$(install_file)/g' \ + -e 's/=L/$(loader)/g' \ + -e 's@=B@$(build_arch)@g' \ + debian/control-scripts/$$script > \ + debian/linux-image-$(abi_release)-$$sub/DEBIAN/$$script;\ + chmod 755 debian/linux-image-$(abi_release)-$$sub/DEBIAN/$$script;\ + done; \ + done +endif + +ifneq ($(skipdbg),true) + # Debug image is simple + install -m644 -D $(builddir)/build-$*/vmlinux \ + $(dbgpkgdir)/usr/lib/debug/boot/vmlinux-$(abi_release)-$* + $(kmake) O=$(builddir)/build-$* modules_install \ + INSTALL_MOD_PATH=$(dbgpkgdir)/usr/lib/debug + rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/build + rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/source + rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/modules.* + rm -fr $(dbgpkgdir)/usr/lib/debug/lib/firmware +endif + + # The flavour specific headers image + # TODO: Would be nice if we didn't have to dupe the original builddir + install -d -m755 $(hdrdir) + cat $(builddir)/build-$*/.config | \ + sed -e 's/.*CONFIG_DEBUG_INFO=.*/# CONFIG_DEBUG_INFO is not set/g' > \ + $(hdrdir)/.config + chmod 644 $(hdrdir)/.config + $(kmake) O=$(hdrdir) silentoldconfig prepare scripts + # We'll symlink this stuff + rm -f $(hdrdir)/Makefile + rm -rf $(hdrdir)/include2 + # Script to symlink everything up + $(SHELL) debian/scripts/link-headers "$(hdrdir)" "$(basepkg)" "$*" + # Setup the proper asm symlink + rm -f $(hdrdir)/include/asm + ln -s asm-$(asm_link) $(hdrdir)/include/asm + # The build symlink + install -d debian/$(basepkg)-$*/lib/modules/$(abi_release)-$* + ln -s /usr/src/$(basepkg)-$* \ + debian/$(basepkg)-$*/lib/modules/$(abi_release)-$*/build + # And finally the symvers + install -m644 $(builddir)/build-$*/Module.symvers \ + $(hdrdir)/Module.symvers + + # Now the header scripts + install -d $(CURDIR)/debian/$(basepkg)-$*/DEBIAN + for script in postinst; do \ + sed -e 's/=V/$(abi_release)-$*/g' -e 's/=K/$(install_file)/g' \ + debian/control-scripts/headers-$$script > \ + $(CURDIR)/debian/$(basepkg)-$*/DEBIAN/$$script; \ + chmod 755 $(CURDIR)/debian/$(basepkg)-$*/DEBIAN/$$script; \ + done + + # At the end of the package prep, call the tests + DPKG_ARCH="$(arch)" KERN_ARCH="$(build_arch)" FLAVOUR="$*" \ + VERSION="$(abi_release)" REVISION="$(revision)" \ + PREV_REVISION="$(prev_revision)" ABI_NUM="$(abinum)" \ + PREV_ABI_NUM="$(prev_abinum)" BUILD_DIR="$(builddir)/build-$*" \ + INSTALL_DIR="$(pkgdir)" SOURCE_DIR="$(CURDIR)" \ + run-parts -v debian/tests + + # + # Remove files which are generated at installation by postinst. + # + rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.* + +headers_tmp := $(CURDIR)/debian/tmp-headers +headers_dir := $(CURDIR)/debian/linux-libc-dev + +hmake := $(MAKE) -C $(CURDIR) O=$(headers_tmp) SUBLEVEL=$(SUBLEVEL) \ + EXTRAVERSION=-$(abinum) INSTALL_HDR_PATH=$(headers_tmp)/install \ + SHELL="$(SHELL)" ARCH=$(header_arch) + +install-arch-headers: + dh_testdir + dh_testroot + dh_clean -k -plinux-libc-dev + + rm -rf $(headers_tmp) + install -d $(headers_tmp) $(headers_dir)/usr/include/ + + $(hmake) $(defconfig) + mv $(headers_tmp)/.config $(headers_tmp)/.config.old + sed -e 's/^# \(CONFIG_MODVERSIONS\) is not set$$/\1=y/' \ + -e 's/.*CONFIG_LOCALVERSION_AUTO.*/# CONFIG_LOCALVERSION_AUTO is not set/' \ + $(headers_tmp)/.config.old > $(headers_tmp)/.config + $(hmake) silentoldconfig + $(hmake) headers_install + + mv $(headers_tmp)/install/include/asm* \ + $(headers_dir)/usr/include/ + mv $(headers_tmp)/install/include/linux \ + $(headers_dir)/usr/include/ + + rm -rf $(headers_tmp) + +binary-arch-headers: install-arch-headers + dh_testdir + dh_testroot + + dh_installchangelogs -plinux-libc-dev + dh_installdocs -plinux-libc-dev + dh_compress -plinux-libc-dev + dh_fixperms -plinux-libc-dev + dh_installdeb -plinux-libc-dev + dh_gencontrol -plinux-libc-dev + dh_md5sums -plinux-libc-dev + dh_builddeb -plinux-libc-dev + +binary-%: pkgimg = linux-image-$(abi_release)-$* +binary-%: pkghdr = linux-headers-$(abi_release)-$* +binary-%: dbgpkg = linux-image-debug-$(abi_release)-$* +binary-%: install-% + dh_testdir + dh_testroot + + dh_installchangelogs -p$(pkgimg) + dh_installdocs -p$(pkgimg) + dh_compress -p$(pkgimg) + dh_fixperms -p$(pkgimg) + dh_installdeb -p$(pkgimg) + dh_gencontrol -p$(pkgimg) + dh_md5sums -p$(pkgimg) + dh_builddeb -p$(pkgimg) -- -Zbzip2 -z9 + + dh_installchangelogs -p$(pkghdr) + dh_installdocs -p$(pkghdr) + dh_compress -p$(pkghdr) + dh_fixperms -p$(pkghdr) + dh_shlibdeps -p$(pkghdr) + dh_installdeb -p$(pkghdr) + dh_gencontrol -p$(pkghdr) + dh_md5sums -p$(pkghdr) + dh_builddeb -p$(pkghdr) + +ifneq ($(skipsub),true) + @set -e; for sub in $($(*)_sub); do \ + pkg=linux-image-$(abi_release)-$$sub; \ + dh_installchangelogs -p$$pkg; \ + dh_installdocs -p$$pkg; \ + dh_compress -p$$pkg; \ + dh_fixperms -p$$pkg; \ + dh_shlibdeps -p$$pkg; \ + dh_installdeb -p$$pkg; \ + dh_gencontrol -p$$pkg; \ + dh_md5sums -p$$pkg; \ + dh_builddeb -p$$pkg; \ + done +endif + +ifneq ($(skipdbg),true) + dh_installchangelogs -p$(dbgpkg) + dh_installdocs -p$(dbgpkg) + dh_compress -p$(dbgpkg) + dh_fixperms -p$(dbgpkg) + dh_installdeb -p$(dbgpkg) + dh_gencontrol -p$(dbgpkg) + dh_md5sums -p$(dbgpkg) + dh_builddeb -p$(dbgpkg) + + # Hokay...here's where we do a little twiddling... + mv ../$(dbgpkg)_$(release)-$(revision)_$(arch).deb \ + ../$(dbgpkg)_$(release)-$(revision)_$(arch).ddeb + grep -v '^$(dbgpkg)_.*$$' debian/files > debian/files.new + mv debian/files.new debian/files + # Now, the package wont get into the archive, but it will get put + # into the debug system. +endif + +$(stampdir)/stamp-flavours: + @echo $(flavours) > $@ + +binary-debs: $(stampdir)/stamp-flavours $(addprefix binary-,$(flavours)) \ + binary-arch-headers + +build-arch: $(addprefix build-,$(flavours)) + +binary-arch-deps = binary-debs +ifeq ($(AUTOBUILD),) +binary-arch-deps += binary-udebs +endif +binary-arch: $(binary-arch-deps) --- linux-2.6.27.orig/debian/rules.d/1-maintainer.mk +++ linux-2.6.27/debian/rules.d/1-maintainer.mk @@ -0,0 +1,104 @@ +# The following targets are for the maintainer only! do no run if you don't +# know what they do. + +.PHONY: printenv updateconfigs printchanges insertchanges startnewrelease diffupstream help + +help: + @echo "These are the targets in addition to the normal debian ones:" + @echo + @echo " printenv : Print some variables used in the build" + @echo + @echo " updateconfigs : Update debian/config/*" + @echo + @echo " editconfigs : Update debian/config/* interactively" + @echo + @echo " printchanges : Print the current changelog entries (from git)" + @echo + @echo " insertchanges : Insert current changelog entries (from git)" + @echo + @echo " startnewrelease : Start a new changelog set" + @echo + @echo " diffupstream : Diff stock kernel code against upstream (git)" + @echo + @echo " help : If you are kernel hacking, you need the professional" + @echo " version of this" + @echo + @echo "Environment variables:" + @echo + @echo " NOKERNLOG : Do not add upstream kernel commits to changelog" + @echo " CONCURRENCY_LEVEL=X" + @echo " : Use -jX for kernel compile" + @echo " PRINTSHAS : Include SHAs for commits in changelog" + +ARCH_CONFIGS=i386 amd64 armel + +updateconfigs: + dh_testdir + @for arch in $(ARCH_CONFIGS); do \ + $(SHELL) debian/scripts/misc/oldconfig $$arch; \ + done + rm -rf build + +editconfigs: + dh_testdir + @for arch in $(ARCH_CONFIGS); do \ + $(SHELL) debian/scripts/misc/doconfig $$arch; \ + done + rm -rf build + +printenv: + dh_testdir + @echo "release = $(release)" + @echo "revisions = $(revisions)" + @echo "revision = $(revision)" + @echo "prev_revisions = $(prev_revisions)" + @echo "prev_revision = $(prev_revision)" + @echo "abinum = $(abinum)" + @echo "gitver = $(gitver)" + @echo "flavours = $(flavours)" + @echo "skipabi = $(skipabi)" + @echo "skipmodule = $(skipmodule)" + @echo "skipdbg = $(skipdbg)" + @echo "ubuntu_log_opts = $(ubuntu_log_opts)" +ifneq ($(SUBLEVEL),) + @echo "SUBLEVEL = $(SUBLEVEL)" +endif + @echo "CONCURRENCY_LEVEL = $(CONCURRENCY_LEVEL)" + +printchanges: + @git-log Ubuntu-$(release)-$(prev_revision)..HEAD | \ + perl -w -f debian/scripts/misc/git-ubuntu-log $(ubuntu_log_opts) + +insertchanges: + @perl -w -f debian/scripts/misc/insert-changes.pl + +diffupstream: + @git-diff-tree -p refs/remotes/linux-2.6/master..HEAD $(shell ls | grep -vE '^(ubuntu|debian|\.git.*)') + +startnewrelease: + dh_testdir + @nextminor=$(shell expr `echo $(revision) | awk -F. '{print $$2}'` + 1); \ + now="$(shell date -R)"; \ + echo "Creating new changelog set for $(abi_release).$$nextminor..."; \ + echo -e "$(stub) ($(abi_release).$$nextminor) UNRELEASED; urgency=low\n" > debian/changelog.new; \ + echo " CHANGELOG: Do not edit directly. Autogenerated at release." >> \ + debian/changelog.new; \ + echo " CHANGELOG: Use the printchanges target to see the curent changes." \ + >> debian/changelog.new; \ + echo " CHANGELOG: Use the insertchanges target to create the final log." \ + >> debian/changelog.new; \ + echo -e "\n -- $$DEBFULLNAME <$$DEBEMAIL> $$now\n" >> \ + debian/changelog.new ; \ + cat debian/changelog >> debian/changelog.new; \ + mv debian/changelog.new debian/changelog +# +# If $(ppa_file) exists, then only the standard flavours are built for PPA, e.g., +# 386, 386-generic, and amd64-generic. +# +prepare-ppa: + @echo Execute debian/scripts/misc/prepare-ppa-source to prepare an upload + @echo for a PPA build. You must do this outside of debian/rules since it cannot + @echo nest. + +print-ppa-file-name: + @echo $(ppa_file) --- linux-2.6.27.orig/debian/rules.d/i386.mk +++ linux-2.6.27/debian/rules.d/i386.mk @@ -0,0 +1,12 @@ +build_arch = i386 +header_arch = x86_64 +asm_link = x86 +defconfig = defconfig +flavours = generic server +build_image = bzImage +kernel_file = arch/$(build_arch)/boot/bzImage +install_file = vmlinuz + +server_sub = virtual + +loader = grub --- linux-2.6.27.orig/debian/rules.d/3-binary-indep.mk +++ linux-2.6.27/debian/rules.d/3-binary-indep.mk @@ -0,0 +1,82 @@ +build-indep: + +docpkg = linux-doc-$(release) +docdir = $(CURDIR)/debian/$(docpkg)/usr/share/doc/$(docpkg) +install-doc: + dh_testdir + dh_testroot + dh_clean -k -p$(docpkg) + + install -d $(docdir) + + # First the html docs. We skip these for autobuilds + if [ -z "$(AUTOBUILD) nobuild" ]; then \ + install -d $(docdir)/linux-doc-tmp; \ + $(kmake) O=$(docdir)/linux-doc-tmp htmldocs; \ + mv $(docdir)/linux-doc-tmp/Documentation/DocBook \ + $(docdir)/html; \ + rm -rf $(docdir)/linux-doc-tmp; \ + fi + + # Copy the rest + cp -a Documentation/* $(docdir) + rm -rf $(docdir)/DocBook + +indep_hdrpkg = linux-headers-$(abi_release) +indep_hdrdir = $(CURDIR)/debian/$(indep_hdrpkg)/usr/src/$(indep_hdrpkg) +install-headers: + dh_testdir + dh_testroot + dh_clean -k -p$(indep_hdrpkg) + + install -d $(indep_hdrdir) + find . -path './debian/*' -prune -o -path './include/*' -prune \ + -o -path './scripts/*' -prune -o -type f \ + \( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \ + -name '*.sh' -o -name '*.pl' -o -name '*.lds' \) \ + -print | cpio -pd --preserve-modification-time $(indep_hdrdir) + cp -a scripts include $(indep_hdrdir) + +srcpkg = linux-source-$(release) +srcdir = $(CURDIR)/debian/$(srcpkg)/usr/src/$(srcpkg) +install-source: + dh_testdir + dh_testroot + dh_clean -k -p$(srcpkg) + + install -d $(srcdir) + find . -path './debian/*' -prune -o \ + -path './.*' -prune -o -print | \ + cpio -pd --preserve-modification-time $(srcdir) + (cd $(srcdir)/..; tar cf - $(srcpkg)) | bzip2 -9c > \ + $(srcdir).tar.bz2 + rm -rf $(srcdir) + +install-indep: install-headers install-doc install-source + +# This is just to make it easy to call manually. Normally done in +# binary-indep target during builds. +binary-headers: install-headers + dh_testdir + dh_testroot + dh_installchangelogs -p$(indep_hdrpkg) + dh_installdocs -p$(indep_hdrpkg) + dh_compress -p$(indep_hdrpkg) + dh_fixperms -p$(indep_hdrpkg) + dh_installdeb -p$(indep_hdrpkg) + dh_gencontrol -p$(indep_hdrpkg) + dh_md5sums -p$(indep_hdrpkg) + dh_builddeb -p$(indep_hdrpkg) + +binary-indep: install-indep + dh_testdir + dh_testroot + + dh_installchangelogs -i + dh_installdocs -i + dh_compress -i + dh_fixperms -i + dh_installdeb -i + dh_gencontrol -i + dh_md5sums -i + dh_builddeb -i --- linux-2.6.27.orig/debian/rules.d/0-common-vars.mk +++ linux-2.6.27/debian/rules.d/0-common-vars.mk @@ -0,0 +1,97 @@ +# Get some version info +stub=linux + +release := $(shell sed -n '1s/^.*(\(.*\)-.*).*$$/\1/p' debian/changelog) +revisions := $(shell sed -n 's/^$(stub)\ .*($(release)-\(.*\)).*$$/\1/p' debian/changelog | tac) +revision ?= $(word $(words $(revisions)),$(revisions)) +prev_revisions := $(filter-out $(revision),0.0 $(revisions)) +prev_revision := $(word $(words $(prev_revisions)),$(prev_revisions)) + +# This is an internally used mechanism for the daily kernel builds. It +# creates packages who's ABI is suffixed with a minimal representation of +# the current git HEAD sha. If .git/HEAD is not present, then it uses the +# uuidgen program, +# +# AUTOBUILD can also be used by anyone wanting to build a custom kernel +# image, or rebuild the entire set of Ubuntu packages using custom patches +# or configs. +AUTOBUILD= + +# +# This is a way to support some external variables. A good example is +# a local setup for ccache and distcc See LOCAL_ENV_CC and +# LOCAL_ENV_DISTCC_HOSTS in the definition of kmake. +# For example: +# LOCAL_ENV_CC="ccache distcc" +# LOCAL_ENV_DISTCC_HOSTS="localhost 10.0.2.5 10.0.2.221" +# +-include $(CURDIR)/../.intrepid-env + +ifneq ($(AUTOBUILD),) +skipabi = true +skipmodule = true +skipdbg = true +gitver=$(shell if test -f .git/HEAD; then cat .git/HEAD; else uuidgen; fi) +gitverpre=$(shell echo $(gitver) | cut -b -3) +gitverpost=$(shell echo $(gitver) | cut -b 38-40) +abi_suffix = -$(gitverpre)$(gitverpost) +endif + +ifneq ($(NOKERNLOG),) +ubuntu_log_opts += --no-kern-log +endif +ifneq ($(PRINTSHAS),) +ubuntu_log_opts += --print-shas +endif + +ifeq ($(wildcard /CurrentlyBuilding),) +skipdbg=true +endif + +abinum := $(shell echo $(revision) | sed -e 's/\..*//')$(abi_suffix) +prev_abinum := $(shell echo $(prev_revision) | sed -e 's/\..*//')$(abi_suffix) + +abi_release := $(release)-$(abinum) + +# We force the sublevel to be exactly what we want. The actual source may +# be an in development git tree. We want to force it here instead of +# committing changes to the top level Makefile +SUBLEVEL := $(shell echo $(release) | awk -F. '{print $$3}') + +arch := $(shell dpkg-architecture -qDEB_HOST_ARCH) +abidir := $(CURDIR)/debian/abi/$(release)-$(revision)/$(arch) +prev_abidir := $(CURDIR)/debian/abi/$(release)-$(prev_revision)/$(arch) +confdir := $(CURDIR)/debian/config/$(arch) +builddir := $(CURDIR)/debian/build +stampdir := $(CURDIR)/debian/stamps + +# Support parallel= in DEB_BUILD_OPTIONS (see #209008) +COMMA=, +DEB_BUILD_OPTIONS_PARA = $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS)))) +ifneq (,$(DEB_BUILD_OPTIONS_PARA)) + CONCURRENCY_LEVEL := $(DEB_BUILD_OPTIONS_PARA) +endif + +ifeq ($(CONCURRENCY_LEVEL),) + # Check the environment + CONCURRENCY_LEVEL := $(shell echo $$CONCURRENCY_LEVEL) + # No? Check if this is on a buildd + ifeq ($(CONCURRENCY_LEVEL),) + ifeq ($(wildcard /CurrentlyBuilding),) + CONCURRENCY_LEVEL := $(shell expr `getconf _NPROCESSORS_ONLN` \* 2) + endif + endif + # Oh hell, give 'em one + ifeq ($(CONCURRENCY_LEVEL),) + CONCURRENCY_LEVEL := 1 + endif +endif + +conc_level = -j$(CONCURRENCY_LEVEL) + +# target_flavour is filled in for each step +kmake = make ARCH=$(build_arch) EXTRAVERSION=-$(abinum)-$(target_flavour) \ + CONFIG_DEBUG_SECTION_MISMATCH=y SUBLEVEL=$(SUBLEVEL) +ifneq ($(LOCAL_ENV_CC),) +kmake += CC=$(LOCAL_ENV_CC) DISTCC_HOSTS=$(LOCAL_ENV_DISTCC_HOSTS) +endif --- linux-2.6.27.orig/debian/rules.d/5-udebs.mk +++ linux-2.6.27/debian/rules.d/5-udebs.mk @@ -0,0 +1,33 @@ +# Do udebs if not disabled in the arch-specific makefile +binary-udebs: binary-debs debian/control +ifeq ($(disable_d_i),) + debian/rules do-binary-udebs; +endif + +do-binary-udebs: + dh_testdir + dh_testroot + + # unpack the kernels into a temporary directory + mkdir -p debian/d-i-${arch} + + imagelist=$$(cat kernel-versions | grep ^${arch} | awk '{print $$4}') && \ + for i in $$imagelist; do \ + dpkg -x $$(ls ../linux-image-$$i\_$(release)-$(revision)_${arch}.deb) \ + debian/d-i-${arch}; \ + /sbin/depmod -b debian/d-i-${arch} $$i; \ + done + + touch ignore-dups + export SOURCEDIR=debian/d-i-${arch} && \ + kernel-wedge install-files && \ + kernel-wedge check + + # Build just the udebs + dilist=$$(dh_listpackages -s | grep "\-di$$") && \ + [ -z "$dilist" ] || \ + for i in $$dilist; do \ + dh_fixperms -p$$i; \ + dh_gencontrol -p$$i; \ + dh_builddeb -p$$i; \ + done --- linux-2.6.27.orig/debian/rules.d/armel.mk +++ linux-2.6.27/debian/rules.d/armel.mk @@ -0,0 +1,12 @@ +build_arch = arm +header_arch = arm +asm_link = arm +defconfig = defconfig +flavours = orion5x iop32x ixp4xx versatile +build_image = zImage +kernel_file = arch/$(build_arch)/boot/zImage +install_file = vmlinuz +no_dumpfile = true +disable_d_i = true + +loader = grub --- linux-2.6.27.orig/debian/config/amd64/config.generic +++ linux-2.6.27/debian/config/amd64/config.generic @@ -0,0 +1,11 @@ +# +# Config options for config.generic automatically generated by splitconfig.pl +# +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y --- linux-2.6.27.orig/debian/config/amd64/config.server +++ linux-2.6.27/debian/config/amd64/config.server @@ -0,0 +1,11 @@ +# +# Config options for config.server automatically generated by splitconfig.pl +# +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_DEADLINE=y +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set --- linux-2.6.27.orig/debian/config/amd64/config +++ linux-2.6.27/debian/config/amd64/config @@ -0,0 +1,3470 @@ +# +# Common config options automatically generated by splitconfig.pl +# +CONFIG_3C359=m +CONFIG_60XX_WDT=m +CONFIG_64BIT=y +CONFIG_6PACK=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +CONFIG_8139TOO_8129=y +CONFIG_8139TOO_PIO=y +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_9P_FS=m +CONFIG_ABYSS=m +CONFIG_AC97_BUS=m +# CONFIG_ACCESSIBILITY is not set +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_ACER_WMI=m +CONFIG_ACORN_PARTITION=y +# CONFIG_ACORN_PARTITION_ADFS is not set +# CONFIG_ACORN_PARTITION_CUMANA is not set +# CONFIG_ACORN_PARTITION_EESOX is not set +CONFIG_ACORN_PARTITION_ICS=y +# CONFIG_ACORN_PARTITION_POWERTEC is not set +CONFIG_ACORN_PARTITION_RISCIX=y +CONFIG_ACPI=y +CONFIG_ACPI_AC=m +# CONFIG_ACPI_ASUS is not set +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BAY=m +CONFIG_ACPI_BLACKLIST_YEAR=0 +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_CONTAINER=m +# CONFIG_ACPI_CUSTOM_DSDT is not set +CONFIG_ACPI_CUSTOM_DSDT_FILE="" +CONFIG_ACPI_CUSTOM_DSDT_INITRD=y +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_EC=y +CONFIG_ACPI_FAN=m +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_PCI_SLOT=m +CONFIG_ACPI_POWER=y +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_PROCFS=y +CONFIG_ACPI_PROCFS_POWER=y +CONFIG_ACPI_PROC_EVENT=y +CONFIG_ACPI_SBS=m +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SYSFS_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_THERMAL=m +# CONFIG_ACPI_TOSHIBA is not set +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_WMI=m +CONFIG_ACQUIRE_WDT=m +CONFIG_ACT200L_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_ADM8211=m +CONFIG_ADVANTECH_WDT=m +CONFIG_AEDSP16_MSS=y +# CONFIG_AEDSP16_SBPRO is not set +CONFIG_AFFS_FS=m +# CONFIG_AFS_DEBUG is not set +CONFIG_AFS_FS=m +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_AGP=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=m +CONFIG_AGP_SIS=m +CONFIG_AGP_VIA=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_DEBUG_ENABLE=y +CONFIG_AIC79XX_DEBUG_MASK=0 +CONFIG_AIC79XX_REG_PRETTY_PRINT=y +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 +CONFIG_AIC7XXX_DEBUG_ENABLE=y +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC94XX_DEBUG is not set +CONFIG_AIRO=m +CONFIG_AIRO_CS=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_ALI_FIR=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD_IOMMU=y +CONFIG_AMIGA_PARTITION=y +CONFIG_ANON_INODES=y +CONFIG_APPLICOM=m +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_ARCH_HAS_CPU_RELAX=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_HIBERNATION_HEADER=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCNET=m +CONFIG_ARCNET_1051=m +CONFIG_ARCNET_1201=m +CONFIG_ARCNET_CAP=m +CONFIG_ARCNET_COM20020=m +CONFIG_ARCNET_COM20020_CS=m +CONFIG_ARCNET_COM20020_PCI=m +CONFIG_ARCNET_COM90xx=m +CONFIG_ARCNET_COM90xxIO=m +CONFIG_ARCNET_RAW=m +CONFIG_ARCNET_RIM_I=m +# CONFIG_ARPD is not set +CONFIG_ASK_IP_FIB_HASH=y +CONFIG_ASUS_LAPTOP=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_AT24=m +CONFIG_ATA=m +CONFIG_ATALK=m +CONFIG_ATARI_PARTITION=y +CONFIG_ATA_ACPI=y +CONFIG_ATA_GENERIC=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_OVER_ETH=m +CONFIG_ATA_PIIX=m +CONFIG_ATA_SFF=y +# CONFIG_ATH5K is not set +CONFIG_ATH9K=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL2=m +CONFIG_ATM=y +CONFIG_ATMEL=m +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_FORE200E=m +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E_TX_RETRY=16 +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_LANAI=m +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_TCP=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATP=m +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_ARCH=y +CONFIG_AUDIT_TREE=y +CONFIG_AUFS=m +# CONFIG_AUFS_BRANCH_MAX_1023 is not set +CONFIG_AUFS_BRANCH_MAX_127=y +# CONFIG_AUFS_BRANCH_MAX_32767 is not set +# CONFIG_AUFS_BRANCH_MAX_511 is not set +CONFIG_AUFS_BR_NFS=y +CONFIG_AUFS_BR_XFS=y +# CONFIG_AUFS_COMPAT is not set +# CONFIG_AUFS_DEBUG is not set +CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH=y +# CONFIG_AUFS_DLGT is not set +CONFIG_AUFS_EXPORT=y +# CONFIG_AUFS_FSYNC_SUPER_PATCH is not set +CONFIG_AUFS_HINOTIFY=y +CONFIG_AUFS_HIN_OR_DLGT=y +CONFIG_AUFS_HIN_OR_FUSE=y +CONFIG_AUFS_INO_T_64=y +CONFIG_AUFS_LHASH_PATCH=y +CONFIG_AUFS_PUT_FILP_PATCH=y +# CONFIG_AUFS_ROBR is not set +CONFIG_AUFS_RR_SQUASHFS=y +CONFIG_AUFS_SEC_PERM_PATCH=y +CONFIG_AUFS_SHWH=y +CONFIG_AUFS_SPLICE_PATCH=y +CONFIG_AUFS_STAT=y +# CONFIG_AUFS_UNIONFS22_PATCH is not set +# CONFIG_AUFS_UNIONFS23_PATCH is not set +# CONFIG_AUFS_WORKAROUND_FUSE is not set +CONFIG_AUTOFS4_FS=m +CONFIG_AUTOFS_FS=m +CONFIG_AUXDISPLAY=y +CONFIG_AVERATEC_5100P=m +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_DEBUG=y +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PIO=y +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_B43LEGACY_RFKILL=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43_LEDS=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_PCI_AUTOSELECT=y +# CONFIG_B43_PCMCIA is not set +CONFIG_B43_RFKILL=y +CONFIG_B44=m +CONFIG_B44_PCI=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_BACKLIGHT_CARILLO_RANCH=m +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_CORGI=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_MBP_NVIDIA=m +CONFIG_BACKLIGHT_PROGEAR=m +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_BASE_FULL=y +CONFIG_BASE_SMALL=0 +CONFIG_BATTERY_DS2760=m +CONFIG_BAYCOM_PAR=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BEFS_FS=m +CONFIG_BFS_FS=m +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_BITREVERSE=y +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_DEV=y +CONFIG_BLK_DEV_3W_XXXX_RAID=m +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_COMPCACHE=m +# CONFIG_BLK_DEV_COMPCACHE_DEBUG is not set +# CONFIG_BLK_DEV_COMPCACHE_STATS is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_DM=m +CONFIG_BLK_DEV_DM_BBR=m +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_MD=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_XIP is not set +CONFIG_BLOCK=y +CONFIG_BLOCK_COMPAT=y +CONFIG_BNX2=m +CONFIG_BNX2X=m +CONFIG_BONDING=m +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BOUNCE=y +CONFIG_BPQETHER=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_NETFILTER=y +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BROADCOM_PHY=m +CONFIG_BSD_DISKLABEL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_BT=m +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIVHCI=m +CONFIG_BT_HIDP=m +CONFIG_BT_L2CAP=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_SCO=m +CONFIG_BUG=y +CONFIG_CALGARY_IOMMU=y +CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y +# CONFIG_CAN is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_CAPI_AVM=y +CONFIG_CAPI_EICON=y +CONFIG_CAPI_TRACE=y +CONFIG_CARDBUS=y +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_CARMINE_DRAM_CUSTOM is not set +CONFIG_CASSINI=m +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_CFAG12864B=m +CONFIG_CFAG12864B_RATE=20 +CONFIG_CFG80211=m +CONFIG_CGROUPS=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_DEVICE is not set +CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_NS=y +CONFIG_CGROUP_SCHED=y +CONFIG_CHECK_SIGNATURE=y +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3=m +CONFIG_CHR_DEV_OSST=m +CONFIG_CHR_DEV_SCH=m +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_ST=m +CONFIG_CICADA_PHY=m +CONFIG_CIFS=m +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_EXPERIMENTAL=y +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_WEAK_PW_HASH=y +# CONFIG_CIFS_XATTR is not set +CONFIG_CISS_SCSI_TAPE=y +CONFIG_CLASSIC_RCU=y +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_CLS_U32_MARK=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CODA_FS=m +CONFIG_COMPAL_LAPTOP=m +CONFIG_COMPAT=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_COMPAT_BRK is not set +CONFIG_COMPAT_FOR_U64_ALIGNMENT=y +# CONFIG_COMPAT_VDSO is not set +CONFIG_COMPUTONE=m +CONFIG_CONFIGFS_FS=m +CONFIG_CONNECTOR=y +CONFIG_CONSOLE_POLL=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_SWITCH_TRACER=y +# CONFIG_CPA_DEBUG is not set +CONFIG_CPU5_WDT=m +CONFIG_CPUSETS=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEBUG is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_TABLE=m +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CRAMFS=y +CONFIG_CRASH_DUMP=y +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_CRC_CCITT=m +CONFIG_CRC_ITU_T=m +CONFIG_CRC_T10DIF=m +CONFIG_CRYPTO=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_LZO=m +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SALSA20_X86_64=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m +CONFIG_CRYPTO_TWOFISH_X86_64=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_XTS=m +CONFIG_CYCLADES=m +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +# CONFIG_CYZ_INTR is not set +# CONFIG_DAB is not set +CONFIG_DAVICOM_PHY=m +CONFIG_DCA=m +CONFIG_DCDBAS=m +CONFIG_DE2104X=m +CONFIG_DE4X5=m +CONFIG_DE600=m +CONFIG_DE620=m +# CONFIG_DEBUG_BOOT_PARAMS is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DECNET=m +CONFIG_DECNET_NF_GRABULATOR=m +# CONFIG_DECNET_ROUTER is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +CONFIG_DEFAULT_IO_DELAY_TYPE=1 +# CONFIG_DEFAULT_NOOP is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_WESTWOOD is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_DEFXX=m +# CONFIG_DEFXX_MMIO is not set +CONFIG_DELL_RBU=m +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_DEVKMEM=y +CONFIG_DEVPORT=y +CONFIG_DEV_APPLETALK=m +CONFIG_DE_AOC=y +CONFIG_DIGIEPCA=m +# CONFIG_DIRECT_GBPAGES is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_DISPLAY_SUPPORT=m +# CONFIG_DL2K is not set +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +CONFIG_DLM=m +# CONFIG_DLM_DEBUG is not set +CONFIG_DM9102=m +CONFIG_DMADEVICES=y +# CONFIG_DMAR is not set +# CONFIG_DMATEST is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMI=y +CONFIG_DMIID=y +CONFIG_DM_CRYPT=m +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_LOOP=m +CONFIG_DM_MIRROR=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_RAID45=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_UEVENT=y +CONFIG_DM_ZERO=m +CONFIG_DNOTIFY=y +CONFIG_DONGLE=y +CONFIG_DRM=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_SAVAGE=m +CONFIG_DRM_SIS=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_VIA=m +CONFIG_DRM_VIA_CHROME9=m +CONFIG_DS1682=m +CONFIG_DSCC4=m +CONFIG_DSCC4_PCISYNC=y +CONFIG_DSCC4_PCI_RST=y +CONFIG_DUMMY=m +CONFIG_DUMMY_CONSOLE=y +CONFIG_DVB_AU8522=m +CONFIG_DVB_AV7110=m +# CONFIG_DVB_AV7110_FIRMWARE is not set +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_B2C2_FLEXCOP=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_BT8XX=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET_PATCH=m +CONFIG_DVB_CAPTURE_DRIVERS=y +CONFIG_DVB_CINERGYT2=m +# CONFIG_DVB_CINERGYT2_TUNING is not set +CONFIG_DVB_CORE=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_DRX397XD=m +# CONFIG_DVB_FE_CUSTOMISE is not set +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_L64781=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_MT312=m +CONFIG_DVB_MT352=m +CONFIG_DVB_NXT200X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_PLL=m +CONFIG_DVB_PLUTO2=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_S5H1411=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_SIANO_SMS1XXX=m +CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_STV0297=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_USB=m +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_CXUSB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_VES1820=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_ZL10353=m +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +# CONFIG_E1000E_ENABLED is not set +# CONFIG_E1000E_NEW is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_EARLY_PRINTK=y +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_ECRYPT_FS=m +CONFIG_EDAC=y +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I3000=m +CONFIG_EDAC_I5000=m +CONFIG_EDAC_I5100=m +CONFIG_EDAC_I82975X=m +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDD=y +CONFIG_EDD_OFF=y +CONFIG_EEEPC_LAPTOP=m +CONFIG_EEPRO100=m +CONFIG_EEPROM_93CX6=m +CONFIG_EFI=y +CONFIG_EFI_PARTITION=y +CONFIG_EFI_VARS=y +CONFIG_EFS_FS=m +CONFIG_ELF_CORE=y +# CONFIG_EMBEDDED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENC28J60 is not set +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_EPIC100=m +CONFIG_EPOLL=y +CONFIG_EQUALIZER=m +CONFIG_ESI_DONGLE=m +CONFIG_EUROTECH_WDT=m +CONFIG_EVENTFD=y +CONFIG_EXPERIMENTAL=y +CONFIG_EXPORTFS=m +CONFIG_EXT2_FS=m +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT4DEV_FS=m +CONFIG_EXT4DEV_FS_POSIX_ACL=y +CONFIG_EXT4DEV_FS_SECURITY=y +CONFIG_EXT4DEV_FS_XATTR=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FARSYNC=m +CONFIG_FAST_CMPXCHG_LOCAL=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_FS=m +# CONFIG_FAULT_INJECTION is not set +CONFIG_FB=y +CONFIG_FB_3DFX=m +# CONFIG_FB_3DFX_ACCEL is not set +CONFIG_FB_ARC=m +CONFIG_FB_ARK=m +CONFIG_FB_ASILIANT=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY128=m +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_CARILLO_RANCH=m +CONFIG_FB_CARMINE=m +CONFIG_FB_CARMINE_DRAM_EVAL=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_CIRRUS=m +CONFIG_FB_CYBER2000=m +CONFIG_FB_DDC=m +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_EFI=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_GEODE=y +CONFIG_FB_GEODE_GX=m +CONFIG_FB_GEODE_GX1=m +CONFIG_FB_GEODE_LX=m +CONFIG_FB_HECUBA=m +CONFIG_FB_HGA=m +# CONFIG_FB_HGA_ACCEL is not set +CONFIG_FB_IMAC=y +CONFIG_FB_IMSTT=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_INTEL_I2C=y +CONFIG_FB_KYRO=m +CONFIG_FB_LE80578=m +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_N411=m +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_BACKLIGHT=y +# CONFIG_FB_NVIDIA_DEBUG is not set +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_PM2=m +CONFIG_FB_PM2_FIFO_DISCONNECT=y +CONFIG_FB_PM3=m +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RIVA=m +CONFIG_FB_RIVA_BACKLIGHT=y +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_I2C=y +CONFIG_FB_S1D13XXX=m +CONFIG_FB_S3=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_SM501=m +CONFIG_FB_SVGALIB=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_TRIDENT=m +# CONFIG_FB_TRIDENT_ACCEL is not set +CONFIG_FB_UVESA=m +CONFIG_FB_VESA=m +CONFIG_FB_VGA16=m +# CONFIG_FB_VIRTUAL is not set +CONFIG_FB_VOODOO1=m +CONFIG_FB_VT8623=m +CONFIG_FDDI=y +CONFIG_FEALNX=m +CONFIG_FIB_RULES=y +# CONFIG_FIREWIRE is not set +CONFIG_FIRMWARE_EDID=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_FIX_EARLYCON_MEM=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x16=y +CONFIG_FONT_8x8=y +CONFIG_FORCEDETH=m +# CONFIG_FORCEDETH_NAPI is not set +CONFIG_FRAMEBUFFER_CONSOLE=m +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FRAME_POINTER=y +CONFIG_FRAME_WARN=2048 +CONFIG_FSAM7400=m +CONFIG_FS_MBCACHE=m +CONFIG_FS_POSIX_ACL=y +CONFIG_FS_UNIONFS=m +CONFIG_FTL=m +CONFIG_FTRACE=y +# CONFIG_FTRACE_STARTUP_TEST is not set +CONFIG_FUJITSU_LAPTOP=m +# CONFIG_FUJITSU_LAPTOP_DEBUG is not set +CONFIG_FUSE_FS=m +CONFIG_FUSION=y +CONFIG_FUSION_CTL=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_LAN=m +CONFIG_FUSION_LOGGING=y +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_SAS=m +CONFIG_FUSION_SPI=m +CONFIG_FUTEX=y +CONFIG_FW_LOADER=y +CONFIG_GACT_PROB=y +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GARP=m +CONFIG_GART_IOMMU=y +CONFIG_GENERIC_ACL=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_GENERIC_LOCKBREAK is not set +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=m +CONFIG_GFS_FS=m +CONFIG_GIGASET_BASE=m +# CONFIG_GIGASET_DEBUG is not set +CONFIG_GIGASET_M101=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_UNDOCREQ is not set +CONFIG_GIRBIL_DONGLE=m +CONFIG_GNBD=m +CONFIG_GPIOLIB=y +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_SYSFS=y +CONFIG_GROUP_SCHED=y +CONFIG_HAMACHI=m +CONFIG_HAMRADIO=y +CONFIG_HANGCHECK_TIMER=m +CONFIG_HAPPYMEAL=m +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_CLK is not set +CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y +CONFIG_HDLC=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_X25=m +# CONFIG_HEADERS_CHECK is not set +CONFIG_HECI=m +CONFIG_HERMES=m +CONFIG_HFSPLUS_FS=m +CONFIG_HFS_FS=m +CONFIG_HIBERNATION=y +CONFIG_HID=m +CONFIG_HIDRAW=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HID_FF is not set +CONFIG_HID_SUPPORT=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_HIPPI=y +CONFIG_HISAX_16_3=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_BKM_A4T=y +# CONFIG_HISAX_DEBUG is not set +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_ENTERNOW_PCI=y +CONFIG_HISAX_EURO=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HDLC=y +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_HFCUSB=m +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_MAX_CARDS=8 +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_NO_KEYPAD is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_TELES_CS=m +CONFIG_HISAX_W6692=y +CONFIG_HOSTAP=m +CONFIG_HOSTAP_CS=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_PLX=m +CONFIG_HOTPLUG=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_PCI=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +CONFIG_HOTPLUG_PCI_CPCI=y +CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m +CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_PCIE=m +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HP100=m +CONFIG_HPET=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_HPET_MMAP=y +CONFIG_HPET_TIMER=y +CONFIG_HPFS_FS=m +CONFIG_HP_ILO=m +# CONFIG_HP_WATCHDOG is not set +CONFIG_HP_WMI=m +CONFIG_HTC_PASIC3=m +CONFIG_HT_IRQ=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HVC_DRIVER=y +CONFIG_HVC_IRQ=y +CONFIG_HVC_XEN=y +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_HWMON_VID=m +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_VIRTIO=m +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_300 is not set +CONFIG_I2C=m +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=m +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_I2C_DEBUG_CORE is not set +CONFIG_I2C_GPIO=m +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_I801=m +CONFIG_I2C_ISCH=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_NFORCE2_S4985=m +CONFIG_I2C_OCORES=m +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PCA_PLATFORM=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_SIMTEC=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_TAOS_EVM=m +CONFIG_I2C_TINY_USB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2O=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_BUS=m +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y +CONFIG_I2O_PROC=m +CONFIG_I2O_SCSI=m +CONFIG_I6300ESB_WDT=m +CONFIG_I82092=m +CONFIG_I8K=m +CONFIG_IA32_AOUT=m +CONFIG_IA32_EMULATION=y +CONFIG_IB700_WDT=m +CONFIG_IBMASR=m +CONFIG_IBMOL=m +CONFIG_IBM_ASM=m +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +CONFIG_ICPLUS_PHY=m +# CONFIG_IDE is not set +CONFIG_IEEE1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_CRYPT_WEP=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IFB=m +CONFIG_IGB=m +# CONFIG_IGB_LRO is not set +# CONFIG_IKCONFIG is not set +CONFIG_INET=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET_AH=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_INET_DIAG=y +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_LRO=m +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_AMSO1100=m +CONFIG_INFINIBAND_AMSO1100_DEBUG=y +CONFIG_INFINIBAND_CXGB3=m +# CONFIG_INFINIBAND_CXGB3_DEBUG is not set +CONFIG_INFINIBAND_IPATH=m +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y +CONFIG_INFINIBAND_IPOIB_DEBUG=y +# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set +CONFIG_INFINIBAND_ISER=m +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +# CONFIG_INFINIBAND_NES is not set +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_MEM=y +CONFIG_INFTL=m +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_INPUT=y +# CONFIG_INPUT_APANEL is not set +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_ATLAS_BTNS=m +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_MOUSE=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_POLLDEV=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_YEALINK=m +CONFIG_INTEL_IOATDMA=m +CONFIG_INTEL_MENLOW=m +# CONFIG_IOMMU_DEBUG is not set +CONFIG_IOMMU_HELPER=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_NOOP=y +# CONFIG_IO_DELAY_0X80 is not set +CONFIG_IO_DELAY_0XED=y +# CONFIG_IO_DELAY_NONE is not set +CONFIG_IO_DELAY_TYPE_0X80=0 +CONFIG_IO_DELAY_TYPE_0XED=1 +CONFIG_IO_DELAY_TYPE_NONE=3 +CONFIG_IO_DELAY_TYPE_UDELAY=2 +# CONFIG_IO_DELAY_UDELAY is not set +CONFIG_IP1000=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IPC_NS=y +CONFIG_IPDDP=m +CONFIG_IPDDP_DECAP=y +CONFIG_IPDDP_ENCAP=y +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_POWEROFF=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPPP_FILTER=y +CONFIG_IPV6=m +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_IPV6_PRIVACY=y +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IPV6_TUNNEL=m +CONFIG_IPW2100=m +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2200=m +# CONFIG_IPW2200_DEBUG is not set +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPWIRELESS=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_DCCP=m +CONFIG_IP_DCCP_ACKVEC=y +CONFIG_IP_DCCP_CCID2=m +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=m +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +# CONFIG_IP_DCCP_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=m +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_IP_PNP is not set +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_SCTP=m +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_TAB_BITS=12 +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_WRR=m +CONFIG_IRCOMM=m +CONFIG_IRDA=m +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_DEBUG=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRDA_ULTRA=y +CONFIG_IRLAN=m +CONFIG_IRNET=m +# CONFIG_IRQSOFF_TRACER is not set +CONFIG_IRTTY_SIR=m +CONFIG_ISA_DMA_API=y +CONFIG_ISCSI_IBFT=m +CONFIG_ISCSI_IBFT_FIND=y +CONFIG_ISCSI_TCP=m +CONFIG_ISDN=y +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIDRV=m +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_MAINT=m +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVERSION=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_ISDN_DRV_HISAX=m +CONFIG_ISDN_I4L=m +CONFIG_ISDN_MPP=y +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_TTY_FAX=y +CONFIG_ISDN_X25=y +# CONFIG_ISI is not set +CONFIG_ISO9660_FS=m +CONFIG_IT8712F_WDT=m +CONFIG_ITCO_VENDOR_SUPPORT=y +CONFIG_ITCO_WDT=m +CONFIG_IWL3945=m +# CONFIG_IWL3945_DEBUG is not set +CONFIG_IWL3945_LEDS=y +CONFIG_IWL3945_RFKILL=y +CONFIG_IWL3945_SPECTRUM_MEASUREMENT=y +CONFIG_IWL4965=y +CONFIG_IWL5000=y +CONFIG_IWLAGN=m +CONFIG_IWLAGN_LEDS=y +CONFIG_IWLAGN_SPECTRUM_MEASUREMENT=y +CONFIG_IWLCORE=m +CONFIG_IWLWIFI=m +# CONFIG_IWLWIFI_DEBUG is not set +CONFIG_IWLWIFI_LEDS=y +CONFIG_IWLWIFI_RFKILL=y +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_JBD=m +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_JOLIET=y +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_K8_NB=y +CONFIG_K8_NUMA=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_KARMA_PARTITION=y +CONFIG_KEXEC=y +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +CONFIG_KGDB=y +CONFIG_KGDB_SERIAL_CONSOLE=y +# CONFIG_KGDB_TESTS is not set +CONFIG_KINGSUN_DONGLE=m +CONFIG_KMOD=y +CONFIG_KPROBES=y +# CONFIG_KPROBES_SANITY_TEST is not set +CONFIG_KRETPROBES=y +CONFIG_KS0108=m +CONFIG_KS0108_DELAY=2 +CONFIG_KS0108_PORT=0x378 +CONFIG_KS959_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +# CONFIG_KTIME_SCALAR is not set +CONFIG_KVM=m +CONFIG_KVM_AMD=m +CONFIG_KVM_CLOCK=y +CONFIG_KVM_GUEST=y +CONFIG_KVM_INTEL=m +# CONFIG_KVM_TRACE is not set +CONFIG_LANMEDIA=m +CONFIG_LAPB=m +CONFIG_LAPBETHER=m +CONFIG_LATENCYTOP=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_ILI9320=m +CONFIG_LCD_LTV350QV=m +CONFIG_LCD_PLATFORM=m +CONFIG_LCD_VGG2432A4=m +# CONFIG_LDM_DEBUG is not set +CONFIG_LDM_PARTITION=y +CONFIG_LEDS_CLASS=m +# CONFIG_LEDS_CLEVO_MAIL is not set +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LIBCRC32C=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_CS=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIRC_ATIUSB=m +CONFIG_LIRC_BT829=m +CONFIG_LIRC_CMDIR=m +CONFIG_LIRC_DEV=m +# CONFIG_LIRC_GPIO is not set +CONFIG_LIRC_I2C=m +CONFIG_LIRC_IGORPLUGUSB=m +CONFIG_LIRC_IMON=m +CONFIG_LIRC_IT87=m +CONFIG_LIRC_MCEUSB=m +CONFIG_LIRC_MCEUSB2=m +# CONFIG_LIRC_PARALLEL is not set +CONFIG_LIRC_PVR150=m +CONFIG_LIRC_SASEM=m +CONFIG_LIRC_SERIAL=m +CONFIG_LIRC_SERIAL_IGOR=m +CONFIG_LIRC_SIR=m +CONFIG_LIRC_STREAMZAP=m +CONFIG_LIRC_TTUSBIR=m +CONFIG_LITELINK_DONGLE=m +# CONFIG_LKDTM is not set +CONFIG_LLC=y +CONFIG_LLC2=m +CONFIG_LMPCM_USB=m +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_LOCKD=m +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_LOCKD_V4=y +CONFIG_LOCK_KERNEL=y +# CONFIG_LOCK_STAT is not set +# CONFIG_LOGO is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_LP_CONSOLE is not set +CONFIG_LXT_PHY=m +CONFIG_LZO_COMPRESS=m +CONFIG_LZO_DECOMPRESS=m +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586MMX is not set +# CONFIG_M586TSC is not set +# CONFIG_M686 is not set +CONFIG_MA600_DONGLE=m +CONFIG_MAC80211=m +CONFIG_MAC80211_DEBUGFS=y +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_MAC80211_HWSIM is not set +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_RC_DEFAULT="pid" +CONFIG_MAC80211_RC_DEFAULT_PID=y +CONFIG_MAC80211_RC_PID=y +CONFIG_MACHZ_WDT=m +CONFIG_MACINTOSH_DRIVERS=y +CONFIG_MACVLAN=m +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_MAC_PARTITION=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MARKERS=y +CONFIG_MARVELL_PHY=m +CONFIG_MAX_RAW_DEVS=256 +# CONFIG_MCORE2 is not set +CONFIG_MCP2120_DONGLE=m +# CONFIG_MCRUSOE is not set +CONFIG_MCS_FIR=m +# CONFIG_MCYRIXIII is not set +CONFIG_MD=y +CONFIG_MDIO_BITBANG=m +CONFIG_MD_FAULTY=m +CONFIG_MD_LINEAR=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +# CONFIG_MEFFICEON is not set +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_SAS=m +# CONFIG_MEMSTICK is not set +# CONFIG_MEMTEST is not set +# CONFIG_MFD_CORE is not set +CONFIG_MFD_SM501=m +# CONFIG_MFD_SM501_GPIO is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +CONFIG_MICROCODE=m +CONFIG_MICROCODE_OLD_INTERFACE=y +CONFIG_MIGRATION=y +CONFIG_MII=m +CONFIG_MINIX_FS=m +CONFIG_MINIX_SUBPARTITION=y +CONFIG_MISC_DEVICES=y +CONFIG_MISDN=m +CONFIG_MISDN_DSP=m +CONFIG_MISDN_HFCMULTI=m +CONFIG_MISDN_HFCPCI=m +CONFIG_MISDN_L1OIP=m +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +CONFIG_MKISS=m +CONFIG_MLX4_CORE=m +CONFIG_MLX4_DEBUG=y +CONFIG_MLX4_INFINIBAND=m +CONFIG_MMC=m +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_RICOH_MMC=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_SDRICOH_CS=m +CONFIG_MMC_SPI=m +# CONFIG_MMC_TEST is not set +CONFIG_MMC_TIFM_SD=m +# CONFIG_MMC_UNSAFE_RESUME is not set +CONFIG_MMC_WBSD=m +# CONFIG_MMIOTRACE is not set +CONFIG_MMU=y +CONFIG_MMU_NOTIFIER=y +CONFIG_MM_OWNER=y +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MOUSE_APPLETOUCH=m +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_GPIO=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +# CONFIG_MPENTIUM4 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPSC is not set +CONFIG_MSDOS_FS=m +CONFIG_MSDOS_PARTITION=y +CONFIG_MSI_LAPTOP=m +CONFIG_MT9M001_PCA9536_SWITCH=y +CONFIG_MT9V022_PCA9536_SWITCH=y +CONFIG_MTD=m +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTD_ABSENT=m +CONFIG_MTD_ALAUDA=m +CONFIG_MTD_AMD76XROM=m +CONFIG_MTD_AR7_PARTS=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK2MTD=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_MTD_CFI=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_CHAR=m +CONFIG_MTD_CK804XROM=m +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_CONCAT=m +CONFIG_MTD_DATAFLASH=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_DILNETPC=m +CONFIG_MTD_DILNETPC_BOOTSIZE=0x80000 +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCECC=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCPROBE_ADDRESS=0 +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_ESB2ROM=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_ICHXROM=m +CONFIG_MTD_INTEL_VR_NOR=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_L440GX=m +CONFIG_MTD_M25P80=m +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_CAFE=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NETSC520=m +CONFIG_MTD_NETtel=m +CONFIG_MTD_ONENAND=m +CONFIG_MTD_ONENAND_2X_PROGRAM=y +# CONFIG_MTD_ONENAND_OTP is not set +CONFIG_MTD_ONENAND_SIM=m +CONFIG_MTD_ONENAND_VERIFY_WRITE=y +CONFIG_MTD_OOPS=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_PCI=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_PHYSMAP_LEN=0x4000000 +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PLATRAM=m +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +CONFIG_MTD_RAM=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS=m +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +CONFIG_MTD_ROM=m +CONFIG_MTD_SBC_GXX=m +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_SCB2_FLASH=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_TS5500=m +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_MTD_UBI_GLUEBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTRR=y +CONFIG_MTRR_SANITIZER=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 +CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 +# CONFIG_MVIAC3_2 is not set +# CONFIG_MVIAC7 is not set +CONFIG_MWAVE=m +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MWINCHIPC6 is not set +CONFIG_MYRI10GE=m +CONFIG_NAMESPACES=y +CONFIG_NATSEMI=m +CONFIG_NCPFS_EXTRAS=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_PACKET_SIGNING=y +# CONFIG_NCPFS_SMALLDOS is not set +CONFIG_NCPFS_STRONG=y +CONFIG_NCP_FS=m +CONFIG_NDISWRAPPER=m +CONFIG_NE2K_PCI=m +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_NET=y +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETDEVICES=y +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETLABEL=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NETROM=m +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETXEN_NIC=m +CONFIG_NET_9P=m +# CONFIG_NET_9P_DEBUG is not set +CONFIG_NET_9P_VIRTIO=m +CONFIG_NET_ACT_GACT=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_CLS_BASIC=m +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_CLS_FW=m +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_DCCPPROBE=m +CONFIG_NET_DMA=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_ET131X=m +CONFIG_NET_ETHERNET=y +CONFIG_NET_FC=y +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_NET_IPIP=m +CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_NET_PCI=y +CONFIG_NET_PCMCIA=y +CONFIG_NET_PKTGEN=m +CONFIG_NET_POCKET=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_NET_SB1000=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_FIFO=y +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_TCPPROBE=m +CONFIG_NET_TULIP=y +CONFIG_NET_VENDOR_3COM=y +CONFIG_NEW_LEDS=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_NF_CONNTRACK_SANE is not set +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_ACCT=y +CONFIG_NF_CT_NETLINK=m +# CONFIG_NF_CT_PROTO_DCCP is not set +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NIU=m +CONFIG_NL80211=y +CONFIG_NLS=y +CONFIG_NLS_ASCII=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_NODES_SHIFT=6 +CONFIG_NODES_SPAN_OTHER_NODES=y +CONFIG_NORTEL_HERMES=m +CONFIG_NOZOMI=m +CONFIG_NO_HZ=y +CONFIG_NR_CPUS=64 +CONFIG_NS83820=m +CONFIG_NSC_FIR=m +CONFIG_NSC_GPIO=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_FS=m +# CONFIG_NTFS_RW is not set +CONFIG_NUMA=y +# CONFIG_NUMA_EMU is not set +CONFIG_NVRAM=m +CONFIG_N_HDLC=m +# CONFIG_OCFS2_DEBUG_FS is not set +CONFIG_OCFS2_DEBUG_MASKLOG=y +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_OMFS_FS=m +CONFIG_OPROFILE=m +CONFIG_OPTIMIZE_INLINING=y +CONFIG_OSF_PARTITION=y +CONFIG_P54_COMMON=m +CONFIG_P54_PCI=m +CONFIG_P54_USB=m +CONFIG_P80211=m +CONFIG_PACKARDBELL_E5=m +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_CLOCK=y +# CONFIG_PARAVIRT_DEBUG is not set +CONFIG_PARAVIRT_GUEST=y +CONFIG_PARIDE=m +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_EPAT=m +# CONFIG_PARIDE_EPATC8 is not set +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PG=m +CONFIG_PARIDE_PT=m +CONFIG_PARPORT=m +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_AX88796=m +# CONFIG_PARPORT_GSC is not set +CONFIG_PARPORT_NOT_PC=y +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_SERIAL=m +CONFIG_PARTITION_ADVANCED=y +CONFIG_PATA_ACPI=m +CONFIG_PATA_ALI=m +CONFIG_PATA_AMD=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +# CONFIG_PATA_CMD640_PCI is not set +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5520=m +CONFIG_PATA_CS5530=m +# CONFIG_PATA_CYPRESS is not set +CONFIG_PATA_EFAR=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +# CONFIG_PATA_HPT3X2N is not set +CONFIG_PATA_HPT3X3=m +# CONFIG_PATA_HPT3X3_DMA is not set +CONFIG_PATA_IT8213=m +CONFIG_PATA_IT821X=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OLDPIIX=m +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +CONFIG_PATA_PCMCIA=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_PDC_OLD=m +# CONFIG_PATA_RADISYS is not set +CONFIG_PATA_RZ1000=m +# CONFIG_PATA_SC1200 is not set +CONFIG_PATA_SCH=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_SIL680=m +CONFIG_PATA_SIS=m +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m +CONFIG_PC300=m +# CONFIG_PC300TOO is not set +# CONFIG_PC300_MLPPP is not set +CONFIG_PC8736x_GPIO=m +CONFIG_PC87413_WDT=m +CONFIG_PCCARD=m +CONFIG_PCCARD_NONSTATIC=m +CONFIG_PCI=y +CONFIG_PCI200SYN=m +CONFIG_PCIEAER=y +# CONFIG_PCIEASPM is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIPCWATCHDOG=m +CONFIG_PCI_ATMEL=m +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_DIRECT=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_HERMES=m +CONFIG_PCI_LEGACY=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCI_MSI=y +CONFIG_PCMCIA=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_AXNET=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_IOCTL=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_NETWAVE=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_PCMCIA_SYM53C500=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_WL3501=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_PCNET32=m +CONFIG_PCSPKR_PLATFORM=y +CONFIG_PD6729=m +CONFIG_PDA_POWER=m +CONFIG_PDC_ADMA=m +CONFIG_PHANTOM=m +CONFIG_PHONE=m +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m +CONFIG_PHYLIB=m +CONFIG_PHYSICAL_ALIGN=0x200000 +CONFIG_PHYSICAL_START=0x200000 +# CONFIG_PID_NS is not set +CONFIG_PLIP=m +CONFIG_PLIST=y +CONFIG_PLX_HERMES=m +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_PM_DISABLE_CONSOLE=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_TEST_SUSPEND=y +CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y +# CONFIG_PM_VERBOSE is not set +CONFIG_PNP=y +CONFIG_PNPACPI=y +# CONFIG_PNP_DEBUG is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_PPDEV=m +CONFIG_PPP=m +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_SYNC_TTY=m +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_PRINTER=m +CONFIG_PRINTK=y +CONFIG_PRINTK_TIME=y +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_PRISM2_USB=m +CONFIG_PRISM54=m +CONFIG_PROC_EVENTS=y +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_VMCORE=y +CONFIG_PROFILING=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set +# CONFIG_PSS_HAVE_BOOT is not set +CONFIG_PSS_MIXER=y +CONFIG_QC_USB=m +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QLA3XXX=m +CONFIG_QNX4FS_FS=m +CONFIG_QSEMI_PHY=m +CONFIG_QUOTA=y +CONFIG_QUOTACTL=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_R3964=m +# CONFIG_R6040 is not set +CONFIG_R8169=m +CONFIG_R8169_VLAN=y +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAESTRO=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RAID_ATTRS=m +CONFIG_RAW_DRIVER=m +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_REALTEK_PHY is not set +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_REISERFS_FS_XATTR=y +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_RELAY=y +CONFIG_RELOCATABLE=y +CONFIG_RESOURCES_64BIT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_RFD_FTL=m +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=m +CONFIG_RFKILL_LEDS=y +CONFIG_RIO=m +# CONFIG_RIO_OLDPCI is not set +CONFIG_RISCOM8=m +CONFIG_ROADRUNNER=m +# CONFIG_ROADRUNNER_LARGE_RINGS is not set +CONFIG_ROCKETPORT=m +CONFIG_ROMFS_FS=m +CONFIG_ROSE=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +CONFIG_RT2400PCI=m +CONFIG_RT2400PCI_LEDS=y +CONFIG_RT2400PCI_RFKILL=y +CONFIG_RT2500PCI=m +CONFIG_RT2500PCI_LEDS=y +CONFIG_RT2500PCI_RFKILL=y +CONFIG_RT2500USB=m +CONFIG_RT2500USB_LEDS=y +CONFIG_RT2X00=m +# CONFIG_RT2X00_DEBUG is not set +CONFIG_RT2X00_LIB=m +# CONFIG_RT2X00_LIB_DEBUGFS is not set +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_LEDS=y +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_RFKILL=y +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT61PCI=m +CONFIG_RT61PCI_LEDS=y +CONFIG_RT61PCI_RFKILL=y +CONFIG_RT73USB=m +CONFIG_RT73USB_LEDS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_DRV_CMOS=y +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +# CONFIG_RTC_DRV_DS1511 is not set +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_M41T80_WDT=y +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_M48T59=m +CONFIG_RTC_DRV_M48T86=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +# CONFIG_RTC_DRV_R9701 is not set +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_S35390A is not set +CONFIG_RTC_DRV_STK17TA8=m +CONFIG_RTC_DRV_TEST=m +CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_LIB=y +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RT_GROUP_SCHED=y +CONFIG_RT_MUTEXES=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_RXKAD=m +CONFIG_S2IO=m +# CONFIG_SAMPLES is not set +CONFIG_SATA_AHCI=m +CONFIG_SATA_INIC162X=m +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_SATA_PMP=y +CONFIG_SATA_PROMISE=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIL24=m +CONFIG_SATA_SIS=m +CONFIG_SATA_SVW=m +CONFIG_SATA_SX4=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m +CONFIG_SBC8360_WDT=m +CONFIG_SBC_EPX_C3_WATCHDOG=m +CONFIG_SBNI=m +# CONFIG_SBNI_MULTILINE is not set +CONFIG_SC1200_WDT=m +CONFIG_SC520_WDT=m +CONFIG_SC6600=y +CONFIG_SC6600_CDROM=4 +CONFIG_SC6600_CDROMBASE=0 +CONFIG_SC6600_JOY=y +CONFIG_SC92031=m +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_HRTICK=y +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +# CONFIG_SCHED_TRACER is not set +CONFIG_SCSI=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_AIC79XX=m +CONFIG_SCSI_AIC7XXX=m +# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_AIC94XX=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ARCMSR_AER=y +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_DC390T=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_DH=m +CONFIG_SCSI_DH_ALUA=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DMA=y +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_LINKED_COMMANDS=y +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_FC_TGT_ATTRS=y +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_IMM=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_IPR=m +# CONFIG_SCSI_IPR_DUMP is not set +# CONFIG_SCSI_IPR_TRACE is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_ISCSITARGET=m +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_LOWLEVEL=y +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_MVSAS is not set +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PPA=m +CONFIG_SCSI_PROC_FS=y +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SAS_LIBSAS=m +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SRP=m +CONFIG_SCSI_SRP_ATTRS=m +CONFIG_SCSI_SRP_TGT_ATTRS=y +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_TGT=m +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SDIO_UART=m +CONFIG_SECCOMP=y +CONFIG_SECURITY=y +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_APPARMOR_DISABLE=y +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_SECURITY_FILE_CAPABILITIES=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_DISABLE=y +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +CONFIG_SECURITY_SMACK=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ABITUGURU3=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7473=m +CONFIG_SENSORS_APPLESMC=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCHMD=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_HDAPS=m +CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_K8TEMP=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MAX6875=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TSL2550=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_CS=m +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_NR_UARTS=48 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_SERIO=y +CONFIG_SERIO_CT82C710=m +CONFIG_SERIO_I8042=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_PARKBD=m +CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_RAW=m +CONFIG_SERIO_SERPORT=m +CONFIG_SFC=m +CONFIG_SGI_GRU=m +# CONFIG_SGI_GRU_DEBUG is not set +CONFIG_SGI_IOC4=m +CONFIG_SGI_PARTITION=y +CONFIG_SGI_XP=m +CONFIG_SHMEM=y +CONFIG_SIGMATEL_FIR=m +CONFIG_SIGNALFD=y +CONFIG_SIS190=m +CONFIG_SIS900=m +CONFIG_SKFP=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +# CONFIG_SLAB is not set +CONFIG_SLABINFO=y +CONFIG_SLHC=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_SLIP_SMART=y +# CONFIG_SLOB is not set +CONFIG_SLUB=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_SMC_IRCC_FIR=m +CONFIG_SMP=y +CONFIG_SMSC37B787_WDT=m +CONFIG_SMSC_PHY=m +CONFIG_SND=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_AD1889=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AW2=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_BTSCO=m +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5530=m +CONFIG_SND_DARLA20=m +CONFIG_SND_DARLA24=m +# CONFIG_SND_DEBUG is not set +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_ECHO3G=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_GINA20=m +CONFIG_SND_GINA24=m +CONFIG_SND_HDA_CODEC_ANALOG=y +CONFIG_SND_HDA_CODEC_ATIHDMI=y +CONFIG_SND_HDA_CODEC_CMEDIA=y +CONFIG_SND_HDA_CODEC_CONEXANT=y +CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_CODEC_SI3054=y +CONFIG_SND_HDA_CODEC_SIGMATEL=y +CONFIG_SND_HDA_CODEC_VIA=y +CONFIG_SND_HDA_GENERIC=y +# CONFIG_SND_HDA_HWDEP is not set +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_POWER_SAVE=y +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_HIFIER=m +CONFIG_SND_HWDEP=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIA=m +CONFIG_SND_MIXART=m +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_MONA=m +CONFIG_SND_MPU401=m +CONFIG_SND_MPU401_UART=m +CONFIG_SND_MTPAV=m +CONFIG_SND_MTS64=m +CONFIG_SND_NM256=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_OXYGEN=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_PCI=y +CONFIG_SND_PCM=m +CONFIG_SND_PCMCIA=y +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_PCSP=m +CONFIG_SND_PCXHR=m +CONFIG_SND_PDAUDIOCF=m +CONFIG_SND_PORTMAN2X4=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SB16_DSP=m +CONFIG_SND_SB_COMMON=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_SOC=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_SPI=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_TIMER=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_USX2Y=m +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VMASTER=y +CONFIG_SND_VX222=m +CONFIG_SND_VXPOCKET=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_YMFPCI=m +CONFIG_SOC_CAMERA=m +CONFIG_SOC_CAMERA_MT9M001=m +CONFIG_SOC_CAMERA_MT9V022=m +CONFIG_SOC_CAMERA_PLATFORM=m +CONFIG_SOFT_WATCHDOG=m +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_SONYPI_COMPAT=y +CONFIG_SONY_LAPTOP=m +CONFIG_SOUND=m +CONFIG_SOUND_AEDSP16=m +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_KAHLUA=m +CONFIG_SOUND_MPU401=m +CONFIG_SOUND_MSS=m +CONFIG_SOUND_OSS=m +CONFIG_SOUND_PAS=m +CONFIG_SOUND_PRIME=m +CONFIG_SOUND_PSS=m +CONFIG_SOUND_SB=m +CONFIG_SOUND_SSCAPE=m +# CONFIG_SOUND_TRACEINIT is not set +CONFIG_SOUND_TRIX=m +CONFIG_SOUND_UART6850=m +CONFIG_SOUND_VMIDI=m +CONFIG_SOUND_YM3812=m +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_MANUAL=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPECIALIX=m +CONFIG_SPI=y +CONFIG_SPI_AT25=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_LM70_LLP=m +CONFIG_SPI_MASTER=y +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_TLE62X0=m +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +CONFIG_SSB=m +CONFIG_SSB_B43_PCI_BRIDGE=y +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +# CONFIG_SSB_PCMCIAHOST is not set +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_POSSIBLE=y +CONFIG_SSB_SPROM=y +CONFIG_SSFDC=m +CONFIG_STACKTRACE=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_STALDRV=y +# CONFIG_STANDALONE is not set +CONFIG_STOP_MACHINE=y +CONFIG_STP=m +CONFIG_STRICT_DEVMEM=y +CONFIG_STRIP=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_SUNGEM=m +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_SUN_PARTITION=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SWAP=y +CONFIG_SWIOTLB=y +CONFIG_SX=m +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_CS=m +CONFIG_SYNCLINK_GT=m +CONFIG_SYN_COOKIES=y +CONFIG_SYSCTL=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_SYSFS=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_SYSPROF_TRACER is not set +CONFIG_SYSV68_PARTITION=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYSV_FS=m +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_TASKSTATS=y +# CONFIG_TASK_DELAY_ACCT is not set +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_TASK_XACCT=y +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_NSC=m +CONFIG_TCG_TIS=m +CONFIG_TCG_TPM=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_MD5SIG=y +CONFIG_TEHUTI=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TELCLOCK=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_TEXTSEARCH_KMP=m +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THINKPAD_ACPI=m +CONFIG_THINKPAD_ACPI_BAY=y +# CONFIG_THINKPAD_ACPI_DEBUG is not set +CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y +CONFIG_THINKPAD_ACPI_VIDEO=y +CONFIG_TICK_ONESHOT=y +CONFIG_TIFM_7XX1=m +CONFIG_TIFM_CORE=m +CONFIG_TIGON3=m +CONFIG_TIMERFD=y +CONFIG_TIMER_STATS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_TLAN=m +CONFIG_TLSF=m +# CONFIG_TLSF_DEBUG is not set +# CONFIG_TLSF_STATS is not set +CONFIG_TLSUP=m +CONFIG_TMD_HERMES=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +# CONFIG_TOIM3232_DONGLE is not set +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_UCB1400=m +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_WM9705=y +CONFIG_TOUCHSCREEN_WM9712=y +CONFIG_TOUCHSCREEN_WM9713=y +CONFIG_TOUCHSCREEN_WM97XX=m +CONFIG_TPS65010=m +CONFIG_TP_SMAPI=m +CONFIG_TP_SMAPI_EC=m +CONFIG_TR=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_TRACING=y +CONFIG_TTPCI_EEPROM=m +CONFIG_TULIP=m +# CONFIG_TULIP_MMIO is not set +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_NAPI is not set +CONFIG_TUN=m +CONFIG_TUNER_3036=m +CONFIG_TYPHOON=m +CONFIG_UBIFS_FS=m +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_UFS_DEBUG is not set +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +CONFIG_UID16=y +CONFIG_UIO=m +CONFIG_UIO_CIF=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_UIO_SMX=m +CONFIG_ULI526X=m +CONFIG_ULTRIX_PARTITION=y +CONFIG_UNIX=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_USB=m +CONFIG_USBPCWATCHDOG=m +CONFIG_USB_ACM=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_APPLEIR=m +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_ATM=m +CONFIG_USB_BELKIN=y +CONFIG_USB_BERRY_CHARGE=m +CONFIG_USB_C67X00_HCD=m +CONFIG_USB_CATC=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_CXACRU=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_DSBR=m +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EMI26=m +CONFIG_USB_EMI62=m +CONFIG_USB_EPSON2888=y +CONFIG_USB_ET61X251=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_EZUSB=y +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_GADGET=m +CONFIG_USB_GADGETFS=m +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +CONFIG_USB_GADGET_NET2280=y +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_G_PRINTER is not set +CONFIG_USB_G_SERIAL=m +CONFIG_USB_HID=m +CONFIG_USB_HIDDEV=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_USB_HSO=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_IRDA=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_ISP1760_HCD=m +# CONFIG_USB_ISP1760_PCI is not set +CONFIG_USB_KAWETH=m +CONFIG_USB_KBD=m +CONFIG_USB_KC2190=y +CONFIG_USB_KONICAWC=m +CONFIG_USB_LCD=m +CONFIG_USB_LD=m +CONFIG_USB_LED=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LIBUSUAL=y +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +# CONFIG_USB_MIDI_GADGET is not set +CONFIG_USB_MON=y +CONFIG_USB_MOUSE=m +CONFIG_USB_NET2280=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_HCD_SSB is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OV511 is not set +CONFIG_USB_OV511_NEW=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_PHIDGET=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETMOTORCONTROL=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_PRINTER=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_R8A66597_HCD=m +CONFIG_USB_RIO500=m +CONFIG_USB_RTL8150=m +CONFIG_USB_S2255=m +CONFIG_USB_SE401=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IPW=m +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_IUU is not set +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SI470X=m +CONFIG_USB_SISUSBVGA=m +# CONFIG_USB_SISUSBVGA_CON is not set +CONFIG_USB_SL811_CS=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SN9C102=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE_ALAUDA=y +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_STORAGE_DATAFAB=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_KARMA=y +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STV680=m +CONFIG_USB_SUPPORT=y +CONFIG_USB_SUSPEND=y +# CONFIG_USB_TEST is not set +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_U132_HCD=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_USBNET=m +CONFIG_USB_USS720=m +CONFIG_USB_VICAM=m +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_W9968CF=m +CONFIG_USB_WDM=m +CONFIG_USB_XUSBATM=m +CONFIG_USB_ZC0301=m +CONFIG_USB_ZD1201=m +CONFIG_USB_ZERO=m +CONFIG_USB_ZR364XX=m +# CONFIG_USER_NS is not set +# CONFIG_USER_SCHED is not set +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_UTS_NS=y +CONFIG_V4L_USB_DRIVERS=y +CONFIG_VERSION_SIGNATURE="" +CONFIG_VETH=m +CONFIG_VFAT_FS=m +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_VGASTATE=m +CONFIG_VGA_CONSOLE=y +CONFIG_VIA_FIR=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_VELOCITY=m +CONFIG_VIDEOBUF_DMA_CONTIG=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +# CONFIG_VIDEO_ADV_DEBUG is not set +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CAFE_CCIC=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX23885=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_MEDIA=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_VIDEO_PVRUSB2=m +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_PVRUSB2_DVB=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA7111=m +CONFIG_VIDEO_SAA7114=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_SELECT=y +CONFIG_VIDEO_SH_MOBILE_CEU=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TDA9875=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_VIVI=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_VPX3220=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_ZR36060=m +CONFIG_VIRTIO=m +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_BLK=m +CONFIG_VIRTIO_CONSOLE=m +CONFIG_VIRTIO_NET=m +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_RING=m +CONFIG_VIRTUALIZATION=y +CONFIG_VIRT_TO_BUS=y +CONFIG_VITESSE_PHY=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLSI_FIR=m +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VORTEX=m +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_VXFS_FS=m +CONFIG_W1=m +CONFIG_W1_CON=y +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W83627HF_WDT=m +CONFIG_W83697HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_WAFER_WDT=m +CONFIG_WAN=y +CONFIG_WANXL=m +CONFIG_WAN_ROUTER=m +CONFIG_WAN_ROUTER_DRIVERS=m +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y +CONFIG_WINBOND_840=m +CONFIG_WINBOND_FIR=m +CONFIG_WIRELESS_ACX=m +CONFIG_WIRELESS_AT76=m +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_WLAN_80211=y +CONFIG_WLAN_PRE80211=y +CONFIG_X25=m +CONFIG_X25_ASY=m +CONFIG_X86=y +# CONFIG_X86_32 is not set +CONFIG_X86_64=y +CONFIG_X86_64_ACPI_NUMA=y +CONFIG_X86_64_SMP=y +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_CMOV=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_CPU=y +CONFIG_X86_CPUID=m +CONFIG_X86_DEBUGCTLMSR=y +# CONFIG_X86_ELAN is not set +CONFIG_X86_FIND_SMP_CONFIG=y +# CONFIG_X86_GENERICARCH is not set +CONFIG_X86_HT=y +CONFIG_X86_INTERNODE_CACHE_BYTES=128 +CONFIG_X86_IO_APIC=y +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_MCE=y +CONFIG_X86_MCE_AMD=y +CONFIG_X86_MCE_INTEL=y +CONFIG_X86_MINIMUM_CPU_FAMILY=64 +CONFIG_X86_MPPARSE=y +CONFIG_X86_MSR=m +# CONFIG_X86_P4_CLOCKMOD is not set +# CONFIG_X86_PAT is not set +CONFIG_X86_PC=y +CONFIG_X86_PM_TIMER=y +CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_POWERNOW_K8_ACPI=y +# CONFIG_X86_PTDUMP is not set +CONFIG_X86_RESERVE_LOW_64K=y +CONFIG_X86_SMP=y +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set +CONFIG_X86_TRAMPOLINE=y +CONFIG_X86_TSC=y +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_VSMP is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_XEN=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_FBDEV_FRONTEND=m +CONFIG_XEN_KBDDEV_FRONTEND=m +CONFIG_XEN_MAX_DOMAIN_MEMORY=32 +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_SAVE_RESTORE=y +CONFIG_XEN_SCRUB_PAGES=y +CONFIG_XFRM=y +CONFIG_XFRM_IPCOMP=m +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_USER=m +# CONFIG_XFS_DEBUG is not set +CONFIG_XFS_FS=m +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_RT=y +CONFIG_XOR_BLOCKS=m +CONFIG_YAM=m +CONFIG_YELLOWFIN=m +CONFIG_YENTA=m +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_ZISOFS=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA=y +CONFIG_ZONE_DMA32=y +CONFIG_ZONE_DMA_FLAG=1 --- linux-2.6.27.orig/debian/config/armel/config.orion5x +++ linux-2.6.27/debian/config/armel/config.orion5x @@ -0,0 +1,668 @@ +# +# Config options for config.orion5x automatically generated by splitconfig.pl +# +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_ACENIC is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_APPLICOM is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IXP4XX is not set +CONFIG_ARCH_ORION5X=y +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCNET is not set +CONFIG_ARM_THUMB=y +CONFIG_ASYNC_CORE=y +CONFIG_ATA=y +# CONFIG_ATALK is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_ATA_PIIX is not set +CONFIG_ATA_SFF=y +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATM is not set +# CONFIG_AX88796 is not set +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BNX2 is not set +# CONFIG_BRIDGE is not set +CONFIG_BSD_DISKLABEL=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_CASSINI is not set +# CONFIG_CFG80211 is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_ST is not set +CONFIG_CMDLINE="" +CONFIG_COMPAT_BRK=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_COPY_FEROCEON=y +CONFIG_CPU_FEROCEON=y +CONFIG_CPU_FEROCEON_OLD_ID=y +# CONFIG_CPU_ICACHE_DISABLE is not set +CONFIG_CPU_TLB_FEROCEON=y +CONFIG_CRAMFS=y +# CONFIG_CRC16 is not set +CONFIG_CRC_ITU_T=m +CONFIG_CRC_T10DIF=y +# CONFIG_CRYPTO_AES is not set +CONFIG_CRYPTO_ALGAPI=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_BLKCIPHER=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_MANAGER=m +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_DAB is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_DEBUG_PREEMPT=y +CONFIG_DEBUG_USER=y +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_CFQ=y +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DEVPORT=y +# CONFIG_DL2K is not set +CONFIG_DMADEVICES=y +# CONFIG_DMATEST is not set +CONFIG_DMA_ENGINE=y +# CONFIG_DRM is not set +# CONFIG_DUMMY is not set +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_ECONET is not set +# CONFIG_EEPRO100 is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_EMBEDDED=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_EPIC100 is not set +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_FS=y +# CONFIG_FB is not set +# CONFIG_FDDI is not set +# CONFIG_FEALNX is not set +# CONFIG_FIREWIRE is not set +# CONFIG_FORCEDETH is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_FUSION is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +# CONFIG_HAMACHI is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_HAVE_CLK is not set +# CONFIG_HID_FF is not set +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_HIPPI is not set +# CONFIG_HP100 is not set +# CONFIG_HP_ILO is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON_VID is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2O is not set +# CONFIG_IDE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_IGB is not set +CONFIG_INET_DIAG=y +# CONFIG_INET_LRO is not set +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_IP1000 is not set +# CONFIG_IPV6 is not set +# CONFIG_IPX is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_MROUTE is not set +CONFIG_IP_PNP_DHCP=y +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_ISCSI_TCP is not set +CONFIG_ISO9660_FS=m +CONFIG_JBD=y +CONFIG_JOLIET=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYS is not set +# CONFIG_LAPB is not set +CONFIG_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CPU=y +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_PCA955X is not set +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_LIBCRC32C is not set +CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCK_KERNEL=y +# CONFIG_MAC80211 is not set +CONFIG_MACH_DB88F5281=y +CONFIG_MACH_DNS323=y +CONFIG_MACH_KUROBOX_PRO=y +CONFIG_MACH_LINKSTATION_PRO=y +CONFIG_MACH_MSS2=y +CONFIG_MACH_MV2120=y +CONFIG_MACH_RD88F5181L_FXO=y +CONFIG_MACH_RD88F5181L_GE=y +CONFIG_MACH_RD88F5182=y +CONFIG_MACH_TS209=y +CONFIG_MACH_TS409=y +CONFIG_MACH_TS78XX=y +CONFIG_MACH_WNR854T=y +CONFIG_MACH_WRT350N_V2=y +# CONFIG_MD is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_MINIX_FS is not set +CONFIG_MISC_DEVICES=y +# CONFIG_MMC is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +CONFIG_MSDOS_FS=y +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_NOSWAP=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_ORION=y +# CONFIG_MTD_NAND_PLATFORM is not set +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_START=0x0 +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_UBI is not set +CONFIG_MV643XX_ETH=y +CONFIG_MV_XOR=y +# CONFIG_NAMESPACES is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +CONFIG_NETDEV_1000=y +# CONFIG_NETDEV_10000 is not set +# CONFIG_NETFILTER is not set +# CONFIG_NET_DMA is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_IPGRE is not set +CONFIG_NET_PCI=y +CONFIG_NET_PKTGEN=m +# CONFIG_NET_SCHED is not set +# CONFIG_NET_TULIP is not set +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NEW_LEDS=y +# CONFIG_NFSD is not set +CONFIG_NLS=y +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +CONFIG_NLS_ISO8859_2=y +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_NOZOMI is not set +CONFIG_NO_HZ=y +# CONFIG_NS83820 is not set +CONFIG_OABI_COMPAT=y +CONFIG_OPROFILE=y +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +CONFIG_PCI=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_LEGACY=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCNET32 is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_PHANTOM is not set +CONFIG_PLAT_ORION=y +# CONFIG_PM is not set +CONFIG_PREEMPT=y +# CONFIG_PREEMPT_TRACER is not set +CONFIG_PROFILING=y +# CONFIG_QLA3XXX is not set +# CONFIG_R6040 is not set +# CONFIG_R8169 is not set +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_RFKILL is not set +# CONFIG_ROMFS_FS is not set +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DEBUG is not set +# CONFIG_RTC_DRV_CMOS is not set +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +CONFIG_RTC_DRV_M41T80=y +# CONFIG_RTC_DRV_M41T80_WDT is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +CONFIG_RTC_DRV_RS5C372=y +CONFIG_RTC_DRV_S35390A=y +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_INIC162X is not set +CONFIG_SATA_MV=y +# CONFIG_SATA_NV is not set +CONFIG_SATA_PMP=y +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SC92031 is not set +CONFIG_SCSI=y +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_PROC_FS is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +CONFIG_SENSORS_LM75=y +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIO is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_SIS190 is not set +# CONFIG_SIS900 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SMC91X is not set +# CONFIG_SOUND is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_SYN_COOKIES is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_TICK_ONESHOT=y +# CONFIG_TIFM_CORE is not set +# CONFIG_TIGON3 is not set +# CONFIG_TLAN is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TR is not set +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_USB=y +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_FTDI_ELAN is not set +CONFIG_USB_HID=y +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LIBUSUAL is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_PHIDGET is not set +CONFIG_USB_PRINTER=y +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_SL811_HCD is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_STORAGE_DATAFAB=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_FREECOM=y +# CONFIG_USB_STORAGE_ISD200 is not set +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_WDM is not set +# CONFIG_VETH is not set +CONFIG_VFAT_FS=y +CONFIG_VFP=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_VT is not set +# CONFIG_WAN is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_WATCHDOG is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_WLAN_80211 is not set +# CONFIG_X25 is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_ZISOFS is not set --- linux-2.6.27.orig/debian/config/armel/config.ixp4xx +++ linux-2.6.27/debian/config/armel/config.ixp4xx @@ -0,0 +1,835 @@ +# +# Config options for config.ixp4xx automatically generated by splitconfig.pl +# +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_ACENIC is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_APPLICOM is not set +CONFIG_ARCH_ADI_COYOTE=y +# CONFIG_ARCH_IOP32X is not set +CONFIG_ARCH_IXCDP1100=y +CONFIG_ARCH_IXDP425=y +CONFIG_ARCH_IXDP4XX=y +CONFIG_ARCH_IXP4XX=y +# CONFIG_ARCH_ORION5X is not set +CONFIG_ARCH_PRPMC1100=y +CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCNET is not set +# CONFIG_ARM_THUMB is not set +CONFIG_ASK_IP_FIB_HASH=y +CONFIG_ATA=y +CONFIG_ATALK=m +# CONFIG_ATA_GENERIC is not set +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_ATA_PIIX is not set +CONFIG_ATA_SFF=y +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +CONFIG_ATM=y +# CONFIG_ATM_AMBASSADOR is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_FORE200E is not set +# CONFIG_ATM_HE is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_LANAI is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +# CONFIG_ATM_NICSTAR is not set +CONFIG_ATM_TCP=m +# CONFIG_ATM_ZATM is not set +# CONFIG_AX88796 is not set +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_GENERIC is not set +CONFIG_BLK_DEV_HPT366=y +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_IDECD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_IDEDMA_SFF=y +# CONFIG_BLK_DEV_IDEFLOPPY is not set +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_JMICRON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_PLATFORM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SL82C105 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_TC86C001 is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_BNX2 is not set +# CONFIG_BNX2X is not set +CONFIG_BRIDGE=m +CONFIG_BRIDGE_NETFILTER=y +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_BSD_DISKLABEL is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_CASSINI is not set +# CONFIG_CFG80211 is not set +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CLS_U32_MARK is not set +# CONFIG_CLS_U32_PERF is not set +CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp root=/dev/nfs" +# CONFIG_COMPAT_BRK is not set +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_IXP43X=y +CONFIG_CPU_IXP46X=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_XSCALE=y +# CONFIG_CRAMFS is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_DEV_IXP4XX is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CYCLADES_SYNC is not set +CONFIG_DAB=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_USER is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_DEVPORT=y +CONFIG_DEV_APPLETALK=m +# CONFIG_DL2K is not set +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +CONFIG_DMABOUNCE=y +# CONFIG_DMADEVICES is not set +# CONFIG_DRM is not set +# CONFIG_DSCC4 is not set +CONFIG_DUMMY=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_EEPRO100=y +# CONFIG_EEPROM_93CX6 is not set +CONFIG_EMBEDDED=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_EPIC100 is not set +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_FARSYNC is not set +# CONFIG_FB is not set +# CONFIG_FDDI is not set +# CONFIG_FEALNX is not set +CONFIG_FIB_RULES=y +# CONFIG_FIREWIRE is not set +# CONFIG_FORCEDETH is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +# CONFIG_FUSION is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +# CONFIG_HAMACHI is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_HAVE_CLK is not set +CONFIG_HDLC=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_RAW=m +# CONFIG_HDLC_RAW_ETH is not set +CONFIG_HDLC_X25=m +# CONFIG_HID_FF is not set +# CONFIG_HIGH_RES_TIMERS is not set +# CONFIG_HIPPI is not set +# CONFIG_HP100 is not set +# CONFIG_HP_ILO is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_HWMON_VID=y +CONFIG_HW_RANDOM=m +CONFIG_HW_RANDOM_IXP4XX=m +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_IOP3XX is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2O is not set +CONFIG_IDE=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_IDEPCI_PCIBUS_ORDER=y +CONFIG_IDE_PROC_FS=y +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TIMINGS=y +# CONFIG_IEEE1394 is not set +# CONFIG_IFB is not set +# CONFIG_IGB is not set +CONFIG_INET_DIAG=y +# CONFIG_INET_LRO is not set +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_EVDEV is not set +CONFIG_INPUT_IXP4XX_BEEPER=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_IP1000 is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_DECAP=y +CONFIG_IPDDP_ENCAP=y +# CONFIG_IPV6 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARPTABLES=m +# CONFIG_IP_NF_ARP_MANGLE is not set +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_RECENT is not set +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_QUEUE=m +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_TARGET_ECN is not set +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_REJECT=m +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_VS=m +CONFIG_IP_VS_DEBUG=y +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_LC=m +# CONFIG_IP_VS_NQ is not set +# CONFIG_IP_VS_PROTO_AH is not set +# CONFIG_IP_VS_PROTO_ESP is not set +# CONFIG_IP_VS_PROTO_TCP is not set +# CONFIG_IP_VS_PROTO_UDP is not set +CONFIG_IP_VS_RR=m +# CONFIG_IP_VS_SED is not set +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_TAB_BITS=12 +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_WRR=m +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_IWMMXT is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +CONFIG_IXP4XX_ETH=y +# CONFIG_IXP4XX_INDIRECT_PCI is not set +CONFIG_IXP4XX_NPE=y +CONFIG_IXP4XX_QMGR=y +CONFIG_IXP4XX_WATCHDOG=y +CONFIG_JBD=y +# CONFIG_KEYS is not set +# CONFIG_LANMEDIA is not set +CONFIG_LAPB=m +# CONFIG_LAPBETHER is not set +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_FSG=y +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_PCA955X is not set +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_LIBCRC32C is not set +CONFIG_LLC=m +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_MAC80211 is not set +CONFIG_MACH_AVILA=y +CONFIG_MACH_DSMG600=y +CONFIG_MACH_FSG=y +CONFIG_MACH_GATEWAY7001=y +CONFIG_MACH_GTWX5715=y +CONFIG_MACH_IXDP465=y +CONFIG_MACH_IXDPG425=y +CONFIG_MACH_KIXRP435=y +CONFIG_MACH_LOFT=y +CONFIG_MACH_NAS100D=y +CONFIG_MACH_NSLU2=y +CONFIG_MACH_WG302V2=y +# CONFIG_MD is not set +# CONFIG_MINIX_FS is not set +CONFIG_MISC_DEVICES=y +# CONFIG_MLX4_CORE is not set +# CONFIG_MMC is not set +# CONFIG_MODULE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MSDOS_FS is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_INTEL_VR_NOR is not set +CONFIG_MTD_IXP4XX=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PMC551 is not set +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS=y +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_UBI is not set +# CONFIG_MYRI10GE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +CONFIG_NETFILTER_XTABLES=m +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +CONFIG_NET_ACT_POLICE=y +# CONFIG_NET_ACT_SIMP is not set +CONFIG_NET_CLS=y +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_CLS_BASIC is not set +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_FW=m +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_U32=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_FC is not set +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_NET_PCI=y +CONFIG_NET_PKTGEN=m +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_FIFO=y +CONFIG_NET_SCH_GRED=m +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_INGRESS=m +# CONFIG_NET_SCH_NETEM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_TEQL=m +# CONFIG_NET_TULIP is not set +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NEW_LEDS=y +# CONFIG_NFSD is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NIU is not set +# CONFIG_NLS is not set +# CONFIG_NOZOMI is not set +# CONFIG_NO_HZ is not set +# CONFIG_NS83820 is not set +CONFIG_OABI_COMPAT=y +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +CONFIG_PATA_ARTOP=y +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +CONFIG_PATA_IXP4XX_CF=y +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PC300 is not set +# CONFIG_PC300TOO is not set +CONFIG_PCI=y +# CONFIG_PCI200SYN is not set +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_LEGACY=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCNET32 is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_PHANTOM is not set +# CONFIG_PM is not set +# CONFIG_PREEMPT is not set +# CONFIG_PROFILING is not set +# CONFIG_QLA3XXX is not set +# CONFIG_R6040 is not set +# CONFIG_R8169 is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +# CONFIG_RFKILL is not set +# CONFIG_ROMFS_FS is not set +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DEBUG is not set +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_FM3130 is not set +CONFIG_RTC_DRV_ISL1208=y +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set +CONFIG_RTC_DRV_X1205=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +# CONFIG_S2IO is not set +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PMP is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_ULI is not set +CONFIG_SATA_VIA=y +# CONFIG_SATA_VITESSE is not set +# CONFIG_SC92031 is not set +CONFIG_SCSI=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_PROC_FS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_DS1621 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_W83627HF is not set +CONFIG_SENSORS_W83781D=y +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIO is not set +# CONFIG_SFC is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_SIS190 is not set +# CONFIG_SIS900 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SLAB is not set +CONFIG_SLABINFO=y +CONFIG_SLUB=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_SMC91X is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_SOUND is not set +CONFIG_STP=m +# CONFIG_SUNDANCE is not set +# CONFIG_SUNGEM is not set +CONFIG_SYN_COOKIES=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_TEHUTI is not set +# CONFIG_TICK_ONESHOT is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_TIGON3 is not set +# CONFIG_TLAN is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TR is not set +# CONFIG_UDF_FS is not set +CONFIG_USB=y +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ATM is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_DABUSB is not set +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y +CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_FTDI_ELAN is not set +CONFIG_USB_HID=y +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LIBUSUAL is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_SL811_HCD is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_USBNET is not set +# CONFIG_USB_WDM is not set +# CONFIG_VETH is not set +# CONFIG_VFAT_FS is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VT is not set +CONFIG_WAN=y +# CONFIG_WANXL is not set +CONFIG_WAN_ROUTER=m +CONFIG_WAN_ROUTER_DRIVERS=m +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_WDTPCI is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_WLAN_80211 is not set +CONFIG_X25=m +# CONFIG_X25_ASY is not set +CONFIG_XSCALE_PMU=y +# CONFIG_YELLOWFIN is not set --- linux-2.6.27.orig/debian/config/armel/config.iop32x +++ linux-2.6.27/debian/config/armel/config.iop32x @@ -0,0 +1,658 @@ +# +# Config options for config.iop32x automatically generated by splitconfig.pl +# +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_ACENIC is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_APPLICOM is not set +CONFIG_ARCH_IOP32X=y +CONFIG_ARCH_IQ31244=y +CONFIG_ARCH_IQ80321=y +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_ORION5X is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCNET is not set +# CONFIG_ARM_THUMB is not set +CONFIG_ASYNC_CORE=y +CONFIG_ASYNC_MEMCPY=y +CONFIG_ASYNC_XOR=y +CONFIG_ATA=y +# CONFIG_ATALK is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_ATA_PIIX is not set +CONFIG_ATA_SFF=y +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATM is not set +# CONFIG_AX88796 is not set +CONFIG_BINFMT_AOUT=y +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DAC960 is not set +CONFIG_BLK_DEV_DM=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_MD=y +CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_SD=y +# CONFIG_BLK_DEV_SR is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_BNX2 is not set +# CONFIG_BNX2X is not set +# CONFIG_BRIDGE is not set +# CONFIG_BSD_DISKLABEL is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_CASSINI is not set +# CONFIG_CFG80211 is not set +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_ST is not set +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp cachepolicy=writealloc" +# CONFIG_COMPAT_BRK is not set +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_XSCALE=y +CONFIG_CRAMFS=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ANUBIS=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_CAST5=y +CONFIG_CRYPTO_CAST6=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_KHAZAD=y +CONFIG_CRYPTO_LRW=y +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TEA=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y +CONFIG_CRYPTO_WP512=y +CONFIG_CRYPTO_XCBC=y +CONFIG_DAB=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_GPIO is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_CFQ=y +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DEVPORT=y +# CONFIG_DL2K is not set +CONFIG_DMADEVICES=y +# CONFIG_DMATEST is not set +CONFIG_DMA_ENGINE=y +# CONFIG_DM_CRYPT is not set +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DRM is not set +# CONFIG_DUMMY is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_E100=y +CONFIG_E1000=y +# CONFIG_E1000E is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_ECONET is not set +CONFIG_ECRYPT_FS=y +# CONFIG_EEPRO100 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EMBEDDED is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_EPIC100 is not set +CONFIG_EXPORTFS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_FB is not set +# CONFIG_FDDI is not set +# CONFIG_FEALNX is not set +# CONFIG_FIREWIRE is not set +# CONFIG_FORCEDETH is not set +CONFIG_FS_MBCACHE=y +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_FUSION is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_TIME is not set +CONFIG_GPIOLIB=y +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_SYSFS=y +# CONFIG_HAMACHI is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_HAVE_CLK is not set +# CONFIG_HIPPI is not set +# CONFIG_HP100 is not set +# CONFIG_HP_ILO is not set +# CONFIG_HTC_EGPIO is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON_VID is not set +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_I2C_ALGOBIT=m +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_GPIO=m +# CONFIG_I2C_I801 is not set +CONFIG_I2C_IOP3XX=y +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2O is not set +# CONFIG_IDE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_IGB is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +CONFIG_INET_DIAG=y +# CONFIG_INET_LRO is not set +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INTEL_IOP_ADMA=y +# CONFIG_IP1000 is not set +# CONFIG_IPC_NS is not set +CONFIG_IPV6=y +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPX is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_IWMMXT is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +CONFIG_JBD=y +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_LAPB is not set +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LIBCRC32C=y +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_MAC80211 is not set +# CONFIG_MACH_EM7210 is not set +CONFIG_MACH_EP80219=y +CONFIG_MACH_GLANTANK=y +CONFIG_MACH_N2100=y +CONFIG_MD=y +# CONFIG_MD_FAULTY is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_MULTIPATH is not set +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y +# CONFIG_MD_RAID5_RESHAPE is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MINIX_FS is not set +CONFIG_MISC_DEVICES=y +# CONFIG_MLX4_CORE is not set +# CONFIG_MMC is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_OOPS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_BANKWIDTH=1 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_START=0x0 +# CONFIG_MTD_PMC551 is not set +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +# CONFIG_MTD_UBI is not set +# CONFIG_MYRI10GE is not set +CONFIG_NAMESPACES=y +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y +# CONFIG_NETFILTER is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_DMA=y +# CONFIG_NET_FC is not set +# CONFIG_NET_IPGRE is not set +CONFIG_NET_PCI=y +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_TULIP is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NEW_LEDS is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +# CONFIG_NIU is not set +# CONFIG_NLS is not set +# CONFIG_NOZOMI is not set +# CONFIG_NS83820 is not set +# CONFIG_OABI_COMPAT is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +CONFIG_PCI=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_LEGACY=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCNET32 is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_PHANTOM is not set +# CONFIG_PID_NS is not set +CONFIG_PLAT_IOP=y +# CONFIG_PM is not set +# CONFIG_PREEMPT is not set +# CONFIG_PROFILING is not set +# CONFIG_QLA3XXX is not set +# CONFIG_R6040 is not set +CONFIG_R8169=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +# CONFIG_RFKILL is not set +# CONFIG_ROMFS_FS is not set +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DEBUG is not set +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +CONFIG_RTC_DRV_RS5C372=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +# CONFIG_S2IO is not set +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PMP is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_QSTOR is not set +CONFIG_SATA_SIL=y +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +CONFIG_SATA_VITESSE=y +# CONFIG_SC92031 is not set +CONFIG_SCSI=y +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_NSP32 is not set +CONFIG_SCSI_PROC_FS=y +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIO is not set +# CONFIG_SFC is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_SIS190 is not set +# CONFIG_SIS900 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_SLAB=y +CONFIG_SLABINFO=y +# CONFIG_SLUB is not set +# CONFIG_SMC91X is not set +# CONFIG_SOUND is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_TEHUTI is not set +# CONFIG_TICK_ONESHOT is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_TIGON3 is not set +# CONFIG_TLAN is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TPS65010 is not set +# CONFIG_TR is not set +# CONFIG_UDF_FS is not set +CONFIG_USB=y +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_DABUSB is not set +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_HID is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LIBUSUAL is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +CONFIG_USB_MON=y +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_SL811_HCD is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_USBNET is not set +CONFIG_USB_WDM=m +# CONFIG_USER_NS is not set +# CONFIG_UTS_NS is not set +# CONFIG_VETH is not set +# CONFIG_VFAT_FS is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_VLAN_8021Q is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_WAN is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_WATCHDOG is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_X25 is not set +CONFIG_XOR_BLOCKS=y +CONFIG_XSCALE_PMU=y +# CONFIG_YELLOWFIN is not set --- linux-2.6.27.orig/debian/config/armel/config +++ linux-2.6.27/debian/config/armel/config @@ -0,0 +1,517 @@ +# +# Common config options automatically generated by splitconfig.pl +# +# CONFIG_ACORN_PARTITION is not set +# CONFIG_ADFS_FS is not set +CONFIG_AEABI=y +# CONFIG_AFFS_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_AF_RXRPC is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_AMIGA_PARTITION is not set +CONFIG_ANON_INODES=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MSM7X00A is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set +CONFIG_ARCH_SUPPORTS_AOUT=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +# CONFIG_ARPD is not set +# CONFIG_AT24 is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_AUDIT is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_B44 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_BASE_FULL=y +CONFIG_BASE_SMALL=0 +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_BITREVERSE=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_BLOCK=y +# CONFIG_BONDING is not set +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BOUNCE=y +CONFIG_BROKEN_ON_SMP=y +# CONFIG_BT is not set +CONFIG_BUG=y +# CONFIG_CAN is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_CGROUPS is not set +# CONFIG_CIFS is not set +CONFIG_CLASSIC_RCU=y +# CONFIG_CODA_FS is not set +# CONFIG_CONFIGFS_FS is not set +# CONFIG_CONNECTOR is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +CONFIG_CPU_32=y +CONFIG_CPU_32v5=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_CRC_CCITT is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DECNET is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_DEVKMEM=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_DLM is not set +# CONFIG_DM9000 is not set +CONFIG_DNOTIFY=y +# CONFIG_DS1682 is not set +# CONFIG_DVB_CORE is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_EFS_FS is not set +CONFIG_ELF_CORE=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_EPOLL=y +# CONFIG_EQUALIZER is not set +CONFIG_EVENTFD=y +CONFIG_EXPERIMENTAL=y +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_FLATMEM=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_FRAME_POINTER=y +CONFIG_FRAME_WARN=1024 +# CONFIG_FTL is not set +# CONFIG_FTRACE is not set +# CONFIG_FUSE_FS is not set +CONFIG_FUTEX=y +CONFIG_FW_LOADER=y +# CONFIG_GAMEPORT is not set +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_IRQ_PROBE=y +# CONFIG_GROUP_SCHED is not set +# CONFIG_HAMRADIO is not set +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_HFS_FS is not set +CONFIG_HID=y +# CONFIG_HIDRAW is not set +# CONFIG_HID_DEBUG is not set +CONFIG_HID_SUPPORT=y +CONFIG_HOTPLUG=y +# CONFIG_HPFS_FS is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_HZ=100 +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_I2C_DEBUG_CORE is not set +CONFIG_I2C_HELPER_AUTO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IEEE80211 is not set +# CONFIG_IKCONFIG is not set +CONFIG_INET=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INFTL is not set +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_INPUT=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_NOOP=y +# CONFIG_IPMI_HANDLER is not set +# CONFIG_IP_DCCP is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_IRDA is not set +# CONFIG_ISDN is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFS_FS is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_KEXEC is not set +# CONFIG_KGDB is not set +CONFIG_KMOD=y +CONFIG_KPROBES=y +# CONFIG_KPROBES_SANITY_TEST is not set +CONFIG_KRETPROBES=y +CONFIG_LATENCYTOP=y +# CONFIG_LBD is not set +# CONFIG_LDM_PARTITION is not set +CONFIG_LEGACY_PTYS=y +# CONFIG_LKDTM is not set +# CONFIG_LLC2 is not set +CONFIG_LOCALVERSION="" +CONFIG_LOCKD=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_LOCKD_V4=y +# CONFIG_LOCK_STAT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_LSF is not set +# CONFIG_MACVLAN is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_MARKERS is not set +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TMIO is not set +CONFIG_MII=y +# CONFIG_MINIX_SUBPARTITION is not set +CONFIG_MMU=y +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_MTD=y +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_MTD_BLOCK2MTD is not set +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_CHAR=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_ONENAND is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_NCP_FS is not set +CONFIG_NET=y +# CONFIG_NETCONSOLE is not set +CONFIG_NETDEVICES=y +# CONFIG_NETPOLL is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NET_9P is not set +CONFIG_NET_ETHERNET=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_KEY is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_NET_TCPPROBE is not set +CONFIG_NFS_COMMON=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFTL is not set +# CONFIG_NO_IOPORT is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NVRAM is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_OUTER_CACHE is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PARPORT is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_PCCARD is not set +# CONFIG_PCF8575 is not set +# CONFIG_PHYLIB is not set +CONFIG_PLIST=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_PPP is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_PRINTK=y +# CONFIG_PRINTK_TIME is not set +CONFIG_PROC_FS=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_SYSCTL=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_R3964 is not set +# CONFIG_RAID_ATTRS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_RELAY is not set +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_RFD_FTL is not set +CONFIG_ROOT_NFS=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_RTC_LIB=y +CONFIG_RT_MUTEXES=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_SAMPLES is not set +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHED_TRACER is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_TSL2550 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_SGI_PARTITION is not set +CONFIG_SHMEM=y +CONFIG_SIGNALFD=y +# CONFIG_SLIP is not set +# CONFIG_SLOB is not set +# CONFIG_SMB_FS is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SPARSEMEM_MANUAL is not set +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +# CONFIG_SPI is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_SSB is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSFDC is not set +CONFIG_STACKTRACE=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_STANDALONE=y +CONFIG_SUNRPC=y +# CONFIG_SUN_PARTITION is not set +CONFIG_SWAP=y +CONFIG_SYSCTL=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSFS=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +# CONFIG_TASKSTATS is not set +# CONFIG_TCG_TPM is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TCP_MD5SIG is not set +CONFIG_TIMERFD=y +# CONFIG_TIMER_STATS is not set +# CONFIG_TINY_SHMEM is not set +# CONFIG_TIPC is not set +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_TUN is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_UFS_FS is not set +CONFIG_UID16=y +# CONFIG_UIO is not set +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_UNIX=y +CONFIG_UNIX98_PTYS=y +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_GADGET is not set +CONFIG_USB_SUPPORT=y +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_VERSION_SIGNATURE="" +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_MEDIA is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_VIRT_TO_BUS=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_VXFS_FS is not set +# CONFIG_W1 is not set +# CONFIG_WLAN_PRE80211 is not set +CONFIG_XFRM=y +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_USER is not set +# CONFIG_XFS_FS is not set +# CONFIG_XIP_KERNEL is not set +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA=y +CONFIG_ZONE_DMA_FLAG=1 --- linux-2.6.27.orig/debian/config/armel/config.versatile +++ linux-2.6.27/debian/config/armel/config.versatile @@ -0,0 +1,400 @@ +# +# Config options for config.versatile automatically generated by splitconfig.pl +# +CONFIG_AC97_BUS=m +# CONFIG_APM_EMULATION is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_ORION5X is not set +CONFIG_ARCH_VERSATILE=y +CONFIG_ARCH_VERSATILE_PB=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_THUMB=y +CONFIG_ARM_VIC=y +# CONFIG_ATA is not set +# CONFIG_ATALK is not set +# CONFIG_ATM is not set +CONFIG_AX88796=m +# CONFIG_AX88796_93CX6 is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_BRIDGE is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_CFG80211=m +CONFIG_CMDLINE="root=1f03 mem=32M" +# CONFIG_COMPAT_BRK is not set +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_ARM926T=y +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_CPU_COPY_V4WB=y +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CRAMFS=y +CONFIG_CRC16=y +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_ALGAPI=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLKCIPHER=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CRC32C is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_DES is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=m +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_DAB is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_USER=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_DMADEVICES is not set +# CONFIG_DUMMY is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_ECONET is not set +# CONFIG_EMBEDDED is not set +CONFIG_EXPORTFS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_FS=m +CONFIG_FB=y +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FONTS=y +# CONFIG_FONT_10x18 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_ACORN_8x8=y +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_SUN8x16 is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_TIME=y +CONFIG_HAVE_CLK=y +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_HOSTAP is not set +# CONFIG_HWMON is not set +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=m +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_VERSATILE=y +CONFIG_ICST307=y +# CONFIG_IDE is not set +# CONFIG_INET_DIAG is not set +CONFIG_INET_LRO=m +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_INOTIFY is not set +# CONFIG_INPUT_EVDEV is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_MISC is not set +CONFIG_INPUT_MOUSE=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_IPC_NS is not set +# CONFIG_IPV6 is not set +# CONFIG_IPX is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_ISO9660_FS is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_KEYBOARD_STOWAWAY=m +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYS is not set +# CONFIG_LAPB is not set +CONFIG_LEDS=y +# CONFIG_LEDS_CLASS is not set +CONFIG_LEDS_CPU=y +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_TIMER is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_LIBCRC32C is not set +# CONFIG_LIBERTAS is not set +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_LOGO is not set +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAC80211=m +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_MAC80211_HWSIM is not set +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_RC_DEFAULT="pid" +CONFIG_MAC80211_RC_DEFAULT_PID=y +CONFIG_MAC80211_RC_PID=y +CONFIG_MACH_VERSATILE_AB=y +# CONFIG_MD is not set +CONFIG_MINIX_FS=y +# CONFIG_MISC_DEVICES is not set +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=m +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MSDOS_FS is not set +CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_NOSWAP=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_NAND is not set +CONFIG_MTD_OOPS=m +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_DEBUG is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_NAMESPACES=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_NETFILTER is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_SCHED is not set +CONFIG_NEW_LEDS=y +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_NL80211=y +CONFIG_NLS=m +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +CONFIG_NO_HZ=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_P54_COMMON is not set +# CONFIG_PCI is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PID_NS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_PM_DISABLE_CONSOLE is not set +CONFIG_PM_SLEEP=y +# CONFIG_PREEMPT is not set +# CONFIG_PROFILING is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=m +CONFIG_RFKILL_LEDS=y +CONFIG_ROMFS_FS=y +# CONFIG_RT2X00 is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SDIO_UART is not set +CONFIG_SENSORS_EEPROM=m +CONFIG_SERIAL_8250=m +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIO=y +CONFIG_SERIO_AMBAKMI=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_SERPORT is not set +CONFIG_SLAB=y +CONFIG_SLABINFO=y +# CONFIG_SLUB is not set +CONFIG_SMC91X=y +CONFIG_SND=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_ARM=y +CONFIG_SND_ARMAACI=m +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_PCM=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_SOC=m +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_TIMER=m +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VMASTER=y +CONFIG_SOUND=y +# CONFIG_SOUND_PRIME is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +CONFIG_TICK_ONESHOT=y +# CONFIG_TMPFS is not set +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_UBIFS_FS_LZO=y +# CONFIG_UBIFS_FS_XATTR is not set +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UDF_FS is not set +# CONFIG_USB is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USER_NS is not set +# CONFIG_UTS_NS is not set +CONFIG_VETH=m +CONFIG_VFAT_FS=m +CONFIG_VFP=y +# CONFIG_VLAN_8021Q is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_WAN is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_WATCHDOG is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_WLAN_80211=y +# CONFIG_X25 is not set --- linux-2.6.27.orig/debian/config/i386/config.generic +++ linux-2.6.27/debian/config/i386/config.generic @@ -0,0 +1,26 @@ +# +# Config options for config.generic automatically generated by splitconfig.pl +# +CONFIG_DCA=m +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DMADEVICES=y +# CONFIG_DMATEST is not set +CONFIG_DMA_ENGINE=y +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_INTEL_IOATDMA=m +# CONFIG_LGUEST is not set +# CONFIG_LGUEST_GUEST is not set +CONFIG_M586=y +# CONFIG_M686 is not set +CONFIG_NET_DMA=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_RESOURCES_64BIT is not set +CONFIG_X86_ALIGNMENT_16=y +CONFIG_X86_F00F_BUG=y --- linux-2.6.27.orig/debian/config/i386/config.server +++ linux-2.6.27/debian/config/i386/config.server @@ -0,0 +1,33 @@ +# +# Config options for config.server automatically generated by splitconfig.pl +# +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_DEADLINE=y +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +CONFIG_HVC_IRQ=y +CONFIG_HVC_XEN=y +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +# CONFIG_M586 is not set +CONFIG_M686=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_RESOURCES_64BIT=y +CONFIG_X86_CMOV=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_DEBUGCTLMSR=y +CONFIG_X86_PAE=y +CONFIG_X86_TSC=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_XEN=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_FBDEV_FRONTEND=m +CONFIG_XEN_KBDDEV_FRONTEND=m +CONFIG_XEN_MAX_DOMAIN_MEMORY=8 +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_SCRUB_PAGES=y --- linux-2.6.27.orig/debian/config/i386/config +++ linux-2.6.27/debian/config/i386/config @@ -0,0 +1,3720 @@ +# +# Common config options automatically generated by splitconfig.pl +# +CONFIG_3C359=m +CONFIG_3C515=m +# CONFIG_4KSTACKS is not set +CONFIG_60XX_WDT=m +# CONFIG_64BIT is not set +CONFIG_6PACK=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +CONFIG_8139TOO_8129=y +CONFIG_8139TOO_PIO=y +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_9P_FS=m +CONFIG_ABYSS=m +CONFIG_AC3200=m +CONFIG_AC97_BUS=m +# CONFIG_ACCESSIBILITY is not set +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_ACER_WMI=m +CONFIG_ACORN_PARTITION=y +# CONFIG_ACORN_PARTITION_ADFS is not set +# CONFIG_ACORN_PARTITION_CUMANA is not set +# CONFIG_ACORN_PARTITION_EESOX is not set +CONFIG_ACORN_PARTITION_ICS=y +# CONFIG_ACORN_PARTITION_POWERTEC is not set +CONFIG_ACORN_PARTITION_RISCIX=y +CONFIG_ACPI=y +CONFIG_ACPI_AC=m +# CONFIG_ACPI_ASUS is not set +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BAY=m +CONFIG_ACPI_BLACKLIST_YEAR=2000 +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_CONTAINER=m +# CONFIG_ACPI_CUSTOM_DSDT is not set +CONFIG_ACPI_CUSTOM_DSDT_FILE="" +CONFIG_ACPI_CUSTOM_DSDT_INITRD=y +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_EC=y +CONFIG_ACPI_FAN=m +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_PCI_SLOT=m +CONFIG_ACPI_POWER=y +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_PROCFS=y +CONFIG_ACPI_PROCFS_POWER=y +CONFIG_ACPI_PROC_EVENT=y +CONFIG_ACPI_SBS=m +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SYSFS_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_THERMAL=m +# CONFIG_ACPI_TOSHIBA is not set +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_WMI=m +CONFIG_ACQUIRE_WDT=m +CONFIG_ACT200L_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_ADM8211=m +CONFIG_ADVANTECH_WDT=m +CONFIG_AEDSP16_MSS=y +# CONFIG_AEDSP16_SBPRO is not set +CONFIG_AFFS_FS=m +# CONFIG_AFS_DEBUG is not set +CONFIG_AFS_FS=m +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_AGP=m +CONFIG_AGP_ALI=m +CONFIG_AGP_AMD=m +CONFIG_AGP_AMD64=m +CONFIG_AGP_ATI=m +CONFIG_AGP_EFFICEON=m +CONFIG_AGP_INTEL=m +CONFIG_AGP_NVIDIA=m +CONFIG_AGP_SIS=m +CONFIG_AGP_SWORKS=m +CONFIG_AGP_VIA=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_DEBUG_ENABLE=y +CONFIG_AIC79XX_DEBUG_MASK=0 +CONFIG_AIC79XX_REG_PRETTY_PRINT=y +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 +CONFIG_AIC7XXX_DEBUG_ENABLE=y +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC94XX_DEBUG is not set +CONFIG_AIRO=m +CONFIG_AIRO_CS=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_ALI_FIR=m +CONFIG_AMD8111_ETH=m +CONFIG_AMIGA_PARTITION=y +CONFIG_ANON_INODES=y +CONFIG_APM=m +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_CPU_IDLE is not set +# CONFIG_APM_DISPLAY_BLANK is not set +# CONFIG_APM_DO_ENABLE is not set +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set +CONFIG_APPLICOM=m +CONFIG_APRICOT=m +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_ARCH_HAS_CPU_RELAX=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCNET=m +CONFIG_ARCNET_1051=m +CONFIG_ARCNET_1201=m +CONFIG_ARCNET_CAP=m +CONFIG_ARCNET_COM20020=m +CONFIG_ARCNET_COM20020_CS=m +CONFIG_ARCNET_COM20020_ISA=m +CONFIG_ARCNET_COM20020_PCI=m +CONFIG_ARCNET_COM90xx=m +CONFIG_ARCNET_COM90xxIO=m +CONFIG_ARCNET_RAW=m +CONFIG_ARCNET_RIM_I=m +CONFIG_ARLAN=m +# CONFIG_ARPD is not set +CONFIG_ASK_IP_FIB_HASH=y +CONFIG_ASUS_LAPTOP=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_AT1700=m +CONFIG_AT24=m +CONFIG_ATA=m +CONFIG_ATALK=m +CONFIG_ATARI_PARTITION=y +CONFIG_ATA_ACPI=y +CONFIG_ATA_GENERIC=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_OVER_ETH=m +CONFIG_ATA_PIIX=m +CONFIG_ATA_SFF=y +# CONFIG_ATH5K is not set +CONFIG_ATH9K=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL2=m +CONFIG_ATM=y +CONFIG_ATMEL=m +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_FORE200E=m +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E_TX_RETRY=16 +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_LANAI=m +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATP=m +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_AUDIT_ARCH is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_TREE=y +CONFIG_AUFS=m +# CONFIG_AUFS_BRANCH_MAX_1023 is not set +CONFIG_AUFS_BRANCH_MAX_127=y +# CONFIG_AUFS_BRANCH_MAX_32767 is not set +# CONFIG_AUFS_BRANCH_MAX_511 is not set +CONFIG_AUFS_BR_NFS=y +CONFIG_AUFS_BR_XFS=y +# CONFIG_AUFS_COMPAT is not set +# CONFIG_AUFS_DEBUG is not set +CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH=y +# CONFIG_AUFS_DLGT is not set +CONFIG_AUFS_EXPORT=y +# CONFIG_AUFS_FSYNC_SUPER_PATCH is not set +CONFIG_AUFS_HINOTIFY=y +CONFIG_AUFS_HIN_OR_DLGT=y +CONFIG_AUFS_HIN_OR_FUSE=y +CONFIG_AUFS_LHASH_PATCH=y +CONFIG_AUFS_PUT_FILP_PATCH=y +# CONFIG_AUFS_ROBR is not set +CONFIG_AUFS_RR_SQUASHFS=y +CONFIG_AUFS_SEC_PERM_PATCH=y +CONFIG_AUFS_SHWH=y +CONFIG_AUFS_SPLICE_PATCH=y +CONFIG_AUFS_STAT=y +# CONFIG_AUFS_UNIONFS22_PATCH is not set +# CONFIG_AUFS_UNIONFS23_PATCH is not set +# CONFIG_AUFS_WORKAROUND_FUSE is not set +CONFIG_AUTOFS4_FS=m +CONFIG_AUTOFS_FS=m +CONFIG_AUXDISPLAY=y +CONFIG_AVERATEC_5100P=m +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_DEBUG=y +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PIO=y +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_B43LEGACY_RFKILL=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43_LEDS=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_PCI_AUTOSELECT=y +# CONFIG_B43_PCMCIA is not set +CONFIG_B43_RFKILL=y +CONFIG_B44=m +CONFIG_B44_PCI=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_BACKLIGHT_CARILLO_RANCH=m +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_CORGI=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_MBP_NVIDIA=m +CONFIG_BACKLIGHT_PROGEAR=m +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_BASE_FULL=y +CONFIG_BASE_SMALL=0 +CONFIG_BATTERY_DS2760=m +CONFIG_BATTERY_OLPC=m +CONFIG_BAYCOM_EPP=m +CONFIG_BAYCOM_PAR=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BEFS_FS=m +CONFIG_BFS_FS=m +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_BITREVERSE=y +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_DEV=y +CONFIG_BLK_DEV_3W_XXXX_RAID=m +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_COMPCACHE=m +# CONFIG_BLK_DEV_COMPCACHE_DEBUG is not set +# CONFIG_BLK_DEV_COMPCACHE_STATS is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_DM=m +CONFIG_BLK_DEV_DM_BBR=m +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_MD=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_XIP is not set +CONFIG_BLOCK=y +CONFIG_BNX2=m +CONFIG_BNX2X=m +CONFIG_BONDING=m +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BOUNCE=y +CONFIG_BPQETHER=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_NETFILTER=y +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BROADCOM_PHY=m +CONFIG_BSD_DISKLABEL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_BT=m +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIVHCI=m +CONFIG_BT_HIDP=m +CONFIG_BT_L2CAP=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_SCO=m +CONFIG_BUG=y +CONFIG_C101=m +# CONFIG_CAN is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_CAPI_AVM=y +CONFIG_CAPI_EICON=y +CONFIG_CAPI_TRACE=y +CONFIG_CARDBUS=y +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_CARMINE_DRAM_CUSTOM is not set +CONFIG_CASSINI=m +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_CFAG12864B=m +CONFIG_CFAG12864B_RATE=20 +CONFIG_CFG80211=m +CONFIG_CGROUPS=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_DEVICE is not set +CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_NS=y +CONFIG_CGROUP_SCHED=y +CONFIG_CHECK_SIGNATURE=y +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3=m +CONFIG_CHR_DEV_OSST=m +CONFIG_CHR_DEV_SCH=m +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_ST=m +CONFIG_CICADA_PHY=m +CONFIG_CIFS=m +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_EXPERIMENTAL=y +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_WEAK_PW_HASH=y +# CONFIG_CIFS_XATTR is not set +CONFIG_CISS_SCSI_TAPE=y +CONFIG_CLASSIC_RCU=y +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_CLS_U32_MARK=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CODA_FS=m +CONFIG_COMPAL_LAPTOP=m +# CONFIG_COMPAT_BRK is not set +# CONFIG_COMPAT_VDSO is not set +CONFIG_COMPUTONE=m +CONFIG_CONFIGFS_FS=m +CONFIG_CONNECTOR=y +CONFIG_CONSOLE_POLL=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_SWITCH_TRACER=y +# CONFIG_COPS is not set +CONFIG_COSA=m +# CONFIG_CPA_DEBUG is not set +CONFIG_CPU5_WDT=m +CONFIG_CPUSETS=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEBUG is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_TABLE=m +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CRAMFS=y +CONFIG_CRASH_DUMP=y +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_CRC_CCITT=m +CONFIG_CRC_ITU_T=m +CONFIG_CRC_T10DIF=m +CONFIG_CRYPTO=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_DEV_GEODE=m +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y +CONFIG_CRYPTO_DEV_PADLOCK=y +CONFIG_CRYPTO_DEV_PADLOCK_AES=m +CONFIG_CRYPTO_DEV_PADLOCK_SHA=m +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_LZO=m +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SALSA20_586=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_586=m +CONFIG_CRYPTO_TWOFISH_COMMON=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_XTS=m +CONFIG_CS5535_GPIO=m +CONFIG_CS89x0=m +CONFIG_CYCLADES=m +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +# CONFIG_CYZ_INTR is not set +# CONFIG_DAB is not set +CONFIG_DAVICOM_PHY=m +CONFIG_DCDBAS=m +CONFIG_DE2104X=m +CONFIG_DE4X5=m +CONFIG_DE600=m +CONFIG_DE620=m +# CONFIG_DEBUG_BOOT_PARAMS is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DECNET=m +CONFIG_DECNET_NF_GRABULATOR=m +# CONFIG_DECNET_ROUTER is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +CONFIG_DEFAULT_IO_DELAY_TYPE=1 +# CONFIG_DEFAULT_NOOP is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_WESTWOOD is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_DEFXX=m +# CONFIG_DEFXX_MMIO is not set +CONFIG_DELL_RBU=m +CONFIG_DEPCA=m +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_DEVKMEM=y +CONFIG_DEVPORT=y +CONFIG_DEV_APPLETALK=m +CONFIG_DE_AOC=y +CONFIG_DIGIEPCA=m +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_DISPLAY_SUPPORT=m +# CONFIG_DL2K is not set +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +CONFIG_DLM=m +# CONFIG_DLM_DEBUG is not set +CONFIG_DM9102=m +CONFIG_DMI=y +CONFIG_DMIID=y +CONFIG_DM_CRYPT=m +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_LOOP=m +CONFIG_DM_MIRROR=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_RAID45=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_UEVENT=y +CONFIG_DM_ZERO=m +CONFIG_DNOTIFY=y +CONFIG_DONGLE=y +CONFIG_DOUBLEFAULT=y +CONFIG_DRM=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_SAVAGE=m +CONFIG_DRM_SIS=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_VIA=m +CONFIG_DRM_VIA_CHROME9=m +CONFIG_DS1682=m +CONFIG_DSCC4=m +CONFIG_DSCC4_PCISYNC=y +CONFIG_DSCC4_PCI_RST=y +CONFIG_DTLK=m +CONFIG_DUMMY=m +CONFIG_DUMMY_CONSOLE=y +CONFIG_DVB_AU8522=m +CONFIG_DVB_AV7110=m +# CONFIG_DVB_AV7110_FIRMWARE is not set +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_B2C2_FLEXCOP=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_BT8XX=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET_PATCH=m +CONFIG_DVB_CAPTURE_DRIVERS=y +CONFIG_DVB_CINERGYT2=m +# CONFIG_DVB_CINERGYT2_TUNING is not set +CONFIG_DVB_CORE=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_DRX397XD=m +# CONFIG_DVB_FE_CUSTOMISE is not set +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_L64781=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_MT312=m +CONFIG_DVB_MT352=m +CONFIG_DVB_NXT200X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_PLL=m +CONFIG_DVB_PLUTO2=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_S5H1411=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_SIANO_SMS1XXX=m +CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_STV0297=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_USB=m +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_CXUSB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_VES1820=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_ZL10353=m +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +# CONFIG_E1000E_ENABLED is not set +# CONFIG_E1000E_NEW is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_E2100=m +CONFIG_EARLY_PRINTK=y +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_ECRYPT_FS=m +CONFIG_EDAC=y +CONFIG_EDAC_AMD76X=m +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_E752X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_I3000=m +CONFIG_EDAC_I5000=m +CONFIG_EDAC_I5100=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82975X=m +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_R82600=m +CONFIG_EDD=y +CONFIG_EDD_OFF=y +CONFIG_EEEPC_LAPTOP=m +CONFIG_EEPRO100=m +CONFIG_EEPROM_93CX6=m +CONFIG_EEXPRESS=m +CONFIG_EEXPRESS_PRO=m +CONFIG_EFI=y +CONFIG_EFI_PARTITION=y +CONFIG_EFI_VARS=y +CONFIG_EFS_FS=m +CONFIG_EISA=y +CONFIG_EISA_NAMES=y +CONFIG_EISA_PCI_EISA=y +CONFIG_EISA_VIRTUAL_ROOT=y +CONFIG_EISA_VLB_PRIMING=y +CONFIG_EL1=m +CONFIG_EL16=m +CONFIG_EL2=m +CONFIG_EL3=m +CONFIG_ELF_CORE=y +CONFIG_ELMC=m +CONFIG_ELMC_II=m +CONFIG_ELPLUS=m +# CONFIG_EMBEDDED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENC28J60 is not set +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_EPIC100=m +CONFIG_EPOLL=y +CONFIG_EQUALIZER=m +CONFIG_ES3210=m +CONFIG_ESI_DONGLE=m +CONFIG_ESPSERIAL=m +CONFIG_ETH16I=m +CONFIG_EUROTECH_WDT=m +CONFIG_EVENTFD=y +CONFIG_EWRK3=m +CONFIG_EXPERIMENTAL=y +CONFIG_EXPORTFS=m +CONFIG_EXT2_FS=m +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT4DEV_FS=m +CONFIG_EXT4DEV_FS_POSIX_ACL=y +CONFIG_EXT4DEV_FS_SECURITY=y +CONFIG_EXT4DEV_FS_XATTR=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FARSYNC=m +CONFIG_FAST_CMPXCHG_LOCAL=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_FS=m +# CONFIG_FAULT_INJECTION is not set +CONFIG_FB=y +CONFIG_FB_3DFX=m +# CONFIG_FB_3DFX_ACCEL is not set +CONFIG_FB_ARC=m +CONFIG_FB_ARK=m +CONFIG_FB_ASILIANT=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY128=m +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_CARILLO_RANCH=m +CONFIG_FB_CARMINE=m +CONFIG_FB_CARMINE_DRAM_EVAL=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_CIRRUS=m +CONFIG_FB_CYBER2000=m +CONFIG_FB_CYBLA=m +CONFIG_FB_DDC=m +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_EFI=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_GEODE=y +CONFIG_FB_GEODE_GX=m +CONFIG_FB_GEODE_GX1=m +CONFIG_FB_GEODE_LX=m +CONFIG_FB_HECUBA=m +CONFIG_FB_HGA=m +# CONFIG_FB_HGA_ACCEL is not set +CONFIG_FB_I810=m +# CONFIG_FB_I810_GTF is not set +CONFIG_FB_IMAC=y +CONFIG_FB_IMSTT=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_INTEL_I2C=y +CONFIG_FB_KYRO=m +CONFIG_FB_LE80578=m +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_N411=m +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_BACKLIGHT=y +# CONFIG_FB_NVIDIA_DEBUG is not set +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_PM2=m +CONFIG_FB_PM2_FIFO_DISCONNECT=y +CONFIG_FB_PM3=m +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RIVA=m +CONFIG_FB_RIVA_BACKLIGHT=y +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_I2C=y +CONFIG_FB_S1D13XXX=m +CONFIG_FB_S3=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_SM501=m +CONFIG_FB_SVGALIB=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_TRIDENT=m +# CONFIG_FB_TRIDENT_ACCEL is not set +CONFIG_FB_UVESA=m +CONFIG_FB_VESA=m +CONFIG_FB_VGA16=m +# CONFIG_FB_VIRTUAL is not set +CONFIG_FB_VOODOO1=m +CONFIG_FB_VT8623=m +CONFIG_FDDI=y +CONFIG_FEALNX=m +CONFIG_FIB_RULES=y +# CONFIG_FIREWIRE is not set +CONFIG_FIRMWARE_EDID=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FLATMEM=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x16=y +CONFIG_FONT_8x8=y +CONFIG_FORCEDETH=m +# CONFIG_FORCEDETH_NAPI is not set +CONFIG_FRAMEBUFFER_CONSOLE=m +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FRAME_POINTER=y +CONFIG_FRAME_WARN=1024 +CONFIG_FSAM7400=m +CONFIG_FS_MBCACHE=m +CONFIG_FS_POSIX_ACL=y +CONFIG_FS_UNIONFS=m +CONFIG_FTL=m +CONFIG_FTRACE=y +# CONFIG_FTRACE_STARTUP_TEST is not set +CONFIG_FUJITSU_LAPTOP=m +# CONFIG_FUJITSU_LAPTOP_DEBUG is not set +CONFIG_FUSE_FS=m +CONFIG_FUSION=y +CONFIG_FUSION_CTL=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_LAN=m +CONFIG_FUSION_LOGGING=y +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_SAS=m +CONFIG_FUSION_SPI=m +CONFIG_FUTEX=y +CONFIG_FW_LOADER=y +CONFIG_GACT_PROB=y +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GARP=m +CONFIG_GENERIC_ACL=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +# CONFIG_GENERIC_CPU is not set +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_GENERIC_LOCKBREAK is not set +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_GENERIC_TIME=y +# CONFIG_GENERIC_TIME_VSYSCALL is not set +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=m +CONFIG_GFS_FS=m +CONFIG_GIGASET_BASE=m +# CONFIG_GIGASET_DEBUG is not set +CONFIG_GIGASET_M101=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_UNDOCREQ is not set +CONFIG_GIRBIL_DONGLE=m +CONFIG_GNBD=m +CONFIG_GPIOLIB=y +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_SYSFS=y +CONFIG_GROUP_SCHED=y +CONFIG_HAMACHI=m +CONFIG_HAMRADIO=y +CONFIG_HANGCHECK_TIMER=m +CONFIG_HAPPYMEAL=m +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_CLK is not set +# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y +CONFIG_HDLC=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_X25=m +# CONFIG_HEADERS_CHECK is not set +CONFIG_HECI=m +CONFIG_HERMES=m +CONFIG_HFSPLUS_FS=m +CONFIG_HFS_FS=m +CONFIG_HIBERNATION=y +CONFIG_HID=m +CONFIG_HIDRAW=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HID_FF is not set +CONFIG_HID_SUPPORT=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_HIPPI=y +CONFIG_HISAX_16_0=y +CONFIG_HISAX_16_3=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_ASUSCOM=y +CONFIG_HISAX_AVM_A1=y +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_BKM_A4T=y +# CONFIG_HISAX_DEBUG is not set +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_ENTERNOW_PCI=y +CONFIG_HISAX_EURO=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HDLC=y +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_HFCS=y +CONFIG_HISAX_HFCUSB=m +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_HSTSAPHIR=y +CONFIG_HISAX_ISURF=y +CONFIG_HISAX_IX1MICROR2=y +CONFIG_HISAX_MAX_CARDS=8 +CONFIG_HISAX_MIC=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_NO_KEYPAD is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_SPORTSTER=y +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_TELEINT=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_TELES_CS=m +CONFIG_HISAX_W6692=y +CONFIG_HOSTAP=m +CONFIG_HOSTAP_CS=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTESS_SV11=m +CONFIG_HOTPLUG=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_PCI=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +CONFIG_HOTPLUG_PCI_COMPAQ=m +CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y +CONFIG_HOTPLUG_PCI_CPCI=y +CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m +CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_HOTPLUG_PCI_PCIE=m +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HP100=m +CONFIG_HPET=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_HPET_MMAP=y +CONFIG_HPET_TIMER=y +CONFIG_HPFS_FS=m +CONFIG_HPLAN=m +CONFIG_HPLAN_PLUS=m +CONFIG_HP_ILO=m +# CONFIG_HP_WATCHDOG is not set +CONFIG_HP_WMI=m +CONFIG_HTC_PASIC3=m +CONFIG_HT_IRQ=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HVC_DRIVER=y +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_HWMON_VID=m +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_HW_RANDOM_VIRTIO=m +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_300 is not set +CONFIG_I2C=m +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=m +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_I2C_DEBUG_CORE is not set +CONFIG_I2C_GPIO=m +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_I801=m +CONFIG_I2C_ISCH=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_NFORCE2_S4985=m +CONFIG_I2C_OCORES=m +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PCA_ISA=m +CONFIG_I2C_PCA_PLATFORM=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_SIMTEC=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_TAOS_EVM=m +CONFIG_I2C_TINY_USB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2O=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_BUS=m +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y +CONFIG_I2O_PROC=m +CONFIG_I2O_SCSI=m +CONFIG_I6300ESB_WDT=m +CONFIG_I82092=m +CONFIG_I82365=m +CONFIG_I8K=m +CONFIG_IB700_WDT=m +CONFIG_IBMASR=m +CONFIG_IBMLANA=m +CONFIG_IBMLS=m +# CONFIG_IBMMCA_SCSI_DEV_RESET is not set +CONFIG_IBMMCA_SCSI_ORDER_STANDARD=y +CONFIG_IBMOL=m +CONFIG_IBMTR=m +CONFIG_IBM_ASM=m +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +CONFIG_ICPLUS_PHY=m +# CONFIG_IDE is not set +CONFIG_IEEE1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_CRYPT_WEP=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IFB=m +CONFIG_IGB=m +# CONFIG_IGB_LRO is not set +# CONFIG_IKCONFIG is not set +CONFIG_INET=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET_AH=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_INET_DIAG=y +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_LRO=m +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_AMSO1100=m +CONFIG_INFINIBAND_AMSO1100_DEBUG=y +CONFIG_INFINIBAND_CXGB3=m +# CONFIG_INFINIBAND_CXGB3_DEBUG is not set +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y +CONFIG_INFINIBAND_IPOIB_DEBUG=y +# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set +CONFIG_INFINIBAND_ISER=m +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +# CONFIG_INFINIBAND_NES is not set +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_MEM=y +CONFIG_INFTL=m +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_INPUT=y +CONFIG_INPUT_ACERHK=m +# CONFIG_INPUT_APANEL is not set +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_ATLAS_BTNS=m +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_MOUSE=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_POLLDEV=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_YEALINK=m +CONFIG_INTEL_MENLOW=m +# CONFIG_IOMMU_HELPER is not set +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_NOOP=y +# CONFIG_IO_DELAY_0X80 is not set +CONFIG_IO_DELAY_0XED=y +# CONFIG_IO_DELAY_NONE is not set +CONFIG_IO_DELAY_TYPE_0X80=0 +CONFIG_IO_DELAY_TYPE_0XED=1 +CONFIG_IO_DELAY_TYPE_NONE=3 +CONFIG_IO_DELAY_TYPE_UDELAY=2 +# CONFIG_IO_DELAY_UDELAY is not set +CONFIG_IP1000=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IPC_NS=y +CONFIG_IPDDP=m +CONFIG_IPDDP_DECAP=y +CONFIG_IPDDP_ENCAP=y +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_POWEROFF=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPPP_FILTER=y +CONFIG_IPV6=m +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_IPV6_PRIVACY=y +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IPV6_TUNNEL=m +CONFIG_IPW2100=m +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2200=m +# CONFIG_IPW2200_DEBUG is not set +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPWIRELESS=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_DCCP=m +CONFIG_IP_DCCP_ACKVEC=y +CONFIG_IP_DCCP_CCID2=m +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=m +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +# CONFIG_IP_DCCP_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=m +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_IP_PNP is not set +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_SCTP=m +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_TAB_BITS=12 +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_WRR=m +CONFIG_IRCOMM=m +CONFIG_IRDA=m +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_DEBUG=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRDA_ULTRA=y +CONFIG_IRLAN=m +CONFIG_IRNET=m +# CONFIG_IRQBALANCE is not set +# CONFIG_IRQSOFF_TRACER is not set +CONFIG_IRTTY_SIR=m +CONFIG_ISA=y +CONFIG_ISAPNP=y +CONFIG_ISA_DMA_API=y +CONFIG_ISCSI_IBFT=m +CONFIG_ISCSI_IBFT_FIND=y +CONFIG_ISCSI_TCP=m +CONFIG_ISDN=y +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIDRV=m +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_MAINT=m +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVERSION=m +CONFIG_ISDN_DRV_ACT2000=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_B1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_ISDN_DRV_AVMB1_T1ISA=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_ISDN_DRV_HISAX=m +CONFIG_ISDN_DRV_ICN=m +CONFIG_ISDN_DRV_PCBIT=m +CONFIG_ISDN_DRV_SC=m +CONFIG_ISDN_I4L=m +CONFIG_ISDN_MPP=y +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_TTY_FAX=y +CONFIG_ISDN_X25=y +# CONFIG_ISI is not set +CONFIG_ISO9660_FS=m +CONFIG_IT8712F_WDT=m +CONFIG_ITCO_VENDOR_SUPPORT=y +CONFIG_ITCO_WDT=m +CONFIG_IWL3945=m +# CONFIG_IWL3945_DEBUG is not set +CONFIG_IWL3945_LEDS=y +CONFIG_IWL3945_RFKILL=y +CONFIG_IWL3945_SPECTRUM_MEASUREMENT=y +CONFIG_IWL4965=y +CONFIG_IWL5000=y +CONFIG_IWLAGN=m +CONFIG_IWLAGN_LEDS=y +CONFIG_IWLAGN_SPECTRUM_MEASUREMENT=y +CONFIG_IWLCORE=m +CONFIG_IWLWIFI=m +# CONFIG_IWLWIFI_DEBUG is not set +CONFIG_IWLWIFI_LEDS=y +CONFIG_IWLWIFI_RFKILL=y +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_JBD=m +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_JOLIET=y +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_K8_NB=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_KARMA_PARTITION=y +CONFIG_KEXEC=y +CONFIG_KEXEC_JUMP=y +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +CONFIG_KGDB=y +CONFIG_KGDB_SERIAL_CONSOLE=y +# CONFIG_KGDB_TESTS is not set +CONFIG_KINGSUN_DONGLE=m +CONFIG_KMOD=y +CONFIG_KPROBES=y +# CONFIG_KPROBES_SANITY_TEST is not set +CONFIG_KRETPROBES=y +CONFIG_KS0108=m +CONFIG_KS0108_DELAY=2 +CONFIG_KS0108_PORT=0x378 +CONFIG_KS959_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KTIME_SCALAR=y +CONFIG_KVM=m +CONFIG_KVM_AMD=m +CONFIG_KVM_CLOCK=y +CONFIG_KVM_GUEST=y +CONFIG_KVM_INTEL=m +# CONFIG_KVM_TRACE is not set +CONFIG_LANCE=m +CONFIG_LANMEDIA=m +CONFIG_LAPB=m +CONFIG_LAPBETHER=m +CONFIG_LATENCYTOP=y +CONFIG_LBD=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_ILI9320=m +CONFIG_LCD_LTV350QV=m +CONFIG_LCD_PLATFORM=m +CONFIG_LCD_VGG2432A4=m +# CONFIG_LDM_DEBUG is not set +CONFIG_LDM_PARTITION=y +CONFIG_LEDS_CLASS=m +# CONFIG_LEDS_CLEVO_MAIL is not set +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_NET48XX=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_WRAP=m +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LIBCRC32C=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_CS=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIRC_ATIUSB=m +CONFIG_LIRC_BT829=m +CONFIG_LIRC_CMDIR=m +CONFIG_LIRC_DEV=m +# CONFIG_LIRC_GPIO is not set +CONFIG_LIRC_I2C=m +CONFIG_LIRC_IGORPLUGUSB=m +CONFIG_LIRC_IMON=m +CONFIG_LIRC_IT87=m +CONFIG_LIRC_MCEUSB=m +CONFIG_LIRC_MCEUSB2=m +# CONFIG_LIRC_PARALLEL is not set +CONFIG_LIRC_PVR150=m +CONFIG_LIRC_SASEM=m +CONFIG_LIRC_SERIAL=m +CONFIG_LIRC_SERIAL_IGOR=m +CONFIG_LIRC_SIR=m +CONFIG_LIRC_STREAMZAP=m +CONFIG_LIRC_TTUSBIR=m +CONFIG_LITELINK_DONGLE=m +# CONFIG_LKDTM is not set +CONFIG_LLC=y +CONFIG_LLC2=m +CONFIG_LMPCM_USB=m +CONFIG_LNE390=m +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_LOCKD=m +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_LOCKD_V4=y +CONFIG_LOCK_KERNEL=y +# CONFIG_LOCK_STAT is not set +# CONFIG_LOGO is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LP486E=m +# CONFIG_LP_CONSOLE is not set +CONFIG_LSF=y +CONFIG_LTPC=m +CONFIG_LXT_PHY=m +CONFIG_LZO_COMPRESS=m +CONFIG_LZO_DECOMPRESS=m +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586MMX is not set +# CONFIG_M586TSC is not set +CONFIG_MA600_DONGLE=m +CONFIG_MAC80211=m +CONFIG_MAC80211_DEBUGFS=y +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_MAC80211_HWSIM is not set +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_RC_DEFAULT="pid" +CONFIG_MAC80211_RC_DEFAULT_PID=y +CONFIG_MAC80211_RC_PID=y +CONFIG_MACHZ_WDT=m +CONFIG_MACINTOSH_DRIVERS=y +CONFIG_MACVLAN=m +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_MAC_PARTITION=y +CONFIG_MADGEMC=m +CONFIG_MAGIC_SYSRQ=y +CONFIG_MARKERS=y +CONFIG_MARVELL_PHY=m +# CONFIG_MATH_EMULATION is not set +CONFIG_MAX_RAW_DEVS=256 +CONFIG_MCA=y +CONFIG_MCA_LEGACY=y +# CONFIG_MCA_PROC_FS is not set +# CONFIG_MCORE2 is not set +CONFIG_MCP2120_DONGLE=m +# CONFIG_MCRUSOE is not set +CONFIG_MCS_FIR=m +# CONFIG_MCYRIXIII is not set +CONFIG_MD=y +CONFIG_MDA_CONSOLE=m +CONFIG_MDIO_BITBANG=m +CONFIG_MD_FAULTY=m +CONFIG_MD_LINEAR=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +# CONFIG_MEFFICEON is not set +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_SAS=m +# CONFIG_MEMSTICK is not set +# CONFIG_MEMTEST is not set +# CONFIG_MFD_CORE is not set +CONFIG_MFD_SM501=m +# CONFIG_MFD_SM501_GPIO is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +CONFIG_MICROCODE=m +CONFIG_MICROCODE_OLD_INTERFACE=y +CONFIG_MII=m +CONFIG_MINIX_FS=m +CONFIG_MINIX_SUBPARTITION=y +CONFIG_MISC_DEVICES=y +CONFIG_MISDN=m +CONFIG_MISDN_DSP=m +CONFIG_MISDN_HFCMULTI=m +CONFIG_MISDN_HFCPCI=m +CONFIG_MISDN_L1OIP=m +CONFIG_MIXCOMWD=m +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +CONFIG_MKISS=m +CONFIG_MLX4_CORE=m +CONFIG_MLX4_DEBUG=y +CONFIG_MLX4_INFINIBAND=m +CONFIG_MMC=m +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_RICOH_MMC=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_SDRICOH_CS=m +# CONFIG_MMC_TEST is not set +CONFIG_MMC_TIFM_SD=m +# CONFIG_MMC_UNSAFE_RESUME is not set +CONFIG_MMC_WBSD=m +# CONFIG_MMIOTRACE is not set +CONFIG_MMU=y +CONFIG_MMU_NOTIFIER=y +CONFIG_MM_OWNER=y +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MOUSE_APPLETOUCH=m +# CONFIG_MOUSE_ATIXL is not set +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_GPIO=m +CONFIG_MOUSE_INPORT=m +CONFIG_MOUSE_LOGIBM=m +CONFIG_MOUSE_PC110PAD=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +# CONFIG_MPENTIUM4 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPSC is not set +CONFIG_MSDOS_FS=m +CONFIG_MSDOS_PARTITION=y +CONFIG_MSI_LAPTOP=m +CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" +CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" +CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" +CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" +CONFIG_MT9M001_PCA9536_SWITCH=y +CONFIG_MT9V022_PCA9536_SWITCH=y +CONFIG_MTD=m +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTD_ABSENT=m +CONFIG_MTD_ALAUDA=m +CONFIG_MTD_AMD76XROM=m +CONFIG_MTD_AR7_PARTS=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK2MTD=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_MTD_CFI=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_CHAR=m +CONFIG_MTD_CK804XROM=m +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_CONCAT=m +CONFIG_MTD_DATAFLASH=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_DILNETPC=m +CONFIG_MTD_DILNETPC_BOOTSIZE=0x80000 +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCECC=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCPROBE_ADDRESS=0 +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_ESB2ROM=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_ICHXROM=m +CONFIG_MTD_INTEL_VR_NOR=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_L440GX=m +CONFIG_MTD_M25P80=m +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_CAFE=m +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NETSC520=m +CONFIG_MTD_NETtel=m +CONFIG_MTD_ONENAND=m +CONFIG_MTD_ONENAND_2X_PROGRAM=y +# CONFIG_MTD_ONENAND_OTP is not set +CONFIG_MTD_ONENAND_SIM=m +CONFIG_MTD_ONENAND_VERIFY_WRITE=y +CONFIG_MTD_OOPS=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_PCI=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_PHYSMAP_LEN=0x4000000 +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PLATRAM=m +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +CONFIG_MTD_RAM=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS=m +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +CONFIG_MTD_ROM=m +CONFIG_MTD_SBC_GXX=m +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_SCB2_FLASH=m +CONFIG_MTD_SCx200_DOCFLASH=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_TS5500=m +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_MTD_UBI_GLUEBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTRR=y +CONFIG_MTRR_SANITIZER=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 +CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 +# CONFIG_MVIAC3_2 is not set +# CONFIG_MVIAC7 is not set +CONFIG_MWAVE=m +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MWINCHIPC6 is not set +CONFIG_MYRI10GE=m +CONFIG_N2=m +CONFIG_NAMESPACES=y +CONFIG_NATSEMI=m +CONFIG_NCPFS_EXTRAS=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_PACKET_SIGNING=y +# CONFIG_NCPFS_SMALLDOS is not set +CONFIG_NCPFS_STRONG=y +CONFIG_NCP_FS=m +CONFIG_NDISWRAPPER=m +CONFIG_NE2000=m +CONFIG_NE2K_PCI=m +CONFIG_NE2_MCA=m +CONFIG_NE3210=m +CONFIG_NET=y +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETDEVICES=y +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETLABEL=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NETROM=m +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETXEN_NIC=m +CONFIG_NET_9P=m +# CONFIG_NET_9P_DEBUG is not set +CONFIG_NET_9P_VIRTIO=m +CONFIG_NET_ACT_GACT=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_CLS_BASIC=m +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_CLS_FW=m +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_DCCPPROBE=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_ET131X=m +CONFIG_NET_ETHERNET=y +CONFIG_NET_FC=y +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_NET_IPIP=m +CONFIG_NET_ISA=y +CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_NET_PCI=y +CONFIG_NET_PCMCIA=y +CONFIG_NET_PKTGEN=m +CONFIG_NET_POCKET=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_NET_SB1000=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_FIFO=y +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_TCPPROBE=m +CONFIG_NET_TULIP=y +CONFIG_NET_VENDOR_3COM=y +CONFIG_NET_VENDOR_RACAL=y +CONFIG_NET_VENDOR_SMC=y +CONFIG_NEW_LEDS=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_NF_CONNTRACK_SANE is not set +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_ACCT=y +CONFIG_NF_CT_NETLINK=m +# CONFIG_NF_CT_PROTO_DCCP is not set +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NI52=m +CONFIG_NI65=m +CONFIG_NIU=m +CONFIG_NL80211=y +CONFIG_NLS=y +CONFIG_NLS_ASCII=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +# CONFIG_NOHIGHMEM is not set +CONFIG_NORTEL_HERMES=m +CONFIG_NOZOMI=m +CONFIG_NO_HZ=y +CONFIG_NR_CPUS=64 +CONFIG_NS83820=m +CONFIG_NSC_FIR=m +CONFIG_NSC_GPIO=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_FS=m +# CONFIG_NTFS_RW is not set +CONFIG_NVRAM=m +CONFIG_N_HDLC=m +# CONFIG_OCFS2_DEBUG_FS is not set +CONFIG_OCFS2_DEBUG_MASKLOG=y +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_OLPC=y +CONFIG_OMFS_FS=m +CONFIG_OPROFILE=m +CONFIG_OPTIMIZE_INLINING=y +CONFIG_OSF_PARTITION=y +CONFIG_P54_COMMON=m +CONFIG_P54_PCI=m +CONFIG_P54_USB=m +CONFIG_P80211=m +CONFIG_PACKARDBELL_E5=m +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_CLOCK=y +# CONFIG_PARAVIRT_DEBUG is not set +CONFIG_PARAVIRT_GUEST=y +CONFIG_PARIDE=m +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_EPAT=m +# CONFIG_PARIDE_EPATC8 is not set +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PG=m +CONFIG_PARIDE_PT=m +CONFIG_PARPORT=m +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_AX88796=m +# CONFIG_PARPORT_GSC is not set +CONFIG_PARPORT_NOT_PC=y +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_SERIAL=m +CONFIG_PARTITION_ADVANCED=y +CONFIG_PATA_ACPI=m +CONFIG_PATA_ALI=m +CONFIG_PATA_AMD=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +# CONFIG_PATA_CMD640_PCI is not set +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5520=m +CONFIG_PATA_CS5530=m +CONFIG_PATA_CS5535=m +CONFIG_PATA_CS5536=m +# CONFIG_PATA_CYPRESS is not set +CONFIG_PATA_EFAR=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +# CONFIG_PATA_HPT3X2N is not set +CONFIG_PATA_HPT3X3=m +# CONFIG_PATA_HPT3X3_DMA is not set +# CONFIG_PATA_ISAPNP is not set +CONFIG_PATA_IT8213=m +CONFIG_PATA_IT821X=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_LEGACY=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OLDPIIX=m +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +CONFIG_PATA_PCMCIA=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_PDC_OLD=m +CONFIG_PATA_QDI=m +# CONFIG_PATA_RADISYS is not set +CONFIG_PATA_RZ1000=m +# CONFIG_PATA_SC1200 is not set +CONFIG_PATA_SCH=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_SIL680=m +CONFIG_PATA_SIS=m +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m +CONFIG_PATA_WINBOND_VLB=m +CONFIG_PC300=m +# CONFIG_PC300TOO is not set +# CONFIG_PC300_MLPPP is not set +CONFIG_PC8736x_GPIO=m +CONFIG_PC87413_WDT=m +CONFIG_PCCARD=m +CONFIG_PCCARD_NONSTATIC=m +CONFIG_PCI=y +CONFIG_PCI200SYN=m +CONFIG_PCIEAER=y +# CONFIG_PCIEASPM is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIPCWATCHDOG=m +CONFIG_PCI_ATMEL=m +CONFIG_PCI_BIOS=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_DIRECT=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_GOANY=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GOOLPC is not set +CONFIG_PCI_HERMES=m +CONFIG_PCI_LEGACY=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCI_MSI=y +CONFIG_PCI_OLPC=y +CONFIG_PCMCIA=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_AXNET=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_IBMTR=m +CONFIG_PCMCIA_IOCTL=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_NETWAVE=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_PROBE=y +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_PCMCIA_SYM53C500=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_WL3501=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_PCNET32=m +CONFIG_PCSPKR_PLATFORM=y +CONFIG_PCWATCHDOG=m +CONFIG_PD6729=m +CONFIG_PDA_POWER=m +CONFIG_PDC_ADMA=m +CONFIG_PHANTOM=m +CONFIG_PHONE=m +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m +CONFIG_PHYLIB=m +CONFIG_PHYSICAL_ALIGN=0x100000 +CONFIG_PHYSICAL_START=0x100000 +# CONFIG_PID_NS is not set +CONFIG_PLIP=m +CONFIG_PLIST=y +CONFIG_PLX_HERMES=m +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_PM_DISABLE_CONSOLE=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_TEST_SUSPEND=y +CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y +# CONFIG_PM_VERBOSE is not set +CONFIG_PNP=y +CONFIG_PNPACPI=y +CONFIG_PNPBIOS=y +CONFIG_PNPBIOS_PROC_FS=y +# CONFIG_PNP_DEBUG is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_PPDEV=m +CONFIG_PPP=m +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_SYNC_TTY=m +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_PRINTER=m +CONFIG_PRINTK=y +CONFIG_PRINTK_TIME=y +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_PRISM2_USB=m +CONFIG_PRISM54=m +CONFIG_PROC_EVENTS=y +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_VMCORE=y +CONFIG_PROFILING=y +CONFIG_PROTEON=m +# CONFIG_PROVE_LOCKING is not set +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set +# CONFIG_PSS_HAVE_BOOT is not set +CONFIG_PSS_MIXER=y +CONFIG_QC_USB=m +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QLA3XXX=m +CONFIG_QNX4FS_FS=m +CONFIG_QSEMI_PHY=m +CONFIG_QUOTA=y +CONFIG_QUOTACTL=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_R3964=m +# CONFIG_R6040 is not set +CONFIG_R8169=m +CONFIG_R8169_VLAN=y +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_AZTECH=m +CONFIG_RADIO_CADET=m +CONFIG_RADIO_GEMTEK=m +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAESTRO=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_RTRACK=m +CONFIG_RADIO_RTRACK2=m +CONFIG_RADIO_SF16FMI=m +CONFIG_RADIO_SF16FMR2=m +CONFIG_RADIO_TERRATEC=m +CONFIG_RADIO_TRUST=m +CONFIG_RADIO_TYPHOON=m +CONFIG_RADIO_TYPHOON_PROC_FS=y +CONFIG_RADIO_ZOLTRIX=m +CONFIG_RAID_ATTRS=m +CONFIG_RAW_DRIVER=m +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_REALTEK_PHY is not set +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_REISERFS_FS_XATTR=y +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_RELAY=y +CONFIG_RELOCATABLE=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_RFD_FTL=m +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=m +CONFIG_RFKILL_LEDS=y +CONFIG_RIO=m +# CONFIG_RIO_OLDPCI is not set +CONFIG_RISCOM8=m +CONFIG_ROADRUNNER=m +# CONFIG_ROADRUNNER_LARGE_RINGS is not set +CONFIG_ROCKETPORT=m +CONFIG_ROMFS_FS=m +CONFIG_ROSE=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +CONFIG_RT2400PCI=m +CONFIG_RT2400PCI_LEDS=y +CONFIG_RT2400PCI_RFKILL=y +CONFIG_RT2500PCI=m +CONFIG_RT2500PCI_LEDS=y +CONFIG_RT2500PCI_RFKILL=y +CONFIG_RT2500USB=m +CONFIG_RT2500USB_LEDS=y +CONFIG_RT2X00=m +# CONFIG_RT2X00_DEBUG is not set +CONFIG_RT2X00_LIB=m +# CONFIG_RT2X00_LIB_DEBUGFS is not set +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_LEDS=y +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_RFKILL=y +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT61PCI=m +CONFIG_RT61PCI_LEDS=y +CONFIG_RT61PCI_RFKILL=y +CONFIG_RT73USB=m +CONFIG_RT73USB_LEDS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_DRV_CMOS=y +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +# CONFIG_RTC_DRV_DS1511 is not set +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_M41T80_WDT=y +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_M48T59=m +CONFIG_RTC_DRV_M48T86=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +# CONFIG_RTC_DRV_R9701 is not set +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_S35390A is not set +CONFIG_RTC_DRV_STK17TA8=m +CONFIG_RTC_DRV_TEST=m +CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_LIB=y +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RT_GROUP_SCHED=y +CONFIG_RT_MUTEXES=y +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_RXKAD=m +CONFIG_S2IO=m +# CONFIG_SAMPLES is not set +CONFIG_SATA_AHCI=m +CONFIG_SATA_INIC162X=m +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_SATA_PMP=y +CONFIG_SATA_PROMISE=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIL24=m +CONFIG_SATA_SIS=m +CONFIG_SATA_SVW=m +CONFIG_SATA_SX4=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m +CONFIG_SBC7240_WDT=m +CONFIG_SBC8360_WDT=m +CONFIG_SBC_EPX_C3_WATCHDOG=m +CONFIG_SBNI=m +# CONFIG_SBNI_MULTILINE is not set +CONFIG_SC1200_WDT=m +CONFIG_SC520_WDT=m +CONFIG_SC6600=y +CONFIG_SC6600_CDROM=4 +CONFIG_SC6600_CDROMBASE=0 +CONFIG_SC6600_JOY=y +CONFIG_SC92031=m +CONFIG_SCC=m +# CONFIG_SCC_DELAY is not set +# CONFIG_SCC_TRXECHO is not set +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_HRTICK=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_SMT=y +# CONFIG_SCHED_TRACER is not set +CONFIG_SCSI=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_7000FASST=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AHA1740=m +CONFIG_SCSI_AIC79XX=m +CONFIG_SCSI_AIC7XXX=m +# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_AIC94XX=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ARCMSR_AER=y +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_DC390T=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_DH=m +CONFIG_SCSI_DH_ALUA=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DMA=y +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_DTC3280=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_LINKED_COMMANDS=y +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_FC_TGT_ATTRS=y +CONFIG_SCSI_FD_MCS=m +# CONFIG_SCSI_FLASHPOINT is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_GENERIC_NCR5380=m +CONFIG_SCSI_GENERIC_NCR5380_MMIO=m +CONFIG_SCSI_GENERIC_NCR53C400=y +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_IBMMCA=m +CONFIG_SCSI_IMM=m +CONFIG_SCSI_IN2000=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_IPR=m +# CONFIG_SCSI_IPR_DUMP is not set +# CONFIG_SCSI_IPR_TRACE is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_ISCSITARGET=m +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_LOWLEVEL=y +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_MVSAS is not set +CONFIG_SCSI_NCR53C406A=m +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 +CONFIG_SCSI_NCR53C8XX_SYNC=5 +CONFIG_SCSI_NCR_D700=m +CONFIG_SCSI_NCR_Q720=m +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_NSP32=m +CONFIG_SCSI_PAS16=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_PROC_FS=y +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLOGIC_FAS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SAS_LIBSAS=m +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_SIM710=m +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SRP=m +CONFIG_SCSI_SRP_ATTRS=m +CONFIG_SCSI_SRP_TGT_ATTRS=y +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C416=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_T128=m +CONFIG_SCSI_TGT=m +CONFIG_SCSI_U14_34F=m +CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y +CONFIG_SCSI_U14_34F_MAX_TAGS=8 +CONFIG_SCSI_U14_34F_TAGGED_QUEUE=y +CONFIG_SCSI_ULTRASTOR=m +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCx200=m +CONFIG_SCx200HR_TIMER=m +CONFIG_SCx200_ACB=m +CONFIG_SCx200_GPIO=m +CONFIG_SCx200_I2C=m +CONFIG_SCx200_I2C_SCL=12 +CONFIG_SCx200_I2C_SDA=13 +CONFIG_SCx200_WDT=m +CONFIG_SDIO_UART=m +CONFIG_SDLA=m +CONFIG_SEALEVEL_4021=m +CONFIG_SECCOMP=y +CONFIG_SECURITY=y +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_APPARMOR_DISABLE=y +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_SECURITY_FILE_CAPABILITIES=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_DISABLE=y +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +CONFIG_SECURITY_SMACK=y +CONFIG_SEEQ8005=m +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ABITUGURU3=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7473=m +CONFIG_SENSORS_APPLESMC=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCHMD=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_HDAPS=m +CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_K8TEMP=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MAX6875=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TSL2550=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_ACCENT=m +CONFIG_SERIAL_8250_BOCA=m +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_CS=m +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_EXAR_ST16C554=m +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FOURPORT=m +CONFIG_SERIAL_8250_HUB6=m +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_MCA=m +CONFIG_SERIAL_8250_NR_UARTS=48 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_SERIO=y +CONFIG_SERIO_CT82C710=m +CONFIG_SERIO_I8042=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_PARKBD=m +CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_RAW=m +CONFIG_SERIO_SERPORT=m +CONFIG_SFC=m +CONFIG_SGI_IOC4=m +CONFIG_SGI_PARTITION=y +CONFIG_SHMEM=y +CONFIG_SIGMATEL_FIR=m +CONFIG_SIGNALFD=y +CONFIG_SIS190=m +CONFIG_SIS900=m +CONFIG_SKFP=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKISA=m +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +# CONFIG_SLAB is not set +CONFIG_SLABINFO=y +CONFIG_SLHC=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_SLIP_SMART=y +# CONFIG_SLOB is not set +CONFIG_SLUB=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_SMC9194=m +CONFIG_SMCTR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_SMP=y +CONFIG_SMSC37B787_WDT=m +CONFIG_SMSC_PHY=m +CONFIG_SND=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_AD1816A=m +CONFIG_SND_AD1848=m +CONFIG_SND_AD1848_LIB=m +CONFIG_SND_AD1889=m +CONFIG_SND_ADLIB=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ALS100=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AW2=m +CONFIG_SND_AZT2320=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_BTSCO=m +CONFIG_SND_CA0106=m +CONFIG_SND_CMI8330=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4231=m +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_CS4232=m +CONFIG_SND_CS4236=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5530=m +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_DARLA24=m +# CONFIG_SND_DEBUG is not set +CONFIG_SND_DRIVERS=y +CONFIG_SND_DT019X=m +CONFIG_SND_DUMMY=m +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_ECHO3G=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1688=m +CONFIG_SND_ES18XX=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_ES968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_GINA20=m +CONFIG_SND_GINA24=m +CONFIG_SND_GUSCLASSIC=m +CONFIG_SND_GUSEXTREME=m +CONFIG_SND_GUSMAX=m +CONFIG_SND_HDA_CODEC_ANALOG=y +CONFIG_SND_HDA_CODEC_ATIHDMI=y +CONFIG_SND_HDA_CODEC_CMEDIA=y +CONFIG_SND_HDA_CODEC_CONEXANT=y +CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_CODEC_SI3054=y +CONFIG_SND_HDA_CODEC_SIGMATEL=y +CONFIG_SND_HDA_CODEC_VIA=y +CONFIG_SND_HDA_GENERIC=y +# CONFIG_SND_HDA_HWDEP is not set +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_POWER_SAVE=y +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_HIFIER=m +CONFIG_SND_HWDEP=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_INTERWAVE=m +CONFIG_SND_INTERWAVE_STB=m +CONFIG_SND_ISA=y +CONFIG_SND_KORG1212=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIA=m +CONFIG_SND_MIRO=m +CONFIG_SND_MIXART=m +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_MONA=m +CONFIG_SND_MPU401=m +CONFIG_SND_MPU401_UART=m +CONFIG_SND_MTPAV=m +CONFIG_SND_MTS64=m +CONFIG_SND_NM256=m +CONFIG_SND_OPL3SA2=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_OPTI92X_AD1848=m +CONFIG_SND_OPTI92X_CS4231=m +CONFIG_SND_OPTI93X=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_OXYGEN=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_PCI=y +CONFIG_SND_PCM=m +CONFIG_SND_PCMCIA=y +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_PCSP=m +CONFIG_SND_PCXHR=m +CONFIG_SND_PDAUDIOCF=m +CONFIG_SND_PORTMAN2X4=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SB16=m +CONFIG_SND_SB16_CSP=y +CONFIG_SND_SB16_DSP=m +CONFIG_SND_SB8=m +CONFIG_SND_SB8_DSP=m +CONFIG_SND_SBAWE=m +CONFIG_SND_SB_COMMON=m +CONFIG_SND_SC6000=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_SGALAXY=m +CONFIG_SND_SIS7019=m +CONFIG_SND_SOC=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_SPI=y +CONFIG_SND_SSCAPE=m +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_TIMER=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_USX2Y=m +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VMASTER=y +CONFIG_SND_VX222=m +CONFIG_SND_VXPOCKET=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_WAVEFRONT=m +CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL=y +CONFIG_SND_YMFPCI=m +CONFIG_SOC_CAMERA=m +CONFIG_SOC_CAMERA_MT9M001=m +CONFIG_SOC_CAMERA_MT9V022=m +CONFIG_SOC_CAMERA_PLATFORM=m +CONFIG_SOFT_WATCHDOG=m +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_SONYPI=m +CONFIG_SONYPI_COMPAT=y +CONFIG_SONY_LAPTOP=m +CONFIG_SOUND=m +CONFIG_SOUND_AEDSP16=m +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_KAHLUA=m +CONFIG_SOUND_MPU401=m +CONFIG_SOUND_MSNDCLAS=m +CONFIG_SOUND_MSNDPIN=m +CONFIG_SOUND_MSS=m +CONFIG_SOUND_OSS=m +CONFIG_SOUND_PAS=m +CONFIG_SOUND_PRIME=m +CONFIG_SOUND_PSS=m +CONFIG_SOUND_SB=m +CONFIG_SOUND_SSCAPE=m +# CONFIG_SOUND_TRACEINIT is not set +CONFIG_SOUND_TRIX=m +CONFIG_SOUND_UART6850=m +CONFIG_SOUND_VMIDI=m +CONFIG_SOUND_YM3812=m +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_SPARSEMEM_STATIC=y +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_SPECIALIX=m +CONFIG_SPI=y +CONFIG_SPI_AT25=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_LM70_LLP=m +CONFIG_SPI_MASTER=y +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_TLE62X0=m +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +CONFIG_SSB=m +CONFIG_SSB_B43_PCI_BRIDGE=y +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +# CONFIG_SSB_PCMCIAHOST is not set +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_POSSIBLE=y +CONFIG_SSB_SPROM=y +CONFIG_SSFDC=m +CONFIG_STACKTRACE=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_STALDRV=y +# CONFIG_STANDALONE is not set +CONFIG_STOP_MACHINE=y +CONFIG_STP=m +CONFIG_STRICT_DEVMEM=y +CONFIG_STRIP=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_SUNGEM=m +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_SUN_PARTITION=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SWAP=y +CONFIG_SX=m +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_CS=m +CONFIG_SYNCLINK_GT=m +CONFIG_SYN_COOKIES=y +CONFIG_SYSCTL=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_SYSFS=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_SYSPROF_TRACER is not set +CONFIG_SYSV68_PARTITION=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYSV_FS=m +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_TASKSTATS=y +# CONFIG_TASK_DELAY_ACCT is not set +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_TASK_XACCT=y +CONFIG_TC1100_WMI=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_NSC=m +CONFIG_TCG_TIS=m +CONFIG_TCG_TPM=m +CONFIG_TCIC=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_MD5SIG=y +CONFIG_TEHUTI=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TELCLOCK=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_TEXTSEARCH_KMP=m +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THINKPAD_ACPI=m +CONFIG_THINKPAD_ACPI_BAY=y +# CONFIG_THINKPAD_ACPI_DEBUG is not set +CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y +CONFIG_THINKPAD_ACPI_VIDEO=y +CONFIG_TICK_ONESHOT=y +CONFIG_TIFM_7XX1=m +CONFIG_TIFM_CORE=m +CONFIG_TIGON3=m +CONFIG_TIMERFD=y +CONFIG_TIMER_STATS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_TLAN=m +CONFIG_TLSF=m +# CONFIG_TLSF_DEBUG is not set +# CONFIG_TLSF_STATS is not set +CONFIG_TLSUP=m +CONFIG_TMD_HERMES=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +# CONFIG_TOIM3232_DONGLE is not set +# CONFIG_TOSHIBA is not set +CONFIG_TOSHIBA_FIR=m +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_HTCPEN=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_UCB1400=m +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_WM9705=y +CONFIG_TOUCHSCREEN_WM9712=y +CONFIG_TOUCHSCREEN_WM9713=y +CONFIG_TOUCHSCREEN_WM97XX=m +CONFIG_TPS65010=m +CONFIG_TP_SMAPI=m +CONFIG_TP_SMAPI_EC=m +CONFIG_TR=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_TRACING=y +CONFIG_TTPCI_EEPROM=m +CONFIG_TULIP=m +# CONFIG_TULIP_MMIO is not set +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_NAPI is not set +CONFIG_TUN=m +CONFIG_TUNER_3036=m +CONFIG_TYPHOON=m +CONFIG_UBIFS_FS=m +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_UFS_DEBUG is not set +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +CONFIG_UID16=y +CONFIG_UIO=m +CONFIG_UIO_CIF=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_UIO_SMX=m +CONFIG_ULI526X=m +CONFIG_ULTRA=m +CONFIG_ULTRA32=m +CONFIG_ULTRAMCA=m +CONFIG_ULTRIX_PARTITION=y +CONFIG_UNIX=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_USB=m +CONFIG_USBPCWATCHDOG=m +CONFIG_USB_ACM=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_APPLEIR=m +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_ATM=m +CONFIG_USB_BELKIN=y +CONFIG_USB_BERRY_CHARGE=m +CONFIG_USB_C67X00_HCD=m +CONFIG_USB_CATC=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_CXACRU=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_DSBR=m +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EMI26=m +CONFIG_USB_EMI62=m +CONFIG_USB_EPSON2888=y +CONFIG_USB_ET61X251=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_EZUSB=y +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_GADGET=m +CONFIG_USB_GADGETFS=m +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +CONFIG_USB_GADGET_NET2280=y +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_G_PRINTER is not set +CONFIG_USB_G_SERIAL=m +CONFIG_USB_HID=m +CONFIG_USB_HIDDEV=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_USB_HSO=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_IRDA=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_ISP1760_HCD=m +# CONFIG_USB_ISP1760_PCI is not set +CONFIG_USB_KAWETH=m +CONFIG_USB_KBD=m +CONFIG_USB_KC2190=y +CONFIG_USB_KONICAWC=m +CONFIG_USB_LCD=m +CONFIG_USB_LD=m +CONFIG_USB_LED=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LIBUSUAL=y +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +# CONFIG_USB_MIDI_GADGET is not set +CONFIG_USB_MON=y +CONFIG_USB_MOUSE=m +CONFIG_USB_NET2280=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_HCD_SSB is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OV511 is not set +CONFIG_USB_OV511_NEW=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_PHIDGET=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETMOTORCONTROL=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_PRINTER=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_R8A66597_HCD=m +CONFIG_USB_RIO500=m +CONFIG_USB_RTL8150=m +CONFIG_USB_S2255=m +CONFIG_USB_SE401=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IPW=m +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_IUU is not set +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SI470X=m +CONFIG_USB_SISUSBVGA=m +# CONFIG_USB_SISUSBVGA_CON is not set +CONFIG_USB_SL811_CS=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SN9C102=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE_ALAUDA=y +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_STORAGE_DATAFAB=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_KARMA=y +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STV680=m +CONFIG_USB_SUPPORT=y +CONFIG_USB_SUSPEND=y +# CONFIG_USB_TEST is not set +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_U132_HCD=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_USBNET=m +CONFIG_USB_USS720=m +CONFIG_USB_VICAM=m +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_W9968CF=m +CONFIG_USB_WDM=m +CONFIG_USB_XUSBATM=m +CONFIG_USB_ZC0301=m +CONFIG_USB_ZD1201=m +CONFIG_USB_ZERO=m +CONFIG_USB_ZR364XX=m +# CONFIG_USER_NS is not set +# CONFIG_USER_SCHED is not set +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_UTS_NS=y +CONFIG_V4L_USB_DRIVERS=y +CONFIG_VERSION_SIGNATURE="" +CONFIG_VETH=m +CONFIG_VFAT_FS=m +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_VGASTATE=m +CONFIG_VGA_CONSOLE=y +CONFIG_VIA_FIR=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_VELOCITY=m +CONFIG_VIDEOBUF_DMA_CONTIG=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +# CONFIG_VIDEO_ADV_DEBUG is not set +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CAFE_CCIC=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX23885=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_MEDIA=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_VIDEO_PMS=m +CONFIG_VIDEO_PVRUSB2=m +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_PVRUSB2_DVB=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA7111=m +CONFIG_VIDEO_SAA7114=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_SELECT=y +CONFIG_VIDEO_SH_MOBILE_CEU=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TDA9875=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_VIVI=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_VPX3220=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_ZR36060=m +CONFIG_VIRTIO=m +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_BLK=m +CONFIG_VIRTIO_CONSOLE=m +CONFIG_VIRTIO_NET=m +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_RING=m +CONFIG_VIRTUALIZATION=y +CONFIG_VIRT_TO_BUS=y +CONFIG_VITESSE_PHY=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLSI_FIR=m +CONFIG_VM86=y +CONFIG_VMI=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VORTEX=m +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_VXFS_FS=m +CONFIG_W1=m +CONFIG_W1_CON=y +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W83627HF_WDT=m +CONFIG_W83697HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_WAFER_WDT=m +CONFIG_WAN=y +CONFIG_WANXL=m +CONFIG_WAN_ROUTER=m +CONFIG_WAN_ROUTER_DRIVERS=m +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WAVELAN=m +CONFIG_WD80x3=m +CONFIG_WDT=m +CONFIG_WDTPCI=m +CONFIG_WDT_501=y +CONFIG_WDT_501_PCI=y +CONFIG_WINBOND_840=m +CONFIG_WINBOND_FIR=m +CONFIG_WIRELESS_ACX=m +CONFIG_WIRELESS_AT76=m +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_WLAN_80211=y +CONFIG_WLAN_PRE80211=y +CONFIG_X25=m +CONFIG_X25_ASY=m +CONFIG_X86=y +CONFIG_X86_32=y +CONFIG_X86_32_SMP=y +# CONFIG_X86_64 is not set +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +CONFIG_X86_APM_BOOT=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_BSWAP=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_CPU=y +CONFIG_X86_CPUFREQ_NFORCE2=m +CONFIG_X86_CPUID=m +# CONFIG_X86_ELAN is not set +# CONFIG_X86_E_POWERSAVER is not set +CONFIG_X86_FIND_SMP_CONFIG=y +CONFIG_X86_GENERIC=y +# CONFIG_X86_GENERICARCH is not set +CONFIG_X86_GX_SUSPMOD=m +CONFIG_X86_HT=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_INVLPG=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_LONGHAUL=m +CONFIG_X86_LONGRUN=m +# CONFIG_X86_MCE is not set +CONFIG_X86_MINIMUM_CPU_FAMILY=4 +CONFIG_X86_MPPARSE=y +CONFIG_X86_MSR=m +CONFIG_X86_P4_CLOCKMOD=m +# CONFIG_X86_PAT is not set +CONFIG_X86_PC=y +CONFIG_X86_PM_TIMER=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_POWERNOW_K6=m +CONFIG_X86_POWERNOW_K7=m +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_POWERNOW_K8_ACPI=y +CONFIG_X86_PPRO_FENCE=y +# CONFIG_X86_PTDUMP is not set +# CONFIG_X86_RDC321X is not set +CONFIG_X86_REBOOTFIXUPS=y +CONFIG_X86_RESERVE_LOW_64K=y +CONFIG_X86_SMP=y +CONFIG_X86_SPEEDSTEP_CENTRINO=m +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y +CONFIG_X86_SPEEDSTEP_ICH=m +CONFIG_X86_SPEEDSTEP_LIB=m +CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y +CONFIG_X86_SPEEDSTEP_SMI=m +CONFIG_X86_TRAMPOLINE=y +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_VSMP is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_XADD=y +CONFIG_XEN_SAVE_RESTORE=y +CONFIG_XFRM=y +CONFIG_XFRM_IPCOMP=m +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_USER=m +# CONFIG_XFS_DEBUG is not set +CONFIG_XFS_FS=m +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_RT=y +CONFIG_XOR_BLOCKS=m +CONFIG_YAM=m +CONFIG_YELLOWFIN=m +CONFIG_YENTA=m +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_ZISOFS=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZNET=m +CONFIG_ZONE_DMA=y +# CONFIG_ZONE_DMA32 is not set +CONFIG_ZONE_DMA_FLAG=1 --- linux-2.6.27.orig/scripts/package/mkspec +++ linux-2.6.27/scripts/package/mkspec @@ -64,8 +64,10 @@ echo "%install" echo "%ifarch ia64" echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib/modules' +echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware' echo "%else" echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib/modules' +echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware' echo "%endif" echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install' @@ -92,5 +94,6 @@ echo '%defattr (-, root, root)' echo "%dir /lib/modules" echo "/lib/modules/$KERNELRELEASE" +echo "/lib/firmware" echo "/boot/*" echo "" --- linux-2.6.27.orig/patches/0005-UBUNTU-SAUCE-Support-for-Poulsbo-I2C-smbus.patch +++ linux-2.6.27/patches/0005-UBUNTU-SAUCE-Support-for-Poulsbo-I2C-smbus.patch @@ -0,0 +1,447 @@ +From 4cc3cb0f7b7a47a2374d8e855b3a0bee5006cc01 Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Tue, 15 Jul 2008 13:17:25 +0300 +Subject: [PATCH] UBUNTU: SAUCE: Support for Poulsbo I2C smbus + +Signed-off-by: Amit Kucheria +--- + drivers/i2c/busses/Kconfig | 9 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-sch.c | 393 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 403 insertions(+), 0 deletions(-) + create mode 100644 drivers/i2c/busses/i2c-sch.c + +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 48438cc..d3d2e22 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -247,6 +247,15 @@ config I2C_PIIX4 + This driver can also be built as a module. If so, the module + will be called i2c-piix4. + ++config I2C_POULSBO ++ tristate "Intel SCH (Poulsbo SMBUS 1.0)" ++ depends on I2C && PCI ++ help ++ If you say yes to this option, support will be included for the Intel ++ SCH ++ Intel POULSBO ++ will be called i2c-sch. ++ + config I2C_IBM_IIC + tristate "IBM PPC 4xx on-chip I2C interface" + depends on 4xx +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index e8c882a..6a13052 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -33,6 +33,7 @@ obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o + obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o + obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o + obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o ++obj-$(CONFIG_I2C_POULSBO) += i2c-sch.o + obj-$(CONFIG_I2C_PNX) += i2c-pnx.o + obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o +diff --git a/drivers/i2c/busses/i2c-sch.c b/drivers/i2c/busses/i2c-sch.c +new file mode 100644 +index 0000000..8940362 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-sch.c +@@ -0,0 +1,393 @@ ++/* ++ i2c-sch.c - Part of lm_sensors, Linux kernel modules for hardware ++ monitoring ++ Based on piix4.c ++ Copyright (c) 1998 - 2002 Frodo Looijaard and ++ Philip Edelbrock ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++/* ++ Supports: ++ Intel POULSBO ++ ++ Note: we assume there can only be one device, with one SMBus interface. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++struct sd { ++ const unsigned short mfr; ++ const unsigned short dev; ++ const unsigned char fn; ++ const char *name; ++}; ++/* POULSBO SMBus address offsets */ ++#define SMBHSTCNT (0 + poulsbo_smba) ++#define SMBHSTSTS (1 + poulsbo_smba) ++#define SMBHSTADD (4 + poulsbo_smba) /* TSA */ ++#define SMBHSTCMD (5 + poulsbo_smba) ++#define SMBHSTDAT0 (6 + poulsbo_smba) ++#define SMBHSTDAT1 (7 + poulsbo_smba) ++#define SMBBLKDAT (0x20 + poulsbo_smba) ++ ++ ++/* count for request_region */ ++#define SMBIOSIZE 8 ++ ++/* PCI Address Constants */ ++#define SMBBA_SCH 0x040 ++ ++/* Other settings */ ++#define MAX_TIMEOUT 500 ++#define ENABLE_INT9 0 ++ ++/* POULSBO constants */ ++#define POULSBO_QUICK 0x00 ++#define POULSBO_BYTE 0x01 ++#define POULSBO_BYTE_DATA 0x02 ++#define POULSBO_WORD_DATA 0x03 ++#define POULSBO_BLOCK_DATA 0x05 ++ ++/* insmod parameters */ ++ ++/* If force is set to anything different from 0, we forcibly enable the ++ POULSBO. DANGEROUS! */ ++static int force; ++module_param (force, int, 0); ++MODULE_PARM_DESC(force, "Forcibly enable the POULSBO. DANGEROUS!"); ++ ++ ++static int poulsbo_transaction(void); ++ ++static unsigned short poulsbo_smba; ++static struct pci_driver poulsbo_driver; ++static struct i2c_adapter poulsbo_adapter; ++ ++ ++static int __devinit poulsbo_setup(struct pci_dev *POULSBO_dev, ++ const struct pci_device_id *id) ++{ ++ unsigned short smbase; ++ if(POULSBO_dev->device != PCI_DEVICE_ID_INTEL_POULSBO_LPC) { ++ /* match up the function */ ++ if (PCI_FUNC(POULSBO_dev->devfn) != id->driver_data) ++ return -ENODEV; ++ dev_info(&POULSBO_dev->dev, "Found %s device\n", pci_name(POULSBO_dev)); ++ } else { ++ dev_info(&POULSBO_dev->dev, "Found POULSBO SMBUS %s device\n", pci_name(POULSBO_dev)); ++ /* find SMBUS base address */ ++ pci_read_config_word(POULSBO_dev, 0x40, &smbase); ++ dev_info(&POULSBO_dev->dev, "POULSBO SM base = 0x%04x\n", smbase); ++ } ++ ++ ++ /* Determine the address of the SMBus areas */ ++ if(POULSBO_dev->device == PCI_DEVICE_ID_INTEL_POULSBO_LPC) ++ pci_read_config_word(POULSBO_dev, SMBBA_SCH, &poulsbo_smba); ++ else ++ poulsbo_smba=0; ++ ++ poulsbo_smba &= 0xfff0; ++ if(poulsbo_smba == 0) { ++ dev_err(&POULSBO_dev->dev, "SMB base address " ++ "uninitialized - upgrade BIOS or use " ++ "force_addr=0xaddr\n"); ++ return -ENODEV; ++ } ++ ++ if (!request_region(poulsbo_smba, SMBIOSIZE, poulsbo_driver.name)) { ++ dev_err(&POULSBO_dev->dev, "SMB region 0x%x already in use!\n", ++ poulsbo_smba); ++ return -ENODEV; ++ } ++ ++ dev_dbg(&POULSBO_dev->dev, "SMBA = 0x%X\n", poulsbo_smba); ++ ++ return 0; ++} ++ ++/* Another internally used function */ ++static int poulsbo_transaction(void) ++{ ++ int temp; ++ int result = 0; ++ int timeout = 0; ++ ++ dev_dbg(&poulsbo_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " ++ "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), ++ inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), ++ inb_p(SMBHSTDAT1)); ++ ++ /* Make sure the SMBus host is ready to start transmitting */ ++ if ((temp = inb_p(SMBHSTSTS)) != 0x00) { ++ if(temp == 1) { ++ dev_dbg(&poulsbo_adapter.dev, "Completion (%02x). " ++ "clear...\n", temp); ++ outb_p(temp, SMBHSTSTS); ++ ++ } else if(temp & 0xe) { ++ dev_dbg(&poulsbo_adapter.dev, "SMBus error (%02x). " ++ "Resetting...\n", temp); ++ outb_p(temp, SMBHSTSTS); ++ } ++ if ((temp = inb_p(SMBHSTSTS)) != 0x00) { ++ dev_err(&poulsbo_adapter.dev, "Failed! (%02x)\n", temp); ++ return -1; ++ } else { ++ dev_dbg(&poulsbo_adapter.dev, "Successfull!\n"); ++ } ++ } ++ ++ /* start the transaction by setting bit 4 */ ++ outb_p(inb(SMBHSTCNT) | 0x10, SMBHSTCNT); ++ ++ /* We will always wait for a fraction of a second! (See POULSBO docs errata) */ ++ do { ++ msleep(1); ++ temp = inb_p(SMBHSTSTS); ++ } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT)); ++ ++ /* If the SMBus is still busy, we give up */ ++ if (timeout >= MAX_TIMEOUT) { ++ dev_err(&poulsbo_adapter.dev, "SMBus Timeout!\n"); ++ result = -1; ++ } ++ ++ if (temp & 0x10) { ++ result = -1; ++ dev_err(&poulsbo_adapter.dev, "Error: Failed bus transaction\n"); ++ } ++ ++ if (temp & 0x08) { ++ result = -1; ++ dev_dbg(&poulsbo_adapter.dev, "Bus collision! SMBus may be " ++ "locked until next hard reset. (sorry!)\n"); ++ /* Clock stops and slave is stuck in mid-transmission */ ++ } ++ ++ if (temp & 0x04) { ++ result = -1; ++ dev_dbg(&poulsbo_adapter.dev, "Error: no response!\n"); ++ } ++ if ((temp = inb_p(SMBHSTSTS)) != 0x00) { ++ if( temp == 0x1) { ++ dev_dbg(&poulsbo_adapter.dev, "post complete!\n"); ++ outb_p(temp, SMBHSTSTS); ++ } ++ else if(temp & 0xe) { ++ dev_dbg(&poulsbo_adapter.dev, "Error: bus, etc!\n"); ++ outb_p(inb(SMBHSTSTS), SMBHSTSTS); ++ } ++ } ++ msleep(1); ++ if ((temp = inb_p(SMBHSTSTS)) & 0xe) { ++ /* BSY, device or bus error */ ++ dev_err(&poulsbo_adapter.dev, "Failed reset at end of " ++ "transaction (%02x), Bus error\n", temp); ++ } ++ dev_dbg(&poulsbo_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " ++ "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), ++ inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), ++ inb_p(SMBHSTDAT1)); ++ return result; ++} ++ ++/* Return -1 on error. */ ++static s32 poulsbo_access(struct i2c_adapter * adap, u16 addr, ++ unsigned short flags, char read_write, ++ u8 command, int size, union i2c_smbus_data * data) ++{ ++ int i, len; ++ dev_dbg(&poulsbo_adapter.dev,"access size: %d %s\n", size, (read_write)?"READ":"WRITE"); ++ switch (size) { ++ case I2C_SMBUS_PROC_CALL: ++ dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); ++ return -1; ++ case I2C_SMBUS_QUICK: ++ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), ++ SMBHSTADD); ++ size = POULSBO_QUICK; ++ break; ++ case I2C_SMBUS_BYTE: ++ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), ++ SMBHSTADD); ++ if (read_write == I2C_SMBUS_WRITE) ++ outb_p(command, SMBHSTCMD); ++ size = POULSBO_BYTE; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), ++ SMBHSTADD); ++ outb_p(command, SMBHSTCMD); ++ if (read_write == I2C_SMBUS_WRITE) ++ outb_p(data->byte, SMBHSTDAT0); ++ size = POULSBO_BYTE_DATA; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), ++ SMBHSTADD); ++ outb_p(command, SMBHSTCMD); ++ if (read_write == I2C_SMBUS_WRITE) { ++ outb_p(data->word & 0xff, SMBHSTDAT0); ++ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); ++ } ++ size = POULSBO_WORD_DATA; ++ break; ++ case I2C_SMBUS_BLOCK_DATA: ++ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), ++ SMBHSTADD); ++ outb_p(command, SMBHSTCMD); ++ if (read_write == I2C_SMBUS_WRITE) { ++ len = data->block[0]; ++ if (len < 0) ++ len = 0; ++ if (len > 32) ++ len = 32; ++ outb_p(len, SMBHSTDAT0); ++ i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ ++ for (i = 1; i <= len; i++) ++ outb_p(data->block[i], SMBBLKDAT); ++ } ++ size = POULSBO_BLOCK_DATA; ++ break; ++ } ++ dev_dbg(&poulsbo_adapter.dev,"write size %d to 0x%04x\n", size, SMBHSTCNT); ++ outb_p((size & 0x7), SMBHSTCNT); ++ ++ if (poulsbo_transaction()) /* Error in transaction */ ++ return -1; ++ ++ if ((read_write == I2C_SMBUS_WRITE) || (size == POULSBO_QUICK)) ++ return 0; ++ ++ ++ switch (size) { ++ case POULSBO_BYTE: /* Where is the result put? I assume here it is in ++ SMBHSTDAT0 but it might just as well be in the ++ SMBHSTCMD. No clue in the docs */ ++ ++ data->byte = inb_p(SMBHSTDAT0); ++ break; ++ case POULSBO_BYTE_DATA: ++ data->byte = inb_p(SMBHSTDAT0); ++ break; ++ case POULSBO_WORD_DATA: ++ data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); ++ break; ++ case POULSBO_BLOCK_DATA: ++ data->block[0] = inb_p(SMBHSTDAT0); ++ i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ ++ for (i = 1; i <= data->block[0]; i++) ++ data->block[i] = inb_p(SMBBLKDAT); ++ break; ++ } ++ return 0; ++} ++ ++static u32 poulsbo_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | ++ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_BLOCK_DATA; ++} ++ ++static const struct i2c_algorithm smbus_algorithm = { ++ .smbus_xfer = poulsbo_access, ++ .functionality = poulsbo_func, ++}; ++ ++static struct i2c_adapter poulsbo_adapter = { ++ .owner = THIS_MODULE, ++ .class = I2C_CLASS_HWMON, ++ .algo = &smbus_algorithm, ++}; ++ ++static struct pci_device_id poulsbo_ids[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_POULSBO_LPC), ++ .driver_data = 0xf8 }, ++ { 0, } ++}; ++ ++MODULE_DEVICE_TABLE (pci, poulsbo_ids); ++ ++static int __devinit poulsbo_probe(struct pci_dev *dev, ++ const struct pci_device_id *id) ++{ ++ int retval; ++ retval = poulsbo_setup(dev, id); ++ if (retval) ++ return retval; ++ ++ /* set up the driverfs linkage to our parent device */ ++ poulsbo_adapter.dev.parent = &dev->dev; ++ ++ snprintf(poulsbo_adapter.name, I2C_NAME_SIZE, ++ "SMBus POULSBO adapter at %04x", poulsbo_smba); ++ ++ if ((retval = i2c_add_adapter(&poulsbo_adapter))) { ++ dev_err(&dev->dev, "Couldn't register adapter!\n"); ++ release_region(poulsbo_smba, SMBIOSIZE); ++ poulsbo_smba = 0; ++ } ++ ++ return retval; ++} ++ ++static void __devexit poulsbo_remove(struct pci_dev *dev) ++{ ++ if (poulsbo_smba) { ++ i2c_del_adapter(&poulsbo_adapter); ++ release_region(poulsbo_smba, SMBIOSIZE); ++ poulsbo_smba = 0; ++ } ++} ++ ++static struct pci_driver poulsbo_driver = { ++ .name = "poulsbo_smbus", ++ .id_table = poulsbo_ids, ++ .probe = poulsbo_probe, ++ .remove = __devexit_p(poulsbo_remove), ++}; ++ ++static int __init i2c_poulsbo_init(void) ++{ ++ return pci_register_driver(&poulsbo_driver); ++} ++ ++static void __exit i2c_poulsbo_exit(void) ++{ ++ pci_unregister_driver(&poulsbo_driver); ++} ++ ++MODULE_AUTHOR("Jacob Pan "); ++MODULE_DESCRIPTION("POULSBO SMBus driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(i2c_poulsbo_init); ++module_exit(i2c_poulsbo_exit); +-- +1.5.4.3 + --- linux-2.6.27.orig/patches/0001-UBUNTU-SAUCE-Start-new-release.patch +++ linux-2.6.27/patches/0001-UBUNTU-SAUCE-Start-new-release.patch @@ -0,0 +1,29 @@ +From f28d8b8f6949a8dfbe0c0bcbed2918441916c4aa Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Thu, 24 Jul 2008 21:47:02 +0000 +Subject: [PATCH] UBUNTU: SAUCE: Start new release + +Signed-off-by: Amit Kucheria +--- + debian/changelog | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/debian/changelog b/debian/changelog +index 33f25e1..0419fae 100644 +--- a/debian/changelog ++++ b/debian/changelog +@@ -1,3 +1,11 @@ ++linux-lpia (2.6.26-1.1) UNRELEASED; urgency=low ++ ++ CHANGELOG: Do not edit directly. Autogenerated at release. ++ CHANGELOG: Use the printchanges target to see the curent changes. ++ CHANGELOG: Use the insertchanges target to create the final log. ++ ++ -- Amit Kucheria Thu, 24 Jul 2008 21:46:14 +0000 ++ + linux-lpia (2.6.26-1.0) UNRELEASED; urgency=low + + * Initial release. +-- +1.5.4.3 + --- linux-2.6.27.orig/patches/0002-UBUNTU-SAUCE-Script-to-automate-rebase-to-Ubuntu-I.patch +++ linux-2.6.27/patches/0002-UBUNTU-SAUCE-Script-to-automate-rebase-to-Ubuntu-I.patch @@ -0,0 +1,128 @@ +From 1b3d2fdc23aebcceebef33bd8d4000387cdc7cfc Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Mon, 14 Jul 2008 17:41:17 +0300 +Subject: [PATCH] UBUNTU: SAUCE: Script to automate rebase to Ubuntu Intrepid Kernel git tree + +Signed-off-by: Amit Kucheria +--- + debian/scripts/misc/rebase-intrepid | 108 +++++++++++++++++++++++++++++++++++ + 1 files changed, 108 insertions(+), 0 deletions(-) + create mode 100755 debian/scripts/misc/rebase-intrepid + +diff --git a/debian/scripts/misc/rebase-intrepid b/debian/scripts/misc/rebase-intrepid +new file mode 100755 +index 0000000..0030d41 +--- /dev/null ++++ b/debian/scripts/misc/rebase-intrepid +@@ -0,0 +1,108 @@ ++#!/bin/sh ++ ++# Script to maintain a (target) tree based on the intrepid main kernel ++# Author: Amit Kucheria (amit@ubuntu.com) ++# Date: 11/07/08 ++ ++# Assumptions: ++# 1. Every rebase during devel-cycle is an ABI bump ++# 2. The target tree's patches are always on top ++# 3. As a consequence of 2., tags are not really useful ++# 4. autogenerated patches are marked with AUTO; others are marked with SAUCE ++# 5. Keep things in a state that they can be merged back into the main tree at the end of the dev cycle ++ ++targetDir=${1:?"Usage: $0 "} ++ ++# Configuration variables ++patchDir=$targetDir/patches ++masterTree=git://zinc.ubuntu.com/ubuntu/ubuntu-intrepid.git ++masterName=ubuntu-intrepid ++ ++curTag=$masterName-cur ++prevTag=$masterName-prev ++baseTag=auto-rebase-tip ++ ++remoteBranch=auto-tmp-remote ++git=`which git` ++ ++mkdir -p $patchDir ++cd $targetDir ++rm -rf .dotest/ ++ ++echo "* Check for uncommitted files..." ++$git-status | grep -q "nothing to commit" ++if [ ! $? -eq "0" ]; then ++ echo "\tUncommitted changes found!\n\tClean out your tree before running this script. Exiting." ++ exit 1; ++fi ++$git-checkout master ++$git-reset --hard ++ ++echo "\n" ++echo "* Fetching Ubuntu master tree..." ++$git-branch -r | grep $masterName ++if [ $? -eq "0" ]; then ++ echo "\t$masterName is already used as a branch name in your tree. Please change the \$masterName variable in this script." ++ exit 1; ++fi ++$git-remote add -f -t master $masterName $masterTree ++$git-checkout -b $remoteBranch $masterName/master ++$git-checkout master ++ ++echo "\n" ++echo "* Exporting current work as patches..." ++$git-format-patch -o $patchDir $curTag ++# Debugging ++mkdir -p /tmp/$patchDir ++cp $patchDir/*.patch /tmp/$patchDir ++# end Debugging ++# Remove auto-generated patches ++find $patchDir -type f -name "*UBUNTU-AUTO*" -print0 | xargs -0 rm -f ++ ++echo "\n" ++echo "* Starting rebase" ++$git-checkout $remoteBranch ++$git-tag -m "Tip of ubuntu git on which we apply patches" $baseTag ++ ++# Move debian/ out of the way ++$git-mv debian/ debian-main/ ++$git commit -s -m "UBUNTU: AUTO: Move upstream debian/ dir out of the way for a lpia-specific debian/" ++$git-status ++ ++# Copy debian-main/ to debian/ ++cp -a debian-main/ debian/ ++$git-add debian/ ++$git-commit -a -s -m "UBUNTU: AUTO: Create a new debian/" ++$git-status ++ ++# Delete upstream ABI, extra arch/flavours ++$git-rm -r debian/abi/* ++$git-rm -r debian/config/* ++$git-rm debian/control.d/vars.generic debian/control.d/vars.server ++$git-rm debian/rules.d/amd64.mk debian/rules.d/i386.mk ++$git-mv debian/changelog debian/changelog.intrepid ++$git-commit -a -s -m "UBUNTU: AUTO: Delete unncessary ABI/arch/flavours" ++$git-status ++ ++# Apply pending patches ++$git-am patches/* ++if [ -d .dotest/ ]; then ++ echo "\tFailed to apply patches" ++ echo "\tPlease fix the patches on branch $remoteBranch and then sync to the master branch" ++ exit 1; ++fi ++ ++echo "\n" ++echo "* Creating tags..." ++$git-tag -d $prevTag ++$git-tag -m "Previous tip of ubuntu git" $prevTag $curTag ++$git-tag -d $curTag ++$git-tag -m "Tip of ubuntu git on which we apply patches" $curTag $baseTag ++$git-tag -d $baseTag ++ ++echo "\n" ++echo "* Cleanup..." ++$git-checkout master ++#$git-branch -D $remoteBranch ++$git remote rm $masterName ++rm -rf patches +-- +1.5.4.3 + --- linux-2.6.27.orig/patches/0004-UBUNTU-SAUCE-PCI-quirk-for-Poulsbo-HDA.patch +++ linux-2.6.27/patches/0004-UBUNTU-SAUCE-PCI-quirk-for-Poulsbo-HDA.patch @@ -0,0 +1,35 @@ +From 793633576c00a3e6cdb2662e300f5a6e24aab531 Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Tue, 15 Jul 2008 12:31:38 +0300 +Subject: [PATCH] UBUNTU: SAUCE: PCI quirk for Poulsbo HDA + +Signed-off-by: Amit Kucheria +--- + drivers/pci/quirks.c | 11 +++++++++++ + 1 files changed, 11 insertions(+), 0 deletions(-) + +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 338a3f9..419cb5d 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -1496,6 +1496,17 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev) + } + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); + ++ ++static void __devinit fixup_poulsbo_hda(struct pci_dev* dev) ++{ ++ /* poulsbo A2 HD audio controller has the wrong class type of 604h */ ++ if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI) { ++ printk(KERN_INFO "Poulsbo A2 HDA detected, setting PCI class.\n"); ++ dev->class = PCI_CLASS_MULTIMEDIA_AUDIO; ++ } ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_POULSBO_HDA, fixup_poulsbo_hda); ++ + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) + { + while (f < end) { +-- +1.5.4.3 + --- linux-2.6.27.orig/patches/0008-UBUNTU-SAUCE-Ubuntu-2.6.26-1.1.patch +++ linux-2.6.27/patches/0008-UBUNTU-SAUCE-Ubuntu-2.6.26-1.1.patch @@ -0,0 +1,36 @@ +From a0d956bc48a106540a313fe27e362e4c40d38d78 Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Thu, 24 Jul 2008 22:24:01 +0000 +Subject: [PATCH] UBUNTU: SAUCE: Ubuntu-2.6.26-1.1 + +Signed-off-by: Amit Kucheria +--- + debian/changelog | 14 ++++++++++---- + 1 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/debian/changelog b/debian/changelog +index 0419fae..54c1c42 100644 +--- a/debian/changelog ++++ b/debian/changelog +@@ -1,8 +1,14 @@ +-linux-lpia (2.6.26-1.1) UNRELEASED; urgency=low ++linux-lpia (2.6.26-1.1) intrepid; urgency=low + +- CHANGELOG: Do not edit directly. Autogenerated at release. +- CHANGELOG: Use the printchanges target to see the curent changes. +- CHANGELOG: Use the insertchanges target to create the final log. ++ [ Amit Kucheria ] ++ ++ * SAUCE: Start new release ++ * SAUCE: Script to automate rebase to Ubuntu Intrepid Kernel git tree ++ * SAUCE: Support for 9202 HDA Sigmatel codec ++ * SAUCE: PCI quirk for Poulsbo HDA ++ * SAUCE: Support for Poulsbo I2C smbus ++ * SAUCE: UHCI USB quirk for resume ++ * SAUCE: Reboot fix for Intel Crownbeach development boards + + -- Amit Kucheria Thu, 24 Jul 2008 21:46:14 +0000 + +-- +1.5.4.3 + --- linux-2.6.27.orig/patches/0003-UBUNTU-SAUCE-Support-for-9202-HDA-Sigmatel-codec.patch +++ linux-2.6.27/patches/0003-UBUNTU-SAUCE-Support-for-9202-HDA-Sigmatel-codec.patch @@ -0,0 +1,391 @@ +From 25510d996e80acb919897fb7c28dfac19639e108 Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Tue, 15 Jul 2008 12:28:45 +0300 +Subject: [PATCH] UBUNTU: SAUCE: Support for 9202 HDA Sigmatel codec + +Signed-off-by: Amit Kucheria +--- + sound/pci/hda/patch_sigmatel.c | 269 ++++++++++++++++++++++++++++++++++++++- + 1 files changed, 262 insertions(+), 7 deletions(-) + +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index a4f44a0..57b8965 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -34,6 +34,9 @@ + #include "hda_local.h" + #include "hda_patch.h" + ++#define dbg(f, x...) \ ++ printk(KERN_ALERT " [%s()]: " f "\n", __func__,## x) ++ + #define NUM_CONTROL_ALLOC 32 + #define STAC_PWR_EVENT 0x20 + #define STAC_HP_EVENT 0x30 +@@ -57,6 +60,12 @@ enum { + }; + + enum { ++ STAC_9202_REF, ++ STAC_9202_TEST1, ++ STAC_9202_MODELS ++}; ++ ++enum { + STAC_9205_REF, + STAC_9205_DELL_M42, + STAC_9205_DELL_M43, +@@ -259,16 +268,32 @@ static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { + 0x18, 0x19, 0 + }; + ++static hda_nid_t stac9202_adc_nids[1] = { ++ 0x03, ++}; ++ ++static hda_nid_t stac9202_mux_nids[1] = { ++ 0x0f, ++}; ++ ++static hda_nid_t stac9202_dac_nids[1] = { ++ 0x02, ++}; ++ ++static hda_nid_t stac9202_dmic_nids[2] = { ++ 0x15, 0 ++}; ++ + static hda_nid_t stac925x_adc_nids[1] = { +- 0x03, ++ 0x03, + }; + + static hda_nid_t stac925x_mux_nids[1] = { +- 0x0f, ++ 0x0f, + }; + + static hda_nid_t stac925x_dac_nids[1] = { +- 0x02, ++ 0x02, + }; + + #define STAC925X_NUM_DMICS 1 +@@ -331,6 +356,11 @@ static hda_nid_t stac9200_pin_nids[8] = { + 0x0f, 0x10, 0x11, 0x12, + }; + ++static hda_nid_t stac9202_pin_nids[9] = { ++ 0x07, 0x08, 0x0a, 0x0d, ++ 0x0c, 0x0b, 0x10, 0x11, 0x15, ++}; ++ + static hda_nid_t stac925x_pin_nids[8] = { + 0x07, 0x08, 0x0a, 0x0b, + 0x0c, 0x0d, 0x10, 0x11, +@@ -654,6 +684,35 @@ static struct hda_verb stac92hd71bxx_analog_core_init[] = { + {} + }; + ++static struct hda_verb stac9202_core_init[] = { ++ /* set dac0mux for dac converter */ ++ { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, ++ {} ++}; ++ ++/* NID 6, the DAC mux, is set to 0, which forces it to uses NID 2 as its input; ++ Not the loopbacks from either the analog (NID 14) nor stereo (NID 7) inputs. ++ ++ NID 15, the DMIC input, has its widget control set to 0x20, which enables it's ++ output into the Azalia link, not the Analog input ++ ++ NID 7, the SPDIF IN pin, set for EAPD; set power amplifier on */ ++ ++static struct hda_verb stac9202_test1_init[] = { ++ /* set dac0mux for dac converter */ ++ { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, ++ /* Set pin widgets */ ++ { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, ++ /* Set EAPD on SPDIF IN for amp on */ ++ { 0x07, AC_VERB_SET_EAPD_BTLENABLE , 0x02}, ++ /* Set Input MUX for digital input */ ++ { 0x14, AC_VERB_SET_CONNECT_SEL, 0x01}, ++ /* Unmute the Input MUX */ ++ { 0x14, 0x390, 0x00}, ++ { 0x14, 0x3a0, 0x00}, ++ {} ++}; ++ + static struct hda_verb stac925x_core_init[] = { + /* set dac0mux for dac converter */ + { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, +@@ -837,6 +896,60 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { + { } /* end */ + }; + ++static struct snd_kcontrol_new stac9202_mixer[] = { ++ HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT), ++ HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT), ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Input Source", ++ .count = 1, ++ .info = stac92xx_mux_enum_info, ++ .get = stac92xx_mux_enum_get, ++ .put = stac92xx_mux_enum_put, ++ }, ++/* ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Digital Input Source", ++ .count = 1, ++ .info = stac92xx_dmux_enum_info, ++ .get = stac92xx_dmux_enum_get, ++ .put = stac92xx_dmux_enum_put, ++ }, ++*/ ++ HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), ++ HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), ++ HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), ++ { } /* end */ ++}; ++ ++static struct snd_kcontrol_new stac9202_test1_mixer[] = { ++ HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT), ++ HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT), ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Input Source", ++ .count = 1, ++ .info = stac92xx_mux_enum_info, ++ .get = stac92xx_mux_enum_get, ++ .put = stac92xx_mux_enum_put, ++ }, ++/* ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Digital Input Source", ++ .count = 1, ++ .info = stac92xx_dmux_enum_info, ++ .get = stac92xx_dmux_enum_get, ++ .put = stac92xx_dmux_enum_put, ++ }, ++*/ ++ HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), ++ HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), ++ HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), ++ { } /* end */ ++}; ++ + static struct snd_kcontrol_new stac925x_mixer[] = { + STAC_INPUT_SOURCE(1), + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), +@@ -1111,6 +1224,30 @@ static unsigned int oqo9200_pin_configs[8] = { + }; + + ++static unsigned int ref9202_pin_configs[9] = { ++ 0x01c10014, 0x01410013, 0x01210011, 0x01010012, ++ 0x01810022, 0x01a10021, 0x01010031, 0x01310023, 0x01d10024, ++}; ++ ++static unsigned int test19202_pin_configs[9] = { ++ ++ 0x01c100f4, 0x014100f3, 0x01010012, 0x01210011, ++ 0x01210013, 0x01a10023, 0x01010031, 0x01310015, 0x01d10024, ++ ++/* ++ ++ 0x01c100f4, 0x014100f3, 0x01010012, 0x01010011, ++ 0x01810013, 0x01a10023, 0x01010031, 0x01310015, 0x01d10024, ++ ++ 0x01c10014, 0x01410013, 0x01210011, 0x01010012, ++ 0x01810022, 0x01a10021, 0x01010031, 0x01310023, 0x01d10024, ++ ++ 0x70fff100, 0x70fff100, 0x9717f11f, 0x03214011, ++ 0x01810022, 0x01a10021, 0x01010031, 0x01310023, 0x97a00120, ++*/ ++ ++}; ++ + static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { + [STAC_REF] = ref9200_pin_configs, + [STAC_9200_OQO] = oqo9200_pin_configs, +@@ -1144,6 +1281,16 @@ static const char *stac9200_models[STAC_9200_MODELS] = { + [STAC_9200_PANASONIC] = "panasonic", + }; + ++static unsigned int *stac9202_brd_tbl[STAC_9202_MODELS] = { ++ [STAC_REF] = ref9202_pin_configs, ++ [STAC_9202_TEST1] = test19202_pin_configs, ++}; ++ ++static const char *stac9202_models[STAC_9202_MODELS] = { ++ [STAC_REF] = "ref", ++ [STAC_9202_TEST1] = "test1", ++}; ++ + static struct snd_pci_quirk stac9200_cfg_tbl[] = { + /* SigmaTel reference board */ + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, +@@ -1220,6 +1367,14 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { + {} /* terminator */ + }; + ++static struct snd_pci_quirk stac9202_cfg_tbl[] = { ++ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, ++ "Stac 9202 Ref Config", STAC_REF), ++ SND_PCI_QUIRK(0x8384, 0x7632, ++ "Stac 9202 Test 1", STAC_9202_TEST1), ++ {} ++}; ++ + static unsigned int ref925x_pin_configs[8] = { + 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021, + 0x90a70320, 0x02214210, 0x01019020, 0x9033032e, +@@ -2990,6 +3145,37 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) + return 1; + } + ++static int stac9202_parse_auto_config(struct hda_codec *codec) ++{ ++ struct sigmatel_spec *spec = codec->spec; ++ int err; ++ ++ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) ++ return err; ++ ++ if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) ++ return err; ++ ++ if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) ++ return err; ++ ++ if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) ++ return err; ++ ++ if (spec->autocfg.dig_out_pin) ++ spec->multiout.dig_out_nid = 0x05; ++ if (spec->autocfg.dig_in_pin) ++ spec->dig_in_nid = 0x04; ++ ++ if (spec->kctl_alloc) ++ spec->mixers[spec->num_mixers++] = spec->kctl_alloc; ++ ++ spec->input_mux = &spec->private_imux; ++ spec->dinput_mux = &spec->private_dimux; ++ ++ return 1; ++} ++ + /* + * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a + * funky external mute control using GPIO pins. +@@ -3387,7 +3573,7 @@ static int patch_stac9200(struct hda_codec *codec) + return 0; + } + +-static int patch_stac925x(struct hda_codec *codec) ++static int patch_stac9202(struct hda_codec *codec) + { + struct sigmatel_spec *spec; + int err; +@@ -3397,6 +3583,75 @@ static int patch_stac925x(struct hda_codec *codec) + return -ENOMEM; + + codec->spec = spec; ++ spec->num_pins = 9; ++ spec->pin_nids = stac9202_pin_nids; ++ spec->board_config = snd_hda_check_board_config(codec, STAC_9202_MODELS, ++ stac9202_models, ++ stac9202_cfg_tbl); ++ if (spec->board_config < 0) { ++ snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9202, using BIOS defaults\n"); ++ err = stac92xx_save_bios_config_regs(codec); ++ if (err < 0) { ++ stac92xx_free(codec); ++ return err; ++ } ++ spec->pin_configs = spec->bios_pin_configs; ++ } else { ++ spec->pin_configs = stac9202_brd_tbl[spec->board_config]; ++ stac92xx_set_config_regs(codec); ++ } ++ ++ switch (spec->board_config) { ++ case STAC_9202_TEST1: ++ snd_printdd(KERN_INFO "here in test1 %x\n", spec->board_config); ++ spec->multiout.max_channels = 2; ++ spec->multiout.num_dacs = 1; ++ spec->multiout.dac_nids = stac9202_dac_nids; ++ spec->adc_nids = stac9202_adc_nids; ++ spec->mux_nids = stac9202_mux_nids; ++ spec->dmic_nids = stac9202_dmic_nids; ++ spec->num_dmics = 1; ++ spec->num_muxes = 1; ++ spec->init = stac9202_test1_init; ++ spec->mixer = stac9202_test1_mixer; ++ break; ++ default: ++ snd_printdd(KERN_INFO "here in default %x\n", spec->board_config); ++ spec->multiout.max_channels = 2; ++ spec->multiout.num_dacs = 1; ++ spec->multiout.dac_nids = stac9202_dac_nids; ++ spec->adc_nids = stac9202_adc_nids; ++ spec->mux_nids = stac9202_mux_nids; ++ spec->dmic_nids = stac9202_dmic_nids; ++ spec->num_muxes = 1; ++ spec->num_dmics = 1; ++ spec->init = stac9202_core_init; ++ spec->mixer = stac9202_mixer; ++ } ++ ++ err = stac9202_parse_auto_config(codec); ++ if (err < 0) { ++ stac92xx_free(codec); ++ return err; ++ } ++ ++ codec->patch_ops = stac92xx_patch_ops; ++ ++ return 0; ++} ++ ++ ++ ++static int patch_stac925x(struct hda_codec *codec) ++{ ++ struct sigmatel_spec *spec; ++ int err; ++ ++ spec = kzalloc(sizeof(*spec), GFP_KERNEL); ++ if (spec == NULL) ++ return -ENOMEM; ++ ++ codec->spec = spec; + spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); + spec->pin_nids = stac925x_pin_nids; + spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, +@@ -3442,7 +3697,7 @@ static int patch_stac925x(struct hda_codec *codec) + + spec->init = stac925x_core_init; + spec->mixer = stac925x_mixer; +- ++ + err = stac92xx_parse_auto_config(codec, 0x8, 0x7); + if (!err) { + if (spec->board_config < 0) { +@@ -4283,8 +4538,8 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { + { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, + { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, + { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, +- { .id = 0x83847632, .name = "STAC9202", .patch = patch_stac925x }, +- { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x }, ++ { .id = 0x83847632, .name = "STAC9202", .patch = patch_stac9202 }, ++ { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac9202 }, + { .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x }, + { .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x }, + { .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x }, +-- +1.5.4.3 + --- linux-2.6.27.orig/patches/0007-UBUNTU-SAUCE-Reboot-fix-for-Intel-Crownbeach-devel.patch +++ linux-2.6.27/patches/0007-UBUNTU-SAUCE-Reboot-fix-for-Intel-Crownbeach-devel.patch @@ -0,0 +1,34 @@ +From 4e0efb5f8f021a80fa8b42b1af9b7ab2cf296eb3 Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Tue, 15 Jul 2008 15:02:23 +0300 +Subject: [PATCH] UBUNTU: SAUCE: Reboot fix for Intel Crownbeach development boards + +Signed-off-by: Amit Kucheria +--- + arch/x86/kernel/reboot.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index f6be7d5..15afde6 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -185,6 +185,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), + }, + }, ++ { /* Handle problems with rebooting on Intel Crown Beach board */ ++ .callback = set_bios_reboot, ++ .ident = "Intel Crown Beach board", ++ .matches = { ++ /* Currently the DMI info is not customized and indicates ++ * OEM need change that */ ++ DMI_MATCH(DMI_SYS_VENDOR, "To Be Filled By O.E.M."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "To Be Filled By O.E.M."), ++ }, ++ }, + { } + }; + +-- +1.5.4.3 + --- linux-2.6.27.orig/patches/0006-UBUNTU-SAUCE-UHCI-USB-quirk-for-resume.patch +++ linux-2.6.27/patches/0006-UBUNTU-SAUCE-UHCI-USB-quirk-for-resume.patch @@ -0,0 +1,67 @@ +From d36249c47c8cd4c232a76c3d02c3057ff57747e3 Mon Sep 17 00:00:00 2001 +From: Amit Kucheria +Date: Tue, 15 Jul 2008 14:55:09 +0300 +Subject: [PATCH] UBUNTU: SAUCE: UHCI USB quirk for resume + +Signed-off-by: Amit Kucheria +--- + drivers/usb/host/pci-quirks.c | 11 +++++++++++ + drivers/usb/host/uhci-hcd.c | 13 +++++++++++++ + 2 files changed, 24 insertions(+), 0 deletions(-) + +diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c +index ae6e70e..34e7f88 100644 +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -51,6 +51,17 @@ + #define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ + #define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */ + ++void uhci_clear_usb_int(unsigned long base) ++{ ++ outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD); ++ mb(); ++ udelay(5); ++ outw(0, base + UHCI_USBINTR); ++ outw(0, base + UHCI_USBCMD); ++ mb(); ++ return; ++} ++EXPORT_SYMBOL (uhci_clear_usb_int); + + /* + * Make sure the controller is completely inactive, unable to +diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c +index 3a7bfe7..d7fb61b 100644 +--- a/drivers/usb/host/uhci-hcd.c ++++ b/drivers/usb/host/uhci-hcd.c +@@ -933,6 +933,18 @@ static const struct pci_device_id uhci_pci_ids[] = { { + + MODULE_DEVICE_TABLE(pci, uhci_pci_ids); + ++extern void uhci_clear_usb_int(unsigned long base); ++static int usb_hcd_resume_early(struct pci_dev *dev) ++{ ++ struct usb_hcd *hcd; ++ struct uhci_hcd *uhci; ++ ++ hcd = pci_get_drvdata(dev); ++ uhci = hcd_to_uhci(hcd); ++ uhci_clear_usb_int(uhci->io_addr); ++ return 0; ++} ++ + static struct pci_driver uhci_pci_driver = { + .name = (char *)hcd_name, + .id_table = uhci_pci_ids, +@@ -942,6 +954,7 @@ static struct pci_driver uhci_pci_driver = { + .shutdown = uhci_shutdown, + + #ifdef CONFIG_PM ++ .resume_early = usb_hcd_resume_early, + .suspend = usb_hcd_pci_suspend, + .resume = usb_hcd_pci_resume, + #endif /* PM */ +-- +1.5.4.3 + --- linux-2.6.27.orig/fs/exec.c +++ linux-2.6.27/fs/exec.c @@ -1827,7 +1827,8 @@ goto close_fail; if (!file->f_op->write) goto close_fail; - if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0) + if (!ispipe && + do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0) goto close_fail; retval = binfmt->core_dump(signr, regs, file, core_limit); --- linux-2.6.27.orig/fs/splice.c +++ linux-2.6.27/fs/splice.c @@ -887,8 +887,8 @@ /* * Attempt to initiate a splice from pipe to file. */ -static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - loff_t *ppos, size_t len, unsigned int flags) +long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) { int ret; @@ -907,13 +907,14 @@ return out->f_op->splice_write(pipe, out, ppos, len, flags); } +EXPORT_SYMBOL(do_splice_from); /* * Attempt to initiate a splice from a file to a pipe. */ -static long do_splice_to(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +long do_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { int ret; @@ -929,6 +930,7 @@ return in->f_op->splice_read(in, ppos, pipe, len, flags); } +EXPORT_SYMBOL(do_splice_to); /** * splice_direct_to_actor - splices data directly between two non-pipes --- linux-2.6.27.orig/fs/seq_file.c +++ linux-2.6.27/fs/seq_file.c @@ -412,9 +412,7 @@ char *s = m->buf + m->count; char *p; - spin_lock(&dcache_lock); - p = __d_path(path, root, s, m->size - m->count); - spin_unlock(&dcache_lock); + p = __d_path(path, root, s, m->size - m->count, 0); err = PTR_ERR(p); if (!IS_ERR(p)) { s = mangle_path(s, p, esc); --- linux-2.6.27.orig/fs/namei.c +++ linux-2.6.27/fs/namei.c @@ -227,7 +227,7 @@ return -EACCES; } -int inode_permission(struct inode *inode, int mask) +static int __inode_permission(struct inode *inode, int mask) { int retval; @@ -269,7 +269,12 @@ if (retval) return retval; - retval = devcgroup_inode_permission(inode, mask); + return devcgroup_inode_permission(inode, mask); +} + +int inode_permission(struct inode *inode, int mask) +{ + int retval = __inode_permission(inode, mask); if (retval) return retval; @@ -277,6 +282,15 @@ mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); } +int path_permission(struct path *path, int mask) +{ + int retval = __inode_permission(path->dentry->d_inode, mask); + if (retval) + return retval; + return security_path_permission(path, + mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); +} + /** * vfs_permission - check for access rights to a given path * @nd: lookup result that describes the path @@ -289,7 +303,7 @@ */ int vfs_permission(struct nameidata *nd, int mask) { - return inode_permission(nd->path.dentry->d_inode, mask); + return path_permission(&nd->path, mask); } /** @@ -306,7 +320,7 @@ */ int file_permission(struct file *file, int mask) { - return inode_permission(file->f_path.dentry->d_inode, mask); + return path_permission(&file->f_path, mask); } /* @@ -447,8 +461,9 @@ * short-cut DAC fails, then call permission() to do more * complete permission check. */ -static int exec_permission_lite(struct inode *inode) +static int exec_permission_lite(struct path *path) { + struct inode *inode = path->dentry->d_inode; umode_t mode = inode->i_mode; if (inode->i_op && inode->i_op->permission) @@ -473,7 +488,7 @@ return -EACCES; ok: - return security_inode_permission(inode, MAY_EXEC); + return security_path_permission(path, MAY_EXEC); } /* @@ -870,7 +885,7 @@ unsigned int c; nd->flags |= LOOKUP_CONTINUE; - err = exec_permission_lite(inode); + err = exec_permission_lite(&nd->path); if (err == -EAGAIN) err = vfs_permission(nd, MAY_EXEC); if (err) @@ -1065,24 +1080,21 @@ path_get(&fs->pwd); read_unlock(&fs->lock); } else { - struct dentry *dentry; - file = fget_light(dfd, &fput_needed); retval = -EBADF; if (!file) goto out_fail; - dentry = file->f_path.dentry; + nd->path = file->f_path; retval = -ENOTDIR; - if (!S_ISDIR(dentry->d_inode->i_mode)) + if (!S_ISDIR(nd->path.dentry->d_inode->i_mode)) goto fput_fail; retval = file_permission(file, MAY_EXEC); if (retval) goto fput_fail; - nd->path = file->f_path; path_get(&file->f_path); fput_light(file, fput_needed); @@ -1193,7 +1205,7 @@ nd, open_flags, create_mode); } -static struct dentry *__lookup_hash(struct qstr *name, +struct dentry *__lookup_hash(struct qstr *name, struct dentry *base, struct nameidata *nd) { struct dentry *dentry; @@ -1245,7 +1257,7 @@ { int err; - err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); + err = path_permission(&nd->path, MAY_EXEC); if (err) return ERR_PTR(err); return __lookup_hash(&nd->last, nd->path.dentry, nd); @@ -1512,7 +1524,7 @@ return -EACCES; /* shouldn't it be ENOSYS? */ mode &= S_IALLUGO; mode |= S_IFREG; - error = security_inode_create(dir, dentry, mode); + error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode); if (error) return error; DQUOT_INIT(dir); @@ -1588,7 +1600,7 @@ if (!error) { DQUOT_INIT(inode); - error = do_truncate(dentry, 0, + error = do_truncate(dentry, nd->path.mnt, 0, ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, NULL); } @@ -1945,7 +1957,8 @@ } EXPORT_SYMBOL_GPL(lookup_create); -int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, + int mode, dev_t dev) { int error = may_create(dir, dentry); @@ -1962,7 +1975,7 @@ if (error) return error; - error = security_inode_mknod(dir, dentry, mode, dev); + error = security_inode_mknod(dir, dentry, mnt, mode, dev); if (error) return error; @@ -2023,11 +2036,12 @@ error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); break; case S_IFCHR: case S_IFBLK: - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode, - new_decode_dev(dev)); + error = vfs_mknod(nd.path.dentry->d_inode, dentry, + nd.path.mnt, mode, new_decode_dev(dev)); break; case S_IFIFO: case S_IFSOCK: - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); + error = vfs_mknod(nd.path.dentry->d_inode, dentry, + nd.path.mnt, mode, 0); break; } mnt_drop_write(nd.path.mnt); @@ -2046,7 +2060,8 @@ return sys_mknodat(AT_FDCWD, filename, mode, dev); } -int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, + int mode) { int error = may_create(dir, dentry); @@ -2057,7 +2072,7 @@ return -EPERM; mode &= (S_IRWXUGO|S_ISVTX); - error = security_inode_mkdir(dir, dentry, mode); + error = security_inode_mkdir(dir, dentry, mnt, mode); if (error) return error; @@ -2089,7 +2104,7 @@ error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; - error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); + error = vfs_mkdir(nd.path.dentry->d_inode, dentry, nd.path.mnt, mode); mnt_drop_write(nd.path.mnt); out_dput: dput(dentry); @@ -2133,7 +2148,7 @@ spin_unlock(&dcache_lock); } -int vfs_rmdir(struct inode *dir, struct dentry *dentry) +int vfs_rmdir(struct inode *dir, struct dentry *dentry,struct vfsmount *mnt) { int error = may_delete(dir, dentry, 1); @@ -2143,6 +2158,10 @@ if (!dir->i_op || !dir->i_op->rmdir) return -EPERM; + error = security_inode_rmdir(dir, dentry, mnt); + if (error) + return error; + DQUOT_INIT(dir); mutex_lock(&dentry->d_inode->i_mutex); @@ -2150,12 +2169,9 @@ if (d_mountpoint(dentry)) error = -EBUSY; else { - error = security_inode_rmdir(dir, dentry); - if (!error) { - error = dir->i_op->rmdir(dir, dentry); - if (!error) - dentry->d_inode->i_flags |= S_DEAD; - } + error = dir->i_op->rmdir(dir, dentry); + if (!error) + dentry->d_inode->i_flags |= S_DEAD; } mutex_unlock(&dentry->d_inode->i_mutex); if (!error) { @@ -2196,7 +2212,7 @@ error = mnt_want_write(nd.path.mnt); if (error) goto exit3; - error = vfs_rmdir(nd.path.dentry->d_inode, dentry); + error = vfs_rmdir(nd.path.dentry->d_inode, dentry, nd.path.mnt); mnt_drop_write(nd.path.mnt); exit3: dput(dentry); @@ -2213,7 +2229,7 @@ return do_rmdir(AT_FDCWD, pathname); } -int vfs_unlink(struct inode *dir, struct dentry *dentry) +int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt) { int error = may_delete(dir, dentry, 0); @@ -2229,7 +2245,7 @@ if (d_mountpoint(dentry)) error = -EBUSY; else { - error = security_inode_unlink(dir, dentry); + error = security_inode_unlink(dir, dentry, mnt); if (!error) error = dir->i_op->unlink(dir, dentry); } @@ -2278,7 +2294,7 @@ error = mnt_want_write(nd.path.mnt); if (error) goto exit2; - error = vfs_unlink(nd.path.dentry->d_inode, dentry); + error = vfs_unlink(nd.path.dentry->d_inode, dentry, nd.path.mnt); mnt_drop_write(nd.path.mnt); exit2: dput(dentry); @@ -2313,7 +2329,8 @@ return do_unlinkat(AT_FDCWD, pathname); } -int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) +int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, + const char *oldname) { int error = may_create(dir, dentry); @@ -2323,7 +2340,7 @@ if (!dir->i_op || !dir->i_op->symlink) return -EPERM; - error = security_inode_symlink(dir, dentry, oldname); + error = security_inode_symlink(dir, dentry, mnt, oldname); if (error) return error; @@ -2359,7 +2376,7 @@ error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; - error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); + error = vfs_symlink(nd.path.dentry->d_inode, dentry, nd.path.mnt, from); mnt_drop_write(nd.path.mnt); out_dput: dput(dentry); @@ -2377,7 +2394,7 @@ return sys_symlinkat(oldname, AT_FDCWD, newname); } -int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) +int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt) { struct inode *inode = old_dentry->d_inode; int error; @@ -2402,7 +2419,8 @@ if (S_ISDIR(inode->i_mode)) return -EPERM; - error = security_inode_link(old_dentry, dir, new_dentry); + error = security_inode_link(old_dentry, old_mnt, dir, new_dentry, + new_mnt); if (error) return error; @@ -2456,7 +2474,9 @@ error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; - error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); + error = vfs_link(old_path.dentry, old_path.mnt, + nd.path.dentry->d_inode, + new_dentry, nd.path.mnt); mnt_drop_write(nd.path.mnt); out_dput: dput(new_dentry); @@ -2509,7 +2529,8 @@ * locking]. */ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) + struct vfsmount *old_mnt, struct inode *new_dir, + struct dentry *new_dentry, struct vfsmount *new_mnt) { int error = 0; struct inode *target; @@ -2524,7 +2545,8 @@ return error; } - error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry); + error = security_inode_rename(old_dir, old_dentry, old_mnt, + new_dir, new_dentry, new_mnt); if (error) return error; @@ -2552,12 +2574,14 @@ } static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) + struct vfsmount *old_mnt, struct inode *new_dir, + struct dentry *new_dentry, struct vfsmount *new_mnt) { struct inode *target; int error; - error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry); + error = security_inode_rename(old_dir, old_dentry, old_mnt, + new_dir, new_dentry, new_mnt); if (error) return error; @@ -2580,7 +2604,8 @@ } int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) + struct vfsmount *old_mnt, struct inode *new_dir, + struct dentry *new_dentry, struct vfsmount *new_mnt) { int error; int is_dir = S_ISDIR(old_dentry->d_inode->i_mode); @@ -2609,9 +2634,11 @@ old_name = fsnotify_oldname_init(old_dentry->d_name.name); if (is_dir) - error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry); + error = vfs_rename_dir(old_dir, old_dentry, old_mnt, + new_dir, new_dentry, new_mnt); else - error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); + error = vfs_rename_other(old_dir, old_dentry, old_mnt, + new_dir, new_dentry, new_mnt); if (!error) { const char *new_name = old_dentry->d_name.name; fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, @@ -2688,8 +2715,8 @@ error = mnt_want_write(oldnd.path.mnt); if (error) goto exit5; - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); + error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.path.mnt, + new_dir->d_inode, new_dentry, newnd.path.mnt); mnt_drop_write(oldnd.path.mnt); exit5: dput(new_dentry); @@ -2857,6 +2884,7 @@ EXPORT_SYMBOL(path_lookup); EXPORT_SYMBOL(vfs_path_lookup); EXPORT_SYMBOL(inode_permission); +EXPORT_SYMBOL(path_permission); EXPORT_SYMBOL(vfs_permission); EXPORT_SYMBOL(file_permission); EXPORT_SYMBOL(unlock_rename); @@ -2873,3 +2901,5 @@ EXPORT_SYMBOL(vfs_unlink); EXPORT_SYMBOL(dentry_unhash); EXPORT_SYMBOL(generic_readlink); +EXPORT_SYMBOL(deny_write_access); +EXPORT_SYMBOL(__lookup_hash); --- linux-2.6.27.orig/fs/utimes.c +++ linux-2.6.27/fs/utimes.c @@ -48,7 +48,8 @@ return nsec >= 0 && nsec <= 999999999; } -static int utimes_common(struct path *path, struct timespec *times) +static int utimes_common(struct path *path, struct timespec *times, + struct file *f) { int error; struct iattr newattrs; @@ -102,7 +103,7 @@ } } mutex_lock(&inode->i_mutex); - error = notify_change(path->dentry, &newattrs); + error = fnotify_change(path->dentry, path->mnt, &newattrs, f); mutex_unlock(&inode->i_mutex); mnt_drop_write_and_out: @@ -149,7 +150,7 @@ if (!file) goto out; - error = utimes_common(&file->f_path, times); + error = utimes_common(&file->f_path, times, file); fput(file); } else { struct path path; @@ -162,7 +163,7 @@ if (error) goto out; - error = utimes_common(&path, times); + error = utimes_common(&path, times, NULL); path_put(&path); } --- linux-2.6.27.orig/fs/inotify_user.c +++ linux-2.6.27/fs/inotify_user.c @@ -372,7 +372,7 @@ if (error) return error; /* you can only watch an inode if you have read permissions on it */ - error = inode_permission(path->dentry->d_inode, MAY_READ); + error = path_permission(path, MAY_READ); if (error) path_put(path); return error; --- linux-2.6.27.orig/fs/open.c +++ linux-2.6.27/fs/open.c @@ -197,8 +197,8 @@ return error; } -int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, - struct file *filp) +int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length, + unsigned int time_attrs, struct file *filp) { int err; struct iattr newattrs; @@ -209,16 +209,15 @@ newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | time_attrs; - if (filp) { - newattrs.ia_file = filp; + + if (filp) newattrs.ia_valid |= ATTR_FILE; - } /* Remove suid/sgid on truncate too */ newattrs.ia_valid |= should_remove_suid(dentry); mutex_lock(&dentry->d_inode->i_mutex); - err = notify_change(dentry, &newattrs); + err = fnotify_change(dentry, mnt, &newattrs, filp); mutex_unlock(&dentry->d_inode->i_mutex); return err; } @@ -251,7 +250,7 @@ if (error) goto dput_and_out; - error = inode_permission(inode, MAY_WRITE); + error = path_permission(&path, MAY_WRITE); if (error) goto mnt_drop_write_and_out; @@ -274,7 +273,7 @@ error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); - error = do_truncate(path.dentry, length, 0, NULL); + error = do_truncate(path.dentry, path.mnt, length, 0, NULL); } put_write_and_out: @@ -329,7 +328,8 @@ error = locks_verify_truncate(inode, file, length); if (!error) - error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); + error = do_truncate(dentry, file->f_path.mnt, length, + ATTR_MTIME|ATTR_CTIME, file); out_putf: fput(file); out: @@ -474,7 +474,7 @@ goto out_path_release; } - res = inode_permission(inode, mode | MAY_ACCESS); + res = path_permission(&path, mode | MAY_ACCESS); /* SuS v2 requires we report a read only fs too */ if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) goto out_path_release; @@ -517,7 +517,7 @@ if (error) goto out; - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); + error = path_permission(&path, MAY_EXEC | MAY_ACCESS); if (error) goto dput_and_out; @@ -546,7 +546,7 @@ if (!S_ISDIR(inode->i_mode)) goto out_putf; - error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); + error = path_permission(&file->f_path, MAY_EXEC | MAY_ACCESS); if (!error) set_fs_pwd(current->fs, &file->f_path); out_putf: @@ -564,7 +564,7 @@ if (error) goto out; - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); + error = path_permission(&path, MAY_EXEC | MAY_ACCESS); if (error) goto dput_and_out; @@ -604,8 +604,8 @@ if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE; + err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file); mutex_unlock(&inode->i_mutex); mnt_drop_write(file->f_path.mnt); out_putf: @@ -635,7 +635,7 @@ mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - error = notify_change(path.dentry, &newattrs); + error = notify_change(path.dentry, path.mnt, &newattrs); mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); dput_and_out: @@ -649,7 +649,8 @@ return sys_fchmodat(AT_FDCWD, filename, mode); } -static int chown_common(struct dentry * dentry, uid_t user, gid_t group) +static int chown_common(struct dentry * dentry, struct vfsmount *mnt, + uid_t user, gid_t group, struct file *file) { struct inode *inode = dentry->d_inode; int error; @@ -667,8 +668,11 @@ if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; + if (file) + newattrs.ia_valid |= ATTR_FILE; + mutex_lock(&inode->i_mutex); - error = notify_change(dentry, &newattrs); + error = fnotify_change(dentry, mnt, &newattrs, file); mutex_unlock(&inode->i_mutex); return error; @@ -685,7 +689,7 @@ error = mnt_want_write(path.mnt); if (error) goto out_release; - error = chown_common(path.dentry, user, group); + error = chown_common(path.dentry, path.mnt, user, group, NULL); mnt_drop_write(path.mnt); out_release: path_put(&path); @@ -710,7 +714,7 @@ error = mnt_want_write(path.mnt); if (error) goto out_release; - error = chown_common(path.dentry, user, group); + error = chown_common(path.dentry, path.mnt, user, group, NULL); mnt_drop_write(path.mnt); out_release: path_put(&path); @@ -729,7 +733,7 @@ error = mnt_want_write(path.mnt); if (error) goto out_release; - error = chown_common(path.dentry, user, group); + error = chown_common(path.dentry, path.mnt, user, group, NULL); mnt_drop_write(path.mnt); out_release: path_put(&path); @@ -753,7 +757,7 @@ goto out_fput; dentry = file->f_path.dentry; audit_inode(NULL, dentry); - error = chown_common(dentry, user, group); + error = chown_common(dentry, file->f_path.mnt, user, group, file); mnt_drop_write(file->f_path.mnt); out_fput: fput(file); --- linux-2.6.27.orig/fs/namespace.c +++ linux-2.6.27/fs/namespace.c @@ -2352,3 +2352,33 @@ release_mounts(&umount_list); kfree(ns); } + +char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt, + char *buf, int buflen) +{ + struct path root, tmp, ns_root = { }; + struct path path = { .mnt = vfsmnt, .dentry = dentry }; + char *res; + + read_lock(¤t->fs->lock); + root = current->fs->root; + path_get(¤t->fs->root); + read_unlock(¤t->fs->lock); + spin_lock(&vfsmount_lock); + if (root.mnt) + ns_root.mnt = mntget(root.mnt->mnt_ns->root); + if (ns_root.mnt) + ns_root.dentry = dget(ns_root.mnt->mnt_root); + spin_unlock(&vfsmount_lock); + tmp = ns_root; + res = __d_path(&path, &tmp, buf, buflen, + D_PATH_FAIL_DELETED | D_PATH_DISCONNECT); + path_put(&root); + path_put(&ns_root); + + /* Prevent empty path for lazily unmounted filesystems. */ + if (!IS_ERR(res) && *res == '\0') + *--res = '.'; + return res; +} +EXPORT_SYMBOL(d_namespace_path); --- linux-2.6.27.orig/fs/file_table.c +++ linux-2.6.27/fs/file_table.c @@ -347,6 +347,7 @@ file_free(file); } } +EXPORT_SYMBOL(put_filp); void file_move(struct file *file, struct list_head *list) { --- linux-2.6.27.orig/fs/dcache.c +++ linux-2.6.27/fs/dcache.c @@ -1897,44 +1897,46 @@ * @root: root vfsmnt/dentry (may be modified by this function) * @buffer: buffer to return value in * @buflen: buffer length + * @flags: flags controling behavior of d_path * - * Convert a dentry into an ASCII path name. If the entry has been deleted - * the string " (deleted)" is appended. Note that this is ambiguous. - * - * Returns the buffer or an error code if the path was too long. - * - * "buflen" should be positive. Caller holds the dcache_lock. + * Convert a dentry into an ASCII path name. If the entry has been deleted, + * then if @flags has D_PATH_FAIL_DELETED set, ERR_PTR(-ENOENT) is returned. + * Otherwise, the string " (deleted)" is appended. Note that this is ambiguous. * * If path is not reachable from the supplied root, then the value of - * root is changed (without modifying refcounts). + * root is changed (without modifying refcounts). The path returned in this + * case will be relative (i.e., it will not start with a slash). + * + * Returns the buffer or an error code if the path was too long. */ char *__d_path(const struct path *path, struct path *root, - char *buffer, int buflen) + char *buffer, int buflen, int flags) { struct dentry *dentry = path->dentry; struct vfsmount *vfsmnt = path->mnt; - char *end = buffer + buflen; - char *retval; + const unsigned char *name; + int namelen; + + buffer += buflen; + prepend(&buffer, &buflen, "\0", 1); spin_lock(&vfsmount_lock); - prepend(&end, &buflen, "\0", 1); - if (!IS_ROOT(dentry) && d_unhashed(dentry) && - (prepend(&end, &buflen, " (deleted)", 10) != 0)) + spin_lock(&dcache_lock); + if (!IS_ROOT(dentry) && d_unhashed(dentry)) { + if (flags & D_PATH_FAIL_DELETED) { + buffer = ERR_PTR(-ENOENT); + goto out; + } + if (prepend(&buffer, &buflen, " (deleted)", 10) != 0) goto Elong; - + } if (buflen < 1) goto Elong; - /* Get '/' right */ - retval = end-1; - *retval = '/'; - for (;;) { + while (dentry != root->dentry || vfsmnt != root->mnt) { struct dentry * parent; - if (dentry == root->dentry && vfsmnt == root->mnt) - break; if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { - /* Global root? */ if (vfsmnt->mnt_parent == vfsmnt) { goto global_root; } @@ -1944,27 +1946,51 @@ } parent = dentry->d_parent; prefetch(parent); - if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) || - (prepend(&end, &buflen, "/", 1) != 0)) + if ((prepend_name(&buffer, &buflen, &dentry->d_name) != 0) || + (prepend(&buffer, &buflen, "/", 1) != 0)) goto Elong; - retval = end; dentry = parent; } + /* Get '/' right. */ + if (*buffer != '/' && prepend(&buffer, &buflen, "/", 1)) + goto Elong; out: + spin_unlock(&dcache_lock); spin_unlock(&vfsmount_lock); - return retval; + return buffer; global_root: - retval += 1; /* hit the slash */ - if (prepend_name(&retval, &buflen, &dentry->d_name) != 0) + /* + * We went past the (vfsmount, dentry) we were looking for and have + * either hit a root dentry, a lazily unmounted dentry, an + * unconnected dentry, or the file is on a pseudo filesystem. + */ + namelen = dentry->d_name.len; + name = dentry->d_name.name; + + /* + * If this is a root dentry, then overwrite the slash. This + * will also DTRT with pseudo filesystems which have root + * dentries named "foo:". + */ + if (IS_ROOT(dentry) && *buffer == '/') { + buffer++; + buflen++; + } + if ((flags & D_PATH_DISCONNECT) && *name == '/') { + /* Make sure we won't return a pathname starting with '/' */ + name++; + namelen--; + } + if (prepend(&buffer, &buflen, name, namelen)) goto Elong; root->mnt = vfsmnt; root->dentry = dentry; goto out; Elong: - retval = ERR_PTR(-ENAMETOOLONG); + buffer = ERR_PTR(-ENAMETOOLONG); goto out; } @@ -2001,10 +2027,8 @@ root = current->fs->root; path_get(&root); read_unlock(¤t->fs->lock); - spin_lock(&dcache_lock); tmp = root; - res = __d_path(path, &tmp, buf, buflen); - spin_unlock(&dcache_lock); + res = __d_path(path, &tmp, buf, buflen, 0); path_put(&root); return res; } @@ -2087,9 +2111,9 @@ */ asmlinkage long sys_getcwd(char __user *buf, unsigned long size) { - int error; - struct path pwd, root; - char *page = (char *) __get_free_page(GFP_USER); + int error, len; + struct path pwd, root, tmp; + char *page = (char *) __get_free_page(GFP_USER), *cwd; if (!page) return -ENOMEM; @@ -2101,30 +2125,20 @@ path_get(&root); read_unlock(¤t->fs->lock); - error = -ENOENT; - /* Has the current directory has been unlinked? */ - spin_lock(&dcache_lock); - if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) { - unsigned long len; - struct path tmp = root; - char * cwd; - - cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE); - spin_unlock(&dcache_lock); - + tmp = root; + cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE, D_PATH_FAIL_DELETED); + if (IS_ERR(cwd)) { error = PTR_ERR(cwd); - if (IS_ERR(cwd)) - goto out; + goto out; + } - error = -ERANGE; - len = PAGE_SIZE + page - cwd; - if (len <= size) { - error = len; - if (copy_to_user(buf, cwd, len)) - error = -EFAULT; - } - } else - spin_unlock(&dcache_lock); + error = -ERANGE; + len = PAGE_SIZE + page - cwd; + if (len <= size) { + error = len; + if (copy_to_user(buf, cwd, len)) + error = -EFAULT; + } out: path_put(&pwd); --- linux-2.6.27.orig/fs/attr.c +++ linux-2.6.27/fs/attr.c @@ -100,7 +100,8 @@ } EXPORT_SYMBOL(inode_setattr); -int notify_change(struct dentry * dentry, struct iattr * attr) +int fnotify_change(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *attr, struct file *file) { struct inode *inode = dentry->d_inode; mode_t mode = inode->i_mode; @@ -163,13 +164,28 @@ down_write(&dentry->d_inode->i_alloc_sem); if (inode->i_op && inode->i_op->setattr) { - error = security_inode_setattr(dentry, attr); - if (!error) - error = inode->i_op->setattr(dentry, attr); + error = security_inode_setattr(dentry, mnt, attr); + if (!error) { + if (file && file->f_op && file->f_op->fsetattr) + error = file->f_op->fsetattr(file, attr); + else { + /* External file system still expect to be + * passed a file pointer via ia_file and + * have it announced via ATTR_FILE. This + * just makes it so they don't need to + * change their API just for us. External + * callers will have set these themselves. */ + if (file) { + attr->ia_valid |= ATTR_FILE; + attr->ia_file = file; + } + error = inode->i_op->setattr(dentry, attr); + } + } } else { error = inode_change_ok(inode, attr); if (!error) - error = security_inode_setattr(dentry, attr); + error = security_inode_setattr(dentry, mnt, attr); if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) @@ -187,5 +203,12 @@ return error; } +EXPORT_SYMBOL_GPL(fnotify_change); + +int notify_change(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *attr) +{ + return fnotify_change(dentry, mnt, attr, NULL); +} EXPORT_SYMBOL(notify_change); --- linux-2.6.27.orig/fs/stat.c +++ linux-2.6.27/fs/stat.c @@ -306,7 +306,7 @@ error = -EINVAL; if (inode->i_op && inode->i_op->readlink) { - error = security_inode_readlink(path.dentry); + error = security_inode_readlink(path.dentry, path.mnt); if (!error) { touch_atime(path.mnt, path.dentry); error = inode->i_op->readlink(path.dentry, --- linux-2.6.27.orig/fs/xattr.c +++ linux-2.6.27/fs/xattr.c @@ -67,8 +67,8 @@ } int -vfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) +vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name, + const void *value, size_t size, int flags, struct file *file) { struct inode *inode = dentry->d_inode; int error; @@ -78,7 +78,7 @@ return error; mutex_lock(&inode->i_mutex); - error = security_inode_setxattr(dentry, name, value, size, flags); + error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file); if (error) goto out; error = -EOPNOTSUPP; @@ -86,7 +86,7 @@ error = inode->i_op->setxattr(dentry, name, value, size, flags); if (!error) { fsnotify_xattr(dentry); - security_inode_post_setxattr(dentry, name, value, + security_inode_post_setxattr(dentry, mnt, name, value, size, flags); } } else if (!strncmp(name, XATTR_SECURITY_PREFIX, @@ -131,7 +131,8 @@ EXPORT_SYMBOL_GPL(xattr_getsecurity); ssize_t -vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) +vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name, + void *value, size_t size, struct file *file) { struct inode *inode = dentry->d_inode; int error; @@ -140,7 +141,7 @@ if (error) return error; - error = security_inode_getxattr(dentry, name); + error = security_inode_getxattr(dentry, mnt, name, file); if (error) return error; @@ -167,18 +168,20 @@ EXPORT_SYMBOL_GPL(vfs_getxattr); ssize_t -vfs_listxattr(struct dentry *d, char *list, size_t size) +vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list, + size_t size, struct file *file) { + struct inode *inode = dentry->d_inode; ssize_t error; - error = security_inode_listxattr(d); + error = security_inode_listxattr(dentry, mnt, file); if (error) return error; error = -EOPNOTSUPP; - if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { - error = d->d_inode->i_op->listxattr(d, list, size); - } else { - error = security_inode_listsecurity(d->d_inode, list, size); + if (inode->i_op && inode->i_op->listxattr) + error = inode->i_op->listxattr(dentry, list, size); + else { + error = security_inode_listsecurity(inode, list, size); if (size && error > size) error = -ERANGE; } @@ -187,7 +190,8 @@ EXPORT_SYMBOL_GPL(vfs_listxattr); int -vfs_removexattr(struct dentry *dentry, const char *name) +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name, + struct file *file) { struct inode *inode = dentry->d_inode; int error; @@ -199,7 +203,7 @@ if (error) return error; - error = security_inode_removexattr(dentry, name); + error = security_inode_removexattr(dentry, mnt, name, file); if (error) return error; @@ -218,8 +222,8 @@ * Extended attribute SET operations */ static long -setxattr(struct dentry *d, const char __user *name, const void __user *value, - size_t size, int flags) +setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name, + const void __user *value, size_t size, int flags, struct file *file) { int error; void *kvalue = NULL; @@ -246,7 +250,7 @@ } } - error = vfs_setxattr(d, kname, kvalue, size, flags); + error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file); kfree(kvalue); return error; } @@ -263,7 +267,7 @@ return error; error = mnt_want_write(path.mnt); if (!error) { - error = setxattr(path.dentry, name, value, size, flags); + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL); mnt_drop_write(path.mnt); } path_put(&path); @@ -282,7 +286,7 @@ return error; error = mnt_want_write(path.mnt); if (!error) { - error = setxattr(path.dentry, name, value, size, flags); + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL); mnt_drop_write(path.mnt); } path_put(&path); @@ -304,7 +308,8 @@ audit_inode(NULL, dentry); error = mnt_want_write(f->f_path.mnt); if (!error) { - error = setxattr(dentry, name, value, size, flags); + error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags, + f); mnt_drop_write(f->f_path.mnt); } fput(f); @@ -315,8 +320,8 @@ * Extended attribute GET operations */ static ssize_t -getxattr(struct dentry *d, const char __user *name, void __user *value, - size_t size) +getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name, + void __user *value, size_t size, struct file *file) { ssize_t error; void *kvalue = NULL; @@ -336,7 +341,7 @@ return -ENOMEM; } - error = vfs_getxattr(d, kname, kvalue, size); + error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file); if (error > 0) { if (size && copy_to_user(value, kvalue, error)) error = -EFAULT; @@ -359,7 +364,7 @@ error = user_path(pathname, &path); if (error) return error; - error = getxattr(path.dentry, name, value, size); + error = getxattr(path.dentry, path.mnt, name, value, size, NULL); path_put(&path); return error; } @@ -374,7 +379,7 @@ error = user_lpath(pathname, &path); if (error) return error; - error = getxattr(path.dentry, name, value, size); + error = getxattr(path.dentry, path.mnt, name, value, size, NULL); path_put(&path); return error; } @@ -389,7 +394,7 @@ if (!f) return error; audit_inode(NULL, f->f_path.dentry); - error = getxattr(f->f_path.dentry, name, value, size); + error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f); fput(f); return error; } @@ -398,7 +403,8 @@ * Extended attribute LIST operations */ static ssize_t -listxattr(struct dentry *d, char __user *list, size_t size) +listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list, + size_t size, struct file *file) { ssize_t error; char *klist = NULL; @@ -411,7 +417,7 @@ return -ENOMEM; } - error = vfs_listxattr(d, klist, size); + error = vfs_listxattr(dentry, mnt, klist, size, file); if (error > 0) { if (size && copy_to_user(list, klist, error)) error = -EFAULT; @@ -433,7 +439,7 @@ error = user_path(pathname, &path); if (error) return error; - error = listxattr(path.dentry, list, size); + error = listxattr(path.dentry, path.mnt, list, size, NULL); path_put(&path); return error; } @@ -447,7 +453,7 @@ error = user_lpath(pathname, &path); if (error) return error; - error = listxattr(path.dentry, list, size); + error = listxattr(path.dentry, path.mnt, list, size, NULL); path_put(&path); return error; } @@ -462,7 +468,7 @@ if (!f) return error; audit_inode(NULL, f->f_path.dentry); - error = listxattr(f->f_path.dentry, list, size); + error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f); fput(f); return error; } @@ -471,7 +477,8 @@ * Extended attribute REMOVE operations */ static long -removexattr(struct dentry *d, const char __user *name) +removexattr(struct dentry *dentry, struct vfsmount *mnt, + const char __user *name, struct file *file) { int error; char kname[XATTR_NAME_MAX + 1]; @@ -482,7 +489,7 @@ if (error < 0) return error; - return vfs_removexattr(d, kname); + return vfs_removexattr(dentry, mnt, kname, file); } asmlinkage long @@ -496,7 +503,7 @@ return error; error = mnt_want_write(path.mnt); if (!error) { - error = removexattr(path.dentry, name); + error = removexattr(path.dentry, path.mnt, name, NULL); mnt_drop_write(path.mnt); } path_put(&path); @@ -514,7 +521,7 @@ return error; error = mnt_want_write(path.mnt); if (!error) { - error = removexattr(path.dentry, name); + error = removexattr(path.dentry, path.mnt, name, NULL); mnt_drop_write(path.mnt); } path_put(&path); @@ -535,7 +542,7 @@ audit_inode(NULL, dentry); error = mnt_want_write(f->f_path.mnt); if (!error) { - error = removexattr(dentry, name); + error = removexattr(dentry, f->f_path.mnt, name, f); mnt_drop_write(f->f_path.mnt); } fput(f); --- linux-2.6.27.orig/fs/ext4/dir.c +++ linux-2.6.27/fs/ext4/dir.c @@ -102,6 +102,7 @@ int err; struct inode *inode = filp->f_path.dentry->d_inode; int ret = 0; + int dir_has_error = 0; sb = inode->i_sb; @@ -148,9 +149,13 @@ * of recovering data when there's a bad sector */ if (!bh) { - ext4_error (sb, "ext4_readdir", - "directory #%lu contains a hole at offset %lu", - inode->i_ino, (unsigned long)filp->f_pos); + if (!dir_has_error) { + ext4_error(sb, __func__, "directory #%lu " + "contains a hole at offset %Lu", + inode->i_ino, + (unsigned long long) filp->f_pos); + dir_has_error = 1; + } /* corrupt size? Maybe no more blocks to read */ if (filp->f_pos > inode->i_blocks << 9) break; --- linux-2.6.27.orig/fs/xfs/xfs_log.c +++ linux-2.6.27/fs/xfs/xfs_log.c @@ -1033,11 +1033,12 @@ l = iclog->ic_log; /* - * If the ordered flag has been removed by a lower - * layer, it means the underlyin device no longer supports + * If the _XFS_BARRIER_FAILED flag was set by a lower + * layer, it means the underlying device no longer supports * barrier I/O. Warn loudly and turn off barriers. */ - if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ISORDERED(bp)) { + if (bp->b_flags & _XFS_BARRIER_FAILED) { + bp->b_flags &= ~_XFS_BARRIER_FAILED; l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; xfs_fs_cmn_err(CE_WARN, l->l_mp, "xlog_iodone: Barriers are no longer supported" --- linux-2.6.27.orig/fs/xfs/linux-2.6/xfs_super.c +++ linux-2.6.27/fs/xfs/linux-2.6/xfs_super.c @@ -1323,7 +1323,7 @@ "XFS: mount option \"%s\" not supported for remount\n", p); return -EINVAL; #else - return 0; + break; #endif } } --- linux-2.6.27.orig/fs/xfs/linux-2.6/xfs_buf.c +++ linux-2.6.27/fs/xfs/linux-2.6/xfs_buf.c @@ -1001,12 +1001,13 @@ * We can get an EOPNOTSUPP to ordered writes. Here we clear the * ordered flag and reissue them. Because we can't tell the higher * layers directly that they should not issue ordered I/O anymore, they - * need to check if the ordered flag was cleared during I/O completion. + * need to check if the _XFS_BARRIER_FAILED flag was set during I/O completion. */ if ((bp->b_error == EOPNOTSUPP) && (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) { XB_TRACE(bp, "ordered_retry", bp->b_iodone); bp->b_flags &= ~XBF_ORDERED; + bp->b_flags |= _XFS_BARRIER_FAILED; xfs_buf_iorequest(bp); } else if (bp->b_iodone) (*(bp->b_iodone))(bp); --- linux-2.6.27.orig/fs/xfs/linux-2.6/xfs_buf.h +++ linux-2.6.27/fs/xfs/linux-2.6/xfs_buf.h @@ -85,6 +85,14 @@ * modifications being lost. */ _XBF_PAGE_LOCKED = (1 << 22), + + /* + * If we try a barrier write, but it fails we have to communicate + * this to the upper layers. Unfortunately b_error gets overwritten + * when the buffer is re-issued so we have to add another flag to + * keep this information. + */ + _XFS_BARRIER_FAILED = (1 << 23), } xfs_buf_flags_t; typedef enum { --- linux-2.6.27.orig/fs/ecryptfs/inode.c +++ linux-2.6.27/fs/ecryptfs/inode.c @@ -403,19 +403,24 @@ struct dentry *new_dentry) { struct dentry *lower_old_dentry; + struct vfsmount *lower_old_mnt; struct dentry *lower_new_dentry; + struct vfsmount *lower_new_mnt; struct dentry *lower_dir_dentry; u64 file_size_save; int rc; file_size_save = i_size_read(old_dentry->d_inode); lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); + lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); + lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry); dget(lower_old_dentry); dget(lower_new_dentry); lower_dir_dentry = lock_parent(lower_new_dentry); - rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, - lower_new_dentry); + rc = vfs_link(lower_old_dentry, lower_old_mnt, + lower_dir_dentry->d_inode, lower_new_dentry, + lower_new_mnt); if (rc || !lower_new_dentry->d_inode) goto out_lock; rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); @@ -440,11 +445,12 @@ { int rc = 0; struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); struct dentry *lower_dir_dentry; lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_unlink(lower_dir_inode, lower_dentry); + rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt); if (rc) { printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); goto out_unlock; @@ -464,6 +470,7 @@ { int rc; struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct dentry *lower_dir_dentry; char *encoded_symname; int encoded_symlen; @@ -471,6 +478,7 @@ lower_dentry = ecryptfs_dentry_to_lower(dentry); dget(lower_dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); lower_dir_dentry = lock_parent(lower_dentry); encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname, strlen(symname), @@ -479,7 +487,7 @@ rc = encoded_symlen; goto out_lock; } - rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, + rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, encoded_symname); kfree(encoded_symname); if (rc || !lower_dentry->d_inode) @@ -501,11 +509,14 @@ { int rc; struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct dentry *lower_dir_dentry; lower_dentry = ecryptfs_dentry_to_lower(dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode); + rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, + mode); if (rc || !lower_dentry->d_inode) goto out; rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); @@ -524,14 +535,16 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct dentry *lower_dir_dentry; int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); dget(lower_dentry); - rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); + rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt); dput(lower_dentry); if (!rc) d_delete(lower_dentry); @@ -549,11 +562,14 @@ { int rc; struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct dentry *lower_dir_dentry; lower_dentry = ecryptfs_dentry_to_lower(dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev); + rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode, + dev); if (rc || !lower_dentry->d_inode) goto out; rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); @@ -574,19 +590,24 @@ { int rc; struct dentry *lower_old_dentry; + struct vfsmount *lower_old_mnt; struct dentry *lower_new_dentry; + struct vfsmount *lower_new_mnt; struct dentry *lower_old_dir_dentry; struct dentry *lower_new_dir_dentry; lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); + lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); + lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry); dget(lower_old_dentry); dget(lower_new_dentry); lower_old_dir_dentry = dget_parent(lower_old_dentry); lower_new_dir_dentry = dget_parent(lower_new_dentry); lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, - lower_new_dir_dentry->d_inode, lower_new_dentry); + lower_old_mnt, lower_new_dir_dentry->d_inode, + lower_new_dentry, lower_new_mnt); if (rc) goto out_lock; fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL); @@ -849,6 +870,7 @@ { int rc = 0; struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct inode *inode; struct inode *lower_inode; struct ecryptfs_crypt_stat *crypt_stat; @@ -859,6 +881,7 @@ inode = dentry->d_inode; lower_inode = ecryptfs_inode_to_lower(inode); lower_dentry = ecryptfs_dentry_to_lower(dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); mutex_lock(&crypt_stat->cs_mutex); if (S_ISDIR(dentry->d_inode->i_mode)) crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); @@ -910,7 +933,7 @@ ia->ia_valid &= ~ATTR_MODE; mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = notify_change(lower_dentry, ia); + rc = notify_change(lower_dentry, lower_mnt, ia); mutex_unlock(&lower_dentry->d_inode->i_mutex); out: fsstack_copy_attr_all(inode, lower_inode, NULL); --- linux-2.6.27.orig/fs/hfs/catalog.c +++ linux-2.6.27/fs/hfs/catalog.c @@ -190,6 +190,10 @@ fd->search_key->cat.ParID = rec.thread.ParID; len = fd->search_key->cat.CName.len = rec.thread.CName.len; + if (len > HFS_NAMELEN) { + printk(KERN_ERR "hfs: bad catalog namelength\n"); + return -EIO; + } memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len); return hfs_brec_find(fd); } --- linux-2.6.27.orig/fs/fuse/fuse_i.h +++ linux-2.6.27/fs/fuse/fuse_i.h @@ -551,6 +551,10 @@ */ int fuse_dev_init(void); + +int fuse_do_setattr(struct dentry *entry, struct iattr *attr, + struct file *file); + /** * Cleanup the client device */ --- linux-2.6.27.orig/fs/fuse/file.c +++ linux-2.6.27/fs/fuse/file.c @@ -1465,6 +1465,11 @@ return retval; } +static int fuse_fsetattr(struct file *file, struct iattr *attr) +{ + return fuse_do_setattr(file->f_path.dentry, attr, file); +} + static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, .read = do_sync_read, @@ -1478,6 +1483,7 @@ .fsync = fuse_fsync, .lock = fuse_file_lock, .flock = fuse_file_flock, + .fsetattr = fuse_fsetattr, .splice_read = generic_file_splice_read, }; @@ -1491,6 +1497,7 @@ .fsync = fuse_fsync, .lock = fuse_file_lock, .flock = fuse_file_flock, + .fsetattr = fuse_fsetattr, /* no mmap and splice_read */ }; --- linux-2.6.27.orig/fs/fuse/dir.c +++ linux-2.6.27/fs/fuse/dir.c @@ -1105,21 +1105,22 @@ return file ? fuse_fsync_common(file, de, datasync, 1) : 0; } -static bool update_mtime(unsigned ivalid) +static bool update_mtime(unsigned ivalid, bool have_file) { /* Always update if mtime is explicitly set */ if (ivalid & ATTR_MTIME_SET) return true; /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ - if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) + if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file)) return false; /* In all other cases update */ return true; } -static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, + bool have_file) { unsigned ivalid = iattr->ia_valid; @@ -1138,7 +1139,7 @@ if (!(ivalid & ATTR_ATIME_SET)) arg->valid |= FATTR_ATIME_NOW; } - if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) { + if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) { arg->valid |= FATTR_MTIME; arg->mtime = iattr->ia_mtime.tv_sec; arg->mtimensec = iattr->ia_mtime.tv_nsec; @@ -1199,8 +1200,8 @@ * vmtruncate() doesn't allow for this case, so do the rlimit checking * and the actual truncation by hand. */ -static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, - struct file *file) +int fuse_do_setattr(struct dentry *entry, struct iattr *attr, + struct file *file) { struct inode *inode = entry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); @@ -1244,7 +1245,7 @@ memset(&inarg, 0, sizeof(inarg)); memset(&outarg, 0, sizeof(outarg)); - iattr_to_fattr(attr, &inarg); + iattr_to_fattr(attr, &inarg, file != NULL); if (file) { struct fuse_file *ff = file->private_data; inarg.valid |= FATTR_FH; @@ -1314,10 +1315,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) { - if (attr->ia_valid & ATTR_FILE) - return fuse_do_setattr(entry, attr, attr->ia_file); - else - return fuse_do_setattr(entry, attr, NULL); + return fuse_do_setattr(entry, attr, NULL); } static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, --- linux-2.6.27.orig/fs/cifs/cifssmb.c +++ linux-2.6.27/fs/cifs/cifssmb.c @@ -3636,6 +3636,8 @@ le16_to_cpu(parms->SearchCount); psrch_inf->index_of_last_entry = 2 /* skip . and .. */ + psrch_inf->entries_in_buffer; + psrch_inf->last_entry = psrch_inf->srch_entries_start + + le16_to_cpu(parms->LastNameOffset); *pnetfid = parms->SearchHandle; } else { cifs_buf_release(pSMB); @@ -3751,6 +3753,8 @@ le16_to_cpu(parms->SearchCount); psrch_inf->index_of_last_entry += psrch_inf->entries_in_buffer; + psrch_inf->last_entry = psrch_inf->srch_entries_start + + le16_to_cpu(parms->LastNameOffset); /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d", psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */ --- linux-2.6.27.orig/fs/cifs/cifsglob.h +++ linux-2.6.27/fs/cifs/cifsglob.h @@ -309,6 +309,7 @@ __u32 resume_key; char *ntwrk_buf_start; char *srch_entries_start; + char *last_entry; char *presume_name; unsigned int resume_name_len; bool endOfSearch:1; --- linux-2.6.27.orig/fs/cifs/readdir.c +++ linux-2.6.27/fs/cifs/readdir.c @@ -640,6 +640,70 @@ } +static int cifs_save_resume_key(const char *current_entry, + struct cifsFileInfo *cifsFile) +{ + int rc = 0; + unsigned int len = 0; + __u16 level; + char *filename; + + if ((cifsFile == NULL) || (current_entry == NULL)) + return -EINVAL; + + level = cifsFile->srch_inf.info_level; + + if (level == SMB_FIND_FILE_UNIX) { + FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; + + filename = &pFindData->FileName[0]; + if (cifsFile->srch_inf.unicode) { + len = cifs_unicode_bytelen(filename); + } else { + /* BB should we make this strnlen of PATH_MAX? */ + len = strnlen(filename, PATH_MAX); + } + cifsFile->srch_inf.resume_key = pFindData->ResumeKey; + } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { + FILE_DIRECTORY_INFO *pFindData = + (FILE_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { + FILE_FULL_DIRECTORY_INFO *pFindData = + (FILE_FULL_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { + SEARCH_ID_FULL_DIR_INFO *pFindData = + (SEARCH_ID_FULL_DIR_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + FILE_BOTH_DIRECTORY_INFO *pFindData = + (FILE_BOTH_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_INFO_STANDARD) { + FIND_FILE_STANDARD_INFO *pFindData = + (FIND_FILE_STANDARD_INFO *)current_entry; + filename = &pFindData->FileName[0]; + /* one byte length, no name conversion */ + len = (unsigned int)pFindData->FileNameLength; + cifsFile->srch_inf.resume_key = pFindData->ResumeKey; + } else { + cFYI(1, ("Unknown findfirst level %d", level)); + return -EINVAL; + } + cifsFile->srch_inf.resume_name_len = len; + cifsFile->srch_inf.presume_name = filename; + return rc; +} + /* find the corresponding entry in the search */ /* Note that the SMB server returns search entries for . and .. which complicates logic here if we choose to parse for them and we do not @@ -698,6 +762,7 @@ rc)); return rc; } + cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); } while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && @@ -705,6 +770,7 @@ cFYI(1, ("calling findnext2")); rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, &cifsFile->srch_inf); + cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); if (rc) return -ENOENT; } @@ -919,69 +985,6 @@ return rc; } -static int cifs_save_resume_key(const char *current_entry, - struct cifsFileInfo *cifsFile) -{ - int rc = 0; - unsigned int len = 0; - __u16 level; - char *filename; - - if ((cifsFile == NULL) || (current_entry == NULL)) - return -EINVAL; - - level = cifsFile->srch_inf.info_level; - - if (level == SMB_FIND_FILE_UNIX) { - FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; - - filename = &pFindData->FileName[0]; - if (cifsFile->srch_inf.unicode) { - len = cifs_unicode_bytelen(filename); - } else { - /* BB should we make this strnlen of PATH_MAX? */ - len = strnlen(filename, PATH_MAX); - } - cifsFile->srch_inf.resume_key = pFindData->ResumeKey; - } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { - FILE_DIRECTORY_INFO *pFindData = - (FILE_DIRECTORY_INFO *)current_entry; - filename = &pFindData->FileName[0]; - len = le32_to_cpu(pFindData->FileNameLength); - cifsFile->srch_inf.resume_key = pFindData->FileIndex; - } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { - FILE_FULL_DIRECTORY_INFO *pFindData = - (FILE_FULL_DIRECTORY_INFO *)current_entry; - filename = &pFindData->FileName[0]; - len = le32_to_cpu(pFindData->FileNameLength); - cifsFile->srch_inf.resume_key = pFindData->FileIndex; - } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { - SEARCH_ID_FULL_DIR_INFO *pFindData = - (SEARCH_ID_FULL_DIR_INFO *)current_entry; - filename = &pFindData->FileName[0]; - len = le32_to_cpu(pFindData->FileNameLength); - cifsFile->srch_inf.resume_key = pFindData->FileIndex; - } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { - FILE_BOTH_DIRECTORY_INFO *pFindData = - (FILE_BOTH_DIRECTORY_INFO *)current_entry; - filename = &pFindData->FileName[0]; - len = le32_to_cpu(pFindData->FileNameLength); - cifsFile->srch_inf.resume_key = pFindData->FileIndex; - } else if (level == SMB_FIND_FILE_INFO_STANDARD) { - FIND_FILE_STANDARD_INFO *pFindData = - (FIND_FILE_STANDARD_INFO *)current_entry; - filename = &pFindData->FileName[0]; - /* one byte length, no name conversion */ - len = (unsigned int)pFindData->FileNameLength; - cifsFile->srch_inf.resume_key = pFindData->ResumeKey; - } else { - cFYI(1, ("Unknown findfirst level %d", level)); - return -EINVAL; - } - cifsFile->srch_inf.resume_name_len = len; - cifsFile->srch_inf.presume_name = filename; - return rc; -} int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) { --- linux-2.6.27.orig/fs/ext3/super.c +++ linux-2.6.27/fs/ext3/super.c @@ -2365,13 +2365,12 @@ static int ext3_sync_fs(struct super_block *sb, int wait) { - tid_t target; - sb->s_dirt = 0; - if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) { - if (wait) - log_wait_commit(EXT3_SB(sb)->s_journal, target); - } + if (wait) + ext3_force_commit(sb); + else + journal_start_commit(EXT3_SB(sb)->s_journal, NULL); + return 0; } --- linux-2.6.27.orig/fs/ext3/dir.c +++ linux-2.6.27/fs/ext3/dir.c @@ -102,6 +102,7 @@ int err; struct inode *inode = filp->f_path.dentry->d_inode; int ret = 0; + int dir_has_error = 0; sb = inode->i_sb; @@ -148,9 +149,12 @@ * of recovering data when there's a bad sector */ if (!bh) { - ext3_error (sb, "ext3_readdir", - "directory #%lu contains a hole at offset %lu", - inode->i_ino, (unsigned long)filp->f_pos); + if (!dir_has_error) { + ext3_error(sb, __func__, "directory #%lu " + "contains a hole at offset %lld", + inode->i_ino, filp->f_pos); + dir_has_error = 1; + } /* corrupt size? Maybe no more blocks to read */ if (filp->f_pos > inode->i_blocks << 9) break; --- linux-2.6.27.orig/fs/hfsplus/bitmap.c +++ linux-2.6.27/fs/hfsplus/bitmap.c @@ -32,6 +32,10 @@ mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); + if (IS_ERR(page)) { + start = size; + goto out; + } pptr = kmap(page); curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; i = offset % 32; @@ -73,6 +77,10 @@ break; page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); + if (IS_ERR(page)) { + start = size; + goto out; + } curr = pptr = kmap(page); if ((size ^ offset) / PAGE_CACHE_BITS) end = pptr + PAGE_CACHE_BITS / 32; @@ -120,6 +128,10 @@ offset += PAGE_CACHE_BITS; page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); + if (IS_ERR(page)) { + start = size; + goto out; + } pptr = kmap(page); curr = pptr; end = pptr + PAGE_CACHE_BITS / 32; --- linux-2.6.27.orig/fs/hfsplus/catalog.c +++ linux-2.6.27/fs/hfsplus/catalog.c @@ -168,6 +168,11 @@ return -EIO; } + if (be16_to_cpu(tmp.thread.nodeName.length) > 255) { + printk(KERN_ERR "hfs: catalog name length corrupted\n"); + return -EIO; + } + hfsplus_cat_build_key_uni(fd->search_key, be32_to_cpu(tmp.thread.parentID), &tmp.thread.nodeName); return hfs_brec_find(fd); --- linux-2.6.27.orig/fs/reiserfs/xattr.c +++ linux-2.6.27/fs/reiserfs/xattr.c @@ -459,7 +459,7 @@ newattrs.ia_size = buffer_size; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR); - err = notify_change(dentry, &newattrs); + err = notify_change(dentry, NULL, &newattrs); if (err) goto out_filp; @@ -746,7 +746,7 @@ if (dir->d_inode->i_nlink <= 2) { root = get_xa_root(inode->i_sb, XATTR_REPLACE); reiserfs_write_lock_xattrs(inode->i_sb); - err = vfs_rmdir(root->d_inode, dir); + err = vfs_rmdir(root->d_inode, dir, NULL); reiserfs_write_unlock_xattrs(inode->i_sb); dput(root); } else { @@ -790,7 +790,7 @@ } if (!S_ISDIR(xafile->d_inode->i_mode)) - err = notify_change(xafile, attrs); + err = notify_change(xafile, NULL, attrs); dput(xafile); return err; @@ -834,7 +834,7 @@ goto out_dir; } - err = notify_change(dir, attrs); + err = notify_change(dir, NULL, attrs); unlock_kernel(); out_dir: --- linux-2.6.27.orig/fs/proc/proc_misc.c +++ linux-2.6.27/fs/proc/proc_misc.c @@ -703,6 +703,19 @@ return proc_calc_metrics(page, start, off, count, eof, len); } +#ifdef CONFIG_VERSION_SIGNATURE +static int version_signature_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + strcpy(page, CONFIG_VERSION_SIGNATURE); + strcat(page, "\n"); + len = strlen(page); + return proc_calc_metrics(page, start, off, count, eof, len); +} +#endif + #ifdef CONFIG_MAGIC_SYSRQ /* * writing 'C' to /proc/sysrq-trigger is like sysrq-C @@ -877,6 +890,9 @@ {"filesystems", filesystems_read_proc}, {"cmdline", cmdline_read_proc}, {"execdomains", execdomains_read_proc}, +#ifdef CONFIG_VERSION_SIGNATURE + {"version_signature", version_signature_read_proc}, +#endif {NULL,} }; for (p = simple_ones; p->name; p++) --- linux-2.6.27.orig/fs/proc/task_mmu.c +++ linux-2.6.27/fs/proc/task_mmu.c @@ -198,11 +198,8 @@ return ret; } -static int show_map(struct seq_file *m, void *v) +static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) { - struct proc_maps_private *priv = m->private; - struct task_struct *task = priv->task; - struct vm_area_struct *vma = v; struct mm_struct *mm = vma->vm_mm; struct file *file = vma->vm_file; int flags = vma->vm_flags; @@ -210,9 +207,6 @@ dev_t dev = 0; int len; - if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) - return -EACCES; - if (file) { struct inode *inode = vma->vm_file->f_path.dentry->d_inode; dev = inode->i_sb->s_dev; @@ -257,6 +251,18 @@ } } seq_putc(m, '\n'); +} + +static int show_map(struct seq_file *m, void *v) +{ + struct vm_area_struct *vma = v; + struct proc_maps_private *priv = m->private; + struct task_struct *task = priv->task; + + if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) + return -EACCES; + + show_map_vma(m, vma); if (m->count < m->size) /* vma is copied successfully */ m->version = (vma != get_gate_vma(task))? vma->vm_start: 0; @@ -367,23 +373,25 @@ static int show_smap(struct seq_file *m, void *v) { + struct proc_maps_private *priv = m->private; + struct task_struct *task = priv->task; struct vm_area_struct *vma = v; struct mem_size_stats mss; - int ret; struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range, .mm = vma->vm_mm, .private = &mss, }; + if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) + return -EACCES; + memset(&mss, 0, sizeof mss); mss.vma = vma; if (vma->vm_mm && !is_vm_hugetlb_page(vma)) walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); - ret = show_map(m, v); - if (ret) - return ret; + show_map_vma(m, vma); seq_printf(m, "Size: %8lu kB\n" @@ -405,7 +413,9 @@ mss.referenced >> 10, mss.swap >> 10); - return ret; + if (m->count < m->size) /* vma is copied successfully */ + m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0; + return 0; } static const struct seq_operations proc_pid_smaps_op = { --- linux-2.6.27.orig/fs/fat/file.c +++ linux-2.6.27/fs/fat/file.c @@ -98,7 +98,7 @@ * out the RO attribute for checking by the security * module, just because it maps to a file mode. */ - err = security_inode_setattr(filp->f_path.dentry, &ia); + err = security_inode_setattr(filp->f_path.dentry, filp->f_path.mnt, &ia); if (err) goto up; --- linux-2.6.27.orig/fs/afs/internal.h +++ linux-2.6.27/fs/afs/internal.h @@ -548,6 +548,7 @@ extern int afs_validate(struct afs_vnode *, struct key *); extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int afs_setattr(struct dentry *, struct iattr *); +extern int afs_fsetattr(struct file *, struct iattr *); extern void afs_clear_inode(struct inode *); /* --- linux-2.6.27.orig/fs/afs/file.c +++ linux-2.6.27/fs/afs/file.c @@ -36,6 +36,7 @@ .fsync = afs_fsync, .lock = afs_lock, .flock = afs_flock, + .fsetattr = afs_fsetattr, }; const struct inode_operations afs_file_inode_operations = { --- linux-2.6.27.orig/fs/afs/dir.c +++ linux-2.6.27/fs/afs/dir.c @@ -45,6 +45,7 @@ .release = afs_release, .readdir = afs_readdir, .lock = afs_lock, + .fsetattr = afs_fsetattr, }; const struct inode_operations afs_dir_inode_operations = { --- linux-2.6.27.orig/fs/afs/inode.c +++ linux-2.6.27/fs/afs/inode.c @@ -358,7 +358,8 @@ /* * set the attributes of an inode */ -int afs_setattr(struct dentry *dentry, struct iattr *attr) +static int afs_do_setattr(struct dentry *dentry, struct iattr *attr, + struct file *file) { struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode); struct key *key; @@ -380,8 +381,8 @@ afs_writeback_all(vnode); } - if (attr->ia_valid & ATTR_FILE) { - key = attr->ia_file->private_data; + if (file) { + key = file->private_data; } else { key = afs_request_key(vnode->volume->cell); if (IS_ERR(key)) { @@ -391,10 +392,20 @@ } ret = afs_vnode_setattr(vnode, key, attr); - if (!(attr->ia_valid & ATTR_FILE)) + if (!file) key_put(key); error: _leave(" = %d", ret); return ret; } + +int afs_setattr(struct dentry *dentry, struct iattr *attr) +{ + return afs_do_setattr(dentry, attr, NULL); +} + +int afs_fsetattr(struct file *file, struct iattr *attr) +{ + return afs_do_setattr(file->f_path.dentry, attr, file); +} --- linux-2.6.27.orig/fs/ext2/dir.c +++ linux-2.6.27/fs/ext2/dir.c @@ -103,7 +103,7 @@ return err; } -static void ext2_check_page(struct page *page) +static void ext2_check_page(struct page *page, int quiet) { struct inode *dir = page->mapping->host; struct super_block *sb = dir->i_sb; @@ -146,10 +146,10 @@ /* Too bad, we had an error */ Ebadsize: - ext2_error(sb, "ext2_check_page", - "size of directory #%lu is not a multiple of chunk size", - dir->i_ino - ); + if (!quiet) + ext2_error(sb, __func__, + "size of directory #%lu is not a multiple " + "of chunk size", dir->i_ino); goto fail; Eshort: error = "rec_len is smaller than minimal"; @@ -166,32 +166,36 @@ Einumber: error = "inode out of bounds"; bad_entry: - ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - " - "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", - dir->i_ino, error, (page->index<inode), - rec_len, p->name_len); + if (!quiet) + ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - " + "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", + dir->i_ino, error, (page->index<inode), + rec_len, p->name_len); goto fail; Eend: - p = (ext2_dirent *)(kaddr + offs); - ext2_error (sb, "ext2_check_page", - "entry in directory #%lu spans the page boundary" - "offset=%lu, inode=%lu", - dir->i_ino, (page->index<inode)); + if (!quiet) { + p = (ext2_dirent *)(kaddr + offs); + ext2_error(sb, "ext2_check_page", + "entry in directory #%lu spans the page boundary" + "offset=%lu, inode=%lu", + dir->i_ino, (page->index<inode)); + } fail: SetPageChecked(page); SetPageError(page); } -static struct page * ext2_get_page(struct inode *dir, unsigned long n) +static struct page * ext2_get_page(struct inode *dir, unsigned long n, + int quiet) { struct address_space *mapping = dir->i_mapping; struct page *page = read_mapping_page(mapping, n, NULL); if (!IS_ERR(page)) { kmap(page); if (!PageChecked(page)) - ext2_check_page(page); + ext2_check_page(page, quiet); if (PageError(page)) goto fail; } @@ -292,7 +296,7 @@ for ( ; n < npages; n++, offset = 0) { char *kaddr, *limit; ext2_dirent *de; - struct page *page = ext2_get_page(inode, n); + struct page *page = ext2_get_page(inode, n, 0); if (IS_ERR(page)) { ext2_error(sb, __func__, @@ -361,6 +365,7 @@ struct page *page = NULL; struct ext2_inode_info *ei = EXT2_I(dir); ext2_dirent * de; + int dir_has_error = 0; if (npages == 0) goto out; @@ -374,7 +379,7 @@ n = start; do { char *kaddr; - page = ext2_get_page(dir, n); + page = ext2_get_page(dir, n, dir_has_error); if (!IS_ERR(page)) { kaddr = page_address(page); de = (ext2_dirent *) kaddr; @@ -391,7 +396,9 @@ de = ext2_next_entry(de); } ext2_put_page(page); - } + } else + dir_has_error = 1; + if (++n >= npages) n = 0; /* next page is past the blocks we've got */ @@ -414,7 +421,7 @@ struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p) { - struct page *page = ext2_get_page(dir, 0); + struct page *page = ext2_get_page(dir, 0, 0); ext2_dirent *de = NULL; if (!IS_ERR(page)) { @@ -487,7 +494,7 @@ for (n = 0; n <= npages; n++) { char *dir_end; - page = ext2_get_page(dir, n); + page = ext2_get_page(dir, n, 0); err = PTR_ERR(page); if (IS_ERR(page)) goto out; @@ -655,14 +662,17 @@ { struct page *page = NULL; unsigned long i, npages = dir_pages(inode); + int dir_has_error = 0; for (i = 0; i < npages; i++) { char *kaddr; ext2_dirent * de; - page = ext2_get_page(inode, i); + page = ext2_get_page(inode, i, dir_has_error); - if (IS_ERR(page)) + if (IS_ERR(page)) { + dir_has_error = 1; continue; + } kaddr = page_address(page); de = (ext2_dirent *)kaddr; --- linux-2.6.27.orig/fs/nfsd/nfs4recover.c +++ linux-2.6.27/fs/nfsd/nfs4recover.c @@ -158,7 +158,8 @@ status = mnt_want_write(rec_dir.path.mnt); if (status) goto out_put; - status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU); + status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, + rec_dir.path.mnt, S_IRWXU); mnt_drop_write(rec_dir.path.mnt); out_put: dput(dentry); @@ -263,7 +264,7 @@ return -EINVAL; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); - status = vfs_unlink(dir->d_inode, dentry); + status = vfs_unlink(dir->d_inode, dentry, rec_dir.path.mnt); mutex_unlock(&dir->d_inode->i_mutex); return status; } @@ -278,7 +279,7 @@ * a kernel from the future.... */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); - status = vfs_rmdir(dir->d_inode, dentry); + status = vfs_rmdir(dir->d_inode, dentry, rec_dir.path.mnt); mutex_unlock(&dir->d_inode->i_mutex); return status; } --- linux-2.6.27.orig/fs/nfsd/nfs4xdr.c +++ linux-2.6.27/fs/nfsd/nfs4xdr.c @@ -1446,7 +1446,7 @@ } if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT | FATTR4_WORD0_SUPPORTED_ATTRS)) { - err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl); + err = nfsd4_get_nfs4_acl(rqstp, dentry, exp->ex_path.mnt, &acl); aclsupport = (err == 0); if (bmval0 & FATTR4_WORD0_ACL) { if (err == -EOPNOTSUPP) --- linux-2.6.27.orig/fs/nfsd/vfs.c +++ linux-2.6.27/fs/nfsd/vfs.c @@ -388,7 +388,7 @@ err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime.tv_sec) { fh_lock(fhp); - host_err = notify_change(dentry, iap); + host_err = notify_change(dentry, fhp->fh_export->ex_path.mnt, iap); err = nfserrno(host_err); fh_unlock(fhp); } @@ -408,11 +408,12 @@ #if defined(CONFIG_NFSD_V2_ACL) || \ defined(CONFIG_NFSD_V3_ACL) || \ defined(CONFIG_NFSD_V4) -static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf) +static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt, + char *key, void **buf) { ssize_t buflen; - buflen = vfs_getxattr(dentry, key, NULL, 0); + buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL); if (buflen <= 0) return buflen; @@ -420,13 +421,14 @@ if (!*buf) return -ENOMEM; - return vfs_getxattr(dentry, key, *buf, buflen); + return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL); } #endif #if defined(CONFIG_NFSD_V4) static int -set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key) +set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt, + struct posix_acl *pacl, char *key) { int len; size_t buflen; @@ -445,7 +447,7 @@ goto out; } - error = vfs_setxattr(dentry, key, buf, len, 0); + error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL); out: kfree(buf); return error; @@ -458,6 +460,7 @@ __be32 error; int host_error; struct dentry *dentry; + struct vfsmount *mnt; struct inode *inode; struct posix_acl *pacl = NULL, *dpacl = NULL; unsigned int flags = 0; @@ -468,6 +471,7 @@ return error; dentry = fhp->fh_dentry; + mnt = fhp->fh_export->ex_path.mnt; inode = dentry->d_inode; if (S_ISDIR(inode->i_mode)) flags = NFS4_ACL_DIR; @@ -478,12 +482,14 @@ } else if (host_error < 0) goto out_nfserr; - host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); + host_error = set_nfsv4_acl_one(dentry, mnt, pacl, + POSIX_ACL_XATTR_ACCESS); if (host_error < 0) goto out_release; if (S_ISDIR(inode->i_mode)) - host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); + host_error = set_nfsv4_acl_one(dentry, mnt, dpacl, + POSIX_ACL_XATTR_DEFAULT); out_release: posix_acl_release(pacl); @@ -496,13 +502,13 @@ } static struct posix_acl * -_get_posix_acl(struct dentry *dentry, char *key) +_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key) { void *buf = NULL; struct posix_acl *pacl = NULL; int buflen; - buflen = nfsd_getxattr(dentry, key, &buf); + buflen = nfsd_getxattr(dentry, mnt, key, &buf); if (!buflen) buflen = -ENODATA; if (buflen <= 0) @@ -514,14 +520,15 @@ } int -nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl) +nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, + struct vfsmount *mnt, struct nfs4_acl **acl) { struct inode *inode = dentry->d_inode; int error = 0; struct posix_acl *pacl = NULL, *dpacl = NULL; unsigned int flags = 0; - pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS); + pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS); if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA) pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); if (IS_ERR(pacl)) { @@ -531,7 +538,7 @@ } if (S_ISDIR(inode->i_mode)) { - dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT); + dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT); if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA) dpacl = NULL; else if (IS_ERR(dpacl)) { @@ -944,13 +951,13 @@ return err; } -static void kill_suid(struct dentry *dentry) +static void kill_suid(struct dentry *dentry, struct vfsmount *mnt) { struct iattr ia; ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; mutex_lock(&dentry->d_inode->i_mutex); - notify_change(dentry, &ia); + notify_change(dentry, mnt, &ia); mutex_unlock(&dentry->d_inode->i_mutex); } @@ -1009,7 +1016,7 @@ /* clear setuid/setgid flag after write */ if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) - kill_suid(dentry); + kill_suid(dentry, exp->ex_path.mnt); if (host_err >= 0 && stable) { static ino_t last_ino; @@ -1187,6 +1194,7 @@ int type, dev_t rdev, struct svc_fh *resfhp) { struct dentry *dentry, *dchild = NULL; + struct svc_export *exp; struct inode *dirp; __be32 err; __be32 err2; @@ -1204,6 +1212,7 @@ goto out; dentry = fhp->fh_dentry; + exp = fhp->fh_export; dirp = dentry->d_inode; err = nfserr_notdir; @@ -1220,7 +1229,7 @@ host_err = PTR_ERR(dchild); if (IS_ERR(dchild)) goto out_nfserr; - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); + err = fh_compose(resfhp, exp, dchild, fhp); if (err) goto out; } else { @@ -1270,13 +1279,14 @@ host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); break; case S_IFDIR: - host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); + host_err = vfs_mkdir(dirp, dchild, exp->ex_path.mnt, iap->ia_mode); break; case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: - host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); + host_err = vfs_mknod(dirp, dchild, exp->ex_path.mnt, + iap->ia_mode, rdev); break; } if (host_err < 0) { @@ -1284,7 +1294,7 @@ goto out_nfserr; } - if (EX_ISSYNC(fhp->fh_export)) { + if (EX_ISSYNC(exp)) { err = nfserrno(nfsd_sync_dir(dentry)); write_inode_now(dchild->d_inode, 1); } @@ -1514,6 +1524,7 @@ struct iattr *iap) { struct dentry *dentry, *dnew; + struct svc_export *exp; __be32 err, cerr; int host_err; @@ -1538,6 +1549,7 @@ if (host_err) goto out_nfserr; + exp = fhp->fh_export; if (unlikely(path[plen] != 0)) { char *path_alloced = kmalloc(plen+1, GFP_KERNEL); if (path_alloced == NULL) @@ -1545,14 +1557,16 @@ else { strncpy(path_alloced, path, plen); path_alloced[plen] = 0; - host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced); + host_err = vfs_symlink(dentry->d_inode, dnew, + exp->ex_path.mnt, path_alloced); kfree(path_alloced); } } else - host_err = vfs_symlink(dentry->d_inode, dnew, path); + host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_path.mnt, + path); if (!host_err) { - if (EX_ISSYNC(fhp->fh_export)) + if (EX_ISSYNC(exp)) host_err = nfsd_sync_dir(dentry); } err = nfserrno(host_err); @@ -1560,7 +1574,7 @@ mnt_drop_write(fhp->fh_export->ex_path.mnt); - cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); + cerr = fh_compose(resfhp, exp, dnew, fhp); dput(dnew); if (err==0) err = cerr; out: @@ -1615,7 +1629,8 @@ err = nfserrno(host_err); goto out_dput; } - host_err = vfs_link(dold, dirp, dnew); + host_err = vfs_link(dold, tfhp->fh_export->ex_path.mnt, dirp, + dnew, ffhp->fh_export->ex_path.mnt); if (!host_err) { if (EX_ISSYNC(ffhp->fh_export)) { err = nfserrno(nfsd_sync_dir(ddir)); @@ -1716,7 +1731,8 @@ if (host_err) goto out_dput_new; - host_err = vfs_rename(fdir, odentry, tdir, ndentry); + host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_path.mnt, + tdir, ndentry, tfhp->fh_export->ex_path.mnt); if (!host_err && EX_ISSYNC(tfhp->fh_export)) { host_err = nfsd_sync_dir(tdentry); if (!host_err) @@ -1754,6 +1770,7 @@ char *fname, int flen) { struct dentry *dentry, *rdentry; + struct svc_export *exp; struct inode *dirp; __be32 err; int host_err; @@ -1768,6 +1785,7 @@ fh_lock_nested(fhp, I_MUTEX_PARENT); dentry = fhp->fh_dentry; dirp = dentry->d_inode; + exp = fhp->fh_export; rdentry = lookup_one_len(fname, dentry, flen); host_err = PTR_ERR(rdentry); @@ -1789,21 +1807,21 @@ if (type != S_IFDIR) { /* It's UNLINK */ #ifdef MSNFS - if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && + if ((exp->ex_flags & NFSEXP_MSNFS) && (atomic_read(&rdentry->d_count) > 1)) { host_err = -EPERM; } else #endif - host_err = vfs_unlink(dirp, rdentry); + host_err = vfs_unlink(dirp, rdentry, exp->ex_path.mnt); } else { /* It's RMDIR */ - host_err = vfs_rmdir(dirp, rdentry); + host_err = vfs_rmdir(dirp, rdentry, exp->ex_path.mnt); } dput(rdentry); if (host_err) goto out_drop; - if (EX_ISSYNC(fhp->fh_export)) + if (EX_ISSYNC(exp)) host_err = nfsd_sync_dir(dentry); out_drop: @@ -2036,7 +2054,8 @@ return ERR_PTR(-EOPNOTSUPP); } - size = nfsd_getxattr(fhp->fh_dentry, name, &value); + size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt, name, + &value); if (size < 0) return ERR_PTR(size); @@ -2048,6 +2067,7 @@ int nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl) { + struct vfsmount *mnt; struct inode *inode = fhp->fh_dentry->d_inode; char *name; void *value = NULL; @@ -2080,21 +2100,24 @@ } else size = 0; - error = mnt_want_write(fhp->fh_export->ex_path.mnt); + mnt = fhp->fh_export->ex_path.mnt; + error = mnt_want_write(mnt); if (error) goto getout; if (size) - error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0); + error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0, + NULL); else { if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT) error = 0; else { - error = vfs_removexattr(fhp->fh_dentry, name); + error = vfs_removexattr(fhp->fh_dentry, mnt, name, + NULL); if (error == -ENODATA) error = 0; } } - mnt_drop_write(fhp->fh_export->ex_path.mnt); + mnt_drop_write(mnt); getout: kfree(value); --- linux-2.6.27.orig/fs/hpfs/namei.c +++ linux-2.6.27/fs/hpfs/namei.c @@ -426,7 +426,7 @@ /*printk("HPFS: truncating file before delete.\n");*/ newattrs.ia_size = 0; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); + err = notify_change(dentry, NULL, &newattrs); put_write_access(inode); if (!err) goto again; --- linux-2.6.27.orig/fs/jffs2/background.c +++ linux-2.6.27/fs/jffs2/background.c @@ -85,15 +85,15 @@ for (;;) { allow_signal(SIGHUP); again: + spin_lock(&c->erase_completion_lock); if (!jffs2_thread_should_wake(c)) { set_current_state (TASK_INTERRUPTIBLE); + spin_unlock(&c->erase_completion_lock); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); - /* Yes, there's a race here; we checked jffs2_thread_should_wake() - before setting current->state to TASK_INTERRUPTIBLE. But it doesn't - matter - We don't care if we miss a wakeup, because the GC thread - is only an optimisation anyway. */ schedule(); - } + } else + spin_unlock(&c->erase_completion_lock); + /* This thread is purely an optimisation. But if it runs when other things could be running, it actually makes things a --- linux-2.6.27.orig/fs/jffs2/compr_lzo.c +++ linux-2.6.27/fs/jffs2/compr_lzo.c @@ -19,7 +19,7 @@ static void *lzo_mem; static void *lzo_compress_buf; -static DEFINE_MUTEX(deflate_mutex); +static DEFINE_MUTEX(deflate_mutex); /* for lzo_mem and lzo_compress_buf */ static void free_workspace(void) { @@ -49,18 +49,21 @@ mutex_lock(&deflate_mutex); ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); - mutex_unlock(&deflate_mutex); - if (ret != LZO_E_OK) - return -1; + goto fail; if (compress_size > *dstlen) - return -1; + goto fail; memcpy(cpage_out, lzo_compress_buf, compress_size); - *dstlen = compress_size; + mutex_unlock(&deflate_mutex); + *dstlen = compress_size; return 0; + + fail: + mutex_unlock(&deflate_mutex); + return -1; } static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, --- linux-2.6.27.orig/kernel/module.c +++ linux-2.6.27/kernel/module.c @@ -1173,7 +1173,7 @@ while (i-- > 0) sysfs_remove_bin_file(notes_attrs->dir, ¬es_attrs->attrs[i]); - kobject_del(notes_attrs->dir); + kobject_put(notes_attrs->dir); } kfree(notes_attrs); } --- linux-2.6.27.orig/kernel/sched_stats.h +++ linux-2.6.27/kernel/sched_stats.h @@ -9,7 +9,7 @@ static int show_schedstat(struct seq_file *seq, void *v) { int cpu; - int mask_len = NR_CPUS/32 * 9; + int mask_len = (NR_CPUS/32 + 1) * 9; char *mask_str = kmalloc(mask_len, GFP_KERNEL); if (mask_str == NULL) --- linux-2.6.27.orig/kernel/cgroup.c +++ linux-2.6.27/kernel/cgroup.c @@ -2443,7 +2443,6 @@ list_del(&cgrp->sibling); spin_lock(&cgrp->dentry->d_lock); d = dget(cgrp->dentry); - cgrp->dentry = NULL; spin_unlock(&d->d_lock); cgroup_d_remove_dir(d); @@ -2905,7 +2904,7 @@ } /* Create the cgroup directory, which also creates the cgroup */ - ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755); + ret = vfs_mkdir(inode, dentry, NULL, S_IFDIR | 0755); child = __d_cgrp(dentry); dput(dentry); if (ret) { --- linux-2.6.27.orig/kernel/sched_features.h +++ linux-2.6.27/kernel/sched_features.h @@ -5,7 +5,7 @@ SCHED_FEAT(AFFINE_WAKEUPS, 1) SCHED_FEAT(CACHE_HOT_BUDDY, 1) SCHED_FEAT(SYNC_WAKEUPS, 1) -SCHED_FEAT(HRTICK, 1) +SCHED_FEAT(HRTICK, 0) SCHED_FEAT(DOUBLE_TICK, 0) SCHED_FEAT(ASYM_GRAN, 1) SCHED_FEAT(LB_BIAS, 1) --- linux-2.6.27.orig/kernel/audit.c +++ linux-2.6.27/kernel/audit.c @@ -1231,8 +1231,7 @@ * will be called a second time. Currently, we assume that a printk * can't format message larger than 1024 bytes, so we don't either. */ -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, - va_list args) +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args) { int len, avail; struct sk_buff *skb; @@ -1506,3 +1505,6 @@ EXPORT_SYMBOL(audit_log_end); EXPORT_SYMBOL(audit_log_format); EXPORT_SYMBOL(audit_log); +EXPORT_SYMBOL_GPL(audit_log_vformat); +EXPORT_SYMBOL_GPL(audit_log_untrustedstring); +EXPORT_SYMBOL_GPL(audit_log_d_path); --- linux-2.6.27.orig/kernel/sched_rt.c +++ linux-2.6.27/kernel/sched_rt.c @@ -102,12 +102,12 @@ static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) { + struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; struct sched_rt_entity *rt_se = rt_rq->rt_se; - if (rt_se && !on_rt_rq(rt_se) && rt_rq->rt_nr_running) { - struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; - - enqueue_rt_entity(rt_se); + if (rt_rq->rt_nr_running) { + if (rt_se && !on_rt_rq(rt_se)) + enqueue_rt_entity(rt_se); if (rt_rq->highest_prio < curr->prio) resched_task(curr); } --- linux-2.6.27.orig/kernel/sched_clock.c +++ linux-2.6.27/kernel/sched_clock.c @@ -118,13 +118,13 @@ /* * scd->clock = clamp(scd->tick_gtod + delta, - * max(scd->tick_gtod, scd->clock), - * scd->tick_gtod + TICK_NSEC); + * max(scd->tick_gtod, scd->clock), + * max(scd->clock, scd->tick_gtod + TICK_NSEC)); */ clock = scd->tick_gtod + delta; min_clock = wrap_max(scd->tick_gtod, scd->clock); - max_clock = scd->tick_gtod + TICK_NSEC; + max_clock = wrap_max(scd->clock, scd->tick_gtod + TICK_NSEC); clock = wrap_max(clock, min_clock); clock = wrap_min(clock, max_clock); --- linux-2.6.27.orig/kernel/sysctl.c +++ linux-2.6.27/kernel/sysctl.c @@ -1506,6 +1506,33 @@ spin_unlock(&sysctl_lock); } +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen) +{ + if (buflen < 1) + return NULL; + buffer += --buflen; + *buffer = '\0'; + + while (table) { + int namelen = strlen(table->procname); + + if (buflen < namelen + 1) + return NULL; + buflen -= namelen + 1; + buffer -= namelen; + memcpy(buffer, table->procname, namelen); + *--buffer = '/'; + table = table->parent; + } + if (buflen < 4) + return NULL; + buffer -= 4; + memcpy(buffer, "/sys", 4); + + return buffer; +} +EXPORT_SYMBOL_GPL(sysctl_pathname); + #ifdef CONFIG_SYSCTL_SYSCALL /* Perform the actual read/write of a sysctl table entry. */ static int do_sysctl_strategy(struct ctl_table_root *root, --- linux-2.6.27.orig/kernel/power/console.c +++ linux-2.6.27/kernel/power/console.c @@ -33,6 +33,7 @@ int pm_prepare_console(void) { +#ifndef CONFIG_PM_DISABLE_CONSOLE acquire_console_sem(); if (disable_vt_switch) { @@ -66,11 +67,13 @@ } orig_kmsg = kmsg_redirect; kmsg_redirect = SUSPEND_CONSOLE; +#endif return 0; } void pm_restore_console(void) { +#ifndef CONFIG_PM_DISABLE_CONSOLE acquire_console_sem(); if (disable_vt_switch) { release_console_sem(); @@ -79,5 +82,6 @@ set_console(orig_fgconsole); release_console_sem(); kmsg_redirect = orig_kmsg; +#endif } #endif --- linux-2.6.27.orig/kernel/power/Kconfig +++ linux-2.6.27/kernel/power/Kconfig @@ -116,6 +116,21 @@ Turning OFF this setting is NOT recommended! If in doubt, say Y. +config PM_DISABLE_CONSOLE + bool "Disable Power Management messing with the active console" + depends on PM + default n + ---help--- + By default, PM will take over the active console (generally, this means + switching to the console when suspending from X). This can at times cause + problems, especially if userspace suspend scripts try to do things with + the console before or after suspending (e.g. calling vbestate). + + To work around this, enable this option so that PM will not handle the + console. + + If unsure, say N. + config HIBERNATION bool "Hibernation (aka 'suspend to disk')" depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE --- linux-2.6.27.orig/kernel/trace/Kconfig +++ linux-2.6.27/kernel/trace/Kconfig @@ -103,7 +103,8 @@ all switching of tasks. config DYNAMIC_FTRACE - bool "enable/disable ftrace tracepoints dynamically" + bool "enable/disable ftrace tracepoints dynamically (BROKEN)" + depends on BROKEN depends on FTRACE depends on HAVE_DYNAMIC_FTRACE default y --- linux-2.6.27.orig/Documentation/kernel-parameters.txt +++ linux-2.6.27/Documentation/kernel-parameters.txt @@ -179,6 +179,9 @@ acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT + acpi_no_initrd_override [KNL,ACPI] + Disable loading custom ACPI tables from the initramfs + acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS Format: To spoof as Windows 98: ="Microsoft Windows" --- linux-2.6.27.orig/Documentation/cciss.txt +++ linux-2.6.27/Documentation/cciss.txt @@ -26,6 +26,8 @@ * SA P410i * SA P411 * SA P812 + * SA P712m + * SA P711m Detecting drive failures: ------------------------- --- linux-2.6.27.orig/Documentation/acpi/dsdt-override.txt +++ linux-2.6.27/Documentation/acpi/dsdt-override.txt @@ -1,7 +1,15 @@ -Linux supports a method of overriding the BIOS DSDT: +Linux supports two methods of overriding the BIOS DSDT: CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel. -When to use this method is described in detail on the +CONFIG_ACPI_CUSTOM_DSDT_INITRD adds the image to the initrd. + +When to use these methods is described in detail on the Linux/ACPI home page: http://www.lesswatts.org/projects/acpi/overridingDSDT.php + +Note that if both options are used, the DSDT supplied +by the INITRD method takes precedence. + +Documentation/initramfs-add-dsdt.sh is provided for convenience +for use with the CONFIG_ACPI_CUSTOM_DSDT_INITRD method. --- linux-2.6.27.orig/Documentation/acpi/initramfs-add-dsdt.sh +++ linux-2.6.27/Documentation/acpi/initramfs-add-dsdt.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Adds a DSDT file to the initrd (if it's an initramfs) +# first argument is the name of archive +# second argument is the name of the file to add +# The file will be copied as /DSDT.aml + +# 20060126: fix "Premature end of file" with some old cpio (Roland Robic) +# 20060205: this time it should really work + +# check the arguments +if [ $# -ne 2 ]; then + program_name=$(basename $0) + echo "\ +$program_name: too few arguments +Usage: $program_name initrd-name.img DSDT-to-add.aml +Adds a DSDT file to an initrd (in initramfs format) + + initrd-name.img: filename of the initrd in initramfs format + DSDT-to-add.aml: filename of the DSDT file to add + " 1>&2 + exit 1 +fi + +# we should check it's an initramfs + +tempcpio=$(mktemp -d) +# cleanup on exit, hangup, interrupt, quit, termination +trap 'rm -rf $tempcpio' 0 1 2 3 15 + +# extract the archive +gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1 + +# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml" +cp -f "$2" "$tempcpio"/DSDT.aml + +# add the file +cd "$tempcpio" +(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1 +cd "$OLDPWD" + +# re-compress the archive +gzip -c "$tempcpio"/initramfs.cpio > "$1" + --- linux-2.6.27.orig/Documentation/video4linux/CARDLIST.au0828 +++ linux-2.6.27/Documentation/video4linux/CARDLIST.au0828 @@ -1,5 +1,5 @@ 0 -> Unknown board (au0828) - 1 -> Hauppauge HVR950Q (au0828) [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008] + 1 -> Hauppauge HVR950Q (au0828) [2040:7200,2040:7210,2040:7217,2040:721b,2040:721e,2040:721f,2040:7280,0fd9:0008] 2 -> Hauppauge HVR850 (au0828) [2040:7240] 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620] 4 -> Hauppauge HVR950Q rev xxF8 (au0828) [2040:7201,2040:7211,2040:7281] --- linux-2.6.27.orig/Documentation/networking/README.ipw2200 +++ linux-2.6.27/Documentation/networking/README.ipw2200 @@ -147,7 +147,7 @@ driver. If disabled, the driver will not attempt to scan for and associate to a network until it has been configured with one or more properties for the target network, for example configuring - the network SSID. Default is 1 (auto-associate) + the network SSID. Default is 0 (do not auto-associate) Example: % modprobe ipw2200 associate=0 --- linux-2.6.27.orig/Documentation/i2c/busses/i2c-sis96x +++ linux-2.6.27/Documentation/i2c/busses/i2c-sis96x @@ -42,7 +42,7 @@ chipsets as well: 635, and 635T. If anyone owns a board with those chips AND is willing to risk crashing & burning an otherwise well-behaved kernel in the name of progress... please contact me at or -via the project's mailing list: . Please send bug +via the linux-i2c mailing list: . Please send bug reports and/or success stories as well. --- linux-2.6.27.orig/sound/pci/hda/hda_intel.c +++ linux-2.6.27/sound/pci/hda/hda_intel.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include "hda_codec.h" @@ -385,6 +386,9 @@ /* for pending irqs */ struct work_struct irq_pending_work; + + /* reboot notifier (for mysterious hangup problem at power-down) */ + struct notifier_block reboot_notifier; }; /* driver types */ @@ -1890,12 +1894,36 @@ /* + * reboot notifier for hang-up problem at power-down + */ +static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) +{ + struct azx *chip = container_of(nb, struct azx, reboot_notifier); + azx_stop_chip(chip); + return NOTIFY_OK; +} + +static void azx_notifier_register(struct azx *chip) +{ + chip->reboot_notifier.notifier_call = azx_halt; + register_reboot_notifier(&chip->reboot_notifier); +} + +static void azx_notifier_unregister(struct azx *chip) +{ + if (chip->reboot_notifier.notifier_call) + unregister_reboot_notifier(&chip->reboot_notifier); +} + +/* * destructor */ static int azx_free(struct azx *chip) { int i; + azx_notifier_unregister(chip); + if (chip->initialized) { azx_clear_irq_pending(chip); for (i = 0; i < chip->num_streams; i++) @@ -2250,6 +2278,7 @@ pci_set_drvdata(pci, card); chip->running = 1; power_down_all_codecs(chip); + azx_notifier_register(chip); dev++; return err; --- linux-2.6.27.orig/sound/pci/hda/patch_sigmatel.c +++ linux-2.6.27/sound/pci/hda/patch_sigmatel.c @@ -67,6 +67,7 @@ enum { STAC_92HD73XX_REF, STAC_DELL_M6, + STAC_DELL_EQ, STAC_92HD73XX_MODELS }; @@ -560,9 +561,7 @@ }; static struct hda_verb dell_m6_core_init[] = { - /* set master volume to max value without distortion - * and direct control */ - { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, + { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, /* setup audio connections */ { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, @@ -1297,11 +1296,13 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, [STAC_DELL_M6] = dell_m6_pin_configs, + [STAC_DELL_EQ] = dell_m6_pin_configs, }; static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_REF] = "ref", [STAC_DELL_M6] = "dell-m6", + [STAC_DELL_EQ] = "dell-eq", }; static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { @@ -3560,8 +3561,12 @@ spec->gpio_data = 0x01; switch (spec->board_config) { - case STAC_DELL_M6: + case STAC_DELL_EQ: spec->init = dell_eq_core_init; + /* fallthru */ + case STAC_DELL_M6: + if (!spec->init) + spec->init = dell_m6_core_init; switch (codec->subsystem_id) { case 0x1028025e: /* Analog Mics */ case 0x1028025f: @@ -3570,8 +3575,6 @@ break; case 0x10280271: /* Digital Mics */ case 0x10280272: - spec->init = dell_m6_core_init; - /* fall-through */ case 0x10280254: case 0x10280255: stac92xx_set_config_reg(codec, 0x13, 0x90A60160); --- linux-2.6.27.orig/sound/pci/hda/patch_realtek.c +++ linux-2.6.27/sound/pci/hda/patch_realtek.c @@ -7950,6 +7950,7 @@ SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1043, 0x8284, "ASUS Z37E", ALC883_6ST_DIG), SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC), @@ -9769,6 +9770,7 @@ SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), + SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO), SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000), SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), --- linux-2.6.27.orig/sound/core/control.c +++ linux-2.6.27/sound/core/control.c @@ -1427,12 +1427,12 @@ cardnum = card->number; snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); - down_read(&card->controls_rwsem); + read_lock(&card->ctl_files_rwlock); list_for_each_entry(ctl, &card->ctl_files, list) { wake_up(&ctl->change_sleep); kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); } - up_read(&card->controls_rwsem); + read_unlock(&card->ctl_files_rwlock); if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1)) < 0) --- linux-2.6.27.orig/mm/internal.h +++ linux-2.6.27/mm/internal.h @@ -17,6 +17,7 @@ unsigned long floor, unsigned long ceiling); extern void prep_compound_page(struct page *page, unsigned long order); +extern void prep_compound_gigantic_page(struct page *page, unsigned long order); static inline void set_page_count(struct page *page, int v) { @@ -53,6 +54,34 @@ } /* + * Return the mem_map entry representing the 'offset' subpage within + * the maximally aligned gigantic page 'base'. Handle any discontiguity + * in the mem_map at MAX_ORDER_NR_PAGES boundaries. + */ +static inline struct page *mem_map_offset(struct page *base, int offset) +{ + if (unlikely(offset >= MAX_ORDER_NR_PAGES)) + return pfn_to_page(page_to_pfn(base) + offset); + return base + offset; +} + +/* + * Iterator over all subpages withing the maximally aligned gigantic + * page 'base'. Handle any discontiguity in the mem_map. + */ +static inline struct page *mem_map_next(struct page *iter, + struct page *base, int offset) +{ + if (unlikely((offset & (MAX_ORDER_NR_PAGES - 1)) == 0)) { + unsigned long pfn = page_to_pfn(base) + offset; + if (!pfn_valid(pfn)) + return NULL; + return pfn_to_page(pfn); + } + return iter + 1; +} + +/* * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node, * so all functions starting at paging_init should be marked __init * in those cases. SPARSEMEM, however, allows for memory hotplug, --- linux-2.6.27.orig/mm/page_alloc.c +++ linux-2.6.27/mm/page_alloc.c @@ -268,24 +268,39 @@ { int i; int nr_pages = 1 << order; + + set_compound_page_dtor(page, free_compound_page); + set_compound_order(page, order); + __SetPageHead(page); + for (i = 1; i < nr_pages; i++) { + struct page *p = page + i; + + __SetPageTail(p); + p->first_page = page; + } +} + +#ifdef CONFIG_HUGETLBFS +void prep_compound_gigantic_page(struct page *page, unsigned long order) +{ + int i; + int nr_pages = 1 << order; struct page *p = page + 1; set_compound_page_dtor(page, free_compound_page); set_compound_order(page, order); __SetPageHead(page); - for (i = 1; i < nr_pages; i++, p++) { - if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) - p = pfn_to_page(page_to_pfn(page) + i); + for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) { __SetPageTail(p); p->first_page = page; } } +#endif static void destroy_compound_page(struct page *page, unsigned long order) { int i; int nr_pages = 1 << order; - struct page *p = page + 1; if (unlikely(compound_order(page) != order)) bad_page(page); @@ -293,9 +308,8 @@ if (unlikely(!PageHead(page))) bad_page(page); __ClearPageHead(page); - for (i = 1; i < nr_pages; i++, p++) { - if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) - p = pfn_to_page(page_to_pfn(page) + i); + for (i = 1; i < nr_pages; i++) { + struct page *p = page + i; if (unlikely(!PageTail(p) | (p->first_page != page))) --- linux-2.6.27.orig/mm/swapfile.c +++ linux-2.6.27/mm/swapfile.c @@ -286,6 +286,8 @@ swap_list.next = p - swap_info; nr_swap_pages++; p->inuse_pages--; + if (p->notify_swap_entry_free_fn) + p->notify_swap_entry_free_fn(offset); } } return count; @@ -1799,6 +1801,23 @@ } /* + * Sets callback for event when swap_map[offset] == 0 + * i.e. page at this swap offset is not longer used. + * + * type: identifies swap file + * fn: callback function + */ +void set_notify_swap_entry_free(unsigned type, void (*fn) (unsigned long)) +{ + struct swap_info_struct *sis; + sis = get_swap_info_struct(type); + BUG_ON(!sis); + sis->notify_swap_entry_free_fn = fn; + return; +} +EXPORT_SYMBOL(set_notify_swap_entry_free); + +/* * swap_lock prevents swap_map being freed. Don't grab an extra * reference on the swaphandle, it doesn't matter if it becomes unused. */ --- linux-2.6.27.orig/mm/rmap.c +++ linux-2.6.27/mm/rmap.c @@ -55,7 +55,33 @@ struct kmem_cache *anon_vma_cachep; -/* This must be called under the mmap_sem. */ +/** + * anon_vma_prepare - attach an anon_vma to a memory region + * @vma: the memory region in question + * + * This makes sure the memory mapping described by 'vma' has + * an 'anon_vma' attached to it, so that we can associate the + * anonymous pages mapped into it with that anon_vma. + * + * The common case will be that we already have one, but if + * if not we either need to find an adjacent mapping that we + * can re-use the anon_vma from (very common when the only + * reason for splitting a vma has been mprotect()), or we + * allocate a new one. + * + * Anon-vma allocations are very subtle, because we may have + * optimistically looked up an anon_vma in page_lock_anon_vma() + * and that may actually touch the spinlock even in the newly + * allocated vma (it depends on RCU to make sure that the + * anon_vma isn't actually destroyed). + * + * As a result, we need to do proper anon_vma locking even + * for the new allocation. At the same time, we do not want + * to do any locking for the common case of already having + * an anon_vma. + * + * This must be called with the mmap_sem held for reading. + */ int anon_vma_prepare(struct vm_area_struct *vma) { struct anon_vma *anon_vma = vma->anon_vma; @@ -63,20 +89,17 @@ might_sleep(); if (unlikely(!anon_vma)) { struct mm_struct *mm = vma->vm_mm; - struct anon_vma *allocated, *locked; + struct anon_vma *allocated; anon_vma = find_mergeable_anon_vma(vma); - if (anon_vma) { - allocated = NULL; - locked = anon_vma; - spin_lock(&locked->lock); - } else { + allocated = NULL; + if (!anon_vma) { anon_vma = anon_vma_alloc(); if (unlikely(!anon_vma)) return -ENOMEM; allocated = anon_vma; - locked = NULL; } + spin_lock(&anon_vma->lock); /* page_table_lock to protect against threads */ spin_lock(&mm->page_table_lock); @@ -87,8 +110,7 @@ } spin_unlock(&mm->page_table_lock); - if (locked) - spin_unlock(&locked->lock); + spin_unlock(&anon_vma->lock); if (unlikely(allocated)) anon_vma_free(allocated); } --- linux-2.6.27.orig/mm/filemap.c +++ linux-2.6.27/mm/filemap.c @@ -1760,12 +1760,12 @@ } EXPORT_SYMBOL(should_remove_suid); -static int __remove_suid(struct dentry *dentry, int kill) +static int __remove_suid(struct path *path, int kill) { struct iattr newattrs; newattrs.ia_valid = ATTR_FORCE | kill; - return notify_change(dentry, &newattrs); + return notify_change(path->dentry, path->mnt, &newattrs); } int file_remove_suid(struct file *file) @@ -1780,7 +1780,7 @@ if (killpriv) error = security_inode_killpriv(dentry); if (!error && killsuid) - error = __remove_suid(dentry, killsuid); + error = __remove_suid(&file->f_path, killsuid); return error; } --- linux-2.6.27.orig/mm/hugetlb.c +++ linux-2.6.27/mm/hugetlb.c @@ -353,11 +353,26 @@ return 0; } +static void clear_gigantic_page(struct page *page, + unsigned long addr, unsigned long sz) +{ + int i; + struct page *p = page; + + might_sleep(); + for (i = 0; i < sz/PAGE_SIZE; i++, p = mem_map_next(p, page, i)) { + cond_resched(); + clear_user_highpage(p, addr + i * PAGE_SIZE); + } +} static void clear_huge_page(struct page *page, unsigned long addr, unsigned long sz) { int i; + if (unlikely(sz > MAX_ORDER_NR_PAGES)) + return clear_gigantic_page(page, addr, sz); + might_sleep(); for (i = 0; i < sz/PAGE_SIZE; i++) { cond_resched(); @@ -365,12 +380,32 @@ } } +static void copy_gigantic_page(struct page *dst, struct page *src, + unsigned long addr, struct vm_area_struct *vma) +{ + int i; + struct hstate *h = hstate_vma(vma); + struct page *dst_base = dst; + struct page *src_base = src; + might_sleep(); + for (i = 0; i < pages_per_huge_page(h); ) { + cond_resched(); + copy_user_highpage(dst, src, addr + i*PAGE_SIZE, vma); + + i++; + dst = mem_map_next(dst, dst_base, i); + src = mem_map_next(src, src_base, i); + } +} static void copy_huge_page(struct page *dst, struct page *src, unsigned long addr, struct vm_area_struct *vma) { int i; struct hstate *h = hstate_vma(vma); + if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) + return copy_gigantic_page(dst, src, addr, vma); + might_sleep(); for (i = 0; i < pages_per_huge_page(h); i++) { cond_resched(); @@ -455,6 +490,8 @@ { int i; + VM_BUG_ON(h->order >= MAX_ORDER); + h->nr_huge_pages--; h->nr_huge_pages_node[page_to_nid(page)]--; for (i = 0; i < pages_per_huge_page(h); i++) { @@ -969,6 +1006,14 @@ return 1; } +static void prep_compound_huge_page(struct page *page, int order) +{ + if (unlikely(order > (MAX_ORDER - 1))) + prep_compound_gigantic_page(page, order); + else + prep_compound_page(page, order); +} + /* Put bootmem huge pages into the standard lists after mem_map is up */ static void __init gather_bootmem_prealloc(void) { @@ -979,7 +1024,7 @@ struct hstate *h = m->hstate; __ClearPageReserved(page); WARN_ON(page_count(page) != 1); - prep_compound_page(page, h->order); + prep_compound_huge_page(page, h->order); prep_new_huge_page(h, page, page_to_nid(page)); } } @@ -2103,7 +2148,7 @@ same_page: if (pages) { get_page(page); - pages[i] = page + pfn_offset; + pages[i] = mem_map_offset(page, pfn_offset); } if (vmas) --- linux-2.6.27.orig/ipc/mqueue.c +++ linux-2.6.27/ipc/mqueue.c @@ -745,7 +745,7 @@ err = mnt_want_write(mqueue_mnt); if (err) goto out_err; - err = vfs_unlink(dentry->d_parent->d_inode, dentry); + err = vfs_unlink(dentry->d_parent->d_inode, dentry, mqueue_mnt); mnt_drop_write(mqueue_mnt); out_err: dput(dentry); --- linux-2.6.27.orig/include/linux/connector.h +++ linux-2.6.27/include/linux/connector.h @@ -39,8 +39,10 @@ #define CN_IDX_V86D 0x4 #define CN_VAL_V86D_UVESAFB 0x1 #define CN_IDX_BB 0x5 /* BlackBoard, from the TSP GPL sampling framework */ +#define CN_IDX_DRBD 0x6 +#define CN_VAL_DRBD 0x1 -#define CN_NETLINK_USERS 6 +#define CN_NETLINK_USERS 7 /* * Maximum connector's message size. --- linux-2.6.27.orig/include/linux/mount.h +++ linux-2.6.27/include/linux/mount.h @@ -114,4 +114,6 @@ extern spinlock_t vfsmount_lock; extern dev_t name_to_dev_t(char *name); +extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int); + #endif /* _LINUX_MOUNT_H */ --- linux-2.6.27.orig/include/linux/splice.h +++ linux-2.6.27/include/linux/splice.h @@ -71,4 +71,10 @@ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, splice_direct_actor *); +extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags); +extern long do_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); + #endif --- linux-2.6.27.orig/include/linux/audit.h +++ linux-2.6.27/include/linux/audit.h @@ -33,7 +33,7 @@ * 1200 - 1299 messages internal to the audit daemon * 1300 - 1399 audit event messages * 1400 - 1499 SE Linux use - * 1500 - 1599 kernel LSPP events + * 1500 - 1599 AppArmor use * 1600 - 1699 kernel crypto events * 1700 - 1799 kernel anomaly records * 1800 - 1999 future kernel use (maybe integrity labels and related events) @@ -119,6 +119,13 @@ #define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */ #define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */ +#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */ +#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */ +#define AUDIT_APPARMOR_DENIED 1503 +#define AUDIT_APPARMOR_HINT 1504 /* Process Tracking information */ +#define AUDIT_APPARMOR_STATUS 1505 /* Changes in config */ +#define AUDIT_APPARMOR_ERROR 1506 /* Internal AppArmor Errors */ + #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG 1799 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ @@ -545,6 +552,9 @@ __attribute__((format(printf,4,5))); extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type); +extern void audit_log_vformat(struct audit_buffer *ab, + const char *fmt, va_list args) + __attribute__((format(printf,2,0))); extern void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) __attribute__((format(printf,2,3))); --- linux-2.6.27.orig/include/linux/swap.h +++ linux-2.6.27/include/linux/swap.h @@ -149,6 +149,7 @@ unsigned int max; unsigned int inuse_pages; int next; /* next entry on swap list */ + void (*notify_swap_entry_free_fn) (unsigned long); }; struct swap_list_t { @@ -251,6 +252,7 @@ extern struct swap_info_struct *get_swap_info_struct(unsigned); extern int can_share_swap_page(struct page *); extern int remove_exclusive_swap_page(struct page *); +extern void set_notify_swap_entry_free(unsigned, void (*) (unsigned long)); struct backing_dev_info; /* linux/mm/thrash.c */ --- linux-2.6.27.orig/include/linux/dcache.h +++ linux-2.6.27/include/linux/dcache.h @@ -299,9 +299,12 @@ /* * helper function for dentry_operations.d_dname() members */ +#define D_PATH_FAIL_DELETED 1 +#define D_PATH_DISCONNECT 2 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); -extern char *__d_path(const struct path *path, struct path *root, char *, int); +extern char *__d_path(const struct path *path, struct path *root, char *, int, + int); extern char *d_path(const struct path *, char *, int); extern char *dentry_path(struct dentry *, char *, int); --- linux-2.6.27.orig/include/linux/aufs_type.h +++ linux-2.6.27/include/linux/aufs_type.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* $Id: aufs_type.h,v 1.124 2008/09/22 03:52:19 sfjro Exp $ */ + +#include + +#ifndef __AUFS_TYPE_H__ +#define __AUFS_TYPE_H__ + +#define AUFS_VERSION "20080922" + +/* move this to linux-2.6.19/include/magic.h */ +#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_BRANCH_MAX_127 +/* some environments treat 'char' as 'unsigned char' by default */ +typedef signed char aufs_bindex_t; +#define AUFS_BRANCH_MAX 127 +#else +typedef short aufs_bindex_t; +#ifdef CONFIG_AUFS_BRANCH_MAX_511 +#define AUFS_BRANCH_MAX 511 +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) +#define AUFS_BRANCH_MAX 1023 +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) +#define AUFS_BRANCH_MAX 32767 +#else +#error unknown CONFIG_AUFS_BRANCH_MAX value +#endif +#endif + +#define AUFS_NAME "aufs" +#define AUFS_FSTYPE AUFS_NAME + +#define AUFS_ROOT_INO 2 +#define AUFS_FIRST_INO 11 + +#define AUFS_WH_PFX ".wh." +#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) +#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" +#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME +#define AUFS_XINO_TRUNC_INIT 64 /* blocks */ +#define AUFS_XINO_TRUNC_STEP 4 /* blocks */ +#define AUFS_DIRWH_DEF 3 +#define AUFS_RDCACHE_DEF 10 /* seconds */ +#define AUFS_WKQ_NAME AUFS_NAME "d" +#define AUFS_NWKQ_DEF 4 +#define AUFS_MFS_SECOND_DEF 30 /* seconds */ +#define AUFS_PLINK_WARN 100 /* number of plinks */ + +#ifdef CONFIG_AUFS_COMPAT +#define AUFS_DIROPQ_NAME "__dir_opaque" +#else +#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ +#endif +#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME + +/* will be whiteouted doubly */ +#define AUFS_WH_BASENAME AUFS_WH_PFX AUFS_NAME +#define AUFS_WH_PLINKDIR AUFS_WH_PFX "plnk" +#define AUFS_WH_TMPDIR AUFS_WH_PFX ".tmp" + +/* ---------------------------------------------------------------------- */ + +/* ioctl */ +#if 0 /* reserved for future use */ +enum { + AuCtlErr, + AuCtlErr_Last +}; +enum { + AuCtl_REFRESH, AuCtl_REFRESHV, + AuCtl_FLUSH_PLINK, + AuCtl_CPUP, + AuCtl_CPDOWN, AuCtl_MVDOWN, + AuCtl_DIROPQ +}; + +struct aufs_ctl_cp { + int bsrc, bdst; + int err; +}; + +#define AuCtlType 'A' +#define AUFS_CTL_REFRESH _IO(AuCtlType, AuCtl_REFRESH) +#define AUFS_CTL_REFRESHV _IO(AuCtlType, AuCtl_REFRESHV) +#define AUFS_CTL_FLUSH_PLINK _IOR(AuCtlType, AuCtl_FLUSH_PLINK) +#define AUFS_CTL_CPUP _IOWR(AuCtlType, AuCtl_CPUP, struct aufs_ctl_cp) +#define AUFS_CTL_CPDOWN \ + _IOWR(AuCtlType, AuCtl_CPDOWN, struct aufs_ctl_cp) +#define AUFS_CTL_MVDOWN \ + _IOWR(AuCtlType, AuCtl_MVDOWN, struct aufs_ctl_cp) +#define AUFS_CTL_DIROPQ _IO(AuCtlType, AuCtl_DIROPQ) +#endif + +#endif /* __AUFS_TYPE_H__ */ --- linux-2.6.27.orig/include/linux/namei.h +++ linux-2.6.27/include/linux/namei.h @@ -80,6 +80,8 @@ extern struct dentry *lock_rename(struct dentry *, struct dentry *); extern void unlock_rename(struct dentry *, struct dentry *); +struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd); + static inline void nd_set_link(struct nameidata *nd, char *path) { nd->saved_names[nd->depth] = path; --- linux-2.6.27.orig/include/linux/sched.h +++ linux-2.6.27/include/linux/sched.h @@ -1286,7 +1286,9 @@ atomic_t fs_excl; /* holding fs exclusive resources */ struct rcu_head rcu; - /* + struct list_head *scm_work_list; + +/* * cache last used pipe for splice */ struct pipe_inode_info *splice_pipe; --- linux-2.6.27.orig/include/linux/xattr.h +++ linux-2.6.27/include/linux/xattr.h @@ -16,6 +16,8 @@ #ifdef __KERNEL__ #include +#include +#include /* Namespaces */ #define XATTR_OS2_PREFIX "os2." @@ -47,10 +49,10 @@ }; ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t); -ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); -ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); -int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int); -int vfs_removexattr(struct dentry *, const char *); +ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t, struct file *file); +ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size, struct file *file); +int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int, struct file *file); +int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *, struct file *file); ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size); ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); --- linux-2.6.27.orig/include/linux/security.h +++ linux-2.6.27/include/linux/security.h @@ -54,9 +54,11 @@ extern int cap_bprm_set_security(struct linux_binprm *bprm); extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe); extern int cap_bprm_secureexec(struct linux_binprm *bprm); -extern int cap_inode_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); -extern int cap_inode_removexattr(struct dentry *dentry, const char *name); +extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, size_t size, + int flags, struct file *file); +extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file); extern int cap_inode_need_killpriv(struct dentry *dentry); extern int cap_inode_killpriv(struct dentry *dentry); extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags); @@ -337,23 +339,28 @@ * Check permission to create a regular file. * @dir contains inode structure of the parent of the new file. * @dentry contains the dentry structure for the file to be created. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @mode contains the file mode of the file to be created. * Return 0 if permission is granted. * @inode_link: * Check permission before creating a new hard link to a file. * @old_dentry contains the dentry structure for an existing link to the file. + * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL). * @dir contains the inode structure of the parent directory of the new link. * @new_dentry contains the dentry structure for the new link. + * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL). * Return 0 if permission is granted. * @inode_unlink: * Check the permission to remove a hard link to a file. * @dir contains the inode structure of parent directory of the file. * @dentry contains the dentry structure for file to be unlinked. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * Return 0 if permission is granted. * @inode_symlink: * Check the permission to create a symbolic link to a file. * @dir contains the inode structure of parent directory of the symbolic link. * @dentry contains the dentry structure of the symbolic link. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @old_name contains the pathname of file. * Return 0 if permission is granted. * @inode_mkdir: @@ -361,12 +368,14 @@ * associated with inode strcture @dir. * @dir containst the inode structure of parent of the directory to be created. * @dentry contains the dentry structure of new directory. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @mode contains the mode of new directory. * Return 0 if permission is granted. * @inode_rmdir: * Check the permission to remove a directory. * @dir contains the inode structure of parent of the directory to be removed. * @dentry contains the dentry structure of directory to be removed. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * Return 0 if permission is granted. * @inode_mknod: * Check permissions when creating a special file (or a socket or a fifo @@ -375,6 +384,7 @@ * and not this hook. * @dir contains the inode structure of parent of the new file. * @dentry contains the dentry structure of the new file. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @mode contains the mode of the new file. * @dev contains the device number. * Return 0 if permission is granted. @@ -382,12 +392,15 @@ * Check for permission to rename a file or directory. * @old_dir contains the inode structure for parent of the old link. * @old_dentry contains the dentry structure of the old link. + * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL). * @new_dir contains the inode structure for parent of the new link. * @new_dentry contains the dentry structure of the new link. + * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL). * Return 0 if permission is granted. * @inode_readlink: * Check the permission to read the symbolic link. * @dentry contains the dentry structure for the file link. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * Return 0 if permission is granted. * @inode_follow_link: * Check permission to follow a symbolic link when looking up a pathname. @@ -411,6 +424,7 @@ * file attributes change (such as when a file is truncated, chown/chmod * operations, transferring disk quotas, etc). * @dentry contains the dentry structure for the file. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @attr is the iattr structure containing the new file attributes. * Return 0 if permission is granted. * @inode_getattr: @@ -426,18 +440,18 @@ * inode. * @inode_setxattr: * Check permission before setting the extended attributes - * @value identified by @name for @dentry. + * @value identified by @name for @dentry and @mnt. * Return 0 if permission is granted. * @inode_post_setxattr: * Update inode security field after successful setxattr operation. - * @value identified by @name for @dentry. + * @value identified by @name for @dentry and @mnt. * @inode_getxattr: * Check permission before obtaining the extended attributes - * identified by @name for @dentry. + * identified by @name for @dentry and @mnt. * Return 0 if permission is granted. * @inode_listxattr: * Check permission before obtaining the list of extended attribute - * names for @dentry. + * names for @dentry and @mnt. * Return 0 if permission is granted. * @inode_removexattr: * Check permission before removing the extended attribute @@ -578,6 +592,20 @@ * file_permission, and recheck access if anything has changed * since inode_permission. * + * Security hook for path + * + * @path_permission: + * Check permission before accessing a path. This hook is called by the + * existing Linux permission function, so a security module can use it to + * provide additional checking for existing Linux permission checks. + * Notice that this hook is called when a file is opened (as well as many + * other operations), whereas the file_security_ops permission hook is + * called when the actual read/write operations are performed. This + * hook is optional and if absent, inode_permission will be substituted. + * @path contains the path structure to check. + * @mask contains the permission mask. + * Return 0 if permission is granted. + * Security hooks for task operations. * * @task_create: @@ -1354,32 +1382,45 @@ void (*inode_free_security) (struct inode *inode); int (*inode_init_security) (struct inode *inode, struct inode *dir, char **name, void **value, size_t *len); - int (*inode_create) (struct inode *dir, - struct dentry *dentry, int mode); - int (*inode_link) (struct dentry *old_dentry, - struct inode *dir, struct dentry *new_dentry); - int (*inode_unlink) (struct inode *dir, struct dentry *dentry); - int (*inode_symlink) (struct inode *dir, - struct dentry *dentry, const char *old_name); - int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode); - int (*inode_rmdir) (struct inode *dir, struct dentry *dentry); + int (*inode_create) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode); + int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt, + struct inode *dir, struct dentry *new_dentry, + struct vfsmount *new_mnt); + int (*inode_unlink) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt); + int (*inode_symlink) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *old_name); + int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode); + int (*inode_rmdir) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt); int (*inode_mknod) (struct inode *dir, struct dentry *dentry, - int mode, dev_t dev); + struct vfsmount *mnt, int mode, dev_t dev); int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry); - int (*inode_readlink) (struct dentry *dentry); + struct vfsmount *old_mnt, + struct inode *new_dir, struct dentry *new_dentry, + struct vfsmount *new_mnt); + int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt); int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); int (*inode_permission) (struct inode *inode, int mask); - int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); + int (*inode_setattr) (struct dentry *dentry, struct vfsmount *, + struct iattr *attr); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); void (*inode_delete) (struct inode *inode); - int (*inode_setxattr) (struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); - void (*inode_post_setxattr) (struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); - int (*inode_getxattr) (struct dentry *dentry, const char *name); - int (*inode_listxattr) (struct dentry *dentry); - int (*inode_removexattr) (struct dentry *dentry, const char *name); + int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, size_t size, + int flags, struct file *file); + void (*inode_post_setxattr) (struct dentry *dentry, + struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags); + int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file); + int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt, + struct file *file); + int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file); int (*inode_need_killpriv) (struct dentry *dentry); int (*inode_killpriv) (struct dentry *dentry); int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc); @@ -1407,6 +1448,7 @@ struct fown_struct *fown, int sig); int (*file_receive) (struct file *file); int (*dentry_open) (struct file *file); + int (*path_permission) (struct path *path, int mask); int (*task_create) (unsigned long clone_flags); int (*task_alloc_security) (struct task_struct *p); @@ -1622,30 +1664,43 @@ void security_inode_free(struct inode *inode); int security_inode_init_security(struct inode *inode, struct inode *dir, char **name, void **value, size_t *len); -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); -int security_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry); -int security_inode_unlink(struct inode *dir, struct dentry *dentry); +int security_inode_create(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode); +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt, + struct inode *dir, struct dentry *new_dentry, + struct vfsmount *new_mnt); +int security_inode_unlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt); int security_inode_symlink(struct inode *dir, struct dentry *dentry, - const char *old_name); -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode); -int security_inode_rmdir(struct inode *dir, struct dentry *dentry); -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev); + struct vfsmount *mnt, const char *old_name); +int security_inode_mkdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode); +int security_inode_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt); +int security_inode_mknod(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode, dev_t dev); int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry); -int security_inode_readlink(struct dentry *dentry); + struct vfsmount *old_mnt, struct inode *new_dir, + struct dentry *new_dentry, struct vfsmount *new_mnt); +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt); int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); int security_inode_permission(struct inode *inode, int mask); -int security_inode_setattr(struct dentry *dentry, struct iattr *attr); +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *attr); int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry); void security_inode_delete(struct inode *inode); -int security_inode_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); -void security_inode_post_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); -int security_inode_getxattr(struct dentry *dentry, const char *name); -int security_inode_listxattr(struct dentry *dentry); -int security_inode_removexattr(struct dentry *dentry, const char *name); +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags, struct file *file); +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags); +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file); +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt, + struct file *file); +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file); int security_inode_need_killpriv(struct dentry *dentry); int security_inode_killpriv(struct dentry *dentry); int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc); @@ -1668,6 +1723,7 @@ struct fown_struct *fown, int sig); int security_file_receive(struct file *file); int security_dentry_open(struct file *file); +int security_path_permission(struct path *path, int mask); int security_task_create(unsigned long clone_flags); int security_task_alloc(struct task_struct *p); void security_task_free(struct task_struct *p); @@ -1968,26 +2024,31 @@ static inline int security_inode_create(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode) { return 0; } static inline int security_inode_link(struct dentry *old_dentry, - struct inode *dir, - struct dentry *new_dentry) + struct vfsmount *old_mnt, + struct inode *dir, + struct dentry *new_dentry, + struct vfsmount *new_mnt) { return 0; } static inline int security_inode_unlink(struct inode *dir, - struct dentry *dentry) + struct dentry *dentry, + struct vfsmount *mnt) { return 0; } static inline int security_inode_symlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *old_name) { return 0; @@ -1995,19 +2056,22 @@ static inline int security_inode_mkdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode) { return 0; } static inline int security_inode_rmdir(struct inode *dir, - struct dentry *dentry) + struct dentry *dentry, + struct vfsmount *mnt) { return 0; } static inline int security_inode_mknod(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode, dev_t dev) { return 0; @@ -2015,13 +2079,16 @@ static inline int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, + struct vfsmount *old_mnt, struct inode *new_dir, - struct dentry *new_dentry) + struct dentry *new_dentry, + struct vfsmount *new_mnt) { return 0; } -static inline int security_inode_readlink(struct dentry *dentry) +static inline int security_inode_readlink(struct dentry *dentry, + struct vfsmount *mnt) { return 0; } @@ -2038,7 +2105,8 @@ } static inline int security_inode_setattr(struct dentry *dentry, - struct iattr *attr) + struct vfsmount *mnt, + struct iattr *attr) { return 0; } @@ -2053,30 +2121,42 @@ { } static inline int security_inode_setxattr(struct dentry *dentry, - const char *name, const void *value, size_t size, int flags) + struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags, + struct file *file) { - return cap_inode_setxattr(dentry, name, value, size, flags); + return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file); } static inline void security_inode_post_setxattr(struct dentry *dentry, - const char *name, const void *value, size_t size, int flags) + struct vfsmount *mnt, + const char *name, + const void *value, + size_t size, int flags) { } static inline int security_inode_getxattr(struct dentry *dentry, - const char *name) + struct vfsmount *mnt, + const char *name, + struct file *file) { return 0; } -static inline int security_inode_listxattr(struct dentry *dentry) +static inline int security_inode_listxattr(struct dentry *dentry, + struct vfsmount *mnt, + struct file *file) { return 0; } static inline int security_inode_removexattr(struct dentry *dentry, - const char *name) + struct vfsmount *mnt, + const char *name, + struct file *file) { - return cap_inode_removexattr(dentry, name); + return cap_inode_removexattr(dentry, mnt, name, file); } static inline int security_inode_need_killpriv(struct dentry *dentry) @@ -2177,6 +2257,11 @@ return 0; } +static inline int security_path_permission(struct path *path, int mask) +{ + return 0; +} + static inline int security_task_create(unsigned long clone_flags) { return 0; --- linux-2.6.27.orig/include/linux/sysctl.h +++ linux-2.6.27/include/linux/sysctl.h @@ -996,6 +996,8 @@ extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int, struct file *, void __user *, size_t *, loff_t *); +extern char *sysctl_pathname(ctl_table *, char *, int); + extern int do_sysctl (int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen); --- linux-2.6.27.orig/include/linux/fs.h +++ linux-2.6.27/include/linux/fs.h @@ -361,6 +361,10 @@ * Not an attribute, but an auxilary info for filesystems wanting to * implement an ftruncate() like method. NOTE: filesystem should * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL). + * + * NOTE: With patches.apparmor/fsetattr.diff applied, this is + * for compatibility with external file system modules only. There + * should not be any in-kernel users left. */ struct file *ia_file; }; @@ -1160,13 +1164,13 @@ */ extern int vfs_permission(struct nameidata *, int); extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); -extern int vfs_mkdir(struct inode *, struct dentry *, int); -extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); -extern int vfs_symlink(struct inode *, struct dentry *, const char *); -extern int vfs_link(struct dentry *, struct inode *, struct dentry *); -extern int vfs_rmdir(struct inode *, struct dentry *); -extern int vfs_unlink(struct inode *, struct dentry *); -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int); +extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t); +extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *); +extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *); +extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *); +extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *); +extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *); /* * VFS dentry helper functions. @@ -1179,6 +1183,11 @@ extern int file_permission(struct file *, int); /* + * VFS path helper functions. + */ +extern int path_permission(struct path *, int); + +/* * File types * * NOTE! These match bits 12..15 of stat.st_mode @@ -1260,6 +1269,7 @@ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **); + int (*fsetattr)(struct file *, struct iattr *); }; struct inode_operations { @@ -1612,8 +1622,8 @@ /* fs/open.c */ -extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, - struct file *filp); +extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start, + unsigned int time_attrs, struct file *filp); extern long do_sys_open(int dfd, const char __user *filename, int flags, int mode); extern struct file *filp_open(const char *, int, int); @@ -1771,7 +1781,8 @@ #ifdef CONFIG_BLOCK extern sector_t bmap(struct inode *, sector_t); #endif -extern int notify_change(struct dentry *, struct iattr *); +extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *); +extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *); extern int inode_permission(struct inode *, int); extern int generic_permission(struct inode *, int, int (*check_acl)(struct inode *, int)); --- linux-2.6.27.orig/include/linux/netfilter_ipv6/Kbuild +++ linux-2.6.27/include/linux/netfilter_ipv6/Kbuild @@ -11,6 +11,7 @@ header-y += ip6t_limit.h header-y += ip6t_mac.h header-y += ip6t_mark.h +header-y += ip6t_mh.h header-y += ip6t_multiport.h header-y += ip6t_opts.h header-y += ip6t_owner.h --- linux-2.6.27.orig/include/linux/nfsd/nfsd.h +++ linux-2.6.27/include/linux/nfsd/nfsd.h @@ -85,7 +85,8 @@ #ifdef CONFIG_NFSD_V4 __be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, struct nfs4_acl *); -int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **); +int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, + struct vfsmount *mnt, struct nfs4_acl **); #endif /* CONFIG_NFSD_V4 */ __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs, --- linux-2.6.27.orig/include/linux/mtd/cfi.h +++ linux-2.6.27/include/linux/mtd/cfi.h @@ -281,9 +281,25 @@ /* * Returns the command address according to the given geometry. */ -static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type) +static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, + struct map_info *map, struct cfi_private *cfi) { - return (cmd_ofs * type) * interleave; + unsigned bankwidth = map_bankwidth(map); + unsigned interleave = cfi_interleave(cfi); + unsigned type = cfi->device_type; + uint32_t addr; + + addr = (cmd_ofs * type) * interleave; + + /* Modify the unlock address if we are in compatiblity mode. + * For 16bit devices on 8 bit busses + * and 32bit devices on 16 bit busses + * set the low bit of the alternating bit sequence of the address. + */ + if (((type * interleave) > bankwidth) && ((uint8_t)cmd_ofs == 0xaa)) + addr |= (type >> 1)*interleave; + + return addr; } /* @@ -429,7 +445,7 @@ int type, map_word *prev_val) { map_word val; - uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type); + uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi); val = cfi_build_cmd(cmd, map, cfi); --- linux-2.6.27.orig/include/linux/netfilter/Kbuild +++ linux-2.6.27/include/linux/netfilter/Kbuild @@ -31,6 +31,8 @@ header-y += xt_owner.h header-y += xt_pkttype.h header-y += xt_rateest.h +header-y += xt_policy.h +header-y += xt_quota.h header-y += xt_realm.h header-y += xt_sctp.h header-y += xt_state.h --- linux-2.6.27.orig/include/math-emu/op-common.h +++ linux-2.6.27/include/math-emu/op-common.h @@ -139,18 +139,27 @@ if (X##_e <= _FP_WFRACBITS_##fs) \ { \ _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ - _FP_ROUND(wc, X); \ if (_FP_FRAC_HIGH_##fs(X) \ & (_FP_OVERFLOW_##fs >> 1)) \ { \ X##_e = 1; \ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ - FP_SET_EXCEPTION(FP_EX_INEXACT); \ } \ else \ { \ - X##_e = 0; \ - _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + _FP_ROUND(wc, X); \ + if (_FP_FRAC_HIGH_##fs(X) \ + & (_FP_OVERFLOW_##fs >> 1)) \ + { \ + X##_e = 1; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + } \ + else \ + { \ + X##_e = 0; \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + } \ } \ if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ --- linux-2.6.27.orig/include/asm-generic/memory_model.h +++ linux-2.6.27/include/asm-generic/memory_model.h @@ -34,7 +34,7 @@ #define __pfn_to_page(pfn) \ ({ unsigned long __pfn = (pfn); \ - unsigned long __nid = arch_pfn_to_nid(pfn); \ + unsigned long __nid = arch_pfn_to_nid(__pfn); \ NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\ }) --- linux-2.6.27.orig/include/net/scm.h +++ linux-2.6.27/include/net/scm.h @@ -14,8 +14,9 @@ struct scm_fp_list { - int count; - struct file *fp[SCM_MAX_FD]; + struct list_head list; + int count; + struct file *fp[SCM_MAX_FD]; }; struct scm_cookie --- linux-2.6.27.orig/include/net/af_unix.h +++ linux-2.6.27/include/net/af_unix.h @@ -54,6 +54,7 @@ atomic_long_t inflight; spinlock_t lock; unsigned int gc_candidate : 1; + unsigned int gc_maybe_cycle : 1; wait_queue_head_t peer_wait; }; #define unix_sk(__sk) ((struct unix_sock *)__sk) --- linux-2.6.27.orig/security/capability.c +++ linux-2.6.27/security/capability.c @@ -155,52 +155,56 @@ } static int cap_inode_create(struct inode *inode, struct dentry *dentry, - int mask) + struct vfsmount *mnt, int mask) { return 0; } -static int cap_inode_link(struct dentry *old_dentry, struct inode *inode, - struct dentry *new_dentry) +static int cap_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt, + struct inode *inode, + struct dentry *new_dentry, struct vfsmount *new_mnt) { return 0; } -static int cap_inode_unlink(struct inode *inode, struct dentry *dentry) +static int cap_inode_unlink(struct inode *inode, struct dentry *dentry, + struct vfsmount *mnt) { return 0; } static int cap_inode_symlink(struct inode *inode, struct dentry *dentry, - const char *name) + struct vfsmount *mnt, const char *name) { return 0; } static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry, - int mask) + struct vfsmount *mnt, int mask) { return 0; } -static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry) +static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry, + struct vfsmount *mnt) { return 0; } static int cap_inode_mknod(struct inode *inode, struct dentry *dentry, - int mode, dev_t dev) + struct vfsmount *mnt, int mode, dev_t dev) { return 0; } static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry, - struct inode *new_inode, struct dentry *new_dentry) + struct vfsmount *old_mnt, struct inode *new_inode, + struct dentry *new_dentry, struct vfsmount *new_mnt) { return 0; } -static int cap_inode_readlink(struct dentry *dentry) +static int cap_inode_readlink(struct dentry *dentry, struct vfsmount *mnt) { return 0; } @@ -216,7 +220,8 @@ return 0; } -static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int cap_inode_setattr(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *iattr) { return 0; } @@ -230,17 +235,20 @@ { } -static void cap_inode_post_setxattr(struct dentry *dentry, const char *name, +static void cap_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, size_t size, int flags) { } -static int cap_inode_getxattr(struct dentry *dentry, const char *name) +static int cap_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *f) { return 0; } -static int cap_inode_listxattr(struct dentry *dentry) +static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt, + struct file *f) { return 0; } @@ -335,6 +343,11 @@ return 0; } +static int cap_path_permission(struct path *path, int mask) +{ + return security_inode_permission(path->dentry->d_inode, mask); +} + static int cap_task_create(unsigned long clone_flags) { return 0; @@ -889,6 +902,7 @@ set_to_cap_if_null(ops, file_send_sigiotask); set_to_cap_if_null(ops, file_receive); set_to_cap_if_null(ops, dentry_open); + set_to_cap_if_null(ops, path_permission); set_to_cap_if_null(ops, task_create); set_to_cap_if_null(ops, task_alloc_security); set_to_cap_if_null(ops, task_free_security); --- linux-2.6.27.orig/security/Kconfig +++ linux-2.6.27/security/Kconfig @@ -117,6 +117,7 @@ source security/selinux/Kconfig source security/smack/Kconfig +source security/apparmor/Kconfig endmenu --- linux-2.6.27.orig/security/commoncap.c +++ linux-2.6.27/security/commoncap.c @@ -279,10 +279,10 @@ struct vfs_cap_data vcaps; struct inode *inode; - if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { - bprm_clear_caps(bprm); + bprm_clear_caps(bprm); + + if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) return 0; - } dentry = dget(bprm->file->f_dentry); inode = dentry->d_inode; @@ -411,8 +411,9 @@ current->egid != current->gid); } -int cap_inode_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, size_t size, + int flags, struct file *file) { if (!strcmp(name, XATTR_NAME_CAPS)) { if (!capable(CAP_SETFCAP)) @@ -425,7 +426,8 @@ return 0; } -int cap_inode_removexattr(struct dentry *dentry, const char *name) +int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file) { if (!strcmp(name, XATTR_NAME_CAPS)) { if (!capable(CAP_SETFCAP)) --- linux-2.6.27.orig/security/security.c +++ linux-2.6.27/security/security.c @@ -358,72 +358,81 @@ } EXPORT_SYMBOL(security_inode_init_security); -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) +int security_inode_create(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return security_ops->inode_create(dir, dentry, mode); + return security_ops->inode_create(dir, dentry, mnt, mode); } -int security_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt, + struct inode *dir, struct dentry *new_dentry, + struct vfsmount *new_mnt) { if (unlikely(IS_PRIVATE(old_dentry->d_inode))) return 0; - return security_ops->inode_link(old_dentry, dir, new_dentry); + return security_ops->inode_link(old_dentry, old_mnt, dir, + new_dentry, new_mnt); } -int security_inode_unlink(struct inode *dir, struct dentry *dentry) +int security_inode_unlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_unlink(dir, dentry); + return security_ops->inode_unlink(dir, dentry, mnt); } int security_inode_symlink(struct inode *dir, struct dentry *dentry, - const char *old_name) + struct vfsmount *mnt, const char *old_name) { if (unlikely(IS_PRIVATE(dir))) return 0; - return security_ops->inode_symlink(dir, dentry, old_name); + return security_ops->inode_symlink(dir, dentry, mnt, old_name); } -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode) +int security_inode_mkdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return security_ops->inode_mkdir(dir, dentry, mode); + return security_ops->inode_mkdir(dir, dentry, mnt, mode); } -int security_inode_rmdir(struct inode *dir, struct dentry *dentry) +int security_inode_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_rmdir(dir, dentry); + return security_ops->inode_rmdir(dir, dentry, mnt); } -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +int security_inode_mknod(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode, dev_t dev) { if (unlikely(IS_PRIVATE(dir))) return 0; - return security_ops->inode_mknod(dir, dentry, mode, dev); + return security_ops->inode_mknod(dir, dentry, mnt, mode, dev); } +EXPORT_SYMBOL_GPL(security_inode_permission); int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) + struct vfsmount *old_mnt, struct inode *new_dir, + struct dentry *new_dentry, struct vfsmount *new_mnt) { if (unlikely(IS_PRIVATE(old_dentry->d_inode) || (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) return 0; - return security_ops->inode_rename(old_dir, old_dentry, - new_dir, new_dentry); + return security_ops->inode_rename(old_dir, old_dentry, old_mnt, + new_dir, new_dentry, new_mnt); } -int security_inode_readlink(struct dentry *dentry) +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_readlink(dentry); + return security_ops->inode_readlink(dentry, mnt); } int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd) @@ -440,11 +449,12 @@ return security_ops->inode_permission(inode, mask); } -int security_inode_setattr(struct dentry *dentry, struct iattr *attr) +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *attr) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_setattr(dentry, attr); + return security_ops->inode_setattr(dentry, mnt, attr); } EXPORT_SYMBOL_GPL(security_inode_setattr); @@ -462,41 +472,48 @@ security_ops->inode_delete(inode); } -int security_inode_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, size_t size, + int flags, struct file *file) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_setxattr(dentry, name, value, size, flags); + return security_ops->inode_setxattr(dentry, mnt, name, value, size, + flags, file); } -void security_inode_post_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return; - security_ops->inode_post_setxattr(dentry, name, value, size, flags); + security_ops->inode_post_setxattr(dentry, mnt, name, value, size, + flags); } -int security_inode_getxattr(struct dentry *dentry, const char *name) +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_getxattr(dentry, name); + return security_ops->inode_getxattr(dentry, mnt, name, file); } -int security_inode_listxattr(struct dentry *dentry) +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt, + struct file *file) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_listxattr(dentry); + return security_ops->inode_listxattr(dentry, mnt, file); } -int security_inode_removexattr(struct dentry *dentry, const char *name) +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_removexattr(dentry, name); + return security_ops->inode_removexattr(dentry, mnt, name, file); } int security_inode_need_killpriv(struct dentry *dentry) @@ -599,6 +616,15 @@ return security_ops->dentry_open(file); } +int security_path_permission(struct path *path, int mask) +{ + struct inode *inode = path->dentry->d_inode; + if (unlikely(IS_PRIVATE(inode))) + return 0; + + return security_ops->path_permission(path, mask); +} + int security_task_create(unsigned long clone_flags) { return security_ops->task_create(clone_flags); --- linux-2.6.27.orig/security/Makefile +++ linux-2.6.27/security/Makefile @@ -14,5 +14,6 @@ # Must precede capability.o in order to stack properly. obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o -obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o +obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/ + obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o --- linux-2.6.27.orig/security/keys/internal.h +++ linux-2.6.27/security/keys/internal.h @@ -107,6 +107,7 @@ extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); +extern int install_user_keyrings(struct task_struct *tsk); extern int install_thread_keyring(struct task_struct *tsk); extern int install_process_keyring(struct task_struct *tsk); --- linux-2.6.27.orig/security/keys/process_keys.c +++ linux-2.6.27/security/keys/process_keys.c @@ -40,7 +40,7 @@ /* * install user and user session keyrings for a particular UID */ -static int install_user_keyrings(struct task_struct *tsk) +int install_user_keyrings(struct task_struct *tsk) { struct user_struct *user = tsk->user; struct key *uid_keyring, *session_keyring; --- linux-2.6.27.orig/security/keys/request_key.c +++ linux-2.6.27/security/keys/request_key.c @@ -74,6 +74,10 @@ kenter("{%d},{%d},%s", key->serial, authkey->serial, op); + ret = install_user_keyrings(tsk); + if (ret < 0) + goto error_alloc; + /* allocate a new session keyring */ sprintf(desc, "_req.%u", key->serial); --- linux-2.6.27.orig/security/apparmor/list.c +++ linux-2.6.27/security/apparmor/list.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor Profile List Management + */ + +#include +#include "apparmor.h" +#include "inline.h" + +/* list of profile namespaces and lock */ +LIST_HEAD(profile_ns_list); +rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED; + +/** + * __aa_find_namespace - look up a profile namespace on the namespace list + * @name: name of namespace to find + * @head: list to search + * + * Returns a pointer to the namespace on the list, or NULL if no namespace + * called @name exists. The caller must hold the profile_ns_list_lock. + */ +struct aa_namespace *__aa_find_namespace(const char *name, + struct list_head *head) +{ + struct aa_namespace *ns; + + list_for_each_entry(ns, head, list) { + if (!strcmp(ns->name, name)) + return ns; + } + + return NULL; +} + +/** + * __aa_find_profile - look up a profile on the profile list + * @name: name of profile to find + * @head: list to search + * + * Returns a pointer to the profile on the list, or NULL if no profile + * called @name exists. The caller must hold the profile_list_lock. + */ +struct aa_profile *__aa_find_profile(const char *name, struct list_head *head) +{ + struct aa_profile *profile; + + list_for_each_entry(profile, head, list) { + if (!strcmp(profile->name, name)) + return profile; + } + + return NULL; +} + +static void aa_profile_list_release(struct list_head *head) +{ + struct aa_profile *profile, *tmp; + list_for_each_entry_safe(profile, tmp, head, list) { + /* Remove the profile from each task context it is on. */ + lock_profile(profile); + profile->isstale = 1; + aa_unconfine_tasks(profile); + list_del_init(&profile->list); + unlock_profile(profile); + aa_put_profile(profile); + } +} + +/** + * aa_profilelist_release - Remove all profiles from profile_list + */ +void aa_profile_ns_list_release(void) +{ + struct aa_namespace *ns, *tmp; + + /* Remove and release all the profiles on namespace profile lists. */ + write_lock(&profile_ns_list_lock); + list_for_each_entry_safe(ns, tmp, &profile_ns_list, list) { + write_lock(&ns->lock); + aa_profile_list_release(&ns->profiles); + list_del_init(&ns->list); + write_unlock(&ns->lock); + aa_put_namespace(ns); + } + write_unlock(&profile_ns_list_lock); +} + + +static struct aa_profile *next_profile(struct aa_profile *profile) +{ + struct aa_profile *next = profile; + struct aa_namespace *ns; + + list_for_each_entry_continue(next, &profile->ns->profiles, list) + return next; + + ns = profile->ns; + read_unlock(&ns->lock); + list_for_each_entry_continue(ns, &profile_ns_list, list) { + read_lock(&ns->lock); + list_for_each_entry(profile, &ns->profiles, list) + return profile; + read_unlock(&ns->lock); + } + return NULL; +} + +static void *p_start(struct seq_file *f, loff_t *pos) +{ + struct aa_namespace *ns; + loff_t l = *pos; + + read_lock(&profile_ns_list_lock); + if (!list_empty(&profile_ns_list)) { + struct aa_profile *profile = NULL; + ns = list_first_entry(&profile_ns_list, typeof(*ns), list); + read_lock(&ns->lock); + if (!list_empty(&ns->profiles)) + profile = list_first_entry(&ns->profiles, + typeof(*profile), list); + else + read_unlock(&ns->lock); + for ( ; profile && l > 0; l--) + profile = next_profile(profile); + return profile; + } + return NULL; +} + +static void *p_next(struct seq_file *f, void *p, loff_t *pos) +{ + struct aa_profile *profile = (struct aa_profile *) p; + + (*pos)++; + profile = next_profile(profile); + + return profile; +} + +static void p_stop(struct seq_file *f, void *p) +{ + struct aa_profile *profile = (struct aa_profile *) p; + + if (profile) + read_unlock(&profile->ns->lock); + read_unlock(&profile_ns_list_lock); +} + +static int seq_show_profile(struct seq_file *f, void *p) +{ + struct aa_profile *profile = (struct aa_profile *)p; + + if (profile->ns == default_namespace) + seq_printf(f, "%s (%s)\n", profile->name, + PROFILE_COMPLAIN(profile) ? "complain" : "enforce"); + else + seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name, + PROFILE_COMPLAIN(profile) ? "complain" : "enforce"); + return 0; +} + +/* Used in apparmorfs.c */ +struct seq_operations apparmorfs_profiles_op = { + .start = p_start, + .next = p_next, + .stop = p_stop, + .show = seq_show_profile, +}; --- linux-2.6.27.orig/security/apparmor/module_interface.c +++ linux-2.6.27/security/apparmor/module_interface.c @@ -0,0 +1,967 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor userspace policy interface + */ + +#include + +#include "apparmor.h" +#include "inline.h" + +/* + * This mutex is used to synchronize profile adds, replacements, and + * removals: we only allow one of these operations at a time. + * We do not use the profile list lock here in order to avoid blocking + * exec during those operations. (Exec involves a profile list lookup + * for named-profile transitions.) + */ +DEFINE_MUTEX(aa_interface_lock); + +/* + * The AppArmor interface treats data as a type byte followed by the + * actual data. The interface has the notion of a a named entry + * which has a name (AA_NAME typecode followed by name string) followed by + * the entries typecode and data. Named types allow for optional + * elements and extensions to be added and tested for without breaking + * backwards compatability. + */ + +enum aa_code { + AA_U8, + AA_U16, + AA_U32, + AA_U64, + AA_NAME, /* same as string except it is items name */ + AA_STRING, + AA_BLOB, + AA_STRUCT, + AA_STRUCTEND, + AA_LIST, + AA_LISTEND, + AA_ARRAY, + AA_ARRAYEND, +}; + +/* + * aa_ext is the read of the buffer containing the serialized profile. The + * data is copied into a kernel buffer in apparmorfs and then handed off to + * the unpack routines. + */ +struct aa_ext { + void *start; + void *end; + void *pos; /* pointer to current position in the buffer */ + u32 version; + char *ns_name; +}; + +static inline int aa_inbounds(struct aa_ext *e, size_t size) +{ + return (size <= e->end - e->pos); +} + +/** + * aa_u16_chunck - test and do bounds checking for a u16 size based chunk + * @e: serialized data read head + * @chunk: start address for chunk of data + * + * return the size of chunk found with the read head at the end of + * the chunk. + */ +static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk) +{ + void *pos = e->pos; + size_t size = 0; + + if (!aa_inbounds(e, sizeof(u16))) + goto fail; + size = le16_to_cpu(get_unaligned((u16 *)e->pos)); + e->pos += sizeof(u16); + if (!aa_inbounds(e, size)) + goto fail; + *chunk = e->pos; + e->pos += size; + return size; + +fail: + e->pos = pos; + return 0; +} + +static inline int aa_is_X(struct aa_ext *e, enum aa_code code) +{ + if (!aa_inbounds(e, 1)) + return 0; + if (*(u8 *) e->pos != code) + return 0; + e->pos++; + return 1; +} + +/** + * aa_is_nameX - check is the next element is of type X with a name of @name + * @e: serialized data extent information + * @code: type code + * @name: name to match to the serialized element. + * + * check that the next serialized data element is of type X and has a tag + * name @name. If @name is specified then there must be a matching + * name element in the stream. If @name is NULL any name element will be + * skipped and only the typecode will be tested. + * returns 1 on success (both type code and name tests match) and the read + * head is advanced past the headers + * returns %0 if either match failes, the read head does not move + */ +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name) +{ + void *pos = e->pos; + /* + * Check for presence of a tagname, and if present name size + * AA_NAME tag value is a u16. + */ + if (aa_is_X(e, AA_NAME)) { + char *tag; + size_t size = aa_is_u16_chunk(e, &tag); + /* if a name is specified it must match. otherwise skip tag */ + if (name && (!size || strcmp(name, tag))) + goto fail; + } else if (name) { + /* if a name is specified and there is no name tag fail */ + goto fail; + } + + /* now check if type code matches */ + if (aa_is_X(e, code)) + return 1; + +fail: + e->pos = pos; + return 0; +} + +static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name) +{ + void *pos = e->pos; + if (aa_is_nameX(e, AA_U16, name)) { + if (!aa_inbounds(e, sizeof(u16))) + goto fail; + if (data) + *data = le16_to_cpu(get_unaligned((u16 *)e->pos)); + e->pos += sizeof(u16); + return 1; + } +fail: + e->pos = pos; + return 0; +} + +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name) +{ + void *pos = e->pos; + if (aa_is_nameX(e, AA_U32, name)) { + if (!aa_inbounds(e, sizeof(u32))) + goto fail; + if (data) + *data = le32_to_cpu(get_unaligned((u32 *)e->pos)); + e->pos += sizeof(u32); + return 1; + } +fail: + e->pos = pos; + return 0; +} + +static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name) +{ + void *pos = e->pos; + if (aa_is_nameX(e, AA_U64, name)) { + if (!aa_inbounds(e, sizeof(u64))) + goto fail; + if (data) + *data = le64_to_cpu(get_unaligned((u64 *)e->pos)); + e->pos += sizeof(u64); + return 1; + } +fail: + e->pos = pos; + return 0; +} + +static size_t aa_is_array(struct aa_ext *e, const char *name) +{ + void *pos = e->pos; + if (aa_is_nameX(e, AA_ARRAY, name)) { + int size; + if (!aa_inbounds(e, sizeof(u16))) + goto fail; + size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos)); + e->pos += sizeof(u16); + return size; + } +fail: + e->pos = pos; + return 0; +} + +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name) +{ + void *pos = e->pos; + if (aa_is_nameX(e, AA_BLOB, name)) { + u32 size; + if (!aa_inbounds(e, sizeof(u32))) + goto fail; + size = le32_to_cpu(get_unaligned((u32 *)e->pos)); + e->pos += sizeof(u32); + if (aa_inbounds(e, (size_t) size)) { + * blob = e->pos; + e->pos += size; + return size; + } + } +fail: + e->pos = pos; + return 0; +} + +static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name) +{ + char *src_str; + size_t size = 0; + void *pos = e->pos; + *string = NULL; + if (aa_is_nameX(e, AA_STRING, name) && + (size = aa_is_u16_chunk(e, &src_str))) { + char *str; + if (!(str = kmalloc(size, GFP_KERNEL))) + goto fail; + memcpy(str, src_str, size); + *string = str; + } + + return size; + +fail: + e->pos = pos; + return 0; +} + +/** + * aa_unpack_dfa - unpack a file rule dfa + * @e: serialized data extent information + * + * returns dfa or ERR_PTR + */ +static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e) +{ + char *blob = NULL; + size_t size, error = 0; + struct aa_dfa *dfa = NULL; + + size = aa_is_blob(e, &blob, "aadfa"); + if (size) { + dfa = aa_match_alloc(); + if (dfa) { + /* + * The dfa is aligned with in the blob to 8 bytes + * from the beginning of the stream. + */ + size_t sz = blob - (char *) e->start; + size_t pad = ALIGN(sz, 8) - sz; + error = unpack_dfa(dfa, blob + pad, size - pad); + if (!error) + error = verify_dfa(dfa); + } else { + error = -ENOMEM; + } + + if (error) { + aa_match_free(dfa); + dfa = ERR_PTR(error); + } + } + + return dfa; +} + +static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile) +{ + void *pos = e->pos; + + /* exec table is optional */ + if (aa_is_nameX(e, AA_STRUCT, "xtable")) { + int i, size; + + size = aa_is_array(e, NULL); + /* currently 4 exec bits and entries 0-3 are reserved iupcx */ + if (size > 16 - 4) + goto fail; + profile->exec_table = kzalloc(sizeof(char *) * size, + GFP_KERNEL); + if (!profile->exec_table) + goto fail; + + for (i = 0; i < size; i++) { + char *tmp; + if (!aa_is_dynstring(e, &tmp, NULL)) + goto fail; + /* note: strings beginning with a : have an embedded + \0 seperating the profile ns name from the profile + name */ + profile->exec_table[i] = tmp; + } + if (!aa_is_nameX(e, AA_ARRAYEND, NULL)) + goto fail; + if (!aa_is_nameX(e, AA_STRUCTEND, NULL)) + goto fail; + profile->exec_table_size = size; + } + return 1; + +fail: + e->pos = pos; + return 0; +} + +int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) +{ + void *pos = e->pos; + + /* rlimits are optional */ + if (aa_is_nameX(e, AA_STRUCT, "rlimits")) { + int i, size; + u32 tmp = 0; + if (!aa_is_u32(e, &tmp, NULL)) + goto fail; + profile->rlimits.mask = tmp; + + size = aa_is_array(e, NULL); + if (size > RLIM_NLIMITS) + goto fail; + for (i = 0; i < size; i++) { + u64 tmp = 0; + if (!aa_is_u64(e, &tmp, NULL)) + goto fail; + profile->rlimits.limits[i].rlim_max = tmp; + } + if (!aa_is_nameX(e, AA_ARRAYEND, NULL)) + goto fail; + if (!aa_is_nameX(e, AA_STRUCTEND, NULL)) + goto fail; + } + return 1; + +fail: + e->pos = pos; + return 0; +} + +/** + * aa_unpack_profile - unpack a serialized profile + * @e: serialized data extent information + * @sa: audit struct for the operation + */ +static struct aa_profile *aa_unpack_profile(struct aa_ext *e, + struct aa_audit *sa) +{ + struct aa_profile *profile = NULL; + size_t size = 0; + int i, error = -EPROTO; + + profile = alloc_aa_profile(); + if (!profile) + return ERR_PTR(-ENOMEM); + + /* check that we have the right struct being passed */ + if (!aa_is_nameX(e, AA_STRUCT, "profile")) + goto fail; + if (!aa_is_dynstring(e, &profile->name, NULL)) + goto fail; + + /* per profile debug flags (complain, audit) */ + if (!aa_is_nameX(e, AA_STRUCT, "flags")) + goto fail; + if (!aa_is_u32(e, &(profile->flags.hat), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->flags.complain), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->flags.audit), NULL)) + goto fail; + if (!aa_is_nameX(e, AA_STRUCTEND, NULL)) + goto fail; + + if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL)) + goto fail; + + if (aa_is_nameX(e, AA_STRUCT, "caps64")) { + /* optional upper half of 64 bit caps */ + if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL)) + goto fail; + if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL)) + goto fail; + if (!aa_is_nameX(e, AA_STRUCTEND, NULL)) + goto fail; + } + + if (!aa_unpack_rlimits(e, profile)) + goto fail; + + size = aa_is_array(e, "net_allowed_af"); + if (size) { + if (size > AF_MAX) + goto fail; + + for (i = 0; i < size; i++) { + if (!aa_is_u16(e, &profile->network_families[i], NULL)) + goto fail; + if (!aa_is_u16(e, &profile->audit_network[i], NULL)) + goto fail; + if (!aa_is_u16(e, &profile->quiet_network[i], NULL)) + goto fail; + } + if (!aa_is_nameX(e, AA_ARRAYEND, NULL)) + goto fail; + /* allow unix domain and netlink sockets they are handled + * by IPC + */ + } + profile->network_families[AF_UNIX] = 0xffff; + profile->network_families[AF_NETLINK] = 0xffff; + + /* get file rules */ + profile->file_rules = aa_unpack_dfa(e); + if (IS_ERR(profile->file_rules)) { + error = PTR_ERR(profile->file_rules); + profile->file_rules = NULL; + goto fail; + } + + if (!aa_unpack_exec_table(e, profile)) + goto fail; + + if (!aa_is_nameX(e, AA_STRUCTEND, NULL)) + goto fail; + + return profile; + +fail: + sa->name = profile && profile->name ? profile->name : "unknown"; + if (!sa->info) + sa->info = "failed to unpack profile"; + aa_audit_status(NULL, sa); + + if (profile) + free_aa_profile(profile); + + return ERR_PTR(error); +} + +/** + * aa_verify_head - unpack serialized stream header + * @e: serialized data read head + * @operation: operation header is being verified for + * + * returns error or 0 if header is good + */ +static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa) +{ + /* get the interface version */ + if (!aa_is_u32(e, &e->version, "version")) { + sa->info = "invalid profile format"; + aa_audit_status(NULL, sa); + return -EPROTONOSUPPORT; + } + + /* check that the interface version is currently supported */ + if (e->version != 5) { + sa->info = "unsupported interface version"; + aa_audit_status(NULL, sa); + return -EPROTONOSUPPORT; + } + + /* read the namespace if present */ + if (!aa_is_dynstring(e, &e->ns_name, "namespace")) { + e->ns_name = NULL; + } + + return 0; +} + +/** + * aa_add_profile - Unpack and add a new profile to the profile list + * @data: serialized data stream + * @size: size of the serialized data stream + */ +ssize_t aa_add_profile(void *data, size_t size) +{ + struct aa_profile *profile = NULL; + struct aa_namespace *ns = NULL; + struct aa_ext e = { + .start = data, + .end = data + size, + .pos = data, + .ns_name = NULL + }; + ssize_t error; + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "profile_load"; + sa.gfp_mask = GFP_KERNEL; + + error = aa_verify_header(&e, &sa); + if (error) + return error; + + profile = aa_unpack_profile(&e, &sa); + if (IS_ERR(profile)) + return PTR_ERR(profile); + + mutex_lock(&aa_interface_lock); + write_lock(&profile_ns_list_lock); + if (e.ns_name) + ns = __aa_find_namespace(e.ns_name, &profile_ns_list); + else + ns = default_namespace; + if (!ns) { + struct aa_namespace *new_ns; + write_unlock(&profile_ns_list_lock); + new_ns = alloc_aa_namespace(e.ns_name); + if (!new_ns) { + mutex_unlock(&aa_interface_lock); + return -ENOMEM; + } + write_lock(&profile_ns_list_lock); + ns = __aa_find_namespace(e.ns_name, &profile_ns_list); + if (!ns) { + list_add(&new_ns->list, &profile_ns_list); + ns = new_ns; + } else + free_aa_namespace(new_ns); + } + + write_lock(&ns->lock); + if (__aa_find_profile(profile->name, &ns->profiles)) { + /* A profile with this name exists already. */ + write_unlock(&ns->lock); + write_unlock(&profile_ns_list_lock); + sa.name = profile->name; + sa.name2 = ns->name; + sa.info = "failed: profile already loaded"; + aa_audit_status(NULL, &sa); + mutex_unlock(&aa_interface_lock); + aa_put_profile(profile); + return -EEXIST; + } + profile->ns = aa_get_namespace(ns); + ns->profile_count++; + list_add(&profile->list, &ns->profiles); + write_unlock(&ns->lock); + write_unlock(&profile_ns_list_lock); + + sa.name = profile->name; + sa.name2 = ns->name; + aa_audit_status(NULL, &sa); + mutex_unlock(&aa_interface_lock); + return size; +} + +/** + * task_replace - replace a task's profile + * @task: task to replace profile on + * @new_cxt: new aa_task_context to do replacement with + * @new_profile: new profile + */ +static inline void task_replace(struct task_struct *task, + struct aa_task_context *new_cxt, + struct aa_profile *new_profile) +{ + struct aa_task_context *cxt = aa_task_context(task); + + AA_DEBUG("%s: replacing profile for task %d " + "profile=%s (%p)\n", + __FUNCTION__, + cxt->task->pid, + cxt->profile->name, cxt->profile); + + aa_change_task_context(task, new_cxt, new_profile, cxt->cookie, + cxt->previous_profile); +} + +/** + * aa_replace_profile - replace a profile on the profile list + * @udata: serialized data stream + * @size: size of the serialized data stream + * + * unpack and replace a profile on the profile list and uses of that profile + * by any aa_task_context. If the profile does not exist on the profile list + * it is added. Return %0 or error. + */ +ssize_t aa_replace_profile(void *udata, size_t size) +{ + struct aa_profile *old_profile, *new_profile; + struct aa_namespace *ns; + struct aa_task_context *new_cxt; + struct aa_ext e = { + .start = udata, + .end = udata + size, + .pos = udata, + .ns_name = NULL + }; + ssize_t error; + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "profile_replace"; + sa.gfp_mask = GFP_KERNEL; + + error = aa_verify_header(&e, &sa); + if (error) + return error; + + new_profile = aa_unpack_profile(&e, &sa); + if (IS_ERR(new_profile)) + return PTR_ERR(new_profile); + + mutex_lock(&aa_interface_lock); + write_lock(&profile_ns_list_lock); + if (e.ns_name) + ns = __aa_find_namespace(e.ns_name, &profile_ns_list); + else + ns = default_namespace; + if (!ns) { + struct aa_namespace *new_ns; + write_unlock(&profile_ns_list_lock); + new_ns = alloc_aa_namespace(e.ns_name); + if (!new_ns) { + mutex_unlock(&aa_interface_lock); + return -ENOMEM; + } + write_lock(&profile_ns_list_lock); + ns = __aa_find_namespace(e.ns_name, &profile_ns_list); + if (!ns) { + list_add(&new_ns->list, &profile_ns_list); + ns = new_ns; + } else + free_aa_namespace(new_ns); + } + + write_lock(&ns->lock); + old_profile = __aa_find_profile(new_profile->name, &ns->profiles); + if (old_profile) { + lock_profile(old_profile); + old_profile->isstale = 1; + list_del_init(&old_profile->list); + unlock_profile(old_profile); + ns->profile_count--; + } + new_profile->ns = aa_get_namespace(ns); + ns->profile_count++; + /* not don't need an extra ref count to keep new_profile as + * it is protect by the interface mutex */ + list_add(&new_profile->list, &ns->profiles); + write_unlock(&ns->lock); + write_unlock(&profile_ns_list_lock); + + if (!old_profile) { + sa.operation = "profile_load"; + goto out; + } + /* do not fail replacement based off of profile's NPROC rlimit */ + + /* + * Replacement needs to allocate a new aa_task_context for each + * task confined by old_profile. To do this the profile locks + * are only held when the actual switch is done per task. While + * looping to allocate a new aa_task_context the old_task list + * may get shorter if tasks exit/change their profile but will + * not get longer as new task will not use old_profile detecting + * that is stale. + */ + do { + new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL); + + lock_both_profiles(old_profile, new_profile); + if (!list_empty(&old_profile->task_contexts)) { + struct task_struct *task = + list_entry(old_profile->task_contexts.next, + struct aa_task_context, list)->task; + task_lock(task); + task_replace(task, new_cxt, new_profile); + task_unlock(task); + aa_set_rlimits(task, new_profile); + new_cxt = NULL; + } + unlock_both_profiles(old_profile, new_profile); + } while (!new_cxt); + aa_free_task_context(new_cxt); + aa_put_profile(old_profile); + +out: + sa.name = new_profile->name; + sa.name2 = ns->name; + aa_audit_status(NULL, &sa); + mutex_unlock(&aa_interface_lock); + return size; +} + +/** + * aa_remove_profile - remove a profile from the system + * @name: name of the profile to remove + * @size: size of the name + * + * remove a profile from the profile list and all aa_task_context references + * to said profile. + * NOTE: removing confinement does not restore rlimits to preconfinemnet values + */ +ssize_t aa_remove_profile(char *name, size_t size) +{ + struct aa_namespace *ns; + struct aa_profile *profile; + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "profile_remove"; + sa.gfp_mask = GFP_KERNEL; + + mutex_lock(&aa_interface_lock); + write_lock(&profile_ns_list_lock); + + if (name[0] == ':') { + char *split = strchr(name + 1, ':'); + if (!split) + goto noent; + *split = 0; + ns = __aa_find_namespace(name + 1, &profile_ns_list); + name = split + 1; + } else { + ns = default_namespace; + } + + if (!ns) + goto noent; + sa.name2 = ns->name; + write_lock(&ns->lock); + profile = __aa_find_profile(name, &ns->profiles); + if (!profile) { + write_unlock(&ns->lock); + goto noent; + } + sa.name = profile->name; + + /* Remove the profile from each task context it is on. */ + lock_profile(profile); + profile->isstale = 1; + aa_unconfine_tasks(profile); + list_del_init(&profile->list); + ns->profile_count--; + unlock_profile(profile); + /* Release the profile itself. */ + write_unlock(&ns->lock); + /* check to see if the namespace has become stale */ + if (ns != default_namespace && ns->profile_count == 0) { + list_del_init(&ns->list); + aa_put_namespace(ns); + } + write_unlock(&profile_ns_list_lock); + + aa_audit_status(NULL, &sa); + mutex_unlock(&aa_interface_lock); + aa_put_profile(profile); + + return size; + +noent: + write_unlock(&profile_ns_list_lock); + sa.info = "failed: profile does not exist"; + aa_audit_status(NULL, &sa); + mutex_unlock(&aa_interface_lock); + return -ENOENT; +} + +/** + * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace) + * @kr: kref callback for freeing of a namespace + */ +void free_aa_namespace_kref(struct kref *kref) +{ + struct aa_namespace *ns=container_of(kref, struct aa_namespace, count); + + free_aa_namespace(ns); +} + +/** + * alloc_aa_namespace - allocate, initialize and return a new namespace + * @name: a preallocated name + * Returns NULL on failure. + */ +struct aa_namespace *alloc_aa_namespace(char *name) +{ + struct aa_namespace *ns; + + ns = kzalloc(sizeof(*ns), GFP_KERNEL); + AA_DEBUG("%s(%p)\n", __FUNCTION__, ns); + if (ns) { + ns->name = name; + INIT_LIST_HEAD(&ns->list); + INIT_LIST_HEAD(&ns->profiles); + kref_init(&ns->count); + rwlock_init(&ns->lock); + + ns->null_complain_profile = alloc_aa_profile(); + if (!ns->null_complain_profile) { + if (!name) + kfree(ns->name); + kfree(ns); + return NULL; + } + ns->null_complain_profile->name = + kstrdup("null-complain-profile", GFP_KERNEL); + if (!ns->null_complain_profile->name) { + free_aa_profile(ns->null_complain_profile); + if (!name) + kfree(ns->name); + kfree(ns); + return NULL; + } + ns->null_complain_profile->flags.complain = 1; + /* null_complain_profile doesn't contribute to ns ref count */ + ns->null_complain_profile->ns = ns; + } + return ns; +} + +/** + * free_aa_namespace - free a profile namespace + * @namespace: the namespace to free + * + * Free a namespace. All references to the namespace must have been put. + * If the namespace was referenced by a profile confining a task, + * free_aa_namespace will be called indirectly (through free_aa_profile) + * from an rcu callback routine, so we must not sleep here. + */ +void free_aa_namespace(struct aa_namespace *ns) +{ + AA_DEBUG("%s(%p)\n", __FUNCTION__, ns); + + if (!ns) + return; + + /* namespace still contains profiles -- invalid */ + if (!list_empty(&ns->profiles)) { + AA_ERROR("%s: internal error, " + "namespace '%s' still contains profiles\n", + __FUNCTION__, + ns->name); + BUG(); + } + if (!list_empty(&ns->list)) { + AA_ERROR("%s: internal error, " + "namespace '%s' still on list\n", + __FUNCTION__, + ns->name); + BUG(); + } + /* null_complain_profile doesn't contribute to ns ref counting */ + ns->null_complain_profile->ns = NULL; + aa_put_profile(ns->null_complain_profile); + kfree(ns->name); + kfree(ns); +} + +/** + * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile) + * @kr: kref callback for freeing of a profile + */ +void free_aa_profile_kref(struct kref *kref) +{ + struct aa_profile *p=container_of(kref, struct aa_profile, count); + + free_aa_profile(p); +} + +/** + * alloc_aa_profile - allocate, initialize and return a new profile + * Returns NULL on failure. + */ +struct aa_profile *alloc_aa_profile(void) +{ + struct aa_profile *profile; + + profile = kzalloc(sizeof(*profile), GFP_KERNEL); + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile); + if (profile) { + INIT_LIST_HEAD(&profile->list); + kref_init(&profile->count); + INIT_LIST_HEAD(&profile->task_contexts); + spin_lock_init(&profile->lock); + } + return profile; +} + +/** + * free_aa_profile - free a profile + * @profile: the profile to free + * + * Free a profile, its hats and null_profile. All references to the profile, + * its hats and null_profile must have been put. + * + * If the profile was referenced from a task context, free_aa_profile() will + * be called from an rcu callback routine, so we must not sleep here. + */ +void free_aa_profile(struct aa_profile *profile) +{ + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile); + + if (!profile) + return; + + /* profile is still on profile namespace list -- invalid */ + if (!list_empty(&profile->list)) { + AA_ERROR("%s: internal error, " + "profile '%s' still on global list\n", + __FUNCTION__, + profile->name); + BUG(); + } + aa_put_namespace(profile->ns); + + aa_match_free(profile->file_rules); + + if (profile->name) { + AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name); + kfree(profile->name); + } + + kfree(profile); +} + +/** + * aa_unconfine_tasks - remove tasks on a profile's task context list + * @profile: profile to remove tasks from + * + * Assumes that @profile lock is held. + */ +void aa_unconfine_tasks(struct aa_profile *profile) +{ + while (!list_empty(&profile->task_contexts)) { + struct task_struct *task = + list_entry(profile->task_contexts.next, + struct aa_task_context, list)->task; + task_lock(task); + aa_change_task_context(task, NULL, NULL, 0, NULL); + task_unlock(task); + } +} --- linux-2.6.27.orig/security/apparmor/apparmor.h +++ linux-2.6.27/security/apparmor/apparmor.h @@ -0,0 +1,403 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor internal prototypes + */ + +#ifndef __APPARMOR_H +#define __APPARMOR_H + +#include +#include +#include +#include +#include +#include +#include + +/* + * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags + * for profile permissions + */ +#define AA_MAY_LINK 0x0010 +#define AA_MAY_LOCK 0x0020 +#define AA_EXEC_MMAP 0x0040 +#define AA_MAY_MOUNT 0x0080 /* no direct audit mapping */ +#define AA_EXEC_UNSAFE 0x0100 +#define AA_EXEC_INHERIT 0x0200 +#define AA_EXEC_MOD_0 0x0400 +#define AA_EXEC_MOD_1 0x0800 +#define AA_EXEC_MOD_2 0x1000 +#define AA_EXEC_MOD_3 0x2000 + +#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \ + MAY_APPEND | AA_MAY_LINK | \ + AA_MAY_LOCK | AA_EXEC_MMAP | \ + AA_MAY_MOUNT | AA_EXEC_UNSAFE | \ + AA_EXEC_INHERIT | AA_EXEC_MOD_0 | \ + AA_EXEC_MOD_1 | AA_EXEC_MOD_2 | \ + AA_EXEC_MOD_3) + +#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \ + AA_EXEC_MOD_2 | AA_EXEC_MOD_3) + +#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \ + AA_EXEC_MODIFIERS) + +#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0 +#define AA_EXEC_PROFILE AA_EXEC_MOD_1 +#define AA_EXEC_CHILD (AA_EXEC_MOD_0 | AA_EXEC_MOD_1) +/* remaining exec modes are index into profile name table */ +#define AA_EXEC_INDEX(mode) ((mode & AA_EXEC_MODIFIERS) >> 10) + +#define AA_USER_SHIFT 0 +#define AA_OTHER_SHIFT 14 + +#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT) +#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT) + +#define AA_FILE_PERMS (AA_USER_PERMS | AA_OTHER_PERMS) + +#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \ + (AA_MAY_LINK << AA_OTHER_SHIFT)) + +#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT) +#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT) + +#define AA_USER_EXEC_TYPE (AA_EXEC_TYPE << AA_USER_SHIFT) +#define AA_OTHER_EXEC_TYPE (AA_EXEC_TYPE << AA_OTHER_SHIFT) + +#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC) + +#define ALL_AA_EXEC_UNSAFE ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \ + (AA_EXEC_UNSAFE << AA_OTHER_SHIFT)) + +#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE) + +/* overloaded permissions for link pairs */ +#define AA_LINK_SUBSET_TEST 0x0020 + +#define AA_USER_PTRACE 0x10000000 +#define AA_OTHER_PTRACE 0x20000000 +#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE) + +/* shared permissions that are not duplicated in user::other */ +#define AA_CHANGE_HAT 0x40000000 +#define AA_CHANGE_PROFILE 0x80000000 + +#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE) + +#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_PTRACE_PERMS | \ + AA_SHARED_PERMS) + +/* audit bits for the second accept field */ +#define AUDIT_FILE_MASK 0x1fc07f +#define AUDIT_QUIET_MASK(mask) ((mask >> 7) & AUDIT_FILE_MASK) +#define AA_VALID_PERM2_MASK 0x0fffffff + +#define AA_SECURE_EXEC_NEEDED 1 + +/* Control parameters (0 or 1), settable thru module/boot flags or + * via /sys/kernel/security/apparmor/control */ +extern int apparmor_complain; +extern int apparmor_debug; +extern int apparmor_audit; +extern int apparmor_logsyscall; +extern unsigned int apparmor_path_max; + +#define PROFILE_COMPLAIN(_profile) \ + (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain)) + +#define APPARMOR_COMPLAIN(_cxt) \ + (apparmor_complain == 1 || \ + ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain)) + +#define PROFILE_AUDIT(_profile) \ + (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit)) + +#define APPARMOR_AUDIT(_cxt) \ + (apparmor_audit == 1 || \ + ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit)) + +#define PROFILE_IS_HAT(_profile) \ + ((_profile) && (_profile)->flags.hat) + +/* + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl + * which is not related to profile accesses. + */ + +#define AA_DEBUG(fmt, args...) \ + do { \ + if (apparmor_debug) \ + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \ + } while (0) + +#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args) + +/* struct aa_rlimit - rlimits settings for the profile + * @mask: which hard limits to set + * @limits: rlimit values that override task limits + * + * AppArmor rlimits are used to set confined task rlimits. Only the + * limits specified in @mask will be controlled by apparmor. + */ +struct aa_rlimit { + unsigned int mask; + struct rlimit limits[RLIM_NLIMITS]; +}; + +struct aa_profile; + +/* struct aa_namespace - namespace for a set of profiles + * @name: the name of the namespace + * @list: list the namespace is on + * @profiles: list of profile in the namespace + * @profile_count: the number of profiles in the namespace + * @null_complain_profile: special profile used for learning in this namespace + * @count: reference count on the namespace + * @lock: lock for adding/removing profile to the namespace + */ +struct aa_namespace { + char *name; + struct list_head list; + struct list_head profiles; + int profile_count; + struct aa_profile *null_complain_profile; + + struct kref count; + rwlock_t lock; +}; + +/* struct aa_profile - basic confinement data + * @name: the profiles name + * @list: list this profile is on + * @ns: namespace the profile is in + * @file_rules: dfa containing the profiles file rules + * @flags: flags controlling profile behavior + * @isstale: flag indicating if profile is stale + * @set_caps: capabilities that are being set + * @capabilities: capabilities mask + * @audit_caps: caps that are to be audited + * @quiet_caps: caps that should not be audited + * @capabilities: capabilities granted by the process + * @rlimits: rlimits for the profile + * @task_count: how many tasks the profile is attached to + * @count: reference count of the profile + * @task_contexts: list of tasks confined by profile + * @lock: lock for the task_contexts list + * @network_families: basic network permissions + * @audit_network: which network permissions to force audit + * @quiet_network: which network permissions to quiet rejects + * + * The AppArmor profile contains the basic confinement data. Each profile + * has a name, and all nonstale profile are in a profile namespace. + * + * The task_contexts list and the isstale flag are protected by the + * profile lock. + * + * If a task context is moved between two profiles, we first need to grab + * both profile locks. lock_both_profiles() does that in a deadlock-safe + * way. + */ +struct aa_profile { + char *name; + struct list_head list; + struct aa_namespace *ns; + + int exec_table_size; + char **exec_table; + struct aa_dfa *file_rules; + struct { + int hat; + int complain; + int audit; + } flags; + int isstale; + + kernel_cap_t set_caps; + kernel_cap_t capabilities; + kernel_cap_t audit_caps; + kernel_cap_t quiet_caps; + + struct aa_rlimit rlimits; + unsigned int task_count; + + struct kref count; + struct list_head task_contexts; + spinlock_t lock; + unsigned long int_flags; + u16 network_families[AF_MAX]; + u16 audit_network[AF_MAX]; + u16 quiet_network[AF_MAX]; +}; + +extern struct list_head profile_ns_list; +extern rwlock_t profile_ns_list_lock; +extern struct mutex aa_interface_lock; + +/** + * struct aa_task_context - primary label for confined tasks + * @profile: the current profile + * @previous_profile: profile the task may return to + * @cookie: magic value the task must know for returning to @previous_profile + * @list: list this aa_task_context is on + * @task: task that the aa_task_context confines + * @rcu: rcu head used when freeing the aa_task_context + * @caps_logged: caps that have previously generated log entries + * + * Contains the task's current profile (which could change due to + * change_hat). Plus the hat_magic needed during change_hat. + */ +struct aa_task_context { + struct aa_profile *profile; + struct aa_profile *previous_profile; + u64 cookie; + struct list_head list; + struct task_struct *task; + struct rcu_head rcu; + kernel_cap_t caps_logged; +}; + +extern struct aa_namespace *default_namespace; + +/* aa_audit - AppArmor auditing structure + * Structure is populated by access control code and passed to aa_audit which + * provides for a single point of logging. + */ + +struct aa_audit { + const char *operation; + gfp_t gfp_mask; + const char *info; + const char *name; + const char *name2; + const char *name3; + int request_mask, denied_mask, audit_mask; + int rlimit; + struct iattr *iattr; + pid_t task, parent; + int family, type, protocol; + int error_code; +}; + +/* Flags for the permission check functions */ +#define AA_CHECK_FD 1 /* coming from a file descriptor */ +#define AA_CHECK_DIR 2 /* file type is directory */ + +/* lock subtypes so lockdep does not raise false dependencies */ +enum aa_lock_class { + aa_lock_normal, + aa_lock_nested, + aa_lock_task_release +}; + +/* main.c */ +extern int alloc_default_namespace(void); +extern void free_default_namespace(void); +extern int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa, + int type); +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa); +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa); +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa); +extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp, + const char *); +extern int aa_audit(struct aa_profile *profile, struct aa_audit *); + +extern int aa_attr(struct aa_profile *profile, struct dentry *dentry, + struct vfsmount *mnt, struct iattr *iattr); +extern int aa_perm_xattr(struct aa_profile *profile, const char *operation, + struct dentry *dentry, struct vfsmount *mnt, + int mask, int check); +extern int aa_capability(struct aa_task_context *cxt, int cap); +extern int aa_perm(struct aa_profile *profile, const char *operation, + struct dentry *dentry, struct vfsmount *mnt, int mask, + int check); +extern int aa_perm_dir(struct aa_profile *profile, const char *operation, + struct dentry *dentry, struct vfsmount *mnt, + int mask); +extern int aa_perm_path(struct aa_profile *, const char *operation, + const char *name, int mask, uid_t uid); +extern int aa_link(struct aa_profile *profile, + struct dentry *link, struct vfsmount *link_mnt, + struct dentry *target, struct vfsmount *target_mnt); +extern int aa_clone(struct task_struct *task); +extern int aa_register(struct linux_binprm *bprm); +extern void aa_release(struct task_struct *task); +extern int aa_change_hat(const char *id, u64 hat_magic); +extern int aa_change_profile(const char *ns_name, const char *name); +extern struct aa_profile *__aa_replace_profile(struct task_struct *task, + struct aa_profile *profile); +extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task, + struct aa_profile *profile); +extern void unlock_task_and_profiles(struct task_struct *task, + struct aa_task_context *cxt, + struct aa_profile *profile); +extern void aa_change_task_context(struct task_struct *task, + struct aa_task_context *new_cxt, + struct aa_profile *profile, u64 cookie, + struct aa_profile *previous_profile); +extern int aa_may_ptrace(struct aa_task_context *cxt, + struct aa_profile *tracee); +extern int aa_net_perm(struct aa_profile *profile, char *operation, + int family, int type, int protocol); +extern int aa_revalidate_sk(struct sock *sk, char *operation); +extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, + struct rlimit *new_rlim); +extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile); + + +/* lsm.c */ +extern int apparmor_initialized; +extern void info_message(const char *str); +extern void apparmor_disable(void); + +/* list.c */ +extern struct aa_namespace *__aa_find_namespace(const char *name, + struct list_head *list); +extern struct aa_profile *__aa_find_profile(const char *name, + struct list_head *list); +extern void aa_profile_ns_list_release(void); + +/* module_interface.c */ +extern ssize_t aa_add_profile(void *, size_t); +extern ssize_t aa_replace_profile(void *, size_t); +extern ssize_t aa_remove_profile(char *, size_t); +extern struct aa_namespace *alloc_aa_namespace(char *name); +extern void free_aa_namespace(struct aa_namespace *ns); +extern void free_aa_namespace_kref(struct kref *kref); +extern struct aa_profile *alloc_aa_profile(void); +extern void free_aa_profile(struct aa_profile *profile); +extern void free_aa_profile_kref(struct kref *kref); +extern void aa_unconfine_tasks(struct aa_profile *profile); + +/* procattr.c */ +extern int aa_getprocattr(struct aa_profile *profile, char **string, + unsigned *len); +extern int aa_setprocattr_changehat(char *args); +extern int aa_setprocattr_changeprofile(char *args); +extern int aa_setprocattr_setprofile(struct task_struct *task, char *args); + +/* apparmorfs.c */ +extern int create_apparmorfs(void); +extern void destroy_apparmorfs(void); + +/* match.c */ +extern struct aa_dfa *aa_match_alloc(void); +extern void aa_match_free(struct aa_dfa *dfa); +extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size); +extern int verify_dfa(struct aa_dfa *dfa); +extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *); +extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start, + const char *str); +extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start, + const char *str, unsigned int *final); +extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, + unsigned int start); + +#endif /* __APPARMOR_H */ --- linux-2.6.27.orig/security/apparmor/lsm.c +++ linux-2.6.27/security/apparmor/lsm.c @@ -0,0 +1,1060 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor LSM interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "apparmor.h" +#include "inline.h" + +/* Flag indicating whether initialization completed */ +int apparmor_initialized = 0; + +static int param_set_aabool(const char *val, struct kernel_param *kp); +static int param_get_aabool(char *buffer, struct kernel_param *kp); +#define param_check_aabool(name, p) __param_check(name, p, int) + +static int param_set_aauint(const char *val, struct kernel_param *kp); +static int param_get_aauint(char *buffer, struct kernel_param *kp); +#define param_check_aauint(name, p) __param_check(name, p, int) + +/* Flag values, also controllable via /sys/module/apparmor/parameters + * We define special types as we want to do additional mediation. + * + * Complain mode -- in complain mode access failures result in auditing only + * and task is allowed access. audit events are processed by userspace to + * generate policy. Default is 'enforce' (0). + * Value is also togglable per profile and referenced when global value is + * enforce. + */ +int apparmor_complain = 0; +module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode"); + +/* Debug mode */ +int apparmor_debug = 0; +module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode"); + +/* Audit mode */ +int apparmor_audit = 0; +module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode"); + +/* Syscall logging mode */ +int apparmor_logsyscall = 0; +module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode"); + +/* Maximum pathname length before accesses will start getting rejected */ +unsigned int apparmor_path_max = 2 * PATH_MAX; +module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed"); + +/* Boot time disable flag */ +#ifdef CONFIG_SECURITY_APPARMOR_DISABLE +#define AA_ENABLED_PERMS 0600 +#else +#define AA_ENABLED_PERMS 0400 +#endif +static int param_set_aa_enabled(const char *val, struct kernel_param *kp); +unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE; +module_param_call(enabled, param_set_aa_enabled, param_get_aauint, + &apparmor_enabled, AA_ENABLED_PERMS); +MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot"); + +static int __init apparmor_enabled_setup(char *str) +{ + apparmor_enabled = simple_strtol(str, NULL, 0); + return 1; +} +__setup("apparmor=", apparmor_enabled_setup); + +static int param_set_aabool(const char *val, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_set_bool(val, kp); +} + +static int param_get_aabool(char *buffer, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_get_bool(buffer, kp); +} + +static int param_set_aauint(const char *val, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_set_uint(val, kp); +} + +static int param_get_aauint(char *buffer, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_get_uint(buffer, kp); +} + +/* allow run time disabling of apparmor */ +static int param_set_aa_enabled(const char *val, struct kernel_param *kp) +{ + char *endp; + unsigned long l; + + if (!apparmor_initialized) { + apparmor_enabled = 0; + return 0; + } + + if (aa_task_context(current)) + return -EPERM; + + if (!apparmor_enabled) + return -EINVAL; + + if (!val) + return -EINVAL; + + l = simple_strtoul(val, &endp, 0); + if (endp == val || l != 0) + return -EINVAL; + + apparmor_enabled = 0; + apparmor_disable(); + return 0; +} + +static int aa_reject_syscall(struct task_struct *task, gfp_t flags, + const char *name) +{ + struct aa_profile *profile = aa_get_profile(task); + int error = 0; + + if (profile) { + error = aa_audit_syscallreject(profile, flags, name); + aa_put_profile(profile); + } + + return error; +} + +static int apparmor_ptrace(struct task_struct *tracer, + struct task_struct *tracee) +{ + struct aa_task_context *cxt; + int error = 0; + + /* + * tracer can ptrace tracee when + * - tracer is unconfined + * - tracer & tracee are in the same namespace && + * - tracer is in complain mode + * - tracer and tracee are confined by the same profile + * - tracer profile has CAP_SYS_PTRACE + */ + + rcu_read_lock(); + cxt = aa_task_context(tracer); + if (cxt) { + if (tracer->nsproxy != tracee->nsproxy) { + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "ptrace"; + sa.gfp_mask = GFP_ATOMIC; + sa.parent = tracer->pid; + sa.task = tracee->pid; + sa.info = "different namespaces"; + aa_audit_reject(cxt->profile, &sa); + error = -EPERM; + } else { + struct aa_task_context *tracee_cxt = + aa_task_context(tracee); + + error = aa_may_ptrace(cxt, tracee_cxt ? + tracee_cxt->profile : NULL); + if (error && PROFILE_COMPLAIN(cxt->profile)) { + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "ptrace"; + sa.gfp_mask = GFP_ATOMIC; + sa.parent = tracer->pid; + sa.task = tracee->pid; + aa_audit_hint(cxt->profile, &sa); + } + } + } + rcu_read_unlock(); + + return error; +} + +static int apparmor_ptrace_may_access(struct task_struct *child, + unsigned int mode) +{ + return apparmor_ptrace(current, child); +} + + +static int apparmor_ptrace_traceme(struct task_struct *parent) +{ + return apparmor_ptrace(parent, current); +} + +static int apparmor_capable(struct task_struct *task, int cap) +{ + int error; + struct aa_task_context *cxt; + + /* cap_capable returns 0 on success, else -EPERM */ + error = cap_capable(task, cap); + + rcu_read_lock(); + cxt = aa_task_context(task); + if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap))) + error = aa_capability(cxt, cap); + rcu_read_unlock(); + + return error; +} + +static int apparmor_sysctl(struct ctl_table *table, int op) +{ + struct aa_profile *profile = aa_get_profile(current); + int error = 0; + + if (profile) { + char *buffer, *name; + int mask; + + mask = 0; + if (op & 4) + mask |= MAY_READ; + if (op & 2) + mask |= MAY_WRITE; + + error = -ENOMEM; + buffer = (char*)__get_free_page(GFP_KERNEL); + if (!buffer) + goto out; + name = sysctl_pathname(table, buffer, PAGE_SIZE); + if (name && name - buffer >= 5) { + name -= 5; + memcpy(name, "/proc", 5); + error = aa_perm_path(profile, "sysctl", name, mask, 0); + } + free_page((unsigned long)buffer); + } + +out: + aa_put_profile(profile); + return error; +} + +static int apparmor_bprm_set_security(struct linux_binprm *bprm) +{ + /* handle capability bits with setuid, etc */ + cap_bprm_set_security(bprm); + /* already set based on script name */ + if (bprm->sh_bang) + return 0; + return aa_register(bprm); +} + +static int apparmor_bprm_secureexec(struct linux_binprm *bprm) +{ + int ret = cap_bprm_secureexec(bprm); + + if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) { + AA_DEBUG("%s: secureexec required for %s\n", + __FUNCTION__, bprm->filename); + ret = 1; + } + + return ret; +} + +static int apparmor_sb_mount(char *dev_name, struct path *path, char *type, + unsigned long flags, void *data) +{ + return aa_reject_syscall(current, GFP_KERNEL, "mount"); +} + +static int apparmor_umount(struct vfsmount *mnt, int flags) +{ + return aa_reject_syscall(current, GFP_KERNEL, "umount"); +} + +static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mask) +{ + struct aa_profile *profile; + int error = 0; + + if (!mnt || !mediated_filesystem(dir)) + goto out; + + profile = aa_get_profile(current); + + if (profile) + error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt, + MAY_WRITE); + + aa_put_profile(profile); + +out: + return error; +} + +static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) +{ + struct aa_profile *profile; + int error = 0; + + if (!mnt || !mediated_filesystem(dir)) + goto out; + + profile = aa_get_profile(current); + + if (profile) + error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt, + MAY_WRITE); + + aa_put_profile(profile); + +out: + return error; +} + +static int aa_permission(const char *operation, struct inode *inode, + struct dentry *dentry, struct vfsmount *mnt, + int mask, int check) +{ + int error = 0; + + if (mnt && mediated_filesystem(inode)) { + struct aa_profile *profile; + + profile = aa_get_profile(current); + if (profile) + error = aa_perm(profile, operation, dentry, mnt, mask, + check); + aa_put_profile(profile); + } + return error; +} + +static inline int aa_mask_permissions(int mask) +{ + if (mask & MAY_APPEND) + mask &= (MAY_READ | MAY_APPEND | MAY_EXEC); + else + mask &= (MAY_READ | MAY_WRITE | MAY_EXEC); + return mask; +} + +static int apparmor_inode_create(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mask) +{ + return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0); +} + +static int apparmor_inode_link(struct dentry *old_dentry, + struct vfsmount *old_mnt, struct inode *dir, + struct dentry *new_dentry, + struct vfsmount *new_mnt) +{ + int error = 0; + struct aa_profile *profile; + + if (!old_mnt || !new_mnt || !mediated_filesystem(dir)) + goto out; + + profile = aa_get_profile(current); + + if (profile) + error = aa_link(profile, new_dentry, new_mnt, + old_dentry, old_mnt); + + aa_put_profile(profile); + +out: + return error; +} + +static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) +{ + int check = 0; + + if (S_ISDIR(dentry->d_inode->i_mode)) + check |= AA_CHECK_DIR; + return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE, + check); +} + +static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *old_name) +{ + return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0); +} + +static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode, dev_t dev) +{ + return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0); +} + +static int apparmor_inode_rename(struct inode *old_dir, + struct dentry *old_dentry, + struct vfsmount *old_mnt, + struct inode *new_dir, + struct dentry *new_dentry, + struct vfsmount *new_mnt) +{ + struct aa_profile *profile; + int error = 0; + + if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir)) + goto out; + + profile = aa_get_profile(current); + + if (profile) { + struct inode *inode = old_dentry->d_inode; + int check = 0; + + if (inode && S_ISDIR(inode->i_mode)) + check |= AA_CHECK_DIR; + if (old_mnt) + error = aa_perm(profile, "inode_rename", old_dentry, + old_mnt, MAY_READ | MAY_WRITE, check); + + if (!error && new_mnt) { + error = aa_perm(profile, "inode_rename", new_dentry, + new_mnt, MAY_WRITE, check); + } + } + + aa_put_profile(profile); + +out: + return error; +} + +static int apparmor_inode_permission(struct inode *inode, int mask) +{ + return 0; +} + +static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *iattr) +{ + int error = 0; + + if (!mnt) + goto out; + + if (mediated_filesystem(dentry->d_inode)) { + struct aa_profile *profile; + + profile = aa_get_profile(current); + /* + * Mediate any attempt to change attributes of a file + * (chmod, chown, chgrp, etc) + */ + if (profile) + error = aa_attr(profile, dentry, mnt, iattr); + + aa_put_profile(profile); + } + +out: + return error; +} + +static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt, + const char *operation, int mask, + struct file *file) +{ + int error = 0; + + if (mnt && mediated_filesystem(dentry->d_inode)) { + struct aa_profile *profile = aa_get_profile(current); + int check = file ? AA_CHECK_FD : 0; + + if (profile) + error = aa_perm_xattr(profile, operation, dentry, mnt, + mask, check); + aa_put_profile(profile); + } + + return error; +} + +static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags, struct file *file) +{ + int error = cap_inode_setxattr(dentry, mnt, name, value, size, flags, + file); + + if (!error) + error = aa_xattr_permission(dentry, mnt, "xattr set", + MAY_WRITE, file); + return error; +} + +static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file) +{ + return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file); +} + +static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt, + struct file *file) +{ + return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file); +} + +static int apparmor_inode_removexattr(struct dentry *dentry, + struct vfsmount *mnt, const char *name, + struct file *file) +{ + return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE, + file); +} + +static int aa_file_permission(const char *op, struct file *file, int mask) +{ + struct aa_profile *profile; + struct aa_profile *file_profile = (struct aa_profile*)file->f_security; + int error = 0; + + if (!file_profile) + goto out; + + /* + * If this file was opened under a different profile, we + * revalidate the access against the current profile. + */ + profile = aa_get_profile(current); + if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) { + struct dentry *dentry = file->f_dentry; + struct vfsmount *mnt = file->f_vfsmnt; + struct inode *inode = dentry->d_inode; + int check = AA_CHECK_FD; + + /* + * FIXME: We should remember which profiles we revalidated + * against. + */ + if (S_ISDIR(inode->i_mode)) + check |= AA_CHECK_DIR; + error = aa_permission(op, inode, dentry, mnt, mask, check); + } + aa_put_profile(profile); + +out: + return error; +} + +static int apparmor_file_permission(struct file *file, int mask) +{ + return aa_file_permission("file_permission", file, + aa_mask_permissions(mask)); +} + +static inline int apparmor_file_lock (struct file *file, unsigned int cmd) +{ + int mask = AA_MAY_LOCK; + if (cmd == F_WRLCK) + mask |= MAY_WRITE; + return aa_file_permission("file_lock", file, mask); +} + +static int apparmor_file_alloc_security(struct file *file) +{ + struct aa_profile *profile; + + profile = aa_get_profile(current); + if (profile) + file->f_security = profile; + + return 0; +} + +static void apparmor_file_free_security(struct file *file) +{ + struct aa_profile *file_profile = (struct aa_profile*)file->f_security; + + aa_put_profile(file_profile); +} + +static inline int aa_mmap(struct file *file, const char *operation, + unsigned long prot, unsigned long flags) +{ + struct dentry *dentry; + int mask = 0; + + if (!file || !file->f_security) + return 0; + + if (prot & PROT_READ) + mask |= MAY_READ; + /* Private mappings don't require write perms since they don't + * write back to the files */ + if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE)) + mask |= MAY_WRITE; + if (prot & PROT_EXEC) + mask |= AA_EXEC_MMAP; + + dentry = file->f_dentry; + return aa_permission(operation, dentry->d_inode, dentry, + file->f_vfsmnt, mask, AA_CHECK_FD); +} + +static int apparmor_file_mmap(struct file *file, unsigned long reqprot, + unsigned long prot, unsigned long flags, + unsigned long addr, unsigned long addr_only) +{ + if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) { + struct aa_profile *profile = aa_get_profile(current); + if (profile) + /* future control check here */ + return -EACCES; + else + return -EACCES; + aa_put_profile(profile); + } + + return aa_mmap(file, "file_mmap", prot, flags); +} + +static int apparmor_file_mprotect(struct vm_area_struct *vma, + unsigned long reqprot, unsigned long prot) +{ + return aa_mmap(vma->vm_file, "file_mprotect", prot, + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); +} + +static int apparmor_path_permission(struct path *path, int mask) +{ + struct inode *inode; + int check = 0; + + if (!path) + return 0; + + inode = path->dentry->d_inode; + + mask = aa_mask_permissions(mask); + if (S_ISDIR(inode->i_mode)) { + check |= AA_CHECK_DIR; + /* allow traverse accesses to directories */ + mask &= ~MAY_EXEC; + if (!mask) + return 0; + } + + return aa_permission("inode_permission", inode, path->dentry, + path->mnt, mask, check); +} + +static int apparmor_task_alloc_security(struct task_struct *task) +{ + return aa_clone(task); +} + +/* + * Called from IRQ context from RCU callback. + */ +static void apparmor_task_free_security(struct task_struct *task) +{ + aa_release(task); +} + +static int apparmor_socket_create(int family, int type, int protocol, int kern) +{ + struct aa_profile *profile; + int error = 0; + + if (kern) + return 0; + + profile = aa_get_profile(current); + if (profile) + error = aa_net_perm(profile, "socket_create", family, + type, protocol); + aa_put_profile(profile); + + return error; +} + +static int apparmor_socket_post_create(struct socket *sock, int family, + int type, int protocol, int kern) +{ + struct sock *sk = sock->sk; + + if (kern) + return 0; + + return aa_revalidate_sk(sk, "socket_post_create"); +} + +static int apparmor_socket_bind(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_bind"); +} + +static int apparmor_socket_connect(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_connect"); +} + +static int apparmor_socket_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_listen"); +} + +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_accept"); +} + +static int apparmor_socket_sendmsg(struct socket *sock, + struct msghdr *msg, int size) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_sendmsg"); +} + +static int apparmor_socket_recvmsg(struct socket *sock, + struct msghdr *msg, int size, int flags) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_recvmsg"); +} + +static int apparmor_socket_getsockname(struct socket *sock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_getsockname"); +} + +static int apparmor_socket_getpeername(struct socket *sock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_getpeername"); +} + +static int apparmor_socket_getsockopt(struct socket *sock, int level, + int optname) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_getsockopt"); +} + +static int apparmor_socket_setsockopt(struct socket *sock, int level, + int optname) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_setsockopt"); +} + +static int apparmor_socket_shutdown(struct socket *sock, int how) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(sk, "socket_shutdown"); +} + +static int apparmor_getprocattr(struct task_struct *task, char *name, + char **value) +{ + unsigned len; + int error; + struct aa_profile *profile; + + /* AppArmor only supports the "current" process attribute */ + if (strcmp(name, "current") != 0) + return -EINVAL; + + /* must be task querying itself or admin */ + if (current != task && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + profile = aa_get_profile(task); + error = aa_getprocattr(profile, value, &len); + aa_put_profile(profile); + if (!error) + error = len; + + return error; +} + +static int apparmor_setprocattr(struct task_struct *task, char *name, + void *value, size_t size) +{ + char *command, *args; + int error; + + if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE) + return -EINVAL; + args = value; + args[size] = '\0'; + args = strstrip(args); + command = strsep(&args, " "); + if (!args) + return -EINVAL; + while (isspace(*args)) + args++; + if (!*args) + return -EINVAL; + + if (strcmp(command, "changehat") == 0) { + if (current != task) + return -EACCES; + error = aa_setprocattr_changehat(args); + } else if (strcmp(command, "changeprofile") == 0) { + if (current != task) + return -EACCES; + error = aa_setprocattr_changeprofile(args); + } else if (strcmp(command, "setprofile") == 0) { + struct aa_profile *profile; + + /* Only an unconfined process with admin capabilities + * may change the profile of another task. + */ + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + profile = aa_get_profile(current); + if (profile) { + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "profile_set"; + sa.gfp_mask = GFP_KERNEL; + sa.task = task->pid; + sa.info = "from confined process"; + aa_audit_reject(profile, &sa); + aa_put_profile(profile); + return -EACCES; + } + error = aa_setprocattr_setprofile(task, args); + } else { + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "setprocattr"; + sa.gfp_mask = GFP_KERNEL; + sa.info = "invalid command"; + sa.name = command; + sa.task = task->pid; + aa_audit_reject(NULL, &sa); + return -EINVAL; + } + + if (!error) + error = size; + return error; +} + +static int apparmor_task_setrlimit(unsigned int resource, + struct rlimit *new_rlim) +{ + struct aa_profile *profile; + int error = 0; + + profile = aa_get_profile(current); + if (profile) { + error = aa_task_setrlimit(profile, resource, new_rlim); + } + aa_put_profile(profile); + + return error; +} + +struct security_operations apparmor_ops = { + .ptrace_may_access = apparmor_ptrace_may_access, + .ptrace_traceme = apparmor_ptrace_traceme, + .capget = cap_capget, + .capset_check = cap_capset_check, + .capset_set = cap_capset_set, + .sysctl = apparmor_sysctl, + .capable = apparmor_capable, + .syslog = cap_syslog, + + .bprm_apply_creds = cap_bprm_apply_creds, + .bprm_set_security = apparmor_bprm_set_security, + .bprm_secureexec = apparmor_bprm_secureexec, + + .sb_mount = apparmor_sb_mount, + .sb_umount = apparmor_umount, + + .inode_mkdir = apparmor_inode_mkdir, + .inode_rmdir = apparmor_inode_rmdir, + .inode_create = apparmor_inode_create, + .inode_link = apparmor_inode_link, + .inode_unlink = apparmor_inode_unlink, + .inode_symlink = apparmor_inode_symlink, + .inode_mknod = apparmor_inode_mknod, + .inode_rename = apparmor_inode_rename, + .inode_permission = apparmor_inode_permission, + .inode_setattr = apparmor_inode_setattr, + .inode_setxattr = apparmor_inode_setxattr, + .inode_getxattr = apparmor_inode_getxattr, + .inode_listxattr = apparmor_inode_listxattr, + .inode_removexattr = apparmor_inode_removexattr, + .file_permission = apparmor_file_permission, + .file_alloc_security = apparmor_file_alloc_security, + .file_free_security = apparmor_file_free_security, + .file_mmap = apparmor_file_mmap, + .file_mprotect = apparmor_file_mprotect, + .file_lock = apparmor_file_lock, + + .path_permission = apparmor_path_permission, + + .task_alloc_security = apparmor_task_alloc_security, + .task_free_security = apparmor_task_free_security, + .task_post_setuid = cap_task_post_setuid, + .task_reparent_to_init = cap_task_reparent_to_init, + .task_setrlimit = apparmor_task_setrlimit, + + .getprocattr = apparmor_getprocattr, + .setprocattr = apparmor_setprocattr, + + .socket_create = apparmor_socket_create, + .socket_post_create = apparmor_socket_post_create, + .socket_bind = apparmor_socket_bind, + .socket_connect = apparmor_socket_connect, + .socket_listen = apparmor_socket_listen, + .socket_accept = apparmor_socket_accept, + .socket_sendmsg = apparmor_socket_sendmsg, + .socket_recvmsg = apparmor_socket_recvmsg, + .socket_getsockname = apparmor_socket_getsockname, + .socket_getpeername = apparmor_socket_getpeername, + .socket_getsockopt = apparmor_socket_getsockopt, + .socket_setsockopt = apparmor_socket_setsockopt, + .socket_shutdown = apparmor_socket_shutdown, +}; + +void info_message(const char *str) +{ + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.gfp_mask = GFP_KERNEL; + sa.info = str; + printk(KERN_INFO "AppArmor: %s\n", str); + if (audit_enabled) + aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS); +} + +static int __init apparmor_init(void) +{ + int error; + + if (!apparmor_enabled) { + info_message("AppArmor disabled by boottime parameter\n"); + return 0; + } + + if ((error = create_apparmorfs())) { + AA_ERROR("Unable to activate AppArmor filesystem\n"); + goto createfs_out; + } + + if ((error = alloc_default_namespace())){ + AA_ERROR("Unable to allocate default profile namespace\n"); + goto alloc_out; + } + + if ((error = register_security(&apparmor_ops))) { + AA_ERROR("Unable to register AppArmor\n"); + goto register_security_out; + } + + /* Report that AppArmor successfully initialized */ + apparmor_initialized = 1; + if (apparmor_complain) + info_message("AppArmor initialized: complainmode enabled"); + else + info_message("AppArmor initialized"); + + return error; + +register_security_out: + free_default_namespace(); + +alloc_out: + destroy_apparmorfs(); + +createfs_out: + return error; + +} + +security_initcall(apparmor_init); + +void apparmor_disable(void) +{ + /* Remove and release all the profiles on the profile list. */ + mutex_lock(&aa_interface_lock); + aa_profile_ns_list_release(); + + /* FIXME: cleanup profiles references on files */ + free_default_namespace(); + + /* + * Delay for an rcu cycle to make sure that all active task + * context readers have finished, and all profiles have been + * freed by their rcu callbacks. + */ + synchronize_rcu(); + + destroy_apparmorfs(); + mutex_unlock(&aa_interface_lock); + + apparmor_initialized = 0; + + info_message("AppArmor protection removed"); +} + +MODULE_DESCRIPTION("AppArmor process confinement"); +MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org"); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/security/apparmor/Kconfig +++ linux-2.6.27/security/apparmor/Kconfig @@ -0,0 +1,42 @@ +config SECURITY_APPARMOR + bool "AppArmor support" + depends on SECURITY + select AUDIT + help + This enables the AppArmor security module. + Required userspace tools (if they are not included in your + distribution) and further information may be found at + + + If you are unsure how to answer this question, answer N. + +config SECURITY_APPARMOR_BOOTPARAM_VALUE + int "AppArmor boot parameter default value" + depends on SECURITY_APPARMOR + range 0 1 + default 1 + help + This option sets the default value for the kernel parameter + 'apparmor', which allows AppArmor to be enabled or disabled + at boot. If this option is set to 0 (zero), the AppArmor + kernel parameter will default to 0, disabling AppArmor at + bootup. If this option is set to 1 (one), the AppArmor + kernel parameter will default to 1, enabling AppArmor at + bootup. + + If you are unsure how to answer this question, answer 1. + +config SECURITY_APPARMOR_DISABLE + bool "AppArmor runtime disable" + depends on SECURITY_APPARMOR + default n + help + This option enables writing to a apparmorfs node 'disable', which + allows AppArmor to be disabled at runtime prior to the policy load. + AppArmor will then remain disabled until the next boot. + This option is similar to the apparmor.enabled=0 boot parameter, + but is to support runtime disabling of AppArmor, e.g. from + /sbin/init, for portability across platforms where boot + parameters are difficult to employ. + + If you are unsure how to answer this question, answer N. --- linux-2.6.27.orig/security/apparmor/main.c +++ linux-2.6.27/security/apparmor/main.c @@ -0,0 +1,1690 @@ +/* + * Copyright (C) 2002-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor Core + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "apparmor.h" + +#include "inline.h" + +/* + * Table of capability names: we generate it from capabilities.h. + */ +static const char *capability_names[] = { +#include "capability_names.h" +}; + +struct aa_namespace *default_namespace; + +static int aa_inode_mode(struct inode *inode) +{ + /* if the inode doesn't exist the user is creating it */ + if (!inode || current->fsuid == inode->i_uid) + return AA_USER_SHIFT; + return AA_OTHER_SHIFT; +} + +int alloc_default_namespace(void) +{ + struct aa_namespace *ns; + char *name = kstrdup("default", GFP_KERNEL); + if (!name) + return -ENOMEM; + ns = alloc_aa_namespace(name); + if (!ns) { + kfree(name); + return -ENOMEM; + } + + write_lock(&profile_ns_list_lock); + default_namespace = ns; + aa_get_namespace(ns); + list_add(&ns->list, &profile_ns_list); + write_unlock(&profile_ns_list_lock); + + return 0; +} + +void free_default_namespace(void) +{ + write_lock(&profile_ns_list_lock); + list_del_init(&default_namespace->list); + write_unlock(&profile_ns_list_lock); + aa_put_namespace(default_namespace); + default_namespace = NULL; +} + +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer, + int mask) +{ + const char unsafex[] = "upcn"; + const char safex[] = "UPCN"; + char *m = buffer; + + if (mask & AA_EXEC_MMAP) + *m++ = 'm'; + if (mask & MAY_READ) + *m++ = 'r'; + if (mask & MAY_WRITE) + *m++ = 'w'; + else if (mask & MAY_APPEND) + *m++ = 'a'; + if (mask & MAY_EXEC) { + int index = AA_EXEC_INDEX(mask); + /* all indexes > 4 are also named transitions */ + if (index > 4) + index = 4; + if (index > 0) { + if (mask & AA_EXEC_UNSAFE) + *m++ = unsafex[index - 1]; + else + *m++ = safex[index - 1]; + } + if (mask & AA_EXEC_INHERIT) + *m++ = 'i'; + *m++ = 'x'; + } + if (mask & AA_MAY_LINK) + *m++ = 'l'; + if (mask & AA_MAY_LOCK) + *m++ = 'k'; + *m++ = '\0'; +} + +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name, + int mask) +{ + char user[10], other[10]; + + aa_audit_file_sub_mask(ab, user, + (mask & AA_USER_PERMS) >> AA_USER_SHIFT); + aa_audit_file_sub_mask(ab, other, + (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT); + + audit_log_format(ab, " %s=\"%s::%s\"", name, user, other); +} + +static const char *address_families[] = { +#include "af_names.h" +}; + +static const char *sock_types[] = { + "unknown(0)", + "stream", + "dgram", + "raw", + "rdm", + "seqpacket", + "dccp", + "unknown(7)", + "unknown(8)", + "unknown(9)", + "packet", +}; + +/** + * aa_audit - Log an audit event to the audit subsystem + * @profile: profile to check against + * @sa: audit event + * @audit_cxt: audit context to log message to + * @type: audit event number + */ +static int aa_audit_base(struct aa_profile *profile, struct aa_audit *sa, + struct audit_context *audit_cxt, int type) +{ + struct audit_buffer *ab = NULL; + + ab = audit_log_start(audit_cxt, sa->gfp_mask, type); + + if (!ab) { + AA_ERROR("Unable to log event (%d) to audit subsys\n", + type); + /* don't fail operations in complain mode even if logging + * fails */ + return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM; + } + + if (sa->operation) + audit_log_format(ab, "operation=\"%s\"", sa->operation); + + if (sa->info) { + audit_log_format(ab, " info=\"%s\"", sa->info); + if (sa->error_code) + audit_log_format(ab, " error=%d", sa->error_code); + } + + if (sa->request_mask) + aa_audit_file_mask(ab, "requested_mask", sa->request_mask); + + if (sa->denied_mask) + aa_audit_file_mask(ab, "denied_mask", sa->denied_mask); + + if (sa->request_mask) + audit_log_format(ab, " fsuid=%d", current->fsuid); + + if (sa->rlimit) + audit_log_format(ab, " rlimit=%d", sa->rlimit - 1); + + if (sa->iattr) { + struct iattr *iattr = sa->iattr; + + audit_log_format(ab, " attribute=\"%s%s%s%s%s%s%s\"", + iattr->ia_valid & ATTR_MODE ? "mode," : "", + iattr->ia_valid & ATTR_UID ? "uid," : "", + iattr->ia_valid & ATTR_GID ? "gid," : "", + iattr->ia_valid & ATTR_SIZE ? "size," : "", + iattr->ia_valid & (ATTR_ATIME | ATTR_ATIME_SET) ? + "atime," : "", + iattr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET) ? + "mtime," : "", + iattr->ia_valid & ATTR_CTIME ? "ctime," : ""); + } + + if (sa->task) + audit_log_format(ab, " task=%d", sa->task); + + if (sa->parent) + audit_log_format(ab, " parent=%d", sa->parent); + + if (sa->name) { + audit_log_format(ab, " name="); + audit_log_untrustedstring(ab, sa->name); + } + + if (sa->name2) { + audit_log_format(ab, " name2="); + audit_log_untrustedstring(ab, sa->name2); + } + + if (sa->family || sa->type) { + if (address_families[sa->family]) + audit_log_format(ab, " family=\"%s\"", + address_families[sa->family]); + else + audit_log_format(ab, " family=\"unknown(%d)\"", + sa->family); + + if (sock_types[sa->type]) + audit_log_format(ab, " sock_type=\"%s\"", + sock_types[sa->type]); + else + audit_log_format(ab, " sock_type=\"unknown(%d)\"", + sa->type); + + audit_log_format(ab, " protocol=%d", sa->protocol); + } + + audit_log_format(ab, " pid=%d", current->pid); + + if (profile) { + audit_log_format(ab, " profile="); + audit_log_untrustedstring(ab, profile->name); + + if (profile->ns != default_namespace) { + audit_log_format(ab, " namespace="); + audit_log_untrustedstring(ab, profile->ns->name); + } + } + + audit_log_end(ab); + + return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error_code; +} + +/** + * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem + * @profile: profile to check against + * @gfp: memory allocation flags + * @msg: string describing syscall being rejected + */ +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp, + const char *msg) +{ + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = "syscall"; + sa.name = msg; + sa.gfp_mask = gfp; + sa.error_code = -EPERM; + + return aa_audit_base(profile, &sa, current->audit_context, + AUDIT_APPARMOR_DENIED); +} + +int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa, + int type) +{ + struct audit_context *audit_cxt; + + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL; + return aa_audit_base(profile, sa, audit_cxt, type); +} + +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa) +{ + aa_audit_message(profile, sa, AUDIT_APPARMOR_HINT); +} + +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa) +{ + aa_audit_message(profile, sa, AUDIT_APPARMOR_STATUS); +} + +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa) +{ + return aa_audit_message(profile, sa, AUDIT_APPARMOR_DENIED); +} + +/** + * aa_audit - Log an audit event to the audit subsystem + * @profile: profile to check against + * @sa: audit event + */ +int aa_audit(struct aa_profile *profile, struct aa_audit *sa) +{ + int type = AUDIT_APPARMOR_DENIED; + struct audit_context *audit_cxt; + + if (likely(!sa->error_code)) + type = AUDIT_APPARMOR_AUDIT; + else if (PROFILE_COMPLAIN(profile)) + type = AUDIT_APPARMOR_ALLOWED; + + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL; + return aa_audit_base(profile, sa, audit_cxt, type); +} + +static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa) +{ + if (likely(!sa->error_code)) { + int mask = sa->audit_mask & AUDIT_FILE_MASK; + + if (unlikely(PROFILE_AUDIT(profile))) + mask |= AUDIT_FILE_MASK; + + if (likely(!(sa->request_mask & mask))) + return 0; + + /* mask off perms that are not being force audited */ + sa->request_mask &= mask | ALL_AA_EXEC_TYPE; + } else { + int mask = AUDIT_QUIET_MASK(sa->audit_mask); + + if (!(sa->denied_mask & ~mask)) + return sa->error_code; + + /* mask off perms whose denial is being silenced */ + if (!PROFILE_COMPLAIN(profile)) + sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE; + } + + return aa_audit(profile, sa); +} + +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa, + int cap) +{ + if (likely(!sa->error_code)) { + if (likely(!PROFILE_AUDIT(profile) && + !cap_raised(profile->audit_caps, cap))) + return 0; + } + + /* quieting of capabilities is handled the caps_logged cache */ + return aa_audit(profile, sa); +} + +/** + * aa_file_denied - check for @mask access on a file + * @profile: profile to check against + * @name: pathname of file + * @mask: permission mask requested for file + * @audit_mask: return audit mask for the match + * + * Return %0 on success, or else the permissions in @mask that the + * profile denies. + */ +static int aa_file_denied(struct aa_profile *profile, const char *name, + int mask, int *audit_mask) +{ + return (mask & ~aa_match(profile->file_rules, name, audit_mask)); +} + +/** + * aa_link_denied - check for permission to link a file + * @profile: profile to check against + * @link: pathname of link being created + * @target: pathname of target to be linked to + * @target_mode: UGO shift for target inode + * @request_mask: the permissions subset valid only if link succeeds + * @audit_mask: return the audit_mask for the link permission + * Return %0 on success, or else the permissions that the profile denies. + */ +static int aa_link_denied(struct aa_profile *profile, const char *link, + const char *target, int target_mode, + int *request_mask, int *audit_mask) +{ + unsigned int state; + int l_mode, t_mode, l_x, t_x, denied_mask = 0; + int link_mask = AA_MAY_LINK << target_mode; + + *request_mask = link_mask; + + l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state); + + if (l_mode & link_mask) { + int mode; + /* test to see if target can be paired with link */ + state = aa_dfa_null_transition(profile->file_rules, state); + mode = aa_match_state(profile->file_rules, state, target, + &state); + + if (!(mode & link_mask)) + denied_mask |= link_mask; + + *audit_mask = dfa_audit_mask(profile->file_rules, state); + + /* return if link subset test is not required */ + if (!(mode & (AA_LINK_SUBSET_TEST << target_mode))) + return denied_mask; + } + + /* Do link perm subset test requiring permission on link are a + * subset of the permissions on target. + * If a subset test is required a permission subset test of the + * perms for the link are done against the user::other of the + * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions. + * + * If the link has 'x', an exact match of all the execute flags + * must match. + */ + denied_mask |= ~l_mode & link_mask; + + t_mode = aa_match(profile->file_rules, target, NULL); + + l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS); + t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS); + + /* For actual subset test ignore valid-profile-transition flags, + * and link bits + */ + l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS; + t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS; + + *request_mask = l_mode | link_mask; + + if (l_mode) { + int x = l_x | (t_x & ALL_AA_EXEC_UNSAFE); + denied_mask |= l_mode & ~t_mode; + /* mask off x modes not used by link */ + + /* handle exec subset + * - link safe exec issubset of unsafe exec + * - no link x perm is subset of target having x perm + */ + if ((l_mode & AA_USER_EXEC) && + (x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE)) + denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE); + if ((l_mode & AA_OTHER_EXEC) && + (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE)) + denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE); + } + + return denied_mask; +} + +/** + * aa_get_name - compute the pathname of a file + * @dentry: dentry of the file + * @mnt: vfsmount of the file + * @buffer: buffer that aa_get_name() allocated + * @check: AA_CHECK_DIR is set if the file is a directory + * + * Returns a pointer to the beginning of the pathname (which usually differs + * from the beginning of the buffer), or an error code. + * + * We need @check to indicate whether the file is a directory or not because + * the file may not yet exist, and so we cannot check the inode's file type. + */ +static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt, + char **buffer, int check) +{ + char *name; + int is_dir, size = 256; + + is_dir = (check & AA_CHECK_DIR) ? 1 : 0; + + for (;;) { + char *buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + name = d_namespace_path(dentry, mnt, buf, size - is_dir); + if (!IS_ERR(name)) { + if (name[0] != '/') { + /* + * This dentry is not connected to the + * namespace root -- reject access. + */ + kfree(buf); + return ERR_PTR(-ENOENT); + } + if (is_dir && name[1] != '\0') { + /* + * Append "/" to the pathname. The root + * directory is a special case; it already + * ends in slash. + */ + buf[size - 2] = '/'; + buf[size - 1] = '\0'; + } + + *buffer = buf; + return name; + } + if (PTR_ERR(name) != -ENAMETOOLONG) + return name; + + kfree(buf); + size <<= 1; + if (size > apparmor_path_max) + return ERR_PTR(-ENAMETOOLONG); + } +} + +static char *new_compound_name(const char *n1, const char *n2) +{ + char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL); + if (name) + sprintf(name, "%s//%s", n1, n2); + return name; +} +static inline void aa_put_name_buffer(char *buffer) +{ + kfree(buffer); +} + +/** + * aa_perm_dentry - check if @profile allows @mask for a file + * @profile: profile to check against + * @dentry: dentry of the file + * @mnt: vfsmount o the file + * @sa: audit context + * @mask: requested profile permissions + * @check: kind of check to perform + * + * Returns 0 upon success, or else an error code. + * + * @check indicates the file type, and whether the file was accessed through + * an open file descriptor (AA_CHECK_FD) or not. + */ +static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry, + struct vfsmount *mnt, struct aa_audit *sa, int check) +{ + int error; + char *buffer = NULL; + + sa->name = aa_get_name(dentry, mnt, &buffer, check); + sa->request_mask <<= aa_inode_mode(dentry->d_inode); + if (IS_ERR(sa->name)) { + /* + * deleted files are given a pass on permission checks when + * accessed through a file descriptor. + */ + if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD)) + sa->denied_mask = 0; + else { + sa->denied_mask = sa->request_mask; + sa->error_code = PTR_ERR(sa->name); + if (sa->error_code == -ENOENT) + sa->info = "Failed name resolution - object not a valid entry"; + else if (sa->error_code == -ENAMETOOLONG) + sa->info = "Failed name resolution - name too long"; + else + sa->info = "Failed name resolution"; + } + sa->name = NULL; + } else + sa->denied_mask = aa_file_denied(profile, sa->name, + sa->request_mask, + &sa->audit_mask); + + if (!sa->denied_mask) + sa->error_code = 0; + + error = aa_audit_file(profile, sa); + aa_put_name_buffer(buffer); + + return error; +} + +/** + * aa_attr - check if attribute change is allowed + * @profile: profile to check against + * @dentry: dentry of the file to check + * @mnt: vfsmount of the file to check + * @iattr: attribute changes requested + */ +int aa_attr(struct aa_profile *profile, struct dentry *dentry, + struct vfsmount *mnt, struct iattr *iattr) +{ + struct inode *inode = dentry->d_inode; + int error, check; + struct aa_audit sa; + + memset(&sa, 0, sizeof(sa)); + sa.operation = "setattr"; + sa.gfp_mask = GFP_KERNEL; + sa.iattr = iattr; + sa.request_mask = MAY_WRITE; + sa.error_code = -EACCES; + + check = 0; + if (inode && S_ISDIR(inode->i_mode)) + check |= AA_CHECK_DIR; + if (iattr->ia_valid & ATTR_FILE) + check |= AA_CHECK_FD; + + error = aa_perm_dentry(profile, dentry, mnt, &sa, check); + + return error; +} + +/** + * aa_perm_xattr - check if xattr attribute change is allowed + * @profile: profile to check against + * @dentry: dentry of the file to check + * @mnt: vfsmount of the file to check + * @operation: xattr operation being done + * @mask: access mode requested + * @check: kind of check to perform + */ +int aa_perm_xattr(struct aa_profile *profile, const char *operation, + struct dentry *dentry, struct vfsmount *mnt, int mask, + int check) +{ + struct inode *inode = dentry->d_inode; + int error; + struct aa_audit sa; + + memset(&sa, 0, sizeof(sa)); + sa.operation = operation; + sa.gfp_mask = GFP_KERNEL; + sa.request_mask = mask; + sa.error_code = -EACCES; + + if (inode && S_ISDIR(inode->i_mode)) + check |= AA_CHECK_DIR; + + error = aa_perm_dentry(profile, dentry, mnt, &sa, check); + + return error; +} + +/** + * aa_perm - basic apparmor permissions check + * @profile: profile to check against + * @dentry: dentry of the file to check + * @mnt: vfsmount of the file to check + * @mask: access mode requested + * @check: kind of check to perform + * + * Determine if access @mask for the file is authorized by @profile. + * Returns 0 on success, or else an error code. + */ +int aa_perm(struct aa_profile *profile, const char *operation, + struct dentry *dentry, struct vfsmount *mnt, int mask, int check) +{ + struct aa_audit sa; + int error = 0; + + if (mask == 0) + goto out; + + memset(&sa, 0, sizeof(sa)); + sa.operation = operation; + sa.gfp_mask = GFP_KERNEL; + sa.request_mask = mask; + sa.error_code = -EACCES; + + error = aa_perm_dentry(profile, dentry, mnt, &sa, check); + +out: + return error; +} + +/** + * aa_perm_dir + * @profile: profile to check against + * @dentry: dentry of directory to check + * @mnt: vfsmount of directory to check + * @operation: directory operation being performed + * @mask: access mode requested + * + * Determine if directory operation (make/remove) for dentry is authorized + * by @profile. + * Returns 0 on success, or else an error code. + */ +int aa_perm_dir(struct aa_profile *profile, const char *operation, + struct dentry *dentry, struct vfsmount *mnt, int mask) +{ + struct aa_audit sa; + + memset(&sa, 0, sizeof(sa)); + sa.operation = operation; + sa.gfp_mask = GFP_KERNEL; + sa.request_mask = mask; + sa.error_code = -EACCES; + + return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR); +} + +int aa_perm_path(struct aa_profile *profile, const char *operation, + const char *name, int mask, uid_t uid) +{ + struct aa_audit sa; + + memset(&sa, 0, sizeof(sa)); + sa.operation = operation; + sa.gfp_mask = GFP_KERNEL; + sa.request_mask = mask; + sa.name = name; + if (current->fsuid == uid) + sa.request_mask = mask << AA_USER_SHIFT; + else + sa.request_mask = mask << AA_OTHER_SHIFT; + + sa.denied_mask = aa_file_denied(profile, name, sa.request_mask, + &sa.audit_mask) ; + sa.error_code = sa.denied_mask ? -EACCES : 0; + + return aa_audit_file(profile, &sa); +} + +/** + * aa_capability - test permission to use capability + * @cxt: aa_task_context with profile to check against + * @cap: capability to be tested + * + * Look up capability in profile capability set. + * Returns 0 on success, or else an error code. + */ +int aa_capability(struct aa_task_context *cxt, int cap) +{ + int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM; + struct aa_audit sa; + + /* test if cap has alread been logged */ + if (cap_raised(cxt->caps_logged, cap)) { + if (PROFILE_COMPLAIN(cxt->profile)) + error = 0; + return error; + } else + /* don't worry about rcu replacement of the cxt here. + * caps_logged is a cache to reduce the occurence of + * duplicate messages in the log. The worst that can + * happen is duplicate capability messages shows up in + * the audit log + */ + cap_raise(cxt->caps_logged, cap); + + memset(&sa, 0, sizeof(sa)); + sa.operation = "capable"; + sa.gfp_mask = GFP_ATOMIC; + sa.name = capability_names[cap]; + sa.error_code = error; + + error = aa_audit_caps(cxt->profile, &sa, cap); + + return error; +} + +/* must be used inside rcu_read_lock or task_lock */ +int aa_may_ptrace(struct aa_task_context *cxt, struct aa_profile *tracee) +{ + if (!cxt || cxt->profile == tracee) + return 0; + return aa_capability(cxt, CAP_SYS_PTRACE); +} + +/** + * aa_link - hard link check + * @profile: profile to check against + * @link: dentry of link being created + * @link_mnt: vfsmount of link being created + * @target: dentry of link target + * @target_mnt: vfsmunt of link target + * + * Returns 0 on success, or else an error code. + */ +int aa_link(struct aa_profile *profile, + struct dentry *link, struct vfsmount *link_mnt, + struct dentry *target, struct vfsmount *target_mnt) +{ + int error; + struct aa_audit sa; + char *buffer = NULL, *buffer2 = NULL; + + memset(&sa, 0, sizeof(sa)); + sa.operation = "inode_link"; + sa.gfp_mask = GFP_KERNEL; + sa.name = aa_get_name(link, link_mnt, &buffer, 0); + sa.name2 = aa_get_name(target, target_mnt, &buffer2, 0); + + if (IS_ERR(sa.name)) { + sa.error_code = PTR_ERR(sa.name); + sa.name = NULL; + } + if (IS_ERR(sa.name2)) { + sa.error_code = PTR_ERR(sa.name2); + sa.name2 = NULL; + } + + if (sa.name && sa.name2) { + sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2, + aa_inode_mode(target->d_inode), + &sa.request_mask, + &sa.audit_mask); + sa.error_code = sa.denied_mask ? -EACCES : 0; + } + + error = aa_audit_file(profile, &sa); + + aa_put_name_buffer(buffer); + aa_put_name_buffer(buffer2); + + return error; +} + +int aa_net_perm(struct aa_profile *profile, char *operation, + int family, int type, int protocol) +{ + struct aa_audit sa; + int error = 0; + u16 family_mask, audit_mask, quiet_mask; + + if ((family < 0) || (family >= AF_MAX)) + return -EINVAL; + + if ((type < 0) || (type >= SOCK_MAX)) + return -EINVAL; + + /* unix domain and netlink sockets are handled by ipc */ + if (family == AF_UNIX || family == AF_NETLINK) + return 0; + + family_mask = profile->network_families[family]; + audit_mask = profile->audit_network[family]; + quiet_mask = profile->quiet_network[family]; + + error = (family_mask & (1 << type)) ? 0 : -EACCES; + + memset(&sa, 0, sizeof(sa)); + sa.operation = operation; + sa.gfp_mask = GFP_KERNEL; + sa.family = family; + sa.type = type; + sa.protocol = protocol; + sa.error_code = error; + + if (likely(!error)) { + if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask)) + return 0; + } else if (!((1 << type) & ~quiet_mask)) { + return error; + } + + error = aa_audit(profile, &sa); + + return error; +} + +int aa_revalidate_sk(struct sock *sk, char *operation) +{ + struct aa_profile *profile; + int error = 0; + + /* this is some debugging code to flush out the network hooks that + that are called in interrupt context */ + if (in_interrupt()) { + printk("AppArmor Debug: Hook being called from interrupt context\n"); + dump_stack(); + return 0; + } + + profile = aa_get_profile(current); + if (profile) + error = aa_net_perm(profile, operation, + sk->sk_family, sk->sk_type, + sk->sk_protocol); + aa_put_profile(profile); + + return error; +} +/** + * aa_task_setrlimit - test permission to set an rlimit + * @profile - profile confining the task + * @resource - the resource being set + * @new_rlim - the new resource limit + * + * Control raising the processes hard limit. + */ +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, + struct rlimit *new_rlim) +{ + struct aa_audit sa; + int error = 0; + + memset(&sa, 0, sizeof(sa)); + sa.operation = "setrlimit"; + sa.gfp_mask = GFP_KERNEL; + sa.rlimit = resource + 1; + + if (profile->rlimits.mask & (1 << resource) && + new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) { + sa.error_code = -EACCES; + + error = aa_audit(profile, &sa); + } + + return error; +} + +static int aa_rlimit_nproc(struct aa_profile *profile) { + if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) && + profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max) + return -EAGAIN; + return 0; +} + +void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile) +{ + int i, mask; + + if (!profile) + return; + + if (!profile->rlimits.mask) + return; + + task_lock(task->group_leader); + mask = 1; + for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) { + struct rlimit new_rlim, *old_rlim; + + /* check to see if NPROC which is per profile and handled + * in clone/exec or whether this is a limit to be set + * can't set cpu limit either right now + */ + if (i == RLIMIT_NPROC || i == RLIMIT_CPU) + continue; + + old_rlim = task->signal->rlim + i; + new_rlim = *old_rlim; + + if (mask & profile->rlimits.mask && + profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) { + new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max; + /* soft limit should not exceed hard limit */ + if (new_rlim.rlim_cur > new_rlim.rlim_max) + new_rlim.rlim_cur = new_rlim.rlim_max; + } + + *old_rlim = new_rlim; + } + task_unlock(task->group_leader); +} + +/******************************* + * Global task related functions + *******************************/ + +/** + * aa_clone - initialize the task context for a new task + * @child: task that is being created + * + * Returns 0 on success, or else an error code. + */ +int aa_clone(struct task_struct *child) +{ + struct aa_audit sa; + struct aa_task_context *cxt, *child_cxt; + struct aa_profile *profile; + + if (!aa_task_context(current)) + return 0; + child_cxt = aa_alloc_task_context(GFP_KERNEL); + if (!child_cxt) + return -ENOMEM; + + memset(&sa, 0, sizeof(sa)); + sa.operation = "clone"; + sa.task = child->pid; + sa.gfp_mask = GFP_KERNEL; + +repeat: + profile = aa_get_profile(current); + if (profile) { + lock_profile(profile); + cxt = aa_task_context(current); + if (unlikely(profile->isstale || !cxt || + cxt->profile != profile)) { + /** + * Race with profile replacement or removal, or with + * task context removal. + */ + unlock_profile(profile); + aa_put_profile(profile); + goto repeat; + } + + if (aa_rlimit_nproc(profile)) { + sa.info = "rlimit nproc limit exceeded"; + unlock_profile(profile); + aa_audit_reject(profile, &sa); + aa_put_profile(profile); + return -EAGAIN; + } + + /* No need to grab the child's task lock here. */ + aa_change_task_context(child, child_cxt, profile, + cxt->cookie, cxt->previous_profile); + + unlock_profile(profile); + + if (APPARMOR_COMPLAIN(child_cxt) && + profile == profile->ns->null_complain_profile) { + aa_audit_hint(profile, &sa); + } + aa_put_profile(profile); + } else + aa_free_task_context(child_cxt); + + return 0; +} + +static struct aa_profile * +aa_register_find(struct aa_profile *profile, const char* ns_name, + const char *name, int mandatory, int complain, + struct aa_audit *sa) +{ + struct aa_namespace *ns; + struct aa_profile *new_profile; + int ns_ref = 0; + + if (profile) + ns = profile->ns; + else + ns = default_namespace; + + if (ns_name) { + /* locate the profile namespace */ + ns = aa_find_namespace(ns_name); + if (!ns) { + if (mandatory) { + sa->info = "profile namespace not found"; + sa->denied_mask = sa->request_mask; + sa->error_code = -ENOENT; + return ERR_PTR(-ENOENT); + } else { + return NULL; + } + } + ns_ref++; + } + + /* Locate new profile */ + new_profile = aa_find_profile(ns, name); + + if (new_profile) { + AA_DEBUG("%s: setting profile %s\n", + __FUNCTION__, new_profile->name); + } else if (mandatory && profile) { + sa->info = "mandatory profile missing"; + sa->denied_mask = sa->request_mask; /* shifted MAY_EXEC */ + if (complain) { + aa_audit_hint(profile, sa); + new_profile = + aa_dup_profile(profile->ns->null_complain_profile); + } else { + sa->error_code = -EACCES; + if (ns_ref) + aa_put_namespace(ns); + return ERR_PTR(-EACCES); + } + } else { + /* Only way we can get into this code is if task + * is unconfined, pix, nix. + */ + AA_DEBUG("%s: No profile found for exec image '%s'\n", + __FUNCTION__, + name); + } + if (ns_ref) + aa_put_namespace(ns); + return new_profile; +} + +static struct aa_profile * +aa_x_to_profile(struct aa_profile *profile, const char *filename, int xmode, + struct aa_audit *sa, char **child) +{ + struct aa_profile *new_profile = NULL; + int ix = xmode & AA_EXEC_INHERIT; + int complain = PROFILE_COMPLAIN(profile); + int index; + + *child = NULL; + switch (xmode & AA_EXEC_MODIFIERS) { + case 0: + /* only valid with ix flag */ + ix = 1; + break; + case AA_EXEC_UNCONFINED: + /* only valid without ix flag */ + ix = 0; + break; + case AA_EXEC_PROFILE: + new_profile = aa_register_find(profile, NULL, filename, !ix, + complain, sa); + break; + case AA_EXEC_CHILD: + *child = new_compound_name(profile->name, filename); + sa->name2 = *child; + if (!*child) { + sa->info = "Failed name resolution - exec failed"; + sa->error_code = -ENOMEM; + new_profile = ERR_PTR(-ENOMEM); + } else { + new_profile = aa_register_find(profile, NULL, *child, + !ix, complain, sa); + } + break; + default: + /* all other indexes are named transitions */ + index = AA_EXEC_INDEX(xmode); + if (index - 4 > profile->exec_table_size) { + sa->info = "invalid named transition - exec failed"; + sa->error_code = -EACCES; + new_profile = ERR_PTR(-EACCES); + } else { + char *ns_name = NULL; + char *name = profile->exec_table[index - 4]; + if (*name == ':') { + ns_name = name + 1; + name = ns_name + strlen(ns_name) + 1; + } + sa->name2 = name; + sa->name3 = ns_name; + new_profile = + aa_register_find(profile, ns_name, name, + !ix, complain, sa); + } + } + if (IS_ERR(new_profile)) + /* all these failures must be audited - no quieting */ + return ERR_PTR(aa_audit_reject(profile, sa)); + return new_profile; +} + +/** + * aa_register - register a new program + * @bprm: binprm of program being registered + * + * Try to register a new program during execve(). This should give the + * new program a valid aa_task_context if confined. + */ +int aa_register(struct linux_binprm *bprm) +{ + const char *filename; + char *buffer = NULL, *child = NULL; + struct file *filp = bprm->file; + struct aa_profile *profile, *old_profile, *new_profile = NULL; + int exec_mode, complain = 0, shift; + struct aa_audit sa; + + AA_DEBUG("%s\n", __FUNCTION__); + + profile = aa_get_profile(current); + + shift = aa_inode_mode(filp->f_dentry->d_inode); + memset(&sa, 0, sizeof(sa)); + sa.operation = "exec"; + sa.gfp_mask = GFP_KERNEL; + sa.request_mask = MAY_EXEC << shift; + + filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0); + if (IS_ERR(filename)) { + if (profile) { + sa.info = "Failed name resolution - exec failed"; + sa.error_code = PTR_ERR(filename); + aa_audit_file(profile, &sa); + return sa.error_code; + } else + return 0; + } + sa.name = filename; + + exec_mode = AA_EXEC_UNSAFE << shift; + +repeat: + if (profile) { + complain = PROFILE_COMPLAIN(profile); + + /* Confined task, determine what mode inherit, unconfined or + * mandatory to load new profile + */ + exec_mode = aa_match(profile->file_rules, filename, + &sa.audit_mask); + + + if (exec_mode & sa.request_mask) { + int xm = exec_mode >> shift; + new_profile = aa_x_to_profile(profile, filename, + xm, &sa, &child); + + if (!new_profile && (xm & AA_EXEC_INHERIT)) + /* (p|c|n|)ix - don't change profile */ + goto cleanup; + /* error case caught below */ + + } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) { + /* quiet failed exit */ + new_profile = ERR_PTR(-EACCES); + } else if (complain) { + /* There was no entry in calling profile + * describing mode to execute image in. + * Drop into null-profile (disabling secure exec). + */ + new_profile = + aa_dup_profile(profile->ns->null_complain_profile); + exec_mode |= AA_EXEC_UNSAFE << shift; + } else { + sa.denied_mask = sa.request_mask; + sa.error_code = -EACCES; + new_profile = ERR_PTR(aa_audit_file(profile, &sa)); + } + } else { + /* Unconfined task, load profile if it exists */ + new_profile = aa_register_find(NULL, NULL, filename, 0, 0, &sa); + if (new_profile == NULL) + goto cleanup; + } + + if (IS_ERR(new_profile)) + goto cleanup; + + old_profile = __aa_replace_profile(current, new_profile); + if (IS_ERR(old_profile)) { + aa_put_profile(new_profile); + aa_put_profile(profile); + if (PTR_ERR(old_profile) == -ESTALE) { + profile = aa_get_profile(current); + goto repeat; + } + if (PTR_ERR(old_profile) == -EPERM) { + sa.denied_mask = sa.request_mask; + sa.info = "unable to set profile due to ptrace"; + sa.task = current->parent->pid; + aa_audit_reject(profile, &sa); + } + if (PTR_ERR(old_profile) == -EAGAIN) { + sa.info = "rlimit nproc limit exceeded"; + aa_audit_reject(profile, &sa); + } + new_profile = old_profile; + goto cleanup; + } + aa_put_profile(old_profile); + aa_put_profile(profile); + + /* Handle confined exec. + * Can be at this point for the following reasons: + * 1. unconfined switching to confined + * 2. confined switching to different confinement + * 3. confined switching to unconfined + * + * Cases 2 and 3 are marked as requiring secure exec + * (unless policy specified "unsafe exec") + */ + if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) { + unsigned long bprm_flags; + + bprm_flags = AA_SECURE_EXEC_NEEDED; + bprm->security = (void*) + ((unsigned long)bprm->security | bprm_flags); + } + + if (complain && new_profile && + new_profile == new_profile->ns->null_complain_profile) { + sa.request_mask = 0; + sa.name = NULL; + sa.info = "set profile"; + aa_audit_hint(new_profile, &sa); + } + +cleanup: + aa_put_name_buffer(child); + aa_put_name_buffer(buffer); + if (IS_ERR(new_profile)) + return PTR_ERR(new_profile); + aa_put_profile(new_profile); + return 0; +} + +/** + * aa_release - release a task context + * @task: task being released + * + * This is called after a task has exited and the parent has reaped it. + */ +void aa_release(struct task_struct *task) +{ + struct aa_task_context *cxt; + struct aa_profile *profile; + /* + * While the task context is still on a profile's task context + * list, another process could replace the profile under us, + * leaving us with a locked profile that is no longer attached + * to this task. So after locking the profile, we check that + * the profile is still attached. The profile lock is + * sufficient to prevent the replacement race so we do not lock + * the task. + * + * Use lock subtyping to avoid lockdep reporting a false irq + * possible inversion between the task_lock and profile_lock + * + * We also avoid taking the task_lock here because lock_dep + * would report another false {softirq-on-W} potential irq_lock + * inversion. + * + * If the task does not have a profile attached we are safe; + * nothing can race with us at this point. + */ + +repeat: + profile = aa_get_profile(task); + if (profile) { + lock_profile_nested(profile, aa_lock_task_release); + cxt = aa_task_context(task); + if (unlikely(!cxt || cxt->profile != profile)) { + unlock_profile(profile); + aa_put_profile(profile); + goto repeat; + } + aa_change_task_context(task, NULL, NULL, 0, NULL); + unlock_profile(profile); + aa_put_profile(profile); + } +} + +static int do_change_profile(struct aa_profile *expected, + struct aa_namespace *ns, const char *name, + u64 cookie, int restore, int hat, + struct aa_audit *sa) +{ + struct aa_profile *new_profile = NULL, *old_profile = NULL, + *previous_profile = NULL; + struct aa_task_context *new_cxt, *cxt; + int error = 0; + + sa->name = name; + + new_cxt = aa_alloc_task_context(GFP_KERNEL); + if (!new_cxt) + return -ENOMEM; + + new_profile = aa_find_profile(ns, name); + if (!new_profile && !restore) { + if (!PROFILE_COMPLAIN(expected)) { + aa_free_task_context(new_cxt); + return -ENOENT; + } + new_profile = aa_dup_profile(ns->null_complain_profile); + } else if (new_profile && hat && !PROFILE_IS_HAT(new_profile)) { + aa_free_task_context(new_cxt); + aa_put_profile(new_profile); + return error; + } + + cxt = lock_task_and_profiles(current, new_profile); + if (!cxt) { + error = -EPERM; + goto out; + } + old_profile = cxt->profile; + + if (cxt->profile != expected || (new_profile && new_profile->isstale)) { + error = -ESTALE; + goto out; + } + + if (cxt->previous_profile) { + if (cxt->cookie != cookie) { + error = -EACCES; + sa->info = "killing process"; + aa_audit_reject(cxt->profile, sa); + /* terminate process */ + (void)send_sig_info(SIGKILL, NULL, current); + goto out; + } + + if (!restore) + previous_profile = cxt->previous_profile; + } else + previous_profile = cxt->profile; + + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, new_profile)) { + error = -EACCES; + goto out; + } + + if ((error = aa_rlimit_nproc(new_profile))) { + sa->info = "rlimit nproc limit exceeded"; + aa_audit_reject(cxt->profile, sa); + goto out; + } + + if (new_profile == ns->null_complain_profile) + aa_audit_hint(cxt->profile, sa); + + if (APPARMOR_AUDIT(cxt)) + aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT); + + if (!restore && cookie) + aa_change_task_context(current, new_cxt, new_profile, cookie, + previous_profile); + else + /* either return to previous_profile, or a permanent change */ + aa_change_task_context(current, new_cxt, new_profile, 0, NULL); + +out: + if (aa_task_context(current) != new_cxt) + aa_free_task_context(new_cxt); + task_unlock(current); + unlock_both_profiles(old_profile, new_profile); + aa_put_profile(new_profile); + return error; +} + +/** + * aa_change_profile - perform a one-way profile transition + * @ns_name: name of the profile namespace to change to + * @name: name of profile to change to + * Change to new profile @name. Unlike with hats, there is no way + * to change back. + * + * Returns %0 on success, error otherwise. + */ +int aa_change_profile(const char *ns_name, const char *name) +{ + struct aa_task_context *cxt; + struct aa_profile *profile = NULL; + struct aa_namespace *ns = NULL; + struct aa_audit sa; + unsigned int state; + int error = -EINVAL; + + if (!name) + return -EINVAL; + + memset(&sa, 0, sizeof(sa)); + sa.gfp_mask = GFP_ATOMIC; + sa.operation = "change_profile"; + +repeat: + task_lock(current); + cxt = aa_task_context(current); + if (cxt) + profile = aa_dup_profile(cxt->profile); + task_unlock(current); + + if (ns_name) + ns = aa_find_namespace(ns_name); + else if (profile) + ns = aa_get_namespace(profile->ns); + else + ns = aa_get_namespace(default_namespace); + + if (!ns) { + aa_put_profile(profile); + return -ENOENT; + } + + if (!profile || PROFILE_COMPLAIN(profile) || + (ns == profile->ns && + (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE))) + error = do_change_profile(profile, ns, name, 0, 0, 0, &sa); + else { + /* check for a rule with a namespace prepended */ + aa_match_state(profile->file_rules, DFA_START, ns->name, + &state); + state = aa_dfa_null_transition(profile->file_rules, state); + if ((aa_match_state(profile->file_rules, state, name, NULL) & + AA_CHANGE_PROFILE)) + error = do_change_profile(profile, ns, name, 0, 0, 0, + &sa); + else + /* no permission to transition to profile @name */ + error = -EACCES; + } + + aa_put_namespace(ns); + aa_put_profile(profile); + if (error == -ESTALE) + goto repeat; + + return error; +} + +/** + * aa_change_hat - change hat to/from subprofile + * @hat_name: hat to change to + * @cookie: magic value to validate the hat change + * + * Change to new @hat_name, and store the @hat_magic in the current task + * context. If the new @hat_name is %NULL and the @cookie matches that + * stored in the current task context and is not 0, return to the top level + * profile. + * Returns %0 on success, error otherwise. + */ +int aa_change_hat(const char *hat_name, u64 cookie) +{ + struct aa_task_context *cxt; + struct aa_profile *profile, *previous_profile; + struct aa_audit sa; + int error = 0; + + memset(&sa, 0, sizeof(sa)); + sa.gfp_mask = GFP_ATOMIC; + sa.operation = "change_hat"; + +repeat: + task_lock(current); + cxt = aa_task_context(current); + if (!cxt) { + task_unlock(current); + return -EPERM; + } + profile = aa_dup_profile(cxt->profile); + previous_profile = aa_dup_profile(cxt->previous_profile); + task_unlock(current); + + if (hat_name) { + char *name, *profile_name; + + if (previous_profile) + profile_name = previous_profile->name; + else + profile_name = profile->name; + + name = new_compound_name(profile_name, hat_name); + if (!name) { + error = -ENOMEM; + goto out; + } + error = do_change_profile(profile, profile->ns, name, cookie, + 0, 1, &sa); + aa_put_name_buffer(name); + } else if (previous_profile) + error = do_change_profile(profile, profile->ns, + previous_profile->name, cookie, 1, 0, + &sa); + /* else ignore restores when there is no saved profile */ + +out: + aa_put_profile(previous_profile); + aa_put_profile(profile); + if (error == -ESTALE) + goto repeat; + + return error; +} + +/** + * __aa_replace_profile - replace a task's profile + * @task: task to switch the profile of + * @profile: profile to switch to + * + * Returns a handle to the previous profile upon success, or else an + * error code. + */ +struct aa_profile *__aa_replace_profile(struct task_struct *task, + struct aa_profile *profile) +{ + struct aa_task_context *cxt, *new_cxt = NULL; + struct aa_profile *old_profile = NULL; + + if (profile) { + new_cxt = aa_alloc_task_context(GFP_KERNEL); + if (!new_cxt) + return ERR_PTR(-ENOMEM); + } + + cxt = lock_task_and_profiles(task, profile); + if (unlikely(profile && profile->isstale)) { + old_profile = ERR_PTR(-ESTALE); + goto error; + } + + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) { + old_profile = ERR_PTR(-EPERM); + goto error; + } + + if (aa_rlimit_nproc(profile)) { + old_profile = ERR_PTR(-EAGAIN); + goto error; + } + + if (cxt) + old_profile = aa_dup_profile(cxt->profile); + aa_change_task_context(task, new_cxt, profile, 0, NULL); + + task_unlock(task); + aa_set_rlimits(task, profile); + unlock_both_profiles(profile, old_profile); + return old_profile; + +error: + task_unlock(task); + unlock_both_profiles(profile, cxt ? cxt->profile : NULL); + aa_free_task_context(new_cxt); + return old_profile; +} + +/** + * lock_task_and_profiles - lock the task and confining profiles and @profile + * @task: task to lock + * @profile: extra profile to lock in addition to the current profile + * + * Handle the spinning on locking to make sure the task context and + * profile are consistent once all locks are aquired. + * + * return the aa_task_context currently confining the task. The task lock + * will be held whether or not the task is confined. + */ +struct aa_task_context * +lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile) +{ + struct aa_task_context *cxt; + struct aa_profile *old_profile = NULL; + + rcu_read_lock(); +repeat: + cxt = aa_task_context(task); + if (cxt) + old_profile = cxt->profile; + + lock_both_profiles(profile, old_profile); + task_lock(task); + + /* check for race with profile transition, replacement or removal */ + if (unlikely(cxt != aa_task_context(task))) { + task_unlock(task); + unlock_both_profiles(profile, old_profile); + old_profile = NULL; + goto repeat; + } + rcu_read_unlock(); + return cxt; +} + +static void free_aa_task_context_rcu_callback(struct rcu_head *head) +{ + struct aa_task_context *cxt; + + cxt = container_of(head, struct aa_task_context, rcu); + aa_free_task_context(cxt); +} + +/** + * aa_change_task_context - switch a task to use a new context and profile + * @task: task that is having its task context changed + * @new_cxt: new task context to use after the switch + * @profile: new profile to use after the switch + * @cookie: magic value to switch to + * @previous_profile: profile the task can return to + */ +void aa_change_task_context(struct task_struct *task, + struct aa_task_context *new_cxt, + struct aa_profile *profile, u64 cookie, + struct aa_profile *previous_profile) +{ + struct aa_task_context *old_cxt = aa_task_context(task); + + if (old_cxt) { + list_del_init(&old_cxt->list); + old_cxt->profile->task_count--; + call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback); + } + if (new_cxt) { + /* set the caps_logged cache to the quiet_caps mask + * this has the effect of quieting caps that are not + * supposed to be logged + */ + new_cxt->caps_logged = profile->quiet_caps; + new_cxt->cookie = cookie; + new_cxt->task = task; + new_cxt->profile = aa_dup_profile(profile); + profile->task_count++; + new_cxt->previous_profile = aa_dup_profile(previous_profile); + list_move(&new_cxt->list, &profile->task_contexts); + } + rcu_assign_pointer(task->security, new_cxt); +} --- linux-2.6.27.orig/security/apparmor/procattr.c +++ linux-2.6.27/security/apparmor/procattr.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor /proc/pid/attr handling + */ + +#include "apparmor.h" +#include "inline.h" + +int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len) +{ + char *str; + + if (profile) { + const char *mode_str = PROFILE_COMPLAIN(profile) ? + " (complain)" : " (enforce)"; + int mode_len, name_len, ns_len = 0; + + mode_len = strlen(mode_str); + name_len = strlen(profile->name); + if (profile->ns != default_namespace) + ns_len = strlen(profile->ns->name) + 2; + *len = mode_len + ns_len + name_len + 1; + str = kmalloc(*len, GFP_ATOMIC); + if (!str) + return -ENOMEM; + + if (ns_len) { + *str++ = ':'; + memcpy(str, profile->ns->name, ns_len - 2); + str += ns_len - 2; + *str++ = ':'; + } + memcpy(str, profile->name, name_len); + str += name_len; + memcpy(str, mode_str, mode_len); + str += mode_len; + *str++ = '\n'; + str -= *len; + } else { + const char *unconfined_str = "unconfined\n"; + + *len = strlen(unconfined_str); + str = kmalloc(*len, GFP_ATOMIC); + if (!str) + return -ENOMEM; + + memcpy(str, unconfined_str, *len); + } + *string = str; + + return 0; +} + +static char *split_token_from_name(const char *op, char *args, u64 *cookie) +{ + char *name; + + *cookie = simple_strtoull(args, &name, 16); + if ((name == args) || *name != '^') { + AA_ERROR("%s: Invalid input '%s'", op, args); + return ERR_PTR(-EINVAL); + } + + name++; /* skip ^ */ + if (!*name) + name = NULL; + return name; +} + +int aa_setprocattr_changehat(char *args) +{ + char *hat; + u64 cookie; + + hat = split_token_from_name("change_hat", args, &cookie); + if (IS_ERR(hat)) + return PTR_ERR(hat); + + if (!hat && !cookie) { + AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic"); + return -EINVAL; + } + + AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n", + __FUNCTION__, cookie, hat ? hat : NULL); + + return aa_change_hat(hat, cookie); +} + +int aa_setprocattr_changeprofile(char *args) +{ + char *name = args, *ns_name = NULL; + + if (name[0] == ':') { + char *split = strchr(&name[1], ':'); + if (split) { + *split = 0; + ns_name = &name[1]; + name = split + 1; + } + } + + return aa_change_profile(ns_name, name); +} + +int aa_setprocattr_setprofile(struct task_struct *task, char *args) +{ + struct aa_profile *old_profile, *new_profile; + struct aa_namespace *ns; + struct aa_audit sa; + char *name, *ns_name = NULL; + + memset(&sa, 0, sizeof(sa)); + sa.operation = "profile_set"; + sa.gfp_mask = GFP_KERNEL; + sa.task = task->pid; + + AA_DEBUG("%s: current %d\n", + __FUNCTION__, current->pid); + + name = args; + if (args[0] != '/') { + char *split = strchr(args, ':'); + if (split) { + *split = 0; + ns_name = args; + name = split + 1; + } + } + if (ns_name) + ns = aa_find_namespace(ns_name); + else + ns = aa_get_namespace(default_namespace); + if (!ns) { + sa.name = ns_name; + sa.info = "unknown namespace"; + aa_audit_reject(NULL, &sa); + aa_put_namespace(ns); + return -EINVAL; + } + +repeat: + if (strcmp(name, "unconfined") == 0) + new_profile = NULL; + else { + new_profile = aa_find_profile(ns, name); + if (!new_profile) { + sa.name = ns_name; + sa.name2 = name; + sa.info = "unknown profile"; + aa_audit_reject(NULL, &sa); + aa_put_namespace(ns); + return -EINVAL; + } + } + + old_profile = __aa_replace_profile(task, new_profile); + if (IS_ERR(old_profile)) { + int error; + + aa_put_profile(new_profile); + error = PTR_ERR(old_profile); + if (error == -ESTALE) + goto repeat; + aa_put_namespace(ns); + return error; + } + + if (new_profile) { + sa.name = ns_name; + sa.name2 = name; + sa.name3 = old_profile ? old_profile->name : + "unconfined"; + aa_audit_status(NULL, &sa); + } else { + if (old_profile) { + sa.name = "unconfined"; + sa.name2 = old_profile->name; + aa_audit_status(NULL, &sa); + } else { + sa.info = "task is unconfined"; + aa_audit_status(NULL, &sa); + } + } + aa_put_namespace(ns); + aa_put_profile(old_profile); + aa_put_profile(new_profile); + return 0; +} --- linux-2.6.27.orig/security/apparmor/match.h +++ linux-2.6.27/security/apparmor/match.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor submodule (match) prototypes + */ + +#ifndef __MATCH_H +#define __MATCH_H + +#define DFA_START 1 + +/** + * The format used for transition tables is based on the GNU flex table + * file format (--tables-file option; see Table File Format in the flex + * info pages and the flex sources for documentation). The magic number + * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because + * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used + * slightly differently (see the apparmor-parser package). + */ + +#define YYTH_MAGIC 0x1B5E783D + +struct table_set_header { + u32 th_magic; /* YYTH_MAGIC */ + u32 th_hsize; + u32 th_ssize; + u16 th_flags; + char th_version[]; +}; + +#define YYTD_ID_ACCEPT 1 +#define YYTD_ID_BASE 2 +#define YYTD_ID_CHK 3 +#define YYTD_ID_DEF 4 +#define YYTD_ID_EC 5 +#define YYTD_ID_META 6 +#define YYTD_ID_ACCEPT2 7 +#define YYTD_ID_NXT 8 + + +#define YYTD_DATA8 1 +#define YYTD_DATA16 2 +#define YYTD_DATA32 4 + +struct table_header { + u16 td_id; + u16 td_flags; + u32 td_hilen; + u32 td_lolen; + char td_data[]; +}; + +#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data)) +#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data)) +#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data)) +#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data)) +#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data)) +#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data)) +#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data)) + +struct aa_dfa { + struct table_header *tables[YYTD_ID_NXT]; +}; + +#define byte_to_byte(X) (X) + +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \ + do { \ + typeof(LEN) __i; \ + TYPE *__t = (TYPE *) TABLE; \ + TYPE *__b = (TYPE *) BLOB; \ + for (__i = 0; __i < LEN; __i++) { \ + __t[__i] = NTOHX(__b[__i]); \ + } \ + } while (0) + +static inline size_t table_size(size_t len, size_t el_size) +{ + return ALIGN(sizeof(struct table_header) + len * el_size, 8); +} + +#endif /* __MATCH_H */ --- linux-2.6.27.orig/security/apparmor/locking.txt +++ linux-2.6.27/security/apparmor/locking.txt @@ -0,0 +1,68 @@ +Locking in AppArmor +=================== + +Lock hierarchy: + + aa_interface_lock + profile_list_lock + aa_profile->lock + task_lock() + + +Which lock protects what? + + /-----------------------+-------------------------------\ + | Variable | Lock | + >-----------------------+-------------------------------< + | profile_list | profile_list_lock | + +-----------------------+-------------------------------+ + | aa_profile | (reference count) | + +-----------------------+-------------------------------+ + | aa_profile-> | aa_profile->lock | + | isstale, | | + | task_contexts | | + +-----------------------+-------------------------------+ + | task_struct->security | read: RCU | + | | write: task_lock() | + +-----------------------+-------------------------------+ + | aa_profile->sub | handle on the profile (list | + | | is never modified) | + \-----------------------+-------------------------------/ + +(Obviously, the list_heads embedded in data structures are always +protected with the lock that also protects the list.) + +When moving a task context from one profile to another, we grab both +profile locks with lock_both_profiles(). This ensures that both locks +are always taken in the same order, and so we won't deadlock. + +Since task_struct->security is RCU protected the aa_task_struct it +references is only guarenteed to exist for the rcu cycle. Where +aa_task_context->profile is needed in blocking operations the +profile's reference count is incremented and the profile reference +is used. + +Profiles on profile_list are never stale: when a profile becomes stale, +it is removed from profile_list at the same time (under profile_list_lock +and aa_profile->lock). + +The aa_interface_lock is taken whenever user-space modifies the profile +list, and can sleep. This ensures that profile loading/replacement/removal +won't race with itself. We release the profile_list_lock as soon as +possible to avoid stalling exec during profile loading/replacement/removal. + +AppArmor uses lock subtyping to avoid false positives from lockdep. The +profile lock is often taken nested, but it is guaranteed to be in a lock +safe order and not the same lock when done, so it is safe. + +A third lock type (aa_lock_task_release) is given to the profile lock +when it is taken in soft irq context during task release (aa_release). +This is to avoid a false positive between the task lock and the profile +lock. In task context the profile lock wraps the task lock with irqs +off, but the kernel takes the task lock with irqs enabled. This won't +result in a deadlock because for a deadlock to occur the kernel must +take dead task A's lock (irqs on), the rcu callback hook freeing +dead task A must be run and AppArmor must be changing the profile on +dead task A. The kernel should not be taking a dead task's task_lock +at the same time the task is being freed by task rcu cleanup other wise +the task would not be out of its quiescent period. --- linux-2.6.27.orig/security/apparmor/apparmorfs.c +++ linux-2.6.27/security/apparmor/apparmorfs.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * AppArmor filesystem (part of securityfs) + */ + +#include +#include +#include +#include +#include +#include + +#include "apparmor.h" +#include "inline.h" + +static char *aa_simple_write_to_buffer(const char __user *userbuf, + size_t alloc_size, size_t copy_size, + loff_t *pos, const char *operation) +{ + struct aa_profile *profile; + char *data; + + if (*pos != 0) { + /* only writes from pos 0, that is complete writes */ + data = ERR_PTR(-ESPIPE); + goto out; + } + + /* + * Don't allow confined processes to load/replace/remove profiles. + * No sane person would add rules allowing this to a profile + * but we enforce the restriction anyways. + */ + profile = aa_get_profile(current); + if (profile) { + struct aa_audit sa; + memset(&sa, 0, sizeof(sa)); + sa.operation = operation; + sa.gfp_mask = GFP_KERNEL; + sa.error_code = -EACCES; + data = ERR_PTR(aa_audit_reject(profile, &sa)); + aa_put_profile(profile); + goto out; + } + + data = vmalloc(alloc_size); + if (data == NULL) { + data = ERR_PTR(-ENOMEM); + goto out; + } + + if (copy_from_user(data, userbuf, copy_size)) { + vfree(data); + data = ERR_PTR(-EFAULT); + goto out; + } + +out: + return data; +} + +/* apparmor/profiles */ +extern struct seq_operations apparmorfs_profiles_op; + +static int aa_profiles_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &apparmorfs_profiles_op); +} + + +static int aa_profiles_release(struct inode *inode, struct file *file) +{ + return seq_release(inode, file); +} + +static struct file_operations apparmorfs_profiles_fops = { + .open = aa_profiles_open, + .read = seq_read, + .llseek = seq_lseek, + .release = aa_profiles_release, +}; + +/* apparmor/matching */ +static ssize_t aa_matching_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other"; + + return simple_read_from_buffer(buf, size, ppos, matching, + strlen(matching)); +} + +static struct file_operations apparmorfs_matching_fops = { + .read = aa_matching_read, +}; + +/* apparmor/features */ +static ssize_t aa_features_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + const char *features = "file=3.0 capability=2.0 network=1.0 " + "change_hat=1.5 change_profile=1.0 " + "aanamespaces=1.0 rlimit=1.0"; + + return simple_read_from_buffer(buf, size, ppos, features, + strlen(features)); +} + +static struct file_operations apparmorfs_features_fops = { + .read = aa_features_read, +}; + +/* apparmor/.load */ +static ssize_t aa_profile_load(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + char *data; + ssize_t error; + + data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load"); + + error = PTR_ERR(data); + if (!IS_ERR(data)) { + error = aa_add_profile(data, size); + vfree(data); + } + + return error; +} + + +static struct file_operations apparmorfs_profile_load = { + .write = aa_profile_load +}; + +/* apparmor/.replace */ +static ssize_t aa_profile_replace(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + char *data; + ssize_t error; + + data = aa_simple_write_to_buffer(buf, size, size, pos, + "profile_replace"); + + error = PTR_ERR(data); + if (!IS_ERR(data)) { + error = aa_replace_profile(data, size); + vfree(data); + } + + return error; +} + + +static struct file_operations apparmorfs_profile_replace = { + .write = aa_profile_replace +}; + +/* apparmor/.remove */ +static ssize_t aa_profile_remove(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + char *data; + ssize_t error; + + /* + * aa_remove_profile needs a null terminated string so 1 extra + * byte is allocated and the copied data is null terminated. + */ + data = aa_simple_write_to_buffer(buf, size + 1, size, pos, + "profile_remove"); + + error = PTR_ERR(data); + if (!IS_ERR(data)) { + data[size] = 0; + error = aa_remove_profile(data, size); + vfree(data); + } + + return error; +} + +static struct file_operations apparmorfs_profile_remove = { + .write = aa_profile_remove +}; + +static struct dentry *apparmor_dentry; + +static void aafs_remove(const char *name) +{ + struct dentry *dentry; + + dentry = lookup_one_len(name, apparmor_dentry, strlen(name)); + if (!IS_ERR(dentry)) { + securityfs_remove(dentry); + dput(dentry); + } +} + +static int aafs_create(const char *name, int mask, struct file_operations *fops) +{ + struct dentry *dentry; + + dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry, + NULL, fops); + + return IS_ERR(dentry) ? PTR_ERR(dentry) : 0; +} + +void destroy_apparmorfs(void) +{ + if (apparmor_dentry) { + aafs_remove(".remove"); + aafs_remove(".replace"); + aafs_remove(".load"); + aafs_remove("matching"); + aafs_remove("features"); + aafs_remove("profiles"); + securityfs_remove(apparmor_dentry); + apparmor_dentry = NULL; + } +} + +int create_apparmorfs(void) +{ + int error; + + if (!apparmor_initialized) + return 0; + + if (apparmor_dentry) { + AA_ERROR("%s: AppArmor securityfs already exists\n", + __FUNCTION__); + return -EEXIST; + } + + apparmor_dentry = securityfs_create_dir("apparmor", NULL); + if (IS_ERR(apparmor_dentry)) { + error = PTR_ERR(apparmor_dentry); + apparmor_dentry = NULL; + goto error; + } + error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops); + if (error) + goto error; + error = aafs_create("matching", 0444, &apparmorfs_matching_fops); + if (error) + goto error; + error = aafs_create("features", 0444, &apparmorfs_features_fops); + if (error) + goto error; + error = aafs_create(".load", 0640, &apparmorfs_profile_load); + if (error) + goto error; + error = aafs_create(".replace", 0640, &apparmorfs_profile_replace); + if (error) + goto error; + error = aafs_create(".remove", 0640, &apparmorfs_profile_remove); + if (error) + goto error; + + /* Report that AppArmor fs is enabled */ + info_message("AppArmor Filesystem Enabled"); + return 0; + +error: + destroy_apparmorfs(); + AA_ERROR("Error creating AppArmor securityfs\n"); + apparmor_disable(); + return error; +} + +fs_initcall(create_apparmorfs); + --- linux-2.6.27.orig/security/apparmor/inline.h +++ linux-2.6.27/security/apparmor/inline.h @@ -0,0 +1,250 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ + +#ifndef __INLINE_H +#define __INLINE_H + +#include + +#include "match.h" + +static inline int mediated_filesystem(struct inode *inode) +{ + return !(inode->i_sb->s_flags & MS_NOUSER); +} + +static inline struct aa_task_context *aa_task_context(struct task_struct *task) +{ + return (struct aa_task_context *) rcu_dereference(task->security); +} + +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns) +{ + if (ns) + kref_get(&(ns->count)); + + return ns; +} + +static inline void aa_put_namespace(struct aa_namespace *ns) +{ + if (ns) + kref_put(&ns->count, free_aa_namespace_kref); +} + + +static inline struct aa_namespace *aa_find_namespace(const char *name) +{ + struct aa_namespace *ns = NULL; + + read_lock(&profile_ns_list_lock); + ns = aa_get_namespace(__aa_find_namespace(name, &profile_ns_list)); + read_unlock(&profile_ns_list_lock); + + return ns; +} + +/** + * aa_dup_profile - increment refcount on profile @p + * @p: profile + */ +static inline struct aa_profile *aa_dup_profile(struct aa_profile *p) +{ + if (p) + kref_get(&(p->count)); + + return p; +} + +/** + * aa_put_profile - decrement refcount on profile @p + * @p: profile + */ +static inline void aa_put_profile(struct aa_profile *p) +{ + if (p) + kref_put(&p->count, free_aa_profile_kref); +} + +static inline struct aa_profile *aa_get_profile(struct task_struct *task) +{ + struct aa_task_context *cxt; + struct aa_profile *profile = NULL; + + rcu_read_lock(); + cxt = aa_task_context(task); + if (cxt) { + profile = cxt->profile; + aa_dup_profile(profile); + } + rcu_read_unlock(); + + return profile; +} + +static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns, + const char *name) +{ + struct aa_profile *profile = NULL; + + read_lock(&ns->lock); + profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles)); + read_unlock(&ns->lock); + + return profile; +} + +static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags) +{ + struct aa_task_context *cxt; + + cxt = kzalloc(sizeof(*cxt), flags); + if (cxt) { + INIT_LIST_HEAD(&cxt->list); + INIT_RCU_HEAD(&cxt->rcu); + } + + return cxt; +} + +static inline void aa_free_task_context(struct aa_task_context *cxt) +{ + if (cxt) { + aa_put_profile(cxt->profile); + aa_put_profile(cxt->previous_profile); + kfree(cxt); + } +} + +/** + * lock_profile - lock a profile + * @profile: the profile to lock + * + * While the profile is locked, local interrupts are disabled. This also + * gives us RCU reader safety. + */ +static inline void lock_profile_nested(struct aa_profile *profile, + enum aa_lock_class lock_class) +{ + /* + * Lock the profile. + * + * Need to disable interrupts here because this lock is used in + * the task_free_security hook, which may run in RCU context. + */ + if (profile) + spin_lock_irqsave_nested(&profile->lock, profile->int_flags, + lock_class); +} + +static inline void lock_profile(struct aa_profile *profile) +{ + lock_profile_nested(profile, aa_lock_normal); +} + +/** + * unlock_profile - unlock a profile + * @profile: the profile to unlock + */ +static inline void unlock_profile(struct aa_profile *profile) +{ + /* Unlock the profile. */ + if (profile) + spin_unlock_irqrestore(&profile->lock, profile->int_flags); +} + +/** + * lock_both_profiles - lock two profiles in a deadlock-free way + * @profile1: profile to lock (may be NULL) + * @profile2: profile to lock (may be NULL) + * + * The order in which profiles are passed into lock_both_profiles() / + * unlock_both_profiles() does not matter. + * While the profile is locked, local interrupts are disabled. This also + * gives us RCU reader safety. + */ +static inline void lock_both_profiles(struct aa_profile *profile1, + struct aa_profile *profile2) +{ + /* + * Lock the two profiles. + * + * We need to disable interrupts because the profile locks are + * used in the task_free_security hook, which may run in RCU + * context. + * + * Do not nest spin_lock_irqsave()/spin_unlock_irqresore(): + * interrupts only need to be turned off once. + */ + if (!profile1 || profile1 == profile2) { + if (profile2) + spin_lock_irqsave_nested(&profile2->lock, + profile2->int_flags, + aa_lock_normal); + } else if (profile1 > profile2) { + /* profile1 cannot be NULL here. */ + spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags, + aa_lock_normal); + if (profile2) + spin_lock_nested(&profile2->lock, aa_lock_nested); + + } else { + /* profile2 cannot be NULL here. */ + spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags, + aa_lock_normal); + spin_lock_nested(&profile1->lock, aa_lock_nested); + } +} + +/** + * unlock_both_profiles - unlock two profiles in a deadlock-free way + * @profile1: profile to unlock (may be NULL) + * @profile2: profile to unlock (may be NULL) + * + * The order in which profiles are passed into lock_both_profiles() / + * unlock_both_profiles() does not matter. + * While the profile is locked, local interrupts are disabled. This also + * gives us RCU reader safety. + */ +static inline void unlock_both_profiles(struct aa_profile *profile1, + struct aa_profile *profile2) +{ + /* Unlock the two profiles. */ + if (!profile1 || profile1 == profile2) { + if (profile2) + spin_unlock_irqrestore(&profile2->lock, + profile2->int_flags); + } else if (profile1 > profile2) { + /* profile1 cannot be NULL here. */ + if (profile2) + spin_unlock(&profile2->lock); + spin_unlock_irqrestore(&profile1->lock, profile1->int_flags); + } else { + /* profile2 cannot be NULL here. */ + spin_unlock(&profile1->lock); + spin_unlock_irqrestore(&profile2->lock, profile2->int_flags); + } +} + +static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname, + int *audit_mask) +{ + if (dfa) + return aa_dfa_match(dfa, pathname, audit_mask); + if (audit_mask) + *audit_mask = 0; + return 0; +} + +static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state) +{ + return ACCEPT_TABLE2(dfa)[state]; +} + +#endif /* __INLINE_H__ */ --- linux-2.6.27.orig/security/apparmor/match.c +++ linux-2.6.27/security/apparmor/match.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2007 Novell/SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * Regular expression transition table matching + */ + +#include +#include +#include +#include "apparmor.h" +#include "match.h" +#include "inline.h" + +static struct table_header *unpack_table(void *blob, size_t bsize) +{ + struct table_header *table = NULL; + struct table_header th; + size_t tsize; + + if (bsize < sizeof(struct table_header)) + goto out; + + th.td_id = be16_to_cpu(*(u16 *) (blob)); + th.td_flags = be16_to_cpu(*(u16 *) (blob + 2)); + th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8)); + blob += sizeof(struct table_header); + + if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 || + th.td_flags == YYTD_DATA8)) + goto out; + + tsize = table_size(th.td_lolen, th.td_flags); + if (bsize < tsize) + goto out; + + table = kmalloc(tsize, GFP_KERNEL); + if (table) { + *table = th; + if (th.td_flags == YYTD_DATA8) + UNPACK_ARRAY(table->td_data, blob, th.td_lolen, + u8, byte_to_byte); + else if (th.td_flags == YYTD_DATA16) + UNPACK_ARRAY(table->td_data, blob, th.td_lolen, + u16, be16_to_cpu); + else + UNPACK_ARRAY(table->td_data, blob, th.td_lolen, + u32, be32_to_cpu); + } + +out: + return table; +} + +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size) +{ + int hsize, i; + int error = -ENOMEM; + + /* get dfa table set header */ + if (size < sizeof(struct table_set_header)) + goto fail; + + if (ntohl(*(u32 *)blob) != YYTH_MAGIC) + goto fail; + + hsize = ntohl(*(u32 *)(blob + 4)); + if (size < hsize) + goto fail; + + blob += hsize; + size -= hsize; + + error = -EPROTO; + while (size > 0) { + struct table_header *table; + table = unpack_table(blob, size); + if (!table) + goto fail; + + switch(table->td_id) { + case YYTD_ID_ACCEPT: + case YYTD_ID_ACCEPT2: + case YYTD_ID_BASE: + dfa->tables[table->td_id - 1] = table; + if (table->td_flags != YYTD_DATA32) + goto fail; + break; + case YYTD_ID_DEF: + case YYTD_ID_NXT: + case YYTD_ID_CHK: + dfa->tables[table->td_id - 1] = table; + if (table->td_flags != YYTD_DATA16) + goto fail; + break; + case YYTD_ID_EC: + dfa->tables[table->td_id - 1] = table; + if (table->td_flags != YYTD_DATA8) + goto fail; + break; + default: + kfree(table); + goto fail; + } + + blob += table_size(table->td_lolen, table->td_flags); + size -= table_size(table->td_lolen, table->td_flags); + } + + return 0; + +fail: + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) { + if (dfa->tables[i]) { + kfree(dfa->tables[i]); + dfa->tables[i] = NULL; + } + } + return error; +} + +/** + * verify_dfa - verify that all the transitions and states in the dfa tables + * are in bounds. + * @dfa: dfa to test + * + * assumes dfa has gone through the verification done by unpacking + */ +int verify_dfa(struct aa_dfa *dfa) +{ + size_t i, state_count, trans_count; + int error = -EPROTO; + + /* check that required tables exist */ + if (!(dfa->tables[YYTD_ID_ACCEPT - 1] && + dfa->tables[YYTD_ID_ACCEPT2 - 1] && + dfa->tables[YYTD_ID_DEF - 1] && + dfa->tables[YYTD_ID_BASE - 1] && + dfa->tables[YYTD_ID_NXT - 1] && + dfa->tables[YYTD_ID_CHK - 1])) + goto out; + + /* accept.size == default.size == base.size */ + state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen; + if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen && + state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen && + state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen)) + goto out; + + /* next.size == chk.size */ + trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen; + if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen) + goto out; + + /* if equivalence classes then its table size must be 256 */ + if (dfa->tables[YYTD_ID_EC - 1] && + dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256) + goto out; + + for (i = 0; i < state_count; i++) { + if (DEFAULT_TABLE(dfa)[i] >= state_count) + goto out; + if (BASE_TABLE(dfa)[i] >= trans_count + 256) + goto out; + } + + for (i = 0; i < trans_count ; i++) { + if (NEXT_TABLE(dfa)[i] >= state_count) + goto out; + if (CHECK_TABLE(dfa)[i] >= state_count) + goto out; + } + + /* verify accept permissions */ + for (i = 0; i < state_count; i++) { + int mode = ACCEPT_TABLE(dfa)[i]; + + if (mode & ~AA_VALID_PERM_MASK) + goto out; + if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK) + goto out; + + /* if any exec modifier is set MAY_EXEC must be set */ + if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC)) + goto out; + if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC)) + goto out; + } + + error = 0; +out: + return error; +} + +struct aa_dfa *aa_match_alloc(void) +{ + return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL); +} + +void aa_match_free(struct aa_dfa *dfa) +{ + if (dfa) { + int i; + + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) + kfree(dfa->tables[i]); + } + kfree(dfa); +} + +/** + * aa_dfa_next_state_len - traverse @dfa to find state @str stops at + * @dfa: the dfa to match @str against + * @start: the state of the dfa to start matching in + * @str: the string of bytes to match against the dfa + * @len: length of the string of bytes to match + * + * aa_dfa_next_state will match @str against the dfa and return the state it + * finished matching in. The final state can be used to look up the accepting + * label, or as the start state of a continuing match. + * + * aa_dfa_next_state could be implement using this function by doing + * return aa_dfa_next_state_len(dfa, start, str, strlen(str)); + * but that would require traversing the string twice and be slightly + * slower. + */ +unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start, + const char *str, int len) +{ + u16 *def = DEFAULT_TABLE(dfa); + u32 *base = BASE_TABLE(dfa); + u16 *next = NEXT_TABLE(dfa); + u16 *check = CHECK_TABLE(dfa); + unsigned int state = start, pos; + + if (state == 0) + return 0; + + /* current state is , matching character *str */ + if (dfa->tables[YYTD_ID_EC - 1]) { + u8 *equiv = EQUIV_TABLE(dfa); + for (; len; len--) { + pos = base[state] + equiv[(u8)*str++]; + if (check[pos] == state) + state = next[pos]; + else + state = def[state]; + } + } else { + for (; len; len--) { + pos = base[state] + (u8)*str++; + if (check[pos] == state) + state = next[pos]; + else + state = def[state]; + } + } + return state; +} + +/** + * aa_dfa_next_state - traverse @dfa to find state @str stops at + * @dfa: the dfa to match @str against + * @start: the state of the dfa to start matching in + * @str: the null terminated string of bytes to match against the dfa + * + * aa_dfa_next_state will match @str against the dfa and return the state it + * finished matching in. The final state can be used to look up the accepting + * label, or as the start state of a continuing match. + */ +unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start, + const char *str) +{ + u16 *def = DEFAULT_TABLE(dfa); + u32 *base = BASE_TABLE(dfa); + u16 *next = NEXT_TABLE(dfa); + u16 *check = CHECK_TABLE(dfa); + unsigned int state = start, pos; + + if (state == 0) + return 0; + + /* current state is , matching character *str */ + if (dfa->tables[YYTD_ID_EC - 1]) { + u8 *equiv = EQUIV_TABLE(dfa); + while (*str) { + pos = base[state] + equiv[(u8)*str++]; + if (check[pos] == state) + state = next[pos]; + else + state = def[state]; + } + } else { + while (*str) { + pos = base[state] + (u8)*str++; + if (check[pos] == state) + state = next[pos]; + else + state = def[state]; + } + } + return state; +} + +/** + * aa_dfa_null_transition - step to next state after null character + * @dfa: the dfa to match against + * @start: the state of the dfa to start matching in + * + * aa_dfa_null_transition transitions to the next state after a null + * character which is not used in standard matching and is only + * used to seperate pairs. + */ +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start) +{ + return aa_dfa_next_state_len(dfa, start, "", 1); +} + +/** + * aa_dfa_match - find accept perm for @str in @dfa + * @dfa: the dfa to match @str against + * @str: the string to match against the dfa + * @audit_mask: the audit_mask for the final state + * + * aa_dfa_match will match @str and return the accept perms for the + * final state. + */ +unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask) +{ + int state = aa_dfa_next_state(dfa, DFA_START, str); + if (audit_mask) + *audit_mask = dfa_audit_mask(dfa, state); + return ACCEPT_TABLE(dfa)[state]; +} + +/** + * aa_match_state - find accept perm and state for @str in @dfa + * @dfa: the dfa to match @str against + * @start: the state to start the match from + * @str: the string to match against the dfa + * @final: the state that the match finished in + * + * aa_match_state will match @str and return the accept perms, and @final + * state, the match occured in. + */ +unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start, + const char *str, unsigned int *final) +{ + unsigned int state; + if (dfa) { + state = aa_dfa_next_state(dfa, start, str); + if (final) + *final = state; + return ACCEPT_TABLE(dfa)[state]; + } + if (final) + *final = 0; + return 0; +} + --- linux-2.6.27.orig/security/apparmor/Makefile +++ linux-2.6.27/security/apparmor/Makefile @@ -0,0 +1,18 @@ +# Makefile for AppArmor Linux Security Module +# +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o + +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \ + module_interface.o match.o + +quiet_cmd_make-caps = GEN $@ +cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@ + +quiet_cmd_make-af = GEN $@ +cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@ + +$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h +$(obj)/capability_names.h : $(srctree)/include/linux/capability.h + $(call cmd,make-caps) +$(obj)/af_names.h : $(srctree)/include/linux/socket.h + $(call cmd,make-af) --- linux-2.6.27.orig/security/selinux/hooks.c +++ linux-2.6.27/security/selinux/hooks.c @@ -1811,40 +1811,16 @@ static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid) { - int buflen, rc; - char *buffer, *path, *end; + char *buffer, *path; + int rc = -ENOMEM; - rc = -ENOMEM; buffer = (char *)__get_free_page(GFP_KERNEL); if (!buffer) goto out; - buflen = PAGE_SIZE; - end = buffer+buflen; - *--end = '\0'; - buflen--; - path = end-1; - *path = '/'; - while (table) { - const char *name = table->procname; - size_t namelen = strlen(name); - buflen -= namelen + 1; - if (buflen < 0) - goto out_free; - end -= namelen; - memcpy(end, name, namelen); - *--end = '/'; - path = end; - table = table->parent; - } - buflen -= 4; - if (buflen < 0) - goto out_free; - end -= 4; - memcpy(end, "/sys", 4); - path = end; - rc = security_genfs_sid("proc", path, tclass, sid); -out_free: + path = sysctl_pathname(table, buffer, PAGE_SIZE); + if (path) + rc = security_genfs_sid("proc", path, tclass, sid); free_page((unsigned long)buffer); out: return rc; @@ -2566,64 +2542,79 @@ return 0; } -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) +static int selinux_inode_create(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mask) { return may_create(dir, dentry, SECCLASS_FILE); } -static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) +static int selinux_inode_link(struct dentry *old_dentry, + struct vfsmount *old_mnt, + struct inode *dir, + struct dentry *new_dentry, + struct vfsmount *new_mnt) { int rc; - rc = secondary_ops->inode_link(old_dentry, dir, new_dentry); + rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry, + new_mnt); if (rc) return rc; return may_link(dir, old_dentry, MAY_LINK); } -static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) +static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { int rc; - rc = secondary_ops->inode_unlink(dir, dentry); + rc = secondary_ops->inode_unlink(dir, dentry, mnt); if (rc) return rc; return may_link(dir, dentry, MAY_UNLINK); } -static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name) +static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *name) { return may_create(dir, dentry, SECCLASS_LNK_FILE); } -static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) +static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mask) { return may_create(dir, dentry, SECCLASS_DIR); } -static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) +static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { return may_link(dir, dentry, MAY_RMDIR); } -static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode, dev_t dev) { int rc; - rc = secondary_ops->inode_mknod(dir, dentry, mode, dev); + rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev); if (rc) return rc; return may_create(dir, dentry, inode_mode_to_security_class(mode)); } -static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, - struct inode *new_inode, struct dentry *new_dentry) +static int selinux_inode_rename(struct inode *old_inode, + struct dentry *old_dentry, + struct vfsmount *old_mnt, + struct inode *new_inode, + struct dentry *new_dentry, + struct vfsmount *new_mnt) { return may_rename(old_inode, old_dentry, new_inode, new_dentry); } -static int selinux_inode_readlink(struct dentry *dentry) +static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt) { return dentry_has_perm(current, NULL, dentry, FILE__READ); } @@ -2655,11 +2646,12 @@ open_file_mask_to_av(inode->i_mode, mask), NULL); } -static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *iattr) { int rc; - rc = secondary_ops->inode_setattr(dentry, iattr); + rc = secondary_ops->inode_setattr(dentry, mnt, iattr); if (rc) return rc; @@ -2697,8 +2689,9 @@ return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); } -static int selinux_inode_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags, struct file *file) { struct task_security_struct *tsec = current->security; struct inode *inode = dentry->d_inode; @@ -2752,7 +2745,8 @@ &ad); } -static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, +static void selinux_inode_post_setxattr(struct dentry *dentry, + struct vfsmount *mnt, const char *name, const void *value, size_t size, int flags) { @@ -2778,17 +2772,21 @@ return; } -static int selinux_inode_getxattr(struct dentry *dentry, const char *name) +static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file) { return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); } -static int selinux_inode_listxattr(struct dentry *dentry) +static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt, + struct file *file) { return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); } -static int selinux_inode_removexattr(struct dentry *dentry, const char *name) +static int selinux_inode_removexattr(struct dentry *dentry, + struct vfsmount *mnt, const char *name, + struct file *file) { if (strcmp(name, XATTR_NAME_SELINUX)) return selinux_inode_setotherxattr(dentry, name); --- linux-2.6.27.orig/security/smack/smack_lsm.c +++ linux-2.6.27/security/smack/smack_lsm.c @@ -432,8 +432,9 @@ * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +static int smack_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt, + struct inode *dir, + struct dentry *new_dentry, struct vfsmount *new_mnt) { int rc; char *isp; @@ -453,11 +454,13 @@ * smack_inode_unlink - Smack check on inode deletion * @dir: containing directory object * @dentry: file to unlink + * @mnt: vfsmount of file to unlink * * Returns 0 if current can write the containing directory * and the object, error code otherwise */ -static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) +static int smack_inode_unlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { struct inode *ip = dentry->d_inode; int rc; @@ -479,11 +482,13 @@ * smack_inode_rmdir - Smack check on directory deletion * @dir: containing directory object * @dentry: directory to unlink + * @mnt: vfsmount @dentry to unlink * * Returns 0 if current can write the containing directory * and the directory, error code otherwise */ -static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) +static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { int rc; @@ -504,8 +509,10 @@ * smack_inode_rename - Smack check on rename * @old_inode: the old directory * @old_dentry: unused + * @old_mnt: unused * @new_inode: the new directory * @new_dentry: unused + * @new_mnt: unused * * Read and write access is required on both the old and * new directories. @@ -514,8 +521,10 @@ */ static int smack_inode_rename(struct inode *old_inode, struct dentry *old_dentry, + struct vfsmount *old_mnt, struct inode *new_inode, - struct dentry *new_dentry) + struct dentry *new_dentry, + struct vfsmount *new_mnt) { int rc; char *isp; @@ -559,7 +568,8 @@ * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int smack_inode_setattr(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *iattr) { /* * Need to allow for clearing the setuid bit. @@ -585,17 +595,20 @@ /** * smack_inode_setxattr - Smack check for setting xattrs * @dentry: the object + * @mnt: unused * @name: name of the attribute * @value: unused * @size: unused * @flags: unused + * @file: unused * * This protects the Smack attribute explicitly. * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +static int smack_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, const void *value, + size_t size, int flags, struct file *file) { int rc = 0; @@ -605,7 +618,8 @@ if (!capable(CAP_MAC_ADMIN)) rc = -EPERM; } else - rc = cap_inode_setxattr(dentry, name, value, size, flags); + rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags, + file); if (rc == 0) rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); @@ -616,6 +630,7 @@ /** * smack_inode_post_setxattr - Apply the Smack update approved above * @dentry: object + * @mnt: unused * @name: attribute name * @value: attribute value * @size: attribute size @@ -624,7 +639,8 @@ * Set the pointer in the inode blob to the entry found * in the master label list. */ -static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, +static void smack_inode_post_setxattr(struct dentry *dentry, + struct vfsmount *mnt, const char *name, const void *value, size_t size, int flags) { struct inode_smack *isp; @@ -657,11 +673,14 @@ /* * smack_inode_getxattr - Smack check on getxattr * @dentry: the object + * @mnt: unused * @name: unused + * @file: unused * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_getxattr(struct dentry *dentry, const char *name) +static int smack_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file) { return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ); } @@ -669,13 +688,16 @@ /* * smack_inode_removexattr - Smack check on removexattr * @dentry: the object + * @mnt: unused * @name: name of the attribute + * @file: unused * * Removing the Smack attribute requires CAP_MAC_ADMIN * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_removexattr(struct dentry *dentry, const char *name) +static int smack_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, + const char *name, struct file *file) { int rc = 0; @@ -685,7 +707,7 @@ if (!capable(CAP_MAC_ADMIN)) rc = -EPERM; } else - rc = cap_inode_removexattr(dentry, name); + rc = cap_inode_removexattr(dentry, mnt, name, file); if (rc == 0) rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); --- linux-2.6.27.orig/net/rfkill/rfkill.c +++ linux-2.6.27/net/rfkill/rfkill.c @@ -117,6 +117,7 @@ static void notify_rfkill_state_change(struct rfkill *rfkill) { + rfkill_led_trigger(rfkill, rfkill->state); blocking_notifier_call_chain(&rfkill_notifier_list, RFKILL_STATE_CHANGED, rfkill); @@ -204,10 +205,8 @@ rfkill->state = state; } - if (force || rfkill->state != oldstate) { - rfkill_led_trigger(rfkill, rfkill->state); + if (force || rfkill->state != oldstate) notify_rfkill_state_change(rfkill); - } return retval; } --- linux-2.6.27.orig/net/mac80211/wext.c +++ linux-2.6.27/net/mac80211/wext.c @@ -804,7 +804,7 @@ * configure it here */ if (local->ops->set_frag_threshold) - local->ops->set_frag_threshold( + return local->ops->set_frag_threshold( local_to_hw(local), local->fragmentation_threshold); --- linux-2.6.27.orig/net/mac80211/debugfs_netdev.c +++ linux-2.6.27/net/mac80211/debugfs_netdev.c @@ -537,6 +537,7 @@ { struct net_device *dev = ndev; struct dentry *dir; + struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; char buf[10+IFNAMSIZ]; @@ -549,10 +550,19 @@ if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) return 0; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); + /* + * Do not use IEEE80211_DEV_TO_SUB_IF because that + * BUG_ONs for the master netdev which we need to + * handle here. + */ + sdata = netdev_priv(dev); - sprintf(buf, "netdev:%s", dev->name); dir = sdata->debugfsdir; + + if (!dir) + return 0; + + sprintf(buf, "netdev:%s", dev->name); if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " "dir to %s\n", buf); --- linux-2.6.27.orig/net/ipv4/tcp_output.c +++ linux-2.6.27/net/ipv4/tcp_output.c @@ -357,6 +357,17 @@ __u32 tsval, tsecr; /* need to include OPTION_TS */ }; +/* Beware: Something in the Internet is very sensitive to the ordering of + * TCP options, we learned this through the hard way, so be careful here. + * Luckily we can at least blame others for their non-compliance but from + * inter-operatibility perspective it seems that we're somewhat stuck with + * the ordering which we have been using if we want to keep working with + * those broken things (not that it currently hurts anybody as there isn't + * particular reason why the ordering would need to be changed). + * + * At least SACK_PERM as the first option is known to lead to a disaster + * (but it may well be that other scenarios fail similarly). + */ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, const struct tcp_out_options *opts, __u8 **md5_hash) { @@ -371,6 +382,12 @@ *md5_hash = NULL; } + if (unlikely(opts->mss)) { + *ptr++ = htonl((TCPOPT_MSS << 24) | + (TCPOLEN_MSS << 16) | + opts->mss); + } + if (likely(OPTION_TS & opts->options)) { if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) { *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | @@ -387,12 +404,6 @@ *ptr++ = htonl(opts->tsecr); } - if (unlikely(opts->mss)) { - *ptr++ = htonl((TCPOPT_MSS << 24) | - (TCPOLEN_MSS << 16) | - opts->mss); - } - if (unlikely(OPTION_SACK_ADVERTISE & opts->options && !(OPTION_TS & opts->options))) { *ptr++ = htonl((TCPOPT_NOP << 24) | @@ -2266,6 +2277,11 @@ } memset(&opts, 0, sizeof(opts)); +#ifdef CONFIG_SYN_COOKIES + if (unlikely(req->cookie_ts)) + TCP_SKB_CB(skb)->when = cookie_init_timestamp(req); + else +#endif TCP_SKB_CB(skb)->when = tcp_time_stamp; tcp_header_size = tcp_synack_options(sk, req, dst_metric(dst, RTAX_ADVMSS), @@ -2292,11 +2308,6 @@ /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ th->window = htons(min(req->rcv_wnd, 65535U)); -#ifdef CONFIG_SYN_COOKIES - if (unlikely(req->cookie_ts)) - TCP_SKB_CB(skb)->when = cookie_init_timestamp(req); - else -#endif tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); th->doff = (tcp_header_size >> 2); TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); --- linux-2.6.27.orig/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ linux-2.6.27/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -150,10 +150,12 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { +#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE) /* Previously seen (loopback)? Ignore. Do this before fragment check. */ if (skb->nfct) return NF_ACCEPT; +#endif /* Gather fragments. */ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { --- linux-2.6.27.orig/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ linux-2.6.27/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -742,6 +742,7 @@ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); if (*obj == NULL) { + kfree(p); kfree(id); if (net_ratelimit()) printk("OOM in bsalg (%d)\n", __LINE__); --- linux-2.6.27.orig/net/unix/af_unix.c +++ linux-2.6.27/net/unix/af_unix.c @@ -827,7 +827,8 @@ err = mnt_want_write(nd.path.mnt); if (err) goto out_mknod_dput; - err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); + err = vfs_mknod(nd.path.dentry->d_inode, dentry, nd.path.mnt, + mode, 0); mnt_drop_write(nd.path.mnt); if (err) goto out_mknod_dput; @@ -1300,14 +1301,23 @@ sock_wfree(skb); } -static void unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) +static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) { int i; + + /* + * Need to duplicate file references for the sake of garbage + * collection. Otherwise a socket in the fps might become a + * candidate for GC while the skb is not yet queued. + */ + UNIXCB(skb).fp = scm_fp_dup(scm->fp); + if (!UNIXCB(skb).fp) + return -ENOMEM; + for (i=scm->fp->count-1; i>=0; i--) unix_inflight(scm->fp->fp[i]); - UNIXCB(skb).fp = scm->fp; skb->destructor = unix_destruct_fds; - scm->fp = NULL; + return 0; } /* @@ -1366,8 +1376,11 @@ goto out; memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); - if (siocb->scm->fp) - unix_attach_fds(siocb->scm, skb); + if (siocb->scm->fp) { + err = unix_attach_fds(siocb->scm, skb); + if (err) + goto out_free; + } unix_get_secdata(siocb->scm, skb); skb_reset_transport_header(skb); @@ -1536,8 +1549,13 @@ size = min_t(int, size, skb_tailroom(skb)); memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); - if (siocb->scm->fp) - unix_attach_fds(siocb->scm, skb); + if (siocb->scm->fp) { + err = unix_attach_fds(siocb->scm, skb); + if (err) { + kfree_skb(skb); + goto out_err; + } + } if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) { kfree_skb(skb); --- linux-2.6.27.orig/net/unix/garbage.c +++ linux-2.6.27/net/unix/garbage.c @@ -186,8 +186,17 @@ */ struct sock *sk = unix_get_socket(*fp++); if (sk) { - hit = true; - func(unix_sk(sk)); + struct unix_sock *u = unix_sk(sk); + + /* + * Ignore non-candidates, they could + * have been added to the queues after + * starting the garbage collection + */ + if (u->gc_candidate) { + hit = true; + func(u); + } } } if (hit && hitlist != NULL) { @@ -249,11 +258,11 @@ { atomic_long_inc(&u->inflight); /* - * If this is still a candidate, move it to the end of the - * list, so that it's checked even if it was already passed - * over + * If this still might be part of a cycle, move it to the end + * of the list, so that it's checked even if it was already + * passed over */ - if (u->gc_candidate) + if (u->gc_maybe_cycle) list_move_tail(&u->link, &gc_candidates); } @@ -267,6 +276,7 @@ struct unix_sock *next; struct sk_buff_head hitlist; struct list_head cursor; + LIST_HEAD(not_cycle_list); spin_lock(&unix_gc_lock); @@ -282,10 +292,14 @@ * * Holding unix_gc_lock will protect these candidates from * being detached, and hence from gaining an external - * reference. This also means, that since there are no - * possible receivers, the receive queues of these sockets are - * static during the GC, even though the dequeue is done - * before the detach without atomicity guarantees. + * reference. Since there are no possible receivers, all + * buffers currently on the candidates' queues stay there + * during the garbage collection. + * + * We also know that no new candidate can be added onto the + * receive queues. Other, non candidate sockets _can_ be + * added to queue, so we must make sure only to touch + * candidates. */ list_for_each_entry_safe(u, next, &gc_inflight_list, link) { long total_refs; @@ -299,6 +313,7 @@ if (total_refs == inflight_refs) { list_move_tail(&u->link, &gc_candidates); u->gc_candidate = 1; + u->gc_maybe_cycle = 1; } } @@ -325,14 +340,24 @@ list_move(&cursor, &u->link); if (atomic_long_read(&u->inflight) > 0) { - list_move_tail(&u->link, &gc_inflight_list); - u->gc_candidate = 0; + list_move_tail(&u->link, ¬_cycle_list); + u->gc_maybe_cycle = 0; scan_children(&u->sk, inc_inflight_move_tail, NULL); } } list_del(&cursor); /* + * not_cycle_list contains those sockets which do not make up a + * cycle. Restore these to the inflight list. + */ + while (!list_empty(¬_cycle_list)) { + u = list_entry(not_cycle_list.next, struct unix_sock, link); + u->gc_candidate = 0; + list_move_tail(&u->link, &gc_inflight_list); + } + + /* * Now gc_candidates contains only garbage. Restore original * inflight counters for these as well, and remove the skbuffs * which are creating the cycle(s). --- linux-2.6.27.orig/net/bluetooth/hidp/core.c +++ linux-2.6.27/net/bluetooth/hidp/core.c @@ -684,6 +684,8 @@ } hidp_blacklist[] = { /* Apple wireless Mighty Mouse */ { 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, + /* Apple wireless Bluetooth Keyboard */ + { 0x05ac, 0x022c, HID_QUIRK_APPLE_HAS_FN }, { } /* Terminating entry */ }; --- linux-2.6.27.orig/net/core/scm.c +++ linux-2.6.27/net/core/scm.c @@ -75,6 +75,7 @@ if (!fpl) return -ENOMEM; *fplp = fpl; + INIT_LIST_HEAD(&fpl->list); fpl->count = 0; } fpp = &fpl->fp[fpl->count]; @@ -106,9 +107,25 @@ if (fpl) { scm->fp = NULL; - for (i=fpl->count-1; i>=0; i--) - fput(fpl->fp[i]); - kfree(fpl); + if (current->scm_work_list) { + list_add_tail(&fpl->list, current->scm_work_list); + } else { + LIST_HEAD(work_list); + + current->scm_work_list = &work_list; + + list_add(&fpl->list, &work_list); + while (!list_empty(&work_list)) { + fpl = list_first_entry(&work_list, struct scm_fp_list, list); + + list_del(&fpl->list); + for (i=fpl->count-1; i>=0; i--) + fput(fpl->fp[i]); + kfree(fpl); + } + + current->scm_work_list = NULL; + } } } @@ -284,6 +301,7 @@ new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); if (new_fpl) { + INIT_LIST_HEAD(&new_fpl->list); for (i=fpl->count-1; i>=0; i--) get_file(fpl->fp[i]); memcpy(new_fpl, fpl, sizeof(*fpl)); --- linux-2.6.27.orig/net/ipv6/tcp_ipv6.c +++ linux-2.6.27/net/ipv6/tcp_ipv6.c @@ -1087,7 +1087,7 @@ *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); *topt++ = htonl(tcp_time_stamp); - *topt = htonl(ts); + *topt++ = htonl(ts); } #ifdef CONFIG_TCP_MD5SIG --- linux-2.6.27.orig/net/sched/sch_generic.c +++ linux-2.6.27/net/sched/sch_generic.c @@ -319,6 +319,7 @@ static struct netdev_queue noop_netdev_queue = { .qdisc = &noop_qdisc, + .qdisc_sleeping = &noop_qdisc, }; struct Qdisc noop_qdisc = { @@ -344,6 +345,7 @@ static struct Qdisc noqueue_qdisc; static struct netdev_queue noqueue_netdev_queue = { .qdisc = &noqueue_qdisc, + .qdisc_sleeping = &noqueue_qdisc, }; static struct Qdisc noqueue_qdisc = { --- linux-2.6.27.orig/net/netfilter/xt_iprange.c +++ linux-2.6.27/net/netfilter/xt_iprange.c @@ -67,7 +67,7 @@ if (info->flags & IPRANGE_SRC) { m = ntohl(iph->saddr) < ntohl(info->src_min.ip); m |= ntohl(iph->saddr) > ntohl(info->src_max.ip); - m ^= info->flags & IPRANGE_SRC_INV; + m ^= !!(info->flags & IPRANGE_SRC_INV); if (m) { pr_debug("src IP " NIPQUAD_FMT " NOT in range %s" NIPQUAD_FMT "-" NIPQUAD_FMT "\n", @@ -81,7 +81,7 @@ if (info->flags & IPRANGE_DST) { m = ntohl(iph->daddr) < ntohl(info->dst_min.ip); m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip); - m ^= info->flags & IPRANGE_DST_INV; + m ^= !!(info->flags & IPRANGE_DST_INV); if (m) { pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s" NIPQUAD_FMT "-" NIPQUAD_FMT "\n", @@ -123,14 +123,14 @@ if (info->flags & IPRANGE_SRC) { m = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0; m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0; - m ^= info->flags & IPRANGE_SRC_INV; + m ^= !!(info->flags & IPRANGE_SRC_INV); if (m) return false; } if (info->flags & IPRANGE_DST) { m = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0; m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0; - m ^= info->flags & IPRANGE_DST_INV; + m ^= !!(info->flags & IPRANGE_DST_INV); if (m) return false; } --- linux-2.6.27.orig/arch/x86/Kconfig +++ linux-2.6.27/arch/x86/Kconfig @@ -1059,6 +1059,26 @@ low memory. Setting this option will put user-space page table entries in high memory. +config X86_RESERVE_LOW_64K + bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen" + default y + help + Reserve the first 64K of physical RAM on BIOSes that are known + to potentially corrupt that memory range. A numbers of BIOSes are + known to utilize this area during suspend/resume, so it must not + be used by the kernel. + + Set this to N if you are absolutely sure that you trust the BIOS + to get all its memory reservations and usages right. + + If you have doubts about the BIOS (e.g. suspend/resume does not + work or there's kernel crashes after certain hardware hotplug + events) and it's not AMI or Phoenix, then you might want to enable + X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical + corruption patterns. + + Say Y if unsure. + config MATH_EMULATION bool prompt "Math emulation" if X86_32 @@ -1782,6 +1802,8 @@ source "drivers/Kconfig" +source "ubuntu/Kconfig" + source "drivers/firmware/Kconfig" source "fs/Kconfig" --- linux-2.6.27.orig/arch/x86/kernel/early-quirks.c +++ linux-2.6.27/arch/x86/kernel/early-quirks.c @@ -95,6 +95,52 @@ } +static u32 ati_ixp4x0_rev(int num, int slot, int func) +{ + u32 d; + u8 b; + + b = read_pci_config_byte(num, slot, func, 0xac); + b &= ~(1<<5); + write_pci_config_byte(num, slot, func, 0xac, b); + + d = read_pci_config(num, slot, func, 0x70); + d |= 1<<8; + write_pci_config(num, slot, func, 0x70, d); + + d = read_pci_config(num, slot, func, 0x8); + d &= 0xff; + return d; +} + +static void __init ati_bugs(int num, int slot, int func) +{ +#if defined(CONFIG_ACPI) && defined (CONFIG_X86_IO_APIC) + u32 d; + u8 b; + + if (acpi_use_timer_override) + return; + + d = ati_ixp4x0_rev(num, slot, func); + if (d < 0x82) + acpi_skip_timer_override = 1; + else { + /* check for IRQ0 interrupt swap */ + outb(0x72, 0xcd6); b = inb(0xcd7); + if (!(b & 0x2)) + acpi_skip_timer_override = 1; + } + + if (acpi_skip_timer_override) { + printk(KERN_INFO "SB4X0 revision 0x%x\n", d); + printk(KERN_INFO "Ignoring ACPI timer override.\n"); + printk(KERN_INFO "If you got timer trouble " + "try acpi_use_timer_override\n"); + } +#endif +} + #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -114,6 +160,8 @@ PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, + PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, {} }; --- linux-2.6.27.orig/arch/x86/kernel/tsc.c +++ linux-2.6.27/arch/x86/kernel/tsc.c @@ -639,10 +639,6 @@ cpu_khz = calibrate_cpu(); #endif - lpj = ((u64)tsc_khz * 1000); - do_div(lpj, HZ); - lpj_fine = lpj; - printk("Detected %lu.%03lu MHz processor.\n", (unsigned long)cpu_khz / 1000, (unsigned long)cpu_khz % 1000); @@ -662,6 +658,10 @@ /* now allow native_sched_clock() to use rdtsc */ tsc_disabled = 0; + lpj = ((u64)tsc_khz * 1000); + do_div(lpj, HZ); + lpj_fine = lpj; + use_tsc_delay(); /* Check and install the TSC clocksource */ dmi_check_system(bad_tsc_dmi_table); --- linux-2.6.27.orig/arch/x86/kernel/reboot.c +++ linux-2.6.27/arch/x86/kernel/reboot.c @@ -169,6 +169,15 @@ DMI_MATCH(DMI_BOARD_NAME, "0KW626"), }, }, + { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */ + .callback = set_bios_reboot, + .ident = "Dell OptiPlex 330", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"), + DMI_MATCH(DMI_BOARD_NAME, "0KP561"), + }, + }, { /* Handle problems with rebooting on Dell 2400's */ .callback = set_bios_reboot, .ident = "Dell PowerEdge 2400", @@ -185,6 +194,15 @@ DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"), }, }, + { /* Handle problems with rebooting on Dell Dimension 9200 */ + .callback = set_bios_reboot, + .ident = "Dell Dimension 9200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"), + DMI_MATCH(DMI_BOARD_NAME, "0CT017"), + }, + }, { /* Handle problems with rebooting on HP laptops */ .callback = set_bios_reboot, .ident = "HP Compaq Laptop", --- linux-2.6.27.orig/arch/x86/kernel/setup.c +++ linux-2.6.27/arch/x86/kernel/setup.c @@ -578,6 +578,39 @@ struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; +static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) +{ + printk(KERN_NOTICE + "%s detected: BIOS may corrupt low RAM, working it around.\n", + d->ident); + + e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED); + sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); + + return 0; +} + +/* List of systems that have known low memory corruption BIOS problems */ +static struct dmi_system_id __initdata bad_bios_dmi_table[] = { +#ifdef CONFIG_X86_RESERVE_LOW_64K + { + .callback = dmi_low_memory_corruption, + .ident = "AMI BIOS", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + }, + }, + { + .callback = dmi_low_memory_corruption, + .ident = "Phoenix BIOS", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + }, + }, +#endif + {} +}; + /* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures @@ -699,6 +732,10 @@ finish_e820_parsing(); + dmi_scan_machine(); + + dmi_check_system(bad_bios_dmi_table); + #ifdef CONFIG_X86_32 probe_roms(); #endif @@ -781,8 +818,6 @@ vsmp_init(); #endif - dmi_scan_machine(); - io_delay_init(); /* @@ -885,3 +920,5 @@ #endif #endif } + + --- linux-2.6.27.orig/arch/x86/kernel/rtc.c +++ linux-2.6.27/arch/x86/kernel/rtc.c @@ -223,11 +223,25 @@ static __init int add_rtc_cmos(void) { #ifdef CONFIG_PNP - if (!pnp_platform_devices) - platform_device_register(&rtc_device); -#else + static const char *ids[] __initconst = + { "PNP0b00", "PNP0b01", "PNP0b02", }; + struct pnp_dev *dev; + struct pnp_id *id; + int i; + + pnp_for_each_dev(dev) { + for (id = dev->id; id; id = id->next) { + for (i = 0; i < ARRAY_SIZE(ids); i++) { + if (compare_pnp_id(id, ids[i]) != 0) + return 0; + } + } + } +#endif + platform_device_register(&rtc_device); -#endif /* CONFIG_PNP */ + dev_info(&rtc_device.dev, + "registered platform RTC device (no PNP device found)\n"); return 0; } device_initcall(add_rtc_cmos); --- linux-2.6.27.orig/arch/x86/kernel/process_64.c +++ linux-2.6.27/arch/x86/kernel/process_64.c @@ -729,12 +729,12 @@ if (!p || p == current || p->state==TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); - if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) + if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); do { if (fp < (unsigned long)stack || - fp > (unsigned long)stack+THREAD_SIZE) + fp >= (unsigned long)stack+THREAD_SIZE) return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) --- linux-2.6.27.orig/arch/x86/kernel/alternative.c +++ linux-2.6.27/arch/x86/kernel/alternative.c @@ -410,6 +410,8 @@ void __init alternative_instructions(void) { + unsigned long flags; + /* The patching is not fully atomic, so try to avoid local interruptions that might execute the to be patched code. Other CPUs are not running. */ @@ -418,7 +420,9 @@ stop_mce(); #endif + local_irq_save(flags); apply_alternatives(__alt_instructions, __alt_instructions_end); + local_irq_restore(flags); /* switch to patch-once-at-boottime-only mode and free the * tables in case we know the number of CPUs will never ever @@ -444,11 +448,13 @@ _text, _etext); /* Only switch to UP mode if we don't immediately boot others */ - if (num_possible_cpus() == 1 || setup_max_cpus <= 1) + if (num_present_cpus() == 1 || setup_max_cpus <= 1) alternatives_smp_switch(0); } #endif + local_irq_save(flags); apply_paravirt(__parainstructions, __parainstructions_end); + local_irq_restore(flags); if (smp_alt_once) free_init_pages("SMP alternatives", --- linux-2.6.27.orig/arch/x86/kernel/io_apic_32.c +++ linux-2.6.27/arch/x86/kernel/io_apic_32.c @@ -2314,6 +2314,9 @@ for (i = first_system_vector; i < NR_VECTORS; i++) set_bit(i, used_vectors); + /* Mark FIRST_DEVICE_VECTOR which is assigned to IRQ0 as used. */ + set_bit(FIRST_DEVICE_VECTOR, used_vectors); + enable_IO_APIC(); io_apic_irqs = ~PIC_IRQS; --- linux-2.6.27.orig/arch/x86/kernel/amd_iommu_init.c +++ linux-2.6.27/arch/x86/kernel/amd_iommu_init.c @@ -210,7 +210,7 @@ /* Programs the physical address of the device table into the IOMMU hardware */ static void __init iommu_set_device_table(struct amd_iommu *iommu) { - u32 entry; + u64 entry; BUG_ON(iommu->mmio_base == NULL); --- linux-2.6.27.orig/arch/x86/kernel/head64.c +++ linux-2.6.27/arch/x86/kernel/head64.c @@ -108,11 +108,11 @@ } load_idt((const struct desc_ptr *)&idt_descr); - early_printk("Kernel alive\n"); + //early_printk("Kernel alive\n"); x86_64_init_pda(); - early_printk("Kernel really alive\n"); + //early_printk("Kernel really alive\n"); x86_64_start_reservations(real_mode_data); } --- linux-2.6.27.orig/arch/x86/kernel/acpi/sleep.c +++ linux-2.6.27/arch/x86/kernel/acpi/sleep.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "realmode/wakeup.h" #include "sleep.h" @@ -98,6 +99,8 @@ header->trampoline_segment = setup_trampoline() >> 4; #ifdef CONFIG_SMP stack_start.sp = temp_stack + 4096; + early_gdt_descr.address = + (unsigned long)get_cpu_gdt_table(smp_processor_id()); #endif initial_code = (unsigned long)wakeup_long64; saved_magic = 0x123456789abcdef0; --- linux-2.6.27.orig/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ linux-2.6.27/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c @@ -45,6 +45,7 @@ CPU_DOTHAN_A1, CPU_DOTHAN_A2, CPU_DOTHAN_B0, + CPU_DOTHAN_C0, CPU_MP4HT_D0, CPU_MP4HT_E0, }; @@ -54,6 +55,7 @@ [CPU_DOTHAN_A1] = { 6, 13, 1 }, [CPU_DOTHAN_A2] = { 6, 13, 2 }, [CPU_DOTHAN_B0] = { 6, 13, 6 }, + [CPU_DOTHAN_C0] = { 6, 13, 8 }, [CPU_MP4HT_D0] = {15, 3, 4 }, [CPU_MP4HT_E0] = {15, 4, 1 }, }; @@ -196,6 +198,88 @@ }; #undef OP + +#define OPEX(mhz, base, mva, mvb, mvc, mvd) \ +{ \ + .frequency = (mhz) * 1000, \ + .index = (((mhz)/(base)) << 8) | ((mva - 700) / 16) \ +} + +/* Intel Pentium M processor 730 / 1.60 GHz (Sonoma) */ +static struct cpufreq_frequency_table sonoma_1596[] = +{ + OPEX( 798, 133, 988, 988, 988, 988), + OPEX(1064, 133, 1116, 1111, 1084, 1079), + OPEX(1330, 133, 1244, 1233, 1180, 1169), + OPEX(1596, 133, 1356, 1356, 1260, 1260), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 740 / 1.73 GHz (Sonoma) */ +static struct cpufreq_frequency_table sonoma_1729[] = +{ + OPEX( 798, 133, 988, 988, 988, 988), + OPEX(1064, 133, 1100, 1093, 1068, 1066), + OPEX(1330, 133, 1212, 1198, 1148, 1143), + OPEX(1729, 133, 1356, 1356, 1260, 1260), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 750 / 1.86 GHz (Sonoma) */ +static struct cpufreq_frequency_table sonoma_1862[] = +{ + OPEX( 798, 133, 988, 988, 988, 988), + OPEX(1064, 133, 1084, 1080, 1068, 1056), + OPEX(1330, 133, 1180, 1172, 1132, 1124), + OPEX(1596, 133, 1276, 1264, 1196, 1192), + OPEX(1862, 133, 1356, 1356, 1260, 1260), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 760 / 2.00 GHz (Sonoma) */ +static struct cpufreq_frequency_table sonoma_1995[] = +{ + OPEX( 798, 133, 988, 988, 988, 988), + OPEX(1064, 133, 1084, 1070, 1052, 1048), + OPEX(1330, 133, 1164, 1152, 1116, 1109), + OPEX(1596, 133, 1244, 1233, 1180, 1169), + OPEX(1995, 133, 1356, 1356, 1260, 1260), + { .frequency = CPUFREQ_TABLE_END } +}; +/* Intel Pentium M processor 770 / 2.13 GHz (Sonoma) */ +static struct cpufreq_frequency_table sonoma_2128[] = +{ + OPEX( 798, 133, 988, 988, 988, 988), + OPEX(1064, 133, 1068, 1065, 1052, 1042), + OPEX(1330, 133, 1148, 1142, 1100, 1097), + OPEX(1596, 133, 1228, 1218, 1164, 1151), + OPEX(1862, 133, 1308, 1295, 1212, 1206), + OPEX(2128, 133, 1372, 1372, 1260, 1260), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 780 / 2.26 GHz (Sonoma) */ +static struct cpufreq_frequency_table sonoma_2261[] = +{ + OPEX( 798, 133, 988, 988, 988, 988), + OPEX(1064, 133, 1068, 1064, 1052, 1037), + OPEX(1330, 133, 1148, 1139, 1100, 1087), + OPEX(1596, 133, 1228, 1215, 1148, 1136), + OPEX(1862, 133, 1292, 1291, 1196, 1186), + OPEX(2261, 133, 1404, 1404, 1260, 1260), + { .frequency = CPUFREQ_TABLE_END } +}; + +#undef OPEX + +#define SONOMA(cpuid, max, base, name) \ +{ .cpu_id = cpuid, \ + .model_name = "Intel(R) Pentium(R) M processor " name "GHz", \ + .max_freq = (max)*1000, \ + .op_points = sonoma_##max, \ +} + + #define _BANIAS(cpuid, max, name) \ { .cpu_id = cpuid, \ .model_name = "Intel(R) Pentium(R) M processor " name "MHz", \ @@ -218,6 +302,15 @@ BANIAS(1600), BANIAS(1700), + /* Builtin tables for Dothan C0 CPUs, a.k.a Sonoma */ + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1596, 133, "1.60"), + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1729, 133, "1.73"), + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1862, 133, "1.86"), + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1995, 133, "2.00"), + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 2128, 133, "2.13"), + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 2261, 133, "2.26"), + + /* NULL model_name is a wildcard */ { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, --- linux-2.6.27.orig/arch/x86/mm/pat.c +++ linux-2.6.27/arch/x86/mm/pat.c @@ -403,12 +403,16 @@ return 1; } #else +/* This check is needed to avoid cache aliasing when PAT is enabled */ static inline int range_is_allowed(unsigned long pfn, unsigned long size) { u64 from = ((u64)pfn) << PAGE_SHIFT; u64 to = from + size; u64 cursor = from; + if (!pat_enabled) + return 1; + while (cursor < to) { if (!devmem_is_allowed(pfn)) { printk(KERN_INFO --- linux-2.6.27.orig/arch/x86/mm/ioremap.c +++ linux-2.6.27/arch/x86/mm/ioremap.c @@ -595,7 +595,7 @@ */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; /* * Mappings have to fit in the FIX_BTMAP area. --- linux-2.6.27.orig/arch/x86/pci/i386.c +++ linux-2.6.27/arch/x86/pci/i386.c @@ -128,7 +128,7 @@ pr = pci_find_parent_resource(dev, r); if (!r->start || !pr || request_resource(pr, r) < 0) { - dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); + dev_warn(&dev->dev, "BAR %d: can't allocate resource\n", idx); /* * Something is wrong with the region. * Invalidate the resource to prevent @@ -169,7 +169,7 @@ r->flags, disabled, pass); pr = pci_find_parent_resource(dev, r); if (!pr || request_resource(pr, r) < 0) { - dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); + dev_warn(&dev->dev, "BAR %d: can't allocate resource\n", idx); /* We'll assign a new address later */ r->end -= r->start; r->start = 0; --- linux-2.6.27.orig/arch/s390/kernel/smp.c +++ linux-2.6.27/arch/s390/kernel/smp.c @@ -1117,9 +1117,7 @@ return rc; } -static ssize_t __ref rescan_store(struct sys_device *dev, - struct sysdev_attribute *attr, - const char *buf, +static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf, size_t count) { int rc; @@ -1127,12 +1125,10 @@ rc = smp_rescan_cpus(); return rc ? rc : count; } -static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); +static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store); #endif /* CONFIG_HOTPLUG_CPU */ -static ssize_t dispatching_show(struct sys_device *dev, - struct sysdev_attribute *attr, - char *buf) +static ssize_t dispatching_show(struct sysdev_class *class, char *buf) { ssize_t count; @@ -1142,9 +1138,8 @@ return count; } -static ssize_t dispatching_store(struct sys_device *dev, - struct sysdev_attribute *attr, - const char *buf, size_t count) +static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf, + size_t count) { int val, rc; char delim; @@ -1166,7 +1161,8 @@ put_online_cpus(); return rc ? rc : count; } -static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store); +static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, + dispatching_store); static int __init topology_init(void) { @@ -1176,13 +1172,11 @@ register_cpu_notifier(&smp_cpu_nb); #ifdef CONFIG_HOTPLUG_CPU - rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, - &attr_rescan.attr); + rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_rescan); if (rc) return rc; #endif - rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, - &attr_dispatching.attr); + rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_dispatching); if (rc) return rc; for_each_present_cpu(cpu) { --- linux-2.6.27.orig/arch/sparc64/kernel/trampoline.S +++ linux-2.6.27/arch/sparc64/kernel/trampoline.S @@ -328,6 +328,12 @@ wrpr %g0, 0, %wstate + sethi %hi(prom_entry_lock), %g2 +1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 + membar #StoreLoad | #StoreStore + brnz,pn %g1, 1b + nop + /* As a hack, put &init_thread_union into %g6. * prom_world() loads from here to restore the %asi * register. @@ -337,7 +343,7 @@ sethi %hi(is_sun4v), %o0 lduw [%o0 + %lo(is_sun4v)], %o0 - brz,pt %o0, 1f + brz,pt %o0, 2f nop TRAP_LOAD_TRAP_BLOCK(%g2, %g3) @@ -369,10 +375,10 @@ call %o1 add %sp, (2047 + 128), %o0 - ba,pt %xcc, 2f + ba,pt %xcc, 3f nop -1: sethi %hi(sparc64_ttable_tl0), %o0 +2: sethi %hi(sparc64_ttable_tl0), %o0 set prom_set_trap_table_name, %g2 stx %g2, [%sp + 2047 + 128 + 0x00] mov 1, %g2 @@ -386,7 +392,11 @@ call %o1 add %sp, (2047 + 128), %o0 -2: ldx [%l0], %g6 +3: sethi %hi(prom_entry_lock), %g2 + stb %g0, [%g2 + %lo(prom_entry_lock)] + membar #StoreStore | #StoreLoad + + ldx [%l0], %g6 ldx [%g6 + TI_TASK], %g4 mov 1, %g5 --- linux-2.6.27.orig/arch/powerpc/mm/hash_utils_64.c +++ linux-2.6.27/arch/powerpc/mm/hash_utils_64.c @@ -381,8 +381,10 @@ printk(KERN_INFO "Huge page(16GB) memory: " "addr = 0x%lX size = 0x%lX pages = %d\n", phys_addr, block_size, expected_pages); - lmb_reserve(phys_addr, block_size * expected_pages); - add_gpage(phys_addr, block_size, expected_pages); + if (phys_addr + (16 * GB) <= lmb_end_of_DRAM()) { + lmb_reserve(phys_addr, block_size * expected_pages); + add_gpage(phys_addr, block_size, expected_pages); + } return 0; } --- linux-2.6.27.orig/arch/powerpc/mm/numa.c +++ linux-2.6.27/arch/powerpc/mm/numa.c @@ -89,6 +89,48 @@ return 0; } +/* + * get_active_region_work_fn - A helper function for get_node_active_region + * Returns datax set to the start_pfn and end_pfn if they contain + * the initial value of datax->start_pfn between them + * @start_pfn: start page(inclusive) of region to check + * @end_pfn: end page(exclusive) of region to check + * @datax: comes in with ->start_pfn set to value to search for and + * goes out with active range if it contains it + * Returns 1 if search value is in range else 0 + */ +static int __init get_active_region_work_fn(unsigned long start_pfn, + unsigned long end_pfn, void *datax) +{ + struct node_active_region *data; + data = (struct node_active_region *)datax; + + if (start_pfn <= data->start_pfn && end_pfn > data->start_pfn) { + data->start_pfn = start_pfn; + data->end_pfn = end_pfn; + return 1; + } + return 0; + +} + +/* + * get_node_active_region - Return active region containing start_pfn + * Active range returned is empty if none found. + * @start_pfn: The page to return the region for. + * @node_ar: Returned set to the active region containing start_pfn + */ +static void __init get_node_active_region(unsigned long start_pfn, + struct node_active_region *node_ar) +{ + int nid = early_pfn_to_nid(start_pfn); + + node_ar->nid = nid; + node_ar->start_pfn = start_pfn; + node_ar->end_pfn = start_pfn; + work_with_active_regions(nid, get_active_region_work_fn, node_ar); +} + static void __cpuinit map_cpu_to_node(int cpu, int node) { numa_cpu_lookup_table[cpu] = node; @@ -837,38 +879,53 @@ start_pfn, end_pfn); free_bootmem_with_active_regions(nid, end_pfn); + } - /* Mark reserved regions on this node */ - for (i = 0; i < lmb.reserved.cnt; i++) { - unsigned long physbase = lmb.reserved.region[i].base; - unsigned long size = lmb.reserved.region[i].size; - unsigned long start_paddr = start_pfn << PAGE_SHIFT; - unsigned long end_paddr = end_pfn << PAGE_SHIFT; - - if (early_pfn_to_nid(physbase >> PAGE_SHIFT) != nid && - early_pfn_to_nid((physbase+size-1) >> PAGE_SHIFT) != nid) - continue; - - if (physbase < end_paddr && - (physbase+size) > start_paddr) { - /* overlaps */ - if (physbase < start_paddr) { - size -= start_paddr - physbase; - physbase = start_paddr; - } - - if (size > end_paddr - physbase) - size = end_paddr - physbase; - - dbg("reserve_bootmem %lx %lx\n", physbase, - size); - reserve_bootmem_node(NODE_DATA(nid), physbase, - size, BOOTMEM_DEFAULT); - } + /* Mark reserved regions */ + for (i = 0; i < lmb.reserved.cnt; i++) { + unsigned long physbase = lmb.reserved.region[i].base; + unsigned long size = lmb.reserved.region[i].size; + unsigned long start_pfn = physbase >> PAGE_SHIFT; + unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT); + struct node_active_region node_ar; + + get_node_active_region(start_pfn, &node_ar); + while (start_pfn < end_pfn && + node_ar.start_pfn < node_ar.end_pfn) { + unsigned long reserve_size = size; + /* + * if reserved region extends past active region + * then trim size to active region + */ + if (end_pfn > node_ar.end_pfn) + reserve_size = (node_ar.end_pfn << PAGE_SHIFT) + - (start_pfn << PAGE_SHIFT); + dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, + reserve_size, node_ar.nid); + reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, + reserve_size, BOOTMEM_DEFAULT); + /* + * if reserved region is contained in the active region + * then done. + */ + if (end_pfn <= node_ar.end_pfn) + break; + + /* + * reserved region extends past the active region + * get next active region that contains this + * reserved region + */ + start_pfn = node_ar.end_pfn; + physbase = start_pfn << PAGE_SHIFT; + size = size - reserve_size; + get_node_active_region(start_pfn, &node_ar); } - sparse_memory_present_with_active_regions(nid); } + + for_each_online_node(nid) + sparse_memory_present_with_active_regions(nid); } void __init paging_init(void) --- linux-2.6.27.orig/arch/powerpc/platforms/embedded6xx/linkstation.c +++ linux-2.6.27/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,19 @@ }, }; +static __initdata struct of_device_id of_bus_ids[] = { + { .type = "soc", }, + { .compatible = "simple-bus", }, + {}, +}; + +static int __init declare_of_platform_devices(void) +{ + of_platform_bus_probe(NULL, of_bus_ids, NULL); + return 0; +} +machine_device_initcall(linkstation, declare_of_platform_devices); + static int __init linkstation_add_bridge(struct device_node *dev) { #ifdef CONFIG_PCI --- linux-2.6.27.orig/arch/powerpc/configs/linkstation_defconfig +++ linux-2.6.27/arch/powerpc/configs/linkstation_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc4 -# Thu Aug 21 00:52:05 2008 +# Linux kernel version: 2.6.27 +# Fri Oct 24 00:42:39 2008 # # CONFIG_PPC64 is not set @@ -934,7 +934,7 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set -CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_OF_PLATFORM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -1211,7 +1211,6 @@ # CONFIG_USB_STORAGE_ALAUDA is not set # CONFIG_USB_STORAGE_ONETOUCH is not set # CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_STORAGE_SIERRA is not set # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_LIBUSUAL is not set --- linux-2.6.27.orig/arch/arm/mm/cache-xsc3l2.c +++ linux-2.6.27/arch/arm/mm/cache-xsc3l2.c @@ -97,7 +97,7 @@ /* * Clean and invalidate partial last cache line. */ - if (end & (CACHE_LINE_SIZE - 1)) { + if (start < end && (end & (CACHE_LINE_SIZE - 1))) { xsc3_l2_clean_pa(end & ~(CACHE_LINE_SIZE - 1)); xsc3_l2_inv_pa(end & ~(CACHE_LINE_SIZE - 1)); end &= ~(CACHE_LINE_SIZE - 1); @@ -106,7 +106,7 @@ /* * Invalidate all full cache lines between 'start' and 'end'. */ - while (start != end) { + while (start < end) { xsc3_l2_inv_pa(start); start += CACHE_LINE_SIZE; } --- linux-2.6.27.orig/arch/arm/mach-pxa/reset.c +++ linux-2.6.27/arch/arm/mach-pxa/reset.c @@ -20,7 +20,7 @@ static int reset_gpio = -1; -int init_gpio_reset(int gpio) +int init_gpio_reset(int gpio, int output) { int rc; @@ -30,9 +30,12 @@ goto out; } - rc = gpio_direction_input(gpio); + if (output) + rc = gpio_direction_output(gpio, 0); + else + rc = gpio_direction_input(gpio); if (rc) { - printk(KERN_ERR "Can't configure reset_gpio for input\n"); + printk(KERN_ERR "Can't configure reset_gpio\n"); gpio_free(gpio); goto out; } --- linux-2.6.27.orig/arch/arm/mach-pxa/spitz.c +++ linux-2.6.27/arch/arm/mach-pxa/spitz.c @@ -548,7 +548,7 @@ static void __init common_init(void) { - init_gpio_reset(SPITZ_GPIO_ON_RESET); + init_gpio_reset(SPITZ_GPIO_ON_RESET, 1); pm_power_off = spitz_poweroff; arm_pm_restart = spitz_restart; --- linux-2.6.27.orig/arch/arm/mach-pxa/tosa.c +++ linux-2.6.27/arch/arm/mach-pxa/tosa.c @@ -781,7 +781,7 @@ gpio_set_wake(MFP_PIN_GPIO1, 1); /* We can't pass to gpio-keys since it will drop the Reset altfunc */ - init_gpio_reset(TOSA_GPIO_ON_RESET); + init_gpio_reset(TOSA_GPIO_ON_RESET, 0); pm_power_off = tosa_poweroff; arm_pm_restart = tosa_restart; --- linux-2.6.27.orig/arch/arm/mach-pxa/include/mach/reset.h +++ linux-2.6.27/arch/arm/mach-pxa/include/mach/reset.h @@ -10,9 +10,12 @@ extern unsigned int reset_status; extern void clear_reset_status(unsigned int mask); -/* - * register GPIO as reset generator +/** + * init_gpio_reset() - register GPIO as reset generator + * + * @gpio - gpio nr + * @output - set gpio as out/low instead of input during normal work */ -extern int init_gpio_reset(int gpio); +extern int init_gpio_reset(int gpio, int output); #endif /* __ASM_ARCH_RESET_H */ --- linux-2.6.27.orig/ubuntu/Kconfig +++ linux-2.6.27/ubuntu/Kconfig @@ -0,0 +1,25 @@ +menu "Ubuntu Supplied Third-Party Device Drivers" + +source "ubuntu/drbd/Kconfig" +source "ubuntu/iscsitarget/Kconfig" +source "ubuntu/squashfs/Kconfig" +source "ubuntu/aufs/Kconfig" +source "ubuntu/atl2/Kconfig" +source "ubuntu/et131x/Kconfig" +source "ubuntu/dm-raid4-5/Kconfig" +source "ubuntu/dm-loop/Kconfig" +source "ubuntu/ndiswrapper/Kconfig" +source "ubuntu/compcache/Kconfig" +source "ubuntu/misc/Kconfig" +source "ubuntu/heci/Kconfig" +source "ubuntu/qc-usb/Kconfig" +source "ubuntu/e1000e/Kconfig" +source "ubuntu/rfkill/Kconfig" +source "ubuntu/via_chrome9/Kconfig" +source "ubuntu/unionfs/Kconfig" +source "ubuntu/lirc/Kconfig" +source "ubuntu/gnbd/Kconfig" +source "ubuntu/gfs/Kconfig" +source "ubuntu/tlsup/Kconfig" + +endmenu --- linux-2.6.27.orig/ubuntu/Makefile +++ linux-2.6.27/ubuntu/Makefile @@ -0,0 +1,28 @@ +# +# Makefile for the Linux kernel ubuntu supplied third-party device drivers. +# + +obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ +obj-$(CONFIG_SCSI_ISCSITARGET) += iscsitarget/ +obj-$(CONFIG_SQUASHFS) += squashfs/ +obj-$(CONFIG_AUFS) += aufs/ +obj-$(CONFIG_ATL2) += atl2/ +obj-$(CONFIG_NET_ET131X) += et131x/ +obj-$(CONFIG_DM_RAID45) += dm-raid4-5/ +obj-$(CONFIG_DM_LOOP) += dm-loop/ +obj-$(CONFIG_NDISWRAPPER) += ndiswrapper/ +obj-$(CONFIG_TLSF) += compcache/ +obj-$(CONFIG_HECI) += heci/ +obj-$(CONFIG_QC_USB) += qc-usb/ +obj-$(CONFIG_E1000E_NEW) += e1000e/ +obj-$(CONFIG_DRM_VIA_CHROME9) += via_chrome9/ +obj-$(CONFIG_FS_UNIONFS) += unionfs/ +obj-$(CONFIG_LIRC_DEV) += lirc/ +obj-$(CONFIG_GNBD) += gnbd/ +obj-$(CONFIG_GFS_FS) += gfs/ +obj-$(CONFIG_TLSUP) += tlsup/ + +obj-m += misc/ rfkill/ + +# This is a stupid trick to get kbuild to create ubuntu/built-in.o +obj- += foo.o --- linux-2.6.27.orig/ubuntu/gfs/ops_export.h +++ linux-2.6.27/ubuntu/gfs/ops_export.h @@ -0,0 +1,6 @@ +#ifndef __OPS_EXPORT_DOT_H__ +#define __OPS_EXPORT_DOT_H__ + +extern const struct export_operations gfs_export_ops; + +#endif /* __OPS_EXPORT_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/file.h +++ linux-2.6.27/ubuntu/gfs/file.h @@ -0,0 +1,42 @@ +#ifndef __FILE_DOT_H__ +#define __FILE_DOT_H__ + +typedef int (*read_copy_fn_t) (struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size); +typedef int (*write_copy_fn_t) (struct gfs_inode *ip, struct buffer_head *bh, + void **buf, unsigned int offset, + unsigned int size, int new); + +int gfs_copy2mem(struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size); +int gfs_copy2user(struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size); +int gfs_readi(struct gfs_inode *ip, void *buf, uint64_t offset, + unsigned int size, read_copy_fn_t copy_fn); + +int gfs_copy_from_mem(struct gfs_inode *ip, struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size, int new); +int gfs_copy_from_user(struct gfs_inode *ip, struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size, int new); +int gfs_writei(struct gfs_inode *ip, void *buf, uint64_t offset, + unsigned int size, write_copy_fn_t copy_fn, + struct kiocb *iocb); + +int gfs_zero_blocks(struct gfs_inode *ip, struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size, int new); + +static __inline__ int +gfs_internal_read(struct gfs_inode *ip, char *buf, uint64_t offset, + unsigned int size) +{ + return gfs_readi(ip, buf, offset, size, gfs_copy2mem); +} + +static __inline__ int +gfs_internal_write(struct gfs_inode *ip, char *buf, uint64_t offset, + unsigned int size) +{ + return gfs_writei(ip, buf, offset, size, gfs_copy_from_mem, NULL); +} + +#endif /* __FILE_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lops.c +++ linux-2.6.27/ubuntu/gfs/lops.c @@ -0,0 +1,1648 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "glock.h" +#include "log.h" +#include "lops.h" +#include "quota.h" +#include "recovery.h" +#include "trans.h" +#include "unlinked.h" + +/** + * generic_le_add - generic routine to add a log element to a transaction + * @sdp: the filesystem + * @le: the log entry + * + */ + +static void +generic_le_add(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + struct gfs_trans *tr; + + /* Make sure it's not attached to a transaction already */ + gfs_assert(sdp, le->le_ops && + !le->le_trans && + list_empty(&le->le_list),); + + /* Attach it to the (one) transaction being built by this process */ + tr = get_transaction; + gfs_assert(sdp, tr,); + + le->le_trans = tr; + list_add(&le->le_list, &tr->tr_elements); +} + +/** + * glock_trans_end - drop a glock reference + * @sdp: the filesystem + * @le: the log element + * + * Called before incore-committing a transaction + * Release reference that was taken in gfs_trans_add_gl() + */ + +static void +glock_trans_end(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + struct gfs_glock *gl = container_of(le, struct gfs_glock, gl_new_le); + + gfs_assert(sdp, gfs_glock_is_locked_by_me(gl) && + gfs_glock_is_held_excl(gl),); + gfs_glock_put(gl); +} + +/** + * glock_print - print debug info about a log element + * @sdp: the filesystem + * @le: the log element + * @where: is this a new transaction or a incore transaction + * + */ + +static void +glock_print(struct gfs_sbd *sdp, struct gfs_log_element *le, unsigned int where) +{ + struct gfs_glock *gl; + + switch (where) { + case TRANS_IS_NEW: + gl = container_of(le, struct gfs_glock, gl_new_le); + break; + case TRANS_IS_INCORE: + gl = container_of(le, struct gfs_glock, gl_incore_le); + break; + default: + gfs_assert_warn(sdp, FALSE); + return; + } + + printk(" Glock: (%u, %"PRIu64")\n", + gl->gl_name.ln_type, + gl->gl_name.ln_number); +} + +/** + * glock_overlap_trans - Find any incore transactions that might overlap with + * (i.e. be combinable with the transaction containing) this LE + * @sdp: the filesystem + * @le: the log element + * + * Transactions that share a given glock are combinable. + * + * For a glock, the scope of the "search" is just the (max) one unique incore + * committed transaction to which the glock may be attached via its + * gl->gl_incore_le embedded log element. This trans may have previously + * been combined with other transactions, though (i.e. previous + * incore committed transactions that shared the same glock). + * + * Called as a beginning part of the incore commit of a transaction. + */ + +static struct gfs_trans * +glock_overlap_trans(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + struct gfs_glock *gl = container_of(le, struct gfs_glock, gl_new_le); + + return gl->gl_incore_le.le_trans; +} + +/** + * glock_incore_commit - commit this LE to the incore log + * @sdp: the filesystem + * @tr: the being-incore-committed transaction this LE is to be a part of + * @le: the log element (should be a gl->gl_new_le), which is attached + * to a "new" (just-ended) transaction. + * + * Attach glock's gl_incore_le to the being-incore-committed trans' LE list. + * Remove glock's gl_new_le from the just-ended new trans' LE list. + * If the just-ended new trans (le->le_trans) was combined (in incore_commit()) + * with a pre-existing incore trans (tr), this function effectively moves + * the LE from the new to the combined incore trans. + * If there was no combining, then the new trans itself is being committed + * (le->le_trans == tr); this function simply replaces the gl_new_le with a + * gl_incore_le on the trans' LE list. + * + * Make sure that this glock's gl_incore_le is attached to one and only one + * incore-committed transaction's (this one's) tr_elements list. + * One transaction (instead of a list of transactions) is sufficient, + * because incore_commit() combines multiple transactions that share a glock + * into one trans. + * Since transactions can contain multiple glocks, there are multiple + * possibilities for shared glocks, therefore multiple potential "bridges" + * for combining transactions. + */ + +static void +glock_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_log_element *le) +{ + struct gfs_glock *gl = container_of(le, struct gfs_glock, gl_new_le); + + /* Transactions were combined, based on this glock */ + if (gl->gl_incore_le.le_trans) + gfs_assert(sdp, gl->gl_incore_le.le_trans == tr,); + else { + /* Attach gl->gl_incore_le to being-committed trans */ + gl->gl_incore_le.le_trans = tr; + list_add(&gl->gl_incore_le.le_list, &tr->tr_elements); + + /* If transactions were combined (via another shared glock), + the combined trans is getting a new glock log element */ + if (tr != le->le_trans) + tr->tr_num_gl++; + } + + /* Remove gl->gl_new_le from "new" trans */ + le->le_trans = NULL; + list_del_init(&le->le_list); +} + +/** + * glock_add_to_ail - Add this LE to the AIL + * @sdp: the filesystem + * @le: the log element + * + * Glocks don't really get added to AIL (there's nothing to write to disk), + * they just get removed from the transaction at this time. + */ + +static void +glock_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + le->le_trans = NULL; + list_del_init(&le->le_list); +} + +/** + * glock_trans_combine - combine two incore transactions + * @sdp: the filesystem + * @tr: the surviving transaction + * @new_tr: the transaction that's going to disappear + * + */ + +static void +glock_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_trans *new_tr) +{ + tr->tr_num_gl += new_tr->tr_num_gl; +} + +/** + * buf_print - print debug info about a log element + * @sdp: the filesystem + * @le: the log element + * @where: is this a new transaction or a incore transaction + * + */ + +static void +buf_print(struct gfs_sbd *sdp, struct gfs_log_element *le, unsigned int where) +{ + struct gfs_bufdata *bd; + + switch (where) { + case TRANS_IS_NEW: + bd = container_of(le, struct gfs_bufdata, bd_new_le); + break; + case TRANS_IS_INCORE: + bd = container_of(le, struct gfs_bufdata, bd_incore_le); + break; + default: + gfs_assert_warn(sdp, FALSE); + return; + } + + printk(" Buffer: %"PRIu64"\n", (uint64_t)bd->bd_bh->b_blocknr); +} + +/** + * buf_incore_commit - commit this buffer LE to the incore log + * @sdp: the filesystem + * @tr: the incore transaction this LE is a part of + * @le: the log element for the "new" (just now complete) trans + * + * Invoked from incore_commit(). + * Move this buffer from "new" stage to "incore committed" stage of the + * transaction pipeline. + * If this buffer was already attached to a pre-existing incore trans, GFS is + * combining the new and incore transactions; decrement buffer's recursive + * pin count that was incremented when it was added to the new transaction, + * and remove the reference to the "new" (being swallowed) trans. + * Else, move this buffer's attach point from "new" to "incore" embedded LE + * (same transaction, just new status) and add this buf to (incore) trans' + * LE list. + */ + +static void +buf_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_log_element *le) +{ + struct gfs_bufdata *bd = container_of(le, struct gfs_bufdata, bd_new_le); + + /* We've completed our (atomic) changes to this buffer for this trans. + We no longer need the frozen copy. If frozen copy was not written + to on-disk log already, there's no longer a need to; we can now + write the "real" buffer (with more up-to-date content) instead. */ + if (bd->bd_frozen) { + kfree(bd->bd_frozen); + bd->bd_frozen = NULL; + } + + /* New trans being combined with pre-existing incore trans? */ + if (bd->bd_incore_le.le_trans) { + gfs_assert(sdp, bd->bd_incore_le.le_trans == tr,); + gfs_dunpin(sdp, bd->bd_bh, NULL); + } else { + bd->bd_incore_le.le_trans = tr; + list_add(&bd->bd_incore_le.le_list, &tr->tr_elements); + if (tr != le->le_trans) + tr->tr_num_buf++; + + sdp->sd_log_buffers++; + } + + /* Reset buffer's bd_new_le */ + le->le_trans = NULL; + list_del_init(&le->le_list); +} + +/** + * buf_add_to_ail - Add this LE to the AIL + * @sdp: the filesystem + * @le: the log element + * + */ + +static void +buf_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + struct gfs_bufdata *bd = container_of(le, + struct gfs_bufdata, + bd_incore_le); + + gfs_dunpin(sdp, bd->bd_bh, le->le_trans); + + le->le_trans = NULL; + list_del_init(&le->le_list); + + gfs_assert(sdp, sdp->sd_log_buffers,); + sdp->sd_log_buffers--; +} + +/** + * buf_trans_size - compute how much space the LE class takes up in a transaction + * @sdp: the filesystem + * @tr: the transaction + * @mblks: the number of regular metadata blocks + * @eblks: the number of extra blocks + * @blocks: the number of log blocks + * @bmem: the number of buffer-sized chunks of memory we need + * + */ + +static void +buf_trans_size(struct gfs_sbd *sdp, struct gfs_trans *tr, + unsigned int *mblks, unsigned int *eblks, + unsigned int *blocks, unsigned int *bmem) +{ + unsigned int cblks; + + if (tr->tr_num_buf) { + cblks = gfs_struct2blk(sdp, tr->tr_num_buf, + sizeof(struct gfs_block_tag)); + + if (mblks) + *mblks += tr->tr_num_buf; + if (blocks) + *blocks += tr->tr_num_buf + cblks; + if (bmem) + *bmem += cblks; + } +} + +/** + * buf_trans_combine - combine two incore transactions + * @sdp: the filesystem + * @tr: the surviving transaction + * @new_tr: the transaction that's going to disappear + * + */ + +static void +buf_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_trans *new_tr) +{ + tr->tr_num_buf += new_tr->tr_num_buf; +} + +/** + * increment_generation - increment the generation number in metadata buffer + * @sdp: the filesystem + * @bd: the struct gfs_bufdata structure associated with the buffer + * + * Increment the generation # of the most recent buffer contents, as well as + * that of frozen buffer, if any. If there is a frozen buffer, only *it* + * will be going to the log now ... in this case, the current buffer will + * have its gen # incremented again later, when it gets written to log. + * Gen # is used by journal recovery (replay_block()) to determine whether + * to overwrite an inplace block with the logged block contents. + */ + +static void +increment_generation(struct gfs_sbd *sdp, struct gfs_bufdata *bd) +{ + struct gfs_meta_header *mh, *mh2; + uint64_t tmp64; + + mh = (struct gfs_meta_header *)bd->bd_bh->b_data; + + tmp64 = gfs64_to_cpu(mh->mh_generation) + 1; + tmp64 = cpu_to_gfs64(tmp64); + + if (bd->bd_frozen) { + mh2 = (struct gfs_meta_header *)bd->bd_frozen; + gfs_assert(sdp, mh->mh_generation == mh2->mh_generation,); + mh2->mh_generation = tmp64; + } + mh->mh_generation = tmp64; +} + +/** + * buf_build_bhlist - create the buffers that will make up the ondisk part of a transaction + * @sdp: the filesystem + * @tr: the transaction + * + * Create the log (transaction) descriptor block + */ + +static void +buf_build_bhlist(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *tmp, *head; + struct gfs_log_element *le; + struct gfs_bufdata *bd; + struct gfs_log_descriptor desc; + struct gfs_block_tag tag; + struct gfs_log_buf *clb = NULL; + unsigned int num_ctl; + unsigned int offset = sizeof(struct gfs_log_descriptor); + unsigned int x, bufs; + + if (!tr->tr_num_buf) + return; + + /* set up control buffers for descriptor and tags */ + + num_ctl = gfs_struct2blk(sdp, tr->tr_num_buf, + sizeof(struct gfs_block_tag)); + + for (x = 0; x < num_ctl; x++) { + if (clb) + gfs_log_get_buf(sdp, tr); + else + clb = gfs_log_get_buf(sdp, tr); + } + + /* Init and copy log descriptor into 1st control block */ + memset(&desc, 0, sizeof(struct gfs_log_descriptor)); + desc.ld_header.mh_magic = GFS_MAGIC; + desc.ld_header.mh_type = GFS_METATYPE_LD; + desc.ld_header.mh_format = GFS_FORMAT_LD; + desc.ld_type = GFS_LOG_DESC_METADATA; + desc.ld_length = num_ctl + tr->tr_num_buf; + desc.ld_data1 = tr->tr_num_buf; + gfs_desc_out(&desc, clb->lb_bh.b_data); + + x = 1; + bufs = 0; + + for (head = &tr->tr_elements, tmp = head->next; + tmp != head; + tmp = tmp->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + + /* Skip over non-buffer (e.g. glock, unlinked, etc.) LEs */ + if (le->le_ops != &gfs_buf_lops) + continue; + + bd = container_of(le, struct gfs_bufdata, bd_incore_le); + + gfs_meta_check(sdp, bd->bd_bh); + + gfs_lock_buffer(bd->bd_bh); + + increment_generation(sdp, bd); + + /* Create "fake" buffer head to write block to on-disk log. Use + frozen copy if another transaction is modifying the "real" + buffer contents. Unlock real bh after log write completes, + so Linux can write real contents to inplace block. */ + gfs_log_fake_buf(sdp, tr, + (bd->bd_frozen) ? bd->bd_frozen : bd->bd_bh->b_data, + bd->bd_bh); + + /* find another buffer for tags if we're overflowing this one */ + if (offset + sizeof(struct gfs_block_tag) > sdp->sd_sb.sb_bsize) { + clb = list_entry(clb->lb_list.prev, + struct gfs_log_buf, lb_list); + if (gfs_log_is_header(sdp, clb->lb_bh.b_blocknr)) + clb = list_entry(clb->lb_list.prev, + struct gfs_log_buf, lb_list); + x++; + offset = 0; + } + + /* Write this LE's tag into a control buffer */ + memset(&tag, 0, sizeof(struct gfs_block_tag)); + tag.bt_blkno = bd->bd_bh->b_blocknr; + + gfs_block_tag_out(&tag, clb->lb_bh.b_data + offset); + + offset += sizeof(struct gfs_block_tag); + bufs++; + } + + gfs_assert(sdp, x == num_ctl,); + gfs_assert(sdp, bufs == tr->tr_num_buf,); +} + +/** + * buf_before_scan - called before journal replay + * @sdp: the filesystem + * @jid: the journal ID about to be replayed + * @head: the current head of the log + * @pass: the pass through the journal + * + */ + +static void +buf_before_scan(struct gfs_sbd *sdp, unsigned int jid, + struct gfs_log_header *head, unsigned int pass) +{ + if (pass == GFS_RECPASS_A1) + sdp->sd_recovery_replays = + sdp->sd_recovery_skips = + sdp->sd_recovery_sames = 0; +} + +/** + * replay_block - Replay a single metadata block + * @sdp: the filesystem + * @jdesc: the struct gfs_jindex structure for the journal being replayed + * @gl: the journal's glock + * @tag: the block tag describing the inplace location of the block + * @blkno: the location of the log's copy of the block + * + * Returns: errno + * + * Read in-place block from disk + * Read log (journal) block from disk + * Compare generation numbers + * Copy log block to in-place block on-disk if: + * log generation # > in-place generation # + * OR generation #s are ==, but data contained in block is different (corrupt) + */ + +static int +replay_block(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, struct gfs_block_tag *tag, uint64_t blkno) +{ + struct buffer_head *inplace_bh, *log_bh; + struct gfs_meta_header inplace_mh, log_mh; + int replay_block = TRUE; + int error = 0; + + gfs_replay_check(sdp); + + /* Warning: Using a real buffer here instead of a tempbh can be bad + on a OS that won't support multiple simultaneous buffers for the + same block on different glocks. */ + + error = gfs_dread(gl, tag->bt_blkno, + DIO_START | DIO_WAIT, &inplace_bh); + if (error) + return error; + if (gfs_meta_check(sdp, inplace_bh)) { + brelse(inplace_bh); + return -EIO; + } + gfs_meta_header_in(&inplace_mh, inplace_bh->b_data); + + error = gfs_dread(gl, blkno, DIO_START | DIO_WAIT, &log_bh); + if (error) { + brelse(inplace_bh); + return error; + } + if (gfs_meta_check(sdp, log_bh)) { + brelse(inplace_bh); + brelse(log_bh); + return -EIO; + } + gfs_meta_header_in(&log_mh, log_bh->b_data); + + if (log_mh.mh_generation < inplace_mh.mh_generation) { + replay_block = FALSE; + sdp->sd_recovery_skips++; + } else if (log_mh.mh_generation == inplace_mh.mh_generation) { + if (memcmp(log_bh->b_data, + inplace_bh->b_data, + sdp->sd_sb.sb_bsize) == 0) { + replay_block = FALSE; + sdp->sd_recovery_sames++; + } + } + + if (replay_block) { + memcpy(inplace_bh->b_data, + log_bh->b_data, + sdp->sd_sb.sb_bsize); + + error = gfs_replay_buf(gl, inplace_bh); + if (!error) + sdp->sd_recovery_replays++; + } + + brelse(log_bh); + brelse(inplace_bh); + + return error; +} + +/** + * buf_scan_elements - Replay a metadata log descriptor + * @sdp: the filesystem + * @jdesc: the struct gfs_jindex structure for the journal being replayed + * @gl: the journal's glock + * @start: the starting block of the descriptor + * @desc: the descriptor structure + * @pass: the pass through the journal + * + * Returns: errno + */ + +static int +buf_scan_elements(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint64_t start, + struct gfs_log_descriptor *desc, unsigned int pass) +{ + struct gfs_block_tag tag; + struct buffer_head *bh; + uint64_t cblk = start; + unsigned int num_tags = desc->ld_data1; + unsigned int offset = sizeof(struct gfs_log_descriptor); + unsigned int x; + int error; + + if (pass != GFS_RECPASS_A1) + return 0; + if (desc->ld_type != GFS_LOG_DESC_METADATA) + return 0; + + x = gfs_struct2blk(sdp, num_tags, sizeof(struct gfs_block_tag)); + while (x--) { + error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE); + if (error) + return error; + } + + for (;;) { + gfs_assert(sdp, num_tags,); + + error = gfs_dread(gl, cblk, DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + /* Do readahead for the inplace blocks in this control block */ + { + unsigned int o2 = offset; + unsigned int nt2 = num_tags; + + while (o2 + sizeof(struct gfs_block_tag) <= + sdp->sd_sb.sb_bsize) { + gfs_block_tag_in(&tag, bh->b_data + o2); + gfs_start_ra(gl, tag.bt_blkno, 1); + if (!--nt2) + break; + o2 += sizeof(struct gfs_block_tag); + } + } + + while (offset + sizeof(struct gfs_block_tag) <= + sdp->sd_sb.sb_bsize) { + gfs_block_tag_in(&tag, bh->b_data + offset); + + error = replay_block(sdp, jdesc, gl, &tag, start); + if (error) + goto out_drelse; + + if (!--num_tags) + goto out_drelse; + + error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE); + if (error) + goto out_drelse; + + offset += sizeof(struct gfs_block_tag); + } + + brelse(bh); + + error = gfs_increment_blkno(sdp, jdesc, gl, &cblk, TRUE); + if (error) + return error; + + offset = 0; + } + + return 0; + + out_drelse: + brelse(bh); + + return error; +} + +/** + * buf_after_scan - called after journal replay + * @sdp: the filesystem + * @jid: the journal ID about to be replayed + * @pass: the pass through the journal + * + */ + +static void +buf_after_scan(struct gfs_sbd *sdp, unsigned int jid, unsigned int pass) +{ + if (pass == GFS_RECPASS_A1) { + printk("GFS: fsid=%s: jid=%u: Replayed %u of %u blocks\n", + sdp->sd_fsname, jid, + sdp->sd_recovery_replays, + sdp->sd_recovery_replays + sdp->sd_recovery_skips + + sdp->sd_recovery_sames); + printk("GFS: fsid=%s: jid=%u: replays = %u, skips = %u, sames = %u\n", + sdp->sd_fsname, jid, sdp->sd_recovery_replays, + sdp->sd_recovery_skips, sdp->sd_recovery_sames); + } +} + +/** + * unlinked_print - print debug info about a log element + * @sdp: the filesystem + * @le: the log element + * @where: is this a new transaction or a incore transaction + * + */ + +static void +unlinked_print(struct gfs_sbd *sdp, struct gfs_log_element *le, + unsigned int where) +{ + struct gfs_unlinked *ul; + char *type; + + switch (where) { + case TRANS_IS_NEW: + ul = container_of(le, struct gfs_unlinked, ul_new_le); + type = (test_bit(ULF_NEW_UL, &ul->ul_flags)) ? + "unlink" : "dealloc"; + break; + case TRANS_IS_INCORE: + ul = container_of(le, struct gfs_unlinked, ul_incore_le); + type = (test_bit(ULF_INCORE_UL, &ul->ul_flags)) ? + "unlink" : "dealloc"; + break; + default: + gfs_assert_warn(sdp, FALSE); + return; + } + + printk(" unlinked: %"PRIu64"/%"PRIu64", %s\n", + ul->ul_inum.no_formal_ino, ul->ul_inum.no_addr, + type); +} + +/** + * unlinked_incore_commit - commit this LE to the incore log + * @sdp: the filesystem + * @tr: the incore transaction this LE is a part of + * @le: the log element + * + */ + +static void +unlinked_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_log_element *le) +{ + struct gfs_unlinked *ul = container_of(le, + struct gfs_unlinked, + ul_new_le); + int n = !!test_bit(ULF_NEW_UL, &ul->ul_flags); + int i = !!test_bit(ULF_INCORE_UL, &ul->ul_flags); + + if (ul->ul_incore_le.le_trans) { + gfs_assert(sdp, ul->ul_incore_le.le_trans == tr,); + gfs_assert(sdp, n != i,); + + ul->ul_incore_le.le_trans = NULL; + list_del_init(&ul->ul_incore_le.le_list); + gfs_unlinked_put(sdp, ul); + + if (i) { + gfs_assert(sdp, tr->tr_num_iul,); + tr->tr_num_iul--; + } else { + gfs_assert(sdp, tr->tr_num_ida,); + tr->tr_num_ida--; + } + } else { + gfs_unlinked_hold(sdp, ul); + ul->ul_incore_le.le_trans = tr; + list_add(&ul->ul_incore_le.le_list, &tr->tr_elements); + + if (n) { + set_bit(ULF_INCORE_UL, &ul->ul_flags); + if (tr != le->le_trans) + tr->tr_num_iul++; + } else { + clear_bit(ULF_INCORE_UL, &ul->ul_flags); + if (tr != le->le_trans) + tr->tr_num_ida++; + } + } + + if (n) { + gfs_unlinked_hold(sdp, ul); + gfs_assert(sdp, !test_bit(ULF_IC_LIST, &ul->ul_flags),); + set_bit(ULF_IC_LIST, &ul->ul_flags); + atomic_inc(&sdp->sd_unlinked_ic_count); + } else { + gfs_assert(sdp, test_bit(ULF_IC_LIST, &ul->ul_flags),); + clear_bit(ULF_IC_LIST, &ul->ul_flags); + gfs_unlinked_put(sdp, ul); + gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count),); + atomic_dec(&sdp->sd_unlinked_ic_count); + } + + le->le_trans = NULL; + list_del_init(&le->le_list); + gfs_unlinked_put(sdp, ul); +} + +/** + * unlinked_add_to_ail - Add this LE to the AIL + * @sdp: the filesystem + * @le: the log element + * + */ + +static void +unlinked_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + struct gfs_unlinked *ul = container_of(le, + struct gfs_unlinked, + ul_incore_le); + int i = !!test_bit(ULF_INCORE_UL, &ul->ul_flags); + + if (i) { + gfs_unlinked_hold(sdp, ul); + gfs_assert(sdp, !test_bit(ULF_OD_LIST, &ul->ul_flags),); + set_bit(ULF_OD_LIST, &ul->ul_flags); + atomic_inc(&sdp->sd_unlinked_od_count); + } else { + gfs_assert(sdp, test_bit(ULF_OD_LIST, &ul->ul_flags),); + clear_bit(ULF_OD_LIST, &ul->ul_flags); + gfs_unlinked_put(sdp, ul); + gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_od_count),); + atomic_dec(&sdp->sd_unlinked_od_count); + } + + le->le_trans = NULL; + list_del_init(&le->le_list); + gfs_unlinked_put(sdp, ul); +} + +/** + * unlinked_clean_dump - clean up a LE after a log dump + * @sdp: the filesystem + * @le: the log element + * + */ + +static void +unlinked_clean_dump(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + le->le_trans = NULL; + list_del_init(&le->le_list); +} + +/** + * unlinked_trans_size - compute how much space the LE class takes up in a transaction + * @sdp: the filesystem + * @tr: the transaction + * @mblks: the number of regular metadata blocks + * @eblks: the number of extra blocks + * @blocks: the number of log blocks + * @bmem: the number of buffer-sized chunks of memory we need + * + */ + +static void +unlinked_trans_size(struct gfs_sbd *sdp, struct gfs_trans *tr, + unsigned int *mblks, unsigned int *eblks, + unsigned int *blocks, unsigned int *bmem) +{ + unsigned int ublks = 0; + + if (tr->tr_num_iul) + ublks = gfs_struct2blk(sdp, tr->tr_num_iul, + sizeof(struct gfs_inum)); + if (tr->tr_num_ida) + ublks += gfs_struct2blk(sdp, tr->tr_num_ida, + sizeof(struct gfs_inum)); + + if (eblks) + *eblks += ublks; + if (blocks) + *blocks += ublks; + if (bmem) + *bmem += ublks; +} + +/** + * unlinked_trans_combine - combine two incore transactions + * @sdp: the filesystem + * @tr: the surviving transaction + * @new_tr: the transaction that's going to disappear + * + */ + +static void +unlinked_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_trans *new_tr) +{ + tr->tr_num_iul += new_tr->tr_num_iul; + tr->tr_num_ida += new_tr->tr_num_ida; +} + +/** + * unlinked_build_bhlist - create the buffers that will make up the ondisk part of a transaction + * @sdp: the filesystem + * @tr: the transaction + * + * For unlinked and/or deallocated inode log elements (separately): + * Get a log block + * Create a log descriptor in beginning of that block + * Fill rest of block with gfs_inum structs to identify each inode + * that became unlinked/deallocated during this transaction. + * Get another log block if needed, continue filling with gfs_inums. + */ + +static void +unlinked_build_bhlist(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *tmp, *head; + struct gfs_log_element *le; + struct gfs_unlinked *ul; + struct gfs_log_descriptor desc; + struct gfs_log_buf *lb; + unsigned int pass = 2; + unsigned int type, number; + unsigned int offset, entries; + + /* 2 passes: 1st for Unlinked, 2nd for De-Alloced inodes, + unless this is a log dump: just 1 pass, for Unlinked */ + while (pass--) { + if (tr->tr_flags & TRF_LOG_DUMP) { + if (pass) { + type = GFS_LOG_DESC_IUL; + number = tr->tr_num_iul; + } else + break; + } else { + if (pass) { + type = GFS_LOG_DESC_IUL; + number = tr->tr_num_iul; + } else { + type = GFS_LOG_DESC_IDA; + number = tr->tr_num_ida; + } + + if (!number) + continue; + } + + lb = gfs_log_get_buf(sdp, tr); + + /* Header: log descriptor */ + memset(&desc, 0, sizeof(struct gfs_log_descriptor)); + desc.ld_header.mh_magic = GFS_MAGIC; + desc.ld_header.mh_type = GFS_METATYPE_LD; + desc.ld_header.mh_format = GFS_FORMAT_LD; + desc.ld_type = type; + desc.ld_length = gfs_struct2blk(sdp, number, sizeof(struct gfs_inum)); + desc.ld_data1 = (tr->tr_flags & TRF_LOG_DUMP) ? TRUE : FALSE; + gfs_desc_out(&desc, lb->lb_bh.b_data); + + offset = sizeof(struct gfs_log_descriptor); + entries = 0; + + /* Look through transaction's log elements for Unlinked LEs */ + for (head = &tr->tr_elements, tmp = head->next; + tmp != head; + tmp = tmp->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + if (le->le_ops != &gfs_unlinked_lops) + continue; + if (tr->tr_flags & TRF_LOG_DUMP) + ul = container_of(le, + struct gfs_unlinked, + ul_ondisk_le); + else { + ul = container_of(le, + struct gfs_unlinked, + ul_incore_le); + if (!!test_bit(ULF_INCORE_UL, &ul->ul_flags) != pass) + continue; + } + + if (offset + sizeof(struct gfs_inum) > sdp->sd_sb.sb_bsize) { + offset = 0; + lb = gfs_log_get_buf(sdp, tr); + } + + /* Payload: write the inode identifier */ + gfs_inum_out(&ul->ul_inum, + lb->lb_bh.b_data + offset); + + offset += sizeof(struct gfs_inum); + entries++; + } + + gfs_assert(sdp, entries == number,); + } +} + +/** + * unlinked_dump_size - compute how much space the LE class takes up in a log dump + * @sdp: the filesystem + * @elements: the number of log elements in the dump + * @blocks: the number of blocks in the dump + * @bmem: the number of buffer-sized chunks of memory we need + * + */ + +static void +unlinked_dump_size(struct gfs_sbd *sdp, unsigned int *elements, + unsigned int *blocks, unsigned int *bmem) +{ + unsigned int c = atomic_read(&sdp->sd_unlinked_od_count); + unsigned int b = gfs_struct2blk(sdp, c, sizeof(struct gfs_inum)); + + if (elements) + *elements += c; + if (blocks) + *blocks += b; + if (bmem) + *bmem += b; +} + +/** + * unlinked_build_dump - create a transaction that represents a log dump for this LE class + * @sdp: the filesystem + * @tr: the transaction to fill + * + */ + +static void +unlinked_build_dump(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *tmp, *head; + struct gfs_unlinked *ul; + unsigned int x = 0; + + tr->tr_num_iul = atomic_read(&sdp->sd_unlinked_od_count); + + spin_lock(&sdp->sd_unlinked_lock); + + for (head = &sdp->sd_unlinked_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + ul = list_entry(tmp, struct gfs_unlinked, ul_list); + if (!test_bit(ULF_OD_LIST, &ul->ul_flags)) + continue; + + gfs_assert(sdp, !ul->ul_ondisk_le.le_trans,); + ul->ul_ondisk_le.le_trans = tr; + list_add(&ul->ul_ondisk_le.le_list, &tr->tr_elements); + + x++; + } + + spin_unlock(&sdp->sd_unlinked_lock); + + gfs_assert(sdp, x == atomic_read(&sdp->sd_unlinked_od_count),); +} + +/** + * unlinked_before_scan - called before a log dump is recovered + * @sdp: the filesystem + * @jid: the journal ID about to be scanned + * @head: the current head of the log + * @pass: the pass through the journal + * + */ + +static void +unlinked_before_scan(struct gfs_sbd *sdp, unsigned int jid, + struct gfs_log_header *head, unsigned int pass) +{ + if (pass == GFS_RECPASS_B1) + clear_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags); +} + +/** + * unlinked_scan_elements - scan unlinked inodes from the journal + * @sdp: the filesystem + * @jdesc: the struct gfs_jindex structure for the journal being scaned + * @gl: the journal's glock + * @start: the starting block of the descriptor + * @desc: the descriptor structure + * @pass: the pass through the journal + * + * Returns: errno + */ + +static int +unlinked_scan_elements(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint64_t start, + struct gfs_log_descriptor *desc, unsigned int pass) +{ + struct gfs_inum inum; + struct buffer_head *bh; + unsigned int offset = sizeof(struct gfs_log_descriptor); + unsigned int x; + int error; + + if (pass != GFS_RECPASS_B1) + return 0; + + switch (desc->ld_type) { + case GFS_LOG_DESC_IUL: + if (test_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags)) + gfs_assert(sdp, !desc->ld_data1,); + else { + gfs_assert(sdp, desc->ld_data1,); + set_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags); + } + break; + + case GFS_LOG_DESC_IDA: + gfs_assert(sdp, test_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags),); + break; + + default: + return 0; + } + + for (x = 0; x < desc->ld_length; x++) { + error = gfs_dread(gl, start, DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + for (; + offset + sizeof(struct gfs_inum) <= sdp->sd_sb.sb_bsize; + offset += sizeof(struct gfs_inum)) { + gfs_inum_in(&inum, bh->b_data + offset); + + if (inum.no_addr) + gfs_unlinked_merge(sdp, desc->ld_type, &inum); + } + + brelse(bh); + + error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE); + if (error) + return error; + + offset = 0; + } + + return 0; +} + +/** + * unlinked_after_scan - called after a log dump is recovered + * @sdp: the filesystem + * @jid: the journal ID about to be scanned + * @pass: the pass through the journal + * + */ + +static void +unlinked_after_scan(struct gfs_sbd *sdp, unsigned int jid, unsigned int pass) +{ + if (pass == GFS_RECPASS_B1) { + gfs_assert(sdp, test_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags),); + printk("GFS: fsid=%s: Found %d unlinked inodes\n", + sdp->sd_fsname, atomic_read(&sdp->sd_unlinked_ic_count)); + } +} + +/** + * quota_print - print debug info about a log element + * @sdp: the filesystem + * @le: the log element + * @where: is this a new transaction or a incore transaction + * + */ + +static void +quota_print(struct gfs_sbd *sdp, struct gfs_log_element *le, unsigned int where) +{ + struct gfs_quota_le *ql; + + ql = container_of(le, struct gfs_quota_le, ql_le); + printk(" quota: %s %u: %"PRId64" blocks\n", + (test_bit(QDF_USER, &ql->ql_data->qd_flags)) ? "user" : "group", + ql->ql_data->qd_id, ql->ql_change); +} + +/** + * quota_incore_commit - commit this LE to the incore log + * @sdp: the filesystem + * @tr: the incore transaction this LE is a part of + * @le: the log element + * + */ + +static void +quota_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_log_element *le) +{ + struct gfs_quota_le *ql = container_of(le, struct gfs_quota_le, ql_le); + struct gfs_quota_data *qd = ql->ql_data; + + gfs_assert(sdp, ql->ql_change,); + + /* Make this change under the sd_quota_lock, so other processes + checking qd_change_ic don't have to acquire the log lock. */ + + spin_lock(&sdp->sd_quota_lock); + qd->qd_change_new -= ql->ql_change; + qd->qd_change_ic += ql->ql_change; + spin_unlock(&sdp->sd_quota_lock); + + if (le->le_trans == tr) + list_add(&ql->ql_data_list, &qd->qd_le_list); + else { + struct list_head *tmp, *head; + struct gfs_quota_le *tmp_ql; + int found = FALSE; + + for (head = &qd->qd_le_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + tmp_ql = list_entry(tmp, struct gfs_quota_le, ql_data_list); + if (tmp_ql->ql_le.le_trans != tr) + continue; + + tmp_ql->ql_change += ql->ql_change; + + list_del(&le->le_list); + gfs_quota_put(sdp, qd); + kfree(ql); + + if (!tmp_ql->ql_change) { + list_del(&tmp_ql->ql_data_list); + list_del(&tmp_ql->ql_le.le_list); + gfs_quota_put(sdp, tmp_ql->ql_data); + kfree(tmp_ql); + tr->tr_num_q--; + } + + found = TRUE; + break; + } + + if (!found) { + le->le_trans = tr; + list_move(&le->le_list, &tr->tr_elements); + tr->tr_num_q++; + list_add(&ql->ql_data_list, &qd->qd_le_list); + } + } +} + +/** + * quota_add_to_ail - Add this LE to the AIL + * @sdp: the filesystem + * @le: the log element + * + */ + +static void +quota_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + struct gfs_quota_le *ql = container_of(le, struct gfs_quota_le, ql_le); + struct gfs_quota_data *qd = ql->ql_data; + + qd->qd_change_od += ql->ql_change; + if (qd->qd_change_od) { + if (!test_bit(QDF_OD_LIST, &qd->qd_flags)) { + gfs_quota_hold(sdp, qd); + set_bit(QDF_OD_LIST, &qd->qd_flags); + atomic_inc(&sdp->sd_quota_od_count); + } + } else { + gfs_assert(sdp, test_bit(QDF_OD_LIST, &qd->qd_flags),); + clear_bit(QDF_OD_LIST, &qd->qd_flags); + gfs_quota_put(sdp, qd); + gfs_assert(sdp, atomic_read(&sdp->sd_quota_od_count),); + atomic_dec(&sdp->sd_quota_od_count); + } + + list_del(&ql->ql_data_list); + list_del(&le->le_list); + gfs_quota_put(sdp, qd); + kfree(ql); +} + +/** + * quota_clean_dump - clean up a LE after a log dump + * @sdp: the filesystem + * @le: the log element + * + */ + +static void +quota_clean_dump(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + le->le_trans = NULL; + list_del_init(&le->le_list); +} + +/** + * quota_trans_size - compute how much space the LE class takes up in a transaction + * @sdp: the filesystem + * @tr: the transaction + * @mblks: the number of regular metadata blocks + * @eblks: the number of extra blocks + * @blocks: the number of log blocks + * @bmem: the number of buffer-sized chunks of memory we need + * + */ + +static void +quota_trans_size(struct gfs_sbd *sdp, struct gfs_trans *tr, + unsigned int *mblks, unsigned int *eblks, + unsigned int *blocks, unsigned int *bmem) +{ + unsigned int qblks; + + if (tr->tr_num_q) { + qblks = gfs_struct2blk(sdp, tr->tr_num_q, + sizeof(struct gfs_quota_tag)); + + if (eblks) + *eblks += qblks; + if (blocks) + *blocks += qblks; + if (bmem) + *bmem += qblks; + } +} + +/** + * quota_trans_combine - combine two incore transactions + * @sdp: the filesystem + * @tr: the surviving transaction + * @new_tr: the transaction that's going to disappear + * + */ + +static void +quota_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_trans *new_tr) +{ + tr->tr_num_q += new_tr->tr_num_q; +} + +/** + * quota_build_bhlist - create the buffers that will make up the ondisk part of a transaction + * @sdp: the filesystem + * @tr: the transaction + * + */ + +static void +quota_build_bhlist(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *tmp, *head; + struct gfs_log_element *le; + struct gfs_quota_le *ql; + struct gfs_log_descriptor desc; + struct gfs_quota_tag tag; + struct gfs_log_buf *lb; + unsigned int offset = sizeof(struct gfs_log_descriptor), entries = 0; + + if (!tr->tr_num_q && !(tr->tr_flags & TRF_LOG_DUMP)) + return; + + lb = gfs_log_get_buf(sdp, tr); + + memset(&desc, 0, sizeof(struct gfs_log_descriptor)); + desc.ld_header.mh_magic = GFS_MAGIC; + desc.ld_header.mh_type = GFS_METATYPE_LD; + desc.ld_header.mh_format = GFS_FORMAT_LD; + desc.ld_type = GFS_LOG_DESC_Q; + desc.ld_length = gfs_struct2blk(sdp, tr->tr_num_q, + sizeof(struct gfs_quota_tag)); + desc.ld_data1 = tr->tr_num_q; + desc.ld_data2 = (tr->tr_flags & TRF_LOG_DUMP) ? TRUE : FALSE; + gfs_desc_out(&desc, lb->lb_bh.b_data); + + for (head = &tr->tr_elements, tmp = head->next; + tmp != head; + tmp = tmp->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + if (le->le_ops != &gfs_quota_lops) + continue; + + ql = container_of(le, struct gfs_quota_le, ql_le); + + if (offset + sizeof(struct gfs_quota_tag) > + sdp->sd_sb.sb_bsize) { + offset = 0; + lb = gfs_log_get_buf(sdp, tr); + } + + memset(&tag, 0, sizeof(struct gfs_quota_tag)); + tag.qt_change = ql->ql_change; + tag.qt_flags = (test_bit(QDF_USER, &ql->ql_data->qd_flags)) ? + GFS_QTF_USER : 0; + tag.qt_id = ql->ql_data->qd_id; + + gfs_quota_tag_out(&tag, lb->lb_bh.b_data + offset); + + offset += sizeof(struct gfs_quota_tag); + entries++; + } + + gfs_assert(sdp, entries == tr->tr_num_q,); +} + +/** + * quota_dump_size - compute how much space the LE class takes up in a log dump + * @sdp: the filesystem + * @elements: the number of log elements in the dump + * @blocks: the number of blocks in the dump + * @bmem: the number of buffer-sized chunks of memory we need + * + */ + +static void +quota_dump_size(struct gfs_sbd *sdp, unsigned int *elements, + unsigned int *blocks, unsigned int *bmem) +{ + unsigned int c = atomic_read(&sdp->sd_quota_od_count); + unsigned int b = gfs_struct2blk(sdp, c, sizeof(struct gfs_quota_tag)); + + if (elements) + *elements += c; + if (blocks) + *blocks += b; + if (bmem) + *bmem += b; +} + +/** + * quota_build_dump - create a transaction that represents a log dump for this LE class + * @sdp: the filesystem + * @tr: the transaction to fill + * + */ + +static void +quota_build_dump(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *tmp, *head; + struct gfs_quota_data *qd; + struct gfs_quota_le *ql; + unsigned int x = 0; + + tr->tr_num_q = atomic_read(&sdp->sd_quota_od_count); + + spin_lock(&sdp->sd_quota_lock); + + for (head = &sdp->sd_quota_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + qd = list_entry(tmp, struct gfs_quota_data, qd_list); + if (!test_bit(QDF_OD_LIST, &qd->qd_flags)) + continue; + + ql = &qd->qd_ondisk_ql; + + ql->ql_le.le_ops = &gfs_quota_lops; + gfs_assert(sdp, !ql->ql_le.le_trans,); + ql->ql_le.le_trans = tr; + list_add(&ql->ql_le.le_list, &tr->tr_elements); + + ql->ql_data = qd; + ql->ql_change = qd->qd_change_od; + + x++; + } + + spin_unlock(&sdp->sd_quota_lock); + + gfs_assert(sdp, x == atomic_read(&sdp->sd_quota_od_count),); +} + +/** + * quota_before_scan - called before a log dump is recovered + * @sdp: the filesystem + * @jid: the journal ID about to be scanned + * @head: the current head of the log + * @pass: the pass through the journal + * + */ + +static void +quota_before_scan(struct gfs_sbd *sdp, unsigned int jid, + struct gfs_log_header *head, unsigned int pass) +{ + if (pass == GFS_RECPASS_B1) + clear_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags); +} + +/** + * quota_scan_elements - scan quota inodes from the journal + * @sdp: the filesystem + * @jdesc: the struct gfs_jindex structure for the journal being scaned + * @gl: the journal's glock + * @start: the starting block of the descriptor + * @desc: the descriptor structure + * @pass: the pass through the journal + * + * Returns: errno + */ + +static int +quota_scan_elements(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint64_t start, + struct gfs_log_descriptor *desc, unsigned int pass) +{ + struct gfs_quota_tag tag; + struct buffer_head *bh; + unsigned int num_tags = desc->ld_data1; + unsigned int offset = sizeof(struct gfs_log_descriptor); + unsigned int x; + int error; + + if (pass != GFS_RECPASS_B1) + return 0; + if (desc->ld_type != GFS_LOG_DESC_Q) + return 0; + + if (test_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags)) + gfs_assert(sdp, !desc->ld_data2,); + else { + gfs_assert(sdp, desc->ld_data2,); + set_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags); + } + + if (!num_tags) + return 0; + + for (x = 0; x < desc->ld_length; x++) { + error = gfs_dread(gl, start, DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + while (offset + sizeof(struct gfs_quota_tag) <= + sdp->sd_sb.sb_bsize) { + gfs_quota_tag_in(&tag, bh->b_data + offset); + + error = gfs_quota_merge(sdp, &tag); + if (error) + goto out_drelse; + + if (!--num_tags) + goto out_drelse; + + offset += sizeof(struct gfs_quota_tag); + } + + brelse(bh); + + error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE); + if (error) + return error; + + offset = 0; + } + + return 0; + + out_drelse: + brelse(bh); + + return error; +} + +/** + * quota_after_scan - called after a log dump is recovered + * @sdp: the filesystem + * @jid: the journal ID about to be scanned + * @pass: the pass through the journal + * + */ + +static void +quota_after_scan(struct gfs_sbd *sdp, unsigned int jid, unsigned int pass) +{ + if (pass == GFS_RECPASS_B1) { + gfs_assert(sdp, !sdp->sd_sb.sb_quota_di.no_formal_ino || + test_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags),); + printk("GFS: fsid=%s: Found quota changes for %d IDs\n", + sdp->sd_fsname, atomic_read(&sdp->sd_quota_od_count)); + } +} + +struct gfs_log_operations gfs_glock_lops = { + .lo_add = generic_le_add, + .lo_trans_end = glock_trans_end, + .lo_print = glock_print, + .lo_overlap_trans = glock_overlap_trans, + .lo_incore_commit = glock_incore_commit, + .lo_add_to_ail = glock_add_to_ail, + .lo_trans_combine = glock_trans_combine, + .lo_name = "glock" +}; + +struct gfs_log_operations gfs_buf_lops = { + .lo_add = generic_le_add, + .lo_print = buf_print, + .lo_incore_commit = buf_incore_commit, + .lo_add_to_ail = buf_add_to_ail, + .lo_trans_size = buf_trans_size, + .lo_trans_combine = buf_trans_combine, + .lo_build_bhlist = buf_build_bhlist, + .lo_before_scan = buf_before_scan, + .lo_scan_elements = buf_scan_elements, + .lo_after_scan = buf_after_scan, + .lo_name = "buf" +}; + +struct gfs_log_operations gfs_unlinked_lops = { + .lo_add = generic_le_add, + .lo_print = unlinked_print, + .lo_incore_commit = unlinked_incore_commit, + .lo_add_to_ail = unlinked_add_to_ail, + .lo_clean_dump = unlinked_clean_dump, + .lo_trans_size = unlinked_trans_size, + .lo_trans_combine = unlinked_trans_combine, + .lo_build_bhlist = unlinked_build_bhlist, + .lo_dump_size = unlinked_dump_size, + .lo_build_dump = unlinked_build_dump, + .lo_before_scan = unlinked_before_scan, + .lo_scan_elements = unlinked_scan_elements, + .lo_after_scan = unlinked_after_scan, + .lo_name = "unlinked" +}; + +struct gfs_log_operations gfs_quota_lops = { + .lo_add = generic_le_add, + .lo_print = quota_print, + .lo_incore_commit = quota_incore_commit, + .lo_add_to_ail = quota_add_to_ail, + .lo_clean_dump = quota_clean_dump, + .lo_trans_size = quota_trans_size, + .lo_trans_combine = quota_trans_combine, + .lo_build_bhlist = quota_build_bhlist, + .lo_dump_size = quota_dump_size, + .lo_build_dump = quota_build_dump, + .lo_before_scan = quota_before_scan, + .lo_scan_elements = quota_scan_elements, + .lo_after_scan = quota_after_scan, + .lo_name = "quota" +}; + +struct gfs_log_operations *gfs_log_ops[] = { + &gfs_glock_lops, + &gfs_buf_lops, + &gfs_unlinked_lops, + &gfs_quota_lops, + NULL +}; --- linux-2.6.27.orig/ubuntu/gfs/ioctl.h +++ linux-2.6.27/ubuntu/gfs/ioctl.h @@ -0,0 +1,9 @@ +#ifndef __IOCTL_DOT_H__ +#define __IOCTL_DOT_H__ + +int gfs_ioctl_i_local(struct gfs_inode *ip, struct gfs_ioctl *gi, + const char *arg0, int from_user); +int gfs_ioctl_i_compat(struct gfs_inode *ip, unsigned long arg); +int gfs_ioctl_i(struct gfs_inode *ip, void *arg); + +#endif /* __IOCTL_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lock_dlm_sysfs.c +++ linux-2.6.27/ubuntu/gfs/lock_dlm_sysfs.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include +#include + +#include "lock_dlm.h" + +static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name); +} + +static ssize_t block_show(struct gdlm_ls *ls, char *buf) +{ + ssize_t ret; + int val = 0; + + if (test_bit(DFL_BLOCK_LOCKS, &ls->flags)) + val = 1; + ret = sprintf(buf, "%d\n", val); + return ret; +} + +static ssize_t block_store(struct gdlm_ls *ls, const char *buf, size_t len) +{ + ssize_t ret = len; + int val; + + val = simple_strtol(buf, NULL, 0); + + if (val == 1) + set_bit(DFL_BLOCK_LOCKS, &ls->flags); + else if (val == 0) { + clear_bit(DFL_BLOCK_LOCKS, &ls->flags); + gdlm_submit_delayed(ls); + } else { + ret = -EINVAL; + } + return ret; +} + +static ssize_t withdraw_show(struct gdlm_ls *ls, char *buf) +{ + ssize_t ret; + int val = 0; + + if (test_bit(DFL_WITHDRAW, &ls->flags)) + val = 1; + ret = sprintf(buf, "%d\n", val); + return ret; +} + +static ssize_t withdraw_store(struct gdlm_ls *ls, const char *buf, size_t len) +{ + ssize_t ret = len; + int val; + + val = simple_strtol(buf, NULL, 0); + + if (val == 1) + set_bit(DFL_WITHDRAW, &ls->flags); + else + ret = -EINVAL; + wake_up(&ls->wait_control); + return ret; +} + +static ssize_t id_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%u\n", ls->id); +} + +static ssize_t jid_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%d\n", ls->jid); +} + +static ssize_t first_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%d\n", ls->first); +} + +static ssize_t first_done_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%d\n", ls->first_done); +} + +static ssize_t recover_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%d\n", ls->recover_jid); +} + +static ssize_t recover_store(struct gdlm_ls *ls, const char *buf, size_t len) +{ + ls->recover_jid = simple_strtol(buf, NULL, 0); + ls->fscb(ls->sdp, LM_CB_NEED_RECOVERY, &ls->recover_jid); + return len; +} + +static ssize_t recover_done_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%d\n", ls->recover_jid_done); +} + +static ssize_t recover_status_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%d\n", ls->recover_jid_status); +} + +static ssize_t drop_count_show(struct gdlm_ls *ls, char *buf) +{ + return sprintf(buf, "%d\n", ls->drop_locks_count); +} + +static ssize_t drop_count_store(struct gdlm_ls *ls, const char *buf, size_t len) +{ + ls->drop_locks_count = simple_strtol(buf, NULL, 0); + return len; +} + +struct gdlm_attr { + struct attribute attr; + ssize_t (*show)(struct gdlm_ls *, char *); + ssize_t (*store)(struct gdlm_ls *, const char *, size_t); +}; + +#define GDLM_ATTR(_name,_mode,_show,_store) \ +static struct gdlm_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) + +GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); +GDLM_ATTR(block, 0644, block_show, block_store); +GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); +GDLM_ATTR(id, 0444, id_show, NULL); +GDLM_ATTR(jid, 0444, jid_show, NULL); +GDLM_ATTR(first, 0444, first_show, NULL); +GDLM_ATTR(first_done, 0444, first_done_show, NULL); +GDLM_ATTR(recover, 0644, recover_show, recover_store); +GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); +GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); +GDLM_ATTR(drop_count, 0644, drop_count_show, drop_count_store); + +static struct attribute *gdlm_attrs[] = { + &gdlm_attr_proto_name.attr, + &gdlm_attr_block.attr, + &gdlm_attr_withdraw.attr, + &gdlm_attr_id.attr, + &gdlm_attr_jid.attr, + &gdlm_attr_first.attr, + &gdlm_attr_first_done.attr, + &gdlm_attr_recover.attr, + &gdlm_attr_recover_done.attr, + &gdlm_attr_recover_status.attr, + &gdlm_attr_drop_count.attr, + NULL, +}; + +static ssize_t gdlm_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj); + struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr); + return a->show ? a->show(ls, buf) : 0; +} + +static ssize_t gdlm_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t len) +{ + struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj); + struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr); + return a->store ? a->store(ls, buf, len) : len; +} + +static struct sysfs_ops gdlm_attr_ops = { + .show = gdlm_attr_show, + .store = gdlm_attr_store, +}; + +static struct kobj_type gdlm_ktype = { + .default_attrs = gdlm_attrs, + .sysfs_ops = &gdlm_attr_ops, +}; + +static struct kset *gdlm_kset; + +int gdlm_kobject_setup(struct gdlm_ls *ls, struct kobject *fskobj) +{ + int error; + + ls->kobj.kset = gdlm_kset; + error = kobject_init_and_add(&ls->kobj, &gdlm_ktype, fskobj, + "lock_module"); + if (error) + log_error("can't register kobj %d", error); + kobject_uevent(&ls->kobj, KOBJ_ADD); + + return error; +} + +void gdlm_kobject_release(struct gdlm_ls *ls) +{ + kobject_put(&ls->kobj); +} + +int gdlm_sysfs_init(void) +{ + gdlm_kset = kset_create_and_add("lock_dlm_gfs", NULL, kernel_kobj); + if (!gdlm_kset) { + printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__); + return -ENOMEM; + } + return 0; +} + +void gdlm_sysfs_exit(void) +{ + kset_unregister(gdlm_kset); +} + --- linux-2.6.27.orig/ubuntu/gfs/ops_vm.h +++ linux-2.6.27/ubuntu/gfs/ops_vm.h @@ -0,0 +1,7 @@ +#ifndef __OPS_VM_DOT_H__ +#define __OPS_VM_DOT_H__ + +extern struct vm_operations_struct gfs_vm_ops_private; +extern struct vm_operations_struct gfs_vm_ops_sharewrite; + +#endif /* __OPS_VM_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/unlinked.h +++ linux-2.6.27/ubuntu/gfs/unlinked.h @@ -0,0 +1,19 @@ +#ifndef __UNLINKED_DOT_H__ +#define __UNLINKED_DOT_H__ + +struct gfs_unlinked *gfs_unlinked_get(struct gfs_sbd *sdp, + struct gfs_inum *inum, int create); +void gfs_unlinked_hold(struct gfs_sbd *sdp, struct gfs_unlinked *ul); +void gfs_unlinked_put(struct gfs_sbd *sdp, struct gfs_unlinked *ul); + +void gfs_unlinked_lock(struct gfs_sbd *sdp, struct gfs_unlinked *ul); +void gfs_unlinked_unlock(struct gfs_sbd *sdp, struct gfs_unlinked *ul); + +void gfs_unlinked_merge(struct gfs_sbd *sdp, unsigned int type, + struct gfs_inum *inum); +void gfs_unlinked_cleanup(struct gfs_sbd *sdp); + +void gfs_unlinked_limit(struct gfs_sbd *sdp); +void gfs_unlinked_dealloc(struct gfs_sbd *sdp); + +#endif /* __UNLINKED_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/daemon.h +++ linux-2.6.27/ubuntu/gfs/daemon.h @@ -0,0 +1,11 @@ +#ifndef __DAEMON_DOT_H__ +#define __DAEMON_DOT_H__ + +int gfs_scand(void *data); +int gfs_glockd(void *data); +int gfs_recoverd(void *data); +int gfs_logd(void *data); +int gfs_quotad(void *data); +int gfs_inoded(void *data); + +#endif /* __DAEMON_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/glops.c +++ linux-2.6.27/ubuntu/gfs/glops.c @@ -0,0 +1,664 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "log.h" +#include "page.h" +#include "recovery.h" +#include "rgrp.h" + +/** + * meta_go_sync - sync out the metadata for this glock + * @gl: the glock + * @flags: DIO_* + * + * Used for meta and rgrp glocks. + * + * Called when demoting (gfs_glock_xmote_th()) or unlocking + * (gfs_glock_drop_th() an EX glock at inter-node scope. We must flush + * to disk all dirty buffers/pages relating to this glock, and must not + * not return to caller to demote/unlock the glock until I/O is complete. + * + * This is *not* called from gfs_glock_dq(), because GL_SYNC flag is not + * currently used for anything but inode glocks. + */ + +static void +meta_go_sync(struct gfs_glock *gl, int flags) +{ + if (!(flags & DIO_METADATA)) + return; + + if (test_bit(GLF_DIRTY, &gl->gl_flags)) { + gfs_log_flush_glock(gl); + gfs_sync_buf(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK); + } + + /* We've synced everything, clear SYNC request and DIRTY flags */ + clear_bit(GLF_DIRTY, &gl->gl_flags); + clear_bit(GLF_SYNC, &gl->gl_flags); +} + +/** + * meta_go_inval - invalidate the metadata for this glock + * @gl: the glock + * @flags: + * + */ + +static void +meta_go_inval(struct gfs_glock *gl, int flags) +{ + if (!(flags & DIO_METADATA)) + return; + + gfs_inval_buf(gl); + gl->gl_vn++; +} + +/** + * meta_go_demote_ok - Check to see if it's ok to unlock a meta glock + * @gl: the glock + * + * Returns: TRUE if we have no cached data; ok to demote meta glock + * + * Called when trying to dump (reclaim) a glock from the glock cache, after + * determining that there is currently no holder on this node for this glock, + * and before placing LM_ST_UNLOCKED request on glock's wait-for-demote queue. + * Note that callbacks from other nodes that need a lock do *not* + * seek permission from this function before requesting a demote. + * Nor do glocks obtained with the following flags (see demote_ok()): + * -- GL_NOCACHE: gets unlocked (and not cached) immediately after use + * -- GLF_STICKY: equivalent to always getting "FALSE" from this function + * -- GLF_PREFETCH: uses its own timeout + * + * For glocks that protect on-disk data (meta, inode, and rgrp glocks), disk + * accesses are slow, while lock manipulation is usually fast. Releasing + * a lock means that we: + * -- Must sync memory-cached write data to disk immediately, before another + * node can be granted the lock (at which point that node must read the + * data from disk). + * -- Must invalidate memory-cached data that we had read from or written + * to disk. Another node can change it if we don't have a lock, so it's + * now useless to us. + * + * Then, if we re-acquire the lock again in the future, we: + * -- Must (re-)read (perhaps unchanged) data from disk into memory. + * + * All of these are painful, so it pays to retain a glock in our glock cache + * as long as we have cached data (even though we have no active holders + * for this lock on this node currently), unless/until another node needs + * to change it. This allows Linux block I/O to sync write data to disk in + * a "lazy" way, rather than forcing an immediate sync (and resultant WAIT), + * and retains current data in memory as long as possible. + * + * This also helps GFS respond to memory pressure. There is no mechanism for + * the Linux virtual memory manager to directly call into GFS to ask it to + * drop locks. So, we take a hint from what the VM does to the page cache. + * When that cache is trimmed (and we see no more pages relating to this + * glock), we trim the glock cache as well, by releasing this lock. + */ + +static int +meta_go_demote_ok(struct gfs_glock *gl) +{ + return (gl->gl_aspace->i_mapping->nrpages) ? FALSE : TRUE; +} + +/** + * inode_go_xmote_th - promote/demote (but don't unlock) an inode glock + * @gl: the glock + * @state: the requested state + * @flags: the flags passed into gfs_glock() + * + * Acquire a new glock, or change an already-acquired glock to + * more/less restrictive state (other than LM_ST_UNLOCKED). + */ + +static void +inode_go_xmote_th(struct gfs_glock *gl, unsigned int state, int flags) +{ + if (gl->gl_state != LM_ST_UNLOCKED) + gfs_inval_pte(gl); + gfs_glock_xmote_th(gl, state, flags); +} + +/** + * inode_go_xmote_bh - After promoting/demoting (but not unlocking) + * an inode glock + * @gl: the glock + * + * FIXME: This will be really broken when (no_formal_ino != no_addr) + * and gl_name.ln_number no longer refers to the dinode block #. + * + * If we've just acquired the inter-node lock for an inode, + * read the dinode block from disk (but don't wait for I/O completion). + * Exceptions (don't read if): + * Glock state is UNLOCKED. + * Glock's requesting holder's GL_SKIP flag is set. + */ + +static void +inode_go_xmote_bh(struct gfs_glock *gl) +{ + struct gfs_holder *gh = gl->gl_req_gh; + struct buffer_head *bh; + int error; + + if (gl->gl_state != LM_ST_UNLOCKED && + (!gh || !(gh->gh_flags & GL_SKIP))) { + error = gfs_dread(gl, gl->gl_name.ln_number, DIO_START, &bh); + if (!error) + brelse(bh); + } +} + +/** + * inode_go_drop_th - unlock an inode glock + * @gl: the glock + * + * Invoked from rq_demote(). + * Another node needs the lock in EXCLUSIVE mode, or lock (unused for too long) + * is being purged from our node's glock cache; we're dropping lock. + */ + +static void +inode_go_drop_th(struct gfs_glock *gl) +{ + gfs_inval_pte(gl); + gfs_glock_drop_th(gl); +} + +/** + * inode_go_sync - Sync the dirty data and/or metadata for an inode glock + * @gl: the glock protecting the inode + * @flags: DIO_METADATA -- sync inode's metadata + * DIO_DATA -- sync inode's data + * DIO_INVISIBLE -- don't clear glock's DIRTY flag when done + * + * If DIO_INVISIBLE: + * 1) Called from gfs_glock_dq(), when releasing the last holder for an EX + * glock (but glock is still in our glock cache in EX state, and might + * stay there for a few minutes). Holder had GL_SYNC flag set, asking + * for early sync (i.e. now, instead of later when we release the EX at + * inter-node scope). GL_SYNC is currently used only for inodes in + * special cases, so inode is the only type of glock for which + * DIO_INVISIBLE would apply. + * 2) Called from depend_sync_one() to sync deallocated inode metadata + * before it can be reallocated by another process or machine. Since + * this call can happen at any time during the lifetime of the + * glock, don't clear the sync bit (more data might be dirtied + * momentarily). + * Else (later): + * Called when demoting (gfs_glock_xmote_th()) or unlocking + * (gfs_glock_drop_th() an EX glock at inter-node scope. We must flush + * to disk all dirty buffers/pages relating to this glock, and must not + * return to caller to demote/unlock the glock until I/O is complete. + * + * Syncs go in following order: + * Start data page writes + * Sync metadata to log (wait to complete I/O) + * Sync metadata to in-place location (wait to complete I/O) + * Wait for data page I/O to complete + * + */ + +static void +inode_go_sync(struct gfs_glock *gl, int flags) +{ + int meta = (flags & DIO_METADATA); + int data = (flags & DIO_DATA); + + if (test_bit(GLF_DIRTY, &gl->gl_flags)) { + if (meta && data) { + gfs_sync_page(gl, flags | DIO_START); + gfs_log_flush_glock(gl); + gfs_sync_buf(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK); + gfs_sync_page(gl, flags | DIO_WAIT | DIO_CHECK); + } else if (meta) { + gfs_log_flush_glock(gl); + gfs_sync_buf(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK); + } else if (data) + gfs_sync_page(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK); + } + + /* If we've synced everything, clear the SYNC request. + If we're doing the final (not early) sync, clear DIRTY */ + if (meta && data) { + if (!(flags & DIO_INVISIBLE)) + clear_bit(GLF_DIRTY, &gl->gl_flags); + clear_bit(GLF_SYNC, &gl->gl_flags); + } +} + +/** + * inode_go_inval - prepare a inode glock to be released + * @gl: the glock + * @flags: + * + */ + +static void +inode_go_inval(struct gfs_glock *gl, int flags) +{ + int meta = (flags & DIO_METADATA); + int data = (flags & DIO_DATA); + + if (meta) { + gfs_inval_buf(gl); + gl->gl_vn++; + } + if (data) + gfs_inval_page(gl); +} + +/** + * inode_go_demote_ok - Check to see if it's ok to unlock an inode glock + * @gl: the glock + * + * See comments for meta_go_demote_ok(). + * + * While other glock types (meta, rgrp) that protect disk data can be retained + * indefinitely, GFS imposes a timeout (overridden when using no_lock lock + * module) for inode glocks, even if there is still data in page cache for + * this inode. + * + * Returns: TRUE if it's ok + */ + +static int +inode_go_demote_ok(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + int demote = FALSE; + + if (!get_gl2ip(gl) && !gl->gl_aspace->i_mapping->nrpages) + demote = TRUE; + else if (!sdp->sd_args.ar_localcaching && + time_after_eq(jiffies, gl->gl_stamp + gfs_tune_get(sdp, gt_demote_secs) * HZ)) + demote = TRUE; + + return demote; +} + +/** + * inode_go_lock - operation done after an inode lock is locked by + * a first holder on this node + * @gl: the glock + * @flags: the flags passed into gfs_glock() + * + * Returns: errno + */ + +static int +inode_go_lock(struct gfs_glock *gl, int flags) +{ + struct gfs_inode *ip = get_gl2ip(gl); + int error = 0; + + if (ip && ip->i_vn != gl->gl_vn) { + error = gfs_copyin_dinode(ip); + if (!error) + gfs_inode_attr_in(ip); + } + + return error; +} + +/** + * inode_go_unlock - operation done when an inode lock is unlocked by + * a last holder on this node + * @gl: the glock + * @flags: the flags passed into gfs_gunlock() + * + */ + +static void +inode_go_unlock(struct gfs_glock *gl, int flags) +{ + struct gfs_inode *ip = get_gl2ip(gl); + + if (ip && test_bit(GLF_DIRTY, &gl->gl_flags)) + gfs_inode_attr_in(ip); + + if (ip) + gfs_flush_meta_cache(ip); +} + +/** + * inode_greedy - + * @gl: the glock + * + */ + +static void +inode_greedy(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_inode *ip = get_gl2ip(gl); + unsigned int quantum = gfs_tune_get(sdp, gt_greedy_quantum); + unsigned int max = gfs_tune_get(sdp, gt_greedy_max); + unsigned int new_time; + + spin_lock(&ip->i_spin); + + if (time_after(ip->i_last_pfault + quantum, jiffies)) { + new_time = ip->i_greedy + quantum; + if (new_time > max) + new_time = max; + } else { + new_time = ip->i_greedy - quantum; + if (!new_time || new_time > max) + new_time = 1; + } + + ip->i_greedy = new_time; + + spin_unlock(&ip->i_spin); + + gfs_inode_put(ip); +} + +/** + * rgrp_go_xmote_th - promote/demote (but don't unlock) a resource group glock + * @gl: the glock + * @state: the requested state + * @flags: the flags passed into gfs_glock() + * + * Acquire a new glock, or change an already-acquired glock to + * more/less restrictive state (other than LM_ST_UNLOCKED). + * + * We're going to lock the lock in SHARED or EXCLUSIVE state, or + * demote it from EXCLUSIVE to SHARED (because another node needs it SHARED). + * When locking, gfs_mhc_zap() and gfs_depend_sync() are basically no-ops; + * meta-header cache and dependency lists should be empty. + * + */ + +static void +rgrp_go_xmote_th(struct gfs_glock *gl, unsigned int state, int flags) +{ + struct gfs_rgrpd *rgd = get_gl2rgd(gl); + + gfs_mhc_zap(rgd); + gfs_depend_sync(rgd); + gfs_glock_xmote_th(gl, state, flags); +} + +/** + * rgrp_go_drop_th - unlock a resource group glock + * @gl: the glock + * + * Invoked from rq_demote(). + * Another node needs the lock in EXCLUSIVE mode, or lock (unused for too long) + * is being purged from our node's glock cache; we're dropping lock. + */ + +static void +rgrp_go_drop_th(struct gfs_glock *gl) +{ + struct gfs_rgrpd *rgd = get_gl2rgd(gl); + + gfs_mhc_zap(rgd); + gfs_depend_sync(rgd); + gfs_glock_drop_th(gl); +} + +/** + * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock + * @gl: the glock + * + * See comments for meta_go_demote_ok(). + * + * In addition to Linux page cache, we also check GFS meta-header-cache. + * + * Returns: TRUE if it's ok + */ + +static int +rgrp_go_demote_ok(struct gfs_glock *gl) +{ + struct gfs_rgrpd *rgd = get_gl2rgd(gl); + int demote = TRUE; + + if (gl->gl_aspace->i_mapping->nrpages) + demote = FALSE; + else if (rgd && !list_empty(&rgd->rd_mhc)) /* Don't bother with lock here */ + demote = FALSE; + + return demote; +} + +/** + * rgrp_go_lock - operation done after an rgrp lock is locked by + * a first holder on this node. + * @gl: the glock + * @flags: the flags passed into gfs_glock() + * + * Returns: errno + * + * Read rgrp's header and block allocation bitmaps from disk. + */ + +static int +rgrp_go_lock(struct gfs_glock *gl, int flags) +{ + if (flags & GL_SKIP) + return 0; + return gfs_rgrp_read(get_gl2rgd(gl)); +} + +/** + * rgrp_go_unlock - operation done when an rgrp lock is unlocked by + * a last holder on this node. + * @gl: the glock + * @flags: the flags passed into gfs_gunlock() + * + * Release rgrp's bitmap buffers (read in when lock was first obtained). + * Make sure rgrp's glock's Lock Value Block has up-to-date block usage stats, + * so other nodes can see them. + */ + +static void +rgrp_go_unlock(struct gfs_glock *gl, int flags) +{ + struct gfs_rgrpd *rgd = get_gl2rgd(gl); + if (flags & GL_SKIP) + return; + gfs_rgrp_relse(rgd); + if (test_bit(GLF_DIRTY, &gl->gl_flags)) + gfs_rgrp_lvb_fill(rgd); +} + +/** + * trans_go_xmote_th - promote/demote (but don't unlock) the transaction glock + * @gl: the glock + * @state: the requested state + * @flags: the flags passed into gfs_glock() + * + * Acquire a new glock, or change an already-acquired glock to + * more/less restrictive state (other than LM_ST_UNLOCKED). + */ + +static void +trans_go_xmote_th(struct gfs_glock *gl, unsigned int state, int flags) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + + if (gl->gl_state != LM_ST_UNLOCKED && + test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { + gfs_sync_meta(sdp); + gfs_log_shutdown(sdp); + } + + gfs_glock_xmote_th(gl, state, flags); +} + +/** + * trans_go_xmote_bh - After promoting/demoting (but not unlocking) + * the transaction glock + * @gl: the glock + * + */ + +static void +trans_go_xmote_bh(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock *j_gl = sdp->sd_journal_gh.gh_gl; + struct gfs_log_header head; + int error; + + if (gl->gl_state != LM_ST_UNLOCKED && + test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { + j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA); + + error = gfs_find_jhead(sdp, &sdp->sd_jdesc, j_gl, &head); + if (error) + gfs_consist(sdp); + if (!(head.lh_flags & GFS_LOG_HEAD_UNMOUNT)) + gfs_consist(sdp); + + /* Initialize some head of the log stuff */ + if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) { + sdp->sd_sequence = head.lh_sequence; + sdp->sd_log_head = head.lh_first + 1; + } + } +} + +/** + * trans_go_drop_th - unlock the transaction glock + * @gl: the glock + * + * Invoked from rq_demote(). + * Another node needs the lock in EXCLUSIVE mode to quiesce the filesystem + * (for journal replay, etc.). + * + * We want to sync the device even with localcaching. Remember + * that localcaching journal replay only marks buffers dirty. + */ + +static void +trans_go_drop_th(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + + if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { + gfs_sync_meta(sdp); + gfs_log_shutdown(sdp); + } + + gfs_glock_drop_th(gl); +} + +/** + * nondisk_go_demote_ok - Check to see if it's ok to unlock a non-disk glock + * @gl: the glock + * + * See comments for meta_go_demote_ok(). + * + * We never give up a non-disk glock (unless another node needs it). + * Non-disk type used for GFS_MOUNT_LOCK, GFS_LIVE_LOCK, GFS_RENAME_LOCK. + * GFS_MOUNT_LOCK is always requested GL_NOCACHE, however, so it never uses + * this function. + * + * Returns: TRUE if it's ok + */ + +static int +nondisk_go_demote_ok(struct gfs_glock *gl) +{ + return FALSE; +} + +/** + * quota_go_demote_ok - Check to see if it's ok to unlock a quota glock + * @gl: the glock + * + * See comments for meta_go_demote_ok(). + * + * Returns: TRUE if it's ok + */ + +static int +quota_go_demote_ok(struct gfs_glock *gl) +{ + return !atomic_read(&gl->gl_lvb_count); +} + +struct gfs_glock_operations gfs_meta_glops = { + .go_xmote_th = gfs_glock_xmote_th, + .go_drop_th = gfs_glock_drop_th, + .go_sync = meta_go_sync, + .go_inval = meta_go_inval, + .go_demote_ok = meta_go_demote_ok, + .go_type = LM_TYPE_META +}; + +struct gfs_glock_operations gfs_inode_glops = { + .go_xmote_th = inode_go_xmote_th, + .go_xmote_bh = inode_go_xmote_bh, + .go_drop_th = inode_go_drop_th, + .go_sync = inode_go_sync, + .go_inval = inode_go_inval, + .go_demote_ok = inode_go_demote_ok, + .go_lock = inode_go_lock, + .go_unlock = inode_go_unlock, + .go_greedy = inode_greedy, + .go_type = LM_TYPE_INODE +}; + +struct gfs_glock_operations gfs_rgrp_glops = { + .go_xmote_th = rgrp_go_xmote_th, + .go_drop_th = rgrp_go_drop_th, + .go_sync = meta_go_sync, + .go_inval = meta_go_inval, + .go_demote_ok = rgrp_go_demote_ok, + .go_lock = rgrp_go_lock, + .go_unlock = rgrp_go_unlock, + .go_type = LM_TYPE_RGRP +}; + +struct gfs_glock_operations gfs_trans_glops = { + .go_xmote_th = trans_go_xmote_th, + .go_xmote_bh = trans_go_xmote_bh, + .go_drop_th = trans_go_drop_th, + .go_type = LM_TYPE_NONDISK +}; + +struct gfs_glock_operations gfs_iopen_glops = { + .go_xmote_th = gfs_glock_xmote_th, + .go_drop_th = gfs_glock_drop_th, + .go_callback = gfs_iopen_go_callback, + .go_type = LM_TYPE_IOPEN +}; + +struct gfs_glock_operations gfs_flock_glops = { + .go_xmote_th = gfs_glock_xmote_th, + .go_drop_th = gfs_glock_drop_th, + .go_type = LM_TYPE_FLOCK +}; + +struct gfs_glock_operations gfs_nondisk_glops = { + .go_xmote_th = gfs_glock_xmote_th, + .go_drop_th = gfs_glock_drop_th, + .go_demote_ok = nondisk_go_demote_ok, + .go_type = LM_TYPE_NONDISK +}; + +struct gfs_glock_operations gfs_quota_glops = { + .go_xmote_th = gfs_glock_xmote_th, + .go_drop_th = gfs_glock_drop_th, + .go_demote_ok = quota_go_demote_ok, + .go_type = LM_TYPE_QUOTA +}; --- linux-2.6.27.orig/ubuntu/gfs/ops_file.c +++ linux-2.6.27/ubuntu/gfs/ops_file.c @@ -0,0 +1,1820 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs_ioctl.h" +#include "gfs.h" +#include "bmap.h" +#include "dio.h" +#include "dir.h" +#include "file.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "ioctl.h" +#include "lm.h" +#include "log.h" +#include "ops_file.h" +#include "ops_vm.h" +#include "quota.h" +#include "rgrp.h" +#include "trans.h" + +/* "bad" is for NFS support */ +struct filldir_bad_entry { + char *fbe_name; + unsigned int fbe_length; + uint64_t fbe_offset; + struct gfs_inum fbe_inum; + unsigned int fbe_type; +}; + +struct filldir_bad { + struct gfs_sbd *fdb_sbd; + + struct filldir_bad_entry *fdb_entry; + unsigned int fdb_entry_num; + unsigned int fdb_entry_off; + + char *fdb_name; + unsigned int fdb_name_size; + unsigned int fdb_name_off; +}; + +/* For regular, non-NFS */ +struct filldir_reg { + struct gfs_sbd *fdr_sbd; + int fdr_prefetch; + + filldir_t fdr_filldir; + void *fdr_opaque; +}; + +typedef ssize_t(*do_rw_t) (struct file * file, + char *buf, + size_t size, loff_t * offset, + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder * ghs); + +/** + * gfs_llseek - seek to a location in a file + * @file: the file + * @offset: the offset + * @origin: Where to seek from (SEEK_SET, SEEK_CUR, or SEEK_END) + * + * SEEK_END requires the glock for the file because it references the + * file's size. + * + * Returns: The new offset, or errno + */ + +static loff_t +gfs_llseek(struct file *file, loff_t offset, int origin) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + struct gfs_holder i_gh; + loff_t error; + + atomic_inc(&ip->i_sbd->sd_ops_file); + + if (origin == 2) { + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + if (!error) { + error = generic_file_llseek_unlocked(file, offset, origin); + gfs_glock_dq_uninit(&i_gh); + } + } else + error = generic_file_llseek_unlocked(file, offset, origin); + + return error; +} + +#define vma2state(vma) \ +((((vma)->vm_flags & (VM_MAYWRITE | VM_MAYSHARE)) == \ + (VM_MAYWRITE | VM_MAYSHARE)) ? \ + LM_ST_EXCLUSIVE : LM_ST_SHARED) \ + +/** + * functionname - summary + * @param1: description + * @param2: description + * @param3: description + * + * Function description + * + * Returns: what is returned + */ + +static ssize_t +walk_vm_hard(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, do_rw_t operation) +{ + struct gfs_holder *ghs; + unsigned int num_gh = 0; + ssize_t count; + + { + struct super_block *sb = file->f_dentry->d_inode->i_sb; + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long start = (unsigned long)buf; + unsigned long end = start + size; + int dumping = (current->flags & PF_DUMPCORE); + unsigned int x = 0; + + for (vma = find_vma(mm, start); vma; vma = vma->vm_next) { + if (end <= vma->vm_start) + break; + if (vma->vm_file && + vma->vm_file->f_dentry->d_inode->i_sb == sb) { + num_gh++; + } + } + + ghs = kmalloc((num_gh + 1) * sizeof(struct gfs_holder), GFP_KERNEL); + if (!ghs) { + if (!dumping) + up_read(&mm->mmap_sem); + return -ENOMEM; + } + + for (vma = find_vma(mm, start); vma; vma = vma->vm_next) { + if (end <= vma->vm_start) + break; + if (vma->vm_file) { + struct inode *inode = vma->vm_file->f_dentry->d_inode; + if (inode->i_sb == sb) + gfs_holder_init(get_v2ip(inode)->i_gl, + vma2state(vma), + 0, &ghs[x++]); + } + } + + if (!dumping) + up_read(&mm->mmap_sem); + + gfs_assert(get_v2sdp(sb), x == num_gh,); + } + + count = operation(file, buf, size, offset, iocb, num_gh, ghs); + + while (num_gh--) + gfs_holder_uninit(&ghs[num_gh]); + kfree(ghs); + + return count; +} + +/** + * walk_vm - Walk the vmas associated with a buffer for read or write. + * If any of them are gfs, pass the gfs inode down to the read/write + * worker function so that locks can be acquired in the correct order. + * @file: The file to read/write from/to + * @buf: The buffer to copy to/from + * @size: The amount of data requested + * @offset: The current file offset + * @operation: The read or write worker function + * + * Outputs: Offset - updated according to number of bytes written + * + * Returns: The number of bytes written, errno on failure + */ + +static ssize_t +walk_vm(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, + do_rw_t operation) +{ + if (current->mm) { + struct super_block *sb = file->f_dentry->d_inode->i_sb; + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long start = (unsigned long)buf; + unsigned long end = start + size; + int dumping = (current->flags & PF_DUMPCORE); + + if (!dumping) + down_read(&mm->mmap_sem); + + for (vma = find_vma(mm, start); vma; vma = vma->vm_next) { + if (end <= vma->vm_start) + break; + if (vma->vm_file && + vma->vm_file->f_dentry->d_inode->i_sb == sb) + goto do_locks; + } + + if (!dumping) + up_read(&mm->mmap_sem); + } + + { + struct gfs_holder gh; + return operation(file, buf, size, offset, iocb, 0, &gh); + } + + do_locks: + return walk_vm_hard(file, buf, size, offset, iocb, operation); +} + +/** + * functionname - summary + * @param1: description + * @param2: description + * @param3: description + * + * Function description + * + * Returns: what is returned + */ + +static ssize_t +do_read_readi(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + ssize_t count = 0; + + if (*offset < 0) + return -EINVAL; + if (!access_ok(VERIFY_WRITE, buf, size)) + return -EFAULT; + + if (!(file->f_flags & O_LARGEFILE)) { + if (*offset >= 0x7FFFFFFFull) + return -EFBIG; + if (*offset + size > 0x7FFFFFFFull) + size = 0x7FFFFFFFull - *offset; + } + + /* ToDo: not sure about iocb .. wcheng + */ + count = gfs_readi(ip, buf, *offset, size, gfs_copy2user); + + if (count > 0) + *offset += count; + + return count; +} + +/** + * do_read_direct - Read bytes from a file + * @file: The file to read from + * @buf: The buffer to copy into + * @size: The amount of data requested + * @offset: The current file offset + * @num_gh: The number of other locks we need to do the read + * @ghs: the locks we need plus one for our lock + * + * Outputs: Offset - updated according to number of bytes read + * + * Returns: The number of bytes read, errno on failure + */ + +static ssize_t +do_read_direct(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder *ghs) +{ + struct inode *inode = file->f_mapping->host; + struct gfs_inode *ip = get_v2ip(inode); + unsigned int state = LM_ST_DEFERRED; + int flags = 0; + unsigned int x; + ssize_t count = 0; + int error; + + for (x = 0; x < num_gh; x++) + if (ghs[x].gh_gl == ip->i_gl) { + state = LM_ST_SHARED; + flags |= GL_LOCAL_EXCL; + break; + } + + gfs_holder_init(ip->i_gl, state, flags, &ghs[num_gh]); + + error = gfs_glock_nq_m(num_gh + 1, ghs); + if (error) + goto out; + + error = -EINVAL; + if (gfs_is_jdata(ip)) + goto out_gunlock; + + if (gfs_is_stuffed(ip)) { + size_t mask = bdev_hardsect_size(inode->i_sb->s_bdev) - 1; + + if (((*offset) & mask) || (((unsigned long)buf) & mask)) + goto out_gunlock; + + count = do_read_readi(file, buf, size & ~mask, offset, iocb); + } + else { + if (!iocb) + count = do_sync_read(file, buf, size, offset); + else { + struct iovec local_iov = { .iov_base = buf, .iov_len = size}; + + count = generic_file_aio_read(iocb, &local_iov, 1, *offset); + iocb->ki_pos = *offset; + } + } + + error = 0; + + out_gunlock: + gfs_glock_dq_m(num_gh + 1, ghs); + + out: + gfs_holder_uninit(&ghs[num_gh]); + + return (count) ? count : error; +} + +/** + * do_read_buf - Read bytes from a file + * @file: The file to read from + * @buf: The buffer to copy into + * @size: The amount of data requested + * @offset: The current file offset + * @num_gh: The number of other locks we need to do the read + * @ghs: the locks we need plus one for our lock + * + * Outputs: Offset - updated according to number of bytes read + * + * Returns: The number of bytes read, errno on failure + */ + +static ssize_t +do_read_buf(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder *ghs) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + ssize_t count = 0; + int error; + + gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &ghs[num_gh]); + + error = gfs_glock_nq_m_atime(num_gh + 1, ghs); + if (error) + goto out; + + if (gfs_is_jdata(ip) || + (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags))) + count = do_read_readi(file, buf, size, offset, iocb); + else { + if (!iocb) { + count = do_sync_read(file, buf, size, offset); + } else { + struct iovec local_iov = { .iov_base = buf, .iov_len = size}; + + count = generic_file_aio_read(iocb, &local_iov, 1, *offset); + iocb->ki_pos = *offset; + } + } + + gfs_glock_dq_m(num_gh + 1, ghs); + + out: + gfs_holder_uninit(&ghs[num_gh]); + + return (count) ? count : error; +} + +static ssize_t +__gfs_read(struct file *file, char *buf, size_t size, loff_t *offset, struct kiocb *iocb) +{ + atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file); + + if (file->f_flags & O_DIRECT) + return walk_vm(file, buf, size, offset, iocb, do_read_direct); + else + return walk_vm(file, buf, size, offset, iocb, do_read_buf); +} + +/** + * gfs_read - Read bytes from a file + * @file: The file to read from + * @buf: The buffer to copy into + * @size: The amount of data requested + * @offset: The current file offset + * + * Outputs: Offset - updated according to number of bytes read + * + * Returns: The number of bytes read, errno on failure + */ + +static ssize_t +gfs_read(struct file *file, char *buf, size_t size, loff_t *offset) +{ + return(__gfs_read(file, buf, size, offset, NULL)); +} + +/* + * gfs_aio_read: match with vfs generic_file_aio_read as: + * (struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) + */ +static ssize_t +gfs_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long count, + loff_t pos) +{ + struct file *filp = iocb->ki_filp; + + BUG_ON(iocb->ki_pos != pos); + return(__gfs_read(filp, iov->iov_base, iov->iov_len, &iocb->ki_pos, iocb)); +} + +/** + * grope_mapping - feel up a mapping that needs to be written + * @buf: the start of the memory to be written + * @size: the size of the memory to be written + * + * We do this after acquiring the locks on the mapping, + * but before starting the write transaction. We need to make + * sure that we don't cause recursive transactions if blocks + * need to be allocated to the file backing the mapping. + * + * Returns: errno + */ + +static int +grope_mapping(char *buf, size_t size) +{ + unsigned long start = (unsigned long)buf; + unsigned long stop = start + size; + char c; + + while (start < stop) { + if (copy_from_user(&c, (char *)start, 1)) + return -EFAULT; + + start += PAGE_CACHE_SIZE; + start &= PAGE_CACHE_MASK; + } + + return 0; +} + +/** + * gfs_file_aio_write_nolock - Call vfs aio layer to write bytes to a file + * @file: The file to write to + * @buf: The buffer to copy from + * @size: The amount of data requested + * @offset: The offset in the file to write + * @iocb: The io control block. If NULL, a temporary one will be used. + * + * Returns: The number of bytes written, errno on failure + */ +static ssize_t +gfs_file_aio_write_nolock(struct file *file, char *buf, size_t size, + loff_t *offset, struct kiocb *iocb) +{ + struct iovec local_iov = { .iov_base = buf, .iov_len = size }; + struct kiocb local_iocb, *kiocb = NULL; + ssize_t count; + + if (!iocb) { + init_sync_kiocb(&local_iocb, file); + local_iocb.ki_nr_segs = 1; + kiocb = &local_iocb; + } + else + kiocb = iocb; + + kiocb->ki_pos = *offset; + count = generic_file_aio_write_nolock(kiocb, &local_iov, kiocb->ki_nr_segs, + kiocb->ki_pos); + *offset = kiocb->ki_pos; + if (kiocb == &local_iocb && count == -EIOCBQUEUED) + count = wait_on_sync_kiocb(kiocb); + return count; +} + +/** + * do_write_direct_alloc - Write bytes to a file + * @file: The file to write to + * @buf: The buffer to copy from + * @size: The amount of data requested + * @offset: The current file offset + * + * Outputs: Offset - updated according to number of bytes written + * + * Returns: The number of bytes written, errno on failure + */ + +static ssize_t +do_write_direct_alloc(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb) +{ + struct inode *inode = file->f_mapping->host; + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = NULL; + struct buffer_head *dibh; + unsigned int data_blocks, ind_blocks; + ssize_t count; + int error; + + gfs_write_calc_reserv(ip, size, &data_blocks, &ind_blocks); + + al = gfs_alloc_get(ip); + + error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto fail; + + error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + if (error) + goto fail_gunlock_q; + + al->al_requested_meta = ind_blocks; + al->al_requested_data = data_blocks; + + error = gfs_inplace_reserve(ip); + if (error) + goto fail_gunlock_q; + + /* Trans may require: + All blocks for a RG bitmap, whatever indirect blocks we + need, a modified dinode, and a quota change. */ + + error = gfs_trans_begin(sdp, + 1 + al->al_rgd->rd_ri.ri_length + ind_blocks, + 1); + if (error) + goto fail_ipres; + + if ((ip->i_di.di_mode & (S_ISUID | S_ISGID)) && !capable(CAP_FSETID)) { + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto fail_end_trans; + + ip->i_di.di_mode &= (ip->i_di.di_mode & S_IXGRP) ? (~(S_ISUID | S_ISGID)) : (~S_ISUID); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + if (gfs_is_stuffed(ip)) { error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL); if (error) + goto fail_end_trans; + } + + count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb); + if (count < 0) { + error = count; + goto fail_end_trans; + } + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto fail_end_trans; + + if (ip->i_di.di_size < inode->i_size) + ip->i_di.di_size = inode->i_size; + ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + + gfs_trans_end(sdp); + + /* Question (wcheng) + * 1. should IS_SYNC flush glock ? + * 2. does gfs_log_flush_glock flush data ? + */ + if (file->f_flags & O_SYNC) + gfs_log_flush_glock(ip->i_gl); + + gfs_inplace_release(ip); + gfs_quota_unlock_m(ip); + gfs_alloc_put(ip); + + if (file->f_mapping->nrpages) { + error = filemap_fdatawrite(file->f_mapping); + if (!error) + error = filemap_fdatawait(file->f_mapping); + } + if (error) + return error; + + return count; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_ipres: + gfs_inplace_release(ip); + + fail_gunlock_q: + gfs_quota_unlock_m(ip); + + fail: + gfs_alloc_put(ip); + + return error; +} + +/** + * do_write_direct - Write bytes to a file + * @file: The file to write to + * @buf: The buffer to copy from + * @size: The amount of data requested + * @offset: The current file offset + * @num_gh: The number of other locks we need to do the read + * @gh: the locks we need plus one for our lock + * + * Outputs: Offset - updated according to number of bytes written + * + * Returns: The number of bytes written, errno on failure + */ + +static ssize_t +do_write_direct(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder *ghs) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_file *fp = get_v2fp(file); + unsigned int state = LM_ST_DEFERRED; + int alloc_required; + unsigned int x; + size_t s; + ssize_t count = 0; + int error; + + if (test_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags)) + state = LM_ST_EXCLUSIVE; + else + for (x = 0; x < num_gh; x++) + if (ghs[x].gh_gl == ip->i_gl) { + state = LM_ST_EXCLUSIVE; + break; + } + + restart: + gfs_holder_init(ip->i_gl, state, 0, &ghs[num_gh]); + + error = gfs_glock_nq_m(num_gh + 1, ghs); + if (error) + goto out; + + error = -EINVAL; + if (gfs_is_jdata(ip)) + goto out_gunlock; + + if (num_gh) { + error = grope_mapping(buf, size); + if (error) + goto out_gunlock; + } + + if (file->f_flags & O_APPEND) + *offset = ip->i_di.di_size; + + if (!(file->f_flags & O_LARGEFILE)) { + error = -EFBIG; + if (*offset >= 0x7FFFFFFFull) + goto out_gunlock; + if (*offset + size > 0x7FFFFFFFull) + size = 0x7FFFFFFFull - *offset; + } + + if (gfs_is_stuffed(ip) || + *offset + size > ip->i_di.di_size || + ((ip->i_di.di_mode & (S_ISUID | S_ISGID)) && !capable(CAP_FSETID))) + alloc_required = TRUE; + else { + error = gfs_write_alloc_required(ip, *offset, size, + &alloc_required); + if (error) + goto out_gunlock; + } + + if (alloc_required && state != LM_ST_EXCLUSIVE) { + gfs_glock_dq_m(num_gh + 1, ghs); + gfs_holder_uninit(&ghs[num_gh]); + state = LM_ST_EXCLUSIVE; + goto restart; + } + + if (alloc_required) { + set_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags); + + /* for asynchronous IO, the buffer can not be splitted */ + if (iocb) { + count = do_write_direct_alloc(file, buf, size, offset, iocb); + goto out_iocb_write; + } + + /* split large writes into smaller atomic transactions */ + while (size) { + s = gfs_tune_get(sdp, gt_max_atomic_write); + if (s > size) + s = size; + + error = do_write_direct_alloc(file, buf, s, offset, iocb); + if (error < 0) + goto out_gunlock; + + buf += error; + size -= error; + count += error; + } + } else { + struct gfs_holder t_gh; + + clear_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags); + + error = gfs_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &t_gh); + if (error) + goto out_gunlock; + + /* Todo: It would be nice if init_sync_kiocb is exported. + * .. wcheng + */ + count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb); + gfs_glock_dq_uninit(&t_gh); + } + +out_iocb_write: + error = 0; + +out_gunlock: + gfs_glock_dq_m(num_gh + 1, ghs); + +out: + gfs_holder_uninit(&ghs[num_gh]); + + return (count) ? count : error; +} + +/** + * do_do_write_buf - Write bytes to a file + * @file: The file to write to + * @buf: The buffer to copy from + * @size: The amount of data requested + * @offset: The current file offset + * + * Outputs: Offset - updated according to number of bytes written + * + * Returns: The number of bytes written, errno on failure + */ + +static ssize_t +do_do_write_buf(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb) +{ + struct inode *inode = file->f_mapping->host; + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = NULL; + struct buffer_head *dibh; + unsigned int data_blocks, ind_blocks; + int alloc_required, journaled; + ssize_t count; + int error; + + journaled = gfs_is_jdata(ip); + + gfs_write_calc_reserv(ip, size, &data_blocks, &ind_blocks); + + error = gfs_write_alloc_required(ip, *offset, size, &alloc_required); + if (error) + return error; + + if (alloc_required) { + al = gfs_alloc_get(ip); + + error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto fail; + + error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + if (error) + goto fail_gunlock_q; + + if (journaled) + al->al_requested_meta = ind_blocks + data_blocks; + else { + al->al_requested_meta = ind_blocks; + al->al_requested_data = data_blocks; + } + + error = gfs_inplace_reserve(ip); + if (error) + goto fail_gunlock_q; + + /* Trans may require: + All blocks for a RG bitmap, whatever indirect blocks we + need, a modified dinode, and a quota change. */ + + error = gfs_trans_begin(sdp, + 1 + al->al_rgd->rd_ri.ri_length + + ind_blocks + + ((journaled) ? data_blocks : 0), 1); + if (error) + goto fail_ipres; + } else { + /* Trans may require: + A modified dinode. */ + + error = gfs_trans_begin(sdp, + 1 + ((journaled) ? data_blocks : 0), 0); + if (error) + goto fail_ipres; + } + + if ((ip->i_di.di_mode & (S_ISUID | S_ISGID)) && !capable(CAP_FSETID)) { + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto fail_end_trans; + + ip->i_di.di_mode &= (ip->i_di.di_mode & S_IXGRP) ? (~(S_ISUID | S_ISGID)) : (~S_ISUID); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + if (journaled || + (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags) && + *offset + size <= sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode))) { + + count = gfs_writei(ip, buf, *offset, size, gfs_copy_from_user, iocb); + if (count < 0) { + error = count; + goto fail_end_trans; + } + if (gfs_is_stuffed(ip)){ + struct page *page; + page = find_get_page(file->f_mapping, 0); + if (page) { + ClearPageUptodate(page); + page_cache_release(page); + } + } + *offset += count; + } else { + count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb); + if (count < 0) { + error = count; + goto fail_end_trans; + } + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto fail_end_trans; + + if (ip->i_di.di_size < inode->i_size) + ip->i_di.di_size = inode->i_size; + ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + gfs_trans_end(sdp); + + if (file->f_flags & O_SYNC || IS_SYNC(inode)) { + gfs_log_flush_glock(ip->i_gl); + error = filemap_fdatawrite(file->f_mapping); + if (error == 0) + error = filemap_fdatawait(file->f_mapping); + if (error) + goto fail_ipres; + } + + if (alloc_required) { + gfs_assert_warn(sdp, count != size || + al->al_alloced_meta || + al->al_alloced_data); + gfs_inplace_release(ip); + gfs_quota_unlock_m(ip); + gfs_alloc_put(ip); + } + + return count; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_ipres: + if (alloc_required) + gfs_inplace_release(ip); + + fail_gunlock_q: + if (alloc_required) + gfs_quota_unlock_m(ip); + + fail: + if (alloc_required) + gfs_alloc_put(ip); + + return error; +} + +/** + * do_write_buf - Write bytes to a file + * @file: The file to write to + * @buf: The buffer to copy from + * @size: The amount of data requested + * @offset: The current file offset + * @num_gh: The number of other locks we need to do the read + * @gh: the locks we need plus one for our lock + * + * Outputs: Offset - updated according to number of bytes written + * + * Returns: The number of bytes written, errno on failure + */ + +static ssize_t +do_write_buf(struct file *file, + char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder *ghs) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + struct gfs_sbd *sdp = ip->i_sbd; + size_t s; + ssize_t count = 0; + int error; + + gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[num_gh]); + + error = gfs_glock_nq_m(num_gh + 1, ghs); + if (error) + goto out; + + if (num_gh) { + error = grope_mapping(buf, size); + if (error) + goto out_gunlock; + } + + if (file->f_flags & O_APPEND) + *offset = ip->i_di.di_size; + + if (!(file->f_flags & O_LARGEFILE)) { + error = -EFBIG; + if (*offset >= 0x7FFFFFFFull) + goto out_gunlock; + if (*offset + size > 0x7FFFFFFFull) + size = 0x7FFFFFFFull - *offset; + } + + /* split large writes into smaller atomic transactions */ + while (size) { + s = gfs_tune_get(sdp, gt_max_atomic_write); + if (s > size) + s = size; + + error = do_do_write_buf(file, buf, s, offset, iocb); + if (error < 0) + goto out_gunlock; + + buf += error; + size -= error; + count += error; + } + + error = 0; + + out_gunlock: + gfs_glock_dq_m(num_gh + 1, ghs); + + out: + gfs_holder_uninit(&ghs[num_gh]); + + return (count) ? count : error; +} + +/** + * gfs_write - Write bytes to a file + * @file: The file to write to + * @buf: The buffer to copy from + * @size: The amount of data requested + * @offset: The current file offset + * + * Outputs: Offset - updated according to number of bytes written + * + * Returns: The number of bytes written, errno on failure + */ + +static ssize_t +__gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset, struct kiocb *iocb) +{ + struct inode *inode = file->f_mapping->host; + ssize_t count; + + atomic_inc(&get_v2sdp(inode->i_sb)->sd_ops_file); + + if (*offset < 0) + return -EINVAL; + if (!access_ok(VERIFY_READ, buf, size)) + return -EFAULT; + + mutex_lock(&inode->i_mutex); + if (file->f_flags & O_DIRECT) + count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_direct); + else + count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_buf); + mutex_unlock(&inode->i_mutex); + + return count; +} + +static ssize_t +gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset) +{ + return(__gfs_write(file, buf, size, offset, NULL)); +} + +static ssize_t +gfs_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long segs, + loff_t pos) +{ + struct file *file = iocb->ki_filp; + + BUG_ON(iocb->ki_pos != pos); + + return(__gfs_write(file, iov->iov_base, iov->iov_len, &iocb->ki_pos, + iocb)); +} + +/** + * filldir_reg_func - Report a directory entry to the caller of gfs_dir_read() + * @opaque: opaque data used by the function + * @name: the name of the directory entry + * @length: the length of the name + * @offset: the entry's offset in the directory + * @inum: the inode number the entry points to + * @type: the type of inode the entry points to + * + * Returns: 0 on success, 1 if buffer full + */ + +static int +filldir_reg_func(void *opaque, + const char *name, unsigned int length, + uint64_t offset, + struct gfs_inum *inum, unsigned int type) +{ + struct filldir_reg *fdr = (struct filldir_reg *)opaque; + struct gfs_sbd *sdp = fdr->fdr_sbd; + unsigned int vfs_type; + int error; + + switch (type) { + case GFS_FILE_NON: + vfs_type = DT_UNKNOWN; + break; + case GFS_FILE_REG: + vfs_type = DT_REG; + break; + case GFS_FILE_DIR: + vfs_type = DT_DIR; + break; + case GFS_FILE_LNK: + vfs_type = DT_LNK; + break; + case GFS_FILE_BLK: + vfs_type = DT_BLK; + break; + case GFS_FILE_CHR: + vfs_type = DT_CHR; + break; + case GFS_FILE_FIFO: + vfs_type = DT_FIFO; + break; + case GFS_FILE_SOCK: + vfs_type = DT_SOCK; + break; + default: + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: type = %u\n", + sdp->sd_fsname, type); + return -EIO; + } + + error = fdr->fdr_filldir(fdr->fdr_opaque, name, length, offset, + inum->no_formal_ino, vfs_type); + if (error) + return 1; + + /* Prefetch locks */ + if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) { + gfs_glock_prefetch_num(sdp, + inum->no_formal_ino, &gfs_inode_glops, + LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); + gfs_glock_prefetch_num(sdp, + inum->no_addr, &gfs_iopen_glops, + LM_ST_SHARED, LM_FLAG_TRY); + } + + return 0; +} + +/** + * readdir_reg - Read directory entries from a directory + * @file: The directory to read from + * @dirent: Buffer for dirents + * @filldir: Function used to do the copying + * + * Returns: errno + */ + +static int +readdir_reg(struct file *file, void *dirent, filldir_t filldir) +{ + struct gfs_inode *dip = get_v2ip(file->f_mapping->host); + struct filldir_reg fdr; + struct gfs_holder d_gh; + uint64_t offset = file->f_pos; + int error; + + fdr.fdr_sbd = dip->i_sbd; + fdr.fdr_prefetch = TRUE; + fdr.fdr_filldir = filldir; + fdr.fdr_opaque = dirent; + + gfs_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh); + error = gfs_glock_nq_atime(&d_gh); + if (error) { + gfs_holder_uninit(&d_gh); + return error; + } + + error = gfs_dir_read(dip, &offset, &fdr, filldir_reg_func); + + gfs_glock_dq_uninit(&d_gh); + + file->f_pos = offset; + + return error; +} + +/** + * filldir_bad_func - Report a directory entry to the caller of gfs_dir_read() + * @opaque: opaque data used by the function + * @name: the name of the directory entry + * @length: the length of the name + * @offset: the entry's offset in the directory + * @inum: the inode number the entry points to + * @type: the type of inode the entry points to + * + * For supporting NFS. + * + * Returns: 0 on success, 1 if buffer full + */ + +static int +filldir_bad_func(void *opaque, + const char *name, unsigned int length, + uint64_t offset, + struct gfs_inum *inum, unsigned int type) +{ + struct filldir_bad *fdb = (struct filldir_bad *)opaque; + struct gfs_sbd *sdp = fdb->fdb_sbd; + struct filldir_bad_entry *fbe; + + if (fdb->fdb_entry_off == fdb->fdb_entry_num || + fdb->fdb_name_off + length > fdb->fdb_name_size) + return 1; + + fbe = &fdb->fdb_entry[fdb->fdb_entry_off]; + fbe->fbe_name = fdb->fdb_name + fdb->fdb_name_off; + memcpy(fbe->fbe_name, name, length); + fbe->fbe_length = length; + fbe->fbe_offset = offset; + fbe->fbe_inum = *inum; + fbe->fbe_type = type; + + fdb->fdb_entry_off++; + fdb->fdb_name_off += length; + + /* Prefetch locks */ + if (!(length == 1 && *name == '.')) { + gfs_glock_prefetch_num(sdp, + inum->no_formal_ino, &gfs_inode_glops, + LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); + gfs_glock_prefetch_num(sdp, + inum->no_addr, &gfs_iopen_glops, + LM_ST_SHARED, LM_FLAG_TRY); + } + + return 0; +} + +/** + * readdir_bad - Read directory entries from a directory + * @file: The directory to read from + * @dirent: Buffer for dirents + * @filldir: Function used to do the copying + * + * For supporting NFS. + * + * Returns: errno + */ + +static int +readdir_bad(struct file *file, void *dirent, filldir_t filldir) +{ + struct gfs_inode *dip = get_v2ip(file->f_mapping->host); + struct gfs_sbd *sdp = dip->i_sbd; + struct filldir_reg fdr; + unsigned int entries, size; + struct filldir_bad *fdb; + struct gfs_holder d_gh; + uint64_t offset = file->f_pos; + unsigned int x; + struct filldir_bad_entry *fbe; + int error; + + entries = gfs_tune_get(sdp, gt_entries_per_readdir); + size = sizeof(struct filldir_bad) + + entries * (sizeof(struct filldir_bad_entry) + GFS_FAST_NAME_SIZE); + + fdb = kmalloc(size, GFP_KERNEL); + if (!fdb) + return -ENOMEM; + memset(fdb, 0, size); + + fdb->fdb_sbd = sdp; + fdb->fdb_entry = (struct filldir_bad_entry *)(fdb + 1); + fdb->fdb_entry_num = entries; + fdb->fdb_name = ((char *)fdb) + sizeof(struct filldir_bad) + + entries * sizeof(struct filldir_bad_entry); + fdb->fdb_name_size = entries * GFS_FAST_NAME_SIZE; + + gfs_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh); + error = gfs_glock_nq_atime(&d_gh); + if (error) { + gfs_holder_uninit(&d_gh); + goto out; + } + + error = gfs_dir_read(dip, &offset, fdb, filldir_bad_func); + + gfs_glock_dq_uninit(&d_gh); + + fdr.fdr_sbd = sdp; + fdr.fdr_prefetch = FALSE; + fdr.fdr_filldir = filldir; + fdr.fdr_opaque = dirent; + + for (x = 0; x < fdb->fdb_entry_off; x++) { + fbe = &fdb->fdb_entry[x]; + + error = filldir_reg_func(&fdr, + fbe->fbe_name, fbe->fbe_length, + fbe->fbe_offset, + &fbe->fbe_inum, fbe->fbe_type); + if (error) { + file->f_pos = fbe->fbe_offset; + error = 0; + goto out; + } + } + + file->f_pos = offset; + + out: + kfree(fdb); + + return error; +} + +/** + * gfs_readdir - Read directory entries from a directory + * @file: The directory to read from + * @dirent: Buffer for dirents + * @filldir: Function used to do the copying + * + * Returns: errno + */ + +static int +gfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + int error; + + atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file); + + /* Use "bad" one if we're called from NFS daemon */ + if (strcmp(current->comm, "nfsd") != 0) + error = readdir_reg(file, dirent, filldir); + else + error = readdir_bad(file, dirent, filldir); + + return error; +} + +/** + * gfs_ioctl - do an ioctl on a file + * @inode: the inode + * @file: the file pointer + * @cmd: the ioctl command + * @arg: the argument + * + * Returns: errno + */ + +static int +gfs_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct gfs_inode *ip = get_v2ip(inode); + + atomic_inc(&ip->i_sbd->sd_ops_file); + + switch (cmd) { + case GFS_IOCTL_IDENTIFY: { + unsigned int x = GFS_MAGIC; + if (copy_to_user((unsigned int *)arg, &x, sizeof(unsigned int))) + return -EFAULT; + return 0; + } + + case GFS_IOCTL_SUPER: + return gfs_ioctl_i(ip, (void *)arg); + + default: + return -ENOTTY; + } +} + +#ifdef CONFIG_COMPAT +/** + * gfs_compat_ioctl - do an ioctl on a file - compatible between 32-64 bit + * @inode: the inode + * @file: the file pointer + * @cmd: the ioctl command + * @arg: the argument + * + * Returns: errno + */ + +static long +gfs_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + + atomic_inc(&ip->i_sbd->sd_ops_file); + + switch (cmd) { + case GFS_IOCTL_IDENTIFY: { + unsigned int x = GFS_MAGIC; + if (copy_to_user((unsigned int *)arg, &x, sizeof(unsigned int))) + return -EFAULT; + return 0; + } + + case GFS_IOCTL_SUPER: + return gfs_ioctl_i_compat(ip, arg); + + default: + return -ENOTTY; + } +} +#endif + +/** + * gfs_mmap - We don't support shared writable mappings right now + * @file: The file to map + * @vma: The VMA which described the mapping + * + * Returns: 0 or error code + */ + +static int +gfs_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + struct gfs_holder i_gh; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_file); + + gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh); + error = gfs_glock_nq_atime(&i_gh); + if (error) { + gfs_holder_uninit(&i_gh); + return error; + } + + if (gfs_is_jdata(ip)) { + if (vma->vm_flags & VM_MAYSHARE) + error = -ENOSYS; + else + vma->vm_ops = &gfs_vm_ops_private; + } else { + /* This is VM_MAYWRITE instead of VM_WRITE because a call + to mprotect() can turn on VM_WRITE later. */ + + if ((vma->vm_flags & (VM_MAYSHARE | VM_MAYWRITE)) == (VM_MAYSHARE | VM_MAYWRITE)) + vma->vm_ops = &gfs_vm_ops_sharewrite; + else + vma->vm_ops = &gfs_vm_ops_private; + } + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_open - open a file + * @inode: the inode to open + * @file: the struct file for this opening + * + * Returns: errno + */ + +static int +gfs_open(struct inode *inode, struct file *file) +{ + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_holder i_gh; + struct gfs_file *fp; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_file); + + fp = kmalloc(sizeof(struct gfs_file), GFP_KERNEL); + if (!fp) + return -ENOMEM; + memset(fp, 0, sizeof(struct gfs_file)); + + init_MUTEX(&fp->f_fl_lock); + + fp->f_inode = ip; + fp->f_vfile = file; + + gfs_assert_warn(ip->i_sbd, !get_v2fp(file)); + set_v2fp(file, fp); + + if (ip->i_di.di_type == GFS_FILE_REG) { + error = gfs_glock_nq_init(ip->i_gl, + LM_ST_SHARED, LM_FLAG_ANY, + &i_gh); + if (error) + goto fail; + + if (!(file->f_flags & O_LARGEFILE) && + ip->i_di.di_size > 0x7FFFFFFFull) { + error = -EFBIG; + goto fail_gunlock; + } + + /* Listen to the Direct I/O flag */ + + if (ip->i_di.di_flags & GFS_DIF_DIRECTIO) + file->f_flags |= O_DIRECT; + + /* Don't let the user open O_DIRECT on a jdata file */ + + if ((file->f_flags & O_DIRECT) && gfs_is_jdata(ip)) { + error = -EINVAL; + goto fail_gunlock; + } + + gfs_glock_dq_uninit(&i_gh); + } + + return 0; + + fail_gunlock: + gfs_glock_dq_uninit(&i_gh); + + fail: + set_v2fp(file, NULL); + kfree(fp); + + return error; +} + +/** + * gfs_close - called to close a struct file + * @inode: the inode the struct file belongs to + * @file: the struct file being closed + * + * Returns: errno + */ + +static int +gfs_close(struct inode *inode, struct file *file) +{ + struct gfs_sbd *sdp = get_v2sdp(inode->i_sb); + struct gfs_file *fp; + + atomic_inc(&sdp->sd_ops_file); + + fp = get_v2fp(file); + set_v2fp(file, NULL); + + if (!gfs_assert_warn(sdp, fp)) + kfree(fp); + + return 0; +} + +/** + * gfs_fsync - sync the dirty data for a file (across the cluster) + * @file: the file that points to the dentry (we ignore this) + * @dentry: the dentry that points to the inode to sync + * + * Returns: errno + * + * Obtain a SHARED lock on the file, to force any node with an EXCLUSIVE lock + * to sync file's dirty data to disk, as it releases the EXCLUSIVE lock. + */ + +static int +gfs_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + struct gfs_inode *ip = get_v2ip(dentry->d_inode); + struct gfs_holder i_gh; + struct inode *inode = dentry->d_inode; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_file); + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + if (error) + return error; + + if (gfs_is_jdata(ip)) + gfs_log_flush_glock(ip->i_gl); + else { + if ((!datasync) || (inode->i_state & I_DIRTY_DATASYNC)) { + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = 0, + }; + error = sync_inode(inode, &wbc); + } + } + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_lock - acquire/release a posix lock on a file + * @file: the file pointer + * @cmd: either modify or retrieve lock state, possibly wait + * @fl: type and range of lock + * + * Returns: errno + */ + +static int +gfs_lock(struct file *file, int cmd, struct file_lock *fl) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + struct gfs_sbd *sdp = ip->i_sbd; + struct lm_lockname name = + { .ln_number = ip->i_num.no_formal_ino, + .ln_type = LM_TYPE_PLOCK }; + + atomic_inc(&sdp->sd_ops_file); + + if (!(fl->fl_flags & FL_POSIX)) + return -ENOLCK; + if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + return -ENOLCK; + + if (IS_GETLK(cmd)) + return gfs_lm_plock_get(sdp, &name, file, fl); + else if (fl->fl_type == F_UNLCK) + return gfs_lm_punlock(sdp, &name, file, fl); + else + return gfs_lm_plock(sdp, &name, file, cmd, fl); +} + +/** + * gfs_splice_read - Send bytes to a file or socket + * @in_file: The file to read from + * @out_file: The file to write to + * @count: The amount of data + * @ppos: The beginning file offset + * + * Outputs: offset - updated according to number of bytes read + * + * Returns: The number of bytes sent, errno on failure + */ + +static ssize_t +gfs_splice_read(struct file *in_file, loff_t *ppos, struct pipe_inode_info *pipe, size_t count, unsigned int flags) +{ + struct gfs_inode *ip = get_v2ip(in_file->f_mapping->host); + struct gfs_holder gh; + ssize_t retval; + + atomic_inc(&ip->i_sbd->sd_ops_file); + + gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); + + retval = gfs_glock_nq_atime(&gh); + if (retval) + goto out; + + if (gfs_is_jdata(ip)) + retval = -ENOSYS; + else + retval = generic_file_splice_read(in_file, ppos, pipe, count, flags); + + gfs_glock_dq(&gh); + + out: + gfs_holder_uninit(&gh); + + return retval; +} + +/** + * do_flock - Acquire a flock on a file + * @file: + * @cmd: + * @fl: + * + * Returns: errno + */ + +static int +do_flock(struct file *file, int cmd, struct file_lock *fl) +{ + struct gfs_file *fp = get_v2fp(file); + struct gfs_holder *fl_gh = &fp->f_fl_gh; + struct gfs_inode *ip = fp->f_inode; + struct gfs_glock *gl; + unsigned int state; + int flags; + int error = 0; + + state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED; + flags = ((IS_SETLKW(cmd)) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE; + + down(&fp->f_fl_lock); + + gl = fl_gh->gh_gl; + if (gl) { + if (fl_gh->gh_state == state) + goto out; + gfs_glock_hold(gl); + flock_lock_file_wait(file, + &(struct file_lock){.fl_type = F_UNLCK}); + gfs_glock_dq_uninit(fl_gh); + } else { + error = gfs_glock_get(ip->i_sbd, + ip->i_num.no_formal_ino, &gfs_flock_glops, + CREATE, &gl); + if (error) + goto out; + } + + gfs_holder_init(gl, state, flags, fl_gh); + gfs_glock_put(gl); + + error = gfs_glock_nq(fl_gh); + if (error) { + gfs_holder_uninit(fl_gh); + if (error == GLR_TRYFAILED) + error = -EAGAIN; + } else { + error = flock_lock_file_wait(file, fl); + gfs_assert_warn(ip->i_sbd, !error); + } + + out: + up(&fp->f_fl_lock); + + return error; +} + +/** + * do_unflock - Release a flock on a file + * @file: the file + * @fl: + * + */ + +static void +do_unflock(struct file *file, struct file_lock *fl) +{ + struct gfs_file *fp = get_v2fp(file); + struct gfs_holder *fl_gh = &fp->f_fl_gh; + + down(&fp->f_fl_lock); + flock_lock_file_wait(file, fl); + if (fl_gh->gh_gl) + gfs_glock_dq_uninit(fl_gh); + up(&fp->f_fl_lock); +} + +/** + * gfs_flock - acquire/release a flock lock on a file + * @file: the file pointer + * @cmd: either modify or retrieve lock state, possibly wait + * @fl: type and range of lock + * + * Returns: errno + */ + +static int +gfs_flock(struct file *file, int cmd, struct file_lock *fl) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + + atomic_inc(&ip->i_sbd->sd_ops_file); + + if (!(fl->fl_flags & FL_FLOCK)) + return -ENOLCK; + if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + return -ENOLCK; + + if (fl->fl_type == F_UNLCK) { + do_unflock(file, fl); + return 0; + } else + return do_flock(file, cmd, fl); +} + +struct file_operations gfs_file_fops = { + .llseek = gfs_llseek, + .read = gfs_read, + .write = gfs_write, + .aio_read = gfs_aio_read, + .aio_write = gfs_aio_write, + .ioctl = gfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gfs_compat_ioctl, +#endif + .mmap = gfs_mmap, + .open = gfs_open, + .release = gfs_close, + .fsync = gfs_fsync, + .lock = gfs_lock, + .splice_read = gfs_splice_read, + .flock = gfs_flock, +}; + +struct file_operations gfs_dir_fops = { + .readdir = gfs_readdir, + .ioctl = gfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gfs_compat_ioctl, +#endif + .open = gfs_open, + .release = gfs_close, + .fsync = gfs_fsync, + .lock = gfs_lock, + .flock = gfs_flock, +}; + +struct file_operations gfs_file_fops_nolock = { + .llseek = gfs_llseek, + .read = gfs_read, + .write = gfs_write, + .aio_read = gfs_aio_read, + .aio_write = gfs_aio_write, + .ioctl = gfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gfs_compat_ioctl, +#endif + .mmap = gfs_mmap, + .open = gfs_open, + .release = gfs_close, + .fsync = gfs_fsync, + .splice_read = gfs_splice_read, +}; + +struct file_operations gfs_dir_fops_nolock = { + .readdir = gfs_readdir, + .ioctl = gfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gfs_compat_ioctl, +#endif + .open = gfs_open, + .release = gfs_close, + .fsync = gfs_fsync, +}; --- linux-2.6.27.orig/ubuntu/gfs/inode.h +++ linux-2.6.27/ubuntu/gfs/inode.h @@ -0,0 +1,57 @@ +#ifndef __INODE_DOT_H__ +#define __INODE_DOT_H__ + +void gfs_inode_attr_in(struct gfs_inode *ip); +void gfs_inode_attr_out(struct gfs_inode *ip); +struct inode *gfs_iget(struct gfs_inode *ip, int create); + +int gfs_copyin_dinode(struct gfs_inode *ip); + +int gfs_inode_get(struct gfs_glock *i_gl, struct gfs_inum *inum, int create, + struct gfs_inode **ipp); +void gfs_inode_hold(struct gfs_inode *ip); +void gfs_inode_put(struct gfs_inode *ip); +void gfs_inode_destroy(struct gfs_inode *ip); + +int gfs_inode_dealloc(struct gfs_sbd *sdp, struct gfs_inum *inum); + +int gfs_change_nlink(struct gfs_inode *ip, int diff); +int gfs_lookupi(struct gfs_holder *d_gh, struct qstr *name, + int is_root, struct gfs_holder *i_gh); +int gfs_createi(struct gfs_holder *d_gh, struct qstr *name, + unsigned int type, unsigned int mode, + struct gfs_holder *i_gh); +int gfs_unlinki(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip); +int gfs_rmdiri(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip); +int gfs_unlink_ok(struct gfs_inode *dip, struct qstr *name, + struct gfs_inode *ip); +int gfs_ok_to_move(struct gfs_inode *this, struct gfs_inode *to); +int gfs_readlinki(struct gfs_inode *ip, char **buf, unsigned int *len); + +int gfs_glock_nq_atime(struct gfs_holder *gh); +int gfs_glock_nq_m_atime(unsigned int num_gh, struct gfs_holder *ghs); + +void gfs_try_toss_vnode(struct gfs_inode *ip); + +int gfs_setattr_simple(struct gfs_inode *ip, struct iattr *attr); + +/* Backwards compatibility functions */ + +int gfs_alloc_qinode(struct gfs_sbd *sdp); +int gfs_alloc_linode(struct gfs_sbd *sdp); + +/* Inlines */ + +static __inline__ int +gfs_is_stuffed(struct gfs_inode *ip) +{ + return !ip->i_di.di_height; +} + +static __inline__ int +gfs_is_jdata(struct gfs_inode *ip) +{ + return ip->i_di.di_flags & GFS_DIF_JDATA; +} + +#endif /* __INODE_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/bits.h +++ linux-2.6.27/ubuntu/gfs/bits.h @@ -0,0 +1,18 @@ +#ifndef __BITS_DOT_H__ +#define __BITS_DOT_H__ + +#define BFITNOENT (0xFFFFFFFF) + +void gfs_setbit(struct gfs_rgrpd *rgd, + unsigned char *buffer, unsigned int buflen, + uint32_t block, unsigned char new_state); +unsigned char gfs_testbit(struct gfs_rgrpd *rgd, + unsigned char *buffer, unsigned int buflen, + uint32_t block); +uint32_t gfs_bitfit(unsigned char *buffer, unsigned int buflen, + uint32_t goal, unsigned char old_state); +uint32_t gfs_bitcount(struct gfs_rgrpd *rgd, + unsigned char *buffer, unsigned int buflen, + unsigned char state); + +#endif /* __BITS_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/log.h +++ linux-2.6.27/ubuntu/gfs/log.h @@ -0,0 +1,66 @@ +#ifndef __LOG_DOT_H__ +#define __LOG_DOT_H__ + +/** + * gfs_log_lock - acquire the right to mess with the log manager + * @sdp: the filesystem + * + */ + +static __inline__ void +gfs_log_lock(struct gfs_sbd *sdp) +{ + down_write(&sdp->sd_log_lock); +} + +/** + * gfs_log_unlock - release the right to mess with the log manager + * @sdp: the filesystem + * + */ + +static __inline__ void +gfs_log_unlock(struct gfs_sbd *sdp) +{ + up_write(&sdp->sd_log_lock); +} + +unsigned int gfs_struct2blk(struct gfs_sbd *sdp, unsigned int nstruct, + unsigned int ssize); +unsigned int gfs_blk2seg(struct gfs_sbd *sdp, unsigned int blocks); + +int gfs_log_reserve(struct gfs_sbd *sdp, unsigned int segments, int jump_queue); +void gfs_log_release(struct gfs_sbd *sdp, unsigned int segments); + +void gfs_ail_start(struct gfs_sbd *sdp, int flags); +int gfs_ail_empty(struct gfs_sbd *sdp); + +void gfs_log_commit(struct gfs_sbd *sdp, struct gfs_trans *trans); +void gfs_log_flush(struct gfs_sbd *sdp); +void gfs_log_flush_glock(struct gfs_glock *gl); + +void gfs_log_shutdown(struct gfs_sbd *sdp); + +void gfs_log_dump(struct gfs_sbd *sdp, int force); + +/* Internal crap used the log operations */ + +/** + * gfs_log_is_header - Discover if block is on journal header + * @sdp: The GFS superblock + * @block: The block number + * + * Returns: TRUE if the block is on a journal segment boundary, FALSE otherwise + */ + +static __inline__ int +gfs_log_is_header(struct gfs_sbd *sdp, uint64_t block) +{ + return !do_mod(block, sdp->sd_sb.sb_seg_size); +} + +struct gfs_log_buf *gfs_log_get_buf(struct gfs_sbd *sdp, struct gfs_trans *tr); +void gfs_log_fake_buf(struct gfs_sbd *sdp, struct gfs_trans *tr, char *data, + struct buffer_head *unlock); + +#endif /* __LOG_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/util.c +++ linux-2.6.27/ubuntu/gfs/util.c @@ -0,0 +1,571 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "glock.h" +#include "lm.h" + +uint32_t gfs_random_number; + +struct kmem_cache *gfs_glock_cachep = NULL; +struct kmem_cache *gfs_inode_cachep = NULL; +struct kmem_cache *gfs_bufdata_cachep = NULL; +struct kmem_cache *gfs_mhc_cachep = NULL; + +/** + * gfs_random - Generate a random 32-bit number + * + * Generate a semi-crappy 32-bit pseudo-random number without using + * floating point. + * + * The PRNG is from "Numerical Recipes in C" (second edition), page 284. + * + * Returns: a 32-bit random number + */ + +uint32_t +gfs_random(void) +{ + gfs_random_number = 0x0019660D * gfs_random_number + 0x3C6EF35F; + return gfs_random_number; +} + +/** + * hash_more_internal - hash an array of data + * @data: the data to be hashed + * @len: the length of data to be hashed + * @hash: the hash from a previous call + * + * Take some data and convert it to a 32-bit hash. + * + * This is the 32-bit FNV-1a hash from: + * http://www.isthe.com/chongo/tech/comp/fnv/ + * + * Hash guts + * + * Returns: the hash + */ + +static __inline__ uint32_t +hash_more_internal(const void *data, unsigned int len, uint32_t hash) +{ + unsigned char *p = (unsigned char *)data; + unsigned char *e = p + len; + uint32_t h = hash; + + while (p < e) { + h ^= (uint32_t)(*p++); + h *= 0x01000193; + } + + return h; +} + +/** + * gfs_hash - hash an array of data + * @data: the data to be hashed + * @len: the length of data to be hashed + * + * Take some data and convert it to a 32-bit hash. + * + * This is the 32-bit FNV-1a hash from: + * http://www.isthe.com/chongo/tech/comp/fnv/ + * + * Returns: the hash + */ + +uint32_t +gfs_hash(const void *data, unsigned int len) +{ + uint32_t h = 0x811C9DC5; + h = hash_more_internal(data, len, h); + return h; +} + +/** + * gfs_hash_more - hash an array of data + * @data: the data to be hashed + * @len: the length of data to be hashed + * @hash: the hash from a previous call + * + * Take some data and convert it to a 32-bit hash. + * + * This is the 32-bit FNV-1a hash from: + * http://www.isthe.com/chongo/tech/comp/fnv/ + * + * This version let's you hash together discontinuous regions. + * For example, to compute the combined hash of the memory in + * (data1, len1), (data2, len2), and (data3, len3) you: + * + * h = gfs_hash(data1, len1); + * h = gfs_hash_more(data2, len2, h); + * h = gfs_hash_more(data3, len3, h); + * + * Returns: the hash + */ + +uint32_t +gfs_hash_more(const void *data, unsigned int len, uint32_t hash) +{ + uint32_t h; + h = hash_more_internal(data, len, hash); + return h; +} + +/* Byte-wise swap two items of size SIZE. */ + +#define SWAP(a, b, size) \ +do { \ + register size_t __size = (size); \ + register char *__a = (a), *__b = (b); \ + do { \ + char __tmp = *__a; \ + *__a++ = *__b; \ + *__b++ = __tmp; \ + } while (__size-- > 1); \ +} while (0) + +/** + * gfs_sort - Sort base array using shell sort algorithm + * @base: the input array + * @num_elem: number of elements in array + * @size: size of each element in array + * @compar: fxn to compare array elements (returns negative + * for lt, 0 for eq, and positive for gt + * + * Sorts the array passed in using the compar fxn to compare elements using + * the shell sort algorithm + */ + +void +gfs_sort(void *base, unsigned int num_elem, unsigned int size, + int (*compar) (const void *, const void *)) +{ + register char *pbase = (char *)base; + int i, j, k, h; + static int cols[16] = {1391376, 463792, 198768, 86961, + 33936, 13776, 4592, 1968, + 861, 336, 112, 48, + 21, 7, 3, 1}; + + for (k = 0; k < 16; k++) { + h = cols[k]; + for (i = h; i < num_elem; i++) { + j = i; + while (j >= h && + (*compar)((void *)(pbase + size * (j - h)), + (void *)(pbase + size * j)) > 0) { + SWAP(pbase + size * j, + pbase + size * (j - h), + size); + j = j - h; + } + } + } +} + +/** + * gfs_assert_i - Cause the machine to panic if @assertion is false + * @sdp: + * @assertion: + * @function: + * @file: + * @line: + * + */ + +void +gfs_assert_i(struct gfs_sbd *sdp, + char *assertion, + const char *function, + char *file, unsigned int line) +{ + if (sdp->sd_args.ar_oopses_ok) { + printk("GFS: fsid=%s: assertion \"%s\" failed\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, assertion, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); + BUG(); + } + dump_stack(); + panic("GFS: fsid=%s: assertion \"%s\" failed\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, assertion, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); +} + +/** + * gfs_assert_withdraw_i - Cause the machine to withdraw if @assertion is false + * @sdp: + * @assertion: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * -2 if it was already withdrawn + */ + +int +gfs_assert_withdraw_i(struct gfs_sbd *sdp, + char *assertion, + const char *function, + char *file, unsigned int line) +{ + int me; + me = gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: assertion \"%s\" failed\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, assertion, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); + return (me) ? -1 : -2; +} + +/** + * gfs_assert_warn_i - Print a message to the console if @assertion is false + * @sdp: + * @assertion: + * @function: + * @file: + * @line: + * + * Returns: -1 if we printed something + * -2 if we didn't + */ + +int +gfs_assert_warn_i(struct gfs_sbd *sdp, + char *assertion, + const char *function, + char *file, unsigned int line) +{ + if (time_before(jiffies, + sdp->sd_last_warning + + gfs_tune_get(sdp, gt_complain_secs) * HZ)) + return -2; + + printk("GFS: fsid=%s: warning: assertion \"%s\" failed\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, assertion, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); + + sdp->sd_last_warning = jiffies; + if (sdp->sd_args.ar_debug) + BUG(); + + + return -1; +} + +/** + * gfs_consist_i - Flag a filesystem consistency error and withdraw + * @sdp: + * @cluster_wide: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int +gfs_consist_i(struct gfs_sbd *sdp, int cluster_wide, + const char *function, + char *file, unsigned int line) +{ + return gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: filesystem consistency error\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); +} + +/** + * gfs_consist_inode_i - Flag an inode consistency error and withdraw + * @ip: + * @cluster_wide: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int +gfs_consist_inode_i(struct gfs_inode *ip, int cluster_wide, + const char *function, + char *file, unsigned int line) +{ + struct gfs_sbd *sdp = ip->i_sbd; + return gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: filesystem consistency error\n" + "GFS: fsid=%s: inode = %"PRIu64"/%"PRIu64"\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, ip->i_num.no_formal_ino, ip->i_num.no_addr, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); +} + +/** + * gfs_consist_rgrpd_i - Flag a RG consistency error and withdraw + * @rgd: + * @cluster_wide: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int +gfs_consist_rgrpd_i(struct gfs_rgrpd *rgd, int cluster_wide, + const char *function, + char *file, unsigned int line) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + return gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: filesystem consistency error\n" + "GFS: fsid=%s: RG = %"PRIu64"\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, rgd->rd_ri.ri_addr, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); +} + +/** + * gfs_meta_check_ii - Flag a magic number consistency error and withdraw + * @sdp: + * @bh: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * -2 if it was already withdrawn + */ + +int +gfs_meta_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh, + const char *function, + char *file, unsigned int line) +{ + int me; + me = gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: invalid metadata block\n" + "GFS: fsid=%s: bh = %"PRIu64" (magic)\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, (uint64_t)bh->b_blocknr, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); + return (me) ? -1 : -2; +} + +/** + * gfs_metatype_check_ii - Flag a metadata type consistency error and withdraw + * @sdp: + * @bh: + * @type: + * @t: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * -2 if it was already withdrawn + */ + +int +gfs_metatype_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh, + uint32_t type, uint32_t t, + const char *function, + char *file, unsigned int line) +{ + int me; + me = gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: invalid metadata block\n" + "GFS: fsid=%s: bh = %"PRIu64" (type: exp=%u, found=%u)\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, (uint64_t)bh->b_blocknr, type, t, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); + return (me) ? -1 : -2; +} + +/** + * gfs_io_error_i - Flag an I/O error and withdraw + * @sdp: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int +gfs_io_error_i(struct gfs_sbd *sdp, + const char *function, + char *file, unsigned int line) +{ + return gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: I/O error\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); +} + +/** + * gfs_io_error_inode_i - Flag an inode I/O error and withdraw + * @ip: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int +gfs_io_error_inode_i(struct gfs_inode *ip, + const char *function, + char *file, unsigned int line) +{ + struct gfs_sbd *sdp = ip->i_sbd; + return gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: I/O error\n" + "GFS: fsid=%s: inode = %"PRIu64"/%"PRIu64"\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, ip->i_num.no_formal_ino, ip->i_num.no_addr, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); +} + +/** + * gfs_io_error_bh_i - Flag a buffer I/O error and withdraw + * @sdp: + * @bh: + * @function: + * @file: + * @line: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int +gfs_io_error_bh_i(struct gfs_sbd *sdp, struct buffer_head *bh, + const char *function, + char *file, unsigned int line) +{ + return gfs_lm_withdraw(sdp, + "GFS: fsid=%s: fatal: I/O error\n" + "GFS: fsid=%s: block = %"PRIu64"\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, + sdp->sd_fsname, (uint64_t)bh->b_blocknr, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); +} + +/** + * gmalloc - malloc a small amount of memory + * @size: the number of bytes to malloc + * + * Returns: the memory + */ + +void * +gmalloc(unsigned int size) +{ + void *p; + RETRY_MALLOC(p = kmalloc(size, GFP_KERNEL), p); + return p; +} + +/** + * gfs_add_bh_to_ub - copy a buffer up to user space + * @ub: the structure representing where to copy + * @bh: the buffer + * + * Returns: errno + */ + +int +gfs_add_bh_to_ub(struct gfs_user_buffer *ub, struct buffer_head *bh) +{ + uint64_t blkno = bh->b_blocknr; + + if (ub->ub_count + sizeof(uint64_t) + bh->b_size > ub->ub_size) + return -ENOMEM; + + if (copy_to_user(ub->ub_data + ub->ub_count, + &blkno, + sizeof(uint64_t))) + return -EFAULT; + ub->ub_count += sizeof(uint64_t); + + if (copy_to_user(ub->ub_data + ub->ub_count, + bh->b_data, + bh->b_size)) + return -EFAULT; + ub->ub_count += bh->b_size; + + return 0; +} + --- linux-2.6.27.orig/ubuntu/gfs/recovery.c +++ linux-2.6.27/ubuntu/gfs/recovery.c @@ -0,0 +1,780 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "glock.h" +#include "glops.h" +#include "lm.h" +#include "lops.h" +#include "recovery.h" + +#define bn2seg(bn) (((uint32_t)((bn) - jdesc->ji_addr)) / sdp->sd_sb.sb_seg_size) +#define seg2bn(seg) ((seg) * sdp->sd_sb.sb_seg_size + jdesc->ji_addr) + +struct dirty_j { + struct list_head dj_list; + unsigned int dj_jid; + struct gfs_jindex dj_desc; +}; + +/** + * gfs_add_dirty_j - add a jid to the list of dirty journals + * @sdp: the filesystem + * @jid: the journal ID number + * + */ + +void +gfs_add_dirty_j(struct gfs_sbd *sdp, unsigned int jid) +{ + struct dirty_j *dj; + + dj = gmalloc(sizeof(struct dirty_j)); + memset(dj, 0, sizeof(struct dirty_j)); + + dj->dj_jid = jid; + + spin_lock(&sdp->sd_dirty_j_lock); + list_add(&dj->dj_list, &sdp->sd_dirty_j); + spin_unlock(&sdp->sd_dirty_j_lock); +} + +/** + * get_dirty_j - return a dirty journal from the list + * @sdp: the filesystem + * + * Returns: a struct dirty_j or NULL + */ + +static struct dirty_j * +get_dirty_j(struct gfs_sbd *sdp) +{ + struct dirty_j *dj = NULL; + + spin_lock(&sdp->sd_dirty_j_lock); + if (!list_empty(&sdp->sd_dirty_j)) { + dj = list_entry(sdp->sd_dirty_j.prev, struct dirty_j, dj_list); + list_del(&dj->dj_list); + } + spin_unlock(&sdp->sd_dirty_j_lock); + + return dj; +} + +/** + * gfs_clear_dirty_j - destroy the list of dirty journals + * @sdp: the filesystem + * + */ + +void +gfs_clear_dirty_j(struct gfs_sbd *sdp) +{ + struct dirty_j *dj; + for (;;) { + dj = get_dirty_j(sdp); + if (!dj) + break; + kfree(dj); + } +} + +/** + * gfs_log_header - read the log header for a given segment + * @sdp: the filesystem + * @jdesc: the journal + * @gl: the journal's glock + * @seg: the segment to look at + * @lh: the log header to return + * + * Read the log header for a given segement in a given journal. Do a few + * sanity checks on it. + * + * Returns: 0 on success, 1 if the header was invalid or incomplete and, errno on error + */ + +static int +get_log_header(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint32_t seg, struct gfs_log_header *lh) +{ + struct buffer_head *bh; + struct gfs_log_header lh2; + int error; + + error = gfs_dread(gl, seg2bn(seg), DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + gfs_log_header_in(lh, bh->b_data); + gfs_log_header_in(&lh2, + bh->b_data + GFS_BASIC_BLOCK - + sizeof(struct gfs_log_header)); + + brelse(bh); + + if (memcmp(lh, &lh2, sizeof(struct gfs_log_header)) != 0 || + lh->lh_header.mh_magic != GFS_MAGIC || + lh->lh_header.mh_type != GFS_METATYPE_LH) + error = 1; + + return error; +} + +/** + * find_good_lh - find a good log header + * @sdp: the filesystem + * @jdesc: the journal + * @gl: the journal's glock + * @seg: the segment to start searching from (it's also filled in with a new value.) + * @lh: the log header to fill in + * @forward: if true search forward in the log, else search backward + * + * Call get_log_header() to get a log header for a segment, but if the + * segment is bad, either scan forward or backward until we find a good one. + * + * Returns: errno + */ + +static int +find_good_lh(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint32_t *seg, struct gfs_log_header *lh, + int forward) +{ + int error; + uint32_t orig_seg = *seg; + + for (;;) { + error = get_log_header(sdp, jdesc, gl, *seg, lh); + if (error <= 0) + return error; + + if (forward) { + if (++*seg == jdesc->ji_nsegment) + *seg = 0; + } else { + if ((*seg)-- == 0) + *seg = jdesc->ji_nsegment - 1; + } + + if (*seg == orig_seg) { + gfs_consist(sdp); + return -EIO; + } + } +} + +/** + * verify_jhead - make sure we've found the head of the log + * @sdp: the filesystem + * @jdesc: the journal + * @gl: the journal's glock + * @head: this is filled in with the log descriptor of the head + * + * At this point, seg and lh should be either the head of the log or just + * before. Scan forward until we find the head. + * + * Returns: errno + */ + +static int +verify_jhead(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, struct gfs_log_header *head) +{ + struct gfs_log_header lh; + uint32_t seg; + int error; + + seg = bn2seg(head->lh_first); + + for (;;) { + if (++seg == jdesc->ji_nsegment) + seg = 0; + + error = get_log_header(sdp, jdesc, gl, seg, &lh); + if (error < 0) + return error; + + if (error == 1) + continue; + if (lh.lh_sequence == head->lh_sequence) + continue; + + if (lh.lh_sequence < head->lh_sequence) + break; + + memcpy(head, &lh, sizeof(struct gfs_log_header)); + } + + return 0; +} + +/** + * gfs_find_jhead - find the head of a log + * @sdp: the filesystem + * @jdesc: the journal + * @gl: the journal's glock + * @head: the log descriptor for the head of the log is returned here + * + * Do a binary search of a journal and find the valid log entry with the + * highest sequence number. (i.e. the log head) + * + * Returns: errno + */ + +int +gfs_find_jhead(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, struct gfs_log_header *head) +{ + struct gfs_log_header lh; + uint32_t seg1, seg2, seg_m; + int error; + uint64_t lh1_sequence; + + seg1 = 0; + seg2 = jdesc->ji_nsegment - 1; + + for (;;) { + seg_m = (seg1 + seg2) / 2; + + error = find_good_lh(sdp, jdesc, gl, &seg1, &lh, TRUE); + if (error) + break; + + if (seg1 == seg_m) { + error = verify_jhead(sdp, jdesc, gl, &lh); + if (unlikely(error)) + printk("GFS: verify_jhead error=%d\n", error); + else + memcpy(head, &lh, sizeof(struct gfs_log_header)); + break; + } + + lh1_sequence = lh.lh_sequence; + + error = find_good_lh(sdp, jdesc, gl, &seg_m, &lh, FALSE); + if (error) + break; + + if (lh1_sequence <= lh.lh_sequence) + seg1 = seg_m; + else + seg2 = seg_m; + } + + return error; +} + +/** + * gfs_increment_blkno - move to the next block in a journal + * @sdp: the filesystem + * @jdesc: the journal + * @gl: the journal's glock + * @addr: the block number to increment + * @skip_header: if this is TRUE, skip log headers + * + * Replace @addr with the location of the next block in the log. + * Take care of journal wrap and skip of log header if necessary. + * + * Returns: errno + */ + +int +gfs_increment_blkno(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint64_t *addr, int skip_headers) +{ + struct gfs_log_header header; + int error; + + (*addr)++; + + /* Handle journal wrap */ + + if (*addr == seg2bn(jdesc->ji_nsegment)) + *addr -= jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size; + + gfs_start_ra(gl, *addr, + jdesc->ji_addr + + jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size - *addr); + + /* Handle landing on a header block */ + + if (skip_headers && !do_mod(*addr, sdp->sd_sb.sb_seg_size)) { + error = get_log_header(sdp, jdesc, gl, bn2seg(*addr), &header); + if (error < 0) + return error; + + if (error) { /* Corrupt headers here are bad */ + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: *addr = %"PRIu64"\n", + sdp->sd_fsname, *addr); + return -EIO; + } + if (header.lh_first == *addr) { + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: *addr = %"PRIu64"\n", + sdp->sd_fsname, *addr); + gfs_log_header_print(&header); + return -EIO; + } + + (*addr)++; + /* Can't wrap here */ + } + + return 0; +} + +/** + * foreach_descriptor - go through the active part of the log + * @sdp: the filesystem + * @jdesc: the journal + * @gl: the journal's glock + * @start: the first log header in the active region + * @end: the last log header (don't process the contents of this entry)) + * @pass: the recovery pass + * + * Call a given function once for every log descriptor in the active + * portion of the log. + * + * Returns: errno + */ + +static int +foreach_descriptor(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint64_t start, uint64_t end, + unsigned int pass) +{ + struct gfs_log_header header; + struct gfs_log_descriptor desc; + struct buffer_head *bh; + int error = 0; + + while (start != end) { + if (do_mod(start, sdp->sd_sb.sb_seg_size)) { + gfs_consist(sdp); + return -EIO; + } + + error = get_log_header(sdp, jdesc, gl, bn2seg(start), &header); + if (error < 0) + return error; + + if (error) { /* Corrupt headers here are bad */ + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: start = %"PRIu64"\n", + sdp->sd_fsname, start); + return -EIO; + } + if (header.lh_first != start) { + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: start = %"PRIu64"\n", + sdp->sd_fsname, start); + gfs_log_header_print(&header); + return -EIO; + } + + start++; + + for (;;) { + error = gfs_dread(gl, start, DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + if (gfs_metatype_check(sdp, bh, GFS_METATYPE_LD)) { + brelse(bh); + return -EIO; + } + + gfs_desc_in(&desc, bh->b_data); + brelse(bh); + + if (desc.ld_type != GFS_LOG_DESC_LAST) { + error = LO_SCAN_ELEMENTS(sdp, jdesc, gl, start, + &desc, pass); + if (error) + return error; + + while (desc.ld_length--) { + error = gfs_increment_blkno(sdp, jdesc, gl, + &start, TRUE); + if (error) + return error; + } + } else { + while (desc.ld_length--) { + error = gfs_increment_blkno(sdp, jdesc, gl, + &start, + !!desc.ld_length); + if (error) + return error; + } + + break; + } + } + } + + return error; +} + +/** + * clean_journal - mark a dirty journal as being clean + * @sdp: the filesystem + * @jdesc: the journal + * @gl: the journal's glock + * @head: the head journal to start from + * + * Returns: errno + */ + +static int noinline +clean_journal(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, struct gfs_log_header *head) +{ + struct gfs_log_header lh; + struct gfs_log_descriptor desc; + struct buffer_head *bh; + uint32_t seg; + uint64_t blkno; + int error; + + seg = bn2seg(head->lh_first); + + for (;;) { + if (++seg == jdesc->ji_nsegment) + seg = 0; + + error = get_log_header(sdp, jdesc, gl, seg, &lh); + if (error < 0) + return error; + + /* Rewrite corrupt header blocks */ + + if (error == 1) { + bh = gfs_dgetblk(gl, seg2bn(seg)); + + gfs_prep_new_buffer(bh); + gfs_buffer_clear(bh); + gfs_log_header_out(head, bh->b_data); + gfs_log_header_out(head, + bh->b_data + GFS_BASIC_BLOCK - + sizeof(struct gfs_log_header)); + + error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT); + brelse(bh); + if (error) + return error; + } + + /* Stop when we get to the end of the log. */ + + if (lh.lh_sequence < head->lh_sequence) + break; + } + + /* Build a "last" descriptor for the transaction we are + about to commit by writing the shutdown header. */ + + memset(&desc, 0, sizeof(struct gfs_log_descriptor)); + desc.ld_header.mh_magic = GFS_MAGIC; + desc.ld_header.mh_type = GFS_METATYPE_LD; + desc.ld_header.mh_format = GFS_FORMAT_LD; + desc.ld_type = GFS_LOG_DESC_LAST; + desc.ld_length = 0; + + for (blkno = head->lh_first + 1; blkno != seg2bn(seg);) { + if (do_mod(blkno, sdp->sd_sb.sb_seg_size)) + desc.ld_length++; + if (++blkno == seg2bn(jdesc->ji_nsegment)) + blkno -= jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size; + } + + /* Write the descriptor */ + + bh = gfs_dgetblk(gl, head->lh_first + 1); + + gfs_prep_new_buffer(bh); + gfs_buffer_clear(bh); + gfs_desc_out(&desc, bh->b_data); + + error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT); + brelse(bh); + if (error) + return error; + + /* Build a log header that says the journal is clean */ + + memset(&lh, 0, sizeof(struct gfs_log_header)); + lh.lh_header.mh_magic = GFS_MAGIC; + lh.lh_header.mh_type = GFS_METATYPE_LH; + lh.lh_header.mh_format = GFS_FORMAT_LH; + lh.lh_flags = GFS_LOG_HEAD_UNMOUNT; + lh.lh_first = seg2bn(seg); + lh.lh_sequence = head->lh_sequence + 1; + /* Don't care about tail */ + lh.lh_last_dump = head->lh_last_dump; + + /* Write the header */ + + bh = gfs_dgetblk(gl, lh.lh_first); + + gfs_prep_new_buffer(bh); + gfs_buffer_clear(bh); + gfs_log_header_out(&lh, bh->b_data); + gfs_log_header_out(&lh, + bh->b_data + GFS_BASIC_BLOCK - + sizeof(struct gfs_log_header)); + + error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT); + brelse(bh); + + return error; +} + +/** + * gfs_recover_journal - recover a given journal + * @sdp: the filesystem + * @jid: the number of the journal to recover + * @jdesc: the struct gfs_jindex describing the journal + * @wait: Don't return until the journal is clean (or an error is encountered) + * + * Acquire the journal's lock, check to see if the journal is clean, and + * do recovery if necessary. + * + * Returns: errno + */ + +int +gfs_recover_journal(struct gfs_sbd *sdp, + unsigned int jid, struct gfs_jindex *jdesc, + int wait) +{ + struct gfs_log_header *head; + struct gfs_holder j_gh, t_gh; + unsigned long t; + int error; + + printk("GFS: fsid=%s: jid=%u: Trying to acquire journal lock...\n", + sdp->sd_fsname, jid); + + /* Acquire the journal lock so we can do recovery */ + + error = gfs_glock_nq_num(sdp, + jdesc->ji_addr, &gfs_meta_glops, + LM_ST_EXCLUSIVE, + LM_FLAG_NOEXP | + ((wait) ? 0 : LM_FLAG_TRY) | + GL_NOCACHE, &j_gh); + switch (error) { + case 0: + break; + + case GLR_TRYFAILED: + printk("GFS: fsid=%s: jid=%u: Busy\n", sdp->sd_fsname, jid); + error = 0; + + default: + goto fail; + }; + + printk("GFS: fsid=%s: jid=%u: Looking at journal...\n", + sdp->sd_fsname, jid); + + head = kmalloc(sizeof(struct gfs_log_header), GFP_KERNEL); + if (!head) { + printk("GFS: fsid=%s jid=%u: Can't replay: Not enough memory", + sdp->sd_fsname, jid); + goto fail_gunlock; + } + + error = gfs_find_jhead(sdp, jdesc, j_gh.gh_gl, head); + if (error) + goto fail_header; + + if (!(head->lh_flags & GFS_LOG_HEAD_UNMOUNT)) { + if (test_bit(SDF_ROFS, &sdp->sd_flags)) { + printk("GFS: fsid=%s: jid=%u: Can't replay: read-only FS\n", + sdp->sd_fsname, jid); + error = -EROFS; + goto fail_header; + } + + printk("GFS: fsid=%s: jid=%u: Acquiring the transaction lock...\n", + sdp->sd_fsname, jid); + + t = jiffies; + + /* Acquire an exclusive hold on the transaction lock */ + + error = gfs_glock_nq_init(sdp->sd_trans_gl, + LM_ST_EXCLUSIVE, + LM_FLAG_NOEXP | + LM_FLAG_PRIORITY | + GL_NOCANCEL | + GL_NOCACHE, + &t_gh); + if (error) + goto fail_header; + + if (test_bit(SDF_ROFS, &sdp->sd_flags)) { + printk("GFS: fsid=%s: jid=%u: Can't replay: read-only FS\n", + sdp->sd_fsname, jid); + error = -EROFS; + goto fail_gunlock_tr; + } + + printk("GFS: fsid=%s: jid=%u: Replaying journal...\n", + sdp->sd_fsname, jid); + + set_bit(GLF_DIRTY, &j_gh.gh_gl->gl_flags); + + LO_BEFORE_SCAN(sdp, jid, head, GFS_RECPASS_A1); + + error = foreach_descriptor(sdp, jdesc, j_gh.gh_gl, + head->lh_tail, head->lh_first, + GFS_RECPASS_A1); + if (error) + goto fail_gunlock_tr; + + LO_AFTER_SCAN(sdp, jid, GFS_RECPASS_A1); + + gfs_replay_wait(sdp); + + error = clean_journal(sdp, jdesc, j_gh.gh_gl, head); + if (error) + goto fail_gunlock_tr; + + gfs_glock_dq_uninit(&t_gh); + + t = DIV_RU(jiffies - t, HZ); + + printk("GFS: fsid=%s: jid=%u: Journal replayed in %lus\n", + sdp->sd_fsname, jid, t); + } + + gfs_lm_recovery_done(sdp, jid, LM_RD_SUCCESS); + + kfree(head); + + gfs_glock_dq_uninit(&j_gh); + + printk("GFS: fsid=%s: jid=%u: Done\n", sdp->sd_fsname, jid); + + return 0; + + fail_gunlock_tr: + gfs_replay_wait(sdp); + gfs_glock_dq_uninit(&t_gh); + + fail_header: + kfree(head); + + fail_gunlock: + gfs_glock_dq_uninit(&j_gh); + + printk("GFS: fsid=%s: jid=%u: %s\n", + sdp->sd_fsname, jid, (error) ? "Failed" : "Done"); + + fail: + gfs_lm_recovery_done(sdp, jid, LM_RD_GAVEUP); + + return error; +} + +/** + * gfs_check_journals - Recover any dirty journals + * @sdp: the filesystem + * + */ + +void +gfs_check_journals(struct gfs_sbd *sdp) +{ + struct dirty_j *dj; + + for (;;) { + dj = get_dirty_j(sdp); + if (!dj) + break; + + down(&sdp->sd_jindex_lock); + + if (dj->dj_jid != sdp->sd_lockstruct.ls_jid && + dj->dj_jid < sdp->sd_journals) { + memcpy(&dj->dj_desc, + sdp->sd_jindex + dj->dj_jid, + sizeof(struct gfs_jindex)); + up(&sdp->sd_jindex_lock); + + gfs_recover_journal(sdp, + dj->dj_jid, &dj->dj_desc, + FALSE); + + } else { + up(&sdp->sd_jindex_lock); + gfs_lm_recovery_done(sdp, dj->dj_jid, LM_RD_GAVEUP); + } + + kfree(dj); + } +} + +/** + * gfs_recover_dump - recover the log elements in this machine's journal + * @sdp: the filesystem + * + * Returns: errno + */ + +int +gfs_recover_dump(struct gfs_sbd *sdp) +{ + struct gfs_log_header head; + int error; + + error = gfs_find_jhead(sdp, &sdp->sd_jdesc, sdp->sd_journal_gh.gh_gl, + &head); + if (error) + goto fail; + + if (!(head.lh_flags & GFS_LOG_HEAD_UNMOUNT)) { + gfs_consist(sdp); + return -EIO; + } + if (!head.lh_last_dump) + return error; + + printk("GFS: fsid=%s: Scanning for log elements...\n", + sdp->sd_fsname); + + LO_BEFORE_SCAN(sdp, sdp->sd_lockstruct.ls_jid, &head, GFS_RECPASS_B1); + + error = foreach_descriptor(sdp, &sdp->sd_jdesc, sdp->sd_journal_gh.gh_gl, + head.lh_last_dump, head.lh_first, + GFS_RECPASS_B1); + if (error) + goto fail; + + LO_AFTER_SCAN(sdp, sdp->sd_lockstruct.ls_jid, GFS_RECPASS_B1); + + /* We need to make sure if we crash during the next log dump that + all intermediate headers in the transaction point to the last + log dump before the one we're making so we don't lose it. */ + + sdp->sd_log_dump_last = head.lh_last_dump; + + printk("GFS: fsid=%s: Done\n", sdp->sd_fsname); + + return 0; + + fail: + printk("GFS: fsid=%s: Failed\n", sdp->sd_fsname); + + return error; +} --- linux-2.6.27.orig/ubuntu/gfs/lm.h +++ linux-2.6.27/ubuntu/gfs/lm.h @@ -0,0 +1,32 @@ +#ifndef __LM_DOT_H__ +#define __LM_DOT_H__ + +int gfs_lm_mount(struct gfs_sbd *sdp, int silent); +void gfs_lm_others_may_mount(struct gfs_sbd *sdp); +void gfs_lm_unmount(struct gfs_sbd *sdp); +int gfs_lm_withdraw(struct gfs_sbd *sdp, char *fmt, ...) +__attribute__ ((format(printf, 2, 3))); +int gfs_lm_get_lock(struct gfs_sbd *sdp, + struct lm_lockname *name, void **lockp); +void gfs_lm_put_lock(struct gfs_sbd *sdp, void *lock); +unsigned int gfs_lm_lock(struct gfs_sbd *sdp, void *lock, + unsigned int cur_state, unsigned int req_state, + unsigned int flags); +unsigned int gfs_lm_unlock(struct gfs_sbd *sdp, void *lock, + unsigned int cur_state); +void gfs_lm_cancel(struct gfs_sbd *sdp, void *lock); +int gfs_lm_hold_lvb(struct gfs_sbd *sdp, void *lock, char **lvbp); +void gfs_lm_unhold_lvb(struct gfs_sbd *sdp, void *lock, char *lvb); +int gfs_lm_plock_get(struct gfs_sbd *sdp, + struct lm_lockname *name, + struct file *file, struct file_lock *fl); +int gfs_lm_plock(struct gfs_sbd *sdp, + struct lm_lockname *name, + struct file *file, int cmd, struct file_lock *fl); +int gfs_lm_punlock(struct gfs_sbd *sdp, + struct lm_lockname *name, + struct file *file, struct file_lock *fl); +void gfs_lm_recovery_done(struct gfs_sbd *sdp, + unsigned int jid, unsigned int message); + +#endif /* __LM_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/incore.h +++ linux-2.6.27/ubuntu/gfs/incore.h @@ -0,0 +1,1207 @@ +/* + * In-core (memory/RAM) structures. + * These do not appear on-disk. See gfs_ondisk.h for on-disk structures. + */ + +#ifndef __INCORE_DOT_H__ +#define __INCORE_DOT_H__ + +/* flags used in function call parameters */ + +#define DIO_NEW (0x00000001) /* Newly allocated metadata */ +#define DIO_FORCE (0x00000002) /* Force read of block from disk */ +#define DIO_CLEAN (0x00000004) /* Don't write to disk */ +#define DIO_DIRTY (0x00000008) /* Data changed, must write to disk */ +#define DIO_START (0x00000010) /* Start disk read or write */ +#define DIO_WAIT (0x00000020) /* Wait for disk r/w to complete */ + +#define DIO_METADATA (0x00000040) /* Process glock's protected metadata */ +#define DIO_DATA (0x00000080) /* Process glock's protected filedata */ +#define DIO_INVISIBLE (0x00000100) /* Don't monkey with glock's dirty bit */ +#define DIO_CHECK (0x00000200) /* Make sure all metadata has been synced */ +#define DIO_ALL (0x00000400) /* Flush all AIL transactions to disk */ + +/* Structure prototypes */ + +struct gfs_log_operations; +struct gfs_log_element; +struct gfs_meta_header_cache; +struct gfs_depend; +struct gfs_bitmap; +struct gfs_rgrpd; +struct gfs_bufdata; +struct gfs_glock_operations; +struct gfs_holder; +struct gfs_glock; +struct gfs_alloc; +struct gfs_inode; +struct gfs_file; +struct gfs_unlinked; +struct gfs_quota_le; +struct gfs_quota_data; +struct gfs_log_buf; +struct gfs_trans; +struct gfs_gl_hash_bucket; +struct gfs_sbd; + +typedef void (*gfs_glop_bh_t) (struct gfs_glock * gl, unsigned int ret); + +/* + * Structure of operations that are associated with each + * type of element in the log. + */ +struct gfs_log_operations { + /* + * Operations specific to a given log element (LE). + * These are typically executed individually via macros such as LO_ADD. + */ + + /* Add new LE to transaction */ + void (*lo_add) (struct gfs_sbd * sdp, struct gfs_log_element * le); + + /* Do any cleanup, etc., needed just before commit to incore log */ + void (*lo_trans_end) (struct gfs_sbd * sdp, + struct gfs_log_element * le); + + /* Print LE-specific info via printk() */ + void (*lo_print) (struct gfs_sbd * sdp, struct gfs_log_element * le, + unsigned int where); + + /* Find any incore transactions that overlap through this LE (e.g. + * share glocks), to determine if any transactions can be combined. */ + struct gfs_trans *(*lo_overlap_trans) (struct gfs_sbd * sdp, + struct gfs_log_element * le); + + /* Change LE from "new" to "incore" status, before write to log */ + void (*lo_incore_commit) (struct gfs_sbd * sdp, struct gfs_trans * tr, + struct gfs_log_element * le); + + /* Allow writes to in-place locations, after log is on-disk */ + void (*lo_add_to_ail) (struct gfs_sbd * sdp, + struct gfs_log_element * le); + + /* Clean up LE after log dump */ + void (*lo_clean_dump) (struct gfs_sbd * sdp, + struct gfs_log_element * le); + + /* + * Operations specific to a class of log elements. + * These are typically executed over a whole transaction by + * macros such as LO_TRANS_SIZE. Each LE-type-specific operation + * for each LE contributes its part to the overall result. + */ + + /* Determine LE-type-specific quantities of blocks of various types + * required for writing the log */ + void (*lo_trans_size) (struct gfs_sbd * sdp, struct gfs_trans * tr, + unsigned int *mblks, unsigned int *eblks, + unsigned int *blocks, unsigned int *bmem); + + /* Combine LE-type-specific values in new_tr and tr, result is in tr */ + void (*lo_trans_combine) (struct gfs_sbd * sdp, struct gfs_trans * tr, + struct gfs_trans * new_tr); + + /* Create control and metadata buffers that will make up the log */ + void (*lo_build_bhlist) (struct gfs_sbd * sdp, struct gfs_trans * tr); + + /* Calculate log space needed for this LE in a log dump */ + void (*lo_dump_size) (struct gfs_sbd * sdp, unsigned int *elements, + unsigned int *blocks, unsigned int *bmem); + + /* Add LE to log dump */ + void (*lo_build_dump) (struct gfs_sbd * sdp, struct gfs_trans * tr); + + /* + * Operations that happen at recovery time + */ + + /* Reset/init whatever before doing recovery */ + void (*lo_before_scan) (struct gfs_sbd * sdp, unsigned int jid, + struct gfs_log_header * head, + unsigned int pass); + + /* LE-specific recovery procedure */ + int (*lo_scan_elements) (struct gfs_sbd * sdp, + struct gfs_jindex * jdesc, + struct gfs_glock * gl, uint64_t start, + struct gfs_log_descriptor * desc, + unsigned int pass); + + /* Verify and report recovery results/statistics */ + void (*lo_after_scan) (struct gfs_sbd * sdp, unsigned int jid, + unsigned int pass); + + + /* + * Type of element (glock/buf/unlinked/quota) + */ + char *lo_name; +}; + +/* + * Structure that gets added to struct gfs_trans->tr_elements. They + * make up the "stuff" in each transaction. + */ +struct gfs_log_element { + struct gfs_log_operations *le_ops; /* Vector of functions */ + + struct gfs_trans *le_trans; /* We're part of this transaction */ + struct list_head le_list; /* Link to transaction's element list */ +}; + +/* + * Meta-header cache structure. + * One for each metadata block that we've de-allocated. + * Used to temporarily store gfs_meta_header structs for meta blocks that + * have been freshly turned into FREEMETA (alloc'd or de-alloc'd). Storing + * these (small) structures in-core allows us to release the (large) buffers, + * and not need to re-read the header from disk if/when we re-allocate the + * blocks to USEDMETA, as long as this node holds the EXCLUSIVE lock for the + * resource group containing the blocks. If we release the EX lock, we must + * throw away the rgrp's cached meta headers, since another node could change + * the blocks' contents. + * In-core superblock structure hosts the hashed cache, as well as a + * linear list of all cached, in most-recently-added order. + * Also, each resource group keeps a list of cached blocks within its scope. + */ +struct gfs_meta_header_cache { + /* Links to various lists */ + struct list_head mc_list_hash; /* Superblock's hashed list */ + struct list_head mc_list_single; /* Superblock's list, MRU order */ + struct list_head mc_list_rgd; /* Resource group's list */ + + uint64_t mc_block; /* Block # (in-place address) */ + struct gfs_meta_header mc_mh; /* Payload: the block's meta-header */ +}; + +/* + * Dependency cache structure. + * In-core superblock structure hosts the actual cache. + * Also, each resource group keeps a list of dependency blocks within its scope. + */ +struct gfs_depend { + /* Links to various lists */ + struct list_head gd_list_hash; /* Superblock's hashed list */ + struct list_head gd_list_rgd; /* Resource group's list */ + + struct gfs_rgrpd *gd_rgd; /* Resource group descriptor */ + uint64_t gd_formal_ino; /* Inode ID */ + unsigned long gd_time; /* Time (jiffies) when put on list */ +}; + +/* + * Block allocation bitmap descriptor structure. + * One of these for each FS block that contains bitmap data + * (i.e. the resource group header blocks and their following bitmap blocks). + * Each allocatable FS data block is represented by 2 bits (4 alloc states). + */ +struct gfs_bitmap { + uint32_t bi_offset; /* Byte offset of bitmap within this bit block + (non-zero only for an rgrp header block) */ + uint32_t bi_start; /* Data block (rgrp scope, 32-bit) represented + by the first bit-pair in this bit block */ + uint32_t bi_len; /* The number of bitmap bytes in this bit block */ +}; + +/* + * Resource Group (Rgrp) descriptor structure. + * There is one of these for each resource (block) group in the FS. + * The filesystem is divided into a number of resource groups to allow + * simultaneous block alloc operations by a number of nodes. + */ +struct gfs_rgrpd { + /* Links to superblock lists */ + struct list_head rd_list; /* On-disk-order list of all rgrps */ + struct list_head rd_list_mru; /* Most Recently Used list of all rgs */ + struct list_head rd_recent; /* recently used rgrps */ + uint32_t rd_try_counter; /* # of times we fail a try lock */ + + struct gfs_glock *rd_gl; /* Glock for this rgrp */ + + struct gfs_rindex rd_ri; /* Resource Index (on-disk) structure */ + struct gfs_rgrp rd_rg; /* Resource Group (on-disk) structure */ + uint64_t rd_rg_vn; /* Version #: if != glock's gl_vn, + we need to read rgrp fm disk */ + + /* Block alloc bitmap cache */ + struct gfs_bitmap *rd_bits; /* Array of block bitmap descriptors */ + struct buffer_head **rd_bh; /* Array of ptrs to block bitmap bh's */ + + /* Block allocation strategy, rgrp scope. Start at these blocks when + searching for next data/meta block to alloc */ + uint32_t rd_last_alloc_data; /* Most recent data block allocated */ + uint32_t rd_last_alloc_meta; /* Most recent meta block allocated */ + + struct list_head rd_mhc; /* Cached meta-headers for this rgrp */ + struct list_head rd_depend; /* Dependent inodes (MRU order) */ + + struct gfs_sbd *rd_sbd; /* FS incore superblock (fs instance) */ +}; + +/* + * Per-buffer data + * One of these is attached as GFS private data to each FS block's buffer_head. + * These keep track of a buffer's progress through the transaction pipeline, + * using the "new" embedded log element to attach it to a being-built + * transaction, and moving the attachment point to the "incore" LE once + * the transaction completes (at which time the buffer becomes a candidate + * to be written to the on-disk log). + * A buffer may be attached simultaneously to a new and an incore transaction, + * but no more than one of each: Only one new trans may be built at a time + * for a given buffer, obviously, since the buffer's contents are protected + * by an EXclusive glock when writing. And, when a transaction is completely + * built, GFS combines incore transactions that share glocks (see + * incore_commit()), i.e. the glock that protects the buffer, so a buffer + * never needs to be attached to more than one (combined) incore trans. + * Note that multiple transactions can modify the buffer since its most + * recent writes to disk. This principle applies to both in-place and + * journal block locations on-disk, allowing this node to keep modifying the + * cached data without writing it to disk, unless/until another node needs + * to access the data, or the Linux OS tells us to sync to disk. + * If a transaction follows another transaction before the first transaction's + * log completes (indicated by the in-place buffer head still being pinned + * in RAM), GFS copies the first transaction's results to a "frozen" + * image of the buffer, so the first transaction results (an atomic + * snapshot) can be logged properly, while the second transaction is + * modifying the "real" buffer. This frozen copy lives only until the new + * transaction is complete, at which point one of two things has occurred: + * 1). Buffer was logged successfully; frozen copy's job is done. + * 2). Buffer was not yet logged; frozen copy no longer needed, newer + * buffer becomes the log candidate. + * + * gfs_bufdata structs also link into the Active Items Lists (AIL) (buffers + * flushed to on-disk log, but not yet flushed to on-disk in-place locations) + * attached to: + * 1). The latest transaction to modify and log (on-disk) the buffer, and + * 2). The glock that protects the buffer's contents. + * The buffer is attached to only the most recent transaction's AIL + * list for a couple of reasons. One is that only the most up-to-date + * buffer content needs to be written to the in-place block on-disk. The + * other is that since there is a more recent copy of the block in + * the log, we don't need to keep the older copies in the log. We can + * remove them from the AIL and let the log space be reused for new + * transactions (GFS advances the log tail when removing buffers from AIL). + */ +struct gfs_bufdata { + struct buffer_head *bd_bh; /* We belong to this Linux buffer_head */ + struct gfs_glock *bd_gl; /* This glock protects buffer's payload */ + + /* Log elements map us to a particular set of log operations functions, + and to a particular transaction */ + struct gfs_log_element bd_new_le; /* New, incomplete transaction */ + struct gfs_log_element bd_incore_le; /* Complete (committed) trans */ + + char *bd_frozen; /* "Frozen" copy of buffer's data */ + struct semaphore bd_lock; /* Protects access to this structure */ + + /* "Pin" means keep buffer in RAM, don't write to disk (yet) */ + unsigned int bd_pinned; /* Recursive pin count */ + + /* Links to Active Items Lists */ + struct list_head bd_ail_tr_list; /* This buf's most recent trans' AIL */ + struct list_head bd_ail_gl_list; /* This buf's glock's AIL */ +}; + +/* + * Glock operations + * One set of operations for each glock, the set selected by type of glock. + * These functions get called at various points in a glock's lifetime. + * "xmote" = promote or demote (change lock state) a glock at inter-node scope. + * "th" = top half, "bh" = bottom half + * Some operations/fields are required (GFS assumes they are there): + * go_xmote_th + * go_drop_th + * go_type + * Other operations are optional (GFS checks for presence before calling). + */ +struct gfs_glock_operations { + + /* Acquire lock or change lock state at inter-node scope: + Does type-specific preparation (if any) + Uses gfs_glock_xmote_th to call lock module. */ + void (*go_xmote_th) (struct gfs_glock * gl, unsigned int state, + int flags); + + /* After acquiring or changing a lock at inter-node scope */ + void (*go_xmote_bh) (struct gfs_glock * gl); + + /* Release (unlock) a lock at inter-node scope: + Does type-specific preparation (if any) + Uses gfs_glock_drop_th to call lock module. */ + void (*go_drop_th) (struct gfs_glock * gl); + + /* After releasing a lock at inter-node scope */ + void (*go_drop_bh) (struct gfs_glock * gl); + + /* Sync dirty data to disk (e.g. before demoting an EX inter-node lock) + (another node needs to read the updated data from disk) */ + void (*go_sync) (struct gfs_glock * gl, int flags); + + /* Invalidate local cached data just after releasing an inter-node lock + (another node may change the on-disk data, so it's no good to us) */ + void (*go_inval) (struct gfs_glock * gl, int flags); + + /* Lock-type-specific check to see if it's okay to unlock a glock + at inter-node scope (and remove it from our glock cache) */ + int (*go_demote_ok) (struct gfs_glock * gl); + + /* After getting lock for first holder (within this node) */ + int (*go_lock) (struct gfs_glock * gl, int flags); + + /* After last holder (within this node) gives up lock (glock may + remain in glock cache, though) */ + void (*go_unlock) (struct gfs_glock * gl, int flags); + + /* After receiving a callback: another node needs the lock */ + void (*go_callback) (struct gfs_glock * gl, unsigned int state); + + /* Called when the glock layer marks a lock as being not greedy + anymore */ + void (*go_greedy) (struct gfs_glock * gl); + + /* Lock type: locks with same lock # (often an FS block #), + but different types, are different locks */ + int go_type; +}; + +/* + * Glock holder structure + * One for each holder of a glock. + * These coordinate the use, within this node, of an acquired inter-node glock. + * Once a node has acquired a glock, it may be shared within that node by + * several processes, or even by several recursive requests from the same + * process. Each is a separate "holder". Different holders may co-exist + * having requested different lock states, as long as the node holds the + * glock in a state that is compatible. A hold requestor may select, via + * flags, the rules by which sharing within the node is granted: + * LM_FLAG_ANY: Grant if glock state is any other than UNLOCKED. + * GL_EXACT: Grant only if glock state is exactly the requested state. + * GL_LOCAL_EXCL: Grant only one holder at a time within this node. + * With no flags, a hold will be granted to a SHARED request even if the + * node holds the glock in EXCLUSIVE mode. See relaxed_state_ok(). + * When a process needs to manipulate a lock, it requests it via one of + * these holder structures. If the request cannot be satisfied immediately, + * the holder structure gets queued on one of these lists in gfs_glock: + * 1) waiters1, for gaining exclusive access to the (local) glock structure. + * 2) waiters2, for demoting a lock (unlocking a glock, or changing its state + * to be less restrictive) or relenquishing "greedy" status. + * 3) waiters3, for promoting (locking a new glock, or changing a glock state + * to be more restrictive). + * When holding a lock, gfs_holder struct stays on glock's holder list. + * See gfs-kernel/src/harness/lm_interface.h for gh_state (LM_ST_...) + * and gh_flags (LM_FLAG...) fields. + * Also see glock.h for gh_flags field (GL_...) flags. + */ + +/* Action requests */ +#define HIF_MUTEX (0) /* Exclusive (local) access to glock struct */ +#define HIF_PROMOTE (1) /* Change lock to more restrictive state */ +#define HIF_DEMOTE (2) /* Change lock to less restrictive state */ +#define HIF_GREEDY (3) /* Wait for the glock to be unlocked */ + +/* States */ +#define HIF_ALLOCED (4) /* Holder structure is or was in use */ +#define HIF_DEALLOC (5) /* Toss holder struct as soon as queued request + * is satisfied */ +#define HIF_HOLDER (6) /* We have been granted a hold on the lock */ +#define HIF_FIRST (7) /* We are first holder to get the lock */ +#define HIF_RECURSE (8) /* >1 hold requests on same glock by same process*/ +#define HIF_ABORTED (9) /* Aborted before being submitted */ + +struct gfs_holder { + struct list_head gh_list; /* Link to one of glock's holder lists */ + + struct gfs_glock *gh_gl; /* Glock that we're holding */ + struct task_struct *gh_owner; /* Linux process that is the holder */ + + /* request to change lock state */ + unsigned int gh_state; /* LM_ST_... requested lock state */ + int gh_flags; /* GL_... or LM_FLAG_... req modifiers */ + + int gh_error; /* GLR_... CANCELLED/TRYFAILED/-errno */ + unsigned long gh_iflags; /* HIF_... holder state, see above */ + struct completion gh_wait; /* Wait for completion of ... */ +}; + +/* + * Glock Structure + * One for each inter-node lock held by this node. + * A glock is a local representation/abstraction of an inter-node lock. + * Inter-node locks are managed by a "lock module" (LM) which plugs in to + * the lock harness / glock interface (see gfs-kernel/harness). Different + * lock modules support different lock protocols (e.g. GULM, GDLM, no_lock). + * A glock may have one or more holders within a node. See gfs_holder above. + * Glocks are managed within a hash table hosted by the in-core superblock. + * After all holders have released a glock, it will stay in the hash table + * cache for a time (depending on lock type), during which the inter-node + * lock will not be released unless another node needs the lock (lock + * manager requests this via callback to GFS through LM on this node). This + * provides better performance in case this node needs the glock again soon. + * See comments for meta_go_demote_ok(), glops.c. + * Each glock has an associated vector of lock-type-specific "glops" functions + * which are called at important times during the life of a glock, and + * which define the type of lock (e.g. dinode, rgrp, non-disk, etc). + * See gfs_glock_operations above. + * A glock, at inter-node scope, is identified by the following dimensions: + * 1) lock number (usually a block # for on-disk protected entities, + * or a fixed assigned number for non-disk locks, e.g. MOUNT). + * 2) lock type (actually, the type of entity protected by the lock). + * 3) lock namespace, to support multiple GFS filesystems simultaneously. + * Namespace (usually cluster:filesystem) is specified when mounting. + * See man page for gfs_mount. + * Glocks require support of Lock Value Blocks (LVBs) by the inter-node lock + * manager. LVBs are small (32-byte) chunks of data associated with a given + * lock, that can be quickly shared between cluster nodes. Used for certain + * purposes such as sharing an rgroup's block usage statistics without + * requiring the overhead of: + * -- sync-to-disk by one node, then a + * -- read from disk by another node. + * + */ + +#define GLF_PLUG (0) /* Dummy */ +#define GLF_LOCK (1) /* Exclusive (local) access to glock + * structure */ +#define GLF_STICKY (2) /* Don't release this inter-node lock + * unless another node explicitly asks */ +#define GLF_PREFETCH (3) /* This lock has been (speculatively) + * prefetched, demote if not used soon */ +#define GLF_SYNC (4) /* Sync lock's protected data as soon as + * there are no more holders */ +#define GLF_DIRTY (5) /* There is dirty data for this lock, + * sync before releasing inter-node */ +#define GLF_SKIP_WAITERS2 (6) /* Make run_queue() ignore gl_waiters2 + * (demote/greedy) holders */ +#define GLF_GREEDY (7) /* This lock is ignoring callbacks + * (requests from other nodes) for now */ + +struct gfs_glock { + struct list_head gl_list; /* Link to hb_list in one of superblock's + * sd_gl_hash glock hash table buckets */ + unsigned long gl_flags; /* GLF_... see above */ + struct lm_lockname gl_name; /* Lock number and lock type */ + atomic_t gl_count; /* Usage count */ + + spinlock_t gl_spin; /* Protects some members of this struct */ + + /* Lock state reflects inter-node manager's lock state */ + unsigned int gl_state; /* LM_ST_... see harness/lm_interface.h */ + + /* Lists of gfs_holders */ + struct list_head gl_holders; /* all current holders of the glock */ + struct list_head gl_waiters1; /* HIF_MUTEX */ + struct list_head gl_waiters2; /* HIF_DEMOTE, HIF_GREEDY */ + struct list_head gl_waiters3; /* HIF_PROMOTE */ + + struct gfs_glock_operations *gl_ops; /* function vector, defines type */ + + /* State to remember for async lock requests */ + struct gfs_holder *gl_req_gh; /* Holder for request being serviced */ + gfs_glop_bh_t gl_req_bh; /* The bottom half to execute */ + + void *gl_lock; /* Lock module's private lock data */ + char *gl_lvb; /* Lock Value Block */ + atomic_t gl_lvb_count; /* LVB recursive usage (hold/unhold) count */ + + uint64_t gl_vn; /* Incremented when protected data changes */ + unsigned long gl_stamp; /* Glock cache retention timer */ + void *gl_object; /* The protected entity (e.g. a dinode) */ + + /* Incore transaction stuff */ + /* Log elements map us to a particular set of log operations functions, + and to a particular transaction */ + struct gfs_log_element gl_new_le; /* New, incomplete transaction */ + struct gfs_log_element gl_incore_le; /* Complete (committed) trans */ + + struct gfs_gl_hash_bucket *gl_bucket; /* Our bucket in sd_gl_hash */ + struct list_head gl_reclaim; /* Link to sd_reclaim_list */ + + struct gfs_sbd *gl_sbd; /* Superblock (FS instance) */ + + struct inode *gl_aspace; /* The buffers protected by this lock */ + struct list_head gl_ail_bufs; /* AIL buffers protected by us */ +}; + +/* + * In-Place Reservation structure + * Coordinates allocation of "in-place" (as opposed to journal) FS blocks, + * which contain persistent inode/file/directory data and metadata. + * These blocks are the allocatable blocks within resource groups (i.e. + * not including rgrp header and block alloc bitmap blocks). + * gfs_inplace_reserve() calculates a fulfillment plan for allocating blocks, + * based on block statistics in the resource group headers. + * Then, gfs_blkalloc() or gfs_metaalloc() walks the block alloc bitmaps + * to do the actual allocation. + */ +struct gfs_alloc { + /* Up to 4 quotas (including an inode's user and group quotas) + can track changes in block allocation */ + + unsigned int al_qd_num; /* # of quotas tracking changes */ + struct gfs_quota_data *al_qd[4]; /* Ptrs to quota structures */ + struct gfs_holder al_qd_ghs[4]; /* Holders for quota glocks */ + + /* Request, filled in by the caller to gfs_inplace_reserve() */ + + uint32_t al_requested_di; /* Number of dinodes to reserve */ + uint32_t al_requested_meta; /* Number of metadata blocks to reserve */ + uint32_t al_requested_data; /* Number of data blocks to reserve */ + + /* Fulfillment plan, filled in by gfs_inplace_reserve() */ + + char *al_file; /* Debug info, .c file making request */ + unsigned int al_line; /* Debug info, line of code making req */ + struct gfs_holder al_ri_gh; /* Glock holder for resource grp index */ + struct gfs_holder al_rgd_gh; /* Glock holder for al_rgd rgrp */ + struct gfs_rgrpd *al_rgd; /* Resource group from which to alloc */ + uint32_t al_reserved_meta; /* Alloc up to this # meta blocks from al_rgd */ + uint32_t al_reserved_data; /* Alloc up to this # data blocks from al_rgd */ + + /* Actual alloc, filled in by gfs_blkalloc()/gfs_metaalloc(), etc. */ + + uint32_t al_alloced_di; /* # dinode blocks allocated */ + uint32_t al_alloced_meta; /* # meta blocks allocated */ + uint32_t al_alloced_data; /* # data blocks allocated */ + + /* Dinode allocation crap */ + + struct gfs_unlinked *al_ul; /* Unlinked dinode log entry */ +}; + +/* + * Incore inode structure + */ + +#define GIF_QD_LOCKED (0) +#define GIF_PAGED (1) +#define GIF_SW_PAGED (2) + +struct gfs_inode { + struct gfs_inum i_num; /* Formal inode # and block address */ + + atomic_t i_count; /* Usage count */ + unsigned long i_flags; /* GIF_... see above */ + + uint64_t i_vn; /* Version #: if different from glock's vn, + we need to read inode from disk */ + struct gfs_dinode i_di; /* Dinode (on-disk) structure */ + + struct gfs_glock *i_gl; /* This glock protects this inode */ + struct gfs_sbd *i_sbd; /* Superblock (fs instance structure) */ + struct inode *i_vnode; /* Linux VFS inode structure */ + + struct gfs_holder i_iopen_gh; /* Glock holder for Inode Open lock */ + + /* Block allocation strategy, inode scope */ + struct gfs_alloc *i_alloc; /* In-place block reservation structure */ + uint64_t i_last_rg_alloc; /* Most recent blk alloc was fm this rgrp */ + + spinlock_t i_spin; + struct rw_semaphore i_rw_mutex; + + /* Cache of most-recently used buffers in indirect addressing chain */ + struct buffer_head *i_cache[GFS_MAX_META_HEIGHT]; + + unsigned int i_greedy; /* The amount of time to be greedy */ + unsigned long i_last_pfault; /* The time of the last page fault */ + struct address_space_operations gfs_file_aops; +}; + +/* + * GFS per-fd structure + */ + +#define GFF_DID_DIRECT_ALLOC (0) + +struct gfs_file { + unsigned long f_flags; /* GFF_... see above */ + + struct semaphore f_fl_lock; /* Lock to protect flock operations */ + struct gfs_holder f_fl_gh; /* Holder for this f_vfile's flock */ + + struct gfs_inode *f_inode; /* Incore GFS inode */ + struct file *f_vfile; /* Linux file struct */ +}; + +/* + * Unlinked inode log entry incore structure + */ + +#define ULF_NEW_UL (0) /* Part of new (being built) trans */ +#define ULF_INCORE_UL (1) /* Part of incore-committed trans */ +#define ULF_IC_LIST (2) +#define ULF_OD_LIST (3) +#define ULF_LOCK (4) /* Protects access to this structure */ + +struct gfs_unlinked { + struct list_head ul_list; /* Link to superblock's sd_unlinked_list */ + unsigned int ul_count; /* Usage count */ + + struct gfs_inum ul_inum; /* Formal inode #, block addr */ + unsigned long ul_flags; /* ULF_... */ + + /* Log elements map us to a particular set of log operations functions, + and to a particular transaction */ + struct gfs_log_element ul_new_le; /* New, not yet committed */ + struct gfs_log_element ul_incore_le; /* Committed to incore log */ + struct gfs_log_element ul_ondisk_le; /* Committed to ondisk log */ +}; + +/* + * Quota log element + * One for each logged change in a block alloc value affecting a given quota. + * Only one of these for a given quota within a given transaction; + * multiple changes, within one transaction, for a given quota will be + * combined into one log element. + */ +struct gfs_quota_le { + /* Log element maps us to a particular set of log operations functions, + and to a particular transaction */ + struct gfs_log_element ql_le; /* Generic log element structure */ + + struct gfs_quota_data *ql_data; /* The quota we're changing */ + struct list_head ql_data_list; /* Link to quota's log element list */ + + int64_t ql_change; /* # of blocks alloc'd (+) or freed (-) */ +}; + +/* + * Quota structure + * One for each user or group quota. + * Summarizes all block allocation activity for a given quota, and supports + * recording updates of current block alloc values in GFS' special quota + * file, including the journaling of these updates, encompassing + * multiple transactions and log dumps. + */ + +#define QDF_USER (0) /* User (1) vs. group (0) quota */ +#define QDF_OD_LIST (1) /* Waiting for sync to quota file */ +#define QDF_LOCK (2) /* Protects access to this structure */ + +struct gfs_quota_data { + struct list_head qd_list; /* Link to superblock's sd_quota_list */ + unsigned int qd_count; /* Usage count */ + + uint32_t qd_id; /* User or group ID number */ + unsigned long qd_flags; /* QDF_... */ + + /* This list is for non-log-dump transactions */ + struct list_head qd_le_list; /* List of gfs_quota_le log elements */ + + /* Summary of block alloc changes affecting this quota, in various + stages of logging & syncing changes to the special quota file */ + int64_t qd_change_new; /* New, not yet committed to in-core log*/ + int64_t qd_change_ic; /* Committed to in-core log */ + int64_t qd_change_od; /* Committed to on-disk log */ + int64_t qd_change_sync; /* Being synced to the in-place quota file */ + + struct gfs_quota_le qd_ondisk_ql; /* Log element for log dump */ + uint64_t qd_sync_gen; /* Sync-to-quota-file generation # */ + + /* Glock provides protection for quota, *and* provides + lock value block (LVB) communication, between nodes, of current + quota values. Shared lock -> LVB read. EX lock -> LVB write. */ + struct gfs_glock *qd_gl; /* glock for this quota */ + struct gfs_quota_lvb qd_qb; /* LVB (limit/warn/value) */ + + unsigned long qd_last_warn; /* Jiffies of last warning to user */ +}; + +/* + * Log Buffer descriptor structure. + * One for each block buffer recorded in the log. + * When beginning a new transaction, GFS pre-allocates a number of these, + * and puts them on transaction's tr_free_bufs list. + * Logged buffers are of two types: + * 1). Exact copies of buffers to be written to in-place location in FS. + * 2). Log-only buffers such as log headers and control blocks (e.g. tags). + * A gfs_log_buf is required for both types; the ones for log-only buffers + * contain NULL in lb_unlock, and get cleaned up after the log write. + * lb_bh is a "fake" buffer head that directs Linux block I/O to write the buf + * to the on-disk log location, rather than the on-disk in-place location. + * Used for both types. + * lb_unlock points to the "real" buffer head that directs Linux to write the + * buf to its regular on-disk in-place filesystem location. Once the commit + * to the on-disk log is finished, GFS unlocks the "real" buffer so it can be + * written to in-place block, or modified by another transaction. + * Used only for type 1). + */ +struct gfs_log_buf { + /* Link to one of the transaction structure's lists */ + struct list_head lb_list; /* Link to tr_free_bufs or tr_list */ + + struct buffer_head lb_bh; /* "Fake" bh; for the log block */ + struct buffer_head *lb_unlock; /* "Real" bh; for the in-place block */ +}; + +/* + * Transaction structure + * One for each transaction + * This coordinates the logging and flushing of written metadata. + */ + +#define TRF_LOG_DUMP (0x00000001) +#define TRF_DUMMY (0x00000002) + +struct gfs_trans { + + /* Link to various lists */ + struct list_head tr_list; /* Superblk's incore trans or AIL list*/ + + /* Initial creation stuff */ + + char *tr_file; /* Debug info: .c file creating trans */ + unsigned int tr_line; /* Debug info: codeline creating trans */ + + /* Reservations for on-disk space in journal. + Meta blocks are copies of in-place filesystem blocks. + Extra blocks are log-only (log header and control blocks) */ + unsigned int tr_mblks_asked; /* # of meta log blocks requested */ + unsigned int tr_eblks_asked; /* # of extra log blocks requested */ + unsigned int tr_seg_reserved; /* # of segments actually reserved */ + + struct gfs_holder *tr_t_gh; /* Glock holder for this transaction */ + + /* Stuff filled in during creation */ + + unsigned int tr_flags; /* TRF_... */ + struct list_head tr_elements; /* List of this trans' log elements */ + + /* Stuff modified during the commit */ + + /* When creating a new transaction, GFS pre-allocates as many of + these buffers and descriptor structures as it might need for + all loggable filesystem (meta)data, and log-control (log-only, not + going to filesystem in-place location) data going to on-disk log. + It keeps them on these "free" lists until they get used (and linked + into tr_bufs list, below) or "refunded" if not needed. */ + unsigned int tr_num_free_bufs; /* List of free gfs_log_buf structs */ + struct list_head tr_free_bufs; /* .. 1 for each log block */ + unsigned int tr_num_free_bmem; /* List of free fs-block-size buffers */ + struct list_head tr_free_bmem; /* .. for log-only (e.g. tag) blocks */ + + /* Logged transaction starts with a (first) log header at a segment + boundary, and fills contiguous blocks after that. Each segment + boundary block gets another log header. */ + uint64_t tr_log_head; /* The next log block # to fill */ + uint64_t tr_first_head; /* Trans' first log header's block # */ + + /* gfs_log_buf structs move from tr_free_bufs to here when being used */ + struct list_head tr_bufs; /* List of buffers going to the log */ + + /* Stuff that's part of the Active Items List (AIL) */ + + struct list_head tr_ail_bufs; /* List of buffers on AIL list */ + + /* # log elements of various types on tr_elements list */ + + unsigned int tr_num_gl; /* Glocks */ + unsigned int tr_num_buf; /* Buffers */ + unsigned int tr_num_iul; /* Unlinked inodes */ + unsigned int tr_num_ida; /* De-allocated inodes */ + unsigned int tr_num_q; /* Quotas */ +}; + +#define GFS_GLOCKD_DEFAULT (1) +#define GFS_GLOCKD_MAX (32) + +#define GFS_QUOTA_DEFAULT GFS_QUOTA_OFF +#define GFS_QUOTA_OFF 0 +#define GFS_QUOTA_ACCOUNT 1 +#define GFS_QUOTA_ON 2 + +#define GFS_DATA_DEFAULT GFS_DATA_ORDERED +#define GFS_DATA_WRITEBACK 1 +#define GFS_DATA_ORDERED 2 + + +struct gfs_args { + char ar_lockproto[GFS_LOCKNAME_LEN]; /* The name of the Lock Protocol */ + char ar_locktable[GFS_LOCKNAME_LEN]; /* The name of the Lock Table */ + char ar_hostdata[GFS_LOCKNAME_LEN]; /* The host specific data */ + + int ar_spectator; /* Don't get a journal because we're always RO. */ + /* + * GFS can invoke some flock and disk caching optimizations if it is + * not in a cluster, i.e. is a local filesystem. The chosen lock + * module tells GFS, at mount time, if it supports clustering. + * The nolock module is the only one that does not support clustering; + * it sets to TRUE the local_fs field in the struct lm_lockops. + * GFS can either optimize, or ignore the opportunity. + * The user controls behavior via the following mount options. + */ + int ar_ignore_local_fs; /* Don't optimize even if local_fs is TRUE */ + int ar_localflocks; /* Let the VFS do flock|fcntl locks for us */ + int ar_localcaching; /* Local-style caching (dangerous on multihost) */ + int ar_oopses_ok; /* Allow oopses */ + + int ar_debug; /* Oops on errors instead of trying to be graceful */ + int ar_upgrade; /* Upgrade ondisk/multihost format */ + + unsigned int ar_num_glockd; /* # of glock cleanup daemons to run + (more daemons => faster cleanup) */ + int ar_posix_acls; /* Enable posix acls */ + int ar_suiddir; /* suiddir support */ + int ar_noquota; /* Turn off quota support */ +}; + +struct gfs_tune { + spinlock_t gt_spin; + + unsigned int gt_ilimit1; + unsigned int gt_ilimit1_tries; + unsigned int gt_ilimit1_min; + unsigned int gt_ilimit2; + unsigned int gt_ilimit2_tries; + unsigned int gt_ilimit2_min; + unsigned int gt_demote_secs; /* Cache retention for unheld glock */ + unsigned int gt_incore_log_blocks; + unsigned int gt_jindex_refresh_secs; /* Check for new journal index */ + unsigned int gt_depend_secs; + + /* How often various daemons run (seconds) */ + unsigned int gt_scand_secs; /* Find unused glocks and inodes */ + unsigned int gt_recoverd_secs; /* Recover journal of crashed node */ + unsigned int gt_logd_secs; /* Update log tail as AIL flushes */ + unsigned int gt_quotad_secs; /* Sync changes to quota file, clean*/ + unsigned int gt_inoded_secs; /* Toss unused inodes */ + unsigned int gt_glock_purge; /* Purge glock */ + + unsigned int gt_quota_simul_sync; /* Max # quotavals to sync at once */ + unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */ + unsigned int gt_atime_quantum; /* Min secs between atime updates */ + unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ + unsigned int gt_quota_scale_num; /* Numerator */ + unsigned int gt_quota_scale_den; /* Denominator */ + unsigned int gt_quota_enforce; + unsigned int gt_quota_account; + unsigned int gt_new_files_jdata; + unsigned int gt_new_files_directio; + unsigned int gt_max_atomic_write; /* Split large writes into this size*/ + unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ + unsigned int gt_lockdump_size; + unsigned int gt_stall_secs; /* Detects trouble! */ + unsigned int gt_complain_secs; + unsigned int gt_reclaim_limit; /* Max # glocks in reclaim list */ + unsigned int gt_entries_per_readdir; + unsigned int gt_prefetch_secs; /* Usage window for prefetched glocks */ + unsigned int gt_statfs_slots; + unsigned int gt_max_mhc; /* Max # of meta headers in mhc cache */ + unsigned int gt_greedy_default; + unsigned int gt_greedy_quantum; + unsigned int gt_greedy_max; + unsigned int gt_rgrp_try_threshold; + unsigned int gt_statfs_fast; +}; + +/* + * One bucket of the filesystem's sd_gl_hash glock hash table. + * + * A gfs_glock links into a bucket's list via glock's gl_list member. + * + */ +struct gfs_gl_hash_bucket { + rwlock_t hb_lock; /* Protects list */ + struct list_head hb_list; /* List of glocks in this bucket */ +}; + +/* + * "Super Block" Data Structure + * One per mounted filesystem. + * This is the big instance structure that ties everything together for + * a given mounted filesystem. Each GFS mount has its own, supporting + * mounts of multiple GFS filesystems on each node. + * Pointer to this is usually seen as "sdp" throughout code. + * This is a very large structure, as structures go, in part because it + * contains arrays of hash buckets for various in-core caches. + */ + +#define SDF_JOURNAL_LIVE (0) /* Journaling is active (journal is writeable)*/ +#define SDF_SHUTDOWN (1) /* FS abnormaly shutdown */ + +/* (Re)mount options from Linux VFS */ +#define SDF_NOATIME (8) /* Don't change access time */ +#define SDF_ROFS (9) /* Read-only mode */ + +/* Journal log dump support */ +#define SDF_NEED_LOG_DUMP (10) /* Need to rewrite unlink and quota tags */ +#define SDF_FOUND_UL_DUMP (11) /* Recovery found unlinked tags */ +#define SDF_FOUND_Q_DUMP (12) /* Recovery found qutoa tags */ +#define SDF_IN_LOG_DUMP (13) /* Serializes log dumps */ + +/* Glock cache */ +#define GFS_GL_HASH_SHIFT (13) /* # hash buckets = 8K */ +#define GFS_GL_HASH_SIZE (1 << GFS_GL_HASH_SHIFT) +#define GFS_GL_HASH_MASK (GFS_GL_HASH_SIZE - 1) + +/* Meta header cache */ +#define GFS_MHC_HASH_SHIFT (10) /* # hash buckets = 1K */ +#define GFS_MHC_HASH_SIZE (1 << GFS_MHC_HASH_SHIFT) +#define GFS_MHC_HASH_MASK (GFS_MHC_HASH_SIZE - 1) + +/* Dependency cache */ +#define GFS_DEPEND_HASH_SHIFT (10) /* # hash buckets = 1K */ +#define GFS_DEPEND_HASH_SIZE (1 << GFS_DEPEND_HASH_SHIFT) +#define GFS_DEPEND_HASH_MASK (GFS_DEPEND_HASH_SIZE - 1) + +struct gfs_sbd { + struct gfs_sb sd_sb; /* GFS on-disk Super Block image */ + + struct super_block *sd_vfs; /* Linux VFS device independent sb */ + + struct gfs_args sd_args; /* Mount arguments */ + unsigned long sd_flags; /* SDF_... see above */ + + struct gfs_tune sd_tune; /* Filesystem tuning structure */ + + /* statfs */ + struct inode *sd_statfs_inode; + spinlock_t sd_statfs_spin; + struct gfs_statfs_change_host sd_statfs_master; + struct gfs_statfs_change_host sd_statfs_local; + unsigned long sd_statfs_sync_time; + + /* Resource group stuff */ + + struct gfs_inode *sd_riinode; /* Resource Index (rindex) inode */ + uint64_t sd_riinode_vn; /* Resource Index version # (detects + whether new rgrps have been added) */ + + struct list_head sd_rglist; /* List of all resource groups, + on-disk order */ + struct semaphore sd_rindex_lock;/* Serializes RIndex rereads */ + struct list_head sd_rg_mru_list;/* List of all resource groups, + most-recently-used (MRU) order */ + spinlock_t sd_rg_mru_lock; /* Protect mru list */ + struct list_head sd_rg_recent; /* List of rgrps from which blocks + were recently allocated */ + spinlock_t sd_rg_recent_lock; /* Protect recent list */ + struct gfs_rgrpd *sd_rg_forward;/* Next rgrp from which to attempt + a block alloc */ + spinlock_t sd_rg_forward_lock; /* Protect forward pointer */ + + unsigned int sd_rgcount; /* Total # of resource groups */ + + /* Constants computed on mount */ + + /* "bb" == "basic block" == 512Byte sector */ + uint32_t sd_fsb2bb; /* # 512B basic blocks in a FS block */ + uint32_t sd_fsb2bb_shift; /* Shift sector # to the right by + this to get FileSystem block addr */ + uint32_t sd_diptrs; /* Max # of block pointers in a dinode */ + uint32_t sd_inptrs; /* Max # of block pointers in an indirect blk */ + uint32_t sd_jbsize; /* Payload size (bytes) of a journaled metadata + block (GFS journals all meta blocks) */ + uint32_t sd_hash_bsize; /* sizeof(exhash hash block) */ + uint32_t sd_hash_bsize_shift; + uint32_t sd_hash_ptrs; /* Number of points in a hash block */ + uint32_t sd_max_dirres; /* Max blocks needed to add a directory entry */ + uint32_t sd_max_height; /* Max height of a file's tree */ + uint64_t sd_heightsize[GFS_MAX_META_HEIGHT]; + uint32_t sd_max_jheight; /* Max height, journaled file's tree */ + uint64_t sd_jheightsize[GFS_MAX_META_HEIGHT]; + + /* Lock Stuff */ + + /* Glock cache (all glocks currently held by this node for this FS) */ + struct gfs_gl_hash_bucket sd_gl_hash[GFS_GL_HASH_SIZE]; + + /* Glock reclaim support for scand and glockd */ + struct list_head sd_reclaim_list; /* List of glocks to reclaim */ + spinlock_t sd_reclaim_lock; + wait_queue_head_t sd_reclaim_wchan; + atomic_t sd_reclaim_count; /* # glocks on reclaim list */ + + /* Lock module tells us if we're first-to-mount, + which journal to use, etc. */ + struct lm_lockstruct sd_lockstruct; /* Info provided by lock module */ + + /* Other caches */ + + /* Meta-header cache (incore copies of on-disk meta headers) */ + struct list_head sd_mhc[GFS_MHC_HASH_SIZE]; /* hash buckets */ + struct list_head sd_mhc_single; /* Non-hashed list of all MHCs */ + spinlock_t sd_mhc_lock; + atomic_t sd_mhc_count; /* # MHCs in cache */ + + /* Dependency cache */ + struct list_head sd_depend[GFS_DEPEND_HASH_SIZE]; /* Hash buckets */ + spinlock_t sd_depend_lock; + atomic_t sd_depend_count; /* # dependencies in cache */ + + /* LIVE inter-node lock indicates that FS is mounted on at least + one node */ + struct gfs_holder sd_live_gh; /* Glock holder for LIVE lock */ + + /* For quiescing the filesystem */ + struct gfs_holder sd_freeze_gh; + struct semaphore sd_freeze_lock; + unsigned int sd_freeze_count; + + /* Inode Stuff */ + + struct gfs_inode *sd_rooti; /* FS's root inode */ + + /* Only 1 node at a time may rename (e.g. mv) directory from + one directory to another. */ + struct gfs_glock *sd_rename_gl; /* Rename glock */ + + /* Daemon stuff */ + + /* Scan for glocks and inodes to toss from memory */ + struct task_struct *sd_scand_process; /* Scand places on reclaim list*/ + struct task_struct *sd_glockd_process[GFS_GLOCKD_MAX]; + unsigned int sd_glockd_num; /* # of glockd procs to do reclaiming*/ + + /* Recover journal of a crashed node */ + struct task_struct *sd_recoverd_process; + + /* Update log tail as AIL gets flushed to in-place on-disk blocks */ + struct task_struct *sd_logd_process; + + /* Sync quota updates to disk, and clean up unused quota structs */ + struct task_struct *sd_quotad_process; + + /* Clean up unused inode structures */ + struct task_struct *sd_inoded_process; + + /* Log stuff */ + + /* Transaction lock protects the following from one another: + normal write transaction, journal replay (recovery), fs upgrade, + fs read-only => read/write and read/write => read-only conversions. + Also, acquiring the transaction lock in a state other than shared + causes all other machines in the cluster to sync out their dirty + data, mark their journal as being clean, and prevent any new FS + modifications from occuring (i.e. quiesces the FS). */ + struct gfs_glock *sd_trans_gl; /* Transaction glock structure */ + + struct gfs_inode *sd_jiinode; /* Journal index inode */ + uint64_t sd_jiinode_vn; /* Journal index version # (detects + if new journals have been added) */ + + unsigned int sd_journals; /* Number of journals in the FS */ + struct gfs_jindex *sd_jindex; /* Array of journal descriptors */ + struct semaphore sd_jindex_lock; + unsigned long sd_jindex_refresh_time; /* Poll for new journals (secs) */ + + struct gfs_jindex sd_jdesc; /* This machine's journal descriptor */ + struct gfs_holder sd_journal_gh; /* This machine's jrnl glock holder */ + + uint64_t sd_sequence; /* Assigned to xactions in order they commit */ + uint64_t sd_log_head; /* Block number of next journal write */ + uint64_t sd_log_wrap; + + spinlock_t sd_log_seg_lock; + unsigned int sd_log_seg_free; /* # of free segments in the log */ + unsigned int sd_log_seg_ail2; /* # of freeable segments in the log */ + struct list_head sd_log_seg_list; + wait_queue_head_t sd_log_seg_wait; + + /* "Active Items List" of transactions that have been flushed to + on-disk log, and are waiting for flush to in-place on-disk blocks */ + struct list_head sd_log_ail; /* "next" is head, "prev" is tail */ + + /* Transactions committed incore, but not yet flushed to on-disk log */ + struct list_head sd_log_incore; /* "Next" is newest, "prev" is oldest */ + unsigned int sd_log_buffers; /* # of buffers in the incore log */ + + struct rw_semaphore sd_log_lock; /* Lock for access to log values */ + + uint64_t sd_log_dump_last; + uint64_t sd_log_dump_last_wrap; + + /* + * Unlinked inode crap. + * List includes newly created, not-yet-linked inodes, + * as well as inodes that have been unlinked and are waiting + * to be de-allocated. + */ + struct list_head sd_unlinked_list; /* List of unlinked inodes */ + spinlock_t sd_unlinked_lock; /* Protects list and members */ + + atomic_t sd_unlinked_ic_count; + atomic_t sd_unlinked_od_count; + + /* Quota crap */ + + struct list_head sd_quota_list; /* List of all gfs_quota_data structs */ + spinlock_t sd_quota_lock; + + atomic_t sd_quota_count; /* # quotas on sd_quota_list */ + atomic_t sd_quota_od_count; /* # quotas waiting for sync to + special on-disk quota file */ + + struct gfs_inode *sd_qinode; /* Special on-disk quota file */ + + uint64_t sd_quota_sync_gen; /* Generation, incr when sync to file */ + unsigned long sd_quota_sync_time; /* Jiffies, last sync to quota file */ + + /* License crap */ + + struct gfs_inode *sd_linode; /* Special on-disk license file */ + + /* Recovery stuff */ + + /* Lock module tells GFS, via callback, when a journal needs recovery. + It stays on this list until recovery daemon performs recovery. */ + struct list_head sd_dirty_j; /* List of dirty journals */ + spinlock_t sd_dirty_j_lock; /* Protects list */ + + /* Statistics for 3 possible recovery actions for each buffer in log, + determined by comparing generation #s of logged block and + in-place block. Scope of stats is for one journal. */ + unsigned int sd_recovery_replays; /* newer than in-place; copy it */ + unsigned int sd_recovery_skips; /* older than in-place; ignore it */ + unsigned int sd_recovery_sames; /* same as in-place; ignore it */ + + /* Counters */ + + /* current quantities of various things */ + atomic_t sd_glock_count; /* # of gfs_glock structs alloc'd */ + atomic_t sd_glock_held_count; /* # of glocks locked by this node */ + atomic_t sd_inode_count; /* # of gfs_inode structs alloc'd */ + atomic_t sd_bufdata_count; /* # of gfs_bufdata structs alloc'd */ + + atomic_t sd_fh2dentry_misses; /* total # get_dentry misses */ + atomic_t sd_reclaimed; /* total # glocks reclaimed since mount */ + + /* total lock-related calls handled since mount */ + atomic_t sd_glock_nq_calls; + atomic_t sd_glock_dq_calls; + atomic_t sd_glock_prefetch_calls; + atomic_t sd_lm_lock_calls; + atomic_t sd_lm_unlock_calls; + atomic_t sd_lm_callbacks; + + atomic_t sd_lm_outstanding; + atomic_t sd_bio_reads; + atomic_t sd_bio_writes; + atomic_t sd_bio_outstanding; + + /* total calls from Linux VFS handled since mount */ + atomic_t sd_ops_address; + atomic_t sd_ops_dentry; + atomic_t sd_ops_export; + atomic_t sd_ops_file; + atomic_t sd_ops_inode; + atomic_t sd_ops_super; + atomic_t sd_ops_vm; + + char sd_fsname[256]; + char sd_table_name[256]; + char sd_proto_name[256]; + + struct kobject sd_kobj; + + /* Debugging crud */ + + unsigned long sd_last_warning; + + spinlock_t sd_ail_lock; + struct list_head sd_recovery_bufs; + + struct list_head sd_list; +}; + +#endif /* __INCORE_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/eattr.c +++ linux-2.6.27/ubuntu/gfs/eattr.c @@ -0,0 +1,2008 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "acl.h" +#include "dio.h" +#include "eaops.h" +#include "eattr.h" +#include "glock.h" +#include "inode.h" +#include "quota.h" +#include "rgrp.h" +#include "trans.h" + +/** + * ea_calc_size - returns the acutal number of bytes the request will take up + * (not counting any unstuffed data blocks) + * @sdp: + * @er: + * @size: + * + * Returns: TRUE if the EA should be stuffed + */ + +static int +ea_calc_size(struct gfs_sbd *sdp, + struct gfs_ea_request *er, + unsigned int *size) +{ + *size = GFS_EAREQ_SIZE_STUFFED(er); + if (*size <= sdp->sd_jbsize) + return TRUE; + + *size = GFS_EAREQ_SIZE_UNSTUFFED(sdp, er); + return FALSE; +} + +/** + * gfs_ea_check_size - + * @ip: + * @er: + * + * Returns: errno + */ + +int +gfs_ea_check_size(struct gfs_sbd *sdp, struct gfs_ea_request *er) +{ + unsigned int size; + + if (er->er_data_len > GFS_EA_MAX_DATA_LEN) + return -ERANGE; + + ea_calc_size(sdp, er, &size); + if (size > sdp->sd_jbsize) + return -ERANGE; /* This can only happen with 512 byte blocks */ + + return 0; +} + +typedef int (*ea_call_t) (struct gfs_inode *ip, + struct buffer_head *bh, + struct gfs_ea_header *ea, + struct gfs_ea_header *prev, + void *private); + +/** + * ea_foreach_i - + * @ip: + * @bh: + * @eabc: + * @data: + * + * Returns: errno + */ + +static int +ea_foreach_i(struct gfs_inode *ip, + struct buffer_head *bh, + ea_call_t ea_call, void *data) +{ + struct gfs_ea_header *ea, *prev = NULL; + int error = 0; + + if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_EA)) + return -EIO; + + for (ea = GFS_EA_BH2FIRST(bh);; prev = ea, ea = GFS_EA2NEXT(ea)) { + if (!GFS_EA_REC_LEN(ea)) + goto fail; + if (!(bh->b_data <= (char *)ea && + (char *)GFS_EA2NEXT(ea) <= + bh->b_data + bh->b_size)) + goto fail; + if (!GFS_EATYPE_VALID(ea->ea_type)) + goto fail; + + error = ea_call(ip, bh, ea, prev, data); + if (error) + return error; + + if (GFS_EA_IS_LAST(ea)) { + if ((char *)GFS_EA2NEXT(ea) != + bh->b_data + bh->b_size) + goto fail; + break; + } + } + + return error; + + fail: + gfs_consist_inode(ip); + return -EIO; +} + +/** + * ea_foreach - + * @ip: + * @ea_call: + * @data: + * + * Returns: errno + */ + +static int +ea_foreach(struct gfs_inode *ip, + ea_call_t ea_call, + void *data) +{ + struct buffer_head *bh; + int error; + + error = gfs_dread(ip->i_gl, ip->i_di.di_eattr, + DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + if (!(ip->i_di.di_flags & GFS_DIF_EA_INDIRECT)) + error = ea_foreach_i(ip, bh, ea_call, data); + else { + struct buffer_head *eabh; + uint64_t *eablk, *end; + + if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_IN)) { + error = -EIO; + goto out; + } + + eablk = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect)); + end = eablk + ip->i_sbd->sd_inptrs; + + for (; eablk < end; eablk++) { + uint64_t bn; + + if (!*eablk) + break; + bn = gfs64_to_cpu(*eablk); + + error = gfs_dread(ip->i_gl, bn, + DIO_START | DIO_WAIT, &eabh); + if (error) + break; + error = ea_foreach_i(ip, eabh, ea_call, data); + brelse(eabh); + if (error) + break; + } + } + + out: + brelse(bh); + + return error; +} + +struct ea_find { + struct gfs_ea_request *ef_er; + struct gfs_ea_location *ef_el; +}; + +/** + * ea_find_i - + * @ip: + * @bh: + * @ea: + * @prev: + * @private: + * + * Returns: -errno on error, 1 if search is over, + * 0 if search should continue + */ + +static int +ea_find_i(struct gfs_inode *ip, + struct buffer_head *bh, + struct gfs_ea_header *ea, + struct gfs_ea_header *prev, + void *private) +{ + struct ea_find *ef = (struct ea_find *)private; + struct gfs_ea_request *er = ef->ef_er; + + if (ea->ea_type == GFS_EATYPE_UNUSED) + return 0; + + if (ea->ea_type == er->er_type) { + if (ea->ea_name_len == er->er_name_len && + !memcmp(GFS_EA2NAME(ea), er->er_name, ea->ea_name_len)) { + struct gfs_ea_location *el = ef->ef_el; + get_bh(bh); + el->el_bh = bh; + el->el_ea = ea; + el->el_prev = prev; + return 1; + } + } + +#if 0 + else if ((ip->i_di.di_flags & GFS_DIF_EA_PACKED) && + er->er_type == GFS_EATYPE_SYS) + return 1; +#endif + + return 0; +} + +/** + * gfs_ea_find - find a matching eattr + * @ip: + * @er: + * @el: + * + * Returns: errno + */ + +int +gfs_ea_find(struct gfs_inode *ip, + struct gfs_ea_request *er, + struct gfs_ea_location *el) +{ + struct ea_find ef; + int error; + + ef.ef_er = er; + ef.ef_el = el; + + memset(el, 0, sizeof(struct gfs_ea_location)); + + error = ea_foreach(ip, ea_find_i, &ef); + if (error > 0) + return 0; + + return error; +} + +/** + * ea_dealloc_unstuffed - + * @ip: + * @bh: + * @ea: + * @prev: + * @private: + * + * Take advantage of the fact that all unstuffed blocks are + * allocated from the same RG. But watch, this may not always + * be true. + * + * Returns: errno + */ + +static int +ea_dealloc_unstuffed(struct gfs_inode *ip, + struct buffer_head *bh, + struct gfs_ea_header *ea, + struct gfs_ea_header *prev, + void *private) +{ + int *leave = (int *)private; + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_rgrpd *rgd; + struct gfs_holder rg_gh; + struct buffer_head *dibh; + uint64_t *dataptrs, bn = 0; + uint64_t bstart = 0; + unsigned int blen = 0; + unsigned int x; + int error; + + if (GFS_EA_IS_STUFFED(ea)) + return 0; + + dataptrs = GFS_EA2DATAPTRS(ea); + for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++) + if (*dataptrs) { + bn = gfs64_to_cpu(*dataptrs); + break; + } + if (!bn) + return 0; + + rgd = gfs_blk2rgrpd(sdp, bn); + if (!rgd) { + gfs_consist_inode(ip); + return -EIO; + } + + error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh); + if (error) + return error; + + error = gfs_trans_begin(sdp, 2 + rgd->rd_ri.ri_length, 1); + if (error) + goto out_gunlock; + + gfs_trans_add_bh(ip->i_gl, bh); + + dataptrs = GFS_EA2DATAPTRS(ea); + for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++) { + if (!*dataptrs) + break; + bn = gfs64_to_cpu(*dataptrs); + + if (bstart + blen == bn) + blen++; + else { + if (bstart) + gfs_metafree(ip, bstart, blen); + bstart = bn; + blen = 1; + } + + *dataptrs = 0; + if (!ip->i_di.di_blocks) + gfs_consist_inode(ip); + ip->i_di.di_blocks--; + } + if (bstart) + gfs_metafree(ip, bstart, blen); + + if (prev && !leave) { + uint32_t len; + + len = GFS_EA_REC_LEN(prev) + GFS_EA_REC_LEN(ea); + prev->ea_rec_len = cpu_to_gfs32(len); + + if (GFS_EA_IS_LAST(ea)) + prev->ea_flags |= GFS_EAFLAG_LAST; + } else { + ea->ea_type = GFS_EATYPE_UNUSED; + ea->ea_num_ptrs = 0; + } + + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + ip->i_di.di_ctime = get_seconds(); + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + gfs_trans_end(sdp); + + out_gunlock: + gfs_glock_dq_uninit(&rg_gh); + + return error; +} + +/** + * ea_remove_unstuffed - + * @ip: + * @bh: + * @ea: + * @prev: + * @leave: + * + * Returns: errno + */ + +static int +ea_remove_unstuffed(struct gfs_inode *ip, + struct buffer_head *bh, + struct gfs_ea_header *ea, + struct gfs_ea_header *prev, + int leave) +{ + struct gfs_alloc *al; + int error; + + al = gfs_alloc_get(ip); + + error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto out_alloc; + + error = gfs_rindex_hold(ip->i_sbd, &al->al_ri_gh); + if (error) + goto out_quota; + + error = ea_dealloc_unstuffed(ip, + bh, ea, prev, + (leave) ? &error : NULL); + + gfs_glock_dq_uninit(&al->al_ri_gh); + + out_quota: + gfs_quota_unhold_m(ip); + + out_alloc: + gfs_alloc_put(ip); + + return error; +} + +/**************************************************************************************************/ + +/** + * gfs_ea_repack_i - + * @ip: + * + * Returns: errno + */ + +int +gfs_ea_repack_i(struct gfs_inode *ip) +{ + return -ENOSYS; +} + +/** + * gfs_ea_repack - + * @ip: + * + * Returns: errno + */ + +int gfs_ea_repack(struct gfs_inode *ip) +{ + struct gfs_holder gh; + int error; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (error) + return error; + + /* Some sort of permissions checking would be nice */ + + error = gfs_ea_repack_i(ip); + + gfs_glock_dq_uninit(&gh); + + return error; +} + +struct ea_list { + struct gfs_ea_request *ei_er; + unsigned int ei_size; +}; + +/** + * ea_list_i - + * @ip: + * @bh: + * @ea: + * @prev: + * @private: + * + * Returns: errno + */ + +static int +ea_list_i(struct gfs_inode *ip, + struct buffer_head *bh, + struct gfs_ea_header *ea, + struct gfs_ea_header *prev, + void *private) +{ + struct ea_list *ei = (struct ea_list *)private; + struct gfs_ea_request *er = ei->ei_er; + unsigned int ea_size = gfs_ea_strlen(ea); + + if (ea->ea_type == GFS_EATYPE_UNUSED) + return 0; + + if (er->er_data_len) { + char *prefix; + unsigned int l; + char c = 0; + + if (ei->ei_size + ea_size > er->er_data_len) + return -ERANGE; + + switch (ea->ea_type) { + case GFS_EATYPE_USR: + prefix = "user."; + l = 5; + break; + case GFS_EATYPE_SYS: + prefix = "system."; + l = 7; + break; + case GFS_EATYPE_SECURITY: + prefix = "security."; + l = 9; + break; + default: + prefix = NULL; + l = 0; + break; + } + + if (prefix == NULL || l == 0) + return -EIO; + + memcpy(er->er_data + ei->ei_size, + prefix, l); + memcpy(er->er_data + ei->ei_size + l, + GFS_EA2NAME(ea), + ea->ea_name_len); + memcpy(er->er_data + ei->ei_size + + ea_size - 1, + &c, 1); + } + + ei->ei_size += ea_size; + + return 0; +} + +/** + * gfs_ea_list - + * @ip: + * @er: + * + * Returns: actual size of data on success, -errno on error + */ + +int +gfs_ea_list(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + struct gfs_holder i_gh; + int error; + + if (!er->er_data || !er->er_data_len) { + er->er_data = NULL; + er->er_data_len = 0; + } + + error = gfs_glock_nq_init(ip->i_gl, + LM_ST_SHARED, LM_FLAG_ANY, + &i_gh); + if (error) + return error; + + if (ip->i_di.di_eattr) { + struct ea_list ei = { .ei_er = er, .ei_size = 0 }; + + error = ea_foreach(ip, ea_list_i, &ei); + if (!error) + error = ei.ei_size; + } + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * ea_get_unstuffed - actually copies the unstuffed data into the + * request buffer + * @ip: + * @ea: + * @data: + * + * Returns: errno + */ + +static int +ea_get_unstuffed(struct gfs_inode *ip, struct gfs_ea_header *ea, + char *data) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head **bh; + unsigned int amount = GFS_EA_DATA_LEN(ea); + unsigned int nptrs = DIV_RU(amount, sdp->sd_jbsize); + uint64_t *dataptrs = GFS_EA2DATAPTRS(ea); + unsigned int x; + int error = 0; + + bh = kmalloc(nptrs * sizeof(struct buffer_head *), GFP_KERNEL); + if (!bh) + return -ENOMEM; + + for (x = 0; x < nptrs; x++) { + error = gfs_dread(ip->i_gl, gfs64_to_cpu(*dataptrs), + DIO_START, bh + x); + if (error) { + while (x--) + brelse(bh[x]); + goto out; + } + dataptrs++; + } + + for (x = 0; x < nptrs; x++) { + error = gfs_dreread(sdp, bh[x], DIO_WAIT); + if (error) { + for (; x < nptrs; x++) + brelse(bh[x]); + goto out; + } + if (gfs_metatype_check2(sdp, bh[x], + GFS_METATYPE_ED, GFS_METATYPE_EA)) { + for (; x < nptrs; x++) + brelse(bh[x]); + error = -EIO; + goto out; + } + + memcpy(data, + bh[x]->b_data + sizeof(struct gfs_meta_header), + (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize); + + amount -= sdp->sd_jbsize; + data += sdp->sd_jbsize; + + brelse(bh[x]); + } + + out: + kfree(bh); + + return error; +} + +/** + * gfs_ea_get_copy - + * @ip: + * @el: + * @data: + * + * Returns: errno + */ + +int +gfs_ea_get_copy(struct gfs_inode *ip, + struct gfs_ea_location *el, + char *data) +{ + if (GFS_EA_IS_STUFFED(el->el_ea)) { + memcpy(data, + GFS_EA2DATA(el->el_ea), + GFS_EA_DATA_LEN(el->el_ea)); + return 0; + } else + return ea_get_unstuffed(ip, el->el_ea, data); +} + +/** + * gfs_ea_get_i - + * @ip: + * @er: + * + * Returns: actual size of data on success, -errno on error + */ + +int +gfs_ea_get_i(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + struct gfs_ea_location el; + int error; + + if (!ip->i_di.di_eattr) + return -ENODATA; + + error = gfs_ea_find(ip, er, &el); + if (error) + return error; + if (!el.el_ea) + return -ENODATA; + + if (er->er_data_len) { + if (GFS_EA_DATA_LEN(el.el_ea) > er->er_data_len) + error = -ERANGE; + else + error = gfs_ea_get_copy(ip, &el, er->er_data); + } + if (!error) + error = GFS_EA_DATA_LEN(el.el_ea); + + brelse(el.el_bh); + + return error; +} + +/** + * gfs_ea_get - + * @ip: + * @er: + * + * Returns: actual size of data on success, -errno on error + */ + +int +gfs_ea_get(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + struct gfs_holder i_gh; + int error; + + if (!er->er_name_len || + er->er_name_len > GFS_EA_MAX_NAME_LEN) + return -EINVAL; + if (!er->er_data || !er->er_data_len) { + er->er_data = NULL; + er->er_data_len = 0; + } + + error = gfs_glock_nq_init(ip->i_gl, + LM_ST_SHARED, LM_FLAG_ANY, + &i_gh); + if (error) + return error; + + error = gfs_ea_ops[er->er_type]->eo_get(ip, er); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * ea_alloc_blk - allocates a new block for extended attributes. + * @ip: A pointer to the inode that's getting extended attributes + * @bhp: + * + * Returns: errno + */ + +static int +ea_alloc_blk(struct gfs_inode *ip, + struct buffer_head **bhp) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_ea_header *ea; + uint64_t block; + int error; + + error = gfs_metaalloc(ip, &block); + if (error) + return error; + + error = gfs_dread(ip->i_gl, block, + DIO_NEW | DIO_START | DIO_WAIT, bhp); + if (error) + return error; + + gfs_trans_add_bh(ip->i_gl, *bhp); + gfs_metatype_set(*bhp, GFS_METATYPE_EA, GFS_FORMAT_EA); + + ea = GFS_EA_BH2FIRST(*bhp); + ea->ea_rec_len = cpu_to_gfs32(sdp->sd_jbsize); + ea->ea_type = GFS_EATYPE_UNUSED; + ea->ea_flags = GFS_EAFLAG_LAST; + ea->ea_num_ptrs = 0; + + ip->i_di.di_blocks++; + + return 0; +} + +/** + * ea_write - writes the request info to an ea, creating new blocks if + * necessary + * @ip: inode that is being modified + * @ea: the location of the new ea in a block + * @er: the write request + * + * Note: does not update ea_rec_len or the GFS_EAFLAG_LAST bin of ea_flags + * + * returns : errno + */ + +static int +ea_write(struct gfs_inode *ip, + struct gfs_ea_header *ea, + struct gfs_ea_request *er) +{ + struct gfs_sbd *sdp = ip->i_sbd; + + ea->ea_data_len = cpu_to_gfs32(er->er_data_len); + ea->ea_name_len = er->er_name_len; + ea->ea_type = er->er_type; + ea->ea_pad = 0; + + memcpy(GFS_EA2NAME(ea), er->er_name, er->er_name_len); + + if (GFS_EAREQ_SIZE_STUFFED(er) <= sdp->sd_jbsize) { + ea->ea_num_ptrs = 0; + memcpy(GFS_EA2DATA(ea), er->er_data, er->er_data_len); + } else { + uint64_t *dataptr = GFS_EA2DATAPTRS(ea); + const char *data = er->er_data; + unsigned int data_len = er->er_data_len; + unsigned int copy; + unsigned int x; + + ea->ea_num_ptrs = DIV_RU(er->er_data_len, sdp->sd_jbsize); + for (x = 0; x < ea->ea_num_ptrs; x++) { + struct buffer_head *bh; + uint64_t block; + int error; + + error = gfs_metaalloc(ip, &block); + if (error) + return error; + + error = gfs_dread(ip->i_gl, block, + DIO_NEW | DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + gfs_trans_add_bh(ip->i_gl, bh); + gfs_metatype_set(bh, GFS_METATYPE_ED, GFS_FORMAT_ED); + ip->i_di.di_blocks++; + + copy = (data_len > sdp->sd_jbsize) ? sdp->sd_jbsize : data_len; + memcpy(bh->b_data + sizeof(struct gfs_meta_header), + data, + copy); + + *dataptr++ = cpu_to_gfs64((uint64_t)bh->b_blocknr); + data += copy; + data_len -= copy; + + brelse(bh); + } + + gfs_assert_withdraw(sdp, !data_len); + } + + return 0; +} + +typedef int (*ea_skeleton_call_t) (struct gfs_inode *ip, + struct gfs_ea_request *er, + void *private); +/** + * ea_alloc_skeleton - + * @ip: + * @er: + * @blks: + * @skeleton_call: + * @private: + * + * Returns: errno + */ + +static int +ea_alloc_skeleton(struct gfs_inode *ip, struct gfs_ea_request *er, + unsigned int blks, + ea_skeleton_call_t skeleton_call, void *private) +{ + struct gfs_alloc *al; + struct buffer_head *dibh; + int error; + + al = gfs_alloc_get(ip); + + error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto out; + + error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + if (error) + goto out_gunlock_q; + + al->al_requested_meta = blks; + + error = gfs_inplace_reserve(ip); + if (error) + goto out_gunlock_q; + + /* Trans may require: + A modified dinode, multiple EA metadata blocks, and all blocks for a RG + bitmap */ + + error = gfs_trans_begin(ip->i_sbd, + 1 + blks + al->al_rgd->rd_ri.ri_length, 1); + if (error) + goto out_ipres; + + error = skeleton_call(ip, er, private); + if (error) + goto out_end_trans; + + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + if (er->er_mode) { + ip->i_vnode->i_mode = er->er_mode; + gfs_inode_attr_out(ip); + } + ip->i_di.di_ctime = get_seconds(); + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + out_end_trans: + gfs_trans_end(ip->i_sbd); + + out_ipres: + gfs_inplace_release(ip); + + out_gunlock_q: + gfs_quota_unlock_m(ip); + + out: + gfs_alloc_put(ip); + + return error; +} + +/** + * ea_init_i - initializes a new eattr block + * @ip: + * @er: + * @private: + * + * Returns: errno + */ + +static int +ea_init_i(struct gfs_inode *ip, + struct gfs_ea_request *er, + void *private) +{ + struct buffer_head *bh; + int error; + + error = ea_alloc_blk(ip, &bh); + if (error) + return error; + + ip->i_di.di_eattr = bh->b_blocknr; + error = ea_write(ip, GFS_EA_BH2FIRST(bh), er); + + brelse(bh); + + return error; +} + +/** + * ea_init - initializes a new eattr block + * @ip: + * @er: + * + * Returns: errno + */ + +static int +ea_init(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + unsigned int jbsize = ip->i_sbd->sd_jbsize; + unsigned int blks = 1; + + if (GFS_EAREQ_SIZE_STUFFED(er) > jbsize) + blks += DIV_RU(er->er_data_len, jbsize); + + return ea_alloc_skeleton(ip, er, + blks, + ea_init_i, NULL); +} + +/** + * ea_split_ea - + * @ea: + * + * Returns: the new ea + */ + +static struct gfs_ea_header * +ea_split_ea(struct gfs_ea_header *ea) +{ + uint32_t ea_size = GFS_EA_SIZE(ea); + struct gfs_ea_header *new = (struct gfs_ea_header *)((char *)ea + ea_size); + uint32_t new_size = GFS_EA_REC_LEN(ea) - ea_size; + int last = ea->ea_flags & GFS_EAFLAG_LAST; + + ea->ea_rec_len = cpu_to_gfs32(ea_size); + ea->ea_flags ^= last; + + new->ea_rec_len = cpu_to_gfs32(new_size); + new->ea_flags = last; + + return new; +} + +/** + * ea_set_remove_stuffed - + * @ip: + * @ea: + * + */ + +static void +ea_set_remove_stuffed(struct gfs_inode *ip, struct gfs_ea_location *el) +{ + struct gfs_ea_header *ea = el->el_ea; + struct gfs_ea_header *prev = el->el_prev; + uint32_t len; + + gfs_trans_add_bh(ip->i_gl, el->el_bh); + + if (!prev || !GFS_EA_IS_STUFFED(ea)) { + ea->ea_type = GFS_EATYPE_UNUSED; + return; + } else if (GFS_EA2NEXT(prev) != ea) { + prev = GFS_EA2NEXT(prev); + gfs_assert_withdraw(ip->i_sbd, GFS_EA2NEXT(prev) == ea); + } + + len = GFS_EA_REC_LEN(prev) + GFS_EA_REC_LEN(ea); + prev->ea_rec_len = cpu_to_gfs32(len); + + if (GFS_EA_IS_LAST(ea)) + prev->ea_flags |= GFS_EAFLAG_LAST; +} + +struct ea_set { + int ea_split; + + struct gfs_ea_request *es_er; + struct gfs_ea_location *es_el; + + struct buffer_head *es_bh; + struct gfs_ea_header *es_ea; +}; + +/** + * ea_set_simple_noalloc - + * @ip: + * @ea: + * @es: + * + * Returns: errno + */ + +static int +ea_set_simple_noalloc(struct gfs_inode *ip, + struct buffer_head *bh, + struct gfs_ea_header *ea, + struct ea_set *es) +{ + struct gfs_ea_request *er = es->es_er; + int error; + + error = gfs_trans_begin(ip->i_sbd, 3, 0); + if (error) + return error; + + gfs_trans_add_bh(ip->i_gl, bh); + + if (es->ea_split) + ea = ea_split_ea(ea); + + ea_write(ip, ea, er); + + if (es->es_el) + ea_set_remove_stuffed(ip, es->es_el); + + { + struct buffer_head *dibh; + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + if (er->er_mode) { + ip->i_vnode->i_mode = er->er_mode; + gfs_inode_attr_out(ip); + } + ip->i_di.di_ctime = get_seconds(); + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + } + + gfs_trans_end(ip->i_sbd); + + return error; +} + +/** + * ea_set_simple_alloc - + * @ip: + * @er: + * @private: + * + * Returns: errno + */ + +static int +ea_set_simple_alloc(struct gfs_inode *ip, + struct gfs_ea_request *er, + void *private) +{ + struct ea_set *es = (struct ea_set *)private; + struct gfs_ea_header *ea = es->es_ea; + int error; + + gfs_trans_add_bh(ip->i_gl, es->es_bh); + + if (es->ea_split) + ea = ea_split_ea(ea); + + error = ea_write(ip, ea, er); + if (error) + return error; + + if (es->es_el) + ea_set_remove_stuffed(ip, es->es_el); + + return 0; +} + +/** + * ea_set_simple - + * @ip: + * @el: + * + * Returns: errno + */ + +static int +ea_set_simple(struct gfs_inode *ip, + struct buffer_head *bh, + struct gfs_ea_header *ea, + struct gfs_ea_header *prev, + void *private) +{ + struct ea_set *es = (struct ea_set *)private; + unsigned int size; + int stuffed; + int error; + + stuffed = ea_calc_size(ip->i_sbd, es->es_er, &size); + + if (ea->ea_type == GFS_EATYPE_UNUSED) { + if (GFS_EA_REC_LEN(ea) < size) + return 0; + if (!GFS_EA_IS_STUFFED(ea)) { + error = ea_remove_unstuffed(ip, bh, ea, prev, TRUE); + if (error) + return error; + } + es->ea_split = FALSE; + } else if (GFS_EA_REC_LEN(ea) - GFS_EA_SIZE(ea) >= size) + es->ea_split = TRUE; + else + return 0; + + if (stuffed) { + error = ea_set_simple_noalloc(ip, bh, ea, es); + if (error) + return error; + } else { + unsigned int blks; + + es->es_bh = bh; + es->es_ea = ea; + blks = 2 + DIV_RU(es->es_er->er_data_len, + ip->i_sbd->sd_jbsize); + + error = ea_alloc_skeleton(ip, es->es_er, + blks, + ea_set_simple_alloc, es); + if (error) + return error; + } + + return 1; +} + +/** + * ea_set_block - + * @ip: + * @er: + * @private: + * + * Returns: errno + */ + +static int +ea_set_block(struct gfs_inode *ip, + struct gfs_ea_request *er, + void *private) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *indbh, *newbh; + uint64_t *eablk; + int error; + + if (ip->i_di.di_flags & GFS_DIF_EA_INDIRECT) { + uint64_t *end; + + error = gfs_dread(ip->i_gl, ip->i_di.di_eattr, + DIO_START | DIO_WAIT, &indbh); + if (error) + return error; + + if (gfs_metatype_check(sdp, indbh, GFS_METATYPE_IN)) { + error = -EIO; + goto out; + } + + eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect)); + end = eablk + sdp->sd_inptrs; + + for (; eablk < end; eablk++) + if (!*eablk) + break; + + if (eablk == end) { + error = -ENOSPC; + goto out; + } + + gfs_trans_add_bh(ip->i_gl, indbh); + } else { + uint64_t blk; + + error = gfs_metaalloc(ip, &blk); + if (error) + return error; + + error = gfs_dread(ip->i_gl, blk, + DIO_NEW | DIO_START | DIO_WAIT, &indbh); + if (error) + return error; + + gfs_trans_add_bh(ip->i_gl, indbh); + gfs_metatype_set(indbh, GFS_METATYPE_IN, GFS_FORMAT_IN); + gfs_buffer_clear_tail(indbh, sizeof(struct gfs_meta_header)); + + eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect)); + *eablk = cpu_to_gfs64(ip->i_di.di_eattr); + ip->i_di.di_eattr = blk; + ip->i_di.di_flags |= GFS_DIF_EA_INDIRECT; + ip->i_di.di_blocks++; + + eablk++; + } + + error = ea_alloc_blk(ip, &newbh); + if (error) + goto out; + + *eablk = cpu_to_gfs64((uint64_t)newbh->b_blocknr); + error = ea_write(ip, GFS_EA_BH2FIRST(newbh), er); + brelse(newbh); + if (error) + goto out; + + if (private) + ea_set_remove_stuffed(ip, (struct gfs_ea_location *)private); + + out: + brelse(indbh); + + return error; +} + +/** + * ea_set_i - + * @ip: + * @el: + * + * Returns: errno + */ + +static int +ea_set_i(struct gfs_inode *ip, + struct gfs_ea_request *er, + struct gfs_ea_location *el) +{ + { + struct ea_set es; + int error; + + memset(&es, 0, sizeof(struct ea_set)); + es.es_er = er; + es.es_el = el; + + error = ea_foreach(ip, ea_set_simple, &es); + if (error > 0) + return 0; + if (error) + return error; + } + { + unsigned int blks = 2; + if (!(ip->i_di.di_flags & GFS_DIF_EA_INDIRECT)) + blks++; + if (GFS_EAREQ_SIZE_STUFFED(er) > ip->i_sbd->sd_jbsize) + blks += DIV_RU(er->er_data_len, + ip->i_sbd->sd_jbsize); + + return ea_alloc_skeleton(ip, er, blks, ea_set_block, el); + } +} + +/** + * ea_set_remove_unstuffed - + * @ip: + * @el: + * + * Returns: errno + */ + +static int +ea_set_remove_unstuffed(struct gfs_inode *ip, struct gfs_ea_location *el) +{ + if (el->el_prev && GFS_EA2NEXT(el->el_prev) != el->el_ea) { + el->el_prev = GFS_EA2NEXT(el->el_prev); + gfs_assert_withdraw(ip->i_sbd, + GFS_EA2NEXT(el->el_prev) == el->el_ea); + } + + return ea_remove_unstuffed(ip, el->el_bh, el->el_ea, el->el_prev, FALSE); +} + +/** + * gfs_ea_set_i - + * @ip: + * @er: + * + * Returns: errno + */ + +int +gfs_ea_set_i(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + struct gfs_ea_location el; + int error; + + if (!ip->i_di.di_eattr) { + if (er->er_flags & XATTR_REPLACE) + return -ENODATA; + return ea_init(ip, er); + } + + error = gfs_ea_find(ip, er, &el); + if (error) + return error; + + if (el.el_ea) { + if (IS_APPEND(ip->i_vnode)) { + brelse(el.el_bh); + return -EPERM; + } + + error = -EEXIST; + if (!(er->er_flags & XATTR_CREATE)) { + int unstuffed = !GFS_EA_IS_STUFFED(el.el_ea); + error = ea_set_i(ip, er, &el); + if (!error && unstuffed) + ea_set_remove_unstuffed(ip, &el); + } + + brelse(el.el_bh); + } else { + error = -ENODATA; + if (!(er->er_flags & XATTR_REPLACE)) + error = ea_set_i(ip, er, NULL); + } + + return error; +} + +/** + * gfs_ea_set - + * @ip: + * @er: + * + * Returns: errno + */ + +int +gfs_ea_set(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + struct gfs_holder i_gh; + int error; + + if (!er->er_name_len || + er->er_name_len > GFS_EA_MAX_NAME_LEN) + return -EINVAL; + if (!er->er_data || !er->er_data_len) { + er->er_data = NULL; + er->er_data_len = 0; + } + error = gfs_ea_check_size(ip->i_sbd, er); + if (error) + return error; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + if (error) + return error; + + if (IS_IMMUTABLE(ip->i_vnode)) + error = -EPERM; + else + error = gfs_ea_ops[er->er_type]->eo_set(ip, er); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * ea_remove_stuffed - + * @ip: + * @el: + * @mode: + * + * Returns: errno + */ + +static int +ea_remove_stuffed(struct gfs_inode *ip, + struct gfs_ea_location *el) +{ + struct gfs_ea_header *ea = el->el_ea; + struct gfs_ea_header *prev = el->el_prev; + int error; + + error = gfs_trans_begin(ip->i_sbd, 2, 0); + if (error) + return error; + + gfs_trans_add_bh(ip->i_gl, el->el_bh); + + if (prev) { + uint32_t len; + + len = GFS_EA_REC_LEN(prev) + GFS_EA_REC_LEN(ea); + prev->ea_rec_len = cpu_to_gfs32(len); + + if (GFS_EA_IS_LAST(ea)) + prev->ea_flags |= GFS_EAFLAG_LAST; + } else + ea->ea_type = GFS_EATYPE_UNUSED; + + { + struct buffer_head *dibh; + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + ip->i_di.di_ctime = get_seconds(); + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + } + + gfs_trans_end(ip->i_sbd); + + return error; +} + +/** + * gfs_ea_remove_i - + * @ip: + * @er: + * + * Returns: errno + */ + +int +gfs_ea_remove_i(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + struct gfs_ea_location el; + int error; + + if (!ip->i_di.di_eattr) + return -ENODATA; + + error = gfs_ea_find(ip, er, &el); + if (error) + return error; + if (!el.el_ea) + return -ENODATA; + + if (GFS_EA_IS_STUFFED(el.el_ea)) + error = ea_remove_stuffed(ip, &el); + else + error = ea_remove_unstuffed(ip, el.el_bh, el.el_ea, el.el_prev, FALSE); + + brelse(el.el_bh); + + return error; +} + +/** + * gfs_ea_remove - sets (or creates or replaces) an extended attribute + * @ip: pointer to the inode of the target file + * @er: request information + * + * Returns: errno + */ + +int +gfs_ea_remove(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + struct gfs_holder i_gh; + int error; + + if (!er->er_name_len || + er->er_name_len > GFS_EA_MAX_NAME_LEN) + return -EINVAL; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + if (error) + return error; + + if (IS_IMMUTABLE(ip->i_vnode) || IS_APPEND(ip->i_vnode)) + error = -EPERM; + else + error = gfs_ea_ops[er->er_type]->eo_remove(ip, er); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_ea_acl_init - + * @ip: + * @er: + * + * Returns: errno + */ + +int +gfs_ea_acl_init(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + int error; + + if (!ip->i_di.di_eattr) + return ea_init_i(ip, er, NULL); + + { + struct buffer_head *bh; + struct gfs_ea_header *ea; + unsigned int size; + + ea_calc_size(ip->i_sbd, er, &size); + + error = gfs_dread(ip->i_gl, ip->i_di.di_eattr, + DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_EA)) { + brelse(bh); + return -EIO; + } + + ea = GFS_EA_BH2FIRST(bh); + if (GFS_EA_REC_LEN(ea) - GFS_EA_SIZE(ea) >= size) { + ea = ea_split_ea(ea); + ea_write(ip, ea, er); + brelse(bh); + return 0; + } + + brelse(bh); + } + + error = ea_set_block(ip, er, NULL); + gfs_assert_withdraw(ip->i_sbd, error != -ENOSPC); + if (error) + return error; + + { + struct buffer_head *dibh; + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + return error; + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + return error; +} + +/** + * ea_acl_chmod_unstuffed - + * @ip: + * @ea: + * @data: + * + * Returns: errno + */ + +static int +ea_acl_chmod_unstuffed(struct gfs_inode *ip, + struct gfs_ea_header *ea, + char *data) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head **bh; + unsigned int amount = GFS_EA_DATA_LEN(ea); + unsigned int nptrs = DIV_RU(amount, sdp->sd_jbsize); + uint64_t *dataptrs = GFS_EA2DATAPTRS(ea); + unsigned int x; + int error; + + bh = kmalloc(nptrs * sizeof(struct buffer_head *), GFP_KERNEL); + if (!bh) + return -ENOMEM; + + error = gfs_trans_begin(sdp, 1 + nptrs, 0); + if (error) + goto out; + + for (x = 0; x < nptrs; x++) { + error = gfs_dread(ip->i_gl, gfs64_to_cpu(*dataptrs), + DIO_START, bh + x); + if (error) { + while (x--) + brelse(bh[x]); + goto fail; + } + dataptrs++; + } + + for (x = 0; x < nptrs; x++) { + error = gfs_dreread(sdp, bh[x], DIO_WAIT); + if (error) { + for (; x < nptrs; x++) + brelse(bh[x]); + goto fail; + } + if (gfs_metatype_check2(sdp, bh[x], + GFS_METATYPE_ED, GFS_METATYPE_EA)) { + for (; x < nptrs; x++) + brelse(bh[x]); + error = -EIO; + goto fail; + } + + gfs_trans_add_bh(ip->i_gl, bh[x]); + + memcpy(bh[x]->b_data + sizeof(struct gfs_meta_header), + data, + (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize); + + amount -= sdp->sd_jbsize; + data += sdp->sd_jbsize; + + brelse(bh[x]); + } + + out: + kfree(bh); + + return error; + + fail: + gfs_trans_end(sdp); + kfree(bh); + + return error; +} + +/** + * gfs_ea_acl_chmod - + * @ip: + * @el: + * @attr: + * @data: + * + * Returns: errno + */ + +int +gfs_ea_acl_chmod(struct gfs_inode *ip, struct gfs_ea_location *el, + struct iattr *attr, char *data) +{ + struct buffer_head *dibh; + int error; + + if (GFS_EA_IS_STUFFED(el->el_ea)) { + error = gfs_trans_begin(ip->i_sbd, 2, 0); + if (error) + return error; + + gfs_trans_add_bh(ip->i_gl, el->el_bh); + memcpy(GFS_EA2DATA(el->el_ea), + data, + GFS_EA_DATA_LEN(el->el_ea)); + } else + error = ea_acl_chmod_unstuffed(ip, el->el_ea, data); + + if (error) + return error; + + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + error = inode_setattr(ip->i_vnode, attr); + gfs_assert_warn(ip->i_sbd, !error); + gfs_inode_attr_out(ip); + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + gfs_trans_end(ip->i_sbd); + + return error; +} + +/** + * ea_dealloc_indirect - + * @ip: + * + * Returns: errno + */ + +static int +ea_dealloc_indirect(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_rgrp_list rlist; + struct buffer_head *indbh, *dibh; + uint64_t *eablk, *end; + unsigned int rg_blocks = 0; + uint64_t bstart = 0; + unsigned int blen = 0; + unsigned int x; + int error; + + memset(&rlist, 0, sizeof(struct gfs_rgrp_list)); + + error = gfs_dread(ip->i_gl, ip->i_di.di_eattr, + DIO_START | DIO_WAIT, &indbh); + if (error) + return error; + + if (gfs_metatype_check(sdp, indbh, GFS_METATYPE_IN)) { + error = -EIO; + goto out; + } + + eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect)); + end = eablk + sdp->sd_inptrs; + + for (; eablk < end; eablk++) { + uint64_t bn; + + if (!*eablk) + break; + bn = gfs64_to_cpu(*eablk); + + if (bstart + blen == bn) + blen++; + else { + if (bstart) + gfs_rlist_add(sdp, &rlist, bstart); + bstart = bn; + blen = 1; + } + } + if (bstart) + gfs_rlist_add(sdp, &rlist, bstart); + else + goto out; + + gfs_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); + + for (x = 0; x < rlist.rl_rgrps; x++) { + struct gfs_rgrpd *rgd; + rgd = get_gl2rgd(rlist.rl_ghs[x].gh_gl); + rg_blocks += rgd->rd_ri.ri_length; + } + + error = gfs_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); + if (error) + goto out_rlist_free; + + error = gfs_trans_begin(sdp, 2 + rg_blocks, 1); + if (error) + goto out_gunlock; + + gfs_trans_add_bh(ip->i_gl, indbh); + + eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect)); + bstart = 0; + blen = 0; + + for (; eablk < end; eablk++) { + uint64_t bn; + + if (!*eablk) + break; + bn = gfs64_to_cpu(*eablk); + + if (bstart + blen == bn) + blen++; + else { + if (bstart) + gfs_metafree(ip, bstart, blen); + bstart = bn; + blen = 1; + } + + *eablk = 0; + if (!ip->i_di.di_blocks) + gfs_consist_inode(ip); + ip->i_di.di_blocks--; + } + if (bstart) + gfs_metafree(ip, bstart, blen); + + ip->i_di.di_flags &= ~GFS_DIF_EA_INDIRECT; + + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + gfs_trans_end(sdp); + + out_gunlock: + gfs_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs); + + out_rlist_free: + gfs_rlist_free(&rlist); + + out: + brelse(indbh); + + return error; +} + +/** + * ea_dealloc_block - + * @ip: + * + * Returns: errno + */ + +static int +ea_dealloc_block(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + struct gfs_rgrpd *rgd; + struct buffer_head *dibh; + int error; + + rgd = gfs_blk2rgrpd(sdp, ip->i_di.di_eattr); + if (!rgd) { + gfs_consist_inode(ip); + return -EIO; + } + + error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &al->al_rgd_gh); + if (error) + return error; + + error = gfs_trans_begin(sdp, 1 + rgd->rd_ri.ri_length, 1); + if (error) + goto out_gunlock; + + gfs_metafree(ip, ip->i_di.di_eattr, 1); + + ip->i_di.di_eattr = 0; + if (!ip->i_di.di_blocks) + gfs_consist_inode(ip); + ip->i_di.di_blocks--; + + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + gfs_trans_end(sdp); + + out_gunlock: + gfs_glock_dq_uninit(&al->al_rgd_gh); + + return error; +} + +/** + * gfs_ea_dealloc - deallocate the extended attribute fork + * @ip: the inode + * + * Returns: errno + */ + +int +gfs_ea_dealloc(struct gfs_inode *ip) +{ + struct gfs_alloc *al; + int error; + + al = gfs_alloc_get(ip); + + error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto out_alloc; + + error = gfs_rindex_hold(ip->i_sbd, &al->al_ri_gh); + if (error) + goto out_quota; + + error = ea_foreach(ip, ea_dealloc_unstuffed, NULL); + if (error) + goto out_rindex; + + if (ip->i_di.di_flags & GFS_DIF_EA_INDIRECT) { + error = ea_dealloc_indirect(ip); + if (error) + goto out_rindex; + } + + error = ea_dealloc_block(ip); + + out_rindex: + gfs_glock_dq_uninit(&al->al_ri_gh); + + out_quota: + gfs_quota_unhold_m(ip); + + out_alloc: + gfs_alloc_put(ip); + + return error; +} + +/** + * gfs_get_eattr_meta - return all the eattr blocks of a file + * @dip: the directory + * @ub: the structure representing the user buffer to copy to + * + * Returns: errno + */ + +int +gfs_get_eattr_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub) +{ + struct buffer_head *bh; + int error; + + error = gfs_dread(ip->i_gl, ip->i_di.di_eattr, + DIO_START | DIO_WAIT, &bh); + if (error) + return error; + + gfs_add_bh_to_ub(ub, bh); + + if (ip->i_di.di_flags & GFS_DIF_EA_INDIRECT) { + struct buffer_head *eabh; + uint64_t *eablk, *end; + + if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_IN)) { + error = -EIO; + goto out; + } + + eablk = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect)); + end = eablk + ip->i_sbd->sd_inptrs; + + for (; eablk < end; eablk++) { + uint64_t bn; + + if (!*eablk) + break; + bn = gfs64_to_cpu(*eablk); + + error = gfs_dread(ip->i_gl, bn, + DIO_START | DIO_WAIT, &eabh); + if (error) + break; + gfs_add_bh_to_ub(ub, eabh); + brelse(eabh); + if (error) + break; + } + } + + out: + brelse(bh); + + return error; +} --- linux-2.6.27.orig/ubuntu/gfs/unlinked.c +++ linux-2.6.27/ubuntu/gfs/unlinked.c @@ -0,0 +1,432 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "inode.h" +#include "log.h" +#include "lops.h" +#include "unlinked.h" + +/** + * gfs_unlinked_get - Get a structure to represent an unlinked inode + * @sdp: the filesystem + * @inum: identifies the inode that's unlinked + * @create: if TRUE, we're allowed to create the structure if we can't find it, + * otherwise return NULL + * + * Returns: the structure, or NULL + * + * Search the filesystem's list of gfs_unlinked to find a match. + * If none found, create a new one and place on list. + */ + +struct gfs_unlinked * +gfs_unlinked_get(struct gfs_sbd *sdp, struct gfs_inum *inum, int create) +{ + struct gfs_unlinked *ul = NULL, *new_ul = NULL; + struct list_head *tmp, *head; + + for (;;) { + spin_lock(&sdp->sd_unlinked_lock); + + for (head = &sdp->sd_unlinked_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + ul = list_entry(tmp, struct gfs_unlinked, ul_list); + if (gfs_inum_equal(&ul->ul_inum, inum)) { + ul->ul_count++; + break; + } + } + + if (tmp == head) + ul = NULL; + + /* 2nd pass, still not there; add the new_ul we prepared */ + if (!ul && new_ul) { + ul = new_ul; + list_add(&ul->ul_list, &sdp->sd_unlinked_list); + new_ul = NULL; + } + + spin_unlock(&sdp->sd_unlinked_lock); + + /* 1st pass; we found pre-existing, OR not allowed to create. + 2nd pass; another process added it, or we did */ + if (ul || !create) { + if (new_ul) + /* someone beat us to it; forget our new_ul */ + kfree(new_ul); + return ul; + } + + /* No match on list, 1st time through loop. + Prepare new_ul, then repeat loop to find out if another + process has created or unlinked an inode and put its + gfs_unlinked on list while we've been preparing this one. */ + new_ul = gmalloc(sizeof(struct gfs_unlinked)); + memset(new_ul, 0, sizeof(struct gfs_unlinked)); + + new_ul->ul_count = 1; + new_ul->ul_inum = *inum; + + INIT_LE(&new_ul->ul_new_le, &gfs_unlinked_lops); + INIT_LE(&new_ul->ul_incore_le, &gfs_unlinked_lops); + INIT_LE(&new_ul->ul_ondisk_le, &gfs_unlinked_lops); + } +} + +/** + * gfs_unlinked_hold - increment the usage count on a struct gfs_unlinked + * @sdp: the filesystem + * @ul: the structure + * + */ + +void +gfs_unlinked_hold(struct gfs_sbd *sdp, struct gfs_unlinked *ul) +{ + spin_lock(&sdp->sd_unlinked_lock); + gfs_assert(sdp, ul->ul_count,); + ul->ul_count++; + spin_unlock(&sdp->sd_unlinked_lock); +} + +/** + * gfs_unlinked_put - decrement the usage count on a struct gfs_unlinked + * @sdp: the filesystem + * @ul: the structure + * + * Free the structure if its reference count hits zero. + * + */ + +void +gfs_unlinked_put(struct gfs_sbd *sdp, struct gfs_unlinked *ul) +{ + spin_lock(&sdp->sd_unlinked_lock); + + gfs_assert(sdp, ul->ul_count,); + ul->ul_count--; + + if (!ul->ul_count) { + gfs_assert_warn(sdp, + !test_bit(ULF_IC_LIST, &ul->ul_flags) && + !test_bit(ULF_OD_LIST, &ul->ul_flags) && + !test_bit(ULF_LOCK, &ul->ul_flags)); + list_del(&ul->ul_list); + spin_unlock(&sdp->sd_unlinked_lock); + kfree(ul); + } else + spin_unlock(&sdp->sd_unlinked_lock); +} + +/** + * unlinked_find - Find a inode to try to deallocate + * @sdp: the filesystem + * + * The returned structure is locked and needs to be unlocked + * with gfs_unlinked_unlock(). + * + * Returns: A unlinked structure, or NULL + */ + +struct gfs_unlinked * +unlinked_find(struct gfs_sbd *sdp) +{ + struct list_head *tmp, *head; + struct gfs_unlinked *ul = NULL; + + if (test_bit(SDF_ROFS, &sdp->sd_flags)) + return NULL; + + gfs_log_lock(sdp); + spin_lock(&sdp->sd_unlinked_lock); + + if (!atomic_read(&sdp->sd_unlinked_ic_count)) + goto out; + + for (head = &sdp->sd_unlinked_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + ul = list_entry(tmp, struct gfs_unlinked, ul_list); + + if (test_bit(ULF_LOCK, &ul->ul_flags)) + continue; + if (!test_bit(ULF_IC_LIST, &ul->ul_flags)) + continue; + + list_move_tail(&ul->ul_list, &sdp->sd_unlinked_list); + + set_bit(ULF_LOCK, &ul->ul_flags); + ul->ul_count++; + + goto out; + } + + ul = NULL; + + out: + spin_unlock(&sdp->sd_unlinked_lock); + gfs_log_unlock(sdp); + + return ul; +} + +/** + * gfs_unlinked_lock - lock a unlinked structure + * @sdp: the filesystem + * @ul: the unlinked inode structure + * + */ + +void +gfs_unlinked_lock(struct gfs_sbd *sdp, struct gfs_unlinked *ul) +{ + spin_lock(&sdp->sd_unlinked_lock); + + gfs_assert_warn(sdp, !test_bit(ULF_LOCK, &ul->ul_flags)); + set_bit(ULF_LOCK, &ul->ul_flags); + + ul->ul_count++; + + spin_unlock(&sdp->sd_unlinked_lock); +} + +/** + * gfs_unlinked_unlock - drop a reference on a unlinked structure + * @sdp: the filesystem + * @ul: the unlinked inode structure + * + */ + +void +gfs_unlinked_unlock(struct gfs_sbd *sdp, struct gfs_unlinked *ul) +{ + spin_lock(&sdp->sd_unlinked_lock); + + gfs_assert_warn(sdp, test_bit(ULF_LOCK, &ul->ul_flags)); + clear_bit(ULF_LOCK, &ul->ul_flags); + + gfs_assert(sdp, ul->ul_count,); + ul->ul_count--; + + if (!ul->ul_count) { + gfs_assert_warn(sdp, !test_bit(ULF_IC_LIST, &ul->ul_flags) && + !test_bit(ULF_OD_LIST, &ul->ul_flags)); + list_del(&ul->ul_list); + spin_unlock(&sdp->sd_unlinked_lock); + kfree(ul); + } else + spin_unlock(&sdp->sd_unlinked_lock); +} + +/** + * gfs_unlinked_merge - add/remove a unlinked inode from the in-memory list + * @sdp: the filesystem + * @type: is this a unlink tag or a dealloc tag + * @inum: the inode number + * + * Called during journal recovery. + */ + +void +gfs_unlinked_merge(struct gfs_sbd *sdp, unsigned int type, + struct gfs_inum *inum) +{ + struct gfs_unlinked *ul; + + gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count) == + atomic_read(&sdp->sd_unlinked_od_count),); + + ul = gfs_unlinked_get(sdp, inum, CREATE); + + gfs_log_lock(sdp); + + switch (type) { + case GFS_LOG_DESC_IUL: + gfs_unlinked_hold(sdp, ul); + gfs_unlinked_hold(sdp, ul); + gfs_assert(sdp, !test_bit(ULF_IC_LIST, &ul->ul_flags) && + !test_bit(ULF_OD_LIST, &ul->ul_flags),); + set_bit(ULF_IC_LIST, &ul->ul_flags); + set_bit(ULF_OD_LIST, &ul->ul_flags); + atomic_inc(&sdp->sd_unlinked_ic_count); + atomic_inc(&sdp->sd_unlinked_od_count); + + break; + + case GFS_LOG_DESC_IDA: + gfs_assert(sdp, test_bit(ULF_IC_LIST, &ul->ul_flags) && + test_bit(ULF_OD_LIST, &ul->ul_flags),); + clear_bit(ULF_IC_LIST, &ul->ul_flags); + clear_bit(ULF_OD_LIST, &ul->ul_flags); + gfs_unlinked_put(sdp, ul); + gfs_unlinked_put(sdp, ul); + gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count) > 0,); + atomic_dec(&sdp->sd_unlinked_ic_count); + gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_od_count) > 0,); + atomic_dec(&sdp->sd_unlinked_od_count); + + break; + } + + gfs_log_unlock(sdp); + + gfs_unlinked_put(sdp, ul); +} + +/** + * gfs_unlinked_cleanup - get rid of any extra struct gfs_unlinked structures + * @sdp: the filesystem + * + */ + +void +gfs_unlinked_cleanup(struct gfs_sbd *sdp) +{ + struct gfs_unlinked *ul; + + restart: + gfs_log_lock(sdp); + + gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count) == + atomic_read(&sdp->sd_unlinked_od_count),); + + spin_lock(&sdp->sd_unlinked_lock); + + while (!list_empty(&sdp->sd_unlinked_list)) { + ul = list_entry(sdp->sd_unlinked_list.next, + struct gfs_unlinked, ul_list); + + if (ul->ul_count > 2) { + spin_unlock(&sdp->sd_unlinked_lock); + gfs_log_unlock(sdp); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + goto restart; + } + gfs_assert(sdp, ul->ul_count == 2,); + + gfs_assert_warn(sdp, + test_bit(ULF_IC_LIST, &ul->ul_flags) && + test_bit(ULF_OD_LIST, &ul->ul_flags) && + !test_bit(ULF_LOCK, &ul->ul_flags)); + + list_del(&ul->ul_list); + + atomic_dec(&sdp->sd_unlinked_ic_count); + atomic_dec(&sdp->sd_unlinked_od_count); + + spin_unlock(&sdp->sd_unlinked_lock); + kfree(ul); + spin_lock(&sdp->sd_unlinked_lock); + } + + spin_unlock(&sdp->sd_unlinked_lock); + + gfs_assert(sdp, !atomic_read(&sdp->sd_unlinked_ic_count) && + !atomic_read(&sdp->sd_unlinked_od_count),); + + gfs_log_unlock(sdp); +} + +/** + * gfs_unlinked_limit - limit the number of inodes waiting to be deallocated + * @sdp: the filesystem + * + * Returns: errno + */ + +void +gfs_unlinked_limit(struct gfs_sbd *sdp) +{ + unsigned int tries = 0, min = 0; + int error; + + if (atomic_read(&sdp->sd_unlinked_ic_count) >= + gfs_tune_get(sdp, gt_ilimit2)) { + tries = gfs_tune_get(sdp, gt_ilimit2_tries); + min = gfs_tune_get(sdp, gt_ilimit2_min); + } else if (atomic_read(&sdp->sd_unlinked_ic_count) >= + gfs_tune_get(sdp, gt_ilimit1)) { + tries = gfs_tune_get(sdp, gt_ilimit1_tries); + min = gfs_tune_get(sdp, gt_ilimit1_min); + } + + while (tries--) { + struct gfs_unlinked *ul = unlinked_find(sdp); + if (!ul) + break; + + error = gfs_inode_dealloc(sdp, &ul->ul_inum); + + gfs_unlinked_unlock(sdp, ul); + + if (!error) { + if (!--min) + break; + } else if (error != 1) + break; + } +} + +/** + * gfs_unlinked_dealloc - Go through the list of inodes to be deallocated + * @sdp: the filesystem + * + * Returns: errno + */ + +void +gfs_unlinked_dealloc(struct gfs_sbd *sdp) +{ + unsigned int hits, strikes; + int error; + + for (;;) { + hits = 0; + strikes = 0; + + for (;;) { + struct gfs_unlinked *ul = unlinked_find(sdp); + if (!ul) + return; + + error = gfs_inode_dealloc(sdp, &ul->ul_inum); + + gfs_unlinked_unlock(sdp, ul); + + if (!error) { + hits++; + if (strikes) + strikes--; + } else if (error == 1) { + strikes++; + if (strikes >= atomic_read(&sdp->sd_unlinked_ic_count)) { + error = 0; + break; + } + } else + goto out; + } + + if (!hits || kthread_should_stop()) + break; + + cond_resched(); + } + + out: + if (error && + error != -EROFS && + !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + printk("GFS: fsid=%s: error deallocating inodes: %d\n", + sdp->sd_fsname, error); +} --- linux-2.6.27.orig/ubuntu/gfs/mount.h +++ linux-2.6.27/ubuntu/gfs/mount.h @@ -0,0 +1,6 @@ +#ifndef __MOUNT_DOT_H__ +#define __MOUNT_DOT_H__ + +int gfs_make_args(char *data, struct gfs_args *args, int remount); + +#endif /* __MOUNT_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/gfs_ondisk.h +++ linux-2.6.27/ubuntu/gfs/gfs_ondisk.h @@ -0,0 +1,1904 @@ +/* + * On-disk structures. + * + * THE BIG PICTURE of on-disk layout: + * + * GFS filesystem code views the entire filesystem, including journals, as + * one contiguous group of blocks on one (perhaps virtual) storage device. + * The filesystem space is shared, not distributed; each node in the cluster + * must see the entire filesystem space. + * + * If the filesystem is spread across multiple physical storage devices, + * volume management (device mapping) must be used to present the fileystem + * space to GFS as one (virtual) device, with contiguous blocks. + * + * The superblock contains basic information about the filesytem, and appears + * at a location 64 KBytes into the filesystem. The first 64 KBytes of the + * filesystem are empty, providing a safety buffer against wayward volume + * management software (that sometimes write data into the first few bytes of + * a device) or administrators. + * + * After the superblock, the rest of the filesystem is divided into multiple + * Resource Groups and several journals. + * + * The Resource Groups (RGs or rgrps) contain the allocatable blocks that are + * used for storing files, directories, etc., and all of the associated + * metadata. Each RG has its own set of block allocation statistics (within + * the RG header), a number of blocks containing the block allocation bitmap, + * and a large number of allocatable blocks for file data and metadata. + * Multiple RGs allow multiple nodes to simultaneously allocate blocks from the + * filesystem (using different RGs), enhancing parallel access. RG size and + * number of RGs are determined by gfs_mkfs when creating the filesystem. + * An administrator can specify RG size (see man gfs_mkfs). + * + * The journals contain temporary copies of metadata blocks, along with + * other data, that allow GFS to recover the filesystem to a consistent state + * (at least as far as metadata is concerned) if a node fails in the midst + * of performing a write transaction. There must be one journal for each node + * in the cluster. Since access to the entire filesystem space is shared, + * if a node crashes, another node will be able to read the crashed node's + * journal, and perform recovery. + * + * Currently, gfs_mkfs places the journals right in the middle of a freshly + * created filesystem space, between 2 large groups of RGs. From a filesystem + * layout perspective, this placement is not a requirement; the journals + * could be placed anywhere within the filesystem space. + * + * New Resource Groups and Journals may be added to the filesystem after the + * filesystem has been created, if the filesystem's (virtual) device is made + * larger. See man gfs_grow and gfs_jadd. + * + * A few special hidden inodes are contained in a GFS filesystem. They do + * not appear in any directories; instead, the superblock points to them + * using block numbers for their location. The special inodes are: + * + * Root inode: Root directory of the filesystem + * Resource Group Index: A file containing block numbers and sizes of all RGs + * Journal Index: A file containing block numbers and sizes of all journals + * Quota: A file containing all quota information for the filesystem + * License: A file containing license information + * + * Note that there is NOTHING RELATED TO INTER-NODE LOCK MANAGEMENT ON-DISK. + * Locking is handled completely off-disk, typically via LAN. + * + * NOTE: + * If you add 8 byte fields to these structures, they must be 8 byte + * aligned. 4 byte field must be 4 byte aligned, etc... + * + * All structures must be a multiple of 8 bytes long. + * + * GRIPES: + * We should have forgetten about supporting 512B FS block sizes + * and made the di_reserved field in the struct gfs_dinode structure + * much bigger. + * + * de_rec_len in struct gfs_dirent should really have been a 32-bit value + * as it now limits us to a 64k FS block size (with the current code + * in dir.c). + */ + +#ifndef __GFS_ONDISK_DOT_H__ +#define __GFS_ONDISK_DOT_H__ + +#define GFS_MAGIC (0x01161970) /* for all on-disk headers */ +#define GFS_BASIC_BLOCK (512) /* "basic block" = "sector" = 512B */ +#define GFS_BASIC_BLOCK_SHIFT (9) + +/* Controls how much data can be logged in-core before dumping log to disk */ + +#define GFS_DUMPS_PER_LOG (4) /* 1/4 of on-disk journal size*/ + +/* Lock numbers of the LM_TYPE_NONDISK type. These protect certain + * cluster-wide operations (rather than on-disk entities). + * Currently, the LIVE lock is not used for any real purpose. */ + +#define GFS_MOUNT_LOCK (0) /* only one node can Mount at a time */ +#define GFS_LIVE_LOCK (1) /* shared by all mounted nodes */ +#define GFS_TRANS_LOCK (2) /* Transaction, protects jrnl recovery */ +#define GFS_RENAME_LOCK (3) /* only one node can Rename at a time */ + +/* On-disk format (version) numbers for various metadata types, + * used in gfs_meta_header */ + +#define GFS_FORMAT_SB (100) /* Super-Block */ +#define GFS_FORMAT_RG (200) /* Resource Group Header */ +#define GFS_FORMAT_RB (300) /* Resource Group Block Alloc BitBlock */ +#define GFS_FORMAT_DI (400) /* "Disk" inode (dinode) */ +#define GFS_FORMAT_IN (500) /* Indirect dinode block list */ +#define GFS_FORMAT_LF (600) /* Leaf dinode block list */ +#define GFS_FORMAT_JD (700) /* Journal Data */ +#define GFS_FORMAT_LH (800) /* Log Header */ +#define GFS_FORMAT_LD (900) /* Log Descriptor */ +/* These don't have actual struct gfs_meta_header structures to go with them */ +#define GFS_FORMAT_JI (1000) /* Journal Index */ +#define GFS_FORMAT_RI (1100) /* Resource Group Index */ +#define GFS_FORMAT_DE (1200) /* Directory Entry */ +#define GFS_FORMAT_QU (1500) /* Quota */ +#define GFS_FORMAT_EA (1600) /* Extended Attribute */ +#define GFS_FORMAT_ED (1700) /* Extended Attribute data */ +/* These version #s are embedded in the superblock */ +#define GFS_FORMAT_FS (1309) /* Filesystem (all-encompassing) */ +#define GFS_FORMAT_MULTI (1401) /* Multi-Host */ + +/* + * An on-disk inode number + * Initially, the on-disk block address of the inode block is assigned as the + * formal (permanent) ID as well. Block address can change (to move inode + * on-disk), but formal ID must stay unchanged once assigned. + */ + +#define gfs_inum_equal(ino1, ino2) \ +(((ino1)->no_formal_ino == (ino2)->no_formal_ino) && \ + ((ino1)->no_addr == (ino2)->no_addr)) + +struct gfs_inum { + uint64_t no_formal_ino; /* inode identifier */ + uint64_t no_addr; /* block # of dinode block */ +}; + +/* + * Generic metadata head structure + * + * Every inplace buffer logged in the journal must start + * with a struct gfs_meta_header. + * + * In addition to telling what kind of metadata is in the block, + * the metaheader contains the important generation and incarnation + * numbers. + * + * The generation number is used during journal recovery to determine + * whether an in-place block on-disk is older than an on-disk journaled copy + * of the block. If so, GFS overwrites the in-place block with the journaled + * version of the block. + * + * A meta block's generation number must increment monotonically across the + * cluster, each time new contents are committed to the block. This means + * that whenever GFS allocates a pre-existing metadata block, GFS must read + * that block from disk (in case another node has incremented it). It also + * means that GFS must sync the block (with incremented generation number) + * to disk (both log and in-place blocks), not only after changing contents + * of the block, but also after de-allocating the block (GFS can't just throw + * away incore metadata for a file that it's just erased). + * + * The incarnation number is used only for on-disk (d)inodes. GFS increments + * it each time it de-allocates a dinode block (i.e. each time the dinode + * loses its identity with a particular file, directory, etc.). When the + * dinode is later allocated (i.e. to be identified with a new file, etc.), + * GFS copies the incarnation number into the VFS inode's i_generation member. + * If GFS is used as the backing store for an NFS server, GFS uses this + * i_generation number as part of the NFS filehandle, which differentiates + * it from the previous identity of the dinode, and helps protect against + * filesystem corruption that could happen with the use of outdated, + * invalid, or malicious filehandles. See ops_export.c. + * + * GFS caches de-allocated meta-headers, to minimize disk reads. + * See struct gfs_meta_header_cache. + */ + +#define GFS_METATYPE_NONE (0) +#define GFS_METATYPE_SB (1) /* Super-Block */ +#define GFS_METATYPE_RG (2) /* Resource Group Header */ +#define GFS_METATYPE_RB (3) /* Resource Group Block Alloc BitBlock */ +#define GFS_METATYPE_DI (4) /* "Disk" inode (dinode) */ +#define GFS_METATYPE_IN (5) /* Indirect dinode block list */ +#define GFS_METATYPE_LF (6) /* Leaf dinode block list */ +#define GFS_METATYPE_JD (7) /* Journal Data */ +#define GFS_METATYPE_LH (8) /* Log Header (gfs_log_header) */ +#define GFS_METATYPE_LD (9) /* Log Descriptor (gfs_log_descriptor) */ +#define GFS_METATYPE_EA (10) /* Extended Attribute */ +#define GFS_METATYPE_ED (11) /* Extended Attribute data */ + +#define GFS_META_CLUMP (64) /* # blocks to convert fm data to meta */ + +struct gfs_meta_header { + uint32_t mh_magic; /* GFS_MAGIC sanity check magic number */ + uint32_t mh_type; /* GFS_METATYPE_XX type of metadata block */ + uint64_t mh_generation; /* increment before writing to journal */ + uint32_t mh_format; /* GFS_FORMAT_XX (version # for this type) */ + uint32_t mh_incarn; /* increment when marking dinode "unused" */ +}; + +/* + * super-block structure + * + * One of these is at beginning of filesystem. + * It's probably good if SIZEOF_SB <= GFS_BASIC_BLOCK (512 bytes) + */ + +/* Address of SuperBlock in GFS basic blocks. 1st 64K of filesystem is empty + for safety against getting clobbered by wayward volume managers, etc. + 64k was chosen because it's the largest GFS-supported fs block size. */ +#define GFS_SB_ADDR (128) + +/* The lock number for the superblock (must be zero) */ +#define GFS_SB_LOCK (0) +#define GFS_CRAP_LOCK (1) + +/* Requirement: GFS_LOCKNAME_LEN % 8 == 0 + Includes: the fencing zero at the end */ +#define GFS_LOCKNAME_LEN (64) + +struct gfs_sb { + /* Order is important; need to be able to read old superblocks + in order to support on-disk version upgrades */ + struct gfs_meta_header sb_header; + + uint32_t sb_fs_format; /* GFS_FORMAT_FS (on-disk version) */ + uint32_t sb_multihost_format; /* GFS_FORMAT_MULTI */ + uint32_t sb_flags; /* ?? */ + + uint32_t sb_bsize; /* fundamental FS block size in bytes */ + uint32_t sb_bsize_shift; /* log2(sb_bsize) */ + uint32_t sb_seg_size; /* Journal segment size in FS blocks */ + + /* These special inodes do not appear in any on-disk directory. */ + struct gfs_inum sb_jindex_di; /* journal index inode */ + struct gfs_inum sb_rindex_di; /* resource group index inode */ + struct gfs_inum sb_root_di; /* root directory inode */ + + /* Default inter-node locking protocol (lock module) and namespace */ + char sb_lockproto[GFS_LOCKNAME_LEN]; /* lock protocol name */ + char sb_locktable[GFS_LOCKNAME_LEN]; /* unique name for this FS */ + + /* More special inodes */ + struct gfs_inum sb_quota_di; /* quota inode */ + struct gfs_inum sb_license_di; /* license inode */ + + char sb_reserved[96]; +}; + +/* + * journal index structure + * + * One for each journal used by the filesystem. + * These descriptors are packed contiguously within the jindex inode (file). + */ + +struct gfs_jindex { + uint64_t ji_addr; /* starting block of the journal */ + uint32_t ji_nsegment; /* number (quantity) of segments in journal */ + uint32_t ji_pad; + + char ji_reserved[64]; +}; + +/* + * resource index structure + * + * One of these for each resource group in the filesystem. + * These descriptors are packed contiguously within the rindex inode (file). + * Also see struct gfs_rgrp. + */ + +struct gfs_rindex { + uint64_t ri_addr; /* block # of 1st block (header) in rgrp */ + uint32_t ri_length; /* # fs blocks containing rgrp header & bitmap */ + uint32_t ri_pad; + + uint64_t ri_data1; /* block # of first data/meta block in rgrp */ + uint32_t ri_data; /* number (qty) of data/meta blocks in rgrp */ + + uint32_t ri_bitbytes; /* total # bytes used by block alloc bitmap */ + + char ri_reserved[64]; +}; + +/* + * resource group header structure + * + * One of these at beginning of the first block of an rgrp, + * followed by block alloc bitmap data in remainder of first block. + * Each resource group contains: + * Header block, including block allocation statistics (struct gfs_rgrp) + * and first part of block alloc bitmap. + * Bitmap block(s), continuing block alloc bitmap started in header block. + * Data/meta blocks, allocatable blocks containing file data and metadata. + * + * In older versions, now-unused (but previously allocated) dinodes were + * saved for re-use in an on-disk linked list (chain). This is no longer + * done, but support still exists for reclaiming dinodes from this list, + * to support upgrades from older on-disk formats. + */ + +/* Each data block within rgrp is represented by 2 bits in the alloc bitmap */ +#define GFS_NBBY (4) /* # blocks represented by 1 bitmap byte */ +#define GFS_BIT_SIZE (2) +#define GFS_BIT_MASK (0x00000003) + +/* + * 4 possible block allocation states: + * bit 0 = alloc(1)/free(0) + * bit 1 = metadata(1)/data(0) + */ +#define GFS_BLKST_FREE (0) +#define GFS_BLKST_USED (1) +#define GFS_BLKST_FREEMETA (2) +#define GFS_BLKST_USEDMETA (3) + +struct gfs_rgrp { + struct gfs_meta_header rg_header; + + uint32_t rg_flags; /* ?? */ + + uint32_t rg_free; /* Number (qty) of free data blocks */ + + /* Dinodes are USEDMETA, but are handled separately from other METAs */ + uint32_t rg_useddi; /* Number (qty) of dinodes (used or free) */ + uint32_t rg_freedi; /* Number (qty) of unused (free) dinodes */ + struct gfs_inum rg_freedi_list; /* 1st block in chain of free dinodes */ + + /* These META statistics do not include dinodes (used or free) */ + uint32_t rg_usedmeta; /* Number (qty) of used metadata blocks */ + uint32_t rg_freemeta; /* Number (qty) of unused metadata blocks */ + + char rg_reserved[64]; +}; + +/* + * quota structure + */ + +struct gfs_quota { + uint64_t qu_limit; + uint64_t qu_warn; + int64_t qu_value; + + char qu_reserved[64]; +}; + +/* + * dinode (disk inode) structure + * The ondisk representation of inodes + * One for each file, directory, etc. + * GFS does not put more than one inode in a single block. + * The inode may be "stuffed", carrying file data along with metadata, + * if the file data is small enough. + * Otherwise, the inode block contains pointers to other blocks that contain + * either file data or other pointers to other blocks (indirect addressing + * via a metadata tree). + */ + +#define GFS_MAX_META_HEIGHT (10) +#define GFS_DIR_MAX_DEPTH (17) + +/* Dinode types */ +#define GFS_FILE_NON (0) +#define GFS_FILE_REG (1) /* regular file */ +#define GFS_FILE_DIR (2) /* directory */ +#define GFS_FILE_LNK (5) /* link */ +#define GFS_FILE_BLK (7) /* block device node */ +#define GFS_FILE_CHR (8) /* character device node */ +#define GFS_FILE_FIFO (101) /* fifo/pipe */ +#define GFS_FILE_SOCK (102) /* socket */ + +/* Dinode flags */ +#define GFS_DIF_JDATA (0x00000001) /* jrnl all data for this file */ +#define GFS_DIF_EXHASH (0x00000002) /* hashed directory (leaves) */ +#define GFS_DIF_UNUSED (0x00000004) /* unused dinode */ +#define GFS_DIF_EA_INDIRECT (0x00000008) /* extended attribute, indirect*/ +#define GFS_DIF_DIRECTIO (0x00000010) +#define GFS_DIF_IMMUTABLE (0x00000020) /* Can't change file */ +#define GFS_DIF_APPENDONLY (0x00000040) /* Can only add to end of file */ +#define GFS_DIF_NOATIME (0x00000080) /* Don't update access time + (currently unused/ignored) */ +#define GFS_DIF_SYNC (0x00000100) /* Flush to disk, don't cache + (currently unused/ignored) */ +#define GFS_DIF_INHERIT_DIRECTIO (0x40000000) /* new files get DIRECTIO flag */ +#define GFS_DIF_INHERIT_JDATA (0x80000000) /* new files get JDATA flag */ + +struct gfs_dinode { + struct gfs_meta_header di_header; + + struct gfs_inum di_num; /* formal inode # and block address */ + + uint32_t di_mode; /* mode of file */ + uint32_t di_uid; /* owner's user id */ + uint32_t di_gid; /* owner's group id */ + uint32_t di_nlink; /* number (qty) of links to this file */ + uint64_t di_size; /* number (qty) of bytes in file */ + uint64_t di_blocks; /* number (qty) of blocks in file */ + int64_t di_atime; /* time last accessed */ + int64_t di_mtime; /* time last modified */ + int64_t di_ctime; /* time last changed */ + + /* Non-zero only for character or block device nodes */ + uint32_t di_major; /* device major number */ + uint32_t di_minor; /* device minor number */ + + /* Block allocation strategy */ + uint64_t di_rgrp; /* dinode rgrp block number */ + uint64_t di_goal_rgrp; /* rgrp to alloc from next */ + uint32_t di_goal_dblk; /* data block goal */ + uint32_t di_goal_mblk; /* metadata block goal */ + + uint32_t di_flags; /* GFS_DIF_... */ + + /* struct gfs_rindex, struct gfs_jindex, or struct gfs_dirent */ + uint32_t di_payload_format; /* GFS_FORMAT_... */ + uint16_t di_type; /* GFS_FILE_... type of file */ + uint16_t di_height; /* height of metadata (0 == stuffed) */ + uint32_t di_incarn; /* incarnation (unused, see gfs_meta_header) */ + uint16_t di_pad; + + /* These only apply to directories */ + uint16_t di_depth; /* Number of bits in the table */ + uint32_t di_entries; /* The # (qty) of entries in the directory */ + + /* This formed an on-disk chain of unused dinodes */ + struct gfs_inum di_next_unused; /* used in old versions only */ + + uint64_t di_eattr; /* extended attribute block number */ + + char di_reserved[56]; +}; + +/* + * indirect block header + * + * A component of a dinode's indirect addressing metadata tree. + * These are pointed to by pointers in dinodes or other indirect blocks. + */ + +struct gfs_indirect { + struct gfs_meta_header in_header; + + char in_reserved[64]; +}; + +/* + * directory structure - many of these per directory file + * + * See comments at beginning of dir.c + */ + +#define GFS_FNAMESIZE (255) +#define GFS_DIRENT_SIZE(name_len) ((sizeof(struct gfs_dirent) + (name_len) + 7) & ~7) +#define IS_LEAF (1) /* Hashed (leaf) directory */ +#define IS_DINODE (2) /* Linear (stuffed dinode block) directory */ + +struct gfs_dirent { + struct gfs_inum de_inum; /* formal inode number and block address */ + uint32_t de_hash; /* hash of the filename */ + uint16_t de_rec_len; /* the length of the dirent */ + uint16_t de_name_len; /* the length of the name */ + uint16_t de_type; /* GFS_FILE_... type of dinode this points to */ + + char de_reserved[14]; +}; + +/* + * Header of leaf directory nodes + * + * See comments at beginning of dir.c + */ + +struct gfs_leaf { + struct gfs_meta_header lf_header; + + uint16_t lf_depth; /* Depth of leaf */ + uint16_t lf_entries; /* Number of dirents in leaf */ + uint32_t lf_dirent_format; /* GFS_FORMAT_DE (version #) */ + uint64_t lf_next; /* Next leaf, if overflow */ + + char lf_reserved[64]; +}; + +/* + * Log header structure + * + * Two of these are in the first block of a transaction log: + * 1) at beginning of block + * 2) at end of first 512-byte sector within block + */ + +#define GFS_LOG_HEAD_UNMOUNT (0x00000001) /* log is clean, can unmount fs */ + +struct gfs_log_header { + struct gfs_meta_header lh_header; + + uint32_t lh_flags; /* GFS_LOG_HEAD_... */ + uint32_t lh_pad; + + uint64_t lh_first; /* Block number of first header in this trans */ + uint64_t lh_sequence; /* Sequence number of this transaction */ + + uint64_t lh_tail; /* Block number of log tail */ + uint64_t lh_last_dump; /* Block number of last dump */ + + char lh_reserved[64]; +}; + +/* + * Log type descriptor + * + * One of these for each chunk in a transaction + */ + +#define GFS_LOG_DESC_METADATA (300) /* metadata */ +/* ld_data1 is the number (quantity) of metadata blocks in the descriptor. + ld_data2 is unused. + */ + +#define GFS_LOG_DESC_IUL (400) /* unlinked inode */ +/* ld_data1 is TRUE if this is a dump. + ld_data2 is unused. + FixMe!!! ld_data1 should be the number (quantity) of entries. + ld_data2 should be "TRUE if this is a dump". + */ + +#define GFS_LOG_DESC_IDA (401) /* de-allocated inode */ +/* ld_data1 is unused. + ld_data2 is unused. + FixMe!!! ld_data1 should be the number (quantity) of entries. + */ + +#define GFS_LOG_DESC_Q (402) /* quota */ +/* ld_data1 is the number of quota changes in the descriptor. + ld_data2 is TRUE if this is a dump. + */ + +#define GFS_LOG_DESC_LAST (500) /* final in a logged transaction */ +/* ld_data1 is unused. + ld_data2 is unused. + */ + +struct gfs_log_descriptor { + struct gfs_meta_header ld_header; + + uint32_t ld_type; /* GFS_LOG_DESC_... Type of this log chunk */ + uint32_t ld_length; /* Number of buffers in this chunk */ + uint32_t ld_data1; /* descriptor-specific field */ + uint32_t ld_data2; /* descriptor-specific field */ + + char ld_reserved[64]; +}; + +/* + * Metadata block tags + * + * One for each logged block. Tells where block really belongs on-disk. + * These descriptor tags are packed contiguously after a gfs_log_descriptor. + */ + +struct gfs_block_tag { + uint64_t bt_blkno; /* inplace block number */ + uint32_t bt_flags; /* ?? */ + uint32_t bt_pad; +}; + +/* + * Quota Journal Tag + */ + +#define GFS_QTF_USER (0x00000001) + +struct gfs_quota_tag { + int64_t qt_change; + uint32_t qt_flags; /* GFS_QTF_... */ + uint32_t qt_id; +}; + +/* + * Extended attribute header format + */ + +#define GFS_EA_MAX_NAME_LEN (255) +#define GFS_EA_MAX_DATA_LEN (65536) + +#define GFS_EATYPE_UNUSED (0) +#define GFS_EATYPE_USR (1) /* user attribute */ +#define GFS_EATYPE_SYS (2) /* system attribute */ +#define GFS_EATYPE_SECURITY (3) /* security attribute */ + +#define GFS_EATYPE_LAST (3) +#define GFS_EATYPE_VALID(x) ((x) <= GFS_EATYPE_LAST) + +#define GFS_EAFLAG_LAST (0x01) /* last ea in block */ + +struct gfs_ea_header { + uint32_t ea_rec_len; /* total record length: hdr + name + data */ + uint32_t ea_data_len; /* data length, in bytes */ + uint8_t ea_name_len; /* no NULL pointer after the string */ + uint8_t ea_type; /* GFS_EATYPE_... */ + uint8_t ea_flags; /* GFS_EAFLAG_... */ + uint8_t ea_num_ptrs; /* # fs blocks needed for EA */ + uint32_t ea_pad; +}; + +/* + * Statfs change + * Describes an change to the pool of free and allocated + * blocks. + */ + +struct gfs_statfs_change { + uint64_t sc_total; + uint64_t sc_free; + uint64_t sc_dinodes; +}; + +struct gfs_statfs_change_host { + int64_t sc_total; + int64_t sc_free; + int64_t sc_dinodes; +}; + +/* Endian functions */ + +#define GFS_ENDIAN_BIG + +#ifdef GFS_ENDIAN_BIG + +#define gfs16_to_cpu be16_to_cpu +#define gfs32_to_cpu be32_to_cpu +#define gfs64_to_cpu be64_to_cpu + +#define cpu_to_gfs16 cpu_to_be16 +#define cpu_to_gfs32 cpu_to_be32 +#define cpu_to_gfs64 cpu_to_be64 + +#else /* GFS_ENDIAN_BIG */ + +#define gfs16_to_cpu le16_to_cpu +#define gfs32_to_cpu le32_to_cpu +#define gfs64_to_cpu le64_to_cpu + +#define cpu_to_gfs16 cpu_to_le16 +#define cpu_to_gfs32 cpu_to_le32 +#define cpu_to_gfs64 cpu_to_le64 + +#endif /* GFS_ENDIAN_BIG */ + +/* Translation functions */ + +void gfs_inum_in(struct gfs_inum *no, char *buf); +void gfs_inum_out(struct gfs_inum *no, char *buf); +void gfs_meta_header_in(struct gfs_meta_header *mh, char *buf); +void gfs_meta_header_out(struct gfs_meta_header *mh, char *buf); +void gfs_sb_in(struct gfs_sb *sb, char *buf); +void gfs_sb_out(struct gfs_sb *sb, char *buf); +void gfs_jindex_in(struct gfs_jindex *jindex, char *buf); +void gfs_jindex_out(struct gfs_jindex *jindex, char *buf); +void gfs_rindex_in(struct gfs_rindex *rindex, char *buf); +void gfs_rindex_out(struct gfs_rindex *rindex, char *buf); +void gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf); +void gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf); +void gfs_quota_in(struct gfs_quota *quota, char *buf); +void gfs_quota_out(struct gfs_quota *quota, char *buf); +void gfs_dinode_in(struct gfs_dinode *dinode, char *buf); +void gfs_dinode_out(struct gfs_dinode *dinode, char *buf); +void gfs_indirect_in(struct gfs_indirect *indirect, char *buf); +void gfs_indirect_out(struct gfs_indirect *indirect, char *buf); +void gfs_dirent_in(struct gfs_dirent *dirent, char *buf); +void gfs_dirent_out(struct gfs_dirent *dirent, char *buf); +void gfs_leaf_in(struct gfs_leaf *leaf, char *buf); +void gfs_leaf_out(struct gfs_leaf *leaf, char *buf); +void gfs_log_header_in(struct gfs_log_header *head, char *buf); +void gfs_log_header_out(struct gfs_log_header *head, char *buf); +void gfs_desc_in(struct gfs_log_descriptor *desc, char *buf); +void gfs_desc_out(struct gfs_log_descriptor *desc, char *buf); +void gfs_block_tag_in(struct gfs_block_tag *btag, char *buf); +void gfs_block_tag_out(struct gfs_block_tag *btag, char *buf); +void gfs_quota_tag_in(struct gfs_quota_tag *qtag, char *buf); +void gfs_quota_tag_out(struct gfs_quota_tag *qtag, char *buf); +void gfs_ea_header_in(struct gfs_ea_header *qtag, char *buf); +void gfs_ea_header_out(struct gfs_ea_header *qtag, char *buf); + +/* Printing functions */ + +void gfs_inum_print(struct gfs_inum *no); +void gfs_meta_header_print(struct gfs_meta_header *mh); +void gfs_sb_print(struct gfs_sb *sb); +void gfs_jindex_print(struct gfs_jindex *jindex); +void gfs_rindex_print(struct gfs_rindex *rindex); +void gfs_rgrp_print(struct gfs_rgrp *rgrp); +void gfs_quota_print(struct gfs_quota *quota); +void gfs_dinode_print(struct gfs_dinode *dinode); +void gfs_indirect_print(struct gfs_indirect *indirect); +void gfs_dirent_print(struct gfs_dirent *dirent, char *name); +void gfs_leaf_print(struct gfs_leaf *leaf); +void gfs_log_header_print(struct gfs_log_header *head); +void gfs_desc_print(struct gfs_log_descriptor *desc); +void gfs_block_tag_print(struct gfs_block_tag *tag); +void gfs_quota_tag_print(struct gfs_quota_tag *tag); +void gfs_ea_header_print(struct gfs_ea_header *ea, char *name); + +/* The hash function for ExHash directories */ + +uint32_t gfs_dir_hash(const char *data, int len); + +#endif /* __GFS_ONDISK_DOT_H__ */ + + + +#ifdef WANT_GFS_CONVERSION_FUNCTIONS + +#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));} +#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));} +#define CPIN_16(s1, s2, member) {(s1->member) = gfs16_to_cpu((s2->member));} +#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_gfs16((s1->member));} +#define CPIN_32(s1, s2, member) {(s1->member) = gfs32_to_cpu((s2->member));} +#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_gfs32((s1->member));} +#define CPIN_64(s1, s2, member) {(s1->member) = gfs64_to_cpu((s2->member));} +#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_gfs64((s1->member));} + +#define pa(struct, member, count) print_array(#member, struct->member, count); + +/** + * print_array - Print out an array of bytes + * @title: what to print before the array + * @buf: the array + * @count: the number of bytes + * + */ + +static void +print_array(char *title, char *buf, int count) +{ + int x; + + printk(" %s =\n", title); + for (x = 0; x < count; x++) { + printk("%.2X ", (unsigned char)buf[x]); + if (x % 16 == 15) + printk("\n"); + } + if (x % 16) + printk("\n"); +} + +/** + * gfs_inum_in - Read in an inode number + * @no: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_inum_in(struct gfs_inum *no, char *buf) +{ + struct gfs_inum *str = (struct gfs_inum *)buf; + + CPIN_64(no, str, no_formal_ino); + CPIN_64(no, str, no_addr); +} + +/** + * gfs_inum_out - Write out an inode number + * @no: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_inum_out(struct gfs_inum *no, char *buf) +{ + struct gfs_inum *str = (struct gfs_inum *)buf; + + CPOUT_64(no, str, no_formal_ino); + CPOUT_64(no, str, no_addr); +} + +/** + * gfs_inum_print - Print out a inode number + * @no: the cpu-order buffer + * + */ + +void +gfs_inum_print(struct gfs_inum *no) +{ + pv(no, no_formal_ino, "%"PRIu64); + pv(no, no_addr, "%"PRIu64); +} + +/** + * gfs_meta_header_in - Read in a metadata header + * @mh: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_meta_header_in(struct gfs_meta_header *mh, char *buf) +{ + struct gfs_meta_header *str = (struct gfs_meta_header *)buf; + + CPIN_32(mh, str, mh_magic); + CPIN_32(mh, str, mh_type); + CPIN_64(mh, str, mh_generation); + CPIN_32(mh, str, mh_format); + CPIN_32(mh, str, mh_incarn); +} + +/** + * gfs_meta_header_in - Write out a metadata header + * @mh: the cpu-order structure + * @buf: the disk-order buffer + * + * Don't ever change the generation number in this routine. + * It's done manually in increment_generation(). + */ + +void +gfs_meta_header_out(struct gfs_meta_header *mh, char *buf) +{ + struct gfs_meta_header *str = (struct gfs_meta_header *)buf; + + CPOUT_32(mh, str, mh_magic); + CPOUT_32(mh, str, mh_type); +#if 0 + /* Don't do this! + Mh_generation should only be change manually. */ + CPOUT_64(mh, str, mh_generation); +#endif + CPOUT_32(mh, str, mh_format); + CPOUT_32(mh, str, mh_incarn); +} + +/** + * gfs_meta_header_print - Print out a metadata header + * @mh: the cpu-order buffer + * + */ + +void +gfs_meta_header_print(struct gfs_meta_header *mh) +{ + pv(mh, mh_magic, "0x%.8X"); + pv(mh, mh_type, "%u"); + pv(mh, mh_generation, "%"PRIu64); + pv(mh, mh_format, "%u"); + pv(mh, mh_incarn, "%u"); +} + +/** + * gfs_sb_in - Read in a superblock + * @sb: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_sb_in(struct gfs_sb *sb, char *buf) +{ + struct gfs_sb *str = (struct gfs_sb *)buf; + + gfs_meta_header_in(&sb->sb_header, buf); + + CPIN_32(sb, str, sb_fs_format); + CPIN_32(sb, str, sb_multihost_format); + CPIN_32(sb, str, sb_flags); + + CPIN_32(sb, str, sb_bsize); + CPIN_32(sb, str, sb_bsize_shift); + CPIN_32(sb, str, sb_seg_size); + + gfs_inum_in(&sb->sb_jindex_di, (char *)&str->sb_jindex_di); + gfs_inum_in(&sb->sb_rindex_di, (char *)&str->sb_rindex_di); + gfs_inum_in(&sb->sb_root_di, (char *)&str->sb_root_di); + + CPIN_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN); + CPIN_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN); + + gfs_inum_in(&sb->sb_quota_di, (char *)&str->sb_quota_di); + gfs_inum_in(&sb->sb_license_di, (char *)&str->sb_license_di); + + CPIN_08(sb, str, sb_reserved, 96); +} + +/** + * gfs_sb_out - Write out a superblock + * @sb: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_sb_out(struct gfs_sb *sb, char *buf) +{ + struct gfs_sb *str = (struct gfs_sb *)buf; + + gfs_meta_header_out(&sb->sb_header, buf); + + CPOUT_32(sb, str, sb_fs_format); + CPOUT_32(sb, str, sb_multihost_format); + CPOUT_32(sb, str, sb_flags); + + CPOUT_32(sb, str, sb_bsize); + CPOUT_32(sb, str, sb_bsize_shift); + CPOUT_32(sb, str, sb_seg_size); + + gfs_inum_out(&sb->sb_jindex_di, (char *)&str->sb_jindex_di); + gfs_inum_out(&sb->sb_rindex_di, (char *)&str->sb_rindex_di); + gfs_inum_out(&sb->sb_root_di, (char *)&str->sb_root_di); + + CPOUT_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN); + CPOUT_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN); + + gfs_inum_out(&sb->sb_quota_di, (char *)&str->sb_quota_di); + gfs_inum_out(&sb->sb_license_di, (char *)&str->sb_license_di); + + CPOUT_08(sb, str, sb_reserved, 96); +} + +/** + * gfs_sb_print - Print out a superblock + * @sb: the cpu-order buffer + * + */ + +void +gfs_sb_print(struct gfs_sb *sb) +{ + gfs_meta_header_print(&sb->sb_header); + + pv(sb, sb_fs_format, "%u"); + pv(sb, sb_multihost_format, "%u"); + pv(sb, sb_flags, "%u"); + + pv(sb, sb_bsize, "%u"); + pv(sb, sb_bsize_shift, "%u"); + pv(sb, sb_seg_size, "%u"); + + gfs_inum_print(&sb->sb_jindex_di); + gfs_inum_print(&sb->sb_rindex_di); + gfs_inum_print(&sb->sb_root_di); + + pv(sb, sb_lockproto, "%s"); + pv(sb, sb_locktable, "%s"); + + gfs_inum_print(&sb->sb_quota_di); + gfs_inum_print(&sb->sb_license_di); + + pa(sb, sb_reserved, 96); +} + +/** + * gfs_jindex_in - Read in a journal index structure + * @jindex: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_jindex_in(struct gfs_jindex *jindex, char *buf) +{ + struct gfs_jindex *str = (struct gfs_jindex *)buf; + + CPIN_64(jindex, str, ji_addr); + CPIN_32(jindex, str, ji_nsegment); + CPIN_32(jindex, str, ji_pad); + + CPIN_08(jindex, str, ji_reserved, 64); +} + +/** + * gfs_jindex_out - Write out a journal index structure + * @jindex: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_jindex_out(struct gfs_jindex *jindex, char *buf) +{ + struct gfs_jindex *str = (struct gfs_jindex *)buf; + + CPOUT_64(jindex, str, ji_addr); + CPOUT_32(jindex, str, ji_nsegment); + CPOUT_32(jindex, str, ji_pad); + + CPOUT_08(jindex, str, ji_reserved, 64); +} + +/** + * gfs_jindex_print - Print out a journal index structure + * @ji: the cpu-order buffer + * + */ + +void +gfs_jindex_print(struct gfs_jindex *ji) +{ + pv(ji, ji_addr, "%"PRIu64); + pv(ji, ji_nsegment, "%u"); + pv(ji, ji_pad, "%u"); + + pa(ji, ji_reserved, 64); +} + +/** + * gfs_rindex_in - Read in a resource index structure + * @rindex: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_rindex_in(struct gfs_rindex *rindex, char *buf) +{ + struct gfs_rindex *str = (struct gfs_rindex *)buf; + + CPIN_64(rindex, str, ri_addr); + CPIN_32(rindex, str, ri_length); + CPIN_32(rindex, str, ri_pad); + + CPIN_64(rindex, str, ri_data1); + CPIN_32(rindex, str, ri_data); + + CPIN_32(rindex, str, ri_bitbytes); + + CPIN_08(rindex, str, ri_reserved, 64); +} + +/** + * gfs_rindex_out - Write out a resource index structure + * @rindex: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_rindex_out(struct gfs_rindex *rindex, char *buf) +{ + struct gfs_rindex *str = (struct gfs_rindex *)buf; + + CPOUT_64(rindex, str, ri_addr); + CPOUT_32(rindex, str, ri_length); + CPOUT_32(rindex, str, ri_pad); + + CPOUT_64(rindex, str, ri_data1); + CPOUT_32(rindex, str, ri_data); + + CPOUT_32(rindex, str, ri_bitbytes); + + CPOUT_08(rindex, str, ri_reserved, 64); +} + +/** + * gfs_rindex_print - Print out a resource index structure + * @ri: the cpu-order buffer + * + */ + +void +gfs_rindex_print(struct gfs_rindex *ri) +{ + pv(ri, ri_addr, "%"PRIu64); + pv(ri, ri_length, "%u"); + pv(ri, ri_pad, "%u"); + + pv(ri, ri_data1, "%"PRIu64); + pv(ri, ri_data, "%u"); + + pv(ri, ri_bitbytes, "%u"); + + pa(ri, ri_reserved, 64); +} + +/** + * gfs_rgrp_in - Read in a resource group header + * @rgrp: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf) +{ + struct gfs_rgrp *str = (struct gfs_rgrp *)buf; + + gfs_meta_header_in(&rgrp->rg_header, buf); + + CPIN_32(rgrp, str, rg_flags); + + CPIN_32(rgrp, str, rg_free); + + CPIN_32(rgrp, str, rg_useddi); + CPIN_32(rgrp, str, rg_freedi); + gfs_inum_in(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list); + + CPIN_32(rgrp, str, rg_usedmeta); + CPIN_32(rgrp, str, rg_freemeta); + + CPIN_08(rgrp, str, rg_reserved, 64); +} + +/** + * gfs_rgrp_out - Write out a resource group header + * @rgrp: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf) +{ + struct gfs_rgrp *str = (struct gfs_rgrp *)buf; + + gfs_meta_header_out(&rgrp->rg_header, buf); + + CPOUT_32(rgrp, str, rg_flags); + + CPOUT_32(rgrp, str, rg_free); + + CPOUT_32(rgrp, str, rg_useddi); + CPOUT_32(rgrp, str, rg_freedi); + gfs_inum_out(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list); + + CPOUT_32(rgrp, str, rg_usedmeta); + CPOUT_32(rgrp, str, rg_freemeta); + + CPOUT_08(rgrp, str, rg_reserved, 64); +} + +/** + * gfs_rgrp_print - Print out a resource group header + * @rg: the cpu-order buffer + * + */ + +void +gfs_rgrp_print(struct gfs_rgrp *rg) +{ + gfs_meta_header_print(&rg->rg_header); + + pv(rg, rg_flags, "%u"); + + pv(rg, rg_free, "%u"); + + pv(rg, rg_useddi, "%u"); + pv(rg, rg_freedi, "%u"); + gfs_inum_print(&rg->rg_freedi_list); + + pv(rg, rg_usedmeta, "%u"); + pv(rg, rg_freemeta, "%u"); + + pa(rg, rg_reserved, 64); +} + +/** + * gfs_quota_in - Read in a quota structures + * @quota: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_quota_in(struct gfs_quota *quota, char *buf) +{ + struct gfs_quota *str = (struct gfs_quota *)buf; + + CPIN_64(quota, str, qu_limit); + CPIN_64(quota, str, qu_warn); + CPIN_64(quota, str, qu_value); + + CPIN_08(quota, str, qu_reserved, 64); +} + +/** + * gfs_quota_out - Write out a quota structure + * @quota: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_quota_out(struct gfs_quota *quota, char *buf) +{ + struct gfs_quota *str = (struct gfs_quota *)buf; + + CPOUT_64(quota, str, qu_limit); + CPOUT_64(quota, str, qu_warn); + CPOUT_64(quota, str, qu_value); + + CPOUT_08(quota, str, qu_reserved, 64); +} + +/** + * gfs_quota_print - Print out a quota structure + * @quota: the cpu-order buffer + * + */ + +void +gfs_quota_print(struct gfs_quota *quota) +{ + pv(quota, qu_limit, "%"PRIu64); + pv(quota, qu_warn, "%"PRIu64); + pv(quota, qu_value, "%"PRId64); + + pa(quota, qu_reserved, 64); +} + +/** + * gfs_dinode_in - Read in a dinode + * @dinode: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_dinode_in(struct gfs_dinode *dinode, char *buf) +{ + struct gfs_dinode *str = (struct gfs_dinode *)buf; + + gfs_meta_header_in(&dinode->di_header, buf); + + gfs_inum_in(&dinode->di_num, (char *)&str->di_num); + + CPIN_32(dinode, str, di_mode); + CPIN_32(dinode, str, di_uid); + CPIN_32(dinode, str, di_gid); + CPIN_32(dinode, str, di_nlink); + CPIN_64(dinode, str, di_size); + CPIN_64(dinode, str, di_blocks); + CPIN_64(dinode, str, di_atime); + CPIN_64(dinode, str, di_mtime); + CPIN_64(dinode, str, di_ctime); + CPIN_32(dinode, str, di_major); + CPIN_32(dinode, str, di_minor); + + CPIN_64(dinode, str, di_rgrp); + CPIN_64(dinode, str, di_goal_rgrp); + CPIN_32(dinode, str, di_goal_dblk); + CPIN_32(dinode, str, di_goal_mblk); + CPIN_32(dinode, str, di_flags); + CPIN_32(dinode, str, di_payload_format); + CPIN_16(dinode, str, di_type); + CPIN_16(dinode, str, di_height); + CPIN_32(dinode, str, di_incarn); + CPIN_16(dinode, str, di_pad); + + CPIN_16(dinode, str, di_depth); + CPIN_32(dinode, str, di_entries); + + gfs_inum_in(&dinode->di_next_unused, (char *)&str->di_next_unused); + + CPIN_64(dinode, str, di_eattr); + + CPIN_08(dinode, str, di_reserved, 56); +} + +/** + * gfs_dinode_out - Write out a dinode + * @dinode: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_dinode_out(struct gfs_dinode *dinode, char *buf) +{ + struct gfs_dinode *str = (struct gfs_dinode *)buf; + + gfs_meta_header_out(&dinode->di_header, buf); + + gfs_inum_out(&dinode->di_num, (char *)&str->di_num); + + CPOUT_32(dinode, str, di_mode); + CPOUT_32(dinode, str, di_uid); + CPOUT_32(dinode, str, di_gid); + CPOUT_32(dinode, str, di_nlink); + CPOUT_64(dinode, str, di_size); + CPOUT_64(dinode, str, di_blocks); + CPOUT_64(dinode, str, di_atime); + CPOUT_64(dinode, str, di_mtime); + CPOUT_64(dinode, str, di_ctime); + CPOUT_32(dinode, str, di_major); + CPOUT_32(dinode, str, di_minor); + + CPOUT_64(dinode, str, di_rgrp); + CPOUT_64(dinode, str, di_goal_rgrp); + CPOUT_32(dinode, str, di_goal_dblk); + CPOUT_32(dinode, str, di_goal_mblk); + CPOUT_32(dinode, str, di_flags); + CPOUT_32(dinode, str, di_payload_format); + CPOUT_16(dinode, str, di_type); + CPOUT_16(dinode, str, di_height); + CPOUT_32(dinode, str, di_incarn); + CPOUT_16(dinode, str, di_pad); + + CPOUT_16(dinode, str, di_depth); + CPOUT_32(dinode, str, di_entries); + + gfs_inum_out(&dinode->di_next_unused, (char *)&str->di_next_unused); + + CPOUT_64(dinode, str, di_eattr); + + CPOUT_08(dinode, str, di_reserved, 56); +} + +/** + * gfs_dinode_print - Print out a dinode + * @di: the cpu-order buffer + * + */ + +void +gfs_dinode_print(struct gfs_dinode *di) +{ + gfs_meta_header_print(&di->di_header); + + gfs_inum_print(&di->di_num); + + pv(di, di_mode, "0%o"); + pv(di, di_uid, "%u"); + pv(di, di_gid, "%u"); + pv(di, di_nlink, "%u"); + pv(di, di_size, "%"PRIu64); + pv(di, di_blocks, "%"PRIu64); + pv(di, di_atime, "%"PRId64); + pv(di, di_mtime, "%"PRId64); + pv(di, di_ctime, "%"PRId64); + pv(di, di_major, "%u"); + pv(di, di_minor, "%u"); + + pv(di, di_rgrp, "%"PRIu64); + pv(di, di_goal_rgrp, "%"PRIu64); + pv(di, di_goal_dblk, "%u"); + pv(di, di_goal_mblk, "%u"); + pv(di, di_flags, "0x%.8X"); + pv(di, di_payload_format, "%u"); + pv(di, di_type, "%u"); + pv(di, di_height, "%u"); + pv(di, di_incarn, "%u"); + pv(di, di_pad, "%u"); + + pv(di, di_depth, "%u"); + pv(di, di_entries, "%u"); + + gfs_inum_print(&di->di_next_unused); + + pv(di, di_eattr, "%"PRIu64); + + pa(di, di_reserved, 56); +} + +/** + * gfs_indirect_in - copy in the header of an indirect block + * @indirect: the in memory copy + * @buf: the buffer copy + * + */ + +void +gfs_indirect_in(struct gfs_indirect *indirect, char *buf) +{ + struct gfs_indirect *str = (struct gfs_indirect *)buf; + + gfs_meta_header_in(&indirect->in_header, buf); + + CPIN_08(indirect, str, in_reserved, 64); +} + +/** + * gfs_indirect_out - copy out the header of an indirect block + * @indirect: the in memory copy + * @buf: the buffer copy + * + */ + +void +gfs_indirect_out(struct gfs_indirect *indirect, char *buf) +{ + struct gfs_indirect *str = (struct gfs_indirect *)buf; + + gfs_meta_header_out(&indirect->in_header, buf); + + CPOUT_08(indirect, str, in_reserved, 64); +} + +/** + * gfs_indirect_print - Print out a indirect block header + * @indirect: the cpu-order buffer + * + */ + +void +gfs_indirect_print(struct gfs_indirect *indirect) +{ + gfs_meta_header_print(&indirect->in_header); + + pa(indirect, in_reserved, 64); +} + +/** + * gfs_dirent_in - Read in a directory entry + * @dirent: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_dirent_in(struct gfs_dirent *dirent, char *buf) +{ + struct gfs_dirent *str = (struct gfs_dirent *)buf; + + gfs_inum_in(&dirent->de_inum, (char *)&str->de_inum); + CPIN_32(dirent, str, de_hash); + CPIN_16(dirent, str, de_rec_len); + CPIN_16(dirent, str, de_name_len); + CPIN_16(dirent, str, de_type); + + CPIN_08(dirent, str, de_reserved, 14); +} + +/** + * gfs_dirent_out - Write out a directory entry + * @dirent: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_dirent_out(struct gfs_dirent *dirent, char *buf) +{ + struct gfs_dirent *str = (struct gfs_dirent *)buf; + + gfs_inum_out(&dirent->de_inum, (char *)&str->de_inum); + CPOUT_32(dirent, str, de_hash); + CPOUT_16(dirent, str, de_rec_len); + CPOUT_16(dirent, str, de_name_len); + CPOUT_16(dirent, str, de_type); + + CPOUT_08(dirent, str, de_reserved, 14); +} + +/** + * gfs_dirent_print - Print out a directory entry + * @de: the cpu-order buffer + * @name: the filename + * + */ + +void +gfs_dirent_print(struct gfs_dirent *de, char *name) +{ + char buf[GFS_FNAMESIZE + 1]; + + gfs_inum_print(&de->de_inum); + pv(de, de_hash, "0x%.8X"); + pv(de, de_rec_len, "%u"); + pv(de, de_name_len, "%u"); + pv(de, de_type, "%u"); + + pa(de, de_reserved, 14); + + memset(buf, 0, GFS_FNAMESIZE + 1); + memcpy(buf, name, de->de_name_len); + printk(" name = %s\n", buf); +} + +/** + * gfs_leaf_in - Read in a directory leaf header + * @leaf: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_leaf_in(struct gfs_leaf *leaf, char *buf) +{ + struct gfs_leaf *str = (struct gfs_leaf *)buf; + + gfs_meta_header_in(&leaf->lf_header, buf); + + CPIN_16(leaf, str, lf_depth); + CPIN_16(leaf, str, lf_entries); + CPIN_32(leaf, str, lf_dirent_format); + CPIN_64(leaf, str, lf_next); + + CPIN_08(leaf, str, lf_reserved, 64); +} + +/** + * gfs_leaf_out - Write out a directory leaf header + * @leaf: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_leaf_out(struct gfs_leaf *leaf, char *buf) +{ + struct gfs_leaf *str = (struct gfs_leaf *)buf; + + gfs_meta_header_out(&leaf->lf_header, buf); + + CPOUT_16(leaf, str, lf_depth); + CPOUT_16(leaf, str, lf_entries); + CPOUT_32(leaf, str, lf_dirent_format); + CPOUT_64(leaf, str, lf_next); + + CPOUT_08(leaf, str, lf_reserved, 64); +} + +/** + * gfs_leaf_print - Print out a directory leaf header + * @lf: the cpu-order buffer + * + */ + +void +gfs_leaf_print(struct gfs_leaf *lf) +{ + gfs_meta_header_print(&lf->lf_header); + + pv(lf, lf_depth, "%u"); + pv(lf, lf_entries, "%u"); + pv(lf, lf_dirent_format, "%u"); + pv(lf, lf_next, "%"PRIu64); + + pa(lf, lf_reserved, 64); +} + +/** + * gfs_log_header_in - Read in a log header + * @head: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_log_header_in(struct gfs_log_header *head, char *buf) +{ + struct gfs_log_header *str = (struct gfs_log_header *)buf; + + gfs_meta_header_in(&head->lh_header, buf); + + CPIN_32(head, str, lh_flags); + CPIN_32(head, str, lh_pad); + + CPIN_64(head, str, lh_first); + CPIN_64(head, str, lh_sequence); + + CPIN_64(head, str, lh_tail); + CPIN_64(head, str, lh_last_dump); + + CPIN_08(head, str, lh_reserved, 64); +} + +/** + * gfs_log_header_out - Write out a log header + * @head: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_log_header_out(struct gfs_log_header *head, char *buf) +{ + struct gfs_log_header *str = (struct gfs_log_header *)buf; + + gfs_meta_header_out(&head->lh_header, buf); + + CPOUT_32(head, str, lh_flags); + CPOUT_32(head, str, lh_pad); + + CPOUT_64(head, str, lh_first); + CPOUT_64(head, str, lh_sequence); + + CPOUT_64(head, str, lh_tail); + CPOUT_64(head, str, lh_last_dump); + + CPOUT_08(head, str, lh_reserved, 64); +} + +/** + * gfs_log_header_print - Print out a log header + * @head: the cpu-order buffer + * + */ + +void +gfs_log_header_print(struct gfs_log_header *lh) +{ + gfs_meta_header_print(&lh->lh_header); + + pv(lh, lh_flags, "0x%.8X"); + pv(lh, lh_pad, "%u"); + + pv(lh, lh_first, "%"PRIu64); + pv(lh, lh_sequence, "%"PRIu64); + + pv(lh, lh_tail, "%"PRIu64); + pv(lh, lh_last_dump, "%"PRIu64); + + pa(lh, lh_reserved, 64); +} + +/** + * gfs_desc_in - Read in a log descriptor + * @desc: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_desc_in(struct gfs_log_descriptor *desc, char *buf) +{ + struct gfs_log_descriptor *str = (struct gfs_log_descriptor *)buf; + + gfs_meta_header_in(&desc->ld_header, buf); + + CPIN_32(desc, str, ld_type); + CPIN_32(desc, str, ld_length); + CPIN_32(desc, str, ld_data1); + CPIN_32(desc, str, ld_data2); + + CPIN_08(desc, str, ld_reserved, 64); +} + +/** + * gfs_desc_out - Write out a log descriptor + * @desc: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_desc_out(struct gfs_log_descriptor *desc, char *buf) +{ + struct gfs_log_descriptor *str = (struct gfs_log_descriptor *)buf; + + gfs_meta_header_out(&desc->ld_header, buf); + + CPOUT_32(desc, str, ld_type); + CPOUT_32(desc, str, ld_length); + CPOUT_32(desc, str, ld_data1); + CPOUT_32(desc, str, ld_data2); + + CPOUT_08(desc, str, ld_reserved, 64); +} + +/** + * gfs_desc_print - Print out a log descriptor + * @ld: the cpu-order buffer + * + */ + +void +gfs_desc_print(struct gfs_log_descriptor *ld) +{ + gfs_meta_header_print(&ld->ld_header); + + pv(ld, ld_type, "%u"); + pv(ld, ld_length, "%u"); + pv(ld, ld_data1, "%u"); + pv(ld, ld_data2, "%u"); + + pa(ld, ld_reserved, 64); +} + +/** + * gfs_block_tag_in - Read in a block tag + * @tag: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_block_tag_in(struct gfs_block_tag *tag, char *buf) +{ + struct gfs_block_tag *str = (struct gfs_block_tag *)buf; + + CPIN_64(tag, str, bt_blkno); + CPIN_32(tag, str, bt_flags); + CPIN_32(tag, str, bt_pad); +} + +/** + * gfs_block_tag_out - Write out a block tag + * @tag: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_block_tag_out(struct gfs_block_tag *tag, char *buf) +{ + struct gfs_block_tag *str = (struct gfs_block_tag *)buf; + + CPOUT_64(tag, str, bt_blkno); + CPOUT_32(tag, str, bt_flags); + CPOUT_32(tag, str, bt_pad); +} + +/** + * gfs_block_tag_print - Print out a block tag + * @tag: the cpu-order buffer + * + */ + +void +gfs_block_tag_print(struct gfs_block_tag *tag) +{ + pv(tag, bt_blkno, "%"PRIu64); + pv(tag, bt_flags, "%u"); + pv(tag, bt_pad, "%u"); +} + +/** + * gfs_quota_tag_in - Read in a quota tag + * @tag: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_quota_tag_in(struct gfs_quota_tag *tag, char *buf) +{ + struct gfs_quota_tag *str = (struct gfs_quota_tag *)buf; + + CPIN_64(tag, str, qt_change); + CPIN_32(tag, str, qt_flags); + CPIN_32(tag, str, qt_id); +} + +/** + * gfs_quota_tag_out - Write out a quota tag + * @tag: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_quota_tag_out(struct gfs_quota_tag *tag, char *buf) +{ + struct gfs_quota_tag *str = (struct gfs_quota_tag *)buf; + + CPOUT_64(tag, str, qt_change); + CPOUT_32(tag, str, qt_flags); + CPOUT_32(tag, str, qt_id); +} + +/** + * gfs_quota_tag_print - Print out a quota tag + * @tag: the cpu-order buffer + * + */ + +void +gfs_quota_tag_print(struct gfs_quota_tag *tag) +{ + pv(tag, qt_change, "%"PRId64); + pv(tag, qt_flags, "0x%.8X"); + pv(tag, qt_id, "%u"); +} + +/** + * gfs_ea_header_in - Read in a Extended Attribute header + * @tag: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_ea_header_in(struct gfs_ea_header *ea, char *buf) +{ + struct gfs_ea_header *str = (struct gfs_ea_header *)buf; + + CPIN_32(ea, str, ea_rec_len); + CPIN_32(ea, str, ea_data_len); + ea->ea_name_len = str->ea_name_len; + ea->ea_type = str->ea_type; + ea->ea_flags = str->ea_flags; + ea->ea_num_ptrs = str->ea_num_ptrs; + CPIN_32(ea, str, ea_pad); +} + +/** + * gfs_ea_header_out - Write out a Extended Attribute header + * @ea: the cpu-order structure + * @buf: the disk-order buffer + * + */ + +void +gfs_ea_header_out(struct gfs_ea_header *ea, char *buf) +{ + struct gfs_ea_header *str = (struct gfs_ea_header *)buf; + + CPOUT_32(ea, str, ea_rec_len); + CPOUT_32(ea, str, ea_data_len); + str->ea_name_len = ea->ea_name_len; + str->ea_type = ea->ea_type; + str->ea_flags = ea->ea_flags; + str->ea_num_ptrs = ea->ea_num_ptrs; + CPOUT_32(ea, str, ea_pad); +} + +/** + * gfs_ea_header_printt - Print out a Extended Attribute header + * @ea: the cpu-order buffer + * + */ + +void +gfs_ea_header_print(struct gfs_ea_header *ea, char *name) +{ + char buf[GFS_EA_MAX_NAME_LEN + 1]; + + pv(ea, ea_rec_len, "%u"); + pv(ea, ea_data_len, "%u"); + pv(ea, ea_name_len, "%u"); + pv(ea, ea_type, "%u"); + pv(ea, ea_flags, "%u"); + pv(ea, ea_num_ptrs, "%u"); + pv(ea, ea_pad, "%u"); + + memset(buf, 0, GFS_EA_MAX_NAME_LEN + 1); + memcpy(buf, name, ea->ea_name_len); + printk(" name = %s\n", buf); +} + +static const uint32_t crc_32_tab[] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +/** + * gfs_dir_hash - hash an array of data + * @data: the data to be hashed + * @len: the length of data to be hashed + * + * Take some data and convert it to a 32-bit hash. + * + * The hash function is a 32-bit CRC of the data. The algorithm uses + * the crc_32_tab table above. + * + * This may not be the fastest hash function, but it does a fair bit better + * at providing uniform results than the others I've looked at. That's + * really important for efficient directories. + * + * Returns: the hash + */ + +uint32_t +gfs_dir_hash(const char *data, int len) +{ + uint32_t hash = 0xFFFFFFFF; + + for (; len--; data++) + hash = crc_32_tab[(hash ^ *data) & 0xFF] ^ (hash >> 8); + + hash = ~hash; + + return hash; +} + +#endif /* WANT_GFS_CONVERSION_FUNCTIONS */ + --- linux-2.6.27.orig/ubuntu/gfs/bits.c +++ linux-2.6.27/ubuntu/gfs/bits.c @@ -0,0 +1,211 @@ +/* + * These routines are used by the resource group routines (rgrp.c) + * to keep track of block allocation. Each block is represented by two + * bits. One bit indicates whether or not the block is used. (1=used, + * 0=free) The other bit indicates whether or not the block contains a + * dinode or not. (1=dinode, 0=data block) So, each byte represents + * GFS_NBBY (i.e. 4) blocks. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bits.h" + +#if BITS_PER_LONG == 32 +#define LBITMASK (0x55555555UL) +#define LBITSKIP55 (0x55555555UL) +#define LBITSKIP00 (0x00000000UL) +#else +#define LBITMASK (0x5555555555555555UL) +#define LBITSKIP55 (0x5555555555555555UL) +#define LBITSKIP00 (0x0000000000000000UL) +#endif + +static const char valid_change[16] = { + /* current */ + /* n */ 0, 1, 1, 1, + /* e */ 1, 0, 0, 0, + /* w */ 1, 0, 0, 1, + 0, 0, 1, 0 +}; + +/** + * gfs_setbit - Set a bit in the bitmaps + * @buffer: the buffer that holds the bitmaps + * @buflen: the length (in bytes) of the buffer + * @block: the block to set + * @new_state: the new state of the block + * + */ + +void +gfs_setbit(struct gfs_rgrpd *rgd, + unsigned char *buffer, unsigned int buflen, + uint32_t block, unsigned char new_state) +{ + unsigned char *byte, *end, cur_state; + unsigned int bit; + + byte = buffer + (block / GFS_NBBY); + bit = (block % GFS_NBBY) * GFS_BIT_SIZE; + end = buffer + buflen; + + gfs_assert(rgd->rd_sbd, byte < end,); + + cur_state = (*byte >> bit) & GFS_BIT_MASK; + + if (valid_change[new_state * 4 + cur_state]) { + *byte ^= cur_state << bit; + *byte |= new_state << bit; + } else + gfs_consist_rgrpd(rgd); +} + +/** + * gfs_testbit - test a bit in the bitmaps + * @buffer: the buffer that holds the bitmaps + * @buflen: the length (in bytes) of the buffer + * @block: the block to read + * + */ + +unsigned char +gfs_testbit(struct gfs_rgrpd *rgd, + unsigned char *buffer, unsigned int buflen, uint32_t block) +{ + unsigned char *byte, *end, cur_state; + unsigned int bit; + + byte = buffer + (block / GFS_NBBY); + bit = (block % GFS_NBBY) * GFS_BIT_SIZE; + end = buffer + buflen; + + gfs_assert(rgd->rd_sbd, byte < end,); + + cur_state = (*byte >> bit) & GFS_BIT_MASK; + + return cur_state; +} + +/** + * gfs_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing + * a block in a given allocation state. + * @buffer: the buffer that holds the bitmaps + * @buflen: the length (in bytes) of the buffer + * @goal: start search at this block's bit-pair (within @buffer) + * @old_state: GFS_BLKST_XXX the state of the block we're looking for; + * bit 0 = alloc(1)/free(0), bit 1 = meta(1)/data(0) + * + * Scope of @goal and returned block number is only within this bitmap buffer, + * not entire rgrp or filesystem. + * @buffer will be offset from the actual beginning of a bitmap block buffer, + * skipping any header structures. + * + * Return: the block number (bitmap buffer scope) that was found + */ + +uint32_t +gfs_bitfit(unsigned char *buffer, unsigned int buflen, + uint32_t goal, unsigned char old_state) +{ + const u8 *byte, *start, *end; + int bit, startbit; + u32 g1, g2, misaligned; + unsigned long *plong; + unsigned long lskipval; + + lskipval = (old_state & GFS_BLKST_USED) ? LBITSKIP00 : LBITSKIP55; + g1 = (goal / GFS_NBBY); + start = buffer + g1; + byte = start; + end = buffer + buflen; + g2 = ALIGN(g1, sizeof(unsigned long)); + plong = (unsigned long *)(buffer + g2); + startbit = bit = (goal % GFS_NBBY) * GFS_BIT_SIZE; + misaligned = g2 - g1; + if (!misaligned) + goto ulong_aligned; +/* parse the bitmap a byte at a time */ +misaligned: + while (byte < end) { + if (((*byte >> bit) & GFS_BIT_MASK) == old_state) { + return goal + + (((byte - start) * GFS_NBBY) + + ((bit - startbit) >> 1)); + } + bit += GFS_BIT_SIZE; + if (bit >= GFS_NBBY * GFS_BIT_SIZE) { + bit = 0; + byte++; + misaligned--; + if (!misaligned) { + plong = (unsigned long *)byte; + goto ulong_aligned; + } + } + } + return BFITNOENT; + +/* parse the bitmap a unsigned long at a time */ +ulong_aligned: + /* Stop at "end - 1" or else prefetch can go past the end and segfault. + We could "if" it but we'd lose some of the performance gained. + This way will only slow down searching the very last 4/8 bytes + depending on architecture. I've experimented with several ways + of writing this section such as using an else before the goto + but this one seems to be the fastest. */ + while ((unsigned char *)plong < end - sizeof(unsigned long)) { + prefetch(plong + 1); + if (((*plong) & LBITMASK) != lskipval) + break; + plong++; + } + if ((unsigned char *)plong < end) { + byte = (const u8 *)plong; + misaligned += sizeof(unsigned long) - 1; + goto misaligned; + } + return BFITNOENT; +} + +/** + * gfs_bitcount - count the number of bits in a certain state + * @buffer: the buffer that holds the bitmaps + * @buflen: the length (in bytes) of the buffer + * @state: the state of the block we're looking for + * + * Returns: The number of bits + */ + +uint32_t +gfs_bitcount(struct gfs_rgrpd *rgd, + unsigned char *buffer, unsigned int buflen, + unsigned char state) +{ + unsigned char *byte = buffer; + unsigned char *end = buffer + buflen; + unsigned char state1 = state << 2; + unsigned char state2 = state << 4; + unsigned char state3 = state << 6; + uint32_t count = 0; + + for (; byte < end; byte++) { + if (((*byte) & 0x03) == state) + count++; + if (((*byte) & 0x0C) == state1) + count++; + if (((*byte) & 0x30) == state2) + count++; + if (((*byte) & 0xC0) == state3) + count++; + } + + return count; +} --- linux-2.6.27.orig/ubuntu/gfs/bmap.h +++ linux-2.6.27/ubuntu/gfs/bmap.h @@ -0,0 +1,35 @@ +#ifndef __BMAP_DOT_H__ +#define __BMAP_DOT_H__ + +typedef int (*gfs_unstuffer_t) (struct gfs_inode * ip, + struct buffer_head * dibh, uint64_t block, + void *private); + +int gfs_unstuffer_sync(struct gfs_inode *ip, struct buffer_head *dibh, + uint64_t block, void *private); +int gfs_unstuffer_async(struct gfs_inode *ip, struct buffer_head *dibh, + uint64_t block, void *private); + +int gfs_unstuff_dinode(struct gfs_inode *ip, gfs_unstuffer_t unstuffer, + void *private); + +int gfs_block_map(struct gfs_inode *ip, + uint64_t lblock, int *new, + uint64_t *dblock, uint32_t *extlen); + +typedef int (*gfs_truncator_t) (struct gfs_inode * ip, uint64_t size); + +int gfs_truncator_default(struct gfs_inode *ip, uint64_t size); + +int gfs_shrink(struct gfs_inode *ip, uint64_t size, gfs_truncator_t truncator); +int gfs_truncatei(struct gfs_inode *ip, uint64_t size, + gfs_truncator_t truncator); + +void gfs_write_calc_reserv(struct gfs_inode *ip, unsigned int len, + unsigned int *data_blocks, unsigned int *ind_blocks); +int gfs_write_alloc_required(struct gfs_inode *ip, uint64_t offset, + unsigned int len, int *alloc_required); + +int gfs_get_file_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub); + +#endif /* __BMAP_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lock_nolock_main.c +++ linux-2.6.27/ubuntu/gfs/lock_nolock_main.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include +#include +#include +#include +#include +#include "lm_interface.h" + +struct nolock_lockspace { + unsigned int nl_lvb_size; +}; + +static const struct lm_lockops nolock_ops; + +static int nolock_mount(char *table_name, char *host_data, + lm_callback_t cb, void *cb_data, + unsigned int min_lvb_size, int flags, + struct lm_lockstruct *lockstruct, + struct kobject *fskobj) +{ + char *c; + unsigned int jid; + struct nolock_lockspace *nl; + + c = strstr(host_data, "jid="); + if (!c) + jid = 0; + else { + c += 4; + sscanf(c, "%u", &jid); + } + + nl = kzalloc(sizeof(struct nolock_lockspace), GFP_KERNEL); + if (!nl) + return -ENOMEM; + + nl->nl_lvb_size = min_lvb_size; + + lockstruct->ls_jid = jid; + lockstruct->ls_first = 1; + lockstruct->ls_lvb_size = min_lvb_size; + lockstruct->ls_lockspace = nl; + lockstruct->ls_ops = &nolock_ops; + lockstruct->ls_flags = LM_LSFLAG_LOCAL; + + return 0; +} + +static void nolock_others_may_mount(void *lockspace) +{ +} + +static void nolock_unmount(void *lockspace) +{ + struct nolock_lockspace *nl = lockspace; + kfree(nl); +} + +static void nolock_withdraw(void *lockspace) +{ +} + +/** + * nolock_get_lock - get a lm_lock_t given a descripton of the lock + * @lockspace: the lockspace the lock lives in + * @name: the name of the lock + * @lockp: return the lm_lock_t here + * + * Returns: 0 on success, -EXXX on failure + */ + +static int nolock_get_lock(void *lockspace, struct lm_lockname *name, + void **lockp) +{ + *lockp = lockspace; + return 0; +} + +/** + * nolock_put_lock - get rid of a lock structure + * @lock: the lock to throw away + * + */ + +static void nolock_put_lock(void *lock) +{ +} + +/** + * nolock_lock - acquire a lock + * @lock: the lock to manipulate + * @cur_state: the current state + * @req_state: the requested state + * @flags: modifier flags + * + * Returns: A bitmap of LM_OUT_* + */ + +static unsigned int nolock_lock(void *lock, unsigned int cur_state, + unsigned int req_state, unsigned int flags) +{ + return req_state | LM_OUT_CACHEABLE; +} + +/** + * nolock_unlock - unlock a lock + * @lock: the lock to manipulate + * @cur_state: the current state + * + * Returns: 0 + */ + +static unsigned int nolock_unlock(void *lock, unsigned int cur_state) +{ + return 0; +} + +static void nolock_cancel(void *lock) +{ +} + +/** + * nolock_hold_lvb - hold on to a lock value block + * @lock: the lock the LVB is associated with + * @lvbp: return the lm_lvb_t here + * + * Returns: 0 on success, -EXXX on failure + */ + +static int nolock_hold_lvb(void *lock, char **lvbp) +{ + struct nolock_lockspace *nl = lock; + int error = 0; + + *lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS); + if (!*lvbp) + error = -ENOMEM; + + return error; +} + +/** + * nolock_unhold_lvb - release a LVB + * @lock: the lock the LVB is associated with + * @lvb: the lock value block + * + */ + +static void nolock_unhold_lvb(void *lock, char *lvb) +{ + kfree(lvb); +} + +static int nolock_plock_get(void *lockspace, struct lm_lockname *name, + struct file *file, struct file_lock *fl) +{ + posix_test_lock(file, fl); + + return 0; +} + +static int nolock_plock(void *lockspace, struct lm_lockname *name, + struct file *file, int cmd, struct file_lock *fl) +{ + int error; + error = posix_lock_file_wait(file, fl); + return error; +} + +static int nolock_punlock(void *lockspace, struct lm_lockname *name, + struct file *file, struct file_lock *fl) +{ + int error; + error = posix_lock_file_wait(file, fl); + return error; +} + +static void nolock_recovery_done(void *lockspace, unsigned int jid, + unsigned int message) +{ +} + +static const struct lm_lockops nolock_ops = { + .lm_proto_name = "lock_nolock", + .lm_mount = nolock_mount, + .lm_others_may_mount = nolock_others_may_mount, + .lm_unmount = nolock_unmount, + .lm_withdraw = nolock_withdraw, + .lm_get_lock = nolock_get_lock, + .lm_put_lock = nolock_put_lock, + .lm_lock = nolock_lock, + .lm_unlock = nolock_unlock, + .lm_cancel = nolock_cancel, + .lm_hold_lvb = nolock_hold_lvb, + .lm_unhold_lvb = nolock_unhold_lvb, + .lm_plock_get = nolock_plock_get, + .lm_plock = nolock_plock, + .lm_punlock = nolock_punlock, + .lm_recovery_done = nolock_recovery_done, + .lm_owner = THIS_MODULE, +}; + +int init_nolock() +{ + int error; + + error = gfs_register_lockproto(&nolock_ops); + if (error) { + printk(KERN_WARNING + "lock_nolock: can't register protocol: %d\n", error); + return error; + } + + printk(KERN_INFO + "Lock_Nolock (built %s %s) installed\n", __DATE__, __TIME__); + return 0; +} + +void exit_nolock() +{ + gfs_unregister_lockproto(&nolock_ops); +} --- linux-2.6.27.orig/ubuntu/gfs/super.c +++ linux-2.6.27/ubuntu/gfs/super.c @@ -0,0 +1,1274 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "file.h" +#include "format.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "log.h" +#include "quota.h" +#include "recovery.h" +#include "rgrp.h" +#include "super.h" +#include "unlinked.h" +#include "trans.h" + +/** + * gfs_tune_init - Fill a gfs_tune structure with default values + * @gt: tune + * + */ + +void +gfs_tune_init(struct gfs_tune *gt) +{ + spin_lock_init(>->gt_spin); + + gt->gt_ilimit1 = 100; + gt->gt_ilimit1_tries = 3; + gt->gt_ilimit1_min = 1; + gt->gt_ilimit2 = 500; + gt->gt_ilimit2_tries = 10; + gt->gt_ilimit2_min = 3; + gt->gt_demote_secs = 300; + gt->gt_incore_log_blocks = 1024; + gt->gt_jindex_refresh_secs = 60; + gt->gt_depend_secs = 60; + gt->gt_scand_secs = 5; + gt->gt_recoverd_secs = 60; + gt->gt_logd_secs = 1; + gt->gt_quotad_secs = 5; + gt->gt_inoded_secs = 15; + gt->gt_glock_purge = 0; + gt->gt_quota_simul_sync = 64; + gt->gt_quota_warn_period = 10; + gt->gt_atime_quantum = 3600; + gt->gt_quota_quantum = 60; + gt->gt_quota_scale_num = 1; + gt->gt_quota_scale_den = 1; + gt->gt_quota_enforce = 1; + gt->gt_quota_account = 1; + gt->gt_new_files_jdata = 0; + gt->gt_new_files_directio = 0; + gt->gt_max_atomic_write = 4 << 20; + gt->gt_max_readahead = 1 << 18; + gt->gt_lockdump_size = 131072; + gt->gt_stall_secs = 600; + gt->gt_complain_secs = 10; + gt->gt_reclaim_limit = 5000; + gt->gt_entries_per_readdir = 32; + gt->gt_prefetch_secs = 10; + gt->gt_statfs_slots = 64; + gt->gt_max_mhc = 10000; + gt->gt_greedy_default = HZ / 10; + gt->gt_greedy_quantum = HZ / 40; + gt->gt_greedy_max = HZ / 4; + gt->gt_rgrp_try_threshold = 100; + gt->gt_statfs_fast = 0; +} + +/** + * gfs_check_sb - Check superblock + * @sdp: the filesystem + * @sb: The superblock + * @silent: Don't print a message if the check fails + * + * Checks the version code of the FS is one that we understand how to + * read and that the sizes of the various on-disk structures have not + * changed. + */ + +int +gfs_check_sb(struct gfs_sbd *sdp, struct gfs_sb *sb, int silent) +{ + unsigned int x; + + if (sb->sb_header.mh_magic != GFS_MAGIC || + sb->sb_header.mh_type != GFS_METATYPE_SB) { + if (!silent) + printk("GFS: not a GFS filesystem\n"); + return -EINVAL; + } + + /* If format numbers match exactly, we're done. */ + + if (sb->sb_fs_format == GFS_FORMAT_FS && + sb->sb_multihost_format == GFS_FORMAT_MULTI) + return 0; + + if (sb->sb_fs_format != GFS_FORMAT_FS) { + for (x = 0; gfs_old_fs_formats[x]; x++) + if (gfs_old_fs_formats[x] == sb->sb_fs_format) + break; + + if (!gfs_old_fs_formats[x]) { + printk("GFS: code version (%u, %u) is incompatible with ondisk format (%u, %u)\n", + GFS_FORMAT_FS, GFS_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk("GFS: I don't know how to upgrade this FS\n"); + return -EINVAL; + } + } + + if (sb->sb_multihost_format != GFS_FORMAT_MULTI) { + for (x = 0; gfs_old_multihost_formats[x]; x++) + if (gfs_old_multihost_formats[x] == sb->sb_multihost_format) + break; + + if (!gfs_old_multihost_formats[x]) { + printk("GFS: code version (%u, %u) is incompatible with ondisk format (%u, %u)\n", + GFS_FORMAT_FS, GFS_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk("GFS: I don't know how to upgrade this FS\n"); + return -EINVAL; + } + } + + if (!sdp->sd_args.ar_upgrade) { + printk("GFS: code version (%u, %u) is incompatible with ondisk format (%u, %u)\n", + GFS_FORMAT_FS, GFS_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk("GFS: Use the \"upgrade\" mount option to upgrade the FS\n"); + printk("GFS: See the manual for more details\n"); + return -EINVAL; + } + + return 0; +} + +/** + * gfs_read_sb - Read super block + * @sdp: The GFS superblock + * @gl: the glock for the superblock (assumed to be held) + * @silent: Don't print message if mount fails + * + */ + +int +gfs_read_sb(struct gfs_sbd *sdp, struct gfs_glock *gl, int silent) +{ + struct buffer_head *bh; + uint32_t hash_blocks, ind_blocks, leaf_blocks; + uint32_t tmp_blocks; + unsigned int x; + int error; + + error = gfs_dread(gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift, + DIO_FORCE | DIO_START | DIO_WAIT, &bh); + if (error) { + if (!silent) + printk("GFS: fsid=%s: can't read superblock\n", + sdp->sd_fsname); + return error; + } + + gfs_assert(sdp, sizeof(struct gfs_sb) <= bh->b_size,); + gfs_sb_in(&sdp->sd_sb, bh->b_data); + brelse(bh); + + error = gfs_check_sb(sdp, &sdp->sd_sb, silent); + if (error) + return error; + + sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - + GFS_BASIC_BLOCK_SHIFT; + sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; + sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) / + sizeof(uint64_t); + sdp->sd_inptrs = (sdp->sd_sb.sb_bsize - sizeof(struct gfs_indirect)) / + sizeof(uint64_t); + sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs_meta_header); + sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2; + sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1; + sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t); + + /* Compute maximum reservation required to add a entry to a directory */ + + hash_blocks = DIV_RU(sizeof(uint64_t) * (1 << GFS_DIR_MAX_DEPTH), + sdp->sd_jbsize); + + ind_blocks = 0; + for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) { + tmp_blocks = DIV_RU(tmp_blocks, sdp->sd_inptrs); + ind_blocks += tmp_blocks; + } + + leaf_blocks = 2 + GFS_DIR_MAX_DEPTH; + + sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks; + + sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode); + sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs; + for (x = 2;; x++) { + uint64_t space, d; + uint32_t m; + + space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs; + d = space; + m = do_div(d, sdp->sd_inptrs); + + if (d != sdp->sd_heightsize[x - 1] || m) + break; + sdp->sd_heightsize[x] = space; + } + sdp->sd_max_height = x; + gfs_assert(sdp, sdp->sd_max_height <= GFS_MAX_META_HEIGHT,); + + sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode); + sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs; + for (x = 2;; x++) { + uint64_t space, d; + uint32_t m; + + space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs; + d = space; + m = do_div(d, sdp->sd_inptrs); + + if (d != sdp->sd_jheightsize[x - 1] || m) + break; + sdp->sd_jheightsize[x] = space; + } + sdp->sd_max_jheight = x; + gfs_assert(sdp, sdp->sd_max_jheight <= GFS_MAX_META_HEIGHT,); + + return 0; +} + +/** + * gfs_do_upgrade - upgrade a filesystem + * @sdp: The GFS superblock + * + */ + +int +gfs_do_upgrade(struct gfs_sbd *sdp, struct gfs_glock *sb_gl) +{ + struct gfs_holder ji_gh, t_gh, j_gh; + struct gfs_log_header lh; + struct buffer_head *bh; + unsigned int x; + int error; + + /* If format numbers match exactly, we're done. */ + + if (sdp->sd_sb.sb_fs_format == GFS_FORMAT_FS && + sdp->sd_sb.sb_multihost_format == GFS_FORMAT_MULTI) { + printk("GFS: fsid=%s: no upgrade necessary\n", + sdp->sd_fsname); + sdp->sd_args.ar_upgrade = FALSE; + return 0; + } + + error = gfs_jindex_hold(sdp, &ji_gh); + if (error) + goto fail; + + error = gfs_glock_nq_init(sdp->sd_trans_gl, + LM_ST_EXCLUSIVE, GL_NOCACHE, + &t_gh); + if (error) + goto fail_ji_relse; + + if (test_bit(SDF_ROFS, &sdp->sd_flags)) { + printk("GFS: fsid=%s: can't upgrade: read-only FS\n", + sdp->sd_fsname); + error = -EROFS; + goto fail_gunlock_tr; + } + + for (x = 0; x < sdp->sd_journals; x++) { + error = gfs_glock_nq_num(sdp, + sdp->sd_jindex[x].ji_addr, + &gfs_meta_glops, LM_ST_SHARED, + LM_FLAG_TRY | GL_NOCACHE, &j_gh); + switch (error) { + case 0: + break; + + case GLR_TRYFAILED: + printk("GFS: fsid=%s: journal %u is busy\n", + sdp->sd_fsname, x); + error = -EBUSY; + + default: + goto fail_gunlock_tr; + } + + error = gfs_find_jhead(sdp, &sdp->sd_jindex[x], + j_gh.gh_gl, &lh); + + gfs_glock_dq_uninit(&j_gh); + + if (error) + goto fail_gunlock_tr; + + if (!(lh.lh_flags & GFS_LOG_HEAD_UNMOUNT) || lh.lh_last_dump) { + printk("GFS: fsid=%s: journal %u is busy\n", + sdp->sd_fsname, x); + error = -EBUSY; + goto fail_gunlock_tr; + } + } + + /* We don't need to journal this change because we're changing + only one sector of one block. We definitely don't want to have + the journaling code running at this point. */ + + error = gfs_dread(sb_gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift, + DIO_START | DIO_WAIT, &bh); + if (error) + goto fail_gunlock_tr; + + gfs_sb_in(&sdp->sd_sb, bh->b_data); + + error = gfs_check_sb(sdp, &sdp->sd_sb, FALSE); + if (error) { + gfs_consist(sdp); + brelse(bh); + goto fail_gunlock_tr; + } + + sdp->sd_sb.sb_fs_format = GFS_FORMAT_FS; + sdp->sd_sb.sb_multihost_format = GFS_FORMAT_MULTI; + + gfs_sb_out(&sdp->sd_sb, bh->b_data); + + set_bit(GLF_DIRTY, &sb_gl->gl_flags); + error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT); + + brelse(bh); + + gfs_glock_dq_uninit(&t_gh); + + gfs_glock_dq_uninit(&ji_gh); + + if (!error) { + printk("GFS: fsid=%s: upgrade successful\n", + sdp->sd_fsname); + sdp->sd_args.ar_upgrade = FALSE; + } + + return error; + + fail_gunlock_tr: + gfs_glock_dq_uninit(&t_gh); + + fail_ji_relse: + gfs_glock_dq_uninit(&ji_gh); + + fail: + if (error == -EBUSY) + printk("GFS: fsid=%s: can't upgrade: the FS is still busy or contains dirty journals\n", + sdp->sd_fsname); + else + printk("GFS: fsid=%s: can't upgrade: %d\n", + sdp->sd_fsname, error); + + return error; +} + +/** + * clear_journalsi - Clear all the journal index information (without locking) + * @sdp: The GFS superblock + * + */ + +static void +clear_journalsi(struct gfs_sbd *sdp) +{ + if (sdp->sd_jindex) { + kfree(sdp->sd_jindex); + sdp->sd_jindex = NULL; + } + sdp->sd_journals = 0; +} + +/** + * gfs_clear_journals - Clear all the journal index information + * @sdp: The GFS superblock + * + */ + +void +gfs_clear_journals(struct gfs_sbd *sdp) +{ + down(&sdp->sd_jindex_lock); + clear_journalsi(sdp); + up(&sdp->sd_jindex_lock); +} + +/** + * gfs_ji_update - Update the journal index information + * @ip: The journal index inode + * + * Returns: errno + */ + +static int +gfs_ji_update(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + char buf[sizeof(struct gfs_jindex)]; + unsigned int j; + int error; + + if (do_mod(ip->i_di.di_size, sizeof(struct gfs_jindex))) { + gfs_consist_inode(ip); + return -EIO; + } + + clear_journalsi(sdp); + + sdp->sd_jindex = kmalloc(ip->i_di.di_size, GFP_KERNEL); + if (!sdp->sd_jindex) + return -ENOMEM; + memset(sdp->sd_jindex, 0, ip->i_di.di_size); + + for (j = 0;; j++) { + error = gfs_internal_read(ip, buf, + j * sizeof(struct gfs_jindex), + sizeof(struct gfs_jindex)); + if (!error) + break; + if (error != sizeof(struct gfs_jindex)) { + if (error > 0) + error = -EIO; + goto fail; + } + + gfs_jindex_in(sdp->sd_jindex + j, buf); + } + + sdp->sd_journals = j; + sdp->sd_jiinode_vn = ip->i_gl->gl_vn; + + return 0; + + fail: + clear_journalsi(sdp); + return error; +} + +/** + * gfs_jindex_hold - Grab a lock on the jindex + * @sdp: The GFS superblock + * @ji_gh: the holder for the jindex glock + * + * This makes sure that we're using the latest copy of the journal index + * special file (this describes all of the journals for this filesystem), + * which might have been updated if someone added journals + * (via gfs_jadd utility). + * + * This is very similar to the gfs_rindex_hold() function, except that + * in general we hold the jindex lock for longer periods of time and + * we grab it far less frequently (in general) then the rgrp lock. + * + * Returns: errno + */ + +int +gfs_jindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ji_gh) +{ + struct gfs_inode *ip = sdp->sd_jiinode; + struct gfs_glock *gl = ip->i_gl; + int error; + + error = gfs_glock_nq_init(gl, LM_ST_SHARED, 0, ji_gh); + if (error) + return error; + + /* Read new copy from disk if we don't have the latest */ + if (sdp->sd_jiinode_vn != gl->gl_vn) { + down(&sdp->sd_jindex_lock); + if (sdp->sd_jiinode_vn != gl->gl_vn) + error = gfs_ji_update(ip); + up(&sdp->sd_jindex_lock); + } + + if (error) + gfs_glock_dq_uninit(ji_gh); + + return error; +} + +/** + * gfs_get_jiinode - Read-in the special (hidden) journal index inode + * @sdp: The GFS superblock + * + * Returns: errno + * + * This reads-in just the dinode, not the special file contents that describe + * the journals themselves (see gfs_jindex_hold()). + */ + +int +gfs_get_jiinode(struct gfs_sbd *sdp) +{ + struct gfs_holder ji_gh; + int error; + + error = gfs_glock_nq_num(sdp, + sdp->sd_sb.sb_jindex_di.no_formal_ino, + &gfs_inode_glops, + LM_ST_SHARED, GL_LOCAL_EXCL, + &ji_gh); + if (error) + return error; + + error = gfs_inode_get(ji_gh.gh_gl, &sdp->sd_sb.sb_jindex_di, + CREATE, &sdp->sd_jiinode); + if (!error) { + sdp->sd_jiinode_vn = ji_gh.gh_gl->gl_vn - 1; + set_bit(GLF_STICKY, &ji_gh.gh_gl->gl_flags); + } + + gfs_glock_dq_uninit(&ji_gh); + + return error; +} + +/** + * gfs_get_riinode - Read in the special (hidden) resource group index inode + * @sdp: The GFS superblock + * + * Returns: errno + * + * This reads-in just the dinode, not the special file contents that describe + * the resource groups themselves (see gfs_rindex_hold()). + */ + +int +gfs_get_riinode(struct gfs_sbd *sdp) +{ + struct gfs_holder ri_gh; + int error; + + error = gfs_glock_nq_num(sdp, + sdp->sd_sb.sb_rindex_di.no_formal_ino, + &gfs_inode_glops, + LM_ST_SHARED, GL_LOCAL_EXCL, + &ri_gh); + if (error) + return error; + + error = gfs_inode_get(ri_gh.gh_gl, &sdp->sd_sb.sb_rindex_di, + CREATE, &sdp->sd_riinode); + if (!error) { + sdp->sd_riinode_vn = ri_gh.gh_gl->gl_vn - 1; + set_bit(GLF_STICKY, &ri_gh.gh_gl->gl_flags); + } + + gfs_glock_dq_uninit(&ri_gh); + + return error; +} + +/** + * gfs_get_rootinode - Read in the filesystem's root inode + * @sdp: The GFS superblock + * + * Returns: errno + */ + +int +gfs_get_rootinode(struct gfs_sbd *sdp) +{ + struct gfs_holder i_gh; + int error; + + error = gfs_glock_nq_num(sdp, + sdp->sd_sb.sb_root_di.no_formal_ino, + &gfs_inode_glops, + LM_ST_SHARED, GL_LOCAL_EXCL, + &i_gh); + if (error) + return error; + + error = gfs_inode_get(i_gh.gh_gl, &sdp->sd_sb.sb_root_di, + CREATE, &sdp->sd_rooti); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_get_qinode - Read in the special (hidden) quota inode + * @sdp: The GFS superblock + * + * If one is not on-disk already, create a new one. + * Does not read in file contents, just the dinode. + * + * Returns: errno + */ + +int +gfs_get_qinode(struct gfs_sbd *sdp) +{ + struct gfs_holder i_gh; + int error; + + /* Create, if not on-disk already */ + if (!sdp->sd_sb.sb_quota_di.no_formal_ino) { + error = gfs_alloc_qinode(sdp); + if (error) + return error; + } + + error = gfs_glock_nq_num(sdp, + sdp->sd_sb.sb_quota_di.no_formal_ino, + &gfs_inode_glops, + LM_ST_SHARED, GL_LOCAL_EXCL, + &i_gh); + if (error) + return error; + + error = gfs_inode_get(i_gh.gh_gl, &sdp->sd_sb.sb_quota_di, + CREATE, &sdp->sd_qinode); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_get_linode - Read in the special (hidden) license inode + * @sdp: The GFS superblock + * + * If one is not on-disk already, create a new one. + * Does not read in file contents, just the dinode. + * + * Returns: errno + */ + +int +gfs_get_linode(struct gfs_sbd *sdp) +{ + struct gfs_holder i_gh; + int error; + + /* Create, if not on-disk already */ + if (!sdp->sd_sb.sb_license_di.no_formal_ino) { + error = gfs_alloc_linode(sdp); + if (error) + return error; + } + + error = gfs_glock_nq_num(sdp, + sdp->sd_sb.sb_license_di.no_formal_ino, + &gfs_inode_glops, + LM_ST_SHARED, GL_LOCAL_EXCL, + &i_gh); + if (error) + return error; + + /* iopen obtained in via gfs_glock_get(..gfs_iopen_glops) */ + error = gfs_inode_get(i_gh.gh_gl, &sdp->sd_sb.sb_license_di, + CREATE, &sdp->sd_linode); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_make_fs_rw - Turn a Read-Only FS into a Read-Write one + * @sdp: the filesystem + * + * Returns: errno + */ + +int +gfs_make_fs_rw(struct gfs_sbd *sdp) +{ + struct gfs_glock *j_gl = sdp->sd_journal_gh.gh_gl; + struct gfs_holder t_gh; + struct gfs_log_header head; + int error; + + error = gfs_glock_nq_init(sdp->sd_trans_gl, + LM_ST_SHARED, + GL_LOCAL_EXCL | GL_EXACT, + &t_gh); + if (error) + return error; + + j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA); + + error = gfs_find_jhead(sdp, &sdp->sd_jdesc, j_gl, &head); + if (error) + goto fail; + + if (!(head.lh_flags & GFS_LOG_HEAD_UNMOUNT)) { + gfs_consist(sdp); + error = -EIO; + goto fail; + } + + /* Initialize some head of the log stuff */ + sdp->sd_sequence = head.lh_sequence; + sdp->sd_log_head = head.lh_first + 1; + + error = gfs_recover_dump(sdp); + if (error) + goto fail; + + set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); + clear_bit(SDF_ROFS, &sdp->sd_flags); + + set_bit(GLF_DIRTY, &j_gl->gl_flags); + gfs_log_dump(sdp, TRUE); + + gfs_glock_dq_uninit(&t_gh); + + return 0; + + fail: + t_gh.gh_flags |= GL_NOCACHE; + gfs_glock_dq_uninit(&t_gh); + + return error; +} + +/** + * gfs_make_fs_ro - Turn a Read-Write FS into a Read-Only one + * @sdp: the filesystem + * + * Returns: errno + */ + +int +gfs_make_fs_ro(struct gfs_sbd *sdp) +{ + struct gfs_holder t_gh; + int error; + + error = gfs_glock_nq_init(sdp->sd_trans_gl, + LM_ST_SHARED, + GL_LOCAL_EXCL | GL_EXACT | GL_NOCACHE, + &t_gh); + if (error && + !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + return error; + + gfs_statfs_sync(sdp); + + gfs_log_flush(sdp); + gfs_quota_sync(sdp); + gfs_quota_scan(sdp); + + gfs_sync_meta(sdp); + gfs_log_dump(sdp, TRUE); + gfs_log_shutdown(sdp); + + set_bit(SDF_ROFS, &sdp->sd_flags); + clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); + + if (t_gh.gh_gl) + gfs_glock_dq_uninit(&t_gh); + + gfs_unlinked_cleanup(sdp); + gfs_quota_cleanup(sdp); + + return error; +} + +/** + * stat_gfs_fill - fill in the sg for a given RG + * @rgd: the RG + * @sg: the sg structure + * + * Returns: 0 on success, -ESTALE if the LVB is invalid + */ + +static int +stat_gfs_fill(struct gfs_rgrpd *rgd, struct gfs_stat_gfs *sg) +{ + struct gfs_rgrp_lvb *rb = (struct gfs_rgrp_lvb *)rgd->rd_gl->gl_lvb; + + if (gfs32_to_cpu(rb->rb_magic) != GFS_MAGIC) + return -ESTALE; + + sg->sg_total_blocks += rgd->rd_ri.ri_data; + sg->sg_free += gfs32_to_cpu(rb->rb_free); + sg->sg_used_dinode += gfs32_to_cpu(rb->rb_useddi); + sg->sg_free_dinode += gfs32_to_cpu(rb->rb_freedi); + sg->sg_used_meta += gfs32_to_cpu(rb->rb_usedmeta); + sg->sg_free_meta += gfs32_to_cpu(rb->rb_freemeta); + + return 0; +} + +/** + * stat_gfs_async - Stat a filesystem using asynchronous locking + * @sdp: the filesystem + * @sg: the sg info that will be returned + * @interruptible: TRUE if we should look for signals. + * + * Any error (other than a signal) will cause this routine to fall back + * to the synchronous version. + * + * FIXME: This really shouldn't busy wait like this. + * + * Returns: errno + */ + +static int +stat_gfs_async(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg, int interruptible) +{ + struct gfs_rgrpd *rgd_next = gfs_rgrpd_get_first(sdp); + struct gfs_holder *gha, *gh; + unsigned int slots = gfs_tune_get(sdp, gt_statfs_slots); + unsigned int x; + int done; + int error = 0, err; + + memset(sg, 0, sizeof(struct gfs_stat_gfs)); + + gha = vmalloc(slots * sizeof(struct gfs_holder)); + if (!gha) + return -ENOMEM; + memset(gha, 0, slots * sizeof(struct gfs_holder)); + + for (;;) { + done = TRUE; + + for (x = 0; x < slots; x++) { + gh = gha + x; + + if (gh->gh_gl && gfs_glock_poll(gh)) { + err = gfs_glock_wait(gh); + if (err) { + gfs_holder_uninit(gh); + error = err; + } else { + if (!error) + error = stat_gfs_fill(get_gl2rgd(gh->gh_gl), sg); + gfs_glock_dq_uninit(gh); + } + } + + if (gh->gh_gl) + done = FALSE; + else if (rgd_next && !error) { + error = gfs_glock_nq_init(rgd_next->rd_gl, + LM_ST_SHARED, + GL_LOCAL_EXCL | GL_SKIP | GL_ASYNC, + gh); + rgd_next = gfs_rgrpd_get_next(rgd_next); + done = FALSE; + } + + if (interruptible && signal_pending(current)) + error = -ERESTARTSYS; + } + + if (done) + break; + + yield(); + } + + vfree(gha); + + return error; +} + +/** + * stat_gfs_sync - Stat a filesystem using synchronous locking + * @sdp: the filesystem + * @sg: the sg info that will be returned + * @interruptible: TRUE if we should look for signals. + * + * Returns: errno + */ + +static int +stat_gfs_sync(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg, int interruptible) +{ + struct gfs_holder rgd_gh; + struct gfs_rgrpd *rgd; + int error; + + memset(sg, 0, sizeof(struct gfs_stat_gfs)); + + for (rgd = gfs_rgrpd_get_first(sdp); + rgd; + rgd = gfs_rgrpd_get_next(rgd)) { + for (;;) { + error = gfs_glock_nq_init(rgd->rd_gl, + LM_ST_SHARED, + GL_LOCAL_EXCL | GL_SKIP, + &rgd_gh); + if (error) + return error; + + error = stat_gfs_fill(rgd, sg); + + gfs_glock_dq_uninit(&rgd_gh); + + if (!error) + break; + + error = gfs_rgrp_lvb_init(rgd); + if (error) + return error; + } + + if (interruptible && signal_pending(current)) + return -ERESTARTSYS; + } + + return 0; +} + +/** + * gfs_stat_gfs - Do a statfs + * @sdp: the filesystem + * @sg: the sg structure + * @interruptible: Stop if there is a signal pending + * + * Returns: errno + */ + +int +gfs_stat_gfs(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg, int interruptible) +{ + struct gfs_holder ri_gh; + int error; + + error = gfs_rindex_hold(sdp, &ri_gh); + if (error) + return error; + + error = stat_gfs_async(sdp, sg, interruptible); + if (error == -ESTALE) + error = stat_gfs_sync(sdp, sg, interruptible); + + gfs_glock_dq_uninit(&ri_gh); + + return error; +} + +/** + * gfs_lock_fs_check_clean - Stop all writes to the FS and check that all journals are clean + * @sdp: the file system + * @state: the state to put the transaction lock into + * @t_gh: the hold on the transaction lock + * + * Returns: errno + */ + +int +gfs_lock_fs_check_clean(struct gfs_sbd *sdp, unsigned int state, + struct gfs_holder *t_gh) +{ + struct gfs_holder ji_gh, cl_gh; + struct gfs_log_header lh; + unsigned int x; + int error; + + error = gfs_jindex_hold(sdp, &ji_gh); + if (error) + return error; + + error = gfs_glock_nq_num(sdp, + GFS_CRAP_LOCK, &gfs_meta_glops, + LM_ST_SHARED, GL_NOCACHE, + &cl_gh); + if (error) + goto fail; + + error = gfs_glock_nq_init(sdp->sd_trans_gl, state, + LM_FLAG_PRIORITY | GL_EXACT | GL_NOCACHE, + t_gh); + if (error) + goto fail_gunlock_craplock; + + for (x = 0; x < sdp->sd_journals; x++) { + error = gfs_find_jhead(sdp, &sdp->sd_jindex[x], + cl_gh.gh_gl, &lh); + if (error) + goto fail_gunlock_trans; + + if (!(lh.lh_flags & GFS_LOG_HEAD_UNMOUNT)) { + error = -EBUSY; + goto fail_gunlock_trans; + } + } + + gfs_glock_dq_uninit(&cl_gh); + gfs_glock_dq_uninit(&ji_gh); + + return 0; + + fail_gunlock_trans: + gfs_glock_dq_uninit(t_gh); + + fail_gunlock_craplock: + gfs_glock_dq_uninit(&cl_gh); + + fail: + gfs_glock_dq_uninit(&ji_gh); + + return error; +} + +/** + * gfs_freeze_fs - freezes the file system + * @sdp: the file system + * + * This function flushes data and meta data for all machines by + * aquiring the transaction log exclusively. All journals are + * ensured to be in a clean state as well. + * + * Returns: errno + */ + +int +gfs_freeze_fs(struct gfs_sbd *sdp) +{ + int error = 0; + + down(&sdp->sd_freeze_lock); + + if (!sdp->sd_freeze_count++) { + error = gfs_lock_fs_check_clean(sdp, LM_ST_DEFERRED, + &sdp->sd_freeze_gh); + if (error) + sdp->sd_freeze_count--; + else + sdp->sd_freeze_gh.gh_owner = NULL; + } + + up(&sdp->sd_freeze_lock); + + return error; +} + +/** + * gfs_unfreeze_fs - unfreezes the file system + * @sdp: the file system + * + * This function allows the file system to proceed by unlocking + * the exclusively held transaction lock. Other GFS nodes are + * now free to acquire the lock shared and go on with their lives. + * + */ + +void +gfs_unfreeze_fs(struct gfs_sbd *sdp) +{ + down(&sdp->sd_freeze_lock); + + if (sdp->sd_freeze_count && !--sdp->sd_freeze_count) + gfs_glock_dq_uninit(&sdp->sd_freeze_gh); + + up(&sdp->sd_freeze_lock); +} + +/* + * Fast statfs implementation - mostly based on GFS2 implementation. + */ + +void gfs_statfs_change_in(struct gfs_statfs_change_host *sc, const void *buf) +{ + const struct gfs_statfs_change *str = buf; + + sc->sc_total = be64_to_cpu(str->sc_total); + sc->sc_free = be64_to_cpu(str->sc_free); + sc->sc_dinodes = be64_to_cpu(str->sc_dinodes); +} + +void gfs_statfs_change_out(const struct gfs_statfs_change_host *sc, void *buf) +{ + struct gfs_statfs_change *str = buf; + + str->sc_total = cpu_to_be64(sc->sc_total); + str->sc_free = cpu_to_be64(sc->sc_free); + str->sc_dinodes = cpu_to_be64(sc->sc_dinodes); +} + +int gfs_statfs_start(struct gfs_sbd *sdp) +{ + struct gfs_stat_gfs sg; + struct gfs_inode *m_ip; + struct gfs_statfs_change_host *m_sc = &sdp->sd_statfs_master; + struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local; + struct buffer_head *m_bh; + struct gfs_holder gh; + int error; + + printk("GFS: fsid=%s: fast statfs start time = %lu\n", + sdp->sd_fsname, get_seconds()); + + /* created via gfs_get_linode() in fill_super(). */ + /* gfs_inode_glops */ + m_ip = sdp->sd_linode; + + /* get real statistics */ + error = gfs_stat_gfs(sdp, &sg, TRUE); + if (error) + return error; + + /* make sure the page is refreshed via glock flushing */ + error = gfs_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, + &gh); + if (error) + goto gfs_statfs_start_out; + + error = gfs_get_inode_buffer(m_ip, &m_bh); + if (error) + goto gfs_statfs_start_unlock; + + error = gfs_trans_begin(sdp, 1, 0); + if (error) + goto gfs_statfs_start_bh; + + spin_lock(&sdp->sd_statfs_spin); + m_sc->sc_total = sg.sg_total_blocks; + m_sc->sc_free = sg.sg_free + sg.sg_free_dinode + sg.sg_free_meta; + m_sc->sc_dinodes = sg.sg_used_dinode; + memset(l_sc, 0, sizeof(struct gfs_statfs_change_host)); + spin_unlock(&sdp->sd_statfs_spin); + + gfs_trans_add_bh(m_ip->i_gl, m_bh); + gfs_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs_dinode)); + + gfs_trans_end(sdp); + +gfs_statfs_start_bh: + brelse(m_bh); + +gfs_statfs_start_unlock: + gfs_glock_dq_uninit(&gh); + +gfs_statfs_start_out: + return 0; +} + +int gfs_statfs_init(struct gfs_sbd *sdp, int flag) +{ + int error; + + /* if flag == 0, do we want to turn this off ? */ + if (!flag) + return 0; + + error = gfs_statfs_start(sdp); + if (error) + printk("GFS: fsid=%s: can't initialize statfs subsystem: %d\n", + sdp->sd_fsname, error); + + return error; +} + +void gfs_statfs_modify(struct gfs_sbd *sdp, + int64_t total, + int64_t free, + int64_t dinodes) +{ + struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local; + + spin_lock(&sdp->sd_statfs_spin); + l_sc->sc_total += total; + l_sc->sc_free += free; + l_sc->sc_dinodes += dinodes; + spin_unlock(&sdp->sd_statfs_spin); +} + +int gfs_statfs_sync(struct gfs_sbd *sdp) +{ + struct gfs_inode *m_ip = sdp->sd_linode; + struct gfs_statfs_change_host *m_sc = &sdp->sd_statfs_master; + struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local; + struct gfs_holder gh; + struct buffer_head *m_bh; + int error; + + error = gfs_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, + &gh); + if (error) + return error; + + error = gfs_get_inode_buffer(m_ip, &m_bh); + if (error) + goto gfs_statfs_sync_out; + + /* if no change, simply return */ + spin_lock(&sdp->sd_statfs_spin); + gfs_statfs_change_in(m_sc, m_bh->b_data + + sizeof(struct gfs_dinode)); + if (!l_sc->sc_total && !l_sc->sc_free && !l_sc->sc_dinodes) { + spin_unlock(&sdp->sd_statfs_spin); + goto out_bh; + } + spin_unlock(&sdp->sd_statfs_spin); + + error = gfs_trans_begin(sdp, 1, 0); + if (error) + goto out_bh; + + spin_lock(&sdp->sd_statfs_spin); + m_sc->sc_total += l_sc->sc_total; + m_sc->sc_free += l_sc->sc_free; + m_sc->sc_dinodes += l_sc->sc_dinodes; + memset(l_sc, 0, sizeof(struct gfs_statfs_change_host)); + spin_unlock(&sdp->sd_statfs_spin); + + gfs_trans_add_bh(m_ip->i_gl, m_bh); + gfs_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs_dinode)); + + gfs_trans_end(sdp); + +out_bh: + brelse(m_bh); + +gfs_statfs_sync_out: + gfs_glock_dq_uninit(&gh); + return error; +} + +int gfs_statfs_fast(struct gfs_sbd *sdp, void *b) +{ + struct kstatfs *buf = (struct kstatfs *)b; + struct gfs_statfs_change_host sc, *m_sc = &sdp->sd_statfs_master; + struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local; + + spin_lock(&sdp->sd_statfs_spin); + + sc.sc_total = m_sc->sc_total + l_sc->sc_total; + sc.sc_free = m_sc->sc_free + l_sc->sc_free; + sc.sc_dinodes = m_sc->sc_dinodes + l_sc->sc_dinodes; + spin_unlock(&sdp->sd_statfs_spin); + + if (sc.sc_free < 0) + sc.sc_free = 0; + if (sc.sc_free > sc.sc_total) + sc.sc_free = sc.sc_total; + if (sc.sc_dinodes < 0) + sc.sc_dinodes = 0; + + /* fill in the statistics */ + memset(buf, 0, sizeof(struct kstatfs)); + + buf->f_type = GFS_MAGIC; buf->f_bsize = sdp->sd_sb.sb_bsize; + buf->f_blocks = sc.sc_total; + buf->f_bfree = sc.sc_free; + buf->f_bavail = sc.sc_free; + buf->f_files = sc.sc_dinodes + sc.sc_free; + buf->f_ffree = sc.sc_free; + buf->f_namelen = GFS_FNAMESIZE; + + return 0; +} --- linux-2.6.27.orig/ubuntu/gfs/trans.c +++ linux-2.6.27/ubuntu/gfs/trans.c @@ -0,0 +1,453 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "glock.h" +#include "log.h" +#include "lops.h" +#include "quota.h" +#include "trans.h" +#include "unlinked.h" + +/** + * gfs_trans_print - Print a transaction to the console + * @sdp: the filesystem + * @tr: The GFS transaction + * @where: Situation of transaction + * + */ + +void +gfs_trans_print(struct gfs_sbd *sdp, struct gfs_trans *tr, unsigned int where) +{ + struct gfs_log_element *le; + struct list_head *tmp, *head; + unsigned int mblks = 0, eblks = 0; + + LO_TRANS_SIZE(sdp, tr, &mblks, &eblks, NULL, NULL); + + printk("Transaction: (%s, %u)\n", tr->tr_file, tr->tr_line); + printk(" tr_mblks_asked = %u, tr_eblks_asked = %u, tr_seg_reserved = %u\n", + tr->tr_mblks_asked, tr->tr_eblks_asked, tr->tr_seg_reserved); + printk(" mblks = %u, eblks = %u\n", mblks, eblks); + printk(" tr_flags = 0x%.8X\n", tr->tr_flags); + + for (head = &tr->tr_elements, tmp = head->next; + tmp != head; + tmp = tmp->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + LO_PRINT(sdp, le, where); + } + + printk("End Trans\n"); +} + +/** + * gfs_trans_begin_i - Prepare to start a transaction + * @sdp: The GFS superblock + * @meta_blocks: Reserve this many metadata blocks in the log + * @extra_blocks: Number of non-metadata blocks to reserve + * + * Allocate the struct gfs_trans struct. + * Grab a shared TRANSaction lock (protects this transaction from + * overlapping with unusual fs writes, e.g. journal replay, fs upgrade, + * while allowing simultaneous transaction writes throughout cluster). + * Reserve space in the log. @meta_blocks and @extra_blocks must indicate + * the worst case (maximum) size of the transaction. + * Record this transaction as the *one* transaction being built by this + * Linux process, in current->journal_info. + * + * Returns: errno + */ + +int +gfs_trans_begin_i(struct gfs_sbd *sdp, + unsigned int meta_blocks, unsigned int extra_blocks, + char *file, unsigned int line) +{ + struct gfs_trans *tr; + unsigned int blocks; + int error; + + tr = kmalloc(sizeof(struct gfs_trans), GFP_KERNEL); + if (!tr) + return -ENOMEM; + memset(tr, 0, sizeof(struct gfs_trans)); + + INIT_LIST_HEAD(&tr->tr_elements); + INIT_LIST_HEAD(&tr->tr_free_bufs); + INIT_LIST_HEAD(&tr->tr_free_bmem); + INIT_LIST_HEAD(&tr->tr_bufs); + INIT_LIST_HEAD(&tr->tr_ail_bufs); + tr->tr_file = file; + tr->tr_line = line; + + error = -ENOMEM; + tr->tr_t_gh = gfs_holder_get(sdp->sd_trans_gl, LM_ST_SHARED, 0); + if (!tr->tr_t_gh) + goto fail; + + error = gfs_glock_nq(tr->tr_t_gh); + if (error) + goto fail_holder_put; + + if (test_bit(SDF_ROFS, &sdp->sd_flags)) { + tr->tr_t_gh->gh_flags |= GL_NOCACHE; + error = -EROFS; + goto fail_gunlock; + } + + /* Do log reservation */ + + tr->tr_mblks_asked = meta_blocks; + tr->tr_eblks_asked = extra_blocks; + + blocks = 1; + if (meta_blocks) + blocks += gfs_struct2blk(sdp, meta_blocks, + sizeof(struct gfs_block_tag)) + + meta_blocks; + blocks += extra_blocks; + tr->tr_seg_reserved = gfs_blk2seg(sdp, blocks); + + error = gfs_log_reserve(sdp, tr->tr_seg_reserved, FALSE); + if (error) + goto fail_gunlock; + + gfs_assert(sdp, !get_transaction,); + set_transaction(tr); + + return 0; + + fail_gunlock: + gfs_glock_dq(tr->tr_t_gh); + + fail_holder_put: + gfs_holder_put(tr->tr_t_gh); + + fail: + kfree(tr); + + return error; +} + +/** + * gfs_trans_end - End a transaction + * @sdp: The GFS superblock + * + * If buffers were actually added to the transaction, + * commit it. + * + */ + +void +gfs_trans_end(struct gfs_sbd *sdp) +{ + struct gfs_trans *tr; + struct gfs_holder *t_gh; + struct list_head *tmp, *head; + struct gfs_log_element *le; + + /* Linux task struct indicates current new trans for this process. + * We're done building it, so set it to NULL */ + tr = get_transaction; + gfs_assert(sdp, tr,); + set_transaction(NULL); + + t_gh = tr->tr_t_gh; + tr->tr_t_gh = NULL; + + /* If no buffers were ever added to trans, forget it */ + if (list_empty(&tr->tr_elements)) { + gfs_log_release(sdp, tr->tr_seg_reserved); + kfree(tr); + + gfs_glock_dq(t_gh); + gfs_holder_put(t_gh); + + return; + } + + /* Do trans_end log-operation for each log element */ + for (head = &tr->tr_elements, tmp = head->next; + tmp != head; + tmp = tmp->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + LO_TRANS_END(sdp, le); + } + + gfs_log_commit(sdp, tr); + + gfs_glock_dq(t_gh); + gfs_holder_put(t_gh); + + if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) + gfs_log_flush(sdp); +} + +/** + * gfs_trans_add_gl - Add a glock to a transaction + * @gl: the glock + * + * If not already attached, add the given glock to this process's transaction. + * + * Even though no glock info will be written to the on-disk log, the glocks + * associated with a transaction provide bridges by which to combine + * a just-built transaction with an earlier incore committed transaction + * that was protected by the same glock. See incore_commit(). + * Combining transactions makes for more efficient logging. + * + * Note that more than one glock may be associated with a single transaction. + * However, a given glock protects no more than *one* transaction at a + * given stage in the transaction pipeline (i.e. new or incore-committed). + * After all, the process holds the glock EX (so no other process can be + * building a separate trans protected by this glock), and the process can + * build only one transaction at a time. + * + * Rules: + * This process must hold the glock in EXclusive mode, since we're going + * to be writing to something protected by this glock. + */ + +void +gfs_trans_add_gl(struct gfs_glock *gl) +{ + if (!gl->gl_new_le.le_trans) { + gfs_assert_withdraw(gl->gl_sbd, + gfs_glock_is_locked_by_me(gl) && + gfs_glock_is_held_excl(gl)); + gfs_glock_hold(gl); /* Released in glock_trans_end() */ + + /* Ask for eventual flush of (meta)data protected by this glock, + once trans is complete and logged. */ + set_bit(GLF_DIRTY, &gl->gl_flags); + + /* Invoke generic_le_add() */ + LO_ADD(gl->gl_sbd, &gl->gl_new_le); + gl->gl_new_le.le_trans->tr_num_gl++; + } +} + +/** + * gfs_trans_add_bh - Add a to-be-modified buffer to the current transaction + * @gl: the glock the buffer belongs to + * @bh: The buffer to add + * + * Add a to-be-modified buffer to the current being-built (i.e. new) trans, + * and pin the buffer in memory. + * + * Caller must hold the glock protecting this buffer. + * + * Call this as many times as you want during transaction formation. It does + * its attachment work only once. After buffer is attached to trans, the + * process building the trans can modify the buffer again and again (calling + * this function before each change). Only the final result (within this trans) + * will be written to log. A good example is when allocating blocks in an RG, + * a given bitmap buffer may be updated many times within a transaction. + * + * Note: This final result will also be written to its in-place location, + * unless this transaction gets combined with a later transaction, + * in which case only the later result will go to in-place. + * + */ + +void +gfs_trans_add_bh(struct gfs_glock *gl, struct buffer_head *bh) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_bufdata *bd; + + /* Make sure GFS private info struct is attached to buffer head */ + bd = get_v2bd(bh); + if (!bd) { + gfs_attach_bufdata(bh, gl); + bd = get_v2bd(bh); + } + + /* If buffer has already been attached to trans, we're done */ + if (bd->bd_new_le.le_trans) + return; + + gfs_meta_check(sdp, bh); + + gfs_assert(sdp, bd->bd_gl == gl,); + + /* Make sure glock is attached to trans */ + if (!gl->gl_new_le.le_trans) + gfs_trans_add_gl(gl); + + gfs_dpin(sdp, bh); + + /* Attach buffer to trans */ + LO_ADD(sdp, &bd->bd_new_le); + bd->bd_new_le.le_trans->tr_num_buf++; +} + +/** + * gfs_trans_add_unlinked - Add an unlinked or dealloced tag to + * the current transaction + * @sdp: the filesystem + * @type: the type of entry + * @inum: the inode number + * + * Returns: the unlinked structure + */ + +struct gfs_unlinked * +gfs_trans_add_unlinked(struct gfs_sbd *sdp, unsigned int type, + struct gfs_inum *inum) +{ + struct gfs_unlinked *ul; + + /* Find in fileystem's unlinked list, or create */ + ul = gfs_unlinked_get(sdp, inum, CREATE); + + LO_ADD(sdp, &ul->ul_new_le); + + switch (type) { + case GFS_LOG_DESC_IUL: + set_bit(ULF_NEW_UL, &ul->ul_flags); + ul->ul_new_le.le_trans->tr_num_iul++; + break; + case GFS_LOG_DESC_IDA: + clear_bit(ULF_NEW_UL, &ul->ul_flags); + ul->ul_new_le.le_trans->tr_num_ida++; + break; + default: + gfs_assert(sdp, FALSE,); + break; + } + + return ul; +} + +/** + * gfs_trans_add_quota - Add quota changes to a transaction + * @sdp: the filesystem + * @change: The number of blocks allocated (positive) or freed (negative) + * @uid: the user ID doing the change + * @gid: the group ID doing the change + * + */ + +void +gfs_trans_add_quota(struct gfs_sbd *sdp, int64_t change, + uint32_t uid, uint32_t gid) +{ + struct gfs_trans *tr; + struct list_head *tmp, *head, *next; + struct gfs_log_element *le; + struct gfs_quota_le *ql; + int found_uid, found_gid; + int error; + + if (!gfs_tune_get(sdp, gt_quota_account)) + return; + if (gfs_assert_warn(sdp, change)) + return; + + found_uid = (uid == NO_QUOTA_CHANGE); + found_gid = (gid == NO_QUOTA_CHANGE); + + if (gfs_assert_warn(sdp, !found_uid || !found_gid)) + return; + + tr = get_transaction; + gfs_assert(sdp, tr,); + + for (head = &tr->tr_elements, tmp = head->next, next = tmp->next; + tmp != head; + tmp = next, next = next->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + if (le->le_ops != &gfs_quota_lops) + continue; + + ql = container_of(le, struct gfs_quota_le, ql_le); + + if (test_bit(QDF_USER, &ql->ql_data->qd_flags)) { + if (ql->ql_data->qd_id == uid) { + ql->ql_change += change; + + spin_lock(&sdp->sd_quota_lock); + ql->ql_data->qd_change_new += change; + spin_unlock(&sdp->sd_quota_lock); + + list_del(&le->le_list); + + if (ql->ql_change) + list_add(&le->le_list, + &tr->tr_elements); + else { + gfs_quota_put(sdp, ql->ql_data); + kfree(ql); + tr->tr_num_q--; + } + + gfs_assert(sdp, !found_uid,); + found_uid = TRUE; + if (found_gid) + break; + } + } else { + if (ql->ql_data->qd_id == gid) { + ql->ql_change += change; + + spin_lock(&sdp->sd_quota_lock); + ql->ql_data->qd_change_new += change; + spin_unlock(&sdp->sd_quota_lock); + + list_del(&le->le_list); + + if (ql->ql_change) + list_add(&le->le_list, + &tr->tr_elements); + else { + gfs_quota_put(sdp, ql->ql_data); + kfree(ql); + tr->tr_num_q--; + } + + gfs_assert(sdp, !found_gid,); + found_gid = TRUE; + if (found_uid) + break; + } + } + } + + while (!found_uid || !found_gid) { + ql = gmalloc(sizeof(struct gfs_quota_le)); + memset(ql, 0, sizeof(struct gfs_quota_le)); + + INIT_LE(&ql->ql_le, &gfs_quota_lops); + + if (found_uid) { + error = gfs_quota_get(sdp, FALSE, gid, + NO_CREATE, + &ql->ql_data); + found_gid = TRUE; + } else { + error = gfs_quota_get(sdp, TRUE, uid, + NO_CREATE, + &ql->ql_data); + found_uid = TRUE; + } + + gfs_assert(sdp, !error && ql->ql_data,); + + ql->ql_change = change; + + spin_lock(&sdp->sd_quota_lock); + ql->ql_data->qd_change_new += change; + spin_unlock(&sdp->sd_quota_lock); + + LO_ADD(sdp, &ql->ql_le); + tr->tr_num_q++; + } +} --- linux-2.6.27.orig/ubuntu/gfs/lops.h +++ linux-2.6.27/ubuntu/gfs/lops.h @@ -0,0 +1,166 @@ +#ifndef __LOPS_DOT_H__ +#define __LOPS_DOT_H__ + +extern struct gfs_log_operations gfs_glock_lops; +extern struct gfs_log_operations gfs_buf_lops; +extern struct gfs_log_operations gfs_unlinked_lops; +extern struct gfs_log_operations gfs_quota_lops; + +extern struct gfs_log_operations *gfs_log_ops[]; + +#define INIT_LE(le, lops) \ +do \ +{ \ + (le)->le_ops = (lops); \ + (le)->le_trans = NULL; \ + INIT_LIST_HEAD(&(le)->le_list); \ +} \ +while (0) + +#define LO_ADD(sdp, le) \ +do \ +{ \ + if ((le)->le_ops->lo_add) \ + (le)->le_ops->lo_add((sdp), (le)); \ +} \ +while (0) + +#define LO_TRANS_END(sdp, le) \ +do \ +{ \ + if ((le)->le_ops->lo_trans_end) \ + (le)->le_ops->lo_trans_end((sdp), (le)); \ +} \ +while (0) + +#define LO_PRINT(sdp, le, where) \ +do \ +{ \ + if ((le)->le_ops->lo_print) \ + (le)->le_ops->lo_print((sdp), (le), (where)); \ +} \ +while (0) + +static __inline__ struct gfs_trans * +LO_OVERLAP_TRANS(struct gfs_sbd *sdp, struct gfs_log_element *le) +{ + if (le->le_ops->lo_overlap_trans) + return le->le_ops->lo_overlap_trans(sdp, le); + else + return NULL; +} + +#define LO_INCORE_COMMIT(sdp, tr, le) \ +do \ +{ \ + if ((le)->le_ops->lo_incore_commit) \ + (le)->le_ops->lo_incore_commit((sdp), (tr), (le)); \ +} \ +while (0) + +#define LO_ADD_TO_AIL(sdp, le) \ +do \ +{ \ + if ((le)->le_ops->lo_add_to_ail) \ + (le)->le_ops->lo_add_to_ail((sdp), (le)); \ +} \ +while (0) + +#define LO_CLEAN_DUMP(sdp, le) \ +do \ +{ \ + if ((le)->le_ops->lo_clean_dump) \ + (le)->le_ops->lo_clean_dump((sdp), (le)); \ +} \ +while (0) + +#define LO_TRANS_SIZE(sdp, tr, mblks, eblks, blocks, bmem) \ +do \ +{ \ + int __lops_x; \ + for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \ + if (gfs_log_ops[__lops_x]->lo_trans_size) \ + gfs_log_ops[__lops_x]->lo_trans_size((sdp), (tr), (mblks), (eblks), (blocks), (bmem)); \ +} \ +while (0) + +#define LO_TRANS_COMBINE(sdp, tr, new_tr) \ +do \ +{ \ + int __lops_x; \ + for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \ + if (gfs_log_ops[__lops_x]->lo_trans_combine) \ + gfs_log_ops[__lops_x]->lo_trans_combine((sdp), (tr), (new_tr)); \ +} \ +while (0) + +#define LO_BUILD_BHLIST(sdp, tr) \ +do \ +{ \ + int __lops_x; \ + for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \ + if (gfs_log_ops[__lops_x]->lo_build_bhlist) \ + gfs_log_ops[__lops_x]->lo_build_bhlist((sdp), (tr)); \ +} \ +while (0) + +#define LO_DUMP_SIZE(sdp, elements, blocks, bmem) \ +do \ +{ \ + int __lops_x; \ + for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \ + if (gfs_log_ops[__lops_x]->lo_dump_size) \ + gfs_log_ops[__lops_x]->lo_dump_size((sdp), (elements), (blocks), (bmem)); \ +} \ +while (0) + +#define LO_BUILD_DUMP(sdp, tr) \ +do \ +{ \ + int __lops_x; \ + for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \ + if (gfs_log_ops[__lops_x]->lo_build_dump) \ + gfs_log_ops[__lops_x]->lo_build_dump((sdp), (tr)); \ +} \ +while (0) + +#define LO_BEFORE_SCAN(sdp, jid, head, pass) \ +do \ +{ \ + int __lops_x; \ + for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \ + if (gfs_log_ops[__lops_x]->lo_before_scan) \ + gfs_log_ops[__lops_x]->lo_before_scan((sdp), (jid), (head), (pass)); \ +} \ +while (0) + +static __inline__ int +LO_SCAN_ELEMENTS(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint64_t start, + struct gfs_log_descriptor *desc, unsigned int pass) +{ + int x; + int error; + + for (x = 0; gfs_log_ops[x]; x++) + if (gfs_log_ops[x]->lo_scan_elements) { + error = gfs_log_ops[x]->lo_scan_elements(sdp, jdesc, gl, + start, desc, pass); + if (error) + return error; + } + + return 0; +} + +#define LO_AFTER_SCAN(sdp, jid, pass) \ +do \ +{ \ + int __lops_x; \ + for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \ + if (gfs_log_ops[__lops_x]->lo_after_scan) \ + gfs_log_ops[__lops_x]->lo_after_scan((sdp), (jid), (pass)); \ +} \ +while (0) + +#endif /* __LOPS_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/ops_dentry.c +++ linux-2.6.27/ubuntu/gfs/ops_dentry.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dir.h" +#include "glock.h" +#include "ops_dentry.h" + +/** + * gfs_drevalidate - Check directory lookup consistency + * @dentry: the mapping to check + * @nd: + * + * Check to make sure the lookup necessary to arrive at this inode from its + * parent is still good. + * + * Returns: 1 if the dentry is ok, 0 if it isn't + */ + +static int +gfs_drevalidate(struct dentry *dentry, struct nameidata *nd) +{ + struct dentry *parent = dget_parent(dentry); + struct gfs_inode *dip = get_v2ip(parent->d_inode); + struct gfs_sbd *sdp = dip->i_sbd; + struct inode *inode; + struct gfs_holder d_gh; + struct gfs_inode *ip; + struct gfs_inum inum; + unsigned int type; + int error; + + lock_kernel(); + + atomic_inc(&sdp->sd_ops_dentry); + + if (sdp->sd_args.ar_localcaching) + goto valid; + + inode = dentry->d_inode; + if (inode && is_bad_inode(inode)) + goto invalid; + + error = gfs_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + if (error) + goto fail; + + error = gfs_dir_search(dip, &dentry->d_name, &inum, &type); + switch (error) { + case 0: + if (!inode) + goto invalid_gunlock; + break; + case -ENOENT: + if (!inode) + goto valid_gunlock; + goto invalid_gunlock; + default: + goto fail_gunlock; + } + + ip = get_v2ip(inode); + + if (ip->i_num.no_formal_ino != inum.no_formal_ino) + goto invalid_gunlock; + + if (ip->i_di.di_type != type) { + gfs_consist_inode(dip); + goto fail_gunlock; + } + + valid_gunlock: + gfs_glock_dq_uninit(&d_gh); + + valid: + unlock_kernel(); + dput(parent); + return 1; + + invalid_gunlock: + gfs_glock_dq_uninit(&d_gh); + + invalid: + if (inode && S_ISDIR(inode->i_mode)) { + if (have_submounts(dentry)) + goto valid; + shrink_dcache_parent(dentry); + } + d_drop(dentry); + + unlock_kernel(); + dput(parent); + return 0; + + fail_gunlock: + gfs_glock_dq_uninit(&d_gh); + + fail: + unlock_kernel(); + dput(parent); + return 0; +} + +struct dentry_operations gfs_dops = { + .d_revalidate = gfs_drevalidate, +}; --- linux-2.6.27.orig/ubuntu/gfs/page.h +++ linux-2.6.27/ubuntu/gfs/page.h @@ -0,0 +1,13 @@ +#ifndef __PAGE_DOT_H__ +#define __PAGE_DOT_H__ + +void gfs_inval_pte(struct gfs_glock *gl); +void gfs_inval_page(struct gfs_glock *gl); +void gfs_sync_page_i(struct inode *inode, int flags); +void gfs_sync_page(struct gfs_glock *gl, int flags); + +int gfs_unstuffer_page(struct gfs_inode *ip, struct buffer_head *dibh, + uint64_t block, void *private); +int gfs_truncator_page(struct gfs_inode *ip, uint64_t size); + +#endif /* __PAGE_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lvb.h +++ linux-2.6.27/ubuntu/gfs/lvb.h @@ -0,0 +1,53 @@ +/* + * Formats of Lock Value Blocks (LVBs) for various types of locks. + * These 32-bit data chunks can be shared quickly between nodes + * via the inter-node lock manager (via LAN instead of on-disk). + */ + +#ifndef __LVB_DOT_H__ +#define __LVB_DOT_H__ + +#define GFS_MIN_LVB_SIZE (32) + +/* + * Resource Group block allocation statistics + * Each resource group lock contains one of these in its LVB. + * Used for sharing approximate current statistics for statfs. + * Not used for actual block allocation. + */ +struct gfs_rgrp_lvb { + uint32_t rb_magic; /* GFS_MAGIC sanity check value */ + uint32_t rb_free; /* # free data blocks */ + uint32_t rb_useddi; /* # used dinode blocks */ + uint32_t rb_freedi; /* # free dinode blocks */ + uint32_t rb_usedmeta; /* # used metadata blocks */ + uint32_t rb_freemeta; /* # free metadata blocks */ +}; + +/* + * Quota + * Each quota lock contains one of these in its LVB. + * Keeps track of block allocation limits and current block allocation + * for either a cluster-wide user or a cluster-wide group. + */ +struct gfs_quota_lvb { + uint32_t qb_magic; /* GFS_MAGIC sanity check value */ + uint32_t qb_pad; + uint64_t qb_limit; /* Hard limit of # blocks to alloc */ + uint64_t qb_warn; /* Warn user when alloc is above this # */ + int64_t qb_value; /* Current # blocks allocated */ +}; + +/* Translation functions */ + +void gfs_rgrp_lvb_in(struct gfs_rgrp_lvb *rb, char *lvb); +void gfs_rgrp_lvb_out(struct gfs_rgrp_lvb *rb, char *lvb); +void gfs_quota_lvb_in(struct gfs_quota_lvb *qb, char *lvb); +void gfs_quota_lvb_out(struct gfs_quota_lvb *qb, char *lvb); + +/* Printing functions */ + +void gfs_rgrp_lvb_print(struct gfs_rgrp_lvb *rb); +void gfs_quota_lvb_print(struct gfs_quota_lvb *qb); + +#endif /* __LVB_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lock_dlm_lock.c +++ linux-2.6.27/ubuntu/gfs/lock_dlm_lock.c @@ -0,0 +1,527 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include "lock_dlm.h" + +static char junk_lvb[GDLM_LVB_SIZE]; + +static void queue_complete(struct gdlm_lock *lp) +{ + struct gdlm_ls *ls = lp->ls; + + clear_bit(LFL_ACTIVE, &lp->flags); + + spin_lock(&ls->async_lock); + list_add_tail(&lp->clist, &ls->complete); + spin_unlock(&ls->async_lock); + wake_up(&ls->thread_wait); +} + +static inline void gdlm_ast(void *astarg) +{ + queue_complete(astarg); +} + +static inline void gdlm_bast(void *astarg, int mode) +{ + struct gdlm_lock *lp = astarg; + struct gdlm_ls *ls = lp->ls; + + if (!mode) { + printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n", + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number); + return; + } + + spin_lock(&ls->async_lock); + if (!lp->bast_mode) { + list_add_tail(&lp->blist, &ls->blocking); + lp->bast_mode = mode; + } else if (lp->bast_mode < mode) + lp->bast_mode = mode; + spin_unlock(&ls->async_lock); + wake_up(&ls->thread_wait); +} + +void gdlm_queue_delayed(struct gdlm_lock *lp) +{ + struct gdlm_ls *ls = lp->ls; + + spin_lock(&ls->async_lock); + list_add_tail(&lp->delay_list, &ls->delayed); + spin_unlock(&ls->async_lock); +} + +/* convert gfs lock-state to dlm lock-mode */ + +static s16 make_mode(s16 lmstate) +{ + switch (lmstate) { + case LM_ST_UNLOCKED: + return DLM_LOCK_NL; + case LM_ST_EXCLUSIVE: + return DLM_LOCK_EX; + case LM_ST_DEFERRED: + return DLM_LOCK_CW; + case LM_ST_SHARED: + return DLM_LOCK_PR; + } + gdlm_assert(0, "unknown LM state %d", lmstate); + return -1; +} + +/* convert dlm lock-mode to gfs lock-state */ + +s16 gdlm_make_lmstate(s16 dlmmode) +{ + switch (dlmmode) { + case DLM_LOCK_IV: + case DLM_LOCK_NL: + return LM_ST_UNLOCKED; + case DLM_LOCK_EX: + return LM_ST_EXCLUSIVE; + case DLM_LOCK_CW: + return LM_ST_DEFERRED; + case DLM_LOCK_PR: + return LM_ST_SHARED; + } + gdlm_assert(0, "unknown DLM mode %d", dlmmode); + return -1; +} + +/* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and + DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */ + +static void check_cur_state(struct gdlm_lock *lp, unsigned int cur_state) +{ + s16 cur = make_mode(cur_state); + if (lp->cur != DLM_LOCK_IV) + gdlm_assert(lp->cur == cur, "%d, %d", lp->cur, cur); +} + +static inline unsigned int make_flags(struct gdlm_lock *lp, + unsigned int gfs_flags, + s16 cur, s16 req) +{ + unsigned int lkf = 0; + + if (gfs_flags & LM_FLAG_TRY) + lkf |= DLM_LKF_NOQUEUE; + + if (gfs_flags & LM_FLAG_TRY_1CB) { + lkf |= DLM_LKF_NOQUEUE; + lkf |= DLM_LKF_NOQUEUEBAST; + } + + if (gfs_flags & LM_FLAG_PRIORITY) { + lkf |= DLM_LKF_NOORDER; + lkf |= DLM_LKF_HEADQUE; + } + + if (gfs_flags & LM_FLAG_ANY) { + if (req == DLM_LOCK_PR) + lkf |= DLM_LKF_ALTCW; + else if (req == DLM_LOCK_CW) + lkf |= DLM_LKF_ALTPR; + } + + if (lp->lksb.sb_lkid != 0) { + lkf |= DLM_LKF_CONVERT; + + /* Conversion deadlock avoidance by DLM */ + + if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) && + !(lkf & DLM_LKF_NOQUEUE) && + cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req) + lkf |= DLM_LKF_CONVDEADLK; + } + + if (lp->lvb) + lkf |= DLM_LKF_VALBLK; + + return lkf; +} + +/* make_strname - convert GFS lock numbers to a string */ + +static inline void make_strname(const struct lm_lockname *lockname, + struct gdlm_strname *str) +{ + sprintf(str->name, "%8x%16llx", lockname->ln_type, + (unsigned long long)lockname->ln_number); + str->namelen = GDLM_STRNAME_BYTES; +} + +static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, + struct gdlm_lock **lpp) +{ + struct gdlm_lock *lp; + + lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS); + if (!lp) + return -ENOMEM; + + lp->lockname = *name; + make_strname(name, &lp->strname); + lp->ls = ls; + lp->cur = DLM_LOCK_IV; + lp->lvb = NULL; + lp->hold_null = NULL; + INIT_LIST_HEAD(&lp->clist); + INIT_LIST_HEAD(&lp->blist); + INIT_LIST_HEAD(&lp->delay_list); + + spin_lock(&ls->async_lock); + list_add(&lp->all_list, &ls->all_locks); + ls->all_locks_count++; + spin_unlock(&ls->async_lock); + + *lpp = lp; + return 0; +} + +void gdlm_delete_lp(struct gdlm_lock *lp) +{ + struct gdlm_ls *ls = lp->ls; + + spin_lock(&ls->async_lock); + if (!list_empty(&lp->clist)) + list_del_init(&lp->clist); + if (!list_empty(&lp->blist)) + list_del_init(&lp->blist); + if (!list_empty(&lp->delay_list)) + list_del_init(&lp->delay_list); + gdlm_assert(!list_empty(&lp->all_list), "%x,%llx", lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number); + list_del_init(&lp->all_list); + ls->all_locks_count--; + spin_unlock(&ls->async_lock); + + kfree(lp); +} + +int gdlm_get_lock(void *lockspace, struct lm_lockname *name, + void **lockp) +{ + struct gdlm_lock *lp; + int error; + + error = gdlm_create_lp(lockspace, name, &lp); + + *lockp = lp; + return error; +} + +void gdlm_put_lock(void *lock) +{ + gdlm_delete_lp(lock); +} + +unsigned int gdlm_do_lock(struct gdlm_lock *lp) +{ + struct gdlm_ls *ls = lp->ls; + int error, bast = 1; + + /* + * When recovery is in progress, delay lock requests for submission + * once recovery is done. Requests for recovery (NOEXP) and unlocks + * can pass. + */ + + if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && + !test_bit(LFL_NOBLOCK, &lp->flags) && lp->req != DLM_LOCK_NL) { + gdlm_queue_delayed(lp); + return LM_OUT_ASYNC; + } + + /* + * Submit the actual lock request. + */ + + if (test_bit(LFL_NOBAST, &lp->flags)) + bast = 0; + + set_bit(LFL_ACTIVE, &lp->flags); + + log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, lp->lksb.sb_lkid, + lp->cur, lp->req, lp->lkf); + + error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf, + lp->strname.name, lp->strname.namelen, 0, gdlm_ast, + lp, bast ? gdlm_bast : NULL); + + if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) { + lp->lksb.sb_status = -EAGAIN; + queue_complete(lp); + error = 0; + } + + if (error) { + log_error("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x " + "flags=%lx", ls->fsname, lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, error, + lp->cur, lp->req, lp->lkf, lp->flags); + return LM_OUT_ERROR; + } + return LM_OUT_ASYNC; +} + +static unsigned int gdlm_do_unlock(struct gdlm_lock *lp) +{ + struct gdlm_ls *ls = lp->ls; + unsigned int lkf = 0; + int error; + + set_bit(LFL_DLM_UNLOCK, &lp->flags); + set_bit(LFL_ACTIVE, &lp->flags); + + if (lp->lvb) + lkf = DLM_LKF_VALBLK; + + log_debug("un %x,%llx %x %d %x", lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, + lp->lksb.sb_lkid, lp->cur, lkf); + + error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp); + + if (error) { + log_error("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x " + "flags=%lx", ls->fsname, lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, error, + lp->cur, lp->req, lp->lkf, lp->flags); + return LM_OUT_ERROR; + } + return LM_OUT_ASYNC; +} + +unsigned int gdlm_lock(void *lock, unsigned int cur_state, + unsigned int req_state, unsigned int flags) +{ + struct gdlm_lock *lp = lock; + + clear_bit(LFL_DLM_CANCEL, &lp->flags); + if (flags & LM_FLAG_NOEXP) + set_bit(LFL_NOBLOCK, &lp->flags); + + check_cur_state(lp, cur_state); + lp->req = make_mode(req_state); + lp->lkf = make_flags(lp, flags, lp->cur, lp->req); + + return gdlm_do_lock(lp); +} + +unsigned int gdlm_unlock(void *lock, unsigned int cur_state) +{ + struct gdlm_lock *lp = lock; + + clear_bit(LFL_DLM_CANCEL, &lp->flags); + if (lp->cur == DLM_LOCK_IV) + return 0; + return gdlm_do_unlock(lp); +} + +void gdlm_cancel(void *lock) +{ + struct gdlm_lock *lp = lock; + struct gdlm_ls *ls = lp->ls; + int error, delay_list = 0; + + if (test_bit(LFL_DLM_CANCEL, &lp->flags)) + return; + + log_info("gdlm_cancel %x,%llx flags %lx", lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, lp->flags); + + spin_lock(&ls->async_lock); + if (!list_empty(&lp->delay_list)) { + list_del_init(&lp->delay_list); + delay_list = 1; + } + spin_unlock(&ls->async_lock); + + if (delay_list) { + set_bit(LFL_CANCEL, &lp->flags); + set_bit(LFL_ACTIVE, &lp->flags); + queue_complete(lp); + return; + } + + if (!test_bit(LFL_ACTIVE, &lp->flags) || + test_bit(LFL_DLM_UNLOCK, &lp->flags)) { + log_info("gdlm_cancel skip %x,%llx flags %lx", + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, lp->flags); + return; + } + + /* the lock is blocked in the dlm */ + + set_bit(LFL_DLM_CANCEL, &lp->flags); + set_bit(LFL_ACTIVE, &lp->flags); + + error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, DLM_LKF_CANCEL, + NULL, lp); + + log_info("gdlm_cancel rv %d %x,%llx flags %lx", error, + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, lp->flags); + + if (error == -EBUSY) + clear_bit(LFL_DLM_CANCEL, &lp->flags); +} + +static int gdlm_add_lvb(struct gdlm_lock *lp) +{ + char *lvb; + + lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS); + if (!lvb) + return -ENOMEM; + + lp->lksb.sb_lvbptr = lvb; + lp->lvb = lvb; + return 0; +} + +static void gdlm_del_lvb(struct gdlm_lock *lp) +{ + kfree(lp->lvb); + lp->lvb = NULL; + lp->lksb.sb_lvbptr = NULL; +} + +static int gdlm_ast_wait(void *word) +{ + schedule(); + return 0; +} + +/* This can do a synchronous dlm request (requiring a lock_dlm thread to get + the completion) because gfs won't call hold_lvb() during a callback (from + the context of a lock_dlm thread). */ + +static int hold_null_lock(struct gdlm_lock *lp) +{ + struct gdlm_lock *lpn = NULL; + int error; + + if (lp->hold_null) { + printk(KERN_INFO "lock_dlm: lvb already held\n"); + return 0; + } + + error = gdlm_create_lp(lp->ls, &lp->lockname, &lpn); + if (error) + goto out; + + lpn->lksb.sb_lvbptr = junk_lvb; + lpn->lvb = junk_lvb; + + lpn->req = DLM_LOCK_NL; + lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE; + set_bit(LFL_NOBAST, &lpn->flags); + set_bit(LFL_INLOCK, &lpn->flags); + set_bit(LFL_AST_WAIT, &lpn->flags); + + gdlm_do_lock(lpn); + wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE); + error = lpn->lksb.sb_status; + if (error) { + printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n", + error); + gdlm_delete_lp(lpn); + lpn = NULL; + } +out: + lp->hold_null = lpn; + return error; +} + +/* This cannot do a synchronous dlm request (requiring a lock_dlm thread to get + the completion) because gfs may call unhold_lvb() during a callback (from + the context of a lock_dlm thread) which could cause a deadlock since the + other lock_dlm thread could be engaged in recovery. */ + +static void unhold_null_lock(struct gdlm_lock *lp) +{ + struct gdlm_lock *lpn = lp->hold_null; + + gdlm_assert(lpn, "%x,%llx", lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number); + lpn->lksb.sb_lvbptr = NULL; + lpn->lvb = NULL; + set_bit(LFL_UNLOCK_DELETE, &lpn->flags); + gdlm_do_unlock(lpn); + lp->hold_null = NULL; +} + +/* Acquire a NL lock because gfs requires the value block to remain + intact on the resource while the lvb is "held" even if it's holding no locks + on the resource. */ + +int gdlm_hold_lvb(void *lock, char **lvbp) +{ + struct gdlm_lock *lp = lock; + int error; + + error = gdlm_add_lvb(lp); + if (error) + return error; + + *lvbp = lp->lvb; + + error = hold_null_lock(lp); + if (error) + gdlm_del_lvb(lp); + + return error; +} + +void gdlm_unhold_lvb(void *lock, char *lvb) +{ + struct gdlm_lock *lp = lock; + + unhold_null_lock(lp); + gdlm_del_lvb(lp); +} + +void gdlm_submit_delayed(struct gdlm_ls *ls) +{ + struct gdlm_lock *lp, *safe; + + spin_lock(&ls->async_lock); + list_for_each_entry_safe(lp, safe, &ls->delayed, delay_list) { + list_del_init(&lp->delay_list); + list_add_tail(&lp->delay_list, &ls->submit); + } + spin_unlock(&ls->async_lock); + wake_up(&ls->thread_wait); +} + +int gdlm_release_all_locks(struct gdlm_ls *ls) +{ + struct gdlm_lock *lp, *safe; + int count = 0; + + spin_lock(&ls->async_lock); + list_for_each_entry_safe(lp, safe, &ls->all_locks, all_list) { + list_del_init(&lp->all_list); + + if (lp->lvb && lp->lvb != junk_lvb) + kfree(lp->lvb); + kfree(lp); + count++; + } + spin_unlock(&ls->async_lock); + + return count; +} + --- linux-2.6.27.orig/ubuntu/gfs/Kconfig +++ linux-2.6.27/ubuntu/gfs/Kconfig @@ -0,0 +1,18 @@ +config GFS_FS + tristate "GFS file system support" + select FS_POSIX_ACL + select CRC32 + help + A cluster filesystem. + + Allows a cluster of computers to simultaneously use a block device + that is shared between them (with FC, iSCSI, NBD, etc...). GFS reads + and writes to the block device like a local filesystem, but also uses + a lock module to allow the computers coordinate their I/O so + filesystem consistency is maintained. One of the nifty features of + GFS is perfect consistency -- changes made to the filesystem on one + machine show up immediately on all other machines in the cluster. + + To use the GFS filesystem, you will need to enable one or more of + the below locking modules. Documentation and utilities for GFS can + be found here: http://sources.redhat.com/cluster --- linux-2.6.27.orig/ubuntu/gfs/ondisk.c +++ linux-2.6.27/ubuntu/gfs/ondisk.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" + +#define pv(struct, member, fmt) printk(" "#member" = "fmt"\n", struct->member); + +#define WANT_GFS_CONVERSION_FUNCTIONS +#include "gfs_ondisk.h" + --- linux-2.6.27.orig/ubuntu/gfs/format.h +++ linux-2.6.27/ubuntu/gfs/format.h @@ -0,0 +1,17 @@ +#ifndef __FORMAT_DOT_H__ +#define __FORMAT_DOT_H__ + +static const uint32_t gfs_old_fs_formats[] = { + 1308, + 1307, + 1306, + 1305, + 0 +}; + +static const uint32_t gfs_old_multihost_formats[] = { + 1400, + 0 +}; + +#endif /* __FORMAT_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lock_dlm_thread.c +++ linux-2.6.27/ubuntu/gfs/lock_dlm_thread.c @@ -0,0 +1,367 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include "lock_dlm.h" + +/* A lock placed on this queue is re-submitted to DLM as soon as the lock_dlm + thread gets to it. */ + +static void queue_submit(struct gdlm_lock *lp) +{ + struct gdlm_ls *ls = lp->ls; + + spin_lock(&ls->async_lock); + list_add_tail(&lp->delay_list, &ls->submit); + spin_unlock(&ls->async_lock); + wake_up(&ls->thread_wait); +} + +static void process_blocking(struct gdlm_lock *lp, int bast_mode) +{ + struct gdlm_ls *ls = lp->ls; + unsigned int cb = 0; + + switch (gdlm_make_lmstate(bast_mode)) { + case LM_ST_EXCLUSIVE: + cb = LM_CB_NEED_E; + break; + case LM_ST_DEFERRED: + cb = LM_CB_NEED_D; + break; + case LM_ST_SHARED: + cb = LM_CB_NEED_S; + break; + default: + gdlm_assert(0, "unknown bast mode %u", lp->bast_mode); + } + + ls->fscb(ls->sdp, cb, &lp->lockname); +} + +static void wake_up_ast(struct gdlm_lock *lp) +{ + clear_bit(LFL_AST_WAIT, &lp->flags); + smp_mb__after_clear_bit(); + wake_up_bit(&lp->flags, LFL_AST_WAIT); +} + +static void process_complete(struct gdlm_lock *lp) +{ + struct gdlm_ls *ls = lp->ls; + struct lm_async_cb acb; + s16 prev_mode = lp->cur; + + memset(&acb, 0, sizeof(acb)); + + if (lp->lksb.sb_status == -DLM_ECANCEL) { + log_info("complete dlm cancel %x,%llx flags %lx", + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, + lp->flags); + + lp->req = lp->cur; + acb.lc_ret |= LM_OUT_CANCELED; + if (lp->cur == DLM_LOCK_IV) + lp->lksb.sb_lkid = 0; + goto out; + } + + if (test_and_clear_bit(LFL_DLM_UNLOCK, &lp->flags)) { + if (lp->lksb.sb_status != -DLM_EUNLOCK) { + log_info("unlock sb_status %d %x,%llx flags %lx", + lp->lksb.sb_status, lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, + lp->flags); + return; + } + + lp->cur = DLM_LOCK_IV; + lp->req = DLM_LOCK_IV; + lp->lksb.sb_lkid = 0; + + if (test_and_clear_bit(LFL_UNLOCK_DELETE, &lp->flags)) { + gdlm_delete_lp(lp); + return; + } + goto out; + } + + if (lp->lksb.sb_flags & DLM_SBF_VALNOTVALID) + memset(lp->lksb.sb_lvbptr, 0, GDLM_LVB_SIZE); + + if (lp->lksb.sb_flags & DLM_SBF_ALTMODE) { + if (lp->req == DLM_LOCK_PR) + lp->req = DLM_LOCK_CW; + else if (lp->req == DLM_LOCK_CW) + lp->req = DLM_LOCK_PR; + } + + /* + * A canceled lock request. The lock was just taken off the delayed + * list and was never even submitted to dlm. + */ + + if (test_and_clear_bit(LFL_CANCEL, &lp->flags)) { + log_info("complete internal cancel %x,%llx", + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number); + lp->req = lp->cur; + acb.lc_ret |= LM_OUT_CANCELED; + goto out; + } + + /* + * An error occured. + */ + + if (lp->lksb.sb_status) { + /* a "normal" error */ + if ((lp->lksb.sb_status == -EAGAIN) && + (lp->lkf & DLM_LKF_NOQUEUE)) { + lp->req = lp->cur; + if (lp->cur == DLM_LOCK_IV) + lp->lksb.sb_lkid = 0; + goto out; + } + + /* this could only happen with cancels I think */ + log_info("ast sb_status %d %x,%llx flags %lx", + lp->lksb.sb_status, lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, + lp->flags); + return; + } + + /* + * This is an AST for an EX->EX conversion for sync_lvb from GFS. + */ + + if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { + wake_up_ast(lp); + return; + } + + /* + * A lock has been demoted to NL because it initially completed during + * BLOCK_LOCKS. Now it must be requested in the originally requested + * mode. + */ + + if (test_and_clear_bit(LFL_REREQUEST, &lp->flags)) { + gdlm_assert(lp->req == DLM_LOCK_NL, "%x,%llx", + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number); + gdlm_assert(lp->prev_req > DLM_LOCK_NL, "%x,%llx", + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number); + + lp->cur = DLM_LOCK_NL; + lp->req = lp->prev_req; + lp->prev_req = DLM_LOCK_IV; + lp->lkf &= ~DLM_LKF_CONVDEADLK; + + set_bit(LFL_NOCACHE, &lp->flags); + + if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && + !test_bit(LFL_NOBLOCK, &lp->flags)) + gdlm_queue_delayed(lp); + else + queue_submit(lp); + return; + } + + /* + * A request is granted during dlm recovery. It may be granted + * because the locks of a failed node were cleared. In that case, + * there may be inconsistent data beneath this lock and we must wait + * for recovery to complete to use it. When gfs recovery is done this + * granted lock will be converted to NL and then reacquired in this + * granted state. + */ + + if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && + !test_bit(LFL_NOBLOCK, &lp->flags) && + lp->req != DLM_LOCK_NL) { + + lp->cur = lp->req; + lp->prev_req = lp->req; + lp->req = DLM_LOCK_NL; + lp->lkf |= DLM_LKF_CONVERT; + lp->lkf &= ~DLM_LKF_CONVDEADLK; + + log_debug("rereq %x,%llx id %x %d,%d", + lp->lockname.ln_type, + (unsigned long long)lp->lockname.ln_number, + lp->lksb.sb_lkid, lp->cur, lp->req); + + set_bit(LFL_REREQUEST, &lp->flags); + queue_submit(lp); + return; + } + + /* + * DLM demoted the lock to NL before it was granted so GFS must be + * told it cannot cache data for this lock. + */ + + if (lp->lksb.sb_flags & DLM_SBF_DEMOTED) + set_bit(LFL_NOCACHE, &lp->flags); + +out: + /* + * This is an internal lock_dlm lock + */ + + if (test_bit(LFL_INLOCK, &lp->flags)) { + clear_bit(LFL_NOBLOCK, &lp->flags); + lp->cur = lp->req; + wake_up_ast(lp); + return; + } + + /* + * Normal completion of a lock request. Tell GFS it now has the lock. + */ + + clear_bit(LFL_NOBLOCK, &lp->flags); + lp->cur = lp->req; + + acb.lc_name = lp->lockname; + acb.lc_ret |= gdlm_make_lmstate(lp->cur); + + if (!test_and_clear_bit(LFL_NOCACHE, &lp->flags) && + (lp->cur > DLM_LOCK_NL) && (prev_mode > DLM_LOCK_NL)) + acb.lc_ret |= LM_OUT_CACHEABLE; + + ls->fscb(ls->sdp, LM_CB_ASYNC, &acb); +} + +static inline int no_work(struct gdlm_ls *ls, int blocking) +{ + int ret; + + spin_lock(&ls->async_lock); + ret = list_empty(&ls->complete) && list_empty(&ls->submit); + if (ret && blocking) + ret = list_empty(&ls->blocking); + spin_unlock(&ls->async_lock); + + return ret; +} + +static inline int check_drop(struct gdlm_ls *ls) +{ + if (!ls->drop_locks_count) + return 0; + + if (time_after(jiffies, ls->drop_time + ls->drop_locks_period * HZ)) { + ls->drop_time = jiffies; + if (ls->all_locks_count >= ls->drop_locks_count) + return 1; + } + return 0; +} + +static int gdlm_thread(void *data, int blist) +{ + struct gdlm_ls *ls = (struct gdlm_ls *) data; + struct gdlm_lock *lp = NULL; + uint8_t complete, blocking, submit, drop; + + /* Only thread1 is allowed to do blocking callbacks since gfs + may wait for a completion callback within a blocking cb. */ + + while (!kthread_should_stop()) { + wait_event_interruptible(ls->thread_wait, + !no_work(ls, blist) || kthread_should_stop()); + + complete = blocking = submit = drop = 0; + + spin_lock(&ls->async_lock); + + if (blist && !list_empty(&ls->blocking)) { + lp = list_entry(ls->blocking.next, struct gdlm_lock, + blist); + list_del_init(&lp->blist); + blocking = lp->bast_mode; + lp->bast_mode = 0; + } else if (!list_empty(&ls->complete)) { + lp = list_entry(ls->complete.next, struct gdlm_lock, + clist); + list_del_init(&lp->clist); + complete = 1; + } else if (!list_empty(&ls->submit)) { + lp = list_entry(ls->submit.next, struct gdlm_lock, + delay_list); + list_del_init(&lp->delay_list); + submit = 1; + } + + drop = check_drop(ls); + spin_unlock(&ls->async_lock); + + if (complete) + process_complete(lp); + + else if (blocking) + process_blocking(lp, blocking); + + else if (submit) + gdlm_do_lock(lp); + + if (drop) + ls->fscb(ls->sdp, LM_CB_DROPLOCKS, NULL); + + schedule(); + } + + return 0; +} + +static int gdlm_thread1(void *data) +{ + return gdlm_thread(data, 1); +} + +static int gdlm_thread2(void *data) +{ + return gdlm_thread(data, 0); +} + +int gdlm_init_threads(struct gdlm_ls *ls) +{ + struct task_struct *p; + int error; + + p = kthread_run(gdlm_thread1, ls, "lock_dlm1"); + error = IS_ERR(p); + if (error) { + log_error("can't start lock_dlm1 thread %d", error); + return error; + } + ls->thread1 = p; + + p = kthread_run(gdlm_thread2, ls, "lock_dlm2"); + error = IS_ERR(p); + if (error) { + log_error("can't start lock_dlm2 thread %d", error); + kthread_stop(ls->thread1); + return error; + } + ls->thread2 = p; + + return 0; +} + +void gdlm_release_threads(struct gdlm_ls *ls) +{ + kthread_stop(ls->thread1); + kthread_stop(ls->thread2); +} + --- linux-2.6.27.orig/ubuntu/gfs/ops_inode.h +++ linux-2.6.27/ubuntu/gfs/ops_inode.h @@ -0,0 +1,9 @@ +#ifndef __OPS_INODE_DOT_H__ +#define __OPS_INODE_DOT_H__ + +extern struct inode_operations gfs_file_iops; +extern struct inode_operations gfs_dir_iops; +extern struct inode_operations gfs_symlink_iops; +extern struct inode_operations gfs_dev_iops; + +#endif /* __OPS_INODE_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/fixed_div64.h +++ linux-2.6.27/ubuntu/gfs/fixed_div64.h @@ -0,0 +1,107 @@ +#ifndef __FIXED_DIV64_DOT_H__ +#define __FIXED_DIV64_DOT_H__ + +#include + +#if defined __i386__ +/* For ia32 we need to pull some tricks to get past various versions + * of the compiler which do not like us using do_div in the middle + * of large functions. + */ +static inline __u32 fixed_div64_do_div(void *a, __u32 b, int n) +{ + __u32 mod; + + switch (n) { + case 4: + mod = *(__u32 *)a % b; + *(__u32 *)a = *(__u32 *)a / b; + return mod; + case 8: + { + unsigned long __upper, __low, __high, __mod; + __u64 c = *(__u64 *)a; + __upper = __high = c >> 32; + __low = c; + if (__high) { + __upper = __high % (b); + __high = __high / (b); + } + asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper)); + asm("":"=A" (c):"a" (__low),"d" (__high)); + *(__u64 *)a = c; + return __mod; + } + } + + /* NOTREACHED */ + return 0; +} + +/* Side effect free 64 bit mod operation */ +static inline __u32 fixed_div64_do_mod(void *a, __u32 b, int n) +{ + switch (n) { + case 4: + return *(__u32 *)a % b; + case 8: + { + unsigned long __upper, __low, __high, __mod; + __u64 c = *(__u64 *)a; + __upper = __high = c >> 32; + __low = c; + if (__high) { + __upper = __high % (b); + __high = __high / (b); + } + asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper)); + asm("":"=A" (c):"a" (__low),"d" (__high)); + return __mod; + } + } + + /* NOTREACHED */ + return 0; +} +#else +static inline __u32 fixed_div64_do_div(void *a, __u32 b, int n) +{ + __u32 mod; + + switch (n) { + case 4: + mod = *(__u32 *)a % b; + *(__u32 *)a = *(__u32 *)a / b; + return mod; + case 8: + mod = do_div(*(__u64 *)a, b); + return mod; + } + + /* NOTREACHED */ + return 0; +} + +/* Side effect free 64 bit mod operation */ +static inline __u32 fixed_div64_do_mod(void *a, __u32 b, int n) +{ + switch (n) { + case 4: + return *(__u32 *)a % b; + case 8: + { + __u64 c = *(__u64 *)a; + return do_div(c, b); + } + } + + /* NOTREACHED */ + return 0; +} +#endif + +#undef do_div +#define do_div(a, b) fixed_div64_do_div(&(a), (b), sizeof(a)) +#define do_mod(a, b) fixed_div64_do_mod(&(a), (b), sizeof(a)) + +#endif /* __FIXED_DIV64_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/proc.h +++ linux-2.6.27/ubuntu/gfs/proc.h @@ -0,0 +1,14 @@ +#ifndef __PROC_DOT_H__ +#define __PROC_DOT_H__ + +/* Allow args to be passed to GFS when using an initial ram disk */ +extern char *gfs_proc_margs; +extern spinlock_t gfs_proc_margs_lock; + +void gfs_proc_fs_add(struct gfs_sbd *sdp); +void gfs_proc_fs_del(struct gfs_sbd *sdp); + +int gfs_proc_init(void); +void gfs_proc_uninit(void); + +#endif /* __PROC_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/main.c +++ linux-2.6.27/ubuntu/gfs/main.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "ops_fstype.h" +#include "sys.h" +#include "proc.h" + +/** + * init_gfs_fs - Register GFS as a filesystem + * + * Returns: 0 on success, error code on failure + */ + +int __init init_gfs_fs(void) +{ + int error; + struct timespec tv; + +/* gfs2_init_lmh(); gfs2 should do this for us*/ + + error = gfs_sys_init(); + if (error) + return error; + error = gfs_proc_init(); + if (error) + goto fail; + + getnstimeofday(&tv); + gfs_random_number = tv.tv_nsec; + + gfs_glock_cachep = kmem_cache_create("gfs_glock", sizeof(struct gfs_glock), + 0, 0, + NULL); + gfs_inode_cachep = NULL; + gfs_bufdata_cachep = NULL; + gfs_mhc_cachep = NULL; + error = -ENOMEM; + if (!gfs_glock_cachep) + goto fail1; + + gfs_inode_cachep = kmem_cache_create("gfs_inode", sizeof(struct gfs_inode), + 0, 0, + NULL); + if (!gfs_inode_cachep) + goto fail1; + + gfs_bufdata_cachep = kmem_cache_create("gfs_bufdata", sizeof(struct gfs_bufdata), + 0, 0, + NULL); + if (!gfs_bufdata_cachep) + goto fail1; + + gfs_mhc_cachep = kmem_cache_create("gfs_meta_header_cache", sizeof(struct gfs_meta_header_cache), + 0, 0, + NULL); + if (!gfs_mhc_cachep) + goto fail; + + error = register_filesystem(&gfs_fs_type); + if (error) + goto fail; + + printk("GFS %s (built %s %s) installed\n", + RELEASE_VERSION, __DATE__, __TIME__); + + error = init_lock_dlm(); + if (error) + goto fail1; + + error = init_nolock(); + if (error) + goto fail1; + + return 0; + + fail1: + if (gfs_mhc_cachep) + kmem_cache_destroy(gfs_mhc_cachep); + + if (gfs_bufdata_cachep) + kmem_cache_destroy(gfs_bufdata_cachep); + + if (gfs_inode_cachep) + kmem_cache_destroy(gfs_inode_cachep); + + if (gfs_glock_cachep) + kmem_cache_destroy(gfs_glock_cachep); + + gfs_proc_uninit(); + + fail: + gfs_sys_uninit(); + + return error; +} + +/** + * exit_gfs_fs - Unregister the file system + * + */ + +void __exit +exit_gfs_fs(void) +{ + exit_nolock(); + exit_lock_dlm(); + unregister_filesystem(&gfs_fs_type); + + kmem_cache_destroy(gfs_mhc_cachep); + kmem_cache_destroy(gfs_bufdata_cachep); + kmem_cache_destroy(gfs_inode_cachep); + kmem_cache_destroy(gfs_glock_cachep); + + gfs_proc_uninit(); + gfs_sys_uninit(); +} + +MODULE_DESCRIPTION("Global File System " RELEASE_VERSION); +MODULE_AUTHOR("Red Hat, Inc."); +MODULE_LICENSE("GPL"); + +module_init(init_gfs_fs); +module_exit(exit_gfs_fs); + --- linux-2.6.27.orig/ubuntu/gfs/eaops.c +++ linux-2.6.27/ubuntu/gfs/eaops.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "acl.h" +#include "eaops.h" +#include "eattr.h" + +/** + * gfs_ea_name2type - get the type of the ea, and trucate the type from the name + * @namep: ea name, possibly with type appended + * + * Returns: GFS_EATYPE_XXX + */ + +unsigned int +gfs_ea_name2type(const char *name, char **truncated_name) +{ + unsigned int type; + + if (strncmp(name, "system.", 7) == 0) { + type = GFS_EATYPE_SYS; + if (truncated_name) + *truncated_name = strchr(name, '.') + 1; + } else if (strncmp(name, "user.", 5) == 0) { + type = GFS_EATYPE_USR; + if (truncated_name) + *truncated_name = strchr(name, '.') + 1; + } else if (strncmp(name, "security.", 9) == 0) { + type = GFS_EATYPE_SECURITY; + if (truncated_name) + *truncated_name = strchr(name, '.') + 1; + } else { + type = GFS_EATYPE_UNUSED; + if (truncated_name) + *truncated_name = NULL; + } + + return type; +} + +/** + * system_eo_get - + * @ip: + * @er: + * + * Returns: errno + */ + +static int +system_eo_get(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + if (!GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len) && + !GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len) && + !capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (ip->i_sbd->sd_args.ar_posix_acls == FALSE && + (GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len) || + GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len))) + return -EOPNOTSUPP; + + return gfs_ea_get_i(ip, er); +} + +/** + * system_eo_set - + * @ip: + * @er: + * + * Returns: errno + */ + +static int +system_eo_set(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + int remove = FALSE; + int error; + + if (GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len)) { + er->er_mode = ip->i_vnode->i_mode; + error = gfs_acl_validate_set(ip, TRUE, er, + &remove, &er->er_mode); + if (error) + return error; + error = gfs_ea_set_i(ip, er); + if (error) + return error; + if (remove) + gfs_ea_remove_i(ip, er); + return 0; + + } else if (GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) { + int error = gfs_acl_validate_set(ip, FALSE, er, + &remove, NULL); + if (error) + return error; + if (!remove) + error = gfs_ea_set_i(ip, er); + else { + error = gfs_ea_remove_i(ip, er); + if (error == -ENODATA) + error = 0; + } + return error; + } + + return -EPERM; +} + +/** + * system_eo_remove - + * @ip: + * @er: + * + * Returns: errno + */ + +static int +system_eo_remove(struct gfs_inode *ip, struct gfs_ea_request *er) +{ + if (GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len)) { + int error = gfs_acl_validate_remove(ip, TRUE); + if (error) + return error; + + } else if (GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) { + int error = gfs_acl_validate_remove(ip, FALSE); + if (error) + return error; + + } else + return -EPERM; + + return gfs_ea_remove_i(ip, er); +} + +struct gfs_eattr_operations gfs_user_eaops = { + .eo_get = gfs_ea_get_i, + .eo_set = gfs_ea_set_i, + .eo_remove = gfs_ea_remove_i, + .eo_name = "user", +}; + +struct gfs_eattr_operations gfs_system_eaops = { + .eo_get = system_eo_get, + .eo_set = system_eo_set, + .eo_remove = system_eo_remove, + .eo_name = "system", +}; + +struct gfs_eattr_operations gfs_security_eaops = { + .eo_get = gfs_ea_get_i, + .eo_set = gfs_ea_set_i, + .eo_remove = gfs_ea_remove_i, + .eo_name = "security", +}; + +struct gfs_eattr_operations *gfs_ea_ops[] = { + NULL, + &gfs_user_eaops, + &gfs_system_eaops, + &gfs_security_eaops, +}; + --- linux-2.6.27.orig/ubuntu/gfs/lm.c +++ linux-2.6.27/ubuntu/gfs/lm.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include + +#include "gfs_ondisk.h" +#include "gfs.h" +#include "incore.h" +#include "glock.h" +#include "lm.h" +#include "super.h" +#include "util.h" +#include "lvb.h" + +/** + * gfs_lm_mount - mount a locking protocol + * @sdp: the filesystem + * @args: mount arguements + * @silent: if 1, don't complain if the FS isn't a GFS fs + * + * Returns: errno + */ + +int gfs_lm_mount(struct gfs_sbd *sdp, int silent) +{ + char *proto = sdp->sd_proto_name; + char *table = sdp->sd_table_name; + int flags = 0; + int error; + + if (sdp->sd_args.ar_spectator) + flags |= LM_MFLAG_SPECTATOR; + + printk("Trying to join cluster \"%s\", \"%s\"\n", proto, table); + + error = gfs_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata, + gfs_glock_cb, sdp, + GFS_MIN_LVB_SIZE, flags, + &sdp->sd_lockstruct, &sdp->sd_kobj); + if (error) { + printk("can't mount proto=%s, table=%s, hostdata=%s\n", + proto, table, sdp->sd_args.ar_hostdata); + goto out; + } + + if (gfs_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) || + gfs_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) || + gfs_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >= + GFS_MIN_LVB_SIZE)) { + gfs_unmount_lockproto(&sdp->sd_lockstruct); + goto out; + } + + if (sdp->sd_args.ar_spectator) + snprintf(sdp->sd_fsname, 256, "%s.s", table); + else + snprintf(sdp->sd_fsname, 256, "%s.%u", table, + sdp->sd_lockstruct.ls_jid); + + printk("Joined cluster. Now mounting FS...\n"); + if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) && + !sdp->sd_args.ar_ignore_local_fs) { + sdp->sd_args.ar_localflocks = 1; + sdp->sd_args.ar_localcaching = 1; + } + + out: + return error; +} + +void gfs_lm_others_may_mount(struct gfs_sbd *sdp) +{ + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + sdp->sd_lockstruct.ls_ops->lm_others_may_mount( + sdp->sd_lockstruct.ls_lockspace); +} + +void gfs_lm_unmount(struct gfs_sbd *sdp) +{ + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + gfs_unmount_lockproto(&sdp->sd_lockstruct); +} + +int gfs_lm_withdraw(struct gfs_sbd *sdp, char *fmt, ...) +{ + va_list args; + + if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + return 0; + + va_start(args, fmt); + vprintk(fmt, args); + va_end(args); + + printk("GFS: fsid=%s: about to withdraw from the cluster\n", + sdp->sd_fsname); + + BUG_ON(sdp->sd_args.ar_debug); + + printk("GFS: fsid=%s: telling LM to withdraw\n", + sdp->sd_fsname); + + gfs_withdraw_lockproto(&sdp->sd_lockstruct); + + printk("GFS: fsid=%s: withdrawn\n", + sdp->sd_fsname); + dump_stack(); + + return -1; +} + +int gfs_lm_get_lock(struct gfs_sbd *sdp, struct lm_lockname *name, + void **lockp) +{ + int error; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + error = -EIO; + else + error = sdp->sd_lockstruct.ls_ops->lm_get_lock( + sdp->sd_lockstruct.ls_lockspace, name, lockp); + return error; +} + +void gfs_lm_put_lock(struct gfs_sbd *sdp, void *lock) +{ + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + sdp->sd_lockstruct.ls_ops->lm_put_lock(lock); +} + +unsigned int gfs_lm_lock(struct gfs_sbd *sdp, void *lock, + unsigned int cur_state, unsigned int req_state, + unsigned int flags) +{ + int ret; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + ret = 0; + else + ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, + cur_state, + req_state, flags); + return ret; +} + +unsigned int gfs_lm_unlock(struct gfs_sbd *sdp, void *lock, + unsigned int cur_state) +{ + int ret; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + ret = 0; + else + ret = sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state); + return ret; +} + +void gfs_lm_cancel(struct gfs_sbd *sdp, void *lock) +{ + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + sdp->sd_lockstruct.ls_ops->lm_cancel(lock); +} + +int gfs_lm_hold_lvb(struct gfs_sbd *sdp, void *lock, char **lvbp) +{ + int error; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + error = -EIO; + else + error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp); + return error; +} + +void gfs_lm_unhold_lvb(struct gfs_sbd *sdp, void *lock, char *lvb) +{ + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(lock, lvb); +} + +#if 0 +void gfs_lm_sync_lvb(struct gfs_sbd *sdp, void *lock, char *lvb) +{ + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + sdp->sd_lockstruct.ls_ops->lm_sync_lvb(lock, lvb); +} +#endif + +int gfs_lm_plock_get(struct gfs_sbd *sdp, struct lm_lockname *name, + struct file *file, struct file_lock *fl) +{ + int error; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + error = -EIO; + else + error = sdp->sd_lockstruct.ls_ops->lm_plock_get( + sdp->sd_lockstruct.ls_lockspace, + name, file, fl); + return error; +} + +int gfs_lm_plock(struct gfs_sbd *sdp, struct lm_lockname *name, + struct file *file, int cmd, struct file_lock *fl) +{ + int error; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + error = -EIO; + else + error = sdp->sd_lockstruct.ls_ops->lm_plock( + sdp->sd_lockstruct.ls_lockspace, + name, file, cmd, fl); + return error; +} + +int gfs_lm_punlock(struct gfs_sbd *sdp, struct lm_lockname *name, + struct file *file, struct file_lock *fl) +{ + int error; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + error = -EIO; + else + error = sdp->sd_lockstruct.ls_ops->lm_punlock( + sdp->sd_lockstruct.ls_lockspace, + name, file, fl); + return error; +} + +void gfs_lm_recovery_done(struct gfs_sbd *sdp, unsigned int jid, + unsigned int message) +{ + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + sdp->sd_lockstruct.ls_ops->lm_recovery_done( + sdp->sd_lockstruct.ls_lockspace, jid, message); +} + --- linux-2.6.27.orig/ubuntu/gfs/ops_address.c +++ linux-2.6.27/ubuntu/gfs/ops_address.c @@ -0,0 +1,504 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bmap.h" +#include "dio.h" +#include "file.h" +#include "glock.h" +#include "inode.h" +#include "ops_address.h" +#include "page.h" +#include "quota.h" +#include "trans.h" + +static int gfs_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to); +/** + * get_block - Fills in a buffer head with details about a block + * @inode: The inode + * @lblock: The block number to look up + * @bh_result: The buffer head to return the result in + * @create: Non-zero if we may add block to the file + * + * Returns: errno + */ + +static int +get_block(struct inode *inode, sector_t lblock, + struct buffer_head *bh_result, int create) +{ + struct gfs_inode *ip = get_v2ip(inode); + int new = create; + uint64_t dblock; + int error; + + error = gfs_block_map(ip, lblock, &new, &dblock, NULL); + if (error) + return error; + + if (!dblock) + return 0; + + map_bh(bh_result, inode->i_sb, dblock); + if (new) + set_buffer_new(bh_result); + + return 0; +} + +/** + * get_block_noalloc - Fills in a buffer head with details about a block + * @inode: The inode + * @lblock: The block number to look up + * @bh_result: The buffer head to return the result in + * @create: Non-zero if we may add block to the file + * + * Returns: errno + */ + +static int +get_block_noalloc(struct inode *inode, sector_t lblock, + struct buffer_head *bh_result, int create) +{ + int error; + + error = get_block(inode, lblock, bh_result, FALSE); + if (error) + return error; + + if (gfs_assert_withdraw(get_v2sdp(inode->i_sb), + !create || buffer_mapped(bh_result))) + return -EIO; + + return 0; +} + +/** + * get_blocks - + * @inode: + * @lblock: + * @max_blocks: + * @bh_result: + * @create: + * + * Returns: errno + */ + +static int +get_blocks(struct inode *inode, sector_t lblock, + struct buffer_head *bh_result, int create) +{ + struct gfs_inode *ip = get_v2ip(inode); + int new = create; + uint64_t dblock; + int error; + + error = gfs_block_map(ip, lblock, &new, &dblock, NULL); + if (error) + return error; + + if (!dblock) + return 0; + + map_bh(bh_result, inode->i_sb, dblock); + if (new) + set_buffer_new(bh_result); + + return 0; +} + +/** + * get_blocks_noalloc - + * @inode: + * @lblock: + * @max_blocks: + * @bh_result: + * @create: + * + * Returns: errno + */ + +static int +get_blocks_noalloc(struct inode *inode, sector_t lblock, + struct buffer_head *bh_result, int create) +{ + int error; + + error = get_blocks(inode, lblock, bh_result, FALSE); + if (error) + return error; + + if (gfs_assert_withdraw(get_v2sdp(inode->i_sb), + !create || buffer_mapped(bh_result))) + return -EIO; + + return 0; +} + +/** + * gfs_writepage - Write complete page + * @page: Page to write + * + * Returns: errno + * + * Use Linux VFS block_write_full_page() to write one page, + * using GFS's get_block_noalloc to find which blocks to write. + */ + +static int +gfs_writepage(struct page *page, struct writeback_control *wbc) +{ + struct gfs_inode *ip = get_v2ip(page->mapping->host); + struct gfs_sbd *sdp = ip->i_sbd; + int error; + + atomic_inc(&sdp->sd_ops_address); + + if (gfs_assert_withdraw(sdp, gfs_glock_is_held_excl(ip->i_gl))) { + unlock_page(page); + return -EIO; + } + if (get_transaction) { + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return 0; + } + + error = block_write_full_page(page, get_block_noalloc, wbc); + + gfs_flush_meta_cache(ip); + + return error; +} + +/** + * stuffed_readpage - Fill in a Linux page with stuffed file data + * @ip: the inode + * @page: the page + * + * Returns: errno + */ + +static int +stuffed_readpage(struct gfs_inode *ip, struct page *page) +{ + struct buffer_head *dibh; + void *kaddr; + int error; + + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + kaddr = kmap(page); + memcpy((char *)kaddr, + dibh->b_data + sizeof(struct gfs_dinode), + ip->i_di.di_size); + memset((char *)kaddr + ip->i_di.di_size, + 0, + PAGE_CACHE_SIZE - ip->i_di.di_size); + kunmap(page); + + brelse(dibh); + + SetPageUptodate(page); + } + + return error; +} + +/** + * readi_readpage - readpage that goes through gfs_internal_read() + * @page: The page to read + * + * Returns: errno + */ + +static int +readi_readpage(struct page *page) +{ + struct gfs_inode *ip = get_v2ip(page->mapping->host); + void *kaddr; + int ret; + + kaddr = kmap(page); + + ret = gfs_internal_read(ip, kaddr, + (uint64_t)page->index << PAGE_CACHE_SHIFT, + PAGE_CACHE_SIZE); + if (ret >= 0) { + if (ret < PAGE_CACHE_SIZE) + memset(kaddr + ret, 0, PAGE_CACHE_SIZE - ret); + SetPageUptodate(page); + ret = 0; + } + + kunmap(page); + + unlock_page(page); + + return ret; +} + +/** + * gfs_readpage - readpage with locking + * @file: The file to read a page for + * @page: The page to read + * + * Returns: errno + */ + +static int +gfs_readpage(struct file *file, struct page *page) +{ + struct gfs_inode *ip = get_v2ip(page->mapping->host); + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_holder *gh; + int error; + + atomic_inc(&sdp->sd_ops_address); + + /* When gfs_readpage is called from the sys_madvise code through the + * readahead code, the inode glock is not held. In this case, we hold + * the inode glock, unlock the page and return AOP_TRUNCATED_PAGE. The + * caller will then reload the page and call gfs_readpage again. We + * also add the flag GL_READPAGE to denote that the glock was held in + * this function and if so, we unlock it before leaving this function + */ + gh = gfs_glock_is_locked_by_me(ip->i_gl); + if (!gh) { + gh = kmalloc(sizeof(struct gfs_holder), GFP_NOFS); + if (!gh) + return -ENOBUFS; + gfs_holder_init(ip->i_gl, LM_ST_SHARED, + GL_READPAGE | LM_FLAG_ANY, gh); + unlock_page(page); + error = gfs_glock_nq(gh); + if (error) { + gfs_holder_uninit(gh); + kfree(gh); + goto out; + } + return AOP_TRUNCATED_PAGE; + } + + if (!gfs_is_jdata(ip)) { + if (gfs_is_stuffed(ip) && !page->index) { + error = stuffed_readpage(ip, page); + unlock_page(page); + } else + error = block_read_full_page(page, get_block); + } else + error = readi_readpage(page); + + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + error = -EIO; + + if (gh->gh_flags & GL_READPAGE) { /* If we grabbed the glock here */ + gfs_glock_dq_uninit(gh); + kfree(gh); + } +out: + return error; +} + +/** + * gfs_prepare_write - Prepare to write a page to a file + * @file: The file to write to + * @page: The page which is to be prepared for writing + * @from: From (byte range within page) + * @to: To (byte range within page) + * + * Returns: errno + * + * Make sure file's inode is glocked; we shouldn't write without that! + * If GFS dinode is currently stuffed (small enough that all data fits within + * the dinode block), and new file size is too large, unstuff it. + * Use Linux VFS block_prepare_write() to write blocks, using GFS' get_block() + * to find which blocks to write. + */ + +static int +gfs_prepare_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + struct gfs_inode *ip = get_v2ip(page->mapping->host); + struct gfs_sbd *sdp = ip->i_sbd; + int error = 0; + + atomic_inc(&sdp->sd_ops_address); + + /* We can't set commit_write in the structure in the declare */ + /* because if we do, loopback (loop.c) will interpret that to mean */ + /* it's okay to do buffered writes without locking through sendfile. */ + /* This is a kludge to get around the problem with loop.c because */ + /* the upstream community rejected my changes to loop.c. */ + ip->gfs_file_aops.commit_write = gfs_commit_write; + + if (gfs_assert_warn(sdp, gfs_glock_is_locked_by_me(ip->i_gl))) + return -ENOSYS; + + if (gfs_is_stuffed(ip)) { + uint64_t file_size = ((uint64_t)page->index << PAGE_CACHE_SHIFT) + to; + + if (file_size > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) { + error = gfs_unstuff_dinode(ip, gfs_unstuffer_page, page); + if (!error) + error = block_prepare_write(page, from, to, get_block); + } else if (!PageUptodate(page)) + error = stuffed_readpage(ip, page); + } else + error = block_prepare_write(page, from, to, get_block); + + return error; +} + +/** + * gfs_commit_write - Commit write to a file + * @file: The file to write to + * @page: The page containing the data + * @from: From (byte range within page) + * @to: To (byte range within page) + * + * Returns: errno + */ + +static int +gfs_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + struct inode *inode = page->mapping->host; + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_sbd *sdp = ip->i_sbd; + int error; + + atomic_inc(&sdp->sd_ops_address); + + if (gfs_is_stuffed(ip)) { + struct buffer_head *dibh; + uint64_t file_size = ((uint64_t)page->index << PAGE_CACHE_SHIFT) + to; + void *kaddr; + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto fail; + + gfs_trans_add_bh(ip->i_gl, dibh); + + kaddr = kmap(page); + memcpy(dibh->b_data + sizeof(struct gfs_dinode) + from, + (char *)kaddr + from, + to - from); + kunmap(page); + + brelse(dibh); + + SetPageUptodate(page); + + if (inode->i_size < file_size) + i_size_write(inode, file_size); + } else { + loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + error = block_commit_write(page, from, to); + if (error) + goto fail; + if (pos > inode->i_size) { + i_size_write(inode, pos); + mark_inode_dirty(inode); + } + } + + ip->gfs_file_aops.commit_write = NULL; + return 0; + + fail: + ClearPageUptodate(page); + + return error; +} + +/** + * gfs_bmap - Block map function + * @mapping: Address space info + * @lblock: The block to map + * + * Returns: The disk address for the block or 0 on hole or error + */ + +static sector_t +gfs_bmap(struct address_space *mapping, sector_t lblock) +{ + struct gfs_inode *ip = get_v2ip(mapping->host); + struct gfs_holder i_gh; + int dblock = 0; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_address); + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + if (error) + return 0; + + if (!gfs_is_stuffed(ip)) + dblock = generic_block_bmap(mapping, lblock, get_block); + + gfs_glock_dq_uninit(&i_gh); + + return dblock; +} + +/** + * gfs_direct_IO - + * @rw: + * @iocb: + * @iov: + * @offset: + * @nr_segs: + * + * Returns: errno + */ + +static ssize_t +gfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, + loff_t offset, unsigned long nr_segs) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_sbd *sdp = ip->i_sbd; + get_block_t *gb = get_blocks; + + atomic_inc(&sdp->sd_ops_address); + + if (gfs_assert_warn(sdp, gfs_glock_is_locked_by_me(ip->i_gl)) || + gfs_assert_warn(sdp, !gfs_is_stuffed(ip))) + return -EINVAL; + + if (rw == WRITE && !get_transaction) + gb = get_blocks_noalloc; + + if (rw == WRITE) + return blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, gb, NULL); + else + return blockdev_direct_IO_no_locking(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, gb, NULL); + +} + +struct address_space_operations gfs_file_aops = { + .writepage = gfs_writepage, + .readpage = gfs_readpage, + .sync_page = block_sync_page, + .prepare_write = gfs_prepare_write, + .bmap = gfs_bmap, + .direct_IO = gfs_direct_IO, +}; --- linux-2.6.27.orig/ubuntu/gfs/page.c +++ linux-2.6.27/ubuntu/gfs/page.c @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bmap.h" +#include "inode.h" +#include "page.h" + +/** + * gfs_inval_pte - Sync and invalidate all PTEs associated with a glock + * @gl: the glock + * + */ + +void +gfs_inval_pte(struct gfs_glock *gl) +{ + struct gfs_inode *ip; + struct inode *inode; + + ip = get_gl2ip(gl); + if (!ip || + ip->i_di.di_type != GFS_FILE_REG) + return; + + if (!test_bit(GIF_PAGED, &ip->i_flags)) + return; + + inode = gfs_iget(ip, NO_CREATE); + if (inode) { + unmap_shared_mapping_range(inode->i_mapping, 0, 0); + iput(inode); + + if (test_bit(GIF_SW_PAGED, &ip->i_flags)) + set_bit(GLF_DIRTY, &gl->gl_flags); + } + + clear_bit(GIF_SW_PAGED, &ip->i_flags); +} + +/** + * gfs_inval_page - Invalidate all pages associated with a glock + * @gl: the glock + * + */ + +void +gfs_inval_page(struct gfs_glock *gl) +{ + struct gfs_inode *ip; + struct inode *inode; + + ip = get_gl2ip(gl); + if (!ip || + ip->i_di.di_type != GFS_FILE_REG) + return; + + inode = gfs_iget(ip, NO_CREATE); + if (inode) { + struct address_space *mapping = inode->i_mapping; + + truncate_inode_pages(mapping, 0); + gfs_assert_withdraw(ip->i_sbd, !mapping->nrpages); + + iput(inode); + } + + clear_bit(GIF_PAGED, &ip->i_flags); +} + +/** + * gfs_sync_page_i - Sync the data pages (not metadata) for a struct inode + * @inode: the inode + * @flags: DIO_START | DIO_WAIT + * + */ + +void +gfs_sync_page_i(struct inode *inode, int flags) +{ + struct address_space *mapping = inode->i_mapping; + int error = 0; + + if (flags & DIO_START) + error = filemap_fdatawrite(mapping); + if (!error && (flags & DIO_WAIT)) + error = filemap_fdatawait(mapping); + + /* Find a better way to report this to the user. */ + if (error) + gfs_io_error_inode(get_v2ip(inode)); +} + +/** + * gfs_sync_page - Sync the data pages (not metadata) associated with a glock + * @gl: the glock + * @flags: DIO_START | DIO_WAIT + * + * Syncs data (not metadata) for a regular file. + * No-op for all other types. + */ + +void +gfs_sync_page(struct gfs_glock *gl, int flags) +{ + struct gfs_inode *ip; + struct inode *inode; + + ip = get_gl2ip(gl); + if (!ip || + ip->i_di.di_type != GFS_FILE_REG) + return; + + inode = gfs_iget(ip, NO_CREATE); + if (inode) { + gfs_sync_page_i(inode, flags); + iput(inode); + } +} + +/** + * gfs_unstuffer_page - unstuff a stuffed inode into a block cached by a page + * @ip: the inode + * @dibh: the dinode buffer + * @block: the block number that was allocated + * @private: any locked page held by the caller process + * + * Returns: errno + */ + +int +gfs_unstuffer_page(struct gfs_inode *ip, struct buffer_head *dibh, + uint64_t block, void *private) +{ + struct inode *inode = ip->i_vnode; + struct page *page = (struct page *)private; + struct buffer_head *bh; + int release = FALSE; + + if (!page || page->index) { + page = grab_cache_page(inode->i_mapping, 0); + if (!page) + return -ENOMEM; + release = TRUE; + } + + if (!PageUptodate(page)) { + void *kaddr = kmap(page); + + memcpy(kaddr, + dibh->b_data + sizeof(struct gfs_dinode), + ip->i_di.di_size); + memset(kaddr + ip->i_di.di_size, + 0, + PAGE_CACHE_SIZE - ip->i_di.di_size); + kunmap(page); + + SetPageUptodate(page); + } + + if (!page_has_buffers(page)) + create_empty_buffers(page, 1 << inode->i_blkbits, + (1 << BH_Uptodate)); + + bh = page_buffers(page); + + if (!buffer_mapped(bh)) + map_bh(bh, inode->i_sb, block); + else if (gfs_assert_warn(ip->i_sbd, + bh->b_bdev == inode->i_sb->s_bdev && + bh->b_blocknr == block)) + map_bh(bh, inode->i_sb, block); + + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + + if (release) { + unlock_page(page); + page_cache_release(page); + } + + return 0; +} + +/** + * gfs_truncator_page - truncate a partial data block in the page cache + * @ip: the inode + * @size: the size the file should be + * + * Returns: errno + */ + +int +gfs_truncator_page(struct gfs_inode *ip, uint64_t size) +{ + struct inode *inode = ip->i_vnode; + struct page *page; + struct buffer_head *bh; + void *kaddr; + uint64_t lbn, dbn; + unsigned long index; + unsigned int offset; + unsigned int bufnum; + int not_new = 0; + int error; + + lbn = size >> inode->i_blkbits; + error = gfs_block_map(ip, + lbn, ¬_new, + &dbn, NULL); + if (error || !dbn) + return error; + + index = size >> PAGE_CACHE_SHIFT; + offset = size & (PAGE_CACHE_SIZE - 1); + bufnum = lbn - (index << (PAGE_CACHE_SHIFT - inode->i_blkbits)); + + /* Not in a transaction here -- a non-disk-I/O error is ok. */ + + page = read_cache_page(inode->i_mapping, index, + (filler_t *)inode->i_mapping->a_ops->readpage, + NULL); + if (IS_ERR(page)) + return PTR_ERR(page); + + lock_page(page); + + if (!PageUptodate(page) || PageError(page)) { + error = -EIO; + goto out; + } + + kaddr = kmap(page); + memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); + kunmap(page); + + if (!page_has_buffers(page)) + create_empty_buffers(page, 1 << inode->i_blkbits, + (1 << BH_Uptodate)); + + for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page) + /* Do nothing */; + + if (!buffer_mapped(bh)) + map_bh(bh, inode->i_sb, dbn); + else if (gfs_assert_warn(ip->i_sbd, + bh->b_bdev == inode->i_sb->s_bdev && + bh->b_blocknr == dbn)) + map_bh(bh, inode->i_sb, dbn); + + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + + out: + unlock_page(page); + page_cache_release(page); + + return error; +} --- linux-2.6.27.orig/ubuntu/gfs/lock_dlm_mount.c +++ linux-2.6.27/ubuntu/gfs/lock_dlm_mount.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include "lock_dlm.h" + +const struct lm_lockops gdlm_ops; + + +static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs_sbd *sdp, + int flags, char *table_name) +{ + struct gdlm_ls *ls; + char buf[256], *p; + + ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL); + if (!ls) + return NULL; + + ls->drop_locks_count = GDLM_DROP_COUNT; + ls->drop_locks_period = GDLM_DROP_PERIOD; + ls->fscb = cb; + ls->sdp = sdp; + ls->fsflags = flags; + spin_lock_init(&ls->async_lock); + INIT_LIST_HEAD(&ls->complete); + INIT_LIST_HEAD(&ls->blocking); + INIT_LIST_HEAD(&ls->delayed); + INIT_LIST_HEAD(&ls->submit); + INIT_LIST_HEAD(&ls->all_locks); + init_waitqueue_head(&ls->thread_wait); + init_waitqueue_head(&ls->wait_control); + ls->thread1 = NULL; + ls->thread2 = NULL; + ls->drop_time = jiffies; + ls->jid = -1; + + strncpy(buf, table_name, 256); + buf[255] = '\0'; + + p = strchr(buf, ':'); + if (!p) { + log_info("invalid table_name \"%s\"", table_name); + kfree(ls); + return NULL; + } + *p = '\0'; + p++; + + strncpy(ls->clustername, buf, GDLM_NAME_LEN); + strncpy(ls->fsname, p, GDLM_NAME_LEN); + + return ls; +} + +static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir) +{ + char data[256]; + char *options, *x, *y; + int error = 0; + + memset(data, 0, 256); + strncpy(data, data_arg, 255); + + if (!strlen(data)) { + log_error("no mount options, (u)mount helpers not installed"); + return -EINVAL; + } + + for (options = data; (x = strsep(&options, ":")); ) { + if (!*x) + continue; + + y = strchr(x, '='); + if (y) + *y++ = 0; + + if (!strcmp(x, "jid")) { + if (!y) { + log_error("need argument to jid"); + error = -EINVAL; + break; + } + sscanf(y, "%u", &ls->jid); + + } else if (!strcmp(x, "first")) { + if (!y) { + log_error("need argument to first"); + error = -EINVAL; + break; + } + sscanf(y, "%u", &ls->first); + + } else if (!strcmp(x, "id")) { + if (!y) { + log_error("need argument to id"); + error = -EINVAL; + break; + } + sscanf(y, "%u", &ls->id); + + } else if (!strcmp(x, "nodir")) { + if (!y) { + log_error("need argument to nodir"); + error = -EINVAL; + break; + } + sscanf(y, "%u", nodir); + + } else { + log_error("unkonwn option: %s", x); + error = -EINVAL; + break; + } + } + + return error; +} + +static int gdlm_mount(char *table_name, char *host_data, + lm_callback_t cb, void *cb_data, + unsigned int min_lvb_size, int flags, + struct lm_lockstruct *lockstruct, + struct kobject *fskobj) +{ + struct gdlm_ls *ls; + int error = -ENOMEM, nodir = 0; + + if (min_lvb_size > GDLM_LVB_SIZE) + goto out; + + ls = init_gdlm(cb, cb_data, flags, table_name); + if (!ls) + goto out; + + error = make_args(ls, host_data, &nodir); + if (error) + goto out; + + error = gdlm_init_threads(ls); + if (error) + goto out_free; + + error = gdlm_kobject_setup(ls, fskobj); + if (error) + goto out_thread; + + error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), + &ls->dlm_lockspace, + DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0), + GDLM_LVB_SIZE); + if (error) { + log_error("dlm_new_lockspace error %d", error); + goto out_kobj; + } + + lockstruct->ls_jid = ls->jid; + lockstruct->ls_first = ls->first; + lockstruct->ls_lockspace = ls; + lockstruct->ls_ops = &gdlm_ops; + lockstruct->ls_flags = 0; + lockstruct->ls_lvb_size = GDLM_LVB_SIZE; + return 0; + +out_kobj: + gdlm_kobject_release(ls); +out_thread: + gdlm_release_threads(ls); +out_free: + kfree(ls); +out: + return error; +} + +static void gdlm_unmount(void *lockspace) +{ + struct gdlm_ls *ls = lockspace; + int rv; + + log_debug("unmount flags %lx", ls->flags); + + /* FIXME: serialize unmount and withdraw in case they + happen at once. Also, if unmount follows withdraw, + wait for withdraw to finish. */ + + if (test_bit(DFL_WITHDRAW, &ls->flags)) + goto out; + + gdlm_kobject_release(ls); + dlm_release_lockspace(ls->dlm_lockspace, 2); + gdlm_release_threads(ls); + rv = gdlm_release_all_locks(ls); + if (rv) + log_info("gdlm_unmount: %d stray locks freed", rv); +out: + kfree(ls); +} + +static void gdlm_recovery_done(void *lockspace, unsigned int jid, + unsigned int message) +{ + struct gdlm_ls *ls = lockspace; + ls->recover_jid_done = jid; + ls->recover_jid_status = message; + kobject_uevent(&ls->kobj, KOBJ_CHANGE); +} + +static void gdlm_others_may_mount(void *lockspace) +{ + struct gdlm_ls *ls = lockspace; + ls->first_done = 1; + kobject_uevent(&ls->kobj, KOBJ_CHANGE); +} + +/* Userspace gets the offline uevent, blocks new gfs locks on + other mounters, and lets us know (sets WITHDRAW flag). Then, + userspace leaves the mount group while we leave the lockspace. */ + +static void gdlm_withdraw(void *lockspace) +{ + struct gdlm_ls *ls = lockspace; + + kobject_uevent(&ls->kobj, KOBJ_OFFLINE); + + wait_event_interruptible(ls->wait_control, + test_bit(DFL_WITHDRAW, &ls->flags)); + + dlm_release_lockspace(ls->dlm_lockspace, 2); + gdlm_release_threads(ls); + gdlm_release_all_locks(ls); + gdlm_kobject_release(ls); +} + +static int gdlm_plock(void *lockspace, struct lm_lockname *name, + struct file *file, int cmd, struct file_lock *fl) +{ + struct gdlm_ls *ls = lockspace; + return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl); +} + +static int gdlm_punlock(void *lockspace, struct lm_lockname *name, + struct file *file, struct file_lock *fl) +{ + struct gdlm_ls *ls = lockspace; + return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl); +} + +static int gdlm_plock_get(void *lockspace, struct lm_lockname *name, + struct file *file, struct file_lock *fl) +{ + struct gdlm_ls *ls = lockspace; + return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl); +} + +const struct lm_lockops gdlm_ops = { + .lm_proto_name = "lock_dlm", + .lm_mount = gdlm_mount, + .lm_others_may_mount = gdlm_others_may_mount, + .lm_unmount = gdlm_unmount, + .lm_withdraw = gdlm_withdraw, + .lm_get_lock = gdlm_get_lock, + .lm_put_lock = gdlm_put_lock, + .lm_lock = gdlm_lock, + .lm_unlock = gdlm_unlock, + .lm_plock = gdlm_plock, + .lm_punlock = gdlm_punlock, + .lm_plock_get = gdlm_plock_get, + .lm_cancel = gdlm_cancel, + .lm_hold_lvb = gdlm_hold_lvb, + .lm_unhold_lvb = gdlm_unhold_lvb, + .lm_recovery_done = gdlm_recovery_done, + .lm_owner = THIS_MODULE, +}; + --- linux-2.6.27.orig/ubuntu/gfs/util.h +++ linux-2.6.27/ubuntu/gfs/util.h @@ -0,0 +1,330 @@ +#ifndef __UTIL_DOT_H__ +#define __UTIL_DOT_H__ + + +/* Utility functions */ + +extern uint32_t gfs_random_number; +uint32_t gfs_random(void); + +uint32_t gfs_hash(const void *data, unsigned int len); +uint32_t gfs_hash_more(const void *data, unsigned int len, uint32_t hash); + +void gfs_sort(void *base, unsigned int num_elem, unsigned int size, + int (*compar) (const void *, const void *)); + + +/* Error handling */ + +/** + * gfs_assert - Cause the machine to panic if @assertion is false + * @sdp: + * @assertion: + * @todo: + * + */ + +void gfs_assert_i(struct gfs_sbd *sdp, + char *assertion, + const char *function, + char *file, unsigned int line) +__attribute__ ((noreturn)); +#define gfs_assert(sdp, assertion, todo) \ +do { \ + if (unlikely(!(assertion))) { \ + {todo} \ + gfs_assert_i((sdp), #assertion, \ + __FUNCTION__, __FILE__, __LINE__); \ + } \ +} while (0) + +/** + * gfs_assert_withdraw - Cause the machine to withdraw if @assertion is false + * @sdp: + * @assertion: + * + * Returns: 0 if things are ok, + * -1 if this call withdrew the machine, + * -2 if it was already withdrawn + */ + +int gfs_assert_withdraw_i(struct gfs_sbd *sdp, + char *assertion, + const char *function, + char *file, unsigned int line); +#define gfs_assert_withdraw(sdp, assertion) \ +((likely(assertion)) ? 0 : \ + gfs_assert_withdraw_i((sdp), #assertion, \ + __FUNCTION__, __FILE__, __LINE__)) + +/** + * gfs_assert_warn - Print a message to the console if @assertion is false + * @sdp: + * @assertion: + * + * Returns: 0 if things are ok, + * -1 if we printed something + * -2 if we didn't + */ + +int gfs_assert_warn_i(struct gfs_sbd *sdp, + char *assertion, + const char *function, + char *file, unsigned int line); +#define gfs_assert_warn(sdp, assertion) \ +((likely(assertion)) ? 0 : \ + gfs_assert_warn_i((sdp), #assertion, \ + __FUNCTION__, __FILE__, __LINE__)) + +/** + * gfs_consist - Flag a filesystem consistency error and withdraw + * gfs_cconsist - Flag a filesystem consistency error and withdraw cluster + * @sdp: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int gfs_consist_i(struct gfs_sbd *sdp, int cluster_wide, + const char *function, + char *file, unsigned int line); +#define gfs_consist(sdp)\ +gfs_consist_i((sdp), FALSE, __FUNCTION__, __FILE__, __LINE__) +#define gfs_cconsist(sdp)\ +gfs_consist_i((sdp), TRUE, __FUNCTION__, __FILE__, __LINE__) + +/** + * gfs_consist_inode - Flag an inode consistency error and withdraw + * gfs_cconsist_inode - Flag an inode consistency error and withdraw cluster + * @ip: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int gfs_consist_inode_i(struct gfs_inode *ip, int cluster_wide, + const char *function, + char *file, unsigned int line); +#define gfs_consist_inode(ip) \ +gfs_consist_inode_i((ip), FALSE, __FUNCTION__, __FILE__, __LINE__) +#define gfs_cconsist_inode(ip) \ +gfs_consist_inode_i((ip), TRUE, __FUNCTION__, __FILE__, __LINE__) + +/** + * gfs_consist_rgrpd - Flag a RG consistency error and withdraw + * gfs_cconsist_rgrpd - Flag a RG consistency error and withdraw cluster + * @rgd: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int gfs_consist_rgrpd_i(struct gfs_rgrpd *rgd, int cluster_wide, + const char *function, + char *file, unsigned int line); +#define gfs_consist_rgrpd(rgd) \ +gfs_consist_rgrpd_i((rgd), FALSE, __FUNCTION__, __FILE__, __LINE__) +#define gfs_cconsist_rgrpd(rgd) \ +gfs_consist_rgrpd_i((rgd), TRUE, __FUNCTION__, __FILE__, __LINE__) + +/** + * gfs_meta_check - Flag a magic number consistency error and withdraw + * @sdp: + * @bh: + * + * Returns: 0 if things are ok, + * -1 if this call withdrew the machine, + * -2 if it was already withdrawn + */ + +int gfs_meta_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh, + const char *function, + char *file, unsigned int line); +static __inline__ int +gfs_meta_check_i(struct gfs_sbd *sdp, struct buffer_head *bh, + const char *function, + char *file, unsigned int line) +{ + uint32_t magic; + magic = ((struct gfs_meta_header *)(bh)->b_data)->mh_magic; + magic = gfs32_to_cpu(magic); + if (likely(magic == GFS_MAGIC)) + return 0; + return gfs_meta_check_ii(sdp, bh, function, file, line); +} +#define gfs_meta_check(sdp, bh) \ +gfs_meta_check_i((sdp), (bh), \ + __FUNCTION__, __FILE__, __LINE__) + +/** + * gfs_metatype_check - Flag a metadata type consistency error and withdraw + * @sdp: + * @bh: + * @type: + * + * Returns: 0 if things are ok, + * -1 if this call withdrew the machine, + * -2 if it was already withdrawn + */ + +int gfs_metatype_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh, + uint32_t type, uint32_t t, + const char *function, + char *file, unsigned int line); +static __inline__ int +gfs_metatype_check_i(struct gfs_sbd *sdp, struct buffer_head *bh, + uint32_t type, + const char *function, + char *file, unsigned int line) +{ + uint32_t magic, t; + magic = ((struct gfs_meta_header *)(bh)->b_data)->mh_magic; + magic = gfs32_to_cpu(magic); + if (unlikely(magic != GFS_MAGIC)) + return gfs_meta_check_ii(sdp, bh, function, file, line); + t = ((struct gfs_meta_header *)(bh)->b_data)->mh_type; + t = gfs32_to_cpu(t); + if (unlikely(t != type)) + return gfs_metatype_check_ii(sdp, bh, type, t, function, file, line); + return 0; +} +#define gfs_metatype_check(sdp, bh, type) \ +gfs_metatype_check_i((sdp), (bh), (type), \ + __FUNCTION__, __FILE__, __LINE__) + +/** + * gfs_metatype_check2 - Flag a metadata type consistency error and withdraw + * @sdp: + * @bh: + * @type1: + * @type2: + * + * Returns: 0 if things are ok, + * -1 if this call withdrew the machine, + * -2 if it was already withdrawn + */ + +static __inline__ int +gfs_metatype_check2_i(struct gfs_sbd *sdp, struct buffer_head *bh, + uint32_t type1, uint32_t type2, + const char *function, + char *file, unsigned int line) +{ + uint32_t magic, t; + magic = ((struct gfs_meta_header *)(bh)->b_data)->mh_magic; + magic = gfs32_to_cpu(magic); + if (unlikely(magic != GFS_MAGIC)) + return gfs_meta_check_ii(sdp, bh, function, file, line); + t = ((struct gfs_meta_header *)(bh)->b_data)->mh_type; + t = gfs32_to_cpu(t); + if (unlikely(t != type1 && t != type2)) + return gfs_metatype_check_ii(sdp, bh, type1, t, function, file, line); + return 0; +} +#define gfs_metatype_check2(sdp, bh, type1, type2) \ +gfs_metatype_check2_i((sdp), (bh), (type1), (type2), \ + __FUNCTION__, __FILE__, __LINE__) + +/** + * gfs_metatype_set - set the metadata type on a buffer + * @bh: + * @type: + * @format: + * + */ + +static __inline__ void +gfs_metatype_set(struct buffer_head *bh, uint32_t type, uint32_t format) +{ + struct gfs_meta_header *mh; + mh = (struct gfs_meta_header *)bh->b_data; + mh->mh_type = cpu_to_gfs32(type); + mh->mh_format = cpu_to_gfs32(format); +} + +/** + * gfs_io_error - Flag an I/O error and withdraw + * @sdp: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int gfs_io_error_i(struct gfs_sbd *sdp, + const char *function, + char *file, unsigned int line); +#define gfs_io_error(sdp) \ +gfs_io_error_i((sdp), __FUNCTION__, __FILE__, __LINE__); + +/** + * gfs_io_error_inode - Flag an inode I/O error and withdraw + * @ip: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int gfs_io_error_inode_i(struct gfs_inode *ip, + const char *function, + char *file, unsigned int line); +#define gfs_io_error_inode(ip) \ +gfs_io_error_inode_i((ip), __FUNCTION__, __FILE__, __LINE__); + +/** + * gfs_io_error_bh - Flag a buffer I/O error and withdraw + * @sdp: + * @bh: + * + * Returns: -1 if this call withdrew the machine, + * 0 if it was already withdrawn + */ + +int gfs_io_error_bh_i(struct gfs_sbd *sdp, struct buffer_head *bh, + const char *function, + char *file, unsigned int line); +#define gfs_io_error_bh(sdp, bh) \ +gfs_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__); + + +/* Memory stuff */ + +#define RETRY_MALLOC(do_this, until_this) \ +for (;;) { \ + { do_this; } \ + if (until_this) \ + break; \ + printk("GFS: out of memory: %s, %u\n", __FILE__, __LINE__); \ + dump_stack(); \ + yield(); \ +} + +extern struct kmem_cache *gfs_glock_cachep; +extern struct kmem_cache *gfs_inode_cachep; +extern struct kmem_cache *gfs_bufdata_cachep; +extern struct kmem_cache *gfs_mhc_cachep; + +void *gmalloc(unsigned int size); + + +struct gfs_user_buffer { + char *ub_data; + unsigned int ub_size; + unsigned int ub_count; +}; +int gfs_add_bh_to_ub(struct gfs_user_buffer *ub, struct buffer_head *bh); + + +static __inline__ unsigned int +gfs_tune_get_i(struct gfs_tune *gt, unsigned int *p) +{ + unsigned int x; + spin_lock(>->gt_spin); + x = *p; + spin_unlock(>->gt_spin); + return x; +} +#define gfs_tune_get(sdp, field) \ +gfs_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field) + + +#endif /* __UTIL_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/super.h +++ linux-2.6.27/ubuntu/gfs/super.h @@ -0,0 +1,53 @@ +#ifndef __SUPER_DOT_H__ +#define __SUPER_DOT_H__ + +void gfs_tune_init(struct gfs_tune *gt); + +int gfs_check_sb(struct gfs_sbd *sdp, struct gfs_sb *sb, int silent); +int gfs_read_sb(struct gfs_sbd *sdp, struct gfs_glock *gl, int silent); +int gfs_do_upgrade(struct gfs_sbd *sdp, struct gfs_glock *gl_sb); + +static __inline__ unsigned int +gfs_num_journals(struct gfs_sbd *sdp) +{ + unsigned int num; + down(&sdp->sd_jindex_lock); + num = sdp->sd_journals; + up(&sdp->sd_jindex_lock); + return num; +} + +int gfs_jindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ji_gh); +void gfs_clear_journals(struct gfs_sbd *sdp); + +int gfs_get_jiinode(struct gfs_sbd *sdp); +int gfs_get_riinode(struct gfs_sbd *sdp); +int gfs_get_rootinode(struct gfs_sbd *sdp); +int gfs_get_qinode(struct gfs_sbd *sdp); +int gfs_get_linode(struct gfs_sbd *sdp); + +int gfs_make_fs_rw(struct gfs_sbd *sdp); +int gfs_make_fs_ro(struct gfs_sbd *sdp); + +int gfs_statfs_init(struct gfs_sbd *sdp, int flag); +int gfs_statfs_sync(struct gfs_sbd *sdp); +int gfs_statfs_fast(struct gfs_sbd *sdp, void *buf); + +struct gfs_stat_gfs { + uint64_t sg_total_blocks; + uint64_t sg_free; + uint64_t sg_used_dinode; + uint64_t sg_free_dinode; + uint64_t sg_used_meta; + uint64_t sg_free_meta; +}; + +int gfs_stat_gfs(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg, + int interruptible); + +int gfs_lock_fs_check_clean(struct gfs_sbd *sdp, unsigned int state, + struct gfs_holder *t_gh); +int gfs_freeze_fs(struct gfs_sbd *sdp); +void gfs_unfreeze_fs(struct gfs_sbd *sdp); + +#endif /* __SUPER_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/ops_fstype.h +++ linux-2.6.27/ubuntu/gfs/ops_fstype.h @@ -0,0 +1,13 @@ +#ifndef __OPS_FSTYPE_DOT_H__ +#define __OPS_FSTYPE_DOT_H__ + +int gfs_sys_init(void); +void gfs_sys_uninit(void); +void gfs_sys_fs_del(struct gfs_sbd *sdp); +int gfs_test_bdev_super(struct super_block *sb, void *data); +int gfs_set_bdev_super(struct super_block *sb, void *data); +int init_names(struct gfs_sbd *sdp, int silent); + +extern struct file_system_type gfs_fs_type; + +#endif /* __OPS_FSTYPE_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/gfs.h +++ linux-2.6.27/ubuntu/gfs/gfs.h @@ -0,0 +1,89 @@ +#ifndef __GFS_DOT_H__ +#define __GFS_DOT_H__ + +#define RELEASE_VERSION "" + +#include "lm_interface.h" + +#include "gfs_ondisk.h" +#include "fixed_div64.h" +#include "lvb.h" +#include "incore.h" +#include "util.h" + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#define NO_CREATE (0) +#define CREATE (1) + +#if (BITS_PER_LONG == 64) +#define PRIu64 "lu" +#define PRId64 "ld" +#define PRIo64 "lo" +#define PRIx64 "lx" +#define PRIX64 "lX" +#define SCNu64 "lu" +#define SCNd64 "ld" +#define SCNo64 "lo" +#define SCNx64 "lx" +#define SCNX64 "lX" +#else +#define PRIu64 "Lu" +#define PRId64 "Ld" +#define PRIo64 "Lo" +#define PRIx64 "Lx" +#define PRIX64 "LX" +#define SCNu64 "Lu" +#define SCNd64 "Ld" +#define SCNo64 "Lo" +#define SCNx64 "Lx" +#define SCNX64 "LX" +#endif + +/* Divide num by den. Round up if there is a remainder. */ +#define DIV_RU(num, den) (((num) + (den) - 1) / (den)) +#define MAKE_MULT8(x) (((x) + 7) & ~7) + +#define GFS_FAST_NAME_SIZE (8) + +#define get_v2sdp(sb) ((struct gfs_sbd *)(sb)->s_fs_info) +#define set_v2sdp(sb, sdp) (sb)->s_fs_info = (sdp) +#define get_v2ip(inode) ((struct gfs_inode *)(inode)->i_private) +#define set_v2ip(inode, ip) (inode)->i_private = (ip) +#define get_v2fp(file) ((struct gfs_file *)(file)->private_data) +#define set_v2fp(file, fp) (file)->private_data = (fp) +#define get_v2bd(bh) ((struct gfs_bufdata *)(bh)->b_private) +#define set_v2bd(bh, bd) (bh)->b_private = (bd) + +#define get_transaction ((struct gfs_trans *)(current->journal_info)) +#define set_transaction(tr) (current->journal_info) = (tr) + +#define get_gl2ip(gl) ((struct gfs_inode *)(gl)->gl_object) +#define set_gl2ip(gl, ip) (gl)->gl_object = (ip) +#define get_gl2rgd(gl) ((struct gfs_rgrpd *)(gl)->gl_object) +#define set_gl2rgd(gl, rgd) (gl)->gl_object = (rgd) +#define get_gl2gl(gl) ((struct gfs_glock *)(gl)->gl_object) +#define set_gl2gl(gl, gl2) (gl)->gl_object = (gl2) + +#define gfs_printf(fmt, args...) \ +do { \ + if (buf) { \ + int gspf_left = size - *count, gspf_out; \ + if (gspf_left <= 0) \ + goto out; \ + gspf_out = snprintf(buf + *count, gspf_left, fmt, ##args); \ + if (gspf_out < gspf_left) \ + *count += gspf_out; \ + else \ + goto out; \ + } else \ + printk(fmt, ##args); \ +} while (0) + +#endif /* __GFS_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lvb.c +++ linux-2.6.27/ubuntu/gfs/lvb.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" + +#define pv(struct, member, fmt) printk(" "#member" = "fmt"\n", struct->member); + +#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));} +#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));} +#define CPIN_16(s1, s2, member) {(s1->member) = gfs16_to_cpu((s2->member));} +#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_gfs16((s1->member));} +#define CPIN_32(s1, s2, member) {(s1->member) = gfs32_to_cpu((s2->member));} +#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_gfs32((s1->member));} +#define CPIN_64(s1, s2, member) {(s1->member) = gfs64_to_cpu((s2->member));} +#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_gfs64((s1->member));} + +/** + * gfs_rgrp_lvb_in - Read in rgrp data + * @rb: the cpu-order structure + * @lvb: the lvb + * + */ + +void +gfs_rgrp_lvb_in(struct gfs_rgrp_lvb *rb, char *lvb) +{ + struct gfs_rgrp_lvb *str = (struct gfs_rgrp_lvb *)lvb; + + CPIN_32(rb, str, rb_magic); + CPIN_32(rb, str, rb_free); + CPIN_32(rb, str, rb_useddi); + CPIN_32(rb, str, rb_freedi); + CPIN_32(rb, str, rb_usedmeta); + CPIN_32(rb, str, rb_freemeta); +} + +/** + * gfs_rgrp_lvb_out - Write out rgrp data + * @rb: the cpu-order structure + * @lvb: the lvb + * + */ + +void +gfs_rgrp_lvb_out(struct gfs_rgrp_lvb *rb, char *lvb) +{ + struct gfs_rgrp_lvb *str = (struct gfs_rgrp_lvb *)lvb; + + CPOUT_32(rb, str, rb_magic); + CPOUT_32(rb, str, rb_free); + CPOUT_32(rb, str, rb_useddi); + CPOUT_32(rb, str, rb_freedi); + CPOUT_32(rb, str, rb_usedmeta); + CPOUT_32(rb, str, rb_freemeta); +} + +/** + * gfs_rgrp_lvb_print - Print out rgrp data + * @rb: the cpu-order structure + * @console - TRUE if this should be printed to the console, + * FALSE if it should be just printed to the incore debug + * buffer + */ + +void +gfs_rgrp_lvb_print(struct gfs_rgrp_lvb *rb) +{ + pv(rb, rb_magic, "%u"); + pv(rb, rb_free, "%u"); + pv(rb, rb_useddi, "%u"); + pv(rb, rb_freedi, "%u"); + pv(rb, rb_usedmeta, "%u"); + pv(rb, rb_freemeta, "%u"); +} + +/** + * gfs_quota_lvb_in - Read in quota data + * @rb: the cpu-order structure + * @lvb: the lvb + * + */ + +void +gfs_quota_lvb_in(struct gfs_quota_lvb *qb, char *lvb) +{ + struct gfs_quota_lvb *str = (struct gfs_quota_lvb *)lvb; + + CPIN_32(qb, str, qb_magic); + CPIN_32(qb, str, qb_pad); + CPIN_64(qb, str, qb_limit); + CPIN_64(qb, str, qb_warn); + CPIN_64(qb, str, qb_value); +} + +/** + * gfs_quota_lvb_out - Write out quota data + * @rb: the cpu-order structure + * @lvb: the lvb + * + */ + +void +gfs_quota_lvb_out(struct gfs_quota_lvb *qb, char *lvb) +{ + struct gfs_quota_lvb *str = (struct gfs_quota_lvb *)lvb; + + CPOUT_32(qb, str, qb_magic); + CPOUT_32(qb, str, qb_pad); + CPOUT_64(qb, str, qb_limit); + CPOUT_64(qb, str, qb_warn); + CPOUT_64(qb, str, qb_value); +} + +/** + * gfs_quota_lvb_print - Print out quota data + * @rb: the cpu-order structure + * @console - TRUE if this should be printed to the console, + * FALSE if it should be just printed to the incore debug + * buffer + */ + +void +gfs_quota_lvb_print(struct gfs_quota_lvb *qb) +{ + pv(qb, qb_magic, "%u"); + pv(qb, qb_pad, "%u"); + pv(qb, qb_limit, "%"PRIu64); + pv(qb, qb_warn, "%"PRIu64); + pv(qb, qb_value, "%"PRId64); +} --- linux-2.6.27.orig/ubuntu/gfs/rgrp.h +++ linux-2.6.27/ubuntu/gfs/rgrp.h @@ -0,0 +1,75 @@ +#ifndef __RGRP_DOT_H__ +#define __RGRP_DOT_H__ + +void gfs_mhc_add(struct gfs_rgrpd *rgd, struct buffer_head **bh, + unsigned int num); +int gfs_mhc_fish(struct gfs_sbd *sdp, struct buffer_head *bh); +void gfs_mhc_zap(struct gfs_rgrpd *rgd); + +void gfs_depend_add(struct gfs_rgrpd *rgd, uint64_t formal_ino); +void gfs_depend_sync(struct gfs_rgrpd *rgd); + +struct gfs_rgrpd *gfs_blk2rgrpd(struct gfs_sbd *sdp, uint64_t blk); +struct gfs_rgrpd *gfs_rgrpd_get_first(struct gfs_sbd *sdp); +struct gfs_rgrpd *gfs_rgrpd_get_next(struct gfs_rgrpd *rgd); + +void gfs_clear_rgrpd(struct gfs_sbd *sdp); + +int gfs_rindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ri_gh); + +int gfs_rgrp_read(struct gfs_rgrpd *rgd); +void gfs_rgrp_relse(struct gfs_rgrpd *rgd); + +void gfs_rgrp_lvb_fill(struct gfs_rgrpd *rgd); +int gfs_rgrp_lvb_init(struct gfs_rgrpd *rgd); + +struct gfs_alloc *gfs_alloc_get(struct gfs_inode *ip); +void gfs_alloc_put(struct gfs_inode *ip); + +int gfs_inplace_reserve_i(struct gfs_inode *ip, + char *file, unsigned int line); +#define gfs_inplace_reserve(ip) \ +gfs_inplace_reserve_i((ip), __FILE__, __LINE__) + +void gfs_inplace_release(struct gfs_inode *ip); + +unsigned char gfs_get_block_type(struct gfs_rgrpd *rgd, uint64_t block); + +void gfs_blkalloc(struct gfs_inode *ip, uint64_t *block); +int gfs_metaalloc(struct gfs_inode *ip, uint64_t *block); +int gfs_dialloc(struct gfs_inode *dip, uint64_t *block); + +void gfs_blkfree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen); +void gfs_metafree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen); +void gfs_difree_uninit(struct gfs_rgrpd *rgd, uint64_t addr); +void gfs_difree(struct gfs_rgrpd *rgd, struct gfs_inode *ip); + +extern void gfs_statfs_modify(struct gfs_sbd *sdp, + int64_t total, + int64_t free, + int64_t dinodes); + +/* + * gfs_rgrp_list + * + * Used to collect a list of all resource groups spanned by a given + * inode/file/directory + */ +struct gfs_rgrp_list { + unsigned int rl_rgrps; /* # (qty) of rgrps in list (array) */ + unsigned int rl_space; /* Current capacity in list for rgrps */ + struct gfs_rgrpd **rl_rgd; /* Array of ptrs to rgrp descriptors */ + struct gfs_holder *rl_ghs; /* Array of glock holders for rgrps */ +}; + +void gfs_rlist_add(struct gfs_sbd *sdp, struct gfs_rgrp_list *rlist, + uint64_t block); +void gfs_rlist_alloc(struct gfs_rgrp_list *rlist, unsigned int state, + int flags); +void gfs_rlist_free(struct gfs_rgrp_list *rlist); + +int gfs_reclaim_metadata(struct gfs_sbd *sdp, + uint64_t *inodes, + uint64_t *metadata); + +#endif /* __RGRP_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/ops_address.h +++ linux-2.6.27/ubuntu/gfs/ops_address.h @@ -0,0 +1,6 @@ +#ifndef __OPS_ADDRESS_DOT_H__ +#define __OPS_ADDRESS_DOT_H__ + +extern struct address_space_operations gfs_file_aops; + +#endif /* __OPS_ADDRESS_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/rgrp.c +++ linux-2.6.27/ubuntu/gfs/rgrp.c @@ -0,0 +1,2152 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bits.h" +#include "dio.h" +#include "file.h" +#include "glock.h" +#include "glops.h" +#include "rgrp.h" +#include "super.h" +#include "trans.h" + +/** + * mhc_hash: find the mhc hash bucket for a buffer + * @bh: the buffer + * + * Returns: The bucket number + */ + +static unsigned int +mhc_hash(struct buffer_head *bh) +{ + uint64_t blkno; + unsigned int h; + + blkno = bh->b_blocknr; + h = gfs_hash(&blkno, sizeof(uint64_t)) & GFS_MHC_HASH_MASK; + + return h; +} + +/** + * mhc_trim - Throw away cached meta-headers, if there are too many of them + * @sdp: The filesystem instance + * @max: Max # of cached meta-headers allowed to survive + * + * Walk filesystem's list of cached meta-headers, in least-recently-used order, + * and keep throwing them away until we're under the max threshold. + */ + +static void +mhc_trim(struct gfs_sbd *sdp, unsigned int max) +{ + struct gfs_meta_header_cache *mc; + + for (;;) { + spin_lock(&sdp->sd_mhc_lock); + if (list_empty(&sdp->sd_mhc_single)) { + spin_unlock(&sdp->sd_mhc_lock); + return; + } else { + mc = list_entry(sdp->sd_mhc_single.prev, + struct gfs_meta_header_cache, + mc_list_single); + list_del(&mc->mc_list_hash); + list_del(&mc->mc_list_single); + list_del(&mc->mc_list_rgd); + spin_unlock(&sdp->sd_mhc_lock); + + kmem_cache_free(gfs_mhc_cachep, mc); + atomic_dec(&sdp->sd_mhc_count); + + if (atomic_read(&sdp->sd_mhc_count) <= max) + return; + } + } +} + +/** + * gfs_mhc_add - add buffer(s) to the cache of metadata headers + * @rgd: Resource Group in which the buffered block(s) reside + * @bh: an array of buffer_head pointers + * @num: the number of bh pointers in the array + * + * Increment each meta-header's generation # by 2. + * Alloc and add each gfs_meta-header_cache to 3 lists/caches: + * Filesystem's meta-header cache (hash) + * Filesystem's list of cached meta-headers + * Resource Group's list of cached meta-headers + * If we now have too many cached, throw some older ones away + */ + +void +gfs_mhc_add(struct gfs_rgrpd *rgd, + struct buffer_head **bh, unsigned int num) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + unsigned int x; + + for (x = 0; x < num; x++) { + struct gfs_meta_header_cache *mc; + struct list_head *head; + uint64_t gen; + + if (gfs_meta_check(sdp, bh[x])) + return; + + mc = kmem_cache_alloc(gfs_mhc_cachep, GFP_KERNEL); + if (!mc) + return; + memset(mc, 0, sizeof(struct gfs_meta_header_cache)); + + mc->mc_block = bh[x]->b_blocknr; + memcpy(&mc->mc_mh, bh[x]->b_data, + sizeof(struct gfs_meta_header)); + + gen = gfs64_to_cpu(mc->mc_mh.mh_generation) + 2; + mc->mc_mh.mh_generation = cpu_to_gfs64(gen); + + head = &sdp->sd_mhc[mhc_hash(bh[x])]; + + spin_lock(&sdp->sd_mhc_lock); + list_add(&mc->mc_list_hash, head); + list_add(&mc->mc_list_single, &sdp->sd_mhc_single); + list_add(&mc->mc_list_rgd, &rgd->rd_mhc); + spin_unlock(&sdp->sd_mhc_lock); + + atomic_inc(&sdp->sd_mhc_count); + } + + x = gfs_tune_get(sdp, gt_max_mhc); + + /* If we've got too many cached, throw some older ones away */ + if (atomic_read(&sdp->sd_mhc_count) > x) + mhc_trim(sdp, x); +} + +/** + * gfs_mhc_fish - Try to fill in a meta buffer with meta-header from the cache + * @sdp: the filesystem + * @bh: the buffer to fill in + * + * Returns: TRUE if the buffer was cached, FALSE otherwise + * + * If buffer is referenced in meta-header cache (search using hash): + * Copy the cached meta-header into the buffer (instead of reading from disk). + * Note that only the meta-header portion of the buffer will have valid data + * (as would be on disk), rest of buffer does *not* reflect disk contents. + * Remove cached gfs_meta_header_cache from all cache lists, free its memory. + */ + +int +gfs_mhc_fish(struct gfs_sbd *sdp, struct buffer_head *bh) +{ + struct list_head *tmp, *head; + struct gfs_meta_header_cache *mc; + + head = &sdp->sd_mhc[mhc_hash(bh)]; + + spin_lock(&sdp->sd_mhc_lock); + + for (tmp = head->next; + tmp != head; + tmp = tmp->next) { + mc = list_entry(tmp, struct gfs_meta_header_cache, mc_list_hash); + if (mc->mc_block != bh->b_blocknr) + continue; + + list_del(&mc->mc_list_hash); + list_del(&mc->mc_list_single); + list_del(&mc->mc_list_rgd); + spin_unlock(&sdp->sd_mhc_lock); + + gfs_prep_new_buffer(bh); + memcpy(bh->b_data, &mc->mc_mh, + sizeof(struct gfs_meta_header)); + + kmem_cache_free(gfs_mhc_cachep, mc); + atomic_dec(&sdp->sd_mhc_count); + + return TRUE; + } + + spin_unlock(&sdp->sd_mhc_lock); + + return FALSE; +} + +/** + * gfs_mhc_zap - Throw away an RG's list of cached metadata headers + * @rgd: The resource group whose list we want to clear + * + * Simply throw away all cached metadata headers on RG's list, + * and free their memory. + */ + +void +gfs_mhc_zap(struct gfs_rgrpd *rgd) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct gfs_meta_header_cache *mc; + + spin_lock(&sdp->sd_mhc_lock); + + while (!list_empty(&rgd->rd_mhc)) { + mc = list_entry(rgd->rd_mhc.next, + struct gfs_meta_header_cache, + mc_list_rgd); + + list_del(&mc->mc_list_hash); + list_del(&mc->mc_list_single); + list_del(&mc->mc_list_rgd); + spin_unlock(&sdp->sd_mhc_lock); + + kmem_cache_free(gfs_mhc_cachep, mc); + atomic_dec(&sdp->sd_mhc_count); + + spin_lock(&sdp->sd_mhc_lock); + } + + spin_unlock(&sdp->sd_mhc_lock); +} + +/** + * depend_hash() - Turn glock number into hash bucket number + * @formal_ino: + * + * Returns: The number of the corresponding hash bucket + */ + +static unsigned int +depend_hash(uint64_t formal_ino) +{ + unsigned int h; + + h = gfs_hash(&formal_ino, sizeof(uint64_t)); + h &= GFS_DEPEND_HASH_MASK; + + return h; +} + +/** + * depend_sync_one - Sync metadata (not data) for a dependency inode + * @sdp: filesystem instance + * @gd: dependency descriptor + * + * Remove dependency from superblock's hash table and rgrp's list. + * Sync dependency inode's metadata to log and in-place location. + */ + +static void +depend_sync_one(struct gfs_sbd *sdp, struct gfs_depend *gd) +{ + struct gfs_glock *gl; + + spin_lock(&sdp->sd_depend_lock); + list_del(&gd->gd_list_hash); + spin_unlock(&sdp->sd_depend_lock); + list_del(&gd->gd_list_rgd); + + gl = gfs_glock_find(sdp, + &(struct lm_lockname){gd->gd_formal_ino, + LM_TYPE_INODE}); + if (gl) { + if (gl->gl_ops->go_sync) + gl->gl_ops->go_sync(gl, + DIO_METADATA | + DIO_INVISIBLE); + gfs_glock_put(gl); + } + + kfree(gd); + atomic_dec(&sdp->sd_depend_count); +} + +/** + * depend_sync_old - Sync older rgrp-dependent inodes to disk. + * @rgd: Resource group containing dependent inodes + * + * Look at oldest entries in resource group's dependency list, + * sync 'em if they're older than timeout threshold. + */ + +static void +depend_sync_old(struct gfs_rgrpd *rgd) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct gfs_depend *gd; + + while (!list_empty(&rgd->rd_depend)) { + /* Oldest entries are in prev direction */ + gd = list_entry(rgd->rd_depend.prev, + struct gfs_depend, + gd_list_rgd); + + if (time_before(jiffies, + gd->gd_time + + gfs_tune_get(sdp, gt_depend_secs) * HZ)) + return; + + depend_sync_one(sdp, gd); + } +} + +/** + * gfs_depend_add - Add a dependent inode to rgrp's and filesystem's list + * @rgd: Resource group containing blocks associated with inode + * @formal_ino: inode + * + * Dependent inodes must be flushed to log and in-place blocks before + * releasing an EXCLUSIVE rgrp lock. + * Find pre-existing dependency for this inode/rgrp combination in + * incore superblock struct's sd_depend hash table, or create a new one. + * Either way, move or attach dependency to head of superblock's hash bucket + * and top of rgrp's list. + * If we create a new one, take a moment to sync older dependencies to disk. + */ + +void +gfs_depend_add(struct gfs_rgrpd *rgd, uint64_t formal_ino) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct list_head *head, *tmp; + struct gfs_depend *gd; + + head = &sdp->sd_depend[depend_hash(formal_ino)]; + + spin_lock(&sdp->sd_depend_lock); + + for (tmp = head->next; + tmp != head; + tmp = tmp->next) { + gd = list_entry(tmp, struct gfs_depend, gd_list_hash); + if (gd->gd_rgd == rgd && + gd->gd_formal_ino == formal_ino) { + list_move(&gd->gd_list_hash, head); + spin_unlock(&sdp->sd_depend_lock); + list_move(&gd->gd_list_rgd, &rgd->rd_depend); + gd->gd_time = jiffies; + return; + } + } + + spin_unlock(&sdp->sd_depend_lock); + + gd = gmalloc(sizeof(struct gfs_depend)); + memset(gd, 0, sizeof(struct gfs_depend)); + + gd->gd_rgd = rgd; + gd->gd_formal_ino = formal_ino; + gd->gd_time = jiffies; + + spin_lock(&sdp->sd_depend_lock); + list_add(&gd->gd_list_hash, head); + spin_unlock(&sdp->sd_depend_lock); + list_add(&gd->gd_list_rgd, &rgd->rd_depend); + + atomic_inc(&sdp->sd_depend_count); + + depend_sync_old(rgd); +} + +/** + * gfs_depend_sync - Sync metadata (not data) for an rgrp's dependent inodes + * @rgd: Resource group containing the dependent inodes + * + * As long as this node owns an EXCLUSIVE lock on the rgrp, we can keep + * rgrp's modified metadata blocks in buffer cache. + * + * When this node releases the EX lock, we must flush metadata, so other + * nodes can read the modified content from disk. + */ + +void +gfs_depend_sync(struct gfs_rgrpd *rgd) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct gfs_depend *gd; + + while (!list_empty(&rgd->rd_depend)) { + gd = list_entry(rgd->rd_depend.next, + struct gfs_depend, + gd_list_rgd); + depend_sync_one(sdp, gd); + } +} + +/** + * rgrp_verify - Verify that a resource group is consistent + * @sdp: the filesystem + * @rgd: the rgrp + * + * Somebody should have already called gfs_glock_rg() on this RG. + */ + +static void +rgrp_verify(struct gfs_rgrpd *rgd) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct gfs_bitmap *bits = NULL; + uint32_t length = rgd->rd_ri.ri_length; + uint32_t count[4], tmp; + int buf, x; + + memset(count, 0, 4 * sizeof(uint32_t)); + + /* Count # blocks in each of 4 possible allocation states */ + for (buf = 0; buf < length; buf++) { + bits = &rgd->rd_bits[buf]; + for (x = 0; x < 4; x++) + count[x] += gfs_bitcount(rgd, + rgd->rd_bh[buf]->b_data + + bits->bi_offset, + bits->bi_len, x); + } + + if (count[0] != rgd->rd_rg.rg_free) { + if (gfs_consist_rgrpd(rgd)) + printk("GFS: fsid=%s: free data mismatch: %u != %u\n", + sdp->sd_fsname, count[0], rgd->rd_rg.rg_free); + return; + } + + tmp = rgd->rd_ri.ri_data - + (rgd->rd_rg.rg_usedmeta + rgd->rd_rg.rg_freemeta) - + (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi) - + rgd->rd_rg.rg_free; + if (count[1] != tmp) { + if (gfs_consist_rgrpd(rgd)) + printk("GFS: fsid=%s: used data mismatch: %u != %u\n", + sdp->sd_fsname, count[1], tmp); + return; + } + + if (count[2] != rgd->rd_rg.rg_freemeta) { + if (gfs_consist_rgrpd(rgd)) + printk("GFS: fsid=%s: free metadata mismatch: %u != %u\n", + sdp->sd_fsname, count[2], rgd->rd_rg.rg_freemeta); + return; + } + + tmp = rgd->rd_rg.rg_usedmeta + + (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi); + if (count[3] != tmp) { + if (gfs_consist_rgrpd(rgd)) + printk("GFS: fsid=%s: used metadata mismatch: %u != %u\n", + sdp->sd_fsname, count[3], tmp); + return; + } +} + +/** + * gfs_blk2rgrpd - Find resource group for a given data/meta block number + * @sdp: The GFS superblock + * @n: The data block number + * + * Returns: The resource group, or NULL if not found + * + * Don't try to use this for non-allocatable block numbers (i.e. rgrp header + * or bitmap blocks); it's for allocatable (data/meta) blocks only. + */ + +struct gfs_rgrpd * +gfs_blk2rgrpd(struct gfs_sbd *sdp, uint64_t blk) +{ + struct list_head *tmp, *head; + struct gfs_rgrpd *rgd = NULL; + struct gfs_rindex *ri; + + spin_lock(&sdp->sd_rg_mru_lock); + + for (head = &sdp->sd_rg_mru_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + rgd = list_entry(tmp, struct gfs_rgrpd, rd_list_mru); + ri = &rgd->rd_ri; + + if (ri->ri_data1 <= blk && blk < ri->ri_data1 + ri->ri_data) { + list_move(&rgd->rd_list_mru, &sdp->sd_rg_mru_list); + spin_unlock(&sdp->sd_rg_mru_lock); + return rgd; + } + } + + spin_unlock(&sdp->sd_rg_mru_lock); + + return NULL; +} + +/** + * gfs_rgrpd_get_first - get the first Resource Group in the filesystem + * @sdp: The GFS superblock + * + * Returns: The first rgrp in the filesystem + */ + +struct gfs_rgrpd * +gfs_rgrpd_get_first(struct gfs_sbd *sdp) +{ + gfs_assert(sdp, !list_empty(&sdp->sd_rglist),); + return list_entry(sdp->sd_rglist.next, struct gfs_rgrpd, rd_list); +} + +/** + * gfs_rgrpd_get_next - get the next RG + * @rgd: A RG + * + * Returns: The next rgrp + */ + +struct gfs_rgrpd * +gfs_rgrpd_get_next(struct gfs_rgrpd *rgd) +{ + if (rgd->rd_list.next == &rgd->rd_sbd->sd_rglist) + return NULL; + return list_entry(rgd->rd_list.next, struct gfs_rgrpd, rd_list); +} + +/** + * clear_rgrpdi - Clear up rgrps + * @sdp: The GFS superblock + * + */ + +void +clear_rgrpdi(struct gfs_sbd *sdp) +{ + struct gfs_rgrpd *rgd; + struct gfs_glock *gl; + + spin_lock(&sdp->sd_rg_forward_lock); + sdp->sd_rg_forward = NULL; + spin_unlock(&sdp->sd_rg_forward_lock); + + spin_lock(&sdp->sd_rg_recent_lock); + while (!list_empty(&sdp->sd_rg_recent)) { + rgd = list_entry(sdp->sd_rg_recent.next, + struct gfs_rgrpd, rd_recent); + list_del(&rgd->rd_recent); + } + spin_unlock(&sdp->sd_rg_recent_lock); + + while (!list_empty(&sdp->sd_rglist)) { + rgd = list_entry(sdp->sd_rglist.next, + struct gfs_rgrpd, rd_list); + gl = rgd->rd_gl; + + list_del(&rgd->rd_list); + list_del(&rgd->rd_list_mru); + + if (gl) { + gfs_glock_force_drop(gl); + if (atomic_read(&gl->gl_lvb_count)) + gfs_lvb_unhold(gl); + set_gl2rgd(gl, NULL); + gfs_glock_put(gl); + } + + if (rgd->rd_bits) + kfree(rgd->rd_bits); + if (rgd->rd_bh) + kfree(rgd->rd_bh); + + kfree(rgd); + } +} + +/** + * gfs_clear_rgrpd - Clear up rgrps + * @sdp: The GFS superblock + * + */ + +void +gfs_clear_rgrpd(struct gfs_sbd *sdp) +{ + down(&sdp->sd_rindex_lock); + clear_rgrpdi(sdp); + up(&sdp->sd_rindex_lock); +} + +/** + * gfs_compute_bitstructs - Compute the bitmap sizes + * @rgd: The resource group descriptor + * + * Calculates bitmap descriptors, one for each block that contains bitmap data + * + * Returns: errno + */ + +static int +compute_bitstructs(struct gfs_rgrpd *rgd) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct gfs_bitmap *bits; + uint32_t length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */ + uint32_t bytes_left, bytes; + int x; + + rgd->rd_bits = kmalloc(length * sizeof(struct gfs_bitmap), GFP_KERNEL); + if (!rgd->rd_bits) + return -ENOMEM; + memset(rgd->rd_bits, 0, length * sizeof(struct gfs_bitmap)); + + bytes_left = rgd->rd_ri.ri_bitbytes; + + for (x = 0; x < length; x++) { + bits = &rgd->rd_bits[x]; + + /* small rgrp; bitmap stored completely in header block */ + if (length == 1) { + bytes = bytes_left; + bits->bi_offset = sizeof(struct gfs_rgrp); + bits->bi_start = 0; + bits->bi_len = bytes; + /* header block */ + } else if (x == 0) { + bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs_rgrp); + bits->bi_offset = sizeof(struct gfs_rgrp); + bits->bi_start = 0; + bits->bi_len = bytes; + /* last block */ + } else if (x + 1 == length) { + bytes = bytes_left; + bits->bi_offset = sizeof(struct gfs_meta_header); + bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left; + bits->bi_len = bytes; + /* other blocks */ + } else { + bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs_meta_header); + bits->bi_offset = sizeof(struct gfs_meta_header); + bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left; + bits->bi_len = bytes; + } + + bytes_left -= bytes; + } + + if (bytes_left) { + gfs_consist_rgrpd(rgd); + return -EIO; + } + if ((rgd->rd_bits[length - 1].bi_start + + rgd->rd_bits[length - 1].bi_len) * GFS_NBBY != + rgd->rd_ri.ri_data) { + if (gfs_consist_rgrpd(rgd)) { + gfs_rindex_print(&rgd->rd_ri); + printk("GFS: fsid=%s: start=%u len=%u offset=%u\n", + sdp->sd_fsname, + rgd->rd_bits[length - 1].bi_start, + rgd->rd_bits[length - 1].bi_len, + rgd->rd_bits[length - 1].bi_offset); + } + return -EIO; + } + + rgd->rd_bh = kmalloc(length * sizeof(struct buffer_head *), GFP_KERNEL); + if (!rgd->rd_bh) { + kfree(rgd->rd_bits); + rgd->rd_bits = NULL; + return -ENOMEM; + } + memset(rgd->rd_bh, 0, length * sizeof(struct buffer_head *)); + + return 0; +} + +/** + * gfs_ri_update - Pull in a new resource index from the disk + * @gl: The glock covering the rindex inode + * + * Returns: 0 on successful update, error code otherwise + */ + +static int +gfs_ri_update(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_rgrpd *rgd; + char buf[sizeof(struct gfs_rindex)]; + int error; + + if (do_mod(ip->i_di.di_size, sizeof(struct gfs_rindex))) { + gfs_consist_inode(ip); + return -EIO; + } + + clear_rgrpdi(sdp); + + for (sdp->sd_rgcount = 0;; sdp->sd_rgcount++) { + error = gfs_internal_read(ip, buf, + sdp->sd_rgcount * + sizeof(struct gfs_rindex), + sizeof(struct gfs_rindex)); + if (!error) + break; + if (error != sizeof(struct gfs_rindex)) { + if (error > 0) + error = -EIO; + goto fail; + } + + rgd = kmalloc(sizeof(struct gfs_rgrpd), GFP_KERNEL); + error = -ENOMEM; + if (!rgd) + goto fail; + memset(rgd, 0, sizeof(struct gfs_rgrpd)); + + INIT_LIST_HEAD(&rgd->rd_mhc); + INIT_LIST_HEAD(&rgd->rd_depend); + rgd->rd_sbd = sdp; + + list_add_tail(&rgd->rd_list, &sdp->sd_rglist); + list_add_tail(&rgd->rd_list_mru, &sdp->sd_rg_mru_list); + + gfs_rindex_in(&rgd->rd_ri, buf); + + error = compute_bitstructs(rgd); + if (error) + goto fail; + + error = gfs_glock_get(sdp, rgd->rd_ri.ri_addr, &gfs_rgrp_glops, + CREATE, &rgd->rd_gl); + if (error) + goto fail; + + error = gfs_lvb_hold(rgd->rd_gl); + if (error) + goto fail; + + set_gl2rgd(rgd->rd_gl, rgd); + rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; + } + + sdp->sd_riinode_vn = ip->i_gl->gl_vn; + + return 0; + + fail: + clear_rgrpdi(sdp); + + return error; +} + +/** + * gfs_rindex_hold - Grab a lock on the rindex + * @sdp: The GFS superblock + * @ri_gh: the glock holder + * + * We grab a lock on the rindex inode to make sure that it doesn't + * change whilst we are performing an operation. We keep this lock + * for quite long periods of time compared to other locks. This + * doesn't matter, since it is shared and it is very, very rarely + * accessed in the exclusive mode (i.e. only when expanding the filesystem). + * + * This makes sure that we're using the latest copy of the resource index + * special file, which might have been updated if someone expanded the + * filesystem (via gfs_grow utility), which adds new resource groups. + * + * Returns: 0 on success, error code otherwise + */ + +int +gfs_rindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ri_gh) +{ + struct gfs_inode *ip = sdp->sd_riinode; + struct gfs_glock *gl = ip->i_gl; + int error; + + error = gfs_glock_nq_init(gl, LM_ST_SHARED, 0, ri_gh); + if (error) + return error; + + /* Read new copy from disk if we don't have the latest */ + if (sdp->sd_riinode_vn != gl->gl_vn) { + down(&sdp->sd_rindex_lock); + if (sdp->sd_riinode_vn != gl->gl_vn) { + error = gfs_ri_update(ip); + if (error) + gfs_glock_dq_uninit(ri_gh); + } + up(&sdp->sd_rindex_lock); + } + + return error; +} + +/** + * gfs_rgrp_read - Read in a RG's header and bitmaps + * @rgd: the struct gfs_rgrpd describing the RG to read in + * + * Read in all of a Resource Group's header and bitmap blocks. + * Caller must eventually call gfs_rgrp_relse() to free the bitmaps. + * + * Returns: errno + */ + +int +gfs_rgrp_read(struct gfs_rgrpd *rgd) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct gfs_glock *gl = rgd->rd_gl; + unsigned int x, length = rgd->rd_ri.ri_length; + int error; + + for (x = 0; x < length; x++) { + gfs_assert_warn(sdp, !rgd->rd_bh[x]); + rgd->rd_bh[x] = gfs_dgetblk(gl, rgd->rd_ri.ri_addr + x); + } + + for (x = 0; x < length; x++) { + error = gfs_dreread(sdp, rgd->rd_bh[x], DIO_START); + if (error) + goto fail; + } + + for (x = length; x--;) { + error = gfs_dreread(sdp, rgd->rd_bh[x], DIO_WAIT); + if (error) + goto fail; + if (gfs_metatype_check(sdp, rgd->rd_bh[x], + (x) ? GFS_METATYPE_RB : GFS_METATYPE_RG)) { + error = -EIO; + goto fail; + } + } + + if (rgd->rd_rg_vn != gl->gl_vn) { + gfs_rgrp_in(&rgd->rd_rg, (rgd->rd_bh[0])->b_data); + rgd->rd_rg_vn = gl->gl_vn; + } + + return 0; + + fail: + for (x = 0; x < length; x++) { + brelse(rgd->rd_bh[x]); + rgd->rd_bh[x] = NULL; + } + + return error; +} + +/** + * gfs_rgrp_relse - Release RG bitmaps read in with gfs_rgrp_read() + * @rgd: the struct gfs_rgrpd describing the RG to read in + * + */ + +void +gfs_rgrp_relse(struct gfs_rgrpd *rgd) +{ + int x, length = rgd->rd_ri.ri_length; + + for (x = 0; x < length; x++) { + brelse(rgd->rd_bh[x]); + rgd->rd_bh[x] = NULL; + } +} + +/** + * gfs_rgrp_lvb_fill - copy RG usage data out of the struct gfs_rgrp into the struct gfs_rgrp_lvb + * @rgd: the resource group data structure + * + */ + +void +gfs_rgrp_lvb_fill(struct gfs_rgrpd *rgd) +{ + struct gfs_rgrp *rg = &rgd->rd_rg; + struct gfs_rgrp_lvb *rb = (struct gfs_rgrp_lvb *)rgd->rd_gl->gl_lvb; + + rb->rb_magic = cpu_to_gfs32(GFS_MAGIC); + rb->rb_free = cpu_to_gfs32(rg->rg_free); + rb->rb_useddi = cpu_to_gfs32(rg->rg_useddi); + rb->rb_freedi = cpu_to_gfs32(rg->rg_freedi); + rb->rb_usedmeta = cpu_to_gfs32(rg->rg_usedmeta); + rb->rb_freemeta = cpu_to_gfs32(rg->rg_freemeta); +} + +/** + * gfs_rgrp_lvb_init - Init the data of a RG LVB + * @rgd: the resource group data structure + * + * Returns: errno + */ + +int +gfs_rgrp_lvb_init(struct gfs_rgrpd *rgd) +{ + struct gfs_glock *gl = rgd->rd_gl; + struct gfs_holder rgd_gh; + int error; + + error = gfs_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &rgd_gh); + if (!error) { + gfs_rgrp_lvb_fill(rgd); + gfs_glock_dq_uninit(&rgd_gh); + } + + return error; +} + +/** + * gfs_alloc_get - allocate a struct gfs_alloc structure for an inode + * @ip: the incore GFS inode structure + * + * Alloc and zero an in-place reservation structure, + * and attach it to the GFS incore inode. + * + * FIXME: Don't use gmalloc() + * + * Returns: the struct gfs_alloc + */ + +struct gfs_alloc * +gfs_alloc_get(struct gfs_inode *ip) +{ + struct gfs_alloc *al = ip->i_alloc; + + gfs_assert_warn(ip->i_sbd, !al); + + al = gmalloc(sizeof(struct gfs_alloc)); + memset(al, 0, sizeof(struct gfs_alloc)); + + ip->i_alloc = al; + + return al; +} + +/** + * gfs_alloc_put - throw away the struct gfs_alloc for an inode + * @ip: the inode + * + */ + +void +gfs_alloc_put(struct gfs_inode *ip) +{ + struct gfs_alloc *al = ip->i_alloc; + + if (gfs_assert_warn(ip->i_sbd, al)) + return; + + ip->i_alloc = NULL; + kfree(al); +} + +/** + * try_rgrp_fit - See if a given reservation will fit in a given RG + * @rgd: the RG data + * @al: the struct gfs_alloc structure describing the reservation + * + * If there's room for the requested blocks to be allocated from the RG: + * Sets the $al_reserved_data field in @al. + * Sets the $al_reserved_meta field in @al. + * Sets the $al_rgd field in @al. + * + * Returns: 1 on success (it fits), 0 on failure (it doesn't fit) + */ + +static int +try_rgrp_fit(struct gfs_rgrpd *rgd, struct gfs_alloc *al) +{ + uint32_t freeblks = rgd->rd_rg.rg_free; + uint32_t freemeta = rgd->rd_rg.rg_freemeta; + uint32_t metares = al->al_requested_meta; + uint32_t datares = al->al_requested_data; + + /* First take care of the data blocks required */ + + if (freeblks < al->al_requested_data) + return 0; + + freeblks -= al->al_requested_data; + + /* Then take care of the dinodes */ + + metares += al->al_requested_di; + + /* Then take care of the metadata blocks */ + + while (freemeta < metares) { + if (freeblks < GFS_META_CLUMP) + return 0; + + freeblks -= GFS_META_CLUMP; + freemeta += GFS_META_CLUMP; + + datares += GFS_META_CLUMP; + } + + al->al_rgd = rgd; + al->al_reserved_meta = metares; + al->al_reserved_data = datares; + + return 1; +} + +/** + * recent_rgrp_first - get first RG from "recent" list + * @sdp: The GFS superblock + * @rglast: address of the rgrp used last + * + * Returns: The first rgrp in the recent list + */ + +static struct gfs_rgrpd * +recent_rgrp_first(struct gfs_sbd *sdp, uint64_t rglast) +{ + struct list_head *tmp, *head; + struct gfs_rgrpd *rgd = NULL; + + spin_lock(&sdp->sd_rg_recent_lock); + + if (list_empty(&sdp->sd_rg_recent)) + goto out; + + if (!rglast) + goto first; + + for (head = &sdp->sd_rg_recent, tmp = head->next; + tmp != head; + tmp = tmp->next) { + rgd = list_entry(tmp, struct gfs_rgrpd, rd_recent); + if (rgd->rd_ri.ri_addr == rglast) + goto out; + } + + first: + rgd = list_entry(sdp->sd_rg_recent.next, struct gfs_rgrpd, rd_recent); + + out: + spin_unlock(&sdp->sd_rg_recent_lock); + + return rgd; +} + +/** + * recent_rgrp_next - get next RG from "recent" list + * @cur_rgd: current rgrp + * @remove: + * + * Returns: The next rgrp in the recent list + */ + +static struct gfs_rgrpd * +recent_rgrp_next(struct gfs_rgrpd *cur_rgd, int remove) +{ + struct gfs_sbd *sdp = cur_rgd->rd_sbd; + struct list_head *tmp, *head; + struct gfs_rgrpd *rgd; + + spin_lock(&sdp->sd_rg_recent_lock); + + for (head = &sdp->sd_rg_recent, tmp = head->next; + tmp != head; + tmp = tmp->next) { + rgd = list_entry(tmp, struct gfs_rgrpd, rd_recent); + if (rgd == cur_rgd) { + if (cur_rgd->rd_recent.next != head) + rgd = list_entry(cur_rgd->rd_recent.next, + struct gfs_rgrpd, rd_recent); + else + rgd = NULL; + + if (remove) + list_del(&cur_rgd->rd_recent); + + goto out; + } + } + + rgd = NULL; + if (!list_empty(head)) + rgd = list_entry(head->next, struct gfs_rgrpd, rd_recent); + + out: + spin_unlock(&sdp->sd_rg_recent_lock); + + return rgd; +} + +/** + * recent_rgrp_add - add an RG to tail of "recent" list + * @new_rgd: The rgrp to add + * + * Before adding, make sure that: + * 1) it's not already on the list + * 2) there's still room for more entries + * The capacity limit imposed on the "recent" list is basically a node's "share" + * of rgrps within a cluster, i.e. (total # rgrps) / (# nodes (journals)) + */ + +static void +recent_rgrp_add(struct gfs_rgrpd *new_rgd) +{ + struct gfs_sbd *sdp = new_rgd->rd_sbd; + struct list_head *tmp, *head; + struct gfs_rgrpd *rgd = NULL; + unsigned int count = 0; + unsigned int max = sdp->sd_rgcount / gfs_num_journals(sdp); + + spin_lock(&sdp->sd_rg_recent_lock); + + for (head = &sdp->sd_rg_recent, tmp = head->next; + tmp != head; + tmp = tmp->next) { + rgd = list_entry(tmp, struct gfs_rgrpd, rd_recent); + if (rgd == new_rgd) + goto out; + + if (++count >= max) + goto out; + } + new_rgd->rd_try_counter = 0; + list_add_tail(&new_rgd->rd_recent, &sdp->sd_rg_recent); + + out: + spin_unlock(&sdp->sd_rg_recent_lock); +} + +/** + * forward_rgrp_get - get an rgrp to try next from full list + * @sdp: The GFS superblock + * + * Returns: The rgrp to try next + */ + +static struct gfs_rgrpd * +forward_rgrp_get(struct gfs_sbd *sdp) +{ + struct gfs_rgrpd *rgd; + unsigned int journals = gfs_num_journals(sdp); + unsigned int rg = 0, x; + + spin_lock(&sdp->sd_rg_forward_lock); + + rgd = sdp->sd_rg_forward; + if (!rgd) { + if (sdp->sd_rgcount >= journals) + rg = sdp->sd_rgcount * + sdp->sd_lockstruct.ls_jid / + journals; + + for (x = 0, rgd = gfs_rgrpd_get_first(sdp); + x < rg; + x++, rgd = gfs_rgrpd_get_next(rgd)) + /* Do Nothing */; + + sdp->sd_rg_forward = rgd; + } + + spin_unlock(&sdp->sd_rg_forward_lock); + + return rgd; +} + +/** + * forward_rgrp_set - set the forward rgrp pointer + * @sdp: the filesystem + * @rgd: The new forward rgrp + * + */ + +static void +forward_rgrp_set(struct gfs_sbd *sdp, struct gfs_rgrpd *rgd) +{ + spin_lock(&sdp->sd_rg_forward_lock); + sdp->sd_rg_forward = rgd; + spin_unlock(&sdp->sd_rg_forward_lock); +} + +/** + * get_local_rgrp - Choose and lock a rgrp for allocation + * @ip: the inode to reserve space for + * @rgp: the chosen and locked rgrp + * + * Try to acquire rgrp in way which avoids contending with others. + * + * Returns: errno + */ + +static int +get_local_rgrp(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_rgrpd *rgd, *begin = NULL; + struct gfs_alloc *al = ip->i_alloc; + int flags = LM_FLAG_TRY; + int skipped = 0; + int loops = 0; + int error; + int try_flag; + unsigned int try_threshold = gfs_tune_get(sdp, gt_rgrp_try_threshold); + + /* Try recently successful rgrps */ + + rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc); + + while (rgd) { + try_flag = (rgd->rd_try_counter >= try_threshold) ? + 0: LM_FLAG_TRY; + error = gfs_glock_nq_init(rgd->rd_gl, + LM_ST_EXCLUSIVE, try_flag, + &al->al_rgd_gh); + switch (error) { + case 0: + if (try_rgrp_fit(rgd, al)) { + rgd->rd_try_counter = 0; + goto out; + } + gfs_glock_dq_uninit(&al->al_rgd_gh); + rgd = recent_rgrp_next(rgd, TRUE); + break; + + case GLR_TRYFAILED: + rgd->rd_try_counter++; + rgd = recent_rgrp_next(rgd, FALSE); + break; + + default: + return error; + } + } + + /* Go through full list of rgrps */ + + begin = rgd = forward_rgrp_get(sdp); + + for (;;) { + error = gfs_glock_nq_init(rgd->rd_gl, + LM_ST_EXCLUSIVE, flags, + &al->al_rgd_gh); + switch (error) { + case 0: + if (try_rgrp_fit(rgd, al)) + goto out; + gfs_glock_dq_uninit(&al->al_rgd_gh); + break; + + case GLR_TRYFAILED: + skipped++; + break; + + default: + return error; + } + + rgd = gfs_rgrpd_get_next(rgd); + if (!rgd) + rgd = gfs_rgrpd_get_first(sdp); + + if (rgd == begin) { + if (++loops >= 2 || !skipped) + return -ENOSPC; + flags = 0; + } + } + + out: + ip->i_last_rg_alloc = rgd->rd_ri.ri_addr; + + if (begin) { + recent_rgrp_add(rgd); + rgd = gfs_rgrpd_get_next(rgd); + if (!rgd) + rgd = gfs_rgrpd_get_first(sdp); + forward_rgrp_set(sdp, rgd); + } + + return 0; +} + +/** + * gfs_inplace_reserve_i - Reserve space in the filesystem + * @ip: the inode to reserve space for + * + * Acquire resource group locks to allow for the maximum allocation + * described by "res". + * + * This should probably become more complex again, but for now, let's go + * for simple (one resource group) reservations. + * + * Returns: errno + */ + +int +gfs_inplace_reserve_i(struct gfs_inode *ip, + char *file, unsigned int line) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + int error; + + if (gfs_assert_warn(sdp, + al->al_requested_di || + al->al_requested_data || + al->al_requested_meta)) + return -EINVAL; + + error = gfs_rindex_hold(sdp, &al->al_ri_gh); + if (error) + return error; + + error = get_local_rgrp(ip); + if (error) { + gfs_glock_dq_uninit(&al->al_ri_gh); + return error; + } + + gfs_depend_sync(al->al_rgd); + + al->al_file = file; + al->al_line = line; + + return 0; +} + +/** + * gfs_inplace_release - release an inplace reservation + * @ip: the inode the reservation was taken out on + * + * Release a reservation made by gfs_inplace_reserve(). + */ + +void +gfs_inplace_release(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + + if (gfs_assert_warn(sdp, al->al_alloced_di <= al->al_requested_di) == -1) + printk("GFS: fsid=%s: al_alloced_di = %u, al_requested_di = %u\n" + "GFS: fsid=%s: al_file = %s, al_line = %u\n", + sdp->sd_fsname, al->al_alloced_di, al->al_requested_di, + sdp->sd_fsname, al->al_file, al->al_line); + if (gfs_assert_warn(sdp, al->al_alloced_meta <= al->al_reserved_meta) == -1) + printk("GFS: fsid=%s: al_alloced_meta = %u, al_reserved_meta = %u\n" + "GFS: fsid=%s: al_file = %s, al_line = %u\n", + sdp->sd_fsname, al->al_alloced_meta, al->al_reserved_meta, + sdp->sd_fsname, al->al_file, al->al_line); + if (gfs_assert_warn(sdp, al->al_alloced_data <= al->al_reserved_data) == -1) + printk("GFS: fsid=%s: al_alloced_data = %u, al_reserved_data = %u\n" + "GFS: fsid=%s: al_file = %s, al_line = %u\n", + sdp->sd_fsname, al->al_alloced_data, al->al_reserved_data, + sdp->sd_fsname, al->al_file, al->al_line); + + al->al_rgd = NULL; + gfs_glock_dq_uninit(&al->al_rgd_gh); + gfs_glock_dq_uninit(&al->al_ri_gh); +} + +/** + * gfs_get_block_type - Check a block in a RG is of given type + * @rgd: the resource group holding the block + * @block: the block number + * + * Returns: The block type (GFS_BLKST_*) + */ + +unsigned char +gfs_get_block_type(struct gfs_rgrpd *rgd, uint64_t block) +{ + struct gfs_bitmap *bits = NULL; + uint32_t length, rgrp_block, buf_block; + unsigned int buf; + unsigned char type; + + length = rgd->rd_ri.ri_length; + rgrp_block = block - rgd->rd_ri.ri_data1; + + for (buf = 0; buf < length; buf++) { + bits = &rgd->rd_bits[buf]; + if (rgrp_block < (bits->bi_start + bits->bi_len) * GFS_NBBY) + break; + } + + gfs_assert(rgd->rd_sbd, buf < length,); + buf_block = rgrp_block - bits->bi_start * GFS_NBBY; + + type = gfs_testbit(rgd, + rgd->rd_bh[buf]->b_data + bits->bi_offset, + bits->bi_len, buf_block); + + return type; +} + +/** + * blkalloc_internal - find a block in @old_state, change allocation + * state to @new_state + * @rgd: the resource group descriptor + * @goal: the goal block within the RG (start here to search for avail block) + * @old_state: GFS_BLKST_XXX the before-allocation state to find + * @new_state: GFS_BLKST_XXX the after-allocation block state + * + * Walk rgrp's bitmap to find bits that represent a block in @old_state. + * Add the found bitmap buffer to the transaction. + * Set the found bits to @new_state to change block's allocation state. + * + * This function never fails, because we wouldn't call it unless we + * know (from reservation results, etc.) that a block is available. + * + * Scope of @goal and returned block is just within rgrp (32-bit), + * not the whole filesystem (64-bit). + * + * Returns: the block # allocated (32-bit rgrp scope) + */ + +static uint32_t +blkalloc_internal(struct gfs_rgrpd *rgd, + uint32_t goal, + unsigned char old_state, unsigned char new_state) +{ + struct gfs_bitmap *bits = NULL; + uint32_t length = rgd->rd_ri.ri_length; + uint32_t blk = 0; + unsigned int buf, x; + + /* Find bitmap block that contains bits for goal block */ + for (buf = 0; buf < length; buf++) { + bits = &rgd->rd_bits[buf]; + if (goal < (bits->bi_start + bits->bi_len) * GFS_NBBY) + break; + } + + gfs_assert(rgd->rd_sbd, buf < length,); + + /* Convert scope of "goal" from rgrp-wide to within found bit block */ + goal -= bits->bi_start * GFS_NBBY; + + /* Search (up to entire) bitmap in this rgrp for allocatable block. + "x <= length", instead of "x < length", because we typically start + the search in the middle of a bit block, but if we can't find an + allocatable block anywhere else, we want to be able wrap around and + search in the first part of our first-searched bit block. */ + for (x = 0; x <= length; x++) { + blk = gfs_bitfit(rgd->rd_bh[buf]->b_data + bits->bi_offset, + bits->bi_len, goal, old_state); + if (blk != BFITNOENT) + break; + + /* Try next bitmap block (wrap back to rgrp header if at end) */ + buf = (buf + 1) % length; + bits = &rgd->rd_bits[buf]; + goal = 0; + } + + if (unlikely(x > length)) { + printk("GFS error: possible RG corruption\n"); + printk(" please run gfs_fsck after withdraw\n"); + dump_stack(); + if (gfs_assert_withdraw(rgd->rd_sbd, x <= length)) + blk = 0; + } + + /* Attach bitmap buffer to trans, modify bits to do block alloc */ + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[buf]); + gfs_setbit(rgd, + rgd->rd_bh[buf]->b_data + bits->bi_offset, + bits->bi_len, blk, new_state); + + /* Return allocated block #, rgrp scope (32-bit) */ + return bits->bi_start * GFS_NBBY + blk; +} + +/** + * blkfree_internal - Change alloc state of given block(s) + * @sdp: the filesystem + * @bstart: first block (64-bit filesystem scope) of a run of contiguous blocks + * @blen: the length of the block run (all must lie within ONE RG!) + * @new_state: GFS_BLKST_XXX the after-allocation block state + * + * Returns: Resource group containing the block(s) + * + * Find rgrp containing @bstart. + * For each block in run: + * Find allocation bitmap buffer. + * Add bitmap buffer to transaction. + * Set bits to new state. + * Typically used to free blocks to GFS_BLKST_FREE or GFS_BLKST_FREEMETA, + * but @new_state can be any GFS_BLKST_XXX + * + */ + +static struct gfs_rgrpd * +blkfree_internal(struct gfs_sbd *sdp, uint64_t bstart, uint32_t blen, + unsigned char new_state) +{ + struct gfs_rgrpd *rgd; + struct gfs_bitmap *bits = NULL; + uint32_t length, rgrp_blk, buf_blk; + unsigned int buf; + + /* Find rgrp */ + rgd = gfs_blk2rgrpd(sdp, bstart); + if (!rgd) { + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: block = %llu\n", + sdp->sd_fsname, bstart); + return NULL; + } + + length = rgd->rd_ri.ri_length; + + /* Convert blk # from filesystem scope (64-bit) to RG scope (32-bit) */ + rgrp_blk = bstart - rgd->rd_ri.ri_data1; + + while (blen--) { + /* Find bitmap buffer for this block */ + for (buf = 0; buf < length; buf++) { + bits = &rgd->rd_bits[buf]; + if (rgrp_blk < (bits->bi_start + bits->bi_len) * GFS_NBBY) + break; + } + + gfs_assert(rgd->rd_sbd, buf < length,); + + /* Find bits and set 'em */ + buf_blk = rgrp_blk - bits->bi_start * GFS_NBBY; + rgrp_blk++; + + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[buf]); + gfs_setbit(rgd, + rgd->rd_bh[buf]->b_data + bits->bi_offset, + bits->bi_len, buf_blk, new_state); + } + + return rgd; +} + +/** + * clump_alloc - Allocate a clump of metadata blocks + * @rgd: the resource group in which to allocate + * @first: returns the first block allocated + * + * Returns: errno + * + * Bitmap-allocate a clump of metadata blocks + * Write metadata blocks to disk with dummy meta-headers + * Add meta-headers to incore meta-header cache + */ + +static int +clump_alloc(struct gfs_rgrpd *rgd, uint32_t *first) +{ + struct gfs_sbd *sdp = rgd->rd_sbd; + struct gfs_meta_header mh; + struct buffer_head **bh; + uint32_t goal, blk; + unsigned int x; + int error = 0; + + /* Dummy meta-header template */ + memset(&mh, 0, sizeof(struct gfs_meta_header)); + mh.mh_magic = GFS_MAGIC; + mh.mh_type = GFS_METATYPE_NONE; + + /* Array of bh pointers used in several steps */ + bh = gmalloc(GFS_META_CLUMP * sizeof(struct buffer_head *)); + memset(bh, 0, GFS_META_CLUMP * sizeof(struct buffer_head *)); + + /* Since we're looking for data blocks to change into meta blocks, + use last alloc'd *data* (not meta) block as start point */ + goal = rgd->rd_last_alloc_data; + + for (x = 0; x < GFS_META_CLUMP; x++) { + blk = blkalloc_internal(rgd, goal, GFS_BLKST_FREE, + GFS_BLKST_FREEMETA); + if (!x) + *first = blk; + + bh[x] = gfs_dgetblk(rgd->rd_gl, rgd->rd_ri.ri_data1 + blk); + + gfs_prep_new_buffer(bh[x]); + + gfs_meta_header_out(&mh, bh[x]->b_data); + ((struct gfs_meta_header *)bh[x]->b_data)->mh_generation = 0; + + /* start write of new meta-buffer to disk */ + error = gfs_dwrite(sdp, bh[x], DIO_DIRTY | DIO_START); + if (error) + goto out; + + goal = blk; + } + + /* Block alloc start point for next time */ + rgd->rd_last_alloc_data = goal; + + /* Wait for all new meta-buffers to get on-disk */ + for (x = 0; x < GFS_META_CLUMP; x++) { + error = gfs_dwrite(sdp, bh[x], DIO_WAIT); + if (error) + goto out; + } + + /* Add all new meta-headers to meta-header cache */ + gfs_mhc_add(rgd, bh, GFS_META_CLUMP); + + gfs_assert_withdraw(sdp, rgd->rd_rg.rg_free >= GFS_META_CLUMP); + rgd->rd_rg.rg_free -= GFS_META_CLUMP; + rgd->rd_rg.rg_freemeta += GFS_META_CLUMP; + + out: + for (x = 0; x < GFS_META_CLUMP; x++) + if (bh[x]) { + gfs_dwrite(sdp, bh[x], DIO_WAIT); + brelse(bh[x]); + } + kfree(bh); + + return error; +} + +/** + * gfs_blkalloc - Allocate a data block + * @ip: the inode to allocate the data block for + * @block: the block allocated + * + */ + +void +gfs_blkalloc(struct gfs_inode *ip, uint64_t *block) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + struct gfs_rgrpd *rgd = al->al_rgd; + uint32_t goal, blk; + int same; + + same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp); + goal = (same) ? ip->i_di.di_goal_dblk : rgd->rd_last_alloc_data; + + blk = blkalloc_internal(rgd, goal, + GFS_BLKST_FREE, GFS_BLKST_USED); + rgd->rd_last_alloc_data = blk; + + if (!same) { + ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr; + ip->i_di.di_goal_mblk = 0; + } + ip->i_di.di_goal_dblk = blk; + + *block = rgd->rd_ri.ri_data1 + blk; + + gfs_assert_withdraw(sdp, rgd->rd_rg.rg_free); + rgd->rd_rg.rg_free--; + + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]); + gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data); + + al->al_alloced_data++; + + gfs_trans_add_quota(sdp, +1, ip->i_di.di_uid, ip->i_di.di_gid); + + /* total=0, free=-1, dinodes=0 */ + gfs_statfs_modify(sdp, 0, -1, 0); +} + +/** + * gfs_metaalloc - Allocate a metadata block to a file + * @ip: the file + * @block: the block allocated + * + * Returns: errno + */ + +int +gfs_metaalloc(struct gfs_inode *ip, uint64_t *block) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + struct gfs_rgrpd *rgd = al->al_rgd; + uint32_t goal, blk; + int same; + int error; + + same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp); + + if (!rgd->rd_rg.rg_freemeta) { + error = clump_alloc(rgd, &goal); + if (error) + return error; + + al->al_alloced_data += GFS_META_CLUMP; + } else + goal = (same) ? ip->i_di.di_goal_mblk : rgd->rd_last_alloc_meta; + + blk = blkalloc_internal(rgd, goal, + GFS_BLKST_FREEMETA, GFS_BLKST_USEDMETA); + rgd->rd_last_alloc_meta = blk; + + if (!same) { + ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr; + ip->i_di.di_goal_dblk = 0; + } + ip->i_di.di_goal_mblk = blk; + + *block = rgd->rd_ri.ri_data1 + blk; + + gfs_assert_withdraw(sdp, rgd->rd_rg.rg_freemeta); + rgd->rd_rg.rg_freemeta--; + rgd->rd_rg.rg_usedmeta++; + + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]); + gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data); + + al->al_alloced_meta++; + + gfs_trans_add_quota(sdp, +1, ip->i_di.di_uid, ip->i_di.di_gid); + + /* total=0, free=-1, dinode=0 */ + gfs_statfs_modify(sdp, 0, -1, 0); + + return 0; +} + +/** + * gfs_dialloc - Allocate a dinode + * @dip: the directory that the inode is going in + * @block: the block (result) which this function allocates as the dinode + * (64-bit filesystem scope) + * + * Returns: errno + */ + +int +gfs_dialloc(struct gfs_inode *dip, uint64_t *block) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_alloc *al = dip->i_alloc; + struct gfs_rgrpd *rgd = al->al_rgd; + uint32_t goal, blk; + int error = 0; + + if (rgd->rd_rg.rg_freemeta) + /* pick up where we left off last time */ + goal = rgd->rd_last_alloc_meta; + else { + /* no free meta blocks, allocate a bunch more */ + error = clump_alloc(rgd, &goal); + if (error) + return error; + + al->al_alloced_data += GFS_META_CLUMP; + } + + /* Alloc the dinode; 32-bit "blk" is block offset within rgrp */ + blk = blkalloc_internal(rgd, goal, + GFS_BLKST_FREEMETA, GFS_BLKST_USEDMETA); + + /* remember where we left off, for next time */ + rgd->rd_last_alloc_meta = blk; + + /* convert from rgrp scope (32-bit) to filesystem scope (64-bit) */ + *block = rgd->rd_ri.ri_data1 + blk; + + gfs_assert_withdraw(rgd->rd_sbd, rgd->rd_rg.rg_freemeta); + rgd->rd_rg.rg_freemeta--; + rgd->rd_rg.rg_useddi++; + + /* Attach rgrp header to trans, update freemeta and useddi stats */ + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]); + gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data); + + /* Update stats in in-place reservation struct */ + al->al_alloced_di++; + al->al_alloced_meta++; + + /* total=0, free=-1, dinodes=1 */ + gfs_statfs_modify(sdp, 0, -1, +1); + + return error; +} + +/** + * gfs_blkfree - free a contiguous run of data block(s) + * @ip: the inode these blocks are being freed from + * @bstart: first block (64-bit filesystem scope) of a run of contiguous blocks + * @blen: the length of the block run (all must lie within ONE RG!) + * + * Bitmap-deallocate the blocks (to FREE data state), add bitmap blks to trans + * Update rgrp alloc statistics in rgrp header, add rgrp header buf to trans + * Update quotas, add to trans. + */ + +void +gfs_blkfree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_rgrpd *rgd; + + rgd = blkfree_internal(sdp, bstart, blen, GFS_BLKST_FREE); + if (!rgd) + return; + + rgd->rd_rg.rg_free += blen; + + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]); + gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data); + + gfs_trans_add_quota(sdp, -(int64_t)blen, + ip->i_di.di_uid, + ip->i_di.di_gid); + + /* total=0, free=+blen, dinodes=0 */ + gfs_statfs_modify(sdp, 0, blen, 0); +} + +/** + * gfs_metafree - free a contiguous run of metadata block(s) + * @ip: the inode these blocks are being freed from + * @bstart: first block (64-bit filesystem scope) of a run of contiguous blocks + * @blen: the length of the block run (all must lie within ONE RG!) + * + * Bitmap-deallocate the blocks (to FREEMETA state), add bitmap blks to trans. + * Update rgrp alloc statistics in rgrp header, add rgrp header to trans. + * Update quotas (quotas include metadata, not just data block usage), + * add to trans. + * Release deallocated buffers, add to meta-header cache (we save these in-core + * so we don't need to re-read meta blocks if/when they are re-alloc'd). + */ + +void +gfs_metafree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_rgrpd *rgd; + + rgd = blkfree_internal(sdp, bstart, blen, GFS_BLKST_FREEMETA); + if (!rgd) + return; + + if (rgd->rd_rg.rg_usedmeta < blen) + gfs_consist_rgrpd(rgd); + rgd->rd_rg.rg_usedmeta -= blen; + rgd->rd_rg.rg_freemeta += blen; + + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]); + gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data); + + /* total=0, free=blen, dinode=0 */ + gfs_statfs_modify(sdp, 0, blen, 0); + + gfs_trans_add_quota(sdp, -(int64_t)blen, + ip->i_di.di_uid, + ip->i_di.di_gid); + gfs_wipe_buffers(ip, rgd, bstart, blen); +} + +/** + * gfs_difree_uninit - free a dinode block + * @rgd: the resource group that contains the dinode + * @addr: the dinode address + * + * De-allocate the dinode to FREEMETA using block alloc bitmap. + * Update rgrp's block usage statistics (used dinode--, free meta++). + * Add rgrp header to transaction. + */ + +void +gfs_difree_uninit(struct gfs_rgrpd *rgd, uint64_t addr) +{ + struct gfs_rgrpd *tmp_rgd; + + tmp_rgd = blkfree_internal(rgd->rd_sbd, addr, 1, + GFS_BLKST_FREEMETA); + if (!tmp_rgd) + return; + gfs_assert_withdraw(rgd->rd_sbd, rgd == tmp_rgd); + + if (!rgd->rd_rg.rg_useddi) + gfs_consist_rgrpd(rgd); + rgd->rd_rg.rg_useddi--; + rgd->rd_rg.rg_freemeta++; + + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]); + gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data); + + /* total=0, free=1, dinodes=-1 */ + gfs_statfs_modify(rgd->rd_sbd, 0, +1, -1); +} + +/** + * gfs_difree - free a dinode block + * @rgd: the resource group that contains the dinode + * @ip: the inode representing the dinode to free + * + * Free the dinode block to FREEMETA, update rgrp's block usage stats. + * Update quotas (quotas include metadata, not just data block usage), + * add to trans. + * Release deallocated buffers, add to meta-header cache (we save these in-core + * so we don't need to re-read meta blocks if/when they are re-alloc'd). + */ + +void +gfs_difree(struct gfs_rgrpd *rgd, struct gfs_inode *ip) +{ + gfs_difree_uninit(rgd, ip->i_num.no_addr); + gfs_trans_add_quota(ip->i_sbd, -1, ip->i_di.di_uid, ip->i_di.di_gid); + gfs_wipe_buffers(ip, rgd, ip->i_num.no_addr, 1); +} + +/** + * gfs_rlist_add - add a RG to a list of RGs + * @sdp: the filesystem + * @rlist: the list of resource groups + * @block: the block + * + * Figure out what RG a block belongs to and add that RG to the list + * + * FIXME: Don't use gmalloc() + * + */ + +void +gfs_rlist_add(struct gfs_sbd *sdp, struct gfs_rgrp_list *rlist, uint64_t block) +{ + struct gfs_rgrpd *rgd; + struct gfs_rgrpd **tmp; + unsigned int new_space; + unsigned int x; + + if (gfs_assert_warn(sdp, !rlist->rl_ghs)) + return; + + rgd = gfs_blk2rgrpd(sdp, block); + if (!rgd) { + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: block = %llu\n", + sdp->sd_fsname, block); + return; + } + + for (x = 0; x < rlist->rl_rgrps; x++) + if (rlist->rl_rgd[x] == rgd) + return; + + if (rlist->rl_rgrps == rlist->rl_space) { + new_space = rlist->rl_space + 10; + + tmp = gmalloc(new_space * sizeof(struct gfs_rgrpd *)); + + if (rlist->rl_rgd) { + memcpy(tmp, rlist->rl_rgd, + rlist->rl_space * sizeof(struct gfs_rgrpd *)); + kfree(rlist->rl_rgd); + } + + rlist->rl_space = new_space; + rlist->rl_rgd = tmp; + } + + rlist->rl_rgd[rlist->rl_rgrps++] = rgd; +} + +/** + * gfs_rlist_alloc - all RGs have been added to the rlist, now allocate + * and initialize an array of glock holders for them + * @rlist: the list of resource groups + * @state: the lock state to acquire the RG lock in + * @flags: the modifier flags for the holder structures + * + * FIXME: Don't use gmalloc() + * + */ + +void +gfs_rlist_alloc(struct gfs_rgrp_list *rlist, unsigned int state, int flags) +{ + unsigned int x; + + rlist->rl_ghs = gmalloc(rlist->rl_rgrps * sizeof(struct gfs_holder)); + for (x = 0; x < rlist->rl_rgrps; x++) + gfs_holder_init(rlist->rl_rgd[x]->rd_gl, + state, flags, + &rlist->rl_ghs[x]); +} + +/** + * gfs_rlist_free - free a resource group list + * @list: the list of resource groups + * + */ + +void +gfs_rlist_free(struct gfs_rgrp_list *rlist) +{ + unsigned int x; + + if (rlist->rl_rgd) + kfree(rlist->rl_rgd); + + if (rlist->rl_ghs) { + for (x = 0; x < rlist->rl_rgrps; x++) + gfs_holder_uninit(&rlist->rl_ghs[x]); + kfree(rlist->rl_ghs); + } +} + +/** + * gfs_reclaim_metadata - reclaims unused metadata + * @sdp: the file system + * @inodes: + * @metadata: + * + * This function will look through the resource groups and + * free the unused metadata. + * + * Returns: errno + */ + +int +gfs_reclaim_metadata(struct gfs_sbd *sdp, + uint64_t *inodes, + uint64_t *metadata) +{ + struct gfs_holder ji_gh, ri_gh, rgd_gh, t_gh; + struct gfs_rgrpd *rgd; + struct gfs_rgrp *rg; + struct gfs_dinode *di; + struct gfs_inum next; + struct buffer_head *bh; + uint32_t flags; + uint32_t goal; + unsigned int x; + int error = 0; + + *inodes = *metadata = 0; + + /* Acquire the jindex lock here so we don't deadlock with a + process writing the the jindex inode. :-( */ + + error = gfs_jindex_hold(sdp, &ji_gh); + if (error) + goto fail; + + error = gfs_rindex_hold(sdp, &ri_gh); + if (error) + goto fail_jindex_relse; + + for (rgd = gfs_rgrpd_get_first(sdp); + rgd; + rgd = gfs_rgrpd_get_next(rgd)) { + error = gfs_glock_nq_init(rgd->rd_gl, + LM_ST_EXCLUSIVE, GL_NOCACHE, + &rgd_gh); + if (error) + goto fail_rindex_relse; + + rgrp_verify(rgd); + + rg = &rgd->rd_rg; + + if (!rg->rg_freedi && !rg->rg_freemeta) { + gfs_glock_dq_uninit(&rgd_gh); + continue; + } + + gfs_mhc_zap(rgd); + gfs_depend_sync(rgd); + + error = gfs_lock_fs_check_clean(sdp, LM_ST_EXCLUSIVE, &t_gh); + if (error) + goto fail_gunlock_rg; + + error = gfs_trans_begin(sdp, rgd->rd_ri.ri_length, 0); + if (error) + goto fail_unlock_fs; + + next = rg->rg_freedi_list; + + for (x = rg->rg_freedi; x--;) { + if (!next.no_formal_ino || !next.no_addr) { + gfs_consist_rgrpd(rgd); + error = -EIO; + goto fail_end_trans; + } + + blkfree_internal(sdp, next.no_addr, 1, GFS_BLKST_FREE); + + error = gfs_dread(rgd->rd_gl, next.no_addr, + DIO_FORCE | DIO_START | DIO_WAIT, &bh); + if (error) + goto fail_end_trans; + + di = (struct gfs_dinode *)bh->b_data; + flags = di->di_flags; + flags = gfs32_to_cpu(flags); + if (!(flags & GFS_DIF_UNUSED)) { + gfs_consist_rgrpd(rgd); + brelse(bh); + error = -EIO; + goto fail_end_trans; + } + + gfs_inum_in(&next, (char *)&di->di_next_unused); + + brelse(bh); + + rg->rg_freedi--; + rg->rg_free++; + (*inodes)++; + } + + if (next.no_formal_ino || next.no_addr) { + gfs_consist_rgrpd(rgd); + error = -EIO; + goto fail_end_trans; + } + rg->rg_freedi_list = next; + + goal = 0; + for (x = rg->rg_freemeta; x--;) { + goal = blkalloc_internal(rgd, goal, + GFS_BLKST_FREEMETA, GFS_BLKST_FREE); + rg->rg_freemeta--; + rg->rg_free++; + (*metadata)++; + } + + gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]); + gfs_rgrp_out(rg, rgd->rd_bh[0]->b_data); + + gfs_trans_end(sdp); + + gfs_glock_dq_uninit(&t_gh); + + gfs_glock_dq_uninit(&rgd_gh); + } + + gfs_glock_dq_uninit(&ri_gh); + + gfs_glock_dq_uninit(&ji_gh); + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_unlock_fs: + gfs_glock_dq_uninit(&t_gh); + + fail_gunlock_rg: + gfs_glock_dq_uninit(&rgd_gh); + + fail_rindex_relse: + gfs_glock_dq_uninit(&ri_gh); + + fail_jindex_relse: + gfs_glock_dq_uninit(&ji_gh); + + fail: + return error; +} --- linux-2.6.27.orig/ubuntu/gfs/file.c +++ linux-2.6.27/ubuntu/gfs/file.c @@ -0,0 +1,437 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bmap.h" +#include "dio.h" +#include "file.h" +#include "inode.h" +#include "trans.h" + +/** + * gfs_copy2mem - Trivial copy function for gfs_readi() + * @bh: The buffer to copy from, or NULL meaning zero the buffer + * @buf: The buffer to copy/zero + * @offset: The offset in the buffer to copy from + * @size: The amount of data to copy/zero + * + * Returns: errno + */ + +int +gfs_copy2mem(struct buffer_head *bh, void **buf, unsigned int offset, + unsigned int size) +{ + char **p = (char **)buf; + + if (bh) + memcpy(*p, bh->b_data + offset, size); + else + memset(*p, 0, size); + + *p += size; + + return 0; +} + +/** + * gfs_copy2user - Copy data to user space + * @bh: The buffer + * @buf: The destination of the data + * @offset: The offset into the buffer + * @size: The amount of data to copy + * + * Returns: errno + */ + +int +gfs_copy2user(struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size) +{ + char **p = (char **)buf; + int error; + + if (bh) + error = copy_to_user(*p, bh->b_data + offset, size); + else + error = clear_user(*p, size); + + if (error) + error = -EFAULT; + else + *p += size; + + return error; +} + +/** + * gfs_readi - Read a file + * @ip: The GFS Inode + * @buf: The buffer to place result into + * @offset: File offset to begin reading from + * @size: Amount of data to transfer + * @copy_fn: Function to actually perform the copy + * + * The @copy_fn only copies a maximum of a single block at once so + * we are safe calling it with int arguments. It is done so that + * we don't needlessly put 64bit arguments on the stack and it + * also makes the code in the @copy_fn nicer too. + * + * Returns: The amount of data actually copied or the error + */ + +int +gfs_readi(struct gfs_inode *ip, void *buf, + uint64_t offset, unsigned int size, + read_copy_fn_t copy_fn) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh; + uint64_t lblock, dblock; + unsigned int o; + uint32_t extlen = 0; + unsigned int amount; + int not_new = 0; + int journaled = gfs_is_jdata(ip); + int copied = 0; + int error = 0; + + if (offset >= ip->i_di.di_size) + return 0; + + if ((offset + size) > ip->i_di.di_size) + size = ip->i_di.di_size - offset; + + if (!size) + return 0; + + if (journaled) { + lblock = offset; + o = do_div(lblock, sdp->sd_jbsize); + } else { + lblock = offset >> sdp->sd_sb.sb_bsize_shift; + o = offset & (sdp->sd_sb.sb_bsize - 1); + } + + if (gfs_is_stuffed(ip)) + o += sizeof(struct gfs_dinode); + else if (journaled) + o += sizeof(struct gfs_meta_header); + + while (copied < size) { + amount = size - copied; + if (amount > sdp->sd_sb.sb_bsize - o) + amount = sdp->sd_sb.sb_bsize - o; + + if (!extlen) { + if (!gfs_is_stuffed(ip)) { + error = gfs_block_map(ip, lblock, ¬_new, + &dblock, &extlen); + if (error) + goto fail; + } else if (!lblock) { + dblock = ip->i_num.no_addr; + extlen = 1; + } else + dblock = 0; + } + + if (extlen > 1) + gfs_start_ra(ip->i_gl, dblock, extlen); + + if (dblock) { + error = gfs_get_data_buffer(ip, dblock, not_new, &bh); + if (error) + goto fail; + + dblock++; + extlen--; + } else + bh = NULL; + + error = copy_fn(bh, &buf, o, amount); + if (bh) + brelse(bh); + if (error) + goto fail; + + copied += amount; + lblock++; + + o = (journaled) ? sizeof(struct gfs_meta_header) : 0; + } + + return copied; + + fail: + return (copied) ? copied : error; +} + +/** + * gfs_copy_from_mem - Trivial copy function for gfs_writei() + * @ip: The file to write to + * @bh: The buffer to copy to or clear + * @buf: The buffer to copy from + * @offset: The offset in the buffer to write to + * @size: The amount of data to write + * @new: Flag indicating that remaining space in the buffer should be zeroed + * + * Returns: errno + */ + +int +gfs_copy_from_mem(struct gfs_inode *ip, struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size, int new) +{ + char **p = (char **)buf; + int error = 0; + + /* The dinode block always gets journaled */ + if (bh->b_blocknr == ip->i_num.no_addr) { + if (gfs_assert_warn(ip->i_sbd, !new)) + return -EIO; + gfs_trans_add_bh(ip->i_gl, bh); + memcpy(bh->b_data + offset, *p, size); + + /* Data blocks for journaled files get written added to the journal */ + } else if (gfs_is_jdata(ip)) { + gfs_trans_add_bh(ip->i_gl, bh); + memcpy(bh->b_data + offset, *p, size); + if (new) + gfs_buffer_clear_ends(bh, offset, size, TRUE); + + /* Non-journaled data blocks get written to in-place disk blocks */ + } else { + memcpy(bh->b_data + offset, *p, size); + if (new) + gfs_buffer_clear_ends(bh, offset, size, FALSE); + error = gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY); + } + + if (!error) + *p += size; + + return error; +} + +/** + * gfs_copy_from_user - Copy bytes from user space for gfs_writei() + * @ip: The file to write to + * @bh: The buffer to copy to or clear + * @buf: The buffer to copy from + * @offset: The offset in the buffer to write to + * @size: The amount of data to write + * @new: Flag indicating that remaining space in the buffer should be zeroed + * + * Returns: errno + */ + +int +gfs_copy_from_user(struct gfs_inode *ip, struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size, int new) +{ + char **p = (char **)buf; + int error = 0; + + /* the dinode block always gets journaled */ + if (bh->b_blocknr == ip->i_num.no_addr) { + if (gfs_assert_warn(ip->i_sbd, !new)) + return -EIO; + gfs_trans_add_bh(ip->i_gl, bh); + if (copy_from_user(bh->b_data + offset, *p, size)) + error = -EFAULT; + + /* Data blocks for journaled files get written added to the journal */ + } else if (gfs_is_jdata(ip)) { + gfs_trans_add_bh(ip->i_gl, bh); + if (copy_from_user(bh->b_data + offset, *p, size)) + error = -EFAULT; + if (new) { + gfs_buffer_clear_ends(bh, offset, size, TRUE); + if (error) + memset(bh->b_data + offset, 0, size); + } + + /* non-journaled data blocks get written to in-place disk blocks */ + } else { + if (copy_from_user(bh->b_data + offset, *p, size)) + error = -EFAULT; + if (error) { + if (new) + gfs_buffer_clear(bh); + gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY); + } else { + if (new) + gfs_buffer_clear_ends(bh, offset, size, FALSE); + error = gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY); + } + } + + if (!error) + *p += size; + + return error; +} + +/** + * gfs_writei - Write bytes to a file + * @ip: The GFS inode + * @buf: The buffer containing information to be written + * @offset: The file offset to start writing at + * @size: The amount of data to write + * @copy_fn: Function to do the actual copying + * + * Returns: The number of bytes correctly written or error code + */ + +int +gfs_writei(struct gfs_inode *ip, void *buf, + uint64_t offset, unsigned int size, + write_copy_fn_t copy_fn, + struct kiocb *iocb) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *dibh, *bh; + uint64_t lblock, dblock; + unsigned int o; + uint32_t extlen = 0; + unsigned int amount; + int new; + int journaled = gfs_is_jdata(ip); + const uint64_t start = offset; + int copied = 0; + int error = 0; + + if (!size) + return 0; + + if (gfs_is_stuffed(ip) && + ((start + size) > (sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)))) { + error = gfs_unstuff_dinode(ip, gfs_unstuffer_async, NULL); + if (error) + return error; + } + + if (journaled) { + lblock = offset; + o = do_div(lblock, sdp->sd_jbsize); + } else { + lblock = offset >> sdp->sd_sb.sb_bsize_shift; + o = offset & (sdp->sd_sb.sb_bsize - 1); + } + + if (gfs_is_stuffed(ip)) + o += sizeof(struct gfs_dinode); + else if (journaled) + o += sizeof(struct gfs_meta_header); + + while (copied < size) { + amount = size - copied; + if (amount > sdp->sd_sb.sb_bsize - o) + amount = sdp->sd_sb.sb_bsize - o; + + if (!extlen) { + if (!gfs_is_stuffed(ip)) { + new = TRUE; + error = gfs_block_map(ip, lblock, &new, &dblock, &extlen); + if (error) + goto fail; + } else { + new = FALSE; + dblock = ip->i_num.no_addr; + extlen = 1; + } + } + + if (journaled && extlen > 1) + gfs_start_ra(ip->i_gl, dblock, extlen); + + error = gfs_get_data_buffer(ip, dblock, + (amount == sdp->sd_sb.sb_bsize) ? TRUE : new, + &bh); + if (error) + goto fail; + + error = copy_fn(ip, bh, &buf, o, amount, new); + brelse(bh); + if (error) + goto fail; + + copied += amount; + lblock++; + dblock++; + extlen--; + + o = (journaled) ? sizeof(struct gfs_meta_header) : 0; + } + + out: + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + return error; + + if (ip->i_di.di_size < start + copied) + ip->i_di.di_size = start + copied; + ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + + return copied; + + fail: + if (copied) + goto out; + return error; +} + +/* + * gfs_zero_blocks - zero out disk blocks via gfs_writei() + * @ip: The file to write to + * @bh: The buffer to clear + * @buf: The pseudo buffer (not used but added to keep interface unchanged) + * @offset: The offset in the buffer to write to + * @size: The size to zero out + * @new: Flag indicating that remaining space in the buffer should be zeroed + * + * Returns: 0 on success, -EXXX on failure + */ + +int +gfs_zero_blocks(struct gfs_inode *ip, struct buffer_head *bh, void **buf, + unsigned int offset, unsigned int size, int new) +{ + int error = 0; + + /* The dinode block always gets journaled */ + if (bh->b_blocknr == ip->i_num.no_addr) { + if (gfs_assert_warn(ip->i_sbd, !new)) + return -EIO; + gfs_trans_add_bh(ip->i_gl, bh); + memset((bh)->b_data + offset, 0, size); + + /* Data blocks for journaled files get written added to the journal */ + } else if (gfs_is_jdata(ip)) { + gfs_trans_add_bh(ip->i_gl, bh); + memset((bh)->b_data + offset, 0, size); + if (new) + gfs_buffer_clear_ends(bh, offset, size, TRUE); + + /* Non-journaled data blocks get written to in-place disk blocks */ + } else { + memset((bh)->b_data + offset, 0, size); + if (new) + gfs_buffer_clear_ends(bh, offset, size, FALSE); + error = gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY); + } + + return error; +} + --- linux-2.6.27.orig/ubuntu/gfs/glock.c +++ linux-2.6.27/ubuntu/gfs/glock.c @@ -0,0 +1,2996 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "lm.h" +#include "lops.h" +#include "quota.h" +#include "recovery.h" + +/* Must be kept in sync with the beginning of struct gfs_glock */ +struct glock_plug { + struct list_head gl_list; + unsigned long gl_flags; +}; + +struct greedy { + struct gfs_holder gr_gh; + struct delayed_work gr_work; +}; + +typedef void (*glock_examiner) (struct gfs_glock * gl, unsigned int *cnt); + +/** + * relaxed_state_ok - is a requested lock compatible with the current lock mode? + * @actual: the current state of the lock + * @requested: the lock state that was requested by the caller + * @flags: the modifier flags passed in by the caller + * + * Returns: TRUE if the locks are compatible, FALSE otherwise + * + * It's often possible that a holder B may request the lock in SHARED mode, + * while another holder A (on this same node) has the lock in EXCLUSIVE mode + * (node must hold the glock in EXCLUSIVE mode for this situation, of course). + * This is okay to grant, in some cases, since both holders would have access + * to the in-core up-to-date cached data that the EX holder would write to disk. + * This is the default behavior. + * + * The EXACT flag disallows this behavior, though. A SHARED request would + * compatible only with a SHARED lock with this flag. + * + * The ANY flag provides broader permission to grant the lock to a holder, + * whatever the requested state is, as long as the lock is locked in any mode. + */ + +static __inline__ int +relaxed_state_ok(unsigned int actual, unsigned requested, int flags) +{ + if (actual == requested) + return TRUE; + + if (flags & GL_EXACT) + return FALSE; + + if (actual == LM_ST_EXCLUSIVE && requested == LM_ST_SHARED) + return TRUE; + + if (actual != LM_ST_UNLOCKED && (flags & LM_FLAG_ANY)) + return TRUE; + + return FALSE; +} + +/** + * gl_hash() - Turn glock number into hash bucket number + * @lock: The glock number + * + * Returns: The number of the corresponding hash bucket + */ + +static unsigned int +gl_hash(struct lm_lockname *name) +{ + unsigned int h; + + h = gfs_hash(&name->ln_number, sizeof(uint64_t)); + h = gfs_hash_more(&name->ln_type, sizeof(unsigned int), h); + h &= GFS_GL_HASH_MASK; + + return h; +} + +/** + * glock_hold() - increment reference count on glock + * @gl: The glock to hold + * + */ + +static __inline__ void +glock_hold(struct gfs_glock *gl) +{ + gfs_assert(gl->gl_sbd, atomic_read(&gl->gl_count) > 0,); + atomic_inc(&gl->gl_count); +} + +/** + * glock_put() - Decrement reference count on glock + * @gl: The glock to put + * + */ + +static __inline__ void +glock_put(struct gfs_glock *gl) +{ + if (atomic_read(&gl->gl_count) == 1) + gfs_glock_schedule_for_reclaim(gl); + gfs_assert(gl->gl_sbd, atomic_read(&gl->gl_count) > 0,); + atomic_dec(&gl->gl_count); +} + +/** + * queue_empty - check to see if a glock's queue is empty + * @gl: the glock + * @head: the head of the queue to check + * + * Returns: TRUE if the queue is empty + */ + +static __inline__ int +queue_empty(struct gfs_glock *gl, struct list_head *head) +{ + int empty; + spin_lock(&gl->gl_spin); + empty = list_empty(head); + spin_unlock(&gl->gl_spin); + return empty; +} + +/** + * search_bucket() - Find struct gfs_glock by lock number + * @bucket: the bucket to search + * @name: The lock name + * + * Returns: NULL, or the struct gfs_glock with the requested number + */ + +static struct gfs_glock * +search_bucket(struct gfs_gl_hash_bucket *bucket, struct lm_lockname *name) +{ + struct list_head *tmp, *head; + struct gfs_glock *gl; + + for (head = &bucket->hb_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gl = list_entry(tmp, struct gfs_glock, gl_list); + + if (test_bit(GLF_PLUG, &gl->gl_flags)) + continue; + if (!lm_name_equal(&gl->gl_name, name)) + continue; + + atomic_inc(&gl->gl_count); + + return gl; + } + + return NULL; +} + +/** + * gfs_glock_find() - Find glock by lock number + * @sdp: The GFS superblock + * @name: The lock name + * + * Figure out what bucket the lock is in, acquire the read lock on + * it and call search_bucket(). + * + * Returns: NULL, or the struct gfs_glock with the requested number + */ + +struct gfs_glock * +gfs_glock_find(struct gfs_sbd *sdp, struct lm_lockname *name) +{ + struct gfs_gl_hash_bucket *bucket = &sdp->sd_gl_hash[gl_hash(name)]; + struct gfs_glock *gl; + + read_lock(&bucket->hb_lock); + gl = search_bucket(bucket, name); + read_unlock(&bucket->hb_lock); + + return gl; +} + +/** + * glock_free() - Perform a few checks and then release struct gfs_glock + * @gl: The glock to release + * + * Also calls lock module to release its internal structure for this glock. + * + */ + +static void +glock_free(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct inode *aspace = gl->gl_aspace; + + gfs_assert_warn(sdp, list_empty(&gl->gl_list)); + gfs_assert_warn(sdp, atomic_read(&gl->gl_count) == 1); + gfs_assert_warn(sdp, list_empty(&gl->gl_holders)); + gfs_assert_warn(sdp, list_empty(&gl->gl_waiters1)); + gfs_assert_warn(sdp, list_empty(&gl->gl_waiters2)); + gfs_assert_warn(sdp, list_empty(&gl->gl_waiters3)); + gfs_assert_warn(sdp, gl->gl_state == LM_ST_UNLOCKED); + gfs_assert_warn(sdp, !gl->gl_object); + gfs_assert_warn(sdp, !gl->gl_lvb); + gfs_assert_warn(sdp, list_empty(&gl->gl_reclaim)); + + gfs_lm_put_lock(sdp, gl->gl_lock); + + if (aspace) + gfs_aspace_put(aspace); + + kmem_cache_free(gfs_glock_cachep, gl); + + atomic_dec(&sdp->sd_glock_count); +} + +/** + * gfs_glock_get() - Get a glock, or create one if one doesn't exist + * @sdp: The GFS superblock + * @number: the lock number + * @glops: The glock_operations to use + * @create: If FALSE, don't create the glock if it doesn't exist + * @glp: the glock is returned here + * + * This does not lock a glock, just finds/creates structures for one. + * + * Returns: errno + */ + +int +gfs_glock_get(struct gfs_sbd *sdp, + uint64_t number, struct gfs_glock_operations *glops, + int create, struct gfs_glock **glp) +{ + struct lm_lockname name; + struct gfs_glock *gl, *tmp; + struct gfs_gl_hash_bucket *bucket; + int error; + + /* Look for pre-existing glock in hash table */ + name.ln_number = number; + name.ln_type = glops->go_type; + bucket = &sdp->sd_gl_hash[gl_hash(&name)]; + + read_lock(&bucket->hb_lock); + gl = search_bucket(bucket, &name); + read_unlock(&bucket->hb_lock); + + if (gl || !create) { + *glp = gl; + return 0; + } + + /* None found; create a new one */ + gl = kmem_cache_alloc(gfs_glock_cachep, GFP_KERNEL); + if (!gl) + return -ENOMEM; + + memset(gl, 0, sizeof(struct gfs_glock)); + + INIT_LIST_HEAD(&gl->gl_list); + gl->gl_name = name; + atomic_set(&gl->gl_count, 1); + + spin_lock_init(&gl->gl_spin); + + gl->gl_state = LM_ST_UNLOCKED; + INIT_LIST_HEAD(&gl->gl_holders); + INIT_LIST_HEAD(&gl->gl_waiters1); + INIT_LIST_HEAD(&gl->gl_waiters2); + INIT_LIST_HEAD(&gl->gl_waiters3); + + gl->gl_ops = glops; + + INIT_LE(&gl->gl_new_le, &gfs_glock_lops); + INIT_LE(&gl->gl_incore_le, &gfs_glock_lops); + + gl->gl_bucket = bucket; + INIT_LIST_HEAD(&gl->gl_reclaim); + + gl->gl_sbd = sdp; + + INIT_LIST_HEAD(&gl->gl_ail_bufs); + + /* If this glock protects actual on-disk data or metadata blocks, + create a VFS inode to manage the pages/buffers holding them. */ + if (glops == &gfs_inode_glops || + glops == &gfs_rgrp_glops || + glops == &gfs_meta_glops) { + gl->gl_aspace = gfs_aspace_get(sdp); + if (!gl->gl_aspace) { + error = -ENOMEM; + goto fail; + } + } + + /* Ask lock module to find/create its structure for this lock + (but this doesn't lock the inter-node lock yet) */ + error = gfs_lm_get_lock(sdp, &name, &gl->gl_lock); + if (error) + goto fail_aspace; + + atomic_inc(&sdp->sd_glock_count); + + /* Double-check, in case another process created the glock, and has + put it in the hash table while we were preparing this one */ + write_lock(&bucket->hb_lock); + tmp = search_bucket(bucket, &name); + if (tmp) { + /* Somebody beat us to it; forget the one we prepared */ + write_unlock(&bucket->hb_lock); + glock_free(gl); + gl = tmp; + } else { + /* Add our glock to hash table */ + list_add_tail(&gl->gl_list, &bucket->hb_list); + write_unlock(&bucket->hb_lock); + } + + *glp = gl; + + return 0; + + fail_aspace: + if (gl->gl_aspace) + gfs_aspace_put(gl->gl_aspace); + + fail: + kmem_cache_free(gfs_glock_cachep, gl); + + return error; +} + +/** + * gfs_glock_hold() - As glock_hold(), but suitable for exporting + * @gl: The glock to hold + * + */ + +void +gfs_glock_hold(struct gfs_glock *gl) +{ + glock_hold(gl); +} + +/** + * gfs_glock_put() - As glock_put(), but suitable for exporting + * @gl: The glock to put + * + */ + +void +gfs_glock_put(struct gfs_glock *gl) +{ + glock_put(gl); +} + +/** + * gfs_holder_init - initialize a struct gfs_holder in the default way + * @gl: the glock + * @state: the state we're requesting + * @flags: the modifier flags + * @gh: the holder structure + * + */ + +void +gfs_holder_init(struct gfs_glock *gl, unsigned int state, int flags, + struct gfs_holder *gh) +{ + memset(gh, 0, sizeof(struct gfs_holder)); + + INIT_LIST_HEAD(&gh->gh_list); + gh->gh_gl = gl; + gh->gh_owner = current; + gh->gh_state = state; + gh->gh_flags = flags; + + if (gh->gh_state == LM_ST_EXCLUSIVE) + gh->gh_flags |= GL_LOCAL_EXCL; + + init_completion(&gh->gh_wait); + + glock_hold(gl); +} + +/** + * gfs_holder_reinit - reinitialize a struct gfs_holder so we can requeue it + * @state: the state we're requesting + * @flags: the modifier flags + * @gh: the holder structure + * + * Preserve holder's associated glock and owning process. + * Reset all holder state flags (we're starting a new request from scratch), + * except for HIF_ALLOCED. + * Don't do glock_hold() again (it was done in gfs_holder_init()). + * Don't mess with the glock. + * + * Rules: + * Holder must have been gfs_holder_init()d already + * Holder must *not* be in glock's holder list or wait queues now + */ + +void +gfs_holder_reinit(unsigned int state, int flags, struct gfs_holder *gh) +{ + int alloced; + + gfs_assert_warn(gh->gh_gl->gl_sbd, + list_empty(&gh->gh_list)); + + gh->gh_state = state; + gh->gh_flags = flags; + + if (gh->gh_state == LM_ST_EXCLUSIVE) + gh->gh_flags |= GL_LOCAL_EXCL; + + alloced = test_bit(HIF_ALLOCED, &gh->gh_iflags); + memset(&gh->gh_iflags, 0, sizeof(unsigned long)); + if (alloced) + set_bit(HIF_ALLOCED, &gh->gh_iflags); +} + +/** + * gfs_holder_uninit - uninitialize a holder structure (drop reference on glock) + * @gh: the holder structure + * + */ + +void +gfs_holder_uninit(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + + gfs_assert_warn(gl->gl_sbd, list_empty(&gh->gh_list)); + gh->gh_gl = NULL; + + glock_put(gl); +} + +/** + * gfs_holder_get - get a struct gfs_holder structure + * @gl: the glock + * @state: the state we're requesting + * @flags: the modifier flags + * + * Figure out how big an impact this function has. Either: + * 1) Replace it with a cache of structures hanging off the struct gfs_sbd + * 2) Leave it like it is + * + * Returns: the holder structure, NULL on ENOMEM + */ + +struct gfs_holder * +gfs_holder_get(struct gfs_glock *gl, unsigned int state, int flags) +{ + struct gfs_holder *gh; + + gh = kmalloc(sizeof(struct gfs_holder), GFP_KERNEL); + if (!gh) + return NULL; + + gfs_holder_init(gl, state, flags, gh); + set_bit(HIF_ALLOCED, &gh->gh_iflags); + + return gh; +} + +/** + * gfs_holder_put - get rid of a struct gfs_holder structure + * @gh: the holder structure + * + */ + +void +gfs_holder_put(struct gfs_holder *gh) +{ + if (gfs_assert_warn(gh->gh_gl->gl_sbd, + test_bit(HIF_ALLOCED, &gh->gh_iflags))) + return; + gfs_holder_uninit(gh); + kfree(gh); +} + +/** + * handle_recurse - put other holder structures (marked recursive) into the holders list + * @gh: the holder structure + * + */ + +static void +handle_recurse(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + struct list_head *tmp, *head, *next; + struct gfs_holder *tmp_gh; + int found = FALSE; + + if (gfs_assert_warn(sdp, gh->gh_owner)) + return; + + for (head = &gl->gl_waiters3, tmp = head->next, next = tmp->next; + tmp != head; + tmp = next, next = tmp->next) { + tmp_gh = list_entry(tmp, struct gfs_holder, gh_list); + if (tmp_gh->gh_owner != gh->gh_owner) + continue; + + gfs_assert_warn(sdp, test_bit(HIF_RECURSE, &tmp_gh->gh_iflags)); + + list_move_tail(&tmp_gh->gh_list, &gl->gl_holders); + tmp_gh->gh_error = 0; + set_bit(HIF_HOLDER, &tmp_gh->gh_iflags); + + complete(&tmp_gh->gh_wait); + + found = TRUE; + } + + gfs_assert_warn(sdp, found); +} + +/** + * do_unrecurse - a recursive holder was just dropped of the waiters3 list + * @gh: the holder + * + * If there is only one other recursive holder, clear its HIF_RECURSE bit + * (it's no longer a recursive request). + * If there is more than one, leave them alone (they're recursive!). + * + */ + +static void +do_unrecurse(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + struct list_head *tmp, *head; + struct gfs_holder *tmp_gh, *last_gh = NULL; + int found = FALSE; + + if (gfs_assert_warn(sdp, gh->gh_owner)) + return; + + for (head = &gl->gl_waiters3, tmp = head->next; + tmp != head; + tmp = tmp->next) { + tmp_gh = list_entry(tmp, struct gfs_holder, gh_list); + if (tmp_gh->gh_owner != gh->gh_owner) + continue; + + gfs_assert_warn(sdp, test_bit(HIF_RECURSE, &tmp_gh->gh_iflags)); + + /* found more than one */ + if (found) + return; + + found = TRUE; + last_gh = tmp_gh; + } + + /* found just one */ + if (!gfs_assert_warn(sdp, found)) + clear_bit(HIF_RECURSE, &last_gh->gh_iflags); +} + +/** + * rq_mutex - process a mutex request in the queue + * @gh: the glock holder + * + * Returns: TRUE if the queue is blocked (always, since there can be only one + * holder of the mutex). + * + * See lock_on_glock() + */ + +static int +rq_mutex(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + + list_del_init(&gh->gh_list); + /* gh->gh_error never examined. */ + set_bit(GLF_LOCK, &gl->gl_flags); + complete(&gh->gh_wait); + + return TRUE; +} + +/** + * rq_promote - process a promote request in the queue + * @gh: the glock holder + * + * Acquire a new inter-node lock, or change a lock state to more restrictive. + * + * Returns: TRUE if the queue is blocked + */ + +static int +rq_promote(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + int recurse; + + if (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) { + if (list_empty(&gl->gl_holders)) { + gl->gl_req_gh = gh; + set_bit(GLF_LOCK, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + + /* If we notice a lot of glocks in reclaim list, free + up memory for 2 of them before locking a new one */ + if (atomic_read(&sdp->sd_reclaim_count) > + gfs_tune_get(sdp, gt_reclaim_limit) && + !(gh->gh_flags & LM_FLAG_PRIORITY)) { + gfs_reclaim_glock(sdp); + gfs_reclaim_glock(sdp); + } + + glops->go_xmote_th(gl, gh->gh_state, + gh->gh_flags); + + spin_lock(&gl->gl_spin); + } + return TRUE; + } + + if (list_empty(&gl->gl_holders)) { + set_bit(HIF_FIRST, &gh->gh_iflags); + set_bit(GLF_LOCK, &gl->gl_flags); + recurse = FALSE; + } else { + struct gfs_holder *next_gh; + if (gh->gh_flags & GL_LOCAL_EXCL) + return TRUE; + next_gh = list_entry(gl->gl_holders.next, struct gfs_holder, gh_list); + if (next_gh->gh_flags & GL_LOCAL_EXCL) + return TRUE; + recurse = test_bit(HIF_RECURSE, &gh->gh_iflags); + } + + list_move_tail(&gh->gh_list, &gl->gl_holders); + gh->gh_error = 0; + set_bit(HIF_HOLDER, &gh->gh_iflags); + + if (recurse) + handle_recurse(gh); + + complete(&gh->gh_wait); + + return FALSE; +} + +/** + * rq_demote - process a demote request in the queue + * @gh: the glock holder + * + * Returns: TRUE if the queue is blocked + * + * Unlock an inter-node lock, or change a lock state to less restrictive. + * If the glock is already the same as the holder's requested state, or is + * UNLOCKED, no lock module request is required. + * Otherwise, we need to ask lock module to unlock or change locked state + * of the glock. + * If requested state is UNLOCKED, or current glock state is SHARED or + * DEFERRED (neither of which have a less restrictive state other than + * UNLOCK), we call go_drop_th() to unlock the lock. + * Otherwise (i.e. requested is SHARED or DEFERRED, and current is EXCLUSIVE), + * we can continue to hold the lock, and just ask for a new state; + * we call go_xmote_th() to change state. + * + * Must be called with glock's gl->gl_spin locked. + */ + +static int +rq_demote(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_glock_operations *glops = gl->gl_ops; + + if (!list_empty(&gl->gl_holders)) + return TRUE; + + if (gl->gl_state == gh->gh_state || gl->gl_state == LM_ST_UNLOCKED) { + list_del_init(&gh->gh_list); + gh->gh_error = 0; + spin_unlock(&gl->gl_spin); + if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) + gfs_holder_put(gh); + else + complete(&gh->gh_wait); + spin_lock(&gl->gl_spin); + } else { + gl->gl_req_gh = gh; + set_bit(GLF_LOCK, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + + if (gh->gh_state == LM_ST_UNLOCKED || + gl->gl_state != LM_ST_EXCLUSIVE) + /* Unlock */ + glops->go_drop_th(gl); + else + /* Change state while holding lock */ + glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags); + + spin_lock(&gl->gl_spin); + } + + return FALSE; +} + +/** + * rq_greedy - process a queued request to drop greedy status + * @gh: the glock holder + * + * Returns: TRUE if the queue is blocked + */ + +static int +rq_greedy(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + + list_del_init(&gh->gh_list); + /* gh->gh_error never examined. */ + clear_bit(GLF_GREEDY, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + + gfs_holder_uninit(gh); + kfree(container_of(gh, struct greedy, gr_gh)); + + spin_lock(&gl->gl_spin); + + return FALSE; +} + +/** + * run_queue - process holder structures on the glock's wait queues + * @gl: the glock + * + * Rules: + * Caller must hold gl->gl_spin. + */ + +static void +run_queue(struct gfs_glock *gl) +{ + struct gfs_holder *gh; + int blocked = TRUE; + + for (;;) { + /* Another process is manipulating the glock structure; + we can't do anything now */ + if (test_bit(GLF_LOCK, &gl->gl_flags)) + break; + + /* Waiting to manipulate the glock structure */ + if (!list_empty(&gl->gl_waiters1)) { + gh = list_entry(gl->gl_waiters1.next, + struct gfs_holder, gh_list); + + if (test_bit(HIF_MUTEX, &gh->gh_iflags)) + blocked = rq_mutex(gh); + else + gfs_assert_warn(gl->gl_sbd, FALSE); + + /* Waiting to demote the lock, or drop greedy status */ + } else if (!list_empty(&gl->gl_waiters2) && + !test_bit(GLF_SKIP_WAITERS2, &gl->gl_flags)) { + gh = list_entry(gl->gl_waiters2.next, + struct gfs_holder, gh_list); + + if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) + blocked = rq_demote(gh); + else if (test_bit(HIF_GREEDY, &gh->gh_iflags)) + blocked = rq_greedy(gh); + else + gfs_assert_warn(gl->gl_sbd, FALSE); + + /* Waiting to promote the lock */ + } else if (!list_empty(&gl->gl_waiters3)) { + gh = list_entry(gl->gl_waiters3.next, + struct gfs_holder, gh_list); + + if (test_bit(HIF_PROMOTE, &gh->gh_iflags)) + blocked = rq_promote(gh); + else + gfs_assert_warn(gl->gl_sbd, FALSE); + + } else + break; + + if (blocked) + break; + } +} + +/** + * lock_on_glock - acquire a local lock on a glock (structure) + * @gl: the glock + * + * Gives caller exclusive access to manipulate a glock structure. + * Has nothing to do with inter-node lock state or GL_LOCAL_EXCL! + * + * If structure already locked, places temporary holder structure on glock's + * wait-for-exclusive-access queue, and blocks until exclusive access granted. + */ + +static void +lock_on_glock(struct gfs_glock *gl) +{ + struct gfs_holder gh; + + gfs_holder_init(gl, 0, 0, &gh); + set_bit(HIF_MUTEX, &gh.gh_iflags); + + spin_lock(&gl->gl_spin); + if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) + list_add_tail(&gh.gh_list, &gl->gl_waiters1); + else + complete(&gh.gh_wait); + spin_unlock(&gl->gl_spin); + + wait_for_completion(&gh.gh_wait); + gfs_holder_uninit(&gh); +} + +/** + * trylock_on_glock - try to acquire a local lock on a glock (structure) + * @gl: the glock + * + * Returns: TRUE if the glock is acquired + * + * Tries to give caller exclusive access to manipulate a glock structure. + * Has nothing to do with inter-node lock state or LOCAL_EXCL! + * + * If structure already locked, does not block to wait; returns FALSE. + */ + +static int +trylock_on_glock(struct gfs_glock *gl) +{ + int acquired = TRUE; + + spin_lock(&gl->gl_spin); + if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) + acquired = FALSE; + spin_unlock(&gl->gl_spin); + + return acquired; +} + +/** + * unlock_on_glock - release a local lock on a glock (structure) + * @gl: the glock + * + * Caller is done manipulating glock structure. + * Service any others waiting for exclusive access. + */ + +static void +unlock_on_glock(struct gfs_glock *gl) +{ + spin_lock(&gl->gl_spin); + clear_bit(GLF_LOCK, &gl->gl_flags); + run_queue(gl); + spin_unlock(&gl->gl_spin); +} + +/** + * handle_callback - add a demote request to a lock's queue + * @gl: the glock + * @state: the state the caller wants us to change to + * + * Called when we learn that another node needs a lock held by this node, + * or when this node simply wants to drop a lock as soon as it's done with + * it (NOCACHE flag), or dump a glock out of glock cache (reclaim it). + * + * We are told the @state that will satisfy the needs of the caller, so + * we can ask for a demote to that state. + * + * If another demote request is already on the queue for a different state, just + * set its request to UNLOCK (and don't bother queueing a request for us). + * This consolidates LM requests and moves the lock to the least restrictive + * state, so it will be compatible with whatever reason we were called. + * No need to be too smart here. Demotes between the shared and deferred + * states will often fail, so don't even try. + * + * Otherwise, queue a demote request to the requested state. + */ + +static void +handle_callback(struct gfs_glock *gl, unsigned int state) +{ + struct list_head *tmp, *head; + struct gfs_holder *gh, *new_gh = NULL; + + if (gfs_assert_warn(gl->gl_sbd, state != LM_ST_EXCLUSIVE)) + return; + + restart: + spin_lock(&gl->gl_spin); + + /* If another queued demote request is for a different state, + set its request to UNLOCKED */ + for (head = &gl->gl_waiters2, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gh = list_entry(tmp, struct gfs_holder, gh_list); + if (test_bit(HIF_DEMOTE, &gh->gh_iflags) && + gl->gl_req_gh != gh) { + if (gh->gh_state != state) + gh->gh_state = LM_ST_UNLOCKED; + goto out; + } + } + + /* pass 2; add new holder to glock's demote request queue */ + if (new_gh) { + list_add_tail(&new_gh->gh_list, &gl->gl_waiters2); + new_gh = NULL; + + /* pass 1; set up a new holder struct for a demote request, then + check again to see if another process added a demote request + while we were preparing this one. */ + } else { + spin_unlock(&gl->gl_spin); + + RETRY_MALLOC(new_gh = gfs_holder_get(gl, state, LM_FLAG_TRY), + new_gh); + set_bit(HIF_DEMOTE, &new_gh->gh_iflags); + set_bit(HIF_DEALLOC, &new_gh->gh_iflags); + new_gh->gh_owner = NULL; + + goto restart; + } + + out: + spin_unlock(&gl->gl_spin); + + if (new_gh) + gfs_holder_put(new_gh); +} + +/** + * state_change - record that the glock is now in a different state + * @gl: the glock + * @new_state the new state + * + */ + +static void +state_change(struct gfs_glock *gl, unsigned int new_state) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + int held1, held2; + + held1 = (gl->gl_state != LM_ST_UNLOCKED); + held2 = (new_state != LM_ST_UNLOCKED); + + if (held1 != held2) { + if (held2) { + atomic_inc(&sdp->sd_glock_held_count); + glock_hold(gl); + } else { + atomic_dec(&sdp->sd_glock_held_count); + glock_put(gl); + } + } + + gl->gl_state = new_state; +} + +/** + * xmote_bh - Called after the lock module is done acquiring a lock + * @gl: The glock in question + * @ret: the int returned from the lock module + * + */ + +static void +xmote_bh(struct gfs_glock *gl, unsigned int ret) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + struct gfs_holder *gh = gl->gl_req_gh; + int prev_state = gl->gl_state; + int op_done = TRUE; + + gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); + gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); + gfs_assert_warn(sdp, !(ret & LM_OUT_ASYNC)); + + state_change(gl, ret & LM_OUT_ST_MASK); + + if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) { + if (glops->go_inval) + glops->go_inval(gl, DIO_METADATA | DIO_DATA); + } else if (gl->gl_state == LM_ST_DEFERRED) { + /* We might not want to do this here. + Look at moving to the inode glops. */ + if (glops->go_inval) + glops->go_inval(gl, DIO_DATA); + } + + /* Deal with each possible exit condition */ + + if (!gh) + gl->gl_stamp = jiffies; + + else if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) { + spin_lock(&gl->gl_spin); + list_del_init(&gh->gh_list); + gh->gh_error = -EIO; + if (test_bit(HIF_RECURSE, &gh->gh_iflags)) + do_unrecurse(gh); + spin_unlock(&gl->gl_spin); + + } else if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) { + spin_lock(&gl->gl_spin); + list_del_init(&gh->gh_list); + if (gl->gl_state == gh->gh_state || + gl->gl_state == LM_ST_UNLOCKED) + gh->gh_error = 0; + else { + if (gfs_assert_warn(sdp, gh->gh_flags & + (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) == -1) + printk("GFS: fsid=%s: ret = 0x%.8X\n", + sdp->sd_fsname, ret); + gh->gh_error = GLR_TRYFAILED; + } + spin_unlock(&gl->gl_spin); + + if (ret & LM_OUT_CANCELED) + handle_callback(gl, LM_ST_UNLOCKED); /* Lame */ + + } else if (ret & LM_OUT_CANCELED) { + spin_lock(&gl->gl_spin); + list_del_init(&gh->gh_list); + gh->gh_error = GLR_CANCELED; + if (test_bit(HIF_RECURSE, &gh->gh_iflags)) + do_unrecurse(gh); + spin_unlock(&gl->gl_spin); + + } else if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) { + spin_lock(&gl->gl_spin); + list_move_tail(&gh->gh_list, &gl->gl_holders); + gh->gh_error = 0; + set_bit(HIF_HOLDER, &gh->gh_iflags); + spin_unlock(&gl->gl_spin); + + set_bit(HIF_FIRST, &gh->gh_iflags); + + op_done = FALSE; + + } else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { + spin_lock(&gl->gl_spin); + list_del_init(&gh->gh_list); + gh->gh_error = GLR_TRYFAILED; + if (test_bit(HIF_RECURSE, &gh->gh_iflags)) + do_unrecurse(gh); + spin_unlock(&gl->gl_spin); + + } else { + if (gfs_assert_withdraw(sdp, FALSE) == -1) + printk("GFS: fsid=%s: ret = 0x%.8X\n", + sdp->sd_fsname, ret); + } + + if (glops->go_xmote_bh) + glops->go_xmote_bh(gl); + + if (op_done) { + spin_lock(&gl->gl_spin); + gl->gl_req_gh = NULL; + gl->gl_req_bh = NULL; + clear_bit(GLF_LOCK, &gl->gl_flags); + run_queue(gl); + spin_unlock(&gl->gl_spin); + } + + glock_put(gl); + + if (gh) { + if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) + gfs_holder_put(gh); + else + complete(&gh->gh_wait); + } +} + +/** + * gfs_glock_xmote_th - Call into the lock module to acquire or change a glock + * @gl: The glock in question + * @state: the requested state + * @flags: modifier flags to the lock call + * + * Used to acquire a new glock, or to change an already-acquired glock to + * more/less restrictive state (other than LM_ST_UNLOCKED). + * + * *Not* used to unlock a glock; use gfs_glock_drop_th() for that. + */ + +void +gfs_glock_xmote_th(struct gfs_glock *gl, unsigned int state, int flags) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB | + LM_FLAG_NOEXP | LM_FLAG_ANY | + LM_FLAG_PRIORITY); + unsigned int lck_ret; + + gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); + gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); + gfs_assert_warn(sdp, state != LM_ST_UNLOCKED); + gfs_assert_warn(sdp, state != gl->gl_state); + + /* Current state EX, may need to sync log/data/metadata to disk */ + if (gl->gl_state == LM_ST_EXCLUSIVE) { + if (glops->go_sync) + glops->go_sync(gl, DIO_METADATA | DIO_DATA); + } + + glock_hold(gl); + gl->gl_req_bh = xmote_bh; + + atomic_inc(&sdp->sd_lm_lock_calls); + + lck_ret = gfs_lm_lock(sdp, gl->gl_lock, + gl->gl_state, state, + lck_flags); + + if (gfs_assert_withdraw(sdp, !(lck_ret & LM_OUT_ERROR))) + goto out; + + if (lck_ret & LM_OUT_ASYNC) + gfs_assert_warn(sdp, lck_ret == LM_OUT_ASYNC); + else + xmote_bh(gl, lck_ret); + out: + return; +} + +/** + * drop_bh - Called after a lock module unlock completes + * @gl: the glock + * @ret: the return status + * + * Doesn't wake up the process waiting on the struct gfs_holder (if any) + * Doesn't drop the reference on the glock the top half took out + * + */ + +static void +drop_bh(struct gfs_glock *gl, unsigned int ret) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + struct gfs_holder *gh = gl->gl_req_gh; + + clear_bit(GLF_PREFETCH, &gl->gl_flags); + + gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); + gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); + gfs_assert_warn(sdp, !ret); + + state_change(gl, LM_ST_UNLOCKED); + + if (glops->go_inval) + glops->go_inval(gl, DIO_METADATA | DIO_DATA); + + if (gh) { + spin_lock(&gl->gl_spin); + list_del_init(&gh->gh_list); + gh->gh_error = 0; + spin_unlock(&gl->gl_spin); + } + + if (glops->go_drop_bh) + glops->go_drop_bh(gl); + + spin_lock(&gl->gl_spin); + gl->gl_req_gh = NULL; + gl->gl_req_bh = NULL; + clear_bit(GLF_LOCK, &gl->gl_flags); + run_queue(gl); + spin_unlock(&gl->gl_spin); + + glock_put(gl); + + if (gh) { + if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) + gfs_holder_put(gh); + else + complete(&gh->gh_wait); + } +} + +/** + * gfs_glock_drop_th - call into the lock module to unlock a lock + * @gl: the glock + * + */ + +void +gfs_glock_drop_th(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + unsigned int ret; + + gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); + gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); + gfs_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED); + + /* Leaving state EX, may need to sync log/data/metadata to disk */ + if (gl->gl_state == LM_ST_EXCLUSIVE) { + if (glops->go_sync) + glops->go_sync(gl, DIO_METADATA | DIO_DATA); + } + + glock_hold(gl); + gl->gl_req_bh = drop_bh; + + atomic_inc(&sdp->sd_lm_unlock_calls); + + ret = gfs_lm_unlock(sdp, gl->gl_lock, gl->gl_state); + + if (gfs_assert_withdraw(sdp, !(ret & LM_OUT_ERROR))) + goto out; + + if (!ret) + drop_bh(gl, ret); + else + gfs_assert_warn(sdp, ret == LM_OUT_ASYNC); + out: + return; +} + +/** + * do_cancels - cancel requests for locks stuck waiting on an expire flag + * @gh: the LM_FLAG_PRIORITY holder waiting to acquire the lock + * + * Don't cancel GL_NOCANCEL requests. + */ + +static void +do_cancels(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + + spin_lock(&gl->gl_spin); + + while (gl->gl_req_gh != gh && + !test_bit(HIF_HOLDER, &gh->gh_iflags) && + !list_empty(&gh->gh_list)) { + if (gl->gl_req_bh && + !(gl->gl_req_gh && + (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) { + spin_unlock(&gl->gl_spin); + gfs_lm_cancel(gl->gl_sbd, gl->gl_lock); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 10); + spin_lock(&gl->gl_spin); + } else { + spin_unlock(&gl->gl_spin); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 10); + spin_lock(&gl->gl_spin); + } + } + + spin_unlock(&gl->gl_spin); +} + +/** + * glock_wait_internal - wait on a glock acquisition + * @gh: the glock holder + * + * Returns: 0 on success + */ + +static int +glock_wait_internal(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + int error = 0; + + if (test_bit(HIF_ABORTED, &gh->gh_iflags)) + return -EIO; + + if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { + spin_lock(&gl->gl_spin); + if (gl->gl_req_gh != gh && + !test_bit(HIF_HOLDER, &gh->gh_iflags) && + !list_empty(&gh->gh_list)) { + list_del_init(&gh->gh_list); + gh->gh_error = GLR_TRYFAILED; + if (test_bit(HIF_RECURSE, &gh->gh_iflags)) + do_unrecurse(gh); + run_queue(gl); + spin_unlock(&gl->gl_spin); + return GLR_TRYFAILED; + } + spin_unlock(&gl->gl_spin); + } + + if ((gh->gh_flags & LM_FLAG_PRIORITY) && + !(gh->gh_flags & GL_NOCANCEL_OTHER)) + do_cancels(gh); + + wait_for_completion(&gh->gh_wait); + + if (gh->gh_error) + return gh->gh_error; + + gfs_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags)); + gfs_assert_withdraw(sdp, relaxed_state_ok(gl->gl_state, + gh->gh_state, + gh->gh_flags)); + + if (test_bit(HIF_FIRST, &gh->gh_iflags)) { + gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); + + if (glops->go_lock) { + error = glops->go_lock(gl, gh->gh_flags); + if (error) { + spin_lock(&gl->gl_spin); + list_del_init(&gh->gh_list); + gh->gh_error = error; + if (test_and_clear_bit(HIF_RECURSE, &gh->gh_iflags)) + do_unrecurse(gh); + spin_unlock(&gl->gl_spin); + } + } + + spin_lock(&gl->gl_spin); + gl->gl_req_gh = NULL; + gl->gl_req_bh = NULL; + clear_bit(GLF_LOCK, &gl->gl_flags); + if (test_bit(HIF_RECURSE, &gh->gh_iflags)) + handle_recurse(gh); + run_queue(gl); + spin_unlock(&gl->gl_spin); + } + + return error; +} + +/** + * add_to_queue - Add a holder to the wait-for-promotion queue or holder list + * (according to recursion) + * @gh: the holder structure to add + * + * If the hold requestor's process already has a granted lock (on holder list), + * and this new request is compatible, go ahead and grant it, adding this + * new holder to the glock's holder list. + * + * If the hold requestor's process has earlier requested a lock, and is still + * waiting for it to be granted, and this new request is compatible with + * the earlier one, they can be handled at the same time when the request + * is finally granted. Mark both (all) with RECURSE flags, and add new + * holder to wait-for-promotion queue. + * + * If there is no previous holder from this process (on holder list or wait- + * for-promotion queue), simply add new holder to wait-for-promotion queue. + */ + +static void +add_to_queue(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + struct list_head *tmp, *head; + struct gfs_holder *tmp_gh; + + if (gh->gh_owner) { + /* Search through glock's holders list to see if this process + already holds a granted lock. */ + for (head = &gl->gl_holders, tmp = head->next; + tmp != head; + tmp = tmp->next) { + tmp_gh = list_entry(tmp, struct gfs_holder, gh_list); + if (tmp_gh->gh_owner == gh->gh_owner) { + /* Make sure pre-existing holder is compatible + with this new one. */ + if (gfs_assert_warn(sdp, (gh->gh_flags & LM_FLAG_ANY) || + !(tmp_gh->gh_flags & LM_FLAG_ANY)) || + gfs_assert_warn(sdp, (tmp_gh->gh_flags & GL_LOCAL_EXCL) || + !(gh->gh_flags & GL_LOCAL_EXCL)) || + gfs_assert_warn(sdp, relaxed_state_ok(gl->gl_state, + gh->gh_state, + gh->gh_flags))) + goto fail; + + /* We're good! Grant the hold. */ + list_add_tail(&gh->gh_list, &gl->gl_holders); + set_bit(HIF_HOLDER, &gh->gh_iflags); + + gh->gh_error = 0; + complete(&gh->gh_wait); + + return; + } + } + + /* If not, Search through glock's wait-for-promotion list to + see if this process already is waiting for a grant. */ + for (head = &gl->gl_waiters3, tmp = head->next; + tmp != head; + tmp = tmp->next) { + tmp_gh = list_entry(tmp, struct gfs_holder, gh_list); + if (tmp_gh->gh_owner == gh->gh_owner) { + /* Yes, make sure it is compatible with new */ + if (gfs_assert_warn(sdp, test_bit(HIF_PROMOTE, + &tmp_gh->gh_iflags)) || + gfs_assert_warn(sdp, (gh->gh_flags & LM_FLAG_ANY) || + !(tmp_gh->gh_flags & LM_FLAG_ANY)) || + gfs_assert_warn(sdp, (tmp_gh->gh_flags & GL_LOCAL_EXCL) || + !(gh->gh_flags & GL_LOCAL_EXCL)) || + gfs_assert_warn(sdp, relaxed_state_ok(tmp_gh->gh_state, + gh->gh_state, + gh->gh_flags))) + goto fail; + + /* OK, make sure they're marked, so + * when one gets granted, the other will too. */ + set_bit(HIF_RECURSE, &gh->gh_iflags); + set_bit(HIF_RECURSE, &tmp_gh->gh_iflags); + + list_add_tail(&gh->gh_list, &gl->gl_waiters3); + + return; + } + } + } + + /* Else, no recursion ... + If high priority request, add to head of promote queue, else tail */ + if (gh->gh_flags & LM_FLAG_PRIORITY) + list_add(&gh->gh_list, &gl->gl_waiters3); + else + list_add_tail(&gh->gh_list, &gl->gl_waiters3); + + return; + + fail: + set_bit(HIF_ABORTED, &gh->gh_iflags); +} + +/** + * gfs_glock_nq - enqueue a struct gfs_holder onto a glock (acquire a glock) + * @gh: the holder structure + * + * if (gh->gh_flags & GL_ASYNC), this never returns an error + * + * Returns: 0, GLR_TRYFAILED, or errno on failure + * + * Rules: + * @gh must not be already attached to a glock. + * Don't ask for UNLOCKED state (use gfs_glock_dq() for that). + * LM_FLAG_ANY (liberal) and GL_EXACT (restrictive) are mutually exclusive. + */ + +int +gfs_glock_nq(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + int error = 0; + + atomic_inc(&sdp->sd_glock_nq_calls); + + restart: + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) || + gfs_assert_warn(sdp, list_empty(&gh->gh_list)) || + gfs_assert_warn(sdp, gh->gh_state != LM_ST_UNLOCKED) || + gfs_assert_warn(sdp, (gh->gh_flags & (LM_FLAG_ANY | GL_EXACT)) != + (LM_FLAG_ANY | GL_EXACT))) { + set_bit(HIF_ABORTED, &gh->gh_iflags); + return -EIO; + } + + set_bit(HIF_PROMOTE, &gh->gh_iflags); + + spin_lock(&gl->gl_spin); + add_to_queue(gh); + run_queue(gl); + spin_unlock(&gl->gl_spin); + + if (!(gh->gh_flags & GL_ASYNC)) { + error = glock_wait_internal(gh); + if (error == GLR_CANCELED) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + goto restart; + } + } + + clear_bit(GLF_PREFETCH, &gl->gl_flags); + + return error; +} + +/** + * gfs_glock_poll - poll to see if an async request has been completed + * @gh: the holder + * + * Returns: TRUE if the request is ready to be gfs_glock_wait()ed on + */ + +int +gfs_glock_poll(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + int ready = FALSE; + + gfs_assert_warn(gl->gl_sbd, gh->gh_flags & GL_ASYNC); + + spin_lock(&gl->gl_spin); + + if (test_bit(HIF_HOLDER, &gh->gh_iflags)) + ready = TRUE; + else if (list_empty(&gh->gh_list)) { + if (gh->gh_error == GLR_CANCELED) { + spin_unlock(&gl->gl_spin); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + if (gfs_glock_nq(gh)) + return TRUE; + return FALSE; + } else + ready = TRUE; + } + + spin_unlock(&gl->gl_spin); + + return ready; +} + +/** + * gfs_glock_wait - wait for a lock acquisition that ended in a GLR_ASYNC + * @gh: the holder structure + * + * Returns: 0, GLR_TRYFAILED, or errno on failure + */ + +int +gfs_glock_wait(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + int error; + + gfs_assert_warn(gl->gl_sbd, gh->gh_flags & GL_ASYNC); + + error = glock_wait_internal(gh); + if (error == GLR_CANCELED) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + gh->gh_flags &= ~GL_ASYNC; + error = gfs_glock_nq(gh); + } + + return error; +} + +/** + * gfs_glock_dq - dequeue a struct gfs_holder from a glock (release a glock) + * @gh: the glock holder + * + * This releases a local process' hold on a glock, and services other waiters. + * If this is the last holder on this node, calls glock operation go_unlock(), + * and go_sync() if requested by glock's GL_SYNC flag. + * If glock's GL_NOCACHE flag is set, requests demotion to unlock the inter- + * node lock now, rather than caching the glock for later use. + * Otherwise, this function does *not* release the glock at inter-node scope. + * The glock will stay in glock cache until: + * -- This node uses it again (extending residence in glock cache), or + * -- Another node asks (via callback) for the lock, or + * -- The glock sits unused in glock cache for a while, and the cleanup + * daemons (gfs_scand and gfs_glockd) reclaim it. + */ + +void +gfs_glock_dq(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + + atomic_inc(&gl->gl_sbd->sd_glock_dq_calls); + + gfs_assert_withdraw(sdp, !queue_empty(gl, &gh->gh_list)); + gfs_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags)); + + if (gh->gh_flags & GL_SYNC) + set_bit(GLF_SYNC, &gl->gl_flags); + + /* Don't cache glock; request demote to unlock at inter-node scope */ + if (gh->gh_flags & GL_NOCACHE && gl->gl_holders.next == &gh->gh_list && + gl->gl_holders.prev == &gh->gh_list) + /* There's a race here. If there are two holders, and both + * are dq'ed at almost the same time, you can't guarantee that + * you will call handle_callback. Fixing this will require + * some refactoring */ + handle_callback(gl, LM_ST_UNLOCKED); + + lock_on_glock(gl); + + spin_lock(&gl->gl_spin); + list_del_init(&gh->gh_list); + + /* If last holder, do appropriate glock operations, set cache timer */ + if (list_empty(&gl->gl_holders)) { + spin_unlock(&gl->gl_spin); + + if (glops->go_unlock) + glops->go_unlock(gl, gh->gh_flags); + + /* Do "early" sync, if requested by holder */ + if (test_bit(GLF_SYNC, &gl->gl_flags)) { + if (glops->go_sync) + glops->go_sync(gl, + DIO_METADATA | + DIO_DATA | + DIO_INVISIBLE); + } + + gl->gl_stamp = jiffies; + + spin_lock(&gl->gl_spin); + } + + clear_bit(GLF_LOCK, &gl->gl_flags); + run_queue(gl); + spin_unlock(&gl->gl_spin); +} + +/** + * gfs_glock_prefetch - Try to prefetch a glock + * @gl: the glock + * @state: the state to prefetch in + * @flags: flags passed to go_xmote_th() + * + * Bypass request queues of glock (i.e. no holder involved), and directly call + * go_xmote_th() to ask lock module for lock, to put in glock cache for + * later use. + * + * Will not prefetch the lock (no need to) if a process on this node is already + * interested in the lock, or if it's sitting in glock cache in a compatible + * state. + * + * Rules: + * Don't ask for UNLOCKED state (use gfs_glock_dq() for that). + * LM_FLAG_ANY (liberal) and GL_EXACT (restrictive) are mutually exclusive. + */ + +void +gfs_glock_prefetch(struct gfs_glock *gl, unsigned int state, int flags) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + + if (gfs_assert_warn(sdp, state != LM_ST_UNLOCKED) || + gfs_assert_warn(sdp, (flags & (LM_FLAG_ANY | GL_EXACT)) != + (LM_FLAG_ANY | GL_EXACT))) + return; + + spin_lock(&gl->gl_spin); + + /* Should we prefetch? */ + if (test_bit(GLF_LOCK, &gl->gl_flags) || + !list_empty(&gl->gl_holders) || + !list_empty(&gl->gl_waiters1) || + !list_empty(&gl->gl_waiters2) || + !list_empty(&gl->gl_waiters3) || + relaxed_state_ok(gl->gl_state, state, flags)) { + spin_unlock(&gl->gl_spin); + return; + } + + /* Let bottom half know we're prefetching, ask lock module for lock */ + set_bit(GLF_PREFETCH, &gl->gl_flags); + + if (gfs_assert_warn(sdp, !gl->gl_req_gh)) + gl->gl_req_gh = NULL; + set_bit(GLF_LOCK, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + + glops->go_xmote_th(gl, state, flags); + + atomic_inc(&gl->gl_sbd->sd_glock_prefetch_calls); +} + +/** + * gfs_glock_force_drop - Force a glock to be uncached + * @gl: the glock + * + */ + +void +gfs_glock_force_drop(struct gfs_glock *gl) +{ + struct gfs_holder gh; + + gfs_holder_init(gl, LM_ST_UNLOCKED, 0, &gh); + set_bit(HIF_DEMOTE, &gh.gh_iflags); + gh.gh_owner = NULL; + + spin_lock(&gl->gl_spin); + list_add_tail(&gh.gh_list, &gl->gl_waiters2); + run_queue(gl); + spin_unlock(&gl->gl_spin); + + wait_for_completion(&gh.gh_wait); + gfs_holder_uninit(&gh); +} + +/** + * greedy_work - + * @data: + * + */ + +static void +greedy_work(struct work_struct *work) +{ + struct greedy *gr = container_of(work, struct greedy, gr_work.work); + struct gfs_holder *gh = &gr->gr_gh; + struct gfs_glock *gl = gh->gh_gl; + struct gfs_glock_operations *glops = gl->gl_ops; + + clear_bit(GLF_SKIP_WAITERS2, &gl->gl_flags); + + if (glops->go_greedy) + glops->go_greedy(gl); + + spin_lock(&gl->gl_spin); + + if (list_empty(&gl->gl_waiters2)) { + clear_bit(GLF_GREEDY, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + gfs_holder_uninit(gh); + kfree(gr); + } else { + glock_hold(gl); + list_add_tail(&gh->gh_list, &gl->gl_waiters2); + run_queue(gl); + spin_unlock(&gl->gl_spin); + glock_put(gl); + } +} + +/** + * gfs_glock_be_greedy - + * @gl: + * @time: + * + * Returns: 0 if go_greedy will be called, 1 otherwise + */ + +int +gfs_glock_be_greedy(struct gfs_glock *gl, unsigned int time) +{ + struct greedy *gr; + struct gfs_holder *gh; + + if (!time || + gl->gl_sbd->sd_args.ar_localcaching || + test_and_set_bit(GLF_GREEDY, &gl->gl_flags)) + return 1; + + gr = kmalloc(sizeof(struct greedy), GFP_KERNEL); + if (!gr) { + clear_bit(GLF_GREEDY, &gl->gl_flags); + return 1; + } + gh = &gr->gr_gh; + + gfs_holder_init(gl, 0, 0, gh); + set_bit(HIF_GREEDY, &gh->gh_iflags); + gh->gh_owner = NULL; + INIT_DELAYED_WORK(&gr->gr_work, greedy_work); + + set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags); + schedule_delayed_work(&gr->gr_work, time); + + return 0; +} + +/** + * gfs_glock_nq_init - intialize a holder and enqueue it on a glock + * @gl: the glock + * @state: the state we're requesting + * @flags: the modifier flags + * @gh: the holder structure + * + * Returns: 0, GLR_*, or errno + */ + +int +gfs_glock_nq_init(struct gfs_glock *gl, unsigned int state, int flags, + struct gfs_holder *gh) +{ + int error; + + gfs_holder_init(gl, state, flags, gh); + + error = gfs_glock_nq(gh); + if (error) + gfs_holder_uninit(gh); + + return error; +} + +/** + * gfs_glock_dq_uninit - dequeue a holder from a glock and initialize it + * @gh: the holder structure + * + */ + +void +gfs_glock_dq_uninit(struct gfs_holder *gh) +{ + gfs_glock_dq(gh); + gfs_holder_uninit(gh); +} + +/** + * gfs_glock_nq_num - acquire a glock based on lock number + * @sdp: the filesystem + * @number: the lock number + * @glops: the glock operations for the type of glock + * @state: the state to acquire the glock in + * @flags: modifier flags for the aquisition + * @gh: the struct gfs_holder + * + * Returns: errno + */ + +int +gfs_glock_nq_num(struct gfs_sbd *sdp, + uint64_t number, struct gfs_glock_operations *glops, + unsigned int state, int flags, struct gfs_holder *gh) +{ + struct gfs_glock *gl; + int error; + + error = gfs_glock_get(sdp, number, glops, CREATE, &gl); + if (!error) { + error = gfs_glock_nq_init(gl, state, flags, gh); + glock_put(gl); + } + + return error; +} + +/** + * glock_compare - Compare two struct gfs_glock structures for sorting + * @arg_a: the first structure + * @arg_b: the second structure + * + */ + +static int +glock_compare(const void *arg_a, const void *arg_b) +{ + struct gfs_holder *gh_a = *(struct gfs_holder **)arg_a; + struct gfs_holder *gh_b = *(struct gfs_holder **)arg_b; + struct lm_lockname *a = &gh_a->gh_gl->gl_name; + struct lm_lockname *b = &gh_b->gh_gl->gl_name; + int ret = 0; + + if (a->ln_number > b->ln_number) + ret = 1; + else if (a->ln_number < b->ln_number) + ret = -1; + else { + if (gh_a->gh_state == LM_ST_SHARED && + gh_b->gh_state == LM_ST_EXCLUSIVE) + ret = 1; + else if (!(gh_a->gh_flags & GL_LOCAL_EXCL) && + (gh_b->gh_flags & GL_LOCAL_EXCL)) + ret = 1; + } + + return ret; +} + +/** + * nq_m_sync - synchonously acquire more than one glock in deadlock free order + * @num_gh: the number of structures + * @ghs: an array of struct gfs_holder structures + * + * Returns: 0 on success (all glocks acquired), errno on failure (no glocks acquired) + */ + +static int +nq_m_sync(unsigned int num_gh, struct gfs_holder *ghs, struct gfs_holder **p) +{ + unsigned int x; + int error = 0; + + for (x = 0; x < num_gh; x++) + p[x] = &ghs[x]; + + gfs_sort(p, num_gh, sizeof(struct gfs_holder *), glock_compare); + + for (x = 0; x < num_gh; x++) { + p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); + + error = gfs_glock_nq(p[x]); + if (error) { + while (x--) + gfs_glock_dq(p[x]); + break; + } + } + + return error; +} + +/** + * gfs_glock_nq_m - acquire multiple glocks + * @num_gh: the number of structures + * @ghs: an array of struct gfs_holder structures + * + * Figure out how big an impact this function has. Either: + * 1) Replace this code with code that calls gfs_glock_prefetch() + * 2) Forget async stuff and just call nq_m_sync() + * 3) Leave it like it is + * + * Returns: 0 on success (all glocks acquired), errno on failure (no glocks acquired) + */ + +int +gfs_glock_nq_m(unsigned int num_gh, struct gfs_holder *ghs) +{ + int *e; + unsigned int x; + int borked = FALSE, serious = 0; + int error = 0; + + if (!num_gh) + return 0; + + /* For just one gh, do request synchronously */ + if (num_gh == 1) { + ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); + return gfs_glock_nq(ghs); + } + + /* using sizeof(struct gfs_holder *) instead of sizeof(int), because + * we're also using this memory for nq_m_sync and ints should never be + * larger than pointers.... I hope + */ + e = kmalloc(num_gh * sizeof(struct gfs_holder *), GFP_KERNEL); + if (!e) + return -ENOMEM; + + /* Send off asynchronous requests */ + for (x = 0; x < num_gh; x++) { + ghs[x].gh_flags |= LM_FLAG_TRY | GL_ASYNC; + error = gfs_glock_nq(&ghs[x]); + if (error) { + borked = TRUE; + serious = error; + num_gh = x; + break; + } + } + + /* Wait for all to complete */ + for (x = 0; x < num_gh; x++) { + error = e[x] = glock_wait_internal(&ghs[x]); + if (error) { + borked = TRUE; + if (error != GLR_TRYFAILED && error != GLR_CANCELED) + serious = error; + } + } + + /* If all good, done! */ + if (!borked) { + kfree(e); + return 0; + } + + for (x = 0; x < num_gh; x++) + if (!e[x]) + gfs_glock_dq(&ghs[x]); + + if (serious) + error = serious; + else { + for (x = 0; x < num_gh; x++) + gfs_holder_reinit(ghs[x].gh_state, ghs[x].gh_flags, + &ghs[x]); + error = nq_m_sync(num_gh, ghs, (struct gfs_holder **)e); + } + + kfree(e); + return error; +} + +/** + * gfs_glock_dq_m - release multiple glocks + * @num_gh: the number of structures + * @ghs: an array of struct gfs_holder structures + * + */ + +void +gfs_glock_dq_m(unsigned int num_gh, struct gfs_holder *ghs) +{ + unsigned int x; + + for (x = 0; x < num_gh; x++) + gfs_glock_dq(&ghs[x]); +} + +/** + * gfs_glock_prefetch_num - prefetch a glock based on lock number + * @sdp: the filesystem + * @number: the lock number + * @glops: the glock operations for the type of glock + * @state: the state to acquire the glock in + * @flags: modifier flags for the aquisition + * + * Returns: errno + */ + +void +gfs_glock_prefetch_num(struct gfs_sbd *sdp, + uint64_t number, struct gfs_glock_operations *glops, + unsigned int state, int flags) +{ + struct gfs_glock *gl; + int error; + + if (atomic_read(&sdp->sd_reclaim_count) < gfs_tune_get(sdp, gt_reclaim_limit)) { + error = gfs_glock_get(sdp, number, glops, CREATE, &gl); + if (!error) { + gfs_glock_prefetch(gl, state, flags); + glock_put(gl); + } + } +} + +/** + * gfs_lvb_hold - attach a LVB from a glock + * @gl: The glock in question + * + */ + +int +gfs_lvb_hold(struct gfs_glock *gl) +{ + int error; + + lock_on_glock(gl); + + if (!atomic_read(&gl->gl_lvb_count)) { + gfs_assert_warn(gl->gl_sbd, !gl->gl_lvb); + error = gfs_lm_hold_lvb(gl->gl_sbd, gl->gl_lock, &gl->gl_lvb); + if (error) { + unlock_on_glock(gl); + return error; + } + glock_hold(gl); + } + atomic_inc(&gl->gl_lvb_count); + + unlock_on_glock(gl); + + return 0; +} + +/** + * gfs_lvb_unhold - detach a LVB from a glock + * @gl: The glock in question + * + */ + +void +gfs_lvb_unhold(struct gfs_glock *gl) +{ + glock_hold(gl); + + lock_on_glock(gl); + + if (!gfs_assert_warn(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0) && + atomic_dec_and_test(&gl->gl_lvb_count)) { + gfs_assert_warn(gl->gl_sbd, gl->gl_lvb); + gfs_lm_unhold_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb); + gl->gl_lvb = NULL; + glock_put(gl); + } + + unlock_on_glock(gl); + + glock_put(gl); +} + +#if 0 +/** + * gfs_lvb_sync - sync a LVB + * @gl: The glock in question + * + */ + +void +gfs_lvb_sync(struct gfs_glock *gl) +{ + if (gfs_assert_warn(gl->gl_sbd, atomic_read(&gl->gl_lvb_count))) + return; + + lock_on_glock(gl); + + if (!gfs_assert_warn(gl->gl_sbd, gfs_glock_is_held_excl(gl))) + gfs_lm_sync_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb); + + unlock_on_glock(gl); +} +#endif + +/** + * blocking_cb - + * @sdp: + * @name: + * @state: + * + */ + +void +blocking_cb(struct gfs_sbd *sdp, struct lm_lockname *name, unsigned int state) +{ + struct gfs_glock *gl; + + gl = gfs_glock_find(sdp, name); + if (!gl) + return; + + if (gl->gl_ops->go_callback) + gl->gl_ops->go_callback(gl, state); + handle_callback(gl, state); + + spin_lock(&gl->gl_spin); + run_queue(gl); + spin_unlock(&gl->gl_spin); + + glock_put(gl); +} + +/** + * gfs_glock_cb - Callback used by locking module + * @fsdata: Pointer to the superblock + * @type: Type of callback + * @data: Type dependent data pointer + * + * Called by the locking module when it wants to tell us something. + * Either we need to drop a lock, one of our ASYNC requests completed, or + * another client expired (crashed/died) and we need to recover its journal. + * If another node needs a lock held by this node, we queue a request to demote + * our lock to a state compatible with that needed by the other node. + * For example, if the other node needs EXCLUSIVE, we request UNLOCKED. + * SHARED and DEFERRED modes can be shared with other nodes, so we request + * accordingly. + * Once all incompatible holders on this node are done with the lock, the + * queued request will cause run_queue() to call the lock module to demote + * our lock to a compatible state, allowing the other node to grab the lock. + */ + +void +gfs_glock_cb(void *fsdata, unsigned int type, void *data) +{ + struct gfs_sbd *sdp = fsdata; + + atomic_inc(&sdp->sd_lm_callbacks); + + switch (type) { + case LM_CB_NEED_E: + blocking_cb(sdp, (struct lm_lockname *)data, LM_ST_UNLOCKED); + return; + + case LM_CB_NEED_D: + blocking_cb(sdp, (struct lm_lockname *)data, LM_ST_DEFERRED); + return; + + case LM_CB_NEED_S: + blocking_cb(sdp, (struct lm_lockname *)data, LM_ST_SHARED); + return; + + case LM_CB_ASYNC: { + struct lm_async_cb *async = (struct lm_async_cb *)data; + struct gfs_glock *gl; + + gl = gfs_glock_find(sdp, &async->lc_name); + if (gfs_assert_warn(sdp, gl)) + return; + if (!gfs_assert_warn(sdp, gl->gl_req_bh)) + gl->gl_req_bh(gl, async->lc_ret); + glock_put(gl); + + return; + } + + case LM_CB_NEED_RECOVERY: + gfs_add_dirty_j(sdp, *(unsigned int *)data); + if (sdp->sd_recoverd_process) + wake_up_process(sdp->sd_recoverd_process); + return; + + case LM_CB_DROPLOCKS: + gfs_gl_hash_clear(sdp, FALSE); + gfs_quota_scan(sdp); + return; + + default: + gfs_assert_warn(sdp, FALSE); + return; + } +} + +/** + * gfs_try_toss_inode - try to remove a particular GFS inode struct from cache + * sdp: the filesystem + * inum: the inode number + * + * Look for the glock protecting the inode of interest. + * If no process is manipulating or holding the glock, see if the glock + * has a gfs_inode attached. + * If gfs_inode has no references, unhold its iopen glock, release any + * indirect addressing buffers, and destroy the gfs_inode. + */ + +void +gfs_try_toss_inode(struct gfs_sbd *sdp, struct gfs_inum *inum) +{ + struct gfs_glock *gl; + struct gfs_inode *ip; + int error; + + error = gfs_glock_get(sdp, + inum->no_formal_ino, &gfs_inode_glops, + NO_CREATE, &gl); + if (error || !gl) + return; + + if (!trylock_on_glock(gl)) + goto out; + + if (!queue_empty(gl, &gl->gl_holders)) + goto out_unlock; + + ip = get_gl2ip(gl); + if (!ip) + goto out_unlock; + + if (atomic_read(&ip->i_count)) + goto out_unlock; + + gfs_inode_destroy(ip); + + out_unlock: + unlock_on_glock(gl); + + out: + glock_put(gl); +} + +/** + * gfs_iopen_go_callback - Try to kick the inode/vnode associated with an iopen glock from memory + * @io_gl: the iopen glock + * @state: the state into which the glock should be put + * + */ + +void +gfs_iopen_go_callback(struct gfs_glock *io_gl, unsigned int state) +{ + struct gfs_glock *i_gl; + struct gfs_inode *ip; + + if (state != LM_ST_UNLOCKED) + return; + + spin_lock(&io_gl->gl_spin); + i_gl = get_gl2gl(io_gl); + if (i_gl) { + glock_hold(i_gl); + spin_unlock(&io_gl->gl_spin); + } else { + spin_unlock(&io_gl->gl_spin); + return; + } + + if (trylock_on_glock(i_gl)) { + if (queue_empty(i_gl, &i_gl->gl_holders)) { + ip = get_gl2ip(i_gl); + if (ip) { + gfs_try_toss_vnode(ip); + unlock_on_glock(i_gl); + gfs_glock_schedule_for_reclaim(i_gl); + goto out; + } + } + unlock_on_glock(i_gl); + } + + out: + glock_put(i_gl); +} + +/** + * demote_ok - Check to see if it's ok to unlock a glock (to remove it + * from glock cache) + * @gl: the glock + * + * Called when trying to reclaim glocks, once it's determined that the glock + * has no holders on this node. + * + * Returns: TRUE if it's ok + * + * It's not okay if: + * -- glock is STICKY + * -- PREFETCHed glock has not been given enough chance to be used + * -- glock-type-specific test says "no" + */ + +static int +demote_ok(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_glock_operations *glops = gl->gl_ops; + int demote = TRUE; + + if (test_bit(GLF_STICKY, &gl->gl_flags)) + demote = FALSE; + else if (test_bit(GLF_PREFETCH, &gl->gl_flags)) + demote = time_after_eq(jiffies, + gl->gl_stamp + + gfs_tune_get(sdp, gt_prefetch_secs) * HZ); + else if (glops->go_demote_ok) + demote = glops->go_demote_ok(gl); + + return demote; +} + +/** + * gfs_glock_schedule_for_reclaim - Add a glock to the reclaim list + * @gl: the glock + * + */ + +void +gfs_glock_schedule_for_reclaim(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + + spin_lock(&sdp->sd_reclaim_lock); + if (list_empty(&gl->gl_reclaim)) { + glock_hold(gl); + list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list); + atomic_inc(&sdp->sd_reclaim_count); + } + spin_unlock(&sdp->sd_reclaim_lock); + + wake_up(&sdp->sd_reclaim_wchan); +} + +/** + * gfs_reclaim_glock - process the next glock on the filesystem's reclaim list + * @sdp: the filesystem + * + * Called from gfs_glockd() glock reclaim daemon, or when promoting a + * (different) glock and we notice that there are a lot of glocks in the + * reclaim list. + * + * Remove glock from filesystem's reclaim list, update reclaim statistics. + * If no holders (might have gotten added since glock was placed on reclaim + * list): + * -- Destroy any now-unused inode protected by glock + * (and release hold on iopen glock). + * -- Ask for demote to UNLOCKED to enable removal of glock from glock cache. + * + * If no further interest in glock struct, remove it from glock cache, and + * free it from memory. (During normal operation, this is the only place + * that this is done). + * + * Glock-type-specific considerations for permission to demote are handled + * in demote_ok(). This includes how long to retain a glock in cache after it + * is no longer held by any process. + */ + +void +gfs_reclaim_glock(struct gfs_sbd *sdp) +{ + struct gfs_glock *gl; + struct gfs_gl_hash_bucket *bucket; + + spin_lock(&sdp->sd_reclaim_lock); + + /* Nothing to reclaim? Done! */ + if (list_empty(&sdp->sd_reclaim_list)) { + spin_unlock(&sdp->sd_reclaim_lock); + return; + } + + /* Remove next victim from reclaim list */ + gl = list_entry(sdp->sd_reclaim_list.next, + struct gfs_glock, gl_reclaim); + list_del_init(&gl->gl_reclaim); + + spin_unlock(&sdp->sd_reclaim_lock); + + atomic_dec(&sdp->sd_reclaim_count); + atomic_inc(&sdp->sd_reclaimed); + + if (trylock_on_glock(gl)) { + if (queue_empty(gl, &gl->gl_holders)) { + /* Inode glock-type-specific; free unused gfs inode, + and release hold on iopen glock */ + if (gl->gl_ops == &gfs_inode_glops) { + struct gfs_inode *ip = get_gl2ip(gl); + if (ip && !atomic_read(&ip->i_count)) + gfs_inode_destroy(ip); + } + /* Generic (including inodes); try to unlock glock */ + if (gl->gl_state != LM_ST_UNLOCKED && + demote_ok(gl)) + handle_callback(gl, LM_ST_UNLOCKED); + } + unlock_on_glock(gl); + } + + bucket = gl->gl_bucket; + + /* If glock struct's only remaining reference is from being put on + the reclaim list, remove glock from hash table (sd_gl_hash), + and free the glock's memory */ + write_lock(&bucket->hb_lock); + if (atomic_read(&gl->gl_count) == 1) { + list_del_init(&gl->gl_list); + write_unlock(&bucket->hb_lock); + glock_free(gl); + } else { + write_unlock(&bucket->hb_lock); + glock_put(gl); /* see gfs_glock_schedule_for_reclaim() */ + } +} + +/** + * examine_bucket - Call a function for glock in a hash bucket + * @examiner: the function + * @sdp: the filesystem + * @bucket: the bucket + * + * Returns: TRUE if the bucket has entries + */ + +static int +examine_bucket(glock_examiner examiner, + struct gfs_sbd *sdp, struct gfs_gl_hash_bucket *bucket, + unsigned int *purge_nr) +{ + struct glock_plug plug; + struct list_head *tmp; + struct gfs_glock *gl; + int entries; + + /* Add "plug" to end of bucket list, work back up list from there */ + memset(&plug.gl_flags, 0, sizeof(unsigned long)); + set_bit(GLF_PLUG, &plug.gl_flags); + + write_lock(&bucket->hb_lock); + list_add(&plug.gl_list, &bucket->hb_list); + write_unlock(&bucket->hb_lock); + + /* Look at each bucket entry */ + for (;;) { + write_lock(&bucket->hb_lock); + + /* Work back up list from plug */ + for (;;) { + tmp = plug.gl_list.next; + + /* Top of list; we're done */ + if (tmp == &bucket->hb_list) { + list_del(&plug.gl_list); + entries = !list_empty(&bucket->hb_list); + write_unlock(&bucket->hb_lock); + return entries; + } + gl = list_entry(tmp, struct gfs_glock, gl_list); + + /* Move plug up list */ + list_move(&plug.gl_list, &gl->gl_list); + + if (test_bit(GLF_PLUG, &gl->gl_flags)) + continue; + + /* glock_hold; examiner must glock_put() */ + atomic_inc(&gl->gl_count); + + break; + } + + write_unlock(&bucket->hb_lock); + + examiner(gl, purge_nr); + } +} + +static void +try_purge_iopen(struct gfs_glock *gl, unsigned int *p_count) +{ + struct gfs_glock *i_gl; + + if (*p_count == 0) + return; + + /* find the associated inode glock */ + i_gl = get_gl2gl(gl); + if (!i_gl) + return; + + /* + * If the associated inode glock has been in unlocked + * state, try to purge it. + */ + if (trylock_on_glock(i_gl)) { + if (i_gl->gl_state == LM_ST_UNLOCKED) { + *p_count = *p_count - 1; + unlock_on_glock(i_gl); + atomic_inc(&gl->gl_count); + gfs_iopen_go_callback(gl, LM_ST_UNLOCKED); + handle_callback(gl, LM_ST_UNLOCKED); + spin_lock(&gl->gl_spin); + run_queue(gl); + spin_unlock(&gl->gl_spin); + glock_put(gl); + } else + unlock_on_glock(i_gl); + } + + return; +} + +/** + * scan_glock - look at a glock and see if we can reclaim it + * @gl: the glock to look at + * + * Called via examine_bucket() when trying to release glocks from glock cache, + * during normal operation (i.e. not unmount time). + * + * Place glock on filesystem's reclaim list if, on this node: + * -- No process is manipulating glock struct, and + * -- No current holders, and either: + * -- GFS incore inode, protected by glock, is no longer in use, or + * -- Glock-type-specific demote_ok glops gives permission + */ + +static void +scan_glock(struct gfs_glock *gl, unsigned int *p_count) +{ + if (trylock_on_glock(gl)) { + if (queue_empty(gl, &gl->gl_holders)) { + /* Inode glock-type-specific; reclaim glock if gfs inode + no longer in use. */ + if (gl->gl_ops == &gfs_inode_glops) { + struct gfs_inode *ip = get_gl2ip(gl); + if (ip && !atomic_read(&ip->i_count)) { + unlock_on_glock(gl); + gfs_glock_schedule_for_reclaim(gl); + goto out; + } + } + /* Generic (including inodes not scheduled above) */ + if (gl->gl_state != LM_ST_UNLOCKED && + demote_ok(gl)) { + unlock_on_glock(gl); + gfs_glock_schedule_for_reclaim(gl); + goto out; + } + } + /* iopen always has holder(s) */ + if (gl->gl_name.ln_type == LM_TYPE_IOPEN) { + unlock_on_glock(gl); + try_purge_iopen(gl, p_count); + goto out; + } + unlock_on_glock(gl); + } + + out: + glock_put(gl); /* see examine_bucket() */ +} + +/** + * gfs_scand_internal - Look for glocks and inodes to toss from memory + * @sdp: the filesystem + * + * Invokes scan_glock() for each glock in each cache bucket. + * + * Steps of reclaiming a glock: + * -- scan_glock() places eligible glocks on filesystem's reclaim list. + * -- gfs_reclaim_glock() processes list members, attaches demotion requests + * to wait queues of glocks still locked at inter-node scope. + * -- Demote to UNLOCKED state (if not already unlocked). + * -- gfs_reclaim_lock() cleans up glock structure. + */ + +void +gfs_scand_internal(struct gfs_sbd *sdp) +{ + unsigned int x, purge_nr; + + if (!sdp->sd_tune.gt_glock_purge) + purge_nr = 0; + else + purge_nr = atomic_read(&sdp->sd_glock_count) * + sdp->sd_tune.gt_glock_purge / 100; + + for (x = 0; x < GFS_GL_HASH_SIZE; x++) { + examine_bucket(scan_glock, sdp, &sdp->sd_gl_hash[x], &purge_nr); + cond_resched(); + } +} + +/** + * clear_glock - look at a glock and see if we can free it from glock cache + * @gl: the glock to look at + * + * Called via examine_bucket() when unmounting the filesystem, or + * when inter-node lock manager requests DROPLOCKS because it is running + * out of capacity. + * + * Similar to gfs_reclaim_glock(), except does *not*: + * -- Consult demote_ok() for permission + * -- Increment sdp->sd_reclaimed statistic + * + */ + +static void +clear_glock(struct gfs_glock *gl, unsigned int *unused) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_gl_hash_bucket *bucket = gl->gl_bucket; + + spin_lock(&sdp->sd_reclaim_lock); + if (!list_empty(&gl->gl_reclaim)) { + list_del_init(&gl->gl_reclaim); + atomic_dec(&sdp->sd_reclaim_count); + glock_put(gl); /* see gfs_glock_schedule_for_reclaim() */ + } + spin_unlock(&sdp->sd_reclaim_lock); + + if (trylock_on_glock(gl)) { + if (queue_empty(gl, &gl->gl_holders)) { + /* Inode glock-type-specific; free unused gfs inode, + and release hold on iopen glock */ + if (gl->gl_ops == &gfs_inode_glops) { + struct gfs_inode *ip = get_gl2ip(gl); + if (ip && !atomic_read(&ip->i_count)) + gfs_inode_destroy(ip); + } + /* Generic (including inodes); unlock glock */ + if (gl->gl_state != LM_ST_UNLOCKED) + handle_callback(gl, LM_ST_UNLOCKED); + } + + unlock_on_glock(gl); + } + + /* If glock struct's only remaining reference is from examine_bucket(), + remove glock from hash table (sd_gl_hash), and free glock's memory */ + write_lock(&bucket->hb_lock); + if (atomic_read(&gl->gl_count) == 1) { + list_del_init(&gl->gl_list); + write_unlock(&bucket->hb_lock); + glock_free(gl); + } else { + write_unlock(&bucket->hb_lock); + glock_put(gl); /* see examine_bucket() */ + } +} + +/** + * gfs_gl_hash_clear - Empty out the glock hash table + * @sdp: the filesystem + * @wait: wait until it's all gone + * + * Called when unmounting the filesystem, or when inter-node lock manager + * requests DROPLOCKS because it is running out of capacity. + */ + +void +gfs_gl_hash_clear(struct gfs_sbd *sdp, int wait) +{ + unsigned long t; + unsigned int x; + int cont; + + t = jiffies; + + for (;;) { + cont = FALSE; + + for (x = 0; x < GFS_GL_HASH_SIZE; x++) + if (examine_bucket(clear_glock, sdp, &sdp->sd_gl_hash[x], 0)) + cont = TRUE; + + if (!wait || !cont) + break; + + if (time_after_eq(jiffies, t + gfs_tune_get(sdp, gt_stall_secs) * HZ)) { + printk("GFS: fsid=%s: Unmount seems to be stalled. Dumping lock state...\n", + sdp->sd_fsname); + gfs_dump_lockstate(sdp, NULL); + t = jiffies; + } + + invalidate_inodes(sdp->sd_vfs); + schedule_timeout_interruptible(HZ / 10); + } +} + +/* + * Diagnostic routines to help debug distributed deadlock + */ + +/** + * dump_holder - print information about a glock holder + * @str: a string naming the type of holder + * @gh: the glock holder + * @buf: the buffer + * @size: the size of the buffer + * @count: where we are in the buffer + * + * Returns: 0 on success, -ENOBUFS when we run out of space + */ + +static int +dump_holder(char *str, struct gfs_holder *gh, + char *buf, unsigned int size, unsigned int *count) +{ + unsigned int x; + int error = -ENOBUFS; + + gfs_printf(" %s\n", str); + gfs_printf(" owner = %ld\n", + (gh->gh_owner) ? (long)gh->gh_owner->pid : -1); + gfs_printf(" gh_state = %u\n", gh->gh_state); + gfs_printf(" gh_flags ="); + for (x = 0; x < 32; x++) + if (gh->gh_flags & (1 << x)) + gfs_printf(" %u", x); + gfs_printf(" \n"); + gfs_printf(" error = %d\n", gh->gh_error); + gfs_printf(" gh_iflags ="); + for (x = 0; x < 32; x++) + if (test_bit(x, &gh->gh_iflags)) + gfs_printf(" %u", x); + gfs_printf(" \n"); + + error = 0; + + out: + return error; +} + +/** + * dump_inode - print information about an inode + * @ip: the inode + * @buf: the buffer + * @size: the size of the buffer + * @count: where we are in the buffer + * + * Returns: 0 on success, -ENOBUFS when we run out of space + */ + +static int +dump_inode(struct gfs_inode *ip, + char *buf, unsigned int size, unsigned int *count) +{ + unsigned int x; + int error = -ENOBUFS; + + gfs_printf(" Inode:\n"); + gfs_printf(" num = %" PRIu64 "/%" PRIu64 "\n", + ip->i_num.no_formal_ino, ip->i_num.no_addr); + gfs_printf(" type = %u\n", ip->i_di.di_type); + gfs_printf(" i_count = %d\n", atomic_read(&ip->i_count)); + gfs_printf(" i_flags ="); + for (x = 0; x < 32; x++) + if (test_bit(x, &ip->i_flags)) + gfs_printf(" %u", x); + gfs_printf(" \n"); + gfs_printf(" vnode = %s\n", (ip->i_vnode) ? "yes" : "no"); + + error = 0; + + out: + return error; +} + +/** + * dump_glock - print information about a glock + * @gl: the glock + * @buf: the buffer + * @size: the size of the buffer + * @count: where we are in the buffer + * + * Returns: 0 on success, -ENOBUFS when we run out of space + */ + +static int +dump_glock(struct gfs_glock *gl, + char *buf, unsigned int size, unsigned int *count) +{ + struct list_head *head, *tmp; + struct gfs_holder *gh; + unsigned int x; + int error = -ENOBUFS; + + spin_lock(&gl->gl_spin); + + gfs_printf("Glock (%u, %" PRIu64 ")\n", + gl->gl_name.ln_type, + gl->gl_name.ln_number); + gfs_printf(" gl_flags ="); + for (x = 0; x < 32; x++) + if (test_bit(x, &gl->gl_flags)) + gfs_printf(" %u", x); + gfs_printf(" \n"); + gfs_printf(" gl_count = %d\n", atomic_read(&gl->gl_count)); + gfs_printf(" gl_state = %u\n", gl->gl_state); + gfs_printf(" req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no"); + gfs_printf(" req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no"); + gfs_printf(" lvb_count = %d\n", atomic_read(&gl->gl_lvb_count)); + gfs_printf(" object = %s\n", (gl->gl_object) ? "yes" : "no"); + gfs_printf(" new_le = %s\n", (gl->gl_new_le.le_trans) ? "yes" : "no"); + gfs_printf(" incore_le = %s\n", (gl->gl_incore_le.le_trans) ? "yes" : "no"); + gfs_printf(" reclaim = %s\n", + (list_empty(&gl->gl_reclaim)) ? "no" : "yes"); + if (gl->gl_aspace) + gfs_printf(" aspace = %lu\n", + gl->gl_aspace->i_mapping->nrpages); + else + gfs_printf(" aspace = no\n"); + gfs_printf(" ail_bufs = %s\n", + (list_empty(&gl->gl_ail_bufs)) ? "no" : "yes"); + if (gl->gl_req_gh) { + error = dump_holder("Request", gl->gl_req_gh, buf, size, count); + if (error) + goto out; + } + for (head = &gl->gl_holders, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gh = list_entry(tmp, struct gfs_holder, gh_list); + error = dump_holder("Holder", gh, buf, size, count); + if (error) + goto out; + } + for (head = &gl->gl_waiters1, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gh = list_entry(tmp, struct gfs_holder, gh_list); + error = dump_holder("Waiter1", gh, buf, size, count); + if (error) + goto out; + } + for (head = &gl->gl_waiters2, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gh = list_entry(tmp, struct gfs_holder, gh_list); + error = dump_holder("Waiter2", gh, buf, size, count); + if (error) + goto out; + } + for (head = &gl->gl_waiters3, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gh = list_entry(tmp, struct gfs_holder, gh_list); + error = dump_holder("Waiter3", gh, buf, size, count); + if (error) + goto out; + } + if (gl->gl_ops == &gfs_inode_glops && get_gl2ip(gl)) { + if (!test_bit(GLF_LOCK, &gl->gl_flags) && + list_empty(&gl->gl_holders)) { + error = dump_inode(get_gl2ip(gl), buf, size, count); + if (error) + goto out; + } else { + error = -ENOBUFS; + gfs_printf(" Inode: busy\n"); + } + } + + error = 0; + + out: + spin_unlock(&gl->gl_spin); + + return error; +} + +/** + * gfs_dump_lockstate - print out the current lockstate + * @sdp: the filesystem + * @ub: the buffer to copy the information into + * + * If @ub is NULL, dump the lockstate to the console. + * + */ + +int +gfs_dump_lockstate(struct gfs_sbd *sdp, struct gfs_user_buffer *ub) +{ + struct gfs_gl_hash_bucket *bucket; + struct list_head *tmp, *head; + struct gfs_glock *gl; + char *buf = NULL; + unsigned int size = gfs_tune_get(sdp, gt_lockdump_size); + unsigned int x, count; + int error = 0; + + if (ub) { + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + } + + for (x = 0; x < GFS_GL_HASH_SIZE; x++) { + bucket = &sdp->sd_gl_hash[x]; + count = 0; + + read_lock(&bucket->hb_lock); + + for (head = &bucket->hb_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gl = list_entry(tmp, struct gfs_glock, gl_list); + + if (test_bit(GLF_PLUG, &gl->gl_flags)) + continue; + + error = dump_glock(gl, buf, size, &count); + if (error) + break; + } + + read_unlock(&bucket->hb_lock); + + if (error) + break; + + if (ub) { + if (ub->ub_count + count > ub->ub_size) { + error = -ENOMEM; + break; + } + if (copy_to_user(ub->ub_data + ub->ub_count, buf, count)) { + error = -EFAULT; + break; + } + ub->ub_count += count; + } + } + + if (ub) + kfree(buf); + + return error; +} --- linux-2.6.27.orig/ubuntu/gfs/dir.c +++ linux-2.6.27/ubuntu/gfs/dir.c @@ -0,0 +1,2394 @@ +/* +* Implements Extendible Hashing as described in: +* "Extendible Hashing" by Fagin, et al in +* __ACM Trans. on Database Systems__, Sept 1979. +* +* +* Here's the layout of dirents which is essentially the same as that of ext2 +* within a single block. The field de_name_len is the number of bytes +* actually required for the name (no null terminator). The field de_rec_len +* is the number of bytes allocated to the dirent. The offset of the next +* dirent in the block is (dirent + dirent->de_rec_len). When a dirent is +* deleted, the preceding dirent inherits its allocated space, ie +* prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained +* by adding de_rec_len to the current dirent, this essentially causes the +* deleted dirent to get jumped over when iterating through all the dirents. +* +* When deleting the first dirent in a block, there is no previous dirent so +* the field de_ino is set to zero to designate it as deleted. When allocating +* a dirent, gfs_dirent_alloc iterates through the dirents in a block. If the +* first dirent has (de_ino == 0) and de_rec_len is large enough, this first +* dirent is allocated. Otherwise it must go through all the 'used' dirents +* searching for one in which the amount of total space minus the amount of +* used space will provide enough space for the new dirent. +* +* There are two types of blocks in which dirents reside. In a stuffed dinode, +* the dirents begin at offset sizeof(struct gfs_dinode) from the beginning of +* the block. In leaves, they begin at offset sizeof (struct gfs_leaf) from the +* beginning of the leaf block. The dirents reside in leaves when +* +* dip->i_di.di_flags & GFS_DIF_EXHASH is true +* +* Otherwise, the dirents are "linear", within a single stuffed dinode block. +* +* When the dirents are in leaves, the actual contents of the directory file are +* used as an array of 64-bit block pointers pointing to the leaf blocks. The +* dirents are NOT in the directory file itself. There can be more than one block +* pointer in the array that points to the same leaf. In fact, when a directory +* is first converted from linear to exhash, all of the pointers point to the +* same leaf. +* +* When a leaf is completely full, the size of the hash table can be +* doubled unless it is already at the maximum size which is hard coded into +* GFS_DIR_MAX_DEPTH. After that, leaves are chained together in a linked list, +* but never before the maximum hash table size has been reached. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "dir.h" +#include "file.h" +#include "glock.h" +#include "inode.h" +#include "quota.h" +#include "rgrp.h" +#include "trans.h" + +#if 1 +#define gfs_dir_hash2offset(h) (((uint64_t)(h)) >> 1) +#define gfs_dir_offset2hash(p) ((uint32_t)(((uint64_t)(p)) << 1)) +#else +#define gfs_dir_hash2offset(h) (((uint64_t)(h))) +#define gfs_dir_offset2hash(p) ((uint32_t)(((uint64_t)(p)))) +#endif + +typedef int (*leaf_call_t) (struct gfs_inode *dip, + uint32_t index, uint32_t len, uint64_t leaf_no, + void *data); + +/** + * int gfs_filecmp - Compare two filenames + * @file1: The first filename + * @file2: The second filename + * @len_of_file2: The length of the second file + * + * This routine compares two filenames and returns TRUE if they are equal. + * + * Returns: TRUE (!=0) if the files are the same, otherwise FALSE (0). + */ + +int +gfs_filecmp(struct qstr *file1, char *file2, int len_of_file2) +{ + if (file1->len != len_of_file2) + return FALSE; + if (memcmp(file1->name, file2, file1->len)) + return FALSE; + return TRUE; +} + +/** + * dirent_first - Return the first dirent + * @dip: the directory + * @bh: The buffer + * @dent: Pointer to list of dirents + * + * return first dirent whether bh points to leaf or stuffed dinode + * + * Returns: IS_LEAF, IS_DINODE, or -errno + */ + +static int +dirent_first(struct gfs_inode *dip, struct buffer_head *bh, + struct gfs_dirent **dent) +{ + struct gfs_meta_header *h = (struct gfs_meta_header *)bh->b_data; + + if (gfs32_to_cpu(h->mh_type) == GFS_METATYPE_LF) { + if (gfs_meta_check(dip->i_sbd, bh)) + return -EIO; + *dent = (struct gfs_dirent *)(bh->b_data + sizeof(struct gfs_leaf)); + return IS_LEAF; + } else { + if (gfs_metatype_check(dip->i_sbd, bh, GFS_METATYPE_DI)) + return -EIO; + *dent = (struct gfs_dirent *)(bh->b_data + sizeof(struct gfs_dinode)); + return IS_DINODE; + } +} + +/** + * dirent_next - Next dirent + * @dip: the directory + * @bh: The buffer + * @dent: Pointer to list of dirents + * + * Returns: 0 on success, error code otherwise + */ + +static int +dirent_next(struct gfs_inode *dip, struct buffer_head *bh, + struct gfs_dirent **dent) +{ + struct gfs_dirent *tmp, *cur; + char *bh_end; + uint32_t cur_rec_len; + + cur = *dent; + bh_end = bh->b_data + bh->b_size; + cur_rec_len = gfs16_to_cpu(cur->de_rec_len); + + if ((char *)cur + cur_rec_len >= bh_end) { + if ((char *)cur + cur_rec_len > bh_end) { + gfs_consist_inode(dip); + return -EIO; + } + return -ENOENT; + } + + tmp = (struct gfs_dirent *)((char *)cur + cur_rec_len); + + if ((char *)tmp + gfs16_to_cpu(tmp->de_rec_len) > bh_end) { + gfs_consist_inode(dip); + return -EIO; + } + /* Only the first dent could ever have de_ino == 0 */ + if (!tmp->de_inum.no_formal_ino) { + gfs_consist_inode(dip); + return -EIO; + } + + *dent = tmp; + + return 0; +} + +/** + * dirent_del - Delete a dirent + * @dip: The GFS inode + * @bh: The buffer + * @prev: The previous dirent + * @cur: The current dirent + * + */ + +static void +dirent_del(struct gfs_inode *dip, struct buffer_head *bh, + struct gfs_dirent *prev, struct gfs_dirent *cur) +{ + uint32_t cur_rec_len, prev_rec_len; + + if (!cur->de_inum.no_formal_ino) { + gfs_consist_inode(dip); + return; + } + + gfs_trans_add_bh(dip->i_gl, bh); + + /* If there is no prev entry, this is the first entry in the block. + The de_rec_len is already as big as it needs to be. Just zero + out the inode number and return. */ + + if (!prev) { + cur->de_inum.no_formal_ino = 0; /* No endianess worries */ + return; + } + + /* Combine this dentry with the previous one. */ + + prev_rec_len = gfs16_to_cpu(prev->de_rec_len); + cur_rec_len = gfs16_to_cpu(cur->de_rec_len); + + if ((char *)prev + prev_rec_len != (char *)cur) + gfs_consist_inode(dip); + if ((char *)cur + cur_rec_len > bh->b_data + bh->b_size) + gfs_consist_inode(dip); + + prev_rec_len += cur_rec_len; + prev->de_rec_len = cpu_to_gfs16(prev_rec_len); +} + +/** + * gfs_dirent_alloc - Allocate a directory entry + * @dip: The GFS inode + * @bh: The buffer + * @name_len: The length of the name + * @dent_out: Pointer to list of dirents + * + * Returns: 0 on success, error code otherwise + */ + +int +gfs_dirent_alloc(struct gfs_inode *dip, struct buffer_head *bh, int name_len, + struct gfs_dirent **dent_out) +{ + struct gfs_dirent *dent, *new; + unsigned int rec_len = GFS_DIRENT_SIZE(name_len); + unsigned int entries = 0, offset = 0; + int type; + + type = dirent_first(dip, bh, &dent); + if (type < 0) + return type; + + if (type == IS_LEAF) { + struct gfs_leaf *leaf = (struct gfs_leaf *)bh->b_data; + entries = gfs16_to_cpu(leaf->lf_entries); + offset = sizeof(struct gfs_leaf); + } else { + struct gfs_dinode *dinode = (struct gfs_dinode *)bh->b_data; + entries = gfs32_to_cpu(dinode->di_entries); + offset = sizeof(struct gfs_dinode); + } + + if (!entries) { + if (dent->de_inum.no_formal_ino) { + gfs_consist_inode(dip); + return -EIO; + } + + gfs_trans_add_bh(dip->i_gl, bh); + + dent->de_rec_len = bh->b_size - offset; + dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len); + dent->de_name_len = cpu_to_gfs16(name_len); + + *dent_out = dent; + return 0; + } + + do { + uint32_t cur_rec_len, cur_name_len; + + cur_rec_len = gfs16_to_cpu(dent->de_rec_len); + cur_name_len = gfs16_to_cpu(dent->de_name_len); + + if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) || + (cur_rec_len >= GFS_DIRENT_SIZE(cur_name_len) + rec_len)) { + gfs_trans_add_bh(dip->i_gl, bh); + + if (dent->de_inum.no_formal_ino) { + new = (struct gfs_dirent *)((char *)dent + + GFS_DIRENT_SIZE(cur_name_len)); + memset(new, 0, sizeof(struct gfs_dirent)); + + new->de_rec_len = cpu_to_gfs16(cur_rec_len - + GFS_DIRENT_SIZE(cur_name_len)); + new->de_name_len = cpu_to_gfs16(name_len); + + dent->de_rec_len = cur_rec_len - gfs16_to_cpu(new->de_rec_len); + dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len); + + *dent_out = new; + return 0; + } + + dent->de_name_len = cpu_to_gfs16(name_len); + + *dent_out = dent; + return 0; + } + } while (dirent_next(dip, bh, &dent) == 0); + + return -ENOSPC; +} + +/** + * dirent_fits - See if we can fit a entry in this buffer + * @dip: The GFS inode + * @bh: The buffer + * @name_len: The length of the name + * + * Returns: TRUE if it can fit, FALSE otherwise + */ + +static int +dirent_fits(struct gfs_inode *dip, struct buffer_head *bh, int name_len) +{ + struct gfs_dirent *dent; + unsigned int rec_len = GFS_DIRENT_SIZE(name_len); + unsigned int entries = 0; + int type; + + type = dirent_first(dip, bh, &dent); + if (type < 0) + return type; + + if (type == IS_LEAF) { + struct gfs_leaf *leaf = (struct gfs_leaf *)bh->b_data; + entries = gfs16_to_cpu(leaf->lf_entries); + } else { + struct gfs_dinode *dinode = (struct gfs_dinode *)bh->b_data; + entries = gfs32_to_cpu(dinode->di_entries); + } + + if (!entries) + return TRUE; + + do { + uint32_t cur_rec_len, cur_name_len; + + cur_rec_len = gfs16_to_cpu(dent->de_rec_len); + cur_name_len = gfs16_to_cpu(dent->de_name_len); + + if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) || + (cur_rec_len >= GFS_DIRENT_SIZE(cur_name_len) + rec_len)) + return TRUE; + } while (dirent_next(dip, bh, &dent) == 0); + + return FALSE; +} + +/** + * leaf_search + * @bh: + * @filename: + * @dent_out: + * @dent_prev: + * + * Returns: + */ + +static int +leaf_search(struct gfs_inode *dip, + struct buffer_head *bh, struct qstr *filename, + struct gfs_dirent **dent_out, struct gfs_dirent **dent_prev) +{ + uint32_t hash; + struct gfs_dirent *dent, *prev = NULL; + unsigned int entries = 0; + int type; + + type = dirent_first(dip, bh, &dent); + if (type < 0) + return type; + + if (type == IS_LEAF) { + struct gfs_leaf *leaf = (struct gfs_leaf *)bh->b_data; + entries = gfs16_to_cpu(leaf->lf_entries); + } else if (type == IS_DINODE) { + struct gfs_dinode *dinode = (struct gfs_dinode *)bh->b_data; + entries = gfs32_to_cpu(dinode->di_entries); + } + + hash = gfs_dir_hash(filename->name, filename->len); + + do { + if (!dent->de_inum.no_formal_ino) { + prev = dent; + continue; + } + + if (gfs32_to_cpu(dent->de_hash) == hash && + gfs_filecmp(filename, (char *)(dent + 1), + gfs16_to_cpu(dent->de_name_len))) { + *dent_out = dent; + if (dent_prev) + *dent_prev = prev; + + return 0; + } + + prev = dent; + } while (dirent_next(dip, bh, &dent) == 0); + + return -ENOENT; +} + +/** + * get_leaf - Get leaf + * @dip: + * @leaf_no: + * @bh_out: + * + * Returns: 0 on success, error code otherwise + */ + +static int +get_leaf(struct gfs_inode *dip, uint64_t leaf_no, struct buffer_head **bhp) +{ + int error; + + error = gfs_dread(dip->i_gl, leaf_no, DIO_START | DIO_WAIT, bhp); + if (!error && gfs_metatype_check(dip->i_sbd, *bhp, GFS_METATYPE_LF)) + error = -EIO; + + return error; +} + +/** + * get_leaf_nr - Get a leaf number associated with the index + * @dip: The GFS inode + * @index: + * @leaf_out: + * + * Returns: 0 on success, error code otherwise + */ + +static int +get_leaf_nr(struct gfs_inode *dip, uint32_t index, uint64_t *leaf_out) +{ + uint64_t leaf_no; + int error; + + error = gfs_internal_read(dip, (char *)&leaf_no, + index * sizeof(uint64_t), + sizeof(uint64_t)); + if (error != sizeof(uint64_t)) + return (error < 0) ? error : -EIO; + + *leaf_out = gfs64_to_cpu(leaf_no); + + return 0; +} + +/** + * get_first_leaf - Get first leaf + * @dip: The GFS inode + * @index: + * @bh_out: + * + * Returns: 0 on success, error code otherwise + */ + +static int +get_first_leaf(struct gfs_inode *dip, uint32_t index, + struct buffer_head **bh_out) +{ + uint64_t leaf_no; + int error; + + error = get_leaf_nr(dip, index, &leaf_no); + if (!error) + error = get_leaf(dip, leaf_no, bh_out); + + return error; +} + +/** + * get_next_leaf - Get next leaf + * @dip: The GFS inode + * @bh_in: The buffer + * @bh_out: + * + * Returns: 0 on success, error code otherwise + */ + +static int +get_next_leaf(struct gfs_inode *dip, struct buffer_head *bh_in, + struct buffer_head **bh_out) +{ + struct gfs_leaf *leaf; + int error; + + leaf = (struct gfs_leaf *)bh_in->b_data; + + if (!leaf->lf_next) + error = -ENOENT; + else + error = get_leaf(dip, gfs64_to_cpu(leaf->lf_next), bh_out); + + return error; +} + +/** + * linked_leaf_search - Linked leaf search + * @dip: The GFS inode + * @filename: The filename to search for + * @dent_out: + * @dent_prev: + * @bh_out: + * + * Returns: 0 on sucess, error code otherwise + */ + +static int +linked_leaf_search(struct gfs_inode *dip, struct qstr *filename, + struct gfs_dirent **dent_out, struct gfs_dirent **dent_prev, + struct buffer_head **bh_out) +{ + struct buffer_head *bh = NULL, *bh_next; + uint32_t hsize, index; + uint32_t hash; + int error; + + hsize = 1 << dip->i_di.di_depth; + if (hsize * sizeof(uint64_t) != dip->i_di.di_size) { + gfs_consist_inode(dip); + return -EIO; + } + + /* Figure out the address of the leaf node. */ + + hash = gfs_dir_hash(filename->name, filename->len); + index = hash >> (32 - dip->i_di.di_depth); + + error = get_first_leaf(dip, index, &bh_next); + if (error) + return error; + + /* Find the entry */ + + do { + if (bh) + brelse(bh); + + bh = bh_next; + + error = leaf_search(dip, bh, filename, dent_out, dent_prev); + switch (error) { + case 0: + *bh_out = bh; + return 0; + + case -ENOENT: + break; + + default: + brelse(bh); + return error; + } + + error = get_next_leaf(dip, bh, &bh_next); + } + while (!error); + + brelse(bh); + + return error; +} + +/** + * dir_make_exhash - Convert a stuffed directory into an ExHash directory + * @dip: The GFS inode + * + * Returns: 0 on success, error code otherwise + */ + +static int +dir_make_exhash(struct gfs_inode *dip) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_dirent *dent; + struct buffer_head *bh, *dibh; + struct gfs_leaf *leaf; + int y; + uint32_t x; + uint64_t *lp, bn; + int error; + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + /* Allocate a new block for the first leaf node */ + + error = gfs_metaalloc(dip, &bn); + if (error) + goto fail; + + /* Turn over a new leaf */ + + error = gfs_dread(dip->i_gl, bn, DIO_NEW | DIO_START | DIO_WAIT, &bh); + if (error) + goto fail; + + gfs_trans_add_bh(dip->i_gl, bh); + gfs_metatype_set(bh, GFS_METATYPE_LF, GFS_FORMAT_LF); + gfs_buffer_clear_tail(bh, sizeof(struct gfs_meta_header)); + + /* Fill in the leaf structure */ + + leaf = (struct gfs_leaf *)bh->b_data; + + gfs_assert(sdp, dip->i_di.di_entries < (1 << 16),); + + leaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE); + leaf->lf_entries = cpu_to_gfs16(dip->i_di.di_entries); + + /* Copy dirents */ + + gfs_buffer_copy_tail(bh, sizeof(struct gfs_leaf), dibh, + sizeof(struct gfs_dinode)); + + /* Find last entry */ + + x = 0; + dirent_first(dip, bh, &dent); + + do { + if (!dent->de_inum.no_formal_ino) + continue; + if (++x == dip->i_di.di_entries) + break; + } + while (dirent_next(dip, bh, &dent) == 0); + + /* Adjust the last dirent's record length + (Remember that dent still points to the last entry.) */ + + dent->de_rec_len = gfs16_to_cpu(dent->de_rec_len) + + sizeof(struct gfs_dinode) - + sizeof(struct gfs_leaf); + dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len); + + brelse(bh); + + /* We're done with the new leaf block, now setup the new + hash table. */ + + gfs_trans_add_bh(dip->i_gl, dibh); + gfs_buffer_clear_tail(dibh, sizeof (struct gfs_dinode)); + + lp = (uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode)); + + for (x = sdp->sd_hash_ptrs; x--; lp++) + *lp = cpu_to_gfs64(bn); + + dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2; + dip->i_di.di_blocks++; + dip->i_di.di_flags |= GFS_DIF_EXHASH; + dip->i_di.di_payload_format = 0; + + for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; + dip->i_di.di_depth = y; + + gfs_dinode_out(&dip->i_di, dibh->b_data); + + brelse(dibh); + + return 0; + + fail: + brelse(dibh); + return error; +} + +/** + * dir_split_leaf - Split a leaf block into two + * @dip: The GFS inode + * @index: + * @leaf_no: + * + * Returns: 0 on success, error code on failure + */ + +static int +dir_split_leaf(struct gfs_inode *dip, uint32_t index, uint64_t leaf_no) +{ + struct buffer_head *nbh, *obh, *dibh; + struct gfs_leaf *nleaf, *oleaf; + struct gfs_dirent *dent, *prev = NULL, *next = NULL, *new; + uint32_t start, len, half_len, divider; + uint64_t bn, *lp; + uint32_t name_len; + int x, moved = FALSE; + int error, lp_vfree=0; + + /* Allocate the new leaf block */ + + error = gfs_metaalloc(dip, &bn); + if (error) + return error; + + /* Get the new leaf block */ + + error = gfs_dread(dip->i_gl, bn, + DIO_NEW | DIO_START | DIO_WAIT, &nbh); + if (error) + return error; + + gfs_trans_add_bh(dip->i_gl, nbh); + gfs_metatype_set(nbh, GFS_METATYPE_LF, GFS_FORMAT_LF); + gfs_buffer_clear_tail(nbh, sizeof (struct gfs_meta_header)); + + nleaf = (struct gfs_leaf *)nbh->b_data; + + nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE); + + /* Get the old leaf block */ + + error = get_leaf(dip, leaf_no, &obh); + if (error) + goto fail; + + gfs_trans_add_bh(dip->i_gl, obh); + + oleaf = (struct gfs_leaf *)obh->b_data; + + /* Compute the start and len of leaf pointers in the hash table. */ + + len = 1 << (dip->i_di.di_depth - gfs16_to_cpu(oleaf->lf_depth)); + half_len = len >> 1; + if (!half_len) { + gfs_consist_inode(dip); + error = -EIO; + goto fail_brelse; + } + + start = (index & ~(len - 1)); + + /* Change the pointers. + Don't bother distinguishing stuffed from non-stuffed. + This code is complicated enough already. */ + + lp = kmalloc(half_len * sizeof (uint64_t), GFP_KERNEL); + if (unlikely(!lp)) { + lp = vmalloc(half_len * sizeof (uint64_t)); + if (!lp) { + printk("GFS: dir_split_leaf vmalloc fail - half_len=%d\n", half_len); + error = -ENOMEM; + goto fail_brelse; + } else + lp_vfree = 1; + } + + error = gfs_internal_read(dip, (char *)lp, start * sizeof(uint64_t), + half_len * sizeof(uint64_t)); + if (error != half_len * sizeof(uint64_t)) { + if (error >= 0) + error = -EIO; + goto fail_lpfree; + } + + /* Change the pointers */ + + for (x = 0; x < half_len; x++) + lp[x] = cpu_to_gfs64(bn); + + error = gfs_internal_write(dip, (char *)lp, start * sizeof(uint64_t), + half_len * sizeof(uint64_t)); + if (error != half_len * sizeof(uint64_t)) { + if (error >= 0) + error = -EIO; + goto fail_lpfree; + } + + if (unlikely(lp_vfree)) + vfree(lp); + else + kfree(lp); + + /* Compute the divider */ + + divider = (start + half_len) << (32 - dip->i_di.di_depth); + + /* Copy the entries */ + + dirent_first(dip, obh, &dent); + + do { + next = dent; + if (dirent_next(dip, obh, &next)) + next = NULL; + + if (dent->de_inum.no_formal_ino && + gfs32_to_cpu(dent->de_hash) < divider) { + name_len = gfs16_to_cpu(dent->de_name_len); + + gfs_dirent_alloc(dip, nbh, name_len, &new); + + new->de_inum = dent->de_inum; /* No endianness worries */ + new->de_hash = dent->de_hash; /* No endianness worries */ + new->de_type = dent->de_type; /* No endianness worries */ + memcpy((char *)(new + 1), (char *)(dent + 1), + name_len); + + nleaf->lf_entries = gfs16_to_cpu(nleaf->lf_entries) + 1; + nleaf->lf_entries = cpu_to_gfs16(nleaf->lf_entries); + + dirent_del(dip, obh, prev, dent); + + if (!oleaf->lf_entries) + gfs_consist_inode(dip); + oleaf->lf_entries = gfs16_to_cpu(oleaf->lf_entries) - 1; + oleaf->lf_entries = cpu_to_gfs16(oleaf->lf_entries); + + if (!prev) + prev = dent; + + moved = TRUE; + } else + prev = dent; + + dent = next; + } + while (dent); + + /* If none of the entries got moved into the new leaf, + artificially fill in the first entry. */ + + if (!moved) { + gfs_dirent_alloc(dip, nbh, 0, &new); + new->de_inum.no_formal_ino = 0; + } + + oleaf->lf_depth = gfs16_to_cpu(oleaf->lf_depth) + 1; + oleaf->lf_depth = cpu_to_gfs16(oleaf->lf_depth); + nleaf->lf_depth = oleaf->lf_depth; + + error = gfs_get_inode_buffer(dip, &dibh); + if (!gfs_assert_withdraw(dip->i_sbd, !error)) { + dip->i_di.di_blocks++; + gfs_dinode_out(&dip->i_di, dibh->b_data); + brelse(dibh); + } + + brelse(obh); + brelse(nbh); + + return error; + + fail_lpfree: + if (unlikely(lp_vfree)) + vfree(lp); + else + kfree(lp); + + fail_brelse: + brelse(obh); + + fail: + brelse(nbh); + return error; +} + +/** + * dir_double_exhash - Double size of ExHash table + * @dip: The GFS dinode + * + * Returns: 0 on success, error code on failure + */ + +static int +dir_double_exhash(struct gfs_inode *dip) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct buffer_head *dibh; + uint32_t hsize; + uint64_t *buf; + uint64_t *from, *to; + uint64_t block; + int x; + int error = 0; + + hsize = 1 << dip->i_di.di_depth; + if (hsize * sizeof(uint64_t) != dip->i_di.di_size) { + gfs_consist_inode(dip); + return -EIO; + } + + /* Allocate both the "from" and "to" buffers in one big chunk */ + + buf = gmalloc(3 * sdp->sd_hash_bsize); + + for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) { + error = gfs_internal_read(dip, (char *)buf, + block * sdp->sd_hash_bsize, + sdp->sd_hash_bsize); + if (error != sdp->sd_hash_bsize) { + if (error >= 0) + error = -EIO; + goto fail; + } + + from = buf; + to = (uint64_t *)((char *)buf + sdp->sd_hash_bsize); + + for (x = sdp->sd_hash_ptrs; x--; from++) { + *to++ = *from; /* No endianess worries */ + *to++ = *from; + } + + error = gfs_internal_write(dip, (char *)buf + sdp->sd_hash_bsize, + block * sdp->sd_sb.sb_bsize, + sdp->sd_sb.sb_bsize); + if (error != sdp->sd_sb.sb_bsize) { + if (error >= 0) + error = -EIO; + goto fail; + } + } + + kfree(buf); + + error = gfs_get_inode_buffer(dip, &dibh); + if (!gfs_assert_withdraw(sdp, !error)) { + dip->i_di.di_depth++; + gfs_dinode_out(&dip->i_di, dibh->b_data); + brelse(dibh); + } + + return error; + + fail: + kfree(buf); + + return error; +} + +/** + * compare_dents - compare directory entries by hash value + * @a: first dent + * @b: second dent + * + * When comparing the hash entries of @a to @b: + * gt: returns 1 + * lt: returns -1 + * eq: returns 0 + */ + +static int +compare_dents(const void *a, const void *b) +{ + struct gfs_dirent *dent_a, *dent_b; + uint32_t hash_a, hash_b; + int ret = 0; + + dent_a = *(struct gfs_dirent **)a; + hash_a = dent_a->de_hash; + hash_a = gfs32_to_cpu(hash_a); + + dent_b = *(struct gfs_dirent **)b; + hash_b = dent_b->de_hash; + hash_b = gfs32_to_cpu(hash_b); + + if (hash_a > hash_b) + ret = 1; + else if (hash_a < hash_b) + ret = -1; + else { + unsigned int len_a = gfs16_to_cpu(dent_a->de_name_len); + unsigned int len_b = gfs16_to_cpu(dent_b->de_name_len); + + if (len_a > len_b) + ret = 1; + else if (len_a < len_b) + ret = -1; + else + ret = memcmp((char *)(dent_a + 1), + (char *)(dent_b + 1), + len_a); + } + + return ret; +} + +/** + * do_filldir_main - read out directory entries + * @dip: The GFS inode + * @offset: The offset in the file to read from + * @opaque: opaque data to pass to filldir + * @filldir: The function to pass entries to + * @darr: an array of struct gfs_dirent pointers to read + * @entries: the number of entries in darr + * @copied: pointer to int that's non-zero if a entry has been copied out + * + * Jump through some hoops to make sure that if there are hash collsions, + * they are read out at the beginning of a buffer. We want to minimize + * the possibility that they will fall into different readdir buffers or + * that someone will want to seek to that location. + * + * Returns: errno, >0 on exception from filldir + */ + +static int +do_filldir_main(struct gfs_inode *dip, uint64_t *offset, + void *opaque, gfs_filldir_t filldir, + struct gfs_dirent **darr, uint32_t entries, int *copied) +{ + struct gfs_dirent *dent, *dent_next; + struct gfs_inum inum; + uint64_t off, off_next; + unsigned int x, y; + int run = FALSE; + int error = 0; + + gfs_sort(darr, entries, sizeof(struct gfs_dirent *), compare_dents); + + dent_next = darr[0]; + off_next = gfs32_to_cpu(dent_next->de_hash); + off_next = gfs_dir_hash2offset(off_next); + + for (x = 0, y = 1; x < entries; x++, y++) { + dent = dent_next; + off = off_next; + + if (y < entries) { + dent_next = darr[y]; + off_next = gfs32_to_cpu(dent_next->de_hash); + off_next = gfs_dir_hash2offset(off_next); + + if (off < *offset) + continue; + *offset = off; + + if (off_next == off) { + if (*copied && !run) + return 1; + run = TRUE; + } else + run = FALSE; + } else { + if (off < *offset) + continue; + *offset = off; + } + + gfs_inum_in(&inum, (char *)&dent->de_inum); + + error = filldir(opaque, (char *)(dent + 1), + gfs16_to_cpu(dent->de_name_len), + off, &inum, + gfs16_to_cpu(dent->de_type)); + if (error) + return 1; + + *copied = TRUE; + } + + /* Increment the *offset by one, so the next time we come into the do_filldir fxn, + we get the next entry instead of the last one in the current leaf */ + + (*offset)++; + + return 0; +} + +/** + * do_filldir_single - Read directory entries out of a single block + * @dip: The GFS inode + * @offset: The offset in the file to read from + * @opaque: opaque data to pass to filldir + * @filldir: The function to pass entries to + * @bh: the block + * @entries: the number of entries in the block + * @copied: pointer to int that's non-zero if a entry has been copied out + * + * Returns: errno, >0 on exception from filldir + */ + +static int +do_filldir_single(struct gfs_inode *dip, uint64_t *offset, + void *opaque, gfs_filldir_t filldir, + struct buffer_head *bh, uint32_t entries, int *copied) +{ + struct gfs_dirent **darr; + struct gfs_dirent *de; + unsigned int e = 0; + int error, do_vfree=0; + + if (!entries) + return 0; + + darr = kmalloc(entries * sizeof(struct gfs_dirent *), GFP_KERNEL); + if (unlikely(!darr)) { + darr = vmalloc(entries * sizeof (struct gfs_dirent *)); + if (!darr) { + printk("GFS: do_filldir_single vmalloc fails, entries=%d\n", entries); + return -ENOMEM; + } + else + do_vfree = 1; + } + + dirent_first(dip, bh, &de); + do { + if (!de->de_inum.no_formal_ino) + continue; + if (e >= entries) { + gfs_consist_inode(dip); + error = -EIO; + goto out; + } + darr[e++] = de; + } + while (dirent_next(dip, bh, &de) == 0); + + if (e != entries) { + gfs_consist_inode(dip); + error = -EIO; + goto out; + } + + error = do_filldir_main(dip, offset, opaque, filldir, darr, + entries, copied); + + out: + if (unlikely(do_vfree)) + vfree(darr); + else + kfree(darr); + + return error; +} + +/** + * do_filldir_multi - Read directory entries out of a linked leaf list + * @dip: The GFS inode + * @offset: The offset in the file to read from + * @opaque: opaque data to pass to filldir + * @filldir: The function to pass entries to + * @bh: the first leaf in the list + * @copied: pointer to int that's non-zero if a entry has been copied out + * + * Returns: errno, >0 on exception from filldir + */ + +static int +do_filldir_multi(struct gfs_inode *dip, uint64_t *offset, + void *opaque, gfs_filldir_t filldir, + struct buffer_head *bh, int *copied) +{ + struct buffer_head **larr = NULL; + struct gfs_dirent **darr; + struct gfs_leaf *leaf; + struct buffer_head *tmp_bh; + struct gfs_dirent *de; + unsigned int entries, e = 0; + unsigned int leaves = 0, l = 0; + unsigned int x; + uint64_t ln; + int error = 0, leaves_vfree=0, entries_vfree=0; + + /* Count leaves and entries */ + + leaf = (struct gfs_leaf *)bh->b_data; + entries = gfs16_to_cpu(leaf->lf_entries); + ln = leaf->lf_next; + + while (ln) { + ln = gfs64_to_cpu(ln); + + error = get_leaf(dip, ln, &tmp_bh); + if (error) + return error; + + leaf = (struct gfs_leaf *)tmp_bh->b_data; + if (leaf->lf_entries) { + entries += gfs16_to_cpu(leaf->lf_entries); + leaves++; + } + ln = leaf->lf_next; + + brelse(tmp_bh); + } + + /* Bail out if there's nothing to do */ + + if (!entries) + return 0; + + /* Alloc arrays */ + + if (leaves) { + larr = kmalloc(leaves * sizeof(struct buffer_head *), GFP_KERNEL); + if (unlikely(!larr)) { + larr = vmalloc(leaves * sizeof (struct buffer_head *)); + if (!larr) { + printk("GFS: do_filldir_multi vmalloc fails leaves=%d\n", leaves); + return -ENOMEM; + } else + leaves_vfree = 1; + } + } + + darr = kmalloc(entries * sizeof(struct gfs_dirent *), GFP_KERNEL); + if (unlikely(!darr)) { + darr = vmalloc(entries * sizeof (struct gfs_dirent *)); + if (!darr) { + printk("GFS: do_filldir_multi vmalloc fails entries=%d\n", entries); + if (larr) { + if (leaves_vfree) + vfree(larr); + else + kfree(larr); + } + return -ENOMEM; + } else + entries_vfree = 1; + } + if (!darr) { + if (larr) + kfree(larr); + return -ENOMEM; + } + + /* Fill in arrays */ + + leaf = (struct gfs_leaf *)bh->b_data; + if (leaf->lf_entries) { + dirent_first(dip, bh, &de); + do { + if (!de->de_inum.no_formal_ino) + continue; + if (e >= entries) { + gfs_consist_inode(dip); + error = -EIO; + goto out; + } + darr[e++] = de; + } + while (dirent_next(dip, bh, &de) == 0); + } + ln = leaf->lf_next; + + while (ln) { + ln = gfs64_to_cpu(ln); + + error = get_leaf(dip, ln, &tmp_bh); + if (error) + goto out; + + leaf = (struct gfs_leaf *)tmp_bh->b_data; + if (leaf->lf_entries) { + dirent_first(dip, tmp_bh, &de); + do { + if (!de->de_inum.no_formal_ino) + continue; + if (e >= entries) { + gfs_consist_inode(dip); + error = -EIO; + goto out; + } + darr[e++] = de; + } + while (dirent_next(dip, tmp_bh, &de) == 0); + + larr[l++] = tmp_bh; + + ln = leaf->lf_next; + } else { + ln = leaf->lf_next; + brelse(tmp_bh); + } + } + + if (gfs_assert_withdraw(dip->i_sbd, l == leaves)) { + error = -EIO; + goto out; + } + if (e != entries) { + gfs_consist_inode(dip); + error = -EIO; + goto out; + } + + /* Do work */ + + error = do_filldir_main(dip, offset, opaque, filldir, darr, + entries, copied); + + /* Clean up */ + + out: + if (unlikely(entries_vfree)) + vfree(darr); + else + kfree(darr); + + for (x = 0; x < l; x++) + brelse(larr[x]); + + if (leaves) { + if (unlikely(leaves_vfree)) + vfree(larr); + else + kfree(larr); + } + + return error; +} + +/** + * dir_e_search - Search exhash (leaf) dir for inode matching name + * @dip: The GFS inode + * @filename: Filename string + * @inode: If non-NULL, function fills with formal inode # and block address + * @type: If non-NULL, function fills with GFS_FILE_... dinode type + * + * Returns: + */ + +static int +dir_e_search(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int *type) +{ + struct buffer_head *bh; + struct gfs_dirent *dent; + int error; + + error = linked_leaf_search(dip, filename, &dent, NULL, &bh); + if (error) + return error; + + if (inum) + gfs_inum_in(inum, (char *)&dent->de_inum); + if (type) + *type = gfs16_to_cpu(dent->de_type); + + brelse(bh); + + return 0; +} + +/** + * dir_e_add - + * @dip: The GFS inode + * @filename: + * @inode: + * @type: + * + */ + +static int +dir_e_add(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int type) +{ + struct buffer_head *bh, *nbh, *dibh; + struct gfs_leaf *leaf, *nleaf; + struct gfs_dirent *dent; + uint32_t hsize, index; + uint32_t hash; + uint64_t leaf_no, bn; + int error; + + restart: + hsize = 1 << dip->i_di.di_depth; + if (hsize * sizeof(uint64_t) != dip->i_di.di_size) { + gfs_consist_inode(dip); + return -EIO; + } + + /* Figure out the address of the leaf node. */ + + hash = gfs_dir_hash(filename->name, filename->len); + index = hash >> (32 - dip->i_di.di_depth); + + error = get_leaf_nr(dip, index, &leaf_no); + if (error) + return error; + + /* Add entry to the leaf */ + + for (;;) { + error = get_leaf(dip, leaf_no, &bh); + if (error) + return error; + + leaf = (struct gfs_leaf *)bh->b_data; + + if (gfs_dirent_alloc(dip, bh, filename->len, &dent)) { + + if (gfs16_to_cpu(leaf->lf_depth) < dip->i_di.di_depth) { + /* Can we split the leaf? */ + + brelse(bh); + + error = dir_split_leaf(dip, index, leaf_no); + if (error) + return error; + + goto restart; + + } else if (dip->i_di.di_depth < GFS_DIR_MAX_DEPTH) { + /* Can we double the hash table? */ + + brelse(bh); + + error = dir_double_exhash(dip); + if (error) + return error; + + goto restart; + + } else if (leaf->lf_next) { + /* Can we try the next leaf in the list? */ + leaf_no = gfs64_to_cpu(leaf->lf_next); + brelse(bh); + continue; + + } else { + /* Create a new leaf and add it to the list. */ + + error = gfs_metaalloc(dip, &bn); + if (error) { + brelse(bh); + return error; + } + + error = gfs_dread(dip->i_gl, bn, + DIO_NEW | DIO_START | DIO_WAIT, + &nbh); + if (error) { + brelse(bh); + return error; + } + + gfs_trans_add_bh(dip->i_gl, nbh); + gfs_metatype_set(nbh, + GFS_METATYPE_LF, + GFS_FORMAT_LF); + gfs_buffer_clear_tail(nbh, + sizeof(struct gfs_meta_header)); + + gfs_trans_add_bh(dip->i_gl, bh); + leaf->lf_next = cpu_to_gfs64(bn); + + nleaf = (struct gfs_leaf *)nbh->b_data; + nleaf->lf_depth = leaf->lf_depth; + nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE); + + gfs_dirent_alloc(dip, nbh, filename->len, &dent); + + dip->i_di.di_blocks++; + + brelse(bh); + + bh = nbh; + leaf = nleaf; + } + } + + /* If the gfs_dirent_alloc() succeeded, it pinned the "bh". */ + + gfs_inum_out(inum, (char *)&dent->de_inum); + dent->de_hash = cpu_to_gfs32(hash); + dent->de_type = cpu_to_gfs16(type); + memcpy((char *)(dent + 1), filename->name, filename->len); + + leaf->lf_entries = gfs16_to_cpu(leaf->lf_entries) + 1; + leaf->lf_entries = cpu_to_gfs16(leaf->lf_entries); + + brelse(bh); + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + dip->i_di.di_entries++; + dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(dip->i_gl, dibh); + gfs_dinode_out(&dip->i_di, dibh->b_data); + brelse(dibh); + + return 0; + } + + return -ENOENT; +} + +/** + * dir_e_del - + * @dip: The GFS inode + * @filename: + * + * Returns: + */ + +static int +dir_e_del(struct gfs_inode *dip, struct qstr *filename) +{ + struct buffer_head *bh, *dibh; + struct gfs_dirent *dent, *prev; + struct gfs_leaf *leaf; + unsigned int entries; + int error; + + error = linked_leaf_search(dip, filename, &dent, &prev, &bh); + if (error == -ENOENT) { + gfs_consist_inode(dip); + return -EIO; + } + if (error) + return error; + + dirent_del(dip, bh, prev, dent); /* Pins bh */ + + leaf = (struct gfs_leaf *)bh->b_data; + entries = gfs16_to_cpu(leaf->lf_entries); + if (!entries) + gfs_consist_inode(dip); + entries--; + leaf->lf_entries = cpu_to_gfs16(entries); + + brelse(bh); + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + if (!dip->i_di.di_entries) + gfs_consist_inode(dip); + dip->i_di.di_entries--; + dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(dip->i_gl, dibh); + gfs_dinode_out(&dip->i_di, dibh->b_data); + brelse(dibh); + + return 0; +} + +/** + * dir_e_read - Reads the entries from a directory into a filldir buffer + * @dip: dinode pointer + * @offset: the hash of the last entry read shifted to the right once + * @opaque: buffer for the filldir function to fill + * @filldir: points to the filldir function to use + * + * Returns: errno + */ + +static int +dir_e_read(struct gfs_inode *dip, uint64_t *offset, void *opaque, + gfs_filldir_t filldir) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct buffer_head *bh; + struct gfs_leaf leaf; + uint32_t hsize, len; + uint32_t ht_offset, lp_offset, ht_offset_cur = -1; + uint32_t hash, index; + uint64_t *lp; + int copied = FALSE; + int error = 0; + + hsize = 1 << dip->i_di.di_depth; + if (hsize * sizeof(uint64_t) != dip->i_di.di_size) { + gfs_consist_inode(dip); + return -EIO; + } + + hash = gfs_dir_offset2hash(*offset); + index = hash >> (32 - dip->i_di.di_depth); + + lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL); + if (!lp) + return -ENOMEM; + + while (index < hsize) { + lp_offset = index & (sdp->sd_hash_ptrs - 1); + ht_offset = index - lp_offset; + + if (ht_offset_cur != ht_offset) { + error = gfs_internal_read(dip, (char *)lp, + ht_offset * sizeof(uint64_t), + sdp->sd_hash_bsize); + if (error != sdp->sd_hash_bsize) { + if (error >= 0) + error = -EIO; + goto out; + } + ht_offset_cur = ht_offset; + } + + error = get_leaf(dip, gfs64_to_cpu(lp[lp_offset]), &bh); + if (error) + goto out; + + gfs_leaf_in(&leaf, bh->b_data); + + if (leaf.lf_next) + error = do_filldir_multi(dip, offset, + opaque, filldir, + bh, &copied); + else + error = do_filldir_single(dip, offset, + opaque, filldir, + bh, leaf.lf_entries, + &copied); + + brelse(bh); + + if (error) { + if (error > 0) + error = 0; + goto out; + } + + len = 1 << (dip->i_di.di_depth - leaf.lf_depth); + index = (index & ~(len - 1)) + len; + } + + out: + kfree(lp); + + return error; +} + +/** + * dir_e_mvino - + * @dip: The GFS inode + * @filename: + * @new_inode: + * + * Returns: + */ + +static int +dir_e_mvino(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int new_type) +{ + struct buffer_head *bh, *dibh; + struct gfs_dirent *dent; + int error; + + error = linked_leaf_search(dip, filename, &dent, NULL, &bh); + if (error == -ENOENT) { + gfs_consist_inode(dip); + return -EIO; + } + if (error) + return error; + + gfs_trans_add_bh(dip->i_gl, bh); + + gfs_inum_out(inum, (char *)&dent->de_inum); + dent->de_type = cpu_to_gfs16(new_type); + + brelse(bh); + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(dip->i_gl, dibh); + gfs_dinode_out(&dip->i_di, dibh->b_data); + brelse(dibh); + + return 0; +} + +/** + * dir_l_search - Search linear (stuffed dinode) dir for inode matching name + * @dip: The GFS inode + * @filename: Filename string + * @inode: If non-NULL, function fills with formal inode # and block address + * @type: If non-NULL, function fills with GFS_FILE_... dinode type + * + * Returns: + */ + +static int +dir_l_search(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int *type) +{ + struct buffer_head *dibh; + struct gfs_dirent *dent; + int error; + + if (!gfs_is_stuffed(dip)) { + gfs_consist_inode(dip); + return -EIO; + } + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + error = leaf_search(dip, dibh, filename, &dent, NULL); + if (!error) { + if (inum) + gfs_inum_in(inum, (char *)&dent->de_inum); + if (type) + *type = gfs16_to_cpu(dent->de_type); + } + + brelse(dibh); + + return error; +} + +/** + * dir_l_add - + * @dip: The GFS inode + * @filename: + * @inode: + * @type: + * + * Returns: + */ + +static int +dir_l_add(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int type) +{ + struct buffer_head *dibh; + struct gfs_dirent *dent; + int error; + + if (!gfs_is_stuffed(dip)) { + gfs_consist_inode(dip); + return -EIO; + } + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + if (gfs_dirent_alloc(dip, dibh, filename->len, &dent)) { + brelse(dibh); + + error = dir_make_exhash(dip); + if (!error) + error = dir_e_add(dip, filename, inum, type); + + return error; + } + + /* gfs_dirent_alloc() pins */ + + gfs_inum_out(inum, (char *)&dent->de_inum); + dent->de_hash = gfs_dir_hash(filename->name, filename->len); + dent->de_hash = cpu_to_gfs32(dent->de_hash); + dent->de_type = cpu_to_gfs16(type); + memcpy((char *)(dent + 1), filename->name, filename->len); + + dip->i_di.di_entries++; + dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + + gfs_dinode_out(&dip->i_di, dibh->b_data); + brelse(dibh); + + return 0; +} + +/** + * dir_l_del - + * @dip: The GFS inode + * @filename: + * + * Returns: + */ + +static int +dir_l_del(struct gfs_inode *dip, struct qstr *filename) +{ + struct buffer_head *dibh; + struct gfs_dirent *dent, *prev; + int error; + + if (!gfs_is_stuffed(dip)) { + gfs_consist_inode(dip); + return -EIO; + } + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + error = leaf_search(dip, dibh, filename, &dent, &prev); + if (error == -ENOENT) { + gfs_consist_inode(dip); + error = -EIO; + goto out; + } + if (error) + goto out; + + dirent_del(dip, dibh, prev, dent); + + /* dirent_del() pins */ + + if (!dip->i_di.di_entries) + gfs_consist_inode(dip); + dip->i_di.di_entries--; + + dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + + gfs_dinode_out(&dip->i_di, dibh->b_data); + + out: + brelse(dibh); + + return error; +} + +/** + * dir_l_read - + * @dip: + * @offset: + * @opaque: + * @filldir: + * + * Returns: + */ + +static int +dir_l_read(struct gfs_inode *dip, uint64_t *offset, void *opaque, + gfs_filldir_t filldir) +{ + struct buffer_head *dibh; + int copied = FALSE; + int error; + + if (!gfs_is_stuffed(dip)) { + gfs_consist_inode(dip); + return -EIO; + } + + if (!dip->i_di.di_entries) + return 0; + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + error = do_filldir_single(dip, offset, + opaque, filldir, + dibh, dip->i_di.di_entries, + &copied); + if (error > 0) + error = 0; + + brelse(dibh); + + return error; +} + +/** + * dir_l_mvino - + * @dip: + * @filename: + * @new_inode: + * + * Returns: + */ + +static int +dir_l_mvino(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int new_type) +{ + struct buffer_head *dibh; + struct gfs_dirent *dent; + int error; + + if (!gfs_is_stuffed(dip)) { + gfs_consist_inode(dip); + return -EIO; + } + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + return error; + + error = leaf_search(dip, dibh, filename, &dent, NULL); + if (error == -ENOENT) { + gfs_consist_inode(dip); + error = -EIO; + goto out; + } + if (error) + goto out; + + gfs_trans_add_bh(dip->i_gl, dibh); + + gfs_inum_out(inum, (char *)&dent->de_inum); + dent->de_type = cpu_to_gfs16(new_type); + + dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + + gfs_dinode_out(&dip->i_di, dibh->b_data); + + out: + brelse(dibh); + + return error; +} + +/** + * gfs_dir_search - Search a directory + * @dip: The GFS inode + * @filename: + * @inode: + * + * This routine searches a directory for a file or another directory. + * Assumes a glock is held on dip. + * + * Returns: errno + */ + +int +gfs_dir_search(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int *type) +{ + int error; + + if (dip->i_di.di_flags & GFS_DIF_EXHASH) + error = dir_e_search(dip, filename, inum, type); + else + error = dir_l_search(dip, filename, inum, type); + + return error; +} + +/** + * gfs_dir_add - Add new filename into directory + * @dip: The GFS inode + * @filename: The new name + * @inode: The inode number of the entry + * @type: The type of the entry + * + * Returns: 0 on success, error code on failure + */ + +int +gfs_dir_add(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int type) +{ + int error; + + if (dip->i_di.di_flags & GFS_DIF_EXHASH) + error = dir_e_add(dip, filename, inum, type); + else + error = dir_l_add(dip, filename, inum, type); + + return error; +} + +/** + * gfs_dir_del - Delete a directory entry + * @dip: The GFS inode + * @filename: The filename + * + * Returns: 0 on success, error code on failure + */ + +int +gfs_dir_del(struct gfs_inode *dip, struct qstr *filename) +{ + int error; + + if (dip->i_di.di_flags & GFS_DIF_EXHASH) + error = dir_e_del(dip, filename); + else + error = dir_l_del(dip, filename); + + return error; +} + +/** + * gfs_dir_read - Translate a GFS filename + * @dip: The GFS inode + * @offset: + * @opaque: + * @filldir: + * + * Returns: 0 on success, error code otherwise + */ + +int +gfs_dir_read(struct gfs_inode *dip, uint64_t * offset, void *opaque, + gfs_filldir_t filldir) +{ + int error; + + if (dip->i_di.di_flags & GFS_DIF_EXHASH) + error = dir_e_read(dip, offset, opaque, filldir); + else + error = dir_l_read(dip, offset, opaque, filldir); + + return error; +} + +/** + * gfs_dir_mvino - Change inode number of directory entry + * @dip: The GFS inode + * @filename: + * @new_inode: + * + * This routine changes the inode number of a directory entry. It's used + * by rename to change ".." when a directory is moved. + * Assumes a glock is held on dvp. + * + * Returns: errno + */ + +int +gfs_dir_mvino(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int new_type) +{ + int error; + + if (dip->i_di.di_flags & GFS_DIF_EXHASH) + error = dir_e_mvino(dip, filename, inum, new_type); + else + error = dir_l_mvino(dip, filename, inum, new_type); + + return error; +} + +/** + * foreach_leaf - call a function for each leaf in a directory + * @dip: the directory + * @lc: the function to call for each each + * @data: private data to pass to it + * + * Returns: errno + */ + +static int +foreach_leaf(struct gfs_inode *dip, leaf_call_t lc, void *data) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct buffer_head *bh; + struct gfs_leaf leaf; + uint32_t hsize, len; + uint32_t ht_offset, lp_offset, ht_offset_cur = -1; + uint32_t index = 0; + uint64_t *lp; + uint64_t leaf_no; + int error = 0; + + hsize = 1 << dip->i_di.di_depth; + if (hsize * sizeof(uint64_t) != dip->i_di.di_size) { + gfs_consist_inode(dip); + return -EIO; + } + + lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL); + if (!lp) + return -ENOMEM; + + while (index < hsize) { + lp_offset = index & (sdp->sd_hash_ptrs - 1); + ht_offset = index - lp_offset; + + if (ht_offset_cur != ht_offset) { + error = gfs_internal_read(dip, (char *)lp, + ht_offset * sizeof(uint64_t), + sdp->sd_hash_bsize); + if (error != sdp->sd_hash_bsize) { + if (error >= 0) + error = -EIO; + goto out; + } + ht_offset_cur = ht_offset; + } + + leaf_no = gfs64_to_cpu(lp[lp_offset]); + if (leaf_no) { + error = get_leaf(dip, leaf_no, &bh); + if (error) + goto out; + gfs_leaf_in(&leaf, bh->b_data); + brelse(bh); + + len = 1 << (dip->i_di.di_depth - leaf.lf_depth); + + error = lc(dip, index, len, leaf_no, data); + if (error) + goto out; + + index = (index & ~(len - 1)) + len; + } else + index++; + } + + if (index != hsize) { + gfs_consist_inode(dip); + error = -EIO; + } + + out: + kfree(lp); + + return error; +} + +/** + * leaf_free - Deallocate a directory leaf + * @dip: the directory + * @index: the hash table offset in the directory + * @len: the number of pointers to this leaf + * @leaf_no: the leaf number + * @data: not used + * + * Returns: errno + */ + +static int +leaf_free(struct gfs_inode *dip, + uint32_t index, uint32_t len, + uint64_t leaf_no, void *data) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_leaf tmp_leaf; + struct gfs_rgrp_list rlist; + struct buffer_head *bh, *dibh; + uint64_t blk; + unsigned int rg_blocks = 0; + char *ht=0; + unsigned int x, size = len * sizeof(uint64_t); + int error; + + memset(&rlist, 0, sizeof(struct gfs_rgrp_list)); + + gfs_alloc_get(dip); + + error = gfs_quota_hold_m(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto out; + + error = gfs_rindex_hold(sdp, &dip->i_alloc->al_ri_gh); + if (error) + goto out_qs; + + /* Count the number of leaves */ + + for (blk = leaf_no; blk; blk = tmp_leaf.lf_next) { + error = get_leaf(dip, blk, &bh); + if (error) + goto out_rlist; + gfs_leaf_in(&tmp_leaf, (bh)->b_data); + brelse(bh); + + gfs_rlist_add(sdp, &rlist, blk); + } + + gfs_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); + + for (x = 0; x < rlist.rl_rgrps; x++) { + struct gfs_rgrpd *rgd; + rgd = get_gl2rgd(rlist.rl_ghs[x].gh_gl); + rg_blocks += rgd->rd_ri.ri_length; + } + + error = gfs_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); + if (error) + goto out_rlist; + + /* Trans may require: + All the bitmaps that were reserved. + One block for the dinode. + All the hash blocks that will be changed. + One block for a quota change. */ + + error = gfs_trans_begin(sdp, + rg_blocks + 1 + (DIV_RU(size, sdp->sd_jbsize) + 1), + 1); + if (error) + goto out_rg_gunlock; + + for (blk = leaf_no; blk; blk = tmp_leaf.lf_next) { + error = get_leaf(dip, blk, &bh); + if (error) + goto out_end_trans; + gfs_leaf_in(&tmp_leaf, bh->b_data); + brelse(bh); + + gfs_metafree(dip, blk, 1); + + if (!dip->i_di.di_blocks) + gfs_consist_inode(dip); + dip->i_di.di_blocks--; + } + + error = gfs_writei(dip, ht, index * sizeof (uint64_t), size, gfs_zero_blocks, NULL); + + if (error != size) { + if (error >= 0) + error = -EIO; + goto out_end_trans; + } + + error = gfs_get_inode_buffer(dip, &dibh); + if (error) + goto out_end_trans; + + gfs_trans_add_bh(dip->i_gl, dibh); + gfs_dinode_out(&dip->i_di, dibh->b_data); + brelse(dibh); + + out_end_trans: + gfs_trans_end(sdp); + + out_rg_gunlock: + gfs_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs); + + out_rlist: + gfs_rlist_free(&rlist); + gfs_glock_dq_uninit(&dip->i_alloc->al_ri_gh); + + out_qs: + gfs_quota_unhold_m(dip); + + out: + gfs_alloc_put(dip); + + return error; +} + +/** + * gfs_dir_exhash_free - free all the leaf blocks in a directory + * @dip: the directory + * + * Dealloc all on-disk directory leaves to FREEMETA state + * Change on-disk inode type to "regular file" + * + * Returns: errno + */ + +int +gfs_dir_exhash_free(struct gfs_inode *dip) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct buffer_head *bh; + int error; + + /* Dealloc on-disk leaves to FREEMETA state */ + error = foreach_leaf(dip, leaf_free, NULL); + if (error) + return error; + + /* Make this a regular file in case we crash. + (We don't want to free these blocks a second time.) */ + + error = gfs_trans_begin(sdp, 1, 0); + if (error) + return error; + + error = gfs_get_inode_buffer(dip, &bh); + if (!error) { + gfs_trans_add_bh(dip->i_gl, bh); + ((struct gfs_dinode *)bh->b_data)->di_type = cpu_to_gfs16(GFS_FILE_REG); + brelse(bh); + } + + gfs_trans_end(sdp); + + return error; +} + +/** + * gfs_diradd_alloc_required - figure out if an entry addition is going to require an allocation + * @ip: the file being written to + * @filname: the filename that's going to be added + * @alloc_required: the int is set to TRUE if an alloc is required, FALSE otherwise + * + * Returns: errno + */ + +int +gfs_diradd_alloc_required(struct gfs_inode *dip, struct qstr *filename, + int *alloc_required) +{ + struct buffer_head *bh = NULL, *bh_next; + uint32_t hsize, hash, index; + int error = 0; + + *alloc_required = FALSE; + + if (dip->i_di.di_flags & GFS_DIF_EXHASH) { + hsize = 1 << dip->i_di.di_depth; + if (hsize * sizeof(uint64_t) != dip->i_di.di_size) { + gfs_consist_inode(dip); + return -EIO; + } + + hash = gfs_dir_hash(filename->name, filename->len); + index = hash >> (32 - dip->i_di.di_depth); + + error = get_first_leaf(dip, index, &bh_next); + if (error) + return error; + + do { + if (bh) + brelse(bh); + + bh = bh_next; + + if (dirent_fits(dip, bh, filename->len)) + break; + + error = get_next_leaf(dip, bh, &bh_next); + if (error == -ENOENT) { + *alloc_required = TRUE; + error = 0; + break; + } + } + while (!error); + + brelse(bh); + } else { + error = gfs_get_inode_buffer(dip, &bh); + if (error) + return error; + + if (!dirent_fits(dip, bh, filename->len)) + *alloc_required = TRUE; + + brelse(bh); + } + + return error; +} + +/** + * do_gdm - copy out one leaf (or list of leaves) + * @dip: the directory + * @index: the hash table offset in the directory + * @len: the number of pointers to this leaf + * @leaf_no: the leaf number + * @data: a pointer to a struct gfs_user_buffer structure + * + * Returns: errno + */ + +static int +do_gdm(struct gfs_inode *dip, + uint32_t index, uint32_t len, uint64_t leaf_no, + void *data) +{ + struct gfs_user_buffer *ub = (struct gfs_user_buffer *)data; + struct gfs_leaf leaf; + struct buffer_head *bh; + uint64_t blk; + int error = 0; + + for (blk = leaf_no; blk; blk = leaf.lf_next) { + error = get_leaf(dip, blk, &bh); + if (error) + break; + + gfs_leaf_in(&leaf, bh->b_data); + + error = gfs_add_bh_to_ub(ub, bh); + + brelse(bh); + + if (error) + break; + } + + return error; +} + +/** + * gfs_get_dir_meta - return all the leaf blocks of a directory + * @dip: the directory + * @ub: the structure representing the meta + * + * Returns: errno + */ + +int +gfs_get_dir_meta(struct gfs_inode *dip, struct gfs_user_buffer *ub) +{ + return foreach_leaf(dip, do_gdm, ub); +} --- linux-2.6.27.orig/ubuntu/gfs/mount.c +++ linux-2.6.27/ubuntu/gfs/mount.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "mount.h" +#include "proc.h" +#include "sys.h" + +/** + * gfs_make_args - Parse mount arguments + * @data: + * @args: + * + * Return: errno + */ + +int +gfs_make_args(char *data_arg, struct gfs_args *args, int remount) +{ + char *data = data_arg; + char *options, *x, *y; + int error = 0; + + /* If someone preloaded options, use those instead */ + + spin_lock(&gfs_proc_margs_lock); + if (!remount && gfs_proc_margs) { + data = gfs_proc_margs; + gfs_proc_margs = NULL; + } + spin_unlock(&gfs_proc_margs_lock); + + /* Set some defaults */ + + memset(args, 0, sizeof(struct gfs_args)); + args->ar_num_glockd = GFS_GLOCKD_DEFAULT; + + if (!remount) { + /* If someone preloaded options, use those instead */ + spin_lock(&gfs_sys_margs_lock); + if (gfs_sys_margs) { + data = gfs_sys_margs; + gfs_sys_margs = NULL; + } + spin_unlock(&gfs_sys_margs_lock); + + /* Set some defaults */ + args->ar_num_glockd = GFS_GLOCKD_DEFAULT; + } + + /* Split the options into tokens with the "," character and + process them */ + + for (options = data; (x = strsep(&options, ",")); ) { + if (!*x) + continue; + + y = strchr(x, '='); + if (y) + *y++ = 0; + + if (!strcmp(x, "lockproto")) { + if (!y) { + printk("GFS: need argument to lockproto\n"); + error = -EINVAL; + break; + } + strncpy(args->ar_lockproto, y, GFS_LOCKNAME_LEN); + args->ar_lockproto[GFS_LOCKNAME_LEN - 1] = 0; + } + + else if (!strcmp(x, "locktable")) { + if (!y) { + printk("GFS: need argument to locktable\n"); + error = -EINVAL; + break; + } + strncpy(args->ar_locktable, y, GFS_LOCKNAME_LEN); + args->ar_locktable[GFS_LOCKNAME_LEN - 1] = 0; + } + + else if (!strcmp(x, "hostdata")) { + if (!y) { + printk("GFS: need argument to hostdata\n"); + error = -EINVAL; + break; + } + strncpy(args->ar_hostdata, y, GFS_LOCKNAME_LEN); + args->ar_hostdata[GFS_LOCKNAME_LEN - 1] = 0; + } + + else if (!strcmp(x, "spectator")) + args->ar_spectator = TRUE; + + else if (!strcmp(x, "ignore_local_fs")) + args->ar_ignore_local_fs = TRUE; + + else if (!strcmp(x, "localflocks")) + args->ar_localflocks = TRUE; + + else if (!strcmp(x, "localcaching")) + args->ar_localcaching = TRUE; + + else if (!strcmp(x, "oopses_ok")) + args->ar_oopses_ok = TRUE; + + else if (!strcmp(x, "debug")) { + args->ar_oopses_ok = TRUE; + args->ar_debug = TRUE; + + } else if (!strcmp(x, "upgrade")) + args->ar_upgrade = TRUE; + + else if (!strcmp(x, "num_glockd")) { + if (!y) { + printk("GFS: need argument to num_glockd\n"); + error = -EINVAL; + break; + } + sscanf(y, "%u", &args->ar_num_glockd); + if (!args->ar_num_glockd || args->ar_num_glockd > GFS_GLOCKD_MAX) { + printk("GFS: 0 < num_glockd <= %u (not %u)\n", + GFS_GLOCKD_MAX, args->ar_num_glockd); + error = -EINVAL; + break; + } + } + + else if (!strcmp(x, "acl")) + args->ar_posix_acls = TRUE; + + else if (!strcmp(x, "noacl")) + args->ar_posix_acls = FALSE; + + else if (!strcmp(x, "suiddir")) + args->ar_suiddir = TRUE; + + else if (!strcmp(x, "noquota")) + args->ar_noquota = TRUE; + + /* Unknown */ + + else { + printk("GFS: unknown option: %s\n", x); + error = -EINVAL; + break; + } + } + + if (error) + printk("GFS: invalid mount option(s)\n"); + + if (data != data_arg) + kfree(data); + + return error; +} + --- linux-2.6.27.orig/ubuntu/gfs/ops_super.h +++ linux-2.6.27/ubuntu/gfs/ops_super.h @@ -0,0 +1,6 @@ +#ifndef __OPS_SUPER_DOT_H__ +#define __OPS_SUPER_DOT_H__ + +extern struct super_operations gfs_super_ops; + +#endif /* __OPS_SUPER_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/log.c +++ linux-2.6.27/ubuntu/gfs/log.c @@ -0,0 +1,1429 @@ +/* + What rolls down stairs + Alone or in pairs + Rolls over your neighbor's dog. + What's great for a snack + And fits on your back + It's log, log, log! + It's lo-og, lo-og, + It's big, it's heavy, it's wood. + It's lo-og, lo-og, + It's better than bad, it's good. + Everyone wants a log, + You're gonna love it, log + Come on and get your log, + Everyone needs a log... + LOG... FROM BLAMMO! + + -- The Ren and Stimpy Show +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "log.h" +#include "lops.h" + +/** + * gfs_struct2blk - compute stuff + * @sdp: the filesystem + * @nstruct: the number of structures + * @ssize: the size of the structures + * + * Compute the number of log descriptor blocks needed to hold a certain number + * of structures of a certain size. + * + * Returns: the number of blocks needed (minimum is always 1) + */ + +unsigned int +gfs_struct2blk(struct gfs_sbd *sdp, unsigned int nstruct, unsigned int ssize) +{ + unsigned int blks; + unsigned int first, second; + + blks = 1; + first = (sdp->sd_sb.sb_bsize - sizeof(struct gfs_log_descriptor)) / ssize; + + if (nstruct > first) { + second = sdp->sd_sb.sb_bsize / ssize; + blks += DIV_RU(nstruct - first, second); + } + + return blks; +} + +/** + * gfs_blk2seg - Convert number of blocks into number of segments + * @sdp: The GFS superblock + * @blocks: The number of blocks + * + * Returns: The number of journal segments + */ + +unsigned int +gfs_blk2seg(struct gfs_sbd *sdp, unsigned int blocks) +{ + return DIV_RU(blocks, sdp->sd_sb.sb_seg_size - 1); +} + +/** + * log_distance - Compute distance between two journal blocks + * @sdp: The GFS superblock + * @newer: The most recent journal block of the pair + * @older: The older journal block of the pair + * + * Compute the distance (in the journal direction) between two + * blocks in the journal + * + * Returns: the distance in blocks + */ + +static __inline__ unsigned int +log_distance(struct gfs_sbd *sdp, uint64_t newer, uint64_t older) +{ + int64_t dist; + + dist = newer - older; + if (dist < 0) + dist += sdp->sd_jdesc.ji_nsegment * sdp->sd_sb.sb_seg_size; + + return dist; +} + +/** + * log_incr_head - Increment journal head (next block to fill in journal) + * @sdp: The GFS superblock + * @head: the variable holding the head of the journal + * + * Increment journal head by one. + * At the end of the journal, wrap head back to the start. + * Don't confuse journal/log head with a gfs_log_header! + */ + +static __inline__ void +log_incr_head(struct gfs_sbd *sdp, uint64_t * head) +{ + struct gfs_jindex *jdesc = &sdp->sd_jdesc; + + if (++*head == + jdesc->ji_addr + jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size) + *head = jdesc->ji_addr; +} + +/** + * gfs_ail_start - Start I/O on the AIL + * @sdp: the filesystem + * @flags: DIO_ALL -- flush *all* AIL transactions to disk + * default -- flush first-on-list AIL transaction to disk + * + */ + +void +gfs_ail_start(struct gfs_sbd *sdp, int flags) +{ + struct list_head *head = &sdp->sd_log_ail; + struct list_head *first, *tmp; + struct gfs_trans *first_tr, *tr; + + gfs_log_lock(sdp); + + if (list_empty(head)) { + gfs_log_unlock(sdp); + return; + } + + first = head->prev; + first_tr = list_entry(first, struct gfs_trans, tr_list); + gfs_ail_start_trans(sdp, first_tr); + + if (flags & DIO_ALL) + first_tr = NULL; + + for (tmp = first->prev; tmp != head; tmp = tmp->prev) { + if (first_tr && gfs_ail_empty_trans(sdp, first_tr)) + break; + + tr = list_entry(tmp, struct gfs_trans, tr_list); + gfs_ail_start_trans(sdp, tr); + } + + gfs_log_unlock(sdp); +} + +/** + * current_tail - Find block number of current log tail + * @sdp: The GFS superblock + * + * Find the block number of the current tail of the log. + * Assumes that the log lock is held. + * + * Returns: The tail's block number (must be on a log segment boundary) + */ + +static uint64_t +current_tail(struct gfs_sbd *sdp) +{ + struct gfs_trans *tr; + uint64_t tail; + + if (list_empty(&sdp->sd_log_ail)) { + tail = sdp->sd_log_head; + + if (!gfs_log_is_header(sdp, tail)) { + tail--; + gfs_assert(sdp, gfs_log_is_header(sdp, tail), ); + } + } else { + tr = list_entry(sdp->sd_log_ail.prev, + struct gfs_trans, tr_list); + tail = tr->tr_first_head; + } + + return tail; +} + +/** + * gfs_ail_empty - move the tail of the log forward (if possible) + * @sdp: the filesystem + * + * Returns: TRUE if the AIL is empty + * + * Checks each transaction on sd_log_ail, to see if it has been successfully + * flushed to in-place blocks on disk. If so, removes trans from sd_log_ail, + * effectively advancing the tail of the log (freeing log segments so they + * can be overwritten). + * Adds # freed log segments to sd_log_seg_free. + */ + +int +gfs_ail_empty(struct gfs_sbd *sdp) +{ + struct list_head *head, *tmp, *prev; + struct gfs_trans *tr; + uint64_t oldtail, newtail; + unsigned int dist; + unsigned int segments; + int ret; + + gfs_log_lock(sdp); + + oldtail = current_tail(sdp); + + for (head = &sdp->sd_log_ail, tmp = head->prev, prev = tmp->prev; + tmp != head; + tmp = prev, prev = tmp->prev) { + tr = list_entry(tmp, struct gfs_trans, tr_list); + if (gfs_ail_empty_trans(sdp, tr)) { + list_del(&tr->tr_list); + kfree(tr); + } + } + + newtail = current_tail(sdp); + + if (oldtail != newtail) { + dist = log_distance(sdp, newtail, oldtail); + + segments = dist / sdp->sd_sb.sb_seg_size; + gfs_assert(sdp, segments * sdp->sd_sb.sb_seg_size == dist,); + + sdp->sd_log_seg_ail2 += segments; + gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <= + sdp->sd_jdesc.ji_nsegment,); + } + + ret = list_empty(head); + + gfs_log_unlock(sdp); + + return ret; +} + +/** + * gfs_log_reserve - Make a log reservation + * @sdp: The GFS superblock + * @segments: The number of segments to reserve + * @jump_queue: if TRUE, don't care about fairness ordering + * + * Returns: errno + */ + +int +gfs_log_reserve(struct gfs_sbd *sdp, unsigned int segments, int jump_queue) +{ + struct list_head list; + unsigned int try = 0; + + if (gfs_assert_warn(sdp, segments)) + return -EINVAL; + if (gfs_assert_warn(sdp, segments < sdp->sd_jdesc.ji_nsegment)) + return -EINVAL; + + INIT_LIST_HEAD(&list); + + for (;;) { + spin_lock(&sdp->sd_log_seg_lock); + + if (list_empty(&list)) { + if (jump_queue) + list_add(&list, &sdp->sd_log_seg_list); + else { + list_add_tail(&list, &sdp->sd_log_seg_list); + while (sdp->sd_log_seg_list.next != &list) { + DECLARE_WAITQUEUE(__wait_chan, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&sdp->sd_log_seg_wait, + &__wait_chan); + spin_unlock(&sdp->sd_log_seg_lock); + schedule(); + spin_lock(&sdp->sd_log_seg_lock); + remove_wait_queue(&sdp->sd_log_seg_wait, + &__wait_chan); + set_current_state(TASK_RUNNING); + } + } + } + + if (sdp->sd_log_seg_free > segments) { + sdp->sd_log_seg_free -= segments; + list_del(&list); + spin_unlock(&sdp->sd_log_seg_lock); + wake_up(&sdp->sd_log_seg_wait); + break; + } + + spin_unlock(&sdp->sd_log_seg_lock); + + if (try) { + gfs_log_flush(sdp); + gfs_ail_start(sdp, 0); + } + + gfs_ail_empty(sdp); + + try++; + yield(); + } + + return 0; +} + +/** + * gfs_log_release - Release a given number of log segments + * @sdp: The GFS superblock + * @segments: The number of segments + * + */ + +void +gfs_log_release(struct gfs_sbd *sdp, unsigned int segments) +{ + spin_lock(&sdp->sd_log_seg_lock); + sdp->sd_log_seg_free += segments; + gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <= + sdp->sd_jdesc.ji_nsegment,); + spin_unlock(&sdp->sd_log_seg_lock); +} + +/** + * log_get_header - Get and initialize a journal header buffer + * @sdp: The GFS superblock + * @tr: The transaction that needs a log header + * @next: FALSE if this log header appears in midst of current transaction + * TRUE if this starts next transaction (and commits current trans) + * + * Returns: the initialized log buffer descriptor + * + * Initialize one of the transaction's pre-allocated buffers (and associated + * log buffer descriptor) to be a log header for this transaction. + * A log header gets written to *each* log segment boundary block, so journal + * recovery will quickly be able to get its bearings. A single transaction + * may span several log segments, which means that log headers will appear + * in the midst of that transaction (@next == FALSE). These headers get + * added to trans' list of buffers to write to log. + * Log commit is accomplished by writing the log header for the next + * transaction (@next == TRUE), with pre-incremented sequence number, + * and updated first-in-transaction block number. These headers do *not* get + * added to trans' buffer list, since they are written separately to disk + * *after* the trans gets completely flushed to on-disk log. + * NOTE: This buffer will *not* get written to an in-place location in the + * filesystem; it is for use only within the log. + */ + +static struct gfs_log_buf * +log_get_header(struct gfs_sbd *sdp, struct gfs_trans *tr, int next) +{ + struct gfs_log_buf *lb; + struct list_head *bmem; + struct gfs_log_header header; + + /* Make sure we're on a log segment boundary block */ + gfs_assert(sdp, gfs_log_is_header(sdp, tr->tr_log_head),); + + /* Grab a free log buffer descriptor (attached to trans) */ + gfs_assert(sdp, tr->tr_num_free_bufs && + !list_empty(&tr->tr_free_bufs),); + lb = list_entry(tr->tr_free_bufs.next, struct gfs_log_buf, lb_list); + list_del(&lb->lb_list); + tr->tr_num_free_bufs--; + + /* Grab a free log buffer (attached to trans) */ + gfs_assert(sdp, tr->tr_num_free_bmem && + !list_empty(&tr->tr_free_bmem),); + bmem = tr->tr_free_bmem.next; + list_del(bmem); + tr->tr_num_free_bmem--; + + /* Create "fake" bh to write bmem to log header block */ + gfs_logbh_init(sdp, &lb->lb_bh, tr->tr_log_head, (char *)bmem); + memset(bmem, 0, sdp->sd_sb.sb_bsize); + + memset(&header, 0, sizeof (header)); + + if (next) { + /* Fill in header for next transaction, committing previous */ + header.lh_header.mh_magic = GFS_MAGIC; + header.lh_header.mh_type = GFS_METATYPE_LH; + header.lh_header.mh_format = GFS_FORMAT_LH; + header.lh_first = tr->tr_log_head; + header.lh_sequence = sdp->sd_sequence + 1; + header.lh_tail = current_tail(sdp); + header.lh_last_dump = sdp->sd_log_dump_last; + } else { + /* Fill in another header for this transaction */ + header.lh_header.mh_magic = GFS_MAGIC; + header.lh_header.mh_type = GFS_METATYPE_LH; + header.lh_header.mh_format = GFS_FORMAT_LH; + header.lh_first = tr->tr_first_head; + header.lh_sequence = sdp->sd_sequence; + header.lh_tail = current_tail(sdp); + header.lh_last_dump = sdp->sd_log_dump_last; + + /* Attach log header buf to trans' list of bufs going to log */ + list_add(&lb->lb_list, &tr->tr_bufs); + } + + /* Copy log header struct to beginning and end of buffer's 1st 512B */ + gfs_log_header_out(&header, lb->lb_bh.b_data); + gfs_log_header_out(&header, + lb->lb_bh.b_data + GFS_BASIC_BLOCK - + sizeof(struct gfs_log_header)); + + /* Find next log buffer to fill */ + log_incr_head(sdp, &tr->tr_log_head); + + return lb; +} + +/** + * gfs_log_get_buf - Get and initialize a buffer to use for log control data + * @sdp: The GFS superblock + * @tr: The GFS transaction + * + * Initialize one of the transaction's pre-allocated buffers (and associated + * log buffer descriptor) to be used for log control data (e.g. log tags). + * Make sure this buffer is attached to the transaction, to be logged to disk. + * NOTE: This buffer will *not* get written to an in-place location in the + * filesystem; it is for use only within the log. + * + * Returns: the log buffer descriptor + */ + +struct gfs_log_buf * +gfs_log_get_buf(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct gfs_log_buf *lb; + struct list_head *bmem; + + /* If next block in log is on a segment boundary, we need to + write a log header */ + if (gfs_log_is_header(sdp, tr->tr_log_head)) + log_get_header(sdp, tr, FALSE); + + /* Grab a free buffer descriptor (attached to trans) */ + gfs_assert(sdp, tr->tr_num_free_bufs && + !list_empty(&tr->tr_free_bufs),); + lb = list_entry(tr->tr_free_bufs.next, struct gfs_log_buf, lb_list); + list_del(&lb->lb_list); + tr->tr_num_free_bufs--; + + /* Grab a free buffer (attached to trans) */ + gfs_assert(sdp, tr->tr_num_free_bmem + && !list_empty(&tr->tr_free_bmem),); + bmem = tr->tr_free_bmem.next; + list_del(bmem); + tr->tr_num_free_bmem--; + + /* Create "fake" bh to write bmem to log block */ + gfs_logbh_init(sdp, &lb->lb_bh, tr->tr_log_head, (char *)bmem); + memset(bmem, 0, sdp->sd_sb.sb_bsize); + + list_add(&lb->lb_list, &tr->tr_bufs); + + /* Find next log buffer to fill */ + log_incr_head(sdp, &tr->tr_log_head); + + return lb; +} + +/** + * gfs_log_fake_buf - Build a fake buffer head to write metadata buffer to log + * @sdp: the filesystem + * @tr: the transaction this is part of + * @data: the data the buffer_head should point to + * @unlock: a buffer_head to be unlocked when struct gfs_log_buf is torn down + * (i.e. the "real" buffer_head that will write to in-place location) + * + * Initialize one of the transaction's pre-allocated log buffer descriptors + * to be used for writing a metadata buffer into the log. + * Make sure this buffer is attached to the transaction, to be logged to disk. + * NOTE: This buffer *will* be written to in-place location within filesytem, + * in addition to being written into the log. + * + */ + +void +gfs_log_fake_buf(struct gfs_sbd *sdp, struct gfs_trans *tr, char *data, + struct buffer_head *unlock) +{ + struct gfs_log_buf *lb; + + if (gfs_log_is_header(sdp, tr->tr_log_head)) + log_get_header(sdp, tr, FALSE); + + /* Grab a free buffer descriptor (attached to trans) */ + gfs_assert(sdp, tr->tr_num_free_bufs && + !list_empty(&tr->tr_free_bufs),); + lb = list_entry(tr->tr_free_bufs.next, struct gfs_log_buf, lb_list); + list_del(&lb->lb_list); + tr->tr_num_free_bufs--; + + /* Create "fake" bh to write data to log block */ + gfs_logbh_init(sdp, &lb->lb_bh, tr->tr_log_head, data); + lb->lb_unlock = unlock; + + list_add(&lb->lb_list, &tr->tr_bufs); + + /* Find next log buffer to fill */ + log_incr_head(sdp, &tr->tr_log_head); +} + +/** + * check_seg_usage - Check that we didn't use too many segments + * @sdp: The GFS superblock + * @tr: The transaction + * + * Also, make sure we don't write ever get to a point where there are + * no dumps in the log (corrupting the log). Panic before we let + * that happen. + * + */ + +static void +check_seg_usage(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct gfs_jindex *jdesc = &sdp->sd_jdesc; + unsigned int dist; + unsigned int segments; + uint64_t head_off, head_wrap; + uint64_t dump_off, dump_wrap; + + dist = log_distance(sdp, tr->tr_log_head, tr->tr_first_head); + + segments = dist / sdp->sd_sb.sb_seg_size; + gfs_assert(sdp, segments * sdp->sd_sb.sb_seg_size == dist,); + gfs_assert(sdp, segments == tr->tr_seg_reserved,); + + if (sdp->sd_log_dump_last) { + int diff; + + head_off = tr->tr_first_head + + tr->tr_seg_reserved * sdp->sd_sb.sb_seg_size; + head_wrap = sdp->sd_log_wrap; + if (head_off >= jdesc->ji_addr + + jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size) { + head_off -= jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size; + head_wrap++; + } + + dump_off = sdp->sd_log_dump_last; + dump_wrap = sdp->sd_log_dump_last_wrap; + + diff = (int)(head_wrap - dump_wrap); + switch (diff) { + case 0: + break; + + case 1: + if (head_off < dump_off - sdp->sd_sb.sb_seg_size) + break; + else if (head_off <= dump_off && + (tr->tr_flags & TRF_LOG_DUMP)) + break; + + default: + gfs_assert(sdp, FALSE, + printk("GFS: fsid=%s: head_off = %"PRIu64", head_wrap = %"PRIu64"\n" + "GFS: fsid=%s: dump_off = %"PRIu64", dump_wrap = %"PRIu64"\n", + sdp->sd_fsname, head_off, head_wrap, + sdp->sd_fsname, dump_off, dump_wrap);); + break; + } + } +} + +/** + * log_free_buf - Free a struct gfs_log_buf (and possibly the data it points to) + * @sdp: the filesystem + * @lb: the log buffer descriptor + * + * If buffer contains (meta)data to be written into filesystem in-place block, + * descriptor will point to the "real" (lb_unlock) buffer head. Unlock it. + * If buffer was used only for log header or control data (e.g. tags), we're + * done with it as soon as it gets written to on-disk log. Free it. + * Either way, we can free the log descriptor structure. + */ + +static void +log_free_buf(struct gfs_sbd *sdp, struct gfs_log_buf *lb) +{ + char *bmem; + + bmem = lb->lb_bh.b_data; + gfs_logbh_uninit(sdp, &lb->lb_bh); + + if (lb->lb_unlock) + gfs_unlock_buffer(lb->lb_unlock); + else + kfree(bmem); + + kfree(lb); +} + +/** + * sync_trans - Add "last" descriptor, sync transaction to on-disk log + * @sdp: The GFS superblock + * @tr: The transaction + * + * Add the "last" descriptor onto the end of the current transaction + * and sync the whole transaction out to on-disk log. + * Don't log-commit (i.e. write next transaction's log header) yet, though. + * + * Returns: errno + */ + +static int +sync_trans(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *tmp, *head, *prev; + struct gfs_log_descriptor desc; + struct gfs_log_buf *lb; + uint64_t blk; + int error = 0, e; + + /* Build LAST descriptor */ + + lb = gfs_log_get_buf(sdp, tr); + + memset(&desc, 0, sizeof(struct gfs_log_descriptor)); + desc.ld_header.mh_magic = GFS_MAGIC; + desc.ld_header.mh_type = GFS_METATYPE_LD; + desc.ld_header.mh_format = GFS_FORMAT_LD; + desc.ld_type = GFS_LOG_DESC_LAST; + desc.ld_length = 1; + for (blk = tr->tr_log_head; !gfs_log_is_header(sdp, blk); blk++) + desc.ld_length++; + gfs_desc_out(&desc, lb->lb_bh.b_data); + + while (!gfs_log_is_header(sdp, tr->tr_log_head)) + log_incr_head(sdp, &tr->tr_log_head); + + check_seg_usage(sdp, tr); + + /* Start I/O + Go in "prev" direction to start the I/O in order. */ + + for (head = &tr->tr_bufs, tmp = head->prev, prev = tmp->prev; + tmp != head; + tmp = prev, prev = tmp->prev) { + lb = list_entry(tmp, struct gfs_log_buf, lb_list); + gfs_logbh_start(sdp, &lb->lb_bh); + } + + /* Wait on I/O + Go in "next" direction to minimize sleeps/wakeups. */ + + while (!list_empty(&tr->tr_bufs)) { + lb = list_entry(tr->tr_bufs.next, struct gfs_log_buf, lb_list); + + e = gfs_logbh_wait(sdp, &lb->lb_bh); + if (e) + error = e; + + list_del(&lb->lb_list); + log_free_buf(sdp, lb); + } + + return error; +} + +/** + * commit_trans - Commit the current transaction + * @sdp: The GFS superblock + * @tr: The transaction + * + * Write next header to commit + * + * Returns: errno + */ + +static int +commit_trans(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct gfs_log_buf *lb; + int error; + + lb = log_get_header(sdp, tr, TRUE); + + gfs_logbh_start(sdp, &lb->lb_bh); + error = gfs_logbh_wait(sdp, &lb->lb_bh); + if (!error) { + spin_lock(&sdp->sd_log_seg_lock); + if (!(tr->tr_flags & TRF_DUMMY)) + sdp->sd_log_seg_free += sdp->sd_log_seg_ail2; + else + sdp->sd_log_seg_free += (sdp->sd_log_seg_ail2 - 1); + sdp->sd_log_seg_ail2 = 0; + spin_unlock(&sdp->sd_log_seg_lock); + } + log_free_buf(sdp, lb); + + return error; +} + +/** + * disk_commit - Write a transaction to the on-disk journal + * @sdp: The GFS superblock + * @tr: The transaction + * + * Returns: errno + */ + +static int +disk_commit(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + uint64_t last_dump, last_dump_wrap; + int error = 0; + + gfs_assert(sdp, !test_bit(SDF_ROFS, &sdp->sd_flags),); + tr->tr_log_head = sdp->sd_log_head; + tr->tr_first_head = tr->tr_log_head - 1; + gfs_assert(sdp, gfs_log_is_header(sdp, tr->tr_first_head),); + + LO_BUILD_BHLIST(sdp, tr); + + if (!(tr->tr_flags & TRF_DUMMY)) + gfs_assert(sdp, !list_empty(&tr->tr_bufs),); + + error = sync_trans(sdp, tr); + if (error) { + /* Eat unusable commit buffer */ + log_free_buf(sdp, log_get_header(sdp, tr, TRUE)); + goto out; + } + + if (tr->tr_flags & TRF_LOG_DUMP) { + /* This commit header should point to the log dump we're + commiting as the current one. But save the copy of the + old one in case we have problems commiting the dump. */ + + last_dump = sdp->sd_log_dump_last; + last_dump_wrap = sdp->sd_log_dump_last_wrap; + + sdp->sd_log_dump_last = tr->tr_first_head; + sdp->sd_log_dump_last_wrap = sdp->sd_log_wrap; + + error = commit_trans(sdp, tr); + if (error) { + sdp->sd_log_dump_last = last_dump; + sdp->sd_log_dump_last_wrap = last_dump_wrap; + goto out; + } + } else { + error = commit_trans(sdp, tr); + if (error) + goto out; + } + + if (sdp->sd_log_head > tr->tr_log_head) + sdp->sd_log_wrap++; + sdp->sd_log_head = tr->tr_log_head; + sdp->sd_sequence++; + + out: + gfs_assert_warn(sdp, !tr->tr_num_free_bufs && + list_empty(&tr->tr_free_bufs)); + gfs_assert_warn(sdp, !tr->tr_num_free_bmem && + list_empty(&tr->tr_free_bmem)); + + return error; +} + +/** + * add_trans_to_ail - Add a ondisk commited transaction to the AIL + * @sdp: the filesystem + * @tr: the transaction + * + */ + +static void +add_trans_to_ail(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct gfs_log_element *le; + + while (!list_empty(&tr->tr_elements)) { + le = list_entry(tr->tr_elements.next, + struct gfs_log_element, le_list); + LO_ADD_TO_AIL(sdp, le); + } + + list_add(&tr->tr_list, &sdp->sd_log_ail); +} + +/** + * log_refund - Refund log segments to the free pool + * @sdp: The GFS superblock + * @tr: The transaction to examine + * + * Look at the number of segments reserved for this transaction and the + * number of segments actually needed for it. If they aren't the + * same, refund the difference to the free segment pool. + * + * De-alloc any unneeded log buffers and log buffer descriptors. + * + * Called with the log lock held. + */ + +static void +log_refund(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct gfs_log_buf *lb; + struct list_head *bmem; + unsigned int num_bufs = 0, num_bmem = 0; + unsigned int segments; + + LO_TRANS_SIZE(sdp, tr, NULL, NULL, &num_bufs, &num_bmem); + + segments = gfs_blk2seg(sdp, num_bufs + 1); + num_bufs += segments + 1; + num_bmem += segments + 1; + + /* Unreserve unneeded log segments */ + if (tr->tr_seg_reserved > segments) { + spin_lock(&sdp->sd_log_seg_lock); + sdp->sd_log_seg_free += tr->tr_seg_reserved - segments; + gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <= + sdp->sd_jdesc.ji_nsegment,); + spin_unlock(&sdp->sd_log_seg_lock); + + tr->tr_seg_reserved = segments; + } else + gfs_assert(sdp, tr->tr_seg_reserved == segments,); + + /* De-alloc unneeded log buffer descriptors */ + gfs_assert(sdp, tr->tr_num_free_bufs >= num_bufs,); + while (tr->tr_num_free_bufs > num_bufs) { + lb = list_entry(tr->tr_free_bufs.next, + struct gfs_log_buf, lb_list); + list_del(&lb->lb_list); + kfree(lb); + tr->tr_num_free_bufs--; + } + + /* De-alloc unneeded log buffers */ + gfs_assert(sdp, tr->tr_num_free_bmem >= num_bmem,); + while (tr->tr_num_free_bmem > num_bmem) { + bmem = tr->tr_free_bmem.next; + list_del(bmem); + kfree(bmem); + tr->tr_num_free_bmem--; + } +} + +/** + * trans_combine - combine two transactions + * @sdp: the filesystem + * @tr: the surviving transaction + * @new_tr: the transaction that gets freed + * + * Assumes that the two transactions are independent. + */ + +static void +trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr, + struct gfs_trans *new_tr) +{ + struct gfs_log_element *le; + struct gfs_log_buf *lb; + struct list_head *bmem; + + tr->tr_file = __FILE__; + tr->tr_line = __LINE__; + tr->tr_seg_reserved += new_tr->tr_seg_reserved; + tr->tr_flags |= new_tr->tr_flags; + tr->tr_num_free_bufs += new_tr->tr_num_free_bufs; + tr->tr_num_free_bmem += new_tr->tr_num_free_bmem; + + /* Combine the log elements of the two transactions */ + + while (!list_empty(&new_tr->tr_elements)) { + le = list_entry(new_tr->tr_elements.next, + struct gfs_log_element, le_list); + gfs_assert(sdp, le->le_trans == new_tr,); + le->le_trans = tr; + list_move(&le->le_list, &tr->tr_elements); + } + + LO_TRANS_COMBINE(sdp, tr, new_tr); + + /* Move free log buffer descriptors to surviving trans */ + while (!list_empty(&new_tr->tr_free_bufs)) { + lb = list_entry(new_tr->tr_free_bufs.next, + struct gfs_log_buf, lb_list); + list_move(&lb->lb_list, &tr->tr_free_bufs); + new_tr->tr_num_free_bufs--; + } + /* Move free log buffers to surviving trans */ + while (!list_empty(&new_tr->tr_free_bmem)) { + bmem = new_tr->tr_free_bmem.next; + list_move(bmem, &tr->tr_free_bmem); + new_tr->tr_num_free_bmem--; + } + + gfs_assert_warn(sdp, !new_tr->tr_num_free_bufs); + gfs_assert_warn(sdp, !new_tr->tr_num_free_bmem); + + kfree(new_tr); +} + +static void +make_dummy_transaction(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct gfs_log_buf *lb; + struct list_head *bmem; + + memset(tr, 0, sizeof(struct gfs_trans)); + INIT_LIST_HEAD(&tr->tr_list); + INIT_LIST_HEAD(&tr->tr_elements); + INIT_LIST_HEAD(&tr->tr_free_bufs); + INIT_LIST_HEAD(&tr->tr_free_bmem); + INIT_LIST_HEAD(&tr->tr_bufs); + INIT_LIST_HEAD(&tr->tr_ail_bufs); + tr->tr_flags = TRF_DUMMY; + tr->tr_file = __FILE__; + tr->tr_line = __LINE__; + tr->tr_seg_reserved = 1; + while (tr->tr_num_free_bufs < 2) { + lb = gmalloc(sizeof(struct gfs_log_buf)); + memset(lb, 0, sizeof(struct gfs_log_buf)); + list_add(&lb->lb_list, &tr->tr_free_bufs); + tr->tr_num_free_bufs++; + } + while (tr->tr_num_free_bmem < 2) { + bmem = gmalloc(sdp->sd_sb.sb_bsize); + list_add(bmem, &tr->tr_free_bmem); + tr->tr_num_free_bmem++; + } +} + + +/** + * log_flush_internal - flush incore transaction(s) + * @sdp: the filesystem + * @gl: The glock structure to flush. If NULL, flush the whole incore log + * + * If a glock is provided, we flush, to on-disk log, all of the metadata for + * the one incore-committed (complete, but not-yet-flushed-to-log) + * transaction that the glock protects. + * If NULL, we combine *all* of the filesystem's incore-committed + * transactions into one big transaction, and flush it to the log. + */ + +static void +log_flush_internal(struct gfs_sbd *sdp, struct gfs_glock *gl) +{ + + struct gfs_trans *trans = NULL, *tr; + int error; + + gfs_log_lock(sdp); + + if (!gl && list_empty(&sdp->sd_log_incore)) { + if (sdp->sd_log_seg_ail2) { + trans = gmalloc(sizeof(struct gfs_trans)); + make_dummy_transaction(sdp, trans); + } + else + goto out; + } + + if (gl) { + if (!gl->gl_incore_le.le_trans) + goto out; + + trans = gl->gl_incore_le.le_trans; + + list_del(&trans->tr_list); + } else { + /* combine *all* transactions in incore list */ + while (!list_empty(&sdp->sd_log_incore)) { + tr = list_entry(sdp->sd_log_incore.next, + struct gfs_trans, tr_list); + + list_del(&tr->tr_list); + + if (trans) + trans_combine(sdp, trans, tr); + else + trans = tr; + } + } + + log_refund(sdp, trans); + + /* Actually do the stuff to commit the transaction */ + + error = disk_commit(sdp, trans); + if (error) + gfs_io_error(sdp); + + add_trans_to_ail(sdp, trans); + + if (log_distance(sdp, sdp->sd_log_head, sdp->sd_log_dump_last) * GFS_DUMPS_PER_LOG >= + sdp->sd_jdesc.ji_nsegment * sdp->sd_sb.sb_seg_size) + set_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags); + + out: + if (list_empty(&sdp->sd_log_incore)) + sdp->sd_vfs->s_dirt = FALSE; + + gfs_log_unlock(sdp); + + /* Dump if we need to. */ + + if (test_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags)) + gfs_log_dump(sdp, FALSE); +} + +/** + * gfs_log_flush - flush the whole incore log + * @sdp: the filesystem + * + */ + +void +gfs_log_flush(struct gfs_sbd *sdp) +{ + log_flush_internal(sdp, NULL); +} + +/** + * gfs_log_flush_glock - flush the incore log for a glock + * @gl: the glock + * + */ + +void +gfs_log_flush_glock(struct gfs_glock *gl) +{ + log_flush_internal(gl->gl_sbd, gl); +} + +/** + * incore_commit - commit a transaction in-core + * @sdp: the filesystem + * @new_tr: the transaction to commit + * + * Add the transaction @new_tr to the end of the incore commit list. + * Pull up and merge any previously committed transactions that share + * locks. Also pull up any rename transactions that need it. + */ + +static void +incore_commit(struct gfs_sbd *sdp, struct gfs_trans *new_tr) +{ + struct gfs_log_element *le; + struct gfs_trans *trans = NULL, *exist_tr; + struct gfs_log_buf *lb; + struct list_head *bmem; + struct list_head *tmp, *head, *next; + + for (head = &new_tr->tr_elements, tmp = head->next; + tmp != head; + tmp = tmp->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + + /* Do overlap_trans log-op, if any, to find another + incore transaction with which we can combine new_tr */ + exist_tr = LO_OVERLAP_TRANS(sdp, le); + if (!exist_tr) + continue; + + if (exist_tr != trans) { + /* remove trans from superblock's sd_log_incore list */ + list_del(&exist_tr->tr_list); + + /* Maybe there's more than one that can be combined. + If so, combine them together before merging new_tr */ + if (trans) + trans_combine(sdp, trans, exist_tr); + else + trans = exist_tr; + } + } + + /* Yes, we can combine new_tr with pre-existing transaction(s) */ + if (trans) { + trans->tr_file = __FILE__; + trans->tr_line = __LINE__; + trans->tr_seg_reserved += new_tr->tr_seg_reserved; + trans->tr_flags |= new_tr->tr_flags; + trans->tr_num_free_bufs += new_tr->tr_num_free_bufs; + trans->tr_num_free_bmem += new_tr->tr_num_free_bmem; + + /* Move free log buffer descriptors to surviving trans */ + while (!list_empty(&new_tr->tr_free_bufs)) { + lb = list_entry(new_tr->tr_free_bufs.next, + struct gfs_log_buf, lb_list); + list_move(&lb->lb_list, &trans->tr_free_bufs); + new_tr->tr_num_free_bufs--; + } + + /* Move free log buffers to surviving trans */ + while (!list_empty(&new_tr->tr_free_bmem)) { + bmem = new_tr->tr_free_bmem.next; + list_move(bmem, &trans->tr_free_bmem); + new_tr->tr_num_free_bmem--; + } + } else + trans = new_tr; + + /* Do incore_commit log-op for each *new* log element (in new_tr). + Each commit log-op removes its log element from "new_tr" LE list, + and attaches an LE to "trans" LE list; if there was no trans + combining, "new_tr" is the same transaction as "trans". */ + for (head = &new_tr->tr_elements, tmp = head->next, next = tmp->next; + tmp != head; + tmp = next, next = next->next) { + le = list_entry(tmp, struct gfs_log_element, le_list); + LO_INCORE_COMMIT(sdp, trans, le); + } + + /* If we successfully combined transactions, new_tr should be empty */ + if (trans != new_tr) { + gfs_assert_warn(sdp, !new_tr->tr_num_free_bufs); + gfs_assert_warn(sdp, !new_tr->tr_num_free_bmem); + gfs_assert_warn(sdp, list_empty(&new_tr->tr_elements)); + kfree(new_tr); + } + + /* If we successfully combined transactions, we might have some log + segments that we reserved, and log buffers and buffer descriptors + that we allocated, but now don't need. */ + log_refund(sdp, trans); + + list_add(&trans->tr_list, &sdp->sd_log_incore); +} + +/** + * gfs_log_commit - Commit a transaction to the log + * @sdp: the filesystem + * @tr: the transaction + * + * Returns: errno + */ + +void +gfs_log_commit(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct gfs_log_buf *lb; + struct list_head *bmem; + unsigned int num_mblks = 0, num_eblks = 0, num_bufs = 0, num_bmem = 0; + unsigned int segments; + + /* Calculate actual log area needed for this trans */ + LO_TRANS_SIZE(sdp, tr, &num_mblks, &num_eblks, &num_bufs, &num_bmem); + + gfs_assert(sdp, num_mblks <= tr->tr_mblks_asked && + num_eblks <= tr->tr_eblks_asked, + printk("GFS: fsid=%s: type = (%s, %u)\n" + "GFS: fsid=%s: num_mblks = %u, tr->tr_mblks_asked = %u\n" + "GFS: fsid=%s: num_eblks = %u, tr->tr_eblks_asked = %u\n", + sdp->sd_fsname, tr->tr_file, tr->tr_line, + sdp->sd_fsname, num_mblks, tr->tr_mblks_asked, + sdp->sd_fsname, num_eblks, tr->tr_eblks_asked);); + + segments = gfs_blk2seg(sdp, num_bufs + 1); + num_bufs += segments + 1; + num_bmem += segments + 1; + + /* Alloc log buffer descriptors */ + while (num_bufs--) { + lb = gmalloc(sizeof(struct gfs_log_buf)); + memset(lb, 0, sizeof(struct gfs_log_buf)); + list_add(&lb->lb_list, &tr->tr_free_bufs); + tr->tr_num_free_bufs++; + } + /* Alloc log buffers */ + while (num_bmem--) { + bmem = gmalloc(sdp->sd_sb.sb_bsize); + list_add(bmem, &tr->tr_free_bmem); + tr->tr_num_free_bmem++; + } + + gfs_log_lock(sdp); + + incore_commit(sdp, tr); + + /* Flush log buffers to disk if we're over the threshold */ + if (sdp->sd_log_buffers > gfs_tune_get(sdp, gt_incore_log_blocks)) { + gfs_log_unlock(sdp); + gfs_log_flush(sdp); + } else { + sdp->sd_vfs->s_dirt = TRUE; + gfs_log_unlock(sdp); + } + +} + +/** + * gfs_log_dump - make a Log Dump entry in the log + * @sdp: the filesystem + * @force: if TRUE, always make the dump even if one has been made recently + * + */ + +void +gfs_log_dump(struct gfs_sbd *sdp, int force) +{ + struct gfs_log_element *le; + struct gfs_trans tr; + struct gfs_log_buf *lb; + struct list_head *bmem; + unsigned int num_bufs, num_bmem; + unsigned int segments; + int error; + + if (test_and_set_bit(SDF_IN_LOG_DUMP, &sdp->sd_flags)) { + gfs_assert(sdp, !force,); + return; + } + + memset(&tr, 0, sizeof(struct gfs_trans)); + INIT_LIST_HEAD(&tr.tr_elements); + INIT_LIST_HEAD(&tr.tr_free_bufs); + INIT_LIST_HEAD(&tr.tr_free_bmem); + INIT_LIST_HEAD(&tr.tr_bufs); + tr.tr_flags = TRF_LOG_DUMP; + tr.tr_file = __FILE__; + tr.tr_line = __LINE__; + + for (;;) { + gfs_log_lock(sdp); + + if (!force && !test_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags)) + goto out; + + num_bufs = num_bmem = 0; + LO_DUMP_SIZE(sdp, NULL, &num_bufs, &num_bmem); + gfs_assert(sdp, num_bufs,); + segments = gfs_blk2seg(sdp, num_bufs + 1); + num_bufs += segments + 1; + num_bmem += segments + 1; + + if (tr.tr_seg_reserved >= segments && + tr.tr_num_free_bufs >= num_bufs && + tr.tr_num_free_bmem >= num_bmem) + break; + + gfs_log_unlock(sdp); + + if (tr.tr_seg_reserved < segments) { + error = gfs_log_reserve(sdp, + segments - tr.tr_seg_reserved, + TRUE); + gfs_assert(sdp, !error,); + tr.tr_seg_reserved = segments; + } + while (tr.tr_num_free_bufs < num_bufs) { + lb = gmalloc(sizeof(struct gfs_log_buf)); + memset(lb, 0, sizeof(struct gfs_log_buf)); + list_add(&lb->lb_list, &tr.tr_free_bufs); + tr.tr_num_free_bufs++; + } + while (tr.tr_num_free_bmem < num_bmem) { + bmem = gmalloc(sdp->sd_sb.sb_bsize); + list_add(bmem, &tr.tr_free_bmem); + tr.tr_num_free_bmem++; + } + } + + if (tr.tr_seg_reserved > segments) { + spin_lock(&sdp->sd_log_seg_lock); + sdp->sd_log_seg_free += tr.tr_seg_reserved - segments; + gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <= + sdp->sd_jdesc.ji_nsegment,); + spin_unlock(&sdp->sd_log_seg_lock); + tr.tr_seg_reserved = segments; + } + while (tr.tr_num_free_bufs > num_bufs) { + lb = list_entry(tr.tr_free_bufs.next, + struct gfs_log_buf, lb_list); + list_del(&lb->lb_list); + kfree(lb); + tr.tr_num_free_bufs--; + } + while (tr.tr_num_free_bmem > num_bmem) { + bmem = tr.tr_free_bmem.next; + list_del(bmem); + kfree(bmem); + tr.tr_num_free_bmem--; + } + + LO_BUILD_DUMP(sdp, &tr); + + error = disk_commit(sdp, &tr); + if (error) + gfs_io_error(sdp); + + while (!list_empty(&tr.tr_elements)) { + le = list_entry(tr.tr_elements.next, + struct gfs_log_element, le_list); + LO_CLEAN_DUMP(sdp, le); + } + + /* If there isn't anything in the AIL, we won't get back the log + space we reserved unless we do it ourselves. */ + + if (list_empty(&sdp->sd_log_ail)) { + spin_lock(&sdp->sd_log_seg_lock); + sdp->sd_log_seg_free += tr.tr_seg_reserved; + gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <= + sdp->sd_jdesc.ji_nsegment,); + spin_unlock(&sdp->sd_log_seg_lock); + } + + clear_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags); + + out: + gfs_log_unlock(sdp); + clear_bit(SDF_IN_LOG_DUMP, &sdp->sd_flags); +} + +/** + * gfs_log_shutdown - write a shutdown header into a journal + * @sdp: the filesystem + * + */ + +void +gfs_log_shutdown(struct gfs_sbd *sdp) +{ + struct gfs_log_buf *lb; + char *bmem; + struct gfs_log_header head; + struct gfs_log_descriptor desc; + unsigned int elements = 0; + int error; + + lb = gmalloc(sizeof(struct gfs_log_buf)); + memset(lb, 0, sizeof(struct gfs_log_buf)); + bmem = gmalloc(sdp->sd_sb.sb_bsize); + + gfs_log_lock(sdp); + + gfs_assert_withdraw(sdp, list_empty(&sdp->sd_log_ail)); + gfs_assert_withdraw(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 == + sdp->sd_jdesc.ji_nsegment); + gfs_assert_withdraw(sdp, !sdp->sd_log_buffers); + gfs_assert_withdraw(sdp, gfs_log_is_header(sdp, sdp->sd_log_head - 1)); + if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + goto out; + + /* Build a "last" log descriptor */ + + memset(&desc, 0, sizeof(struct gfs_log_descriptor)); + desc.ld_header.mh_magic = GFS_MAGIC; + desc.ld_header.mh_type = GFS_METATYPE_LD; + desc.ld_header.mh_format = GFS_FORMAT_LD; + desc.ld_type = GFS_LOG_DESC_LAST; + desc.ld_length = sdp->sd_sb.sb_seg_size - 1; + + /* Write the descriptor */ + + gfs_logbh_init(sdp, &lb->lb_bh, sdp->sd_log_head, bmem); + memset(bmem, 0, sdp->sd_sb.sb_bsize); + gfs_desc_out(&desc, lb->lb_bh.b_data); + gfs_logbh_start(sdp, &lb->lb_bh); + error = gfs_logbh_wait(sdp, &lb->lb_bh); + gfs_logbh_uninit(sdp, &lb->lb_bh); + + if (error) + goto out; + + /* Move to the next header */ + + while (!gfs_log_is_header(sdp, sdp->sd_log_head)) + log_incr_head(sdp, &sdp->sd_log_head); + + LO_DUMP_SIZE(sdp, &elements, NULL, NULL); + + /* Build the shutdown header */ + + memset(&head, 0, sizeof (struct gfs_log_header)); + head.lh_header.mh_magic = GFS_MAGIC; + head.lh_header.mh_type = GFS_METATYPE_LH; + head.lh_header.mh_format = GFS_FORMAT_LH; + head.lh_flags = GFS_LOG_HEAD_UNMOUNT; + head.lh_first = sdp->sd_log_head; + head.lh_sequence = sdp->sd_sequence + 1; + /* Don't care about tail */ + head.lh_last_dump = (elements) ? sdp->sd_log_dump_last : 0; + + /* Write out the shutdown header */ + + gfs_logbh_init(sdp, &lb->lb_bh, sdp->sd_log_head, bmem); + memset(bmem, 0, sdp->sd_sb.sb_bsize); + gfs_log_header_out(&head, lb->lb_bh.b_data); + gfs_log_header_out(&head, + lb->lb_bh.b_data + GFS_BASIC_BLOCK - + sizeof(struct gfs_log_header)); + gfs_logbh_start(sdp, &lb->lb_bh); + gfs_logbh_wait(sdp, &lb->lb_bh); + gfs_logbh_uninit(sdp, &lb->lb_bh); + + /* If a withdraw is called before we've a chance to relock the trans + * lock, the sd_log_head points to the wrong place, and a umount will + * fail on asserts because of this. + * Adding one puts sd_log_head at a value that passes the assert. The + * value may not be correct for on disk, but we've withdrawn so there is + * no more disk io. + * If we're not withdrawn, the next io will grab the trans lock, which + * will fill sd_log_head with the correct value. + */ + sdp->sd_log_head += 1; + + out: + gfs_log_unlock(sdp); + + kfree(lb); + kfree(bmem); +} --- linux-2.6.27.orig/ubuntu/gfs/recovery.h +++ linux-2.6.27/ubuntu/gfs/recovery.h @@ -0,0 +1,23 @@ +#ifndef __RECOVERY_DOT_H__ +#define __RECOVERY_DOT_H__ + +#define GFS_RECPASS_A1 (12) +#define GFS_RECPASS_B1 (14) + +void gfs_add_dirty_j(struct gfs_sbd *sdp, unsigned int jid); +void gfs_clear_dirty_j(struct gfs_sbd *sdp); + +int gfs_find_jhead(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, struct gfs_log_header *head); +int gfs_increment_blkno(struct gfs_sbd *sdp, struct gfs_jindex *jdesc, + struct gfs_glock *gl, uint64_t *addr, + int skip_headers); + +int gfs_recover_journal(struct gfs_sbd *sdp, + unsigned int jid, struct gfs_jindex *jdesc, + int wait); +void gfs_check_journals(struct gfs_sbd *sdp); + +int gfs_recover_dump(struct gfs_sbd *sdp); + +#endif /* __RECOVERY_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/glock.h +++ linux-2.6.27/ubuntu/gfs/glock.h @@ -0,0 +1,137 @@ +#ifndef __GFS_GLOCK_DOT_H__ +#define __GFS_GLOCK_DOT_H__ + +/* Flags for lock requests; used in gfs_holder gh_flag field. */ +/* These are defined in lm_interface.h, commented out here. +#define LM_FLAG_TRY (0x00000001) +#define LM_FLAG_TRY_1CB (0x00000002) +#define LM_FLAG_NOEXP (0x00000004) +#define LM_FLAG_ANY (0x00000008) +#define LM_FLAG_PRIORITY (0x00000010) + These are defined here. */ +#define GL_LOCAL_EXCL (0x00000020) /* Only one holder may be granted the + * lock on this node, even if SHARED */ +#define GL_ASYNC (0x00000040) /* Don't block waiting for lock ... + * must poll to wait for grant */ +#define GL_EXACT (0x00000080) /* Requested state must == current state + * for lock to be granted */ +#define GL_SKIP (0x00000100) /* Don't read from disk after grant */ +#define GL_ATIME (0x00000200) /* Update inode's ATIME after grant */ +#define GL_NOCACHE (0x00000400) /* Release glock when done, don't cache */ +#define GL_SYNC (0x00000800) /* Sync to disk when no more holders */ +#define GL_NOCANCEL (0x00001000) /* Don't ever cancel this request */ +#define GL_READPAGE (0x00002000) /* gfs_readpage() issued this lock request */ +#define GL_NOCANCEL_OTHER (0x00004000) /* Don't cancel other locks for this */ + +#define GLR_TRYFAILED (13) +#define GLR_CANCELED (14) + +static __inline__ struct gfs_holder* +gfs_glock_is_locked_by_me(struct gfs_glock *gl) +{ + struct list_head *tmp, *head; + struct gfs_holder *gh; + + /* Look in glock's list of holders for one with current task as owner */ + spin_lock(&gl->gl_spin); + for (head = &gl->gl_holders, tmp = head->next; + tmp != head; + tmp = tmp->next) { + gh = list_entry(tmp, struct gfs_holder, gh_list); + if (gh->gh_owner == current) + goto out; + } + gh = NULL; +out: + spin_unlock(&gl->gl_spin); + return gh; +} +static __inline__ int +gfs_glock_is_held_excl(struct gfs_glock *gl) +{ + return (gl->gl_state == LM_ST_EXCLUSIVE); +} +static __inline__ int +gfs_glock_is_held_dfrd(struct gfs_glock *gl) +{ + return (gl->gl_state == LM_ST_DEFERRED); +} +static __inline__ int +gfs_glock_is_held_shrd(struct gfs_glock *gl) +{ + return (gl->gl_state == LM_ST_SHARED); +} + +static __inline__ int +gfs_glock_is_blocking(struct gfs_glock *gl) +{ + int ret; + spin_lock(&gl->gl_spin); + ret = !list_empty(&gl->gl_waiters2) || !list_empty(&gl->gl_waiters3); + spin_unlock(&gl->gl_spin); + return ret; +} + +struct gfs_glock *gfs_glock_find(struct gfs_sbd *sdp, + struct lm_lockname *name); +int gfs_glock_get(struct gfs_sbd *sdp, + uint64_t number, struct gfs_glock_operations *glops, + int create, struct gfs_glock **glp); +void gfs_glock_hold(struct gfs_glock *gl); +void gfs_glock_put(struct gfs_glock *gl); + +void gfs_holder_init(struct gfs_glock *gl, unsigned int state, int flags, + struct gfs_holder *gh); +void gfs_holder_reinit(unsigned int state, int flags, struct gfs_holder *gh); +void gfs_holder_uninit(struct gfs_holder *gh); +struct gfs_holder *gfs_holder_get(struct gfs_glock *gl, unsigned int state, + int flags); +void gfs_holder_put(struct gfs_holder *gh); + +void gfs_glock_xmote_th(struct gfs_glock *gl, unsigned int state, int flags); +void gfs_glock_drop_th(struct gfs_glock *gl); + +int gfs_glock_nq(struct gfs_holder *gh); +int gfs_glock_poll(struct gfs_holder *gh); +int gfs_glock_wait(struct gfs_holder *gh); +void gfs_glock_dq(struct gfs_holder *gh); + +void gfs_glock_prefetch(struct gfs_glock *gl, unsigned int state, int flags); +void gfs_glock_force_drop(struct gfs_glock *gl); + +int gfs_glock_be_greedy(struct gfs_glock *gl, unsigned int time); + +int gfs_glock_nq_init(struct gfs_glock *gl, unsigned int state, int flags, + struct gfs_holder *gh); +void gfs_glock_dq_uninit(struct gfs_holder *gh); +int gfs_glock_nq_num(struct gfs_sbd *sdp, + uint64_t number, struct gfs_glock_operations *glops, + unsigned int state, int flags, struct gfs_holder *gh); + +int gfs_glock_nq_m(unsigned int num_gh, struct gfs_holder *ghs); +void gfs_glock_dq_m(unsigned int num_gh, struct gfs_holder *ghs); + +void gfs_glock_prefetch_num(struct gfs_sbd *sdp, + uint64_t number, struct gfs_glock_operations *glops, + unsigned int state, int flags); + +/* Lock Value Block functions */ + +int gfs_lvb_hold(struct gfs_glock *gl); +void gfs_lvb_unhold(struct gfs_glock *gl); +void gfs_lvb_sync(struct gfs_glock *gl); + +void gfs_glock_cb(void *fsdata, unsigned int type, void *data); + +void gfs_try_toss_inode(struct gfs_sbd *sdp, struct gfs_inum *inum); +void gfs_iopen_go_callback(struct gfs_glock *gl, unsigned int state); + +void gfs_glock_schedule_for_reclaim(struct gfs_glock *gl); +void gfs_reclaim_glock(struct gfs_sbd *sdp); + +void gfs_scand_internal(struct gfs_sbd *sdp); +void gfs_gl_hash_clear(struct gfs_sbd *sdp, int wait); + +int gfs_dump_lockstate(struct gfs_sbd *sdp, struct gfs_user_buffer *ub); + +#endif /* __GFS_GLOCK_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/inode.c +++ linux-2.6.27/ubuntu/gfs/inode.c @@ -0,0 +1,2212 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "acl.h" +#include "bmap.h" +#include "dio.h" +#include "dir.h" +#include "eattr.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "log.h" +#include "ops_address.h" +#include "ops_file.h" +#include "ops_inode.h" +#include "quota.h" +#include "rgrp.h" +#include "trans.h" +#include "unlinked.h" + +/** + * inode_attr_in - Copy attributes from the dinode into the VFS inode + * @ip: The GFS inode (with embedded disk inode data) + * @inode: The Linux VFS inode + * + */ + +static void +inode_attr_in(struct gfs_inode *ip, struct inode *inode) +{ + unsigned int mode; + + inode->i_ino = ip->i_num.no_formal_ino; + + switch (ip->i_di.di_type) { + case GFS_FILE_REG: + mode = S_IFREG; + inode->i_rdev = 0; + break; + case GFS_FILE_DIR: + mode = S_IFDIR; + inode->i_rdev = 0; + break; + case GFS_FILE_LNK: + mode = S_IFLNK; + inode->i_rdev = 0; + break; + case GFS_FILE_BLK: + mode = S_IFBLK; + inode->i_rdev = MKDEV(ip->i_di.di_major, ip->i_di.di_minor); + break; + case GFS_FILE_CHR: + mode = S_IFCHR; + inode->i_rdev = MKDEV(ip->i_di.di_major, ip->i_di.di_minor); + break; + case GFS_FILE_FIFO: + mode = S_IFIFO; + inode->i_rdev = 0; + break; + case GFS_FILE_SOCK: + mode = S_IFSOCK; + inode->i_rdev = 0; + break; + default: + if (gfs_consist_inode(ip)) + printk("GFS: fsid=%s: type = %u\n", + ip->i_sbd->sd_fsname, ip->i_di.di_type); + return; + }; + + inode->i_mode = mode | (ip->i_di.di_mode & S_IALLUGO); + inode->i_nlink = ip->i_di.di_nlink; + inode->i_uid = ip->i_di.di_uid; + inode->i_gid = ip->i_di.di_gid; + i_size_write(inode, ip->i_di.di_size); + inode->i_atime.tv_sec = ip->i_di.di_atime; + inode->i_mtime.tv_sec = ip->i_di.di_mtime; + inode->i_ctime.tv_sec = ip->i_di.di_ctime; + inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0; + inode->i_blocks = ip->i_di.di_blocks << + (ip->i_sbd->sd_sb.sb_bsize_shift - GFS_BASIC_BLOCK_SHIFT); + inode->i_generation = ip->i_di.di_header.mh_incarn; + + if (ip->i_di.di_flags & GFS_DIF_IMMUTABLE) + inode->i_flags |= S_IMMUTABLE; + else + inode->i_flags &= ~S_IMMUTABLE; + + if (ip->i_di.di_flags & GFS_DIF_APPENDONLY) + inode->i_flags |= S_APPEND; + else + inode->i_flags &= ~S_APPEND; +} + +/** + * gfs_inode_attr_in - Copy attributes from the dinode into the VFS inode + * @ip: The GFS inode (with embedded disk inode data) + * + */ + +void +gfs_inode_attr_in(struct gfs_inode *ip) +{ + struct inode *inode; + + inode = gfs_iget(ip, NO_CREATE); + if (inode) { + inode_attr_in(ip, inode); + iput(inode); + } + +} + +/** + * gfs_inode_attr_out - Copy attributes from VFS inode into the dinode + * @ip: The GFS inode + * + * Only copy out the attributes that we want the VFS layer + * to be able to modify. + */ + +void +gfs_inode_attr_out(struct gfs_inode *ip) +{ + struct inode *inode = ip->i_vnode; + + ip->i_di.di_mode = inode->i_mode & S_IALLUGO; + ip->i_di.di_uid = inode->i_uid; + ip->i_di.di_gid = inode->i_gid; + ip->i_di.di_atime = inode->i_atime.tv_sec; + ip->i_di.di_mtime = inode->i_mtime.tv_sec; + ip->i_di.di_ctime = inode->i_ctime.tv_sec; +} + +/** + * gfs_iget - Get/Create a struct inode for a struct gfs_inode + * @ip: the struct gfs_inode to get the struct inode for + * @create: CREATE -- create a new struct inode if one does not already exist + * NO_CREATE -- return NULL if inode doesn't exist + * + * Returns: A VFS inode, or NULL if NO_CREATE and none in existance + * + * If this function creates a new inode, it: + * Copies fields from the GFS on-disk (d)inode to the VFS inode + * Attaches the appropriate ops vectors to the VFS inode and address_space + * Attaches the VFS inode to the gfs_inode + * Inserts the new inode in the VFS inode hash, while avoiding races + */ + +struct inode * +gfs_iget(struct gfs_inode *ip, int create) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct inode *inode = NULL, *tmp; + + spin_lock(&ip->i_spin); + if (ip->i_vnode) + inode = igrab(ip->i_vnode); + spin_unlock(&ip->i_spin); + + if (inode || !create) + return inode; + + tmp = new_inode(ip->i_sbd->sd_vfs); + if (!tmp) + return NULL; + + inode_attr_in(ip, tmp); + + /* Attach GFS-specific ops vectors */ + if (ip->i_di.di_type == GFS_FILE_REG) { + tmp->i_op = &gfs_file_iops; + memcpy(&ip->gfs_file_aops, &gfs_file_aops, + sizeof(struct address_space_operations)); + tmp->i_mapping->a_ops = &ip->gfs_file_aops; + if (sdp->sd_args.ar_localflocks) + tmp->i_fop = &gfs_file_fops_nolock; + else + tmp->i_fop = &gfs_file_fops; + } else if (ip->i_di.di_type == GFS_FILE_DIR) { + tmp->i_op = &gfs_dir_iops; + if (sdp->sd_args.ar_localflocks) + tmp->i_fop = &gfs_dir_fops_nolock; + else + tmp->i_fop = &gfs_dir_fops; + } else if (ip->i_di.di_type == GFS_FILE_LNK) { + tmp->i_op = &gfs_symlink_iops; + } else { + tmp->i_op = &gfs_dev_iops; + init_special_inode(tmp, tmp->i_mode, tmp->i_rdev); + } + + set_v2ip(tmp, NULL); + + /* Did another process successfully create an inode while we were + preparing this (tmp) one? If so, we can use that other one, and + trash the one we were preparing. + The other process might not be done inserting the inode in the + VFS hash table. If so, we need to wait until it is done, then + we can use it. */ + for (;;) { + spin_lock(&ip->i_spin); + if (!ip->i_vnode) + break; + inode = igrab(ip->i_vnode); + spin_unlock(&ip->i_spin); + + if (inode) { + iput(tmp); + return inode; + } + yield(); + } + + inode = tmp; + + gfs_inode_hold(ip); + ip->i_vnode = inode; + set_v2ip(inode, ip); + + spin_unlock(&ip->i_spin); + + insert_inode_hash(inode); + + return inode; +} + +/** + * gfs_copyin_dinode - Refresh the incore copy of the dinode + * @ip: The GFS inode + * + * Returns: errno + */ + +int +gfs_copyin_dinode(struct gfs_inode *ip) +{ + struct buffer_head *dibh; + int error; + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + return error; + + if (gfs_metatype_check(ip->i_sbd, dibh, GFS_METATYPE_DI)) { + brelse(dibh); + return -EIO; + } + + gfs_dinode_in(&ip->i_di, dibh->b_data); + brelse(dibh); + + if (ip->i_num.no_formal_ino != ip->i_di.di_num.no_formal_ino) { + if (gfs_consist_inode(ip)) + gfs_dinode_print(&ip->i_di); + return -EIO; + } + + /* Handle a moved inode (not implemented yet) */ + if (ip->i_num.no_addr != ip->i_di.di_num.no_addr) { + if (gfs_consist_inode(ip)) + gfs_dinode_print(&ip->i_di); + return -EIO; + } + + ip->i_vn = ip->i_gl->gl_vn; + + return 0; +} + +/** + * inode_create - create a struct gfs_inode, acquire Inode-Open (iopen) glock, + * read dinode from disk + * @i_gl: The (already held) glock covering the inode + * @inum: The inode number + * @io_gl: the iopen glock to acquire/hold (using holder in new gfs_inode) + * @io_state: the state the iopen glock should be acquired in + * @ipp: pointer to put the returned inode in + * + * Returns: errno + */ + +static int +inode_create(struct gfs_glock *i_gl, struct gfs_inum *inum, + struct gfs_glock *io_gl, unsigned int io_state, + struct gfs_inode **ipp) +{ + struct gfs_sbd *sdp = i_gl->gl_sbd; + struct gfs_inode *ip; + int error = 0; + + RETRY_MALLOC(ip = kmem_cache_alloc(gfs_inode_cachep, GFP_KERNEL), ip); + memset(ip, 0, sizeof(struct gfs_inode)); + + ip->i_num = *inum; + + atomic_set(&ip->i_count, 1); + + ip->i_gl = i_gl; + ip->i_sbd = sdp; + + spin_lock_init(&ip->i_spin); + init_rwsem(&ip->i_rw_mutex); + + ip->i_greedy = gfs_tune_get(sdp, gt_greedy_default); + + /* Lock the iopen glock (may be recursive) */ + error = gfs_glock_nq_init(io_gl, + io_state, GL_LOCAL_EXCL | GL_EXACT, + &ip->i_iopen_gh); + if (error) + goto fail; + + ip->i_iopen_gh.gh_owner = NULL; + + /* Assign the inode's glock as this iopen glock's protected object */ + spin_lock(&io_gl->gl_spin); + gfs_glock_hold(i_gl); + set_gl2gl(io_gl, i_gl); + spin_unlock(&io_gl->gl_spin); + + /* Read dinode from disk */ + error = gfs_copyin_dinode(ip); + if (error) + goto fail_iopen; + + gfs_glock_hold(i_gl); + set_gl2ip(i_gl, ip); + + atomic_inc(&sdp->sd_inode_count); + + *ipp = ip; + + return 0; + + fail_iopen: + spin_lock(&io_gl->gl_spin); + set_gl2gl(io_gl, NULL); + gfs_glock_put(i_gl); + spin_unlock(&io_gl->gl_spin); + + gfs_glock_dq_uninit(&ip->i_iopen_gh); + + fail: + gfs_flush_meta_cache(ip); + kmem_cache_free(gfs_inode_cachep, ip); + *ipp = NULL; + + return error; +} + +/** + * gfs_inode_get - Get an inode given its number + * @i_gl: The glock covering the inode + * @inum: The inode number + * @create: Flag to say if we are allowed to create a new struct gfs_inode + * @ipp: pointer to put the returned inode in + * + * Returns: errno + * + * If creating a new gfs_inode structure, reads dinode from disk. + */ + +int +gfs_inode_get(struct gfs_glock *i_gl, struct gfs_inum *inum, int create, + struct gfs_inode **ipp) +{ + struct gfs_glock *io_gl; + int error = 0; + + *ipp = get_gl2ip(i_gl); + if (*ipp) { + atomic_inc(&(*ipp)->i_count); + gfs_assert_warn(i_gl->gl_sbd, + (*ipp)->i_num.no_formal_ino == + inum->no_formal_ino); + } else if (create) { + error = gfs_glock_get(i_gl->gl_sbd, + inum->no_addr, &gfs_iopen_glops, + CREATE, &io_gl); + if (!error) { + error = inode_create(i_gl, inum, io_gl, + LM_ST_SHARED, ipp); + gfs_glock_put(io_gl); + } + } + + return error; +} + +/** + * gfs_inode_hold - hold a struct gfs_inode structure + * @ip: The GFS inode + * + */ + +void +gfs_inode_hold(struct gfs_inode *ip) +{ + gfs_assert(ip->i_sbd, atomic_read(&ip->i_count) > 0,); + atomic_inc(&ip->i_count); +} + +/** + * gfs_inode_put - put a struct gfs_inode structure + * @ip: The GFS inode + * + */ + +void +gfs_inode_put(struct gfs_inode *ip) +{ + gfs_assert(ip->i_sbd, atomic_read(&ip->i_count) > 0,); + atomic_dec(&ip->i_count); +} + +/** + * gfs_inode_destroy - Destroy a GFS inode structure with no references on it + * @ip: The GFS inode + * + * Also, unhold the iopen glock and release indirect addressing buffers. + * This function must be called with a glocks held on the inode and + * the associated iopen. + * + */ + +void +gfs_inode_destroy(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_glock *io_gl = ip->i_iopen_gh.gh_gl; + struct gfs_glock *i_gl = ip->i_gl; + + gfs_assert_warn(sdp, !atomic_read(&ip->i_count)); + gfs_assert(sdp, get_gl2gl(io_gl) == i_gl,); + + /* Unhold the iopen glock */ + spin_lock(&io_gl->gl_spin); + set_gl2gl(io_gl, NULL); + gfs_glock_put(i_gl); + spin_unlock(&io_gl->gl_spin); + + gfs_glock_dq_uninit(&ip->i_iopen_gh); + + /* Release indirect addressing buffers, destroy the GFS inode struct */ + gfs_flush_meta_cache(ip); + kmem_cache_free(gfs_inode_cachep, ip); + + set_gl2ip(i_gl, NULL); + gfs_glock_put(i_gl); + + atomic_dec(&sdp->sd_inode_count); +} + +/** + * dinode_mark_unused - Set UNUSED flag in on-disk dinode + * @ip: + * + * Also: + * -- Increment incarnation number, to indicate that it no longer + * represents the old inode. + * -- Update change time (ctime) + * + * Returns: errno + */ + +static int +dinode_mark_unused(struct gfs_inode *ip) +{ + struct buffer_head *dibh; + struct gfs_dinode *di; + uint32_t incarn; + uint64_t ctime; + uint32_t flags; + int error; + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + return error; + + di = (struct gfs_dinode *)dibh->b_data; + + gfs_trans_add_bh(ip->i_gl, dibh); + + incarn = gfs32_to_cpu(di->di_header.mh_incarn) + 1; + di->di_header.mh_incarn = cpu_to_gfs32(incarn); + + ctime = get_seconds(); + di->di_ctime = cpu_to_gfs64(ctime); + + flags = (gfs32_to_cpu(di->di_flags)) | GFS_DIF_UNUSED; + di->di_flags = cpu_to_gfs32(flags); + + brelse(dibh); + + return 0; +} + +/** + * dinode_dealloc - Put deallocate a dinode + * @ip: The GFS inode + * + * Returns: errno + */ + +static int +dinode_dealloc(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al; + struct gfs_rgrpd *rgd; + int error; + + if (ip->i_di.di_blocks != 1) { + if (gfs_consist_inode(ip)) + gfs_dinode_print(&ip->i_di); + return -EIO; + } + + al = gfs_alloc_get(ip); + + error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto out; + + error = gfs_rindex_hold(sdp, &al->al_ri_gh); + if (error) + goto out_qs; + + rgd = gfs_blk2rgrpd(sdp, ip->i_num.no_addr); + if (!rgd) { + gfs_consist_inode(ip); + error = -EIO; + goto out_rindex_relse; + } + + error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &al->al_rgd_gh); + if (error) + goto out_rindex_relse; + + /* Trans may require: + One block for the RG header. + One block for the dinode bit. + One block for the dinode. + We also need a block for the unlinked change. + One block for the quota change. */ + + error = gfs_trans_begin(sdp, 3, 2); + if (error) + goto out_rg_gunlock; + + /* Set the UNUSED flag in the on-disk dinode block, increment incarn */ + error = dinode_mark_unused(ip); + if (error) + goto out_end_trans; + + /* De-allocate on-disk dinode block to FREEMETA */ + gfs_difree(rgd, ip); + + gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA, &ip->i_num); + clear_bit(GLF_STICKY, &ip->i_gl->gl_flags); + + out_end_trans: + gfs_trans_end(sdp); + + out_rg_gunlock: + gfs_glock_dq_uninit(&al->al_rgd_gh); + + out_rindex_relse: + gfs_glock_dq_uninit(&al->al_ri_gh); + + out_qs: + gfs_quota_unhold_m(ip); + + out: + gfs_alloc_put(ip); + + return error; +} + +/** + * inode_dealloc - Deallocate all on-disk blocks for an inode (dinode) + * @sdp: the filesystem + * @inum: the inode number to deallocate + * @io_gh: a holder for the iopen glock for this inode + * + * De-allocates all on-disk blocks, data and metadata, associated with an inode. + * All metadata blocks become GFS_BLKST_FREEMETA. + * All data blocks become GFS_BLKST_FREE. + * Also de-allocates incore gfs_inode structure. + * + * Returns: errno + */ + +static int +inode_dealloc(struct gfs_sbd *sdp, struct gfs_inum *inum, + struct gfs_holder *io_gh) +{ + struct gfs_inode *ip; + struct gfs_holder i_gh; + int error; + + /* Lock the inode as we blow it away */ + error = gfs_glock_nq_num(sdp, + inum->no_formal_ino, &gfs_inode_glops, + LM_ST_EXCLUSIVE, 0, &i_gh); + if (error) + return error; + + /* We reacquire the iopen lock here to avoid a race with the NFS server + calling gfs_read_inode() with the inode number of a inode we're in + the process of deallocating. And we can't keep our hold on the lock + from inode_dealloc_init() for deadlock reasons. We do, however, + overlap this iopen lock with the one to be acquired EX within + inode_create(), below (recursive EX locks will be granted to same + holder process, i.e. this process). */ + + gfs_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY, io_gh); + error = gfs_glock_nq(io_gh); + switch (error) { + case 0: + break; + case GLR_TRYFAILED: + error = 0; + goto fail; + default: + goto fail; + } + + gfs_assert_warn(sdp, !get_gl2ip(i_gh.gh_gl)); + error = inode_create(i_gh.gh_gl, inum, io_gh->gh_gl, LM_ST_EXCLUSIVE, + &ip); + + gfs_glock_dq(io_gh); + + if (error) + goto fail; + + /* Verify disk (d)inode, gfs inode, and VFS (v)inode are unused */ + if (ip->i_di.di_nlink) { + if (gfs_consist_inode(ip)) + gfs_dinode_print(&ip->i_di); + error = -EIO; + goto fail_iput; + } + gfs_assert_warn(sdp, atomic_read(&ip->i_count) == 1); + gfs_assert_warn(sdp, !ip->i_vnode); + + /* Free all on-disk directory leaves (if any) to FREEMETA state */ + if (ip->i_di.di_type == GFS_FILE_DIR && + (ip->i_di.di_flags & GFS_DIF_EXHASH)) { + error = gfs_dir_exhash_free(ip); + if (error) + goto fail_iput; + } + + /* Free all on-disk extended attribute blocks to FREEMETA state */ + if (ip->i_di.di_eattr) { + error = gfs_ea_dealloc(ip); + if (error) + goto fail_iput; + } + + /* Free all data blocks to FREE state, and meta blocks to FREEMETA */ + error = gfs_shrink(ip, 0, NULL); + if (error) + goto fail_iput; + + /* Set UNUSED flag and increment incarn # in on-disk dinode block, + and de-alloc the block to FREEMETA */ + error = dinode_dealloc(ip); + if (error) + goto fail_iput; + + /* Free the GFS inode structure, unhold iopen and inode glocks */ + gfs_inode_put(ip); + gfs_inode_destroy(ip); + + gfs_glock_dq_uninit(&i_gh); + + return 0; + + fail_iput: + gfs_inode_put(ip); + gfs_inode_destroy(ip); + + fail: + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * inode_dealloc_init - Try to deallocate an initialized on-disk inode (dinode) + * and all of its associated data and meta blocks + * @sdp: the filesystem + * + * Returns: 0 on success, -errno on error, 1 on busy (inode open) + */ + +static int +inode_dealloc_init(struct gfs_sbd *sdp, struct gfs_inum *inum) +{ + struct gfs_holder io_gh; + int error = 0; + + /* If not busy (on this node), de-alloc GFS incore inode, releasing + any indirect addressing buffers, and unholding iopen glock */ + gfs_try_toss_inode(sdp, inum); + + /* Does another process (cluster-wide) have this inode open? */ + error = gfs_glock_nq_num(sdp, + inum->no_addr, &gfs_iopen_glops, + LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &io_gh); + switch (error) { + case 0: + break; + case GLR_TRYFAILED: + return 1; + default: + return error; + } + + /* Unlock here to prevent deadlock */ + gfs_glock_dq(&io_gh); + + /* No other process in the entire cluster has this inode open; + we can remove it and all of its associated blocks from disk */ + error = inode_dealloc(sdp, inum, &io_gh); + gfs_holder_uninit(&io_gh); + + return error; +} + +/** + * inode_dealloc_uninit - dealloc an uninitialized on-disk inode (dinode) block + * @sdp: the filesystem + * + * Create a transaction to change dinode block's alloc state to FREEMETA + * + * Returns: 0 on success, -errno on error, 1 on busy + */ + +static int +inode_dealloc_uninit(struct gfs_sbd *sdp, struct gfs_inum *inum) +{ + struct gfs_rgrpd *rgd; + struct gfs_holder ri_gh, rgd_gh; + int error; + + error = gfs_rindex_hold(sdp, &ri_gh); + if (error) + return error; + + rgd = gfs_blk2rgrpd(sdp, inum->no_addr); + if (!rgd) { + gfs_consist(sdp); + error = -EIO; + goto fail; + } + + error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rgd_gh); + if (error) + goto fail; + + /* Trans may require: + One block for the RG header. + One block for the dinode bit. + We also need a block for the unlinked change. */ + + error = gfs_trans_begin(sdp, 2, 1); + if (error) + goto fail_gunlock; + + gfs_difree_uninit(rgd, inum->no_addr); + gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA, inum); + + gfs_trans_end(sdp); + + gfs_glock_dq_uninit(&rgd_gh); + gfs_glock_dq_uninit(&ri_gh); + + return 0; + + fail_gunlock: + gfs_glock_dq_uninit(&rgd_gh); + + fail: + gfs_glock_dq_uninit(&ri_gh); + + return error; +} + +/** + * gfs_inode_dealloc - Grab an unlinked inode off the list and try to free it. + * @sdp: the filesystem + * + * Returns: 0 on success, -errno on error, 1 on busy + */ + +int +gfs_inode_dealloc(struct gfs_sbd *sdp, struct gfs_inum *inum) +{ + if (inum->no_formal_ino) + return inode_dealloc_init(sdp, inum); + else + return inode_dealloc_uninit(sdp, inum); +} + +/** + * gfs_change_nlink - Change nlink count on inode + * @ip: The GFS inode + * @diff: The change in the nlink count required + * + * Returns: errno + */ + +int +gfs_change_nlink(struct gfs_inode *ip, int diff) +{ + struct buffer_head *dibh; + uint32_t nlink; + int error; + + nlink = ip->i_di.di_nlink + diff; + + /* Tricky. If we are reducing the nlink count, + but the new value ends up being bigger than the + old one, we must have underflowed. */ + if (diff < 0 && nlink > ip->i_di.di_nlink) { + if (gfs_consist_inode(ip)) + gfs_dinode_print(&ip->i_di); + return -EIO; + } + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + return error; + + ip->i_di.di_nlink = nlink; + ip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + + return 0; +} + +/** + * gfs_lookupi - Look up a filename in a directory and return its inode + * @d_gh: An initialized holder for the directory glock + * @name: The name of the inode to look for + * @is_root: If TRUE, ignore the caller's permissions + * @i_gh: An uninitialized holder for the new inode glock + * + * There will always be a vnode (Linux VFS inode) for the d_gh inode unless + * @is_root is true. + * + * Returns: errno + */ + +int +gfs_lookupi(struct gfs_holder *d_gh, struct qstr *name, + int is_root, struct gfs_holder *i_gh) +{ + struct gfs_inode *dip = get_gl2ip(d_gh->gh_gl); + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_glock *gl; + struct gfs_inode *ip; + struct gfs_inum inum, inum2; + unsigned int type; + int error; + + i_gh->gh_gl = NULL; + + if (!name->len || name->len > GFS_FNAMESIZE) + return -ENAMETOOLONG; + + if (gfs_filecmp(name, ".", 1) || + (gfs_filecmp(name, "..", 2) && dip == sdp->sd_rooti)) { + gfs_holder_reinit(LM_ST_SHARED, 0, d_gh); + error = gfs_glock_nq(d_gh); + if (!error) { + error = gfs_glock_nq_init(dip->i_gl, + LM_ST_SHARED, 0, + i_gh); + if (error) { + gfs_glock_dq(d_gh); + return error; + } + gfs_inode_hold(dip); + } + return error; + } + + if (gfs_assert_warn(sdp, !gfs_glock_is_locked_by_me(d_gh->gh_gl))) + return -EINVAL; + + gfs_holder_reinit(LM_ST_SHARED, 0, d_gh); + error = gfs_glock_nq(d_gh); + if (error) + return error; + + if (!is_root) { + error = inode_permission(dip->i_vnode, MAY_EXEC); + if (error) { + gfs_glock_dq(d_gh); + return error; + } + } + + error = gfs_dir_search(dip, name, &inum, &type); + if (error) { + gfs_glock_dq(d_gh); + if (error == -ENOENT) + error = 0; + return error; + } + + restart: + error = gfs_glock_get(sdp, inum.no_formal_ino, &gfs_inode_glops, + CREATE, &gl); + if (error) { + gfs_glock_dq(d_gh); + return error; + } + + /* Acquire the second lock */ + + if (gl->gl_name.ln_number < dip->i_gl->gl_name.ln_number) { + gfs_glock_dq(d_gh); + + error = gfs_glock_nq_init(gl, LM_ST_SHARED, + LM_FLAG_ANY | GL_LOCAL_EXCL, + i_gh); + if (error) + goto out; + + gfs_holder_reinit(LM_ST_SHARED, 0, d_gh); + error = gfs_glock_nq(d_gh); + if (error) { + gfs_glock_dq_uninit(i_gh); + goto out; + } + + if (!is_root) { + error = inode_permission(dip->i_vnode, MAY_EXEC); + if (error) { + gfs_glock_dq(d_gh); + gfs_glock_dq_uninit(i_gh); + goto out; + } + } + + error = gfs_dir_search(dip, name, &inum2, &type); + if (error) { + gfs_glock_dq(d_gh); + gfs_glock_dq_uninit(i_gh); + if (error == -ENOENT) + error = 0; + goto out; + } + + if (!gfs_inum_equal(&inum, &inum2)) { + gfs_glock_dq_uninit(i_gh); + gfs_glock_put(gl); + inum = inum2; + goto restart; + } + } else { + error = gfs_glock_nq_init(gl, LM_ST_SHARED, + LM_FLAG_ANY | GL_LOCAL_EXCL, + i_gh); + if (error) { + gfs_glock_dq(d_gh); + goto out; + } + } + + error = gfs_inode_get(gl, &inum, CREATE, &ip); + if (error) { + gfs_glock_dq(d_gh); + gfs_glock_dq_uninit(i_gh); + } else if (ip->i_di.di_type != type) { + gfs_consist_inode(dip); + gfs_inode_put(ip); + gfs_glock_dq(d_gh); + gfs_glock_dq_uninit(i_gh); + error = -EIO; + } + + out: + gfs_glock_put(gl); + + return error; +} + +/** + * create_ok - OK to create a new on-disk inode here? + * @dip: Directory in which dinode is to be created + * @name: Name of new dinode + * @type: GFS_FILE_XXX (regular file, dir, etc.) + * + * Returns: errno + */ + +static int +create_ok(struct gfs_inode *dip, struct qstr *name, unsigned int type) +{ + int error; + + error = inode_permission(dip->i_vnode, MAY_WRITE | MAY_EXEC); + if (error) + return error; + + /* Don't create entries in an unlinked directory */ + + if (!dip->i_di.di_nlink) + return -EPERM; + + error = gfs_dir_search(dip, name, NULL, NULL); + switch (error) { + case -ENOENT: + error = 0; + break; + case 0: + return -EEXIST; + default: + return error; + } + + if (dip->i_di.di_entries == (uint32_t)-1) + return -EFBIG; + if (type == GFS_FILE_DIR && dip->i_di.di_nlink == (uint32_t)-1) + return -EMLINK; + + return 0; +} + +/** + * dinode_alloc - Create an on-disk inode + * @dip: Directory in which to create the dinode + * @ul: + * + * Since this dinode is not yet linked, we also create an unlinked inode + * descriptor. + * + * Returns: errno + */ + +static int +dinode_alloc(struct gfs_inode *dip, struct gfs_unlinked **ul) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_alloc *al; + struct gfs_inum inum; + int error; + + /* Create in-place allocation structure, reserve 1 dinode */ + al = gfs_alloc_get(dip); + al->al_requested_di = 1; + error = gfs_inplace_reserve(dip); + if (error) + goto out; + + error = gfs_trans_begin(sdp, al->al_rgd->rd_ri.ri_length, 1); + if (error) + goto out_inplace; + + inum.no_formal_ino = 0; + error = gfs_dialloc(dip, &inum.no_addr); + if (error) + goto out_end_trans; + + *ul = gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IUL, &inum); + gfs_unlinked_lock(sdp, *ul); + + gfs_trans_add_gl(dip->i_gl); + + out_end_trans: + gfs_trans_end(sdp); + + out_inplace: + gfs_inplace_release(dip); + + out: + gfs_alloc_put(dip); + + return error; +} + +/** + * pick_formal_ino - Pick a formal inode number for a given inode + * @sdp: the filesystem + * @inum: the inode number structure + * + */ + +static void +pick_formal_ino(struct gfs_sbd *sdp, struct gfs_inum *inum) +{ + /* This won't always be true */ + inum->no_formal_ino = inum->no_addr; +} + +/** + * make_dinode - Fill in a new dinode structure + * @dip: the directory this inode is being created in + * @gl: The glock covering the new inode + * @inum: the inode number + * @type: the file type + * @mode: the file permissions + * @uid: + * @gid: + * + */ + +static int +make_dinode(struct gfs_inode *dip, + struct gfs_glock *gl, struct gfs_inum *inum, + unsigned int type, unsigned int mode, + unsigned int uid, unsigned int gid) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_dinode di; + struct buffer_head *dibh; + struct gfs_rgrpd *rgd; + int error; + + error = gfs_dread(gl, inum->no_addr, + DIO_NEW | DIO_START | DIO_WAIT, + &dibh); + if (error) + return error; + + gfs_trans_add_bh(gl, dibh); + gfs_metatype_set(dibh, GFS_METATYPE_DI, GFS_FORMAT_DI); + gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode)); + + memset(&di, 0, sizeof(struct gfs_dinode)); + + gfs_meta_header_in(&di.di_header, dibh->b_data); + + di.di_num = *inum; + + di.di_mode = mode & S_IALLUGO; + di.di_uid = uid; + di.di_gid = gid; + di.di_nlink = 1; + di.di_blocks = 1; + di.di_atime = di.di_mtime = di.di_ctime = get_seconds(); + + rgd = gfs_blk2rgrpd(sdp, inum->no_addr); + if (!rgd) { + if (gfs_consist(sdp)) + printk("GFS: fsid=%s: block = %"PRIu64"\n", + sdp->sd_fsname, inum->no_addr); + brelse(dibh); + return -EIO; + } + + di.di_rgrp = rgd->rd_ri.ri_addr; + di.di_goal_rgrp = di.di_rgrp; + di.di_goal_dblk = di.di_goal_mblk = inum->no_addr - rgd->rd_ri.ri_data1; + + if (type == GFS_FILE_REG) { + if ((dip->i_di.di_flags & GFS_DIF_INHERIT_JDATA) || + gfs_tune_get(sdp, gt_new_files_jdata)) + di.di_flags |= GFS_DIF_JDATA; + if ((dip->i_di.di_flags & GFS_DIF_INHERIT_DIRECTIO) || + gfs_tune_get(sdp, gt_new_files_directio)) + di.di_flags |= GFS_DIF_DIRECTIO; + } else if (type == GFS_FILE_DIR) { + di.di_flags |= (dip->i_di.di_flags & GFS_DIF_INHERIT_DIRECTIO); + di.di_flags |= (dip->i_di.di_flags & GFS_DIF_INHERIT_JDATA); + } + + di.di_type = type; + + gfs_dinode_out(&di, dibh->b_data); + brelse(dibh); + + return 0; +} + +/** + * inode_init_and_link - + * @dip: + * @name: + * @inum: + * @gl: + * @type: + * @mode: + * + * Returns: errno + */ + +static int +inode_init_and_link(struct gfs_inode *dip, struct qstr *name, + struct gfs_inum *inum, struct gfs_glock *gl, + unsigned int type, mode_t mode) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_alloc *al; + struct gfs_inode *ip; + unsigned int uid, gid; + int alloc_required; + void *acl_a_data = NULL, *acl_d_data = NULL; + unsigned int acl_size = 0, acl_blocks = 0; + int error; + + if (sdp->sd_args.ar_suiddir && + (dip->i_di.di_mode & S_ISUID) && + dip->i_di.di_uid) { + if (type == GFS_FILE_DIR) + mode |= S_ISUID; + else if (dip->i_di.di_uid != current->fsuid) + mode &= ~07111; + uid = dip->i_di.di_uid; + } else + uid = current->fsuid; + + if (dip->i_di.di_mode & S_ISGID) { + if (type == GFS_FILE_DIR) + mode |= S_ISGID; + gid = dip->i_di.di_gid; + } else + gid = current->fsgid; + + error = gfs_acl_new_prep(dip, type, &mode, + &acl_a_data, &acl_d_data, + &acl_size, &acl_blocks); + if (error) + return error; + + al = gfs_alloc_get(dip); + + error = gfs_quota_lock_m(dip, uid, gid); + if (error) + goto fail; + + error = gfs_quota_check(dip, uid, gid); + if (error) + goto fail_gunlock_q; + + if (acl_blocks) + alloc_required = TRUE; + else { + error = gfs_diradd_alloc_required(dip, name, &alloc_required); + if (error) + goto fail_gunlock_q; + } + + if (alloc_required) { + error = gfs_quota_check(dip, dip->i_di.di_uid, dip->i_di.di_gid); + if (error) + goto fail_gunlock_q; + + al->al_requested_meta = sdp->sd_max_dirres + acl_blocks; + + error = gfs_inplace_reserve(dip); + if (error) + goto fail_gunlock_q; + + /* Trans may require: + blocks for two dinodes, the directory blocks necessary for + a new entry, RG bitmap blocks for an allocation, + and one block for a quota change and + one block for an unlinked tag. */ + + error = gfs_trans_begin(sdp, + 2 + sdp->sd_max_dirres + acl_blocks + + al->al_rgd->rd_ri.ri_length, 2); + if (error) + goto fail_inplace; + } else { + error = gfs_rindex_hold(sdp, &al->al_ri_gh); + if (error) + goto fail_gunlock_q; + + /* Trans may require: + blocks for two dinodes, a leaf block, + and one block for a quota change and + one block for an unlinked tag. */ + + error = gfs_trans_begin(sdp, 3, 2); + if (error) + goto fail_inplace; + } + + error = gfs_dir_add(dip, name, inum, type); + if (error) + goto fail_end_trans; + + error = make_dinode(dip, gl, inum, type, mode, uid, gid); + if (error) + goto fail_end_trans; + + al->al_ul = gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA, + &(struct gfs_inum){0, inum->no_addr}); + gfs_trans_add_quota(sdp, +1, uid, gid); + + error = gfs_inode_get(gl, inum, CREATE, &ip); + + /* This should only fail if we are already shutdown. */ + if (gfs_assert_withdraw(sdp, !error)) + goto fail_end_trans; + + if (acl_blocks) + error = gfs_acl_new_init(dip, ip, + acl_a_data, acl_d_data, + acl_size); + + if (!alloc_required) + gfs_glock_dq_uninit(&al->al_ri_gh); + + return error; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_inplace: + if (alloc_required) + gfs_inplace_release(dip); + else + gfs_glock_dq_uninit(&al->al_ri_gh); + + fail_gunlock_q: + gfs_quota_unlock_m(dip); + + fail: + gfs_alloc_put(dip); + if (acl_a_data) + kfree(acl_a_data); + else if (acl_d_data) + kfree(acl_d_data); + + return error; +} + +/** + * gfs_createi - Create a new inode + * @d_gh: An initialized holder for the directory glock + * @name: The name of the new file + * @type: The type of dinode (GFS_FILE_REG, GFS_FILE_DIR, GFS_FILE_LNK, ...) + * @mode: the permissions on the new inode + * @i_gh: An uninitialized holder for the new inode glock + * + * If the return value is 0, the glocks on both the directory and the new + * file are held. A transaction has been started and an inplace reservation + * is held, as well. + * + * Returns: errno + */ + +int +gfs_createi(struct gfs_holder *d_gh, struct qstr *name, + unsigned int type, unsigned int mode, + struct gfs_holder *i_gh) +{ + struct gfs_inode *dip = get_gl2ip(d_gh->gh_gl); + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_unlinked *ul; + struct gfs_inum inum; + struct gfs_holder io_gh; + int error; + + if (!name->len || name->len > GFS_FNAMESIZE) + return -ENAMETOOLONG; + + gfs_holder_reinit(LM_ST_EXCLUSIVE, 0, d_gh); + error = gfs_glock_nq(d_gh); + if (error) + return error; + + error = create_ok(dip, name, type); + if (error) + goto fail; + + error = dinode_alloc(dip, &ul); + if (error) + goto fail; + + inum.no_addr = ul->ul_inum.no_addr; + pick_formal_ino(sdp, &inum); + + if (inum.no_formal_ino < dip->i_num.no_formal_ino) { + gfs_glock_dq(d_gh); + + error = gfs_glock_nq_num(sdp, + inum.no_formal_ino, &gfs_inode_glops, + LM_ST_EXCLUSIVE, GL_SKIP, i_gh); + if (error) { + gfs_unlinked_unlock(sdp, ul); + return error; + } + + gfs_holder_reinit(LM_ST_EXCLUSIVE, 0, d_gh); + error = gfs_glock_nq(d_gh); + if (error) { + gfs_glock_dq_uninit(i_gh); + gfs_unlinked_unlock(sdp, ul); + return error; + } + + error = create_ok(dip, name, type); + if (error) + goto fail_gunlock_i; + } else { + error = gfs_glock_nq_num(sdp, + inum.no_formal_ino, &gfs_inode_glops, + LM_ST_EXCLUSIVE, GL_SKIP, i_gh); + if (error) + goto fail_ul; + } + + error = gfs_glock_nq_num(sdp, + inum.no_addr, &gfs_iopen_glops, + LM_ST_SHARED, GL_LOCAL_EXCL | GL_EXACT, + &io_gh); + if (error) + goto fail_gunlock_i; + + error = inode_init_and_link(dip, name, &inum, i_gh->gh_gl, type, mode); + if (error) + goto fail_gunlock_io; + + gfs_glock_dq_uninit(&io_gh); + + return 0; + + fail_gunlock_io: + gfs_glock_dq_uninit(&io_gh); + + fail_gunlock_i: + gfs_glock_dq_uninit(i_gh); + + fail_ul: + gfs_unlinked_unlock(sdp, ul); + + fail: + gfs_glock_dq(d_gh); + + return error; +} + +/** + * gfs_unlinki - Unlink a file + * @dip: The inode of the directory + * @name: The name of the file to be unlinked + * @ip: The inode of the file to be removed + * + * Assumes Glocks on both dip and ip are held. + * + * Returns: errno + */ + +int +gfs_unlinki(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = dip->i_sbd; + int error; + + error = gfs_dir_del(dip, name); + if (error) + return error; + + error = gfs_change_nlink(ip, -1); + if (error) + return error; + + /* If this inode is being unlinked from the directory structure, + we need to mark that in the log so that it isn't lost during + a crash. */ + + if (!ip->i_di.di_nlink) { + gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IUL, &ip->i_num); + set_bit(GLF_STICKY, &ip->i_gl->gl_flags); + } + + return 0; +} + +/** + * gfs_rmdiri - Remove a directory + * @dip: The parent directory of the directory to be removed + * @name: The name of the directory to be removed + * @ip: The GFS inode of the directory to be removed + * + * Assumes Glocks on dip and ip are held + * + * Returns: errno + */ + +int +gfs_rmdiri(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = dip->i_sbd; + struct qstr dotname; + int error; + + if (ip->i_di.di_entries != 2) { + if (gfs_consist_inode(ip)) + gfs_dinode_print(&ip->i_di); + return -EIO; + } + + error = gfs_dir_del(dip, name); + if (error) + return error; + + error = gfs_change_nlink(dip, -1); + if (error) + return error; + + dotname.len = 1; + dotname.name = "."; + error = gfs_dir_del(ip, &dotname); + if (error) + return error; + + dotname.len = 2; + dotname.name = ".."; + error = gfs_dir_del(ip, &dotname); + if (error) + return error; + + error = gfs_change_nlink(ip, -2); + if (error) + return error; + + /* This inode is being unlinked from the directory structure and + we need to mark that in the log so that it isn't lost during + a crash. */ + + gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IUL, &ip->i_num); + set_bit(GLF_STICKY, &ip->i_gl->gl_flags); + + return 0; +} + +/* + * gfs_unlink_ok - check to see that a inode is still in a directory + * @dip: the directory + * @name: the name of the file + * @ip: the inode + * + * Assumes that the lock on (at least) @dip is held. + * + * Returns: 0 if the parent/child relationship is correct, errno if it isn't + */ + +int +gfs_unlink_ok(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip) +{ + struct gfs_inum inum; + unsigned int type; + int error; + + if (IS_IMMUTABLE(ip->i_vnode) || IS_APPEND(ip->i_vnode)) + return -EPERM; + + if ((dip->i_di.di_mode & S_ISVTX) && + dip->i_di.di_uid != current->fsuid && + ip->i_di.di_uid != current->fsuid && + !capable(CAP_FOWNER)) + return -EPERM; + + if (IS_APPEND(dip->i_vnode)) + return -EPERM; + + error = inode_permission(dip->i_vnode, MAY_WRITE | MAY_EXEC); + if (error) + return error; + + error = gfs_dir_search(dip, name, &inum, &type); + if (error) + return error; + + if (inum.no_formal_ino != ip->i_num.no_formal_ino) + return -ENOENT; + + if (ip->i_di.di_type != type) { + gfs_consist_inode(dip); + return -EIO; + } + + return 0; +} + +/* + * gfs_ok_to_move - check if it's ok to move a directory to another directory + * @this: move this + * @to: to here + * + * Follow @to back to the root and make sure we don't encounter @this + * Assumes we already hold the rename lock. + * + * Returns: errno + */ + +int +gfs_ok_to_move(struct gfs_inode *this, struct gfs_inode *to) +{ + struct gfs_sbd *sdp = this->i_sbd; + struct gfs_inode *tmp; + struct gfs_holder to_gh, tmp_gh; + struct qstr dotdot; + int error = 0; + + memset(&dotdot, 0, sizeof (struct qstr)); + dotdot.name = ".."; + dotdot.len = 2; + + gfs_inode_hold(to); + + for (;;) { + if (to == this) { + error = -EINVAL; + break; + } + if (to == sdp->sd_rooti) { + error = 0; + break; + } + + gfs_holder_init(to->i_gl, 0, 0, &to_gh); + + error = gfs_lookupi(&to_gh, &dotdot, TRUE, &tmp_gh); + if (error) { + gfs_holder_uninit(&to_gh); + break; + } + if (!tmp_gh.gh_gl) { + gfs_holder_uninit(&to_gh); + error = -ENOENT; + break; + } + + tmp = get_gl2ip(tmp_gh.gh_gl); + + gfs_glock_dq_uninit(&to_gh); + gfs_glock_dq_uninit(&tmp_gh); + + gfs_inode_put(to); + to = tmp; + } + + gfs_inode_put(to); + + return error; +} + +/** + * gfs_readlinki - return the contents of a symlink + * @ip: the symlink's inode + * @buf: a pointer to the buffer to be filled + * @len: a pointer to the length of @buf + * + * If @buf is too small, a piece of memory is kmalloc()ed and needs + * to be freed by the caller. + * + * Returns: errno + */ + +int +gfs_readlinki(struct gfs_inode *ip, char **buf, unsigned int *len) +{ + struct gfs_holder i_gh; + struct buffer_head *dibh; + unsigned int x; + int error; + + gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh); + error = gfs_glock_nq_atime(&i_gh); + if (error) { + gfs_holder_uninit(&i_gh); + return error; + } + + if (!ip->i_di.di_size) { + gfs_consist_inode(ip); + error = -EIO; + goto out; + } + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto out; + + x = ip->i_di.di_size + 1; + if (x > *len) { + *buf = kmalloc(x, GFP_KERNEL); + if (!*buf) { + error = -ENOMEM; + goto out_brelse; + } + } + + memcpy(*buf, dibh->b_data + sizeof(struct gfs_dinode), x); + *len = x; + + out_brelse: + brelse(dibh); + + out: + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_glock_nq_atime - Acquire a hold on an inode's glock, and + * conditionally update the inode's atime + * @gh: the holder to acquire + * + * Tests atime (access time) for gfs_read, gfs_readdir and gfs_mmap + * Update if the difference between the current time and the inode's current + * atime is greater than an interval specified at mount (or default). + * + * Will not update if GFS mounted NOATIME (this is *the* place where NOATIME + * has an effect) or Read-Only. + * + * Returns: errno + */ + +int +gfs_glock_nq_atime(struct gfs_holder *gh) +{ + struct gfs_glock *gl = gh->gh_gl; + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_inode *ip = get_gl2ip(gl); + int64_t curtime, quantum = gfs_tune_get(sdp, gt_atime_quantum); + unsigned int state; + int flags; + int error; + + if (gfs_assert_warn(sdp, gh->gh_flags & GL_ATIME) || + gfs_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) || + gfs_assert_warn(sdp, gl->gl_ops == &gfs_inode_glops)) + return -EINVAL; + + /* Save original request state of lock holder */ + state = gh->gh_state; + flags = gh->gh_flags; + + error = gfs_glock_nq(gh); + if (error) + return error; + + if (test_bit(SDF_NOATIME, &sdp->sd_flags) || + test_bit(SDF_ROFS, &sdp->sd_flags)) + return 0; + + curtime = get_seconds(); + if (curtime - ip->i_di.di_atime >= quantum) { + /* Get EX hold (force EX glock via !ANY) to write the dinode */ + gfs_glock_dq(gh); + gfs_holder_reinit(LM_ST_EXCLUSIVE, + gh->gh_flags & ~LM_FLAG_ANY, + gh); + error = gfs_glock_nq(gh); + if (error) + return error; + + /* Verify that atime hasn't been updated while we were + trying to get exclusive lock. */ + + curtime = get_seconds(); + if (curtime - ip->i_di.di_atime >= quantum) { + struct buffer_head *dibh; + + error = gfs_trans_begin(sdp, 1, 0); + if (error == -EROFS) + return 0; + if (error) + goto fail; + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto fail_end_trans; + + ip->i_di.di_atime = curtime; + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + + gfs_trans_end(sdp); + } + + /* If someone else has asked for the glock, + unlock and let them have it. Then reacquire + in the original state. */ + if (gfs_glock_is_blocking(gl)) { + gfs_glock_dq(gh); + gfs_holder_reinit(state, flags, gh); + return gfs_glock_nq(gh); + } + } + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail: + gfs_glock_dq(gh); + + return error; +} + +/** + * glock_compare_atime - Compare two struct gfs_glock structures for gfs_sort() + * @arg_a: the first structure + * @arg_b: the second structure + * + * Sort order determined by (in order of priority): + * -- lock number + * -- lock state (SHARED > EXCLUSIVE or GL_ATIME, which can demand EXCLUSIVE) + * + * Returns: 1 if A > B + * -1 if A < B + * 0 if A = B + */ + +static int +glock_compare_atime(const void *arg_a, const void *arg_b) +{ + struct gfs_holder *gh_a = *(struct gfs_holder **)arg_a; + struct gfs_holder *gh_b = *(struct gfs_holder **)arg_b; + struct lm_lockname *a = &gh_a->gh_gl->gl_name; + struct lm_lockname *b = &gh_b->gh_gl->gl_name; + int ret = 0; + + if (a->ln_number > b->ln_number) + ret = 1; + else if (a->ln_number < b->ln_number) + ret = -1; + else { + if (gh_a->gh_state == LM_ST_SHARED && + gh_b->gh_state == LM_ST_EXCLUSIVE) + ret = 1; + else if (gh_a->gh_state == LM_ST_SHARED && + (gh_b->gh_flags & GL_ATIME)) + ret = 1; + } + + return ret; +} + +/** + * gfs_glock_nq_m_atime - acquire multiple glocks where one may need an + * atime update + * @num_gh: the number of structures + * @ghs: an array of struct gfs_holder structures + * + * Returns: 0 on success (all glocks acquired), + * errno on failure (no glocks acquired) + */ + +int +gfs_glock_nq_m_atime(unsigned int num_gh, struct gfs_holder *ghs) +{ + struct gfs_holder **p; + unsigned int x; + int error = 0; + + if (!num_gh) + return 0; + + if (num_gh == 1) { + ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); + if (ghs->gh_flags & GL_ATIME) + error = gfs_glock_nq_atime(ghs); + else + error = gfs_glock_nq(ghs); + return error; + } + + p = kmalloc(num_gh * sizeof(struct gfs_holder *), GFP_KERNEL); + if (!p) + return -ENOMEM; + + for (x = 0; x < num_gh; x++) + p[x] = &ghs[x]; + + gfs_sort(p, num_gh, sizeof(struct gfs_holder *), glock_compare_atime); + + for (x = 0; x < num_gh; x++) { + p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); + + if (p[x]->gh_flags & GL_ATIME) + error = gfs_glock_nq_atime(p[x]); + else + error = gfs_glock_nq(p[x]); + + if (error) { + while (x--) + gfs_glock_dq(p[x]); + break; + } + } + + kfree(p); + return error; +} + +/** + * gfs_try_toss_vnode - See if we can toss a vnode from memory + * @ip: the inode + * + * Returns: TRUE if the vnode was tossed + */ + +void +gfs_try_toss_vnode(struct gfs_inode *ip) +{ + struct inode *inode; + + inode = gfs_iget(ip, NO_CREATE); + if (!inode) + return; + + d_prune_aliases(inode); + + if (ip->i_di.di_type == GFS_FILE_DIR) { + struct list_head *head = &inode->i_dentry; + struct dentry *d = NULL; + + spin_lock(&dcache_lock); + if (list_empty(head)) + spin_unlock(&dcache_lock); + else { + d = list_entry(head->next, struct dentry, d_alias); + dget_locked(d); + spin_unlock(&dcache_lock); + + if (have_submounts(d)) + dput(d); + else { + shrink_dcache_parent(d); + dput(d); + d_prune_aliases(inode); + } + } + } + + inode->i_nlink = 0; + iput(inode); +} + + +static int +__gfs_setattr_simple(struct gfs_inode *ip, struct iattr *attr) +{ + struct buffer_head *dibh; + int error; + + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + error = inode_setattr(ip->i_vnode, attr); + gfs_assert_warn(ip->i_sbd, !error); + gfs_inode_attr_out(ip); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + return error; +} + +/** + * gfs_setattr_simple - + * @ip: + * @attr: + * + * Called with a reference on the vnode. + * + * Returns: errno + */ + +int +gfs_setattr_simple(struct gfs_inode *ip, struct iattr *attr) +{ + int error; + + if (get_transaction) + return __gfs_setattr_simple(ip, attr); + + /* Trans may require: + one dinode block. */ + + error = gfs_trans_begin(ip->i_sbd, 1, 0); + if (error) + return error; + + error = __gfs_setattr_simple(ip, attr); + + gfs_trans_end(ip->i_sbd); + + return error; +} + +/** + * iah_make_jdata - + * @gl: + * @inum: + * + */ + +static void +iah_make_jdata(struct gfs_glock *gl, struct gfs_inum *inum) +{ + struct buffer_head *bh; + struct gfs_dinode *di; + uint32_t flags; + int error; + + error = gfs_dread(gl, inum->no_addr, DIO_START | DIO_WAIT, &bh); + + /* This should only fail if we are already shutdown. */ + if (gfs_assert_withdraw(gl->gl_sbd, !error)) + return; + + di = (struct gfs_dinode *)bh->b_data; + + flags = di->di_flags; + flags = gfs32_to_cpu(flags) | GFS_DIF_JDATA; + di->di_flags = cpu_to_gfs32(flags); + + brelse(bh); +} + +/** + * iah_super_update - Write superblock to disk + * @sdp: filesystem instance structure + * + * Returns: errno + * + * Update on-disk superblock, using (modified) data in sdp->sd_sb + */ + +static int +iah_super_update(struct gfs_sbd *sdp) +{ + struct gfs_glock *gl; + struct buffer_head *bh; + int error; + + error = gfs_glock_get(sdp, + GFS_SB_LOCK, &gfs_meta_glops, + NO_CREATE, &gl); + if (gfs_assert_withdraw(sdp, !error && gl)) /* This should already be held. */ + return -EINVAL; + + error = gfs_dread(gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift, + DIO_START | DIO_WAIT, &bh); + if (!error) { + gfs_trans_add_bh(gl, bh); + gfs_sb_out(&sdp->sd_sb, bh->b_data); + brelse(bh); + } + + gfs_glock_put(gl); + + return error; +} + +/** + * inode_alloc_hidden - allocate on-disk inode for a special (hidden) file + * @sdp: the filesystem instance structure + * @inum: new dinode's block # and formal inode #, to be filled + * in by this function. + * + * Returns: errno + * + * This function is called only very rarely, when the first-to-mount + * node can't find a pre-existing special file (e.g. license or quota file) that + * it expects to find. This should happen only when upgrading from an older + * version of the filesystem. + * + * The @inum must be a member of sdp->sd_sb in order to get updated to on-disk + * superblock properly. + */ + +static int +inode_alloc_hidden(struct gfs_sbd *sdp, struct gfs_inum *inum) +{ + struct gfs_inode *dip = sdp->sd_rooti; + struct gfs_holder d_gh, i_gh; + struct gfs_unlinked *ul; + int error; + + error = gfs_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh); + if (error) + return error; + + error = dinode_alloc(dip, &ul); + if (error) + goto fail; + + inum->no_addr = ul->ul_inum.no_addr; + pick_formal_ino(sdp, inum); + + /* Don't worry about deadlock ordering here. We're the first + mounter and still under the mount lock (i.e. there is no + contention). */ + + error = gfs_glock_nq_num(sdp, + inum->no_formal_ino, &gfs_inode_glops, + LM_ST_EXCLUSIVE, GL_SKIP, &i_gh); + if (error) + goto fail_ul; + + gfs_alloc_get(dip); + + error = gfs_quota_hold_m(dip, 0, 0); + if (error) + goto fail_al; + + /* Trans may require: + The new inode, the superblock, + and one block for a quota change and + one block for an unlinked tag. */ + + error = gfs_trans_begin(sdp, 2, 2); + if (error) + goto fail_unhold; + + error = make_dinode(dip, i_gh.gh_gl, inum, GFS_FILE_REG, 0600, 0, 0); + if (error) + goto fail_end_trans; + + /* Hidden files get all of their data (not just metadata) journaled */ + iah_make_jdata(i_gh.gh_gl, inum); + + error = iah_super_update(sdp); + if (error) + goto fail_end_trans; + + gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA, + &(struct gfs_inum){0, inum->no_addr}); + gfs_trans_add_quota(sdp, +1, 0, 0); + gfs_trans_add_gl(dip->i_gl); + + gfs_trans_end(sdp); + gfs_quota_unhold_m(dip); + gfs_alloc_put(dip); + + gfs_glock_dq_uninit(&i_gh); + gfs_glock_dq_uninit(&d_gh); + + gfs_unlinked_unlock(sdp, ul); + + gfs_log_flush(sdp); + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_unhold: + gfs_quota_unhold_m(dip); + + fail_al: + gfs_alloc_put(dip); + gfs_glock_dq_uninit(&i_gh); + + fail_ul: + gfs_unlinked_unlock(sdp, ul); + + fail: + gfs_glock_dq_uninit(&d_gh); + + return error; +} + +/** + * gfs_alloc_qinode - allocate a quota inode + * @sdp: The GFS superblock + * + * Returns: 0 on success, error code otherwise + */ + +int +gfs_alloc_qinode(struct gfs_sbd *sdp) +{ + return inode_alloc_hidden(sdp, &sdp->sd_sb.sb_quota_di); +} + +/** + * gfs_alloc_linode - allocate a license inode + * @sdp: The GFS superblock + * + * Returns: 0 on success, error code otherwise + */ + +int +gfs_alloc_linode(struct gfs_sbd *sdp) +{ + return inode_alloc_hidden(sdp, &sdp->sd_sb.sb_license_di); +} --- linux-2.6.27.orig/ubuntu/gfs/glops.h +++ linux-2.6.27/ubuntu/gfs/glops.h @@ -0,0 +1,13 @@ +#ifndef __GLOPS_DOT_H__ +#define __GLOPS_DOT_H__ + +extern struct gfs_glock_operations gfs_meta_glops; +extern struct gfs_glock_operations gfs_inode_glops; +extern struct gfs_glock_operations gfs_rgrp_glops; +extern struct gfs_glock_operations gfs_trans_glops; +extern struct gfs_glock_operations gfs_iopen_glops; +extern struct gfs_glock_operations gfs_flock_glops; +extern struct gfs_glock_operations gfs_nondisk_glops; +extern struct gfs_glock_operations gfs_quota_glops; + +#endif /* __GLOPS_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/sys.c +++ linux-2.6.27/ubuntu/gfs/sys.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "glock.h" +#include "lm.h" +#include "sys.h" +#include "super.h" + +char *gfs_sys_margs; +spinlock_t gfs_sys_margs_lock; + +static ssize_t id_show(struct gfs_sbd *sdp, char *buf) +{ + return sprintf(buf, "%s\n", sdp->sd_vfs->s_id); +} + +static ssize_t fsname_show(struct gfs_sbd *sdp, char *buf) +{ + return sprintf(buf, "%s\n", sdp->sd_fsname); +} + +struct gfs_attr { + struct attribute attr; + ssize_t (*show)(struct gfs_sbd *, char *); + ssize_t (*store)(struct gfs_sbd *, const char *, size_t); +}; + +#define GFS_ATTR(name, mode, show, store) \ +static struct gfs_attr gfs_attr_##name = __ATTR(name, mode, show, store) + +GFS_ATTR(id, 0444, id_show, NULL); +GFS_ATTR(fsname, 0444, fsname_show, NULL); + +static struct attribute *gfs_attrs[] = { + &gfs_attr_id.attr, + &gfs_attr_fsname.attr, + NULL, +}; + +static ssize_t gfs_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct gfs_sbd *sdp = container_of(kobj, struct gfs_sbd, sd_kobj); + struct gfs_attr *a = container_of(attr, struct gfs_attr, attr); + return a->show ? a->show(sdp, buf) : 0; +} + +static ssize_t gfs_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t len) +{ + struct gfs_sbd *sdp = container_of(kobj, struct gfs_sbd, sd_kobj); + struct gfs_attr *a = container_of(attr, struct gfs_attr, attr); + return a->store ? a->store(sdp, buf, len) : len; +} + +static struct sysfs_ops gfs_attr_ops = { + .show = gfs_attr_show, + .store = gfs_attr_store, +}; + +static struct kobj_type gfs_ktype = { + .default_attrs = gfs_attrs, + .sysfs_ops = &gfs_attr_ops, +}; + +static struct kset *gfs_kset; + +int gfs_sys_fs_add(struct gfs_sbd *sdp) +{ + int error; + + sdp->sd_kobj.kset = gfs_kset; + + error = kobject_init_and_add(&sdp->sd_kobj, &gfs_ktype, NULL, + "%s", sdp->sd_table_name); + if (error) + goto fail; + + kobject_uevent(&sdp->sd_kobj, KOBJ_ADD); + + return 0; + + fail: + return error; +} + +void gfs_sys_fs_del(struct gfs_sbd *sdp) +{ + kobject_put(&sdp->sd_kobj); +} + +int gfs_sys_init(void) +{ + gfs_sys_margs = NULL; + spin_lock_init(&gfs_sys_margs_lock); + gfs_kset = kset_create_and_add("gfs", NULL, fs_kobj); + if (!gfs_kset) + return -ENOMEM; + return 0; +} + +void gfs_sys_uninit(void) +{ + kfree(gfs_sys_margs); + kset_unregister(gfs_kset); +} --- linux-2.6.27.orig/ubuntu/gfs/ops_super.c +++ linux-2.6.27/ubuntu/gfs/ops_super.c @@ -0,0 +1,455 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "glock.h" +#include "inode.h" +#include "lm.h" +#include "log.h" +#include "ops_fstype.h" +#include "ops_super.h" +#include "page.h" +#include "proc.h" +#include "quota.h" +#include "recovery.h" +#include "rgrp.h" +#include "super.h" +#include "sys.h" +#include "mount.h" + +/** + * gfs_write_inode - Make sure the inode is stable on the disk + * @inode: The inode + * @sync: synchronous write flag + * + * Returns: errno + */ + +static int +gfs_write_inode(struct inode *inode, int sync) +{ + struct gfs_inode *ip = get_v2ip(inode); + + atomic_inc(&ip->i_sbd->sd_ops_super); + + if (ip && sync) + gfs_log_flush_glock(ip->i_gl); + + return 0; +} + +/** + * gfs_drop_inode - drop an inode + * @inode: The inode + * + * If i_nlink is zero, any dirty data for the inode is thrown away. + * If a process on another machine has the file open, it may need that + * data. So, sync it out. + */ + +static void +gfs_drop_inode(struct inode *inode) +{ + struct gfs_sbd *sdp = get_v2sdp(inode->i_sb); + struct gfs_inode *ip = get_v2ip(inode); + + atomic_inc(&sdp->sd_ops_super); + + if (ip && + !inode->i_nlink && + S_ISREG(inode->i_mode) && + !sdp->sd_args.ar_localcaching) + gfs_sync_page_i(inode, DIO_START | DIO_WAIT); + generic_drop_inode(inode); +} + +/** + * gfs_put_super - Unmount the filesystem + * @sb: The VFS superblock + * + */ + +static void +gfs_put_super(struct super_block *sb) +{ + struct gfs_sbd *sdp = get_v2sdp(sb); + int error; + + if (!sdp) + return; + + atomic_inc(&sdp->sd_ops_super); + + gfs_proc_fs_del(sdp); + + /* Unfreeze the filesystem, if we need to */ + + down(&sdp->sd_freeze_lock); + if (sdp->sd_freeze_count) + gfs_glock_dq_uninit(&sdp->sd_freeze_gh); + up(&sdp->sd_freeze_lock); + + /* Kill off the inode thread */ + kthread_stop(sdp->sd_inoded_process); + + /* Kill off the quota thread */ + kthread_stop(sdp->sd_quotad_process); + + /* Kill off the log thread */ + kthread_stop(sdp->sd_logd_process); + + /* Kill off the recoverd thread */ + kthread_stop(sdp->sd_recoverd_process); + + /* Kill off the glockd threads */ + while (sdp->sd_glockd_num--) + kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); + + /* Kill off the scand thread */ + kthread_stop(sdp->sd_scand_process); + + if (!test_bit(SDF_ROFS, &sdp->sd_flags)) { + error = gfs_make_fs_ro(sdp); + if (error) + gfs_io_error(sdp); + } + + /* At this point, we're through modifying the disk */ + + /* Release stuff */ + + gfs_inode_put(sdp->sd_riinode); + gfs_inode_put(sdp->sd_jiinode); + gfs_inode_put(sdp->sd_rooti); + gfs_inode_put(sdp->sd_qinode); + gfs_inode_put(sdp->sd_linode); + gfs_glock_put(sdp->sd_trans_gl); + gfs_glock_put(sdp->sd_rename_gl); + + if (!sdp->sd_args.ar_spectator) + gfs_glock_dq_uninit(&sdp->sd_journal_gh); + + gfs_glock_dq_uninit(&sdp->sd_live_gh); + + /* Get rid of rgrp bitmap structures */ + gfs_clear_rgrpd(sdp); + gfs_clear_journals(sdp); + + /* Take apart glock structures and buffer lists */ + gfs_gl_hash_clear(sdp, TRUE); + + /* Unmount the locking protocol */ + gfs_lm_unmount(sdp); + + /* At this point, we're through participating in the lockspace */ + + gfs_sys_fs_del(sdp); + + gfs_clear_dirty_j(sdp); + + /* Get rid of any extra inodes */ + while (invalidate_inodes(sb)) + yield(); + + vfree(sdp); + + set_v2sdp(sb, NULL); +} + +/** + * gfs_write_super - disk commit all incore transactions + * @sb: the filesystem + * + * This function is called every time sync(2) is called. + * After this exits, all dirty buffers and synced. + */ + +static void +gfs_write_super(struct super_block *sb) +{ + struct gfs_sbd *sdp = get_v2sdp(sb); + atomic_inc(&sdp->sd_ops_super); + gfs_log_flush(sdp); +} + +/** + * gfs_write_super_lockfs - prevent further writes to the filesystem + * @sb: the VFS structure for the filesystem + * + */ + +static void +gfs_write_super_lockfs(struct super_block *sb) +{ + struct gfs_sbd *sdp = get_v2sdp(sb); + int error; + + if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + return; + + atomic_inc(&sdp->sd_ops_super); + + for (;;) { + error = gfs_freeze_fs(sdp); + if (!error) + break; + + switch (error) { + case -EBUSY: + printk("GFS: fsid=%s: waiting for recovery before freeze\n", + sdp->sd_fsname); + break; + + default: + printk("GFS: fsid=%s: error freezing FS: %d\n", + sdp->sd_fsname, error); + break; + } + + printk("GFS: fsid=%s: retrying...\n", sdp->sd_fsname); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + } +} + +/** + * gfs_unlockfs - reallow writes to the filesystem + * @sb: the VFS structure for the filesystem + * + */ + +static void +gfs_unlockfs(struct super_block *sb) +{ + struct gfs_sbd *sdp = get_v2sdp(sb); + + atomic_inc(&sdp->sd_ops_super); + + gfs_unfreeze_fs(sdp); +} + +/** + * gfs_statfs - Gather and return stats about the filesystem + * @sb: The superblock + * @statfsbuf: The buffer + * + * Returns: 0 on success or error code + */ + +static int gfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_inode->i_sb; + struct gfs_sbd *sdp = get_v2sdp(sb); + struct gfs_stat_gfs sg; + int error; + + atomic_inc(&sdp->sd_ops_super); + + if (gfs_tune_get(sdp, gt_statfs_fast)) + return(gfs_statfs_fast(sdp, (void *)buf)); + + error = gfs_stat_gfs(sdp, &sg, TRUE); + if (error) + return error; + + memset(buf, 0, sizeof(struct kstatfs)); + + buf->f_type = GFS_MAGIC; + buf->f_bsize = sdp->sd_sb.sb_bsize; + buf->f_blocks = sg.sg_total_blocks; + buf->f_bfree = sg.sg_free + sg.sg_free_dinode + sg.sg_free_meta; + buf->f_bavail = sg.sg_free + sg.sg_free_dinode + sg.sg_free_meta; + buf->f_files = sg.sg_used_dinode + sg.sg_free_dinode + + sg.sg_free_meta + sg.sg_free; + buf->f_ffree = sg.sg_free_dinode + sg.sg_free_meta + sg.sg_free; + buf->f_namelen = GFS_FNAMESIZE; + + return 0; +} + +/** + * gfs_remount_fs - called when the FS is remounted + * @sb: the filesystem + * @flags: the remount flags + * @data: extra data passed in (not used right now) + * + * Returns: errno + */ + +static int +gfs_remount_fs(struct super_block *sb, int *flags, char *data) +{ + struct gfs_sbd *sdp = get_v2sdp(sb); + struct gfs_tune *gt = &sdp->sd_tune; + int error = 0; + struct gfs_args *args; + + atomic_inc(&sdp->sd_ops_super); + + args = kmalloc(sizeof(struct gfs_args), GFP_KERNEL); + if (!args) + return -ENOMEM; + + error = gfs_make_args(data, args, TRUE); + if (error) { + printk("GFS: can't parse remount arguments\n"); + goto out; + } + if (args->ar_posix_acls) { + sdp->sd_args.ar_posix_acls = TRUE; + sb->s_flags |= MS_POSIXACL; + } + else { + sdp->sd_args.ar_posix_acls = FALSE; + sb->s_flags &= ~MS_POSIXACL; + } + + if (*flags & (MS_NOATIME | MS_NODIRATIME)) + set_bit(SDF_NOATIME, &sdp->sd_flags); + else + clear_bit(SDF_NOATIME, &sdp->sd_flags); + + if (sdp->sd_args.ar_spectator) + *flags |= MS_RDONLY; + else { + if (*flags & MS_RDONLY) { + if (!test_bit(SDF_ROFS, &sdp->sd_flags)) + error = gfs_make_fs_ro(sdp); + } else if (!(*flags & MS_RDONLY) && + test_bit(SDF_ROFS, &sdp->sd_flags)) { + error = gfs_make_fs_rw(sdp); + } + } + + if (args->ar_noquota) { + if (sdp->sd_args.ar_noquota == FALSE) + printk("GFS: remounting without quota\n"); + sdp->sd_args.ar_noquota = TRUE; + spin_lock(>->gt_spin); + gt->gt_quota_enforce = 0; + gt->gt_quota_account = 0; + spin_unlock(>->gt_spin); + } + else { + if (sdp->sd_args.ar_noquota == TRUE) + printk("GFS: remounting with quota\n"); + sdp->sd_args.ar_noquota = FALSE; + spin_lock(>->gt_spin); + gt->gt_quota_enforce = 1; + gt->gt_quota_account = 1; + spin_unlock(>->gt_spin); + } + + /* Don't let the VFS update atimes. GFS handles this itself. */ + *flags |= MS_NOATIME | MS_NODIRATIME; + +out: + kfree(args); + return error; +} + +/** + * gfs_clear_inode - Deallocate an inode when VFS is done with it + * @inode: The VFS inode + * + * If there's a GFS incore inode structure attached to the VFS inode: + * -- Detach them from one another. + * -- Schedule reclaim of GFS inode struct, the glock protecting it, and + * the associated iopen glock. + */ + +static void +gfs_clear_inode(struct inode *inode) +{ + struct gfs_inode *ip = get_v2ip(inode); + + atomic_inc(&get_v2sdp(inode->i_sb)->sd_ops_super); + + if (ip) { + spin_lock(&ip->i_spin); + ip->i_vnode = NULL; + set_v2ip(inode, NULL); + spin_unlock(&ip->i_spin); + + gfs_glock_schedule_for_reclaim(ip->i_gl); + gfs_inode_put(ip); + } +} + +/** + * gfs_show_options - Show mount options for /proc/mounts + * @s: seq_file structure + * @mnt: vfsmount + * + * Returns: 0 on success or error code + */ + +static int +gfs_show_options(struct seq_file *s, struct vfsmount *mnt) +{ + struct gfs_sbd *sdp = get_v2sdp(mnt->mnt_sb); + struct gfs_args *args = &sdp->sd_args; + + atomic_inc(&sdp->sd_ops_super); + + if (args->ar_lockproto[0]) { + seq_printf(s, ",lockproto="); + seq_puts(s, args->ar_lockproto); + } + if (args->ar_locktable[0]) { + seq_printf(s, ",locktable="); + seq_puts(s, args->ar_locktable); + } + if (args->ar_hostdata[0]) { + seq_printf(s, ",hostdata="); + seq_puts(s, args->ar_hostdata); + } + if (args->ar_spectator) + seq_printf(s, ",spectator"); + if (args->ar_ignore_local_fs) + seq_printf(s, ",ignore_local_fs"); + if (args->ar_localflocks) + seq_printf(s, ",localflocks"); + if (args->ar_localcaching) + seq_printf(s, ",localcaching"); + if (args->ar_oopses_ok) + seq_printf(s, ",oopses_ok"); + if (args->ar_debug) + seq_printf(s, ",debug"); + if (args->ar_upgrade) + seq_printf(s, ",upgrade"); + if (args->ar_num_glockd != GFS_GLOCKD_DEFAULT) + seq_printf(s, ",num_glockd=%u", args->ar_num_glockd); + if (args->ar_posix_acls) + seq_printf(s, ",acl"); + if (args->ar_noquota) + seq_printf(s, ",noquota"); + if (args->ar_suiddir) + seq_printf(s, ",suiddir"); + + return 0; +} + +struct super_operations gfs_super_ops = { + .write_inode = gfs_write_inode, + .drop_inode = gfs_drop_inode, + .put_super = gfs_put_super, + .write_super = gfs_write_super, + .write_super_lockfs = gfs_write_super_lockfs, + .unlockfs = gfs_unlockfs, + .statfs = gfs_statfs, + .remount_fs = gfs_remount_fs, + .clear_inode = gfs_clear_inode, + .show_options = gfs_show_options, +}; --- linux-2.6.27.orig/ubuntu/gfs/ops_export.c +++ linux-2.6.27/ubuntu/gfs/ops_export.c @@ -0,0 +1,403 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "dir.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "ops_dentry.h" +#include "ops_export.h" +#include "rgrp.h" + +struct inode_cookie +{ + uint64_t formal_ino; + uint32_t gen; + int gen_valid; +}; + +struct get_name_filldir +{ + uint64_t formal_ino; + char *name; +}; + +/** + * gfs_encode_fh - + * @param1: description + * @param2: description + * @param3: description + * + * Function description + * + * Returns: what is returned + */ + +int +gfs_encode_fh(struct dentry *dentry, __u32 *fh, int *len, + int connectable) +{ + struct inode *inode = dentry->d_inode; + struct gfs_inode *ip = get_v2ip(inode); + int maxlen = *len; + + atomic_inc(&ip->i_sbd->sd_ops_export); + + if (maxlen < 3) + return 255; + + fh[0] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino >> 32)); + fh[1] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino & 0xFFFFFFFF)); + fh[2] = cpu_to_gfs32(inode->i_generation); /* dinode's mh_incarn */ + *len = 3; + + if (maxlen < 5 || !connectable) + return 3; + + spin_lock(&dentry->d_lock); + + inode = dentry->d_parent->d_inode; + ip = get_v2ip(inode); + + fh[3] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino >> 32)); + fh[4] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino & 0xFFFFFFFF)); + *len = 5; + + if (maxlen < 6) { + spin_unlock(&dentry->d_lock); + return 5; + } + + fh[5] = cpu_to_gfs32(inode->i_generation); /* dinode's mh_incarn */ + + spin_unlock(&dentry->d_lock); + + *len = 6; + + return 6; +} + +/** + * get_name_filldir - + * @param1: description + * @param2: description + * @param3: description + * + * Function description + * + * Returns: what is returned + */ + +static int +get_name_filldir(void *opaque, + const char *name, unsigned int length, + uint64_t offset, + struct gfs_inum *inum, unsigned int type) +{ + struct get_name_filldir *gnfd = (struct get_name_filldir *)opaque; + + if (inum->no_formal_ino != gnfd->formal_ino) + return 0; + + memcpy(gnfd->name, name, length); + gnfd->name[length] = 0; + + return 1; +} + +/** + * gfs_get_name - + * @param1: description + * @param2: description + * @param3: description + * + * Function description + * + * Returns: what is returned + */ + +int gfs_get_name(struct dentry *parent, char *name, + struct dentry *child) +{ + struct inode *dir = parent->d_inode; + struct inode *inode = child->d_inode; + struct gfs_inode *dip, *ip; + struct get_name_filldir gnfd; + struct gfs_holder gh; + uint64_t offset = 0; + int error; + + if (!dir) + return -EINVAL; + + atomic_inc(&get_v2sdp(dir->i_sb)->sd_ops_export); + + if (!S_ISDIR(dir->i_mode) || !inode) + return -EINVAL; + + dip = get_v2ip(dir); + ip = get_v2ip(inode); + + *name = 0; + gnfd.formal_ino = ip->i_num.no_formal_ino; + gnfd.name = name; + + error = gfs_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); + if (error) + return error; + + error = gfs_dir_read(dip, &offset, &gnfd, get_name_filldir); + + gfs_glock_dq_uninit(&gh); + + if (!error & !*name) + error = -ENOENT; + + return error; +} + +/** + * gfs_get_parent - + * @param1: description + * @param2: description + * @param3: description + * + * Function description + * + * Returns: what is returned + */ + +struct dentry * +gfs_get_parent(struct dentry *child) +{ + struct gfs_inode *dip = get_v2ip(child->d_inode); + struct gfs_holder d_gh, i_gh; + struct qstr dotdot = { .name = "..", .len = 2 }; + struct gfs_inode *ip; + struct inode *inode; + struct dentry *dentry; + int error; + + atomic_inc(&dip->i_sbd->sd_ops_export); + + gfs_holder_init(dip->i_gl, 0, 0, &d_gh); + error = gfs_lookupi(&d_gh, &dotdot, TRUE, &i_gh); + if (error) + goto fail; + + error = -ENOENT; + if (!i_gh.gh_gl) + goto fail; + + ip = get_gl2ip(i_gh.gh_gl); + + inode = gfs_iget(ip, CREATE); + gfs_inode_put(ip); + + gfs_glock_dq_uninit(&d_gh); + gfs_glock_dq_uninit(&i_gh); + + if (!inode) + return ERR_PTR(-ENOMEM); + + dentry = d_alloc_anon(inode); + if (!dentry) { + iput(inode); + return ERR_PTR(-ENOMEM); + } + + dentry->d_op = &gfs_dops; + return dentry; + + fail: + gfs_holder_uninit(&d_gh); + return ERR_PTR(error); +} + +/** + * gfs_get_dentry - + * @param1: description + * @param2: description + * @param3: description + * + * Function description + * + * Returns: what is returned + */ + +struct dentry * +gfs_get_dentry(struct super_block *sb, struct inode_cookie *cookie) +{ + struct gfs_sbd *sdp = get_v2sdp(sb); + struct gfs_inum inum; + struct gfs_holder i_gh, ri_gh, rgd_gh; + struct gfs_rgrpd *rgd; + struct buffer_head *bh; + struct gfs_dinode *di; + struct gfs_inode *ip; + struct inode *inode; + struct dentry *dentry; + int error; + + atomic_inc(&sdp->sd_ops_export); + + if (!cookie->formal_ino || + cookie->formal_ino == sdp->sd_jiinode->i_num.no_formal_ino || + cookie->formal_ino == sdp->sd_riinode->i_num.no_formal_ino || + cookie->formal_ino == sdp->sd_qinode->i_num.no_formal_ino) + return ERR_PTR(-EINVAL); + + inum.no_formal_ino = cookie->formal_ino; + inum.no_addr = cookie->formal_ino; + + error = gfs_glock_nq_num(sdp, + inum.no_formal_ino, &gfs_inode_glops, + LM_ST_SHARED, LM_FLAG_ANY | GL_LOCAL_EXCL, + &i_gh); + if (error) + return ERR_PTR(error); + + error = gfs_inode_get(i_gh.gh_gl, &inum, NO_CREATE, &ip); + if (error) + goto fail; + if (ip) + goto out; + + error = gfs_rindex_hold(sdp, &ri_gh); + if (error) + goto fail; + + error = -EINVAL; + rgd = gfs_blk2rgrpd(sdp, inum.no_addr); + if (!rgd) + goto fail_rindex; + + error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh); + if (error) + goto fail_rindex; + + error = -ESTALE; + if (gfs_get_block_type(rgd, inum.no_addr) != GFS_BLKST_USEDMETA) + goto fail_rgd; + + error = gfs_dread(i_gh.gh_gl, inum.no_addr, + DIO_START | DIO_WAIT, &bh); + if (error) + goto fail_rgd; + + di = (struct gfs_dinode *)bh->b_data; + + error = -ESTALE; + if (gfs32_to_cpu(di->di_header.mh_magic) != GFS_MAGIC || + gfs32_to_cpu(di->di_header.mh_type) != GFS_METATYPE_DI || + (gfs32_to_cpu(di->di_flags) & GFS_DIF_UNUSED)) + goto fail_relse; + + brelse(bh); + gfs_glock_dq_uninit(&rgd_gh); + gfs_glock_dq_uninit(&ri_gh); + + error = gfs_inode_get(i_gh.gh_gl, &inum, CREATE, &ip); + if (error) + goto fail; + + atomic_inc(&sdp->sd_fh2dentry_misses); + + out: + inode = gfs_iget(ip, CREATE); + gfs_inode_put(ip); + + gfs_glock_dq_uninit(&i_gh); + + if (!inode) + return ERR_PTR(-ENOMEM); + + /* inode->i_generation is GFS dinode's mh_incarn value */ + if (cookie->gen_valid && cookie->gen != inode->i_generation) { + iput(inode); + return ERR_PTR(-ESTALE); + } + + dentry = d_alloc_anon(inode); + if (!dentry) { + iput(inode); + return ERR_PTR(-ENOMEM); + } + + dentry->d_op = &gfs_dops; + return dentry; + + fail_relse: + brelse(bh); + + fail_rgd: + gfs_glock_dq_uninit(&rgd_gh); + + fail_rindex: + gfs_glock_dq_uninit(&ri_gh); + + fail: + gfs_glock_dq_uninit(&i_gh); + return ERR_PTR(error); +} + +static struct dentry *gfs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + struct inode_cookie this; + __u32 *fh = fid->raw; + + atomic_inc(&get_v2sdp(sb)->sd_ops_export); + + switch (fh_type) { + case 6: + case 5: + case 3: + this.gen_valid = TRUE; + this.gen = gfs32_to_cpu(fh[2]); + this.formal_ino = ((uint64_t)gfs32_to_cpu(fh[0])) << 32; + this.formal_ino |= (uint64_t)gfs32_to_cpu(fh[1]); + return gfs_get_dentry(sb, &this); + default: + return NULL; + } +} + +static struct dentry *gfs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + struct inode_cookie parent; + __u32 *fh = fid->raw; + + atomic_inc(&get_v2sdp(sb)->sd_ops_export); + + switch (fh_type) { + case 6: + parent.gen_valid = TRUE; + parent.gen = gfs32_to_cpu(fh[5]); + case 5: + parent.formal_ino = ((uint64_t)gfs32_to_cpu(fh[3])) << 32; + parent.formal_ino |= (uint64_t)gfs32_to_cpu(fh[4]); + default: + return NULL; + } + + return gfs_get_dentry(sb, &parent); +} + +const struct export_operations gfs_export_ops = { + .encode_fh = gfs_encode_fh, + .fh_to_dentry = gfs_fh_to_dentry, + .fh_to_parent = gfs_fh_to_parent, + .get_name = gfs_get_name, + .get_parent = gfs_get_parent, +}; + --- linux-2.6.27.orig/ubuntu/gfs/sys.h +++ linux-2.6.27/ubuntu/gfs/sys.h @@ -0,0 +1,14 @@ +#ifndef __SYS_DOT_H__ +#define __SYS_DOT_H__ + +/* Allow args to be passed to GFS when using an initial ram disk */ +extern char *gfs_sys_margs; +extern spinlock_t gfs_sys_margs_lock; + +int gfs_sys_fs_add(struct gfs_sbd *sdp); +void gfs_sys_fs_del(struct gfs_sbd *sdp); + +int gfs_sys_init(void); +void gfs_sys_uninit(void); + +#endif /* __SYS_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/dio.c +++ linux-2.6.27/ubuntu/gfs/dio.c @@ -0,0 +1,1342 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "dio.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "log.h" +#include "lops.h" +#include "rgrp.h" +#include "trans.h" + +#define buffer_busy(bh) ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock))) + +/** + * aspace_get_block - + * @inode: + * @lblock: + * @bh_result: + * @create: + * + * Returns: errno + */ + +static int +aspace_get_block(struct inode *inode, sector_t lblock, + struct buffer_head *bh_result, int create) +{ + gfs_assert_warn(get_v2sdp(inode->i_sb), FALSE); + return -ENOSYS; +} + +/** + * gfs_aspace_writepage - write an aspace page + * @page: the page + * @wbc: + * + * Returns: errno + */ + +static int +gfs_aspace_writepage(struct page *page, struct writeback_control *wbc) +{ + return block_write_full_page(page, aspace_get_block, wbc); +} + +/** + * stuck_releasepage - We're stuck in gfs_releasepage(). Print stuff out. + * @bh: the buffer we're stuck on + * + */ + +static void +stuck_releasepage(struct buffer_head *bh) +{ + struct gfs_sbd *sdp = get_v2sdp(bh->b_page->mapping->host->i_sb); + struct gfs_bufdata *bd = get_v2bd(bh); + + printk("GFS: fsid=%s: stuck in gfs_releasepage()...\n", sdp->sd_fsname); + printk("GFS: fsid=%s: blkno = %"PRIu64", bh->b_count = %d\n", + sdp->sd_fsname, + (uint64_t)bh->b_blocknr, + atomic_read(&bh->b_count)); + printk("GFS: fsid=%s: get_v2bd(bh) = %s\n", + sdp->sd_fsname, + (bd) ? "!NULL" : "NULL"); + + if (bd) { + struct gfs_glock *gl = bd->bd_gl; + + printk("GFS: fsid=%s: gl = (%u, %"PRIu64")\n", + sdp->sd_fsname, + gl->gl_name.ln_type, + gl->gl_name.ln_number); + + printk("GFS: fsid=%s: bd_new_le.le_trans = %s\n", + sdp->sd_fsname, + (bd->bd_new_le.le_trans) ? "!NULL" : "NULL"); + printk("GFS: fsid=%s: bd_incore_le.le_trans = %s\n", + sdp->sd_fsname, + (bd->bd_incore_le.le_trans) ? "!NULL" : "NULL"); + printk("GFS: fsid=%s: bd_frozen = %s\n", + sdp->sd_fsname, + (bd->bd_frozen) ? "!NULL" : "NULL"); + printk("GFS: fsid=%s: bd_pinned = %u\n", + sdp->sd_fsname, bd->bd_pinned); + printk("GFS: fsid=%s: bd_ail_tr_list = %s\n", + sdp->sd_fsname, + (list_empty(&bd->bd_ail_tr_list)) ? "Empty" : "!Empty"); + + if (gl->gl_ops == &gfs_inode_glops) { + struct gfs_inode *ip = get_gl2ip(gl); + + if (ip) { + unsigned int x; + + printk("GFS: fsid=%s: ip = %"PRIu64"/%"PRIu64"\n", + sdp->sd_fsname, + ip->i_num.no_formal_ino, + ip->i_num.no_addr); + printk("GFS: fsid=%s: ip->i_count = %d, ip->i_vnode = %s\n", + sdp->sd_fsname, + atomic_read(&ip->i_count), + (ip->i_vnode) ? "!NULL" : "NULL"); + for (x = 0; x < GFS_MAX_META_HEIGHT; x++) + printk("GFS: fsid=%s: ip->i_cache[%u] = %s\n", + sdp->sd_fsname, x, + (ip->i_cache[x]) ? "!NULL" : "NULL"); + } + } + } +} + +/** + * gfs_aspace_releasepage - free the metadata associated with a page + * @page: the page that's being released + * @gfp_mask: passed from Linux VFS, ignored by us + * + * Call try_to_free_buffers() if the buffers in this page can be + * released. + * + * Returns: 0 + */ + +static int +gfs_aspace_releasepage(struct page *page, gfp_t gfp_mask) +{ + struct inode *aspace = page->mapping->host; + struct gfs_sbd *sdp = get_v2sdp(aspace->i_sb); + struct buffer_head *bh, *head; + struct gfs_bufdata *bd; + unsigned long t; + + if (!page_has_buffers(page)) + goto out; + + head = bh = page_buffers(page); + do { + t = jiffies; + + while (atomic_read(&bh->b_count)) { + if (atomic_read(&aspace->i_writecount)) { + if (time_after_eq(jiffies, + t + + gfs_tune_get(sdp, gt_stall_secs) * HZ)) { + stuck_releasepage(bh); + t = jiffies; + } + + yield(); + continue; + } + + return 0; + } + + bd = get_v2bd(bh); + if (bd) { + gfs_assert_warn(sdp, bd->bd_bh == bh); + gfs_assert_warn(sdp, !bd->bd_new_le.le_trans); + gfs_assert_warn(sdp, !bd->bd_incore_le.le_trans); + gfs_assert_warn(sdp, !bd->bd_frozen); + gfs_assert_warn(sdp, !bd->bd_pinned); + gfs_assert_warn(sdp, list_empty(&bd->bd_ail_tr_list)); + kmem_cache_free(gfs_bufdata_cachep, bd); + atomic_dec(&sdp->sd_bufdata_count); + set_v2bd(bh, NULL); + } + + bh = bh->b_this_page; + } + while (bh != head); + + out: + return try_to_free_buffers(page); +} + +static struct address_space_operations aspace_aops = { + .writepage = gfs_aspace_writepage, + .releasepage = gfs_aspace_releasepage, +}; + +/** + * gfs_aspace_get - Create and initialize a struct inode structure + * @sdp: the filesystem the aspace is in + * + * Right now a struct inode is just a struct inode. Maybe Linux + * will supply a more lightweight address space construct (that works) + * in the future. + * + * Make sure pages/buffers in this aspace aren't in high memory. + * + * Returns: the aspace + */ + +struct inode * +gfs_aspace_get(struct gfs_sbd *sdp) +{ + struct inode *aspace; + + aspace = new_inode(sdp->sd_vfs); + if (aspace) { + mapping_set_gfp_mask(aspace->i_mapping, GFP_KERNEL); + aspace->i_mapping->a_ops = &aspace_aops; + aspace->i_size = ~0ULL; + set_v2ip(aspace, NULL); + insert_inode_hash(aspace); + } + + return aspace; +} + +/** + * gfs_aspace_put - get rid of an aspace + * @aspace: + * + */ + +void +gfs_aspace_put(struct inode *aspace) +{ + remove_inode_hash(aspace); + iput(aspace); +} + +/** + * gfs_ail_start_trans - Start I/O on a part of the AIL + * @sdp: the filesystem + * @tr: the part of the AIL + * + */ + +void +gfs_ail_start_trans(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *head, *tmp, *prev; + struct gfs_bufdata *bd; + struct buffer_head *bh; + int retry; + + do { + retry = FALSE; + + spin_lock(&sdp->sd_ail_lock); + + for (head = &tr->tr_ail_bufs, tmp = head->prev, prev = tmp->prev; + tmp != head; + tmp = prev, prev = tmp->prev) { + bd = list_entry(tmp, struct gfs_bufdata, bd_ail_tr_list); + bh = bd->bd_bh; + + if (gfs_trylock_buffer(bh)) + continue; + + if (bd->bd_pinned) { + gfs_unlock_buffer(bh); + continue; + } + + if (!buffer_busy(bh)) { + if (!buffer_uptodate(bh)) + gfs_io_error_bh(sdp, bh); + + list_del_init(&bd->bd_ail_tr_list); + list_del(&bd->bd_ail_gl_list); + + gfs_unlock_buffer(bh); + brelse(bh); + continue; + } + + if (buffer_dirty(bh)) { + list_move(&bd->bd_ail_tr_list, head); + + spin_unlock(&sdp->sd_ail_lock); + wait_on_buffer(bh); + ll_rw_block(WRITE, 1, &bh); + spin_lock(&sdp->sd_ail_lock); + + gfs_unlock_buffer(bh); + retry = TRUE; + break; + } + + gfs_unlock_buffer(bh); + } + + spin_unlock(&sdp->sd_ail_lock); + } while (retry); +} + +/** + * gfs_ail_empty_trans - Check whether or not a trans in the AIL has been synced + * @sdp: the filesystem + * @tr: the transaction + * + */ + +int +gfs_ail_empty_trans(struct gfs_sbd *sdp, struct gfs_trans *tr) +{ + struct list_head *head, *tmp, *prev; + struct gfs_bufdata *bd; + struct buffer_head *bh; + int ret; + + spin_lock(&sdp->sd_ail_lock); + + for (head = &tr->tr_ail_bufs, tmp = head->prev, prev = tmp->prev; + tmp != head; + tmp = prev, prev = tmp->prev) { + bd = list_entry(tmp, struct gfs_bufdata, bd_ail_tr_list); + bh = bd->bd_bh; + + if (gfs_trylock_buffer(bh)) + continue; + + if (bd->bd_pinned || buffer_busy(bh)) { + gfs_unlock_buffer(bh); + continue; + } + + if (!buffer_uptodate(bh)) + gfs_io_error_bh(sdp, bh); + + list_del_init(&bd->bd_ail_tr_list); + list_del(&bd->bd_ail_gl_list); + + gfs_unlock_buffer(bh); + brelse(bh); + } + + ret = list_empty(head); + + spin_unlock(&sdp->sd_ail_lock); + + return ret; +} + +/** + * ail_empty_gl - remove all buffers for a given lock from the AIL + * @gl: the glock + * + * None of the buffers should be dirty, locked, or pinned. + */ + +static void +ail_empty_gl(struct gfs_glock *gl) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_bufdata *bd; + struct buffer_head *bh; + + spin_lock(&sdp->sd_ail_lock); + + while (!list_empty(&gl->gl_ail_bufs)) { + bd = list_entry(gl->gl_ail_bufs.next, + struct gfs_bufdata, bd_ail_gl_list); + bh = bd->bd_bh; + + gfs_assert_withdraw(sdp, !bd->bd_pinned && !buffer_busy(bh)); + if (!buffer_uptodate(bh)) + gfs_io_error_bh(sdp, bh); + + list_del_init(&bd->bd_ail_tr_list); + list_del(&bd->bd_ail_gl_list); + + brelse(bh); + } + + spin_unlock(&sdp->sd_ail_lock); +} + +/** + * gfs_inval_buf - Invalidate all buffers associated with a glock + * @gl: the glock + * + */ + +void +gfs_inval_buf(struct gfs_glock *gl) +{ + struct inode *aspace = gl->gl_aspace; + struct address_space *mapping = gl->gl_aspace->i_mapping; + + ail_empty_gl(gl); + + atomic_inc(&aspace->i_writecount); + truncate_inode_pages(mapping, 0); + atomic_dec(&aspace->i_writecount); + + gfs_assert_withdraw(gl->gl_sbd, !mapping->nrpages); +} + +/** + * gfs_sync_buf - Sync all buffers associated with a glock + * @gl: The glock + * @flags: DIO_START | DIO_WAIT | DIO_CHECK + * + */ + +void +gfs_sync_buf(struct gfs_glock *gl, int flags) +{ + struct address_space *mapping = gl->gl_aspace->i_mapping; + int error = 0; + + if (flags & DIO_START) + error = filemap_fdatawrite(mapping); + if (!error && (flags & DIO_WAIT)) + error = filemap_fdatawait(mapping); + if (!error && (flags & (DIO_INVISIBLE | DIO_CHECK)) == DIO_CHECK) + ail_empty_gl(gl); + + if (error) + gfs_io_error(gl->gl_sbd); +} + +/** + * getbuf - Get a buffer with a given address space + * @sdp: the filesystem + * @aspace: the address space + * @blkno: the block number (filesystem scope) + * @create: TRUE if the buffer should be created + * + * Returns: the buffer + */ + +static struct buffer_head * +getbuf(struct gfs_sbd *sdp, struct inode *aspace, uint64_t blkno, int create) +{ + struct page *page; + struct buffer_head *bh; + unsigned int shift; + unsigned long index; + unsigned int bufnum; + + shift = PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift; + index = blkno >> shift; /* convert block to page */ + bufnum = blkno - (index << shift); /* block buf index within page */ + + if (create) { + RETRY_MALLOC(page = grab_cache_page(aspace->i_mapping, index), page); + } else { + page = find_lock_page(aspace->i_mapping, index); + if (!page) + return NULL; + } + + if (!page_has_buffers(page)) + create_empty_buffers(page, sdp->sd_sb.sb_bsize, 0); + + /* Locate header for our buffer within our page */ + for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page) + /* Do nothing */; + get_bh(bh); + + if (!buffer_mapped(bh)) + map_bh(bh, sdp->sd_vfs, blkno); + else if (gfs_assert_warn(sdp, bh->b_bdev == sdp->sd_vfs->s_bdev && + bh->b_blocknr == blkno)) + map_bh(bh, sdp->sd_vfs, blkno); + + unlock_page(page); + page_cache_release(page); + + return bh; +} + +/** + * gfs_dgetblk - Get a block + * @gl: The glock associated with this block + * @blkno: The block number + * + * Returns: The buffer + */ + +struct buffer_head * +gfs_dgetblk(struct gfs_glock *gl, uint64_t blkno) +{ + return getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE); +} + +/** + * gfs_dread - Read a block from disk + * @gl: The glock covering the block + * @blkno: The block number + * @flags: flags to gfs_dreread() + * @bhp: the place where the buffer is returned (NULL on failure) + * + * Returns: errno + */ + +int +gfs_dread(struct gfs_glock *gl, uint64_t blkno, + int flags, struct buffer_head **bhp) +{ + int error; + + *bhp = gfs_dgetblk(gl, blkno); + error = gfs_dreread(gl->gl_sbd, *bhp, flags); + if (error) + brelse(*bhp); + + return error; +} + +/** + * gfs_prep_new_buffer - Mark a new buffer we just gfs_dgetblk()ed uptodate + * @bh: the buffer + * + */ + +void +gfs_prep_new_buffer(struct buffer_head *bh) +{ + wait_on_buffer(bh); + clear_buffer_dirty(bh); + set_buffer_uptodate(bh); +} + +/** + * gfs_dreread - Reread a block from disk + * @sdp: the filesystem + * @bh: The block to read + * @flags: Flags that control the read + * + * Returns: errno + */ + +int +gfs_dreread(struct gfs_sbd *sdp, struct buffer_head *bh, int flags) +{ + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + return -EIO; + + /* Fill in meta-header if we have a cached copy, else read from disk */ + if (flags & DIO_NEW) { + if (gfs_mhc_fish(sdp, bh)) + return 0; + clear_buffer_uptodate(bh); + } + + if (flags & DIO_FORCE) + clear_buffer_uptodate(bh); + + if ((flags & DIO_START) && !buffer_uptodate(bh)) + ll_rw_block(READ, 1, &bh); + + if (flags & DIO_WAIT) { + wait_on_buffer(bh); + + if (!buffer_uptodate(bh)) { + gfs_io_error_bh(sdp, bh); + return -EIO; + } + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + return -EIO; + } + + return 0; +} + +/** + * gfs_dwrite - Write a buffer to disk (and/or wait for write to complete) + * @sdp: the filesystem + * @bh: The buffer to write + * @flags: DIO_XXX The type of write/wait operation to do + * + * Returns: errno + */ + +int +gfs_dwrite(struct gfs_sbd *sdp, struct buffer_head *bh, int flags) +{ + if (gfs_assert_warn(sdp, !test_bit(SDF_ROFS, &sdp->sd_flags))) + return -EIO; + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + return -EIO; + + if (flags & DIO_CLEAN) { + lock_buffer(bh); + clear_buffer_dirty(bh); + unlock_buffer(bh); + } + + if (flags & DIO_DIRTY) { + if (gfs_assert_warn(sdp, buffer_uptodate(bh))) + return -EIO; + mark_buffer_dirty(bh); + } + + if ((flags & DIO_START) && buffer_dirty(bh)) { + wait_on_buffer(bh); + ll_rw_block(WRITE, 1, &bh); + } + + if (flags & DIO_WAIT) { + wait_on_buffer(bh); + + if (!buffer_uptodate(bh) || buffer_dirty(bh)) { + gfs_io_error_bh(sdp, bh); + return -EIO; + } + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + return -EIO; + } + + return 0; +} + +/** + * gfs_attach_bufdata - attach a struct gfs_bufdata structure to a buffer + * @bh: The buffer to be attached to + * @gl: the glock the buffer belongs to + * + */ + +void +gfs_attach_bufdata(struct buffer_head *bh, struct gfs_glock *gl) +{ + struct gfs_bufdata *bd; + + lock_page(bh->b_page); + + /* If there's one attached already, we're done */ + if (get_v2bd(bh)) { + unlock_page(bh->b_page); + return; + } + + RETRY_MALLOC(bd = kmem_cache_alloc(gfs_bufdata_cachep, GFP_KERNEL), bd); + atomic_inc(&gl->gl_sbd->sd_bufdata_count); + + memset(bd, 0, sizeof(struct gfs_bufdata)); + + bd->bd_bh = bh; + bd->bd_gl = gl; + + INIT_LE(&bd->bd_new_le, &gfs_buf_lops); + INIT_LE(&bd->bd_incore_le, &gfs_buf_lops); + + init_MUTEX(&bd->bd_lock); + + INIT_LIST_HEAD(&bd->bd_ail_tr_list); + + set_v2bd(bh, bd); + + unlock_page(bh->b_page); +} + +/** + * gfs_is_pinned - Figure out if a buffer is pinned or not + * @sdp: the filesystem the buffer belongs to + * @bh: The buffer to be pinned + * + * Returns: TRUE if the buffer is pinned, FALSE otherwise + */ + +int +gfs_is_pinned(struct gfs_sbd *sdp, struct buffer_head *bh) +{ + struct gfs_bufdata *bd = get_v2bd(bh); + int ret = FALSE; + + if (bd) { + gfs_lock_buffer(bh); + if (bd->bd_pinned) + ret = TRUE; + gfs_unlock_buffer(bh); + } + + return ret; +} + +/** + * gfs_dpin - Pin a metadata buffer in memory + * @sdp: the filesystem the buffer belongs to + * @bh: The buffer to be pinned + * + * "Pinning" means keeping buffer from being written to its in-place location. + * A buffer should be pinned from the time it is added to a new transaction, + * until after it has been written to the log. + * If an earlier change to this buffer is still pinned, waiting to be written + * to on-disk log, we need to keep a "frozen" copy of the old data while this + * transaction is modifying the real data. We keep the frozen copy until + * this transaction's incore_commit(), i.e. until the transaction has + * finished modifying the real data, at which point we can use the real + * buffer for logging, even if the frozen copy didn't get written to the log. + * + */ + +void +gfs_dpin(struct gfs_sbd *sdp, struct buffer_head *bh) +{ + struct gfs_bufdata *bd = get_v2bd(bh); + char *data; + + gfs_assert_withdraw(sdp, !test_bit(SDF_ROFS, &sdp->sd_flags)); + + gfs_lock_buffer(bh); + + gfs_assert_warn(sdp, !bd->bd_frozen); + + if (!bd->bd_pinned++) { + wait_on_buffer(bh); + + /* If this buffer is in the AIL and it has already been written + to in-place disk block, remove it from the AIL. */ + + spin_lock(&sdp->sd_ail_lock); + if (!list_empty(&bd->bd_ail_tr_list) && !buffer_busy(bh)) { + list_del_init(&bd->bd_ail_tr_list); + list_del(&bd->bd_ail_gl_list); + brelse(bh); + } + spin_unlock(&sdp->sd_ail_lock); + + clear_buffer_dirty(bh); + wait_on_buffer(bh); + + if (!buffer_uptodate(bh)) + gfs_io_error_bh(sdp, bh); + } else { + gfs_unlock_buffer(bh); + + gfs_assert_withdraw(sdp, buffer_uptodate(bh)); + + data = gmalloc(sdp->sd_sb.sb_bsize); + + gfs_lock_buffer(bh); + + /* Create frozen copy, if needed. */ + if (bd->bd_pinned > 1) { + memcpy(data, bh->b_data, sdp->sd_sb.sb_bsize); + bd->bd_frozen = data; + } else + kfree(data); + } + + gfs_unlock_buffer(bh); + + get_bh(bh); +} + +/** + * gfs_dunpin - Unpin a buffer + * @sdp: the filesystem the buffer belongs to + * @bh: The buffer to unpin + * @tr: The transaction in the AIL that contains this buffer + * If NULL, don't attach buffer to any AIL list + * (i.e. when dropping a pin reference when merging a new transaction + * with an already existing incore transaction) + * + * Called for (meta) buffers, after they've been logged to on-disk journal. + * Make a (meta) buffer writeable to in-place location on-disk, if recursive + * pin count is 1 (i.e. no other, later transaction is modifying this buffer). + * Add buffer to AIL lists of 1) the latest transaction that's modified and + * logged (on-disk) the buffer, and of 2) the glock that protects the buffer. + * A single buffer might have been modified by more than one transaction + * since the buffer's previous write to disk (in-place location). We keep + * the buffer on only one transaction's AIL list, i.e. that of the latest + * transaction that's completed logging this buffer (no need to write it to + * in-place block multiple times for multiple transactions, only once with + * the most up-to-date data). + * A single buffer will be protected by one and only one glock. If buffer is + * already on a (previous) transaction's AIL, we know that we're already + * on buffer's glock's AIL. + * + */ + +void +gfs_dunpin(struct gfs_sbd *sdp, struct buffer_head *bh, struct gfs_trans *tr) +{ + struct gfs_bufdata *bd = get_v2bd(bh); + + gfs_assert_withdraw(sdp, buffer_uptodate(bh)); + + gfs_lock_buffer(bh); + + if (gfs_assert_warn(sdp, bd->bd_pinned)) { + gfs_unlock_buffer(bh); + return; + } + + /* No other (later) transaction is modifying buffer; ready to write */ + if (bd->bd_pinned == 1) + mark_buffer_dirty(bh); + + bd->bd_pinned--; + + gfs_unlock_buffer(bh); + + if (tr) { + spin_lock(&sdp->sd_ail_lock); + + if (list_empty(&bd->bd_ail_tr_list)) { + /* Buffer not attached to any earlier transaction. Add + it to glock's AIL, and this trans' AIL (below). */ + list_add(&bd->bd_ail_gl_list, &bd->bd_gl->gl_ail_bufs); + } else { + /* Was part of earlier transaction. + Move from that trans' AIL to this newer one's AIL. + Buf is already on glock's AIL. */ + list_del_init(&bd->bd_ail_tr_list); + brelse(bh); + } + list_add(&bd->bd_ail_tr_list, &tr->tr_ail_bufs); + + spin_unlock(&sdp->sd_ail_lock); + } else + brelse(bh); +} + +/** + * logbh_end_io - Called by OS at the end of a logbh ("fake" bh) write to log + * @bh: the buffer + * @uptodate: whether or not the write succeeded + * + * Interrupt context, no ENTER/RETURN + * + */ + +static void +logbh_end_io(struct buffer_head *bh, int uptodate) +{ + if (uptodate) + set_buffer_uptodate(bh); + else + clear_buffer_uptodate(bh); + unlock_buffer(bh); +} + +/** + * gfs_logbh_init - Initialize a fake buffer head + * @sdp: the filesystem + * @bh: the buffer to initialize + * @blkno: the block address of the buffer + * @data: the data to be written + * + */ + +void +gfs_logbh_init(struct gfs_sbd *sdp, struct buffer_head *bh, + uint64_t blkno, char *data) +{ + memset(bh, 0, sizeof(struct buffer_head)); + bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock); + atomic_set(&bh->b_count, 1); + set_bh_page(bh, virt_to_page(data), ((unsigned long)data) & (PAGE_SIZE - 1)); + bh->b_blocknr = blkno; + bh->b_size = sdp->sd_sb.sb_bsize; + bh->b_bdev = sdp->sd_vfs->s_bdev; + init_buffer(bh, logbh_end_io, NULL); + INIT_LIST_HEAD(&bh->b_assoc_buffers); +} + +/** + * gfs_logbh_uninit - Clean up a fake buffer head + * @sdp: the filesystem + * @bh: the buffer to clean + * + */ + +void +gfs_logbh_uninit(struct gfs_sbd *sdp, struct buffer_head *bh) +{ + gfs_assert_warn(sdp, test_bit(SDF_SHUTDOWN, &sdp->sd_flags) || + !buffer_busy(bh)); + gfs_assert_warn(sdp, atomic_read(&bh->b_count) == 1); +} + +/** + * gfs_logbh_start - Start writing a fake buffer head + * @sdp: the filesystem + * @bh: the buffer to write + * + * This starts a block write to our journal. + */ + +void +gfs_logbh_start(struct gfs_sbd *sdp, struct buffer_head *bh) +{ + submit_bh(WRITE, bh); +} + +/** + * gfs_logbh_wait - Wait for the write of a fake buffer head to complete + * @sdp: the filesystem + * @bh: the buffer to write + * + * This waits for a block write to our journal to complete. + * + * Returns: errno + */ + +int +gfs_logbh_wait(struct gfs_sbd *sdp, struct buffer_head *bh) +{ + wait_on_buffer(bh); + + if (!buffer_uptodate(bh) || buffer_dirty(bh)) { + gfs_io_error_bh(sdp, bh); + return -EIO; + } + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + return -EIO; + + return 0; +} + +/** + * gfs_replay_buf - write a log buffer to its inplace location + * @gl: the journal's glock + * @bh: the buffer + * + * Returns: errno + */ + +int +gfs_replay_buf(struct gfs_glock *gl, struct buffer_head *bh) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct gfs_bufdata *bd; + + bd = get_v2bd(bh); + if (!bd) { + gfs_attach_bufdata(bh, gl); + bd = get_v2bd(bh); + } + + mark_buffer_dirty(bh); + + if (list_empty(&bd->bd_ail_tr_list)) { + get_bh(bh); + list_add(&bd->bd_ail_tr_list, &sdp->sd_recovery_bufs); + } + + return 0; +} + +/** + * gfs_replay_check - Check up on journal replay + * @sdp: the filesystem + * + */ + +void +gfs_replay_check(struct gfs_sbd *sdp) +{ + struct buffer_head *bh; + struct gfs_bufdata *bd; + + while (!list_empty(&sdp->sd_recovery_bufs)) { + bd = list_entry(sdp->sd_recovery_bufs.prev, + struct gfs_bufdata, bd_ail_tr_list); + bh = bd->bd_bh; + + if (buffer_busy(bh)) { + list_move(&bd->bd_ail_tr_list, + &sdp->sd_recovery_bufs); + break; + } else { + list_del_init(&bd->bd_ail_tr_list); + if (!buffer_uptodate(bh)) + gfs_io_error_bh(sdp, bh); + brelse(bh); + } + } +} + +/** + * gfs_replay_wait - Wait for all replayed buffers to hit the disk + * @sdp: the filesystem + * + */ + +void +gfs_replay_wait(struct gfs_sbd *sdp) +{ + struct list_head *head, *tmp, *prev; + struct buffer_head *bh; + struct gfs_bufdata *bd; + + for (head = &sdp->sd_recovery_bufs, tmp = head->prev, prev = tmp->prev; + tmp != head; + tmp = prev, prev = tmp->prev) { + bd = list_entry(tmp, struct gfs_bufdata, bd_ail_tr_list); + bh = bd->bd_bh; + + if (!buffer_busy(bh)) { + list_del_init(&bd->bd_ail_tr_list); + if (!buffer_uptodate(bh)) + gfs_io_error_bh(sdp, bh); + brelse(bh); + continue; + } + + if (buffer_dirty(bh)) { + wait_on_buffer(bh); + ll_rw_block(WRITE, 1, &bh); + } + } + + while (!list_empty(head)) { + bd = list_entry(head->prev, struct gfs_bufdata, bd_ail_tr_list); + bh = bd->bd_bh; + + wait_on_buffer(bh); + + gfs_assert_withdraw(sdp, !buffer_busy(bh)); + + list_del_init(&bd->bd_ail_tr_list); + if (!buffer_uptodate(bh)) + gfs_io_error_bh(sdp, bh); + brelse(bh); + } +} + +/** + * gfs_wipe_buffers - make inode's buffers so they aren't dirty/AILed anymore + * @ip: the inode who owns the buffers + * @rgd: the resource group + * @bstart: the first buffer in the run + * @blen: the number of buffers in the run + * + * Called when de-allocating a contiguous run of meta blocks within an rgrp. + * Make sure all buffers for de-alloc'd blocks are removed from the AIL, if + * they can be. Dirty or pinned blocks are left alone. Add relevant + * meta-headers to meta-header cache, so we don't need to read disk + * if we re-allocate blocks. + */ + +void +gfs_wipe_buffers(struct gfs_inode *ip, struct gfs_rgrpd *rgd, + uint64_t bstart, uint32_t blen) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct inode *aspace = ip->i_gl->gl_aspace; + struct buffer_head *bh; + struct gfs_bufdata *bd; + int busy; + int add = FALSE; + + while (blen) { + bh = getbuf(sdp, aspace, bstart, NO_CREATE); + if (bh) { + + bd = get_v2bd(bh); + + if (buffer_uptodate(bh)) { + if (bd) { + gfs_lock_buffer(bh); + gfs_mhc_add(rgd, &bh, 1); + busy = bd->bd_pinned || buffer_busy(bh); + gfs_unlock_buffer(bh); + + if (busy) + add = TRUE; + else { + spin_lock(&sdp->sd_ail_lock); + if (!list_empty(&bd->bd_ail_tr_list)) { + list_del_init(&bd->bd_ail_tr_list); + list_del(&bd->bd_ail_gl_list); + brelse(bh); + } + spin_unlock(&sdp->sd_ail_lock); + } + } else { + gfs_assert_withdraw(sdp, !buffer_dirty(bh)); + wait_on_buffer(bh); + gfs_assert_withdraw(sdp, !buffer_busy(bh)); + gfs_mhc_add(rgd, &bh, 1); + } + } else { + gfs_assert_withdraw(sdp, !bd || !bd->bd_pinned); + gfs_assert_withdraw(sdp, !buffer_dirty(bh)); + wait_on_buffer(bh); + gfs_assert_withdraw(sdp, !buffer_busy(bh)); + } + + brelse(bh); + } + + bstart++; + blen--; + } + + if (add) + gfs_depend_add(rgd, ip->i_num.no_formal_ino); +} + +/** + * gfs_sync_meta - sync all the buffers in a filesystem + * @sdp: the filesystem + * + * Flush metadata blocks to on-disk journal, then + * Flush metadata blocks (now in AIL) to on-disk in-place locations + * Periodically keep checking until done (AIL empty) + */ + +void +gfs_sync_meta(struct gfs_sbd *sdp) +{ + gfs_log_flush(sdp); + for (;;) { + gfs_ail_start(sdp, DIO_ALL); + if (gfs_ail_empty(sdp)) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 10); + } +} + +/** + * gfs_flush_meta_cache - get rid of any references on buffers for this inode + * @ip: The GFS inode + * + * This releases buffers that are in the most-recently-used array of + * blocks used for indirect block addressing for this inode. + * Don't confuse this with the meta-HEADER cache (mhc)! + */ + +void +gfs_flush_meta_cache(struct gfs_inode *ip) +{ + struct buffer_head **bh_slot; + unsigned int x; + + spin_lock(&ip->i_spin); + + for (x = 0; x < GFS_MAX_META_HEIGHT; x++) { + bh_slot = &ip->i_cache[x]; + if (*bh_slot) { + brelse(*bh_slot); + *bh_slot = NULL; + } + } + + spin_unlock(&ip->i_spin); +} + +/** + * gfs_get_meta_buffer - Get a metadata buffer + * @ip: The GFS inode + * @height: The level of this buf in the metadata (indir addr) tree (if any) + * @num: The block number (device relative) of the buffer + * @new: Non-zero if we may create a new buffer + * @bhp: the buffer is returned here + * + * Returns: errno + */ + +int +gfs_get_meta_buffer(struct gfs_inode *ip, int height, uint64_t num, int new, + struct buffer_head **bhp) +{ + struct buffer_head *bh, **bh_slot = &ip->i_cache[height]; + int flags = ((new) ? DIO_NEW : 0) | DIO_START | DIO_WAIT; + int error; + + /* Try to use the gfs_inode's MRU metadata tree cache */ + spin_lock(&ip->i_spin); + bh = *bh_slot; + if (bh) { + if (bh->b_blocknr == num) + get_bh(bh); + else + bh = NULL; + } + spin_unlock(&ip->i_spin); + + if (bh) { + error = gfs_dreread(ip->i_sbd, bh, flags); + if (error) { + brelse(bh); + return error; + } + } else { + error = gfs_dread(ip->i_gl, num, flags, &bh); + if (error) + return error; + + spin_lock(&ip->i_spin); + if (*bh_slot != bh) { + if (*bh_slot) + brelse(*bh_slot); + *bh_slot = bh; + get_bh(bh); + } + spin_unlock(&ip->i_spin); + } + + if (new) { + if (gfs_assert_warn(ip->i_sbd, height)) { + brelse(bh); + return -EIO; + } + gfs_trans_add_bh(ip->i_gl, bh); + gfs_metatype_set(bh, GFS_METATYPE_IN, GFS_FORMAT_IN); + gfs_buffer_clear_tail(bh, sizeof(struct gfs_meta_header)); + } else if (gfs_metatype_check(ip->i_sbd, bh, + (height) ? GFS_METATYPE_IN : GFS_METATYPE_DI)) { + brelse(bh); + return -EIO; + } + + *bhp = bh; + + return 0; +} + +/** + * gfs_get_data_buffer - Get a data buffer + * @ip: The GFS inode + * @num: The block number (device relative) of the data block + * @new: Non-zero if this is a new allocation + * @bhp: the buffer is returned here + * + * Returns: errno + */ + +int +gfs_get_data_buffer(struct gfs_inode *ip, uint64_t block, int new, + struct buffer_head **bhp) +{ + struct buffer_head *bh; + int error = 0; + + if (block == ip->i_num.no_addr) { + if (gfs_assert_warn(ip->i_sbd, !new)) + return -EIO; + error = gfs_dread(ip->i_gl, block, DIO_START | DIO_WAIT, &bh); + if (error) + return error; + if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_DI)) { + brelse(bh); + return -EIO; + } + } else if (gfs_is_jdata(ip)) { + if (new) { + error = gfs_dread(ip->i_gl, block, + DIO_NEW | DIO_START | DIO_WAIT, &bh); + if (error) + return error; + gfs_trans_add_bh(ip->i_gl, bh); + gfs_metatype_set(bh, GFS_METATYPE_JD, GFS_FORMAT_JD); + gfs_buffer_clear_tail(bh, sizeof(struct gfs_meta_header)); + } else { + error = gfs_dread(ip->i_gl, block, + DIO_START | DIO_WAIT, &bh); + if (error) + return error; + if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_JD)) { + brelse(bh); + return -EIO; + } + } + } else { + if (new) { + bh = gfs_dgetblk(ip->i_gl, block); + gfs_prep_new_buffer(bh); + } else { + error = gfs_dread(ip->i_gl, block, + DIO_START | DIO_WAIT, &bh); + if (error) + return error; + } + } + + *bhp = bh; + + return 0; +} + +/** + * gfs_start_ra - start readahead on an extent of a file + * @gl: the glock the blocks belong to + * @dblock: the starting disk block + * @extlen: the number of blocks in the extent + * + */ + +void +gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen) +{ + struct gfs_sbd *sdp = gl->gl_sbd; + struct inode *aspace = gl->gl_aspace; + struct buffer_head *first_bh, *bh; + uint32_t max_ra = gfs_tune_get(sdp, gt_max_readahead) >> sdp->sd_sb.sb_bsize_shift; + int error; + + if (!extlen) + return; + if (!max_ra) + return; + if (extlen > max_ra) + extlen = max_ra; + + first_bh = getbuf(sdp, aspace, dblock, CREATE); + + if (buffer_uptodate(first_bh)) + goto out; + if (!buffer_locked(first_bh)) { + error = gfs_dreread(sdp, first_bh, DIO_START); + if (error) + goto out; + } + + dblock++; + extlen--; + + while (extlen) { + bh = getbuf(sdp, aspace, dblock, CREATE); + + if (!buffer_uptodate(bh) && !buffer_locked(bh)) { + error = gfs_dreread(sdp, bh, DIO_START); + brelse(bh); + if (error) + goto out; + } else + brelse(bh); + + dblock++; + extlen--; + + if (buffer_uptodate(first_bh)) + break; + } + + out: + brelse(first_bh); +} --- linux-2.6.27.orig/ubuntu/gfs/quota.h +++ linux-2.6.27/ubuntu/gfs/quota.h @@ -0,0 +1,28 @@ +#ifndef __QUOTA_DOT_H__ +#define __QUOTA_DOT_H__ + +#define NO_QUOTA_CHANGE ((uint32_t)-1) + +int gfs_quota_get(struct gfs_sbd *sdp, int user, uint32_t id, int create, + struct gfs_quota_data **qdp); +void gfs_quota_hold(struct gfs_sbd *sdp, struct gfs_quota_data *qd); +void gfs_quota_put(struct gfs_sbd *sdp, struct gfs_quota_data *qd); + +int gfs_quota_merge(struct gfs_sbd *sdp, struct gfs_quota_tag *tag); +void gfs_quota_scan(struct gfs_sbd *sdp); +void gfs_quota_cleanup(struct gfs_sbd *sdp); + +int gfs_quota_hold_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid); +void gfs_quota_unhold_m(struct gfs_inode *ip); + +int gfs_quota_lock_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid); +void gfs_quota_unlock_m(struct gfs_inode *ip); + +int gfs_quota_check(struct gfs_inode *ip, uint32_t uid, uint32_t gid); + +int gfs_quota_sync(struct gfs_sbd *sdp); +int gfs_quota_refresh(struct gfs_sbd *sdp, int user, uint32_t id); +int gfs_quota_read(struct gfs_sbd *sdp, int user, uint32_t id, + struct gfs_quota *q); + +#endif /* __QUOTA_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/dio.h +++ linux-2.6.27/ubuntu/gfs/dio.h @@ -0,0 +1,157 @@ +#ifndef __DIO_DOT_H__ +#define __DIO_DOT_H__ + +void gfs_ail_start_trans(struct gfs_sbd *sdp, struct gfs_trans *tr); +int gfs_ail_empty_trans(struct gfs_sbd *sdp, struct gfs_trans *tr); + +/* Asynchronous I/O Routines */ + +struct buffer_head *gfs_dgetblk(struct gfs_glock *gl, uint64_t blkno); +int gfs_dread(struct gfs_glock *gl, uint64_t blkno, + int flags, struct buffer_head **bhp); + +void gfs_prep_new_buffer(struct buffer_head *bh); +int gfs_dreread(struct gfs_sbd *sdp, struct buffer_head *bh, int flags); +int gfs_dwrite(struct gfs_sbd *sdp, struct buffer_head *bh, int flags); + +void gfs_attach_bufdata(struct buffer_head *bh, struct gfs_glock *gl); +int gfs_is_pinned(struct gfs_sbd *sdp, struct buffer_head *bh); +void gfs_dpin(struct gfs_sbd *sdp, struct buffer_head *bh); +void gfs_dunpin(struct gfs_sbd *sdp, struct buffer_head *bh, + struct gfs_trans *tr); + +static __inline__ +void gfs_lock_buffer(struct buffer_head *bh) +{ + struct gfs_bufdata *bd = get_v2bd(bh); + down(&bd->bd_lock); +} +static __inline__ +int gfs_trylock_buffer(struct buffer_head *bh) +{ + struct gfs_bufdata *bd = get_v2bd(bh); + return down_trylock(&bd->bd_lock); +} +static __inline__ +void gfs_unlock_buffer(struct buffer_head *bh) +{ + struct gfs_bufdata *bd = get_v2bd(bh); + up(&bd->bd_lock); +} + +void gfs_logbh_init(struct gfs_sbd *sdp, struct buffer_head *bh, uint64_t blkno, + char *data); +void gfs_logbh_uninit(struct gfs_sbd *sdp, struct buffer_head *bh); +void gfs_logbh_start(struct gfs_sbd *sdp, struct buffer_head *bh); +int gfs_logbh_wait(struct gfs_sbd *sdp, struct buffer_head *bh); + +int gfs_replay_buf(struct gfs_glock *gl, struct buffer_head *bh); +void gfs_replay_check(struct gfs_sbd *sdp); +void gfs_replay_wait(struct gfs_sbd *sdp); + +void gfs_wipe_buffers(struct gfs_inode *ip, struct gfs_rgrpd *rgd, + uint64_t bstart, uint32_t blen); + +void gfs_sync_meta(struct gfs_sbd *sdp); + +/* Buffer Caching routines */ + +int gfs_get_meta_buffer(struct gfs_inode *ip, int height, uint64_t num, int new, + struct buffer_head **bhp); +int gfs_get_data_buffer(struct gfs_inode *ip, uint64_t block, int new, + struct buffer_head **bhp); +void gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen); + +static __inline__ int +gfs_get_inode_buffer(struct gfs_inode *ip, struct buffer_head **bhp) +{ + return gfs_get_meta_buffer(ip, 0, ip->i_num.no_addr, FALSE, bhp); +} + +struct inode *gfs_aspace_get(struct gfs_sbd *sdp); +void gfs_aspace_put(struct inode *aspace); + +void gfs_inval_buf(struct gfs_glock *gl); +void gfs_sync_buf(struct gfs_glock *gl, int flags); + +void gfs_flush_meta_cache(struct gfs_inode *ip); + +/* Buffer Content Functions */ + +/** + * gfs_buffer_clear - Zeros out a buffer + * @ip: The GFS inode + * @bh: The buffer to zero + * + */ + +static __inline__ void +gfs_buffer_clear(struct buffer_head *bh) +{ + memset(bh->b_data, 0, bh->b_size); +} + +/** + * gfs_buffer_clear_tail - Clear buffer beyond the dinode + * @bh: The buffer containing the on-disk inode + * @head: the size of the head of the buffer + * + * Clears the remaining part of an on-disk inode that is not a dinode. + * i.e. The data part of a stuffed inode, or the top level of metadata + * of a non-stuffed inode. + */ + +static __inline__ void +gfs_buffer_clear_tail(struct buffer_head *bh, int head) +{ + memset(bh->b_data + head, 0, bh->b_size - head); +} + +/** + * gfs_buffer_clear_ends - Zero out any bits of a buffer which are not being written + * @bh: The buffer + * @offset: Offset in buffer where write starts + * @amount: Amount of data being written + * @journaled: TRUE if this is a journaled buffer + * + */ + +static __inline__ void +gfs_buffer_clear_ends(struct buffer_head *bh, int offset, int amount, + int journaled) +{ + int z_off1 = (journaled) ? sizeof(struct gfs_meta_header) : 0; + int z_len1 = offset - z_off1; + int z_off2 = offset + amount; + int z_len2 = (bh)->b_size - z_off2; + + if (z_len1) + memset(bh->b_data + z_off1, 0, z_len1); + + if (z_len2) + memset(bh->b_data + z_off2, 0, z_len2); +} + +/** + * gfs_buffer_copy_tail - copies the tail of one buffer to another + * @to_bh: the buffer to copy to + * @to_head: the size of the head of to_bh + * @from_bh: the buffer to copy from + * @from_head: the size of the head of from_bh + * + * from_head is guaranteed to bigger than to_head + */ + +static __inline__ void +gfs_buffer_copy_tail(struct buffer_head *to_bh, int to_head, + struct buffer_head *from_bh, int from_head) +{ + memcpy(to_bh->b_data + to_head, + from_bh->b_data + from_head, + from_bh->b_size - from_head); + memset(to_bh->b_data + to_bh->b_size + to_head - from_head, + 0, + from_head - to_head); +} + +#endif /* __DIO_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/eaops.h +++ linux-2.6.27/ubuntu/gfs/eaops.h @@ -0,0 +1,21 @@ +#ifndef __EAOPS_DOT_H__ +#define __EAOPS_DOT_H__ + +struct gfs_ea_request; + +struct gfs_eattr_operations { + int (*eo_get) (struct gfs_inode *ip, struct gfs_ea_request *er); + int (*eo_set) (struct gfs_inode *ip, struct gfs_ea_request *er); + int (*eo_remove) (struct gfs_inode *ip, struct gfs_ea_request *er); + char *eo_name; +}; + +unsigned int gfs_ea_name2type(const char *name, char **truncated_name); + +extern struct gfs_eattr_operations gfs_user_eaops; +extern struct gfs_eattr_operations gfs_system_eaops; + +extern struct gfs_eattr_operations *gfs_ea_ops[]; + +#endif /* __EAOPS_DOT_H__ */ + --- linux-2.6.27.orig/ubuntu/gfs/proc.c +++ linux-2.6.27/ubuntu/gfs/proc.c @@ -0,0 +1,491 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "glock.h" +#include "lm.h" +#include "proc.h" +#include "super.h" + +struct list_head gfs_fs_list; +struct semaphore gfs_fs_lock; +char *gfs_proc_margs; +spinlock_t gfs_proc_margs_lock; +spinlock_t gfs_req_lock; + +/** + * gfs_proc_fs_add - Add a FS to the list of mounted FSs + * @sdp: + * + */ + +void +gfs_proc_fs_add(struct gfs_sbd *sdp) +{ + down(&gfs_fs_lock); + list_add(&sdp->sd_list, &gfs_fs_list); + up(&gfs_fs_lock); +} + +/** + * gfs_proc_fs_del - Remove a FS from the list of mounted FSs + * @sdp: + * + */ + +void +gfs_proc_fs_del(struct gfs_sbd *sdp) +{ + down(&gfs_fs_lock); + list_del(&sdp->sd_list); + up(&gfs_fs_lock); +} + +/** + * do_list - Copy the list of mountes FSs to userspace + * @user_buf: + * @size: + * + * @Returns: -errno, or the number of bytes copied to userspace + */ + +static ssize_t +do_list(char *user_buf, size_t size) +{ + struct list_head *tmp; + struct gfs_sbd *sdp = NULL; + unsigned int x; + char num[21]; + char device_id[32]; + char *buf; + int error = 0; + + down(&gfs_fs_lock); + + x = 0; + for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) { + sdp = list_entry(tmp, struct gfs_sbd, sd_list); + sprintf(device_id, "%u:%u", MAJOR(sdp->sd_vfs->s_dev), + MINOR(sdp->sd_vfs->s_dev)); + x += sprintf(num, "%lu", (unsigned long)sdp) + + strlen(device_id) + + strlen(sdp->sd_fsname) + 3; + } + + if (!x) + goto out; + + error = -EFBIG; + if (x > size) + goto out; + + error = -ENOMEM; + buf = kmalloc(x + 1, GFP_KERNEL); + if (!buf) + goto out; + + x = 0; + for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) { + sdp = list_entry(tmp, struct gfs_sbd, sd_list); + sprintf(device_id, "%u:%u", MAJOR(sdp->sd_vfs->s_dev), + MINOR(sdp->sd_vfs->s_dev)); + x += sprintf(buf + x, "%lu %s %s\n", + (unsigned long)sdp, device_id, sdp->sd_fsname); + } + + if (copy_to_user(user_buf, buf, x)) + error = -EFAULT; + else + error = x; + + kfree(buf); + + out: + up(&gfs_fs_lock); + + return error; +} + +/** + * find_argument - + * @p: + * + * Returns: + */ + +static char * +find_argument(char *p) +{ + char *p2; + + while (*p == ' ' || *p == '\n') + p++; + if (!*p) + return NULL; + for (p2 = p; *p2; p2++) /* do nothing */; + p2--; + while (*p2 == ' ' || *p2 == '\n') + *p2-- = 0; + + return p; +} + +/** + * do_freeze - freeze a filesystem + * @p: the freeze command + * + * Returns: errno + */ + +static int +do_freeze(char *p) +{ + struct list_head *tmp; + struct gfs_sbd *sdp; + char num[21]; + int error = 0; + + p = find_argument(p + 6); + if (!p) + return -ENOENT; + + down(&gfs_fs_lock); + + for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) { + sdp = list_entry(tmp, struct gfs_sbd, sd_list); + sprintf(num, "%lu", (unsigned long)sdp); + if (strcmp(num, p) == 0) + break; + } + + if (tmp == &gfs_fs_list) + error = -ENOENT; + else + error = gfs_freeze_fs(sdp); + + up(&gfs_fs_lock); + + return error; +} + +/** + * do_unfreeze - unfreeze a filesystem + * @p: the unfreeze command + * + * Returns: errno + */ + +static int +do_unfreeze(char *p) +{ + struct list_head *tmp; + struct gfs_sbd *sdp; + char num[21]; + int error = 0; + + p = find_argument(p + 8); + if (!p) + return -ENOENT; + + down(&gfs_fs_lock); + + for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) { + sdp = list_entry(tmp, struct gfs_sbd, sd_list); + sprintf(num, "%lu", (unsigned long)sdp); + if (strcmp(num, p) == 0) + break; + } + + if (tmp == &gfs_fs_list) + error = -ENOENT; + else + gfs_unfreeze_fs(sdp); + + up(&gfs_fs_lock); + + return error; +} + +/** + * do_margs - Pass in mount arguments + * @p: the margs command + * + * Returns: errno + */ + +static int +do_margs(char *p) +{ + char *new_buf, *old_buf; + + p = find_argument(p + 5); + if (!p) + return -ENOENT; + + new_buf = kmalloc(strlen(p) + 1, GFP_KERNEL); + if (!new_buf) + return -ENOMEM; + strcpy(new_buf, p); + + spin_lock(&gfs_proc_margs_lock); + old_buf = gfs_proc_margs; + gfs_proc_margs = new_buf; + spin_unlock(&gfs_proc_margs_lock); + + if (old_buf) + kfree(old_buf); + + return 0; +} + +/** + * do_withdraw - withdraw a from the cluster for one filesystem + * @p: the cookie of the filesystem + * + * Returns: errno + */ + +static int +do_withdraw(char *p) +{ + struct list_head *tmp; + struct gfs_sbd *sdp; + char num[21]; + int error = 0; + + p = find_argument(p + 8); + if (!p) + return -ENOENT; + + down(&gfs_fs_lock); + + for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) { + sdp = list_entry(tmp, struct gfs_sbd, sd_list); + sprintf(num, "%lu", (unsigned long)sdp); + if (strcmp(num, p) == 0) + break; + } + + if (tmp == &gfs_fs_list) + error = -ENOENT; + else + gfs_lm_withdraw(sdp, + "GFS: fsid=%s: withdrawing from cluster at user's request\n", + sdp->sd_fsname); + + up(&gfs_fs_lock); + + return error; +} + +/** + * do_lockdump - Copy out the lock hash table to userspace + * @p: the cookie of the filesystem + * @buf: + * @size: + * + * Returns: errno + */ + +static int +do_lockdump(char *p, char *buf, size_t size) +{ + struct list_head *tmp; + struct gfs_sbd *sdp; + char num[21]; + struct gfs_user_buffer ub; + int error = 0; + + p = find_argument(p + 8); + if (!p) + return -ENOENT; + + down(&gfs_fs_lock); + + for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) { + sdp = list_entry(tmp, struct gfs_sbd, sd_list); + sprintf(num, "%lu", (unsigned long)sdp); + if (strcmp(num, p) == 0) + break; + } + + if (tmp == &gfs_fs_list) + error = -ENOENT; + else { + ub.ub_data = buf; + ub.ub_size = size; + ub.ub_count = 0; + + error = gfs_dump_lockstate(sdp, &ub); + if (!error) + error = ub.ub_count; + } + + up(&gfs_fs_lock); + + return error; +} + +/** + * gfs_proc_write - take a command from userspace + * @file: + * @buf: + * @size: + * @offset: + * + * Returns: -errno or the number of bytes taken + */ + +static ssize_t +gfs_proc_write(struct file *file, const char *buf, size_t size, loff_t *offset) +{ + char *p; + + spin_lock(&gfs_req_lock); + p = file->private_data; + file->private_data = NULL; + spin_unlock(&gfs_req_lock); + + if (p) + kfree(p); + + if (!size) + return -EINVAL; + + p = kmalloc(size + 1, GFP_KERNEL); + if (!p) + return -ENOMEM; + p[size] = 0; + + if (copy_from_user(p, buf, size)) { + kfree(p); + return -EFAULT; + } + + spin_lock(&gfs_req_lock); + file->private_data = p; + spin_unlock(&gfs_req_lock); + + return size; +} + +/** + * gfs_proc_read - return the results of a command + * @file: + * @buf: + * @size: + * @offset: + * + * Returns: -errno or the number of bytes returned + */ + +static ssize_t +gfs_proc_read(struct file *file, char *buf, size_t size, loff_t *offset) +{ + char *p; + int error; + + spin_lock(&gfs_req_lock); + p = file->private_data; + file->private_data = NULL; + spin_unlock(&gfs_req_lock); + + if (!p) + return -ENOENT; + + if (!size) { + kfree(p); + return -EINVAL; + } + + if (strncmp(p, "list", 4) == 0) + error = do_list(buf, size); + else if (strncmp(p, "freeze", 6) == 0) + error = do_freeze(p); + else if (strncmp(p, "unfreeze", 8) == 0) + error = do_unfreeze(p); + else if (strncmp(p, "margs", 5) == 0) + error = do_margs(p); + else if (strncmp(p, "withdraw", 8) == 0) + error = do_withdraw(p); + else if (strncmp(p, "lockdump", 8) == 0) + error = do_lockdump(p, buf, size); + else + error = -ENOSYS; + + kfree(p); + + return error; +} + +/** + * gfs_proc_close - free any mismatches writes + * @inode: + * @file: + * + * Returns: 0 + */ + +static int +gfs_proc_close(struct inode *inode, struct file *file) +{ + if (file->private_data) + kfree(file->private_data); + return 0; +} + +static struct file_operations gfs_proc_fops = +{ + .owner = THIS_MODULE, + .write = gfs_proc_write, + .read = gfs_proc_read, + .release = gfs_proc_close, +}; + +/** + * gfs_proc_init - initialize GFS' proc interface + * + */ + +int +gfs_proc_init(void) +{ + struct proc_dir_entry *pde; + + INIT_LIST_HEAD(&gfs_fs_list); + init_MUTEX(&gfs_fs_lock); + gfs_proc_margs = NULL; + spin_lock_init(&gfs_proc_margs_lock); + spin_lock_init(&gfs_req_lock); + + pde = create_proc_entry("fs/gfs", S_IFREG | 0600, NULL); + if (!pde) + return -ENOMEM; + + pde->owner = THIS_MODULE; + pde->proc_fops = &gfs_proc_fops; + + return 0; +} + +/** + * gfs_proc_uninit - uninitialize GFS' proc interface + * + */ + +void +gfs_proc_uninit(void) +{ + if (gfs_proc_margs) + kfree(gfs_proc_margs); + remove_proc_entry("fs/gfs", NULL); +} + --- linux-2.6.27.orig/ubuntu/gfs/acl.h +++ linux-2.6.27/ubuntu/gfs/acl.h @@ -0,0 +1,34 @@ +#ifndef __ACL_DOT_H__ +#define __ACL_DOT_H__ + +#define GFS_POSIX_ACL_ACCESS "posix_acl_access" +#define GFS_POSIX_ACL_ACCESS_LEN (16) +#define GFS_POSIX_ACL_DEFAULT "posix_acl_default" +#define GFS_POSIX_ACL_DEFAULT_LEN (17) + +#define GFS_ACL_IS_ACCESS(name, len) \ + ((len) == GFS_POSIX_ACL_ACCESS_LEN && \ + !memcmp(GFS_POSIX_ACL_ACCESS, (name), (len))) + +#define GFS_ACL_IS_DEFAULT(name, len) \ + ((len) == GFS_POSIX_ACL_DEFAULT_LEN && \ + !memcmp(GFS_POSIX_ACL_DEFAULT, (name), (len))) + +struct gfs_ea_request; + +int gfs_acl_validate_set(struct gfs_inode *ip, int access, + struct gfs_ea_request *er, + int *remove, mode_t *mode); +int gfs_acl_validate_remove(struct gfs_inode *ip, int access); +int gfs_acl_get(struct gfs_inode *ip, int access, struct posix_acl **acl); +int gfs_check_acl(struct inode *inode, int mask); +int gfs_acl_new_prep(struct gfs_inode *dip, + unsigned int type, mode_t *mode, + void **a_data, void **d_data, + unsigned int *size, + unsigned int *blocks); +int gfs_acl_new_init(struct gfs_inode *dip, struct gfs_inode *ip, + void *a_data, void *d_data, unsigned int size); +int gfs_acl_chmod(struct gfs_inode *ip, struct iattr *attr); + +#endif /* __ACL_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/trans.h +++ linux-2.6.27/ubuntu/gfs/trans.h @@ -0,0 +1,24 @@ +#ifndef __TRANS_DOT_H__ +#define __TRANS_DOT_H__ + +#define TRANS_IS_NEW (53) +#define TRANS_IS_INCORE (54) +void gfs_trans_print(struct gfs_sbd *sdp, struct gfs_trans *tr, + unsigned int where); + +int gfs_trans_begin_i(struct gfs_sbd *sdp, + unsigned int meta_blocks, unsigned int extra_blocks, + char *file, unsigned int line); +#define gfs_trans_begin(sdp, mb, eb) \ +gfs_trans_begin_i((sdp), (mb), (eb), __FILE__, __LINE__) + +void gfs_trans_end(struct gfs_sbd *sdp); + +void gfs_trans_add_gl(struct gfs_glock *gl); +void gfs_trans_add_bh(struct gfs_glock *gl, struct buffer_head *bh); +struct gfs_unlinked *gfs_trans_add_unlinked(struct gfs_sbd *sdp, unsigned int type, + struct gfs_inum *inum); +void gfs_trans_add_quota(struct gfs_sbd *sdp, int64_t change, uint32_t uid, + uint32_t gid); + +#endif /* __TRANS_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/lm_interface.h +++ linux-2.6.27/ubuntu/gfs/lm_interface.h @@ -0,0 +1,278 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#ifndef __LM_INTERFACE_DOT_H__ +#define __LM_INTERFACE_DOT_H__ + + +typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); + +/* + * lm_mount() flags + * + * LM_MFLAG_SPECTATOR + * GFS is asking to join the filesystem's lockspace, but it doesn't want to + * modify the filesystem. The lock module shouldn't assign a journal to the FS + * mount. It shouldn't send recovery callbacks to the FS mount. If the node + * dies or withdraws, all locks can be wiped immediately. + */ + +#define LM_MFLAG_SPECTATOR 0x00000001 + +/* + * lm_lockstruct flags + * + * LM_LSFLAG_LOCAL + * The lock_nolock module returns LM_LSFLAG_LOCAL to GFS, indicating that GFS + * can make single-node optimizations. + */ + +#define LM_LSFLAG_LOCAL 0x00000001 + +/* + * lm_lockname types + */ + +#define LM_TYPE_RESERVED 0x00 +#define LM_TYPE_NONDISK 0x01 +#define LM_TYPE_INODE 0x02 +#define LM_TYPE_RGRP 0x03 +#define LM_TYPE_META 0x04 +#define LM_TYPE_IOPEN 0x05 +#define LM_TYPE_FLOCK 0x06 +#define LM_TYPE_PLOCK 0x07 +#define LM_TYPE_QUOTA 0x08 +#define LM_TYPE_JOURNAL 0x09 + +/* + * lm_lock() states + * + * SHARED is compatible with SHARED, not with DEFERRED or EX. + * DEFERRED is compatible with DEFERRED, not with SHARED or EX. + */ + +#define LM_ST_UNLOCKED 0 +#define LM_ST_EXCLUSIVE 1 +#define LM_ST_DEFERRED 2 +#define LM_ST_SHARED 3 + +/* + * lm_lock() flags + * + * LM_FLAG_TRY + * Don't wait to acquire the lock if it can't be granted immediately. + * + * LM_FLAG_TRY_1CB + * Send one blocking callback if TRY is set and the lock is not granted. + * + * LM_FLAG_NOEXP + * GFS sets this flag on lock requests it makes while doing journal recovery. + * These special requests should not be blocked due to the recovery like + * ordinary locks would be. + * + * LM_FLAG_ANY + * A SHARED request may also be granted in DEFERRED, or a DEFERRED request may + * also be granted in SHARED. The preferred state is whichever is compatible + * with other granted locks, or the specified state if no other locks exist. + * + * LM_FLAG_PRIORITY + * Override fairness considerations. Suppose a lock is held in a shared state + * and there is a pending request for the deferred state. A shared lock + * request with the priority flag would be allowed to bypass the deferred + * request and directly join the other shared lock. A shared lock request + * without the priority flag might be forced to wait until the deferred + * requested had acquired and released the lock. + */ + +#define LM_FLAG_TRY 0x00000001 +#define LM_FLAG_TRY_1CB 0x00000002 +#define LM_FLAG_NOEXP 0x00000004 +#define LM_FLAG_ANY 0x00000008 +#define LM_FLAG_PRIORITY 0x00000010 + +/* + * lm_lock() and lm_async_cb return flags + * + * LM_OUT_ST_MASK + * Masks the lower two bits of lock state in the returned value. + * + * LM_OUT_CACHEABLE + * The lock hasn't been released so GFS can continue to cache data for it. + * + * LM_OUT_CANCELED + * The lock request was canceled. + * + * LM_OUT_ASYNC + * The result of the request will be returned in an LM_CB_ASYNC callback. + */ + +#define LM_OUT_ST_MASK 0x00000003 +#define LM_OUT_CACHEABLE 0x00000004 +#define LM_OUT_CANCELED 0x00000008 +#define LM_OUT_ASYNC 0x00000080 +#define LM_OUT_ERROR 0x00000100 + +/* + * lm_callback_t types + * + * LM_CB_NEED_E LM_CB_NEED_D LM_CB_NEED_S + * Blocking callback, a remote node is requesting the given lock in + * EXCLUSIVE, DEFERRED, or SHARED. + * + * LM_CB_NEED_RECOVERY + * The given journal needs to be recovered. + * + * LM_CB_DROPLOCKS + * Reduce the number of cached locks. + * + * LM_CB_ASYNC + * The given lock has been granted. + */ + +#define LM_CB_NEED_E 257 +#define LM_CB_NEED_D 258 +#define LM_CB_NEED_S 259 +#define LM_CB_NEED_RECOVERY 260 +#define LM_CB_DROPLOCKS 261 +#define LM_CB_ASYNC 262 + +/* + * lm_recovery_done() messages + */ + +#define LM_RD_GAVEUP 308 +#define LM_RD_SUCCESS 309 + + +struct lm_lockname { + u64 ln_number; + unsigned int ln_type; +}; + +#define lm_name_equal(name1, name2) \ + (((name1)->ln_number == (name2)->ln_number) && \ + ((name1)->ln_type == (name2)->ln_type)) \ + +struct lm_async_cb { + struct lm_lockname lc_name; + int lc_ret; +}; + +struct lm_lockstruct; + +struct lm_lockops { + const char *lm_proto_name; + + /* + * Mount/Unmount + */ + + int (*lm_mount) (char *table_name, char *host_data, + lm_callback_t cb, void *cb_data, + unsigned int min_lvb_size, int flags, + struct lm_lockstruct *lockstruct, + struct kobject *fskobj); + + void (*lm_others_may_mount) (void *lockspace); + + void (*lm_unmount) (void *lockspace); + + void (*lm_withdraw) (void *lockspace); + + /* + * Lock oriented operations + */ + + int (*lm_get_lock) (void *lockspace, struct lm_lockname *name, void **lockp); + + void (*lm_put_lock) (void *lock); + + unsigned int (*lm_lock) (void *lock, unsigned int cur_state, + unsigned int req_state, unsigned int flags); + + unsigned int (*lm_unlock) (void *lock, unsigned int cur_state); + + void (*lm_cancel) (void *lock); + + int (*lm_hold_lvb) (void *lock, char **lvbp); + void (*lm_unhold_lvb) (void *lock, char *lvb); + + /* + * Posix Lock oriented operations + */ + + int (*lm_plock_get) (void *lockspace, struct lm_lockname *name, + struct file *file, struct file_lock *fl); + + int (*lm_plock) (void *lockspace, struct lm_lockname *name, + struct file *file, int cmd, struct file_lock *fl); + + int (*lm_punlock) (void *lockspace, struct lm_lockname *name, + struct file *file, struct file_lock *fl); + + /* + * Client oriented operations + */ + + void (*lm_recovery_done) (void *lockspace, unsigned int jid, + unsigned int message); + + struct module *lm_owner; +}; + +/* + * lm_mount() return values + * + * ls_jid - the journal ID this node should use + * ls_first - this node is the first to mount the file system + * ls_lvb_size - size in bytes of lock value blocks + * ls_lockspace - lock module's context for this file system + * ls_ops - lock module's functions + * ls_flags - lock module features + */ + +struct lm_lockstruct { + unsigned int ls_jid; + unsigned int ls_first; + unsigned int ls_lvb_size; + void *ls_lockspace; + const struct lm_lockops *ls_ops; + int ls_flags; +}; + +/* + * Lock module bottom interface. A lock module makes itself available to GFS + * with these functions. + */ + +int gfs_register_lockproto(const struct lm_lockops *proto); +void gfs_unregister_lockproto(const struct lm_lockops *proto); + +/* + * Lock module top interface. GFS calls these functions when mounting or + * unmounting a file system. + */ + +int gfs_mount_lockproto(char *proto_name, char *table_name, char *host_data, + lm_callback_t cb, void *cb_data, + unsigned int min_lvb_size, int flags, + struct lm_lockstruct *lockstruct, + struct kobject *fskobj); + +void gfs_unmount_lockproto(struct lm_lockstruct *lockstruct); + +void gfs_withdraw_lockproto(struct lm_lockstruct *lockstruct); + +int init_lock_dlm(void); +void exit_lock_dlm(void); +int init_nolock(void); +void exit_nolock(void); + +#endif /* __LM_INTERFACE_DOT_H__ */ + --- linux-2.6.27.orig/ubuntu/gfs/ops_dentry.h +++ linux-2.6.27/ubuntu/gfs/ops_dentry.h @@ -0,0 +1,6 @@ +#ifndef __OPS_DENTRY_DOT_H__ +#define __OPS_DENTRY_DOT_H__ + +extern struct dentry_operations gfs_dops; + +#endif /* __OPS_DENTRY_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/acl.c +++ linux-2.6.27/ubuntu/gfs/acl.c @@ -0,0 +1,396 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "acl.h" +#include "eattr.h" +#include "inode.h" + +/** + * gfs_acl_validate_set - + * @ip: + * @access: + * @er: + * @mode: + * @remove: + * + * Returns: errno + */ + +int +gfs_acl_validate_set(struct gfs_inode *ip, int access, + struct gfs_ea_request *er, + int *remove, mode_t *mode) +{ + struct posix_acl *acl; + int error; + + error = gfs_acl_validate_remove(ip, access); + if (error) + return error; + + if (!er->er_data) + return -EINVAL; + + acl = posix_acl_from_xattr(er->er_data, er->er_data_len); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (!acl) { + *remove = TRUE; + return 0; + } + + error = posix_acl_valid(acl); + if (error) + goto out; + + if (access) { + error = posix_acl_equiv_mode(acl, mode); + if (!error) + *remove = TRUE; + else if (error > 0) + error = 0; + } + + out: + posix_acl_release(acl); + + return error; +} + +/** + * gfs_acl_validate_remove - + * @ip: + * @access: + * + * Returns: errno + */ + +int +gfs_acl_validate_remove(struct gfs_inode *ip, int access) +{ + if (!ip->i_sbd->sd_args.ar_posix_acls) + return -EOPNOTSUPP; + if (current->fsuid != ip->i_di.di_uid && !capable(CAP_FOWNER)) + return -EPERM; + if (ip->i_di.di_type == GFS_FILE_LNK) + return -EOPNOTSUPP; + if (!access && ip->i_di.di_type != GFS_FILE_DIR) + return -EACCES; + + return 0; +} + +/** + * gfs_acl_get - + * @ip: + * @access: + * @acl: + * + * Returns: errno + */ + +int +gfs_acl_get(struct gfs_inode *ip, int access, struct posix_acl **acl) +{ + struct gfs_ea_request er; + struct gfs_ea_location el; + int error; + + if (!ip->i_di.di_eattr) + return 0; + + memset(&er, 0, sizeof(struct gfs_ea_request)); + if (access) { + er.er_name = GFS_POSIX_ACL_ACCESS; + er.er_name_len = GFS_POSIX_ACL_ACCESS_LEN; + } else { + er.er_name = GFS_POSIX_ACL_DEFAULT; + er.er_name_len = GFS_POSIX_ACL_DEFAULT_LEN; + } + er.er_type = GFS_EATYPE_SYS; + + error = gfs_ea_find(ip, &er, &el); + if (error) + return error; + if (!el.el_ea) + return 0; + if (!GFS_EA_DATA_LEN(el.el_ea)) + goto out; + + er.er_data = kmalloc(GFS_EA_DATA_LEN(el.el_ea), GFP_KERNEL); + error = -ENOMEM; + if (!er.er_data) + goto out; + + error = gfs_ea_get_copy(ip, &el, er.er_data); + if (error) + goto out_kfree; + + *acl = posix_acl_from_xattr(er.er_data, GFS_EA_DATA_LEN(el.el_ea)); + if (IS_ERR(*acl)) + error = PTR_ERR(*acl); + + out_kfree: + kfree(er.er_data); + + out: + brelse(el.el_bh); + + return error; +} + +/** + * gfs_check_acl - Check an ACL for to see if we're allowed to do something + * @inode: the file we want to do something to + * @mask: what we want to do + * + * Returns: errno + */ + +int +gfs_check_acl(struct inode *inode, int mask) +{ + struct posix_acl *acl = NULL; + int error; + + error = gfs_acl_get(get_v2ip(inode), TRUE, &acl); + if (error) + return error; + + if (acl) { + error = posix_acl_permission(inode, acl, mask); + posix_acl_release(acl); + return error; + } + + return -EAGAIN; +} + +/** + * gfs_acl_new_prep - + * @dip: + * @type: + * @mode: + * @a_acl: + * @d_acl: + * @blocks: + * @data: + * + * Returns: errno + */ + +int +gfs_acl_new_prep(struct gfs_inode *dip, + unsigned int type, mode_t *mode, + void **a_data, void **d_data, + unsigned int *size, + unsigned int *blocks) +{ + struct posix_acl *acl = NULL; + int set_a = FALSE, set_d = FALSE; + int error; + + if (!dip->i_sbd->sd_args.ar_posix_acls) + return 0; + if (type == GFS_FILE_LNK) + return 0; + + error = gfs_acl_get(dip, FALSE, &acl); + if (error) + return error; + if (!acl) { + (*mode) &= ~current->fs->umask; + return 0; + } + + { + struct posix_acl *clone = posix_acl_clone(acl, GFP_KERNEL); + error = -ENOMEM; + if (!clone) + goto out; + posix_acl_release(acl); + acl = clone; + } + + error = posix_acl_create_masq(acl, mode); + if (error < 0) + goto out; + if (error > 0) { + set_a = TRUE; + error = 0; + } + if (type == GFS_FILE_DIR) + set_d = TRUE; + + if (set_a || set_d) { + struct gfs_ea_request er; + void *d; + unsigned int s = posix_acl_xattr_size(acl->a_count); + unsigned int b; + + memset(&er, 0, sizeof(struct gfs_ea_request)); + er.er_name_len = GFS_POSIX_ACL_DEFAULT_LEN; + er.er_data_len = s; + error = gfs_ea_check_size(dip->i_sbd, &er); + if (error) + goto out; + + b = DIV_RU(er.er_data_len, dip->i_sbd->sd_jbsize); + if (set_a && set_d) + b *= 2; + b++; + + d = kmalloc(s, GFP_KERNEL); + error = -ENOMEM; + if (!d) + goto out; + posix_acl_to_xattr(acl, d, s); + + if (set_a) + *a_data = d; + if (set_d) + *d_data = d; + *size = s; + *blocks = b; + + error = 0; + } + + out: + posix_acl_release(acl); + + return error; +} + +/** + * gfs_acl_new_init - + * @dip: + * @ip: + * @a_data: + * @d_data: + * @size: + * + * Returns: errno + */ + +int gfs_acl_new_init(struct gfs_inode *dip, struct gfs_inode *ip, + void *a_data, void *d_data, unsigned int size) +{ + void *data = (a_data) ? a_data : d_data; + unsigned int x; + int error = 0; + + ip->i_alloc = dip->i_alloc; /* Cheesy, but it works. */ + + for (x = 0; x < 2; x++) { + struct gfs_ea_request er; + + memset(&er, 0, sizeof(struct gfs_ea_request)); + if (x) { + if (!a_data) + continue; + er.er_name = GFS_POSIX_ACL_ACCESS; + er.er_name_len = GFS_POSIX_ACL_ACCESS_LEN; + } else { + if (!d_data) + continue; + er.er_name = GFS_POSIX_ACL_DEFAULT; + er.er_name_len = GFS_POSIX_ACL_DEFAULT_LEN; + } + er.er_data = data; + er.er_data_len = size; + er.er_type = GFS_EATYPE_SYS; + + error = gfs_ea_acl_init(ip, &er); + if (error) + break; + } + + ip->i_alloc = NULL; + + kfree(data); + + return error; +} + +/** + * gfs_acl_chmod - + * @ip: + * @attr: + * + * Returns: errno + */ + +int +gfs_acl_chmod(struct gfs_inode *ip, struct iattr *attr) +{ + struct gfs_ea_request er; + struct gfs_ea_location el; + struct posix_acl *acl; + int error; + + if (!ip->i_di.di_eattr) + goto simple; + + memset(&er, 0, sizeof(struct gfs_ea_request)); + er.er_name = GFS_POSIX_ACL_ACCESS; + er.er_name_len = GFS_POSIX_ACL_ACCESS_LEN; + er.er_type = GFS_EATYPE_SYS; + + error = gfs_ea_find(ip, &er, &el); + if (error) + return error; + if (!el.el_ea) + goto simple; + if (!GFS_EA_DATA_LEN(el.el_ea)) + goto simple; + + er.er_data = kmalloc(GFS_EA_DATA_LEN(el.el_ea), GFP_KERNEL); + error = -ENOMEM; + if (!er.er_data) + goto out; + + error = gfs_ea_get_copy(ip, &el, er.er_data); + if (error) + goto out_kfree; + + acl = posix_acl_from_xattr(er.er_data, GFS_EA_DATA_LEN(el.el_ea)); + if (IS_ERR(acl)) { + error = PTR_ERR(acl); + goto out_kfree; + } else if (!acl) { + kfree(er.er_data); + brelse(el.el_bh); + goto simple; + } + + error = posix_acl_chmod_masq(acl, attr->ia_mode); + if (error) + goto out_acl; + + posix_acl_to_xattr(acl, er.er_data, GFS_EA_DATA_LEN(el.el_ea)); + + error = gfs_ea_acl_chmod(ip, &el, attr, er.er_data); + + out_acl: + posix_acl_release(acl); + + out_kfree: + kfree(er.er_data); + + out: + brelse(el.el_bh); + + return error; + + simple: + return gfs_setattr_simple(ip, attr); +} --- linux-2.6.27.orig/ubuntu/gfs/ops_fstype.c +++ linux-2.6.27/ubuntu/gfs/ops_fstype.c @@ -0,0 +1,816 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "daemon.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "lm.h" +#include "mount.h" +#include "ops_export.h" +#include "ops_fstype.h" +#include "ops_super.h" +#include "proc.h" +#include "quota.h" +#include "recovery.h" +#include "rgrp.h" +#include "super.h" +#include "sys.h" +#include "unlinked.h" + +#define DO 0 +#define UNDO 1 + +extern struct dentry_operations gfs_dops; + +static struct gfs_sbd *init_sbd(struct super_block *sb) +{ + struct gfs_sbd *sdp; + unsigned int x; + + sdp = vmalloc(sizeof(struct gfs_sbd)); + if (!sdp) + return NULL; + + memset(sdp, 0, sizeof(struct gfs_sbd)); + + set_v2sdp(sb, sdp); + sdp->sd_vfs = sb; + gfs_tune_init(&sdp->sd_tune); + + /* Init rgrp variables */ + + INIT_LIST_HEAD(&sdp->sd_rglist); + init_MUTEX(&sdp->sd_rindex_lock); + INIT_LIST_HEAD(&sdp->sd_rg_mru_list); + spin_lock_init(&sdp->sd_rg_mru_lock); + INIT_LIST_HEAD(&sdp->sd_rg_recent); + spin_lock_init(&sdp->sd_rg_recent_lock); + spin_lock_init(&sdp->sd_rg_forward_lock); + + spin_lock_init(&sdp->sd_statfs_spin); + + for (x = 0; x < GFS_GL_HASH_SIZE; x++) { + sdp->sd_gl_hash[x].hb_lock = RW_LOCK_UNLOCKED; + INIT_LIST_HEAD(&sdp->sd_gl_hash[x].hb_list); + } + + INIT_LIST_HEAD(&sdp->sd_reclaim_list); + spin_lock_init(&sdp->sd_reclaim_lock); + init_waitqueue_head(&sdp->sd_reclaim_wchan); + + for (x = 0; x < GFS_MHC_HASH_SIZE; x++) + INIT_LIST_HEAD(&sdp->sd_mhc[x]); + INIT_LIST_HEAD(&sdp->sd_mhc_single); + spin_lock_init(&sdp->sd_mhc_lock); + + for (x = 0; x < GFS_DEPEND_HASH_SIZE; x++) + INIT_LIST_HEAD(&sdp->sd_depend[x]); + spin_lock_init(&sdp->sd_depend_lock); + + init_MUTEX(&sdp->sd_freeze_lock); + + spin_lock_init(&sdp->sd_log_seg_lock); + INIT_LIST_HEAD(&sdp->sd_log_seg_list); + init_waitqueue_head(&sdp->sd_log_seg_wait); + INIT_LIST_HEAD(&sdp->sd_log_ail); + INIT_LIST_HEAD(&sdp->sd_log_incore); + init_rwsem(&sdp->sd_log_lock); + INIT_LIST_HEAD(&sdp->sd_unlinked_list); + spin_lock_init(&sdp->sd_unlinked_lock); + INIT_LIST_HEAD(&sdp->sd_quota_list); + spin_lock_init(&sdp->sd_quota_lock); + + INIT_LIST_HEAD(&sdp->sd_dirty_j); + spin_lock_init(&sdp->sd_dirty_j_lock); + + spin_lock_init(&sdp->sd_ail_lock); + INIT_LIST_HEAD(&sdp->sd_recovery_bufs); + + return sdp; +} + +static void init_vfs(struct super_block *sb, unsigned noatime) +{ + struct gfs_sbd *sdp = sb->s_fs_info; + + /* Set up Linux Virtual (VFS) Super Block */ + + sb->s_magic = GFS_MAGIC; + sb->s_op = &gfs_super_ops; + sb->s_export_op = &gfs_export_ops; + + /* Don't let the VFS update atimes. GFS handles this itself. */ + sb->s_flags |= MS_NOATIME | MS_NODIRATIME; + sb->s_maxbytes = MAX_LFS_FILESIZE; + + /* If we were mounted with -o acl (to support POSIX access control + lists), tell VFS */ + if (sdp->sd_args.ar_posix_acls) + sb->s_flags |= MS_POSIXACL; +} + +int init_names(struct gfs_sbd *sdp, int silent) +{ + struct gfs_sb *sb = NULL; + char *proto, *table; + int error = 0; + + proto = sdp->sd_args.ar_lockproto; + table = sdp->sd_args.ar_locktable; + + /* Try to autodetect */ + + if (!proto[0] || !table[0]) { + struct buffer_head *bh; + + bh = sb_getblk(sdp->sd_vfs, + GFS_SB_ADDR >> sdp->sd_fsb2bb_shift); + lock_buffer(bh); + clear_buffer_uptodate(bh); + clear_buffer_dirty(bh); + unlock_buffer(bh); + ll_rw_block(READ, 1, &bh); + wait_on_buffer(bh); + + if (!buffer_uptodate(bh)) { + brelse(bh); + return -EIO; + } + + sb = kmalloc(sizeof(struct gfs_sb), GFP_KERNEL); + if (!sb) { + brelse(bh); + return -ENOMEM; + } + gfs_sb_in(sb, bh->b_data); + brelse(bh); + + error = gfs_check_sb(sdp, sb, silent); + if (error) + goto out; + + if (!proto[0]) + proto = sb->sb_lockproto; + if (!table[0]) + table = sb->sb_locktable; + } + + if (!table[0]) + table = sdp->sd_vfs->s_id; + + snprintf(sdp->sd_proto_name, 256, "%s", proto); + snprintf(sdp->sd_table_name, 256, "%s", table); + + while ((table = strchr(sdp->sd_table_name, '/'))) + *table = '_'; + + out: + kfree(sb); + + return error; +} + +static int init_locking(struct gfs_sbd *sdp, struct gfs_holder *mount_gh, + int undo) +{ + struct task_struct *p; + int error = 0; + + if (undo) + goto fail_live; + + if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) && + !sdp->sd_args.ar_ignore_local_fs) { + /* Force local [p|f]locks */ + sdp->sd_args.ar_localflocks = TRUE; + + /* Force local read ahead and caching */ + sdp->sd_args.ar_localcaching = TRUE; + + /* Allow the machine to oops */ + sdp->sd_args.ar_oopses_ok = TRUE; + } + + /* Start up the scand thread */ + + p = kthread_run(gfs_scand, sdp, "gfs_scand"); + error = IS_ERR(p); + if (error) { + printk("GFS: fsid=%s: can't start scand thread: %d\n", + sdp->sd_fsname, error); + return error; + } + sdp->sd_scand_process = p; + + /* Start up the glockd thread */ + + for (sdp->sd_glockd_num = 0; + sdp->sd_glockd_num < sdp->sd_args.ar_num_glockd; + sdp->sd_glockd_num++) { + p = kthread_run(gfs_glockd, sdp, "gfs_glockd"); + error = IS_ERR(p); + if (error) { + printk("GFS: fsid=%s: can't start glockd thread: %d\n", + sdp->sd_fsname, error); + goto fail; + } + sdp->sd_glockd_process[sdp->sd_glockd_num] = p; + } + + /* Only one node may mount at a time */ + error = gfs_glock_nq_num(sdp, + GFS_MOUNT_LOCK, &gfs_nondisk_glops, + LM_ST_EXCLUSIVE, LM_FLAG_NOEXP | GL_NOCACHE, + mount_gh); + if (error) { + printk("GFS: fsid=%s: can't acquire mount glock: %d\n", + sdp->sd_fsname, error); + goto fail; + } + + /* Show that cluster is alive */ + error = gfs_glock_nq_num(sdp, + GFS_LIVE_LOCK, &gfs_nondisk_glops, + LM_ST_SHARED, LM_FLAG_NOEXP | GL_EXACT, + &sdp->sd_live_gh); + if (error) { + printk("GFS: fsid=%s: can't acquire live glock: %d\n", + sdp->sd_fsname, error); + goto fail_mount; + } + + sdp->sd_live_gh.gh_owner = NULL; + return 0; + +fail_live: + gfs_glock_dq_uninit(&sdp->sd_live_gh); + +fail_mount: + gfs_glock_dq_uninit(mount_gh); + +fail: + while (sdp->sd_glockd_num--) + kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); + + kthread_stop(sdp->sd_scand_process); + + return error; +} + +static int init_sb(struct gfs_sbd *sdp, int silent, int undo) +{ + struct super_block *sb = sdp->sd_vfs; + struct gfs_holder sb_gh; + int error = 0; + struct inode *inode; + + if (undo) + goto fail_dput; + + /* Read the SuperBlock from disk, get enough info to enable us + to read-in the journal index and replay all journals. */ + + error = gfs_glock_nq_num(sdp, + GFS_SB_LOCK, &gfs_meta_glops, + (sdp->sd_args.ar_upgrade) ? LM_ST_EXCLUSIVE : LM_ST_SHARED, + 0, &sb_gh); + if (error) { + printk("GFS: fsid=%s: can't acquire superblock glock: %d\n", + sdp->sd_fsname, error); + return error; + } + + error = gfs_read_sb(sdp, sb_gh.gh_gl, silent); + if (error) { + printk("GFS: fsid=%s: can't read superblock: %d\n", + sdp->sd_fsname, error); + goto out; + } + + /* Set up the buffer cache and SB for real, now that we know block + sizes, version #s, locations of important on-disk inodes, etc. */ + + error = -EINVAL; + if (sdp->sd_sb.sb_bsize < bdev_hardsect_size(sb->s_bdev)) { + printk("GFS: fsid=%s: FS block size (%u) is too small for device block size (%u)\n", + sdp->sd_fsname, sdp->sd_sb.sb_bsize, bdev_hardsect_size(sb->s_bdev)); + goto fail; + } + if (sdp->sd_sb.sb_bsize > PAGE_SIZE) { + printk("GFS: fsid=%s: FS block size (%u) is too big for machine page size (%u)\n", + sdp->sd_fsname, sdp->sd_sb.sb_bsize, + (unsigned int)PAGE_SIZE); + goto fail; + } + + /* Get rid of buffers from the original block size */ + sb_gh.gh_gl->gl_ops->go_inval(sb_gh.gh_gl, DIO_METADATA | DIO_DATA); + sb_gh.gh_gl->gl_aspace->i_blkbits = sdp->sd_sb.sb_bsize_shift; + + sb_set_blocksize(sb, sdp->sd_sb.sb_bsize); + + /* Read in the resource index inode */ + + error = gfs_get_riinode(sdp); + if (error) { + printk("GFS: fsid=%s: can't get resource index inode: %d\n", + sdp->sd_fsname, error); + goto fail; + } + + /* Get the root inode */ + error = gfs_get_rootinode(sdp); + if (error) { + printk("GFS: fsid=%s: can't read in root inode: %d\n", + sdp->sd_fsname, error); + goto fail_ri_free; + } + /* Get the root inode/dentry */ + + inode = gfs_iget(sdp->sd_rooti, CREATE); + if (!inode) { + printk("GFS: fsid=%s: can't get root inode\n", sdp->sd_fsname); + error = -ENOMEM; + goto fail_ri_free; + } + sb->s_root = d_alloc_root(inode); + if (!sb->s_root) { + iput(inode); + printk("GFS: fsid=%s: can't get root dentry\n", sdp->sd_fsname); + error = -ENOMEM; + goto fail_root_free; + } + sb->s_root->d_op = &gfs_dops; + + /* Read in the quota inode */ + error = gfs_get_qinode(sdp); + if (error) { + printk("GFS: fsid=%s: can't get quota file inode: %d\n", + sdp->sd_fsname, error); + goto fail_root_free; + } + + /* Implement fast statfs on the unused license inode location. + * sb->sb_quota_di.no_formal_ino = jindex_dinode + 2; + * sb->sb_quota_di.no_addr = jindex_dinode + 2; + * sb->sb_license_di.no_formal_ino = jindex_dinode + 3; + * sb->sb_license_di.no_addr = jindex_dinode + 3; + */ + error = gfs_get_linode(sdp); + if (error) { + printk("GFS: fsid=%s: can't get statfs file inode: %d\n", + sdp->sd_fsname, error); + goto fail_qi_free; + } + + /* We're through with the superblock lock */ +out: + gfs_glock_dq_uninit(&sb_gh); + return error; + +fail_dput: + gfs_inode_put(sdp->sd_linode); + if (sb->s_root) { + dput(sb->s_root); + sb->s_root = NULL; + } +fail_qi_free: + gfs_inode_put(sdp->sd_qinode); +fail_root_free: + gfs_inode_put(sdp->sd_rooti); +fail_ri_free: + gfs_inode_put(sdp->sd_riinode); + gfs_clear_rgrpd(sdp); +fail: + if (!undo) + gfs_glock_dq_uninit(&sb_gh); + return error; +} + +static int init_journal(struct gfs_sbd *sdp, int undo) +{ + struct gfs_holder ji_gh; + int error = 0; + unsigned int x; + int jindex = TRUE; + struct task_struct *p; + + if (undo) { + jindex = 0; + goto fail_recoverd; + } + + init_MUTEX(&sdp->sd_jindex_lock); + + /* Get a handle on the transaction glock; we need this for disk format + upgrade and journal replays, as well as normal operation. */ + + error = gfs_glock_get(sdp, GFS_TRANS_LOCK, &gfs_trans_glops, + CREATE, &sdp->sd_trans_gl); + if (error) + return error; + set_bit(GLF_STICKY, &sdp->sd_trans_gl->gl_flags); + + /* Load in the journal index special file */ + + error = gfs_jindex_hold(sdp, &ji_gh); + if (error) { + printk("GFS: fsid=%s: can't read journal index: %d\n", + sdp->sd_fsname, error); + goto fail_jhold; + } + + if (sdp->sd_args.ar_spectator) { + sdp->sd_jdesc = sdp->sd_jindex[0]; + sdp->sd_log_seg_free = sdp->sd_jdesc.ji_nsegment; + sdp->sd_log_seg_ail2 = 0; + } + else { + /* Discover this node's journal number (lock module tells us + which one to use), and lock it */ + error = -EINVAL; + if (sdp->sd_lockstruct.ls_jid >= sdp->sd_journals) { + printk("GFS: fsid=%s: can't mount journal #%u\n", + sdp->sd_fsname, sdp->sd_lockstruct.ls_jid); + printk("GFS: fsid=%s: there are only %u journals (0 - %u)\n", + sdp->sd_fsname, sdp->sd_journals, sdp->sd_journals - 1); + goto fail_jindex; + } + sdp->sd_jdesc = sdp->sd_jindex[sdp->sd_lockstruct.ls_jid]; + sdp->sd_log_seg_free = sdp->sd_jdesc.ji_nsegment; + sdp->sd_log_seg_ail2 = 0; + + error = gfs_glock_nq_num(sdp, + sdp->sd_jdesc.ji_addr, &gfs_meta_glops, + LM_ST_EXCLUSIVE, LM_FLAG_NOEXP, + &sdp->sd_journal_gh); + if (error) { + printk("GFS: fsid=%s: can't acquire the journal glock: %d\n", + sdp->sd_fsname, error); + goto fail_jindex; + } + } + + if (sdp->sd_lockstruct.ls_first) { + /* We're first node within cluster to mount this filesystem, + replay ALL of the journals, then let lock module know + that we're done. */ + for (x = 0; x < sdp->sd_journals; x++) { + error = gfs_recover_journal(sdp, + x, sdp->sd_jindex + x, + FALSE); + if (error) { + printk("GFS: fsid=%s: error recovering journal %u: %d\n", + sdp->sd_fsname, x, error); + goto fail_journal_gh; + } + } + + gfs_lm_others_may_mount(sdp); + } else if (!sdp->sd_args.ar_spectator) { + /* We're not the first; replay only our own journal. */ + error = gfs_recover_journal(sdp, sdp->sd_lockstruct.ls_jid, + &sdp->sd_jdesc, TRUE); + if (error) { + printk("GFS: fsid=%s: error recovering my journal: %d\n", + sdp->sd_fsname, error); + goto fail_journal_gh; + } + } + + gfs_glock_dq_uninit(&ji_gh); + jindex = FALSE; + + /* Disown my Journal glock */ + sdp->sd_journal_gh.gh_owner = NULL; + + /* Make the FS read/write */ + + if (!test_bit(SDF_ROFS, &sdp->sd_flags)) { + error = gfs_make_fs_rw(sdp); + if (error) { + printk("GFS: fsid=%s: can't make file system RW: %d\n", + sdp->sd_fsname, error); + goto fail_journal_gh; + } + } + + /* Start up the journal recovery thread */ + + p = kthread_run(gfs_recoverd, sdp, "gfs_recoverd"); + error = IS_ERR(p); + if (error) { + printk("GFS: fsid=%s: can't start recoverd thread: %d\n", + sdp->sd_fsname, error); + goto fail_journal_gh; + } + sdp->sd_recoverd_process = p; + + return 0; + +fail_recoverd: + kthread_stop(sdp->sd_recoverd_process); + sdp->sd_recoverd_process = NULL; + +fail_journal_gh: + if (!sdp->sd_args.ar_spectator) + gfs_glock_dq_uninit(&sdp->sd_journal_gh); + +fail_jindex: + if (jindex) + gfs_glock_dq_uninit(&ji_gh); + +fail_jhold: + gfs_glock_put(sdp->sd_trans_gl); + return error; +} + +static int init_threads(struct gfs_sbd *sdp, int undo) +{ + struct task_struct *p; + int error = 0; + + if (undo) + goto fail_logd; + + sdp->sd_jindex_refresh_time = jiffies; + + /* Start up the logd thread */ + p = kthread_run(gfs_logd, sdp, "gfs_logd"); + error = IS_ERR(p); + if (error) { + printk("GFS: fsid=%s: can't start logd thread: %d\n", + sdp->sd_fsname, error); + goto fail; + } + sdp->sd_logd_process = p; + + /* Start up the quotad thread */ + + p = kthread_run(gfs_quotad, sdp, "gfs_quotad"); + if (error < 0) { + printk("GFS: fsid=%s: can't start quotad thread: %d\n", + sdp->sd_fsname, error); + goto fail_quotad; + } + sdp->sd_quotad_process = p; + + /* Start up the inoded thread */ + + p = kthread_run(gfs_inoded, sdp, "gfs_inoded"); + if (error < 0) { + printk("GFS: fsid=%s: can't start inoded thread: %d\n", + sdp->sd_fsname, error); + goto fail_inoded; + } + sdp->sd_inoded_process = p; + return 0; + +fail_logd: + kthread_stop(sdp->sd_inoded_process); +fail_inoded: + kthread_stop(sdp->sd_quotad_process); +fail_quotad: + kthread_stop(sdp->sd_logd_process); +fail: + return error; +} + +/** + * fill_super - Read in superblock + * @sb: The VFS superblock + * @data: Mount options + * @silent: Don't complain if it's not a GFS filesystem + * + * Returns: errno + * + * After cross-linking Linux VFS incore superblock and our GFS incore + * superblock (filesystem instance structures) to one another, we: + * -- Init some of our GFS incore superblock, including some temporary + * block-size values (enough to read on-disk superblock). + * -- Set up some things in Linux VFS superblock. + * -- Mount a lock module, init glock system (incl. glock reclaim daemons), + * and init some important inter-node locks (MOUNT, LIVE, SuperBlock). + * -- Read-in the GFS on-disk superblock (1st time, to get enough info + * to do filesystem upgrade and journal replay, incl. journal index). + * -- Upgrade on-disk filesystem format (rarely needed). + * -- Replay journals (always; replay *all* journals if we're first-to-mount). + * -- Read-in on-disk superblock and journal index special file again + * (2nd time, assumed 100% valid now after journal replay). + * -- Read-in info on other special (hidden) files (root inode, resource index, + * quota inode, license inode). + * -- Start other daemons (journal/log recovery, log tail, quota updates, inode + * reclaim) for periodic maintenance. + * + */ + +static int fill_super(struct super_block *sb, void *data, int silent) +{ + struct gfs_sbd *sdp; + struct gfs_holder mount_gh; + int error; + + sdp = init_sbd(sb); + if (!sdp) { + printk(KERN_WARNING "GFS: can't alloc struct gfs_sbd\n"); + return -ENOMEM; + } + + error = gfs_make_args((char *)data, &sdp->sd_args, FALSE); + if (error) { + printk("GFS: can't parse mount arguments\n"); + goto fail; + } + + if (sdp->sd_args.ar_spectator) { + sb->s_flags |= MS_RDONLY; + set_bit(SDF_ROFS, &sdp->sd_flags); + } + + /* Copy VFS mount flags */ + + if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME)) + set_bit(SDF_NOATIME, &sdp->sd_flags); + if (sb->s_flags & MS_RDONLY) + set_bit(SDF_ROFS, &sdp->sd_flags); + + init_vfs(sb, SDF_NOATIME); + + /* Turn off quota stuff if we get the noquota mount option, don't + need to grab the sd_tune lock here since its before anything + touches the sd_tune values */ + if (sdp->sd_args.ar_noquota) { + sdp->sd_tune.gt_quota_enforce = 0; + sdp->sd_tune.gt_quota_account = 0; + } + + /* Set up the buffer cache and fill in some fake block size values + to allow us to read-in the on-disk superblock. */ + + sdp->sd_sb.sb_bsize = sb_min_blocksize(sb, GFS_BASIC_BLOCK); + sdp->sd_sb.sb_bsize_shift = sb->s_blocksize_bits; + sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - GFS_BASIC_BLOCK_SHIFT; + sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; + + if (sizeof(struct gfs_sb) > sdp->sd_sb.sb_bsize) { + printk("GFS: sizeof(struct gfs_sb) > sdp->sd_sb.sb_bsize\n" + "GFS: %u > %u\n", + (unsigned int)sizeof(struct gfs_sb), sdp->sd_sb.sb_bsize); + error = -EINVAL; + goto fail; + } + error = init_names(sdp, silent); + if (error) + goto fail; + + error = gfs_sys_fs_add(sdp); + if (error) + goto fail; + + /* Mount an inter-node lock module, check for local optimizations */ + + error = gfs_lm_mount(sdp, silent); + if (error) + goto fail_sys; + + error = init_locking(sdp, &mount_gh, DO); + if (error) + goto fail_lm; + + error = init_sb(sdp, silent, DO); + if (error) + goto fail_locking; + + /* Read-in journal index inode (but not the file contents, yet) */ + + error = gfs_get_jiinode(sdp); + if (error) { + printk("GFS: fsid=%s: can't get journal index inode: %d\n", + sdp->sd_fsname, error); + goto fail_jiinode; + } + + error = init_journal(sdp, DO); + if (error) + goto fail_sb; + /* Get a handle on the rename lock */ + + error = gfs_glock_get(sdp, GFS_RENAME_LOCK, &gfs_nondisk_glops, + CREATE, &sdp->sd_rename_gl); + if (error) + goto fail_journal; + + error = init_threads(sdp, DO); + if (error) + goto fail_journal; + + gfs_proc_fs_add(sdp); + gfs_glock_dq_uninit(&mount_gh); + + return 0; + +fail_journal: + init_journal(sdp, UNDO); + +fail_sb: + gfs_inode_put(sdp->sd_jiinode); + +fail_jiinode: + init_sb(sdp, 0, UNDO); + +fail_locking: + init_locking(sdp, &mount_gh, UNDO); + +fail_lm: + gfs_gl_hash_clear(sdp, TRUE); + gfs_lm_unmount(sdp); + gfs_clear_dirty_j(sdp); + while (invalidate_inodes(sb)) + yield(); + +fail_sys: + gfs_sys_fs_del(sdp); + +fail: + vfree(sdp); + sb->s_fs_info = NULL; + + return error; +} + +/** + * gfs_test_bdev_super - + * @sb: + * @data: + * + */ + +int +gfs_test_bdev_super(struct super_block *sb, void *data) +{ + return (void *)sb->s_bdev == data; +} + +/** + * gfs_test_bdev_super - + * @sb: + * @data: + * + */ + +int +gfs_set_bdev_super(struct super_block *sb, void *data) +{ + sb->s_bdev = data; + sb->s_dev = sb->s_bdev->bd_dev; + return 0; +} + +/** + * gfs_get_sb - + * @fs_type: + * @flags: + * @dev_name: + * @data: + * + * Rip off of get_sb_bdev(). + * + * Returns: the new superblock + */ + +static int gfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); +} + +/** + * gfs_kill_sb - + * @sb: + * + * Rip off of kill_block_super(). + * + */ + +void +gfs_kill_sb(struct super_block *sb) +{ + kill_block_super(sb); +} + +struct file_system_type gfs_fs_type = { + .name = "gfs", + .fs_flags = FS_REQUIRES_DEV, + .get_sb = gfs_get_sb, + .kill_sb = gfs_kill_sb, + .owner = THIS_MODULE, +}; --- linux-2.6.27.orig/ubuntu/gfs/ioctl.c +++ linux-2.6.27/ubuntu/gfs/ioctl.c @@ -0,0 +1,1605 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs_ioctl.h" +#include "gfs.h" +#include "bmap.h" +#include "dio.h" +#include "dir.h" +#include "eattr.h" +#include "file.h" +#include "glock.h" +#include "glops.h" +#include "inode.h" +#include "ioctl.h" +#include "log.h" +#include "quota.h" +#include "rgrp.h" +#include "super.h" +#include "trans.h" + +typedef int (*gi_filler_t) (struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count); + +#define ARG_SIZE (32) + +/** + * gi_skeleton - Setup a buffer that functions can print into + * @ip: + * @gi: + * @filler: + * + * Returns: -errno or count of bytes copied to userspace + */ + +static int +gi_skeleton(struct gfs_inode *ip, struct gfs_ioctl *gi, + gi_filler_t filler) +{ + unsigned int size = gfs_tune_get(ip->i_sbd, gt_lockdump_size); + char *buf; + unsigned int count = 0; + int error; + + if (size > gi->gi_size) + size = gi->gi_size; + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + error = filler(ip, gi, buf, size, &count); + if (error) + goto out; + + if (copy_to_user(gi->gi_data, buf, count + 1)) + error = -EFAULT; + else + error = count + 1; + + out: + kfree(buf); + + return error; +} + +/** + * gi_get_cookie - Return the "cookie" (identifying string) for a + * filesystem mount + * @ip: + * @gi: + * @buf: + * @size: + * @count: + * + * Returns: errno + */ + +static int +gi_get_cookie(struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count) +{ + int error = -ENOBUFS; + + if (gi->gi_argc != 1) + return -EINVAL; + + gfs_printf("version 0\n"); + gfs_printf("%lu", (unsigned long)ip->i_sbd); + + error = 0; + + out: + return error; +} + +/** + * gi_get_super - Return the "struct gfs_sb" for a filesystem + * @sdp: + * @gi: + * + * Returns: errno + */ + +static int +gi_get_super(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +{ + struct gfs_holder sb_gh; + struct buffer_head *bh; + struct gfs_sb *sb; + int error; + + if (gi->gi_argc != 1) + return -EINVAL; + if (gi->gi_size != sizeof(struct gfs_sb)) + return -EINVAL; + + sb = kmalloc(sizeof(struct gfs_sb), GFP_KERNEL); + if (!sb) + return -ENOMEM; + + error = gfs_glock_nq_num(sdp, + GFS_SB_LOCK, &gfs_meta_glops, + LM_ST_SHARED, 0, &sb_gh); + if (error) + goto out; + + error = gfs_dread(sb_gh.gh_gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift, + DIO_START | DIO_WAIT, &bh); + if (error) { + gfs_glock_dq_uninit(&sb_gh); + goto out; + } + gfs_sb_in(sb, bh->b_data); + brelse(bh); + + gfs_glock_dq_uninit(&sb_gh); + + if (copy_to_user(gi->gi_data, sb, + sizeof(struct gfs_sb))) + error = -EFAULT; + else + error = sizeof(struct gfs_sb); + + out: + kfree(sb); + + return error; +} + +/** + * gi_get_args - Return the mount arguments + * @ip: + * @gi: + * @buf: + * @size: + * @count: + * + * Returns: errno + */ + +static int +gi_get_args(struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count) +{ + struct gfs_args *args = &ip->i_sbd->sd_args; + int error = -ENOBUFS; + + if (gi->gi_argc != 1) + return -EINVAL; + + gfs_printf("version 0\n"); + gfs_printf("lockproto %s\n", args->ar_lockproto); + gfs_printf("locktable %s\n", args->ar_locktable); + gfs_printf("hostdata %s\n", args->ar_hostdata); + gfs_printf("ignore_local_fs %d\n", args->ar_ignore_local_fs); + gfs_printf("localcaching %d\n", args->ar_localcaching); + gfs_printf("localflocks %d\n", args->ar_localflocks); + gfs_printf("oopses_ok %d\n", args->ar_oopses_ok); + gfs_printf("upgrade %d\n", args->ar_upgrade); + gfs_printf("num_glockd %u\n", args->ar_num_glockd); + gfs_printf("posix_acls %d\n", args->ar_posix_acls); + gfs_printf("suiddir %d\n", args->ar_suiddir); + + error = 0; + + out: + return error; +} + +/** + * gi_get_lockstruct - Return the information in the FS' lockstruct + * @ip: + * @gi: + * @buf: + * @size: + * @count: + * + * Returns: errno + */ + +static int +gi_get_lockstruct(struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count) +{ + struct lm_lockstruct *ls = &ip->i_sbd->sd_lockstruct; + int error = -ENOBUFS; + + if (gi->gi_argc != 1) + return -EINVAL; + + gfs_printf("version 0\n"); + gfs_printf("jid %u\n", ls->ls_jid); + gfs_printf("first %u\n", ls->ls_first); + gfs_printf("lvb_size %u\n", ls->ls_lvb_size); + gfs_printf("flags %d\n", ls->ls_flags); + + error = 0; + + out: + return error; +} + +/** + * gi_get_stat_gfs - Return a filesystem's space usage information + * @ip: + * @gi: + * @buf: + * @size: + * @count: + * + * Returns: errno + */ + +static int +gi_get_stat_gfs(struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count) +{ + struct gfs_stat_gfs sg; + int error; + + if (gi->gi_argc != 1) + return -EINVAL; + + error = gfs_stat_gfs(ip->i_sbd, &sg, TRUE); + if (error) + return error; + + error = -ENOBUFS; + + gfs_printf("version 0\n"); + gfs_printf("bsize %u\n", ip->i_sbd->sd_sb.sb_bsize); + gfs_printf("total_blocks %"PRIu64"\n", sg.sg_total_blocks); + gfs_printf("free %"PRIu64"\n", sg.sg_free); + gfs_printf("used_dinode %"PRIu64"\n", sg.sg_used_dinode); + gfs_printf("free_dinode %"PRIu64"\n", sg.sg_free_dinode); + gfs_printf("used_meta %"PRIu64"\n", sg.sg_used_meta); + gfs_printf("free_meta %"PRIu64"\n", sg.sg_free_meta); + + error = 0; + + out: + return error; +} + +/** + * handle_roll - Read a atomic_t as an unsigned int + * @a: a counter + * + * if @a is negative, reset it to zero + * + * Returns: the value of the counter + */ + +static unsigned int +handle_roll(atomic_t *a) +{ + int x = atomic_read(a); + if (x < 0) { + atomic_set(a, 0); + return 0; + } + return (unsigned int)x; +} + +/** + * gi_get_counters - Return usage counters + * @ip: + * @gi: + * @buf: + * @size: + * @count: + * + * Returns: errno + */ + +static int +gi_get_counters(struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count) +{ + struct gfs_sbd *sdp = ip->i_sbd; + int error = -ENOBUFS; + + if (gi->gi_argc != 1) + return -EINVAL; + + gfs_printf("version 0\n"); + gfs_printf("sd_glock_count:locks::%d\n", + atomic_read(&sdp->sd_glock_count)); + gfs_printf("sd_glock_held_count:locks held::%d\n", + atomic_read(&sdp->sd_glock_held_count)); + gfs_printf("sd_freeze_count:freeze count::%d\n", + sdp->sd_freeze_count); + gfs_printf("sd_inode_count:incore inodes::%d\n", + atomic_read(&sdp->sd_inode_count)); + gfs_printf("sd_bufdata_count:metadata buffers::%d\n", + atomic_read(&sdp->sd_bufdata_count)); + gfs_printf("sd_unlinked_ic_count:unlinked inodes::%d\n", + atomic_read(&sdp->sd_unlinked_ic_count)); + gfs_printf("sd_quota_count:quota IDs::%d\n", + atomic_read(&sdp->sd_quota_count)); + gfs_printf("sd_log_buffers:incore log buffers::%u\n", + sdp->sd_log_buffers); + gfs_printf("sd_log_seg_free:log segments free::%u\n", + sdp->sd_log_seg_free); + gfs_printf("ji_nsegment:log segments total::%u\n", + sdp->sd_jdesc.ji_nsegment); + gfs_printf("sd_mhc_count:meta header cache entries::%d\n", + atomic_read(&sdp->sd_mhc_count)); + gfs_printf("sd_depend_count:glock dependencies::%d\n", + atomic_read(&sdp->sd_depend_count)); + gfs_printf("sd_reclaim_count:glocks on reclaim list::%d\n", + atomic_read(&sdp->sd_reclaim_count)); + gfs_printf("sd_log_wrap:log wraps::%"PRIu64"\n", + sdp->sd_log_wrap); + gfs_printf("sd_lm_outstanding:outstanding LM calls::%d\n", + atomic_read(&sdp->sd_lm_outstanding)); + gfs_printf("sd_bio_outstanding:outstanding BIO calls::%u\n", + atomic_read(&sdp->sd_bio_outstanding)); + gfs_printf("sd_fh2dentry_misses:fh2dentry misses:diff:%u\n", + handle_roll(&sdp->sd_fh2dentry_misses)); + gfs_printf("sd_reclaimed:glocks reclaimed:diff:%u\n", + handle_roll(&sdp->sd_reclaimed)); + gfs_printf("sd_glock_nq_calls:glock nq calls:diff:%u\n", + handle_roll(&sdp->sd_glock_nq_calls)); + gfs_printf("sd_glock_dq_calls:glock dq calls:diff:%u\n", + handle_roll(&sdp->sd_glock_dq_calls)); + gfs_printf("sd_glock_prefetch_calls:glock prefetch calls:diff:%u\n", + handle_roll(&sdp->sd_glock_prefetch_calls)); + gfs_printf("sd_lm_lock_calls:lm_lock calls:diff:%u\n", + handle_roll(&sdp->sd_lm_lock_calls)); + gfs_printf("sd_lm_unlock_calls:lm_unlock calls:diff:%u\n", + handle_roll(&sdp->sd_lm_unlock_calls)); + gfs_printf("sd_lm_callbacks:lm callbacks:diff:%u\n", + handle_roll(&sdp->sd_lm_callbacks)); + gfs_printf("sd_ops_address:address operations:diff:%u\n", + handle_roll(&sdp->sd_ops_address)); + gfs_printf("sd_ops_dentry:dentry operations:diff:%u\n", + handle_roll(&sdp->sd_ops_dentry)); + gfs_printf("sd_ops_export:export operations:diff:%u\n", + handle_roll(&sdp->sd_ops_export)); + gfs_printf("sd_ops_file:file operations:diff:%u\n", + handle_roll(&sdp->sd_ops_file)); + gfs_printf("sd_ops_inode:inode operations:diff:%u\n", + handle_roll(&sdp->sd_ops_inode)); + gfs_printf("sd_ops_super:super operations:diff:%u\n", + handle_roll(&sdp->sd_ops_super)); + gfs_printf("sd_ops_vm:vm operations:diff:%u\n", + handle_roll(&sdp->sd_ops_vm)); + gfs_printf("sd_bio_reads:block I/O reads:diff:%u\n", + handle_roll(&sdp->sd_bio_reads) >> + (sdp->sd_sb.sb_bsize_shift - 9)); + gfs_printf("sd_bio_writes:block I/O writes:diff:%u\n", + handle_roll(&sdp->sd_bio_writes) >> + (sdp->sd_sb.sb_bsize_shift - 9)); + + error = 0; + + out: + return error; +} + +/** + * gi_get_tune - Return current values of the tuneable parameters + * @ip: + * @gi: + * @buf: + * @size: + * @count: + * + * Returns: errno + */ + +static int +gi_get_tune(struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count) +{ + struct gfs_tune *gt = &ip->i_sbd->sd_tune; + int error = -ENOBUFS; + + if (gi->gi_argc != 1) + return -EINVAL; + + spin_lock(>->gt_spin); + + gfs_printf("version 0\n"); + gfs_printf("ilimit1 %u\n", gt->gt_ilimit1); + gfs_printf("ilimit1_tries %u\n", gt->gt_ilimit1_tries); + gfs_printf("ilimit1_min %u\n", gt->gt_ilimit1_min); + gfs_printf("ilimit2 %u\n", gt->gt_ilimit2); + gfs_printf("ilimit2_tries %u\n", gt->gt_ilimit2_tries); + gfs_printf("ilimit2_min %u\n", gt->gt_ilimit2_min); + gfs_printf("demote_secs %u\n", gt->gt_demote_secs); + gfs_printf("incore_log_blocks %u\n", gt->gt_incore_log_blocks); + gfs_printf("jindex_refresh_secs %u\n", gt->gt_jindex_refresh_secs); + gfs_printf("depend_secs %u\n", gt->gt_depend_secs); + gfs_printf("scand_secs %u\n", gt->gt_scand_secs); + gfs_printf("recoverd_secs %u\n", gt->gt_recoverd_secs); + gfs_printf("logd_secs %u\n", gt->gt_logd_secs); + gfs_printf("quotad_secs %u\n", gt->gt_quotad_secs); + gfs_printf("inoded_secs %u\n", gt->gt_inoded_secs); + gfs_printf("glock_purge %u\n", gt->gt_glock_purge); + gfs_printf("quota_simul_sync %u\n", gt->gt_quota_simul_sync); + gfs_printf("quota_warn_period %u\n", gt->gt_quota_warn_period); + gfs_printf("atime_quantum %u\n", gt->gt_atime_quantum); + gfs_printf("quota_quantum %u\n", gt->gt_quota_quantum); + gfs_printf("quota_scale_num %u\n", gt->gt_quota_scale_num); + gfs_printf("quota_scale_den %u\n", gt->gt_quota_scale_den); + gfs_printf("quota_enforce %u\n", gt->gt_quota_enforce); + gfs_printf("quota_account %u\n", gt->gt_quota_account); + gfs_printf("new_files_jdata %u\n", gt->gt_new_files_jdata); + gfs_printf("new_files_directio %u\n", gt->gt_new_files_directio); + gfs_printf("max_atomic_write %u\n", gt->gt_max_atomic_write); + gfs_printf("max_readahead %u\n", gt->gt_max_readahead); + gfs_printf("lockdump_size %u\n", gt->gt_lockdump_size); + gfs_printf("stall_secs %u\n", gt->gt_stall_secs); + gfs_printf("complain_secs %u\n", gt->gt_complain_secs); + gfs_printf("reclaim_limit %u\n", gt->gt_reclaim_limit); + gfs_printf("entries_per_readdir %u\n", gt->gt_entries_per_readdir); + gfs_printf("prefetch_secs %u\n", gt->gt_prefetch_secs); + gfs_printf("statfs_slots %u\n", gt->gt_statfs_slots); + gfs_printf("max_mhc %u\n", gt->gt_max_mhc); + gfs_printf("greedy_default %u\n", gt->gt_greedy_default); + gfs_printf("greedy_quantum %u\n", gt->gt_greedy_quantum); + gfs_printf("greedy_max %u\n", gt->gt_greedy_max); + gfs_printf("rgrp_try_threshold %u\n", gt->gt_rgrp_try_threshold); + gfs_printf("statfs_fast %u\n", gt->gt_statfs_fast); + + error = 0; + + out: + spin_unlock(>->gt_spin); + + return error; +} + +#define tune_set(f, v) \ +do { \ + spin_lock(>->gt_spin); \ + gt->f = (v); \ + spin_unlock(>->gt_spin); \ +} while (0) + +/** + * gi_set_tune - Set a tuneable parameter + * @sdp: + * @gi: + * + * Returns: errno + */ + +static int +gi_set_tune(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + struct gfs_tune *gt = &sdp->sd_tune; + char param[ARG_SIZE], value[ARG_SIZE]; + unsigned int x; + int error; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (gi->gi_argc != 3) + return -EINVAL; + + if (from_user) { + if (strncpy_from_user(param, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(param, gi->gi_argv[1], ARG_SIZE); + } + param[ARG_SIZE - 1] = 0; + + if (from_user) { + if (strncpy_from_user(value, gi->gi_argv[2], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(value, gi->gi_argv[2], ARG_SIZE); + } + + value[ARG_SIZE - 1] = 0; + + if (strcmp(param, "ilimit1") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_ilimit1, x); + + } else if (strcmp(param, "ilimit1_tries") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_ilimit1_tries, x); + + } else if (strcmp(param, "ilimit1_min") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_ilimit1_min, x); + + } else if (strcmp(param, "ilimit2") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_ilimit2, x); + + } else if (strcmp(param, "ilimit2_tries") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_ilimit2_tries, x); + + } else if (strcmp(param, "ilimit2_min") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_ilimit2_min, x); + + } else if (strcmp(param, "demote_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_demote_secs, x); + + } else if (strcmp(param, "incore_log_blocks") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_incore_log_blocks, x); + + } else if (strcmp(param, "jindex_refresh_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_jindex_refresh_secs, x); + + } else if (strcmp(param, "depend_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_depend_secs, x); + + } else if (strcmp(param, "scand_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_scand_secs, x); + wake_up_process(sdp->sd_scand_process); + + } else if (strcmp(param, "recoverd_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_recoverd_secs, x); + wake_up_process(sdp->sd_recoverd_process); + + } else if (strcmp(param, "logd_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_logd_secs, x); + wake_up_process(sdp->sd_logd_process); + + } else if (strcmp(param, "quotad_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_quotad_secs, x); + wake_up_process(sdp->sd_quotad_process); + + } else if (strcmp(param, "inoded_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_inoded_secs, x); + wake_up_process(sdp->sd_inoded_process); + + } else if (strcmp(param, "glock_purge") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_glock_purge, x); + + } else if (strcmp(param, "quota_simul_sync") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_quota_simul_sync, x); + + } else if (strcmp(param, "quota_warn_period") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_quota_warn_period, x); + + } else if (strcmp(param, "atime_quantum") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_atime_quantum, x); + + } else if (strcmp(param, "quota_quantum") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_quota_quantum, x); + + } else if (strcmp(param, "quota_scale") == 0) { + unsigned int y; + if (sscanf(value, "%u %u", &x, &y) != 2 || !y) + return -EINVAL; + spin_lock(>->gt_spin); + gt->gt_quota_scale_num = x; + gt->gt_quota_scale_den = y; + spin_unlock(>->gt_spin); + + } else if (strcmp(param, "quota_enforce") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + x = !!x; + spin_lock(>->gt_spin); + gt->gt_quota_enforce = x; + if (x) + gt->gt_quota_account = 1; + spin_unlock(>->gt_spin); + + } else if (strcmp(param, "quota_account") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + x = !!x; + spin_lock(>->gt_spin); + gt->gt_quota_account = x; + if (x) + spin_unlock(>->gt_spin); + else { + unsigned int y; + gt->gt_quota_enforce = 0; + spin_unlock(>->gt_spin); + for (y = 0; y < 2; y++) { + gfs_log_flush(sdp); + gfs_sync_meta(sdp); + gfs_quota_sync(sdp); + } + } + + } else if (strcmp(param, "new_files_jdata") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + x = !!x; + tune_set(gt_new_files_jdata, x); + + } else if (strcmp(param, "new_files_directio") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + x = !!x; + tune_set(gt_new_files_directio, x); + + } else if (strcmp(param, "max_atomic_write") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_max_atomic_write, x); + + } else if (strcmp(param, "max_readahead") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_max_readahead, x); + + } else if (strcmp(param, "lockdump_size") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_lockdump_size, x); + + } else if (strcmp(param, "stall_secs") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_stall_secs, x); + + } else if (strcmp(param, "complain_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_complain_secs, x); + + } else if (strcmp(param, "reclaim_limit") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_reclaim_limit, x); + + } else if (strcmp(param, "entries_per_readdir") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_entries_per_readdir, x); + + } else if (strcmp(param, "prefetch_secs") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_prefetch_secs, x); + + } else if (strcmp(param, "statfs_slots") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_statfs_slots, x); + + } else if (strcmp(param, "max_mhc") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_max_mhc, x); + + } else if (strcmp(param, "greedy_default") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_greedy_default, x); + + } else if (strcmp(param, "greedy_quantum") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_greedy_quantum, x); + + } else if (strcmp(param, "greedy_max") == 0) { + if (sscanf(value, "%u", &x) != 1 || !x) + return -EINVAL; + tune_set(gt_greedy_max, x); + + } else if (strcmp(param, "rgrp_try_threshold") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + tune_set(gt_rgrp_try_threshold, x); + + } else if (strcmp(param, "statfs_fast") == 0) { + if (sscanf(value, "%u", &x) != 1) + return -EINVAL; + error = gfs_statfs_init(sdp, x); + if (error) + return error; + else + tune_set(gt_statfs_fast, x); + + + } else + return -EINVAL; + + return 0; +} + +/** + * gi_do_reclaim - Reclaim unused metadata + * @ip: + * @gi: + * @buf: + * @size: + * @count: + * + * Returns: errno + */ + +static int +gi_do_reclaim(struct gfs_inode *ip, + struct gfs_ioctl *gi, + char *buf, + unsigned int size, + unsigned int *count) +{ + uint64_t inodes, metadata; + int error; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (gi->gi_argc != 1) + return -EINVAL; + + error = gfs_reclaim_metadata(ip->i_sbd, + &inodes, + &metadata); + if (error) + return error; + + error = -ENOBUFS; + + gfs_printf("version 0\n"); + gfs_printf("inodes %"PRIu64"\n", inodes); + gfs_printf("metadata %"PRIu64"\n", metadata); + + error = 0; + + out: + return error; +} + +/** + * gi_do_shrink - throw out unused glocks + * @sdp: + * @gi: + * + * Returns: 0 + */ + +static int +gi_do_shrink(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (gi->gi_argc != 1) + return -EINVAL; + gfs_gl_hash_clear(sdp, FALSE); + return 0; +} + +/** + * gi_get_file_stat - + * @ip: + * @gi: + * + * Returns: the number of bytes copied, or -errno + */ + +static int +gi_get_file_stat(struct gfs_inode *ip, struct gfs_ioctl *gi) +{ + struct gfs_holder i_gh; + struct gfs_dinode *di; + int error; + + if (gi->gi_argc != 1) + return -EINVAL; + if (gi->gi_size != sizeof(struct gfs_dinode)) + return -EINVAL; + + di = kmalloc(sizeof(struct gfs_dinode), GFP_KERNEL); + if (!di) + return -ENOMEM; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + if (error) + goto out; + memcpy(di, &ip->i_di, sizeof(struct gfs_dinode)); + gfs_glock_dq_uninit(&i_gh); + + if (copy_to_user(gi->gi_data, di, + sizeof(struct gfs_dinode))) + error = -EFAULT; + else + error = sizeof(struct gfs_dinode); + + out: + kfree(di); + + return error; +} + +/** + * gi_set_file_flag - set or clear a flag on a file + * @ip: + * @gi: + * + * Returns: errno + */ + +static int +gi_set_file_flag(struct gfs_inode *ip, struct gfs_ioctl *gi, int from_user) +{ + char buf[ARG_SIZE]; + int set; + uint32_t flag; + struct gfs_holder i_gh; + struct buffer_head *dibh; + int error; + + if (gi->gi_argc != 3) + return -EINVAL; + + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } + buf[ARG_SIZE - 1] = 0; + + if (strcmp(buf, "set") == 0) + set = TRUE; + else if (strcmp(buf, "clear") == 0) + set = FALSE; + else + return -EINVAL; + + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[2], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[2], ARG_SIZE); + } + buf[ARG_SIZE - 1] = 0; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + if (error) + return error; + + error = -EACCES; + if (ip->i_di.di_uid != current->fsuid && !capable(CAP_FOWNER)) + goto out; + + error = -EINVAL; + + if (strcmp(buf, "jdata") == 0) { + if (ip->i_di.di_type != GFS_FILE_REG || + ip->i_di.di_size) + goto out; + flag = GFS_DIF_JDATA; + } else if (strcmp(buf, "directio") == 0) { + if (ip->i_di.di_type != GFS_FILE_REG) + goto out; + flag = GFS_DIF_DIRECTIO; + } else if (strcmp(buf, "immutable") == 0) { + /* The IMMUTABLE flag can only be changed by + the relevant capability. */ + error = -EPERM; + if (!capable(CAP_LINUX_IMMUTABLE)) + goto out; + flag = GFS_DIF_IMMUTABLE; + } else if (strcmp(buf, "appendonly") == 0) { + /* The APPENDONLY flag can only be changed by + the relevant capability. */ + error = -EPERM; + if (!capable(CAP_LINUX_IMMUTABLE)) + goto out; + flag = GFS_DIF_APPENDONLY; + } else if (strcmp(buf, "inherit_jdata") == 0) { + if (ip->i_di.di_type != GFS_FILE_DIR) + goto out; + flag = GFS_DIF_INHERIT_JDATA; + } else if (strcmp(buf, "inherit_directio") == 0) { + if (ip->i_di.di_type != GFS_FILE_DIR) + goto out; + flag = GFS_DIF_INHERIT_DIRECTIO; + } else + goto out; + + error = gfs_trans_begin(ip->i_sbd, 1, 0); + if (error) + goto out; + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto out_trans_end; + + if (set) + ip->i_di.di_flags |= flag; + else + ip->i_di.di_flags &= ~flag; + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + + brelse(dibh); + + out_trans_end: + gfs_trans_end(ip->i_sbd); + + out: + gfs_glock_dq_uninit(&i_gh); + + return error; + +} + +/** + * gi_get_file_meta - Return all the metadata for a file + * @ip: + * @gi: + * + * Returns: the number of bytes copied, or -errno + */ + +static int +gi_get_file_meta(struct gfs_inode *ip, struct gfs_ioctl *gi) +{ + struct gfs_holder i_gh; + struct gfs_user_buffer ub; + int error; + + if (gi->gi_argc != 1) + return -EINVAL; + + ub.ub_data = gi->gi_data; + ub.ub_size = gi->gi_size; + ub.ub_count = 0; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + if (error) + return error; + + error = -EACCES; + if (ip->i_di.di_uid != current->fsuid && !capable(CAP_FOWNER)) + goto out; + + error = gfs_get_file_meta(ip, &ub); + if (error) + goto out; + + if (ip->i_di.di_type == GFS_FILE_DIR && + (ip->i_di.di_flags & GFS_DIF_EXHASH)) { + error = gfs_get_dir_meta(ip, &ub); + if (error) + goto out; + } + + if (ip->i_di.di_eattr) { + error = gfs_get_eattr_meta(ip, &ub); + if (error) + goto out; + } + + error = ub.ub_count; + + out: + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gi_do_file_flush - sync out all dirty data and + * drop the cache (and lock) for a file. + * @ip: + * @gi: + * + * Returns: errno + */ + +static int +gi_do_file_flush(struct gfs_inode *ip, struct gfs_ioctl *gi) +{ + if (gi->gi_argc != 1) + return -EINVAL; + gfs_glock_force_drop(ip->i_gl); + return 0; +} + +/** + * gi2hip - return the "struct gfs_inode" for a hidden file + * @sdp: + * @gi: + * + * Returns: the "struct gfs_inode" + */ + +static struct gfs_inode * +gi2hip(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + char buf[ARG_SIZE]; + + if (gi->gi_argc != 2) + return ERR_PTR(-EINVAL); + + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return ERR_PTR(-EFAULT); + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } + buf[ARG_SIZE - 1] = 0; + + if (strcmp(buf, "jindex") == 0) + return sdp->sd_jiinode; + else if (strcmp(buf, "rindex") == 0) + return sdp->sd_riinode; + else if (strcmp(buf, "quota") == 0) + return sdp->sd_qinode; + else if (strcmp(buf, "license") == 0) + return sdp->sd_linode; + else + return ERR_PTR(-EINVAL); +} + +/** + * gi_get_hfile_stat - get stat info on a hidden file + * @sdp: + * @gi: + * + * Returns: the number of bytes copied, or -errno + */ + +static int +gi_get_hfile_stat(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + struct gfs_inode *ip; + struct gfs_dinode *di; + struct gfs_holder i_gh; + int error; + + ip = gi2hip(sdp, gi, from_user); + if (IS_ERR(ip)) + return PTR_ERR(ip); + + if (gi->gi_size != sizeof(struct gfs_dinode)) + return -EINVAL; + + di = kmalloc(sizeof(struct gfs_dinode), GFP_KERNEL); + if (!di) + return -ENOMEM; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + if (error) + goto out; + memcpy(di, &ip->i_di, sizeof(struct gfs_dinode)); + gfs_glock_dq_uninit(&i_gh); + + if (copy_to_user(gi->gi_data, di, + sizeof(struct gfs_dinode))) + error = -EFAULT; + else + error = sizeof(struct gfs_dinode); + + out: + kfree(di); + + return error; +} + +/** + * gi_do_hfile_read - Read data from a hidden file + * @sdp: + * @gi: + * + * Returns: the number of bytes read, or -errno + */ + +static int +gi_do_hfile_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + struct gfs_inode *ip; + struct gfs_holder i_gh; + int error; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + ip = gi2hip(sdp, gi, from_user); + if (IS_ERR(ip)) + return PTR_ERR(ip); + + if (!access_ok(VERIFY_WRITE, gi->gi_data, gi->gi_size)) + return -EFAULT; + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + if (error) + return error; + + error = gfs_readi(ip, gi->gi_data, gi->gi_offset, gi->gi_size, + gfs_copy2user); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gi_do_hfile_write - Write data to a hidden file + * @sdp: + * @gi: + * + * Returns: the number of bytes written, or -errno + */ + +static int +gi_do_hfile_write(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + struct gfs_inode *ip; + struct gfs_alloc *al = NULL; + struct gfs_holder i_gh; + unsigned int data_blocks, ind_blocks; + int alloc_required; + int error; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + ip = gi2hip(sdp, gi, from_user); + if (IS_ERR(ip)) + return PTR_ERR(ip); + + if (!access_ok(VERIFY_READ, gi->gi_data, gi->gi_size)) + return -EFAULT; + + gfs_write_calc_reserv(ip, gi->gi_size, &data_blocks, &ind_blocks); + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, + LM_FLAG_PRIORITY | GL_SYNC | GL_NOCANCEL_OTHER, + &i_gh); + if (error) + return error; + + if (!gfs_is_jdata(ip)) { + gfs_consist_inode(ip); + error = -EIO; + goto out; + } + + error = gfs_write_alloc_required(ip, gi->gi_offset, gi->gi_size, + &alloc_required); + if (error) + goto out; + + if (alloc_required) { + al = gfs_alloc_get(ip); + + error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, + NO_QUOTA_CHANGE); + if (error) + goto out_alloc; + + al->al_requested_meta = ind_blocks + data_blocks; + + error = gfs_inplace_reserve(ip); + if (error) + goto out_qs; + + /* Trans may require: + All blocks for a RG bitmap, all the "data" blocks, whatever + indirect blocks we need, a modified dinode, and a quota change */ + + error = gfs_trans_begin(sdp, + 1 + al->al_rgd->rd_ri.ri_length + + ind_blocks + data_blocks, 1); + if (error) + goto out_relse; + } else { + /* Trans may require: + All the "data" blocks and a modified dinode. */ + + error = gfs_trans_begin(sdp, 1 + data_blocks, 0); + if (error) + goto out_relse; + } + + if (from_user) + error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size, + gfs_copy_from_user, NULL); + else + error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size, + gfs_copy_from_mem, NULL); + + gfs_trans_end(sdp); + + out_relse: + if (alloc_required) { + gfs_assert_warn(sdp, error || al->al_alloced_meta); + gfs_inplace_release(ip); + } + + out_qs: + if (alloc_required) + gfs_quota_unhold_m(ip); + + out_alloc: + if (alloc_required) + gfs_alloc_put(ip); + + out: + ip->i_gl->gl_vn++; + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gi_do_hfile_trunc - truncate a hidden file + * @sdp: + * @gi: + * + * Returns: the number of bytes copied, or -errno + */ + +static int +gi_do_hfile_trunc(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + struct gfs_inode *ip; + struct gfs_holder i_gh; + int error; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + ip = gi2hip(sdp, gi, from_user); + if (IS_ERR(ip)) + return PTR_ERR(ip); + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SYNC, &i_gh); + if (error) + return error; + + error = gfs_truncatei(ip, gi->gi_offset, NULL); + + ip->i_gl->gl_vn++; + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gi_do_quota_sync - sync the outstanding quota changes for a FS + * @sdp: + * @gi: + * + * Returns: errno + */ + +static int +gi_do_quota_sync(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (gi->gi_argc != 1) + return -EINVAL; + return gfs_quota_sync(sdp); +} + +/** + * gi_do_quota_refresh - Refresh the a quota LVB from the quota file + * @sdp: + * @gi: + * + * Returns: errno + */ + +static int +gi_do_quota_refresh(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + char buf[ARG_SIZE]; + int user; + uint32_t id; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (gi->gi_argc != 2) + return -EINVAL; + + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } + buf[ARG_SIZE - 1] = 0; + + switch (buf[0]) { + case 'u': + user = TRUE; + break; + case 'g': + user = FALSE; + break; + default: + return -EINVAL; + } + + if (buf[1] != ':') + return -EINVAL; + + if (sscanf(buf + 2, "%u", &id) != 1) + return -EINVAL; + + return gfs_quota_refresh(sdp, user, id); +} + +/** + * gi_do_quota_read - read quota values from the quota file + * @sdp: + * @gi: + * + * Returns: errno + */ + +static int +gi_do_quota_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) +{ + char buf[ARG_SIZE]; + int user; + uint32_t id; + struct gfs_quota q; + int error; + + if (gi->gi_argc != 2) + return -EINVAL; + if (gi->gi_size != sizeof(struct gfs_quota)) + return -EINVAL; + + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } + buf[ARG_SIZE - 1] = 0; + + switch (buf[0]) { + case 'u': + user = TRUE; + break; + case 'g': + user = FALSE; + break; + default: + return -EINVAL; + } + + if (buf[1] != ':') + return -EINVAL; + + if (sscanf(buf + 2, "%u", &id) != 1) + return -EINVAL; + + error = gfs_quota_read(sdp, user, id, &q); + if (error) + return error; + + if (copy_to_user(gi->gi_data, &q, sizeof(struct gfs_quota))) + return -EFAULT; + + return 0; +} + +int +gfs_ioctl_i_local(struct gfs_inode *ip, struct gfs_ioctl *gi, const char *arg0, + int from_user) +{ + int error = -EFAULT; + + if (strcmp(arg0, "get_cookie") == 0) + error = gi_skeleton(ip, gi, gi_get_cookie); + else if (strcmp(arg0, "get_super") == 0) + error = gi_get_super(ip->i_sbd, gi); + else if (strcmp(arg0, "get_args") == 0) + error = gi_skeleton(ip, gi, gi_get_args); + else if (strcmp(arg0, "get_lockstruct") == 0) + error = gi_skeleton(ip, gi, gi_get_lockstruct); + else if (strcmp(arg0, "get_stat_gfs") == 0) + error = gi_skeleton(ip, gi, gi_get_stat_gfs); + else if (strcmp(arg0, "get_counters") == 0) + error = gi_skeleton(ip, gi, gi_get_counters); + else if (strcmp(arg0, "get_tune") == 0) + error = gi_skeleton(ip, gi, gi_get_tune); + else if (strcmp(arg0, "set_tune") == 0) + error = gi_set_tune(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_reclaim") == 0) + error = gi_skeleton(ip, gi, gi_do_reclaim); + else if (strcmp(arg0, "do_shrink") == 0) + error = gi_do_shrink(ip->i_sbd, gi); + else if (strcmp(arg0, "get_file_stat") == 0) + error = gi_get_file_stat(ip, gi); + else if (strcmp(arg0, "set_file_flag") == 0) + error = gi_set_file_flag(ip, gi, from_user); + else if (strcmp(arg0, "get_file_meta") == 0) + error = gi_get_file_meta(ip, gi); + else if (strcmp(arg0, "get_file_meta_quota") == 0) + error = gi_get_file_meta(ip->i_sbd->sd_qinode, gi); + else if (strcmp(arg0, "do_file_flush") == 0) + error = gi_do_file_flush(ip, gi); + else if (strcmp(arg0, "get_hfile_stat") == 0) + error = gi_get_hfile_stat(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_hfile_read") == 0) + error = gi_do_hfile_read(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_hfile_write") == 0) + error = gi_do_hfile_write(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_hfile_trunc") == 0) + error = gi_do_hfile_trunc(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_quota_sync") == 0) + error = gi_do_quota_sync(ip->i_sbd, gi); + else if (strcmp(arg0, "do_quota_refresh") == 0) + error = gi_do_quota_refresh(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_quota_read") == 0) + error = gi_do_quota_read(ip->i_sbd, gi, from_user); + else + error = -ENOTTY; + + return error; +} + +/** + * gfs_ioctl_i - Normal ioctls + * @ip: + * @arg: + * + * Returns: -errno or positive byte count + */ + +int +gfs_ioctl_i(struct gfs_inode *ip, void *arg) +{ + struct gfs_ioctl *gi_user = (struct gfs_ioctl *)arg; + struct gfs_ioctl gi; + char **argv; + char arg0[ARG_SIZE]; + int error = -EFAULT; + + if (copy_from_user(&gi, gi_user, sizeof(struct gfs_ioctl))) + return -EFAULT; + if (!gi.gi_argc) + return -EINVAL; + argv = kmalloc(gi.gi_argc * sizeof(char *), GFP_KERNEL); + if (!argv) + return -ENOMEM; + if (copy_from_user(argv, gi.gi_argv, + gi.gi_argc * sizeof(char *))) + goto out; + gi.gi_argv = argv; + + if (strncpy_from_user(arg0, argv[0], ARG_SIZE) < 0) + goto out; + arg0[ARG_SIZE - 1] = 0; + error = gfs_ioctl_i_local(ip, &gi, arg0, 1); + out: + kfree(argv); + + return error; +} + +#ifdef CONFIG_COMPAT +/** + * gfs_ioctl_i_compat - compatibility ioctls + * These ioctls are used to provide ioctls for situations + * where userland and kernel arch is different. + * For example, userland may be 32-bit ppc whereas the + * kernel may be ppc64. In this case, we need to do + * extra translation between the addresses. + * @ip: + * @arg: + * + * Returns: -errno or positive byte count + */ + +int +gfs_ioctl_i_compat(struct gfs_inode *ip, unsigned long arg) +{ + struct gfs_ioctl_compat *src; + struct gfs_ioctl dst; + char **argv, *argptr; + uint32_t *ptr; + char arg0[ARG_SIZE]; + char *tmparg; + int i; + int error = -EFAULT; + + src = (struct gfs_ioctl_compat *)compat_ptr(arg); + + memset(&dst, 0, sizeof(dst)); + dst.gi_argc = src->gi_argc; + dst.gi_size = src->gi_size; + dst.gi_offset = src->gi_offset; + + argv = kmalloc(dst.gi_argc * sizeof(char *), GFP_KERNEL); + if (!argv) + return -ENOMEM; + + memset(argv, 0, dst.gi_argc * sizeof(char *)); + ptr = (uint32_t *)compat_ptr(src->gi_argv); + + for (i = 0; i < dst.gi_argc; i++) { /* for each parm */ + tmparg = kmalloc(ARG_SIZE * sizeof(char *), GFP_KERNEL); + if (!tmparg) + goto out; + argptr = (char *)compat_ptr(*ptr); + if (strncpy_from_user(tmparg, argptr, ARG_SIZE) < 0) + goto out; + argv[i] = tmparg; + ptr++; + } + + strncpy(arg0, argv[0], ARG_SIZE); + arg0[ARG_SIZE - 1] = 0; + dst.gi_argv = argv; + dst.gi_data = compat_ptr(src->gi_data); + error = gfs_ioctl_i_local(ip, &dst, arg0, 0); + out: + for (i = 0; i < dst.gi_argc; i++) + kfree(argv[i]); + kfree(argv); + return error; +} +#endif --- linux-2.6.27.orig/ubuntu/gfs/Makefile +++ linux-2.6.27/ubuntu/gfs/Makefile @@ -0,0 +1,46 @@ +obj-$(CONFIG_GFS_FS) += gfs.o +gfs-objs := acl.o \ + bits.o \ + bmap.o \ + daemon.o \ + dio.o \ + dir.o \ + eaops.o \ + eattr.o \ + file.o \ + glock.o \ + glops.o \ + inode.o \ + ioctl.o \ + lm.o \ + locking.o \ + lock_nolock_main.o \ + lock_dlm_lock.o \ + lock_dlm_main.o \ + lock_dlm_mount.o \ + lock_dlm_sysfs.o \ + lock_dlm_thread.o \ + log.o \ + lops.o \ + lvb.o \ + main.o \ + mount.o \ + ondisk.o \ + ops_address.o \ + ops_dentry.o \ + ops_export.o \ + ops_file.o \ + ops_fstype.o \ + ops_inode.o \ + ops_super.o \ + ops_vm.o \ + page.o \ + proc.o \ + quota.o \ + recovery.o \ + rgrp.o \ + super.o \ + sys.o \ + trans.o \ + unlinked.o \ + util.o --- linux-2.6.27.orig/ubuntu/gfs/dir.h +++ linux-2.6.27/ubuntu/gfs/dir.h @@ -0,0 +1,42 @@ +#ifndef __DIR_DOT_H__ +#define __DIR_DOT_H__ + +/** + * gfs_filldir_t - Report a directory entry to the caller of gfs_dir_read() + * @opaque: opaque data used by the function + * @name: the name of the directory entry + * @length: the length of the name + * @offset: the entry's offset in the directory + * @inum: the inode number the entry points to + * @type: the type of inode the entry points to + * + * Returns: 0 on success, 1 if buffer full + */ + +typedef int (*gfs_filldir_t) (void *opaque, + const char *name, unsigned int length, + uint64_t offset, + struct gfs_inum *inum, unsigned int type); + +int gfs_filecmp(struct qstr *file1, char *file2, int len_of_file2); +int gfs_dirent_alloc(struct gfs_inode *dip, struct buffer_head *bh, + int name_len, struct gfs_dirent **dent_out); + +int gfs_dir_search(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int *type); +int gfs_dir_add(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *inum, unsigned int type); +int gfs_dir_del(struct gfs_inode *dip, struct qstr *filename); +int gfs_dir_read(struct gfs_inode *dip, uint64_t * offset, void *opaque, + gfs_filldir_t filldir); +int gfs_dir_mvino(struct gfs_inode *dip, struct qstr *filename, + struct gfs_inum *new_inum, unsigned int new_type); + +int gfs_dir_exhash_free(struct gfs_inode *dip); + +int gfs_diradd_alloc_required(struct gfs_inode *dip, struct qstr *filename, + int *alloc_required); + +int gfs_get_dir_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub); + +#endif /* __DIR_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/locking.c +++ linux-2.6.27/ubuntu/gfs/locking.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lm_interface.h" + +struct lmh_wrapper { + struct list_head lw_list; + const struct lm_lockops *lw_ops; +}; + +/* List of registered low-level locking protocols. A file system selects one + of them by name at mount time, e.g. lock_nolock, lock_dlm. */ + +static LIST_HEAD(lmh_list); +static DEFINE_MUTEX(lmh_lock); + +/** + * gfs_register_lockproto - Register a low-level locking protocol + * @proto: the protocol definition + * + * Returns: 0 on success, -EXXX on failure + */ + +int gfs_register_lockproto(const struct lm_lockops *proto) +{ + struct lmh_wrapper *lw; + + mutex_lock(&lmh_lock); + + list_for_each_entry(lw, &lmh_list, lw_list) { + if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) { + mutex_unlock(&lmh_lock); + printk(KERN_INFO "GFS2: protocol %s already exists\n", + proto->lm_proto_name); + return -EEXIST; + } + } + + lw = kzalloc(sizeof(struct lmh_wrapper), GFP_KERNEL); + if (!lw) { + mutex_unlock(&lmh_lock); + return -ENOMEM; + } + + lw->lw_ops = proto; + list_add(&lw->lw_list, &lmh_list); + + mutex_unlock(&lmh_lock); + + return 0; +} + +/** + * gfs_unregister_lockproto - Unregister a low-level locking protocol + * @proto: the protocol definition + * + */ + +void gfs_unregister_lockproto(const struct lm_lockops *proto) +{ + struct lmh_wrapper *lw; + + mutex_lock(&lmh_lock); + + list_for_each_entry(lw, &lmh_list, lw_list) { + if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) { + list_del(&lw->lw_list); + mutex_unlock(&lmh_lock); + kfree(lw); + return; + } + } + + mutex_unlock(&lmh_lock); + + printk(KERN_WARNING "GFS2: can't unregister lock protocol %s\n", + proto->lm_proto_name); +} + +/** + * gfs_mount_lockproto - Mount a lock protocol + * @proto_name - the name of the protocol + * @table_name - the name of the lock space + * @host_data - data specific to this host + * @cb - the callback to the code using the lock module + * @sdp - The GFS2 superblock + * @min_lvb_size - the mininum LVB size that the caller can deal with + * @flags - LM_MFLAG_* + * @lockstruct - a structure returned describing the mount + * + * Returns: 0 on success, -EXXX on failure + */ + +int gfs_mount_lockproto(char *proto_name, char *table_name, char *host_data, + lm_callback_t cb, void *cb_data, + unsigned int min_lvb_size, int flags, + struct lm_lockstruct *lockstruct, + struct kobject *fskobj) +{ + struct lmh_wrapper *lw = NULL; + int try = 0; + int error, found; + +retry: + mutex_lock(&lmh_lock); + + found = 0; + list_for_each_entry(lw, &lmh_list, lw_list) { + if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) { + found = 1; + break; + } + } + + if (!found) { + if (!try && capable(CAP_SYS_MODULE)) { + try = 1; + mutex_unlock(&lmh_lock); + request_module(proto_name); + goto retry; + } + printk(KERN_INFO "GFS2: can't find protocol %s\n", proto_name); + error = -ENOENT; + goto out; + } + + if (!try_module_get(lw->lw_ops->lm_owner)) { + try = 0; + mutex_unlock(&lmh_lock); + msleep(1000); + goto retry; + } + + error = lw->lw_ops->lm_mount(table_name, host_data, cb, cb_data, + min_lvb_size, flags, lockstruct, fskobj); + if (error) + module_put(lw->lw_ops->lm_owner); +out: + mutex_unlock(&lmh_lock); + return error; +} + +void gfs_unmount_lockproto(struct lm_lockstruct *lockstruct) +{ + mutex_lock(&lmh_lock); + lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace); + if (lockstruct->ls_ops->lm_owner) + module_put(lockstruct->ls_ops->lm_owner); + mutex_unlock(&lmh_lock); +} + +/** + * gfs_withdraw_lockproto - abnormally unmount a lock module + * @lockstruct: the lockstruct passed into mount + * + */ + +void gfs_withdraw_lockproto(struct lm_lockstruct *lockstruct) +{ + mutex_lock(&lmh_lock); + lockstruct->ls_ops->lm_withdraw(lockstruct->ls_lockspace); + if (lockstruct->ls_ops->lm_owner) + module_put(lockstruct->ls_ops->lm_owner); + mutex_unlock(&lmh_lock); +} --- linux-2.6.27.orig/ubuntu/gfs/ops_inode.c +++ linux-2.6.27/ubuntu/gfs/ops_inode.c @@ -0,0 +1,1670 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "acl.h" +#include "bmap.h" +#include "dio.h" +#include "dir.h" +#include "eaops.h" +#include "eattr.h" +#include "glock.h" +#include "inode.h" +#include "ops_dentry.h" +#include "ops_inode.h" +#include "page.h" +#include "quota.h" +#include "rgrp.h" +#include "trans.h" +#include "unlinked.h" + +/** + * gfs_security_init - + * @dip: + * @ip: + * + * Returns: errno + */ + +static int +gfs_security_init(struct gfs_inode *dip, struct gfs_inode *ip) +{ + int err; + size_t len; + void *value; + char *name; + struct gfs_ea_request er; + + err = security_inode_init_security(ip->i_vnode, dip->i_vnode, + &name, &value, &len); + + if (err) { + if (err == -EOPNOTSUPP) + return 0; + return err; + } + + memset(&er, 0, sizeof(struct gfs_ea_request)); + + er.er_type = GFS_EATYPE_SECURITY; + er.er_name = name; + er.er_data = value; + er.er_name_len = strlen(name); + er.er_data_len = len; + + err = gfs_ea_set_i(ip, &er); + + kfree(value); + kfree(name); + + return err; +} + +/** + * gfs_create - Create a file + * @dir: The directory in which to create the file + * @dentry: The dentry of the new file + * @mode: The mode of the new file + * + * Returns: errno + */ + +static int +gfs_create(struct inode *dir, struct dentry *dentry, + int mode, struct nameidata *nd) +{ + struct gfs_inode *dip = get_v2ip(dir), *ip; + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_holder d_gh, i_gh; + struct inode *inode; + int new = TRUE; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + gfs_unlinked_limit(sdp); + + gfs_holder_init(dip->i_gl, 0, 0, &d_gh); + + for (;;) { + error = gfs_createi(&d_gh, &dentry->d_name, + GFS_FILE_REG, mode, + &i_gh); + if (!error) + break; + else if (error != -EEXIST || + (nd && (nd->intent.open.flags & O_EXCL))) { + gfs_holder_uninit(&d_gh); + return error; + } + + error = gfs_lookupi(&d_gh, &dentry->d_name, + FALSE, &i_gh); + if (!error) { + if (i_gh.gh_gl) { + new = FALSE; + break; + } + } else { + gfs_holder_uninit(&d_gh); + return error; + } + } + + ip = get_gl2ip(i_gh.gh_gl); + + if (new) { + gfs_trans_end(sdp); + if (dip->i_alloc->al_rgd) + gfs_inplace_release(dip); + gfs_quota_unlock_m(dip); + gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul); + gfs_alloc_put(dip); + } + + inode = gfs_iget(ip, CREATE); + gfs_inode_put(ip); + + if (!inode) + error = -ENOMEM; + else + error = gfs_security_init(dip, ip); + + gfs_glock_dq_uninit(&d_gh); + gfs_glock_dq_uninit(&i_gh); + + if (error) + return error; + + d_instantiate(dentry, inode); + if (new) + mark_inode_dirty(inode); + + return 0; +} + +/** + * lookup_cdpn_sub_at - Maybe lookup a Context Dependent Pathname + * @sdp: the filesystem + * @dentry: the original dentry to lookup + * @new_dentry: the new dentry, if this was a substitutable path. + * + * Returns: the new dentry, a ERR_PTR, or NULL + */ + +static struct dentry * +lookup_cdpn_sub_at(struct gfs_sbd *sdp, struct dentry *dentry) +{ + struct dentry *parent, *new = NULL; + char *buf; + + buf = kmalloc(2 * __NEW_UTS_LEN + 2, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + parent = dget_parent(dentry); + + if (gfs_filecmp(&dentry->d_name, "@hostname", 9)) + new = lookup_one_len(init_utsname()->nodename, + parent, + strlen(init_utsname()->nodename)); + else if (gfs_filecmp(&dentry->d_name, "@mach", 5)) + new = lookup_one_len(init_utsname()->machine, + parent, + strlen(init_utsname()->machine)); + else if (gfs_filecmp(&dentry->d_name, "@os", 3)) + new = lookup_one_len(init_utsname()->sysname, + parent, + strlen(init_utsname()->sysname)); + else if (gfs_filecmp(&dentry->d_name, "@uid", 4)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%u", current->fsuid)); + else if (gfs_filecmp(&dentry->d_name, "@gid", 4)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%u", current->fsgid)); + else if (gfs_filecmp(&dentry->d_name, "@sys", 4)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%s_%s", + init_utsname()->machine, + init_utsname()->sysname)); + else if (gfs_filecmp(&dentry->d_name, "@jid", 4)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%u", + sdp->sd_lockstruct.ls_jid)); + + dput(parent); + kfree(buf); + + return new; +} + +/** + * lookup_cdpn_sub_brace - Maybe lookup a Context Dependent Pathname + * @sdp: the filesystem + * @dentry: the original dentry to lookup + * @new_dentry: the new dentry, if this was a substitutable path. + * + * Returns: the new dentry, a ERR_PTR, or NULL + */ + +static struct dentry * +lookup_cdpn_sub_brace(struct gfs_sbd *sdp, struct dentry *dentry) +{ + struct dentry *parent, *new = NULL; + char *buf; + + buf = kmalloc(2 * __NEW_UTS_LEN + 2, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + parent = dget_parent(dentry); + + if (gfs_filecmp(&dentry->d_name, "{hostname}", 10)) + new = lookup_one_len(init_utsname()->nodename, + parent, + strlen(init_utsname()->nodename)); + else if (gfs_filecmp(&dentry->d_name, "{mach}", 6)) + new = lookup_one_len(init_utsname()->machine, + parent, + strlen(init_utsname()->machine)); + else if (gfs_filecmp(&dentry->d_name, "{os}", 4)) + new = lookup_one_len(init_utsname()->sysname, + parent, + strlen(init_utsname()->sysname)); + else if (gfs_filecmp(&dentry->d_name, "{uid}", 5)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%u", current->fsuid)); + else if (gfs_filecmp(&dentry->d_name, "{gid}", 5)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%u", current->fsgid)); + else if (gfs_filecmp(&dentry->d_name, "{sys}", 5)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%s_%s", + init_utsname()->machine, + init_utsname()->sysname)); + else if (gfs_filecmp(&dentry->d_name, "{jid}", 5)) + new = lookup_one_len(buf, + parent, + sprintf(buf, "%u", + sdp->sd_lockstruct.ls_jid)); + + dput(parent); + kfree(buf); + + return new; +} + +/** + * gfs_lookup - Look up a filename in a directory and return its inode + * @dir: The directory inode + * @dentry: The dentry of the new inode + * @nd: passed from Linux VFS, ignored by us + * + * Called by the VFS layer. Lock dir and call gfs_lookupi() + * + * Returns: errno + */ + +static struct dentry * +gfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +{ + struct gfs_inode *dip = get_v2ip(dir), *ip; + struct gfs_holder d_gh, i_gh; + struct inode *inode = NULL; + int error; + + atomic_inc(&dip->i_sbd->sd_ops_inode); + + /* Do Context Dependent Path Name expansion */ + + if (*dentry->d_name.name == '@' && dentry->d_name.len > 1) { + struct dentry *new_dentry; + new_dentry = lookup_cdpn_sub_at(dip->i_sbd, dentry); + if (new_dentry) + return new_dentry; + } else if (*dentry->d_name.name == '{' && dentry->d_name.len > 2) { + struct dentry *new_dentry; + new_dentry = lookup_cdpn_sub_brace(dip->i_sbd, dentry); + if (new_dentry) + return new_dentry; + } + + dentry->d_op = &gfs_dops; + + gfs_holder_init(dip->i_gl, 0, 0, &d_gh); + + error = gfs_lookupi(&d_gh, &dentry->d_name, FALSE, &i_gh); + if (error) { + gfs_holder_uninit(&d_gh); + return ERR_PTR(error); + } + + if (i_gh.gh_gl) { + ip = get_gl2ip(i_gh.gh_gl); + + inode = gfs_iget(ip, CREATE); + gfs_inode_put(ip); + + gfs_glock_dq_uninit(&d_gh); + gfs_glock_dq_uninit(&i_gh); + + if (!inode) + return ERR_PTR(-ENOMEM); + } else + gfs_holder_uninit(&d_gh); + + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + + return NULL; +} + +/** + * gfs_link - Link to a file + * @old_dentry: The inode to link + * @dir: Add link to this directory + * @dentry: The name of the link + * + * Link the inode in "old_dentry" into the directory "dir" with the + * name in "dentry". + * + * Returns: errno + */ + +static int +gfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) +{ + struct gfs_inode *dip = get_v2ip(dir); + struct gfs_sbd *sdp = dip->i_sbd; + struct inode *inode = old_dentry->d_inode; + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_alloc *al = NULL; + struct gfs_holder ghs[2]; + int alloc_required; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + if (ip->i_di.di_type == GFS_FILE_DIR) + return -EPERM; + + gfs_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]); + gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]); + + error = gfs_glock_nq_m(2, ghs); + if (error) + goto fail; + + error = inode_permission(dir, MAY_WRITE | MAY_EXEC); + if (error) + goto fail_gunlock; + + error = gfs_dir_search(dip, &dentry->d_name, NULL, NULL); + switch (error) { + case -ENOENT: + break; + case 0: + error = -EEXIST; + default: + goto fail_gunlock; + } + + if (!dip->i_di.di_nlink) { + error = -EINVAL; + goto fail_gunlock; + } + if (dip->i_di.di_entries == (uint32_t)-1) { + error = -EFBIG; + goto fail_gunlock; + } + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + error = -EPERM; + goto fail_gunlock; + } + if (!ip->i_di.di_nlink) { + error = -EINVAL; + goto fail_gunlock; + } + if (ip->i_di.di_nlink == (uint32_t)-1) { + error = -EMLINK; + goto fail_gunlock; + } + + error = gfs_diradd_alloc_required(dip, &dentry->d_name, &alloc_required); + if (error) + goto fail_gunlock; + + if (alloc_required) { + al = gfs_alloc_get(dip); + + error = gfs_quota_lock_m(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto fail_alloc; + + error = gfs_quota_check(dip, dip->i_di.di_uid, dip->i_di.di_gid); + if (error) + goto fail_gunlock_q; + + al->al_requested_meta = sdp->sd_max_dirres; + + error = gfs_inplace_reserve(dip); + if (error) + goto fail_gunlock_q; + + /* Trans may require: + two dinode blocks, directory modifications to add an entry, + RG bitmap blocks to allocate from, and quota change */ + + error = gfs_trans_begin(sdp, + 2 + sdp->sd_max_dirres + + al->al_rgd->rd_ri.ri_length, + 1); + if (error) + goto fail_ipres; + } else { + /* Trans may require: + Two dinode blocks and a leaf block. */ + + error = gfs_trans_begin(sdp, 3, 0); + if (error) + goto fail_ipres; + } + + error = gfs_dir_add(dip, &dentry->d_name, &ip->i_num, ip->i_di.di_type); + if (error) + goto fail_end_trans; + + error = gfs_change_nlink(ip, +1); + if (error) + goto fail_end_trans; + + gfs_trans_end(sdp); + + if (alloc_required) { + gfs_assert_warn(sdp, al->al_alloced_meta); + gfs_inplace_release(dip); + gfs_quota_unlock_m(dip); + gfs_alloc_put(dip); + } + + gfs_glock_dq_m(2, ghs); + + gfs_holder_uninit(&ghs[0]); + gfs_holder_uninit(&ghs[1]); + + atomic_inc(&inode->i_count); + + d_instantiate(dentry, inode); + mark_inode_dirty(inode); + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_ipres: + if (alloc_required) + gfs_inplace_release(dip); + + fail_gunlock_q: + if (alloc_required) + gfs_quota_unlock_m(dip); + + fail_alloc: + if (alloc_required) + gfs_alloc_put(dip); + + fail_gunlock: + gfs_glock_dq_m(2, ghs); + + fail: + gfs_holder_uninit(&ghs[0]); + gfs_holder_uninit(&ghs[1]); + + return error; +} + +/** + * gfs_unlink - Unlink a file + * @dir: The inode of the directory containing the file to unlink + * @dentry: The file itself + * + * Unlink a file. Call gfs_unlinki() + * + * Returns: errno + */ + +static int +gfs_unlink(struct inode *dir, struct dentry *dentry) +{ + struct gfs_inode *dip = get_v2ip(dir); + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_inode *ip = get_v2ip(dentry->d_inode); + struct gfs_holder ghs[2]; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + gfs_unlinked_limit(sdp); + + gfs_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]); + gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]); + + error = gfs_glock_nq_m(2, ghs); + if (error) + goto fail; + + error = gfs_unlink_ok(dip, &dentry->d_name, ip); + if (error) + goto fail_gunlock; + + /* Trans may require: + Two dinode blocks and one modified directory leaf block + and one unlinked tag. */ + + error = gfs_trans_begin(sdp, 3, 1); + if (error) + goto fail_gunlock; + + error = gfs_unlinki(dip, &dentry->d_name, ip); + if (error) + goto fail_end_trans; + + gfs_trans_end(sdp); + + gfs_glock_dq_m(2, ghs); + + gfs_holder_uninit(&ghs[0]); + gfs_holder_uninit(&ghs[1]); + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_gunlock: + gfs_glock_dq_m(2, ghs); + + fail: + gfs_holder_uninit(&ghs[0]); + gfs_holder_uninit(&ghs[1]); + + return error; +} + +/** + * gfs_symlink - Create a symlink + * @dir: The directory to create the symlink in + * @dentry: The dentry to put the symlink in + * @symname: The thing which the link points to + * + * Returns: errno + */ + +static int +gfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +{ + struct gfs_inode *dip = get_v2ip(dir), *ip; + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_holder d_gh, i_gh; + struct inode *inode; + struct buffer_head *dibh; + int size; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + gfs_unlinked_limit(sdp); + + /* Must be stuffed with a null terminator for gfs_follow_link() */ + size = strlen(symname); + if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode) - 1) + return -ENAMETOOLONG; + + gfs_holder_init(dip->i_gl, 0, 0, &d_gh); + + error = gfs_createi(&d_gh, &dentry->d_name, + GFS_FILE_LNK, S_IFLNK | S_IRWXUGO, + &i_gh); + if (error) { + gfs_holder_uninit(&d_gh); + return error; + } + + ip = get_gl2ip(i_gh.gh_gl); + + ip->i_di.di_size = size; + + error = gfs_get_inode_buffer(ip, &dibh); + + if (!gfs_assert_withdraw(sdp, !error)) { + gfs_dinode_out(&ip->i_di, dibh->b_data); + memcpy(dibh->b_data + sizeof(struct gfs_dinode), symname, size); + brelse(dibh); + } + + gfs_trans_end(sdp); + if (dip->i_alloc->al_rgd) + gfs_inplace_release(dip); + gfs_quota_unlock_m(dip); + gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul); + gfs_alloc_put(dip); + + inode = gfs_iget(ip, CREATE); + gfs_inode_put(ip); + + error = gfs_security_init(dip, ip); + + gfs_glock_dq_uninit(&d_gh); + gfs_glock_dq_uninit(&i_gh); + + if (error) + return error; + + if (!inode) + return -ENOMEM; + + d_instantiate(dentry, inode); + mark_inode_dirty(inode); + + return 0; +} + +/** + * gfs_mkdir - Make a directory + * @dir: The parent directory of the new one + * @dentry: The dentry of the new directory + * @mode: The mode of the new directory + * + * Returns: errno + */ + +static int +gfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + struct gfs_inode *dip = get_v2ip(dir), *ip; + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_holder d_gh, i_gh; + struct inode *inode; + struct buffer_head *dibh; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + gfs_unlinked_limit(sdp); + + gfs_holder_init(dip->i_gl, 0, 0, &d_gh); + + error = gfs_createi(&d_gh, &dentry->d_name, + GFS_FILE_DIR, S_IFDIR | mode, + &i_gh); + if (error) { + gfs_holder_uninit(&d_gh); + return error; + } + + ip = get_gl2ip(i_gh.gh_gl); + + ip->i_di.di_nlink = 2; + ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode); + ip->i_di.di_flags |= GFS_DIF_JDATA; + ip->i_di.di_payload_format = GFS_FORMAT_DE; + ip->i_di.di_entries = 2; + + error = gfs_get_inode_buffer(ip, &dibh); + + if (!gfs_assert_withdraw(sdp, !error)) { + struct gfs_dinode *di = (struct gfs_dinode *)dibh->b_data; + struct gfs_dirent *dent; + + gfs_dirent_alloc(ip, dibh, 1, &dent); + + dent->de_inum = di->di_num; /* already GFS endian */ + dent->de_hash = gfs_dir_hash(".", 1); + dent->de_hash = cpu_to_gfs32(dent->de_hash); + dent->de_type = cpu_to_gfs16(GFS_FILE_DIR); + memcpy((char *) (dent + 1), ".", 1); + di->di_entries = cpu_to_gfs32(1); + + gfs_dirent_alloc(ip, dibh, 2, &dent); + + gfs_inum_out(&dip->i_num, (char *) &dent->de_inum); + dent->de_hash = gfs_dir_hash("..", 2); + dent->de_hash = cpu_to_gfs32(dent->de_hash); + dent->de_type = cpu_to_gfs16(GFS_FILE_DIR); + memcpy((char *) (dent + 1), "..", 2); + + gfs_dinode_out(&ip->i_di, (char *)di); + + brelse(dibh); + } + + error = gfs_change_nlink(dip, +1); + gfs_assert_withdraw(sdp, !error); /* dip already pinned */ + + gfs_trans_end(sdp); + if (dip->i_alloc->al_rgd) + gfs_inplace_release(dip); + gfs_quota_unlock_m(dip); + gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul); + gfs_alloc_put(dip); + + inode = gfs_iget(ip, CREATE); + gfs_inode_put(ip); + + if (!inode) + return -ENOMEM; + + error = gfs_security_init(dip, ip); + + gfs_glock_dq_uninit(&d_gh); + gfs_glock_dq_uninit(&i_gh); + + if (error) + return error; + + d_instantiate(dentry, inode); + mark_inode_dirty(inode); + + return 0; +} + +/** + * gfs_rmdir - Remove a directory + * @dir: The parent directory of the directory to be removed + * @dentry: The dentry of the directory to remove + * + * Remove a directory. Call gfs_rmdiri() + * + * Returns: errno + */ + +static int +gfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct gfs_inode *dip = get_v2ip(dir); + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_inode *ip = get_v2ip(dentry->d_inode); + struct gfs_holder ghs[2]; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + gfs_unlinked_limit(sdp); + + gfs_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]); + gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]); + + error = gfs_glock_nq_m(2, ghs); + if (error) + goto fail; + + error = gfs_unlink_ok(dip, &dentry->d_name, ip); + if (error) + goto fail_gunlock; + + if (ip->i_di.di_entries < 2) { + if (gfs_consist_inode(ip)) + gfs_dinode_print(&ip->i_di); + error = -EIO; + goto fail_gunlock; + } + if (ip->i_di.di_entries > 2) { + error = -ENOTEMPTY; + goto fail_gunlock; + } + + /* Trans may require: + Two dinode blocks, one directory leaf block containing the + entry to be rmdired, two leaf blocks containing . and .. of + the directory being rmdired, and one unlinked tag */ + + error = gfs_trans_begin(sdp, 5, 1); + if (error) + goto fail_gunlock; + + error = gfs_rmdiri(dip, &dentry->d_name, ip); + if (error) + goto fail_end_trans; + + gfs_trans_end(sdp); + + gfs_glock_dq_m(2, ghs); + + gfs_holder_uninit(&ghs[0]); + gfs_holder_uninit(&ghs[1]); + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_gunlock: + gfs_glock_dq_m(2, ghs); + + fail: + gfs_holder_uninit(&ghs[0]); + gfs_holder_uninit(&ghs[1]); + + return error; +} + +/** + * gfs_mknod - Make a special file + * @dir: The directory in which the special file will reside + * @dentry: The dentry of the special file + * @mode: The mode of the special file + * @rdev: The device specification of the special file + * + */ + +static int +gfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +{ + struct gfs_inode *dip = get_v2ip(dir), *ip; + struct gfs_sbd *sdp = dip->i_sbd; + struct gfs_holder d_gh, i_gh; + struct inode *inode; + struct buffer_head *dibh; + uint16_t type = 0; + uint32_t major = 0, minor = 0; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + gfs_unlinked_limit(sdp); + + switch (mode & S_IFMT) { + case S_IFBLK: + type = GFS_FILE_BLK; + major = MAJOR(dev); + minor = MINOR(dev); + break; + case S_IFCHR: + type = GFS_FILE_CHR; + major = MAJOR(dev); + minor = MINOR(dev); + break; + case S_IFIFO: + type = GFS_FILE_FIFO; + break; + case S_IFSOCK: + type = GFS_FILE_SOCK; + break; + default: + printk("GFS: fsid=%s: mknod() with invalid type (%d)\n", + sdp->sd_fsname, mode); + return -EINVAL; + }; + + gfs_holder_init(dip->i_gl, 0, 0, &d_gh); + + error = gfs_createi(&d_gh, &dentry->d_name, + type, mode, + &i_gh); + if (error) { + gfs_holder_uninit(&d_gh); + return error; + } + + ip = get_gl2ip(i_gh.gh_gl); + + ip->i_di.di_major = major; + ip->i_di.di_minor = minor; + + error = gfs_get_inode_buffer(ip, &dibh); + + if (!gfs_assert_withdraw(sdp, !error)) { + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + gfs_trans_end(sdp); + if (dip->i_alloc->al_rgd) + gfs_inplace_release(dip); + gfs_quota_unlock_m(dip); + gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul); + gfs_alloc_put(dip); + + inode = gfs_iget(ip, CREATE); + gfs_inode_put(ip); + + error = gfs_security_init(dip, ip); + + gfs_glock_dq_uninit(&d_gh); + gfs_glock_dq_uninit(&i_gh); + + if (error) + return error; + + if (!inode) + return -ENOMEM; + + d_instantiate(dentry, inode); + mark_inode_dirty(inode); + + return 0; +} + +/** + * gfs_rename - Rename a file + * @odir: Parent directory of old file name + * @odentry: The old dentry of the file + * @ndir: Parent directory of new file name + * @ndentry: The new dentry of the file + * + * Returns: errno + */ + +static int +gfs_rename(struct inode *odir, struct dentry *odentry, + struct inode *ndir, struct dentry *ndentry) +{ + struct gfs_inode *odip = get_v2ip(odir); + struct gfs_inode *ndip = get_v2ip(ndir); + struct gfs_inode *ip = get_v2ip(odentry->d_inode); + struct gfs_inode *nip = NULL; + struct gfs_sbd *sdp = odip->i_sbd; + struct qstr name; + struct gfs_alloc *al; + struct gfs_holder ghs[4], r_gh; + unsigned int num_gh; + int dir_rename = FALSE; + int alloc_required; + unsigned int x; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + gfs_unlinked_limit(sdp); + + if (ndentry->d_inode) { + nip = get_v2ip(ndentry->d_inode); + if (ip == nip) + return 0; + } + + /* Make sure we aren't trying to move a dirctory into it's subdir */ + + if (ip->i_di.di_type == GFS_FILE_DIR && odip != ndip) { + dir_rename = TRUE; + + error = gfs_glock_nq_init(sdp->sd_rename_gl, + LM_ST_EXCLUSIVE, 0, + &r_gh); + if (error) + return error; + + error = gfs_ok_to_move(ip, ndip); + if (error) + goto fail; + } + + gfs_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]); + gfs_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]); + num_gh = 2; + + if (nip) + gfs_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[num_gh++]); + + if (dir_rename) + gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[num_gh++]); + + error = gfs_glock_nq_m(num_gh, ghs); + if (error) + goto fail_uninit; + + /* Check out the old directory */ + + error = gfs_unlink_ok(odip, &odentry->d_name, ip); + if (error) + goto fail_gunlock; + + /* Check out the new directory */ + + if (nip) { + error = gfs_unlink_ok(ndip, &ndentry->d_name, nip); + if (error) + goto fail_gunlock; + + if (nip->i_di.di_type == GFS_FILE_DIR) { + if (nip->i_di.di_entries < 2) { + if (gfs_consist_inode(nip)) + gfs_dinode_print(&nip->i_di); + error = -EIO; + goto fail_gunlock; + } + if (nip->i_di.di_entries > 2) { + error = -ENOTEMPTY; + goto fail_gunlock; + } + } + } else { + error = inode_permission(ndir, MAY_WRITE | MAY_EXEC); + if (error) + goto fail_gunlock; + + error = gfs_dir_search(ndip, &ndentry->d_name, NULL, NULL); + switch (error) { + case -ENOENT: + error = 0; + break; + case 0: + error = -EEXIST; + default: + goto fail_gunlock; + }; + + if (odip != ndip) { + if (!ndip->i_di.di_nlink) { + error = -EINVAL; + goto fail_gunlock; + } + if (ndip->i_di.di_entries == (uint32_t)-1) { + error = -EFBIG; + goto fail_gunlock; + } + if (ip->i_di.di_type == GFS_FILE_DIR && + ndip->i_di.di_nlink == (uint32_t)-1) { + error = -EMLINK; + goto fail_gunlock; + } + } + } + + error = gfs_diradd_alloc_required(ndip, &ndentry->d_name, &alloc_required); + if (error) + goto fail_gunlock; + + if (alloc_required) { + al = gfs_alloc_get(ndip); + + error = gfs_quota_lock_m(ndip, + NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto fail_alloc; + + error = gfs_quota_check(ndip, ndip->i_di.di_uid, ndip->i_di.di_gid); + if (error) + goto fail_gunlock_q; + + al->al_requested_meta = sdp->sd_max_dirres; + + error = gfs_inplace_reserve(ndip); + if (error) + goto fail_gunlock_q; + + /* Trans may require: + Dinodes for the srcdir, srcino, dstdir, dstino. Blocks for + adding the entry to dstdir. RG bitmaps for that allocation. + One leaf block in the srcdir for removal of the entry. + One leaf block for changing .. in srcino (if it's a directory). + Two leaf blocks for removing . and .. from dstino (if it exists + and it's a directory), one unlinked tag, and one quota block. */ + + error = gfs_trans_begin(sdp, + 8 + sdp->sd_max_dirres + + al->al_rgd->rd_ri.ri_length, + 2); + if (error) + goto fail_ipres; + } else { + /* Trans may require: + Dinodes for the srcdir, srcino, dstdir, dstino. One block for + adding the entry to dstdir. + One leaf block in the srcdir for removal of the entry. + One leaf block for changing .. in srcino (if it's a directory). + Two leaf blocks for removing . and .. from dstino (if it exists + and it's a directory), and one unlinked tag. */ + + error = gfs_trans_begin(sdp, 9, 1); + if (error) + goto fail_ipres; + } + + /* Remove the target file, if it exists */ + + if (nip) { + if (nip->i_di.di_type == GFS_FILE_DIR) + error = gfs_rmdiri(ndip, &ndentry->d_name, nip); + else + error = gfs_unlinki(ndip, &ndentry->d_name, nip); + + if (error) + goto fail_end_trans; + } + + if (dir_rename) { + error = gfs_change_nlink(ndip, +1); + if (error) + goto fail_end_trans; + error = gfs_change_nlink(odip, -1); + if (error) + goto fail_end_trans; + + name.len = 2; + name.name = ".."; + + error = gfs_dir_mvino(ip, &name, &ndip->i_num, GFS_FILE_DIR); + if (error) + goto fail_end_trans; + } + + error = gfs_dir_del(odip, &odentry->d_name); + if (error) + goto fail_end_trans; + + error = gfs_dir_add(ndip, &ndentry->d_name, &ip->i_num, ip->i_di.di_type); + if (error) + goto fail_end_trans; + + if (dir_rename) + gfs_trans_add_gl(sdp->sd_rename_gl); + + gfs_trans_end(sdp); + + if (alloc_required) { + /* Don't check al->al_alloced_meta and friends. */ + gfs_inplace_release(ndip); + gfs_quota_unlock_m(ndip); + gfs_alloc_put(ndip); + } + + gfs_glock_dq_m(num_gh, ghs); + + for (x = 0; x < num_gh; x++) + gfs_holder_uninit(&ghs[x]); + + if (dir_rename) + gfs_glock_dq_uninit(&r_gh); + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_ipres: + if (alloc_required) + gfs_inplace_release(ndip); + + fail_gunlock_q: + if (alloc_required) + gfs_quota_unlock_m(ndip); + + fail_alloc: + if (alloc_required) + gfs_alloc_put(ndip); + + fail_gunlock: + gfs_glock_dq_m(num_gh, ghs); + + fail_uninit: + for (x = 0; x < num_gh; x++) + gfs_holder_uninit(&ghs[x]); + + fail: + if (dir_rename) + gfs_glock_dq_uninit(&r_gh); + + return error; +} + +/** + * gfs_readlink - Read the value of a symlink + * @dentry: the symlink + * @buf: the buffer to read the symlink data into + * @size: the size of the buffer + * + * Returns: errno + */ + +static int +gfs_readlink(struct dentry *dentry, char *user_buf, int user_size) +{ + struct gfs_inode *ip = get_v2ip(dentry->d_inode); + char array[GFS_FAST_NAME_SIZE], *buf = array; + unsigned int len = GFS_FAST_NAME_SIZE; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_inode); + + error = gfs_readlinki(ip, &buf, &len); + if (error) + return error; + + if (user_size > len - 1) + user_size = len - 1; + + if (copy_to_user(user_buf, buf, user_size)) + error = -EFAULT; + else + error = user_size; + + if (buf != array) + kfree(buf); + + return error; +} + +/** + * gfs_follow_link - Follow a symbolic link + * @dentry: The dentry of the link + * @nd: Data that we pass to vfs_follow_link() + * + * This can handle symlinks of any size. It is optimised for symlinks + * under GFS_FAST_NAME_SIZE. + * + * Returns: 0 on success or error code + */ + +static void * +gfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct gfs_inode *ip = get_v2ip(dentry->d_inode); + char array[GFS_FAST_NAME_SIZE], *buf = array; + unsigned int len = GFS_FAST_NAME_SIZE; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_inode); + + error = gfs_readlinki(ip, &buf, &len); + if (!error) { + error = vfs_follow_link(nd, buf); + if (buf != array) + kfree(buf); + } + + return ERR_PTR(error); +} + +/** + * gfs_permission_i - + * @inode: + * @mask: + * + * Shamelessly ripped from ext3 + * + * Returns: errno + */ + +static int +gfs_permission_i(struct inode *inode, int mask) +{ + return generic_permission(inode, mask, gfs_check_acl); +} + +/** + * gfs_permission - + * @inode: + * @mask: + * + * Returns: errno + */ + +static int +gfs_permission(struct inode *inode, int mask) +{ + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_holder i_gh; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_inode); + + error = gfs_glock_nq_init(ip->i_gl, + LM_ST_SHARED, LM_FLAG_ANY, + &i_gh); + if (error) + return error; + + error = gfs_permission_i(inode, mask); + + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_setattr - Change attributes on an inode + * @dentry: The dentry which is changing + * @attr: The structure describing the change + * + * The VFS layer wants to change one or more of an inodes attributes. Write + * that change out to disk. + * + * Returns: errno + */ + +static int +gfs_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_holder i_gh; + int error; + + atomic_inc(&sdp->sd_ops_inode); + + /* Bugzilla 203170: we'll have the same deadlock as described + * in bugzilla 173912 if + * 1. without RHEL4's DIO_CLUSTER_LOCKING, and + * 2. we come down to this line of code from do_truncate() + * where i_sem(i_mutex) and i_alloc_sem have been taken, and + * 3. grab the exclusive glock here. + * To avoid this to happen, i_alloc_sem must be dropped and trust + * be put into glock that it can carry the same protection. + * + * One issue with dropping i_alloc_sem is that the gfs_setattr() + * can be invoked from other code path without this sempaphore. + * We'll need a new rwsem function that can "up" the semaphore + * only when it is needed. Before that happens (will research the + * possibility), i_alloc_sem (now) is a meaningless lock within + * GFS. If it is ever been used by other non-directIO code, this + * hack will fall apart. + * + * wcheng@redhat.com 10/14/06 + */ + if (attr->ia_valid & ATTR_SIZE) { + up_write(&dentry->d_inode->i_alloc_sem); + } + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + + if (attr->ia_valid & ATTR_SIZE) { + down_write(&dentry->d_inode->i_alloc_sem); + } + + if (error) + return error; + + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + error = -EPERM; + goto fail; + } + + error = inode_change_ok(inode, attr); + if (error) + goto fail; + + if (attr->ia_valid & ATTR_SIZE) { + error = inode_permission(inode, MAY_WRITE); + if (error) + goto fail; + + if (attr->ia_size != ip->i_di.di_size) { + error = vmtruncate(inode, attr->ia_size); + if (error) + goto fail; + } + + error = gfs_truncatei(ip, attr->ia_size, gfs_truncator_page); + if (error) { + if (inode->i_size != ip->i_di.di_size) + i_size_write(inode, ip->i_di.di_size); + goto fail; + } + + if ((sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) && + !gfs_is_jdata(ip)) + i_gh.gh_flags |= GL_SYNC; + } + + else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) { + struct gfs_alloc *al; + struct buffer_head *dibh; + uint32_t ouid, ogid, nuid, ngid; + + ouid = ip->i_di.di_uid; + ogid = ip->i_di.di_gid; + nuid = attr->ia_uid; + ngid = attr->ia_gid; + + if (!(attr->ia_valid & ATTR_UID) || ouid == nuid) + ouid = nuid = NO_QUOTA_CHANGE; + if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) + ogid = ngid = NO_QUOTA_CHANGE; + + al = gfs_alloc_get(ip); + + error = gfs_quota_lock_m(ip, nuid, ngid); + if (error) + goto fail_alloc; + + if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { + error = gfs_quota_check(ip, nuid, ngid); + if (error) + goto fail_gunlock_q; + } + + /* Trans may require: + one dinode block and one quota change block */ + + error = gfs_trans_begin(sdp, 1, 1); + if (error) + goto fail_gunlock_q; + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto fail_end_trans; + + if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { + gfs_trans_add_quota(sdp, -ip->i_di.di_blocks, + ouid, ogid); + gfs_trans_add_quota(sdp, ip->i_di.di_blocks, + nuid, ngid); + } + + error = inode_setattr(inode, attr); + gfs_assert_warn(sdp, !error); + gfs_inode_attr_out(ip); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + + gfs_trans_end(sdp); + + gfs_quota_unlock_m(ip); + gfs_alloc_put(ip); + } + + else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) { + error = gfs_acl_chmod(ip, attr); + if (error) + goto fail; + } + + else { + error = gfs_setattr_simple(ip, attr); + if (error) + goto fail; + } + + gfs_glock_dq_uninit(&i_gh); + + mark_inode_dirty(inode); + + return error; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_gunlock_q: + gfs_quota_unlock_m(ip); + + fail_alloc: + gfs_alloc_put(ip); + + fail: + gfs_glock_dq_uninit(&i_gh); + + return error; +} + +/** + * gfs_getattr - Read out an inode's attributes + * @mnt: ? + * @dentry: The dentry to stat + * @stat: The inode's stats + * + * Returns: errno + */ + +static int +gfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + struct gfs_inode *ip = get_v2ip(inode); + struct gfs_holder gh; + int error; + + atomic_inc(&ip->i_sbd->sd_ops_inode); + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); + if (!error) { + generic_fillattr(inode, stat); + gfs_glock_dq_uninit(&gh); + } + + return error; +} + +/** + * gfs_setxattr - Set (or create or replace) an inode's extended attribute + * @dentry: + * @name: + * @data: + * @size: + * @flags: + * + * Returns: errno + */ + +int +gfs_setxattr(struct dentry *dentry, const char *name, + const void *data, size_t size, + int flags) +{ + struct gfs_ea_request er; + + atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode); + + memset(&er, 0, sizeof(struct gfs_ea_request)); + er.er_type = gfs_ea_name2type(name, &er.er_name); + if (er.er_type == GFS_EATYPE_UNUSED) + return -EOPNOTSUPP; + er.er_data = (char *)data; + er.er_name_len = strlen(er.er_name); + er.er_data_len = size; + er.er_flags = flags; + + return gfs_ea_set(get_v2ip(dentry->d_inode), &er); +} + +/** + * gfs_getxattr - + * @dentry: + * @name: + * @data: + * @size: + * + * Returns: The number of bytes put into data, or -errno + */ + +ssize_t +gfs_getxattr(struct dentry *dentry, const char *name, + void *data, size_t size) +{ + struct gfs_ea_request er; + + atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode); + + memset(&er, 0, sizeof(struct gfs_ea_request)); + er.er_type = gfs_ea_name2type(name, &er.er_name); + if (er.er_type == GFS_EATYPE_UNUSED) + return -EOPNOTSUPP; + er.er_data = data; + er.er_name_len = strlen(er.er_name); + er.er_data_len = size; + + return gfs_ea_get(get_v2ip(dentry->d_inode), &er); +} + +/** + * gfs_listxattr - + * @dentry: + * @buffer: + * @size: + * + * Returns: The number of bytes put into data, or -errno + */ + +ssize_t +gfs_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct gfs_ea_request er; + + atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode); + + memset(&er, 0, sizeof(struct gfs_ea_request)); + er.er_data = (size) ? buffer : NULL; + er.er_data_len = size; + + return gfs_ea_list(get_v2ip(dentry->d_inode), &er); +} + +/** + * gfs_removexattr - + * @dentry: + * @name: + * + * Returns: errno + */ + +int +gfs_removexattr(struct dentry *dentry, const char *name) +{ + struct gfs_ea_request er; + + atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode); + + memset(&er, 0, sizeof(struct gfs_ea_request)); + er.er_type = gfs_ea_name2type(name, &er.er_name); + if (er.er_type == GFS_EATYPE_UNUSED) + return -EOPNOTSUPP; + er.er_name_len = strlen(er.er_name); + + return gfs_ea_remove(get_v2ip(dentry->d_inode), &er); +} + +struct inode_operations gfs_file_iops = { + .permission = gfs_permission, + .setattr = gfs_setattr, + .getattr = gfs_getattr, + .setxattr = gfs_setxattr, + .getxattr = gfs_getxattr, + .listxattr = gfs_listxattr, + .removexattr = gfs_removexattr, +}; + +struct inode_operations gfs_dev_iops = { + .permission = gfs_permission, + .setattr = gfs_setattr, + .getattr = gfs_getattr, + .setxattr = gfs_setxattr, + .getxattr = gfs_getxattr, + .listxattr = gfs_listxattr, + .removexattr = gfs_removexattr, +}; + +struct inode_operations gfs_dir_iops = { + .create = gfs_create, + .lookup = gfs_lookup, + .link = gfs_link, + .unlink = gfs_unlink, + .symlink = gfs_symlink, + .mkdir = gfs_mkdir, + .rmdir = gfs_rmdir, + .mknod = gfs_mknod, + .rename = gfs_rename, + .permission = gfs_permission, + .setattr = gfs_setattr, + .getattr = gfs_getattr, + .setxattr = gfs_setxattr, + .getxattr = gfs_getxattr, + .listxattr = gfs_listxattr, + .removexattr = gfs_removexattr, +}; + +struct inode_operations gfs_symlink_iops = { + .readlink = gfs_readlink, + .follow_link = gfs_follow_link, + .permission = gfs_permission, + .setattr = gfs_setattr, + .getattr = gfs_getattr, + .setxattr = gfs_setxattr, + .getxattr = gfs_getxattr, + .listxattr = gfs_listxattr, + .removexattr = gfs_removexattr, +}; + --- linux-2.6.27.orig/ubuntu/gfs/daemon.c +++ linux-2.6.27/ubuntu/gfs/daemon.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "daemon.h" +#include "glock.h" +#include "log.h" +#include "quota.h" +#include "recovery.h" +#include "super.h" +#include "unlinked.h" + +/** + * gfs_scand - Look for cached glocks and inodes to toss from memory + * @sdp: Pointer to GFS superblock + * + * One of these daemons runs, finding candidates to add to sd_reclaim_list. + * See gfs_glockd() + */ + +int +gfs_scand(void *data) +{ + struct gfs_sbd *sdp = (struct gfs_sbd *)data; + + while (!kthread_should_stop()) { + gfs_scand_internal(sdp); + schedule_timeout_interruptible(gfs_tune_get(sdp, gt_scand_secs) * HZ); + } + + return 0; +} + +/** + * gfs_glockd - Reclaim unused glock structures + * @sdp: Pointer to GFS superblock + * + * One or more of these daemons run, reclaiming glocks on sd_reclaim_list. + * sd_glockd_num says how many daemons are running now. + * Number of daemons can be set by user, with num_glockd mount option. + * See gfs_scand() + */ + +int +gfs_glockd(void *data) +{ + struct gfs_sbd *sdp = (struct gfs_sbd *)data; + + while (!kthread_should_stop()) { + while (atomic_read(&sdp->sd_reclaim_count)) + gfs_reclaim_glock(sdp); + + wait_event_interruptible(sdp->sd_reclaim_wchan, + (atomic_read(&sdp->sd_reclaim_count) || + kthread_should_stop())); + } + + return 0; +} + +/** + * gfs_recoverd - Recover dead machine's journals + * @sdp: Pointer to GFS superblock + * + */ + +int +gfs_recoverd(void *data) +{ + struct gfs_sbd *sdp = (struct gfs_sbd *)data; + + while (!kthread_should_stop()) { + gfs_check_journals(sdp); + schedule_timeout_interruptible(gfs_tune_get(sdp, gt_recoverd_secs) * HZ); + } + + return 0; +} + +/** + * gfs_logd - Update log tail as Active Items get flushed to in-place blocks + * @sdp: Pointer to GFS superblock + * + * Also, periodically check to make sure that we're using the most recent + * journal index. + */ + +int +gfs_logd(void *data) +{ + struct gfs_sbd *sdp = (struct gfs_sbd *)data; + struct gfs_holder ji_gh; + + while (!kthread_should_stop()) { + /* Advance the log tail */ + gfs_ail_empty(sdp); + + /* Check for latest journal index */ + if (time_after_eq(jiffies, + sdp->sd_jindex_refresh_time + + gfs_tune_get(sdp, gt_jindex_refresh_secs) * HZ)) { + if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags) && + !gfs_jindex_hold(sdp, &ji_gh)) + gfs_glock_dq_uninit(&ji_gh); + sdp->sd_jindex_refresh_time = jiffies; + } + + schedule_timeout_interruptible(gfs_tune_get(sdp, gt_logd_secs) * HZ); + } + + return 0; +} + +/** + * gfs_quotad - Write cached quota changes into the quota file + * @sdp: Pointer to GFS superblock + * + */ + +int +gfs_quotad(void *data) +{ + struct gfs_sbd *sdp = (struct gfs_sbd *)data; + int error; + + while (!kthread_should_stop()) { + /* Update statfs file */ + if (gfs_tune_get(sdp, gt_statfs_fast) && + time_after_eq(jiffies, + sdp->sd_statfs_sync_time + + gfs_tune_get(sdp, gt_statfs_fast) * HZ)) { + error = gfs_statfs_sync(sdp); + if (error && error != -EROFS && + !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + printk("GFS: fsid=%s: statfs: error = %d\n", + sdp->sd_fsname, error); + sdp->sd_statfs_sync_time = jiffies; + } + /* Update quota file */ + if (time_after_eq(jiffies, + sdp->sd_quota_sync_time + + gfs_tune_get(sdp, gt_quota_quantum) * HZ)) { + error = gfs_quota_sync(sdp); + if (error && + error != -EROFS && + !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + printk("GFS: fsid=%s: quotad: error = %d\n", + sdp->sd_fsname, error); + sdp->sd_quota_sync_time = jiffies; + } + + /* Clean up */ + gfs_quota_scan(sdp); + schedule_timeout_interruptible(gfs_tune_get(sdp, gt_quotad_secs) * HZ); + } + + return 0; +} + +/** + * gfs_inoded - Deallocate unlinked inodes + * @sdp: Pointer to GFS superblock + * + */ + +int +gfs_inoded(void *data) +{ + struct gfs_sbd *sdp = (struct gfs_sbd *)data; + + while (!kthread_should_stop()) { + gfs_unlinked_dealloc(sdp); + schedule_timeout_interruptible(gfs_tune_get(sdp, gt_inoded_secs) * HZ); + } + + return 0; +} --- linux-2.6.27.orig/ubuntu/gfs/lock_dlm_main.c +++ linux-2.6.27/ubuntu/gfs/lock_dlm_main.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include + +#include "lock_dlm.h" + +int init_lock_dlm() +{ + int error; + + error = gfs_register_lockproto(&gdlm_ops); + if (error) { + printk(KERN_WARNING "lock_dlm: can't register protocol: %d\n", + error); + return error; + } + + error = gdlm_sysfs_init(); + if (error) { + gfs_unregister_lockproto(&gdlm_ops); + return error; + } + + printk(KERN_INFO + "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__); + return 0; +} + +void exit_lock_dlm() +{ + gdlm_sysfs_exit(); + gfs_unregister_lockproto(&gdlm_ops); +} --- linux-2.6.27.orig/ubuntu/gfs/lock_dlm.h +++ linux-2.6.27/ubuntu/gfs/lock_dlm.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#ifndef LOCK_DLM_DOT_H +#define LOCK_DLM_DOT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "lm_interface.h" + +/* + * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a + * prefix of lock_dlm_ gets awkward. Externally, GFS refers to this module + * as "lock_dlm". + */ + +#define GDLM_STRNAME_BYTES 24 +#define GDLM_LVB_SIZE 32 +#define GDLM_DROP_COUNT 0 +#define GDLM_DROP_PERIOD 60 +#define GDLM_NAME_LEN 128 + +/* GFS uses 12 bytes to identify a resource (32 bit type + 64 bit number). + We sprintf these numbers into a 24 byte string of hex values to make them + human-readable (to make debugging simpler.) */ + +struct gdlm_strname { + unsigned char name[GDLM_STRNAME_BYTES]; + unsigned short namelen; +}; + +enum { + DFL_BLOCK_LOCKS = 0, + DFL_SPECTATOR = 1, + DFL_WITHDRAW = 2, +}; + +struct gdlm_ls { + u32 id; + int jid; + int first; + int first_done; + unsigned long flags; + struct kobject kobj; + char clustername[GDLM_NAME_LEN]; + char fsname[GDLM_NAME_LEN]; + int fsflags; + dlm_lockspace_t *dlm_lockspace; + lm_callback_t fscb; + struct gfs_sbd *sdp; + int recover_jid; + int recover_jid_done; + int recover_jid_status; + spinlock_t async_lock; + struct list_head complete; + struct list_head blocking; + struct list_head delayed; + struct list_head submit; + struct list_head all_locks; + u32 all_locks_count; + wait_queue_head_t wait_control; + struct task_struct *thread1; + struct task_struct *thread2; + wait_queue_head_t thread_wait; + unsigned long drop_time; + int drop_locks_count; + int drop_locks_period; +}; + +enum { + LFL_NOBLOCK = 0, + LFL_NOCACHE = 1, + LFL_DLM_UNLOCK = 2, + LFL_DLM_CANCEL = 3, + LFL_SYNC_LVB = 4, + LFL_FORCE_PROMOTE = 5, + LFL_REREQUEST = 6, + LFL_ACTIVE = 7, + LFL_INLOCK = 8, + LFL_CANCEL = 9, + LFL_NOBAST = 10, + LFL_HEADQUE = 11, + LFL_UNLOCK_DELETE = 12, + LFL_AST_WAIT = 13, +}; + +struct gdlm_lock { + struct gdlm_ls *ls; + struct lm_lockname lockname; + struct gdlm_strname strname; + char *lvb; + struct dlm_lksb lksb; + + s16 cur; + s16 req; + s16 prev_req; + u32 lkf; /* dlm flags DLM_LKF_ */ + unsigned long flags; /* lock_dlm flags LFL_ */ + + int bast_mode; /* protected by async_lock */ + + struct list_head clist; /* complete */ + struct list_head blist; /* blocking */ + struct list_head delay_list; /* delayed */ + struct list_head all_list; /* all locks for the fs */ + struct gdlm_lock *hold_null; /* NL lock for hold_lvb */ +}; + +#define gdlm_assert(assertion, fmt, args...) \ +do { \ + if (unlikely(!(assertion))) { \ + printk(KERN_EMERG "lock_dlm: fatal assertion failed \"%s\"\n" \ + "lock_dlm: " fmt "\n", \ + #assertion, ##args); \ + BUG(); \ + } \ +} while (0) + +#define log_print(lev, fmt, arg...) printk(lev "lock_dlm: " fmt "\n" , ## arg) +#define log_info(fmt, arg...) log_print(KERN_INFO , fmt , ## arg) +#define log_error(fmt, arg...) log_print(KERN_ERR , fmt , ## arg) +#ifdef LOCK_DLM_LOG_DEBUG +#define log_debug(fmt, arg...) log_print(KERN_DEBUG , fmt , ## arg) +#else +#define log_debug(fmt, arg...) +#endif + +/* sysfs.c */ + +int gdlm_sysfs_init(void); +void gdlm_sysfs_exit(void); +int gdlm_kobject_setup(struct gdlm_ls *, struct kobject *); +void gdlm_kobject_release(struct gdlm_ls *); + +/* thread.c */ + +int gdlm_init_threads(struct gdlm_ls *); +void gdlm_release_threads(struct gdlm_ls *); + +/* lock.c */ + +s16 gdlm_make_lmstate(s16); +void gdlm_queue_delayed(struct gdlm_lock *); +void gdlm_submit_delayed(struct gdlm_ls *); +int gdlm_release_all_locks(struct gdlm_ls *); +void gdlm_delete_lp(struct gdlm_lock *); +unsigned int gdlm_do_lock(struct gdlm_lock *); + +int gdlm_get_lock(void *, struct lm_lockname *, void **); +void gdlm_put_lock(void *); +unsigned int gdlm_lock(void *, unsigned int, unsigned int, unsigned int); +unsigned int gdlm_unlock(void *, unsigned int); +void gdlm_cancel(void *); +int gdlm_hold_lvb(void *, char **); +void gdlm_unhold_lvb(void *, char *); + +/* mount.c */ + +extern const struct lm_lockops gdlm_ops; + +#endif + --- linux-2.6.27.orig/ubuntu/gfs/gfs_ioctl.h +++ linux-2.6.27/ubuntu/gfs/gfs_ioctl.h @@ -0,0 +1,31 @@ +#ifndef __GFS_IOCTL_DOT_H__ +#define __GFS_IOCTL_DOT_H__ + +#define _GFSC_(x) (('G' << 8) | (x)) + +/* Ioctls implemented */ + +#define GFS_IOCTL_IDENTIFY _GFSC_(35) +#define GFS_IOCTL_SUPER _GFSC_(45) + +struct gfs_ioctl { + unsigned int gi_argc; + char **gi_argv; + + char __user *gi_data; + unsigned int gi_size; + uint64_t gi_offset; +}; + +#ifdef CONFIG_COMPAT +struct gfs_ioctl_compat { + unsigned int gi_argc; + uint32_t gi_argv; + + uint32_t gi_data; + unsigned int gi_size; + uint64_t gi_offset; +}; +#endif + +#endif /* ___GFS_IOCTL_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/eattr.h +++ linux-2.6.27/ubuntu/gfs/eattr.h @@ -0,0 +1,97 @@ +#ifndef __EATTR_DOT_H__ +#define __EATTR_DOT_H__ + +#define GFS_EA_REC_LEN(ea) gfs32_to_cpu((ea)->ea_rec_len) +#define GFS_EA_DATA_LEN(ea) gfs32_to_cpu((ea)->ea_data_len) + +#define GFS_EA_SIZE(ea) \ +MAKE_MULT8(sizeof(struct gfs_ea_header) + \ + (ea)->ea_name_len + \ + ((GFS_EA_IS_STUFFED(ea)) ? \ + GFS_EA_DATA_LEN(ea) : \ + (sizeof(uint64_t) * (ea)->ea_num_ptrs))) +#define GFS_EA_STRLEN(ea) \ +((((ea)->ea_type == GFS_EATYPE_USR) ? 5 : 7) + \ + (ea)->ea_name_len + 1) + +#define GFS_EA_IS_STUFFED(ea) (!(ea)->ea_num_ptrs) +#define GFS_EA_IS_LAST(ea) ((ea)->ea_flags & GFS_EAFLAG_LAST) + +#define GFS_EAREQ_SIZE_STUFFED(er) \ +MAKE_MULT8(sizeof(struct gfs_ea_header) + \ + (er)->er_name_len + (er)->er_data_len) +#define GFS_EAREQ_SIZE_UNSTUFFED(sdp, er) \ +MAKE_MULT8(sizeof(struct gfs_ea_header) + \ + (er)->er_name_len + \ + sizeof(uint64_t) * DIV_RU((er)->er_data_len, (sdp)->sd_jbsize)) + +#define GFS_EA2NAME(ea) ((char *)((struct gfs_ea_header *)(ea) + 1)) +#define GFS_EA2DATA(ea) (GFS_EA2NAME(ea) + (ea)->ea_name_len) +#define GFS_EA2DATAPTRS(ea) \ +((uint64_t *)(GFS_EA2NAME(ea) + MAKE_MULT8((ea)->ea_name_len))) +#define GFS_EA2NEXT(ea) \ +((struct gfs_ea_header *)((char *)(ea) + GFS_EA_REC_LEN(ea))) +#define GFS_EA_BH2FIRST(bh) \ +((struct gfs_ea_header *)((bh)->b_data + \ + sizeof(struct gfs_meta_header))) + +struct gfs_ea_request { + char *er_name; + char *er_data; + unsigned int er_name_len; + unsigned int er_data_len; + unsigned int er_type; /* GFS_EATYPE_... */ + int er_flags; + mode_t er_mode; +}; + +struct gfs_ea_location { + struct buffer_head *el_bh; + struct gfs_ea_header *el_ea; + struct gfs_ea_header *el_prev; +}; + +static inline unsigned int +gfs_ea_strlen(struct gfs_ea_header *ea) +{ + switch (ea->ea_type) { + case GFS_EATYPE_USR: + return (5 + (ea->ea_name_len + 1)); + case GFS_EATYPE_SYS: + return (7 + (ea->ea_name_len + 1)); + case GFS_EATYPE_SECURITY: + return (9 + (ea->ea_name_len + 1)); + default: + return (0); + } +} + +int gfs_ea_repack(struct gfs_inode *ip); + +int gfs_ea_get_i(struct gfs_inode *ip, struct gfs_ea_request *er); +int gfs_ea_set_i(struct gfs_inode *ip, struct gfs_ea_request *er); +int gfs_ea_remove_i(struct gfs_inode *ip, struct gfs_ea_request *er); + +int gfs_ea_list(struct gfs_inode *ip, struct gfs_ea_request *er); +int gfs_ea_get(struct gfs_inode *ip, struct gfs_ea_request *er); +int gfs_ea_set(struct gfs_inode *ip, struct gfs_ea_request *er); +int gfs_ea_remove(struct gfs_inode *ip, struct gfs_ea_request *er); + +int gfs_ea_dealloc(struct gfs_inode *ip); + +int gfs_get_eattr_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub); + +/* Exported to acl.c */ + +int gfs_ea_check_size(struct gfs_sbd *sdp, struct gfs_ea_request *er); +int gfs_ea_find(struct gfs_inode *ip, + struct gfs_ea_request *er, + struct gfs_ea_location *el); +int gfs_ea_get_copy(struct gfs_inode *ip, + struct gfs_ea_location *el, + char *data); +int gfs_ea_acl_init(struct gfs_inode *ip, struct gfs_ea_request *er); +int gfs_ea_acl_chmod(struct gfs_inode *ip, struct gfs_ea_location *el, + struct iattr *attr, char *data); + +#endif /* __EATTR_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gfs/quota.c +++ linux-2.6.27/ubuntu/gfs/quota.c @@ -0,0 +1,1139 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bmap.h" +#include "file.h" +#include "glock.h" +#include "glops.h" +#include "log.h" +#include "quota.h" +#include "rgrp.h" +#include "super.h" +#include "trans.h" + +/** + * gfs_quota_get - Get a structure to represent a quota change + * @sdp: the filesystem + * @user: TRUE if this is a user quota + * @id: the uid or gid + * @create: if TRUE, create the structure, otherwise return NULL + * @qdp: the returned quota structure + * + * Returns: errno + */ + +int +gfs_quota_get(struct gfs_sbd *sdp, int user, uint32_t id, int create, + struct gfs_quota_data **qdp) +{ + struct gfs_quota_data *qd = NULL, *new_qd = NULL; + struct list_head *tmp, *head; + int error; + + *qdp = NULL; + + for (;;) { + spin_lock(&sdp->sd_quota_lock); + + for (head = &sdp->sd_quota_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + qd = list_entry(tmp, struct gfs_quota_data, qd_list); + if (qd->qd_id == id && + !test_bit(QDF_USER, &qd->qd_flags) == !user) { + qd->qd_count++; + break; + } + } + + if (tmp == head) + qd = NULL; + + if (!qd && new_qd) { + qd = new_qd; + list_add(&qd->qd_list, &sdp->sd_quota_list); + new_qd = NULL; + } + + spin_unlock(&sdp->sd_quota_lock); + + if (qd || !create) { + if (new_qd) { + gfs_lvb_unhold(new_qd->qd_gl); + kfree(new_qd); + atomic_dec(&sdp->sd_quota_count); + } + *qdp = qd; + return 0; + } + + new_qd = kmalloc(sizeof(struct gfs_quota_data), GFP_KERNEL); + if (!new_qd) + return -ENOMEM; + memset(new_qd, 0, sizeof(struct gfs_quota_data)); + + new_qd->qd_count = 1; + + new_qd->qd_id = id; + if (user) + set_bit(QDF_USER, &new_qd->qd_flags); + + INIT_LIST_HEAD(&new_qd->qd_le_list); + + error = gfs_glock_get(sdp, 2 * (uint64_t)id + ((user) ? 0 : 1), + &gfs_quota_glops, CREATE, + &new_qd->qd_gl); + if (error) { + kfree(new_qd); + return error; + } + + error = gfs_lvb_hold(new_qd->qd_gl); + + gfs_glock_put(new_qd->qd_gl); + + if (error) { + kfree(new_qd); + return error; + } + + atomic_inc(&sdp->sd_quota_count); + } +} + +/** + * gfs_quota_hold - increment the usage count on a struct gfs_quota_data + * @sdp: the filesystem + * @qd: the structure + * + */ + +void +gfs_quota_hold(struct gfs_sbd *sdp, struct gfs_quota_data *qd) +{ + spin_lock(&sdp->sd_quota_lock); + gfs_assert(sdp, qd->qd_count,); + qd->qd_count++; + spin_unlock(&sdp->sd_quota_lock); +} + +/** + * gfs_quota_put - decrement the usage count on a struct gfs_quota_data + * @sdp: the filesystem + * @qd: the structure + * + * Free the structure if its reference count hits zero. + * + */ + +void +gfs_quota_put(struct gfs_sbd *sdp, struct gfs_quota_data *qd) +{ + spin_lock(&sdp->sd_quota_lock); + gfs_assert(sdp, qd->qd_count,); + qd->qd_count--; + spin_unlock(&sdp->sd_quota_lock); +} + +/** + * quota_find - Find a quota change to sync to the quota file + * @sdp: the filesystem + * + * The returned structure is locked and needs to be unlocked + * with quota_unlock(). + * + * Returns: A quota structure, or NULL + */ + +static struct gfs_quota_data * +quota_find(struct gfs_sbd *sdp) +{ + struct list_head *tmp, *head; + struct gfs_quota_data *qd = NULL; + + if (test_bit(SDF_ROFS, &sdp->sd_flags)) + return NULL; + + gfs_log_lock(sdp); + spin_lock(&sdp->sd_quota_lock); + + if (!atomic_read(&sdp->sd_quota_od_count)) + goto out; + + for (head = &sdp->sd_quota_list, tmp = head->next; + tmp != head; + tmp = tmp->next) { + qd = list_entry(tmp, struct gfs_quota_data, qd_list); + + if (test_bit(QDF_LOCK, &qd->qd_flags)) + continue; + if (!test_bit(QDF_OD_LIST, &qd->qd_flags)) + continue; + if (qd->qd_sync_gen >= sdp->sd_quota_sync_gen) + continue; + + list_move_tail(&qd->qd_list, &sdp->sd_quota_list); + + set_bit(QDF_LOCK, &qd->qd_flags); + qd->qd_count++; + qd->qd_change_sync = qd->qd_change_od; + + goto out; + } + + qd = NULL; + + out: + spin_unlock(&sdp->sd_quota_lock); + gfs_log_unlock(sdp); + + return qd; +} + +/** + * quota_trylock - Try to lock a given quota entry + * @sdp: the filesystem + * @qd: the quota data structure + * + * Returns: TRUE if the lock was successful, FALSE, otherwise + */ + +static int +quota_trylock(struct gfs_sbd *sdp, struct gfs_quota_data *qd) +{ + int ret = FALSE; + + if (test_bit(SDF_ROFS, &sdp->sd_flags)) + return FALSE; + + gfs_log_lock(sdp); + spin_lock(&sdp->sd_quota_lock); + + if (test_bit(QDF_LOCK, &qd->qd_flags)) + goto out; + if (!test_bit(QDF_OD_LIST, &qd->qd_flags)) + goto out; + + list_move_tail(&qd->qd_list, &sdp->sd_quota_list); + + set_bit(QDF_LOCK, &qd->qd_flags); + qd->qd_count++; + qd->qd_change_sync = qd->qd_change_od; + + ret = TRUE; + + out: + spin_unlock(&sdp->sd_quota_lock); + gfs_log_unlock(sdp); + + return ret; +} + +/** + * quota_unlock - drop and a reference on a quota structure + * @sdp: the filesystem + * @qd: the quota inode structure + * + */ + +static void +quota_unlock(struct gfs_sbd *sdp, struct gfs_quota_data *qd) +{ + spin_lock(&sdp->sd_quota_lock); + + gfs_assert_warn(sdp, test_bit(QDF_LOCK, &qd->qd_flags)); + clear_bit(QDF_LOCK, &qd->qd_flags); + + gfs_assert(sdp, qd->qd_count,); + qd->qd_count--; + + spin_unlock(&sdp->sd_quota_lock); +} + +/** + * gfs_quota_merge - add/remove a quota change from the in-memory list + * @sdp: the filesystem + * @tag: the quota change tag + * + * Returns: errno + */ + +int +gfs_quota_merge(struct gfs_sbd *sdp, struct gfs_quota_tag *tag) +{ + struct gfs_quota_data *qd; + int error; + + error = gfs_quota_get(sdp, + tag->qt_flags & GFS_QTF_USER, tag->qt_id, + CREATE, &qd); + if (error) + return error; + + gfs_assert(sdp, qd->qd_change_ic == qd->qd_change_od,); + + gfs_log_lock(sdp); + + qd->qd_change_ic += tag->qt_change; + qd->qd_change_od += tag->qt_change; + + if (qd->qd_change_od) { + if (!test_bit(QDF_OD_LIST, &qd->qd_flags)) { + gfs_quota_hold(sdp, qd); + set_bit(QDF_OD_LIST, &qd->qd_flags); + atomic_inc(&sdp->sd_quota_od_count); + } + } else { + gfs_assert_warn(sdp, test_bit(QDF_OD_LIST, &qd->qd_flags)); + clear_bit(QDF_OD_LIST, &qd->qd_flags); + gfs_quota_put(sdp, qd); + gfs_assert(sdp, atomic_read(&sdp->sd_quota_od_count) > 0,); + atomic_dec(&sdp->sd_quota_od_count); + } + + gfs_log_unlock(sdp); + + gfs_quota_put(sdp, qd); + + return 0; +} + +/** + * gfs_quota_scan - Look for unused struct gfs_quota_data structures to throw away + * @sdp: the filesystem + * + */ + +void +gfs_quota_scan(struct gfs_sbd *sdp) +{ + struct list_head *head, *tmp, *next; + struct gfs_quota_data *qd; + LIST_HEAD(dead); + + spin_lock(&sdp->sd_quota_lock); + + for (head = &sdp->sd_quota_list, tmp = head->next, next = tmp->next; + tmp != head; + tmp = next, next = next->next) { + qd = list_entry(tmp, struct gfs_quota_data, qd_list); + if (!qd->qd_count) + list_move(&qd->qd_list, &dead); + } + + spin_unlock(&sdp->sd_quota_lock); + + while (!list_empty(&dead)) { + qd = list_entry(dead.next, struct gfs_quota_data, qd_list); + + gfs_assert_warn(sdp, !qd->qd_count); + gfs_assert_warn(sdp, !test_bit(QDF_OD_LIST, &qd->qd_flags) && + !test_bit(QDF_LOCK, &qd->qd_flags)); + gfs_assert_warn(sdp, !qd->qd_change_new && !qd->qd_change_ic && + !qd->qd_change_od); + + list_del(&qd->qd_list); + gfs_lvb_unhold(qd->qd_gl); + kfree(qd); + atomic_dec(&sdp->sd_quota_count); + } +} + +/** + * gfs_quota_cleanup - get rid of any extra struct gfs_quota_data structures + * @sdp: the filesystem + * + */ + +void +gfs_quota_cleanup(struct gfs_sbd *sdp) +{ + struct gfs_quota_data *qd; + + restart: + gfs_log_lock(sdp); + + spin_lock(&sdp->sd_quota_lock); + + while (!list_empty(&sdp->sd_quota_list)) { + qd = list_entry(sdp->sd_quota_list.next, + struct gfs_quota_data, + qd_list); + + if (qd->qd_count > 1) { + spin_unlock(&sdp->sd_quota_lock); + gfs_log_unlock(sdp); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + goto restart; + + } else if (qd->qd_count) { + gfs_assert_warn(sdp, + test_bit(QDF_OD_LIST, &qd->qd_flags) && + !test_bit(QDF_LOCK, &qd->qd_flags)); + gfs_assert_warn(sdp, qd->qd_change_od && + qd->qd_change_od == qd->qd_change_ic); + gfs_assert_warn(sdp, !qd->qd_change_new); + + list_del(&qd->qd_list); + atomic_dec(&sdp->sd_quota_od_count); + + spin_unlock(&sdp->sd_quota_lock); + gfs_lvb_unhold(qd->qd_gl); + kfree(qd); + atomic_dec(&sdp->sd_quota_count); + spin_lock(&sdp->sd_quota_lock); + + } else { + gfs_assert_warn(sdp, + !test_bit(QDF_OD_LIST, &qd->qd_flags) && + !test_bit(QDF_LOCK, &qd->qd_flags)); + gfs_assert_warn(sdp, !qd->qd_change_new && + !qd->qd_change_ic && + !qd->qd_change_od); + + list_del(&qd->qd_list); + + spin_unlock(&sdp->sd_quota_lock); + gfs_lvb_unhold(qd->qd_gl); + kfree(qd); + atomic_dec(&sdp->sd_quota_count); + spin_lock(&sdp->sd_quota_lock); + } + } + + spin_unlock(&sdp->sd_quota_lock); + + gfs_assert(sdp, !atomic_read(&sdp->sd_quota_od_count),); + + gfs_log_unlock(sdp); +} + +/** + * sort_qd - figure out the order between two quota data structures + * @a: first quota data structure + * @b: second quota data structure + * + * Returns: -1 if @a comes before @b, 0 if @a equals @b, 1 if @b comes before @a + */ + +static int +sort_qd(const void *a, const void *b) +{ + struct gfs_quota_data *qd_a = *(struct gfs_quota_data **)a; + struct gfs_quota_data *qd_b = *(struct gfs_quota_data **)b; + int ret = 0; + + if (!test_bit(QDF_USER, &qd_a->qd_flags) != + !test_bit(QDF_USER, &qd_b->qd_flags)) { + if (test_bit(QDF_USER, &qd_a->qd_flags)) + ret = -1; + else + ret = 1; + } else { + if (qd_a->qd_id < qd_b->qd_id) + ret = -1; + else if (qd_a->qd_id > qd_b->qd_id) + ret = 1; + } + + return ret; +} + +/** + * do_quota_sync - Sync a bunch quota changes to the quota file + * @sdp: the filesystem + * @qda: an array of struct gfs_quota_data structures to be synced + * @num_qd: the number of elements in @qda + * + * Returns: errno + */ + +static int +do_quota_sync(struct gfs_sbd *sdp, struct gfs_quota_data **qda, + unsigned int num_qd) +{ + struct gfs_inode *ip = sdp->sd_qinode; + struct gfs_alloc *al = NULL; + struct gfs_holder i_gh, *ghs; + struct gfs_quota q; + char buf[sizeof(struct gfs_quota)]; + uint64_t offset; + unsigned int qx, x; + int ar; + unsigned int nalloc = 0; + unsigned int data_blocks, ind_blocks; + int error; + + gfs_write_calc_reserv(ip, sizeof(struct gfs_quota), &data_blocks, + &ind_blocks); + + ghs = kmalloc(num_qd * sizeof(struct gfs_holder), GFP_KERNEL); + if (!ghs) + return -ENOMEM; + + gfs_sort(qda, num_qd, sizeof (struct gfs_quota_data *), sort_qd); + for (qx = 0; qx < num_qd; qx++) { + error = gfs_glock_nq_init(qda[qx]->qd_gl, + LM_ST_EXCLUSIVE, + GL_NOCACHE, &ghs[qx]); + if (error) + goto fail; + } + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + if (error) + goto fail; + + for (x = 0; x < num_qd; x++) { + offset = (2 * (uint64_t)qda[x]->qd_id + + ((test_bit(QDF_USER, &qda[x]->qd_flags)) ? 0 : 1)) * + sizeof(struct gfs_quota); + + error = gfs_write_alloc_required(ip, offset, + sizeof(struct gfs_quota), + &ar); + if (error) + goto fail_gunlock; + + if (ar) + nalloc++; + } + + if (nalloc) { + al = gfs_alloc_get(ip); + + error = + gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, + NO_QUOTA_CHANGE); + if (error) + goto fail_alloc; + + al->al_requested_meta = nalloc * (data_blocks + ind_blocks); + + error = gfs_inplace_reserve(ip); + if (error) + goto fail_qs; + + /* Trans may require: + two (journaled) data blocks, a dinode block, RG bitmaps to allocate from, + indirect blocks, and a quota block */ + + error = gfs_trans_begin(sdp, + 1 + al->al_rgd->rd_ri.ri_length + + num_qd * data_blocks + + nalloc * ind_blocks, + gfs_struct2blk(sdp, num_qd + 2, + sizeof(struct gfs_quota_tag))); + if (error) + goto fail_ipres; + } else { + /* Trans may require: + Data blocks, a dinode block, and quota blocks */ + + error = gfs_trans_begin(sdp, + 1 + data_blocks * num_qd, + gfs_struct2blk(sdp, num_qd, + sizeof(struct gfs_quota_tag))); + if (error) + goto fail_gunlock; + } + + for (x = 0; x < num_qd; x++) { + offset = (2 * (uint64_t)qda[x]->qd_id + + ((test_bit(QDF_USER, &qda[x]->qd_flags)) ? 0 : 1)) * + sizeof(struct gfs_quota); + + /* The quota file may not be a multiple of sizeof(struct gfs_quota) bytes. */ + memset(buf, 0, sizeof(struct gfs_quota)); + + error = gfs_internal_read(ip, buf, offset, + sizeof(struct gfs_quota)); + if (error < 0) + goto fail_end_trans; + + gfs_quota_in(&q, buf); + q.qu_value += qda[x]->qd_change_sync; + gfs_quota_out(&q, buf); + + error = gfs_internal_write(ip, buf, offset, + sizeof(struct gfs_quota)); + if (error < 0) + goto fail_end_trans; + else if (error != sizeof(struct gfs_quota)) { + error = -EIO; + goto fail_end_trans; + } + + if (test_bit(QDF_USER, &qda[x]->qd_flags)) + gfs_trans_add_quota(sdp, -qda[x]->qd_change_sync, + qda[x]->qd_id, NO_QUOTA_CHANGE); + else + gfs_trans_add_quota(sdp, -qda[x]->qd_change_sync, + NO_QUOTA_CHANGE, qda[x]->qd_id); + + memset(&qda[x]->qd_qb, 0, sizeof(struct gfs_quota_lvb)); + qda[x]->qd_qb.qb_magic = GFS_MAGIC; + qda[x]->qd_qb.qb_limit = q.qu_limit; + qda[x]->qd_qb.qb_warn = q.qu_warn; + qda[x]->qd_qb.qb_value = q.qu_value; + + gfs_quota_lvb_out(&qda[x]->qd_qb, qda[x]->qd_gl->gl_lvb); + } + + gfs_trans_end(sdp); + + if (nalloc) { + gfs_assert_warn(sdp, al->al_alloced_meta); + gfs_inplace_release(ip); + gfs_quota_unhold_m(ip); + gfs_alloc_put(ip); + } + + gfs_glock_dq_uninit(&i_gh); + + for (x = 0; x < num_qd; x++) + gfs_glock_dq_uninit(&ghs[x]); + + kfree(ghs); + + gfs_log_flush_glock(ip->i_gl); + + return 0; + + fail_end_trans: + gfs_trans_end(sdp); + + fail_ipres: + if (nalloc) + gfs_inplace_release(ip); + + fail_qs: + if (nalloc) + gfs_quota_unhold_m(ip); + + fail_alloc: + if (nalloc) + gfs_alloc_put(ip); + + fail_gunlock: + gfs_glock_dq_uninit(&i_gh); + + fail: + while (qx--) + gfs_glock_dq_uninit(&ghs[qx]); + + kfree(ghs); + + return error; +} + +/** + * glock_q - Acquire a lock for a quota entry + * @sdp: the filesystem + * @qd: the quota data structure to glock + * @force_refresh: If TRUE, always read from the quota file + * @q_gh: the glock holder for the quota lock + * + * Returns: errno + */ + +static int +glock_q(struct gfs_sbd *sdp, struct gfs_quota_data *qd, int force_refresh, + struct gfs_holder *q_gh) +{ + struct gfs_holder i_gh; + struct gfs_quota q; + char buf[sizeof(struct gfs_quota)]; + int error; + + restart: + error = gfs_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh); + if (error) + return error; + + gfs_quota_lvb_in(&qd->qd_qb, qd->qd_gl->gl_lvb); + + if (force_refresh || + qd->qd_qb.qb_magic != GFS_MAGIC) { + gfs_glock_dq_uninit(q_gh); + error = gfs_glock_nq_init(qd->qd_gl, + LM_ST_EXCLUSIVE, GL_NOCACHE, + q_gh); + if (error) + return error; + + error = gfs_glock_nq_init(sdp->sd_qinode->i_gl, + LM_ST_SHARED, 0, + &i_gh); + if (error) + goto fail; + + memset(buf, 0, sizeof(struct gfs_quota)); + + error = gfs_internal_read(sdp->sd_qinode, buf, + (2 * (uint64_t)qd->qd_id + + ((test_bit(QDF_USER, &qd->qd_flags)) ? 0 : 1)) * + sizeof(struct gfs_quota), + sizeof(struct gfs_quota)); + if (error < 0) + goto fail_gunlock; + + gfs_glock_dq_uninit(&i_gh); + + gfs_quota_in(&q, buf); + + memset(&qd->qd_qb, 0, sizeof(struct gfs_quota_lvb)); + qd->qd_qb.qb_magic = GFS_MAGIC; + qd->qd_qb.qb_limit = q.qu_limit; + qd->qd_qb.qb_warn = q.qu_warn; + qd->qd_qb.qb_value = q.qu_value; + + gfs_quota_lvb_out(&qd->qd_qb, qd->qd_gl->gl_lvb); + + gfs_glock_dq_uninit(q_gh); + force_refresh = FALSE; + goto restart; + } + + return 0; + + fail_gunlock: + gfs_glock_dq_uninit(&i_gh); + + fail: + gfs_glock_dq_uninit(q_gh); + + return error; +} + +/** + * gfs_quota_hold_m - Hold the quota structures for up to 4 IDs + * @ip: Two of the IDs are the UID and GID from this file + * @uid: a UID or the constant NO_QUOTA_CHANGE + * @gid: a GID or the constant NO_QUOTA_CHANGE + * + * The struct gfs_quota_data structures representing the locks are + * stored in the ip->i_alloc->al_qd array. + * + * Returns: errno + */ + +int +gfs_quota_hold_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + unsigned int x = 0; + int error; + + if (gfs_assert_warn(sdp, !al->al_qd_num && + !test_bit(GIF_QD_LOCKED, &ip->i_flags))) + return -EIO; + + if (!gfs_tune_get(sdp, gt_quota_account)) + return 0; + + error = gfs_quota_get(sdp, TRUE, ip->i_di.di_uid, + CREATE, &al->al_qd[x]); + if (error) + goto fail; + x++; + + error = gfs_quota_get(sdp, FALSE, ip->i_di.di_gid, + CREATE, &al->al_qd[x]); + if (error) + goto fail; + x++; + + if (uid != NO_QUOTA_CHANGE) { + error = gfs_quota_get(sdp, TRUE, uid, + CREATE, &al->al_qd[x]); + if (error) + goto fail; + x++; + } + + if (gid != NO_QUOTA_CHANGE) { + error = gfs_quota_get(sdp, FALSE, gid, + CREATE, &al->al_qd[x]); + if (error) + goto fail; + x++; + } + + al->al_qd_num = x; + + return 0; + + fail: + if (x) { + al->al_qd_num = x; + gfs_quota_unhold_m(ip); + } + + return error; +} + +/** + * gfs_quota_unhold_m - throw away some quota locks + * @ip: the inode who's ip->i_alloc->al_qd array holds the structures + * + */ + +void +gfs_quota_unhold_m(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + unsigned int x; + + gfs_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)); + + for (x = 0; x < al->al_qd_num; x++) { + gfs_quota_put(sdp, al->al_qd[x]); + al->al_qd[x] = NULL; + } + al->al_qd_num = 0; +} + +/** + * gfs_quota_lock_m - Acquire the quota locks for up to 4 IDs + * @ip: Two of the IDs are the UID and GID from this file + * @uid: a UID or the constant NO_QUOTA_CHANGE + * @gid: a GID or the constant NO_QUOTA_CHANGE + * + * The struct gfs_quota_data structures representing the locks are + * stored in the ip->i_alloc->al_qd array. + * + * Returns: errno + */ + +int +gfs_quota_lock_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + unsigned int x; + int error; + + gfs_quota_hold_m(ip, uid, gid); + + if (!gfs_tune_get(sdp, gt_quota_enforce)) + return 0; + if (capable(CAP_SYS_RESOURCE)) + return 0; + + gfs_sort(al->al_qd, al->al_qd_num, + sizeof(struct gfs_quota_data *), sort_qd); + + for (x = 0; x < al->al_qd_num; x++) { + error = glock_q(sdp, al->al_qd[x], FALSE, &al->al_qd_ghs[x]); + if (error) + goto fail; + } + + set_bit(GIF_QD_LOCKED, &ip->i_flags); + + return 0; + + fail: + while (x--) + gfs_glock_dq_uninit(&al->al_qd_ghs[x]); + + return error; +} + +/** + * gfs_quota_unlock_m - drop some quota locks + * @ip: the inode who's ip->i_alloc->al_qd array holds the locks + * + */ + +void +gfs_quota_unlock_m(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + struct gfs_quota_data *qd, *qda[4]; + int64_t value; + unsigned int count = 0; + unsigned int x; + int do_sync; + + if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags)) + goto out; + + for (x = 0; x < al->al_qd_num; x++) { + qd = al->al_qd[x]; + + spin_lock(&sdp->sd_quota_lock); + value = qd->qd_change_new + qd->qd_change_ic; + spin_unlock(&sdp->sd_quota_lock); + + do_sync = TRUE; + if (!qd->qd_qb.qb_limit) + do_sync = FALSE; + else if (qd->qd_qb.qb_value >= (int64_t)qd->qd_qb.qb_limit) + do_sync = FALSE; + else { + struct gfs_tune *gt = &sdp->sd_tune; + unsigned int num, den; + int64_t v; + + spin_lock(>->gt_spin); + num = gt->gt_quota_scale_num; + den = gt->gt_quota_scale_den; + spin_unlock(>->gt_spin); + + v = value * gfs_num_journals(sdp) * num; + do_div(v, den); + v += qd->qd_qb.qb_value; + if (v < (int64_t)qd->qd_qb.qb_limit) + do_sync = FALSE; + } + + gfs_glock_dq_uninit(&al->al_qd_ghs[x]); + + if (do_sync) { + gfs_log_flush(sdp); + if (quota_trylock(sdp, qd)) + qda[count++] = qd; + } + } + + if (count) { + do_quota_sync(sdp, qda, count); + + for (x = 0; x < count; x++) + quota_unlock(sdp, qda[x]); + } + + out: + gfs_quota_unhold_m(ip); +} + +/** + * print_quota_message - print a message to the user's tty about quotas + * @sdp: the filesystem + * @qd: the quota ID that the message is about + * @type: the type of message ("exceeded" or "warning") + * + * Returns: errno + */ + +static int +print_quota_message(struct gfs_sbd *sdp, struct gfs_quota_data *qd, char *type) +{ + struct tty_struct *tty; + char *line; + int len; + + line = kmalloc(256, GFP_KERNEL); + if (!line) + return -ENOMEM; + + len = snprintf(line, 256, "GFS: fsid=%s: quota %s for %s %u\r\n", + sdp->sd_fsname, type, + (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group", + qd->qd_id); + + if (current->signal) { + tty = current->signal->tty; + if (tty && tty->ops->write) + tty->ops->write(tty, line, len); + } + + kfree(line); + + return 0; +} + +/** + * gfs_quota_check - Check to see if a block allocation is possible + * @ip: the inode who's ip->i_res.ir_qd array holds the quota locks + * @uid: the UID the block is allocated for + * @gid: the GID the block is allocated for + * + */ + +int +gfs_quota_check(struct gfs_inode *ip, uint32_t uid, uint32_t gid) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al = ip->i_alloc; + struct gfs_quota_data *qd; + int64_t value; + unsigned int x; + int error = 0; + + if (!al) + return 0; + + if (!gfs_tune_get(sdp, gt_quota_enforce)) + return 0; + + for (x = 0; x < al->al_qd_num; x++) { + qd = al->al_qd[x]; + + if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) || + (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags)))) + continue; + + spin_lock(&sdp->sd_quota_lock); + value = qd->qd_change_new + qd->qd_change_ic; + spin_unlock(&sdp->sd_quota_lock); + value += qd->qd_qb.qb_value; + + if (qd->qd_qb.qb_limit && (int64_t)qd->qd_qb.qb_limit < value) { + print_quota_message(sdp, qd, "exceeded"); + error = -EDQUOT; + break; + } else if (qd->qd_qb.qb_warn && + (int64_t)qd->qd_qb.qb_warn < value && + time_after_eq(jiffies, + qd->qd_last_warn + + gfs_tune_get(sdp, gt_quota_warn_period) * HZ)) { + error = print_quota_message(sdp, qd, "warning"); + qd->qd_last_warn = jiffies; + } + } + + return error; +} + +/** + * gfs_quota_sync - Sync quota changes to the quota file + * @sdp: the filesystem + * + * Returns: errno + */ + +int +gfs_quota_sync(struct gfs_sbd *sdp) +{ + struct gfs_quota_data **qda; + unsigned int max_qd = gfs_tune_get(sdp, gt_quota_simul_sync); + unsigned int num_qd; + unsigned int x; + int error = 0; + + sdp->sd_quota_sync_gen++; + + qda = kmalloc(max_qd * sizeof(struct gfs_quota_data *), GFP_KERNEL); + if (!qda) + return -ENOMEM; + memset(qda, 0, max_qd * sizeof(struct gfs_quota_data *)); + + do { + num_qd = 0; + + for (;;) { + qda[num_qd] = quota_find(sdp); + if (!qda[num_qd]) + break; + + if (++num_qd == max_qd) + break; + } + + if (num_qd) { + error = do_quota_sync(sdp, qda, num_qd); + if (!error) + for (x = 0; x < num_qd; x++) + qda[x]->qd_sync_gen = + sdp->sd_quota_sync_gen; + + for (x = 0; x < num_qd; x++) + quota_unlock(sdp, qda[x]); + } + } + while (!error && num_qd == max_qd); + + kfree(qda); + + return error; +} + +/** + * gfs_quota_refresh - Refresh the LVB for a given quota ID + * @sdp: the filesystem + * @user: + * @id: + * + * Returns: errno + */ + +int +gfs_quota_refresh(struct gfs_sbd *sdp, int user, uint32_t id) +{ + struct gfs_quota_data *qd; + struct gfs_holder q_gh; + int error; + + error = gfs_quota_get(sdp, user, id, CREATE, &qd); + if (error) + return error; + + error = glock_q(sdp, qd, TRUE, &q_gh); + if (!error) + gfs_glock_dq_uninit(&q_gh); + + gfs_quota_put(sdp, qd); + + return error; +} + +/** + * gfs_quota_read - Read the info a given quota ID + * @sdp: the filesystem + * @user: + * @id: + * @q: + * + * Returns: errno + */ + +int +gfs_quota_read(struct gfs_sbd *sdp, int user, uint32_t id, + struct gfs_quota *q) +{ + struct gfs_quota_data *qd; + struct gfs_holder q_gh; + int error; + + if (((user) ? (id != current->fsuid) : (!in_group_p(id))) && + !capable(CAP_SYS_ADMIN)) + return -EACCES; + + error = gfs_quota_get(sdp, user, id, CREATE, &qd); + if (error) + return error; + + error = glock_q(sdp, qd, FALSE, &q_gh); + if (error) + goto out; + + memset(q, 0, sizeof(struct gfs_quota)); + q->qu_limit = qd->qd_qb.qb_limit; + q->qu_warn = qd->qd_qb.qb_warn; + q->qu_value = qd->qd_qb.qb_value; + + spin_lock(&sdp->sd_quota_lock); + q->qu_value += qd->qd_change_new + qd->qd_change_ic; + spin_unlock(&sdp->sd_quota_lock); + + gfs_glock_dq_uninit(&q_gh); + + out: + gfs_quota_put(sdp, qd); + + return error; +} --- linux-2.6.27.orig/ubuntu/gfs/ops_vm.c +++ linux-2.6.27/ubuntu/gfs/ops_vm.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bmap.h" +#include "glock.h" +#include "inode.h" +#include "ops_vm.h" +#include "page.h" +#include "quota.h" +#include "rgrp.h" +#include "trans.h" + +/** + * pfault_be_greedy - + * @ip: + * + */ + +static void +pfault_be_greedy(struct gfs_inode *ip) +{ + unsigned int time; + + spin_lock(&ip->i_spin); + time = ip->i_greedy; + ip->i_last_pfault = jiffies; + spin_unlock(&ip->i_spin); + + gfs_inode_hold(ip); + if (gfs_glock_be_greedy(ip->i_gl, time)) + gfs_inode_put(ip); +} + +/** + * gfs_private_fault - + * @area: + * @address: + * @type: + * + * Returns: the page + */ + +static int gfs_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct gfs_inode *ip = get_v2ip(vma->vm_file->f_mapping->host); + struct gfs_holder i_gh; + int error; + int ret = 0; + + atomic_inc(&ip->i_sbd->sd_ops_vm); + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + if (error) + goto out; + + set_bit(GIF_PAGED, &ip->i_flags); + + ret = filemap_fault(vma, vmf); + + if (ret && ret != VM_FAULT_OOM) + pfault_be_greedy(ip); + + gfs_glock_dq_uninit(&i_gh); + out: + return ret; +} + +/** + * alloc_page_backing - + * @ip: + * @index: + * + * Returns: errno + */ + +static int +alloc_page_backing(struct gfs_inode *ip, struct page *page) +{ + struct gfs_sbd *sdp = ip->i_sbd; + unsigned long index = page->index; + uint64_t lblock = index << (PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift); + unsigned int blocks = PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift; + struct gfs_alloc *al; + unsigned int x; + int error; + + al = gfs_alloc_get(ip); + + error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto out; + + error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + if (error) + goto out_gunlock_q; + + gfs_write_calc_reserv(ip, PAGE_CACHE_SIZE, + &al->al_requested_data, &al->al_requested_meta); + + error = gfs_inplace_reserve(ip); + if (error) + goto out_gunlock_q; + + /* Trans may require: + a dinode block, RG bitmaps to allocate from, + indirect blocks, and a quota block */ + + error = gfs_trans_begin(sdp, + 1 + al->al_rgd->rd_ri.ri_length + + al->al_requested_meta, 1); + if (error) + goto out_ipres; + + if (gfs_is_stuffed(ip)) { + error = gfs_unstuff_dinode(ip, gfs_unstuffer_page, NULL); + if (error) + goto out_trans; + } + + for (x = 0; x < blocks; ) { + uint64_t dblock; + unsigned int extlen; + int new = TRUE; + + error = gfs_block_map(ip, lblock, &new, &dblock, &extlen); + if (error) + goto out_trans; + + lblock += extlen; + x += extlen; + } + + gfs_assert_warn(sdp, al->al_alloced_meta || al->al_alloced_data); + + out_trans: + gfs_trans_end(sdp); + + out_ipres: + gfs_inplace_release(ip); + + out_gunlock_q: + gfs_quota_unlock_m(ip); + + out: + gfs_alloc_put(ip); + + return error; +} + +/** + * gfs_sharewrite_fault - + * @area: + * @address: + * @type: + * + * Returns: the page + */ + +static int gfs_sharewrite_fault(struct vm_area_struct *vma, + struct vm_fault *vmf) +{ + struct file *file = vma->vm_file; + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + struct gfs_holder i_gh; + int alloc_required; + int error; + int ret = 0; + + atomic_inc(&ip->i_sbd->sd_ops_vm); + + error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + if (error) + goto out; + + if (gfs_is_jdata(ip)) + goto out_unlock; + + set_bit(GIF_PAGED, &ip->i_flags); + set_bit(GIF_SW_PAGED, &ip->i_flags); + + error = gfs_write_alloc_required(ip, + (u64)vmf->pgoff << PAGE_CACHE_SHIFT, + PAGE_CACHE_SIZE, &alloc_required); + if (error) { + ret = VM_FAULT_OOM; /* XXX: are these right? */ + goto out_unlock; + } + + ret = filemap_fault(vma, vmf); + if (ret & VM_FAULT_ERROR) + goto out_unlock; + + if (alloc_required) { + /* XXX: do we need to drop page lock around alloc_page_backing?*/ + error = alloc_page_backing(ip, vmf->page); + if (error) { + /* + * VM_FAULT_LOCKED should always be the case for + * filemap_fault, but it may not be in a future + * implementation. + */ + if (ret & VM_FAULT_LOCKED) + unlock_page(vmf->page); + page_cache_release(vmf->page); + ret = VM_FAULT_OOM; + goto out_unlock; + } + set_page_dirty(vmf->page); + } + + pfault_be_greedy(ip); + + out_unlock: + gfs_glock_dq_uninit(&i_gh); + out: + return ret; +} + +struct vm_operations_struct gfs_vm_ops_private = { + .fault = gfs_private_fault, +}; + +struct vm_operations_struct gfs_vm_ops_sharewrite = { + .fault = gfs_sharewrite_fault, +}; + --- linux-2.6.27.orig/ubuntu/gfs/bmap.c +++ linux-2.6.27/ubuntu/gfs/bmap.c @@ -0,0 +1,1393 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gfs.h" +#include "bmap.h" +#include "dio.h" +#include "glock.h" +#include "inode.h" +#include "quota.h" +#include "rgrp.h" +#include "trans.h" + +struct metapath { + unsigned int mp_list[GFS_MAX_META_HEIGHT]; +}; + +typedef int (*block_call_t) (struct gfs_inode *ip, struct buffer_head *dibh, + struct buffer_head *bh, uint64_t *top, + uint64_t *bottom, unsigned int height, + void *data); + +struct strip_mine { + int sm_first; + unsigned int sm_height; +}; + +/** + * gfs_unstuffer_sync - unstuff a dinode synchronously + * @ip: the inode + * @dibh: the dinode buffer + * @block: the block number that was allocated + * @private: not used + * + * Returns: errno + */ + +int +gfs_unstuffer_sync(struct gfs_inode *ip, struct buffer_head *dibh, + uint64_t block, void *private) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh; + int error; + + error = gfs_get_data_buffer(ip, block, TRUE, &bh); + if (error) + return error; + + gfs_buffer_copy_tail(bh, 0, dibh, sizeof(struct gfs_dinode)); + + error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT); + + brelse(bh); + + return error; +} + +/** + * gfs_unstuffer_async - unstuff a dinode asynchronously + * @ip: the inode + * @dibh: the dinode buffer + * @block: the block number that was allocated + * @private: not used + * + * Returns: errno + */ + +int +gfs_unstuffer_async(struct gfs_inode *ip, struct buffer_head *dibh, + uint64_t block, void *private) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh; + int error; + + error = gfs_get_data_buffer(ip, block, TRUE, &bh); + if (error) + return error; + + gfs_buffer_copy_tail(bh, 0, dibh, sizeof(struct gfs_dinode)); + + error = gfs_dwrite(sdp, bh, DIO_DIRTY); + + brelse(bh); + + return error; +} + +/** + * gfs_unstuff_dinode - Unstuff a dinode when the data has grown too big + * @ip: The GFS inode to unstuff + * @unstuffer: the routine that handles unstuffing a non-zero length file + * @private: private data for the unstuffer + * + * This routine unstuffs a dinode and returns it to a "normal" state such + * that the height can be grown in the traditional way. + * + * Returns: errno + */ + +int +gfs_unstuff_dinode(struct gfs_inode *ip, gfs_unstuffer_t unstuffer, + void *private) +{ + struct buffer_head *bh, *dibh; + uint64_t block = 0; + int journaled = gfs_is_jdata(ip); + int error; + + down_write(&ip->i_rw_mutex); + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto out; + + if (ip->i_di.di_size) { + /* Get a free block, fill it with the stuffed data, + and write it out to disk */ + + if (journaled) { + error = gfs_metaalloc(ip, &block); + if (error) + goto out_brelse; + + error = gfs_get_data_buffer(ip, block, TRUE, &bh); + if (error) + goto out_brelse; + + gfs_buffer_copy_tail(bh, sizeof(struct gfs_meta_header), + dibh, sizeof(struct gfs_dinode)); + + brelse(bh); + } else { + gfs_blkalloc(ip, &block); + + error = unstuffer(ip, dibh, block, private); + if (error) + goto out_brelse; + } + } + + /* Set up the pointer to the new block */ + + gfs_trans_add_bh(ip->i_gl, dibh); + + gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode)); + + if (ip->i_di.di_size) { + *(uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode)) = cpu_to_gfs64(block); + ip->i_di.di_blocks++; + } + + ip->i_di.di_height = 1; + + gfs_dinode_out(&ip->i_di, dibh->b_data); + + out_brelse: + brelse(dibh); + + out: + up_write(&ip->i_rw_mutex); + + return error; +} + +/** + * calc_tree_height - Calculate the height of a metadata tree + * @ip: The GFS inode + * @size: The proposed size of the file + * + * Work out how tall a metadata tree needs to be in order to accommodate a + * file of a particular size. If size is less than the current size of + * the inode, then the current size of the inode is used instead of the + * supplied one. + * + * Returns: the height the tree should be + */ + +static unsigned int +calc_tree_height(struct gfs_inode *ip, uint64_t size) +{ + struct gfs_sbd *sdp = ip->i_sbd; + uint64_t *arr; + unsigned int max, height; + + if (ip->i_di.di_size > size) + size = ip->i_di.di_size; + + if (gfs_is_jdata(ip)) { + arr = sdp->sd_jheightsize; + max = sdp->sd_max_jheight; + } else { + arr = sdp->sd_heightsize; + max = sdp->sd_max_height; + } + + for (height = 0; height < max; height++) + if (arr[height] >= size) + break; + + return height; +} + +/** + * build_height - Build a metadata tree of the requested height + * @ip: The GFS inode + * @height: The height to build to + * + * This routine makes sure that the metadata tree is tall enough to hold + * "size" bytes of data. + * + * Returns: errno + */ + +static int +build_height(struct gfs_inode *ip, int height) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh, *dibh; + uint64_t block, *bp; + unsigned int x; + int new_block; + int error; + + while (ip->i_di.di_height < height) { + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + return error; + + new_block = FALSE; + bp = (uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode)); + for (x = 0; x < sdp->sd_diptrs; x++, bp++) + if (*bp) { + new_block = TRUE; + break; + } + + if (new_block) { + /* Get a new block, fill it with the old direct pointers, + and write it out */ + + error = gfs_metaalloc(ip, &block); + if (error) + goto fail; + + error = gfs_dread(ip->i_gl, block, + DIO_NEW | DIO_START | DIO_WAIT, &bh); + if (error) + goto fail; + + gfs_trans_add_bh(ip->i_gl, bh); + gfs_metatype_set(bh, + GFS_METATYPE_IN, + GFS_FORMAT_IN); + memset(bh->b_data + sizeof(struct gfs_meta_header), + 0, + sizeof(struct gfs_indirect) - + sizeof(struct gfs_meta_header)); + gfs_buffer_copy_tail(bh, sizeof(struct gfs_indirect), + dibh, sizeof(struct gfs_dinode)); + + brelse(bh); + } + + /* Set up the new direct pointer and write it out to disk */ + + gfs_trans_add_bh(ip->i_gl, dibh); + + gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode)); + + if (new_block) { + *(uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode)) = cpu_to_gfs64(block); + ip->i_di.di_blocks++; + } + + ip->i_di.di_height++; + + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + } + + return 0; + + fail: + brelse(dibh); + + return error; +} + +/** + * find_metapath - Find path through the metadata tree + * @ip: The inode pointer + * @mp: The metapath to return the result in + * @block: The disk block to look up + * + * This routine returns a struct metapath structure that defines a path through + * the metadata of inode "ip" to get to block "block". + * + * Example: + * Given: "ip" is a height 3 file, "offset" is 101342453, and this is a + * filesystem with a blocksize of 4096. + * + * find_metapath() would return a struct metapath structure set to: + * mp_offset = 101342453, mp_height = 3, mp_list[0] = 0, mp_list[1] = 48, + * and mp_list[2] = 165. + * + * That means that in order to get to the block containing the byte at + * offset 101342453, we would load the indirect block pointed to by pointer + * 0 in the dinode. We would then load the indirect block pointed to by + * pointer 48 in that indirect block. We would then load the data block + * pointed to by pointer 165 in that indirect block. + * + * ---------------------------------------- + * | Dinode | | + * | | 4| + * | |0 1 2 3 4 5 9| + * | | 6| + * ---------------------------------------- + * | + * | + * V + * ---------------------------------------- + * | Indirect Block | + * | 5| + * | 4 4 4 4 4 5 5 1| + * |0 5 6 7 8 9 0 1 2| + * ---------------------------------------- + * | + * | + * V + * ---------------------------------------- + * | Indirect Block | + * | 1 1 1 1 1 5| + * | 6 6 6 6 6 1| + * |0 3 4 5 6 7 2| + * ---------------------------------------- + * | + * | + * V + * ---------------------------------------- + * | Data block containing offset | + * | 101342453 | + * | | + * | | + * ---------------------------------------- + * + */ + +static struct metapath * +find_metapath(struct gfs_inode *ip, uint64_t block) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct metapath *mp; + uint64_t b = block; + unsigned int i; + + mp = gmalloc(sizeof(struct metapath)); + memset(mp, 0, sizeof(struct metapath)); + + for (i = ip->i_di.di_height; i--;) + mp->mp_list[i] = do_div(b, sdp->sd_inptrs); + + return mp; +} + +/** + * metapointer - Return pointer to start of metadata in a buffer + * @bh: The buffer + * @height: The metadata height (0 = dinode) + * @mp: The metapath + * + * Return a pointer to the block number of the next height of the metadata + * tree given a buffer containing the pointer to the current height of the + * metadata tree. + */ + +static __inline__ uint64_t * +metapointer(struct buffer_head *bh, unsigned int height, struct metapath *mp) +{ + unsigned int head_size = (height > 0) ? + sizeof(struct gfs_indirect) : sizeof(struct gfs_dinode); + + return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height]; +} + +/** + * get_metablock - Get the next metadata block in metadata tree + * @ip: The GFS inode + * @bh: Buffer containing the pointers to metadata blocks + * @height: The height of the tree (0 = dinode) + * @mp: The metapath + * @create: Non-zero if we may create a new meatdata block + * @new: Used to indicate if we did create a new metadata block + * @block: the returned disk block number + * + * Given a metatree, complete to a particular height, checks to see if the next + * height of the tree exists. If not the next height of the tree is created. + * The block number of the next height of the metadata tree is returned. + * + * Returns: errno + */ + +static int +get_metablock(struct gfs_inode *ip, + struct buffer_head *bh, unsigned int height, struct metapath *mp, + int create, int *new, uint64_t *block) +{ + uint64_t *ptr = metapointer(bh, height, mp); + int error; + + if (*ptr) { + *block = gfs64_to_cpu(*ptr); + return 0; + } + + *block = 0; + + if (!create) + return 0; + + error = gfs_metaalloc(ip, block); + if (error) + return error; + + gfs_trans_add_bh(ip->i_gl, bh); + + *ptr = cpu_to_gfs64(*block); + ip->i_di.di_blocks++; + + *new = 1; + + return 0; +} + +/** + * get_datablock - Get datablock number from metadata block + * @ip: The GFS inode + * @bh: The buffer containing pointers to datablocks + * @mp: The metapath + * @create: Non-zero if we may create a new data block + * @new: Used to indicate if we created a new data block + * @block: the returned disk block number + * + * Given a fully built metadata tree, checks to see if a particular data + * block exists. It is created if it does not exist and the block number + * on disk is returned. + * + * Returns: errno + */ + +static int +get_datablock(struct gfs_inode *ip, + struct buffer_head *bh, struct metapath *mp, + int create, int *new, uint64_t *block) +{ + uint64_t *ptr = metapointer(bh, ip->i_di.di_height - 1, mp); + + if (*ptr) { + *block = gfs64_to_cpu(*ptr); + return 0; + } + + *block = 0; + + if (!create) + return 0; + + if (gfs_is_jdata(ip)) { + int error; + error = gfs_metaalloc(ip, block); + if (error) + return error; + } else + gfs_blkalloc(ip, block); + + gfs_trans_add_bh(ip->i_gl, bh); + + *ptr = cpu_to_gfs64(*block); + ip->i_di.di_blocks++; + + *new = 1; + + return 0; +} + +/** + * gfs_block_map - Map a block from an inode to a disk block + * @ip: The GFS inode + * @lblock: The logical block number + * @new: Value/Result argument (1 = may create/did create new blocks) + * @dblock: the disk block number of the start of an extent + * @extlen: the size of the extent + * + * Find the block number on the current device which corresponds to an + * inode's block. If the block had to be created, "new" will be set. + * + * Returns: errno + */ + +int +gfs_block_map(struct gfs_inode *ip, + uint64_t lblock, int *new, + uint64_t *dblock, uint32_t *extlen) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh; + struct metapath *mp; + int create = *new; + unsigned int bsize; + unsigned int height; + unsigned int end_of_metadata; + unsigned int x; + int error = 0; + + *new = 0; + *dblock = 0; + if (extlen) + *extlen = 0; + + if (create) + down_write(&ip->i_rw_mutex); + else + down_read(&ip->i_rw_mutex); + + if (gfs_assert_warn(sdp, !gfs_is_stuffed(ip))) + goto out; + + bsize = (gfs_is_jdata(ip)) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize; + + height = calc_tree_height(ip, (lblock + 1) * bsize); + if (ip->i_di.di_height < height) { + if (!create) + goto out; + + error = build_height(ip, height); + if (error) + goto out; + } + + mp = find_metapath(ip, lblock); + end_of_metadata = ip->i_di.di_height - 1; + + error = gfs_get_inode_buffer(ip, &bh); + if (error) + goto out_kfree; + + for (x = 0; x < end_of_metadata; x++) { + error = get_metablock(ip, bh, x, mp, create, new, dblock); + brelse(bh); + if (error || !*dblock) + goto out_kfree; + + error = gfs_get_meta_buffer(ip, x + 1, *dblock, *new, &bh); + if (error) + goto out_kfree; + } + + error = get_datablock(ip, bh, mp, create, new, dblock); + if (error) { + brelse(bh); + goto out_kfree; + } + + if (extlen && *dblock) { + *extlen = 1; + + if (!*new) { + uint64_t tmp_dblock; + int tmp_new; + unsigned int nptrs; + + nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs; + + while (++mp->mp_list[end_of_metadata] < nptrs) { + get_datablock(ip, bh, mp, + FALSE, &tmp_new, + &tmp_dblock); + + if (*dblock + *extlen != tmp_dblock) + break; + + (*extlen)++; + } + } + } + + brelse(bh); + + if (*new) { + error = gfs_get_inode_buffer(ip, &bh); + if (!error) { + gfs_trans_add_bh(ip->i_gl, bh); + gfs_dinode_out(&ip->i_di, bh->b_data); + brelse(bh); + } + } + + out_kfree: + kfree(mp); + + out: + if (create) + up_write(&ip->i_rw_mutex); + else + up_read(&ip->i_rw_mutex); + + return error; +} + +/** + * do_grow - Make a file look bigger than it is + * @ip: the inode + * @size: the size to set the file to + * + * Called with an exclusive lock on @ip. + * + * Returns: errno + */ + +static int +do_grow(struct gfs_inode *ip, uint64_t size) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_alloc *al; + struct buffer_head *dibh; + unsigned int h; + int journaled = gfs_is_jdata(ip); + int error; + + al = gfs_alloc_get(ip); + + error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) + goto out; + + error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + if (error) + goto out_gunlock_q; + + if (journaled) + al->al_requested_meta = sdp->sd_max_height + 1; + else { + al->al_requested_meta = sdp->sd_max_height; + al->al_requested_data = 1; + } + + error = gfs_inplace_reserve(ip); + if (error) + goto out_gunlock_q; + + /* Trans may require: + Full extention of the metadata tree, block allocation, + a dinode modification, and a quota change */ + + error = gfs_trans_begin(sdp, + sdp->sd_max_height + al->al_rgd->rd_ri.ri_length + + 1 + !!journaled, + 1); + if (error) + goto out_ipres; + + if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) { + if (gfs_is_stuffed(ip)) { + error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL); + if (error) + goto out_end_trans; + } + + h = calc_tree_height(ip, size); + if (ip->i_di.di_height < h) { + down_write(&ip->i_rw_mutex); + error = build_height(ip, h); + up_write(&ip->i_rw_mutex); + if (error) + goto out_end_trans; + } + } + + ip->i_di.di_size = size; + ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto out_end_trans; + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + + out_end_trans: + gfs_trans_end(sdp); + + out_ipres: + gfs_inplace_release(ip); + + out_gunlock_q: + gfs_quota_unlock_m(ip); + + out: + gfs_alloc_put(ip); + + return error; +} + +/** + * recursive_scan - recursively scan through the end of a file + * @ip: the inode + * @dibh: the dinode buffer + * @mp: the path through the metadata to the point to start + * @height: the height the recursion is at + * @block: the indirect block to look at + * @first: TRUE if this is the first block + * @bc: the call to make for each piece of metadata + * @data: data opaque to this function to pass to @bc + * + * When this is first called @height and @block should be zero and + * @first should be TRUE. + * + * Returns: errno + */ + +static int +recursive_scan(struct gfs_inode *ip, struct buffer_head *dibh, + struct metapath *mp, unsigned int height, uint64_t block, + int first, block_call_t bc, void *data) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh = NULL; + uint64_t *top, *bottom; + uint64_t bn; + int error; + + if (!height) { + error = gfs_get_inode_buffer(ip, &bh); + if (error) + goto fail; + dibh = bh; + + top = (uint64_t *)(bh->b_data + sizeof(struct gfs_dinode)) + + mp->mp_list[0]; + bottom = (uint64_t *)(bh->b_data + sizeof(struct gfs_dinode)) + + sdp->sd_diptrs; + } else { + error = gfs_get_meta_buffer(ip, height, block, FALSE, &bh); + if (error) + goto fail; + + top = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect)) + + ((first) ? mp->mp_list[height] : 0); + bottom = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect)) + + sdp->sd_inptrs; + } + + error = bc(ip, dibh, bh, top, bottom, height, data); + if (error) + goto fail; + + if (height < ip->i_di.di_height - 1) + for (; top < bottom; top++, first = FALSE) { + if (!*top) + continue; + + bn = gfs64_to_cpu(*top); + + error = recursive_scan(ip, dibh, mp, + height + 1, bn, first, + bc, data); + if (error) + goto fail; + } + + brelse(bh); + + return 0; + + fail: + if (bh) + brelse(bh); + + return error; +} + +/** + * do_strip - Look for a layer a particular layer of the file and strip it off + * @ip: the inode + * @dibh: the dinode buffer + * @bh: A buffer of pointers + * @top: The first pointer in the buffer + * @bottom: One more than the last pointer + * @height: the height this buffer is at + * @data: a pointer to a struct strip_mine + * + * Returns: errno + */ + +static int +do_strip(struct gfs_inode *ip, struct buffer_head *dibh, + struct buffer_head *bh, uint64_t *top, uint64_t *bottom, + unsigned int height, void *data) +{ + struct strip_mine *sm = (struct strip_mine *)data; + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_rgrp_list rlist; + uint64_t bn, bstart; + uint32_t blen; + uint64_t *p; + unsigned int rg_blocks = 0; + int metadata; + int x; + int error; + + if (!*top) + sm->sm_first = FALSE; + + if (height != sm->sm_height) + return 0; + + if (sm->sm_first) { + top++; + sm->sm_first = FALSE; + } + + metadata = (height != ip->i_di.di_height - 1) || gfs_is_jdata(ip); + + error = gfs_rindex_hold(sdp, &ip->i_alloc->al_ri_gh); + if (error) + return error; + + memset(&rlist, 0, sizeof(struct gfs_rgrp_list)); + bstart = 0; + blen = 0; + + for (p = top; p < bottom; p++) { + if (!*p) + continue; + + bn = gfs64_to_cpu(*p); + + if (bstart + blen == bn) + blen++; + else { + if (bstart) + gfs_rlist_add(sdp, &rlist, bstart); + + bstart = bn; + blen = 1; + } + } + + if (bstart) + gfs_rlist_add(sdp, &rlist, bstart); + else + goto out; /* Nothing to do */ + + gfs_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); + + for (x = 0; x < rlist.rl_rgrps; x++) { + struct gfs_rgrpd *rgd; + rgd = get_gl2rgd(rlist.rl_ghs[x].gh_gl); + rg_blocks += rgd->rd_ri.ri_length; + } + + error = gfs_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); + if (error) + goto out_rlist; + + /* Trans may require: + All the bitmaps that were reserved. + One block for the dinode. + One block for the indirect block being cleared. + One block for a quota change. */ + + error = gfs_trans_begin(sdp, rg_blocks + 2, 1); + if (error) + goto out_rg_gunlock; + + down_write(&ip->i_rw_mutex); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_trans_add_bh(ip->i_gl, bh); + + bstart = 0; + blen = 0; + + for (p = top; p < bottom; p++) { + if (!*p) + continue; + + bn = gfs64_to_cpu(*p); + + if (bstart + blen == bn) + blen++; + else { + if (bstart) { + if (metadata) + gfs_metafree(ip, bstart, blen); + else + gfs_blkfree(ip, bstart, blen); + } + + bstart = bn; + blen = 1; + } + + *p = 0; + if (!ip->i_di.di_blocks) + gfs_consist_inode(ip); + ip->i_di.di_blocks--; + } + if (bstart) { + if (metadata) + gfs_metafree(ip, bstart, blen); + else + gfs_blkfree(ip, bstart, blen); + } + + ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + + gfs_dinode_out(&ip->i_di, dibh->b_data); + + up_write(&ip->i_rw_mutex); + + gfs_trans_end(sdp); + + out_rg_gunlock: + gfs_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs); + + out_rlist: + gfs_rlist_free(&rlist); + + out: + gfs_glock_dq_uninit(&ip->i_alloc->al_ri_gh); + + return error; +} + +/** + * gfs_truncator_default - truncate a partial data block + * @ip: the inode + * @size: the size the file should be + * + * Returns: errno + */ + +int +gfs_truncator_default(struct gfs_inode *ip, uint64_t size) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh; + uint64_t bn; + int not_new = 0; + int error; + + error = gfs_block_map(ip, size >> sdp->sd_sb.sb_bsize_shift, ¬_new, + &bn, NULL); + if (error) + return error; + if (!bn) + return 0; + + error = gfs_get_data_buffer(ip, bn, FALSE, &bh); + if (error) + return error; + + gfs_buffer_clear_tail(bh, size & (sdp->sd_sb.sb_bsize - 1)); + + error = gfs_dwrite(sdp, bh, DIO_DIRTY); + + brelse(bh); + + return error; +} + +/** + * truncator_journaled - truncate a partial data block + * @ip: the inode + * @size: the size the file should be + * + * Returns: errno + */ + +static int +truncator_journaled(struct gfs_inode *ip, uint64_t size) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *bh; + uint64_t lbn, dbn; + uint32_t off; + int not_new = 0; + int error; + + lbn = size; + off = do_div(lbn, sdp->sd_jbsize); + + error = gfs_block_map(ip, lbn, ¬_new, &dbn, NULL); + if (error) + return error; + if (!dbn) + return 0; + + error = gfs_trans_begin(sdp, 1, 0); + if (error) + return error; + + error = gfs_get_data_buffer(ip, dbn, FALSE, &bh); + if (!error) { + gfs_trans_add_bh(ip->i_gl, bh); + gfs_buffer_clear_tail(bh, + sizeof(struct gfs_meta_header) + + off); + brelse(bh); + } + + gfs_trans_end(sdp); + + return error; +} + +/** + * gfs_shrink - make a file smaller + * @ip: the inode + * @size: the size to make the file + * @truncator: function to truncate the last partial block + * + * Called with an exclusive lock on @ip. + * + * Returns: errno + */ + +int +gfs_shrink(struct gfs_inode *ip, uint64_t size, gfs_truncator_t truncator) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_holder ri_gh; + struct gfs_rgrpd *rgd; + struct buffer_head *dibh; + uint64_t block; + unsigned int height; + int journaled = gfs_is_jdata(ip); + int error; + + if (!size) + block = 0; + else if (journaled) { + block = size - 1; + do_div(block, sdp->sd_jbsize); + } + else + block = (size - 1) >> sdp->sd_sb.sb_bsize_shift; + + /* Get rid of all the data/metadata blocks */ + + height = ip->i_di.di_height; + if (height) { + struct metapath *mp = find_metapath(ip, block); + gfs_alloc_get(ip); + + error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + if (error) { + gfs_alloc_put(ip); + kfree(mp); + return error; + } + + while (height--) { + struct strip_mine sm; + + sm.sm_first = (size) ? TRUE : FALSE; + sm.sm_height = height; + + error = recursive_scan(ip, NULL, mp, 0, 0, TRUE, + do_strip, &sm); + if (error) { + gfs_quota_unhold_m(ip); + gfs_alloc_put(ip); + kfree(mp); + return error; + } + } + + gfs_quota_unhold_m(ip); + gfs_alloc_put(ip); + kfree(mp); + } + + /* If we truncated in the middle of a block, zero out the leftovers. */ + + if (gfs_is_stuffed(ip)) { + /* Do nothing */ + } else if (journaled) { + if (do_mod(size, sdp->sd_jbsize)) { + error = truncator_journaled(ip, size); + if (error) + return error; + } + } else if (size & (uint64_t)(sdp->sd_sb.sb_bsize - 1)) { + error = truncator(ip, size); + if (error) + return error; + } + + /* Set the new size (and possibly the height) */ + + if (!size) { + error = gfs_rindex_hold(sdp, &ri_gh); + if (error) + return error; + } + + error = gfs_trans_begin(sdp, 1, 0); + if (error) + goto out; + + down_write(&ip->i_rw_mutex); + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto out_end_trans; + + if (!size) { + ip->i_di.di_height = 0; + + rgd = gfs_blk2rgrpd(sdp, ip->i_num.no_addr); + if (!rgd) { + gfs_consist_inode(ip); + error = -EIO; + goto out_end_trans; + } + + ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr; + ip->i_di.di_goal_dblk = + ip->i_di.di_goal_mblk = + ip->i_num.no_addr - rgd->rd_ri.ri_data1; + } + + ip->i_di.di_size = size; + ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(ip->i_gl, dibh); + + if (!ip->i_di.di_height && + size < sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) + gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode) + size); + + gfs_dinode_out(&ip->i_di, dibh->b_data); + brelse(dibh); + + out_end_trans: + up_write(&ip->i_rw_mutex); + + gfs_trans_end(sdp); + + out: + if (!size) + gfs_glock_dq_uninit(&ri_gh); + + return error; +} + +/** + * do_same - truncate to same size (update time stamps) + * @ip: + * + * Returns: errno + */ + +static int +do_same(struct gfs_inode *ip) +{ + struct gfs_sbd *sdp = ip->i_sbd; + struct buffer_head *dibh; + int error; + + error = gfs_trans_begin(sdp, 1, 0); + if (error) + return error; + + error = gfs_get_inode_buffer(ip, &dibh); + if (error) + goto out; + + ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + + gfs_trans_add_bh(ip->i_gl, dibh); + gfs_dinode_out(&ip->i_di, dibh->b_data); + + brelse(dibh); + + out: + gfs_trans_end(sdp); + + return error; +} + +/** + * gfs_truncatei - make a file a give size + * @ip: the inode + * @size: the size to make the file + * @truncator: function to truncate the last partial block + * + * The file size can grow, shrink, or stay the same size. + * + * Returns: errno + */ + +int +gfs_truncatei(struct gfs_inode *ip, uint64_t size, + gfs_truncator_t truncator) +{ + if (gfs_assert_warn(ip->i_sbd, ip->i_di.di_type == GFS_FILE_REG)) + return -EINVAL; + + if (size == ip->i_di.di_size) + return do_same(ip); + else if (size > ip->i_di.di_size) + return do_grow(ip, size); + else + return gfs_shrink(ip, size, truncator); +} + +/** + * gfs_write_calc_reserv - calculate the number of blocks needed to write to a file + * @ip: the file + * @len: the number of bytes to be written to the file + * @data_blocks: returns the number of data blocks required + * @ind_blocks: returns the number of indirect blocks required + * + */ + +void +gfs_write_calc_reserv(struct gfs_inode *ip, unsigned int len, + unsigned int *data_blocks, unsigned int *ind_blocks) +{ + struct gfs_sbd *sdp = ip->i_sbd; + unsigned int tmp; + + if (gfs_is_jdata(ip)) { + *data_blocks = DIV_RU(len, sdp->sd_jbsize) + 2; + *ind_blocks = 3 * (sdp->sd_max_jheight - 1); + } else { + *data_blocks = (len >> sdp->sd_sb.sb_bsize_shift) + 3; + *ind_blocks = 3 * (sdp->sd_max_height - 1); + } + + for (tmp = *data_blocks; tmp > sdp->sd_diptrs;) { + tmp = DIV_RU(tmp, sdp->sd_inptrs); + *ind_blocks += tmp; + } +} + +/** + * gfs_write_alloc_required - figure out if a write is going to require an allocation + * @ip: the file being written to + * @offset: the offset to write to + * @len: the number of bytes being written + * @alloc_required: the int is set to TRUE if an alloc is required, FALSE otherwise + * + * Returns: errno + */ + +int +gfs_write_alloc_required(struct gfs_inode *ip, + uint64_t offset, unsigned int len, + int *alloc_required) +{ + struct gfs_sbd *sdp = ip->i_sbd; + uint64_t lblock, lblock_stop, dblock; + uint32_t extlen; + int not_new = FALSE; + int error = 0; + + *alloc_required = FALSE; + + if (!len) + return 0; + + if (gfs_is_stuffed(ip)) { + if (offset + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) + *alloc_required = TRUE; + return 0; + } + + if (gfs_is_jdata(ip)) { + unsigned int bsize = sdp->sd_jbsize; + lblock = offset; + do_div(lblock, bsize); + lblock_stop = offset + len + bsize - 1; + do_div(lblock_stop, bsize); + } else { + unsigned int shift = sdp->sd_sb.sb_bsize_shift; + lblock = offset >> shift; + lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; + } + + for (; lblock < lblock_stop; lblock += extlen) { + error = gfs_block_map(ip, lblock, ¬_new, &dblock, &extlen); + if (error) + return error; + + if (!dblock) { + *alloc_required = TRUE; + return 0; + } + } + + return 0; +} + +/** + * do_gfm - Copy out the dinode/indirect blocks of a file + * @ip: the file + * @dibh: the dinode buffer + * @bh: the indirect buffer we're looking at + * @top: the first pointer in the block + * @bottom: one more than the last pointer in the block + * @height: the height the block is at + * @data: a pointer to a struct gfs_user_buffer structure + * + * If this is a journaled file, copy out the data too. + * + * Returns: errno + */ + +static int +do_gfm(struct gfs_inode *ip, struct buffer_head *dibh, + struct buffer_head *bh, uint64_t *top, uint64_t *bottom, + unsigned int height, void *data) +{ + struct gfs_user_buffer *ub = (struct gfs_user_buffer *)data; + int error; + + error = gfs_add_bh_to_ub(ub, bh); + if (error) + return error; + + if (ip->i_di.di_type != GFS_FILE_DIR || + height + 1 != ip->i_di.di_height) + return 0; + + for (; top < bottom; top++) + if (*top) { + struct buffer_head *data_bh; + + error = gfs_dread(ip->i_gl, gfs64_to_cpu(*top), + DIO_START | DIO_WAIT, + &data_bh); + if (error) + return error; + + error = gfs_add_bh_to_ub(ub, data_bh); + + brelse(data_bh); + + if (error) + return error; + } + + return 0; +} + +/** + * gfs_get_file_meta - return all the metadata for a file + * @ip: the file + * @ub: the structure representing the meta + * + * Returns: errno + */ + +int +gfs_get_file_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub) +{ + int error; + + if (gfs_is_stuffed(ip)) { + struct buffer_head *dibh; + error = gfs_get_inode_buffer(ip, &dibh); + if (!error) { + error = gfs_add_bh_to_ub(ub, dibh); + brelse(dibh); + } + } else { + struct metapath *mp = find_metapath(ip, 0); + error = recursive_scan(ip, NULL, mp, 0, 0, TRUE, do_gfm, ub); + kfree(mp); + } + + return error; +} --- linux-2.6.27.orig/ubuntu/gfs/ops_file.h +++ linux-2.6.27/ubuntu/gfs/ops_file.h @@ -0,0 +1,9 @@ +#ifndef __OPS_FILE_DOT_H__ +#define __OPS_FILE_DOT_H__ + +extern struct file_operations gfs_file_fops; +extern struct file_operations gfs_dir_fops; +extern struct file_operations gfs_file_fops_nolock; +extern struct file_operations gfs_dir_fops_nolock; + +#endif /* __OPS_FILE_DOT_H__ */ --- linux-2.6.27.orig/ubuntu/gnbd/gnbd.h +++ linux-2.6.27/ubuntu/gnbd/gnbd.h @@ -0,0 +1,93 @@ +#ifndef LINUX_GNBD_H +#define LINUX_GNBD_H + +#define GNBD_DO_IT _IO( 0xab, 0x20 ) +#define GNBD_CLEAR_QUE _IO( 0xab, 0x21 ) +#define GNBD_PRINT_DEBUG _IO( 0xab, 0x22 ) +#define GNBD_DISCONNECT _IO( 0xab, 0x23 ) +#define GNBD_PING _IO( 0xab, 0x24 ) +#define GNBD_GET_TIME _IO( 0xab, 0x25 ) + +enum { + GNBD_CMD_READ = 0, + GNBD_CMD_WRITE = 1, + GNBD_CMD_DISC = 2, + GNBD_CMD_PING = 3 +}; + +#define gnbd_cmd(req) ((req)->__cmd[0]) +#define MAX_GNBD 128 + +/* values for flags field */ +#define GNBD_READ_ONLY 0x0001 + +/* userspace doesn't need the gnbd_device structure */ +#ifdef __KERNEL__ + +struct gnbd_device { + unsigned short int flags; + struct socket * sock; + struct file * file; /* If == NULL, device is not ready, yet */ + int magic; + spinlock_t queue_lock; + spinlock_t open_lock; + struct list_head queue_head;/* Requests are added here... */ + struct semaphore tx_lock; + struct gendisk *disk; + pid_t receiver_pid; + struct semaphore do_it_lock; + int open_count; + struct device class_dev; + unsigned short int server_port; + char *server_name; + char name[32]; + unsigned long last_received; + struct block_device *bdev; + struct request *current_request; + wait_queue_head_t tx_wait; + int corrupt; +}; + +#endif /* __KERNEL__ */ + +/* These are sent over the network in the request/reply magic fields */ + +#define GNBD_REQUEST_MAGIC 0x37a07e00 +#define GNBD_REPLY_MAGIC 0x41f09370 +#define GNBD_KEEP_ALIVE_MAGIC 0x5B46D8C2 +/* Do *not* use magics: 0x12560953 0x96744668. */ + +/* + * This is the packet used for communication between client and + * server. All data are in network byte order. + */ +struct gnbd_request { + uint32_t magic; + uint32_t type; /* == READ || == WRITE why so long */ + char handle[8]; /* why is this a char array instead of a u64 */ + uint64_t from; + uint32_t len; +} +#ifdef __GNUC__ + __attribute__ ((packed)) +#endif /* __GNUC__ */ +; + +/* + * This is the reply packet that gnbd-server sends back to the client after + * it has completed an I/O request (or an error occurs). + */ +#define SIZE_OF_REPLY 16 +struct gnbd_reply { + uint32_t magic; + uint32_t error; /* 0 = ok, else error */ + char handle[8]; /* handle you got from request */ +}; + +struct do_it_req_s { + unsigned int minor; + int sock_fd; +}; +typedef struct do_it_req_s do_it_req_t; + +#endif /* LINUX_GNBD_H */ --- linux-2.6.27.orig/ubuntu/gnbd/Kconfig +++ linux-2.6.27/ubuntu/gnbd/Kconfig @@ -0,0 +1,4 @@ +config GNBD + tristate "GFS Network Block Device" + default m + depends on SYSFS && NET && INET --- linux-2.6.27.orig/ubuntu/gnbd/BOM +++ linux-2.6.27/ubuntu/gnbd/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://git.fedorahosted.org/git/cluster.git +Current Version: 2.03.06 --- linux-2.6.27.orig/ubuntu/gnbd/gnbd.c +++ linux-2.6.27/ubuntu/gnbd/gnbd.c @@ -0,0 +1,1118 @@ +/* Large chunks of this code were lifted from nbd.c */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_COMPAT +#include +#endif + +#include +#include + +#include "gnbd.h" + +static int major_nr = 0; +uint64_t insmod_time; + + +#define GNBD_MAGIC 0x74d06100 + +#ifdef NDEBUG +#define dprintk(flags, fmt...) +#else /* NDEBUG */ +#define dprintk(flags, fmt...) do { \ + if (debugflags & (flags)) printk(KERN_DEBUG fmt); \ +} while (0) +#define DBG_IOCTL 0x0004 +#define DBG_INIT 0x0010 +#define DBG_EXIT 0x0020 +#define DBG_BLKDEV 0x0100 +#define DBG_RX 0x0200 +#define DBG_TX 0x0400 +static unsigned int debugflags; +#endif /* NDEBUG */ + +static struct gnbd_device gnbd_dev[MAX_GNBD]; + +struct request shutdown_req; +struct request ping_req; + +static spinlock_t gnbd_lock = SPIN_LOCK_UNLOCKED; + +#define to_gnbd_dev(d) container_of(d, struct gnbd_device, class_dev) + +static void gnbd_class_release(struct device *class_dev) +{ + /* FIXME -- What the hell do I have to free up here */ +} + +static struct class gnbd_class = { + .name = "gnbd", + .dev_release = gnbd_class_release +}; + +static ssize_t show_pid(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + return sprintf(buf, "%d\n", dev->receiver_pid); +} + +DEVICE_ATTR(pid, S_IRUGO, show_pid, NULL); + +static ssize_t show_server(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + if (dev->server_name) + return sprintf(buf, "%s/%hx\n", dev->server_name, + dev->server_port); + else + return sprintf(buf, "\n"); +} + +/* FIXME -- should a empty store free the memory */ +static ssize_t store_server(struct device *class_dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int res; + short unsigned int port; + char *ptr; + struct gnbd_device *dev = to_gnbd_dev(class_dev); + if (down_trylock(&dev->do_it_lock)) + return -EBUSY; + if (dev->server_name) + kfree(dev->server_name); + dev->server_name = kmalloc(count + 1, GFP_KERNEL); + if (!dev->server_name) + return -ENOMEM; + memcpy(dev->server_name, buf, count); + dev->server_name[count] = 0; + ptr = strchr(dev->server_name, '/'); + if (!ptr) + return -EINVAL; + *ptr++ = 0; + res = sscanf(ptr, "%4hx", &port); + if (res != 1){ + up(&dev->do_it_lock); + return -EINVAL; + } + dev->server_port = port; + up(&dev->do_it_lock); + return count; +} + +DEVICE_ATTR(server, S_IRUGO | S_IWUSR, show_server, store_server); + +static ssize_t show_name(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + return sprintf(buf, "%s\n", dev->name); +} + +static ssize_t store_name(struct device *class_dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int res; + struct gnbd_device *dev = to_gnbd_dev(class_dev); + if (down_trylock(&dev->do_it_lock)) + return -EBUSY; + res = sscanf(buf, "%31s", dev->name); + up(&dev->do_it_lock); + if (res != 1) + return -EINVAL; + return count; +} + +DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_name, store_name); + + +static ssize_t show_sectors(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + return sprintf(buf, "%Lu\n", + (unsigned long long)get_capacity(dev->disk)); +} + +static ssize_t store_sectors(struct device *class_dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int res; + sector_t size; + struct block_device *bdev; + struct gnbd_device *dev = to_gnbd_dev(class_dev); + + if (down_trylock(&dev->do_it_lock)) + return -EBUSY; + res = sscanf(buf, "%Lu\n", (unsigned long long int *)&size); + if (res != 1){ + up(&dev->do_it_lock); + return -EINVAL; + } + /* FIXME -- should I switch the order here, so that I don't have + capacity set to one thing and the bdev inode size set to another */ + set_capacity(dev->disk, size); + bdev = bdget_disk(dev->disk, 0); + if (bdev) { + mutex_lock(&bdev->bd_inode->i_mutex); + i_size_write(bdev->bd_inode, (loff_t)size << 9); + mutex_unlock(&bdev->bd_inode->i_mutex); + bdput(bdev); + } + up(&dev->do_it_lock); + return count; +} + +DEVICE_ATTR(sectors, S_IRUGO | S_IWUSR, show_sectors, store_sectors); + +static ssize_t show_usage(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + return sprintf(buf, "%d\n", dev->open_count); +} + +DEVICE_ATTR(usage, S_IRUGO, show_usage, NULL); + +static ssize_t show_flags(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + return sprintf(buf, "0x%04x\n", dev->flags); +} + +static ssize_t store_flags(struct device *class_dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int res; + + struct gnbd_device *dev = to_gnbd_dev(class_dev); + if (down_trylock(&dev->do_it_lock)) + return -EBUSY; + res = sscanf(buf, "0x%hx", &dev->flags); + up(&dev->do_it_lock); + if (res != 1) + return -EINVAL; + return count; +} + + +DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags); + +static ssize_t show_waittime(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + if (list_empty(&dev->queue_head)) + return sprintf(buf, "-1\n"); + return sprintf(buf, "%ld\n", + ((long)jiffies - (long)dev->last_received) / HZ); +} + +DEVICE_ATTR(waittime, S_IRUGO, show_waittime, NULL); + +static ssize_t show_connected(struct device *class_dev, struct device_attribute *attr, char *buf) +{ + struct gnbd_device *dev = to_gnbd_dev(class_dev); + return sprintf(buf, "%d\n", (dev->sock != NULL)); +} + +DEVICE_ATTR(connected, S_IRUGO, show_connected, NULL); + +#ifndef NDEBUG +static const char *ioctl_cmd_to_ascii(int cmd) +{ + switch (cmd) { + case GNBD_DO_IT: return "do-it"; + case GNBD_CLEAR_QUE: return "clear-que"; + case GNBD_PRINT_DEBUG: return "print-debug"; + case GNBD_DISCONNECT: return "disconnect"; + } + return "unknown"; +} + +static const char *gnbdcmd_to_ascii(int cmd) +{ + switch (cmd) { + case GNBD_CMD_READ: return "read"; + case GNBD_CMD_WRITE: return "write"; + case GNBD_CMD_DISC: return "disconnect"; + case GNBD_CMD_PING: return "ping"; + } + return "invalid"; +} +#endif /* NDEBUG */ + + +static int wait_for_send(struct request *req, struct gnbd_device *dev) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&dev->tx_wait, &wait); + while(dev->current_request == req) { + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + printk(KERN_WARNING "gnbd (pid %d: %s) wait interrupted by signal\n", + current->pid, current->comm); + return -EINTR; + } + schedule(); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&dev->tx_wait, &wait); + return 0; +} + +static void gnbd_end_request(struct request *req) +{ + int error = req->errors ? -EIO : 0; + struct request_queue *q = req->q; + unsigned long flags; + + dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name, + req, error ? "failed" : "done"); + + if (error) + printk("%s %d called gnbd_end_request with an error\n", + current->comm, current->pid); + + spin_lock_irqsave(q->queue_lock, flags); + __blk_end_request(req, error, req->nr_sectors << 9); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +/* + * Send or receive packet. + */ +static int sock_xmit(struct socket *sock, int send, void *buf, int size, + int msg_flags, int can_signal) +{ + mm_segment_t oldfs; + int result; + struct msghdr msg; + struct iovec iov; + unsigned long flags; + sigset_t oldset; + + oldfs = get_fs(); + set_fs(get_ds()); + spin_lock_irqsave(¤t->sighand->siglock, flags); + oldset = current->blocked; + sigfillset(¤t->blocked); + if (can_signal) + sigdelsetmask(¤t->blocked, sigmask(SIGKILL) | + sigmask(SIGTERM) | sigmask(SIGHUP)); + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + + do { + sock->sk->sk_allocation = GFP_NOIO; + iov.iov_base = buf; + iov.iov_len = size; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_namelen = 0; + msg.msg_flags = msg_flags | MSG_NOSIGNAL; + + if (send) + result = sock_sendmsg(sock, &msg, size); + else + result = sock_recvmsg(sock, &msg, size, 0); + + if (can_signal && signal_pending(current)) { + printk(KERN_WARNING "gnbd (pid %d: %s) got signal\n", + current->pid, current->comm); + result = -EINTR; + break; + } + + if (result <= 0) { + if (result == 0) + result = -EPIPE; /* short read */ + break; + } + size -= result; + buf += result; + } while (size > 0); + + spin_lock_irqsave(¤t->sighand->siglock, flags); + current->blocked = oldset; + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + + set_fs(oldfs); + return result; +} + +static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec, + int flags, int can_signal) +{ + int result; + void *kaddr = kmap(bvec->bv_page); + result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len, + flags, can_signal); + kunmap(bvec->bv_page); + return result; +} + + +#define gnbd_send_req(dev, req, can_sig) \ +__gnbd_send_req((dev), (dev)->sock, (req), (can_sig)) + +int __gnbd_send_req(struct gnbd_device *dev, struct socket *sock, + struct request *req, int can_signal) +{ + int result, flags; + struct gnbd_request request; + unsigned long size = req->nr_sectors << 9; + + request.magic = htonl(GNBD_REQUEST_MAGIC); + request.type = htonl(gnbd_cmd(req)); + request.from = cpu_to_be64((u64) req->sector << 9); + request.len = htonl(size); + memcpy(request.handle, &req, sizeof(req)); + + down(&dev->tx_lock); + + if (dev->corrupt) { + printk(KERN_ERR "%s: Attempted to send on a faulty socket\n", + dev->disk->disk_name); + result = -EBADFD; + goto error_out; + } + if (!sock) { + printk(KERN_ERR "%s: Attempted send on closed socket\n", + dev->disk->disk_name); + result = -ENOTCONN; + goto error_out; + } + + dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n", + dev->disk->disk_name, req, + gnbdcmd_to_ascii(gnbd_cmd(req)), + (unsigned long long)req->sector << 9, + req->nr_sectors << 9); + dev->current_request = req; + result = sock_xmit(sock, 1, &request, sizeof(request), + (gnbd_cmd(req) == GNBD_CMD_WRITE)? MSG_MORE: 0, + can_signal); + if (result < 0) { + printk(KERN_ERR "%s: Send control failed (result %d)\n", + dev->disk->disk_name, result); + goto send_error_out; + } + + if (gnbd_cmd(req) == GNBD_CMD_WRITE) { + struct req_iterator iter; + struct bio_vec *bvec; + /* + * we are really probing at internals to determine + * whether to set MSG_MORE or not... + */ + rq_for_each_segment(bvec, req, iter) { + flags = 0; + if (!rq_iter_last(req, iter)) + flags = MSG_MORE; + dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", + dev->disk->disk_name, req, + bvec->bv_len); + result = sock_send_bvec(sock, bvec, flags, + can_signal); + if (result < 0) { + printk(KERN_ERR "%s: Send data failed (result %d)\n", + dev->disk->disk_name, + result); + goto send_error_out; + } + } + } + dev->current_request = NULL; + wake_up(&dev->tx_wait); + up(&dev->tx_lock); + return 0; + +send_error_out: + dev->corrupt = 1; + dev->current_request = NULL; + wake_up(&dev->tx_wait); +error_out: + up(&dev->tx_lock); + return result; +} + + +static int gnbd_find_request(struct gnbd_device *dev, struct request *xreq) +{ + struct request *req; + struct list_head *tmp; + + list_for_each(tmp, &dev->queue_head) { + req = list_entry(tmp, struct request, queuelist); + if (req != xreq) + continue; + return 1; + } + return 0; +} + +static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec) +{ + int result; + void *kaddr = kmap(bvec->bv_page); + result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len, + MSG_WAITALL, 1); + kunmap(bvec->bv_page); + return result; +} + +int gnbd_recv_req(struct gnbd_device *dev, struct request *req) +{ + int result; + struct bio_vec *bvec; + struct req_iterator iter; + + rq_for_each_segment(bvec, req, iter) { + result = sock_recv_bvec(dev->sock, bvec); + if (result < 0) { + printk(KERN_ERR "%s: Receive data failed (result %d)\n", + dev->disk->disk_name, + result); + return result; + } + dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", + dev->disk->disk_name, req, bvec->bv_len); + } + return 0; +} + +int gnbd_do_it(struct gnbd_device *dev) +{ + int result; + struct gnbd_reply reply; + struct request *req; + struct socket *sock = dev->sock; + + BUG_ON(dev->magic != GNBD_MAGIC); + + while((result = sock_xmit(sock, 0, &reply,sizeof(reply), MSG_WAITALL, 1)) > 0){ + if (dev->corrupt) { + printk(KERN_ERR "%s: faulty socket\n",dev->disk->disk_name); + return -EBADFD; + } + + if (ntohl(reply.magic) == GNBD_KEEP_ALIVE_MAGIC) + /* FIXME -- I should reset the wait time here */ + continue; + + memcpy(&req, reply.handle, sizeof(req)); + if (req == &shutdown_req) + return 0; + + if (!gnbd_find_request(dev, req)){ + printk(KERN_ERR "%s: Unexpected reply (%p)\n", + dev->disk->disk_name, reply.handle); + return -EBADR; + } + if (ntohl(reply.magic) != GNBD_REPLY_MAGIC) { + printk(KERN_ERR "%s: Wrong magic (0x%lx)\n", + dev->disk->disk_name, + (unsigned long)ntohl(reply.magic)); + return -EPROTO; + } + if (ntohl(reply.error)) { + printk(KERN_ERR "%s: Other side returned error (%d)\n", + dev->disk->disk_name, ntohl(reply.error)); + req->errors++; + goto remove_req; + } + dprintk(DBG_RX, "%s: request %p: got reply\n", + dev->disk->disk_name, req); + + if (gnbd_cmd(req) == GNBD_CMD_READ){ + result = gnbd_recv_req(dev, req); + if (result < 0) + return result; + } +remove_req: + result = wait_for_send(req, dev); + if (result != 0) + return result; + spin_lock(&dev->queue_lock); + list_del_init(&req->queuelist); + dev->last_received = jiffies; + spin_unlock(&dev->queue_lock); + if (req != &ping_req) + gnbd_end_request(req); + } + printk(KERN_ERR "%s: Receive control failed (result %d)\n", + dev->disk->disk_name, result); + return result; +} + +int gnbd_clear_que(struct gnbd_device *dev) +{ + int err; + struct request *req; + + BUG_ON(dev->magic != GNBD_MAGIC); + + do { + req = NULL; + if (!list_empty(&dev->queue_head)) { + req = list_entry(dev->queue_head.next, struct request, queuelist); + err = wait_for_send(req, dev); + if (err) + return err; + list_del_init(&req->queuelist); + } + if (req && req != &ping_req) { + req->errors++; + gnbd_end_request(req); + } + } while (req); + + return 0; +} + +/* + * We always wait for result of write, for now. It would be nice to make it optional + * in future + * if ((req->cmd == WRITE) && (dev->flags & GNBD_WRITE_NOCHK)) + * { printk( "Warning: Ignoring result!\n"); gnbd_end_request( req ); } + */ + +static void do_gnbd_request(struct request_queue *q) +{ + int err; + struct request *req; + + while ((req = elv_next_request(q)) != NULL) { + struct gnbd_device *dev; + + blkdev_dequeue_request(req); + dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", + req->rq_disk->disk_name, req, req->cmd_type); + + if (!blk_fs_request(req)) + goto error_out; + + dev = req->rq_disk->private_data; + + if (dev->receiver_pid == -1) + goto error_out; + + BUG_ON(dev->magic != GNBD_MAGIC); + + gnbd_cmd(req) = GNBD_CMD_READ; + if (rq_data_dir(req) == WRITE) { + gnbd_cmd(req) = GNBD_CMD_WRITE; + if (dev->flags & GNBD_READ_ONLY) { + printk(KERN_ERR "%s: Write on read-only\n", + dev->disk->disk_name); + goto error_out; + } + } + + req->errors = 0; + spin_unlock_irq(q->queue_lock); + + spin_lock(&dev->queue_lock); + + if (list_empty(&dev->queue_head)) + dev->last_received = jiffies; + list_add(&req->queuelist, &dev->queue_head); + spin_unlock(&dev->queue_lock); + + err = gnbd_send_req(dev, req, 0); + + spin_lock_irq(q->queue_lock); + if (err) + goto sock_error; + continue; + +error_out: + req->errors++; + spin_unlock(q->queue_lock); + gnbd_end_request(req); + spin_lock(q->queue_lock); + } + return; + +sock_error: + return; +} + +/* + * This is called before dev-sock is set, so you dodn't need + * to worry about the tx_lock or the queue_lock + */ +static int gnbd_resend_requests(struct gnbd_device *dev, struct socket *sock) +{ + int err = 0; + struct request *req; + struct list_head *tmp; + + printk("resending requests\n"); + list_for_each(tmp, &dev->queue_head) { + req = list_entry(tmp, struct request, queuelist); + err = __gnbd_send_req(dev, sock, req, 1); + + if (err){ + printk("failed trying to resend request (%d)\n", err); + break; + } + } + + return err; +} +/* +static int get_server_info(struct gnbd_device *dev, struct socket *sock) +{ + struct sockaddr_in server; + int len; + int err; + + err = sock->ops->getname(sock, (struct sockaddr *) &server, &len, 1); + if (err) { + printk(KERN_WARNING "cannot get socket info, shutting down\n"); + } else{ + dev->server_addr = server.sin_addr; + dev->server_port = server.sin_port; + } + return err; +} +*/ + +static int gnbd_ctl_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct gnbd_device *dev = NULL; + struct block_device *bdev; + do_it_req_t req; + int error; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (cmd == GNBD_DISCONNECT || cmd == GNBD_CLEAR_QUE || + cmd == GNBD_PING || cmd == GNBD_PRINT_DEBUG) { + if (arg >= MAX_GNBD) + return -EINVAL; + dev = &gnbd_dev[arg]; + BUG_ON(dev->magic != GNBD_MAGIC); + } + + /* Anyone capable of this syscall can do *real bad* things */ + dprintk(DBG_IOCTL, "%s: gnbd_ioctl cmd=%s(0x%x) arg=%lu\n", + dev->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg); + + switch (cmd) { + case GNBD_DISCONNECT: + printk(KERN_INFO "%s: GNBD_DISCONNECT\n", dev->disk->disk_name); + spin_lock(&dev->open_lock); + if (dev->open_count > 0){ + spin_unlock(&dev->open_lock); + return -EBUSY; + } + dev->receiver_pid = -1; + spin_unlock(&dev->open_lock); + /* There is no one using the device, you can disconnect it */ + if (dev->sock == NULL) + return -ENOTCONN; + gnbd_send_req(dev, &shutdown_req, 1); + return 0; + case GNBD_CLEAR_QUE: + if (down_interruptible(&dev->do_it_lock)) + return -EBUSY; + dev->receiver_pid = -1; + error = gnbd_clear_que(dev); + if (error) + return error; + bdev = dev->bdev; + if (bdev) { + blk_run_queue(dev->disk->queue); +#if 0 + fsync_bdev(bdev); + invalidate_bdev(bdev); +#endif + } + up(&dev->do_it_lock); + return 0; + case GNBD_DO_IT: + if (copy_from_user(&req, (do_it_req_t *)arg, sizeof(req))) + return -EFAULT; + if (req.minor >= 128) + return -EINVAL; + dev = &gnbd_dev[req.minor]; + BUG_ON(dev->magic != GNBD_MAGIC); + if (dev->file) + return -EBUSY; + error = -EINVAL; + file = fget(req.sock_fd); + if (!file) + return error; + inode = file->f_dentry->d_inode; + if (!S_ISSOCK(inode->i_mode)) { + fput(file); + return error; + } + if (down_trylock(&dev->do_it_lock)){ + fput(file); + return -EBUSY; + } + error = gnbd_resend_requests(dev, SOCKET_I(inode)); + if (error){ + printk("quitting GNBD_DO_IT\n"); + up(&dev->do_it_lock); + fput(file); + return error; + } + dev->file = file; + dev->sock = SOCKET_I(inode); + dev->corrupt = 0; + dev->receiver_pid = current->pid; + blk_run_queue(dev->disk->queue); + error = gnbd_do_it(dev); + /* should I kill the socket first */ + up(&dev->do_it_lock); + down(&dev->tx_lock); + if (dev->sock) { + printk(KERN_WARNING "%s: shutting down socket\n", + dev->disk->disk_name); + dev->sock->ops->shutdown(dev->sock, + SEND_SHUTDOWN|RCV_SHUTDOWN); + dev->sock = NULL; + } + up(&dev->tx_lock); + file = dev->file; + dev->file = NULL; + if (file) + fput(file); + printk("exiting GNBD_DO_IT ioctl\n"); + return error; + case GNBD_PING: + /* FIXME -- should I allow pings if everything is compeletely + * shutdown */ + spin_lock(&dev->queue_lock); + /* only one outstanding ping at a time */ + if (list_empty(&ping_req.queuelist)){ + if (list_empty(&dev->queue_head)) + dev->last_received = jiffies; + list_add(&ping_req.queuelist, &dev->queue_head); + } + spin_unlock(&dev->queue_lock); + gnbd_send_req(dev, &ping_req, 1); /* ignore the errors */ + return 0; + case GNBD_PRINT_DEBUG: + printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n", + dev->disk->disk_name, + dev->queue_head.next, dev->queue_head.prev, + &dev->queue_head); + return 0; + case GNBD_GET_TIME: + if (copy_to_user((void *)arg, &insmod_time, sizeof(uint64_t))){ + printk(KERN_WARNING "couldn't copy time argument to user\n"); + return -EFAULT; + } + return 0; + } + /* FIXME -- should I print something, is EINVAL the right error */ + return -EINVAL; +} + +#ifdef CONFIG_COMPAT +static long gnbd_ctl_compat_ioctl(struct file *f, unsigned cmd, + unsigned long arg) +{ + int ret; + switch (cmd) { + case GNBD_DISCONNECT: + case GNBD_CLEAR_QUE: + case GNBD_PING: + case GNBD_PRINT_DEBUG: + lock_kernel(); + ret = gnbd_ctl_ioctl(f->f_dentry->d_inode, f, cmd, arg); + unlock_kernel(); + return ret; + case GNBD_DO_IT: + case GNBD_GET_TIME: + lock_kernel(); + ret = gnbd_ctl_ioctl(f->f_dentry->d_inode, f, cmd, + (unsigned long)compat_ptr(arg)); + unlock_kernel(); + return ret; + default: + return -ENOIOCTLCMD; + } +} +#endif + +static int gnbd_open(struct inode *inode, struct file *file) +{ + struct gnbd_device *dev = inode->i_bdev->bd_disk->private_data; + spin_lock(&dev->open_lock); + if (dev->receiver_pid == -1){ + spin_unlock(&dev->open_lock); + return -ENXIO; + } + spin_unlock(&dev->open_lock); + if ((file->f_mode & FMODE_WRITE) && (dev->flags & GNBD_READ_ONLY)){ + printk(KERN_INFO "cannot open read only gnbd device read/write"); + return -EROFS; + } + + dev->open_count++; + dev->bdev = inode->i_bdev; + return 0; +} + +/* FIXME -- I don't sync the device at close. This means that If you write + * something, and close the device, and expect that then it is written, + * you are wrong.... This might cause problems */ +static int gnbd_release(struct inode *inode, struct file *file) +{ + struct gnbd_device *dev = inode->i_bdev->bd_disk->private_data; + + dev->open_count--; + if (dev->open_count == 0) + dev->bdev = NULL; + return 0; +} + +static struct file_operations _gnbd_ctl_fops = +{ + .ioctl = gnbd_ctl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gnbd_ctl_compat_ioctl, +#endif + .owner = THIS_MODULE, +}; + +static struct miscdevice _gnbd_misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "gnbd_ctl", + .fops = &_gnbd_ctl_fops +}; + +/* FIXME -- I should probably do more here */ +int __init gnbd_ctl_init(void) +{ + int err; + + err = misc_register(&_gnbd_misc); + if (err) { + printk("cannot register control device\n"); + return err; + } + return 0; +} + +void gnbd_ctl_cleanup(void) +{ + if (misc_deregister(&_gnbd_misc) < 0) + printk("cannot deregister control device\n"); +} + +static struct block_device_operations gnbd_fops = +{ + .open = gnbd_open, + .release = gnbd_release, + .owner = THIS_MODULE, +}; + +/* + * And here should be modules and kernel interface + * (Just smiley confuses emacs :-) + */ + +static int __init gnbd_init(void) +{ + int err = -ENOMEM; + struct timeval tv; + int i; + + BUILD_BUG_ON(sizeof(struct gnbd_request) != 28); + + shutdown_req.cmd_type = REQ_TYPE_SPECIAL; + gnbd_cmd(&shutdown_req) = GNBD_CMD_DISC; + shutdown_req.sector = 0; + shutdown_req.nr_sectors = 0; + + ping_req.cmd_type = REQ_TYPE_SPECIAL; + gnbd_cmd(&ping_req) = GNBD_CMD_PING; + ping_req.sector = 0; + ping_req.nr_sectors = 0; + + for (i = 0; i < MAX_GNBD; i++) { + struct gendisk *disk = alloc_disk(1); + if (!disk) + goto out; + gnbd_dev[i].disk = disk; + /* + * The new linux 2.5 block layer implementation requires + * every gendisk to have its very own request_queue struct. + * These structs are big so we dynamically allocate them. + */ + disk->queue = blk_init_queue(do_gnbd_request, &gnbd_lock); + if (!disk->queue) { + put_disk(disk); + goto out; + } + elevator_exit(disk->queue->elevator); + err = elevator_init(disk->queue, "deadline"); + if (err) { + blk_cleanup_queue(disk->queue); + put_disk(disk); + goto out; + } + } + major_nr = register_blkdev(major_nr, "gnbd"); + if (major_nr < 0) { + printk("gnbd: unable to get a major number\n"); + err = major_nr; + goto out; + } + + printk(KERN_INFO "gnbd: registered device at major %d\n", major_nr); + dprintk(DBG_INIT, "gnbd: debugflags=0x%x\n", debugflags); + + err = class_register(&gnbd_class); + if (err) + goto out_unregister; + for (i = 0; i < MAX_GNBD; i++) { + struct gendisk *disk = gnbd_dev[i].disk; + gnbd_dev[i].file = NULL; + gnbd_dev[i].magic = GNBD_MAGIC; + gnbd_dev[i].flags = 0; + gnbd_dev[i].open_count = 0; + gnbd_dev[i].receiver_pid = -1; + gnbd_dev[i].server_name = NULL; + gnbd_dev[i].server_port = 0; + gnbd_dev[i].name[0] = '\0'; + gnbd_dev[i].bdev = NULL; + spin_lock_init(&gnbd_dev[i].queue_lock); + spin_lock_init(&gnbd_dev[i].open_lock); + INIT_LIST_HEAD(&gnbd_dev[i].queue_head); + init_MUTEX(&gnbd_dev[i].tx_lock); + init_MUTEX(&gnbd_dev[i].do_it_lock); + init_waitqueue_head(&gnbd_dev[i].tx_wait); + gnbd_dev[i].current_request = NULL; + gnbd_dev[i].class_dev.class = &gnbd_class; + sprintf(gnbd_dev[i].class_dev.bus_id, "gnbd%d", i); + err = device_register(&gnbd_dev[i].class_dev); + if (err){ + printk("device_register failed with %d\n", err); + goto out_unregister_class; + } + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_pid)) + goto out_remove_file; + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_server)) + goto out_remove_file; + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_name)) + goto out_remove_file; + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_sectors)) + goto out_remove_file; + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_usage)) + goto out_remove_file; + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_flags)) + goto out_remove_file; + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_waittime)) + goto out_remove_file; + if(device_create_file(&gnbd_dev[i].class_dev, + &dev_attr_connected)) + goto out_remove_file; + disk->major = major_nr; + disk->first_minor = i; + disk->fops = &gnbd_fops; + disk->private_data = &gnbd_dev[i]; + sprintf(disk->disk_name, "gnbd%d", i); + set_capacity(disk, 0); + add_disk(disk); + if(sysfs_create_link(&gnbd_dev[i].class_dev.kobj, + &gnbd_dev[i].disk->dev.kobj, "block")) + goto out_remove_disk; + + } + + err = gnbd_ctl_init(); + if (err) + goto out_unregister_class; + + do_gettimeofday(&tv); + insmod_time = (uint64_t) tv.tv_sec * 1000000 + tv.tv_usec; + + return 0; +out_remove_disk: + del_gendisk(gnbd_dev[i].disk); +out_remove_file: + device_unregister(&gnbd_dev[i].class_dev); +out_unregister_class: + while(i--){ + del_gendisk(gnbd_dev[i].disk); + device_unregister(&gnbd_dev[i].class_dev); + } + i = MAX_GNBD; + class_unregister(&gnbd_class); +out_unregister: + unregister_blkdev(major_nr, "gnbd"); +out: + while (i--) { + blk_cleanup_queue(gnbd_dev[i].disk->queue); + put_disk(gnbd_dev[i].disk); + } + return err; +} + +static void __exit gnbd_cleanup(void) +{ + int i; + + gnbd_ctl_cleanup(); + for (i = 0; i < MAX_GNBD; i++) { + struct gendisk *disk = gnbd_dev[i].disk; + device_unregister(&gnbd_dev[i].class_dev); + if (disk) { + del_gendisk(disk); + blk_cleanup_queue(disk->queue); + put_disk(disk); + } + if (gnbd_dev[i].server_name) + kfree(gnbd_dev[i].server_name); + } + class_unregister(&gnbd_class); + unregister_blkdev(major_nr, "gnbd"); + printk(KERN_INFO "gnbd: unregistered device at major %d\n", major_nr); +} + +module_init(gnbd_init); +module_exit(gnbd_cleanup); + +MODULE_DESCRIPTION("Network Block Device"); +MODULE_LICENSE("GPL"); + +#ifndef NDEBUG +module_param(debugflags, uint, 0644); +MODULE_PARM_DESC(debugflags, "flags for controlling debug output"); +#endif --- linux-2.6.27.orig/ubuntu/gnbd/Makefile +++ linux-2.6.27/ubuntu/gnbd/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_GNBD) += gnbd.o --- linux-2.6.27.orig/ubuntu/rfkill/pbe5.c +++ linux-2.6.27/ubuntu/rfkill/pbe5.c @@ -0,0 +1,205 @@ +/******************************************************************************* + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Author: + Pedro Ramalhais + + Based on: + av5100.c from http://ipw2100.sourceforge.net/ + +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pbe5" +#define DRV_VERSION "1.3" +#define DRV_DESCRIPTION "SW RF kill switch for Packard Bell EasyNote E5" +#define DRV_AUTHOR "Pedro Ramalhais" +#define DRV_LICENSE "GPL" + +static int radio = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + +MODULE_PARM(radio, "i"); + +#else /* LINUX_VERSION_CODE < 2.6.0 */ + +#include +module_param(radio, int, 1); + +#endif /* LINUX_VERSION_CODE < 2.6.0 */ + +MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)"); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_AUTHOR); +MODULE_LICENSE(DRV_LICENSE); + +/* + * NOTE: These values were obtained from disassembling the Icon.exe program + * installed in the Packard Bell EasyNote E5 laptop. The names were guessed, + * so don't rely on them. + */ +#define PBE5_PORT_TOGGLE 0x0b3 +#define PBE5_VALUE_TOGGLE_ON 0x01 +#define PBE5_VALUE_TOGGLE_OFF 0x00 +#define PBE5_PORT_APPLY 0x0b2 +#define PBE5_VALUE_APPLY 0xef + +// Some "booleans" =;-) +#define PBE5_RADIO_OFF 0 +#define PBE5_RADIO_ON 1 + +static int pbe5_radio_status = PBE5_RADIO_ON; + +unsigned char pbe5_get_radio(void) +{ + unsigned char val = 0x00; + + val = inb(PBE5_PORT_TOGGLE); + + return val; +} + +static void pbe5_set_radio(int state_set) +{ + pbe5_radio_status = pbe5_get_radio(); + + if (pbe5_radio_status != state_set) { + // Set the radio toggle register + outb(PBE5_VALUE_TOGGLE_ON, PBE5_PORT_TOGGLE); + // Commit the radio toggle register value + outb(PBE5_VALUE_APPLY, PBE5_PORT_APPLY); + // Update the radio status + pbe5_radio_status = pbe5_get_radio(); + + printk(KERN_INFO DRV_NAME ": Radio turned %s\n", + (state_set == PBE5_RADIO_ON) ? "ON" : "OFF"); + } else { + printk(KERN_INFO DRV_NAME ": Radio already %s\n", + (state_set == PBE5_RADIO_ON) ? "ON" : "OFF"); + } +} + + +/* + * proc stuff + */ +static struct proc_dir_entry *dir_base = NULL; + +static int proc_set_radio(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + pbe5_set_radio(buffer[0] == '0' ? PBE5_RADIO_OFF : PBE5_RADIO_ON); + + return count; +} + +static int proc_get_radio(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = 0; + + len += snprintf(page, count, DRV_NAME ": %d\n", + pbe5_radio_status == PBE5_RADIO_OFF ? 0 : 1); + + *eof = 1; + return len; +} + + +static void pbe5_proc_cleanup(void) +{ + if (dir_base) { + remove_proc_entry("radio", dir_base); + remove_proc_entry(DRV_NAME, NULL); + dir_base = NULL; + } +} + + +static int pbe5_proc_init(void) +{ + struct proc_dir_entry *ent; + int err = 0; + + dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL); + if (dir_base == NULL) { + printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/" + DRV_NAME "\n"); + err = -ENOMEM; + goto fail; + } + + + ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR, + dir_base); + if (ent) { + ent->read_proc = proc_get_radio; + ent->write_proc = proc_set_radio; + } else { + printk(KERN_ERR + "Unable to initialize /proc/" DRV_NAME "/radio\n"); + err = -ENOMEM; + goto fail; + } + + return 0; + + fail: + pbe5_proc_cleanup(); + return err; +} + +/* + * module stuff + */ +static int __init pbe5_init(void) +{ + pbe5_proc_init(); + + pbe5_set_radio((radio == 1) ? PBE5_RADIO_ON : PBE5_RADIO_OFF); + + return 0; +} + +static void __exit pbe5_exit(void) +{ + pbe5_set_radio(PBE5_RADIO_OFF); + + pbe5_proc_cleanup(); +} + +module_init(pbe5_init); +module_exit(pbe5_exit); + +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ --- linux-2.6.27.orig/ubuntu/rfkill/Kconfig +++ linux-2.6.27/ubuntu/rfkill/Kconfig @@ -0,0 +1,7 @@ +config AVERATEC_5100P + tristate "Software kill switch for Averatec 5100P" + default m + +config PACKARDBELL_E5 + tristate "Software kill switch for Packard Bell EasyNote E5" + default m --- linux-2.6.27.orig/ubuntu/rfkill/BOM +++ linux-2.6.27/ubuntu/rfkill/BOM @@ -0,0 +1,6 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=108766 +Current Version: 1.3 +Comments: + +Had to change &proc_root to NULL due to changes in create/remove proc +entry usage. --- linux-2.6.27.orig/ubuntu/rfkill/av5100.c +++ linux-2.6.27/ubuntu/rfkill/av5100.c @@ -0,0 +1,174 @@ +/******************************************************************************* + + Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRV_NAME "av5100" +#define DRV_VERSION "1.3" +#define DRV_DESCRIPTION "SW RF kill switch for Averatec 5100P" +#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" + +static int radio = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + +MODULE_PARM(radio, "i"); + +#else /* LINUX_VERSION_CODE < 2.6.0 */ + +#include +module_param(radio, int, 1); + +#endif /* LINUX_VERSION_CODE < 2.6.0 */ + +MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)"); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL"); + +#define AV5100_RADIO_ON (0xe0) +#define AV5100_RADIO_OFF (0xe1) + +static int av5100_radio = AV5100_RADIO_OFF; + +static void av5100_set_radio(int state) +{ + printk(KERN_INFO DRV_NAME ": Radio being turned %s\n", + (state == AV5100_RADIO_ON) ? "ON" : "OFF"); + outl(0x80020800, 0xcf8); + outb(0x6f, 0x0072); + outl(0x1800ffff, 0x1184); + outb(state, 0x00b2); + av5100_radio = state; +} + + +/* + * proc stuff + */ +static struct proc_dir_entry *dir_base = NULL; + +static int proc_set_radio(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + av5100_set_radio(buffer[0] == '0' ? AV5100_RADIO_OFF : AV5100_RADIO_ON); + + return count; +} + +static int proc_get_radio(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = 0; + + len += snprintf(page, count, DRV_NAME ": %d\n", + av5100_radio == AV5100_RADIO_OFF ? 0 : 1); + + *eof = 1; + return len; +} + + +static void av5100_proc_cleanup(void) +{ + if (dir_base) { + remove_proc_entry("radio", dir_base); + remove_proc_entry(DRV_NAME, NULL); + dir_base = NULL; + } +} + + +static int av5100_proc_init(void) +{ + struct proc_dir_entry *ent; + int err = 0; + + dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL); + if (dir_base == NULL) { + printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/" + DRV_NAME "\n"); + err = -ENOMEM; + goto fail; + } + + + ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR, + dir_base); + if (ent) { + ent->read_proc = proc_get_radio; + ent->write_proc = proc_set_radio; + } else { + printk(KERN_ERR + "Unable to initialize /proc/" DRV_NAME "/radio\n"); + err = -ENOMEM; + goto fail; + } + + return 0; + + fail: + av5100_proc_cleanup(); + return err; +} + +/* + * module stuff + */ +static int __init av5100_init(void) +{ + av5100_proc_init(); + + av5100_set_radio((radio == 1) ? AV5100_RADIO_ON : AV5100_RADIO_OFF); + + return 0; +} + +static void __exit av5100_exit(void) +{ + av5100_set_radio(AV5100_RADIO_OFF); + + av5100_proc_cleanup(); +} + +module_init(av5100_init); +module_exit(av5100_exit); + +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ --- linux-2.6.27.orig/ubuntu/rfkill/Makefile +++ linux-2.6.27/ubuntu/rfkill/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for Ubuntu additional drivers +# + +obj-$(CONFIG_AVERATEC_5100P) += av5100.o +obj-$(CONFIG_PACKARDBELL_E5) += pbe5.o --- linux-2.6.27.orig/ubuntu/drbd/drbd_req.h +++ linux-2.6.27/ubuntu/drbd/drbd_req.h @@ -0,0 +1,333 @@ +/* + drbd_req.h + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2006-2008, LINBIT Information Technologies GmbH. + Copyright (C) 2006-2008, Lars Ellenberg . + Copyright (C) 2006-2008, Philipp Reisner . + + DRBD is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + DRBD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _DRBD_REQ_H +#define _DRBD_REQ_H + +#include +#include + +#include +#include +#include "drbd_int.h" + +/* The request callbacks will be called in irq context by the IDE drivers, + and in Softirqs/Tasklets/BH context by the SCSI drivers, + and by the receiver and worker in kernel-thread context. + Try to get the locking right :) */ + +/* + * Objects of type struct drbd_request do only exist on a Primary node, and are + * associated with IO requests originating from the block layer above us. + * + * There are quite a few things that may happen to a drbd request + * during its lifetime. + * + * It will be created. + * It will be marked with the intention to be + * submitted to local disk and/or + * send via the network. + * + * It has to be placed on the transfer log and other housekeeping lists, + * In case we have a network connection. + * FIXME I believe that for consistency we should place even READ requests + * on these lists, so we can moan when we detect that the other node is + * writing to an area that we currently read from (when this happens, our + * users are broken). + * + * It may be identified as a concurrent (write) request + * and be handled accordingly. + * + * It may me handed over to the local disk subsystem. + * It may be completed by the local disk subsystem, + * either sucessfully or with io-error. + * In case it is a READ request, and it failed locally, + * it may be retried remotely. + * + * It may be queued for sending. + * It may be handed over to the network stack, + * which may fail. + * It may be acknowledged by the "peer" according to the wire_protocol in use. + * this may be a negative ack. + * It may receive a faked ack when the network connection is lost and the + * transfer log is cleaned up. + * Sending may be canceled due to network connection loss. + * When it finally has outlived its time, + * corresponding dirty bits in the resync-bitmap may be cleared or set, + * it will be destroyed, + * and completion will be signalled to the originator, + * with or without "success". + * + * See also documentation/drbd-request-state-overview.dot + * (dot -Tps2 documentation/drbd-request-state-overview.dot | display -) + */ + +enum drbd_req_event { + created, + to_be_send, + to_be_submitted, + + /* XXX yes, now I am inconsistent... + * these two are not "events" but "actions" + * oh, well... */ + queue_for_net_write, + queue_for_net_read, + + send_canceled, + send_failed, + handed_over_to_network, + connection_lost_while_pending, + recv_acked_by_peer, + write_acked_by_peer, + write_acked_by_peer_and_sis, /* and set_in_sync */ + conflict_discarded_by_peer, + neg_acked, + barrier_acked, /* in protocol A and B */ + data_received, /* (remote read) */ + + read_completed_with_error, + write_completed_with_error, + completed_ok, +}; + +/* encoding of request states for now. we don't actually need that many bits. + * we don't need to do atomic bit operations either, since most of the time we + * need to look at the connection state and/or manipulate some lists at the + * same time, so we should hold the request lock anyways. + */ +enum drbd_req_state_bits { + /* 210 + * 000: no local possible + * 001: to be submitted + * UNUSED, we could map: 011: submitted, completion still pending + * 110: completed ok + * 010: completed with error + */ + __RQ_LOCAL_PENDING, + __RQ_LOCAL_COMPLETED, + __RQ_LOCAL_OK, + + /* 76543 + * 00000: no network possible + * 00001: to be send + * 00011: to be send, on worker queue + * 00101: sent, expecting recv_ack (B) or write_ack (C) + * 11101: sent, + * recv_ack (B) or implicit "ack" (A), + * still waiting for the barrier ack. + * master_bio may already be completed and invalidated. + * 11100: write_acked (C), + * data_received (for remote read, any protocol) + * or finally the barrier ack has arrived (B,A)... + * request can be freed + * 01100: neg-acked (write, protocol C) + * or neg-d-acked (read, any protocol) + * or killed from the transfer log + * during cleanup after connection loss + * request can be freed + * 01000: canceled or send failed... + * request can be freed + */ + + /* if "SENT" is not set, yet, this can still fail or be canceled. + * if "SENT" is set already, we still wait for an Ack packet. + * when cleared, the master_bio may be completed. + * in (B,A) the request object may still linger on the transaction log + * until the corresponding barrier ack comes in */ + __RQ_NET_PENDING, + + /* If it is QUEUED, and it is a WRITE, it is also registered in the + * transfer log. Currently we need this flag to avoid conflicts between + * worker canceling the request and tl_clear_barrier killing it from + * transfer log. We should restructure the code so this conflict does + * no longer occur. */ + __RQ_NET_QUEUED, + + /* well, actually only "handed over to the network stack". + * + * TODO can potentially be dropped because of the similar meaning + * of RQ_NET_SENT and ~RQ_NET_QUEUED. + * however it is not exactly the same. before we drop it + * we must ensure that we can tell a request with network part + * from a request without, regardless of what happens to it. */ + __RQ_NET_SENT, + + /* when set, the request may be freed (if RQ_NET_QUEUED is clear). + * in (C) this happens when WriteAck is received, + * in (B,A) when the corresponding BarrierAck is received */ + __RQ_NET_DONE, + + /* whether or not we know (C) or pretend (B,A) that the write + * was successfully written on the peer. + */ + __RQ_NET_OK, + + /* peer called drbd_set_in_sync() for this write */ + __RQ_NET_SIS, + + /* keep this last, its for the RQ_NET_MASK */ + __RQ_NET_MAX, +}; + +#define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) +#define RQ_LOCAL_COMPLETED (1UL << __RQ_LOCAL_COMPLETED) +#define RQ_LOCAL_OK (1UL << __RQ_LOCAL_OK) + +#define RQ_LOCAL_MASK ((RQ_LOCAL_OK << 1)-1) /* 0x07 */ + +#define RQ_NET_PENDING (1UL << __RQ_NET_PENDING) +#define RQ_NET_QUEUED (1UL << __RQ_NET_QUEUED) +#define RQ_NET_SENT (1UL << __RQ_NET_SENT) +#define RQ_NET_DONE (1UL << __RQ_NET_DONE) +#define RQ_NET_OK (1UL << __RQ_NET_OK) +#define RQ_NET_SIS (1UL << __RQ_NET_SIS) + +/* 0x1f8 */ +#define RQ_NET_MASK (((1UL << __RQ_NET_MAX)-1) & ~RQ_LOCAL_MASK) + +/* epoch entries */ +static inline +struct hlist_head *ee_hash_slot(struct drbd_conf *mdev, sector_t sector) +{ + BUG_ON(mdev->ee_hash_s == 0); + return mdev->ee_hash + + ((unsigned int)(sector>>HT_SHIFT) % mdev->ee_hash_s); +} + +/* transfer log (drbd_request objects) */ +static inline +struct hlist_head *tl_hash_slot(struct drbd_conf *mdev, sector_t sector) +{ + BUG_ON(mdev->tl_hash_s == 0); + return mdev->tl_hash + + ((unsigned int)(sector>>HT_SHIFT) % mdev->tl_hash_s); +} + +/* when we receive the ACK for a write request, + * verify that we actually know about it */ +static inline struct drbd_request *_ack_id_to_req(struct drbd_conf *mdev, + u64 id, sector_t sector) +{ + struct hlist_head *slot = tl_hash_slot(mdev, sector); + struct hlist_node *n; + struct drbd_request *req; + + hlist_for_each_entry(req, n, slot, colision) { + if ((unsigned long)req == (unsigned long)id) + { + if (req->sector != sector) { + ERR("_ack_id_to_req: found req %p but it has " + "wrong sector (%llus versus %llus)\n", req, + (unsigned long long)req->sector, + (unsigned long long)sector); + break; + } + return req; + } + } + ERR("_ack_id_to_req: failed to find req %p, sector %llus in list\n", + (void *)(unsigned long)id, (unsigned long long)sector); + return NULL; +} + +/* application reads (drbd_request objects) */ +static struct hlist_head *ar_hash_slot(struct drbd_conf *mdev, sector_t sector) +{ + return mdev->app_reads_hash + + ((unsigned int)(sector) % APP_R_HSIZE); +} + +/* when we receive the answer for a read request, + * verify that we actually know about it */ +static inline struct drbd_request *_ar_id_to_req(struct drbd_conf *mdev, + u64 id, sector_t sector) +{ + struct hlist_head *slot = ar_hash_slot(mdev, sector); + struct hlist_node *n; + struct drbd_request *req; + + hlist_for_each_entry(req, n, slot, colision) { + if ((unsigned long)req == (unsigned long)id) + { + D_ASSERT(req->sector == sector); + return req; + } + } + return NULL; +} + +static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev, + struct bio *bio_src) +{ + struct bio *bio; + struct drbd_request *req = + mempool_alloc(drbd_request_mempool, GFP_NOIO); + if (likely(req)) { + bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */ + + req->rq_state = 0; + req->mdev = mdev; + req->master_bio = bio_src; + req->private_bio = bio; + req->epoch = 0; + req->sector = bio->bi_sector; + req->size = bio->bi_size; + req->start_time = jiffies; + INIT_HLIST_NODE(&req->colision); + INIT_LIST_HEAD(&req->tl_requests); + + bio->bi_private = req; + bio->bi_end_io = drbd_endio_pri; + bio->bi_next = NULL; + } + return req; +} + +static inline void drbd_req_free(struct drbd_request *req) +{ + mempool_free(req, drbd_request_mempool); +} + +static inline int overlaps(sector_t s1, int l1, sector_t s2, int l2) +{ + return !( ( s1 + (l1>>9) <= s2 ) || ( s1 >= s2 + (l2>>9) ) ); +} + +/* aparently too large to be inlined... + * moved to drbd_req.c */ +extern void _req_may_be_done(struct drbd_request *req, int error); +extern void _req_mod(struct drbd_request *req, + enum drbd_req_event what, int error); + +/* If you need it irqsave, do it your self! */ +static inline void req_mod(struct drbd_request *req, + enum drbd_req_event what, int error) +{ + struct drbd_conf *mdev = req->mdev; + spin_lock_irq(&mdev->req_lock); + _req_mod(req, what, error); + spin_unlock_irq(&mdev->req_lock); +} +#endif --- linux-2.6.27.orig/ubuntu/drbd/lru_cache.c +++ linux-2.6.27/ubuntu/drbd/lru_cache.c @@ -0,0 +1,398 @@ +/* +-*- linux-c -*- + lru_cache.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. + Copyright (C) 2003-2008, Philipp Reisner . + Copyright (C) 2003-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include +#include +#include /* for memset */ +#include /* for seq_printf */ +#include "lru_cache.h" + +#define STATIC static + +/* this is developers aid only! */ +#define PARANOIA_ENTRY() BUG_ON(test_and_set_bit(__LC_PARANOIA, &lc->flags)) +#define PARANOIA_LEAVE() do { clear_bit(__LC_PARANOIA, &lc->flags); smp_mb__after_clear_bit(); } while (0) +#define RETURN(x...) do { PARANOIA_LEAVE(); return x ; } while (0) + +static inline size_t size_of_lc(unsigned int e_count, size_t e_size) +{ + return sizeof(struct lru_cache) + + e_count * (e_size + sizeof(struct hlist_head)); +} + +static inline void lc_init(struct lru_cache *lc, + const size_t bytes, const char *name, + const unsigned int e_count, const size_t e_size, + void *private_p) +{ + struct lc_element *e; + unsigned int i; + + memset(lc, 0, bytes); + INIT_LIST_HEAD(&lc->in_use); + INIT_LIST_HEAD(&lc->lru); + INIT_LIST_HEAD(&lc->free); + lc->element_size = e_size; + lc->nr_elements = e_count; + lc->new_number = -1; + lc->lc_private = private_p; + lc->name = name; + for (i = 0; i < e_count; i++) { + e = lc_entry(lc, i); + e->lc_number = LC_FREE; + list_add(&e->list, &lc->free); + // memset(,0,) did the rest of init for us + } +} + +/** + * lc_alloc: allocates memory for @e_count objects of @e_size bytes plus the + * struct lru_cache, and the hash table slots. + * returns pointer to a newly initialized lru_cache object with said parameters. + */ +struct lru_cache *lc_alloc(const char *name, unsigned int e_count, + size_t e_size, void *private_p) +{ + struct lru_cache *lc; + size_t bytes; + + BUG_ON(!e_count); + e_size = max(sizeof(struct lc_element),e_size); + bytes = size_of_lc(e_count, e_size); + lc = vmalloc(bytes); + if (lc) + lc_init(lc, bytes, name, e_count, e_size, private_p); + return lc; +} + +/** + * lc_free: Frees memory allocated by lc_alloc. + * @lc: The lru_cache object + */ +void lc_free(struct lru_cache *lc) +{ + vfree(lc); +} + +/** + * lc_reset: does a full reset for @lc and the hash table slots. + * It is roughly the equivalent of re-allocating a fresh lru_cache object, + * basically a short cut to lc_free(lc); lc = lc_alloc(...); + */ +void lc_reset(struct lru_cache *lc) +{ + lc_init(lc, size_of_lc(lc->nr_elements, lc->element_size), lc->name, + lc->nr_elements, lc->element_size, lc->lc_private); +} + +size_t lc_printf_stats(struct seq_file *seq, struct lru_cache* lc) +{ + /* NOTE: + * total calls to lc_get are + * (starving + hits + misses) + * misses include "dirty" count (update from an other thread in + * progress) and "changed", when this in fact lead to an successful + * update of the cache. + */ + return seq_printf(seq, "\t%s: used:%u/%u " + "hits:%lu misses:%lu starving:%lu dirty:%lu changed:%lu\n", + lc->name, lc->used, lc->nr_elements, + lc->hits, lc->misses, lc->starving, lc->dirty, lc->changed); +} + +static unsigned int lc_hash_fn(struct lru_cache *lc, unsigned int enr) +{ + return enr % lc->nr_elements; +} + + +/** + * lc_find: Returns the pointer to an element, if the element is present + * in the hash table. In case it is not this function returns NULL. + * @lc: The lru_cache object + * @enr: element number + */ +struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr) +{ + struct hlist_node *n; + struct lc_element *e; + + BUG_ON(!lc); + BUG_ON(!lc->nr_elements); + hlist_for_each_entry(e, n, lc->slot + lc_hash_fn(lc, enr), colision) { + if (e->lc_number == enr) + return e; + } + return NULL; +} + +STATIC struct lc_element *lc_evict(struct lru_cache *lc) +{ + struct list_head *n; + struct lc_element *e; + + if (list_empty(&lc->lru)) return NULL; + + n = lc->lru.prev; + e = list_entry(n, struct lc_element, list); + + list_del(&e->list); + hlist_del(&e->colision); + return e; +} + +/** + * lc_del: Removes an element from the cache (and therefore adds the + * element's storage to the free list) + * + * @lc: The lru_cache object + * @e: The element to remove + */ +void lc_del(struct lru_cache *lc, struct lc_element *e) +{ + /* FIXME what to do with refcnt != 0 ? */ + PARANOIA_ENTRY(); + BUG_ON(e->refcnt); + list_del(&e->list); + hlist_del_init(&e->colision); + e->lc_number = LC_FREE; + e->refcnt = 0; + list_add(&e->list, &lc->free); + RETURN(); +} + +STATIC struct lc_element *lc_get_unused_element(struct lru_cache *lc) +{ + struct list_head *n; + + if (list_empty(&lc->free)) return lc_evict(lc); + + n = lc->free.next; + list_del(n); + return list_entry(n, struct lc_element, list); +} + +STATIC int lc_unused_element_available(struct lru_cache *lc) +{ + if (!list_empty(&lc->free)) return 1; /* something on the free list */ + if (!list_empty(&lc->lru)) return 1; /* something to evict */ + + return 0; +} + + +/** + * lc_get: Finds an element in the cache, increases its usage count, + * "touches" and returns it. + * In case the requested number is not present, it needs to be added to the + * cache. Therefore it is possible that an other element becomes eviced from + * the cache. In either case, the user is notified so he is able to e.g. keep + * a persistent log of the cache changes, and therefore the objects in use. + * + * Return values: + * NULL if the requested element number was not in the cache, and no unused + * element could be recycled + * pointer to the element with the REQUESTED element number + * In this case, it can be used right away + * + * pointer to an UNUSED element with some different element number. + * In this case, the cache is marked dirty, and the returned element + * pointer is removed from the lru list and hash collision chains. + * The user now should do whatever houskeeping is necessary. Then he + * needs to call lc_element_changed(lc,element_pointer), to finish the + * change. + * + * NOTE: The user needs to check the lc_number on EACH use, so he recognizes + * any cache set change. + * + * @lc: The lru_cache object + * @enr: element number + */ +struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr) +{ + struct lc_element *e; + + BUG_ON(!lc); + BUG_ON(!lc->nr_elements); + + PARANOIA_ENTRY(); + if (lc->flags & LC_STARVING) { + ++lc->starving; + RETURN(NULL); + } + + e = lc_find(lc, enr); + if (e) { + ++lc->hits; + if (e->refcnt++ == 0) + lc->used++; + list_move(&e->list, &lc->in_use); /* Not evictable... */ + RETURN(e); + } + + ++lc->misses; + + /* In case there is nothing available and we can not kick out + * the LRU element, we have to wait ... + */ + if (!lc_unused_element_available(lc)) { + __set_bit(__LC_STARVING, &lc->flags); + RETURN(NULL); + } + + /* it was not present in the cache, find an unused element, + * which then is replaced. + * we need to update the cache; serialize on lc->flags & LC_DIRTY + */ + if (test_and_set_bit(__LC_DIRTY, &lc->flags)) { + ++lc->dirty; + RETURN(NULL); + } + + e = lc_get_unused_element(lc); + BUG_ON(!e); + + clear_bit(__LC_STARVING, &lc->flags); + BUG_ON(++e->refcnt != 1); + lc->used++; + + lc->changing_element = e; + lc->new_number = enr; + + RETURN(e); +} + +/* similar to lc_get, + * but only gets a new reference on an existing element. + * you either get the requested element, or NULL. + */ +struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr) +{ + struct lc_element *e; + + BUG_ON(!lc); + BUG_ON(!lc->nr_elements); + + PARANOIA_ENTRY(); + if (lc->flags & LC_STARVING) { + ++lc->starving; + RETURN(NULL); + } + + e = lc_find(lc, enr); + if (e) { + ++lc->hits; + if (e->refcnt++ == 0) + lc->used++; + list_move(&e->list, &lc->in_use); /* Not evictable... */ + } + RETURN(e); +} + +void lc_changed(struct lru_cache *lc, struct lc_element *e) +{ + PARANOIA_ENTRY(); + BUG_ON(e != lc->changing_element); + ++lc->changed; + e->lc_number = lc->new_number; + list_add(&e->list, &lc->in_use); + hlist_add_head(&e->colision, + lc->slot + lc_hash_fn(lc, lc->new_number)); + lc->changing_element = NULL; + lc->new_number = -1; + clear_bit(__LC_DIRTY, &lc->flags); + smp_mb__after_clear_bit(); + PARANOIA_LEAVE(); +} + + +unsigned int lc_put(struct lru_cache *lc, struct lc_element *e) +{ + BUG_ON(!lc); + BUG_ON(!lc->nr_elements); + BUG_ON(!e); + + PARANOIA_ENTRY(); + BUG_ON(e->refcnt == 0); + BUG_ON(e == lc->changing_element); + if (--e->refcnt == 0) { + /* move it to the front of LRU. */ + list_move(&e->list, &lc->lru); + lc->used--; + clear_bit(__LC_STARVING, &lc->flags); + smp_mb__after_clear_bit(); + } + RETURN(e->refcnt); +} + + +/** + * lc_set: Sets an element in the cache. You might use this function to + * setup the cache. It is expected that the elements are properly initialized. + * @lc: The lru_cache object + * @enr: element number + * @index: The elements' position in the cache + */ +void lc_set(struct lru_cache *lc, unsigned int enr, int index) +{ + struct lc_element *e; + + if (index < 0 || index >= lc->nr_elements) + return; + + e = lc_entry(lc, index); + e->lc_number = enr; + + hlist_del_init(&e->colision); + hlist_add_head( &e->colision, lc->slot + lc_hash_fn(lc, enr) ); + list_move(&e->list, e->refcnt ? &lc->in_use : &lc->lru); +} + +/** + * lc_dump: Dump a complete LRU cache to seq in textual form. + */ +void lc_dump(struct lru_cache *lc, struct seq_file *seq, char *utext, + void (*detail) (struct seq_file *, struct lc_element *) ) +{ + unsigned int nr_elements = lc->nr_elements; + struct lc_element *e; + int i; + + seq_printf(seq, "\tnn: lc_number refcnt %s\n ", utext); + for (i = 0; i < nr_elements; i++) { + e = lc_entry(lc, i); + if (e->lc_number == LC_FREE) { + seq_printf(seq, "\t%2d: FREE\n", i ); + } else { + seq_printf(seq, "\t%2d: %4u %4u ", i, + e->lc_number, + e->refcnt ); + detail(seq, e); + } + } +} + --- linux-2.6.27.orig/ubuntu/drbd/drbd_receiver.c +++ linux-2.6.27/ubuntu/drbd/drbd_receiver.c @@ -0,0 +1,3652 @@ +/* +-*- linux-c -*- + drbd_receiver.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 1999-2008, Philipp Reisner . + Copyright (C) 2002-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#ifdef HAVE_LINUX_SCATTERLIST_H +#include +#endif +#include +#include "drbd_int.h" +#include "drbd_req.h" + +#ifdef DBG_ASSERTS +void drbd_assert_breakpoint(struct drbd_conf *mdev, char *exp, + char *file, int line) +{ + ERR("ASSERT( %s ) in %s:%d\n", exp, file, line); +} +#endif + +#define GFP_TRY ( __GFP_HIGHMEM | __GFP_NOWARN ) + +/** + * drbd_bp_alloc: Returns a page. Fails only if a signal comes in. + */ +STATIC struct page *drbd_pp_alloc(struct drbd_conf *mdev, gfp_t gfp_mask) +{ + unsigned long flags = 0; + struct page *page; + DEFINE_WAIT(wait); + + /* FIXME Add some usefull watermark again to "kick_lo", if pages get + * used up too quickly. The watermark that had been in place here did + * not make sense. + */ + + spin_lock_irqsave(&drbd_pp_lock, flags); + /* This lock needs to lock out irq because we might call drbd_pp_free() + from IRQ context. + FIXME but why irq _save_ ? + this is only called from drbd_alloc_ee, + and that is strictly process context! */ + page = drbd_pp_pool; + if (page) { + drbd_pp_pool = (struct page *)page_private(page); + set_page_private(page, 0); /* just to be polite */ + drbd_pp_vacant--; + } + spin_unlock_irqrestore(&drbd_pp_lock, flags); + if (page) + goto got_page; + + drbd_kick_lo(mdev); + + for (;;) { + prepare_to_wait(&drbd_pp_wait, &wait, TASK_INTERRUPTIBLE); + + /* try the pool again, maybe the drbd_kick_lo set some free */ + spin_lock_irqsave(&drbd_pp_lock, flags); + page = drbd_pp_pool; + if (page) { + drbd_pp_pool = (struct page *)page_private(page); + drbd_pp_vacant--; + } + spin_unlock_irqrestore(&drbd_pp_lock, flags); + + if (page) + break; + + /* hm. pool was empty. try to allocate from kernel. + * don't wait, if none is available, though. + */ + if (atomic_read(&mdev->pp_in_use) + < mdev->net_conf->max_buffers) { + page = alloc_page(GFP_TRY); + if (page) + break; + } + + /* doh. still no page. + * either used up the configured maximum number, + * or we are low on memory. + * wait for someone to return a page into the pool. + * unless, of course, someone signalled us. + */ + if (signal_pending(current)) { + DRBD_WARN("drbd_pp_alloc interrupted!\n"); + finish_wait(&drbd_pp_wait, &wait); + return NULL; + } + drbd_kick_lo(mdev); + schedule(); + } + finish_wait(&drbd_pp_wait, &wait); + + got_page: + atomic_inc(&mdev->pp_in_use); + return page; +} + +STATIC void drbd_pp_free(struct drbd_conf *mdev, struct page *page) +{ + unsigned long flags = 0; + int free_it; + + spin_lock_irqsave(&drbd_pp_lock, flags); + if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count) { + free_it = 1; + } else { + set_page_private(page, (unsigned long)drbd_pp_pool); + drbd_pp_pool = page; + drbd_pp_vacant++; + free_it = 0; + } + spin_unlock_irqrestore(&drbd_pp_lock, flags); + + atomic_dec(&mdev->pp_in_use); + + if (free_it) + __free_page(page); + + /* + * FIXME + * typically there are no waiters. + * we should try to avoid any unnecessary call to wake_up. + */ + wake_up(&drbd_pp_wait); +} + +/* +You need to hold the req_lock: + drbd_free_ee() + _drbd_wait_ee_list_empty() + +You must not have the req_lock: + drbd_alloc_ee() + drbd_init_ee() + drbd_release_ee() + drbd_ee_fix_bhs() + drbd_process_done_ee() + drbd_clear_done_ee() + drbd_wait_ee_list_empty() +*/ + +struct Tl_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev, + u64 id, + sector_t sector, + unsigned int data_size, + gfp_t gfp_mask) __must_hold(local) +{ + struct request_queue *q; + struct Tl_epoch_entry *e; + struct bio_vec *bvec; + struct page *page; + struct bio *bio; + unsigned int ds; + int i; + + e = mempool_alloc(drbd_ee_mempool, gfp_mask); + if (!e) { + ERR("alloc_ee: Allocation of an EE failed\n"); + return NULL; + } + + bio = bio_alloc(GFP_KERNEL, div_ceil(data_size, PAGE_SIZE)); + if (!bio) { + ERR("alloc_ee: Allocation of a bio failed\n"); + goto fail1; + } + + bio->bi_bdev = mdev->bc->backing_bdev; + bio->bi_sector = sector; + + ds = data_size; + while (ds) { + page = drbd_pp_alloc(mdev, gfp_mask); + if (!page) { + ERR("alloc_ee: Allocation of a page failed\n"); + goto fail2; + } + if (!bio_add_page(bio, page, min_t(int, ds, PAGE_SIZE), 0)) { + drbd_pp_free(mdev, page); + ERR("alloc_ee: bio_add_page(s=%llu," + "data_size=%u,ds=%u) failed\n", + (unsigned long long)sector, data_size, ds); + + q = bdev_get_queue(bio->bi_bdev); + if (q->merge_bvec_fn) { + struct bvec_merge_data bvm = { + .bi_bdev = bio->bi_bdev, + .bi_sector = bio->bi_sector, + .bi_size = bio->bi_size, + .bi_rw = bio->bi_rw, + }; + ERR("merge_bvec_fn() = %d\n", + q->merge_bvec_fn(q, &bvm, + &bio->bi_io_vec[bio->bi_vcnt])); + } + + /* dump more of the bio. */ + DUMPI(bio->bi_max_vecs); + DUMPI(bio->bi_vcnt); + DUMPI(bio->bi_size); + DUMPI(bio->bi_phys_segments); + DUMPI(bio->bi_hw_segments); + + goto fail2; + break; + } + ds -= min_t(int, ds, PAGE_SIZE); + } + + D_ASSERT( data_size == bio->bi_size); + + bio->bi_private = e; + e->mdev = mdev; + e->sector = sector; + e->size = bio->bi_size; + + e->private_bio = bio; + e->block_id = id; + INIT_HLIST_NODE(&e->colision); + e->barrier_nr = 0; + e->barrier_nr2 = 0; + e->flags = 0; + + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("allocated EE sec=%llus size=%u ee=%p\n", + (unsigned long long)sector, data_size, e); + ); + + return e; + + fail2: + __bio_for_each_segment(bvec, bio, i, 0) { + drbd_pp_free(mdev, bvec->bv_page); + } + bio_put(bio); + fail1: + mempool_free(e, drbd_ee_mempool); + + return NULL; +} + +void drbd_free_ee(struct drbd_conf *mdev, struct Tl_epoch_entry *e) +{ + struct bio *bio = e->private_bio; + struct bio_vec *bvec; + int i; + + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("Free EE sec=%llus size=%u ee=%p\n", + (unsigned long long)e->sector, e->size, e); + ); + + __bio_for_each_segment(bvec, bio, i, 0) { + drbd_pp_free(mdev, bvec->bv_page); + } + + bio_put(bio); + + D_ASSERT(hlist_unhashed(&e->colision)); + + mempool_free(e, drbd_ee_mempool); +} + +/* currently on module unload only */ +int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list) +{ + int count = 0; + struct Tl_epoch_entry *e; + struct list_head *le; + + spin_lock_irq(&mdev->req_lock); + while (!list_empty(list)) { + le = list->next; + list_del(le); + e = list_entry(le, struct Tl_epoch_entry, w.list); + drbd_free_ee(mdev, e); + count++; + } + spin_unlock_irq(&mdev->req_lock); + + return count; +} + + +STATIC void reclaim_net_ee(struct drbd_conf *mdev) +{ + struct Tl_epoch_entry *e; + struct list_head *le, *tle; + + /* The EEs are always appended to the end of the list. Since + they are sent in order over the wire, they have to finish + in order. As soon as we see the first not finished we can + stop to examine the list... */ + + list_for_each_safe(le, tle, &mdev->net_ee) { + e = list_entry(le, struct Tl_epoch_entry, w.list); + if ( drbd_bio_has_active_page(e->private_bio) ) break; + list_del(le); + drbd_free_ee(mdev, e); + } +} + + +/* + * This function is called from _asender only_ + * but see also comments in _req_mod(,barrier_acked) + * and receive_Barrier_no_tcq. + * + * Move entries from net_ee to done_ee, if ready. + * Grab done_ee, call all callbacks, free the entries. + * The callbacks typically send out ACKs. + */ +STATIC int drbd_process_done_ee(struct drbd_conf *mdev) +{ + LIST_HEAD(work_list); + struct Tl_epoch_entry *e, *t; + int ok = 1; + int do_clear_bit = test_bit(WRITE_ACK_PENDING, &mdev->flags); + + spin_lock_irq(&mdev->req_lock); + reclaim_net_ee(mdev); + list_splice_init(&mdev->done_ee, &work_list); + spin_unlock_irq(&mdev->req_lock); + + /* possible callbacks here: + * e_end_block, and e_end_resync_block, e_send_discard_ack. + * all ignore the last argument. + */ + list_for_each_entry_safe(e, t, &work_list, w.list) { + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("Process EE on done_ee sec=%llus size=%u ee=%p\n", + (unsigned long long)e->sector, e->size, e); + ); + /* list_del not necessary, next/prev members not touched */ + if (e->w.cb(mdev, &e->w, 0) == 0) ok = 0; + drbd_free_ee(mdev, e); + } + if (do_clear_bit) + clear_bit(WRITE_ACK_PENDING, &mdev->flags); + wake_up(&mdev->ee_wait); + + return ok; +} + + + +/* clean-up helper for drbd_disconnect */ +void _drbd_clear_done_ee(struct drbd_conf *mdev) +{ + struct list_head *le; + struct Tl_epoch_entry *e; + int n = 0; + + MUST_HOLD(&mdev->req_lock); + + reclaim_net_ee(mdev); + + while (!list_empty(&mdev->done_ee)) { + le = mdev->done_ee.next; + list_del(le); + e = list_entry(le, struct Tl_epoch_entry, w.list); + if (mdev->net_conf->wire_protocol == DRBD_PROT_C + || is_syncer_block_id(e->block_id)) + ++n; + + if (!hlist_unhashed(&e->colision)) hlist_del_init(&e->colision); + drbd_free_ee(mdev, e); + } + + sub_unacked(mdev, n); +} + +void _drbd_wait_ee_list_empty(struct drbd_conf *mdev, struct list_head *head) +{ + DEFINE_WAIT(wait); + MUST_HOLD(&mdev->req_lock); + + /* avoids spin_lock/unlock + * and calling prepare_to_wait in the fast path */ + while (!list_empty(head)) { + prepare_to_wait(&mdev->ee_wait, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock_irq(&mdev->req_lock); + drbd_kick_lo(mdev); + schedule(); + finish_wait(&mdev->ee_wait, &wait); + spin_lock_irq(&mdev->req_lock); + } +} + +void drbd_wait_ee_list_empty(struct drbd_conf *mdev, struct list_head *head) +{ + spin_lock_irq(&mdev->req_lock); + _drbd_wait_ee_list_empty(mdev, head); + spin_unlock_irq(&mdev->req_lock); +} + +STATIC struct socket *drbd_accept(struct drbd_conf *mdev, struct socket *sock) +{ + struct socket *newsock; + int err = 0; + + err = sock->ops->listen(sock, 5); + if (err) + goto out; + + if (sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock)) + goto out; + + newsock->type = sock->type; + newsock->ops = sock->ops; + + err = newsock->ops->accept(sock, newsock, 0); + if (err < 0) + goto out_release; + + return newsock; + +out_release: + sock_release(newsock); +out: + if (err != -EAGAIN && err != -EINTR) + ERR("accept failed! %d\n", err); + return NULL; +} + +STATIC int drbd_recv_short(struct drbd_conf *mdev, struct socket *sock, + void *buf, size_t size, int flags) +{ + mm_segment_t oldfs; + struct kvec iov = { + .iov_base = buf, + .iov_len = size, + }; + struct msghdr msg = { + .msg_iovlen = 1, + .msg_iov = (struct iovec *)&iov, + .msg_flags = (flags ? flags : MSG_WAITALL | MSG_NOSIGNAL) + }; + int rv; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + rv = sock_recvmsg(sock, &msg, size, msg.msg_flags); + set_fs(oldfs); + + return rv; +} + +STATIC int drbd_recv(struct drbd_conf *mdev, void *buf, size_t size) +{ + mm_segment_t oldfs; + struct kvec iov = { + .iov_base = buf, + .iov_len = size, + }; + struct msghdr msg = { + .msg_iovlen = 1, + .msg_iov = (struct iovec *)&iov, + .msg_flags = MSG_WAITALL | MSG_NOSIGNAL + }; + int rv; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + + for (;;) { + rv = sock_recvmsg(mdev->data.socket, &msg, size, msg.msg_flags); + if (rv == size) + break; + + /* Note: + * ECONNRESET other side closed the connection + * ERESTARTSYS (on sock) we got a signal + */ + + if (rv < 0) { + if (rv == -ECONNRESET) + INFO("sock was reset by peer\n"); + else if (rv != -ERESTARTSYS) + ERR("sock_recvmsg returned %d\n", rv); + break; + } else if (rv == 0) { + INFO("sock was shut down by peer\n"); + break; + } else { + /* signal came in, or peer/link went down, + * after we read a partial message + */ + /* D_ASSERT(signal_pending(current)); */ + break; + } + }; + + set_fs(oldfs); + + if (rv != size) + drbd_force_state(mdev, NS(conn, BrokenPipe)); + + return rv; +} + +STATIC struct socket *drbd_try_connect(struct drbd_conf *mdev) +{ + int err; + struct socket *sock; + struct sockaddr_in src_in; + + if (!inc_net(mdev)) return NULL; + + err = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); + if (err) { + dec_net(mdev); + ERR("sock_creat(..)=%d\n", err); + return NULL; + } + + sock->sk->sk_rcvtimeo = + sock->sk->sk_sndtimeo = mdev->net_conf->try_connect_int*HZ; + + /* explicitly bind to the configured IP as source IP + * for the outgoing connections. + * This is needed for multihomed hosts and to be + * able to use lo: interfaces for drbd. + * Make sure to use 0 as portnumber, so linux selects + * a free one dynamically. + */ + memcpy(&src_in, &(mdev->net_conf->my_addr), sizeof(struct sockaddr_in)); + src_in.sin_port = 0; + + err = sock->ops->bind(sock, + (struct sockaddr *) &src_in, + sizeof(struct sockaddr_in)); + if (err) { + ERR("Unable to bind source sock (%d)\n", err); + sock_release(sock); + sock = NULL; + dec_net(mdev); + return sock; + } + + err = sock->ops->connect(sock, + (struct sockaddr *)mdev->net_conf->peer_addr, + mdev->net_conf->peer_addr_len, 0); + + if (err) { + sock_release(sock); + sock = NULL; + } + + dec_net(mdev); + return sock; +} + +STATIC struct socket *drbd_wait_for_connect(struct drbd_conf *mdev) +{ + int err; + struct socket *sock, *sock2; + + if (!inc_net(mdev)) return NULL; + + err = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock2); + if (err) { + dec_net(mdev); + ERR("sock_creat(..)=%d\n", err); + return NULL; + } + + sock2->sk->sk_reuse = 1; /* SO_REUSEADDR */ + sock2->sk->sk_rcvtimeo = + sock2->sk->sk_sndtimeo = mdev->net_conf->try_connect_int*HZ; + + err = sock2->ops->bind(sock2, + (struct sockaddr *) mdev->net_conf->my_addr, + mdev->net_conf->my_addr_len); + dec_net(mdev); + + if (err) { + ERR("Unable to bind sock2 (%d)\n", err); + sock_release(sock2); + drbd_force_state(mdev, NS(conn, Disconnecting)); + return NULL; + } + + sock = drbd_accept(mdev, sock2); + sock_release(sock2); + + return sock; +} + +int drbd_do_handshake(struct drbd_conf *mdev); +int drbd_do_auth(struct drbd_conf *mdev); + +STATIC int drbd_send_fp(struct drbd_conf *mdev, + struct socket *sock, enum Drbd_Packet_Cmd cmd) +{ + struct Drbd_Header *h = (struct Drbd_Header *) &mdev->data.sbuf.head; + + return _drbd_send_cmd(mdev, sock, cmd, h, sizeof(*h), 0); +} + +STATIC enum Drbd_Packet_Cmd drbd_recv_fp(struct drbd_conf *mdev, struct socket *sock) +{ + struct Drbd_Header *h = (struct Drbd_Header *) &mdev->data.sbuf.head; + int rr; + + rr = drbd_recv_short(mdev, sock, h, sizeof(*h), 0); + + if (rr == sizeof(*h) && h->magic == BE_DRBD_MAGIC) + return be16_to_cpu(h->command); + + return 0xffff; +} + +/** + * drbd_socket_okay: + * Tests if the connection behind the socket still exists. If not it frees + * the socket. + */ +STATIC int drbd_socket_okay(struct drbd_conf *mdev, struct socket **sock) +{ + int rr; + char tb[4]; + + rr = drbd_recv_short(mdev, *sock, tb, 4, MSG_DONTWAIT | MSG_PEEK); + + if (rr > 0 || rr == -EAGAIN) { + return TRUE; + } else { + sock_release(*sock); + *sock = NULL; + return FALSE; + } +} + +/* + * return values: + * 1 yess, we have a valid connection + * 0 oops, did not work out, please try again + * -1 peer talks different language, + * no point in trying again, please go standalone. + * -2 We do not have a network config... + */ +STATIC int drbd_connect(struct drbd_conf *mdev) +{ + struct socket *s, *sock, *msock; + int try, h, ok; + + D_ASSERT(!mdev->data.socket); + + if (test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) + ERR("CREATE_BARRIER flag was set in drbd_connect - now cleared!\n"); + + if (drbd_request_state(mdev, NS(conn, WFConnection)) < SS_Success ) + return -2; + + clear_bit(DISCARD_CONCURRENT, &mdev->flags); + + sock = NULL; + msock = NULL; + + do { + for (try = 0;;) { + /* 3 tries, this should take less than a second! */ + s = drbd_try_connect(mdev); + if (s || ++try >= 3) + break; + /* give the other side time to call bind() & listen() */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 10); + } + + if (s) { + if (!sock) { + drbd_send_fp(mdev, s, HandShakeS); + sock = s; + s = NULL; + } else if (!msock) { + drbd_send_fp(mdev, s, HandShakeM); + msock = s; + s = NULL; + } else { + ERR("Logic error in drbd_connect()\n"); + return -1; + } + } + + if (sock && msock) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 10); + ok = drbd_socket_okay(mdev, &sock); + ok = drbd_socket_okay(mdev, &msock) && ok; + if (ok) break; + } + + s = drbd_wait_for_connect(mdev); + if (s) { + switch (drbd_recv_fp(mdev, s)) { + case HandShakeS: + if (sock) + sock_release(sock); + sock = s; + break; + case HandShakeM: + if (msock) + sock_release(msock); + msock = s; + set_bit(DISCARD_CONCURRENT, &mdev->flags); + break; + default: + DRBD_WARN("Error receiving initial packet\n"); + sock_release(s); + } + } + + if (mdev->state.conn <= Disconnecting) + return -1; + if (signal_pending(current)) { + flush_signals(current); + smp_rmb(); + if (get_t_state(&mdev->receiver) == Exiting) { + if (sock) + sock_release(sock); + if (msock) + sock_release(msock); + return -1; + } + } + + if (sock && msock) { + ok = drbd_socket_okay(mdev, &sock); + ok = drbd_socket_okay(mdev, &msock) && ok; + if (ok) break; + } + } while (1); + + msock->sk->sk_reuse = 1; /* SO_REUSEADDR */ + sock->sk->sk_reuse = 1; /* SO_REUSEADDR */ + + sock->sk->sk_allocation = GFP_NOIO; + msock->sk->sk_allocation = GFP_NOIO; + + sock->sk->sk_priority = TC_PRIO_BULK; + /* FIXME fold to limits. should be done in drbd_ioctl */ + sock->sk->sk_sndbuf = mdev->net_conf->sndbuf_size; + sock->sk->sk_rcvbuf = mdev->net_conf->sndbuf_size; + /* NOT YET ... + * sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10; + * sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; + * first set it to the HandShake timeout, wich is hardcoded for now: */ + sock->sk->sk_sndtimeo = + sock->sk->sk_rcvtimeo = 2*HZ; + sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK; + + msock->sk->sk_priority = TC_PRIO_INTERACTIVE; + msock->sk->sk_sndbuf = 2*32767; + msock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10; + msock->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ; + + mdev->data.socket = sock; + mdev->meta.socket = msock; + mdev->last_received = jiffies; + + D_ASSERT(mdev->asender.task == NULL); + + h = drbd_do_handshake(mdev); + if (h <= 0) + return h; + + if (mdev->cram_hmac_tfm) { + /* drbd_request_state(mdev, NS(conn, WFAuth)); */ + if (!drbd_do_auth(mdev)) { + ERR("Authentication of peer failed\n"); + return -1; + } + } + + if (drbd_request_state(mdev, NS(conn, WFReportParams)) < SS_Success) + return 0; + + sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10; + sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; + + atomic_set(&mdev->packet_seq, 0); + mdev->peer_seq = 0; + + drbd_thread_start(&mdev->asender); + + drbd_send_protocol(mdev); + drbd_send_sync_param(mdev, &mdev->sync_conf); + drbd_send_sizes(mdev); + drbd_send_uuids(mdev); + drbd_send_state(mdev); + clear_bit(USE_DEGR_WFC_T, &mdev->flags); + + return 1; +} + +STATIC int drbd_recv_header(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + int r; + + r = drbd_recv(mdev, h, sizeof(*h)); + + if (unlikely( r != sizeof(*h) )) { + ERR("short read expecting header on sock: r=%d\n", r); + return FALSE; + }; + h->command = be16_to_cpu(h->command); + h->length = be16_to_cpu(h->length); + if (unlikely( h->magic != BE_DRBD_MAGIC )) { + ERR("magic?? on data m: 0x%lx c: %d l: %d\n", + (long)be32_to_cpu(h->magic), + h->command, h->length); + return FALSE; + } + mdev->last_received = jiffies; + + return TRUE; +} + +STATIC int receive_Barrier_no_tcq(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + int rv; + int epoch_size; + struct Drbd_Barrier_Packet *p = (struct Drbd_Barrier_Packet *)h; + + ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; + + rv = drbd_recv(mdev, h->payload, h->length); + ERR_IF(rv != h->length) return FALSE; + + inc_unacked(mdev); + + if (mdev->net_conf->wire_protocol != DRBD_PROT_C) + drbd_kick_lo(mdev); + + spin_lock_irq(&mdev->req_lock); + _drbd_wait_ee_list_empty(mdev, &mdev->active_ee); + epoch_size = mdev->epoch_size; + mdev->epoch_size = 0; + spin_unlock_irq(&mdev->req_lock); + + /* BarrierAck may imply that the corresponding extent is dropped from + * the activity log, which means it would not be resynced in case the + * Primary crashes now. + * Just waiting for write_completion is not enough, + * better flush to make sure it is all on stable storage. */ + if (!test_bit(LL_DEV_NO_FLUSH, &mdev->flags) && inc_local(mdev)) { + rv = blkdev_issue_flush(mdev->bc->backing_bdev, NULL); + dec_local(mdev); + if (rv == -EOPNOTSUPP) /* don't try again */ + set_bit(LL_DEV_NO_FLUSH, &mdev->flags); + if (rv) + ERR("local disk flush failed with status %d\n",rv); + } + + /* FIXME CAUTION! receiver thread sending via msock. + * to make sure this BarrierAck will not be received before the asender + * had a chance to send all the write acks corresponding to this epoch, + * wait_for that bit to clear... */ + set_bit(WRITE_ACK_PENDING, &mdev->flags); + wake_asender(mdev); + rv = wait_event_interruptible(mdev->ee_wait, + !test_bit(WRITE_ACK_PENDING, &mdev->flags)); + + if (rv == 0 && mdev->state.conn >= Connected) + rv = drbd_send_b_ack(mdev, p->barrier, epoch_size); + else + rv = 0; + dec_unacked(mdev); + + return rv; +} + +/* used from receive_RSDataReply (recv_resync_read) + * and from receive_Data */ +STATIC struct Tl_epoch_entry * +read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __must_hold(local) +{ + struct Tl_epoch_entry *e; + struct bio_vec *bvec; + struct page *page; + struct bio *bio; + int dgs, ds, i, rr; + void *dig_in = mdev->int_dig_in; + void *dig_vv = mdev->int_dig_vv; + + dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ? + crypto_hash_digestsize(mdev->integrity_r_tfm) : 0; + + if (dgs) { + rr = drbd_recv(mdev, dig_in, dgs); + if (rr != dgs) { + DRBD_WARN("short read receiving data digest: read %d expected %d\n", + rr, dgs); + return NULL; + } + } + + data_size -= dgs; + + ERR_IF(data_size & 0x1ff) return NULL; + ERR_IF(data_size > DRBD_MAX_SEGMENT_SIZE) return NULL; + + e = drbd_alloc_ee(mdev, id, sector, data_size, GFP_KERNEL); + if (!e) + return NULL; + bio = e->private_bio; + ds = data_size; + bio_for_each_segment(bvec, bio, i) { + page = bvec->bv_page; + rr = drbd_recv(mdev, kmap(page), min_t(int, ds, PAGE_SIZE)); + kunmap(page); + if ( rr != min_t(int, ds, PAGE_SIZE) ) { + drbd_free_ee(mdev, e); + DRBD_WARN("short read receiving data: read %d expected %d\n", + rr, min_t(int, ds, PAGE_SIZE)); + return NULL; + } + ds -= rr; + } + + if (dgs) { + drbd_csum(mdev, mdev->integrity_r_tfm, bio, dig_vv); + if (memcmp(dig_in,dig_vv,dgs)) { + ERR("Digest integrity check FAILED.\n"); + drbd_bcast_ee(mdev, "digest failed", + dgs, dig_in, dig_vv, e); + drbd_free_ee(mdev, e); + return NULL; + } + } + mdev->recv_cnt += data_size>>9; + return e; +} + +/* drbd_drain_block() just takes a data block + * out of the socket input buffer, and discards it. + */ +STATIC int drbd_drain_block(struct drbd_conf *mdev, int data_size) +{ + struct page *page; + int rr, rv = 1; + void *data; + + page = drbd_pp_alloc(mdev, GFP_KERNEL); + + data = kmap(page); + while (data_size) { + rr = drbd_recv(mdev, data, min_t(int, data_size, PAGE_SIZE)); + if ( rr != min_t(int, data_size, PAGE_SIZE) ) { + rv = 0; + DRBD_WARN("short read receiving data: read %d expected %d\n", + rr, min_t(int, data_size, PAGE_SIZE)); + break; + } + data_size -= rr; + } + kunmap(page); + drbd_pp_free(mdev, page); + return rv; +} + +/* kick lower level device, if we have more than (arbitrary number) + * reference counts on it, which typically are locally submitted io + * requests. don't use unacked_cnt, so we speed up proto A and B, too. */ +static void maybe_kick_lo(struct drbd_conf *mdev) +{ + /* FIXME hysteresis ?? */ + if (atomic_read(&mdev->local_cnt) >= mdev->net_conf->unplug_watermark) + drbd_kick_lo(mdev); +} + +STATIC int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req, + sector_t sector, int data_size) +{ + struct bio_vec *bvec; + struct bio *bio; + int dgs, rr, i, expect; + void *dig_in = mdev->int_dig_in; + void *dig_vv = mdev->int_dig_vv; + + dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ? + crypto_hash_digestsize(mdev->integrity_r_tfm) : 0; + + if (dgs) { + rr = drbd_recv(mdev, dig_in, dgs); + if (rr != dgs) { + DRBD_WARN("short read receiving data reply digest: read %d expected %d\n", + rr, dgs); + return 0; + } + } + + data_size -= dgs; + + bio = req->master_bio; + D_ASSERT( sector == bio->bi_sector ); + + bio_for_each_segment(bvec, bio, i) { + expect = min_t(int, data_size, bvec->bv_len); + rr = drbd_recv(mdev, + kmap(bvec->bv_page)+bvec->bv_offset, + expect); + kunmap(bvec->bv_page); + if (rr != expect) { + DRBD_WARN("short read receiving data reply: " + "read %d expected %d\n", + rr, expect); + return 0; + } + data_size -= rr; + } + + if (dgs) { + drbd_csum(mdev, mdev->integrity_r_tfm, bio, dig_vv); + if (memcmp(dig_in,dig_vv,dgs)) { + ERR("Digest integrity check FAILED. Broken NICs?\n"); + return 0; + } + } + + D_ASSERT(data_size == 0); + /* FIXME recv_cnt accounting ?? */ + return 1; +} + +/* e_end_resync_block() is called via + * drbd_process_done_ee() by asender only */ +STATIC int e_end_resync_block(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + struct Tl_epoch_entry *e = (struct Tl_epoch_entry *)w; + sector_t sector = e->sector; + int ok; + + D_ASSERT(hlist_unhashed(&e->colision)); + + if (likely( drbd_bio_uptodate(e->private_bio) )) { + drbd_set_in_sync(mdev, sector, e->size); + ok = drbd_send_ack(mdev, RSWriteAck, e); + } else { + /* Record failure to sync */ + drbd_rs_failed_io(mdev, sector, e->size); + + ok = drbd_send_ack(mdev, NegAck, e); + ok &= drbd_io_error(mdev, FALSE); + } + dec_unacked(mdev); + + return ok; +} + +STATIC int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_size) __releases(local) +{ + struct Tl_epoch_entry *e; + + e = read_in_block(mdev, ID_SYNCER, sector, data_size); + if (!e) { + dec_local(mdev); + return FALSE; + } + + dec_rs_pending(mdev); + + e->private_bio->bi_end_io = drbd_endio_write_sec; + e->private_bio->bi_rw = WRITE; + e->w.cb = e_end_resync_block; + + inc_unacked(mdev); + /* corresponding dec_unacked() in e_end_resync_block() + * respective _drbd_clear_done_ee */ + + spin_lock_irq(&mdev->req_lock); + list_add(&e->w.list, &mdev->sync_ee); + spin_unlock_irq(&mdev->req_lock); + + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("submit EE (RS)WRITE sec=%llus size=%u ee=%p\n", + (unsigned long long)e->sector, e->size, e); + ); + dump_internal_bio("Sec", mdev, e->private_bio, 0); + drbd_generic_make_request(mdev, DRBD_FAULT_RS_WR, e->private_bio); + /* accounting done in endio */ + + maybe_kick_lo(mdev); + return TRUE; +} + +STATIC int receive_DataReply(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct drbd_request *req; + sector_t sector; + unsigned int header_size, data_size; + int ok; + struct Drbd_Data_Packet *p = (struct Drbd_Data_Packet *)h; + + header_size = sizeof(*p) - sizeof(*h); + data_size = h->length - header_size; + + /* I expect a block to be a multiple of 512 byte, + * and no more than DRBD_MAX_SEGMENT_SIZE. + * is this too restrictive? */ + ERR_IF(data_size == 0) return FALSE; + + if (drbd_recv(mdev, h->payload, header_size) != header_size) + return FALSE; + + sector = be64_to_cpu(p->sector); + + spin_lock_irq(&mdev->req_lock); + req = _ar_id_to_req(mdev, p->block_id, sector); + spin_unlock_irq(&mdev->req_lock); + if (unlikely(!req)) { + ERR("Got a corrupt block_id/sector pair(1).\n"); + return FALSE; + } + + /* hlist_del(&req->colision) is done in _req_may_be_done, to avoid + * special casing it there for the various failure cases. + * still no race with drbd_fail_pending_reads */ + ok = recv_dless_read(mdev, req, sector, data_size); + + if (ok) + req_mod(req, data_received, 0); + /* else: nothing. handled from drbd_disconnect... + * I don't think we may complete this just yet + * in case we are "on-disconnect: freeze" */ + + return ok; +} + +STATIC int receive_RSDataReply(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + sector_t sector; + unsigned int header_size, data_size; + int ok; + struct Drbd_Data_Packet *p = (struct Drbd_Data_Packet *)h; + + header_size = sizeof(*p) - sizeof(*h); + data_size = h->length - header_size; + + if (drbd_recv(mdev, h->payload, header_size) != header_size) + return FALSE; + + sector = be64_to_cpu(p->sector); + D_ASSERT(p->block_id == ID_SYNCER); + + if (inc_local(mdev)) { + /* data is submitted to disk within recv_resync_read. + * corresponding dec_local done below on error, + * or in drbd_endio_write_sec. */ + /* FIXME paranoia: + * verify that the corresponding bit is set. + * in case we are Primary SyncTarget, + * verify there are no pending write request to that area. + */ + ok = recv_resync_read(mdev, sector, data_size); + } else { + if (DRBD_ratelimit(5*HZ, 5)) + ERR("Can not write resync data to local disk.\n"); + + ok = drbd_drain_block(mdev, data_size); + + drbd_send_ack_dp(mdev, NegAck, p); + } + + return ok; +} + +/* e_end_block() is called via drbd_process_done_ee(). + * this means this function only runs in the asender thread + * + * for a broken example implementation of the TCQ barrier version of + * e_end_block see older revisions... + */ +STATIC int e_end_block(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + struct Tl_epoch_entry *e = (struct Tl_epoch_entry *)w; + sector_t sector = e->sector; + /* unsigned int epoch_size; */ + int ok = 1, pcmd; + + if (mdev->net_conf->wire_protocol == DRBD_PROT_C) { + if (likely(drbd_bio_uptodate(e->private_bio))) { + pcmd = (mdev->state.conn >= SyncSource && + mdev->state.conn <= PausedSyncT && + e->flags & EE_MAY_SET_IN_SYNC) ? + RSWriteAck : WriteAck; + ok &= drbd_send_ack(mdev, pcmd, e); + if (pcmd == RSWriteAck) + drbd_set_in_sync(mdev, sector, e->size); + } else { + /* FIXME I think we should send a NegAck regardless of + * which protocol is in effect. + * In which case we would need to make sure that any + * NegAck is sent. Basically that means that + * drbd_process_done_ee may not list_del() the ee + * before this callback did run... + * maybe even move the list_del(e) in here... */ + ok = drbd_send_ack(mdev, NegAck, e); + ok &= drbd_io_error(mdev, FALSE); + /* we expect it to be marked out of sync anyways... + * maybe assert this? */ + } + dec_unacked(mdev); + } else if (unlikely(!drbd_bio_uptodate(e->private_bio))) { + ok = drbd_io_error(mdev, FALSE); + } + + /* we delete from the conflict detection hash _after_ we sent out the + * WriteAck / NegAck, to get the sequence number right. */ + if (mdev->net_conf->two_primaries) { + spin_lock_irq(&mdev->req_lock); + D_ASSERT(!hlist_unhashed(&e->colision)); + hlist_del_init(&e->colision); + spin_unlock_irq(&mdev->req_lock); + } else { + D_ASSERT(hlist_unhashed(&e->colision)); + } + + return ok; +} + +STATIC int e_send_discard_ack(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + struct Tl_epoch_entry *e = (struct Tl_epoch_entry *)w; + int ok = 1; + + D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C); + ok = drbd_send_ack(mdev, DiscardAck, e); + + spin_lock_irq(&mdev->req_lock); + D_ASSERT(!hlist_unhashed(&e->colision)); + hlist_del_init(&e->colision); + spin_unlock_irq(&mdev->req_lock); + + dec_unacked(mdev); + + return ok; +} + +/* Called from receive_Data. + * Synchronize packets on sock with packets on msock. + * + * This is here so even when a Data packet traveling via sock overtook an Ack + * packet traveling on msock, they are still processed in the order they have + * been sent. + * + * Note: we don't care for Ack packets overtaking Data packets. + * + * In case packet_seq is larger than mdev->peer_seq number, there are + * outstanding packets on the msock. We wait for them to arrive. + * In case we are the logically next packet, we update mdev->peer_seq + * ourselves. Correctly handles 32bit wrap around. + * FIXME verify that atomic_t guarantees 32bit wrap around, + * otherwise we have to play tricks with << ... + * + * Assume we have a 10 GBit connection, that is about 1<<30 byte per second, + * about 1<<21 sectors per second. So "worst" case, we have 1<<3 == 8 seconds + * for the 24bit wrap (historical atomic_t guarantee on some archs), and we have + * 1<<9 == 512 seconds aka ages for the 32bit wrap around... + * + * returns 0 if we may process the packet, + * -ERESTARTSYS if we were interrupted (by disconnect signal). */ +static int drbd_wait_peer_seq(struct drbd_conf *mdev, const u32 packet_seq) +{ + DEFINE_WAIT(wait); + int ret = 0; + spin_lock(&mdev->peer_seq_lock); + for (;;) { + prepare_to_wait(&mdev->seq_wait, &wait, TASK_INTERRUPTIBLE); + if (seq_le(packet_seq, mdev->peer_seq+1)) + break; + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + spin_unlock(&mdev->peer_seq_lock); + schedule(); + spin_lock(&mdev->peer_seq_lock); + } + finish_wait(&mdev->seq_wait, &wait); + if (mdev->peer_seq+1 == packet_seq) + mdev->peer_seq++; + spin_unlock(&mdev->peer_seq_lock); + return ret; +} + +/* mirrored write */ +STATIC int receive_Data(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + sector_t sector; + struct Tl_epoch_entry *e; + struct Drbd_Data_Packet *p = (struct Drbd_Data_Packet *)h; + int header_size, data_size; + int rw = WRITE; + unsigned int barrier_nr = 0; + unsigned int epoch_size = 0; + u32 dp_flags; + + /* FIXME merge this code dups into some helper function */ + header_size = sizeof(*p) - sizeof(*h); + data_size = h->length - header_size; + + ERR_IF(data_size == 0) return FALSE; + + if (drbd_recv(mdev, h->payload, header_size) != header_size) + return FALSE; + + if (!inc_local(mdev)) { + /* data is submitted to disk at the end of this function. + * corresponding dec_local done either below (on error), + * or in drbd_endio_write_sec. */ + if (DRBD_ratelimit(5*HZ, 5)) + ERR("Can not write mirrored data block " + "to local disk.\n"); + spin_lock(&mdev->peer_seq_lock); + if (mdev->peer_seq+1 == be32_to_cpu(p->seq_num)) + mdev->peer_seq++; + spin_unlock(&mdev->peer_seq_lock); + + drbd_send_ack_dp(mdev, NegAck, p); + mdev->epoch_size++; /* spin lock ? */ + return drbd_drain_block(mdev, data_size); + } + + sector = be64_to_cpu(p->sector); + e = read_in_block(mdev, p->block_id, sector, data_size); + if (!e) { + dec_local(mdev); + return FALSE; + } + + e->private_bio->bi_end_io = drbd_endio_write_sec; + e->private_bio->bi_rw = WRITE; + e->w.cb = e_end_block; + + dp_flags = be32_to_cpu(p->dp_flags); + if (dp_flags & DP_HARDBARRIER) + rw |= (1<flags |= EE_MAY_SET_IN_SYNC; + + /* I'm the receiver, I do hold a net_cnt reference. */ + if (!mdev->net_conf->two_primaries) { + spin_lock_irq(&mdev->req_lock); + } else { + /* don't get the req_lock yet, + * we may sleep in drbd_wait_peer_seq */ + const int size = e->size; + const int discard = test_bit(DISCARD_CONCURRENT, &mdev->flags); + DEFINE_WAIT(wait); + struct drbd_request *i; + struct hlist_node *n; + struct hlist_head *slot; + int first; + + D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C); + BUG_ON(mdev->ee_hash == NULL); + BUG_ON(mdev->tl_hash == NULL); + + /* conflict detection and handling: + * 1. wait on the sequence number, + * in case this data packet overtook ACK packets. + * 2. check our hash tables for conflicting requests. + * we only need to walk the tl_hash, since an ee can not + * have a conflict with an other ee: on the submitting + * node, the corresponding req had already been conflicting, + * and a conflicting req is never sent. + * + * Note: for two_primaries, we are protocol C, + * so there cannot be any request that is DONE + * but still on the transfer log. + * + * unconditionally add to the ee_hash. + * + * if no conflicting request is found: + * submit. + * + * if any conflicting request is found + * that has not yet been acked, + * AND I have the "discard concurrent writes" flag: + * queue (via done_ee) the DiscardAck; OUT. + * + * if any conflicting request is found: + * block the receiver, waiting on misc_wait + * until no more conflicting requests are there, + * or we get interrupted (disconnect). + * + * we do not just write after local io completion of those + * requests, but only after req is done completely, i.e. + * we wait for the DiscardAck to arrive! + * + * then proceed normally, i.e. submit. + */ + if (drbd_wait_peer_seq(mdev, be32_to_cpu(p->seq_num))) + goto out_interrupted; + + spin_lock_irq(&mdev->req_lock); + + hlist_add_head(&e->colision, ee_hash_slot(mdev, sector)); + +#define OVERLAPS overlaps(i->sector, i->size, sector, size) + slot = tl_hash_slot(mdev, sector); + first = 1; + for (;;) { + int have_unacked = 0; + int have_conflict = 0; + prepare_to_wait(&mdev->misc_wait, &wait, + TASK_INTERRUPTIBLE); + hlist_for_each_entry(i, n, slot, colision) { + if (OVERLAPS) { + /* only ALERT on first iteration, + * we may be woken up early... */ + if (first) + ALERT("%s[%u] Concurrent local write detected!" + " new: %llus +%u; pending: %llus +%u\n", + current->comm, current->pid, + (unsigned long long)sector, size, + (unsigned long long)i->sector, i->size); + if (i->rq_state & RQ_NET_PENDING) + ++have_unacked; + ++have_conflict; + } + } +#undef OVERLAPS + if (!have_conflict) + break; + + /* Discard Ack only for the _first_ iteration */ + if (first && discard && have_unacked) { + ALERT("Concurrent write! [DISCARD BY FLAG] sec=%llus\n", + (unsigned long long)sector); + inc_unacked(mdev); + mdev->epoch_size++; + e->w.cb = e_send_discard_ack; + list_add_tail(&e->w.list, &mdev->done_ee); + + spin_unlock_irq(&mdev->req_lock); + + /* we could probably send that DiscardAck ourselves, + * but I don't like the receiver using the msock */ + + dec_local(mdev); + wake_asender(mdev); + finish_wait(&mdev->misc_wait, &wait); + return TRUE; + } + + if (signal_pending(current)) { + hlist_del_init(&e->colision); + + spin_unlock_irq(&mdev->req_lock); + + finish_wait(&mdev->misc_wait, &wait); + goto out_interrupted; + } + + spin_unlock_irq(&mdev->req_lock); + if (first) { + first = 0; + ALERT("Concurrent write! [W AFTERWARDS] " + "sec=%llus\n", (unsigned long long)sector); + } else if (discard) { + /* we had none on the first iteration. + * there must be none now. */ + D_ASSERT(have_unacked == 0); + } + schedule(); + spin_lock_irq(&mdev->req_lock); + } + finish_wait(&mdev->misc_wait, &wait); + } + + /* when using TCQ: + * note that, when using tagged command queuing, we may + * have more than one reorder domain "active" at a time. + * + * THINK: + * do we have any guarantees that we get the completion + * events of the different reorder domains in order? + * or does the api only "guarantee" that the events + * _happened_ in order, but eventually the completion + * callbacks are shuffeled again? + * + * note that I wonder about the order in which the + * callbacks are run, I am reasonable confident that the + * actual completion happens in order. + * + * - can it happen that the tagged write completion is + * called even though not all of the writes before it + * have run their completion callback? + * - can it happen that some completion callback of some + * write after the tagged one is run, even though the + * callback of the tagged one itself is still pending? + * + * if this can happen, we either need to drop our "debug + * assertion" about the epoch size and just trust our code + * and the layers below us (nah, won't do that). + * + * or we need to replace the "active_ee" list by some sort + * of "transfer log" on the receiving side, too, which + * uses epoch counters per reorder domain. + */ + + /* when using tcq: + * if we got a barrier packet before, but at that time the active_ee + * was not yet empty, we just "remembered" this barrier request. + * + * if this is the first data packet since that barrier, maybe meanwhile + * all previously active writes have been completed? + * if so, send the b_ack right now + * (though, maybe rather move it into the e_end_block callback, + * where it would be sent as soon as possible). + * + * otherwise, tag the write with the barrier number, so it + * will trigger the b_ack before its own ack. + */ + if (mdev->next_barrier_nr) { + /* only when using TCQ */ + if (list_empty(&mdev->active_ee)) { + barrier_nr = mdev->next_barrier_nr; + epoch_size = mdev->epoch_size; + mdev->epoch_size = 0; + } else { + e->barrier_nr = mdev->next_barrier_nr; + } + rw |= (1<next_barrier_nr = 0; + } + list_add(&e->w.list, &mdev->active_ee); + spin_unlock_irq(&mdev->req_lock); + + if (barrier_nr) { + /* only when using TCQ + * maybe rather move it into the e_end_block callback, + * where it would be sent as soon as possible). + */ + (void)drbd_send_b_ack(mdev, + cpu_to_be32(barrier_nr), epoch_size); + } + + switch (mdev->net_conf->wire_protocol) { + case DRBD_PROT_C: + inc_unacked(mdev); + /* corresponding dec_unacked() in e_end_block() + * respective _drbd_clear_done_ee */ + break; + case DRBD_PROT_B: + /* I really don't like it that the receiver thread + * sends on the msock, but anyways */ + drbd_send_ack(mdev, RecvAck, e); + break; + case DRBD_PROT_A: + /* nothing to do */ + break; + } + + if (mdev->state.pdsk == Diskless) { + /* In case we have the only disk of the cluster, */ + drbd_set_out_of_sync(mdev, e->sector, e->size); + e->flags |= EE_CALL_AL_COMPLETE_IO; + drbd_al_begin_io(mdev, e->sector); + } + + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("submit EE (DATA)WRITE sec=%llus size=%u ee=%p\n", + (unsigned long long)e->sector, e->size, e); + ); + /* FIXME drbd_al_begin_io in case we have two primaries... */ + e->private_bio->bi_rw = rw; + dump_internal_bio("Sec", mdev, e->private_bio, 0); + drbd_generic_make_request(mdev, DRBD_FAULT_DT_WR, e->private_bio); + /* accounting done in endio */ + + maybe_kick_lo(mdev); + return TRUE; + +out_interrupted: + /* yes, the epoch_size now is imbalanced. + * but we drop the connection anyways, so we don't have a chance to + * receive a barrier... atomic_inc(&mdev->epoch_size); */ + dec_local(mdev); + drbd_free_ee(mdev, e); + return FALSE; +} + +STATIC int receive_DataRequest(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + sector_t sector; + const sector_t capacity = drbd_get_capacity(mdev->this_bdev); + struct Tl_epoch_entry *e; + struct digest_info *di; + int size,digest_size; + unsigned int fault_type; + struct Drbd_BlockRequest_Packet *p = + (struct Drbd_BlockRequest_Packet *)h; + const int brps = sizeof(*p)-sizeof(*h); + + if (drbd_recv(mdev, h->payload, brps) != brps) + return FALSE; + + sector = be64_to_cpu(p->sector); + size = be32_to_cpu(p->blksize); + + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + ERR("%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__, + (unsigned long long)sector, size); + return FALSE; + } + if ( sector + (size>>9) > capacity) { + ERR("%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__, + (unsigned long long)sector, size); + return FALSE; + } + + if (!inc_local_if_state(mdev, UpToDate)) { + if (DRBD_ratelimit(5*HZ, 5)) + ERR("Can not satisfy peer's read request, " + "no local data.\n"); + drbd_send_ack_rp(mdev, h->command == DataRequest ? NegDReply : + NegRSDReply , p); + return TRUE; + } + + e = drbd_alloc_ee(mdev, p->block_id, sector, size, GFP_KERNEL); + if (!e) { + dec_local(mdev); + return FALSE; + } + + /* FIXME actually, it could be a READA originating from the peer, + * also it could have set some flags (e.g. BIO_RW_SYNC) ... */ + e->private_bio->bi_rw = READ; + e->private_bio->bi_end_io = drbd_endio_read_sec; + + switch (h->command) { + case DataRequest: + e->w.cb = w_e_end_data_req; + fault_type = DRBD_FAULT_DT_RD; + break; + case RSDataRequest: + e->w.cb = w_e_end_rsdata_req; + fault_type = DRBD_FAULT_RS_RD; + /* Eventually this should become asynchrously. Currently it + * blocks the whole receiver just to delay the reading of a + * resync data block. + * the drbd_work_queue mechanism is made for this... + */ + if (!drbd_rs_begin_io(mdev, sector)) { + /* we have been interrupted, + * probably connection lost! */ + D_ASSERT(signal_pending(current)); + dec_local(mdev); + drbd_free_ee(mdev, e); + return 0; + } + break; + + case OVReply: + fault_type = DRBD_FAULT_RS_RD; + digest_size = h->length - brps ; + di = kmalloc(sizeof(*di) + digest_size ,GFP_KERNEL); + if(!di) { + dec_local(mdev); + drbd_free_ee(mdev,e); + return 0; + } + + di->digest_size = digest_size; + di->digest = (((char *)di)+sizeof(struct digest_info)); + + if (drbd_recv(mdev, di->digest, digest_size) != digest_size) { + dec_local(mdev); + drbd_free_ee(mdev,e); + kfree(di); + return FALSE; + } + + e->block_id = (u64)(unsigned long)di; + e->w.cb = w_e_end_ov_reply; + dec_rs_pending(mdev); + break; + + case OVRequest: + e->w.cb = w_e_end_ov_req; + fault_type = DRBD_FAULT_RS_RD; + /* Eventually this should become asynchrously. Currently it + * blocks the whole receiver just to delay the reading of a + * resync data block. + * the drbd_work_queue mechanism is made for this... + */ + if (!drbd_rs_begin_io(mdev,sector)) { + /* we have been interrupted, + * probably connection lost! */ + D_ASSERT(signal_pending(current)); + dec_local(mdev); + drbd_free_ee(mdev,e); + return 0; + } + break; + + + default:; /* avoid compiler warning */ + ERR("unexpected command (%s) in receive_DataRequest\n", + cmdname(h->command)); + fault_type = DRBD_FAULT_MAX; + } + + spin_lock_irq(&mdev->req_lock); + list_add(&e->w.list, &mdev->read_ee); + spin_unlock_irq(&mdev->req_lock); + + inc_unacked(mdev); + + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("submit EE READ sec=%llus size=%u ee=%p\n", + (unsigned long long)e->sector, e->size, e); + ); + + dump_internal_bio("Sec", mdev, e->private_bio, 0); + drbd_generic_make_request(mdev, fault_type, e->private_bio); + maybe_kick_lo(mdev); + + return TRUE; +} + +STATIC int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local) +{ + int self, peer, rv = -100; + unsigned long ch_self, ch_peer; + + self = mdev->bc->md.uuid[Bitmap] & 1; + peer = mdev->p_uuid[Bitmap] & 1; + + ch_peer = mdev->p_uuid[UUID_SIZE]; + ch_self = mdev->comm_bm_set; + + switch ( mdev->net_conf->after_sb_0p ) { + case Consensus: + case DiscardSecondary: + case CallHelper: + ERR("Configuration error.\n"); + break; + case Disconnect: + break; + case DiscardYoungerPri: + if (self == 0 && peer == 1) { rv = -1; break; } + if (self == 1 && peer == 0) { rv = 1; break; } + /* Else fall through to one of the other strategies... */ + case DiscardOlderPri: + if (self == 0 && peer == 1) { rv = 1; break; } + if (self == 1 && peer == 0) { rv = -1; break; } + /* Else fall through to one of the other strategies... */ + DRBD_WARN("Discard younger/older primary did not found a decision\n" + "Using discard-least-changes instead\n"); + case DiscardZeroChg: + if (ch_peer == 0 && ch_self == 0) { + rv = test_bit(DISCARD_CONCURRENT, &mdev->flags) + ? -1 : 1; + break; + } else { + if (ch_peer == 0) { rv = 1; break; } + if (ch_self == 0) { rv = -1; break; } + } + if (mdev->net_conf->after_sb_0p == DiscardZeroChg) + break; + case DiscardLeastChg: + if ( ch_self < ch_peer ) + rv = -1; + else if (ch_self > ch_peer) + rv = 1; + else /* ( ch_self == ch_peer ) */ + /* Well, then use something else. */ + rv = test_bit(DISCARD_CONCURRENT, &mdev->flags) + ? -1 : 1; + break; + case DiscardLocal: + rv = -1; + break; + case DiscardRemote: + rv = 1; + } + + return rv; +} + +STATIC int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local) +{ + int self, peer, hg, rv = -100; + + self = mdev->bc->md.uuid[Bitmap] & 1; + peer = mdev->p_uuid[Bitmap] & 1; + + switch ( mdev->net_conf->after_sb_1p ) { + case DiscardYoungerPri: + case DiscardOlderPri: + case DiscardLeastChg: + case DiscardLocal: + case DiscardRemote: + ERR("Configuration error.\n"); + break; + case Disconnect: + break; + case Consensus: + hg = drbd_asb_recover_0p(mdev); + if (hg == -1 && mdev->state.role == Secondary) + rv = hg; + if (hg == 1 && mdev->state.role == Primary) + rv = hg; + break; + case Violently: + rv = drbd_asb_recover_0p(mdev); + break; + case DiscardSecondary: + return mdev->state.role == Primary ? 1 : -1; + case CallHelper: + hg = drbd_asb_recover_0p(mdev); + if (hg == -1 && mdev->state.role == Primary) { + self = drbd_set_role(mdev, Secondary, 0); + if (self != SS_Success) { + drbd_khelper(mdev, "pri-lost-after-sb"); + } else { + DRBD_WARN("Sucessfully gave up primary role.\n"); + rv = hg; + } + } else + rv = hg; + } + + return rv; +} + +STATIC int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local) +{ + int self, peer, hg, rv = -100; + + self = mdev->bc->md.uuid[Bitmap] & 1; + peer = mdev->p_uuid[Bitmap] & 1; + + switch ( mdev->net_conf->after_sb_2p ) { + case DiscardYoungerPri: + case DiscardOlderPri: + case DiscardLeastChg: + case DiscardLocal: + case DiscardRemote: + case Consensus: + case DiscardSecondary: + ERR("Configuration error.\n"); + break; + case Violently: + rv = drbd_asb_recover_0p(mdev); + break; + case Disconnect: + break; + case CallHelper: + hg = drbd_asb_recover_0p(mdev); + if (hg == -1) { + self = drbd_set_role(mdev, Secondary, 0); + if (self != SS_Success) { + drbd_khelper(mdev, "pri-lost-after-sb"); + } else { + DRBD_WARN("Sucessfully gave up primary role.\n"); + rv = hg; + } + } else + rv = hg; + } + + return rv; +} + +STATIC void drbd_uuid_dump(struct drbd_conf *mdev, char *text, u64 *uuid) +{ + INFO("%s %016llX:%016llX:%016llX:%016llX\n", + text, + uuid[Current], + uuid[Bitmap], + uuid[History_start], + uuid[History_end]); +} + +/* + 100 after split brain try auto recover + 2 SyncSource set BitMap + 1 SyncSource use BitMap + 0 no Sync + -1 SyncTarget use BitMap + -2 SyncTarget set BitMap + -100 after split brain, disconnect +-1000 unrelated data + */ +STATIC int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(local) +{ + u64 self, peer; + int i, j; + + self = mdev->bc->md.uuid[Current] & ~((u64)1); + peer = mdev->p_uuid[Current] & ~((u64)1); + + *rule_nr = 1; + if (self == UUID_JUST_CREATED && + peer == UUID_JUST_CREATED) return 0; + + *rule_nr = 2; + if ( (self == UUID_JUST_CREATED || self == (u64)0) && + peer != UUID_JUST_CREATED) return -2; + + *rule_nr = 3; + if ( self != UUID_JUST_CREATED && + (peer == UUID_JUST_CREATED || peer == (u64)0) ) return 2; + + *rule_nr = 4; + if (self == peer) { /* Common power [off|failure] */ + int rct, dc; /* roles at crash time */ + + rct = (test_bit(CRASHED_PRIMARY, &mdev->flags) ? 1 : 0) + + ( mdev->p_uuid[UUID_FLAGS] & 2 ); + /* lowest bit is set when we were primary, + * next bit (weight 2) is set when peer was primary */ + + MTRACE(TraceTypeUuid, TraceLvlMetrics, DUMPI(rct); ); + + switch (rct) { + case 0: /* !self_pri && !peer_pri */ return 0; + case 1: /* self_pri && !peer_pri */ return 1; + case 2: /* !self_pri && peer_pri */ return -1; + case 3: /* self_pri && peer_pri */ + dc = test_bit(DISCARD_CONCURRENT, &mdev->flags); + MTRACE(TraceTypeUuid, TraceLvlMetrics, DUMPI(dc); ); + return dc ? -1 : 1; + } + } + + *rule_nr = 5; + peer = mdev->p_uuid[Bitmap] & ~((u64)1); + if (self == peer) + return -1; + + *rule_nr = 6; + for ( i = History_start ; i <= History_end ; i++ ) { + peer = mdev->p_uuid[i] & ~((u64)1); + if (self == peer) + return -2; + } + + *rule_nr = 7; + self = mdev->bc->md.uuid[Bitmap] & ~((u64)1); + peer = mdev->p_uuid[Current] & ~((u64)1); + if (self == peer) + return 1; + + *rule_nr = 8; + for ( i = History_start ; i <= History_end ; i++ ) { + self = mdev->bc->md.uuid[i] & ~((u64)1); + if (self == peer) + return 2; + } + + *rule_nr = 9; + self = mdev->bc->md.uuid[Bitmap] & ~((u64)1); + peer = mdev->p_uuid[Bitmap] & ~((u64)1); + if (self == peer && self != ((u64)0) ) return 100; + + *rule_nr = 10; + for ( i = History_start ; i <= History_end ; i++ ) { + self = mdev->p_uuid[i] & ~((u64)1); + for ( j = History_start ; j <= History_end ; j++ ) { + peer = mdev->p_uuid[j] & ~((u64)1); + if (self == peer) + return -100; + } + } + + return -1000; +} + +/* drbd_sync_handshake() returns the new conn state on success, or + conn_mask (-1) on failure. + */ +STATIC enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_role peer_role, + enum drbd_disk_state peer_disk) __must_hold(local) +{ + int hg, rule_nr; + enum drbd_conns rv = conn_mask; + enum drbd_disk_state mydisk; + + mydisk = mdev->state.disk; + if (mydisk == Negotiating) + mydisk = mdev->new_state_tmp.disk; + + hg = drbd_uuid_compare(mdev, &rule_nr); + + MTRACE(TraceTypeUuid, TraceLvlSummary, + INFO("drbd_sync_handshake:\n"); + drbd_uuid_dump(mdev, "self", mdev->bc->md.uuid); + drbd_uuid_dump(mdev, "peer", mdev->p_uuid); + INFO("uuid_compare()=%d by rule %d\n", hg, rule_nr); + ); + + if (hg == -1000) { + ALERT("Unrelated data, aborting!\n"); + return conn_mask; + } + + if ( (mydisk == Inconsistent && peer_disk > Inconsistent) || + (peer_disk == Inconsistent && mydisk > Inconsistent) ) { + int f = (hg == -100) || abs(hg) == 2; + hg = mydisk > Inconsistent ? 1 : -1; + if (f) + hg = hg*2; + INFO("Becoming sync %s due to disk states.\n", + hg > 0 ? "source" : "target"); + } + + if (hg == 100 || (hg == -100 && mdev->net_conf->always_asbp) ) { + int pcount = (mdev->state.role == Primary) + + (peer_role == Primary); + int forced = (hg == -100); + + switch (pcount) { + case 0: + hg = drbd_asb_recover_0p(mdev); + break; + case 1: + hg = drbd_asb_recover_1p(mdev); + break; + case 2: + hg = drbd_asb_recover_2p(mdev); + break; + } + if ( abs(hg) < 100 ) { + DRBD_WARN("Split-Brain detected, %d primaries, " + "automatically solved. Sync from %s node\n", + pcount, (hg < 0) ? "peer":"this"); + if (forced) { + DRBD_WARN("Doing a full sync, since" + " UUIDs where ambiguous.\n"); + drbd_uuid_dump(mdev, "self", mdev->bc->md.uuid); + drbd_uuid_dump(mdev, "peer", mdev->p_uuid); + hg = hg*2; + } + } + } + + if (hg == -100) { + if (mdev->net_conf->want_lose && !(mdev->p_uuid[UUID_FLAGS]&1)) + hg = -1; + if (!mdev->net_conf->want_lose && (mdev->p_uuid[UUID_FLAGS]&1)) + hg = 1; + + if ( abs(hg) < 100 ) + DRBD_WARN("Split-Brain detected, manually solved. " + "Sync from %s node\n", + (hg < 0) ? "peer":"this"); + } + + if (hg == -100) { + ALERT("Split-Brain detected, dropping connection!\n"); + drbd_uuid_dump(mdev, "self", mdev->bc->md.uuid); + drbd_uuid_dump(mdev, "peer", mdev->p_uuid); + drbd_khelper(mdev, "split-brain"); + return conn_mask; + } + + if (hg > 0 && mydisk <= Inconsistent) { + ERR("I shall become SyncSource, but I am inconsistent!\n"); + return conn_mask; + } + + if (hg < 0 && /* by intention we do not use mydisk here. */ + mdev->state.role == Primary && mdev->state.disk >= Consistent ) { + switch (mdev->net_conf->rr_conflict) { + case CallHelper: + drbd_khelper(mdev, "pri-lost"); + /* fall through */ + case Disconnect: + ERR("I shall become SyncTarget, but I am primary!\n"); + return conn_mask; + case Violently: + DRBD_WARN("Becoming SyncTarget, violating the stable-data" + "assumption\n"); + } + } + + if (abs(hg) >= 2) { + INFO("Writing the whole bitmap, full sync required after drbd_sync_handshake.\n"); + if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write)) + return conn_mask; + } + + if (hg > 0) { /* become sync source. */ + rv = WFBitMapS; + } else if (hg < 0) { /* become sync target */ + rv = WFBitMapT; + } else { + rv = Connected; + if (drbd_bm_total_weight(mdev)) { + INFO("No resync, but %lu bits in bitmap!\n", + drbd_bm_total_weight(mdev)); + } + } + + drbd_bm_recount_bits(mdev); + + return rv; +} + +/* returns 1 if invalid */ +STATIC int cmp_after_sb(enum after_sb_handler peer, enum after_sb_handler self) +{ + /* DiscardRemote - DiscardLocal is valid */ + if ( (peer == DiscardRemote && self == DiscardLocal) || + (self == DiscardRemote && peer == DiscardLocal) ) return 0; + + /* any other things with DiscardRemote or DiscardLocal are invalid */ + if ( peer == DiscardRemote || peer == DiscardLocal || + self == DiscardRemote || self == DiscardLocal ) return 1; + + /* everything else is valid if they are equal on both sides. */ + if (peer == self) + return 0; + + /* everything es is invalid. */ + return 1; +} + +STATIC int receive_protocol(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_Protocol_Packet *p = (struct Drbd_Protocol_Packet *)h; + int header_size, data_size; + int p_proto, p_after_sb_0p, p_after_sb_1p, p_after_sb_2p; + int p_want_lose, p_two_primaries; + char p_integrity_alg[SHARED_SECRET_MAX]; + + header_size = sizeof(*p) - sizeof(*h); + data_size = h->length - header_size; + + if (drbd_recv(mdev, h->payload, header_size) != header_size) + return FALSE; + + p_proto = be32_to_cpu(p->protocol); + p_after_sb_0p = be32_to_cpu(p->after_sb_0p); + p_after_sb_1p = be32_to_cpu(p->after_sb_1p); + p_after_sb_2p = be32_to_cpu(p->after_sb_2p); + p_want_lose = be32_to_cpu(p->want_lose); + p_two_primaries = be32_to_cpu(p->two_primaries); + + if (p_proto != mdev->net_conf->wire_protocol) { + ERR("incompatible communication protocols\n"); + goto disconnect; + } + + if ( cmp_after_sb(p_after_sb_0p, mdev->net_conf->after_sb_0p) ) { + ERR("incompatible after-sb-0pri settings\n"); + goto disconnect; + } + + if ( cmp_after_sb(p_after_sb_1p, mdev->net_conf->after_sb_1p) ) { + ERR("incompatible after-sb-1pri settings\n"); + goto disconnect; + } + + if ( cmp_after_sb(p_after_sb_2p, mdev->net_conf->after_sb_2p) ) { + ERR("incompatible after-sb-2pri settings\n"); + goto disconnect; + } + + if (p_want_lose && mdev->net_conf->want_lose) { + ERR("both sides have the 'want_lose' flag set\n"); + goto disconnect; + } + + if (p_two_primaries != mdev->net_conf->two_primaries) { + ERR("incompatible setting of the two-primaries options\n"); + goto disconnect; + } + + if (mdev->agreed_pro_version >= 87) { + unsigned char *my_alg = mdev->net_conf->integrity_alg; + + if (drbd_recv(mdev, p_integrity_alg, data_size) != data_size) + return FALSE; + + p_integrity_alg[SHARED_SECRET_MAX-1] = 0; + if (strcmp(p_integrity_alg, my_alg)) { + ERR("incompatible setting of the data-integrity-alg\n"); + goto disconnect; + } + INFO("data-integrity-alg: %s\n", + my_alg[0] ? my_alg : (unsigned char *)""); + } + + return TRUE; + +disconnect: + drbd_force_state(mdev, NS(conn, Disconnecting)); + return FALSE; +} + +STATIC int receive_SyncParam(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + int ok = TRUE; + struct Drbd_SyncParam_Packet *p = (struct Drbd_SyncParam_Packet *)h; + int header_size, data_size; + char p_verify_alg[SHARED_SECRET_MAX]; + struct crypto_hash *verify_tfm = NULL, *old_verify_tfm; + + header_size = sizeof(*p) - sizeof(*h); + data_size = h->length - header_size; + + if (drbd_recv(mdev, h->payload, header_size) != header_size) + return FALSE; + + mdev->sync_conf.rate = be32_to_cpu(p->rate); + + if (mdev->agreed_pro_version >= 88) { + + if (drbd_recv(mdev, p_verify_alg, data_size) != data_size) + return FALSE; + + p_verify_alg[SHARED_SECRET_MAX-1] = 0; + if (strcpy(mdev->sync_conf.verify_alg, p_verify_alg)) { + if (strlen(p_verify_alg)) { + verify_tfm = crypto_alloc_hash(p_verify_alg, 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(verify_tfm)) { + ERR("Can not allocate \"%s\" as verify-alg\n", + p_verify_alg); + return FALSE; + } + + if (crypto_tfm_alg_type(crypto_hash_tfm(verify_tfm)) != + CRYPTO_ALG_TYPE_DIGEST) { + crypto_free_hash(verify_tfm); + ERR("\"%s\" is not a digest (verify-alg)\n", + p_verify_alg); + return FALSE; + } + } + + spin_lock(&mdev->peer_seq_lock); + /* lock against drbd_nl_syncer_conf() */ + strcpy(mdev->sync_conf.verify_alg, p_verify_alg); + mdev->sync_conf.verify_alg_len = strlen(p_verify_alg) + 1; + old_verify_tfm = mdev->verify_tfm; + mdev->verify_tfm = verify_tfm; + spin_unlock(&mdev->peer_seq_lock); + + crypto_free_hash(old_verify_tfm); + } + } + + return ok; +} + +STATIC void drbd_setup_order_type(struct drbd_conf *mdev, int peer) +{ + /* sorry, we currently have no working implementation + * of distributed TCQ */ +} + +/* warn if the arguments differ by more than 12.5% */ +static void warn_if_differ_considerably(struct drbd_conf *mdev, + const char *s, sector_t a, sector_t b) +{ + sector_t d; + if (a == 0 || b == 0) + return; + d = (a > b) ? (a - b) : (b - a); + if ( d > (a>>3) || d > (b>>3)) + DRBD_WARN("Considerable difference in %s: %llus vs. %llus\n", s, + (unsigned long long)a, (unsigned long long)b); +} + +STATIC int receive_sizes(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_Sizes_Packet *p = (struct Drbd_Sizes_Packet *)h; + enum determin_dev_size_enum dd = unchanged; + unsigned int max_seg_s; + sector_t p_size, p_usize, my_usize; + int ldsc = 0; /* local disk size changed */ + enum drbd_conns nconn; + + ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; + if (drbd_recv(mdev, h->payload, h->length) != h->length) + return FALSE; + + p_size = be64_to_cpu(p->d_size); + p_usize = be64_to_cpu(p->u_size); + + if (p_size == 0 && mdev->state.disk == Diskless) { + ERR("some backing storage is needed\n"); + drbd_force_state(mdev, NS(conn, Disconnecting)); + return FALSE; + } + + /* just store the peer's disk size for now. + * we still need to figure out wether we accept that. */ + mdev->p_size = p_size; + +#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) + if (inc_local(mdev)) { + warn_if_differ_considerably(mdev, "lower level device sizes", + p_size, drbd_get_capacity(mdev->bc->backing_bdev)); + warn_if_differ_considerably(mdev, "user requested size", + p_usize, mdev->bc->dc.disk_size); + + /* if this is the first connect, or an otherwise expected + * param exchange, choose the minimum */ + if (mdev->state.conn == WFReportParams) + p_usize = min_not_zero((sector_t)mdev->bc->dc.disk_size, + p_usize); + + my_usize = mdev->bc->dc.disk_size; + + if (mdev->bc->dc.disk_size != p_usize) { + mdev->bc->dc.disk_size = p_usize; + INFO("Peer sets u_size to %lu sectors\n", + (unsigned long)mdev->bc->dc.disk_size); + } + + /* Never shrink a device with usable data during connect. + But allow online shrinking if we are connected. */ + if (drbd_new_dev_size(mdev, mdev->bc) < + drbd_get_capacity(mdev->this_bdev) && + mdev->state.disk >= Outdated && + mdev->state.conn < Connected ) { + ERR("The peer's disk size is too small!\n"); + drbd_force_state(mdev, NS(conn, Disconnecting)); + mdev->bc->dc.disk_size = my_usize; + dec_local(mdev); + return FALSE; + } + dec_local(mdev); + } +#undef min_not_zero + + if (inc_local(mdev)) { + dd = drbd_determin_dev_size(mdev); + dec_local(mdev); + if (dd == dev_size_error) return FALSE; + drbd_md_sync(mdev); + } else { + /* I am diskless, need to accept the peer's size. */ + drbd_set_my_capacity(mdev, p_size); + } + + if (mdev->p_uuid && mdev->state.conn <= Connected && inc_local(mdev)) { + nconn = drbd_sync_handshake(mdev, + mdev->state.peer, mdev->state.pdsk); + dec_local(mdev); + + if (nconn == conn_mask) { + drbd_force_state(mdev, NS(conn, Disconnecting)); + return FALSE; + } + + if (drbd_request_state(mdev, NS(conn, nconn)) < SS_Success) { + drbd_force_state(mdev, NS(conn, Disconnecting)); + return FALSE; + } + } + + if (inc_local(mdev)) { + if (mdev->bc->known_size != drbd_get_capacity(mdev->bc->backing_bdev)) { + mdev->bc->known_size = drbd_get_capacity(mdev->bc->backing_bdev); + ldsc = 1; + } + + max_seg_s = be32_to_cpu(p->max_segment_size); + if (max_seg_s != mdev->rq_queue->max_segment_size) + drbd_setup_queue_param(mdev, max_seg_s); + + drbd_setup_order_type(mdev, be32_to_cpu(p->queue_order_type)); + dec_local(mdev); + } + + if (mdev->state.conn > WFReportParams) { + if ( be64_to_cpu(p->c_size) != + drbd_get_capacity(mdev->this_bdev) || ldsc ) { + /* we have different sizes, probabely peer + * needs to know my new size... */ + drbd_send_sizes(mdev); + } + if (dd == grew && mdev->state.conn == Connected && + mdev->state.pdsk >= Inconsistent && + mdev->state.disk >= Inconsistent) { + /* With disk >= Inconsistent we take care to not get + here during an attach while we are connected. */ + resync_after_online_grow(mdev); + } + } + + return TRUE; +} + +STATIC int receive_uuids(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_GenCnt_Packet *p = (struct Drbd_GenCnt_Packet *)h; + u64 *p_uuid; + int i; + + ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; + if (drbd_recv(mdev, h->payload, h->length) != h->length) + return FALSE; + + p_uuid = kmalloc(sizeof(u64)*EXT_UUID_SIZE, GFP_KERNEL); + + for (i = Current; i < EXT_UUID_SIZE; i++) + p_uuid[i] = be64_to_cpu(p->uuid[i]); + + kfree(mdev->p_uuid); + mdev->p_uuid = p_uuid; + + if (mdev->state.conn < Connected && + mdev->state.disk < Outdated && + mdev->state.role == Primary && + (mdev->ed_uuid & ~((u64)1)) != (p_uuid[Current] & ~((u64)1))) { + ERR("Can only connect to data with current UUID=%016llX\n", + (unsigned long long)mdev->ed_uuid); + drbd_force_state(mdev,NS(conn,Disconnecting)); + return FALSE; + } + + if (mdev->state.conn >= Connected && mdev->state.disk < Inconsistent) + drbd_set_ed_uuid(mdev, p_uuid[Current]); + + return TRUE; +} + +/** + * convert_state: + * Switches the view of the state. + */ +STATIC union drbd_state_t convert_state(union drbd_state_t ps) +{ + union drbd_state_t ms; + + static enum drbd_conns c_tab[] = { + [Connected] = Connected, + + [StartingSyncS] = StartingSyncT, + [StartingSyncT] = StartingSyncS, + [Disconnecting] = TearDown, /* NetworkFailure, */ + [VerifyS] = VerifyT, + [conn_mask] = conn_mask, + }; + + ms.i = ps.i; + + ms.conn = c_tab[ps.conn]; + ms.peer = ps.role; + ms.role = ps.peer; + ms.pdsk = ps.disk; + ms.disk = ps.pdsk; + ms.peer_isp = ( ps.aftr_isp | ps.user_isp ); + + return ms; +} + +STATIC int receive_req_state(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_Req_State_Packet *p = (struct Drbd_Req_State_Packet *)h; + union drbd_state_t mask, val; + int rv; + + ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; + if (drbd_recv(mdev, h->payload, h->length) != h->length) + return FALSE; + + mask.i = be32_to_cpu(p->mask); + val.i = be32_to_cpu(p->val); + + if (test_bit(DISCARD_CONCURRENT, &mdev->flags) && + test_bit(CLUSTER_ST_CHANGE, &mdev->flags)) { + drbd_send_sr_reply(mdev, SS_ConcurrentStChg); + return TRUE; + } + + mask = convert_state(mask); + val = convert_state(val); + + rv = drbd_change_state(mdev, ChgStateVerbose, mask, val); + + drbd_send_sr_reply(mdev,rv); + drbd_md_sync(mdev); + + return TRUE; +} + +STATIC int receive_state(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_State_Packet *p = (struct Drbd_State_Packet *)h; + enum drbd_conns nconn, oconn; + union drbd_state_t ns, peer_state; + enum drbd_disk_state real_peer_disk; + int rv; + + ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) + return FALSE; + + if (drbd_recv(mdev, h->payload, h->length) != h->length) + return FALSE; + + peer_state.i = be32_to_cpu(p->state); + + real_peer_disk = peer_state.disk; + if (peer_state.disk == Negotiating) { + real_peer_disk = mdev->p_uuid[UUID_FLAGS] & 4 ? Inconsistent : Consistent; + INFO("real peer disk state = %s\n", disks_to_name(real_peer_disk)); + } + + spin_lock_irq(&mdev->req_lock); + retry: + oconn = nconn = mdev->state.conn; + spin_unlock_irq(&mdev->req_lock); + + if (nconn == WFReportParams) + nconn = Connected; + + if (mdev->p_uuid && peer_state.disk >= Negotiating && + inc_local_if_state(mdev, Negotiating) ) { + int cr; /* consider resync */ + + cr = (oconn < Connected); + cr |= (oconn == Connected && + (peer_state.disk == Negotiating || + mdev->state.disk == Negotiating)); + cr |= test_bit(CONSIDER_RESYNC, &mdev->flags); /* peer forced */ + cr |= (oconn == Connected && peer_state.conn > Connected); + + if (cr) nconn=drbd_sync_handshake(mdev, peer_state.role, real_peer_disk); + + dec_local(mdev); + if (nconn == conn_mask) { + if (mdev->state.disk == Negotiating) { + drbd_force_state(mdev, NS(disk, Diskless)); + nconn = Connected; + } else if (peer_state.disk == Negotiating) { + ERR("Disk attach process on the peer node was aborted.\n"); + peer_state.disk = Diskless; + } else { + D_ASSERT(oconn == WFReportParams); + drbd_force_state(mdev, NS(conn, Disconnecting)); + return FALSE; + } + } + } + + spin_lock_irq(&mdev->req_lock); + if (mdev->state.conn != oconn) + goto retry; + clear_bit(CONSIDER_RESYNC, &mdev->flags); + ns.i = mdev->state.i; + ns.conn = nconn; + ns.peer = peer_state.role; + ns.pdsk = real_peer_disk; + ns.peer_isp = ( peer_state.aftr_isp | peer_state.user_isp ); + if ((nconn == Connected || nconn == WFBitMapS) && ns.disk == Negotiating) + ns.disk = mdev->new_state_tmp.disk; + rv = _drbd_set_state(mdev, ns, ChgStateVerbose | ChgStateHard, NULL); + ns = mdev->state; + spin_unlock_irq(&mdev->req_lock); + + if (rv < SS_Success) { + drbd_force_state(mdev, NS(conn, Disconnecting)); + return FALSE; + } + + if (oconn > WFReportParams ) { + if (nconn > Connected && peer_state.conn <= Connected) { + // we want resync, peer has not yet decided to sync... + drbd_send_uuids(mdev); + drbd_send_state(mdev); + } + else if (nconn == Connected && peer_state.disk == Negotiating) { + // peer is waiting for us to respond... + drbd_send_state(mdev); + } + } + + mdev->net_conf->want_lose = 0; + + /* FIXME assertion for (gencounts do not diverge) */ + drbd_md_sync(mdev); /* update connected indicator, la_size, ... */ + + return TRUE; +} + +STATIC int receive_sync_uuid(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_SyncUUID_Packet *p = (struct Drbd_SyncUUID_Packet *)h; + + wait_event( mdev->misc_wait, + mdev->state.conn < Connected || + mdev->state.conn == WFSyncUUID); + + /* D_ASSERT( mdev->state.conn == WFSyncUUID ); */ + + ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; + if (drbd_recv(mdev, h->payload, h->length) != h->length) + return FALSE; + + /* Here the _drbd_uuid_ functions are right, current should + _not_ be rotated into the history */ + if (inc_local_if_state(mdev, Negotiating)) { + _drbd_uuid_set(mdev, Current,be64_to_cpu(p->uuid)); + _drbd_uuid_set(mdev, Bitmap, 0UL); + + drbd_start_resync(mdev, SyncTarget); + + dec_local(mdev); + } else + ERR("Ignoring SyncUUID packet!\n"); + + return TRUE; +} + +/* Since we are processing the bitfild from lower addresses to higher, + it does not matter if the process it in 32 bit chunks or 64 bit + chunks as long as it is little endian. (Understand it as byte stream, + beginning with the lowest byte...) If we would use big endian + we would need to process it from the highest address to the lowest, + in order to be agnostic to the 32 vs 64 bits issue. + + returns 0 on failure, 1 if we suceessfully received it. */ +STATIC int receive_bitmap(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + size_t bm_words, bm_i, want, num_words; + unsigned long *buffer; + int ok = FALSE; + + wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); + + drbd_bm_lock(mdev); + + bm_words = drbd_bm_words(mdev); + bm_i = 0; + buffer = vmalloc(BM_PACKET_WORDS*sizeof(long)); + + while (1) { + num_words = min_t(size_t, BM_PACKET_WORDS, bm_words-bm_i ); + want = num_words * sizeof(long); + ERR_IF(want != h->length) goto out; + if (want == 0) + break; + if (drbd_recv(mdev, buffer, want) != want) + goto out; + + drbd_bm_merge_lel(mdev, bm_i, num_words, buffer); + bm_i += num_words; + + if (!drbd_recv_header(mdev, h)) + goto out; + D_ASSERT(h->command == ReportBitMap); + } + + if (mdev->state.conn == WFBitMapS) { + drbd_start_resync(mdev, SyncSource); + } else if (mdev->state.conn == WFBitMapT) { + ok = !drbd_send_bitmap(mdev); + if (!ok) goto out; + ok = drbd_request_state(mdev, NS(conn, WFSyncUUID)); + D_ASSERT( ok == SS_Success ); + } else { + ERR("unexpected cstate (%s) in receive_bitmap\n", + conns_to_name(mdev->state.conn)); + } + + ok = TRUE; + out: + drbd_bm_unlock(mdev); + vfree(buffer); + return ok; +} + +STATIC int receive_skip(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + /* TODO zero copy sink :) */ + static char sink[128]; + int size, want, r; + + DRBD_WARN("skipping unknown optional packet type %d, l: %d!\n", + h->command, h->length ); + + size = h->length; + while (size > 0) { + want = min_t(int, size, sizeof(sink)); + r = drbd_recv(mdev, sink, want); + ERR_IF(r < 0) break; + size -= r; + } + return (size == 0); +} + +STATIC int receive_UnplugRemote(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + if (mdev->state.disk >= Inconsistent) + drbd_kick_lo(mdev); + return TRUE; /* cannot fail. */ +} + +typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, struct Drbd_Header *); + +static drbd_cmd_handler_f drbd_default_handler[] = { + [Data] = receive_Data, + [DataReply] = receive_DataReply, + [RSDataReply] = receive_RSDataReply, + [Barrier] = receive_Barrier_no_tcq, + [ReportBitMap] = receive_bitmap, + [UnplugRemote] = receive_UnplugRemote, + [DataRequest] = receive_DataRequest, + [RSDataRequest] = receive_DataRequest, + [SyncParam] = receive_SyncParam, + [ReportProtocol] = receive_protocol, + [ReportUUIDs] = receive_uuids, + [ReportSizes] = receive_sizes, + [ReportState] = receive_state, + [StateChgRequest] = receive_req_state, + [ReportSyncUUID] = receive_sync_uuid, + [OVRequest] = receive_DataRequest, + [OVReply] = receive_DataRequest, + /* anything missing from this table is in + * the asender_tbl, see get_asender_cmd */ + [MAX_CMD] = NULL, +}; + +static drbd_cmd_handler_f *drbd_cmd_handler = drbd_default_handler; +static drbd_cmd_handler_f *drbd_opt_cmd_handler; + +STATIC void drbdd(struct drbd_conf *mdev) +{ + drbd_cmd_handler_f handler; + struct Drbd_Header *header = &mdev->data.rbuf.head; + + while (get_t_state(&mdev->receiver) == Running) { + if (!drbd_recv_header(mdev, header)) + break; + + if (header->command < MAX_CMD) + handler = drbd_cmd_handler[header->command]; + else if (MayIgnore < header->command + && header->command < MAX_OPT_CMD) + handler = drbd_opt_cmd_handler[header->command-MayIgnore]; + else if (header->command > MAX_OPT_CMD) + handler = receive_skip; + else + handler = NULL; + + if (unlikely(!handler)) { + ERR("unknown packet type %d, l: %d!\n", + header->command, header->length); + drbd_force_state(mdev, NS(conn, ProtocolError)); + break; + } + if (unlikely(!handler(mdev, header))) { + ERR("error receiving %s, l: %d!\n", + cmdname(header->command), header->length); + drbd_force_state(mdev, NS(conn, ProtocolError)); + break; + } + + dump_packet(mdev, mdev->data.socket, 2, &mdev->data.rbuf, + __FILE__, __LINE__); + } +} + +/* FIXME how should freeze-io be handled? */ +STATIC void drbd_fail_pending_reads(struct drbd_conf *mdev) +{ + struct hlist_head *slot; + struct hlist_node *n; + struct drbd_request *req; + struct list_head *le; + LIST_HEAD(workset); + int i; + + /* + * Application READ requests + */ + spin_lock_irq(&mdev->req_lock); + for (i = 0; i < APP_R_HSIZE; i++) { + slot = mdev->app_reads_hash+i; + hlist_for_each_entry(req, n, slot, colision) { + list_add(&req->w.list, &workset); + } + } + memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *)); + + while (!list_empty(&workset)) { + le = workset.next; + req = list_entry(le, struct drbd_request, w.list); + list_del(le); + + _req_mod(req, connection_lost_while_pending, 0); + } + spin_unlock_irq(&mdev->req_lock); +} + +STATIC void drbd_disconnect(struct drbd_conf *mdev) +{ + struct drbd_work prev_work_done; + enum fencing_policy fp; + union drbd_state_t os, ns; + int rv = SS_UnknownError; + + D_ASSERT(mdev->state.conn < Connected); + if (mdev->state.conn == StandAlone) return; + /* FIXME verify that: + * the state change magic prevents us from becoming >= Connected again + * while we are still cleaning up. + */ + + /* asender does not clean up anything. it must not interfere, either */ + drbd_thread_stop(&mdev->asender); + + down(&mdev->data.mutex); + drbd_free_sock(mdev); + up(&mdev->data.mutex); + + spin_lock_irq(&mdev->req_lock); + _drbd_wait_ee_list_empty(mdev, &mdev->active_ee); + _drbd_wait_ee_list_empty(mdev, &mdev->sync_ee); + _drbd_clear_done_ee(mdev); + _drbd_wait_ee_list_empty(mdev, &mdev->read_ee); + reclaim_net_ee(mdev); + spin_unlock_irq(&mdev->req_lock); + + /* FIXME: fail pending reads? + * when we are configured for freeze io, + * we could retry them once we un-freeze. */ + drbd_fail_pending_reads(mdev); + + /* We do not have data structures that would allow us to + * get the rs_pending_cnt down to 0 again. + * * On SyncTarget we do not have any data structures describing + * the pending RSDataRequest's we have sent. + * * On SyncSource there is no data structure that tracks + * the RSDataReply blocks that we sent to the SyncTarget. + * And no, it is not the sum of the reference counts in the + * resync_LRU. The resync_LRU tracks the whole operation including + * the disk-IO, while the rs_pending_cnt only tracks the blocks + * on the fly. */ + drbd_rs_cancel_all(mdev); + mdev->rs_total = 0; + mdev->rs_failed = 0; + atomic_set(&mdev->rs_pending_cnt, 0); + wake_up(&mdev->misc_wait); + + /* make sure syncer is stopped and w_resume_next_sg queued */ + del_timer_sync(&mdev->resync_timer); + set_bit(STOP_SYNC_TIMER, &mdev->flags); + resync_timer_fn((unsigned long)mdev); + + /* wait for all w_e_end_data_req, w_e_end_rsdata_req, w_send_barrier, + * w_make_resync_request etc. which may still be on the worker queue + * to be "canceled" */ + set_bit(WORK_PENDING, &mdev->flags); + prev_work_done.cb = w_prev_work_done; + drbd_queue_work(&mdev->data.work, &prev_work_done); + wait_event(mdev->misc_wait, !test_bit(WORK_PENDING, &mdev->flags)); + + kfree(mdev->p_uuid); + mdev->p_uuid = NULL; + + /* queue cleanup for the worker. + * FIXME this should go into after_state_ch */ + if (!mdev->state.susp) + tl_clear(mdev); + + INFO("Connection closed\n"); + + drbd_md_sync(mdev); + + fp = DontCare; + if (inc_local(mdev)) { + fp = mdev->bc->dc.fencing; + dec_local(mdev); + } + + if (mdev->state.role == Primary) { + if (fp >= Resource && mdev->state.pdsk >= DUnknown) { + enum drbd_disk_state nps = drbd_try_outdate_peer(mdev); + drbd_request_state(mdev, NS(pdsk, nps)); + } + } + + spin_lock_irq(&mdev->req_lock); + os = mdev->state; + if (os.conn >= Unconnected) { + /* Do not restart in case we are Disconnecting */ + ns = os; + ns.conn = Unconnected; + rv = _drbd_set_state(mdev, ns, ChgStateVerbose, NULL); + } + spin_unlock_irq(&mdev->req_lock); + + if (os.conn == Disconnecting) { + wait_event( mdev->misc_wait, atomic_read(&mdev->net_cnt) == 0 ); + + kfree(mdev->ee_hash); + mdev->ee_hash = NULL; + mdev->ee_hash_s = 0; + + kfree(mdev->tl_hash); + mdev->tl_hash = NULL; + mdev->tl_hash_s = 0; + + crypto_free_hash(mdev->cram_hmac_tfm); + mdev->cram_hmac_tfm = NULL; + + kfree(mdev->net_conf); + mdev->net_conf = NULL; + drbd_request_state(mdev, NS(conn, StandAlone)); + } + + /* they do trigger all the time. + * hm. why won't tcp release the page references, + * we already released the socket!? + D_ASSERT(atomic_read(&mdev->pp_in_use) == 0); + D_ASSERT(list_empty(&mdev->net_ee)); + */ + D_ASSERT(list_empty(&mdev->read_ee)); + D_ASSERT(list_empty(&mdev->active_ee)); + D_ASSERT(list_empty(&mdev->sync_ee)); + D_ASSERT(list_empty(&mdev->done_ee)); + + /* ok, no more ee's on the fly, it is safe to reset the epoch_size */ + mdev->epoch_size = 0; +} + +/* + * We support PRO_VERSION_MIN to PRO_VERSION_MAX. The protocol version + * we can agree on is stored in agreed_pro_version. + * + * feature flags and the reserved array should be enough room for future + * enhancements of the handshake protocol, and possible plugins... + * + * for now, they are expected to be zero, but ignored. + */ +STATIC int drbd_send_handshake(struct drbd_conf *mdev) +{ + /* ASSERT current == mdev->receiver ... */ + struct Drbd_HandShake_Packet *p = &mdev->data.sbuf.HandShake; + int ok; + + if (down_interruptible(&mdev->data.mutex)) { + ERR("interrupted during initial handshake\n"); + return 0; /* interrupted. not ok. */ + } + /* FIXME do we need to verify this here? */ + if (mdev->data.socket == NULL) { + up(&mdev->data.mutex); + return 0; + } + + memset(p, 0, sizeof(*p)); + p->protocol_min = cpu_to_be32(PRO_VERSION_MIN); + p->protocol_max = cpu_to_be32(PRO_VERSION_MAX); + ok = _drbd_send_cmd( mdev, mdev->data.socket, HandShake, + (struct Drbd_Header *)p, sizeof(*p), 0 ); + up(&mdev->data.mutex); + return ok; +} + +/* + * return values: + * 1 yess, we have a valid connection + * 0 oops, did not work out, please try again + * -1 peer talks different language, + * no point in trying again, please go standalone. + */ +int drbd_do_handshake(struct drbd_conf *mdev) +{ + /* ASSERT current == mdev->receiver ... */ + struct Drbd_HandShake_Packet *p = &mdev->data.rbuf.HandShake; + const int expect = sizeof(struct Drbd_HandShake_Packet) + -sizeof(struct Drbd_Header); + int rv; + + rv = drbd_send_handshake(mdev); + if (!rv) + return 0; + + rv = drbd_recv_header(mdev, &p->head); + if (!rv) + return 0; + + if (p->head.command != HandShake) { + ERR( "expected HandShake packet, received: %s (0x%04x)\n", + cmdname(p->head.command), p->head.command ); + return -1; + } + + if (p->head.length != expect) { + ERR( "expected HandShake length: %u, received: %u\n", + expect, p->head.length ); + return -1; + } + + rv = drbd_recv(mdev, &p->head.payload, expect); + + if (rv != expect) { + ERR("short read receiving handshake packet: l=%u\n", rv); + return 0; + } + + dump_packet(mdev, mdev->data.socket, 2, &mdev->data.rbuf, + __FILE__, __LINE__); + + p->protocol_min = be32_to_cpu(p->protocol_min); + p->protocol_max = be32_to_cpu(p->protocol_max); + if(p->protocol_max == 0) p->protocol_max = p->protocol_min; + + if (PRO_VERSION_MAX < p->protocol_min ) goto incompat; + if (PRO_VERSION_MIN > p->protocol_max ) goto incompat; + + mdev->agreed_pro_version = min_t(int,PRO_VERSION_MAX,p->protocol_max); + + INFO("Handshake successful: " + "Agreed network protocol version %d\n", mdev->agreed_pro_version); + + return 1; + + incompat: + ERR("incompatible DRBD dialects: " + "I support %d-%d, peer supports %d-%d\n", + PRO_VERSION_MIN,PRO_VERSION_MAX, + p->protocol_min, p->protocol_max); + return -1; +} + +#if !defined(CONFIG_CRYPTO_HMAC) && !defined(CONFIG_CRYPTO_HMAC_MODULE) +int drbd_do_auth(struct drbd_conf *mdev) +{ + ERR( "This kernel was build without CONFIG_CRYPTO_HMAC.\n"); + ERR( "You need to disable 'cram-hmac-alg' in drbd.conf.\n"); + return 0; +} +#else +#define CHALLENGE_LEN 64 +int drbd_do_auth(struct drbd_conf *mdev) +{ + char my_challenge[CHALLENGE_LEN]; /* 64 Bytes... */ + struct scatterlist sg; + char *response = NULL; + char *right_response = NULL; + char *peers_ch = NULL; + struct Drbd_Header p; + unsigned int key_len = strlen(mdev->net_conf->shared_secret); + unsigned int resp_size; + struct hash_desc desc; + int rv; + + desc.tfm = mdev->cram_hmac_tfm; + desc.flags = 0; + + rv = crypto_hash_setkey(mdev->cram_hmac_tfm, + (u8 *)mdev->net_conf->shared_secret, key_len); + if (rv) { + ERR("crypto_hash_setkey() failed with %d\n", rv); + rv = 0; + goto fail; + } + + get_random_bytes(my_challenge, CHALLENGE_LEN); + + rv = drbd_send_cmd2(mdev, AuthChallenge, my_challenge, CHALLENGE_LEN); + if (!rv) + goto fail; + + rv = drbd_recv_header(mdev, &p); + if (!rv) + goto fail; + + if (p.command != AuthChallenge) { + ERR( "expected AuthChallenge packet, received: %s (0x%04x)\n", + cmdname(p.command), p.command ); + rv = 0; + goto fail; + } + + if (p.length > CHALLENGE_LEN*2) { + ERR( "expected AuthChallenge payload too big.\n"); + rv = 0; + goto fail; + } + + peers_ch = kmalloc(p.length, GFP_KERNEL); + if (peers_ch == NULL) { + ERR("kmalloc of peers_ch failed\n"); + rv = 0; + goto fail; + } + + rv = drbd_recv(mdev, peers_ch, p.length); + + if (rv != p.length) { + ERR("short read AuthChallenge: l=%u\n", rv); + rv = 0; + goto fail; + } + + resp_size = crypto_hash_digestsize(mdev->cram_hmac_tfm); + response = kmalloc(resp_size, GFP_KERNEL); + if (response == NULL) { + ERR("kmalloc of response failed\n"); + rv = 0; + goto fail; + } + + sg_init_table(&sg, 1); + sg_set_buf(&sg, peers_ch, p.length); + + rv = crypto_hash_digest(&desc, &sg, sg.length, response); + if (rv) { + ERR( "crypto_hash_digest() failed with %d\n", rv); + rv = 0; + goto fail; + } + + rv = drbd_send_cmd2(mdev, AuthResponse, response, resp_size); + if (!rv) + goto fail; + + rv = drbd_recv_header(mdev, &p); + if (!rv) + goto fail; + + if (p.command != AuthResponse) { + ERR( "expected AuthResponse packet, received: %s (0x%04x)\n", + cmdname(p.command), p.command ); + rv = 0; + goto fail; + } + + if (p.length != resp_size) { + ERR( "expected AuthResponse payload of wrong size\n" ); + rv = 0; + goto fail; + } + + rv = drbd_recv(mdev, response , resp_size); + + if (rv != resp_size) { + ERR("short read receiving AuthResponse: l=%u\n", rv); + rv = 0; + goto fail; + } + + right_response = kmalloc(resp_size, GFP_KERNEL); + if (response == NULL) { + ERR("kmalloc of right_response failed\n"); + rv = 0; + goto fail; + } + + sg_set_buf(&sg, my_challenge, CHALLENGE_LEN); + + rv = crypto_hash_digest(&desc, &sg, sg.length, right_response); + if (rv) { + ERR( "crypto_hash_digest() failed with %d\n", rv); + rv = 0; + goto fail; + } + + rv = !memcmp(response, right_response, resp_size); + + if (rv) + INFO("Peer authenticated using %d bytes of '%s' HMAC\n", + resp_size, mdev->net_conf->cram_hmac_alg); + + fail: + kfree(peers_ch); + kfree(response); + kfree(right_response); + + return rv; +} +#endif + +STATIC int drbdd_init(struct Drbd_thread *thi) +{ + struct drbd_conf *mdev = thi->mdev; + int minor = mdev_to_minor(mdev); + int h; + + sprintf(current->comm, "drbd%d_receiver", minor); + set_cpus_allowed(current, drbd_calc_cpu_mask(mdev)); + INFO("receiver (re)started\n"); + + do { + h = drbd_connect(mdev); + if (h == 0) { + drbd_disconnect(mdev); + schedule_timeout(HZ); + } + if (h == -1) { + DRBD_WARN("Discarding network configuration.\n"); + drbd_force_state(mdev, NS(conn, Disconnecting)); + } + } while ( h == 0 ); + + if (h > 0) { + if (inc_net(mdev)) { + drbdd(mdev); + dec_net(mdev); + } + } + + drbd_disconnect(mdev); + + /* Ensure that the thread state fits to our connection state. */ + if (mdev->state.conn == Unconnected) { + ERR_IF( mdev->receiver.t_state != Restarting ) + drbd_thread_restart_nowait(&mdev->receiver); + } else if (mdev->state.conn == StandAlone) { + ERR_IF( mdev->receiver.t_state != Exiting ) + drbd_thread_stop_nowait(&mdev->receiver); + } + + INFO("receiver terminated\n"); + return 0; +} + +/* ********* acknowledge sender ******** */ + +STATIC int got_RqSReply(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_RqS_Reply_Packet *p = (struct Drbd_RqS_Reply_Packet *)h; + + int retcode = be32_to_cpu(p->retcode); + + if (retcode >= SS_Success) { + set_bit(CL_ST_CHG_SUCCESS, &mdev->flags); + } else { + set_bit(CL_ST_CHG_FAIL, &mdev->flags); + ERR("Requested state change failed by peer: %s\n", + set_st_err_name(retcode)); + } + wake_up(&mdev->state_wait); + + return TRUE; +} + +STATIC int got_Ping(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + return drbd_send_ping_ack(mdev); + +} + +STATIC int got_PingAck(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + /* restore idle timeout */ + mdev->meta.socket->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ; + + return TRUE; +} + +STATIC int got_BlockAck(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct drbd_request *req; + struct Drbd_BlockAck_Packet *p = (struct Drbd_BlockAck_Packet *)h; + sector_t sector = be64_to_cpu(p->sector); + int blksize = be32_to_cpu(p->blksize); + + update_peer_seq(mdev, be32_to_cpu(p->seq_num)); + + if ( is_syncer_block_id(p->block_id)) { + drbd_set_in_sync(mdev, sector, blksize); + dec_rs_pending(mdev); + } else { + spin_lock_irq(&mdev->req_lock); + req = _ack_id_to_req(mdev, p->block_id, sector); + + if (unlikely(!req)) { + spin_unlock_irq(&mdev->req_lock); + ERR("Got a corrupt block_id/sector pair(2).\n"); + return FALSE; + } + + switch (be16_to_cpu(h->command)) { + case RSWriteAck: + D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C); + _req_mod(req, write_acked_by_peer_and_sis, 0); + break; + case WriteAck: + D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C); + _req_mod(req, write_acked_by_peer, 0); + break; + case RecvAck: + D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_B); + _req_mod(req, recv_acked_by_peer, 0); + break; + case DiscardAck: + D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C); + ALERT("Got DiscardAck packet %llus +%u!" + " DRBD is not a random data generator!\n", + (unsigned long long)req->sector, req->size); + _req_mod(req, conflict_discarded_by_peer, 0); + break; + default: + D_ASSERT(0); + } + spin_unlock_irq(&mdev->req_lock); + } + /* dec_ap_pending is handled within _req_mod */ + + return TRUE; +} + +STATIC int got_NegAck(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_BlockAck_Packet *p = (struct Drbd_BlockAck_Packet *)h; + sector_t sector = be64_to_cpu(p->sector); + struct drbd_request *req; + + if (DRBD_ratelimit(5*HZ, 5)) + DRBD_WARN("Got NegAck packet. Peer is in troubles?\n"); + + update_peer_seq(mdev, be32_to_cpu(p->seq_num)); + + if (is_syncer_block_id(p->block_id)) { + int size = be32_to_cpu(p->blksize); + + dec_rs_pending(mdev); + + drbd_rs_failed_io(mdev, sector, size); + } else { + spin_lock_irq(&mdev->req_lock); + req = _ack_id_to_req(mdev, p->block_id, sector); + + if (unlikely(!req)) { + spin_unlock_irq(&mdev->req_lock); + ERR("Got a corrupt block_id/sector pair(2).\n"); + return FALSE; + } + + _req_mod(req, neg_acked, 0); + spin_unlock_irq(&mdev->req_lock); + } + + return TRUE; +} + +STATIC int got_NegDReply(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct drbd_request *req; + struct Drbd_BlockAck_Packet *p = (struct Drbd_BlockAck_Packet *)h; + sector_t sector = be64_to_cpu(p->sector); + + spin_lock_irq(&mdev->req_lock); + req = _ar_id_to_req(mdev, p->block_id, sector); + if (unlikely(!req)) { + spin_unlock_irq(&mdev->req_lock); + ERR("Got a corrupt block_id/sector pair(3).\n"); + return FALSE; + } + + /* FIXME explicitly warn if protocol != C */ + + ERR("Got NegDReply; Sector %llus, len %u; Fail original request.\n", + (unsigned long long)sector, be32_to_cpu(p->blksize)); + + _req_mod(req, neg_acked, 0); + spin_unlock_irq(&mdev->req_lock); + + /* "ugly and wrong" but what can we do !? */ + drbd_khelper(mdev, "pri-on-incon-degr"); + + return TRUE; +} + +STATIC int got_NegRSDReply(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + sector_t sector; + int size; + struct Drbd_BlockAck_Packet *p = (struct Drbd_BlockAck_Packet *)h; + + sector = be64_to_cpu(p->sector); + size = be32_to_cpu(p->blksize); + D_ASSERT(p->block_id == ID_SYNCER); + + dec_rs_pending(mdev); + + if (inc_local_if_state(mdev, Failed)) { + drbd_rs_complete_io(mdev, sector); + drbd_rs_failed_io(mdev, sector, size); + dec_local(mdev); + } + + return TRUE; +} + +STATIC int got_BarrierAck(struct drbd_conf *mdev, struct Drbd_Header *h) +{ + struct Drbd_BarrierAck_Packet *p = (struct Drbd_BarrierAck_Packet *)h; + + tl_release(mdev, p->barrier, be32_to_cpu(p->set_size)); + dec_ap_pending(mdev); + + return TRUE; +} + + +STATIC int got_OVResult(struct drbd_conf *mdev, struct Drbd_Header* h) +{ + struct Drbd_BlockAck_Packet *p = (struct Drbd_BlockAck_Packet*)h; + struct drbd_work* w; + sector_t sector; + int size; + + sector = be64_to_cpu(p->sector); + size = be32_to_cpu(p->blksize); + + if (be64_to_cpu(p->block_id) == ID_OUT_OF_SYNC) { + drbd_ov_oos_found(mdev, sector, size); + } else ov_oos_print(mdev); + + drbd_rs_complete_io(mdev, sector); + dec_rs_pending(mdev); + + if (--mdev->ov_left == 0) { + w = kmalloc(sizeof(w), GFP_KERNEL); + if (w) { + w->cb = w_ov_finished; + drbd_queue_work_front(&mdev->data.work, w); + } else { + ERR("kmalloc(w) failed."); + drbd_resync_finished(mdev); + } + } + return TRUE; +} + + +struct asender_cmd { + size_t pkt_size; + int (*process)(struct drbd_conf *mdev, struct Drbd_Header *h); +}; + +static struct asender_cmd* get_asender_cmd(int cmd) +{ + static struct asender_cmd asender_tbl[] = { + /* anything missing from this table is in + * the drbd_cmd_handler (drbd_default_handler) table, + * see the beginning of drbdd() */ + [Ping] = { sizeof(struct Drbd_Header), got_Ping }, + [PingAck] = { sizeof(struct Drbd_Header), got_PingAck }, + [RecvAck] = { sizeof(struct Drbd_BlockAck_Packet), got_BlockAck }, + [WriteAck] = { sizeof(struct Drbd_BlockAck_Packet), got_BlockAck }, + [RSWriteAck] = { sizeof(struct Drbd_BlockAck_Packet), got_BlockAck }, + [DiscardAck] = { sizeof(struct Drbd_BlockAck_Packet), got_BlockAck }, + [NegAck] = { sizeof(struct Drbd_BlockAck_Packet), got_NegAck }, + [NegDReply] = + { sizeof(struct Drbd_BlockAck_Packet), got_NegDReply }, + [NegRSDReply] = + { sizeof(struct Drbd_BlockAck_Packet), got_NegRSDReply}, + [OVResult] = { sizeof(struct Drbd_BlockAck_Packet), got_OVResult }, + + [BarrierAck] = + { sizeof(struct Drbd_BarrierAck_Packet), got_BarrierAck }, + [StateChgReply] = + { sizeof(struct Drbd_RqS_Reply_Packet), got_RqSReply }, + }; + if (cmd == OVResult) + return &asender_tbl[cmd]; + if (cmd < FIRST_ASENDER_CMD) + return NULL; + if (cmd > LAST_ASENDER_CMD) + return NULL; + return &asender_tbl[cmd]; +} + +STATIC int drbd_asender(struct Drbd_thread *thi) +{ + struct drbd_conf *mdev = thi->mdev; + struct Drbd_Header *h = &mdev->meta.rbuf.head; + struct asender_cmd *cmd = NULL; + + int rv,len; + void *buf = h; + int received = 0; + int expect = sizeof(struct Drbd_Header); + int empty; + + sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev)); + + current->policy = SCHED_RR; /* Make this a realtime task! */ + current->rt_priority = 2; /* more important than all other tasks */ + + set_cpus_allowed(current, drbd_calc_cpu_mask(mdev)); + + while (get_t_state(thi) == Running) { + if (test_and_clear_bit(SEND_PING, &mdev->flags)) { + ERR_IF(!drbd_send_ping(mdev)) goto reconnect; + mdev->meta.socket->sk->sk_rcvtimeo = + mdev->net_conf->ping_timeo*HZ/10; + } + + while (1) { + if (!drbd_process_done_ee(mdev)) { + ERR("process_done_ee() = NOT_OK\n"); + goto reconnect; + } + set_bit(SIGNAL_ASENDER, &mdev->flags); + spin_lock_irq(&mdev->req_lock); + empty = list_empty(&mdev->done_ee); + spin_unlock_irq(&mdev->req_lock); + if (empty && !test_bit(WRITE_ACK_PENDING, &mdev->flags)) + break; + clear_bit(SIGNAL_ASENDER, &mdev->flags); + flush_signals(current); + } + drbd_tcp_flush(mdev->meta.socket); + + rv = drbd_recv_short(mdev, mdev->meta.socket, + buf, expect-received, 0); + clear_bit(SIGNAL_ASENDER, &mdev->flags); + + flush_signals(current); + + drbd_tcp_cork(mdev->meta.socket); + + /* Note: + * -EINTR (on meta) we got a signal + * -EAGAIN (on meta) rcvtimeo expired + * -ECONNRESET other side closed the connection + * -ERESTARTSYS (on data) we got a signal + * rv < 0 other than above: unexpected error! + * rv == expected: full header or command + * rv < expected: "woken" by signal during receive + * rv == 0 : "connection shut down by peer" + */ + if (likely(rv > 0)) { + received += rv; + buf += rv; + } else if (rv == 0) { + ERR("meta connection shut down by peer.\n"); + goto reconnect; + } else if (rv == -EAGAIN) { + if ( mdev->meta.socket->sk->sk_rcvtimeo == + mdev->net_conf->ping_timeo*HZ/10 ) { + ERR("PingAck did not arrive in time.\n"); + goto reconnect; + } + set_bit(SEND_PING, &mdev->flags); + continue; + } else if (rv == -EINTR) { + continue; + } else { + ERR("sock_recvmsg returned %d\n", rv); + goto reconnect; + } + + if (received == expect && cmd == NULL ) { + if (unlikely( h->magic != BE_DRBD_MAGIC )) { + ERR("magic?? on meta m: 0x%lx c: %d l: %d\n", + (long)be32_to_cpu(h->magic), + h->command, h->length); + goto reconnect; + } + cmd = get_asender_cmd(be16_to_cpu(h->command)); + len = be16_to_cpu(h->length); + if (unlikely(cmd == NULL)) { + ERR("unknown command?? on meta m: 0x%lx c: %d l: %d\n", + (long)be32_to_cpu(h->magic), + h->command, h->length); + goto disconnect; + } + expect = cmd->pkt_size; + ERR_IF(len != expect-sizeof(struct Drbd_Header)) { + dump_packet(mdev,mdev->meta.socket,1,(void*)h, __FILE__, __LINE__); + DUMPI(expect); + goto reconnect; + } + } + if (received == expect) { + D_ASSERT(cmd != NULL); + dump_packet(mdev,mdev->meta.socket,1,(void*)h, __FILE__, __LINE__); + if (!cmd->process(mdev,h)) goto reconnect; + + buf = h; + received = 0; + expect = sizeof(struct Drbd_Header); + cmd = NULL; + } + } + + if (0) { + reconnect: + drbd_force_state(mdev,NS(conn, NetworkFailure)); + } + if (0) { + disconnect: + drbd_force_state(mdev,NS(conn, Disconnecting)); + } + clear_bit(SIGNAL_ASENDER, &mdev->flags); + + D_ASSERT(mdev->state.conn < Connected); + INFO("asender terminated\n"); + + return 0; +} --- linux-2.6.27.orig/ubuntu/drbd/drbd_strings.c +++ linux-2.6.27/ubuntu/drbd/drbd_strings.c @@ -0,0 +1,116 @@ +/* + drbd.h + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. + Copyright (C) 2003-2008, Philipp Reisner . + Copyright (C) 2003-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include + +static const char *drbd_conn_s_names[] = { + [StandAlone] = "StandAlone", + [Disconnecting] = "Disconnecting", + [Unconnected] = "Unconnected", + [Timeout] = "Timeout", + [BrokenPipe] = "BrokenPipe", + [NetworkFailure] = "NetworkFailure", + [ProtocolError] = "ProtocolError", + [WFConnection] = "WFConnection", + [WFReportParams] = "WFReportParams", + [TearDown] = "TearDown", + [Connected] = "Connected", + [StartingSyncS] = "StartingSyncS", + [StartingSyncT] = "StartingSyncT", + [WFBitMapS] = "WFBitMapS", + [WFBitMapT] = "WFBitMapT", + [WFSyncUUID] = "WFSyncUUID", + [SyncSource] = "SyncSource", + [SyncTarget] = "SyncTarget", + [VerifyS] = "VerifyS", + [VerifyT] = "VerifyT", + [PausedSyncS] = "PausedSyncS", + [PausedSyncT] = "PausedSyncT" +}; + +static const char *drbd_role_s_names[] = { + [Primary] = "Primary", + [Secondary] = "Secondary", + [Unknown] = "Unknown" +}; + +static const char *drbd_disk_s_names[] = { + [Diskless] = "Diskless", + [Attaching] = "Attaching", + [Failed] = "Failed", + [Negotiating] = "Negotiating", + [Inconsistent] = "Inconsistent", + [Outdated] = "Outdated", + [DUnknown] = "DUnknown", + [Consistent] = "Consistent", + [UpToDate] = "UpToDate", +}; + +static const char *drbd_state_sw_errors[] = { + [-SS_TwoPrimaries] = "Multiple primaries not allowed by config", + [-SS_NoUpToDateDisk] = + "Refusing to be Primary without at least one UpToDate disk", + [-SS_BothInconsistent] = "Refusing to be inconsistent on both nodes", + [-SS_SyncingDiskless] = "Refusing to be syncing and diskless", + [-SS_ConnectedOutdates] = "Refusing to be Outdated while Connected", + [-SS_PrimaryNOP] = "Refusing to be Primary while peer is not outdated", + [-SS_ResyncRunning] = "Can not start OV/resync since it is already active", + [-SS_AlreadyStandAlone] = "Can not disconnect a StandAlone device", + [-SS_CW_FailedByPeer] = "State changed was refused by peer node", + [-SS_IsDiskLess] = + "Device is diskless, the requesed operation requires a disk", + [-SS_DeviceInUse] = "Device is held open by someone", + [-SS_NoNetConfig] = "Have no net/connection configuration", + [-SS_NoVerifyAlg] = "Need a verify algorithm to start online verify", + [-SS_NeedConnection] = "Need a connection to start verify or resync", + [-SS_NotSupported] = "Peer does not support protocol", + [-SS_LowerThanOutdated] = "Disk state is lower than outdated", + [-SS_InTransientState] = "In transient state, retry after next state change", + [-SS_ConcurrentStChg] = "Concurrent state changes detected and aborted", +}; + +const char *conns_to_name(enum drbd_conns s) +{ + /* enums are unsigned... */ + return s > PausedSyncT ? "TOO_LARGE" : drbd_conn_s_names[s]; +} + +const char *roles_to_name(enum drbd_role s) +{ + return s > Secondary ? "TOO_LARGE" : drbd_role_s_names[s]; +} + +const char *disks_to_name(enum drbd_disk_state s) +{ + return s > UpToDate ? "TOO_LARGE" : drbd_disk_s_names[s]; +} + +const char *set_st_err_name(enum set_st_err err) +{ + return err < SS_NotSupported ? "TOO_SMALL" : + err > SS_TwoPrimaries ? "TOO_LARGE" + : drbd_state_sw_errors[-err]; +} --- linux-2.6.27.orig/ubuntu/drbd/drbd_buildtag.c +++ linux-2.6.27/ubuntu/drbd/drbd_buildtag.c @@ -0,0 +1,7 @@ +/* automatically generated. DO NOT EDIT. */ +#include +const char * drbd_buildtag(void) +{ + return "GIT-hash: 3e69822d3bb4920a8c1bfdf7d647169eba7d2eb4" + " build by phil@fat-tyre, 2008-05-30 12:59:17"; +} --- linux-2.6.27.orig/ubuntu/drbd/drbd_actlog.c +++ linux-2.6.27/ubuntu/drbd/drbd_actlog.c @@ -0,0 +1,1510 @@ +/* +-*- linux-c -*- + drbd_actlog.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. + Copyright (C) 2003-2008, Philipp Reisner . + Copyright (C) 2003-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include +#include +#include "drbd_int.h" + +/* This is what I like so much about the linux kernel: + * if you have a close look, you can almost always reuse code by someone else + * ;) + * this is mostly from drivers/md/md.c + */ +STATIC int _drbd_md_sync_page_io(struct drbd_conf *mdev, + struct drbd_backing_dev *bdev, + struct page *page, sector_t sector, + int rw, int size) +{ + struct bio *bio; + struct drbd_md_io md_io; + int ok; + + md_io.mdev = mdev; + init_completion(&md_io.event); + md_io.error = 0; + + if (rw == WRITE && !test_bit(MD_NO_BARRIER, &mdev->flags)) + rw |= (1<bi_bdev = bdev->md_bdev; + bio->bi_sector = sector; + ok = (bio_add_page(bio, page, size, 0) == size); + if (!ok) + goto out; + bio->bi_private = &md_io; + bio->bi_end_io = drbd_md_io_complete; + bio->bi_rw = rw; + + dump_internal_bio("Md", mdev, bio, 0); + + if (FAULT_ACTIVE(mdev, (rw & WRITE)? DRBD_FAULT_MD_WR:DRBD_FAULT_MD_RD)) + bio_endio(bio, -EIO); + else + submit_bio(rw, bio); + wait_for_completion(&md_io.event); + ok = bio_flagged(bio, BIO_UPTODATE); + + /* check for unsupported barrier op */ + if (unlikely(md_io.error == -EOPNOTSUPP && bio_barrier(bio))) { + /* Try again with no barrier */ + DRBD_WARN("Barriers not supported on meta data device - disabling\n"); + set_bit(MD_NO_BARRIER,&mdev->flags); + rw &= ~(1 << BIO_RW_BARRIER); + bio_put(bio); + goto retry; + } + out: + bio_put(bio); + return ok; +} + +int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, + sector_t sector, int rw) +{ + int hardsect, mask, ok; + int offset = 0; + struct page *iop = mdev->md_io_page; + + D_ASSERT(semaphore_is_locked(&mdev->md_io_mutex)); + + if (!bdev->md_bdev) { + if (DRBD_ratelimit(5*HZ, 5)) { + ERR("bdev->md_bdev==NULL\n"); + dump_stack(); + } + return 0; + } + + hardsect = drbd_get_hardsect(bdev->md_bdev); + if (hardsect == 0) + hardsect = MD_HARDSECT; + + /* in case hardsect != 512 [ s390 only? ] */ + if (hardsect != MD_HARDSECT) { + if (!mdev->md_io_tmpp) { + struct page *page = alloc_page(GFP_NOIO); + if (!page) + return 0; + + DRBD_WARN("Meta data's bdev hardsect = %d != %d\n", + hardsect, MD_HARDSECT); + DRBD_WARN("Workaround engaged (has performace impact).\n"); + + mdev->md_io_tmpp = page; + } + + mask = ( hardsect / MD_HARDSECT ) - 1; + D_ASSERT( mask == 1 || mask == 3 || mask == 7 ); + D_ASSERT( hardsect == (mask+1) * MD_HARDSECT ); + offset = sector & mask; + sector = sector & ~mask; + iop = mdev->md_io_tmpp; + + if (rw == WRITE) { + void *p = page_address(mdev->md_io_page); + void *hp = page_address(mdev->md_io_tmpp); + + ok = _drbd_md_sync_page_io(mdev, bdev, iop, + sector, READ, hardsect); + + if (unlikely(!ok)) { + ERR("drbd_md_sync_page_io(,%llus," + "READ [hardsect!=512]) failed!\n", + (unsigned long long)sector); + return 0; + } + + memcpy(hp + offset*MD_HARDSECT , p, MD_HARDSECT); + } + } + +#if DUMP_MD >= 3 + INFO("%s [%d]:%s(,%llus,%s)\n", + current->comm, current->pid, __func__, + (unsigned long long)sector, rw ? "WRITE" : "READ"); +#endif + + if (sector < drbd_md_first_sector(bdev) || + sector > drbd_md_last_sector(bdev)) + ALERT("%s [%d]:%s(,%llus,%s) out of range md access!\n", + current->comm, current->pid, __func__, + (unsigned long long)sector, rw ? "WRITE" : "READ"); + + ok = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, hardsect); + if (unlikely(!ok)) { + ERR("drbd_md_sync_page_io(,%llus,%s) failed!\n", + (unsigned long long)sector, rw ? "WRITE" : "READ"); + return 0; + } + + if (hardsect != MD_HARDSECT && rw == READ) { + void *p = page_address(mdev->md_io_page); + void *hp = page_address(mdev->md_io_tmpp); + + memcpy(p, hp + offset*MD_HARDSECT, MD_HARDSECT); + } + + return ok; +} + +/* I do not believe that all storage medias can guarantee atomic + * 512 byte write operations. When the journal is read, only + * transactions with correct xor_sums are considered. + * sizeof() = 512 byte */ +struct __attribute__((packed)) al_transaction { + u32 magic; + u32 tr_number; + /* u32 tr_generation; TODO */ + struct __attribute__((packed)) { + u32 pos; + u32 extent; } updates[1 + AL_EXTENTS_PT]; + u32 xor_sum; +}; + +struct update_odbm_work { + struct drbd_work w; + unsigned int enr; +}; + +struct update_al_work { + struct drbd_work w; + struct lc_element *al_ext; + struct completion event; + unsigned int enr; + /* if old_enr != LC_FREE, write corresponding bitmap sector, too */ + unsigned int old_enr; +}; + +int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int); + +static inline +struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr) +{ + struct lc_element *al_ext; + struct bm_extent *bm_ext; + unsigned long al_flags = 0; + + spin_lock_irq(&mdev->al_lock); + bm_ext = (struct bm_extent *) + lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT); + if (unlikely(bm_ext != NULL)) { + if (test_bit(BME_NO_WRITES, &bm_ext->flags)) { + spin_unlock_irq(&mdev->al_lock); + return NULL; + } + } + al_ext = lc_get(mdev->act_log, enr); + al_flags = mdev->act_log->flags; + spin_unlock_irq(&mdev->al_lock); + + /* + if (!al_ext) { + if (al_flags & LC_STARVING) + DRBD_WARN("Have to wait for LRU element (AL too small?)\n"); + if (al_flags & LC_DIRTY) + DRBD_WARN("Ongoing AL update (AL device too slow?)\n"); + } + */ + + return al_ext; +} + +/* FIXME + * this should be able to return failure when meta data update has failed. + */ +void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector) +{ + unsigned int enr = (sector >> (AL_EXTENT_SIZE_B-9)); + struct lc_element *al_ext; + struct update_al_work al_work; + + D_ASSERT(atomic_read(&mdev->local_cnt) > 0); + + MTRACE(TraceTypeALExts, TraceLvlMetrics, + INFO("al_begin_io( sec=%llus (al_enr=%u) (rs_enr=%d) )\n", + (unsigned long long) sector, enr, + (int)BM_SECT_TO_EXT(sector)); + ); + + wait_event(mdev->al_wait, (al_ext = _al_get(mdev, enr)) ); + + if (al_ext->lc_number != enr) { + /* drbd_al_write_transaction(mdev,al_ext,enr); + generic_make_request() are serialized on the + current->bio_tail list now. Therefore we have + to deligate writing something to AL to the + worker thread. */ + init_completion(&al_work.event); + al_work.al_ext = al_ext; + al_work.enr = enr; + al_work.old_enr = al_ext->lc_number; + al_work.w.cb = w_al_write_transaction; + drbd_queue_work_front(&mdev->data.work, &al_work.w); + wait_for_completion(&al_work.event); + + mdev->al_writ_cnt++; + + /* + DUMPI(al_ext->lc_number); + DUMPI(mdev->act_log->new_number); + */ + spin_lock_irq(&mdev->al_lock); + lc_changed(mdev->act_log, al_ext); + spin_unlock_irq(&mdev->al_lock); + wake_up(&mdev->al_wait); + } +} + +void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector) +{ + unsigned int enr = (sector >> (AL_EXTENT_SIZE_B-9)); + struct lc_element *extent; + unsigned long flags; + + MTRACE(TraceTypeALExts, TraceLvlMetrics, + INFO("al_complete_io( sec=%llus (al_enr=%u) (rs_enr=%d) )\n", + (unsigned long long) sector, enr, + (int)BM_SECT_TO_EXT(sector)); + ); + + spin_lock_irqsave(&mdev->al_lock, flags); + + extent = lc_find(mdev->act_log, enr); + + if (!extent) { + spin_unlock_irqrestore(&mdev->al_lock, flags); + ERR("al_complete_io() called on inactive extent %u\n", enr); + return; + } + + if (lc_put(mdev->act_log, extent) == 0) + wake_up(&mdev->al_wait); + + spin_unlock_irqrestore(&mdev->al_lock, flags); +} + +int +w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + struct update_al_work *aw = (struct update_al_work*)w; + struct lc_element *updated = aw->al_ext; + const unsigned int new_enr = aw->enr; + const unsigned int evicted = aw->old_enr; + + struct al_transaction* buffer; + sector_t sector; + int i,n,mx; + unsigned int extent_nr; + u32 xor_sum=0; + + if (!inc_local(mdev)) { + ERR("inc_local() failed in w_al_write_transaction\n"); + complete(&((struct update_al_work*)w)->event); + return 1; + } + /* do we have to do a bitmap write, first? + * TODO reduce maximum latency: + * submit both bios, then wait for both, + * instead of doing two synchronous sector writes. */ + if (mdev->state.conn < Connected && evicted != LC_FREE) + drbd_bm_write_sect(mdev, evicted/AL_EXT_PER_BM_SECT); + + down(&mdev->md_io_mutex); /* protects md_io_buffer, al_tr_cycle, ... */ + buffer = (struct al_transaction *)page_address(mdev->md_io_page); + + buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC); + buffer->tr_number = cpu_to_be32(mdev->al_tr_number); + + n = lc_index_of(mdev->act_log, updated); + + buffer->updates[0].pos = cpu_to_be32(n); + buffer->updates[0].extent = cpu_to_be32(new_enr); + + xor_sum ^= new_enr; + + mx = min_t(int, AL_EXTENTS_PT, + mdev->act_log->nr_elements - mdev->al_tr_cycle); + for (i = 0; i < mx; i++) { + extent_nr = lc_entry(mdev->act_log, + mdev->al_tr_cycle+i)->lc_number; + buffer->updates[i+1].pos = cpu_to_be32(mdev->al_tr_cycle+i); + buffer->updates[i+1].extent = cpu_to_be32(extent_nr); + xor_sum ^= extent_nr; + } + for (; i < AL_EXTENTS_PT; i++) { + buffer->updates[i+1].pos = __constant_cpu_to_be32(-1); + buffer->updates[i+1].extent = __constant_cpu_to_be32(LC_FREE); + xor_sum ^= LC_FREE; + } + mdev->al_tr_cycle += AL_EXTENTS_PT; + if (mdev->al_tr_cycle >= mdev->act_log->nr_elements) + mdev->al_tr_cycle = 0; + + buffer->xor_sum = cpu_to_be32(xor_sum); + + sector = mdev->bc->md.md_offset + + mdev->bc->md.al_offset + mdev->al_tr_pos; + + if (!drbd_md_sync_page_io(mdev, mdev->bc, sector, WRITE)) { + drbd_chk_io_error(mdev, 1, TRUE); + drbd_io_error(mdev, TRUE); + } + + if (++mdev->al_tr_pos > + div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT)) + mdev->al_tr_pos = 0; + + D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE); + mdev->al_tr_number++; + + up(&mdev->md_io_mutex); + + complete(&((struct update_al_work *)w)->event); + dec_local(mdev); + + return 1; +} + +/** + * drbd_al_read_tr: Reads a single transaction record form the + * on disk activity log. + * Returns -1 on IO error, 0 on checksum error and 1 if it is a valid + * record. + */ +STATIC int drbd_al_read_tr(struct drbd_conf *mdev, + struct drbd_backing_dev *bdev, + struct al_transaction *b, + int index) +{ + sector_t sector; + int rv, i; + u32 xor_sum = 0; + + sector = bdev->md.md_offset + bdev->md.al_offset + index; + + /* Dont process error normally, + * as this is done before disk is atached! */ + if (!drbd_md_sync_page_io(mdev, bdev, sector, READ)) + return -1; + + rv = ( be32_to_cpu(b->magic) == DRBD_MAGIC ); + + for (i = 0; i < AL_EXTENTS_PT+1; i++) + xor_sum ^= be32_to_cpu(b->updates[i].extent); + rv &= (xor_sum == be32_to_cpu(b->xor_sum)); + + return rv; +} + +/** + * drbd_al_read_log: Restores the activity log from its on disk + * representation. Returns 1 on success, returns 0 when + * reading the log failed due to IO errors. + */ +int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) +{ + struct al_transaction *buffer; + int i; + int rv; + int mx; + int cnr; + int active_extents = 0; + int transactions = 0; + int overflow = 0; + int from = -1; + int to = -1; + u32 from_tnr = -1; + u32 to_tnr = 0; + + mx = div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT); + + /* lock out all other meta data io for now, + * and make sure the page is mapped. + */ + down(&mdev->md_io_mutex); + buffer = page_address(mdev->md_io_page); + + /* Find the valid transaction in the log */ + for (i = 0; i <= mx; i++) { + rv = drbd_al_read_tr(mdev, bdev, buffer, i); + if (rv == 0) + continue; + if (rv == -1) { + up(&mdev->md_io_mutex); + return 0; + } + cnr = be32_to_cpu(buffer->tr_number); + /* INFO("index %d valid tnr=%d\n",i,cnr); */ + + if (cnr == -1) + overflow = 1; + + if (cnr < from_tnr && !overflow) { + from = i; + from_tnr = cnr; + } + if (cnr > to_tnr) { + to = i; + to_tnr = cnr; + } + } + + if (from == -1 || to == -1) { + DRBD_WARN("No usable activity log found.\n"); + + up(&mdev->md_io_mutex); + return 1; + } + + /* Read the valid transactions. + * INFO("Reading from %d to %d.\n",from,to); */ + i = from; + while (1) { + int j, pos; + unsigned int extent_nr; + unsigned int trn; + + rv = drbd_al_read_tr(mdev, bdev, buffer, i); + ERR_IF(rv == 0) goto cancel; + if (rv == -1) { + up(&mdev->md_io_mutex); + return 0; + } + + trn = be32_to_cpu(buffer->tr_number); + + spin_lock_irq(&mdev->al_lock); + + /* This loop runs backwards because in the cyclic + elements there might be an old version of the + updated element (in slot 0). So the element in slot 0 + can overwrite old versions. */ + for (j = AL_EXTENTS_PT; j >= 0; j--) { + pos = be32_to_cpu(buffer->updates[j].pos); + extent_nr = be32_to_cpu(buffer->updates[j].extent); + + if (extent_nr == LC_FREE) + continue; + + lc_set(mdev->act_log, extent_nr, pos); + active_extents++; + } + spin_unlock_irq(&mdev->al_lock); + + transactions++; + +cancel: + if (i == to) + break; + i++; + if (i > mx) + i = 0; + } + + mdev->al_tr_number = to_tnr+1; + mdev->al_tr_pos = to; + if (++mdev->al_tr_pos > + div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT)) + mdev->al_tr_pos = 0; + + /* ok, we are done with it */ + up(&mdev->md_io_mutex); + + INFO("Found %d transactions (%d active extents) in activity log.\n", + transactions, active_extents); + + return 1; +} + +struct drbd_atodb_wait { + atomic_t count; + struct completion io_done; + struct drbd_conf *mdev; + int error; +}; + +STATIC BIO_ENDIO_TYPE atodb_endio BIO_ENDIO_ARGS(struct bio *bio, int error) +{ + struct drbd_atodb_wait *wc = bio->bi_private; + struct drbd_conf *mdev = wc->mdev; + struct page *page; + int uptodate = bio_flagged(bio, BIO_UPTODATE); + + BIO_ENDIO_FN_START; + /* strange behaviour of some lower level drivers... + * fail the request by clearing the uptodate flag, + * but do not return any error?! + * do we want to DRBD_WARN() on this? */ + if (!error && !uptodate) + error = -EIO; + + /* corresponding drbd_io_error is in drbd_al_to_on_disk_bm */ + drbd_chk_io_error(mdev, error, TRUE); + if (error && wc->error == 0) + wc->error = error; + + if (atomic_dec_and_test(&wc->count)) + complete(&wc->io_done); + + page = bio->bi_io_vec[0].bv_page; + put_page(page); + bio_put(bio); + mdev->bm_writ_cnt++; + dec_local(mdev); + + BIO_ENDIO_FN_RETURN; +} + +#define S2W(s) ((s)<<(BM_EXT_SIZE_B-BM_BLOCK_SIZE_B-LN2_BPL)) +/* activity log to on disk bitmap -- prepare bio unless that sector + * is already covered by previously prepared bios */ +STATIC int atodb_prepare_unless_covered(struct drbd_conf *mdev, + struct bio **bios, + unsigned int enr, + struct drbd_atodb_wait *wc) __must_hold(local) +{ + struct bio *bio; + struct page *page; + sector_t on_disk_sector = enr + mdev->bc->md.md_offset + + mdev->bc->md.bm_offset; + unsigned int page_offset = PAGE_SIZE; + int offset; + int i = 0; + int err = -ENOMEM; + + /* Check if that enr is already covered by an already created bio. + * Caution, bios[] is not NULL terminated, + * but only initialized to all NULL. + * For completely scattered activity log, + * the last invocation iterates over all bios, + * and finds the last NULL entry. + */ + while ( (bio = bios[i]) ) { + if (bio->bi_sector == on_disk_sector) + return 0; + i++; + } + /* bios[i] == NULL, the next not yet used slot */ + + bio = bio_alloc(GFP_KERNEL, 1); + if (bio == NULL) + return -ENOMEM; + + if (i > 0) { + const struct bio_vec *prev_bv = bios[i-1]->bi_io_vec; + page_offset = prev_bv->bv_offset + prev_bv->bv_len; + page = prev_bv->bv_page; + } + if (page_offset == PAGE_SIZE) { + page = alloc_page(__GFP_HIGHMEM); + if (page == NULL) + goto out_bio_put; + page_offset = 0; + } else { + get_page(page); + } + + offset = S2W(enr); + drbd_bm_get_lel( mdev, offset, + min_t(size_t, S2W(1), drbd_bm_words(mdev) - offset), + kmap(page) + page_offset ); + kunmap(page); + + bio->bi_private = wc; + bio->bi_end_io = atodb_endio; + bio->bi_bdev = mdev->bc->md_bdev; + bio->bi_sector = on_disk_sector; + + if (bio_add_page(bio, page, MD_HARDSECT, page_offset) != MD_HARDSECT) + goto out_put_page; + + atomic_inc(&wc->count); + /* we already know that we may do this... + * inc_local_if_state(mdev,Attaching); + * just get the extra reference, so that the local_cnt reflects + * the number of pending IO requests DRBD at its backing device. + */ + atomic_inc(&mdev->local_cnt); + + bios[i] = bio; + + return 0; + +out_put_page: + err = -EINVAL; + put_page(page); +out_bio_put: + bio_put(bio); + return err; +} + +/** + * drbd_al_to_on_disk_bm: + * Writes the areas of the bitmap which are covered by the AL. + * called when we detach (unconfigure) local storage, + * or when we go from Primary to Secondary state. + */ +void drbd_al_to_on_disk_bm(struct drbd_conf *mdev) +{ + int i, nr_elements; + unsigned int enr; + struct bio **bios; + struct drbd_atodb_wait wc; + + ERR_IF (!inc_local_if_state(mdev, Attaching)) + return; /* sorry, I don't have any act_log etc... */ + + wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); + + nr_elements = mdev->act_log->nr_elements; + + bios = kzalloc(sizeof(struct bio *) * nr_elements, GFP_KERNEL); + if (!bios) + goto submit_one_by_one; + + atomic_set(&wc.count, 0); + init_completion(&wc.io_done); + wc.mdev = mdev; + wc.error = 0; + + for (i = 0; i < nr_elements; i++) { + enr = lc_entry(mdev->act_log, i)->lc_number; + if (enr == LC_FREE) + continue; + /* next statement also does atomic_inc wc.count and local_cnt */ + if (atodb_prepare_unless_covered(mdev, bios, + enr/AL_EXT_PER_BM_SECT, + &wc)) + goto free_bios_submit_one_by_one; + } + + /* unneccessary optimization? */ + lc_unlock(mdev->act_log); + wake_up(&mdev->al_wait); + + /* all prepared, submit them */ + for (i = 0; i < nr_elements; i++) { + if (bios[i] == NULL) + break; + if (FAULT_ACTIVE( mdev, DRBD_FAULT_MD_WR )) { + bios[i]->bi_rw = WRITE; + bio_endio(bios[i], -EIO); + } else { + submit_bio(WRITE, bios[i]); + } + } + + drbd_blk_run_queue(bdev_get_queue(mdev->bc->md_bdev)); + + /* In case we did not submit a single IO do not wait for + * them to complete. ( Because we would wait forever here. ) + * + * In case we had IOs and they are already complete, there + * is not point in waiting anyways. + * Therefore this if () ... */ + if (atomic_read(&wc.count)) { + wait_for_completion(&wc.io_done); + /* flush bitmap to stable storage */ + if (!test_bit(MD_NO_BARRIER, &mdev->flags)) + blkdev_issue_flush(mdev->bc->md_bdev, NULL); + } + + dec_local(mdev); + + if (wc.error) + drbd_io_error(mdev, TRUE); + kfree(bios); + return; + + free_bios_submit_one_by_one: + /* free everything by calling the endio callback directly. */ + for (i = 0; i < nr_elements && bios[i]; i++) + bio_endio(bios[i], 0); + + kfree(bios); + + submit_one_by_one: + DRBD_WARN("Using the slow drbd_al_to_on_disk_bm()\n"); + + for (i = 0; i < mdev->act_log->nr_elements; i++) { + enr = lc_entry(mdev->act_log, i)->lc_number; + if (enr == LC_FREE) + continue; + /* Really slow: if we have al-extents 16..19 active, + * sector 4 will be written four times! Synchronous! */ + drbd_bm_write_sect(mdev, enr/AL_EXT_PER_BM_SECT ); + } + + lc_unlock(mdev->act_log); + wake_up(&mdev->al_wait); + dec_local(mdev); +} + +/** + * drbd_al_apply_to_bm: Sets the bits in the bitmap that are described + * by the active extents of the AL. + */ +void drbd_al_apply_to_bm(struct drbd_conf *mdev) +{ + unsigned int enr; + unsigned long add = 0; + char ppb[10]; + int i; + + wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); + + for (i = 0; i < mdev->act_log->nr_elements; i++) { + enr = lc_entry(mdev->act_log, i)->lc_number; + if (enr == LC_FREE) + continue; + add += drbd_bm_ALe_set_all(mdev, enr); + } + + lc_unlock(mdev->act_log); + wake_up(&mdev->al_wait); + + INFO("Marked additional %s as out-of-sync based on AL.\n", + ppsize(ppb, Bit2KB(add))); +} + +static inline int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext) +{ + int rv; + + spin_lock_irq(&mdev->al_lock); + rv = (al_ext->refcnt == 0); + if (likely(rv)) lc_del(mdev->act_log, al_ext); + spin_unlock_irq(&mdev->al_lock); + + MTRACE(TraceTypeALExts,TraceLvlMetrics, + if(unlikely(!rv)) + INFO("Waiting for extent in drbd_al_shrink()\n"); + ); + + return rv; +} + +/** + * drbd_al_shrink: Removes all active extents form the AL. (but does not + * write any transactions) + * You need to lock mdev->act_log with lc_try_lock() / lc_unlock() + */ +void drbd_al_shrink(struct drbd_conf *mdev) +{ + struct lc_element *al_ext; + int i; + + D_ASSERT( test_bit(__LC_DIRTY, &mdev->act_log->flags) ); + + for (i = 0; i < mdev->act_log->nr_elements; i++) { + al_ext = lc_entry(mdev->act_log, i); + if (al_ext->lc_number == LC_FREE) + continue; + wait_event(mdev->al_wait, _try_lc_del(mdev, al_ext)); + } + + wake_up(&mdev->al_wait); +} + +STATIC int w_update_odbm(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + struct update_odbm_work *udw = (struct update_odbm_work *)w; + + if (!inc_local(mdev)) { + if (DRBD_ratelimit(5*HZ, 5)) + DRBD_WARN("Can not update on disk bitmap, local IO disabled.\n"); + return 1; + } + + drbd_bm_write_sect(mdev, udw->enr ); + dec_local(mdev); + + kfree(udw); + + if (drbd_bm_total_weight(mdev) <= mdev->rs_failed) { + switch (mdev->state.conn) { + case SyncSource: case SyncTarget: + case PausedSyncS: case PausedSyncT: + drbd_resync_finished(mdev); + default: /* nothing to do */; + } + } + drbd_bcast_sync_progress(mdev); + + return 1; +} + + +/* ATTENTION. The AL's extents are 4MB each, while the extents in the + * resync LRU-cache are 16MB each. + * The caller of this function has to hold an inc_local() reference. + * + * TODO will be obsoleted once we have a caching lru of the on disk bitmap + */ +STATIC void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector, + int count, int success) +{ + struct bm_extent *ext; + struct update_odbm_work *udw; + + unsigned int enr; + + MUST_HOLD(&mdev->al_lock); + D_ASSERT(atomic_read(&mdev->local_cnt)); + + /* I simply assume that a sector/size pair never crosses + * a 16 MB extent border. (Currently this is true...) */ + enr = BM_SECT_TO_EXT(sector); + + ext = (struct bm_extent *) lc_get(mdev->resync, enr); + if (ext) { + if (ext->lce.lc_number == enr) { + if (success) + ext->rs_left -= count; + else + ext->rs_failed += count; + if (ext->rs_left < ext->rs_failed) { + ERR("BAD! sector=%llus enr=%u rs_left=%d " + "rs_failed=%d count=%d\n", + (unsigned long long)sector, + ext->lce.lc_number, ext->rs_left, + ext->rs_failed, count); + dump_stack(); + /* FIXME brrrgs. should never happen! */ + lc_put(mdev->resync, &ext->lce); + drbd_force_state(mdev, NS(conn, Disconnecting)); + return; + } + } else { + /* Normally this element should be in the cache, + * since drbd_rs_begin_io() pulled it already in. + * + * But maybe an application write finished, and we set + * something in outside the resync lru_cache in sync. + */ + int rs_left = drbd_bm_e_weight(mdev, enr); + if (ext->flags != 0) { + DRBD_WARN("changing resync lce: %d[%u;%02lx]" + " -> %d[%u;00]\n", + ext->lce.lc_number, ext->rs_left, + ext->flags, enr, rs_left); + ext->flags = 0; + } + if (ext->rs_failed) { + DRBD_WARN("Kicking resync_lru element enr=%u " + "out with rs_failed=%d\n", + ext->lce.lc_number, ext->rs_failed); + set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags); + } + ext->rs_left = rs_left; + ext->rs_failed = success ? 0 : count; + lc_changed(mdev->resync, &ext->lce); + } + lc_put(mdev->resync, &ext->lce); + /* no race, we are within the al_lock! */ + + if (ext->rs_left == ext->rs_failed) { + ext->rs_failed = 0; + + udw = kmalloc(sizeof(*udw), GFP_ATOMIC); + if (udw) { + udw->enr = ext->lce.lc_number; + udw->w.cb = w_update_odbm; + drbd_queue_work_front(&mdev->data.work, &udw->w); + } else { + DRBD_WARN("Could not kmalloc an udw\n"); + set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags); + } + } + } else { + ERR("lc_get() failed! locked=%d/%d flags=%lu\n", + mdev->resync_locked, + mdev->resync->nr_elements, + mdev->resync->flags); + } +} + +/* clear the bit corresponding to the piece of storage in question: + * size byte of data starting from sector. Only clear a bits of the affected + * one ore more _aligned_ BM_BLOCK_SIZE blocks. + * + * called by worker on SyncTarget and receiver on SyncSource. + * + */ +void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, + const char *file, const unsigned int line) +{ + /* Is called from worker and receiver context _only_ */ + unsigned long sbnr, ebnr, lbnr; + unsigned long count = 0; + sector_t esector, nr_sectors; + int wake_up = 0; + unsigned long flags; + + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + ERR("drbd_set_in_sync: sector=%llus size=%d nonsense!\n", + (unsigned long long)sector, size); + return; + } + nr_sectors = drbd_get_capacity(mdev->this_bdev); + esector = sector + (size>>9) -1; + + ERR_IF(sector >= nr_sectors) return; + ERR_IF(esector >= nr_sectors) esector = (nr_sectors-1); + + lbnr = BM_SECT_TO_BIT(nr_sectors-1); + + /* we clear it (in sync). + * round up start sector, round down end sector. we make sure we only + * clear full, alligned, BM_BLOCK_SIZE (4K) blocks */ + if (unlikely(esector < BM_SECT_PER_BIT-1)) + return; + if (unlikely(esector == (nr_sectors-1))) + ebnr = lbnr; + else + ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1)); + sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1); + + MTRACE(TraceTypeResync, TraceLvlMetrics, + INFO("drbd_set_in_sync: sector=%llus size=%u sbnr=%lu ebnr=%lu\n", + (unsigned long long)sector, size, sbnr, ebnr); + ); + + if (sbnr > ebnr) + return; + + /* + * ok, (capacity & 7) != 0 sometimes, but who cares... + * we count rs_{total,left} in bits, not sectors. + */ + spin_lock_irqsave(&mdev->al_lock, flags); + count = drbd_bm_clear_bits(mdev, sbnr, ebnr); + if (count) { + /* we need the lock for drbd_try_clear_on_disk_bm */ + if (jiffies - mdev->rs_mark_time > HZ*10) { + /* should be roling marks, + * but we estimate only anyways. */ + if ( mdev->rs_mark_left != drbd_bm_total_weight(mdev) && + mdev->state.conn != PausedSyncT && + mdev->state.conn != PausedSyncS ) { + mdev->rs_mark_time = jiffies; + mdev->rs_mark_left = drbd_bm_total_weight(mdev); + } + } + if (inc_local(mdev)) { + drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE); + dec_local(mdev); + } + /* just wake_up unconditional now, various lc_chaged(), + * lc_put() in drbd_try_clear_on_disk_bm(). */ + wake_up = 1; + } + spin_unlock_irqrestore(&mdev->al_lock, flags); + if (wake_up) + wake_up(&mdev->al_wait); +} + +/* + * this is intended to set one request worth of data out of sync. + * affects at least 1 bit, + * and at most 1+DRBD_MAX_SEGMENT_SIZE/BM_BLOCK_SIZE bits. + * + * called by tl_clear and drbd_send_dblock (==drbd_make_request). + * so this can be _any_ process. + */ +void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, + const char *file, const unsigned int line) +{ + unsigned long sbnr, ebnr, lbnr, flags; + sector_t esector, nr_sectors; + unsigned int enr, count; + struct bm_extent* ext; + + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + ERR("sector: %llus, size: %d\n", + (unsigned long long)sector, size); + return; + } + + if (!inc_local(mdev)) + return; /* no disk, no metadata, no bitmap to set bits in */ + + nr_sectors = drbd_get_capacity(mdev->this_bdev); + esector = sector + (size>>9) -1; + + ERR_IF(sector >= nr_sectors) + goto out; + ERR_IF(esector >= nr_sectors) + esector = (nr_sectors-1); + + lbnr = BM_SECT_TO_BIT(nr_sectors-1); + + /* we set it out of sync, + * we do not need to round anything here */ + sbnr = BM_SECT_TO_BIT(sector); + ebnr = BM_SECT_TO_BIT(esector); + + MTRACE(TraceTypeResync, TraceLvlMetrics, + INFO("drbd_set_out_of_sync: sector=%llus size=%u " + "sbnr=%lu ebnr=%lu\n", + (unsigned long long)sector, size, sbnr, ebnr); + ); + + /* ok, (capacity & 7) != 0 sometimes, but who cares... + * we count rs_{total,left} in bits, not sectors. */ + spin_lock_irqsave(&mdev->al_lock, flags); + count = drbd_bm_set_bits(mdev, sbnr, ebnr); + + enr = BM_SECT_TO_EXT(sector); + ext = (struct bm_extent *) lc_find(mdev->resync, enr); + if (ext) + ext->rs_left += count; + spin_unlock_irqrestore(&mdev->al_lock, flags); + +out: + dec_local(mdev); +} + +static inline +struct bm_extent *_bme_get(struct drbd_conf *mdev, unsigned int enr) +{ + struct bm_extent *bm_ext; + int wakeup = 0; + unsigned long rs_flags; + + spin_lock_irq(&mdev->al_lock); + if (mdev->resync_locked > mdev->resync->nr_elements/2) { + spin_unlock_irq(&mdev->al_lock); + return NULL; + } + bm_ext = (struct bm_extent *) lc_get(mdev->resync, enr); + if (bm_ext) { + if (bm_ext->lce.lc_number != enr) { + bm_ext->rs_left = drbd_bm_e_weight(mdev, enr); + bm_ext->rs_failed = 0; + lc_changed(mdev->resync, (struct lc_element *)bm_ext); + wakeup = 1; + } + if (bm_ext->lce.refcnt == 1) + mdev->resync_locked++; + set_bit(BME_NO_WRITES, &bm_ext->flags); + } + rs_flags = mdev->resync->flags; + spin_unlock_irq(&mdev->al_lock); + if (wakeup) + wake_up(&mdev->al_wait); + + if (!bm_ext) { + if (rs_flags & LC_STARVING) + DRBD_WARN("Have to wait for element" + " (resync LRU too small?)\n"); + BUG_ON(rs_flags & LC_DIRTY); + } + + return bm_ext; +} + +static inline int _is_in_al(struct drbd_conf *mdev, unsigned int enr) +{ + struct lc_element *al_ext; + int rv = 0; + + spin_lock_irq(&mdev->al_lock); + if (unlikely(enr == mdev->act_log->new_number)) rv = 1; + else { + al_ext = lc_find(mdev->act_log, enr); + if (al_ext) { + if (al_ext->refcnt) + rv = 1; + } + } + spin_unlock_irq(&mdev->al_lock); + + /* + if (unlikely(rv)) { + INFO("Delaying sync read until app's write is done\n"); + } + */ + return rv; +} + +/** + * drbd_rs_begin_io: Gets an extent in the resync LRU cache and sets it + * to BME_LOCKED. + * + * @sector: The sector number + * + * sleeps on al_wait. + * returns 1 if successful. + * returns 0 if interrupted. + */ +int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector) +{ + unsigned int enr = BM_SECT_TO_EXT(sector); + struct bm_extent *bm_ext; + int i, sig; + + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("drbd_rs_begin_io: sector=%llus (rs_end=%d)\n", + (unsigned long long)sector, enr); + ); + + sig = wait_event_interruptible( mdev->al_wait, + (bm_ext = _bme_get(mdev, enr)) ); + if (sig) + return 0; + + if (test_bit(BME_LOCKED, &bm_ext->flags)) return 1; + + for (i = 0; i < AL_EXT_PER_BM_SECT; i++) { + sig = wait_event_interruptible( mdev->al_wait, + !_is_in_al(mdev, enr*AL_EXT_PER_BM_SECT+i) ); + if (sig) { + spin_lock_irq(&mdev->al_lock); + if ( lc_put(mdev->resync, &bm_ext->lce) == 0 ) { + clear_bit(BME_NO_WRITES, &bm_ext->flags); + mdev->resync_locked--; + wake_up(&mdev->al_wait); + } + spin_unlock_irq(&mdev->al_lock); + return 0; + } + } + + set_bit(BME_LOCKED, &bm_ext->flags); + + return 1; +} + +/** + * drbd_try_rs_begin_io: Gets an extent in the resync LRU cache, sets it + * to BME_NO_WRITES, then tries to set it to BME_LOCKED. + * + * @sector: The sector number + * + * does not sleep. + * returns zero if we could set BME_LOCKED and can proceed, + * -EAGAIN if we need to try again. + */ +int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector) +{ + unsigned int enr = BM_SECT_TO_EXT(sector); + const unsigned int al_enr = enr*AL_EXT_PER_BM_SECT; + struct bm_extent *bm_ext; + int i; + + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("drbd_try_rs_begin_io: sector=%llus\n", + (unsigned long long)sector); + ); + + spin_lock_irq(&mdev->al_lock); + if (mdev->resync_wenr != LC_FREE && mdev->resync_wenr != enr) { + /* in case you have very heavy scattered io, it may + * stall the syncer undefined if we giveup the ref count + * when we try again and requeue. + * + * if we don't give up the refcount, but the next time + * we are scheduled this extent has been "synced" by new + * application writes, we'd miss the lc_put on the + * extent we keept the refcount on. + * so we remembered which extent we had to try agin, and + * if the next requested one is something else, we do + * the lc_put here... + * we also have to wake_up + */ + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("dropping %u, aparently got 'synced' " + "by application io\n", mdev->resync_wenr); + ); + bm_ext = (struct bm_extent *) + lc_find(mdev->resync, mdev->resync_wenr); + if (bm_ext) { + D_ASSERT(!test_bit(BME_LOCKED, &bm_ext->flags)); + D_ASSERT(test_bit(BME_NO_WRITES, &bm_ext->flags)); + clear_bit(BME_NO_WRITES, &bm_ext->flags); + mdev->resync_wenr = LC_FREE; + if (lc_put(mdev->resync, &bm_ext->lce) == 0) + mdev->resync_locked--; + wake_up(&mdev->al_wait); + } else { + ALERT("LOGIC BUG\n"); + } + } + bm_ext = (struct bm_extent *)lc_try_get(mdev->resync, enr); + if (bm_ext) { + if (test_bit(BME_LOCKED, &bm_ext->flags)) + goto proceed; + if (!test_and_set_bit(BME_NO_WRITES, &bm_ext->flags)) { + mdev->resync_locked++; + } else { + /* we did set the BME_NO_WRITES, + * but then could not set BME_LOCKED, + * so we tried again. + * drop the extra reference. */ + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("dropping extra reference on %u\n", enr); + ); + bm_ext->lce.refcnt--; + D_ASSERT(bm_ext->lce.refcnt > 0); + } + goto check_al; + } else { + if (mdev->resync_locked > mdev->resync->nr_elements-3) { + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("resync_locked = %u!\n", mdev->resync_locked); + ); + goto try_again; + } + bm_ext = (struct bm_extent *)lc_get(mdev->resync, enr); + if (!bm_ext) { + const unsigned long rs_flags = mdev->resync->flags; + if (rs_flags & LC_STARVING) + DRBD_WARN("Have to wait for element" + " (resync LRU too small?)\n"); + BUG_ON(rs_flags & LC_DIRTY); + goto try_again; + } + if (bm_ext->lce.lc_number != enr) { + bm_ext->rs_left = drbd_bm_e_weight(mdev, enr); + bm_ext->rs_failed = 0; + lc_changed(mdev->resync, (struct lc_element *)bm_ext); + wake_up(&mdev->al_wait); + D_ASSERT(test_bit(BME_LOCKED, &bm_ext->flags) == 0); + } + set_bit(BME_NO_WRITES, &bm_ext->flags); + D_ASSERT(bm_ext->lce.refcnt == 1); + mdev->resync_locked++; + goto check_al; + } +check_al: + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("checking al for %u\n", enr); + ); + for (i = 0; i < AL_EXT_PER_BM_SECT; i++) { + if (unlikely(al_enr+i == mdev->act_log->new_number)) + goto try_again; + if (lc_is_used(mdev->act_log, al_enr+i)) + goto try_again; + } + set_bit(BME_LOCKED, &bm_ext->flags); +proceed: + mdev->resync_wenr = LC_FREE; + spin_unlock_irq(&mdev->al_lock); + return 0; + +try_again: + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("need to try again for %u\n", enr); + ); + if (bm_ext) + mdev->resync_wenr = enr; + spin_unlock_irq(&mdev->al_lock); + return -EAGAIN; +} + +void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector) +{ + unsigned int enr = BM_SECT_TO_EXT(sector); + struct bm_extent *bm_ext; + unsigned long flags; + + MTRACE(TraceTypeResync, TraceLvlAll, + INFO("drbd_rs_complete_io: sector=%llus (rs_enr=%d)\n", + (long long)sector, enr); + ); + + spin_lock_irqsave(&mdev->al_lock, flags); + bm_ext = (struct bm_extent *) lc_find(mdev->resync, enr); + if (!bm_ext) { + spin_unlock_irqrestore(&mdev->al_lock, flags); + ERR("drbd_rs_complete_io() called, but extent not found\n"); + return; + } + + if (bm_ext->lce.refcnt == 0) { + spin_unlock_irqrestore(&mdev->al_lock, flags); + ERR("drbd_rs_complete_io(,%llu [=%u]) called, " + "but refcnt is 0!?\n", + (unsigned long long)sector, enr); + return; + } + + if ( lc_put(mdev->resync, (struct lc_element *)bm_ext) == 0 ) { + clear_bit(BME_LOCKED, &bm_ext->flags); + clear_bit(BME_NO_WRITES, &bm_ext->flags); + mdev->resync_locked--; + wake_up(&mdev->al_wait); + } + + spin_unlock_irqrestore(&mdev->al_lock, flags); +} + +/** + * drbd_rs_cancel_all: Removes extents from the resync LRU. Even + * if they are BME_LOCKED. + */ +void drbd_rs_cancel_all(struct drbd_conf *mdev) +{ + MTRACE(TraceTypeResync, TraceLvlMetrics, + INFO("drbd_rs_cancel_all\n"); + ); + + spin_lock_irq(&mdev->al_lock); + + if (inc_local_if_state(mdev,Failed)) { /* Makes sure ->resync is there. */ + lc_reset(mdev->resync); + dec_local(mdev); + } + mdev->resync_locked = 0; + mdev->resync_wenr = LC_FREE; + spin_unlock_irq(&mdev->al_lock); + wake_up(&mdev->al_wait); +} + +/** + * drbd_rs_del_all: Gracefully remove all extents from the resync LRU. + * there may be still a reference hold by someone. In that case this function + * returns -EAGAIN. + * In case all elements got removed it returns zero. + */ +int drbd_rs_del_all(struct drbd_conf *mdev) +{ + struct bm_extent *bm_ext; + int i; + + MTRACE(TraceTypeResync, TraceLvlMetrics, + INFO("drbd_rs_del_all\n"); + ); + + spin_lock_irq(&mdev->al_lock); + + if (inc_local_if_state(mdev, Failed)) { + /* ok, ->resync is there. */ + for (i = 0; i < mdev->resync->nr_elements; i++) { + bm_ext = (struct bm_extent *) lc_entry(mdev->resync, i); + if (bm_ext->lce.lc_number == LC_FREE) + continue; + if (bm_ext->lce.lc_number == mdev->resync_wenr) { + INFO("dropping %u in drbd_rs_del_all, aparently" + " got 'synced' by application io\n", + mdev->resync_wenr); + D_ASSERT(!test_bit(BME_LOCKED, &bm_ext->flags)); + D_ASSERT(test_bit(BME_NO_WRITES, &bm_ext->flags)); + clear_bit(BME_NO_WRITES, &bm_ext->flags); + mdev->resync_wenr = LC_FREE; + lc_put(mdev->resync, &bm_ext->lce); + } + if (bm_ext->lce.refcnt != 0) { + INFO("Retrying drbd_rs_del_all() later. " + "refcnt=%d\n", bm_ext->lce.refcnt); + dec_local(mdev); + spin_unlock_irq(&mdev->al_lock); + return -EAGAIN; + } + D_ASSERT(!test_bit(BME_LOCKED, &bm_ext->flags)); + D_ASSERT(!test_bit(BME_NO_WRITES, &bm_ext->flags)); + lc_del(mdev->resync, &bm_ext->lce); + } + D_ASSERT(mdev->resync->used == 0); + dec_local(mdev); + } + spin_unlock_irq(&mdev->al_lock); + + return 0; +} + +/* Record information on a failure to resync the specified blocks + * + * called on SyncTarget when resync write fails or NegRSDReply received + * + */ +void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size) +{ + /* Is called from worker and receiver context _only_ */ + unsigned long sbnr, ebnr, lbnr; + unsigned long count; + sector_t esector, nr_sectors; + int wake_up = 0; + + MTRACE(TraceTypeResync, TraceLvlSummary, + INFO("drbd_rs_failed_io: sector=%llus, size=%u\n", + (unsigned long long)sector, size); + ); + + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + ERR("drbd_rs_failed_io: sector=%llus size=%d nonsense!\n", + (unsigned long long)sector, size); + return; + } + nr_sectors = drbd_get_capacity(mdev->this_bdev); + esector = sector + (size>>9) -1; + + ERR_IF(sector >= nr_sectors) return; + ERR_IF(esector >= nr_sectors) esector = (nr_sectors-1); + + lbnr = BM_SECT_TO_BIT(nr_sectors-1); + + /* + * round up start sector, round down end sector. we make sure we only + * handle full, alligned, BM_BLOCK_SIZE (4K) blocks */ + if (unlikely(esector < BM_SECT_PER_BIT-1)) + return; + if (unlikely(esector == (nr_sectors-1))) + ebnr = lbnr; + else + ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1)); + sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1); + + if (sbnr > ebnr) + return; + + /* + * ok, (capacity & 7) != 0 sometimes, but who cares... + * we count rs_{total,left} in bits, not sectors. + */ + spin_lock_irq(&mdev->al_lock); + count = drbd_bm_count_bits(mdev, sbnr, ebnr); + if (count) { + mdev->rs_failed += count; + + if (inc_local(mdev)) { + drbd_try_clear_on_disk_bm(mdev, sector, count, FALSE); + dec_local(mdev); + } + + /* just wake_up unconditional now, various lc_chaged(), + * lc_put() in drbd_try_clear_on_disk_bm(). */ + wake_up = 1; + } + spin_unlock_irq(&mdev->al_lock); + if (wake_up) + wake_up(&mdev->al_wait); +} --- linux-2.6.27.orig/ubuntu/drbd/Kconfig +++ linux-2.6.27/ubuntu/drbd/Kconfig @@ -0,0 +1,32 @@ +# +# DRBD device driver configuration +# +config BLK_DEV_DRBD + tristate "DRBD Distributed Replicated Block Device support" + select INET + select PROC_FS + select CONNECTOR + select CRYPTO + select CRYPTO_HMAC + ---help--- + DRBD is a block device which is designed to build high availability + clusters. This is done by mirroring a whole block device via (a + dedicated) network. You could see it as a network RAID 1. + + Each minor device has a state, which can be 'primary' or 'secondary'. + On the node with the primary device the application is supposed to + run and to access the device (/dev/drbdX). Every write is sent to the + local 'lower level block device' and via network to the node with the + device in 'secondary' state. + The secondary device simply writes the data to its lower level block + device. Currently no read-balancing via the network is done. + + DRBD can also be used with "shared-disk semantics" (primary-primary), + even though it is a "shared-nothing cluster". You'd need to use a + cluster file system on top of that for cache coherency. + + DRBD management is done through user-space tools. + For automatic failover you need a cluster manager (e.g. heartbeat). + See also: http://www.drbd.org/, http://www.linux-ha.org + + If unsure, say N. --- linux-2.6.27.orig/ubuntu/drbd/lru_cache.h +++ linux-2.6.27/ubuntu/drbd/lru_cache.h @@ -0,0 +1,149 @@ +/* +-*- linux-c -*- + lru_cache.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. + Copyright (C) 2003-2008, Philipp Reisner . + Copyright (C) 2003-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +/* + * The lru_cache describes a big set of objects that are addressed + * by an index number (=lc_number). Only a small fraction of this set + * is present in the cache. + * (You set the size of the cache during lc_alloc) + * Once created, the api consists of + * lc_find(,nr) -- finds the object with the given number, if present + * lc_get(,nr) -- finds the object and increases the usage count + * if not present, actions are taken to make sure that + * the cache is updated, the user is notified of this by a callback. + * Return value is NULL in this case. + * As soon as the user informs the cache that it has been updated, + * the next lc_get on that very object number will be successfull. + * lc_put(,lc_element*) + * -- decreases the usage count of this object, and returns the new value. + * + * NOTE: It is the USERS responsibility + * to make sure that calls do not happen concurrently. + */ + +#ifndef LRU_CACHE_H +#define LRU_CACHE_H + +#include +#ifndef HLIST_HEAD_INIT +# include "hlist.h" +#endif + +#include + +/* FIXME + * I want these structs opaque outside of lru_cache.c + */ + +struct lc_element { + struct hlist_node colision; + struct list_head list; /* LRU list or free list */ + unsigned int refcnt; + unsigned int lc_number; +}; + +struct lru_cache { + struct list_head lru; + struct list_head free; + struct list_head in_use; + size_t element_size; + unsigned int nr_elements; + unsigned int new_number; + + /* here may or may not be a pad... */ + + unsigned int used; + unsigned long flags; + unsigned long hits, misses, starving, dirty, changed; + struct lc_element *changing_element; /* just for paranoia */ + + void *lc_private; + const char *name; + + struct hlist_head slot[0]; + /* hash colision chains here, then element storage. */ +}; + + +/* flag-bits for lru_cache */ +enum { + __LC_PARANOIA, + __LC_DIRTY, + __LC_STARVING, +}; +#define LC_PARANOIA (1<<__LC_PARANOIA) +#define LC_DIRTY (1<<__LC_DIRTY) +#define LC_STARVING (1<<__LC_STARVING) + +extern struct lru_cache *lc_alloc(const char *name, unsigned int e_count, + size_t e_size, void *private_p); +extern void lc_reset(struct lru_cache *lc); +extern void lc_free(struct lru_cache *lc); +extern void lc_set(struct lru_cache *lc, unsigned int enr, int index); +extern void lc_del(struct lru_cache *lc, struct lc_element *element); + +extern struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr); +extern struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr); +extern struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr); +extern unsigned int lc_put(struct lru_cache *lc, struct lc_element *e); +extern void lc_changed(struct lru_cache *lc, struct lc_element *e); + +struct seq_file; +extern size_t lc_printf_stats(struct seq_file *seq, struct lru_cache *lc); + +void lc_dump(struct lru_cache *lc, struct seq_file *seq, char *utext, + void (*detail) (struct seq_file *, struct lc_element *) ); + +/* This can be used to stop lc_get from changing the set of active elements. + * Note that the reference counts and order on the lru list may still change. + * returns true if we aquired the lock. + */ +static inline int lc_try_lock(struct lru_cache *lc) +{ + return !test_and_set_bit(__LC_DIRTY, &lc->flags); +} + +static inline void lc_unlock(struct lru_cache *lc) +{ + clear_bit(__LC_DIRTY, &lc->flags); + smp_mb__after_clear_bit(); +} + +static inline int lc_is_used(struct lru_cache *lc, unsigned int enr) +{ + struct lc_element *e = lc_find(lc, enr); + return (e && e->refcnt); +} + +#define LC_FREE (-1U) + +#define lc_e_base(lc) ((char *) ( (lc)->slot + (lc)->nr_elements ) ) +#define lc_entry(lc, i) ((struct lc_element *) \ + (lc_e_base(lc) + (i)*(lc)->element_size)) +#define lc_index_of(lc, e) (((char *)(e) - lc_e_base(lc))/(lc)->element_size) + +#endif --- linux-2.6.27.orig/ubuntu/drbd/drbd_proc.c +++ linux-2.6.27/ubuntu/drbd/drbd_proc.c @@ -0,0 +1,257 @@ +/* +-*- linux-c -*- + drbd_proc.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 1999-2008, Philipp Reisner . + Copyright (C) 2002-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "drbd_int.h" +#include "lru_cache.h" /* for lc_sprintf_stats */ + +int drbd_proc_open(struct inode *inode, struct file *file); + + +struct proc_dir_entry *drbd_proc; +struct file_operations drbd_proc_fops = { + .owner = THIS_MODULE, + .open = drbd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + +/*lge + * progress bars shamelessly adapted from driver/md/md.c + * output looks like + * [=====>..............] 33.5% (23456/123456) + * finish: 2:20:20 speed: 6,345 (6,456) K/sec + */ +STATIC void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) +{ + unsigned long db, dt, dbdt, rt, rs_left; + unsigned int res; + int i, x, y; + + drbd_get_syncer_progress(mdev, &rs_left, &res); + + x = res/50; + y = 20-x; + seq_printf(seq, "\t["); + for (i = 1; i < x; i++) + seq_printf(seq, "="); + seq_printf(seq, ">"); + for (i = 0; i < y; i++) + seq_printf(seq, "."); + seq_printf(seq, "] "); + + seq_printf(seq, "sync'ed:%3u.%u%% ", res / 10, res % 10); + /* if more than 1 GB display in MB */ + if (mdev->rs_total > 0x100000L) + seq_printf(seq, "(%lu/%lu)M\n\t", + (unsigned long) Bit2KB(rs_left) >> 10, + (unsigned long) Bit2KB(mdev->rs_total) >> 10 ); + else + seq_printf(seq, "(%lu/%lu)K\n\t", + (unsigned long) Bit2KB(rs_left), + (unsigned long) Bit2KB(mdev->rs_total) ); + + /* see drivers/md/md.c + * We do not want to overflow, so the order of operands and + * the * 100 / 100 trick are important. We do a +1 to be + * safe against division by zero. We only estimate anyway. + * + * dt: time from mark until now + * db: blocks written from mark until now + * rt: remaining time + */ + dt = (jiffies - mdev->rs_mark_time) / HZ; + + if (dt > 20) { + /* if we made no update to rs_mark_time for too long, + * we are stalled. show that. */ + seq_printf(seq, "stalled\n"); + return; + } + + if (!dt) + dt++; + db = mdev->rs_mark_left - rs_left; + rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */ + + seq_printf(seq, "finish: %lu:%02lu:%02lu", + rt / 3600, (rt % 3600) / 60, rt % 60); + + /* current speed average over (SYNC_MARKS * SYNC_MARK_STEP) jiffies */ + dbdt = Bit2KB(db/dt); + if (dbdt > 1000) + seq_printf(seq, " speed: %ld,%03ld", + dbdt/1000, dbdt % 1000); + else + seq_printf(seq, " speed: %ld", dbdt); + + /* mean speed since syncer started + * we do account for PausedSync periods */ + dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ; + if (dt <= 0) + dt = 1; + db = mdev->rs_total - rs_left; + dbdt = Bit2KB(db/dt); + if (dbdt > 1000) + seq_printf(seq, " (%ld,%03ld)", + dbdt/1000, dbdt % 1000); + else + seq_printf(seq, " (%ld)", dbdt); + + seq_printf(seq, " K/sec\n"); +} + +#ifdef ENABLE_DYNAMIC_TRACE +STATIC void resync_dump_detail(struct seq_file *seq, struct lc_element *e) +{ + struct bm_extent *bme = (struct bm_extent *)e; + + seq_printf(seq, "%5d %s %s\n", bme->rs_left, + bme->flags & BME_NO_WRITES ? "NO_WRITES" : "---------", + bme->flags & BME_LOCKED ? "LOCKED" : "------" + ); +} +#endif + +STATIC int drbd_seq_show(struct seq_file *seq, void *v) +{ + int i, hole = 0; + const char *sn; + struct drbd_conf *mdev; + + seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n", + API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag()); + + /* + cs .. connection state + st .. node state (local/remote) + ld .. local data consistentency + ns .. network send + nr .. network receive + dw .. disk write + dr .. disk read + pe .. pending (waiting for ack) + ua .. unack'd (still need to send ack) + al .. access log write count + */ + + for (i = 0; i < minor_count; i++) { + mdev = minor_to_mdev(i); + if (!mdev) { + hole = 1; + continue; + } + if (hole) { + hole = 0; + seq_printf( seq, "\n"); + } + + sn = conns_to_name(mdev->state.conn); + + if ( mdev->state.conn == StandAlone && + mdev->state.disk == Diskless) { + seq_printf( seq, "%2d: cs:Unconfigured\n", i); + } else { + seq_printf( seq, + "%2d: cs:%s st:%s/%s ds:%s/%s %c %c%c%c%c\n" + " ns:%u nr:%u dw:%u dr:%u al:%u bm:%u " + "lo:%d pe:%d ua:%d ap:%d", + i, sn, + roles_to_name(mdev->state.role), + roles_to_name(mdev->state.peer), + disks_to_name(mdev->state.disk), + disks_to_name(mdev->state.pdsk), + (mdev->net_conf == NULL ? ' ' : + (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')), + mdev->state.susp ? 's' : 'r', + mdev->state.aftr_isp ? 'a' : '-', + mdev->state.peer_isp ? 'p' : '-', + mdev->state.user_isp ? 'u' : '-', + mdev->send_cnt/2, + mdev->recv_cnt/2, + mdev->writ_cnt/2, + mdev->read_cnt/2, + mdev->al_writ_cnt, + mdev->bm_writ_cnt, + atomic_read(&mdev->local_cnt), + atomic_read(&mdev->ap_pending_cnt) + + atomic_read(&mdev->rs_pending_cnt), + atomic_read(&mdev->unacked_cnt), + atomic_read(&mdev->ap_bio_cnt) + ); + seq_printf(seq, " oos:%lu\n", + drbd_bm_total_weight(mdev) << (BM_BLOCK_SIZE_B - 10)); + } + if ( mdev->state.conn == SyncSource || + mdev->state.conn == SyncTarget ) + drbd_syncer_progress(mdev, seq); + + if ( mdev->state.conn == VerifyS || + mdev->state.conn == VerifyT ) { + seq_printf(seq,"\t%3d%% %lu/%lu\n", + (int)((mdev->rs_total-mdev->ov_left) / + (mdev->rs_total/100+1)), + mdev->rs_total - mdev->ov_left, + mdev->rs_total); + } + +#ifdef ENABLE_DYNAMIC_TRACE + if (proc_details >= 1 && inc_local_if_state(mdev, Failed)) { + lc_printf_stats(seq, mdev->resync); + lc_printf_stats(seq, mdev->act_log); + dec_local(mdev); + } + + if (proc_details >= 2) { + if (mdev->resync) { + lc_dump(mdev->resync, seq, "rs_left", + resync_dump_detail); + } + } +#endif + } + + return 0; +} + +int drbd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, drbd_seq_show, PDE(inode)->data); +} + +/* PROC FS stuff end */ --- linux-2.6.27.orig/ubuntu/drbd/drbd_int.h +++ linux-2.6.27/ubuntu/drbd/drbd_int.h @@ -0,0 +1,2130 @@ +/* + drbd_int.h + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 1999-2008, Philipp Reisner . + Copyright (C) 2002-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef _DRBD_INT_H +#define _DRBD_INT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lru_cache.h" + +#ifdef __CHECKER__ +# define __protected_by(x) __attribute__((require_context(x,1,999,"rdwr"))) +# define __protected_read_by(x) __attribute__((require_context(x,1,999,"read"))) +# define __protected_write_by(x) __attribute__((require_context(x,1,999,"write"))) +# define __must_hold(x) __attribute__((context(x,1,1), require_context(x,1,999,"call"))) +#else +# define __protected_by(x) +# define __protected_read_by(x) +# define __protected_write_by(x) +# define __must_hold(x) +#endif + +#define __no_warn(lock, stmt) do { __acquire(lock); stmt; __release(lock); } while (0) + +/* Compatibility for older kernels */ +#ifndef __acquires +# ifdef __CHECKER__ +# define __acquires(x) __attribute__((context(x,0,1))) +# define __releases(x) __attribute__((context(x,1,0))) +# define __acquire(x) __context__(x,1) +# define __release(x) __context__(x,-1) +# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) +# else +# define __acquires(x) +# define __releases(x) +# define __acquire(x) (void)0 +# define __release(x) (void)0 +# define __cond_lock(x,c) (c) +# endif +#endif + +/* module parameter, defined in drbd_main.c */ +extern int minor_count; +extern int allow_oos; + +#ifdef DRBD_ENABLE_FAULTS +extern int enable_faults; +extern int fault_rate; +extern int fault_devs; +#endif + +extern char usermode_helper[]; + +#include +#ifndef DRBD_MAJOR +# define DRBD_MAJOR 147 +#endif + +#include +#include + +// XXX do we need this? +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* I don't remember why XCPU ... + * This is used to wake the asender, + * and to interrupt sending the sending task + * on disconnect. + */ +#define DRBD_SIG SIGXCPU + +/* This is used to stop/restart our threads. + * Cannot use SIGTERM nor SIGKILL, since these + * are sent out by init on runlevel changes + * I choose SIGHUP for now. + * + * FIXME btw, we should register some reboot notifier. + */ +#define DRBD_SIGKILL SIGHUP + +/* All EEs on the free list should have ID_VACANT (== 0) + * freshly allocated EEs get !ID_VACANT (== 1) + * so if it says "cannot dereference null pointer at adress 0x00000001", + * it is most likely one of these :( */ + +#define ID_IN_SYNC (4711ULL) +#define ID_OUT_OF_SYNC (4712ULL) + +#define ID_SYNCER (-1ULL) +#define ID_VACANT 0 +#define is_syncer_block_id(id) ((id) == ID_SYNCER) + +struct drbd_conf; + +#ifdef DBG_ALL_SYMBOLS +# define STATIC +#else +# define STATIC static +#endif + +#ifdef PARANOIA +# define PARANOIA_BUG_ON(x) BUG_ON(x) +#else +# define PARANOIA_BUG_ON(x) +#endif + +/* + * Some Message Macros + *************************/ + +/* handy macro: DUMPP(somepointer) */ +#define DUMPP(A) ERR( #A " = %p in %s:%d\n", (A), __FILE__, __LINE__); +#define DUMPLU(A) ERR( #A " = %lu in %s:%d\n", (unsigned long)(A), __FILE__, __LINE__); +#define DUMPLLU(A) ERR( #A " = %llu in %s:%d\n", (unsigned long long)(A), __FILE__, __LINE__); +#define DUMPLX(A) ERR( #A " = %lx in %s:%d\n", (A), __FILE__, __LINE__); +#define DUMPI(A) ERR( #A " = %d in %s:%d\n", (int)(A), __FILE__, __LINE__); + +#define DUMPST(A) DUMPLLU((unsigned long long)(A)) + +#if 0 +#define D_DUMPP(A) DUMPP(A) +#define D_DUMPLU(A) DUMPLU(A) +#define D_DUMPLLU(A) DUMPLLU(A) +#define D_DUMPLX(A) DUMPLX(A) +#define D_DUMPI(A) DUMPI(A) +#else +#define D_DUMPP(A) +#define D_DUMPLU(A) +#define D_DUMPLLU(A) +#define D_DUMPLX(A) +#define D_DUMPI(A) +#endif + +/* Info: do not remove the spaces around the "," before ## + * Otherwise this is not portable from gcc-2.95 to gcc-3.3 */ +#define PRINTK(level, fmt, args...) \ + printk(level "drbd%d: " fmt, \ + mdev->minor , ##args) + +#define ALERT(fmt, args...) PRINTK(KERN_ALERT, fmt , ##args) +#define ERR(fmt, args...) PRINTK(KERN_ERR, fmt , ##args) +#define DRBD_WARN(fmt, args...) PRINTK(KERN_WARNING, fmt , ##args) +#define INFO(fmt, args...) PRINTK(KERN_INFO, fmt , ##args) +#define DBG(fmt, args...) PRINTK(KERN_DEBUG, fmt , ##args) + +/* see kernel/printk.c:printk_ratelimit + * macro, so it is easy do have independend rate limits at different locations + * "initializer element not constant ..." with kernel 2.4 :( + * so I initialize toks to something large + */ +#define DRBD_ratelimit(ratelimit_jiffies, ratelimit_burst) \ +({ \ + int __ret; \ + static unsigned long toks = 0x80000000UL; \ + static unsigned long last_msg; \ + static int missed; \ + unsigned long now = jiffies; \ + toks += now - last_msg; \ + last_msg = now; \ + if (toks > (ratelimit_burst * ratelimit_jiffies)) \ + toks = ratelimit_burst * ratelimit_jiffies; \ + if (toks >= ratelimit_jiffies) { \ + int lost = missed; \ + missed = 0; \ + toks -= ratelimit_jiffies; \ + if (lost) \ + DRBD_WARN("%d messages suppressed in %s:%d.\n", \ + lost , __FILE__ , __LINE__ ); \ + __ret = 1; \ + } else { \ + missed++; \ + __ret = 0; \ + } \ + __ret; \ +}) + + +#ifdef DBG_ASSERTS +extern void drbd_assert_breakpoint(struct drbd_conf *, char *, char *, int ); +# define D_ASSERT(exp) if (!(exp)) \ + drbd_assert_breakpoint(mdev, #exp, __FILE__, __LINE__) +#else +# define D_ASSERT(exp) if (!(exp)) \ + ERR("ASSERT( " #exp " ) in %s:%d\n", __FILE__, __LINE__) +#endif +#define ERR_IF(exp) if (({ \ + int _b = (exp)!=0; \ + if (_b) ERR("%s: (%s) in %s:%d\n", \ + __func__, #exp, __FILE__,__LINE__); \ + _b; \ + })) + +/* Defines to control fault insertion */ +enum { + DRBD_FAULT_MD_WR = 0, /* meta data write */ + DRBD_FAULT_MD_RD, /* read */ + DRBD_FAULT_RS_WR, /* resync */ + DRBD_FAULT_RS_RD, + DRBD_FAULT_DT_WR, /* data */ + DRBD_FAULT_DT_RD, + DRBD_FAULT_DT_RA, /* data read ahead */ + + DRBD_FAULT_MAX, +}; + +#ifdef DRBD_ENABLE_FAULTS +extern unsigned int +_drbd_insert_fault(struct drbd_conf *mdev, unsigned int type); +static inline int +drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) { + return (fault_rate && + (enable_faults & (1< +/* integer division, round _UP_ to the next integer */ +#define div_ceil(A, B) ( (A)/(B) + ((A)%(B) ? 1 : 0) ) +/* usual integer division */ +#define div_floor(A, B) ( (A)/(B) ) + +/* + * Compatibility Section + *************************/ + +#define LOCK_SIGMASK(task, flags) spin_lock_irqsave(&task->sighand->siglock, flags) +#define UNLOCK_SIGMASK(task, flags) spin_unlock_irqrestore(&task->sighand->siglock, flags) +#define RECALC_SIGPENDING() recalc_sigpending(); + +#if defined(DBG_SPINLOCKS) && defined(__SMP__) +# define MUST_HOLD(lock) if (!spin_is_locked(lock)) { ERR("Not holding lock! in %s\n", __FUNCTION__ ); } +#else +# define MUST_HOLD(lock) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8) +# define HAVE_KERNEL_SENDMSG 1 +#else +# define HAVE_KERNEL_SENDMSG 0 +#endif + + +/* + * our structs + *************************/ + +#define SET_MDEV_MAGIC(x) \ + ({ typecheck(struct drbd_conf*, x); \ + (x)->magic = (long)(x) ^ DRBD_MAGIC; }) +#define IS_VALID_MDEV(x) \ + ( typecheck(struct drbd_conf*, x) && \ + ((x) ? (((x)->magic ^ DRBD_MAGIC) == (long)(x)):0)) + +/* drbd_meta-data.c (still in drbd_main.c) */ +/* 4th incarnation of the disk layout. */ +#define DRBD_MD_MAGIC (DRBD_MAGIC+4) + +extern struct drbd_conf **minor_table; + +/*** + * on the wire + *********************************************************************/ + +enum Drbd_Packet_Cmd { + Data, + DataReply, /* Response to DataRequest */ + RSDataReply, /* Response to RSDataRequest */ + Barrier, + ReportBitMap, + BecomeSyncTarget, + BecomeSyncSource, + UnplugRemote, /* Used at various times to hint the peer */ + DataRequest, /* Used to ask for a data block */ + RSDataRequest, /* Used to ask for a data block for resync */ + SyncParam, + ReportProtocol, + ReportUUIDs, + ReportSizes, + ReportState, + ReportSyncUUID, + AuthChallenge, + AuthResponse, + StateChgRequest, + + FIRST_ASENDER_CMD, + Ping = FIRST_ASENDER_CMD, + PingAck, + RecvAck, /* Used in protocol B */ + WriteAck, /* Used in protocol C */ + RSWriteAck, /* Is a WriteAck, additionally call set_in_sync(). */ + DiscardAck, /* Used in proto C, two-primaries conflict detection */ + NegAck, /* Sent if local disk is unusable */ + NegDReply, /* Local disk is broken... */ + NegRSDReply, /* Local disk is broken... */ + BarrierAck, + StateChgReply, + LAST_ASENDER_CMD = StateChgReply, + + OVRequest, + OVReply, + OVResult, // Exception to the FIRST/LAST ASENDER_CMD + + MAX_CMD, + MayIgnore = 0x100, /* Flag to test if (cmd > MayIgnore) ... */ + MAX_OPT_CMD, + + /* FIXME + * to get a more useful error message with drbd-8 <-> drbd 0.7.x, + * these could be reimplemented as special case of HandShake. */ + HandShakeM = 0xfff1, /* First Packet on the MetaSock */ + HandShakeS = 0xfff2, /* First Packet on the Socket */ + + HandShake = 0xfffe /* FIXED for the next century! */ +}; + +static inline const char *cmdname(enum Drbd_Packet_Cmd cmd) +{ + /* THINK may need to become several global tables + * when we want to support more than + * one PRO_VERSION */ + static const char *cmdnames[] = { + [Data] = "Data", + [DataReply] = "DataReply", + [RSDataReply] = "RSDataReply", + [Barrier] = "Barrier", + [ReportBitMap] = "ReportBitMap", + [BecomeSyncTarget] = "BecomeSyncTarget", + [BecomeSyncSource] = "BecomeSyncSource", + [UnplugRemote] = "UnplugRemote", + [DataRequest] = "DataRequest", + [RSDataRequest] = "RSDataRequest", + [SyncParam] = "SyncParam", + [ReportProtocol] = "ReportProtocol", + [ReportUUIDs] = "ReportUUIDs", + [ReportSizes] = "ReportSizes", + [ReportState] = "ReportState", + [ReportSyncUUID] = "ReportSyncUUID", + [AuthChallenge] = "AuthChallenge", + [AuthResponse] = "AuthResponse", + [Ping] = "Ping", + [PingAck] = "PingAck", + [RecvAck] = "RecvAck", + [WriteAck] = "WriteAck", + [RSWriteAck] = "RSWriteAck", + [DiscardAck] = "DiscardAck", + [NegAck] = "NegAck", + [NegDReply] = "NegDReply", + [NegRSDReply] = "NegRSDReply", + [BarrierAck] = "BarrierAck", + [StateChgRequest] = "StateChgRequest", + [StateChgReply] = "StateChgReply", + [OVRequest] = "OVRequest", + [OVReply] = "OVReply", + [OVResult] = "OVResult", + }; + + if (Data > cmd || cmd >= MAX_CMD) { + switch (cmd) { + case HandShakeM: + return "HandShakeM"; + break; + case HandShakeS: + return "HandShakeS"; + break; + case HandShake: + return "HandShake"; + break; + default: + return "Unknown"; + break; + } + } + return cmdnames[cmd]; +} + + +/* This is the layout for a packet on the wire. + * The byteorder is the network byte order. + * (except block_id and barrier fields. + * these are pointers to local structs + * and have no relevance for the partner, + * which just echoes them as received.) + * + * NOTE that the payload starts at a long aligned offset, + * regardless of 32 or 64 bit arch! + */ +struct Drbd_Header { + u32 magic; + u16 command; + u16 length; /* bytes of data after this header */ + char payload[0]; +} __attribute((packed)); +/* 8 bytes. packet FIXED for the next century! */ + +/* + * short commands, packets without payload, plain Drbd_Header: + * Ping + * PingAck + * BecomeSyncTarget + * BecomeSyncSource + * UnplugRemote + */ + +/* + * commands with out-of-struct payload: + * ReportBitMap (no additional fields) + * Data, DataReply (see Drbd_Data_Packet) + */ + +#define DP_HARDBARRIER 1 +#define DP_RW_SYNC 2 +#define DP_MAY_SET_IN_SYNC 4 + +struct Drbd_Data_Packet { + struct Drbd_Header head; + u64 sector; /* 64 bits sector number */ + u64 block_id; /* to identify the request in protocol B&C */ + u32 seq_num; + u32 dp_flags; +} __attribute((packed)); + +/* + * commands which share a struct: + * Drbd_BlockAck_Packet: + * RecvAck (proto B), WriteAck (proto C), + * DiscardAck (proto C, two-primaries conflict detection) + * Drbd_BlockRequest_Packet: + * DataRequest, RSDataRequest + */ +struct Drbd_BlockAck_Packet { + struct Drbd_Header head; + u64 sector; + u64 block_id; + u32 blksize; + u32 seq_num; +} __attribute((packed)); + + +struct Drbd_BlockRequest_Packet { + struct Drbd_Header head; + u64 sector; + u64 block_id; + u32 blksize; + u32 pad; /* to multiple of 8 Byte */ +} __attribute((packed)); + +/* + * commands with their own struct for additional fields: + * HandShake + * Barrier + * BarrierAck + * SyncParam + * ReportParams + */ + +struct Drbd_HandShake_Packet { + struct Drbd_Header head; /* 8 bytes */ + u32 protocol_min; + u32 feature_flags; + u32 protocol_max; + + /* should be more than enough for future enhancements + * for now, feature_flags and the reserverd array shall be zero. + */ + + u32 _pad; + u64 reserverd[7]; +} __attribute((packed)); +/* 80 bytes, FIXED for the next century */ + +struct Drbd_Barrier_Packet { + struct Drbd_Header head; + u32 barrier; /* barrier number _handle_ only */ + u32 pad; /* to multiple of 8 Byte */ +} __attribute((packed)); + +struct Drbd_BarrierAck_Packet { + struct Drbd_Header head; + u32 barrier; + u32 set_size; +} __attribute((packed)); + +struct Drbd_SyncParam_Packet { + struct Drbd_Header head; + u32 rate; + + /* Since protocol version 88 and higher. */ + char online_verify_alg[0]; +} __attribute((packed)); + +struct Drbd_Protocol_Packet { + struct Drbd_Header head; + u32 protocol; + u32 after_sb_0p; + u32 after_sb_1p; + u32 after_sb_2p; + u32 want_lose; + u32 two_primaries; + + /* Since protocol version 87 and higher. */ + char integrity_alg[0]; + +} __attribute((packed)); + +struct Drbd_GenCnt_Packet { + struct Drbd_Header head; + u64 uuid[EXT_UUID_SIZE]; +} __attribute((packed)); + +struct Drbd_SyncUUID_Packet { + struct Drbd_Header head; + u64 uuid; +} __attribute((packed)); + +struct Drbd_Sizes_Packet { + struct Drbd_Header head; + u64 d_size; /* size of disk */ + u64 u_size; /* user requested size */ + u64 c_size; /* current exported size */ + u32 max_segment_size; /* Maximal size of a BIO */ + u32 queue_order_type; +} __attribute((packed)); + +struct Drbd_State_Packet { + struct Drbd_Header head; + u32 state; +} __attribute((packed)); + +struct Drbd_Req_State_Packet { + struct Drbd_Header head; + u32 mask; + u32 val; +} __attribute((packed)); + +struct Drbd_RqS_Reply_Packet { + struct Drbd_Header head; + u32 retcode; +} __attribute((packed)); + +struct Drbd06_Parameter_P { + u64 size; + u32 state; + u32 blksize; + u32 protocol; + u32 version; + u32 gen_cnt[5]; + u32 bit_map_gen[5]; +} __attribute((packed)); + +struct Drbd_Discard_Packet { + struct Drbd_Header head; + u64 block_id; + u32 seq_num; + u32 pad; +} __attribute((packed)); + +union Drbd_Polymorph_Packet { + struct Drbd_Header head; + struct Drbd_HandShake_Packet HandShake; + struct Drbd_Data_Packet Data; + struct Drbd_BlockAck_Packet BlockAck; + struct Drbd_Barrier_Packet Barrier; + struct Drbd_BarrierAck_Packet BarrierAck; + struct Drbd_SyncParam_Packet SyncParam; + struct Drbd_Protocol_Packet Protocol; + struct Drbd_Sizes_Packet Sizes; + struct Drbd_GenCnt_Packet GenCnt; + struct Drbd_State_Packet State; + struct Drbd_Req_State_Packet ReqState; + struct Drbd_RqS_Reply_Packet RqSReply; + struct Drbd_BlockRequest_Packet BlockRequest; +} __attribute((packed)); + +/**********************************************************************/ +enum Drbd_thread_state { + None, + Running, + Exiting, + Restarting +}; + +struct Drbd_thread { + spinlock_t t_lock; + struct task_struct *task; + struct completion startstop; + enum Drbd_thread_state t_state; + int (*function) (struct Drbd_thread *); + struct drbd_conf *mdev; + struct mutex task_mutex; +}; + +static inline enum Drbd_thread_state get_t_state(struct Drbd_thread *thi) +{ + /* THINK testing the t_state seems to be uncritical in all cases + * (but thread_{start,stop}), so we can read it *without* the lock. + * --lge */ + + smp_rmb(); + return thi->t_state; +} + + +/* + * Having this as the first member of a struct provides sort of "inheritance". + * "derived" structs can be "drbd_queue_work()"ed. + * The callback should know and cast back to the descendant struct. + * drbd_request and Tl_epoch_entry are descendants of drbd_work. + */ +struct drbd_work; +typedef int (*drbd_work_cb)(struct drbd_conf *, struct drbd_work *, int cancel); +struct drbd_work { + struct list_head list; + drbd_work_cb cb; +}; + +struct drbd_barrier; +struct drbd_request { + struct drbd_work w; + struct drbd_conf *mdev; + struct bio *private_bio; + struct hlist_node colision; + sector_t sector; + unsigned int size; + unsigned int epoch; /* barrier_nr */ + + /* barrier_nr: used to check on "completion" whether this req was in + * the current epoch, and we therefore have to close it, + * starting a new epoch... + */ + + /* up to here, the struct layout is identical to Tl_epoch_entry; + * we might be able to use that to our advantage... */ + + struct list_head tl_requests; /* ring list in the transfer log */ + struct bio *master_bio; /* master bio pointer */ + unsigned long rq_state; /* see comments above _req_mod() */ + int seq_num; + unsigned long start_time; +}; + +struct drbd_barrier { + struct drbd_work w; + struct list_head requests; /* requests before */ + struct drbd_barrier *next; /* pointer to the next barrier */ + unsigned int br_number; /* the barriers identifier. */ + int n_req; /* number of requests attached before this barrier */ +}; + +struct drbd_request; + +/* These Tl_epoch_entries may be in one of 6 lists: + active_ee .. data packet being written + sync_ee .. syncer block being written + done_ee .. block written, need to send WriteAck + read_ee .. [RS]DataRequest being read +*/ + +struct Tl_epoch_entry { + struct drbd_work w; + struct drbd_conf *mdev; + struct bio *private_bio; + struct hlist_node colision; + sector_t sector; + unsigned int size; + unsigned int barrier_nr; + + /* up to here, the struct layout is identical to drbd_request; + * we might be able to use that to our advantage... */ + + unsigned int barrier_nr2; + /* If we issue the bio with BIO_RW_BARRIER we have to + send a barrier ACK before we send the ACK to this + write. We store the barrier number in here. + In case the barrier after this write has been coalesced + as well, we set it's barrier_nr into barrier_nr2 */ + + unsigned int flags; + u64 block_id; +}; + +struct digest_info { + int digest_size; + void *digest; +}; + +/* ee flag bits */ +enum { + __EE_CALL_AL_COMPLETE_IO, + __EE_CONFLICT_PENDING, + __EE_MAY_SET_IN_SYNC, +}; +#define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO) +#define EE_CONFLICT_PENDING (1<<__EE_CONFLICT_PENDING) +#define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC) + +/* global flag bits */ +enum { + CREATE_BARRIER, /* next Data is preceeded by a Barrier */ + SIGNAL_ASENDER, /* whether asender wants to be interrupted */ + SEND_PING, /* whether asender should send a ping asap */ + WRITE_ACK_PENDING, /* so BarrierAck won't overtake WriteAck */ + WORK_PENDING, /* completion flag for drbd_disconnect */ + STOP_SYNC_TIMER, /* tell timer to cancel itself */ + UNPLUG_QUEUED, /* only relevant with kernel 2.4 */ + UNPLUG_REMOTE, /* sending a "UnplugRemote" could help */ + MD_DIRTY, /* current uuids and flags not yet on disk */ + DISCARD_CONCURRENT, /* Set on one node, cleared on the peer! */ + USE_DEGR_WFC_T, /* degr-wfc-timeout instead of wfc-timeout. */ + CLUSTER_ST_CHANGE, /* Cluster wide state change going on... */ + CL_ST_CHG_SUCCESS, + CL_ST_CHG_FAIL, + CRASHED_PRIMARY, /* This node was a crashed primary. + * Gets cleared when the state.conn + * goes into Connected state. */ + WRITE_BM_AFTER_RESYNC, /* A kmalloc() during resync failed */ + NO_BARRIER_SUPP, /* underlying block device doesn't implement barriers */ + CONSIDER_RESYNC, + + LL_DEV_NO_FLUSH, /* blkdev_issue_flush does not work, + so don't even try */ + MD_NO_BARRIER, /* meta data device does not support barriers, + so don't even try */ + BITMAP_IO, /* Let user IO drain */ + BITMAP_IO_QUEUED, /* Started bitmap IO */ +}; + +struct drbd_bitmap; /* opaque for drbd_conf */ + +/* TODO sort members for performance + * MAYBE group them further */ + +/* THINK maybe we actually want to use the default "event/%s" worker threads + * or similar in linux 2.6, which uses per cpu data and threads. + * + * To be general, this might need a spin_lock member. + * For now, please use the mdev->req_lock to protect list_head, + * see drbd_queue_work below. + */ +struct drbd_work_queue { + struct list_head q; + struct semaphore s; /* producers up it, worker down()s it */ + spinlock_t q_lock; /* to protect the list. */ +}; + +/* If Philipp agrees, we remove the "mutex", and make_request will only + * (throttle on "queue full" condition and) queue it to the worker thread... + * which then is free to do whatever is needed, and has exclusive send access + * to the data socket ... + */ +struct drbd_socket { + struct drbd_work_queue work; + struct semaphore mutex; + struct socket *socket; + /* this way we get our + * send/receive buffers off the stack */ + union Drbd_Polymorph_Packet sbuf; + union Drbd_Polymorph_Packet rbuf; +}; + +struct drbd_md { + u64 md_offset; /* sector offset to 'super' block */ + + u64 la_size_sect; /* last agreed size, unit sectors */ + u64 uuid[UUID_SIZE]; + u64 device_uuid; + u32 flags; + u32 md_size_sect; + + s32 al_offset; /* signed relative sector offset to al area */ + s32 bm_offset; /* signed relative sector offset to bitmap */ + + /* u32 al_nr_extents; important for restoring the AL + * is stored into sync_conf.al_extents, which in turn + * gets applied to act_log->nr_elements + */ +}; + +// for sync_conf and other types... +#define NL_PACKET(name, number, fields) struct name { fields }; +#define NL_INTEGER(pn,pr,member) int member; +#define NL_INT64(pn,pr,member) __u64 member; +#define NL_BIT(pn,pr,member) unsigned member : 1; +#define NL_STRING(pn,pr,member,len) unsigned char member[len]; int member ## _len; +#include "linux/drbd_nl.h" + +struct drbd_backing_dev { + struct block_device *backing_bdev; + struct block_device *md_bdev; + struct file *lo_file; + struct file *md_file; + struct drbd_md md; + struct disk_conf dc; /* The user provided config... */ + sector_t known_size; +}; + +struct drbd_md_io { + struct drbd_conf *mdev; + struct completion event; + int error; +}; + +struct bm_io_work { + struct drbd_work w; + int (*io_fn)(struct drbd_conf *mdev); + void (*done)(struct drbd_conf *mdev, int rv); +}; + +struct drbd_conf { +#ifdef PARANOIA + long magic; +#endif + /* things that are stored as / read from meta data on disk */ + unsigned long flags; + + /* configured by drbdsetup */ + struct net_conf *net_conf; /* protected by inc_net() and dec_net() */ + struct syncer_conf sync_conf; + struct drbd_backing_dev *bc __protected_by(local); + + sector_t p_size; /* partner's disk size */ + struct request_queue *rq_queue; + struct block_device *this_bdev; + struct gendisk *vdisk; + + struct drbd_socket data; /* data/barrier/cstate/parameter packets */ + struct drbd_socket meta; /* ping/ack (metadata) packets */ + int agreed_pro_version; /* actually used protocol version */ + unsigned long last_received; /* in jiffies, either socket */ + unsigned int ko_count; + struct drbd_work resync_work, + unplug_work, + md_sync_work; + struct timer_list resync_timer; + struct timer_list md_sync_timer; + + /* Used after attach while negotiating new disk state. */ + union drbd_state_t new_state_tmp; + + union drbd_state_t state; + wait_queue_head_t misc_wait; + wait_queue_head_t state_wait; /* upon each state change. */ + unsigned int send_cnt; + unsigned int recv_cnt; + unsigned int read_cnt; + unsigned int writ_cnt; + unsigned int al_writ_cnt; + unsigned int bm_writ_cnt; + atomic_t ap_bio_cnt; /* Requests we need to complete */ + atomic_t ap_pending_cnt; /* AP data packets on the wire, ack expected */ + atomic_t rs_pending_cnt; /* RS request/data packets on the wire */ + atomic_t unacked_cnt; /* Need to send replys for */ + atomic_t local_cnt; /* Waiting for local completion */ + atomic_t net_cnt; /* Users of net_conf */ + spinlock_t req_lock; + struct drbd_barrier *unused_spare_barrier; /* for pre-allocation */ + struct drbd_barrier *newest_barrier; + struct drbd_barrier *oldest_barrier; + struct hlist_head *tl_hash; + unsigned int tl_hash_s; + + /* blocks to sync in this run [unit BM_BLOCK_SIZE] */ + unsigned long rs_total; + /* number of sync IOs that failed in this run */ + unsigned long rs_failed; + /* Syncer's start time [unit jiffies] */ + unsigned long rs_start; + /* cumulated time in PausedSyncX state [unit jiffies] */ + unsigned long rs_paused; + /* block not up-to-date at mark [unit BM_BLOCK_SIZE] */ + unsigned long rs_mark_left; + /* marks's time [unit jiffies] */ + unsigned long rs_mark_time; + + sector_t ov_position; + sector_t ov_last_oos_start; /* Start sector of out of sync range */ + sector_t ov_last_oos_size; /* size of out-of-sync range in sectors */ + unsigned long ov_left; + struct crypto_hash *verify_tfm; + + struct Drbd_thread receiver; + struct Drbd_thread worker; + struct Drbd_thread asender; + struct drbd_bitmap *bitmap; + + /* Used to track operations of resync... */ + struct lru_cache *resync; + /* Number of locked elements in resync LRU */ + unsigned int resync_locked; + /* resync extent number waiting for application requests */ + unsigned int resync_wenr; + + int open_cnt; + u64 *p_uuid; + /* FIXME clean comments, restructure so it is more obvious which + * members are protected by what */ + unsigned int epoch_size; + struct list_head active_ee; /* IO in progress */ + struct list_head sync_ee; /* IO in progress */ + struct list_head done_ee; /* send ack */ + struct list_head read_ee; /* IO in progress */ + struct list_head net_ee; /* zero-copy network send in progress */ + struct hlist_head *ee_hash; /* is proteced by req_lock! */ + unsigned int ee_hash_s; + + /* this one is protected by ee_lock, single thread */ + struct Tl_epoch_entry *last_write_w_barrier; + + int next_barrier_nr; + struct hlist_head *app_reads_hash; /* is proteced by req_lock */ + struct list_head resync_reads; + atomic_t pp_in_use; + wait_queue_head_t ee_wait; + struct page *md_io_page; /* one page buffer for md_io */ + struct page *md_io_tmpp; /* for hardsect != 512 [s390 only?] */ + struct semaphore md_io_mutex; /* protects the md_io_buffer */ + spinlock_t al_lock; + wait_queue_head_t al_wait; + struct lru_cache *act_log; /* activity log */ + unsigned int al_tr_number; + int al_tr_cycle; + int al_tr_pos; /* position of the next transaction in the journal */ + struct crypto_hash *cram_hmac_tfm; + struct crypto_hash *integrity_w_tfm; /* to be used by the worker thread */ + struct crypto_hash *integrity_r_tfm; /* to be used by the receiver thread */ + void *int_dig_out; + void *int_dig_in; + void *int_dig_vv; + wait_queue_head_t seq_wait; + atomic_t packet_seq; + unsigned int peer_seq; + spinlock_t peer_seq_lock; + int minor; + unsigned long comm_bm_set; /* communicated number of set bits. */ + cpumask_t cpu_mask; + struct bm_io_work bm_io_work; + u64 ed_uuid; /* UUID of the exposed data */ + struct mutex state_mutex; +}; + +static inline struct drbd_conf *minor_to_mdev(int minor) +{ + struct drbd_conf *mdev; + + mdev = minor < minor_count ? minor_table[minor] : NULL; + + return mdev; +} + +static inline int mdev_to_minor(struct drbd_conf *mdev) +{ + return mdev->minor; +} + +/* returns 1 if it was successfull, + * returns 0 if there was no data socket. + * so wherever you are going to use the data.socket, e.g. do + * if (!drbd_get_data_sock(mdev)) + * return 0; + * CODE(); + * drbd_put_data_sock(mdev); + */ +static inline int drbd_get_data_sock(struct drbd_conf *mdev) +{ + down(&mdev->data.mutex); + /* drbd_disconnect() could have called drbd_free_sock() + * while we were waiting in down()... */ + if (unlikely(mdev->data.socket == NULL)) { + up(&mdev->data.mutex); + return 0; + } + return 1; +} + +static inline void drbd_put_data_sock(struct drbd_conf *mdev) +{ + up(&mdev->data.mutex); +} + +/* + * function declarations + *************************/ + +/* drbd_main.c */ + +enum chg_state_flags { + ChgStateHard = 1, + ChgStateVerbose = 2, + ChgWaitComplete = 4, + ChgSerialize = 8, + ChgOrdered = ChgWaitComplete + ChgSerialize, +}; + +extern void drbd_init_set_defaults(struct drbd_conf *mdev); +extern int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f, + union drbd_state_t mask, union drbd_state_t val); +extern void drbd_force_state(struct drbd_conf *, union drbd_state_t, + union drbd_state_t); +extern int _drbd_request_state(struct drbd_conf *, union drbd_state_t, + union drbd_state_t, enum chg_state_flags); +extern int _drbd_set_state(struct drbd_conf *, union drbd_state_t, + enum chg_state_flags, struct completion *done); +extern void print_st_err(struct drbd_conf *, union drbd_state_t, + union drbd_state_t, int ); +extern int drbd_thread_start(struct Drbd_thread *thi); +extern void _drbd_thread_stop(struct Drbd_thread *thi, int restart, int wait); +#ifdef CONFIG_SMP +extern void drbd_thread_set_cpu(struct Drbd_thread *thi, cpumask_t cpu_mask); +extern cpumask_t drbd_calc_cpu_mask(struct drbd_conf *mdev); +#else +#define drbd_thread_set_cpu(A,B) ({}) +#define drbd_calc_cpu_mask(A) CPU_MASK_ALL +#endif +extern void drbd_free_resources(struct drbd_conf *mdev); +extern void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr, + unsigned int set_size); +extern void tl_clear(struct drbd_conf *mdev); +extern void _tl_add_barrier(struct drbd_conf *, struct drbd_barrier *); +extern void drbd_free_sock(struct drbd_conf *mdev); +extern int drbd_send(struct drbd_conf *mdev, struct socket *sock, + void *buf, size_t size, unsigned msg_flags); +extern int drbd_send_protocol(struct drbd_conf *mdev); +extern int _drbd_send_uuids(struct drbd_conf *mdev); +extern int drbd_send_uuids(struct drbd_conf *mdev); +extern int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val); +extern int drbd_send_sizes(struct drbd_conf *mdev); +extern int _drbd_send_state(struct drbd_conf *mdev); +extern int drbd_send_state(struct drbd_conf *mdev); +extern int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock, + enum Drbd_Packet_Cmd cmd, struct Drbd_Header *h, + size_t size, unsigned msg_flags); +#define USE_DATA_SOCKET 1 +#define USE_META_SOCKET 0 +extern int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket, + enum Drbd_Packet_Cmd cmd, struct Drbd_Header *h, + size_t size); +extern int drbd_send_cmd2(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + char *data, size_t size); +extern int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc); +extern int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr, + u32 set_size); +extern int drbd_send_ack(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + struct Tl_epoch_entry *e); +extern int drbd_send_ack_rp(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + struct Drbd_BlockRequest_Packet *rp); +extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + struct Drbd_Data_Packet *dp); +extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + sector_t sector, int blksize, u64 block_id); +extern int _drbd_send_page(struct drbd_conf *mdev, struct page *page, + int offset, size_t size); +extern int drbd_send_block(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + struct Tl_epoch_entry *e); +extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); +extern int _drbd_send_barrier(struct drbd_conf *mdev, + struct drbd_barrier *barrier); +extern int drbd_send_drequest(struct drbd_conf *mdev, int cmd, + sector_t sector, int size, u64 block_id); +extern int drbd_send_drequest_csum(struct drbd_conf *mdev, + sector_t sector,int size, + void *digest, int digest_size, + enum Drbd_Packet_Cmd cmd); +extern int drbd_send_ov_request(struct drbd_conf *mdev,sector_t sector,int size); + +extern int drbd_send_bitmap(struct drbd_conf *mdev); +extern int _drbd_send_bitmap(struct drbd_conf *mdev); +extern int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode); +extern void drbd_free_bc(struct drbd_backing_dev *bc); +extern int drbd_io_error(struct drbd_conf *mdev, int forcedetach); +extern void drbd_mdev_cleanup(struct drbd_conf *mdev); + +/* drbd_meta-data.c (still in drbd_main.c) */ +extern void drbd_md_sync(struct drbd_conf *mdev); +extern int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev); +/* maybe define them below as inline? */ +extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local); +extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local); +extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local); +extern void _drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local); +extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local); +extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local); +extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local); +extern int drbd_md_test_flag(struct drbd_backing_dev *, int); +extern void drbd_md_mark_dirty(struct drbd_conf *mdev); +extern void drbd_queue_bitmap_io(struct drbd_conf *mdev, + int (*io_fn)(struct drbd_conf *), + void (*done)(struct drbd_conf *, int)); +extern int drbd_bmio_set_n_write(struct drbd_conf *mdev); +extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *)); + + +/* Meta data layout + We reserve a 128MB Block (4k aligned) + * either at the end of the backing device + * or on a seperate meta data device. */ + +#define MD_RESERVED_SECT ( 128LU << 11 ) /* 128 MB, unit sectors */ +/* The following numbers are sectors */ +#define MD_AL_OFFSET 8 /* 8 Sectors after start of meta area */ +#define MD_AL_MAX_SIZE 64 /* = 32 kb LOG ~ 3776 extents ~ 14 GB Storage */ +/* Allows up to about 3.8TB */ +#define MD_BM_OFFSET (MD_AL_OFFSET + MD_AL_MAX_SIZE) + +/* Since the smalles IO unit is usually 512 byte */ +#define MD_HARDSECT_B 9 +#define MD_HARDSECT (1< we need 32 KB bitmap. + * Bit 0 ==> local node thinks this block is binary identical on both nodes + * Bit 1 ==> local node thinks this block needs to be synced. + */ + +#define BM_BLOCK_SIZE_B 12 /* 4k per bit */ +#define BM_BLOCK_SIZE (1<>(BM_BLOCK_SIZE_B-9)) +#define BM_BIT_TO_SECT(x) ((sector_t)(x)<<(BM_BLOCK_SIZE_B-9)) +#define BM_SECT_PER_BIT BM_BIT_TO_SECT(1) + +/* bit to represented kilo byte conversion */ +#define Bit2KB(bits) ((bits)<<(BM_BLOCK_SIZE_B-10)) + +/* in which _bitmap_ extent (resp. sector) the bit for a certain + * _storage_ sector is located in */ +#define BM_SECT_TO_EXT(x) ((x)>>(BM_EXT_SIZE_B-9)) + +/* who much _storage_ sectors we have per bitmap sector */ +#define BM_SECT_PER_EXT (1ULL << (BM_EXT_SIZE_B-9)) + +/* in one sector of the bitmap, we have this many activity_log extents. */ +#define AL_EXT_PER_BM_SECT (1 << (BM_EXT_SIZE_B - AL_EXTENT_SIZE_B) ) +#define BM_WORDS_PER_AL_EXT (1 << (AL_EXTENT_SIZE_B-BM_BLOCK_SIZE_B-LN2_BPL)) + + +#define BM_BLOCKS_PER_BM_EXT_B ( BM_EXT_SIZE_B - BM_BLOCK_SIZE_B ) +#define BM_BLOCKS_PER_BM_EXT_MASK ( (1<= level) && (type & trace_type)); +} +static inline int +is_mdev_trace(struct drbd_conf *mdev, unsigned int type, unsigned int level) { + return (is_trace(type, level) && + ( ( 1 << mdev_to_minor(mdev)) & trace_devs)); +} + +#define MTRACE(type, lvl, code...) \ +do { \ + if (unlikely(is_mdev_trace(mdev, type, lvl))) { \ + code \ + } \ +} while (0) + +#define TRACE(type, lvl, code...) \ +do { \ + if (unlikely(is_trace(type, lvl))) { \ + code \ + } \ +} while (0) + +/* Buffer printing support + * dbg_print_flags: used for Flags arg to drbd_print_buffer + * - DBGPRINT_BUFFADDR; if set, each line starts with the + * virtual address of the line being output. If clear, + * each line starts with the offset from the beginning + * of the buffer. */ +enum dbg_print_flags { + DBGPRINT_BUFFADDR = 0x0001, +}; + +extern void drbd_print_uuid(struct drbd_conf *mdev, unsigned int idx); + +extern void drbd_print_buffer(const char *prefix, unsigned int flags, int size, + const void *buffer, const void *buffer_va, + unsigned int length); + +/* Bio printing support */ +extern void _dump_bio(const char *pfx, struct drbd_conf *mdev, struct bio *bio, int complete); + +static inline void dump_bio(struct drbd_conf *mdev, + struct bio *bio, int complete) +{ + MTRACE(TraceTypeRq, TraceLvlSummary, + _dump_bio("Rq", mdev, bio, complete); + ); +} + +static inline void dump_internal_bio(const char *pfx, struct drbd_conf *mdev, struct bio *bio, int complete) { + MTRACE(TraceTypeIntRq,TraceLvlSummary, + _dump_bio(pfx, mdev, bio, complete); + ); +} + +/* Packet dumping support */ +extern void _dump_packet(struct drbd_conf *mdev, struct socket *sock, + int recv, union Drbd_Polymorph_Packet *p, + char *file, int line); + +static inline void +dump_packet(struct drbd_conf *mdev, struct socket *sock, + int recv, union Drbd_Polymorph_Packet *p, char *file, int line) +{ + MTRACE(TraceTypePacket, TraceLvlSummary, + _dump_packet(mdev, sock, recv, p, file, line); + ); +} + +#else + +#define MTRACE(ignored...) ((void)0) +#define TRACE(ignored...) ((void)0) + +#define dump_bio(ignored...) ((void)0) +#define dump_internal_bio(ignored...) ((void)0) +#define dump_packet(ignored...) ((void)0) +#endif + +/* drbd_req */ +extern int drbd_make_request_26(struct request_queue *q, struct bio *bio); +extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req); +extern int drbd_merge_bvec(struct request_queue *, struct bvec_merge_data *bvm, struct bio_vec *); +extern int is_valid_ar_handle(struct drbd_request *, sector_t); + + +/* drbd_nl.c */ +extern char *ppsize(char *buf, unsigned long long size); +extern sector_t drbd_new_dev_size(struct drbd_conf *, + struct drbd_backing_dev *); +enum determin_dev_size_enum { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = 2 }; +extern enum determin_dev_size_enum drbd_determin_dev_size(struct drbd_conf *) __must_hold(local); +extern void resync_after_online_grow(struct drbd_conf *); +extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local); +extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, + int force); +extern int drbd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev); +extern long drbd_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); +extern int drbd_khelper(struct drbd_conf *mdev, char *cmd); + +/* drbd_worker.c */ +extern int drbd_worker(struct Drbd_thread *thi); +extern void drbd_alter_sa(struct drbd_conf *mdev, int na); +extern void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side); +extern void resume_next_sg(struct drbd_conf *mdev); +extern void suspend_other_sg(struct drbd_conf *mdev); +extern int drbd_resync_finished(struct drbd_conf *mdev); +/* maybe rather drbd_main.c ? */ +extern int drbd_md_sync_page_io(struct drbd_conf *mdev, + struct drbd_backing_dev *bdev, sector_t sector, int rw); +extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int); + +static inline void ov_oos_print(struct drbd_conf *mdev) +{ + if (mdev->ov_last_oos_size) { + ERR("Out of sync: start=%llu, size=%lu (sectors)\n", + (unsigned long long)mdev->ov_last_oos_start, + (unsigned long)mdev->ov_last_oos_size); + } + mdev->ov_last_oos_size=0; +} + + +void drbd_csum(struct drbd_conf *, struct crypto_hash *, struct bio *, void *); +/* worker callbacks */ +extern int w_req_cancel_conflict(struct drbd_conf *, struct drbd_work *, int); +extern int w_read_retry_remote(struct drbd_conf *, struct drbd_work *, int); +extern int w_e_end_data_req(struct drbd_conf *, struct drbd_work *, int); +extern int w_e_end_rsdata_req(struct drbd_conf *, struct drbd_work *, int); +extern int w_e_end_ov_reply(struct drbd_conf *, struct drbd_work *, int); +extern int w_e_end_ov_req(struct drbd_conf *, struct drbd_work *, int); +extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int); +extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int); +extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int); +extern int w_io_error(struct drbd_conf *, struct drbd_work *, int); +extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int); +extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int); +extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int); +extern int w_send_barrier(struct drbd_conf *, struct drbd_work *, int); +extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int); +extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); + +extern void resync_timer_fn(unsigned long data); + +/* drbd_receiver.c */ +extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list); +extern struct Tl_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev, + u64 id, + sector_t sector, + unsigned int data_size, + gfp_t gfp_mask) __must_hold(local); +extern void drbd_free_ee(struct drbd_conf *mdev, struct Tl_epoch_entry *e); +extern void drbd_wait_ee_list_empty(struct drbd_conf *mdev, + struct list_head *head); +extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev, + struct list_head *head); +extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled); +extern void _drbd_clear_done_ee(struct drbd_conf *mdev); + +static inline void drbd_tcp_cork(struct socket *sock) +{ + int __user val = 1; + tcp_setsockopt(sock->sk, SOL_TCP, TCP_CORK, (char __user *)&val, sizeof(val) ); +} + +static inline void drbd_tcp_flush(struct socket *sock) +{ + int __user val = 0; + tcp_setsockopt(sock->sk, SOL_TCP, TCP_CORK, (char __user *)&val, sizeof(val) ); +} + +/* drbd_proc.c */ +extern struct proc_dir_entry *drbd_proc; +extern struct file_operations drbd_proc_fops; +extern const char *conns_to_name(enum drbd_conns s); +extern const char *roles_to_name(enum drbd_role s); + +/* drbd_actlog.c */ +extern void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector); +extern void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector); +extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector); +extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector); +extern int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector); +extern void drbd_rs_cancel_all(struct drbd_conf *mdev); +extern int drbd_rs_del_all(struct drbd_conf *mdev); +extern void drbd_rs_failed_io(struct drbd_conf *mdev, + sector_t sector, int size); +extern int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *); +extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, + int size, const char *file, const unsigned int line); +#define drbd_set_in_sync(mdev, sector, size) \ + __drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__ ) +extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, + int size, const char *file, const unsigned int line); +#define drbd_set_out_of_sync(mdev, sector, size) \ + __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__ ) +extern void drbd_al_apply_to_bm(struct drbd_conf *mdev); +extern void drbd_al_to_on_disk_bm(struct drbd_conf *mdev); +extern void drbd_al_shrink(struct drbd_conf *mdev); + + +/* drbd_nl.c */ + +void drbd_nl_cleanup(void); +int __init drbd_nl_init(void); +void drbd_bcast_state(struct drbd_conf *mdev, union drbd_state_t); +void drbd_bcast_sync_progress(struct drbd_conf *mdev); +void drbd_bcast_ee(struct drbd_conf *mdev, + const char *reason, const int dgs, + const char* seen_hash, const char* calc_hash, + const struct Tl_epoch_entry* e); + +/* + * inline helper functions + *************************/ + +#define peer_mask role_mask +#define pdsk_mask disk_mask +#define susp_mask 1 +#define user_isp_mask 1 +#define aftr_isp_mask 1 + +#define NS(T, S) \ + ({ union drbd_state_t mask; mask.i = 0; mask.T = T##_mask; mask; }), \ + ({ union drbd_state_t val; val.i = 0; val.T = (S); val; }) +#define NS2(T1, S1, T2, S2) \ + ({ union drbd_state_t mask; mask.i = 0; mask.T1 = T1##_mask; \ + mask.T2 = T2##_mask; mask; }), \ + ({ union drbd_state_t val; val.i = 0; val.T1 = (S1); \ + val.T2 = (S2); val; }) +#define NS3(T1, S1, T2, S2, T3, S3) \ + ({ union drbd_state_t mask; mask.i = 0; mask.T1 = T1##_mask; \ + mask.T2 = T2##_mask; mask.T3 = T3##_mask; mask; }), \ + ({ union drbd_state_t val; val.i = 0; val.T1 = (S1); \ + val.T2 = (S2); val.T3 = (S3); val; }) + +#define _NS(D, T, S) \ + D, ({ union drbd_state_t __ns; __ns.i = D->state.i; __ns.T = (S); __ns; }) +#define _NS2(D, T1, S1, T2, S2) \ + D, ({ union drbd_state_t __ns; __ns.i = D->state.i; __ns.T1 = (S1); \ + __ns.T2 = (S2); __ns; }) +#define _NS3(D, T1, S1, T2, S2, T3, S3) \ + D, ({ union drbd_state_t __ns; __ns.i = D->state.i; __ns.T1 = (S1); \ + __ns.T2 = (S2); __ns.T3 = (S3); __ns; }) + +static inline void drbd_state_lock(struct drbd_conf *mdev) +{ + wait_event(mdev->misc_wait, + !test_and_set_bit(CLUSTER_ST_CHANGE, &mdev->flags)); +} + +static inline void drbd_state_unlock(struct drbd_conf *mdev) +{ + clear_bit(CLUSTER_ST_CHANGE, &mdev->flags); + wake_up(&mdev->misc_wait); +} + +static inline int drbd_request_state(struct drbd_conf *mdev, + union drbd_state_t mask, + union drbd_state_t val) +{ + return _drbd_request_state(mdev, mask, val, ChgStateVerbose + ChgOrdered); +} + +/** + * drbd_chk_io_error: Handles the on_io_error setting, should be called from + * all io completion handlers. See also drbd_io_error(). + */ +static inline void __drbd_chk_io_error(struct drbd_conf *mdev, int forcedetach) +{ + switch (mdev->bc->dc.on_io_error) { + case PassOn: /* FIXME would this be better named "Ignore"? */ + if (!forcedetach) { + if (printk_ratelimit()) + ERR("Local IO failed. Passing error on...\n"); + break; + } + /* NOTE fall through to detach case if forcedetach set */ + case Detach: + case CallIOEHelper: + if (mdev->state.disk > Failed) { + _drbd_set_state(_NS(mdev, disk, Failed), ChgStateHard, NULL); + ERR("Local IO failed. Detaching...\n"); + } + break; + } +} + +static inline void drbd_chk_io_error(struct drbd_conf *mdev, + int error, int forcedetach) +{ + if (error) { + unsigned long flags; + spin_lock_irqsave(&mdev->req_lock, flags); + __drbd_chk_io_error(mdev, forcedetach); + spin_unlock_irqrestore(&mdev->req_lock, flags); + } +} + +static inline int semaphore_is_locked(struct semaphore *s) +{ + if (!down_trylock(s)) { + up(s); + return 0; + } + return 1; +} + +/* Returns the first sector number of our meta data, + * which, for internal meta data, happens to be the maximum capacity + * we could agree upon with our peer + */ +static inline sector_t drbd_md_first_sector(struct drbd_backing_dev *bdev) +{ + switch (bdev->dc.meta_dev_idx) { + case DRBD_MD_INDEX_INTERNAL: + case DRBD_MD_INDEX_FLEX_INT: + return bdev->md.md_offset + bdev->md.bm_offset; + case DRBD_MD_INDEX_FLEX_EXT: + default: + return bdev->md.md_offset; + } +} + +/* returns the last sector number of our meta data, + * to be able to catch out of band md access */ +static inline sector_t drbd_md_last_sector(struct drbd_backing_dev *bdev) +{ + switch (bdev->dc.meta_dev_idx) { + case DRBD_MD_INDEX_INTERNAL: + case DRBD_MD_INDEX_FLEX_INT: + return bdev->md.md_offset + MD_AL_OFFSET -1; + case DRBD_MD_INDEX_FLEX_EXT: + default: + return bdev->md.md_offset + bdev->md.md_size_sect; + } +} + +/* returns the capacity we announce to out peer */ +static inline sector_t drbd_get_max_capacity(struct drbd_backing_dev *bdev) +{ + switch (bdev->dc.meta_dev_idx) { + case DRBD_MD_INDEX_INTERNAL: + case DRBD_MD_INDEX_FLEX_INT: + return drbd_get_capacity(bdev->backing_bdev) + ? drbd_md_first_sector(bdev) + : 0; + case DRBD_MD_INDEX_FLEX_EXT: + default: + return drbd_get_capacity(bdev->backing_bdev); + } +} + +/* returns the sector number of our meta data 'super' block */ +static inline sector_t drbd_md_ss__(struct drbd_conf *mdev, + struct drbd_backing_dev *bdev) +{ + switch (bdev->dc.meta_dev_idx) { + default: /* external, some index */ + return MD_RESERVED_SECT * bdev->dc.meta_dev_idx; + case DRBD_MD_INDEX_INTERNAL: + /* with drbd08, internal meta data is always "flexible" */ + case DRBD_MD_INDEX_FLEX_INT: + /* sizeof(struct md_on_disk_07) == 4k + * position: last 4k aligned block of 4k size */ + if (!bdev->backing_bdev) { + if (DRBD_ratelimit(5*HZ, 5)) { + ERR("bdev->backing_bdev==NULL\n"); + dump_stack(); + } + return 0; + } + return (drbd_get_capacity(bdev->backing_bdev) & ~7ULL) + - MD_AL_OFFSET; + case DRBD_MD_INDEX_FLEX_EXT: + return 0; + } +} + +static inline void +_drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w) +{ + list_add_tail(&w->list, &q->q); + up(&q->s); +} + +static inline void +drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w) +{ + unsigned long flags; + spin_lock_irqsave(&q->q_lock, flags); + list_add(&w->list, &q->q); + up(&q->s); /* within the spinlock, + see comment near end of drbd_worker() */ + spin_unlock_irqrestore(&q->q_lock, flags); +} + +static inline void +drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w) +{ + unsigned long flags; + spin_lock_irqsave(&q->q_lock, flags); + list_add_tail(&w->list, &q->q); + up(&q->s); /* within the spinlock, + see comment near end of drbd_worker() */ + spin_unlock_irqrestore(&q->q_lock, flags); +} + +static inline void wake_asender(struct drbd_conf *mdev) +{ + if (test_bit(SIGNAL_ASENDER, &mdev->flags)) + force_sig(DRBD_SIG, mdev->asender.task); +} + +static inline void request_ping(struct drbd_conf *mdev) +{ + set_bit(SEND_PING, &mdev->flags); + wake_asender(mdev); +} + +static inline int drbd_send_short_cmd(struct drbd_conf *mdev, + enum Drbd_Packet_Cmd cmd) +{ + struct Drbd_Header h; + return drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd, &h, sizeof(h)); +} + +static inline int drbd_send_ping(struct drbd_conf *mdev) +{ + struct Drbd_Header h; + return drbd_send_cmd(mdev, USE_META_SOCKET, Ping, &h, sizeof(h)); +} + +static inline int drbd_send_ping_ack(struct drbd_conf *mdev) +{ + struct Drbd_Header h; + return drbd_send_cmd(mdev, USE_META_SOCKET, PingAck, &h, sizeof(h)); +} + +static inline void drbd_thread_stop(struct Drbd_thread *thi) +{ + _drbd_thread_stop(thi, FALSE, TRUE); +} + +static inline void drbd_thread_stop_nowait(struct Drbd_thread *thi) +{ + _drbd_thread_stop(thi, FALSE, FALSE); +} + +static inline void drbd_thread_restart_nowait(struct Drbd_thread *thi) +{ + _drbd_thread_stop(thi, TRUE, FALSE); +} + +/* counts how many answer packets packets we expect from our peer, + * for either explicit application requests, + * or implicit barrier packets as necessary. + * increased: + * w_send_barrier + * _req_mod(req, queue_for_net_write or queue_for_net_read); + * it is much easier and equally valid to count what we queue for the + * worker, even before it actually was queued or send. + * (drbd_make_request_common; recovery path on read io-error) + * decreased: + * got_BarrierAck (respective tl_clear, tl_clear_barrier) + * _req_mod(req, data_received) + * [from receive_DataReply] + * _req_mod(req, write_acked_by_peer or recv_acked_by_peer or neg_acked) + * [from got_BlockAck (WriteAck, RecvAck)] + * FIXME + * for some reason it is NOT decreased in got_NegAck, + * but in the resulting cleanup code from report_params. + * we should try to remember the reason for that... + * _req_mod(req, send_failed or send_canceled) + * _req_mod(req, connection_lost_while_pending) + * [from tl_clear_barrier] + */ +static inline void inc_ap_pending(struct drbd_conf *mdev) +{ + atomic_inc(&mdev->ap_pending_cnt); +} + +#define ERR_IF_CNT_IS_NEGATIVE(which) \ + if (atomic_read(&mdev->which) < 0) \ + ERR("in %s:%d: " #which " = %d < 0 !\n", \ + __func__ , __LINE__ , \ + atomic_read(&mdev->which)) + +#define dec_ap_pending(mdev) do { \ + typecheck(struct drbd_conf *, mdev); \ + if (atomic_dec_and_test(&mdev->ap_pending_cnt)) \ + wake_up(&mdev->misc_wait); \ + ERR_IF_CNT_IS_NEGATIVE(ap_pending_cnt); } while (0) + +/* counts how many resync-related answers we still expect from the peer + * increase decrease + * SyncTarget sends RSDataRequest (and expects RSDataReply) + * SyncSource sends RSDataReply (and expects WriteAck whith ID_SYNCER) + * (or NegAck with ID_SYNCER) + */ +static inline void inc_rs_pending(struct drbd_conf *mdev) +{ + atomic_inc(&mdev->rs_pending_cnt); +} + +#define dec_rs_pending(mdev) do { \ + typecheck(struct drbd_conf *, mdev); \ + atomic_dec(&mdev->rs_pending_cnt); \ + ERR_IF_CNT_IS_NEGATIVE(rs_pending_cnt); } while (0) + +/* counts how many answers we still need to send to the peer. + * increased on + * receive_Data unless protocol A; + * we need to send a RecvAck (proto B) + * or WriteAck (proto C) + * receive_RSDataReply (recv_resync_read) we need to send a WriteAck + * receive_DataRequest (receive_RSDataRequest) we need to send back Data + * receive_Barrier_* we need to send a BarrierAck + */ +static inline void inc_unacked(struct drbd_conf *mdev) +{ + atomic_inc(&mdev->unacked_cnt); +} + +#define dec_unacked(mdev) do { \ + typecheck(struct drbd_conf *, mdev); \ + atomic_dec(&mdev->unacked_cnt); \ + ERR_IF_CNT_IS_NEGATIVE(unacked_cnt); } while (0) + +#define sub_unacked(mdev, n) do { \ + typecheck(struct drbd_conf *, mdev); \ + atomic_sub(n, &mdev->unacked_cnt); \ + ERR_IF_CNT_IS_NEGATIVE(unacked_cnt); } while (0) + + +static inline void dec_net(struct drbd_conf *mdev) +{ + if (atomic_dec_and_test(&mdev->net_cnt)) + wake_up(&mdev->misc_wait); +} + +/** + * inc_net: Returns TRUE when it is ok to access mdev->net_conf. You + * should call dec_net() when finished looking at mdev->net_conf. + */ +static inline int inc_net(struct drbd_conf *mdev) +{ + int have_net_conf; + + atomic_inc(&mdev->net_cnt); + have_net_conf = mdev->state.conn >= Unconnected; + if (!have_net_conf) + dec_net(mdev); + return have_net_conf; +} + +/** + * inc_local: Returns TRUE when local IO is possible. If it returns + * TRUE you should call dec_local() after IO is completed. + */ +#define inc_local_if_state(M,MINS) __cond_lock(local, _inc_local_if_state(M,MINS)) +#define inc_local(M) __cond_lock(local, _inc_local_if_state(M,Inconsistent)) + +static inline void dec_local(struct drbd_conf *mdev) +{ + __release(local); + if (atomic_dec_and_test(&mdev->local_cnt)) + wake_up(&mdev->misc_wait); + D_ASSERT(atomic_read(&mdev->local_cnt) >= 0); +} + +#ifndef __CHECKER__ +static inline int _inc_local_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins) +{ + int io_allowed; + + atomic_inc(&mdev->local_cnt); + io_allowed = (mdev->state.disk >= mins ); + if (!io_allowed) + dec_local(mdev); + return io_allowed; +} +#else +extern int _inc_local_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins); +#endif + +/* you must have an "inc_local" reference */ +static inline void drbd_get_syncer_progress(struct drbd_conf *mdev, + unsigned long *bits_left, unsigned int *per_mil_done) +{ + /* + * this is to break it at compile time when we change that + * (we may feel 4TB maximum storage per drbd is not enough) + */ + typecheck(unsigned long, mdev->rs_total); + + /* note: both rs_total and rs_left are in bits, i.e. in + * units of BM_BLOCK_SIZE. + * for the percentage, we don't care. */ + + *bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed; + /* >> 10 to prevent overflow, + * +1 to prevent division by zero */ + if (*bits_left > mdev->rs_total) { + /* doh. maybe a logic bug somewhere. + * may also be just a race condition + * between this and a disconnect during sync. + * for now, just prevent in-kernel buffer overflow. + */ + smp_rmb(); + DRBD_WARN("cs:%s rs_left=%lu > rs_total=%lu (rs_failed %lu)\n", + conns_to_name(mdev->state.conn), + *bits_left, mdev->rs_total, mdev->rs_failed); + *per_mil_done = 0; + } else { + /* make sure the calculation happens in long context */ + unsigned long tmp = 1000UL - + (*bits_left >> 10)*1000UL + / ((mdev->rs_total >> 10) + 1UL); + *per_mil_done = tmp; + } +} + + +/* this throttles on-the-fly application requests + * according to max_buffers settings; + * maybe re-implement using semaphores? */ +static inline int drbd_get_max_buffers(struct drbd_conf *mdev) +{ + int mxb = 1000000; /* arbitrary limit on open requests */ + if (inc_net(mdev)) { + mxb = mdev->net_conf->max_buffers; + dec_net(mdev); + } + return mxb; +} + +static inline int __inc_ap_bio_cond(struct drbd_conf *mdev) +{ + const unsigned int cs = mdev->state.conn; + const unsigned int ds = mdev->state.disk; + int mxb = drbd_get_max_buffers(mdev); + if (mdev->state.susp) + return 0; + /* to avoid deadlock or bitmap corruption, we need to lock out + * application io during attaching and bitmap exchange */ + if (Attaching <= ds && ds <= Negotiating) + return 0; + if (cs == WFBitMapS || cs == WFBitMapT || cs == WFReportParams || cs == WFSyncUUID) + return 0; + + /* since some older kernels don't have atomic_add_unless, + * and we are within the spinlock anyways, we have this workaround. */ + if (atomic_read(&mdev->ap_bio_cnt) > mxb) + return 0; + if (test_bit(BITMAP_IO, &mdev->flags)) + return 0; + atomic_inc(&mdev->ap_bio_cnt); + return 1; +} + +/* I'd like to use wait_event_lock_irq, + * but I'm not sure when it got introduced, + * and not sure when it has 3 or 4 arguments */ +static inline void inc_ap_bio(struct drbd_conf *mdev) +{ + /* compare with after_state_ch, + * os.conn != WFBitMapS && ns.conn == WFBitMapS */ + DEFINE_WAIT(wait); + + /* we wait here + * as long as the device is suspended + * until the bitmap is no longer on the fly during connection + * handshake as long as we would exeed the max_buffer limit. + * + * to avoid races with the reconnect code, + * we need to atomic_inc within the spinlock. */ + + spin_lock_irq(&mdev->req_lock); + while (!__inc_ap_bio_cond(mdev)) { + prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock_irq(&mdev->req_lock); + schedule(); + finish_wait(&mdev->misc_wait, &wait); + spin_lock_irq(&mdev->req_lock); + } + spin_unlock_irq(&mdev->req_lock); +} + +static inline void dec_ap_bio(struct drbd_conf *mdev) +{ + int mxb = drbd_get_max_buffers(mdev); + int ap_bio = atomic_dec_return(&mdev->ap_bio_cnt); + + D_ASSERT(ap_bio >= 0); + if (ap_bio < mxb) + wake_up(&mdev->misc_wait); + if (ap_bio == 0 && test_bit(BITMAP_IO, &mdev->flags)) { + if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags)) + drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w); + } +} + +static inline void drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val) +{ + mdev->ed_uuid = val; + + MTRACE(TraceTypeUuid,TraceLvlMetrics, + INFO(" exposed data uuid now %016llX\n",val); + ); +} + +static inline int seq_cmp(u32 a, u32 b) +{ + /* we assume wrap around at 32bit. + * for wrap around at 24bit (old atomic_t), + * we'd have to + * a <<= 8; b <<= 8; + */ + return ((s32)(a) - (s32)(b)); +} +#define seq_lt(a, b) (seq_cmp((a), (b)) < 0) +#define seq_gt(a, b) (seq_cmp((a), (b)) > 0) +#define seq_ge(a, b) (seq_cmp((a), (b)) >= 0) +#define seq_le(a, b) (seq_cmp((a), (b)) <= 0) +/* CAUTION: please no side effects in arguments! */ +#define seq_max(a, b) ((u32)(seq_gt((a), (b)) ? (a) : (b))) + +static inline void update_peer_seq(struct drbd_conf *mdev, unsigned int new_seq) +{ + unsigned int m; + spin_lock(&mdev->peer_seq_lock); + m = seq_max(mdev->peer_seq, new_seq); + mdev->peer_seq = m; + spin_unlock(&mdev->peer_seq_lock); + if (m == new_seq) + wake_up(&mdev->seq_wait); +} + +static inline int drbd_queue_order_type(struct drbd_conf *mdev) +{ + /* sorry, we currently have no working implementation + * of distributed TCQ stuff */ +#ifndef QUEUE_ORDERED_NONE +#define QUEUE_ORDERED_NONE 0 +#endif + return QUEUE_ORDERED_NONE; +} + +/* + * FIXME investigate what makes most sense: + * a) blk_run_queue(q); + * + * b) struct backing_dev_info *bdi; + * b1) bdi = &q->backing_dev_info; + * b2) bdi = mdev->bc->backing_bdev->bd_inode->i_mapping->backing_dev_info; + * blk_run_backing_dev(bdi,NULL); + * + * c) generic_unplug(q) ? __generic_unplug(q) ? + * + * d) q->unplug_fn(q), which is what all the drivers/md/ stuff uses... + * + */ +static inline void drbd_blk_run_queue(struct request_queue *q) +{ + if (q && q->unplug_fn) + q->unplug_fn(q); +} + +static inline void drbd_kick_lo(struct drbd_conf *mdev) +{ + if (inc_local(mdev)) { + drbd_blk_run_queue(bdev_get_queue(mdev->bc->backing_bdev)); + dec_local(mdev); + } +} +#endif --- linux-2.6.27.orig/ubuntu/drbd/BOM +++ linux-2.6.27/ubuntu/drbd/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://oss.linbit.com/drbd/ +Current Version: 8.2.6 --- linux-2.6.27.orig/ubuntu/drbd/drbd_worker.c +++ linux-2.6.27/ubuntu/drbd/drbd_worker.c @@ -0,0 +1,1322 @@ +/* +-*- linux-c -*- + drbd_worker.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 1999-2008, Philipp Reisner . + Copyright (C) 2002-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_SCATTERLIST_H +#include +#endif + +#include +#include "drbd_int.h" +#include "drbd_req.h" + +/* defined here: + drbd_md_io_complete + drbd_endio_write_sec + drbd_endio_read_sec + drbd_endio_pri + + * more endio handlers: + atodb_endio in drbd_actlog.c + drbd_bm_async_io_complete in drbd_bitmap.c + + * For all these callbacks, note the follwing: + * The callbacks will be called in irq context by the IDE drivers, + * and in Softirqs/Tasklets/BH context by the SCSI drivers. + * Try to get the locking right :) + * + */ + +/* used for synchronous meta data and bitmap IO + * submitted by drbd_md_sync_page_io() + */ +BIO_ENDIO_TYPE drbd_md_io_complete BIO_ENDIO_ARGS(struct bio *bio, int error) +{ + struct drbd_md_io *md_io; + + BIO_ENDIO_FN_START; + + /* error parameter ignored: + * drbd_md_sync_page_io explicitly tests bio_uptodate(bio); */ + + md_io = (struct drbd_md_io *)bio->bi_private; + + md_io->error = error; + + dump_internal_bio("Md", md_io->mdev, bio, 1); + + complete(&md_io->event); + + BIO_ENDIO_FN_RETURN; +} + +/* reads on behalf of the partner, + * "submitted" by the receiver + */ +BIO_ENDIO_TYPE drbd_endio_read_sec BIO_ENDIO_ARGS(struct bio *bio, int error) __releases(local) +{ + unsigned long flags = 0; + struct Tl_epoch_entry *e = NULL; + struct drbd_conf *mdev; + int uptodate = bio_flagged(bio, BIO_UPTODATE); + + e = bio->bi_private; + mdev = e->mdev; + + BIO_ENDIO_FN_START; + if (!error && !uptodate) { + /* strange behaviour of some lower level drivers... + * fail the request by clearing the uptodate flag, + * but do not return any error?! + * do we want to DRBD_WARN() on this? */ + error = -EIO; + } + + D_ASSERT(e->block_id != ID_VACANT); + + dump_internal_bio("Sec", mdev, bio, 1); + + spin_lock_irqsave(&mdev->req_lock, flags); + mdev->read_cnt += e->size >> 9; + list_del(&e->w.list); + if (list_empty(&mdev->read_ee)) wake_up(&mdev->ee_wait); + spin_unlock_irqrestore(&mdev->req_lock, flags); + + drbd_chk_io_error(mdev, error, FALSE); + drbd_queue_work(&mdev->data.work, &e->w); + dec_local(mdev); + + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("Moved EE (READ) to worker sec=%llus size=%u ee=%p\n", + (unsigned long long)e->sector, e->size, e); + ); + BIO_ENDIO_FN_RETURN; +} + +/* writes on behalf of the partner, or resync writes, + * "submitted" by the receiver. + */ +BIO_ENDIO_TYPE drbd_endio_write_sec BIO_ENDIO_ARGS(struct bio *bio, int error) __releases(local) +{ + unsigned long flags = 0; + struct Tl_epoch_entry *e = NULL; + struct drbd_conf *mdev; + sector_t e_sector; + int do_wake; + int is_syncer_req; + int do_al_complete_io; + int uptodate = bio_flagged(bio, BIO_UPTODATE); + + e = bio->bi_private; + mdev = e->mdev; + + BIO_ENDIO_FN_START; + if (!error && !uptodate) { + /* strange behaviour of some lower level drivers... + * fail the request by clearing the uptodate flag, + * but do not return any error?! + * do we want to DRBD_WARN() on this? */ + error = -EIO; + } + + D_ASSERT(e->block_id != ID_VACANT); + + dump_internal_bio("Sec", mdev, bio, 1); + + spin_lock_irqsave(&mdev->req_lock, flags); + mdev->writ_cnt += e->size >> 9; + is_syncer_req = is_syncer_block_id(e->block_id); + + /* after we moved e to done_ee, + * we may no longer access it, + * it may be freed/reused already! + * (as soon as we release the req_lock) */ + e_sector = e->sector; + do_al_complete_io = e->flags & EE_CALL_AL_COMPLETE_IO; + + list_del(&e->w.list); /* has been on active_ee or sync_ee */ + list_add_tail(&e->w.list, &mdev->done_ee); + + MTRACE(TraceTypeEE, TraceLvlAll, + INFO("Moved EE (WRITE) to done_ee sec=%llus size=%u ee=%p\n", + (unsigned long long)e->sector, e->size, e); + ); + + /* No hlist_del_init(&e->colision) here, we did not send the Ack yet, + * neither did we wake possibly waiting conflicting requests. + * done from "drbd_process_done_ee" within the appropriate w.cb + * (e_end_block/e_end_resync_block) or from _drbd_clear_done_ee */ + + if (!is_syncer_req) + mdev->epoch_size++; + + do_wake = is_syncer_req + ? list_empty(&mdev->sync_ee) + : list_empty(&mdev->active_ee); + + if (error) + __drbd_chk_io_error(mdev, FALSE); + spin_unlock_irqrestore(&mdev->req_lock, flags); + + if (is_syncer_req) + drbd_rs_complete_io(mdev, e_sector); + + if (do_wake) + wake_up(&mdev->ee_wait); + + if (do_al_complete_io) + drbd_al_complete_io(mdev, e_sector); + + wake_asender(mdev); + dec_local(mdev); + + BIO_ENDIO_FN_RETURN; +} + +/* read, readA or write requests on Primary comming from drbd_make_request + */ +BIO_ENDIO_TYPE drbd_endio_pri BIO_ENDIO_ARGS(struct bio *bio, int error) +{ + unsigned long flags; + struct drbd_request *req = bio->bi_private; + struct drbd_conf *mdev = req->mdev; + enum drbd_req_event what; + int uptodate = bio_flagged(bio, BIO_UPTODATE); + + BIO_ENDIO_FN_START; + if (!error && !uptodate) { + /* strange behaviour of some lower level drivers... + * fail the request by clearing the uptodate flag, + * but do not return any error?! + * do we want to DRBD_WARN() on this? */ + error = -EIO; + } + + dump_internal_bio("Pri", mdev, bio, 1); + + /* to avoid recursion in _req_mod */ + what = error + ? (bio_data_dir(bio) == WRITE) + ? write_completed_with_error + : read_completed_with_error + : completed_ok; + spin_lock_irqsave(&mdev->req_lock, flags); + _req_mod(req, what, error); + spin_unlock_irqrestore(&mdev->req_lock, flags); + + BIO_ENDIO_FN_RETURN; +} + +int w_io_error(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct drbd_request *req = (struct drbd_request *)w; + int ok; + + /* FIXME send a "set_out_of_sync" packet to the peer + * in the PassOn case... + * in the Detach (or Panic) case, we (try to) send + * a "we are diskless" param packet anyways, and the peer + * will then set the FullSync bit in the meta data ... + */ + /* NOTE: mdev->bc can be NULL by the time we get here! */ + /* D_ASSERT(mdev->bc->dc.on_io_error != PassOn); */ + + /* the only way this callback is scheduled is from _req_may_be_done, + * when it is done and had a local write error, see comments there */ + drbd_req_free(req); + + ok = drbd_io_error(mdev, FALSE); + if (unlikely(!ok)) ERR("Sending in w_io_error() failed\n"); + return ok; +} + +int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct drbd_request *req = (struct drbd_request *)w; + + /* FIXME this is ugly. we should not detach for read io-error, + * but try to WRITE the DataReply to the failed location, + * to give the disk the chance to relocate that block */ + drbd_io_error(mdev,FALSE); /* tries to schedule a detach and notifies peer */ + + spin_lock_irq(&mdev->req_lock); + if ( cancel || + mdev->state.conn < Connected || + mdev->state.pdsk <= Inconsistent ) { + _req_mod(req, send_canceled, 0); /* FIXME freeze? ... */ + spin_unlock_irq(&mdev->req_lock); + drbd_khelper(mdev, "pri-on-incon-degr"); /* FIXME REALLY? */ + ALERT("WE ARE LOST. Local IO failure, no peer.\n"); + return 1; + } + spin_unlock_irq(&mdev->req_lock); + + return w_send_read_req(mdev, w, 0); +} + +int w_resync_inactive(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + ERR_IF(cancel) return 1; + ERR("resync inactive, but callback triggered??\n"); + return 1; /* Simply ignore this! */ +} + +STATIC void drbd_csum(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio *bio, void *digest) +{ + struct hash_desc desc; + struct scatterlist sg; + struct bio_vec *bvec; + int i; + + desc.tfm=tfm; + desc.flags=0; + + sg_init_table(&sg, 1); + crypto_hash_init(&desc); + + __bio_for_each_segment(bvec, bio, i, 0) { + sg_set_page(&sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset); + crypto_hash_update(&desc, &sg, sg.length); + } + crypto_hash_final(&desc, digest); +} + +int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work* w,int cancel); + + +void resync_timer_fn(unsigned long data) +{ + unsigned long flags; + struct drbd_conf *mdev = (struct drbd_conf *) data; + int queue; + + spin_lock_irqsave(&mdev->req_lock, flags); + + if (likely(!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))) { + queue = 1; + if(mdev->state.conn == VerifyS ) { + mdev->resync_work.cb = w_make_ov_request; + } else mdev->resync_work.cb = w_make_resync_request; + } else { + queue = 0; + mdev->resync_work.cb = w_resync_inactive; + } + + spin_unlock_irqrestore(&mdev->req_lock, flags); + + /* harmless race: list_empty outside data.work.q_lock */ + if (list_empty(&mdev->resync_work.list) && queue) + drbd_queue_work(&mdev->data.work, &mdev->resync_work); +} + +#define SLEEP_TIME (HZ/10) + +int w_make_resync_request(struct drbd_conf *mdev, + struct drbd_work *w, int cancel) +{ + unsigned long bit; + sector_t sector; + const sector_t capacity = drbd_get_capacity(mdev->this_bdev); + int max_segment_size = mdev->rq_queue->max_segment_size; + int number, i, size; + int align; + + PARANOIA_BUG_ON(w != &mdev->resync_work); + + if (unlikely(cancel)) return 1; + + if (unlikely(mdev->state.conn < Connected)) { + ERR("Confused in w_make_resync_request()! cstate < Connected"); + return 0; + } + + if (mdev->state.conn != SyncTarget) + ERR("%s in w_make_resync_request\n", + conns_to_name(mdev->state.conn)); + + if (!inc_local(mdev)) { + /* Since we only need to access mdev->rsync a + inc_local_if_state(mdev,Failed) would be sufficient, but + to continue resync with a broken disk makes no sense at + all */ + ERR("Disk broke down during resync!\n"); + mdev->resync_work.cb = w_resync_inactive; + return 1; + } + /* All goto requeses have to happend after this block: inc_local() */ + + number = SLEEP_TIME*mdev->sync_conf.rate / ((BM_BLOCK_SIZE/1024)*HZ); + + if (atomic_read(&mdev->rs_pending_cnt) > number) + goto requeue; + number -= atomic_read(&mdev->rs_pending_cnt); + + for (i = 0; i < number; i++) { +next_sector: + size = BM_BLOCK_SIZE; + /* as of now, we are the only user of drbd_bm_find_next */ + bit = drbd_bm_find_next(mdev); + + if (bit == -1UL) { + /* FIXME either test_and_set some bit, + * or make this the _only_ place that is allowed + * to assign w_resync_inactive! */ + mdev->resync_work.cb = w_resync_inactive; + dec_local(mdev); + return 1; + } + + sector = BM_BIT_TO_SECT(bit); + + if (drbd_try_rs_begin_io(mdev, sector)) { + drbd_bm_set_find(mdev, bit); + goto requeue; + } + + if (unlikely(drbd_bm_test_bit(mdev, bit) == 0 )) { + drbd_rs_complete_io(mdev, sector); + goto next_sector; + } + +#if DRBD_MAX_SEGMENT_SIZE > BM_BLOCK_SIZE + /* try to find some adjacent bits. + * we stop if we have already the maximum req size. + * + * Aditionally always align bigger requests, in order to + * be prepared for all stripe sizes of software RAIDs. + * + * we _do_ care about the agreed-uppon q->max_segment_size + * here, as splitting up the requests on the other side is more + * difficult. the consequence is, that on lvm and md and other + * "indirect" devices, this is dead code, since + * q->max_segment_size will be PAGE_SIZE. + */ + align = 1; + for (;;) { + if (size + BM_BLOCK_SIZE > max_segment_size) + break; + + /* Be always aligned */ + if (sector & ((1<<(align+3))-1) ) + break; + + /* do not cross extent boundaries */ + if (( (bit+1) & BM_BLOCKS_PER_BM_EXT_MASK ) == 0) + break; + /* now, is it actually dirty, after all? + * caution, drbd_bm_test_bit is tri-state for some + * obscure reason; ( b == 0 ) would get the out-of-band + * only accidentally right because of the "oddly sized" + * adjustment below */ + if ( drbd_bm_test_bit(mdev, bit+1) != 1 ) + break; + bit++; + size += BM_BLOCK_SIZE; + if ( (BM_BLOCK_SIZE< BM_BLOCK_SIZE) + drbd_bm_set_find(mdev, bit+1); +#endif + + /* adjust very last sectors, in case we are oddly sized */ + if (sector + (size>>9) > capacity) + size = (capacity-sector)<<9; + inc_rs_pending(mdev); + if (!drbd_send_drequest(mdev, RSDataRequest, + sector, size, ID_SYNCER)) { + ERR("drbd_send_drequest() failed, aborting...\n"); + dec_rs_pending(mdev); + dec_local(mdev); + return 0; + } + } + + if (drbd_bm_rs_done(mdev)) { + /* last syncer _request_ was sent, + * but the RSDataReply not yet received. sync will end (and + * next sync group will resume), as soon as we receive the last + * resync data block, and the last bit is cleared. + * until then resync "work" is "inactive" ... + */ + mdev->resync_work.cb = w_resync_inactive; + dec_local(mdev); + return 1; + } + + requeue: + mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME); + dec_local(mdev); + return 1; +} + +int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work* w,int cancel) +{ + int number,i,size; + sector_t sector; + const sector_t capacity = drbd_get_capacity(mdev->this_bdev); + + if(unlikely(cancel)) return 1; + + if (unlikely(mdev->state.conn < Connected)) { + ERR("Confused in w_make_ov_request()! cstate < Connected"); + return 0; + } + + number = SLEEP_TIME*mdev->sync_conf.rate / ((BM_BLOCK_SIZE/1024)*HZ); + if (atomic_read(&mdev->rs_pending_cnt)>number) { + goto requeue; + } + number -= atomic_read(&mdev->rs_pending_cnt); + + sector = mdev->ov_position; + for(i=0;iov_position = sector; + goto requeue; + } + + if (sector + (size>>9) > capacity) size = (capacity-sector)<<9; + + inc_rs_pending(mdev); + if(!drbd_send_ov_request(mdev, sector, size)) { + dec_rs_pending(mdev); + return 0; + } + sector += BM_SECT_PER_BIT; + if(sector >= capacity) { + mdev->resync_work.cb = w_resync_inactive; + + return 1; + } + } + mdev->ov_position = sector; + + requeue: + mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME); + return 1; +} + + +int w_ov_finished(struct drbd_conf *mdev, struct drbd_work* w,int cancel) +{ + kfree(w); + ov_oos_print(mdev); + drbd_resync_finished(mdev); + + return 1; +} + +STATIC int w_resync_finished(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + kfree(w); + + drbd_resync_finished(mdev); + + return 1; +} + +int drbd_resync_finished(struct drbd_conf *mdev) +{ + unsigned long db,dt,dbdt; + union drbd_state_t os, ns; + struct drbd_work *w; + int art = 0; + + /* Remove all elements from the resync LRU. Since future actions + * might set bits in the (main) bitmap, then the entries in the + * resync LRU would be wrong. */ + if (drbd_rs_del_all(mdev)) { + /* In case this is not possible now, most probabely because + * there are RSDataReply Packets lingering on the worker's + * queue (or even the read operations for those packets + * is not finished by now). Retry in 100ms. */ + + drbd_kick_lo(mdev); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 10); + w = kmalloc(sizeof(struct drbd_work), GFP_ATOMIC); + if (w) { + w->cb = w_resync_finished; + drbd_queue_work(&mdev->data.work, w); + return 1; + } + ERR("Warn failed to drbd_rs_del_all() and to kmalloc(w).\n"); + } + + dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ; + if (dt <= 0) + dt = 1; + db = mdev->rs_total; + dbdt = Bit2KB(db/dt); + mdev->rs_paused /= HZ; + + if (!inc_local(mdev)) + goto out; + + spin_lock_irq(&mdev->req_lock); + os = mdev->state; + + /* This protects us against multiple calls (that can happen in the presence + of application IO), and against connectivity loss just before we arrive here. */ + if (os.conn <= Connected) + goto out_unlock; + + ns = os; + ns.conn = Connected; + + INFO("%s done (total %lu sec; paused %lu sec; %lu K/sec)\n", + (os.conn == VerifyS || os.conn == VerifyT) ? + "Online verify ": "Resync", + dt + mdev->rs_paused, mdev->rs_paused, dbdt); + + if (os.conn == VerifyS || os.conn == VerifyT) { + if (drbd_bm_total_weight(mdev)) { + ALERT("Online verify found %lu %dk block out of sync!\n", + drbd_bm_total_weight(mdev),BM_BLOCK_SIZE/1024); + drbd_khelper(mdev,"out-of-sync"); + } + } else { + D_ASSERT((drbd_bm_total_weight(mdev)-mdev->rs_failed) == 0); + } + + if (mdev->rs_failed) { + INFO(" %lu failed blocks\n", mdev->rs_failed); + + if (os.conn == SyncTarget || os.conn == PausedSyncT) { + ns.disk = Inconsistent; + ns.pdsk = UpToDate; + } else { + ns.disk = UpToDate; + ns.pdsk = Inconsistent; + } + } else { + ns.disk = UpToDate; + ns.pdsk = UpToDate; + + if (os.conn == SyncTarget || os.conn == PausedSyncT) { + if (mdev->p_uuid) { + int i; + for (i = Bitmap ; i <= History_end ; i++) + _drbd_uuid_set(mdev, i, mdev->p_uuid[i]); + drbd_uuid_set(mdev, Bitmap, mdev->bc->md.uuid[Current]); + _drbd_uuid_set(mdev, Current, mdev->p_uuid[Current]); + } else { + ERR("mdev->p_uuid is NULL! BUG\n"); + } + } + + drbd_uuid_set_bm(mdev, 0UL); + + if (mdev->p_uuid) { + /* Now the two UUID sets are equal, update what we + * know of the peer. */ + int i; + for (i = Current ; i <= History_end ; i++) + mdev->p_uuid[i] = mdev->bc->md.uuid[i]; + } + } + + art = os.conn == SyncTarget || os.conn == PausedSyncT; + + _drbd_set_state(mdev, ns, ChgStateVerbose, NULL); + out_unlock: + spin_unlock_irq(&mdev->req_lock); + dec_local(mdev); + out: + mdev->rs_total = 0; + mdev->rs_failed = 0; + mdev->rs_paused = 0; + + if (test_and_clear_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags)) { + DRBD_WARN("Writing the whole bitmap, due to failed kmalloc\n"); + drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL); + } + + drbd_bm_recount_bits(mdev); + + if (art) + drbd_khelper(mdev, "after-resync-target"); + + return 1; +} + +/** + * w_e_end_data_req: Send the answer (DataReply) in response to a DataRequest. + */ +int w_e_end_data_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct Tl_epoch_entry *e = (struct Tl_epoch_entry *)w; + int ok; + + if (unlikely(cancel)) { + drbd_free_ee(mdev, e); + dec_unacked(mdev); + return 1; + } + + if (likely(drbd_bio_uptodate(e->private_bio))) { + ok = drbd_send_block(mdev, DataReply, e); + } else { + if (DRBD_ratelimit(5*HZ, 5)) + ERR("Sending NegDReply. sector=%llus.\n", + (unsigned long long)e->sector); + + ok = drbd_send_ack(mdev, NegDReply, e); + + /* FIXME we should not detach for read io-errors, in particular + * not now: when the peer asked us for our data, we are likely + * the only remaining disk... */ + drbd_io_error(mdev, FALSE); + } + + dec_unacked(mdev); + + spin_lock_irq(&mdev->req_lock); + if (drbd_bio_has_active_page(e->private_bio)) { + /* This might happen if sendpage() has not finished */ + list_add_tail(&e->w.list, &mdev->net_ee); + } else { + drbd_free_ee(mdev, e); + } + spin_unlock_irq(&mdev->req_lock); + + if (unlikely(!ok)) ERR("drbd_send_block() failed\n"); + return ok; +} + +/** + * w_e_end_rsdata_req: Send the answer (RSDataReply) to a RSDataRequest. + */ +int w_e_end_rsdata_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct Tl_epoch_entry *e = (struct Tl_epoch_entry *)w; + int ok; + + if (unlikely(cancel)) { + drbd_free_ee(mdev, e); + dec_unacked(mdev); + return 1; + } + + if (inc_local_if_state(mdev, Failed)) { + drbd_rs_complete_io(mdev, e->sector); + dec_local(mdev); + } + + if (likely(drbd_bio_uptodate(e->private_bio))) { + if (likely( mdev->state.pdsk >= Inconsistent )) { + inc_rs_pending(mdev); + ok = drbd_send_block(mdev, RSDataReply, e); + } else { + if (DRBD_ratelimit(5*HZ, 5)) + ERR("Not sending RSDataReply, " + "partner DISKLESS!\n"); + ok = 1; + } + } else { + if (DRBD_ratelimit(5*HZ, 5)) + ERR("Sending NegRSDReply. sector %llus.\n", + (unsigned long long)e->sector); + + ok = drbd_send_ack(mdev, NegRSDReply, e); + + drbd_io_error(mdev, FALSE); + + /* update resync data with failure */ + drbd_rs_failed_io(mdev, e->sector, e->size); + } + + dec_unacked(mdev); + + spin_lock_irq(&mdev->req_lock); + if (drbd_bio_has_active_page(e->private_bio)) { + /* This might happen if sendpage() has not finished */ + list_add_tail(&e->w.list, &mdev->net_ee); + } else { + drbd_free_ee(mdev, e); + } + spin_unlock_irq(&mdev->req_lock); + + if (unlikely(!ok)) ERR("drbd_send_block() failed\n"); + return ok; +} + + +int w_e_end_ov_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct Tl_epoch_entry *e = (struct Tl_epoch_entry*)w; + int digest_size; + void *digest; + int ok=1; + + if(unlikely(cancel)) { + drbd_free_ee(mdev,e); + dec_unacked(mdev); + return 1; + } + + if(likely(drbd_bio_uptodate(e->private_bio))) { + digest_size = crypto_hash_digestsize(mdev->verify_tfm); + digest = kmalloc(digest_size,GFP_KERNEL); + if(digest) { + drbd_csum(mdev,mdev->verify_tfm,e->private_bio,digest); + ok = drbd_send_drequest_csum(mdev, e->sector, e->size, + digest, digest_size, OVReply); + if (ok) inc_rs_pending(mdev); + kfree(digest); + } + } + + dec_unacked(mdev); + + spin_lock_irq(&mdev->req_lock); + drbd_free_ee(mdev,e); + spin_unlock_irq(&mdev->req_lock); + + return ok; +} + +void drbd_ov_oos_found(struct drbd_conf *mdev, sector_t sector, int size) +{ + if (mdev->ov_last_oos_start + mdev->ov_last_oos_size == sector) { + mdev->ov_last_oos_size += size>>9; + } else { + mdev->ov_last_oos_start = sector; + mdev->ov_last_oos_size = size>>9; + } + drbd_set_out_of_sync(mdev, sector, size); + set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags); +} + +int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct Tl_epoch_entry *e = (struct Tl_epoch_entry*)w; + struct digest_info *di; + int digest_size; + void *digest; + int ok,eq=0; + + if(unlikely(cancel)) { + drbd_free_ee(mdev,e); + dec_unacked(mdev); + return 1; + } + + /* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all + * the resync lru has been cleaned up already */ + drbd_rs_complete_io(mdev,e->sector); + + di = (struct digest_info *)(unsigned long)e->block_id; + + if(likely(drbd_bio_uptodate(e->private_bio))) { + digest_size = crypto_hash_digestsize(mdev->verify_tfm); + digest = kmalloc(digest_size,GFP_KERNEL); + if(digest) { + drbd_csum(mdev, mdev->verify_tfm, e->private_bio, digest); + + D_ASSERT(digest_size == di->digest_size); + eq = !memcmp(digest, di->digest, digest_size); + kfree(digest); + } + } else { + ok=drbd_send_ack(mdev,NegRSDReply,e); + if (DRBD_ratelimit(5*HZ,5)) + ERR("Sending NegDReply. I guess it gets messy.\n"); + drbd_io_error(mdev, FALSE); + } + + dec_unacked(mdev); + + kfree(di); + + if (!eq) drbd_ov_oos_found(mdev,e->sector,e->size); + else ov_oos_print(mdev); + + ok = drbd_send_ack_ex(mdev,OVResult,e->sector,e->size, + eq ? ID_IN_SYNC : ID_OUT_OF_SYNC); + + spin_lock_irq(&mdev->req_lock); + drbd_free_ee(mdev,e); + spin_unlock_irq(&mdev->req_lock); + + if( --mdev->ov_left == 0 ) { + ov_oos_print(mdev); + drbd_resync_finished(mdev); + } + + return ok; +} + + +int w_prev_work_done(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + clear_bit(WORK_PENDING, &mdev->flags); + wake_up(&mdev->misc_wait); + return 1; +} + +int w_send_barrier(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct drbd_barrier *b = (struct drbd_barrier *)w; + struct Drbd_Barrier_Packet *p = &mdev->data.sbuf.Barrier; + int ok = 1; + + /* really avoid racing with tl_clear. w.cb may have been referenced + * just before it was reassigned and requeued, so double check that. + * actually, this race was harmless, since we only try to send the + * barrier packet here, and otherwise do nothing with the object. + * but compare with the head of w_clear_epoch */ + spin_lock_irq(&mdev->req_lock); + if (w->cb != w_send_barrier || mdev->state.conn < Connected) + cancel = 1; + spin_unlock_irq(&mdev->req_lock); + if (cancel) + return 1; + + if (!drbd_get_data_sock(mdev)) + return 0; + p->barrier = b->br_number; + /* inc_ap_pending was done where this was queued. + * dec_ap_pending will be done in got_BarrierAck + * or (on connection loss) in w_clear_epoch. */ + ok = _drbd_send_cmd(mdev, mdev->data.socket, Barrier, + (struct Drbd_Header *)p, sizeof(*p), 0); + drbd_put_data_sock(mdev); + + return ok; +} + +int w_send_write_hint(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + if (cancel) + return 1; + return drbd_send_short_cmd(mdev, UnplugRemote); +} + +/** + * w_send_dblock: Send a mirrored write request. + */ +int w_send_dblock(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct drbd_request *req = (struct drbd_request *)w; + int ok; + + if (unlikely(cancel)) { + req_mod(req, send_canceled, 0); + return 1; + } + + ok = drbd_send_dblock(mdev, req); + req_mod(req, ok ? handed_over_to_network : send_failed, 0); + + return ok; +} + +/** + * w_send_read_req: Send a read requests. + */ +int w_send_read_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct drbd_request *req = (struct drbd_request *)w; + int ok; + + if (unlikely(cancel)) { + req_mod(req, send_canceled, 0); + return 1; + } + + ok = drbd_send_drequest(mdev, DataRequest, req->sector, req->size, + (unsigned long)req); + + if (ok) { + req_mod(req, handed_over_to_network, 0); + } else { + /* ?? we set Timeout or BrokenPipe in drbd_send() */ + if (mdev->state.conn >= Connected) + drbd_force_state(mdev, NS(conn, NetworkFailure)); + /* req_mod(req, send_failed); we should not fail it here, + * we might have to "freeze" on disconnect. + * handled by req_mod(req, connection_lost_while_pending); + * in drbd_fail_pending_reads soon enough. */ + } + + return ok; +} + +STATIC void drbd_global_lock(void) __acquires(drbd_global_lock) +{ + struct drbd_conf *mdev; + int i; + + __acquire(drbd_global_lock); + local_irq_disable(); + for (i = 0; i < minor_count; i++) { + mdev = minor_to_mdev(i); + if (!mdev) + continue; + spin_lock(&mdev->req_lock); + __release(&mdev->req_lock); /* annihilate the spin_lock's annotation here */ + } +} + +STATIC void drbd_global_unlock(void) __releases(drbd_global_lock) +{ + struct drbd_conf *mdev; + int i; + + for (i = 0; i < minor_count; i++) { + mdev = minor_to_mdev(i); + if (!mdev) + continue; + __acquire(&mdev->req_lock); + spin_unlock(&mdev->req_lock); + } + local_irq_enable(); + __release(drbd_global_lock); +} + +STATIC int _drbd_may_sync_now(struct drbd_conf *mdev) +{ + struct drbd_conf *odev = mdev; + + while (1) { + if (odev->sync_conf.after == -1) + return 1; + odev = minor_to_mdev(odev->sync_conf.after); + ERR_IF(!odev) return 1; + if ( (odev->state.conn >= SyncSource && + odev->state.conn <= PausedSyncT) || + odev->state.aftr_isp || odev->state.peer_isp || + odev->state.user_isp ) return 0; + } +} + +/** + * _drbd_pause_after: + * Finds all devices that may not resync now, and causes them to + * pause their resynchronisation. + * Called from process context only ( ioctl and after_state_ch ). + */ +STATIC int _drbd_pause_after(struct drbd_conf *mdev) +{ + struct drbd_conf *odev; + int i, rv = 0; + + for (i = 0; i < minor_count; i++) { + odev = minor_to_mdev(i); + if (!odev) + continue; + if (odev->state.conn == StandAlone && odev->state.disk == Diskless) + continue; + if (!_drbd_may_sync_now(odev)) + rv |= ( _drbd_set_state(_NS(odev, aftr_isp, 1), ChgStateHard, NULL) + != SS_NothingToDo ) ; + } + + return rv; +} + +/** + * _drbd_resume_next: + * Finds all devices that can resume resynchronisation + * process, and causes them to resume. + * Called from process context only ( ioctl and worker ). + */ +STATIC int _drbd_resume_next(struct drbd_conf *mdev) +{ + struct drbd_conf *odev; + int i, rv = 0; + + for (i = 0; i < minor_count; i++) { + odev = minor_to_mdev(i); + if (!odev) + continue; + if (odev->state.aftr_isp) { + if (_drbd_may_sync_now(odev)) + rv |= (_drbd_set_state(_NS(odev, aftr_isp, 0), + ChgStateHard, NULL) + != SS_NothingToDo) ; + } + } + return rv; +} + +void resume_next_sg(struct drbd_conf *mdev) +{ + drbd_global_lock(); + _drbd_resume_next(mdev); + drbd_global_unlock(); +} + +void suspend_other_sg(struct drbd_conf *mdev) +{ + drbd_global_lock(); + _drbd_pause_after(mdev); + drbd_global_unlock(); +} + +void drbd_alter_sa(struct drbd_conf *mdev, int na) +{ + int changes; + + drbd_global_lock(); + mdev->sync_conf.after = na; + + do { + changes = _drbd_pause_after(mdev); + changes |= _drbd_resume_next(mdev); + } while (changes); + + drbd_global_unlock(); +} + +/** + * drbd_start_resync: + * @side: Either SyncSource or SyncTarget + * Start the resync process. Called from process context only, + * either ioctl or drbd_receiver. + * Note, this function might bring you directly into one of the + * PausedSync* states. + */ +void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) +{ + union drbd_state_t ns; + int r; + + MTRACE(TraceTypeResync, TraceLvlSummary, + INFO("Resync starting: side=%s\n", + side == SyncTarget?"SyncTarget":"SyncSource"); + ); + + drbd_bm_recount_bits(mdev); + + /* In case a previous resync run was aborted by an IO error... */ + drbd_rs_cancel_all(mdev); + + if (side == SyncTarget) { + /* Since application IO was locked out during WFBitMapT and + WFSyncUUID we are still unmodified. Before going to SyncTarget + we check that we might make the data inconsistent. */ + r = drbd_khelper(mdev, "before-resync-target"); + r = (r >> 8) & 0xff; + if (r > 0) { + INFO("before-resync-target handler returned %d, " + "dropping connection.\n", r); + drbd_force_state(mdev, NS(conn, Disconnecting)); + return; + } + } + + drbd_state_lock(mdev); + + if (!inc_local_if_state(mdev, Negotiating)) { + drbd_state_unlock(mdev); + return; + } + + if (side == SyncTarget) { + drbd_bm_reset_find(mdev); + } else /* side == SyncSource */ { + u64 uuid; + + get_random_bytes(&uuid, sizeof(u64)); + drbd_uuid_set(mdev, Bitmap, uuid); + drbd_send_sync_uuid(mdev, uuid); + + D_ASSERT(mdev->state.disk == UpToDate); + } + + drbd_global_lock(); + ns = mdev->state; + + ns.aftr_isp = !_drbd_may_sync_now(mdev); + + ns.conn = side; + + if (side == SyncTarget) + ns.disk = Inconsistent; + else /* side == SyncSource */ + ns.pdsk = Inconsistent; + + r = _drbd_set_state(mdev, ns, ChgStateVerbose, NULL); + ns = mdev->state; + + if (ns.conn < Connected) + r = SS_UnknownError; + + if (r == SS_Success) { + mdev->rs_total = + mdev->rs_mark_left = drbd_bm_total_weight(mdev); + mdev->rs_failed = 0; + mdev->rs_paused = 0; + mdev->rs_start = + mdev->rs_mark_time = jiffies; + _drbd_pause_after(mdev); + } + drbd_global_unlock(); + drbd_state_unlock(mdev); + dec_local(mdev); + + if (r == SS_Success) { + INFO("Began resync as %s (will sync %lu KB [%lu bits set]).\n", + conns_to_name(ns.conn), + (unsigned long) mdev->rs_total << (BM_BLOCK_SIZE_B-10), + (unsigned long) mdev->rs_total); + + if (mdev->rs_total == 0) { + drbd_resync_finished(mdev); + return; + } + + if (ns.conn == SyncTarget) { + D_ASSERT(!test_bit(STOP_SYNC_TIMER, &mdev->flags)); + mod_timer(&mdev->resync_timer, jiffies); + } + + drbd_md_sync(mdev); + } +} + +int drbd_worker(struct Drbd_thread *thi) +{ + struct drbd_conf *mdev = thi->mdev; + struct drbd_work *w = NULL; + LIST_HEAD(work_list); + int intr = 0, i; + + sprintf(current->comm, "drbd%d_worker", mdev_to_minor(mdev)); + set_cpus_allowed(current, drbd_calc_cpu_mask(mdev)); + + while (get_t_state(thi) == Running) { + + if (down_trylock(&mdev->data.work.s)) { + down(&mdev->data.mutex); + if (mdev->data.socket) + drbd_tcp_flush(mdev->data.socket); + up(&mdev->data.mutex); + + intr = down_interruptible(&mdev->data.work.s); + + down(&mdev->data.mutex); + if (mdev->data.socket) + drbd_tcp_cork(mdev->data.socket); + up(&mdev->data.mutex); + } + + if (intr) { + D_ASSERT(intr == -EINTR); + flush_signals(current); + ERR_IF (get_t_state(thi) == Running) + continue; + break; + } + + if (get_t_state(thi) != Running) break; + /* With this break, we have done a down() but not consumed + the entry from the list. The cleanup code takes care of + this... */ + + w = NULL; + spin_lock_irq(&mdev->data.work.q_lock); + ERR_IF(list_empty(&mdev->data.work.q)) { + /* something terribly wrong in our logic. + * we were able to down() the semaphore, + * but the list is empty... doh. + * + * what is the best thing to do now? + * try again from scratch, restarting the receiver, + * asender, whatnot? could break even more ugly, + * e.g. when we are primary, but no good local data. + * + * I'll try to get away just starting over this loop. + */ + spin_unlock_irq(&mdev->data.work.q_lock); + continue; + } + w = list_entry(mdev->data.work.q.next, struct drbd_work, list); + list_del_init(&w->list); + spin_unlock_irq(&mdev->data.work.q_lock); + + if (!w->cb(mdev, w, mdev->state.conn < Connected )) { + /* DRBD_WARN("worker: a callback failed! \n"); */ + if (mdev->state.conn >= Connected) + drbd_force_state(mdev, + NS(conn, NetworkFailure)); + } + } + + spin_lock_irq(&mdev->data.work.q_lock); + i = 0; + while (!list_empty(&mdev->data.work.q)) { + list_splice_init(&mdev->data.work.q, &work_list); + spin_unlock_irq(&mdev->data.work.q_lock); + + while (!list_empty(&work_list)) { + w = list_entry(work_list.next, struct drbd_work, list); + list_del_init(&w->list); + w->cb(mdev, w, 1); + i++; /* dead debugging code */ + } + + spin_lock_irq(&mdev->data.work.q_lock); + } + sema_init(&mdev->data.work.s, 0); + /* DANGEROUS race: if someone did queue his work within the spinlock, + * but up() ed outside the spinlock, we could get an up() on the + * semaphore without corresponding list entry. + * So don't do that. + */ + spin_unlock_irq(&mdev->data.work.q_lock); + /* FIXME verify that there absolutely can not be any more work + * on the queue now... + * if so, the comment above is no longer true, but historic + * from the times when the worker did not live as long as the + * device.. */ + + D_ASSERT(mdev->state.disk == Diskless && mdev->state.conn == StandAlone); + drbd_mdev_cleanup(mdev); + + INFO("worker terminated\n"); + + return 0; +} --- linux-2.6.27.orig/ubuntu/drbd/drbd_req.c +++ linux-2.6.27/ubuntu/drbd/drbd_req.c @@ -0,0 +1,1274 @@ +/* +-*- linux-c -*- + drbd_req.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 1999-2008, Philipp Reisner . + Copyright (C) 2002-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include +#include + +#include +#include +#include "drbd_int.h" +#include "drbd_req.h" + +/* outside of the ifdef + * because of the _print_rq_state(,FIXME) in barrier_acked */ +STATIC void _print_rq_state(struct drbd_request *req, const char *txt) +{ + const unsigned long s = req->rq_state; + struct drbd_conf *mdev = req->mdev; + const int rw = (req->master_bio == NULL || + bio_data_dir(req->master_bio) == WRITE) ? + 'W' : 'R'; + + INFO("%s %p %c L%c%c%cN%c%c%c%c%c %u (%llus +%u) %s\n", + txt, req, rw, + s & RQ_LOCAL_PENDING ? 'p' : '-', + s & RQ_LOCAL_COMPLETED ? 'c' : '-', + s & RQ_LOCAL_OK ? 'o' : '-', + s & RQ_NET_PENDING ? 'p' : '-', + s & RQ_NET_QUEUED ? 'q' : '-', + s & RQ_NET_SENT ? 's' : '-', + s & RQ_NET_DONE ? 'd' : '-', + s & RQ_NET_OK ? 'o' : '-', + req->epoch, + (unsigned long long)req->sector, + req->size, + conns_to_name(mdev->state.conn)); +} + +/* #define VERBOSE_REQUEST_CODE */ +#if defined(VERBOSE_REQUEST_CODE) || defined(ENABLE_DYNAMIC_TRACE) +STATIC void _print_req_mod(struct drbd_request *req, enum drbd_req_event what) +{ + struct drbd_conf *mdev = req->mdev; + const int rw = (req->master_bio == NULL || + bio_data_dir(req->master_bio) == WRITE) ? + 'W' : 'R'; + + static const char *rq_event_names[] = { + [created] = "created", + [to_be_send] = "to_be_send", + [to_be_submitted] = "to_be_submitted", + [queue_for_net_write] = "queue_for_net_write", + [queue_for_net_read] = "queue_for_net_read", + [send_canceled] = "send_canceled", + [send_failed] = "send_failed", + [handed_over_to_network] = "handed_over_to_network", + [connection_lost_while_pending] = + "connection_lost_while_pending", + [recv_acked_by_peer] = "recv_acked_by_peer", + [write_acked_by_peer] = "write_acked_by_peer", + [neg_acked] = "neg_acked", + [conflict_discarded_by_peer] = "conflict_discarded_by_peer", + [barrier_acked] = "barrier_acked", + [data_received] = "data_received", + [read_completed_with_error] = "read_completed_with_error", + [write_completed_with_error] = "write_completed_with_error", + [completed_ok] = "completed_ok", + }; + + INFO("_req_mod(%p %c ,%s)\n", req, rw, rq_event_names[what]); +} + +# ifdef ENABLE_DYNAMIC_TRACE +# define print_rq_state(R, T) \ + MTRACE(TraceTypeRq, TraceLvlMetrics, _print_rq_state(R, T);) +# define print_req_mod(T, W) \ + MTRACE(TraceTypeRq, TraceLvlMetrics, _print_req_mod(T, W);) +# else +# define print_rq_state(R, T) _print_rq_state(R, T) +# define print_req_mod(T, W) _print_req_mod(T, W) +# endif + +#else +#define print_rq_state(R, T) +#define print_req_mod(T, W) +#endif + +/* We only support diskstats for 2.6.16 and up. + * see also commit commit a362357b6cd62643d4dda3b152639303d78473da + * Author: Jens Axboe + * Date: Tue Nov 1 09:26:16 2005 +0100 + * [BLOCK] Unify the seperate read/write io stat fields into arrays */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) +#define _drbd_start_io_acct(...) do {} while (0) +#define _drbd_end_io_acct(...) do {} while (0) +#else + +/* Update disk stats at start of I/O request */ +static inline void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req, struct bio *bio) +{ + const int rw = bio_data_dir(bio); + + MUST_HOLD(&mdev->req_lock) + __disk_stat_inc(mdev->vdisk, ios[rw]); + __disk_stat_add(mdev->vdisk, sectors[rw], bio_sectors(bio)); + disk_round_stats(mdev->vdisk); + mdev->vdisk->in_flight++; +} + +/* Update disk stats when completing request upwards */ +static inline void _drbd_end_io_acct(struct drbd_conf *mdev, struct drbd_request *req) +{ + int rw = bio_data_dir(req->master_bio); + unsigned long duration = jiffies - req->start_time; + + MUST_HOLD(&mdev->req_lock) + __disk_stat_add(mdev->vdisk, ticks[rw], duration); + disk_round_stats(mdev->vdisk); + mdev->vdisk->in_flight--; +} + +#endif + +static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const int rw) +{ + const unsigned long s = req->rq_state; + /* if it was a write, we may have to set the corresponding + * bit(s) out-of-sync first. If it had a local part, we need to + * release the reference to the activity log. */ + if (rw == WRITE) { + /* remove it from the transfer log. + * well, only if it had been there in the first + * place... if it had not (local only or conflicting + * and never sent), it should still be "empty" as + * initialised in drbd_req_new(), so we can list_del() it + * here unconditionally */ + list_del(&req->tl_requests); + /* Set out-of-sync unless both OK flags are set + * (local only or remote failed). + * Other places where we set out-of-sync: + * READ with local io-error */ + if (!(s & RQ_NET_OK) || !(s & RQ_LOCAL_OK)) + drbd_set_out_of_sync(mdev, req->sector, req->size); + + if ((s & RQ_NET_OK) && (s & RQ_LOCAL_OK) && (s & RQ_NET_SIS)) + drbd_set_in_sync(mdev, req->sector, req->size); + + /* one might be tempted to move the drbd_al_complete_io + * to the local io completion callback drbd_endio_pri. + * but, if this was a mirror write, we may only + * drbd_al_complete_io after this is RQ_NET_DONE, + * otherwise the extent could be dropped from the al + * before it has actually been written on the peer. + * if we crash before our peer knows about the request, + * but after the extent has been dropped from the al, + * we would forget to resync the corresponding extent. + */ + if (s & RQ_LOCAL_MASK) { + if (inc_local_if_state(mdev, Failed)) { + drbd_al_complete_io(mdev, req->sector); + dec_local(mdev); + } else { + DRBD_WARN("Should have called drbd_al_complete_io(, %llu), " + "but my Disk seems to have failed :(\n", + (unsigned long long) req->sector); + } + } + } + + /* if it was a local io error, we want to notify our + * peer about that, and see if we need to + * detach the disk and stuff. + * to avoid allocating some special work + * struct, reuse the request. */ + + /* THINK + * why do we do this not when we detect the error, + * but delay it until it is "done", i.e. possibly + * until the next barrier ack? */ + + if (rw == WRITE && + (( s & RQ_LOCAL_MASK) && !(s & RQ_LOCAL_OK))) { + if (!(req->w.list.next == LIST_POISON1 || + list_empty(&req->w.list))) { + /* DEBUG ASSERT only; if this triggers, we + * probably corrupt the worker list here */ + DUMPP(req->w.list.next); + DUMPP(req->w.list.prev); + } + req->w.cb = w_io_error; + drbd_queue_work(&mdev->data.work, &req->w); + /* drbd_req_free() is done in w_io_error */ + } else { + drbd_req_free(req); + } +} + +static void queue_barrier(struct drbd_conf *mdev) +{ + struct drbd_barrier *b; + + /* We are within the req_lock. Once we queued the barrier for sending, + * we set the CREATE_BARRIER bit. It is cleared as soon as a new + * barrier/epoch object is added. This is the only place this bit is + * set. It indicates that the barrier for this epoch is already queued, + * and no new epoch has been created yet. */ + if (test_bit(CREATE_BARRIER, &mdev->flags)) + return; + + b = mdev->newest_barrier; + b->w.cb = w_send_barrier; + /* inc_ap_pending done here, so we won't + * get imbalanced on connection loss. + * dec_ap_pending will be done in got_BarrierAck + * or (on connection loss) in tl_clear. */ + inc_ap_pending(mdev); + drbd_queue_work(&mdev->data.work, &b->w); + set_bit(CREATE_BARRIER, &mdev->flags); +} + +static void _about_to_complete_local_write(struct drbd_conf *mdev, + struct drbd_request *req) +{ + const unsigned long s = req->rq_state; + struct drbd_request *i; + struct Tl_epoch_entry *e; + struct hlist_node *n; + struct hlist_head *slot; + + /* before we can signal completion to the upper layers, + * we may need to close the current epoch */ + if (mdev->state.conn >= Connected && + req->epoch == mdev->newest_barrier->br_number) + queue_barrier(mdev); + + /* we need to do the conflict detection stuff, + * if we have the ee_hash (two_primaries) and + * this has been on the network */ + if ((s & RQ_NET_DONE) && mdev->ee_hash != NULL) { + const sector_t sector = req->sector; + const int size = req->size; + + /* ASSERT: + * there must be no conflicting requests, since + * they must have been failed on the spot */ +#define OVERLAPS overlaps(sector, size, i->sector, i->size) + slot = tl_hash_slot(mdev, sector); + hlist_for_each_entry(i, n, slot, colision) { + if (OVERLAPS) { + ALERT("LOGIC BUG: completed: %p %llus +%u; " + "other: %p %llus +%u\n", + req, (unsigned long long)sector, size, + i, (unsigned long long)i->sector, i->size); + } + } + + /* maybe "wake" those conflicting epoch entries + * that wait for this request to finish. + * + * currently, there can be only _one_ such ee + * (well, or some more, which would be pending + * DiscardAck not yet sent by the asender...), + * since we block the receiver thread upon the + * first conflict detection, which will wait on + * misc_wait. maybe we want to assert that? + * + * anyways, if we found one, + * we just have to do a wake_up. */ +#undef OVERLAPS +#define OVERLAPS overlaps(sector, size, e->sector, e->size) + slot = ee_hash_slot(mdev, req->sector); + hlist_for_each_entry(e, n, slot, colision) { + if (OVERLAPS) { + wake_up(&mdev->misc_wait); + break; + } + } + } +#undef OVERLAPS +} + +static void _complete_master_bio(struct drbd_conf *mdev, + struct drbd_request *req, int error) +{ + dump_bio(mdev, req->master_bio, 1); + bio_endio(req->master_bio, error); + req->master_bio = NULL; + dec_ap_bio(mdev); +} + +void _req_may_be_done(struct drbd_request *req, int error) +{ + const unsigned long s = req->rq_state; + struct drbd_conf *mdev = req->mdev; + int rw; + + print_rq_state(req, "_req_may_be_done"); + MUST_HOLD(&mdev->req_lock) + + /* we must not complete the master bio, while it is + * still being processed by _drbd_send_zc_bio (drbd_send_dblock) + * not yet acknowledged by the peer + * not yet completed by the local io subsystem + * these flags may get cleared in any order by + * the worker, + * the receiver, + * the bio_endio completion callbacks. + */ + if (s & RQ_NET_QUEUED) + return; + if (s & RQ_NET_PENDING) + return; + if (s & RQ_LOCAL_PENDING) + return; + + if (req->master_bio) { + /* this is data_received (remote read) + * or protocol C WriteAck + * or protocol B RecvAck + * or protocol A "handed_over_to_network" (SendAck) + * or canceled or failed, + * or killed from the transfer log due to connection loss. + */ + + /* + * figure out whether to report success or failure. + * + * report success when at least one of the operations suceeded. + * or, to put the other way, + * only report failure, when both operations failed. + * + * what to do about the failures is handled elsewhere. + * what we need to do here is just: complete the master_bio. + */ + int ok = (s & RQ_LOCAL_OK) || (s & RQ_NET_OK); + rw = bio_data_dir(req->master_bio); + + /* remove the request from the conflict detection + * respective block_id verification hash */ + if (!hlist_unhashed(&req->colision)) + hlist_del(&req->colision); + else + D_ASSERT((s & RQ_NET_MASK) == 0); + + /* for writes we need to do some extra housekeeping */ + if (rw == WRITE) + _about_to_complete_local_write(mdev, req); + + /* FIXME not yet implemented... + * in case we got "suspended" (on_disconnect: freeze io) + * we may not yet complete the request... + * though, this is probably best handled elsewhere by not + * walking the transfer log until "unfreeze", so we won't end + * up here anyways during the freeze ... + * then again, if it is a READ, it is not in the TL at all. + * is it still leagal to complete a READ during freeze? */ + + /* Update disk stats */ + _drbd_end_io_acct(mdev, req); + + _complete_master_bio(mdev,req, + ok ? 0 : ( error ? error : -EIO ) ); + } else { + /* only WRITE requests can end up here without a master_bio */ + rw = WRITE; + } + + if ((s & RQ_NET_MASK) == 0 || (s & RQ_NET_DONE)) { + /* this is disconnected (local only) operation, + * or protocol C WriteAck, + * or protocol A or B BarrierAck, + * or killed from the transfer log due to connection loss. */ + _req_is_done(mdev, req, rw); + } + /* else: network part and not DONE yet. that is + * protocol A or B, barrier ack still pending... */ +} + +/* + * checks whether there was an overlapping request + * or ee already registered. + * + * if so, return 1, in which case this request is completed on the spot, + * without ever being submitted or send. + * + * return 0 if it is ok to submit this request. + * + * NOTE: + * paranoia: assume something above us is broken, and issues different write + * requests for the same block simultaneously... + * + * To ensure these won't be reordered differently on both nodes, resulting in + * diverging data sets, we discard the later one(s). Not that this is supposed + * to happen, but this is the rationale why we also have to check for + * conflicting requests with local origin, and why we have to do so regardless + * of whether we allowed multiple primaries. + * + * BTW, in case we only have one primary, the ee_hash is empty anyways, and the + * second hlist_for_each_entry becomes a noop. This is even simpler than to + * grab a reference on the net_conf, and check for the two_primaries flag... + */ +STATIC int _req_conflicts(struct drbd_request *req) +{ + struct drbd_conf *mdev = req->mdev; + const sector_t sector = req->sector; + const int size = req->size; + struct drbd_request *i; + struct Tl_epoch_entry *e; + struct hlist_node *n; + struct hlist_head *slot; + + MUST_HOLD(&mdev->req_lock); + D_ASSERT(hlist_unhashed(&req->colision)); + + /* FIXME should this inc_net/dec_net + * rather be done in drbd_make_request_common? */ + if (!inc_net(mdev)) + return 0; + + /* BUG_ON */ + ERR_IF (mdev->tl_hash_s == 0) + goto out_no_conflict; + BUG_ON(mdev->tl_hash == NULL); + +#define OVERLAPS overlaps(i->sector, i->size, sector, size) + slot = tl_hash_slot(mdev, sector); + hlist_for_each_entry(i, n, slot, colision) { + if (OVERLAPS) { + ALERT("%s[%u] Concurrent local write detected! " + "[DISCARD L] new: %llus +%u; " + "pending: %llus +%u\n", + current->comm, current->pid, + (unsigned long long)sector, size, + (unsigned long long)i->sector, i->size); + goto out_conflict; + } + } + + if (mdev->ee_hash_s) { + /* now, check for overlapping requests with remote origin */ + BUG_ON(mdev->ee_hash == NULL); +#undef OVERLAPS +#define OVERLAPS overlaps(e->sector, e->size, sector, size) + slot = ee_hash_slot(mdev, sector); + hlist_for_each_entry(e, n, slot, colision) { + if (OVERLAPS) { + ALERT("%s[%u] Concurrent remote write detected!" + " [DISCARD L] new: %llus +%u; " + "pending: %llus +%u\n", + current->comm, current->pid, + (unsigned long long)sector, size, + (unsigned long long)e->sector, e->size); + goto out_conflict; + } + } + } +#undef OVERLAPS + +out_no_conflict: + /* this is like it should be, and what we expected. + * our users do behave after all... */ + dec_net(mdev); + return 0; + +out_conflict: + dec_net(mdev); + return 1; +} + +/* obviously this could be coded as many single functions + * instead of one huge switch, + * or by putting the code directly in the respective locations + * (as it has been before). + * + * but having it this way + * enforces that it is all in this one place, where it is easier to audit, + * it makes it obvious that whatever "event" "happens" to a request should + * happen "atomically" within the req_lock, + * and it enforces that we have to think in a very structured manner + * about the "events" that may happen to a request during its life time ... + * + * Though I think it is likely that we break this again into many + * static inline void _req_mod_ ## what (req) ... + */ +void _req_mod(struct drbd_request *req, enum drbd_req_event what, int error) +{ + struct drbd_conf *mdev = req->mdev; + MUST_HOLD(&mdev->req_lock); + + if (error && (bio_rw(req->master_bio) != READA)) + ERR("got an _req_mod() errno of %d\n", error); + + print_req_mod(req, what); + + switch (what) { + default: + ERR("LOGIC BUG in %s:%u\n", __FILE__ , __LINE__ ); + return; + + /* does not happen... + * initialization done in drbd_req_new + case created: + break; + */ + + case to_be_send: /* via network */ + /* reached via drbd_make_request_common + * and from FIXME w_read_retry_remote */ + D_ASSERT(!(req->rq_state & RQ_NET_MASK)); + req->rq_state |= RQ_NET_PENDING; + inc_ap_pending(mdev); + break; + + case to_be_submitted: /* locally */ + /* reached via drbd_make_request_common */ + D_ASSERT(!(req->rq_state & RQ_LOCAL_MASK)); + req->rq_state |= RQ_LOCAL_PENDING; + break; + + /* FIXME these *_completed_* are basically the same. + * can probably be merged with some if (what == xy) */ + + case completed_ok: + if (bio_data_dir(req->private_bio) == WRITE) + mdev->writ_cnt += req->size>>9; + else + mdev->read_cnt += req->size>>9; + + bio_put(req->private_bio); + req->private_bio = NULL; + + req->rq_state |= (RQ_LOCAL_COMPLETED|RQ_LOCAL_OK); + req->rq_state &= ~RQ_LOCAL_PENDING; + + _req_may_be_done(req, error); + dec_local(mdev); + break; + + case write_completed_with_error: + req->rq_state |= RQ_LOCAL_COMPLETED; + req->rq_state &= ~RQ_LOCAL_PENDING; + + bio_put(req->private_bio); + req->private_bio = NULL; + ALERT("Local WRITE failed sec=%llus size=%u\n", + (unsigned long long)req->sector, req->size); + /* and now: check how to handle local io error. + * FIXME see comment below in read_completed_with_error */ + __drbd_chk_io_error(mdev, FALSE); + _req_may_be_done(req, error); + dec_local(mdev); + break; + + case read_completed_with_error: + if (bio_rw(req->master_bio) != READA) + drbd_set_out_of_sync(mdev, req->sector, req->size); + + req->rq_state |= RQ_LOCAL_COMPLETED; + req->rq_state &= ~RQ_LOCAL_PENDING; + + bio_put(req->private_bio); + req->private_bio = NULL; + if (bio_rw(req->master_bio) == READA) { + /* it is legal to fail READA */ + _req_may_be_done(req, error); + dec_local(mdev); + break; + } + /* else */ + ALERT("Local READ failed sec=%llus size=%u\n", + (unsigned long long)req->sector, req->size); + /* _req_mod(req,to_be_send); oops, recursion in static inline */ + D_ASSERT(!(req->rq_state & RQ_NET_MASK)); + req->rq_state |= RQ_NET_PENDING; + inc_ap_pending(mdev); + + /* and now: check how to handle local io error. + * + * FIXME we should not handle WRITE and READ io errors + * the same. When we retry the READ, and then write + * the answer, that might suceed because modern drives + * would relocate the sectors. We'd need to keep our + * private bio then, and round the offset and size so + * we get back enough data to be able to clear the bits again. + */ + __drbd_chk_io_error(mdev, FALSE); + dec_local(mdev); + /* NOTE: if we have no connection, + * or know the peer has no good data either, + * then we don't actually need to "queue_for_net_read", + * but we do so anyways, since the drbd_io_error() + * and the potential state change to "Diskless" + * needs to be done from process context */ + + /* fall through: _req_mod(req,queue_for_net_read); */ + + case queue_for_net_read: + /* READ or READA, and + * no local disk, + * or target area marked as invalid, + * or just got an io-error. */ + /* from drbd_make_request_common + * or from bio_endio during read io-error recovery */ + + /* so we can verify the handle in the answer packet + * corresponding hlist_del is in _req_may_be_done() */ + hlist_add_head(&req->colision, ar_hash_slot(mdev, req->sector)); + + set_bit(UNPLUG_REMOTE, &mdev->flags); /* why? */ + + D_ASSERT(req->rq_state & RQ_NET_PENDING); + req->rq_state |= RQ_NET_QUEUED; + req->w.cb = (req->rq_state & RQ_LOCAL_MASK) + ? w_read_retry_remote + : w_send_read_req; + drbd_queue_work(&mdev->data.work, &req->w); + break; + + case queue_for_net_write: + /* assert something? */ + /* from drbd_make_request_common only */ + + hlist_add_head(&req->colision, tl_hash_slot(mdev, req->sector)); + /* corresponding hlist_del is in _req_may_be_done() */ + + /* NOTE + * In case the req ended up on the transfer log before being + * queued on the worker, it could lead to this request being + * missed during cleanup after connection loss. + * So we have to do both operations here, + * within the same lock that protects the transfer log. + * + * _req_add_to_epoch(req); this has to be after the + * _maybe_start_new_epoch(req); which happened in + * drbd_make_request_common, because we now may set the bit + * again ourselves to close the current epoch. + * + * Add req to the (now) current epoch (barrier). */ + + /* see drbd_make_request_common, + * just after it grabs the req_lock */ + D_ASSERT(test_bit(CREATE_BARRIER, &mdev->flags) == 0); + + req->epoch = mdev->newest_barrier->br_number; + list_add_tail(&req->tl_requests, + &mdev->newest_barrier->requests); + + /* increment size of current epoch */ + mdev->newest_barrier->n_req++; + + /* queue work item to send data */ + D_ASSERT(req->rq_state & RQ_NET_PENDING); + req->rq_state |= RQ_NET_QUEUED; + req->w.cb = w_send_dblock; + drbd_queue_work(&mdev->data.work, &req->w); + + /* close the epoch, in case it outgrew the limit */ + if (mdev->newest_barrier->n_req >= mdev->net_conf->max_epoch_size) + queue_barrier(mdev); + + break; + + /* FIXME + * to implement freeze-io, + * we may not finish the request just yet. + */ + case send_canceled: + /* may be a write, may be a remote read */ + if (req->rq_state & RQ_NET_PENDING) dec_ap_pending(mdev); + req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING); + /* fall through */ + case send_failed: + /* real cleanup will be done from tl_clear. just update flags + * so it is no longer marked as on the worker queue */ + req->rq_state &= ~RQ_NET_QUEUED; + /* if we did it right, tl_clear should be scheduled only after + * this, so this should not be necessary! */ + _req_may_be_done(req, error); + break; + + case handed_over_to_network: + /* assert something? */ + if ( bio_data_dir(req->master_bio) == WRITE && + mdev->net_conf->wire_protocol == DRBD_PROT_A ) { + /* this is what is dangerous about protocol A: + * pretend it was sucessfully written on the peer. + * FIXME in case we get a local io-error in + * protocol != C, we might want to defer comletion + * until we get the barrier ack, and send a NegAck + * in case the other node had an io-error, too... + * That way we would at least not report "success" + * if it was not written at all. */ + if (req->rq_state & RQ_NET_PENDING) { + dec_ap_pending(mdev); + req->rq_state &= ~RQ_NET_PENDING; + req->rq_state |= RQ_NET_OK; + } /* else: neg-ack was faster... */ + /* it is still not yet RQ_NET_DONE until the + * corresponding epoch barrier got acked as well, + * so we know what to dirty on connection loss */ + } + req->rq_state &= ~RQ_NET_QUEUED; + req->rq_state |= RQ_NET_SENT; + /* because _drbd_send_zc_bio could sleep, and may want to + * dereference the bio even after the "write_acked_by_peer" and + * "completed_ok" events came in, once we return from + * _drbd_send_zc_bio (drbd_send_dblock), we have to check + * whether it is done already, and end it. */ + _req_may_be_done(req, error); + break; + + case connection_lost_while_pending: + /* transfer log cleanup after connection loss */ + /* assert something? */ + if (req->rq_state & RQ_NET_PENDING) + dec_ap_pending(mdev); + req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING); + req->rq_state |= RQ_NET_DONE; + /* if it is still queued, we may not complete it here. + * it will be canceled soon. + * FIXME we should change the code so this can not happen. */ + if (!(req->rq_state & RQ_NET_QUEUED)) + _req_may_be_done(req, error); + break; + + case write_acked_by_peer_and_sis: + req->rq_state |= RQ_NET_SIS; + case conflict_discarded_by_peer: + /* for discarded conflicting writes of multiple primarys, + * there is no need to keep anything in the tl, potential + * node crashes are covered by the activity log. */ + req->rq_state |= RQ_NET_DONE; + /* fall through */ + case write_acked_by_peer: + /* protocol C; successfully written on peer. + * Nothing to do here. + * We want to keep the tl in place for all protocols, to cater + * for volatile write-back caches on lower level devices. + * + * A barrier request is expected to have forced all prior + * requests onto stable storage, so completion of a barrier + * request could set NET_DONE right here, and not wait for the + * BarrierAck, but that is an unecessary optimisation. */ + + /* this makes it effectively the same as for: */ + case recv_acked_by_peer: + /* protocol B; pretends to be sucessfully written on peer. + * see also notes above in handed_over_to_network about + * protocol != C */ + req->rq_state |= RQ_NET_OK; + D_ASSERT(req->rq_state & RQ_NET_PENDING); + dec_ap_pending(mdev); + req->rq_state &= ~RQ_NET_PENDING; + _req_may_be_done(req, error); + break; + + case neg_acked: + /* assert something? */ + if (req->rq_state & RQ_NET_PENDING) + dec_ap_pending(mdev); + req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING); + /* FIXME THINK! is it DONE now, or is it not? */ + req->rq_state |= RQ_NET_DONE; + _req_may_be_done(req, error); + /* else: done by handed_over_to_network */ + break; + + case barrier_acked: + if (req->rq_state & RQ_NET_PENDING) { + /* barrier came in before all requests have been acked. + * this is bad, because if the connection is lost now, + * we won't be able to clean them up... */ + _print_rq_state(req, + "FIXME (barrier_acked but pending)"); + } + D_ASSERT(req->rq_state & RQ_NET_SENT); + req->rq_state |= RQ_NET_DONE; + _req_may_be_done(req, error); + break; + + case data_received: + D_ASSERT(req->rq_state & RQ_NET_PENDING); + dec_ap_pending(mdev); + req->rq_state &= ~RQ_NET_PENDING; + req->rq_state |= (RQ_NET_OK|RQ_NET_DONE); + _req_may_be_done(req, error); + break; + }; +} + +/* we may do a local read if: + * - we are consistent (of course), + * - or we are generally inconsistent, + * BUT we are still/already IN SYNC for this area. + * since size may be bigger than BM_BLOCK_SIZE, + * we may need to check several bits. + */ +STATIC int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int size) +{ + unsigned long sbnr, ebnr; + sector_t esector, nr_sectors; + + if (mdev->state.disk == UpToDate) + return 1; + if (mdev->state.disk >= Outdated) + return 0; + if (mdev->state.disk < Inconsistent) + return 0; + /* state.disk == Inconsistent We will have a look at the BitMap */ + nr_sectors = drbd_get_capacity(mdev->this_bdev); + esector = sector + (size>>9) -1; + + D_ASSERT(sector < nr_sectors); + D_ASSERT(esector < nr_sectors); + + sbnr = BM_SECT_TO_BIT(sector); + ebnr = BM_SECT_TO_BIT(esector); + + return (0 == drbd_bm_count_bits(mdev, sbnr, ebnr)); +} + +/* + * general note: + * looking at the state (conn, disk, susp, pdsk) outside of the spinlock that + * protects the state changes is inherently racy. + * + * FIXME verify this rationale why we may do so anyways: + * + * I think it "should" be like this: + * as soon as we have a "ap_bio_cnt" reference we may test for "bad" states, + * because the transition from "bad" to "good" states may only happen while no + * application request is on the fly, so once we are positive about a "bad" + * state, we know it won't get better during the lifetime of this request. + * + * In case we think we are ok, but "asynchronously" some interrupt or other + * thread marks some operation as impossible, we are still ok, since we would + * just try anyways, and then see that it does not work there and then. + */ + +STATIC int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) +{ + const int rw = bio_rw(bio); + const int size = bio->bi_size; + const sector_t sector = bio->bi_sector; + struct drbd_barrier *b = NULL; + struct drbd_request *req; + int local, remote; + int err = -EIO; + + /* allocate outside of all locks; get a "reference count" (ap_bio_cnt) + * to avoid races with the disconnect/reconnect code. */ + inc_ap_bio(mdev); + req = drbd_req_new(mdev, bio); + if (!req) { + dec_ap_bio(mdev); + /* only pass the error to the upper layers. + * if user cannot handle io errors, thats not our business. */ + ERR("could not kmalloc() req\n"); + bio_endio(bio, -ENOMEM); + return 0; + } + + dump_bio(mdev, bio, 0); + + local = inc_local(mdev); + if (!local) { + bio_put(req->private_bio); /* or we get a bio leak */ + req->private_bio = NULL; + } + if (rw == WRITE) { + remote = 1; + } else { + /* READ || READA */ + if (local) { + if (!drbd_may_do_local_read(mdev, sector, size)) { + /* we could kick the syncer to + * sync this extent asap, wait for + * it, then continue locally. + * Or just issue the request remotely. + */ + /* FIXME + * I think we have a RACE here. We request + * something from the peer, then later some + * write starts ... and finished *before* + * the answer to the read comes in, because + * the ACK for the WRITE goes over + * meta-socket ... + * Maybe we need to properly lock reads + * against the syncer, too. But if we have + * some user issuing writes on an area that + * he has pending reads on, _he_ is really + * broke anyways, and would get "undefined + * results" on _any_ io stack, even just the + * local io stack. + */ + + local = 0; + bio_put(req->private_bio); + req->private_bio = NULL; + dec_local(mdev); + } + } + remote = !local && mdev->state.pdsk >= UpToDate; + } + + /* If we have a disk, but a READA request is mapped to remote, + * we are Primary, Inconsistent, SyncTarget. + * Just fail that READA request right here. + * + * THINK: maybe fail all READA when not local? + * or make this configurable... + * if network is slow, READA won't do any good. + */ + if (rw == READA && mdev->state.disk >= Inconsistent && !local) { + err = -EWOULDBLOCK; + goto fail_and_free_req; + } + + /* For WRITES going to the local disk, grab a reference on the target + * extent. This waits for any resync activity in the corresponding + * resync extent to finish, and, if necessary, pulls in the target + * extent into the activity log, which involves further disk io because + * of transactional on-disk meta data updates. */ + if (rw == WRITE && local) + drbd_al_begin_io(mdev, sector); + + remote = remote && (mdev->state.pdsk == UpToDate || + ( mdev->state.pdsk == Inconsistent && + mdev->state.conn >= Connected ) ); + + if (!(local || remote)) { + ERR("IO ERROR: neither local nor remote disk\n"); + goto fail_and_free_req; + } + + /* For WRITE request, we have to make sure that we have an + * unused_spare_barrier, in case we need to start a new epoch. + * I try to be smart and avoid to pre-allocate always "just in case", + * but there is a race between testing the bit and pointer outside the + * spinlock, and grabbing the spinlock. + * if we lost that race, we retry. */ + if (rw == WRITE && remote && + mdev->unused_spare_barrier == NULL && + test_bit(CREATE_BARRIER, &mdev->flags)) { +allocate_barrier: + b = kmalloc(sizeof(struct drbd_barrier), GFP_NOIO); + if (!b) { + ERR("Failed to alloc barrier.\n"); + err = -ENOMEM; + goto fail_and_free_req; + } + } + + /* GOOD, everything prepared, grab the spin_lock */ + spin_lock_irq(&mdev->req_lock); + + /* FIXME race with drbd_disconnect and tl_clear? */ + if (remote) { + remote = (mdev->state.pdsk == UpToDate || + ( mdev->state.pdsk == Inconsistent && + mdev->state.conn >= Connected ) ); + if (!remote) + DRBD_WARN("lost connection while grabbing the req_lock!\n"); + if (!(local || remote)) { + ERR("IO ERROR: neither local nor remote disk\n"); + spin_unlock_irq(&mdev->req_lock); + goto fail_and_free_req; + } + } + + if (b && mdev->unused_spare_barrier == NULL) { + mdev->unused_spare_barrier = b; + b = NULL; + } + if (rw == WRITE && remote && + mdev->unused_spare_barrier == NULL && + test_bit(CREATE_BARRIER, &mdev->flags)) { + /* someone closed the current epoch + * while we were grabbing the spinlock */ + spin_unlock_irq(&mdev->req_lock); + goto allocate_barrier; + } + + + /* Update disk stats */ + _drbd_start_io_acct(mdev, req, bio); + + /* _maybe_start_new_epoch(mdev); + * If we need to generate a write barrier packet, we have to add the + * new epoch (barrier) object, and queue the barrier packet for sending, + * and queue the req's data after it _within the same lock_, otherwise + * we have race conditions were the reorder domains could be mixed up. + * + * Even read requests may start a new epoch and queue the corresponding + * barrier packet. To get the write ordering right, we only have to + * make sure that, if this is a write request and it triggered a + * barrier packet, this request is queued within the same spinlock. */ + if (remote && mdev->unused_spare_barrier && + test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { + _tl_add_barrier(mdev, mdev->unused_spare_barrier); + mdev->unused_spare_barrier = NULL; + } else { + D_ASSERT(!(remote && rw == WRITE && + test_bit(CREATE_BARRIER, &mdev->flags))); + } + + /* NOTE + * Actually, 'local' may be wrong here already, since we may have failed + * to write to the meta data, and may become wrong anytime because of + * local io-error for some other request, which would lead to us + * "detaching" the local disk. + * + * 'remote' may become wrong any time because the network could fail. + * + * This is a harmless race condition, though, since it is handled + * correctly at the appropriate places; so it just deferres the failure + * of the respective operation. + */ + + /* mark them early for readability. + * this just sets some state flags. */ + if (remote) + _req_mod(req, to_be_send, 0); + if (local) + _req_mod(req, to_be_submitted, 0); + + /* check this request on the colison detection hash tables. + * if we have a conflict, just complete it here. + * THINK do we want to check reads, too? (I don't think so...) */ + if (rw == WRITE && _req_conflicts(req)) { + /* this is a conflicting request. + * even though it may have been only _partially_ + * overlapping with one of the currently pending requests, + * without even submitting or sending it, we will + * pretend that it was successfully served right now. + */ + if (local) { + bio_put(req->private_bio); + req->private_bio = NULL; + drbd_al_complete_io(mdev, req->sector); + dec_local(mdev); + local = 0; + } + if (remote) + dec_ap_pending(mdev); + _drbd_end_io_acct(mdev, req); + /* THINK: do we want to fail it (-EIO), or pretend success? */ + bio_endio(req->master_bio, 0); + req->master_bio = NULL; + dec_ap_bio(mdev); + drbd_req_free(req); + remote = 0; + } + + /* NOTE remote first: to get the concurrent write detection right, + * we must register the request before start of local IO. */ + if (remote) { + /* either WRITE and Connected, + * or READ, and no local disk, + * or READ, but not in sync. + */ + if (rw == WRITE) + _req_mod(req, queue_for_net_write, 0); + else + _req_mod(req, queue_for_net_read, 0); + } + spin_unlock_irq(&mdev->req_lock); + kfree(b); /* if someone else has beaten us to it... */ + + if (local) { + req->private_bio->bi_bdev = mdev->bc->backing_bdev; + + dump_internal_bio("Pri", mdev, req->private_bio, 0); + + if (FAULT_ACTIVE(mdev, rw==WRITE ? DRBD_FAULT_DT_WR : + (rw==READ ? DRBD_FAULT_DT_RD : + DRBD_FAULT_DT_RA) )) + bio_endio(req->private_bio, -EIO); + else + generic_make_request(req->private_bio); + } + + /* we need to plug ALWAYS since we possibly need to kick lo_dev. + * we plug after submit, so we won't miss an unplug event */ + drbd_plug_device(mdev); + + return 0; + +fail_and_free_req: + kfree(b); + bio_endio(bio, err); + drbd_req_free(req); + return 0; +} + +/* helper function for drbd_make_request + * if we can determine just by the mdev (state) that this request will fail, + * return 1 + * otherwise return 0 + */ +static int drbd_fail_request_early(struct drbd_conf *mdev, int is_write) +{ + /* Unconfigured */ + if (mdev->state.conn == Disconnecting && + mdev->state.disk == Diskless) + return 1; + + if (mdev->state.role != Primary && + ( !allow_oos || is_write) ) { + if (DRBD_ratelimit(5*HZ, 5)) { + ERR("Process %s[%u] tried to %s; " + "since we are not in Primary state, " + "we cannot allow this\n", + current->comm, current->pid, + is_write ? "WRITE" : "READ"); + } + return 1; + } + + /* + * Paranoia: we might have been primary, but sync target, or + * even diskless, then lost the connection. + * This should have been handled (panic? suspend?) somehwere + * else. But maybe it was not, so check again here. + * Caution: as long as we do not have a read/write lock on mdev, + * to serialize state changes, this is racy, since we may lose + * the connection *after* we test for the cstate. + */ + if ( mdev->state.disk < UpToDate && + mdev->state.conn < Connected) { + if (DRBD_ratelimit(5*HZ, 5)) + ERR("Sorry, I have no access to good data anymore.\n"); + /* + * FIXME suspend, loop waiting on cstate wait? + */ + return 1; + } + + return 0; +} + +int drbd_make_request_26(struct request_queue *q, struct bio *bio) +{ + unsigned int s_enr, e_enr; + struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata; + + if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) { + bio_endio(bio, -EPERM); + return 0; + } + + /* Reject barrier requests if we know the underlying device does + * not support them. + * XXX: Need to get this info from peer as well some how so we + * XXX: reject if EITHER side/data/metadata area does not support them. + * + * because of those XXX, this is not yet enabled, + * i.e. in drbd_init_set_defaults we set the NO_BARRIER_SUPP bit. + */ + if (unlikely(bio_barrier(bio) && test_bit(NO_BARRIER_SUPP, &mdev->flags))) { + /* DRBD_WARN("Rejecting barrier request as underlying device does not support\n"); */ + bio_endio(bio, -EOPNOTSUPP); + return 0; + } + + /* + * what we "blindly" assume: + */ + D_ASSERT(bio->bi_size > 0); + D_ASSERT( (bio->bi_size & 0x1ff) == 0); + D_ASSERT(bio->bi_idx == 0); + + /* to make some things easier, force allignment of requests within the + * granularity of our hash tables */ + s_enr = bio->bi_sector >> HT_SHIFT; + e_enr = (bio->bi_sector+(bio->bi_size>>9)-1) >> HT_SHIFT; + + if (unlikely(s_enr != e_enr)) { + if (bio->bi_vcnt != 1 || bio->bi_idx != 0) { + /* rather error out here than BUG in bio_split */ + ERR("bio would need to, but cannot, be split: " + "(vcnt=%u,idx=%u,size=%u,sector=%llu)\n", + bio->bi_vcnt, bio->bi_idx, bio->bi_size, + (unsigned long long)bio->bi_sector); + bio_endio(bio, -EINVAL); + return 0; + } else { + /* This bio crosses some boundary, so we have to split it. */ + struct bio_pair *bp; + /* works for the "do not cross hash slot boundaries" case + * e.g. sector 262269, size 4096 + * s_enr = 262269 >> 6 = 4097 + * e_enr = (262269+8-1) >> 6 = 4098 + * HT_SHIFT = 6 + * sps = 64, mask = 63 + * first_sectors = 64 - (262269 & 63) = 3 + */ + const sector_t sect = bio->bi_sector; + const int sps = 1<bio1); + drbd_make_request_26(q, &bp->bio2); + bio_pair_release(bp); + return 0; + } + } + + return drbd_make_request_common(mdev,bio); +} + +/* This is called by bio_add_page(). With this function we reduce + * the number of BIOs that span over multiple DRBD_MAX_SEGMENT_SIZEs + * units (was AL_EXTENTs). + * + * we do the calculation within the lower 32bit of the byte offsets, + * since we don't care for actual offset, but only check whether it + * would cross "activity log extent" boundaries. + * + * As long as the BIO is emtpy we have to allow at least one bvec, + * regardless of size and offset. so the resulting bio may still + * cross extent boundaries. those are dealt with (bio_split) in + * drbd_make_request_26. + */ +int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec) +{ + struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata; + unsigned int bio_offset = + (unsigned int)bvm->bi_sector << 9; /* 32 bit */ + unsigned int bio_size = bvm->bi_size; + int limit, backing_limit; + + limit = DRBD_MAX_SEGMENT_SIZE + - ((bio_offset & (DRBD_MAX_SEGMENT_SIZE-1)) + bio_size); + if (limit < 0) + limit = 0; + if (bio_size == 0) { + if (limit <= bvec->bv_len) + limit = bvec->bv_len; + } else if (limit && inc_local(mdev)) { + struct request_queue * const b = + mdev->bc->backing_bdev->bd_disk->queue; + if (b->merge_bvec_fn && mdev->bc->dc.use_bmbv) { + backing_limit = b->merge_bvec_fn(b, bvm, bvec); + limit = min(limit, backing_limit); + } + dec_local(mdev); + } + return limit; +} --- linux-2.6.27.orig/ubuntu/drbd/drbd_bitmap.c +++ linux-2.6.27/ubuntu/drbd/drbd_bitmap.c @@ -0,0 +1,1004 @@ +/* +-*- linux-c -*- + drbd_bitmap.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2004-2008, LINBIT Information Technologies GmbH. + Copyright (C) 2004-2008, Philipp Reisner . + Copyright (C) 2004-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include "drbd_int.h" + +/* OPAQUE outside this file! + * interface defined in drbd_int.h + + * convetion: + * function name drbd_bm_... => used elsewhere, "public". + * function name bm_... => internal to implementation, "private". + + * Note that since find_first_bit returns int, at the current granularity of + * the bitmap (4KB per byte), this implementation "only" supports up to + * 1<<(32+12) == 16 TB... + * other shortcomings in the meta data area may reduce this even further. + * + * we will eventually change the implementation to not allways hold the full + * bitmap in memory, but only some 'lru_cache' of the on disk bitmap. + + * THINK + * I'm not yet sure whether this file should be bits only, + * or wether I want it to do all the sector<->bit calculation in here. + */ + +/* + * NOTE + * Access to the *bm is protected by bm_lock. + * It is safe to read the other members within the lock. + * + * drbd_bm_set_bits is called from bio_endio callbacks, + * We may be called with irq already disabled, + * so we need spin_lock_irqsave(). + * FIXME + * for performance reasons, when we _know_ we have irq disabled, we should + * probably introduce some _in_irq variants, so we know to only spin_lock(). + * + * FIXME + * Actually you need to serialize all resize operations. + * but then, resize is a drbd state change, and it should be serialized + * already. Unfortunately it is not (yet), so two concurrent resizes, like + * attach storage (drbdsetup) and receive the peers size (drbd receiver) + * may eventually blow things up. + * Therefore, + * you may only change the other members when holding + * the bm_change mutex _and_ the bm_lock. + * thus reading them holding either is safe. + * this is sort of overkill, but I rather do it right + * than have two resize operations interfere somewhen. + */ +struct drbd_bitmap { + unsigned long *bm; + spinlock_t bm_lock; + /* WARNING unsigned long bm_fo and friends: + * 32bit number of bit offset is just enough for 512 MB bitmap. + * it will blow up if we make the bitmap bigger... + * not that it makes much sense to have a bitmap that large, + * rather change the granularity to 16k or 64k or something. + * (that implies other problems, however...) + */ + unsigned long bm_fo; /* next offset for drbd_bm_find_next */ + unsigned long bm_set; /* nr of set bits; THINK maybe atomic_t? */ + unsigned long bm_bits; + size_t bm_words; + sector_t bm_dev_capacity; + struct semaphore bm_change; /* serializes resize operations */ + + atomic_t bm_async_io; + wait_queue_head_t bm_io_wait; + + unsigned long bm_flags; + + /* debugging aid, in case we are still racy somewhere */ + unsigned long bm_line; + char *bm_file; +}; + +/* definition of bits in bm_flags */ +#define BM_LOCKED 0 +#define BM_MD_IO_ERROR (BITS_PER_LONG-1) /* 31? 63? */ + +void __drbd_bm_lock(struct drbd_conf *mdev, char *file, int line) +{ + struct drbd_bitmap *b = mdev->bitmap; + + spin_lock_irq(&b->bm_lock); + if (!__test_and_set_bit(BM_LOCKED,&b->bm_flags)) { + b->bm_file = file; + b->bm_line = line; + } else if (DRBD_ratelimit(5*HZ,5)) { + ERR("%s:%d: bitmap already locked by %s:%lu\n", + file, line, b->bm_file,b->bm_line); + /* + dump_stack(); + ERR("This is no oops, but debug stack trace only.\n"); + ERR("If you get this often, or in reproducable situations, " + "notify \n"); + */ + } + spin_unlock_irq(&b->bm_lock); +} + +void drbd_bm_unlock(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + spin_lock_irq(&b->bm_lock); + if (!__test_and_clear_bit(BM_LOCKED,&mdev->bitmap->bm_flags)) { + ERR("bitmap not locked in bm_unlock\n"); + } else { + /* FIXME if we got a "is already locked" previously, + * we unlock here even though we actually MUST NOT do so... */ + b->bm_file = NULL; + b->bm_line = -1; + } + spin_unlock_irq(&b->bm_lock); +} + +#if DUMP_MD >= 3 +/* debugging aid */ +void bm_end_info(struct drbd_conf *mdev, const char *where) +{ + struct drbd_bitmap *b = mdev->bitmap; + size_t w = (b->bm_bits-1) >> LN2_BPL; + + INFO("%s: bm_set=%lu\n", where, b->bm_set); + INFO("bm[%d]=0x%lX\n", w, b->bm[w]); + w++; + + if (w < b->bm_words) { + D_ASSERT(w == b->bm_words -1); + INFO("bm[%d]=0x%lX\n", w, b->bm[w]); + } +} +#else +#define bm_end_info(ignored...) ((void)(0)) +#endif + +/* long word offset of _bitmap_ sector */ +#define S2W(s) ((s)<<(BM_EXT_SIZE_B-BM_BLOCK_SIZE_B-LN2_BPL)) + +/* + * actually most functions herein should take a struct drbd_bitmap*, not a + * struct drbd_conf*, but for the debug macros I like to have the mdev around + * to be able to report device specific. + */ + +/* FIXME TODO sometimes I use "int offset" as index into the bitmap. + * since we currently are LIMITED to (128<<11)-64-8 sectors of bitmap, + * this is ok [as long as we dont run on a 24 bit arch :)]. + * But it is NOT strictly ok. + */ + +/* + * called on driver init only. TODO call when a device is created. + * allocates the drbd_bitmap, and stores it in mdev->bitmap. + */ +int drbd_bm_init(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + WARN_ON(b != NULL); + b = kzalloc(sizeof(struct drbd_bitmap), GFP_KERNEL); + if (!b) + return -ENOMEM; + spin_lock_init(&b->bm_lock); + init_MUTEX(&b->bm_change); + init_waitqueue_head(&b->bm_io_wait); + + mdev->bitmap = b; + + return 0; +} + +sector_t drbd_bm_capacity(struct drbd_conf *mdev) +{ + ERR_IF(!mdev->bitmap) return 0; + return mdev->bitmap->bm_dev_capacity; +} + +/* called on driver unload. TODO: call when a device is destroyed. + */ +void drbd_bm_cleanup(struct drbd_conf *mdev) +{ + ERR_IF (!mdev->bitmap) return; + /* FIXME I think we should explicitly change the device size to zero + * before this... + * + WARN_ON(mdev->bitmap->bm); + */ + vfree(mdev->bitmap->bm); + kfree(mdev->bitmap); + mdev->bitmap = NULL; +} + +/* + * since (b->bm_bits % BITS_PER_LONG) != 0, + * this masks out the remaining bits. + * Rerturns the number of bits cleared. + */ +STATIC int bm_clear_surplus(struct drbd_bitmap *b) +{ + const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) -1; + size_t w = b->bm_bits >> LN2_BPL; + int cleared = 0; + + if (w < b->bm_words) { + cleared = hweight_long(b->bm[w] & ~mask); + b->bm[w++] &= mask; + } + + if (w < b->bm_words) { + cleared += hweight_long(b->bm[w]); + b->bm[w++] = 0; + } + + return cleared; +} + +STATIC void bm_set_surplus(struct drbd_bitmap *b) +{ + const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) -1; + size_t w = b->bm_bits >> LN2_BPL; + + if (w < b->bm_words) + b->bm[w++] |= ~mask; + + if (w < b->bm_words) + b->bm[w++] = ~(0UL); +} + +STATIC unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endian) +{ + unsigned long *bm = b->bm; + unsigned long *ep = b->bm + b->bm_words; + unsigned long bits = 0; + + while ( bm < ep ) { +#ifndef __LITTLE_ENDIAN + if (swap_endian) *bm = lel_to_cpu(*bm); +#endif + bits += hweight_long(*bm++); + } + + return bits; +} + +static inline unsigned long bm_count_bits(struct drbd_bitmap *b) +{ + return __bm_count_bits(b,0); +} + +static inline unsigned long bm_count_bits_swap_endian(struct drbd_bitmap *b) +{ + return __bm_count_bits(b,1); +} + + +void _drbd_bm_recount_bits(struct drbd_conf *mdev, char* file, int line) +{ + struct drbd_bitmap *b = mdev->bitmap; + unsigned long flags, bits; + + ERR_IF(!b) return; + + spin_lock_irqsave(&b->bm_lock, flags); + bits = bm_count_bits(b); + if (bits != b->bm_set) { + ERR("bm_set was %lu, corrected to %lu. %s:%d\n", + b->bm_set, bits, file, line); + b->bm_set = bits; + } + spin_unlock_irqrestore(&b->bm_lock, flags); +} + +#define BM_SECTORS_PER_BIT (BM_BLOCK_SIZE/512) + +/* + * make sure the bitmap has enough room for the attached storage, + * if neccessary, resize. + * called whenever we may have changed the device size. + * returns -ENOMEM if we could not allocate enough memory, 0 on success. + * In case this is actually a resize, we copy the old bitmap into the new one. + * Otherwise, the bitmap is initiallized to all bits set. + */ +int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity) +{ + struct drbd_bitmap *b = mdev->bitmap; + unsigned long bits, bytes, words, *nbm, *obm = NULL; + int err = 0, growing; + + ERR_IF(!b) return -ENOMEM; + + ERR_IF (down_trylock(&b->bm_change)) { + down(&b->bm_change); + } + + INFO("drbd_bm_resize called with capacity == %llu\n", + (unsigned long long)capacity); + + if (capacity == b->bm_dev_capacity) + goto out; + + if (capacity == 0) { + spin_lock_irq(&b->bm_lock); + obm = b->bm; + b->bm = NULL; + b->bm_fo = + b->bm_set = + b->bm_bits = + b->bm_words = + b->bm_dev_capacity = 0; + spin_unlock_irq(&b->bm_lock); + goto free_obm; + } else { + bits = BM_SECT_TO_BIT(ALIGN(capacity, BM_SECTORS_PER_BIT)); + + /* if we would use + words = ALIGN(bits,BITS_PER_LONG) >> LN2_BPL; + a 32bit host could present the wrong number of words + to a 64bit host. + */ + words = ALIGN(bits, 64) >> LN2_BPL; + + if (inc_local(mdev)) { + D_ASSERT((u64)bits <= (((u64)mdev->bc->md.md_size_sect-MD_BM_OFFSET) << 12)); + dec_local(mdev); + } + + if (words == b->bm_words) { + /* optimize: capacity has changed, + * but only within one long word worth of bits. + * just update the bm_dev_capacity and bm_bits members. + */ + spin_lock_irq(&b->bm_lock); + b->bm_bits = bits; + b->bm_dev_capacity = capacity; + b->bm_set -= bm_clear_surplus(b); + bm_end_info(mdev, __FUNCTION__ ); + spin_unlock_irq(&b->bm_lock); + goto out; + } else { + /* one extra long to catch off by one errors */ + bytes = (words+1)*sizeof(long); + nbm = vmalloc(bytes); + if (!nbm) { + ERR("bitmap: failed to vmalloc %lu bytes\n", + bytes); + err = -ENOMEM; + goto out; + } + } + spin_lock_irq(&b->bm_lock); + obm = b->bm; + /* brgs. move several MB within spinlock... + * FIXME this should go into userspace! */ + if (obm) { + bm_set_surplus(b); + D_ASSERT(b->bm[b->bm_words] == DRBD_MAGIC); + memcpy(nbm, obm, min_t(size_t, b->bm_words, words) + *sizeof(long)); + } + growing = words > b->bm_words; + if (growing) { + /* set all newly allocated bits + * start at -1, just to be sure. */ + memset( nbm + (b->bm_words?:1)-1 , 0xff, + (words - ((b->bm_words?:1)-1)) * sizeof(long) ); + b->bm_set += bits - b->bm_bits; + } + nbm[words] = DRBD_MAGIC; + b->bm = nbm; + b->bm_bits = bits; + b->bm_words = words; + b->bm_dev_capacity = capacity; + bm_clear_surplus(b); + if (!growing) + b->bm_set = bm_count_bits(b); + bm_end_info(mdev, __FUNCTION__ ); + spin_unlock_irq(&b->bm_lock); + INFO("resync bitmap: bits=%lu words=%lu\n", bits, words); + } + free_obm: + vfree(obm); /* vfree(NULL) is noop */ + out: + up(&b->bm_change); + return err; +} + +/* inherently racy: + * if not protected by other means, return value may be out of date when + * leaving this function... + * we still need to lock it, since it is important that this returns + * bm_set == 0 precisely. + * + * maybe bm_set should be atomic_t ? + */ +unsigned long drbd_bm_total_weight(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + unsigned long s; + unsigned long flags; + + ERR_IF(!b) return 0; + + spin_lock_irqsave(&b->bm_lock, flags); + s = b->bm_set; + spin_unlock_irqrestore(&b->bm_lock, flags); + + return s; +} + +size_t drbd_bm_words(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + ERR_IF(!b) return 0; + return b->bm_words; +} + +unsigned long drbd_bm_bits(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + ERR_IF(!b) return 0; + + return b->bm_bits; +} + + +/* merge number words from buffer into the bitmap starting at offset. + * buffer[i] is expected to be little endian unsigned long. + */ +void drbd_bm_merge_lel( struct drbd_conf *mdev, size_t offset, size_t number, + unsigned long *buffer ) +{ + struct drbd_bitmap *b = mdev->bitmap; + unsigned long *bm; + unsigned long word, bits; + size_t n = number; + + if (number == 0) + return; + ERR_IF(!b) return; + ERR_IF(!b->bm) return; + WARN_ON(offset >= b->bm_words); + WARN_ON(offset+number > b->bm_words); + WARN_ON(number > PAGE_SIZE/sizeof(long)); + + spin_lock_irq(&b->bm_lock); + bm = b->bm + offset; + while (n--) { + bits = hweight_long(*bm); + word = *bm | lel_to_cpu(*buffer++); + *bm++ = word; + b->bm_set += hweight_long(word) - bits; + } + /* with 32bit <-> 64bit cross-platform connect + * this is only correct for current usage, + * where we _know_ that we are 64 bit aligned, + * and know that this function is used in this way, too... + */ + if (offset+number == b->bm_words) { + b->bm_set -= bm_clear_surplus(b); + bm_end_info(mdev, __FUNCTION__ ); + } + spin_unlock_irq(&b->bm_lock); +} + +/* copy number words from the bitmap starting at offset into the buffer. + * buffer[i] will be little endian unsigned long. + */ +void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number, + unsigned long *buffer ) +{ + struct drbd_bitmap *b = mdev->bitmap; + unsigned long *bm; + + if (number == 0) + return; + ERR_IF(!b) return; + ERR_IF(!b->bm) return; + if ( (offset >= b->bm_words) || + (offset+number > b->bm_words) || + (number > PAGE_SIZE/sizeof(long)) || + (number <= 0) ) { + /* yes, there is "%z", but that gives compiler warnings... */ + ERR("offset=%lu number=%lu bm_words=%lu\n", + (unsigned long) offset, + (unsigned long) number, + (unsigned long) b->bm_words); + return; + } + + spin_lock_irq(&b->bm_lock); + bm = b->bm + offset; + while (number--) *buffer++ = cpu_to_lel(*bm++); + spin_unlock_irq(&b->bm_lock); +} + +/* set all bits in the bitmap */ +void drbd_bm_set_all(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + ERR_IF(!b) return; + ERR_IF(!b->bm) return; + + spin_lock_irq(&b->bm_lock); + memset(b->bm, 0xff, b->bm_words*sizeof(long)); + bm_clear_surplus(b); + b->bm_set = b->bm_bits; + spin_unlock_irq(&b->bm_lock); +} + +static BIO_ENDIO_TYPE bm_async_io_complete BIO_ENDIO_ARGS(struct bio *bio, int error) +{ + struct drbd_bitmap *b = bio->bi_private; + int uptodate = bio_flagged(bio, BIO_UPTODATE); + + BIO_ENDIO_FN_START; + /* strange behaviour of some lower level drivers... + * fail the request by clearing the uptodate flag, + * but do not return any error?! + * do we want to DRBD_WARN() on this? */ + if (!error && !uptodate) + error = -EIO; + + if (error) { + /* doh. what now? + * for now, set all bits, and flag MD_IO_ERROR + */ + /* FIXME kmap_atomic memset etc. pp. */ + __set_bit(BM_MD_IO_ERROR, &b->bm_flags); + } + if (atomic_dec_and_test(&b->bm_async_io)) + wake_up(&b->bm_io_wait); + + bio_put(bio); + + BIO_ENDIO_FN_RETURN; +} + +STATIC void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int page_nr, int rw) __must_hold(local) +{ + /* we are process context. we always get a bio */ + /* THINK: do we need GFP_NOIO here? */ + struct bio *bio = bio_alloc(GFP_KERNEL, 1); + struct page *page = vmalloc_to_page((char *)(b->bm) + + (PAGE_SIZE*page_nr)); + unsigned int len; + sector_t on_disk_sector = + mdev->bc->md.md_offset + mdev->bc->md.bm_offset; + on_disk_sector += ((sector_t)page_nr) << (PAGE_SHIFT-9); + + /* this might happen with very small + * flexible external meta data device */ + len = min_t(unsigned int, PAGE_SIZE, + (drbd_md_last_sector(mdev->bc) - on_disk_sector + 1)<<9); + + D_DUMPLU(on_disk_sector); + D_DUMPI(len); + + bio->bi_bdev = mdev->bc->md_bdev; + bio->bi_sector = on_disk_sector; + bio_add_page(bio, page, len, 0); + bio->bi_private = b; + bio->bi_end_io = bm_async_io_complete; + + if (FAULT_ACTIVE(mdev, (rw&WRITE)?DRBD_FAULT_MD_WR:DRBD_FAULT_MD_RD)) { + bio->bi_rw |= rw; + bio_endio(bio, -EIO); + } else { + submit_bio(rw, bio); + } +} + +# if defined(__LITTLE_ENDIAN) + /* nothing to do, on disk == in memory */ +# define bm_cpu_to_lel(x) ((void)0) +# else +void bm_cpu_to_lel(struct drbd_bitmap *b) +{ + /* need to cpu_to_lel all the pages ... + * this may be optimized by using + * cpu_to_lel(-1) == -1 and cpu_to_lel(0) == 0; + * the following is still not optimal, but better than nothing */ + const unsigned long *end = b->bm+b->bm_words; + unsigned long *bm; + if (b->bm_set == 0) { + /* no page at all; avoid swap if all is 0 */ + return; + } else if (b->bm_set == b->bm_bits) { + /* only the last words */ + bm = end-2; + } else { + /* all pages */ + bm = b->bm; + } + for (; bm < end; bm++) + *bm = cpu_to_lel(*bm); +} +# endif +/* lel_to_cpu == cpu_to_lel */ +# define bm_lel_to_cpu(x) bm_cpu_to_lel(x) + +/* + * bm_rw: read/write the whole bitmap from/to its on disk location. + */ +STATIC int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) +{ + struct drbd_bitmap *b = mdev->bitmap; + /* sector_t sector; */ + int bm_words, num_pages, i; + unsigned long now; + char ppb[10]; + int err = 0; + + bm_words = drbd_bm_words(mdev); + num_pages = (bm_words*sizeof(long) + PAGE_SIZE-1) >> PAGE_SHIFT; + + /* OK, I manipulate the bitmap low level, + * and I expect to be the exclusive user. + * If not, I am really in a bad mood... + * to catch such bugs early, make all people who want to access the + * bitmap while I read/write it dereference a NULL pointer :-> + */ + mdev->bitmap = NULL; + + /* on disk bitmap is little endian */ + if (rw == WRITE) + bm_cpu_to_lel(b); + + now = jiffies; + atomic_set(&b->bm_async_io, num_pages); + __clear_bit(BM_MD_IO_ERROR, &b->bm_flags); + + /* let the layers below us try to merge these bios... */ + for (i = 0; i < num_pages; i++) + bm_page_io_async(mdev, b, i, rw); + + drbd_blk_run_queue(bdev_get_queue(mdev->bc->md_bdev)); + wait_event(b->bm_io_wait, atomic_read(&b->bm_async_io) == 0); + INFO("%s of bitmap took %lu jiffies\n", + rw == READ ? "reading" : "writing", jiffies - now); + + if (test_bit(BM_MD_IO_ERROR, &b->bm_flags)) { + ALERT("we had at least one MD IO ERROR during bitmap IO\n"); + drbd_chk_io_error(mdev, 1, TRUE); + drbd_io_error(mdev, TRUE); + err = -EIO; + } + + now = jiffies; + if (rw == WRITE) { + /* swap back endianness */ + bm_lel_to_cpu(b); + /* flush bitmap to stable storage */ + if (!test_bit(MD_NO_BARRIER,&mdev->flags)) + blkdev_issue_flush(mdev->bc->md_bdev, NULL); + } else /* rw == READ */ { + /* just read, if neccessary adjust endianness */ + b->bm_set = bm_count_bits_swap_endian(b); + INFO("recounting of set bits took additional %lu jiffies\n", + jiffies - now); + } + now = b->bm_set; + + /* ok, done, + * now it is visible again + */ + + mdev->bitmap = b; + + INFO("%s (%lu bits) marked out-of-sync by on disk bit-map.\n", + ppsize(ppb, now << (BM_BLOCK_SIZE_B-10)), now); + + return err; +} + +/** + * drbd_bm_read: Read the whole bitmap from its on disk location. + * + * currently only called from "drbd_nl_disk_conf" + */ +int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local) +{ + struct drbd_bitmap *b = mdev->bitmap; + int err = 0; + + if (b->bm) { + /* bitmap size > 0 */ + err = bm_rw(mdev, READ); + + if (err == 0) + b->bm[b->bm_words] = DRBD_MAGIC; + } + + return err; +} + +/** + * drbd_bm_write: Write the whole bitmap to its on disk location. + * + * called at various occasions. + */ +int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) +{ + return bm_rw(mdev, WRITE); +} + +/** + * drbd_bm_write_sect: Writes a 512 byte piece of the bitmap to its + * on disk location. On disk bitmap is little endian. + * + * @enr: The _sector_ offset from the start of the bitmap. + * + */ +int drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(local) +{ + sector_t on_disk_sector = enr + mdev->bc->md.md_offset + + mdev->bc->md.bm_offset; + int bm_words, num_words, offset; + int err = 0; + + down(&mdev->md_io_mutex); + bm_words = drbd_bm_words(mdev); + offset = S2W(enr); /* word offset into bitmap */ + num_words = min(S2W(1), bm_words - offset); +#if DUMP_MD >= 3 + INFO("write_sect: sector=%lu offset=%u num_words=%u\n", + enr, offset, num_words); +#endif + if (num_words < S2W(1)) + memset(page_address(mdev->md_io_page), 0, MD_HARDSECT); + drbd_bm_get_lel( mdev, offset, num_words, + page_address(mdev->md_io_page) ); + if (!drbd_md_sync_page_io(mdev, mdev->bc, on_disk_sector, WRITE)) { + int i; + err = -EIO; + ERR( "IO ERROR writing bitmap sector %lu " + "(meta-disk sector %llus)\n", + enr, (unsigned long long)on_disk_sector ); + drbd_chk_io_error(mdev, 1, TRUE); + drbd_io_error(mdev, TRUE); + for (i = 0; i < AL_EXT_PER_BM_SECT; i++) + drbd_bm_ALe_set_all(mdev, enr*AL_EXT_PER_BM_SECT+i); + } + mdev->bm_writ_cnt++; + up(&mdev->md_io_mutex); + return err; +} + +void drbd_bm_reset_find(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + + ERR_IF(!b) return; + + spin_lock_irq(&b->bm_lock); + b->bm_fo = 0; + spin_unlock_irq(&b->bm_lock); + +} + +/* NOTE + * find_first_bit returns int, we return unsigned long. + * should not make much difference anyways, but ... + * this returns a bit number, NOT a sector! + */ +unsigned long drbd_bm_find_next(struct drbd_conf *mdev) +{ + struct drbd_bitmap *b = mdev->bitmap; + unsigned long i = -1UL; + + ERR_IF(!b) return i; + ERR_IF(!b->bm) return i; + + spin_lock_irq(&b->bm_lock); + if (b->bm_fo < b->bm_bits) + i = find_next_bit(b->bm, b->bm_bits, b->bm_fo); + else if (b->bm_fo > b->bm_bits) + ERR("bm_fo=%lu bm_bits=%lu\n", b->bm_fo, b->bm_bits); + + if (i >= b->bm_bits) { + i = -1UL; + /* leave b->bm_fo unchanged. */ + } else { + b->bm_fo = i+1; + } + spin_unlock_irq(&b->bm_lock); + return i; +} + +void drbd_bm_set_find(struct drbd_conf *mdev, unsigned long i) +{ + struct drbd_bitmap *b = mdev->bitmap; + + spin_lock_irq(&b->bm_lock); + + b->bm_fo = min_t(unsigned long, i, b->bm_bits); + + spin_unlock_irq(&b->bm_lock); +} + + +int drbd_bm_rs_done(struct drbd_conf *mdev) +{ + return (mdev->bitmap->bm_fo >= mdev->bitmap->bm_bits); +} + +/* returns number of bits actually changed. + * for val != 0, we change 0 -> 1, return code positiv + * for val == 0, we change 1 -> 0, return code negative + * wants bitnr, not sector */ +static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, + const unsigned long e, int val) +{ + unsigned long flags; + struct drbd_bitmap *b = mdev->bitmap; + unsigned long bitnr; + int c = 0; + ERR_IF(!b) return 1; + ERR_IF(!b->bm) return 1; + + spin_lock_irqsave(&b->bm_lock,flags); + for (bitnr = s; bitnr <= e; bitnr++) { + ERR_IF (bitnr >= b->bm_bits) { + ERR("bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits); + } else { + if (val) + c += (0 == __test_and_set_bit(bitnr, b->bm)); + else + c -= (0 != __test_and_clear_bit(bitnr, b->bm)); + } + } + b->bm_set += c; + spin_unlock_irqrestore(&b->bm_lock, flags); + return c; +} + +/* returns number of bits changed 0 -> 1 */ +int drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e) +{ + return bm_change_bits_to(mdev, s, e, 1); +} + +/* returns number of bits changed 1 -> 0 */ +int drbd_bm_clear_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e) +{ + return -bm_change_bits_to(mdev, s, e, 0); +} + +/* returns bit state + * wants bitnr, NOT sector. + * inherently racy... area needs to be locked by means of {al,rs}_lru + * 1 ... bit set + * 0 ... bit not set + * -1 ... first out of bounds access, stop testing for bits! + */ +int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr) +{ + unsigned long flags; + struct drbd_bitmap *b = mdev->bitmap; + int i; + ERR_IF(!b) return 0; + ERR_IF(!b->bm) return 0; + + spin_lock_irqsave(&b->bm_lock, flags); + if (bitnr < b->bm_bits) { + i = test_bit(bitnr, b->bm) ? 1 : 0; + } else if (bitnr == b->bm_bits) { + i = -1; + } else { /* (bitnr > b->bm_bits) */ + ERR("bitnr=%lu > bm_bits=%lu\n", bitnr, b->bm_bits); + i = 0; + } + + spin_unlock_irqrestore(&b->bm_lock, flags); + return i; +} + +/* returns number of bits set */ +int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e) +{ + unsigned long flags; + struct drbd_bitmap *b = mdev->bitmap; + unsigned long bitnr; + int c = 0; + + /* If this is called without a bitmap, that is a bug. But just to be + * robust in case we screwed up elsewhere, in that case pretend there + * was one dirty bit in the requested area, so we won't try to do a + * local read there (no bitmap probably implies no disk) */ + ERR_IF(!b) return 1; + ERR_IF(!b->bm) return 1; + + spin_lock_irqsave(&b->bm_lock,flags); + for (bitnr = s; bitnr <=e; bitnr++) { + ERR_IF (bitnr >= b->bm_bits) { + ERR("bitnr=%lu bm_bits=%lu\n",bitnr, b->bm_bits); + } else { + c += (0 != test_bit(bitnr, b->bm)); + } + } + spin_unlock_irqrestore(&b->bm_lock,flags); + return c; +} + + +/* inherently racy... + * return value may be already out-of-date when this function returns. + * but the general usage is that this is only use during a cstate when bits are + * only cleared, not set, and typically only care for the case when the return + * value is zero, or we already "locked" this "bitmap extent" by other means. + * + * enr is bm-extent number, since we chose to name one sector (512 bytes) + * worth of the bitmap a "bitmap extent". + * + * TODO + * I think since we use it like a reference count, we should use the real + * reference count of some bitmap extent element from some lru instead... + * + */ +int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr) +{ + struct drbd_bitmap *b = mdev->bitmap; + int count, s, e; + unsigned long flags; + + ERR_IF(!b) return 0; + ERR_IF(!b->bm) return 0; + spin_lock_irqsave(&b->bm_lock, flags); + + s = S2W(enr); + e = min((size_t)S2W(enr+1), b->bm_words); + count = 0; + if (s < b->bm_words) { + const unsigned long *w = b->bm+s; + int n = e-s; + while (n--) count += hweight_long(*w++); + } else { + ERR("start offset (%d) too large in drbd_bm_e_weight\n", s); + } + spin_unlock_irqrestore(&b->bm_lock, flags); +#if DUMP_MD >= 3 + INFO("enr=%lu weight=%d e=%d s=%d\n", enr, count, e, s); +#endif + return count; +} + +/* set all bits covered by the AL-extent al_enr */ +unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr) +{ + struct drbd_bitmap *b = mdev->bitmap; + unsigned long weight; + int count, s, e; + ERR_IF(!b) return 0; + ERR_IF(!b->bm) return 0; + + spin_lock_irq(&b->bm_lock); + weight = b->bm_set; + + s = al_enr * BM_WORDS_PER_AL_EXT; + e = min_t(size_t, s + BM_WORDS_PER_AL_EXT, b->bm_words); + count = 0; + if (s < b->bm_words) { + const unsigned long *w = b->bm+s; + int n = e-s; + while (n--) count += hweight_long(*w++); + n = e-s; + memset(b->bm+s, -1, n*sizeof(long)); + b->bm_set += n*BITS_PER_LONG - count; + if (e == b->bm_words) + b->bm_set -= bm_clear_surplus(b); + } else { + ERR("start offset (%d) too large in drbd_bm_ALe_set_all\n", s); + } + weight = b->bm_set - weight; + spin_unlock_irq(&b->bm_lock); + return weight; +} --- linux-2.6.27.orig/ubuntu/drbd/drbd_main.c +++ linux-2.6.27/ubuntu/drbd/drbd_main.c @@ -0,0 +1,3752 @@ +/* +-*- Linux-c -*- + drbd.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 1999-2008, Philipp Reisner . + Copyright (C) 2002-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __KERNEL_SYSCALLS__ +#include +#include + +#include +#include +#include "drbd_int.h" +#include "drbd_req.h" /* only for _req_mod in tl_release and tl_clear */ + +struct after_state_chg_work { + struct drbd_work w; + union drbd_state_t os; + union drbd_state_t ns; + enum chg_state_flags flags; + struct completion *done; +}; + +int drbdd_init(struct Drbd_thread *); +int drbd_worker(struct Drbd_thread *); +int drbd_asender(struct Drbd_thread *); + +int drbd_init(void); +int drbd_open(struct inode *inode, struct file *file); +int drbd_close(struct inode *inode, struct file *file); +int w_after_state_ch(struct drbd_conf *mdev, struct drbd_work *w, int unused); +static void after_state_ch(struct drbd_conf *mdev, union drbd_state_t os, + union drbd_state_t ns, enum chg_state_flags flags); +int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused); +void md_sync_timer_fn(unsigned long data); + +MODULE_AUTHOR("Philipp Reisner , " + "Lars Ellenberg "); +MODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION); +MODULE_LICENSE("GPL"); +MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices (1-255)"); +MODULE_ALIAS_BLOCKDEV_MAJOR(DRBD_MAJOR); + +#include +/* allow_open_on_secondary */ +MODULE_PARM_DESC(allow_oos, "DONT USE!"); +/* thanks to these macros, if compiled into the kernel (not-module), + * this becomes the boot parameter drbd.minor_count */ +module_param(minor_count, int,0444); +module_param(allow_oos, bool,0); + +#ifdef DRBD_ENABLE_FAULTS +int enable_faults; +int fault_rate; +static int fault_count; +int fault_devs; +/* bitmap of enabled faults */ +module_param(enable_faults, int, 0664); +/* fault rate % value - applies to all enabled faults */ +module_param(fault_rate, int, 0664); +/* count of faults inserted */ +module_param(fault_count, int, 0664); +/* bitmap of devices to insert faults on */ +module_param(fault_devs, int, 0644); +#endif + +/* module parameter, defined */ +int minor_count = 32; +int allow_oos; + +#ifdef ENABLE_DYNAMIC_TRACE +int trace_type; /* Bitmap of trace types to enable */ +int trace_level; /* Current trace level */ +int trace_devs; /* Bitmap of devices to trace */ +int proc_details; /* Detail level in proc drbd*/ + +module_param(trace_level, int, 0644); +module_param(trace_type, int, 0644); +module_param(trace_devs, int, 0644); +module_param(proc_details, int, 0644); +#endif + +/* Module parameter for setting the user mode helper program + * to run. Default is /sbin/drbdadm */ +char usermode_helper[80] = "/sbin/drbdadm"; + +module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0644); + +/* in 2.6.x, our device mapping and config info contains our virtual gendisks + * as member "struct gendisk *vdisk;" + */ +struct drbd_conf **minor_table; + +struct kmem_cache *drbd_request_cache; +struct kmem_cache *drbd_ee_cache; +mempool_t *drbd_request_mempool; +mempool_t *drbd_ee_mempool; + +/* I do not use a standard mempool, because: + 1) I want to hand out the preallocated objects first. + 2) I want to be able to interrupt sleeping allocation with a signal. + Note: This is a single linked list, the next pointer is the private + member of struct page. + */ +struct page *drbd_pp_pool; +spinlock_t drbd_pp_lock; +int drbd_pp_vacant; +wait_queue_head_t drbd_pp_wait; + +STATIC struct block_device_operations drbd_ops = { + .owner = THIS_MODULE, + .open = drbd_open, + .release = drbd_close, +}; + +#define ARRY_SIZE(A) (sizeof(A)/sizeof(A[0])) + +#ifdef __CHECKER__ +/* When checking with sparse, and this is an inline function, sparse will + give tons of false positives. When this is a real functions sparse works. + */ +int _inc_local_if_state(struct drbd_conf* mdev, enum drbd_disk_state mins) +{ + int io_allowed; + + atomic_inc(&mdev->local_cnt); + io_allowed = (mdev->state.disk >= mins ); + if( !io_allowed ) { + if(atomic_dec_and_test(&mdev->local_cnt)) + wake_up(&mdev->misc_wait); + } + return io_allowed; +} + +#endif + +/************************* The transfer log start */ +STATIC int tl_init(struct drbd_conf *mdev) +{ + struct drbd_barrier *b; + + b = kmalloc(sizeof(struct drbd_barrier), GFP_KERNEL); + if (!b) + return 0; + INIT_LIST_HEAD(&b->requests); + INIT_LIST_HEAD(&b->w.list); + b->next = NULL; + b->br_number = 4711; + b->n_req = 0; + b->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */ + + mdev->oldest_barrier = b; + mdev->newest_barrier = b; + + mdev->tl_hash = NULL; + mdev->tl_hash_s = 0; + + return 1; +} + +STATIC void tl_cleanup(struct drbd_conf *mdev) +{ + D_ASSERT(mdev->oldest_barrier == mdev->newest_barrier); + kfree(mdev->oldest_barrier); + kfree(mdev->unused_spare_barrier); + kfree(mdev->tl_hash); + mdev->tl_hash_s = 0; +} + +/** + * _tl_add_barrier: Adds a barrier to the TL. + */ +void _tl_add_barrier(struct drbd_conf *mdev, struct drbd_barrier *new) +{ + struct drbd_barrier *newest_before; + + INIT_LIST_HEAD(&new->requests); + INIT_LIST_HEAD(&new->w.list); + new->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */ + new->next = NULL; + new->n_req = 0; + + newest_before = mdev->newest_barrier; + /* never send a barrier number == 0, because that is special-cased + * when using TCQ for our write ordering code */ + new->br_number = (newest_before->br_number+1) ?: 1; + if (mdev->newest_barrier != new) { + mdev->newest_barrier->next = new; + mdev->newest_barrier = new; + } +} + +/* when we receive a barrier ack */ +void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr, + unsigned int set_size) +{ + struct drbd_barrier *b, *nob; /* next old barrier */ + struct list_head *le, *tle; + struct drbd_request *r; + + spin_lock_irq(&mdev->req_lock); + + b = mdev->oldest_barrier; + + /* Clean up list of requests processed during current epoch */ + list_for_each_safe(le, tle, &b->requests) { + r = list_entry(le, struct drbd_request, tl_requests); + _req_mod(r, barrier_acked, 0); + } + list_del(&b->requests); + /* There could be requests on the list waiting for completion + of the write to the local disk, to avoid corruptions of + slab's data structures we have to remove the lists head */ + + D_ASSERT(b->br_number == barrier_nr); + D_ASSERT(b->n_req == set_size); + +#if 1 + if (b->br_number != barrier_nr) { + DUMPI(b->br_number); + DUMPI(barrier_nr); + } + if (b->n_req != set_size) { + DUMPI(b->n_req); + DUMPI(set_size); + } +#endif + + nob = b->next; + if (test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { + _tl_add_barrier(mdev, b); + if (nob) + mdev->oldest_barrier = nob; + /* if nob == NULL b was the only barrier, and becomes the new + barrer. Threfore mdev->oldest_barrier points already to b */ + } else { + D_ASSERT(nob != NULL); + mdev->oldest_barrier = nob; + kfree(b); + } + + spin_unlock_irq(&mdev->req_lock); +} + + +/* called by drbd_disconnect (exiting receiver thread) + * or from some after_state_ch */ +void tl_clear(struct drbd_conf *mdev) +{ + struct drbd_barrier *b, *tmp; + + DRBD_WARN("tl_clear()\n"); + + spin_lock_irq(&mdev->req_lock); + + b = mdev->oldest_barrier; + while ( b ) { + struct list_head *le, *tle; + struct drbd_request *r; + + list_for_each_safe(le, tle, &b->requests) { + r = list_entry(le, struct drbd_request, tl_requests); + _req_mod(r, connection_lost_while_pending, 0); + } + tmp = b->next; + + /* there could still be requests on that ring list, + * in case local io is still pending */ + list_del(&b->requests); + + /* dec_ap_pending corresponding to queue_barrier. + * the newest barrier may not have been queued yet, + * in which case w.cb is still NULL. */ + if (b->w.cb != NULL) + dec_ap_pending(mdev); + + if (b == mdev->newest_barrier) { + /* recycle, but reinit! */ + D_ASSERT(tmp == NULL); + INIT_LIST_HEAD(&b->requests); + INIT_LIST_HEAD(&b->w.list); + b->w.cb = NULL; + b->br_number = 4711; + b->n_req = 0; + + mdev->oldest_barrier = b; + break; + } + kfree(b); + b = tmp; + } + D_ASSERT(mdev->newest_barrier == mdev->oldest_barrier); + D_ASSERT(mdev->newest_barrier->br_number == 4711); + + /* ensure bit indicating barrier is required is clear */ + clear_bit(CREATE_BARRIER, &mdev->flags); + + spin_unlock_irq(&mdev->req_lock); +} + +/** + * drbd_io_error: Handles the on_io_error setting, should be called in the + * unlikely(!drbd_bio_uptodate(e->bio)) case from kernel thread context. + * See also drbd_chk_io_error + * + * NOTE: we set ourselves FAILED here if on_io_error is Detach or Panic OR + * if the forcedetach flag is set. This flag is set when failures + * occur writing the meta data portion of the disk as they are + * not recoverable. We also try to write the "need full sync bit" here + * anyways. This is to make sure that you get a resynchronisation of + * the full device the next time you connect. + */ +int drbd_io_error(struct drbd_conf *mdev, int forcedetach) +{ + enum io_error_handler eh; + unsigned long flags; + int send; + int ok = 1; + + eh = PassOn; + if (inc_local_if_state(mdev, Failed)) { + eh = mdev->bc->dc.on_io_error; + dec_local(mdev); + } + + if (!forcedetach && eh == PassOn) + return 1; + + spin_lock_irqsave(&mdev->req_lock, flags); + send = (mdev->state.disk == Failed); + if (send) + _drbd_set_state(_NS(mdev, disk, Diskless), ChgStateHard, NULL); + spin_unlock_irqrestore(&mdev->req_lock, flags); + + if (!send) + return ok; + + if (mdev->state.conn >= Connected) { + ok = drbd_send_state(mdev); + if (ok) DRBD_WARN("Notified peer that my disk is broken.\n"); + else ERR("Sending state in drbd_io_error() failed\n"); + } + + /* Make sure we try to flush meta-data to disk - we come + * in here because of a local disk error so it might fail + * but we still need to try -- both because the error might + * be in the data portion of the disk and because we need + * to ensure the md-sync-timer is stopped if running. */ + drbd_md_sync(mdev); + + /* Releasing the backing device is done in after_state_ch() */ + + if (eh == CallIOEHelper) + drbd_khelper(mdev, "local-io-error"); + + return ok; +} + +/** + * cl_wide_st_chg: + * Returns TRUE if this state change should be preformed as a cluster wide + * transaction. Of course it returns 0 as soon as the connection is lost. + */ +STATIC int cl_wide_st_chg(struct drbd_conf *mdev, + union drbd_state_t os, union drbd_state_t ns) +{ + return ( os.conn >= Connected && ns.conn >= Connected && + ( ( os.role != Primary && ns.role == Primary ) || + ( os.conn != StartingSyncT && ns.conn == StartingSyncT ) || + ( os.conn != StartingSyncS && ns.conn == StartingSyncS ) || + ( os.disk != Diskless && ns.disk == Diskless ) ) ) || + (os.conn >= Connected && ns.conn == Disconnecting) || + (os.conn == Connected && ns.conn == VerifyS); +} + +int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f, + union drbd_state_t mask, union drbd_state_t val) +{ + unsigned long flags; + union drbd_state_t os, ns; + int rv; + + spin_lock_irqsave(&mdev->req_lock, flags); + os = mdev->state; + ns.i = (os.i & ~mask.i) | val.i; + rv = _drbd_set_state(mdev, ns, f, NULL); + ns = mdev->state; + spin_unlock_irqrestore(&mdev->req_lock, flags); + + return rv; +} + +void drbd_force_state(struct drbd_conf *mdev, + union drbd_state_t mask, union drbd_state_t val) +{ + drbd_change_state(mdev, ChgStateHard, mask, val); +} + +int is_valid_state(struct drbd_conf *mdev, union drbd_state_t ns); +int is_valid_state_transition(struct drbd_conf *, + union drbd_state_t, union drbd_state_t); +int drbd_send_state_req(struct drbd_conf *, + union drbd_state_t, union drbd_state_t); + +STATIC enum set_st_err _req_st_cond(struct drbd_conf *mdev, + union drbd_state_t mask, union drbd_state_t val) +{ + union drbd_state_t os, ns; + unsigned long flags; + int rv; + + if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &mdev->flags)) + return SS_CW_Success; + + if (test_and_clear_bit(CL_ST_CHG_FAIL, &mdev->flags)) + return SS_CW_FailedByPeer; + + rv = 0; + spin_lock_irqsave(&mdev->req_lock, flags); + os = mdev->state; + ns.i = (os.i & ~mask.i) | val.i; + if ( !cl_wide_st_chg(mdev, os, ns) ) rv = SS_CW_NoNeed; + if (!rv) { + rv = is_valid_state(mdev, ns); + if (rv == SS_Success) { + rv = is_valid_state_transition(mdev, ns, os); + if (rv == SS_Success) + rv = 0; /* cont waiting, otherwise fail. */ + } + } + spin_unlock_irqrestore(&mdev->req_lock, flags); + + return rv; +} + +/** + * _drbd_request_state: + * This function is the most gracefull way to change state. For some state + * transition this function even does a cluster wide transaction. + * It has a cousin named drbd_request_state(), which is always verbose. + */ +STATIC int drbd_req_state(struct drbd_conf *mdev, + union drbd_state_t mask, union drbd_state_t val, + enum chg_state_flags f) +{ + struct completion done; + unsigned long flags; + union drbd_state_t os, ns; + int rv; + + init_completion(&done); + + if (f & ChgSerialize) + mutex_lock(&mdev->state_mutex); + + spin_lock_irqsave(&mdev->req_lock,flags); + os = mdev->state; + ns.i = (os.i & ~mask.i) | val.i; + + if (cl_wide_st_chg(mdev, os, ns)) { + rv = is_valid_state(mdev, ns); + if (rv == SS_Success) + rv = is_valid_state_transition(mdev, ns, os); + spin_unlock_irqrestore(&mdev->req_lock, flags); + + if (rv < SS_Success) { + if (f & ChgStateVerbose) + print_st_err(mdev, os, ns, rv); + goto abort; + } + + drbd_state_lock(mdev); + if ( !drbd_send_state_req(mdev, mask, val) ) { + drbd_state_unlock(mdev); + rv = SS_CW_FailedByPeer; + if (f & ChgStateVerbose) + print_st_err(mdev, os, ns, rv); + goto abort; + } + + wait_event(mdev->state_wait, + (rv = _req_st_cond(mdev, mask, val))); + + if (rv < SS_Success) { + /* nearly dead code. */ + drbd_state_unlock(mdev); + if (f & ChgStateVerbose) + print_st_err(mdev, os, ns, rv); + goto abort; + } + spin_lock_irqsave(&mdev->req_lock, flags); + os = mdev->state; + ns.i = (os.i & ~mask.i) | val.i; + rv = _drbd_set_state(mdev, ns, f, &done); + drbd_state_unlock(mdev); + } else { + rv = _drbd_set_state(mdev, ns, f, &done); + } + + spin_unlock_irqrestore(&mdev->req_lock, flags); + + if (f & ChgWaitComplete && rv == SS_Success) { + D_ASSERT(current != mdev->worker.task); + wait_for_completion(&done); + } + + abort: + if (f & ChgSerialize) + mutex_unlock(&mdev->state_mutex); + + return rv; +} + +/** + * _drbd_request_state: + * This function is the most gracefull way to change state. For some state + * transition this function even does a cluster wide transaction. + * It has a cousin named drbd_request_state(), which is always verbose. + */ +int _drbd_request_state(struct drbd_conf *mdev, union drbd_state_t mask, + union drbd_state_t val, enum chg_state_flags f) +{ + int rv; + + wait_event(mdev->state_wait, + (rv = drbd_req_state(mdev, mask, val, f)) != SS_InTransientState); + + return rv; +} + + +STATIC void print_st(struct drbd_conf *mdev, char *name, union drbd_state_t ns) +{ + ERR(" %s = { cs:%s st:%s/%s ds:%s/%s %c%c%c%c }\n", + name, + conns_to_name(ns.conn), + roles_to_name(ns.role), + roles_to_name(ns.peer), + disks_to_name(ns.disk), + disks_to_name(ns.pdsk), + ns.susp ? 's' : 'r', + ns.aftr_isp ? 'a' : '-', + ns.peer_isp ? 'p' : '-', + ns.user_isp ? 'u' : '-' + ); +} + +void print_st_err(struct drbd_conf *mdev, + union drbd_state_t os, union drbd_state_t ns, int err) +{ + if (err == SS_InTransientState) + return; + ERR("State change failed: %s\n", set_st_err_name(err)); + print_st(mdev, " state", os); + print_st(mdev, "wanted", ns); +} + + +#define peers_to_name roles_to_name +#define pdsks_to_name disks_to_name + +#define susps_to_name(A) ( (A) ? "1" : "0" ) +#define aftr_isps_to_name(A) ( (A) ? "1" : "0" ) +#define peer_isps_to_name(A) ( (A) ? "1" : "0" ) +#define user_isps_to_name(A) ( (A) ? "1" : "0" ) + +#define PSC(A) \ + ({ if (ns.A != os.A) { \ + pbp += sprintf(pbp, #A "( %s -> %s ) ", \ + A##s_to_name(os.A), \ + A##s_to_name(ns.A)); \ + } }) + +int is_valid_state(struct drbd_conf *mdev, union drbd_state_t ns) +{ + /* See drbd_state_sw_errors in drbd_strings.c */ + + enum fencing_policy fp; + int rv = SS_Success; + + fp = DontCare; + if (inc_local(mdev)) { + fp = mdev->bc->dc.fencing; + dec_local(mdev); + } + + if (inc_net(mdev)) { + if ( !mdev->net_conf->two_primaries && + ns.role == Primary && ns.peer == Primary ) + rv = SS_TwoPrimaries; + dec_net(mdev); + } + + if (rv <= 0) + /* already found a reason to abort */; + else if (ns.role == Secondary && mdev->open_cnt) + rv = SS_DeviceInUse; + + else if ( ns.role == Primary && ns.conn < Connected && + ns.disk < UpToDate ) rv = SS_NoUpToDateDisk; + + else if ( fp >= Resource && + ns.role == Primary && ns.conn < Connected && + ns.pdsk >= DUnknown ) rv = SS_PrimaryNOP; + + else if ( ns.role == Primary && ns.disk <= Inconsistent && + ns.pdsk <= Inconsistent ) rv = SS_NoUpToDateDisk; + + else if ( ns.conn > Connected && + ns.disk < UpToDate && ns.pdsk < UpToDate ) + rv = SS_BothInconsistent; + + else if ( ns.conn > Connected && + (ns.disk == Diskless || ns.pdsk == Diskless ) ) + rv = SS_SyncingDiskless; + + else if ( (ns.conn == Connected || + ns.conn == WFBitMapS || + ns.conn == SyncSource || + ns.conn == PausedSyncS) && + ns.disk == Outdated ) rv = SS_ConnectedOutdates; + + else if( (ns.conn == VerifyS || + ns.conn == VerifyT) && + (mdev->sync_conf.verify_alg[0] == 0)) rv=SS_NoVerifyAlg; + + else if( (ns.conn == VerifyS || + ns.conn == VerifyT) && + mdev->agreed_pro_version < 88) rv = SS_NotSupported; + + return rv; +} + +int is_valid_state_transition(struct drbd_conf *mdev, + union drbd_state_t ns, union drbd_state_t os) +{ + int rv = SS_Success; + + if ( (ns.conn == StartingSyncT || ns.conn == StartingSyncS ) && + os.conn > Connected) rv = SS_ResyncRunning; + + if (ns.conn == Disconnecting && os.conn == StandAlone) + rv = SS_AlreadyStandAlone; + + if (ns.disk > Attaching && os.disk == Diskless) + rv = SS_IsDiskLess; + + if ( ns.conn == WFConnection && os.conn < Unconnected ) + rv=SS_NoNetConfig; + + if ( ns.disk == Outdated && os.disk < Outdated && os.disk != Attaching) + rv=SS_LowerThanOutdated; + + if (ns.conn == Disconnecting && os.conn == Unconnected) + rv = SS_InTransientState; + + if (ns.conn == os.conn && ns.conn == WFReportParams) + rv = SS_InTransientState; + + if( (ns.conn == VerifyS || ns.conn == VerifyT) && os.conn < Connected ) + rv=SS_NeedConnection; + + if ((ns.conn == VerifyS || ns.conn == VerifyT) && + ns.conn != os.conn && os.conn > Connected) + rv = SS_ResyncRunning; + + if ((ns.conn == StartingSyncS || ns.conn == StartingSyncT) && + os.conn < Connected) + rv = SS_NeedConnection; + + return rv; +} + +int _drbd_set_state(struct drbd_conf *mdev, + union drbd_state_t ns, enum chg_state_flags flags, + struct completion *done) +{ + union drbd_state_t os; + int rv = SS_Success; + int warn_sync_abort = 0; + enum fencing_policy fp; + struct after_state_chg_work* ascw; + + MUST_HOLD(&mdev->req_lock); + + os = mdev->state; + + fp = DontCare; + if (inc_local(mdev)) { + fp = mdev->bc->dc.fencing; + dec_local(mdev); + } + + /* Early state sanitising. */ + + /* Dissalow Network errors to configure a device's network part */ + if ( (ns.conn >= Timeout && ns.conn <= TearDown ) && + os.conn <= Disconnecting ) + ns.conn = os.conn; + + /* After a network error (+TearDown) only Unconnected can follow */ + if (os.conn >= Timeout && os.conn <= TearDown && ns.conn != Unconnected) + ns.conn = os.conn; + + /* After Disconnecting only StandAlone may follow */ + if (os.conn == Disconnecting && ns.conn != StandAlone) + ns.conn = os.conn; + + if (ns.conn < Connected) { + ns.peer_isp = 0; + ns.peer = Unknown; + if ( ns.pdsk > DUnknown || + ns.pdsk < Inconsistent ) ns.pdsk = DUnknown; + } + + if (ns.conn <= Disconnecting && ns.disk == Diskless) + ns.pdsk = DUnknown; + + if (os.conn > Connected && ns.conn > Connected && + (ns.disk <= Failed || ns.pdsk <= Failed )) { + warn_sync_abort = 1; + ns.conn = Connected; + } + + if (ns.conn != os.conn && ns.conn >= Connected && + (ns.disk == Consistent || ns.disk == Outdated)) { + switch(ns.conn) { + case WFBitMapT: + case PausedSyncT: + ns.disk = Outdated; + break; + case Connected: + case WFBitMapS: + case SyncSource: + case PausedSyncS: + ns.disk = UpToDate; + break; + case SyncTarget: + ns.disk = Inconsistent; + DRBD_WARN("Implicit set disk state Inconsistent!\n"); + break; + } + if (os.disk == Outdated && ns.disk == UpToDate) + DRBD_WARN("Implicit set disk from Outdate to UpToDate\n"); + } + + if (ns.conn != os.conn && ns.conn >= Connected && + (ns.pdsk == Consistent || ns.pdsk == Outdated)) { + switch(ns.conn) { + case Connected: + case WFBitMapT: + case PausedSyncT: + case SyncTarget: + ns.pdsk = UpToDate; + break; + case WFBitMapS: + case PausedSyncS: + ns.pdsk = Outdated; + break; + case SyncSource: + ns.pdsk = Inconsistent; + DRBD_WARN("Implicit set pdsk Inconsistent!\n"); + break; + } + if (os.pdsk == Outdated && ns.pdsk == UpToDate) + DRBD_WARN("Implicit set pdsk from Outdate to UpToDate\n"); + } + + /* Connection breaks down before we finished "Negotiating" */ + if (ns.conn < Connected && ns.disk == Negotiating && + inc_local_if_state(mdev, Negotiating)) { + if (mdev->ed_uuid == mdev->bc->md.uuid[Current]) { + ns.disk = mdev->new_state_tmp.disk; + ns.pdsk = mdev->new_state_tmp.pdsk; + } else { + ALERT("Connection lost while negotiating, no data!\n"); + ns.disk = Diskless; + ns.pdsk = DUnknown; + } + dec_local(mdev); + } + + if (fp == Stonith && + (ns.role == Primary && + ns.conn < Connected && + ns.pdsk > Outdated)) + ns.susp = 1; + + if (ns.aftr_isp || ns.peer_isp || ns.user_isp) { + if (ns.conn == SyncSource) + ns.conn = PausedSyncS; + if (ns.conn == SyncTarget) + ns.conn = PausedSyncT; + } else { + if (ns.conn == PausedSyncS) + ns.conn = SyncSource; + if (ns.conn == PausedSyncT) + ns.conn = SyncTarget; + } + + if (ns.i == os.i) + return SS_NothingToDo; + + if ( !(flags & ChgStateHard) ) { + /* pre-state-change checks ; only look at ns */ + /* See drbd_state_sw_errors in drbd_strings.c */ + + rv = is_valid_state(mdev, ns); + if (rv < SS_Success) { + /* If the old state was illegal as well, then let + this happen...*/ + + if ( is_valid_state(mdev, os) == rv ) { + ERR("Considering state change from bad state. " + "Error would be: '%s'\n", + set_st_err_name(rv)); + print_st(mdev, "old", os); + print_st(mdev, "new", ns); + rv = is_valid_state_transition(mdev,ns,os); + } + } else + rv = is_valid_state_transition(mdev, ns, os); + } + + if (rv < SS_Success) { + if (flags & ChgStateVerbose) + print_st_err(mdev, os, ns, rv); + return rv; + } + + if (warn_sync_abort) + DRBD_WARN("Resync aborted.\n"); + +#if DUMP_MD >= 2 + { + char *pbp, pb[300]; + pbp = pb; + *pbp = 0; + PSC(role); + PSC(peer); + PSC(conn); + PSC(disk); + PSC(pdsk); + PSC(susp); + PSC(aftr_isp); + PSC(peer_isp); + PSC(user_isp); + INFO("%s\n", pb); + } +#endif + + mdev->state.i = ns.i; + wake_up(&mdev->misc_wait); + wake_up(&mdev->state_wait); + + /** post-state-change actions **/ + if (os.conn >= SyncSource && ns.conn <= Connected) { + set_bit(STOP_SYNC_TIMER, &mdev->flags); + mod_timer(&mdev->resync_timer, jiffies); + } + + if ( (os.conn == PausedSyncT || os.conn == PausedSyncS) && + (ns.conn == SyncTarget || ns.conn == SyncSource) ) { + INFO("Syncer continues.\n"); + mdev->rs_paused += (long)jiffies-(long)mdev->rs_mark_time; + if (ns.conn == SyncTarget) { + if (!test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags)) { + mod_timer(&mdev->resync_timer,jiffies); + } + /* This if (!test_bit) is only needed for the case + that a device that has ceased to used its timer, + i.e. it is already in drbd_resync_finished() gets + paused and resumed. */ + } + } + + if ( (os.conn == SyncTarget || os.conn == SyncSource) && + (ns.conn == PausedSyncT || ns.conn == PausedSyncS) ) { + INFO("Resync suspended\n"); + mdev->rs_mark_time = jiffies; + if (ns.conn == PausedSyncT) + set_bit(STOP_SYNC_TIMER, &mdev->flags); + } + + if (os.conn == Connected && + (ns.conn == VerifyS || ns.conn == VerifyT )) { + mdev->ov_position = 0; + mdev->ov_left = + mdev->rs_total = + mdev->rs_mark_left = drbd_bm_bits(mdev); + mdev->rs_start = + mdev->rs_mark_time = jiffies; + mdev->ov_last_oos_size = 0; + mdev->ov_last_oos_start = 0; + if(ns.conn == VerifyS) { + mod_timer(&mdev->resync_timer,jiffies); + } + } + + if(inc_local(mdev)) { + u32 mdf = mdev->bc->md.flags & ~(MDF_Consistent|MDF_PrimaryInd| + MDF_ConnectedInd|MDF_WasUpToDate| + MDF_PeerOutDated ); + if (test_bit(CRASHED_PRIMARY,&mdev->flags) || + mdev->state.role == Primary || + ( mdev->state.pdsk < Inconsistent && + mdev->state.peer == Primary ) ) mdf |= MDF_PrimaryInd; + if (mdev->state.conn > WFReportParams) mdf |= MDF_ConnectedInd; + if (mdev->state.disk > Inconsistent) mdf |= MDF_Consistent; + if (mdev->state.disk > Outdated) mdf |= MDF_WasUpToDate; + if (mdev->state.pdsk <= Outdated && + mdev->state.pdsk >= Inconsistent) mdf |= MDF_PeerOutDated; + if( mdf != mdev->bc->md.flags) { + mdev->bc->md.flags = mdf; + drbd_md_mark_dirty(mdev); + } + if (os.disk < Consistent && ns.disk >= Consistent) + drbd_set_ed_uuid(mdev, mdev->bc->md.uuid[Current]); + dec_local(mdev); + } + + /* Peer was forced UpToDate & Primary, consider to resync */ + if (os.disk == Inconsistent && os.pdsk == Inconsistent && + os.peer == Secondary && ns.peer == Primary) + set_bit(CONSIDER_RESYNC, &mdev->flags); + + /* Receiver should clean up itself */ + if (os.conn != Disconnecting && ns.conn == Disconnecting) + drbd_thread_stop_nowait(&mdev->receiver); + + /* Now the receiver finished cleaning up itself, it should die */ + if (os.conn != StandAlone && ns.conn == StandAlone) + drbd_thread_stop_nowait(&mdev->receiver); + + /* Upon network failure, we need to restart the receiver. */ + if (os.conn > TearDown && + ns.conn <= TearDown && ns.conn >= Timeout) + drbd_thread_restart_nowait(&mdev->receiver); + + ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); + if (ascw) { + ascw->os = os; + ascw->ns = ns; + ascw->flags = flags; + ascw->w.cb = w_after_state_ch; + ascw->done = done; + drbd_queue_work(&mdev->data.work, &ascw->w); + } else { + DRBD_WARN("Could not kmalloc an ascw\n"); + } + + return rv; +} + +int w_after_state_ch(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + struct after_state_chg_work *ascw; + + ascw = (struct after_state_chg_work *) w; + after_state_ch(mdev, ascw->os, ascw->ns, ascw->flags); + if (ascw->flags & ChgWaitComplete) { + D_ASSERT(ascw->done != NULL); + complete(ascw->done); + } + kfree(ascw); + + return 1; +} + +static void abw_start_sync(struct drbd_conf *mdev, int rv) +{ + if (rv) { + ERR("Writing the bitmap failed not starting resync.\n"); + _drbd_request_state(mdev, NS(conn, Connected), ChgStateVerbose); + return; + } + + switch (mdev->state.conn) { + case StartingSyncT: + _drbd_request_state(mdev, NS(conn, WFSyncUUID), ChgStateVerbose); + break; + case StartingSyncS: + drbd_start_resync(mdev, SyncSource); + break; + } +} + +static void after_state_ch(struct drbd_conf *mdev, union drbd_state_t os, + union drbd_state_t ns, enum chg_state_flags flags) +{ + enum fencing_policy fp; + + if ( (os.conn != Connected && ns.conn == Connected) ) { + clear_bit(CRASHED_PRIMARY, &mdev->flags); + if (mdev->p_uuid) + mdev->p_uuid[UUID_FLAGS] &= ~((u64)2); + } + + fp = DontCare; + if (inc_local(mdev)) { + fp = mdev->bc->dc.fencing; + dec_local(mdev); + } + + /* Inform userspace about the change... */ + drbd_bcast_state(mdev, ns); + + /* Here we have the actions that are performed after a + state change. This function might sleep */ + + if (fp == Stonith && ns.susp) { + /* case1: The outdate peer handler is successfull: + * case2: The connection was established again: */ + if ( (os.pdsk > Outdated && ns.pdsk <= Outdated) || + (os.conn < Connected && ns.conn >= Connected) ) { + tl_clear(mdev); + spin_lock_irq(&mdev->req_lock); + _drbd_set_state(_NS(mdev, susp, 0), ChgStateVerbose, NULL); + spin_unlock_irq(&mdev->req_lock); + } + } + /* Do not change the order of the if above and below... */ + if (os.conn != WFBitMapS && ns.conn == WFBitMapS) + drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL); + + /* Lost contact to peer's copy of the data */ + if ( (os.pdsk >= Inconsistent && + os.pdsk != DUnknown && + os.pdsk != Outdated) + && (ns.pdsk < Inconsistent || + ns.pdsk == DUnknown || + ns.pdsk == Outdated) ) { + kfree(mdev->p_uuid); + mdev->p_uuid = NULL; + if (inc_local(mdev)) { + /* generate new uuid, unless we did already */ + if (ns.role == Primary && + mdev->bc->md.uuid[Bitmap] == 0) + drbd_uuid_new_current(mdev); + if (ns.peer == Primary) { + /* Note: The condition ns.peer == Primary implies + that we are connected. Otherwise it would + be ns.peer == Unknown. */ + /* A FullSync is required after a + primary detached from its disk! */ + _drbd_uuid_new_current(mdev); + drbd_send_uuids(mdev); + } + dec_local(mdev); + } + } + + if (ns.pdsk < Inconsistent && inc_local(mdev)) { + if (ns.peer == Primary && mdev->bc->md.uuid[Bitmap] == 0) { + /* Diskless Peer becomes primary */ + if (os.peer == Secondary) + drbd_uuid_new_current(mdev); + + /* Got connected to diskless, primary peer */ + if (os.peer == Unknown) + _drbd_uuid_new_current(mdev); + } + + /* Diskless Peer becomes secondary */ + if (os.peer == Primary && ns.peer == Secondary) + drbd_al_to_on_disk_bm(mdev); + dec_local(mdev); + } + + /* Last part of the attaching process ... */ + if ( ns.conn >= Connected && + os.disk == Attaching && ns.disk == Negotiating ) { + kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */ + mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */ + drbd_send_sizes(mdev); /* to start sync... */ + drbd_send_uuids(mdev); + drbd_send_state(mdev); + } + + /* We want to pause/continue resync, tell peer. */ + if ( ns.conn >= Connected && + (( os.aftr_isp != ns.aftr_isp ) || + ( os.user_isp != ns.user_isp )) ) + drbd_send_state(mdev); + + /* In case one of the isp bits got set, suspend other devices. */ + if ( ( !os.aftr_isp && !os.peer_isp && !os.user_isp) && + ( ns.aftr_isp || ns.peer_isp || ns.user_isp) ) + suspend_other_sg(mdev); + + /* Make sure the peer gets informed about eventual state + changes (ISP bits) while we were in WFReportParams. */ + if (os.conn == WFReportParams && ns.conn >= Connected) { + drbd_send_state(mdev); + } + + /* We are in the progress to start a full sync... */ + if ( ( os.conn != StartingSyncT && ns.conn == StartingSyncT ) || + ( os.conn != StartingSyncS && ns.conn == StartingSyncS ) ) { + INFO("Queueing bitmap io: about to start a forced full sync\n"); + drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, &abw_start_sync); + } + + /* We are invalidating our self... */ + if ( os.conn < Connected && ns.conn < Connected && + os.disk > Inconsistent && ns.disk == Inconsistent ) { + INFO("Queueing bitmap io: invalidate forced full sync\n"); + drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL); + } + + if (os.disk > Diskless && ns.disk == Diskless) { + /* since inc_local() only works as long as disk>=Inconsistent, + and it is Diskless here, local_cnt can only go down, it can + not increase... It will reach zero */ + wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); + + lc_free(mdev->resync); + mdev->resync = NULL; + lc_free(mdev->act_log); + mdev->act_log = NULL; + __no_warn(local, drbd_free_bc(mdev->bc);); + wmb(); /* see begin of drbd_nl_disk_conf() */ + __no_warn(local, mdev->bc = NULL;); + } + + /* A resync finished or aborted, wake paused devices... */ + if ( (os.conn > Connected && ns.conn <= Connected) || + (os.peer_isp && !ns.peer_isp) || + (os.user_isp && !ns.user_isp) ) + resume_next_sg(mdev); + + /* Upon network connection, we need to start the received */ + if (os.conn == StandAlone && ns.conn == Unconnected) + drbd_thread_start(&mdev->receiver); + + /* Terminate worker thread if we are unconfigured - it will be + restarted as needed... */ + if (ns.disk == Diskless && ns.conn == StandAlone) + drbd_thread_stop_nowait(&mdev->worker); + + drbd_md_sync(mdev); +} + + +STATIC int drbd_thread_setup(void *arg) +{ + struct Drbd_thread *thi = (struct Drbd_thread *) arg; + struct drbd_conf *mdev = thi->mdev; + int retval; + + daemonize("drbd_thread"); + D_ASSERT(get_t_state(thi) == Running); + D_ASSERT(thi->task == NULL); + spin_lock(&thi->t_lock); + thi->task = current; + smp_mb(); + spin_unlock(&thi->t_lock); + complete(&thi->startstop); /* notify: thi->task is set. */ + + while (1) { + retval = thi->function(thi); + if (get_t_state(thi) != Restarting) break; + thi->t_state = Running; + } + + mutex_lock(&thi->task_mutex); + spin_lock(&thi->t_lock); + thi->task = NULL; + thi->t_state = None; + smp_mb(); + spin_unlock(&thi->t_lock); + mutex_unlock(&thi->task_mutex); + + /* THINK maybe two different completions? */ + complete(&thi->startstop); /* notify: thi->task unset. */ + + INFO("Terminating %s thread\n", + thi == &mdev->receiver ? "receiver" : + thi == &mdev->asender ? "asender" : + thi == &mdev->worker ? "worker" : "NONSENSE"); + + // Release mod reference taken when thread was started + module_put(THIS_MODULE); + return retval; +} + +STATIC void drbd_thread_init(struct drbd_conf *mdev, struct Drbd_thread *thi, + int (*func) (struct Drbd_thread *)) +{ + spin_lock_init(&thi->t_lock); + thi->task = NULL; + thi->t_state = None; + thi->function = func; + thi->mdev = mdev; + mutex_init(&thi->task_mutex); +} + +int drbd_thread_start(struct Drbd_thread *thi) +{ + int pid; + struct drbd_conf *mdev = thi->mdev; + + spin_lock(&thi->t_lock); + + if (thi->t_state == None) { + INFO("Starting %s thread (from %s [%d])\n", + thi == &mdev->receiver ? "receiver" : + thi == &mdev->asender ? "asender" : + thi == &mdev->worker ? "worker" : "NONSENSE", + current->comm, current->pid); + + /* Get ref on module for thread - this is released when thread exits */ + if (!try_module_get(THIS_MODULE)) { + ERR("Failed to get module reference in drbd_thread_start\n"); + spin_unlock(&thi->t_lock); + return FALSE; + } + + init_completion(&thi->startstop); + D_ASSERT(thi->task == NULL); + thi->t_state = Running; + spin_unlock(&thi->t_lock); + flush_signals(current); /* otherw. may get -ERESTARTNOINTR */ + + /* FIXME rewrite to use kthread interface */ + pid = kernel_thread(drbd_thread_setup, (void *) thi, CLONE_FS); + if (pid < 0) { + ERR("Couldn't start thread (%d)\n", pid); + + module_put(THIS_MODULE); + return FALSE; + } + /* waits until thi->task is set */ + wait_for_completion(&thi->startstop); + D_ASSERT(thi->task); + D_ASSERT(get_t_state(thi) == Running); + } else { + spin_unlock(&thi->t_lock); + } + + return TRUE; +} + + +void _drbd_thread_stop(struct Drbd_thread *thi, int restart, int wait) +{ + struct drbd_conf *mdev = thi->mdev; + enum Drbd_thread_state ns = restart ? Restarting : Exiting; + + spin_lock(&thi->t_lock); + + /* INFO("drbd_thread_stop: %s [%d]: %s %d -> %d; %d\n", + current->comm, current->pid, + thi->task ? thi->task->comm : "NULL", thi->t_state, ns, wait); */ + + if (thi->t_state == None) { + spin_unlock(&thi->t_lock); + if (restart) + drbd_thread_start(thi); + return; + } + + if (thi->t_state != ns) { + if (thi->task == NULL) { + spin_unlock(&thi->t_lock); + return; + } + + thi->t_state = ns; + smp_mb(); + if (thi->task != current) { + if (wait) + init_completion(&thi->startstop); + force_sig(DRBD_SIGKILL, thi->task); + } else + D_ASSERT(!wait); + } + spin_unlock(&thi->t_lock); + + if (wait) { + D_ASSERT(thi->task != current); + wait_for_completion(&thi->startstop); + spin_lock(&thi->t_lock); + D_ASSERT(thi->task == NULL); + D_ASSERT(thi->t_state == None); + spin_unlock(&thi->t_lock); + } +} + +#ifdef CONFIG_SMP +/** + * drbd_calc_cpu_mask: Generates CPU masks, sprad over all CPUs. + * Forces all threads of a device onto the same CPU. This is benificial for + * DRBD's performance. May be overwritten by user's configuration. + */ +cpumask_t drbd_calc_cpu_mask(struct drbd_conf *mdev) +{ + int sv, cpu; + cpumask_t av_cpu_m; + + if (cpus_weight(mdev->cpu_mask)) + return mdev->cpu_mask; + + av_cpu_m = cpu_online_map; + sv = mdev_to_minor(mdev) % cpus_weight(av_cpu_m); + + for_each_cpu_mask(cpu, av_cpu_m) { + if (sv-- == 0) + return cpumask_of_cpu(cpu); + } + + /* some kernel versions "forget" to add the (cpumask_t) typecast + * to that macro, which results in "parse error before '{'" ;-> */ + return (cpumask_t) CPU_MASK_ALL; /* Never reached. */ +} + +void drbd_thread_set_cpu(struct Drbd_thread *thi, cpumask_t cpu_mask) +{ + struct task_struct *p; + + mutex_lock(&thi->task_mutex); + p = thi->task; + if (p) set_cpus_allowed(p, cpu_mask); + mutex_unlock(&thi->task_mutex); +} + +#endif + +/* the appropriate socket mutex must be held already */ +int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock, + enum Drbd_Packet_Cmd cmd, struct Drbd_Header *h, + size_t size, unsigned msg_flags) +{ + int sent, ok; + + ERR_IF(!h) return FALSE; + ERR_IF(!size) return FALSE; + + h->magic = BE_DRBD_MAGIC; + h->command = cpu_to_be16(cmd); + h->length = cpu_to_be16(size-sizeof(struct Drbd_Header)); + + dump_packet(mdev, sock, 0, (void *)h, __FILE__, __LINE__); + sent = drbd_send(mdev, sock, h, size, msg_flags); + + ok = ( sent == size ); + if (!ok) + ERR("short sent %s size=%d sent=%d\n", + cmdname(cmd), (int)size, sent); + return ok; +} + +/* don't pass the socket. we may only look at it + * when we hold the appropriate socket mutex. + */ +int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket, + enum Drbd_Packet_Cmd cmd, struct Drbd_Header *h, size_t size) +{ + int ok = 0; + struct socket *sock; + + if (use_data_socket) { + down(&mdev->data.mutex); + sock = mdev->data.socket; + } else { + down(&mdev->meta.mutex); + sock = mdev->meta.socket; + } + + /* drbd_disconnect() could have called drbd_free_sock() + * while we were waiting in down()... */ + if (likely(sock != NULL)) + ok = _drbd_send_cmd(mdev, sock, cmd, h, size, 0); + + if (use_data_socket) + up(&mdev->data.mutex); + else + up(&mdev->meta.mutex); + return ok; +} + +int drbd_send_cmd2(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, char *data, + size_t size) +{ + struct Drbd_Header h; + int ok; + + h.magic = BE_DRBD_MAGIC; + h.command = cpu_to_be16(cmd); + h.length = cpu_to_be16(size); + + if (!drbd_get_data_sock(mdev)) + return 0; + + dump_packet(mdev, mdev->data.socket, 0, (void *)&h, __FILE__, __LINE__); + + ok = ( sizeof(h) == + drbd_send(mdev, mdev->data.socket, &h, sizeof(h), 0) ); + ok = ok && ( size == + drbd_send(mdev, mdev->data.socket, data, size, 0) ); + + drbd_put_data_sock(mdev); + + return ok; +} + +int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc) +{ + struct Drbd_SyncParam_Packet *p; + int size, rv; + + size = sizeof(struct Drbd_SyncParam_Packet); + + if (mdev->agreed_pro_version >= 88) + size += strlen(mdev->sync_conf.verify_alg) + 1; + + p = kmalloc(size, GFP_KERNEL); + if (p == NULL) + return 0; + + p->rate = cpu_to_be32(sc->rate); + + if (mdev->agreed_pro_version >= 88) + strcpy(p->online_verify_alg,mdev->sync_conf.verify_alg); + + rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, SyncParam, + (struct Drbd_Header *)p, size); + kfree(p); + return rv; +} + +int drbd_send_protocol(struct drbd_conf *mdev) +{ + struct Drbd_Protocol_Packet *p; + int size,rv; + + size = sizeof(struct Drbd_Protocol_Packet); + + if (mdev->agreed_pro_version >= 87) + size += strlen(mdev->net_conf->integrity_alg) + 1; + + if ((p = kmalloc(size, GFP_KERNEL)) == NULL) + return 0; + + p->protocol = cpu_to_be32(mdev->net_conf->wire_protocol); + p->after_sb_0p = cpu_to_be32(mdev->net_conf->after_sb_0p); + p->after_sb_1p = cpu_to_be32(mdev->net_conf->after_sb_1p); + p->after_sb_2p = cpu_to_be32(mdev->net_conf->after_sb_2p); + p->want_lose = cpu_to_be32(mdev->net_conf->want_lose); + p->two_primaries = cpu_to_be32(mdev->net_conf->two_primaries); + + if (mdev->agreed_pro_version >= 87) + strcpy(p->integrity_alg, mdev->net_conf->integrity_alg); + + rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, ReportProtocol, + (struct Drbd_Header *)p, size); + kfree(p); + return rv; +} + +int drbd_send_uuids(struct drbd_conf *mdev) +{ + struct Drbd_GenCnt_Packet p; + int i; + + u64 uuid_flags = 0; + + if (!inc_local_if_state(mdev, Negotiating)) + return 1; + + /* FIXME howto handle diskless ? */ + for (i = Current; i < UUID_SIZE; i++) + p.uuid[i] = mdev->bc ? cpu_to_be64(mdev->bc->md.uuid[i]) : 0; + + mdev->comm_bm_set = drbd_bm_total_weight(mdev); + p.uuid[UUID_SIZE] = cpu_to_be64(mdev->comm_bm_set); + uuid_flags |= mdev->net_conf->want_lose ? 1 : 0; + uuid_flags |= test_bit(CRASHED_PRIMARY, &mdev->flags) ? 2 : 0; + uuid_flags |= mdev->new_state_tmp.disk == Inconsistent ? 4 : 0; + p.uuid[UUID_FLAGS] = cpu_to_be64(uuid_flags); + + dec_local(mdev); + + return drbd_send_cmd(mdev, USE_DATA_SOCKET, ReportUUIDs, + (struct Drbd_Header*)&p, sizeof(p)); +} + +int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val) +{ + struct Drbd_SyncUUID_Packet p; + + p.uuid = cpu_to_be64(val); + + return drbd_send_cmd(mdev, USE_DATA_SOCKET, ReportSyncUUID, + (struct Drbd_Header *)&p, sizeof(p)); +} + +int drbd_send_sizes(struct drbd_conf *mdev) +{ + struct Drbd_Sizes_Packet p; + sector_t d_size, u_size; + int q_order_type; + int ok; + + if (inc_local_if_state(mdev, Negotiating)) { + D_ASSERT(mdev->bc->backing_bdev); + d_size = drbd_get_max_capacity(mdev->bc); + u_size = mdev->bc->dc.disk_size; + q_order_type = drbd_queue_order_type(mdev); + p.queue_order_type = cpu_to_be32(drbd_queue_order_type(mdev)); + dec_local(mdev); + } else { + d_size = 0; + u_size = 0; + q_order_type = QUEUE_ORDERED_NONE; + } + + p.d_size = cpu_to_be64(d_size); + p.u_size = cpu_to_be64(u_size); + p.c_size = cpu_to_be64(drbd_get_capacity(mdev->this_bdev)); + p.max_segment_size = cpu_to_be32(mdev->rq_queue->max_segment_size); + p.queue_order_type = cpu_to_be32(q_order_type); + + ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, ReportSizes, + (struct Drbd_Header *)&p, sizeof(p)); + return ok; +} + +/** + * drbd_send_state: + * Informs the peer about our state. Only call it when + * mdev->state.conn >= Connected (I.e. you may not call it while in + * WFReportParams. Though there is one valid and necessary exception, + * drbd_connect() calls drbd_send_state() while in it WFReportParams. + */ +int drbd_send_state(struct drbd_conf *mdev) +{ + struct socket *sock; + struct Drbd_State_Packet p; + int ok = 0; + + /* Grab state lock so we wont send state if we're in the middle + * of a cluster wide state change on another thread */ + drbd_state_lock(mdev); + + down(&mdev->data.mutex); + + p.state = cpu_to_be32(mdev->state.i); /* Within the send mutex */ + sock = mdev->data.socket; + + if (likely(sock != NULL)) { + ok = _drbd_send_cmd(mdev, sock, ReportState, + (struct Drbd_Header*)&p, sizeof(p), 0); + } + + up(&mdev->data.mutex); + + drbd_state_unlock(mdev); + return ok; +} + +int drbd_send_state_req(struct drbd_conf *mdev, + union drbd_state_t mask, union drbd_state_t val) +{ + struct Drbd_Req_State_Packet p; + + p.mask = cpu_to_be32(mask.i); + p.val = cpu_to_be32(val.i); + + return drbd_send_cmd(mdev, USE_DATA_SOCKET, StateChgRequest, + (struct Drbd_Header *)&p, sizeof(p)); +} + +int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode) +{ + struct Drbd_RqS_Reply_Packet p; + + p.retcode = cpu_to_be32(retcode); + + return drbd_send_cmd(mdev, USE_META_SOCKET, StateChgReply, + (struct Drbd_Header *)&p, sizeof(p)); +} + + +/* See the comment at receive_bitmap() */ +int _drbd_send_bitmap(struct drbd_conf *mdev) +{ + int want; + int ok = TRUE; + int bm_i = 0; + size_t bm_words, num_words; + unsigned long *buffer; + struct Drbd_Header *p; + + ERR_IF(!mdev->bitmap) return FALSE; + + bm_words = drbd_bm_words(mdev); + p = vmalloc(PAGE_SIZE); /* sleeps. cannot fail. */ + buffer = (unsigned long *)p->payload; + + if (inc_local(mdev)) { + if (drbd_md_test_flag(mdev->bc,MDF_FullSync)) { + INFO("Writing the whole bitmap, MDF_FullSync was set.\n"); + drbd_bm_set_all(mdev); + if (drbd_bm_write(mdev)) { + /* write_bm did fail! Leave full sync flag set in Meta Data + * but otherwise process as per normal - need to tell other + * side that a full resync is required! */ + ERR("Failed to write bitmap to disk!\n"); + } + else { + drbd_md_clear_flag(mdev,MDF_FullSync); + drbd_md_sync(mdev); + } + } + dec_local(mdev); + } + + /* + * maybe TODO use some simple compression scheme, nowadays there are + * some such algorithms in the kernel anyways. + */ + do { + num_words = min_t(size_t, BM_PACKET_WORDS, bm_words-bm_i ); + want = num_words * sizeof(long); + if (want) + drbd_bm_get_lel(mdev, bm_i, num_words, buffer); + ok = _drbd_send_cmd(mdev, mdev->data.socket, ReportBitMap, + p, sizeof(*p) + want, 0); + bm_i += num_words; + } while (ok && want); + + vfree(p); + return ok; +} + +int drbd_send_bitmap(struct drbd_conf *mdev) +{ + int err; + + if (!drbd_get_data_sock(mdev)) + return -1; + err = !_drbd_send_bitmap(mdev); + drbd_put_data_sock(mdev); + return err; +} + +int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr, u32 set_size) +{ + int ok; + struct Drbd_BarrierAck_Packet p; + + p.barrier = barrier_nr; + p.set_size = cpu_to_be32(set_size); + + ok = drbd_send_cmd(mdev, USE_META_SOCKET, BarrierAck, + (struct Drbd_Header *)&p, sizeof(p)); + return ok; +} + +/** + * _drbd_send_ack: + * This helper function expects the sector and block_id parameter already + * in big endian! + */ +STATIC int _drbd_send_ack(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + u64 sector, + u32 blksize, + u64 block_id) +{ + int ok; + struct Drbd_BlockAck_Packet p; + + p.sector = sector; + p.block_id = block_id; + p.blksize = blksize; + p.seq_num = cpu_to_be32(atomic_add_return(1, &mdev->packet_seq)); + + if (!mdev->meta.socket || mdev->state.conn < Connected) + return FALSE; + ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd, + (struct Drbd_Header *)&p, sizeof(p)); + return ok; +} + +int drbd_send_ack_dp(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + struct Drbd_Data_Packet *dp) +{ + const int header_size = sizeof(struct Drbd_Data_Packet) + - sizeof(struct Drbd_Header); + int data_size = ((struct Drbd_Header *)dp)->length - header_size; + + return _drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size), + dp->block_id); +} + +int drbd_send_ack_rp(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + struct Drbd_BlockRequest_Packet *rp) +{ + return _drbd_send_ack(mdev, cmd, rp->sector, rp->blksize, rp->block_id); +} + +int drbd_send_ack(struct drbd_conf *mdev, + enum Drbd_Packet_Cmd cmd, struct Tl_epoch_entry *e) +{ + return _drbd_send_ack(mdev, cmd, + cpu_to_be64(e->sector), + cpu_to_be32(e->size), + e->block_id); +} + +int drbd_send_ack_ex(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + sector_t sector, int blksize, u64 block_id) +{ + /* This function misuses the block_id field to signal if the blocks + are is sync or not. */ + return _drbd_send_ack(mdev,cmd, + cpu_to_be64(sector), + cpu_to_be32(blksize), + cpu_to_be64(block_id)); +} + + +int drbd_send_drequest(struct drbd_conf *mdev, int cmd, + sector_t sector, int size, u64 block_id) +{ + int ok; + struct Drbd_BlockRequest_Packet p; + + p.sector = cpu_to_be64(sector); + p.block_id = block_id; + p.blksize = cpu_to_be32(size); + + /* FIXME BIO_RW_SYNC ? */ + + ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd, + (struct Drbd_Header *)&p, sizeof(p)); + return ok; +} + + +int drbd_send_drequest_csum(struct drbd_conf *mdev, + sector_t sector,int size, + void *digest, int digest_size, + enum Drbd_Packet_Cmd cmd) +{ + int ok; + struct Drbd_BlockRequest_Packet p; + + p.sector = cpu_to_be64(sector); + p.block_id = BE_DRBD_MAGIC + 0xbeef; + p.blksize = cpu_to_be32(size); + + p.head.magic = BE_DRBD_MAGIC; + p.head.command = cpu_to_be16(cmd); + p.head.length = cpu_to_be16( sizeof(p)-sizeof(struct Drbd_Header) + digest_size ); + + down(&mdev->data.mutex); + + ok = ( sizeof(p) == drbd_send(mdev,mdev->data.socket,&p,sizeof(p),0) ); + ok = ok&& ( digest_size == drbd_send(mdev,mdev->data.socket,digest,digest_size,0) ); + + up(&mdev->data.mutex); + + return ok; +} + +int drbd_send_ov_request(struct drbd_conf *mdev,sector_t sector,int size) +{ + int ok; + struct Drbd_BlockRequest_Packet p; + + p.sector = cpu_to_be64(sector); + p.block_id = BE_DRBD_MAGIC + 0xbabe; + p.blksize = cpu_to_be32(size); + + ok = drbd_send_cmd(mdev,USE_DATA_SOCKET, OVRequest, + (struct Drbd_Header*)&p,sizeof(p)); + return ok; +} + + +/* called on sndtimeo + * returns FALSE if we should retry, + * TRUE if we think connection is dead + */ +STATIC int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *sock) +{ + int drop_it; + /* long elapsed = (long)(jiffies - mdev->last_received); */ + /* DUMPLU(elapsed); // elapsed ignored for now. */ + + drop_it = mdev->meta.socket == sock + || !mdev->asender.task + || get_t_state(&mdev->asender) != Running + || mdev->state.conn < Connected; + + if (drop_it) + return TRUE; + + drop_it = !--mdev->ko_count; + if (!drop_it) { + ERR("[%s/%d] sock_sendmsg time expired, ko = %u\n", + current->comm, current->pid, mdev->ko_count); + request_ping(mdev); + } + + return drop_it; /* && (mdev->state == Primary) */; +} + +/* The idea of sendpage seems to be to put some kind of reference + * to the page into the skb, and to hand it over to the NIC. In + * this process get_page() gets called. + * + * As soon as the page was really sent over the network put_page() + * gets called by some part of the network layer. [ NIC driver? ] + * + * [ get_page() / put_page() increment/decrement the count. If count + * reaches 0 the page will be freed. ] + * + * This works nicely with pages from FSs. + * But this means that in protocol A we might signal IO completion too early! + * + * In order not to corrupt data during a resync we must make sure + * that we do not reuse our own buffer pages (EEs) to early, therefore + * we have the net_ee list. + * + * XFS seems to have problems, still, it submits pages with page_count == 0! + * As a workaround, we disable sendpage on pages + * with page_count == 0 or PageSlab. + */ +STATIC int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page, + int offset, size_t size) +{ + int ret; + ret = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, 0); + kunmap(page); + return ret; +} + +int _drbd_send_page(struct drbd_conf *mdev, struct page *page, + int offset, size_t size) +{ + mm_segment_t oldfs = get_fs(); + int sent, ok; + int len = size; + +#ifdef SHOW_SENDPAGE_USAGE + unsigned long now = jiffies; + static unsigned long total; + static unsigned long fallback; + static unsigned long last_rep; + + /* report statistics every hour, + * if we had at least one fallback. + */ + ++total; + if (fallback && time_before(last_rep+3600*HZ, now)) { + last_rep = now; + printk(KERN_INFO "drbd: sendpage() omitted: %lu/%lu\n", + fallback, total); + } +#endif + + /* PARANOIA. if this ever triggers, + * something in the layers above us is really kaputt. + *one roundtrip later: + * doh. it triggered. so XFS _IS_ really kaputt ... + * oh well... + */ + if ( (page_count(page) < 1) || PageSlab(page) ) { + /* e.g. XFS meta- & log-data is in slab pages, which have a + * page_count of 0 and/or have PageSlab() set... + */ +#ifdef SHOW_SENDPAGE_USAGE + ++fallback; +#endif + sent = _drbd_no_send_page(mdev, page, offset, size); + if (likely(sent > 0)) len -= sent; + goto out; + } + + set_fs(KERNEL_DS); + do { + sent = mdev->data.socket->ops->sendpage(mdev->data.socket, page, + offset, len, + MSG_NOSIGNAL); + if (sent == -EAGAIN) { + if (we_should_drop_the_connection(mdev, + mdev->data.socket)) + break; + else + continue; + } + if (sent <= 0) { + DRBD_WARN("%s: size=%d len=%d sent=%d\n", + __func__, (int)size, len, sent); + break; + } + len -= sent; + offset += sent; + /* FIXME test "last_received" ... */ + } while (len > 0 /* THINK && mdev->cstate >= Connected*/); + set_fs(oldfs); + +out: + ok = (len == 0); + if (likely(ok)) + mdev->send_cnt += size>>9; + return ok; +} + +static inline int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio) +{ + struct bio_vec *bvec; + int i; + __bio_for_each_segment(bvec, bio, i, 0) { + if (!_drbd_no_send_page(mdev, bvec->bv_page, + bvec->bv_offset, bvec->bv_len)) + return 0; + } + return 1; +} + +static inline int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio) +{ + struct bio_vec *bvec; + int i; + __bio_for_each_segment(bvec, bio, i, 0) { + if (!_drbd_send_page(mdev, bvec->bv_page, + bvec->bv_offset, bvec->bv_len)) + return 0; + } + + return 1; +} + +/* Used to send write requests + * Primary -> Peer (Data) + */ +int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) +{ + int ok = 1; + struct Drbd_Data_Packet p; + unsigned int dp_flags = 0; + void *dgb; + int dgs; + + if (!drbd_get_data_sock(mdev)) + return 0; + + dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ? + crypto_hash_digestsize(mdev->integrity_w_tfm) : 0; + + p.head.magic = BE_DRBD_MAGIC; + p.head.command = cpu_to_be16(Data); + p.head.length = cpu_to_be16( sizeof(p) + -sizeof(struct Drbd_Header)+dgs+req->size); + + p.sector = cpu_to_be64(req->sector); + p.block_id = (unsigned long)req; + p.seq_num = cpu_to_be32( req->seq_num = + atomic_add_return(1, &mdev->packet_seq) ); + dp_flags = 0; + + /* NOTE: no need to check if barriers supported here as we would + * not pass the test in make_request_common in that case + */ + if (bio_barrier(req->master_bio)) + dp_flags |= DP_HARDBARRIER; + if (bio_sync(req->master_bio)) + dp_flags |= DP_RW_SYNC; + if (mdev->state.conn >= SyncSource && + mdev->state.conn <= PausedSyncT) + dp_flags |= DP_MAY_SET_IN_SYNC; + + p.dp_flags = cpu_to_be32(dp_flags); + dump_packet(mdev, mdev->data.socket, 0, (void *)&p, __FILE__, __LINE__); + set_bit(UNPLUG_REMOTE, &mdev->flags); + ok = (sizeof(p) == + drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE)); + if (ok && dgs) { + dgb = mdev->int_dig_out; + drbd_csum(mdev, mdev->integrity_w_tfm, req->master_bio, dgb); + ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE); + } + if (ok) { + if (mdev->net_conf->wire_protocol == DRBD_PROT_A) + ok = _drbd_send_bio(mdev, req->master_bio); + else + ok = _drbd_send_zc_bio(mdev, req->master_bio); + } + + drbd_put_data_sock(mdev); + return ok; +} + +/* answer packet, used to send data back for read requests: + * Peer -> (diskless) Primary (DataReply) + * SyncSource -> SyncTarget (RSDataReply) + */ +int drbd_send_block(struct drbd_conf *mdev, enum Drbd_Packet_Cmd cmd, + struct Tl_epoch_entry *e) +{ + int ok; + struct Drbd_Data_Packet p; + void *dgb; + int dgs; + + dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ? + crypto_hash_digestsize(mdev->integrity_w_tfm) : 0; + + p.head.magic = BE_DRBD_MAGIC; + p.head.command = cpu_to_be16(cmd); + p.head.length = cpu_to_be16( sizeof(p) + -sizeof(struct Drbd_Header) + dgs + e->size); + + p.sector = cpu_to_be64(e->sector); + p.block_id = e->block_id; + /* p.seq_num = 0; No sequence numbers here.. */ + + /* Only called by our kernel thread. + * This one may be interupted by DRBD_SIG and/or DRBD_SIGKILL + * in response to ioctl or module unload. + */ + if (!drbd_get_data_sock(mdev)) + return 0; + + dump_packet(mdev, mdev->data.socket, 0, (void *)&p, __FILE__, __LINE__); + ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, + sizeof(p), MSG_MORE); + if (ok && dgs) { + dgb = mdev->int_dig_out; + drbd_csum(mdev, mdev->integrity_w_tfm, e->private_bio, dgb); + ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE); + } + if (ok) + ok = _drbd_send_zc_bio(mdev, e->private_bio); + + drbd_put_data_sock(mdev); + return ok; +} + +/* + drbd_send distinguishes two cases: + + Packets sent via the data socket "sock" + and packets sent via the meta data socket "msock" + + sock msock + -----------------+-------------------------+------------------------------ + timeout conf.timeout / 2 conf.timeout / 2 + timeout action send a ping via msock Abort communication + and close all sockets +*/ + +/* + * you must have down()ed the appropriate [m]sock_mutex elsewhere! + */ +int drbd_send(struct drbd_conf *mdev, struct socket *sock, + void *buf, size_t size, unsigned msg_flags) +{ +#if !HAVE_KERNEL_SENDMSG + mm_segment_t oldfs; + struct iovec iov; +#else + struct kvec iov; +#endif + struct msghdr msg; + int rv, sent = 0; + + if (!sock) + return -1000; + + /* THINK if (signal_pending) return ... ? */ + + iov.iov_base = buf; + iov.iov_len = size; + + msg.msg_name = NULL; + msg.msg_namelen = 0; +#if !HAVE_KERNEL_SENDMSG + msg.msg_iov = &iov; + msg.msg_iovlen = 1; +#endif + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = msg_flags | MSG_NOSIGNAL; + +#if !HAVE_KERNEL_SENDMSG + oldfs = get_fs(); + set_fs(KERNEL_DS); +#endif + + if (sock == mdev->data.socket) + mdev->ko_count = mdev->net_conf->ko_count; + do { + /* STRANGE + * tcp_sendmsg does _not_ use its size parameter at all ? + * + * -EAGAIN on timeout, -EINTR on signal. + */ +/* THINK + * do we need to block DRBD_SIG if sock == &meta.socket ?? + * otherwise wake_asender() might interrupt some send_*Ack ! + */ +#if !HAVE_KERNEL_SENDMSG + rv = sock_sendmsg(sock, &msg, iov.iov_len ); +#else + rv = kernel_sendmsg(sock, &msg, &iov, 1, size); +#endif + if (rv == -EAGAIN) { + if (we_should_drop_the_connection(mdev, sock)) + break; + else + continue; + } + D_ASSERT(rv != 0); + if (rv == -EINTR) { +#if 0 + /* FIXME this happens all the time. + * we don't care for now! + * eventually this should be sorted out be the proper + * use of the SIGNAL_ASENDER bit... */ + if (DRBD_ratelimit(5*HZ, 5)) { + DBG("Got a signal in drbd_send(,%c,)!\n", + sock == mdev->meta.socket ? 'm' : 's'); + /* dump_stack(); */ + } +#endif + flush_signals(current); + rv = 0; + } + if (rv < 0) + break; + sent += rv; + iov.iov_base += rv; + iov.iov_len -= rv; + } while (sent < size); + +#if !HAVE_KERNEL_SENDMSG + set_fs(oldfs); +#endif + + if (rv <= 0) { + if (rv != -EAGAIN) { + ERR("%s_sendmsg returned %d\n", + sock == mdev->meta.socket ? "msock" : "sock", + rv); + drbd_force_state(mdev, NS(conn, BrokenPipe)); + } else + drbd_force_state(mdev, NS(conn, Timeout)); + } + + return sent; +} + +int drbd_open(struct inode *inode, struct file *file) +{ + struct drbd_conf *mdev; + unsigned long flags; + int rv = 0; + + mdev = minor_to_mdev(MINOR(inode->i_rdev)); + if (!mdev) + return -ENODEV; + + spin_lock_irqsave(&mdev->req_lock, flags); + /* to have a stable mdev->state.role + * and no race with updating open_cnt */ + + if (mdev->state.role != Primary) { + if (file->f_mode & FMODE_WRITE) + rv = -EROFS; + else if (!allow_oos) + rv = -EMEDIUMTYPE; + } + + if (!rv) + mdev->open_cnt++; + spin_unlock_irqrestore(&mdev->req_lock, flags); + + return rv; +} + +int drbd_close(struct inode *inode, struct file *file) +{ + /* do not use *file (May be NULL, in case of a unmount :-) */ + struct drbd_conf *mdev; + + mdev = minor_to_mdev(MINOR(inode->i_rdev)); + if (!mdev) + return -ENODEV; + + /* + printk(KERN_ERR "drbd: close(inode=%p,file=%p)" + "current=%p,minor=%d,wc=%d\n", inode, file, current, minor, + inode->i_writecount); + */ + + mdev->open_cnt--; + + return 0; +} + +STATIC void drbd_unplug_fn(struct request_queue *q) +{ + struct drbd_conf *mdev = q->queuedata; + + MTRACE(TraceTypeUnplug, TraceLvlSummary, + INFO("got unplugged ap_bio_count=%d\n", + atomic_read(&mdev->ap_bio_cnt)); + ); + + /* unplug FIRST */ + spin_lock_irq(q->queue_lock); + blk_remove_plug(q); + spin_unlock_irq(q->queue_lock); + + /* only if connected */ + spin_lock_irq(&mdev->req_lock); + if (mdev->state.pdsk >= Inconsistent && mdev->state.conn >= Connected) { + D_ASSERT(mdev->state.role == Primary); + if (test_and_clear_bit(UNPLUG_REMOTE, &mdev->flags)) { + /* add to the data.work queue, + * unless already queued. + * XXX this might be a good addition to drbd_queue_work + * anyways, to detect "double queuing" ... */ + if (list_empty(&mdev->unplug_work.list)) + drbd_queue_work(&mdev->data.work, + &mdev->unplug_work); + } + } + spin_unlock_irq(&mdev->req_lock); + + if (mdev->state.disk >= Inconsistent) + drbd_kick_lo(mdev); +} + +STATIC void drbd_set_defaults(struct drbd_conf *mdev) +{ + mdev->sync_conf.after = DRBD_AFTER_DEF; + mdev->sync_conf.rate = DRBD_RATE_DEF; + mdev->sync_conf.al_extents = DRBD_AL_EXTENTS_DEF; + mdev->state = (union drbd_state_t) { + { Secondary, Unknown, StandAlone, Diskless, DUnknown, 0 } }; +} + +void drbd_init_set_defaults(struct drbd_conf *mdev) +{ + /* the memset(,0,) did most of this. + * note: only assignments, no allocation in here */ + +#ifdef PARANOIA + SET_MDEV_MAGIC(mdev); +#endif + + drbd_set_defaults(mdev); + + /* for now, we do NOT yet support it, + * even though we start some framework + * to eventually support barriers */ + set_bit(NO_BARRIER_SUPP, &mdev->flags); + + atomic_set(&mdev->ap_bio_cnt, 0); + atomic_set(&mdev->ap_pending_cnt, 0); + atomic_set(&mdev->rs_pending_cnt, 0); + atomic_set(&mdev->unacked_cnt, 0); + atomic_set(&mdev->local_cnt, 0); + atomic_set(&mdev->net_cnt, 0); + atomic_set(&mdev->packet_seq, 0); + atomic_set(&mdev->pp_in_use, 0); + + init_MUTEX(&mdev->md_io_mutex); + init_MUTEX(&mdev->data.mutex); + init_MUTEX(&mdev->meta.mutex); + sema_init(&mdev->data.work.s, 0); + sema_init(&mdev->meta.work.s, 0); + mutex_init(&mdev->state_mutex); + + spin_lock_init(&mdev->data.work.q_lock); + spin_lock_init(&mdev->meta.work.q_lock); + + spin_lock_init(&mdev->al_lock); + spin_lock_init(&mdev->req_lock); + spin_lock_init(&mdev->peer_seq_lock); + + INIT_LIST_HEAD(&mdev->active_ee); + INIT_LIST_HEAD(&mdev->sync_ee); + INIT_LIST_HEAD(&mdev->done_ee); + INIT_LIST_HEAD(&mdev->read_ee); + INIT_LIST_HEAD(&mdev->net_ee); + INIT_LIST_HEAD(&mdev->resync_reads); + INIT_LIST_HEAD(&mdev->data.work.q); + INIT_LIST_HEAD(&mdev->meta.work.q); + INIT_LIST_HEAD(&mdev->resync_work.list); + INIT_LIST_HEAD(&mdev->unplug_work.list); + INIT_LIST_HEAD(&mdev->md_sync_work.list); + mdev->resync_work.cb = w_resync_inactive; + mdev->unplug_work.cb = w_send_write_hint; + mdev->md_sync_work.cb = w_md_sync; + init_timer(&mdev->resync_timer); + init_timer(&mdev->md_sync_timer); + mdev->resync_timer.function = resync_timer_fn; + mdev->resync_timer.data = (unsigned long) mdev; + mdev->md_sync_timer.function = md_sync_timer_fn; + mdev->md_sync_timer.data = (unsigned long) mdev; + + init_waitqueue_head(&mdev->misc_wait); + init_waitqueue_head(&mdev->state_wait); + init_waitqueue_head(&mdev->ee_wait); + init_waitqueue_head(&mdev->al_wait); + init_waitqueue_head(&mdev->seq_wait); + + drbd_thread_init(mdev, &mdev->receiver, drbdd_init); + drbd_thread_init(mdev, &mdev->worker, drbd_worker); + drbd_thread_init(mdev, &mdev->asender, drbd_asender); + + mdev->agreed_pro_version = PRO_VERSION_MAX; + +#ifdef __arch_um__ + INFO("mdev = 0x%p\n", mdev); +#endif + mdev->resync_wenr = LC_FREE; +} + +void drbd_mdev_cleanup(struct drbd_conf *mdev) +{ + /* I'd like to cleanup completely, and memset(,0,) it. + * but I'd have to reinit it. + * FIXME: do the right thing... + */ + + /* list of things that may still + * hold data of the previous config + + * act_log ** re-initialized in set_disk + * on_io_error + + * al_tr_cycle ** re-initialized in ... FIXME?? + * al_tr_number + * al_tr_pos + + * backing_bdev ** re-initialized in drbd_free_ll_dev + * lo_file + * md_bdev + * md_file + * md_index + + * ko_count ** re-initialized in set_net + + * last_received ** currently ignored + + * mbds_id ** re-initialized in ... FIXME?? + + * resync ** re-initialized in ... FIXME?? + + *** no re-init necessary (?) *** + * md_io_page + * this_bdev + + * vdisk ? + + * rq_queue ** FIXME ASSERT ?? + * newest_barrier + * oldest_barrier + */ + + D_ASSERT(mdev->receiver.t_state == None); + + if (mdev->verify_tfm) { + crypto_free_hash(mdev->verify_tfm); + mdev->verify_tfm=NULL; + } + /* no need to lock it, I'm the only thread alive */ + if (mdev->epoch_size != 0) + ERR("epoch_size:%d\n", mdev->epoch_size); + mdev->al_writ_cnt = + mdev->bm_writ_cnt = + mdev->read_cnt = + mdev->recv_cnt = + mdev->send_cnt = + mdev->writ_cnt = + mdev->p_size = + mdev->rs_start = + mdev->rs_total = + mdev->rs_failed = + mdev->rs_mark_left = + mdev->rs_mark_time = 0; + D_ASSERT(mdev->net_conf == NULL); + drbd_set_my_capacity(mdev, 0); + drbd_bm_resize(mdev, 0); + drbd_bm_cleanup(mdev); + + /* just in case */ + drbd_free_resources(mdev); + + /* + * currently we drbd_init_ee only on module load, so + * we may do drbd_release_ee only on module unload! + */ + D_ASSERT(list_empty(&mdev->active_ee)); + D_ASSERT(list_empty(&mdev->sync_ee)); + D_ASSERT(list_empty(&mdev->done_ee)); + D_ASSERT(list_empty(&mdev->read_ee)); + D_ASSERT(list_empty(&mdev->net_ee)); + D_ASSERT(list_empty(&mdev->resync_reads)); + D_ASSERT(list_empty(&mdev->data.work.q)); + D_ASSERT(list_empty(&mdev->meta.work.q)); + D_ASSERT(list_empty(&mdev->resync_work.list)); + D_ASSERT(list_empty(&mdev->unplug_work.list)); + +} + + +STATIC void drbd_destroy_mempools(void) +{ + struct page *page; + + while (drbd_pp_pool) { + page = drbd_pp_pool; + drbd_pp_pool = (struct page *)page_private(page); + __free_page(page); + drbd_pp_vacant--; + } + + /* D_ASSERT(atomic_read(&drbd_pp_vacant)==0); */ + + if (drbd_ee_mempool) + mempool_destroy(drbd_ee_mempool); + if (drbd_request_mempool) + mempool_destroy(drbd_request_mempool); + if (drbd_ee_cache) + kmem_cache_destroy(drbd_ee_cache); + if (drbd_request_cache) + kmem_cache_destroy(drbd_request_cache); + + drbd_ee_mempool = NULL; + drbd_request_mempool = NULL; + drbd_ee_cache = NULL; + drbd_request_cache = NULL; + + return; +} + +STATIC int drbd_create_mempools(void) +{ + struct page *page; + const int number = (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE) * minor_count; + int i; + + /* prepare our caches and mempools */ + drbd_request_mempool = NULL; + drbd_ee_cache = NULL; + drbd_request_cache = NULL; + drbd_pp_pool = NULL; + + /* caches */ + drbd_request_cache = kmem_cache_create( + "drbd_req_cache", sizeof(struct drbd_request), 0, 0, NULL); + if (drbd_request_cache == NULL) + goto Enomem; + + drbd_ee_cache = kmem_cache_create( + "drbd_ee_cache", sizeof(struct Tl_epoch_entry), 0, 0, NULL); + if (drbd_ee_cache == NULL) + goto Enomem; + + /* mempools */ + drbd_request_mempool = mempool_create( number, + mempool_alloc_slab, mempool_free_slab, drbd_request_cache); + if (drbd_request_mempool == NULL) + goto Enomem; + + drbd_ee_mempool = mempool_create( number, + mempool_alloc_slab, mempool_free_slab, drbd_ee_cache); + if (drbd_request_mempool == NULL) + goto Enomem; + + /* drbd's page pool */ + spin_lock_init(&drbd_pp_lock); + + for (i = 0; i < number; i++) { + page = alloc_page(GFP_HIGHUSER); + if (!page) + goto Enomem; + set_page_private(page, (unsigned long)drbd_pp_pool); + drbd_pp_pool = page; + } + drbd_pp_vacant = number; + + return 0; + +Enomem: + drbd_destroy_mempools(); /* in case we allocated some */ + return -ENOMEM; +} + +STATIC int drbd_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + /* just so we have it. you never know what interessting things we + * might want to do here some day... + */ + + return NOTIFY_DONE; +} + +STATIC struct notifier_block drbd_notifier = { + .notifier_call = drbd_notify_sys, +}; + + +STATIC void drbd_cleanup(void) +{ + int i, rr; + + unregister_reboot_notifier(&drbd_notifier); + + drbd_nl_cleanup(); + + if (minor_table) { + if (drbd_proc) { + remove_proc_entry("drbd", NULL); + drbd_proc = NULL; + } + i = minor_count; + while (i--) { + struct drbd_conf *mdev = minor_to_mdev(i); + struct gendisk **disk = &mdev->vdisk; + struct request_queue **q = &mdev->rq_queue; + + if (!mdev) + continue; + drbd_free_resources(mdev); + + if (*disk) { + del_gendisk(*disk); + put_disk(*disk); + *disk = NULL; + } + if (*q) + blk_cleanup_queue(*q); + *q = NULL; + + D_ASSERT(mdev->open_cnt == 0); + if (mdev->this_bdev) + bdput(mdev->this_bdev); + + tl_cleanup(mdev); + if (mdev->resync) + lc_free(mdev->resync); + + rr = drbd_release_ee(mdev, &mdev->active_ee); + if (rr) + ERR("%d EEs in active list found!\n", rr); + + rr = drbd_release_ee(mdev, &mdev->sync_ee); + if (rr) + ERR("%d EEs in sync list found!\n", rr); + + rr = drbd_release_ee(mdev, &mdev->read_ee); + if (rr) + ERR("%d EEs in read list found!\n", rr); + + rr = drbd_release_ee(mdev, &mdev->done_ee); + if (rr) + ERR("%d EEs in done list found!\n", rr); + + rr = drbd_release_ee(mdev, &mdev->net_ee); + if (rr) + ERR("%d EEs in net list found!\n", rr); + + ERR_IF (!list_empty(&mdev->data.work.q)) { + struct list_head *lp; + list_for_each(lp, &mdev->data.work.q) { + DUMPP(lp); + } + }; + + if (mdev->md_io_page) + __free_page(mdev->md_io_page); + + if (mdev->md_io_tmpp) + __free_page(mdev->md_io_tmpp); + + if (mdev->act_log) + lc_free(mdev->act_log); + + kfree(mdev->ee_hash); + mdev->ee_hash_s = 0; + mdev->ee_hash = NULL; + + kfree(mdev->tl_hash); + mdev->tl_hash_s = 0; + mdev->tl_hash = NULL; + + kfree(mdev->app_reads_hash); + mdev->app_reads_hash = NULL; + + kfree(mdev->p_uuid); + mdev->p_uuid = NULL; + + kfree(mdev->int_dig_out); + kfree(mdev->int_dig_in); + kfree(mdev->int_dig_vv); + } + drbd_destroy_mempools(); + } + + kfree(minor_table); + + drbd_unregister_blkdev(DRBD_MAJOR, "drbd"); + + printk(KERN_INFO "drbd: module cleanup done.\n"); +} + +struct drbd_conf *drbd_new_device(int minor) +{ + struct drbd_conf *mdev = NULL; + struct gendisk *disk; + struct request_queue *q; + + mdev = kzalloc(sizeof(struct drbd_conf), GFP_KERNEL); + if (!mdev) + goto Enomem; + + mdev->minor = minor; + + drbd_init_set_defaults(mdev); + + q = blk_alloc_queue(GFP_KERNEL); + if (!q) + goto Enomem; + mdev->rq_queue = q; + q->queuedata = mdev; + q->max_segment_size = DRBD_MAX_SEGMENT_SIZE; + + disk = alloc_disk(1); + if (!disk) + goto Enomem; + mdev->vdisk = disk; + + set_disk_ro( disk, TRUE ); + + disk->queue = q; + disk->major = DRBD_MAJOR; + disk->first_minor = minor; + disk->fops = &drbd_ops; + sprintf(disk->disk_name, "drbd%d", minor); + disk->private_data = mdev; + add_disk(disk); + + mdev->this_bdev = bdget(MKDEV(DRBD_MAJOR, minor)); + /* we have no partitions. we contain only ourselves. */ + mdev->this_bdev->bd_contains = mdev->this_bdev; + + blk_queue_make_request(q, drbd_make_request_26); + blk_queue_merge_bvec(q, drbd_merge_bvec); + q->queue_lock = &mdev->req_lock; /* needed since we use */ + /* plugging on a queue, that actually has no requests! */ + q->unplug_fn = drbd_unplug_fn; + + mdev->md_io_page = alloc_page(GFP_KERNEL); + if (!mdev->md_io_page) + goto Enomem; + + if (!tl_init(mdev)) goto Enomem; + + mdev->app_reads_hash = kzalloc(APP_R_HSIZE*sizeof(void *), GFP_KERNEL); + if (!mdev->app_reads_hash) + goto Enomem; + + return mdev; + + Enomem: + if (mdev) { + kfree(mdev->app_reads_hash); + if (mdev->md_io_page) + __free_page(mdev->md_io_page); + kfree(mdev); + } + return NULL; +} + +int __init drbd_init(void) +{ + int err; + +#ifdef __arch_um__ + printk(KERN_INFO "drbd_module = 0x%p core = 0x%p\n", + THIS_MODULE, THIS_MODULE->module_core); +#endif + + /* FIXME should be a compile time assert */ + if (sizeof(struct Drbd_HandShake_Packet) != 80) { + printk(KERN_ERR + "drbd: never change the size or layout " + "of the HandShake packet.\n"); + return -EINVAL; + } + + if (1 > minor_count || minor_count > 255) { + printk(KERN_ERR + "drbd: invalid minor_count (%d)\n", minor_count); +#ifdef MODULE + return -EINVAL; +#else + minor_count = 8; +#endif + } + + err = drbd_nl_init(); + if (err) + return err; + + err = register_blkdev(DRBD_MAJOR, "drbd"); + if (err) { + printk(KERN_ERR + "drbd: unable to register block device major %d\n", + DRBD_MAJOR); + return err; + } + + register_reboot_notifier(&drbd_notifier); + + /* + * allocate all necessary structs + */ + err = -ENOMEM; + + init_waitqueue_head(&drbd_pp_wait); + + minor_table = kzalloc(sizeof(struct drbd_conf *)*minor_count, + GFP_KERNEL); + if (!minor_table) + goto Enomem; + + err = drbd_create_mempools(); + if (err) + goto Enomem; + +#if CONFIG_PROC_FS + /* + * register with procfs + */ + drbd_proc = proc_create("drbd", S_IFREG | S_IRUGO , NULL, &drbd_proc_fops); + + if (!drbd_proc) { + printk(KERN_ERR "drbd: unable to register proc file\n"); + goto Enomem; + } + + drbd_proc->owner = THIS_MODULE; +#else +# error "Currently drbd depends on the proc file system (CONFIG_PROC_FS)" +#endif + + printk(KERN_INFO "drbd: initialised. " + "Version: " REL_VERSION " (api:%d/proto:%d-%d)\n", + API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX); + printk(KERN_INFO "drbd: %s\n", drbd_buildtag()); + printk(KERN_INFO "drbd: registered as block device major %d\n", + DRBD_MAJOR); + printk(KERN_INFO "drbd: minor_table @ 0x%p\n", minor_table); + + return 0; /* Success! */ + +Enomem: + drbd_cleanup(); + if (err == -ENOMEM) + /* currently always the case */ + printk(KERN_ERR "drbd: ran out of memory\n"); + else + printk(KERN_ERR "drbd: initialization failure\n"); + return err; +} + +void drbd_free_bc(struct drbd_backing_dev *bc) +{ + if (bc == NULL) + return; + + bd_release(bc->backing_bdev); + bd_release(bc->md_bdev); + + fput(bc->lo_file); + fput(bc->md_file); + + kfree(bc); +} + +void drbd_free_sock(struct drbd_conf *mdev) +{ + if (mdev->data.socket) { + sock_release(mdev->data.socket); + mdev->data.socket = NULL; + } + if (mdev->meta.socket) { + sock_release(mdev->meta.socket); + mdev->meta.socket = NULL; + } +} + + +void drbd_free_resources(struct drbd_conf *mdev) +{ + crypto_free_hash(mdev->cram_hmac_tfm); + mdev->cram_hmac_tfm = NULL; + crypto_free_hash(mdev->integrity_w_tfm); + mdev->integrity_w_tfm=NULL; + crypto_free_hash(mdev->integrity_r_tfm); + mdev->integrity_r_tfm=NULL; + drbd_free_sock(mdev); + __no_warn(local, + drbd_free_bc(mdev->bc); + mdev->bc = NULL;); +} + +/*********************************/ +/* meta data management */ + +struct meta_data_on_disk { + u64 la_size; /* last agreed size. */ + u64 uuid[UUID_SIZE]; /* UUIDs. */ + u64 device_uuid; + u64 reserved_u64_1; + u32 flags; /* MDF */ + u32 magic; + u32 md_size_sect; + u32 al_offset; /* offset to this block */ + u32 al_nr_extents; /* important for restoring the AL */ + /* `-- act_log->nr_elements <-- sync_conf.al_extents */ + u32 bm_offset; /* offset to the bitmap, from here */ + u32 bm_bytes_per_bit; /* BM_BLOCK_SIZE */ + u32 reserved_u32[4]; + +} __attribute((packed)); + +/** + * drbd_md_sync: + * Writes the meta data super block if the MD_DIRTY flag bit is set. + */ +void drbd_md_sync(struct drbd_conf *mdev) +{ + struct meta_data_on_disk *buffer; + sector_t sector; + int i; + + if (!test_and_clear_bit(MD_DIRTY, &mdev->flags)) return; + del_timer(&mdev->md_sync_timer); + + /* We use here Failed and not Attaching because we try to write + * metadata even if we detach due to a disk failure! */ + if (!inc_local_if_state(mdev, Failed)) return; + + INFO("Writing meta data super block now.\n"); + + down(&mdev->md_io_mutex); + buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page); + memset(buffer, 0, 512); + + buffer->la_size = cpu_to_be64(drbd_get_capacity(mdev->this_bdev)); + for (i = Current; i < UUID_SIZE; i++) + buffer->uuid[i] = cpu_to_be64(mdev->bc->md.uuid[i]); + buffer->flags = cpu_to_be32(mdev->bc->md.flags); + buffer->magic = cpu_to_be32(DRBD_MD_MAGIC); + + buffer->md_size_sect = cpu_to_be32(mdev->bc->md.md_size_sect); + buffer->al_offset = cpu_to_be32(mdev->bc->md.al_offset); + buffer->al_nr_extents = cpu_to_be32(mdev->act_log->nr_elements); + buffer->bm_bytes_per_bit = cpu_to_be32(BM_BLOCK_SIZE); + buffer->device_uuid = cpu_to_be64(mdev->bc->md.device_uuid); + + buffer->bm_offset = cpu_to_be32(mdev->bc->md.bm_offset); + + D_ASSERT(drbd_md_ss__(mdev, mdev->bc) == mdev->bc->md.md_offset); + sector = mdev->bc->md.md_offset; + + if (drbd_md_sync_page_io(mdev, mdev->bc, sector, WRITE)) { + clear_bit(MD_DIRTY, &mdev->flags); + } else { + /* this was a try anyways ... */ + ERR("meta data update failed!\n"); + + drbd_chk_io_error(mdev, 1, TRUE); + drbd_io_error(mdev, TRUE); + } + + /* Update mdev->bc->md.la_size_sect, + * since we updated it on metadata. */ + mdev->bc->md.la_size_sect = drbd_get_capacity(mdev->this_bdev); + + up(&mdev->md_io_mutex); + dec_local(mdev); +} + +/** + * drbd_md_read: + * @bdev: describes the backing storage and the meta-data storage + * Reads the meta data from bdev. Return 0 (NoError) on success, and an + * enum ret_codes in case something goes wrong. + * Currently only: MDIOError, MDInvalid. + */ +int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) +{ + struct meta_data_on_disk *buffer; + int i, rv = NoError; + + if (!inc_local_if_state(mdev, Attaching)) return MDIOError; + + down(&mdev->md_io_mutex); + buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page); + + if (!drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) { + /* NOTE: cant do normal error processing here as this is + called BEFORE disk is attached */ + ERR("Error while reading metadata.\n"); + rv = MDIOError; + goto err; + } + + if (be32_to_cpu(buffer->magic) != DRBD_MD_MAGIC) { + ERR("Error while reading metadata, magic not found.\n"); + rv = MDInvalid; + goto err; + } + if (be32_to_cpu(buffer->al_offset) != bdev->md.al_offset) { + ERR("unexpected al_offset: %d (expected %d)\n", + be32_to_cpu(buffer->al_offset), bdev->md.al_offset); + rv = MDInvalid; + goto err; + } + if (be32_to_cpu(buffer->bm_offset) != bdev->md.bm_offset) { + ERR("unexpected bm_offset: %d (expected %d)\n", + be32_to_cpu(buffer->bm_offset), bdev->md.bm_offset); + rv = MDInvalid; + goto err; + } + if (be32_to_cpu(buffer->md_size_sect) != bdev->md.md_size_sect) { + ERR("unexpected md_size: %u (expected %u)\n", + be32_to_cpu(buffer->md_size_sect), bdev->md.md_size_sect); + rv = MDInvalid; + goto err; + } + + if (be32_to_cpu(buffer->bm_bytes_per_bit) != BM_BLOCK_SIZE) { + ERR("unexpected bm_bytes_per_bit: %u (expected %u)\n", + be32_to_cpu(buffer->bm_bytes_per_bit), BM_BLOCK_SIZE); + rv = MDInvalid; + goto err; + } + + bdev->md.la_size_sect = be64_to_cpu(buffer->la_size); + for (i = Current; i < UUID_SIZE; i++) + bdev->md.uuid[i] = be64_to_cpu(buffer->uuid[i]); + bdev->md.flags = be32_to_cpu(buffer->flags); + mdev->sync_conf.al_extents = be32_to_cpu(buffer->al_nr_extents); + bdev->md.device_uuid = be64_to_cpu(buffer->device_uuid); + + if (mdev->sync_conf.al_extents < 7) + mdev->sync_conf.al_extents = 127; + /* FIXME if this ever happens when reading meta data, + * it possibly screws up reading of the activity log? + */ + + err: + up(&mdev->md_io_mutex); + dec_local(mdev); + + return rv; +} + +/** + * drbd_md_mark_dirty: + * Call this function if you change enything that should be written to + * the meta-data super block. This function sets MD_DIRTY, and starts a + * timer that ensures that within five seconds you have to call drbd_md_sync(). + */ +void drbd_md_mark_dirty(struct drbd_conf *mdev) +{ + set_bit(MD_DIRTY, &mdev->flags); + mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ ); +} + + +STATIC void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local) +{ + int i; + + for ( i = History_start ; i < History_end ; i++ ) { + mdev->bc->md.uuid[i+1] = mdev->bc->md.uuid[i]; + + MTRACE(TraceTypeUuid, TraceLvlAll, + drbd_print_uuid(mdev, i+1); + ); + } +} + +void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) +{ + if (idx == Current) { + if (mdev->state.role == Primary) + val |= 1; + else + val &= ~((u64)1); + + drbd_set_ed_uuid(mdev, val); + } + + mdev->bc->md.uuid[idx] = val; + + MTRACE(TraceTypeUuid, TraceLvlSummary, + drbd_print_uuid(mdev, idx); + ); + + drbd_md_mark_dirty(mdev); +} + + +void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) +{ + if (mdev->bc->md.uuid[idx]) { + drbd_uuid_move_history(mdev); + mdev->bc->md.uuid[History_start] = mdev->bc->md.uuid[idx]; + MTRACE(TraceTypeUuid, TraceLvlMetrics, + drbd_print_uuid(mdev, History_start); + ); + } + _drbd_uuid_set(mdev, idx, val); +} + +/** + * _drbd_uuid_new_current: + * Creates a new current UUID, but does NOT rotate the old current + * UUID into the bitmap slot (but into history). This causes a full + * sync upon next connect. Aditionally the full sync is also requested + * by the FullSync bit. + */ +void _drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local) +{ + u64 uuid; + + /* Actually a seperate bit names DisklessPeer, would be + the right thing. But for now the FullSync bit is a + working substitute, to avoid repetitive generating + of new current UUIDs in case we loose connection + and reconnect in a loop. */ + if (mdev->bc->md.flags & MDF_FullSync) return; + INFO("Creating new current UUID [no BitMap]\n"); + get_random_bytes(&uuid, sizeof(u64)); + drbd_uuid_set(mdev, Current, uuid); + drbd_md_set_flag(mdev, MDF_FullSync); +} + +/** + * drbd_uuid_new_current: + * Creates a new current UUID, and rotates the old current UUID into + * the bitmap slot. Causes an incremental resync upon next connect. + */ +void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local) +{ + u64 val; + + INFO("Creating new current UUID\n"); + D_ASSERT(mdev->bc->md.uuid[Bitmap] == 0); + mdev->bc->md.uuid[Bitmap] = mdev->bc->md.uuid[Current]; + MTRACE(TraceTypeUuid, TraceLvlMetrics, + drbd_print_uuid(mdev, Bitmap); + ); + + get_random_bytes(&val, sizeof(u64)); + _drbd_uuid_set(mdev, Current, val); +} + +void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local) +{ + if (mdev->bc->md.uuid[Bitmap] == 0 && val == 0) + return; + + if (val == 0) { + drbd_uuid_move_history(mdev); + mdev->bc->md.uuid[History_start] = mdev->bc->md.uuid[Bitmap]; + mdev->bc->md.uuid[Bitmap] = 0; + + MTRACE(TraceTypeUuid, TraceLvlMetrics, + drbd_print_uuid(mdev, History_start); + drbd_print_uuid(mdev, Bitmap); + ); + } else { + if (mdev->bc->md.uuid[Bitmap]) + DRBD_WARN("bm UUID already set"); + + mdev->bc->md.uuid[Bitmap] = val; + mdev->bc->md.uuid[Bitmap] &= ~((u64)1); + + MTRACE(TraceTypeUuid, TraceLvlMetrics, + drbd_print_uuid(mdev, Bitmap); + ); + } + drbd_md_mark_dirty(mdev); +} + +/** + * drbd_bmio_set_n_write: + * Is an io_fn for drbd_queue_bitmap_io() or drbd_bitmap_io() that sets + * all bits in the bitmap and writes the whole bitmap to stable storage. + */ +int drbd_bmio_set_n_write(struct drbd_conf *mdev) +{ + int rv = -EIO; + + if (inc_local_if_state(mdev, Attaching)) { + drbd_md_set_flag(mdev, MDF_FullSync); + drbd_md_sync(mdev); + drbd_bm_set_all(mdev); + + rv = drbd_bm_write(mdev); + + if (!rv) { + drbd_md_clear_flag(mdev, MDF_FullSync); + drbd_md_sync(mdev); + } + + dec_local(mdev); + } + + return rv; +} + +STATIC int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + struct bm_io_work *work = (struct bm_io_work *)w; + int rv; + + D_ASSERT(atomic_read(&mdev->ap_bio_cnt)==0); + + drbd_bm_lock(mdev); + rv = work->io_fn(mdev); + drbd_bm_unlock(mdev); + + clear_bit(BITMAP_IO, &mdev->flags); + wake_up(&mdev->misc_wait); + + if (work->done) work->done(mdev, rv); + + return 1; +} + +/** + * drbd_queue_bitmap_io: + * Queues an IO operation on the whole bitmap. + * While IO on the bitmap happens we freeze appliation IO thus we ensure + * that drbd_set_out_of_sync() can not be called. This function might be + * called from the worker thread and other contexts. + */ +void drbd_queue_bitmap_io(struct drbd_conf *mdev, + int (*io_fn)(struct drbd_conf *), + void (*done)(struct drbd_conf *, int)) +{ + unsigned long flags; + + D_ASSERT(!test_bit(BITMAP_IO, &mdev->flags)); + + mdev->bm_io_work.w.cb = w_bitmap_io; + mdev->bm_io_work.io_fn = io_fn; + mdev->bm_io_work.done = done; + + spin_lock_irqsave(&mdev->req_lock, flags); + clear_bit(BITMAP_IO_QUEUED, &mdev->flags); + set_bit(BITMAP_IO, &mdev->flags); + if (atomic_read(&mdev->ap_bio_cnt) == 0) { + set_bit(BITMAP_IO_QUEUED, &mdev->flags); + drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w); + } + spin_unlock_irqrestore(&mdev->req_lock, flags); +} + +/** + * drbd_bitmap_io: + * Does an IO operation on the bitmap, freezing application IO while that + * IO operations runs. This functions might not be called from the context + * of the worker thread. + */ +int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *)) +{ + int rv; + + D_ASSERT(current != mdev->worker.task); + D_ASSERT(!test_bit(BITMAP_IO, &mdev->flags)); + + set_bit(BITMAP_IO_QUEUED, &mdev->flags); + set_bit(BITMAP_IO, &mdev->flags); + wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); + + drbd_bm_lock(mdev); + rv = io_fn(mdev); + drbd_bm_unlock(mdev); + + clear_bit(BITMAP_IO, &mdev->flags); + wake_up(&mdev->misc_wait); + + return rv; +} + +void drbd_md_set_flag(struct drbd_conf *mdev, int flag) __must_hold(local) +{ + MUST_HOLD(mdev->req_lock); + if ( (mdev->bc->md.flags & flag) != flag) { + drbd_md_mark_dirty(mdev); + mdev->bc->md.flags |= flag; + } +} + +void drbd_md_clear_flag(struct drbd_conf *mdev, int flag) __must_hold(local) +{ + MUST_HOLD(mdev->req_lock); + if ( (mdev->bc->md.flags & flag) != 0 ) { + drbd_md_mark_dirty(mdev); + mdev->bc->md.flags &= ~flag; + } +} +int drbd_md_test_flag(struct drbd_backing_dev *bdev, int flag) +{ + return ((bdev->md.flags & flag) != 0); +} + +void md_sync_timer_fn(unsigned long data) +{ + struct drbd_conf *mdev = (struct drbd_conf *) data; + + drbd_queue_work_front(&mdev->data.work, &mdev->md_sync_work); +} + +int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused) +{ + DRBD_WARN("md_sync_timer expired! Worker calls drbd_md_sync().\n"); + drbd_md_sync(mdev); + + return 1; +} + +#ifdef DRBD_ENABLE_FAULTS +/* Fault insertion support including random number generator shamelessly + * stolen from kernel/rcutorture.c */ +struct fault_random_state { + unsigned long state; + unsigned long count; +}; + +#define FAULT_RANDOM_MULT 39916801 /* prime */ +#define FAULT_RANDOM_ADD 479001701 /* prime */ +#define FAULT_RANDOM_REFRESH 10000 + +/* + * Crude but fast random-number generator. Uses a linear congruential + * generator, with occasional help from get_random_bytes(). + */ +STATIC unsigned long +_drbd_fault_random(struct fault_random_state *rsp) +{ + long refresh; + + if (--rsp->count < 0) { + get_random_bytes(&refresh, sizeof(refresh)); + rsp->state += refresh; + rsp->count = FAULT_RANDOM_REFRESH; + } + rsp->state = rsp->state * FAULT_RANDOM_MULT + FAULT_RANDOM_ADD; + return swahw32(rsp->state); +} + +STATIC char * +_drbd_fault_str(unsigned int type) { + static char *_faults[] = { + "Meta-data write", + "Meta-data read", + "Resync write", + "Resync read", + "Data write", + "Data read", + "Data read ahead", + }; + + return (type < DRBD_FAULT_MAX)? _faults[type] : "**Unknown**"; +} + +unsigned int +_drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) +{ + static struct fault_random_state rrs = {0, 0}; + + unsigned int ret = ( + (fault_devs == 0 || + ((1 << mdev_to_minor(mdev)) & fault_devs) != 0) && + (((_drbd_fault_random(&rrs) % 100) + 1) <= fault_rate)); + + if (ret) { + fault_count++; + + if (printk_ratelimit()) + DRBD_WARN("***Simulating %s failure\n", + _drbd_fault_str(type)); + } + + return ret; +} +#endif + +#ifdef ENABLE_DYNAMIC_TRACE + +STATIC char *_drbd_uuid_str(unsigned int idx) +{ + static char *uuid_str[] = { + "Current", + "Bitmap", + "History_start", + "History_end", + "UUID_SIZE", + "UUID_FLAGS", + }; + + return (idx < EXT_UUID_SIZE) ? uuid_str[idx] : "*Unknown UUID index*"; +} + +/* Pretty print a UUID value */ +void drbd_print_uuid(struct drbd_conf *mdev, unsigned int idx) __must_hold(local) +{ + INFO(" uuid[%s] now %016llX\n", + _drbd_uuid_str(idx), mdev->bc->md.uuid[idx]); +} + + +/* + * + * drbd_print_buffer + * + * This routine dumps binary data to the debugging output. Can be + * called at interrupt level. + * + * Arguments: + * + * prefix - String is output at the beginning of each line output + * flags - Control operation of the routine. Currently defined + * Flags are: + * DBGPRINT_BUFFADDR; if set, each line starts with the + * virtual address of the line being outupt. If clear, + * each line starts with the offset from the beginning + * of the buffer. + * size - Indicates the size of each entry in the buffer. Supported + * values are sizeof(char), sizeof(short) and sizeof(int) + * buffer - Start address of buffer + * buffer_va - Virtual address of start of buffer (normally the same + * as Buffer, but having it separate allows it to hold + * file address for example) + * length - length of buffer + * + */ +void +drbd_print_buffer(const char *prefix, unsigned int flags, int size, + const void *buffer, const void *buffer_va, + unsigned int length) + +#define LINE_SIZE 16 +#define LINE_ENTRIES (int)(LINE_SIZE/size) +{ + const unsigned char *pstart; + const unsigned char *pstart_va; + const unsigned char *pend; + char bytes_str[LINE_SIZE*3+8], ascii_str[LINE_SIZE+8]; + char *pbytes = bytes_str, *pascii = ascii_str; + int offset = 0; + long sizemask; + int field_width; + int index; + const unsigned char *pend_str; + const unsigned char *p; + int count; + + /* verify size parameter */ + if (size != sizeof(char) && + size != sizeof(short) && + size != sizeof(int)) { + printk(KERN_DEBUG "drbd_print_buffer: " + "ERROR invalid size %d\n", size); + return; + } + + sizemask = size-1; + field_width = size*2; + + /* Adjust start/end to be on appropriate boundary for size */ + buffer = (const char *)((long)buffer & ~sizemask); + pend = (const unsigned char *) + (((long)buffer + length + sizemask) & ~sizemask); + + if (flags & DBGPRINT_BUFFADDR) { + /* Move start back to nearest multiple of line size, + * if printing address. This results in nicely formatted output + * with addresses being on line size (16) byte boundaries */ + pstart = (const unsigned char *)((long)buffer & ~(LINE_SIZE-1)); + } else { + pstart = (const unsigned char *)buffer; + } + + /* Set value of start VA to print if addresses asked for */ + pstart_va = (const unsigned char *)buffer_va + - ((const unsigned char *)buffer-pstart); + + /* Calculate end position to nicely align right hand side */ + pend_str = pstart + (((pend-pstart) + LINE_SIZE-1) & ~(LINE_SIZE-1)); + + /* Init strings */ + *pbytes = *pascii = '\0'; + + /* Start at beginning of first line */ + p = pstart; + count = 0; + + while (p < pend_str) { + if (p < (const unsigned char *)buffer || p >= pend) { + /* Before start of buffer or after end- print spaces */ + pbytes += sprintf(pbytes, "%*c ", field_width, ' '); + pascii += sprintf(pascii, "%*c", size, ' '); + p += size; + } else { + /* Add hex and ascii to strings */ + int val; + switch (size) { + default: + case 1: + val = *(unsigned char *)p; + break; + case 2: + val = *(unsigned short *)p; + break; + case 4: + val = *(unsigned int *)p; + break; + } + + pbytes += sprintf(pbytes, "%0*x ", field_width, val); + + for (index = size; index; index--) { + *pascii++ = isprint(*p) ? *p : '.'; + p++; + } + } + + count++; + + if (count == LINE_ENTRIES || p >= pend_str) { + /* Null terminate and print record */ + *pascii = '\0'; + printk(KERN_DEBUG "%s%8.8lx: %*s|%*s|\n", + prefix, + (flags & DBGPRINT_BUFFADDR) + ? (long)pstart_va : (long)offset, + LINE_ENTRIES*(field_width+1), bytes_str, + LINE_SIZE, ascii_str); + + /* Move onto next line */ + pstart_va += (p-pstart); + pstart = p; + count = 0; + offset += LINE_SIZE; + + /* Re-init strings */ + pbytes = bytes_str; + pascii = ascii_str; + *pbytes = *pascii = '\0'; + } + } +} + +#define PSM(A) \ +do { \ + if (mask.A) { \ + int i = snprintf(p, len, " " #A "( %s )", \ + A##s_to_name(val.A)); \ + if (i >= len) \ + return op; \ + p += i; \ + len -= i; \ + } \ +} while (0) + +STATIC char *dump_st(char *p, int len, union drbd_state_t mask, union drbd_state_t val) +{ + char *op = p; + *p = '\0'; + PSM(role); + PSM(peer); + PSM(conn); + PSM(disk); + PSM(pdsk); + + return op; +} + +#define INFOP(fmt, args...) \ +do { \ + if (trace_level >= TraceLvlAll) { \ + INFO("%s:%d: %s [%d] %s %s " fmt , \ + file, line, current->comm, current->pid, \ + sockname, recv?"<<<":">>>", \ + ## args ); \ + } \ + else { \ + INFO("%s %s " fmt, sockname, \ + recv?"<<<":">>>", \ + ## args ); \ + } \ +} while (0) + +STATIC char *_dump_block_id(u64 block_id, char *buff) +{ + if (is_syncer_block_id(block_id)) + strcpy(buff, "SyncerId"); + else + sprintf(buff, "%llx", block_id); + + return buff; +} + +void +_dump_packet(struct drbd_conf *mdev, struct socket *sock, + int recv, union Drbd_Polymorph_Packet *p, char *file, int line) +{ + char *sockname = sock == mdev->meta.socket ? "meta" : "data"; + int cmd = (recv == 2) ? p->head.command : be16_to_cpu(p->head.command); + char tmp[300]; + union drbd_state_t m, v; + + switch (cmd) { + case HandShake: + INFOP("%s (protocol %u-%u)\n", cmdname(cmd), + be32_to_cpu(p->HandShake.protocol_min), + be32_to_cpu(p->HandShake.protocol_max)); + break; + + case ReportBitMap: /* don't report this */ + break; + + case Data: + INFOP("%s (sector %llus, id %s, seq %u, f %x)\n", cmdname(cmd), + (unsigned long long)be64_to_cpu(p->Data.sector), + _dump_block_id(p->Data.block_id, tmp), + be32_to_cpu(p->Data.seq_num), + be32_to_cpu(p->Data.dp_flags) + ); + break; + + case DataReply: + case RSDataReply: + INFOP("%s (sector %llus, id %s)\n", cmdname(cmd), + (unsigned long long)be64_to_cpu(p->Data.sector), + _dump_block_id(p->Data.block_id, tmp) + ); + break; + + case RecvAck: + case WriteAck: + case RSWriteAck: + case DiscardAck: + case NegAck: + case NegRSDReply: + INFOP("%s (sector %llus, size %u, id %s, seq %u)\n", + cmdname(cmd), + (long long)be64_to_cpu(p->BlockAck.sector), + be32_to_cpu(p->BlockAck.blksize), + _dump_block_id(p->BlockAck.block_id, tmp), + be32_to_cpu(p->BlockAck.seq_num) + ); + break; + + case DataRequest: + case RSDataRequest: + INFOP("%s (sector %llus, size %u, id %s)\n", cmdname(cmd), + (long long)be64_to_cpu(p->BlockRequest.sector), + be32_to_cpu(p->BlockRequest.blksize), + _dump_block_id(p->BlockRequest.block_id, tmp) + ); + break; + + case Barrier: + case BarrierAck: + INFOP("%s (barrier %u)\n", cmdname(cmd), p->Barrier.barrier); + break; + + case ReportUUIDs: + INFOP("%s Curr:%016llX, Bitmap:%016llX, " + "HisSt:%016llX, HisEnd:%016llX\n", + cmdname(cmd), + be64_to_cpu(p->GenCnt.uuid[Current]), + be64_to_cpu(p->GenCnt.uuid[Bitmap]), + be64_to_cpu(p->GenCnt.uuid[History_start]), + be64_to_cpu(p->GenCnt.uuid[History_end])); + break; + + case ReportSizes: + INFOP("%s (d %lluMiB, u %lluMiB, c %lldMiB, " + "max bio %x, q order %x)\n", + cmdname(cmd), + (long long)(be64_to_cpu(p->Sizes.d_size)>>(20-9)), + (long long)(be64_to_cpu(p->Sizes.u_size)>>(20-9)), + (long long)(be64_to_cpu(p->Sizes.c_size)>>(20-9)), + be32_to_cpu(p->Sizes.max_segment_size), + be32_to_cpu(p->Sizes.queue_order_type)); + break; + + case ReportState: + v.i = be32_to_cpu(p->State.state); + m.i = 0xffffffff; + dump_st(tmp, sizeof(tmp), m, v); + INFOP("%s (s %x {%s})\n", cmdname(cmd), v.i, tmp); + break; + + case StateChgRequest: + m.i = be32_to_cpu(p->ReqState.mask); + v.i = be32_to_cpu(p->ReqState.val); + dump_st(tmp, sizeof(tmp), m, v); + INFOP("%s (m %x v %x {%s})\n", cmdname(cmd), m.i, v.i, tmp); + break; + + case StateChgReply: + INFOP("%s (ret %x)\n", cmdname(cmd), + be32_to_cpu(p->RqSReply.retcode)); + break; + + case Ping: + case PingAck: + /* + * Dont trace pings at summary level + */ + if (trace_level < TraceLvlAll) + break; + /* fall through... */ + default: + INFOP("%s (%u)\n", cmdname(cmd), cmd); + break; + } +} + +/* Debug routine to dump info about bio */ + +void _dump_bio(const char *pfx, struct drbd_conf *mdev, struct bio *bio, int complete) +{ +#ifdef CONFIG_LBD +#define SECTOR_FORMAT "%Lx" +#else +#define SECTOR_FORMAT "%lx" +#endif +#define SECTOR_SHIFT 9 + + unsigned long lowaddr = (unsigned long)(bio->bi_sector << SECTOR_SHIFT); + char *faddr = (char *)(lowaddr); + struct bio_vec *bvec; + int segno; + + const int rw = bio->bi_rw; + const int biorw = (rw & (RW_MASK|RWA_MASK)); + const int biobarrier = (rw & (1<>>", + pfx, + biorw==WRITE?"Write":"Read", + biobarrier?":B":"", + biosync?":S":"", + bio, + complete? (drbd_bio_uptodate(bio)? "Success, ":"Failed, ") : "", + bio->bi_sector << SECTOR_SHIFT, + bio->bi_size); + + if (trace_level >= TraceLvlMetrics && + ((biorw == WRITE) ^ complete) ) { + printk(KERN_DEBUG " ind page offset length\n"); + __bio_for_each_segment(bvec, bio, segno, 0) { + printk(KERN_DEBUG " [%d] %p %8.8x %8.8x\n", segno, + bvec->bv_page, bvec->bv_offset, bvec->bv_len); + + if (trace_level >= TraceLvlAll) { + char *bvec_buf; + unsigned long flags; + + bvec_buf = bvec_kmap_irq(bvec, &flags); + + drbd_print_buffer(" ", DBGPRINT_BUFFADDR, 1, + bvec_buf, + faddr, + (bvec->bv_len <= 0x80) + ? bvec->bv_len : 0x80); + + bvec_kunmap_irq(bvec_buf, &flags); + + if (bvec->bv_len > 0x40) + printk(KERN_DEBUG " ....\n"); + + faddr += bvec->bv_len; + } + } + } +} +#endif + +module_init(drbd_init) +module_exit(drbd_cleanup) --- linux-2.6.27.orig/ubuntu/drbd/drbd_wrappers.h +++ linux-2.6.27/ubuntu/drbd/drbd_wrappers.h @@ -0,0 +1,442 @@ +#include + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# error "use a 2.6 kernel, please" +#endif + + +/* struct page has a union in 2.6.15 ... + * an anonymous union and struct since 2.6.16 + * or in fc5 "2.6.15" */ +#include +#ifndef page_private +# define page_private(page) ((page)->private) +# define set_page_private(page, v) ((page)->private = (v)) +#endif + +/* see get_sb_bdev and bd_claim */ +extern char *drbd_sec_holder; + +static inline sector_t drbd_get_hardsect(struct block_device *bdev) +{ + return bdev->bd_disk->queue->hardsect_size; +} + +/* Returns the number of 512 byte sectors of the device */ +static inline sector_t drbd_get_capacity(struct block_device *bdev) +{ + /* return bdev ? get_capacity(bdev->bd_disk) : 0; */ + return bdev ? bdev->bd_inode->i_size >> 9 : 0; +} + +/* sets the number of 512 byte sectors of our virtual device */ +static inline void drbd_set_my_capacity(struct drbd_conf *mdev, + sector_t size) +{ + /* set_capacity(mdev->this_bdev->bd_disk, size); */ + set_capacity(mdev->vdisk, size); + mdev->this_bdev->bd_inode->i_size = (loff_t)size << 9; +} + +#define drbd_bio_uptodate(bio) bio_flagged(bio, BIO_UPTODATE) + +static inline int drbd_bio_has_active_page(struct bio *bio) +{ + struct bio_vec *bvec; + int i; + + __bio_for_each_segment(bvec, bio, i, 0) { + if (page_count(bvec->bv_page) > 1) return 1; + } + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +/* Before Linux-2.6.24 bie_endio() had the size of the bio as second argument. + See 6712ecf8f648118c3363c142196418f89a510b90 */ +#define bio_endio(B,E) bio_endio(B, (B)->bi_size, E) +#define BIO_ENDIO_TYPE int +#define BIO_ENDIO_ARGS(b,e) (b, unsigned int bytes_done, e) +#define BIO_ENDIO_FN_START if (bio->bi_size) return 1 +#define BIO_ENDIO_FN_RETURN return 0 +#else +#define BIO_ENDIO_TYPE void +#define BIO_ENDIO_ARGS(b,e) (b,e) +#define BIO_ENDIO_FN_START while(0) {} +#define BIO_ENDIO_FN_RETURN return +#endif + +// bi_end_io handlers +extern BIO_ENDIO_TYPE drbd_md_io_complete BIO_ENDIO_ARGS(struct bio *bio, int error); +extern BIO_ENDIO_TYPE drbd_endio_read_sec BIO_ENDIO_ARGS(struct bio *bio, int error); +extern BIO_ENDIO_TYPE drbd_endio_write_sec BIO_ENDIO_ARGS(struct bio *bio, int error); +extern BIO_ENDIO_TYPE drbd_endio_pri BIO_ENDIO_ARGS(struct bio *bio, int error); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) +/* Before 2.6.23 (with 20c2df83d25c6a95affe6157a4c9cac4cf5ffaac) kmem_cache_create had a + ctor and a dtor */ +#define kmem_cache_create(N,S,A,F,C) kmem_cache_create(N,S,A,F,C,NULL) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +static inline void sg_set_page(struct scatterlist *sg, struct page *page, + unsigned int len, unsigned int offset) +{ + sg->page = page; + sg->offset = offset; + sg->length = len; +} + +#define sg_init_table(S,N) ({}) + +#ifdef NEED_SG_SET_BUF +static inline void sg_set_buf(struct scatterlist *sg, const void *buf, + unsigned int buflen) +{ + sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); +} +#endif + +#endif + +/* + * used to submit our private bio + */ +static inline void drbd_generic_make_request(struct drbd_conf *mdev, + int fault_type, struct bio *bio) +{ + __release(local); + if (!bio->bi_bdev) { + printk(KERN_ERR "drbd%d: drbd_generic_make_request: " + "bio->bi_bdev == NULL\n", + mdev_to_minor(mdev)); + dump_stack(); + bio_endio(bio, -ENODEV); + return; + } + + if (FAULT_ACTIVE(mdev, fault_type)) + bio_endio(bio, -EIO); + else + generic_make_request(bio); +} + +static inline void drbd_plug_device(struct drbd_conf *mdev) +{ + struct request_queue *q; + q = bdev_get_queue(mdev->this_bdev); + + spin_lock_irq(q->queue_lock); + +/* XXX the check on !blk_queue_plugged is redundant, + * implicitly checked in blk_plug_device */ + + if (!blk_queue_plugged(q)) { + blk_plug_device(q); + del_timer(&q->unplug_timer); + /* unplugging should not happen automatically... */ + } + spin_unlock_irq(q->queue_lock); +} + +#ifdef DEFINE_SOCK_CREATE_KERN +#define sock_create_kern sock_create +#endif + +#ifdef USE_KMEM_CACHE_S +#define kmem_cache kmem_cache_s +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) +static inline void drbd_unregister_blkdev(unsigned int major, const char *name) +{ + int ret = unregister_blkdev(major,name); + if (ret) + printk(KERN_ERR "drbd: unregister of device failed\n"); +} +#else +#define drbd_unregister_blkdev unregister_blkdev +#endif + +#ifdef NEED_BACKPORT_OF_ATOMIC_ADD + +#if defined(__x86_64__) + +static __inline__ int atomic_add_return(int i, atomic_t *v) +{ + int __i = i; + __asm__ __volatile__( + LOCK_PREFIX "xaddl %0, %1;" + :"=r"(i) + :"m"(v->counter), "0"(i)); + return i + __i; +} + +static __inline__ int atomic_sub_return(int i, atomic_t *v) +{ + return atomic_add_return(-i,v); +} + +#define atomic_inc_return(v) (atomic_add_return(1,v)) +#define atomic_dec_return(v) (atomic_sub_return(1,v)) + +#elif defined(__i386__) || defined(__arch_um__) + +static __inline__ int atomic_add_return(int i, atomic_t *v) +{ + int __i; +#ifdef CONFIG_M386 + unsigned long flags; + if(unlikely(boot_cpu_data.x86==3)) + goto no_xadd; +#endif + /* Modern 486+ processor */ + __i = i; + __asm__ __volatile__( + LOCK_PREFIX "xaddl %0, %1;" + :"=r"(i) + :"m"(v->counter), "0"(i)); + return i + __i; + +#ifdef CONFIG_M386 +no_xadd: /* Legacy 386 processor */ + local_irq_save(flags); + __i = atomic_read(v); + atomic_set(v, i + __i); + local_irq_restore(flags); + return i + __i; +#endif +} + +static __inline__ int atomic_sub_return(int i, atomic_t *v) +{ + return atomic_add_return(-i,v); +} + +#define atomic_inc_return(v) (atomic_add_return(1,v)) +#define atomic_dec_return(v) (atomic_sub_return(1,v)) + +#else +# error "You need to copy/past atomic_inc_return()/atomic_dec_return() here" +# error "for your architecture. (Hint: Kernels after 2.6.10 have those" +# error "by default! Using a later kernel might be less effort!)" +#endif + +#endif + +#if !defined(CRYPTO_ALG_ASYNC) +/* With Linux-2.6.19 the crypto API changed! */ +/* This is not a generic backport of the new api, it just implements + the corner case of "hmac(xxx)". */ + +#define CRYPTO_ALG_ASYNC 4711 +#define CRYPTO_ALG_TYPE_HASH CRYPTO_ALG_TYPE_DIGEST + +struct crypto_hash { + struct crypto_tfm *base; + const u8 *key; + int keylen; +}; + +struct hash_desc { + struct crypto_hash *tfm; + u32 flags; +}; + +static inline struct crypto_hash * +crypto_alloc_hash(char *alg_name, u32 type, u32 mask) +{ + struct crypto_hash *ch; + char *closing_bracket; + + // "hmac(xxx)" is in alg_name we need that xxx. + closing_bracket = strchr(alg_name,')'); + if(!closing_bracket) { + ch = kmalloc(sizeof(struct crypto_hash),GFP_KERNEL); + if(!ch) return ERR_PTR(-ENOMEM); + ch->base = crypto_alloc_tfm(alg_name, 0); + if (ch->base == NULL) { + kfree(ch); + return ERR_PTR(-ENOMEM); + } + return ch; + } + if(closing_bracket-alg_name < 6) return ERR_PTR(-ENOENT); + + ch = kmalloc(sizeof(struct crypto_hash),GFP_KERNEL); + if(!ch) return ERR_PTR(-ENOMEM); + + *closing_bracket = 0; + ch->base = crypto_alloc_tfm(alg_name + 5, 0); + *closing_bracket = ')'; + + if (ch->base == NULL) { + kfree(ch); + return ERR_PTR(-ENOMEM); + } + + return ch; +} + +static inline int +crypto_hash_setkey(struct crypto_hash *hash,const u8 *key,unsigned int keylen) +{ + hash->key = key; + hash->keylen = keylen; + + return 0; +} + +static inline int +crypto_hash_digest(struct hash_desc *desc, struct scatterlist *sg, + unsigned int nbytes, u8 *out) +{ + + crypto_hmac(desc->tfm->base, (u8*)desc->tfm->key, + &desc->tfm->keylen, sg, 1 /* ! */ , out); + /* ! this is not generic. Would need to convert nbytes -> nsg */ + + return 0; +} + +static inline void crypto_free_hash(struct crypto_hash *tfm) +{ + if (!tfm) return; + crypto_free_tfm(tfm->base); + kfree(tfm); +} + +static inline unsigned int crypto_hash_digestsize(struct crypto_hash *tfm) +{ + return crypto_tfm_alg_digestsize(tfm->base); +} + +static inline struct crypto_tfm *crypto_hash_tfm(struct crypto_hash *tfm) +{ + return tfm->base; +} + +static inline int crypto_hash_init(struct hash_desc *desc) +{ + crypto_digest_init(desc->tfm->base); + return 0; +} + +static inline int crypto_hash_update(struct hash_desc *desc, + struct scatterlist *sg, + unsigned int nbytes) +{ + crypto_digest_update(desc->tfm->base,sg,1 /* ! */ ); + /* ! this is not generic. Would need to convert nbytes -> nsg */ + + return 0; +} + +static inline int crypto_hash_final(struct hash_desc *desc, u8 *out) +{ + crypto_digest_final(desc->tfm->base, out); + return 0; +} + +#endif + +#ifdef NEED_BACKPORT_OF_KZALLOC +static inline void *kzalloc(size_t size, int flags) +{ + void *rv = kmalloc(size,flags); + if(rv) memset(rv,0,size); + + return rv; +} +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +#define __bitmap_parse(BUF, BUFLEN, ISUSR, MASKP, NMASK) \ + backport_bitmap_parse(BUF, BUFLEN, ISUSR, MASKP, NMASK) + +#define CHUNKSZ 32 +#define nbits_to_hold_value(val) fls(val) +#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10)) + +static inline int backport_bitmap_parse(const char *buf, unsigned int buflen, + int is_user, unsigned long *maskp, + int nmaskbits) +{ + int c, old_c, totaldigits, ndigits, nchunks, nbits; + u32 chunk; + const char __user *ubuf = buf; + + bitmap_zero(maskp, nmaskbits); + + nchunks = nbits = totaldigits = c = 0; + do { + chunk = ndigits = 0; + + /* Get the next chunk of the bitmap */ + while (buflen) { + old_c = c; + if (is_user) { + if (__get_user(c, ubuf++)) + return -EFAULT; + } + else + c = *buf++; + buflen--; + if (isspace(c)) + continue; + + /* + * If the last character was a space and the current + * character isn't '\0', we've got embedded whitespace. + * This is a no-no, so throw an error. + */ + if (totaldigits && c && isspace(old_c)) + return -EINVAL; + + /* A '\0' or a ',' signal the end of the chunk */ + if (c == '\0' || c == ',') + break; + + if (!isxdigit(c)) + return -EINVAL; + + /* + * Make sure there are at least 4 free bits in 'chunk'. + * If not, this hexdigit will overflow 'chunk', so + * throw an error. + */ + if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) + return -EOVERFLOW; + + chunk = (chunk << 4) | unhex(c); + ndigits++; totaldigits++; + } + if (ndigits == 0) + return -EINVAL; + if (nchunks == 0 && chunk == 0) + continue; + + bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits); + *maskp |= chunk; + nchunks++; + nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ; + if (nbits > nmaskbits) + return -EOVERFLOW; + } while (buflen && c == ','); + + return 0; +} +#endif + +#ifndef __CHECKER__ +# undef __cond_lock +# define __cond_lock(x,c) (c) +#endif + +#ifndef KERNEL_HAS_GFP_T +#define KERNEL_HAS_GFP_T +typedef unsigned gfp_t; +#endif --- linux-2.6.27.orig/ubuntu/drbd/Makefile +++ linux-2.6.27/ubuntu/drbd/Makefile @@ -0,0 +1,7 @@ +drbd-objs := drbd_buildtag.o drbd_bitmap.o drbd_proc.o \ + drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o \ + lru_cache.o drbd_main.o drbd_strings.o drbd_nl.o + +EXTRA_CFLAGS += -I$(src) + +obj-$(CONFIG_BLK_DEV_DRBD) += drbd.o --- linux-2.6.27.orig/ubuntu/drbd/drbd_nl.c +++ linux-2.6.27/ubuntu/drbd/drbd_nl.c @@ -0,0 +1,2197 @@ +/* +-*- linux-c -*- + drbd_nl.c + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 1999-2008, Philipp Reisner . + Copyright (C) 2002-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include +#include +#include +#include +#include /* for fsync_bdev */ +#include +#include +#include +#include +#include +#include + +#include "drbd_int.h" +#include +#include + +/* see get_sb_bdev and bd_claim */ +static char *drbd_m_holder = "Hands off! this is DRBD's meta data device."; + +/* Generate the tag_list to struct functions */ +#define NL_PACKET(name, number, fields) \ +STATIC int name ## _from_tags (struct drbd_conf *mdev, \ + unsigned short *tags, struct name *arg) \ +{ \ + int tag; \ + int dlen; \ + \ + while ( (tag = *tags++) != TT_END ) { \ + dlen = *tags++; \ + switch ( tag_number(tag) ) { \ + fields \ + default: \ + if (tag & T_MANDATORY) { \ + ERR("Unknown tag: %d\n", tag_number(tag)); \ + return 0; \ + } \ + } \ + tags = (unsigned short *)((char *)tags + dlen); \ + } \ + return 1; \ +} +#define NL_INTEGER(pn, pr, member) \ + case pn: /* D_ASSERT( tag_type(tag) == TT_INTEGER ); */ \ + arg->member = *(int *)(tags); \ + break; +#define NL_INT64(pn, pr, member) \ + case pn: /* D_ASSERT( tag_type(tag) == TT_INT64 ); */ \ + arg->member = *(u64 *)(tags); \ + break; +#define NL_BIT(pn, pr, member) \ + case pn: /* D_ASSERT( tag_type(tag) == TT_BIT ); */ \ + arg->member = *(char *)(tags) ? 1 : 0; \ + break; +#define NL_STRING(pn, pr, member, len) \ + case pn: /* D_ASSERT( tag_type(tag) == TT_STRING ); */ \ + arg->member ## _len = dlen; \ + memcpy(arg->member, tags, min_t(size_t, dlen, len)); \ + break; +#include "linux/drbd_nl.h" + +// Generate the struct to tag_list functions +#define NL_PACKET(name, number, fields) \ +STATIC unsigned short* \ +name ## _to_tags (struct drbd_conf *mdev, \ + struct name *arg, unsigned short *tags) \ +{ \ + fields \ + return tags; \ +} + +#define NL_INTEGER(pn, pr, member) \ + *tags++ = pn | pr | TT_INTEGER; \ + *tags++ = sizeof(int); \ + *(int *)tags = arg->member; \ + tags = (unsigned short *)((char *)tags+sizeof(int)); +#define NL_INT64(pn, pr, member) \ + *tags++ = pn | pr | TT_INT64; \ + *tags++ = sizeof(u64); \ + *(u64 *)tags = arg->member; \ + tags = (unsigned short *)((char *)tags+sizeof(u64)); +#define NL_BIT(pn, pr, member) \ + *tags++ = pn | pr | TT_BIT; \ + *tags++ = sizeof(char); \ + *(char *)tags = arg->member; \ + tags = (unsigned short *)((char *)tags+sizeof(char)); +#define NL_STRING(pn, pr, member, len) \ + *tags++ = pn | pr | TT_STRING; \ + *tags++ = arg->member ## _len; \ + memcpy(tags, arg->member, arg->member ## _len); \ + tags = (unsigned short *)((char *)tags + arg->member ## _len); +#include "linux/drbd_nl.h" + +void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name); +void drbd_nl_send_reply(struct cn_msg *, int); + +STATIC char *nl_packet_name(int packet_type) +{ +/* Generate packet type strings */ +#define NL_PACKET(name, number, fields) \ + [ P_ ## name ] = # name, +#define NL_INTEGER Argh! +#define NL_BIT Argh! +#define NL_INT64 Argh! +#define NL_STRING Argh! + + static char *nl_tag_name[P_nl_after_last_packet] = { +#include "linux/drbd_nl.h" + }; + + return (packet_type < sizeof(nl_tag_name)/sizeof(nl_tag_name[0])) ? + nl_tag_name[packet_type] : "*Unknown*"; +} + +STATIC void nl_trace_packet(void *data) +{ + struct cn_msg *req = data; + struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req *)req->data; + + printk(KERN_INFO "drbd%d: " + "Netlink: << %s (%d) - seq: %x, ack: %x, len: %x\n", + nlp->drbd_minor, + nl_packet_name(nlp->packet_type), + nlp->packet_type, + req->seq, req->ack, req->len); +} + +STATIC void nl_trace_reply(void *data) +{ + struct cn_msg *req = data; + struct drbd_nl_cfg_reply *nlp = (struct drbd_nl_cfg_reply *)req->data; + + printk(KERN_INFO "drbd%d: " + "Netlink: >> %s (%d) - seq: %x, ack: %x, len: %x\n", + nlp->minor, + nlp->packet_type == P_nl_after_last_packet? + "Empty-Reply" : nl_packet_name(nlp->packet_type), + nlp->packet_type, + req->seq, req->ack, req->len); +} + +int drbd_khelper(struct drbd_conf *mdev, char *cmd) +{ + char mb[12]; + char *argv[] = {usermode_helper, cmd, mb, NULL }; + static char *envp[] = { "HOME=/", + "TERM=linux", + "PATH=/sbin:/usr/sbin:/bin:/usr/bin", + NULL }; + + snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev)); + + INFO("helper command: %s %s\n", usermode_helper, cmd); + + drbd_bcast_ev_helper(mdev, cmd); + return call_usermodehelper(usermode_helper, argv, envp, 1); +} + +enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev) +{ + char *ex_to_string; + int r; + enum drbd_disk_state nps; + enum fencing_policy fp; + + D_ASSERT(mdev->state.pdsk == DUnknown); + + if (inc_local_if_state(mdev, Consistent)) { + fp = mdev->bc->dc.fencing; + dec_local(mdev); + } else { + DRBD_WARN("Not outdating peer, I'm not even Consistent myself.\n"); + return mdev->state.pdsk; + } + + if (fp == Stonith) + _drbd_request_state(mdev, NS(susp,1), ChgWaitComplete); + + r = drbd_khelper(mdev, "outdate-peer"); + + switch ((r>>8) & 0xff) { + case 3: /* peer is inconsistent */ + ex_to_string = "peer is inconsistent or worse"; + nps = Inconsistent; + break; + case 4: + ex_to_string = "peer is outdated"; + nps = Outdated; + break; + case 5: /* peer was down, we will(have) create(d) a new UUID anyways... */ + /* If we would be more strict, we would return DUnknown here. */ + ex_to_string = "peer is unreachable, assumed to be dead"; + nps = Outdated; + break; + case 6: /* Peer is primary, voluntarily outdate myself. + * This is useful when an unconnected Secondary is asked to + * become Primary, but findes the other peer being active. */ + ex_to_string = "peer is active"; + DRBD_WARN("Peer is primary, outdating myself.\n"); + nps = DUnknown; + _drbd_request_state(mdev, NS(disk, Outdated), ChgWaitComplete); + break; + case 7: + if (fp != Stonith) + ERR("outdate-peer() = 7 && fencing != Stonith !!!\n"); + ex_to_string = "peer was stonithed"; + nps = Outdated; + break; + default: + /* The script is broken ... */ + nps = DUnknown; + ERR("outdate-peer helper broken, returned %d\n", (r>>8)&0xff); + return nps; + } + + INFO("outdate-peer helper returned %d (%s)\n", + (r>>8) & 0xff, ex_to_string); + return nps; +} + + +int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) +{ + const int max_tries = 4; + int r = 0; + int try = 0; + int forced = 0; + union drbd_state_t mask, val; + enum drbd_disk_state nps; + + if (new_role == Primary) + request_ping(mdev); /* Detect a dead peer ASAP */ + + mutex_lock(&mdev->state_mutex); + + mask.i = 0; mask.role = role_mask; + val.i = 0; val.role = new_role; + + while (try++ < max_tries) { + r = _drbd_request_state(mdev, mask, val, ChgWaitComplete); + + /* in case we first succeeded to outdate, + * but now suddenly could establish a connection */ + if (r == SS_CW_FailedByPeer && mask.pdsk != 0) { + val.pdsk = 0; + mask.pdsk = 0; + continue; + } + + if( r == SS_NoUpToDateDisk && force && + ( mdev->state.disk == Inconsistent || + mdev->state.disk == Outdated ) ) { + mask.disk = disk_mask; + val.disk = UpToDate; + forced = 1; + continue; + } + + if ( r == SS_NoUpToDateDisk && + mdev->state.disk == Consistent ) { + D_ASSERT(mdev->state.pdsk == DUnknown); + nps = drbd_try_outdate_peer(mdev); + + if (nps == Outdated) { + val.disk = UpToDate; + mask.disk = disk_mask; + } + + val.pdsk = nps; + mask.pdsk = disk_mask; + + continue; + } + + if (r == SS_NothingToDo) + goto fail; + if (r == SS_PrimaryNOP) { + nps = drbd_try_outdate_peer(mdev); + + if (force && nps > Outdated) { + DRBD_WARN("Forced into split brain situation!\n"); + nps = Outdated; + } + + mask.pdsk = disk_mask; + val.pdsk = nps; + + continue; + } + if (r == SS_TwoPrimaries) { + /* Maybe the peer is detected as dead very soon... + retry at most once more in this case. */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((mdev->net_conf->ping_timeo+1)*HZ/10); + if (try < max_tries) + try = max_tries -1; + continue; + } + if (r < SS_Success) { + r = _drbd_request_state(mdev, mask, val, + ChgStateVerbose + ChgWaitComplete); + if (r < SS_Success) + goto fail; + } + break; + } + + if (forced) + DRBD_WARN("Forced to consider local data as UpToDate!\n"); + + fsync_bdev(mdev->this_bdev); + + /* Wait until nothing is on the fly :) */ + wait_event(mdev->misc_wait, atomic_read(&mdev->ap_pending_cnt) == 0); + + /* FIXME RACE here: if our direct user is not using bd_claim (i.e. + * not a filesystem) since cstate might still be >= Connected, new + * ap requests may come in and increase ap_pending_cnt again! + * but that means someone is misusing DRBD... + * */ + + if (new_role == Secondary) { + set_disk_ro(mdev->vdisk, TRUE ); + if (inc_local(mdev)) { + mdev->bc->md.uuid[Current] &= ~(u64)1; + dec_local(mdev); + } + } else { + if (inc_net(mdev)) { + mdev->net_conf->want_lose = 0; + dec_net(mdev); + } + set_disk_ro(mdev->vdisk, FALSE ); + if (inc_local(mdev)) { + if ( ((mdev->state.conn < Connected || + mdev->state.pdsk <= Failed) + && mdev->bc->md.uuid[Bitmap] == 0) || forced) + drbd_uuid_new_current(mdev); + + mdev->bc->md.uuid[Current] |= (u64)1; + dec_local(mdev); + } + } + + if ((new_role == Secondary) && inc_local(mdev) ) + { + drbd_al_to_on_disk_bm(mdev); + dec_local(mdev); + } + + if (mdev->state.conn >= WFReportParams) { + /* if this was forced, we should consider sync */ + if (forced) + drbd_send_uuids(mdev); + drbd_send_state(mdev); + } + + drbd_md_sync(mdev); + + fail: + mutex_unlock(&mdev->state_mutex); + return r; +} + + +STATIC int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + struct primary primary_args; + + memset(&primary_args, 0, sizeof(struct primary)); + if (!primary_from_tags(mdev, nlp->tag_list, &primary_args)) { + reply->ret_code = UnknownMandatoryTag; + return 0; + } + + reply->ret_code = + drbd_set_role(mdev, Primary, primary_args.overwrite_peer); + + return 0; +} + +STATIC int drbd_nl_secondary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + reply->ret_code = drbd_set_role(mdev, Secondary, 0); + + return 0; +} + +/* initializes the md.*_offset members, so we are able to find + * the on disk meta data */ +STATIC void drbd_md_set_sector_offsets(struct drbd_conf *mdev, + struct drbd_backing_dev *bdev) +{ + sector_t md_size_sect = 0; + switch (bdev->dc.meta_dev_idx) { + default: + /* v07 style fixed size indexed meta data */ + bdev->md.md_size_sect = MD_RESERVED_SECT; + bdev->md.md_offset = drbd_md_ss__(mdev, bdev); + bdev->md.al_offset = MD_AL_OFFSET; + bdev->md.bm_offset = MD_BM_OFFSET; + break; + case DRBD_MD_INDEX_FLEX_EXT: + /* just occupy the full device; unit: sectors */ + bdev->md.md_size_sect = drbd_get_capacity(bdev->md_bdev); + bdev->md.md_offset = 0; + bdev->md.al_offset = MD_AL_OFFSET; + bdev->md.bm_offset = MD_BM_OFFSET; + break; + case DRBD_MD_INDEX_INTERNAL: + case DRBD_MD_INDEX_FLEX_INT: + bdev->md.md_offset = drbd_md_ss__(mdev, bdev); + /* al size is still fixed */ + bdev->md.al_offset = -MD_AL_MAX_SIZE; + /* LGE FIXME max size check missing. */ + /* we need (slightly less than) ~ this much bitmap sectors: */ + md_size_sect = drbd_get_capacity(bdev->backing_bdev); + md_size_sect = ALIGN(md_size_sect, BM_SECT_PER_EXT); + md_size_sect = BM_SECT_TO_EXT(md_size_sect); + md_size_sect = ALIGN(md_size_sect, 8); + + /* plus the "drbd meta data super block", + * and the activity log; */ + md_size_sect += MD_BM_OFFSET; + + bdev->md.md_size_sect = md_size_sect; + /* bitmap offset is adjusted by 'super' block size */ + bdev->md.bm_offset = -md_size_sect + MD_AL_OFFSET; + break; + } +} + +char *ppsize(char *buf, unsigned long long size) +{ + /* Needs 9 bytes at max. */ + static char units[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; + int base = 0; + while (size >= 10000 ) { + /* shift + round */ + size = (size >> 10) + !!(size & (1<<9)); + base++; + } + sprintf(buf, "%lu %cB", (long)size, units[base]); + + return buf; +} + +/** + * drbd_determin_dev_size: + * Evaluates all constraints and sets our correct device size. + * Negative return values indicate errors. 0 and positive values + * indicate success. + * You should call drbd_md_sync() after calling this function. + */ +enum determin_dev_size_enum drbd_determin_dev_size(struct drbd_conf *mdev) __must_hold(local) +{ + sector_t prev_first_sect, prev_size; /* previous meta location */ + sector_t la_size; + sector_t size; + char ppb[10]; + + int md_moved, la_size_changed; + enum determin_dev_size_enum rv=unchanged; + + wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); + + prev_first_sect = drbd_md_first_sector(mdev->bc); + prev_size = mdev->bc->md.md_size_sect; + la_size = mdev->bc->md.la_size_sect; + + /* TODO: should only be some assert here, not (re)init... */ + drbd_md_set_sector_offsets(mdev, mdev->bc); + + size = drbd_new_dev_size(mdev, mdev->bc); + + if ( drbd_get_capacity(mdev->this_bdev) != size || + drbd_bm_capacity(mdev) != size ) { + int err; + err = drbd_bm_resize(mdev, size); + if (unlikely(err)) { + /* currently there is only one error: ENOMEM! */ + size = drbd_bm_capacity(mdev)>>1; + if (size == 0) { + ERR("OUT OF MEMORY! " + "Could not allocate bitmap! "); + } else { + /* FIXME this is problematic, + * if we in fact are smaller now! */ + ERR("BM resizing failed. " + "Leaving size unchanged at size = %lu KB\n", + (unsigned long)size); + } + rv = dev_size_error; + } + /* racy, see comments above. */ + drbd_set_my_capacity(mdev, size); + mdev->bc->md.la_size_sect = size; + INFO("size = %s (%llu KB)\n", ppsize(ppb, size>>1), + (unsigned long long)size>>1); + } + if (rv == dev_size_error) + goto out; + + la_size_changed = (la_size != mdev->bc->md.la_size_sect); + + /* LGE: flexible device size!! is this the right thing to test? */ + md_moved = prev_first_sect != drbd_md_first_sector(mdev->bc) + || prev_size != mdev->bc->md.md_size_sect; + + if (md_moved) { + DRBD_WARN("Moving meta-data.\n"); + /* assert: (flexible) internal meta data */ + } + + if (la_size_changed || md_moved) { + drbd_al_shrink(mdev); /* All extents inactive. */ + INFO("Writing the whole bitmap, size changed\n"); + rv = drbd_bitmap_io(mdev, &drbd_bm_write); + drbd_md_mark_dirty(mdev); + } + + if (size > la_size) rv = grew; + if (size < la_size) rv = shrunk; +out: + lc_unlock(mdev->act_log); + wake_up(&mdev->al_wait); + + return rv; +} + +sector_t +drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) +{ + sector_t p_size = mdev->p_size; /* partner's disk size. */ + sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */ + sector_t m_size; /* my size */ + sector_t u_size = bdev->dc.disk_size; /* size requested by user. */ + sector_t size = 0; + + m_size = drbd_get_max_capacity(bdev); + + if (p_size && m_size) { + size = min_t(sector_t, p_size, m_size); + } else { + if (la_size) { + size = la_size; + if (m_size && m_size < size) + size = m_size; + if (p_size && p_size < size) + size = p_size; + } else { + if (m_size) + size = m_size; + if (p_size) + size = p_size; + } + } + + if (size == 0) + ERR("Both nodes diskless!\n"); + + if (u_size) { + if (u_size > size) + ERR("Requested disk size is too big (%lu > %lu)\n", + (unsigned long)u_size>>1, (unsigned long)size>>1); + else + size = u_size; + } + + return size; +} + +/** + * drbd_check_al_size: + * checks that the al lru is of requested size, and if neccessary tries to + * allocate a new one. returns -EBUSY if current al lru is still used, + * -ENOMEM when allocation failed, and 0 on success. You should call + * drbd_md_sync() after you called this function. + */ +STATIC int drbd_check_al_size(struct drbd_conf *mdev) +{ + struct lru_cache *n, *t; + struct lc_element *e; + unsigned int in_use; + int i; + + ERR_IF(mdev->sync_conf.al_extents < 7) + mdev->sync_conf.al_extents = 127; + + if ( mdev->act_log && + mdev->act_log->nr_elements == mdev->sync_conf.al_extents ) + return 0; + + in_use = 0; + t = mdev->act_log; + n = lc_alloc("act_log", mdev->sync_conf.al_extents, + sizeof(struct lc_element), mdev); + + if (n == NULL) { + ERR("Cannot allocate act_log lru!\n"); + return -ENOMEM; + } + spin_lock_irq(&mdev->al_lock); + if (t) { + for (i = 0; i < t->nr_elements; i++) { + e = lc_entry(t, i); + if (e->refcnt) + ERR("refcnt(%d)==%d\n", + e->lc_number, e->refcnt); + in_use += e->refcnt; + } + } + if (!in_use) + mdev->act_log = n; + spin_unlock_irq(&mdev->al_lock); + if (in_use) { + ERR("Activity log still in use!\n"); + lc_free(n); + return -EBUSY; + } else { + if (t) + lc_free(t); + } + drbd_md_mark_dirty(mdev); /* we changed mdev->act_log->nr_elemens */ + return 0; +} + +void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __must_hold(local) +{ + struct request_queue * const q = mdev->rq_queue; + struct request_queue * const b = mdev->bc->backing_bdev->bd_disk->queue; + /* unsigned int old_max_seg_s = q->max_segment_size; */ + int max_segments = mdev->bc->dc.max_bio_bvecs; + + if (b->merge_bvec_fn && !mdev->bc->dc.use_bmbv) + max_seg_s = PAGE_SIZE; + + max_seg_s = min(b->max_sectors * b->hardsect_size, max_seg_s); + + MTRACE(TraceTypeRq, TraceLvlSummary, + DUMPI(b->max_sectors); + DUMPI(b->max_phys_segments); + DUMPI(b->max_hw_segments); + DUMPI(b->max_segment_size); + DUMPI(b->hardsect_size); + DUMPI(b->seg_boundary_mask); + ); + + q->max_sectors = max_seg_s >> 9; + if (max_segments) { + q->max_phys_segments = max_segments; + q->max_hw_segments = max_segments; + } else { + q->max_phys_segments = MAX_PHYS_SEGMENTS; + q->max_hw_segments = MAX_HW_SEGMENTS; + } + q->max_segment_size = max_seg_s; + q->hardsect_size = 512; + q->seg_boundary_mask = PAGE_SIZE-1; + blk_queue_stack_limits(q, b); + + /* KERNEL BUG. in ll_rw_blk.c ?? + * t->max_segment_size = min(t->max_segment_size,b->max_segment_size); + * should be + * t->max_segment_size = min_not_zero(...,...) + * workaround here: */ + if (q->max_segment_size == 0) + q->max_segment_size = max_seg_s; + + MTRACE(TraceTypeRq, TraceLvlSummary, + DUMPI(q->max_sectors); + DUMPI(q->max_phys_segments); + DUMPI(q->max_hw_segments); + DUMPI(q->max_segment_size); + DUMPI(q->hardsect_size); + DUMPI(q->seg_boundary_mask); + ); + + if (b->merge_bvec_fn) + DRBD_WARN("Backing device's merge_bvec_fn() = %p\n", + b->merge_bvec_fn); + INFO("max_segment_size ( = BIO size ) = %u\n", q->max_segment_size); + + if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) { + INFO("Adjusting my ra_pages to backing device's (%lu -> %lu)\n", + q->backing_dev_info.ra_pages, + b->backing_dev_info.ra_pages); + q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages; + } +} + +/* does always return 0; + * interesting return code is in reply->ret_code */ +STATIC int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + enum ret_codes retcode; + struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */ + struct inode *inode, *inode2; + struct lru_cache *resync_lru = NULL; + union drbd_state_t ns, os; + int rv, ntries = 0; + + /* if you want to reconfigure, please tear down first */ + if (mdev->state.disk > Diskless) { + retcode = HaveDiskConfig; + goto fail; + } + + /* + * We may have gotten here very quickly from a detach. Wait for a bit + * then fail. + */ + while (1) { + __no_warn(local, nbc = mdev->bc; ); + if (nbc == NULL) + break; + if (ntries++ >= 5) { + DRBD_WARN("drbd_nl_disk_conf: mdev->bc not NULL.\n"); + retcode = HaveDiskConfig; + goto fail; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + } + + nbc = kmalloc(sizeof(struct drbd_backing_dev), GFP_KERNEL); + if (!nbc) { + retcode = KMallocFailed; + goto fail; + } + + if ( !(nlp->flags & DRBD_NL_SET_DEFAULTS) && inc_local(mdev) ) { + memcpy(&nbc->dc, &mdev->bc->dc, sizeof(struct disk_conf)); + dec_local(mdev); + } else { + memset(&nbc->dc, 0, sizeof(struct disk_conf)); + nbc->dc.disk_size = DRBD_DISK_SIZE_SECT_DEF; + nbc->dc.on_io_error = DRBD_ON_IO_ERROR_DEF; + nbc->dc.fencing = DRBD_FENCING_DEF; + nbc->dc.max_bio_bvecs= DRBD_MAX_BIO_BVECS_DEF; + } + + if (!disk_conf_from_tags(mdev, nlp->tag_list, &nbc->dc)) { + retcode = UnknownMandatoryTag; + goto fail; + } + + nbc->lo_file = NULL; + nbc->md_file = NULL; + + if (nbc->dc.meta_dev_idx < DRBD_MD_INDEX_FLEX_INT) { + retcode = LDMDInvalid; + goto fail; + } + + nbc->lo_file = filp_open(nbc->dc.backing_dev, O_RDWR, 0); + if (IS_ERR(nbc->lo_file)) { + ERR("open(\"%s\") failed with %ld\n", nbc->dc.backing_dev, + PTR_ERR(nbc->lo_file)); + nbc->lo_file = NULL; + retcode = LDNameInvalid; + goto fail; + } + + inode = nbc->lo_file->f_dentry->d_inode; + + if (!S_ISBLK(inode->i_mode)) { + retcode = LDNoBlockDev; + goto fail; + } + + nbc->md_file = filp_open(nbc->dc.meta_dev, O_RDWR, 0); + if (IS_ERR(nbc->md_file)) { + ERR("open(\"%s\") failed with %ld\n", nbc->dc.meta_dev, + PTR_ERR(nbc->md_file)); + nbc->md_file = NULL; + retcode = MDNameInvalid; + goto fail; + } + + inode2 = nbc->md_file->f_dentry->d_inode; + + if (!S_ISBLK(inode2->i_mode)) { + retcode = MDNoBlockDev; + goto fail; + } + + nbc->backing_bdev = inode->i_bdev; + if (bd_claim(nbc->backing_bdev, mdev)) { + printk(KERN_ERR "drbd: bd_claim(%p,%p); failed [%p;%p;%u]\n", + nbc->backing_bdev, mdev, + nbc->backing_bdev->bd_holder, + nbc->backing_bdev->bd_contains->bd_holder, + nbc->backing_bdev->bd_holders); + retcode = LDMounted; + goto fail; + } + + resync_lru = lc_alloc("resync", 61, sizeof(struct bm_extent), mdev); + if (!resync_lru) { + retcode = KMallocFailed; + goto fail; + } + + if (!mdev->bitmap) { + if(drbd_bm_init(mdev)) { + retcode = KMallocFailed; + goto fail; + } + } + + nbc->md_bdev = inode2->i_bdev; + if (bd_claim(nbc->md_bdev, + (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL || + nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT) ? + (void *)mdev : (void *) drbd_m_holder )) { + retcode = MDMounted; + goto release_bdev_fail; + } + + if ( (nbc->backing_bdev == nbc->md_bdev) != + (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL || + nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT) ) { + retcode = LDMDInvalid; + goto release_bdev2_fail; + } + + if ((drbd_get_capacity(nbc->backing_bdev)) < nbc->dc.disk_size) { + retcode = LDDeviceTooSmall; + goto release_bdev2_fail; + } + +/* TODO check whether backing device size is within plausible limits */ + + /* Make sure the new disk is big enough + * (we may currently be Primary with no local disk...) */ + if (drbd_get_capacity(nbc->backing_bdev) < + drbd_get_capacity(mdev->this_bdev) ) { + retcode = LDDeviceTooSmall; + goto release_bdev2_fail; + } + + nbc->known_size = drbd_get_capacity(nbc->backing_bdev); + + retcode = _drbd_request_state(mdev, NS(disk, Attaching), ChgStateVerbose); + if (retcode < SS_Success ) + goto release_bdev2_fail; + + if (!inc_local_if_state(mdev, Attaching)) { + goto force_diskless; + } + + drbd_thread_start(&mdev->worker); + drbd_md_set_sector_offsets(mdev, nbc); + + retcode = drbd_md_read(mdev, nbc); + if (retcode != NoError) + goto force_diskless_dec; + + if (mdev->state.conn < Connected && + mdev->state.role == Primary && + (mdev->ed_uuid & ~((u64)1)) != (nbc->md.uuid[Current] & ~((u64)1))) { + ERR("Can only attach to data with current UUID=%016llX\n", + (unsigned long long)mdev->ed_uuid); + retcode = DataOfWrongCurrent; + goto force_diskless_dec; + } + + /* Since we are diskless, fix the AL first... */ + if (drbd_check_al_size(mdev)) { + retcode = KMallocFailed; + goto force_diskless_dec; + } + + /* Prevent shrinking of consistent devices ! */ + if (drbd_md_test_flag(nbc, MDF_Consistent) && + drbd_new_dev_size(mdev, nbc) < nbc->md.la_size_sect) { + retcode = LDDeviceTooSmall; + goto force_diskless_dec; + } + + if (!drbd_al_read_log(mdev, nbc)) { + retcode = MDIOError; + goto force_diskless_dec; + } + + /* Reset the "barriers don't work" bits here, then force meta data to + * be written, to ensure we determine if barriers are supported. */ + if (nbc->dc.no_disk_flush) + set_bit(LL_DEV_NO_FLUSH, &mdev->flags); + else + clear_bit(LL_DEV_NO_FLUSH, &mdev->flags); + + if (nbc->dc.no_md_flush) + set_bit(MD_NO_BARRIER, &mdev->flags); + else + clear_bit(MD_NO_BARRIER, &mdev->flags); + + /* Point of no return reached. + * Devices and memory are no longer released by error cleanup below. + * now mdev takes over responsibility, and the state engine should + * clean it up somewhere. */ + D_ASSERT(mdev->bc == NULL); + mdev->bc = nbc; + mdev->resync = resync_lru; + nbc = NULL; + resync_lru = NULL; + + if (drbd_md_test_flag(mdev->bc, MDF_PrimaryInd)) + set_bit(CRASHED_PRIMARY, &mdev->flags); + else + clear_bit(CRASHED_PRIMARY, &mdev->flags); + + mdev->send_cnt = 0; + mdev->recv_cnt = 0; + mdev->read_cnt = 0; + mdev->writ_cnt = 0; + + drbd_setup_queue_param(mdev, DRBD_MAX_SEGMENT_SIZE); + /* + * FIXME currently broken. + * drbd_set_recv_tcq(mdev, + * drbd_queue_order_type(mdev)==QUEUE_ORDERED_TAG); + */ + + /* If I am currently not Primary, + * but meta data primary indicator is set, + * I just now recover from a hard crash, + * and have been Primary before that crash. + * + * Now, if I had no connection before that crash + * (have been degraded Primary), chances are that + * I won't find my peer now either. + * + * In that case, and _only_ in that case, + * we use the degr-wfc-timeout instead of the default, + * so we can automatically recover from a crash of a + * degraded but active "cluster" after a certain timeout. + */ + clear_bit(USE_DEGR_WFC_T, &mdev->flags); + if ( mdev->state.role != Primary && + drbd_md_test_flag(mdev->bc, MDF_PrimaryInd) && + !drbd_md_test_flag(mdev->bc, MDF_ConnectedInd) ) + set_bit(USE_DEGR_WFC_T, &mdev->flags); + + if (drbd_determin_dev_size(mdev) == dev_size_error) { + retcode = VMallocFailed; + goto force_diskless_dec; + } + + if (drbd_md_test_flag(mdev->bc, MDF_FullSync)) { + INFO("Assuming that all blocks are out of sync " + "(aka FullSync)\n"); + if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write)) { + retcode = MDIOError; + goto force_diskless_dec; + } + } else { + if (drbd_bitmap_io(mdev, &drbd_bm_read) < 0) { + retcode = MDIOError; + goto force_diskless_dec; + } + } + + if (test_bit(CRASHED_PRIMARY, &mdev->flags)) { + drbd_al_apply_to_bm(mdev); + drbd_al_to_on_disk_bm(mdev); + } + /* else { + FIXME wipe out on disk al! + } */ + + spin_lock_irq(&mdev->req_lock); + os = mdev->state; + ns.i = os.i; + /* If MDF_Consistent is not set go into inconsistent state, + otherwise investige MDF_WasUpToDate... + If MDF_WasUpToDate is not set go into Outdated disk state, + otherwise into Consistent state. + */ + if (drbd_md_test_flag(mdev->bc, MDF_Consistent)) { + if (drbd_md_test_flag(mdev->bc, MDF_WasUpToDate)) + ns.disk = Consistent; + else + ns.disk = Outdated; + } else { + ns.disk = Inconsistent; + } + + if (drbd_md_test_flag(mdev->bc, MDF_PeerOutDated)) + ns.pdsk = Outdated; + + if ( ns.disk == Consistent && + ( ns.pdsk == Outdated || mdev->bc->dc.fencing == DontCare ) ) + ns.disk = UpToDate; + + /* All tests on MDF_PrimaryInd, MDF_ConnectedInd, + MDF_Consistent and MDF_WasUpToDate must happen before + this point, because drbd_request_state() modifies these + flags. */ + + /* In case we are Connected postpone any desicion on the new disk + state after the negotiation phase. */ + if (mdev->state.conn == Connected) { + mdev->new_state_tmp.i = ns.i; + ns.i = os.i; + ns.disk = Negotiating; + } + + rv = _drbd_set_state(mdev, ns, ChgStateVerbose, NULL); + ns = mdev->state; + spin_unlock_irq(&mdev->req_lock); + + if (rv < SS_Success) + goto force_diskless_dec; + + if(mdev->state.role == Primary) mdev->bc->md.uuid[Current] |= (u64)1; + else mdev->bc->md.uuid[Current] &= ~(u64)1; + + drbd_md_mark_dirty(mdev); + drbd_md_sync(mdev); + + dec_local(mdev); + reply->ret_code = retcode; + return 0; + + force_diskless_dec: + dec_local(mdev); + force_diskless: + drbd_force_state(mdev, NS(disk, Diskless)); + drbd_md_sync(mdev); + release_bdev2_fail: + if (nbc) + bd_release(nbc->md_bdev); + release_bdev_fail: + if (nbc) + bd_release(nbc->backing_bdev); + fail: + if (nbc) { + if (nbc->lo_file) + fput(nbc->lo_file); + if (nbc->md_file) + fput(nbc->md_file); + kfree(nbc); + } + if (resync_lru) + lc_free(resync_lru); + + reply->ret_code = retcode; + return 0; +} + +STATIC int drbd_nl_detach(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + fsync_bdev(mdev->this_bdev); + reply->ret_code = drbd_request_state(mdev, NS(disk, Diskless)); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/20); /* 50ms; Time for worker to finally terminate */ + + return 0; +} + +#define HMAC_NAME_L 20 + +STATIC int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + int i, ns; + enum ret_codes retcode; + struct net_conf *new_conf = NULL; + struct crypto_hash *tfm = NULL; + struct crypto_hash *integrity_w_tfm = NULL; + struct crypto_hash *integrity_r_tfm = NULL; + struct hlist_head *new_tl_hash = NULL; + struct hlist_head *new_ee_hash = NULL; + struct drbd_conf *odev; + char hmac_name[HMAC_NAME_L]; + void *int_dig_out = NULL; + void *int_dig_in = NULL; + void *int_dig_vv = NULL; + + if (mdev->state.conn > StandAlone) { + retcode = HaveNetConfig; + goto fail; + } + + new_conf = kmalloc(sizeof(struct net_conf), GFP_KERNEL); + if (!new_conf) { + retcode = KMallocFailed; + goto fail; + } + + if ( !(nlp->flags & DRBD_NL_SET_DEFAULTS) && inc_net(mdev)) { + memcpy(new_conf, mdev->net_conf, sizeof(struct net_conf)); + dec_net(mdev); + } else { + memset(new_conf, 0, sizeof(struct net_conf)); + new_conf->timeout = DRBD_TIMEOUT_DEF; + new_conf->try_connect_int = DRBD_CONNECT_INT_DEF; + new_conf->ping_int = DRBD_PING_INT_DEF; + new_conf->max_epoch_size = DRBD_MAX_EPOCH_SIZE_DEF; + new_conf->max_buffers = DRBD_MAX_BUFFERS_DEF; + new_conf->unplug_watermark = DRBD_UNPLUG_WATERMARK_DEF; + new_conf->sndbuf_size = DRBD_SNDBUF_SIZE_DEF; + new_conf->ko_count = DRBD_KO_COUNT_DEF; + new_conf->after_sb_0p = DRBD_AFTER_SB_0P_DEF; + new_conf->after_sb_1p = DRBD_AFTER_SB_1P_DEF; + new_conf->after_sb_2p = DRBD_AFTER_SB_2P_DEF; + new_conf->want_lose = 0; + new_conf->two_primaries = 0; + new_conf->wire_protocol = DRBD_PROT_C; + new_conf->ping_timeo = DRBD_PING_TIMEO_DEF; + new_conf->rr_conflict = DRBD_RR_CONFLICT_DEF; + } + + if (!net_conf_from_tags(mdev, nlp->tag_list, new_conf)) { + retcode = UnknownMandatoryTag; + goto fail; + } + + if (new_conf->two_primaries + && (new_conf->wire_protocol != DRBD_PROT_C)) { + retcode = ProtocolCRequired; + goto fail; + }; + + if (mdev->state.role == Primary && new_conf->want_lose) { + retcode = DiscardNotAllowed; + goto fail; + } + +#define M_ADDR(A) (((struct sockaddr_in *)&A->my_addr)->sin_addr.s_addr) +#define M_PORT(A) (((struct sockaddr_in *)&A->my_addr)->sin_port) +#define O_ADDR(A) (((struct sockaddr_in *)&A->peer_addr)->sin_addr.s_addr) +#define O_PORT(A) (((struct sockaddr_in *)&A->peer_addr)->sin_port) + retcode = NoError; + for (i = 0; i < minor_count; i++) { + odev = minor_to_mdev(i); + if (!odev || odev == mdev) + continue; + if ( inc_net(odev)) { + if ( M_ADDR(new_conf) == M_ADDR(odev->net_conf) && + M_PORT(new_conf) == M_PORT(odev->net_conf) ) + retcode = LAAlreadyInUse; + + if (O_ADDR(new_conf) == O_ADDR(odev->net_conf) && + O_PORT(new_conf) == O_PORT(odev->net_conf) ) + retcode = OAAlreadyInUse; + + dec_net(odev); + if (retcode != NoError) + goto fail; + } + } +#undef M_ADDR +#undef M_PORT +#undef O_ADDR +#undef O_PORT + + if (new_conf->cram_hmac_alg[0] != 0) { + snprintf(hmac_name, HMAC_NAME_L, "hmac(%s)", + new_conf->cram_hmac_alg); + tfm = crypto_alloc_hash(hmac_name, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + tfm = NULL; + retcode = CRAMAlgNotAvail; + goto fail; + } + + if (crypto_tfm_alg_type(crypto_hash_tfm(tfm)) + != CRYPTO_ALG_TYPE_HASH) { + retcode = CRAMAlgNotDigest; + goto fail; + } + } + + if (new_conf->integrity_alg[0]) { + integrity_w_tfm = crypto_alloc_hash(new_conf->integrity_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(integrity_w_tfm)) { + integrity_w_tfm = NULL; + retcode=IntegrityAlgNotAvail; + goto fail; + } + + if (crypto_tfm_alg_type(crypto_hash_tfm(integrity_w_tfm)) != CRYPTO_ALG_TYPE_DIGEST) { + retcode=IntegrityAlgNotDigest; + goto fail; + } + + integrity_r_tfm = crypto_alloc_hash(new_conf->integrity_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(integrity_r_tfm)) { + integrity_r_tfm = NULL; + retcode=IntegrityAlgNotAvail; + goto fail; + } + } + + ns = new_conf->max_epoch_size/8; + if (mdev->tl_hash_s != ns) { + new_tl_hash = kzalloc(ns*sizeof(void *), GFP_KERNEL); + if (!new_tl_hash) { + retcode = KMallocFailed; + goto fail; + } + } + + ns = new_conf->max_buffers/8; + if (new_conf->two_primaries && ( mdev->ee_hash_s != ns ) ) { + new_ee_hash = kzalloc(ns*sizeof(void *), GFP_KERNEL); + if (!new_ee_hash) { + retcode = KMallocFailed; + goto fail; + } + } + + ((char *)new_conf->shared_secret)[SHARED_SECRET_MAX-1] = 0; + +#if 0 + /* for the connection loss logic in drbd_recv + * I _need_ the resulting timeo in jiffies to be + * non-zero and different + * + * XXX maybe rather store the value scaled to jiffies? + * Note: MAX_SCHEDULE_TIMEOUT/HZ*HZ != MAX_SCHEDULE_TIMEOUT + * and HZ > 10; which is unlikely to change... + * Thus, if interrupted by a signal, + * sock_{send,recv}msg returns -EINTR, + * if the timeout expires, -EAGAIN. + */ + /* unlikely: someone disabled the timeouts ... + * just put some huge values in there. */ + if (!new_conf->ping_int) + new_conf->ping_int = MAX_SCHEDULE_TIMEOUT/HZ; + if (!new_conf->timeout) + new_conf->timeout = MAX_SCHEDULE_TIMEOUT/HZ*10; + if (new_conf->ping_int*10 < new_conf->timeout) + new_conf->timeout = new_conf->ping_int*10/6; + if (new_conf->ping_int*10 == new_conf->timeout) + new_conf->ping_int = new_conf->ping_int+1; +#endif + + if (integrity_w_tfm) { + i = crypto_hash_digestsize(integrity_w_tfm); + int_dig_out = kmalloc(i, GFP_KERNEL); + if (!int_dig_out) { + retcode = KMallocFailed; + goto fail; + } + int_dig_in = kmalloc(i, GFP_KERNEL); + if (!int_dig_in) { + retcode = KMallocFailed; + goto fail; + } + int_dig_vv = kmalloc(i, GFP_KERNEL); + if (!int_dig_vv) { + retcode = KMallocFailed; + goto fail; + } + } + + if (!mdev->bitmap) { + if(drbd_bm_init(mdev)) { + retcode = KMallocFailed; + goto fail; + } + } + + D_ASSERT(mdev->net_conf == NULL); + mdev->net_conf = new_conf; + + mdev->send_cnt = 0; + mdev->recv_cnt = 0; + + if (new_tl_hash) { + kfree(mdev->tl_hash); + mdev->tl_hash_s = mdev->net_conf->max_epoch_size/8; + mdev->tl_hash = new_tl_hash; + } + + if (new_ee_hash) { + kfree(mdev->ee_hash); + mdev->ee_hash_s = mdev->net_conf->max_buffers/8; + mdev->ee_hash = new_ee_hash; + } + + crypto_free_hash(mdev->cram_hmac_tfm); + mdev->cram_hmac_tfm = tfm; + + crypto_free_hash(mdev->integrity_w_tfm); + mdev->integrity_w_tfm = integrity_w_tfm; + + crypto_free_hash(mdev->integrity_r_tfm); + mdev->integrity_r_tfm = integrity_r_tfm; + + kfree(mdev->int_dig_out); + kfree(mdev->int_dig_in); + kfree(mdev->int_dig_vv); + mdev->int_dig_out=int_dig_out; + mdev->int_dig_in=int_dig_in; + mdev->int_dig_vv=int_dig_vv; + + retcode = _drbd_request_state(mdev, NS(conn, Unconnected), ChgStateVerbose); + if (retcode >= SS_Success) + drbd_thread_start(&mdev->worker); + + reply->ret_code = retcode; + return 0; + +fail: + kfree(int_dig_out); + kfree(int_dig_in); + kfree(int_dig_vv); + crypto_free_hash(tfm); + crypto_free_hash(integrity_w_tfm); + crypto_free_hash(integrity_r_tfm); + kfree(new_tl_hash); + kfree(new_ee_hash); + kfree(new_conf); + + reply->ret_code = retcode; + return 0; +} + +STATIC int drbd_nl_disconnect(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + int retcode; + + retcode = _drbd_request_state(mdev, NS(conn, Disconnecting), ChgOrdered); + + if (retcode == SS_NothingToDo) + goto done; + else if (retcode == SS_AlreadyStandAlone) + goto done; + else if (retcode == SS_PrimaryNOP) { + /* Our statche checking code wants to see the peer outdated. */ + retcode = drbd_request_state(mdev, NS2(conn, Disconnecting, + pdsk, Outdated)); + } else if (retcode == SS_CW_FailedByPeer) { + /* The peer probabely wants to see us outdated. */ + retcode = _drbd_request_state(mdev, NS2(conn, Disconnecting, + disk, Outdated), + ChgOrdered); + if (retcode == SS_IsDiskLess || retcode == SS_LowerThanOutdated) { + drbd_force_state(mdev, NS(conn, Disconnecting)); + retcode = SS_Success; + } + + } + + if (retcode < SS_Success) + goto fail; + + if (wait_event_interruptible(mdev->state_wait, + mdev->state.conn != Disconnecting) ) { + /* Do not test for mdev->state.conn == StandAlone, since + someone else might connect us in the mean time! */ + retcode = GotSignal; + goto fail; + } + + done: + retcode = NoError; + fail: + drbd_md_sync(mdev); + reply->ret_code = retcode; + return 0; +} + +void resync_after_online_grow(struct drbd_conf *mdev) +{ + int iass; /* I am sync source */ + + INFO("Resync of new storage after online grow\n"); + if (mdev->state.role != mdev->state.peer) + iass = (mdev->state.role == Primary); + else + iass = test_bit(DISCARD_CONCURRENT,&mdev->flags); + + if (iass) + drbd_start_resync(mdev,SyncSource); + else + drbd_request_state(mdev,NS(conn,WFSyncUUID)); +} + +STATIC int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + struct resize rs; + int retcode = NoError; + int ldsc = 0; /* local disk size changed */ + enum determin_dev_size_enum dd; + + memset(&rs, 0, sizeof(struct resize)); + if (!resize_from_tags(mdev, nlp->tag_list, &rs)) { + retcode = UnknownMandatoryTag; + goto fail; + } + + if (mdev->state.conn > Connected) { + retcode = NoResizeDuringResync; + goto fail; + } + + if ( mdev->state.role == Secondary && + mdev->state.peer == Secondary) { + retcode = APrimaryNodeNeeded; + goto fail; + } + + if (!inc_local(mdev)) { + retcode = HaveNoDiskConfig; + goto fail; + } + + if (mdev->bc->known_size != drbd_get_capacity(mdev->bc->backing_bdev)) { + mdev->bc->known_size = drbd_get_capacity(mdev->bc->backing_bdev); + ldsc = 1; + } + + mdev->bc->dc.disk_size = (sector_t)rs.resize_size; + dd = drbd_determin_dev_size(mdev); + drbd_md_sync(mdev); + dec_local(mdev); + if (dd == dev_size_error) { + retcode = VMallocFailed; + goto fail; + } + + if (mdev->state.conn == Connected && ( dd != unchanged || ldsc) ) { + drbd_send_uuids(mdev); + drbd_send_sizes(mdev); + if (dd == grew) + resync_after_online_grow(mdev); + } + + fail: + reply->ret_code = retcode; + return 0; +} + +STATIC int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + int retcode = NoError; + struct syncer_conf sc; + struct drbd_conf *odev; + int err; + struct crypto_hash *verify_tfm = NULL, *old_verify_tfm = NULL; + int ovr; /* online verify running */ + cpumask_t n_cpu_mask = CPU_MASK_NONE; + + memcpy(&sc, &mdev->sync_conf, sizeof(struct syncer_conf)); + + if (nlp->flags & DRBD_NL_SET_DEFAULTS) { + memset(&sc, 0, sizeof(struct syncer_conf)); + sc.rate = DRBD_RATE_DEF; + sc.after = DRBD_AFTER_DEF; + sc.al_extents = DRBD_AL_EXTENTS_DEF; + } + + if (!syncer_conf_from_tags(mdev, nlp->tag_list, &sc)) { + retcode = UnknownMandatoryTag; + goto fail; + } + + if (sc.after != -1) { + if ( sc.after < -1 || minor_to_mdev(sc.after) == NULL ) { + retcode = SyncAfterInvalid; + goto fail; + } + odev = minor_to_mdev(sc.after); /* check against loops in */ + while (1) { + if (odev == mdev) { + retcode = SyncAfterCycle; + goto fail; + } + if (odev->sync_conf.after == -1) + break; /* no cycles. */ + odev = minor_to_mdev(odev->sync_conf.after); + } + } + + ovr = (mdev->state.conn == VerifyS || mdev->state.conn == VerifyT); + + if (ovr) { + if (strcmp(sc.verify_alg, mdev->sync_conf.verify_alg)) { + retcode = VERIFYIsRunning; + goto fail; + } + } + + if (!ovr && sc.verify_alg[0]) { + verify_tfm = crypto_alloc_hash(sc.verify_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(verify_tfm)) { + verify_tfm = NULL; + retcode=VERIFYAlgNotAvail; + goto fail; + } + + if (crypto_tfm_alg_type(crypto_hash_tfm(verify_tfm)) != CRYPTO_ALG_TYPE_DIGEST) { + retcode=VERIFYAlgNotDigest; + goto fail; + } + } + + if (sc.cpu_mask[0] != 0) { + err = __bitmap_parse(sc.cpu_mask, 32, 0, (unsigned long *)&n_cpu_mask, NR_CPUS); + if (err) { + DRBD_WARN("__bitmap_parse() failed with %d\n", err); + retcode = CPUMaskParseFailed; + goto fail; + } + } + + ERR_IF (sc.rate < 1) sc.rate = 1; + ERR_IF (sc.al_extents < 7) sc.al_extents = 127; /* arbitrary minimum */ +#define AL_MAX ((MD_AL_MAX_SIZE-1) * AL_EXTENTS_PT) + if (sc.al_extents > AL_MAX) { + ERR("sc.al_extents > %d\n", AL_MAX); + sc.al_extents = AL_MAX; + } +#undef AL_MAX + + spin_lock(&mdev->peer_seq_lock); + /* lock against receive_SyncParam() */ + mdev->sync_conf = sc; + if (!ovr) { + old_verify_tfm = mdev->verify_tfm; + mdev->verify_tfm = verify_tfm; + verify_tfm = NULL; + } + spin_unlock(&mdev->peer_seq_lock); + + crypto_free_hash(old_verify_tfm); + + if (inc_local(mdev)) { + wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); + drbd_al_shrink(mdev); + err = drbd_check_al_size(mdev); + lc_unlock(mdev->act_log); + wake_up(&mdev->al_wait); + + dec_local(mdev); + drbd_md_sync(mdev); + + if (err) { + retcode = KMallocFailed; + goto fail; + } + } + + if (mdev->state.conn >= Connected) + drbd_send_sync_param(mdev, &sc); + + drbd_alter_sa(mdev, sc.after); + + if (!cpus_equal(mdev->cpu_mask, n_cpu_mask)) { + mdev->cpu_mask = n_cpu_mask; + n_cpu_mask = drbd_calc_cpu_mask(mdev); + drbd_thread_set_cpu(&mdev->receiver, n_cpu_mask); + drbd_thread_set_cpu(&mdev->worker, n_cpu_mask); + drbd_thread_set_cpu(&mdev->asender, n_cpu_mask); + } + +fail: + crypto_free_hash(verify_tfm); + reply->ret_code = retcode; + return 0; +} + +STATIC int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + int retcode; + + retcode = _drbd_request_state(mdev, NS(conn, StartingSyncT), ChgOrdered); + + if (retcode < SS_Success && retcode != SS_NeedConnection) + retcode = drbd_request_state(mdev, NS(conn, StartingSyncT)); + + while (retcode == SS_NeedConnection) { + spin_lock_irq(&mdev->req_lock); + if (mdev->state.conn < Connected) + retcode = _drbd_set_state(_NS(mdev, disk, Inconsistent), ChgStateVerbose, NULL); + spin_unlock_irq(&mdev->req_lock); + + if (retcode != SS_NeedConnection) + break; + + retcode = drbd_request_state(mdev, NS(conn, StartingSyncT)); + } + + reply->ret_code = retcode; + return 0; +} + +STATIC int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + + reply->ret_code = drbd_request_state(mdev, NS(conn, StartingSyncS)); + + return 0; +} + +STATIC int drbd_nl_pause_sync(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + int retcode = NoError; + + if (drbd_request_state(mdev, NS(user_isp, 1)) == SS_NothingToDo) + retcode = PauseFlagAlreadySet; + + reply->ret_code = retcode; + return 0; +} + +STATIC int drbd_nl_resume_sync(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + int retcode = NoError; + + if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NothingToDo) + retcode = PauseFlagAlreadyClear; + + reply->ret_code = retcode; + return 0; +} + +STATIC int drbd_nl_suspend_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + reply->ret_code = drbd_request_state(mdev, NS(susp, 1)); + + return 0; +} + +STATIC int drbd_nl_resume_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + reply->ret_code = drbd_request_state(mdev, NS(susp, 0)); + return 0; +} + +STATIC int drbd_nl_outdate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + reply->ret_code = drbd_request_state(mdev, NS(disk, Outdated)); + return 0; +} + +STATIC int drbd_nl_get_config(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + unsigned short *tl; + + tl = reply->tag_list; + + if (inc_local(mdev)) { + tl = disk_conf_to_tags(mdev, &mdev->bc->dc, tl); + dec_local(mdev); + } + + if (inc_net(mdev)) { + tl = net_conf_to_tags(mdev, mdev->net_conf, tl); + dec_net(mdev); + } + tl = syncer_conf_to_tags(mdev, &mdev->sync_conf, tl); + + *tl++ = TT_END; /* Close the tag list */ + + return (int)((char *)tl - (char *)reply->tag_list); +} + +STATIC int drbd_nl_get_state(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + unsigned short *tl; + + tl = reply->tag_list; + + tl = get_state_to_tags(mdev, (struct get_state *)&mdev->state, tl); + *tl++ = TT_END; /* Close the tag list */ + + return (int)((char *)tl - (char *)reply->tag_list); +} + +STATIC int drbd_nl_get_uuids(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + unsigned short *tl; + + tl = reply->tag_list; + + if (inc_local(mdev)) { + /* This is a hand crafted add tag ;) */ + *tl++ = T_uuids; + *tl++ = UUID_SIZE*sizeof(u64); + memcpy(tl, mdev->bc->md.uuid, UUID_SIZE*sizeof(u64)); + tl = (unsigned short *)((char *)tl + UUID_SIZE*sizeof(u64)); + *tl++ = T_uuids_flags; + *tl++ = sizeof(int); + memcpy(tl, &mdev->bc->md.flags, sizeof(int)); + tl = (unsigned short *)((char *)tl + sizeof(int)); + dec_local(mdev); + } + *tl++ = TT_END; /* Close the tag list */ + + return (int)((char *)tl - (char *)reply->tag_list); +} + + +STATIC int drbd_nl_get_timeout_flag(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + unsigned short *tl; + + tl = reply->tag_list; + + /* This is a hand crafted add tag ;) */ + *tl++ = T_use_degraded; + *tl++ = sizeof(char); + *((char *)tl) = test_bit(USE_DEGR_WFC_T, &mdev->flags) ? 1 : 0 ; + tl = (unsigned short *)((char *)tl + sizeof(char)); + *tl++ = TT_END; + + return (int)((char *)tl - (char *)reply->tag_list); +} + +STATIC int drbd_nl_start_ov(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, + struct drbd_nl_cfg_reply *reply) +{ + reply->ret_code = drbd_request_state(mdev,NS(conn,VerifyS)); + + return 0; +} + + +STATIC struct drbd_conf *ensure_mdev(struct drbd_nl_cfg_req *nlp) +{ + struct drbd_conf *mdev; + + mdev = minor_to_mdev(nlp->drbd_minor); + + if (!mdev && (nlp->flags & DRBD_NL_CREATE_DEVICE)) { + mdev = drbd_new_device(nlp->drbd_minor); + + spin_lock_irq(&drbd_pp_lock); + if (minor_table[nlp->drbd_minor] == NULL) { + minor_table[nlp->drbd_minor] = mdev; + mdev = NULL; + } + spin_unlock_irq(&drbd_pp_lock); + + if (mdev) { + kfree(mdev->app_reads_hash); + if (mdev->md_io_page) + __free_page(mdev->md_io_page); + kfree(mdev); + mdev = NULL; + } + + mdev = minor_to_mdev(nlp->drbd_minor); + } + + return mdev; +} + +struct cn_handler_struct { + int (*function)(struct drbd_conf *, + struct drbd_nl_cfg_req *, + struct drbd_nl_cfg_reply* ); + int reply_body_size; +}; + +static struct cn_handler_struct cnd_table[] = { + [ P_primary ] = { &drbd_nl_primary, 0 }, + [ P_secondary ] = { &drbd_nl_secondary, 0 }, + [ P_disk_conf ] = { &drbd_nl_disk_conf, 0 }, + [ P_detach ] = { &drbd_nl_detach, 0 }, + [ P_net_conf ] = { &drbd_nl_net_conf, 0 }, + [ P_disconnect ] = { &drbd_nl_disconnect, 0 }, + [ P_resize ] = { &drbd_nl_resize, 0 }, + [ P_syncer_conf ] = { &drbd_nl_syncer_conf, 0 }, + [ P_invalidate ] = { &drbd_nl_invalidate, 0 }, + [ P_invalidate_peer ] = { &drbd_nl_invalidate_peer, 0 }, + [ P_pause_sync ] = { &drbd_nl_pause_sync, 0 }, + [ P_resume_sync ] = { &drbd_nl_resume_sync, 0 }, + [ P_suspend_io ] = { &drbd_nl_suspend_io, 0 }, + [ P_resume_io ] = { &drbd_nl_resume_io, 0 }, + [ P_outdate ] = { &drbd_nl_outdate, 0 }, + [ P_get_config ] = { &drbd_nl_get_config, + sizeof(struct syncer_conf_tag_len_struct) + + sizeof(struct disk_conf_tag_len_struct) + + sizeof(struct net_conf_tag_len_struct) }, + [ P_get_state ] = { &drbd_nl_get_state, + sizeof(struct get_state_tag_len_struct) }, + [ P_get_uuids ] = { &drbd_nl_get_uuids, + sizeof(struct get_uuids_tag_len_struct) }, + [ P_get_timeout_flag ] = + { &drbd_nl_get_timeout_flag, + sizeof(struct get_timeout_flag_tag_len_struct)}, + [ P_start_ov ] = { &drbd_nl_start_ov, 0 }, +}; + +STATIC void drbd_connector_callback(void *data) +{ + struct cn_msg *req = data; + struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req *)req->data; + struct cn_handler_struct *cm; + struct cn_msg *cn_reply; + struct drbd_nl_cfg_reply *reply; + struct drbd_conf *mdev; + int retcode, rr; + int reply_size = sizeof(struct cn_msg) + + sizeof(struct drbd_nl_cfg_reply) + + sizeof(short int); + + if (!try_module_get(THIS_MODULE)) { + printk(KERN_ERR "drbd: try_module_get() failed!\n"); + return; + } + + mdev = ensure_mdev(nlp); + if (!mdev) { + retcode = MinorNotKnown; + goto fail; + } + + TRACE(TraceTypeNl, TraceLvlSummary, nl_trace_packet(data);); + + if (nlp->packet_type >= P_nl_after_last_packet) { + retcode = UnknownNetLinkPacket; + goto fail; + } + + cm = cnd_table + nlp->packet_type; + reply_size += cm->reply_body_size; + + cn_reply = kmalloc(reply_size, GFP_KERNEL); + if (!cn_reply) { + retcode = KMallocFailed; + goto fail; + } + reply = (struct drbd_nl_cfg_reply *) cn_reply->data; + + reply->packet_type = + cm->reply_body_size ? nlp->packet_type : P_nl_after_last_packet; + reply->minor = nlp->drbd_minor; + reply->ret_code = NoError; /* Might by modified by cm->function. */ + /* reply->tag_list; might be modified by cm->fucntion. */ + + rr = cm->function(mdev, nlp, reply); + + cn_reply->id = req->id; + cn_reply->seq = req->seq; + cn_reply->ack = req->ack + 1; + cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + rr; + cn_reply->flags = 0; + + TRACE(TraceTypeNl, TraceLvlSummary, nl_trace_reply(cn_reply);); + + rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); + if (rr && rr != -ESRCH) + printk(KERN_INFO "drbd: cn_netlink_send()=%d\n", rr); + + kfree(cn_reply); + module_put(THIS_MODULE); + return; + fail: + drbd_nl_send_reply(req, retcode); + module_put(THIS_MODULE); +} + +static atomic_t drbd_nl_seq = ATOMIC_INIT(2); /* two. */ + +static inline unsigned short * +__tl_add_blob(unsigned short *tl, enum drbd_tags tag, const void *data, + int len, int nul_terminated) +{ + int l = tag_descriptions[tag_number(tag)].max_len; + l = (len < l) ? len : l; + *tl++ = tag; + *tl++ = len; + memcpy(tl, data, len); + /* TODO + * maybe we need to add some padding to the data stream. + * otherwise we may get strange effects on architectures + * that require certain data types to be strictly aligned, + * because now the next "unsigned short" may be misaligned. */ + tl = (unsigned short*)((char*)tl + len); + if (nul_terminated) + *((char*)tl - 1) = 0; + return tl; +} + +static inline unsigned short * +tl_add_blob(unsigned short *tl, enum drbd_tags tag, const void *data, int len) +{ + return __tl_add_blob(tl, tag, data, len, 0); +} + +static inline unsigned short * +tl_add_str(unsigned short *tl, enum drbd_tags tag, const char *str) +{ + return __tl_add_blob(tl, tag, str, strlen(str)+1, 0); +} + +static inline unsigned short * +tl_add_int(unsigned short *tl, enum drbd_tags tag, const void *val) +{ + switch(tag_type(tag)) { + case TT_INTEGER: + *tl++ = tag; + *tl++ = sizeof(int); + *(int*)tl = *(int*)val; + tl = (unsigned short*)((char*)tl+sizeof(int)); + break; + case TT_INT64: + *tl++ = tag; + *tl++ = sizeof(u64); + *(u64*)tl = *(u64*)val; + tl = (unsigned short*)((char*)tl+sizeof(u64)); + break; + default: + /* someone did something stupid. */ + ; + } + return tl; +} + +void drbd_bcast_state(struct drbd_conf *mdev, union drbd_state_t state) +{ + char buffer[sizeof(struct cn_msg)+ + sizeof(struct drbd_nl_cfg_reply)+ + sizeof(struct get_state_tag_len_struct)+ + sizeof(short int)]; + struct cn_msg *cn_reply = (struct cn_msg *) buffer; + struct drbd_nl_cfg_reply *reply = + (struct drbd_nl_cfg_reply *)cn_reply->data; + unsigned short *tl = reply->tag_list; + + /* DRBD_WARN("drbd_bcast_state() got called\n"); */ + + tl = get_state_to_tags(mdev, (struct get_state *)&state, tl); + *tl++ = TT_END; /* Close the tag list */ + + cn_reply->id.idx = CN_IDX_DRBD; + cn_reply->id.val = CN_VAL_DRBD; + + cn_reply->seq = atomic_add_return(1, &drbd_nl_seq); + cn_reply->ack = 0; /* not used here. */ + cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + + (int)((char *)tl - (char *)reply->tag_list); + cn_reply->flags = 0; + + reply->packet_type = P_get_state; + reply->minor = mdev_to_minor(mdev); + reply->ret_code = NoError; + + TRACE(TraceTypeNl, TraceLvlSummary, nl_trace_reply(cn_reply);); + + cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); +} + +void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name) +{ + char buffer[sizeof(struct cn_msg)+ + sizeof(struct drbd_nl_cfg_reply)+ + sizeof(struct call_helper_tag_len_struct)+ + sizeof(short int)]; + struct cn_msg *cn_reply = (struct cn_msg *) buffer; + struct drbd_nl_cfg_reply *reply = + (struct drbd_nl_cfg_reply *)cn_reply->data; + unsigned short *tl = reply->tag_list; + int str_len; + + /* DRBD_WARN("drbd_bcast_state() got called\n"); */ + + str_len = strlen(helper_name)+1; + *tl++ = T_helper; + *tl++ = str_len; + memcpy(tl, helper_name, str_len); + tl = (unsigned short *)((char *)tl + str_len); + *tl++ = TT_END; /* Close the tag list */ + + cn_reply->id.idx = CN_IDX_DRBD; + cn_reply->id.val = CN_VAL_DRBD; + + cn_reply->seq = atomic_add_return(1, &drbd_nl_seq); + cn_reply->ack = 0; /* not used here. */ + cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + + (int)((char *)tl - (char *)reply->tag_list); + cn_reply->flags = 0; + + reply->packet_type = P_call_helper; + reply->minor = mdev_to_minor(mdev); + reply->ret_code = NoError; + + TRACE(TraceTypeNl, TraceLvlSummary, nl_trace_reply(cn_reply);); + + cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); +} + +void drbd_bcast_ee(struct drbd_conf *mdev, + const char *reason, const int dgs, + const char* seen_hash, const char* calc_hash, + const struct Tl_epoch_entry* e) +{ + struct cn_msg *cn_reply; + struct drbd_nl_cfg_reply *reply; + struct bio_vec *bvec; + unsigned short *tl; + int i; + + if (!e) + return; + if (!reason || !reason[0]) + return; + + /* aparently we have to memcpy twice, first to prepare the data for the + * struct cn_msg, then within cn_netlink_send from the cn_msg to the + * netlink skb. */ + cn_reply = kmalloc( + sizeof(struct cn_msg)+ + sizeof(struct drbd_nl_cfg_reply)+ + sizeof(struct dump_ee_tag_len_struct)+ + sizeof(short int) + , GFP_KERNEL); + + if (!cn_reply) { + ERR("could not kmalloc buffer for drbd_bcast_ee, sector %llu, size %u\n", + (unsigned long long)e->sector, e->size); + return; + } + + reply = (struct drbd_nl_cfg_reply*)cn_reply->data; + tl = reply->tag_list; + + tl = tl_add_str(tl, T_dump_ee_reason, reason); + tl = tl_add_blob(tl, T_seen_digest, seen_hash, dgs); + tl = tl_add_blob(tl, T_calc_digest, calc_hash, dgs); + tl = tl_add_int(tl, T_ee_sector, &e->sector); + tl = tl_add_int(tl, T_ee_block_id, &e->block_id); + + *tl++ = T_ee_data; + *tl++ = e->size; + + __bio_for_each_segment(bvec, e->private_bio, i, 0) { + void *d = kmap(bvec->bv_page); + memcpy(tl, d + bvec->bv_offset, bvec->bv_len); + kunmap(bvec->bv_page); + tl=(unsigned short*)((char*)tl + bvec->bv_len); + } + *tl++ = TT_END; /* Close the tag list */ + + cn_reply->id.idx = CN_IDX_DRBD; + cn_reply->id.val = CN_VAL_DRBD; + + cn_reply->seq = atomic_add_return(1,&drbd_nl_seq); + cn_reply->ack = 0; // not used here. + cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + + (int)((char*)tl - (char*)reply->tag_list); + cn_reply->flags = 0; + + reply->packet_type = P_dump_ee; + reply->minor = mdev_to_minor(mdev); + reply->ret_code = NoError; + + TRACE(TraceTypeNl, TraceLvlSummary, nl_trace_reply(cn_reply);); + + cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); + kfree(cn_reply); +} + +void drbd_bcast_sync_progress(struct drbd_conf *mdev) +{ + char buffer[sizeof(struct cn_msg)+ + sizeof(struct drbd_nl_cfg_reply)+ + sizeof(struct sync_progress_tag_len_struct)+ + sizeof(short int)]; + struct cn_msg *cn_reply = (struct cn_msg *) buffer; + struct drbd_nl_cfg_reply *reply = + (struct drbd_nl_cfg_reply *)cn_reply->data; + unsigned short *tl = reply->tag_list; + unsigned long rs_left; + unsigned int res; + + /* no local ref, no bitmap, no syncer progress, no broadcast. */ + if (!inc_local(mdev)) + return; + drbd_get_syncer_progress(mdev, &rs_left, &res); + dec_local(mdev); + + *tl++ = T_sync_progress; + *tl++ = sizeof(int); + memcpy(tl, &res, sizeof(int)); + tl = (unsigned short *)((char *)tl + sizeof(int)); + *tl++ = TT_END; /* Close the tag list */ + + cn_reply->id.idx = CN_IDX_DRBD; + cn_reply->id.val = CN_VAL_DRBD; + + cn_reply->seq = atomic_add_return(1, &drbd_nl_seq); + cn_reply->ack = 0; /* not used here. */ + cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + + (int)((char *)tl - (char *)reply->tag_list); + cn_reply->flags = 0; + + reply->packet_type = P_sync_progress; + reply->minor = mdev_to_minor(mdev); + reply->ret_code = NoError; + + TRACE(TraceTypeNl, TraceLvlSummary, nl_trace_reply(cn_reply);); + + cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); +} + +int __init drbd_nl_init(void) +{ + static struct cb_id cn_id_drbd = { CN_IDX_DRBD, CN_VAL_DRBD }; + int err; + + err = cn_add_callback(&cn_id_drbd, "cn_drbd", &drbd_connector_callback); + if (err) { + printk(KERN_ERR "drbd: cn_drbd failed to register\n"); + return err; + } + + return 0; +} + +void drbd_nl_cleanup(void) +{ + static struct cb_id cn_id_drbd = { CN_IDX_DRBD, CN_VAL_DRBD }; + + cn_del_callback(&cn_id_drbd); +} + +void drbd_nl_send_reply( struct cn_msg *req, + int ret_code) +{ + char buffer[sizeof(struct cn_msg)+sizeof(struct drbd_nl_cfg_reply)]; + struct cn_msg *cn_reply = (struct cn_msg *) buffer; + struct drbd_nl_cfg_reply *reply = + (struct drbd_nl_cfg_reply *)cn_reply->data; + int rr; + + cn_reply->id = req->id; + + cn_reply->seq = req->seq; + cn_reply->ack = req->ack + 1; + cn_reply->len = sizeof(struct drbd_nl_cfg_reply); + cn_reply->flags = 0; + + reply->minor = ((struct drbd_nl_cfg_req *)req->data)->drbd_minor; + reply->ret_code = ret_code; + + TRACE(TraceTypeNl, TraceLvlSummary, nl_trace_reply(cn_reply);); + + rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); + if (rr && rr != -ESRCH) + printk(KERN_INFO "drbd: cn_netlink_send()=%d\n", rr); +} + --- linux-2.6.27.orig/ubuntu/drbd/linux/drbd_nl.h +++ linux-2.6.27/ubuntu/drbd/linux/drbd_nl.h @@ -0,0 +1,123 @@ +/* + PAKET( name, + TYPE ( pn, pr, member ) + ... + ) + + You may never reissue one of the pn arguments +*/ + +#if !defined(NL_PACKET) || !defined(NL_STRING) || !defined(NL_INTEGER) || !defined(NL_BIT) || !defined(NL_INT64) +#error "The macros NL_PACKET, NL_STRING, NL_INTEGER, NL_INT64 and NL_BIT needs to be defined" +#endif + +NL_PACKET(primary, 1, + NL_BIT( 1, T_MAY_IGNORE, overwrite_peer) +) + +NL_PACKET(secondary, 2, ) + +NL_PACKET(disk_conf, 3, + NL_INT64( 2, T_MAY_IGNORE, disk_size) + NL_STRING( 3, T_MANDATORY, backing_dev, 128) + NL_STRING( 4, T_MANDATORY, meta_dev, 128) + NL_INTEGER( 5, T_MANDATORY, meta_dev_idx) + NL_INTEGER( 6, T_MAY_IGNORE, on_io_error) + NL_INTEGER( 7, T_MAY_IGNORE, fencing) + NL_BIT( 37, T_MAY_IGNORE, use_bmbv) + NL_BIT( 53, T_MAY_IGNORE, no_disk_flush) + NL_BIT( 54, T_MAY_IGNORE, no_md_flush) + /* 55 max_bio_size was available in 8.2.6rc2 */ + NL_INTEGER( 56, T_MAY_IGNORE, max_bio_bvecs) +) + +NL_PACKET(detach, 4, ) +NL_PACKET(net_conf, 5, + NL_STRING( 8, T_MANDATORY, my_addr, 128) + NL_STRING( 9, T_MANDATORY, peer_addr, 128) + NL_STRING( 10, T_MAY_IGNORE, shared_secret, SHARED_SECRET_MAX) + NL_STRING( 11, T_MAY_IGNORE, cram_hmac_alg, SHARED_SECRET_MAX) + NL_STRING( 44, T_MAY_IGNORE, integrity_alg, SHARED_SECRET_MAX) + NL_INTEGER( 14, T_MAY_IGNORE, timeout) + NL_INTEGER( 15, T_MANDATORY, wire_protocol) + NL_INTEGER( 16, T_MAY_IGNORE, try_connect_int) + NL_INTEGER( 17, T_MAY_IGNORE, ping_int) + NL_INTEGER( 18, T_MAY_IGNORE, max_epoch_size) + NL_INTEGER( 19, T_MAY_IGNORE, max_buffers) + NL_INTEGER( 20, T_MAY_IGNORE, unplug_watermark) + NL_INTEGER( 21, T_MAY_IGNORE, sndbuf_size) + NL_INTEGER( 22, T_MAY_IGNORE, ko_count) + NL_INTEGER( 24, T_MAY_IGNORE, after_sb_0p) + NL_INTEGER( 25, T_MAY_IGNORE, after_sb_1p) + NL_INTEGER( 26, T_MAY_IGNORE, after_sb_2p) + NL_INTEGER( 39, T_MAY_IGNORE, rr_conflict) + NL_INTEGER( 40, T_MAY_IGNORE, ping_timeo) + NL_BIT( 27, T_MAY_IGNORE, want_lose) + NL_BIT( 28, T_MAY_IGNORE, two_primaries) + NL_BIT( 41, T_MAY_IGNORE, always_asbp) +) + +NL_PACKET(disconnect, 6, ) + +NL_PACKET(resize, 7, + NL_INT64( 29, T_MAY_IGNORE, resize_size) +) + +NL_PACKET(syncer_conf, 8, + NL_INTEGER( 30, T_MAY_IGNORE, rate) + NL_INTEGER( 31, T_MAY_IGNORE, after) + NL_INTEGER( 32, T_MAY_IGNORE, al_extents) + NL_STRING( 52, T_MAY_IGNORE, verify_alg, SHARED_SECRET_MAX) + NL_STRING( 51, T_MAY_IGNORE, cpu_mask, 32) +) + +NL_PACKET(invalidate, 9, ) +NL_PACKET(invalidate_peer, 10, ) +NL_PACKET(pause_sync, 11, ) +NL_PACKET(resume_sync, 12, ) +NL_PACKET(suspend_io, 13, ) +NL_PACKET(resume_io, 14, ) +NL_PACKET(outdate, 15, ) +NL_PACKET(get_config, 16, ) +NL_PACKET(get_state, 17, + NL_INTEGER( 33, T_MAY_IGNORE, state_i) +) + +NL_PACKET(get_uuids, 18, + NL_STRING( 34, T_MAY_IGNORE, uuids, (UUID_SIZE*sizeof(__u64))) + NL_INTEGER( 35, T_MAY_IGNORE, uuids_flags) +) + +NL_PACKET(get_timeout_flag, 19, + NL_BIT( 36, T_MAY_IGNORE, use_degraded) +) + +NL_PACKET(call_helper, 20, + NL_STRING( 38, T_MAY_IGNORE, helper, 32) +) + +/* Tag nr 42 already allocated in drbd-8.1 development. + * Packet numbers 21 and 22 already in drbd-8.1 development. */ + +NL_PACKET(sync_progress, 23, + NL_INTEGER( 43, T_MAY_IGNORE, sync_progress) +) + +NL_PACKET(dump_ee, 24, + NL_STRING( 45, T_MAY_IGNORE, dump_ee_reason, 32) + NL_STRING( 46, T_MAY_IGNORE, seen_digest, SHARED_SECRET_MAX) + NL_STRING( 47, T_MAY_IGNORE, calc_digest, SHARED_SECRET_MAX) + NL_INT64( 48, T_MAY_IGNORE, ee_sector) + NL_INT64( 49, T_MAY_IGNORE, ee_block_id) + NL_STRING( 50, T_MAY_IGNORE, ee_data, 32 << 10) +) + +NL_PACKET(start_ov, 25, +) + +#undef NL_PACKET +#undef NL_INTEGER +#undef NL_INT64 +#undef NL_BIT +#undef NL_STRING + --- linux-2.6.27.orig/ubuntu/drbd/linux/drbd_limits.h +++ linux-2.6.27/ubuntu/drbd/linux/drbd_limits.h @@ -0,0 +1,128 @@ +/* + drbd_limits.h + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. +*/ + +/* + * Our current limitations. + * Some of them are hard limits, + * some of them are arbitrary range limits, that make it easier to provide + * feedback about nonsense settings for certain configurable values. + */ + +#ifndef DRBD_LIMITS_H +#define DRBD_LIMITS_H 1 + +#define DEBUG_RANGE_CHECK 0 + +#define DRBD_MINOR_COUNT_MIN 1 +#define DRBD_MINOR_COUNT_MAX 255 + +#define DRBD_DIALOG_REFRESH_MIN 0 +#define DRBD_DIALOG_REFRESH_MAX 600 + +/* valid port number */ +#define DRBD_PORT_MIN 1 +#define DRBD_PORT_MAX 0xffff + +/* startup { */ + /* if you want more than 3.4 days, disable */ +#define DRBD_WFC_TIMEOUT_MIN 0 +#define DRBD_WFC_TIMEOUT_MAX 300000 +#define DRBD_WFC_TIMEOUT_DEF 0 + +#define DRBD_DEGR_WFC_TIMEOUT_MIN 0 +#define DRBD_DEGR_WFC_TIMEOUT_MAX 300000 +#define DRBD_DEGR_WFC_TIMEOUT_DEF 60 + +/* }*/ + +/* net { */ + /* timeout, unit centi seconds + * more than one minute timeout is not usefull */ +#define DRBD_TIMEOUT_MIN 1 +#define DRBD_TIMEOUT_MAX 600 +#define DRBD_TIMEOUT_DEF 60 /* 6 seconds */ + + /* active connection retries when WFConnection */ +#define DRBD_CONNECT_INT_MIN 1 +#define DRBD_CONNECT_INT_MAX 120 +#define DRBD_CONNECT_INT_DEF 10 /* seconds */ + + /* keep-alive probes when idle */ +#define DRBD_PING_INT_MIN 1 +#define DRBD_PING_INT_MAX 120 +#define DRBD_PING_INT_DEF 10 + + /* timeout for the ping packets.*/ +#define DRBD_PING_TIMEO_MIN 1 +#define DRBD_PING_TIMEO_MAX 100 +#define DRBD_PING_TIMEO_DEF 5 + + /* max number of write requests between write barriers */ +#define DRBD_MAX_EPOCH_SIZE_MIN 1 +#define DRBD_MAX_EPOCH_SIZE_MAX 20000 +#define DRBD_MAX_EPOCH_SIZE_DEF 2048 + + /* I don't think that a tcp send buffer of more than 10M is usefull */ +#define DRBD_SNDBUF_SIZE_MIN 1 +#define DRBD_SNDBUF_SIZE_MAX 10000000 +#define DRBD_SNDBUF_SIZE_DEF (2*65535) + + /* @4k PageSize -> 128kB - 512MB */ +#define DRBD_MAX_BUFFERS_MIN 32 +#define DRBD_MAX_BUFFERS_MAX 131072 +#define DRBD_MAX_BUFFERS_DEF 2048 + + /* @4k PageSize -> 4kB - 512MB */ +#define DRBD_UNPLUG_WATERMARK_MIN 1 +#define DRBD_UNPLUG_WATERMARK_MAX 131072 +#define DRBD_UNPLUG_WATERMARK_DEF (DRBD_MAX_BUFFERS_DEF/16) + + /* 0 is disabled. + * 200 should be more than enough even for very short timeouts */ +#define DRBD_KO_COUNT_MIN 0 +#define DRBD_KO_COUNT_MAX 200 +#define DRBD_KO_COUNT_DEF 0 +/* } */ + +/* syncer { */ + /* FIXME allow rate to be zero? */ +#define DRBD_RATE_MIN 1 +#define DRBD_RATE_MAX 700000 +#define DRBD_RATE_DEF 250 /* kb/second */ + + /* less than 7 would hit performance unneccessarily. + * 3833 is the largest prime that still does fit + * into 64 sectors of activity log */ +#define DRBD_AL_EXTENTS_MIN 7 +#define DRBD_AL_EXTENTS_MAX 3833 +#define DRBD_AL_EXTENTS_DEF 127 + +#define DRBD_AFTER_MIN -1 +#define DRBD_AFTER_MAX 255 +#define DRBD_AFTER_DEF -1 + +/* } */ + +/* drbdsetup XY resize -d Z + * you are free to reduce the device size to nothing, if you want to. + * but more than 3998G are currently not possible */ +/* DRBD_MAX_SECTORS */ +#define DRBD_DISK_SIZE_SECT_MIN 0 +#define DRBD_DISK_SIZE_SECT_MAX ((128LLU*1024*2 - 72)*512LLU*8*8) +#define DRBD_DISK_SIZE_SECT_DEF 0 /* = disabled = no user size... */ + +#define DRBD_ON_IO_ERROR_DEF PassOn +#define DRBD_FENCING_DEF DontCare +#define DRBD_AFTER_SB_0P_DEF Disconnect +#define DRBD_AFTER_SB_1P_DEF Disconnect +#define DRBD_AFTER_SB_2P_DEF Disconnect +#define DRBD_RR_CONFLICT_DEF Disconnect + +#define DRBD_MAX_BIO_BVECS_MIN 0 +#define DRBD_MAX_BIO_BVECS_MAX 128 +#define DRBD_MAX_BIO_BVECS_DEF 0 + +#undef RANGE +#endif --- linux-2.6.27.orig/ubuntu/drbd/linux/drbd.h +++ linux-2.6.27/ubuntu/drbd/linux/drbd.h @@ -0,0 +1,355 @@ +/* + drbd.h + Kernel module for 2.6.x Kernels + + This file is part of DRBD by Philipp Reisner and Lars Ellenberg. + + Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. + Copyright (C) 2001-2008, Philipp Reisner . + Copyright (C) 2001-2008, Lars Ellenberg . + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef DRBD_H +#define DRBD_H +#include + +#include + +#ifdef __KERNEL__ +#include +#include +#else +#include +#include +#include + +/* Altough the Linux source code makes a difference between + generic endiness and the bitfields' endianess, there is no + architecture as of Linux-2.6.24-rc4 where the bitfileds' endianess + does not match the generic endianess. */ + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define __LITTLE_ENDIAN_BITFIELD +#elif __BYTE_ORDER == __BIG_ENDIAN +#define __BIG_ENDIAN_BITFIELD +#else +# error "sorry, weird endianness on this box" +#endif + +#endif + + +enum io_error_handler { + PassOn, /* FIXME should the better be named "Ignore"? */ + CallIOEHelper, + Detach +}; + +enum fencing_policy { + DontCare, + Resource, + Stonith +}; + +enum disconnect_handler { + Reconnect, + DropNetConf, + FreezeIO +}; + +enum after_sb_handler { + Disconnect, + DiscardYoungerPri, + DiscardOlderPri, + DiscardZeroChg, + DiscardLeastChg, + DiscardLocal, + DiscardRemote, + Consensus, + DiscardSecondary, + CallHelper, + Violently +}; + +/* KEEP the order, do not delete or insert! + * Or change the API_VERSION, too. */ +enum ret_codes { + RetCodeBase = 100, + NoError, /* 101 ... */ + LAAlreadyInUse, + OAAlreadyInUse, + LDNameInvalid, + MDNameInvalid, + LDAlreadyInUse, + LDNoBlockDev, + MDNoBlockDev, + LDOpenFailed, + MDOpenFailed, + LDDeviceTooSmall, + MDDeviceTooSmall, + LDNoConfig, + LDMounted, + MDMounted, + LDMDInvalid, + LDDeviceTooLarge, + MDIOError, + MDInvalid, + CRAMAlgNotAvail, + CRAMAlgNotDigest, + KMallocFailed, + DiscardNotAllowed, + HaveDiskConfig, + HaveNetConfig, + UnknownMandatoryTag, + MinorNotKnown, + StateNotAllowed, + GotSignal, /* EINTR */ + NoResizeDuringResync, + APrimaryNodeNeeded, + SyncAfterInvalid, + SyncAfterCycle, + PauseFlagAlreadySet, + PauseFlagAlreadyClear, + DiskLowerThanOutdated, /* obsolete, now SS_LowerThanOutdated */ + UnknownNetLinkPacket, + HaveNoDiskConfig, + ProtocolCRequired, + VMallocFailed, + IntegrityAlgNotAvail, + IntegrityAlgNotDigest, + CPUMaskParseFailed, + CSUMSAlgNotAvail, + CSUMSAlgNotDigest, + VERIFYAlgNotAvail, + VERIFYAlgNotDigest, + CSUMSResyncRunning, + VERIFYIsRunning, + DataOfWrongCurrent, + + /* insert new ones above this line */ + AfterLastRetCode, +}; + +#define DRBD_PROT_A 1 +#define DRBD_PROT_B 2 +#define DRBD_PROT_C 3 + +enum drbd_role { + Unknown = 0, + Primary = 1, /* role */ + Secondary = 2, /* role */ + role_mask = 3, +}; + +/* The order of these constants is important. + * The lower ones (=WFReportParams ==> There is a socket + * + * THINK + * Skipped should be < Connected, + * so writes on a Primary after Skipped sync are not mirrored either ? + */ +enum drbd_conns { + StandAlone, + Disconnecting, /* Temporal state on the way to StandAlone. */ + Unconnected, /* >= Unconnected -> inc_net() succeeds */ + + /* These temporal states are all used on the way + * from >= Connected to Unconnected. + * The 'disconnect reason' states + * I do not allow to change beween them. */ + Timeout, + BrokenPipe, + NetworkFailure, + ProtocolError, + TearDown, + + WFConnection, + WFReportParams, /* we have a socket */ + Connected, /* we have introduced each other */ + StartingSyncS, /* starting full sync by IOCTL. */ + StartingSyncT, /* stariing full sync by IOCTL. */ + WFBitMapS, + WFBitMapT, + WFSyncUUID, + + /* The distance between original state and pause + * state must be the same for source and target. (+2) + * All SyncStates are tested with this comparison + * xx >= SyncSource && xx <= PausedSyncT */ + SyncSource, + SyncTarget, + VerifyS, + VerifyT, + PausedSyncS, + PausedSyncT, + conn_mask = 31 +}; + +enum drbd_disk_state { + Diskless, + Attaching, /* In the process of reading the meta-data */ + Failed, /* Becomes Diskless as soon as we told it the peer */ + /* when >= Failed it is legal to access mdev->bc */ + Negotiating, /* Late attaching state, we need to talk to the peer */ + Inconsistent, + Outdated, + DUnknown, /* Only used for the peer, never for myself */ + Consistent, /* Might be Outdated, might be UpToDate ... */ + UpToDate, /* Only this disk state allows applications' IO ! */ + disk_mask = 15 +}; + +union drbd_state_t { +/* According to gcc's docs is the ... + * The order of allocation of bit-fields within a unit (C90 6.5.2.1, C99 6.7.2.1). + * Determined by ABI. + * pointed out by Maxim Uvarov q + * even though we transmit as "cpu_to_be32(state)", + * the offsets of the bitfields still need to be swapped + * on different endianess. + */ + struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) + unsigned role : 2 ; /* 3/4 primary/secondary/unknown */ + unsigned peer : 2 ; /* 3/4 primary/secondary/unknown */ + unsigned conn : 5 ; /* 17/32 cstates */ + unsigned disk : 4 ; /* 8/16 from Diskless to UpToDate */ + unsigned pdsk : 4 ; /* 8/16 from Diskless to UpToDate */ + unsigned susp : 1 ; /* 2/2 IO suspended no/yes */ + unsigned aftr_isp : 1 ; /* isp .. imposed sync pause */ + unsigned peer_isp : 1 ; + unsigned user_isp : 1 ; + unsigned _pad : 11; /* 0 unused */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned _pad : 11; /* 0 unused */ + unsigned user_isp : 1 ; + unsigned peer_isp : 1 ; + unsigned aftr_isp : 1 ; /* isp .. imposed sync pause */ + unsigned susp : 1 ; /* 2/2 IO suspended no/yes */ + unsigned pdsk : 4 ; /* 8/16 from Diskless to UpToDate */ + unsigned disk : 4 ; /* 8/16 from Diskless to UpToDate */ + unsigned conn : 5 ; /* 17/32 cstates */ + unsigned peer : 2 ; /* 3/4 primary/secondary/unknown */ + unsigned role : 2 ; /* 3/4 primary/secondary/unknown */ +#else +# error "this endianess is not supported" +#endif + }; + unsigned int i; +}; + +enum set_st_err { + SS_CW_NoNeed = 4, + SS_CW_Success = 3, + SS_NothingToDo = 2, + SS_Success = 1, + SS_UnknownError = 0, /* Used to sleep longer in _drbd_request_state */ + SS_TwoPrimaries = -1, + SS_NoUpToDateDisk = -2, + SS_BothInconsistent = -4, + SS_SyncingDiskless = -5, + SS_ConnectedOutdates = -6, + SS_PrimaryNOP = -7, + SS_ResyncRunning = -8, + SS_AlreadyStandAlone = -9, + SS_CW_FailedByPeer = -10, + SS_IsDiskLess = -11, + SS_DeviceInUse = -12, + SS_NoNetConfig = -13, + SS_NoVerifyAlg = -14, /* drbd-8.2 only */ + SS_NeedConnection = -15, /* drbd-8.2 only */ + SS_LowerThanOutdated = -16, + SS_NotSupported = -17, /* drbd-8.2 only */ + SS_InTransientState = -18, /* Retry after the next state change */ + SS_ConcurrentStChg = -19, /* Concurrent cluster side state change! */ +}; + + +/* from drbd_strings.c */ +extern const char *conns_to_name(enum drbd_conns); +extern const char *roles_to_name(enum drbd_role); +extern const char *disks_to_name(enum drbd_disk_state); +extern const char *set_st_err_name(enum set_st_err); + +#ifndef BDEVNAME_SIZE +# define BDEVNAME_SIZE 32 +#endif + +#define SHARED_SECRET_MAX 64 + +enum MetaDataFlags { + __MDF_Consistent, + __MDF_PrimaryInd, + __MDF_ConnectedInd, + __MDF_FullSync, + __MDF_WasUpToDate, + __MDF_PeerOutDated /* or worse (e.g. invalid). */ +}; +#define MDF_Consistent (1<<__MDF_Consistent) +#define MDF_PrimaryInd (1<<__MDF_PrimaryInd) +#define MDF_ConnectedInd (1<<__MDF_ConnectedInd) +#define MDF_FullSync (1<<__MDF_FullSync) +#define MDF_WasUpToDate (1<<__MDF_WasUpToDate) +#define MDF_PeerOutDated (1<<__MDF_PeerOutDated) + +enum UuidIndex { + Current, + Bitmap, + History_start, + History_end, + UUID_SIZE, /* nl-packet: number of dirty bits */ + UUID_FLAGS, /* nl-packet: flags */ + EXT_UUID_SIZE /* Everything. */ +}; + +#define UUID_JUST_CREATED ((__u64)4) + +#define DRBD_MAGIC 0x83740267 +#define BE_DRBD_MAGIC __constant_cpu_to_be32(DRBD_MAGIC) + +/* these are of type "int" */ +#define DRBD_MD_INDEX_INTERNAL -1 +#define DRBD_MD_INDEX_FLEX_EXT -2 +#define DRBD_MD_INDEX_FLEX_INT -3 + +/* Start of the new netlink/connector stuff */ + +#define DRBD_NL_CREATE_DEVICE 0x01 +#define DRBD_NL_SET_DEFAULTS 0x02 + +/* The following line should be moved over to linux/connector.h + * when the time comes */ +//#define CN_IDX_DRBD 0x5 +//#define CN_VAL_DRBD 0x1 + +struct drbd_nl_cfg_req { + int packet_type; + int drbd_minor; + int flags; + unsigned short tag_list[]; +}; + +struct drbd_nl_cfg_reply { + int packet_type; + int minor; + int ret_code; /* enum ret_code or set_st_err_t */ + unsigned short tag_list[]; /* only used with get_* calls */ +}; + +#endif --- linux-2.6.27.orig/ubuntu/drbd/linux/drbd_tag_magic.h +++ linux-2.6.27/ubuntu/drbd/linux/drbd_tag_magic.h @@ -0,0 +1,83 @@ +#ifndef DRBD_TAG_MAGIC_H +#define DRBD_TAG_MAGIC_H + +#define TT_END 0 +#define TT_REMOVED 0xE000 + +/* declare packet_type enums */ +enum packet_types { +#define NL_PACKET(name, number, fields) P_ ## name = number, +#define NL_INTEGER(pn, pr, member) +#define NL_INT64(pn, pr, member) +#define NL_BIT(pn, pr, member) +#define NL_STRING(pn, pr, member, len) +#include "drbd_nl.h" + P_nl_after_last_packet, +}; + +/* These struct are used to deduce the size of the tag lists: */ +#define NL_PACKET(name, number, fields) \ + struct name ## _tag_len_struct { fields }; +#define NL_INTEGER(pn, pr, member) \ + int member; int tag_and_len ## member; +#define NL_INT64(pn, pr, member) \ + __u64 member; int tag_and_len ## member; +#define NL_BIT(pn, pr, member) \ + unsigned char member : 1; int tag_and_len ## member; +#define NL_STRING(pn, pr, member, len) \ + unsigned char member[len]; int member ## _len; \ + int tag_and_len ## member; +#include "linux/drbd_nl.h" + +/* declate tag-list-sizes */ +static const int tag_list_sizes[] = { +#define NL_PACKET(name, number, fields) 2 fields , +#define NL_INTEGER(pn, pr, member) + 4 + 4 +#define NL_INT64(pn, pr, member) + 4 + 8 +#define NL_BIT(pn, pr, member) + 4 + 1 +#define NL_STRING(pn, pr, member, len) + 4 + (len) +#include "drbd_nl.h" +}; + +/* The two highest bits are used for the tag type */ +#define TT_MASK 0xC000 +#define TT_INTEGER 0x0000 +#define TT_INT64 0x4000 +#define TT_BIT 0x8000 +#define TT_STRING 0xC000 +/* The next bit indicates if processing of the tag is mandatory */ +#define T_MANDATORY 0x2000 +#define T_MAY_IGNORE 0x0000 +#define TN_MASK 0x1fff +/* The remaining 13 bits are used to enumerate the tags */ + +#define tag_type(T) ((T) & TT_MASK) +#define tag_number(T) ((T) & TN_MASK) + +/* declare tag enums */ +#define NL_PACKET(name, number, fields) fields +enum drbd_tags { +#define NL_INTEGER(pn, pr, member) T_ ## member = pn | TT_INTEGER | pr , +#define NL_INT64(pn, pr, member) T_ ## member = pn | TT_INT64 | pr , +#define NL_BIT(pn, pr, member) T_ ## member = pn | TT_BIT | pr , +#define NL_STRING(pn, pr, member, len) T_ ## member = pn | TT_STRING | pr , +#include "drbd_nl.h" +}; + +struct tag { + const char *name; + int type_n_flags; + int max_len; +}; + +/* declare tag names */ +#define NL_PACKET(name, number, fields) fields +static const struct tag tag_descriptions[] = { +#define NL_INTEGER(pn, pr, member) [ pn ] = { #member, TT_INTEGER | pr, sizeof(int) }, +#define NL_INT64(pn, pr, member) [ pn ] = { #member, TT_INT64 | pr, sizeof(__u64) }, +#define NL_BIT(pn, pr, member) [ pn ] = { #member, TT_BIT | pr, sizeof(int) }, +#define NL_STRING(pn, pr, member, len) [ pn ] = { #member, TT_STRING | pr, (len) }, +#include "drbd_nl.h" +}; + +#endif --- linux-2.6.27.orig/ubuntu/drbd/linux/drbd_config.h +++ linux-2.6.27/ubuntu/drbd/linux/drbd_config.h @@ -0,0 +1,89 @@ +/* + drbd_config.h + DRBD's compile time configuration. + + drbd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + drbd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with drbd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef DRBD_CONFIG_H +#define DRBD_CONFIG_H + +extern const char *drbd_buildtag(void); + +#define REL_VERSION "8.2.6" +#define API_VERSION 88 +#define PRO_VERSION_MIN 86 +#define PRO_VERSION_MAX 88 + +#ifndef __CHECKER__ /* for a sparse run, we need all STATICs */ +#define DBG_ALL_SYMBOLS /* no static functs, improves quality of OOPS traces */ +#endif + +/* drbd_assert_breakpoint() function +#define DBG_ASSERTS + */ + +/* Dump all cstate changes */ +#define DUMP_MD 2 + +/* some extra checks +#define PARANOIA + */ + +/* Dump every hour the usage / not usage of zero copy IO */ +/* #define SHOW_SENDPAGE_USAGE */ + +/* Define this to enable dynamic tracing controlled by module parameters + * at run time. This enables ALL use of dynamic tracing including packet + * and bio dumping, etc */ +#define ENABLE_DYNAMIC_TRACE + +/* You can disable the use of the sendpage() call (= zero copy IO) + * If you have the feeling that this might be the cause for troubles. +#define DRBD_DISABLE_SENDPAGE + */ + +/* Enable fault insertion code */ +#define DRBD_ENABLE_FAULTS + +/* RedHat's 2.6.9 kernels have the gfp_t type. Mainline has this feature + * since 2.6.16. If you build for RedHat enable the line below. */ +#define KERNEL_HAS_GFP_T + +/* kernel.org has atomic_add_return since 2.6.10. some vendor kernels + * have it backported, though. Others don't. */ +//#define NEED_BACKPORT_OF_ATOMIC_ADD + +/* 2.6.something has deprecated kmem_cache_t + * some older still use it. + * some have it defined as struct kmem_cache_s, some as struct kmem_cache */ +//#define USE_KMEM_CACHE_S + +/* 2.6.something has sock_create_kern (SE-linux security context stuff) + * some older distribution kernels don't. */ +//#define DEFINE_SOCK_CREATE_KERN + +/* in older kernels (vanilla < 2.6.16) struct netlink_skb_parms has a + * member called dst_groups. Later it is called dst_group (without 's'). */ +//#define DRBD_NL_DST_GROUPS + +/* in older kernels (vanilla < 2.6.14) is no kzalloc() */ +//#define NEED_BACKPORT_OF_KZALLOC + +// some vendor kernels have it, some don't +//#define NEED_SG_SET_BUF +#define HAVE_LINUX_SCATTERLIST_H + +#endif --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_acpi.h +++ linux-2.6.27/ubuntu/tlsup/tlsup_acpi.h @@ -0,0 +1,81 @@ +/* Toshiba Laptop Support -- tlsup_acpi.h + * + * ACPI support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#ifndef TLSUP_ACPI_H +#define TLSUP_ACPI_H + +/* Detect the toshiba ACPI support and prepare the HCI. + * Returns zero on success, -errno on failure. + */ +extern int tlsup_acpi_detect(void); + +/* Report the details of the chosen/found ACPI interface to the kernel + * log + */ +extern void tlsup_acpi_report(void); + +/* Toshiba HCI */ + +#define HCI_SUCCESS 0x0000 +#define HCI_FAILURE 0x1000 +#define HCI_NOT_SUPPORTED 0x8000 +#define HCI_EMPTY 0x8c00 + +/* perform an HCI read operation, returning one u32 value and the + * HCI status. + * + * The function itself returns 0 on success, -errno on failure. + */ +extern int tlsup_hci_read_1_reg(u32 reg, u32 *result, u32 *hci_status); + +/* perform an HCI write operation with one u32 value and returning the + * HCI status. + * + * The function itself returns 0 on success, -errno on failure. + */ +extern int tlsup_hci_write_1_reg(u32 reg, u32 value, u32 *hci_status); + +/* perform an HCI read operation, returning two u32 values and the HCI + * status. + * + * The two values are passed to the call, so zero them if you don't + * want that. + * + * The function itself returns 0 on success, -errno on failure. + */ +extern int tlsup_hci_read_2_reg(u32 reg, u32 *result1, u32 *result2, u32 *hci_status); + +/* perform an HCI write operation with two u32 values and returning + * the HCI status. + * + * The function itself returns 0 on success, -errno on failure. + */ +extern int tlsup_hci_write_2_reg(u32 reg, u32 value1, u32 value2, u32 *hci_status); + +#endif /* TLSUP_ACPI_H */ --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_backlight.c +++ linux-2.6.27/ubuntu/tlsup/tlsup_backlight.c @@ -0,0 +1,115 @@ +/* Toshiba Laptop Support -- tlsup_backlight.c + * + * LCD Backlight support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#include +#include +#include +#include +#include +#include + +#include "tlsup.h" + +/* HCI registers */ +#define HCI_REG_LCD_BRIGHTNESS 0x002a + +/* Value manipulation */ +#define HCI_LCD_BRIGHTNESS_BITS 3 +#define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS) +#define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS) + + +/* Backlight driver */ +static struct backlight_device *tlsup_backlight_device = NULL; + +static int tlsup_read_brightness(struct backlight_device *bd) +{ + u32 hci_result; + u32 value; + + if (tlsup_hci_read_1_reg(HCI_REG_LCD_BRIGHTNESS, &value, &hci_result)) + return -EFAULT; + + if (hci_result != HCI_SUCCESS) + return -EFAULT; + + return (value >> HCI_LCD_BRIGHTNESS_SHIFT); +} + +static int tlsup_set_brightness(struct backlight_device *bd) +{ + u32 hci_result; + u32 value = bd->props.brightness << HCI_LCD_BRIGHTNESS_SHIFT; + + if (tlsup_hci_write_1_reg(HCI_REG_LCD_BRIGHTNESS, value, &hci_result)) + return -EFAULT; + + if (hci_result != HCI_SUCCESS) + return -EFAULT; + + return 0; +} + +static struct backlight_ops tlsup_backlight_data = { + .get_brightness = tlsup_read_brightness, + .update_status = tlsup_set_brightness, +}; + +/* Registration functions */ + +int tlsup_register_backlight(void) +{ + u32 hci_result, ignored; + if (tlsup_hci_read_1_reg(HCI_REG_LCD_BRIGHTNESS, &ignored, &hci_result)) + return -EFAULT; + if (hci_result != HCI_SUCCESS) + return 0; + /* Present and results are sane, register the backlight driver. */ + tlsup_backlight_device = backlight_device_register("toshiba", + NULL, + NULL, + &tlsup_backlight_data); + + if (IS_ERR(tlsup_backlight_device)) { + int ret = PTR_ERR(tlsup_backlight_device); + tlsup_err("Could not register backlight device\n"); + tlsup_backlight_device = NULL; + return ret; + } + + tlsup_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; + + return 1; +} + +void tlsup_deregister_backlight(void) +{ + if (tlsup_backlight_device) + backlight_device_unregister(tlsup_backlight_device); +} --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_acpi.c +++ linux-2.6.27/ubuntu/tlsup/tlsup_acpi.c @@ -0,0 +1,162 @@ +/* Toshiba Laptop Support -- tlsup_acpi.c + * + * ACPI support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#include +#include +#include +#include + +#include + +#include "tlsup.h" + +/* Toshibas use one of two ACPI method named typically. + * + * The one we detect goes in here. + */ +static const char *hci_method = NULL; + +#define HCI_METHOD_1 "\\_SB_.VALD.GHCI" +#define HCI_METHOD_2 "\\_SB_.VALZ.GHCI" + +/* Check if the provided method name is a valid ACPI method for + * the machine. + * + * Return 0 if it is not valid, 1 if it is. + */ +static int is_valid_acpi_path(const char *method_name) +{ + acpi_handle handle; + acpi_status status; + + status = acpi_get_handle(NULL, (char *)method_name, &handle); + return !ACPI_FAILURE(status); +} + + +/* Detect the toshiba ACPI support and prepare the HCI. + * Returns zero on success, -errno on failure. + */ +int tlsup_acpi_detect(void) +{ + if (acpi_disabled) + return -ENODEV; + + if (is_valid_acpi_path(HCI_METHOD_1)) + hci_method = HCI_METHOD_1; + else if (is_valid_acpi_path(HCI_METHOD_2)) + hci_method = HCI_METHOD_2; + else + return -ENODEV; + + return 0; +} + +void tlsup_acpi_report(void) +{ + tlsup_info(" HCI method: %s\n", hci_method); +} + +/* Toshiba HCI IO */ + +#define HCI_WORDS (6) + +/* operations */ +#define HCI_SET 0xff00 +#define HCI_GET 0xfe00 + +static acpi_status tlsup_hci_raw_io(const u32 input[HCI_WORDS], u32 output[HCI_WORDS]) +{ + struct acpi_object_list params; + union acpi_object in_objs[HCI_WORDS]; + struct acpi_buffer results; + union acpi_object out_objs[HCI_WORDS + 1]; + acpi_status status; + int i; + + params.count = HCI_WORDS; + params.pointer = in_objs; + for (i = 0; i < HCI_WORDS; ++i) { + in_objs[i].type = ACPI_TYPE_INTEGER; + in_objs[i].integer.value = input[i]; + } + + results.length = sizeof(out_objs); + results.pointer = out_objs; + + status = acpi_evaluate_object(NULL, (char *)hci_method, ¶ms, + &results); + if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { + for (i = 0; i < out_objs->package.count; ++i) { + output[i] = out_objs->package.elements[i].integer.value; + } + } + + return status; +} + +int tlsup_hci_read_1_reg(u32 reg, u32 *result, u32 *hci_status) +{ + u32 hci_input[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 }; + u32 hci_output[HCI_WORDS]; + acpi_status status = tlsup_hci_raw_io(hci_input, hci_output); + *result = hci_output[2]; + *hci_status = (status == AE_OK) ? hci_output[0] : HCI_FAILURE; + return (status == AE_OK) ? 0 : -EIO; +} + +int tlsup_hci_write_1_reg(u32 reg, u32 value, u32 *hci_status) +{ + u32 hci_input[HCI_WORDS] = { HCI_SET, reg, value, 0, 0, 0 }; + u32 hci_output[HCI_WORDS]; + acpi_status status = tlsup_hci_raw_io(hci_input, hci_output); + *hci_status = (status == AE_OK) ? hci_output[0] : HCI_FAILURE; + return (status == AE_OK) ? 0 : -EIO; +} + +int tlsup_hci_read_2_reg(u32 reg, u32 *result1, u32 *result2, u32 *hci_status) +{ + u32 hci_input[HCI_WORDS] = { HCI_GET, reg, *result1, *result2, 0, 0 }; + u32 hci_output[HCI_WORDS]; + acpi_status status = tlsup_hci_raw_io(hci_input, hci_output); + *result1 = hci_output[2]; + *result2 = hci_output[3]; + *hci_status = (status == AE_OK) ? hci_output[0] : HCI_FAILURE; + return (status == AE_OK) ? 0 : -EIO; +} + +int tlsup_hci_write_2_reg(u32 reg, u32 value1, u32 value2, u32 *hci_status) +{ + u32 hci_input[HCI_WORDS] = { HCI_SET, reg, value1, value2, 0, 0 }; + u32 hci_output[HCI_WORDS]; + acpi_status status = tlsup_hci_raw_io(hci_input, hci_output); + *hci_status = (status == AE_OK) ? hci_output[0] : HCI_FAILURE; + return (status == AE_OK) ? 0 : -EIO; +} + --- linux-2.6.27.orig/ubuntu/tlsup/Kconfig +++ linux-2.6.27/ubuntu/tlsup/Kconfig @@ -0,0 +1,4 @@ +config TLSUP + tristate "Toshiba ACPI laptop driver" + depends on ACPI && X86 + default m --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_radios.h +++ linux-2.6.27/ubuntu/tlsup/tlsup_radios.h @@ -0,0 +1,45 @@ +/* Toshiba Laptop Support -- tlsup_radios.h + * + * Radio kill-switch support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#ifndef TLSUP_RADIOS_H +#define TLSUP_RADIOS_H + +/* Look for the radio kill switch support and if present, register + * rfkill devices to manage them. This supports wifi, bluetooth and + * hsdpa modem. + * + * Returns -errno on error, 0 on success (but no registration) or the + * number of rfkills registered. + */ +extern int tlsup_register_radios(void); + +/* Remove the registration of the radios. */ +extern void tlsup_deregister_radios(void); + +#endif /* TLSUP_RADIOS_H */ --- linux-2.6.27.orig/ubuntu/tlsup/BOM +++ linux-2.6.27/ubuntu/tlsup/BOM @@ -0,0 +1,4 @@ +Downloaded from: http://bzr.digital-scurf.org/trees/dsilvers/toshiba-laptop-support/ +Current Version: Mon, 11 Aug 2008 13:07:54 -0400 +Comments: Supercedes toshiba and toshiba_acpi drivers. + --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_hotkeys.c +++ linux-2.6.27/ubuntu/tlsup/tlsup_hotkeys.c @@ -0,0 +1,238 @@ +/* Toshiba Laptop Support -- tlsup_hotkeys.c + * + * Hotkeys input support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#include +#include +#include +#include +#include +#include + +#include "tlsup.h" + +/* HCI registers */ +#define HCI_SYSTEM_EVENT 0x0016 + +/* Value manipulation */ + +/* Module stuff */ +static int hotkeys_checks_per_second = 4; +module_param(hotkeys_checks_per_second, uint, 0400); +MODULE_PARM_DESC(hotkeys_checks_per_second, "The number of times per second that the kernel will poll the HCI for hotkey events."); + +/* Keycode system */ + +struct key_entry { + u8 fncode; + u16 keycode; +}; + +static struct key_entry tlsup_hotkey_map[] = { + {2, KEY_FN_1}, + {0, 0} +}; + +static struct key_entry *tlsup_get_entry_by_scancode(int code) +{ + struct key_entry *key; + + for (key = tlsup_hotkey_map; key->fncode != 0; key++) { + if (key->fncode == code) + return key; + } + + return NULL; +} + +static struct key_entry *tlsup_get_entry_by_keycode(int code) +{ + struct key_entry *key; + + for (key = tlsup_hotkey_map; key->fncode != 0; key++) { + if (key->keycode == code) + return key; + } + + return NULL; +} + +static int tlsup_get_keycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct key_entry *key = tlsup_get_entry_by_scancode(scancode); + + if (key != NULL) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int tlsup_set_keycode(struct input_dev *dev, int scancode, int keycode) +{ + struct key_entry *key = tlsup_get_entry_by_scancode(scancode); + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + if (key != NULL) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (tlsup_get_entry_by_keycode(old_keycode) == NULL) + clear_bit(old_keycode, dev->keybit); + return 0; + } + + return -EINVAL; +} + +/* Hotkey system */ + +static struct input_polled_dev *tlsup_polled_dev = NULL; + +static int tlsup_read_hotkey_event(void) +{ + u32 value, hci_result; + if (tlsup_hci_read_1_reg(HCI_SYSTEM_EVENT, &value, &hci_result)) + return -EFAULT; + + if (hci_result == HCI_EMPTY) { + /* better luck next time */ + return 0; + } else if (hci_result == HCI_NOT_SUPPORTED) { + /* This is a workaround for an unresolved issue on + * some machines where system events sporadically + * become disabled. */ + tlsup_hci_write_1_reg(HCI_SYSTEM_EVENT, 1, &hci_result); + tlsup_info("Had to re-enable hotkeys.\n"); + return 0; + } else if (hci_result == HCI_SUCCESS) { + /* Process key */ + if (value == 0x0100) { + /* Fn+ */ + return 0; + } else { + return value; + } + } else { + /* Unknown result */ + return -EFAULT; + } + /* Not reached */ + BUG(); +} + +static void tlsup_polled_dev_poll(struct input_polled_dev *dev) +{ + int scancode = tlsup_read_hotkey_event(); + struct key_entry *key; + + if (scancode <= 0) + return; + + key = tlsup_get_entry_by_scancode(scancode & 0x7F); + + if (key != NULL) { + input_report_key(dev->input, key->keycode, + !(scancode & 0x80)); + input_sync(dev->input); + } + +} + +/* Registration functions */ + +int tlsup_register_hotkeys(void) +{ + int ret; + struct input_dev *input; + struct key_entry *key; + + /* Swallow what's there already */ + while ((ret = tlsup_read_hotkey_event()) > 0); + + if (ret < 0) + return -EFAULT; + + + + /* Present and results are sane, register the backlight driver. */ + tlsup_polled_dev = input_allocate_polled_device(); + if (tlsup_polled_dev == NULL) { + tlsup_err("Could not allocate polled device for hotkeys\n"); + return -ENOMEM; + } + + tlsup_polled_dev->private = kmalloc(sizeof(tlsup_hotkey_map), GFP_KERNEL); + + tlsup_polled_dev->poll = tlsup_polled_dev_poll; + tlsup_polled_dev->poll_interval = 1000 / hotkeys_checks_per_second; + + /* id name phys bits */ + + input = tlsup_polled_dev->input; + + input->id.bustype = BUS_HOST; + input->name = "tlsup: Toshiba Fn Hotkeys"; + input->phys = "toshiba/hotkeys0"; + + input->keycode = tlsup_polled_dev->private; + input->keycodemax = ARRAY_SIZE(tlsup_hotkey_map); + input->keycodesize = sizeof(unsigned short); + + input->getkeycode = tlsup_get_keycode; + input->setkeycode = tlsup_set_keycode; + + set_bit(EV_KEY, input->evbit); + for (key = tlsup_hotkey_map; key->fncode != 0; key++) + set_bit(key->keycode, input->keybit); + clear_bit(KEY_RESERVED, input->keybit); + + if ((ret = input_register_polled_device(tlsup_polled_dev)) < 0) { + input_free_polled_device(tlsup_polled_dev); + tlsup_err("Could not register polled device for hotkeys\n"); + tlsup_polled_dev = NULL; + return ret; + } + + tlsup_info("Hotkeys polled every %dms.\n", 1000 / hotkeys_checks_per_second); + + return 1; +} + +void tlsup_deregister_hotkeys(void) +{ + if (tlsup_polled_dev != NULL) { + input_unregister_polled_device(tlsup_polled_dev); + input_free_polled_device(tlsup_polled_dev); + tlsup_polled_dev = NULL; + } +} --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_radios.c +++ linux-2.6.27/ubuntu/tlsup/tlsup_radios.c @@ -0,0 +1,334 @@ +/* Toshiba Laptop Support -- tlsup_radios.c + * + * Radio kill switch support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#include +#include +#include +#include +#include +#include + +#include "tlsup.h" + +/* Module stuff */ +static int radio_powerdown_time = 100; +static int powerup_settle_time = 200; + +module_param(radio_powerdown_time, uint, 0400); +MODULE_PARM_DESC(radio_powerdown_time, "The number of milliseconds between powering off a radio and the device power."); +module_param(powerup_settle_time, uint, 0400); +MODULE_PARM_DESC(powerup_settle_time, "The number of milliseconds between powering on a device and applying radio power."); + +/* HCI registers */ +#define HCI_WIRELESS 0x0056 + +/* Value manipulation */ +#define HCI_WIRELESS_PRESENT 0x0000 +#define HCI_WIRELESS_STATUS 0x0001 +#define HCI_WIRELESS_GLOBAL_RADIO_SWITCH 0x0001 +#define HCI_WIRELESS_3GHSDPA_POWER 0x4000 +#define HCI_WIRELESS_3GHSDPA_RADIO 0x2000 +#define HCI_WIRELESS_BLUETOOTH_POWER 0x0040 +#define HCI_WIRELESS_BLUETOOTH_RADIO 0x0080 +#define HCI_WIRELESS_WLAN_RADIO 0x0200 + +/* Radio manipulation functions */ + +static u32 tlsup_radios_present = 0; + +static int tlsup_test_radio_presence(u32 this_switch) +{ + u32 swvalue; + u32 swaddr; + u32 hci_result; + u32 current_status; + + swvalue = 0; + swaddr = HCI_WIRELESS_STATUS; + + if (tlsup_hci_read_2_reg(HCI_WIRELESS, &swvalue, &swaddr, &hci_result)) + return 0; + if (hci_result != HCI_SUCCESS) + return 0; + + current_status = (swvalue & this_switch) ? 1 : 0; + + /* Attempt to invert the current state */ + + swvalue = !current_status; + swaddr = this_switch; + if (tlsup_hci_write_2_reg(HCI_WIRELESS, swvalue, swaddr, &hci_result)) + return 0; + if (hci_result != HCI_SUCCESS) + return 0; + + /* Read back the allegedly inverted switch status */ + swvalue = 0; + swaddr = HCI_WIRELESS_STATUS; + + if (tlsup_hci_read_2_reg(HCI_WIRELESS, &swvalue, &swaddr, &hci_result)) + return 0; + if (hci_result != HCI_SUCCESS) + return 0; + + if (((swvalue & this_switch) ? 1 : 0) != !current_status) + /* Failed to invert */ + return 0; + + /* inversion successful, attempt to restore previous value */ + + swvalue = current_status; + swaddr = this_switch; + + if (tlsup_hci_write_2_reg(HCI_WIRELESS, swvalue, swaddr, &hci_result)) + return 0; + if (hci_result != HCI_SUCCESS) + return 0; + + /* verify restoration of value */ + + swvalue = 0; + swaddr = HCI_WIRELESS_STATUS; + + if (tlsup_hci_read_2_reg(HCI_WIRELESS, &swvalue, &swaddr, &hci_result)) + return 0; + if (hci_result != HCI_SUCCESS) + return 0; + + if (((swvalue & this_switch) ? 1 : 0) != current_status) + /* Failed to restore */ + return 0; + + /* Restoration successful */ + + tlsup_radios_present |= this_switch; + return 1; +} + +static enum rfkill_state tlsup_read_switch_state(u32 this_switch) +{ + u32 swvalue = 0; + u32 swaddr = HCI_WIRELESS_STATUS; + u32 hci_result; + + if (tlsup_hci_read_2_reg(HCI_WIRELESS, &swvalue, &swaddr, &hci_result)) + return 0; + if (hci_result != HCI_SUCCESS) + return 0; + + return (swvalue & this_switch) ? RFKILL_STATE_ON : RFKILL_STATE_OFF; +} + +static void tlsup_set_switch_state(u32 this_switch, enum rfkill_state state) +{ + u32 swvalue = state; + u32 swaddr = this_switch; + u32 hci_result; + + if (tlsup_hci_write_2_reg(HCI_WIRELESS, swvalue, swaddr, &hci_result)) { + tlsup_err("Error setting switch state\n"); + } + if (hci_result != HCI_SUCCESS) { + tlsup_err("Error setting switch state\n"); + } +} + +/* Radio rfkill driver */ + +struct tlsup_radio_power_control { + u32 power_reg; + u32 radio_reg; +}; + +static int tlsup_radio_switch_set(void *data, enum rfkill_state state) +{ + struct tlsup_radio_power_control *rpc = (struct tlsup_radio_power_control *)data; + + if (state == RFKILL_STATE_OFF) { + if (rpc->radio_reg) { + tlsup_set_switch_state(rpc->radio_reg, RFKILL_STATE_OFF); + msleep(radio_powerdown_time); + } + + if (rpc->power_reg) + tlsup_set_switch_state(rpc->power_reg, RFKILL_STATE_OFF); + } else { + if (rpc->power_reg) { + tlsup_set_switch_state(rpc->power_reg, RFKILL_STATE_ON); + msleep(powerup_settle_time); + } + if (rpc->radio_reg) + tlsup_set_switch_state(rpc->radio_reg, RFKILL_STATE_ON); + } + + return 0; +} + +static struct rfkill *hsdpa_rfkill_dev = NULL; +static struct rfkill *bluetooth_rfkill_dev = NULL; +static struct rfkill *wlan_rfkill_dev = NULL; + +static struct rfkill *tlsup_register_rfkill(const char *name, enum rfkill_type rft, + u32 optional_power, + u32 optional_radio) +{ + struct tlsup_radio_power_control *rpc; + struct rfkill *ret; + enum rfkill_state curstate = RFKILL_STATE_OFF; + + ret = rfkill_allocate(NULL, rft); + + if (ret == NULL) + return NULL; + + rpc = kmalloc(sizeof(struct tlsup_radio_power_control), GFP_KERNEL); + if (rpc == NULL) { + rfkill_free(ret); + return NULL; + } + + ret->name = name; + ret->data = rpc; + + rpc->power_reg = optional_power; + rpc->radio_reg = optional_radio; + + if (optional_power) + curstate |= tlsup_read_switch_state(optional_power); + if (optional_radio) + curstate |= tlsup_read_switch_state(optional_radio); + + ret->state = curstate; + + if (optional_power) + tlsup_set_switch_state(optional_power, curstate); + if (optional_radio) + tlsup_set_switch_state(optional_radio, curstate); + + ret->toggle_radio = tlsup_radio_switch_set; + ret->user_claim_unsupported = 1; + + rfkill_register(ret); + + return ret; +} + +/* Registration functions */ + +int tlsup_register_radios(void) +{ + int hsdpa_present = 0, bluetooth_present = 0, wlan_present = 0; + int registered = 0; + + if (tlsup_test_radio_presence(HCI_WIRELESS_3GHSDPA_POWER)) { + hsdpa_present = 1; + } + + if (tlsup_test_radio_presence(HCI_WIRELESS_3GHSDPA_RADIO)) { + hsdpa_present = 1; + } + + if (tlsup_test_radio_presence(HCI_WIRELESS_BLUETOOTH_POWER)) { + bluetooth_present = 1; + } + + if (tlsup_test_radio_presence(HCI_WIRELESS_BLUETOOTH_RADIO)) { + bluetooth_present = 1; + } + + if (tlsup_test_radio_presence(HCI_WIRELESS_WLAN_RADIO)) { + wlan_present = 1; + } + + if (hsdpa_present) { + tlsup_info("HSDPA Modem power switch %spresent, radio switch %spresent\n", + (tlsup_radios_present & HCI_WIRELESS_3GHSDPA_POWER) ? "" : "not ", + (tlsup_radios_present & HCI_WIRELESS_3GHSDPA_RADIO) ? "" : "not "); + hsdpa_rfkill_dev = tlsup_register_rfkill("tlsup-hsdpa_3g_modem", RFKILL_TYPE_WLAN, + HCI_WIRELESS_3GHSDPA_POWER, + HCI_WIRELESS_3GHSDPA_RADIO); + if (hsdpa_rfkill_dev) { + tlsup_info("HSDPA Modem claims to be %s\n", + (hsdpa_rfkill_dev->state == RFKILL_STATE_OFF) ? "off" : "on"); + registered++; + } else { + tlsup_err("Failed to register HSDPA modem switch\n"); + } + } + + if (bluetooth_present) { + tlsup_info("Bluetooth power switch %spresent, radio switch %spresent\n", + (tlsup_radios_present & HCI_WIRELESS_BLUETOOTH_POWER) ? "" : "not ", + (tlsup_radios_present & HCI_WIRELESS_BLUETOOTH_RADIO) ? "" : "not "); + bluetooth_rfkill_dev = tlsup_register_rfkill("tlsup-bluetooth", RFKILL_TYPE_BLUETOOTH, + HCI_WIRELESS_BLUETOOTH_POWER, + HCI_WIRELESS_BLUETOOTH_RADIO); + if (bluetooth_rfkill_dev) { + tlsup_info("Bluetooth claims to be %s\n", + (bluetooth_rfkill_dev->state == RFKILL_STATE_OFF) ? "off" : "on"); + registered++; + } else { + tlsup_err("Failed to register bluetooth switch\n"); + } + } + + if (wlan_present) { + tlsup_info("WLAN radio switch %spresent\n", + (tlsup_radios_present & HCI_WIRELESS_WLAN_RADIO) ? "" : "not "); + wlan_rfkill_dev = tlsup_register_rfkill("tlsup-wlan", RFKILL_TYPE_WLAN, + 0, + HCI_WIRELESS_WLAN_RADIO); + if (wlan_rfkill_dev) { + tlsup_info("WLAN claims to be %s\n", + (wlan_rfkill_dev->state == RFKILL_STATE_OFF) ? "off" : "on"); + registered++; + } else { + tlsup_err("Failed to register WLAN switch\n"); + } + } + + return registered; +} + +static inline void tlsup_free_rfkill_dev(struct rfkill *d) +{ + void *data = d->data; + rfkill_unregister(d); + kfree(data); +} + +void tlsup_deregister_radios(void) +{ + if (hsdpa_rfkill_dev) + tlsup_free_rfkill_dev(hsdpa_rfkill_dev); + if (bluetooth_rfkill_dev) + tlsup_free_rfkill_dev(bluetooth_rfkill_dev); + if (wlan_rfkill_dev) + tlsup_free_rfkill_dev(wlan_rfkill_dev); +} --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_mod.c +++ linux-2.6.27/ubuntu/tlsup/tlsup_mod.c @@ -0,0 +1,87 @@ +/* Toshiba Laptop Support -- tlsup_mod.c + * + * Aggregation and module structural support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#include +#include +#include +#include + +#include "tlsup.h" + +MODULE_AUTHOR("Daniel Silverstone"); +MODULE_DESCRIPTION("Toshiba Laptop Support Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION(TLSUP_VERSION); + +/* The following ACPI devices tend to be exported by toshiba laptops */ +MODULE_ALIAS("acpi:TOS6200"); +MODULE_ALIAS("acpi:TOS6207"); +MODULE_ALIAS("acpi:TOS6208"); + +static void toshiba_laptop_support_exit(void) +{ + tlsup_deregister_radios(); + tlsup_deregister_hotkeys(); + tlsup_deregister_backlight(); +} + +static int __init toshiba_laptop_support_init(void) +{ + int ret; + + if ((ret = tlsup_acpi_detect()) < 0) + return ret; + + tlsup_info("Toshiba Laptop Support version %s initialising...\n", + TLSUP_VERSION); + + tlsup_acpi_report(); + + if ((ret = tlsup_register_backlight()) < 0) + return ret; + + if ((ret = tlsup_register_hotkeys()) < 0) { + tlsup_deregister_backlight(); + return ret; + } + + if ((ret = tlsup_register_radios()) < 0) { + tlsup_deregister_hotkeys(); + tlsup_deregister_backlight(); + return ret; + } + + tlsup_info("Toshiba Laptop Support version %s loaded.\n", + TLSUP_VERSION); + + return 0; +} + +module_init(toshiba_laptop_support_init); +module_exit(toshiba_laptop_support_exit); --- linux-2.6.27.orig/ubuntu/tlsup/tlsup.h +++ linux-2.6.27/ubuntu/tlsup/tlsup.h @@ -0,0 +1,44 @@ +/* Toshiba Laptop Support -- tlsup.h + * + * General top level definitions etc for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#ifndef TLSUP_H +#define TLSUP_H + +#define MODULE_LOGPREFIX "tlsup: " + +#define tlsup_info(X...) printk(KERN_INFO MODULE_LOGPREFIX X) +#define tlsup_err(X...) printk(KERN_ERR MODULE_LOGPREFIX X) +#define tlsup_notice(X...) printk(KERN_NOTICE MODULE_LOGPREFIX X) + +#include "tlsup_acpi.h" +#include "tlsup_backlight.h" +#include "tlsup_hotkeys.h" +#include "tlsup_radios.h" + +#endif /* TLSUP_H */ --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_hotkeys.h +++ linux-2.6.27/ubuntu/tlsup/tlsup_hotkeys.h @@ -0,0 +1,45 @@ +/* Toshiba Laptop Support -- tlsup_hotkeys.h + * + * Hotkeys input support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#ifndef TLSUP_HOTKEYS_H +#define TLSUP_HOTKEYS_H + +/* Look for the hotkey support in the HCI and if found, register with + * input-polldev to get an input device to provide events to userland + * with. + * + * Returns -errno on error, 0 on success (but no registration) or 1 if + * an input device was registered. + */ +extern int tlsup_register_hotkeys(void); + +/* Remove the registration of the hotkeys input device. */ +extern void tlsup_deregister_hotkeys(void); + +#endif /* TLSUP_BACKLIGHT_H */ --- linux-2.6.27.orig/ubuntu/tlsup/Makefile +++ linux-2.6.27/ubuntu/tlsup/Makefile @@ -0,0 +1,6 @@ +TLSUP_VERSION := 0.10 +EXTRA_CFLAGS += '-DTLSUP_VERSION="$(TLSUP_VERSION)"' + +obj-$(CONFIG_TLSUP) := tlsup.o + +tlsup-objs := tlsup_mod.o tlsup_acpi.o tlsup_backlight.o tlsup_hotkeys.o tlsup_radios.o --- linux-2.6.27.orig/ubuntu/tlsup/tlsup_backlight.h +++ linux-2.6.27/ubuntu/tlsup/tlsup_backlight.h @@ -0,0 +1,44 @@ +/* Toshiba Laptop Support -- tlsup_backlight.h + * + * LCD Backlight support for T.L.S. + * + * Copyright 2008 Daniel Silverstone + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; specifically version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * + * Credits: + * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse + * engineering the Windows drivers + * Rob Miller - TV out and hotkeys help + * John Belmonte - The toshiba_acpi driver maintainance for some time. + */ + +#ifndef TLSUP_BACKLIGHT_H +#define TLSUP_BACKLIGHT_H + +/* Look for the LCD backlight support and if present, register a backlight + * class device to manage it. + * + * Returns -errno on error, 0 on success (but no registration) or 1 if + * a backlight was registered. + */ +extern int tlsup_register_backlight(void); + +/* Remove the registration of the backlight. */ +extern void tlsup_deregister_backlight(void); + +#endif /* TLSUP_BACKLIGHT_H */ --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-raid4-5.c +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-raid4-5.c @@ -0,0 +1,4422 @@ +/* + * Copyright (C) 2005-2008 Red Hat GmbH + * + * Module Author: Heinz Mauelshagen + * + * This file is released under the GPL. + * + * WARNING: this is Alpha software wich can corrupt your data! + * + * + * Linux 2.6 Device Mapper RAID4 and RAID5 target. + * + * Supports: + * o RAID4 with dedicated and selectable parity device + * o RAID5 with rotating parity (left+right, symmetric+asymmetric) + * + * + * Thanks to MD for: + * o the raid address calculation algorithm + * o the base of the biovec <-> page list copier. + * + * + * Uses region hash to keep track of how many writes are in flight to + * regions in order to use dirty log to keep state of regions to recover: + * + * o clean regions (those which are synchronized + * and don't have write io in flight) + * o dirty regions (those with write io in flight) + * + * + * On startup, any dirty regions are migrated to the 'nosync' state + * and are subject to recovery by the daemon. + * + * See raid_ctr() for table definition. + * + * + * FIXME: + * o add virtual interface for locking + * o remove instrumentation (REMOVEME:) + * + */ + +static const char *version = "v0.2427"; + +#include "dm.h" +#include "dm-bio-list.h" +#include +#include +#include "dm-mem-cache.h" +#include "dm-message.h" +#include "dm-region_hash.h" +#include "dm-raid4-5.h" +#include +#include + +#define STR_LEN(ptr, str) ptr, str, strlen(ptr) +/* + * Configurable parameters + */ +#define INLINE + +/* Default # of stripes if not set in constructor. */ +#define STRIPES 64 + +/* Minimum/maximum # of selectable stripes. */ +#define STRIPES_MIN 8 +#define STRIPES_MAX 16384 + +/* Default chunk size in sectors if not set in constructor. */ +#define CHUNK_SIZE 64 + +/* Default io size in sectors if not set in constructor. */ +#define IO_SIZE_MIN SECTORS_PER_PAGE +#define IO_SIZE IO_SIZE_MIN + +/* Maximum setable chunk size in sectors. */ +#define CHUNK_SIZE_MAX 16384 + +/* Recover io size default in sectors. */ +#define RECOVER_IO_SIZE_MIN 64 +#define RECOVER_IO_SIZE 256 + +/* Default percentage recover io bandwidth. */ +#define BANDWIDTH 10 +#define BANDWIDTH_MIN 1 +#define BANDWIDTH_MAX 100 +/* + * END Configurable parameters + */ + +#define TARGET "dm-raid45" +#define DAEMON "kraid45d" +#define DM_MSG_PREFIX TARGET + +#define SECTORS_PER_PAGE (PAGE_SIZE >> SECTOR_SHIFT) + +/* Amount/size for __xor(). */ +#define SECTORS_PER_XOR SECTORS_PER_PAGE +#define XOR_SIZE PAGE_SIZE + +/* Derive raid_set from stripe_cache pointer. */ +#define RS(x) container_of(x, struct raid_set, sc) + +/* Check value in range. */ +#define range_ok(i, min, max) (i >= min && i <= max) + +/* Page reference. */ +#define PAGE(stripe, p) ((stripe)->obj[p].pl->page) + +/* Bio list reference. */ +#define BL(stripe, p, rw) (stripe->ss[p].bl + rw) + +/* Page list reference. */ +#define PL(stripe, p) (stripe->obj[p].pl) + +/* Check argument is power of 2. */ +#define POWER_OF_2(a) (!(a & (a - 1))) + +/* xor optimization. */ +typedef unsigned long xor_t; + +/* Factor out to dm-bio-list.h */ +static inline void bio_list_push(struct bio_list *bl, struct bio *bio) +{ + bio->bi_next = bl->head; + bl->head = bio; + + if (!bl->tail) + bl->tail = bio; +} + +/* Factor out to dm.h */ +#define TI_ERR_RET(str, ret) \ + do { ti->error = DM_MSG_PREFIX ": " str; return ret; } while(0); +#define TI_ERR(str) TI_ERR_RET(str, -EINVAL) + +/*----------------------------------------------------------------- + * Stripe cache + * + * Cache for all reads and writes to raid sets (operational or degraded) + * + * We need to run all data to and from a RAID set through this cache, + * because parity chunks need to get calculated from data chunks + * or, in the degraded/resynchronization case, missing chunks need + * to be reconstructed using the other chunks of the stripe. + *---------------------------------------------------------------*/ +/* Protect kmem cache # counter. */ +static atomic_t _stripe_sc_nr = ATOMIC_INIT(-1); /* kmem cache # counter. */ + +/* A stripe set (holds bios hanging off). */ +struct stripe_set { + struct stripe *stripe; /* Backpointer to stripe for endio(). */ + struct bio_list bl[3]; /* Reads, writes, and writes merged. */ +#define WRITE_MERGED 2 +}; + +#if READ != 0 || WRITE != 1 +#error dm-raid45: READ/WRITE != 0/1 used as index!!! +#endif + +/* + * Stripe linked list indexes. Keep order, because the stripe + * and the stripe cache rely on the first 3! + */ +enum list_types { + LIST_IO = 0, /* Stripes with io pending. */ + LIST_ENDIO, /* Stripes to endio. */ + LIST_LRU, /* Least recently used stripes. */ + LIST_HASH, /* Hashed stripes. */ + NR_LISTS, /* To size array in struct stripe. */ +}; + +enum lock_types { + LOCK_ENDIO = 0, /* Protect endio list. */ + LOCK_LRU, /* Protect lru list. */ + NR_LOCKS, /* To size array in struct stripe_cache. */ +}; + +/* A stripe: the io object to handle all reads and writes to a RAID set. */ +struct stripe { + struct stripe_cache *sc; /* Backpointer to stripe cache. */ + + sector_t key; /* Hash key. */ + sector_t region; /* Region stripe is mapped to. */ + + /* Reference count. */ + atomic_t cnt; + + struct { + unsigned long flags; /* flags (see below). */ + + /* + * Pending ios in flight: + * + * used as a 'lock' to control move of stripe to endio list + */ + atomic_t pending; /* Pending ios in flight. */ + + /* Sectors to read and write for multi page stripe sets. */ + unsigned size; + } io; + + /* Lock on stripe (for clustering). */ + void *lock; + + /* + * 4 linked lists: + * o io list to flush io + * o endio list + * o LRU list to put stripes w/o reference count on + * o stripe cache hash + */ + struct list_head lists[NR_LISTS]; + + struct { + unsigned short parity; /* Parity chunk index. */ + short recover; /* Recovery chunk index. */ + } idx; + + /* This sets memory cache object (dm-mem-cache). */ + struct dm_mem_cache_object *obj; + + /* Array of stripe sets (dynamically allocated). */ + struct stripe_set ss[0]; +}; + +/* States stripes can be in (flags field). */ +enum stripe_states { + STRIPE_ACTIVE, /* Active io on stripe. */ + STRIPE_ERROR, /* io error on stripe. */ + STRIPE_MERGED, /* Writes got merged. */ + STRIPE_READ, /* Read. */ + STRIPE_RBW, /* Read-before-write. */ + STRIPE_RECONSTRUCT, /* reconstruct of a missing chunk required. */ + STRIPE_RECOVER, /* Stripe used for RAID set recovery. */ +}; + +/* ... and macros to access them. */ +#define BITOPS(name, what, var, flag) \ +static inline int TestClear ## name ## what(struct var *v) \ +{ return test_and_clear_bit(flag, &v->io.flags); } \ +static inline int TestSet ## name ## what(struct var *v) \ +{ return test_and_set_bit(flag, &v->io.flags); } \ +static inline void Clear ## name ## what(struct var *v) \ +{ clear_bit(flag, &v->io.flags); } \ +static inline void Set ## name ## what(struct var *v) \ +{ set_bit(flag, &v->io.flags); } \ +static inline int name ## what(struct var *v) \ +{ return test_bit(flag, &v->io.flags); } + + +BITOPS(Stripe, Active, stripe, STRIPE_ACTIVE) +BITOPS(Stripe, Merged, stripe, STRIPE_MERGED) +BITOPS(Stripe, Error, stripe, STRIPE_ERROR) +BITOPS(Stripe, Read, stripe, STRIPE_READ) +BITOPS(Stripe, RBW, stripe, STRIPE_RBW) +BITOPS(Stripe, Reconstruct, stripe, STRIPE_RECONSTRUCT) +BITOPS(Stripe, Recover, stripe, STRIPE_RECOVER) + +/* A stripe hash. */ +struct stripe_hash { + struct list_head *hash; + unsigned buckets; + unsigned mask; + unsigned prime; + unsigned shift; +}; + +/* A stripe cache. */ +struct stripe_cache { + /* Stripe hash. */ + struct stripe_hash hash; + + /* Stripes with io to flush, stripes to endio and LRU lists. */ + struct list_head lists[3]; + + /* Locks to protect endio and lru lists. */ + spinlock_t locks[NR_LOCKS]; + + /* Slab cache to allocate stripes from. */ + struct { + struct kmem_cache *cache; /* Cache itself. */ + char name[32]; /* Unique name. */ + } kc; + + struct dm_io_client *dm_io_client; /* dm-io client resource context. */ + + /* dm-mem-cache client resource context. */ + struct dm_mem_cache_client *dm_mem_cache_client; + + int stripes_parm; /* # stripes parameter from constructor. */ + atomic_t stripes; /* actual # of stripes in cache. */ + atomic_t stripes_to_shrink; /* # of stripes to shrink cache by. */ + atomic_t stripes_last; /* last # of stripes in cache. */ + atomic_t active_stripes; /* actual # of active stripes in cache. */ + + /* REMOVEME: */ + atomic_t max_active_stripes; /* actual # of active stripes in cache. */ +}; + +/* Flag specs for raid_dev */ ; +enum raid_dev_flags { DEVICE_FAILED, IO_QUEUED }; + +/* The raid device in a set. */ +struct raid_dev { + struct dm_dev *dev; + unsigned long flags; /* raid_dev_flags. */ + sector_t start; /* offset to map to. */ +}; + +/* Flags spec for raid_set. */ +enum raid_set_flags { + RS_CHECK_OVERWRITE, /* Check for chunk overwrites. */ + RS_DEAD, /* RAID set inoperational. */ + RS_DEVEL_STATS, /* REMOVEME: display status information. */ + RS_IO_ERROR, /* io error on set. */ + RS_RECOVER, /* Do recovery. */ + RS_RECOVERY_BANDWIDTH, /* Allow recovery bandwidth (delayed bios). */ + RS_REGION_GET, /* get a region to recover. */ + RS_SC_BUSY, /* stripe cache busy -> send an event. */ + RS_SUSPENDED, /* RAID set suspendedn. */ +}; + +/* REMOVEME: devel stats counters. */ +enum stats_types { + S_BIOS_READ, + S_BIOS_ADDED_READ, + S_BIOS_ENDIO_READ, + S_BIOS_WRITE, + S_BIOS_ADDED_WRITE, + S_BIOS_ENDIO_WRITE, + S_CAN_MERGE, + S_CANT_MERGE, + S_CONGESTED, + S_DM_IO_READ, + S_DM_IO_WRITE, + S_ACTIVE_READS, + S_BANDWIDTH, + S_BARRIER, + S_BIO_COPY_PL_NEXT, + S_DEGRADED, + S_DELAYED_BIOS, + S_EVICT, + S_FLUSHS, + S_HITS_1ST, + S_IOS_POST, + S_INSCACHE, + S_MAX_LOOKUP, + S_MERGE_PAGE_LOCKED, + S_NO_BANDWIDTH, + S_NOT_CONGESTED, + S_NO_RW, + S_NOSYNC, + S_PROHIBITPAGEIO, + S_RECONSTRUCT_EI, + S_RECONSTRUCT_DEV, + S_REDO, + S_REQUEUE, + S_STRIPE_ERROR, + S_SUM_DELAYED_BIOS, + S_XORS, + S_NR_STATS, /* # of stats counters. */ +}; + +/* Status type -> string mappings. */ +struct stats_map { + const enum stats_types type; + const char *str; +}; + +static struct stats_map stats_map[] = { + { S_BIOS_READ, "r=" }, + { S_BIOS_ADDED_READ, "/" }, + { S_BIOS_ENDIO_READ, "/" }, + { S_BIOS_WRITE, " w=" }, + { S_BIOS_ADDED_WRITE, "/" }, + { S_BIOS_ENDIO_WRITE, "/" }, + { S_DM_IO_READ, " rc=" }, + { S_DM_IO_WRITE, " wc=" }, + { S_ACTIVE_READS, " active_reads=" }, + { S_BANDWIDTH, " bandwidth=" }, + { S_NO_BANDWIDTH, " no_bandwidth=" }, + { S_BARRIER, " barrier=" }, + { S_BIO_COPY_PL_NEXT, " bio_copy_pl_next=" }, + { S_CAN_MERGE, " can_merge=" }, + { S_MERGE_PAGE_LOCKED, "/page_locked=" }, + { S_CANT_MERGE, "/cant_merge=" }, + { S_CONGESTED, " congested=" }, + { S_NOT_CONGESTED, "/not_congested=" }, + { S_DEGRADED, " degraded=" }, + { S_DELAYED_BIOS, " delayed_bios=" }, + { S_SUM_DELAYED_BIOS, "/sum_delayed_bios=" }, + { S_EVICT, " evict=" }, + { S_FLUSHS, " flushs=" }, + { S_HITS_1ST, " hits_1st=" }, + { S_IOS_POST, " ios_post=" }, + { S_INSCACHE, " inscache=" }, + { S_MAX_LOOKUP, " max_lookup=" }, + { S_NO_RW, " no_rw=" }, + { S_NOSYNC, " nosync=" }, + { S_PROHIBITPAGEIO, " ProhibitPageIO=" }, + { S_RECONSTRUCT_EI, " reconstruct_ei=" }, + { S_RECONSTRUCT_DEV, " reconstruct_dev=" }, + { S_REDO, " redo=" }, + { S_REQUEUE, " requeue=" }, + { S_STRIPE_ERROR, " stripe_error=" }, + { S_XORS, " xors=" }, +}; + +/* + * A RAID set. + */ +typedef void (*xor_function_t)(unsigned count, xor_t **data); +struct raid_set { + struct dm_target *ti; /* Target pointer. */ + + struct { + unsigned long flags; /* State flags. */ + spinlock_t in_lock; /* Protects central input list below. */ + struct bio_list in; /* Pending ios (central input list). */ + struct bio_list work; /* ios work set. */ + wait_queue_head_t suspendq; /* suspend synchronization. */ + atomic_t in_process; /* counter of queued bios (suspendq). */ + atomic_t in_process_max;/* counter of queued bios max. */ + + /* io work. */ + struct workqueue_struct *wq; + struct delayed_work dws; + } io; + + /* External locking. */ + struct dmraid45_locking_type *locking; + + struct stripe_cache sc; /* Stripe cache for this set. */ + + /* Xor optimization. */ + struct { + struct xor_func *f; + unsigned chunks; + unsigned speed; + } xor; + + /* Recovery parameters. */ + struct recover { + struct dm_dirty_log *dl; /* Dirty log. */ + void *rh; /* Region hash. */ + + region_t nr_regions; + region_t nr_regions_to_recover; + region_t nr_regions_recovered; + unsigned long start_jiffies; + unsigned long end_jiffies; + + unsigned bandwidth; /* Recovery bandwidth [%]. */ + unsigned bandwidth_work; /* Recovery bandwidth [factor]. */ + unsigned bandwidth_parm; /* " constructor parm. */ + unsigned io_size; /* io size <= chunk size. */ + unsigned io_size_parm; /* io size ctr parameter. */ + + /* recovery io throttling. */ + atomic_t io_count[2]; /* counter recover/regular io. */ + unsigned long last_jiffies; + + void *reg; /* Actual region to recover. */ + struct stripe *stripe; /* Stripe used for recovery. */ + sector_t pos; /* Position within region to recover. */ + sector_t end; /* End of region to recover. */ + } recover; + + /* RAID set parameters. */ + struct { + struct raid_type *raid_type; /* RAID type (eg, RAID4). */ + unsigned raid_parms; /* # variable raid parameters. */ + + unsigned chunk_size; /* Sectors per chunk. */ + unsigned chunk_size_parm; + unsigned chunk_mask; /* Mask for amount. */ + unsigned chunk_shift; /* rsector chunk size shift. */ + + unsigned io_size; /* Sectors per io. */ + unsigned io_size_parm; + unsigned io_mask; /* Mask for amount. */ + unsigned io_shift_mask; /* Mask for raid_address(). */ + unsigned io_shift; /* rsector io size shift. */ + unsigned pages_per_io; /* Pages per io. */ + + sector_t sectors_per_dev; /* Sectors per device. */ + + atomic_t failed_devs; /* Amount of devices failed. */ + + /* Index of device to initialize. */ + int dev_to_init; + int dev_to_init_parm; + + /* Raid devices dynamically allocated. */ + unsigned raid_devs; /* # of RAID devices below. */ + unsigned data_devs; /* # of RAID data devices. */ + + int ei; /* index of failed RAID device. */ + + /* index of dedicated parity device (i.e. RAID4). */ + int pi; + int pi_parm; /* constructor parm for status output. */ + } set; + + /* REMOVEME: devel stats counters. */ + atomic_t stats[S_NR_STATS]; + + /* Dynamically allocated temporary pointers for xor(). */ + xor_t **data; + + /* Dynamically allocated RAID devices. Alignment? */ + struct raid_dev dev[0]; +}; + + +BITOPS(RS, Bandwidth, raid_set, RS_RECOVERY_BANDWIDTH) +BITOPS(RS, CheckOverwrite, raid_set, RS_CHECK_OVERWRITE) +BITOPS(RS, Dead, raid_set, RS_DEAD) +BITOPS(RS, DevelStats, raid_set, RS_DEVEL_STATS) +BITOPS(RS, IoError, raid_set, RS_IO_ERROR) +BITOPS(RS, Recover, raid_set, RS_RECOVER) +BITOPS(RS, RegionGet, raid_set, RS_REGION_GET) +BITOPS(RS, ScBusy, raid_set, RS_SC_BUSY) +BITOPS(RS, Suspended, raid_set, RS_SUSPENDED) +#undef BITOPS + +#define PageIO(page) PageChecked(page) +#define AllowPageIO(page) SetPageChecked(page) +#define ProhibitPageIO(page) ClearPageChecked(page) + +/*----------------------------------------------------------------- + * Raid-4/5 set structures. + *---------------------------------------------------------------*/ +/* RAID level definitions. */ +enum raid_level { + raid4, + raid5, +}; + +/* Symmetric/Asymmetric, Left/Right parity rotating algorithms. */ +enum raid_algorithm { + none, + left_asym, + right_asym, + left_sym, + right_sym, +}; + +struct raid_type { + const char *name; /* RAID algorithm. */ + const char *descr; /* Descriptor text for logging. */ + const unsigned parity_devs; /* # of parity devices. */ + const unsigned minimal_devs; /* minimal # of devices in set. */ + const enum raid_level level; /* RAID level. */ + const enum raid_algorithm algorithm; /* RAID algorithm. */ +}; + +/* Supported raid types and properties. */ +static struct raid_type raid_types[] = { + {"raid4", "RAID4 (dedicated parity disk)", 1, 3, raid4, none}, + {"raid5_la", "RAID5 (left asymmetric)", 1, 3, raid5, left_asym}, + {"raid5_ra", "RAID5 (right asymmetric)", 1, 3, raid5, right_asym}, + {"raid5_ls", "RAID5 (left symmetric)", 1, 3, raid5, left_sym}, + {"raid5_rs", "RAID5 (right symmetric)", 1, 3, raid5, right_sym}, +}; + +/* Address as calculated by raid_address(). */ +struct address { + sector_t key; /* Hash key (start address of stripe). */ + unsigned di, pi; /* Data and parity disks index. */ +}; + +/* REMOVEME: reset statistics counters. */ +static void stats_reset(struct raid_set *rs) +{ + unsigned s = S_NR_STATS; + + while (s--) + atomic_set(rs->stats + s, 0); +} + +/*---------------------------------------------------------------- + * RAID set management routines. + *--------------------------------------------------------------*/ +/* + * Begin small helper functions. + */ +/* Queue (optionally delayed) io work. */ +static void wake_do_raid_delayed(struct raid_set *rs, unsigned long delay) +{ + struct delayed_work *dws = &rs->io.dws; + + cancel_delayed_work(dws); + queue_delayed_work(rs->io.wq, dws, delay); +} + +/* Queue io work immediately (called from region hash too). */ +static INLINE void wake_do_raid(void *context) +{ + wake_do_raid_delayed(context, 0); +} + +/* Wait until all io has been processed. */ +static INLINE void wait_ios(struct raid_set *rs) +{ + wait_event(rs->io.suspendq, !atomic_read(&rs->io.in_process)); +} + +/* Declare io queued to device. */ +static INLINE void io_dev_queued(struct raid_dev *dev) +{ + set_bit(IO_QUEUED, &dev->flags); +} + +/* Io on device and reset ? */ +static inline int io_dev_clear(struct raid_dev *dev) +{ + return test_and_clear_bit(IO_QUEUED, &dev->flags); +} + +/* Get an io reference. */ +static INLINE void io_get(struct raid_set *rs) +{ + int p = atomic_inc_return(&rs->io.in_process); + + if (p > atomic_read(&rs->io.in_process_max)) + atomic_set(&rs->io.in_process_max, p); /* REMOVEME: max. */ +} + +/* Put the io reference and conditionally wake io waiters. */ +static INLINE void io_put(struct raid_set *rs) +{ + if (atomic_dec_and_test(&rs->io.in_process)) + wake_up(&rs->io.suspendq); +} + +/* Calculate device sector offset. */ +static INLINE sector_t _sector(struct raid_set *rs, struct bio *bio) +{ + sector_t sector = bio->bi_sector; + + sector_div(sector, rs->set.data_devs); + return sector; +} + +/* Test device operational. */ +static INLINE int dev_operational(struct raid_set *rs, unsigned p) +{ + return !test_bit(DEVICE_FAILED, &rs->dev[p].flags); +} + +/* Return # of active stripes in stripe cache. */ +static INLINE int sc_active(struct stripe_cache *sc) +{ + return atomic_read(&sc->active_stripes); +} + +/* Test io pending on stripe. */ +static INLINE int stripe_io(struct stripe *stripe) +{ + return atomic_read(&stripe->io.pending); +} + +static INLINE void stripe_io_inc(struct stripe *stripe) +{ + atomic_inc(&stripe->io.pending); +} + +static INLINE void stripe_io_dec(struct stripe *stripe) +{ + atomic_dec(&stripe->io.pending); +} + +/* Wrapper needed by for_each_io_dev(). */ +static void _stripe_io_inc(struct stripe *stripe, unsigned p) +{ + stripe_io_inc(stripe); +} + +/* Error a stripe. */ +static INLINE void stripe_error(struct stripe *stripe, struct page *page) +{ + SetStripeError(stripe); + SetPageError(page); + atomic_inc(RS(stripe->sc)->stats + S_STRIPE_ERROR); +} + +/* Page IOed ok. */ +enum dirty_type { CLEAN, DIRTY }; +static INLINE void page_set(struct page *page, enum dirty_type type) +{ + switch (type) { + case DIRTY: + SetPageDirty(page); + AllowPageIO(page); + break; + + case CLEAN: + ClearPageDirty(page); + break; + + default: + BUG(); + } + + SetPageUptodate(page); + ClearPageError(page); +} + +/* Return region state for a sector. */ +static INLINE int +region_state(struct raid_set *rs, sector_t sector, unsigned long state) +{ + void *rh = rs->recover.rh; + + if (unlikely(RSRecover(rs))) + return rh_state(rh, rh_sector_to_region(rh, sector), 1) & state; + else + return 0; +} + +/* Check maximum devices which may fail in a raid set. */ +static inline int raid_set_degraded(struct raid_set *rs) +{ + return RSIoError(rs); +} + +/* Check # of devices which may fail in a raid set. */ +static INLINE int raid_set_operational(struct raid_set *rs) +{ + /* Too many failed devices -> BAD. */ + return atomic_read(&rs->set.failed_devs) <= + rs->set.raid_type->parity_devs; +} + +/* + * Return true in case a page_list should be read/written + * + * Conditions to read/write: + * o 1st page in list not uptodate + * o 1st page in list dirty + * o if we optimized io away, we flag it using the pages checked bit. + */ +static INLINE unsigned page_io(struct page *page) +{ + /* Optimization: page was flagged to need io during first run. */ + if (PagePrivate(page)) { + ClearPagePrivate(page); + return 1; + } + + /* Avoid io if prohibited or a locked page. */ + if (!PageIO(page) || PageLocked(page)) + return 0; + + if (!PageUptodate(page) || PageDirty(page)) { + /* Flag page needs io for second run optimization. */ + SetPagePrivate(page); + return 1; + } + + return 0; +} + +/* Call a function on each page list needing io. */ +static INLINE unsigned +for_each_io_dev(struct raid_set *rs, struct stripe *stripe, + void (*f_io)(struct stripe *stripe, unsigned p)) +{ + unsigned p = rs->set.raid_devs, r = 0; + + while (p--) { + if (page_io(PAGE(stripe, p))) { + f_io(stripe, p); + r++; + } + } + + return r; +} + +/* Reconstruct a particular device ?. */ +static INLINE int dev_to_init(struct raid_set *rs) +{ + return rs->set.dev_to_init > -1; +} + +/* Index of device to calculate parity on. */ +static INLINE unsigned dev_for_parity(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + + return dev_to_init(rs) ? rs->set.dev_to_init : stripe->idx.parity; +} + +/* Return the index of the device to be recovered. */ +static int idx_get(struct raid_set *rs) +{ + /* Avoid to read in the pages to be reconstructed anyway. */ + if (dev_to_init(rs)) + return rs->set.dev_to_init; + else if (rs->set.raid_type->level == raid4) + return rs->set.pi; + + return -1; +} + +/* RAID set congested function. */ +static int raid_set_congested(void *congested_data, int bdi_bits) +{ + struct raid_set *rs = congested_data; + int r = 0; /* Assume uncongested. */ + unsigned p = rs->set.raid_devs; + + /* If any of our component devices are overloaded. */ + while (p--) + r |= bdi_congested(&bdev_get_queue(rs->dev[p].dev->bdev)->backing_dev_info, bdi_bits); + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (r ? S_CONGESTED : S_NOT_CONGESTED)); + return r; +} + +/* Display RAID set dead message once. */ +static void raid_set_dead(struct raid_set *rs) +{ + if (!TestSetRSDead(rs)) { + unsigned p; + char buf[BDEVNAME_SIZE]; + + DMERR("FATAL: too many devices failed -> RAID set dead"); + + for (p = 0; p < rs->set.raid_devs; p++) { + if (!dev_operational(rs, p)) + DMERR("device /dev/%s failed", + bdevname(rs->dev[p].dev->bdev, buf)); + } + } +} + +/* RAID set degrade check. */ +static INLINE int +raid_set_check_and_degrade(struct raid_set *rs, + struct stripe *stripe, unsigned p) +{ + if (test_and_set_bit(DEVICE_FAILED, &rs->dev[p].flags)) + return -EPERM; + + /* Through an event in case of member device errors. */ + dm_table_event(rs->ti->table); + atomic_inc(&rs->set.failed_devs); + + /* Only log the first member error. */ + if (!TestSetRSIoError(rs)) { + char buf[BDEVNAME_SIZE]; + + /* Store index for recovery. */ + mb(); + rs->set.ei = p; + mb(); + + DMERR("CRITICAL: %sio error on device /dev/%s " + "in region=%llu; DEGRADING RAID set", + stripe ? "" : "FAKED ", + bdevname(rs->dev[p].dev->bdev, buf), + (unsigned long long) (stripe ? stripe->key : 0)); + DMERR("further device error messages suppressed"); + } + + return 0; +} + +static void +raid_set_check_degrade(struct raid_set *rs, struct stripe *stripe) +{ + unsigned p = rs->set.raid_devs; + + while (p--) { + struct page *page = PAGE(stripe, p); + + if (PageError(page)) { + ClearPageError(page); + raid_set_check_and_degrade(rs, stripe, p); + } + } +} + +/* RAID set upgrade check. */ +static int raid_set_check_and_upgrade(struct raid_set *rs, unsigned p) +{ + if (!test_and_clear_bit(DEVICE_FAILED, &rs->dev[p].flags)) + return -EPERM; + + if (atomic_dec_and_test(&rs->set.failed_devs)) { + ClearRSIoError(rs); + rs->set.ei = -1; + } + + return 0; +} + +/* Lookup a RAID device by name or by major:minor number. */ +union dev_lookup { + const char *dev_name; + struct raid_dev *dev; +}; +enum lookup_type { byname, bymajmin, bynumber }; +static int raid_dev_lookup(struct raid_set *rs, enum lookup_type by, + union dev_lookup *dl) +{ + unsigned p; + + /* + * Must be an incremental loop, because the device array + * can have empty slots still on calls from raid_ctr() + */ + for (p = 0; p < rs->set.raid_devs; p++) { + char buf[BDEVNAME_SIZE]; + struct raid_dev *dev = rs->dev + p; + + if (!dev->dev) + break; + + /* Format dev string appropriately if necessary. */ + if (by == byname) + bdevname(dev->dev->bdev, buf); + else if (by == bymajmin) + format_dev_t(buf, dev->dev->bdev->bd_dev); + + /* Do the actual check. */ + if (by == bynumber) { + if (dl->dev->dev->bdev->bd_dev == + dev->dev->bdev->bd_dev) + return p; + } else if (!strcmp(dl->dev_name, buf)) + return p; + } + + return -ENODEV; +} + +/* End io wrapper. */ +static INLINE void +_bio_endio(struct raid_set *rs, struct bio *bio, int error) +{ + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (bio_data_dir(bio) == WRITE ? + S_BIOS_ENDIO_WRITE : S_BIOS_ENDIO_READ)); + bio_endio(bio, error); + io_put(rs); /* Wake any suspend waiters. */ +} + +/* + * End small helper functions. + */ + + +/* + * Stripe hash functions + */ +/* Initialize/destroy stripe hash. */ +static int hash_init(struct stripe_hash *hash, unsigned stripes) +{ + unsigned buckets = 1, max_buckets = stripes / 4; + unsigned hash_primes[] = { + /* Table of primes for hash_fn/table size optimization. */ + 3, 7, 13, 27, 53, 97, 193, 389, 769, + 1543, 3079, 6151, 12289, 24593, + }; + + /* Calculate number of buckets (2^^n <= stripes / 4). */ + while ((buckets <<= 1) < max_buckets); + + /* Allocate stripe hash. */ + hash->hash = vmalloc(buckets * sizeof(*hash->hash)); + if (!hash->hash) + return -ENOMEM; + + hash->buckets = buckets; + hash->mask = buckets - 1; + hash->shift = ffs(buckets); + if (hash->shift > ARRAY_SIZE(hash_primes) + 1) + hash->shift = ARRAY_SIZE(hash_primes) + 1; + + BUG_ON(hash->shift - 2 > ARRAY_SIZE(hash_primes) + 1); + hash->prime = hash_primes[hash->shift - 2]; + + /* Initialize buckets. */ + while (buckets--) + INIT_LIST_HEAD(hash->hash + buckets); + + return 0; +} + +static INLINE void hash_exit(struct stripe_hash *hash) +{ + if (hash->hash) { + vfree(hash->hash); + hash->hash = NULL; + } +} + +/* List add (head/tail/locked/unlocked) inlines. */ +enum list_lock_type { LIST_LOCKED, LIST_UNLOCKED }; +#define LIST_DEL(name, list) \ +static void stripe_ ## name ## _del(struct stripe *stripe, \ + enum list_lock_type lock) { \ + struct list_head *lh = stripe->lists + (list); \ + spinlock_t *l = NULL; \ +\ + if (lock == LIST_LOCKED) { \ + l = stripe->sc->locks + LOCK_LRU; \ + spin_lock_irq(l); \ + } \ +\ +\ + if (!list_empty(lh)) \ + list_del_init(lh); \ +\ + if (lock == LIST_LOCKED) \ + spin_unlock_irq(l); \ +} + +LIST_DEL(hash, LIST_HASH) +LIST_DEL(lru, LIST_LRU) +#undef LIST_DEL + +enum list_pos_type { POS_HEAD, POS_TAIL }; +#define LIST_ADD(name, list) \ +static void stripe_ ## name ## _add(struct stripe *stripe, \ + enum list_pos_type pos, \ + enum list_lock_type lock) { \ + struct list_head *lh = stripe->lists + (list); \ + struct stripe_cache *sc = stripe->sc; \ + spinlock_t *l = NULL; \ +\ + if (lock == LIST_LOCKED) { \ + l = sc->locks + LOCK_LRU; \ + spin_lock_irq(l); \ + } \ +\ + if (list_empty(lh)) { \ + if (pos == POS_HEAD) \ + list_add(lh, sc->lists + (list)); \ + else \ + list_add_tail(lh, sc->lists + (list)); \ + } \ +\ + if (lock == LIST_LOCKED) \ + spin_unlock_irq(l); \ +} + +LIST_ADD(endio, LIST_ENDIO) +LIST_ADD(io, LIST_IO) +LIST_ADD(lru, LIST_LRU) +#undef LIST_ADD + +#define POP(list) \ + if (list_empty(sc->lists + list)) \ + stripe = NULL; \ + else { \ + stripe = list_entry(sc->lists[list].next, struct stripe, \ + lists[list]); \ + list_del_init(&stripe->lists[list]); \ + } + +/* Pop an available stripe off the lru list. */ +static struct stripe *stripe_lru_pop(struct stripe_cache *sc) +{ + struct stripe *stripe; + spinlock_t *lock = sc->locks + LOCK_LRU; + + spin_lock_irq(lock); + POP(LIST_LRU); + spin_unlock_irq(lock); + + if (stripe) + /* Remove from hash before reuse. */ + stripe_hash_del(stripe, LIST_UNLOCKED); + + return stripe; +} + +static inline unsigned hash_fn(struct stripe_hash *hash, sector_t key) +{ + return (unsigned) (((key * hash->prime) >> hash->shift) & hash->mask); +} + +static inline struct list_head * +hash_bucket(struct stripe_hash *hash, sector_t key) +{ + return hash->hash + hash_fn(hash, key); +} + +/* Insert an entry into a hash. */ +static inline void hash_insert(struct stripe_hash *hash, struct stripe *stripe) +{ + list_add(stripe->lists + LIST_HASH, hash_bucket(hash, stripe->key)); +} + +/* Insert an entry into the stripe hash. */ +static inline void +sc_insert(struct stripe_cache *sc, struct stripe *stripe) +{ + hash_insert(&sc->hash, stripe); +} + +/* Lookup an entry in the stripe hash. */ +static inline struct stripe * +stripe_lookup(struct stripe_cache *sc, sector_t key) +{ + unsigned c = 0; + struct stripe *stripe; + struct list_head *bucket = hash_bucket(&sc->hash, key); + + list_for_each_entry(stripe, bucket, lists[LIST_HASH]) { + /* REMOVEME: statisics. */ + if (++c > atomic_read(RS(sc)->stats + S_MAX_LOOKUP)) + atomic_set(RS(sc)->stats + S_MAX_LOOKUP, c); + + if (stripe->key == key) + return stripe; + } + + return NULL; +} + +/* Resize the stripe cache hash on size changes. */ +static int hash_resize(struct stripe_cache *sc) +{ + /* Resize threshold reached? */ + if (atomic_read(&sc->stripes) > 2 * atomic_read(&sc->stripes_last) + || atomic_read(&sc->stripes) < atomic_read(&sc->stripes_last) / 4) { + int r; + struct stripe_hash hash, hash_tmp; + spinlock_t *lock; + + r = hash_init(&hash, atomic_read(&sc->stripes)); + if (r) + return r; + + lock = sc->locks + LOCK_LRU; + spin_lock_irq(lock); + if (sc->hash.hash) { + unsigned b = sc->hash.buckets; + struct list_head *pos, *tmp; + + /* Walk old buckets and insert into new. */ + while (b--) { + list_for_each_safe(pos, tmp, sc->hash.hash + b) + hash_insert(&hash, + list_entry(pos, struct stripe, + lists[LIST_HASH])); + } + + } + + memcpy(&hash_tmp, &sc->hash, sizeof(hash_tmp)); + memcpy(&sc->hash, &hash, sizeof(sc->hash)); + atomic_set(&sc->stripes_last, atomic_read(&sc->stripes)); + spin_unlock_irq(lock); + + hash_exit(&hash_tmp); + } + + return 0; +} + +/* + * Stripe cache locking functions + */ +/* Dummy lock function for local RAID4+5. */ +static void *no_lock(sector_t key, enum lock_type type) +{ + return &no_lock; +} + +/* Dummy unlock function for local RAID4+5. */ +static void no_unlock(void *lock_handle) +{ +} + +/* No locking (for local RAID 4+5). */ +static struct dmraid45_locking_type locking_none = { + .lock = no_lock, + .unlock = no_unlock, +}; + +/* Clustered RAID 4+5. */ +/* FIXME: code this. */ +static struct dmraid45_locking_type locking_cluster = { + .lock = no_lock, + .unlock = no_unlock, +}; + +/* Lock a stripe (for clustering). */ +static int +stripe_lock(struct raid_set *rs, struct stripe *stripe, int rw, sector_t key) +{ + stripe->lock = rs->locking->lock(key, rw == READ ? RAID45_SHARED : + RAID45_EX); + return stripe->lock ? 0 : -EPERM; +} + +/* Unlock a stripe (for clustering). */ +static void stripe_unlock(struct raid_set *rs, struct stripe *stripe) +{ + rs->locking->unlock(stripe->lock); + stripe->lock = NULL; +} + +/* + * Stripe cache functions. + */ +/* + * Invalidate all page lists pages of a stripe. + * + * I only keep state for the whole list in the first page. + */ +static INLINE void +stripe_pages_invalidate(struct stripe *stripe) +{ + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) { + struct page *page = PAGE(stripe, p); + + ProhibitPageIO(page); + ClearPageChecked(page); + ClearPageDirty(page); + ClearPageError(page); + clear_page_locked(page); + ClearPagePrivate(page); + ClearPageUptodate(page); + } +} + +/* Prepare stripe for (re)use. */ +static INLINE void stripe_invalidate(struct stripe *stripe) +{ + stripe->io.flags = 0; + stripe_pages_invalidate(stripe); +} + +/* Allow io on all chunks of a stripe. */ +static INLINE void stripe_allow_io(struct stripe *stripe) +{ + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) + AllowPageIO(PAGE(stripe, p)); +} + +/* Initialize a stripe. */ +static void +stripe_init(struct stripe_cache *sc, struct stripe *stripe, unsigned io_size) +{ + unsigned p = RS(sc)->set.raid_devs; + unsigned i; + + /* Work all io chunks. */ + while (p--) { + struct stripe_set *ss = stripe->ss + p; + + stripe->obj[p].private = ss; + ss->stripe = stripe; + + i = ARRAY_SIZE(ss->bl); + while (i--) + bio_list_init(ss->bl + i); + } + + stripe->sc = sc; + + i = ARRAY_SIZE(stripe->lists); + while (i--) + INIT_LIST_HEAD(&stripe->lists[i]); + + stripe->io.size = io_size; + atomic_set(&stripe->cnt, 0); + atomic_set(&stripe->io.pending, 0); + + stripe_invalidate(stripe); +} + +/* Number of pages per chunk. */ +static inline unsigned chunk_pages(unsigned io_size) +{ + return dm_div_up(io_size, SECTORS_PER_PAGE); +} + +/* Number of pages per stripe. */ +static inline unsigned stripe_pages(struct raid_set *rs, unsigned io_size) +{ + return chunk_pages(io_size) * rs->set.raid_devs; +} + +/* Initialize part of page_list (recovery). */ +static INLINE void stripe_zero_pl_part(struct stripe *stripe, unsigned p, + unsigned start, unsigned count) +{ + unsigned pages = chunk_pages(count); + /* Get offset into the page_list. */ + struct page_list *pl = pl_elem(PL(stripe, p), start / SECTORS_PER_PAGE); + + BUG_ON(!pl); + while (pl && pages--) { + BUG_ON(!pl->page); + memset(page_address(pl->page), 0, PAGE_SIZE); + pl = pl->next; + } +} + +/* Initialize parity chunk of stripe. */ +static INLINE void stripe_zero_chunk(struct stripe *stripe, unsigned p) +{ + stripe_zero_pl_part(stripe, p, 0, stripe->io.size); +} + +/* Return dynamic stripe structure size. */ +static INLINE size_t stripe_size(struct raid_set *rs) +{ + return sizeof(struct stripe) + + rs->set.raid_devs * sizeof(struct stripe_set); +} + +/* Allocate a stripe and its memory object. */ +enum grow { grow, keep }; +static struct stripe *stripe_alloc(struct stripe_cache *sc, + unsigned io_size, enum grow grow) +{ + int r; + unsigned pages_per_chunk = chunk_pages(io_size); + struct stripe *stripe; + + stripe = kmem_cache_alloc(sc->kc.cache, GFP_KERNEL); + if (stripe) { + memset(stripe, 0, stripe_size(RS(sc))); + + /* Grow the dm-mem-cache on request. */ + if (grow == grow) { + r = dm_mem_cache_grow(sc->dm_mem_cache_client, + pages_per_chunk); + if (r) + goto err_free; + } + + stripe->obj = dm_mem_cache_alloc(sc->dm_mem_cache_client, + pages_per_chunk); + if (!stripe->obj) + goto err_shrink; + + stripe_init(sc, stripe, io_size); + } + + return stripe; + + err_shrink: + if (grow == grow) + dm_mem_cache_shrink(sc->dm_mem_cache_client, pages_per_chunk); + err_free: + kmem_cache_free(sc->kc.cache, stripe); + return NULL; +} + +/* + * Free a stripes memory object, shrink the + * memory cache and free the stripe itself + */ +static void stripe_free(struct stripe *stripe) +{ + dm_mem_cache_free(stripe->sc->dm_mem_cache_client, stripe->obj); + dm_mem_cache_shrink(stripe->sc->dm_mem_cache_client, + chunk_pages(stripe->io.size)); + kmem_cache_free(stripe->sc->kc.cache, stripe); +} + +/* Free the recovery stripe. */ +static void stripe_recover_free(struct raid_set *rs) +{ + if (rs->recover.stripe) { + ClearRSRecover(rs); + stripe_free(rs->recover.stripe); + rs->recover.stripe = NULL; + } +} + +/* Push a stripe safely onto the endio list to be handled by do_endios(). */ +static INLINE void stripe_endio_push(struct stripe *stripe) +{ + int wake; + unsigned long flags; + struct stripe_cache *sc = stripe->sc; + spinlock_t *lock = sc->locks + LOCK_ENDIO; + + spin_lock_irqsave(lock, flags); + wake = list_empty(sc->lists + LIST_ENDIO); + stripe_endio_add(stripe, POS_HEAD, LIST_UNLOCKED); + spin_unlock_irqrestore(lock, flags); + + if (wake) + wake_do_raid(RS(sc)); +} + +/* Protected check for stripe cache endio list empty. */ +static INLINE int stripe_endio_empty(struct stripe_cache *sc) +{ + int r; + spinlock_t *lock = sc->locks + LOCK_ENDIO; + + spin_lock_irq(lock); + r = list_empty(sc->lists + LIST_ENDIO); + spin_unlock_irq(lock); + + return r; +} + +/* Pop a stripe off safely off the endio list. */ +static struct stripe *stripe_endio_pop(struct stripe_cache *sc) +{ + struct stripe *stripe; + spinlock_t *lock = sc->locks + LOCK_ENDIO; + + /* This runs in parallel with endio(). */ + spin_lock_irq(lock); + POP(LIST_ENDIO) + spin_unlock_irq(lock); + return stripe; +} + +#undef POP + +/* Evict stripe from cache. */ +static void stripe_evict(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + stripe_hash_del(stripe, LIST_UNLOCKED); /* Take off hash. */ + + if (list_empty(stripe->lists + LIST_LRU)) { + stripe_lru_add(stripe, POS_TAIL, LIST_LOCKED); + atomic_inc(rs->stats + S_EVICT); /* REMOVEME: statistics. */ + } +} + +/* Grow stripe cache. */ +static int +sc_grow(struct stripe_cache *sc, unsigned stripes, enum grow grow) +{ + int r = 0; + struct raid_set *rs = RS(sc); + + /* Try to allocate this many (additional) stripes. */ + while (stripes--) { + struct stripe *stripe = stripe_alloc(sc, rs->set.io_size, grow); + + if (likely(stripe)) { + stripe_lru_add(stripe, POS_TAIL, LIST_LOCKED); + atomic_inc(&sc->stripes); + } else { + r = -ENOMEM; + break; + } + } + + ClearRSScBusy(rs); + return r ? r : hash_resize(sc); +} + +/* Shrink stripe cache. */ +static int sc_shrink(struct stripe_cache *sc, unsigned stripes) +{ + int r = 0; + + /* Try to get unused stripe from LRU list. */ + while (stripes--) { + struct stripe *stripe; + + stripe = stripe_lru_pop(sc); + if (stripe) { + /* An lru stripe may never have ios pending!. */ + BUG_ON(stripe_io(stripe)); + stripe_free(stripe); + atomic_dec(&sc->stripes); + } else { + r = -ENOENT; + break; + } + } + + /* Check if stats are still sane. */ + if (atomic_read(&sc->max_active_stripes) > + atomic_read(&sc->stripes)) + atomic_set(&sc->max_active_stripes, 0); + + if (r) + return r; + + ClearRSScBusy(RS(sc)); + return hash_resize(sc); +} + +/* Create stripe cache. */ +static int sc_init(struct raid_set *rs, unsigned stripes) +{ + unsigned i, nr; + struct stripe_cache *sc = &rs->sc; + struct stripe *stripe; + + /* Initialize lists and locks. */ + i = ARRAY_SIZE(sc->lists); + while (i--) + INIT_LIST_HEAD(sc->lists + i); + + i = NR_LOCKS; + while (i--) + spin_lock_init(sc->locks + i); + + /* Initialize atomic variables. */ + atomic_set(&sc->stripes, 0); + atomic_set(&sc->stripes_last, 0); + atomic_set(&sc->stripes_to_shrink, 0); + atomic_set(&sc->active_stripes, 0); + atomic_set(&sc->max_active_stripes, 0); /* REMOVEME: */ + + /* + * We need a runtime unique # to suffix the kmem cache name + * because we'll have one for each active RAID set. + */ + nr = atomic_inc_return(&_stripe_sc_nr); + sprintf(sc->kc.name, "%s_%d", TARGET, nr); + sc->kc.cache = kmem_cache_create(sc->kc.name, stripe_size(rs), + 0, 0, NULL); + if (!sc->kc.cache) + return -ENOMEM; + + /* Create memory cache client context and Allocate memory objects. */ + sc->dm_mem_cache_client = dm_mem_cache_client_create( + stripes * stripe_pages(rs, rs->set.io_size) + + 2 * stripe_pages(rs, rs->recover.io_size), + stripes + 2, rs->set.raid_devs); + if (IS_ERR(sc->dm_mem_cache_client)) + return PTR_ERR(sc->dm_mem_cache_client); + + /* Allocate stripe for set recovery. */ + stripe = stripe_alloc(sc, rs->recover.io_size, keep); + if (!stripe) + return -ENOMEM; + + SetStripeRecover(stripe); + rs->recover.stripe = stripe; + return sc_grow(sc, stripes, keep); /* Grow the cache. */ +} + +/* Destroy the stripe cache. */ +static void sc_exit(struct stripe_cache *sc) +{ + if (sc->hash.hash) { + if (sc->kc.cache) { + BUG_ON(sc_shrink(sc, atomic_read(&sc->stripes))); + kmem_cache_destroy(sc->kc.cache); + } + + if (sc->dm_mem_cache_client) + dm_mem_cache_client_destroy(sc->dm_mem_cache_client); + + hash_exit(&sc->hash); + } +} + +/* + * Calculate RAID address + * + * Delivers tuple with the index of the data disk holding the chunk + * in the set, the parity disks index and the start of the stripe + * within the address space of the set (used as the stripe cache hash key). + */ +/* thx MD. */ +static struct address * +raid_address(struct raid_set *rs, sector_t sector, struct address *addr) +{ + unsigned data_devs = rs->set.data_devs, di, pi, + raid_devs = rs->set.raid_devs; + sector_t stripe, tmp; + + /* + * chunk_number = sector / chunk_size + * stripe = chunk_number / data_devs + * di = stripe % data_devs; + */ + stripe = sector >> rs->set.chunk_shift; + di = sector_div(stripe, data_devs); + + switch (rs->set.raid_type->level) { + case raid5: + tmp = stripe; + pi = sector_div(tmp, raid_devs); + + switch (rs->set.raid_type->algorithm) { + case left_asym: /* Left asymmetric. */ + pi = data_devs - pi; + case right_asym: /* Right asymmetric. */ + if (di >= pi) + di++; + break; + + case left_sym: /* Left symmetric. */ + pi = data_devs - pi; + case right_sym: /* Right symmetric. */ + di = (pi + di + 1) % raid_devs; + break; + + default: + DMERR("Unknown RAID algorithm %d", + rs->set.raid_type->algorithm); + goto out; + } + + break; + + case raid4: + pi = rs->set.pi; + if (di >= pi) + di++; + break; + + default: + DMERR("Unknown RAID level %d", rs->set.raid_type->level); + goto out; + } + + /* + * Hash key = start offset on any single device of the RAID set; + * adjusted in case io size differs from chunk size. + */ + addr->key = (stripe << rs->set.chunk_shift) + + (sector & rs->set.io_shift_mask); + addr->di = di; + addr->pi = pi; + + out: + return addr; +} + +/* + * Copy data across between stripe pages and bio vectors. + * + * Pay attention to data alignment in stripe and bio pages. + */ +static void +bio_copy_page_list(int rw, struct stripe *stripe, + struct page_list *pl, struct bio *bio) +{ + unsigned i, page_offset; + void *page_addr; + struct raid_set *rs = RS(stripe->sc); + struct bio_vec *bv; + + /* Get start page in page list for this sector. */ + i = (bio->bi_sector & rs->set.io_mask) / SECTORS_PER_PAGE; + pl = pl_elem(pl, i); + + page_addr = page_address(pl->page); + page_offset = to_bytes(bio->bi_sector & (SECTORS_PER_PAGE - 1)); + + /* Walk all segments and copy data across between bio_vecs and pages. */ + bio_for_each_segment(bv, bio, i) { + int len = bv->bv_len, size; + unsigned bio_offset = 0; + void *bio_addr = __bio_kmap_atomic(bio, i, KM_USER0); + redo: + size = (page_offset + len > PAGE_SIZE) ? + PAGE_SIZE - page_offset : len; + + if (rw == READ) + memcpy(bio_addr + bio_offset, + page_addr + page_offset, size); + else + memcpy(page_addr + page_offset, + bio_addr + bio_offset, size); + + page_offset += size; + if (page_offset == PAGE_SIZE) { + /* + * We reached the end of the chunk page -> + * need refer to the next one to copy more data. + */ + len -= size; + if (len) { + /* Get next page. */ + pl = pl->next; + BUG_ON(!pl); + page_addr = page_address(pl->page); + page_offset = 0; + bio_offset += size; + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_BIO_COPY_PL_NEXT); + goto redo; + } + } + + __bio_kunmap_atomic(bio_addr, KM_USER0); + } +} + +/* + * Xor optimization macros. + */ +/* Xor data pointer declaration and initialization macros. */ +#define DECLARE_2 xor_t *d0 = data[0], *d1 = data[1] +#define DECLARE_3 DECLARE_2, *d2 = data[2] +#define DECLARE_4 DECLARE_3, *d3 = data[3] +#define DECLARE_5 DECLARE_4, *d4 = data[4] +#define DECLARE_6 DECLARE_5, *d5 = data[5] +#define DECLARE_7 DECLARE_6, *d6 = data[6] +#define DECLARE_8 DECLARE_7, *d7 = data[7] + +/* Xor unrole macros. */ +#define D2(n) d0[n] = d0[n] ^ d1[n] +#define D3(n) D2(n) ^ d2[n] +#define D4(n) D3(n) ^ d3[n] +#define D5(n) D4(n) ^ d4[n] +#define D6(n) D5(n) ^ d5[n] +#define D7(n) D6(n) ^ d6[n] +#define D8(n) D7(n) ^ d7[n] + +#define X_2(macro, offset) macro(offset); macro(offset + 1); +#define X_4(macro, offset) X_2(macro, offset); X_2(macro, offset + 2); +#define X_8(macro, offset) X_4(macro, offset); X_4(macro, offset + 4); +#define X_16(macro, offset) X_8(macro, offset); X_8(macro, offset + 8); +#define X_32(macro, offset) X_16(macro, offset); X_16(macro, offset + 16); +#define X_64(macro, offset) X_32(macro, offset); X_32(macro, offset + 32); + +/* Define a _xor_#chunks_#xors_per_run() function. */ +#define _XOR(chunks, xors_per_run) \ +static void _xor ## chunks ## _ ## xors_per_run(xor_t **data) \ +{ \ + unsigned end = XOR_SIZE / sizeof(data[0]), i; \ + DECLARE_ ## chunks; \ +\ + for (i = 0; i < end; i += xors_per_run) { \ + X_ ## xors_per_run(D ## chunks, i); \ + } \ +} + +/* Define xor functions for 2 - 8 chunks. */ +#define MAKE_XOR_PER_RUN(xors_per_run) \ + _XOR(2, xors_per_run); _XOR(3, xors_per_run); \ + _XOR(4, xors_per_run); _XOR(5, xors_per_run); \ + _XOR(6, xors_per_run); _XOR(7, xors_per_run); \ + _XOR(8, xors_per_run); + +MAKE_XOR_PER_RUN(8) /* Define _xor_*_8() functions. */ +MAKE_XOR_PER_RUN(16) /* Define _xor_*_16() functions. */ +MAKE_XOR_PER_RUN(32) /* Define _xor_*_32() functions. */ +MAKE_XOR_PER_RUN(64) /* Define _xor_*_64() functions. */ + +#define MAKE_XOR(xors_per_run) \ +struct { \ + void (*f)(xor_t**); \ +} static xor_funcs ## xors_per_run[] = { \ + { NULL }, \ + { NULL }, \ + { _xor2_ ## xors_per_run }, \ + { _xor3_ ## xors_per_run }, \ + { _xor4_ ## xors_per_run }, \ + { _xor5_ ## xors_per_run }, \ + { _xor6_ ## xors_per_run }, \ + { _xor7_ ## xors_per_run }, \ + { _xor8_ ## xors_per_run }, \ +}; \ +\ +static void xor_ ## xors_per_run(unsigned n, xor_t **data) \ +{ \ + /* Call respective function for amount of chunks. */ \ + xor_funcs ## xors_per_run[n].f(data); \ +} + +/* Define xor_8() - xor_64 functions. */ +MAKE_XOR(8) +MAKE_XOR(16) +MAKE_XOR(32) +MAKE_XOR(64) + +/* Maximum number of chunks, which can be xor'ed in one go. */ +#define XOR_CHUNKS_MAX (ARRAY_SIZE(xor_funcs8) - 1) + +struct xor_func { + xor_function_t f; + const char *name; +} static xor_funcs[] = { + {xor_8, "xor_8"}, + {xor_16, "xor_16"}, + {xor_32, "xor_32"}, + {xor_64, "xor_64"}, +}; + +/* + * Calculate crc. + * + * This indexes into the page list of the stripe. + * + * All chunks will be xored into the parity chunk + * in maximum groups of xor.chunks. + * + * FIXME: try mapping the pages on discontiguous memory. + */ +static void xor(struct stripe *stripe, unsigned pi, unsigned sector) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned max_chunks = rs->xor.chunks, n, p; + unsigned o = sector / SECTORS_PER_PAGE; /* Offset into the page_list. */ + xor_t **d = rs->data; + xor_function_t xor_f = rs->xor.f->f; + + /* Address of parity page to xor into. */ + d[0] = page_address(pl_elem(PL(stripe, pi), o)->page); + + /* Preset pointers to data pages. */ + for (n = 1, p = rs->set.raid_devs; p--; ) { + if (p != pi && PageIO(PAGE(stripe, p))) + d[n++] = page_address(pl_elem(PL(stripe, p), o)->page); + + /* If max chunks -> xor .*/ + if (n == max_chunks) { + xor_f(n, d); + n = 1; + } + } + + /* If chunks -> xor. */ + if (n > 1) + xor_f(n, d); + + /* Set parity page uptodate and clean. */ + page_set(PAGE(stripe, pi), CLEAN); +} + +/* Common xor loop through all stripe page lists. */ +static void common_xor(struct stripe *stripe, sector_t count, + unsigned off, unsigned p) +{ + unsigned sector; + + for (sector = off; sector < count; sector += SECTORS_PER_XOR) + xor(stripe, p, sector); + + atomic_inc(RS(stripe->sc)->stats + S_XORS); /* REMOVEME: statistics. */ +} + +/* + * Calculate parity sectors on intact stripes. + * + * Need to calculate raid address for recover stripe, because its + * chunk sizes differs and is typically larger than io chunk size. + */ +static void parity_xor(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned chunk_size = rs->set.chunk_size, + io_size = stripe->io.size, + xor_size = chunk_size > io_size ? io_size : chunk_size; + sector_t off; + + + /* This can be the recover stripe with a larger io size. */ + for (off = 0; off < io_size; off += xor_size) { + unsigned pi; + + /* + * Recover stripe likely is bigger than regular io + * ones and has no precalculated parity disk index -> + * need to calculate RAID address. + */ + if (unlikely(StripeRecover(stripe))) { + struct address addr; + + raid_address(rs, + (stripe->key + off) * rs->set.data_devs, + &addr); + pi = addr.pi; + stripe_zero_pl_part(stripe, pi, off, + rs->set.chunk_size); + } else + pi = stripe->idx.parity; + + common_xor(stripe, xor_size, off, pi); + page_set(PAGE(stripe, pi), DIRTY); + } +} + +/* Reconstruct missing chunk. */ +static void reconstruct_xor(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + int p = stripe->idx.recover; + + BUG_ON(p < 0); + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (raid_set_degraded(rs) ? + S_RECONSTRUCT_EI : S_RECONSTRUCT_DEV)); + + /* Zero chunk to be reconstructed. */ + stripe_zero_chunk(stripe, p); + common_xor(stripe, stripe->io.size, 0, p); +} + +/* + * Try getting a stripe either from the hash or from the lru list + */ +static inline void _stripe_get(struct stripe *stripe) +{ + atomic_inc(&stripe->cnt); +} + +static struct stripe *stripe_get(struct raid_set *rs, struct address *addr) +{ + struct stripe_cache *sc = &rs->sc; + struct stripe *stripe; + + + stripe = stripe_lookup(sc, addr->key); + if (stripe) { + _stripe_get(stripe); + /* Remove from the lru list if on. */ + stripe_lru_del(stripe, LIST_LOCKED); + atomic_inc(rs->stats + S_HITS_1ST); /* REMOVEME: statistics. */ + } else { + /* Second try to get an LRU stripe. */ + stripe = stripe_lru_pop(sc); + if (stripe) { + _stripe_get(stripe); + /* Invalidate before reinserting with changed key. */ + stripe_invalidate(stripe); + stripe->key = addr->key; + stripe->region = rh_sector_to_region(rs->recover.rh, + addr->key); + stripe->idx.parity = addr->pi; + sc_insert(sc, stripe); + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_INSCACHE); + } + } + + return stripe; +} + +/* + * Decrement reference count on a stripe. + * + * Move it to list of LRU stripes if zero. + */ +static void stripe_put(struct stripe *stripe) +{ + if (atomic_dec_and_test(&stripe->cnt)) { + if (TestClearStripeActive(stripe)) + atomic_dec(&stripe->sc->active_stripes); + + /* Put stripe onto the LRU list. */ + stripe_lru_add(stripe, POS_TAIL, LIST_LOCKED); + } + + BUG_ON(atomic_read(&stripe->cnt) < 0); +} + +/* + * Process end io + * + * I need to do it here because I can't in interrupt + * + * Read and write functions are split in order to avoid + * conditionals in the main loop for performamce reasons. + */ +typedef void(*endio_helper_function)(struct stripe *, struct page_list *, + struct bio *); + +/* Helper read bios on a page list. */ +static void _bio_copy_page_list(struct stripe *stripe, struct page_list *pl, + struct bio *bio) +{ + bio_copy_page_list(READ, stripe, pl, bio); +} + +/* Helper write bios on a page list. */ +static void _rh_dec(struct stripe *stripe, struct page_list *pl, + struct bio *bio) +{ + rh_dec(RS(stripe->sc)->recover.rh, stripe->region); +} + +/* End io all bios on a page list. */ +static inline int +page_list_endio(int rw, struct stripe *stripe, unsigned p, unsigned *count) +{ + int r = 0; + struct bio_list *bl = BL(stripe, p, rw); + + if (!bio_list_empty(bl)) { + struct page_list *pl = PL(stripe, p); + struct page *page = pl->page; + + if (PageLocked(page)) + r = -EBUSY; + else if (PageUptodate(page)) { + struct bio *bio; + struct raid_set *rs = RS(stripe->sc); + endio_helper_function h_f = + rw == READ ? _bio_copy_page_list : _rh_dec; + + while ((bio = bio_list_pop(bl))) { + h_f(stripe, pl, bio); + _bio_endio(rs, bio, 0); + stripe_put(stripe); + if (count) + (*count)++; + } + } else + r = -EAGAIN; + } + + return r; +} + +/* + * End io all reads/writes on a stripe copying + * read date accross from stripe to bios. + */ +static int stripe_end_io(int rw, struct stripe *stripe, unsigned *count) +{ + int r = 0; + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) { + int rr = page_list_endio(rw, stripe, p, count); + + if (rr && r != -EIO) + r = rr; + } + + return r; +} + +/* Fail all ios on a bio list and return # of bios. */ +static unsigned +bio_list_fail(struct raid_set *rs, struct stripe *stripe, struct bio_list *bl) +{ + unsigned r; + struct bio *bio; + + raid_set_dead(rs); + + /* Update region counters. */ + if (stripe) { + void *rh = rs->recover.rh; + + bio_list_for_each(bio, bl) { + if (bio_data_dir(bio) == WRITE) + rh_dec(rh, stripe->region); + } + } + + /* Error end io all bios. */ + for (r = 0; (bio = bio_list_pop(bl)); r++) + _bio_endio(rs, bio, -EIO); + + return r; +} + +/* Fail all ios of a bio list of a stripe and drop io pending count. */ +static void +stripe_bio_list_fail(struct raid_set *rs, struct stripe *stripe, + struct bio_list *bl) +{ + unsigned put = bio_list_fail(rs, stripe, bl); + + while (put--) + stripe_put(stripe); +} + +/* Fail all ios hanging off all bio lists of a stripe. */ +static void stripe_fail_io(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned p = rs->set.raid_devs; + + stripe_evict(stripe); + + while (p--) { + struct stripe_set *ss = stripe->ss + p; + int i = ARRAY_SIZE(ss->bl); + + while (i--) + stripe_bio_list_fail(rs, stripe, ss->bl + i); + } +} + +/* + * Handle all stripes by handing them to the daemon, because we can't + * map their pages to copy the data in interrupt context. + * + * We don't want to handle them here either, while interrupts are disabled. + */ + +/* Read/write endio function for dm-io (interrupt context). */ +static void endio(unsigned long error, void *context) +{ + struct dm_mem_cache_object *obj = context; + struct stripe_set *ss = obj->private; + struct stripe *stripe = ss->stripe; + struct page *page = obj->pl->page; + + if (unlikely(error)) + stripe_error(stripe, page); + else + page_set(page, CLEAN); + + clear_page_locked(page); + stripe_io_dec(stripe); + + /* Add stripe to endio list and wake daemon. */ + stripe_endio_push(stripe); +} + +/* + * Recovery io throttling + */ +/* Conditionally reset io counters. */ +enum count_type { IO_WORK = 0, IO_RECOVER }; +static int recover_io_reset(struct raid_set *rs) +{ + unsigned long j = jiffies; + + /* Pay attention to jiffies overflows. */ + if (j > rs->recover.last_jiffies + HZ + || j < rs->recover.last_jiffies) { + rs->recover.last_jiffies = j; + atomic_set(rs->recover.io_count + IO_WORK, 0); + atomic_set(rs->recover.io_count + IO_RECOVER, 0); + return 1; + } + + return 0; +} + +/* Count ios. */ +static INLINE void +recover_io_count(struct raid_set *rs, struct stripe *stripe) +{ + if (RSRecover(rs)) { + recover_io_reset(rs); + atomic_inc(rs->recover.io_count + + (stripe == rs->recover.stripe ? + IO_RECOVER : IO_WORK)); + } +} + +/* Read/Write a page_list asynchronously. */ +static void page_list_rw(struct stripe *stripe, unsigned p) +{ + struct stripe_cache *sc = stripe->sc; + struct raid_set *rs = RS(sc); + struct dm_mem_cache_object *obj = stripe->obj + p; + struct page_list *pl = obj->pl; + struct page *page = pl->page; + struct raid_dev *dev = rs->dev + p; + struct dm_io_region io = { + .bdev = dev->dev->bdev, + .sector = stripe->key, + .count = stripe->io.size, + }; + struct dm_io_request control = { + .bi_rw = PageDirty(page) ? WRITE : READ, + .mem.type = DM_IO_PAGE_LIST, + .mem.ptr.pl = pl, + .mem.offset = 0, + .notify.fn = endio, + .notify.context = obj, + .client = sc->dm_io_client, + }; + + BUG_ON(PageLocked(page)); + + /* + * Don't rw past end of device, which can happen, because + * typically sectors_per_dev isn't divisable by io_size. + */ + if (unlikely(io.sector + io.count > rs->set.sectors_per_dev)) + io.count = rs->set.sectors_per_dev - io.sector; + + io.sector += dev->start; /* Add . */ + recover_io_count(rs, stripe); /* Recovery io accounting. */ + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (PageDirty(page) ? S_DM_IO_WRITE: S_DM_IO_READ)); + + ClearPageError(page); + set_page_locked(page); + io_dev_queued(dev); + BUG_ON(dm_io(&control, 1, &io, NULL)); +} + +/* + * Write dirty / read not uptodate page lists of a stripe. + */ +static unsigned stripe_page_lists_rw(struct raid_set *rs, struct stripe *stripe) +{ + unsigned r; + + /* + * Increment the pending count on the stripe + * first, so that we don't race in endio(). + * + * An inc (IO) is needed for any page: + * + * o not uptodate + * o dirtied by writes merged + * o dirtied by parity calculations + */ + r = for_each_io_dev(rs, stripe, _stripe_io_inc); + if (r) { + /* io needed: chunks are not uptodate/dirty. */ + int max; /* REMOVEME: */ + struct stripe_cache *sc = &rs->sc; + + if (!TestSetStripeActive(stripe)) + atomic_inc(&sc->active_stripes); + + /* Take off the lru list in case it got added there. */ + stripe_lru_del(stripe, LIST_LOCKED); + + /* Submit actual io. */ + for_each_io_dev(rs, stripe, page_list_rw); + + /* REMOVEME: statistics */ + max = sc_active(sc); + if (atomic_read(&sc->max_active_stripes) < max) + atomic_set(&sc->max_active_stripes, max); + + atomic_inc(rs->stats + S_FLUSHS); + /* END REMOVEME: statistics */ + } + + return r; +} + +/* Work in all pending writes. */ +static INLINE void _writes_merge(struct stripe *stripe, unsigned p) +{ + struct bio_list *write = BL(stripe, p, WRITE); + + if (!bio_list_empty(write)) { + struct page_list *pl = stripe->obj[p].pl; + struct bio *bio; + struct bio_list *write_merged = BL(stripe, p, WRITE_MERGED); + + /* + * We can play with the lists without holding a lock, + * because it is just us accessing them anyway. + */ + bio_list_for_each(bio, write) + bio_copy_page_list(WRITE, stripe, pl, bio); + + bio_list_merge(write_merged, write); + bio_list_init(write); + page_set(pl->page, DIRTY); + } +} + +/* Merge in all writes hence dirtying respective pages. */ +static INLINE void writes_merge(struct stripe *stripe) +{ + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) + _writes_merge(stripe, p); +} + +/* Check, if a chunk gets completely overwritten. */ +static INLINE int stripe_check_overwrite(struct stripe *stripe, unsigned p) +{ + unsigned sectors = 0; + struct bio *bio; + struct bio_list *bl = BL(stripe, p, WRITE); + + bio_list_for_each(bio, bl) + sectors += bio_sectors(bio); + + return sectors == RS(stripe->sc)->set.io_size; +} + +/* + * Prepare stripe to avoid io on broken/reconstructed + * drive to be reconstructed on endio. + */ +enum prepare_type { IO_ALLOW, IO_PROHIBIT }; +static void stripe_prepare(struct stripe *stripe, unsigned p, + enum prepare_type type) +{ + struct page *page = PAGE(stripe, p); + + switch (type) { + case IO_PROHIBIT: + /* REMOVEME: statistics. */ + atomic_inc(RS(stripe->sc)->stats + S_PROHIBITPAGEIO); + ProhibitPageIO(page); + stripe->idx.recover = p; + SetStripeReconstruct(stripe); + break; + + case IO_ALLOW: + AllowPageIO(page); + stripe->idx.recover = -1; + ClearStripeReconstruct(stripe); + break; + + default: + BUG(); + } +} + +/* + * Degraded/reconstruction mode. + * + * Check stripe state to figure which chunks don't need IO. + */ +static INLINE void stripe_check_reconstruct(struct stripe *stripe, + int prohibited) +{ + struct raid_set *rs = RS(stripe->sc); + + /* + * Degraded mode (device(s) failed) -> + * avoid io on the failed device. + */ + if (unlikely(raid_set_degraded(rs))) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_DEGRADED); + stripe_prepare(stripe, rs->set.ei, IO_PROHIBIT); + return; + } else { + /* + * Reconstruction mode (ie. a particular device or + * some (rotating) parity chunk is being resynchronized) -> + * o make sure all needed pages are read in + * o writes are allowed to go through + */ + int r = region_state(rs, stripe->key, RH_NOSYNC); + + if (r) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_NOSYNC); + stripe_prepare(stripe, dev_for_parity(stripe), + IO_PROHIBIT); + return; + } + } + + /* + * All disks good. Avoid reading parity chunk and reconstruct it + * unless we have prohibited io to chunk(s). + */ + if (!prohibited) { + if (StripeMerged(stripe)) + stripe_prepare(stripe, stripe->idx.parity, IO_ALLOW); + else { + stripe_prepare(stripe, stripe->idx.parity, IO_PROHIBIT); + ClearStripeReconstruct(stripe); + } + } +} + +/* Check, if stripe is ready to merge writes. */ +static INLINE int stripe_check_merge(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + int prohibited = 0; + unsigned chunks = 0, p = rs->set.raid_devs; + + /* Walk all chunks. */ + while (p--) { + struct page *page = PAGE(stripe, p); + + /* Can't merge active chunks. */ + if (PageLocked(page)) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_MERGE_PAGE_LOCKED); + break; + } + + /* Can merge uptodate chunks and have to count parity chunk. */ + if (PageUptodate(page) || p == stripe->idx.parity) { + chunks++; + continue; + } + + /* Read before write ordering. */ + if (RSCheckOverwrite(rs) && + bio_list_empty(BL(stripe, p, READ))) { + int r = stripe_check_overwrite(stripe, p); + + if (r) { + chunks++; + /* REMOVEME: statistics. */ + atomic_inc(RS(stripe->sc)->stats + + S_PROHIBITPAGEIO); + ProhibitPageIO(page); + prohibited = 1; + } + } + } + + if (chunks == rs->set.raid_devs) { + /* All pages are uptodate or get written over or mixture. */ + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_CAN_MERGE); + return 0; + } else + /* REMOVEME: statistics.*/ + atomic_inc(rs->stats + S_CANT_MERGE); + + return prohibited ? 1 : -EPERM; +} + +/* Check, if stripe is ready to merge writes. */ +static INLINE int stripe_check_read(struct stripe *stripe) +{ + int r = 0; + unsigned p = RS(stripe->sc)->set.raid_devs; + + /* Walk all chunks. */ + while (p--) { + struct page *page = PAGE(stripe, p); + + if (!PageLocked(page) && + bio_list_empty(BL(stripe, p, READ))) { + ProhibitPageIO(page); + r = 1; + } + } + + return r; +} + +/* + * Read/write a stripe. + * + * States to cover: + * o stripe to read and/or write + * o stripe with error to reconstruct + */ +static int stripe_rw(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + int prohibited = 0, r; + + /* + * Check the state of the RAID set and if degraded (or + * resynchronizing for reads), read in all other chunks but + * the one on the dead/resynchronizing device in order to be + * able to reconstruct the missing one. + * + * Merge all writes hanging off uptodate pages of the stripe. + */ + + /* Initially allow io on all chunks and prohibit below, if necessary. */ + stripe_allow_io(stripe); + + if (StripeRBW(stripe)) { + r = stripe_check_merge(stripe); + if (!r) { + /* + * If I could rely on valid parity (which would only + * be sure in case of a full synchronization), + * I could xor a fraction of chunks out of + * parity and back in. + * + * For the time being, I got to redo parity... + */ + // parity_xor(stripe); /* Xor chunks out. */ + stripe_zero_chunk(stripe, stripe->idx.parity); + writes_merge(stripe); /* Merge writes in. */ + parity_xor(stripe); /* Update parity. */ + ClearStripeRBW(stripe); /* Disable RBW. */ + SetStripeMerged(stripe); /* Writes merged. */ + } + + if (r > 0) + prohibited = 1; + } else if (!raid_set_degraded(rs)) + prohibited = stripe_check_read(stripe); + + /* + * Check, if io needs to be allowed/prohibeted on certain chunks + * because of a degraded set or reconstruction on a region. + */ + stripe_check_reconstruct(stripe, prohibited); + + /* Now submit any reads/writes. */ + r = stripe_page_lists_rw(rs, stripe); + if (!r) { + /* + * No io submitted because of chunk io prohibited or + * locked pages -> push to end io list for processing. + */ + atomic_inc(rs->stats + S_NO_RW); /* REMOVEME: statistics. */ + stripe_endio_push(stripe); + wake_do_raid(rs); /* Wake myself. */ + } + + return 0; +} + +/* Flush stripe either via flush list or imeediately. */ +enum flush_type { FLUSH_DELAY, FLUSH_NOW }; +static int stripe_flush(struct stripe *stripe, enum flush_type type) +{ + int r = 0; + + stripe_lru_del(stripe, LIST_LOCKED); + + /* Delay flush by putting it on io list for later processing. */ + if (type == FLUSH_DELAY) + stripe_io_add(stripe, POS_TAIL, LIST_UNLOCKED); + + /* Immediately flush. */ + else if (type == FLUSH_NOW) { + if (likely(raid_set_operational(RS(stripe->sc)))) + r = stripe_rw(stripe); /* Read/write stripe. */ + else + /* Optimization: Fail early on failed sets. */ + stripe_fail_io(stripe); + } else + BUG(); + + return r; +} + +/* + * Queue reads and writes to a stripe by hanging + * their bios off the stripsets read/write lists. + * + * Endio reads on uptodate chunks. + */ +static INLINE int stripe_queue_bio(struct raid_set *rs, struct bio *bio, + struct bio_list *reject) +{ + int r = 0; + struct address addr; + struct stripe *stripe = + stripe_get(rs, raid_address(rs, bio->bi_sector, &addr)); + + if (stripe) { + int rr, rw = bio_data_dir(bio); + + rr = stripe_lock(rs, stripe, rw, addr.key); /* Lock stripe */ + if (rr) { + stripe_put(stripe); + goto out; + } + + /* Distinguish read and write cases. */ + bio_list_add(BL(stripe, addr.di, rw), bio); + + /* REMOVEME: statistics */ + atomic_inc(rs->stats + (rw == WRITE ? + S_BIOS_ADDED_WRITE : S_BIOS_ADDED_READ)); + + if (rw == READ) + SetStripeRead(stripe); + else { + SetStripeRBW(stripe); + + /* Inrement pending write count on region. */ + rh_inc(rs->recover.rh, stripe->region); + r = 1; /* Region hash needs a flush. */ + } + + /* + * Optimize stripe flushing: + * + * o directly start io for read stripes. + * + * o put stripe onto stripe caches io_list for RBW, + * so that do_flush() can belabour it after we put + * more bios to the stripe for overwrite optimization. + */ + stripe_flush(stripe, + StripeRead(stripe) ? FLUSH_NOW : FLUSH_DELAY); + + /* Got no stripe from cache -> reject bio. */ + } else { + out: + bio_list_add(reject, bio); + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_IOS_POST); + } + + return r; +} + +/* + * Recovery functions + */ +/* Read a stripe off a raid set for recovery. */ +static int recover_read(struct raid_set *rs, struct stripe *stripe, int idx) +{ + /* Invalidate all pages so that they get read in. */ + stripe_pages_invalidate(stripe); + + /* Allow io on all recovery chunks. */ + stripe_allow_io(stripe); + + if (idx > -1) + ProhibitPageIO(PAGE(stripe, idx)); + + stripe->key = rs->recover.pos; + return stripe_page_lists_rw(rs, stripe); +} + +/* Write a stripe to a raid set for recovery. */ +static int recover_write(struct raid_set *rs, struct stripe *stripe, int idx) +{ + /* + * If this is a reconstruct of a particular device, then + * reconstruct the respective page(s), else create parity page(s). + */ + if (idx > -1) { + struct page *page = PAGE(stripe, idx); + + AllowPageIO(page); + stripe_zero_chunk(stripe, idx); + common_xor(stripe, stripe->io.size, 0, idx); + page_set(page, DIRTY); + } else + parity_xor(stripe); + + return stripe_page_lists_rw(rs, stripe); +} + +/* Recover bandwidth available ?. */ +static int recover_bandwidth(struct raid_set *rs) +{ + int r, work; + + /* On reset -> allow recovery. */ + r = recover_io_reset(rs); + if (r || RSBandwidth(rs)) + goto out; + + work = atomic_read(rs->recover.io_count + IO_WORK); + if (work) { + /* Pay attention to larger recover stripe size. */ + int recover = + atomic_read(rs->recover.io_count + IO_RECOVER) * + rs->recover.stripe->io.size / + rs->set.io_size; + + /* + * Don't use more than given bandwidth of + * the work io for recovery. + */ + if (recover > work / rs->recover.bandwidth_work) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_NO_BANDWIDTH); + return 0; + } + } + + out: + atomic_inc(rs->stats + S_BANDWIDTH); /* REMOVEME: statistics. */ + return 1; +} + +/* Try to get a region to recover. */ +static int recover_get_region(struct raid_set *rs) +{ + struct recover *rec = &rs->recover; + void *rh = rec->rh; + + /* Start quiescing some regions. */ + if (!RSRegionGet(rs)) { + int r = recover_bandwidth(rs); /* Enough bandwidth ?. */ + + if (r) { + if (rh_recovery_prepare(rh) < 0) { + DMINFO("No %sregions to recover", + rec->nr_regions_to_recover ? + "more " : ""); + return -ENOENT; + } + } else + return -EAGAIN; + + SetRSRegionGet(rs); + } + + if (!rec->reg) { + rec->reg = rh_recovery_start(rh); + if (rec->reg) { + /* + * A reference for the the region I'll + * keep till I've completely synced it. + */ + io_get(rs); + rec->pos = + rh_region_to_sector(rh, + rh_get_region_key(rec->reg)); + rec->end = rec->pos + rh_get_region_size(rh); + return 1; + } else + return -EAGAIN; + } + + return 0; +} + +/* Read/write a recovery stripe. */ +static INLINE int recover_stripe_rw(struct raid_set *rs, struct stripe *stripe) +{ + /* Read/write flip-flop. */ + if (TestClearStripeRBW(stripe)) { + SetStripeRead(stripe); + return recover_read(rs, stripe, idx_get(rs)); + } else if (TestClearStripeRead(stripe)) + return recover_write(rs, stripe, idx_get(rs)); + + return 0; +} + +/* Reset recovery variables. */ +static void recovery_region_reset(struct raid_set *rs) +{ + rs->recover.reg = NULL; + ClearRSRegionGet(rs); +} + +/* Update region hash state. */ +static void recover_rh_update(struct raid_set *rs, int error) +{ + struct recover *rec = &rs->recover; + void *rh = rec->rh; + void *reg = rec->reg; + + if (reg) { + rh_recovery_end(reg, error); + if (!error) + rec->nr_regions_recovered++; + + recovery_region_reset(rs); + } + + rh_update_states(rh); + rh_flush(rh); + io_put(rs); /* Release the io reference for the region. */ +} + +/* Called by main io daemon to recover regions. */ +static INLINE void do_recovery(struct raid_set *rs) +{ + if (RSRecover(rs)) { + int r; + struct recover *rec = &rs->recover; + struct stripe *stripe = rec->stripe; + + /* If recovery is active -> return. */ + if (StripeActive(stripe)) + return; + + /* io error is fatal for recovery -> stop it. */ + if (unlikely(StripeError(stripe))) + goto err; + + /* Get a region to recover. */ + r = recover_get_region(rs); + switch (r) { + case 1: /* Got a new region. */ + /* Flag read before write. */ + ClearStripeRead(stripe); + SetStripeRBW(stripe); + break; + + case 0: + /* Got a region in the works. */ + r = recover_bandwidth(rs); + if (r) /* Got enough bandwidth. */ + break; + + case -EAGAIN: + /* No bandwidth/quiesced region yet, try later. */ + wake_do_raid_delayed(rs, HZ / 10); + return; + + case -ENOENT: /* No more regions. */ + goto free; + } + + /* Read/write a recover stripe. */ + r = recover_stripe_rw(rs, stripe); + if (r) { + /* Io initiated, get another reference for the IO. */ + io_get(rs); + return; + } + + /* Update recovery position within region. */ + rec->pos += stripe->io.size; + + /* If we're at end of region, update region hash. */ + if (rec->pos >= rec->end || + rec->pos >= rs->set.sectors_per_dev) + recover_rh_update(rs, 0); + else + SetStripeRBW(stripe); + + /* Schedule myself for another round... */ + wake_do_raid(rs); + return; + + err: + raid_set_check_degrade(rs, stripe); + + { + char buf[BDEVNAME_SIZE]; + + DMERR("stopping recovery due to " + "ERROR on /dev/%s, stripe at offset %llu", + bdevname(rs->dev[rs->set.ei].dev->bdev, buf), + (unsigned long long) stripe->key); + + } + + /* Make sure, that all quiesced regions get released. */ + do { + if (rec->reg) + rh_recovery_end(rec->reg, -EIO); + + rec->reg = rh_recovery_start(rec->rh); + } while (rec->reg); + + recover_rh_update(rs, -EIO); + free: + stripe_recover_free(rs); + rs->set.dev_to_init = -1; + rs->recover.end_jiffies = jiffies; + /* Check for jiffies overrun. */ + if (rs->recover.end_jiffies < rs->recover.start_jiffies) + rs->recover.end_jiffies = ~0; + } +} + +/* + * END recovery functions + */ + +/* End io process all stripes handed in by endio() callback. */ +static void do_endios(struct raid_set *rs) +{ + struct stripe_cache *sc = &rs->sc; + struct stripe *stripe; + + while ((stripe = stripe_endio_pop(sc))) { + unsigned count; + + /* Recovery stripe special case. */ + if (unlikely(StripeRecover(stripe))) { + if (stripe_io(stripe)) + continue; + + io_put(rs); /* Release region io reference. */ + ClearStripeActive(stripe); + atomic_dec(&sc->active_stripes); /* REMOVEME: */ + continue; + } + + /* Early end io all reads on any uptodate chunks. */ + stripe_end_io(READ, stripe, (count = 0, &count)); + if (stripe_io(stripe)) { + if (count) /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_ACTIVE_READS); + + continue; + } + + /* Set stripe inactive after all io got processed. */ + if (TestClearStripeActive(stripe)) + atomic_dec(&sc->active_stripes); + + /* Unlock stripe (for clustering). */ + stripe_unlock(rs, stripe); + + /* + * If an io error on a stripe occured and the RAID set + * is still operational, requeue the stripe for io. + */ + if (TestClearStripeError(stripe)) { + raid_set_check_degrade(rs, stripe); + ClearStripeReconstruct(stripe); + + if (!StripeMerged(stripe) && + raid_set_operational(rs)) { + stripe_pages_invalidate(stripe); + stripe_flush(stripe, FLUSH_DELAY); + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_REQUEUE); + continue; + } + } + + /* Check if the RAID set is inoperational to error ios. */ + if (!raid_set_operational(rs)) { + ClearStripeReconstruct(stripe); + stripe_fail_io(stripe); + BUG_ON(atomic_read(&stripe->cnt)); + continue; + } + + /* Got to reconstruct a missing chunk. */ + if (TestClearStripeReconstruct(stripe)) + reconstruct_xor(stripe); + + /* + * Now that we've got a complete stripe, we can + * process the rest of the end ios on reads. + */ + BUG_ON(stripe_end_io(READ, stripe, NULL)); + ClearStripeRead(stripe); + + /* + * Read-before-write stripes need to be flushed again in + * order to work the write data into the pages *after* + * they were read in. + */ + if (TestClearStripeMerged(stripe)) + /* End io all bios which got merged already. */ + BUG_ON(stripe_end_io(WRITE_MERGED, stripe, NULL)); + + /* Got to put on flush list because of new writes. */ + if (StripeRBW(stripe)) + stripe_flush(stripe, FLUSH_DELAY); + } +} + +/* + * Stripe cache shrinking. + */ +static INLINE void do_sc_shrink(struct raid_set *rs) +{ + unsigned shrink = atomic_read(&rs->sc.stripes_to_shrink); + + if (shrink) { + unsigned cur = atomic_read(&rs->sc.stripes); + + sc_shrink(&rs->sc, shrink); + shrink -= cur - atomic_read(&rs->sc.stripes); + atomic_set(&rs->sc.stripes_to_shrink, shrink); + + /* + * Wake myself up in case we failed to shrink the + * requested amount in order to try again later. + */ + if (shrink) + wake_do_raid(rs); + } +} + + +/* + * Process all ios + * + * We do different things with the io depending on the + * state of the region that it's in: + * + * o reads: hang off stripe cache or postpone if full + * + * o writes: + * + * CLEAN/DIRTY/NOSYNC: increment pending and hang io off stripe's stripe set. + * In case stripe cache is full or busy, postpone the io. + * + * RECOVERING: delay the io until recovery of the region completes. + * + */ +static INLINE void do_ios(struct raid_set *rs, struct bio_list *ios) +{ + int r; + unsigned flush = 0; + void *rh = rs->recover.rh; + struct bio *bio; + struct bio_list delay, reject; + + bio_list_init(&delay); + bio_list_init(&reject); + + /* + * Classify each io: + * o delay to recovering regions + * o queue to all other regions + */ + while ((bio = bio_list_pop(ios))) { + /* + * In case we get a barrier bio, push it back onto + * the input queue unless all work queues are empty + * and the stripe cache is inactive. + */ + if (unlikely(bio_barrier(bio))) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_BARRIER); + if (!list_empty(rs->sc.lists + LIST_IO) || + !bio_list_empty(&delay) || + !bio_list_empty(&reject) || + sc_active(&rs->sc)) { + bio_list_push(ios, bio); + break; + } + } + + r = region_state(rs, _sector(rs, bio), RH_RECOVERING); + if (unlikely(r)) { + /* Got to wait for recovering regions. */ + bio_list_add(&delay, bio); + SetRSBandwidth(rs); + } else { + /* + * Process ios to non-recovering regions by queueing + * them to stripes (does rh_inc()) for writes). + */ + flush += stripe_queue_bio(rs, bio, &reject); + } + } + + if (flush) + rh_flush(rh); /* Writes got queued -> flush dirty log. */ + + /* Delay ios to regions which are recovering. */ + while ((bio = bio_list_pop(&delay))) { + /* REMOVEME: statistics.*/ + atomic_inc(rs->stats + S_DELAYED_BIOS); + atomic_inc(rs->stats + S_SUM_DELAYED_BIOS); + rh_delay_by_region(rh, bio, + rh_sector_to_region(rh, _sector(rs, bio))); + } + + /* Merge any rejected bios back to the head of the input list. */ + bio_list_merge_head(ios, &reject); +} + +/* Flush any stripes on the io list. */ +static INLINE void do_flush(struct raid_set *rs) +{ + struct list_head *list = rs->sc.lists + LIST_IO, *pos, *tmp; + + list_for_each_safe(pos, tmp, list) { + int r = stripe_flush(list_entry(pos, struct stripe, + lists[LIST_IO]), FLUSH_NOW); + + /* Remove from the list only if the stripe got processed. */ + if (!r) + list_del_init(pos); + } +} + +/* Send an event in case we're getting too busy. */ +static INLINE void do_busy_event(struct raid_set *rs) +{ + if ((sc_active(&rs->sc) > atomic_read(&rs->sc.stripes) * 4 / 5)) { + if (!TestSetRSScBusy(rs)) + dm_table_event(rs->ti->table); + } else + ClearRSScBusy(rs); +} + +/* Unplug: let the io role on the sets devices. */ +static INLINE void do_unplug(struct raid_set *rs) +{ + struct raid_dev *dev = rs->dev + rs->set.raid_devs; + + while (dev-- > rs->dev) { + /* Only call any device unplug function, if io got queued. */ + if (io_dev_clear(dev)) { + struct request_queue *q = + bdev_get_queue(dev->dev->bdev); + + if (q->unplug_fn) + q->unplug_fn(q); + } + } +} + +/*----------------------------------------------------------------- + * RAID daemon + *---------------------------------------------------------------*/ +/* + * o belabour all end ios + * o optionally shrink the stripe cache + * o update the region hash states + * o optionally do recovery + * o grab the input queue + * o work an all requeued or new ios and perform stripe cache flushs + * unless the RAID set is inoperational (when we error ios) + * o check, if the stripe cache gets too busy and throw an event if so + * o unplug any component raid devices with queued bios + */ +static void do_raid(struct work_struct *ws) +{ + struct raid_set *rs = container_of(ws, struct raid_set, io.dws.work); + struct bio_list *ios = &rs->io.work, *ios_in = &rs->io.in; + spinlock_t *lock = &rs->io.in_lock; + + /* + * We always need to end io, so that ios + * can get errored in case the set failed + * and the region counters get decremented + * before we update the region hash states. + */ + redo: + do_endios(rs); + + /* + * Now that we've end io'd, which may have put stripes on + * the LRU list, we shrink the stripe cache if requested. + */ + do_sc_shrink(rs); + + /* Update region hash states before we go any further. */ + rh_update_states(rs->recover.rh); + + /* Try to recover regions. */ + do_recovery(rs); + + /* More endios -> process. */ + if (!stripe_endio_empty(&rs->sc)) { + atomic_inc(rs->stats + S_REDO); + goto redo; + } + + /* Quickly grab all new ios queued and add them to the work list. */ + spin_lock_irq(lock); + bio_list_merge(ios, ios_in); + bio_list_init(ios_in); + spin_unlock_irq(lock); + + /* Let's assume we're operational most of the time ;-). */ + if (likely(raid_set_operational(rs))) { + /* If we got ios, work them into the cache. */ + if (!bio_list_empty(ios)) { + do_ios(rs, ios); + do_unplug(rs); /* Unplug the sets device queues. */ + } + + do_flush(rs); /* Flush any stripes on io list. */ + do_unplug(rs); /* Unplug the sets device queues. */ + do_busy_event(rs); /* Check if we got too busy. */ + + /* More endios -> process. */ + if (!stripe_endio_empty(&rs->sc)) { + atomic_inc(rs->stats + S_REDO); + goto redo; + } + } else + /* No way to reconstruct data with too many devices failed. */ + bio_list_fail(rs, NULL, ios); +} + +/* + * Callback for region hash to dispatch + * delayed bios queued to recovered regions + * (Gets called via rh_update_states()). + */ +static void dispatch_delayed_bios(void *context, struct bio_list *bl) +{ + struct raid_set *rs = context; + struct bio *bio; + + /* REMOVEME: decrement pending delayed bios counter. */ + bio_list_for_each(bio, bl) + atomic_dec(rs->stats + S_DELAYED_BIOS); + + /* Merge region hash private list to work list. */ + bio_list_merge_head(&rs->io.work, bl); + bio_list_init(bl); + ClearRSBandwidth(rs); +} + +/************************************************************* + * Constructor helpers + *************************************************************/ +#define XOR_SPEED_SIZE rs->recover.io_size + +/* Calculate MB/sec. */ +static INLINE unsigned mbpers(struct raid_set *rs, unsigned speed) +{ + return to_bytes(speed * rs->set.data_devs * + XOR_SPEED_SIZE * HZ >> 10) >> 10; +} + +/* + * Discover fastest xor algorithm and # of chunks combination. + */ +/* Calculate speed for algorithm and # of chunks. */ +static INLINE unsigned xor_speed(struct raid_set *rs) +{ + unsigned r = 0; + unsigned long j; + + for (j = jiffies; j == jiffies;); /* Wait for next tick. */ + + /* Do xors for a full tick. */ + for (j = jiffies; j == jiffies;) { + mb(); + common_xor(rs->recover.stripe, XOR_SPEED_SIZE, 0, 0); + mb(); + r++; + mb(); + } + + return r; +} + +/* Optimize xor algorithm for this RAID set. */ +static unsigned xor_optimize(struct raid_set *rs) +{ + unsigned chunks_max = 2, speed_max = 0; + struct xor_func *f = ARRAY_END(xor_funcs), *f_max = NULL; + + /* + * Got to allow io on all chunks, so that + * xor() will actually work on them. + */ + stripe_allow_io(rs->recover.stripe); + + /* Try all xor functions. */ + while (f-- > xor_funcs) { + unsigned speed; + + /* Set actual xor function for common_xor(). */ + rs->xor.f = f; + rs->xor.chunks = XOR_CHUNKS_MAX + 1; + + while (rs->xor.chunks-- > 2) { + speed = xor_speed(rs); + if (speed > speed_max) { + speed_max = speed; + chunks_max = rs->xor.chunks; + f_max = f; + } + } + } + + /* Memorize optimum parameters. */ + rs->xor.f = f_max; + rs->xor.chunks = chunks_max; + return speed_max; +} + +/* + * Allocate a RAID context (a RAID set) + */ +static int +context_alloc(struct raid_set **raid_set, struct raid_type *raid_type, + unsigned stripes, unsigned chunk_size, unsigned io_size, + unsigned recover_io_size, unsigned raid_devs, + sector_t sectors_per_dev, + struct dm_target *ti, unsigned dl_parms, char **argv) +{ + int r; + unsigned p; + size_t len; + sector_t region_size, ti_len; + struct raid_set *rs = NULL; + struct dm_dirty_log *dl; + + /* + * Create the dirty log + * + * We need to change length for the dirty log constructor, + * because we want an amount of regions for all stripes derived + * from the single device size, so that we can keep region + * size = 2^^n independant of the number of devices + */ + ti_len = ti->len; + ti->len = sectors_per_dev; + dl = dm_dirty_log_create(argv[0], ti, dl_parms, argv + 2); + ti->len = ti_len; + if (!dl) + goto bad_dirty_log; + + /* Chunk size *must* be smaller than region size. */ + region_size = dl->type->get_region_size(dl); + if (chunk_size > region_size) + goto bad_chunk_size; + + /* Recover io size *must* be smaller than region size as well. */ + if (recover_io_size > region_size) + goto bad_recover_io_size; + + /* Size and allocate the RAID set structure. */ + len = sizeof(*rs->data) + sizeof(*rs->dev); + if (array_too_big(sizeof(*rs), len, raid_devs)) + goto bad_array; + + len = sizeof(*rs) + raid_devs * len; + rs = kzalloc(len, GFP_KERNEL); + if (!rs) + goto bad_alloc; + + atomic_set(&rs->io.in_process, 0); + atomic_set(&rs->io.in_process_max, 0); + rs->recover.io_size = recover_io_size; + + /* Pointer to data array. */ + rs->data = (xor_t **) ((void *) rs->dev + raid_devs * sizeof(*rs->dev)); + rs->recover.dl = dl; + rs->set.raid_devs = p = raid_devs; + rs->set.data_devs = raid_devs - raid_type->parity_devs; + rs->set.raid_type = raid_type; + + /* + * Set chunk and io size and respective shifts + * (used to avoid divisions) + */ + rs->set.chunk_size = chunk_size; + rs->set.chunk_mask = chunk_size - 1; + rs->set.chunk_shift = ffs(chunk_size) - 1; + + rs->set.io_size = io_size; + rs->set.io_mask = io_size - 1; + rs->set.io_shift = ffs(io_size) - 1; + rs->set.io_shift_mask = rs->set.chunk_mask & ~rs->set.io_mask; + + rs->set.pages_per_io = chunk_pages(io_size); + rs->set.sectors_per_dev = sectors_per_dev; + + rs->set.ei = -1; /* Indicate no failed device. */ + atomic_set(&rs->set.failed_devs, 0); + + rs->ti = ti; + + atomic_set(rs->recover.io_count + IO_WORK, 0); + atomic_set(rs->recover.io_count + IO_RECOVER, 0); + + /* Initialize io lock and queues. */ + spin_lock_init(&rs->io.in_lock); + bio_list_init(&rs->io.in); + bio_list_init(&rs->io.work); + + init_waitqueue_head(&rs->io.suspendq); /* Suspend waiters (dm-io). */ + + rs->recover.nr_regions = dm_sector_div_up(sectors_per_dev, region_size); + r = rh_init(&rs->recover.rh, 1, dispatch_delayed_bios, rs, + wake_do_raid, rs, dl, region_size, + rs->recover.nr_regions); + if (r) + goto bad_rh; + + /* Initialize stripe cache. */ + r = sc_init(rs, stripes); + if (r) + goto bad_sc; + + /* Create dm-io client context. */ + rs->sc.dm_io_client = dm_io_client_create(rs->set.raid_devs * + rs->set.pages_per_io); + if (IS_ERR(rs->sc.dm_io_client)) + goto bad_dm_io_client; + + /* REMOVEME: statistics. */ + stats_reset(rs); + ClearRSDevelStats(rs); /* Disnable development status. */ + + *raid_set = rs; + return 0; + + bad_dirty_log: + TI_ERR_RET("Error creating dirty log", -ENOMEM); + + + bad_chunk_size: + dm_dirty_log_destroy(dl); + TI_ERR("Chunk size larger than region size"); + + bad_recover_io_size: + dm_dirty_log_destroy(dl); + TI_ERR("Recover stripe io size larger than region size"); + + bad_array: + dm_dirty_log_destroy(dl); + TI_ERR("Arry too big"); + + bad_alloc: + dm_dirty_log_destroy(dl); + TI_ERR_RET("Cannot allocate raid context", -ENOMEM); + + bad_rh: + dm_dirty_log_destroy(dl); + ti->error = DM_MSG_PREFIX "Error creating dirty region hash"; + goto free_rs; + + bad_sc: + ti->error = DM_MSG_PREFIX "Error creating stripe cache"; + goto free; + + bad_dm_io_client: + ti->error = DM_MSG_PREFIX "Error allocating dm-io resources"; + free: + sc_exit(&rs->sc); + rh_exit(rs->recover.rh); + free_rs: + kfree(rs); + return -ENOMEM; +} + +/* Free a RAID context (a RAID set). */ +static void +context_free(struct raid_set *rs, struct dm_target *ti, unsigned r) +{ + while (r--) + dm_put_device(ti, rs->dev[r].dev); + + dm_io_client_destroy(rs->sc.dm_io_client); + stripe_recover_free(rs); + sc_exit(&rs->sc); + rh_exit(rs->recover.rh); /* Destroys dirty log as well. */ + kfree(rs); +} + +/* Create work queue and initialize work. */ +static int rs_workqueue_init(struct raid_set *rs) +{ + struct dm_target *ti = rs->ti; + + rs->io.wq = create_singlethread_workqueue(DAEMON); + if (!rs->io.wq) + TI_ERR_RET("failed to create " DAEMON, -ENOMEM); + + INIT_DELAYED_WORK(&rs->io.dws, do_raid); + return 0; +} + +/* Return pointer to raid_type structure for raid name. */ +static struct raid_type *get_raid_type(char *name) +{ + struct raid_type *r = ARRAY_END(raid_types); + + while (r-- > raid_types) { + if (!strnicmp(STR_LEN(r->name, name))) + return r; + } + + return NULL; +} + +/* FIXME: factor out to dm core. */ +static int multiple(sector_t a, sector_t b, sector_t *n) +{ + sector_t r = a; + + sector_div(r, b); + *n = r; + return a == r * b; +} + +/* Log RAID set information to kernel log. */ +static void raid_set_log(struct raid_set *rs, unsigned speed) +{ + unsigned p; + char buf[BDEVNAME_SIZE]; + + for (p = 0; p < rs->set.raid_devs; p++) + DMINFO("/dev/%s is raid disk %u", + bdevname(rs->dev[p].dev->bdev, buf), p); + + DMINFO("%d/%d/%d sectors chunk/io/recovery size, %u stripes", + rs->set.chunk_size, rs->set.io_size, rs->recover.io_size, + atomic_read(&rs->sc.stripes)); + DMINFO("algorithm \"%s\", %u chunks with %uMB/s", rs->xor.f->name, + rs->xor.chunks, mbpers(rs, speed)); + DMINFO("%s set with net %u/%u devices", rs->set.raid_type->descr, + rs->set.data_devs, rs->set.raid_devs); +} + +/* Get all devices and offsets. */ +static int +dev_parms(struct dm_target *ti, struct raid_set *rs, + char **argv, int *p) +{ + for (*p = 0; *p < rs->set.raid_devs; (*p)++, argv += 2) { + int r; + unsigned long long tmp; + struct raid_dev *dev = rs->dev + *p; + union dev_lookup dl = {.dev = dev }; + + /* Get offset and device. */ + r = sscanf(argv[1], "%llu", &tmp); + if (r != 1) + TI_ERR("Invalid RAID device offset parameter"); + + dev->start = tmp; + r = dm_get_device(ti, argv[0], dev->start, + rs->set.sectors_per_dev, + dm_table_get_mode(ti->table), &dev->dev); + if (r) + TI_ERR_RET("RAID device lookup failure", r); + + r = raid_dev_lookup(rs, bynumber, &dl); + if (r != -ENODEV && r < *p) { + (*p)++; /* Ensure dm_put_device() on actual device. */ + TI_ERR_RET("Duplicate RAID device", -ENXIO); + } + } + + return 0; +} + +/* Set recovery bandwidth. */ +static INLINE void +recover_set_bandwidth(struct raid_set *rs, unsigned bandwidth) +{ + rs->recover.bandwidth = bandwidth; + rs->recover.bandwidth_work = 100 / bandwidth; +} + +/* Handle variable number of RAID parameters. */ +static int +raid_variable_parms(struct dm_target *ti, char **argv, + unsigned i, int *raid_parms, + int *chunk_size, int *chunk_size_parm, + int *stripes, int *stripes_parm, + int *io_size, int *io_size_parm, + int *recover_io_size, int *recover_io_size_parm, + int *bandwidth, int *bandwidth_parm) +{ + /* Fetch # of variable raid parameters. */ + if (sscanf(argv[i++], "%d", raid_parms) != 1 || + !range_ok(*raid_parms, 0, 5)) + TI_ERR("Bad variable raid parameters number"); + + if (*raid_parms) { + /* + * If we've got variable RAID parameters, + * chunk size is the first one + */ + if (sscanf(argv[i++], "%d", chunk_size) != 1 || + (*chunk_size != -1 && + (!POWER_OF_2(*chunk_size) || + !range_ok(*chunk_size, IO_SIZE_MIN, CHUNK_SIZE_MAX)))) + TI_ERR ("Invalid chunk size; " + "must be 2^^n and <= 16384"); + + *chunk_size_parm = *chunk_size; + if (*chunk_size == -1) + *chunk_size = CHUNK_SIZE; + + /* + * In case we've got 2 or more variable raid + * parameters, the number of stripes is the second one + */ + if (*raid_parms > 1) { + if (sscanf(argv[i++], "%d", stripes) != 1 || + (*stripes != -1 && + !range_ok(*stripes, STRIPES_MIN, + STRIPES_MAX))) + TI_ERR("Invalid number of stripes: must " + "be >= 8 and <= 8192"); + } + + *stripes_parm = *stripes; + if (*stripes == -1) + *stripes = STRIPES; + + /* + * In case we've got 3 or more variable raid + * parameters, the io size is the third one. + */ + if (*raid_parms > 2) { + if (sscanf(argv[i++], "%d", io_size) != 1 || + (*io_size != -1 && + (!POWER_OF_2(*io_size) || + !range_ok(*io_size, IO_SIZE_MIN, + min(BIO_MAX_SECTORS / 2, + *chunk_size))))) + TI_ERR("Invalid io size; must " + "be 2^^n and less equal " + "min(BIO_MAX_SECTORS/2, chunk size)"); + } else + *io_size = *chunk_size; + + *io_size_parm = *io_size; + if (*io_size == -1) + *io_size = *chunk_size; + + /* + * In case we've got 4 variable raid parameters, + * the recovery stripe io_size is the fourth one + */ + if (*raid_parms > 3) { + if (sscanf(argv[i++], "%d", recover_io_size) != 1 || + (*recover_io_size != -1 && + (!POWER_OF_2(*recover_io_size) || + !range_ok(*recover_io_size, RECOVER_IO_SIZE_MIN, + BIO_MAX_SECTORS / 2)))) + TI_ERR("Invalid recovery io size; must be " + "2^^n and less equal BIO_MAX_SECTORS/2"); + } + + *recover_io_size_parm = *recover_io_size; + if (*recover_io_size == -1) + *recover_io_size = RECOVER_IO_SIZE; + + /* + * In case we've got 5 variable raid parameters, + * the recovery io bandwidth is the fifth one + */ + if (*raid_parms > 4) { + if (sscanf(argv[i++], "%d", bandwidth) != 1 || + (*bandwidth != -1 && + !range_ok(*bandwidth, BANDWIDTH_MIN, + BANDWIDTH_MAX))) + TI_ERR("Invalid recovery bandwidth " + "percentage; must be > 0 and <= 100"); + } + + *bandwidth_parm = *bandwidth; + if (*bandwidth == -1) + *bandwidth = BANDWIDTH; + } + + return 0; +} + +/* Parse optional locking parameters. */ +static int +raid_locking_parms(struct dm_target *ti, char **argv, + unsigned i, int *locking_parms, + struct dmraid45_locking_type **locking_type) +{ + *locking_parms = 0; + *locking_type = &locking_none; + + if (!strnicmp(argv[i], "none", strlen(argv[i]))) + *locking_parms = 1; + else if (!strnicmp(argv[i + 1], "locking", strlen(argv[i + 1]))) { + *locking_type = &locking_none; + *locking_parms = 2; + } else if (!strnicmp(argv[i + 1], "cluster", strlen(argv[i + 1]))) { + *locking_type = &locking_cluster; + /* FIXME: namespace. */ + *locking_parms = 3; + } + + return *locking_parms == 1 ? -EINVAL : 0; +} + +/* Set backing device information properties of RAID set. */ +static void rs_set_bdi(struct raid_set *rs, unsigned stripes, unsigned chunks) +{ + unsigned p, ra_pages; + struct mapped_device *md = dm_table_get_md(rs->ti->table); + struct backing_dev_info *bdi = &dm_disk(md)->queue->backing_dev_info; + + /* Set read-ahead for the RAID set and the component devices. */ + bdi->ra_pages = stripes * stripe_pages(rs, rs->set.io_size); + ra_pages = chunks * chunk_pages(rs->set.io_size); + for (p = rs->set.raid_devs; p--; ) + bdev_get_queue(rs->dev[p].dev->bdev)->backing_dev_info.ra_pages = ra_pages; + + /* Set congested function and data. */ + bdi->congested_fn = raid_set_congested; + bdi->congested_data = rs; + + dm_put(md); +} + +/* Get backing device information properties of RAID set. */ +static void rs_get_ra(struct raid_set *rs, unsigned *stripes, unsigned *chunks) +{ + struct mapped_device *md = dm_table_get_md(rs->ti->table); + + *stripes = dm_disk(md)->queue->backing_dev_info.ra_pages + / stripe_pages(rs, rs->set.io_size); + *chunks = bdev_get_queue(rs->dev->dev->bdev)->backing_dev_info.ra_pages + / chunk_pages(rs->set.io_size); + + dm_put(md); +} + +/* + * Construct a RAID4/5 mapping: + * + * log_type #log_params \ + * raid_type [#parity_dev] #raid_variable_params \ + * [locking "none"/"cluster"] + * #raid_devs #dev_to_initialize [ ]{3,} + * + * log_type = "core"/"disk", + * #log_params = 1-3 (1-2 for core dirty log type, 3 for disk dirty log only) + * log_params = [dirty_log_path] region_size [[no]sync]) + * + * raid_type = "raid4", "raid5_la", "raid5_ra", "raid5_ls", "raid5_rs" + * + * #parity_dev = N if raid_type = "raid4" + * o N = -1: pick default = last device + * o N >= 0 and < #raid_devs: parity device index + * + * #raid_variable_params = 0-5; raid_params (-1 = default): + * [chunk_size [#stripes [io_size [recover_io_size [%recovery_bandwidth]]]]] + * o chunk_size (unit to calculate drive addresses; must be 2^^n, > 8 + * and <= CHUNK_SIZE_MAX) + * o #stripes is number of stripes allocated to stripe cache + * (must be > 1 and < STRIPES_MAX) + * o io_size (io unit size per device in sectors; must be 2^^n and > 8) + * o recover_io_size (io unit size per device for recovery in sectors; + must be 2^^n, > SECTORS_PER_PAGE and <= region_size) + * o %recovery_bandwith is the maximum amount spend for recovery during + * application io (1-100%) + * If raid_variable_params = 0, defaults will be used. + * Any raid_variable_param can be set to -1 to apply a default + * + * #raid_devs = N (N >= 3) + * + * #dev_to_initialize = N + * -1: initialize parity on all devices + * >= 0 and < #raid_devs: initialize raid_path; used to force reconstruction + * of a failed devices content after replacement + * + * = device_path (eg, /dev/sdd1) + * = begin at offset on + * + */ +#define MIN_PARMS 13 +static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) +{ + int bandwidth = BANDWIDTH, bandwidth_parm = -1, + chunk_size = CHUNK_SIZE, chunk_size_parm = -1, + dev_to_init, dl_parms, locking_parms, parity_parm, pi = -1, + i, io_size = IO_SIZE, io_size_parm = -1, + r, raid_devs, raid_parms, + recover_io_size = RECOVER_IO_SIZE, recover_io_size_parm = -1, + stripes = STRIPES, stripes_parm = -1; + unsigned speed; + sector_t tmp, sectors_per_dev; + struct dmraid45_locking_type *locking; + struct raid_set *rs; + struct raid_type *raid_type; + + /* Ensure minimum number of parameters. */ + if (argc < MIN_PARMS) + TI_ERR("Not enough parameters"); + + /* Fetch # of dirty log parameters. */ + if (sscanf(argv[1], "%d", &dl_parms) != 1 + || !range_ok(dl_parms, 1, 4711)) + TI_ERR("Bad dirty log parameters number"); + + /* Check raid_type. */ + raid_type = get_raid_type(argv[dl_parms + 2]); + if (!raid_type) + TI_ERR("Bad raid type"); + + /* In case of RAID4, parity drive is selectable. */ + parity_parm = !!(raid_type->level == raid4); + + /* Handle variable number of RAID parameters. */ + r = raid_variable_parms(ti, argv, dl_parms + parity_parm + 3, + &raid_parms, + &chunk_size, &chunk_size_parm, + &stripes, &stripes_parm, + &io_size, &io_size_parm, + &recover_io_size, &recover_io_size_parm, + &bandwidth, &bandwidth_parm); + if (r) + return r; + + r = raid_locking_parms(ti, argv, + dl_parms + parity_parm + raid_parms + 4, + &locking_parms, &locking); + if (r) + return r; + + /* # of raid devices. */ + if (sscanf(argv[dl_parms + parity_parm + raid_parms + locking_parms +4], + "%d", &raid_devs) != 1 || raid_devs < raid_type->minimal_devs) + TI_ERR("Invalid number of raid devices"); + + /* In case of RAID4, check parity drive index is in limits. */ + if (raid_type->level == raid4) { + /* Fetch index of parity device. */ + if (sscanf(argv[dl_parms + 3], "%d", &pi) != 1 || + !range_ok(pi, 0, raid_devs - 1)) + TI_ERR("Invalid RAID4 parity device index"); + } + + /* + * Index of device to initialize starts at 0 + * + * o -1 -> don't initialize a particular device, + * o 0..raid_devs-1 -> initialize respective device + * (used for reconstruction of a replaced device) + */ + if (sscanf + (argv[dl_parms + parity_parm + raid_parms + locking_parms + 5], + "%d", &dev_to_init) != 1 + || !range_ok(dev_to_init, -1, raid_devs - 1)) + TI_ERR("Invalid number for raid device to initialize"); + + /* Check # of raid device arguments. */ + if (argc - dl_parms - parity_parm - raid_parms - 6 != + 2 * raid_devs) + TI_ERR("Wrong number of raid device/offset arguments"); + + /* + * Check that the table length is devisable + * w/o rest by (raid_devs - parity_devs) + */ + if (!multiple(ti->len, raid_devs - raid_type->parity_devs, + §ors_per_dev)) + TI_ERR + ("Target length not divisable by number of data devices"); + + /* + * Check that the device size is + * devisable w/o rest by chunk size + */ + if (!multiple(sectors_per_dev, chunk_size, &tmp)) + TI_ERR("Device length not divisable by chunk_size"); + + /**************************************************************** + * Now that we checked the constructor arguments -> + * let's allocate the RAID set + ****************************************************************/ + r = context_alloc(&rs, raid_type, stripes, chunk_size, io_size, + recover_io_size, raid_devs, sectors_per_dev, + ti, dl_parms, argv); + if (r) + return r; + + /* + * Set these here in order to avoid passing + * too many arguments to context_alloc() + */ + rs->set.dev_to_init_parm = dev_to_init; + rs->set.dev_to_init = dev_to_init; + rs->set.pi_parm = pi; + rs->set.pi = (pi == -1) ? rs->set.data_devs : pi; + rs->set.raid_parms = raid_parms; + rs->set.chunk_size_parm = chunk_size_parm; + rs->set.io_size_parm = io_size_parm; + rs->sc.stripes_parm = stripes_parm; + rs->recover.io_size_parm = recover_io_size_parm; + rs->recover.bandwidth_parm = bandwidth_parm; + recover_set_bandwidth(rs, bandwidth); + + /* Use locking type to lock stripe access. */ + rs->locking = locking; + + /* Get the device/offset tupels. */ + argv += dl_parms + 6 + parity_parm + raid_parms; + r = dev_parms(ti, rs, argv, &i); + if (r) + goto err; + + /* Initialize recovery. */ + rs->recover.start_jiffies = jiffies; + rs->recover.end_jiffies = 0; + recovery_region_reset(rs); + SetRSRecover(rs); + + /* Set backing device information (eg. read ahead). */ + rs_set_bdi(rs, chunk_size * 2, io_size * 4); + SetRSCheckOverwrite(rs); /* Allow chunk overwrite checks. */ + + speed = xor_optimize(rs); /* Select best xor algorithm. */ + + /* Initialize work queue to handle this RAID set's io. */ + r = rs_workqueue_init(rs); + if (r) + goto err; + + raid_set_log(rs, speed); /* Log information about RAID set. */ + + /* + * Make sure that dm core only hands maximum io size + * length down and pays attention to io boundaries. + */ + ti->split_io = rs->set.io_size; + ti->private = rs; + return 0; + + err: + context_free(rs, ti, i); + return r; +} + +/* + * Destruct a raid mapping + */ +static void raid_dtr(struct dm_target *ti) +{ + struct raid_set *rs = ti->private; + + /* Indicate recovery end. */ + ClearRSRecover(rs); + wake_do_raid(rs); /* Wake daemon. */ + wait_ios(rs); /* Wait for any io still being processed. */ + destroy_workqueue(rs->io.wq); + context_free(rs, ti, rs->set.raid_devs); +} + +/* Queues ios to RAID sets. */ +static inline void queue_bio(struct raid_set *rs, struct bio *bio) +{ + int wake; + struct bio_list *in = &rs->io.in; + spinlock_t *in_lock = &rs->io.in_lock; + + spin_lock_irq(in_lock); + wake = bio_list_empty(in); + bio_list_add(in, bio); + spin_unlock_irq(in_lock); + + /* Wake daemon if input list was empty. */ + if (wake) + wake_do_raid(rs); +} + +/* Raid mapping function. */ +static int raid_map(struct dm_target *ti, struct bio *bio, + union map_info *map_context) +{ + /* I don't want to waste stripe cache capacity. */ + if (bio_rw(bio) == READA) + return -EIO; + else { + struct raid_set *rs = ti->private; + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + + (bio_data_dir(bio) == WRITE ? + S_BIOS_WRITE : S_BIOS_READ)); + + /* + * Get io reference to be waiting for to drop + * to zero on device suspension/destruction. + */ + io_get(rs); + bio->bi_sector -= ti->begin; /* Remap sector. */ + queue_bio(rs, bio); /* Queue to the daemon. */ + return DM_MAPIO_SUBMITTED; /* Handle later. */ + } +} + +/* Device suspend. */ +static void raid_postsuspend(struct dm_target *ti) +{ + struct raid_set *rs = ti->private; + struct dm_dirty_log *dl = rs->recover.dl; + + SetRSSuspended(rs); + + if (RSRecover(rs)) + rh_stop_recovery(rs->recover.rh); /* Wakes do_raid(). */ + else + wake_do_raid(rs); + + wait_ios(rs); /* Wait for completion of all ios being processed. */ + if (dl->type->postsuspend && dl->type->postsuspend(dl)) + /* Suspend dirty log. */ + /* FIXME: need better error handling. */ + DMWARN("log suspend failed"); +} + +/* Device resume. */ +static void raid_resume(struct dm_target *ti) +{ + struct raid_set *rs = ti->private; + struct dm_dirty_log *dl = rs->recover.dl; + + if (dl->type->resume && dl->type->resume(dl)) + /* Resume dirty log. */ + /* FIXME: need better error handling. */ + DMWARN("log resume failed"); + + rs->recover.nr_regions_to_recover = + rs->recover.nr_regions - dl->type->get_sync_count(dl); + + ClearRSSuspended(rs); + + /* Reset any unfinished recovery. */ + if (RSRecover(rs)) { + recovery_region_reset(rs); + rh_start_recovery(rs->recover.rh); /* Calls wake_do_raid(). */ + } else + wake_do_raid(rs); +} + +static INLINE unsigned sc_size(struct raid_set *rs) +{ + return to_sector(atomic_read(&rs->sc.stripes) * + (sizeof(struct stripe) + + (sizeof(struct stripe_set) + + (sizeof(struct page_list) + + to_bytes(rs->set.io_size) * + rs->set.raid_devs)) + + (rs->recover. + end_jiffies ? 0 : to_bytes(rs->set.raid_devs * + rs->recover. + io_size)))); +} + +/* REMOVEME: status output for development. */ +static void +raid_devel_stats(struct dm_target *ti, char *result, + unsigned *size, unsigned maxlen) +{ + unsigned chunks, stripes, sz = *size; + unsigned long j; + char buf[BDEVNAME_SIZE], *p; + struct stats_map *sm, *sm_end = ARRAY_END(stats_map); + struct raid_set *rs = ti->private; + struct recover *rec = &rs->recover; + struct timespec ts; + + DMEMIT("%s ", version); + DMEMIT("io_inprocess=%d ", atomic_read(&rs->io.in_process)); + DMEMIT("io_inprocess_max=%d ", atomic_read(&rs->io.in_process_max)); + + for (sm = stats_map; sm < sm_end; sm++) + DMEMIT("%s%d", sm->str, atomic_read(rs->stats + sm->type)); + + DMEMIT(" overwrite=%s ", RSCheckOverwrite(rs) ? "on" : "off"); + DMEMIT("sc=%u/%u/%u/%u/%u ", rs->set.chunk_size, rs->set.io_size, + atomic_read(&rs->sc.stripes), rs->sc.hash.buckets, + sc_size(rs)); + + j = (rec->end_jiffies ? rec->end_jiffies : jiffies) - + rec->start_jiffies; + jiffies_to_timespec(j, &ts); + sprintf(buf, "%ld.%ld", ts.tv_sec, ts.tv_nsec); + p = strchr(buf, '.'); + p[3] = 0; + + DMEMIT("rg=%llu%s/%llu/%llu/%u %s ", + (unsigned long long) rec->nr_regions_recovered, + RSRegionGet(rs) ? "+" : "", + (unsigned long long) rec->nr_regions_to_recover, + (unsigned long long) rec->nr_regions, rec->bandwidth, buf); + + rs_get_ra(rs, &stripes, &chunks); + DMEMIT("ra=%u/%u ", stripes, chunks); + + *size = sz; +} + +static int +raid_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) +{ + unsigned i, sz = 0; + char buf[BDEVNAME_SIZE]; + struct raid_set *rs = ti->private; + + switch (type) { + case STATUSTYPE_INFO: + /* REMOVEME: statistics. */ + if (RSDevelStats(rs)) + raid_devel_stats(ti, result, &sz, maxlen); + + DMEMIT("%u ", rs->set.raid_devs); + + for (i = 0; i < rs->set.raid_devs; i++) + DMEMIT("%s ", + format_dev_t(buf, rs->dev[i].dev->bdev->bd_dev)); + + DMEMIT("1 "); + for (i = 0; i < rs->set.raid_devs; i++) { + DMEMIT("%c", + dev_operational(rs, i) ? 'A' : 'D'); + + if (rs->set.raid_type->level == raid4 && + i == rs->set.pi) + DMEMIT("p"); + + if (rs->set.dev_to_init == i) + DMEMIT("i"); + } + + break; + + case STATUSTYPE_TABLE: + sz = rs->recover.dl->type->status(rs->recover.dl, type, + result, maxlen); + DMEMIT("%s %u ", rs->set.raid_type->name, + rs->set.raid_parms); + + if (rs->set.raid_type->level == raid4) + DMEMIT("%d ", rs->set.pi_parm); + + if (rs->set.raid_parms) + DMEMIT("%d ", rs->set.chunk_size_parm); + + if (rs->set.raid_parms > 1) + DMEMIT("%d ", rs->sc.stripes_parm); + + if (rs->set.raid_parms > 2) + DMEMIT("%d ", rs->set.io_size_parm); + + if (rs->set.raid_parms > 3) + DMEMIT("%d ", rs->recover.io_size_parm); + + if (rs->set.raid_parms > 4) + DMEMIT("%d ", rs->recover.bandwidth_parm); + + DMEMIT("%u %d ", rs->set.raid_devs, rs->set.dev_to_init); + + for (i = 0; i < rs->set.raid_devs; i++) + DMEMIT("%s %llu ", + format_dev_t(buf, + rs->dev[i].dev->bdev->bd_dev), + (unsigned long long) rs->dev[i].start); + } + + return 0; +} + +/* + * Message interface + */ +enum raid_msg_actions { + act_bw, /* Recovery bandwidth switch. */ + act_dev, /* Device failure switch. */ + act_overwrite, /* Stripe overwrite check. */ + act_read_ahead, /* Set read ahead. */ + act_stats, /* Development statistics switch. */ + act_sc, /* Stripe cache switch. */ + + act_on, /* Set entity on. */ + act_off, /* Set entity off. */ + act_reset, /* Reset entity. */ + + act_set = act_on, /* Set # absolute. */ + act_grow = act_off, /* Grow # by an amount. */ + act_shrink = act_reset, /* Shrink # by an amount. */ +}; + +/* Turn a delta to absolute. */ +static int _absolute(unsigned long action, int act, int r) +{ + /* Make delta absolute. */ + if (test_bit(act_set, &action)); + else if (test_bit(act_grow, &action)) + r += act; + else if (test_bit(act_shrink, &action)) + r = act - r; + else + r = -EINVAL; + + return r; +} + + /* Change recovery io bandwidth. */ +static int bandwidth_change(struct dm_msg *msg, void *context) +{ + struct raid_set *rs = context; + int act = rs->recover.bandwidth; + int bandwidth = DM_MSG_INT_ARG(msg); + + if (range_ok(bandwidth, BANDWIDTH_MIN, BANDWIDTH_MAX)) { + /* Make delta bandwidth absolute. */ + bandwidth = _absolute(msg->action, act, bandwidth); + + /* Check range. */ + if (range_ok(bandwidth, BANDWIDTH_MIN, BANDWIDTH_MAX)) { + recover_set_bandwidth(rs, bandwidth); + return 0; + } + } + + set_bit(dm_msg_ret_arg, &msg->ret); + set_bit(dm_msg_ret_inval, &msg->ret); + return -EINVAL; +} + +/* Change state of a device (running/offline). */ +/* FIXME: this only works while recovering!. */ +static int device_state(struct dm_msg *msg, void *context) +{ + int r; + const char *str = "is already "; + union dev_lookup dl = { .dev_name = DM_MSG_STR_ARG(msg) }; + struct raid_set *rs = context; + + r = raid_dev_lookup(rs, strchr(dl.dev_name, ':') ? + bymajmin : byname, &dl); + if (r == -ENODEV) { + DMERR("device %s is no member of this set", dl.dev_name); + return r; + } + + if (test_bit(act_off, &msg->action)) { + if (dev_operational(rs, r)) + str = ""; + } else if (!dev_operational(rs, r)) + str = ""; + + DMINFO("/dev/%s %s%s", dl.dev_name, str, + test_bit(act_off, &msg->action) ? "offline" : "running"); + + return test_bit(act_off, &msg->action) ? + raid_set_check_and_degrade(rs, NULL, r) : + raid_set_check_and_upgrade(rs, r); +} + +/* Set/reset development feature flags. */ +static int devel_flags(struct dm_msg *msg, void *context) +{ + struct raid_set *rs = context; + + if (test_bit(act_on, &msg->action)) + return test_and_set_bit(msg->spec->parm, + &rs->io.flags) ? -EPERM : 0; + else if (test_bit(act_off, &msg->action)) + return test_and_clear_bit(msg->spec->parm, + &rs->io.flags) ? 0 : -EPERM; + else if (test_bit(act_reset, &msg->action)) { + if (test_bit(act_stats, &msg->action)) { + stats_reset(rs); + goto on; + } else if (test_bit(act_overwrite, &msg->action)) { + on: + set_bit(msg->spec->parm, &rs->io.flags); + return 0; + } + } + + return -EINVAL; +} + + /* Set stripe and chunk read ahead pages. */ +static int read_ahead_set(struct dm_msg *msg, void *context) +{ + int stripes = DM_MSG_INT_ARGS(msg, 0); + int chunks = DM_MSG_INT_ARGS(msg, 1); + + if (range_ok(stripes, 1, 512) && + range_ok(chunks, 1, 512)) { + rs_set_bdi(context, stripes, chunks); + return 0; + } + + set_bit(dm_msg_ret_arg, &msg->ret); + set_bit(dm_msg_ret_inval, &msg->ret); + return -EINVAL; +} + +/* Resize the stripe cache. */ +static int stripecache_resize(struct dm_msg *msg, void *context) +{ + int act, stripes; + struct raid_set *rs = context; + + /* Deny permission in case the daemon is still shrinking!. */ + if (atomic_read(&rs->sc.stripes_to_shrink)) + return -EPERM; + + stripes = DM_MSG_INT_ARG(msg); + if (stripes > 0) { + act = atomic_read(&rs->sc.stripes); + + /* Make delta stripes absolute. */ + stripes = _absolute(msg->action, act, stripes); + + /* + * Check range and that the # of stripes changes. + * We can grow from gere but need to leave any + * shrinking to the worker for synchronization. + */ + if (range_ok(stripes, STRIPES_MIN, STRIPES_MAX)) { + if (stripes > act) + return sc_grow(&rs->sc, stripes - act, grow); + else if (stripes < act) { + atomic_set(&rs->sc.stripes_to_shrink, + act - stripes); + wake_do_raid(rs); + } + + return 0; + } + } + + set_bit(dm_msg_ret_arg, &msg->ret); + set_bit(dm_msg_ret_inval, &msg->ret); + return -EINVAL; +} + +/* Parse the RAID message action. */ +/* + * 'ba[ndwidth] {se[t],g[row],sh[rink]} #' # e.g 'ba se 50' + * 'de{vice] o[ffline]/r[unning] DevName/maj:min' # e.g 'device o /dev/sda' + * "o[verwrite] {on,of[f],r[eset]}' # e.g. 'o of' + * "r[ead_ahead] set #stripes #chunks # e.g. 'r se 3 2' + * 'sta[tistics] {on,of[f],r[eset]}' # e.g. 'stat of' + * 'str[ipecache] {se[t],g[row],sh[rink]} #' # e.g. 'stripe set 1024' + * + */ +static int +raid_message(struct dm_target *ti, unsigned argc, char **argv) +{ + /* Variables to store the parsed parameters im. */ + static int i[2]; + static unsigned long *i_arg[] = { + (unsigned long *) i + 0, + (unsigned long *) i + 1, + }; + static char *p; + static unsigned long *p_arg[] = { (unsigned long *) &p }; + + /* Declare all message option strings. */ + static char *str_sgs[] = { "set", "grow", "shrink" }; + static char *str_dev[] = { "running", "offline" }; + static char *str_oor[] = { "on", "off", "reset" }; + + /* Declare all actions. */ + static unsigned long act_sgs[] = { act_set, act_grow, act_shrink }; + static unsigned long act_oor[] = { act_on, act_off, act_reset }; + + /* Bandwidth option. */ + static struct dm_message_option bw_opt = { 3, str_sgs, act_sgs }; + static struct dm_message_argument bw_args = + { 1, i_arg, { dm_msg_int_t } }; + + /* Device option. */ + static struct dm_message_option dev_opt = { 2, str_dev, act_oor }; + static struct dm_message_argument dev_args = + { 1, p_arg, { dm_msg_base_t } }; + + /* Read ahead option. */ + static struct dm_message_option ra_opt = { 1, str_sgs, act_sgs }; + static struct dm_message_argument ra_args = + { 2, i_arg, { dm_msg_int_t, dm_msg_int_t } }; + + static struct dm_message_argument null_args = + { 0, NULL, { dm_msg_int_t } }; + + /* Overwrite and statistics option. */ + static struct dm_message_option ovr_stats_opt = { 3, str_oor, act_oor }; + + /* Sripecache option. */ + static struct dm_message_option stripe_opt = { 3, str_sgs, act_sgs }; + + /* Declare messages. */ + static struct dm_msg_spec specs[] = { + { "bandwidth", act_bw, &bw_opt, &bw_args, + 0, bandwidth_change }, + { "device", act_dev, &dev_opt, &dev_args, + 0, device_state }, + { "overwrite", act_overwrite, &ovr_stats_opt, &null_args, + RS_CHECK_OVERWRITE, devel_flags }, + { "read_ahead", act_read_ahead, &ra_opt, &ra_args, + 0, read_ahead_set }, + { "statistics", act_stats, &ovr_stats_opt, &null_args, + RS_DEVEL_STATS, devel_flags }, + { "stripecache", act_sc, &stripe_opt, &bw_args, + 0, stripecache_resize }, + }; + + /* The message for the parser. */ + struct dm_msg msg = { + .num_specs = ARRAY_SIZE(specs), + .specs = specs, + }; + + return dm_message_parse(TARGET, &msg, ti->private, argc, argv); +} +/* + * END message interface + */ + +static struct target_type raid_target = { + .name = "raid45", + .version = {1, 0, 0}, + .module = THIS_MODULE, + .ctr = raid_ctr, + .dtr = raid_dtr, + .map = raid_map, + .postsuspend = raid_postsuspend, + .resume = raid_resume, + .status = raid_status, + .message = raid_message, +}; + +static void init_exit(const char *bad_msg, const char *good_msg, int r) +{ + if (r) + DMERR("Failed to %sregister target [%d]", bad_msg, r); + else + DMINFO("%s %s", good_msg, version); +} + +static int __init dm_raid_init(void) +{ + int r; + + r = dm_register_target(&raid_target); + init_exit("", "initialized", r); + return r; +} + +static void __exit dm_raid_exit(void) +{ + int r; + + r = dm_unregister_target(&raid_target); + init_exit("un", "exit", r); +} + +/* Module hooks. */ +module_init(dm_raid_init); +module_exit(dm_raid_exit); + +MODULE_DESCRIPTION(DM_NAME " raid4/5 target"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/dm-raid4-5/Kconfig +++ linux-2.6.27/ubuntu/dm-raid4-5/Kconfig @@ -0,0 +1,6 @@ +config DM_RAID45 + tristate "RAID 4/5 target (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + default m + ---help--- + A target that supports RAID4 and RAID5 mappings. --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-region_hash.h +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-region_hash.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2003 Sistina Software Limited. + * Copyright (C) 2004-2007 Red Hat Inc. + * + * This file is released under the GPL. + */ + +#ifndef DM_RH_H +#define DM_RH_H + +#include "dm.h" +#include +#include "dm-bio-list.h" + +/*----------------------------------------------------------------- + * Region hash + *----------------------------------------------------------------*/ + +/* + * States a region can have. + */ +enum { + RH_CLEAN = 0x01, /* No writes in flight. */ + RH_DIRTY = 0x02, /* Writes in flight. */ + RH_NOSYNC = 0x04, /* Out of sync. */ + RH_RECOVERING = 0x08, /* Under resynchronization. */ + RH_ERROR = 0x10, /* Error recovering region */ +}; + +/* + * Conversion fns + */ +region_t rh_bio_to_region(void *rh, struct bio *bio); +region_t rh_sector_to_region(void *rh, sector_t sector); +sector_t rh_region_to_sector(void *rh, region_t region); + + +/* + * Functions to set a caller context in a region. + */ +void *rh_reg_get_context(void *reg); +void rh_reg_set_context(void *reg, void *context); + +/* + * Reagion hash and region parameters. + */ +region_t rh_get_region_size(void *rh); +sector_t rh_get_region_key(void *reg); + +int rh_init(void **rh, + unsigned int max_recovery, + void (*dispatch)(void *dispatch_context, struct bio_list *bios), + void *dispatch_context, + void (*wake)(void *wake_context), + void *wake_context, + struct dm_dirty_log *log, uint32_t region_size, region_t nr_regions); +void rh_exit(void *rh); + +int rh_state(void *rh, region_t region, int may_block); +void rh_update_states(void *rh); +void rh_flush(void *rh); + +void rh_inc(void *rh, region_t region); +void rh_inc_pending(void *rh, struct bio_list *bios); +void rh_dec(void *rh, region_t region); +void rh_delay(void *rh, struct bio *bio); +void rh_delay_by_region(void *rh, struct bio *bio, region_t region); + +int rh_recovery_prepare(void *rh); +void *rh_recovery_start(void *rh); +void rh_recovery_end(void *reg, int error); +void rh_stop_recovery(void *rh); +void rh_start_recovery(void *rh); + +#endif --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-region_hash.c +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-region_hash.c @@ -0,0 +1,643 @@ +/* + * Copyright (C) 2003 Sistina Software Limited. + * Copyright (C) 2004-2007 Red Hat Inc. + * + * This file is released under the GPL. + */ + +#include "dm.h" +#include +#include "dm-region_hash.h" + +#include +#include +#include +#include + +#define DM_MSG_PREFIX "region hash" + +/*----------------------------------------------------------------- + * Region hash + * + * The set splits itself up into discrete regions. + * Each region can be in one of three states: + * + * o clean + * o dirty, + * o nosync. + * + * There is no need to put clean regions in the hash. + * + * + * In addition to being present in the hash table a region _may_ + * be present on one of three lists. + * + * clean_regions: Regions on this list have no io pending to + * them, they are in sync, we are no longer interested in them, + * they are dull. rh_update_states() will remove them from the + * hash table. + * + * quiesced_regions: These regions have been spun down, ready + * for recovery. rh_recovery_start() will remove regions from + * this list and hand them to kmirrord, which will schedule the + * recovery io with kcopyd. + * + * recovered_regions: Regions that kcopyd has successfully + * recovered. rh_update_states() will now schedule any delayed + * io, up the recovery_count, and remove the region from the hash. + * + * There are 2 locks: + * A rw spin lock 'hash_lock' protects just the hash table, + * this is never held in write mode from interrupt context, + * which I believe means that we only have to disable irqs when + * doing a write lock. + * + * An ordinary spin lock 'region_lock' that protects the three + * lists in the region_hash, with the 'state', 'list' and + * 'delayed_bios' fields of the regions. This is used from irq + * context, so all other uses will have to suspend local irqs. + *---------------------------------------------------------------*/ +enum region_hash_flags { + RECOVERY, +}; + +struct region_hash { + unsigned int max_recovery; /* Max # of regions to recover in parallel */ + unsigned long flags; + + /* Callback function to dispatch queued writes on recovered regions. */ + void (*dispatch)(void *context, struct bio_list *bios); + void *dispatch_context; + + /* Callback function to wakeup callers worker thread. */ + void (*wake)(void *context); + void *wake_context; + + uint32_t region_size; + unsigned int region_shift; + + /* holds persistent region state */ + struct dm_dirty_log *log; + + /* hash table */ + rwlock_t hash_lock; + mempool_t *region_pool; + unsigned int mask; + unsigned int nr_buckets; + unsigned int prime; + unsigned int shift; + struct list_head *buckets; + + spinlock_t region_lock; + struct semaphore recovery_count; + struct list_head clean_regions; + struct list_head quiesced_regions; + struct list_head recovered_regions; +}; + +struct region { + struct region_hash *rh; /* FIXME: can we get rid of this ? */ + region_t key; + int state; + void *context; /* Caller context. */ + + struct list_head hash_list; + struct list_head list; + + atomic_t pending; + struct bio_list delayed_bios; +}; + +/* + * Conversion fns + */ +region_t rh_sector_to_region(void *rh, sector_t sector) +{ + return sector >> ((struct region_hash*) rh)->region_shift; +} + +region_t rh_bio_to_region(void *rh, struct bio *bio) +{ + return rh_sector_to_region(rh, bio->bi_sector); +} + +sector_t rh_region_to_sector(void *rh, region_t region) +{ + return region << ((struct region_hash*) rh)->region_shift; +} + +/* + * Retrival fns. + */ +region_t rh_get_region_key(void *reg) +{ + return ((struct region *)reg)->key; +} + +sector_t rh_get_region_size(void *rh) +{ + return ((struct region_hash *)rh)->region_size; +} + +/* Squirrel a context with a region. */ +void *rh_reg_get_context(void *reg) +{ + return ((struct region*) reg)->context; +} + +void rh_reg_set_context(void *reg, void *context) +{ + ((struct region*) reg)->context = context; +} + +/* + * Region struct allocation/free. + */ +static void *region_alloc(unsigned int gfp_mask, void *pool_data) +{ + return kmalloc(sizeof(struct region), gfp_mask); +} + +static void region_free(void *element, void *pool_data) +{ + kfree(element); +} + +#define MIN_REGIONS 64 +int rh_init(void **region_hash, + unsigned int max_recovery, + + void (*dispatch)(void *dispatch_context, struct bio_list *bios), + void *dispatch_context, + void (*wake)(void *wake_context), + void *wake_context, + struct dm_dirty_log *log, uint32_t region_size, region_t nr_regions) +{ + unsigned int nr_buckets, max_buckets; + unsigned hash_primes[] = { + /* Table of primes for rh_hash/table size optimization. */ + 3, 7, 13, 27, 53, 97, 193, 389, 769, + 1543, 3079, 6151, 12289, 24593, + }; + size_t i; + struct region_hash *rh; + + if (region_size & (region_size - 1)) { + DMERR("region size must be 2^^n"); + return -EINVAL; + } + + rh = kmalloc(sizeof(*rh), GFP_KERNEL); + if (!rh) { + DMERR("unable to allocate region hash memory"); + return -ENOMEM; + } + + rh->max_recovery = max_recovery; + rh->dispatch = dispatch; + rh->dispatch_context = dispatch_context; + rh->wake = wake; + rh->wake_context = wake_context; + rh->log = log; + rh->region_size = region_size; + rh->region_shift = ffs(region_size) - 1; + rwlock_init(&rh->hash_lock); + + /* Calculate a suitable number of buckets for our hash table. */ + max_buckets = nr_regions >> 6; + for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1); + nr_buckets >>= 1; + rh->mask = rh->nr_buckets = nr_buckets; + rh->mask--; + rh->shift = ffs(nr_buckets); + rh->prime = hash_primes[rh->shift - 1]; + if (rh->prime > ARRAY_SIZE(hash_primes) - 2) + rh->prime = ARRAY_SIZE(hash_primes) - 1; + + rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets)); + if (!rh->buckets) { + DMERR("unable to allocate region hash bucket memory"); + vfree(rh); + return -ENOMEM; + } + + for (i = 0; i < nr_buckets; i++) + INIT_LIST_HEAD(rh->buckets + i); + + spin_lock_init(&rh->region_lock); + sema_init(&rh->recovery_count, 0); + INIT_LIST_HEAD(&rh->clean_regions); + INIT_LIST_HEAD(&rh->quiesced_regions); + INIT_LIST_HEAD(&rh->recovered_regions); + + rh->region_pool = mempool_create(MIN_REGIONS, region_alloc, + region_free, NULL); + if (!rh->region_pool) { + vfree(rh->buckets); + vfree(rh); + return -ENOMEM; + } + + *region_hash = rh; + + return 0; +} + +void rh_exit(void *v) +{ + unsigned int h; + struct region *reg, *tmp; + struct region_hash *rh = v; + + BUG_ON(!list_empty(&rh->quiesced_regions)); + + for (h = 0; h < rh->nr_buckets; h++) { + list_for_each_entry_safe(reg, tmp, rh->buckets + h, hash_list) { + BUG_ON(atomic_read(®->pending)); + mempool_free(reg, rh->region_pool); + } + } + + dm_dirty_log_destroy(rh->log); + + if (rh->region_pool) + mempool_destroy(rh->region_pool); + + vfree(rh->buckets); + kfree(rh); +} + +static inline unsigned int rh_hash(struct region_hash *rh, region_t region) +{ + return (unsigned int) ((region * rh->prime) >> rh->shift) & rh->mask; +} + +static struct region *__rh_lookup(struct region_hash *rh, region_t region) +{ + struct region *reg; + struct list_head *bucket = rh->buckets + rh_hash(rh, region); + + list_for_each_entry(reg, bucket, hash_list) { + if (reg->key == region) + return reg; + } + + return NULL; +} + +static void __rh_insert(struct region_hash *rh, struct region *reg) +{ + unsigned int h = rh_hash(rh, reg->key); + list_add(®->hash_list, rh->buckets + h); +} + +static struct region *__rh_alloc(struct region_hash *rh, region_t region) +{ + struct region *reg, *nreg; + + read_unlock(&rh->hash_lock); + + nreg = mempool_alloc(rh->region_pool, GFP_NOIO); + nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? + RH_CLEAN : RH_NOSYNC; + nreg->rh = rh; + nreg->key = region; + + INIT_LIST_HEAD(&nreg->list); + + atomic_set(&nreg->pending, 0); + bio_list_init(&nreg->delayed_bios); + + write_lock_irq(&rh->hash_lock); + + reg = __rh_lookup(rh, region); + if (reg) + /* we lost the race */ + mempool_free(nreg, rh->region_pool); + else { + __rh_insert(rh, nreg); + if (nreg->state == RH_CLEAN) { + spin_lock(&rh->region_lock); + list_add(&nreg->list, &rh->clean_regions); + spin_unlock(&rh->region_lock); + } + reg = nreg; + } + + write_unlock_irq(&rh->hash_lock); + read_lock(&rh->hash_lock); + + return reg; +} + +static inline struct region *__rh_find(struct region_hash *rh, region_t region) +{ + struct region *reg; + + reg = __rh_lookup(rh, region); + if (!reg) + reg = __rh_alloc(rh, region); + + return reg; +} + +int rh_state(void *v, region_t region, int may_block) +{ + int r = 0; + struct region *reg; + struct region_hash *rh = v; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + if (reg) + r = reg->state; + read_unlock(&rh->hash_lock); + + if (r) + return r; + + /* + * The region wasn't in the hash, so we fall back to the dirty log. + */ + r = rh->log->type->in_sync(rh->log, region, may_block); + + /* + * Any error from the dirty log (eg. -EWOULDBLOCK) gets + * taken as a RH_NOSYNC + */ + return r == 1 ? RH_CLEAN : RH_NOSYNC; +} + +void rh_update_states(void *v) +{ + struct region *reg, *next; + struct region_hash *rh = v; + LIST_HEAD(clean); + LIST_HEAD(recovered); + + /* + * Quickly grab the lists. + */ + write_lock_irq(&rh->hash_lock); + spin_lock(&rh->region_lock); + if (!list_empty(&rh->clean_regions)) { + list_splice(&rh->clean_regions, &clean); + INIT_LIST_HEAD(&rh->clean_regions); + + list_for_each_entry(reg, &clean, list) + list_del(®->hash_list); + } + + if (!list_empty(&rh->recovered_regions)) { + list_splice(&rh->recovered_regions, &recovered); + INIT_LIST_HEAD(&rh->recovered_regions); + + list_for_each_entry(reg, &recovered, list) + list_del(®->hash_list); + } + + spin_unlock(&rh->region_lock); + write_unlock_irq(&rh->hash_lock); + + /* + * All the regions on the recovered and clean lists have + * now been pulled out of the system, so no need to do + * any more locking. + */ + list_for_each_entry_safe (reg, next, &recovered, list) { + if (reg->state != RH_ERROR) + rh->log->type->clear_region(rh->log, reg->key); + + rh->log->type->set_region_sync(rh->log, reg->key, + reg->state != RH_ERROR); + up(&rh->recovery_count); + if (reg->delayed_bios.head) + rh->dispatch(rh->dispatch_context, ®->delayed_bios); + + mempool_free(reg, rh->region_pool); + } + + list_for_each_entry_safe(reg, next, &clean, list) { + rh->log->type->clear_region(rh->log, reg->key); + mempool_free(reg, rh->region_pool); + } + + rh_flush(rh); +} + +void rh_inc(void *v, region_t region) +{ + struct region *reg; + struct region_hash *rh = v; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + if (reg->state == RH_CLEAN) { + rh->log->type->mark_region(rh->log, reg->key); + + spin_lock_irq(&rh->region_lock); + reg->state = RH_DIRTY; + list_del_init(®->list); /* Take off the clean list. */ + spin_unlock_irq(&rh->region_lock); + } + + atomic_inc(®->pending); + read_unlock(&rh->hash_lock); +} + +void rh_inc_pending(void *v, struct bio_list *bios) +{ + struct bio *bio; + struct region_hash *rh = v; + + for (bio = bios->head; bio; bio = bio->bi_next) + rh_inc(rh, rh_bio_to_region(rh, bio)); +} + +void rh_dec(void *v, region_t region) +{ + unsigned long flags; + struct region *reg; + struct region_hash *rh = v; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + read_unlock(&rh->hash_lock); + + BUG_ON(!reg); + + if (atomic_dec_and_test(®->pending)) { + spin_lock_irqsave(&rh->region_lock, flags); + if (reg->state == RH_RECOVERING) { + list_add_tail(®->list, &rh->quiesced_regions); + } else { + reg->state = RH_CLEAN; + list_add(®->list, &rh->clean_regions); + } + spin_unlock_irqrestore(&rh->region_lock, flags); + } +} + +/* + * Starts quiescing a region in preparation for recovery. + */ +static int __rh_recovery_prepare(struct region_hash *rh) +{ + int r; + struct region *reg; + region_t region; + + /* + * Ask the dirty log what's next. + */ + r = rh->log->type->get_resync_work(rh->log, ®ion); + if (r <= 0) + return r; + + /* + * Get this region, and start it quiescing + * by setting the recovering flag. + */ + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + read_unlock(&rh->hash_lock); + + spin_lock_irq(&rh->region_lock); + + reg->state = RH_RECOVERING; + + /* Already quiesced ? */ + list_del_init(®->list); + if (!atomic_read(®->pending)) + list_add(®->list, &rh->quiesced_regions); + + spin_unlock_irq(&rh->region_lock); + + return 1; +} + +int rh_recovery_prepare(void *v) +{ + struct region_hash *rh = v; + + if (test_bit(RECOVERY, &rh->flags)) { + while (!down_trylock(&rh->recovery_count)) { + if (__rh_recovery_prepare(rh) <= 0) { + up(&rh->recovery_count); + return -ENOENT; + } + } + } + + return 0; +} + +/* + * Returns any quiesced regions. + */ +void *rh_recovery_start(void *v) +{ + struct region *reg = NULL; + struct region_hash *rh = v; + + spin_lock_irq(&rh->region_lock); + if (!list_empty(&rh->quiesced_regions)) { + reg = list_entry(rh->quiesced_regions.next, + struct region, list); + list_del_init(®->list); /* Remove from the quiesced list. */ + } + spin_unlock_irq(&rh->region_lock); + + return (void*) reg; +} + +/* + * Put region on list of recovered ones. + */ +void rh_recovery_end(void *v, int error) +{ + struct region *reg = v; + struct region_hash *rh = reg->rh; + + if (error) + reg->state = RH_ERROR; + + spin_lock_irq(&rh->region_lock); + list_add(®->list, &rh->recovered_regions); + spin_unlock_irq(&rh->region_lock); +} + +void rh_flush(void *v) +{ + struct region_hash *rh = v; + + rh->log->type->flush(rh->log); +} + +void rh_delay_by_region(void *v, struct bio *bio, region_t region) +{ + struct region_hash *rh = v; + struct region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + bio_list_add(®->delayed_bios, bio); + read_unlock(&rh->hash_lock); +} + +void rh_delay(void *v, struct bio *bio) +{ + return rh_delay_by_region(v, bio, rh_bio_to_region(v, bio)); +} + +void rh_stop_recovery(void *v) +{ + int i; + struct region_hash *rh = v; + + clear_bit(RECOVERY, &rh->flags); + rh->wake(rh->wake_context); + + /* wait for any recovering regions */ + for (i = 0; i < rh->max_recovery; i++) + down(&rh->recovery_count); +} + +void rh_start_recovery(void *v) +{ + int i; + struct region_hash *rh = v; + + set_bit(RECOVERY, &rh->flags); + for (i = 0; i < rh->max_recovery; i++) + up(&rh->recovery_count); + + rh->wake(rh->wake_context); +} + +EXPORT_SYMBOL(rh_bio_to_region); +EXPORT_SYMBOL(rh_sector_to_region); +EXPORT_SYMBOL(rh_region_to_sector); +EXPORT_SYMBOL(rh_init); +EXPORT_SYMBOL(rh_exit); +EXPORT_SYMBOL(rh_state); +EXPORT_SYMBOL(rh_update_states); +EXPORT_SYMBOL(rh_flush); +EXPORT_SYMBOL(rh_inc); +EXPORT_SYMBOL(rh_inc_pending); +EXPORT_SYMBOL(rh_dec); +EXPORT_SYMBOL(rh_delay); +EXPORT_SYMBOL(rh_delay_by_region); +EXPORT_SYMBOL(rh_recovery_prepare); +EXPORT_SYMBOL(rh_recovery_start); +EXPORT_SYMBOL(rh_recovery_end); +EXPORT_SYMBOL(rh_stop_recovery); +EXPORT_SYMBOL(rh_start_recovery); +EXPORT_SYMBOL(rh_reg_get_context); +EXPORT_SYMBOL(rh_reg_set_context); +EXPORT_SYMBOL(rh_get_region_key); +EXPORT_SYMBOL(rh_get_region_size); + +MODULE_DESCRIPTION(DM_NAME " region hash"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-raid4-5.h +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-raid4-5.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2006 Red Hat GmbH + * + * Module Author: Heinz Mauelshagen (Mauelshagen@RedHat.com) + * + * This file is released under the GPL. + * + */ + +#ifndef _DM_RAID45_H +#define _DM_RAID45_H + +/* Factor out to dm.h! */ +#define STR_LEN(ptr, str) ptr, str, strlen(ptr) + +enum lock_type { RAID45_EX, RAID45_SHARED }; + +struct dmraid45_locking_type { + /* Request a lock on a stripe. */ + void* (*lock)(sector_t key, enum lock_type type); + + /* Release a lock on a stripe. */ + void (*unlock)(void *lock_handle); + +}; + +#endif --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-mem-cache.c +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-mem-cache.c @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2006,2007 Red Hat GmbH + * + * Module Author: Heinz Mauelshagen + * + * Allocate/free total_pages to a per client page pool. + * Allocate/free memory objects with chunks (1..n) of pages_per_chunk pages + * hanging off. + * + * This file is released under the GPL. + */ + +#define DM_MEM_CACHE_VERSION "0.2" + +#include "dm.h" +#include +#include "dm-mem-cache.h" + +struct dm_mem_cache_client { + spinlock_t lock; + mempool_t *objs_pool; + struct page_list *free_list; + unsigned objects; + unsigned chunks; + unsigned free_pages; + unsigned total_pages; +}; + +/* + * Free pages and page_list elements of client. + */ +static void free_cache_pages(struct page_list *list) +{ + while (list) { + struct page_list *pl = list; + + list = pl->next; + BUG_ON(!pl->page); + __free_page(pl->page); + kfree(pl); + } +} + +/* + * Alloc number of pages and page_list elements as required by client. + */ +static struct page_list *alloc_cache_pages(unsigned pages) +{ + struct page_list *pl, *ret = NULL; + struct page *page; + + while (pages--) { + page = alloc_page(GFP_NOIO); + if (!page) + goto err; + + pl = kmalloc(sizeof(*pl), GFP_NOIO); + if (!pl) { + __free_page(page); + goto err; + } + + pl->page = page; + pl->next = ret; + ret = pl; + } + + return ret; + + err: + free_cache_pages(ret); + return NULL; +} + +/* + * Allocate page_list elements from the pool to chunks of the mem object + */ +static void alloc_chunks(struct dm_mem_cache_client *cl, + struct dm_mem_cache_object *obj, + unsigned pages_per_chunk) +{ + unsigned chunks = cl->chunks; + unsigned long flags; + + local_irq_save(flags); + local_irq_disable(); + while (chunks--) { + unsigned p = pages_per_chunk; + + obj[chunks].pl = NULL; + + while (p--) { + struct page_list *pl; + + /* Take next element from free list */ + spin_lock(&cl->lock); + pl = cl->free_list; + BUG_ON(!pl); + cl->free_list = pl->next; + spin_unlock(&cl->lock); + + pl->next = obj[chunks].pl; + obj[chunks].pl = pl; + } + } + + local_irq_restore(flags); +} + +/* + * Free page_list elements putting them back onto free list + */ +static void free_chunks(struct dm_mem_cache_client *cl, + struct dm_mem_cache_object *obj) +{ + unsigned chunks = cl->chunks; + unsigned long flags; + struct page_list *next, *pl; + + local_irq_save(flags); + local_irq_disable(); + while (chunks--) { + for (pl = obj[chunks].pl; pl; pl = next) { + next = pl->next; + + spin_lock(&cl->lock); + pl->next = cl->free_list; + cl->free_list = pl; + cl->free_pages++; + spin_unlock(&cl->lock); + } + } + + local_irq_restore(flags); +} + +/* + * Create/destroy dm memory cache client resources. + */ +struct dm_mem_cache_client * +dm_mem_cache_client_create(unsigned total_pages, unsigned objects, + unsigned chunks) +{ + struct dm_mem_cache_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + client->objs_pool = mempool_create_kmalloc_pool(objects, chunks * sizeof(struct dm_mem_cache_object)); + if (!client->objs_pool) + goto err; + + client->free_list = alloc_cache_pages(total_pages); + if (!client->free_list) + goto err1; + + spin_lock_init(&client->lock); + client->objects = objects; + client->chunks = chunks; + client->free_pages = client->total_pages = total_pages; + return client; + + err1: + mempool_destroy(client->objs_pool); + err: + kfree(client); + return ERR_PTR(-ENOMEM); +} + +void dm_mem_cache_client_destroy(struct dm_mem_cache_client *cl) +{ + BUG_ON(cl->free_pages != cl->total_pages); + free_cache_pages(cl->free_list); + mempool_destroy(cl->objs_pool); + kfree(cl); +} + +/* + * Grow a clients cache by an amount of pages. + * + * Don't call from interrupt context! + */ +int dm_mem_cache_grow(struct dm_mem_cache_client *cl, + unsigned pages_per_chunk) +{ + unsigned pages = cl->chunks * pages_per_chunk; + struct page_list *pl = alloc_cache_pages(pages), *last = pl; + + if (!pl) + return -ENOMEM; + + while (last->next) + last = last->next; + + spin_lock_irq(&cl->lock); + last->next = cl->free_list; + cl->free_list = pl; + cl->free_pages += pages; + cl->total_pages += pages; + cl->objects++; + spin_unlock_irq(&cl->lock); + + mempool_resize(cl->objs_pool, cl->objects, GFP_NOIO); + return 0; +} + +/* Shrink a clients cache by an amount of pages */ +int dm_mem_cache_shrink(struct dm_mem_cache_client *cl, + unsigned pages_per_chunk) +{ + int r = 0; + unsigned pages = cl->chunks * pages_per_chunk, p = pages; + unsigned long flags; + struct page_list *last = NULL, *pl, *pos; + + spin_lock_irqsave(&cl->lock, flags); + pl = pos = cl->free_list; + while (p-- && pos->next) { + last = pos; + pos = pos->next; + } + + if (++p) + r = -ENOMEM; + else { + cl->free_list = pos; + cl->free_pages -= pages; + cl->total_pages -= pages; + cl->objects--; + last->next = NULL; + } + spin_unlock_irqrestore(&cl->lock, flags); + + if (!r) { + free_cache_pages(pl); + mempool_resize(cl->objs_pool, cl->objects, GFP_NOIO); + } + + return r; +} + +/* + * Allocate/free a memory object + * + * Can be called from interrupt context + */ +struct dm_mem_cache_object *dm_mem_cache_alloc(struct dm_mem_cache_client *cl, + unsigned pages_per_chunk) +{ + int r = 0; + unsigned pages = cl->chunks * pages_per_chunk; + unsigned long flags; + struct dm_mem_cache_object *obj; + + obj = mempool_alloc(cl->objs_pool, GFP_NOIO); + if (!obj) + return ERR_PTR(-ENOMEM); + + spin_lock_irqsave(&cl->lock, flags); + if (pages > cl->free_pages) + r = -ENOMEM; + else + cl->free_pages -= pages; + spin_unlock_irqrestore(&cl->lock, flags); + + if (r) { + mempool_free(obj, cl->objs_pool); + return ERR_PTR(r); + } + + alloc_chunks(cl, obj, pages_per_chunk); + return obj; +} + +void dm_mem_cache_free(struct dm_mem_cache_client *cl, + struct dm_mem_cache_object *obj) +{ + free_chunks(cl, obj); + mempool_free(obj, cl->objs_pool); +} + +EXPORT_SYMBOL(dm_mem_cache_client_create); +EXPORT_SYMBOL(dm_mem_cache_client_destroy); +EXPORT_SYMBOL(dm_mem_cache_alloc); +EXPORT_SYMBOL(dm_mem_cache_free); +EXPORT_SYMBOL(dm_mem_cache_grow); +EXPORT_SYMBOL(dm_mem_cache_shrink); + +MODULE_DESCRIPTION(DM_NAME " dm memory cache"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/dm-raid4-5/BOM +++ linux-2.6.27/ubuntu/dm-raid4-5/BOM @@ -0,0 +1,3 @@ +Downloaded from: http://people.redhat.com/~heinzm/sw/dm/dm-raid45/ +Current Version: 20080221 +Comments: All of the patches to dmraid1/dm-log, etc are upstream. --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-mem-cache.h +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-mem-cache.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2006,2007 Red Hat GmbH + * + * Module Author: Heinz Mauelshagen + * + * Allocate/free total_pages to a per client page pool. + * Allocate/free memory objects with chunks (1..n) of pages_per_chunk pages + * hanging off. + * + * This file is released under the GPL. + */ + +#ifndef _DM_MEM_CACHE_H +#define _DM_MEM_CACHE_H + +#define DM_MEM_CACHE_H_VERSION "0.1" + +#include "dm.h" + +static inline struct page_list *pl_elem(struct page_list *pl, unsigned int p) +{ + while (pl && p--) + pl = pl->next; + + return pl; +} + +struct dm_mem_cache_object { + struct page_list *pl; /* Dynamically allocated array */ + void *private; /* Caller context reference */ +}; + +struct dm_mem_cache_client; + +/* + * Create/destroy dm memory cache client resources. + */ +struct dm_mem_cache_client *dm_mem_cache_client_create( + unsigned int total_pages, unsigned int objects, unsigned int chunks); +void dm_mem_cache_client_destroy(struct dm_mem_cache_client *client); + +/* + * Grow/shrink a dm memory cache client resources. + */ +int dm_mem_cache_grow(struct dm_mem_cache_client *client, unsigned int pages); +int dm_mem_cache_shrink(struct dm_mem_cache_client *client, unsigned int pages); + +/* + * Allocate/free a memory object + */ +struct dm_mem_cache_object * +dm_mem_cache_alloc(struct dm_mem_cache_client *client, + unsigned int pages_per_chunk); +void dm_mem_cache_free(struct dm_mem_cache_client *client, + struct dm_mem_cache_object *object); + +#endif --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-message.h +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-message.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2007 Red Hat GmbH + * + * Module Author: Heinz Mauelshagen + * + * This file is released under the GPL. + * + */ + +#ifndef DM_MESSAGE_H +#define DM_MESSAGE_H + +/* Factor out to dm.h. */ +/* Reference to array end. */ +#define ARRAY_END(a) ((a) + ARRAY_SIZE(a)) + +/* Message return bits. */ +enum dm_message_return { + dm_msg_ret_ambiguous, /* Action ambiguous. */ + dm_msg_ret_inval, /* Action invalid. */ + dm_msg_ret_undef, /* Action undefined. */ + + dm_msg_ret_option, /* Option error. */ + dm_msg_ret_arg, /* Argument error. */ + dm_msg_ret_argcount, /* Argument count error. */ +}; + +/* Message argument type conversions. */ +enum dm_message_argument_type { + dm_msg_base_t, /* Basename string. */ + dm_msg_str_t, /* String. */ + dm_msg_int_t, /* Signed int. */ + dm_msg_uint_t, /* Unsigned int. */ + dm_msg_uint64_t, /* Unsigned int 64. */ +}; + +/* A message option. */ +struct dm_message_option { + unsigned num_options; + char **options; + unsigned long *actions; +}; + +/* Message arguments and types. */ +struct dm_message_argument { + unsigned num_args; + unsigned long **ptr; + enum dm_message_argument_type types[]; +}; + +/* Client message. */ +struct dm_msg { + unsigned long action; /* Identified action. */ + unsigned long ret; /* Return bits. */ + unsigned num_specs; /* # of sepcifications listed. */ + struct dm_msg_spec *specs; /* Specification list. */ + struct dm_msg_spec *spec; /* Specification selected. */ +}; + +/* Secification of the message. */ +struct dm_msg_spec { + const char *cmd; /* Name of the command (i.e. 'bandwidth'). */ + unsigned long action; + struct dm_message_option *options; + struct dm_message_argument *args; + unsigned long parm; /* Parameter to pass through to callback. */ + /* Function to process for action. */ + int (*f) (struct dm_msg *msg, void *context); +}; + +/* Parameter access macros. */ +#define DM_MSG_PARM(msg) ((msg)->spec->parm) + +#define DM_MSG_STR_ARGS(msg, idx) ((char*) *(msg)->spec->args->ptr[idx]) +#define DM_MSG_INT_ARGS(msg, idx) ((int) *(msg)->spec->args->ptr[idx]) +#define DM_MSG_UINT_ARGS(msg, idx) ((unsigned) DM_MSG_INT_ARG(msg, idx)) +#define DM_MSG_UINT64_ARGS(msg, idx) ((uint64_t) *(msg)->spec->args->ptr[idx]) + +#define DM_MSG_STR_ARG(msg) DM_MSG_STR_ARGS(msg, 0) +#define DM_MSG_INT_ARG(msg) DM_MSG_INT_ARGS(msg, 0) +#define DM_MSG_UINT_ARG(msg) DM_MSG_UINT_ARGS(msg, 0) +#define DM_MSG_UINT64_ARG(msg) DM_MSG_UINT64_ARGS(msg, 0) + + +/* Parse a message and its options and optionally call a function back. */ +int dm_message_parse(const char *caller, struct dm_msg *msg, void *context, + int argc, char **argv); + +#endif --- linux-2.6.27.orig/ubuntu/dm-raid4-5/Makefile +++ linux-2.6.27/ubuntu/dm-raid4-5/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS += -I$(srctree)/drivers/md + +obj-$(CONFIG_DM_RAID45) += dm-raid4-5.o dm-mem-cache.o dm-region_hash.o dm-message.o --- linux-2.6.27.orig/ubuntu/dm-raid4-5/dm-message.c +++ linux-2.6.27/ubuntu/dm-raid4-5/dm-message.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2007 Red Hat GmbH + * + * Module Author: Heinz Mauelshagen + * + * This file is released under the GPL. + * + * device-mapper message parser. + * + */ + +#include "dm.h" +#include "dm-message.h" +#include + +#define DM_MSG_PREFIX "dm_message" + +/* Basename of a path. */ +static inline char * +basename(char *s) +{ + char *p = strrchr(s, '/'); + + return p ? p + 1 : s; +} + +/* Get an argument depending on type. */ +static void +message_arguments(struct dm_msg *msg, int argc, char **argv) +{ + + if (argc) { + int i; + struct dm_message_argument *args = msg->spec->args; + + for (i = 0; i < args->num_args; i++) { + int r; + unsigned long **ptr = args->ptr; + enum dm_message_argument_type type = args->types[i]; + + switch (type) { + case dm_msg_base_t: + ((char **) ptr)[i] = basename(argv[i]); + break; + + case dm_msg_str_t: + ((char **) ptr)[i] = argv[i]; + break; + + case dm_msg_int_t: + r = sscanf(argv[i], "%d", ((int **) ptr)[i]); + goto check; + + case dm_msg_uint_t: + r = sscanf(argv[i], "%u", + ((unsigned **) ptr)[i]); + goto check; + + case dm_msg_uint64_t: + r = sscanf(argv[i], "%llu", + ((unsigned long long **) ptr)[i]); + + check: + if (r != 1) { + set_bit(dm_msg_ret_undef, &msg->ret); + set_bit(dm_msg_ret_arg, &msg->ret); + } + } + } + } +} + +/* Parse message options. */ +static void +message_options_parse(struct dm_msg *msg, int argc, char **argv) +{ + int hit = 0; + unsigned long *action; + size_t l1 = strlen(*argv), l_hit = 0; + struct dm_message_option *o = msg->spec->options; + char **option, **option_end = o->options + o->num_options; + + for (option = o->options, action = o->actions; + option < option_end; option++, action++) { + size_t l2 = strlen(*option); + + if (!strnicmp(*argv, *option, min(l1, l2))) { + hit++; + l_hit = l2; + set_bit(*action, &msg->action); + } + } + + /* Assume error. */ + msg->ret = 0; + set_bit(dm_msg_ret_option, &msg->ret); + if (!hit || l1 > l_hit) + set_bit(dm_msg_ret_undef, &msg->ret); /* Undefined option. */ + else if (hit > 1) + set_bit(dm_msg_ret_ambiguous, &msg->ret); /* Ambiguous option.*/ + else { + clear_bit(dm_msg_ret_option, &msg->ret); /* Option OK. */ + message_arguments(msg, --argc, ++argv); + } +} + +static inline void +print_ret(const char *caller, unsigned long ret) +{ + struct { + unsigned long err; + const char *err_str; + } static err_msg[] = { + { dm_msg_ret_ambiguous, "message ambiguous" }, + { dm_msg_ret_inval, "message invalid" }, + { dm_msg_ret_undef, "message undefined" }, + { dm_msg_ret_arg, "message argument" }, + { dm_msg_ret_argcount, "message argument count" }, + { dm_msg_ret_option, "option" }, + }, *e = ARRAY_END(err_msg); + + while (e-- > err_msg) { + if (test_bit(e->err, &ret)) + DMERR("%s %s", caller, e->err_str); + } +} + +/* Parse a message action. */ +int +dm_message_parse(const char *caller, struct dm_msg *msg, void *context, + int argc, char **argv) +{ + int hit = 0; + size_t l1 = strlen(*argv), l_hit = 0; + struct dm_msg_spec *s, *s_hit = NULL, + *s_end = msg->specs + msg->num_specs; + + if (argc < 2) + return -EINVAL; + + for (s = msg->specs; s < s_end; s++) { + size_t l2 = strlen(s->cmd); + + if (!strnicmp(*argv, s->cmd, min(l1, l2))) { + hit++; + l_hit = l2; + s_hit = s; + } + } + + msg->ret = 0; + if (!hit || l1 > l_hit) /* No hit or message string too long. */ + set_bit(dm_msg_ret_undef, &msg->ret); + else if (hit > 1) /* Ambiguous message. */ + set_bit(dm_msg_ret_ambiguous, &msg->ret); + else if (argc - 2 != s_hit->args->num_args) { + set_bit(dm_msg_ret_undef, &msg->ret); + set_bit(dm_msg_ret_argcount, &msg->ret); + } + + if (msg->ret) + goto bad; + + msg->action = 0; + msg->spec = s_hit; + set_bit(s_hit->action, &msg->action); + message_options_parse(msg, --argc, ++argv); + + if (!msg->ret) + return msg->spec->f(msg, context); + + bad: + print_ret(caller, msg->ret); + return -EINVAL; +} +EXPORT_SYMBOL(dm_message_parse); + +MODULE_DESCRIPTION(DM_NAME " device-mapper target message parser"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_drm.c +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_drm.c @@ -0,0 +1,993 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include "via_chrome9_drm.h" +#include "via_chrome9_drv.h" +#include "via_chrome9_mm.h" +#include "via_chrome9_dma.h" +#include "via_chrome9_3d_reg.h" + +#define VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT 10 + + +void __via_chrome9ke_udelay(unsigned long usecs) +{ + unsigned long start; + unsigned long stop; + unsigned long period; + unsigned long wait_period; + struct timespec tval; + +#ifdef NDELAY_LIMIT +#define UDELAY_LIMIT (NDELAY_LIMIT/1000) /* supposed to be 10 msec */ +#else +#define UDELAY_LIMIT (10000) /* 10 msec */ +#endif + + if (usecs > UDELAY_LIMIT) { + start = jiffies; + tval.tv_sec = usecs / 1000000; + tval.tv_nsec = (usecs - tval.tv_sec * 1000000) * 1000; + wait_period = timespec_to_jiffies(&tval); + do { + stop = jiffies; + + if (stop < start) + period = ((unsigned long)-1 - start) + stop + 1; + else + period = stop - start; + + } while (period < wait_period); + } else + udelay(usecs); /* delay value might get checked once again */ +} + +int via_chrome9_ioctl_process_exit(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return 0; +} + +int via_chrome9_ioctl_restore_primary(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + return 0; +} + +void Initialize3DEngine(struct drm_via_chrome9_private *dev_priv) +{ + int i; + unsigned int StageOfTexture; + + if (dev_priv->chip_sub_index == CHIP_H5 || + dev_priv->chip_sub_index == CHIP_H5S1) { + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + 0x00010000); + + for (i = 0; i <= 0x8A; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (unsigned int) i << 24); + } + + /* Initial Texture Stage Setting*/ + for (StageOfTexture = 0; StageOfTexture < 0xf; + StageOfTexture++) { + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00020000 | 0x00000000 | + (StageOfTexture & 0xf)<<24)); + /* *((unsigned int volatile*)(pMapIOPort+HC_REG_TRANS_SET)) = + (0x00020000 | HC_ParaSubType_Tex0 | (StageOfTexture & + 0xf)<<24);*/ + for (i = 0 ; i <= 0x30 ; i++) { + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_Hpara0)) = ((unsigned int) i << 24);*/ + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (unsigned int) i << 24); + } + } + + /* Initial Texture Sampler Setting*/ + for (StageOfTexture = 0; StageOfTexture < 0xf; + StageOfTexture++) { + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00020000 | 0x00020000 | + (StageOfTexture & 0xf)<<24)); + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_TRANS_SET)) = (0x00020000 | 0x00020000 | + ( StageOfTexture & 0xf)<<24);*/ + for (i = 0 ; i <= 0x30 ; i++) { + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_Hpara0)) = ((unsigned int) i << 24);*/ + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (unsigned int) i << 24); + } + } + + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00020000 | 0xfe000000)); + /* *((unsigned int volatile*)(pMapIOPort+HC_REG_TRANS_SET)) = + (0x00020000 | HC_ParaSubType_TexGen);*/ + for (i = 0 ; i <= 0x13 ; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (unsigned int) i << 24); + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_Hpara0)) = ((unsigned int) i << 24);*/ + } + + /* Initial Gamma Table Setting*/ + /* Initial Gamma Table Setting*/ + /* 5 + 4 = 9 (12) dwords*/ + /* sRGB texture is not directly support by H3 hardware. + We have to set the deGamma table for texture sampling.*/ + + /* degamma table*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x15000000)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (30 << 20) | (15 << 10) | (5))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((119 << 20) | (81 << 10) | (52))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((283 << 20) | (219 << 10) | (165))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((535 << 20) | (441 << 10) | (357))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((119 << 20) | (884 << 20) | (757 << 10) | + (640))); + + /* gamma table*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x17000000)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (13 << 20) | (13 << 10) | (13))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (26 << 20) | (26 << 10) | (26))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (39 << 20) | (39 << 10) | (39))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((51 << 20) | (51 << 10) | (51))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((71 << 20) | (71 << 10) | (71))); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (87 << 20) | (87 << 10) | (87)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (113 << 20) | (113 << 10) | (113)); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (135 << 20) | (135 << 10) | (135)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (170 << 20) | (170 << 10) | (170)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (199 << 20) | (199 << 10) | (199)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (246 << 20) | (246 << 10) | (246)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (284 << 20) | (284 << 10) | (284)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (317 << 20) | (317 << 10) | (317)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (347 << 20) | (347 << 10) | (347)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (373 << 20) | (373 << 10) | (373)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (398 << 20) | (398 << 10) | (398)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (442 << 20) | (442 << 10) | (442)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (481 << 20) | (481 << 10) | (481)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (517 << 20) | (517 << 10) | (517)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (550 << 20) | (550 << 10) | (550)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (609 << 20) | (609 << 10) | (609)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (662 << 20) | (662 << 10) | (662)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (709 << 20) | (709 << 10) | (709)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (753 << 20) | (753 << 10) | (753)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (794 << 20) | (794 << 10) | (794)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (832 << 20) | (832 << 10) | (832)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (868 << 20) | (868 << 10) | (868)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (902 << 20) | (902 << 10) | (902)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (934 << 20) | (934 << 10) | (934)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (966 << 20) | (966 << 10) | (966)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (996 << 20) | (996 << 10) | (996)); + + + /* + For Interrupt Restore only All types of write through + regsiters should be write header data to hardware at + least before it can restore. H/W will automatically + record the header to write through state buffer for + resture usage. + By Jaren: + HParaType = 8'h03, HParaSubType = 8'h00 + 8'h11 + 8'h12 + 8'h14 + 8'h15 + 8'h17 + HParaSubType 8'h12, 8'h15 is initialized. + [HWLimit] + 1. All these write through registers can't be partial + update. + 2. All these write through must be AGP command + 16 entries : 4 128-bit data */ + + /* Initialize INV_ParaSubType_TexPal */ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x00000000)); + for (i = 0; i < 16; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x00000000); + } + + /* Initialize INV_ParaSubType_4X4Cof */ + /* 32 entries : 8 128-bit data */ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x11000000)); + for (i = 0; i < 32; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x00000000); + } + + /* Initialize INV_ParaSubType_StipPal */ + /* 5 entries : 2 128-bit data */ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x14000000)); + for (i = 0; i < (5+3); i++) { + SetMMIORegister(dev_priv->mmio->handle, + 0x440, 0x00000000); + } + + /* primitive setting & vertex format*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00040000 | 0x14000000)); + for (i = 0; i < 52; i++) { + SetMMIORegister(dev_priv->mmio->handle, + 0x440, ((unsigned int) i << 24)); + } + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + 0x00fe0000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x4000840f); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x47000400); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x44000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x46000000); + + /* setting Misconfig*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + 0x00fe0000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x00001004); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0800004b); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0a000049); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0b0000fb); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0c000001); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0d0000cb); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0e000009); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x10000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x110000ff); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x12000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x130000db); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x14000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x15000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x16000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x17000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x18000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x19000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x20000000); + } else if (dev_priv->chip_sub_index == CHIP_H6S2) { + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + 0x00010000); + for (i = 0; i <= 0x9A; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (unsigned int) i << 24); + } + + /* Initial Texture Stage Setting*/ + for (StageOfTexture = 0; StageOfTexture <= 0xf; + StageOfTexture++) { + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00020000 | 0x00000000 | + (StageOfTexture & 0xf)<<24)); + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_TRANS_SET)) = + (0x00020000 | HC_ParaSubType_Tex0 | + (StageOfTexture & 0xf)<<24);*/ + for (i = 0 ; i <= 0x30 ; i++) { + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_Hpara0)) =((unsigned int) i << 24);*/ + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (unsigned int) i << 24); + } + } + + /* Initial Texture Sampler Setting*/ + for (StageOfTexture = 0; StageOfTexture <= 0xf; + StageOfTexture++) { + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00020000 | 0x20000000 | + (StageOfTexture & 0xf)<<24)); + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_TRANS_SET)) =(0x00020000 | 0x00020000 | + ( StageOfTexture & 0xf)<<24);*/ + for (i = 0 ; i <= 0x36 ; i++) { + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_Hpara0)) =((unsigned int) i << 24);*/ + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (unsigned int) i << 24); + } + } + + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00020000 | 0xfe000000)); + for (i = 0 ; i <= 0x13 ; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (unsigned int) i << 24); + /* *((unsigned int volatile*)(pMapIOPort+ + HC_REG_Hpara0)) =((unsigned int) i << 24);*/ + } + + /* Initial Gamma Table Setting*/ + /* Initial Gamma Table Setting*/ + /* 5 + 4 = 9 (12) dwords*/ + /* sRGB texture is not directly support by + H3 hardware.*/ + /* We have to set the deGamma table for texture + sampling.*/ + + /* degamma table*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x15000000)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (30 << 20) | (15 << 10) | (5))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((119 << 20) | (81 << 10) | (52))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((283 << 20) | (219 << 10) | (165))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((535 << 20) | (441 << 10) | (357))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((119 << 20) | (884 << 20) | (757 << 10) + | (640))); + + /* gamma table*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x17000000)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (13 << 20) | (13 << 10) | (13))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (26 << 20) | (26 << 10) | (26))); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (0x40000000 | (39 << 20) | (39 << 10) | (39))); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, ((51 << 20) | (51 << 10) | (51))); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, ((71 << 20) | (71 << 10) | (71))); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (87 << 20) | (87 << 10) | (87)); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (113 << 20) | (113 << 10) | (113)); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (135 << 20) | (135 << 10) | (135)); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (170 << 20) | (170 << 10) | (170)); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (199 << 20) | (199 << 10) | (199)); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (246 << 20) | (246 << 10) | (246)); + SetMMIORegister(dev_priv->mmio->handle, + 0x440, (284 << 20) | (284 << 10) | (284)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (317 << 20) | (317 << 10) | (317)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (347 << 20) | (347 << 10) | (347)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (373 << 20) | (373 << 10) | (373)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (398 << 20) | (398 << 10) | (398)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (442 << 20) | (442 << 10) | (442)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (481 << 20) | (481 << 10) | (481)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (517 << 20) | (517 << 10) | (517)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (550 << 20) | (550 << 10) | (550)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (609 << 20) | (609 << 10) | (609)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (662 << 20) | (662 << 10) | (662)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (709 << 20) | (709 << 10) | (709)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (753 << 20) | (753 << 10) | (753)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (794 << 20) | (794 << 10) | (794)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (832 << 20) | (832 << 10) | (832)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (868 << 20) | (868 << 10) | (868)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (902 << 20) | (902 << 10) | (902)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (934 << 20) | (934 << 10) | (934)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (966 << 20) | (966 << 10) | (966)); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + (996 << 20) | (996 << 10) | (996)); + + + /* For Interrupt Restore only + All types of write through regsiters should be write + header data to hardware at least before it can restore. + H/W will automatically record the header to write + through state buffer for restureusage. + By Jaren: + HParaType = 8'h03, HParaSubType = 8'h00 + 8'h11 + 8'h12 + 8'h14 + 8'h15 + 8'h17 + HParaSubType 8'h12, 8'h15 is initialized. + [HWLimit] + 1. All these write through registers can't be partial + update. + 2. All these write through must be AGP command + 16 entries : 4 128-bit data */ + + /* Initialize INV_ParaSubType_TexPal */ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x00000000)); + for (i = 0; i < 16; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x00000000); + } + + /* Initialize INV_ParaSubType_4X4Cof */ + /* 32 entries : 8 128-bit data */ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x11000000)); + for (i = 0; i < 32; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x00000000); + } + + /* Initialize INV_ParaSubType_StipPal */ + /* 5 entries : 2 128-bit data */ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00030000 | 0x14000000)); + for (i = 0; i < (5+3); i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x00000000); + } + + /* primitive setting & vertex format*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00040000)); + for (i = 0; i <= 0x62; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((unsigned int) i << 24)); + } + + /*ParaType 0xFE - Configure and Misc Setting*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00fe0000)); + for (i = 0; i <= 0x47; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((unsigned int) i << 24)); + } + /*ParaType 0x11 - Frame Buffer Auto-Swapping and + Command Regulator Misc*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + (0x00110000)); + for (i = 0; i <= 0x20; i++) { + SetMMIORegister(dev_priv->mmio->handle, 0x440, + ((unsigned int) i << 24)); + } + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + 0x00fe0000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x4000840f); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x47000404); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x44000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x46000005); + + /* setting Misconfig*/ + SetMMIORegister(dev_priv->mmio->handle, 0x43C, + 0x00fe0000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x00001004); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x08000249); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0a0002c9); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0b0002fb); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0c000000); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0d0002cb); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x0e000009); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x10000049); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x110002ff); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x12000008); + SetMMIORegister(dev_priv->mmio->handle, 0x440, + 0x130002db); + } +} + +int via_chrome9_drm_resume(struct pci_dev *pci) +{ + struct drm_device *dev = (struct drm_device *)pci_get_drvdata(pci); + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *)dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + dev_priv->dma_manager; + + Initialize3DEngine(dev_priv); + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, 0x00110000); + if (dev_priv->chip_sub_index == CHIP_H6S2) { + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x06000000); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x07100000); + } else{ + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x02000000); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x03100000); + } + + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, + INV_ParaType_PreCR); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + INV_SubA_HSetRBGID | INV_HSetRBGID_CR); + + if (dev_priv->chip_sub_index == CHIP_H6S2) { + unsigned int *pGARTTable; + unsigned int i, entries, GARTOffset; + unsigned char sr6a, sr6b, sr6c, sr6f, sr7b; + unsigned int *addrlinear; + unsigned int size, alignedoffset; + + entries = dev_priv->pagetable_map.pagetable_size / + sizeof(unsigned int); + pGARTTable = dev_priv->pagetable_map.pagetable_handle; + + GARTOffset = dev_priv->pagetable_map.pagetable_offset; + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c &= (~0x80); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + sr6a = (unsigned char)((GARTOffset & 0xff000) >> 12); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6a); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6a); + + sr6b = (unsigned char)((GARTOffset & 0xff00000) >> 20); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6b); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6b); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c |= ((unsigned char)((GARTOffset >> 28) & 0x01)); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x7b); + sr7b = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr7b &= (~0x0f); + sr7b |= ProtectSizeValue(dev_priv-> + pagetable_map.pagetable_size); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr7b); + + for (i = 0; i < entries; i++) + writel(0x80000000, pGARTTable+i); + + /*flush*/ + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f); + do { + sr6f = GetMMIORegisterU8(dev_priv->mmio->handle, + 0x83c5); + } while (sr6f & 0x80); + + sr6f |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + size = lpcmDMAManager->DMASize * sizeof(unsigned int) + + dev_priv->agp_size; + alignedoffset = 0; + entries = (size + PAGE_SIZE - 1) / PAGE_SIZE; + addrlinear = (unsigned int *)dev_priv->pcie_vmalloc_nocache; + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c &= (~0x80); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f); + do { + sr6f = GetMMIORegisterU8(dev_priv->mmio->handle, + 0x83c5); + } while (sr6f & 0x80); + + for (i = 0; i < entries; i++) + writel(page_to_pfn(vmalloc_to_page((void *)addrlinear + + PAGE_SIZE * i)) & 0x3fffffff, pGARTTable+ + i+alignedoffset); + + sr6f |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + } + + if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER) + SetAGPDoubleCmd_inv(dev); + else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER) + SetAGPRingCmdRegs_inv(dev); + return 0; +} + +int via_chrome9_drm_suspend(struct pci_dev *dev, + pm_message_t state) +{ + return 0; +} + +int via_chrome9_driver_load(struct drm_device *dev, + unsigned long chipset) +{ + struct drm_via_chrome9_private *dev_priv; + int ret = 0; + static int associate; + + if (!associate) { + pci_set_drvdata(dev->pdev, dev); + dev->pdev->driver = &dev->driver->pci_driver; + associate = 1; + } + + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; + + dev_priv = drm_calloc(1, sizeof(struct drm_via_chrome9_private), + DRM_MEM_DRIVER); + if (dev_priv == NULL) + return -ENOMEM; + + /* Clear */ + memset(dev_priv, 0, sizeof(struct drm_via_chrome9_private)); + + dev_priv->dev = dev; + dev->dev_private = (void *)dev_priv; + + dev_priv->chip_index = chipset; + + ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); + if (ret) + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + return ret; +} + +int via_chrome9_driver_unload(struct drm_device *dev) +{ + struct drm_via_chrome9_private *dev_priv = dev->dev_private; + + drm_sman_takedown(&dev_priv->sman); + + drm_free(dev_priv, sizeof(struct drm_via_chrome9_private), + DRM_MEM_DRIVER); + + return 0; +} + +static int via_chrome9_initialize(struct drm_device *dev, + struct drm_via_chrome9_init *init) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *)dev->dev_private; + + dev_priv->chip_agp = init->chip_agp; + dev_priv->chip_index = init->chip_index; + dev_priv->chip_sub_index = init->chip_sub_index; + + dev_priv->usec_timeout = init->usec_timeout; + dev_priv->front_offset = init->front_offset; + dev_priv->back_offset = init->back_offset >> + VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT << + VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT; + dev_priv->available_fb_size = init->available_fb_size - + (init->available_fb_size % + (1 << VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT)); + dev_priv->depth_offset = init->depth_offset; + + /* Find all the map added first, doing this is necessary to + intialize hw */ + if (via_chrome9_map_init(dev, init)) { + DRM_ERROR("function via_chrome9_map_init ERROR !\n"); + goto error; + } + + /* Necessary information has been gathered for initialize hw */ + if (via_chrome9_hw_init(dev, init)) { + DRM_ERROR("function via_chrome9_hw_init ERROR !\n"); + goto error; + } + + /* After hw intialization, we have kown whether to use agp + or to use pcie for texture */ + if (via_chrome9_heap_management_init(dev, init)) { + DRM_ERROR("function \ + via_chrome9_heap_management_init ERROR !\n"); + goto error; + } + + return 0; + +error: + /* all the error recover has been processed in relevant function, + so here just return error */ + return -EINVAL; +} + +static void via_chrome9_cleanup(struct drm_device *dev, + struct drm_via_chrome9_init *init) +{ + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = NULL; + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *)dev->dev_private; + DRM_DEBUG("function via_chrome9_cleanup run!\n"); + + if (!dev_priv) + return ; + + lpcmDMAManager = + (struct drm_via_chrome9_DMA_manager *)dev_priv->dma_manager; + if (dev_priv->pcie_vmalloc_nocache) { + vfree((void *)dev_priv->pcie_vmalloc_nocache); + dev_priv->pcie_vmalloc_nocache = 0; + if (lpcmDMAManager) + lpcmDMAManager->addr_linear = NULL; + } + + if (dev_priv->pagetable_map.pagetable_handle) { + iounmap(dev_priv->pagetable_map.pagetable_handle); + dev_priv->pagetable_map.pagetable_handle = NULL; + } + + if (lpcmDMAManager && lpcmDMAManager->addr_linear) { + iounmap(lpcmDMAManager->addr_linear); + lpcmDMAManager->addr_linear = NULL; + } + + kfree(lpcmDMAManager); + dev_priv->dma_manager = NULL; + + if (dev_priv->event_tag_info) { + vfree(dev_priv->event_tag_info); + dev_priv->event_tag_info = NULL; + } + + if (dev_priv->bci_buffer) { + vfree(dev_priv->bci_buffer); + dev_priv->bci_buffer = NULL; + } + + via_chrome9_memory_destroy_heap(dev, dev_priv); +} + +/* +Do almost everything intialize here,include: +1.intialize all addmaps in private data structure +2.intialize memory heap management for video agp/pcie +3.intialize hw for dma(pcie/agp) function + +Note:all this function will dispatch into relevant function +*/ +int via_chrome9_ioctl_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_via_chrome9_init *init = (struct drm_via_chrome9_init *)data; + + switch (init->func) { + case VIA_CHROME9_INIT: + if (via_chrome9_initialize(dev, init)) { + DRM_ERROR("function via_chrome9_initialize error\n"); + return -1; + } + break; + + case VIA_CHROME9_CLEANUP: + via_chrome9_cleanup(dev, init); + break; + + default: + return -1; + } + + return 0; +} + +int via_chrome9_ioctl_allocate_event_tag(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_via_chrome9_event_tag *event_tag = data; + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *)dev->dev_private; + struct drm_clb_event_tag_info *event_tag_info = + dev_priv->event_tag_info; + unsigned int *event_addr = 0, i = 0; + + for (i = 0; i < NUMBER_OF_EVENT_TAGS; i++) { + if (!event_tag_info->usage[i]) + break; + } + + if (i < NUMBER_OF_EVENT_TAGS) { + event_tag_info->usage[i] = 1; + event_tag->event_offset = i; + event_tag->last_sent_event_value.event_low = 0; + event_tag->current_event_value.event_low = 0; + event_addr = event_tag_info->linear_address + + event_tag->event_offset * 4; + *event_addr = 0; + return 0; + } else { + return -7; + } + + return 0; +} + +int via_chrome9_ioctl_free_event_tag(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *)dev->dev_private; + struct drm_clb_event_tag_info *event_tag_info = + dev_priv->event_tag_info; + struct drm_via_chrome9_event_tag *event_tag = data; + + event_tag_info->usage[event_tag->event_offset] = 0; + return 0; +} + +void via_chrome9_lastclose(struct drm_device *dev) +{ + via_chrome9_cleanup(dev, 0); + return ; +} + +static int via_chrome9_do_wait_vblank(struct drm_via_chrome9_private + *dev_priv) +{ + int i; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + VIA_CHROME9_WRITE8(0x83d4, 0x34); + if ((VIA_CHROME9_READ8(0x83d5)) & 0x8) + return 0; + __via_chrome9ke_udelay(1); + } + + return (-1); +} + +void via_chrome9_preclose(struct drm_device *dev, struct drm_file *file_priv) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_sarea *sarea_priv = NULL; + + if (!dev_priv) + return ; + + sarea_priv = dev_priv->sarea_priv; + if (!sarea_priv) + return ; + + if ((sarea_priv->page_flip == 1) && + (sarea_priv->current_page != VIA_CHROME9_FRONT)) { + volatile unsigned long *bci_base; + if (via_chrome9_do_wait_vblank(dev_priv)) + return; + + bci_base = (volatile unsigned long *)(dev_priv->bci); + + BCI_SET_STREAM_REGISTER(bci_base, 0x81c4, 0xc0000000); + BCI_SET_STREAM_REGISTER(bci_base, 0x81c0, + dev_priv->front_offset); + BCI_SEND(bci_base, 0x64000000);/* wait vsync */ + + sarea_priv->current_page = VIA_CHROME9_FRONT; + } +} + +int via_chrome9_is_agp(struct drm_device *dev) +{ + /* filter out pcie group which has no AGP device */ + if (dev->pci_device == 0x1122) { + dev->driver->driver_features &= + ~(DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_REQUIRE_AGP); + return 0; + } + return 1; +} + --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_3d_reg.h +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_3d_reg.h @@ -0,0 +1,398 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef VIA_CHROME9_3D_REG_H +#define VIA_CHROME9_3D_REG_H + +#include + +#define GetMMIORegister(base, offset) \ + (*(volatile unsigned int *)(void *)(((unsigned char *)(base)) + \ + (offset))) +#define SetMMIORegister(base, offset, val) \ + (*(volatile unsigned int *)(void *)(((unsigned char *)(base)) + \ + (offset)) = (val)) + +#define GetMMIORegisterU8(base, offset) \ + (*(volatile unsigned char *)(void *)(((unsigned char *)(base)) + \ + (offset))) +#define SetMMIORegisterU8(base, offset, val) \ + (*(volatile unsigned char *)(void *)(((unsigned char *)(base)) + \ + (offset)) = (val)) + +#define BCI_SEND(bci, value) (*(bci)++ = (unsigned long)(value)) +#define BCI_SET_STREAM_REGISTER(bci_base, bci_index, reg_value) \ +do { \ + unsigned long cmd; \ + \ + cmd = (0x90000000 \ + | (1<<16) /* stream processor register */ \ + | (bci_index & 0x3FFC)); /* MMIO register address */ \ + BCI_SEND(bci_base, cmd); \ + BCI_SEND(bci_base, reg_value); \ + } while (0) + +/* Command Header Type */ + +#define INV_AGPHeader0 0xFE000000 +#define INV_AGPHeader1 0xFE010000 +#define INV_AGPHeader2 0xFE020000 +#define INV_AGPHeader3 0xFE030000 +#define INV_AGPHeader4 0xFE040000 +#define INV_AGPHeader5 0xFE050000 +#define INV_AGPHeader6 0xFE060000 +#define INV_AGPHeader7 0xFE070000 +#define INV_AGPHeader82 0xFE820000 +#define INV_AGPHeader_MASK 0xFFFF0000 + +/*send pause address of AGP ring command buffer via_chrome9 this IO port*/ +#define INV_REG_PCIPAUSE 0x294 +#define INV_REG_PCIPAUSE_ENABLE 0x4 + +#define INV_CMDBUF_THRESHOLD (8) +#define INV_QW_PAUSE_ALIGN 0x40 + +/* Transmission IO Space*/ +#define INV_REG_CR_TRANS 0x041C +#define INV_REG_CR_BEGIN 0x0420 +#define INV_REG_CR_END 0x0438 + +#define INV_REG_3D_TRANS 0x043C +#define INV_REG_3D_BEGIN 0x0440 +#define INV_REG_3D_END 0x06FC +#define INV_REG_23D_WAIT 0x326C +/*3D / 2D ID Control (Only For Group A)*/ +#define INV_REG_2D3D_ID_CTRL 0x060 + + +/* Engine Status */ + +#define INV_RB_ENG_STATUS 0x0400 +#define INV_ENG_BUSY_HQV0 0x00040000 +#define INV_ENG_BUSY_HQV1 0x00020000 +#define INV_ENG_BUSY_CR 0x00000010 +#define INV_ENG_BUSY_MPEG 0x00000008 +#define INV_ENG_BUSY_VQ 0x00000004 +#define INV_ENG_BUSY_2D 0x00000002 +#define INV_ENG_BUSY_3D 0x00001FE1 +#define INV_ENG_BUSY_ALL \ + (INV_ENG_BUSY_2D | INV_ENG_BUSY_3D | INV_ENG_BUSY_CR) + +/* Command Queue Status*/ +#define INV_RB_VQ_STATUS 0x0448 +#define INV_VQ_FULL 0x40000000 + +/* AGP command buffer pointer current position*/ +#define INV_RB_AGPCMD_CURRADDR 0x043C + +/* AGP command buffer status*/ +#define INV_RB_AGPCMD_STATUS 0x0444 +#define INV_AGPCMD_InPause 0x80000000 + +/*AGP command buffer pause address*/ +#define INV_RB_AGPCMD_PAUSEADDR 0x045C + +/*AGP command buffer jump address*/ +#define INV_RB_AGPCMD_JUMPADDR 0x0460 + +/*AGP command buffer start address*/ +#define INV_RB_AGPCMD_STARTADDR 0x0464 + + +/* Constants */ +#define NUMBER_OF_EVENT_TAGS 1024 +#define NUMBER_OF_APERTURES_CLB 16 + +/* Register definition */ +#define HW_SHADOW_ADDR 0x8520 +#define HW_GARTTABLE_ADDR 0x8540 + +#define INV_HSWFlag_DBGMASK 0x00000FFF +#define INV_HSWFlag_ENCODEMASK 0x007FFFF0 +#define INV_HSWFlag_ADDRSHFT 8 +#define INV_HSWFlag_DECODEMASK \ + (INV_HSWFlag_ENCODEMASK << INV_HSWFlag_ADDRSHFT) +#define INV_HSWFlag_ADDR_ENCODE(x) 0xCC000000 +#define INV_HSWFlag_ADDR_DECODE(x) \ + (((unsigned int)x & INV_HSWFlag_DECODEMASK) >> INV_HSWFlag_ADDRSHFT) + + +#define INV_SubA_HAGPBstL 0x60000000 +#define INV_SubA_HAGPBstH 0x61000000 +#define INV_SubA_HAGPBendL 0x62000000 +#define INV_SubA_HAGPBendH 0x63000000 +#define INV_SubA_HAGPBpL 0x64000000 +#define INV_SubA_HAGPBpID 0x65000000 +#define INV_HAGPBpID_PAUSE 0x00000000 +#define INV_HAGPBpID_JUMP 0x00000100 +#define INV_HAGPBpID_STOP 0x00000200 + +#define INV_HAGPBpH_MASK 0x000000FF +#define INV_HAGPBpH_SHFT 0 + +#define INV_SubA_HAGPBjumpL 0x66000000 +#define INV_SubA_HAGPBjumpH 0x67000000 +#define INV_HAGPBjumpH_MASK 0x000000FF +#define INV_HAGPBjumpH_SHFT 0 + +#define INV_SubA_HFthRCM 0x68000000 +#define INV_HFthRCM_MASK 0x003F0000 +#define INV_HFthRCM_SHFT 16 +#define INV_HFthRCM_8 0x00080000 +#define INV_HFthRCM_10 0x000A0000 +#define INV_HFthRCM_18 0x00120000 +#define INV_HFthRCM_24 0x00180000 +#define INV_HFthRCM_32 0x00200000 + +#define INV_HAGPBClear 0x00000008 + +#define INV_HRSTTrig_RestoreAGP 0x00000004 +#define INV_HRSTTrig_RestoreAll 0x00000002 +#define INV_HAGPBTrig 0x00000001 + +#define INV_ParaSubType_MASK 0xff000000 +#define INV_ParaType_MASK 0x00ff0000 +#define INV_ParaOS_MASK 0x0000ff00 +#define INV_ParaAdr_MASK 0x000000ff +#define INV_ParaSubType_SHIFT 24 +#define INV_ParaType_SHIFT 16 +#define INV_ParaOS_SHIFT 8 +#define INV_ParaAdr_SHIFT 0 + +#define INV_ParaType_Vdata 0x00000000 +#define INV_ParaType_Attr 0x00010000 +#define INV_ParaType_Tex 0x00020000 +#define INV_ParaType_Pal 0x00030000 +#define INV_ParaType_FVF 0x00040000 +#define INV_ParaType_PreCR 0x00100000 +#define INV_ParaType_CR 0x00110000 +#define INV_ParaType_Cfg 0x00fe0000 +#define INV_ParaType_Dummy 0x00300000 + +#define INV_HWBasL_MASK 0x00FFFFFF +#define INV_HWBasH_MASK 0xFF000000 +#define INV_HWBasH_SHFT 24 +#define INV_HWBasL(x) ((unsigned int)(x) & INV_HWBasL_MASK) +#define INV_HWBasH(x) ((unsigned int)(x) >> INV_HWBasH_SHFT) +#define INV_HWBas256(x) ((unsigned int)(x) >> 8) +#define INV_HWPit32(x) ((unsigned int)(x) >> 5) + +/* Read Back Register Setting */ +#define INV_SubA_HSetRBGID 0x02000000 +#define INV_HSetRBGID_CR 0x00000000 +#define INV_HSetRBGID_FE 0x00000001 +#define INV_HSetRBGID_PE 0x00000002 +#define INV_HSetRBGID_RC 0x00000003 +#define INV_HSetRBGID_PS 0x00000004 +#define INV_HSetRBGID_XE 0x00000005 +#define INV_HSetRBGID_BE 0x00000006 + + +struct drm_clb_event_tag_info { + unsigned int *linear_address; + unsigned int *event_tag_linear_address; + int usage[NUMBER_OF_EVENT_TAGS]; + unsigned int pid[NUMBER_OF_EVENT_TAGS]; +}; + +static inline int IS_AGPHEADER_INV(unsigned int data) +{ + switch (data & INV_AGPHeader_MASK) { + case INV_AGPHeader0: + case INV_AGPHeader1: + case INV_AGPHeader2: + case INV_AGPHeader3: + case INV_AGPHeader4: + case INV_AGPHeader5: + case INV_AGPHeader6: + case INV_AGPHeader7: + return TRUE; + default: + return FALSE; + } +} + +/* Header0: 2D */ +#define ADDCmdHeader0_INVI(pCmd, dwCount) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader0; \ + *(pCmd)++ = (dwCount); \ + *(pCmd)++ = 0; \ + *(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd); \ +} + +/* Header1: 2D */ +#define ADDCmdHeader1_INVI(pCmd, dwAddr, dwCount) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader1 | (dwAddr); \ + *(pCmd)++ = (dwCount); \ + *(pCmd)++ = 0; \ + *(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd); \ +} + +/* Header2: CR/3D */ +#define ADDCmdHeader2_INVI(pCmd, dwAddr, dwType) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader2 | ((dwAddr)+4); \ + *(pCmd)++ = (dwAddr); \ + *(pCmd)++ = (dwType); \ + *(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd); \ +} + +/* Header2: CR/3D with SW Flag */ +#define ADDCmdHeader2_SWFlag_INVI(pCmd, dwAddr, dwType, dwSWFlag) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader2 | ((dwAddr)+4); \ + *(pCmd)++ = (dwAddr); \ + *(pCmd)++ = (dwType); \ + *(pCmd)++ = (dwSWFlag); \ +} + + +/* Header3: 3D */ +#define ADDCmdHeader3_INVI(pCmd, dwType, dwStart, dwCount) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader3 | INV_REG_3D_TRANS; \ + *(pCmd)++ = (dwCount); \ + *(pCmd)++ = (dwType) | ((dwStart) & 0xFFFF); \ + *(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd); \ +} + +/* Header3: 3D with SW Flag */ +#define ADDCmdHeader3_SWFlag_INVI(pCmd, dwType, dwStart, dwSWFlag, dwCount) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader3 | INV_REG_3D_TRANS; \ + *(pCmd)++ = (dwCount); \ + *(pCmd)++ = (dwType) | ((dwStart) & 0xFFFF); \ + *(pCmd)++ = (dwSWFlag); \ +} + +/* Header4: DVD */ +#define ADDCmdHeader4_INVI(pCmd, dwAddr, dwCount, id) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader4 | (dwAddr); \ + *(pCmd)++ = (dwCount); \ + *(pCmd)++ = (id); \ + *(pCmd)++ = 0; \ +} + +/* Header5: DVD */ +#define ADDCmdHeader5_INVI(pCmd, dwQWcount, id) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader5; \ + *(pCmd)++ = (dwQWcount); \ + *(pCmd)++ = (id); \ + *(pCmd)++ = 0; \ +} + +/* Header6: DEBUG */ +#define ADDCmdHeader6_INVI(pCmd) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader6; \ + *(pCmd)++ = 0; \ + *(pCmd)++ = 0; \ + *(pCmd)++ = 0; \ +} + +/* Header7: DMA */ +#define ADDCmdHeader7_INVI(pCmd, dwQWcount, id) \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader7; \ + *(pCmd)++ = (dwQWcount); \ + *(pCmd)++ = (id); \ + *(pCmd)++ = 0; \ +} + +/* Header82: Branch buffer */ +#define ADDCmdHeader82_INVI(pCmd, dwAddr, dwType); \ +{ \ + /* 4 unsigned int align, insert NULL Command for padding */ \ + while (((unsigned long *)(pCmd)) & 0xF) { \ + *(pCmd)++ = 0xCC000000; \ + } \ + *(pCmd)++ = INV_AGPHeader82 | ((dwAddr)+4); \ + *(pCmd)++ = (dwAddr); \ + *(pCmd)++ = (dwType); \ + *(pCmd)++ = 0xCC000000; \ +} + + +#define ADD2DCmd_INVI(pCmd, dwAddr, dwCmd) \ +{ \ + *(pCmd)++ = (dwAddr); \ + *(pCmd)++ = (dwCmd); \ +} + +#define ADDCmdData_INVI(pCmd, dwCmd) *(pCmd)++ = (dwCmd) + +#define ADDCmdDataStream_INVI(pCmdBuf, pCmd, dwCount) \ +{ \ + memcpy((pCmdBuf), (pCmd), ((dwCount)<<2)); \ + (pCmdBuf) += (dwCount); \ +} + +#endif --- linux-2.6.27.orig/ubuntu/via_chrome9/Kconfig +++ linux-2.6.27/ubuntu/via_chrome9/Kconfig @@ -0,0 +1,6 @@ +config DRM_VIA_CHROME9 + tristate "Via unichrome9 video cards" + depends on DRM + help + Choose this option if you have a Via unichrome9 or compatible video + chipset. If M is selected the module will be called via_chrome9. --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_drv.c +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_drv.c @@ -0,0 +1,160 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "via_chrome9_drm.h" +#include "via_chrome9_drv.h" +#include "via_chrome9_dma.h" +#include "via_chrome9_mm.h" + +#include + +#define via_chrome9DRV_PCI_IDS \ + {0x1106, 0x3225, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_CHROME9_DX9_0}, \ + {0x1106, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x1122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_CHROME9_PCIE_GROUP},\ + {0, 0, 0} + +static int dri_library_name(struct drm_device *dev, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "via_chrome9"); +} + +int via_chrome9_drm_authmagic(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return 0; +} + +struct drm_ioctl_desc via_chrome9_ioctls[] = { + DRM_IOCTL_DEF(DRM_VIA_CHROME9_INIT, via_chrome9_ioctl_init, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),/* via_chrome9_map.c*/ + DRM_IOCTL_DEF(DRM_VIA_CHROME9_FLUSH, via_chrome9_ioctl_flush, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE, via_chrome9_ioctl_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCATE_EVENT_TAG, + via_chrome9_ioctl_allocate_event_tag, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE_EVENT_TAG, + via_chrome9_ioctl_free_event_tag, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCATE_APERTURE, + via_chrome9_ioctl_allocate_aperture, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE_APERTURE, + via_chrome9_ioctl_free_aperture, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCATE_VIDEO_MEM, + via_chrome9_ioctl_allocate_mem_wrapper, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE_VIDEO_MEM, + via_chrome9_ioctl_free_mem_wrapper, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_WAIT_CHIP_IDLE, + via_chrome9_ioctl_wait_chip_idle, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_PROCESS_EXIT, + via_chrome9_ioctl_process_exit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_RESTORE_PRIMARY, + via_chrome9_ioctl_restore_primary, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_FLUSH_CACHE, + via_chrome9_ioctl_flush_cache, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCMEM, + via_chrome9_ioctl_allocate_mem_base, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREEMEM, + via_chrome9_ioctl_freemem_base, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_CHECKVIDMEMSIZE, + via_chrome9_ioctl_check_vidmem_size, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_PCIEMEMCTRL, + via_chrome9_ioctl_pciemem_ctrl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CHROME9_AUTH_MAGIC, via_chrome9_drm_authmagic, 0) +}; + +int via_chrome9_max_ioctl = DRM_ARRAY_SIZE(via_chrome9_ioctls); + +static struct pci_device_id pciidlist[] = { + via_chrome9DRV_PCI_IDS +}; + +int via_chrome9_driver_open(struct drm_device *dev, + struct drm_file *priv) +{ + priv->authenticated = 1; + return 0; +} + +static struct drm_driver driver = { + .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | + DRIVER_HAVE_DMA | DRIVER_FB_DMA | DRIVER_USE_MTRR, + .open = via_chrome9_driver_open, + .load = via_chrome9_driver_load, + .unload = via_chrome9_driver_unload, + .device_is_agp = via_chrome9_is_agp, + .dri_library_name = dri_library_name, + .reclaim_buffers = drm_core_reclaim_buffers, + .reclaim_buffers_locked = NULL, + .reclaim_buffers_idlelocked = via_chrome9_reclaim_buffers_locked, + .lastclose = via_chrome9_lastclose, + .preclose = via_chrome9_preclose, + .get_map_ofs = drm_core_get_map_ofs, + .get_reg_ofs = drm_core_get_reg_ofs, + .ioctls = via_chrome9_ioctls, + .fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .ioctl = drm_ioctl, + .mmap = drm_mmap, + .poll = drm_poll, + .fasync = drm_fasync, + }, + .pci_driver = { + .name = DRIVER_NAME, + .id_table = pciidlist, + .resume = via_chrome9_drm_resume, + .suspend = via_chrome9_drm_suspend, + }, + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +static int __init via_chrome9_init(void) +{ + driver.num_ioctls = via_chrome9_max_ioctl; + driver.dev_priv_size = sizeof(struct drm_via_chrome9_private); + return drm_init(&driver); +} + +static void __exit via_chrome9_exit(void) +{ + drm_exit(&driver); +} + +module_init(via_chrome9_init); +module_exit(via_chrome9_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL and additional rights"); --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_drm.h +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_drm.h @@ -0,0 +1,423 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_CHROME9_DRM_H_ +#define _VIA_CHROME9_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _VIA_CHROME9_DEFINES_ +#define _VIA_CHROME9_DEFINES_ + +#ifndef __KERNEL__ +#include "via_drmclient.h" +#endif + +#define VIA_CHROME9_NR_SAREA_CLIPRECTS 8 +#define VIA_CHROME9_NR_XVMC_PORTS 10 +#define VIA_CHROME9_NR_XVMC_LOCKS 5 +#define VIA_CHROME9_MAX_CACHELINE_SIZE 64 +#define XVMCLOCKPTR(saPriv,lockNo) \ + ((volatile struct drm_hw_lock *) \ + (((((unsigned long) (saPriv)->XvMCLockArea) + \ + (VIA_CHROME9_MAX_CACHELINE_SIZE - 1)) & \ + ~(VIA_CHROME9_MAX_CACHELINE_SIZE - 1)) + \ + VIA_CHROME9_MAX_CACHELINE_SIZE*(lockNo))) + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define VIA_CHROME9_NR_TEX_REGIONS 64 +#define VIA_CHROME9_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define VIA_CHROME9_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define VIA_CHROME9_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define VIA_CHROME9_UPLOAD_CTX 0x4 +#define VIA_CHROME9_UPLOAD_BUFFERS 0x8 +#define VIA_CHROME9_UPLOAD_TEX0 0x10 +#define VIA_CHROME9_UPLOAD_TEX1 0x20 +#define VIA_CHROME9_UPLOAD_CLIPRECTS 0x40 +#define VIA_CHROME9_UPLOAD_ALL 0xff + +/* VIA_CHROME9 specific ioctls */ +#define DRM_VIA_CHROME9_ALLOCMEM 0x00 +#define DRM_VIA_CHROME9_FREEMEM 0x01 +#define DRM_VIA_CHROME9_FREE 0x02 +#define DRM_VIA_CHROME9_ALLOCATE_EVENT_TAG 0x03 +#define DRM_VIA_CHROME9_FREE_EVENT_TAG 0x04 +#define DRM_VIA_CHROME9_ALLOCATE_APERTURE 0x05 +#define DRM_VIA_CHROME9_FREE_APERTURE 0x06 +#define DRM_VIA_CHROME9_ALLOCATE_VIDEO_MEM 0x07 +#define DRM_VIA_CHROME9_FREE_VIDEO_MEM 0x08 +#define DRM_VIA_CHROME9_WAIT_CHIP_IDLE 0x09 +#define DRM_VIA_CHROME9_PROCESS_EXIT 0x0A +#define DRM_VIA_CHROME9_RESTORE_PRIMARY 0x0B +#define DRM_VIA_CHROME9_FLUSH_CACHE 0x0C +#define DRM_VIA_CHROME9_INIT 0x0D +#define DRM_VIA_CHROME9_FLUSH 0x0E +#define DRM_VIA_CHROME9_CHECKVIDMEMSIZE 0x0F +#define DRM_VIA_CHROME9_PCIEMEMCTRL 0x10 +#define DRM_VIA_CHROME9_AUTH_MAGIC 0x11 + +#define DRM_IOCTL_VIA_CHROME9_INIT \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_INIT, \ + struct drm_via_chrome9_init) +#define DRM_IOCTL_VIA_CHROME9_FLUSH \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FLUSH, \ + struct drm_via_chrome9_flush) +#define DRM_IOCTL_VIA_CHROME9_FREE \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE, int) +#define DRM_IOCTL_VIA_CHROME9_ALLOCATE_EVENT_TAG \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCATE_EVENT_TAG, \ + struct drm_event_via_chrome9_tag) +#define DRM_IOCTL_VIA_CHROME9_FREE_EVENT_TAG \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE_EVENT_TAG, \ + struct drm_event_via_chrome9_tag) +#define DRM_IOCTL_VIA_CHROME9_ALLOCATE_APERTURE \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCATE_APERTURE, \ + struct drm_via_chrome9_aperture) +#define DRM_IOCTL_VIA_CHROME9_FREE_APERTURE \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE_APERTURE, \ + struct drm_via_chrome9_aperture) +#define DRM_IOCTL_VIA_CHROME9_ALLOCATE_VIDEO_MEM \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCATE_VIDEO_MEM, \ + struct drm_via_chrome9_memory_alloc) +#define DRM_IOCTL_VIA_CHROME9_FREE_VIDEO_MEM \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE_VIDEO_MEM, \ + struct drm_via_chrome9_memory_alloc) +#define DRM_IOCTL_VIA_CHROME9_WAIT_CHIP_IDLE \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_WAIT_CHIP_IDLE, int) +#define DRM_IOCTL_VIA_CHROME9_PROCESS_EXIT \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_PROCESS_EXIT, int) +#define DRM_IOCTL_VIA_CHROME9_RESTORE_PRIMARY \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_RESTORE_PRIMARY, int) +#define DRM_IOCTL_VIA_CHROME9_FLUSH_CACHE \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FLUSH_CACHE, int) +#define DRM_IOCTL_VIA_CHROME9_ALLOCMEM \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCMEM, int) +#define DRM_IOCTL_VIA_CHROME9_FREEMEM \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREEMEM, int) +#define DRM_IOCTL_VIA_CHROME9_CHECK_VIDMEM_SIZE \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_CHECKVIDMEMSIZE, \ + struct drm_via_chrome9_memory_alloc) +#define DRM_IOCTL_VIA_CHROME9_PCIEMEMCTRL \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_PCIEMEMCTRL,\ + drm_via_chrome9_pciemem_ctrl_t) +#define DRM_IOCTL_VIA_CHROME9_AUTH_MAGIC \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_AUTH_MAGIC, drm_auth_t) + +enum S3GCHIPIDS { + CHIP_UNKNOWN = -1, + CHIP_CMODEL, /*Model for any chip. */ + CHIP_CLB, /*Columbia */ + CHIP_DST, /*Destination */ + CHIP_CSR, /*Castlerock */ + CHIP_INV, /*Innovation (H3) */ + CHIP_H5, /*Innovation (H5) */ + CHIP_H5S1, /*Innovation (H5S1) */ + CHIP_H6S2, /*Innovation (H6S2) */ + CHIP_CMS, /*Columbia MS */ + CHIP_METRO, /*Metropolis */ + CHIP_MANHATTAN, /*manhattan */ + CHIP_MATRIX, /*matrix */ + CHIP_EVO, /*change for GCC 4.1 -add- 07.02.12*/ + CHIP_H6S1, /*Innovation (H6S1)*/ + CHIP_DST2, /*Destination-2 */ + CHIP_LAST /*Maximum number of chips supported. */ +}; + +enum VIA_CHROME9CHIPBUS { + CHIP_PCI, + CHIP_AGP, + CHIP_PCIE +}; + +struct drm_via_chrome9_init { + enum { + VIA_CHROME9_INIT = 0x01, + VIA_CHROME9_CLEANUP = 0x02 + } func; + int chip_agp; + int chip_index; + int chip_sub_index; + int usec_timeout; + unsigned int sarea_priv_offset; + unsigned int fb_cpp; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int mmio_handle; + unsigned int dma_handle; + unsigned int fb_handle; + unsigned int front_handle; + unsigned int back_handle; + unsigned int depth_handle; + + unsigned int fb_tex_offset; + unsigned int fb_tex_size; + + unsigned int agp_tex_size; + unsigned int agp_tex_handle; + unsigned int shadow_size; + unsigned int shadow_handle; + unsigned int garttable_size; + unsigned int garttable_offset; + unsigned long available_fb_size; + unsigned long fb_base_address; + unsigned int DMA_size; + unsigned long DMA_phys_address; + enum { + AGP_RING_BUFFER, + AGP_DOUBLE_BUFFER, + AGP_DISABLED + } agp_type; + unsigned int hostBlt_handle; +}; + +enum dma_cmd_type { + flush_bci = 0, + flush_bci_and_wait, + dma_kickoff, + flush_dma_buffer, + flush_dma_and_wait +}; + +struct drm_via_chrome9_flush { + enum dma_cmd_type dma_cmd_type; + /* command buffer index */ + int cmd_idx; + /* command buffer offset */ + int cmd_offset; + /* command dword size,command always from beginning */ + int cmd_size; + /* if use dma kick off,it is dma kick off command */ + unsigned long dma_kickoff[2]; + /* user mode DMA buffer pointer */ + unsigned int *usermode_dma_buf; +}; + +struct event_value { + int event_low; + int event_high; +}; + +struct drm_via_chrome9_event_tag { + unsigned int event_size; /* event tag size */ + int event_offset; /* event tag id */ + struct event_value last_sent_event_value; + struct event_value current_event_value; + int query_mask0; + int query_mask1; + int query_Id1; +}; + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +#define VIA_CHROME9_TEX_SETUP_SIZE 8 + +/* Flags for clear ioctl + */ +#define VIA_CHROME9_FRONT 0x1 +#define VIA_CHROME9_BACK 0x2 +#define VIA_CHROME9_DEPTH 0x4 +#define VIA_CHROME9_STENCIL 0x8 +#define VIA_CHROME9_MEM_VIDEO 0 /* matches drm constant */ +#define VIA_CHROME9_MEM_AGP 1 /* matches drm constant */ +#define VIA_CHROME9_MEM_SYSTEM 2 +#define VIA_CHROME9_MEM_MIXED 3 +#define VIA_CHROME9_MEM_UNKNOWN 4 + +struct drm_via_chrome9_agp { + uint32_t offset; + uint32_t size; +}; + +struct drm_via_chrome9_fb { + uint32_t offset; + uint32_t size; +}; + +struct drm_via_chrome9_mem { + uint32_t context; + uint32_t type; + uint32_t size; + unsigned long index; + unsigned long offset; +}; + +struct drm_via_chrome9_aperture { + /*IN: The frame buffer offset of the surface. */ + int surface_offset; + /*IN: Surface pitch in byte, */ + int pitch; + /*IN: Surface width in pixel */ + int width; + /*IN: Surface height in pixel */ + int height; + /*IN: Surface color format, Columbia has more color formats */ + int color_format; + /*IN: Rotation degrees, only for Columbia */ + int rotation_degree; + /*IN Is the PCIE Video, for MATRIX support NONLOCAL Aperture */ + int isPCIEVIDEO; + /*IN: Is the surface tilled, only for Columbia */ + int is_tiled; + /*IN: Only allocate apertur, not hardware setup. */ + int allocate_only; + /* OUT: linear address for aperture */ + unsigned int *aperture_linear_address; + /*OUT: The pitch of the aperture,for CPU write not for GE */ + int aperture_pitch; + /*OUT: The index of the aperture */ + int aperture_handle; + int apertureID; + /* always =0xAAAAAAAA */ + /* Aligned surface's width(in pixel) */ + int width_aligned; + /* Aligned surface's height(in pixel) */ + int height_aligned; +}; + +/* + Some fileds of this data structure has no meaning now since + we have managed heap based on mechanism provided by DRM + Remain what it was to keep consistent with 3D driver interface. +*/ +struct drm_via_chrome9_memory_alloc { + enum { + memory_heap_video = 0, + memory_heap_agp, + memory_heap_pcie_video, + memory_heap_pcie, + max_memory_heaps + } heap_type; + struct { + void *lpL1Node; + unsigned int alcL1Tag; + unsigned int usageCount; + unsigned int dwVersion; + unsigned int dwResHandle; + unsigned int dwProcessID; + } heap_info; + unsigned int flags; + unsigned int size; + unsigned int physaddress; + unsigned int offset; + unsigned int align; + void *linearaddress; +}; + +struct drm_via_chrome9_dma_init { + enum { + VIA_CHROME9_INIT_DMA = 0x01, + VIA_CHROME9_CLEANUP_DMA = 0x02, + VIA_CHROME9_DMA_INITIALIZED = 0x03 + } func; + + unsigned long offset; + unsigned long size; + unsigned long reg_pause_addr; +}; + +struct drm_via_chrome9_cmdbuffer { + char __user *buf; + unsigned long size; +}; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +struct drm_via_chrome9_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char inUse; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +}; + +struct drm_via_chrome9_sarea { + int page_flip; + int current_page; + unsigned int req_drawable;/* the X drawable id */ + unsigned int req_draw_buffer;/* VIA_CHROME9_FRONT or VIA_CHROME9_BACK */ + /* Last context that uploaded state */ + int ctx_owner; +}; + +struct drm_via_chrome9_cmdbuf_size { + enum { + VIA_CHROME9_CMDBUF_SPACE = 0x01, + VIA_CHROME9_CMDBUF_LAG = 0x02 + } func; + int wait; + uint32_t size; +}; + +struct drm_via_chrome9_DMA_manager { + unsigned int *addr_linear; + unsigned int DMASize; + unsigned int bDMAAgp; + unsigned int LastIssuedEventTag; + unsigned int *pBeg; + unsigned int *pInUseByHW; + unsigned int **ppInUseByHW; + unsigned int *pInUseBySW; + unsigned int *pFree; + unsigned int *pEnd; + + unsigned long pPhysical; + unsigned int MaxKickoffSize; +}; + +extern int via_chrome9_ioctl_wait_chip_idle(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_init(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_allocate_event_tag(struct drm_device + *dev, void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_free_event_tag(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_driver_load(struct drm_device *dev, + unsigned long chipset); +extern int via_chrome9_driver_unload(struct drm_device *dev); +extern int via_chrome9_ioctl_process_exit(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_restore_primary(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_drm_resume(struct pci_dev *dev); +extern int via_chrome9_drm_suspend(struct pci_dev *dev, + pm_message_t state); +extern void __via_chrome9ke_udelay(unsigned long usecs); +extern void via_chrome9_lastclose(struct drm_device *dev); +extern void via_chrome9_preclose(struct drm_device *dev, + struct drm_file *file_priv); +extern int via_chrome9_is_agp(struct drm_device *dev); + + +#endif /* _VIA_CHROME9_DRM_H_ */ --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_drv.h +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_drv.h @@ -0,0 +1,145 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_CHROME9_DRV_H_ +#define _VIA_CHROME9_DRV_H_ + +#include +#define DRIVER_AUTHOR "Various" + +#define DRIVER_NAME "via_chrome9_chrome9" +#define DRIVER_DESC "VIA_CHROME9 Unichrome / Pro" +#define DRIVER_DATE "20080415" + +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 11 +#define DRIVER_PATCHLEVEL 1 + +#define via_chrome9_PCI_BUF_SIZE 60000 +#define via_chrome9_FIRE_BUF_SIZE 1024 +#define via_chrome9_NUM_IRQS 4 + +#define MAX_MEMORY_HEAPS 4 +#define NUMBER_OF_APERTURES 32 + +/*typedef struct drm_via_chrome9_shadow_map drm_via_chrome9_shadow_map_t;*/ +struct drm_via_chrome9_shadow_map { + struct drm_map *shadow; + unsigned int shadow_size; + unsigned int *shadow_handle; +}; + +/*typedef struct drm_via_chrome9_pagetable_map + *drm_via_chrome9_pagetable_map_t; + */ +struct drm_via_chrome9_pagetable_map { + unsigned int pagetable_offset; + unsigned int pagetable_size; + unsigned int *pagetable_handle; + unsigned int mmt_register; +}; + +/*typedef struct drm_via_chrome9_private drm_via_chrome9_private_t;*/ +struct drm_via_chrome9_private { + int chip_agp; + int chip_index; + int chip_sub_index; + + unsigned long front_offset; + unsigned long back_offset; + unsigned long depth_offset; + unsigned long fb_base_address; + unsigned long available_fb_size; + int usec_timeout; + int max_apertures; + struct drm_sman sman; + unsigned int alignment; + /* bit[31]:0:indicate no alignment needed,1:indicate + alignment needed and size is bit[0:30]*/ + + struct drm_map *sarea; + struct drm_via_chrome9_sarea *sarea_priv; + + struct drm_map *mmio; + struct drm_map *hostBlt; + struct drm_map *fb; + struct drm_map *front; + struct drm_map *back; + struct drm_map *depth; + struct drm_map *agp_tex; + unsigned int agp_size; + unsigned int agp_offset; + + struct semaphore *drm_s3g_sem; + + struct drm_via_chrome9_shadow_map shadow_map; + struct drm_via_chrome9_pagetable_map pagetable_map; + + char *bci; + + int aperture_usage[NUMBER_OF_APERTURES]; + void *event_tag_info; + + /* DMA buffer manager */ + void *dma_manager; + /* Indicate agp/pcie heap initialization flag */ + int agp_initialized; + /* Indicate video heap initialization flag */ + int vram_initialized; + + unsigned long pcie_vmalloc_addr; + + /* pointer to device information */ + void *dev; + /* if agp init fail, go ahead and force dri use PCI*/ + enum { + DRM_AGP_RING_BUFFER, + DRM_AGP_DOUBLE_BUFFER, + DRM_AGP_DISABLED + } drm_agp_type; + /*end*/ + + unsigned long *bci_buffer; + unsigned long pcie_vmalloc_nocache; +}; + + +enum via_chrome9_family { + VIA_CHROME9_OTHER = 0, /* Baseline */ + VIA_CHROME9_PRO_GROUP_A,/* Another video engine and DMA commands */ + VIA_CHROME9_DX9_0, + VIA_CHROME9_PCIE_GROUP +}; + +/* VIA_CHROME9 MMIO register access */ +#define VIA_CHROME9_BASE ((dev_priv->mmio)) + +#define VIA_CHROME9_READ(reg) DRM_READ32(VIA_CHROME9_BASE, reg) +#define VIA_CHROME9_WRITE(reg, val) DRM_WRITE32(VIA_CHROME9_BASE, reg, val) +#define VIA_CHROME9_READ8(reg) DRM_READ8(VIA_CHROME9_BASE, reg) +#define VIA_CHROME9_WRITE8(reg, val) DRM_WRITE8(VIA_CHROME9_BASE, reg, val) + +#endif --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_dma.c +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_dma.c @@ -0,0 +1,1147 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "via_chrome9_drm.h" +#include "via_chrome9_drv.h" +#include "via_chrome9_3d_reg.h" +#include "via_chrome9_dma.h" + +#define NULLCOMMANDNUMBER 256 +unsigned int NULL_COMMAND_INV[4] = + { 0xCC000000, 0xCD000000, 0xCE000000, 0xCF000000 }; + +void +via_chrome9ke_assert(int a) +{ +} + +unsigned int +ProtectSizeValue(unsigned int size) +{ + unsigned int i; + for (i = 0; i < 8; i++) + if ((size > (1 << (i + 12))) + && (size <= (1 << (i + 13)))) + return (i + 1); + return 0; +} + +static unsigned int +InitPCIEGART(struct drm_via_chrome9_private *dev_priv) +{ + unsigned int *pGARTTable; + unsigned int i, entries, GARTOffset; + unsigned char sr6a, sr6b, sr6c, sr6f, sr7b; + + if (!dev_priv->pagetable_map.pagetable_size) + return 0; + + entries = dev_priv->pagetable_map.pagetable_size / sizeof(unsigned int); + + pGARTTable = + ioremap_nocache(dev_priv->fb_base_address + + dev_priv->pagetable_map.pagetable_offset, + dev_priv->pagetable_map.pagetable_size); + if (pGARTTable) + dev_priv->pagetable_map.pagetable_handle = pGARTTable; + else + return 0; + + /*set gart table base */ + GARTOffset = dev_priv->pagetable_map.pagetable_offset; + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c &= (~0x80); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + sr6a = (unsigned char) ((GARTOffset & 0xff000) >> 12); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6a); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6a); + + sr6b = (unsigned char) ((GARTOffset & 0xff00000) >> 20); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6b); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6b); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c |= ((unsigned char) ((GARTOffset >> 28) & 0x01)); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x7b); + sr7b = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr7b &= (~0x0f); + sr7b |= ProtectSizeValue(dev_priv->pagetable_map.pagetable_size); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr7b); + + for (i = 0; i < entries; i++) + writel(0x80000000, pGARTTable + i); + /*flush */ + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f); + do { + sr6f = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + } + while (sr6f & 0x80) + ; + + sr6f |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + return 1; +} + + +static unsigned int * +AllocAndBindPCIEMemory(struct drm_via_chrome9_private *dev_priv, + unsigned int size, unsigned int offset) +{ + unsigned int *addrlinear; + unsigned int *pGARTTable; + unsigned int entries, alignedoffset, i; + unsigned char sr6c, sr6f; + + if (!size) + return NULL; + + entries = (size + PAGE_SIZE - 1) / PAGE_SIZE; + alignedoffset = (offset + PAGE_SIZE - 1) / PAGE_SIZE; + + if ((entries + alignedoffset) > + (dev_priv->pagetable_map.pagetable_size / sizeof(unsigned int))) + return NULL; + + addrlinear = + __vmalloc(entries * PAGE_SIZE, GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_NOCACHE); + + if (!addrlinear) + return NULL; + + pGARTTable = dev_priv->pagetable_map.pagetable_handle; + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c &= (~0x80); + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f); + do { + sr6f = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + } + while (sr6f & 0x80) + ; + + for (i = 0; i < entries; i++) + writel(page_to_pfn + (vmalloc_to_page((void *) addrlinear + PAGE_SIZE * i)) & + 0x3fffffff, pGARTTable + i + alignedoffset); + + sr6f |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f); + + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c); + sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5); + sr6c |= 0x80; + SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c); + + return addrlinear; + +} + +void +SetAGPDoubleCmd_inv(struct drm_device *dev) +{ + /* we now don't use double buffer */ + return; +} + +void +SetAGPRingCmdRegs_inv(struct drm_device *dev) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + (struct drm_via_chrome9_DMA_manager *) dev_priv->dma_manager; + unsigned int AGPBufLinearBase = 0, AGPBufPhysicalBase = 0; + unsigned long *pFree; + unsigned int dwStart, dwEnd, dwPause, AGPCurrAddr, AGPCurStat, CurrAGP; + unsigned int dwReg60, dwReg61, dwReg62, dwReg63, + dwReg64, dwReg65, dwJump; + + lpcmDMAManager->pFree = lpcmDMAManager->pBeg; + + AGPBufLinearBase = (unsigned int) lpcmDMAManager->addr_linear; + AGPBufPhysicalBase = + (dev_priv->chip_agp == + CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base + + lpcmDMAManager->pPhysical; + /*add shadow offset */ + + CurrAGP = + GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_CURRADDR); + AGPCurStat = + GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_STATUS); + + if (AGPCurStat & INV_AGPCMD_InPause) { + AGPCurrAddr = + GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + pFree = (unsigned long *) (AGPBufLinearBase + AGPCurrAddr - + AGPBufPhysicalBase); + ADDCmdHeader2_INVI(pFree, INV_REG_CR_TRANS, INV_ParaType_Dummy); + if (dev_priv->chip_sub_index == CHIP_H6S2) + do { + ADDCmdData_INVI(pFree, 0xCCCCCCC0); + ADDCmdData_INVI(pFree, 0xDDD00000); + } + while ((u32)((unsigned int) pFree) & 0x7f) + ; + /*for 8*128bit aligned */ + else + do { + ADDCmdData_INVI(pFree, 0xCCCCCCC0); + ADDCmdData_INVI(pFree, 0xDDD00000); + } + while ((u32) ((unsigned int) pFree) & 0x1f) + ; + /*for 256bit aligned */ + dwPause = + (u32) (((unsigned int) pFree) - AGPBufLinearBase + + AGPBufPhysicalBase - 16); + + dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause); + dwReg65 = + INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | + INV_HAGPBpID_STOP; + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, + INV_ParaType_PreCR); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + dwReg64); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + dwReg65); + + while ((GetMMIORegister + (dev_priv->mmio->handle, + INV_RB_ENG_STATUS) & INV_ENG_BUSY_ALL)); + } + dwStart = + (u32) ((unsigned int) lpcmDMAManager->pBeg - AGPBufLinearBase + + AGPBufPhysicalBase); + dwEnd = (u32) ((unsigned int) lpcmDMAManager->pEnd - AGPBufLinearBase + + AGPBufPhysicalBase); + + lpcmDMAManager->pFree = lpcmDMAManager->pBeg; + if (dev_priv->chip_sub_index == CHIP_H6S2) { + ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS, + INV_ParaType_Dummy); + do { + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC0); + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xDDD00000); + } + while ((u32)((unsigned long *) lpcmDMAManager->pFree) & 0x7f) + ; + } + dwJump = 0xFFFFFFF0; + dwPause = + (u32)(((unsigned int) lpcmDMAManager->pFree) - + 16 - AGPBufLinearBase + AGPBufPhysicalBase); + + DRM_DEBUG("dwStart = %08x, dwEnd = %08x, dwPause = %08x\n", dwStart, + dwEnd, dwPause); + + dwReg60 = INV_SubA_HAGPBstL | INV_HWBasL(dwStart); + dwReg61 = INV_SubA_HAGPBstH | INV_HWBasH(dwStart); + dwReg62 = INV_SubA_HAGPBendL | INV_HWBasL(dwEnd); + dwReg63 = INV_SubA_HAGPBendH | INV_HWBasH(dwEnd); + dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause); + dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_PAUSE; + + if (dev_priv->chip_sub_index == CHIP_H6S2) + dwReg60 |= 0x01; + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, + INV_ParaType_PreCR); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg60); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg61); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg62); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg63); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + INV_SubA_HAGPBjumpL | INV_HWBasL(dwJump)); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + INV_SubA_HAGPBjumpH | INV_HWBasH(dwJump)); + + /* Trigger AGP cycle */ + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + INV_SubA_HFthRCM | INV_HFthRCM_10 | INV_HAGPBTrig); + + /*for debug */ + CurrAGP = + GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_CURRADDR); + + lpcmDMAManager->pInUseBySW = lpcmDMAManager->pFree; +} + +/* Do hw intialization and determine whether to use dma or mmio to +talk with hw */ +int +via_chrome9_hw_init(struct drm_device *dev, + struct drm_via_chrome9_init *init) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + unsigned retval = 0; + unsigned int *pGARTTable, *addrlinear = NULL; + int pages; + struct drm_clb_event_tag_info *event_tag_info; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = NULL; + + if (init->chip_agp == CHIP_PCIE) { + dev_priv->pagetable_map.pagetable_offset = + init->garttable_offset; + dev_priv->pagetable_map.pagetable_size = init->garttable_size; + dev_priv->agp_size = init->agp_tex_size; + /*Henry :prepare for PCIE texture buffer */ + } else { + dev_priv->pagetable_map.pagetable_offset = 0; + dev_priv->pagetable_map.pagetable_size = 0; + } + + dev_priv->dma_manager = + kmalloc(sizeof(struct drm_via_chrome9_DMA_manager), GFP_KERNEL); + if (!dev_priv->dma_manager) { + DRM_ERROR("could not allocate system for dma_manager!\n"); + return -ENOMEM; + } + + lpcmDMAManager = + (struct drm_via_chrome9_DMA_manager *) dev_priv->dma_manager; + ((struct drm_via_chrome9_DMA_manager *) + dev_priv->dma_manager)->DMASize = init->DMA_size; + ((struct drm_via_chrome9_DMA_manager *) + dev_priv->dma_manager)->pPhysical = init->DMA_phys_address; + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, 0x00110000); + if (dev_priv->chip_sub_index == CHIP_H6S2) { + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x06000000); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x07100000); + } else { + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x02000000); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + 0x03100000); + } + + /* Specify fence command read back ID */ + /* Default the read back ID is CR */ + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, + INV_ParaType_PreCR); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + INV_SubA_HSetRBGID | INV_HSetRBGID_CR); + + DRM_DEBUG("begin to init\n"); + + if (dev_priv->chip_sub_index == CHIP_H6S2) { + dev_priv->pcie_vmalloc_nocache = 0; + if (dev_priv->pagetable_map.pagetable_size) + retval = InitPCIEGART(dev_priv); + + if (retval && dev_priv->drm_agp_type != DRM_AGP_DISABLED) { + addrlinear = + AllocAndBindPCIEMemory(dev_priv, + lpcmDMAManager->DMASize + + dev_priv->agp_size, 0); + if (addrlinear) { + dev_priv->pcie_vmalloc_nocache = (unsigned long) + addrlinear; + } else { + dev_priv->bci_buffer = + vmalloc(MAX_BCI_BUFFER_SIZE); + dev_priv->drm_agp_type = DRM_AGP_DISABLED; + } + } else { + dev_priv->bci_buffer = vmalloc(MAX_BCI_BUFFER_SIZE); + dev_priv->drm_agp_type = DRM_AGP_DISABLED; + } + } else { + if (dev_priv->drm_agp_type != DRM_AGP_DISABLED) { + pGARTTable = NULL; + addrlinear = (unsigned int *) + ioremap(dev->agp->base + + lpcmDMAManager->pPhysical, + lpcmDMAManager->DMASize); + dev_priv->bci_buffer = NULL; + } else { + dev_priv->bci_buffer = vmalloc(MAX_BCI_BUFFER_SIZE); + /*Homer, BCI path always use this block of memory8 */ + } + } + + /*till here we have known whether support dma or not */ + pages = dev->sg->pages; + event_tag_info = vmalloc(sizeof(struct drm_clb_event_tag_info)); + memset(event_tag_info, 0, sizeof(struct drm_clb_event_tag_info)); + if (!event_tag_info) + return DRM_ERROR(" event_tag_info allocate error!"); + + /* aligned to 16k alignment */ + event_tag_info->linear_address = + (int + *) (((unsigned int) dev_priv->shadow_map.shadow_handle + + 0x3fff) & 0xffffc000); + event_tag_info->event_tag_linear_address = + event_tag_info->linear_address + 3; + dev_priv->event_tag_info = (void *) event_tag_info; + dev_priv->max_apertures = NUMBER_OF_APERTURES_CLB; + + /* Initialize DMA data structure */ + lpcmDMAManager->DMASize /= sizeof(unsigned int); + lpcmDMAManager->pBeg = addrlinear; + lpcmDMAManager->pFree = lpcmDMAManager->pBeg; + lpcmDMAManager->pInUseBySW = lpcmDMAManager->pBeg; + lpcmDMAManager->pInUseByHW = lpcmDMAManager->pBeg; + lpcmDMAManager->LastIssuedEventTag = (unsigned int) (unsigned long *) + lpcmDMAManager->pBeg; + lpcmDMAManager->ppInUseByHW = + (unsigned int **) ((char *) (dev_priv->mmio->handle) + + INV_RB_AGPCMD_CURRADDR); + lpcmDMAManager->bDMAAgp = dev_priv->chip_agp; + lpcmDMAManager->addr_linear = (unsigned int *) addrlinear; + + if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER) { + lpcmDMAManager->MaxKickoffSize = lpcmDMAManager->DMASize >> 1; + lpcmDMAManager->pEnd = + lpcmDMAManager->addr_linear + + (lpcmDMAManager->DMASize >> 1) - 1; + SetAGPDoubleCmd_inv(dev); + if (dev_priv->chip_sub_index == CHIP_H6S2) { + DRM_INFO("DMA buffer initialized finished. "); + DRM_INFO("Use PCIE Double Buffer type!\n"); + DRM_INFO("Total PCIE DMA buffer size = %8d bytes. \n", + lpcmDMAManager->DMASize << 2); + } else { + DRM_INFO("DMA buffer initialized finished. "); + DRM_INFO("Use AGP Double Buffer type!\n"); + DRM_INFO("Total AGP DMA buffer size = %8d bytes. \n", + lpcmDMAManager->DMASize << 2); + } + } else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER) { + lpcmDMAManager->MaxKickoffSize = lpcmDMAManager->DMASize; + lpcmDMAManager->pEnd = + lpcmDMAManager->addr_linear + lpcmDMAManager->DMASize; + SetAGPRingCmdRegs_inv(dev); + if (dev_priv->chip_sub_index == CHIP_H6S2) { + DRM_INFO("DMA buffer initialized finished. \n"); + DRM_INFO("Use PCIE Ring Buffer type!"); + DRM_INFO("Total PCIE DMA buffer size = %8d bytes. \n", + lpcmDMAManager->DMASize << 2); + } else { + DRM_INFO("DMA buffer initialized finished. "); + DRM_INFO("Use AGP Ring Buffer type!\n"); + DRM_INFO("Total AGP DMA buffer size = %8d bytes. \n", + lpcmDMAManager->DMASize << 2); + } + } else if (dev_priv->drm_agp_type == DRM_AGP_DISABLED) { + lpcmDMAManager->MaxKickoffSize = 0x0; + if (dev_priv->chip_sub_index == CHIP_H6S2) + DRM_INFO("PCIE init failed! Use PCI\n"); + else + DRM_INFO("AGP init failed! Use PCI\n"); + } + return 0; +} + +static void +kickoff_bci_inv(struct drm_via_chrome9_private *dev_priv, + struct drm_via_chrome9_flush *dma_info) +{ + u32 HdType, dwQWCount, i, dwCount, Addr1, Addr2, SWPointer, + SWPointerEnd; + unsigned long *pCmdData; + int result; + + /*pCmdData = __s3gke_vmalloc(dma_info->cmd_size<<2); */ + pCmdData = dev_priv->bci_buffer; + + if (!pCmdData) + return; + + result = copy_from_user((int *) pCmdData, dma_info->usermode_dma_buf, + dma_info->cmd_size << 2); + + SWPointer = 0; + SWPointerEnd = (u32) dma_info->cmd_size; + while (SWPointer < SWPointerEnd) { + HdType = pCmdData[SWPointer] & INV_AGPHeader_MASK; + switch (HdType) { + case INV_AGPHeader0: + case INV_AGPHeader5: + dwQWCount = pCmdData[SWPointer + 1]; + SWPointer += 4; + + for (i = 0; i < dwQWCount; i++) { + SetMMIORegister(dev_priv->mmio->handle, + pCmdData[SWPointer], + pCmdData[SWPointer + 1]); + SWPointer += 2; + } + break; + + case INV_AGPHeader1: + dwCount = pCmdData[SWPointer + 1]; + Addr1 = 0x0; + SWPointer += 4; /* skip 128-bit. */ + + for (; dwCount > 0; dwCount--, SWPointer++, + Addr1 += 4) { + SetMMIORegister(dev_priv->hostBlt->handle, + Addr1, pCmdData[SWPointer]); + } + break; + + case INV_AGPHeader4: + dwCount = pCmdData[SWPointer + 1]; + Addr1 = pCmdData[SWPointer] & 0x0000FFFF; + SWPointer += 4; /* skip 128-bit. */ + + for (; dwCount > 0; dwCount--, SWPointer++) + SetMMIORegister(dev_priv->mmio->handle, Addr1, + pCmdData[SWPointer]); + break; + + case INV_AGPHeader2: + Addr1 = pCmdData[SWPointer + 1] & 0xFFFF; + Addr2 = pCmdData[SWPointer] & 0xFFFF; + + /* Write first data (either ParaType or whatever) to + Addr1 */ + SetMMIORegister(dev_priv->mmio->handle, Addr1, + pCmdData[SWPointer + 2]); + SWPointer += 4; + + /* The following data are all written to Addr2, + until another header is met */ + while (!IS_AGPHEADER_INV(pCmdData[SWPointer]) + && (SWPointer < SWPointerEnd)) { + SetMMIORegister(dev_priv->mmio->handle, Addr2, + pCmdData[SWPointer]); + SWPointer++; + } + break; + + case INV_AGPHeader3: + Addr1 = pCmdData[SWPointer] & 0xFFFF; + Addr2 = Addr1 + 4; + dwCount = pCmdData[SWPointer + 1]; + + /* Write first data (either ParaType or whatever) to + Addr1 */ + SetMMIORegister(dev_priv->mmio->handle, Addr1, + pCmdData[SWPointer + 2]); + SWPointer += 4; + + for (i = 0; i < dwCount; i++) { + SetMMIORegister(dev_priv->mmio->handle, Addr2, + pCmdData[SWPointer]); + SWPointer++; + } + break; + + case INV_AGPHeader6: + break; + + case INV_AGPHeader7: + break; + + default: + SWPointer += 4; /* Advance to next header */ + } + + SWPointer = (SWPointer + 3) & ~3; + } +} + +void +kickoff_dma_db_inv(struct drm_device *dev) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + dev_priv->dma_manager; + + u32 BufferSize = (u32) (lpcmDMAManager->pFree - lpcmDMAManager->pBeg); + + unsigned int AGPBufLinearBase = + (unsigned int) lpcmDMAManager->addr_linear; + unsigned int AGPBufPhysicalBase = + (unsigned int) dev->agp->base + lpcmDMAManager->pPhysical; + /*add shadow offset */ + + unsigned int dwStart, dwEnd, dwPause; + unsigned int dwReg60, dwReg61, dwReg62, dwReg63, dwReg64, dwReg65; + unsigned int CR_Status; + + if (BufferSize == 0) + return; + + /* 256-bit alignment of AGP pause address */ + if ((u32) ((unsigned long *) lpcmDMAManager->pFree) & 0x1f) { + ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS, + INV_ParaType_Dummy); + do { + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC0); + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xDDD00000); + } + while (((unsigned int) lpcmDMAManager->pFree) & 0x1f) + ; + } + + dwStart = + (u32) (unsigned long *)lpcmDMAManager->pBeg - + AGPBufLinearBase + AGPBufPhysicalBase; + dwEnd = (u32) (unsigned long *)lpcmDMAManager->pEnd - + AGPBufLinearBase + AGPBufPhysicalBase; + dwPause = + (u32)(unsigned long *)lpcmDMAManager->pFree - + AGPBufLinearBase + AGPBufPhysicalBase - 4; + + dwReg60 = INV_SubA_HAGPBstL | INV_HWBasL(dwStart); + dwReg61 = INV_SubA_HAGPBstH | INV_HWBasH(dwStart); + dwReg62 = INV_SubA_HAGPBendL | INV_HWBasL(dwEnd); + dwReg63 = INV_SubA_HAGPBendH | INV_HWBasH(dwEnd); + dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause); + dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_STOP; + + /* wait CR idle */ + CR_Status = GetMMIORegister(dev_priv->mmio->handle, INV_RB_ENG_STATUS); + while (CR_Status & INV_ENG_BUSY_CR) + CR_Status = + GetMMIORegister(dev_priv->mmio->handle, + INV_RB_ENG_STATUS); + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, + INV_ParaType_PreCR); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg60); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg61); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg62); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg63); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65); + + /* Trigger AGP cycle */ + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, + INV_SubA_HFthRCM | INV_HFthRCM_10 | INV_HAGPBTrig); + + if (lpcmDMAManager->pBeg == lpcmDMAManager->addr_linear) { + /* The second AGP command buffer */ + lpcmDMAManager->pBeg = + lpcmDMAManager->addr_linear + + (lpcmDMAManager->DMASize >> 2); + lpcmDMAManager->pEnd = + lpcmDMAManager->addr_linear + lpcmDMAManager->DMASize; + lpcmDMAManager->pFree = lpcmDMAManager->pBeg; + } else { + /* The first AGP command buffer */ + lpcmDMAManager->pBeg = lpcmDMAManager->addr_linear; + lpcmDMAManager->pEnd = + lpcmDMAManager->addr_linear + + (lpcmDMAManager->DMASize / 2) - 1; + lpcmDMAManager->pFree = lpcmDMAManager->pBeg; + } + CR_Status = GetMMIORegister(dev_priv->mmio->handle, INV_RB_ENG_STATUS); +} + + +void +kickoff_dma_ring_inv(struct drm_device *dev) +{ + unsigned int dwPause, dwReg64, dwReg65; + + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + dev_priv->dma_manager; + + unsigned int AGPBufLinearBase = + (unsigned int) lpcmDMAManager->addr_linear; + unsigned int AGPBufPhysicalBase = + (dev_priv->chip_agp == + CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base + + lpcmDMAManager->pPhysical; + /*add shadow offset */ + + /* 256-bit alignment of AGP pause address */ + if (dev_priv->chip_sub_index == CHIP_H6S2) { + if ((u32) + ((unsigned long *) lpcmDMAManager->pFree) & 0x7f) { + ADDCmdHeader2_INVI(lpcmDMAManager->pFree, + INV_REG_CR_TRANS, + INV_ParaType_Dummy); + do { + ADDCmdData_INVI(lpcmDMAManager->pFree, + 0xCCCCCCC0); + ADDCmdData_INVI(lpcmDMAManager->pFree, + 0xDDD00000); + } + while ((u32)((unsigned long *) lpcmDMAManager->pFree) & + 0x7f) + ; + } + } else { + if ((u32) + ((unsigned long *) lpcmDMAManager->pFree) & 0x1f) { + ADDCmdHeader2_INVI(lpcmDMAManager->pFree, + INV_REG_CR_TRANS, + INV_ParaType_Dummy); + do { + ADDCmdData_INVI(lpcmDMAManager->pFree, + 0xCCCCCCC0); + ADDCmdData_INVI(lpcmDMAManager->pFree, + 0xDDD00000); + } + while ((u32)((unsigned long *) lpcmDMAManager->pFree) & + 0x1f) + ; + } + } + + + dwPause = (u32) ((unsigned long *) lpcmDMAManager->pFree) + - AGPBufLinearBase + AGPBufPhysicalBase - 16; + + dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause); + dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_PAUSE; + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, + INV_ParaType_PreCR); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65); + + lpcmDMAManager->pInUseBySW = lpcmDMAManager->pFree; +} + +static int +waitchipidle_inv(struct drm_via_chrome9_private *dev_priv) +{ + unsigned int count = 50000; + unsigned int eng_status; + unsigned int engine_busy; + + do { + eng_status = + GetMMIORegister(dev_priv->mmio->handle, + INV_RB_ENG_STATUS); + engine_busy = eng_status & INV_ENG_BUSY_ALL; + count--; + } + while (engine_busy && count) + ; + if (count && engine_busy == 0) + return 0; + return -1; +} + +void +get_space_db_inv(struct drm_device *dev, + struct cmd_get_space *lpcmGetSpaceData) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + dev_priv->dma_manager; + + unsigned int dwRequestSize = lpcmGetSpaceData->dwRequestSize; + if (dwRequestSize > lpcmDMAManager->MaxKickoffSize) { + DRM_INFO("too big DMA buffer request!!!\n"); + via_chrome9ke_assert(0); + *lpcmGetSpaceData->pCmdData = (unsigned int) NULL; + return; + } + + if ((lpcmDMAManager->pFree + dwRequestSize) > + (lpcmDMAManager->pEnd - INV_CMDBUF_THRESHOLD * 2)) + kickoff_dma_db_inv(dev); + + *lpcmGetSpaceData->pCmdData = (unsigned int) lpcmDMAManager->pFree; +} + +void +RewindRingAGP_inv(struct drm_device *dev) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + dev_priv->dma_manager; + + unsigned int AGPBufLinearBase = + (unsigned int) lpcmDMAManager->addr_linear; + unsigned int AGPBufPhysicalBase = + (dev_priv->chip_agp == + CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base + + lpcmDMAManager->pPhysical; + /*add shadow offset */ + + unsigned int dwPause, dwJump; + unsigned int dwReg66, dwReg67; + unsigned int dwReg64, dwReg65; + + ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS, + INV_ParaType_Dummy); + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC7); + if (dev_priv->chip_sub_index == CHIP_H6S2) + while ((unsigned int) lpcmDMAManager->pFree & 0x7F) + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC7); + else + while ((unsigned int) lpcmDMAManager->pFree & 0x1F) + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC7); + dwJump = ((u32) ((unsigned long *) lpcmDMAManager->pFree)) + - AGPBufLinearBase + AGPBufPhysicalBase - 16; + + lpcmDMAManager->pFree = lpcmDMAManager->pBeg; + + dwPause = ((u32) ((unsigned long *) lpcmDMAManager->pFree)) + - AGPBufLinearBase + AGPBufPhysicalBase - 16; + + dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause); + dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_PAUSE; + + dwReg66 = INV_SubA_HAGPBjumpL | INV_HWBasL(dwJump); + dwReg67 = INV_SubA_HAGPBjumpH | INV_HWBasH(dwJump); + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, + INV_ParaType_PreCR); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg66); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg67); + + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64); + SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65); + lpcmDMAManager->pInUseBySW = lpcmDMAManager->pFree; +} + + +void +get_space_ring_inv(struct drm_device *dev, + struct cmd_get_space *lpcmGetSpaceData) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + dev_priv->dma_manager; + unsigned int dwUnFlushed; + unsigned int dwRequestSize = lpcmGetSpaceData->dwRequestSize; + + unsigned int AGPBufLinearBase = + (unsigned int) lpcmDMAManager->addr_linear; + unsigned int AGPBufPhysicalBase = + (dev_priv->chip_agp == + CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base + + lpcmDMAManager->pPhysical; + /*add shadow offset */ + u32 BufStart, BufEnd, CurSW, CurHW, NextSW, BoundaryCheck; + + dwUnFlushed = + (unsigned int) (lpcmDMAManager->pFree - lpcmDMAManager->pBeg); + /*default bEnableModuleSwitch is on for metro,is off for rest */ + /*cmHW_Module_Switch is context-wide variable which is enough for 2d/3d + switch in a context. */ + /*But we must keep the dma buffer being wrapped head and tail by 3d cmds + when it is kicked off to kernel mode. */ + /*Get DMA Space (If requested, or no BCI space and BCI not forced. */ + + if (dwRequestSize > lpcmDMAManager->MaxKickoffSize) { + DRM_INFO("too big DMA buffer request!!!\n"); + via_chrome9ke_assert(0); + *lpcmGetSpaceData->pCmdData = 0; + return; + } + + if (dwUnFlushed + dwRequestSize > lpcmDMAManager->MaxKickoffSize) + kickoff_dma_ring_inv(dev); + + BufStart = + (u32)((unsigned int) lpcmDMAManager->pBeg) - AGPBufLinearBase + + AGPBufPhysicalBase; + BufEnd = (u32)((unsigned int) lpcmDMAManager->pEnd) - AGPBufLinearBase + + AGPBufPhysicalBase; + dwRequestSize = lpcmGetSpaceData->dwRequestSize << 2; + NextSW = (u32) ((unsigned int) lpcmDMAManager->pFree) + dwRequestSize + + INV_CMDBUF_THRESHOLD * 8 - AGPBufLinearBase + + AGPBufPhysicalBase; + + CurSW = (u32)((unsigned int) lpcmDMAManager->pFree) - AGPBufLinearBase + + AGPBufPhysicalBase; + CurHW = GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_CURRADDR); + + if (NextSW >= BufEnd) { + kickoff_dma_ring_inv(dev); + CurSW = (u32) ((unsigned int) lpcmDMAManager->pFree) - + AGPBufLinearBase + AGPBufPhysicalBase; + /* make sure the last rewind is completed */ + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + while (CurHW > CurSW) + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + /* Sometime the value read from HW is unreliable, + so need double confirm. */ + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + while (CurHW > CurSW) + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + BoundaryCheck = + BufStart + dwRequestSize + INV_QW_PAUSE_ALIGN * 16; + if (BoundaryCheck >= BufEnd) + /* If an empty command buffer can't hold + the request data. */ + via_chrome9ke_assert(0); + else { + /* We need to guarntee the new commands have no chance + to override the unexected commands or wait until there + is no unexecuted commands in agp buffer */ + if (CurSW <= BoundaryCheck) { + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + while (CurHW < CurSW) + CurHW = GetMMIORegister( + dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + /*Sometime the value read from HW is unreliable, + so need double confirm. */ + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + while (CurHW < CurSW) { + CurHW = GetMMIORegister( + dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + } + RewindRingAGP_inv(dev); + CurSW = (u32) ((unsigned long *) + lpcmDMAManager->pFree) - + AGPBufLinearBase + AGPBufPhysicalBase; + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + /* Waiting until hw pointer jump to start + and hw pointer will */ + /* equal to sw pointer */ + while (CurHW != CurSW) { + CurHW = GetMMIORegister( + dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + } + } else { + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + + while (CurHW <= BoundaryCheck) { + CurHW = GetMMIORegister( + dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + } + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + /* Sometime the value read from HW is + unreliable, so need double confirm. */ + while (CurHW <= BoundaryCheck) { + CurHW = GetMMIORegister( + dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + } + RewindRingAGP_inv(dev); + } + } + } else { + /* no need to rewind Ensure unexecuted agp commands will + not be override by new + agp commands */ + CurSW = (u32) ((unsigned int) lpcmDMAManager->pFree) - + AGPBufLinearBase + AGPBufPhysicalBase; + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + + while ((CurHW > CurSW) && (CurHW <= NextSW)) + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + + /* Sometime the value read from HW is unreliable, + so need double confirm. */ + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + while ((CurHW > CurSW) && (CurHW <= NextSW)) + CurHW = GetMMIORegister(dev_priv->mmio->handle, + INV_RB_AGPCMD_CURRADDR); + } + /*return the space handle */ + *lpcmGetSpaceData->pCmdData = (unsigned int) lpcmDMAManager->pFree; +} + +void +release_space_inv(struct drm_device *dev, + struct cmd_release_space *lpcmReleaseSpaceData) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_DMA_manager *lpcmDMAManager = + dev_priv->dma_manager; + unsigned int dwReleaseSize = lpcmReleaseSpaceData->dwReleaseSize; + int i = 0; + + lpcmDMAManager->pFree += dwReleaseSize; + + /* aligned address */ + while (((unsigned int) lpcmDMAManager->pFree) & 0xF) { + /* not in 4 unsigned ints (16 Bytes) align address, + insert NULL Commands */ + *lpcmDMAManager->pFree++ = NULL_COMMAND_INV[i & 0x3]; + i++; + } + + if ((dev_priv->chip_sub_index == CHIP_H5) + && (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER)) { + ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS, + INV_ParaType_Dummy); + for (i = 0; i < NULLCOMMANDNUMBER; i++) + ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCC000000); + } +} + +int +via_chrome9_ioctl_flush(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_via_chrome9_flush *dma_info = data; + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + int ret = 0; + int result = 0; + struct cmd_get_space getspace; + struct cmd_release_space releasespace; + volatile unsigned long *pCmdData = NULL; + + switch (dma_info->dma_cmd_type) { + /* Copy DMA buffer to BCI command buffer */ + case flush_bci: + case flush_bci_and_wait: + if (dma_info->cmd_size <= 0) + return 0; + if (dma_info->cmd_size > MAX_BCI_BUFFER_SIZE) { + DRM_INFO("too big BCI space request!!!\n"); + return 0; + } + + kickoff_bci_inv(dev_priv, dma_info); + waitchipidle_inv(dev_priv); + break; + /* Use DRM DMA buffer manager to kick off DMA directly */ + case dma_kickoff: + break; + + /* Copy user mode DMA buffer to kernel DMA buffer, + then kick off DMA */ + case flush_dma_buffer: + case flush_dma_and_wait: + if (dma_info->cmd_size <= 0) + return 0; + + getspace.dwRequestSize = dma_info->cmd_size; + if ((dev_priv->chip_sub_index == CHIP_H5) + && (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER)) + getspace.dwRequestSize += (NULLCOMMANDNUMBER + 4); + /*henry:Patch for VT3293 agp ring buffer stability */ + getspace.pCmdData = (unsigned int *) &pCmdData; + + if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER) + get_space_db_inv(dev, &getspace); + else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER) + get_space_ring_inv(dev, &getspace); + + if (pCmdData) { + /*copy data from userspace to kernel-dma-agp buffer */ + result = copy_from_user((int *) + pCmdData, + dma_info->usermode_dma_buf, + dma_info->cmd_size << 2); + releasespace.dwReleaseSize = dma_info->cmd_size; + release_space_inv(dev, &releasespace); + + if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER) + kickoff_dma_db_inv(dev); + else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER) + kickoff_dma_ring_inv(dev); + + if (dma_info->dma_cmd_type == flush_dma_and_wait) + waitchipidle_inv(dev_priv); + } else { + DRM_INFO("No enough DMA space"); + ret = -ENOMEM; + } + break; + + default: + DRM_INFO("Invalid DMA buffer type"); + ret = -EINVAL; + break; + } + return ret; +} + +int +via_chrome9_ioctl_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return 0; +} + +int +via_chrome9_ioctl_wait_chip_idle(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + + waitchipidle_inv(dev_priv); + /* maybe_bug here, do we always return 0 */ + return 0; +} + +int +via_chrome9_ioctl_flush_cache(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return 0; +} --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_mm.h +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_mm.h @@ -0,0 +1,67 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_CHROME9_MM_H_ +#define _VIA_CHROME9_MM_H_ +struct drm_via_chrome9_pciemem_ctrl { + enum { + pciemem_copy_from_user = 0, + pciemem_copy_to_user, + pciemem_memset, + } ctrl_type; + unsigned int pcieoffset; + unsigned int size;/*in Byte*/ + unsigned char memsetdata;/*for memset*/ + void *usermode_data;/*user mode data pointer*/ +}; + +extern int via_chrome9_map_init(struct drm_device *dev, + struct drm_via_chrome9_init *init); +extern int via_chrome9_heap_management_init(struct drm_device + *dev, struct drm_via_chrome9_init *init); +extern void via_chrome9_memory_destroy_heap(struct drm_device + *dev, struct drm_via_chrome9_private *dev_priv); +extern int via_chrome9_ioctl_check_vidmem_size(struct drm_device + *dev, void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_pciemem_ctrl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_allocate_aperture(struct drm_device + *dev, void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_free_aperture(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_allocate_mem_base(struct drm_device + *dev, void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_allocate_mem_wrapper( + struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_freemem_base(struct drm_device + *dev, void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_free_mem_wrapper(struct drm_device + *dev, void *data, struct drm_file *file_priv); +extern void via_chrome9_reclaim_buffers_locked(struct drm_device + *dev, struct drm_file *file_priv); + +#endif + --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_mm.c +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_mm.c @@ -0,0 +1,388 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "via_chrome9_drm.h" +#include "via_chrome9_drv.h" +#include +#include "via_chrome9_mm.h" + +#define VIA_CHROME9_MM_GRANULARITY 4 +#define VIA_CHROME9_MM_GRANULARITY_MASK ((1 << VIA_CHROME9_MM_GRANULARITY) - 1) + + +int via_chrome9_map_init(struct drm_device *dev, + struct drm_via_chrome9_init *init) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *)dev->dev_private; + + dev_priv->sarea = drm_getsarea(dev); + if (!dev_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); + goto error; + } + dev_priv->sarea_priv = + (struct drm_via_chrome9_sarea *)((unsigned char *)dev_priv-> + sarea->handle + init->sarea_priv_offset); + + dev_priv->fb = drm_core_findmap(dev, init->fb_handle); + if (!dev_priv->fb) { + DRM_ERROR("could not find framebuffer!\n"); + goto error; + } + /* Frame buffer physical base address */ + dev_priv->fb_base_address = init->fb_base_address; + + if (init->shadow_size) { + /* find apg shadow region mappings */ + dev_priv->shadow_map.shadow = drm_core_findmap(dev, init-> + shadow_handle); + if (!dev_priv->shadow_map.shadow) { + DRM_ERROR("could not shadow map!\n"); + goto error; + } + dev_priv->shadow_map.shadow_size = init->shadow_size; + dev_priv->shadow_map.shadow_handle = (unsigned int *)dev_priv-> + shadow_map.shadow->handle; + init->shadow_handle = dev_priv->shadow_map.shadow->offset; + } + if (init->agp_tex_size && init->chip_agp != CHIP_PCIE) { + /* find apg texture buffer mappings */ + dev_priv->agp_tex = drm_core_findmap(dev, init->agp_tex_handle); + dev_priv->agp_size = init->agp_tex_size; + dev_priv->agp_offset = init->agp_tex_handle; + if (!dev_priv->agp_tex) { + DRM_ERROR("could not find agp texture map !\n"); + goto error; + } + } + /* find mmio/dma mappings */ + dev_priv->mmio = drm_core_findmap(dev, init->mmio_handle); + if (!dev_priv->mmio) { + DRM_ERROR("failed to find mmio region!\n"); + goto error; + } + + dev_priv->hostBlt = drm_core_findmap(dev, init->hostBlt_handle); + if (!dev_priv->hostBlt) { + DRM_ERROR("failed to find host bitblt region!\n"); + goto error; + } + + dev_priv->drm_agp_type = init->agp_type; + if (init->agp_type != AGP_DISABLED && init->chip_agp != CHIP_PCIE) { + dev->agp_buffer_map = drm_core_findmap(dev, init->dma_handle); + if (!dev->agp_buffer_map) { + DRM_ERROR("failed to find dma buffer region!\n"); + goto error; + } + } + + dev_priv->bci = (char *)dev_priv->mmio->handle + 0x10000; + + return 0; + +error: + /* do cleanup here, refine_later */ + return (-EINVAL); +} + +int via_chrome9_heap_management_init(struct drm_device *dev, + struct drm_via_chrome9_init *init) +{ + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + int ret = 0; + + /* video memory management. range: 0 ---- video_whole_size */ + mutex_lock(&dev->struct_mutex); + ret = drm_sman_set_range(&dev_priv->sman, VIA_CHROME9_MEM_VIDEO, + 0, dev_priv->available_fb_size >> VIA_CHROME9_MM_GRANULARITY); + if (ret) { + DRM_ERROR("VRAM memory manager initialization ******ERROR\ + !******\n"); + mutex_unlock(&dev->struct_mutex); + goto error; + } + dev_priv->vram_initialized = 1; + /* agp/pcie heap management. + note:because agp is contradict with pcie, so only one is enough + for managing both of them.*/ + init->agp_type = dev_priv->drm_agp_type; + if (init->agp_type != AGP_DISABLED && dev_priv->agp_size) { + ret = drm_sman_set_range(&dev_priv->sman, VIA_CHROME9_MEM_AGP, + 0, dev_priv->agp_size >> VIA_CHROME9_MM_GRANULARITY); + if (ret) { + DRM_ERROR("AGP/PCIE memory manager initialization ******ERROR\ + !******\n"); + mutex_unlock(&dev->struct_mutex); + goto error; + } + dev_priv->agp_initialized = 1; + } + mutex_unlock(&dev->struct_mutex); + return 0; + +error: + /* Do error recover here, refine_later */ + return -EINVAL; +} + + +void via_chrome9_memory_destroy_heap(struct drm_device *dev, + struct drm_via_chrome9_private *dev_priv) +{ + mutex_lock(&dev->struct_mutex); + drm_sman_cleanup(&dev_priv->sman); + dev_priv->vram_initialized = 0; + dev_priv->agp_initialized = 0; + mutex_unlock(&dev->struct_mutex); +} + +void via_chrome9_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv) +{ + return; +} + +int via_chrome9_ioctl_allocate_aperture(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + return 0; +} + +int via_chrome9_ioctl_free_aperture(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + return 0; +} + + +/* Allocate memory from DRM module for video playing */ +int via_chrome9_ioctl_allocate_mem_base(struct drm_device *dev, +void *data, struct drm_file *file_priv) +{ + struct drm_via_chrome9_mem *mem = data; + struct drm_memblock_item *item; + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + unsigned long tmpSize = 0, offset = 0, alignment = 0; + /* modify heap_type to agp for pcie, since we treat pcie/agp heap + no difference in heap management */ + if (mem->type == memory_heap_pcie) { + if (dev_priv->chip_agp != CHIP_PCIE) { + DRM_ERROR( + "User want to alloc memory from pcie heap but via_chrome9.ko\ + has no this heap exist.******ERROR******\n"); + return -EINVAL; + } + mem->type = memory_heap_agp; + } + + if (mem->type > VIA_CHROME9_MEM_AGP) { + DRM_ERROR("Unknown memory type allocation\n"); + return -EINVAL; + } + mutex_lock(&dev->struct_mutex); + if (0 == ((mem->type == VIA_CHROME9_MEM_VIDEO) ? + dev_priv->vram_initialized : dev_priv->agp_initialized)) { + DRM_ERROR("Attempt to allocate from uninitialized\ + memory manager.\n"); + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + tmpSize = (mem->size + VIA_CHROME9_MM_GRANULARITY_MASK) >> + VIA_CHROME9_MM_GRANULARITY; + mem->size = tmpSize << VIA_CHROME9_MM_GRANULARITY; + alignment = (dev_priv->alignment & 0x80000000) ? dev_priv-> + alignment & 0x7FFFFFFF:0; + alignment /= (1 << VIA_CHROME9_MM_GRANULARITY); + item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, alignment, + (unsigned long)file_priv); + mutex_unlock(&dev->struct_mutex); + /* alloc failed */ + if (!item) { + DRM_ERROR("Allocate memory failed ******ERROR******.\n"); + return -ENOMEM; + } + /* Till here every thing is ok, we check the memory type allocated + and return appropriate value to user mode Here the value return to + user is very difficult to operate. BE CAREFULLY!!! */ + /* offset is used by user mode ap to calculate the virtual address + which is used to access the memory allocated */ + mem->index = item->user_hash.key; + offset = item->mm->offset(item->mm, item->mm_info) << + VIA_CHROME9_MM_GRANULARITY; + switch (mem->type) { + case VIA_CHROME9_MEM_VIDEO: + mem->offset = offset + dev_priv->back_offset; + break; + case VIA_CHROME9_MEM_AGP: + /* return different value to user according to the chip type */ + if (dev_priv->chip_agp == CHIP_PCIE) { + mem->offset = offset + + ((struct drm_via_chrome9_DMA_manager *)dev_priv-> + dma_manager)->DMASize * sizeof(unsigned long); + } else { + mem->offset = offset; + } + break; + default: + /* Strange thing happen! Faint. Code bug! */ + DRM_ERROR("Enter here is impossible ******\ + ERROR******.\n"); + return -EINVAL; + } + /*DONE. Need we call function copy_to_user ?NO. We can't even + touch user's space.But we are lucky, since kernel drm:drm_ioctl + will to the job for us. */ + return 0; +} + +/* Allocate video/AGP/PCIE memory from heap management */ +int via_chrome9_ioctl_allocate_mem_wrapper(struct drm_device + *dev, void *data, struct drm_file *file_priv) +{ + struct drm_via_chrome9_memory_alloc *memory_alloc = + (struct drm_via_chrome9_memory_alloc *)data; + struct drm_via_chrome9_private *dev_priv = + (struct drm_via_chrome9_private *) dev->dev_private; + struct drm_via_chrome9_mem mem; + + mem.size = memory_alloc->size; + mem.type = memory_alloc->heap_type; + dev_priv->alignment = memory_alloc->align | 0x80000000; + if (via_chrome9_ioctl_allocate_mem_base(dev, &mem, file_priv)) { + DRM_ERROR("Allocate memory error!.\n"); + return -ENOMEM; + } + dev_priv->alignment = 0; + /* Till here every thing is ok, we check the memory type allocated and + return appropriate value to user mode Here the value return to user is + very difficult to operate. BE CAREFULLY!!!*/ + /* offset is used by user mode ap to calculate the virtual address + which is used to access the memory allocated */ + memory_alloc->offset = mem.offset; + memory_alloc->heap_info.lpL1Node = (void *)mem.index; + memory_alloc->size = mem.size; + switch (memory_alloc->heap_type) { + case VIA_CHROME9_MEM_VIDEO: + memory_alloc->physaddress = memory_alloc->offset + + dev_priv->fb_base_address; + memory_alloc->linearaddress = (void *)memory_alloc->physaddress; + break; + case VIA_CHROME9_MEM_AGP: + /* return different value to user according to the chip type */ + if (dev_priv->chip_agp == CHIP_PCIE) { + memory_alloc->physaddress = memory_alloc->offset; + memory_alloc->linearaddress = (void *)memory_alloc-> + physaddress; + } else { + memory_alloc->physaddress = dev->agp->base + + memory_alloc->offset + + ((struct drm_via_chrome9_DMA_manager *) + dev_priv->dma_manager)->DMASize * sizeof(unsigned long); + memory_alloc->linearaddress = + (void *)memory_alloc->physaddress; + } + break; + default: + /* Strange thing happen! Faint. Code bug! */ + DRM_ERROR("Enter here is impossible ******ERROR******.\n"); + return -EINVAL; + } + return 0; +} + +int via_chrome9_ioctl_free_mem_wrapper(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_via_chrome9_memory_alloc *memory_alloc = data; + struct drm_via_chrome9_mem mem; + + mem.index = (unsigned long)memory_alloc->heap_info.lpL1Node; + if (via_chrome9_ioctl_freemem_base(dev, &mem, file_priv)) { + DRM_ERROR("function free_mem_wrapper error.\n"); + return -EINVAL; + } + + return 0; +} + +int via_chrome9_ioctl_freemem_base(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_via_chrome9_private *dev_priv = dev->dev_private; + struct drm_via_chrome9_mem *mem = data; + int ret; + + mutex_lock(&dev->struct_mutex); + ret = drm_sman_free_key(&dev_priv->sman, mem->index); + mutex_unlock(&dev->struct_mutex); + DRM_DEBUG("free = 0x%lx\n", mem->index); + + return ret; +} + +int via_chrome9_ioctl_check_vidmem_size(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + return 0; +} + +int via_chrome9_ioctl_pciemem_ctrl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + int result = 0; + struct drm_via_chrome9_private *dev_priv = dev->dev_private; + struct drm_via_chrome9_pciemem_ctrl *pcie_memory_ctrl = data; + switch (pcie_memory_ctrl->ctrl_type) { + case pciemem_copy_from_user: + result = copy_from_user((void *)( + dev_priv->pcie_vmalloc_nocache+ + pcie_memory_ctrl->pcieoffset), + pcie_memory_ctrl->usermode_data, + pcie_memory_ctrl->size); + break; + case pciemem_copy_to_user: + result = copy_to_user(pcie_memory_ctrl->usermode_data, + (void *)(dev_priv->pcie_vmalloc_nocache+ + pcie_memory_ctrl->pcieoffset), + pcie_memory_ctrl->size); + break; + case pciemem_memset: + memset((void *)(dev_priv->pcie_vmalloc_nocache + + pcie_memory_ctrl->pcieoffset), + pcie_memory_ctrl->memsetdata, + pcie_memory_ctrl->size); + break; + default: + break; + } + return 0; +} --- linux-2.6.27.orig/ubuntu/via_chrome9/via_chrome9_dma.h +++ linux-2.6.27/ubuntu/via_chrome9/via_chrome9_dma.h @@ -0,0 +1,68 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * (including the next paragraph) shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_CHROME9_DMA_H_ +#define _VIA_CHROME9_DMA_H_ + +#define MAX_BCI_BUFFER_SIZE 16*1024*1024 + +enum cmd_request_type { + CM_REQUEST_BCI, + CM_REQUEST_DMA, + CM_REQUEST_RB, + CM_REQUEST_RB_FORCED_DMA, + CM_REQUEST_NOTAVAILABLE +}; + +struct cmd_get_space { + unsigned int dwRequestSize; + enum cmd_request_type hint; + volatile unsigned int *pCmdData; +}; + +struct cmd_release_space { + unsigned int dwReleaseSize; +}; + +extern int via_chrome9_hw_init(struct drm_device *dev, + struct drm_via_chrome9_init *init); +extern int via_chrome9_ioctl_flush(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int via_chrome9_ioctl_free(struct drm_device *dev, void *data, + struct drm_file *file_prev); +extern int via_chrome9_ioctl_wait_chip_idle(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_flush_cache(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int via_chrome9_ioctl_flush(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int via_chrome9_ioctl_free(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern unsigned int ProtectSizeValue(unsigned int size); +extern void SetAGPDoubleCmd_inv(struct drm_device *dev); +extern void SetAGPRingCmdRegs_inv(struct drm_device *dev); + +#endif --- linux-2.6.27.orig/ubuntu/via_chrome9/Makefile +++ linux-2.6.27/ubuntu/via_chrome9/Makefile @@ -0,0 +1,3 @@ +via_chrome9-objs := via_chrome9_drv.o via_chrome9_drm.o via_chrome9_mm.o via_chrome9_dma.o + +obj-$(CONFIG_DRM_VIA_CHROME9) += via_chrome9.o --- linux-2.6.27.orig/ubuntu/lirc/lirc.h +++ linux-2.6.27/ubuntu/lirc/lirc.h @@ -0,0 +1,110 @@ +/* $Id: lirc.h,v 5.14 2008/01/12 21:57:57 lirc Exp $ */ + +#ifndef _LINUX_LIRC_H +#define _LINUX_LIRC_H + +#if defined(__linux__) +#include +#include +#else +#include +#if defined(__NetBSD__) +#include +#endif +typedef u_int32_t __u32; +#endif + +#define PULSE_BIT 0x01000000 +#define PULSE_MASK 0x00FFFFFF + +typedef int lirc_t; + +/* + * lirc compatible hardware features + */ + + +#define LIRC_MODE2SEND(x) (x) +#define LIRC_SEND2MODE(x) (x) +#define LIRC_MODE2REC(x) ((x) << 16) +#define LIRC_REC2MODE(x) ((x) >> 16) + +#define LIRC_MODE_RAW 0x00000001 +#define LIRC_MODE_PULSE 0x00000002 +#define LIRC_MODE_MODE2 0x00000004 +#define LIRC_MODE_CODE 0x00000008 +#define LIRC_MODE_LIRCCODE 0x00000010 +#define LIRC_MODE_STRING 0x00000020 + + +#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) +#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) +#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) +#define LIRC_CAN_SEND_CODE LIRC_MODE2SEND(LIRC_MODE_CODE) +#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) +#define LIRC_CAN_SEND_STRING LIRC_MODE2SEND(LIRC_MODE_STRING) + +#define LIRC_CAN_SEND_MASK 0x0000003f + +#define LIRC_CAN_SET_SEND_CARRIER 0x00000100 +#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 +#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 + +#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) +#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) +#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) +#define LIRC_CAN_REC_CODE LIRC_MODE2REC(LIRC_MODE_CODE) +#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) +#define LIRC_CAN_REC_STRING LIRC_MODE2REC(LIRC_MODE_STRING) + +#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) + +#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16) +#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16) + +#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000 +#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 +#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 + +#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) +#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) + +#define LIRC_CAN_NOTIFY_DECODE 0x01000000 + +/* + * IOCTL commands for lirc driver + */ + +#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32) + +#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) +#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) +#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32) +#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32) +#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32) +#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, __u32) +#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) + +/* code length in bits, currently only for LIRC_MODE_LIRCCODE */ +#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) + +#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32) +#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32) +/* Note: these can reset the according pulse_width */ +#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) +#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) +#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) +#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, __u32) +#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) + +/* to set a range use + LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the + lower bound first and later + LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound */ + +#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, __u32) +#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) + +#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) + +#endif --- linux-2.6.27.orig/ubuntu/lirc/kcompat.h +++ linux-2.6.27/ubuntu/lirc/kcompat.h @@ -0,0 +1,369 @@ +/* $Id: kcompat.h,v 5.36 2008/05/14 16:37:49 lirc Exp $ */ + +#ifndef _KCOMPAT_H +#define _KCOMPAT_H + +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) +#define LIRC_THIS_MODULE(x) x, +#else /* >= 2.6.16 */ +#define LIRC_THIS_MODULE(x) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#define LIRC_HAVE_DEVFS +#define LIRC_HAVE_DEVFS_26 +#endif + +#define LIRC_HAVE_SYSFS + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13) + +typedef struct class_simple lirc_class_t; + +static inline lirc_class_t *class_create(struct module *owner, char *name) +{ + return class_simple_create(owner, name); +} + +static inline void class_destroy(lirc_class_t *cls) +{ + class_simple_destroy(cls); +} + +#define lirc_device_create(cs, parent, dev, fmt, args...) \ + class_simple_device_add(cs, dev, parent, fmt, ## args) + +static inline void lirc_device_destroy(lirc_class_t *cls, dev_t devt) +{ + class_simple_device_remove(devt); +} + +#else /* >= 2.6.13 */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) + +#define lirc_device_create(cs, parent, dev, fmt, args...) \ + class_device_create(cs, dev, parent, fmt, ## args) + +#else /* >= 2.6.15 */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + +#define lirc_device_create(cs, parent, dev, fmt, args...) \ + class_device_create(cs, NULL, dev, parent, fmt, ## args) + +#else /* >= 2.6.26 */ + +#define lirc_device_create device_create + +#endif /* >= 2.6.26 */ + +#define LIRC_DEVFS_PREFIX + +#endif /* >= 2.6.15 */ + +typedef struct class lirc_class_t; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + +#define lirc_device_destroy class_device_destroy + +#else + +#define lirc_device_destroy device_destroy + +#endif + +#endif /* >= 2.6.13 */ + +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) +#define LIRC_HAVE_DEVFS +#define LIRC_HAVE_DEVFS_24 +#endif + +#ifndef LIRC_DEVFS_PREFIX +#define LIRC_DEVFS_PREFIX "usb/" +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) +#include +#include +static inline void del_timer_sync(struct timer_list *timerlist) +{ + start_bh_atomic(); + del_timer(timerlist); + end_bh_atomic(); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +#ifdef daemonize +#undef daemonize +#endif +#define daemonize(name) do { \ + \ + lock_kernel(); \ + \ + exit_mm(current); \ + exit_files(current); \ + exit_fs(current); \ + current->session = 1; \ + current->pgrp = 1; \ + current->euid = 0; \ + current->tty = NULL; \ + sigfillset(¤t->blocked); \ + \ + strcpy(current->comm, name); \ + \ + unlock_kernel(); \ + \ +} while (0) + +/* Not sure when this was introduced, sometime during 2.5.X */ +#define MODULE_PARM_int(x) MODULE_PARM(x, "i") +#define MODULE_PARM_bool(x) MODULE_PARM(x, "i") +#define MODULE_PARM_long(x) MODULE_PARM(x, "l") +#define module_param(x, y, z) MODULE_PARM_##y(x) +#else +#include +#endif /* Linux < 2.6.0 */ + +/* DevFS header */ +#if defined(LIRC_HAVE_DEVFS) +#include +#endif + +#ifdef LIRC_HAVE_DEVFS_24 +#ifdef register_chrdev +#undef register_chrdev +#endif +#define register_chrdev devfs_register_chrdev +#ifdef unregister_chrdev +#undef unregister_chrdev +#endif +#define unregister_chrdev devfs_unregister_chrdev +#endif /* DEVFS 2.4 */ + +#ifndef LIRC_HAVE_SYSFS +#define class_destroy(x) do { } while (0) +#define class_create(x, y) NULL +#define lirc_class_destroy(x, y) do { } while (0) +#define lirc_class_create(x, y, z, xx, yy, zz) 0 +#define IS_ERR(x) 0 +typedef struct class_simple +{ + int notused; +} lirc_class_t; +#endif /* No SYSFS */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) +#define KERNEL_2_5 + +/* + * We still are using MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT in the set_use_inc + * function of all modules for 2.4 kernel compatibility. + * + * For 2.6 kernels reference counting is done in lirc_dev by + * try_module_get()/module_put() because the old approach is racy. + * + */ +#ifdef MOD_INC_USE_COUNT +#undef MOD_INC_USE_COUNT +#endif +#define MOD_INC_USE_COUNT + +#ifdef MOD_DEC_USE_COUNT +#undef MOD_DEC_USE_COUNT +#endif +#define MOD_DEC_USE_COUNT + +#ifdef EXPORT_NO_SYMBOLS +#undef EXPORT_NO_SYMBOLS +#endif +#define EXPORT_NO_SYMBOLS + +#else /* Kernel < 2.5.0 */ + +static inline int try_module_get(struct module *module) +{ + return 1; +} + +static inline void module_put(struct module *module) +{ +} + +#endif /* Kernel >= 2.5.0 */ + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(x) +#endif + +#ifndef MODULE_PARM_DESC +#define MODULE_PARM_DESC(x, y) +#endif + +#ifndef MODULE_ALIAS_CHARDEV_MAJOR +#define MODULE_ALIAS_CHARDEV_MAJOR(x) +#endif + +#ifndef MODULE_DEVICE_TABLE +#define MODULE_DEVICE_TABLE(x, y) +#endif + +#include +#ifndef IRQ_RETVAL +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) +#endif + +#ifndef MOD_IN_USE +#ifdef CONFIG_MODULE_UNLOAD +#define MOD_IN_USE module_refcount(THIS_MODULE) +#else +#error "LIRC modules currently require" +#error " 'Loadable module support ---> Module unloading'" +#error "to be enabled in the kernel" +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#if !defined(local_irq_save) +#define local_irq_save(flags) do { save_flags(flags); cli(); } while (0) +#endif +#if !defined(local_irq_restore) +#define local_irq_restore(flags) do { restore_flags(flags); } while (0) +#endif +#endif + +#if KERNEL_VERSION(2, 4, 0) <= LINUX_VERSION_CODE +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 22) +#include +static inline char *pci_name(struct pci_dev *pdev) +{ + return pdev->slot_name; +} +#endif /* kernel < 2.4.22 */ +#endif /* kernel >= 2.4.0 */ + +/*************************** I2C specific *****************************/ +#include + +#ifndef I2C_CLIENT_END +#error "********************************************************" +#error " Sorry, this driver needs the new I2C stack. " +#error " You can get it at http://www2.lm-sensors.nu/~lm78/. " +#error "********************************************************" +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) + +#undef i2c_get_clientdata +#define i2c_get_clientdata(client) ((client)->data) + + +#undef i2c_set_clientdata +#define i2c_set_clientdata(client_ptr, new_data) do { \ + (client_ptr)->data = new_data; \ +} while (0) + + +#endif + +/* removed in 2.6.14 */ +#ifndef I2C_ALGO_BIT +# define I2C_ALGO_BIT 0 +#endif + +/* removed in 2.6.16 */ +#ifndef I2C_DRIVERID_EXP3 +# define I2C_DRIVERID_EXP3 0xf003 +#endif + +/*************************** USB specific *****************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8) +static inline int usb_kill_urb(struct urb *urb) +{ + return usb_unlink_urb(urb); +} +#endif + +/* removed in 2.6.14 */ +#ifndef URB_ASYNC_UNLINK +#define URB_ASYNC_UNLINK 0 +#endif +#endif + +/*************************** bttv specific ****************************/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) /* BTTV_* -> BTTV_BOARD_* */ +#define BTTV_BOARD_UNKNOWN BTTV_UNKNOWN +#define BTTV_BOARD_PXELVWPLTVPAK BTTV_PXELVWPLTVPAK +#define BTTV_BOARD_PXELVWPLTVPRO BTTV_PXELVWPLTVPRO +#define BTTV_BOARD_PV_BT878P_9B BTTV_PV_BT878P_9B +#define BTTV_BOARD_PV_BT878P_PLUS BTTV_PV_BT878P_PLUS +#define BTTV_BOARD_AVERMEDIA BTTV_AVERMEDIA +#define BTTV_BOARD_AVPHONE98 BTTV_AVPHONE98 +#define BTTV_BOARD_AVERMEDIA98 BTTV_AVERMEDIA98 +#define BTTV_BOARD_CHRONOS_VS2 BTTV_CHRONOS_VS2 +#define BTTV_BOARD_MIRO BTTV_MIRO +#define BTTV_BOARD_DYNALINK BTTV_DYNALINK +#define BTTV_BOARD_WINVIEW_601 BTTV_WINVIEW_601 +#ifdef BTTV_KWORLD +#define BTTV_BOARD_KWORLD BTTV_KWORLD +#endif +#define BTTV_BOARD_MAGICTVIEW061 BTTV_MAGICTVIEW061 +#define BTTV_BOARD_MAGICTVIEW063 BTTV_MAGICTVIEW063 +#define BTTV_BOARD_PHOEBE_TVMAS BTTV_PHOEBE_TVMAS +#ifdef BTTV_BESTBUY_EASYTV2 +#define BTTV_BOARD_BESTBUY_EASYTV BTTV_BESTBUY_EASYTV +#define BTTV_BOARD_BESTBUY_EASYTV2 BTTV_BESTBUY_EASYTV2 +#endif +#define BTTV_BOARD_FLYVIDEO BTTV_FLYVIDEO +#define BTTV_BOARD_FLYVIDEO_98 BTTV_FLYVIDEO_98 +#define BTTV_BOARD_TYPHOON_TVIEW BTTV_TYPHOON_TVIEW +#ifdef BTTV_FLYVIDEO_98FM +#define BTTV_BOARD_FLYVIDEO_98FM BTTV_FLYVIDEO_98FM +#endif +#define BTTV_BOARD_WINFAST2000 BTTV_WINFAST2000 +#ifdef BTTV_GVBCTV5PCI +#define BTTV_BOARD_GVBCTV5PCI BTTV_GVBCTV5PCI +#endif +#endif /* end BTTV_* -> BTTV_BOARD_* */ + + +/******************************* pm.h *********************************/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) +typedef u32 pm_message_t; +#endif /* kernel < 2.6.11 */ +#endif /* kernel >= 2.6.0 */ + +/*************************** interrupt.h ******************************/ +/* added in 2.6.18, old defines removed in 2.6.24 */ +#ifndef IRQF_DISABLED +#define IRQF_DISABLED SA_INTERRUPT +#endif +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +/*************************** spinlock.h *******************************/ +/* added in 2.6.11 */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) +#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED +#endif + +#endif /* _KCOMPAT_H */ --- linux-2.6.27.orig/ubuntu/lirc/Kconfig +++ linux-2.6.27/ubuntu/lirc/Kconfig @@ -0,0 +1,93 @@ +config LIRC_DEV + tristate "LIRC Device support" + default m + +config LIRC_ATIUSB + tristate "LIRC ATI RF Remote" + default m + depends on LIRC_DEV + +config LIRC_BT829 + tristate "LIRC BT829" + default m + depends on LIRC_DEV + +config LIRC_CMDIR + tristate "LIRC CommandIR kernel support" + default m + depends on LIRC_DEV + +config LIRC_I2C + tristate "LIRC I2C interface remote" + default m + depends on LIRC_DEV + +config LIRC_IGORPLUGUSB + tristate "LIRC IGOR custom remote" + default m + depends on LIRC_DEV + +config LIRC_IMON + tristate "LIRC Imon remote or pad" + default m + depends on LIRC_DEV + +config LIRC_IT87 + tristate "LIRC IT87" + default m + depends on LIRC_DEV + +config LIRC_MCEUSB + tristate "LIRC Microsoft Media Center Remote" + default m + depends on LIRC_DEV + +config LIRC_MCEUSB2 + tristate "LIRC Microsoft Media Center Remote v2" + default m + depends on LIRC_DEV + +config LIRC_PVR150 + tristate "LIRC Hauppauge PVR-XXX remote" + default m + depends on LIRC_DEV + +config LIRC_PARALLEL + tristate "LIRC Parallel port custom remote" + default n + depends on LIRC_DEV + +config LIRC_SASEM + tristate "LIRC Sasem" + default m + depends on LIRC_DEV + +config LIRC_SERIAL + tristate "LIRC Serial port remote" + default m + depends on LIRC_DEV + +config LIRC_SERIAL_IGOR + tristate "LIRC Igor design serial remote" + default m + depends on LIRC_DEV + +config LIRC_SIR + tristate "LIRC Laptop port IR (SIR))" + default m + depends on LIRC_DEV + +config LIRC_STREAMZAP + tristate "LIRC Streamzap remote" + default m + depends on LIRC_DEV + +config LIRC_TTUSBIR + tristate "LIRC TT USB IR device" + default m + depends on LIRC_DEV + +config LIRC_GPIO + tristate "LIRC TV Card GPIO remote" + default n + depends on LIRC_DEV --- linux-2.6.27.orig/ubuntu/lirc/Makefile +++ linux-2.6.27/ubuntu/lirc/Makefile @@ -0,0 +1,24 @@ +#include $(src)/../../.config + +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src) + +obj-$(CONFIG_LIRC_DEV) += lirc_dev/ +obj-$(CONFIG_LIRC_ATIUSB) += lirc_atiusb/ +obj-$(CONFIG_LIRC_BT829) += lirc_bt829/ +obj-$(CONFIG_LIRC_CMDIR) += lirc_cmdir/ +obj-$(CONFIG_LIRC_I2C) += lirc_i2c/ +obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb/ +obj-$(CONFIG_LIRC_IMON) += lirc_imon/ +obj-$(CONFIG_LIRC_IT87) += lirc_it87/ +obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb/ +obj-$(CONFIG_LIRC_MCEUSB2) += lirc_mceusb2/ +obj-$(CONFIG_LIRC_PVR150) += lirc_pvr150/ +obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel/ +obj-$(CONFIG_LIRC_SASEM) += lirc_sasem/ +obj-$(CONFIG_LIRC_SERIAL) += lirc_serial/ +obj-$(CONFIG_LIRC_SERIAL_IGOR) += lirc_serial_igor/ +obj-$(CONFIG_LIRC_SIR) += lirc_sir/ +obj-$(CONFIG_LIRC_STREAMZAP) += lirc_streamzap/ +obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir/ +obj-$(CONFIG_LIRC_GPIO) += lirc_gpio/ +obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir/ --- linux-2.6.27.orig/ubuntu/lirc/lirc_streamzap/lirc_streamzap.c +++ linux-2.6.27/ubuntu/lirc/lirc_streamzap/lirc_streamzap.c @@ -0,0 +1,912 @@ +/* $Id: lirc_streamzap.c,v 1.27 2008/01/13 11:13:50 lirc Exp $ */ + +/* + * Streamzap Remote Control driver + * + * Copyright (c) 2005 Christoph Bartelmus + * + * This driver was based on the work of Greg Wickham and Adrian + * Dewhurst. It was substantially rewritten to support correct signal + * gaps and now maintains a delay buffer, which is used to present + * consistent timing behaviour to user space applications. Without the + * delay buffer an ugly hack would be required in lircd, which can + * cause sluggish signal decoding in certain situations. + * + * This driver is based on the USB skeleton driver packaged with the + * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +#error "*******************************************************" +#error "Sorry, this driver needs kernel version 2.4.0 or higher" +#error "*******************************************************" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#include + +#include "lirc.h" +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +#define DRIVER_VERSION "$Revision: 1.27 $" +#define DRIVER_NAME "lirc_streamzap" +#define DRIVER_DESC "Streamzap Remote Control driver" + +/* ------------------------------------------------------------------ */ + +static int debug; + +#define USB_STREAMZAP_VENDOR_ID 0x0e9c +#define USB_STREAMZAP_PRODUCT_ID 0x0000 + +/* Use our own dbg macro */ +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG DRIVER_NAME "[%d]: " \ + fmt "\n", ## args); \ + } while (0) + +/* + * table of devices that work with this driver + */ +static struct usb_device_id streamzap_table [] = { + { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, streamzap_table); + +#define STREAMZAP_PULSE_MASK 0xf0 +#define STREAMZAP_SPACE_MASK 0x0f +#define STREAMZAP_RESOLUTION 256 + +/* number of samples buffered */ +#define STREAMZAP_BUFFER_SIZE 128 + +enum StreamzapDecoderState { + PulseSpace, + FullPulse, + FullSpace, + IgnorePulse +}; + +/* Structure to hold all of our device specific stuff */ +/* some remarks regarding locking: + theoretically this struct can be accessed from three threads: + + - from lirc_dev through set_use_inc/set_use_dec + + - from the USB layer throuh probe/disconnect/irq + + Careful placement of lirc_register_plugin/lirc_unregister_plugin + calls will prevent conflicts. lirc_dev makes sure that + set_use_inc/set_use_dec are not being executed and will not be + called after lirc_unregister_plugin returns. + + - by the timer callback + + The timer is only running when the device is connected and the + LIRC device is open. Making sure the timer is deleted by + set_use_dec will make conflicts impossible. +*/ +struct usb_streamzap { + + /* usb */ + /* save off the usb device pointer */ + struct usb_device *udev; + /* the interface for this device */ + struct usb_interface *interface; + + /* buffer & dma */ + unsigned char *buf_in; + dma_addr_t dma_in; + unsigned int buf_in_len; + + struct usb_endpoint_descriptor *endpoint; + + /* IRQ */ + struct urb *urb_in; + + /* lirc */ + struct lirc_plugin plugin; + struct lirc_buffer delay_buf; + struct lirc_buffer lirc_buf; + + /* timer used to support delay buffering */ + struct timer_list delay_timer; + int timer_running; + spinlock_t timer_lock; + + /* tracks whether we are currently receiving some signal */ + int idle; + /* sum of signal lengths received since signal start */ + unsigned long sum; + /* start time of signal; necessary for gap tracking */ + struct timeval signal_last; + struct timeval signal_start; + enum StreamzapDecoderState decoder_state; + struct timer_list flush_timer; + int flush; + int in_use; +}; + + +/* local function prototypes */ +#ifdef KERNEL_2_5 +static int streamzap_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void streamzap_disconnect(struct usb_interface *interface); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_streamzap_irq(struct urb *urb, struct pt_regs *regs); +#else +static void usb_streamzap_irq(struct urb *urb); +#endif +#else +static void *streamzap_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id); +static void streamzap_disconnect(struct usb_device *dev, void *ptr); +static void usb_streamzap_irq(struct urb *urb); +#endif +static int streamzap_use_inc(void *data); +static void streamzap_use_dec(void *data); +static int streamzap_ioctl(struct inode *node, struct file *filep, + unsigned int cmd, unsigned long arg); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); +static int streamzap_resume(struct usb_interface *intf); +#endif + +/* usb specific object needed to register this driver with the usb subsystem */ + +static struct usb_driver streamzap_driver = { + LIRC_THIS_MODULE(.owner = THIS_MODULE) + .name = DRIVER_NAME, + .probe = streamzap_probe, + .disconnect = streamzap_disconnect, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + .suspend = streamzap_suspend, + .resume = streamzap_resume, +#endif + .id_table = streamzap_table, +}; + +static void stop_timer(struct usb_streamzap *sz) +{ + unsigned long flags; + + spin_lock_irqsave(&sz->timer_lock, flags); + if (sz->timer_running) { + sz->timer_running = 0; + del_timer_sync(&sz->delay_timer); + } + spin_unlock_irqrestore(&sz->timer_lock, flags); +} + +static void flush_timeout(unsigned long arg) +{ + struct usb_streamzap *sz = (struct usb_streamzap *) arg; + + /* finally start accepting data */ + sz->flush = 0; +} +static void delay_timeout(unsigned long arg) +{ + unsigned long flags; + /* deliver data every 10 ms */ + static unsigned long timer_inc = + (10000/(1000000/HZ)) == 0 ? 1:(10000/(1000000/HZ)); + struct usb_streamzap *sz = (struct usb_streamzap *) arg; + lirc_t data; + + spin_lock_irqsave(&sz->timer_lock, flags); + + if (!lirc_buffer_empty(&sz->delay_buf) && + !lirc_buffer_full(&sz->lirc_buf)) { + lirc_buffer_read_1(&sz->delay_buf, (unsigned char *) &data); + lirc_buffer_write_1(&sz->lirc_buf, (unsigned char *) &data); + } + if (!lirc_buffer_empty(&sz->delay_buf)) { + while (lirc_buffer_available(&sz->delay_buf) < + STREAMZAP_BUFFER_SIZE/2 && + !lirc_buffer_full(&sz->lirc_buf)) { + lirc_buffer_read_1(&sz->delay_buf, + (unsigned char *) &data); + lirc_buffer_write_1(&sz->lirc_buf, + (unsigned char *) &data); + } + if (sz->timer_running) { + sz->delay_timer.expires += timer_inc; + add_timer(&sz->delay_timer); + } + } else { + sz->timer_running = 0; + } + + if (!lirc_buffer_empty(&sz->lirc_buf)) + wake_up(&sz->lirc_buf.wait_poll); + + spin_unlock_irqrestore(&sz->timer_lock, flags); +} + +static inline void flush_delay_buffer(struct usb_streamzap *sz) +{ + lirc_t data; + int empty = 1; + + while (!lirc_buffer_empty(&sz->delay_buf)) { + empty = 0; + lirc_buffer_read_1(&sz->delay_buf, (unsigned char *) &data); + if (!lirc_buffer_full(&sz->lirc_buf)) { + lirc_buffer_write_1(&sz->lirc_buf, + (unsigned char *) &data); + } else { + dprintk("buffer overflow\n", sz->plugin.minor); + } + } + if (!empty) + wake_up(&sz->lirc_buf.wait_poll); +} + +static inline void push(struct usb_streamzap *sz, unsigned char *data) +{ + unsigned long flags; + + spin_lock_irqsave(&sz->timer_lock, flags); + if (lirc_buffer_full(&sz->delay_buf)) { + lirc_t data; + + lirc_buffer_read_1(&sz->delay_buf, (unsigned char *) &data); + if (!lirc_buffer_full(&sz->lirc_buf)) { + lirc_buffer_write_1(&sz->lirc_buf, + (unsigned char *) &data); + } else { + dprintk("buffer overflow", sz->plugin.minor); + } + } + + lirc_buffer_write_1(&sz->delay_buf, data); + + if (!sz->timer_running) { + sz->delay_timer.expires = jiffies + HZ/10; + add_timer(&sz->delay_timer); + sz->timer_running = 1; + } + + spin_unlock_irqrestore(&sz->timer_lock, flags); +} + +static inline void push_full_pulse(struct usb_streamzap *sz, + unsigned char value) +{ + lirc_t pulse; + + if (sz->idle) { + long deltv; + lirc_t tmp; + + sz->signal_last = sz->signal_start; + do_gettimeofday(&sz->signal_start); + + deltv = sz->signal_start.tv_sec-sz->signal_last.tv_sec; + if (deltv > 15) { + tmp = PULSE_MASK; /* really long time */ + } else { + tmp = (lirc_t) (deltv*1000000+ + sz->signal_start.tv_usec - + sz->signal_last.tv_usec); + tmp -= sz->sum; + } + dprintk("ls %u", sz->plugin.minor, tmp); + push(sz, (char *)&tmp); + + sz->idle = 0; + sz->sum = 0; + } + + pulse = ((lirc_t) value)*STREAMZAP_RESOLUTION; + pulse += STREAMZAP_RESOLUTION/2; + sz->sum += pulse; + pulse |= PULSE_BIT; + + dprintk("p %u", sz->plugin.minor, pulse&PULSE_MASK); + push(sz, (char *)&pulse); +} + +static inline void push_half_pulse(struct usb_streamzap *sz, + unsigned char value) +{ + push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK)>>4); +} + +static inline void push_full_space(struct usb_streamzap *sz, + unsigned char value) +{ + lirc_t space; + + space = ((lirc_t) value)*STREAMZAP_RESOLUTION; + space += STREAMZAP_RESOLUTION/2; + sz->sum += space; + dprintk("s %u", sz->plugin.minor, space); + push(sz, (char *)&space); +} + +static inline void push_half_space(struct usb_streamzap *sz, + unsigned char value) +{ + push_full_space(sz, value & STREAMZAP_SPACE_MASK); +} + +/* + * usb_streamzap_irq - IRQ handler + * + * This procedure is invoked on reception of data from + * the usb remote. + */ +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_streamzap_irq(struct urb *urb, struct pt_regs *regs) +#else +static void usb_streamzap_irq(struct urb *urb) +#endif +{ + struct usb_streamzap *sz; + int len; + unsigned int i = 0; + + if (!urb) + return; + + sz = urb->context; + len = urb->actual_length; + + switch (urb->status) { + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + /* sz might already be invalid at this point */ + dprintk("urb status: %d", -1, urb->status); + return; + default: + break; + } + + dprintk("received %d", sz->plugin.minor, urb->actual_length); + if (!sz->flush) { + for (i = 0; i < urb->actual_length; i++) { + dprintk("%d: %x", sz->plugin.minor, + i, (unsigned char) sz->buf_in[i]); + switch (sz->decoder_state) { + case PulseSpace: + if ((sz->buf_in[i]&STREAMZAP_PULSE_MASK) == + STREAMZAP_PULSE_MASK) { + sz->decoder_state = FullPulse; + continue; + } else if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) + == STREAMZAP_SPACE_MASK) { + push_half_pulse(sz, sz->buf_in[i]); + sz->decoder_state = FullSpace; + continue; + } else { + push_half_pulse(sz, sz->buf_in[i]); + push_half_space(sz, sz->buf_in[i]); + } + break; + case FullPulse: + push_full_pulse(sz, sz->buf_in[i]); + sz->decoder_state = IgnorePulse; + break; + case FullSpace: + if (sz->buf_in[i] == 0xff) { + sz->idle = 1; + stop_timer(sz); + flush_delay_buffer(sz); + } else + push_full_space(sz, sz->buf_in[i]); + sz->decoder_state = PulseSpace; + break; + case IgnorePulse: + if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) == + STREAMZAP_SPACE_MASK) { + sz->decoder_state = FullSpace; + continue; + } + push_half_space(sz, sz->buf_in[i]); + sz->decoder_state = PulseSpace; + break; + } + } + } + +#ifdef KERNEL_2_5 + /* resubmit only for 2.6 */ + usb_submit_urb(urb, GFP_ATOMIC); +#endif + + return; +} + +/** + * streamzap_probe + * + * Called by usb-core to associated with a candidate device + * On any failure the return value is the ERROR + * On success return 0 + */ +#ifdef KERNEL_2_5 +static int streamzap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct usb_host_interface *iface_host; +#else +static void *streamzap_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct usb_interface *interface = &udev->actconfig->interface[ifnum]; + struct usb_interface_descriptor *iface_host; +#endif + int retval = -ENOMEM; + struct usb_streamzap *sz = NULL; + char buf[63], name[128] = ""; + + /*************************************************** + * Allocate space for device driver specific data + */ + sz = kmalloc(sizeof(struct usb_streamzap), GFP_KERNEL); + if (sz == NULL) + goto error; + + memset(sz, 0, sizeof(*sz)); + sz->udev = udev; + sz->interface = interface; + + /*************************************************** + * Check to ensure endpoint information matches requirements + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) + iface_host = &interface->altsetting[interface->act_altsetting]; +#else + iface_host = interface->cur_altsetting; +#endif + +#ifdef KERNEL_2_5 + if (iface_host->desc.bNumEndpoints != 1) { +#else + if (iface_host->bNumEndpoints != 1) { +#endif +#ifdef KERNEL_2_5 + err("%s: Unexpected desc.bNumEndpoints (%d)", __FUNCTION__, + iface_host->desc.bNumEndpoints); +#else + err("%s: Unexpected desc.bNumEndpoints (%d)", __FUNCTION__, + iface_host->bNumEndpoints); +#endif + retval = -ENODEV; + goto error; + } + +#ifdef KERNEL_2_5 + sz->endpoint = &(iface_host->endpoint[0].desc); +#else + sz->endpoint = &(iface_host->endpoint[0]); +#endif + if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + != USB_DIR_IN) { + err("%s: endpoint doesn't match input device 02%02x", + __FUNCTION__, sz->endpoint->bEndpointAddress); + retval = -ENODEV; + goto error; + } + + if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_INT) { + err("%s: endpoint attributes don't match xfer 02%02x", + __FUNCTION__, sz->endpoint->bmAttributes); + retval = -ENODEV; + goto error; + } + + if (sz->endpoint->wMaxPacketSize == 0) { + err("%s: endpoint message size==0? ", __FUNCTION__); + retval = -ENODEV; + goto error; + } + + /*************************************************** + * Allocate the USB buffer and IRQ URB + */ + + sz->buf_in_len = sz->endpoint->wMaxPacketSize; +#ifdef KERNEL_2_5 + sz->buf_in = usb_buffer_alloc(sz->udev, sz->buf_in_len, + GFP_ATOMIC, &sz->dma_in); +#else + sz->buf_in = kmalloc(sz->buf_in_len, GFP_KERNEL); +#endif + if (sz->buf_in == NULL) + goto error; + +#ifdef KERNEL_2_5 + sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); +#else + + sz->urb_in = usb_alloc_urb(0); +#endif + if (sz->urb_in == NULL) + goto error; + + /*************************************************** + * Connect this device to the LIRC sub-system + */ + + if (lirc_buffer_init(&sz->lirc_buf, sizeof(lirc_t), + STREAMZAP_BUFFER_SIZE)) + goto error; + + if (lirc_buffer_init(&sz->delay_buf, sizeof(lirc_t), + STREAMZAP_BUFFER_SIZE)) { + lirc_buffer_free(&sz->lirc_buf); + goto error; + } + + /*************************************************** + * As required memory is allocated now populate the plugin structure + */ + + memset(&sz->plugin, 0, sizeof(sz->plugin)); + + strcpy(sz->plugin.name, DRIVER_NAME); + sz->plugin.minor = -1; + sz->plugin.sample_rate = 0; + sz->plugin.code_length = sizeof(lirc_t) * 8; + sz->plugin.features = LIRC_CAN_REC_MODE2|LIRC_CAN_GET_REC_RESOLUTION; + sz->plugin.data = sz; + sz->plugin.rbuf = &sz->lirc_buf; + sz->plugin.set_use_inc = &streamzap_use_inc; + sz->plugin.set_use_dec = &streamzap_use_dec; + sz->plugin.ioctl = streamzap_ioctl; +#ifdef LIRC_HAVE_SYSFS + sz->plugin.dev = &udev->dev; +#endif + sz->plugin.owner = THIS_MODULE; + + sz->idle = 1; + sz->decoder_state = PulseSpace; + init_timer(&sz->delay_timer); + sz->delay_timer.function = delay_timeout; + sz->delay_timer.data = (unsigned long) sz; + sz->timer_running = 0; + spin_lock_init(&sz->timer_lock); + + init_timer(&sz->flush_timer); + sz->flush_timer.function = flush_timeout; + sz->flush_timer.data = (unsigned long) sz; + /*************************************************** + * Complete final initialisations + */ + + usb_fill_int_urb(sz->urb_in, udev, + usb_rcvintpipe(udev, sz->endpoint->bEndpointAddress), + sz->buf_in, sz->buf_in_len, usb_streamzap_irq, sz, + sz->endpoint->bInterval); + + if (udev->descriptor.iManufacturer + && usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0) + strncpy(name, buf, 128); + + if (udev->descriptor.iProduct + && usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0) + snprintf(name, 128, "%s %s", name, buf); + + printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d attached\n", + sz->plugin.minor, name, + udev->bus->busnum, sz->udev->devnum); + +#ifdef KERNEL_2_5 + usb_set_intfdata(interface, sz); +#endif + + if (lirc_register_plugin(&sz->plugin) < 0) { + lirc_buffer_free(&sz->delay_buf); + lirc_buffer_free(&sz->lirc_buf); + goto error; + } + +#ifdef KERNEL_2_5 + return 0; +#else + return sz; +#endif + +error: + + /*************************************************** + * Premise is that a 'goto error' can be invoked from inside the + * probe function and all necessary cleanup actions will be taken + * including freeing any necessary memory blocks + */ + + if (retval == -ENOMEM) + err("Out of memory"); + + if (sz) { + + if (sz->urb_in) + usb_free_urb(sz->urb_in); + + if (sz->buf_in) { +#ifdef KERNEL_2_5 + usb_buffer_free(udev, sz->buf_in_len, + sz->buf_in, sz->dma_in); +#else + kfree(sz->buf_in); +#endif + } + kfree(sz); + } + +#ifdef KERNEL_2_5 + return retval; +#else + return NULL; +#endif +} + +static int streamzap_use_inc(void *data) +{ + struct usb_streamzap *sz = data; + + if (!sz) { + dprintk("%s called with no context", -1, __FUNCTION__); + return -EINVAL; + } + dprintk("set use inc", sz->plugin.minor); + + MOD_INC_USE_COUNT; + + while (!lirc_buffer_empty(&sz->lirc_buf)) + lirc_buffer_remove_1(&sz->lirc_buf); + while (!lirc_buffer_empty(&sz->delay_buf)) + lirc_buffer_remove_1(&sz->delay_buf); + + sz->flush_timer.expires = jiffies + HZ; + sz->flush = 1; + add_timer(&sz->flush_timer); + + sz->urb_in->dev = sz->udev; +#ifdef KERNEL_2_5 + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { +#else + if (usb_submit_urb(sz->urb_in)) { +#endif + dprintk("open result = -EIO error submitting urb", + sz->plugin.minor); + MOD_DEC_USE_COUNT; + return -EIO; + } + sz->in_use++; + + return 0; +} + +static void streamzap_use_dec(void *data) +{ + struct usb_streamzap *sz = data; + + if (!sz) { + dprintk("%s called with no context", -1, __FUNCTION__); + return; + } + dprintk("set use dec", sz->plugin.minor); + + if (sz->flush) { + sz->flush = 0; + del_timer_sync(&sz->flush_timer); + } + + stop_timer(sz); + + usb_kill_urb(sz->urb_in); + + MOD_DEC_USE_COUNT; + sz->in_use--; +} + +static int streamzap_ioctl(struct inode *node, struct file *filep, + unsigned int cmd, unsigned long arg) +{ + int result; + + switch (cmd) { + case LIRC_GET_REC_RESOLUTION: + result = put_user(STREAMZAP_RESOLUTION, (unsigned long *) arg); + if (result) + return(result); + break; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/** + * streamzap_disconnect + * + * Called by the usb core when the device is removed from the system. + * + * This routine guarantees that the driver will not submit any more urbs + * by clearing dev->udev. It is also supposed to terminate any currently + * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), + * does not provide any way to do this. + */ +#ifdef KERNEL_2_5 +static void streamzap_disconnect(struct usb_interface *interface) +#else +static void streamzap_disconnect(struct usb_device *dev, void *ptr) +#endif +{ + struct usb_streamzap *sz; + int errnum; + int minor; + +#ifdef KERNEL_2_5 + sz = usb_get_intfdata(interface); +#else + sz = ptr; +#endif + + /* + * unregister from the LIRC sub-system + */ + + errnum = lirc_unregister_plugin(sz->plugin.minor); + if (errnum != 0) + dprintk("error in lirc_unregister: (returned %d)", + sz->plugin.minor, errnum); + + lirc_buffer_free(&sz->delay_buf); + lirc_buffer_free(&sz->lirc_buf); + + /* + * unregister from the USB sub-system + */ + + usb_free_urb(sz->urb_in); + +#ifdef KERNEL_2_5 + usb_buffer_free(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in); +#else + kfree(sz->buf_in); +#endif + + minor = sz->plugin.minor; + kfree(sz); + + printk(KERN_INFO DRIVER_NAME "[%d]: disconnected\n", minor); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_streamzap *sz = usb_get_intfdata(intf); + + printk(DRIVER_NAME "[%d]: suspend\n", sz->plugin.minor); + if (sz->in_use) { + if (sz->flush) { + sz->flush = 0; + del_timer_sync(&sz->flush_timer); + } + + stop_timer(sz); + + usb_kill_urb(sz->urb_in); + } + return 0; +} + +static int streamzap_resume(struct usb_interface *intf) +{ + struct usb_streamzap *sz = usb_get_intfdata(intf); + + while (!lirc_buffer_empty(&sz->lirc_buf)) + lirc_buffer_remove_1(&sz->lirc_buf); + while (!lirc_buffer_empty(&sz->delay_buf)) + lirc_buffer_remove_1(&sz->delay_buf); + + if (sz->in_use) { + sz->flush_timer.expires = jiffies + HZ; + sz->flush = 1; + add_timer(&sz->flush_timer); + + sz->urb_in->dev = sz->udev; +#ifdef KERNEL_2_5 + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { +#else + if (usb_submit_urb(sz->urb_in)) { +#endif + dprintk("open result = -EIO error submitting urb", + sz->plugin.minor); + MOD_DEC_USE_COUNT; + return -EIO; + } + } + return 0; +} +#endif + +#ifdef MODULE + +/** + * usb_streamzap_init + */ +static int __init usb_streamzap_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + + result = usb_register(&streamzap_driver); + + if (result) { + err("usb_register failed. Error number %d", + result); + return result; + } + + printk(KERN_INFO DRIVER_NAME " " DRIVER_VERSION " registered\n"); + return 0; +} + +/** + * usb_streamzap_exit + */ +static void __exit usb_streamzap_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&streamzap_driver); +} + + +module_init(usb_streamzap_init); +module_exit(usb_streamzap_exit); + +MODULE_AUTHOR("Christoph Bartelmus, Greg Wickham, Adrian Dewhurst"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +EXPORT_NO_SYMBOLS; + +#endif /* MODULE */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_streamzap/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_streamzap/Makefile @@ -0,0 +1,3 @@ + +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. +obj-$(CONFIG_LIRC_STREAMZAP) += lirc_streamzap.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_serial_igor/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_serial_igor/Makefile @@ -0,0 +1,4 @@ + +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_SERIAL_IGOR) += lirc_serial_igor.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_serial_igor/lirc_serial_igor.c +++ linux-2.6.27/ubuntu/lirc/lirc_serial_igor/lirc_serial_igor.c @@ -0,0 +1,1341 @@ +/* $Id: lirc_serial.c,v 5.87 2007/12/15 17:28:01 lirc Exp $ */ + +/**************************************************************************** + ** lirc_serial.c *********************************************************** + **************************************************************************** + * + * lirc_serial - Device driver that records pulse- and pause-lengths + * (space-lengths) between DDCD event on a serial port. + * + * Copyright (C) 1996,97 Ralph Metzler + * Copyright (C) 1998 Trent Piepho + * Copyright (C) 1998 Ben Pfaff + * Copyright (C) 1999 Christoph Bartelmus + * Copyright (C) 2007 Andrei Tanas (suspend/resume support) + * Copyright (C) 2007 Mario Limonciello Compile for Ubuntu with igor support + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Steve's changes to improve transmission fidelity: + - for systems with the rdtsc instruction and the clock counter, a + send_pule that times the pulses directly using the counter. + This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is + not needed. Measurement shows very stable waveform, even where + PCI activity slows the access to the UART, which trips up other + versions. + - For other system, non-integer-microsecond pulse/space lengths, + done using fixed point binary. So, much more accurate carrier + frequency. + - fine tuned transmitter latency, taking advantage of fractional + microseconds in previous change + - Fixed bug in the way transmitter latency was accounted for by + tuning the pulse lengths down - the send_pulse routine ignored + this overhead as it timed the overall pulse length - so the + pulse frequency was right but overall pulse length was too + long. Fixed by accounting for latency on each pulse/space + iteration. + + Steve Davies July 2001 +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) +#error "**********************************************************" +#error " Sorry, this driver needs kernel version 2.2.18 or higher " +#error "**********************************************************" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +#include +#endif + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#include +#include +#include + +#if defined(LIRC_SERIAL_NSLU2) +#include +/* From Intel IXP42X Developer's Manual (#252480-005): */ +/* ftp://download.intel.com/design/network/manuals/25248005.pdf */ +#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */ +#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */ +#ifndef NSLU2_LED_GRN_GPIO +/* added in 2.6.22 */ +#define NSLU2_LED_GRN_GPIO NSLU2_LED_GRN +#endif +#endif + +#include "lirc.h" +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +#if defined(LIRC_SERIAL_SOFTCARRIER) && !defined(LIRC_SERIAL_TRANSMITTER) +#warning "Software carrier only affects transmitting" +#endif + +#if defined(rdtscl) + +#define USE_RDTSC +#warning "Note: using rdtsc instruction" +#endif + +#ifdef LIRC_SERIAL_ANIMAX +#ifdef LIRC_SERIAL_TRANSMITTER +#warning "******************************************" +#warning " This receiver does not have a " +#warning " transmitter diode " +#warning "******************************************" +#endif +#endif + +#define LIRC_DRIVER_NAME "lirc_serial_igor" + +struct lirc_serial_igor +{ + int signal_pin; + int signal_pin_change; + int on; + int off; + long (*send_pulse)(unsigned long length); + void (*send_space)(long length); + int features; +}; + +#define LIRC_HOMEBREW 0 +#define LIRC_IRDEO 1 +#define LIRC_IRDEO_REMOTE 2 +#define LIRC_ANIMAX 3 +#define LIRC_IGOR 4 +#define LIRC_NSLU2 5 + +static int type = LIRC_IGOR; + +/* Set defaults for NSLU2 */ +#if defined(LIRC_SERIAL_NSLU2) +#ifndef LIRC_IRQ +#define LIRC_IRQ IRQ_IXP4XX_UART2 +#endif +#ifndef LIRC_PORT +#define LIRC_PORT (IXP4XX_UART2_BASE_VIRT + REG_OFFSET) +#endif +#ifndef LIRC_IOMMAP +#define LIRC_IOMMAP IXP4XX_UART2_BASE_PHYS +#endif +#ifndef LIRC_IOSHIFT +#define LIRC_IOSHIFT 2 +#endif +#ifndef LIRC_ALLOW_MMAPPED_IO +#define LIRC_ALLOW_MMAPPED_IO +#endif +#endif + +#if defined(LIRC_ALLOW_MMAPPED_IO) +#ifndef LIRC_IOMMAP +#define LIRC_IOMMAP 0 +#endif +#ifndef LIRC_IOSHIFT +#define LIRC_IOSHIFT 0 +#endif +static int iommap = LIRC_IOMMAP; +static int ioshift = LIRC_IOSHIFT; +#endif + +static int softcarrier; + +static int share_irq; +static int debug; + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + +/* forward declarations */ +static long send_pulse_irdeo(unsigned long length); +static long send_pulse_homebrew(unsigned long length); +static void send_space_irdeo(long length); +static void send_space_homebrew(long length); + +static struct lirc_serial_igor hardware[] = { + /* home-brew receiver/transmitter */ + { + UART_MSR_DCD, + UART_MSR_DDCD, + UART_MCR_RTS|UART_MCR_OUT2|UART_MCR_DTR, + UART_MCR_RTS|UART_MCR_OUT2, + send_pulse_homebrew, + send_space_homebrew, + ( +#ifdef LIRC_SERIAL_TRANSMITTER + LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| +#endif + LIRC_CAN_REC_MODE2) + }, + + /* IRdeo classic */ + { + UART_MSR_DSR, + UART_MSR_DDSR, + UART_MCR_OUT2, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + send_pulse_irdeo, + send_space_irdeo, + (LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SEND_PULSE| + LIRC_CAN_REC_MODE2) + }, + + /* IRdeo remote */ + { + UART_MSR_DSR, + UART_MSR_DDSR, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + send_pulse_irdeo, + send_space_irdeo, + (LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SEND_PULSE| + LIRC_CAN_REC_MODE2) + }, + + /* AnimaX */ + { + UART_MSR_DCD, + UART_MSR_DDCD, + 0, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + NULL, + NULL, + LIRC_CAN_REC_MODE2 + }, + + /* home-brew receiver/transmitter (Igor Cesko's variation) */ + { + UART_MSR_DSR, + UART_MSR_DDSR, + UART_MCR_RTS|UART_MCR_OUT2|UART_MCR_DTR, + UART_MCR_RTS|UART_MCR_OUT2, + send_pulse_homebrew, + send_space_homebrew, + ( +#ifdef LIRC_SERIAL_TRANSMITTER + LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| +#endif + LIRC_CAN_REC_MODE2) + }, + +#if defined(LIRC_SERIAL_NSLU2) + /* Modified Linksys Network Storage Link USB 2.0 (NSLU2): + We receive on CTS of the 2nd serial port (R142,LHS), we + transmit with a IR diode between GPIO[1] (green status LED), + and ground (Matthias Goebl ). + See also http://www.nslu2-linux.org for this device */ + { + UART_MSR_CTS, + UART_MSR_DCTS, + UART_MCR_RTS|UART_MCR_OUT2|UART_MCR_DTR, + UART_MCR_RTS|UART_MCR_OUT2, + send_pulse_homebrew, + send_space_homebrew, + ( +#ifdef LIRC_SERIAL_TRANSMITTER + LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| +#endif + LIRC_CAN_REC_MODE2) + }, +#endif + +}; + +#define RS_ISR_PASS_LIMIT 256 + +/* A long pulse code from a remote might take upto 300 bytes. The + daemon should read the bytes as soon as they are generated, so take + the number of keys you think you can push before the daemon runs + and multiply by 300. The driver will warn you if you overrun this + buffer. If you have a slow computer or non-busmastering IDE disks, + maybe you will need to increase this. */ + +/* This MUST be a power of two! It has to be larger than 1 as well. */ + +#define RBUF_LEN 256 +#define WBUF_LEN 256 + +static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ +static int txsense; /* 0 = active high, 1 = active low */ + +#ifndef LIRC_IRQ +#define LIRC_IRQ 4 +#endif +#ifndef LIRC_PORT +#define LIRC_PORT 0x3f8 +#endif + +static int io = LIRC_PORT; +static int irq = LIRC_IRQ; + +static struct timeval lasttv = {0, 0}; + +static struct lirc_buffer rbuf; + +static lirc_t wbuf[WBUF_LEN]; + +static unsigned int freq = 38000; +static unsigned int duty_cycle = 50; + +/* Initialized in init_timing_params() */ +static unsigned long period; +static unsigned long pulse_width; +static unsigned long space_width; + +#if defined(__i386__) +/* + From: + Linux I/O port programming mini-HOWTO + Author: Riku Saikkonen + v, 28 December 1997 + + [...] + Actually, a port I/O instruction on most ports in the 0-0x3ff range + takes almost exactly 1 microsecond, so if you're, for example, using + the parallel port directly, just do additional inb()s from that port + to delay. + [...] +*/ +/* transmitter latency 1.5625us 0x1.90 - this figure arrived at from + * comment above plus trimming to match actual measured frequency. + * This will be sensitive to cpu speed, though hopefully most of the 1.5us + * is spent in the uart access. Still - for reference test machine was a + * 1.13GHz Athlon system - Steve + */ + +/* changed from 400 to 450 as this works better on slower machines; + faster machines will use the rdtsc code anyway */ + +#define LIRC_SERIAL_TRANSMITTER_LATENCY 450 + +#else + +/* does anybody have information on other platforms ? */ +/* 256 = 1<<8 */ +#define LIRC_SERIAL_TRANSMITTER_LATENCY 256 + +#endif /* __i386__ */ + +static inline unsigned int sinp(int offset) +{ +#if defined(LIRC_ALLOW_MMAPPED_IO) + if (iommap != 0) { /* the register is memory-mapped */ + offset <<= ioshift; + return readb(io + offset); + } +#endif + return inb(io + offset); +} + +static inline void soutp(int offset, int value) +{ +#if defined(LIRC_ALLOW_MMAPPED_IO) + if (iommap != 0) { /* the register is memory-mapped */ + offset <<= ioshift; + writeb(value, io + offset); + } +#endif + outb(value, io + offset); +} + +static inline void on(void) +{ +#if defined(LIRC_SERIAL_NSLU2) + /* On NSLU2, we put the transmit diode between the output of the green + status LED and ground */ + if (type == LIRC_NSLU2) { + gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_LOW); + return; + } +#endif + if (txsense) + soutp(UART_MCR, hardware[type].off); + else + soutp(UART_MCR, hardware[type].on); +} + +static inline void off(void) +{ +#if defined(LIRC_SERIAL_NSLU2) + if (type == LIRC_NSLU2) { + gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_HIGH); + return; + } +#endif + if (txsense) + soutp(UART_MCR, hardware[type].on); + else + soutp(UART_MCR, hardware[type].off); +} + +#ifndef MAX_UDELAY_MS +#define MAX_UDELAY_US 5000 +#else +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) +#endif + +static inline void safe_udelay(unsigned long usecs) +{ + while (usecs > MAX_UDELAY_US) { + udelay(MAX_UDELAY_US); + usecs -= MAX_UDELAY_US; + } + udelay(usecs); +} + +#ifdef USE_RDTSC +/* This is an overflow/precision juggle, complicated in that we can't + do long long divide in the kernel */ + +/* When we use the rdtsc instruction to measure clocks, we keep the + * pulse and space widths as clock cycles. As this is CPU speed + * dependent, the widths must be calculated in init_port and ioctl + * time + */ + +/* So send_pulse can quickly convert microseconds to clocks */ +static unsigned long conv_us_to_clocks; + +static inline int init_timing_params(unsigned int new_duty_cycle, + unsigned int new_freq) +{ + unsigned long long loops_per_sec, work; + + duty_cycle = new_duty_cycle; + freq = new_freq; + + loops_per_sec = current_cpu_data.loops_per_jiffy; + loops_per_sec *= HZ; + + /* How many clocks in a microsecond?, avoiding long long divide */ + work = loops_per_sec; + work *= 4295; /* 4295 = 2^32 / 1e6 */ + conv_us_to_clocks = (work>>32); + + /* Carrier period in clocks, approach good up to 32GHz clock, + gets carrier frequency within 8Hz */ + period = loops_per_sec>>3; + period /= (freq>>3); + + /* Derive pulse and space from the period */ + + pulse_width = period*duty_cycle/100; + space_width = period - pulse_width; + dprintk("in init_timing_params, freq=%d, duty_cycle=%d, " + "clk/jiffy=%ld, pulse=%ld, space=%ld, " + "conv_us_to_clocks=%ld\n", + freq, duty_cycle, current_cpu_data.loops_per_jiffy, + pulse_width, space_width, conv_us_to_clocks); + return 0; +} +#else /* ! USE_RDTSC */ +static inline int init_timing_params(unsigned int new_duty_cycle, + unsigned int new_freq) +{ +/* period, pulse/space width are kept with 8 binary places - + * IE multiplied by 256. */ + if (256*1000000L/new_freq*new_duty_cycle/100 <= + LIRC_SERIAL_TRANSMITTER_LATENCY) + return(-EINVAL); + if (256*1000000L/new_freq*(100-new_duty_cycle)/100 <= + LIRC_SERIAL_TRANSMITTER_LATENCY) + return(-EINVAL); + duty_cycle = new_duty_cycle; + freq = new_freq; + period = 256*1000000L/freq; + pulse_width = period*duty_cycle/100; + space_width = period-pulse_width; + dprintk("in init_timing_params, freq=%d pulse=%ld, " + "space=%ld\n", freq, pulse_width, space_width); + return 0; +} +#endif /* USE_RDTSC */ + + +/* return value: space length delta */ + +static long send_pulse_irdeo(unsigned long length) +{ + long rawbits; + int i; + unsigned char output; + unsigned char chunk, shifted; + + /* how many bits have to be sent ? */ + rawbits = length*1152/10000; + if (duty_cycle > 50) + chunk = 3; + else + chunk = 1; + for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) { + shifted = chunk<<(i*3); + shifted >>= 1; + output &= (~shifted); + i++; + if (i == 3) { + soutp(UART_TX, output); + while (!(sinp(UART_LSR) & UART_LSR_THRE)); + output = 0x7f; + i = 0; + } + } + if (i != 0) { + soutp(UART_TX, output); + while (!(sinp(UART_LSR) & UART_LSR_TEMT)); + } + + if (i == 0) + return ((-rawbits)*10000/1152); + else + return ((3-i)*3*10000/1152+(-rawbits)*10000/1152); +} + +#ifdef USE_RDTSC +/* Version that uses Pentium rdtsc instruction to measure clocks */ + +/* This version does sub-microsecond timing using rdtsc instruction, + * and does away with the fudged LIRC_SERIAL_TRANSMITTER_LATENCY + * Implicitly i586 architecture... - Steve + */ + +static inline long send_pulse_homebrew_softcarrier(unsigned long length) +{ + int flag; + unsigned long target, start, now; + + /* Get going quick as we can */ + rdtscl(start); on(); + /* Convert length from microseconds to clocks */ + length *= conv_us_to_clocks; + /* And loop till time is up - flipping at right intervals */ + now = start; + target = pulse_width; + flag = 1; + while ((now-start) < length) { + /* Delay till flip time */ + do + rdtscl(now); + while ((now-start) < target); + + /* flip */ + if (flag) { + rdtscl(now); off(); + target += space_width; + } else { + rdtscl(now); on(); + target += pulse_width; + } + flag = !flag; + } + rdtscl(now); + return (((now-start)-length)/conv_us_to_clocks); +} +#else /* ! USE_RDTSC */ +/* Version using udelay() */ + +/* here we use fixed point arithmetic, with 8 + fractional bits. that gets us within 0.1% or so of the right average + frequency, albeit with some jitter in pulse length - Steve */ + +/* To match 8 fractional bits used for pulse/space length */ + +static inline long send_pulse_homebrew_softcarrier(unsigned long length) +{ + int flag; + unsigned long actual, target, d; + length <<= 8; + + actual = 0; target = 0; flag = 0; + while (actual < length) { + if (flag) { + off(); + target += space_width; + } else { + on(); + target += pulse_width; + } + d = (target-actual-LIRC_SERIAL_TRANSMITTER_LATENCY+128)>>8; + /* Note - we've checked in ioctl that the pulse/space + widths are big enough so that d is > 0 */ + udelay(d); + actual += (d<<8)+LIRC_SERIAL_TRANSMITTER_LATENCY; + flag = !flag; + } + return ((actual-length)>>8); +} +#endif /* USE_RDTSC */ + +static long send_pulse_homebrew(unsigned long length) +{ + if (length <= 0) + return 0; + + if (softcarrier) + return send_pulse_homebrew_softcarrier(length); + else { + on(); + safe_udelay(length); + return 0; + } +} + +static void send_space_irdeo(long length) +{ + if (length <= 0) + return; + + safe_udelay(length); +} + +static void send_space_homebrew(long length) +{ + off(); + if (length <= 0) + return; + safe_udelay(length); +} + +static inline void rbwrite(lirc_t l) +{ + if (lirc_buffer_full(&rbuf)) { /* no new signals will be accepted */ + dprintk("Buffer overrun\n"); + return; + } + _lirc_buffer_write_1(&rbuf, (void *)&l); +} + +static inline void frbwrite(lirc_t l) +{ + /* simple noise filter */ + static lirc_t pulse = 0L, space = 0L; + static unsigned int ptr; + + if (ptr > 0 && (l&PULSE_BIT)) { + pulse += l&PULSE_MASK; + if (pulse > 250) { + rbwrite(space); + rbwrite(pulse|PULSE_BIT); + ptr = 0; + pulse = 0; + } + return; + } + if (!(l&PULSE_BIT)) { + if (ptr == 0) { + if (l > 20000) { + space = l; + ptr++; + return; + } + } else { + if (l > 20000) { + space += pulse; + if (space > PULSE_MASK) + space = PULSE_MASK; + space += l; + if (space > PULSE_MASK) + space = PULSE_MASK; + pulse = 0; + return; + } + rbwrite(space); + rbwrite(pulse|PULSE_BIT); + ptr = 0; + pulse = 0; + } + } + rbwrite(l); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) +static irqreturn_t irq_handler(int i, void *blah) +#else +static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs) +#endif +{ + struct timeval tv; + int status, counter, dcd; + long deltv; + lirc_t data; + static int last_dcd = -1; + + if ((sinp(UART_IIR) & UART_IIR_NO_INT)) { + /* not our interrupt */ + return IRQ_RETVAL(IRQ_NONE); + } + + counter = 0; + do { + counter++; + status = sinp(UART_MSR); + if (counter > RS_ISR_PASS_LIMIT) { + printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: " + "We're caught!\n"); + break; + } + if ((status&hardware[type].signal_pin_change) && sense != -1) { + /* get current time */ + do_gettimeofday(&tv); + + /* New mode, written by Trent Piepho + . */ + + /* The old format was not very portable. + We now use the type lirc_t to pass pulses + and spaces to user space. + + If PULSE_BIT is set a pulse has been + received, otherwise a space has been + received. The driver needs to know if your + receiver is active high or active low, or + the space/pulse sense could be + inverted. The bits denoted by PULSE_MASK are + the length in microseconds. Lengths greater + than or equal to 16 seconds are clamped to + PULSE_MASK. All other bits are unused. + This is a much simpler interface for user + programs, as well as eliminating "out of + phase" errors with space/pulse + autodetection. */ + + /* calculate time since last interrupt in + microseconds */ + dcd = (status & hardware[type].signal_pin) ? 1:0; + + if (dcd == last_dcd) { + printk(KERN_WARNING LIRC_DRIVER_NAME + ": ignoring spike: %d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + continue; + } + + deltv = tv.tv_sec-lasttv.tv_sec; + if (tv.tv_sec < lasttv.tv_sec || + (tv.tv_sec == lasttv.tv_sec && + tv.tv_usec < lasttv.tv_usec)) { + printk(KERN_WARNING LIRC_DRIVER_NAME + ": AIEEEE: your clock just jumped " + "backwards\n"); + printk(KERN_WARNING LIRC_DRIVER_NAME + ": %d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + data = PULSE_MASK; + } else if (deltv > 15) { + data = PULSE_MASK; /* really long time */ + if (!(dcd^sense)) { /* sanity check */ + printk(KERN_WARNING LIRC_DRIVER_NAME + ": AIEEEE: " + "%d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + /* detecting pulse while this + MUST be a space! */ + sense = sense ? 0:1; + } + } else + data = (lirc_t) (deltv*1000000 + + tv.tv_usec - + lasttv.tv_usec); + frbwrite(dcd^sense ? data : (data|PULSE_BIT)); + lasttv = tv; + last_dcd = dcd; + wake_up_interruptible(&rbuf.wait_poll); + } + } while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */ + return IRQ_RETVAL(IRQ_HANDLED); +} + +static void hardware_init_port(void) +{ + unsigned long flags; + local_irq_save(flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Clear registers. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + +#if defined(LIRC_SERIAL_NSLU2) + if (type == LIRC_NSLU2) { /* Setup NSLU2 UART */ + /* Enable UART */ + soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE); + /* Disable Receiver data Time out interrupt */ + soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE); + /* set out2 = interupt unmask; off() doesn't set MCR + on NSLU2 */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + } +#endif + + /* Set line for power source */ + off(); + + /* Clear registers again to be sure. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + + switch (type) { + case LIRC_IRDEO: + case LIRC_IRDEO_REMOTE: + /* setup port to 7N1 @ 115200 Baud */ + /* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */ + + /* Set DLAB 1. */ + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + /* Set DLAB 0 + 7N1 */ + soutp(UART_LCR, UART_LCR_WLEN7); + /* THR interrupt already disabled at this point */ + break; + default: + break; + } + + local_irq_restore(flags); +} + +static int init_port(void) +{ + int i, nlow, nhigh; + + /* Reserve io region. */ +#if defined(LIRC_ALLOW_MMAPPED_IO) + /* Future MMAP-Developers: Attention! + For memory mapped I/O you *might* need to use ioremap() first, + for the NSLU2 it's done in boot code. */ + if (((iommap != 0) + && (request_mem_region(iommap, 8<= nhigh ? 1 : 0); + printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " + "%s receiver\n", sense ? "low":"high"); + } else + printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " + "%s receiver\n", sense ? "low":"high"); + + return 0; +} + +static int set_use_inc(void *data) +{ + int result; + unsigned long flags; + + /* Init read buffer. */ + if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0) + return -ENOMEM; + + /* initialize timestamp */ + do_gettimeofday(&lasttv); + + result = request_irq(irq, irq_handler, + IRQF_DISABLED | (share_irq ? IRQF_SHARED:0), + LIRC_DRIVER_NAME, (void *)&hardware); + + switch (result) { + case -EBUSY: + printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); + lirc_buffer_free(&rbuf); + return -EBUSY; + case -EINVAL: + printk(KERN_ERR LIRC_DRIVER_NAME + ": Bad irq number or handler\n"); + lirc_buffer_free(&rbuf); + return -EINVAL; + default: + dprintk("Interrupt %d, port %04x obtained\n", irq, io); + break; + }; + + local_irq_save(flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); + + local_irq_restore(flags); + + MOD_INC_USE_COUNT; + return 0; +} + +static void set_use_dec(void *data) +{ unsigned long flags; + + local_irq_save(flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + local_irq_restore(flags); + + free_irq(irq, (void *)&hardware); + + dprintk("freed IRQ %d\n", irq); + lirc_buffer_free(&rbuf); + + MOD_DEC_USE_COUNT; +} + +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *ppos) +{ + int i, count; + unsigned long flags; + long delta = 0; + + if (!(hardware[type].features&LIRC_CAN_SEND_PULSE)) + return(-EBADF); + + if (n%sizeof(lirc_t)) return(-EINVAL); + count = n/sizeof(lirc_t); + if (count > WBUF_LEN || count%2 == 0) return(-EINVAL); + if (copy_from_user(wbuf, buf, n)) return -EFAULT; + local_irq_save(flags); + if (type == LIRC_IRDEO) { + /* DTR, RTS down */ + on(); + } + for (i = 0; i < count; i++) { + if (i%2) + hardware[type].send_space(wbuf[i]-delta); + else + delta = hardware[type].send_pulse(wbuf[i]); + } + off(); + local_irq_restore(flags); + return(n); +} + +static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int result; + unsigned long value; + unsigned int ivalue; + + switch (cmd) { + case LIRC_GET_SEND_MODE: + if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) + return(-ENOIOCTLCMD); + + result = put_user(LIRC_SEND2MODE + (hardware[type].features&LIRC_CAN_SEND_MASK), + (unsigned long *) arg); + if (result) + return result; + break; + + case LIRC_SET_SEND_MODE: + if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) + return(-ENOIOCTLCMD); + + result = get_user(value, (unsigned long *) arg); + if (result) + return result; + /* only LIRC_MODE_PULSE supported */ + if (value != LIRC_MODE_PULSE) + return -ENOSYS; + break; + + case LIRC_GET_LENGTH: + return -ENOSYS; + break; + + case LIRC_SET_SEND_DUTY_CYCLE: + dprintk("SET_SEND_DUTY_CYCLE\n"); + if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if (ivalue <= 0 || ivalue > 100) + return -EINVAL; + return init_timing_params(ivalue, freq); + break; + + case LIRC_SET_SEND_CARRIER: + dprintk("SET_SEND_CARRIER\n"); + if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if (ivalue > 500000 || ivalue < 20000) + return -EINVAL; + return init_timing_params(duty_cycle, ivalue); + break; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static struct file_operations lirc_fops = { + .write = lirc_write, +}; + +static struct lirc_plugin plugin = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .get_queue = NULL, + .rbuf = &rbuf, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .ioctl = lirc_ioctl, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + +#ifdef MODULE + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +static struct platform_device *lirc_serial_igor_dev; + +static int __devinit lirc_serial_igor_probe(struct platform_device *dev) +{ + return 0; +} + +static int __devexit lirc_serial_igor_remove(struct platform_device * dev) +{ + return 0; +} + +static int lirc_serial_igor_suspend(struct platform_device *dev, + pm_message_t state) +{ + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* Disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Clear registers. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + + return 0; +} + +static int lirc_serial_igor_resume(struct platform_device *dev) +{ + unsigned long flags; + + hardware_init_port(); + + local_irq_save(flags); + /* Enable Interrupt */ + do_gettimeofday(&lasttv); + soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); + off(); + + lirc_buffer_clear(&rbuf); + + local_irq_restore(flags); + + return 0; +} + +static struct platform_driver lirc_serial_igor_driver = { + .probe = lirc_serial_igor_probe, + .remove = __devexit_p(lirc_serial_igor_remove), + .suspend = lirc_serial_igor_suspend, + .resume = lirc_serial_igor_resume, + .driver = { + .name = "lirc_serial_igor", + .owner = THIS_MODULE, + }, +}; + +static int __init lirc_serial_igor_init(void) +{ + int result; + + result = platform_driver_register(&lirc_serial_igor_driver); + if (result) { + printk("lirc register returned %d\n", result); + return result; + } + + lirc_serial_igor_dev = platform_device_alloc("lirc_serial_igor", 0); + if (!lirc_serial_igor_dev) { + result = -ENOMEM; + goto exit_driver_unregister; + } + + result = platform_device_add(lirc_serial_igor_dev); + if (result) + goto exit_device_put; + + return 0; + +exit_device_put: + platform_device_put(lirc_serial_igor_dev); +exit_driver_unregister: + platform_driver_unregister(&lirc_serial_igor_driver); + return result; +} + +static void __exit lirc_serial_igor_exit(void) +{ + platform_device_unregister(lirc_serial_igor_dev); + platform_driver_unregister(&lirc_serial_igor_driver); +} +#endif + +int __init init_module(void) +{ + int result; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) + result = lirc_serial_igor_init(); + if (result) + return result; +#endif + switch (type) { + case LIRC_HOMEBREW: + case LIRC_IRDEO: + case LIRC_IRDEO_REMOTE: + case LIRC_ANIMAX: + case LIRC_IGOR: +#if defined(LIRC_SERIAL_NSLU2) + case LIRC_NSLU2: +#endif + break; + default: + result = -EINVAL; + goto exit_serial_exit; + } + if (!softcarrier) { + switch (type) { + case LIRC_HOMEBREW: + case LIRC_IGOR: + case LIRC_NSLU2: + hardware[type].features &= + ~(LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER); + break; + } + } + result = init_port(); + if (result < 0) + goto exit_serial_exit; + plugin.features = hardware[type].features; + plugin.minor = lirc_register_plugin(&plugin); + if (plugin.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": register_chrdev failed!\n"); + result = -EIO; + goto exit_release; + } + return 0; +exit_release: + release_region(io, 8); +exit_serial_exit: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) + lirc_serial_igor_exit(); +#endif + return result; +} + +void __exit cleanup_module(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) + lirc_serial_igor_exit(); +#endif +#if defined(LIRC_ALLOW_MMAPPED_IO) + if (iommap != 0) + release_mem_region(iommap, 8<add_to_buf API. Properly + * handle broken fragments from the receiver. Up the + * sample rate and remove any pacing from + * fetch_more_data. Fixes all known issues. + * + * TODO + * - Fix up minor number, registration of major/minor with usb subsystem + * + */ +/* + * USB Skeleton driver - 1.1 + * + * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + * + * This driver is to be used as a skeleton driver to be able to create a + * USB driver quickly. The design of it is based on the usb-serial and + * dc2xx drivers. + * + * Thanks to Oliver Neukum, David Brownell, and Alan Stern for their help + * in debugging this driver. + * + * + * History: + * + * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev() + * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and + * disconnect. Fix transfer amount in read(). Use + * macros instead of magic numbers in probe(). Change + * size variables to size_t. Show how to eliminate + * DMA bounce buffer. + * 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array. + * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device + * driver. + * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do + * not have both a bulk in and bulk out endpoint. + * Thanks to Holger Waechtler for the fix. + * 2001_11_05 - 0.6 - fix minor locking problem in skel_disconnect. + * Thanks to Pete Zaitcev for the fix. + * 2001_09_04 - 0.5 - fix devfs bug in skel_disconnect. Thanks to wim delvaux + * 2001_08_21 - 0.4 - more small bug fixes. + * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel + * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people + * 2001_05_01 - 0.1 - first version + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef KERNEL_2_5 +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +#include +#else +#include +#endif +#else +#include +#include +#include +#include +#include +#include +#endif + +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif + +#include "kcompat.h" +#include "lirc.h" +#include "lirc_dev/lirc_dev.h" + +/* Use our own dbg macro */ +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG __FILE__ ": " \ + fmt "\n", ## args); \ + } while (0) + +/* Version Information */ +#define DRIVER_VERSION "v0.2" +#define DRIVER_AUTHOR "Dan Conti, dconti@acm.wwu.edu" +#define DRIVER_DESC "USB Microsoft IR Transceiver Driver" +#define DRIVER_NAME "lirc_mceusb" + +/* Define these values to match your device */ +#define USB_MCEUSB_VENDOR_ID 0x045e +#define USB_MCEUSB_PRODUCT_ID 0x006d + +/* table of devices that work with this driver */ +static struct usb_device_id mceusb_table[] = { + { USB_DEVICE(USB_MCEUSB_VENDOR_ID, USB_MCEUSB_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + +/* we can have up to this number of device plugged in at once */ +#define MAX_DEVICES 16 + +/* Structure to hold all of our device specific stuff */ +struct usb_skel { + struct usb_device *udev; /* save off the usb device pointer */ + struct usb_interface *interface; /* the interface for this device */ + unsigned char minor; /* the starting minor number for this device */ + unsigned char num_ports; /* the number of ports this device has */ + char num_interrupt_in; /* number of interrupt in endpoints */ + char num_bulk_in; /* number of bulk in endpoints */ + char num_bulk_out; /* number of bulk out endpoints */ + + unsigned char *bulk_in_buffer; /* the buffer to receive data */ + int bulk_in_size; /* the size of the receive buffer */ + __u8 bulk_in_endpointAddr; /* the address of bulk in endpoint */ + + unsigned char *bulk_out_buffer; /* the buffer to send data */ + int bulk_out_size; /* the size of the send buffer */ + struct urb *write_urb; /* the urb used to send data */ + __u8 bulk_out_endpointAddr; /* the address of bulk out endpoint */ + + atomic_t write_busy; /* true iff write urb is busy */ + struct completion write_finished; /* wait for the write to finish */ + + wait_queue_head_t wait_q; /* for timeouts */ + int open_count; /* number of times this port has been opened */ + struct semaphore sem; /* locks this structure */ + + int present; /* if the device is not disconnected */ + + struct lirc_plugin *plugin; + + lirc_t lircdata[256]; /* place to store data until lirc processes it */ + int lircidx; /* current index */ + int lirccnt; /* remaining values */ + + int usb_valid_bytes_in_bulk_buffer; /* leftover data from prior read */ + int mce_bytes_left_in_packet; /* for packets split across reads */ + + /* Value to hold the last received space; 0 if last value + * received was a pulse */ + int last_space; + +#ifdef KERNEL_2_5 + dma_addr_t dma_in; + dma_addr_t dma_out; +#endif +}; + +#define MCE_TIME_UNIT 50 + +/* driver api */ +#ifdef KERNEL_2_5 +static int mceusb_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void mceusb_disconnect(struct usb_interface *interface); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void mceusb_write_bulk_callback(struct urb *urb, struct pt_regs *regs); +#else +static void mceusb_write_bulk_callback(struct urb *urb); +#endif +#else +static void *mceusb_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); +static void mceusb_disconnect(struct usb_device *dev, void *ptr); +static void mceusb_write_bulk_callback(struct urb *urb); +#endif + +/* read data from the usb bus; convert to mode2 */ +static int msir_fetch_more_data(struct usb_skel *dev, int dont_block); + +/* helper functions */ +static void msir_cleanup(struct usb_skel *dev); +static void set_use_dec(void *data); +static int set_use_inc(void *data); + +/* array of pointers to our devices that are currently connected */ +static struct usb_skel *minor_table[MAX_DEVICES]; + +/* lock to protect the minor_table structure */ +static DECLARE_MUTEX(minor_table_mutex); +static void mceusb_setup(struct usb_device *udev); + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver mceusb_driver = { + LIRC_THIS_MODULE(.owner = THIS_MODULE) + .name = DRIVER_NAME, + .probe = mceusb_probe, + .disconnect = mceusb_disconnect, + .id_table = mceusb_table, +}; + + +/** + * usb_mceusb_debug_data + */ +static inline void usb_mceusb_debug_data(const char *function, int size, + const unsigned char *data) +{ + int i; + if (!debug) + return; + + printk(KERN_DEBUG __FILE__": %s - length = %d, data = ", + function, size); + for (i = 0; i < size; ++i) + printk(KERN_DEBUG "%.2x ", data[i]); + printk(KERN_DEBUG "\n"); +} + +/** + *mceusb_delete + */ +static inline void mceusb_delete(struct usb_skel *dev) +{ + dprintk("%s", __func__); + minor_table[dev->minor] = NULL; +#ifdef KERNEL_2_5 + usb_buffer_free(dev->udev, dev->bulk_in_size, + dev->bulk_in_buffer, dev->dma_in); + usb_buffer_free(dev->udev, dev->bulk_out_size, + dev->bulk_out_buffer, dev->dma_out); +#else + if (dev->bulk_in_buffer != NULL) + kfree(dev->bulk_in_buffer); + if (dev->bulk_out_buffer != NULL) + kfree(dev->bulk_out_buffer); +#endif + if (dev->write_urb != NULL) + usb_free_urb(dev->write_urb); + kfree(dev); +} + +static void mceusb_setup(struct usb_device *udev) +{ + char data[8]; + int res; + + memset(data, 0, 8); + + /* Get Status */ + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN, + 0, 0, data, 2, HZ * 3); + + /* res = usb_get_status( udev, 0, 0, data ); */ + dprintk("%s - res = %d status = 0x%x 0x%x", __func__, + res, data[0], data[1]); + + /* This is a strange one. They issue a set address to the device + * on the receive control pipe and expect a certain value pair back + */ + memset(data, 0, 8); + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 5, USB_TYPE_VENDOR, 0, 0, + data, 2, HZ * 3); + dprintk("%s - res = %d, devnum = %d", __func__, res, udev->devnum); + dprintk("%s - data[0] = %d, data[1] = %d", __func__, + data[0], data[1]); + + + /* set feature */ + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, + 0xc04e, 0x0000, NULL, 0, HZ * 3); + + dprintk("%s - res = %d", __func__, res); + + /* These two are sent by the windows driver, but stall for + * me. I dont have an analyzer on the linux side so i can't + * see what is actually different and why the device takes + * issue with them + */ +#if 0 + /* this is some custom control message they send */ + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, USB_TYPE_VENDOR, + 0x0808, 0x0000, NULL, 0, HZ * 3); + + dprintk("%s - res = %d", __func__, res); + + /* this is another custom control message they send */ + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x02, USB_TYPE_VENDOR, + 0x0000, 0x0100, NULL, 0, HZ * 3); + + dprintk("%s - res = %d", __func__, res); +#endif +} + +static void msir_cleanup(struct usb_skel *dev) +{ + memset(dev->bulk_in_buffer, 0, dev->bulk_in_size); + + dev->usb_valid_bytes_in_bulk_buffer = 0; + + dev->last_space = PULSE_MASK; + + dev->mce_bytes_left_in_packet = 0; + dev->lircidx = 0; + dev->lirccnt = 0; + memset(dev->lircdata, 0, sizeof(dev->lircdata)); +} + +static int set_use_inc(void *data) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static void set_use_dec(void *data) +{ + MOD_DEC_USE_COUNT; +} + +/* + * msir_fetch_more_data + * + * The goal here is to read in more remote codes from the remote. In + * the event that the remote isn't sending us anything, the caller + * will block until a key is pressed (i.e. this performs phys read, + * filtering, and queueing of data) unless dont_block is set to 1; in + * this situation, it will perform a few reads and will exit out if it + * does not see any appropriate data + * + * dev->sem should be locked when this function is called - fine grain + * locking isn't really important here anyways + * + * This routine always returns the number of words available + * + */ +static int msir_fetch_more_data(struct usb_skel *dev, int dont_block) +{ + int retries = 0; + int words_to_read = + (sizeof(dev->lircdata)/sizeof(lirc_t)) - dev->lirccnt; + int partial, this_read = 0; + int bulkidx = 0; + int bytes_left_in_packet = 0; + signed char *signedp = (signed char*)dev->bulk_in_buffer; + + if (words_to_read == 0) + return dev->lirccnt; + + /* this forces all existing data to be read by lirc before we + * issue another usb command. this is the only form of + * throttling we have + */ + if (dev->lirccnt) + return dev->lirccnt; + + /* reserve room for our leading space */ + if (dev->last_space) + words_to_read--; + + while (words_to_read) { + /* handle signals and USB disconnects */ + if (signal_pending(current)) + return dev->lirccnt ? dev->lirccnt : -EINTR; + if (!dev->udev) + return -ENODEV; + + bulkidx = 0; + + /* + * perform data read (phys or from previous buffer) + */ + + /* use leftovers if present, otherwise perform a read */ + if (dev->usb_valid_bytes_in_bulk_buffer) { + this_read = dev->usb_valid_bytes_in_bulk_buffer; + partial = this_read; + dev->usb_valid_bytes_in_bulk_buffer = 0; + } else { + int retval; + + this_read = dev->bulk_in_size; + partial = 0; + retval = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), + (unsigned char *)dev->bulk_in_buffer, + this_read, &partial, HZ*10); + + /* retry a few times on overruns; map all + other errors to -EIO */ + if (retval) { + if (retval == -EOVERFLOW && retries < 5) { + retries++; + interruptible_sleep_on_timeout( + &dev->wait_q, HZ); + continue; + } else + return -EIO; + } + + retries = 0; + if (partial) + this_read = partial; + + /* skip the header */ + bulkidx += 2; + + /* check for empty reads (header only) */ + if (this_read == 2) { + /* assume no data */ + if (dont_block) + break; + + /* sleep for a bit before performing + another read */ + interruptible_sleep_on_timeout(&dev->wait_q, 1); + continue; + } + } + + /* + * process data + */ + + /* at this point this_read is > 0 */ + while (bulkidx < this_read && + (words_to_read > (dev->last_space ? 1 : 0))) { + /* while( bulkidx < this_read && words_to_read) */ + int keycode; + int pulse = 0; + + /* read packet length if needed */ + if (!bytes_left_in_packet) { + /* we assume we are on a packet length + * value. it is possible, in some + * cases, to get a packet that does + * not start with a length, apparently + * due to some sort of fragmenting, + * but occaisonally we do not receive + * the second half of a fragment + */ + bytes_left_in_packet = + 128 + signedp[bulkidx++]; + + /* unfortunately rather than keep all + * the data in the packetized format, + * the transceiver sends a trailing 8 + * bytes that aren't part of the + * transmittion from the remote, + * aren't packetized, and dont really + * have any value. we can basically + * tell we have hit them if 1) we have + * a loooong space currently stored + * up, and 2) the bytes_left value for + * this packet is obviously wrong + */ + if (bytes_left_in_packet > 4) { + if (dev->mce_bytes_left_in_packet) { + bytes_left_in_packet = + dev->mce_bytes_left_in_packet; + bulkidx--; + } + bytes_left_in_packet = 0; + bulkidx = this_read; + } + + /* always clear this if we have a + valid packet */ + dev->mce_bytes_left_in_packet = 0; + + /* continue here to verify we haven't + hit the end of the bulk_in */ + continue; + + } + + /* + * generate mode2 + */ + + keycode = signedp[bulkidx++]; + if (keycode < 0) { + pulse = 1; + keycode += 128; + } + keycode *= MCE_TIME_UNIT; + + bytes_left_in_packet--; + + if (pulse) { + if (dev->last_space) { + dev->lircdata[dev->lirccnt++] = + dev->last_space; + dev->last_space = 0; + words_to_read--; + + /* clear the lirc_t for the pulse */ + dev->lircdata[dev->lirccnt] = 0; + } + dev->lircdata[dev->lirccnt] += keycode; + dev->lircdata[dev->lirccnt] |= PULSE_BIT; + } else { + /* on pulse->space transition, add one + for the existing pulse */ + if (dev->lircdata[dev->lirccnt] && + !dev->last_space) { + dev->lirccnt++; + words_to_read--; + } + + dev->last_space += keycode; + } + } + } + + /* save off some info if we are exiting mid-packet, or with + leftovers */ + if (bytes_left_in_packet) + dev->mce_bytes_left_in_packet = bytes_left_in_packet; + if (bulkidx < this_read) { + dev->usb_valid_bytes_in_bulk_buffer = (this_read - bulkidx); + memcpy(dev->bulk_in_buffer, &(dev->bulk_in_buffer[bulkidx]), + dev->usb_valid_bytes_in_bulk_buffer); + } + return dev->lirccnt; +} + +/* mceusb_add_to_buf: called by lirc_dev to fetch all available keys + * this is used as a polling interface for us: since we set + * plugin->sample_rate we will periodically get the below call to + * check for new data returns 0 on success, or -ENODATA if nothing is + * available + */ +static int mceusb_add_to_buf(void *data, struct lirc_buffer *buf) +{ + struct usb_skel *dev = (struct usb_skel *) data; + + down(&dev->sem); + + /* verify device still present */ + if (dev->udev == NULL) { + up(&dev->sem); + return -ENODEV; + } + + if (!dev->lirccnt) { + int res; + dev->lircidx = 0; + + res = msir_fetch_more_data(dev, 1); + + if (res == 0) + res = -ENODATA; + if (res < 0) { + up(&dev->sem); + return res; + } + } + + if (dev->lirccnt) { + int keys_to_copy; + + /* determine available buffer space and available data */ + keys_to_copy = lirc_buffer_available(buf); + if (keys_to_copy > dev->lirccnt) + keys_to_copy = dev->lirccnt; + + lirc_buffer_write_n(buf, + (unsigned char *) &(dev->lircdata[dev->lircidx]), + keys_to_copy); + dev->lircidx += keys_to_copy; + dev->lirccnt -= keys_to_copy; + + up(&dev->sem); + return 0; + } + + up(&dev->sem); + return -ENODATA; +} + +/** + * mceusb_write_bulk_callback + */ +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void mceusb_write_bulk_callback(struct urb *urb, struct pt_regs *regs) +#else +static void mceusb_write_bulk_callback(struct urb *urb) +#endif +{ + struct usb_skel *dev = (struct usb_skel *)urb->context; + + dprintk("%s - minor %d", __func__, dev->minor); + + if ((urb->status != -ENOENT) && + (urb->status != -ECONNRESET)) { + dprintk("%s - nonzero write buld status received: %d", + __func__, urb->status); + return; + } + + return; +} + +/** + * mceusb_probe + * + * Called by the usb core when a new device is connected that it + * thinks this driver might be interested in. + */ +#ifdef KERNEL_2_5 +static int mceusb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct usb_host_interface *iface_desc; +#else +static void *mceusb_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct usb_interface *interface = &udev->actconfig->interface[ifnum]; + struct usb_interface_descriptor *iface_desc; +#endif + struct usb_skel *dev = NULL; + struct usb_endpoint_descriptor *endpoint; + + struct lirc_plugin *plugin; + struct lirc_buffer *rbuf; + + int minor; + size_t buffer_size; + int i; + int retval = -ENOMEM; + char junk[64]; + int partial = 0; + + /* See if the device offered us matches what we can accept */ + if (cpu_to_le16(udev->descriptor.idVendor) != USB_MCEUSB_VENDOR_ID || + cpu_to_le16(udev->descriptor.idProduct) != USB_MCEUSB_PRODUCT_ID) { + dprintk("Wrong Vendor/Product IDs"); +#ifdef KERNEL_2_5 + return -ENODEV; +#else + return NULL; +#endif + } + + /* select a "subminor" number (part of a minor number) */ + down(&minor_table_mutex); + for (minor = 0; minor < MAX_DEVICES; ++minor) { + if (minor_table[minor] == NULL) + break; + } + if (minor >= MAX_DEVICES) { + info("Too many devices plugged in, " + "can not handle this device."); + goto error; + } + + /* allocate memory for our device state and initialize it */ + dev = kmalloc(sizeof(struct usb_skel), GFP_KERNEL); + if (dev == NULL) { + err("Out of memory"); +#ifdef KERNEL_2_5 + retval = -ENOMEM; +#endif + goto error; + } + minor_table[minor] = dev; + + memset(dev, 0x00, sizeof(*dev)); + init_MUTEX(&dev->sem); + dev->udev = udev; + dev->interface = interface; + dev->minor = minor; + + /* set up the endpoint information */ + /* check out the endpoints */ + /* use only the first bulk-in and bulk-out endpoints */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) + iface_desc = &interface->altsetting[0]; +#else + iface_desc = interface->cur_altsetting; +#endif + +#ifdef KERNEL_2_5 + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; +#else + for (i = 0; i < iface_desc->bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i]; +#endif + if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK)) { + dprintk("we found a bulk in endpoint"); + buffer_size = endpoint->wMaxPacketSize; + dev->bulk_in_size = buffer_size; + dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; +#ifdef KERNEL_2_5 + dev->bulk_in_buffer = + usb_buffer_alloc(udev, buffer_size, + GFP_ATOMIC, &dev->dma_in); +#else + dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); +#endif + if (!dev->bulk_in_buffer) { + err("Couldn't allocate bulk_in_buffer"); + goto error; + } + } + + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == 0x00) + && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK)) { + dprintk("we found a bulk out endpoint"); +#ifdef KERNEL_2_5 + dev->write_urb = usb_alloc_urb(0, GFP_KERNEL); +#else + dev->write_urb = usb_alloc_urb(0); +#endif + if (!dev->write_urb) { + err("No free urbs available"); + goto error; + } + buffer_size = endpoint->wMaxPacketSize; + dev->bulk_out_size = buffer_size; + dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; +#ifdef KERNEL_2_5 + dev->bulk_out_buffer = + usb_buffer_alloc(udev, buffer_size, + GFP_ATOMIC, &dev->dma_out); +#else + dev->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); +#endif + if (!dev->bulk_out_buffer) { + err("Couldn't allocate bulk_out_buffer"); + goto error; + } +#ifdef KERNEL_2_5 + usb_fill_bulk_urb(dev->write_urb, udev, + usb_sndbulkpipe + (udev, endpoint->bEndpointAddress), + dev->bulk_out_buffer, buffer_size, + mceusb_write_bulk_callback, dev); +#else + FILL_BULK_URB(dev->write_urb, udev, + usb_sndbulkpipe(udev, + endpoint->bEndpointAddress), + dev->bulk_out_buffer, buffer_size, + mceusb_write_bulk_callback, dev); +#endif + } + } + + if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { + err("Couldn't find both bulk-in and bulk-out endpoints"); + goto error; + } + + /* init the waitq */ + init_waitqueue_head(&dev->wait_q); + + + /* Set up our lirc plugin */ + plugin = kmalloc(sizeof(struct lirc_plugin), GFP_KERNEL); + if (!plugin) { + err("out of memory"); + goto error; + } + memset(plugin, 0, sizeof(struct lirc_plugin)); + + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) { + err("out of memory"); + kfree(plugin); + goto error; + } + + /* the lirc_atiusb module doesn't memset rbuf here ... ? */ + if (lirc_buffer_init(rbuf, sizeof(lirc_t), 128)) { + err("out of memory"); + kfree(plugin); + kfree(rbuf); + goto error; + } + + strcpy(plugin->name, DRIVER_NAME " "); + plugin->minor = minor; + plugin->code_length = sizeof(lirc_t) * 8; + plugin->features = LIRC_CAN_REC_MODE2; /* | LIRC_CAN_SEND_MODE2; */ + plugin->data = dev; + plugin->rbuf = rbuf; + plugin->ioctl = NULL; + plugin->set_use_inc = &set_use_inc; + plugin->set_use_dec = &set_use_dec; + plugin->sample_rate = 80; /* sample at 100hz (10ms) */ + plugin->add_to_buf = &mceusb_add_to_buf; + /* plugin->fops = &mceusb_fops; */ +#ifdef LIRC_HAVE_SYSFS + plugin->dev = &udev->dev; +#endif + plugin->owner = THIS_MODULE; + if (lirc_register_plugin(plugin) < 0) { + kfree(plugin); + lirc_buffer_free(rbuf); + kfree(rbuf); + goto error; + } + dev->plugin = plugin; + + /* clear off the first few messages. these look like + * calibration or test data, i can't really tell + * this also flushes in case we have random ir data queued up + */ + for (i = 0; i < 40; i++) + (void) usb_bulk_msg(udev, + usb_rcvbulkpipe(udev, + dev->bulk_in_endpointAddr), + junk, 64, &partial, HZ*10); + + msir_cleanup(dev); + mceusb_setup(udev); + +#ifdef KERNEL_2_5 + /* we can register the device now, as it is ready */ + usb_set_intfdata(interface, dev); +#endif + /* let the user know what node this device is now attached to */ + /* info("USB Microsoft IR Transceiver device now attached to msir%d", + dev->minor); */ + up(&minor_table_mutex); +#ifdef KERNEL_2_5 + return 0; +#else + return dev; +#endif +error: + mceusb_delete(dev); + dev = NULL; + dprintk("%s: retval = %x", __func__, retval); + up(&minor_table_mutex); +#ifdef KERNEL_2_5 + return retval; +#else + return NULL; +#endif +} + +/** + * mceusb_disconnect + * + * Called by the usb core when the device is removed from the system. + * + * This routine guarantees that the driver will not submit any more urbs + * by clearing dev->udev. It is also supposed to terminate any currently + * active urbs. Unfortunately, usb_bulk_msg(), used in skel_read(), does + * not provide any way to do this. But at least we can cancel an active + * write. + */ +#ifdef KERNEL_2_5 +static void mceusb_disconnect(struct usb_interface *interface) +#else +static void mceusb_disconnect(struct usb_device *udev, void *ptr) +#endif +{ + struct usb_skel *dev; + int minor; +#ifdef KERNEL_2_5 + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); +#else + dev = (struct usb_skel *)ptr; +#endif + + down(&minor_table_mutex); + down(&dev->sem); + minor = dev->minor; + + /* unhook lirc things */ + lirc_unregister_plugin(minor); + lirc_buffer_free(dev->plugin->rbuf); + kfree(dev->plugin->rbuf); + kfree(dev->plugin); +#ifdef KERNEL_2_5 + /* terminate an ongoing write */ + if (atomic_read(&dev->write_busy)) { + usb_kill_urb(dev->write_urb); + wait_for_completion(&dev->write_finished); + } + + /* prevent device read, write and ioctl */ + dev->present = 0; +#endif + + mceusb_delete(dev); + + info("Microsoft IR Transceiver #%d now disconnected", minor); + up(&dev->sem); + up(&minor_table_mutex); +} + + + +/** + * usb_mceusb_init + */ +static int __init usb_mceusb_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&mceusb_driver); +#ifdef KERNEL_2_5 + if (result) { +#else + if (result < 0) { +#endif + err("usb_register failed for the " DRIVER_NAME + " driver. error number %d", result); +#ifdef KERNEL_2_5 + return result; +#else + return -1; +#endif + } + + info(DRIVER_DESC " " DRIVER_VERSION); + return 0; +} + + +/** + * usb_mceusb_exit + */ +static void __exit usb_mceusb_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&mceusb_driver); +} + +module_init(usb_mceusb_init); +module_exit(usb_mceusb_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, mceusb_table); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +EXPORT_NO_SYMBOLS; --- linux-2.6.27.orig/ubuntu/lirc/lirc_mceusb/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_mceusb/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_dev/lirc_dev.h +++ linux-2.6.27/ubuntu/lirc/lirc_dev/lirc_dev.h @@ -0,0 +1,264 @@ +/* + * LIRC base driver + * + * (L) by Artur Lipowski + * This code is licensed under GNU GPL + * + * $Id: lirc_dev.h,v 1.22 2008/01/13 10:45:02 lirc Exp $ + * + */ + +#ifndef _LINUX_LIRC_DEV_H +#define _LINUX_LIRC_DEV_H + +#define MAX_IRCTL_DEVICES 4 +#define BUFLEN 16 + +/* #define LIRC_BUFF_POWER_OF_2 */ +#ifdef LIRC_BUFF_POWER_OF_2 +#define mod(n, div) ((n) & ((div) - 1)) +#else +#define mod(n, div) ((n) % (div)) +#endif +#include +#include + +struct lirc_buffer { + wait_queue_head_t wait_poll; + spinlock_t lock; + + unsigned char *data; + unsigned int chunk_size; + unsigned int size; /* in chunks */ + unsigned int fill; /* in chunks */ + int head, tail; /* in chunks */ + /* Using chunks instead of bytes pretends to simplify boundary checking + * And should allow for some performance fine tunning later */ +}; +static inline void _lirc_buffer_clear(struct lirc_buffer *buf) +{ + buf->head = 0; + buf->tail = 0; + buf->fill = 0; +} +static inline int lirc_buffer_init(struct lirc_buffer *buf, + unsigned int chunk_size, + unsigned int size) +{ + /* Adjusting size to the next power of 2 would allow for + * inconditional LIRC_BUFF_POWER_OF_2 optimization */ + init_waitqueue_head(&buf->wait_poll); + spin_lock_init(&buf->lock); + _lirc_buffer_clear(buf); + buf->chunk_size = chunk_size; + buf->size = size; + buf->data = kmalloc(size*chunk_size, GFP_KERNEL); + if (buf->data == NULL) + return -1; + memset(buf->data, 0, size*chunk_size); + return 0; +} +static inline void lirc_buffer_free(struct lirc_buffer *buf) +{ + kfree(buf->data); + buf->data = NULL; + buf->head = 0; + buf->tail = 0; + buf->fill = 0; + buf->chunk_size = 0; + buf->size = 0; +} +static inline int lirc_buffer_full(struct lirc_buffer *buf) +{ + return (buf->fill >= buf->size); +} +static inline int lirc_buffer_empty(struct lirc_buffer *buf) +{ + return !(buf->fill); +} +static inline int lirc_buffer_available(struct lirc_buffer *buf) +{ + return (buf->size - buf->fill); +} +static inline void lirc_buffer_lock(struct lirc_buffer *buf, + unsigned long *flags) +{ + spin_lock_irqsave(&buf->lock, *flags); +} +static inline void lirc_buffer_unlock(struct lirc_buffer *buf, + unsigned long *flags) +{ + spin_unlock_irqrestore(&buf->lock, *flags); +} +static inline void lirc_buffer_clear(struct lirc_buffer *buf) +{ + unsigned long flags; + lirc_buffer_lock(buf, &flags); + _lirc_buffer_clear(buf); + lirc_buffer_unlock(buf, &flags); +} +static inline void _lirc_buffer_remove_1(struct lirc_buffer *buf) +{ + buf->head = mod(buf->head+1, buf->size); + buf->fill -= 1; +} +static inline void lirc_buffer_remove_1(struct lirc_buffer *buf) +{ + unsigned long flags; + lirc_buffer_lock(buf, &flags); + _lirc_buffer_remove_1(buf); + lirc_buffer_unlock(buf, &flags); +} +static inline void _lirc_buffer_read_1(struct lirc_buffer *buf, + unsigned char *dest) +{ + memcpy(dest, &buf->data[buf->head*buf->chunk_size], buf->chunk_size); + buf->head = mod(buf->head+1, buf->size); + buf->fill -= 1; +} +static inline void lirc_buffer_read_1(struct lirc_buffer *buf, + unsigned char *dest) +{ + unsigned long flags; + lirc_buffer_lock(buf, &flags); + _lirc_buffer_read_1(buf, dest); + lirc_buffer_unlock(buf, &flags); +} +static inline void _lirc_buffer_write_1(struct lirc_buffer *buf, + unsigned char *orig) +{ + memcpy(&buf->data[buf->tail*buf->chunk_size], orig, buf->chunk_size); + buf->tail = mod(buf->tail+1, buf->size); + buf->fill++; +} +static inline void lirc_buffer_write_1(struct lirc_buffer *buf, + unsigned char *orig) +{ + unsigned long flags; + lirc_buffer_lock(buf, &flags); + _lirc_buffer_write_1(buf, orig); + lirc_buffer_unlock(buf, &flags); +} +static inline void _lirc_buffer_write_n(struct lirc_buffer *buf, + unsigned char *orig, int count) +{ + memcpy(&buf->data[buf->tail * buf->chunk_size], orig, + count * buf->chunk_size); + buf->tail = mod(buf->tail + count, buf->size); + buf->fill += count; +} +static inline void lirc_buffer_write_n(struct lirc_buffer *buf, + unsigned char *orig, int count) +{ + unsigned long flags; + int space1; + + lirc_buffer_lock(buf, &flags); + if (buf->head > buf->tail) + space1 = buf->head - buf->tail; + else + space1 = buf->size - buf->tail; + + if (count > space1) { + _lirc_buffer_write_n(buf, orig, space1); + _lirc_buffer_write_n(buf, orig+(space1*buf->chunk_size), + count-space1); + } else { + _lirc_buffer_write_n(buf, orig, count); + } + lirc_buffer_unlock(buf, &flags); +} + +struct lirc_plugin { + char name[40]; + int minor; + int code_length; + int sample_rate; + unsigned long features; + void *data; + int (*add_to_buf) (void *data, struct lirc_buffer *buf); + wait_queue_head_t* (*get_queue) (void *data); + struct lirc_buffer *rbuf; + int (*set_use_inc) (void *data); + void (*set_use_dec) (void *data); + int (*ioctl) (struct inode *, struct file *, unsigned int, + unsigned long); + struct file_operations *fops; + struct device *dev; + struct module *owner; +}; +/* name: + * this string will be used for logs + * + * minor: + * indicates minor device (/dev/lirc) number for registered plugin + * if caller fills it with negative value, then the first free minor + * number will be used (if available) + * + * code_length: + * length of the remote control key code expressed in bits + * + * sample_rate: + * sample_rate equal to 0 means that no polling will be performed and + * add_to_buf will be triggered by external events (through task queue + * returned by get_queue) + * + * data: + * it may point to any plugin data and this pointer will be passed to + * all callback functions + * + * add_to_buf: + * add_to_buf will be called after specified period of the time or + * triggered by the external event, this behavior depends on value of + * the sample_rate this function will be called in user context. This + * routine should return 0 if data was added to the buffer and + * -ENODATA if none was available. This should add some number of bits + * evenly divisible by code_length to the buffer + * + * get_queue: + * this callback should return a pointer to the task queue which will + * be used for external event waiting + * + * rbuf: + * if not NULL, it will be used as a read buffer, you will have to + * write to the buffer by other means, like irq's (see also + * lirc_serial.c). + * + * set_use_inc: + * set_use_inc will be called after device is opened + * + * set_use_dec: + * set_use_dec will be called after device is closed + * + * ioctl: + * Some ioctl's can be directly handled by lirc_dev but will be + * forwared here if not NULL and only handled if it returns + * -ENOIOCTLCMD (see also lirc_serial.c). + * + * fops: + * file_operations for drivers which don't fit the current plugin model. + * + * owner: + * the module owning this struct + * + */ + + +/* following functions can be called ONLY from user context + * + * returns negative value on error or minor number + * of the registered device if success + * contens of the structure pointed by p is copied + */ +extern int lirc_register_plugin(struct lirc_plugin *p); + +/* returns negative value on error or 0 if success +*/ +extern int lirc_unregister_plugin(int minor); + +/* Returns the private data stored in the lirc_plugin + * associated with the given device file pointer. + */ +void *lirc_get_pdata(struct file *file); + +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_dev/lirc_dev.c +++ linux-2.6.27/ubuntu/lirc/lirc_dev/lirc_dev.c @@ -0,0 +1,960 @@ +/* + * LIRC base driver + * + * (L) by Artur Lipowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: lirc_dev.c,v 1.58 2008/05/14 16:37:49 lirc Exp $ + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) +#error "**********************************************************" +#error " Sorry, this driver needs kernel version 2.2.18 or higher " +#error "**********************************************************" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#include +#else +#include +#include +#endif +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +#include +#endif +#define __KERNEL_SYSCALLS__ +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) +#include +#endif + +#include "kcompat.h" + +/* SysFS header */ +#if defined(LIRC_HAVE_SYSFS) +#include +#endif + +#include "lirc.h" +#include "lirc_dev.h" + +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG fmt, ## args); \ + } while (0) + +#define IRCTL_DEV_NAME "BaseRemoteCtl" +#define SUCCESS 0 +#define NOPLUG -1 +#define LOGHEAD "lirc_dev (%s[%d]): " + +struct irctl { + struct lirc_plugin p; + int attached; + int open; + + struct semaphore buffer_sem; + struct lirc_buffer *buf; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + int tpid; + struct completion *t_notify; + struct completion *t_notify2; + int shutdown; +#else + struct task_struct *task; +#endif + long jiffies_to_wait; + +#ifdef LIRC_HAVE_DEVFS_24 + devfs_handle_t devfs_handle; +#endif +}; + +DECLARE_MUTEX(plugin_lock); + +static struct irctl irctls[MAX_IRCTL_DEVICES]; +static struct file_operations fops; + +/* Only used for sysfs but defined to void otherwise */ +static lirc_class_t *lirc_class; + +/* helper function + * initializes the irctl structure + */ +static inline void init_irctl(struct irctl *ir) +{ + memset(&ir->p, 0, sizeof(struct lirc_plugin)); + sema_init(&ir->buffer_sem, 1); + ir->p.minor = NOPLUG; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + ir->tpid = -1; + ir->t_notify = NULL; + ir->t_notify2 = NULL; + ir->shutdown = 0; +#else + ir->task = NULL; +#endif + ir->jiffies_to_wait = 0; + + ir->open = 0; + ir->attached = 0; +} + +static void cleanup(struct irctl *ir) +{ + dprintk(LOGHEAD "cleaning up\n", ir->p.name, ir->p.minor); + +#ifdef LIRC_HAVE_DEVFS_24 + devfs_unregister(ir->devfs_handle); +#endif +#ifdef LIRC_HAVE_DEVFS_26 + devfs_remove(DEV_LIRC "/%u", ir->p.minor); +#endif + lirc_device_destroy(lirc_class, + MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); + + if (ir->buf != ir->p.rbuf) { + lirc_buffer_free(ir->buf); + kfree(ir->buf); + } + ir->buf = NULL; + + init_irctl(ir); +} + +/* helper function + * reads key codes from plugin and puts them into buffer + * buffer free space is checked and locking performed + * returns 0 on success + */ +static inline int add_to_buf(struct irctl *ir) +{ + if (lirc_buffer_full(ir->buf)) { + dprintk(LOGHEAD "buffer overflow\n", + ir->p.name, ir->p.minor); + return -EOVERFLOW; + } + + if (ir->p.add_to_buf) { + int res = -ENODATA; + int got_data = 0; + + /* service the device as long as it is returning + * data and we have space + */ + while (!lirc_buffer_full(ir->buf)) { + res = ir->p.add_to_buf(ir->p.data, ir->buf); + if (res == SUCCESS) + got_data++; + else + break; + } + + if (res == -ENODEV) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + ir->shutdown = 1; +#else + kthread_stop(ir->task); +#endif + + return (got_data ? SUCCESS : res); + } + + return SUCCESS; +} + +/* main function of the polling thread + */ +static int lirc_thread(void *irctl) +{ + struct irctl *ir = irctl; + + /* This thread doesn't need any user-level access, + * so get rid of all our resources + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + daemonize("lirc_dev"); + + if (ir->t_notify != NULL) + complete(ir->t_notify); +#endif + + dprintk(LOGHEAD "poll thread started\n", ir->p.name, ir->p.minor); + + do { + if (ir->open) { + if (ir->jiffies_to_wait) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(ir->jiffies_to_wait); + } else { + interruptible_sleep_on( + ir->p.get_queue(ir->p.data)); + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + if (ir->shutdown) +#else + if (kthread_should_stop()) +#endif + break; + if (!add_to_buf(ir)) + wake_up_interruptible(&ir->buf->wait_poll); + } else { + /* if device not opened so we can sleep half a second */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/2); + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + } while (!ir->shutdown); + + if (ir->t_notify2 != NULL) + wait_for_completion(ir->t_notify2); + + ir->tpid = -1; + if (ir->t_notify != NULL) + complete(ir->t_notify); +#else + } while (!kthread_should_stop()); +#endif + + dprintk(LOGHEAD "poll thread ended\n", ir->p.name, ir->p.minor); + + return 0; +} + +int lirc_register_plugin(struct lirc_plugin *p) +{ + struct irctl *ir; + int minor; + int bytes_in_key; + int err; +#ifdef LIRC_HAVE_DEVFS_24 + char name[16]; +#endif + DECLARE_COMPLETION(tn); + + if (!p) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "plugin pointer must be not NULL!\n"); + err = -EBADRQC; + goto out; + } + + if (MAX_IRCTL_DEVICES <= p->minor) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "\"minor\" must be between 0 and %d (%d)!\n", + MAX_IRCTL_DEVICES-1, p->minor); + err = -EBADRQC; + goto out; + } + + if (1 > p->code_length || (BUFLEN * 8) < p->code_length) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "code length in bits for minor (%d) " + "must be less than %d!\n", + p->minor, BUFLEN * 8); + err = -EBADRQC; + goto out; + } + + printk(KERN_INFO "lirc_dev: lirc_register_plugin: sample_rate: %d\n", + p->sample_rate); + if (p->sample_rate) { + if (2 > p->sample_rate || HZ < p->sample_rate) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "sample_rate must be between 2 and %d!\n", HZ); + err = -EBADRQC; + goto out; + } + if (!p->add_to_buf) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "add_to_buf cannot be NULL when " + "sample_rate is set\n"); + err = -EBADRQC; + goto out; + } + } else if (!(p->fops && p->fops->read) + && !p->get_queue && !p->rbuf) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "fops->read, get_queue and rbuf " + "cannot all be NULL!\n"); + err = -EBADRQC; + goto out; + } else if (!p->get_queue && !p->rbuf) { + if (!(p->fops && p->fops->read && p->fops->poll) + || (!p->fops->ioctl && !p->ioctl)) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "neither read, poll nor ioctl can be NULL!\n"); + err = -EBADRQC; + goto out; + } + } + + if (p->owner == NULL) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "no module owner registered\n"); + err = -EBADRQC; + goto out; + } + + down(&plugin_lock); + + minor = p->minor; + + if (0 > minor) { + /* find first free slot for plugin */ + for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) + if (irctls[minor].p.minor == NOPLUG) + break; + if (MAX_IRCTL_DEVICES == minor) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "no free slots for plugins!\n"); + err = -ENOMEM; + goto out_lock; + } + } else if (irctls[minor].p.minor != NOPLUG) { + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "minor (%d) just registered!\n", minor); + err = -EBUSY; + goto out_lock; + } + + ir = &irctls[minor]; + + if (p->sample_rate) { + ir->jiffies_to_wait = HZ / p->sample_rate; + } else { + /* it means - wait for external event in task queue */ + ir->jiffies_to_wait = 0; + } + + /* some safety check 8-) */ + p->name[sizeof(p->name)-1] = '\0'; + + bytes_in_key = p->code_length/8 + (p->code_length%8 ? 1 : 0); + + if (p->rbuf) { + ir->buf = p->rbuf; + } else { + ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!ir->buf) { + err = -ENOMEM; + goto out_lock; + } + if (lirc_buffer_init(ir->buf, bytes_in_key, + BUFLEN/bytes_in_key) != 0) { + kfree(ir->buf); + err = -ENOMEM; + goto out_lock; + } + } + + if (p->features == 0) + p->features = (p->code_length > 8) ? + LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_CODE; + + ir->p = *p; + ir->p.minor = minor; + +#if defined(LIRC_HAVE_DEVFS_24) + sprintf(name, DEV_LIRC "/%d", ir->p.minor); + ir->devfs_handle = devfs_register(NULL, name, DEVFS_FL_DEFAULT, + IRCTL_DEV_MAJOR, ir->p.minor, + S_IFCHR | S_IRUSR | S_IWUSR, + &fops, NULL); +#elif defined(LIRC_HAVE_DEVFS_26) + devfs_mk_cdev(MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), + S_IFCHR|S_IRUSR|S_IWUSR, + DEV_LIRC "/%u", ir->p.minor); +#endif + (void) device_create(lirc_class, ir->p.dev, + MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), + NULL, "lirc%u", ir->p.minor); + + if (p->sample_rate || p->get_queue) { + /* try to fire up polling thread */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + ir->t_notify = &tn; + ir->tpid = kernel_thread(lirc_thread, (void *)ir, 0); + if (ir->tpid < 0) { +#else + ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev"); + if (IS_ERR(ir->task)) { +#endif + printk(KERN_ERR "lirc_dev: lirc_register_plugin: " + "cannot run poll thread for minor = %d\n", + p->minor); + err = -ECHILD; + goto out_sysfs; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + wait_for_completion(&tn); + ir->t_notify = NULL; +#endif + } + ir->attached = 1; + up(&plugin_lock); + +/* + * Recent kernels should handle this autmatically by increasing/decreasing + * use count when a dependant module is loaded/unloaded. + */ +#ifndef KERNEL_2_5 + MOD_INC_USE_COUNT; +#endif + dprintk("lirc_dev: plugin %s registered at minor number = %d\n", + ir->p.name, ir->p.minor); + p->minor = minor; + return minor; + +out_sysfs: + lirc_device_destroy(lirc_class, + MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); +#ifdef LIRC_HAVE_DEVFS_24 + devfs_unregister(ir->devfs_handle); +#endif +#ifdef LIRC_HAVE_DEVFS_26 + devfs_remove(DEV_LIRC "/%i", ir->p.minor); +#endif +out_lock: + up(&plugin_lock); +out: + return err; +} +EXPORT_SYMBOL(lirc_register_plugin); + +int lirc_unregister_plugin(int minor) +{ + struct irctl *ir; + DECLARE_COMPLETION(tn); + DECLARE_COMPLETION(tn2); + + if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { + printk(KERN_ERR "lirc_dev: lirc_unregister_plugin: " + "\"minor\" must be between 0 and %d!\n", + MAX_IRCTL_DEVICES-1); + return -EBADRQC; + } + + ir = &irctls[minor]; + + down(&plugin_lock); + + if (ir->p.minor != minor) { + printk(KERN_ERR "lirc_dev: lirc_unregister_plugin: " + "minor (%d) device not registered!", minor); + up(&plugin_lock); + return -ENOENT; + } + + /* end up polling thread */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + if (ir->tpid >= 0) { + ir->t_notify = &tn; + ir->t_notify2 = &tn2; + ir->shutdown = 1; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) + { + struct task_struct *p; + + p = find_task_by_pid(ir->tpid); + wake_up_process(p); + } +#else + /* 2.2.x does not export wake_up_process() */ + wake_up_interruptible(ir->p.get_queue(ir->p.data)); +#endif + complete(&tn2); + wait_for_completion(&tn); + ir->t_notify = NULL; + ir->t_notify2 = NULL; + } +#else /* kernel >= 2.6.23 */ + if (ir->task) { + wake_up_process(ir->task); + kthread_stop(ir->task); + } +#endif + + dprintk("lirc_dev: plugin %s unregistered from minor number = %d\n", + ir->p.name, ir->p.minor); + + ir->attached = 0; + if (ir->open) { + dprintk(LOGHEAD "releasing opened plugin\n", + ir->p.name, ir->p.minor); + wake_up_interruptible(&ir->buf->wait_poll); + down(&ir->buffer_sem); + ir->p.set_use_dec(ir->p.data); + module_put(ir->p.owner); + up(&ir->buffer_sem); + } else + cleanup(ir); + up(&plugin_lock); + +/* + * Recent kernels should handle this autmatically by increasing/decreasing + * use count when a dependant module is loaded/unloaded. + */ +#ifndef KERNEL_2_5 + MOD_DEC_USE_COUNT; +#endif + + return SUCCESS; +} +EXPORT_SYMBOL(lirc_unregister_plugin); + +/* + * + */ +static int irctl_open(struct inode *inode, struct file *file) +{ + struct irctl *ir; + int retval; + + if (MINOR(inode->i_rdev) >= MAX_IRCTL_DEVICES) { + dprintk("lirc_dev [%d]: open result = -ENODEV\n", + MINOR(inode->i_rdev)); + return -ENODEV; + } + + ir = &irctls[MINOR(inode->i_rdev)]; + + dprintk(LOGHEAD "open called\n", ir->p.name, ir->p.minor); + + /* if the plugin has an open function use it instead */ + if (ir->p.fops && ir->p.fops->open) + return ir->p.fops->open(inode, file); + + if (down_interruptible(&plugin_lock)) + return -ERESTARTSYS; + + if (ir->p.minor == NOPLUG) { + up(&plugin_lock); + dprintk(LOGHEAD "open result = -ENODEV\n", + ir->p.name, ir->p.minor); + return -ENODEV; + } + + if (ir->open) { + up(&plugin_lock); + dprintk(LOGHEAD "open result = -EBUSY\n", + ir->p.name, ir->p.minor); + return -EBUSY; + } + + /* there is no need for locking here because ir->open is 0 + * and lirc_thread isn't using buffer + * plugins which use irq's should allocate them on set_use_inc, + * so there should be no problem with those either. + */ + ir->buf->head = ir->buf->tail; + ir->buf->fill = 0; + + if (ir->p.owner != NULL && try_module_get(ir->p.owner)) { + ++ir->open; + retval = ir->p.set_use_inc(ir->p.data); + + if (retval != SUCCESS) { + module_put(ir->p.owner); + --ir->open; + } + } else { + if (ir->p.owner == NULL) + dprintk(LOGHEAD "no module owner!!!\n", + ir->p.name, ir->p.minor); + + retval = -ENODEV; + } + + dprintk(LOGHEAD "open result = %d\n", ir->p.name, ir->p.minor, retval); + up(&plugin_lock); + + return retval; +} + +/* + * + */ +static int irctl_close(struct inode *inode, struct file *file) +{ + struct irctl *ir = &irctls[MINOR(inode->i_rdev)]; + + dprintk(LOGHEAD "close called\n", ir->p.name, ir->p.minor); + + /* if the plugin has a close function use it instead */ + if (ir->p.fops && ir->p.fops->release) + return ir->p.fops->release(inode, file); + + if (down_interruptible(&plugin_lock)) + return -ERESTARTSYS; + + --ir->open; + if (ir->attached) { + ir->p.set_use_dec(ir->p.data); + module_put(ir->p.owner); + } else { + cleanup(ir); + } + + up(&plugin_lock); + + return SUCCESS; +} + +/* + * + */ +static unsigned int irctl_poll(struct file *file, poll_table *wait) +{ + struct irctl *ir = &irctls[MINOR(file->f_dentry->d_inode->i_rdev)]; + unsigned int ret; + + dprintk(LOGHEAD "poll called\n", ir->p.name, ir->p.minor); + + /* if the plugin has a poll function use it instead */ + if (ir->p.fops && ir->p.fops->poll) + return ir->p.fops->poll(file, wait); + + down(&ir->buffer_sem); + if (!ir->attached) { + up(&ir->buffer_sem); + return POLLERR; + } + + poll_wait(file, &ir->buf->wait_poll, wait); + + dprintk(LOGHEAD "poll result = %s\n", + ir->p.name, ir->p.minor, + lirc_buffer_empty(ir->buf) ? "0" : "POLLIN|POLLRDNORM"); + + ret = lirc_buffer_empty(ir->buf) ? 0 : (POLLIN|POLLRDNORM); + + up(&ir->buffer_sem); + return ret; +} + +/* + * + */ +static int irctl_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned long mode; + int result; + struct irctl *ir = &irctls[MINOR(inode->i_rdev)]; + + dprintk(LOGHEAD "ioctl called (0x%x)\n", + ir->p.name, ir->p.minor, cmd); + + /* if the plugin has a ioctl function use it instead */ + if (ir->p.fops && ir->p.fops->ioctl) + return ir->p.fops->ioctl(inode, file, cmd, arg); + + if (ir->p.minor == NOPLUG || !ir->attached) { + dprintk(LOGHEAD "ioctl result = -ENODEV\n", + ir->p.name, ir->p.minor); + return -ENODEV; + } + + /* Give the plugin a chance to handle the ioctl */ + if (ir->p.ioctl) { + result = ir->p.ioctl(inode, file, cmd, arg); + if (result != -ENOIOCTLCMD) + return result; + } + /* The plugin can't handle cmd */ + result = SUCCESS; + + switch (cmd) { + case LIRC_GET_FEATURES: + result = put_user(ir->p.features, (unsigned long *)arg); + break; + case LIRC_GET_REC_MODE: + if (!(ir->p.features&LIRC_CAN_REC_MASK)) + return -ENOSYS; + + result = put_user(LIRC_REC2MODE + (ir->p.features&LIRC_CAN_REC_MASK), + (unsigned long *)arg); + break; + case LIRC_SET_REC_MODE: + if (!(ir->p.features&LIRC_CAN_REC_MASK)) + return -ENOSYS; + + result = get_user(mode, (unsigned long *)arg); + if (!result && !(LIRC_MODE2REC(mode) & ir->p.features)) + result = -EINVAL; + /* + * FIXME: We should actually set the mode somehow but + * for now, lirc_serial doesn't support mode changing either + */ + break; + case LIRC_GET_LENGTH: + result = put_user((unsigned long)ir->p.code_length, + (unsigned long *)arg); + break; + default: + result = -ENOIOCTLCMD; + } + + dprintk(LOGHEAD "ioctl result = %d\n", + ir->p.name, ir->p.minor, result); + + return result; +} + +/* + * + */ +static ssize_t irctl_read(struct file *file, + char *buffer, + size_t length, + loff_t *ppos) +{ + struct irctl *ir = &irctls[MINOR(file->f_dentry->d_inode->i_rdev)]; + unsigned char buf[ir->buf->chunk_size]; + int ret = 0, written = 0; + DECLARE_WAITQUEUE(wait, current); + + dprintk(LOGHEAD "read called\n", ir->p.name, ir->p.minor); + + /* if the plugin has a specific read function use it instead */ + if (ir->p.fops && ir->p.fops->read) + return ir->p.fops->read(file, buffer, length, ppos); + + if (down_interruptible(&ir->buffer_sem)) + return -ERESTARTSYS; + if (!ir->attached) { + up(&ir->buffer_sem); + return -ENODEV; + } + + if (length % ir->buf->chunk_size) { + dprintk(LOGHEAD "read result = -EINVAL\n", + ir->p.name, ir->p.minor); + up(&ir->buffer_sem); + return -EINVAL; + } + + /* + * we add ourselves to the task queue before buffer check + * to avoid losing scan code (in case when queue is awaken somewhere + * beetwen while condition checking and scheduling) + */ + add_wait_queue(&ir->buf->wait_poll, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + /* + * while we did't provide 'length' bytes, device is opened in blocking + * mode and 'copy_to_user' is happy, wait for data. + */ + while (written < length && ret == 0) { + if (lirc_buffer_empty(ir->buf)) { + /* According to the read(2) man page, 'written' can be + * returned as less than 'length', instead of blocking + * again, returning -EWOULDBLOCK, or returning + * -ERESTARTSYS */ + if (written) + break; + if (file->f_flags & O_NONBLOCK) { + ret = -EWOULDBLOCK; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + if (!ir->attached) { + ret = -ENODEV; + break; + } + } else { + lirc_buffer_read_1(ir->buf, buf); + ret = copy_to_user((void *)buffer+written, buf, + ir->buf->chunk_size); + written += ir->buf->chunk_size; + } + } + + remove_wait_queue(&ir->buf->wait_poll, &wait); + set_current_state(TASK_RUNNING); + up(&ir->buffer_sem); + + dprintk(LOGHEAD "read result = %s (%d)\n", + ir->p.name, ir->p.minor, ret ? "-EFAULT" : "OK", ret); + + return ret ? ret : written; +} + + +void *lirc_get_pdata(struct file *file) +{ + void *data = NULL; + + if (file && file->f_dentry && file->f_dentry->d_inode && + file->f_dentry->d_inode->i_rdev) { + struct irctl *ir; + ir = &irctls[MINOR(file->f_dentry->d_inode->i_rdev)]; + data = ir->p.data; + } + + return data; +} +EXPORT_SYMBOL(lirc_get_pdata); + + +static ssize_t irctl_write(struct file *file, const char *buffer, + size_t length, loff_t *ppos) +{ + struct irctl *ir = &irctls[MINOR(file->f_dentry->d_inode->i_rdev)]; + + dprintk(LOGHEAD "write called\n", ir->p.name, ir->p.minor); + + /* if the plugin has a specific read function use it instead */ + if (ir->p.fops && ir->p.fops->write) + return ir->p.fops->write(file, buffer, length, ppos); + + if (!ir->attached) + return -ENODEV; + + return -EINVAL; +} + + +static struct file_operations fops = { + .read = irctl_read, + .write = irctl_write, + .poll = irctl_poll, + .ioctl = irctl_ioctl, + .open = irctl_open, + .release = irctl_close +}; + + +static int lirc_dev_init(void) +{ + int i; + + for (i = 0; i < MAX_IRCTL_DEVICES; ++i) + init_irctl(&irctls[i]); + + if (register_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME, &fops)) { + printk(KERN_ERR "lirc_dev: register_chrdev failed\n"); + goto out; + } + + lirc_class = class_create(THIS_MODULE, "lirc"); + if (IS_ERR(lirc_class)) { + printk(KERN_ERR "lirc_dev: class_create failed\n"); + goto out_unregister; + } + + printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, " + "major %d \n", IRCTL_DEV_MAJOR); + + return SUCCESS; + +out_unregister: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + if (unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME)) + printk(KERN_ERR "lirc_dev: unregister_chrdev failed!\n"); +#else + /* unregister_chrdev returns void now */ + unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME); +#endif +out: + return -1; +} + +/* ---------------------------------------------------------------------- */ + +/* For now dont try to use it as a static version ! */ + +#ifdef MODULE + +/* + * + */ +int init_module(void) +{ + return lirc_dev_init(); +} + +/* + * + */ +void cleanup_module(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + int ret; + + ret = unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME); + class_destroy(lirc_class); + + if (ret) + printk(KERN_ERR "lirc_dev: error in " + "module_unregister_chrdev: %d\n", ret); + else + dprintk("lirc_dev: module successfully unloaded\n"); +#else + /* unregister_chrdev returns void now */ + unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME); + class_destroy(lirc_class); + dprintk("lirc_dev: module unloaded\n"); +#endif +} + +MODULE_DESCRIPTION("LIRC base driver module"); +MODULE_AUTHOR("Artur Lipowski"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(IRCTL_DEV_MAJOR); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +#endif /* MODULE */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_dev/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_dev/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_DEV) += lirc_dev.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_pvr150/lirc_pvr150.c +++ linux-2.6.27/ubuntu/lirc/lirc_pvr150/lirc_pvr150.c @@ -0,0 +1,1481 @@ +/* $Id: $ */ + +/* + * i2c IR lirc plugin for Hauppauge PVR 150 card + * + * Copyright (c) 2000 Gerd Knorr + * modified for PixelView (BT878P+W/FM) by + * Michal Kochanowicz + * Christoph Bartelmus + * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by + * Ulrich Mueller + * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by + * Stefan Jahn + * modified for inclusion into kernel sources by + * Jerome Brock + * modified for Leadtek Winfast PVR2000 by + * Thomas Reitmayr (treitmayr@yahoo.com) + * modified for Hauppauge PVR-150 IR TX device by + * Mark Weaver + * + * parts are cut&pasted from the lirc_pvr150.c driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" +#include "lirc.h" + +/* We need to be able to reset the crappy IR chip by talking to the ivtv driver */ +struct ivtv; +void ivtv_reset_ir_gpio(struct ivtv *itv); + +struct IR +{ + struct lirc_plugin l; + + /* Device info */ + struct semaphore lock; + int open; + + /* RX device */ + struct i2c_client c_rx; + + /* RX device buffer & lock */ + struct lirc_buffer buf; + struct semaphore buf_sem; + + /* RX polling thread data */ + struct completion *t_notify; + struct completion *t_notify2; + int shutdown; + int tpid; + + /* RX read data */ + unsigned char b[3]; + + /* TX device */ + struct i2c_client c_tx; + int need_boot; + + /* # devices, for shutdown */ + int devs; +}; + +/* Minor -> data mapping */ +static struct IR *ir_devices[MAX_IRCTL_DEVICES]; + +/* Block size for haup PVR-150 IR transmitter */ +#define TX_BLOCK_SIZE 99 + +/* Hauppuage IR transmitter data */ +typedef struct TX_DATA_s +{ + /* Boot block */ + unsigned char *boot_data; + + /* Start of binary data block */ + unsigned char *datap; + + /* End of binary data block */ + unsigned char *endp; + + /* Number of installed codesets */ + unsigned int num_code_sets; + + /* Pointers to codesets */ + unsigned char **code_sets; + + /* Global fixed data template */ + int fixed[TX_BLOCK_SIZE]; +} TX_DATA; + +static TX_DATA *tx_data; +struct semaphore tx_data_lock; + +/* ----------------------------------------------------------------------- */ + +#define DEVICE_NAME "lirc_pvr150" + +/* ----------------------------------------------------------------------- */ +/* insmod parameters */ + +static int debug = 0; /* debug output */ +static int disable_rx = 0; /* disable RX device */ +static int disable_tx = 0; /* disable TX device */ +static int minor = -1; /* minor number */ + +#define dprintk(fmt, args...) \ + do{ \ + if(debug) printk(KERN_DEBUG DEVICE_NAME ": " fmt, \ + ## args); \ + }while(0) + +/* ----------------------------------------------------------------------- */ + +static int add_to_buf(struct IR *ir) +{ + __u16 code; + unsigned char codes[2]; + unsigned char keybuf[6]; + int got_data = 0; + int ret; + int failures = 0; + unsigned char sendbuf[1] = { 0 }; + + if (lirc_buffer_full(&ir->buf)) { + dprintk("buffer overflow\n"); + return -EOVERFLOW; + } + + /* service the device as long as it is returning + * data and we have space + */ + do + { + /* Lock i2c bus for the duration. RX/TX chips interfere so + this is worth it + */ + down(&ir->lock); + + /* Send random "poll command" (?) Windows driver does this + and it is a good point to detect chip failure. + */ + ret = i2c_master_send(&ir->c_rx, sendbuf, 1); + if (ret != 1) + { + printk(KERN_ERR + "lirc_pvr150: i2c_master_send failed with %d\n", + ret); + if (failures >= 3) { + up(&ir->lock); + printk(KERN_ERR "lirc_pvr150: unable to read " + "from the IR chip after 3 " + "resets, giving up\n"); + return ret; + } + + /* Looks like the chip crashed, reset it */ + printk(KERN_ERR "lirc_pvr150: polling the IR receiver " + "chip failed, trying reset\n"); + + ivtv_reset_ir_gpio(i2c_get_adapdata(ir->c_rx.adapter)); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((100 * HZ + 999) / 1000); + ir->need_boot = 1; + + ++failures; + up(&ir->lock); + continue; + } + + ret = i2c_master_recv(&ir->c_rx, keybuf, sizeof(keybuf)); + up(&ir->lock); + if (ret != sizeof(keybuf)) + { + printk(KERN_ERR + "lirc_pvr150: i2c_master_recv failed with %d" + " -- keeping last read buffer\n", ret); + } + else + { + ir->b[0] = keybuf[3]; + ir->b[1] = keybuf[4]; + ir->b[2] = keybuf[5]; + dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]); + } + + /* key pressed ? */ + if ((ir->b[0] & 0x80) == 0) + return got_data ? 0 : -ENODATA; + + /* look what we have */ + code = (((__u16)ir->b[0]&0x7f)<<6) | (ir->b[1]>>2); + + codes[0] = (code >> 8) & 0xff; + codes[1] = code & 0xff; + + /* return it */ + lirc_buffer_write_1( &ir->buf, codes ); + ++got_data; + } while (!lirc_buffer_full(&ir->buf)); + return 0; +} + +/* Main function of the polling thread -- from lirc_dev. + * We don't fit the LIRC model at all anymore. This is horrible, but + * basically we have a single RX/TX device with a nasty failure mode + * that needs to be accounted for across the pair. lirc lets us provide + * fops, but prevents us from using the internal polling, etc. if we do + * so. Hence the replication. Might be neater to extend the LIRC model + * to account for this but I'd think it's a very special case of seriously + * messed up hardware. + */ +static int lirc_thread(void *arg) +{ + struct IR *ir = arg; + + /* This thread doesn't need any user-level access, + * so get rid of all our resources + */ + daemonize("lirc_pvr150"); + + if (ir->t_notify != NULL) { + complete(ir->t_notify); + } + + dprintk("poll thread started\n"); + + do { + if (ir->open) { + set_current_state(TASK_INTERRUPTIBLE); + + /* This is ~113*2 + 24 + jitter (2*repeat gap + + code length). We use this interval as the chip + resets every time you poll it (bad!). This is + therefore just sufficient to catch all of the + button presses. It makes the remote much more + responsive. You can see the difference by + running irw and holding down a button. With + 100ms, the old polling interval, you'll notice + breaks in the repeat sequence corresponding to + lost keypresses. + */ + schedule_timeout((260 * HZ) / 1000); + if (ir->shutdown) { + break; + } + if (!add_to_buf(ir)) { + wake_up_interruptible(&ir->buf.wait_poll); + } + } else { + /* if device not opened so we can sleep half a second */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/2); + } + } while (!ir->shutdown); + + if (ir->t_notify2 != NULL) { + wait_for_completion(ir->t_notify2); + } + + ir->tpid = -1; + if (ir->t_notify != NULL) { + complete(ir->t_notify); + } + + dprintk("poll thread ended\n"); + return 0; +} + +static int set_use_inc(void* data) +{ + struct IR *ir = data; + + if (ir->l.owner == NULL || try_module_get(ir->l.owner) == 0) { + return -ENODEV; + } + + /* lock bttv in memory while /dev/lirc is in use */ + /* this is completely broken code. lirc_unregister_plugin() + must be possible even when the device is open */ + if (ir->c_rx.addr) i2c_use_client(&ir->c_rx); + if (ir->c_tx.addr) i2c_use_client(&ir->c_tx); + MOD_INC_USE_COUNT; + + return 0; +} + +static void set_use_dec(void* data) +{ + struct IR *ir = data; + + if (ir->c_rx.addr) i2c_release_client(&ir->c_rx); + if (ir->c_tx.addr) i2c_release_client(&ir->c_tx); + MOD_DEC_USE_COUNT; + if (ir->l.owner != NULL) + module_put(ir->l.owner); +} + +/* safe read of a uint32 (always network byte order) */ +static __inline int read_uint32(unsigned char **data, + unsigned char *endp, unsigned int *val) +{ + if (*data + 4 > endp) + return 0; + *val = ((*data)[0] << 24) | ((*data)[1] << 16) | + ((*data)[2] << 8) | (*data)[3]; + *data += 4; + return 1; +} + +/* safe read of a uint8 */ +static __inline int read_uint8(unsigned char **data, + unsigned char *endp, unsigned char *val) +{ + if (*data + 1 > endp) + return 0; + *val = *((*data)++); + return 1; +} + +/* safe skipping of N bytes */ +static __inline int skip(unsigned char **data, + unsigned char *endp, unsigned int distance) +{ + if (*data + distance > endp) + return 0; + *data += distance; + return 1; +} + +/* decompress key data into the given buffer */ +static int get_key_data(unsigned char *buf, + unsigned int codeset, unsigned int key) +{ + unsigned char *data, *endp, *diffs, *key_block; + unsigned char keys, ndiffs, id; + unsigned int base, lim, pos, i; + + /* Binary search for the codeset */ + for (base = 0, lim = tx_data->num_code_sets; lim; lim >>= 1) { + pos = base + (lim >> 1); + data = tx_data->code_sets[pos]; + + if (!read_uint32(&data, tx_data->endp, &i)) + goto corrupt; + + if (i == codeset) + break; + else if (codeset > i) { + base = pos + 1; + --lim; + } + } + /* Not found? */ + if (!lim) + return -EPROTO; + + /* Set end of data block */ + endp = pos < tx_data->num_code_sets - 1 ? + tx_data->code_sets[pos + 1] : tx_data->endp; + + /* Read the block header */ + if (!read_uint8(&data, endp, &keys) || + !read_uint8(&data, endp, &ndiffs) || + ndiffs > TX_BLOCK_SIZE || keys == 0) + goto corrupt; + + /* Save diffs & skip */ + diffs = data; + if (!skip(&data, endp, ndiffs)) + goto corrupt; + + /* Read the id of the first key */ + if (!read_uint8(&data, endp, &id)) + goto corrupt; + + /* Unpack the first key's data */ + for (i = 0; i < TX_BLOCK_SIZE; ++i) + { + if (tx_data->fixed[i] == -1) + { + if (!read_uint8(&data, endp, &buf[i])) + goto corrupt; + } + else + { + buf[i] = (unsigned char)tx_data->fixed[i]; + } + } + + /* Early out key found/not found */ + if (key == id) + return 0; + if (keys == 1) + return -EPROTO; + + /* Sanity check */ + key_block = data; + if (!skip(&data, endp, (keys - 1) * (ndiffs + 1))) + goto corrupt; + + /* Binary search for the key */ + for (base = 0, lim = keys - 1; lim; lim >>= 1) { + /* Seek to block */ + unsigned char *key_data; + pos = base + (lim >> 1); + key_data = key_block + (ndiffs + 1) * pos; + + if (*key_data == key) { + /* skip key id */ + ++key_data; + + /* found, so unpack the diffs */ + for (i = 0; i < ndiffs; ++i) { + unsigned char val; + if (!read_uint8(&key_data, endp, &val) || + diffs[i] >= TX_BLOCK_SIZE) + goto corrupt; + buf[diffs[i]] = val; + } + + return 0; + } else if (key > *key_data) { + base = pos + 1; + --lim; + } + } + /* Key not found */ + return -EPROTO; + +corrupt: + printk(KERN_ERR "lirc_pvr150: firmware is corrupt\n"); + return -EFAULT; +} + +/* send a block of data to the IR TX device of the PVR-150 */ +static int send_data_block(struct IR *ir, unsigned char *data_block) +{ + int i, j, ret; + unsigned char buf[5]; + + for (i = 0; i < TX_BLOCK_SIZE; ) + { + int tosend = TX_BLOCK_SIZE - i; + if (tosend > 4) + tosend = 4; + buf[0] = (unsigned char)(i + 1); + for (j = 0; j < tosend; ++j) + buf[1 + j] = data_block[i + j]; + dprintk("%02x %02x %02x %02x %02x", + buf[0],buf[1],buf[2],buf[3],buf[4]); + ret = i2c_master_send(&ir->c_tx, buf, tosend + 1); + if (ret != tosend + 1) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_send failed with %d\n", + ret); + return ret < 0 ? ret : -EFAULT; + } + i += tosend; + } + return 0; +} + +/* send boot data to the IR TX device of the PVR-150 */ +static int send_boot_data(struct IR *ir) +{ + int ret; + unsigned char buf[4]; + + /* send the boot block */ + ret = send_data_block(ir, tx_data->boot_data); + if (ret != 0) + return ret; + + /* kick it off? */ + buf[0] = 0x00; + buf[1] = 0x20; + ret = i2c_master_send(&ir->c_tx, buf, 2); + if (ret != 2) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + ret = i2c_master_send(&ir->c_tx, buf, 1); + if (ret != 1) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + + /* Here comes the firmware version... (hopefully) */ + ret = i2c_master_recv(&ir->c_tx, buf, 4); + if (ret != 4) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_recv failed with %d\n", ret); + return 0; + } + if (buf[0] != 0x80) { + printk(KERN_ERR + "lirc_pvr150: unexpected IR TX response: %02x\n", + buf[0]); + return 0; + } + printk(KERN_INFO + "lirc_pvr150: Hauppauge PVR-150 IR blaster: " + "firmware version %d.%d.%d\n", + buf[1], buf[2], buf[3]); + + return 0; +} + +/* unload "firmware", lock held */ +static void fw_unload_locked(void) +{ + if (tx_data) { + if (tx_data->code_sets) + vfree(tx_data->code_sets); + + if (tx_data->datap) + vfree(tx_data->datap); + + vfree(tx_data); + tx_data = NULL; + dprintk("successfully unloaded PVR-150 IR " + "blaster firmware\n"); + } +} + +/* unload "firmware" for the IR TX device of the PVR-150 */ +static void fw_unload(void) +{ + down(&tx_data_lock); + fw_unload_locked(); + up(&tx_data_lock); +} + +/* load "firmware" for the IR TX device of the PVR-150 */ +static int fw_load(struct IR *ir) +{ + int ret; + unsigned int i; + unsigned char *data, version, num_global_fixed; + const struct firmware *fw_entry = NULL; + + /* Already loaded? */ + down(&tx_data_lock); + if (tx_data) { + ret = 0; + goto out; + } + + /* Request codeset data file */ + ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &ir->c_tx.dev); + if (ret != 0) { + printk(KERN_ERR + "lirc_pvr150: firmware haup-ir-blaster.bin " + "not available (%d)\n", ret); + ret = ret < 0 ? ret : -EFAULT; + goto out; + } + printk(KERN_INFO + "lirc_pvr150: firmware of size %zd loaded\n", fw_entry->size); + + /* Parse the file */ + tx_data = vmalloc(sizeof(TX_DATA)); + if (tx_data == NULL) { + printk(KERN_ERR + "lirc_pvr150: out of memory\n"); + release_firmware(fw_entry); + ret = -ENOMEM; + goto out; + } + tx_data->code_sets = NULL; + + /* Copy the data so hotplug doesn't get confused and timeout */ + tx_data->datap = vmalloc(fw_entry->size); + if (tx_data->datap == NULL) { + printk(KERN_ERR + "lirc_pvr150: out of memory\n"); + release_firmware(fw_entry); + vfree(tx_data); + ret = -ENOMEM; + goto out; + } + memcpy(tx_data->datap, fw_entry->data, fw_entry->size); + tx_data->endp = tx_data->datap + fw_entry->size; + release_firmware(fw_entry); fw_entry = NULL; + + /* Check version */ + data = tx_data->datap; + if (!read_uint8(&data, tx_data->endp, &version)) + goto corrupt; + if (version != 1) { + printk(KERN_ERR + "lirc_pvr150: unsupported code set file version (%u, " + "expected 1) -- please upgrade to a newer driver", + version); + fw_unload_locked(); + ret = -EFAULT; + goto out; + } + + /* Save boot block for later */ + tx_data->boot_data = data; + if (!skip(&data, tx_data->endp, TX_BLOCK_SIZE)) + goto corrupt; + + if (!read_uint32(&data, tx_data->endp, + &tx_data->num_code_sets)) + goto corrupt; + + printk(KERN_INFO + "lirc_pvr150: %u codesets loaded\n", tx_data->num_code_sets); + + tx_data->code_sets = vmalloc( + tx_data->num_code_sets * sizeof(char *)); + if (tx_data->code_sets == NULL) { + fw_unload_locked(); + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < TX_BLOCK_SIZE; ++i) + tx_data->fixed[i] = -1; + + /* Read global fixed data template */ + if (!read_uint8(&data, tx_data->endp, &num_global_fixed) || + num_global_fixed > TX_BLOCK_SIZE) + goto corrupt; + for (i = 0; i < num_global_fixed; ++i) { + unsigned char pos, val; + if (!read_uint8(&data, tx_data->endp, &pos) || + !read_uint8(&data, tx_data->endp, &val) || + pos >= TX_BLOCK_SIZE) { + goto corrupt; + } + tx_data->fixed[pos] = (int)val; + } + + /* Filch out the position of each code set */ + for (i = 0; i < tx_data->num_code_sets; ++i) { + unsigned int id; + unsigned char keys; + unsigned char ndiffs; + + /* Save the codeset position */ + tx_data->code_sets[i] = data; + + /* Read header */ + if (!read_uint32(&data, tx_data->endp, &id) || + !read_uint8(&data, tx_data->endp, &keys) || + !read_uint8(&data, tx_data->endp, &ndiffs) || + ndiffs > TX_BLOCK_SIZE || keys == 0) + goto corrupt; + + /* skip diff positions */ + if (!skip(&data, tx_data->endp, ndiffs)) + goto corrupt; + + /* After the diffs we have the first key id + data - + global fixed */ + if (!skip(&data, tx_data->endp, + 1 + TX_BLOCK_SIZE - num_global_fixed)) + goto corrupt; + + /* Then we have keys-1 blocks of key id+diffs */ + if (!skip(&data, tx_data->endp, + (ndiffs + 1) * (keys - 1))) + goto corrupt; + } + ret = 0; + goto out; + +corrupt: + printk(KERN_ERR "lirc_pvr150: firmware is corrupt\n"); + fw_unload_locked(); + ret = -EFAULT; + +out: + up(&tx_data_lock); + return ret; +} + +/* initialise the IR TX device of the PVR-150 */ +static int tx_init(struct IR *ir) +{ + int ret; + + /* Load 'firmware' */ + ret = fw_load(ir); + if (ret != 0) + return ret; + + /* Send boot block */ + ret = send_boot_data(ir); + if (ret != 0) + return ret; + ir->need_boot = 0; + + /* Looks good */ + return 0; +} + +/* do nothing stub to make LIRC happy */ +static loff_t lseek(struct file *filep,loff_t offset,int orig) +{ + return(-ESPIPE); +} + +/* copied from lirc_dev */ +static ssize_t read(struct file *filep,char *outbuf,size_t n,loff_t *ppos) +{ + struct IR *ir = (struct IR *)filep->private_data; + unsigned char buf[ir->buf.chunk_size]; + int ret=0, written=0; + DECLARE_WAITQUEUE(wait, current); + + dprintk("read called\n"); + if (ir->c_rx.addr == 0) + return -ENODEV; + + if (down_interruptible(&ir->buf_sem)) + return -ERESTARTSYS; + + if (n % ir->buf.chunk_size) { + dprintk("read result = -EINVAL\n"); + up(&ir->buf_sem); + return -EINVAL; + } + + /* we add ourselves to the task queue before buffer check + * to avoid losing scan code (in case when queue is awaken somewhere + * beetwen while condition checking and scheduling) + */ + add_wait_queue(&ir->buf.wait_poll, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + /* while we did't provide 'length' bytes, device is opened in blocking + * mode and 'copy_to_user' is happy, wait for data. + */ + while (written < n && ret == 0) { + if (lirc_buffer_empty(&ir->buf)) { + /* According to the read(2) man page, 'written' can be + * returned as less than 'n', instead of blocking + * again, returning -EWOULDBLOCK, or returning + * -ERESTARTSYS */ + if (written) break; + if (filep->f_flags & O_NONBLOCK) { + ret = -EWOULDBLOCK; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } else { + lirc_buffer_read_1(&ir->buf, buf); + ret = copy_to_user((void *)outbuf+written, buf, + ir->buf.chunk_size); + written += ir->buf.chunk_size; + } + } + + remove_wait_queue(&ir->buf.wait_poll, &wait); + set_current_state(TASK_RUNNING); + up(&ir->buf_sem); + + dprintk("read result = %s (%d)\n", + ret ? "-EFAULT" : "OK", ret); + + return ret ? ret : written; +} + +/* send a keypress to the IR TX device of the PVR-150 */ +static int send_code(struct IR *ir, unsigned int code, unsigned int key) +{ + unsigned char data_block[TX_BLOCK_SIZE]; + unsigned char buf[2]; + int i, ret; + + /* Get data for the codeset/key */ + ret = get_key_data(data_block, code, key); + + if (ret == -EPROTO) { + printk(KERN_ERR + "lirc_pvr150: failed to get data for code %u, " + "key %u -- check lircd.conf entries\n", + code, key); + return ret; + } else if (ret != 0) + return ret; + + /* Send the data block */ + ret = send_data_block(ir, data_block); + if (ret != 0) + return ret; + + /* Send data block length? */ + buf[0] = 0x00; + buf[1] = 0x40; + ret = i2c_master_send(&ir->c_tx, buf, 2); + if (ret != 2) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + ret = i2c_master_send(&ir->c_tx, buf, 1); + if (ret != 1) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + + /* Send finished download? */ + ret = i2c_master_recv(&ir->c_tx, buf, 1); + if (ret != 1) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_recv failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + if (buf[0] != 0xA0) { + printk(KERN_ERR + "lirc_pvr150: unexpected IR TX response #1: %02x\n", + buf[0]); + return ret < 0 ? ret : -EFAULT; + } + + /* Send prepare command? */ + buf[0] = 0x00; + buf[1] = 0x80; + ret = i2c_master_send(&ir->c_tx, buf, 2); + if (ret != 2) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + + /* This bit NAKs until the device is ready, so we retry it + sleeping a bit each time. This seems to be what the windows + driver does, approximately. + Try for up to 1s. + */ + for (i = 0; i < 20; ++i) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((50 * HZ + 999) / 1000); + ret = i2c_master_send(&ir->c_tx, buf, 1); + if (ret == 1) + break; + dprintk("NAK expected: i2c_master_send " + "failed with %d (try %d)\n", ret, i+1); + } + if (ret != 1) { + printk(KERN_ERR + "lirc_pvr150: IR TX chip never got ready: last " + "i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + + /* Seems to be an 'ok' response */ + i = i2c_master_recv(&ir->c_tx, buf, 1); + if (i != 1) { + printk(KERN_ERR + "lirc_pvr150: i2c_master_recv failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + if (buf[0] != 0x80) { + printk(KERN_ERR + "lirc_pvr150: unexpected IR TX response #2: %02x\n", + buf[0]); + return -EFAULT; + } + + /* Oh good, it worked */ + dprintk("sent code %u, key %u\n", code, key); + return 0; +} + +/* Write a code to the device. We take in a 32-bit number (a lirc_t) and then + decode this to a codeset/key index. The key data is then decompressed and + sent to the device. We have a spin lock as per i2c documentation to prevent + multiple concurrent sends which would probably cause the device to explode. + */ +static ssize_t write(struct file *filep,const char *buf,size_t n, + loff_t *ppos) +{ + struct IR *ir = (struct IR *)filep->private_data; + size_t i; + int failures = 0; + + if (ir->c_tx.addr == 0) + return -ENODEV; + + /* Validate user parameters */ + if (n % sizeof(lirc_t)) + return(-EINVAL); + + /* Lock i2c bus for the duration */ + down(&ir->lock); + + /* Send each keypress */ + for (i = 0; i < n; ) + { + int ret = 0; + lirc_t command; + + if (copy_from_user(&command, buf + i, sizeof(command))) { + up(&ir->lock); + return -EFAULT; + } + + /* Send boot data first if required */ + if (ir->need_boot == 1) + { + ret = send_boot_data(ir); + if (ret == 0) + ir->need_boot = 0; + } + + /* Send the code */ + if (ret == 0) { + ret = send_code(ir, (unsigned)command >> 16, + (unsigned)command & 0xFFFF); + if (ret == -EPROTO) { + up(&ir->lock); + return ret; + } + } + + /* Hmm, a failure. If we've had a few then give up, otherwise + try a reset + */ + if (ret != 0) { + /* Looks like the chip crashed, reset it */ + printk(KERN_ERR "lirc_pvr150: sending to the IR " + "transmitter chip failed, trying " + "reset\n"); + + if (failures >= 3) { + printk(KERN_ERR "lirc_pvr150: unable to send " + "to the IR chip after 3 " + "resets, giving up\n"); + up(&ir->lock); + return ret; + } + ivtv_reset_ir_gpio(i2c_get_adapdata(ir->c_tx.adapter)); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((100 * HZ + 999) / 1000); + ir->need_boot = 1; + ++failures; + } + else + { + i += sizeof(lirc_t); + } + } + + /* Release i2c bus */ + up(&ir->lock); + + /* All looks good */ + return n; +} + +/* copied from lirc_dev */ +static unsigned int poll(struct file *filep, poll_table * wait) +{ + struct IR *ir = (struct IR *)filep->private_data; + unsigned int ret; + + dprintk("poll called\n"); + if (ir->c_rx.addr == 0) + return -ENODEV; + + down(&ir->buf_sem); + + poll_wait(filep, &ir->buf.wait_poll, wait); + + dprintk("poll result = %s\n", + lirc_buffer_empty(&ir->buf) ? "0" : "POLLIN|POLLRDNORM"); + + ret = lirc_buffer_empty(&ir->buf) ? 0 : (POLLIN|POLLRDNORM); + + up(&ir->buf_sem); + return ret; +} + +static int ioctl(struct inode *node,struct file *filep,unsigned int cmd, + unsigned long arg) +{ + struct IR *ir = (struct IR *)filep->private_data; + int result; + unsigned long mode, features = 0; + + if (ir->c_rx.addr != 0) + features |= LIRC_CAN_REC_LIRCCODE; + if (ir->c_tx.addr != 0) + features |= LIRC_CAN_SEND_PULSE; + + switch(cmd) + { + case LIRC_GET_LENGTH: + result = put_user((unsigned long)13, + (unsigned long *)arg); + break; + case LIRC_GET_FEATURES: + result=put_user(features,(unsigned long *) arg); + if(result) return(result); + break; + case LIRC_GET_REC_MODE: + if(!(features&LIRC_CAN_REC_MASK)) + return -ENOSYS; + + result = put_user(LIRC_REC2MODE + (features&LIRC_CAN_REC_MASK), + (unsigned long*)arg); + break; + case LIRC_SET_REC_MODE: + if(!(features&LIRC_CAN_REC_MASK)) + return -ENOSYS; + + result = get_user(mode, (unsigned long*)arg); + if(!result && !(LIRC_MODE2REC(mode) & features)) { + result = -EINVAL; + } + break; + case LIRC_GET_SEND_MODE: + if(!(features&LIRC_CAN_SEND_MASK)) + return -ENOSYS; + + result=put_user(LIRC_MODE_PULSE,(unsigned long *) arg); + if(result) return(result); + break; + case LIRC_SET_SEND_MODE: + if(!(features&LIRC_CAN_SEND_MASK)) + return -ENOSYS; + + result=get_user(mode,(unsigned long *) arg); + if(result) return(result); + if(mode!=LIRC_MODE_PULSE) return(-EINVAL); + break; + default: + return(-ENOIOCTLCMD); + } + return (0); +} + +/* Open the IR device of the PVR-150. Get hold of our IR structure and + stash it in private_data for the file */ +static int open(struct inode* node,struct file* filep) +{ + struct IR *ir; + int ret; + + /* find our IR struct */ + unsigned minor = MINOR(node->i_rdev); + if (minor >= MAX_IRCTL_DEVICES) { + dprintk("minor %d: open result = -ENODEV\n", + minor); + return -ENODEV; + } + ir = ir_devices[minor]; + + /* increment in use count */ + down(&ir->lock); + ++ir->open; + ret = set_use_inc(ir); + if (ret != 0) { + --ir->open; + up(&ir->lock); + return ret; + } + up(&ir->lock); + + /* stash our IR struct */ + filep->private_data = ir; + + return(0); +} + +/* Close the IR device of the PVR-150 */ +static int close(struct inode* node,struct file* filep) +{ + /* find our IR struct */ + struct IR *ir = (struct IR *)filep->private_data; + if (ir == NULL) { + printk(KERN_ERR + "lirc_pvr150: close: no private_data " + "attached to the file!\n"); + return -ENODEV; + } + + /* decrement in use count */ + down(&ir->lock); + --ir->open; + set_use_dec(ir); + up(&ir->lock); + + return(0); +} + +static struct lirc_plugin lirc_template = { + name: "lirc_pvr150", + set_use_inc: set_use_inc, + set_use_dec: set_use_dec, + owner: THIS_MODULE +}; + +/* ----------------------------------------------------------------------- */ + +static int ir_attach(struct i2c_adapter *adap, int have_rx, int have_tx); +static int ir_detach(struct i2c_client *client); +static int ir_probe(struct i2c_adapter *adap); +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); + +static struct i2c_driver driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) + name: "i2c ir driver", + flags: I2C_DF_NOTIFY, +#else + .driver = { + owner: THIS_MODULE, + name: "i2c ir driver", + }, +#endif + id: I2C_DRIVERID_EXP3, /* FIXME */ + attach_adapter: ir_probe, + detach_client: ir_detach, + command: ir_command, +}; + +static struct i2c_client client_template = +{ + name: "unset", + driver: &driver +}; + +static struct file_operations lirc_fops = +{ + llseek: lseek, + read: read, + write: write, + poll: poll, + ioctl: ioctl, + open: open, + release: close +}; + +static int i2c_attach(struct i2c_client *client, struct IR *ir) +{ + int ret; + + i2c_set_clientdata(client, ir); + + ret = i2c_attach_client(client); + if (ret != 0) { + client->addr = 0; + return ret; + } + if (i2c_use_client(client) == NULL) { + i2c_detach_client(client); + client->addr = 0; + return ret; + } + ++ir->devs; + return 0; +} + +static int ir_attach(struct i2c_adapter *adap, int have_rx, int have_tx) +{ + struct IR *ir; + int ret, i; + + printk("lirc_pvr150: chip found with %s\n", + have_rx && have_tx ? "RX and TX" : + have_rx ? "RX only" : "TX only"); + + if (NULL == (ir = kmalloc(sizeof(struct IR),GFP_KERNEL))) + return -ENOMEM; + if (lirc_buffer_init(&ir->buf, 2, BUFLEN/2) != 0) { + kfree(ir); + return -ENOMEM; + } + init_MUTEX(&ir->lock); + init_MUTEX(&ir->buf_sem); + ir->open = 0; + ir->devs = 0; + ir->tpid = 0; + ir->need_boot = 1; + ir->shutdown = 0; + ir->t_notify = ir->t_notify2 = NULL; + for (i = 0; i < sizeof(ir->b); ++i) + ir->b[0] = 0; + + memcpy(&ir->l,&lirc_template,sizeof(struct lirc_plugin)); + ir->l.minor = -1; + + /* initialise RX device */ + client_template.adapter = adap; + memcpy(&ir->c_rx,&client_template,sizeof(struct i2c_client)); + if (have_rx) { + DECLARE_COMPLETION(tn); + + /* I2C attach to device */ + ir->c_rx.addr = 0x71; + strlcpy(ir->c_rx.name, "Hauppauge PVR150 RX", + sizeof(ir->c_rx.name)); + if ( (ret = i2c_attach(&ir->c_rx, ir)) != 0 ) + goto err; + + /* try to fire up polling thread */ + ir->t_notify = &tn; + ir->tpid = kernel_thread(lirc_thread, ir, 0); + if (ir->tpid < 0) { + printk(KERN_ERR "lirc_pvr150: lirc_register_plugin: " + "cannot run poll thread\n"); + ret = -ECHILD; + goto err; + } + wait_for_completion(&tn); + ir->t_notify = NULL; + } + + /* initialise TX device */ + memcpy(&ir->c_tx,&client_template,sizeof(struct i2c_client)); + if (have_tx) { + /* I2C attach to device */ + ir->c_tx.addr = 0x70; + strlcpy(ir->c_tx.name, "Hauppauge PVR150 TX", + sizeof(ir->c_tx.name)); + if ( (ret = i2c_attach(&ir->c_tx, ir)) != 0 ) + goto err; + } + + /* set lirc_dev stuff */ + ir->l.code_length = 13; + ir->l.rbuf = &ir->buf; + ir->l.fops = &lirc_fops; + ir->l.data = ir; + ir->l.minor = minor; + ir->l.sample_rate = 0; + + /* register with lirc */ + ir->l.minor = lirc_register_plugin(&ir->l); + if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { + printk(KERN_ERR + "lirc_pvr150: ir_attach: " + "\"minor\" must be between 0 and %d (%d)!\n", + MAX_IRCTL_DEVICES-1, ir->l.minor); + ret = -EBADRQC; + goto err; + } + + /* store this for getting back in open() later on */ + ir_devices[ir->l.minor] = ir; + + /* if we have the tx device, load the 'firmware'. We do this + after registering with lirc as otherwise hotplug seems to take + 10s to create the lirc device. + */ + if (have_tx) { + /* Special TX init */ + ret = tx_init(ir); + if (ret != 0) + goto err; + } + return 0; + +err: + /* undo everything, hopefully... */ + if (ir->c_rx.addr) ir_detach(&ir->c_rx); + if (ir->c_tx.addr) ir_detach(&ir->c_tx); + return ret; +} + +static int ir_detach(struct i2c_client *client) +{ + struct IR *ir = i2c_get_clientdata(client); + down(&ir->lock); + + if (client == &ir->c_rx) { + DECLARE_COMPLETION(tn); + DECLARE_COMPLETION(tn2); + + /* end up polling thread */ + if (ir->tpid >= 0) { + ir->t_notify = &tn; + ir->t_notify2 = &tn2; + ir->shutdown = 1; + { + struct task_struct *p; + p = find_task_by_pid_ns(ir->tpid, &init_pid_ns); + wake_up_process(p); + } + complete(&tn2); + wait_for_completion(&tn); + ir->t_notify = NULL; + ir->t_notify2 = NULL; + } + + /* unregister device */ + i2c_release_client(&ir->c_rx); + i2c_detach_client(&ir->c_rx); + } else if (client == &ir->c_tx) { + i2c_release_client(&ir->c_tx); + i2c_detach_client(&ir->c_tx); + } else { + up(&ir->lock); + printk(KERN_ERR "lirc_pvr150: ir_detach: detached from " + "something we didn't attach to\n"); + return -ENODEV; + } + + --ir->devs; + if (ir->devs < 0) + { + up(&ir->lock); + printk(KERN_ERR "lirc_pvr150: ir_detach: invalid " + "device count\n"); + return -ENODEV; + } + else if (ir->devs == 0) + { + /* unregister lirc plugin */ + if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) + { + lirc_unregister_plugin(ir->l.minor); + ir_devices[ir->l.minor] = NULL; + } + + /* free memory */ + lirc_buffer_free(&ir->buf); + up(&ir->lock); + kfree(ir); + return 0; + } + up(&ir->lock); + return 0; +} + +static int ir_probe(struct i2c_adapter *adap) +{ + struct i2c_client c; + char buf; + +#ifdef I2C_HW_B_CX2341X + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) || + adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) +#else + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) +#endif + { + int have_rx = 0, have_tx = 0; + + /* The external IR receiver is at i2c address 0x71 on the PVR-150 + The IR transmitter is at 0x70. + */ + memset(&c,0,sizeof(c)); + c.adapter = adap; + c.addr = 0x70; + + if (!disable_rx) { + if (i2c_master_recv(&c,&buf,1) == 1) + have_rx = 1; + dprintk("probe 0x70 @ %s: %s\n", + adap->name, + have_rx ? "yes" : "no"); + } + + if (!disable_tx) { + c.addr = 0x71; + if (i2c_master_recv(&c,&buf,1) == 1) + have_tx = 1; + dprintk("probe 0x71 @ %s: %s\n", + adap->name, + have_tx ? "yes" : "no"); + } + + if (have_rx || have_tx) + return ir_attach(adap, have_rx, have_tx); + else + { + printk(KERN_ERR "lirc_pvr150: %s: no devices found\n", adap->name); + } + } + + return 0; +} + +static int ir_command(struct i2c_client *client,unsigned int cmd, void *arg) +{ + /* nothing */ + return 0; +} + +/* ----------------------------------------------------------------------- */ +#ifdef MODULE + +int init_module(void) +{ + init_MUTEX(&tx_data_lock); + request_module("ivtv"); + request_module("firmware_class"); + i2c_add_driver(&driver); + return 0; +} + +void cleanup_module(void) +{ + i2c_del_driver(&driver); + /* if loaded */ + fw_unload(); +} + +MODULE_DESCRIPTION("Infrared receiver driver for Hauppauge PVR-150 card (i2c stack)"); +MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver"); +MODULE_LICENSE("GPL"); + +module_param(minor, int, 0444); +MODULE_PARM_DESC(minor, "Preferred minor device number"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +module_param(disable_rx, bool, 0644); +MODULE_PARM_DESC(disable_rx, "Disable the IR receiver device"); + +module_param(disable_tx, bool, 0644); +MODULE_PARM_DESC(disable_tx, "Disable the IR transmitter device"); + +EXPORT_NO_SYMBOLS; + +#endif /* MODULE */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_pvr150/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_pvr150/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_PVR150) += lirc_pvr150.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_cmdir/lirc_cmdir.h +++ linux-2.6.27/ubuntu/lirc/lirc_cmdir/lirc_cmdir.h @@ -0,0 +1,27 @@ +/* $Id: lirc_cmdir.h,v 1.3 2007/09/27 19:47:20 lirc Exp $ */ + +/* + * lirc_cmdir.h + */ + +#ifndef LIRC_CMDIR_H +#define LIRC_CMDIR_H + +#define ON 1 +#define OFF 0 + +/* transmitter channel control */ +#define MAX_CHANNELS 32 + +/* CommandIR control codes */ +#define MCU_CTRL_SIZE 3 +#define FREQ_HEADER 2 +#define TX_HEADER 7 +#define TX_HEADER_NEW 8 + +extern int cmdir_write(unsigned char *buffer, int count, + void *callback_fct, int u); +extern ssize_t cmdir_read(unsigned char *buffer, size_t count); +extern int set_tx_channels(unsigned int next_tx); + +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_cmdir/commandir.h +++ linux-2.6.27/ubuntu/lirc/lirc_cmdir/commandir.h @@ -0,0 +1,41 @@ +/* + * commandir.h + */ + +#define ASCII0 48 + +/* transmitter channel control */ +#define MAX_DEVICES 8 +#define MAX_CHANNELS 32 +#define TX1_ENABLE 0x80 +#define TX2_ENABLE 0x40 +#define TX3_ENABLE 0x20 +#define TX4_ENABLE 0x10 + +/* command types */ +#define cNothing 0 +#define cRESET 1 +#define cFLASH 2 +#define cLCD 3 +#define cRX 4 + +/* CommandIR control codes */ +#define MCU_CTRL_SIZE 3 +#define FREQ_HEADER 2 +#define RESET_HEADER 3 +#define FLASH_HEADER 4 +#define LCD_HEADER 5 +#define TX_HEADER 7 +#define TX_HEADER_NEW 8 + +/* Queue buffering constants */ +#define SEND_IDLE 0 +#define SEND_ACTIVE 1 + +#define QUEUELENGTH 256 + +extern int cmdir_write(unsigned char *buffer, int count, + void *callback_fct, int u); +extern ssize_t cmdir_read(unsigned char *buffer, size_t count); +extern int set_tx_channels(unsigned int next_tx); + --- linux-2.6.27.orig/ubuntu/lirc/lirc_cmdir/commandir.c +++ linux-2.6.27/ubuntu/lirc/lirc_cmdir/commandir.c @@ -0,0 +1,1521 @@ + +/* + * + * Hardware Driver for COMMANDIR USB Transceiver + * 2005-2007 InnovationOne - Matt Bodkin, Evelyn Yeung + * + * Version 1.4.2 + * For 2.4.* or 2.6.* kernel versions + * Based on the USB Skeleton driver, versions 0.7 and 2.0 + * + */ + +#include +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "commandir.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +#include +#include +#include +#include +#include +#include +#include +#else +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#endif + +#define DRIVER_VERSION "v1.1.2" +#define DRIVER_AUTHOR "Evelyn Yeung, InnovationOne" +#define DRIVER_DESC "CommandIR USB Transceiver Driver" + +#define USB_CMDIR_VENDOR_ID 0x10c4 +#define USB_CMDIR_PRODUCT_ID 0x0003 +#define USB_CMDIR_MINOR_BASE 192 + +/* table of devices that work with this driver */ +static struct usb_device_id cmdir_table [] = +{ + { USB_DEVICE(USB_CMDIR_VENDOR_ID, USB_CMDIR_PRODUCT_ID) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, cmdir_table); + +static int cmdir_open(struct inode *inode, struct file *file); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +static void *cmdir_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); +static int cmdir_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static void cmdir_disconnect(struct usb_device *dev, void *ptr); +#else +static int cmdir_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void cmdir_disconnect(struct usb_interface *interface); +#endif +static int cmdir_release(struct inode *inode, struct file *file); +static int cmdir_check(int device_num); +static void init_cmdir_var(int device_num); +static void reset_cmdir(int device_num); +static void update_cmdir_string(int device_num); +static void print_cmdir(int device_num); +static ssize_t cmdir_file_read(struct file *file, char *buffer, + size_t count, loff_t *ppos); +ssize_t cmdir_read(unsigned char *buffer, size_t count); +static ssize_t cmdir_file_write(struct file *file, const char *buffer, + size_t count, loff_t *ppos); +int cmdir_write(unsigned char *buffer, int count, void *callback_fct, int u); +int write_core(unsigned char *buffer, int count, + void *callback_fct, int device_num); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +static void cmdir_write_bulk_callback(struct urb *urb); +#else +static void cmdir_write_bulk_callback(struct urb *urb, struct pt_regs *regs); +#endif +int set_tx_channels(unsigned int next_tx); + +int add_cmdir_queue(unsigned char *buffer, int count, + void *callback_vct, int usecdelay); +int cmdir_write_queue(unsigned char *buffer, int count, void *callback_vct); +int send_queue(void); +int wait_to_tx(int usecs); + +/* circular packet queue */ +unsigned char ourbuffers[QUEUELENGTH][64]; +int waitusecs[QUEUELENGTH]; +int ourbufferlengths[QUEUELENGTH]; +int nexttosend; +int nexttofill; +int send_status = SEND_IDLE; +int last_tx_sec; +int last_tx_usec; + +static int curTXFill; +struct timeval tp; + +int debug_commandir; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + +/* Structure to hold all of our device specific stuff */ +struct usb_skel { + struct usb_device *udev; /* save off the usb device pointer */ + struct usb_interface *interface; /* the interface for this device */ + devfs_handle_t devfs; /* devfs device node */ + unsigned char minor; /* the starting minor number */ + unsigned char num_ports; /* the number of ports this device has */ + char num_interrupt_in; /* number of interrupt in endpoints */ + char num_bulk_in; /* number of bulk in endpoints */ + char num_bulk_out; /* number of bulk out endpoints */ + + unsigned char *bulk_in_buffer; /* the buffer to receive data */ + int bulk_in_size; /* the size of the receive buffer */ + __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ + + unsigned char *bulk_out_buffer; /* the buffer to send data */ + int bulk_out_size; /* the size of the send buffer */ + struct urb *write_urb; /* the urb used to send data */ + __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ + + struct tq_struct tqueue; /* task queue for line discipline waking up */ + int open_count; /* number of times this port has been opened */ + struct semaphore sem; /* locks this structure */ +}; + +extern devfs_handle_t usb_devfs_handle; /* the global usb devfs handle */ + +/* array of pointers to our devices that are currently connected */ +static struct usb_skel *minor_table[MAX_DEVICES]; +/* lock to protect the minor_table structure */ +static DECLARE_MUTEX(minor_table_mutex); + +static struct file_operations cmdir_fops = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) + .owner = THIS_MODULE, +#endif /* kernel < 2.6.16 */ +#endif /* kernel >= 2.6.0 */ + .read = cmdir_file_read, + .write = cmdir_file_write, + .ioctl = cmdir_ioctl, + .open = cmdir_open, + .release = cmdir_release, +}; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver cmdir_driver = { + .name = "commandir", + .probe = cmdir_probe, + .disconnect = cmdir_disconnect, + .fops = &cmdir_fops, + .minor = USB_CMDIR_MINOR_BASE, + .id_table = cmdir_table, +}; + +#else /* kernel >= 2.6 */ + +/* Structure to hold all of our device specific stuff */ +struct usb_skel { + struct usb_device *udev; /* the usb device for this device */ + struct usb_interface *interface; /* the interface for this device */ + unsigned char *bulk_in_buffer; /* the buffer to receive data */ + size_t bulk_in_size; /* the size of the receive buffer */ + __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ + __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ + struct kref kref; +}; +#define to_skel_dev(d) container_of(d, struct usb_skel, kref) + +static struct file_operations cmdir_fops = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) + .owner = THIS_MODULE, +#endif /* kernel < 2.6.16 */ +#endif /* kernel >= 2.6.0 */ + .read = cmdir_file_read, + .write = cmdir_file_write, + .open = cmdir_open, + .release = cmdir_release, +}; + +/* usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with devfs and the driver core */ +static struct usb_class_driver cmdir_class = { + .name = "usb/commandir%d", + .fops = &cmdir_fops, + /* .mode = S_IFCHR | S_IRUSR | S_IWUSR | + * S_IRGRP | S_IWGRP | S_IROTH, */ + .minor_base = USB_CMDIR_MINOR_BASE, +}; + +static struct usb_driver cmdir_driver = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) + .owner = THIS_MODULE, +#endif /* kernel < 2.6.16 */ +#endif /* kernel >= 2.6.0 */ + .name = "commandir", + .probe = cmdir_probe, + .disconnect = cmdir_disconnect, + .id_table = cmdir_table, +}; + +#endif /* kernel < 2.6.0 */ + +static int lcd_device; +static int rx_device; +static int def_device; + +#define DEFAULT_TRANSMITTERS 0x0F +static unsigned int transmitters = DEFAULT_TRANSMITTERS; +static unsigned int next_transmitters = DEFAULT_TRANSMITTERS; + +#define CMDIR_VAR_LEN 68 +static char cmdir_var[] = +"COMMANDIRx:\n TX Enabled: 1, 2, 3, 4\n RX: commandirx\n LCD: commandirx"; + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +static inline void cmdir_delete(struct usb_skel *dev) +{ + minor_table[dev->minor] = NULL; + if (dev->bulk_in_buffer != NULL) + kfree(dev->bulk_in_buffer); + if (dev->bulk_out_buffer != NULL) + kfree(dev->bulk_out_buffer); + if (dev->write_urb != NULL) + usb_free_urb(dev->write_urb); + kfree(dev); +} +#else +static void cmdir_delete(struct kref *kref) +{ + struct usb_skel *dev = to_skel_dev(kref); + + usb_put_dev(dev->udev); + kfree(dev->bulk_in_buffer); + kfree(dev); +} +#endif + +static int __init usb_cmdir_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&cmdir_driver); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + if (result < 0) { + err("usb_register failed for the "__FILE__ + " driver. Error number %d", result); + return -1; + } + + info(DRIVER_DESC " " DRIVER_VERSION); + + return 0; +#else + if (result) + err("usb_register failed. Error number %d", result); + + return result; +#endif +} + +static int cmdir_open(struct inode *inode, struct file *file) +{ + struct usb_skel *dev; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) + struct usb_interface *interface; +#endif + int subminor; + int retval = 0; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + subminor = MINOR(inode->i_rdev) - USB_CMDIR_MINOR_BASE; + if ((subminor < 0) || (subminor >= MAX_DEVICES)) + return -ENODEV; + MOD_INC_USE_COUNT; + + /* lock our minor table and get our local data for this minor */ + down(&minor_table_mutex); + dev = minor_table[subminor]; + if (dev == NULL) { + up(&minor_table_mutex); + MOD_DEC_USE_COUNT; + return -ENODEV; + } + + down(&dev->sem); /* lock this device */ + up(&minor_table_mutex); /* unlock the minor table */ + ++dev->open_count; /* increment our usage count for the driver */ + file->private_data = dev; /* save object in file's private structure */ + up(&dev->sem); /* unlock this device */ + + return retval; +#else + subminor = iminor(inode); + interface = usb_find_interface(&cmdir_driver, subminor); + if (!interface) { + err("%s - error, can't find device for minor %d", + __FUNCTION__, subminor); + retval = -ENODEV; + goto exit; + } + + dev = usb_get_intfdata(interface); + if (!dev) { + retval = -ENODEV; + goto exit; + } + + kref_get(&dev->kref); /* increment our usage count for the device */ + file->private_data = dev; /* save object in file's private structure */ + +exit: + return retval; +#endif +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +static void *cmdir_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct usb_skel *dev = NULL; + struct usb_interface *interface; + struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int minor; + int buffer_size; + int i; + char name[10]; + + /* See if the device offered us matches what we can accept */ + if ((udev->descriptor.idVendor != USB_CMDIR_VENDOR_ID) || + (udev->descriptor.idProduct != USB_CMDIR_PRODUCT_ID)) + return NULL; + + /* select a "subminor" number (part of a minor number) */ + down(&minor_table_mutex); + for (minor = 0; minor < MAX_DEVICES; ++minor) { + if (minor_table[minor] == NULL) + break; + } + if (minor >= MAX_DEVICES) { + info("Too many devices plugged in, cannot handle this device."); + goto exit; + } + + /* allocate memory for our device state and intialize it */ + dev = kmalloc(sizeof(struct usb_skel), GFP_KERNEL); + if (dev == NULL) { + err("Out of memory"); + goto exit; + } + memset(dev, 0x00, sizeof(*dev)); + minor_table[minor] = dev; + + interface = &udev->actconfig->interface[ifnum]; + + init_MUTEX(&dev->sem); + dev->udev = udev; + dev->interface = interface; + dev->minor = minor; + + /* set up and check the endpoint information */ + iface_desc = &interface->altsetting[0]; + for (i = 0; i < iface_desc->bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i]; + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + buffer_size = endpoint->wMaxPacketSize; + dev->bulk_in_size = buffer_size; + dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; + dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!dev->bulk_in_buffer) { + err("Couldn't allocate bulk_in_buffer"); + goto error; + } + } + + if (((endpoint->bEndpointAddress & 0x80) == 0x00) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk out endpoint */ + dev->write_urb = usb_alloc_urb(0); + if (!dev->write_urb) { + err("No free urbs available"); + goto error; + } + buffer_size = endpoint->wMaxPacketSize; + dev->bulk_out_size = buffer_size; + dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; + dev->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!dev->bulk_out_buffer) { + err("Couldn't allocate bulk_out_buffer"); + goto error; + } + FILL_BULK_URB(dev->write_urb, udev, + usb_sndbulkpipe(udev, + endpoint->bEndpointAddress), + dev->bulk_out_buffer, buffer_size, + cmdir_write_bulk_callback, dev); + } + } + + /* initialize the devfs node for this device and register it */ + sprintf(name, "commandir%d", dev->minor); + + dev->devfs = devfs_register(usb_devfs_handle, name, + DEVFS_FL_DEFAULT, USB_MAJOR, + USB_CMDIR_MINOR_BASE + dev->minor, + S_IFCHR | S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | S_IROTH, + &cmdir_fops, NULL); + + /* let the user know what node this device is now attached to */ + info("CommandIR USB device now attached to commandir%d", dev->minor); + + /* should reset just the one that was plugged in */ + reset_cmdir(minor); + + goto exit; + +error: + cmdir_delete(dev); + dev = NULL; + +exit: + up(&minor_table_mutex); + return dev; +} +#else +static int cmdir_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_skel *dev = NULL; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + size_t buffer_size; + + int i; + int retval = -ENOMEM; + int minor; + + /* allocate memory for our device state and initialize it */ + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + err("Out of memory"); + goto error; + } + memset(dev, 0x00, sizeof(*dev)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 9) + kref_init(&dev->kref, cmdir_delete); +#else + kref_init(&dev->kref); +#endif + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + /* set up the endpoint information */ + /* use only the first bulk-in and bulk-out endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!dev->bulk_in_endpointAddr && + (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK)) { + /* we found a bulk in endpoint */ + buffer_size = endpoint->wMaxPacketSize; + dev->bulk_in_size = buffer_size; + dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; + dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!dev->bulk_in_buffer) { + err("Could not allocate bulk_in_buffer"); + goto error; + } + } + + if (!dev->bulk_out_endpointAddr && + !(endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK)) { + /* we found a bulk out endpoint */ + dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; + } + } + if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { + err("Could not find both bulk-in and bulk-out endpoints"); + goto error; + } + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* we can register the device now, as it is ready */ + retval = usb_register_dev(interface, &cmdir_class); + if (retval) { + /* something prevented us from registering this driver */ + err("Not able to get a minor for this device."); + usb_set_intfdata(interface, NULL); + goto error; + } + + /* check whether minor already includes base */ + minor = interface->minor; + if (minor >= USB_CMDIR_MINOR_BASE) + minor = minor-USB_CMDIR_MINOR_BASE; + + /* let the user know what node this device is now attached to */ + info("CommandIR USB device now attached to commandir%d", minor); + + reset_cmdir(minor); + + return 0; + +error: + if (dev) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 9) + kref_put(&dev->kref); +#else + kref_put(&dev->kref, cmdir_delete); +#endif + return retval; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +static int cmdir_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_skel *dev; + + dev = (struct usb_skel *)file->private_data; + + /* lock this object */ + down(&dev->sem); + + /* verify that the device wasn't unplugged */ + if (dev->udev == NULL) { + up(&dev->sem); + return -ENODEV; + } + + /* unlock the device */ + up(&dev->sem); + + /* return that we did not understand this ioctl call */ + return -ENOTTY; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +static void cmdir_disconnect(struct usb_device *udev, void *ptr) +{ + struct usb_skel *dev; + int minor; + + dev = (struct usb_skel *)ptr; + + down(&minor_table_mutex); + down(&dev->sem); + + minor = dev->minor; + + /* remove our devfs node */ + devfs_unregister(dev->devfs); + + /* if the device is not opened, then we clean up right now */ + if (!dev->open_count) { + up(&dev->sem); + cmdir_delete(dev); + } else { + dev->udev = NULL; + up(&dev->sem); + } + + info("CommandIR #%d now disconnected", minor); + up(&minor_table_mutex); + + /* check if default RX device still exists */ + if (minor == rx_device) { + /* decrement until find next valid device */ + while (rx_device > 0) { + rx_device--; + if (cmdir_check(rx_device) == 0) break; + } + if (minor > 0) + info("Active Receiver is on CommandIR #%d", rx_device); + } + +} +#else +static void cmdir_disconnect(struct usb_interface *interface) +{ + struct usb_skel *dev; + int minor = interface->minor; + + /* prevent cmdir_open() from racing cmdir_disconnect() */ + lock_kernel(); + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + /* give back our minor */ + usb_deregister_dev(interface, &cmdir_class); + + unlock_kernel(); + + /* decrement our usage count */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 9) + kref_put(&dev->kref); +#else + kref_put(&dev->kref, cmdir_delete); +#endif + + /* check whether minor already includes base */ + if (minor >= USB_CMDIR_MINOR_BASE) + minor = minor-USB_CMDIR_MINOR_BASE; + + info("CommandIR #%d now disconnected", minor); + + /* check if default RX device still exists */ + if (minor == rx_device) { + /* decrement until find next valid device */ + while (rx_device > 0) { + rx_device--; + if (cmdir_check(rx_device) == 0) + break; + } + if (minor > 0) + info("Active Receiver is on CommandIR #%d", rx_device); + } +} +#endif + +static int cmdir_release(struct inode *inode, struct file *file) +{ + struct usb_skel *dev; + int retval = 0; + + dev = (struct usb_skel *)file->private_data; + if (dev == NULL) + /*dbg(" - object is NULL");*/ + return -ENODEV; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + + /* lock our minor table */ + down(&minor_table_mutex); + + /* lock our device */ + down(&dev->sem); + + if (dev->open_count <= 0) { + /*dbg(" - device not opened");*/ + retval = -ENODEV; + goto exit_not_opened; + } + + if (dev->udev == NULL) { + /* the device was unplugged before the file was released */ + /*dbg(" - device unplugged before file released");*/ + up(&dev->sem); + cmdir_delete(dev); + up(&minor_table_mutex); + MOD_DEC_USE_COUNT; + return 0; + } + + /* decrement our usage count for the device */ + --dev->open_count; + if (dev->open_count <= 0) { + /* shutdown any bulk writes that might be going on */ + usb_unlink_urb(dev->write_urb); + dev->open_count = 0; + } + + /* decrement our usage count for the module */ + MOD_DEC_USE_COUNT; + +exit_not_opened: + up(&dev->sem); + up(&minor_table_mutex); + + return retval; + +#else + /* decrement the count on our device */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 9) + kref_put(&dev->kref); +#else + kref_put(&dev->kref, cmdir_delete); +#endif + return retval; +#endif +} + +static void __exit usb_cmdir_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&cmdir_driver); + +} + +static int cmdir_check(int device_num) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + if (minor_table[device_num] == NULL) + return -ENODEV; + return 0; +#else + struct usb_interface *interface; + + interface = usb_find_interface(&cmdir_driver, + USB_CMDIR_MINOR_BASE+device_num); + if (!interface) { + /* also check without adding base, for devfs */ + interface = usb_find_interface(&cmdir_driver, rx_device); + if (!interface) + return -ENODEV; + } + return 0; +#endif +} + +static void init_cmdir_var(int device_num) +{ + int i; + unsigned int multiplier = 1; + + for (i = 0; i < device_num; i++) + multiplier = multiplier*0x10; + transmitters |= multiplier * 0x0F; + next_transmitters = transmitters; + info("commandir%d reset", device_num); + return; +} + +static void reset_cmdir(int device_num) +{ + unsigned char ctrl_buffer[MCU_CTRL_SIZE]; + int retval; + int i; + + ctrl_buffer[0] = RESET_HEADER; + for (i = 1; i < MCU_CTRL_SIZE; i++) + ctrl_buffer[i] = 'j'; + retval = write_core(ctrl_buffer, MCU_CTRL_SIZE, NULL, device_num); + + init_cmdir_var(device_num); + print_cmdir(device_num); + + return; +} + +static void update_cmdir_string(int device_num) +{ + int next_comma = 0; + int next_pos = 25; + unsigned int multiplier; + int i; + + /* cmdir_var[] = "COMMANDIRx:\n" + * " TX Enabled: 1, 2, 3, 4\n" + * " RX: commandirx\n" + * " LCD: commandirx\n" */ + + cmdir_var[9] = ASCII0+device_num; + cmdir_var[50] = ASCII0+rx_device; + cmdir_var[67] = ASCII0+lcd_device; + + for (i = 25; i < 35; i++) + cmdir_var[i] = ' '; + + multiplier = 1; + for (i = 0; i < device_num; i++) + multiplier = multiplier*0x10; + + if (transmitters & (multiplier*0x01)) { + cmdir_var[next_pos] = '1'; + next_pos += 3; + next_comma++; + } + if (transmitters & (multiplier*0x02)) { + cmdir_var[next_pos] = '2'; + if (next_comma > 0) + cmdir_var[next_pos-2] = ','; + next_pos += 3; + next_comma++; + } + if (transmitters & (multiplier*0x04)) { + cmdir_var[next_pos] = '3'; + if (next_comma > 0) + cmdir_var[next_pos-2] = ','; + next_pos += 3; + next_comma++; + } + if (transmitters & (multiplier*0x08)) { + cmdir_var[next_pos] = '4'; + if (next_comma > 0) + cmdir_var[next_pos-2] = ','; + next_pos += 3; + next_comma++; + } + return; +} + +static void print_cmdir(int device_num) +{ + update_cmdir_string(device_num); + info("%s", cmdir_var); + return; +} + +static ssize_t cmdir_file_read(struct file *file, char *buffer, + size_t count, loff_t *ppos) +{ + int retval = 0; + int minor = 0; + struct usb_skel *dev; + + dev = (struct usb_skel *)file->private_data; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + minor = dev->minor; +#else + minor = dev->interface->minor; + if (minor >= USB_CMDIR_MINOR_BASE) + minor = minor - USB_CMDIR_MINOR_BASE; +#endif + + if (((int)*ppos) == 0) { + update_cmdir_string(minor); + if (copy_to_user(buffer, cmdir_var, CMDIR_VAR_LEN)) + retval = -EFAULT; + else + retval = CMDIR_VAR_LEN; + return retval; + } else + return 0; +} + +/* Read data from CommandIR */ +ssize_t cmdir_read(unsigned char *buffer, size_t count) +{ + struct usb_skel *dev; + int retval = 0; + int len; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + if (minor_table[rx_device] == NULL) + return -ENODEV; + dev = minor_table[rx_device]; + + /* lock this object */ + down(&dev->sem); + retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), + dev->bulk_in_buffer, dev->bulk_in_size, &len, HZ*100); +#else + struct usb_interface *interface; + interface = usb_find_interface(&cmdir_driver, + USB_CMDIR_MINOR_BASE+rx_device); + if (!interface) { + /* also check without adding base, for devfs */ + interface = usb_find_interface(&cmdir_driver, rx_device); + if (!interface) + return -ENODEV; + } + dev = usb_get_intfdata(interface); + if (!dev) + return -ENODEV; + retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), + dev->bulk_in_buffer, min(dev->bulk_in_size, count), + &len, HZ*10); +#endif + if (!retval) { + if (!memcpy(buffer, dev->bulk_in_buffer, len)) + retval = -EFAULT; + else { + /* current status of the TX buffer */ + curTXFill = buffer[2]; + retval = len; + } + } + /* suppress errors */ + /* + else { + err("Read from device failed, error %d",retval); + } + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + /* unlock the device */ + up(&dev->sem); +#endif + /* printk(KERN_INFO "CommandIR Reporting TX buffer at %d bytes. \n", + * curTXFill); */ + return retval; +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +EXPORT_SYMBOL_NOVERS(cmdir_read); +#else +EXPORT_SYMBOL(cmdir_read); +#endif + +static ssize_t cmdir_file_write(struct file *file, const char *buffer, + size_t count, loff_t *ppos) +{ + int retval; + int i; + int equalsign = 0; + int changeType = 0; + unsigned char ctrl_buffer[MCU_CTRL_SIZE]; + char *local_buffer; + int minor; + + /* set as default - if non-specific error, + * won't keep calling this function */ + retval = count; + local_buffer = kmalloc(count, GFP_KERNEL); + + /* verify that we actually have some data to write */ + if (count == 0) { + err("Write request of 0 bytes"); + goto exit; + } + if (count > 64) { + err("Input too long"); + goto exit; + } + + /* copy the data from userspace into our local buffer */ + if (copy_from_user(local_buffer, buffer, count)) { + retval = -EFAULT; + goto exit; + } + + /* parse code */ + changeType = cNothing; + equalsign = 0; + for (i = 0; i < MCU_CTRL_SIZE; i++) + ctrl_buffer[i] = 'j'; + + for (i = 0; i < count; i++) { + switch (local_buffer[i]) { + case 'X': + case 'x': + if ((i > 0) && ((local_buffer[i - 1] == 'R') + || (local_buffer[i - 1] == 'r'))) + changeType = cRX; + break; + case 'S': + case 's': + if ((i > 1) && ((local_buffer[i - 1] == 'E') + || (local_buffer[i - 1] == 'e'))) { + if ((local_buffer[i-2] == 'R') + || (local_buffer[i-2] == 'r')) + changeType = cRESET; + } + break; + case 'L': + case 'l': + if ((i > 0) && ((local_buffer[i - 1] == 'F') + || (local_buffer[i - 1] == 'f'))) + changeType = cFLASH; + break; + case 'C': + case 'c': + if ((i > 0) && ((local_buffer[i - 1] == 'L') + || (local_buffer[i - 1] == 'l'))) + changeType = cLCD; + break; + case '=': + if (changeType != cNothing) + equalsign = i; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if (equalsign > 0) { + minor = local_buffer[i] - ASCII0; + switch (changeType) { + case cRESET: + ctrl_buffer[0] = RESET_HEADER; + retval = write_core(ctrl_buffer, + MCU_CTRL_SIZE, + cmdir_write_bulk_callback, + minor); + if (retval != MCU_CTRL_SIZE) { + if (retval == -ENODEV) + err("Device %d " + "unplugged", minor); + else + err("Error on write to " + "%d", minor); + goto exit; + } else + retval = count; + init_cmdir_var(minor); + break; + case cFLASH: + ctrl_buffer[0] = FLASH_HEADER; + info("Flashing indicators on device %d", + minor); + retval = write_core(ctrl_buffer, + MCU_CTRL_SIZE, + cmdir_write_bulk_callback, + minor); + if (retval != MCU_CTRL_SIZE) { + if (retval == -ENODEV) + err("Device %d " + "unplugged", minor); + else + err("Error on write to " + "%d", minor); + goto exit; + } else + retval = count; + break; + case cRX: + rx_device = minor; + info("Default receiver set to %d", + minor); + break; + case cLCD: + lcd_device = minor; + info("commandir: Default LCD set to %d", + minor); + break; + default: + break; + } + } + break; + case ',': + equalsign = 0; + changeType = cNothing; + break; + default: + if ((equalsign > 0) && (local_buffer[i] > 32)) { + err("Non-numerical argument"); + goto exit; + } + break; + } + } + + if ((changeType != cNothing) && (equalsign == 0)) + err("No device specified"); + if (changeType == cNothing) + err("Unknown command"); + +exit: + kfree(local_buffer); + return retval; +} + +int cmdir_write(unsigned char *buffer, int count, + void *callback_fct, int usecdelay) +{ + /* Always add to queue, then send queue number + * no locks + * mbodkin, Sept 8, 2005 */ + int ret = 0; + if (debug_commandir == 1) { + do_gettimeofday(&tp); + printk(KERN_INFO "cmdir_write at %d\n", (int)tp.tv_usec); + } + ret = add_cmdir_queue(buffer, count, callback_fct, usecdelay); + + if (ret == -1) { + printk(KERN_INFO "cmdir_write returning 0\n"); + return 0; + } + return count; + +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +EXPORT_SYMBOL_NOVERS(cmdir_write); +#else +EXPORT_SYMBOL(cmdir_write); +#endif + +int add_cmdir_queue(unsigned char *buffer, int count, + void *callback_vct, int usecdelay) +{ + int ret = 0; + if ((nexttofill + 1) % (QUEUELENGTH - 1) == nexttosend) { + + /* our buffer is full */ + printk(KERN_INFO "Too many packets backlogged " + "in CommandIR Queue.\n"); + return -1; + } + /* go ahead and use this one: */ + memcpy(ourbuffers[nexttofill], buffer, count); + ourbufferlengths[nexttofill] = count; + waitusecs[nexttofill] = (usecdelay == 0) ? 10000 : usecdelay; + /* printk(KERN_INFO "Adding %d to queue at position %d.\n", + * count, nexttofill); */ + nexttofill = (nexttofill + 1) % (QUEUELENGTH - 1); + ret = nexttofill; + /* if (timer_running == 0) */ + send_queue(); /* fake it if the timer's not running */ + return ret; /* we accepted the full packet */ + +} + +int send_queue() +{ + int last_sent = 0; + int ret = 0; + if (debug_commandir == 1) { + do_gettimeofday(&tp); + printk(KERN_INFO "Send_queue() at %d\n", (int)tp.tv_usec); + } + /* initiate the send/callback routine if not already running. */ + if (send_status == SEND_IDLE) { + if (!(nexttofill == nexttosend)) { + /* start it up: */ + + last_sent = nexttosend - 1; + if (last_sent < 0) + last_sent = QUEUELENGTH - 1; + /* Final check - is it TIME to send this packet yet? */ + /* if (wait_to_tx(waitusecs[last_sent]) == 0) { */ + /* always send if there's room, + * otherwise wait until room */ + if (curTXFill < 190) { + if (debug_commandir == 1) { + do_gettimeofday(&tp); + printk(KERN_INFO "Sending packet data " + "at %d\n", (int)tp.tv_usec); + } + ret = cmdir_write_queue(ourbuffers[nexttosend], + ourbufferlengths[nexttosend], NULL); + if (ret <= 0) { + /* send failed - the device is either + * unplugged or full + * nexttosend = + * (nexttosend + 1) + * % (QUEUELENGTH - 1); */ + send_status = SEND_IDLE; + return 0; /*send_queue(); */ + } else + nexttosend = (nexttosend + 1) + % (QUEUELENGTH - 1); + return 1; + } else { + if (debug_commandir == 1) { + do_gettimeofday(&tp); + printk(KERN_INFO "Not time to send yet " + "- starting timer at %d.\n", + (int)tp.tv_usec); + printk(KERN_INFO "Enabling timer.\n"); + } + return 0; /* doesn't matter anymore */ + } + } else { + if (debug_commandir == 1) { + do_gettimeofday(&tp); + printk(KERN_INFO "No more data to send %d!\n", + (int)tp.tv_usec); + } + last_tx_sec = 0; /* reset our TX counters */ + last_tx_usec = 0; + return 1; /* nothing more to send! */ + } + } else { + if (debug_commandir == 1) + /* will try again on the callback */ + printk(KERN_INFO "Already sending\n"); + return 1; /* then the timer shouldn't be running... */ + } + return 0; /* should never get here... */ +} + + +int wait_to_tx(int usecs) +{ + /* don't return until last_time + usecs has been reached + * for non-zero last_tx's. */ + int wait_until_sec = 0, wait_until_usec = 0; + int now_sec = 0, now_usec = 0; + if (debug_commandir == 1) + printk(KERN_INFO "waittotx(%d)\n", usecs); + if (usecs == 0) + return 0; + + if (!(last_tx_sec == 0 && last_tx_usec == 0)) { + /* calculate wait time: */ + wait_until_sec = last_tx_sec + (usecs / 1000000); + wait_until_usec = last_tx_usec + usecs; + + do_gettimeofday(&tp); + now_sec = tp.tv_sec; + now_usec = tp.tv_usec; + + if (wait_until_usec > 1000000) { + /* we've spilled over to the next second. */ + wait_until_sec++; + wait_until_usec -= 1000000; + /* printk(KERN_INFO "usec rollover\n"); */ + } + if (debug_commandir == 1) + printk(KERN_INFO "Testing for the right second, now = " + "%d %d, wait = %d %d\n", + now_sec, now_usec, + wait_until_sec, wait_until_usec); + /* now we are always on the same second. */ + if (now_sec > wait_until_sec) { + if (debug_commandir == 1) + printk(KERN_INFO "Setting last_tx_sec to %d.\n", + wait_until_sec); + last_tx_sec = wait_until_sec; + last_tx_usec = wait_until_usec; + return 0; + } + + if ((now_sec == wait_until_sec) + && (now_usec > wait_until_usec)) { + if (debug_commandir == 1) + printk(KERN_INFO "Setting last_tx_sec to %d.\n", + wait_until_sec); + last_tx_sec = wait_until_sec; + last_tx_usec = wait_until_usec; + return 0; + } + return -1; /* didn't send */ + } + + do_gettimeofday(&tp); + last_tx_usec = tp.tv_usec; + last_tx_sec = tp.tv_sec; + return 0; /* if there's no last even, go ahead and send */ +} + + +int cmdir_write_queue(unsigned char *buffer, int count, void *callback_fct) +{ + int retval = count; + static char prev_signal_num; + unsigned char next_mask; + unsigned int multiplier; + int i; + + send_status = SEND_ACTIVE; + + if (count < 2) { + err("Not enough bytes (write request of %d bytes)", count); + return count; + } + + /* check data; decide which device to send to */ + switch (buffer[0]) { + case TX_HEADER: + case TX_HEADER_NEW: + /* this is LIRC transmit data */ + if (curTXFill >= 190) { + printk(KERN_INFO + "TX buffer too full to send more TX data\n"); + return 0; + } + if (next_transmitters != transmitters) { + if (buffer[1] != prev_signal_num) + /* this is new signal; change transmitter mask*/ + transmitters = next_transmitters; + } + prev_signal_num = buffer[1]; + + multiplier = 1; + for (i = 0; i < MAX_DEVICES; i++) { + next_mask = 0; + if (transmitters & (0x01*multiplier)) + next_mask |= TX1_ENABLE; + if (transmitters & (0x02*multiplier)) + next_mask |= TX2_ENABLE; + if (transmitters & (0x04*multiplier)) + next_mask |= TX3_ENABLE; + if (transmitters & (0x08*multiplier)) + next_mask |= TX4_ENABLE; + + if (next_mask > 0) { + buffer[1] = next_mask; + retval = write_core(buffer, count, + callback_fct, i); + if (retval != count) { + if (retval == -ENODEV) + err("Device %d not plugged in", + i); + else + err("Write error to device %d", + i); + return retval; + } + } + multiplier = multiplier*0x10; + } + return retval; + break; + case LCD_HEADER: + return write_core(buffer, count, callback_fct, lcd_device); + break; + default: + return write_core(buffer, count, callback_fct, def_device); + break; + } + /* should never get here */ + return retval; + +} + +int write_core(unsigned char *buffer, int count, + void *callback_fct, int device_num) +{ + struct usb_skel *dev; + int retval = count; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + ssize_t bytes_written = 0; + if (minor_table[device_num] == NULL) + /* device is unplugged */ + return -ENODEV; + dev = minor_table[device_num]; + + /* lock this object */ + down(&dev->sem); + + /* see if we are already in the middle of a write */ + if (dev->write_urb->status == -EINPROGRESS) { + /*suppress errors - should just try sending again*/ + /*dbg(" - already writing");*/ + retval = -EINPROGRESS; + goto exit; + } + + /* we can only write as much as 1 urb will hold */ + bytes_written = (count > dev->bulk_out_size) ? + dev->bulk_out_size : count; + + /* copy the data into our urb */ + if (!(memcpy(dev->write_urb->transfer_buffer, buffer, bytes_written))) { + retval = -EFAULT; + goto exit; + } + + /* set up our urb */ + if (callback_fct == NULL) { + /*FILL_BULK_URB(dev->write_urb, dev->udev, + usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), + dev->write_urb->transfer_buffer, bytes_written, + cmdir_write_bulk_callback, dev); */ + usb_fill_bulk_urb(dev->write_urb, dev->udev, + usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), + dev->write_urb->transfer_buffer, bytes_written, + cmdir_write_bulk_callback, dev); + } else { + FILL_BULK_URB(dev->write_urb, dev->udev, + usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), + dev->write_urb->transfer_buffer, bytes_written, + callback_fct, dev); + } + + /* send the data out the bulk port */ + retval = usb_submit_urb(dev->write_urb); + if (!(retval)) + retval = bytes_written; + /* suppress errors */ + /* else { + err("Failed submitting write urb, error %d", retval); + } */ +exit: + /* unlock the device */ + up(&dev->sem); + return retval; /* this should be return error I think */ + +#else + struct usb_interface *interface; + struct urb *urb = NULL; + char *buf = NULL; + interface = usb_find_interface(&cmdir_driver, + USB_CMDIR_MINOR_BASE + device_num); + if (!interface) { + /* also check without adding base, for devfs */ + interface = usb_find_interface(&cmdir_driver, device_num); + if (!interface) + return -ENODEV; + } + dev = usb_get_intfdata(interface); + if (!dev) + return -ENODEV; + /* create a urb, and a buffer for it, and copy the data to the urb */ + urb = usb_alloc_urb(0, GFP_ATOMIC); /* Now -=Atomic=- */ + if (!urb) { + retval = -ENOMEM; + goto error; + } + buf = usb_buffer_alloc(dev->udev, count, + GFP_KERNEL, &urb->transfer_dma); + if (!buf) { + retval = -ENOMEM; + goto error; + } + if (!memcpy(buf, buffer, count)) { + retval = -EFAULT; + goto error; + } + /* initialize the urb properly */ + if (callback_fct == NULL) { + usb_fill_bulk_urb(urb, dev->udev, + usb_sndbulkpipe(dev->udev, + dev->bulk_out_endpointAddr), + buf, count, (void *) cmdir_write_bulk_callback, dev); + } else { + usb_fill_bulk_urb(urb, dev->udev, + usb_sndbulkpipe(dev->udev, + dev->bulk_out_endpointAddr), + buf, count, callback_fct, dev); + } + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* double check this */ + + /* send the data out the bulk port */ + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + err("%s - failed submitting write urb, error %d", + __FUNCTION__, retval); + goto error; + } + + /* release our reference to this urb, the USB + * core will eventually free it entirely */ + usb_free_urb(urb); + return count; + +error: + usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); + usb_free_urb(urb); + return retval; +#endif +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +static void cmdir_write_bulk_callback(struct urb *urb) +{ + if (debug_commandir == 1) { + do_gettimeofday(&tp); + printk(KERN_INFO "cmdir_write_bulk_callback at %d\n", + (int)tp.tv_usec); + } + /*if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) + return; + else { + dbg(" - urb status: %d", urb->status); + return; + }*/ + + send_status = SEND_IDLE; + /* printk(KERN_INFO "cmdir_write_bulk_callback - set idle\n"); */ + send_queue(); /* send the next packet */ + return; +} +#else +static void cmdir_write_bulk_callback(struct urb *urb, struct pt_regs *regs) +{ + struct usb_skel *dev; + dev = (struct usb_skel *)urb->context; + send_status = SEND_IDLE; + if (debug_commandir == 1) + printk(KERN_INFO "callback()\n"); + /* free up our allocated buffer */ + + usb_buffer_free(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + send_queue(); /* send the next packet */ + +} +#endif + +int set_tx_channels(unsigned int next_tx) +{ + next_transmitters = next_tx; + return 0; +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +EXPORT_SYMBOL_NOVERS(set_tx_channels); +#else +EXPORT_SYMBOL(set_tx_channels); +#endif + +module_init(usb_cmdir_init); +module_exit(usb_cmdir_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/lirc/lirc_cmdir/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_cmdir/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_CMDIR) += lirc_cmdir.o commandir.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_cmdir/lirc_cmdir.c +++ linux-2.6.27/ubuntu/lirc/lirc_cmdir/lirc_cmdir.c @@ -0,0 +1,613 @@ +/* $Id: lirc_cmdir.c,v 1.9 2008/01/13 11:13:49 lirc Exp $ */ + +/* + * lirc_cmdir.c - Driver for InnovationOne's COMMANDIR USB Transceiver + * + * This driver requires the COMMANDIR hardware driver, available at + * http://www.commandir.com/. + * + * Copyright (C) 2005 InnovationOne - Evelyn Yeung + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) +#error "**********************************************************" +#error " Sorry, this driver needs kernel version 2.2.18 or higher " +#error "**********************************************************" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lirc.h" +#include "lirc_dev/lirc_dev.h" +#include "kcompat.h" +#include "lirc_cmdir.h" + +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG fmt, ## args); \ + } while (0) + +struct lirc_cmdir { + int features; +}; + +struct lirc_cmdir hardware = { + ( + /* LIRC_CAN_SET_SEND_DUTY_CYCLE| */ + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| + LIRC_CAN_SET_TRANSMITTER_MASK| + LIRC_CAN_REC_MODE2) + , +}; + +#define LIRC_DRIVER_NAME "lirc_cmdir" +#define RBUF_LEN 256 +#define WBUF_LEN 256 +#define MAX_PACKET 64 + +static struct lirc_buffer rbuf; +static lirc_t wbuf[WBUF_LEN]; +static unsigned char cmdir_char[4*WBUF_LEN]; +static unsigned char write_control[MCU_CTRL_SIZE]; +static unsigned int last_mc_time; +static int usb_status = ON; +static unsigned char signal_num; +char timerval; + +unsigned int freq = 38000; +/* unsigned int duty_cycle = 50; */ + + +#ifndef MAX_UDELAY_MS +#define MAX_UDELAY_US 5000 +#else +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) +#endif + +static inline void safe_udelay(unsigned long usecs) +{ + while (usecs > MAX_UDELAY_US) { + udelay(MAX_UDELAY_US); + usecs -= MAX_UDELAY_US; + } + udelay(usecs); +} + +static unsigned int get_time_value(unsigned int firstint, + unsigned int secondint, unsigned char overflow) +{ /* get difference between two timestamps from MCU */ + unsigned int t_answer = 0; + + if (secondint > firstint) { + t_answer = secondint - firstint + overflow*65536; + } else { + if (overflow > 0) + t_answer = (65536 - firstint) + secondint + + (overflow - 1) * 65536; + else + t_answer = (65536 - firstint) + secondint; + } + + /* clamp to long signal */ + if (t_answer > 16000000) + t_answer = PULSE_MASK; + + return t_answer; +} + + +static int set_use_inc(void *data) +{ + /* Init read buffer. */ + if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0) + return -ENOMEM; + + MOD_INC_USE_COUNT; + return 0; +} + +static void set_use_dec(void *data) +{ + lirc_buffer_free(&rbuf); + MOD_DEC_USE_COUNT; +} + + +static void usb_error_handle(int retval) +{ + switch (retval) { + case -ENODEV: + /* device has been unplugged */ + if (usb_status == ON) { + usb_status = OFF; + printk(LIRC_DRIVER_NAME ": device is unplugged\n"); + } + break; + default: + printk(LIRC_DRIVER_NAME ": usb error = %d\n", retval); + break; + } +} + +static int write_to_usb(unsigned char *buffer, int count, int time_elapsed) +{ + int write_return; + + write_return = cmdir_write(buffer, count, NULL, time_elapsed); + if (write_return != count) { + usb_error_handle(write_return); + } else { + if (usb_status == OFF) { + printk(LIRC_DRIVER_NAME ": device is now plugged in\n"); + usb_status = ON; + } + } + return write_return; +} + +static void set_freq(void) +{ + /* float tempfreq = 0.0; */ + int write_return; + + /* + * Can't use floating point in 2.6 kernel! + * May be some loss of precision + */ + timerval = (1000000 / freq) / 2; + write_control[0] = FREQ_HEADER; + write_control[1] = timerval; + write_control[2] = 0; + write_return = write_to_usb(write_control, MCU_CTRL_SIZE, 0); + if (write_return == MCU_CTRL_SIZE) + printk(LIRC_DRIVER_NAME ": freq set to %dHz\n", freq); + else + printk(LIRC_DRIVER_NAME ": freq unchanged\n"); + +} + +static int cmdir_convert_RX(unsigned char *orig_rxbuffer) +{ + unsigned char tmp_char_buffer[80]; + unsigned int tmp_int_buffer[20]; + unsigned int final_data_buffer[20]; + unsigned int num_data_values = 0; + unsigned char num_data_bytes = 0; + unsigned int orig_index = 0; + int i; + + for (i = 0; i < 80; i++) + tmp_char_buffer[i] = 0; + for (i = 0; i < 20; i++) + tmp_int_buffer[i] = 0; + + /* + * get number of data bytes that follow the control bytes + * (NOT including them) + */ + num_data_bytes = orig_rxbuffer[1]; + + /* check if num_bytes is multiple of 3; if not, error */ + if (num_data_bytes % 3 > 0) + return -1; + if (num_data_bytes > 60) + return -3; + if (num_data_bytes < 3) + return -2; + + /* + * get number of ints to be returned; num_data_bytes does + * NOT include control bytes + */ + num_data_values = num_data_bytes/3; + + for (i = 0; i < num_data_values; i++) { + tmp_char_buffer[i*4] = orig_rxbuffer[(i+1)*3]; + tmp_char_buffer[i*4+1] = orig_rxbuffer[(i+1)*3+1]; + tmp_char_buffer[i*4+2] = 0; + tmp_char_buffer[i*4+3] = 0; + } + + /* convert to int array */ + memcpy((unsigned char *)tmp_int_buffer, tmp_char_buffer, + (num_data_values*4)); + + if (orig_rxbuffer[5] < 255) { + /* space */ + final_data_buffer[0] = get_time_value(last_mc_time, + tmp_int_buffer[0], + orig_rxbuffer[5]); + } else { /* is pulse */ + final_data_buffer[0] = get_time_value(last_mc_time, + tmp_int_buffer[0], + 0); + final_data_buffer[0] |= PULSE_BIT; + } + for (i = 1; i < num_data_values; i++) { + /* + * index of orig_rxbuffer that corresponds to + * overflow/pulse/space + */ + orig_index = (i + 1)*3 + 2; + if (orig_rxbuffer[orig_index] < 255) { + final_data_buffer[i] = + get_time_value(tmp_int_buffer[i - 1], + tmp_int_buffer[i], + orig_rxbuffer[orig_index]); + } else { + final_data_buffer[i] = + get_time_value(tmp_int_buffer[i - 1], + tmp_int_buffer[i], + 0); + final_data_buffer[i] |= PULSE_BIT; + } + } + last_mc_time = tmp_int_buffer[num_data_values - 1]; + + if (lirc_buffer_full(&rbuf)) { + printk(KERN_ERR LIRC_DRIVER_NAME ": lirc_buffer is full\n"); + return -EOVERFLOW; + } + lirc_buffer_write_n(&rbuf, (char *)final_data_buffer, num_data_values); + + return 0; +} + + +static int usb_read_once(void) +{ + int read_retval = 0; + int conv_retval = 0; + unsigned char read_buffer[MAX_PACKET]; + int i = 0; + int tooFull = 5; /* read up to 5 packets */ + + for (i = 0; i < MAX_PACKET; i++) + read_buffer[i] = 0; + + while (tooFull--) { + read_retval = cmdir_read(read_buffer, MAX_PACKET); + /* Loop until we unload the data build-up */ + if (read_buffer[1] < 60) + tooFull = 0; + if (!(read_retval == MAX_PACKET)) { + if (read_retval == -ENODEV) { + if (usb_status == ON) { + printk(KERN_ALERT LIRC_DRIVER_NAME + ": device is unplugged\n"); + usb_status = OFF; + } + } else { + /* supress errors */ + printk(KERN_ALERT LIRC_DRIVER_NAME + ": usb error on read = %d\n", + read_retval); + return -ENODATA; + } + dprintk("Error 3\n"); + return -ENODATA; + } else { + if (usb_status == OFF) { + usb_status = ON; + printk(LIRC_DRIVER_NAME + ": device is now plugged in\n"); + } + } + + if (read_buffer[0] & 0x08) { + conv_retval = cmdir_convert_RX(read_buffer); + if (conv_retval == 0) { + if (!tooFull) + return 0; + else + dprintk("Looping for more data...\n"); + } else { + dprintk("Error 2: %d\n", (int)conv_retval); + return -ENODATA; + } + } else { + /* There really is no data in their buffer */ + dprintk("Empty RX Buffer!\n"); + return -ENODATA; + } + } + return -1; +} + +int add_to_buf(void *data, struct lirc_buffer *buf) +{ + return usb_read_once(); +} + + +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *ppos) +{ + int i, count; + unsigned int mod_signal_length = 0; + unsigned int time_elapse = 0; + unsigned int total_time_elapsed = 0; + unsigned int num_bytes_already_sent = 0; + unsigned int hibyte = 0; + unsigned int lobyte = 0; + int cmdir_cnt = 0; + unsigned int wait_this = 0; + struct timeval start_time; + struct timeval end_time; + unsigned int real_time_elapsed = 0; + + /* save the time we started the write: */ + do_gettimeofday(&start_time); + + if (n % sizeof(lirc_t)) + return -EINVAL; + + count = n/sizeof(lirc_t); + if (count > WBUF_LEN || count % 2 == 0) + return -EINVAL; + if (copy_from_user(wbuf, buf, n)) + return -EFAULT; + + /* + * the first time we have to flag that this is the start of a new + * signal otherwise COMMANDIR may receive 2 back-to-back pulses & + * invert the signal + */ + cmdir_char[0] = TX_HEADER_NEW; + signal_num++; + cmdir_char[1] = signal_num; + cmdir_cnt = 2; + for (i = 0; i < count; i++) { + /* conversion to number of modulation frequency pulse edges */ + mod_signal_length = wbuf[i] >> 3; + /* + * account for minor rounding errors - + * calculate length from this: + */ + time_elapse += mod_signal_length * timerval; + + hibyte = mod_signal_length / 256; + lobyte = mod_signal_length % 256; + cmdir_char[cmdir_cnt+1] = lobyte; + cmdir_char[cmdir_cnt] = hibyte; + cmdir_cnt += 2; + + /* write data to usb if full packet is collected */ + if (cmdir_cnt % MAX_PACKET == 0) { + write_to_usb(cmdir_char, MAX_PACKET, time_elapse); + + total_time_elapsed += time_elapse; + + num_bytes_already_sent += MAX_PACKET; + time_elapse = 0; + + if ((i + 1) < count) { + /* still more to send: */ + cmdir_char[0] = TX_HEADER; /* Next Packet */ + cmdir_char[1] = signal_num; + cmdir_cnt = 2; /* reset the count */ + } + } + } + + /* send last chunk of data */ + if (cmdir_cnt > 0) { + total_time_elapsed += time_elapse; + write_to_usb(cmdir_char, cmdir_cnt, time_elapse); + } + /* XXX ERS remove all this? */ + /* + * we need to _manually delay ourselves_ to remain backwards + * compatible with LIRC and prevent our queue buffer from overflowing. + * Queuing in this driver is about instant, and send_start for example + * will fill it up quickly and prevent send_stop from taking immediate + * effect. + */ + dprintk("Total elapsed time is: %d. \n", total_time_elapsed); + do_gettimeofday(&end_time); + /* + * udelay for the difference between endtime and + * start + total_time_elapsed + */ + if (start_time.tv_usec < end_time.tv_usec) + real_time_elapsed = (end_time.tv_usec - start_time.tv_usec); + else + real_time_elapsed = ((end_time.tv_usec + 1000000) - + start_time.tv_usec); + dprintk("Real time elapsed was %u.\n", real_time_elapsed); + if (real_time_elapsed < (total_time_elapsed - 1000)) + wait_this = total_time_elapsed - real_time_elapsed - 1000; + +#if 0 /* enable this for backwards compatibility */ + safe_udelay(wait_this); +#endif + + return(n); +} + + +static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int result; + unsigned long value; + unsigned int ivalue; + unsigned int multiplier = 1; + unsigned int mask = 0; + int i; + + switch (cmd) { + case LIRC_SET_TRANSMITTER_MASK: + if (!(hardware.features&LIRC_CAN_SET_TRANSMITTER_MASK)) + return -ENOIOCTLCMD; + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + for (i = 0; i < MAX_CHANNELS; i++) { + multiplier = multiplier * 0x10; + mask |= multiplier; + } + if (ivalue >= mask) + return MAX_CHANNELS; + set_tx_channels(ivalue); + return 0; + break; + + case LIRC_GET_SEND_MODE: + if (!(hardware.features & LIRC_CAN_SEND_MASK)) + return -ENOIOCTLCMD; + + result = put_user(LIRC_SEND2MODE + (hardware.features & LIRC_CAN_SEND_MASK), + (unsigned long *) arg); + if (result) + return result; + break; + + case LIRC_SET_SEND_MODE: + if (!(hardware.features&LIRC_CAN_SEND_MASK)) + return -ENOIOCTLCMD; + + result = get_user(value, (unsigned long *)arg); + if (result) + return result; + break; + + case LIRC_GET_LENGTH: + return -ENOSYS; + break; + + case LIRC_SET_SEND_DUTY_CYCLE: + dprintk(KERN_WARNING LIRC_DRIVER_NAME + ": SET_SEND_DUTY_CYCLE\n"); + + if (!(hardware.features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *)arg); + if (result) + return result; + if (ivalue <= 0 || ivalue > 100) + return -EINVAL; + + /* TODO: */ + dprintk(LIRC_DRIVER_NAME + ": set_send_duty_cycle not yet supported\n"); + + return 0; + break; + + case LIRC_SET_SEND_CARRIER: + dprintk(KERN_WARNING LIRC_DRIVER_NAME ": SET_SEND_CARRIER\n"); + + if (!(hardware.features & LIRC_CAN_SET_SEND_CARRIER)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *)arg); + if (result) + return result; + if (ivalue > 500000 || ivalue < 24000) + return -EINVAL; + if (ivalue != freq) { + freq = ivalue; + set_freq(); + } + return 0; + break; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static struct file_operations lirc_fops = { + .write = lirc_write, +}; + +static struct lirc_plugin plugin = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 20, + .data = NULL, + .add_to_buf = add_to_buf, + .get_queue = NULL, + .rbuf = &rbuf, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .ioctl = lirc_ioctl, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + +#ifdef MODULE + +MODULE_AUTHOR("Evelyn Yeung, Matt Bodkin"); +MODULE_DESCRIPTION("InnovationOne driver for " + "CommandIR USB infrared transceiver"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +#ifndef KERNEL_2_5 +EXPORT_NO_SYMBOLS; +#endif + +int init_module(void) +{ + plugin.features = hardware.features; + plugin.minor = lirc_register_plugin(&plugin); + if (plugin.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": register_chrdev failed!\n"); + return -EIO; + } + set_freq(); + return 0; +} + +void cleanup_module(void) +{ + lirc_unregister_plugin(plugin.minor); + printk(KERN_INFO LIRC_DRIVER_NAME ": module removed\n"); +} + +#endif + + --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/bttv_deprecated.c +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/bttv_deprecated.c @@ -0,0 +1,44 @@ +//Temporarily added until a resolution is reached upstream +//For kernel 2.6.22 + +#include +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,22) +#include "extra_2.6.22/bttv.h" +#include "extra_2.6.22/bttvp.h" +#else +#include "../drivers/media/video/bt8xx/bttv.h" +#include "../drivers/media/video/bt8xx/bttvp.h" +#endif + +struct bttv bttvs[BTTV_MAX]; +unsigned int bttv_debug; +unsigned int bttv_num; /* number of Bt848s in use */ + +int bttv_get_cardinfo(unsigned int card, int *type, unsigned *cardid) +{ + printk("The bttv_* interface is obsolete and will go away,\n" + "please use the new, sysfs based interface instead.\n"); + if (card >= bttv_num) { + return -1; + } + *type = bttvs[card].c.type; + *cardid = bttvs[card].cardid; + return 0; +} + +wait_queue_head_t* bttv_get_gpio_queue(unsigned int card) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return NULL; + } + + btv = &bttvs[card]; + if (bttvs[card].shutdown) { + return NULL; + } + return &btv->gpioq; +} + + --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/lirc_gpio.c +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/lirc_gpio.c @@ -0,0 +1,630 @@ +/* + * Remote control driver for the TV-card + * key codes are obtained from GPIO port + * + * (L) by Artur Lipowski + * patch for the AverMedia by Santiago Garcia Mantinan + * and Christoph Bartelmus + * patch for the BestBuy by Miguel Angel Alvarez + * patch for the Winfast TV2000 by Juan Toledo + * + * patch for the I-O Data GV-BCTV5/PCI by Jens C. Rasmussen + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: lirc_gpio.c,v 1.50 2007/09/27 19:47:20 lirc Exp $ + * + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 4) +#error "*******************************************************" +#error "Sorry, this driver needs kernel version 2.2.4 or higher" +#error "*******************************************************" +#endif + +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +#include +#endif +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +#include "../drivers/char/bttv.h" +#include "../drivers/char/bttvp.h" +#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16) +#include "extra_2.6.16/bttv.h" +#include "extra_2.6.16/bttvp.h" +#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,17) +#include "extra_2.6.17/bttv.h" +#include "extra_2.6.17/bttvp.h" +#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18) +#include "extra_2.6.18/bttv.h" +#include "extra_2.6.18/bttvp.h" +#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,20) +#include "extra_2.6.20/bttv.h" +#include "extra_2.6.20/bttvp.h" +#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,22) +#include "extra_2.6.22/bttv.h" +#include "extra_2.6.22/bttvp.h" +#include "bttv_deprecated.h" +#endif + +#if BTTV_VERSION_CODE < KERNEL_VERSION(0, 7, 45) +#error "*******************************************************" +#error " Sorry, this driver needs bttv version 0.7.45 or " +#error " higher. If you are using the bttv package, copy it to " +#error " the kernel " +#error "*******************************************************" +#endif + +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +/* insmod parameters */ +static int debug; +static int card; +static int minor = -1; +static int bttv_id = BTTV_BOARD_UNKNOWN; +static unsigned long gpio_mask; +static unsigned long gpio_enable; +static unsigned long gpio_lock_mask; +static unsigned long gpio_xor_mask; +static int soft_gap; +static int sample_rate = 10; + +struct rcv_info { + int bttv_id; + int card_id; + unsigned long gpio_mask; + unsigned long gpio_enable; + unsigned long gpio_lock_mask; + unsigned long gpio_xor_mask; + int soft_gap; + int sample_rate; + unsigned char code_length; +}; + +static struct rcv_info rcv_infos[] = { + {BTTV_BOARD_UNKNOWN, + 0, 0, 0, 0, 0, 0, 1, 0}, + {BTTV_BOARD_PXELVWPLTVPAK, + 0, 0x00003e00, 0, 0x0010000, 0, 0, 15, 32}, + {BTTV_BOARD_PXELVWPLTVPRO, + 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, + {BTTV_BOARD_PV_BT878P_9B, + 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, + {BTTV_BOARD_PV_BT878P_PLUS, + 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, +#ifdef BTTV_BOARD_PV_M4900 + {BTTV_BOARD_PV_M4900, + 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, +#endif + {BTTV_BOARD_AVERMEDIA, + 0, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, + + /* mapped to Capture98 */ + {BTTV_BOARD_AVPHONE98, + 0x00011461, 0x003b8000, 0x00004000, + 0x0800000, 0x00800000, 0, 10, 0}, + {BTTV_BOARD_AVERMEDIA98, + 0x00021461, 0x003b8000, 0x00004000, + 0x0800000, 0x00800000, 0, 10, 0}, + + /* mapped to Phone98 */ + {BTTV_BOARD_AVPHONE98, + 0x00031461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, + /* is this one correct? */ + {BTTV_BOARD_AVERMEDIA98, + 0x00041461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, + /* work-around for VDOMATE */ + {BTTV_BOARD_AVERMEDIA98, + 0x03001461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, + /* reported by Danijel Korzinek, AVerTV GOw/FM */ + {BTTV_BOARD_AVERMEDIA98, + 0x00000000, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, + + {BTTV_BOARD_CHRONOS_VS2, + 0, 0x000000f8, 0, 0x0000100, 0, 0, 20, 0}, + /* CPH031 and CPH033 cards (?) */ + /* MIRO was just a work-around */ + {BTTV_BOARD_MIRO, + 0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32}, + {BTTV_BOARD_DYNALINK, + 0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32}, +#ifdef BTTV_BOARD_ASKEY_CPH03X + {BTTV_BOARD_ASKEY_CPH03X, + 0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32}, +#endif + {BTTV_BOARD_WINVIEW_601, + 0, 0x00001f00, 0, 0x0004000, 0, 0, 0, 32}, +#ifdef BTTV_BOARD_KWORLD + {BTTV_BOARD_KWORLD, + 0, 0x00007f00, 0, 0x0004000, 0, 0, 12, 32}, +#endif + /* just a guess */ + {BTTV_BOARD_MAGICTVIEW061, + 0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32}, + {BTTV_BOARD_MAGICTVIEW063, + 0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32}, + {BTTV_BOARD_PHOEBE_TVMAS, + 0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32}, +#ifdef BTTV_BOARD_BESTBUY_EASYTV2 + {BTTV_BOARD_BESTBUY_EASYTV, + 0, 0x00007F00, 0, 0x0004000, 0, 0, 10, 8}, + {BTTV_BOARD_BESTBUY_EASYTV2, + 0, 0x00007F00, 0, 0x0008000, 0, 0, 10, 8}, +#endif + /* lock_mask probably also 0x100, or maybe it is 0x0 for all others? */ + {BTTV_BOARD_FLYVIDEO, + 0, 0x000000f8, 0, 0, 0, 0, 0, 42}, + {BTTV_BOARD_FLYVIDEO_98, + 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42}, + {BTTV_BOARD_TYPHOON_TVIEW, + 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42}, +#ifdef BTTV_BOARD_FLYVIDEO_98FM + /* smorar@alfonzo.smuts.uct.ac.za */ + {BTTV_BOARD_FLYVIDEO_98FM, + 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42}, +#endif + /* The Leadtek WinFast TV 2000 XP card (id 0x6606107d) uses an + * extra gpio bit compared to the original TV 2000 card (id + * 0x217d6606); as the bttv-0.7.100 driver does not + * distinguish between the two cards, we enable the extra bit + * based on the card id: */ + {BTTV_BOARD_WINFAST2000, + 0x6606107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32}, + {BTTV_BOARD_WINFAST2000, + 0x6609107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32}, + {BTTV_BOARD_WINFAST2000, + 0xff06107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32}, + /* default: */ + {BTTV_BOARD_WINFAST2000, + 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 32}, +#ifdef BTTV_BOARD_GVBCTV5PCI + {BTTV_BOARD_GVBCTV5PCI, + 0, 0x00f0b000, 0, 0, 0, 0, 20, 8}, +#endif +}; + +static unsigned char code_length; +static unsigned char code_bytes = 1; + +#define MAX_BYTES 8 + +#define SUCCESS 0 +#define LOGHEAD "lirc_gpio (%d): " + +/* how many bits GPIO value can be shifted right before processing + * it is computed from the value of gpio_mask_parameter + */ +static unsigned char gpio_pre_shift; + +static inline int reverse(int data, int bits) +{ + int i; + int c; + + for (c = 0, i = 0; i < bits; i++) + c |= (((data & (1<>= gpio_pre_shift; + while (mask) { + if (mask & 1u) + codes[0] |= (gpio_val & 1u) << shift++; + mask >>= 1; + gpio_val >>= 1; + } + + dprintk(LOGHEAD "code is %lx\n", card, (unsigned long) codes[0]); + switch (bttv_id) { + case BTTV_BOARD_AVERMEDIA: + codes[2] = (codes[0]<<2)&0xff; + codes[3] = (~codes[2])&0xff; + codes[0] = 0x02; + codes[1] = 0xFD; + break; + case BTTV_BOARD_AVPHONE98: + codes[2] = ((codes[0]&(~0x1))<<2)&0xff; + codes[3] = (~codes[2])&0xff; + if (codes[0]&0x1) { + codes[0] = 0xc0; + codes[1] = 0x3f; + } else { + codes[0] = 0x40; + codes[1] = 0xbf; + } + break; + case BTTV_BOARD_AVERMEDIA98: + break; + case BTTV_BOARD_FLYVIDEO: + case BTTV_BOARD_FLYVIDEO_98: + case BTTV_BOARD_TYPHOON_TVIEW: +#ifdef BTTV_BOARD_FLYVIDEO_98FM + case BTTV_BOARD_FLYVIDEO_98FM: +#endif + codes[4] = codes[0]<<3; + codes[5] = ((~codes[4])&0xff); + + codes[0] = 0x00; + codes[1] = 0x1A; + codes[2] = 0x1F; + codes[3] = 0x2F; + break; + case BTTV_BOARD_MAGICTVIEW061: + case BTTV_BOARD_MAGICTVIEW063: + case BTTV_BOARD_PHOEBE_TVMAS: + codes[0] = (codes[0]&0x01) + | ((codes[0]&0x02)<<1) + | ((codes[0]&0x04)<<2) + | ((codes[0]&0x08)>>2) + | ((codes[0]&0x10)>>1); + /* FALLTHROUGH */ + case BTTV_BOARD_MIRO: + case BTTV_BOARD_DYNALINK: +#ifdef BTTV_BOARD_ASKEY_CPH03X + case BTTV_BOARD_ASKEY_CPH03X: +#endif + case BTTV_BOARD_PXELVWPLTVPAK: + case BTTV_BOARD_PXELVWPLTVPRO: + case BTTV_BOARD_PV_BT878P_9B: + case BTTV_BOARD_PV_BT878P_PLUS: +#ifdef BTTV_BOARD_PV_M4900 + case BTTV_BOARD_PV_M4900: +#endif +#ifdef BTTV_BOARD_KWORLD + case BTTV_BOARD_KWORLD: +#endif + codes[2] = reverse(codes[0], 8); + codes[3] = (~codes[2])&0xff; + codes[0] = 0x61; + codes[1] = 0xD6; + break; +#if 0 + /* derived from e-tech config file */ + /* 26 + 16 bits */ + /* won't apply it until it's confirmed with a fly98 */ + case BTTV_BOARD_FLYVIDEO_98: + case BTTV_BOARD_FLYVIDEO_98FM: + codes[4] = codes[0]<<3; + codes[5] = (~codes[4])&0xff; + + codes[0] = 0x00; + codes[1] = 0x1A; + codes[2] = 0x1F; + codes[3] = 0x2F; + break; +#endif + case BTTV_BOARD_WINFAST2000: + /* shift extra bit */ + codes[0] = (codes[0]&0x1f) | ((codes[0]&0x20) << 1); + case BTTV_BOARD_WINVIEW_601: + codes[2] = reverse(codes[0], 8); + codes[3] = (~codes[2])&0xff; + codes[0] = 0xC0; + codes[1] = 0x3F; + break; + default: + break; + } + + return SUCCESS; +} + +/* add_to_buf - copy a code to the buffer */ +static int add_to_buf(void *data, struct lirc_buffer *buf) +{ + static unsigned long next_time; + static unsigned char prev_codes[MAX_BYTES]; + unsigned long code = 0; + unsigned char cur_codes[MAX_BYTES]; + + if (bttv_read_gpio(card, &code)) { + dprintk(LOGHEAD "cannot read GPIO\n", card); + return -EIO; + } + + if (build_key(code, cur_codes)) + return -EFAULT; + + if (soft_gap) { + if (!memcmp(prev_codes, cur_codes, code_bytes) && + jiffies < next_time) + return -EAGAIN; + + next_time = jiffies + soft_gap; + } + memcpy(prev_codes, cur_codes, code_bytes); + + lirc_buffer_write_1(buf, cur_codes); + + return SUCCESS; +} + +static int set_use_inc(void *data) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static void set_use_dec(void *data) +{ + MOD_DEC_USE_COUNT; +} + +static wait_queue_head_t *get_queue(void *data) +{ + return bttv_get_gpio_queue(card); +} + +static struct lirc_plugin plugin = { + .name = "lirc_gpio ", + .add_to_buf = add_to_buf, + .get_queue = get_queue, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .dev = NULL, + .owner = THIS_MODULE, +}; + +/* + * + */ +static int gpio_remote_init(void) +{ + int ret; + unsigned int mask; + + /* "normalize" gpio_mask + * this means shift it right until first bit is set + */ + while (!(gpio_mask & 1u)) { + gpio_pre_shift++; + gpio_mask >>= 1; + } + + if (code_length) + plugin.code_length = code_length; + else { + /* calculate scan code length in bits if needed */ + plugin.code_length = 1; + mask = gpio_mask >> 1; + while (mask) { + if (mask & 1u) + plugin.code_length++; + mask >>= 1; + } + } + + code_bytes = (plugin.code_length/8) + (plugin.code_length % 8 ? 1 : 0); + if (MAX_BYTES < code_bytes) { + printk(LOGHEAD "scan code too long (%d bytes)\n", + minor, code_bytes); + return -EBADRQC; + } + + if (gpio_enable) { + if (bttv_gpio_enable(card, gpio_enable, gpio_enable)) { + printk(LOGHEAD "gpio_enable failure\n", minor); + return -EIO; + } + } + + + /* translate ms to jiffies */ + soft_gap = (soft_gap*HZ) / 1000; + + plugin.minor = minor; + plugin.sample_rate = sample_rate; + + ret = lirc_register_plugin(&plugin); + + if (0 > ret) { + printk(LOGHEAD "device registration failed with %d\n", + minor, ret); + return ret; + } + + minor = ret; + printk(LOGHEAD "driver registered\n", minor); + + return SUCCESS; +} + +#ifdef MODULE +/* + * + */ +int init_module(void) +{ + int type, cardid, card_type; + + if (MAX_IRCTL_DEVICES < minor) { + printk(KERN_INFO "lirc_gpio: parameter minor (%d) " + "must be less than %d!\n", + minor, MAX_IRCTL_DEVICES - 1); + return -EBADRQC; + } + + request_module("bttv"); + + /* if gpio_mask not zero then use module parameters + * instead of autodetecting TV card + */ + if (gpio_mask) { + if (sample_rate != 0 && + (2 > sample_rate || HZ < sample_rate)) { + printk(LOGHEAD "parameter sample_rate " + "must be between 2 and %d!\n", minor, HZ); + return -EBADRQC; + } + + if (sample_rate != 0 && soft_gap && + ((2000/sample_rate) > soft_gap || 1000 < soft_gap)) { + printk(LOGHEAD "parameter soft_gap " + "must be between %d and 1000!\n", + minor, 2000/sample_rate); + return -EBADRQC; + } + } else { + if (bttv_get_cardinfo(card, &type, &cardid) == -1) { + printk(LOGHEAD "could not get card type\n", minor); + return -EBADRQC; + } + printk(LOGHEAD "card type 0x%x, id 0x%x\n", minor, + type, cardid); + + if (type == BTTV_BOARD_UNKNOWN) { + printk(LOGHEAD "cannot detect TV card nr %d!\n", + minor, card); + return -EBADRQC; + } + for (card_type = 1; + card_type < sizeof(rcv_infos)/sizeof(struct rcv_info); + card_type++) { + if (rcv_infos[card_type].bttv_id == type && + (rcv_infos[card_type].card_id == 0 || + rcv_infos[card_type].card_id == cardid)) { + bttv_id = rcv_infos[card_type].bttv_id; + gpio_mask = rcv_infos[card_type].gpio_mask; + gpio_enable = rcv_infos[card_type].gpio_enable; + gpio_lock_mask = + rcv_infos[card_type].gpio_lock_mask; + gpio_xor_mask = + rcv_infos[card_type].gpio_xor_mask; + soft_gap = rcv_infos[card_type].soft_gap; + sample_rate = rcv_infos[card_type].sample_rate; + code_length = rcv_infos[card_type].code_length; + break; + } + } + if (type == BTTV_BOARD_AVPHONE98 && cardid == 0x00011461) + bttv_id = BTTV_BOARD_AVERMEDIA98; + + if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x00041461) + bttv_id = BTTV_BOARD_AVPHONE98; + + if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x03001461) + bttv_id = BTTV_BOARD_AVPHONE98; + + if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x00000000) + bttv_id = BTTV_BOARD_AVPHONE98; + + if (card_type == sizeof(rcv_infos)/sizeof(struct rcv_info)) { + printk(LOGHEAD "TV card type 0x%x not supported!\n", + minor, type); + return -EBADRQC; + } + } + + request_module("lirc_dev"); + + return gpio_remote_init(); +} + +/* + * + */ +void cleanup_module(void) +{ + lirc_unregister_plugin(minor); + + dprintk(LOGHEAD "module successfully unloaded\n", minor); +} + +/* Dont try to use it as a static version ! */ +MODULE_DESCRIPTION("Driver module for remote control (data " + "from bt848 GPIO port)"); +MODULE_AUTHOR("Artur Lipowski"); +MODULE_LICENSE("GPL"); + +module_param(minor, int, 0444); +MODULE_PARM_DESC(minor, "Preferred minor device number"); + +module_param(card, int, 0444); +MODULE_PARM_DESC(card, "TV card number to attach to"); + +module_param(gpio_mask, long, 0444); +MODULE_PARM_DESC(gpio_mask, "gpio_mask"); + +module_param(gpio_lock_mask, long, 0444); +MODULE_PARM_DESC(gpio_lock_mask, "gpio_lock_mask"); + +module_param(gpio_xor_mask, long, 0444); +MODULE_PARM_DESC(gpio_xor_mask, "gpio_xor_mask"); + +module_param(soft_gap, int, 0444); +MODULE_PARM_DESC(soft_gap, "Time between keypresses (in ms)"); + +module_param(sample_rate, int, 0444); +MODULE_PARM_DESC(sample_rate, "Sample rate (between 2 and HZ)"); + +module_param(bttv_id, int, 0444); +MODULE_PARM_DESC(bttv_id, "BTTV card type"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +EXPORT_NO_SYMBOLS; + +#endif /* MODULE */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/Makefile @@ -0,0 +1,4 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_GPIO) += lirc_gpio.o +lirc_gpio/lirc_gpio-objs += bttv_deprecated.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/bttv_deprecated.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/bttv_deprecated.h @@ -0,0 +1,6 @@ +//Temporarily re-added for Ubuntu Kernel 2.6.22 until upstream +//Resolution is reached. +extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); +extern int bttv_get_cardinfo(unsigned int card, int *type, + unsigned int *cardid); + --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.17/bttvp.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.17/bttvp.h @@ -0,0 +1,413 @@ +/* + + bttv - Bt848 frame grabber driver + + bttv's *private* header file -- nobody other than bttv itself + should ever include this file. + + (c) 2000-2002 Gerd Knorr + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BTTVP_H_ +#define _BTTVP_H_ + +#include +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "bt848.h" +#include "bttv.h" +#include "btcx-risc.h" + +#ifdef __KERNEL__ + +#define FORMAT_FLAGS_DITHER 0x01 +#define FORMAT_FLAGS_PACKED 0x02 +#define FORMAT_FLAGS_PLANAR 0x04 +#define FORMAT_FLAGS_RAW 0x08 +#define FORMAT_FLAGS_CrCb 0x10 + +#define RISC_SLOT_O_VBI 4 +#define RISC_SLOT_O_FIELD 6 +#define RISC_SLOT_E_VBI 10 +#define RISC_SLOT_E_FIELD 12 +#define RISC_SLOT_LOOP 14 + +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO 2 +#define RESOURCE_VBI 4 + +#define RAW_LINES 640 +#define RAW_BPL 1024 + +#define UNSET (-1U) + +#define clamp(x, low, high) min (max (low, x), high) + +/* ---------------------------------------------------------- */ + +struct bttv_tvnorm { + int v4l2_id; + char *name; + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ + u16 totalwidth; + u8 adelay, bdelay, iform; + u32 scaledtwidth; + u16 hdelayx1, hactivex1; + u16 vdelay; + u8 vbipack; + u16 vtotal; + int sram; + /* ITU-R frame line number of the first VBI line we can + capture, of the first and second field. */ + u16 vbistart[2]; +}; +extern const struct bttv_tvnorm bttv_tvnorms[]; + +struct bttv_format { + char *name; + int palette; /* video4linux 1 */ + int fourcc; /* video4linux 2 */ + int btformat; /* BT848_COLOR_FMT_* */ + int btswap; /* BT848_COLOR_CTL_* */ + int depth; /* bit/pixel */ + int flags; + int hshift,vshift; /* for planar modes */ +}; + +/* ---------------------------------------------------------- */ + +struct bttv_geometry { + u8 vtc,crop,comb; + u16 width,hscale,hdelay; + u16 sheight,vscale,vdelay,vtotal; +}; + +struct bttv_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* bttv specific */ + const struct bttv_format *fmt; + int tvnorm; + int btformat; + int btswap; + struct bttv_geometry geo; + struct btcx_riscmem top; + struct btcx_riscmem bottom; +}; + +struct bttv_buffer_set { + struct bttv_buffer *top; /* top field buffer */ + struct bttv_buffer *bottom; /* bottom field buffer */ + unsigned int top_irq; + unsigned int frame_irq; +}; + +struct bttv_overlay { + int tvnorm; + struct v4l2_rect w; + enum v4l2_field field; + struct v4l2_clip *clips; + int nclips; + int setup_ok; +}; + +struct bttv_fh { + struct bttv *btv; + int resources; +#ifdef VIDIOC_G_PRIORITY + enum v4l2_priority prio; +#endif + enum v4l2_buf_type type; + + /* video capture */ + struct videobuf_queue cap; + const struct bttv_format *fmt; + int width; + int height; + + /* current settings */ + const struct bttv_format *ovfmt; + struct bttv_overlay ov; + + /* video overlay */ + struct videobuf_queue vbi; + int lines; +}; + +/* ---------------------------------------------------------- */ +/* bttv-risc.c */ + +/* risc code generators - capture */ +int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int offset, unsigned int bpl, + unsigned int pitch, unsigned int lines); + +/* control dma register + risc main loop */ +void bttv_set_dma(struct bttv *btv, int override); +int bttv_risc_init_main(struct bttv *btv); +int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, + int irqflags); + +/* capture buffer handling */ +int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); +int bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set); +int bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi); +void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, + struct bttv_buffer *buf); + +/* overlay handling */ +int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, + const struct bttv_format *fmt, + struct bttv_buffer *buf); + + +/* ---------------------------------------------------------- */ +/* bttv-vbi.c */ + +void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines); + +extern struct videobuf_queue_ops bttv_vbi_qops; + +/* ---------------------------------------------------------- */ +/* bttv-gpio.c */ + + +extern struct bus_type bttv_sub_bus_type; +int bttv_sub_add_device(struct bttv_core *core, char *name); +int bttv_sub_del_devices(struct bttv_core *core); +void bttv_gpio_irq(struct bttv_core *core); + + +/* ---------------------------------------------------------- */ +/* bttv-driver.c */ + +/* insmod options */ +extern unsigned int bttv_verbose; +extern unsigned int bttv_debug; +extern unsigned int bttv_gpio; +extern void bttv_gpio_tracking(struct bttv *btv, char *comment); +extern int init_bttv_i2c(struct bttv *btv); +extern int fini_bttv_i2c(struct bttv *btv); + +#define bttv_printk if (bttv_verbose) printk +#define dprintk if (bttv_debug >= 1) printk +#define d2printk if (bttv_debug >= 2) printk + +#define BTTV_MAX_FBUF 0x208000 +#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) +#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BTTV_FREE_IDLE (HZ) /* one second */ + + +struct bttv_pll_info { + unsigned int pll_ifreq; /* PLL input frequency */ + unsigned int pll_ofreq; /* PLL output frequency */ + unsigned int pll_crystal; /* Crystal used for input */ + unsigned int pll_current; /* Currently programmed ofreq */ +}; + +/* for gpio-connected remote control */ +struct bttv_input { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + u32 mask_keycode; + u32 mask_keydown; +}; + +struct bttv_suspend_state { + u32 gpio_enable; + u32 gpio_data; + int disabled; + int loop_irq; + struct bttv_buffer_set video; + struct bttv_buffer *vbi; +}; + +struct bttv { + struct bttv_core c; + + /* pci device config */ + unsigned short id; + unsigned char revision; + unsigned char __iomem *bt848_mmio; /* pointer to mmio */ + + /* card configuration info */ + unsigned int cardid; /* pci subsystem id (bt878 based ones) */ + unsigned int tuner_type; /* tuner chip type */ + unsigned int tda9887_conf; + unsigned int svhs; + struct bttv_pll_info pll; + int triton1; + int gpioirq; + int (*custom_irq)(struct bttv *btv); + + int use_i2c_hw; + + /* old gpio interface */ + wait_queue_head_t gpioq; + int shutdown; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + + /* new gpio interface */ + spinlock_t gpio_lock; + + /* i2c layer */ + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_state, i2c_rc; + int i2c_done; + wait_queue_head_t i2c_queue; + struct i2c_client *i2c_msp34xx_client; + struct i2c_client *i2c_tvaudio_client; + + /* video4linux (1) */ + struct video_device *video_dev; + struct video_device *radio_dev; + struct video_device *vbi_dev; + + /* infrared remote */ + int has_remote; + struct bttv_ir *remote; + + /* locking */ + spinlock_t s_lock; + struct mutex lock; + int resources; + struct mutex reslock; +#ifdef VIDIOC_G_PRIORITY + struct v4l2_prio_state prio; +#endif + + /* video state */ + unsigned int input; + unsigned int audio; + unsigned int mute; + unsigned long freq; + int tvnorm,hue,contrast,bright,saturation; + struct v4l2_framebuffer fbuf; + unsigned int field_count; + + /* various options */ + int opt_combfilter; + int opt_lumafilter; + int opt_automute; + int opt_chroma_agc; + int opt_adc_crush; + int opt_vcr_hack; + int opt_whitecrush_upper; + int opt_whitecrush_lower; + int opt_uv_ratio; + int opt_full_luma_range; + int opt_coring; + + /* radio data/state */ + int has_radio; + int radio_user; + + /* miro/pinnacle + Aimslab VHX + philips matchbox (tea5757 radio tuner) support */ + int has_matchbox; + int mbox_we; + int mbox_data; + int mbox_clk; + int mbox_most; + int mbox_mask; + + /* ISA stuff (Terratec Active Radio Upgrade) */ + int mbox_ior; + int mbox_iow; + int mbox_csel; + + /* risc memory management data + - must aquire s_lock before changing these + - only the irq handler is supported to touch top + bottom + vcurr */ + struct btcx_riscmem main; + struct bttv_buffer *screen; /* overlay */ + struct list_head capture; /* video capture queue */ + struct list_head vcapture; /* vbi capture queue */ + struct bttv_buffer_set curr; /* active buffers */ + struct bttv_buffer *cvbi; /* active vbi buffer */ + int loop_irq; + int new_input; + + unsigned long cap_ctl; + unsigned long dma_on; + struct timer_list timeout; + struct bttv_suspend_state state; + + /* stats */ + unsigned int errors; + unsigned int framedrop; + unsigned int irq_total; + unsigned int irq_me; + + unsigned int users; + struct bttv_fh init; +}; + +/* our devices */ +#define BTTV_MAX 16 +extern unsigned int bttv_num; +extern struct bttv bttvs[BTTV_MAX]; + +/* private ioctls */ +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) +#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) + +#endif + +#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) +#define btread(adr) readl(btv->bt848_mmio+(adr)) + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +#endif /* _BTTVP_H_ */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.17/btcx-risc.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.17/btcx-risc.h @@ -0,0 +1,34 @@ +/* + */ +struct btcx_riscmem { + unsigned int size; + u32 *cpu; + u32 *jmp; + dma_addr_t dma; +}; + +struct btcx_skiplist { + int start; + int end; +}; + +int btcx_riscmem_alloc(struct pci_dev *pci, + struct btcx_riscmem *risc, + unsigned int size); +void btcx_riscmem_free(struct pci_dev *pci, + struct btcx_riscmem *risc); + +int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, + struct v4l2_clip *clips, unsigned int n); +int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, + unsigned int n, int mask); +void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); +void btcx_calc_skips(int line, int width, unsigned int *maxy, + struct btcx_skiplist *skips, unsigned int *nskips, + const struct v4l2_clip *clips, unsigned int nclips); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.17/bttv.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.17/bttv.h @@ -0,0 +1,390 @@ +/* + * + * bttv - Bt848 frame grabber driver + * + * card ID's and external interfaces of the bttv driver + * basically stuff needed by other drivers (i2c, lirc, ...) + * and is supported not to change much over time. + * + * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + * (c) 1999,2000 Gerd Knorr + * + */ + +#ifndef _BTTV_H_ +#define _BTTV_H_ + +#include +#include +#include +#include +#include + +/* ---------------------------------------------------------- */ +/* exported by bttv-cards.c */ + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ASOUND_SKYEYE 0x8d +#define BTTV_BOARD_SABRENT_TVFM 0x8e +#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f +#define BTTV_BOARD_MACHTV_MAGICTV 0x90 + +/* more card-specific defines */ +#define PT2254_L_CHANNEL 0x10 +#define PT2254_R_CHANNEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + +/* digital_mode */ +#define DIGITAL_MODE_VIDEO 1 +#define DIGITAL_MODE_CAMERA 2 + +struct bttv_core { + /* device structs */ + struct pci_dev *pci; + struct i2c_adapter i2c_adap; + struct list_head subs; /* struct bttv_sub_device */ + + /* device config */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int type; /* card type (pointer into tvcards[]) */ + char name[8]; /* dev name */ +}; + +struct bttv; + + +struct bttv_ir { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* Usual gpio signalling */ + + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + struct work_struct work; + struct timer_list timer; + + /* RC5 gpio */ + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + struct timer_list timer_keyup; /* timer_end for key release */ + u32 last_rc5; /* last good rc5 code */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + int active; /* building raw code */ +}; + +struct tvcard +{ + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; + unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO + u32 gpiomask; + u32 muxsel[16]; + u32 gpiomux[4]; /* Tuner, Radio, external, internal */ + u32 gpiomute; /* GPIO mute setting */ + u32 gpiomask2; /* GPIO MUX mask */ + + /* i2c audio flags */ + unsigned int no_msp34xx:1; + unsigned int no_tda9875:1; + unsigned int no_tda7432:1; + unsigned int needs_tvaudio:1; + unsigned int msp34xx_alt:1; + + /* flag: video pci function is unused */ + unsigned int no_video:1; + unsigned int has_dvb:1; + unsigned int has_remote:1; + unsigned int no_gpioirq:1; + + /* other settings */ + unsigned int pll; +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 + + unsigned int tuner_type; + unsigned int tuner_addr; + unsigned int radio_addr; + + unsigned int has_radio; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); +}; + +extern struct tvcard bttv_tvcards[]; + +/* identification / initialization of the card */ +extern void bttv_idcard(struct bttv *btv); +extern void bttv_init_card1(struct bttv *btv); +extern void bttv_init_card2(struct bttv *btv); + +/* card-specific funtions */ +extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); +extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); + +/* extra tweaks for some chipsets */ +extern void bttv_check_chipset(void); +extern int bttv_handle_chipset(struct bttv *btv); + +/* ---------------------------------------------------------- */ +/* exported by bttv-if.c */ + +/* this obsolete -- please use the sysfs-based + interface below for new code */ + +/* returns card type + card ID (for bt878-based ones) + for possible values see lines below beginning with #define BTTV_BOARD_UNKNOWN + returns negative value if error occurred +*/ +extern int bttv_get_cardinfo(unsigned int card, int *type, + unsigned int *cardid); +extern struct pci_dev* bttv_get_pcidev(unsigned int card); + +/* obsolete, use bttv_get_cardinfo instead */ +extern int bttv_get_id(unsigned int card); + +/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: + data | (current_GPOE_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_gpio_enable(unsigned int card, + unsigned long mask, unsigned long data); + +/* fills data with GPDATA register contents + returns negative value if error occurred +*/ +extern int bttv_read_gpio(unsigned int card, unsigned long *data); + +/* sets GPDATA register to new value: + (data & mask) | (current_GPDATA_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_write_gpio(unsigned int card, + unsigned long mask, unsigned long data); + +/* returns pointer to task queue which can be used as parameter to + interruptible_sleep_on + in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated + (wake_up_interruptible) and following call to the function bttv_read_gpio + should return new value of GPDATA, + returns NULL value if error occurred or queue is not available + WARNING: because there is no buffer for GPIO data, one MUST + process data ASAP +*/ +extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); + +/* call i2c clients +*/ +extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); + + + +/* ---------------------------------------------------------- */ +/* sysfs/driver-moded based gpio access interface */ + + +struct bttv_sub_device { + struct device dev; + struct bttv_core *core; + struct list_head list; +}; +#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) + +struct bttv_sub_driver { + struct device_driver drv; + char wanted[BUS_ID_SIZE]; + int (*probe)(struct bttv_sub_device *sub); + void (*remove)(struct bttv_sub_device *sub); + void (*gpio_irq)(struct bttv_sub_device *sub); +}; +#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) + +int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); +int bttv_sub_unregister(struct bttv_sub_driver *drv); + +/* gpio access functions */ +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); +u32 bttv_gpio_read(struct bttv_core *core); +void bttv_gpio_write(struct bttv_core *core, u32 value); +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); + +#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) +#define gpio_read() bttv_gpio_read(&btv->c) +#define gpio_write(value) bttv_gpio_write(&btv->c, value) +#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) + + +/* ---------------------------------------------------------- */ +/* i2c */ + +extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); +extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both); +extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); + +extern int bttv_input_init(struct bttv *dev); +extern void bttv_input_fini(struct bttv *dev); +extern void bttv_input_irq(struct bttv *dev); + +#endif /* _BTTV_H_ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.17/bt848.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.17/bt848.h @@ -0,0 +1,366 @@ +/* + bt848.h - Bt848 register offsets + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BT848_H_ +#define _BT848_H_ + +#ifndef PCI_VENDOR_ID_BROOKTREE +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#endif +#ifndef PCI_DEVICE_ID_BT848 +#define PCI_DEVICE_ID_BT848 0x350 +#endif +#ifndef PCI_DEVICE_ID_BT849 +#define PCI_DEVICE_ID_BT849 0x351 +#endif +#ifndef PCI_DEVICE_ID_BT878 +#define PCI_DEVICE_ID_BT878 0x36e +#endif +#ifndef PCI_DEVICE_ID_BT879 +#define PCI_DEVICE_ID_BT879 0x36f +#endif + + +/* Brooktree 848 registers */ + +#define BT848_DSTATUS 0x000 +#define BT848_DSTATUS_PRES (1<<7) +#define BT848_DSTATUS_HLOC (1<<6) +#define BT848_DSTATUS_FIELD (1<<5) +#define BT848_DSTATUS_NUML (1<<4) +#define BT848_DSTATUS_CSEL (1<<3) +#define BT848_DSTATUS_PLOCK (1<<2) +#define BT848_DSTATUS_LOF (1<<1) +#define BT848_DSTATUS_COF (1<<0) + +#define BT848_IFORM 0x004 +#define BT848_IFORM_HACTIVE (1<<7) +#define BT848_IFORM_MUXSEL (3<<5) +#define BT848_IFORM_MUX0 (2<<5) +#define BT848_IFORM_MUX1 (3<<5) +#define BT848_IFORM_MUX2 (1<<5) +#define BT848_IFORM_XTSEL (3<<3) +#define BT848_IFORM_XT0 (1<<3) +#define BT848_IFORM_XT1 (2<<3) +#define BT848_IFORM_XTAUTO (3<<3) +#define BT848_IFORM_XTBOTH (3<<3) +#define BT848_IFORM_NTSC 1 +#define BT848_IFORM_NTSC_J 2 +#define BT848_IFORM_PAL_BDGHI 3 +#define BT848_IFORM_PAL_M 4 +#define BT848_IFORM_PAL_N 5 +#define BT848_IFORM_SECAM 6 +#define BT848_IFORM_PAL_NC 7 +#define BT848_IFORM_AUTO 0 +#define BT848_IFORM_NORM 7 + +#define BT848_TDEC 0x008 +#define BT848_TDEC_DEC_FIELD (1<<7) +#define BT848_TDEC_FLDALIGN (1<<6) +#define BT848_TDEC_DEC_RAT (0x1f) + +#define BT848_E_CROP 0x00C +#define BT848_O_CROP 0x08C + +#define BT848_E_VDELAY_LO 0x010 +#define BT848_O_VDELAY_LO 0x090 + +#define BT848_E_VACTIVE_LO 0x014 +#define BT848_O_VACTIVE_LO 0x094 + +#define BT848_E_HDELAY_LO 0x018 +#define BT848_O_HDELAY_LO 0x098 + +#define BT848_E_HACTIVE_LO 0x01C +#define BT848_O_HACTIVE_LO 0x09C + +#define BT848_E_HSCALE_HI 0x020 +#define BT848_O_HSCALE_HI 0x0A0 + +#define BT848_E_HSCALE_LO 0x024 +#define BT848_O_HSCALE_LO 0x0A4 + +#define BT848_BRIGHT 0x028 + +#define BT848_E_CONTROL 0x02C +#define BT848_O_CONTROL 0x0AC +#define BT848_CONTROL_LNOTCH (1<<7) +#define BT848_CONTROL_COMP (1<<6) +#define BT848_CONTROL_LDEC (1<<5) +#define BT848_CONTROL_CBSENSE (1<<4) +#define BT848_CONTROL_CON_MSB (1<<2) +#define BT848_CONTROL_SAT_U_MSB (1<<1) +#define BT848_CONTROL_SAT_V_MSB (1<<0) + +#define BT848_CONTRAST_LO 0x030 +#define BT848_SAT_U_LO 0x034 +#define BT848_SAT_V_LO 0x038 +#define BT848_HUE 0x03C + +#define BT848_E_SCLOOP 0x040 +#define BT848_O_SCLOOP 0x0C0 +#define BT848_SCLOOP_CAGC (1<<6) +#define BT848_SCLOOP_CKILL (1<<5) +#define BT848_SCLOOP_HFILT_AUTO (0<<3) +#define BT848_SCLOOP_HFILT_CIF (1<<3) +#define BT848_SCLOOP_HFILT_QCIF (2<<3) +#define BT848_SCLOOP_HFILT_ICON (3<<3) + +#define BT848_SCLOOP_PEAK (1<<7) +#define BT848_SCLOOP_HFILT_MINP (1<<3) +#define BT848_SCLOOP_HFILT_MEDP (2<<3) +#define BT848_SCLOOP_HFILT_MAXP (3<<3) + + +#define BT848_OFORM 0x048 +#define BT848_OFORM_RANGE (1<<7) +#define BT848_OFORM_CORE0 (0<<5) +#define BT848_OFORM_CORE8 (1<<5) +#define BT848_OFORM_CORE16 (2<<5) +#define BT848_OFORM_CORE32 (3<<5) + +#define BT848_E_VSCALE_HI 0x04C +#define BT848_O_VSCALE_HI 0x0CC +#define BT848_VSCALE_YCOMB (1<<7) +#define BT848_VSCALE_COMB (1<<6) +#define BT848_VSCALE_INT (1<<5) +#define BT848_VSCALE_HI 15 + +#define BT848_E_VSCALE_LO 0x050 +#define BT848_O_VSCALE_LO 0x0D0 +#define BT848_TEST 0x054 +#define BT848_ADELAY 0x060 +#define BT848_BDELAY 0x064 + +#define BT848_ADC 0x068 +#define BT848_ADC_RESERVED (2<<6) +#define BT848_ADC_SYNC_T (1<<5) +#define BT848_ADC_AGC_EN (1<<4) +#define BT848_ADC_CLK_SLEEP (1<<3) +#define BT848_ADC_Y_SLEEP (1<<2) +#define BT848_ADC_C_SLEEP (1<<1) +#define BT848_ADC_CRUSH (1<<0) + +#define BT848_WC_UP 0x044 +#define BT848_WC_DOWN 0x078 + +#define BT848_E_VTC 0x06C +#define BT848_O_VTC 0x0EC +#define BT848_VTC_HSFMT (1<<7) +#define BT848_VTC_VFILT_2TAP 0 +#define BT848_VTC_VFILT_3TAP 1 +#define BT848_VTC_VFILT_4TAP 2 +#define BT848_VTC_VFILT_5TAP 3 + +#define BT848_SRESET 0x07C + +#define BT848_COLOR_FMT 0x0D4 +#define BT848_COLOR_FMT_O_RGB32 (0<<4) +#define BT848_COLOR_FMT_O_RGB24 (1<<4) +#define BT848_COLOR_FMT_O_RGB16 (2<<4) +#define BT848_COLOR_FMT_O_RGB15 (3<<4) +#define BT848_COLOR_FMT_O_YUY2 (4<<4) +#define BT848_COLOR_FMT_O_BtYUV (5<<4) +#define BT848_COLOR_FMT_O_Y8 (6<<4) +#define BT848_COLOR_FMT_O_RGB8 (7<<4) +#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) +#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) +#define BT848_COLOR_FMT_O_RAW (14<<4) +#define BT848_COLOR_FMT_E_RGB32 0 +#define BT848_COLOR_FMT_E_RGB24 1 +#define BT848_COLOR_FMT_E_RGB16 2 +#define BT848_COLOR_FMT_E_RGB15 3 +#define BT848_COLOR_FMT_E_YUY2 4 +#define BT848_COLOR_FMT_E_BtYUV 5 +#define BT848_COLOR_FMT_E_Y8 6 +#define BT848_COLOR_FMT_E_RGB8 7 +#define BT848_COLOR_FMT_E_YCrCb422 8 +#define BT848_COLOR_FMT_E_YCrCb411 9 +#define BT848_COLOR_FMT_E_RAW 14 + +#define BT848_COLOR_FMT_RGB32 0x00 +#define BT848_COLOR_FMT_RGB24 0x11 +#define BT848_COLOR_FMT_RGB16 0x22 +#define BT848_COLOR_FMT_RGB15 0x33 +#define BT848_COLOR_FMT_YUY2 0x44 +#define BT848_COLOR_FMT_BtYUV 0x55 +#define BT848_COLOR_FMT_Y8 0x66 +#define BT848_COLOR_FMT_RGB8 0x77 +#define BT848_COLOR_FMT_YCrCb422 0x88 +#define BT848_COLOR_FMT_YCrCb411 0x99 +#define BT848_COLOR_FMT_RAW 0xee + +#define BT848_VTOTAL_LO 0xB0 +#define BT848_VTOTAL_HI 0xB4 + +#define BT848_COLOR_CTL 0x0D8 +#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) +#define BT848_COLOR_CTL_COLOR_BARS (1<<6) +#define BT848_COLOR_CTL_RGB_DED (1<<5) +#define BT848_COLOR_CTL_GAMMA (1<<4) +#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) +#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) +#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) +#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) + +#define BT848_CAP_CTL 0x0DC +#define BT848_CAP_CTL_DITH_FRAME (1<<4) +#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) +#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) +#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) +#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) + +#define BT848_VBI_PACK_SIZE 0x0E0 + +#define BT848_VBI_PACK_DEL 0x0E4 +#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc +#define BT848_VBI_PACK_DEL_EXT_FRAME 2 +#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 + + +#define BT848_INT_STAT 0x100 +#define BT848_INT_MASK 0x104 + +#define BT848_INT_ETBF (1<<23) + +#define BT848_INT_RISCS (0xf<<28) +#define BT848_INT_RISC_EN (1<<27) +#define BT848_INT_RACK (1<<25) +#define BT848_INT_FIELD (1<<24) +#define BT848_INT_SCERR (1<<19) +#define BT848_INT_OCERR (1<<18) +#define BT848_INT_PABORT (1<<17) +#define BT848_INT_RIPERR (1<<16) +#define BT848_INT_PPERR (1<<15) +#define BT848_INT_FDSR (1<<14) +#define BT848_INT_FTRGT (1<<13) +#define BT848_INT_FBUS (1<<12) +#define BT848_INT_RISCI (1<<11) +#define BT848_INT_GPINT (1<<9) +#define BT848_INT_I2CDONE (1<<8) +#define BT848_INT_VPRES (1<<5) +#define BT848_INT_HLOCK (1<<4) +#define BT848_INT_OFLOW (1<<3) +#define BT848_INT_HSYNC (1<<2) +#define BT848_INT_VSYNC (1<<1) +#define BT848_INT_FMTCHG (1<<0) + + +#define BT848_GPIO_DMA_CTL 0x10C +#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) +#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) +#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) +#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) +#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) +#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) +#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) +#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) +#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) +#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) +#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) +#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) +#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) + +#define BT848_I2C 0x110 +#define BT878_I2C_MODE (1<<7) +#define BT878_I2C_RATE (1<<6) +#define BT878_I2C_NOSTOP (1<<5) +#define BT878_I2C_NOSTART (1<<4) +#define BT848_I2C_DIV (0xf<<4) +#define BT848_I2C_SYNC (1<<3) +#define BT848_I2C_W3B (1<<2) +#define BT848_I2C_SCL (1<<1) +#define BT848_I2C_SDA (1<<0) + +#define BT848_RISC_STRT_ADD 0x114 +#define BT848_GPIO_OUT_EN 0x118 +#define BT848_GPIO_REG_INP 0x11C +#define BT848_RISC_COUNT 0x120 +#define BT848_GPIO_DATA 0x200 + + +/* Bt848 RISC commands */ + +/* only for the SYNC RISC command */ +#define BT848_FIFO_STATUS_FM1 0x06 +#define BT848_FIFO_STATUS_FM3 0x0e +#define BT848_FIFO_STATUS_SOL 0x02 +#define BT848_FIFO_STATUS_EOL4 0x01 +#define BT848_FIFO_STATUS_EOL3 0x0d +#define BT848_FIFO_STATUS_EOL2 0x09 +#define BT848_FIFO_STATUS_EOL1 0x05 +#define BT848_FIFO_STATUS_VRE 0x04 +#define BT848_FIFO_STATUS_VRO 0x0c +#define BT848_FIFO_STATUS_PXV 0x00 + +#define BT848_RISC_RESYNC (1<<15) + +/* WRITE and SKIP */ +/* disable which bytes of each DWORD */ +#define BT848_RISC_BYTE0 (1U<<12) +#define BT848_RISC_BYTE1 (1U<<13) +#define BT848_RISC_BYTE2 (1U<<14) +#define BT848_RISC_BYTE3 (1U<<15) +#define BT848_RISC_BYTE_ALL (0x0fU<<12) +#define BT848_RISC_BYTE_NONE 0 +/* cause RISCI */ +#define BT848_RISC_IRQ (1U<<24) +/* RISC command is last one in this line */ +#define BT848_RISC_EOL (1U<<26) +/* RISC command is first one in this line */ +#define BT848_RISC_SOL (1U<<27) + +#define BT848_RISC_WRITE (0x01U<<28) +#define BT848_RISC_SKIP (0x02U<<28) +#define BT848_RISC_WRITEC (0x05U<<28) +#define BT848_RISC_JUMP (0x07U<<28) +#define BT848_RISC_SYNC (0x08U<<28) + +#define BT848_RISC_WRITE123 (0x09U<<28) +#define BT848_RISC_SKIP123 (0x0aU<<28) +#define BT848_RISC_WRITE1S23 (0x0bU<<28) + + +/* Bt848A and higher only !! */ +#define BT848_TGLB 0x080 +#define BT848_TGCTRL 0x084 +#define BT848_FCAP 0x0E8 +#define BT848_PLL_F_LO 0x0F0 +#define BT848_PLL_F_HI 0x0F4 + +#define BT848_PLL_XCI 0x0F8 +#define BT848_PLL_X (1<<7) +#define BT848_PLL_C (1<<6) + +#define BT848_DVSIF 0x0FC + +/* Bt878 register */ + +#define BT878_DEVCTRL 0x40 +#define BT878_EN_TBFX 0x02 +#define BT878_EN_VSFX 0x04 + +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.18/bttvp.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.18/bttvp.h @@ -0,0 +1,413 @@ +/* + + bttv - Bt848 frame grabber driver + + bttv's *private* header file -- nobody other than bttv itself + should ever include this file. + + (c) 2000-2002 Gerd Knorr + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BTTVP_H_ +#define _BTTVP_H_ + +#include +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "bt848.h" +#include "bttv.h" +#include "btcx-risc.h" + +#ifdef __KERNEL__ + +#define FORMAT_FLAGS_DITHER 0x01 +#define FORMAT_FLAGS_PACKED 0x02 +#define FORMAT_FLAGS_PLANAR 0x04 +#define FORMAT_FLAGS_RAW 0x08 +#define FORMAT_FLAGS_CrCb 0x10 + +#define RISC_SLOT_O_VBI 4 +#define RISC_SLOT_O_FIELD 6 +#define RISC_SLOT_E_VBI 10 +#define RISC_SLOT_E_FIELD 12 +#define RISC_SLOT_LOOP 14 + +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO 2 +#define RESOURCE_VBI 4 + +#define RAW_LINES 640 +#define RAW_BPL 1024 + +#define UNSET (-1U) + +#define clamp(x, low, high) min (max (low, x), high) + +/* ---------------------------------------------------------- */ + +struct bttv_tvnorm { + int v4l2_id; + char *name; + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ + u16 totalwidth; + u8 adelay, bdelay, iform; + u32 scaledtwidth; + u16 hdelayx1, hactivex1; + u16 vdelay; + u8 vbipack; + u16 vtotal; + int sram; + /* ITU-R frame line number of the first VBI line we can + capture, of the first and second field. */ + u16 vbistart[2]; +}; +extern const struct bttv_tvnorm bttv_tvnorms[]; + +struct bttv_format { + char *name; + int palette; /* video4linux 1 */ + int fourcc; /* video4linux 2 */ + int btformat; /* BT848_COLOR_FMT_* */ + int btswap; /* BT848_COLOR_CTL_* */ + int depth; /* bit/pixel */ + int flags; + int hshift,vshift; /* for planar modes */ +}; + +/* ---------------------------------------------------------- */ + +struct bttv_geometry { + u8 vtc,crop,comb; + u16 width,hscale,hdelay; + u16 sheight,vscale,vdelay,vtotal; +}; + +struct bttv_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* bttv specific */ + const struct bttv_format *fmt; + int tvnorm; + int btformat; + int btswap; + struct bttv_geometry geo; + struct btcx_riscmem top; + struct btcx_riscmem bottom; +}; + +struct bttv_buffer_set { + struct bttv_buffer *top; /* top field buffer */ + struct bttv_buffer *bottom; /* bottom field buffer */ + unsigned int top_irq; + unsigned int frame_irq; +}; + +struct bttv_overlay { + int tvnorm; + struct v4l2_rect w; + enum v4l2_field field; + struct v4l2_clip *clips; + int nclips; + int setup_ok; +}; + +struct bttv_fh { + struct bttv *btv; + int resources; +#ifdef VIDIOC_G_PRIORITY + enum v4l2_priority prio; +#endif + enum v4l2_buf_type type; + + /* video capture */ + struct videobuf_queue cap; + const struct bttv_format *fmt; + int width; + int height; + + /* current settings */ + const struct bttv_format *ovfmt; + struct bttv_overlay ov; + + /* video overlay */ + struct videobuf_queue vbi; + int lines; +}; + +/* ---------------------------------------------------------- */ +/* bttv-risc.c */ + +/* risc code generators - capture */ +int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int offset, unsigned int bpl, + unsigned int pitch, unsigned int lines); + +/* control dma register + risc main loop */ +void bttv_set_dma(struct bttv *btv, int override); +int bttv_risc_init_main(struct bttv *btv); +int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, + int irqflags); + +/* capture buffer handling */ +int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); +int bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set); +int bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi); +void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, + struct bttv_buffer *buf); + +/* overlay handling */ +int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, + const struct bttv_format *fmt, + struct bttv_buffer *buf); + + +/* ---------------------------------------------------------- */ +/* bttv-vbi.c */ + +void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines); + +extern struct videobuf_queue_ops bttv_vbi_qops; + +/* ---------------------------------------------------------- */ +/* bttv-gpio.c */ + + +extern struct bus_type bttv_sub_bus_type; +int bttv_sub_add_device(struct bttv_core *core, char *name); +int bttv_sub_del_devices(struct bttv_core *core); + + +/* ---------------------------------------------------------- */ +/* bttv-driver.c */ + +/* insmod options */ +extern unsigned int bttv_verbose; +extern unsigned int bttv_debug; +extern unsigned int bttv_gpio; +extern void bttv_gpio_tracking(struct bttv *btv, char *comment); +extern int init_bttv_i2c(struct bttv *btv); +extern int fini_bttv_i2c(struct bttv *btv); + +#define bttv_printk if (bttv_verbose) printk +#define dprintk if (bttv_debug >= 1) printk +#define d2printk if (bttv_debug >= 2) printk + +#define BTTV_MAX_FBUF 0x208000 +#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) +#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BTTV_FREE_IDLE (HZ) /* one second */ + + +struct bttv_pll_info { + unsigned int pll_ifreq; /* PLL input frequency */ + unsigned int pll_ofreq; /* PLL output frequency */ + unsigned int pll_crystal; /* Crystal used for input */ + unsigned int pll_current; /* Currently programmed ofreq */ +}; + +/* for gpio-connected remote control */ +struct bttv_input { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + u32 mask_keycode; + u32 mask_keydown; +}; + +struct bttv_suspend_state { + u32 gpio_enable; + u32 gpio_data; + int disabled; + int loop_irq; + struct bttv_buffer_set video; + struct bttv_buffer *vbi; +}; + +struct bttv { + struct bttv_core c; + + /* pci device config */ + unsigned short id; + unsigned char revision; + unsigned char __iomem *bt848_mmio; /* pointer to mmio */ + + /* card configuration info */ + unsigned int cardid; /* pci subsystem id (bt878 based ones) */ + unsigned int tuner_type; /* tuner chip type */ + unsigned int tda9887_conf; + unsigned int svhs; + struct bttv_pll_info pll; + int triton1; + int gpioirq; + int (*custom_irq)(struct bttv *btv); + + int use_i2c_hw; + + /* old gpio interface */ + wait_queue_head_t gpioq; + int shutdown; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + + /* new gpio interface */ + spinlock_t gpio_lock; + + /* i2c layer */ + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_state, i2c_rc; + int i2c_done; + wait_queue_head_t i2c_queue; + struct i2c_client *i2c_msp34xx_client; + struct i2c_client *i2c_tvaudio_client; + + /* video4linux (1) */ + struct video_device *video_dev; + struct video_device *radio_dev; + struct video_device *vbi_dev; + + /* infrared remote */ + int has_remote; + struct bttv_ir *remote; + + /* locking */ + spinlock_t s_lock; + struct mutex lock; + int resources; + struct mutex reslock; +#ifdef VIDIOC_G_PRIORITY + struct v4l2_prio_state prio; +#endif + + /* video state */ + unsigned int input; + unsigned int audio; + unsigned int mute; + unsigned long freq; + int tvnorm,hue,contrast,bright,saturation; + struct v4l2_framebuffer fbuf; + unsigned int field_count; + + /* various options */ + int opt_combfilter; + int opt_lumafilter; + int opt_automute; + int opt_chroma_agc; + int opt_adc_crush; + int opt_vcr_hack; + int opt_whitecrush_upper; + int opt_whitecrush_lower; + int opt_uv_ratio; + int opt_full_luma_range; + int opt_coring; + + /* radio data/state */ + int has_radio; + int radio_user; + + /* miro/pinnacle + Aimslab VHX + philips matchbox (tea5757 radio tuner) support */ + int has_matchbox; + int mbox_we; + int mbox_data; + int mbox_clk; + int mbox_most; + int mbox_mask; + + /* ISA stuff (Terratec Active Radio Upgrade) */ + int mbox_ior; + int mbox_iow; + int mbox_csel; + + /* risc memory management data + - must acquire s_lock before changing these + - only the irq handler is supported to touch top + bottom + vcurr */ + struct btcx_riscmem main; + struct bttv_buffer *screen; /* overlay */ + struct list_head capture; /* video capture queue */ + struct list_head vcapture; /* vbi capture queue */ + struct bttv_buffer_set curr; /* active buffers */ + struct bttv_buffer *cvbi; /* active vbi buffer */ + int loop_irq; + int new_input; + + unsigned long cap_ctl; + unsigned long dma_on; + struct timer_list timeout; + struct bttv_suspend_state state; + + /* stats */ + unsigned int errors; + unsigned int framedrop; + unsigned int irq_total; + unsigned int irq_me; + + unsigned int users; + struct bttv_fh init; +}; + +/* our devices */ +#define BTTV_MAX 16 +extern unsigned int bttv_num; +extern struct bttv bttvs[BTTV_MAX]; + +/* private ioctls */ +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) +#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) + +#endif + +#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) +#define btread(adr) readl(btv->bt848_mmio+(adr)) + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +#endif /* _BTTVP_H_ */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.18/btcx-risc.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.18/btcx-risc.h @@ -0,0 +1,34 @@ +/* + */ +struct btcx_riscmem { + unsigned int size; + u32 *cpu; + u32 *jmp; + dma_addr_t dma; +}; + +struct btcx_skiplist { + int start; + int end; +}; + +int btcx_riscmem_alloc(struct pci_dev *pci, + struct btcx_riscmem *risc, + unsigned int size); +void btcx_riscmem_free(struct pci_dev *pci, + struct btcx_riscmem *risc); + +int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, + struct v4l2_clip *clips, unsigned int n); +int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, + unsigned int n, int mask); +void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); +void btcx_calc_skips(int line, int width, unsigned int *maxy, + struct btcx_skiplist *skips, unsigned int *nskips, + const struct v4l2_clip *clips, unsigned int nclips); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.18/bttv.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.18/bttv.h @@ -0,0 +1,389 @@ +/* + * + * bttv - Bt848 frame grabber driver + * + * card ID's and external interfaces of the bttv driver + * basically stuff needed by other drivers (i2c, lirc, ...) + * and is supported not to change much over time. + * + * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + * (c) 1999,2000 Gerd Knorr + * + */ + +#ifndef _BTTV_H_ +#define _BTTV_H_ + +#include +#include +#include +#include +#include + +/* ---------------------------------------------------------- */ +/* exported by bttv-cards.c */ + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ASOUND_SKYEYE 0x8d +#define BTTV_BOARD_SABRENT_TVFM 0x8e +#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f +#define BTTV_BOARD_MACHTV_MAGICTV 0x90 + +/* more card-specific defines */ +#define PT2254_L_CHANNEL 0x10 +#define PT2254_R_CHANNEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + +/* digital_mode */ +#define DIGITAL_MODE_VIDEO 1 +#define DIGITAL_MODE_CAMERA 2 + +struct bttv_core { + /* device structs */ + struct pci_dev *pci; + struct i2c_adapter i2c_adap; + struct list_head subs; /* struct bttv_sub_device */ + + /* device config */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int type; /* card type (pointer into tvcards[]) */ + char name[8]; /* dev name */ +}; + +struct bttv; + + +struct bttv_ir { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* Usual gpio signalling */ + + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + struct work_struct work; + struct timer_list timer; + + /* RC5 gpio */ + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + struct timer_list timer_keyup; /* timer_end for key release */ + u32 last_rc5; /* last good rc5 code */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + int active; /* building raw code */ +}; + +struct tvcard +{ + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; + unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO + u32 gpiomask; + u32 muxsel[16]; + u32 gpiomux[4]; /* Tuner, Radio, external, internal */ + u32 gpiomute; /* GPIO mute setting */ + u32 gpiomask2; /* GPIO MUX mask */ + + /* i2c audio flags */ + unsigned int no_msp34xx:1; + unsigned int no_tda9875:1; + unsigned int no_tda7432:1; + unsigned int needs_tvaudio:1; + unsigned int msp34xx_alt:1; + + /* flag: video pci function is unused */ + unsigned int no_video:1; + unsigned int has_dvb:1; + unsigned int has_remote:1; + unsigned int no_gpioirq:1; + + /* other settings */ + unsigned int pll; +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 + + unsigned int tuner_type; + unsigned int tuner_addr; + unsigned int radio_addr; + + unsigned int has_radio; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); +}; + +extern struct tvcard bttv_tvcards[]; + +/* identification / initialization of the card */ +extern void bttv_idcard(struct bttv *btv); +extern void bttv_init_card1(struct bttv *btv); +extern void bttv_init_card2(struct bttv *btv); + +/* card-specific funtions */ +extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); +extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); + +/* extra tweaks for some chipsets */ +extern void bttv_check_chipset(void); +extern int bttv_handle_chipset(struct bttv *btv); + +/* ---------------------------------------------------------- */ +/* exported by bttv-if.c */ + +/* this obsolete -- please use the sysfs-based + interface below for new code */ + +/* returns card type + card ID (for bt878-based ones) + for possible values see lines below beginning with #define BTTV_BOARD_UNKNOWN + returns negative value if error occurred +*/ +extern int bttv_get_cardinfo(unsigned int card, int *type, + unsigned int *cardid); +extern struct pci_dev* bttv_get_pcidev(unsigned int card); + +/* obsolete, use bttv_get_cardinfo instead */ +extern int bttv_get_id(unsigned int card); + +/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: + data | (current_GPOE_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_gpio_enable(unsigned int card, + unsigned long mask, unsigned long data); + +/* fills data with GPDATA register contents + returns negative value if error occurred +*/ +extern int bttv_read_gpio(unsigned int card, unsigned long *data); + +/* sets GPDATA register to new value: + (data & mask) | (current_GPDATA_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_write_gpio(unsigned int card, + unsigned long mask, unsigned long data); + +/* returns pointer to task queue which can be used as parameter to + interruptible_sleep_on + in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated + (wake_up_interruptible) and following call to the function bttv_read_gpio + should return new value of GPDATA, + returns NULL value if error occurred or queue is not available + WARNING: because there is no buffer for GPIO data, one MUST + process data ASAP +*/ +extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); + +/* call i2c clients +*/ +extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); + + + +/* ---------------------------------------------------------- */ +/* sysfs/driver-moded based gpio access interface */ + + +struct bttv_sub_device { + struct device dev; + struct bttv_core *core; + struct list_head list; +}; +#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) + +struct bttv_sub_driver { + struct device_driver drv; + char wanted[BUS_ID_SIZE]; + int (*probe)(struct bttv_sub_device *sub); + void (*remove)(struct bttv_sub_device *sub); +}; +#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) + +int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); +int bttv_sub_unregister(struct bttv_sub_driver *drv); + +/* gpio access functions */ +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); +u32 bttv_gpio_read(struct bttv_core *core); +void bttv_gpio_write(struct bttv_core *core, u32 value); +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); + +#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) +#define gpio_read() bttv_gpio_read(&btv->c) +#define gpio_write(value) bttv_gpio_write(&btv->c, value) +#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) + + +/* ---------------------------------------------------------- */ +/* i2c */ + +extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); +extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both); +extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); + +extern int bttv_input_init(struct bttv *dev); +extern void bttv_input_fini(struct bttv *dev); +extern void bttv_input_irq(struct bttv *dev); + +#endif /* _BTTV_H_ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.18/bt848.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.18/bt848.h @@ -0,0 +1,366 @@ +/* + bt848.h - Bt848 register offsets + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BT848_H_ +#define _BT848_H_ + +#ifndef PCI_VENDOR_ID_BROOKTREE +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#endif +#ifndef PCI_DEVICE_ID_BT848 +#define PCI_DEVICE_ID_BT848 0x350 +#endif +#ifndef PCI_DEVICE_ID_BT849 +#define PCI_DEVICE_ID_BT849 0x351 +#endif +#ifndef PCI_DEVICE_ID_BT878 +#define PCI_DEVICE_ID_BT878 0x36e +#endif +#ifndef PCI_DEVICE_ID_BT879 +#define PCI_DEVICE_ID_BT879 0x36f +#endif + + +/* Brooktree 848 registers */ + +#define BT848_DSTATUS 0x000 +#define BT848_DSTATUS_PRES (1<<7) +#define BT848_DSTATUS_HLOC (1<<6) +#define BT848_DSTATUS_FIELD (1<<5) +#define BT848_DSTATUS_NUML (1<<4) +#define BT848_DSTATUS_CSEL (1<<3) +#define BT848_DSTATUS_PLOCK (1<<2) +#define BT848_DSTATUS_LOF (1<<1) +#define BT848_DSTATUS_COF (1<<0) + +#define BT848_IFORM 0x004 +#define BT848_IFORM_HACTIVE (1<<7) +#define BT848_IFORM_MUXSEL (3<<5) +#define BT848_IFORM_MUX0 (2<<5) +#define BT848_IFORM_MUX1 (3<<5) +#define BT848_IFORM_MUX2 (1<<5) +#define BT848_IFORM_XTSEL (3<<3) +#define BT848_IFORM_XT0 (1<<3) +#define BT848_IFORM_XT1 (2<<3) +#define BT848_IFORM_XTAUTO (3<<3) +#define BT848_IFORM_XTBOTH (3<<3) +#define BT848_IFORM_NTSC 1 +#define BT848_IFORM_NTSC_J 2 +#define BT848_IFORM_PAL_BDGHI 3 +#define BT848_IFORM_PAL_M 4 +#define BT848_IFORM_PAL_N 5 +#define BT848_IFORM_SECAM 6 +#define BT848_IFORM_PAL_NC 7 +#define BT848_IFORM_AUTO 0 +#define BT848_IFORM_NORM 7 + +#define BT848_TDEC 0x008 +#define BT848_TDEC_DEC_FIELD (1<<7) +#define BT848_TDEC_FLDALIGN (1<<6) +#define BT848_TDEC_DEC_RAT (0x1f) + +#define BT848_E_CROP 0x00C +#define BT848_O_CROP 0x08C + +#define BT848_E_VDELAY_LO 0x010 +#define BT848_O_VDELAY_LO 0x090 + +#define BT848_E_VACTIVE_LO 0x014 +#define BT848_O_VACTIVE_LO 0x094 + +#define BT848_E_HDELAY_LO 0x018 +#define BT848_O_HDELAY_LO 0x098 + +#define BT848_E_HACTIVE_LO 0x01C +#define BT848_O_HACTIVE_LO 0x09C + +#define BT848_E_HSCALE_HI 0x020 +#define BT848_O_HSCALE_HI 0x0A0 + +#define BT848_E_HSCALE_LO 0x024 +#define BT848_O_HSCALE_LO 0x0A4 + +#define BT848_BRIGHT 0x028 + +#define BT848_E_CONTROL 0x02C +#define BT848_O_CONTROL 0x0AC +#define BT848_CONTROL_LNOTCH (1<<7) +#define BT848_CONTROL_COMP (1<<6) +#define BT848_CONTROL_LDEC (1<<5) +#define BT848_CONTROL_CBSENSE (1<<4) +#define BT848_CONTROL_CON_MSB (1<<2) +#define BT848_CONTROL_SAT_U_MSB (1<<1) +#define BT848_CONTROL_SAT_V_MSB (1<<0) + +#define BT848_CONTRAST_LO 0x030 +#define BT848_SAT_U_LO 0x034 +#define BT848_SAT_V_LO 0x038 +#define BT848_HUE 0x03C + +#define BT848_E_SCLOOP 0x040 +#define BT848_O_SCLOOP 0x0C0 +#define BT848_SCLOOP_CAGC (1<<6) +#define BT848_SCLOOP_CKILL (1<<5) +#define BT848_SCLOOP_HFILT_AUTO (0<<3) +#define BT848_SCLOOP_HFILT_CIF (1<<3) +#define BT848_SCLOOP_HFILT_QCIF (2<<3) +#define BT848_SCLOOP_HFILT_ICON (3<<3) + +#define BT848_SCLOOP_PEAK (1<<7) +#define BT848_SCLOOP_HFILT_MINP (1<<3) +#define BT848_SCLOOP_HFILT_MEDP (2<<3) +#define BT848_SCLOOP_HFILT_MAXP (3<<3) + + +#define BT848_OFORM 0x048 +#define BT848_OFORM_RANGE (1<<7) +#define BT848_OFORM_CORE0 (0<<5) +#define BT848_OFORM_CORE8 (1<<5) +#define BT848_OFORM_CORE16 (2<<5) +#define BT848_OFORM_CORE32 (3<<5) + +#define BT848_E_VSCALE_HI 0x04C +#define BT848_O_VSCALE_HI 0x0CC +#define BT848_VSCALE_YCOMB (1<<7) +#define BT848_VSCALE_COMB (1<<6) +#define BT848_VSCALE_INT (1<<5) +#define BT848_VSCALE_HI 15 + +#define BT848_E_VSCALE_LO 0x050 +#define BT848_O_VSCALE_LO 0x0D0 +#define BT848_TEST 0x054 +#define BT848_ADELAY 0x060 +#define BT848_BDELAY 0x064 + +#define BT848_ADC 0x068 +#define BT848_ADC_RESERVED (2<<6) +#define BT848_ADC_SYNC_T (1<<5) +#define BT848_ADC_AGC_EN (1<<4) +#define BT848_ADC_CLK_SLEEP (1<<3) +#define BT848_ADC_Y_SLEEP (1<<2) +#define BT848_ADC_C_SLEEP (1<<1) +#define BT848_ADC_CRUSH (1<<0) + +#define BT848_WC_UP 0x044 +#define BT848_WC_DOWN 0x078 + +#define BT848_E_VTC 0x06C +#define BT848_O_VTC 0x0EC +#define BT848_VTC_HSFMT (1<<7) +#define BT848_VTC_VFILT_2TAP 0 +#define BT848_VTC_VFILT_3TAP 1 +#define BT848_VTC_VFILT_4TAP 2 +#define BT848_VTC_VFILT_5TAP 3 + +#define BT848_SRESET 0x07C + +#define BT848_COLOR_FMT 0x0D4 +#define BT848_COLOR_FMT_O_RGB32 (0<<4) +#define BT848_COLOR_FMT_O_RGB24 (1<<4) +#define BT848_COLOR_FMT_O_RGB16 (2<<4) +#define BT848_COLOR_FMT_O_RGB15 (3<<4) +#define BT848_COLOR_FMT_O_YUY2 (4<<4) +#define BT848_COLOR_FMT_O_BtYUV (5<<4) +#define BT848_COLOR_FMT_O_Y8 (6<<4) +#define BT848_COLOR_FMT_O_RGB8 (7<<4) +#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) +#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) +#define BT848_COLOR_FMT_O_RAW (14<<4) +#define BT848_COLOR_FMT_E_RGB32 0 +#define BT848_COLOR_FMT_E_RGB24 1 +#define BT848_COLOR_FMT_E_RGB16 2 +#define BT848_COLOR_FMT_E_RGB15 3 +#define BT848_COLOR_FMT_E_YUY2 4 +#define BT848_COLOR_FMT_E_BtYUV 5 +#define BT848_COLOR_FMT_E_Y8 6 +#define BT848_COLOR_FMT_E_RGB8 7 +#define BT848_COLOR_FMT_E_YCrCb422 8 +#define BT848_COLOR_FMT_E_YCrCb411 9 +#define BT848_COLOR_FMT_E_RAW 14 + +#define BT848_COLOR_FMT_RGB32 0x00 +#define BT848_COLOR_FMT_RGB24 0x11 +#define BT848_COLOR_FMT_RGB16 0x22 +#define BT848_COLOR_FMT_RGB15 0x33 +#define BT848_COLOR_FMT_YUY2 0x44 +#define BT848_COLOR_FMT_BtYUV 0x55 +#define BT848_COLOR_FMT_Y8 0x66 +#define BT848_COLOR_FMT_RGB8 0x77 +#define BT848_COLOR_FMT_YCrCb422 0x88 +#define BT848_COLOR_FMT_YCrCb411 0x99 +#define BT848_COLOR_FMT_RAW 0xee + +#define BT848_VTOTAL_LO 0xB0 +#define BT848_VTOTAL_HI 0xB4 + +#define BT848_COLOR_CTL 0x0D8 +#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) +#define BT848_COLOR_CTL_COLOR_BARS (1<<6) +#define BT848_COLOR_CTL_RGB_DED (1<<5) +#define BT848_COLOR_CTL_GAMMA (1<<4) +#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) +#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) +#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) +#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) + +#define BT848_CAP_CTL 0x0DC +#define BT848_CAP_CTL_DITH_FRAME (1<<4) +#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) +#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) +#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) +#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) + +#define BT848_VBI_PACK_SIZE 0x0E0 + +#define BT848_VBI_PACK_DEL 0x0E4 +#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc +#define BT848_VBI_PACK_DEL_EXT_FRAME 2 +#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 + + +#define BT848_INT_STAT 0x100 +#define BT848_INT_MASK 0x104 + +#define BT848_INT_ETBF (1<<23) + +#define BT848_INT_RISCS (0xf<<28) +#define BT848_INT_RISC_EN (1<<27) +#define BT848_INT_RACK (1<<25) +#define BT848_INT_FIELD (1<<24) +#define BT848_INT_SCERR (1<<19) +#define BT848_INT_OCERR (1<<18) +#define BT848_INT_PABORT (1<<17) +#define BT848_INT_RIPERR (1<<16) +#define BT848_INT_PPERR (1<<15) +#define BT848_INT_FDSR (1<<14) +#define BT848_INT_FTRGT (1<<13) +#define BT848_INT_FBUS (1<<12) +#define BT848_INT_RISCI (1<<11) +#define BT848_INT_GPINT (1<<9) +#define BT848_INT_I2CDONE (1<<8) +#define BT848_INT_VPRES (1<<5) +#define BT848_INT_HLOCK (1<<4) +#define BT848_INT_OFLOW (1<<3) +#define BT848_INT_HSYNC (1<<2) +#define BT848_INT_VSYNC (1<<1) +#define BT848_INT_FMTCHG (1<<0) + + +#define BT848_GPIO_DMA_CTL 0x10C +#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) +#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) +#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) +#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) +#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) +#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) +#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) +#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) +#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) +#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) +#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) +#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) +#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) + +#define BT848_I2C 0x110 +#define BT878_I2C_MODE (1<<7) +#define BT878_I2C_RATE (1<<6) +#define BT878_I2C_NOSTOP (1<<5) +#define BT878_I2C_NOSTART (1<<4) +#define BT848_I2C_DIV (0xf<<4) +#define BT848_I2C_SYNC (1<<3) +#define BT848_I2C_W3B (1<<2) +#define BT848_I2C_SCL (1<<1) +#define BT848_I2C_SDA (1<<0) + +#define BT848_RISC_STRT_ADD 0x114 +#define BT848_GPIO_OUT_EN 0x118 +#define BT848_GPIO_REG_INP 0x11C +#define BT848_RISC_COUNT 0x120 +#define BT848_GPIO_DATA 0x200 + + +/* Bt848 RISC commands */ + +/* only for the SYNC RISC command */ +#define BT848_FIFO_STATUS_FM1 0x06 +#define BT848_FIFO_STATUS_FM3 0x0e +#define BT848_FIFO_STATUS_SOL 0x02 +#define BT848_FIFO_STATUS_EOL4 0x01 +#define BT848_FIFO_STATUS_EOL3 0x0d +#define BT848_FIFO_STATUS_EOL2 0x09 +#define BT848_FIFO_STATUS_EOL1 0x05 +#define BT848_FIFO_STATUS_VRE 0x04 +#define BT848_FIFO_STATUS_VRO 0x0c +#define BT848_FIFO_STATUS_PXV 0x00 + +#define BT848_RISC_RESYNC (1<<15) + +/* WRITE and SKIP */ +/* disable which bytes of each DWORD */ +#define BT848_RISC_BYTE0 (1U<<12) +#define BT848_RISC_BYTE1 (1U<<13) +#define BT848_RISC_BYTE2 (1U<<14) +#define BT848_RISC_BYTE3 (1U<<15) +#define BT848_RISC_BYTE_ALL (0x0fU<<12) +#define BT848_RISC_BYTE_NONE 0 +/* cause RISCI */ +#define BT848_RISC_IRQ (1U<<24) +/* RISC command is last one in this line */ +#define BT848_RISC_EOL (1U<<26) +/* RISC command is first one in this line */ +#define BT848_RISC_SOL (1U<<27) + +#define BT848_RISC_WRITE (0x01U<<28) +#define BT848_RISC_SKIP (0x02U<<28) +#define BT848_RISC_WRITEC (0x05U<<28) +#define BT848_RISC_JUMP (0x07U<<28) +#define BT848_RISC_SYNC (0x08U<<28) + +#define BT848_RISC_WRITE123 (0x09U<<28) +#define BT848_RISC_SKIP123 (0x0aU<<28) +#define BT848_RISC_WRITE1S23 (0x0bU<<28) + + +/* Bt848A and higher only !! */ +#define BT848_TGLB 0x080 +#define BT848_TGCTRL 0x084 +#define BT848_FCAP 0x0E8 +#define BT848_PLL_F_LO 0x0F0 +#define BT848_PLL_F_HI 0x0F4 + +#define BT848_PLL_XCI 0x0F8 +#define BT848_PLL_X (1<<7) +#define BT848_PLL_C (1<<6) + +#define BT848_DVSIF 0x0FC + +/* Bt878 register */ + +#define BT878_DEVCTRL 0x40 +#define BT878_EN_TBFX 0x02 +#define BT878_EN_VSFX 0x04 + +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.22/bttvp.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.22/bttvp.h @@ -0,0 +1,480 @@ +/* + + bttv - Bt848 frame grabber driver + + bttv's *private* header file -- nobody other than bttv itself + should ever include this file. + + (c) 2000-2002 Gerd Knorr + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BTTVP_H_ +#define _BTTVP_H_ + +#include +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,17) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "bt848.h" +#include "bttv.h" +#include "btcx-risc.h" + +#ifdef __KERNEL__ + +#define FORMAT_FLAGS_DITHER 0x01 +#define FORMAT_FLAGS_PACKED 0x02 +#define FORMAT_FLAGS_PLANAR 0x04 +#define FORMAT_FLAGS_RAW 0x08 +#define FORMAT_FLAGS_CrCb 0x10 + +#define RISC_SLOT_O_VBI 4 +#define RISC_SLOT_O_FIELD 6 +#define RISC_SLOT_E_VBI 10 +#define RISC_SLOT_E_FIELD 12 +#define RISC_SLOT_LOOP 14 + +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO_STREAM 2 +#define RESOURCE_VBI 4 +#define RESOURCE_VIDEO_READ 8 + +#define RAW_LINES 640 +#define RAW_BPL 1024 + +#define UNSET (-1U) + +/* Min. value in VDELAY register. */ +#define MIN_VDELAY 2 +/* Even to get Cb first, odd for Cr. */ +#define MAX_HDELAY (0x3FF & -2) +/* Limits scaled width, which must be a multiple of 4. */ +#define MAX_HACTIVE (0x3FF & -4) + +#define clamp(x, low, high) min (max (low, x), high) + +/* ---------------------------------------------------------- */ + +struct bttv_tvnorm { + int v4l2_id; + char *name; + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ + u16 totalwidth; + u8 adelay, bdelay, iform; + u32 scaledtwidth; + u16 hdelayx1, hactivex1; + u16 vdelay; + u8 vbipack; + u16 vtotal; + int sram; + /* ITU-R frame line number of the first VBI line we can + capture, of the first and second field. The last possible line + is determined by cropcap.bounds. */ + u16 vbistart[2]; + /* Horizontally this counts fCLKx1 samples following the leading + edge of the horizontal sync pulse, vertically ITU-R frame line + numbers of the first field times two (2, 4, 6, ... 524 or 624). */ + struct v4l2_cropcap cropcap; +}; +extern const struct bttv_tvnorm bttv_tvnorms[]; + +struct bttv_format { + char *name; + int palette; /* video4linux 1 */ + int fourcc; /* video4linux 2 */ + int btformat; /* BT848_COLOR_FMT_* */ + int btswap; /* BT848_COLOR_CTL_* */ + int depth; /* bit/pixel */ + int flags; + int hshift,vshift; /* for planar modes */ +}; + +/* ---------------------------------------------------------- */ + +struct bttv_geometry { + u8 vtc,crop,comb; + u16 width,hscale,hdelay; + u16 sheight,vscale,vdelay,vtotal; +}; + +struct bttv_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* bttv specific */ + const struct bttv_format *fmt; + int tvnorm; + int btformat; + int btswap; + struct bttv_geometry geo; + struct btcx_riscmem top; + struct btcx_riscmem bottom; + struct v4l2_rect crop; + unsigned int vbi_skip[2]; + unsigned int vbi_count[2]; +}; + +struct bttv_buffer_set { + struct bttv_buffer *top; /* top field buffer */ + struct bttv_buffer *bottom; /* bottom field buffer */ + unsigned int top_irq; + unsigned int frame_irq; +}; + +struct bttv_overlay { + int tvnorm; + struct v4l2_rect w; + enum v4l2_field field; + struct v4l2_clip *clips; + int nclips; + int setup_ok; +}; + +struct bttv_vbi_fmt { + struct v4l2_vbi_format fmt; + + /* fmt.start[] and count[] refer to this video standard. */ + const struct bttv_tvnorm *tvnorm; + + /* Earliest possible start of video capturing with this + v4l2_vbi_format, in struct bttv_crop.rect units. */ + __s32 end; +}; + +/* bttv-vbi.c */ +void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm); + +struct bttv_crop { + /* A cropping rectangle in struct bttv_tvnorm.cropcap units. */ + struct v4l2_rect rect; + + /* Scaled image size limits with this crop rect. Divide + max_height, but not min_height, by two when capturing + single fields. See also bttv_crop_reset() and + bttv_crop_adjust() in bttv-driver.c. */ + __s32 min_scaled_width; + __s32 min_scaled_height; + __s32 max_scaled_width; + __s32 max_scaled_height; +}; + +struct bttv_fh { + struct bttv *btv; + int resources; +#ifdef VIDIOC_G_PRIORITY + enum v4l2_priority prio; +#endif + enum v4l2_buf_type type; + + /* video capture */ + struct videobuf_queue cap; + const struct bttv_format *fmt; + int width; + int height; + + /* video overlay */ + const struct bttv_format *ovfmt; + struct bttv_overlay ov; + + /* Application called VIDIOC_S_CROP. */ + int do_crop; + + /* vbi capture */ + struct videobuf_queue vbi; + /* Current VBI capture window as seen through this fh (cannot + be global for compatibility with earlier drivers). Protected + by struct bttv.lock and struct bttv_fh.vbi.lock. */ + struct bttv_vbi_fmt vbi_fmt; +}; + +/* ---------------------------------------------------------- */ +/* bttv-risc.c */ + +/* risc code generators - capture */ +int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int offset, unsigned int bpl, + unsigned int pitch, unsigned int skip_lines, + unsigned int store_lines); + +/* control dma register + risc main loop */ +void bttv_set_dma(struct bttv *btv, int override); +int bttv_risc_init_main(struct bttv *btv); +int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, + int irqflags); + +/* capture buffer handling */ +int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); +int bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set); +int bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi); +void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, + struct bttv_buffer *buf); + +/* overlay handling */ +int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, + const struct bttv_format *fmt, + struct bttv_buffer *buf); + + +/* ---------------------------------------------------------- */ +/* bttv-vbi.c */ + +int bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); +void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); +int bttv_vbi_set_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); + +extern struct videobuf_queue_ops bttv_vbi_qops; + +/* ---------------------------------------------------------- */ +/* bttv-gpio.c */ + + +extern struct bus_type bttv_sub_bus_type; +int bttv_sub_add_device(struct bttv_core *core, char *name); +int bttv_sub_del_devices(struct bttv_core *core); + + +/* ---------------------------------------------------------- */ +/* bttv-driver.c */ + +/* insmod options */ +extern unsigned int bttv_verbose; +extern unsigned int bttv_debug; +extern unsigned int bttv_gpio; +extern void bttv_gpio_tracking(struct bttv *btv, char *comment); +extern int init_bttv_i2c(struct bttv *btv); +extern int fini_bttv_i2c(struct bttv *btv); + +#define bttv_printk if (bttv_verbose) printk +#define dprintk if (bttv_debug >= 1) printk +#define d2printk if (bttv_debug >= 2) printk + +#define BTTV_MAX_FBUF 0x208000 +#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BTTV_FREE_IDLE (HZ) /* one second */ + + +struct bttv_pll_info { + unsigned int pll_ifreq; /* PLL input frequency */ + unsigned int pll_ofreq; /* PLL output frequency */ + unsigned int pll_crystal; /* Crystal used for input */ + unsigned int pll_current; /* Currently programmed ofreq */ +}; + +/* for gpio-connected remote control */ +struct bttv_input { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + u32 mask_keycode; + u32 mask_keydown; +}; + +struct bttv_suspend_state { + u32 gpio_enable; + u32 gpio_data; + int disabled; + int loop_irq; + struct bttv_buffer_set video; + struct bttv_buffer *vbi; +}; + +struct bttv { + struct bttv_core c; + + /* pci device config */ + unsigned short id; + unsigned char revision; + unsigned char __iomem *bt848_mmio; /* pointer to mmio */ + + /* card configuration info */ + unsigned int cardid; /* pci subsystem id (bt878 based ones) */ + unsigned int tuner_type; /* tuner chip type */ + unsigned int tda9887_conf; + unsigned int svhs; + struct bttv_pll_info pll; + int triton1; + int gpioirq; + int (*custom_irq)(struct bttv *btv); + + int use_i2c_hw; + + /* old gpio interface */ + wait_queue_head_t gpioq; + int shutdown; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + + /* new gpio interface */ + spinlock_t gpio_lock; + + /* i2c layer */ + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_state, i2c_rc; + int i2c_done; + wait_queue_head_t i2c_queue; + struct i2c_client *i2c_msp34xx_client; + struct i2c_client *i2c_tvaudio_client; + + /* video4linux (1) */ + struct video_device *video_dev; + struct video_device *radio_dev; + struct video_device *vbi_dev; + + /* infrared remote */ + int has_remote; + struct card_ir *remote; + + /* locking */ + spinlock_t s_lock; + struct mutex lock; + int resources; +#ifdef VIDIOC_G_PRIORITY + struct v4l2_prio_state prio; +#endif + + /* video state */ + unsigned int input; + unsigned int audio; + unsigned int mute; + unsigned long freq; + int tvnorm,hue,contrast,bright,saturation; + struct v4l2_framebuffer fbuf; + unsigned int field_count; + + /* various options */ + int opt_combfilter; + int opt_lumafilter; + int opt_automute; + int opt_chroma_agc; + int opt_adc_crush; + int opt_vcr_hack; + int opt_whitecrush_upper; + int opt_whitecrush_lower; + int opt_uv_ratio; + int opt_full_luma_range; + int opt_coring; + + /* radio data/state */ + int has_radio; + int radio_user; + + /* miro/pinnacle + Aimslab VHX + philips matchbox (tea5757 radio tuner) support */ + int has_matchbox; + int mbox_we; + int mbox_data; + int mbox_clk; + int mbox_most; + int mbox_mask; + + /* ISA stuff (Terratec Active Radio Upgrade) */ + int mbox_ior; + int mbox_iow; + int mbox_csel; + + /* risc memory management data + - must acquire s_lock before changing these + - only the irq handler is supported to touch top + bottom + vcurr */ + struct btcx_riscmem main; + struct bttv_buffer *screen; /* overlay */ + struct list_head capture; /* video capture queue */ + struct list_head vcapture; /* vbi capture queue */ + struct bttv_buffer_set curr; /* active buffers */ + struct bttv_buffer *cvbi; /* active vbi buffer */ + int loop_irq; + int new_input; + + unsigned long cap_ctl; + unsigned long dma_on; + struct timer_list timeout; + struct bttv_suspend_state state; + + /* stats */ + unsigned int errors; + unsigned int framedrop; + unsigned int irq_total; + unsigned int irq_me; + + unsigned int users; + struct bttv_fh init; + + /* used to make dvb-bt8xx autoloadable */ + struct work_struct request_module_wk; + + /* Default (0) and current (1) video capturing and overlay + cropping parameters in bttv_tvnorm.cropcap units. Protected + by bttv.lock. */ + struct bttv_crop crop[2]; + + /* Earliest possible start of video capturing in + bttv_tvnorm.cropcap line units. Set by check_alloc_btres() + and free_btres(). Protected by bttv.lock. */ + __s32 vbi_end; + + /* Latest possible end of VBI capturing (= crop[x].rect.top when + VIDEO_RESOURCES are locked). Set by check_alloc_btres() + and free_btres(). Protected by bttv.lock. */ + __s32 crop_start; +}; + +/* our devices */ +#define BTTV_MAX 16 +extern unsigned int bttv_num; +extern struct bttv bttvs[BTTV_MAX]; + +/* private ioctls */ +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) +#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) + +#endif + +#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) +#define btread(adr) readl(btv->bt848_mmio+(adr)) + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +#endif /* _BTTVP_H_ */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.22/btcx-risc.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.22/btcx-risc.h @@ -0,0 +1,34 @@ +/* + */ +struct btcx_riscmem { + unsigned int size; + u32 *cpu; + u32 *jmp; + dma_addr_t dma; +}; + +struct btcx_skiplist { + int start; + int end; +}; + +int btcx_riscmem_alloc(struct pci_dev *pci, + struct btcx_riscmem *risc, + unsigned int size); +void btcx_riscmem_free(struct pci_dev *pci, + struct btcx_riscmem *risc); + +int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, + struct v4l2_clip *clips, unsigned int n); +int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, + unsigned int n, int mask); +void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); +void btcx_calc_skips(int line, int width, unsigned int *maxy, + struct btcx_skiplist *skips, unsigned int *nskips, + const struct v4l2_clip *clips, unsigned int nclips); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.22/bttv.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.22/bttv.h @@ -0,0 +1,341 @@ +/* + * + * bttv - Bt848 frame grabber driver + * + * card ID's and external interfaces of the bttv driver + * basically stuff needed by other drivers (i2c, lirc, ...) + * and is supported not to change much over time. + * + * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + * (c) 1999,2000 Gerd Knorr + * + */ + +#ifndef _BTTV_H_ +#define _BTTV_H_ + +#include +#include +#include +#include +#include + +/* ---------------------------------------------------------- */ +/* exported by bttv-cards.c */ + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ASOUND_SKYEYE 0x8d +#define BTTV_BOARD_SABRENT_TVFM 0x8e +#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f +#define BTTV_BOARD_MACHTV_MAGICTV 0x90 +#define BTTV_BOARD_SSAI_SECURITY 0x91 +#define BTTV_BOARD_SSAI_ULTRASOUND 0x92 + +/* more card-specific defines */ +#define PT2254_L_CHANNEL 0x10 +#define PT2254_R_CHANNEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + +/* digital_mode */ +#define DIGITAL_MODE_VIDEO 1 +#define DIGITAL_MODE_CAMERA 2 + +struct bttv_core { + /* device structs */ + struct pci_dev *pci; + struct i2c_adapter i2c_adap; + struct list_head subs; /* struct bttv_sub_device */ + + /* device config */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int type; /* card type (pointer into tvcards[]) */ + char name[8]; /* dev name */ +}; + +struct bttv; + + +struct tvcard +{ + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; + unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO + u32 gpiomask; + u32 muxsel[16]; + u32 gpiomux[4]; /* Tuner, Radio, external, internal */ + u32 gpiomute; /* GPIO mute setting */ + u32 gpiomask2; /* GPIO MUX mask */ + + /* i2c audio flags */ + unsigned int no_msp34xx:1; + unsigned int no_tda9875:1; + unsigned int no_tda7432:1; + unsigned int needs_tvaudio:1; + unsigned int msp34xx_alt:1; + + /* flag: video pci function is unused */ + unsigned int no_video:1; + unsigned int has_dvb:1; + unsigned int has_remote:1; + unsigned int no_gpioirq:1; + + /* other settings */ + unsigned int pll; +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 + + unsigned int tuner_type; + unsigned int tuner_addr; + unsigned int radio_addr; + + unsigned int has_radio; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); +}; + +extern struct tvcard bttv_tvcards[]; + +/* identification / initialization of the card */ +extern void bttv_idcard(struct bttv *btv); +extern void bttv_init_card1(struct bttv *btv); +extern void bttv_init_card2(struct bttv *btv); + +/* card-specific funtions */ +extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); +extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); + +/* extra tweaks for some chipsets */ +extern void bttv_check_chipset(void); +extern int bttv_handle_chipset(struct bttv *btv); + +/* ---------------------------------------------------------- */ +/* exported by bttv-if.c */ + +/* this obsolete -- please use the sysfs-based + interface below for new code */ + +extern struct pci_dev* bttv_get_pcidev(unsigned int card); + +/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: + data | (current_GPOE_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_gpio_enable(unsigned int card, + unsigned long mask, unsigned long data); + +/* fills data with GPDATA register contents + returns negative value if error occurred +*/ +extern int bttv_read_gpio(unsigned int card, unsigned long *data); + +/* sets GPDATA register to new value: + (data & mask) | (current_GPDATA_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_write_gpio(unsigned int card, + unsigned long mask, unsigned long data); + + + + +/* ---------------------------------------------------------- */ +/* sysfs/driver-moded based gpio access interface */ + + +struct bttv_sub_device { + struct device dev; + struct bttv_core *core; + struct list_head list; +}; +#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) + +struct bttv_sub_driver { + struct device_driver drv; + char wanted[BUS_ID_SIZE]; + int (*probe)(struct bttv_sub_device *sub); + void (*remove)(struct bttv_sub_device *sub); +}; +#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) + +int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); +int bttv_sub_unregister(struct bttv_sub_driver *drv); + +/* gpio access functions */ +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); +u32 bttv_gpio_read(struct bttv_core *core); +void bttv_gpio_write(struct bttv_core *core, u32 value); +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); + +#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) +#define gpio_read() bttv_gpio_read(&btv->c) +#define gpio_write(value) bttv_gpio_write(&btv->c, value) +#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) + + +/* ---------------------------------------------------------- */ +/* i2c */ + +extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); +extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both); +extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); + +extern int bttv_input_init(struct bttv *dev); +extern void bttv_input_fini(struct bttv *dev); +extern void bttv_input_irq(struct bttv *dev); + +#endif /* _BTTV_H_ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.22/bt848.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.22/bt848.h @@ -0,0 +1,366 @@ +/* + bt848.h - Bt848 register offsets + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BT848_H_ +#define _BT848_H_ + +#ifndef PCI_VENDOR_ID_BROOKTREE +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#endif +#ifndef PCI_DEVICE_ID_BT848 +#define PCI_DEVICE_ID_BT848 0x350 +#endif +#ifndef PCI_DEVICE_ID_BT849 +#define PCI_DEVICE_ID_BT849 0x351 +#endif +#ifndef PCI_DEVICE_ID_BT878 +#define PCI_DEVICE_ID_BT878 0x36e +#endif +#ifndef PCI_DEVICE_ID_BT879 +#define PCI_DEVICE_ID_BT879 0x36f +#endif + + +/* Brooktree 848 registers */ + +#define BT848_DSTATUS 0x000 +#define BT848_DSTATUS_PRES (1<<7) +#define BT848_DSTATUS_HLOC (1<<6) +#define BT848_DSTATUS_FIELD (1<<5) +#define BT848_DSTATUS_NUML (1<<4) +#define BT848_DSTATUS_CSEL (1<<3) +#define BT848_DSTATUS_PLOCK (1<<2) +#define BT848_DSTATUS_LOF (1<<1) +#define BT848_DSTATUS_COF (1<<0) + +#define BT848_IFORM 0x004 +#define BT848_IFORM_HACTIVE (1<<7) +#define BT848_IFORM_MUXSEL (3<<5) +#define BT848_IFORM_MUX0 (2<<5) +#define BT848_IFORM_MUX1 (3<<5) +#define BT848_IFORM_MUX2 (1<<5) +#define BT848_IFORM_XTSEL (3<<3) +#define BT848_IFORM_XT0 (1<<3) +#define BT848_IFORM_XT1 (2<<3) +#define BT848_IFORM_XTAUTO (3<<3) +#define BT848_IFORM_XTBOTH (3<<3) +#define BT848_IFORM_NTSC 1 +#define BT848_IFORM_NTSC_J 2 +#define BT848_IFORM_PAL_BDGHI 3 +#define BT848_IFORM_PAL_M 4 +#define BT848_IFORM_PAL_N 5 +#define BT848_IFORM_SECAM 6 +#define BT848_IFORM_PAL_NC 7 +#define BT848_IFORM_AUTO 0 +#define BT848_IFORM_NORM 7 + +#define BT848_TDEC 0x008 +#define BT848_TDEC_DEC_FIELD (1<<7) +#define BT848_TDEC_FLDALIGN (1<<6) +#define BT848_TDEC_DEC_RAT (0x1f) + +#define BT848_E_CROP 0x00C +#define BT848_O_CROP 0x08C + +#define BT848_E_VDELAY_LO 0x010 +#define BT848_O_VDELAY_LO 0x090 + +#define BT848_E_VACTIVE_LO 0x014 +#define BT848_O_VACTIVE_LO 0x094 + +#define BT848_E_HDELAY_LO 0x018 +#define BT848_O_HDELAY_LO 0x098 + +#define BT848_E_HACTIVE_LO 0x01C +#define BT848_O_HACTIVE_LO 0x09C + +#define BT848_E_HSCALE_HI 0x020 +#define BT848_O_HSCALE_HI 0x0A0 + +#define BT848_E_HSCALE_LO 0x024 +#define BT848_O_HSCALE_LO 0x0A4 + +#define BT848_BRIGHT 0x028 + +#define BT848_E_CONTROL 0x02C +#define BT848_O_CONTROL 0x0AC +#define BT848_CONTROL_LNOTCH (1<<7) +#define BT848_CONTROL_COMP (1<<6) +#define BT848_CONTROL_LDEC (1<<5) +#define BT848_CONTROL_CBSENSE (1<<4) +#define BT848_CONTROL_CON_MSB (1<<2) +#define BT848_CONTROL_SAT_U_MSB (1<<1) +#define BT848_CONTROL_SAT_V_MSB (1<<0) + +#define BT848_CONTRAST_LO 0x030 +#define BT848_SAT_U_LO 0x034 +#define BT848_SAT_V_LO 0x038 +#define BT848_HUE 0x03C + +#define BT848_E_SCLOOP 0x040 +#define BT848_O_SCLOOP 0x0C0 +#define BT848_SCLOOP_CAGC (1<<6) +#define BT848_SCLOOP_CKILL (1<<5) +#define BT848_SCLOOP_HFILT_AUTO (0<<3) +#define BT848_SCLOOP_HFILT_CIF (1<<3) +#define BT848_SCLOOP_HFILT_QCIF (2<<3) +#define BT848_SCLOOP_HFILT_ICON (3<<3) + +#define BT848_SCLOOP_PEAK (1<<7) +#define BT848_SCLOOP_HFILT_MINP (1<<3) +#define BT848_SCLOOP_HFILT_MEDP (2<<3) +#define BT848_SCLOOP_HFILT_MAXP (3<<3) + + +#define BT848_OFORM 0x048 +#define BT848_OFORM_RANGE (1<<7) +#define BT848_OFORM_CORE0 (0<<5) +#define BT848_OFORM_CORE8 (1<<5) +#define BT848_OFORM_CORE16 (2<<5) +#define BT848_OFORM_CORE32 (3<<5) + +#define BT848_E_VSCALE_HI 0x04C +#define BT848_O_VSCALE_HI 0x0CC +#define BT848_VSCALE_YCOMB (1<<7) +#define BT848_VSCALE_COMB (1<<6) +#define BT848_VSCALE_INT (1<<5) +#define BT848_VSCALE_HI 15 + +#define BT848_E_VSCALE_LO 0x050 +#define BT848_O_VSCALE_LO 0x0D0 +#define BT848_TEST 0x054 +#define BT848_ADELAY 0x060 +#define BT848_BDELAY 0x064 + +#define BT848_ADC 0x068 +#define BT848_ADC_RESERVED (2<<6) +#define BT848_ADC_SYNC_T (1<<5) +#define BT848_ADC_AGC_EN (1<<4) +#define BT848_ADC_CLK_SLEEP (1<<3) +#define BT848_ADC_Y_SLEEP (1<<2) +#define BT848_ADC_C_SLEEP (1<<1) +#define BT848_ADC_CRUSH (1<<0) + +#define BT848_WC_UP 0x044 +#define BT848_WC_DOWN 0x078 + +#define BT848_E_VTC 0x06C +#define BT848_O_VTC 0x0EC +#define BT848_VTC_HSFMT (1<<7) +#define BT848_VTC_VFILT_2TAP 0 +#define BT848_VTC_VFILT_3TAP 1 +#define BT848_VTC_VFILT_4TAP 2 +#define BT848_VTC_VFILT_5TAP 3 + +#define BT848_SRESET 0x07C + +#define BT848_COLOR_FMT 0x0D4 +#define BT848_COLOR_FMT_O_RGB32 (0<<4) +#define BT848_COLOR_FMT_O_RGB24 (1<<4) +#define BT848_COLOR_FMT_O_RGB16 (2<<4) +#define BT848_COLOR_FMT_O_RGB15 (3<<4) +#define BT848_COLOR_FMT_O_YUY2 (4<<4) +#define BT848_COLOR_FMT_O_BtYUV (5<<4) +#define BT848_COLOR_FMT_O_Y8 (6<<4) +#define BT848_COLOR_FMT_O_RGB8 (7<<4) +#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) +#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) +#define BT848_COLOR_FMT_O_RAW (14<<4) +#define BT848_COLOR_FMT_E_RGB32 0 +#define BT848_COLOR_FMT_E_RGB24 1 +#define BT848_COLOR_FMT_E_RGB16 2 +#define BT848_COLOR_FMT_E_RGB15 3 +#define BT848_COLOR_FMT_E_YUY2 4 +#define BT848_COLOR_FMT_E_BtYUV 5 +#define BT848_COLOR_FMT_E_Y8 6 +#define BT848_COLOR_FMT_E_RGB8 7 +#define BT848_COLOR_FMT_E_YCrCb422 8 +#define BT848_COLOR_FMT_E_YCrCb411 9 +#define BT848_COLOR_FMT_E_RAW 14 + +#define BT848_COLOR_FMT_RGB32 0x00 +#define BT848_COLOR_FMT_RGB24 0x11 +#define BT848_COLOR_FMT_RGB16 0x22 +#define BT848_COLOR_FMT_RGB15 0x33 +#define BT848_COLOR_FMT_YUY2 0x44 +#define BT848_COLOR_FMT_BtYUV 0x55 +#define BT848_COLOR_FMT_Y8 0x66 +#define BT848_COLOR_FMT_RGB8 0x77 +#define BT848_COLOR_FMT_YCrCb422 0x88 +#define BT848_COLOR_FMT_YCrCb411 0x99 +#define BT848_COLOR_FMT_RAW 0xee + +#define BT848_VTOTAL_LO 0xB0 +#define BT848_VTOTAL_HI 0xB4 + +#define BT848_COLOR_CTL 0x0D8 +#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) +#define BT848_COLOR_CTL_COLOR_BARS (1<<6) +#define BT848_COLOR_CTL_RGB_DED (1<<5) +#define BT848_COLOR_CTL_GAMMA (1<<4) +#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) +#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) +#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) +#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) + +#define BT848_CAP_CTL 0x0DC +#define BT848_CAP_CTL_DITH_FRAME (1<<4) +#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) +#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) +#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) +#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) + +#define BT848_VBI_PACK_SIZE 0x0E0 + +#define BT848_VBI_PACK_DEL 0x0E4 +#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc +#define BT848_VBI_PACK_DEL_EXT_FRAME 2 +#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 + + +#define BT848_INT_STAT 0x100 +#define BT848_INT_MASK 0x104 + +#define BT848_INT_ETBF (1<<23) + +#define BT848_INT_RISCS (0xf<<28) +#define BT848_INT_RISC_EN (1<<27) +#define BT848_INT_RACK (1<<25) +#define BT848_INT_FIELD (1<<24) +#define BT848_INT_SCERR (1<<19) +#define BT848_INT_OCERR (1<<18) +#define BT848_INT_PABORT (1<<17) +#define BT848_INT_RIPERR (1<<16) +#define BT848_INT_PPERR (1<<15) +#define BT848_INT_FDSR (1<<14) +#define BT848_INT_FTRGT (1<<13) +#define BT848_INT_FBUS (1<<12) +#define BT848_INT_RISCI (1<<11) +#define BT848_INT_GPINT (1<<9) +#define BT848_INT_I2CDONE (1<<8) +#define BT848_INT_VPRES (1<<5) +#define BT848_INT_HLOCK (1<<4) +#define BT848_INT_OFLOW (1<<3) +#define BT848_INT_HSYNC (1<<2) +#define BT848_INT_VSYNC (1<<1) +#define BT848_INT_FMTCHG (1<<0) + + +#define BT848_GPIO_DMA_CTL 0x10C +#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) +#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) +#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) +#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) +#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) +#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) +#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) +#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) +#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) +#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) +#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) +#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) +#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) + +#define BT848_I2C 0x110 +#define BT878_I2C_MODE (1<<7) +#define BT878_I2C_RATE (1<<6) +#define BT878_I2C_NOSTOP (1<<5) +#define BT878_I2C_NOSTART (1<<4) +#define BT848_I2C_DIV (0xf<<4) +#define BT848_I2C_SYNC (1<<3) +#define BT848_I2C_W3B (1<<2) +#define BT848_I2C_SCL (1<<1) +#define BT848_I2C_SDA (1<<0) + +#define BT848_RISC_STRT_ADD 0x114 +#define BT848_GPIO_OUT_EN 0x118 +#define BT848_GPIO_REG_INP 0x11C +#define BT848_RISC_COUNT 0x120 +#define BT848_GPIO_DATA 0x200 + + +/* Bt848 RISC commands */ + +/* only for the SYNC RISC command */ +#define BT848_FIFO_STATUS_FM1 0x06 +#define BT848_FIFO_STATUS_FM3 0x0e +#define BT848_FIFO_STATUS_SOL 0x02 +#define BT848_FIFO_STATUS_EOL4 0x01 +#define BT848_FIFO_STATUS_EOL3 0x0d +#define BT848_FIFO_STATUS_EOL2 0x09 +#define BT848_FIFO_STATUS_EOL1 0x05 +#define BT848_FIFO_STATUS_VRE 0x04 +#define BT848_FIFO_STATUS_VRO 0x0c +#define BT848_FIFO_STATUS_PXV 0x00 + +#define BT848_RISC_RESYNC (1<<15) + +/* WRITE and SKIP */ +/* disable which bytes of each DWORD */ +#define BT848_RISC_BYTE0 (1U<<12) +#define BT848_RISC_BYTE1 (1U<<13) +#define BT848_RISC_BYTE2 (1U<<14) +#define BT848_RISC_BYTE3 (1U<<15) +#define BT848_RISC_BYTE_ALL (0x0fU<<12) +#define BT848_RISC_BYTE_NONE 0 +/* cause RISCI */ +#define BT848_RISC_IRQ (1U<<24) +/* RISC command is last one in this line */ +#define BT848_RISC_EOL (1U<<26) +/* RISC command is first one in this line */ +#define BT848_RISC_SOL (1U<<27) + +#define BT848_RISC_WRITE (0x01U<<28) +#define BT848_RISC_SKIP (0x02U<<28) +#define BT848_RISC_WRITEC (0x05U<<28) +#define BT848_RISC_JUMP (0x07U<<28) +#define BT848_RISC_SYNC (0x08U<<28) + +#define BT848_RISC_WRITE123 (0x09U<<28) +#define BT848_RISC_SKIP123 (0x0aU<<28) +#define BT848_RISC_WRITE1S23 (0x0bU<<28) + + +/* Bt848A and higher only !! */ +#define BT848_TGLB 0x080 +#define BT848_TGCTRL 0x084 +#define BT848_FCAP 0x0E8 +#define BT848_PLL_F_LO 0x0F0 +#define BT848_PLL_F_HI 0x0F4 + +#define BT848_PLL_XCI 0x0F8 +#define BT848_PLL_X (1<<7) +#define BT848_PLL_C (1<<6) + +#define BT848_DVSIF 0x0FC + +/* Bt878 register */ + +#define BT878_DEVCTRL 0x40 +#define BT878_EN_TBFX 0x02 +#define BT878_EN_VSFX 0x04 + +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.16/bttvp.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.16/bttvp.h @@ -0,0 +1,410 @@ +/* + + bttv - Bt848 frame grabber driver + + bttv's *private* header file -- nobody other than bttv itself + should ever include this file. + + (c) 2000-2002 Gerd Knorr + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BTTVP_H_ +#define _BTTVP_H_ + +#include +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include "bt848.h" +#include "bttv.h" +#include "btcx-risc.h" + +#ifdef __KERNEL__ + +#define FORMAT_FLAGS_DITHER 0x01 +#define FORMAT_FLAGS_PACKED 0x02 +#define FORMAT_FLAGS_PLANAR 0x04 +#define FORMAT_FLAGS_RAW 0x08 +#define FORMAT_FLAGS_CrCb 0x10 + +#define RISC_SLOT_O_VBI 4 +#define RISC_SLOT_O_FIELD 6 +#define RISC_SLOT_E_VBI 10 +#define RISC_SLOT_E_FIELD 12 +#define RISC_SLOT_LOOP 14 + +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO 2 +#define RESOURCE_VBI 4 + +#define RAW_LINES 640 +#define RAW_BPL 1024 + +#define UNSET (-1U) + +#define clamp(x, low, high) min (max (low, x), high) + +/* ---------------------------------------------------------- */ + +struct bttv_tvnorm { + int v4l2_id; + char *name; + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ + u16 totalwidth; + u8 adelay, bdelay, iform; + u32 scaledtwidth; + u16 hdelayx1, hactivex1; + u16 vdelay; + u8 vbipack; + u16 vtotal; + int sram; + /* ITU-R frame line number of the first VBI line we can + capture, of the first and second field. */ + u16 vbistart[2]; +}; +extern const struct bttv_tvnorm bttv_tvnorms[]; + +struct bttv_format { + char *name; + int palette; /* video4linux 1 */ + int fourcc; /* video4linux 2 */ + int btformat; /* BT848_COLOR_FMT_* */ + int btswap; /* BT848_COLOR_CTL_* */ + int depth; /* bit/pixel */ + int flags; + int hshift,vshift; /* for planar modes */ +}; + +/* ---------------------------------------------------------- */ + +struct bttv_geometry { + u8 vtc,crop,comb; + u16 width,hscale,hdelay; + u16 sheight,vscale,vdelay,vtotal; +}; + +struct bttv_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* bttv specific */ + const struct bttv_format *fmt; + int tvnorm; + int btformat; + int btswap; + struct bttv_geometry geo; + struct btcx_riscmem top; + struct btcx_riscmem bottom; +}; + +struct bttv_buffer_set { + struct bttv_buffer *top; /* top field buffer */ + struct bttv_buffer *bottom; /* bottom field buffer */ + unsigned int top_irq; + unsigned int frame_irq; +}; + +struct bttv_overlay { + int tvnorm; + struct v4l2_rect w; + enum v4l2_field field; + struct v4l2_clip *clips; + int nclips; + int setup_ok; +}; + +struct bttv_fh { + struct bttv *btv; + int resources; +#ifdef VIDIOC_G_PRIORITY + enum v4l2_priority prio; +#endif + enum v4l2_buf_type type; + + /* video capture */ + struct videobuf_queue cap; + const struct bttv_format *fmt; + int width; + int height; + + /* current settings */ + const struct bttv_format *ovfmt; + struct bttv_overlay ov; + + /* video overlay */ + struct videobuf_queue vbi; + int lines; +}; + +/* ---------------------------------------------------------- */ +/* bttv-risc.c */ + +/* risc code generators - capture */ +int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int offset, unsigned int bpl, + unsigned int pitch, unsigned int lines); + +/* control dma register + risc main loop */ +void bttv_set_dma(struct bttv *btv, int override); +int bttv_risc_init_main(struct bttv *btv); +int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, + int irqflags); + +/* capture buffer handling */ +int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); +int bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set); +int bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi); +void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf); + +/* overlay handling */ +int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, + const struct bttv_format *fmt, + struct bttv_buffer *buf); + + +/* ---------------------------------------------------------- */ +/* bttv-vbi.c */ + +void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines); + +extern struct videobuf_queue_ops bttv_vbi_qops; + +/* ---------------------------------------------------------- */ +/* bttv-gpio.c */ + + +extern struct bus_type bttv_sub_bus_type; +int bttv_sub_add_device(struct bttv_core *core, char *name); +int bttv_sub_del_devices(struct bttv_core *core); +void bttv_gpio_irq(struct bttv_core *core); + + +/* ---------------------------------------------------------- */ +/* bttv-driver.c */ + +/* insmod options */ +extern unsigned int bttv_verbose; +extern unsigned int bttv_debug; +extern unsigned int bttv_gpio; +extern void bttv_gpio_tracking(struct bttv *btv, char *comment); +extern int init_bttv_i2c(struct bttv *btv); +extern int fini_bttv_i2c(struct bttv *btv); + +#define bttv_printk if (bttv_verbose) printk +#define dprintk if (bttv_debug >= 1) printk +#define d2printk if (bttv_debug >= 2) printk + +#define BTTV_MAX_FBUF 0x208000 +#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) +#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BTTV_FREE_IDLE (HZ) /* one second */ + + +struct bttv_pll_info { + unsigned int pll_ifreq; /* PLL input frequency */ + unsigned int pll_ofreq; /* PLL output frequency */ + unsigned int pll_crystal; /* Crystal used for input */ + unsigned int pll_current; /* Currently programmed ofreq */ +}; + +/* for gpio-connected remote control */ +struct bttv_input { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + u32 mask_keycode; + u32 mask_keydown; +}; + +struct bttv_suspend_state { + u32 gpio_enable; + u32 gpio_data; + int disabled; + int loop_irq; + struct bttv_buffer_set video; + struct bttv_buffer *vbi; +}; + +struct bttv { + struct bttv_core c; + + /* pci device config */ + unsigned short id; + unsigned char revision; + unsigned char __iomem *bt848_mmio; /* pointer to mmio */ + + /* card configuration info */ + unsigned int cardid; /* pci subsystem id (bt878 based ones) */ + unsigned int tuner_type; /* tuner chip type */ + unsigned int tda9887_conf; + unsigned int svhs; + struct bttv_pll_info pll; + int triton1; + int gpioirq; + int (*custom_irq)(struct bttv *btv); + + int use_i2c_hw; + + /* old gpio interface */ + wait_queue_head_t gpioq; + int shutdown; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + + /* new gpio interface */ + spinlock_t gpio_lock; + + /* i2c layer */ + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_state, i2c_rc; + int i2c_done; + wait_queue_head_t i2c_queue; + + /* video4linux (1) */ + struct video_device *video_dev; + struct video_device *radio_dev; + struct video_device *vbi_dev; + + /* infrared remote */ + int has_remote; + struct bttv_ir *remote; + + /* locking */ + spinlock_t s_lock; + struct mutex lock; + int resources; + struct mutex reslock; +#ifdef VIDIOC_G_PRIORITY + struct v4l2_prio_state prio; +#endif + + /* video state */ + unsigned int input; + unsigned int audio; + unsigned long freq; + int tvnorm,hue,contrast,bright,saturation; + struct v4l2_framebuffer fbuf; + unsigned int field_count; + + /* various options */ + int opt_combfilter; + int opt_lumafilter; + int opt_automute; + int opt_chroma_agc; + int opt_adc_crush; + int opt_vcr_hack; + int opt_whitecrush_upper; + int opt_whitecrush_lower; + int opt_uv_ratio; + int opt_full_luma_range; + int opt_coring; + + /* radio data/state */ + int has_radio; + int radio_user; + + /* miro/pinnacle + Aimslab VHX + philips matchbox (tea5757 radio tuner) support */ + int has_matchbox; + int mbox_we; + int mbox_data; + int mbox_clk; + int mbox_most; + int mbox_mask; + + /* ISA stuff (Terratec Active Radio Upgrade) */ + int mbox_ior; + int mbox_iow; + int mbox_csel; + + /* risc memory management data + - must aquire s_lock before changing these + - only the irq handler is supported to touch top + bottom + vcurr */ + struct btcx_riscmem main; + struct bttv_buffer *screen; /* overlay */ + struct list_head capture; /* video capture queue */ + struct list_head vcapture; /* vbi capture queue */ + struct bttv_buffer_set curr; /* active buffers */ + struct bttv_buffer *cvbi; /* active vbi buffer */ + int loop_irq; + int new_input; + + unsigned long cap_ctl; + unsigned long dma_on; + struct timer_list timeout; + struct bttv_suspend_state state; + + /* stats */ + unsigned int errors; + unsigned int framedrop; + unsigned int irq_total; + unsigned int irq_me; + + unsigned int users; + struct bttv_fh init; +}; + +/* our devices */ +#define BTTV_MAX 16 +extern unsigned int bttv_num; +extern struct bttv bttvs[BTTV_MAX]; + +/* private ioctls */ +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) +#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) + +#endif + +#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) +#define btread(adr) readl(btv->bt848_mmio+(adr)) + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +#endif /* _BTTVP_H_ */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.16/btcx-risc.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.16/btcx-risc.h @@ -0,0 +1,34 @@ +/* + */ +struct btcx_riscmem { + unsigned int size; + u32 *cpu; + u32 *jmp; + dma_addr_t dma; +}; + +struct btcx_skiplist { + int start; + int end; +}; + +int btcx_riscmem_alloc(struct pci_dev *pci, + struct btcx_riscmem *risc, + unsigned int size); +void btcx_riscmem_free(struct pci_dev *pci, + struct btcx_riscmem *risc); + +int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, + struct v4l2_clip *clips, unsigned int n); +int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, + unsigned int n, int mask); +void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); +void btcx_calc_skips(int line, int width, unsigned int *maxy, + struct btcx_skiplist *skips, unsigned int *nskips, + const struct v4l2_clip *clips, unsigned int nclips); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.16/bttv.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.16/bttv.h @@ -0,0 +1,407 @@ +/* + * + * bttv - Bt848 frame grabber driver + * + * card ID's and external interfaces of the bttv driver + * basically stuff needed by other drivers (i2c, lirc, ...) + * and is supported not to change much over time. + * + * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + * (c) 1999,2000 Gerd Knorr + * + */ + +#ifndef _BTTV_H_ +#define _BTTV_H_ + +#include +#include +#include +#include + +/* ---------------------------------------------------------- */ +/* exported by bttv-cards.c */ + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ASOUND_SKYEYE 0x8d +#define BTTV_BOARD_SABRENT_TVFM 0x8e +#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f +#define BTTV_BOARD_MACHTV_MAGICTV 0x90 + +/* i2c address list */ +#define I2C_TSA5522 0xc2 +#define I2C_TDA7432 0x8a +#define I2C_BT832_ALT1 0x88 +#define I2C_BT832_ALT2 0x8a // alternate setting +#define I2C_TDA8425 0x82 +#define I2C_TDA9840 0x84 +#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ +#define I2C_TDA9874 0xb0 /* also used by 9875 */ +#define I2C_TDA9875 0xb0 +#define I2C_HAUPEE 0xa0 +#define I2C_STBEE 0xae +#define I2C_VHX 0xc0 +#define I2C_MSP3400 0x80 +#define I2C_MSP3400_ALT 0x88 +#define I2C_TEA6300 0x80 /* also used by 6320 */ +#define I2C_DPL3518 0x84 +#define I2C_TDA9887 0x86 + +/* more card-specific defines */ +#define PT2254_L_CHANNEL 0x10 +#define PT2254_R_CHANNEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + +/* digital_mode */ +#define DIGITAL_MODE_VIDEO 1 +#define DIGITAL_MODE_CAMERA 2 + +struct bttv_core { + /* device structs */ + struct pci_dev *pci; + struct i2c_adapter i2c_adap; + struct list_head subs; /* struct bttv_sub_device */ + + /* device config */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int type; /* card type (pointer into tvcards[]) */ + char name[8]; /* dev name */ +}; + +struct bttv; + + +struct bttv_ir { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* Usual gpio signalling */ + + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + struct work_struct work; + struct timer_list timer; + + /* RC5 gpio */ + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + struct timer_list timer_keyup; /* timer_end for key release */ + u32 last_rc5; /* last good rc5 code */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + int active; /* building raw code */ +}; + +struct tvcard +{ + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; + unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO + u32 gpiomask; + u32 muxsel[16]; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask2; /* GPIO MUX mask */ + + /* i2c audio flags */ + unsigned int no_msp34xx:1; + unsigned int no_tda9875:1; + unsigned int no_tda7432:1; + unsigned int needs_tvaudio:1; + unsigned int msp34xx_alt:1; + + /* flag: video pci function is unused */ + unsigned int no_video:1; + unsigned int has_dvb:1; + unsigned int has_remote:1; + unsigned int no_gpioirq:1; + + /* other settings */ + unsigned int pll; +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 + + unsigned int tuner_type; + unsigned int tuner_addr; + unsigned int radio_addr; + + unsigned int has_radio; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); +}; + +extern struct tvcard bttv_tvcards[]; + +/* identification / initialization of the card */ +extern void bttv_idcard(struct bttv *btv); +extern void bttv_init_card1(struct bttv *btv); +extern void bttv_init_card2(struct bttv *btv); + +/* card-specific funtions */ +extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); +extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); + +/* extra tweaks for some chipsets */ +extern void bttv_check_chipset(void); +extern int bttv_handle_chipset(struct bttv *btv); + +/* ---------------------------------------------------------- */ +/* exported by bttv-if.c */ + +/* this obsolete -- please use the sysfs-based + interface below for new code */ + +/* returns card type + card ID (for bt878-based ones) + for possible values see lines below beginning with #define BTTV_BOARD_UNKNOWN + returns negative value if error occurred +*/ +extern int bttv_get_cardinfo(unsigned int card, int *type, + unsigned int *cardid); +extern struct pci_dev* bttv_get_pcidev(unsigned int card); + +/* obsolete, use bttv_get_cardinfo instead */ +extern int bttv_get_id(unsigned int card); + +/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: + data | (current_GPOE_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_gpio_enable(unsigned int card, + unsigned long mask, unsigned long data); + +/* fills data with GPDATA register contents + returns negative value if error occurred +*/ +extern int bttv_read_gpio(unsigned int card, unsigned long *data); + +/* sets GPDATA register to new value: + (data & mask) | (current_GPDATA_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_write_gpio(unsigned int card, + unsigned long mask, unsigned long data); + +/* returns pointer to task queue which can be used as parameter to + interruptible_sleep_on + in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated + (wake_up_interruptible) and following call to the function bttv_read_gpio + should return new value of GPDATA, + returns NULL value if error occurred or queue is not available + WARNING: because there is no buffer for GPIO data, one MUST + process data ASAP +*/ +extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); + +/* call i2c clients +*/ +extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); + + + +/* ---------------------------------------------------------- */ +/* sysfs/driver-moded based gpio access interface */ + + +struct bttv_sub_device { + struct device dev; + struct bttv_core *core; + struct list_head list; +}; +#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) + +struct bttv_sub_driver { + struct device_driver drv; + char wanted[BUS_ID_SIZE]; + int (*probe)(struct bttv_sub_device *sub); + void (*remove)(struct bttv_sub_device *sub); + void (*gpio_irq)(struct bttv_sub_device *sub); +}; +#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) + +int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); +int bttv_sub_unregister(struct bttv_sub_driver *drv); + +/* gpio access functions */ +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); +u32 bttv_gpio_read(struct bttv_core *core); +void bttv_gpio_write(struct bttv_core *core, u32 value); +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); + +#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) +#define gpio_read() bttv_gpio_read(&btv->c) +#define gpio_write(value) bttv_gpio_write(&btv->c, value) +#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) + + +/* ---------------------------------------------------------- */ +/* i2c */ + +extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); +extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both); +extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); + +extern int bttv_input_init(struct bttv *dev); +extern void bttv_input_fini(struct bttv *dev); +extern void bttv_input_irq(struct bttv *dev); + +#endif /* _BTTV_H_ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.16/bt848.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.16/bt848.h @@ -0,0 +1,366 @@ +/* + bt848.h - Bt848 register offsets + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BT848_H_ +#define _BT848_H_ + +#ifndef PCI_VENDOR_ID_BROOKTREE +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#endif +#ifndef PCI_DEVICE_ID_BT848 +#define PCI_DEVICE_ID_BT848 0x350 +#endif +#ifndef PCI_DEVICE_ID_BT849 +#define PCI_DEVICE_ID_BT849 0x351 +#endif +#ifndef PCI_DEVICE_ID_BT878 +#define PCI_DEVICE_ID_BT878 0x36e +#endif +#ifndef PCI_DEVICE_ID_BT879 +#define PCI_DEVICE_ID_BT879 0x36f +#endif + + +/* Brooktree 848 registers */ + +#define BT848_DSTATUS 0x000 +#define BT848_DSTATUS_PRES (1<<7) +#define BT848_DSTATUS_HLOC (1<<6) +#define BT848_DSTATUS_FIELD (1<<5) +#define BT848_DSTATUS_NUML (1<<4) +#define BT848_DSTATUS_CSEL (1<<3) +#define BT848_DSTATUS_PLOCK (1<<2) +#define BT848_DSTATUS_LOF (1<<1) +#define BT848_DSTATUS_COF (1<<0) + +#define BT848_IFORM 0x004 +#define BT848_IFORM_HACTIVE (1<<7) +#define BT848_IFORM_MUXSEL (3<<5) +#define BT848_IFORM_MUX0 (2<<5) +#define BT848_IFORM_MUX1 (3<<5) +#define BT848_IFORM_MUX2 (1<<5) +#define BT848_IFORM_XTSEL (3<<3) +#define BT848_IFORM_XT0 (1<<3) +#define BT848_IFORM_XT1 (2<<3) +#define BT848_IFORM_XTAUTO (3<<3) +#define BT848_IFORM_XTBOTH (3<<3) +#define BT848_IFORM_NTSC 1 +#define BT848_IFORM_NTSC_J 2 +#define BT848_IFORM_PAL_BDGHI 3 +#define BT848_IFORM_PAL_M 4 +#define BT848_IFORM_PAL_N 5 +#define BT848_IFORM_SECAM 6 +#define BT848_IFORM_PAL_NC 7 +#define BT848_IFORM_AUTO 0 +#define BT848_IFORM_NORM 7 + +#define BT848_TDEC 0x008 +#define BT848_TDEC_DEC_FIELD (1<<7) +#define BT848_TDEC_FLDALIGN (1<<6) +#define BT848_TDEC_DEC_RAT (0x1f) + +#define BT848_E_CROP 0x00C +#define BT848_O_CROP 0x08C + +#define BT848_E_VDELAY_LO 0x010 +#define BT848_O_VDELAY_LO 0x090 + +#define BT848_E_VACTIVE_LO 0x014 +#define BT848_O_VACTIVE_LO 0x094 + +#define BT848_E_HDELAY_LO 0x018 +#define BT848_O_HDELAY_LO 0x098 + +#define BT848_E_HACTIVE_LO 0x01C +#define BT848_O_HACTIVE_LO 0x09C + +#define BT848_E_HSCALE_HI 0x020 +#define BT848_O_HSCALE_HI 0x0A0 + +#define BT848_E_HSCALE_LO 0x024 +#define BT848_O_HSCALE_LO 0x0A4 + +#define BT848_BRIGHT 0x028 + +#define BT848_E_CONTROL 0x02C +#define BT848_O_CONTROL 0x0AC +#define BT848_CONTROL_LNOTCH (1<<7) +#define BT848_CONTROL_COMP (1<<6) +#define BT848_CONTROL_LDEC (1<<5) +#define BT848_CONTROL_CBSENSE (1<<4) +#define BT848_CONTROL_CON_MSB (1<<2) +#define BT848_CONTROL_SAT_U_MSB (1<<1) +#define BT848_CONTROL_SAT_V_MSB (1<<0) + +#define BT848_CONTRAST_LO 0x030 +#define BT848_SAT_U_LO 0x034 +#define BT848_SAT_V_LO 0x038 +#define BT848_HUE 0x03C + +#define BT848_E_SCLOOP 0x040 +#define BT848_O_SCLOOP 0x0C0 +#define BT848_SCLOOP_CAGC (1<<6) +#define BT848_SCLOOP_CKILL (1<<5) +#define BT848_SCLOOP_HFILT_AUTO (0<<3) +#define BT848_SCLOOP_HFILT_CIF (1<<3) +#define BT848_SCLOOP_HFILT_QCIF (2<<3) +#define BT848_SCLOOP_HFILT_ICON (3<<3) + +#define BT848_SCLOOP_PEAK (1<<7) +#define BT848_SCLOOP_HFILT_MINP (1<<3) +#define BT848_SCLOOP_HFILT_MEDP (2<<3) +#define BT848_SCLOOP_HFILT_MAXP (3<<3) + + +#define BT848_OFORM 0x048 +#define BT848_OFORM_RANGE (1<<7) +#define BT848_OFORM_CORE0 (0<<5) +#define BT848_OFORM_CORE8 (1<<5) +#define BT848_OFORM_CORE16 (2<<5) +#define BT848_OFORM_CORE32 (3<<5) + +#define BT848_E_VSCALE_HI 0x04C +#define BT848_O_VSCALE_HI 0x0CC +#define BT848_VSCALE_YCOMB (1<<7) +#define BT848_VSCALE_COMB (1<<6) +#define BT848_VSCALE_INT (1<<5) +#define BT848_VSCALE_HI 15 + +#define BT848_E_VSCALE_LO 0x050 +#define BT848_O_VSCALE_LO 0x0D0 +#define BT848_TEST 0x054 +#define BT848_ADELAY 0x060 +#define BT848_BDELAY 0x064 + +#define BT848_ADC 0x068 +#define BT848_ADC_RESERVED (2<<6) +#define BT848_ADC_SYNC_T (1<<5) +#define BT848_ADC_AGC_EN (1<<4) +#define BT848_ADC_CLK_SLEEP (1<<3) +#define BT848_ADC_Y_SLEEP (1<<2) +#define BT848_ADC_C_SLEEP (1<<1) +#define BT848_ADC_CRUSH (1<<0) + +#define BT848_WC_UP 0x044 +#define BT848_WC_DOWN 0x078 + +#define BT848_E_VTC 0x06C +#define BT848_O_VTC 0x0EC +#define BT848_VTC_HSFMT (1<<7) +#define BT848_VTC_VFILT_2TAP 0 +#define BT848_VTC_VFILT_3TAP 1 +#define BT848_VTC_VFILT_4TAP 2 +#define BT848_VTC_VFILT_5TAP 3 + +#define BT848_SRESET 0x07C + +#define BT848_COLOR_FMT 0x0D4 +#define BT848_COLOR_FMT_O_RGB32 (0<<4) +#define BT848_COLOR_FMT_O_RGB24 (1<<4) +#define BT848_COLOR_FMT_O_RGB16 (2<<4) +#define BT848_COLOR_FMT_O_RGB15 (3<<4) +#define BT848_COLOR_FMT_O_YUY2 (4<<4) +#define BT848_COLOR_FMT_O_BtYUV (5<<4) +#define BT848_COLOR_FMT_O_Y8 (6<<4) +#define BT848_COLOR_FMT_O_RGB8 (7<<4) +#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) +#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) +#define BT848_COLOR_FMT_O_RAW (14<<4) +#define BT848_COLOR_FMT_E_RGB32 0 +#define BT848_COLOR_FMT_E_RGB24 1 +#define BT848_COLOR_FMT_E_RGB16 2 +#define BT848_COLOR_FMT_E_RGB15 3 +#define BT848_COLOR_FMT_E_YUY2 4 +#define BT848_COLOR_FMT_E_BtYUV 5 +#define BT848_COLOR_FMT_E_Y8 6 +#define BT848_COLOR_FMT_E_RGB8 7 +#define BT848_COLOR_FMT_E_YCrCb422 8 +#define BT848_COLOR_FMT_E_YCrCb411 9 +#define BT848_COLOR_FMT_E_RAW 14 + +#define BT848_COLOR_FMT_RGB32 0x00 +#define BT848_COLOR_FMT_RGB24 0x11 +#define BT848_COLOR_FMT_RGB16 0x22 +#define BT848_COLOR_FMT_RGB15 0x33 +#define BT848_COLOR_FMT_YUY2 0x44 +#define BT848_COLOR_FMT_BtYUV 0x55 +#define BT848_COLOR_FMT_Y8 0x66 +#define BT848_COLOR_FMT_RGB8 0x77 +#define BT848_COLOR_FMT_YCrCb422 0x88 +#define BT848_COLOR_FMT_YCrCb411 0x99 +#define BT848_COLOR_FMT_RAW 0xee + +#define BT848_VTOTAL_LO 0xB0 +#define BT848_VTOTAL_HI 0xB4 + +#define BT848_COLOR_CTL 0x0D8 +#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) +#define BT848_COLOR_CTL_COLOR_BARS (1<<6) +#define BT848_COLOR_CTL_RGB_DED (1<<5) +#define BT848_COLOR_CTL_GAMMA (1<<4) +#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) +#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) +#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) +#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) + +#define BT848_CAP_CTL 0x0DC +#define BT848_CAP_CTL_DITH_FRAME (1<<4) +#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) +#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) +#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) +#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) + +#define BT848_VBI_PACK_SIZE 0x0E0 + +#define BT848_VBI_PACK_DEL 0x0E4 +#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc +#define BT848_VBI_PACK_DEL_EXT_FRAME 2 +#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 + + +#define BT848_INT_STAT 0x100 +#define BT848_INT_MASK 0x104 + +#define BT848_INT_ETBF (1<<23) + +#define BT848_INT_RISCS (0xf<<28) +#define BT848_INT_RISC_EN (1<<27) +#define BT848_INT_RACK (1<<25) +#define BT848_INT_FIELD (1<<24) +#define BT848_INT_SCERR (1<<19) +#define BT848_INT_OCERR (1<<18) +#define BT848_INT_PABORT (1<<17) +#define BT848_INT_RIPERR (1<<16) +#define BT848_INT_PPERR (1<<15) +#define BT848_INT_FDSR (1<<14) +#define BT848_INT_FTRGT (1<<13) +#define BT848_INT_FBUS (1<<12) +#define BT848_INT_RISCI (1<<11) +#define BT848_INT_GPINT (1<<9) +#define BT848_INT_I2CDONE (1<<8) +#define BT848_INT_VPRES (1<<5) +#define BT848_INT_HLOCK (1<<4) +#define BT848_INT_OFLOW (1<<3) +#define BT848_INT_HSYNC (1<<2) +#define BT848_INT_VSYNC (1<<1) +#define BT848_INT_FMTCHG (1<<0) + + +#define BT848_GPIO_DMA_CTL 0x10C +#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) +#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) +#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) +#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) +#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) +#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) +#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) +#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) +#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) +#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) +#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) +#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) +#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) + +#define BT848_I2C 0x110 +#define BT878_I2C_MODE (1<<7) +#define BT878_I2C_RATE (1<<6) +#define BT878_I2C_NOSTOP (1<<5) +#define BT878_I2C_NOSTART (1<<4) +#define BT848_I2C_DIV (0xf<<4) +#define BT848_I2C_SYNC (1<<3) +#define BT848_I2C_W3B (1<<2) +#define BT848_I2C_SCL (1<<1) +#define BT848_I2C_SDA (1<<0) + +#define BT848_RISC_STRT_ADD 0x114 +#define BT848_GPIO_OUT_EN 0x118 +#define BT848_GPIO_REG_INP 0x11C +#define BT848_RISC_COUNT 0x120 +#define BT848_GPIO_DATA 0x200 + + +/* Bt848 RISC commands */ + +/* only for the SYNC RISC command */ +#define BT848_FIFO_STATUS_FM1 0x06 +#define BT848_FIFO_STATUS_FM3 0x0e +#define BT848_FIFO_STATUS_SOL 0x02 +#define BT848_FIFO_STATUS_EOL4 0x01 +#define BT848_FIFO_STATUS_EOL3 0x0d +#define BT848_FIFO_STATUS_EOL2 0x09 +#define BT848_FIFO_STATUS_EOL1 0x05 +#define BT848_FIFO_STATUS_VRE 0x04 +#define BT848_FIFO_STATUS_VRO 0x0c +#define BT848_FIFO_STATUS_PXV 0x00 + +#define BT848_RISC_RESYNC (1<<15) + +/* WRITE and SKIP */ +/* disable which bytes of each DWORD */ +#define BT848_RISC_BYTE0 (1U<<12) +#define BT848_RISC_BYTE1 (1U<<13) +#define BT848_RISC_BYTE2 (1U<<14) +#define BT848_RISC_BYTE3 (1U<<15) +#define BT848_RISC_BYTE_ALL (0x0fU<<12) +#define BT848_RISC_BYTE_NONE 0 +/* cause RISCI */ +#define BT848_RISC_IRQ (1U<<24) +/* RISC command is last one in this line */ +#define BT848_RISC_EOL (1U<<26) +/* RISC command is first one in this line */ +#define BT848_RISC_SOL (1U<<27) + +#define BT848_RISC_WRITE (0x01U<<28) +#define BT848_RISC_SKIP (0x02U<<28) +#define BT848_RISC_WRITEC (0x05U<<28) +#define BT848_RISC_JUMP (0x07U<<28) +#define BT848_RISC_SYNC (0x08U<<28) + +#define BT848_RISC_WRITE123 (0x09U<<28) +#define BT848_RISC_SKIP123 (0x0aU<<28) +#define BT848_RISC_WRITE1S23 (0x0bU<<28) + + +/* Bt848A and higher only !! */ +#define BT848_TGLB 0x080 +#define BT848_TGCTRL 0x084 +#define BT848_FCAP 0x0E8 +#define BT848_PLL_F_LO 0x0F0 +#define BT848_PLL_F_HI 0x0F4 + +#define BT848_PLL_XCI 0x0F8 +#define BT848_PLL_X (1<<7) +#define BT848_PLL_C (1<<6) + +#define BT848_DVSIF 0x0FC + +/* Bt878 register */ + +#define BT878_DEVCTRL 0x40 +#define BT878_EN_TBFX 0x02 +#define BT878_EN_VSFX 0x04 + +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.20/bttvp.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.20/bttvp.h @@ -0,0 +1,413 @@ +/* + + bttv - Bt848 frame grabber driver + + bttv's *private* header file -- nobody other than bttv itself + should ever include this file. + + (c) 2000-2002 Gerd Knorr + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BTTVP_H_ +#define _BTTVP_H_ + +#include +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "bt848.h" +#include "bttv.h" +#include "btcx-risc.h" + +#ifdef __KERNEL__ + +#define FORMAT_FLAGS_DITHER 0x01 +#define FORMAT_FLAGS_PACKED 0x02 +#define FORMAT_FLAGS_PLANAR 0x04 +#define FORMAT_FLAGS_RAW 0x08 +#define FORMAT_FLAGS_CrCb 0x10 + +#define RISC_SLOT_O_VBI 4 +#define RISC_SLOT_O_FIELD 6 +#define RISC_SLOT_E_VBI 10 +#define RISC_SLOT_E_FIELD 12 +#define RISC_SLOT_LOOP 14 + +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO 2 +#define RESOURCE_VBI 4 + +#define RAW_LINES 640 +#define RAW_BPL 1024 + +#define UNSET (-1U) + +#define clamp(x, low, high) min (max (low, x), high) + +/* ---------------------------------------------------------- */ + +struct bttv_tvnorm { + int v4l2_id; + char *name; + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ + u16 totalwidth; + u8 adelay, bdelay, iform; + u32 scaledtwidth; + u16 hdelayx1, hactivex1; + u16 vdelay; + u8 vbipack; + u16 vtotal; + int sram; + /* ITU-R frame line number of the first VBI line we can + capture, of the first and second field. */ + u16 vbistart[2]; +}; +extern const struct bttv_tvnorm bttv_tvnorms[]; + +struct bttv_format { + char *name; + int palette; /* video4linux 1 */ + int fourcc; /* video4linux 2 */ + int btformat; /* BT848_COLOR_FMT_* */ + int btswap; /* BT848_COLOR_CTL_* */ + int depth; /* bit/pixel */ + int flags; + int hshift,vshift; /* for planar modes */ +}; + +/* ---------------------------------------------------------- */ + +struct bttv_geometry { + u8 vtc,crop,comb; + u16 width,hscale,hdelay; + u16 sheight,vscale,vdelay,vtotal; +}; + +struct bttv_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* bttv specific */ + const struct bttv_format *fmt; + int tvnorm; + int btformat; + int btswap; + struct bttv_geometry geo; + struct btcx_riscmem top; + struct btcx_riscmem bottom; +}; + +struct bttv_buffer_set { + struct bttv_buffer *top; /* top field buffer */ + struct bttv_buffer *bottom; /* bottom field buffer */ + unsigned int top_irq; + unsigned int frame_irq; +}; + +struct bttv_overlay { + int tvnorm; + struct v4l2_rect w; + enum v4l2_field field; + struct v4l2_clip *clips; + int nclips; + int setup_ok; +}; + +struct bttv_fh { + struct bttv *btv; + int resources; +#ifdef VIDIOC_G_PRIORITY + enum v4l2_priority prio; +#endif + enum v4l2_buf_type type; + + /* video capture */ + struct videobuf_queue cap; + const struct bttv_format *fmt; + int width; + int height; + + /* current settings */ + const struct bttv_format *ovfmt; + struct bttv_overlay ov; + + /* video overlay */ + struct videobuf_queue vbi; + int lines; +}; + +/* ---------------------------------------------------------- */ +/* bttv-risc.c */ + +/* risc code generators - capture */ +int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int offset, unsigned int bpl, + unsigned int pitch, unsigned int lines); + +/* control dma register + risc main loop */ +void bttv_set_dma(struct bttv *btv, int override); +int bttv_risc_init_main(struct bttv *btv); +int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, + int irqflags); + +/* capture buffer handling */ +int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); +int bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set); +int bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi); +void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, + struct bttv_buffer *buf); + +/* overlay handling */ +int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, + const struct bttv_format *fmt, + struct bttv_buffer *buf); + + +/* ---------------------------------------------------------- */ +/* bttv-vbi.c */ + +void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines); + +extern struct videobuf_queue_ops bttv_vbi_qops; + +/* ---------------------------------------------------------- */ +/* bttv-gpio.c */ + + +extern struct bus_type bttv_sub_bus_type; +int bttv_sub_add_device(struct bttv_core *core, char *name); +int bttv_sub_del_devices(struct bttv_core *core); + + +/* ---------------------------------------------------------- */ +/* bttv-driver.c */ + +/* insmod options */ +extern unsigned int bttv_verbose; +extern unsigned int bttv_debug; +extern unsigned int bttv_gpio; +extern void bttv_gpio_tracking(struct bttv *btv, char *comment); +extern int init_bttv_i2c(struct bttv *btv); +extern int fini_bttv_i2c(struct bttv *btv); + +#define bttv_printk if (bttv_verbose) printk +#define dprintk if (bttv_debug >= 1) printk +#define d2printk if (bttv_debug >= 2) printk + +#define BTTV_MAX_FBUF 0x208000 +#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) +#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BTTV_FREE_IDLE (HZ) /* one second */ + + +struct bttv_pll_info { + unsigned int pll_ifreq; /* PLL input frequency */ + unsigned int pll_ofreq; /* PLL output frequency */ + unsigned int pll_crystal; /* Crystal used for input */ + unsigned int pll_current; /* Currently programmed ofreq */ +}; + +/* for gpio-connected remote control */ +struct bttv_input { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + u32 mask_keycode; + u32 mask_keydown; +}; + +struct bttv_suspend_state { + u32 gpio_enable; + u32 gpio_data; + int disabled; + int loop_irq; + struct bttv_buffer_set video; + struct bttv_buffer *vbi; +}; + +struct bttv { + struct bttv_core c; + + /* pci device config */ + unsigned short id; + unsigned char revision; + unsigned char __iomem *bt848_mmio; /* pointer to mmio */ + + /* card configuration info */ + unsigned int cardid; /* pci subsystem id (bt878 based ones) */ + unsigned int tuner_type; /* tuner chip type */ + unsigned int tda9887_conf; + unsigned int svhs; + struct bttv_pll_info pll; + int triton1; + int gpioirq; + int (*custom_irq)(struct bttv *btv); + + int use_i2c_hw; + + /* old gpio interface */ + wait_queue_head_t gpioq; + int shutdown; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + + /* new gpio interface */ + spinlock_t gpio_lock; + + /* i2c layer */ + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_state, i2c_rc; + int i2c_done; + wait_queue_head_t i2c_queue; + struct i2c_client *i2c_msp34xx_client; + struct i2c_client *i2c_tvaudio_client; + + /* video4linux (1) */ + struct video_device *video_dev; + struct video_device *radio_dev; + struct video_device *vbi_dev; + + /* infrared remote */ + int has_remote; + struct bttv_ir *remote; + + /* locking */ + spinlock_t s_lock; + struct mutex lock; + int resources; + struct mutex reslock; +#ifdef VIDIOC_G_PRIORITY + struct v4l2_prio_state prio; +#endif + + /* video state */ + unsigned int input; + unsigned int audio; + unsigned int mute; + unsigned long freq; + int tvnorm,hue,contrast,bright,saturation; + struct v4l2_framebuffer fbuf; + unsigned int field_count; + + /* various options */ + int opt_combfilter; + int opt_lumafilter; + int opt_automute; + int opt_chroma_agc; + int opt_adc_crush; + int opt_vcr_hack; + int opt_whitecrush_upper; + int opt_whitecrush_lower; + int opt_uv_ratio; + int opt_full_luma_range; + int opt_coring; + + /* radio data/state */ + int has_radio; + int radio_user; + + /* miro/pinnacle + Aimslab VHX + philips matchbox (tea5757 radio tuner) support */ + int has_matchbox; + int mbox_we; + int mbox_data; + int mbox_clk; + int mbox_most; + int mbox_mask; + + /* ISA stuff (Terratec Active Radio Upgrade) */ + int mbox_ior; + int mbox_iow; + int mbox_csel; + + /* risc memory management data + - must acquire s_lock before changing these + - only the irq handler is supported to touch top + bottom + vcurr */ + struct btcx_riscmem main; + struct bttv_buffer *screen; /* overlay */ + struct list_head capture; /* video capture queue */ + struct list_head vcapture; /* vbi capture queue */ + struct bttv_buffer_set curr; /* active buffers */ + struct bttv_buffer *cvbi; /* active vbi buffer */ + int loop_irq; + int new_input; + + unsigned long cap_ctl; + unsigned long dma_on; + struct timer_list timeout; + struct bttv_suspend_state state; + + /* stats */ + unsigned int errors; + unsigned int framedrop; + unsigned int irq_total; + unsigned int irq_me; + + unsigned int users; + struct bttv_fh init; +}; + +/* our devices */ +#define BTTV_MAX 16 +extern unsigned int bttv_num; +extern struct bttv bttvs[BTTV_MAX]; + +/* private ioctls */ +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) +#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) + +#endif + +#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) +#define btread(adr) readl(btv->bt848_mmio+(adr)) + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +#endif /* _BTTVP_H_ */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.20/btcx-risc.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.20/btcx-risc.h @@ -0,0 +1,34 @@ +/* + */ +struct btcx_riscmem { + unsigned int size; + u32 *cpu; + u32 *jmp; + dma_addr_t dma; +}; + +struct btcx_skiplist { + int start; + int end; +}; + +int btcx_riscmem_alloc(struct pci_dev *pci, + struct btcx_riscmem *risc, + unsigned int size); +void btcx_riscmem_free(struct pci_dev *pci, + struct btcx_riscmem *risc); + +int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, + struct v4l2_clip *clips, unsigned int n); +int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, + unsigned int n, int mask); +void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); +void btcx_calc_skips(int line, int width, unsigned int *maxy, + struct btcx_skiplist *skips, unsigned int *nskips, + const struct v4l2_clip *clips, unsigned int nclips); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.20/bttv.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.20/bttv.h @@ -0,0 +1,389 @@ +/* + * + * bttv - Bt848 frame grabber driver + * + * card ID's and external interfaces of the bttv driver + * basically stuff needed by other drivers (i2c, lirc, ...) + * and is supported not to change much over time. + * + * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + * (c) 1999,2000 Gerd Knorr + * + */ + +#ifndef _BTTV_H_ +#define _BTTV_H_ + +#include +#include +#include +#include +#include + +/* ---------------------------------------------------------- */ +/* exported by bttv-cards.c */ + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ASOUND_SKYEYE 0x8d +#define BTTV_BOARD_SABRENT_TVFM 0x8e +#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f +#define BTTV_BOARD_MACHTV_MAGICTV 0x90 + +/* more card-specific defines */ +#define PT2254_L_CHANNEL 0x10 +#define PT2254_R_CHANNEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + +/* digital_mode */ +#define DIGITAL_MODE_VIDEO 1 +#define DIGITAL_MODE_CAMERA 2 + +struct bttv_core { + /* device structs */ + struct pci_dev *pci; + struct i2c_adapter i2c_adap; + struct list_head subs; /* struct bttv_sub_device */ + + /* device config */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int type; /* card type (pointer into tvcards[]) */ + char name[8]; /* dev name */ +}; + +struct bttv; + + +struct bttv_ir { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* Usual gpio signalling */ + + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + struct work_struct work; + struct timer_list timer; + + /* RC5 gpio */ + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + struct timer_list timer_keyup; /* timer_end for key release */ + u32 last_rc5; /* last good rc5 code */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + int active; /* building raw code */ +}; + +struct tvcard +{ + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; + unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO + u32 gpiomask; + u32 muxsel[16]; + u32 gpiomux[4]; /* Tuner, Radio, external, internal */ + u32 gpiomute; /* GPIO mute setting */ + u32 gpiomask2; /* GPIO MUX mask */ + + /* i2c audio flags */ + unsigned int no_msp34xx:1; + unsigned int no_tda9875:1; + unsigned int no_tda7432:1; + unsigned int needs_tvaudio:1; + unsigned int msp34xx_alt:1; + + /* flag: video pci function is unused */ + unsigned int no_video:1; + unsigned int has_dvb:1; + unsigned int has_remote:1; + unsigned int no_gpioirq:1; + + /* other settings */ + unsigned int pll; +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 + + unsigned int tuner_type; + unsigned int tuner_addr; + unsigned int radio_addr; + + unsigned int has_radio; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); +}; + +extern struct tvcard bttv_tvcards[]; + +/* identification / initialization of the card */ +extern void bttv_idcard(struct bttv *btv); +extern void bttv_init_card1(struct bttv *btv); +extern void bttv_init_card2(struct bttv *btv); + +/* card-specific funtions */ +extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); +extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); + +/* extra tweaks for some chipsets */ +extern void bttv_check_chipset(void); +extern int bttv_handle_chipset(struct bttv *btv); + +/* ---------------------------------------------------------- */ +/* exported by bttv-if.c */ + +/* this obsolete -- please use the sysfs-based + interface below for new code */ + +/* returns card type + card ID (for bt878-based ones) + for possible values see lines below beginning with #define BTTV_BOARD_UNKNOWN + returns negative value if error occurred +*/ +extern int bttv_get_cardinfo(unsigned int card, int *type, + unsigned int *cardid); +extern struct pci_dev* bttv_get_pcidev(unsigned int card); + +/* obsolete, use bttv_get_cardinfo instead */ +extern int bttv_get_id(unsigned int card); + +/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: + data | (current_GPOE_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_gpio_enable(unsigned int card, + unsigned long mask, unsigned long data); + +/* fills data with GPDATA register contents + returns negative value if error occurred +*/ +extern int bttv_read_gpio(unsigned int card, unsigned long *data); + +/* sets GPDATA register to new value: + (data & mask) | (current_GPDATA_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_write_gpio(unsigned int card, + unsigned long mask, unsigned long data); + +/* returns pointer to task queue which can be used as parameter to + interruptible_sleep_on + in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated + (wake_up_interruptible) and following call to the function bttv_read_gpio + should return new value of GPDATA, + returns NULL value if error occurred or queue is not available + WARNING: because there is no buffer for GPIO data, one MUST + process data ASAP +*/ +extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); + +/* call i2c clients +*/ +extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); + + + +/* ---------------------------------------------------------- */ +/* sysfs/driver-moded based gpio access interface */ + + +struct bttv_sub_device { + struct device dev; + struct bttv_core *core; + struct list_head list; +}; +#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) + +struct bttv_sub_driver { + struct device_driver drv; + char wanted[BUS_ID_SIZE]; + int (*probe)(struct bttv_sub_device *sub); + void (*remove)(struct bttv_sub_device *sub); +}; +#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) + +int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); +int bttv_sub_unregister(struct bttv_sub_driver *drv); + +/* gpio access functions */ +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); +u32 bttv_gpio_read(struct bttv_core *core); +void bttv_gpio_write(struct bttv_core *core, u32 value); +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); + +#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) +#define gpio_read() bttv_gpio_read(&btv->c) +#define gpio_write(value) bttv_gpio_write(&btv->c, value) +#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) + + +/* ---------------------------------------------------------- */ +/* i2c */ + +extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); +extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both); +extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); + +extern int bttv_input_init(struct bttv *dev); +extern void bttv_input_fini(struct bttv *dev); +extern void bttv_input_irq(struct bttv *dev); + +#endif /* _BTTV_H_ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_gpio/extra_2.6.20/bt848.h +++ linux-2.6.27/ubuntu/lirc/lirc_gpio/extra_2.6.20/bt848.h @@ -0,0 +1,366 @@ +/* + bt848.h - Bt848 register offsets + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BT848_H_ +#define _BT848_H_ + +#ifndef PCI_VENDOR_ID_BROOKTREE +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#endif +#ifndef PCI_DEVICE_ID_BT848 +#define PCI_DEVICE_ID_BT848 0x350 +#endif +#ifndef PCI_DEVICE_ID_BT849 +#define PCI_DEVICE_ID_BT849 0x351 +#endif +#ifndef PCI_DEVICE_ID_BT878 +#define PCI_DEVICE_ID_BT878 0x36e +#endif +#ifndef PCI_DEVICE_ID_BT879 +#define PCI_DEVICE_ID_BT879 0x36f +#endif + + +/* Brooktree 848 registers */ + +#define BT848_DSTATUS 0x000 +#define BT848_DSTATUS_PRES (1<<7) +#define BT848_DSTATUS_HLOC (1<<6) +#define BT848_DSTATUS_FIELD (1<<5) +#define BT848_DSTATUS_NUML (1<<4) +#define BT848_DSTATUS_CSEL (1<<3) +#define BT848_DSTATUS_PLOCK (1<<2) +#define BT848_DSTATUS_LOF (1<<1) +#define BT848_DSTATUS_COF (1<<0) + +#define BT848_IFORM 0x004 +#define BT848_IFORM_HACTIVE (1<<7) +#define BT848_IFORM_MUXSEL (3<<5) +#define BT848_IFORM_MUX0 (2<<5) +#define BT848_IFORM_MUX1 (3<<5) +#define BT848_IFORM_MUX2 (1<<5) +#define BT848_IFORM_XTSEL (3<<3) +#define BT848_IFORM_XT0 (1<<3) +#define BT848_IFORM_XT1 (2<<3) +#define BT848_IFORM_XTAUTO (3<<3) +#define BT848_IFORM_XTBOTH (3<<3) +#define BT848_IFORM_NTSC 1 +#define BT848_IFORM_NTSC_J 2 +#define BT848_IFORM_PAL_BDGHI 3 +#define BT848_IFORM_PAL_M 4 +#define BT848_IFORM_PAL_N 5 +#define BT848_IFORM_SECAM 6 +#define BT848_IFORM_PAL_NC 7 +#define BT848_IFORM_AUTO 0 +#define BT848_IFORM_NORM 7 + +#define BT848_TDEC 0x008 +#define BT848_TDEC_DEC_FIELD (1<<7) +#define BT848_TDEC_FLDALIGN (1<<6) +#define BT848_TDEC_DEC_RAT (0x1f) + +#define BT848_E_CROP 0x00C +#define BT848_O_CROP 0x08C + +#define BT848_E_VDELAY_LO 0x010 +#define BT848_O_VDELAY_LO 0x090 + +#define BT848_E_VACTIVE_LO 0x014 +#define BT848_O_VACTIVE_LO 0x094 + +#define BT848_E_HDELAY_LO 0x018 +#define BT848_O_HDELAY_LO 0x098 + +#define BT848_E_HACTIVE_LO 0x01C +#define BT848_O_HACTIVE_LO 0x09C + +#define BT848_E_HSCALE_HI 0x020 +#define BT848_O_HSCALE_HI 0x0A0 + +#define BT848_E_HSCALE_LO 0x024 +#define BT848_O_HSCALE_LO 0x0A4 + +#define BT848_BRIGHT 0x028 + +#define BT848_E_CONTROL 0x02C +#define BT848_O_CONTROL 0x0AC +#define BT848_CONTROL_LNOTCH (1<<7) +#define BT848_CONTROL_COMP (1<<6) +#define BT848_CONTROL_LDEC (1<<5) +#define BT848_CONTROL_CBSENSE (1<<4) +#define BT848_CONTROL_CON_MSB (1<<2) +#define BT848_CONTROL_SAT_U_MSB (1<<1) +#define BT848_CONTROL_SAT_V_MSB (1<<0) + +#define BT848_CONTRAST_LO 0x030 +#define BT848_SAT_U_LO 0x034 +#define BT848_SAT_V_LO 0x038 +#define BT848_HUE 0x03C + +#define BT848_E_SCLOOP 0x040 +#define BT848_O_SCLOOP 0x0C0 +#define BT848_SCLOOP_CAGC (1<<6) +#define BT848_SCLOOP_CKILL (1<<5) +#define BT848_SCLOOP_HFILT_AUTO (0<<3) +#define BT848_SCLOOP_HFILT_CIF (1<<3) +#define BT848_SCLOOP_HFILT_QCIF (2<<3) +#define BT848_SCLOOP_HFILT_ICON (3<<3) + +#define BT848_SCLOOP_PEAK (1<<7) +#define BT848_SCLOOP_HFILT_MINP (1<<3) +#define BT848_SCLOOP_HFILT_MEDP (2<<3) +#define BT848_SCLOOP_HFILT_MAXP (3<<3) + + +#define BT848_OFORM 0x048 +#define BT848_OFORM_RANGE (1<<7) +#define BT848_OFORM_CORE0 (0<<5) +#define BT848_OFORM_CORE8 (1<<5) +#define BT848_OFORM_CORE16 (2<<5) +#define BT848_OFORM_CORE32 (3<<5) + +#define BT848_E_VSCALE_HI 0x04C +#define BT848_O_VSCALE_HI 0x0CC +#define BT848_VSCALE_YCOMB (1<<7) +#define BT848_VSCALE_COMB (1<<6) +#define BT848_VSCALE_INT (1<<5) +#define BT848_VSCALE_HI 15 + +#define BT848_E_VSCALE_LO 0x050 +#define BT848_O_VSCALE_LO 0x0D0 +#define BT848_TEST 0x054 +#define BT848_ADELAY 0x060 +#define BT848_BDELAY 0x064 + +#define BT848_ADC 0x068 +#define BT848_ADC_RESERVED (2<<6) +#define BT848_ADC_SYNC_T (1<<5) +#define BT848_ADC_AGC_EN (1<<4) +#define BT848_ADC_CLK_SLEEP (1<<3) +#define BT848_ADC_Y_SLEEP (1<<2) +#define BT848_ADC_C_SLEEP (1<<1) +#define BT848_ADC_CRUSH (1<<0) + +#define BT848_WC_UP 0x044 +#define BT848_WC_DOWN 0x078 + +#define BT848_E_VTC 0x06C +#define BT848_O_VTC 0x0EC +#define BT848_VTC_HSFMT (1<<7) +#define BT848_VTC_VFILT_2TAP 0 +#define BT848_VTC_VFILT_3TAP 1 +#define BT848_VTC_VFILT_4TAP 2 +#define BT848_VTC_VFILT_5TAP 3 + +#define BT848_SRESET 0x07C + +#define BT848_COLOR_FMT 0x0D4 +#define BT848_COLOR_FMT_O_RGB32 (0<<4) +#define BT848_COLOR_FMT_O_RGB24 (1<<4) +#define BT848_COLOR_FMT_O_RGB16 (2<<4) +#define BT848_COLOR_FMT_O_RGB15 (3<<4) +#define BT848_COLOR_FMT_O_YUY2 (4<<4) +#define BT848_COLOR_FMT_O_BtYUV (5<<4) +#define BT848_COLOR_FMT_O_Y8 (6<<4) +#define BT848_COLOR_FMT_O_RGB8 (7<<4) +#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) +#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) +#define BT848_COLOR_FMT_O_RAW (14<<4) +#define BT848_COLOR_FMT_E_RGB32 0 +#define BT848_COLOR_FMT_E_RGB24 1 +#define BT848_COLOR_FMT_E_RGB16 2 +#define BT848_COLOR_FMT_E_RGB15 3 +#define BT848_COLOR_FMT_E_YUY2 4 +#define BT848_COLOR_FMT_E_BtYUV 5 +#define BT848_COLOR_FMT_E_Y8 6 +#define BT848_COLOR_FMT_E_RGB8 7 +#define BT848_COLOR_FMT_E_YCrCb422 8 +#define BT848_COLOR_FMT_E_YCrCb411 9 +#define BT848_COLOR_FMT_E_RAW 14 + +#define BT848_COLOR_FMT_RGB32 0x00 +#define BT848_COLOR_FMT_RGB24 0x11 +#define BT848_COLOR_FMT_RGB16 0x22 +#define BT848_COLOR_FMT_RGB15 0x33 +#define BT848_COLOR_FMT_YUY2 0x44 +#define BT848_COLOR_FMT_BtYUV 0x55 +#define BT848_COLOR_FMT_Y8 0x66 +#define BT848_COLOR_FMT_RGB8 0x77 +#define BT848_COLOR_FMT_YCrCb422 0x88 +#define BT848_COLOR_FMT_YCrCb411 0x99 +#define BT848_COLOR_FMT_RAW 0xee + +#define BT848_VTOTAL_LO 0xB0 +#define BT848_VTOTAL_HI 0xB4 + +#define BT848_COLOR_CTL 0x0D8 +#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) +#define BT848_COLOR_CTL_COLOR_BARS (1<<6) +#define BT848_COLOR_CTL_RGB_DED (1<<5) +#define BT848_COLOR_CTL_GAMMA (1<<4) +#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) +#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) +#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) +#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) + +#define BT848_CAP_CTL 0x0DC +#define BT848_CAP_CTL_DITH_FRAME (1<<4) +#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) +#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) +#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) +#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) + +#define BT848_VBI_PACK_SIZE 0x0E0 + +#define BT848_VBI_PACK_DEL 0x0E4 +#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc +#define BT848_VBI_PACK_DEL_EXT_FRAME 2 +#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 + + +#define BT848_INT_STAT 0x100 +#define BT848_INT_MASK 0x104 + +#define BT848_INT_ETBF (1<<23) + +#define BT848_INT_RISCS (0xf<<28) +#define BT848_INT_RISC_EN (1<<27) +#define BT848_INT_RACK (1<<25) +#define BT848_INT_FIELD (1<<24) +#define BT848_INT_SCERR (1<<19) +#define BT848_INT_OCERR (1<<18) +#define BT848_INT_PABORT (1<<17) +#define BT848_INT_RIPERR (1<<16) +#define BT848_INT_PPERR (1<<15) +#define BT848_INT_FDSR (1<<14) +#define BT848_INT_FTRGT (1<<13) +#define BT848_INT_FBUS (1<<12) +#define BT848_INT_RISCI (1<<11) +#define BT848_INT_GPINT (1<<9) +#define BT848_INT_I2CDONE (1<<8) +#define BT848_INT_VPRES (1<<5) +#define BT848_INT_HLOCK (1<<4) +#define BT848_INT_OFLOW (1<<3) +#define BT848_INT_HSYNC (1<<2) +#define BT848_INT_VSYNC (1<<1) +#define BT848_INT_FMTCHG (1<<0) + + +#define BT848_GPIO_DMA_CTL 0x10C +#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) +#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) +#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) +#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) +#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) +#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) +#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) +#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) +#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) +#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) +#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) +#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) +#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) + +#define BT848_I2C 0x110 +#define BT878_I2C_MODE (1<<7) +#define BT878_I2C_RATE (1<<6) +#define BT878_I2C_NOSTOP (1<<5) +#define BT878_I2C_NOSTART (1<<4) +#define BT848_I2C_DIV (0xf<<4) +#define BT848_I2C_SYNC (1<<3) +#define BT848_I2C_W3B (1<<2) +#define BT848_I2C_SCL (1<<1) +#define BT848_I2C_SDA (1<<0) + +#define BT848_RISC_STRT_ADD 0x114 +#define BT848_GPIO_OUT_EN 0x118 +#define BT848_GPIO_REG_INP 0x11C +#define BT848_RISC_COUNT 0x120 +#define BT848_GPIO_DATA 0x200 + + +/* Bt848 RISC commands */ + +/* only for the SYNC RISC command */ +#define BT848_FIFO_STATUS_FM1 0x06 +#define BT848_FIFO_STATUS_FM3 0x0e +#define BT848_FIFO_STATUS_SOL 0x02 +#define BT848_FIFO_STATUS_EOL4 0x01 +#define BT848_FIFO_STATUS_EOL3 0x0d +#define BT848_FIFO_STATUS_EOL2 0x09 +#define BT848_FIFO_STATUS_EOL1 0x05 +#define BT848_FIFO_STATUS_VRE 0x04 +#define BT848_FIFO_STATUS_VRO 0x0c +#define BT848_FIFO_STATUS_PXV 0x00 + +#define BT848_RISC_RESYNC (1<<15) + +/* WRITE and SKIP */ +/* disable which bytes of each DWORD */ +#define BT848_RISC_BYTE0 (1U<<12) +#define BT848_RISC_BYTE1 (1U<<13) +#define BT848_RISC_BYTE2 (1U<<14) +#define BT848_RISC_BYTE3 (1U<<15) +#define BT848_RISC_BYTE_ALL (0x0fU<<12) +#define BT848_RISC_BYTE_NONE 0 +/* cause RISCI */ +#define BT848_RISC_IRQ (1U<<24) +/* RISC command is last one in this line */ +#define BT848_RISC_EOL (1U<<26) +/* RISC command is first one in this line */ +#define BT848_RISC_SOL (1U<<27) + +#define BT848_RISC_WRITE (0x01U<<28) +#define BT848_RISC_SKIP (0x02U<<28) +#define BT848_RISC_WRITEC (0x05U<<28) +#define BT848_RISC_JUMP (0x07U<<28) +#define BT848_RISC_SYNC (0x08U<<28) + +#define BT848_RISC_WRITE123 (0x09U<<28) +#define BT848_RISC_SKIP123 (0x0aU<<28) +#define BT848_RISC_WRITE1S23 (0x0bU<<28) + + +/* Bt848A and higher only !! */ +#define BT848_TGLB 0x080 +#define BT848_TGCTRL 0x084 +#define BT848_FCAP 0x0E8 +#define BT848_PLL_F_LO 0x0F0 +#define BT848_PLL_F_HI 0x0F4 + +#define BT848_PLL_XCI 0x0F8 +#define BT848_PLL_X (1<<7) +#define BT848_PLL_C (1<<6) + +#define BT848_DVSIF 0x0FC + +/* Bt878 register */ + +#define BT878_DEVCTRL 0x40 +#define BT878_EN_TBFX 0x02 +#define BT878_EN_VSFX 0x04 + +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_ttusbir/lirc_ttusbir.c +++ linux-2.6.27/ubuntu/lirc/lirc_ttusbir/lirc_ttusbir.c @@ -0,0 +1,401 @@ +/**************************************************************************** + ** lirc_ttusbir.c *********************************************************** + **************************************************************************** + * + * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver + * + * Copyright (C) 2007 Stefan Macher + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This LIRC driver provides access to the TechnoTrend USB IR Receiver. + * The receiver delivers the IR signal as raw sampled true/false data in + * isochronous USB packets each of size 128 byte. + * Currently the driver reduces the sampling rate by factor of 8 as this + * is still more than enough to decode RC-5 - others should be analyzed. + * But the driver does not rely on RC-5 it should be able to decode every + * IR signal that is not too fast. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "lirc.h" +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC"); +MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)"); +MODULE_LICENSE("GPL"); + +/* #define DEBUG */ +#ifdef DEBUG +#define DPRINTK printk +#else +#define DPRINTK(_x_, a...) +#endif + +/* function declarations */ +static int probe(struct usb_interface *intf, const struct usb_device_id *id); +static void disconnect(struct usb_interface *intf); +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void urb_complete(struct urb *urb, struct pt_regs *pt_regs); +#else +static void urb_complete(struct urb *urb); +#endif +static int set_use_inc(void *data); +static void set_use_dec(void *data); + +static int num_urbs = 2; +module_param(num_urbs, int, 0444); +MODULE_PARM_DESC(num_urbs, + "Number of URBs in queue. Try to increase to 4 in case " + "of problems (default: 2; minimum: 2)"); + +/* table of devices that work with this driver */ +static struct usb_device_id device_id_table[] = { + { USB_DEVICE(0x0B48, 0x2003) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, device_id_table); + +/* USB driver definition */ +static struct usb_driver driver = { + .name = "TTUSBIR", + .id_table = &(device_id_table[0]), + .probe = probe, + .disconnect = disconnect, +}; + +/* USB device definition */ +struct ttusbir_device { + struct usb_driver *driver; + struct usb_device *udev; + struct usb_interface *interf; + struct usb_class_driver class_driver; + unsigned int ifnum; /* Interface number to use */ + unsigned int alt_setting; /* alternate setting to use */ + unsigned int endpoint; /* Endpoint to use */ + struct urb **urb; /* num_urb URB pointers*/ + char **buffer; /* 128 byte buffer for each URB */ + struct lirc_buffer rbuf; /* Buffer towards LIRC */ + struct lirc_plugin plugin; + int minor; + int last_pulse; /* remembers if last received byte was pulse or space */ + int last_num; /* remembers how many last bytes appeared */ + int opened; +}; + +/************************************* + * LIRC specific functions + */ +static int set_use_inc(void *data) +{ + int i; + struct ttusbir_device *ttusbir = data; + + DPRINTK("Sending first URBs\n"); + /* @TODO Do I need to check if I am already opened */ + ttusbir->opened = 1; + + for (i = 0; i < num_urbs; i++) + usb_submit_urb(ttusbir->urb[i], GFP_KERNEL); + + return 0; +} + +static void set_use_dec(void *data) +{ + struct ttusbir_device *ttusbir = data; + + DPRINTK("Device closed\n"); + + ttusbir->opened = 0; +} + +/************************************* + * USB specific functions + */ + +/* This mapping table is used to do a very simple filtering of the + * input signal. + * For a value with at least 4 bits set it returns 0xFF otherwise + * 0x00. For faster IR signals this can not be used. But for RC-5 we + * still have about 14 samples per pulse/space, i.e. we sample with 14 + * times higher frequency than the signal frequency */ +const unsigned char map_table[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void urb_complete(struct urb *urb, struct pt_regs *pt_regs) +#else +static void urb_complete(struct urb *urb) +#endif +{ + struct ttusbir_device *ttusbir; + unsigned char *buf; + int i; + lirc_t l; + + ttusbir = urb->context; + + if (!ttusbir->opened) + return; + + buf = (unsigned char *)urb->transfer_buffer; + + for (i = 0; i < 128; i++) { + /* Here we do the filtering and some kind of down sampling */ + buf[i] = ~map_table[buf[i]]; + if (ttusbir->last_pulse == buf[i]) { + if (ttusbir->last_num < PULSE_MASK/63) + ttusbir->last_num++; + /* else we are in a idle period and do not need to + * increment any longer */ + } else { + l = ttusbir->last_num * 62; /* about 62 = us/byte */ + if (ttusbir->last_pulse) /* pulse or space? */ + l |= PULSE_BIT; + if (!lirc_buffer_full(&ttusbir->rbuf)) { + lirc_buffer_write_1(&ttusbir->rbuf, (void *)&l); + wake_up_interruptible(&ttusbir->rbuf.wait_poll); + } + ttusbir->last_num = 0; + ttusbir->last_pulse = buf[i]; + } + } + usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */ +} + +/* Called whenever the USB subsystem thinks we could be the right driver + to handle this device +*/ +static int probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int alt_set, endp; + int found = 0; + int i, j; + int struct_size; + struct usb_host_interface *host_interf; + struct usb_interface_descriptor *interf_desc; + struct usb_host_endpoint *host_endpoint; + struct ttusbir_device *ttusbir; + + DPRINTK("Module ttusbir probe\n"); + + /* To reduce memory fragmentation we use only one allocation */ + struct_size = sizeof(struct ttusbir_device) + + (sizeof(struct urb *) * num_urbs) + + (sizeof(char *) * num_urbs) + + (num_urbs * 128); + ttusbir = kmalloc(struct_size, GFP_KERNEL); + if (!ttusbir) + return -ENOMEM; + memset(ttusbir, 0, struct_size); + + ttusbir->urb = (struct urb **)((char *)ttusbir + + sizeof(struct ttusbir_device)); + ttusbir->buffer = (char **)((char *)ttusbir->urb + + (sizeof(struct urb *) * num_urbs)); + for (i = 0; i < num_urbs; i++) + ttusbir->buffer[i] = (char *)ttusbir->buffer + + (sizeof(char *)*num_urbs) + (i * 128); + + ttusbir->driver = &driver; + ttusbir->alt_setting = -1; + /* @TODO check if error can be returned */ + ttusbir->udev = usb_get_dev(interface_to_usbdev(intf)); + ttusbir->interf = intf; + ttusbir->last_pulse = 0x00; + ttusbir->last_num = 0; + + /* Now look for interface setting we can handle + We are searching for the alt setting where end point + 0x82 has max packet size 16 + */ + for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) { + host_interf = &intf->altsetting[alt_set]; + interf_desc = &host_interf->desc; + for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) { + host_endpoint = &host_interf->endpoint[endp]; + if ((host_endpoint->desc.bEndpointAddress == 0x82) && + (host_endpoint->desc.wMaxPacketSize == 0x10)) { + ttusbir->alt_setting = alt_set; + ttusbir->endpoint = endp; + found = 1; + break; + } + } + } + if (ttusbir->alt_setting != -1) + DPRINTK("alt setting: %d\n", ttusbir->alt_setting); + else { + err("Could not find alternate setting\n"); + kfree(ttusbir); + return -EINVAL; + } + + /* OK lets setup this interface setting */ + usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting); + + /* Store device info in interface structure */ + usb_set_intfdata(intf, ttusbir); + + /* Register as a LIRC plugin */ + if (lirc_buffer_init(&ttusbir->rbuf, sizeof(lirc_t), 256) < 0) { + err("Could not get memory for LIRC data buffer\n"); + usb_set_intfdata(intf, NULL); + kfree(ttusbir); + return -ENOMEM; + } + strcpy(ttusbir->plugin.name, "TTUSBIR"); + ttusbir->plugin.minor = -1; + ttusbir->plugin.code_length = 1; + ttusbir->plugin.sample_rate = 0; + ttusbir->plugin.data = ttusbir; + ttusbir->plugin.add_to_buf = NULL; + ttusbir->plugin.get_queue = NULL; + ttusbir->plugin.rbuf = &ttusbir->rbuf; + ttusbir->plugin.set_use_inc = set_use_inc; + ttusbir->plugin.set_use_dec = set_use_dec; + ttusbir->plugin.ioctl = NULL; + ttusbir->plugin.fops = NULL; + ttusbir->plugin.owner = THIS_MODULE; + ttusbir->plugin.features = LIRC_CAN_REC_MODE2; + ttusbir->minor = lirc_register_plugin(&ttusbir->plugin); + if (ttusbir->minor < 0) { + err("Error registering as LIRC plugin\n"); + usb_set_intfdata(intf, NULL); + lirc_buffer_free(&ttusbir->rbuf); + kfree(ttusbir); + return -EIO; + } + + /* Allocate and setup the URB that we will use to talk to the device */ + for (i = 0; i < num_urbs; i++) { + ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL); + if (!ttusbir->urb[i]) { + err("Could not allocate memory for the URB\n"); + for (j = i - 1; j >= 0; j--) + kfree(ttusbir->urb[j]); + lirc_buffer_free(&ttusbir->rbuf); + lirc_unregister_plugin(ttusbir->minor); + kfree(ttusbir); + usb_set_intfdata(intf, NULL); + return -ENOMEM; + } + ttusbir->urb[i]->dev = ttusbir->udev; + ttusbir->urb[i]->context = ttusbir; + ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev, + ttusbir->endpoint); + ttusbir->urb[i]->interval = 1; + ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP; + ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0]; + ttusbir->urb[i]->complete = urb_complete; + ttusbir->urb[i]->number_of_packets = 8; + ttusbir->urb[i]->transfer_buffer_length = 128; + for (j = 0; j < 8; j++) { + ttusbir->urb[i]->iso_frame_desc[j].offset = j*16; + ttusbir->urb[i]->iso_frame_desc[j].length = 16; + } + } + return 0; +} + +/* Called when the driver is unloaded or the device is unplugged + */ +static void disconnect(struct usb_interface *intf) +{ + int i; + struct ttusbir_device *ttusbir; + + DPRINTK("Module ttusbir disconnect\n"); + + ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + lirc_unregister_plugin(ttusbir->minor); + DPRINTK("unregistered\n"); + + for (i = 0; i < num_urbs; i++) { + usb_kill_urb(ttusbir->urb[i]); + usb_free_urb(ttusbir->urb[i]); + } + DPRINTK("URBs killed\n"); + lirc_buffer_free(&ttusbir->rbuf); + kfree(ttusbir); +} + +static int ttusbir_init_module(void) +{ + int result; + + DPRINTK(KERN_DEBUG "Module ttusbir init\n"); + + /* register this driver with the USB subsystem */ + result = usb_register(&driver); + if (result) + err("usb_register failed. Error number %d", result); + return result; +} + +static void ttusbir_exit_module(void) +{ + printk(KERN_DEBUG "Module ttusbir exit\n"); + /* deregister this driver with the USB subsystem */ + usb_deregister(&driver); +} + +module_init(ttusbir_init_module); +module_exit(ttusbir_exit_module); --- linux-2.6.27.orig/ubuntu/lirc/lirc_ttusbir/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_ttusbir/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_imon/lirc_imon.c +++ linux-2.6.27/ubuntu/lirc/lirc_imon/lirc_imon.c @@ -0,0 +1,1524 @@ +/* + * lirc_imon.c: LIRC plugin/VFD driver for Ahanix/Soundgraph IMON IR/VFD + * + * $Id: lirc_imon.c,v 1.23 2008/01/19 10:06:46 lirc Exp $ + * + * Version 0.3 + * Supports newer iMON models that send decoded IR signals. + * This includes the iMON PAD model. + * Removed module option for vfd_proto_6p. This driver supports + * multiple iMON devices so it is meaningless to have + * a global option to set protocol variants. + * + * Version 0.2 beta 2 [January 31, 2005] + * USB disconnect/reconnect no longer causes problems for lircd + * + * Version 0.2 beta 1 [January 29, 2005] + * Added support for original iMON receiver(ext USB) + * + * Version 0.2 alpha 2 [January 24, 2005] + * Added support for VFDs with 6-packet protocol + * + * Version 0.2 alpha 1 [January 23, 2005] + * Added support for 2.6 kernels + * Reworked disconnect handling + * Incorporated Changwoo Ryu's algorithm + * + * Version 0.1 alpha 1[July 5, 2004] + * + * Copyright(C) 2004 Venky Raju(dev@venky.ws) + * + * lirc_imon is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 22) +#error "*** Sorry, this driver requires kernel version 2.4.22 or higher" +#endif + +#include + +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#include + +#include "kcompat.h" +#include "lirc.h" +#include "lirc_dev/lirc_dev.h" + + +#define MOD_AUTHOR "Venky Raju " +#define MOD_DESC "Driver for Soundgraph iMON MultiMedia IR/VFD w/imon pad2keys patch" +#define MOD_NAME "lirc_imon" +#define MOD_VERSION "0.3p2k" + +#define VFD_MINOR_BASE 144 /* Same as LCD */ +#define DEVFS_MODE (S_IFCHR | S_IRUSR | S_IWUSR | \ + S_IRGRP | S_IWGRP | S_IROTH) +#define DEVFS_NAME LIRC_DEVFS_PREFIX "lcd%d" + +#define BUF_CHUNK_SIZE 4 +#define BUF_SIZE 128 + +#define BIT_DURATION 250 /* each bit received is 250us */ + +#define SUCCESS 0 +#define TRUE 1 +#define FALSE 0 + +#define CURSOR_LIMIT 16 + +/* ------------------------------------------------------------ + * P R O T O T Y P E S + * ------------------------------------------------------------ + */ + +/* USB Callback prototypes */ +#ifdef KERNEL_2_5 +static int imon_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void imon_disconnect(struct usb_interface *interface); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_rx_callback(struct urb *urb, struct pt_regs *regs); +static void usb_tx_callback(struct urb *urb, struct pt_regs *regs); +#else +static void usb_rx_callback(struct urb *urb); +static void usb_tx_callback(struct urb *urb); +#endif +#else +static void *imon_probe(struct usb_device *dev, unsigned int intf, + const struct usb_device_id *id); +static void imon_disconnect(struct usb_device *dev, void *data); +static void usb_rx_callback(struct urb *urb); +static void usb_tx_callback(struct urb *urb); +#endif + +/* VFD file_operations function prototypes */ +static int vfd_open(struct inode *inode, struct file *file); +static int vfd_close(struct inode *inode, struct file *file); +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/* LCD file_operations override function prototypes */ +static ssize_t lcd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/* LIRC plugin function prototypes */ +static int ir_open(void *data); +static void ir_close(void *data); + +/* Driver init/exit prototypes */ +static int __init imon_init(void); +static void __exit imon_exit(void); + +/* ------------------------------------------------------------ + * G L O B A L S + * ------------------------------------------------------------ + */ + +struct imon_context { + struct usb_device *dev; + int vfd_supported; /* not all controllers do */ + int vfd_isopen; /* VFD port has been opened */ +#if !defined(KERNEL_2_5) + int subminor; /* index into minor_table */ + devfs_handle_t devfs; +#endif + int ir_isopen; /* IR port open */ + int ir_isassociating; /* IR port open for association */ + int dev_present; /* USB device presence */ + struct semaphore sem; /* to lock this object */ + wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ + + int vfd_proto_6p; /* VFD requires 6th packet */ + int ir_onboard_decode; /* IR signals decoded onboard */ + + struct lirc_plugin *plugin; + struct usb_endpoint_descriptor *rx_endpoint; + struct usb_endpoint_descriptor *tx_endpoint; + struct urb *rx_urb; + struct urb *tx_urb; + unsigned char usb_rx_buf[8]; + unsigned char usb_tx_buf[8]; + + struct rx_data { + int count; /* length of 0 or 1 sequence */ + int prev_bit; /* logic level of sequence */ + int initial_space; /* initial space flag */ + } rx; + + struct tx_t { + unsigned char data_buf[35]; /* user data buffer */ + struct completion finished; /* wait for write to finish */ + atomic_t busy; /* write in progress */ + int status; /* status of tx completion */ + } tx; + + int key_x; + int key_y; + int last_count; /* number of times pressed */ +}; + +#define LOCK_CONTEXT down(&context->sem) +#define UNLOCK_CONTEXT up(&context->sem) + +/* VFD file operations */ +static struct file_operations vfd_fops = { + .owner = THIS_MODULE, + .open = &vfd_open, + .write = &vfd_write, + .release = &vfd_close +}; + +/* USB Device ID for IMON USB Control Board */ +static struct usb_device_id imon_usb_id_table[] = { + { USB_DEVICE(0x0aa8, 0xffda) }, /* IR & VFD */ + { USB_DEVICE(0x0aa8, 0x8001) }, /* IR only */ + { USB_DEVICE(0x15c2, 0xffda) }, /* IR & VFD */ + { USB_DEVICE(0x15c2, 0xffdc) }, /* IR & VFD */ + { USB_DEVICE(0x04e8, 0xff30) }, /* ext IR only */ + {} +}; + +/* Some iMON VFD models requires a 6th packet */ +static unsigned short vfd_proto_6p_vendor_list[] = { + /* terminate this list with a 0 */ + 0x15c2, + 0 }; +static unsigned char vfd_packet6[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; + +/* Newer iMON models decode the signal onboard */ +static unsigned short ir_onboard_decode_product_list[] = { + /* terminate this list with a 0 */ + 0xffdc, + 0 }; + +/* USB Device data */ +static struct usb_driver imon_driver = { + LIRC_THIS_MODULE(.owner = THIS_MODULE) + .name = MOD_NAME, + .probe = imon_probe, + .disconnect = imon_disconnect, + .id_table = imon_usb_id_table, +#if !defined(KERNEL_2_5) + .fops = &vfd_fops, + .minor = VFD_MINOR_BASE, +#endif +}; + +#ifdef KERNEL_2_5 +static struct usb_class_driver imon_class = { + .name = DEVFS_NAME, + .fops = &vfd_fops, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) + .mode = DEVFS_MODE, +#endif + .minor_base = VFD_MINOR_BASE, +}; +#endif + +/* to prevent races between open() and disconnect() */ +static DECLARE_MUTEX(disconnect_sem); + +static int debug; +#ifdef LIRC_IMON_LCD +static int is_lcd = 1; +#else +static int is_lcd; /* If LIRC_IMON_LCD not defined, default to non-LCD */ +#endif + +/* pad2keys module parameter. pad2keys patch active? */ +static int pad2keys_active = 0; + +#if !defined(KERNEL_2_5) + +#define MAX_DEVICES 4 /* In case there's more than one iMON device */ +static struct imon_context *minor_table[MAX_DEVICES]; + +/* +static DECLARE_MUTEX(minor_table_sem); +#define LOCK_MINOR_TABLE down(&minor_table_sem) +#define UNLOCK_MINOR_TABLE up(&minor_table_sem) +*/ + +/* the global usb devfs handle */ +extern devfs_handle_t usb_devfs_handle; + +#endif + +/* ------------------------------------------------------------ + * M O D U L E C O D E + * ------------------------------------------------------------ + */ + +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_DESCRIPTION(MOD_DESC); +MODULE_VERSION(MOD_VERSION); /* MBr: was missing */ +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, imon_usb_id_table); + +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); + +#ifdef LIRC_IMON_LCD +module_param(is_lcd, int, 1); +MODULE_PARM_DESC(is_lcd, "The device is an LCD: 0=no (it's a VFD), " + "1=yes (default:yes)"); +#else +module_param(is_lcd, int, 0); +MODULE_PARM_DESC(is_lcd, "The device is an LCD: 0=no (it's a VFD), " + "1=yes (default:no)"); +#endif +module_param (pad2keys_active, int, 0); +MODULE_PARM_DESC (pad2keys_active, "pad2keys patch active: 0=no, 1=yes (default: no)"); + +static inline void delete_context(struct imon_context *context) +{ + if (context->vfd_supported) + usb_free_urb(context->tx_urb); + usb_free_urb(context->rx_urb); + lirc_buffer_free(context->plugin->rbuf); + kfree(context->plugin->rbuf); + kfree(context->plugin); + kfree(context); + + if (debug) + info("%s: context deleted", __FUNCTION__); +} + +static inline void deregister_from_lirc(struct imon_context *context) +{ + int retval; + int minor = context->plugin->minor; + + retval = lirc_unregister_plugin(minor); + if (retval) + err("%s: unable to deregister from lirc(%d)", + __FUNCTION__, retval); + else + info("Deregistered iMON plugin(minor:%d)", minor); + +} + +/** + * Called when the VFD device(e.g. /dev/usb/lcd) + * is opened by the application. + */ +static int vfd_open(struct inode *inode, struct file *file) +{ +#ifdef KERNEL_2_5 + struct usb_interface *interface; +#endif + struct imon_context *context = NULL; + int subminor; + int retval = SUCCESS; + + /* prevent races with disconnect */ + down(&disconnect_sem); + +#ifdef KERNEL_2_5 + subminor = iminor(inode); + interface = usb_find_interface(&imon_driver, subminor); + if (!interface) { + err("%s: could not find interface for minor %d", + __FUNCTION__, subminor); + retval = -ENODEV; + goto exit; + } + context = usb_get_intfdata(interface); +#else + subminor = MINOR(inode->i_rdev) - VFD_MINOR_BASE; + if (subminor < 0 || subminor >= MAX_DEVICES) { + err("%s: no record of minor %d", __FUNCTION__, subminor); + retval = -ENODEV; + goto exit; + } + context = minor_table[subminor]; +#endif + + if (!context) { + err("%s: no context found for minor %d", + __FUNCTION__, subminor); + retval = -ENODEV; + goto exit; + } + + LOCK_CONTEXT; + + if (!context->vfd_supported) { + err("%s: VFD not supported by device", __FUNCTION__); + retval = -ENODEV; + } else if (context->vfd_isopen) { + err("%s: VFD port is already open", __FUNCTION__); + retval = -EBUSY; + } else { + MOD_INC_USE_COUNT; + context->vfd_isopen = TRUE; + file->private_data = context; + info("VFD port opened"); + } + + UNLOCK_CONTEXT; + +exit: + up(&disconnect_sem); + return retval; +} + +/** + * Called when the VFD device(e.g. /dev/usb/lcd) + * is closed by the application. + */ +static int vfd_close(struct inode *inode, struct file *file) +{ + struct imon_context *context = NULL; + int retval = SUCCESS; + + context = (struct imon_context *) file->private_data; + + if (!context) { + err("%s: no context for device", __FUNCTION__); + return -ENODEV; + } + + LOCK_CONTEXT; + + if (!context->vfd_supported) { + err("%s: VFD not supported by device", __FUNCTION__); + retval = -ENODEV; + } else if (!context->vfd_isopen) { + err("%s: VFD is not open", __FUNCTION__); + retval = -EIO; + } else { + context->vfd_isopen = FALSE; + MOD_DEC_USE_COUNT; + info("VFD port closed"); + if (!context->dev_present && !context->ir_isopen) { + /* Device disconnected before close and IR port is not + * open. If IR port is open, context will be deleted by + * ir_close. */ + UNLOCK_CONTEXT; + delete_context(context); + return retval; + } + } + + UNLOCK_CONTEXT; + return retval; +} + +/** + * Sends a packet to the VFD. + */ +static inline int send_packet(struct imon_context *context) +{ + unsigned int pipe; + int interval = 0; + int retval = SUCCESS; + + pipe = usb_sndintpipe(context->dev, + context->tx_endpoint->bEndpointAddress); +#ifdef KERNEL_2_5 + interval = context->tx_endpoint->bInterval; +#endif /* Use 0 for 2.4 kernels */ + + usb_fill_int_urb(context->tx_urb, context->dev, pipe, + context->usb_tx_buf, sizeof(context->usb_tx_buf), + usb_tx_callback, context, interval); + + context->tx_urb->actual_length = 0; + + init_completion(&context->tx.finished); + atomic_set(&(context->tx.busy), 1); + +#ifdef KERNEL_2_5 + retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); +#else + retval = usb_submit_urb(context->tx_urb); +#endif + if (retval != SUCCESS) { + atomic_set(&(context->tx.busy), 0); + err("%s: error submitting urb(%d)", __FUNCTION__, retval); + } else { + /* Wait for tranmission to complete(or abort) */ + UNLOCK_CONTEXT; + wait_for_completion(&context->tx.finished); + LOCK_CONTEXT; + + retval = context->tx.status; + if (retval != SUCCESS) + err("%s: packet tx failed(%d)", __FUNCTION__, retval); + } + + return retval; +} + +/** + * Sends an associate packet to the iMON 2.4G. + * + * This might not be such a good idea, since it has an id + * collition with some versions of the "IR & VFD" combo. + * The only way to determine if it is a RF version is to look + * at the product description string.(Which we currently do + * not fetch). + */ +static inline int send_associate_24g(struct imon_context *context) +{ + int retval; + const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20 }; + + if (!context) { + err("%s: no context for device", __FUNCTION__); + return -ENODEV; + } + + LOCK_CONTEXT; + + if (!context->dev_present) { + err("%s: no iMON device present", __FUNCTION__); + retval = -ENODEV; + goto exit; + } + + memcpy(context->usb_tx_buf, packet, sizeof(packet)); + retval = send_packet(context); + +exit: + UNLOCK_CONTEXT; + + return retval; +} + +#ifdef KERNEL_2_5 +/** + * This is the sysfs functions to handle the association og the iMON 2.4G LT. + * + * + */ + +static ssize_t show_associate_remote(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct imon_context *context = dev_get_drvdata(d); + + if (!context) + return -ENODEV; + + if (context->ir_isassociating) { + strcpy(buf, "The device it associating press some button " + "on the remote.\n"); + } else if (context->ir_isopen) { + strcpy(buf, "Device is open and ready to associate.\n" + "Echo something into this file to start " + "the process.\n"); + } else { + strcpy(buf, "Device is closed, you need to open it to " + "associate the remote(you can use irw).\n"); + } + return strlen(buf); +} + +static ssize_t store_associate_remote(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct imon_context *context; + + context = dev_get_drvdata(d); + + if (!context) + return -ENODEV; + + if (!context->ir_isopen) + return -EINVAL; + + if (context->ir_isopen) { + context->ir_isassociating = TRUE; + send_associate_24g(context); + } + + return count; +} + +static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote, + store_associate_remote); + +static struct attribute *imon_sysfs_entries[] = { + &dev_attr_associate_remote.attr, + NULL +}; + +static struct attribute_group imon_attribute_group = { + .attrs = imon_sysfs_entries +}; + +#endif + + + +/** + * Writes data to the VFD. The IMON VFD is 2x16 characters + * and requires data in 5 consecutive USB interrupt packets, + * each packet but the last carrying 7 bytes. + * + * I don't know if the VFD board supports features such as + * scrolling, clearing rows, blanking, etc. so at + * the caller must provide a full screen of data. If fewer + * than 32 bytes are provided spaces will be appended to + * generate a full screen. + */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int i; + int offset; + int seq; + int retval = SUCCESS; + struct imon_context *context; + + context = (struct imon_context *) file->private_data; + if (!context) { + err("%s: no context for device", __FUNCTION__); + return -ENODEV; + } + + LOCK_CONTEXT; + + if (!context->dev_present) { + err("%s: no iMON device present", __FUNCTION__); + retval = -ENODEV; + goto exit; + } + + if (n_bytes <= 0 || n_bytes > 32) { + err("%s: invalid payload size", __FUNCTION__); + retval = -EINVAL; + goto exit; + } + + if (copy_from_user(context->tx.data_buf, buf, n_bytes)) + return -EFAULT; + + /* Pad with spaces */ + for (i = n_bytes; i < 32; ++i) + context->tx.data_buf[i] = ' '; + + for (i = 32; i < 35; ++i) + context->tx.data_buf[i] = 0xFF; + + offset = 0; + seq = 0; + + do { + memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7); + context->usb_tx_buf[7] = (unsigned char) seq; + + retval = send_packet(context); + if (retval != SUCCESS) { + err("%s: send packet failed for packet #%d", + __FUNCTION__, seq/2); + goto exit; + } else { + seq += 2; + offset += 7; + } + + } while (offset < 35); + + if (context->vfd_proto_6p) { + /* Send packet #6 */ + memcpy(context->usb_tx_buf, vfd_packet6, 7); + context->usb_tx_buf[7] = (unsigned char) seq; + retval = send_packet(context); + if (retval != SUCCESS) + err("%s: send packet failed for packet #%d", + __FUNCTION__, seq/2); + } + +exit: + UNLOCK_CONTEXT; + + return(retval == SUCCESS) ? n_bytes : retval; +} + +/** + * Writes data to the LCD. The iMON OEM LCD screen excepts 8-byte + * packets. We accept data as 16 hexadecimal digits, followed by a + * newline (to make it easy to drive the device from a command-line + * -- even though the actual binary data is a bit complicated). + * + * The device itself is not a "traditional" text-mode display. It's + * actually a 16x96 pixel bitmap display. That means if you want to + * display text, you've got to have your own "font" and translate the + * text into bitmaps for display. This is really flexible (you can + * display whatever diacritics you need, and so on), but it's also + * a lot more complicated than most LCDs... + */ +static ssize_t lcd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int retval = SUCCESS; + struct imon_context *context; + + context = (struct imon_context *) file->private_data; + if (!context) { + err("%s: no context for device", __FUNCTION__); + return -ENODEV; + } + + LOCK_CONTEXT; + + if (!context->dev_present) { + err("%s: no iMON device present", __FUNCTION__); + retval = -ENODEV; + goto exit; + } + + if (n_bytes != 8) { + err("%s: invalid payload size: %d (expecting 8)", + __FUNCTION__, (int) n_bytes); + retval = -EINVAL; + goto exit; + } + + if (copy_from_user(context->usb_tx_buf, buf, 8)) + return -EFAULT; + + retval = send_packet(context); + if (retval != SUCCESS) { + err("%s: send packet failed!", + __FUNCTION__); + goto exit; + } else if (debug) { + info("%s: write %d bytes to LCD", __FUNCTION__, (int) n_bytes); + } +exit: + UNLOCK_CONTEXT; + return (retval == SUCCESS) ? n_bytes : retval; +} + +/** + * Callback function for USB core API: transmit data + */ +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_tx_callback(struct urb *urb, struct pt_regs *regs) +#else +static void usb_tx_callback(struct urb *urb) +#endif +{ + struct imon_context *context; + + if (!urb) + return; + context = (struct imon_context *) urb->context; + if (!context) + return; + + context->tx.status = urb->status; + + /* notify waiters that write has finished */ + atomic_set(&context->tx.busy, 0); + complete(&context->tx.finished); + + return; +} + +/** + * Called by lirc_dev when the application opens /dev/lirc + */ +static int ir_open(void *data) +{ + int retval = SUCCESS; + struct imon_context *context; + + /* prevent races with disconnect */ + down(&disconnect_sem); + + context = (struct imon_context *) data; + + LOCK_CONTEXT; + + if (context->ir_isopen) { + err("%s: IR port is already open", __FUNCTION__); + retval = -EBUSY; + goto exit; + } + + /* initial IR protocol decode variables */ + context->rx.count = 0; + context->rx.initial_space = 1; + context->rx.prev_bit = 0; + + /* init pad context for pad2keys */ + context ->key_x = 0; + context ->key_y = 0; + context ->last_count = 0; + + usb_fill_int_urb(context->rx_urb, context->dev, + usb_rcvintpipe(context->dev, + context->rx_endpoint->bEndpointAddress), + context->usb_rx_buf, sizeof(context->usb_rx_buf), + usb_rx_callback, context, context->rx_endpoint->bInterval); + +#ifdef KERNEL_2_5 + retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); +#else + retval = usb_submit_urb(context->rx_urb); +#endif + + if (retval) + err("%s: usb_submit_urb failed for ir_open(%d)", + __FUNCTION__, retval); + else { + MOD_INC_USE_COUNT; + context->ir_isopen = TRUE; + info("IR port opened"); + } + +exit: + UNLOCK_CONTEXT; + + up(&disconnect_sem); + return SUCCESS; +} + +/** + * Called by lirc_dev when the application closes /dev/lirc + */ +static void ir_close(void *data) +{ + struct imon_context *context; + + context = (struct imon_context *)data; + if (!context) { + err("%s: no context for device", __FUNCTION__); + return; + } + + LOCK_CONTEXT; + + usb_kill_urb(context->rx_urb); + context->ir_isopen = FALSE; + context->ir_isassociating = FALSE; + MOD_DEC_USE_COUNT; + info("IR port closed"); + + if (!context->dev_present) { + /* Device disconnected while IR port was + * still open. Plugin was not deregistered + * at disconnect time, so do it now. */ + deregister_from_lirc(context); + + if (!context->vfd_isopen) { + UNLOCK_CONTEXT; + delete_context(context); + return; + } + /* If VFD port is open, context will be deleted by vfd_close */ + } + + UNLOCK_CONTEXT; + return; +} + +/** + * Convert bit count to time duration(in us) and submit + * the value to lirc_dev. + */ +static inline void submit_data(struct imon_context *context) +{ + unsigned char buf[4]; + int value = context->rx.count; + int i; + + if (debug) + info("submitting data to LIRC\n"); + + value *= BIT_DURATION; + value &= PULSE_MASK; + if (context->rx.prev_bit) + value |= PULSE_BIT; + + for (i = 0; i < 4; ++i) + buf[i] = value>>(i*8); + + lirc_buffer_write_1(context->plugin->rbuf, buf); + wake_up(&context->plugin->rbuf->wait_poll); + return; +} + +/** + * Process the incoming packet + */ +static inline void incoming_packet(struct imon_context *context, + struct urb *urb) +{ + int len = urb->actual_length; + unsigned char *buf = urb->transfer_buffer; + int octet, bit; + unsigned char mask; + int chunk_num; +#ifdef DEBUG + int i; +#endif + + if (len != 8) { + warn("%s: invalid incoming packet size(%d)", + __FUNCTION__, len); + return; + } + + /* iMON 2.4G associate frame */ + if (buf[0] == 0x00 && + buf[2] == 0xFF && /* REFID */ + buf[3] == 0xFF && + buf[4] == 0xFF && + buf[5] == 0xFF && /* iMON 2.4G */ + ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */ + (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ + warn("%s: remote associated refid=%02X", __FUNCTION__, buf[1]); + context->ir_isassociating = FALSE; + } + + chunk_num = buf[7]; + + if (chunk_num == 0xFF) + return; /* filler frame, no data here */ + + if (buf[0] == 0xFF && + buf[1] == 0xFF && + buf[2] == 0xFF && + buf[3] == 0xFF && + buf[4] == 0xFF && + buf[5] == 0xFF && /* iMON 2.4G */ + ((buf[6] == 0x4E && buf[7] == 0xAF) || /* LT */ + (buf[6] == 0x5E && buf[7] == 0xAF))) /* DT */ + return; /* filler frame, no data here */ + +#ifdef DEBUG + for (i = 0; i < 8; ++i) + printk(KERN_INFO "%02x ", buf[i]); + printk(KERN_INFO "\n"); +#endif + + if (context->ir_onboard_decode) { + /* The signals have been decoded onboard the iMON controller */ + + if (pad2keys_active) + { + /* imon pad2keys patch + * + * make PAD and mouse buttons available for use with VDR, + * based on pad-mouse-emu patch from venky's forum + * + * last change: M.Brakemeier 2007-10-14 + * + * generated PAD key codes: + * Mouse_N 0x690281B7 + * Mouse_S 0x688291B7 + * Mouse_W 0x6A8281B7 + * Mouse_E 0x688A81B7 + * + * mouse buttons (non-synthetic): + * MouseRightClick 0x688481B7 + * MouseLeftClick 0x688301B7 + */ + if((buf[0] & 0x40) && + !(buf[1] & 0x01 || buf[1] >> 2 & 0x01)) + { + int rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; + int rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; + + if(buf[0] & 0x02) + rel_x |= ~0x10+1; + if(buf[0] & 0x01) + rel_y |= ~0x10+1; + + /* keyboard direction key emulation */ + if( context->last_count > 32 ) + { /* Hopefully eliminate drift*/ + context->last_count=0; + context->key_y=0; + context->key_x=0; + } + context->last_count++; + + /* limit decoded events */ + if(abs(context->key_x) > CURSOR_LIMIT || abs(context->key_y) > CURSOR_LIMIT ) + { + if(abs(context->key_y ) > abs(context->key_x)) + { /* mouse s/n */ + if(context->key_y > 0 && rel_y > 0) + { /* mouse s */ + buf[0] = 0x68; + buf[1] = 0x82; + buf[2] = 0x91; + } + else if(context->key_y < 0 && rel_y < 0) + { /* mouse n */ + buf[0] = 0x69; + buf[1] = 0x02; + buf[2] = 0x81; + } + } + else + { /* mouse e/w*/ + if(context->key_x > 0 && rel_x > 0 ) + { /* mouse e */ + buf[0] = 0x68; + buf[1] = 0x8A; + buf[2] = 0x81; + } + else if(context->key_x < 0 && rel_x < 0 ) + { /* mouse w */ + buf[0] = 0x6A; + buf[1] = 0x82; + buf[2] = 0x81; + } + } + } + else + { + context->key_x += rel_x; + context->key_y += rel_y; + + return; /* discard those key codes */ + } + } + /* a key was pressed, reset count */ + context->key_x = 0; + context->key_y = 0; + context->last_count = 0; + } + + lirc_buffer_write_1(context->plugin->rbuf, buf); + wake_up(&context->plugin->rbuf->wait_poll); + return; + } + + /* Translate received data to pulse and space lengths. + * Received data is active low, i.e. pulses are 0 and + * spaces are 1. + * + * My original algorithm was essentially similar to + * Changwoo Ryu's with the exception that he switched + * the incoming bits to active high and also fed an + * initial space to LIRC at the start of a new sequence + * if the previous bit was a pulse. + * + * I've decided to adopt his algorithm. */ + + if (chunk_num == 1 && context->rx.initial_space) { + /* LIRC requires a leading space */ + context->rx.prev_bit = 0; + context->rx.count = 4; + submit_data(context); + context->rx.count = 0; + } + + for (octet = 0; octet < 5; ++octet) { + mask = 0x80; + for (bit = 0; bit < 8; ++bit) { + int curr_bit = !(buf[octet] & mask); + if (curr_bit != context->rx.prev_bit) { + if (context->rx.count) { + submit_data(context); + context->rx.count = 0; + } + context->rx.prev_bit = curr_bit; + } + ++context->rx.count; + mask >>= 1; + } + } + + if (chunk_num == 10) { + if (context->rx.count) { + submit_data(context); + context->rx.count = 0; + } + context->rx.initial_space = context->rx.prev_bit; + } +} + +/** + * Callback function for USB core API: receive data + */ +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_rx_callback(struct urb *urb, struct pt_regs *regs) +#else +static void usb_rx_callback(struct urb *urb) +#endif +{ + struct imon_context *context; + + if (!urb) + return; + context = (struct imon_context *) urb->context; + if (!context) + return; + + switch (urb->status) { + case -ENOENT: /* usbcore unlink successful! */ + return; + case SUCCESS: + if (context->ir_isopen) + incoming_packet(context, urb); + break; + default : + warn("%s: status(%d): ignored", __FUNCTION__, urb->status); + break; + } + +#ifdef KERNEL_2_5 + usb_submit_urb(context->rx_urb, GFP_ATOMIC); +#endif + return; +} + + + +/** + * Callback function for USB core API: Probe + */ +#ifdef KERNEL_2_5 +static int imon_probe(struct usb_interface *interface, + const struct usb_device_id *id) +#else +static void *imon_probe(struct usb_device *dev, unsigned int intf, + const struct usb_device_id *id) +#endif +{ +#ifdef KERNEL_2_5 + struct usb_device *dev = NULL; + struct usb_host_interface *iface_desc = NULL; +#else + struct usb_interface *interface = NULL; + struct usb_interface_descriptor *iface_desc = NULL; + char name[10]; + int subminor = 0; +#endif + struct usb_endpoint_descriptor *rx_endpoint = NULL; + struct usb_endpoint_descriptor *tx_endpoint = NULL; + struct urb *rx_urb = NULL; + struct urb *tx_urb = NULL; + struct lirc_plugin *plugin = NULL; + struct lirc_buffer *rbuf = NULL; + int lirc_minor = 0; + int num_endpoints; + int retval = SUCCESS; + int vfd_ep_found; + int ir_ep_found; + int alloc_status; + int vfd_proto_6p = FALSE; + int ir_onboard_decode = FALSE; + struct imon_context *context = NULL; + int i; + + info("%s: found IMON device", __FUNCTION__); + + /* + * If it's the LCD, as opposed to the VFD, we just need to replace + * the "write" file op. + */ + if (is_lcd) + vfd_fops.write = &lcd_write; + +#if !defined(KERNEL_2_5) + for (subminor = 0; subminor < MAX_DEVICES; ++subminor) { + if (minor_table[subminor] == NULL) + break; + } + if (subminor == MAX_DEVICES) { + err("%s: allowed max number of devices already present", + __FUNCTION__); + retval = -ENOMEM; + goto exit; + } +#endif + +#ifdef KERNEL_2_5 + dev = usb_get_dev(interface_to_usbdev(interface)); + iface_desc = interface->cur_altsetting; + num_endpoints = iface_desc->desc.bNumEndpoints; +#else + interface = &dev->actconfig->interface[intf]; + iface_desc = &interface->altsetting[interface->act_altsetting]; + num_endpoints = iface_desc->bNumEndpoints; +#endif + + /* + * Scan the endpoint list and set: + * first input endpoint = IR endpoint + * first output endpoint = VFD endpoint + */ + + ir_ep_found = FALSE; + vfd_ep_found = FALSE; + + for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) { + struct usb_endpoint_descriptor *ep; + int ep_dir; + int ep_type; +#ifdef KERNEL_2_5 + ep = &iface_desc->endpoint[i].desc; +#else + ep = &iface_desc->endpoint[i]; +#endif + ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + if (!ir_ep_found && + ep_dir == USB_DIR_IN && + ep_type == USB_ENDPOINT_XFER_INT) { + + rx_endpoint = ep; + ir_ep_found = TRUE; + if (debug) + info("%s: found IR endpoint", __FUNCTION__); + + } else if (!vfd_ep_found && + ep_dir == USB_DIR_OUT && + ep_type == USB_ENDPOINT_XFER_INT) { + tx_endpoint = ep; + vfd_ep_found = TRUE; + if (debug) + info("%s: found VFD endpoint", __FUNCTION__); + } + } + + /* Input endpoint is mandatory */ + if (!ir_ep_found) { + err("%s: no valid input(IR) endpoint found.", __FUNCTION__); + retval = -ENODEV; + goto exit; + } else { + /* Determine if the IR signals are decoded onboard */ + unsigned short product_id; + unsigned short *id_list_item; + + product_id = cpu_to_le16(dev->descriptor.idProduct); + id_list_item = ir_onboard_decode_product_list; + while (*id_list_item) { + if (*id_list_item++ == product_id) { + ir_onboard_decode = TRUE; + break; + } + } + + if (debug) + info("ir_onboard_decode: %d", ir_onboard_decode); + } + + /* Determine if VFD requires 6 packets */ + if (vfd_ep_found) { + unsigned short vendor_id; + unsigned short *id_list_item; + + vendor_id = cpu_to_le16(dev->descriptor.idVendor); + id_list_item = vfd_proto_6p_vendor_list; + while (*id_list_item) { + if (*id_list_item++ == vendor_id) { + vfd_proto_6p = TRUE; + break; + } + } + + if (debug) + info("vfd_proto_6p: %d", vfd_proto_6p); + } + + + /* Allocate memory */ + + alloc_status = SUCCESS; + + context = kmalloc(sizeof(struct imon_context), GFP_KERNEL); + if (!context) { + err("%s: kmalloc failed for context", __FUNCTION__); + alloc_status = 1; + goto alloc_status_switch; + } + plugin = kmalloc(sizeof(struct lirc_plugin), GFP_KERNEL); + if (!plugin) { + err("%s: kmalloc failed for lirc_plugin", __FUNCTION__); + alloc_status = 2; + goto alloc_status_switch; + } + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) { + err("%s: kmalloc failed for lirc_buffer", __FUNCTION__); + alloc_status = 3; + goto alloc_status_switch; + } + if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { + err("%s: lirc_buffer_init failed", __FUNCTION__); + alloc_status = 4; + goto alloc_status_switch; + } +#ifdef KERNEL_2_5 + rx_urb = usb_alloc_urb(0, GFP_KERNEL); +#else + rx_urb = usb_alloc_urb(0); +#endif + if (!rx_urb) { + err("%s: usb_alloc_urb failed for IR urb", __FUNCTION__); + alloc_status = 5; + goto alloc_status_switch; + } + if (vfd_ep_found) { +#ifdef KERNEL_2_5 + tx_urb = usb_alloc_urb(0, GFP_KERNEL); +#else + tx_urb = usb_alloc_urb(0); +#endif + if (!tx_urb) { + err("%s: usb_alloc_urb failed for VFD urb", + __FUNCTION__); + alloc_status = 6; + goto alloc_status_switch; + } + } + + /* clear all members of imon_context and lirc_plugin */ + memset(context, 0, sizeof(struct imon_context)); + init_MUTEX(&context->sem); + context->vfd_proto_6p = vfd_proto_6p; + context->ir_onboard_decode = ir_onboard_decode; + + memset(plugin, 0, sizeof(struct lirc_plugin)); + + strcpy(plugin->name, MOD_NAME); + plugin->minor = -1; + plugin->code_length = (ir_onboard_decode) ? + 32 : sizeof(lirc_t) * 8; + plugin->sample_rate = 0; + plugin->features = (ir_onboard_decode) ? + LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_MODE2; + plugin->data = context; + plugin->rbuf = rbuf; + plugin->set_use_inc = ir_open; + plugin->set_use_dec = ir_close; +#ifdef LIRC_HAVE_SYSFS + plugin->dev = &dev->dev; +#endif + plugin->owner = THIS_MODULE; + + LOCK_CONTEXT; + + lirc_minor = lirc_register_plugin(plugin); + if (lirc_minor < 0) { + err("%s: lirc_register_plugin failed", __FUNCTION__); + alloc_status = 7; + UNLOCK_CONTEXT; + goto alloc_status_switch; + } else + info("%s: Registered iMON plugin(minor:%d)", + __FUNCTION__, lirc_minor); + +alloc_status_switch: + + switch (alloc_status) { + case 7: + if (vfd_ep_found) + usb_free_urb(tx_urb); + case 6: + usb_free_urb(rx_urb); + case 5: + lirc_buffer_free(rbuf); + case 4: + kfree(rbuf); + case 3: + kfree(plugin); + case 2: + kfree(context); + context = NULL; + case 1: + retval = -ENOMEM; + } + + /* Needed while unregistering! */ + plugin->minor = lirc_minor; + + context->dev = dev; + context->dev_present = TRUE; + context->rx_endpoint = rx_endpoint; + context->rx_urb = rx_urb; + if (vfd_ep_found) { + context->vfd_supported = TRUE; + context->tx_endpoint = tx_endpoint; + context->tx_urb = tx_urb; + } + context->plugin = plugin; + +#ifdef KERNEL_2_5 + usb_set_intfdata(interface, context); + + if (cpu_to_le16(dev->descriptor.idProduct) == 0xffdc) { + int err; + + err = sysfs_create_group(&interface->dev.kobj, + &imon_attribute_group); + if (err) + err("%s: Could not create sysfs entries(%d)", + __FUNCTION__, err); + } +#else + minor_table[subminor] = context; + context->subminor = subminor; +#endif + + if (vfd_ep_found) { + if (debug) + info("Registering VFD with devfs"); +#ifdef KERNEL_2_5 + if (usb_register_dev(interface, &imon_class)) { + /* Not a fatal error, so ignore */ + info("%s: could not get a minor number for VFD", + __FUNCTION__); + } +#else + sprintf(name, DEVFS_NAME, subminor); + if (!(context->devfs = devfs_register(usb_devfs_handle, name, + DEVFS_FL_DEFAULT, + USB_MAJOR, VFD_MINOR_BASE + subminor, + DEVFS_MODE, &vfd_fops, NULL))) { + /* not a fatal error so ignore */ + info("%s: devfs register failed for VFD", + __FUNCTION__); + } +#endif + } + + info("%s: iMON device on usb<%d:%d> initialized", + __FUNCTION__, dev->bus->busnum, dev->devnum); + + UNLOCK_CONTEXT; + + exit: +#ifdef KERNEL_2_5 + return retval; +#else + return (retval == SUCCESS) ? context : NULL; +#endif +} + +/** + * Callback function for USB core API: disonnect + */ +#ifdef KERNEL_2_5 +static void imon_disconnect(struct usb_interface *interface) +#else +static void imon_disconnect(struct usb_device *dev, void *data) +#endif +{ + struct imon_context *context; + + /* prevent races with ir_open()/vfd_open() */ + down(&disconnect_sem); + +#ifdef KERNEL_2_5 + context = usb_get_intfdata(interface); +#else + context = (struct imon_context *)data; +#endif + LOCK_CONTEXT; + + info("%s: iMON device disconnected", __FUNCTION__); + +#ifdef KERNEL_2_5 + /* sysfs_remove_group is safe to call even if sysfs_create_group + * hasn't been called */ + sysfs_remove_group(&interface->dev.kobj, + &imon_attribute_group); + usb_set_intfdata(interface, NULL); +#else + minor_table[context->subminor] = NULL; +#endif + context->dev_present = FALSE; + + /* Stop reception */ + usb_kill_urb(context->rx_urb); + + /* Abort ongoing write */ + if (atomic_read(&context->tx.busy)) { + usb_kill_urb(context->tx_urb); + wait_for_completion(&context->tx.finished); + } + + /* De-register from lirc_dev if IR port is not open */ + if (!context->ir_isopen) + deregister_from_lirc(context); + + if (context->vfd_supported) +#ifdef KERNEL_2_5 + usb_deregister_dev(interface, &imon_class); +#else + if (context->devfs) + devfs_unregister(context->devfs); +#endif + + UNLOCK_CONTEXT; + + if (!context->ir_isopen && !context->vfd_isopen) + delete_context(context); + + up(&disconnect_sem); +} + +static int __init imon_init(void) +{ + int rc; + + info(MOD_DESC ", v" MOD_VERSION); + info(MOD_AUTHOR); + + rc = usb_register(&imon_driver); + if (rc) { + err("%s: usb register failed(%d)", __FUNCTION__, rc); + return -ENODEV; + } + return SUCCESS; +} + +static void __exit imon_exit(void) +{ + usb_deregister(&imon_driver); + info("module removed. Goodbye!"); +} + + +module_init(imon_init); +module_exit(imon_exit); + +#if !defined(KERNEL_2_5) +EXPORT_NO_SYMBOLS; +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_imon/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_imon/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_IMON) += lirc_imon.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_igorplugusb/lirc_igorplugusb.c +++ linux-2.6.27/ubuntu/lirc/lirc_igorplugusb/lirc_igorplugusb.c @@ -0,0 +1,697 @@ +/* lirc_igorplugusb - USB remote support for LIRC + * + * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware. + * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm + * + * The device can only record bursts of up to 36 pulses/spaces. + * Works fine with RC5. Longer commands lead to device buffer overrun. + * (Maybe a better firmware or a microcontroller with more ram can help?) + * + * Version 0.1 [beta status] + * + * Copyright (C) 2004 Jan M. Hochstein + * + * + * This driver was derived from: + * Paul Miller + * "lirc_atiusb" module + * Vladimir Dergachev 's 2002 + * "USB ATI Remote support" (input device) + * Adrian Dewhurst 's 2002 + * "USB StreamZap remote driver" (LIRC) + * Artur Lipowski 's 2002 + * "lirc_dev" and "lirc_gpio" LIRC modules + * + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +#error "*******************************************************" +#error "Sorry, this driver needs kernel version 2.4.0 or higher" +#error "*******************************************************" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcompat.h" +#include "lirc.h" +#include "lirc_dev/lirc_dev.h" + +#if !defined(KERNEL_2_5) +#define USB_CTRL_GET_TIMEOUT 5 +#endif + +/* lock irctl structure */ +#define IRLOCK down_interruptible(&ir->lock) +#define IRUNLOCK up(&ir->lock) + +/* module identification */ +#define DRIVER_VERSION "0.1" +#define DRIVER_AUTHOR \ + "Jan M. Hochstein " +#define DRIVER_DESC "USB remote driver for LIRC" +#define DRIVER_NAME "lirc_igorplugusb" + +/* debugging support */ +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG fmt, ## args); \ + } while (0) + +/* general constants */ +#define SUCCESS 0 + +/* One mode2 pulse/space has 4 bytes. */ +#define CODE_LENGTH sizeof(lirc_t) + +/* Igor's firmware cannot record bursts longer than 36. */ +#define DEVICE_BUFLEN 36 + +/** Header at the beginning of the device's buffer: + unsigned char data_length + unsigned char data_start (!=0 means ring-buffer overrun) + unsigned char counter (incremented by each burst) +**/ +#define DEVICE_HEADERLEN 3 + +/* This is for the gap */ +#define ADDITIONAL_LIRC_BYTES 2 + +/* times to poll per second */ +#define SAMPLE_RATE 100 + +static int sample_rate = SAMPLE_RATE; + +/**** Igor's USB Request Codes */ + +#define SET_INFRABUFFER_EMPTY 1 +/** + * Params: none + * Answer: empty + * +**/ + +#define GET_INFRACODE 2 +/** + * Params: + * wValue: offset to begin reading infra buffer + * + * Answer: infra data + * +**/ + +#define SET_DATAPORT_DIRECTION 3 +/** + * Params: + * wValue: (byte) 1 bit for each data port pin (0=in, 1=out) + * + * Answer: empty + * +**/ + +#define GET_DATAPORT_DIRECTION 4 +/** + * Params: none + * + * Answer: (byte) 1 bit for each data port pin (0=in, 1=out) + * +**/ + +#define SET_OUT_DATAPORT 5 +/** + * Params: + * wValue: byte to write to output data port + * + * Answer: empty + * +**/ + +#define GET_OUT_DATAPORT 6 +/** + * Params: none + * + * Answer: least significant 3 bits read from output data port + * +**/ + +#define GET_IN_DATAPORT 7 +/** + * Params: none + * + * Answer: least significant 3 bits read from input data port + * +**/ + +#define READ_EEPROM 8 +/** + * Params: + * wValue: offset to begin reading EEPROM + * + * Answer: EEPROM bytes + * +**/ + +#define WRITE_EEPROM 9 +/** + * Params: + * wValue: offset to EEPROM byte + * wIndex: byte to write + * + * Answer: empty + * +**/ + +#define SEND_RS232 10 +/** + * Params: + * wValue: byte to send + * + * Answer: empty + * +**/ + +#define RECV_RS232 11 +/** + * Params: none + * + * Answer: byte received + * +**/ + +#define SET_RS232_BAUD 12 +/** + * Params: + * wValue: byte to write to UART bit rate register (UBRR) + * + * Answer: empty + * +**/ + +#define GET_RS232_BAUD 13 +/** + * Params: none + * + * Answer: byte read from UART bit rate register (UBRR) + * +**/ + + +/* data structure for each usb remote */ +struct irctl { + + /* usb */ + struct usb_device *usbdev; + struct urb *urb_in; + int devnum; + + unsigned char *buf_in; + unsigned int len_in; + int in_space; + struct timeval last_time; + +#if defined(KERNEL_2_5) + dma_addr_t dma_in; +#endif + + /* lirc */ + struct lirc_plugin *p; + + /* handle sending (init strings) */ + int send_flags; + wait_queue_head_t wait_out; + + struct semaphore lock; +}; + +static int unregister_from_lirc(struct irctl *ir) +{ + struct lirc_plugin *p = ir->p; + int devnum; + + if (!ir->p) + return -EINVAL; + + devnum = ir->devnum; + dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); + + lirc_unregister_plugin(p->minor); + + printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); + + lirc_buffer_free(p->rbuf); + kfree(p->rbuf); + kfree(p); + kfree(ir); + ir->p = NULL; + return SUCCESS; +} + +static int set_use_inc(void *data) +{ + struct irctl *ir = data; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); + return -EIO; + } + dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); + + MOD_INC_USE_COUNT; + + if (!ir->usbdev) + return -ENODEV; + + return SUCCESS; +} + +static void set_use_dec(void *data) +{ + struct irctl *ir = data; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); + return; + } + dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); + + MOD_DEC_USE_COUNT; +} + + +/** + * Called in user context. + * return 0 if data was added to the buffer and + * -ENODATA if none was available. This should add some number of bits + * evenly divisible by code_length to the buffer +**/ +static int usb_remote_poll(void *data, struct lirc_buffer *buf) +{ + int ret; + struct irctl *ir = (struct irctl *)data; + + if (!ir->usbdev) /* Has the device been removed? */ + return -ENODEV; + + memset(ir->buf_in, 0, ir->len_in); + + ret = usb_control_msg( + ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + GET_INFRACODE, USB_TYPE_VENDOR|USB_DIR_IN, + 0/* offset */, /*unused*/0, + ir->buf_in, ir->len_in, + /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); + if (ret > 0) { + int i = DEVICE_HEADERLEN; + lirc_t code, timediff; + struct timeval now; + + if (ret <= 1) /* ACK packet has 1 byte --> ignore */ + return -ENODATA; + + dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n", + ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]); + + if (ir->buf_in[2] != 0) { + printk(DRIVER_NAME "[%d]: Device buffer overrun.\n", + ir->devnum); + /* start at earliest byte */ + i = DEVICE_HEADERLEN + ir->buf_in[2]; + /* where are we now? space, gap or pulse? */ + } + + do_gettimeofday(&now); + timediff = now.tv_sec - ir->last_time.tv_sec; + if (timediff + 1 > PULSE_MASK / 1000000) + timediff = PULSE_MASK; + else { + timediff *= 1000000; + timediff += now.tv_usec - ir->last_time.tv_usec; + } + ir->last_time.tv_sec = now.tv_sec; + ir->last_time.tv_usec = now.tv_usec; + + /* create leading gap */ + code = timediff; + lirc_buffer_write_n(buf, (unsigned char *)&code, 1); + ir->in_space = 1; /* next comes a pulse */ + + /* MODE2: pulse/space (PULSE_BIT) in 1us units */ + + while (i < ret) { + /* 1 Igor-tick = 85.333333 us */ + code = (unsigned int)ir->buf_in[i] * 85 + + (unsigned int)ir->buf_in[i] / 3; + ir->last_time.tv_usec += code; + if (ir->in_space) + code |= PULSE_BIT; + lirc_buffer_write_n(buf, (unsigned char *)&code, 1); + /* 1 chunk = CODE_LENGTH bytes */ + ir->in_space ^= 1; + ++i; + } + + ret = usb_control_msg( + ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, + /*unused*/0, /*unused*/0, + /*dummy*/ir->buf_in, /*dummy*/ir->len_in, + /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); + if (ret < 0) + printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: " + "error %d\n", ir->devnum, ret); + return SUCCESS; + } else + printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n", + ir->devnum, ret); + + return -ENODATA; +} + + + +#if defined(KERNEL_2_5) +static int usb_remote_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = NULL; + struct usb_host_interface *idesc = NULL; + struct usb_host_endpoint *ep_ctl2; +#else +static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct usb_interface *intf; + struct usb_interface_descriptor *idesc; + struct usb_endpoint_descriptor *ep_ctl2; +#endif + struct irctl *ir = NULL; + struct lirc_plugin *plugin = NULL; + struct lirc_buffer *rbuf = NULL; + int devnum, pipe, maxp, bytes_in_key; + int minor = 0; + char buf[63], name[128] = ""; + int mem_failure = 0; + int ret; + + dprintk(DRIVER_NAME ": usb probe called.\n"); + +#if defined(KERNEL_2_5) + dev = interface_to_usbdev(intf); + +# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) + idesc = &intf->altsetting[intf->act_altsetting]; /* in 2.6.4 */ +# else + idesc = intf->cur_altsetting; /* in 2.6.6 */ +# endif + + if (idesc->desc.bNumEndpoints != 1) + return -ENODEV; + ep_ctl2 = idesc->endpoint; + if (((ep_ctl2->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) + != USB_DIR_IN) + || (ep_ctl2->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_CONTROL) + return -ENODEV; + pipe = usb_rcvctrlpipe(dev, ep_ctl2->desc.bEndpointAddress); +#else + intf = &dev->actconfig->interface[ifnum]; + idesc = &intf->altsetting[intf->act_altsetting]; + if (idesc->bNumEndpoints != 1) + return NULL; + ep_ctl2 = idesc->endpoint; + if (((ep_ctl2->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + != USB_DIR_IN) + || (ep_ctl2->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_CONTROL) + return NULL; + pipe = usb_rcvctrlpipe(dev, ep_ctl2->bEndpointAddress); +#endif + devnum = dev->devnum; + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + bytes_in_key = CODE_LENGTH; + + dprintk(DRIVER_NAME "[%d]: bytes_in_key=%d maxp=%d\n", + devnum, bytes_in_key, maxp); + + + /* allocate kernel memory */ + mem_failure = 0; + ir = kmalloc(sizeof(struct irctl), GFP_KERNEL); + if (!ir) { + mem_failure = 1; + goto mem_failure_switch; + } + + memset(ir, 0, sizeof(struct irctl)); + + plugin = kmalloc(sizeof(struct lirc_plugin), GFP_KERNEL); + if (!plugin) { + mem_failure = 2; + goto mem_failure_switch; + } + + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) { + mem_failure = 3; + goto mem_failure_switch; + } + + if (lirc_buffer_init(rbuf, bytes_in_key, + DEVICE_BUFLEN+ADDITIONAL_LIRC_BYTES)) { + mem_failure = 4; + goto mem_failure_switch; + } + +#if defined(KERNEL_2_5) + ir->buf_in = usb_buffer_alloc(dev, + DEVICE_BUFLEN+DEVICE_HEADERLEN, + GFP_ATOMIC, &ir->dma_in); +#else + ir->buf_in = kmalloc(DEVICE_BUFLEN+DEVICE_HEADERLEN, + GFP_KERNEL); +#endif + if (!ir->buf_in) { + mem_failure = 5; + goto mem_failure_switch; + } + + memset(plugin, 0, sizeof(struct lirc_plugin)); + + strcpy(plugin->name, DRIVER_NAME " "); + plugin->minor = -1; + plugin->code_length = bytes_in_key*8; /* in bits */ + plugin->features = LIRC_CAN_REC_MODE2; + plugin->data = ir; + plugin->rbuf = rbuf; + plugin->set_use_inc = &set_use_inc; + plugin->set_use_dec = &set_use_dec; + plugin->sample_rate = sample_rate; /* per second */ + plugin->add_to_buf = &usb_remote_poll; +#ifdef LIRC_HAVE_SYSFS + plugin->dev = &dev->dev; +#endif + plugin->owner = THIS_MODULE; + + init_MUTEX(&ir->lock); + init_waitqueue_head(&ir->wait_out); + + minor = lirc_register_plugin(plugin); + if (minor < 0) + mem_failure = 9; + +mem_failure_switch: + + /* free allocated memory in case of failure */ + switch (mem_failure) { + case 9: +#if defined(KERNEL_2_5) + usb_buffer_free(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, + ir->buf_in, ir->dma_in); +#else + kfree(ir->buf_in); +#endif + case 5: + lirc_buffer_free(rbuf); + case 4: + kfree(rbuf); + case 3: + kfree(plugin); + case 2: + kfree(ir); + case 1: + printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", + devnum, mem_failure); +#if defined(KERNEL_2_5) + return -ENOMEM; +#else + return NULL; +#endif + } + + plugin->minor = minor; + ir->p = plugin; + ir->devnum = devnum; + ir->usbdev = dev; + ir->len_in = DEVICE_BUFLEN+DEVICE_HEADERLEN; + ir->in_space = 1; /* First mode2 event is a space. */ + do_gettimeofday(&ir->last_time); + + if (dev->descriptor.iManufacturer + && usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) + strncpy(name, buf, 128); + if (dev->descriptor.iProduct + && usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + snprintf(name, 128, "%s %s", name, buf); + printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, + dev->bus->busnum, devnum); + + /* clear device buffer */ + ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, + /*unused*/0, /*unused*/0, + /*dummy*/ir->buf_in, /*dummy*/ir->len_in, + /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); + if (ret < 0) + printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", + devnum, ret); + +#if defined(KERNEL_2_5) + usb_set_intfdata(intf, ir); + return SUCCESS; +#else + return ir; +#endif +} + + +#if defined(KERNEL_2_5) +static void usb_remote_disconnect(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct irctl *ir = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); +#else +static void usb_remote_disconnect(struct usb_device *dev, void *ptr) +{ + struct irctl *ir = ptr; +#endif + + if (!ir || !ir->p) + return; + + ir->usbdev = NULL; + wake_up_all(&ir->wait_out); + + IRLOCK; +#if defined(KERNEL_2_5) + usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in); +#else + kfree(ir->buf_in); +#endif + IRUNLOCK; + + unregister_from_lirc(ir); +} + +static struct usb_device_id usb_remote_id_table [] = { + /* Igor Plug USB (Atmel's Manufact. ID) */ + { USB_DEVICE(0x03eb, 0x0002) }, + + /* Terminating entry */ + { } +}; + +static struct usb_driver usb_remote_driver = { + LIRC_THIS_MODULE(.owner = THIS_MODULE) + .name = DRIVER_NAME, + .probe = usb_remote_probe, + .disconnect = usb_remote_disconnect, + .id_table = usb_remote_id_table +}; + +static int __init usb_remote_init(void) +{ + int i; + + printk(KERN_INFO "\n" + DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n"); + printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); + dprintk(DRIVER_NAME ": debug mode enabled\n"); + + request_module("lirc_dev"); + + i = usb_register(&usb_remote_driver); + if (i < 0) { + printk(DRIVER_NAME ": usb register failed, result = %d\n", i); + return -ENODEV; + } + + return SUCCESS; +} + +static void __exit usb_remote_exit(void) +{ + usb_deregister(&usb_remote_driver); +} + +module_init(usb_remote_init); +module_exit(usb_remote_exit); + +#if defined(KERNEL_2_5) +#include +MODULE_INFO(vermagic, VERMAGIC_STRING); +#endif + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, usb_remote_id_table); + +module_param(sample_rate, int, 0644); +MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)"); + +EXPORT_NO_SYMBOLS; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_igorplugusb/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_igorplugusb/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_sir/lirc_sir.c +++ linux-2.6.27/ubuntu/lirc/lirc_sir/lirc_sir.c @@ -0,0 +1,1323 @@ +/* + * LIRC SIR driver, (C) 2000 Milan Pikula + * + * lirc_sir - Device driver for use with SIR (serial infra red) + * mode of IrDA on many notebooks. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * 2000/09/16 Frank Przybylski : + * added timeout and relaxed pulse detection, removed gap bug + * + * 2000/12/15 Christoph Bartelmus : + * added support for Tekram Irmate 210 (sending does not work yet, + * kind of disappointing that nobody was able to implement that + * before), + * major clean-up + * + * 2001/02/27 Christoph Bartelmus : + * added support for StrongARM SA1100 embedded microprocessor + * parts cut'n'pasted from sa1100_ir.c (C) 2000 Russell King + */ + + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) +#error "**********************************************************" +#error " Sorry, this driver needs kernel version 2.2.18 or higher " +#error "**********************************************************" +#endif +#include + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LIRC_ON_SA1100 +#include +#ifdef CONFIG_SA1100_COLLIE +#include +#include +#endif +#endif + +#include + +#include "lirc.h" +#include "lirc_dev/lirc_dev.h" +#include "kcompat.h" + +/* SECTION: Definitions */ + +/**************************** Tekram dongle ***************************/ +#ifdef LIRC_SIR_TEKRAM +/* stolen from kernel source */ +/* definitions for Tekram dongle */ +#define TEKRAM_115200 0x00 +#define TEKRAM_57600 0x01 +#define TEKRAM_38400 0x02 +#define TEKRAM_19200 0x03 +#define TEKRAM_9600 0x04 +#define TEKRAM_2400 0x08 + +#define TEKRAM_PW 0x10 /* Pulse select bit */ + +/* 10bit * 1s/115200bit in miliseconds = 87ms*/ +#define TIME_CONST (10000000ul/115200ul) + +#endif + +#ifdef LIRC_SIR_ACTISYS_ACT200L +static void init_act200(void); +#elif defined(LIRC_SIR_ACTISYS_ACT220L) +static void init_act220(void); +#endif + +/******************************* SA1100 ********************************/ +#ifdef LIRC_ON_SA1100 +struct sa1100_ser2_registers { + /* HSSP control register */ + unsigned char hscr0; + /* UART registers */ + unsigned char utcr0; + unsigned char utcr1; + unsigned char utcr2; + unsigned char utcr3; + unsigned char utcr4; + unsigned char utdr; + unsigned char utsr0; + unsigned char utsr1; +} sr; + +static int irq = IRQ_Ser2ICP; + +#define LIRC_ON_SA1100_TRANSMITTER_LATENCY 0 + +/* pulse/space ratio of 50/50 */ +static unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); +/* 1000000/freq-pulse_width */ +static unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); +static unsigned int freq = 38000; /* modulation frequency */ +static unsigned int duty_cycle = 50; /* duty cycle of 50% */ + +#endif + +#define RBUF_LEN 1024 +#define WBUF_LEN 1024 + +#define LIRC_DRIVER_NAME "lirc_sir" + +#define PULSE '[' + +#ifndef LIRC_SIR_TEKRAM +/* 9bit * 1s/115200bit in milli seconds = 78.125ms*/ +#define TIME_CONST (9000000ul/115200ul) +#endif + + +/* timeout for sequences in jiffies (=5/100s) */ +/* must be longer than TIME_CONST */ +#define SIR_TIMEOUT (HZ*5/100) + +#ifndef LIRC_ON_SA1100 +#ifndef LIRC_IRQ +#define LIRC_IRQ 4 +#endif +#ifndef LIRC_PORT +#define LIRC_PORT 0x3e8 +#endif + +static int io = LIRC_PORT; +static int irq = LIRC_IRQ; +static int threshold = 3; +#endif + +static DEFINE_SPINLOCK(timer_lock); +static struct timer_list timerlist; +/* time of last signal change detected */ +static struct timeval last_tv = {0, 0}; +/* time of last UART data ready interrupt */ +static struct timeval last_intr_tv = {0, 0}; +static int last_value; + +static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); + +static DEFINE_SPINLOCK(hardware_lock); +static DEFINE_SPINLOCK(dev_lock); + +static lirc_t rx_buf[RBUF_LEN]; +static unsigned int rx_tail, rx_head; +static lirc_t tx_buf[WBUF_LEN]; + +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + +/* SECTION: Prototypes */ + +/* Communication with user-space */ +static int lirc_open(struct inode *inode, struct file *file); +static int lirc_close(struct inode *inode, struct file *file); +static unsigned int lirc_poll(struct file *file, poll_table *wait); +static ssize_t lirc_read(struct file *file, char *buf, size_t count, + loff_t *ppos); +static ssize_t lirc_write(struct file *file, const char *buf, size_t n, + loff_t *pos); +static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, + unsigned long arg); +static void add_read_queue(int flag, unsigned long val); +#ifdef MODULE +static int init_chrdev(void); +static void drop_chrdev(void); +#endif + /* Hardware */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static irqreturn_t sir_interrupt(int irq, void *dev_id, + struct pt_regs *regs); +#else +static irqreturn_t sir_interrupt(int irq, void *dev_id); +#endif +static void send_space(unsigned long len); +static void send_pulse(unsigned long len); +static int init_hardware(void); +static void drop_hardware(void); + /* Initialisation */ +static int init_port(void); +static void drop_port(void); +int init_module(void); +void cleanup_module(void); + +#ifdef LIRC_ON_SA1100 +static inline void on(void) +{ + PPSR |= PPC_TXD2; +} + +static inline void off(void) +{ + PPSR &= ~PPC_TXD2; +} +#else +static inline unsigned int sinp(int offset) +{ + return inb(io + offset); +} + +static inline void soutp(int offset, int value) +{ + outb(value, io + offset); +} +#endif + +#ifndef MAX_UDELAY_MS +#define MAX_UDELAY_US 5000 +#else +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) +#endif + +static inline void safe_udelay(unsigned long usecs) +{ + while (usecs > MAX_UDELAY_US) { + udelay(MAX_UDELAY_US); + usecs -= MAX_UDELAY_US; + } + udelay(usecs); +} + +/* SECTION: Communication with user-space */ + +static int lirc_open(struct inode *inode, struct file *file) +{ + spin_lock(&dev_lock); + if (MOD_IN_USE) { + spin_unlock(&dev_lock); + return -EBUSY; + } + MOD_INC_USE_COUNT; + spin_unlock(&dev_lock); + return 0; +} + +static int lirc_close(struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static unsigned int lirc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &lirc_read_queue, wait); + if (rx_head != rx_tail) + return POLLIN | POLLRDNORM; + return 0; +} + +static ssize_t lirc_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + int n = 0; + int retval = 0; + DECLARE_WAITQUEUE(wait, current); + + if (n % sizeof(lirc_t)) + return -EINVAL; + + add_wait_queue(&lirc_read_queue, &wait); + set_current_state(TASK_INTERRUPTIBLE); + while (n < count) { + if (rx_head != rx_tail) { + if (copy_to_user((void *) buf + n, + (void *) (rx_buf + rx_head), + sizeof(lirc_t))) { + retval = -EFAULT; + break; + } + rx_head = (rx_head + 1) & (RBUF_LEN - 1); + n += sizeof(lirc_t); + } else { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + } + remove_wait_queue(&lirc_read_queue, &wait); + set_current_state(TASK_RUNNING); + return (n ? n : retval); +} +static ssize_t lirc_write(struct file *file, const char *buf, size_t n, + loff_t *pos) +{ + unsigned long flags; + int i; + + if (n % sizeof(lirc_t) || (n/sizeof(lirc_t)) > WBUF_LEN) + return -EINVAL; + if (copy_from_user(tx_buf, buf, n)) + return -EFAULT; + i = 0; + n /= sizeof(lirc_t); +#ifdef LIRC_ON_SA1100 + /* disable receiver */ + Ser2UTCR3 = 0; +#endif + local_irq_save(flags); + while (1) { + if (i >= n) + break; + if (tx_buf[i]) + send_pulse(tx_buf[i]); + i++; + if (i >= n) + break; + if (tx_buf[i]) + send_space(tx_buf[i]); + i++; + } + local_irq_restore(flags); +#ifdef LIRC_ON_SA1100 + off(); + udelay(1000); /* wait 1ms for IR diode to recover */ + Ser2UTCR3 = 0; + /* clear status register to prevent unwanted interrupts */ + Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + /* enable receiver */ + Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; +#endif + return n; +} + +static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int retval = 0; + unsigned long value = 0; +#ifdef LIRC_ON_SA1100 + unsigned int ivalue; + + if (cmd == LIRC_GET_FEATURES) + value = LIRC_CAN_SEND_PULSE | + LIRC_CAN_SET_SEND_DUTY_CYCLE | + LIRC_CAN_SET_SEND_CARRIER | + LIRC_CAN_REC_MODE2; + else if (cmd == LIRC_GET_SEND_MODE) + value = LIRC_MODE_PULSE; + else if (cmd == LIRC_GET_REC_MODE) + value = LIRC_MODE_MODE2; +#else + if (cmd == LIRC_GET_FEATURES) + value = LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; + else if (cmd == LIRC_GET_SEND_MODE) + value = LIRC_MODE_PULSE; + else if (cmd == LIRC_GET_REC_MODE) + value = LIRC_MODE_MODE2; +#endif + + switch (cmd) { + case LIRC_GET_FEATURES: + case LIRC_GET_SEND_MODE: + case LIRC_GET_REC_MODE: + retval = put_user(value, (unsigned long *) arg); + break; + + case LIRC_SET_SEND_MODE: + case LIRC_SET_REC_MODE: + retval = get_user(value, (unsigned long *) arg); + break; +#ifdef LIRC_ON_SA1100 + case LIRC_SET_SEND_DUTY_CYCLE: + retval = get_user(ivalue, (unsigned int *) arg); + if (retval) + return reetval; + if (ivalue <= 0 || ivalue > 100) + return -EINVAL; + /* (ivalue/100)*(1000000/freq) */ + duty_cycle = ivalue; + pulse_width = (unsigned long) duty_cycle*10000/freq; + space_width = (unsigned long) 1000000L/freq-pulse_width; + if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + break; + case LIRC_SET_SEND_CARRIER: + retval = get_user(ivalue, (unsigned int *) arg); + if (retval) + return retval; + if (ivalue > 500000 || ivalue < 20000) + return -EINVAL; + freq = ivalue; + pulse_width = (unsigned long) duty_cycle*10000/freq; + space_width = (unsigned long) 1000000L/freq-pulse_width; + if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + break; +#endif + default: + retval = -ENOIOCTLCMD; + + } + + if (retval) + return retval; + if (cmd == LIRC_SET_REC_MODE) { + if (value != LIRC_MODE_MODE2) + retval = -ENOSYS; + } else if (cmd == LIRC_SET_SEND_MODE) { + if (value != LIRC_MODE_PULSE) + retval = -ENOSYS; + } + + return retval; +} + +static void add_read_queue(int flag, unsigned long val) +{ + unsigned int new_rx_tail; + lirc_t newval; + + dprintk("add flag %d with val %lu\n", flag, val); + + newval = val & PULSE_MASK; + + /* statistically pulses are ~TIME_CONST/2 too long: we could + maybe make this more exactly but this is good enough */ + if (flag) { + /* pulse */ + if (newval > TIME_CONST/2) + newval -= TIME_CONST/2; + else /* should not ever happen */ + newval = 1; + newval |= PULSE_BIT; + } else { + newval += TIME_CONST/2; + } + new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); + if (new_rx_tail == rx_head) { + dprintk("Buffer overrun.\n"); + return; + } + rx_buf[rx_tail] = newval; + rx_tail = new_rx_tail; + wake_up_interruptible(&lirc_read_queue); +} + +static struct file_operations lirc_fops = { + .read = lirc_read, + .write = lirc_write, + .poll = lirc_poll, + .ioctl = lirc_ioctl, + .open = lirc_open, + .release = lirc_close, +}; + +static int set_use_inc(void *data) +{ + return 0; +} + +static void set_use_dec(void *data) +{ +} +static struct lirc_plugin plugin = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .get_queue = NULL, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + + +#ifdef MODULE +static int init_chrdev(void) +{ + plugin.minor = lirc_register_plugin(&plugin); + if (plugin.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); + return -EIO; + } + return 0; +} + +static void drop_chrdev(void) +{ + lirc_unregister_plugin(plugin.minor); +} +#endif + +/* SECTION: Hardware */ +static long delta(struct timeval *tv1, struct timeval *tv2) +{ + unsigned long deltv; + + deltv = tv2->tv_sec - tv1->tv_sec; + if (deltv > 15) + deltv = 0xFFFFFF; + else + deltv = deltv*1000000 + + tv2->tv_usec - + tv1->tv_usec; + return deltv; +} + +static void sir_timeout(unsigned long data) +{ + /* if last received signal was a pulse, but receiving stopped + within the 9 bit frame, we need to finish this pulse and + simulate a signal change to from pulse to space. Otherwise + upper layers will receive two sequences next time. */ + + unsigned long flags; + unsigned long pulse_end; + + /* avoid interference with interrupt */ + spin_lock_irqsave(&timer_lock, flags); + if (last_value) { +#ifndef LIRC_ON_SA1100 + /* clear unread bits in UART and restart */ + outb(UART_FCR_CLEAR_RCVR, io + UART_FCR); +#endif + /* determine 'virtual' pulse end: */ + pulse_end = delta(&last_tv, &last_intr_tv); + dprintk("timeout add %d for %lu usec\n", last_value, pulse_end); + add_read_queue(last_value, pulse_end); + last_value = 0; + last_tv = last_intr_tv; + } + spin_unlock_irqrestore(&timer_lock, flags); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static irqreturn_t sir_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +#else +static irqreturn_t sir_interrupt(int irq, void *dev_id) +#endif +{ + unsigned char data; + struct timeval curr_tv; + static unsigned long deltv; +#ifdef LIRC_ON_SA1100 + int status; + static int n; + + status = Ser2UTSR0; + /* + * Deal with any receive errors first. The bytes in error may be + * the only bytes in the receive FIFO, so we do this first. + */ + while (status & UTSR0_EIF) { + int bstat; + + if (debug) { + dprintk("EIF\n"); + bstat = Ser2UTSR1; + + if (bstat & UTSR1_FRE) + dprintk("frame error\n"); + if (bstat & UTSR1_ROR) + dprintk("receive fifo overrun\n"); + if (bstat & UTSR1_PRE) + dprintk("parity error\n"); + } + + bstat = Ser2UTDR; + n++; + status = Ser2UTSR0; + } + + if (status & (UTSR0_RFS | UTSR0_RID)) { + do_gettimeofday(&curr_tv); + deltv = delta(&last_tv, &curr_tv); + do { + data = Ser2UTDR; + dprintk("%d data: %u\n", n, (unsigned int) data); + n++; + } while (status & UTSR0_RID && /* do not empty fifo in + order to get UTSR0_RID in + any case */ + Ser2UTSR1 & UTSR1_RNE); /* data ready */ + + if (status&UTSR0_RID) { + add_read_queue(0 , deltv - n * TIME_CONST); /*space*/ + add_read_queue(1, n * TIME_CONST); /*pulse*/ + n = 0; + last_tv = curr_tv; + } + } + + if (status & UTSR0_TFS) + printk(KERN_ERR "transmit fifo not full, shouldn't happen\n"); + + /* + * We must clear certain bits. + */ + status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + if (status) + Ser2UTSR0 = status; +#else + unsigned long deltintrtv; + unsigned long flags; + int iir, lsr; + + while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) { + switch (iir&UART_IIR_ID) { /* FIXME toto treba preriedit */ + case UART_IIR_MSI: + (void) inb(io + UART_MSR); + break; + case UART_IIR_RLSI: + (void) inb(io + UART_LSR); + break; + case UART_IIR_THRI: +#if 0 + if (lsr & UART_LSR_THRE) /* FIFO is empty */ + outb(data, io + UART_TX) +#endif + break; + case UART_IIR_RDI: + /* avoid interference with timer */ + spin_lock_irqsave(&timer_lock, flags); + do { + del_timer(&timerlist); + data = inb(io + UART_RX); + do_gettimeofday(&curr_tv); + deltv = delta(&last_tv, &curr_tv); + deltintrtv = delta(&last_intr_tv, &curr_tv); + dprintk("t %lu, d %d\n", deltintrtv, (int)data); + /* if nothing came in last X cycles, + it was gap */ + if (deltintrtv > TIME_CONST * threshold) { + if (last_value) { + dprintk("GAP\n"); + /* simulate signal change */ + add_read_queue(last_value, + deltv - + deltintrtv); + last_value = 0; + last_tv.tv_sec = + last_intr_tv.tv_sec; + last_tv.tv_usec = + last_intr_tv.tv_usec; + deltv = deltintrtv; + } + } + data = 1; + if (data ^ last_value) { + /* deltintrtv > 2*TIME_CONST, + remember ? */ + /* the other case is timeout */ + add_read_queue(last_value, + deltv-TIME_CONST); + last_value = data; + last_tv = curr_tv; + if (last_tv.tv_usec >= TIME_CONST) { + last_tv.tv_usec -= TIME_CONST; + } else { + last_tv.tv_sec--; + last_tv.tv_usec += 1000000 - + TIME_CONST; + } + } + last_intr_tv = curr_tv; + if (data) { + /* start timer for end of + * sequence detection */ + timerlist.expires = jiffies + + SIR_TIMEOUT; + add_timer(&timerlist); + } + } + while ((lsr = inb(io + UART_LSR)) + & UART_LSR_DR); /* data ready */ + spin_unlock_irqrestore(&timer_lock, flags); + break; + default: + break; + } + } +#endif + return IRQ_RETVAL(IRQ_HANDLED); +} + +#ifdef LIRC_ON_SA1100 +static void send_pulse(unsigned long length) +{ + unsigned long k, delay; + int flag; + + if (length == 0) + return; + /* this won't give us the carrier frequency we really want + due to integer arithmetic, but we can accept this inaccuracy */ + + for (k = flag = 0; k < length; k += delay, flag = !flag) { + if (flag) { + off(); + delay = space_width; + } else { + on(); + delay = pulse_width; + } + safe_udelay(delay); + } + off(); +} + +static void send_space(unsigned long length) +{ + if (length == 0) + return; + off(); + safe_udelay(length); +} +#else +static void send_space(unsigned long len) +{ + safe_udelay(len); +} + +static void send_pulse(unsigned long len) +{ + long bytes_out = len / TIME_CONST; + long time_left; + + time_left = (long)len - (long)bytes_out * (long)TIME_CONST; + if (bytes_out == 0) { + bytes_out++; + time_left = 0; + } + while (bytes_out--) { + outb(PULSE, io + UART_TX); + /* FIXME treba seriozne cakanie z drivers/char/serial.c */ + while (!(inb(io + UART_LSR) & UART_LSR_THRE)); + } +#if 0 + if (time_left > 0) + safe_udelay(time_left); +#endif +} +#endif + +#ifdef CONFIG_SA1100_COLLIE +static inline int sa1100_irda_set_power_collie(int state) +{ + if (state) { + /* + * 0 - off + * 1 - short range, lowest power + * 2 - medium range, medium power + * 3 - maximum range, high power + */ + ucb1200_set_io_direction(TC35143_GPIO_IR_ON, + TC35143_IODIR_OUTPUT); + ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_LOW); + udelay(100); + } else { + /* OFF */ + ucb1200_set_io_direction(TC35143_GPIO_IR_ON, + TC35143_IODIR_OUTPUT); + ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH); + } + return 0; +} +#endif + +static int init_hardware(void) +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + /* reset UART */ +#ifdef LIRC_ON_SA1100 +#ifdef CONFIG_SA1100_BITSY + if (machine_is_bitsy()) { + printk(KERN_INFO "Power on IR module\n"); + set_bitsy_egpio(EGPIO_BITSY_IR_ON); + } +#endif +#ifdef CONFIG_SA1100_COLLIE + sa1100_irda_set_power_collie(3); /* power on */ +#endif + sr.hscr0 = Ser2HSCR0; + + sr.utcr0 = Ser2UTCR0; + sr.utcr1 = Ser2UTCR1; + sr.utcr2 = Ser2UTCR2; + sr.utcr3 = Ser2UTCR3; + sr.utcr4 = Ser2UTCR4; + + sr.utdr = Ser2UTDR; + sr.utsr0 = Ser2UTSR0; + sr.utsr1 = Ser2UTSR1; + + /* configure GPIO */ + /* output */ + PPDR |= PPC_TXD2; + PSDR |= PPC_TXD2; + /* set output to 0 */ + off(); + + /* + * Enable HP-SIR modulation, and ensure that the port is disabled. + */ + Ser2UTCR3 = 0; + Ser2HSCR0 = sr.hscr0 & (~HSCR0_HSSP); + + /* clear status register to prevent unwanted interrupts */ + Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + + /* 7N1 */ + Ser2UTCR0 = UTCR0_1StpBit|UTCR0_7BitData; + /* 115200 */ + Ser2UTCR1 = 0; + Ser2UTCR2 = 1; + /* use HPSIR, 1.6 usec pulses */ + Ser2UTCR4 = UTCR4_HPSIR|UTCR4_Z1_6us; + + /* enable receiver, receive fifo interrupt */ + Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; + + /* clear status register to prevent unwanted interrupts */ + Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + +#elif defined(LIRC_SIR_TEKRAM) + /* disable FIFO */ + soutp(UART_FCR, + UART_FCR_CLEAR_RCVR| + UART_FCR_CLEAR_XMIT| + UART_FCR_TRIGGER_1); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Set DLAB 1. */ + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + + /* Set divisor to 12 => 9600 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 12); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* power supply */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + safe_udelay(50*1000); + + /* -DTR low -> reset PIC */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + udelay(1*1000); + + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(100); + + + /* -RTS low -> send control byte */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); + udelay(7); + soutp(UART_TX, TEKRAM_115200|TEKRAM_PW); + + /* one byte takes ~1042 usec to transmit at 9600,8N1 */ + udelay(1500); + + /* back to normal operation */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(50); + + udelay(1500); + + /* read previous control byte */ + printk(KERN_INFO LIRC_DRIVER_NAME + ": 0x%02x\n", sinp(UART_RX)); + + /* Set DLAB 1. */ + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + + /* Set DLAB 0, 8 Bit */ + soutp(UART_LCR, UART_LCR_WLEN8); + /* enable interrupts */ + soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); +#else + outb(0, io + UART_MCR); + outb(0, io + UART_IER); + /* init UART */ + /* set DLAB, speed = 115200 */ + outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR); + outb(1, io + UART_DLL); outb(0, io + UART_DLM); + /* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */ + outb(UART_LCR_WLEN7, io + UART_LCR); + /* FIFO operation */ + outb(UART_FCR_ENABLE_FIFO, io + UART_FCR); + /* interrupts */ + /* outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); */ + outb(UART_IER_RDI, io + UART_IER); + /* turn on UART */ + outb(UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2, io + UART_MCR); +#ifdef LIRC_SIR_ACTISYS_ACT200L + init_act200(); +#elif defined(LIRC_SIR_ACTISYS_ACT220L) + init_act220(); +#endif +#endif + spin_unlock_irqrestore(&hardware_lock, flags); + return 0; +} + +static void drop_hardware(void) +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + +#ifdef LIRC_ON_SA1100 + Ser2UTCR3 = 0; + + Ser2UTCR0 = sr.utcr0; + Ser2UTCR1 = sr.utcr1; + Ser2UTCR2 = sr.utcr2; + Ser2UTCR4 = sr.utcr4; + Ser2UTCR3 = sr.utcr3; + + Ser2HSCR0 = sr.hscr0; +#ifdef CONFIG_SA1100_BITSY + if (machine_is_bitsy()) + clr_bitsy_egpio(EGPIO_BITSY_IR_ON); +#endif +#ifdef CONFIG_SA1100_COLLIE + sa1100_irda_set_power_collie(0); /* power off */ +#endif +#else + /* turn off interrupts */ + outb(0, io + UART_IER); +#endif + spin_unlock_irqrestore(&hardware_lock, flags); +} + +/* SECTION: Initialisation */ + +static int init_port(void) +{ + int retval; + + /* get I/O port access and IRQ line */ +#ifndef LIRC_ON_SA1100 + if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": i/o port 0x%.4x already in use.\n", io); + return -EBUSY; + } +#endif + retval = request_irq(irq, sir_interrupt, IRQF_DISABLED, + LIRC_DRIVER_NAME, NULL); + if (retval < 0) { +# ifndef LIRC_ON_SA1100 + release_region(io, 8); +# endif + printk(KERN_ERR LIRC_DRIVER_NAME + ": IRQ %d already in use.\n", + irq); + return retval; + } +#ifndef LIRC_ON_SA1100 + printk(KERN_INFO LIRC_DRIVER_NAME + ": I/O port 0x%.4x, IRQ %d.\n", + io, irq); +#endif + + init_timer(&timerlist); + timerlist.function = sir_timeout; + timerlist.data = 0xabadcafe; + + return 0; +} + +static void drop_port(void) +{ + free_irq(irq, NULL); + del_timer_sync(&timerlist); +#ifndef LIRC_ON_SA1100 + release_region(io, 8); +#endif +} + +#ifdef LIRC_SIR_ACTISYS_ACT200L +/******************************************************/ +/* Crystal/Cirrus CS8130 IR transceiver, used in Actisys Act200L dongle */ +/* some code borrowed from Linux IRDA driver */ + +/* Regsiter 0: Control register #1 */ +#define ACT200L_REG0 0x00 +#define ACT200L_TXEN 0x01 /* Enable transmitter */ +#define ACT200L_RXEN 0x02 /* Enable receiver */ +#define ACT200L_ECHO 0x08 /* Echo control chars */ + +/* Register 1: Control register #2 */ +#define ACT200L_REG1 0x10 +#define ACT200L_LODB 0x01 /* Load new baud rate count value */ +#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */ + +/* Register 3: Transmit mode register #2 */ +#define ACT200L_REG3 0x30 +#define ACT200L_B0 0x01 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ +#define ACT200L_B1 0x02 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ +#define ACT200L_CHSY 0x04 /* StartBit Synced 0=bittime, 1=startbit */ + +/* Register 4: Output Power register */ +#define ACT200L_REG4 0x40 +#define ACT200L_OP0 0x01 /* Enable LED1C output */ +#define ACT200L_OP1 0x02 /* Enable LED2C output */ +#define ACT200L_BLKR 0x04 + +/* Register 5: Receive Mode register */ +#define ACT200L_REG5 0x50 +#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */ + /*.. other various IRDA bit modes, and TV remote modes..*/ + +/* Register 6: Receive Sensitivity register #1 */ +#define ACT200L_REG6 0x60 +#define ACT200L_RS0 0x01 /* receive threshold bit 0 */ +#define ACT200L_RS1 0x02 /* receive threshold bit 1 */ + +/* Register 7: Receive Sensitivity register #2 */ +#define ACT200L_REG7 0x70 +#define ACT200L_ENPOS 0x04 /* Ignore the falling edge */ + +/* Register 8,9: Baud Rate Dvider register #1,#2 */ +#define ACT200L_REG8 0x80 +#define ACT200L_REG9 0x90 + +#define ACT200L_2400 0x5f +#define ACT200L_9600 0x17 +#define ACT200L_19200 0x0b +#define ACT200L_38400 0x05 +#define ACT200L_57600 0x03 +#define ACT200L_115200 0x01 + +/* Register 13: Control register #3 */ +#define ACT200L_REG13 0xd0 +#define ACT200L_SHDW 0x01 /* Enable access to shadow registers */ + +/* Register 15: Status register */ +#define ACT200L_REG15 0xf0 + +/* Register 21: Control register #4 */ +#define ACT200L_REG21 0x50 +#define ACT200L_EXCK 0x02 /* Disable clock output driver */ +#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */ + +static void init_act200(void) +{ + int i; + __u8 control[] = { + ACT200L_REG15, + ACT200L_REG13 | ACT200L_SHDW, + ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL, + ACT200L_REG13, + ACT200L_REG7 | ACT200L_ENPOS, + ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1, + ACT200L_REG5 | ACT200L_RWIDL, + ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR, + ACT200L_REG3 | ACT200L_B0, + ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN, + ACT200L_REG8 | (ACT200L_115200 & 0x0f), + ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f), + ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE + }; + + /* Set DLAB 1. */ + soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); + + /* Set divisor to 12 => 9600 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 12); + + /* Set DLAB 0. */ + soutp(UART_LCR, UART_LCR_WLEN8); + /* Set divisor to 12 => 9600 Baud */ + + /* power supply */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + for (i = 0; i < 50; i++) + safe_udelay(1000); + + /* Reset the dongle : set RTS low for 25 ms */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); + for (i = 0; i < 25; i++) + udelay(1000); + + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(100); + + /* Clear DTR and set RTS to enter command mode */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + udelay(7); + +/* send out the control register settings for 115K 7N1 SIR operation */ + for (i = 0; i < sizeof(control); i++) { + soutp(UART_TX, control[i]); + /* one byte takes ~1042 usec to transmit at 9600,8N1 */ + udelay(1500); + } + + /* back to normal operation */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(50); + + udelay(1500); + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + + /* Set DLAB 1. */ + soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); + + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* Set DLAB 0, 7 Bit */ + soutp(UART_LCR, UART_LCR_WLEN7); + + /* enable interrupts */ + soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); +} +#endif + +#ifdef LIRC_SIR_ACTISYS_ACT220L +/* Derived from linux IrDA driver (drivers/net/irda/actisys.c) + * Drop me a mail for any kind of comment: maxx@spaceboyz.net */ + +void init_act220(void) +{ + int i; + + /* DLAB 1 */ + soutp(UART_LCR, UART_LCR_DLAB|UART_LCR_WLEN7); + + /* 9600 baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 12); + + /* DLAB 0 */ + soutp(UART_LCR, UART_LCR_WLEN7); + + /* reset the dongle, set DTR low for 10us */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + udelay(10); + + /* back to normal (still 9600) */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2); + + /* send RTS pulses until we reach 115200 + * i hope this is really the same for act220l/act220l+ */ + for (i = 0; i < 3; i++) { + udelay(10); + /* set RTS low for 10 us */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); + udelay(10); + /* set RTS high for 10 us */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + } + + /* back to normal operation */ + udelay(1500); /* better safe than sorry ;) */ + + /* Set DLAB 1. */ + soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); + + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + + /* Set DLAB 0, 7 Bit */ + /* The dongle doesn't seem to have any problems with operation + at 7N1 */ + soutp(UART_LCR, UART_LCR_WLEN7); + + /* enable interrupts */ + soutp(UART_IER, UART_IER_RDI); +} +#endif + +static int init_lirc_sir(void) +{ + int retval; + + init_waitqueue_head(&lirc_read_queue); + retval = init_port(); + if (retval < 0) + return retval; + init_hardware(); + printk(KERN_INFO LIRC_DRIVER_NAME + ": Installed.\n"); + return 0; +} + +#ifdef MODULE + +int init_module(void) +{ + int retval; + + retval = init_chrdev(); + if (retval < 0) + return retval; + retval = init_lirc_sir(); + if (retval) { + drop_chrdev(); + return retval; + } + return 0; +} + +void cleanup_module(void) +{ + drop_hardware(); + drop_chrdev(); + drop_port(); + printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); +} + +#ifdef LIRC_SIR_TEKRAM +MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210"); +MODULE_AUTHOR("Christoph Bartelmus"); +#elif defined(LIRC_ON_SA1100) +MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor"); +MODULE_AUTHOR("Christoph Bartelmus"); +#elif defined(LIRC_SIR_ACTISYS_ACT200L) +MODULE_DESCRIPTION("LIRC driver for Actisys Act200L"); +MODULE_AUTHOR("Karl Bongers"); +#elif defined(LIRC_SIR_ACTISYS_ACT220L) +MODULE_DESCRIPTION("LIRC driver for Actisys Act220L(+)"); +MODULE_AUTHOR("Jan Roemisch"); +#else +MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports"); +MODULE_AUTHOR("Milan Pikula"); +#endif +MODULE_LICENSE("GPL"); + +#ifdef LIRC_ON_SA1100 +module_param(irq, int, 0444); +MODULE_PARM_DESC(irq, "Interrupt (16)"); +#else +module_param(io, int, 0444); +MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); + +module_param(irq, int, 0444); +MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); + +module_param(threshold, int, 0444); +MODULE_PARM_DESC(threshold, "space detection threshold (3)"); +#endif + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +EXPORT_NO_SYMBOLS; + +#endif /* MODULE */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_sir/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_sir/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_SIR) += lirc_sir.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_parallel/lirc_parallel.c +++ linux-2.6.27/ubuntu/lirc/lirc_parallel/lirc_parallel.c @@ -0,0 +1,782 @@ +/* $Id: lirc_parallel.c,v 5.40 2008/01/13 11:13:50 lirc Exp $ */ + +/**************************************************************************** + ** lirc_parallel.c ********************************************************* + **************************************************************************** + * + * lirc_parallel - device driver for infra-red signal receiving and + * transmitting unit built by the author + * + * Copyright (C) 1998 Christoph Bartelmus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/*********************************************************************** + ************************* Includes *********************** + ***********************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) +#error "**********************************************************" +#error " Sorry, this driver needs kernel version 2.2.18 or higher " +#error "**********************************************************" +#endif + +#include + +#ifdef CONFIG_SMP +#error "--- Sorry, this driver is not SMP safe. ---" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) +#include +#endif + +#include +#include + +#include "lirc.h" +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +#include "lirc_parallel.h" + +#define LIRC_DRIVER_NAME "lirc_parallel" + +#ifndef LIRC_IRQ +#define LIRC_IRQ 7 +#endif +#ifndef LIRC_PORT +#define LIRC_PORT 0x378 +#endif +#ifndef LIRC_TIMER +#define LIRC_TIMER 65536 +#endif + +/*********************************************************************** + ************************* Globale Variablen *********************** + ***********************************************************************/ + +static int debug; +static int check_pselecd; + +unsigned int irq = LIRC_IRQ; +unsigned int io = LIRC_PORT; +#ifdef LIRC_TIMER +unsigned int timer; +unsigned int default_timer = LIRC_TIMER; +#endif + +#define WBUF_SIZE (256) +#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */ + +static lirc_t wbuf[WBUF_SIZE]; +static lirc_t rbuf[RBUF_SIZE]; + +DECLARE_WAIT_QUEUE_HEAD(lirc_wait); + +unsigned int rptr; +unsigned int wptr; +unsigned int lost_irqs; +int is_open; + +struct parport *pport; +struct pardevice *ppdevice; +int is_claimed; + +unsigned int tx_mask = 1; + +/*********************************************************************** + ************************* Interne Funktionen *********************** + ***********************************************************************/ + +static inline unsigned int in(int offset) +{ + switch (offset) { + case LIRC_LP_BASE: + return (parport_read_data(pport)); + case LIRC_LP_STATUS: + return (parport_read_status(pport)); + case LIRC_LP_CONTROL: + return (parport_read_control(pport)); + } + return 0; /* make compiler happy */ +} + +static inline void out(int offset, int value) +{ + switch (offset) { + case LIRC_LP_BASE: + parport_write_data(pport, value); + break; + case LIRC_LP_CONTROL: + parport_write_control(pport, value); + break; + case LIRC_LP_STATUS: + printk(KERN_INFO "%s: attempt to write to status register\n", + LIRC_DRIVER_NAME); + break; + } +} + +static inline unsigned int lirc_get_timer(void) +{ + return (in(LIRC_PORT_TIMER)&LIRC_PORT_TIMER_BIT); +} + +static inline unsigned int lirc_get_signal(void) +{ + return (in(LIRC_PORT_SIGNAL)&LIRC_PORT_SIGNAL_BIT); +} + +static inline void lirc_on(void) +{ + out(LIRC_PORT_DATA, tx_mask); +} + +static inline void lirc_off(void) +{ + out(LIRC_PORT_DATA, 0); +} + +static unsigned int init_lirc_timer(void) +{ + struct timeval tv, now; + unsigned int level, newlevel, timeelapsed, newtimer; + int count = 0; + + do_gettimeofday(&tv); + tv.tv_sec++; /* wait max. 1 sec. */ + level = lirc_get_timer(); + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + count++; + level = newlevel; + do_gettimeofday(&now); + } while (count < 1000 && (now.tv_sec < tv.tv_sec + || (now.tv_sec == tv.tv_sec + && now.tv_usec < tv.tv_usec))); + + timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000 + + (now.tv_usec - tv.tv_usec)); + if (count >= 1000 && timeelapsed > 0) { + if (default_timer == 0) { + /* autodetect timer */ + newtimer = (1000000*count)/timeelapsed; + printk(KERN_INFO "%s: %u Hz timer detected\n", + LIRC_DRIVER_NAME, newtimer); + return newtimer; + } else { + newtimer = (1000000*count)/timeelapsed; + if (abs(newtimer - default_timer) > default_timer/10) { + /* bad timer */ + printk(KERN_NOTICE "%s: bad timer: %u Hz\n", + LIRC_DRIVER_NAME, newtimer); + printk(KERN_NOTICE "%s: using default timer: " + "%u Hz\n", + LIRC_DRIVER_NAME, default_timer); + return default_timer; + } else { + printk(KERN_INFO "%s: %u Hz timer detected\n", + LIRC_DRIVER_NAME, newtimer); + return newtimer; /* use detected value */ + } + } + } else { + printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME); + return 0; + } +} + +static int lirc_claim(void) +{ + if (parport_claim(ppdevice) != 0) { + printk(KERN_WARNING "%s: could not claim port\n", + LIRC_DRIVER_NAME); + printk(KERN_WARNING "%s: waiting for port becoming available" + "\n", LIRC_DRIVER_NAME); + if (parport_claim_or_block(ppdevice) < 0) { + printk(KERN_NOTICE "%s: could not claim port, giving" + " up\n", LIRC_DRIVER_NAME); + return 0; + } + } + out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + is_claimed = 1; + return 1; +} + +/*********************************************************************** + ************************* interrupt handler ************************ + ***********************************************************************/ + +static inline void rbuf_write(lirc_t signal) +{ + unsigned int nwptr; + + nwptr = (wptr + 1) & (RBUF_SIZE - 1); + if (nwptr == rptr) { + /* no new signals will be accepted */ + lost_irqs++; + printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME); + return; + } + rbuf[wptr] = signal; + wptr = nwptr; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void irq_handler(int i, void *blah, struct pt_regs *regs) +#else +static void irq_handler(int i, void *blah) +#endif +{ + struct timeval tv; + static struct timeval lasttv; + static int init; + long signal; + lirc_t data; + unsigned int level, newlevel; + unsigned int timeout; + + if (!MOD_IN_USE) + return; + + if (!is_claimed) + return; + + /* disable interrupt */ + /* + disable_irq(irq); + out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN)); + */ + if (check_pselecd && (in(1) & LP_PSELECD)) + return; + +#ifdef LIRC_TIMER + if (init) { + do_gettimeofday(&tv); + + signal = tv.tv_sec - lasttv.tv_sec; + if (signal > 15) + /* really long time */ + data = PULSE_MASK; + else + data = (lirc_t) (signal*1000000 + + tv.tv_usec - lasttv.tv_usec + + LIRC_SFH506_DELAY); + + rbuf_write(data); /* space */ + } else { + if (timer == 0) { + /* wake up; we'll lose this signal + * but it will be garbage if the device + * is turned on anyway */ + timer = init_lirc_timer(); + /* enable_irq(irq); */ + return; + } + init = 1; + } + + timeout = timer/10; /* timeout after 1/10 sec. */ + signal = 1; + level = lirc_get_timer(); + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + signal++; + level = newlevel; + + /* giving up */ + if (signal > timeout + || (check_pselecd && (in(1) & LP_PSELECD))) { + signal = 0; + printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME); + break; + } + } + while (lirc_get_signal()); + if (signal != 0) { + /* ajust value to usecs */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) + unsigned long long helper; + + helper = ((unsigned long long) signal)*1000000; + do_div(helper, timer); + signal = (long) helper; +#else + signal = (long) ((((double) signal)*1000000)/timer); +#endif + + if (signal > LIRC_SFH506_DELAY) + data = signal - LIRC_SFH506_DELAY; + else + data = 1; + rbuf_write(PULSE_BIT|data); /* pulse */ + } + do_gettimeofday(&lasttv); +#else + /* add your code here */ +#endif + + wake_up_interruptible(&lirc_wait); + + /* enable interrupt */ + /* + enable_irq(irq); + out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN); + */ +} + +/*********************************************************************** + ************************** file_operations ************************ + ***********************************************************************/ + +static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig) +{ + return -ESPIPE; +} + +static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos) +{ + int result = 0; + int count = 0; + DECLARE_WAITQUEUE(wait, current); + + if (n % sizeof(lirc_t)) + return -EINVAL; + + add_wait_queue(&lirc_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + while (count < n) { + if (rptr != wptr) { + if (copy_to_user(buf+count, (char *) &rbuf[rptr], + sizeof(lirc_t))) { + result = -EFAULT; + break; + } + rptr = (rptr + 1) & (RBUF_SIZE - 1); + count += sizeof(lirc_t); + } else { + if (filep->f_flags & O_NONBLOCK) { + result = -EAGAIN; + break; + } + if (signal_pending(current)) { + result = -ERESTARTSYS; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + } + remove_wait_queue(&lirc_wait, &wait); + set_current_state(TASK_RUNNING); + return (count ? count : result); +} + +static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, + loff_t *ppos) +{ + int count; + unsigned int i; + unsigned int level, newlevel; + unsigned long flags; + lirc_t counttimer; + + if (!is_claimed) + return(-EBUSY); + + if (n % sizeof(lirc_t)) + return(-EINVAL); + + count = n / sizeof(lirc_t); + + if (count > WBUF_SIZE || count % 2 == 0) + return(-EINVAL); + + if (copy_from_user(wbuf, buf, n)) + return -EFAULT; + +#ifdef LIRC_TIMER + if (timer == 0) { + /* try again if device is ready */ + timer = init_lirc_timer(); + if (timer == 0) + return(-EIO); + } + + /* ajust values from usecs */ + for (i = 0; i < count; i++) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) + unsigned long long helper; + + helper = ((unsigned long long) wbuf[i])*timer; + do_div(helper, 1000000); + wbuf[i] = (lirc_t) helper; +#else + wbuf[i] = (lirc_t) (((double) wbuf[i])*timer/1000000); +#endif + } + + local_irq_save(flags); + i = 0; + while (i < count) { + level = lirc_get_timer(); + counttimer = 0; + lirc_on(); + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + counttimer++; + level = newlevel; + if (check_pselecd && (in(1) & LP_PSELECD)) { + lirc_off(); + local_irq_restore(flags); + return -EIO; + } + } while (counttimer < wbuf[i]); + i++; + + lirc_off(); + if (i == count) + break; + counttimer = 0; + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + counttimer++; + level = newlevel; + if (check_pselecd && (in(1) & LP_PSELECD)) { + local_irq_restore(flags); + return -EIO; + } + } while (counttimer < wbuf[i]); + i++; + } + local_irq_restore(flags); +#else + /* place code that handles write + * without external timer here */ +#endif + return n; +} + +static unsigned int lirc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &lirc_wait, wait); + if (rptr != wptr) + return (POLLIN|POLLRDNORM); + return 0; +} + +static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int result; + unsigned long features = LIRC_CAN_SET_TRANSMITTER_MASK | + LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; + unsigned long mode; + unsigned int ivalue; + + switch (cmd) { + case LIRC_GET_FEATURES: + result = put_user(features, (unsigned long *) arg); + if (result) + return result; + break; + case LIRC_GET_SEND_MODE: + result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); + if (result) + return result; + break; + case LIRC_GET_REC_MODE: + result = put_user(LIRC_MODE_MODE2, (unsigned long *) arg); + if (result) + return result; + break; + case LIRC_SET_SEND_MODE: + result = get_user(mode, (unsigned long *) arg); + if (result) + return result; + if (mode != LIRC_MODE_PULSE) + return -EINVAL; + break; + case LIRC_SET_REC_MODE: + result = get_user(mode, (unsigned long *) arg); + if (result) + return result; + if (mode != LIRC_MODE_MODE2) + return -ENOSYS; + break; + case LIRC_SET_TRANSMITTER_MASK: + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if ((ivalue & LIRC_PARALLEL_TRANSMITTER_MASK) != ivalue) + return LIRC_PARALLEL_MAX_TRANSMITTERS; + tx_mask = ivalue; + break; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int lirc_open(struct inode *node, struct file *filep) +{ + if (MOD_IN_USE || !lirc_claim()) + return -EBUSY; + + parport_enable_irq(pport); + + /* init read ptr */ + rptr = 0; + wptr = 0; + lost_irqs = 0; + + MOD_INC_USE_COUNT; + is_open = 1; + return 0; +} + +static int lirc_close(struct inode *node, struct file *filep) +{ + if (is_claimed) { + is_claimed = 0; + parport_release(ppdevice); + } + is_open = 0; + MOD_DEC_USE_COUNT; + return 0; +} + +static struct file_operations lirc_fops = { + .llseek = lirc_lseek, + .read = lirc_read, + .write = lirc_write, + .poll = lirc_poll, + .ioctl = lirc_ioctl, + .open = lirc_open, + .release = lirc_close +}; + +static int set_use_inc(void *data) +{ +#if WE_DONT_USE_LOCAL_OPEN_CLOSE + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static void set_use_dec(void *data) +{ +#if WE_DONT_USE_LOCAL_OPEN_CLOSE + MOD_DEC_USE_COUNT; +#endif +} + +static struct lirc_plugin plugin = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .get_queue = NULL, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + +#ifdef MODULE + +static int pf(void *handle); +static void kf(void *handle); + +static struct timer_list poll_timer; +static void poll_state(unsigned long ignored); + +static void poll_state(unsigned long ignored) +{ + printk(KERN_NOTICE "%s: time\n", + LIRC_DRIVER_NAME); + del_timer(&poll_timer); + if (is_claimed) + return; + kf(NULL); + if (!is_claimed) { + printk(KERN_NOTICE "%s: could not claim port, giving up\n", + LIRC_DRIVER_NAME); + init_timer(&poll_timer); + poll_timer.expires = jiffies + HZ; + poll_timer.data = (unsigned long)current; + poll_timer.function = poll_state; + add_timer(&poll_timer); + } +} + +static int pf(void *handle) +{ + parport_disable_irq(pport); + is_claimed = 0; + return 0; +} + +static void kf(void *handle) +{ + if (!is_open) + return; + if (!lirc_claim()) + return; + parport_enable_irq(pport); + lirc_off(); + /* this is a bit annoying when you actually print...*/ + /* + printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME); + */ +} + +/*********************************************************************** + ****************** init_module()/cleanup_module() ****************** + ***********************************************************************/ + +int init_module(void) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 3) + pport = parport_find_base(io); +#else + pport = parport_enumerate(); + while (pport != NULL) { + if (pport->base == io) + break; + pport = pport->next; + } +#endif + if (pport == NULL) { + printk(KERN_NOTICE "%s: no port at %x found\n", + LIRC_DRIVER_NAME, io); + return -ENXIO; + } + ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME, + pf, kf, irq_handler, 0, NULL); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 3) + parport_put_port(pport); +#endif + if (ppdevice == NULL) { + printk(KERN_NOTICE "%s: parport_register_device() failed\n", + LIRC_DRIVER_NAME); + return -ENXIO; + } + if (parport_claim(ppdevice) != 0) + goto skip_init; + is_claimed = 1; + out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + +#ifdef LIRC_TIMER + if (debug) + out(LIRC_PORT_DATA, tx_mask); + + timer = init_lirc_timer(); + +#if 0 /* continue even if device is offline */ + if (timer == 0) { + is_claimed = 0; + parport_release(pport); + parport_unregister_device(ppdevice); + return -EIO; + } + +#endif + if (debug) + out(LIRC_PORT_DATA, 0); +#endif + + is_claimed = 0; + parport_release(ppdevice); + skip_init: + plugin.minor = lirc_register_plugin(&plugin); + if (plugin.minor < 0) { + printk(KERN_NOTICE "%s: register_chrdev() failed\n", + LIRC_DRIVER_NAME); + parport_unregister_device(ppdevice); + return -EIO; + } + printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n", + LIRC_DRIVER_NAME, io, irq); + return 0; +} + +void cleanup_module(void) +{ + parport_unregister_device(ppdevice); + lirc_unregister_plugin(plugin.minor); +} + +MODULE_DESCRIPTION("Infrared receiver driver for parallel ports."); +MODULE_AUTHOR("Christoph Bartelmus"); +MODULE_LICENSE("GPL"); + +module_param(io, int, 0444); +MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)"); + +module_param(irq, int, 0444); +MODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); + +module_param(tx_mask, int, 0444); +MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +module_param(check_pselecd, bool, 0644); +MODULE_PARM_DESC(debug, "Check for printer (default: 0)"); + +EXPORT_NO_SYMBOLS; + +#endif /* MODULE */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_parallel/lirc_parallel.h +++ linux-2.6.27/ubuntu/lirc/lirc_parallel/lirc_parallel.h @@ -0,0 +1,26 @@ +/* $Id: lirc_parallel.h,v 5.2 2007/01/25 04:32:05 lirc Exp $ */ + +#ifndef _LIRC_PARALLEL_H +#define _LIRC_PARALLEL_H + +#include + +#define LIRC_PORT_LEN 3 + +#define LIRC_LP_BASE 0 +#define LIRC_LP_STATUS 1 +#define LIRC_LP_CONTROL 2 + +#define LIRC_PORT_DATA LIRC_LP_BASE /* base */ +#define LIRC_PORT_TIMER LIRC_LP_STATUS /* status port */ +#define LIRC_PORT_TIMER_BIT LP_PBUSY /* busy signal */ +#define LIRC_PORT_SIGNAL LIRC_LP_STATUS /* status port */ +#define LIRC_PORT_SIGNAL_BIT LP_PACK /* ack signal */ +#define LIRC_PORT_IRQ LIRC_LP_CONTROL /* control port */ + +#define LIRC_SFH506_DELAY 0 /* delay t_phl in usecs */ + +#define LIRC_PARALLEL_MAX_TRANSMITTERS 8 +#define LIRC_PARALLEL_TRANSMITTER_MASK ((1< + * modified for PixelView (BT878P+W/FM) by + * Michal Kochanowicz + * Christoph Bartelmus + * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by + * Ulrich Mueller + * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by + * Stefan Jahn + * modified for inclusion into kernel sources by + * Jerome Brock + * modified for Leadtek Winfast PVR2000 by + * Thomas Reitmayr (treitmayr@yahoo.com) + * modified for Hauppauge HVR-1300 by + * Jan Frey (jfrey@gmx.de) + * + * parts are cut&pasted from the old lirc_haup.c driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +struct IR { + struct lirc_plugin l; + struct i2c_client c; + int nextkey; + unsigned char b[3]; + unsigned char bits; + unsigned char flag; +}; + +/* ----------------------------------------------------------------------- */ + +#define DEVICE_NAME "lirc_i2c" + +/* ----------------------------------------------------------------------- */ +/* insmod parameters */ + +static int debug; /* debug output */ +static int minor = -1; /* minor number */ + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG DEVICE_NAME ": " fmt, \ + ## args); \ + } while (0) + +/* ----------------------------------------------------------------------- */ + +static inline int reverse(int data, int bits) +{ + int i; + int c; + + for (c = 0, i = 0; i < bits; i++) + c |= (((data & (1<c, keybuf, 1); + /* poll IR chip */ + if (i2c_master_recv(&ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { + dprintk("read error\n"); + return -EIO; + } + + dprintk("key (0x%02x%02x%02x%02x)\n", + keybuf[0], keybuf[1], keybuf[2], keybuf[3]); + + /* key pressed ? */ + if (keybuf[2] == 0xff) + return -ENODATA; + + /* remove repeat bit */ + keybuf[2] &= 0x7f; + keybuf[3] |= 0x80; + + lirc_buffer_write_1(buf, keybuf); + return 0; +} + +static int add_to_buf_pcf8574(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + int rc; + unsigned char all, mask; + unsigned char key; + + /* compute all valid bits (key code + pressed/release flag) */ + all = ir->bits | ir->flag; + + /* save IR writable mask bits */ + mask = i2c_smbus_read_byte(&ir->c) & ~all; + + /* send bit mask */ + rc = i2c_smbus_write_byte(&ir->c, (0xff & all) | mask); + + /* receive scan code */ + rc = i2c_smbus_read_byte(&ir->c); + + if (rc == -1) { + dprintk("%s read error\n", ir->c.name); + return -EIO; + } + + /* drop duplicate polls */ + if (ir->b[0] == (rc & all)) + return -ENODATA; + + ir->b[0] = rc & all; + + dprintk("%s key 0x%02X %s\n", ir->c.name, rc & ir->bits, + (rc & ir->flag) ? "released" : "pressed"); + + if (rc & ir->flag) { + /* ignore released buttons */ + return -ENODATA; + } + + /* set valid key code */ + key = rc & ir->bits; + lirc_buffer_write_1(buf, &key); + return 0; +} + +/* common for Hauppauge IR receivers */ +static int add_to_buf_haup_common(void *data, struct lirc_buffer *buf, + unsigned char *keybuf, int size, int offset) +{ + struct IR *ir = data; + __u16 code; + unsigned char codes[2]; + + /* poll IR chip */ + if (size == i2c_master_recv(&ir->c, keybuf, size)) { + ir->b[0] = keybuf[offset]; + ir->b[1] = keybuf[offset+1]; + ir->b[2] = keybuf[offset+2]; + dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]); + } else { + dprintk("read error\n"); + /* keep last successfull read buffer */ + } + + /* key pressed ? */ + if ((ir->b[0] & 0x80) == 0) + return -ENODATA; + + /* look what we have */ + code = (((__u16)ir->b[0]&0x7f)<<6) | (ir->b[1]>>2); + + codes[0] = (code >> 8) & 0xff; + codes[1] = code & 0xff; + + /* return it */ + lirc_buffer_write_1(buf, codes); + return 0; +} + +/* specific for the Hauppauge PVR150 IR receiver */ +static int add_to_buf_haup_pvr150(void *data, struct lirc_buffer *buf) +{ + unsigned char keybuf[6]; + /* fetch 6 bytes, first relevant is at offset 3 */ + return add_to_buf_haup_common(data, buf, keybuf, 6, 3); +} + +/* used for all Hauppauge IR receivers but the PVR150 */ +static int add_to_buf_haup(void *data, struct lirc_buffer *buf) +{ + unsigned char keybuf[3]; + /* fetch 3 bytes, first relevant is at offset 0 */ + return add_to_buf_haup_common(data, buf, keybuf, 3, 0); +} + + +static int add_to_buf_pvr2000(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + unsigned char key; + s32 flags; + s32 code; + + /* poll IR chip */ + flags = i2c_smbus_read_byte_data(&ir->c, 0x10); + if (-1 == flags) { + dprintk("read error\n"); + return -ENODATA; + } + /* key pressed ? */ + if (0 == (flags & 0x80)) + return -ENODATA; + + /* read actual key code */ + code = i2c_smbus_read_byte_data(&ir->c, 0x00); + if (-1 == code) { + dprintk("read error\n"); + return -ENODATA; + } + + key = code & 0xFF; + + dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", key, flags & 0xFF); + + /* return it */ + lirc_buffer_write_1(buf, &key); + return 0; +} + +static int add_to_buf_pixelview(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + unsigned char key; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c, &key, 1)) { + dprintk("read error\n"); + return -1; + } + dprintk("key %02x\n", key); + + /* return it */ + lirc_buffer_write_1(buf, &key); + return 0; +} + +static int add_to_buf_pv951(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + unsigned char key; + unsigned char codes[4]; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c, &key, 1)) { + dprintk("read error\n"); + return -ENODATA; + } + /* ignore 0xaa */ + if (key == 0xaa) + return -ENODATA; + dprintk("key %02x\n", key); + + codes[0] = 0x61; + codes[1] = 0xD6; + codes[2] = reverse(key, 8); + codes[3] = (~codes[2])&0xff; + + lirc_buffer_write_1(buf, codes); + return 0; +} + +static int add_to_buf_knc1(void *data, struct lirc_buffer *buf) +{ + static unsigned char last_key = 0xFF; + struct IR *ir = data; + unsigned char key; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c, &key, 1)) { + dprintk("read error\n"); + return -ENODATA; + } + + /* it seems that 0xFE indicates that a button is still hold + down, while 0xFF indicates that no button is hold + down. 0xFE sequences are sometimes interrupted by 0xFF */ + + dprintk("key %02x\n", key); + + if (key == 0xFF) + return -ENODATA; + + if (key == 0xFE) + key = last_key; + + last_key = key; + lirc_buffer_write_1(buf, &key); + + return 0; +} + +static int set_use_inc(void *data) +{ + struct IR *ir = data; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) + i2c_use_client(&ir->c); +#else + int ret; + + /* lock bttv in memory while /dev/lirc is in use */ + ret = i2c_use_client(&ir->c); + if (ret != 0) + return ret; +#endif + + MOD_INC_USE_COUNT; + return 0; +} + +static void set_use_dec(void *data) +{ + struct IR *ir = data; + + i2c_release_client(&ir->c); + MOD_DEC_USE_COUNT; +} + +static struct lirc_plugin lirc_template = { + .name = "lirc_i2c", + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .dev = NULL, + .owner = THIS_MODULE, +}; + +/* ----------------------------------------------------------------------- */ + +static int ir_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind); +static int ir_detach(struct i2c_client *client); +static int ir_probe(struct i2c_adapter *adap); +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); + +static struct i2c_driver driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) + .name = "i2c ir driver", + .flags = I2C_DF_NOTIFY, +#else + .driver = { + .owner = THIS_MODULE, + .name = "i2c ir driver", + }, +#endif + .id = I2C_DRIVERID_EXP3, /* FIXME */ + .attach_adapter = ir_probe, + .detach_client = ir_detach, + .command = ir_command, +}; + +static struct i2c_client client_template = { + .name = "unset", + .driver = &driver +}; + +static int ir_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct IR *ir; + int err; + + client_template.adapter = adap; + client_template.addr = addr; + + ir = kmalloc(sizeof(struct IR), GFP_KERNEL); + if (!ir) + return -ENOMEM; + memcpy(&ir->l, &lirc_template, sizeof(struct lirc_plugin)); + memcpy(&ir->c, &client_template, sizeof(struct i2c_client)); + + ir->c.adapter = adap; + ir->c.addr = addr; + i2c_set_clientdata(&ir->c, ir); + ir->l.data = ir; + ir->l.minor = minor; + ir->l.sample_rate = 10; + ir->nextkey = -1; + + switch (addr) { + case 0x64: + strlcpy(ir->c.name, "Pixelview IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_pixelview; + break; + case 0x4b: + strlcpy(ir->c.name, "PV951 IR", I2C_NAME_SIZE); + ir->l.code_length = 32; + ir->l.add_to_buf = add_to_buf_pv951; + break; + case 0x71: +#ifdef I2C_HW_B_CX2341X + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) || + adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) { +#else + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) { +#endif + /* The PVR150 IR receiver uses the same protocol as + * other Hauppauge cards, but the data flow is + * different, so we need to deal with it by its own. */ + strlcpy(ir->c.name, "Hauppauge PVR150", I2C_NAME_SIZE); + } else /* I2C_HW_B_CX2388x */ + strlcpy(ir->c.name, "Hauppauge HVR1300", I2C_NAME_SIZE); + ir->l.code_length = 13; + ir->l.add_to_buf = add_to_buf_haup_pvr150; + break; + case 0x6b: + strlcpy(ir->c.name, "Adaptec IR", I2C_NAME_SIZE); + ir->l.code_length = 32; + ir->l.add_to_buf = add_to_buf_adap; + break; + case 0x18: + case 0x1a: +#ifdef I2C_HW_B_CX2341X + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) || + adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) { +#else + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) { +#endif + strlcpy(ir->c.name, "Hauppauge IR", I2C_NAME_SIZE); + ir->l.code_length = 13; + ir->l.add_to_buf = add_to_buf_haup; + } else { /* I2C_HW_B_CX2388x */ + strlcpy(ir->c.name, "Leadtek IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_pvr2000; + } + break; + case 0x30: + strlcpy(ir->c.name, "KNC ONE IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_knc1; + break; + case 0x21: + case 0x23: + strlcpy(ir->c.name, "TV-Box IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_pcf8574; + ir->bits = flags & 0xff; + ir->flag = (flags >> 8) & 0xff; + break; + default: + /* shouldn't happen */ + printk("lirc_i2c: Huh? unknown i2c address (0x%02x)?\n", addr); + kfree(ir); + return -1; + } + printk(KERN_INFO "lirc_i2c: chip 0x%x found @ 0x%02x (%s)\n", + adap->id, addr, ir->c.name); + + /* register device */ + err = i2c_attach_client(&ir->c); + if (err) { + kfree(ir); + return err; + } + ir->l.minor = lirc_register_plugin(&ir->l); + + return 0; +} + +static int ir_detach(struct i2c_client *client) +{ + struct IR *ir = i2c_get_clientdata(client); + + /* unregister device */ + lirc_unregister_plugin(ir->l.minor); + i2c_detach_client(&ir->c); + + /* free memory */ + kfree(ir); + return 0; +} + +static int ir_probe(struct i2c_adapter *adap) +{ + /* The external IR receiver is at i2c address 0x34 (0x35 for + * reads). Future Hauppauge cards will have an internal + * receiver at 0x30 (0x31 for reads). In theory, both can be + * fitted, and Hauppauge suggest an external overrides an + * internal. + * + * That's why we probe 0x1a (~0x34) first. CB + * + * The i2c address for the Hauppauge PVR-150 card is 0xe2, + * so we need to probe 0x71 as well. */ + + static const int probe[] = { + 0x1a, /* Hauppauge IR external */ + 0x18, /* Hauppauge IR internal */ + 0x71, /* Hauppauge IR (PVR150) */ + 0x4b, /* PV951 IR */ + 0x64, /* Pixelview IR */ + 0x30, /* KNC ONE IR */ + 0x6b, /* Adaptec IR */ + -1}; + +#ifdef I2C_HW_B_CX2388x + static const int probe_cx88[] = { + 0x18, /* Leadtek Winfast PVR2000 */ + 0x71, /* Hauppauge HVR-IR */ + -1}; +#endif + + struct i2c_client c; + char buf; + int i, rc; + +#ifdef I2C_HW_B_CX2341X + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) || + adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) +#else + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) +#endif + { + memset(&c, 0, sizeof(c)); + c.adapter = adap; + for (i = 0; -1 != probe[i]; i++) { + c.addr = probe[i]; + rc = i2c_master_recv(&c, &buf, 1); + dprintk("probe 0x%02x @ %s: %s\n", + probe[i], adap->name, + (1 == rc) ? "yes" : "no"); + if (1 == rc) + ir_attach(adap, probe[i], 0, 0); + } + } + +#ifdef I2C_HW_B_CX2388x + /* Leadtek Winfast PVR2000 or Hauppauge HVR-1300 */ + else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2388x)) { + memset(&c, 0, sizeof(c)); + c.adapter = adap; + for (i = 0; -1 != probe_cx88[i]; i++) { + c.addr = probe_cx88[i]; + rc = i2c_master_recv(&c, &buf, 1); + dprintk("probe 0x%02x @ %s: %s\n", + c.addr, adap->name, + (1 == rc) ? "yes" : "no"); + if (1 == rc) + ir_attach(adap, c.addr, 0, 0); + } + } +#endif + + /* Asus TV-Box and Creative/VisionTek BreakOut-Box (PCF8574) */ + else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_RIVA)) { + /* addresses to probe; + leave 0x24 and 0x25 because SAA7113H possibly uses it + 0x21 and 0x22 possibly used by SAA7108E + Asus: 0x21 is a correct address (channel 1 of PCF8574) + Creative: 0x23 is a correct address (channel 3 of PCF8574) + VisionTek: 0x23 is a correct address (channel 3 of PCF8574) + */ + static const int pcf_probe[] = { 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, -1 }; + int ret1, ret2, ret3, ret4; + unsigned char bits = 0, flag = 0; + + memset(&c, 0, sizeof(c)); + c.adapter = adap; + for (i = 0; -1 != pcf_probe[i]; i++) { + c.addr = pcf_probe[i]; + ret1 = i2c_smbus_write_byte(&c, 0xff); + ret2 = i2c_smbus_read_byte(&c); + ret3 = i2c_smbus_write_byte(&c, 0x00); + ret4 = i2c_smbus_read_byte(&c); + + /* ensure that the writable bitmask works correctly */ + rc = 0; + if (ret1 != -1 && ret2 != -1 && + ret3 != -1 && ret4 != -1) { + /* in the Asus TV-Box: bit 1-0 */ + if (((ret2 & 0x03) == 0x03) && + ((ret4 & 0x03) == 0x00)) { + bits = (unsigned char) ~0x07; + flag = 0x04; + rc = 1; + } + /* in the Creative/VisionTek BreakOut-Box: bit 7-6 */ + if (((ret2 & 0xc0) == 0xc0) && + ((ret4 & 0xc0) == 0x00)) { + bits = (unsigned char) ~0xe0; + flag = 0x20; + rc = 1; + } + } + dprintk("probe 0x%02x @ %s: %s\n", + c.addr, adap->name, rc ? "yes" : "no"); + if (rc) + ir_attach(adap, pcf_probe[i], + bits|(flag<<8), 0); + } + } + + return 0; +} + +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + /* nothing */ + return 0; +} + +/* ----------------------------------------------------------------------- */ +#ifdef MODULE + +int init_module(void) +{ + request_module("bttv"); + request_module("rivatv"); + request_module("ivtv"); + request_module("cx8800"); + i2c_add_driver(&driver); + return 0; +} + +void cleanup_module(void) +{ + i2c_del_driver(&driver); +} + +MODULE_DESCRIPTION("Infrared receiver driver for Hauppauge and " + "Pixelview cards (i2c stack)"); +MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, " + "Ulrich Mueller, Stefan Jahn, Jerome Brock"); +MODULE_LICENSE("GPL"); + +module_param(minor, int, 0444); +MODULE_PARM_DESC(minor, "Preferred minor device number"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +EXPORT_NO_SYMBOLS; + +#endif /* MODULE */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_sasem/lirc_sasem.c +++ linux-2.6.27/ubuntu/lirc/lirc_sasem/lirc_sasem.c @@ -0,0 +1,1130 @@ +/* $Id: lirc_sasem.c,v 1.21 2007/09/30 09:58:46 lirc Exp $ */ + +/* lirc_sasem.c - USB remote support for LIRC + * Version 0.5 + * + * Copyright (C) 2004-2005 Oliver Stabel + * Tim Davies + * + * This driver was derived from: + * Venky Raju + * "lirc_imon - "LIRC plugin/VFD driver for Ahanix/Soundgraph IMON IR/VFD" + * Paul Miller 's 2003-2004 + * "lirc_atiusb - USB remote support for LIRC" + * Culver Consulting Services 's 2003 + * "Sasem OnAir VFD/IR USB driver" + * + * + * 2004/06/13 - 0.1 + * initial version + * + * 2004/06/28 - 0.2 + * added file system support to write data to VFD device (used + * in conjunction with LCDProc) + * + * 2004/11/22 - 0.3 + * Ported to 2.6 kernel + * - Tim Davies + * + * 2005/03/29 - 0.4 + * A few tidyups and keypress timings + * - Tim Davies + * + * 2005/06/23 - 0.5 + * A complete rewrite (shamelessly) based on lirc_imon.c + * Tim Davies + * + * NOTE - The LCDproc iMon driver should work with this module. More info at + * http://www.frogstorm.info/sasem + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 22) +#error "*** Sorry, this driver requires kernel version 2.4.22 or higher" +#endif + +#include + +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#include + +#include "kcompat.h" +#include "lirc.h" +#include "lirc_dev/lirc_dev.h" + + +#define MOD_AUTHOR "Oliver Stabel , " \ + "Tim Davies " +#define MOD_DESC "USB Driver for Sasem Remote Controller V1.1" +#define MOD_NAME "lirc_sasem" +#define MOD_VERSION "0.5" + +#define VFD_MINOR_BASE 144 /* Same as LCD */ +#define DEVFS_MODE S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH +#define DEVFS_NAME LIRC_DEVFS_PREFIX "lcd%d" + +#define BUF_CHUNK_SIZE 8 +#define BUF_SIZE 128 + +#define SUCCESS 0 +#define TRUE 1 +#define FALSE 0 + +#define IOCTL_LCD_CONTRAST 1 + +/* ------------------------------------------------------------ + * P R O T O T Y P E S + * ------------------------------------------------------------ + */ + +/* USB Callback prototypes */ +#ifdef KERNEL_2_5 +static int sasem_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void sasem_disconnect(struct usb_interface *interface); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_rx_callback(struct urb *urb, struct pt_regs *regs); +static void usb_tx_callback(struct urb *urb, struct pt_regs *regs); +#else +static void usb_rx_callback(struct urb *urb); +static void usb_tx_callback(struct urb *urb); +#endif +#else +static void *sasem_probe(struct usb_device *dev, unsigned int intf, + const struct usb_device_id *id); +static void sasem_disconnect(struct usb_device *dev, void *data); +static void usb_rx_callback(struct urb *urb); +static void usb_tx_callback(struct urb *urb); +#endif + +/* VFD file_operations function prototypes */ +static int vfd_open(struct inode *inode, struct file *file); +static int vfd_ioctl(struct inode *inode, struct file *file, + unsigned cmd, unsigned long arg); +static int vfd_close(struct inode *inode, struct file *file); +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/* LIRC plugin function prototypes */ +static int ir_open(void *data); +static void ir_close(void *data); + +/* Driver init/exit prototypes */ +static int __init sasem_init(void); +static void __exit sasem_exit(void); + +/* ------------------------------------------------------------ + * G L O B A L S + * ------------------------------------------------------------ + */ + +struct sasem_context { + + struct usb_device *dev; + int vfd_isopen; /* VFD port has been opened */ + unsigned int vfd_contrast; /* VFD contrast */ +#if !defined(KERNEL_2_5) + int subminor; /* index into minor_table */ + devfs_handle_t devfs; +#endif + int ir_isopen; /* IR port has been opened */ + int dev_present; /* USB device presence */ + struct semaphore sem; /* to lock this object */ + wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ + + struct lirc_plugin *plugin; + struct usb_endpoint_descriptor *rx_endpoint; + struct usb_endpoint_descriptor *tx_endpoint; + struct urb *rx_urb; + struct urb *tx_urb; + unsigned char usb_rx_buf [8]; + unsigned char usb_tx_buf [8]; + + struct tx_t { + unsigned char data_buf [32]; /* user data buffer */ + struct completion finished; /* wait for write to finish */ + atomic_t busy; /* write in progress */ + int status; /* status of tx completion */ + } tx; + + /* for dealing with repeat codes (wish there was a toggle bit!) */ + struct timeval presstime; + char lastcode[8]; + int codesaved; +}; + +#define LOCK_CONTEXT down(&context->sem) +#define UNLOCK_CONTEXT up(&context->sem) + +/* VFD file operations */ +static struct file_operations vfd_fops = { + + .owner = THIS_MODULE, + .open = &vfd_open, + .write = &vfd_write, + .ioctl = &vfd_ioctl, + .release = &vfd_close +}; + +/* USB Device ID for Sasem USB Control Board */ +static struct usb_device_id sasem_usb_id_table [] = { + { USB_DEVICE(0x11ba, 0x0101) }, /* Sasem */ + {} +}; + +/* USB Device data */ +static struct usb_driver sasem_driver = { + LIRC_THIS_MODULE(.owner = THIS_MODULE) + .name = MOD_NAME, + .probe = sasem_probe, + .disconnect = sasem_disconnect, + .id_table = sasem_usb_id_table, +#if !defined(KERNEL_2_5) + .fops = &vfd_fops, + .minor = VFD_MINOR_BASE, +#endif +}; + +#ifdef KERNEL_2_5 +static struct usb_class_driver sasem_class = { + .name = DEVFS_NAME, + .fops = &vfd_fops, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) + .mode = DEVFS_MODE, +#endif + .minor_base = VFD_MINOR_BASE, +}; +#endif + +/* to prevent races between open() and disconnect() */ +static DECLARE_MUTEX(disconnect_sem); + +static int debug; + +#if !defined(KERNEL_2_5) + +#define MAX_DEVICES 4 /* In case there's more than one Sasem device */ +static struct sasem_context *minor_table [MAX_DEVICES]; + +/* the global usb devfs handle */ +extern devfs_handle_t usb_devfs_handle; + +#endif + +/* ------------------------------------------------------------ + * M O D U L E C O D E + * ------------------------------------------------------------ + */ + +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_DESCRIPTION(MOD_DESC); +MODULE_LICENSE("GPL"); +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); + +static inline void delete_context(struct sasem_context *context) +{ + usb_free_urb(context->tx_urb); /* VFD */ + usb_free_urb(context->rx_urb); /* IR */ + lirc_buffer_free(context->plugin->rbuf); + kfree(context->plugin->rbuf); + kfree(context->plugin); + kfree(context); + + if (debug) + info("%s: context deleted", __FUNCTION__); +} + +static inline void deregister_from_lirc(struct sasem_context *context) +{ + int retval; + int minor = context->plugin->minor; + + retval = lirc_unregister_plugin(minor); + if (retval) + err("%s: unable to deregister from lirc (%d)", + __FUNCTION__, retval); + else + info("Deregistered Sasem plugin (minor:%d)", minor); + +} + +/** + * Called when the VFD device (e.g. /dev/usb/lcd) + * is opened by the application. + */ +static int vfd_open(struct inode *inode, struct file *file) +{ +#ifdef KERNEL_2_5 + struct usb_interface *interface; +#endif + struct sasem_context *context = NULL; + int subminor; + int retval = SUCCESS; + + /* prevent races with disconnect */ + down(&disconnect_sem); + +#ifdef KERNEL_2_5 + subminor = iminor(inode); + interface = usb_find_interface(&sasem_driver, subminor); + if (!interface) { + err("%s: could not find interface for minor %d", + __FUNCTION__, subminor); + retval = -ENODEV; + goto exit; + } + context = usb_get_intfdata(interface); +#else + subminor = MINOR(inode->i_rdev) - VFD_MINOR_BASE; + if (subminor < 0 || subminor >= MAX_DEVICES) { + err("%s: no record of minor %d", __FUNCTION__, subminor); + retval = -ENODEV; + goto exit; + } + context = minor_table [subminor]; +#endif + + if (!context) { + err("%s: no context found for minor %d", + __FUNCTION__, subminor); + retval = -ENODEV; + goto exit; + } + + LOCK_CONTEXT; + + if (context->vfd_isopen) { + err("%s: VFD port is already open", __FUNCTION__); + retval = -EBUSY; + } else { + MOD_INC_USE_COUNT; + context->vfd_isopen = TRUE; + file->private_data = context; + info("VFD port opened"); + } + + UNLOCK_CONTEXT; + +exit: + up(&disconnect_sem); + return retval; +} + +/** + * Called when the VFD device (e.g. /dev/usb/lcd) + * is closed by the application. + */ +static int vfd_ioctl(struct inode *inode, struct file *file, + unsigned cmd, unsigned long arg) +{ + struct sasem_context *context = NULL; + + context = (struct sasem_context *) file->private_data; + + if (!context) { + err("%s: no context for device", __FUNCTION__); + return -ENODEV; + } + + LOCK_CONTEXT; + + switch (cmd) { + case IOCTL_LCD_CONTRAST: + if (arg > 1000) + arg = 1000; + if (arg < 0) + arg = 0; + context->vfd_contrast = (unsigned int)arg; + break; + default: + info("Unknown IOCTL command"); + UNLOCK_CONTEXT; + return -ENOIOCTLCMD; /* not supported */ + } + + UNLOCK_CONTEXT; + return 0; +} + +/** + * Called when the VFD device (e.g. /dev/usb/lcd) + * is closed by the application. + */ +static int vfd_close(struct inode *inode, struct file *file) +{ + struct sasem_context *context = NULL; + int retval = SUCCESS; + + context = (struct sasem_context *) file->private_data; + + if (!context) { + err("%s: no context for device", __FUNCTION__); + return -ENODEV; + } + + LOCK_CONTEXT; + + if (!context->vfd_isopen) { + err("%s: VFD is not open", __FUNCTION__); + retval = -EIO; + } else { + context->vfd_isopen = FALSE; + MOD_DEC_USE_COUNT; + info("VFD port closed"); + if (!context->dev_present && !context->ir_isopen) { + + /* Device disconnected before close and IR port is + * not open. If IR port is open, context will be + * deleted by ir_close. */ + UNLOCK_CONTEXT; + delete_context(context); + return retval; + } + } + + UNLOCK_CONTEXT; + return retval; +} + +/** + * Sends a packet to the VFD. + */ +static inline int send_packet(struct sasem_context *context) +{ + unsigned int pipe; + int interval = 0; + int retval = SUCCESS; + + pipe = usb_sndintpipe(context->dev, + context->tx_endpoint->bEndpointAddress); +#ifdef KERNEL_2_5 + interval = context->tx_endpoint->bInterval; +#endif /* Use 0 for 2.4 kernels */ + + usb_fill_int_urb(context->tx_urb, context->dev, pipe, + context->usb_tx_buf, sizeof(context->usb_tx_buf), + usb_tx_callback, context, interval); + + context->tx_urb->actual_length = 0; + + init_completion(&context->tx.finished); + atomic_set(&(context->tx.busy), 1); + +#ifdef KERNEL_2_5 + retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); +#else + retval = usb_submit_urb(context->tx_urb); +#endif + if (retval != SUCCESS) { + atomic_set(&(context->tx.busy), 0); + err("%s: error submitting urb (%d)", __FUNCTION__, retval); + } else { + /* Wait for tranmission to complete (or abort) */ + UNLOCK_CONTEXT; + wait_for_completion(&context->tx.finished); + LOCK_CONTEXT; + + retval = context->tx.status; + if (retval != SUCCESS) + err("%s: packet tx failed (%d)", __FUNCTION__, retval); + } + + return retval; +} + +/** + * Writes data to the VFD. The Sasem VFD is 2x16 characters + * and requires data in 9 consecutive USB interrupt packets, + * each packet carrying 8 bytes. + */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int i; + int retval = SUCCESS; + struct sasem_context *context; + + context = (struct sasem_context *) file->private_data; + if (!context) { + err("%s: no context for device", __FUNCTION__); + return -ENODEV; + } + + LOCK_CONTEXT; + + if (!context->dev_present) { + err("%s: no Sasem device present", __FUNCTION__); + retval = -ENODEV; + goto exit; + } + + if (n_bytes <= 0 || n_bytes > 32) { + err("%s: invalid payload size", __FUNCTION__); + retval = -EINVAL; + goto exit; + } + + copy_from_user(context->tx.data_buf, buf, n_bytes); + + /* Pad with spaces */ + for (i = n_bytes; i < 32; ++i) + context->tx.data_buf [i] = ' '; + + /* Nine 8 byte packets to be sent */ + /* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0" + * will clear the VFD */ + for (i = 0; i < 9; i++) { + switch (i) { + case 0: + memcpy(context->usb_tx_buf, "\x07\0\0\0\0\0\0\0", 8); + context->usb_tx_buf[1] = (context->vfd_contrast) ? + (0x2B - (context->vfd_contrast - 1) / 250):0x2B; + break; + case 1: + memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); + break; + case 2: + memcpy(context->usb_tx_buf, "\x0b\x01\0\0\0\0\0\0", 8); + break; + case 3: + memcpy(context->usb_tx_buf, context->tx.data_buf, 8); + break; + case 4: + memcpy(context->usb_tx_buf, + context->tx.data_buf + 8, 8); + break; + case 5: + memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); + break; + case 6: + memcpy(context->usb_tx_buf, "\x0b\x02\0\0\0\0\0\0", 8); + break; + case 7: + memcpy(context->usb_tx_buf, + context->tx.data_buf + 16, 8); + break; + case 8: + memcpy(context->usb_tx_buf, + context->tx.data_buf + 24, 8); + break; + } + retval = send_packet(context); + if (retval != SUCCESS) { + + err("%s: send packet failed for packet #%d", + __FUNCTION__, i); + goto exit; + } + } +exit: + + UNLOCK_CONTEXT; + + return (retval == SUCCESS) ? n_bytes : retval; +} + +/** + * Callback function for USB core API: transmit data + */ +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_tx_callback(struct urb *urb, struct pt_regs *regs) +#else +static void usb_tx_callback(struct urb *urb) +#endif +{ + struct sasem_context *context; + + if (!urb) + return; + context = (struct sasem_context *) urb->context; + if (!context) + return; + + context->tx.status = urb->status; + + /* notify waiters that write has finished */ + atomic_set(&context->tx.busy, 0); + complete(&context->tx.finished); + + return; +} + +/** + * Called by lirc_dev when the application opens /dev/lirc + */ +static int ir_open(void *data) +{ + int retval = SUCCESS; + struct sasem_context *context; + + /* prevent races with disconnect */ + down(&disconnect_sem); + + context = (struct sasem_context *) data; + + LOCK_CONTEXT; + + if (context->ir_isopen) { + err("%s: IR port is already open", __FUNCTION__); + retval = -EBUSY; + goto exit; + } + + usb_fill_int_urb(context->rx_urb, context->dev, + usb_rcvintpipe(context->dev, + context->rx_endpoint->bEndpointAddress), + context->usb_rx_buf, sizeof(context->usb_rx_buf), + usb_rx_callback, context, context->rx_endpoint->bInterval); + +#ifdef KERNEL_2_5 + retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); +#else + retval = usb_submit_urb(context->rx_urb); +#endif + + if (retval) + err("%s: usb_submit_urb failed for ir_open (%d)", + __FUNCTION__, retval); + else { + MOD_INC_USE_COUNT; + context->ir_isopen = TRUE; + info("IR port opened"); + } + +exit: + UNLOCK_CONTEXT; + + up(&disconnect_sem); + return SUCCESS; +} + +/** + * Called by lirc_dev when the application closes /dev/lirc + */ +static void ir_close(void *data) +{ + struct sasem_context *context; + + context = (struct sasem_context *)data; + if (!context) { + err("%s: no context for device", __FUNCTION__); + return; + } + + LOCK_CONTEXT; + + usb_kill_urb(context->rx_urb); + context->ir_isopen = FALSE; + MOD_DEC_USE_COUNT; + info("IR port closed"); + + if (!context->dev_present) { + + /* + * Device disconnected while IR port was + * still open. Plugin was not deregistered + * at disconnect time, so do it now. + */ + deregister_from_lirc(context); + + if (!context->vfd_isopen) { + + UNLOCK_CONTEXT; + delete_context(context); + return; + } + /* If VFD port is open, context will be deleted by vfd_close */ + } + + UNLOCK_CONTEXT; + return; +} + +/** + * Process the incoming packet + */ +static inline void incoming_packet(struct sasem_context *context, + struct urb *urb) +{ + int len = urb->actual_length; + unsigned char *buf = urb->transfer_buffer; + long ms; + struct timeval tv; + + if (len != 8) { + warn("%s: invalid incoming packet size (%d)", + __FUNCTION__, len); + return; + } + +#ifdef DEBUG + int i; + for (i = 0; i < 8; ++i) + printk(KERN_INFO "%02x ", buf [i]); + printk(KERN_INFO "\n"); +#endif + + /* Lirc could deal with the repeat code, but we really need to block it + * if it arrives too late. Otherwise we could repeat the wrong code. */ + + /* get the time since the last button press */ + do_gettimeofday(&tv); + ms = (tv.tv_sec - context->presstime.tv_sec) * 1000 + + (tv.tv_usec - context->presstime.tv_usec) / 1000; + + if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) { + /* the repeat code is being sent, so we copy + * the old code to LIRC */ + + /* NOTE: Only if the last code was less than 250ms ago + * - no one should be able to push another (undetected) button + * in that time and then get a false repeat of the previous + * press but it is long enough for a genuine repeat */ + if ((ms < 250) && (context->codesaved != 0)) { + memcpy(buf, &context->lastcode, 8); + context->presstime.tv_sec = tv.tv_sec; + context->presstime.tv_usec = tv.tv_usec; + } + } else { + /* save the current valid code for repeats */ + memcpy(&context->lastcode, buf, 8); + /* set flag to signal a valid code was save; + * just for safety reasons */ + context->codesaved = 1; + context->presstime.tv_sec = tv.tv_sec; + context->presstime.tv_usec = tv.tv_usec; + } + + lirc_buffer_write_1(context->plugin->rbuf, buf); + wake_up(&context->plugin->rbuf->wait_poll); +} + +/** + * Callback function for USB core API: receive data + */ +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_rx_callback(struct urb *urb, struct pt_regs *regs) +#else +static void usb_rx_callback(struct urb *urb) +#endif +{ + struct sasem_context *context; + + if (!urb) + return; + context = (struct sasem_context *) urb->context; + if (!context) + return; + + switch (urb->status) { + + case -ENOENT: /* usbcore unlink successful! */ + return; + + case SUCCESS: + if (context->ir_isopen) + incoming_packet(context, urb); + break; + + default: + warn("%s: status (%d): ignored", + __FUNCTION__, urb->status); + break; + } + +#ifdef KERNEL_2_5 + usb_submit_urb(context->rx_urb, GFP_ATOMIC); +#endif + return; +} + + + +/** + * Callback function for USB core API: Probe + */ +#ifdef KERNEL_2_5 +static int sasem_probe(struct usb_interface *interface, + const struct usb_device_id *id) +#else +static void *sasem_probe(struct usb_device *dev, unsigned int intf, + const struct usb_device_id *id) +#endif +{ +#ifdef KERNEL_2_5 + struct usb_device *dev = NULL; + struct usb_host_interface *iface_desc = NULL; +#else + struct usb_interface *interface = NULL; + struct usb_interface_descriptor *iface_desc = NULL; + char name [10]; + int subminor = 0; +#endif + struct usb_endpoint_descriptor *rx_endpoint = NULL; + struct usb_endpoint_descriptor *tx_endpoint = NULL; + struct urb *rx_urb = NULL; + struct urb *tx_urb = NULL; + struct lirc_plugin *plugin = NULL; + struct lirc_buffer *rbuf = NULL; + int lirc_minor = 0; + int num_endpoints; + int retval = SUCCESS; + int vfd_ep_found; + int ir_ep_found; + int alloc_status; + struct sasem_context *context = NULL; + int i; + + info("%s: found Sasem device", __FUNCTION__); + +#if !defined(KERNEL_2_5) + for (subminor = 0; subminor < MAX_DEVICES; ++subminor) { + if (minor_table [subminor] == NULL) + break; + } + if (subminor == MAX_DEVICES) { + err("%s: allowed number of devices already present", + __FUNCTION__); + retval = -ENOMEM; + goto exit; + } +#endif + +#ifdef KERNEL_2_5 + dev = usb_get_dev(interface_to_usbdev(interface)); + iface_desc = interface->cur_altsetting; + num_endpoints = iface_desc->desc.bNumEndpoints; +#else + interface = &dev->actconfig->interface [intf]; + iface_desc = &interface->altsetting [interface->act_altsetting]; + num_endpoints = iface_desc->bNumEndpoints; +#endif + + /* + * Scan the endpoint list and set: + * first input endpoint = IR endpoint + * first output endpoint = VFD endpoint + */ + + ir_ep_found = FALSE; + vfd_ep_found = FALSE; + + for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) { + + struct usb_endpoint_descriptor *ep; + int ep_dir; + int ep_type; +#ifdef KERNEL_2_5 + ep = &iface_desc->endpoint [i].desc; +#else + ep = &iface_desc->endpoint [i]; +#endif + ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + if (!ir_ep_found && + ep_dir == USB_DIR_IN && + ep_type == USB_ENDPOINT_XFER_INT) { + + rx_endpoint = ep; + ir_ep_found = TRUE; + if (debug) + info("%s: found IR endpoint", __FUNCTION__); + + } else if (!vfd_ep_found && + ep_dir == USB_DIR_OUT && + ep_type == USB_ENDPOINT_XFER_INT) { + + tx_endpoint = ep; + vfd_ep_found = TRUE; + if (debug) + info("%s: found VFD endpoint", __FUNCTION__); + } + } + + /* Input endpoint is mandatory */ + if (!ir_ep_found) { + + err("%s: no valid input (IR) endpoint found.", __FUNCTION__); + retval = -ENODEV; + goto exit; + } + + /* Warning if no VFD endpoint */ + if (!vfd_ep_found) + info("%s: no valid output (VFD) endpoint found.", __FUNCTION__); + + + /* Allocate memory */ + alloc_status = SUCCESS; + + context = kmalloc(sizeof(struct sasem_context), GFP_KERNEL); + if (!context) { + err("%s: kmalloc failed for context", __FUNCTION__); + alloc_status = 1; + goto alloc_status_switch; + } + plugin = kmalloc(sizeof(struct lirc_plugin), GFP_KERNEL); + if (!plugin) { + err("%s: kmalloc failed for lirc_plugin", __FUNCTION__); + alloc_status = 2; + goto alloc_status_switch; + } + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) { + err("%s: kmalloc failed for lirc_buffer", __FUNCTION__); + alloc_status = 3; + goto alloc_status_switch; + } + if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { + err("%s: lirc_buffer_init failed", __FUNCTION__); + alloc_status = 4; + goto alloc_status_switch; + } +#ifdef KERNEL_2_5 + rx_urb = usb_alloc_urb(0, GFP_KERNEL); +#else + rx_urb = usb_alloc_urb(0); +#endif + if (!rx_urb) { + err("%s: usb_alloc_urb failed for IR urb", __FUNCTION__); + alloc_status = 5; + goto alloc_status_switch; + } + if (vfd_ep_found) { +#ifdef KERNEL_2_5 + tx_urb = usb_alloc_urb(0, GFP_KERNEL); +#else + tx_urb = usb_alloc_urb(0); +#endif + if (!tx_urb) { + err("%s: usb_alloc_urb failed for VFD urb", + __FUNCTION__); + alloc_status = 6; + goto alloc_status_switch; + } + } + + /* clear all members of sasem_context and lirc_plugin */ + memset(context, 0, sizeof(struct sasem_context)); + init_MUTEX(&context->sem); + + memset(plugin, 0, sizeof(struct lirc_plugin)); + + strcpy(plugin->name, MOD_NAME); + plugin->minor = -1; + plugin->code_length = 64; + plugin->sample_rate = 0; + plugin->features = LIRC_CAN_REC_LIRCCODE; + plugin->data = context; + plugin->rbuf = rbuf; + plugin->set_use_inc = ir_open; + plugin->set_use_dec = ir_close; +#ifdef LIRC_HAVE_SYSFS + plugin->dev = &dev->dev; +#endif + plugin->owner = THIS_MODULE; + + LOCK_CONTEXT; + + lirc_minor = lirc_register_plugin(plugin); + if (lirc_minor < 0) { + err("%s: lirc_register_plugin failed", __FUNCTION__); + alloc_status = 7; + UNLOCK_CONTEXT; + } else + info("%s: Registered Sasem plugin (minor:%d)", + __FUNCTION__, lirc_minor); + +alloc_status_switch: + + switch (alloc_status) { + + case 7: + if (vfd_ep_found) + usb_free_urb(tx_urb); + case 6: + usb_free_urb(rx_urb); + case 5: + lirc_buffer_free(rbuf); + case 4: + kfree(rbuf); + case 3: + kfree(plugin); + case 2: + kfree(context); + context = NULL; + case 1: + retval = -ENOMEM; + goto exit; + } + + /* Needed while unregistering! */ + plugin->minor = lirc_minor; + + context->dev = dev; + context->dev_present = TRUE; + context->rx_endpoint = rx_endpoint; + context->rx_urb = rx_urb; + if (vfd_ep_found) { + context->tx_endpoint = tx_endpoint; + context->tx_urb = tx_urb; + context->vfd_contrast = 1000; /* range 0 - 1000 */ + } + context->plugin = plugin; + +#ifdef KERNEL_2_5 + usb_set_intfdata(interface, context); +#else + minor_table [subminor] = context; + context->subminor = subminor; +#endif + + if (vfd_ep_found) { + + if (debug) + info("Registering VFD with devfs"); +#ifdef KERNEL_2_5 + if (usb_register_dev(interface, &sasem_class)) + /* Not a fatal error, so ignore */ + info("%s: could not get a minor number for VFD", + __FUNCTION__); +#else + sprintf(name, DEVFS_NAME, subminor); + context->devfs = devfs_register(usb_devfs_handle, name, + DEVFS_FL_DEFAULT, + USB_MAJOR, VFD_MINOR_BASE + subminor, + DEVFS_MODE, &vfd_fops, NULL); + if (!context->devfs) + /* not a fatal error so ignore */ + info("%s: devfs register failed for VFD", + __FUNCTION__); +#endif + } + + info("%s: Sasem device on usb<%d:%d> initialized", + __FUNCTION__, dev->bus->busnum, dev->devnum); + + UNLOCK_CONTEXT; +exit: +#ifdef KERNEL_2_5 + return retval; +#else + return (retval == SUCCESS) ? context : NULL; +#endif +} + +/** + * Callback function for USB core API: disonnect + */ +#ifdef KERNEL_2_5 +static void sasem_disconnect(struct usb_interface *interface) +#else +static void sasem_disconnect(struct usb_device *dev, void *data) +#endif +{ + struct sasem_context *context; + + /* prevent races with ir_open()/vfd_open() */ + down(&disconnect_sem); + +#ifdef KERNEL_2_5 + context = usb_get_intfdata(interface); +#else + context = (struct sasem_context *)data; +#endif + LOCK_CONTEXT; + + info("%s: Sasem device disconnected", __FUNCTION__); + +#ifdef KERNEL_2_5 + usb_set_intfdata(interface, NULL); +#else + minor_table [context->subminor] = NULL; +#endif + context->dev_present = FALSE; + + /* Stop reception */ + usb_kill_urb(context->rx_urb); + + /* Abort ongoing write */ + if (atomic_read(&context->tx.busy)) { + + usb_kill_urb(context->tx_urb); + wait_for_completion(&context->tx.finished); + } + + /* De-register from lirc_dev if IR port is not open */ + if (!context->ir_isopen) + deregister_from_lirc(context); + +#ifdef KERNEL_2_5 + usb_deregister_dev(interface, &sasem_class); +#else + if (context->devfs) + devfs_unregister(context->devfs); +#endif + + UNLOCK_CONTEXT; + + if (!context->ir_isopen && !context->vfd_isopen) + delete_context(context); + + up(&disconnect_sem); +} + +static int __init sasem_init(void) +{ + int rc; + + info(MOD_DESC ", v" MOD_VERSION); + info(MOD_AUTHOR); + + rc = usb_register(&sasem_driver); + if (rc < 0) { + err("%s: usb register failed (%d)", __FUNCTION__, rc); + return -ENODEV; + } + return SUCCESS; +} + +static void __exit sasem_exit(void) +{ + usb_deregister(&sasem_driver); + info("module removed. Goodbye!"); +} + + +module_init(sasem_init); +module_exit(sasem_exit); + +#if !defined(KERNEL_2_5) +EXPORT_NO_SYMBOLS; +#endif --- linux-2.6.27.orig/ubuntu/lirc/lirc_sasem/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_sasem/Makefile @@ -0,0 +1,2 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. +obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_atiusb/lirc_atiusb.c +++ linux-2.6.27/ubuntu/lirc/lirc_atiusb/lirc_atiusb.c @@ -0,0 +1,1437 @@ +/* lirc_atiusb - USB remote support for LIRC + * (currently only supports X10 USB remotes) + * (supports ATI Remote Wonder and ATI Remote Wonder II, too) + * + * Copyright (C) 2003-2004 Paul Miller + * + * This driver was derived from: + * Vladimir Dergachev 's 2002 + * "USB ATI Remote support" (input device) + * Adrian Dewhurst 's 2002 + * "USB StreamZap remote driver" (LIRC) + * Artur Lipowski 's 2002 + * "lirc_dev" and "lirc_gpio" LIRC modules + * Michael Wojciechowski + * initial xbox support + * Vassilis Virvilis 2006 + * reworked the patch for lirc submission + * + * $Id: lirc_atiusb.c,v 1.69 2008/04/28 06:47:29 lirc Exp $ + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +#error "*******************************************************" +#error "Sorry, this driver needs kernel version 2.4.0 or higher" +#error "*******************************************************" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#include +#include +#include +#include + +#include "lirc.h" +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +#define DRIVER_VERSION "$Revision: 1.69 $" +#define DRIVER_AUTHOR "Paul Miller " +#define DRIVER_DESC "USB remote driver for LIRC" +#define DRIVER_NAME "lirc_atiusb" + +#define CODE_LENGTH code_length[ir->remote_type] +#define CODE_MIN_LENGTH code_min_length[ir->remote_type] +#define DECODE_LENGTH decode_length[ir->remote_type] + +#define RW2_MODENAV_KEYCODE 0x3F +#define RW2_NULL_MODE 0xFF +/* Fake (virtual) keycode indicating compass mouse usage */ +#define RW2_MOUSE_KEYCODE 0xFF +#define RW2_PRESSRELEASE_KEYCODE 0xFE + +#define RW2_PRESS_CODE 1 +#define RW2_HOLD_CODE 2 +#define RW2_RELEASE_CODE 0 + +/* module parameters */ +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG fmt, ## args); \ + } while (0) + +/* ATI, ATI2, XBOX */ +static const int code_length[] = {5, 3, 6}; +static const int code_min_length[] = {3, 3, 6}; +static const int decode_length[] = {5, 3, 1}; +/* USB_BUFF_LEN must be the maximum value of the code_length array. + * It is used for static arrays. */ +#define USB_BUFF_LEN 6 + +static int mask = 0xFFFF; /* channel acceptance bit mask */ +static int unique; /* enable channel-specific codes */ +static int repeat = 10; /* repeat time in 1/100 sec */ +static int emit_updown; /* send seperate press/release codes (rw2) */ +static int emit_modekeys; /* send keycodes for aux1-4, pc, and mouse (rw2) */ +static unsigned long repeat_jiffies; /* repeat timeout */ +static int mdeadzone; /* mouse sensitivity >= 0 */ +static int mgradient = 375; /* 1000*gradient from cardinal direction */ + +/* get hi and low bytes of a 16-bits int */ +#define HI(a) ((unsigned char)((a) >> 8)) +#define LO(a) ((unsigned char)((a) & 0xff)) + +/* lock irctl structure */ +#define IRLOCK down_interruptible(&ir->lock) +#define IRUNLOCK up(&ir->lock) + +/* general constants */ +#define SUCCESS 0 +#define SEND_FLAG_IN_PROGRESS 1 +#define SEND_FLAG_COMPLETE 2 +#define FREE_ALL 0xFF + +/* endpoints */ +#define EP_KEYS 0 +#define EP_MOUSE 1 +#define EP_MOUSE_ADDR 0x81 +#define EP_KEYS_ADDR 0x82 + +#define VENDOR_ATI1 0x0bc7 +#define VENDOR_ATI2 0x0471 +#define VENDOR_MS1 0x040b +#define VENDOR_MS2 0x045e +#define VENDOR_MS3 0xFFFF + +static struct usb_device_id usb_remote_table [] = { + /* X10 USB Firecracker Interface */ + { USB_DEVICE(VENDOR_ATI1, 0x0002) }, + + /* X10 VGA Video Sender */ + { USB_DEVICE(VENDOR_ATI1, 0x0003) }, + + /* ATI Wireless Remote Receiver */ + { USB_DEVICE(VENDOR_ATI1, 0x0004) }, + + /* NVIDIA Wireless Remote Receiver */ + { USB_DEVICE(VENDOR_ATI1, 0x0005) }, + + /* ATI Wireless Remote Receiver */ + { USB_DEVICE(VENDOR_ATI1, 0x0006) }, + + /* X10 USB Wireless Transceivers */ + { USB_DEVICE(VENDOR_ATI1, 0x0007) }, + { USB_DEVICE(VENDOR_ATI1, 0x0008) }, + { USB_DEVICE(VENDOR_ATI1, 0x0009) }, + { USB_DEVICE(VENDOR_ATI1, 0x000A) }, + { USB_DEVICE(VENDOR_ATI1, 0x000B) }, + { USB_DEVICE(VENDOR_ATI1, 0x000C) }, + { USB_DEVICE(VENDOR_ATI1, 0x000D) }, + { USB_DEVICE(VENDOR_ATI1, 0x000E) }, + { USB_DEVICE(VENDOR_ATI1, 0x000F) }, + + /* ATI Remote Wonder 2: Input Device */ + { USB_DEVICE(VENDOR_ATI2, 0x0602) }, + + /* ATI Remote Wonder 2: Controller (???) */ + { USB_DEVICE(VENDOR_ATI2, 0x0603) }, + + /* Gamester Xbox DVD Movie Playback Kit IR */ + { USB_DEVICE(VENDOR_MS1, 0x6521) }, + + /* Microsoft Xbox DVD Movie Playback Kit IR */ + { USB_DEVICE(VENDOR_MS2, 0x0284) }, + + /* Some chinese manufacterer -- conflicts with the joystick from the + * same manufacterer */ + { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, + + /* Terminating entry */ + { } +}; + + +/* init strings */ +#define USB_OUTLEN 7 + +static char init1[] = {0x01, 0x00, 0x20, 0x14}; +static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; + +struct in_endpt { + /* inner link in list of endpoints for the remote specified by ir */ + struct list_head iep_list_link; + struct irctl *ir; + struct urb *urb; + struct usb_endpoint_descriptor *ep; + int type; + + /* buffers and dma */ + unsigned char *buf; + unsigned int len; +#ifdef KERNEL_2_5 + dma_addr_t dma; +#endif + + /* handle repeats */ + unsigned char old[USB_BUFF_LEN]; + unsigned long old_jiffies; +}; + +struct out_endpt { + struct irctl *ir; + struct urb *urb; + struct usb_endpoint_descriptor *ep; + + /* buffers and dma */ + unsigned char *buf; +#ifdef KERNEL_2_5 + dma_addr_t dma; +#endif + + /* handle sending (init strings) */ + int send_flags; + wait_queue_head_t wait; +}; + + +/* data structure for each usb remote */ +struct irctl { + /* inner link in list of all remotes managed by this module */ + struct list_head remote_list_link; + /* Number of usb interfaces associated with this device */ + int dev_refcount; + + /* usb */ + struct usb_device *usbdev; + /* Head link to list of all inbound endpoints in this remote */ + struct list_head iep_listhead; + struct out_endpt *out_init; + int devnum; + + /* remote type based on usb_device_id tables */ + enum { + ATI1_COMPATIBLE, + ATI2_COMPATIBLE, + XBOX_COMPATIBLE + } remote_type; + + /* rw2 current mode (mirror's remote's state) */ + int mode; + + /* lirc */ + struct lirc_plugin *p; + int connected; + + /* locking */ + struct semaphore lock; +}; + +/* list of all registered devices via the remote_list_link in irctl */ +static struct list_head remote_list; + +/* Convenience macros to retrieve a pointer to the surrounding struct from + * the given list_head reference within, pointed at by link. */ +#define get_iep_from_link(link) \ + list_entry((link), struct in_endpt, iep_list_link); +#define get_irctl_from_link(link) \ + list_entry((link), struct irctl, remote_list_link); + +/* send packet - used to initialize remote */ +static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) +{ + struct irctl *ir = oep->ir; + DECLARE_WAITQUEUE(wait, current); + int timeout = HZ; /* 1 second */ + unsigned char buf[USB_OUTLEN]; + + dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); + + IRLOCK; + oep->urb->transfer_buffer_length = LO(cmd) + 1; + oep->urb->dev = oep->ir->usbdev; + oep->send_flags = SEND_FLAG_IN_PROGRESS; + + memcpy(buf+1, data, LO(cmd)); + buf[0] = HI(cmd); + memcpy(oep->buf, buf, LO(cmd)+1); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&oep->wait, &wait); + +#ifdef KERNEL_2_5 + if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { +#else + if (usb_submit_urb(oep->urb)) { +#endif + set_current_state(TASK_RUNNING); + remove_wait_queue(&oep->wait, &wait); + IRUNLOCK; + return; + } + IRUNLOCK; + + while (timeout && (oep->urb->status == -EINPROGRESS) + && !(oep->send_flags & SEND_FLAG_COMPLETE)) { + timeout = schedule_timeout(timeout); + rmb(); + } + + dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); + + set_current_state(TASK_RUNNING); + remove_wait_queue(&oep->wait, &wait); +#ifdef KERNEL_2_5 + oep->urb->transfer_flags |= URB_ASYNC_UNLINK; +#endif + usb_unlink_urb(oep->urb); +} + +static int unregister_from_lirc(struct irctl *ir) +{ + struct lirc_plugin *p = ir->p; + int devnum; + + devnum = ir->devnum; + dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); + + lirc_unregister_plugin(p->minor); + + printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); + return SUCCESS; +} + + +static int set_use_inc(void *data) +{ + struct irctl *ir = data; + struct list_head *pos, *n; + struct in_endpt *iep; + int rtn; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); + return -EIO; + } + dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); + + MOD_INC_USE_COUNT; + + IRLOCK; + if (!ir->connected) { + if (!ir->usbdev) { + IRUNLOCK; + dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); + return -ENOENT; + } + + /* Iterate through the inbound endpoints */ + list_for_each_safe(pos, n, &ir->iep_listhead) { + /* extract the current in_endpt */ + iep = get_iep_from_link(pos); + iep->urb->dev = ir->usbdev; + dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", + ir->devnum, iep->ep->bEndpointAddress, iep); +#ifdef KERNEL_2_5 + rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); +#else + rtn = usb_submit_urb(iep->urb); +#endif + if (rtn) { + printk(DRIVER_NAME "[%d]: open result = %d " + "error submitting urb\n", + ir->devnum, rtn); + IRUNLOCK; + MOD_DEC_USE_COUNT; + return -EIO; + } + } + ir->connected = 1; + } + IRUNLOCK; + + return SUCCESS; +} + +static void set_use_dec(void *data) +{ + struct irctl *ir = data; + struct list_head *pos, *n; + struct in_endpt *iep; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); + return; + } + dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); + + IRLOCK; + if (ir->connected) { + /* Free inbound usb urbs */ + list_for_each_safe(pos, n, &ir->iep_listhead) { + iep = get_iep_from_link(pos); + dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", + ir->devnum, iep->ep->bEndpointAddress, iep); + usb_kill_urb(iep->urb); + } + ir->connected = 0; + } + IRUNLOCK; + MOD_DEC_USE_COUNT; +} + +static void print_data(struct in_endpt *iep, char *buf, int len) +{ + const int clen = code_length[iep->ir->remote_type]; + char codes[clen * 3 + 1]; + int i; + + if (len <= 0) + return; + + for (i = 0; i < len && i < clen; i++) + snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); + printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", + iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); +} + +static int code_check_ati1(struct in_endpt *iep, int len) +{ + struct irctl *ir = iep->ir; + int i, chan; + + /* ATI RW1: some remotes emit both 4 and 5 byte length codes. */ + /* ATI RW2: emit 3 byte codes */ + if (len < CODE_MIN_LENGTH || len > CODE_LENGTH) + return -1; + + /* *** channel not tested with 4/5-byte Dutch remotes *** */ + chan = ((iep->buf[len-1]>>4) & 0x0F); + + /* strip channel code */ + if (!unique) { + iep->buf[len-1] &= 0x0F; + iep->buf[len-3] -= (chan<<4); + } + + if (!((1U<devnum, chan+1); + return -1; + } + dprintk(DRIVER_NAME "[%d]: accept channel %d\n", ir->devnum, chan+1); + + if (ir->remote_type == ATI1_COMPATIBLE) { + for (i = len; i < CODE_LENGTH; i++) iep->buf[i] = 0; + /* check for repeats */ + if (memcmp(iep->old, iep->buf, len) == 0) { + if (iep->old_jiffies + repeat_jiffies > jiffies) + return -1; + } else + memcpy(iep->old, iep->buf, CODE_LENGTH); + iep->old_jiffies = jiffies; + } + + return SUCCESS; +} + +/* + * Since the ATI Remote Wonder II has quite a different structure from the + * prior version, this function was seperated out to clarify the sanitization + * process. + * + * Here is a summary of the main differences: + * + * a. The rw2 has no sense of a transmission channel. But, it does have an + * auxilliary mode state, which is set by the mode buttons Aux1 through + * Aux4 and "PC". These map respectively to 0-4 in the first byte of the + * recv buffer. Any subsequent button press sends this mode number as its + * "channel code." Annoyingly enough, the mode setting buttons all send + * the same key code (0x3f), and can only be distinguished via their mode + * byte. + * + * Because of this, old-style "unique"-parameter-enabled channel squashing + * kills the functionality of the aux1-aux4 and PC buttons. However, to + * not do so would cause each remote key to send a different code depending + * on the active aux. Further complicating matters, using the mouse norb + * also sends an identical code as would pushing the active aux button. To + * handle this we need a seperate parameter, like rw2modes, with the + * following values and meanings: + * + * 0: Don't squash any channel info + * 1: Only squash channel data for non-mode setting keys + * 2: Ignore aux keypresses, but don't squash channel + * 3: Ignore aux keypresses and squash channel data + * + * Option 1 may seem useless since the mouse sends the same code, but one + * need only ignore in userspace any press of a mode-setting code that only + * reaffirms the current mode. The 3rd party lirccd should be able to + * handle this easily enough, but lircd doesn't keep the state necessary + * for this. TODO We could work around this in the driver by emitting a + * single 02 (press) code for a mode key only if that mode is not currently + * active. + * + * Option 2 would be useful for those wanting super configurability, + * offering the ability to program 5 times the number actions based on the + * current mode. + * + * b. The rw2 has its own built in repeat handling; the keys endpoint + * encodes this in the second byte as 1 for press, 2 for hold, and 0 for + * release. This is generally much more responsive than lirc's built-in + * timeout handling. + * + * The problem is that the remote can send the release-recieve pair + * (0,1) while one is still holding down the same button if the + * transmission is momentarilly interrupted. (It seems that the receiver + * manages this count instead of the remote.) By default, this information + * is squashed to 2. + * + * In order to expose the built-in repeat code, set the emit_updown + * parameter as described below. + * + * c. The mouse norb is much more sensitive than on the rw1. It emulates + * a joystick-like controller with the second byte representing the x-axis + * and the third, the y-axis. Treated as signed integers, these axes range + * approximately as follows: + * + * x: (left) -46 ... 46 (right) (0xd2..0x2e) + * y: (up) -46 ... 46 (down) (0xd2..0x2e) + * + * NB these values do not correspond to the pressure with which the mouse + * norb is pushed in a given direction, but rather seems to indicate the + * duration for which a given direction is held. + * + * These are normalized to 8 cardinal directions for easy configuration via + * lircd.conf. The normalization can be fined tuned with the mdeadzone and + * mgradient parameters as described below. + * + * d. The interrupt rate of the mouse vs. the normal keys is different. + * + * mouse: ~27Hz (37ms between interrupts) + * keys: ~10Hz (100ms between interrupts) + * + * This means that the normal gap mechanism for lircd won't work as + * expected; is emit_updown>0 if you can get away with it. + */ +static int code_check_ati2(struct in_endpt *iep, int len) +{ + struct irctl *ir = iep->ir; + int mode, i; + char *buf = iep->buf; + + if (len != CODE_LENGTH) { + dprintk(DRIVER_NAME + "[%d]: Huh? Abnormal length (%d) buffer recieved.\n", + ir->devnum, len); + return -1; + } + for (i = len; i < CODE_LENGTH; i++) iep->buf[i] = 0; + + mode = buf[0]; + + /* Squash the mode indicator if unique wasn't set non-zero */ + if (!unique) + buf[0] = 0; + + if (iep->ep->bEndpointAddress == EP_KEYS_ADDR) { + /* ignore mouse navigation indicator key and + * mode-set (aux) keys */ + if (buf[2] == RW2_MODENAV_KEYCODE) { + if (emit_modekeys >= 2) /* emit raw */ + buf[0] = mode; + else if (emit_modekeys == 1) { + /* translate */ + buf[0] = mode; + if (ir->mode != mode) { + buf[1] = 0x03; + ir->mode = mode; + return SUCCESS; + } + } else { + dprintk(DRIVER_NAME + "[%d]: ignore dummy code 0x%x " + "(ep=0x%x)\n", ir->devnum, + buf[2], iep->ep->bEndpointAddress); + return -1; + } + } + + if (buf[1] != 2) { + /* handle press/release codes */ + if (emit_updown == 0) /* ignore */ + return -1; + else if (emit_updown == 1) /* normalize keycode */ + buf[2] = RW2_PRESSRELEASE_KEYCODE; + /* else emit raw */ + } + + } else { + int x = (signed char)buf[1]; + int y = (signed char)buf[2]; + int code = 0x00; + int dir_ew, dir_ns; + + buf[2] = RW2_MOUSE_KEYCODE; + + /* sensitivity threshold (use L2norm^2) */ + if (mdeadzone > (x*x+y*y)) { + buf[1] = 0x00; + return SUCCESS; + } + +/* Nybble encoding: xy, 2 is -1 (S or W); 1 (N or E) */ +#define MOUSE_N 0x01 +#define MOUSE_NE 0x11 +#define MOUSE_E 0x10 +#define MOUSE_SE 0x12 +#define MOUSE_S 0x02 +#define MOUSE_SW 0x22 +#define MOUSE_W 0x20 +#define MOUSE_NW 0x21 + + /* cardinal leanings: positive x -> E, positive y -> S */ + dir_ew = (x > 0) ? MOUSE_E : MOUSE_W; + dir_ns = (y > 0) ? MOUSE_S : MOUSE_N; + + /* convert coordintes(angle) into compass direction */ + if (x == 0) + code = dir_ns; + else if (y == 0) + code = dir_ew; + else { + if (abs(1000*y/x) > mgradient) + code = dir_ns; + if (abs(1000*x/y) > mgradient) + code |= dir_ew; + } + + buf[1] = code; + dprintk(DRIVER_NAME "[%d]: mouse compass=0x%x %s%s (%d,%d)\n", + ir->devnum, code, + (code & MOUSE_S ? "S" : (code & MOUSE_N ? "N" : "")), + (code & MOUSE_E ? "E" : (code & MOUSE_W ? "W" : "")), + x, y); + } + + return SUCCESS; +} + +static int code_check_xbox(struct in_endpt *iep, int len) +{ + struct irctl *ir = iep->ir; + const int clen = CODE_LENGTH; + + if (len != clen) { + dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " + "ir.. ?\n", len, clen); + return -1; + } + + /* check for repeats */ + if (memcmp(iep->old, iep->buf, len) == 0) { + if (iep->old_jiffies + repeat_jiffies > jiffies) + return -1; + } else { + /* the third byte of xbox ir packet seems to contain key info + * the last two bytes are.. some kind of clock? */ + iep->buf[0] = iep->buf[2]; + memset(iep->buf + 1, 0, len - 1); + memcpy(iep->old, iep->buf, len); + } + iep->old_jiffies = jiffies; + + return SUCCESS; +} + +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) +#else +static void usb_remote_recv(struct urb *urb) +#endif +{ + struct in_endpt *iep; + int len, result = -1; + + if (!urb) + return; + iep = urb->context; + if (!iep) { +#ifdef KERNEL_2_5 + urb->transfer_flags |= URB_ASYNC_UNLINK; +#endif + usb_unlink_urb(urb); + return; + } + if (!iep->ir->usbdev) + return; + + len = urb->actual_length; + if (debug) + print_data(iep, urb->transfer_buffer, len); + + switch (urb->status) { + + /* success */ + case SUCCESS: + switch (iep->ir->remote_type) { + case XBOX_COMPATIBLE: + result = code_check_xbox(iep, len); + break; + case ATI2_COMPATIBLE: + result = code_check_ati2(iep, len); + break; + case ATI1_COMPATIBLE: + default: + result = code_check_ati1(iep, len); + } + if (result < 0) + break; + lirc_buffer_write_1(iep->ir->p->rbuf, iep->buf); + wake_up(&iep->ir->p->rbuf->wait_poll); + break; + + /* unlink */ + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: +#ifdef KERNEL_2_5 + urb->transfer_flags |= URB_ASYNC_UNLINK; +#endif + usb_unlink_urb(urb); + return; + + case -EPIPE: + default: + break; + } + + /* resubmit urb */ +#ifdef KERNEL_2_5 + usb_submit_urb(urb, GFP_ATOMIC); +#endif +} + +#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void usb_remote_send(struct urb *urb, struct pt_regs *regs) +#else +static void usb_remote_send(struct urb *urb) +#endif +{ + struct out_endpt *oep; + + if (!urb) + return; + oep = urb->context; + if (!oep) { +#ifdef KERNEL_2_5 + urb->transfer_flags |= URB_ASYNC_UNLINK; +#endif + usb_unlink_urb(urb); + return; + } + if (!oep->ir->usbdev) + return; + + dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); + + if (urb->status) + return; + + oep->send_flags |= SEND_FLAG_COMPLETE; + wmb(); + if (waitqueue_active(&oep->wait)) + wake_up(&oep->wait); +} + + +/*************************************************************************** + * Initialization and removal + ***************************************************************************/ + +/* + * Free iep according to mem_failure which specifies a checkpoint into the + * initialization sequence for rollback recovery. + */ +static void free_in_endpt(struct in_endpt *iep, int mem_failure) +{ + struct irctl *ir; + dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); + if (!iep) + return; + + ir = iep->ir; + if (!ir) { + dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); + return; + } + IRLOCK; + switch (mem_failure) { + case FREE_ALL: + case 5: + list_del(&iep->iep_list_link); + dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " + "from list\n", ir->devnum, iep->ep->bEndpointAddress); + case 4: + if (iep->urb) { +#ifdef KERNEL_2_5 + iep->urb->transfer_flags |= URB_ASYNC_UNLINK; +#endif + usb_unlink_urb(iep->urb); + usb_free_urb(iep->urb); + iep->urb = 0; + } else + dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", + ir->devnum); + case 3: +#ifdef KERNEL_2_5 + usb_buffer_free(iep->ir->usbdev, iep->len, iep->buf, iep->dma); +#else + kfree(iep->buf); +#endif + iep->buf = 0; + case 2: + kfree(iep); + } + IRUNLOCK; +} + +/* + * Construct a new inbound endpoint for this remote, and add it to the list of + * in_epts in ir. + */ +static struct in_endpt *new_in_endpt(struct irctl *ir, + struct usb_endpoint_descriptor *ep) +{ + struct usb_device *dev = ir->usbdev; + struct in_endpt *iep; + int pipe, maxp, len, addr; + int mem_failure; + + addr = ep->bEndpointAddress; + pipe = usb_rcvintpipe(dev, addr); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + +/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; + * len -= (len % CODE_LENGTH); */ + len = CODE_LENGTH; + + dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " + "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); + + mem_failure = 0; + iep = kmalloc(sizeof(*iep), GFP_KERNEL); + if (!iep) { + mem_failure = 1; + goto new_in_endpt_failure_check; + } + memset(iep, 0, sizeof(*iep)); + iep->ir = ir; + iep->ep = ep; + iep->len = len; + +#ifdef KERNEL_2_5 + iep->buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &iep->dma); +#else + iep->buf = kmalloc(len, GFP_KERNEL); +#endif + if (!iep->buf) { + mem_failure = 2; + goto new_in_endpt_failure_check; + } + +#ifdef KERNEL_2_5 + iep->urb = usb_alloc_urb(0, GFP_KERNEL); +#else + iep->urb = usb_alloc_urb(0); +#endif + if (!iep->urb) + mem_failure = 3; + +new_in_endpt_failure_check: + + if (mem_failure) { + free_in_endpt(iep, mem_failure); + printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", + ir->devnum, addr, mem_failure); + return NULL; + } + list_add_tail(&iep->iep_list_link, &ir->iep_listhead); + dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", + ir->devnum, iep->ep->bEndpointAddress); + return iep; +} + +static void free_out_endpt(struct out_endpt *oep, int mem_failure) +{ + struct irctl *ir; + dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); + if (!oep) + return; + + wake_up_all(&oep->wait); + + ir = oep->ir; + if (!ir) { + dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); + return; + } + IRLOCK; + switch (mem_failure) { + case FREE_ALL: + case 4: + if (oep->urb) { +#ifdef KERNEL_2_5 + oep->urb->transfer_flags |= URB_ASYNC_UNLINK; +#endif + usb_unlink_urb(oep->urb); + usb_free_urb(oep->urb); + oep->urb = 0; + } else { + dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", + ir->devnum); + } + case 3: +#ifdef KERNEL_2_5 + usb_buffer_free(oep->ir->usbdev, USB_OUTLEN, + oep->buf, oep->dma); +#else + kfree(oep->buf); +#endif + oep->buf = 0; + case 2: + kfree(oep); + } + IRUNLOCK; +} + +static struct out_endpt *new_out_endpt(struct irctl *ir, + struct usb_endpoint_descriptor *ep) +{ +#ifdef KERNEL_2_5 + struct usb_device *dev = ir->usbdev; +#endif + struct out_endpt *oep; + int mem_failure; + + dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", + ir->devnum, ep->bEndpointAddress); + + mem_failure = 0; + oep = kmalloc(sizeof(*oep), GFP_KERNEL); + if (!oep) + mem_failure = 1; + else { + memset(oep, 0, sizeof(*oep)); + oep->ir = ir; + oep->ep = ep; + init_waitqueue_head(&oep->wait); + +#ifdef KERNEL_2_5 + oep->buf = usb_buffer_alloc(dev, USB_OUTLEN, + GFP_ATOMIC, &oep->dma); +#else + oep->buf = kmalloc(USB_OUTLEN, GFP_KERNEL); +#endif + if (!oep->buf) + mem_failure = 2; + else { +#ifdef KERNEL_2_5 + oep->urb = usb_alloc_urb(0, GFP_KERNEL); +#else + oep->urb = usb_alloc_urb(0); +#endif + if (!oep->urb) + mem_failure = 3; + } + } + if (mem_failure) { + free_out_endpt(oep, mem_failure); + printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", + ir->devnum, ep->bEndpointAddress, mem_failure); + return NULL; + } + return oep; +} + +static void free_irctl(struct irctl *ir, int mem_failure) +{ + struct list_head *pos, *n; + struct in_endpt *in; + dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); + + if (!ir) + return; + + list_for_each_safe(pos, n, &ir->iep_listhead) { + in = get_iep_from_link(pos); + free_in_endpt(in, FREE_ALL); + } + if (ir->out_init) { + free_out_endpt(ir->out_init, FREE_ALL); + ir->out_init = NULL; + } + + IRLOCK; + switch (mem_failure) { + case FREE_ALL: + case 6: + if (!--ir->dev_refcount) { + list_del(&ir->remote_list_link); + dprintk(DRIVER_NAME "[%d]: free_irctl: removing " + "remote from list\n", ir->devnum); + } else { + dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," + "aborting free_irctl\n", + ir->devnum, ir->dev_refcount); + IRUNLOCK; + return; + } + case 5: + case 4: + case 3: + if (ir->p) { + switch (mem_failure) { + case 5: + lirc_buffer_free(ir->p->rbuf); + case 4: + kfree(ir->p->rbuf); + case 3: + kfree(ir->p); + } + } else + printk(DRIVER_NAME "[%d]: ir->p is a null pointer!\n", + ir->devnum); + case 2: + IRUNLOCK; + kfree(ir); + return; + } + IRUNLOCK; +} + +static struct irctl *new_irctl(struct usb_device *dev) +{ + struct irctl *ir; + struct lirc_plugin *plugin; + int type, devnum; + int mem_failure; + int dclen; + + devnum = dev->devnum; + + /* determine remote type */ + switch (cpu_to_le16(dev->descriptor.idVendor)) { + case VENDOR_ATI1: + type = ATI1_COMPATIBLE; + break; + case VENDOR_ATI2: + type = ATI2_COMPATIBLE; + break; + case VENDOR_MS1: + case VENDOR_MS2: + case VENDOR_MS3: + type = XBOX_COMPATIBLE; + break; + default: + dprintk(DRIVER_NAME "[%d]: unknown type\n", devnum); + return NULL; + } + dprintk(DRIVER_NAME "[%d]: remote type = %d\n", devnum, type); + + /* allocate kernel memory */ + mem_failure = 0; + ir = kmalloc(sizeof(*ir), GFP_KERNEL); + if (!ir) { + mem_failure = 1; + goto new_irctl_failure_check; + } + + /* at this stage we cannot use the macro [DE]CODE_LENGTH: ir + * is not yet setup */ + dclen = decode_length[type]; + memset(ir, 0, sizeof(*ir)); + /* add this infrared remote struct to remote_list, keeping track + * of the number of drivers registered. */ + dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); + list_add_tail(&ir->remote_list_link, &remote_list); + ir->dev_refcount = 1; + + plugin = kmalloc(sizeof(*plugin), GFP_KERNEL); + if (!plugin) { + mem_failure = 2; + goto new_irctl_failure_check; + } + + memset(plugin, 0, sizeof(*plugin)); + ir->p = plugin; + plugin->rbuf = kmalloc(sizeof(*(plugin->rbuf)), GFP_KERNEL); + if (!plugin->rbuf) { + mem_failure = 3; + goto new_irctl_failure_check; + } + + if (lirc_buffer_init(plugin->rbuf, dclen, 1)) { + mem_failure = 4; + goto new_irctl_failure_check; + } + + strcpy(plugin->name, DRIVER_NAME " "); + plugin->minor = -1; + plugin->code_length = dclen * 8; + plugin->features = LIRC_CAN_REC_LIRCCODE; + plugin->data = ir; + plugin->set_use_inc = &set_use_inc; + plugin->set_use_dec = &set_use_dec; +#ifdef LIRC_HAVE_SYSFS + plugin->dev = &dev->dev; +#endif + plugin->owner = THIS_MODULE; + ir->usbdev = dev; + ir->remote_type = type; + ir->devnum = devnum; + ir->mode = RW2_NULL_MODE; + + init_MUTEX(&ir->lock); + INIT_LIST_HEAD(&ir->iep_listhead); + +new_irctl_failure_check: + + if (mem_failure) { + free_irctl(ir, mem_failure); + printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", + devnum, mem_failure); + return NULL; + } + return ir; +} + + +/* + * Scan the global list of remotes to see if the device listed is one of them. + * If it is, the corresponding irctl is returned, with its dev_refcount + * incremented. Otherwise, returns null. + */ +static struct irctl *get_prior_reg_ir(struct usb_device *dev) +{ + struct list_head *pos; + struct irctl *ir = NULL; + + dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); + list_for_each(pos, &remote_list) { + ir = get_irctl_from_link(pos); + if (ir->usbdev != dev) { + dprintk(DRIVER_NAME "[%d]: device %d isn't it...", + dev->devnum, ir->devnum); + ir = NULL; + } else { + dprintk(DRIVER_NAME "[%d]: prior instance found.\n", + dev->devnum); + ir->dev_refcount++; + break; + } + } + return ir; +} + +/* If the USB interface has an out endpoint for control (eg, the first Remote + * Wonder) send the appropriate initialization packets. */ +static void send_outbound_init(struct irctl *ir) +{ + if (ir->out_init) { + struct out_endpt *oep = ir->out_init; + dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " + "outbound ep\n", ir->devnum); + usb_fill_int_urb(oep->urb, ir->usbdev, + usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), + oep->buf, USB_OUTLEN, usb_remote_send, + oep, oep->ep->bInterval); + + send_packet(oep, 0x8004, init1); + send_packet(oep, 0x8007, init2); + } +} + +/* Log driver and usb info */ +static void log_usb_dev_info(struct usb_device *dev) +{ + char buf[63], name[128] = ""; + if (dev->descriptor.iManufacturer + && usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) + strncpy(name, buf, 128); + if (dev->descriptor.iProduct + && usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + snprintf(name, 128, "%s %s", name, buf); + printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, + dev->bus->busnum, dev->devnum); +} + + +#ifdef KERNEL_2_5 +static int usb_remote_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_host_interface *idesc; +#else +static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct usb_interface *intf = &dev->actconfig->interface[ifnum]; + struct usb_interface_descriptor *idesc; +#endif + struct usb_endpoint_descriptor *ep; + struct in_endpt *iep; + struct irctl *ir; + int i, type; + + dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", + dev->devnum, dev, intf, id); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) + idesc = &intf->altsetting[intf->act_altsetting]; +#else + idesc = intf->cur_altsetting; +#endif + + /* Check if a usb remote has already been registered for this device */ + ir = get_prior_reg_ir(dev); + + if (!ir) { + ir = new_irctl(dev); + if (!ir) +#ifdef KERNEL_2_5 + return -ENOMEM; +#else + return NULL; +#endif + } + type = ir->remote_type; + + /* step through the endpoints to find first in and first out endpoint + * of type interrupt transfer */ +#ifdef KERNEL_2_5 + for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { + ep = &idesc->endpoint[i].desc; +#else + for (i = 0; i < idesc->bNumEndpoints; ++i) { + ep = &idesc->endpoint[i]; +#endif + dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", + dev->devnum, i); + if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_IN) && + ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT)) { + + iep = new_in_endpt(ir, ep); + if (iep) + usb_fill_int_urb(iep->urb, dev, + usb_rcvintpipe(dev, + iep->ep->bEndpointAddress), + iep->buf, iep->len, usb_remote_recv, + iep, iep->ep->bInterval); + } + + if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_OUT) && + ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT) && + (ir->out_init == NULL)) + ir->out_init = new_out_endpt(ir, ep); + } + if (list_empty(&ir->iep_listhead)) { + printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", + ir->devnum); + free_irctl(ir, FREE_ALL); +#ifdef KERNEL_2_5 + return -ENODEV; +#else + return NULL; +#endif + } + if (ir->dev_refcount == 1) { + ir->p->minor = lirc_register_plugin(ir->p); + if (ir->p->minor < 0) { + free_irctl(ir, FREE_ALL); +#ifdef KERNEL_2_5 + return -ENODEV; +#else + return NULL; +#endif + } + + /* Note new driver registration in kernel logs */ + log_usb_dev_info(dev); + + /* outbound data (initialization) */ + send_outbound_init(ir); + } + +#ifdef KERNEL_2_5 + usb_set_intfdata(intf, ir); + return SUCCESS; +#else + return ir; +#endif +} + +#ifdef KERNEL_2_5 +static void usb_remote_disconnect(struct usb_interface *intf) +{ +/* struct usb_device *dev = interface_to_usbdev(intf); */ + struct irctl *ir = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); +#else +static void usb_remote_disconnect(struct usb_device *dev, void *ptr) +{ + struct irctl *ir = ptr; +#endif + + dprintk(DRIVER_NAME ": disconnecting remote %d:\n", + (ir? ir->devnum: -1)); + if (!ir || !ir->p) + return; + + if (ir->usbdev) { + /* Only unregister once */ + ir->usbdev = NULL; + unregister_from_lirc(ir); + } + + /* This also removes the current remote from remote_list */ + free_irctl(ir, FREE_ALL); +} + +static struct usb_driver usb_remote_driver = { + LIRC_THIS_MODULE(.owner = THIS_MODULE) + .name = DRIVER_NAME, + .probe = usb_remote_probe, + .disconnect = usb_remote_disconnect, + .id_table = usb_remote_table +}; + +static int __init usb_remote_init(void) +{ + int i; + + INIT_LIST_HEAD(&remote_list); + + printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " + DRIVER_VERSION "\n"); + printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); + dprintk(DRIVER_NAME ": debug mode enabled: " + "$Id: lirc_atiusb.c,v 1.69 2008/04/28 06:47:29 lirc Exp $\n"); + + request_module("lirc_dev"); + + repeat_jiffies = repeat*HZ/100; + + i = usb_register(&usb_remote_driver); + if (i) { + printk(DRIVER_NAME ": usb register failed, result = %d\n", i); + return -ENODEV; + } + + return SUCCESS; +} + +static void __exit usb_remote_exit(void) +{ + usb_deregister(&usb_remote_driver); +} + +module_init(usb_remote_init); +module_exit(usb_remote_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, usb_remote_table); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); + +module_param(mask, int, 0644); +MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); + +module_param(unique, bool, 0644); +MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); + +module_param(repeat, int, 0644); +MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); + +module_param(mdeadzone, int, 0644); +MODULE_PARM_DESC(mdeadzone, "rw2 mouse sensitivity threshold (default: 0)"); + +/* + * Enabling this will cause the built-in Remote Wonder II repeate coding to + * not be squashed. The second byte of the keys output will then be: + * + * 1 initial press (button down) + * 2 holding (button remains pressed) + * 0 release (button up) + * + * By default, the driver emits 2 for both 1 and 2, and emits nothing for 0. + * This is good for people having trouble getting their rw2 to send a good + * consistent signal to the receiver. + * + * However, if you have no troubles with the driver outputting up-down pairs + * at random points while you're still holding a button, then you can enable + * this parameter to get finer grain repeat control out of your remote: + * + * 1 Emit a single (per-channel) virtual code for all up/down events + * 2 Emit the actual rw2 output + * + * 1 is easier to write lircd configs for; 2 allows full control. + */ +module_param(emit_updown, int, 0644); +MODULE_PARM_DESC(emit_updown, "emit press/release codes (rw2): 0:don't " + "(default), 1:emit 2 codes only, 2:code for each button"); + +module_param(emit_modekeys, int, 0644); +MODULE_PARM_DESC(emit_modekeys, "emit keycodes for aux1-aux4, pc, and mouse " + "(rw2): 0:don't (default), 1:emit translated codes: one for " + "mode switch, one for same mode, 2:raw codes"); + +module_param(mgradient, int, 0644); +MODULE_PARM_DESC(mgradient, "rw2 mouse: 1000*gradient from E to NE (default: " + "500 => .5 => ~27 degrees)"); + +EXPORT_NO_SYMBOLS; --- linux-2.6.27.orig/ubuntu/lirc/lirc_atiusb/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_atiusb/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_ATIUSB) += lirc_atiusb.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_mceusb2/lirc_mceusb2.c +++ linux-2.6.27/ubuntu/lirc/lirc_mceusb2/lirc_mceusb2.c @@ -0,0 +1,1076 @@ +/* + * LIRC driver for Philips eHome USB Infrared Transceiver + * and the Microsoft MCE 2005 Remote Control + * + * (C) by Martin A. Blatter + * + * Transmitter support and reception code cleanup. + * (C) by Daniel Melander + * + * Derived from ATI USB driver by Paul Miller and the original + * MCE USB driver by Dan Corti + * + * This driver will only work reliably with kernel version 2.6.10 + * or higher, probably because of differences in USB device enumeration + * in the kernel code. Device initialization fails most of the time + * with earlier kernel versions. + * + ********************************************************************** + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) +#error "*******************************************************" +#error "Sorry, this driver needs kernel version 2.6.5 or higher" +#error "*******************************************************" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#include +#include +#include +#include + +#include "lirc.h" +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +#define DRIVER_VERSION "$Revision: 1.44 $" +#define DRIVER_AUTHOR "Daniel Melander , " \ + "Martin Blatter " +#define DRIVER_DESC "Philips eHome USB IR Transceiver and Microsoft " \ + "MCE 2005 Remote Control driver for LIRC" +#define DRIVER_NAME "lirc_mceusb2" + +#define USB_BUFLEN 16 /* USB reception buffer length */ +#define LIRCBUF_SIZE 256 /* LIRC work buffer length */ + +/* MCE constants */ +#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ +#define MCE_TIME_UNIT 50 /* Approx 50us resolution */ +#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ +#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ +#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ +#define MCE_CONTROL_HEADER 0x9F /* MCE status header */ +#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */ +#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ +#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */ +#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */ +#define MCE_PULSE_MASK 0x7F /* Pulse mask */ +#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */ + + +/* module parameters */ +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG fmt, ## args); \ + } while (0) + +/* lock irctl structure */ +/*#define IRLOCK down_interruptible(&ir->lock) */ +#define IRLOCK down(&ir->lock) +#define IRUNLOCK up(&ir->lock) + +/* general constants */ +#define SUCCESS 0 +#define SEND_FLAG_IN_PROGRESS 1 +#define SEND_FLAG_COMPLETE 2 +#define RECV_FLAG_IN_PROGRESS 3 +#define RECV_FLAG_COMPLETE 4 + +#define PHILUSB_INBOUND 1 +#define PHILUSB_OUTBOUND 2 + +#define VENDOR_PHILIPS 0x0471 +#define VENDOR_SMK 0x0609 +#define VENDOR_TATUNG 0x1460 +#define VENDOR_GATEWAY 0x107b +#define VENDOR_SHUTTLE 0x1308 +#define VENDOR_SHUTTLE2 0x051c +#define VENDOR_MITSUMI 0x03ee +#define VENDOR_TOPSEED 0x1784 +#define VENDOR_RICAVISION 0x179d +#define VENDOR_ITRON 0x195d +#define VENDOR_FIC 0x1509 +#define VENDOR_LG 0x043e +#define VENDOR_MICROSOFT 0x045e +#define VENDOR_FORMOSA 0x147a +#define VENDOR_FINTEK 0x1934 + +static struct usb_device_id usb_remote_table [] = { + /* Philips eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, + /* Philips Infrared Transceiver - HP branded */ + { USB_DEVICE(VENDOR_PHILIPS, 0x060c) }, + /* Philips SRM5100 */ + { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, + /* SMK/Toshiba G83C0004D410 */ + { USB_DEVICE(VENDOR_SMK, 0x031d) }, + /* SMK eHome Infrared Transceiver (Sony VAIO) */ + { USB_DEVICE(VENDOR_SMK, 0x0322) }, + /* bundled with Hauppauge PVR-150 */ + { USB_DEVICE(VENDOR_SMK, 0x0334) }, + /* Tatung eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, + /* Shuttle eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, + /* Shuttle eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, + /* Gateway eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, + /* Mitsumi */ + { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, + /* Topseed HP eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, + /* Ricavision internal Infrared Transceiver */ + { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, + /* Itron ione Libra Q-11 */ + { USB_DEVICE(VENDOR_ITRON, 0x7002) }, + /* FIC eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_FIC, 0x9242) }, + /* LG eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_LG, 0x9803) }, + /* Microsoft MCE Infrared Transceiver */ + { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, + /* Formosa eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, + /* Formosa aim / Trust MCE Infrared Receiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, + /* Formosa Industrial Computing / Beanbag Emulation Device */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, + /* Fintek eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, + /* Terminating entry */ + { } +}; + +/* data structure for each usb remote */ +struct irctl { + + /* usb */ + struct usb_device *usbdev; + struct urb *urb_in; + int devnum; + struct usb_endpoint_descriptor *usb_ep_in; + struct usb_endpoint_descriptor *usb_ep_out; + + /* buffers and dma */ + unsigned char *buf_in; + unsigned int len_in; + dma_addr_t dma_in; + dma_addr_t dma_out; + + /* lirc */ + struct lirc_plugin *p; + lirc_t lircdata; + unsigned char is_pulse; + int connected; + + unsigned char transmitter_mask; + unsigned int carrier_freq; + + /* handle sending (init strings) */ + int send_flags; + wait_queue_head_t wait_out; + + struct semaphore lock; +}; + +/* init strings */ +static char init1[] = {0x00, 0xff, 0xaa, 0xff, 0x0b}; +static char init2[] = {0xff, 0x18}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) +static inline unsigned long usecs_to_jiffies(const unsigned int u) +{ + if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; +#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) + return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ); +#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC) + return u * (HZ / USEC_PER_SEC); +#else + return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC; +#endif +} +#endif + + +static void usb_remote_printdata(struct irctl *ir, char *buf, int len) +{ + char codes[USB_BUFLEN*3 + 1]; + int i; + + if (len <= 0) + return; + + for (i = 0; i < len && i < USB_BUFLEN; i++) + snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); + + printk(KERN_INFO "" DRIVER_NAME "[%d]: data received %s (length=%d)\n", + ir->devnum, codes, len); +} + +static void usb_async_callback(struct urb *urb, struct pt_regs *regs) +{ + struct irctl *ir; + int len; + + if (!urb) + return; + + ir = urb->context; + if (ir) { + len = urb->actual_length; + + dprintk(DRIVER_NAME + "[%d]: callback called (status=%d len=%d)\n", + ir->devnum, urb->status, len); + + if (debug) + usb_remote_printdata(ir, urb->transfer_buffer, len); + } + +} + + +/* request incoming or send outgoing usb packet - used to initialize remote */ +static void request_packet_async(struct irctl *ir, + struct usb_endpoint_descriptor *ep, + unsigned char *data, int size, int urb_type) +{ + int res; + struct urb *async_urb; + unsigned char *async_buf; + + if (urb_type) { + async_urb = usb_alloc_urb(0, GFP_KERNEL); + if (async_urb) { + /* alloc buffer */ + async_buf = kmalloc(size, GFP_KERNEL); + if (async_buf) { + if (urb_type == PHILUSB_OUTBOUND) { + /* outbound data */ + usb_fill_int_urb(async_urb, ir->usbdev, + usb_sndintpipe(ir->usbdev, + ep->bEndpointAddress), + async_buf, + size, + (usb_complete_t) usb_async_callback, + ir, ep->bInterval); + + memcpy(async_buf, data, size); + async_urb->transfer_flags = + URB_ASYNC_UNLINK; + } else { + /* inbound data */ + usb_fill_int_urb(async_urb, ir->usbdev, + usb_rcvintpipe(ir->usbdev, + ep->bEndpointAddress), + async_buf, size, + (usb_complete_t) usb_async_callback, + ir, ep->bInterval); + + async_urb->transfer_flags = + URB_ASYNC_UNLINK; + } + } else { + usb_free_urb(async_urb); + return; + } + } + } else { + /* standard request */ + async_urb = ir->urb_in; + ir->send_flags = RECV_FLAG_IN_PROGRESS; + } + dprintk(DRIVER_NAME "[%d]: receive request called (size=%#x)\n", + ir->devnum, size); + + async_urb->transfer_buffer_length = size; + async_urb->dev = ir->usbdev; + + res = usb_submit_urb(async_urb, GFP_ATOMIC); + if (res) { + dprintk(DRIVER_NAME "[%d]: receive request FAILED! (res=%d)\n", + ir->devnum, res); + return; + } + dprintk(DRIVER_NAME "[%d]: receive request complete (res=%d)\n", + ir->devnum, res); +} + +static int unregister_from_lirc(struct irctl *ir) +{ + struct lirc_plugin *p = ir->p; + int devnum; + int rtn; + + devnum = ir->devnum; + dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); + + rtn = lirc_unregister_plugin(p->minor); + if (rtn > 0) { + printk(DRIVER_NAME "[%d]: error in lirc_unregister minor: %d\n" + "Trying again...\n", devnum, p->minor); + if (rtn == -EBUSY) { + printk(DRIVER_NAME + "[%d]: device is opened, will unregister" + " on close\n", devnum); + return -EAGAIN; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + + rtn = lirc_unregister_plugin(p->minor); + if (rtn > 0) + printk(DRIVER_NAME "[%d]: lirc_unregister failed\n", + devnum); + } + + if (rtn != SUCCESS) { + printk(DRIVER_NAME "[%d]: didn't free resources\n", devnum); + return -EAGAIN; + } + + printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); + + lirc_buffer_free(p->rbuf); + kfree(p->rbuf); + kfree(p); + kfree(ir); + return SUCCESS; +} + +static int set_use_inc(void *data) +{ + struct irctl *ir = data; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); + return -EIO; + } + dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); + + MOD_INC_USE_COUNT; + + if (!ir->connected) { + if (!ir->usbdev) + return -ENOENT; + ir->connected = 1; + } + + return SUCCESS; +} + +static void set_use_dec(void *data) +{ + struct irctl *ir = data; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); + return; + } + dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); + + if (ir->connected) { + IRLOCK; + ir->connected = 0; + IRUNLOCK; + } + MOD_DEC_USE_COUNT; +} + +static void send_packet_to_lirc(struct irctl *ir) +{ + if (ir->lircdata != 0) { + lirc_buffer_write_1(ir->p->rbuf, + (unsigned char *) &ir->lircdata); + wake_up(&ir->p->rbuf->wait_poll); + ir->lircdata = 0; + } +} + +static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) +{ + struct irctl *ir; + int buf_len, packet_len; + int i, j; + + if (!urb) + return; + + ir = urb->context; + if (!ir) { + urb->transfer_flags |= URB_ASYNC_UNLINK; + usb_unlink_urb(urb); + return; + } + + buf_len = urb->actual_length; + packet_len = 0; + + if (debug) + usb_remote_printdata(ir, urb->transfer_buffer, buf_len); + + if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { + ir->send_flags = SEND_FLAG_COMPLETE; + dprintk(DRIVER_NAME "[%d]: setup answer received %d bytes\n", + ir->devnum, buf_len); + } + + switch (urb->status) { + /* success */ + case SUCCESS: + for (i = 0; i < buf_len; i++) { + /* decode mce packets on the form (84),AA,BB,CC,DD */ + switch (ir->buf_in[i]) { + /* data headers */ + case 0x8F: + case 0x8E: + case 0x8D: + case 0x8C: + case 0x8B: + case 0x8A: + case 0x89: + case 0x88: + case 0x87: + case 0x86: + case 0x85: + case 0x84: + case 0x83: + case 0x82: + case 0x81: + case 0x80: + /* decode packet data */ + packet_len = ir->buf_in[i] & MCE_PULSE_MASK; + for (j = 1; + j <= packet_len && (i+j < buf_len); + j++) { + /* rising/falling flank */ + if (ir->is_pulse != + (ir->buf_in[i + j] & + MCE_PULSE_BIT)) { + send_packet_to_lirc(ir); + ir->is_pulse = + ir->buf_in[i + j] & + MCE_PULSE_BIT; + } + + /* accumulate mce pulse/space values */ + ir->lircdata += + (ir->buf_in[i + j] & + MCE_PULSE_MASK)*MCE_TIME_UNIT; + ir->lircdata |= + (ir->is_pulse ? PULSE_BIT : 0); + } + + i += packet_len; + break; + + /* status header (0x9F) */ + case MCE_CONTROL_HEADER: + /* A transmission containing one or + more consecutive ir commands always + ends with a GAP of 100ms followed by the + sequence 0x9F 0x01 0x01 0x9F 0x15 + 0x00 0x00 0x80 */ + + /* + Uncomment this if the last 100ms + "infinity"-space should be transmitted + to lirc directly instead of at the beginning + of the next transmission. Changes pulse/space order. + + if (++i < buf_len && ir->buf_in[i]==0x01) + send_packet_to_lirc(ir); + + */ + + /* end decode loop */ + i = buf_len; + break; + default: + break; + } + } + + break; + + /* unlink */ + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + urb->transfer_flags |= URB_ASYNC_UNLINK; + usb_unlink_urb(urb); + return; + + case -EPIPE: + default: + break; + } + + /* resubmit urb */ + usb_submit_urb(urb, GFP_ATOMIC); +} + + +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *ppos) +{ + int i, count = 0, cmdcount = 0; + struct irctl *ir = NULL; + lirc_t wbuf[LIRCBUF_SIZE]; /* Workbuffer with values from lirc */ + unsigned char cmdbuf[MCE_CMDBUF_SIZE]; /* MCE command buffer */ + unsigned long signal_duration = 0; /* Singnal length in us */ + struct timeval start_time, end_time; + + do_gettimeofday(&start_time); + + /* Retrieve lirc_plugin data for the device */ + ir = lirc_get_pdata(file); + if (!ir && !ir->usb_ep_out) + return -EFAULT; + + if (n % sizeof(lirc_t)) + return(-EINVAL); + count = n / sizeof(lirc_t); + + /* Check if command is within limits */ + if (count > LIRCBUF_SIZE || count%2 == 0) + return(-EINVAL); + if (copy_from_user(wbuf, buf, n)) + return -EFAULT; + + /* MCE tx init header */ + cmdbuf[cmdcount++] = MCE_CONTROL_HEADER; + cmdbuf[cmdcount++] = 0x08; + cmdbuf[cmdcount++] = ir->transmitter_mask; + + /* Generate mce packet data */ + for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { + signal_duration += wbuf[i]; + wbuf[i] = wbuf[i] / MCE_TIME_UNIT; + + do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ + + /* Insert mce packet header every 4th entry */ + if ((cmdcount < MCE_CMDBUF_SIZE) && + (cmdcount - MCE_TX_HEADER_LENGTH) % + MCE_CODE_LENGTH == 0) + cmdbuf[cmdcount++] = MCE_PACKET_HEADER; + + /* Insert mce packet data */ + if (cmdcount < MCE_CMDBUF_SIZE) + cmdbuf[cmdcount++] = + (wbuf[i] < MCE_PULSE_BIT ? + wbuf[i] : MCE_MAX_PULSE_LENGTH) | + (i & 1 ? 0x00 : MCE_PULSE_BIT); + else + return -EINVAL; + } while ((wbuf[i] > MCE_MAX_PULSE_LENGTH) && + (wbuf[i] -= MCE_MAX_PULSE_LENGTH)); + } + + /* Fix packet length in last header */ + cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] = + 0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1; + + /* Check if we have room for the empty packet at the end */ + if (cmdcount >= MCE_CMDBUF_SIZE) + return -EINVAL; + + /* All mce commands end with an empty packet (0x80) */ + cmdbuf[cmdcount++] = 0x80; + + /* Transmit the command to the mce device */ + request_packet_async(ir, ir->usb_ep_out, cmdbuf, + cmdcount, PHILUSB_OUTBOUND); + + /* The lircd gap calculation expects the write function to + wait the time it takes for the ircommand to be sent before + it returns. */ + do_gettimeofday(&end_time); + signal_duration -= (end_time.tv_usec - start_time.tv_usec) + + (end_time.tv_sec - start_time.tv_sec) * 1000000; + + /* delay with the closest number of ticks */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(signal_duration)); + + return n; +} + +static void set_transmitter_mask(struct irctl *ir, unsigned int mask) +{ + + /* SMK Transceiver does not use the inverted scheme, nor does Topseed*/ + if ((ir->usbdev->descriptor.idVendor == VENDOR_SMK && + (ir->usbdev->descriptor.idProduct == 0x031d || + ir->usbdev->descriptor.idProduct == 0x0322 || + ir->usbdev->descriptor.idProduct == 0x0334)) || + (ir->usbdev->descriptor.idVendor == VENDOR_TOPSEED && + (ir->usbdev->descriptor.idProduct == 0x0001 || + ir->usbdev->descriptor.idProduct == 0x0007 || + ir->usbdev->descriptor.idProduct == 0x0008))) + ir->transmitter_mask = mask; + else + /* The mask begins at 0x02 and has an inverted + numbering scheme */ + ir->transmitter_mask = (mask != 0x03 ? mask ^ 0x03 : mask) << 1; +} + + +/* Sets the send carrier frequency */ +static int set_send_carrier(struct irctl *ir, int carrier) +{ + int clk = 10000000; + int prescaler = 0, divisor = 0; + unsigned char cmdbuf[] = { 0x9F, 0x06, 0x01, 0x80 }; + + /* Carrier is changed */ + if (ir->carrier_freq != carrier) { + + if (carrier <= 0) { + ir->carrier_freq = carrier; + dprintk(DRIVER_NAME "[%d]: SET_CARRIER disabling " + "carrier modulation\n", ir->devnum); + request_packet_async(ir, ir->usb_ep_out, + cmdbuf, sizeof(cmdbuf), + PHILUSB_OUTBOUND); + return carrier; + } + + for (prescaler = 0; prescaler < 4; ++prescaler) { + divisor = (clk >> (2 * prescaler)) / carrier; + if (divisor <= 0xFF) { + ir->carrier_freq = carrier; + cmdbuf[2] = prescaler; + cmdbuf[3] = divisor; + dprintk(DRIVER_NAME "[%d]: SET_CARRIER " + "requesting %d Hz\n", + ir->devnum, carrier); + + /* Transmit the new carrier to the mce + device */ + request_packet_async(ir, ir->usb_ep_out, + cmdbuf, sizeof(cmdbuf), + PHILUSB_OUTBOUND); + return carrier; + } + } + + return -EINVAL; + + } + + return carrier; +} + + +static int lirc_ioctl(struct inode *node, struct file *filep, + unsigned int cmd, unsigned long arg) +{ + int result; + unsigned int ivalue; + unsigned long lvalue; + struct irctl *ir = NULL; + + /* Retrieve lirc_plugin data for the device */ + ir = lirc_get_pdata(filep); + if (!ir && !ir->usb_ep_out) + return -EFAULT; + + + switch (cmd) { + case LIRC_SET_TRANSMITTER_MASK: + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + switch (ivalue) { + case 0x01: /* Transmitter 1 => 0x04 */ + case 0x02: /* Transmitter 2 => 0x02 */ + case 0x03: /* Transmitter 1 & 2 => 0x06 */ + set_transmitter_mask(ir, ivalue); + break; + + default: /* Unsupported transmitter mask */ + return MCE_MAX_CHANNELS; + } + + dprintk(DRIVER_NAME ": SET_TRANSMITTERS mask=%d\n", ivalue); + break; + + case LIRC_GET_SEND_MODE: + + result = put_user(LIRC_SEND2MODE(LIRC_CAN_SEND_PULSE & + LIRC_CAN_SEND_MASK), + (unsigned long *) arg); + + if (result) + return result; + break; + + case LIRC_SET_SEND_MODE: + + result = get_user(lvalue, (unsigned long *) arg); + + if (result) + return result; + if (lvalue != (LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK)) + return -EINVAL; + break; + + case LIRC_SET_SEND_CARRIER: + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + + set_send_carrier(ir, ivalue); + break; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static struct file_operations lirc_fops = { + .write = lirc_write, +}; + + +static int usb_remote_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_host_interface *idesc; + struct usb_endpoint_descriptor *ep = NULL; + struct usb_endpoint_descriptor *ep_in = NULL; + struct usb_endpoint_descriptor *ep_out = NULL; + struct usb_host_config *config; + struct irctl *ir = NULL; + struct lirc_plugin *plugin = NULL; + struct lirc_buffer *rbuf = NULL; + int devnum, pipe, maxp; + int minor = 0; + int i; + char buf[63], name[128] = ""; + int mem_failure = 0; + + dprintk(DRIVER_NAME ": usb probe called\n"); + + usb_reset_device(dev); + + config = dev->actconfig; + + idesc = intf->cur_altsetting; + + /* step through the endpoints to find first bulk in and out endpoint */ + for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { + ep = &idesc->endpoint[i].desc; + + if ((ep_in == NULL) + && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) + && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK) + || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT))) { + + dprintk(DRIVER_NAME ": acceptable inbound endpoint " + "found\n"); + ep_in = ep; + ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; + ep_in->bInterval = 1; + } + + if ((ep_out == NULL) + && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_OUT) + && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK) + || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT))) { + + dprintk(DRIVER_NAME ": acceptable outbound endpoint " + "found\n"); + ep_out = ep; + ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; + ep_out->bInterval = 1; + } + } + if (ep_in == NULL) { + dprintk(DRIVER_NAME ": inbound and/or endpoint not found\n"); + return -ENODEV; + } + + devnum = dev->devnum; + pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + /* allocate kernel memory */ + mem_failure = 0; + ir = kmalloc(sizeof(struct irctl), GFP_KERNEL); + if (!ir) { + mem_failure = 1; + goto mem_failure_switch; + } + + memset(ir, 0, sizeof(struct irctl)); + + plugin = kmalloc(sizeof(struct lirc_plugin), GFP_KERNEL); + if (!plugin) { + mem_failure = 2; + goto mem_failure_switch; + } + + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) { + mem_failure = 3; + goto mem_failure_switch; + } + + if (lirc_buffer_init(rbuf, sizeof(lirc_t), LIRCBUF_SIZE)) { + mem_failure = 4; + goto mem_failure_switch; + } + + ir->buf_in = usb_buffer_alloc(dev, maxp, GFP_ATOMIC, &ir->dma_in); + if (!ir->buf_in) { + mem_failure = 5; + goto mem_failure_switch; + } + + ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); + if (!ir->urb_in) { + mem_failure = 7; + goto mem_failure_switch; + } + + memset(plugin, 0, sizeof(struct lirc_plugin)); + + strcpy(plugin->name, DRIVER_NAME " "); + plugin->minor = -1; + plugin->features = LIRC_CAN_SEND_PULSE | + LIRC_CAN_SET_TRANSMITTER_MASK | + LIRC_CAN_REC_MODE2 | + LIRC_CAN_SET_SEND_CARRIER; + plugin->data = ir; + plugin->rbuf = rbuf; + plugin->set_use_inc = &set_use_inc; + plugin->set_use_dec = &set_use_dec; + plugin->code_length = sizeof(lirc_t) * 8; + plugin->ioctl = lirc_ioctl; + plugin->fops = &lirc_fops; + plugin->dev = &dev->dev; + plugin->owner = THIS_MODULE; + + init_MUTEX(&ir->lock); + init_waitqueue_head(&ir->wait_out); + + minor = lirc_register_plugin(plugin); + if (minor < 0) + mem_failure = 9; + +mem_failure_switch: + + /* free allocated memory incase of failure */ + switch (mem_failure) { + case 9: + usb_free_urb(ir->urb_in); + case 7: + usb_buffer_free(dev, maxp, ir->buf_in, ir->dma_in); + case 5: + lirc_buffer_free(rbuf); + case 4: + kfree(rbuf); + case 3: + kfree(plugin); + case 2: + kfree(ir); + case 1: + printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", + devnum, mem_failure); + return -ENOMEM; + } + + plugin->minor = minor; + ir->p = plugin; + ir->devnum = devnum; + ir->usbdev = dev; + ir->len_in = maxp; + ir->connected = 0; + + ir->lircdata = PULSE_MASK; + ir->is_pulse = 0; + + /* ir->usbdev must be set */ + set_transmitter_mask(ir, MCE_DEFAULT_TX_MASK); + /* Saving usb interface data for use by the transmitter routine */ + ir->usb_ep_in = ep_in; + ir->usb_ep_out = ep_out; + + if (dev->descriptor.iManufacturer + && usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) + strncpy(name, buf, 128); + if (dev->descriptor.iProduct + && usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + snprintf(name, 128, "%s %s", name, buf); + printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, + dev->bus->busnum, devnum); + + /* inbound data */ + usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, + maxp, (usb_complete_t) usb_remote_recv, ir, ep_in->bInterval); + + /* initialize device */ + request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND); + request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND); + request_packet_async(ir, ep_out, init1, + sizeof(init1), PHILUSB_OUTBOUND); + request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND); + request_packet_async(ir, ep_out, init2, + sizeof(init2), PHILUSB_OUTBOUND); + request_packet_async(ir, ep_in, NULL, maxp, 0); + + usb_set_intfdata(intf, ir); + + return SUCCESS; +} + + +static void usb_remote_disconnect(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct irctl *ir = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); + + if (!ir || !ir->p) + return; + + ir->usbdev = NULL; + wake_up_all(&ir->wait_out); + + IRLOCK; + usb_kill_urb(ir->urb_in); + usb_free_urb(ir->urb_in); + usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in); + IRUNLOCK; + + unregister_from_lirc(ir); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +static int usb_remote_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct irctl *ir = usb_get_intfdata(intf); + printk(DRIVER_NAME "[%d]: suspend\n", ir->devnum); + usb_kill_urb(ir->urb_in); + return 0; +} + +static int usb_remote_resume(struct usb_interface *intf) +{ + struct irctl *ir = usb_get_intfdata(intf); + printk(DRIVER_NAME "[%d]: resume\n", ir->devnum); + if (usb_submit_urb(ir->urb_in, GFP_ATOMIC)) + return -EIO; + return 0; +} +#endif + +static struct usb_driver usb_remote_driver = { + LIRC_THIS_MODULE(.owner = THIS_MODULE) + .name = DRIVER_NAME, + .probe = usb_remote_probe, + .disconnect = usb_remote_disconnect, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + .suspend = usb_remote_suspend, + .resume = usb_remote_resume, +#endif + .id_table = usb_remote_table +}; + +static int __init usb_remote_init(void) +{ + int i; + + printk(KERN_INFO "\n"); + printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " " DRIVER_VERSION "\n"); + printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n"); + dprintk(DRIVER_NAME ": debug mode enabled\n"); + + request_module("lirc_dev"); + + i = usb_register(&usb_remote_driver); + if (i < 0) { + printk(DRIVER_NAME ": usb register failed, result = %d\n", i); + return -ENODEV; + } + + return SUCCESS; +} + +static void __exit usb_remote_exit(void) +{ + usb_deregister(&usb_remote_driver); +} + +module_init(usb_remote_init); +module_exit(usb_remote_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, usb_remote_table); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +EXPORT_NO_SYMBOLS; --- linux-2.6.27.orig/ubuntu/lirc/lirc_mceusb2/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_mceusb2/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_MCEUSB2) += lirc_mceusb2.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_bt829/lirc_bt829.c +++ linux-2.6.27/ubuntu/lirc/lirc_bt829/lirc_bt829.c @@ -0,0 +1,403 @@ +/* + * Remote control driver for the TV-card based on bt829 + * + * by Leonid Froenchenko + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +#error "This driver needs kernel version 2.4.0 or higher" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +static int poll_main(void); +static int atir_init_start(void); + +static void write_index(unsigned char index, unsigned int value); +static unsigned int read_index(unsigned char index); + +static void do_i2c_start(void); +static void do_i2c_stop(void); + +static void seems_wr_byte(unsigned char al); +static unsigned char seems_rd_byte(void); + +static unsigned int read_index(unsigned char al); +static void write_index(unsigned char ah, unsigned int edx); + +static void cycle_delay(int cycle); + +static void do_set_bits(unsigned char bl); +static unsigned char do_get_bits(void); + +#define DATA_PCI_OFF 0x7FFC00 +#define WAIT_CYCLE 20 + +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG fmt, ## args); \ + } while (0) + +static int atir_minor; +static unsigned long pci_addr_phys; +static unsigned char *pci_addr_lin; + +static struct lirc_plugin atir_plugin; + +static struct pci_dev *do_pci_probe(void) +{ + struct pci_dev *my_dev; +#ifndef KERNEL_2_5 + /* unnecessary with recent kernels */ + if (!pci_present()) + printk(KERN_ERR "ATIR: no pci in this kernel\n"); +#endif + my_dev = pci_get_device(PCI_VENDOR_ID_ATI, + PCI_DEVICE_ID_ATI_264VT, NULL); + if (my_dev) { + printk(KERN_ERR "ATIR: Using device: %s\n", + pci_name(my_dev)); + pci_addr_phys = 0; + if (my_dev->resource[0].flags & IORESOURCE_MEM) { + pci_addr_phys = my_dev->resource[0].start; + printk(KERN_INFO "ATIR memory at 0x%08X \n", + (unsigned int)pci_addr_phys); + } + if (pci_addr_phys == 0) { + printk(KERN_ERR "ATIR no memory resource ?\n"); + return NULL; + } + } else { + printk(KERN_ERR "ATIR: pci_prob failed\n"); + return NULL; + } + return my_dev; +} + +static int atir_add_to_buf(void *data, struct lirc_buffer *buf) +{ + unsigned char key; + int status; + status = poll_main(); + key = (status >> 8) & 0xFF; + if (status & 0xFF) { + dprintk("ATIR reading key %02X\n", key); + lirc_buffer_write_1(buf, &key); + return 0; + } + return -ENODATA; +} + +static int atir_set_use_inc(void *data) +{ + MOD_INC_USE_COUNT; + dprintk("ATIR driver is opened\n"); + return 0; +} + +static void atir_set_use_dec(void *data) +{ + MOD_DEC_USE_COUNT; + dprintk("ATIR driver is closed\n"); +} + +int init_module(void) +{ + struct pci_dev *pdev; + + pdev = do_pci_probe(); + if (pdev == NULL) + return 1; + + if (!atir_init_start()) + return 1; + + strcpy(atir_plugin.name, "ATIR"); + atir_plugin.minor = -1; + atir_plugin.code_length = 8; + atir_plugin.sample_rate = 10; + atir_plugin.data = 0; + atir_plugin.add_to_buf = atir_add_to_buf; + atir_plugin.set_use_inc = atir_set_use_inc; + atir_plugin.set_use_dec = atir_set_use_dec; +#ifdef LIRC_HAVE_SYSFS + atir_plugin.dev = &pdev->dev; +#endif + atir_plugin.owner = THIS_MODULE; + + atir_minor = lirc_register_plugin(&atir_plugin); + dprintk("ATIR driver is registered on minor %d\n", atir_minor); + + return 0; +} + + +void cleanup_module(void) +{ + lirc_unregister_plugin(atir_minor); +} + + +static int atir_init_start(void) +{ + pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400); + if (pci_addr_lin == 0) { + printk(KERN_INFO "atir: pci mem must be mapped\n"); + return 0; + } + return 1; +} + +static void cycle_delay(int cycle) +{ + udelay(WAIT_CYCLE*cycle); +} + + +static int poll_main() +{ + unsigned char status_high, status_low; + + do_i2c_start(); + + seems_wr_byte(0xAA); + seems_wr_byte(0x01); + + do_i2c_start(); + + seems_wr_byte(0xAB); + + status_low = seems_rd_byte(); + status_high = seems_rd_byte(); + + do_i2c_stop(); + + return (status_high << 8) | status_low; +} + +static void do_i2c_start(void) +{ + do_set_bits(3); + cycle_delay(4); + + do_set_bits(1); + cycle_delay(7); + + do_set_bits(0); + cycle_delay(2); +} + +static void do_i2c_stop(void) +{ + unsigned char bits; + bits = do_get_bits() & 0xFD; + do_set_bits(bits); + cycle_delay(1); + + bits |= 1; + do_set_bits(bits); + cycle_delay(2); + + bits |= 2; + do_set_bits(bits); + bits = 3; + do_set_bits(bits); + cycle_delay(2); +} + +static void seems_wr_byte(unsigned char value) +{ + int i; + unsigned char reg; + + reg = do_get_bits(); + for (i = 0; i < 8; i++) { + if (value & 0x80) + reg |= 0x02; + else + reg &= 0xFD; + + do_set_bits(reg); + cycle_delay(1); + + reg |= 1; + do_set_bits(reg); + cycle_delay(1); + + reg &= 0xFE; + do_set_bits(reg); + cycle_delay(1); + value <<= 1; + } + cycle_delay(2); + + reg |= 2; + do_set_bits(reg); + + reg |= 1; + do_set_bits(reg); + + cycle_delay(1); + do_get_bits(); + + reg &= 0xFE; + do_set_bits(reg); + cycle_delay(3); +} + +static unsigned char seems_rd_byte(void) +{ + int i; + int rd_byte; + unsigned char bits_2, bits_1; + + bits_1 = do_get_bits() | 2; + do_set_bits(bits_1); + + rd_byte = 0; + for (i = 0; i < 8; i++) { + bits_1 &= 0xFE; + do_set_bits(bits_1); + cycle_delay(2); + + bits_1 |= 1; + do_set_bits(bits_1); + cycle_delay(1); + + bits_2 = do_get_bits(); + if (bits_2 & 2) + rd_byte |= 1; + + rd_byte <<= 1; + } + + bits_1 = 0; + if (bits_2 == 0) + bits_1 |= 2; + + do_set_bits(bits_1); + cycle_delay(2); + + bits_1 |= 1; + do_set_bits(bits_1); + cycle_delay(3); + + bits_1 &= 0xFE; + do_set_bits(bits_1); + cycle_delay(2); + + rd_byte >>= 1; + rd_byte &= 0xFF; + return rd_byte; +} + +static void do_set_bits(unsigned char new_bits) +{ + int reg_val; + reg_val = read_index(0x34); + if (new_bits & 2) { + reg_val &= 0xFFFFFFDF; + reg_val |= 1; + } else { + reg_val &= 0xFFFFFFFE; + reg_val |= 0x20; + } + reg_val |= 0x10; + write_index(0x34, reg_val); + + reg_val = read_index(0x31); + if (new_bits & 1) { + reg_val |= 0x1000000; + } else { + reg_val &= 0xFEFFFFFF; + } + reg_val |= 0x8000000; + write_index(0x31, reg_val); +} + +static unsigned char do_get_bits(void) +{ + unsigned char bits; + int reg_val; + + reg_val = read_index(0x34); + reg_val |= 0x10; + reg_val &= 0xFFFFFFDF; + write_index(0x34, reg_val); + + reg_val = read_index(0x34); + bits = 0; + if (reg_val & 8) { + bits |= 2; + } else { + bits &= 0xFD; + } + reg_val = read_index(0x31); + if (reg_val & 0x1000000) { + bits |= 1; + } else { + bits &= 0xFE; + } + return bits; +} + +static unsigned int read_index(unsigned char index) +{ + unsigned char *addr; + unsigned int value; + /* addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */ + addr = pci_addr_lin + ((index & 0xFF) << 2); + value = readl(addr); + return value; +} + +static void write_index(unsigned char index, unsigned int reg_val) +{ + unsigned char *addr; + addr = pci_addr_lin + ((index & 0xFF) << 2); + writel(reg_val, addr); +} + +MODULE_AUTHOR("Froenchenko Leonid"); +MODULE_DESCRIPTION("IR remote driver for bt829 based TV cards"); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +EXPORT_NO_SYMBOLS; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_bt829/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_bt829/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_ATIUSB) += lirc_bt829.o --- linux-2.6.27.orig/ubuntu/lirc/lirc_serial/lirc_serial.c +++ linux-2.6.27/ubuntu/lirc/lirc_serial/lirc_serial.c @@ -0,0 +1,1368 @@ +/* $Id: lirc_serial.c,v 5.89 2008/04/06 19:03:52 lirc Exp $ */ + +/**************************************************************************** + ** lirc_serial.c *********************************************************** + **************************************************************************** + * + * lirc_serial - Device driver that records pulse- and pause-lengths + * (space-lengths) between DDCD event on a serial port. + * + * Copyright (C) 1996,97 Ralph Metzler + * Copyright (C) 1998 Trent Piepho + * Copyright (C) 1998 Ben Pfaff + * Copyright (C) 1999 Christoph Bartelmus + * Copyright (C) 2007 Andrei Tanas (suspend/resume support) + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Steve's changes to improve transmission fidelity: + - for systems with the rdtsc instruction and the clock counter, a + send_pule that times the pulses directly using the counter. + This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is + not needed. Measurement shows very stable waveform, even where + PCI activity slows the access to the UART, which trips up other + versions. + - For other system, non-integer-microsecond pulse/space lengths, + done using fixed point binary. So, much more accurate carrier + frequency. + - fine tuned transmitter latency, taking advantage of fractional + microseconds in previous change + - Fixed bug in the way transmitter latency was accounted for by + tuning the pulse lengths down - the send_pulse routine ignored + this overhead as it timed the overall pulse length - so the + pulse frequency was right but overall pulse length was too + long. Fixed by accounting for latency on each pulse/space + iteration. + + Steve Davies July 2001 +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) +#error "**********************************************************" +#error " Sorry, this driver needs kernel version 2.2.18 or higher " +#error "**********************************************************" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +#include +#endif + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +#include +#else +#include +#endif +#include +#include + +#if defined(LIRC_SERIAL_NSLU2) +#include +/* From Intel IXP42X Developer's Manual (#252480-005): */ +/* ftp://download.intel.com/design/network/manuals/25248005.pdf */ +#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */ +#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */ +#ifndef NSLU2_LED_GRN_GPIO +/* added in 2.6.22 */ +#define NSLU2_LED_GRN_GPIO NSLU2_LED_GRN +#endif +#endif + +#include "lirc.h" +#include "kcompat.h" +#include "lirc_dev/lirc_dev.h" + +#if defined(LIRC_SERIAL_SOFTCARRIER) && !defined(LIRC_SERIAL_TRANSMITTER) +#warning "Software carrier only affects transmitting" +#endif + +#if defined(rdtscl) + +#define USE_RDTSC +#warning "Note: using rdtsc instruction" +#endif + +#ifdef LIRC_SERIAL_ANIMAX +#ifdef LIRC_SERIAL_TRANSMITTER +#warning "******************************************" +#warning " This receiver does not have a " +#warning " transmitter diode " +#warning "******************************************" +#endif +#endif + +#define LIRC_DRIVER_NAME "lirc_serial" + +struct lirc_serial { + int signal_pin; + int signal_pin_change; + int on; + int off; + long (*send_pulse)(unsigned long length); + void (*send_space)(long length); + int features; +}; + +#define LIRC_HOMEBREW 0 +#define LIRC_IRDEO 1 +#define LIRC_IRDEO_REMOTE 2 +#define LIRC_ANIMAX 3 +#define LIRC_IGOR 4 +#define LIRC_NSLU2 5 + +#ifdef LIRC_SERIAL_IRDEO +static int type = LIRC_IRDEO; +#elif defined(LIRC_SERIAL_IRDEO_REMOTE) +static int type = LIRC_IRDEO_REMOTE; +#elif defined(LIRC_SERIAL_ANIMAX) +static int type = LIRC_ANIMAX; +#elif defined(LIRC_SERIAL_IGOR) +static int type = LIRC_IGOR; +#elif defined(LIRC_SERIAL_NSLU2) +static int type = LIRC_NSLU2; +#else +static int type = LIRC_HOMEBREW; +#endif + +/* Set defaults for NSLU2 */ +#if defined(LIRC_SERIAL_NSLU2) +#ifndef LIRC_IRQ +#define LIRC_IRQ IRQ_IXP4XX_UART2 +#endif +#ifndef LIRC_PORT +#define LIRC_PORT (IXP4XX_UART2_BASE_VIRT + REG_OFFSET) +#endif +#ifndef LIRC_IOMMAP +#define LIRC_IOMMAP IXP4XX_UART2_BASE_PHYS +#endif +#ifndef LIRC_IOSHIFT +#define LIRC_IOSHIFT 2 +#endif +#ifndef LIRC_ALLOW_MMAPPED_IO +#define LIRC_ALLOW_MMAPPED_IO +#endif +#endif + +#if defined(LIRC_ALLOW_MMAPPED_IO) +#ifndef LIRC_IOMMAP +#define LIRC_IOMMAP 0 +#endif +#ifndef LIRC_IOSHIFT +#define LIRC_IOSHIFT 0 +#endif +static int iommap = LIRC_IOMMAP; +static int ioshift = LIRC_IOSHIFT; +#endif + +#ifdef LIRC_SERIAL_SOFTCARRIER +static int softcarrier = 1; +#else +static int softcarrier; +#endif + +static int share_irq; +static int debug; + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + +/* forward declarations */ +static long send_pulse_irdeo(unsigned long length); +static long send_pulse_homebrew(unsigned long length); +static void send_space_irdeo(long length); +static void send_space_homebrew(long length); + +static struct lirc_serial hardware[] = { + /* home-brew receiver/transmitter */ + { + UART_MSR_DCD, + UART_MSR_DDCD, + UART_MCR_RTS|UART_MCR_OUT2|UART_MCR_DTR, + UART_MCR_RTS|UART_MCR_OUT2, + send_pulse_homebrew, + send_space_homebrew, + ( +#ifdef LIRC_SERIAL_TRANSMITTER + LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| +#endif + LIRC_CAN_REC_MODE2) + }, + + /* IRdeo classic */ + { + UART_MSR_DSR, + UART_MSR_DDSR, + UART_MCR_OUT2, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + send_pulse_irdeo, + send_space_irdeo, + (LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SEND_PULSE| + LIRC_CAN_REC_MODE2) + }, + + /* IRdeo remote */ + { + UART_MSR_DSR, + UART_MSR_DDSR, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + send_pulse_irdeo, + send_space_irdeo, + (LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SEND_PULSE| + LIRC_CAN_REC_MODE2) + }, + + /* AnimaX */ + { + UART_MSR_DCD, + UART_MSR_DDCD, + 0, + UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2, + NULL, + NULL, + LIRC_CAN_REC_MODE2 + }, + + /* home-brew receiver/transmitter (Igor Cesko's variation) */ + { + UART_MSR_DSR, + UART_MSR_DDSR, + UART_MCR_RTS|UART_MCR_OUT2|UART_MCR_DTR, + UART_MCR_RTS|UART_MCR_OUT2, + send_pulse_homebrew, + send_space_homebrew, + ( +#ifdef LIRC_SERIAL_TRANSMITTER + LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| +#endif + LIRC_CAN_REC_MODE2) + }, + +#if defined(LIRC_SERIAL_NSLU2) + /* Modified Linksys Network Storage Link USB 2.0 (NSLU2): + We receive on CTS of the 2nd serial port (R142,LHS), we + transmit with a IR diode between GPIO[1] (green status LED), + and ground (Matthias Goebl ). + See also http://www.nslu2-linux.org for this device */ + { + UART_MSR_CTS, + UART_MSR_DCTS, + UART_MCR_RTS|UART_MCR_OUT2|UART_MCR_DTR, + UART_MCR_RTS|UART_MCR_OUT2, + send_pulse_homebrew, + send_space_homebrew, + ( +#ifdef LIRC_SERIAL_TRANSMITTER + LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| +#endif + LIRC_CAN_REC_MODE2) + }, +#endif + +}; + +#define RS_ISR_PASS_LIMIT 256 + +/* A long pulse code from a remote might take upto 300 bytes. The + daemon should read the bytes as soon as they are generated, so take + the number of keys you think you can push before the daemon runs + and multiply by 300. The driver will warn you if you overrun this + buffer. If you have a slow computer or non-busmastering IDE disks, + maybe you will need to increase this. */ + +/* This MUST be a power of two! It has to be larger than 1 as well. */ + +#define RBUF_LEN 256 +#define WBUF_LEN 256 + +static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ +static int txsense; /* 0 = active high, 1 = active low */ + +#ifndef LIRC_IRQ +#define LIRC_IRQ 4 +#endif +#ifndef LIRC_PORT +#define LIRC_PORT 0x3f8 +#endif + +static int io = LIRC_PORT; +static int irq = LIRC_IRQ; + +static struct timeval lasttv = {0, 0}; + +static struct lirc_buffer rbuf; + +static lirc_t wbuf[WBUF_LEN]; + +static unsigned int freq = 38000; +static unsigned int duty_cycle = 50; + +/* Initialized in init_timing_params() */ +static unsigned long period; +static unsigned long pulse_width; +static unsigned long space_width; + +#if defined(__i386__) +/* + From: + Linux I/O port programming mini-HOWTO + Author: Riku Saikkonen + v, 28 December 1997 + + [...] + Actually, a port I/O instruction on most ports in the 0-0x3ff range + takes almost exactly 1 microsecond, so if you're, for example, using + the parallel port directly, just do additional inb()s from that port + to delay. + [...] +*/ +/* transmitter latency 1.5625us 0x1.90 - this figure arrived at from + * comment above plus trimming to match actual measured frequency. + * This will be sensitive to cpu speed, though hopefully most of the 1.5us + * is spent in the uart access. Still - for reference test machine was a + * 1.13GHz Athlon system - Steve + */ + +/* changed from 400 to 450 as this works better on slower machines; + faster machines will use the rdtsc code anyway */ + +#define LIRC_SERIAL_TRANSMITTER_LATENCY 450 + +#else + +/* does anybody have information on other platforms ? */ +/* 256 = 1<<8 */ +#define LIRC_SERIAL_TRANSMITTER_LATENCY 256 + +#endif /* __i386__ */ + +static inline unsigned int sinp(int offset) +{ +#if defined(LIRC_ALLOW_MMAPPED_IO) + if (iommap != 0) { + /* the register is memory-mapped */ + offset <<= ioshift; + return readb(io + offset); + } +#endif + return inb(io + offset); +} + +static inline void soutp(int offset, int value) +{ +#if defined(LIRC_ALLOW_MMAPPED_IO) + if (iommap != 0) { + /* the register is memory-mapped */ + offset <<= ioshift; + writeb(value, io + offset); + } +#endif + outb(value, io + offset); +} + +static inline void on(void) +{ +#if defined(LIRC_SERIAL_NSLU2) + /* On NSLU2, we put the transmit diode between the output of the green + status LED and ground */ + if (type == LIRC_NSLU2) { + gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_LOW); + return; + } +#endif + if (txsense) + soutp(UART_MCR, hardware[type].off); + else + soutp(UART_MCR, hardware[type].on); +} + +static inline void off(void) +{ +#if defined(LIRC_SERIAL_NSLU2) + if (type == LIRC_NSLU2) { + gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_HIGH); + return; + } +#endif + if (txsense) + soutp(UART_MCR, hardware[type].on); + else + soutp(UART_MCR, hardware[type].off); +} + +#ifndef MAX_UDELAY_MS +#define MAX_UDELAY_US 5000 +#else +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) +#endif + +static inline void safe_udelay(unsigned long usecs) +{ + while (usecs > MAX_UDELAY_US) { + udelay(MAX_UDELAY_US); + usecs -= MAX_UDELAY_US; + } + udelay(usecs); +} + +#ifdef USE_RDTSC +/* This is an overflow/precision juggle, complicated in that we can't + do long long divide in the kernel */ + +/* When we use the rdtsc instruction to measure clocks, we keep the + * pulse and space widths as clock cycles. As this is CPU speed + * dependent, the widths must be calculated in init_port and ioctl + * time + */ + +/* So send_pulse can quickly convert microseconds to clocks */ +static unsigned long conv_us_to_clocks; + +static inline int init_timing_params(unsigned int new_duty_cycle, + unsigned int new_freq) +{ + unsigned long long loops_per_sec, work; + + duty_cycle = new_duty_cycle; + freq = new_freq; + + loops_per_sec = current_cpu_data.loops_per_jiffy; + loops_per_sec *= HZ; + + /* How many clocks in a microsecond?, avoiding long long divide */ + work = loops_per_sec; + work *= 4295; /* 4295 = 2^32 / 1e6 */ + conv_us_to_clocks = (work>>32); + + /* Carrier period in clocks, approach good up to 32GHz clock, + gets carrier frequency within 8Hz */ + period = loops_per_sec>>3; + period /= (freq>>3); + + /* Derive pulse and space from the period */ + + pulse_width = period*duty_cycle/100; + space_width = period - pulse_width; + dprintk("in init_timing_params, freq=%d, duty_cycle=%d, " + "clk/jiffy=%ld, pulse=%ld, space=%ld, " + "conv_us_to_clocks=%ld\n", + freq, duty_cycle, current_cpu_data.loops_per_jiffy, + pulse_width, space_width, conv_us_to_clocks); + return 0; +} +#else /* ! USE_RDTSC */ +static inline int init_timing_params(unsigned int new_duty_cycle, + unsigned int new_freq) +{ +/* period, pulse/space width are kept with 8 binary places - + * IE multiplied by 256. */ + if (256*1000000L/new_freq*new_duty_cycle/100 <= + LIRC_SERIAL_TRANSMITTER_LATENCY) + return -EINVAL; + if (256*1000000L/new_freq*(100-new_duty_cycle)/100 <= + LIRC_SERIAL_TRANSMITTER_LATENCY) + return -EINVAL; + duty_cycle = new_duty_cycle; + freq = new_freq; + period = 256*1000000L/freq; + pulse_width = period*duty_cycle/100; + space_width = period-pulse_width; + dprintk("in init_timing_params, freq=%d pulse=%ld, " + "space=%ld\n", freq, pulse_width, space_width); + return 0; +} +#endif /* USE_RDTSC */ + + +/* return value: space length delta */ + +static long send_pulse_irdeo(unsigned long length) +{ + long rawbits; + int i; + unsigned char output; + unsigned char chunk, shifted; + + /* how many bits have to be sent ? */ + rawbits = length*1152/10000; + if (duty_cycle > 50) + chunk = 3; + else + chunk = 1; + for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) { + shifted = chunk<<(i*3); + shifted >>= 1; + output &= (~shifted); + i++; + if (i == 3) { + soutp(UART_TX, output); + while (!(sinp(UART_LSR) & UART_LSR_THRE)); + output = 0x7f; + i = 0; + } + } + if (i != 0) { + soutp(UART_TX, output); + while (!(sinp(UART_LSR) & UART_LSR_TEMT)); + } + + if (i == 0) + return ((-rawbits)*10000/1152); + else + return ((3-i)*3*10000/1152+(-rawbits)*10000/1152); +} + +#ifdef USE_RDTSC +/* Version that uses Pentium rdtsc instruction to measure clocks */ + +/* This version does sub-microsecond timing using rdtsc instruction, + * and does away with the fudged LIRC_SERIAL_TRANSMITTER_LATENCY + * Implicitly i586 architecture... - Steve + */ + +static inline long send_pulse_homebrew_softcarrier(unsigned long length) +{ + int flag; + unsigned long target, start, now; + + /* Get going quick as we can */ + rdtscl(start); on(); + /* Convert length from microseconds to clocks */ + length *= conv_us_to_clocks; + /* And loop till time is up - flipping at right intervals */ + now = start; + target = pulse_width; + flag = 1; + while ((now-start) < length) { + /* Delay till flip time */ + do + rdtscl(now); + while ((now-start) < target); + + /* flip */ + if (flag) { + rdtscl(now); off(); + target += space_width; + } else { + rdtscl(now); on(); + target += pulse_width; + } + flag = !flag; + } + rdtscl(now); + return (((now-start)-length)/conv_us_to_clocks); +} +#else /* ! USE_RDTSC */ +/* Version using udelay() */ + +/* here we use fixed point arithmetic, with 8 + fractional bits. that gets us within 0.1% or so of the right average + frequency, albeit with some jitter in pulse length - Steve */ + +/* To match 8 fractional bits used for pulse/space length */ + +static inline long send_pulse_homebrew_softcarrier(unsigned long length) +{ + int flag; + unsigned long actual, target, d; + length <<= 8; + + actual = 0; target = 0; flag = 0; + while (actual < length) { + if (flag) { + off(); + target += space_width; + } else { + on(); + target += pulse_width; + } + d = (target-actual-LIRC_SERIAL_TRANSMITTER_LATENCY+128)>>8; + /* Note - we've checked in ioctl that the pulse/space + widths are big enough so that d is > 0 */ + udelay(d); + actual += (d<<8)+LIRC_SERIAL_TRANSMITTER_LATENCY; + flag = !flag; + } + return ((actual-length)>>8); +} +#endif /* USE_RDTSC */ + +static long send_pulse_homebrew(unsigned long length) +{ + if (length <= 0) + return 0; + + if (softcarrier) + return send_pulse_homebrew_softcarrier(length); + else { + on(); + safe_udelay(length); + return 0; + } +} + +static void send_space_irdeo(long length) +{ + if (length <= 0) + return; + + safe_udelay(length); +} + +static void send_space_homebrew(long length) +{ + off(); + if (length <= 0) + return; + safe_udelay(length); +} + +static inline void rbwrite(lirc_t l) +{ + if (lirc_buffer_full(&rbuf)) { + /* no new signals will be accepted */ + dprintk("Buffer overrun\n"); + return; + } + _lirc_buffer_write_1(&rbuf, (void *)&l); +} + +static inline void frbwrite(lirc_t l) +{ + /* simple noise filter */ + static lirc_t pulse = 0L, space = 0L; + static unsigned int ptr; + + if (ptr > 0 && (l&PULSE_BIT)) { + pulse += l&PULSE_MASK; + if (pulse > 250) { + rbwrite(space); + rbwrite(pulse|PULSE_BIT); + ptr = 0; + pulse = 0; + } + return; + } + if (!(l&PULSE_BIT)) { + if (ptr == 0) { + if (l > 20000) { + space = l; + ptr++; + return; + } + } else { + if (l > 20000) { + space += pulse; + if (space > PULSE_MASK) + space = PULSE_MASK; + space += l; + if (space > PULSE_MASK) + space = PULSE_MASK; + pulse = 0; + return; + } + rbwrite(space); + rbwrite(pulse|PULSE_BIT); + ptr = 0; + pulse = 0; + } + } + rbwrite(l); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) +static irqreturn_t irq_handler(int i, void *blah) +#else +static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs) +#endif +{ + struct timeval tv; + int status, counter, dcd; + long deltv; + lirc_t data; + static int last_dcd = -1; + + if ((sinp(UART_IIR) & UART_IIR_NO_INT)) { + /* not our interrupt */ + return IRQ_RETVAL(IRQ_NONE); + } + + counter = 0; + do { + counter++; + status = sinp(UART_MSR); + if (counter > RS_ISR_PASS_LIMIT) { + printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: " + "We're caught!\n"); + break; + } + if ((status&hardware[type].signal_pin_change) && sense != -1) { + /* get current time */ + do_gettimeofday(&tv); + + /* New mode, written by Trent Piepho + . */ + + /* The old format was not very portable. + We now use the type lirc_t to pass pulses + and spaces to user space. + + If PULSE_BIT is set a pulse has been + received, otherwise a space has been + received. The driver needs to know if your + receiver is active high or active low, or + the space/pulse sense could be + inverted. The bits denoted by PULSE_MASK are + the length in microseconds. Lengths greater + than or equal to 16 seconds are clamped to + PULSE_MASK. All other bits are unused. + This is a much simpler interface for user + programs, as well as eliminating "out of + phase" errors with space/pulse + autodetection. */ + + /* calculate time since last interrupt in + microseconds */ + dcd = (status & hardware[type].signal_pin) ? 1:0; + + if (dcd == last_dcd) { + printk(KERN_WARNING LIRC_DRIVER_NAME + ": ignoring spike: %d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + continue; + } + + deltv = tv.tv_sec-lasttv.tv_sec; + if (tv.tv_sec < lasttv.tv_sec || + (tv.tv_sec == lasttv.tv_sec && + tv.tv_usec < lasttv.tv_usec)) { + printk(KERN_WARNING LIRC_DRIVER_NAME + ": AIEEEE: your clock just jumped " + "backwards\n"); + printk(KERN_WARNING LIRC_DRIVER_NAME + ": %d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + data = PULSE_MASK; + } else if (deltv > 15) { + data = PULSE_MASK; /* really long time */ + if (!(dcd^sense)) { + /* sanity check */ + printk(KERN_WARNING LIRC_DRIVER_NAME + ": AIEEEE: " + "%d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + /* detecting pulse while this + MUST be a space! */ + sense = sense ? 0:1; + } + } else + data = (lirc_t) (deltv*1000000 + + tv.tv_usec - + lasttv.tv_usec); + frbwrite(dcd^sense ? data : (data|PULSE_BIT)); + lasttv = tv; + last_dcd = dcd; + wake_up_interruptible(&rbuf.wait_poll); + } + } while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */ + return IRQ_RETVAL(IRQ_HANDLED); +} + +static void hardware_init_port(void) +{ + unsigned long flags; + local_irq_save(flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Clear registers. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + +#if defined(LIRC_SERIAL_NSLU2) + if (type == LIRC_NSLU2) { + /* Setup NSLU2 UART */ + + /* Enable UART */ + soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE); + /* Disable Receiver data Time out interrupt */ + soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE); + /* set out2 = interupt unmask; off() doesn't set MCR + on NSLU2 */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + } +#endif + + /* Set line for power source */ + off(); + + /* Clear registers again to be sure. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + + switch (type) { + case LIRC_IRDEO: + case LIRC_IRDEO_REMOTE: + /* setup port to 7N1 @ 115200 Baud */ + /* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */ + + /* Set DLAB 1. */ + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + /* Set DLAB 0 + 7N1 */ + soutp(UART_LCR, UART_LCR_WLEN7); + /* THR interrupt already disabled at this point */ + break; + default: + break; + } + + local_irq_restore(flags); +} + +static int init_port(void) +{ + int i, nlow, nhigh; + + /* Reserve io region. */ +#if defined(LIRC_ALLOW_MMAPPED_IO) + /* Future MMAP-Developers: Attention! + For memory mapped I/O you *might* need to use ioremap() first, + for the NSLU2 it's done in boot code. */ + if (((iommap != 0) + && (request_mem_region(iommap, 8<= nhigh ? 1 : 0); + printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " + "%s receiver\n", sense ? "low":"high"); + } else + printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " + "%s receiver\n", sense ? "low":"high"); + + return 0; +} + +static int set_use_inc(void *data) +{ + int result; + unsigned long flags; + + /* Init read buffer. */ + if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0) + return -ENOMEM; + + /* initialize timestamp */ + do_gettimeofday(&lasttv); + + result = request_irq(irq, irq_handler, + IRQF_DISABLED | (share_irq ? IRQF_SHARED:0), + LIRC_DRIVER_NAME, (void *)&hardware); + + switch (result) { + case -EBUSY: + printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); + lirc_buffer_free(&rbuf); + return -EBUSY; + case -EINVAL: + printk(KERN_ERR LIRC_DRIVER_NAME + ": Bad irq number or handler\n"); + lirc_buffer_free(&rbuf); + return -EINVAL; + default: + dprintk("Interrupt %d, port %04x obtained\n", irq, io); + break; + }; + + local_irq_save(flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); + + local_irq_restore(flags); + + MOD_INC_USE_COUNT; + return 0; +} + +static void set_use_dec(void *data) +{ unsigned long flags; + + local_irq_save(flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + local_irq_restore(flags); + + free_irq(irq, (void *)&hardware); + + dprintk("freed IRQ %d\n", irq); + lirc_buffer_free(&rbuf); + + MOD_DEC_USE_COUNT; +} + +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *ppos) +{ + int i, count; + unsigned long flags; + long delta = 0; + + if (!(hardware[type].features&LIRC_CAN_SEND_PULSE)) + return -EBADF; + + if (n % sizeof(lirc_t)) + return -EINVAL; + count = n / sizeof(lirc_t); + if (count > WBUF_LEN || count % 2 == 0) + return -EINVAL; + if (copy_from_user(wbuf, buf, n)) + return -EFAULT; + local_irq_save(flags); + if (type == LIRC_IRDEO) { + /* DTR, RTS down */ + on(); + } + for (i = 0; i < count; i++) { + if (i%2) + hardware[type].send_space(wbuf[i]-delta); + else + delta = hardware[type].send_pulse(wbuf[i]); + } + off(); + local_irq_restore(flags); + return n; +} + +static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int result; + unsigned long value; + unsigned int ivalue; + + switch (cmd) { + case LIRC_GET_SEND_MODE: + if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) + return -ENOIOCTLCMD; + + result = put_user(LIRC_SEND2MODE + (hardware[type].features&LIRC_CAN_SEND_MASK), + (unsigned long *) arg); + if (result) + return result; + break; + + case LIRC_SET_SEND_MODE: + if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) + return -ENOIOCTLCMD; + + result = get_user(value, (unsigned long *) arg); + if (result) + return result; + /* only LIRC_MODE_PULSE supported */ + if (value != LIRC_MODE_PULSE) + return -ENOSYS; + break; + + case LIRC_GET_LENGTH: + return -ENOSYS; + break; + + case LIRC_SET_SEND_DUTY_CYCLE: + dprintk("SET_SEND_DUTY_CYCLE\n"); + if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if (ivalue <= 0 || ivalue > 100) + return -EINVAL; + return init_timing_params(ivalue, freq); + break; + + case LIRC_SET_SEND_CARRIER: + dprintk("SET_SEND_CARRIER\n"); + if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if (ivalue > 500000 || ivalue < 20000) + return -EINVAL; + return init_timing_params(duty_cycle, ivalue); + break; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static struct file_operations lirc_fops = { + .write = lirc_write, +}; + +static struct lirc_plugin plugin = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .get_queue = NULL, + .rbuf = &rbuf, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .ioctl = lirc_ioctl, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + +#ifdef MODULE + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +static struct platform_device *lirc_serial_dev; + +static int __devinit lirc_serial_probe(struct platform_device *dev) +{ + return 0; +} + +static int __devexit lirc_serial_remove(struct platform_device *dev) +{ + return 0; +} + +static int lirc_serial_suspend(struct platform_device *dev, + pm_message_t state) +{ + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* Disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Clear registers. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + + return 0; +} + +static int lirc_serial_resume(struct platform_device *dev) +{ + unsigned long flags; + + hardware_init_port(); + + local_irq_save(flags); + /* Enable Interrupt */ + do_gettimeofday(&lasttv); + soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); + off(); + + lirc_buffer_clear(&rbuf); + + local_irq_restore(flags); + + return 0; +} + +static struct platform_driver lirc_serial_driver = { + .probe = lirc_serial_probe, + .remove = __devexit_p(lirc_serial_remove), + .suspend = lirc_serial_suspend, + .resume = lirc_serial_resume, + .driver = { + .name = "lirc_serial", + .owner = THIS_MODULE, + }, +}; + +static int __init lirc_serial_init(void) +{ + int result; + + result = platform_driver_register(&lirc_serial_driver); + if (result) { + printk("lirc register returned %d\n", result); + return result; + } + + lirc_serial_dev = platform_device_alloc("lirc_serial", 0); + if (!lirc_serial_dev) { + result = -ENOMEM; + goto exit_driver_unregister; + } + + result = platform_device_add(lirc_serial_dev); + if (result) + goto exit_device_put; + + return 0; + +exit_device_put: + platform_device_put(lirc_serial_dev); +exit_driver_unregister: + platform_driver_unregister(&lirc_serial_driver); + return result; +} + +static void __exit lirc_serial_exit(void) +{ + platform_device_unregister(lirc_serial_dev); + platform_driver_unregister(&lirc_serial_driver); +} +#endif + +int __init init_module(void) +{ + int result; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) + result = lirc_serial_init(); + if (result) + return result; +#endif + switch (type) { + case LIRC_HOMEBREW: + case LIRC_IRDEO: + case LIRC_IRDEO_REMOTE: + case LIRC_ANIMAX: + case LIRC_IGOR: +#if defined(LIRC_SERIAL_NSLU2) + case LIRC_NSLU2: +#endif + break; + default: + result = -EINVAL; + goto exit_serial_exit; + } + if (!softcarrier) { + switch (type) { + case LIRC_HOMEBREW: + case LIRC_IGOR: + case LIRC_NSLU2: + hardware[type].features &= + ~(LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER); + break; + } + } + result = init_port(); + if (result < 0) + goto exit_serial_exit; + plugin.features = hardware[type].features; + plugin.minor = lirc_register_plugin(&plugin); + if (plugin.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": register_chrdev failed!\n"); + result = -EIO; + goto exit_release; + } + return 0; +exit_release: + release_region(io, 8); +exit_serial_exit: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) + lirc_serial_exit(); +#endif + return result; +} + +void __exit cleanup_module(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) + lirc_serial_exit(); +#endif +#if defined(LIRC_ALLOW_MMAPPED_IO) + if (iommap != 0) + release_mem_region(iommap, 8< + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * ITE IT8705 and IT8712(not tested) CIR-port support for lirc based + * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula + * + * Attention: Sendmode only tested with debugging logs + * + * 2001/02/27 Christoph Bartelmus : + * reimplemented read function + * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, + * based on work of the following member of the Outertrack Digimatrix + * Forum: Art103 + */ + + +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include + +#include "lirc.h" +#include "lirc_dev/lirc_dev.h" +#include "kcompat.h" + +#include "lirc_it87.h" + +#ifdef LIRC_IT87_DIGIMATRIX +static int digimatrix = 1; +static int it87_freq = 36; /* kHz */ +static int irq = 9; +#else +static int digimatrix; +static int it87_freq = 38; /* kHz */ +static int irq = IT87_CIR_DEFAULT_IRQ; +#endif + +static unsigned long it87_bits_in_byte_out; +static unsigned long it87_send_counter; +static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; + +#define RBUF_LEN 1024 +#define WBUF_LEN 1024 + +#define LIRC_DRIVER_NAME "lirc_it87" + +/* timeout for sequences in jiffies (=5/100s) */ +/* must be longer than TIME_CONST */ +#define IT87_TIMEOUT (HZ*5/100) + +/* insmod parameters */ +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + +static int io = IT87_CIR_DEFAULT_IOBASE; +/* receiver demodulator default: off */ +static int it87_enable_demodulator; + +static int timer_enabled; +static DEFINE_SPINLOCK(timer_lock); +static struct timer_list timerlist; +/* time of last signal change detected */ +static struct timeval last_tv = {0, 0}; +/* time of last UART data ready interrupt */ +static struct timeval last_intr_tv = {0, 0}; +static int last_value; + +static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); + +static DEFINE_SPINLOCK(hardware_lock); +static DEFINE_SPINLOCK(dev_lock); + +static lirc_t rx_buf[RBUF_LEN]; +unsigned int rx_tail, rx_head; +static lirc_t tx_buf[WBUF_LEN]; + +/* SECTION: Prototypes */ + +/* Communication with user-space */ +static int lirc_open(struct inode *inode, struct file *file); +static int lirc_close(struct inode *inode, struct file *file); +static unsigned int lirc_poll(struct file *file, poll_table *wait); +static ssize_t lirc_read(struct file *file, char *buf, + size_t count, loff_t *ppos); +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *pos); +static int lirc_ioctl(struct inode *node, struct file *filep, + unsigned int cmd, unsigned long arg); +static void add_read_queue(int flag, unsigned long val); +#ifdef MODULE +static int init_chrdev(void); +static void drop_chrdev(void); +#endif + /* Hardware */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static irqreturn_t it87_interrupt(int irq, void *dev_id, + struct pt_regs *regs); +#else +static irqreturn_t it87_interrupt(int irq, void *dev_id); +#endif +static void send_space(unsigned long len); +static void send_pulse(unsigned long len); +static void init_send(void); +static void terminate_send(unsigned long len); +static int init_hardware(void); +static void drop_hardware(void); + /* Initialisation */ +static int init_port(void); +static void drop_port(void); +int init_module(void); +void cleanup_module(void); + + +/* SECTION: Communication with user-space */ + +static int lirc_open(struct inode *inode, struct file *file) +{ + spin_lock(&dev_lock); + if (MOD_IN_USE) { + spin_unlock(&dev_lock); + return -EBUSY; + } + MOD_INC_USE_COUNT; + spin_unlock(&dev_lock); + return 0; +} + + +static int lirc_close(struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + + +static unsigned int lirc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &lirc_read_queue, wait); + if (rx_head != rx_tail) + return POLLIN | POLLRDNORM; + return 0; +} + + +static ssize_t lirc_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + int n = 0; + int retval = 0; + + while (n < count) { + if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { + retval = -EAGAIN; + break; + } + retval = wait_event_interruptible(lirc_read_queue, + rx_head != rx_tail); + if (retval) + break; + + if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), + sizeof(lirc_t))) { + retval = -EFAULT; + break; + } + rx_head = (rx_head + 1) & (RBUF_LEN - 1); + n += sizeof(lirc_t); + } + if (n) + return n; + return retval; +} + + +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *pos) +{ + int i = 0; + + if (n % sizeof(lirc_t) || (n / sizeof(lirc_t)) > WBUF_LEN) + return -EINVAL; + if (copy_from_user(tx_buf, buf, n)) + return -EFAULT; + n /= sizeof(lirc_t); + init_send(); + while (1) { + if (i >= n) + break; + if (tx_buf[i]) + send_pulse(tx_buf[i]); + i++; + if (i >= n) + break; + if (tx_buf[i]) + send_space(tx_buf[i]); + i++; + } + terminate_send(tx_buf[i - 1]); + return n; +} + + +static int lirc_ioctl(struct inode *node, struct file *filep, + unsigned int cmd, unsigned long arg) +{ + int retval = 0; + unsigned long value = 0; + unsigned int ivalue; + unsigned long hw_flags; + + if (cmd == LIRC_GET_FEATURES) + value = LIRC_CAN_SEND_PULSE | + LIRC_CAN_SET_SEND_CARRIER | + LIRC_CAN_REC_MODE2; + else if (cmd == LIRC_GET_SEND_MODE) + value = LIRC_MODE_PULSE; + else if (cmd == LIRC_GET_REC_MODE) + value = LIRC_MODE_MODE2; + + switch (cmd) { + case LIRC_GET_FEATURES: + case LIRC_GET_SEND_MODE: + case LIRC_GET_REC_MODE: + retval = put_user(value, (unsigned long *) arg); + break; + + case LIRC_SET_SEND_MODE: + case LIRC_SET_REC_MODE: + retval = get_user(value, (unsigned long *) arg); + break; + + case LIRC_SET_SEND_CARRIER: + retval = get_user(ivalue, (unsigned int *) arg); + if (retval) + return retval; + ivalue /= 1000; + if (ivalue > IT87_CIR_FREQ_MAX || + ivalue < IT87_CIR_FREQ_MIN) + return -EINVAL; + + it87_freq = ivalue; + + spin_lock_irqsave(&hardware_lock, hw_flags); + outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | + (it87_freq - IT87_CIR_FREQ_MIN) << 3), + io + IT87_CIR_TCR2); + spin_unlock_irqrestore(&hardware_lock, hw_flags); + dprintk("demodulation frequency: %d kHz\n", it87_freq); + + break; + + default: + retval = -ENOIOCTLCMD; + } + + if (retval) + return retval; + + if (cmd == LIRC_SET_REC_MODE) { + if (value != LIRC_MODE_MODE2) + retval = -ENOSYS; + } else if (cmd == LIRC_SET_SEND_MODE) { + if (value != LIRC_MODE_PULSE) + retval = -ENOSYS; + } + return retval; +} + +static void add_read_queue(int flag, unsigned long val) +{ + unsigned int new_rx_tail; + lirc_t newval; + + dprintk("add flag %d with val %lu\n", flag, val); + + newval = val & PULSE_MASK; + + /* statistically pulses are ~TIME_CONST/2 too long: we could + maybe make this more exactly but this is good enough */ + if (flag) { + /* pulse */ + if (newval > TIME_CONST / 2) + newval -= TIME_CONST / 2; + else /* should not ever happen */ + newval = 1; + newval |= PULSE_BIT; + } else + newval += TIME_CONST / 2; + new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); + if (new_rx_tail == rx_head) { + dprintk("Buffer overrun.\n"); + return; + } + rx_buf[rx_tail] = newval; + rx_tail = new_rx_tail; + wake_up_interruptible(&lirc_read_queue); +} + + +static struct file_operations lirc_fops = { + .read = lirc_read, + .write = lirc_write, + .poll = lirc_poll, + .ioctl = lirc_ioctl, + .open = lirc_open, + .release = lirc_close, +}; + +static int set_use_inc(void *data) +{ + return 0; +} + +static void set_use_dec(void *data) +{ + +} +static struct lirc_plugin plugin = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .get_queue = NULL, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + + +#ifdef MODULE +static int init_chrdev(void) +{ + plugin.minor = lirc_register_plugin(&plugin); + + if (plugin.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); + return -EIO; + } + return 0; +} + + +static void drop_chrdev(void) +{ + lirc_unregister_plugin(plugin.minor); +} +#endif + + +/* SECTION: Hardware */ +static long delta(struct timeval *tv1, struct timeval *tv2) +{ + unsigned long deltv; + + deltv = tv2->tv_sec - tv1->tv_sec; + if (deltv > 15) + deltv = 0xFFFFFF; + else + deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; + return deltv; +} + +static void it87_timeout(unsigned long data) +{ + unsigned long flags; + + /* avoid interference with interrupt */ + spin_lock_irqsave(&timer_lock, flags); + + if (digimatrix) { + /* We have timed out. + Disable the RX mechanism. + */ + + outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | + IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); + if (it87_RXEN_mask) + outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + dprintk(" TIMEOUT\n"); + timer_enabled = 0; + + /* fifo clear */ + outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, + io+IT87_CIR_TCR1); + + } else { + /* if last received signal was a pulse, but receiving + stopped within the 9 bit frame, we need to finish + this pulse and simulate a signal change to from + pulse to space. Otherwise upper layers will receive + two sequences next time. */ + + if (last_value) { + unsigned long pulse_end; + + /* determine 'virtual' pulse end: */ + pulse_end = delta(&last_tv, &last_intr_tv); + dprintk("timeout add %d for %lu usec\n", + last_value, pulse_end); + add_read_queue(last_value, pulse_end); + last_value = 0; + last_tv = last_intr_tv; + } + } + spin_unlock_irqrestore(&timer_lock, flags); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static irqreturn_t it87_interrupt(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t it87_interrupt(int irq, void *dev_id) +#endif +{ + unsigned char data; + struct timeval curr_tv; + static unsigned long deltv; + unsigned long deltintrtv; + unsigned long flags, hw_flags; + int iir, lsr; + int fifo = 0; + static char lastbit; + char bit; + + /* Bit duration in microseconds */ + const unsigned long bit_duration = 1000000ul / + (115200 / IT87_CIR_BAUDRATE_DIVISOR); + + + iir = inb(io + IT87_CIR_IIR); + + switch (iir & IT87_CIR_IIR_IID) { + case 0x4: + case 0x6: + lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | + IT87_CIR_RSR_RXFBC); + fifo = lsr & IT87_CIR_RSR_RXFBC; + dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); + + /* avoid interference with timer */ + spin_lock_irqsave(&timer_lock, flags); + spin_lock_irqsave(&hardware_lock, hw_flags); + if (digimatrix) { + static unsigned long acc_pulse; + static unsigned long acc_space; + + do { + data = inb(io + IT87_CIR_DR); + data = ~data; + fifo--; + if (data != 0x00) { + if (timer_enabled) + del_timer(&timerlist); + /* start timer for end of + * sequence detection */ + timerlist.expires = jiffies + + IT87_TIMEOUT; + add_timer(&timerlist); + timer_enabled = 1; + } + /* Loop through */ + for (bit = 0; bit < 8; ++bit) { + if ((data >> bit) & 1) { + ++acc_pulse; + if (lastbit == 0) { + add_read_queue(0, + acc_space * + bit_duration); + acc_space = 0; + } + } else { + ++acc_space; + if (lastbit == 1) { + add_read_queue(1, + acc_pulse * + bit_duration); + acc_pulse = 0; + } + } + lastbit = (data >> bit) & 1; + } + + } while (fifo != 0); + } else { /* Normal Operation */ + do { + del_timer(&timerlist); + data = inb(io + IT87_CIR_DR); + + dprintk("data=%.2x\n", data); + do_gettimeofday(&curr_tv); + deltv = delta(&last_tv, &curr_tv); + deltintrtv = delta(&last_intr_tv, &curr_tv); + + dprintk("t %lu , d %d\n", + deltintrtv, (int)data); + + /* if nothing came in last 2 cycles, + it was gap */ + if (deltintrtv > TIME_CONST * 2) { + if (last_value) { + dprintk("GAP\n"); + + /* simulate signal change */ + add_read_queue(last_value, + deltv - + deltintrtv); + last_value = 0; + last_tv.tv_sec = + last_intr_tv.tv_sec; + last_tv.tv_usec = + last_intr_tv.tv_usec; + deltv = deltintrtv; + } + } + data = 1; + if (data ^ last_value) { + /* deltintrtv > 2*TIME_CONST, + remember ? */ + /* the other case is timeout */ + add_read_queue(last_value, + deltv-TIME_CONST); + last_value = data; + last_tv = curr_tv; + if (last_tv.tv_usec >= TIME_CONST) + last_tv.tv_usec -= TIME_CONST; + else { + last_tv.tv_sec--; + last_tv.tv_usec += 1000000 - + TIME_CONST; + } + } + last_intr_tv = curr_tv; + if (data) { + /* start timer for end of + * sequence detection */ + timerlist.expires = + jiffies + IT87_TIMEOUT; + add_timer(&timerlist); + } + outb((inb(io + IT87_CIR_RCR) & + ~IT87_CIR_RCR_RXEN) | + IT87_CIR_RCR_RXACT, + io + IT87_CIR_RCR); + if (it87_RXEN_mask) + outb(inb(io + IT87_CIR_RCR) | + IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + fifo--; + } while (fifo != 0); + } + spin_unlock_irqrestore(&hardware_lock, hw_flags); + spin_unlock_irqrestore(&timer_lock, flags); + + return IRQ_RETVAL(IRQ_HANDLED); + + default: + /* not our irq */ + dprintk("unknown IRQ (shouldn't happen) !!\n"); + return IRQ_RETVAL(IRQ_NONE); + } +} + + +static void send_it87(unsigned long len, unsigned long stime, + unsigned char send_byte, unsigned int count_bits) +{ + long count = len / stime; + long time_left = 0; + static unsigned char byte_out; + unsigned long hw_flags; + + dprintk("%s: len=%ld, sb=%d\n", __FUNCTION__, len, send_byte); + + time_left = (long)len - (long)count * (long)stime; + count += ((2 * time_left) / stime); + while (count) { + long i = 0; + for (i = 0; i < count_bits; i++) { + byte_out = (byte_out << 1) | (send_byte & 1); + it87_bits_in_byte_out++; + } + if (it87_bits_in_byte_out == 8) { + dprintk("out=0x%x, tsr_txfbc: 0x%x\n", + byte_out, + inb(io + IT87_CIR_TSR) & + IT87_CIR_TSR_TXFBC); + + while ((inb(io + IT87_CIR_TSR) & + IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) + ; + + spin_lock_irqsave(&hardware_lock, hw_flags); + outb(byte_out, io + IT87_CIR_DR); + spin_unlock_irqrestore(&hardware_lock, hw_flags); + + it87_bits_in_byte_out = 0; + it87_send_counter++; + byte_out = 0; + } + count--; + } +} + + +/* +maybe: exchange space and pulse because +it8705 only modulates 0-bits +*/ + + +static void send_space(unsigned long len) +{ + send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); +} + +static void send_pulse(unsigned long len) +{ + send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); +} + + +static void init_send() +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + /* RXEN=0: receiver disable */ + it87_RXEN_mask = 0; + outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + spin_unlock_irqrestore(&hardware_lock, flags); + it87_bits_in_byte_out = 0; + it87_send_counter = 0; +} + + +static void terminate_send(unsigned long len) +{ + unsigned long flags; + unsigned long last = 0; + + last = it87_send_counter; + /* make sure all necessary data has been sent */ + while (last == it87_send_counter) + send_space(len); + /* wait until all data sent */ + while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0); + /* then reenable receiver */ + spin_lock_irqsave(&hardware_lock, flags); + it87_RXEN_mask = IT87_CIR_RCR_RXEN; + outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + spin_unlock_irqrestore(&hardware_lock, flags); +} + + +static int init_hardware(void) +{ + unsigned long flags; + unsigned char it87_rcr = 0; + + spin_lock_irqsave(&hardware_lock, flags); + /* init cir-port */ + /* enable r/w-access to Baudrate-Register */ + outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); + outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); + outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); + /* Baudrate Register off, define IRQs: Input only */ + if (digimatrix) { + outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); + /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ + } else { + outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); + /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ + } + it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; + if (it87_enable_demodulator) + it87_rcr |= IT87_CIR_RCR_RXEND; + outb(it87_rcr, io + IT87_CIR_RCR); + if (digimatrix) { + /* Set FIFO depth to 1 byte, and disable TX */ + outb(inb(io + IT87_CIR_TCR1) | 0x00, + io + IT87_CIR_TCR1); + + /* TX: it87_freq (36kHz), + 'reserved' sensitivity setting (0x00) */ + outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, + io + IT87_CIR_TCR2); + } else { + /* TX: 38kHz, 13,3us (pulse-width */ + outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, + io + IT87_CIR_TCR2); + } + spin_unlock_irqrestore(&hardware_lock, flags); + return 0; +} + + +static void drop_hardware(void) +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + disable_irq(irq); + /* receiver disable */ + it87_RXEN_mask = 0; + outb(0x1, io + IT87_CIR_RCR); + /* turn off irqs */ + outb(0, io + IT87_CIR_IER); + /* fifo clear */ + outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); + /* reset */ + outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); + enable_irq(irq); + spin_unlock_irqrestore(&hardware_lock, flags); +} + + +static unsigned char it87_read(unsigned char port) +{ + outb(port, IT87_ADRPORT); + return inb(IT87_DATAPORT); +} + + +static void it87_write(unsigned char port, unsigned char data) +{ + outb(port, IT87_ADRPORT); + outb(data, IT87_DATAPORT); +} + + +/* SECTION: Initialisation */ + +static int init_port(void) +{ + unsigned long hw_flags; + int retval = 0; + + unsigned char init_bytes[4] = {IT87_INIT}; + unsigned char it87_chipid = 0; + unsigned char ldn = 0; + unsigned int it87_io = 0; + unsigned int it87_irq = 0; + + /* Enter MB PnP Mode */ + outb(init_bytes[0], IT87_ADRPORT); + outb(init_bytes[1], IT87_ADRPORT); + outb(init_bytes[2], IT87_ADRPORT); + outb(init_bytes[3], IT87_ADRPORT); + + /* 8712 or 8705 ? */ + it87_chipid = it87_read(IT87_CHIP_ID1); + if (it87_chipid != 0x87) { + retval = -ENXIO; + return retval; + } + it87_chipid = it87_read(IT87_CHIP_ID2); + if ((it87_chipid != 0x12) && (it87_chipid != 0x05)) { + printk(KERN_INFO LIRC_DRIVER_NAME + ": no IT8705/12 found, exiting..\n"); + retval = -ENXIO; + return retval; + } + printk(KERN_INFO LIRC_DRIVER_NAME + ": found IT87%.2x.\n", + it87_chipid); + + /* get I/O-Port and IRQ */ + if (it87_chipid == 0x12) + ldn = IT8712_CIR_LDN; + else + ldn = IT8705_CIR_LDN; + it87_write(IT87_LDN, ldn); + + it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + + it87_read(IT87_CIR_BASE_LSB); + if (it87_io == 0) { + if (io == 0) + io = IT87_CIR_DEFAULT_IOBASE; + printk(KERN_INFO LIRC_DRIVER_NAME + ": set default io 0x%x\n", + io); + it87_write(IT87_CIR_BASE_MSB, io / 0x100); + it87_write(IT87_CIR_BASE_LSB, io % 0x100); + } else + io = it87_io; + + it87_irq = it87_read(IT87_CIR_IRQ); + if (digimatrix || it87_irq == 0) { + if (irq == 0) + irq = IT87_CIR_DEFAULT_IRQ; + printk(KERN_INFO LIRC_DRIVER_NAME + ": set default irq 0x%x\n", + irq); + it87_write(IT87_CIR_IRQ, irq); + } else + irq = it87_irq; + + spin_lock_irqsave(&hardware_lock, hw_flags); + /* reset */ + outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); + /* fifo clear */ + outb(IT87_CIR_TCR1_FIFOCLR | + /* IT87_CIR_TCR1_ILE | */ + IT87_CIR_TCR1_TXRLE | + IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); + spin_unlock_irqrestore(&hardware_lock, hw_flags); + + /* get I/O port access and IRQ line */ + if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": i/o port 0x%.4x already in use.\n", io); + /* Leaving MB PnP Mode */ + it87_write(IT87_CFGCTRL, 0x2); + return -EBUSY; + } + + /* activate CIR-Device */ + it87_write(IT87_CIR_ACT, 0x1); + + /* Leaving MB PnP Mode */ + it87_write(IT87_CFGCTRL, 0x2); + + retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, + LIRC_DRIVER_NAME, NULL); + if (retval < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": IRQ %d already in use.\n", + irq); + release_region(io, 8); + return retval; + } + + printk(KERN_INFO LIRC_DRIVER_NAME + ": I/O port 0x%.4x, IRQ %d.\n", io, irq); + + init_timer(&timerlist); + timerlist.function = it87_timeout; + timerlist.data = 0xabadcafe; + + return 0; +} + + +static void drop_port(void) +{ +/* + unsigned char init_bytes[4] = {IT87_INIT}; + + / * Enter MB PnP Mode * / + outb(init_bytes[0], IT87_ADRPORT); + outb(init_bytes[1], IT87_ADRPORT); + outb(init_bytes[2], IT87_ADRPORT); + outb(init_bytes[3], IT87_ADRPORT); + + / * deactivate CIR-Device * / + it87_write(IT87_CIR_ACT, 0x0); + + / * Leaving MB PnP Mode * / + it87_write(IT87_CFGCTRL, 0x2); +*/ + + del_timer_sync(&timerlist); + free_irq(irq, NULL); + release_region(io, 8); +} + + +static int init_lirc_it87(void) +{ + int retval; + + init_waitqueue_head(&lirc_read_queue); + retval = init_port(); + if (retval < 0) + return retval; + init_hardware(); + printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); + return 0; +} + + +#ifdef MODULE + +int init_module(void) +{ + int retval; + + retval = init_chrdev(); + if (retval < 0) + return retval; + retval = init_lirc_it87(); + if (retval) { + drop_chrdev(); + return retval; + } + return 0; +} + + +void cleanup_module(void) +{ + drop_hardware(); + drop_chrdev(); + drop_port(); + printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); +} + +MODULE_DESCRIPTION("LIRC driver for ITE IT8712/IT8705 CIR port"); +MODULE_AUTHOR("Hans-Günter Lütke Uphues"); +MODULE_LICENSE("GPL"); + +module_param(io, int, 0444); +MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); + +module_param(irq, int, 0444); +#ifdef LIRC_IT87_DIGIMATRIX +MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); +#else +MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); +#endif + +module_param(it87_enable_demodulator, bool, 0444); +MODULE_PARM_DESC(it87_enable_demodulator, + "Receiver demodulator enable/disable (1/0), default: 0"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +module_param(digimatrix, bool, 0644); +#ifdef LIRC_IT87_DIGIMATRIX +MODULE_PARM_DESC(digimatrix, + "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); +#else +MODULE_PARM_DESC(digimatrix, + "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); +#endif + + +module_param(it87_freq, int, 0444); +#ifdef LIRC_IT87_DIGIMATRIX +MODULE_PARM_DESC(it87_freq, + "Carrier demodulator frequency (kHz), (default: 36)"); +#else +MODULE_PARM_DESC(it87_freq, + "Carrier demodulator frequency (kHz), (default: 38)"); +#endif + +EXPORT_NO_SYMBOLS; + +#endif /* MODULE */ + + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/lirc/lirc_it87/TODO +++ linux-2.6.27/ubuntu/lirc/lirc_it87/TODO @@ -0,0 +1,5 @@ +This is my todo-list for lirc_it87: + +1. enabling/using shared IRQ +2. init/drop IRQ-usage in lirc_open/lirc_close + --- linux-2.6.27.orig/ubuntu/lirc/lirc_it87/Makefile +++ linux-2.6.27/ubuntu/lirc/lirc_it87/Makefile @@ -0,0 +1,3 @@ +EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. + +obj-$(CONFIG_LIRC_IT87) += lirc_it87.o --- linux-2.6.27.orig/ubuntu/aufs/vdir.c +++ linux-2.6.27/ubuntu/aufs/vdir.c @@ -0,0 +1,941 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * virtual or vertical directory + * + * $Id: vdir.c,v 1.11 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include "aufs.h" + +static int calc_size(int namelen) +{ + int sz; + + sz = sizeof(struct au_vdir_de) + namelen; + if (sizeof(ino_t) == sizeof(long)) { + const int mask = sizeof(ino_t) - 1; + if (sz & mask) { + sz += sizeof(ino_t); + sz &= ~mask; + } + } + + AuDebugOn(sz % sizeof(ino_t)); + return sz; +} + +static int set_deblk_end(union au_vdir_deblk_p *p, + union au_vdir_deblk_p *deblk_end) +{ + if (calc_size(0) <= deblk_end->p - p->p) { + p->de->de_str.len = 0; + /* smp_mb(); */ + return 0; + } + return -1; /* error */ +} + +/* returns true or false */ +static int is_deblk_end(union au_vdir_deblk_p *p, + union au_vdir_deblk_p *deblk_end) +{ + if (calc_size(0) <= deblk_end->p - p->p) + return !p->de->de_str.len; + return 1; +} + +static au_vdir_deblk_t *last_deblk(struct au_vdir *vdir) +{ + return vdir->vd_deblk[vdir->vd_nblk - 1]; +} + +void au_nhash_init(struct au_nhash *nhash) +{ + int i; + for (i = 0; i < AuSize_NHASH; i++) + INIT_HLIST_HEAD(nhash->heads + i); +} + +struct au_nhash *au_nhash_new(gfp_t gfp) +{ + struct au_nhash *nhash; + + nhash = kmalloc(sizeof(*nhash), gfp); + if (nhash) { + au_nhash_init(nhash); + return nhash; + } + return ERR_PTR(-ENOMEM); +} + +void au_nhash_del(struct au_nhash *nhash) +{ + au_nhash_fin(nhash); + kfree(nhash); +} + +void au_nhash_move(struct au_nhash *dst, struct au_nhash *src) +{ + int i; + + AuTraceEnter(); + + *dst = *src; + for (i = 0; i < AuSize_NHASH; i++) { + struct hlist_head *h; + h = dst->heads + i; + if (h->first) + h->first->pprev = &h->first; + INIT_HLIST_HEAD(src->heads + i); + } + /* smp_mb(); */ +} + +/* ---------------------------------------------------------------------- */ + +void au_nhash_fin(struct au_nhash *whlist) +{ + int i; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos, *n; + + AuTraceEnter(); + + for (i = 0; i < AuSize_NHASH; i++) { + head = whlist->heads + i; + hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) { + /* hlist_del(pos); */ + kfree(tpos); + } + } +} + +int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, + int limit) +{ + int n, i; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + + LKTRTrace("limit %d\n", limit); + + n = 0; + for (i = 0; i < AuSize_NHASH; i++) { + head = whlist->heads + i; + hlist_for_each_entry(tpos, pos, head, wh_hash) + if (tpos->wh_bindex == btgt && ++n > limit) + return 1; + } + return 0; +} + +static unsigned int au_name_hash(const unsigned char *name, unsigned int len) +{ + return (full_name_hash(name, len) % AuSize_NHASH); +} + +/* returns found(true) or not */ +int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int namelen) +{ + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + struct au_vdir_destr *str; + + LKTRTrace("%.*s\n", namelen, name); + + head = whlist->heads + au_name_hash(name, namelen); + hlist_for_each_entry(tpos, pos, head, wh_hash) { + str = &tpos->wh_str; + LKTRTrace("%.*s\n", str->len, str->name); + if (str->len == namelen && !memcmp(str->name, name, namelen)) + return 1; + } + return 0; +} + +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int namelen, + ino_t ino, unsigned int d_type, aufs_bindex_t bindex, + unsigned char shwh) +{ + int err; + struct au_vdir_destr *str; + struct au_vdir_wh *wh; + + LKTRTrace("%.*s\n", namelen, name); + + err = -ENOMEM; + wh = kmalloc(sizeof(*wh) + namelen, GFP_NOFS); + if (unlikely(!wh)) + goto out; + err = 0; + wh->wh_bindex = bindex; + if (unlikely(shwh)) + au_shwh_init_wh(wh, ino, d_type); + str = &wh->wh_str; + str->len = namelen; + memcpy(str->name, name, namelen); + hlist_add_head(&wh->wh_hash, + whlist->heads + au_name_hash(name, namelen)); + /* smp_mb(); */ + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +void au_vdir_free(struct au_vdir *vdir) +{ + au_vdir_deblk_t **deblk; + + AuTraceEnter(); + + deblk = vdir->vd_deblk; + while (vdir->vd_nblk--) { + kfree(*deblk); + deblk++; + } + kfree(vdir->vd_deblk); + au_cache_free_vdir(vdir); +} + +static int append_deblk(struct au_vdir *vdir) +{ + int err, sz, i; + au_vdir_deblk_t **o; + union au_vdir_deblk_p p, deblk_end; + + AuTraceEnter(); + + err = -ENOMEM; + sz = sizeof(*o) * vdir->vd_nblk; + o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_NOFS); + if (unlikely(!o)) + goto out; + vdir->vd_deblk = o; + p.deblk = kmalloc(sizeof(*p.deblk), GFP_NOFS); + if (p.deblk) { + i = vdir->vd_nblk++; + vdir->vd_deblk[i] = p.deblk; + vdir->vd_last.i = i; + vdir->vd_last.p.p = p.p; + deblk_end.deblk = p.deblk + 1; + err = set_deblk_end(&p, &deblk_end); + AuDebugOn(err); + } + + out: + AuTraceErr(err); + return err; +} + +static struct au_vdir *alloc_vdir(void) +{ + struct au_vdir *vdir; + int err; + + AuTraceEnter(); + + err = -ENOMEM; + vdir = au_cache_alloc_vdir(); + if (unlikely(!vdir)) + goto out; + vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS); + if (unlikely(!vdir->vd_deblk)) + goto out_free; + + vdir->vd_nblk = 0; + vdir->vd_version = 0; + vdir->vd_jiffy = 0; + err = append_deblk(vdir); + if (!err) + return vdir; /* success */ + + kfree(vdir->vd_deblk); + + out_free: + au_cache_free_vdir(vdir); + out: + vdir = ERR_PTR(err); + AuTraceErrPtr(vdir); + return vdir; +} + +static int reinit_vdir(struct au_vdir *vdir) +{ + int err; + union au_vdir_deblk_p p, deblk_end; + + AuTraceEnter(); + + while (vdir->vd_nblk > 1) { + kfree(vdir->vd_deblk[vdir->vd_nblk - 1]); + vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; + vdir->vd_nblk--; + } + p.deblk = vdir->vd_deblk[0]; + deblk_end.deblk = p.deblk + 1; + err = set_deblk_end(&p, &deblk_end); + AuDebugOn(err); + vdir->vd_version = 0; + vdir->vd_jiffy = 0; + vdir->vd_last.i = 0; + vdir->vd_last.p.deblk = vdir->vd_deblk[0]; + /* smp_mb(); */ + return err; +} + +/* ---------------------------------------------------------------------- */ + +static void free_dehlist(struct au_nhash *dehlist) +{ + int i; + struct hlist_head *head; + struct au_vdir_dehstr *tpos; + struct hlist_node *pos, *n; + + AuTraceEnter(); + + for (i = 0; i < AuSize_NHASH; i++) { + head = dehlist->heads + i; + hlist_for_each_entry_safe(tpos, pos, n, head, hash) { + /* hlist_del(pos); */ + au_cache_free_dehstr(tpos); + } + } +} + +/* returns found(true) or not */ +static int test_known(struct au_nhash *delist, char *name, int namelen) +{ + struct hlist_head *head; + struct au_vdir_dehstr *tpos; + struct hlist_node *pos; + struct au_vdir_destr *str; + + LKTRTrace("%.*s\n", namelen, name); + + head = delist->heads + au_name_hash(name, namelen); + hlist_for_each_entry(tpos, pos, head, hash) { + str = tpos->str; + LKTRTrace("%.*s\n", str->len, str->name); + if (str->len == namelen && !memcmp(str->name, name, namelen)) + return 1; + } + return 0; + +} + +static int append_de(struct au_vdir *vdir, char *name, int namelen, ino_t ino, + unsigned int d_type, struct au_nhash *delist) +{ + int err, sz; + union au_vdir_deblk_p p, *room, deblk_end; + struct au_vdir_dehstr *dehstr; + + LKTRTrace("%.*s %d, i%lu, dt%u\n", + namelen, name, namelen, (unsigned long)ino, d_type); + + p.deblk = last_deblk(vdir); + deblk_end.deblk = p.deblk + 1; + room = &vdir->vd_last.p; + AuDebugOn(room->p < p.p || deblk_end.p <= room->p + || !is_deblk_end(room, &deblk_end)); + + sz = calc_size(namelen); + if (unlikely(sz > deblk_end.p - room->p)) { + err = append_deblk(vdir); + if (unlikely(err)) + goto out; + p.deblk = last_deblk(vdir); + deblk_end.deblk = p.deblk + 1; + /* smp_mb(); */ + AuDebugOn(room->p != p.p); + } + + err = -ENOMEM; + dehstr = au_cache_alloc_dehstr(); + if (unlikely(!dehstr)) + goto out; + dehstr->str = &room->de->de_str; + hlist_add_head(&dehstr->hash, + delist->heads + au_name_hash(name, namelen)); + + room->de->de_ino = ino; + room->de->de_type = d_type; + room->de->de_str.len = namelen; + memcpy(room->de->de_str.name, name, namelen); + + err = 0; + room->p += sz; + if (unlikely(set_deblk_end(room, &deblk_end))) + err = append_deblk(vdir); + /* smp_mb(); */ + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + unsigned int d_type, ino_t *ino) +{ + int err; + struct au_xino_entry xinoe; + struct mutex *mtx; + const int isdir = (d_type == DT_DIR); + + /* prevent hardlinks from race condition */ + mtx = NULL; + if (!isdir) { + mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx; + mutex_lock(mtx); + } + err = au_xino_read(sb, bindex, h_ino, &xinoe); + if (unlikely(err)) + goto out; + + if (!xinoe.ino) { + err = -EIO; + xinoe.ino = au_xino_new_ino(sb); + if (unlikely(!xinoe.ino)) + goto out; + +#if 0 /* reserved for future use */ + struct inode *h_inode; + xinoe.h_gen = AuXino_INVALID_HGEN; + h_inode = ilookup(au_sbr_sb(sb, bindex), h_ino); + if (h_inode) { + if (!is_bad_inode(h_inode)) { + xinoe.h_gen = h_inode->i_generation; + WARN_ON(xinoe.h_gen == AuXino_INVALID_HGEN); + } + iput(h_inode); + } +#endif + err = au_xino_write(sb, bindex, h_ino, &xinoe); + if (unlikely(err)) + goto out; + } + + *ino = xinoe.ino; + + out: + if (!isdir) + mutex_unlock(mtx); + AuTraceErr(err); + return err; +} + +static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + unsigned int d_type, ino_t *ino) +{ +#ifdef CONFIG_AUFS_SHWH + return au_ino(sb, bindex, h_ino, d_type, ino); +#else + return 0; +#endif +} + +#define AuFillVdir_CALLED 1 +#define AuFillVdir_SHWH (1 << 1) +#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name) +#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; } +#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; } +#ifndef CONFIG_AUFS_SHWH +#undef AuFillVdir_SHWH +#define AuFillVdir_SHWH 0 +#endif + +struct fillvdir_arg { + struct file *file; + struct au_vdir *vdir; + struct au_nhash *delist; + struct au_nhash *whlist; + aufs_bindex_t bindex; + unsigned int flags; + int err; +}; + +static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset, + u64 h_ino, unsigned int d_type) +{ + struct fillvdir_arg *arg = __arg; + char *name = (void *)__name; + aufs_bindex_t bindex, bend; + struct super_block *sb; + ino_t ino; + + LKTRTrace("%.*s, namelen %d, i%llu, dt%u\n", + namelen, name, namelen, (unsigned long long)h_ino, d_type); + + sb = arg->file->f_dentry->d_sb; + bend = arg->bindex; + arg->err = 0; + au_fset_fillvdir(arg->flags, CALLED); + /* smp_mb(); */ + if (namelen <= AUFS_WH_PFX_LEN + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { + for (bindex = 0; bindex < bend; bindex++) + if (test_known(arg->delist + bindex, name, namelen) + || au_nhash_test_known_wh(arg->whlist + bindex, + name, namelen)) + goto out; /* already exists or whiteouted */ + + ino = 1; /* why does gcc warns? */ + arg->err = au_ino(sb, bend, h_ino, d_type, &ino); + if (!arg->err) + arg->err = append_de(arg->vdir, name, namelen, ino, + d_type, arg->delist + bend); + } else { + name += AUFS_WH_PFX_LEN; + namelen -= AUFS_WH_PFX_LEN; + for (bindex = 0; bindex < bend; bindex++) + if (au_nhash_test_known_wh(arg->whlist + bend, name, + namelen)) + goto out; /* already whiteouted */ + + ino = 1; /* dummy */ + if (unlikely(au_ftest_fillvdir(arg->flags, SHWH))) + arg->err = au_wh_ino(sb, bend, h_ino, d_type, &ino); + if (!arg->err) + arg->err = au_nhash_append_wh + (arg->whlist + bend, name, namelen, ino, d_type, + bend, au_ftest_fillvdir(arg->flags, SHWH)); + } + + out: + if (!arg->err) + arg->vdir->vd_jiffy = jiffies; + /* smp_mb(); */ + AuTraceErr(arg->err); + return arg->err; +} + +static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, + aufs_bindex_t bstart, aufs_bindex_t bend, + struct au_nhash *_whlist, struct au_nhash *_delist) +{ +#ifdef CONFIG_AUFS_SHWH + int err, i; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos, *n; + char *p, *o; + struct au_nhash *whlist, *delist; + struct au_vdir_destr *destr; + aufs_bindex_t bindex; + + AuTraceEnter(); + AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH)); + + err = -ENOMEM; + o = p = __getname(); + if (unlikely(!p)) + goto out; + + err = 0; + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); + p += AUFS_WH_PFX_LEN; + for (bindex = bstart; !err && bindex <= bend; bindex++) { + whlist = _whlist + bindex; + delist = _delist + bindex; + + for (i = 0; i < AuSize_NHASH; i++) { + head = whlist->heads + i; + hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) { + destr = &tpos->wh_str; + memcpy(p, destr->name, destr->len); + err = append_de(vdir, o, + destr->len + AUFS_WH_PFX_LEN, + tpos->wh_ino, tpos->wh_type, + delist); + if (unlikely(err)) + break; + } + } + } + + __putname(o); + + out: + AuTraceErr(err); + return err; +#else + return 0; +#endif +} + +static int au_do_read_vdir(struct fillvdir_arg *arg) +{ + int err; + unsigned int mnt_flags; + loff_t offset; + aufs_bindex_t bend, bindex, bstart; + unsigned char dlgt, shwh; + struct super_block *sb; + struct file *hf; + + AuTraceEnter(); + + err = -ENOMEM; + bend = au_fbend(arg->file); + arg->delist = kmalloc(sizeof(*arg->delist) * (bend + 1), GFP_NOFS); + if (unlikely(!arg->delist)) + goto out; + arg->whlist = kmalloc(sizeof(*arg->whlist) * (bend + 1), GFP_NOFS); + if (unlikely(!arg->whlist)) + goto out_delist; + err = 0; + for (bindex = 0; bindex <= bend; bindex++) { + au_nhash_init(arg->delist + bindex); + au_nhash_init(arg->whlist + bindex); + } + + sb = arg->file->f_dentry->d_sb; + mnt_flags = au_mntflags(sb); + dlgt = !!au_test_dlgt(mnt_flags); + arg->flags = 0; + shwh = 0; + if (unlikely(au_opt_test(mnt_flags, SHWH))) { + shwh = 1; + au_fset_fillvdir(arg->flags, SHWH); + } + bstart = au_fbstart(arg->file); + for (bindex = bstart; !err && bindex <= bend; bindex++) { + hf = au_h_fptr(arg->file, bindex); + if (!hf) + continue; + + offset = vfsub_llseek(hf, 0, SEEK_SET); + err = offset; + if (unlikely(offset)) + break; + arg->bindex = bindex; + do { + arg->err = 0; + au_fclr_fillvdir(arg->flags, CALLED); + /* smp_mb(); */ + err = vfsub_readdir(hf, fillvdir, arg, dlgt); + if (err >= 0) + err = arg->err; + } while (!err && au_ftest_fillvdir(arg->flags, CALLED)); + } + + if (unlikely(!err && shwh)) + err = au_handle_shwh(sb, arg->vdir, bstart, bend, arg->whlist, + arg->delist); + + for (bindex = bstart; bindex <= bend; bindex++) { + free_dehlist(arg->delist + bindex); + au_nhash_fin(arg->whlist + bindex); + } + kfree(arg->whlist); + + out_delist: + kfree(arg->delist); + out: + AuTraceErr(err); + return err; +} + +static int read_vdir(struct file *file, int may_read) +{ + int err; + unsigned long expire; + struct fillvdir_arg arg; + unsigned char do_read; + struct dentry *dentry; + struct inode *inode; + struct au_vdir *vdir, *allocated; + struct super_block *sb; + + dentry = file->f_dentry; + LKTRTrace("%.*s, may %d\n", AuDLNPair(dentry), may_read); + FiMustWriteLock(file); + inode = dentry->d_inode; + IMustLock(inode); + IiMustWriteLock(inode); + AuDebugOn(!S_ISDIR(inode->i_mode)); + + err = 0; + allocated = NULL; + do_read = 0; + sb = inode->i_sb; + expire = au_sbi(sb)->si_rdcache; + vdir = au_ivdir(inode); + if (!vdir) { + AuDebugOn(au_fvdir_cache(file)); + do_read = 1; + vdir = alloc_vdir(); + err = PTR_ERR(vdir); + if (IS_ERR(vdir)) + goto out; + err = 0; + allocated = vdir; + } else if (may_read + && (inode->i_version != vdir->vd_version + || time_after(jiffies, vdir->vd_jiffy + expire))) { + LKTRTrace("iver %llu, vdver %lu, exp %lu\n", + (unsigned long long)inode->i_version, + vdir->vd_version, vdir->vd_jiffy + expire); + do_read = 1; + err = reinit_vdir(vdir); + if (unlikely(err)) + goto out; + } + + if (!do_read) + return 0; /* success */ + + arg.file = file; + arg.vdir = vdir; + err = au_do_read_vdir(&arg); + if (!err) { + /* todo: necessary? */ + /* file->f_pos = 0; */ + vdir->vd_version = inode->i_version; + vdir->vd_last.i = 0; + vdir->vd_last.p.deblk = vdir->vd_deblk[0]; + if (allocated) + au_set_ivdir(inode, allocated); + } else if (allocated) + au_vdir_free(allocated); + + out: + AuTraceErr(err); + return err; +} + +static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) +{ + int err, i, rerr, n; + + AuTraceEnter(); + AuDebugOn(tgt->vd_nblk != 1); + + err = -ENOMEM; + if (tgt->vd_nblk < src->vd_nblk) { + au_vdir_deblk_t **p; + p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk, + sizeof(*p) * src->vd_nblk, GFP_NOFS); + if (unlikely(!p)) + goto out; + tgt->vd_deblk = p; + } + + tgt->vd_nblk = src->vd_nblk; + n = src->vd_nblk; + memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AuSize_DEBLK); + /* tgt->vd_last.i = 0; */ + /* tgt->vd_last.p.deblk = tgt->vd_deblk[0]; */ + tgt->vd_version = src->vd_version; + tgt->vd_jiffy = src->vd_jiffy; + + for (i = 1; i < n; i++) { + tgt->vd_deblk[i] = kmalloc(AuSize_DEBLK, GFP_NOFS); + if (tgt->vd_deblk[i]) + memcpy(tgt->vd_deblk[i], src->vd_deblk[i], + AuSize_DEBLK); + else + goto out; + } + /* smp_mb(); */ + return 0; /* success */ + + out: + rerr = reinit_vdir(tgt); + BUG_ON(rerr); + AuTraceErr(err); + return err; +} + +int au_vdir_init(struct file *file) +{ + int err; + struct dentry *dentry; + struct inode *inode; + struct au_vdir *vdir_cache, *allocated; + + dentry = file->f_dentry; + LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos); + FiMustWriteLock(file); + inode = dentry->d_inode; + IiMustWriteLock(inode); + AuDebugOn(!S_ISDIR(inode->i_mode)); + + err = read_vdir(file, !file->f_pos); + if (unlikely(err)) + goto out; + + allocated = NULL; + vdir_cache = au_fvdir_cache(file); + if (!vdir_cache) { + vdir_cache = alloc_vdir(); + err = PTR_ERR(vdir_cache); + if (IS_ERR(vdir_cache)) + goto out; + allocated = vdir_cache; + } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) { + err = reinit_vdir(vdir_cache); + if (unlikely(err)) + goto out; + } else + return 0; /* success */ + + err = copy_vdir(vdir_cache, au_ivdir(inode)); + if (!err) { + file->f_version = inode->i_version; + if (allocated) + au_set_fvdir_cache(file, allocated); + } else if (allocated) + au_vdir_free(allocated); + + out: + AuTraceErr(err); + return err; +} + +static loff_t calc_offset(struct au_vdir *vdir) +{ + loff_t offset; + union au_vdir_deblk_p p; + + p.deblk = vdir->vd_deblk[vdir->vd_last.i]; + offset = vdir->vd_last.p.p - p.p; + offset += sizeof(*p.deblk) * vdir->vd_last.i; + return offset; +} + +/* returns true or false */ +static int seek_vdir(struct file *file) +{ + int valid, i, n; + struct dentry *dentry; + struct au_vdir *vdir_cache; + loff_t offset; + union au_vdir_deblk_p p, deblk_end; + + dentry = file->f_dentry; + LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos); + vdir_cache = au_fvdir_cache(file); + AuDebugOn(!vdir_cache); + + valid = 1; + offset = calc_offset(vdir_cache); + LKTRTrace("offset %lld\n", offset); + if (file->f_pos == offset) + goto out; + + vdir_cache->vd_last.i = 0; + vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0]; + if (!file->f_pos) + goto out; + + valid = 0; + i = file->f_pos / AuSize_DEBLK; + LKTRTrace("i %d\n", i); + if (i >= vdir_cache->vd_nblk) + goto out; + + n = vdir_cache->vd_nblk; + for (; i < n; i++) { + p.deblk = vdir_cache->vd_deblk[i]; + deblk_end.deblk = p.deblk + 1; + offset = i; + offset *= AuSize_DEBLK; + while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) { + int l; + l = calc_size(p.de->de_str.len); + offset += l; + p.p += l; + } + if (!is_deblk_end(&p, &deblk_end)) { + valid = 1; + vdir_cache->vd_last.i = i; + vdir_cache->vd_last.p = p; + break; + } + } + + out: + /* smp_mb(); */ + AuTraceErr(!valid); + return valid; +} + +int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir) +{ + int err, l; + struct dentry *dentry; + struct au_vdir *vdir_cache; + struct au_vdir_de *de; + union au_vdir_deblk_p deblk_end; + + dentry = file->f_dentry; + LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos); + vdir_cache = au_fvdir_cache(file); + AuDebugOn(!vdir_cache); + + if (!seek_vdir(file)) + return 0; + + while (1) { + deblk_end.deblk + = vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1; + while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) { + de = vdir_cache->vd_last.p.de; + LKTRTrace("%.*s, off%lld, i%lu, dt%d\n", + de->de_str.len, de->de_str.name, + file->f_pos, (unsigned long)de->de_ino, + de->de_type); + err = filldir(dirent, de->de_str.name, de->de_str.len, + file->f_pos, de->de_ino, de->de_type); + if (unlikely(err)) { + AuTraceErr(err); + /* todo: ignore the error caused by udba? */ + /* return err; */ + return 0; + } + + l = calc_size(de->de_str.len); + vdir_cache->vd_last.p.p += l; + file->f_pos += l; + } + if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) { + vdir_cache->vd_last.i++; + vdir_cache->vd_last.p.deblk + = vdir_cache->vd_deblk[vdir_cache->vd_last.i]; + file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk) + * vdir_cache->vd_last.i; + continue; + } + break; + } + + /* smp_mb(); */ + return 0; +} --- linux-2.6.27.orig/ubuntu/aufs/misc.c +++ linux-2.6.27/ubuntu/aufs/misc.c @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * $Id: misc.c,v 1.17 2008/09/08 02:40:48 sfjro Exp $ + */ + +#include "aufs.h" + +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp) +{ + void *q; + + LKTRTrace("p %p, nused %d, sz %d\n", p, nused, new_sz); + AuDebugOn(new_sz <= 0); + if (new_sz <= nused) + return p; + + q = krealloc(p, new_sz, gfp); + if (q) + memset(q + nused, 0, new_sz - nused); + return q; +} + +/* ---------------------------------------------------------------------- */ + +struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst, + struct nameidata *src) +{ + LKTRTrace("src %p\n", src); + + if (src) { + *dst = *src; + dst->flags &= ~LOOKUP_PARENT; + if (sbinfo->si_wbr_create == AuWbrCreate_TDP) { + if ((dst->flags & LOOKUP_CREATE) + && !(dst->intent.open.flags & O_CREAT)) + dst->flags &= ~LOOKUP_CREATE; + } else { + dst->flags &= ~LOOKUP_CREATE; + dst->intent.open.flags &= ~O_CREAT; + } + } else + dst = NULL; + + return dst; +} + +struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd, + struct super_block *sb, aufs_bindex_t bindex) +{ + LKTRTrace("nd %p, b%d\n", nd, bindex); + + if (!nd) + return NULL; + + DiMustAnyLock(nd->path.dentry); + + fake_nd->path.dentry = NULL; + fake_nd->path.mnt = NULL; + + if (bindex <= au_dbend(nd->path.dentry)) + fake_nd->path.dentry = au_h_dptr(nd->path.dentry, bindex); + if (fake_nd->path.dentry) { + fake_nd->path.mnt = au_sbr_mnt(sb, bindex); + AuDebugOn(!fake_nd->path.mnt); + path_get(&fake_nd->path); + } else + fake_nd = ERR_PTR(-ENOENT); + + AuTraceErrPtr(fake_nd); + return fake_nd; +} + +void au_fake_dm_release(struct nameidata *fake_nd) +{ + if (fake_nd) + path_put(&fake_nd->path); +} + +int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode, + struct vfsub_args *vargs, struct nameidata *nd, + struct vfsmount *nfsmnt) +{ + int err; + + LKTRTrace("hi%lu, %.*s, 0%o, nd %d, nfsmnt %d\n", + h_dir->i_ino, AuDLNPair(h_dentry), mode, !!nd, !!nfsmnt); + + err = -ENOSYS; + if (!nfsmnt) + err = vfsub_create(h_dir, h_dentry, mode, /*nd*/NULL, vargs); + else { + struct nameidata fake_nd; + + if (nd) + fake_nd = *nd; + else + memset(&fake_nd, 0, sizeof(fake_nd)); + fake_nd.path.dentry = h_dentry; + fake_nd.path.mnt = nfsmnt; + path_get(&fake_nd.path); + fake_nd.flags = LOOKUP_CREATE; + fake_nd.intent.open.flags = O_CREAT | FMODE_READ; + fake_nd.intent.open.create_mode = mode; + + err = vfsub_create(h_dir, h_dentry, mode, &fake_nd, vargs); + path_put(&fake_nd.path); + } + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +int au_copy_file(struct file *dst, struct file *src, loff_t len, + struct au_hinode *hdir, struct super_block *sb, + struct vfsub_args *vargs) +{ + int err, all_zero, do_kfree; + unsigned long blksize; + char *buf, *zp; + /* reduce stack usage */ + struct iattr *ia; + + LKTRTrace("%.*s, %.*s\n", + AuDLNPair(dst->f_dentry), AuDLNPair(src->f_dentry)); + AuDebugOn(!(dst->f_mode & FMODE_WRITE)); +#ifdef CONFIG_AUFS_DEBUG + { + struct dentry *parent; + parent = dget_parent(dst->f_dentry); + IMustLock(parent->d_inode); + dput(parent); + } +#endif + + err = -ENOMEM; + blksize = dst->f_dentry->d_sb->s_blocksize; + if (!blksize || PAGE_SIZE < blksize) + blksize = PAGE_SIZE; + LKTRTrace("blksize %lu\n", blksize); + /* todo: use ZERO_PAGE(0) */ + BUILD_BUG_ON(KMALLOC_MAX_SIZE < 128 << 10); + do_kfree = 1; + if (blksize <= 64 << 10 && blksize * 2 >= sizeof(*ia)) { + buf = kmalloc(blksize * 2, GFP_NOFS); + if (unlikely(!buf)) + goto out; + zp = buf + blksize; + memset(zp, 0, blksize); + } else { + BUILD_BUG_ON(PAGE_SIZE * 2 < sizeof(*ia)); +#if 0 + buf = (void *)__get_free_pages(GFP_NOFS, 1); + zp = buf + PAGE_SIZE; +#endif + do_kfree = 0; + buf = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!buf)) + goto out; + zp = (void *)get_zeroed_page(GFP_NOFS); + if (unlikely(!zp)) + goto out_buf; + } + +#ifdef CONFIG_AUFS_DEBUG + if (len > (1 << 22)) + AuWarn("copying a large file %lld\n", (long long)len); +#endif + err = 0; + all_zero = 0; + src->f_pos = 0; + dst->f_pos = 0; + while (len) { + size_t sz, rbytes, wbytes; + char *p; + + LKTRTrace("len %lld\n", len); + sz = blksize; + if (len < blksize) + sz = len; + + /* support LSM and notify */ + rbytes = 0; + /* todo: signal_pending? */ + while (!rbytes || err == -EAGAIN || err == -EINTR) { + rbytes = vfsub_read_k(src, buf, sz, &src->f_pos, + vfsub_ftest(vargs->flags, DLGT)); + err = rbytes; + } + if (unlikely(err < 0)) + break; + + all_zero = 0; + if (len >= rbytes && rbytes == blksize) { +#if 1 + all_zero = !memcmp(buf, zp, rbytes); +#else /* reserved for future use */ + unsigned long long *ullp; + size_t n, i; + + all_zero = 1; + ullp = (void *)buf; + n = rbytes / sizeof(*ullp); + i = n; + while (n-- > 0 && all_zero) + all_zero = !*ullp++; + p = (void *)ullp; + i *= sizeof(*ullp); + for (; all_zero && i < rbytes; i++) + all_zero = !*p++; +#endif + } + if (!all_zero) { + wbytes = rbytes; + p = buf; + while (wbytes) { + size_t b; + /* support LSM and notify */ + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_MODIFY, hdir); + b = vfsub_write_k(dst, p, wbytes, &dst->f_pos, + vargs); + err = b; + /* todo: signal_pending? */ + if (unlikely(err == -EAGAIN || err == -EINTR)) + continue; + if (unlikely(err < 0)) + break; + wbytes -= b; + p += b; + } + } else { + loff_t res; + LKTRLabel(hole); + res = vfsub_llseek(dst, rbytes, SEEK_CUR); + err = res; + if (unlikely(res < 0)) + break; + } + len -= rbytes; + err = 0; + } + + /* the last block may be a hole */ + if (unlikely(!err && all_zero)) { + struct dentry *h_d = dst->f_dentry; + struct inode *h_i = h_d->d_inode; + + LKTRLabel(last hole); + do { + /* todo: signal_pending? */ + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_MODIFY, hdir); + err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, vargs); + } while (err == -EAGAIN || err == -EINTR); + if (err == 1) { + ia = (void *)buf; + ia->ia_size = dst->f_pos; + ia->ia_valid = ATTR_SIZE | ATTR_FILE; + ia->ia_file = dst; + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, vfsub_events_notify_change(ia), + hdir); + mutex_lock_nested(&h_i->i_mutex, AuLsc_I_CHILD2); + err = vfsub_notify_change(h_d, ia, vargs); + mutex_unlock(&h_i->i_mutex); + } + } + if (do_kfree) + kfree(buf); + else + free_page((unsigned long)zp); + + out_buf: + if (unlikely(!do_kfree)) + free_page((unsigned long)buf); + out: + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/branch.h +++ linux-2.6.27/ubuntu/aufs/branch.h @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * branch filesystems and xino for them + * + * $Id: branch.h,v 1.12 2008/09/15 03:14:03 sfjro Exp $ + */ + +#ifndef __AUFS_BRANCH_H__ +#define __AUFS_BRANCH_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include "misc.h" +#include "super.h" + +/* ---------------------------------------------------------------------- */ + +/* an entry in a xino file */ +struct au_xino_entry { + ino_t ino; + /* __u32 h_gen; */ /* reserved for future use */ +} __packed; + +/* reserved for future use */ +/* #define AuXino_INVALID_HGEN (-1) */ + +/* a xino file */ +struct au_xino_file { + struct file *xi_file; + struct mutex xi_nondir_mtx; + + /* reserved for future use */ +#if 0 + struct file **xi_file; + + /* array management */ + unsigned long long xi_limit; /* Max xino file size */ + unsigned long long xi_size; /* s_maxbytes */ + + /* truncation */ + unsigned long long xi_upper; /* watermark in bytes */ + unsigned long long xi_step; /* to next watermark in bytes */ + + /* truncation */ + blkcnt_t xi_upper; /* watermark in blocks */ + atomic_t xi_running; +#endif +}; + +/* members for writable branch only */ +enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_TMP, AuBrWh_Last}; +struct au_wbr { + struct au_rwsem wbr_wh_rwsem; + struct dentry *wbr_wh[AuBrWh_Last]; + atomic_t wbr_wh_running; +#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */ +#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */ +#define wbr_tmp wbr_wh[AuBrWh_TMP] /* temporary dir */ + + /* mfs mode */ + unsigned long long wbr_bytes; +}; + +/* protected by superblock rwsem */ +struct au_branch { + struct au_xino_file br_xino; + + aufs_bindex_t br_id; + + int br_perm; + struct vfsmount *br_mnt; + atomic_t br_count; + + struct au_wbr *br_wbr; + +#if 1 /* reserved for future use */ + /* xino truncation */ + blkcnt_t br_xino_upper; /* watermark in blocks */ + atomic_t br_xino_running; +#endif + +#ifdef CONFIG_SYSFS + /* an entry under sysfs per mount-point */ + char br_name[8]; + struct attribute br_attr; +#endif + + au_gen_t br_generation; +}; + +/* ---------------------------------------------------------------------- */ + +/* branch permission and attribute */ +enum { + AuBrPerm_RW, /* writable, linkable wh */ + AuBrPerm_RO, /* readonly, no wh */ + AuBrPerm_RR, /* natively readonly, no wh */ + + AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */ + + AuBrPerm_ROWH, + AuBrPerm_RRWH, /* whiteout-able */ + + AuBrPerm_Last +}; + +static inline int au_br_writable(int brperm) +{ + return (brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH); +} + +static inline int au_br_whable(int brperm) +{ + return (brperm == AuBrPerm_RW + || brperm == AuBrPerm_ROWH + || brperm == AuBrPerm_RRWH); +} + +#if 0 /* reserved for future use */ +static inline int au_br_linkable_wh(int brperm) +{ + return (brperm == AuBrPerm_RW); +} +#endif + +static inline int au_br_hinotifyable(int brperm) +{ +#ifdef CONFIG_AUFS_HINOTIFY + return (brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH); +#else + return 0; +#endif +} + +/* ---------------------------------------------------------------------- */ + +/* branch.c */ +struct au_sbinfo; +void au_br_free(struct au_sbinfo *sinfo); +int au_test_def_rr(struct super_block *h_sb); +int au_br_index(struct super_block *sb, aufs_bindex_t br_id); +struct au_opt_add; +int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount); +struct au_opt_del; +int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount); +struct au_opt_mod; +int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, + int *do_update); + +/* xino.c */ +#define Au_LOFF_MAX ((loff_t)LLONG_MAX) +int au_xib_trunc(struct super_block *sb); +ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size, + loff_t *pos); +ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size, + loff_t *pos); +struct file *au_xino_create(struct super_block *sb, char *fname, int silent); +struct file *au_xino_create2(struct super_block *sb, struct file *base_file, + struct file *copy_src); +ino_t au_xino_new_ino(struct super_block *sb); +int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + ino_t ino); +int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + struct au_xino_entry *xinoe); +int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + struct au_xino_entry *xinoe); +int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino, + struct file *base_file, int do_test); +int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex); + +struct au_opt_xino; +int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount); +void au_xino_clr(struct super_block *sb); +struct file *au_xino_def(struct super_block *sb); + +struct au_opt_xinodir; +#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for future use */ +/* export.c */ +int au_xinodir_br(struct super_block *sb, struct au_branch *br, ino_t hino, + int do_test); +int au_xinodir_set(struct super_block *sb, struct au_opt_xinodir *xinodir, + int remount); +#else +static inline +int au_xinodir_br(struct super_block *sb, struct au_branch *br, ino_t hino, + int do_test) +{ + return 0; +} + +static inline +int au_xinodir_set(struct super_block *sb, struct au_opt_xinodir *xinodir, + int remount) +{ + return 0; +} +#endif + +/* ---------------------------------------------------------------------- */ + +/* todo: memory barrier? */ +static inline int au_br_count(struct au_branch *br) +{ + return atomic_read(&br->br_count); +} + +static inline int au_br_get(struct au_branch *br) +{ + return atomic_inc_return(&br->br_count); +} + +static inline int au_br_put(struct au_branch *br) +{ + return atomic_dec_return(&br->br_count); +} + +static inline au_gen_t au_br_gen(struct au_branch *br) +{ + return br->br_generation; +} + +/* + * test if the @br is readonly or not. + */ +static inline int au_br_rdonly(struct au_branch *br) +{ + return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY) + || !au_br_writable(br->br_perm)) + ? -EROFS : 0; +} + +/* ---------------------------------------------------------------------- */ + +/* Superblock to branch */ +static inline +aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr(sb, bindex)->br_id; +} + +static inline +struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr(sb, bindex)->br_mnt; +} + +static inline +struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr_mnt(sb, bindex)->mnt_sb; +} + +#if 0 /* reserved for future use */ +static inline int au_sbr_count(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_br_count(au_sbr(sb, bindex)); +} + +static inline void au_sbr_get(struct super_block *sb, aufs_bindex_t bindex) +{ + au_br_get(au_sbr(sb, bindex)); +} +#endif + +static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex) +{ + au_br_put(au_sbr(sb, bindex)); +} + +static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr(sb, bindex)->br_perm; +} + +static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_br_whable(au_sbr_perm(sb, bindex)); +} + +static inline int au_test_trunc_xino(struct super_block *sb) +{ + return au_test_tmpfs(sb); +} + +/* temporary support for i#1 in cramfs */ +static inline int au_test_unique_ino(struct dentry *h_dentry, ino_t h_ino) +{ +#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE) + if (unlikely(h_dentry->d_sb->s_magic == CRAMFS_MAGIC)) + return (h_ino != 1); +#endif + return 1; +} + +static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt) +{ + if (!au_test_nfs(h_mnt->mnt_sb)) + return NULL; + return h_mnt; +} + +static inline void au_br_nfs_lockdep_off(struct super_block *sb) +{ + if (au_test_nfs(sb)) + lockdep_off(); +} + +static inline void au_br_nfs_lockdep_on(struct super_block *sb) +{ + /* hoping this condition will be optimized... */ + if (au_test_nfs(sb)) + lockdep_on(); +} + +#ifdef CONFIG_AUFS_BR_NFS +static inline int au_test_unsupported_nfs(struct super_block *h_sb) +{ + return 0; +} + +/* it doesn't mntget() */ +static inline +struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_do_nfsmnt(au_sbr_mnt(sb, bindex)); +} + +#define AuNoNfsBranchMsg "dummy" + +#else +static inline int au_test_unsupported_nfs(struct super_block *h_sb) +{ + return (h_sb->s_magic == NFS_SUPER_MAGIC); +} + +static inline +struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex) +{ + return NULL; +} + +#define AuNoNfsBranchMsg "NFS branch is not supported" \ + ", try some configurations and patches included in aufs source CVS." + +#endif /* CONFIG_AUFS_BR_NFS */ + +/* ---------------------------------------------------------------------- */ + +/* + * br_wh_read_lock, br_wh_write_lock + * br_wh_read_unlock, br_wh_write_unlock, br_wh_downgrade_lock + */ +AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, wbr->wbr_wh_rwsem); + +/* to debug easier, do not make them inlined functions */ +#define WbrWhMustReadLock(wbr) do { \ + /* SiMustAnyLock(sb); */ \ + AuRwMustReadLock(&(wbr)->wbr_wh_rwsem); \ +} while (0) + +#define WbrWhMustWriteLock(wbr) do { \ + /* SiMustAnyLock(sb); */ \ + AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem); \ +} while (0) + +#define WbrWhMustAnyLock(br) do { \ + /* SiMustAnyLock(sb); */ \ + AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem); \ +} while (0) + +#endif /* __KERNEL__ */ +#endif /* __AUFS_BRANCH_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/file.h +++ linux-2.6.27/ubuntu/aufs/file.h @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * file operations + * + * $Id: file.h,v 1.5 2008/06/30 03:53:43 sfjro Exp $ + */ + +#ifndef __AUFS_FILE_H__ +#define __AUFS_FILE_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include "dentry.h" +#include "misc.h" +#include "super.h" + +/* ---------------------------------------------------------------------- */ + +struct au_branch; +struct au_hfile { + struct file *hf_file; + struct au_branch *hf_br; +}; + +struct au_vdir; +struct au_finfo { + atomic_t fi_generation; + + struct au_rwsem fi_rwsem; + struct au_hfile *fi_hfile; + aufs_bindex_t fi_bstart, fi_bend; + + union { + struct vm_operations_struct *fi_h_vm_ops; + struct au_vdir *fi_vdir_cache; + }; +}; + +/* ---------------------------------------------------------------------- */ + +/* file.c */ +extern struct address_space_operations aufs_aop; +unsigned int au_file_roflags(unsigned int flags); +struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, + struct file *file); +int au_do_open(struct inode *inode, struct file *file, + int (*open)(struct file *file, int flags)); +int au_reopen_nondir(struct file *file); +struct au_pin; +int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), + int wlock, int locked); + +/* f_op.c */ +extern struct file_operations aufs_file_fop; +int aufs_flush(struct file *file, fl_owner_t id); + +/* finfo.c */ +struct au_finfo *au_fi(struct file *file); +struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex); +struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex); + +void au_hfput(struct au_hfile *hf); +void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, + struct file *h_file); + +void au_finfo_fin(struct file *file); +int au_finfo_init(struct file *file); + +#ifdef CONFIG_AUFS_ROBR +/* robr.c */ +struct file *au_robr_safe_file(struct vm_area_struct *vma); +void au_robr_reset_file(struct vm_area_struct *vma, struct file *file); +#else +static inline struct file *au_robr_safe_file(struct vm_area_struct *vma) +{ + struct file *file; + + file = vma->vm_file; + if (file->private_data && au_test_aufs(file->f_dentry->d_sb)) + return file; + return NULL; +} + +static inline +void au_robr_reset_file(struct vm_area_struct *vma, struct file *file) +{ + vma->vm_file = file; + /* smp_mb(); */ /* flush vm_file */ +} +#endif /* CONFIG_AUFS_ROBR */ + +/* ---------------------------------------------------------------------- */ + +/* todo: memory barrier? */ +static inline au_gen_t au_figen(struct file *f) +{ + return atomic_read(&au_fi(f)->fi_generation); +} + +static inline int au_test_mmapped(struct file *f) +{ + return !!(au_fi(f)->fi_h_vm_ops); +} + +static inline int au_test_aufs_file(struct file *f) +{ + return !(f->f_dentry->d_inode->i_mode + & (S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK)); +} + +/* ---------------------------------------------------------------------- */ + +#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH) +int au_store_fmode_exec(struct nameidata *nd, struct inode *inode); + +static inline int au_deny_write_access(struct file *h_file) +{ + LKTRTrace("%.*s\n", AuDLNPair(h_file->f_dentry)); + return deny_write_access(h_file); +} + +static inline void au_allow_write_access(struct file *h_file) +{ + allow_write_access(h_file); +} + +#else + +static inline int au_store_fmode_exec(struct nameidata *nd, struct inode *inode) +{ + /* nothing */ + return 0; +} + +static inline int au_deny_write_access(struct file *h_file) +{ + /* nothing */ + return 0; +} + +static inline void au_allow_write_access(struct file *h_file) +{ + /* nothing */ +} +#endif /* CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH */ + +/* ---------------------------------------------------------------------- */ + +/* + * fi_read_lock, fi_write_lock, + * fi_read_unlock, fi_write_unlock, fi_downgrade_lock + */ +AuSimpleRwsemFuncs(fi, struct file *f, au_fi(f)->fi_rwsem); + +/* to debug easier, do not make them inlined functions */ +#define FiMustReadLock(f) do { \ + SiMustAnyLock((f)->f_dentry->d_sb); \ + AuRwMustReadLock(&au_fi(f)->fi_rwsem); \ +} while (0) + +#define FiMustWriteLock(f) do { \ + SiMustAnyLock((f)->f_dentry->d_sb); \ + AuRwMustWriteLock(&au_fi(f)->fi_rwsem); \ +} while (0) + +#define FiMustAnyLock(f) do { \ + SiMustAnyLock((f)->f_dentry->d_sb); \ + AuRwMustAnyLock(&au_fi(f)->fi_rwsem); \ +} while (0) + +#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) + +/* ---------------------------------------------------------------------- */ + +/* todo: hard/soft set? */ +static inline aufs_bindex_t au_fbstart(struct file *file) +{ + FiMustAnyLock(file); + return au_fi(file)->fi_bstart; +} + +static inline aufs_bindex_t au_fbend(struct file *file) +{ + FiMustAnyLock(file); + return au_fi(file)->fi_bend; +} + +static inline struct au_vdir *au_fvdir_cache(struct file *file) +{ + FiMustAnyLock(file); + return au_fi(file)->fi_vdir_cache; +} + +static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex) +{ + FiMustWriteLock(file); + AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex); + au_fi(file)->fi_bstart = bindex; +} + +static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex) +{ + FiMustWriteLock(file); + AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex + || bindex < au_fbstart(file)); + au_fi(file)->fi_bend = bindex; +} + +static inline void au_set_fvdir_cache(struct file *file, + struct au_vdir *vdir_cache) +{ + FiMustWriteLock(file); + AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode) + || (au_fi(file)->fi_vdir_cache && vdir_cache)); + au_fi(file)->fi_vdir_cache = vdir_cache; +} + +static inline void au_update_figen(struct file *file) +{ + atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry)); + /* smp_mb(); */ /* atomic_set */ +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_FILE_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/module.h +++ linux-2.6.27/ubuntu/aufs/module.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * module initialization and module-global + * + * $Id: module.h,v 1.8 2008/08/25 01:50:37 sfjro Exp $ + */ + +#ifndef __AUFS_MODULE_H__ +#define __AUFS_MODULE_H__ + +#ifdef __KERNEL__ + +/* module parameters */ +extern short aufs_nwkq; +extern int sysaufs_brs; + +/* ---------------------------------------------------------------------- */ + +extern char au_esc_chars[]; +extern int au_dir_roflags; + +/* kmem cache */ +enum { + AuCache_DINFO, + AuCache_ICNTNR, + AuCache_FINFO, + AuCache_VDIR, + AuCache_DEHSTR, +#ifdef CONFIG_AUFS_HINOTIFY + AuCache_HINOTIFY, +#endif + AuCache_Last +}; + +extern struct kmem_cache *au_cachep[]; + +#define AuCacheArgs(type, sz) (type), (sz), 0, SLAB_RECLAIM_ACCOUNT, NULL +#define AuCache(type) \ + kmem_cache_create(AuCacheArgs(#type, sizeof(struct type))) + +/* ---------------------------------------------------------------------- */ + +#define AuCacheFuncs(name, index) \ +static inline void *au_cache_alloc_##name(void) \ +{ return kmem_cache_alloc(au_cachep[index], GFP_NOFS); } \ +static inline void au_cache_free_##name(void *p) \ +{ kmem_cache_free(au_cachep[index], p); } + +AuCacheFuncs(dinfo, AuCache_DINFO); +AuCacheFuncs(icntnr, AuCache_ICNTNR); +AuCacheFuncs(finfo, AuCache_FINFO); +AuCacheFuncs(vdir, AuCache_VDIR); +AuCacheFuncs(dehstr, AuCache_DEHSTR); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_MODULE_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/robr.c +++ linux-2.6.27/ubuntu/aufs/robr.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * 'robr', aufs as readonly branch of another aufs + * + * $Id: robr.c,v 1.6 2008/07/21 02:53:51 sfjro Exp $ + */ + +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +int au_test_robr_wh(struct qstr *name, struct dentry *h_parent, + struct qstr *wh_name, int try_sio, struct au_ndx *ndx) +{ + if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) + return au_wh_test(h_parent, wh_name, try_sio, ndx); + return -EPERM; +} + +int au_test_robr_shwh(struct super_block *sb, const struct qstr *name) +{ + return 0; +} + +/* ---------------------------------------------------------------------- */ + +struct au_robr_lvma { + struct list_head list; + struct vm_area_struct *vma; +}; + +struct file *au_robr_safe_file(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct super_block *sb = file->f_dentry->d_sb; + struct au_robr_lvma *lvma, *entry; + struct au_sbinfo *sbinfo; + unsigned char found, warn; + + AuTraceEnter(); + AuDebugOn(!au_test_aufs(sb)); + + warn = 0; + found = 0; + sbinfo = au_sbi(sb); + spin_lock(&sbinfo->si_lvma_lock); + list_for_each_entry(entry, &sbinfo->si_lvma, list) { + found = (entry->vma == vma); + if (unlikely(found)) + break; + } + if (!found) { + lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC); + if (lvma) { + lvma->vma = vma; + list_add(&lvma->list, &sbinfo->si_lvma); + } else { + warn = 1; + file = NULL; + } + } else + file = NULL; + spin_unlock(&sbinfo->si_lvma_lock); + + if (unlikely(warn)) + AuWarn1("no memory for lvma\n"); + return file; +} + +void au_robr_reset_file(struct vm_area_struct *vma, struct file *file) +{ + struct super_block *sb = file->f_dentry->d_sb; + struct au_robr_lvma *entry, *found; + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + AuDebugOn(!au_test_aufs(sb)); + + vma->vm_file = file; + /* smp_mb(); */ /* flush vm_file */ + + found = NULL; + sbinfo = au_sbi(sb); + spin_lock(&sbinfo->si_lvma_lock); + list_for_each_entry(entry, &sbinfo->si_lvma, list) + if (entry->vma == vma) { + found = entry; + break; + } + AuDebugOn(!found); + list_del(&found->list); + spin_unlock(&sbinfo->si_lvma_lock); + kfree(found); +} --- linux-2.6.27.orig/ubuntu/aufs/inode.h +++ linux-2.6.27/ubuntu/aufs/inode.h @@ -0,0 +1,545 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations + * + * $Id: inode.h,v 1.13 2008/09/15 03:14:44 sfjro Exp $ + */ + +#ifndef __AUFS_INODE_H__ +#define __AUFS_INODE_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include "hinode.h" +#include "misc.h" +#include "super.h" + +struct au_hinode; +struct au_vdir; +struct au_iinfo { + atomic_t ii_generation; + struct super_block *ii_hsb1; /* no get/put */ + + struct au_rwsem ii_rwsem; + aufs_bindex_t ii_bstart, ii_bend; + __u32 ii_higen; + struct au_hinode *ii_hinode; + struct au_vdir *ii_vdir; +}; + +struct aufs_icntnr { + struct au_iinfo iinfo; + struct inode vfs_inode; +}; + +struct au_pin1 { + /* input */ + struct dentry *dentry; + unsigned char di_locked, lsc_di, lsc_hi; + /* auto */ + unsigned char do_verify; + + /* output */ + struct dentry *parent; + struct inode *h_dir; +}; + +enum {AuPin_PARENT, AuPin_GPARENT}; +struct au_pin { +#ifdef CONFIG_AUFS_HINOTIFY + struct au_pin1 pin[2]; +#else + struct au_pin1 pin[1]; /* no grand parent */ +#endif +}; + +/* ---------------------------------------------------------------------- */ + +/* inode.c */ +int au_refresh_hinode_self(struct inode *inode); +int au_refresh_hinode(struct inode *inode, struct dentry *dentry); +struct inode *au_new_inode(struct dentry *dentry); +int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, + struct inode *inode); +int au_test_h_perm(struct inode *h_inode, int mask, int dlgt); +int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt); + +/* i_op.c */ +extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop; + +/* au_wr_dir flags */ +#define AuWrDir_ADD_ENTRY 1 +#define AuWrDir_ISDIR (1 << 1) +#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) +#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; } +#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; } + +struct au_wr_dir_args { + aufs_bindex_t force_btgt; + unsigned char flags; +}; +int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, + struct au_wr_dir_args *args); + +void au_pin_init(struct au_pin *args, struct dentry *dentry, int di_locked, + int lsc_di, int lsc_hi, int do_gp); +int au_pin(struct au_pin *args, struct dentry *dentry, aufs_bindex_t bindex, + int di_locked, int do_gp) __must_check; +int au_do_pin(struct au_pin1 *p, struct au_pin1 *gp, const aufs_bindex_t bindex, + const int do_gp) __must_check; +void au_do_unpin(struct au_pin1 *p, struct au_pin1 *gp); + +/* i_op_add.c */ +struct au_ndx; +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir, struct au_ndx *ndx); +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev); +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); +int aufs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd); +int aufs_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry); +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode); + +/* i_op_del.c */ +int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); +int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir, struct au_ndx *ndx); +int aufs_unlink(struct inode *dir, struct dentry *dentry); +int aufs_rmdir(struct inode *dir, struct dentry *dentry); + +/* i_op_ren.c */ +int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry); + +#ifdef CONFIG_AUFS_DLGT +/* dlgt.c */ +int au_security_inode_permission(struct inode *h_inode, int mask, + struct nameidata *fake_nd, int dlgt); +#else +static inline +int au_security_inode_permission(struct inode *h_inode, int mask, + struct nameidata *fake_nd, int dlgt) +{ + return vfsub_security_inode_permission(h_inode, mask, fake_nd); +} +#endif /* CONFIG_AUFS_DLGT */ + +#ifdef CONFIG_AUFS_HIN_OR_FUSE +/* hin_or_fuse.c */ +int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st); +#endif + +#if 0 /* reserved for future use */ +/* xattr.c */ +int aufs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t sz, int flags); +ssize_t aufs_getxattr(struct dentry *dentry, const char *name, void *value, + size_t sz); +ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t sz); +int aufs_removexattr(struct dentry *dentry, const char *name); +#endif + +/* iinfo.c */ +struct au_iinfo *au_ii(struct inode *inode); +struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); +aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex); + +void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex); +void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, + struct dentry *h_wh); +unsigned int au_hi_flags(struct inode *inode, int isdir); + +/* hinode flags */ +#define AuHi_XINO 1 +#define AuHi_NOTIFY (1 << 1) +#define au_ftest_hi(flags, name) ((flags) & AuHi_##name) +#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; } +#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; } +#ifndef CONFIG_AUFS_HINOTIFY +#undef AuHi_NOTIFY +#define AuHi_NOTIFY 0 +#endif + +void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, + struct inode *h_inode, unsigned int flags); + +void au_update_iigen(struct inode *inode); +void au_update_brange(struct inode *inode, int do_put_zero); + +int au_iinfo_init(struct inode *inode); +void au_iinfo_fin(struct inode *inode); + +/* plink.c */ +#ifdef CONFIG_AUFS_DEBUG +void au_plink_list(struct super_block *sb); +#else +static inline void au_plink_list(struct super_block *sb) +{ + /* nothing */ +} +#endif +int au_plink_test(struct super_block *sb, struct inode *inode); +struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex, + struct inode *inode); +void au_plink_append(struct super_block *sb, struct inode *inode, + struct dentry *h_dentry, aufs_bindex_t bindex); +void au_plink_put(struct super_block *sb); +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); + +/* ---------------------------------------------------------------------- */ + +/* lock subclass for iinfo */ +enum { + AuLsc_II_CHILD, /* child first */ + AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */ + AuLsc_II_CHILD3, /* copyup dirs */ + AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ + AuLsc_II_PARENT2, + AuLsc_II_PARENT3, + AuLsc_II_PARENT4, + AuLsc_II_NEW_CHILD, +}; + +/* + * ii_read_lock_child, ii_write_lock_child, + * ii_read_lock_child2, ii_write_lock_child2, + * ii_read_lock_child3, ii_write_lock_child3, + * ii_read_lock_parent, ii_write_lock_parent, + * ii_read_lock_parent2, ii_write_lock_parent2, + * ii_read_lock_parent3, ii_write_lock_parent3, + * ii_read_lock_parent4, ii_write_lock_parent4, + * ii_read_lock_new_child, ii_write_lock_new_child, + */ +#define AuReadLockFunc(name, lsc) \ +static inline void ii_read_lock_##name(struct inode *i) \ +{ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); } + +#define AuWriteLockFunc(name, lsc) \ +static inline void ii_write_lock_##name(struct inode *i) \ +{ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); } + +#define AuRWLockFuncs(name, lsc) \ + AuReadLockFunc(name, lsc) \ + AuWriteLockFunc(name, lsc) + +AuRWLockFuncs(child, CHILD); +AuRWLockFuncs(child2, CHILD2); +AuRWLockFuncs(child3, CHILD3); +AuRWLockFuncs(parent, PARENT); +AuRWLockFuncs(parent2, PARENT2); +AuRWLockFuncs(parent3, PARENT3); +AuRWLockFuncs(parent4, PARENT4); +AuRWLockFuncs(new_child, NEW_CHILD); + +#undef AuReadLockFunc +#undef AuWriteLockFunc +#undef AuRWLockFuncs + +/* + * ii_read_unlock, ii_write_unlock, ii_downgrade_lock + */ +AuSimpleUnlockRwsemFuncs(ii, struct inode *i, au_ii(i)->ii_rwsem); + +/* to debug easier, do not make them inlined functions */ +#define IiMustReadLock(i) do { \ + SiMustAnyLock((i)->i_sb); \ + AuRwMustReadLock(&au_ii(i)->ii_rwsem); \ +} while (0) + +#define IiMustWriteLock(i) do { \ + SiMustAnyLock((i)->i_sb); \ + AuRwMustWriteLock(&au_ii(i)->ii_rwsem); \ +} while (0) + +#define IiMustAnyLock(i) do { \ + SiMustAnyLock((i)->i_sb); \ + AuRwMustAnyLock(&au_ii(i)->ii_rwsem); \ +} while (0) + +#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) + +/* ---------------------------------------------------------------------- */ + +static inline struct inode *au_igrab(struct inode *inode) +{ + if (inode) { + AuDebugOn(!atomic_read(&inode->i_count)); + atomic_inc_return(&inode->i_count); + } + return inode; +} + +/* ---------------------------------------------------------------------- */ + +static inline aufs_bindex_t au_ibstart(struct inode *inode) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_bstart; +} + +static inline aufs_bindex_t au_ibend(struct inode *inode) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_bend; +} + +static inline struct au_vdir *au_ivdir(struct inode *inode) +{ + IiMustAnyLock(inode); + AuDebugOn(!S_ISDIR(inode->i_mode)); + return au_ii(inode)->ii_vdir; +} + +static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) +{ + struct au_hinode *hinode; + IiMustAnyLock(inode); + hinode = au_ii(inode)->ii_hinode + bindex; + return hinode->hi_whdentry; +} + +static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex) +{ + IiMustWriteLock(inode); + AuDebugOn(au_sbend(inode->i_sb) < bindex || bindex < au_ibstart(inode)); + au_ii(inode)->ii_bend = bindex; +} + +static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) +{ + IiMustWriteLock(inode); + AuDebugOn(!S_ISDIR(inode->i_mode) || (au_ii(inode)->ii_vdir && vdir)); + au_ii(inode)->ii_vdir = vdir; +} + +static inline void au_hiput(struct au_hinode *hinode) +{ + au_hin_free(hinode); + dput(hinode->hi_whdentry); + iput(hinode->hi_inode); +} + +static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) +{ + /* todo: this lock check causes some unnecessary locks in callers. */ + IiMustAnyLock(inode); + return au_ii(inode)->ii_hinode + bindex; +} + +/* tiny test for inode number */ +/* tmpfs generation is too rough */ +static inline int au_test_higen(struct inode *inode, struct inode *h_inode) +{ + struct au_iinfo *iinfo; + + IiMustAnyLock(inode); + + iinfo = au_ii(inode); + return !(iinfo->ii_hsb1 == h_inode->i_sb + && iinfo->ii_higen == h_inode->i_generation); +} + +static inline au_gen_t au_iigen(struct inode *inode) +{ + return atomic_read(&au_ii(inode)->ii_generation); +} + +#ifdef CONFIG_AUFS_HINOTIFY +static inline au_gen_t au_iigen_dec(struct inode *inode) +{ + /* AuDbg("i%lu\n", inode->i_ino); */ + return atomic_dec_return(&au_ii(inode)->ii_generation); +} +#endif + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_HINOTIFY +static inline struct au_pin1 *au_pin_gp(struct au_pin *args) +{ + return args->pin + AuPin_GPARENT; +} + +/* hinotify.c */ +void au_unpin_gp(struct au_pin *args); + +#else + +static inline struct au_pin1 *au_pin_gp(struct au_pin *args) +{ + return NULL; +} + +static inline void au_unpin_gp(struct au_pin *args) +{ + /* empty */ +} +#endif /* HINOTIFY */ + +static inline void au_unpin(struct au_pin *args) +{ + au_do_unpin(args->pin + AuPin_PARENT, au_pin_gp(args)); +} + +static inline +struct au_hinode *au_do_pinned_hdir(struct au_pin1 *pin, aufs_bindex_t bindex) +{ + if (pin && pin->parent) + return au_hi(pin->parent->d_inode, bindex); + return NULL; +} + +struct dentry *au_do_pinned_h_parent(struct au_pin1 *pin, aufs_bindex_t bindex); + +static inline struct dentry *au_do_pinned_parent(struct au_pin1 *pin) +{ + if (pin) + return pin->parent; + return NULL; +} + +static inline struct inode *au_do_pinned_h_dir(struct au_pin1 *pin) +{ + if (pin) + return pin->h_dir; + return NULL; +} + +static inline +void au_pin_do_set_dentry(struct au_pin1 *pin, struct dentry *dentry) +{ + if (pin) + pin->dentry = dentry; +} + +static inline +void au_pin_do_set_parent(struct au_pin1 *pin, struct dentry *parent) +{ + if (pin) { + dput(pin->parent); + pin->parent = dget(parent); + } +} + +static inline void au_pin_do_set_h_dir(struct au_pin1 *pin, struct inode *h_dir) +{ + if (pin) { + iput(pin->h_dir); + pin->h_dir = au_igrab(h_dir); + } +} + +static inline +void au_pin_do_set_parent_lflag(struct au_pin1 *pin, unsigned char lflag) +{ + if (pin) + pin->di_locked = lflag; +} + +static inline +struct au_hinode *au_pinned_hdir(struct au_pin *args, aufs_bindex_t bindex) +{ + return au_do_pinned_hdir(args->pin + AuPin_PARENT, bindex); +} + +static inline +struct au_hinode *au_pinned_hgdir(struct au_pin *args, aufs_bindex_t bindex) +{ + return au_do_pinned_hdir(au_pin_gp(args), bindex); +} + +static inline +struct dentry *au_pinned_h_parent(struct au_pin *args, aufs_bindex_t bindex) +{ + return au_do_pinned_h_parent(args->pin + AuPin_PARENT, bindex); +} + +#if 0 /* reserved for future use */ +static inline +struct dentry *au_pinned_h_gparent(struct au_pin *args, aufs_bindex_t bindex) +{ + return au_do_pinned_h_parent(au_pin_gp(args), bindex); +} +#endif + +static inline +struct dentry *au_pinned_parent(struct au_pin *args) +{ + return au_do_pinned_parent(args->pin + AuPin_PARENT); +} + +static inline +struct dentry *au_pinned_gparent(struct au_pin *args) +{ + return au_do_pinned_parent(au_pin_gp(args)); +} + +static inline +struct inode *au_pinned_h_dir(struct au_pin *args) +{ + return au_do_pinned_h_dir(args->pin + AuPin_PARENT); +} + +static inline +struct inode *au_pinned_h_gdir(struct au_pin *args) +{ + return au_do_pinned_h_dir(au_pin_gp(args)); +} + +static inline void au_pin_set_parent(struct au_pin *args, struct dentry *d) +{ + au_pin_do_set_parent(args->pin + AuPin_PARENT, d); +} + +static inline void au_pin_set_gparent(struct au_pin *args, struct dentry *d) +{ + au_pin_do_set_parent(au_pin_gp(args), d); +} + +static inline void au_pin_set_h_dir(struct au_pin *args, struct inode *h_dir) +{ + au_pin_do_set_h_dir(args->pin + AuPin_PARENT, h_dir); +} + +static inline void au_pin_set_h_gdir(struct au_pin *args, struct inode *h_dir) +{ + au_pin_do_set_h_dir(au_pin_gp(args), h_dir); +} + +static inline +void au_pin_set_parent_lflag(struct au_pin *args, unsigned char lflag) +{ + au_pin_do_set_parent_lflag(args->pin + AuPin_PARENT, lflag); +} + +static inline +void au_pin_set_gparent_lflag(struct au_pin *args, unsigned char lflag) +{ + au_pin_do_set_parent_lflag(au_pin_gp(args), lflag); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_INODE_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/vfsub.c +++ linux-2.6.27/ubuntu/aufs/vfsub.c @@ -0,0 +1,719 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for VFS + * + * $Id: vfsub.c,v 1.11 2008/08/04 00:32:35 sfjro Exp $ + */ + +#include +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign, + int dlgt, int force_unlink) +{ + do_vfsub_args_reinit(vargs, ign); + vargs->flags = 0; + if (unlikely(dlgt)) + vfsub_fset(vargs->flags, DLGT); + if (force_unlink) + vfsub_fset(vargs->flags, FORCE_UNLINK); +} + +/* ---------------------------------------------------------------------- */ + +struct file *vfsub_filp_open(const char *path, int oflags, int mode) +{ + struct file *err; + + LKTRTrace("%s\n", path); + + lockdep_off(); + err = filp_open(path, oflags, mode); + lockdep_on(); + if (!IS_ERR(err)) + au_update_fuse_h_inode(err->f_vfsmnt, err->f_dentry); /*ignore*/ + return err; +} + +int vfsub_path_lookup(const char *name, unsigned int flags, + struct nameidata *nd) +{ + int err; + + LKTRTrace("%s\n", name); + + /* lockdep_off(); */ + err = path_lookup(name, flags, nd); + /* lockdep_on(); */ + if (!err) + au_update_fuse_h_inode(nd->path.mnt, nd->path.dentry); + /*ignore*/ + return err; +} + +struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, + int len) +{ + struct dentry *d; + + LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name); + IMustLock(parent->d_inode); + + d = lookup_one_len(name, parent, len); + if (!IS_ERR(d)) + au_update_fuse_h_inode(NULL, d); /*ignore*/ + return d; +} + +#ifdef CONFIG_AUFS_LHASH_PATCH +struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent, + struct nameidata *nd) +{ + struct dentry *d; + + LKTRTrace("%.*s/%.*s, nd %d\n", + AuDLNPair(parent), AuLNPair(name), !!nd); + if (nd) + LKTRTrace("nd{0x%x}\n", nd->flags); + IMustLock(parent->d_inode); + + d = __lookup_hash(name, parent, nd); + if (!IS_ERR(d)) + au_update_fuse_h_inode(NULL, d); /*ignore*/ + return d; +} +#endif + +/* ---------------------------------------------------------------------- */ + +int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + int err; + struct vfsmount *mnt; + + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode); + IMustLock(dir); + + err = vfs_create(dir, dentry, mode, nd); + if (!err) { + mnt = NULL; + if (nd) + mnt = nd->path.mnt; + /* dir inode is locked */ + au_update_fuse_h_inode(mnt, dentry->d_parent); /*ignore*/ + au_update_fuse_h_inode(mnt, dentry); /*ignore*/ + } + return err; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +#define VfsubSymlinkArgs dir, dentry, symname +#else +#define VfsubSymlinkArgs dir, dentry, symname, mode +#endif + +int do_vfsub_symlink(struct inode *dir, struct dentry *dentry, + const char *symname, int mode) +{ + int err; + + LKTRTrace("i%lu, %.*s, %s, 0x%x\n", + dir->i_ino, AuDLNPair(dentry), symname, mode); + IMustLock(dir); + + err = vfs_symlink(dir, dentry, NULL, symname); + if (!err) { + /* dir inode is locked */ + au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ + au_update_fuse_h_inode(NULL, dentry); /*ignore*/ + } + return err; +} + +int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, + dev_t dev) +{ + int err; + + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode); + IMustLock(dir); + + #ifdef CONFIG_VSERVER + err = vfs_mknod(dir, dentry, mode, dev, NULL); + #elif defined(CONFIG_SECURITY_APPARMOR) + err = vfs_mknod(dir, dentry, NULL, mode, dev); + #else + err = vfs_mknod(dir, dentry, mode, dev); + #endif + if (!err) { + /* dir inode is locked */ + au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ + au_update_fuse_h_inode(NULL, dentry); /*ignore*/ + } + return err; +} + +int do_vfsub_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry) +{ + int err; + + LKTRTrace("%.*s, i%lu, %.*s\n", + AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry)); + IMustLock(dir); + + lockdep_off(); + #ifdef CONFIG_VSERVER + err = vfs_link(src_dentry, dir, dentry, NULL); + #elif defined(CONFIG_SECURITY_APPARMOR) + err = vfs_link(src_dentry, NULL, dir, dentry, NULL); + #else + err = vfs_link(src_dentry, dir, dentry); + #endif + + lockdep_on(); + if (!err) { + LKTRTrace("src_i %p, dst_i %p\n", + src_dentry->d_inode, dentry->d_inode); + /* fuse has different memory inode for the same inumber */ + au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/ + /* dir inode is locked */ + au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ + au_update_fuse_h_inode(NULL, dentry); /*ignore*/ + } + return err; +} + +int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry) +{ + int err; + + LKTRTrace("i%lu, %.*s, i%lu, %.*s\n", + src_dir->i_ino, AuDLNPair(src_dentry), + dir->i_ino, AuDLNPair(dentry)); + IMustLock(dir); + IMustLock(src_dir); + + lockdep_off(); + #ifdef CONFIG_SECURITY_APPARMOR + err = vfs_rename(src_dir, src_dentry, NULL, dir, dentry, NULL); + #else + err = vfs_rename(src_dir, src_dentry, dir, dentry); + #endif + lockdep_on(); + if (!err) { + /* dir inode is locked */ + au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ + au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/ + au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/ + } + return err; +} + +int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int err; + + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode); + IMustLock(dir); + + #ifdef CONFIG_VSERVER + err = vfs_mkdir(dir, dentry, mode, NULL); + #elif defined(CONFIG_SECURITY_APPARMOR) + err = vfs_mkdir(dir, dentry, NULL, mode); + #else + err = vfs_mkdir(dir, dentry, mode); + #endif + + if (!err) { + /* dir inode is locked */ + au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ + au_update_fuse_h_inode(NULL, dentry); /*ignore*/ + } + return err; +} + +int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry) +{ + int err; + + LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); + IMustLock(dir); + + lockdep_off(); + #if defined(CONFIG_VSERVER) || defined(CONFIG_SECURITY_APPARMOR) + err = vfs_rmdir(dir, dentry, NULL); + #else + err = vfs_rmdir(dir, dentry); + #endif + + lockdep_on(); + /* dir inode is locked */ + if (!err) + au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ + return err; +} + +int do_vfsub_unlink(struct inode *dir, struct dentry *dentry) +{ + int err; + + LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); + IMustLock(dir); + + /* vfs_unlink() locks inode */ + lockdep_off(); + #if defined(CONFIG_VSERVER) || defined(CONFIG_SECURITY_APPARMOR) + err = vfs_unlink(dir, dentry, NULL); + #else + err = vfs_unlink(dir, dentry); + #endif + + lockdep_on(); + /* dir inode is locked */ + if (!err) + au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ + return err; +} + +/* ---------------------------------------------------------------------- */ + +ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count, + loff_t *ppos) +{ + ssize_t err; + + LKTRTrace("%.*s, cnt %lu, pos %lld\n", + AuDLNPair(file->f_dentry), (unsigned long)count, *ppos); + + /* todo: always off, regardless nfs branch? */ + au_br_nfs_lockdep_off(file->f_vfsmnt->mnt_sb); + err = vfs_read(file, ubuf, count, ppos); + au_br_nfs_lockdep_on(file->f_vfsmnt->mnt_sb); + if (err >= 0) + au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry); + /*ignore*/ + return err; +} + +/* todo: kernel_read()? */ +ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos) +{ + ssize_t err; + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = do_vfsub_read_u(file, (char __user *)kbuf, count, ppos); + set_fs(oldfs); + return err; +} + +ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + ssize_t err; + + LKTRTrace("%.*s, cnt %lu, pos %lld\n", + AuDLNPair(file->f_dentry), (unsigned long)count, *ppos); + + lockdep_off(); + err = vfs_write(file, ubuf, count, ppos); + lockdep_on(); + if (err >= 0) + au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry); + /*ignore*/ + return err; +} + +ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos) +{ + ssize_t err; + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = do_vfsub_write_u(file, (const char __user *)kbuf, count, ppos); + set_fs(oldfs); + return err; +} + +int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg) +{ + int err; + + LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry)); + + lockdep_off(); + err = vfs_readdir(file, filldir, arg); + lockdep_on(); + if (err >= 0) + au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry); + /*ignore*/ + return err; +} + +#ifdef CONFIG_AUFS_SPLICE_PATCH +long do_vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + long err; + + LKTRTrace("%.*s, pos %lld, len %lu, 0x%x\n", + AuDLNPair(in->f_dentry), *ppos, (unsigned long)len, flags); + + lockdep_off(); + err = vfs_splice_to(in, ppos, pipe, len, flags); + lockdep_on(); + if (err >= 0) + au_update_fuse_h_inode(in->f_vfsmnt, in->f_dentry); /*ignore*/ + return err; +} + +long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) +{ + long err; + + LKTRTrace("%.*s, pos %lld, len %lu, 0x%x\n", + AuDLNPair(out->f_dentry), *ppos, (unsigned long)len, flags); + + lockdep_off(); + err = vfs_splice_from(pipe, out, ppos, len, flags); + lockdep_on(); + if (err >= 0) + au_update_fuse_h_inode(out->f_vfsmnt, out->f_dentry); /*ignore*/ + return err; +} +#endif + +/* ---------------------------------------------------------------------- */ + +struct au_vfsub_mkdir_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + int mode; + struct vfsub_args *vargs; +}; + +static void au_call_vfsub_mkdir(void *args) +{ + struct au_vfsub_mkdir_args *a = args; + *a->errp = vfsub_mkdir(a->dir, a->dentry, a->mode, a->vargs); +} + +int vfsub_sio_mkdir(struct au_hinode *hdir, struct dentry *dentry, int mode, + int dlgt) +{ + int err, do_sio, wkq_err; + struct inode *dir = hdir->hi_inode; + struct au_hin_ignore ign; + struct vfsub_args vargs; + + LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); + + vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0); + vfsub_ign_hinode(&vargs, IN_CREATE, hdir); + do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt); + if (!do_sio) + err = vfsub_mkdir(dir, dentry, mode, &vargs); + else { + struct au_vfsub_mkdir_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .mode = mode, + .vargs = &vargs + }; + vfsub_fclr(vargs.flags, DLGT); + wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + } + + AuTraceErr(err); + return err; +} + +struct au_vfsub_rmdir_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + struct vfsub_args *vargs; +}; + +static void au_call_vfsub_rmdir(void *args) +{ + struct au_vfsub_rmdir_args *a = args; + *a->errp = vfsub_rmdir(a->dir, a->dentry, a->vargs); +} + +int vfsub_sio_rmdir(struct au_hinode *hdir, struct dentry *dentry, int dlgt) +{ + int err, do_sio, wkq_err; + struct inode *dir = hdir->hi_inode; + struct au_hin_ignore ign; + struct vfsub_args vargs; + + LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); + + vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0); + vfsub_ign_hinode(&vargs, IN_DELETE, hdir); + do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt); + if (!do_sio) + err = vfsub_rmdir(dir, dentry, &vargs); + else { + struct au_vfsub_rmdir_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .vargs = &vargs + }; + vfsub_fclr(vargs.flags, DLGT); + wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + } + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct notify_change_args { + int *errp; + struct dentry *h_dentry; + struct iattr *ia; + struct vfsub_args *vargs; +}; + +static void call_notify_change(void *args) +{ + struct notify_change_args *a = args; + struct inode *h_inode; + + LKTRTrace("%.*s, ia_valid 0x%x\n", + AuDLNPair(a->h_dentry), a->ia->ia_valid); + h_inode = a->h_dentry->d_inode; + IMustLock(h_inode); + + *a->errp = -EPERM; + if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { + vfsub_ignore(a->vargs); + lockdep_off(); + *a->errp = notify_change(a->h_dentry, NULL, a->ia); + lockdep_on(); + if (!*a->errp) + au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/ + else + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); + } + AuTraceErr(*a->errp); +} + +#ifdef CONFIG_AUFS_DLGT +static void vfsub_notify_change_dlgt(struct notify_change_args *args, + unsigned int flags) +{ + if (!vfsub_ftest(flags, DLGT)) + call_notify_change(args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_notify_change, args, /*dlgt*/1); + if (unlikely(wkq_err)) + *args->errp = wkq_err; + } +} +#else +static void vfsub_notify_change_dlgt(struct notify_change_args *args, + unsigned int flags) +{ + call_notify_change(args); +} +#endif + +int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, + struct vfsub_args *vargs) +{ + int err; + struct notify_change_args args = { + .errp = &err, + .h_dentry = dentry, + .ia = ia, + .vargs = vargs + }; + + vfsub_notify_change_dlgt(&args, vargs->flags); + + AuTraceErr(err); + return err; +} + +int vfsub_sio_notify_change(struct au_hinode *hdir, struct dentry *dentry, + struct iattr *ia) +{ + int err, wkq_err; + struct au_hin_ignore ign; + struct vfsub_args vargs; + __u32 events; + struct notify_change_args args = { + .errp = &err, + .h_dentry = dentry, + .ia = ia, + .vargs = &vargs + }; + + LKTRTrace("%.*s, 0x%x\n", AuDLNPair(dentry), ia->ia_valid); + + vfsub_args_init(&vargs, &ign, /*dlgt*/0, /*force_unlink*/0); + events = vfsub_events_notify_change(ia); + if (events) + vfsub_ign_hinode(&vargs, events, hdir); + wkq_err = au_wkq_wait(call_notify_change, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct unlink_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + struct vfsub_args *vargs; +}; + +static void call_unlink(void *args) +{ + struct unlink_args *a = args; + struct inode *h_inode; + const int stop_sillyrename = (au_test_nfs(a->dentry->d_sb) + && atomic_read(&a->dentry->d_count) == 1); + + LKTRTrace("%.*s, stop_silly %d, cnt %d\n", + AuDLNPair(a->dentry), stop_sillyrename, + atomic_read(&a->dentry->d_count)); + + if (!stop_sillyrename) + dget(a->dentry); + h_inode = a->dentry->d_inode; + if (h_inode) + atomic_inc_return(&h_inode->i_count); + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_unlink(a->dir, a->dentry); + if (unlikely(*a->errp || (a->dentry->d_flags & DCACHE_NFSFS_RENAMED))) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); + if (!stop_sillyrename) + dput(a->dentry); + if (h_inode) + iput(h_inode); + + AuTraceErr(*a->errp); +} + +/* + * @dir: must be locked. + * @dentry: target dentry. + */ +int vfsub_unlink(struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs) +{ + int err; + struct unlink_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT) + && !vfsub_ftest(vargs->flags, FORCE_UNLINK)) + call_unlink(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_unlink, &args, + vfsub_ftest(vargs->flags, DLGT)); + if (unlikely(wkq_err)) + err = wkq_err; + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct statfs_args { + int *errp; + void *arg; + struct kstatfs *buf; +}; + +static void call_statfs(void *args) +{ + struct statfs_args *a = args; + *a->errp = vfs_statfs(a->arg, a->buf); +} + +#ifdef CONFIG_AUFS_DLGT +static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt) +{ + if (!dlgt) + call_statfs(args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_statfs, args, /*dlgt*/1); + if (unlikely(wkq_err)) + *args->errp = wkq_err; + } +} +#else +static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt) +{ + call_statfs(args); +} +#endif + +int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt) +{ + int err; + struct statfs_args args = { + .errp = &err, + .arg = arg, + .buf = buf + }; + + vfsub_statfs_dlgt(&args, dlgt); + + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/opts.h +++ linux-2.6.27/ubuntu/aufs/opts.h @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * mount options/flags + * + * $Id: opts.h,v 1.6 2008/08/17 23:03:27 sfjro Exp $ + */ + +#ifndef __AUFS_OPTS_H__ +#define __AUFS_OPTS_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include "wkq.h" + +/* ---------------------------------------------------------------------- */ +/* mount flags */ + +/* external inode number bitmap and translation table */ +#define AuOpt_XINO 1 +#define AuOpt_XINODIR (1 << 1) +#define AuOpt_TRUNC_XINO (1 << 2) +#define AuOpt_UDBA_NONE (1 << 3) /* users direct branch access */ +#define AuOpt_UDBA_REVAL (1 << 4) +#define AuOpt_UDBA_INOTIFY (1 << 5) +#define AuOpt_SHWH (1 << 6) +#define AuOpt_PLINK (1 << 7) +#define AuOpt_WARN_PERM (1 << 8) +#define AuOpt_DIRPERM1 (1 << 9) +#define AuOpt_DLGT (1 << 10) +#define AuOpt_COO_NONE (1 << 11) /* copyup on open */ +#define AuOpt_COO_LEAF (1 << 12) +#define AuOpt_COO_ALL (1 << 13) +#define AuOpt_ALWAYS_DIROPQ (1 << 14) +#define AuOpt_REFROF (1 << 15) +#define AuOpt_VERBOSE (1 << 16) + +#if 1 /* ndef CONFIG_AUFS_EXPORT */ /* reserved for future use */ +#undef AuOpt_XINODIR +#define AuOpt_XINODIR 0 +#endif +#ifndef CONFIG_AUFS_HINOTIFY +#undef AuOpt_UDBA_INOTIFY +#define AuOpt_UDBA_INOTIFY 0 +#endif +#ifndef CONFIG_AUFS_SHWH +#undef AuOpt_SHWH +#define AuOpt_SHWH 0 +#endif +#ifndef CONFIG_AUFS_DLGT +#undef AuOpt_DIRPERM1 +#define AuOpt_DIRPERM1 0 +#undef AuOpt_DLGT +#define AuOpt_DLGT 0 +#endif + +/* policies to select one among multiple writable branches */ +enum { + AuWbrCreate_TDP, /* top down parent */ + AuWbrCreate_RR, /* round robin */ + AuWbrCreate_MFS, /* most free space */ + AuWbrCreate_MFSV, /* mfs with seconds */ + AuWbrCreate_MFSRR, /* mfs then rr */ + AuWbrCreate_MFSRRV, /* mfs then rr with seconds */ + AuWbrCreate_PMFS, /* parent and mfs */ + AuWbrCreate_PMFSV, /* parent and mfs with seconds */ + + AuWbrCreate_Def = AuWbrCreate_TDP +}; + +enum { + AuWbrCopyup_TDP, /* top down parent */ + AuWbrCopyup_BUP, /* bottom up parent */ + AuWbrCopyup_BU, /* bottom up */ + + AuWbrCopyup_Def = AuWbrCopyup_TDP +}; + +#define AuOptMask_COO (AuOpt_COO_NONE \ + | AuOpt_COO_LEAF \ + | AuOpt_COO_ALL) +#define AuOptMask_UDBA (AuOpt_UDBA_NONE \ + | AuOpt_UDBA_REVAL \ + | AuOpt_UDBA_INOTIFY) + +#ifdef CONFIG_AUFS_COMPAT +#define AuOpt_DefExtra1 AuOpt_ALWAYS_DIROPQ +#else +#define AuOpt_DefExtra1 0 +#endif + +#define AuOpt_Def (AuOpt_XINO \ + | AuOpt_UDBA_REVAL \ + | AuOpt_WARN_PERM \ + | AuOpt_COO_NONE \ + | AuOpt_PLINK \ + | AuOpt_DefExtra1) + +/* ---------------------------------------------------------------------- */ + +struct au_opt_add { + aufs_bindex_t bindex; + char *path; + int perm; + struct nameidata nd; +}; + +struct au_opt_del { + char *path; + struct dentry *h_root; +}; + +struct au_opt_mod { + char *path; + int perm; + struct dentry *h_root; +}; + +struct au_opt_xino { + char *path; + struct file *file; +}; + +struct au_opt_xinodir { + char *name; + struct path path; +}; + +struct au_opt_xino_itrunc { + aufs_bindex_t bindex; +}; + +struct au_opt_xino_trunc_v { + unsigned long long upper; + int step; +}; + +struct au_opt_wbr_create { + int wbr_create; + int mfs_second; + unsigned long long mfsrr_watermark; +}; + +struct au_opt { + int type; + union { + struct au_opt_xino xino; + struct au_opt_xinodir xinodir; + struct au_opt_xino_itrunc xino_itrunc; + struct au_opt_add add; + struct au_opt_del del; + struct au_opt_mod mod; + int dirwh; + int rdcache; + int deblk; + int nhash; + int udba; + int coo; + struct au_opt_wbr_create wbr_create; + int wbr_copyup; + }; +}; + +/* opts flags */ +#define AuOpts_REMOUNT 1 +#define AuOpts_REFRESH_DIR (1 << 1) +#define AuOpts_REFRESH_NONDIR (1 << 2) +#define AuOpts_TRUNC_XIB (1 << 3) +#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) +#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; } +#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; } + +struct au_opts { + struct au_opt *opt; + int max_opt; + + unsigned int given_udba; + unsigned int flags; +}; + +/* ---------------------------------------------------------------------- */ + +const char *au_optstr_br_perm(int brperm); +const char *au_optstr_udba(int udba); +const char *au_optstr_coo(int coo); +const char *au_optstr_wbr_copyup(int wbr_copyup); +const char *au_optstr_wbr_create(int wbr_create); + +void au_opts_free(struct au_opts *opts); +int au_opts_parse(struct super_block *sb, unsigned long flags, char *str, + struct au_opts *opts); +int au_opts_mount(struct super_block *sb, struct au_opts *opts); +int au_opts_remount(struct super_block *sb, struct au_opts *opts); + +/* ---------------------------------------------------------------------- */ + +#define au_opt_test(flags, name) (flags & AuOpt_##name) + +static inline int au_opt_test_xino(unsigned int flags) +{ + return (flags & (AuOpt_XINO | AuOpt_XINODIR)); +} + +#define au_opt_set(flags, name) do { \ + BUILD_BUG_ON(AuOpt_##name & (AuOptMask_COO | AuOptMask_UDBA)); \ + ((flags) |= AuOpt_##name); \ +} while (0) + +#define au_opt_set_coo(flags, name) do { \ + (flags) &= ~AuOptMask_COO; \ + ((flags) |= AuOpt_##name); \ +} while (0) + +#define au_opt_set_udba(flags, name) do { \ + (flags) &= ~AuOptMask_UDBA; \ + ((flags) |= AuOpt_##name); \ +} while (0) + +#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); } + +static inline int au_test_dlgt(unsigned int flags) +{ + return (au_opt_test(flags, DLGT) && !au_test_wkq(current)); +} + +static inline int au_test_dirperm1(unsigned int flags) +{ + return (au_opt_test(flags, DIRPERM1) && !au_test_wkq(current)); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_OPTS_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/wbr_policy.c +++ linux-2.6.27/ubuntu/aufs/wbr_policy.c @@ -0,0 +1,699 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * policies for selecting one among multiple writable branches + * + * $Id: wbr_policy.c,v 1.12 2008/09/01 02:55:35 sfjro Exp $ + */ + +#include +#include "aufs.h" + +static int au_cpdown_attr(struct au_hinode *hdir, struct dentry *h_dst, + struct dentry *h_src) +{ + int err, sbits; + struct iattr ia; + struct inode *h_idst, *h_isrc; + + LKTRTrace("%.*s\n", AuDLNPair(h_dst)); + h_idst = h_dst->d_inode; + /* todo? IMustLock(h_idst); */ + h_isrc = h_src->d_inode; + /* todo? IMustLock(h_isrc); */ + + ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID; + ia.ia_mode = h_isrc->i_mode; + ia.ia_uid = h_isrc->i_uid; + ia.ia_gid = h_isrc->i_gid; + sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); + + err = vfsub_sio_notify_change(hdir, h_dst, &ia); + + /* is this nfs only? */ + if (!err && sbits && au_test_nfs(h_dst->d_sb)) { + ia.ia_valid = ATTR_FORCE | ATTR_MODE; + ia.ia_mode = h_isrc->i_mode; + err = vfsub_sio_notify_change(hdir, h_dst, &ia); + } + + /* todo: necessary? */ + if (!err) + h_idst->i_flags = h_isrc->i_flags; + + AuTraceErr(err); + return err; +} + +struct au_cpdown_dir_args { + struct dentry *parent; + unsigned int parent_opq; /* bit-flags */ +}; + +static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent, void *arg) +{ + int err, rerr; + struct au_cpdown_dir_args *args = arg; + aufs_bindex_t bend, bopq, bstart; + unsigned char parent_opq, whed, dlgt, do_opq, made_dir, diropq; + struct dentry *h_dentry, *opq_dentry, *wh_dentry, *parent; + struct inode *h_dir, *h_inode, *inode, *dir; + + LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst); + bstart = au_dbstart(dentry); + AuDebugOn(bstart <= bdst + && bdst <= au_dbend(dentry) + && au_h_dptr(dentry, bdst)); + AuDebugOn(!h_parent); + /* todo: safe? */ + parent = dget_parent(dentry); + dir = parent->d_inode; + dput(parent); + h_dir = h_parent->d_inode; + AuDebugOn(!h_dir); + AuDebugOn(h_dir != au_h_iptr(dir, bdst)); + IMustLock(h_dir); + + err = au_lkup_neg(dentry, bdst); + if (unlikely(err < 0)) + goto out; + h_dentry = au_h_dptr(dentry, bdst); + dlgt = !!au_test_dlgt(au_mntflags(dentry->d_sb)); + err = vfsub_sio_mkdir(au_hi(dir, bdst), h_dentry, S_IRWXU | S_IRUGO | S_IXUGO, + dlgt); + if (unlikely(err)) + goto out_put; + + made_dir = 1; + bend = au_dbend(dentry); + bopq = au_dbdiropq(dentry); + whed = (au_dbwh(dentry) == bdst); + if (!args->parent_opq) + args->parent_opq |= (bopq <= bdst); + parent_opq = (args->parent_opq && args->parent == dentry); + do_opq = 0; + diropq = 0; + h_inode = h_dentry->d_inode; + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + if (whed || (parent_opq && do_opq)) { + opq_dentry = au_diropq_create(dentry, bdst, dlgt); + err = PTR_ERR(opq_dentry); + if (IS_ERR(opq_dentry)) { + mutex_unlock(&h_inode->i_mutex); + goto out_dir; + } + dput(opq_dentry); + diropq = 1; + } + + err = au_cpdown_attr(au_hi(dir, bdst), h_dentry, au_h_dptr(dentry, bstart)); + mutex_unlock(&h_inode->i_mutex); + if (unlikely(err)) + goto out_opq; + + wh_dentry = NULL; + if (whed) { + wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, /*ndx*/NULL); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out_opq; + err = 0; + if (wh_dentry->d_inode) + err = au_wh_unlink_dentry(au_hi(dir, bdst), wh_dentry, + dentry, dlgt); + dput(wh_dentry); + if (unlikely(err)) + goto out_opq; + } + + inode = dentry->d_inode; + if (au_ibend(inode) < bdst) + au_set_ibend(inode, bdst); + au_set_h_iptr(inode, bdst, au_igrab(h_inode), au_hi_flags(inode, 1)); + goto out; /* success */ + + /* revert */ + out_opq: + if (diropq) { + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + rerr = au_diropq_remove(dentry, bdst, dlgt); + mutex_unlock(&h_inode->i_mutex); + if (unlikely(rerr)) { + AuIOErr("failed removing diropq for %.*s b%d (%d)\n", + AuDLNPair(dentry), bdst, rerr); + err = -EIO; + goto out; + } + } + out_dir: + if (made_dir) { + rerr = vfsub_sio_rmdir(au_hi(dir, bdst), h_dentry, dlgt); + if (unlikely(rerr)) { + AuIOErr("failed removing %.*s b%d (%d)\n", + AuDLNPair(dentry), bdst, rerr); + err = -EIO; + } + } + out_put: + au_set_h_dptr(dentry, bdst, NULL); + if (au_dbend(dentry) == bdst) + au_update_dbend(dentry); + out: + AuTraceErr(err); + return err; +} + +int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) +{ + int err; + struct au_cpdown_dir_args args = { + .parent = dget_parent(dentry), + .parent_opq = 0 + }; + + LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst); + + err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args); + dput(args.parent); + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* policies for create */ + +static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) +{ + for (; bindex >= 0; bindex--) + if (!au_br_rdonly(au_sbr(sb, bindex))) + return bindex; + return -EROFS; +} + +/* top down parent */ +static int au_wbr_create_tdp(struct dentry *dentry, int isdir) +{ + int err; + struct super_block *sb; + aufs_bindex_t bstart, bindex; + unsigned char dirperm1; + struct dentry *parent, *h_parent; + struct inode *h_dir; + + LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir); + + sb = dentry->d_sb; + dirperm1 = !!au_test_dirperm1(au_mntflags(sb)); + bstart = au_dbstart(dentry); + AuDebugOn(bstart < 0); + err = bstart; + /* todo: can 'err' be an illegal? */ + if (/* err >= 0 && */ !au_br_rdonly(au_sbr(sb, bstart))) + goto out; + + err = -EROFS; + parent = dget_parent(dentry); + for (bindex = au_dbstart(parent); bindex < bstart; bindex++) { + h_parent = au_h_dptr(parent, bindex); + if (!h_parent) + continue; + h_dir = h_parent->d_inode; + if (!h_dir) + continue; + + if (!au_br_rdonly(au_sbr(sb, bindex)) + && (!dirperm1 + || au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC, + /*dlgt*/0))) { + err = bindex; + break; + } + } + dput(parent); + + /* bottom up here */ + if (unlikely(err < 0)) + err = au_wbr_bu(sb, bstart - 1); + + out: + LKTRTrace("b%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* an exception for the policy other than tdp */ +static int au_wbr_create_exp(struct dentry *dentry) +{ + int err; + struct dentry *parent; + aufs_bindex_t bwh, bdiropq; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + err = -1; + bwh = au_dbwh(dentry); + parent = dget_parent(dentry); + bdiropq = au_dbdiropq(parent); + if (bwh >= 0) { + if (bdiropq >= 0) + err = min(bdiropq, bwh); + else + err = bwh; + LKTRTrace("%d\n", err); + } else if (bdiropq >= 0) { + err = bdiropq; + LKTRTrace("%d\n", err); + } + dput(parent); + + if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err))) + err = -1; + + LKTRTrace("%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* round robin */ +static int au_wbr_create_init_rr(struct super_block *sb) +{ + int err; + + err = au_wbr_bu(sb, au_sbend(sb)); + atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */ + + LKTRTrace("b%d\n", err); + return err; +} + +static int au_wbr_create_rr(struct dentry *dentry, int isdir) +{ + int err, nbr; + struct super_block *sb; + atomic_t *next; + unsigned int u; + aufs_bindex_t bindex, bend; + + LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir); + + sb = dentry->d_sb; + next = NULL; + err = au_wbr_create_exp(dentry); + if (err >= 0) + goto out; + + next = &au_sbi(sb)->si_wbr_rr_next; + bend = au_sbend(sb); + nbr = bend + 1; + for (bindex = 0; bindex <= bend; bindex++) { + if (!isdir) { + err = atomic_dec_return(next) + 1; + /* modulo for 0 is meaningless */ + if (unlikely(!err)) + err = atomic_dec_return(next) + 1; + } else + err = atomic_read(next); + LKTRTrace("%d\n", err); + u = err; + err = u % nbr; + LKTRTrace("%d\n", err); + if (!au_br_rdonly(au_sbr(sb, err))) + break; + err = -EROFS; + } + + out: + LKTRTrace("%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* most free space */ +static void *au_wbr_statfs_arg(struct au_branch *br, struct super_block *sb, + aufs_bindex_t bindex) +{ + struct super_block *h_sb; + + h_sb = br->br_mnt->mnt_sb; + + if (!au_test_nfs(h_sb)) + return h_sb->s_root; + + /* sigh,,, why nfs s_root has wrong inode? */ + return au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry; +} + +static void au_mfs(struct dentry *dentry) +{ + struct super_block *sb; + aufs_bindex_t bindex, bend; + unsigned char dlgt; + int err; + struct kstatfs st; + unsigned long long b, bavail; + void *arg; + struct au_branch *br; + struct au_wbr_mfs *mfs; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + bavail = 0; + sb = dentry->d_sb; + mfs = &au_sbi(sb)->si_wbr_mfs; + mfs->mfs_bindex = -EROFS; + mfs->mfsrr_bytes = 0; + dlgt = !!au_test_dlgt(au_mntflags(sb)); + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + if (au_br_rdonly(br)) + continue; + AuDebugOn(!br->br_wbr); + arg = au_wbr_statfs_arg(br, sb, bindex); + if (!arg) + continue; + + err = vfsub_statfs(arg, &st, dlgt); + LKTRTrace("b%d, %d, %llu\n", + bindex, err, (unsigned long long)st.f_bavail); + if (unlikely(err)) { + AuWarn1("failed statfs, b%d, %d\n", bindex, err); + continue; + } + + /* when the available size is equal, select lower one */ + b = st.f_bavail * st.f_bsize; + br->br_wbr->wbr_bytes = b; + if (b >= bavail) { + bavail = b; + mfs->mfs_bindex = bindex; + mfs->mfs_jiffy = jiffies; + } + } + + mfs->mfsrr_bytes = bavail; + LKTRTrace("b%d\n", mfs->mfs_bindex); +} + +static int au_wbr_create_mfs(struct dentry *dentry, int isdir) +{ + int err; + struct super_block *sb; + struct au_wbr_mfs *mfs; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + sb = dentry->d_sb; + err = au_wbr_create_exp(dentry); + if (err >= 0) + goto out; + + mfs = &au_sbi(sb)->si_wbr_mfs; + mutex_lock(&mfs->mfs_lock); + if (unlikely(time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) + || mfs->mfs_bindex < 0 + || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))) + au_mfs(dentry); + mutex_unlock(&mfs->mfs_lock); + err = mfs->mfs_bindex; + + out: + LKTRTrace("b%d\n", err); + return err; +} + +static int au_wbr_create_init_mfs(struct super_block *sb) +{ + struct au_wbr_mfs *mfs; + + mfs = &au_sbi(sb)->si_wbr_mfs; + LKTRTrace("expire %lu\n", mfs->mfs_expire); + + mutex_init(&mfs->mfs_lock); + mfs->mfs_jiffy = 0; + mfs->mfs_bindex = -EROFS; + + return 0; +} + +static int au_wbr_create_fin_mfs(struct super_block *sb) +{ + AuTraceEnter(); + mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +/* most free space and then round robin */ +static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir) +{ + int err; + struct au_wbr_mfs *mfs; + + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir); + + err = au_wbr_create_mfs(dentry, isdir); + if (err >= 0) { + mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs; + LKTRTrace("%llu bytes, %llu wmark\n", + mfs->mfsrr_bytes, mfs->mfsrr_watermark); + if (unlikely(mfs->mfsrr_bytes < mfs->mfsrr_watermark)) + err = au_wbr_create_rr(dentry, isdir); + } + + LKTRTrace("b%d\n", err); + return err; +} + +static int au_wbr_create_init_mfsrr(struct super_block *sb) +{ + int err; + + au_wbr_create_init_mfs(sb); /* ignore */ + err = au_wbr_create_init_rr(sb); + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* top down parent and most free space */ +static int au_wbr_create_pmfs(struct dentry *dentry, int isdir) +{ + int err, e2; + struct super_block *sb; + struct dentry *parent, *h_parent; + aufs_bindex_t bindex, bstart, bend; + unsigned char dirperm1; + struct au_branch *br; + unsigned long long b; + struct inode *h_dir; + + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir); + + err = au_wbr_create_tdp(dentry, isdir); + if (unlikely(err < 0)) + goto out; + parent = dget_parent(dentry); + bstart = au_dbstart(parent); + bend = au_dbtaildir(parent); + if (bstart == bend) + goto out_parent; /* success */ + + e2 = au_wbr_create_mfs(dentry, isdir); + if (e2 < 0) + goto out_parent; /* success */ + + /* when the available size is equal, select upper one */ + sb = dentry->d_sb; + br = au_sbr(sb, err); + AuDebugOn(!br->br_wbr); + dirperm1 = !!au_test_dirperm1(au_mntflags(sb)); + b = br->br_wbr->wbr_bytes; + LKTRTrace("b%d, %llu\n", err, b); + + if (unlikely(dirperm1)) { + for (bindex = bstart; bindex <= bend; bindex++) { + h_parent = au_h_dptr(parent, bindex); + if (!h_parent) + continue; + h_dir = h_parent->d_inode; + if (!h_dir) + continue; + + br = au_sbr(sb, bindex); + if (!au_br_rdonly(br) + && au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC, + /*dlgt*/0) + && br->br_wbr->wbr_bytes > b) { + b = br->br_wbr->wbr_bytes; + err = bindex; + LKTRTrace("b%d, %llu\n", err, b); + } + } + if (err >= 0) + goto out_parent; + } + for (bindex = bstart; bindex <= bend; bindex++) { + h_parent = au_h_dptr(parent, bindex); + if (!h_parent || !h_parent->d_inode) + continue; + + br = au_sbr(sb, bindex); + if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) { + b = br->br_wbr->wbr_bytes; + err = bindex; + LKTRTrace("b%d, %llu\n", err, b); + } + } + + out_parent: + dput(parent); + out: + LKTRTrace("b%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* policies for copyup */ + +/* top down parent */ +static int au_wbr_copyup_tdp(struct dentry *dentry) +{ + return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0); +} + +/* bottom up parent */ +static int au_wbr_copyup_bup(struct dentry *dentry) +{ + int err; + struct dentry *parent, *h_parent; + aufs_bindex_t bindex, bstart; + unsigned char dirperm1; + struct super_block *sb; + struct inode *h_dir; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + err = -EROFS; + sb = dentry->d_sb; + dirperm1 = !!au_test_dirperm1(au_mntflags(sb)); + parent = dget_parent(dentry); + bstart = au_dbstart(parent); + for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) { + h_parent = au_h_dptr(parent, bindex); + if (!h_parent) + continue; + h_dir = h_parent->d_inode; + if (!h_dir) + continue; + + if (!au_br_rdonly(au_sbr(sb, bindex)) + && (!dirperm1 + || au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC, + /*dlgt*/0))) { + err = bindex; + break; + } + } + dput(parent); + + /* bottom up here */ + if (unlikely(err < 0)) + err = au_wbr_bu(sb, bstart - 1); + + LKTRTrace("b%d\n", err); + return err; +} + +/* bottom up */ +static int au_wbr_copyup_bu(struct dentry *dentry) +{ + int err; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry)); + + LKTRTrace("b%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { + [AuWbrCopyup_TDP] = { + .copyup = au_wbr_copyup_tdp + }, + [AuWbrCopyup_BUP] = { + .copyup = au_wbr_copyup_bup + }, + [AuWbrCopyup_BU] = { + .copyup = au_wbr_copyup_bu + } +}; + +struct au_wbr_create_operations au_wbr_create_ops[] = { + [AuWbrCreate_TDP] = { + .create = au_wbr_create_tdp + }, + [AuWbrCreate_RR] = { + .create = au_wbr_create_rr, + .init = au_wbr_create_init_rr + }, + [AuWbrCreate_MFS] = { + .create = au_wbr_create_mfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_MFSV] = { + .create = au_wbr_create_mfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_MFSRR] = { + .create = au_wbr_create_mfsrr, + .init = au_wbr_create_init_mfsrr, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_MFSRRV] = { + .create = au_wbr_create_mfsrr, + .init = au_wbr_create_init_mfsrr, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_PMFS] = { + .create = au_wbr_create_pmfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_PMFSV] = { + .create = au_wbr_create_pmfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + } +}; --- linux-2.6.27.orig/ubuntu/aufs/module.c +++ linux-2.6.27/ubuntu/aufs/module.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * module global variables and operations + * + * $Id: module.c,v 1.10 2008/08/25 01:50:37 sfjro Exp $ + */ + +#include +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +/* + * aufs caches + */ +struct kmem_cache *au_cachep[AuCache_Last]; +static int __init create_cache(void) +{ + au_cachep[AuCache_DINFO] = AuCache(au_dinfo); + if (au_cachep[AuCache_DINFO]) + au_cachep[AuCache_ICNTNR] = AuCache(aufs_icntnr); + if (au_cachep[AuCache_ICNTNR]) + au_cachep[AuCache_FINFO] = AuCache(au_finfo); + if (au_cachep[AuCache_FINFO]) + au_cachep[AuCache_VDIR] = AuCache(au_vdir); + if (au_cachep[AuCache_VDIR]) + au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); + if (au_cachep[AuCache_DEHSTR]) + return 0; + + return -ENOMEM; +} + +static void destroy_cache(void) +{ + int i; + for (i = 0; i < AuCache_Last; i++) + if (au_cachep[i]) { + kmem_cache_destroy(au_cachep[i]); + au_cachep[i] = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */ +int au_dir_roflags; + +/* + * functions for module interface. + */ +MODULE_LICENSE("GPL"); +/* MODULE_LICENSE("GPL v2"); */ +MODULE_AUTHOR("Junjiro Okajima"); +MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs"); +MODULE_VERSION(AUFS_VERSION); + +/* it should be 'byte', but param_set_byte() prints it by "%c" */ +short aufs_nwkq = AUFS_NWKQ_DEF; +MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME); +module_param_named(nwkq, aufs_nwkq, short, S_IRUGO); + +int sysaufs_brs; +MODULE_PARM_DESC(brs, "use /fs/aufs/si_*/brN"); +module_param_named(brs, sysaufs_brs, int, S_IRUGO); + +/* ---------------------------------------------------------------------- */ + +static int __init aufs_init(void) +{ + int err, i; + char *p; + + au_debug_init(); +#ifdef CONFIG_AUFS_INO_T_64 + BUILD_BUG_ON(sizeof(ino_t) != sizeof(long long)); +#else + BUILD_BUG_ON(sizeof(ino_t) != sizeof(int)); +#endif + + p = au_esc_chars; + for (i = 1; i <= ' '; i++) + *p++ = i; + *p++ = '\\'; + *p++ = '\x7f'; + *p = 0; + + au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); + + err = -EINVAL; + if (unlikely(aufs_nwkq <= 0)) + goto out; + + err = sysaufs_init(); + if (unlikely(err)) + goto out; + err = au_wkq_init(); + if (unlikely(err)) + goto out_sysaufs; + err = au_inotify_init(); + if (unlikely(err)) + goto out_wkq; + err = au_sysrq_init(); + if (unlikely(err)) + goto out_inotify; + + err = create_cache(); + if (unlikely(err)) + goto out_sysrq; + + err = register_filesystem(&aufs_fs_type); + if (unlikely(err)) + goto out_cache; + pr_info(AUFS_NAME " " AUFS_VERSION "\n"); + return 0; /* success */ + + out_cache: + destroy_cache(); + out_sysrq: + au_sysrq_fin(); + out_inotify: + au_inotify_fin(); + out_wkq: + au_wkq_fin(); + out_sysaufs: + sysaufs_fin(); + out: + AuTraceErr(err); + return err; +} + +static void __exit aufs_exit(void) +{ + unregister_filesystem(&aufs_fs_type); + destroy_cache(); + + au_sysrq_fin(); + au_inotify_fin(); + au_wkq_fin(); + sysaufs_fin(); +} + +module_init(aufs_init); +module_exit(aufs_exit); + +/* ---------------------------------------------------------------------- */ + +/* fake Kconfig */ +#if 1 + +#ifdef CONFIG_AUFS_HINOTIFY +#ifndef CONFIG_INOTIFY +#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY. +#endif +#endif /* CONFIG_AUFS_HINOTIFY */ + +#if AUFS_BRANCH_MAX > 511 && PAGE_SIZE > 4096 +#warning pagesize is larger than 4kb, \ + CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended. +#endif + +#ifdef CONFIG_AUFS_STAT +#ifndef CONFIG_SYSFS +#error CONFIG_AUFS_STAT requires CONFIG_SYSFS. +#endif +#endif /* CONFIG_AUFS_STAT */ + +#ifdef CONFIG_AUFS_SYSAUFS +#warning CONFIG_AUFS_SYSAUFS is unnecessary for linux-2.6.25 and later. +#endif + +#ifdef CONFIG_AUFS_EXPORT +#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE) +#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS +#endif +#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS) +#error need CONFIG_EXPORTFS = y to link aufs statically with CONFIG_AUFS_EXPORT +#endif +#endif /* CONFIG_AUFS_EXPORT */ + +#ifdef CONFIG_AUFS_SEC_PERM_PATCH +#ifndef CONFIG_SECURITY +#warning CONFIG_AUFS_SEC_PERM_PATCH is unnecessary since CONFIG_SECURITY is disabled. +#endif +#ifdef CONFIG_AUFS +#warning CONFIG_AUFS_SEC_PERM_PATCH is unnecessary since CONFIG_AUFS is not a module. +#endif +#endif + +#ifdef CONFIG_AUFS_PUT_FILP_PATCH +#if !defined(CONFIG_NFS_FS) && !defined(CONFIG_NFS_FS_MODULE) +#warning CONFIG_AUFS_PUT_FILP_PATCH is unnecessary since CONFIG_NFS_FS is disabled. +#endif +#ifdef CONFIG_AUFS +#warning CONFIG_AUFS_PUT_FILP_PATCH is unnecessary since CONFIG_AUFS is not a module. +#endif +#endif /* CONFIG_AUFS_PUT_FILP_PATCH */ + +#ifdef CONFIG_AUFS_LHASH_PATCH +#if !defined(CONFIG_NFS_FS) && !defined(CONFIG_NFS_FS_MODULE) +#warning CONFIG_AUFS_LHASH_PATCH is unnecessary since CONFIG_NFS_FS is disabled. +#endif +#endif + +#ifdef CONFIG_AUFS_KSIZE_PATCH +#warning CONFIG_AUFS_KSIZE_PATCH is unnecessary for linux-2.6.22 and later. +#endif + +#ifdef CONFIG_AUFS_WORKAROUND_FUSE +#if !defined(CONFIG_FUSE_FS) && !defined(CONFIG_FUSE_FS_MODULE) +#warning CONFIG_AUFS_WORKAROUND_FUSE is enabled while FUSE is disabled. +#endif +#endif + +#ifdef CONFIG_DEBUG_PROVE_LOCKING +#if MAX_LOCKDEP_SUBCLASSES < AuLsc_I_End +#warning lockdep will not work since aufs uses deeper locks. +#endif +#endif + +#ifdef CONFIG_AUFS_COMPAT +#warning CONFIG_AUFS_COMPAT will be removed in the near future. +#endif + +#if defined(CONFIG_AUFS_UNIONFS23_PATCH) \ + && !defined(CONFIG_AUFS_UNIONFS22_PATCH) +#error mis-configuration. CONFIG_AUFS_UNIONFS23_PATCH is enabled but CONFIG_AUFS_UNIONFS22_PATCH. +#endif + +#endif --- linux-2.6.27.orig/ubuntu/aufs/dcsub.c +++ linux-2.6.27/ubuntu/aufs/dcsub.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for dentry cache + * + * $Id: dcsub.c,v 1.7 2008/07/21 02:54:22 sfjro Exp $ + */ + +#include "aufs.h" + +static void au_dpage_free(struct au_dpage *dpage) +{ + int i; + + AuTraceEnter(); + AuDebugOn(!dpage); + + for (i = 0; i < dpage->ndentry; i++) + dput(dpage->dentries[i]); + free_page((unsigned long)dpage->dentries); +} + +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) +{ + int err; + void *p; + + AuTraceEnter(); + + err = -ENOMEM; + dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp); + if (unlikely(!dpages->dpages)) + goto out; + p = (void *)__get_free_page(gfp); + if (unlikely(!p)) + goto out_dpages; + dpages->dpages[0].ndentry = 0; + dpages->dpages[0].dentries = p; + dpages->ndpage = 1; + return 0; /* success */ + + out_dpages: + kfree(dpages->dpages); + out: + AuTraceErr(err); + return err; +} + +void au_dpages_free(struct au_dcsub_pages *dpages) +{ + int i; + + AuTraceEnter(); + + for (i = 0; i < dpages->ndpage; i++) + au_dpage_free(dpages->dpages + i); + kfree(dpages->dpages); +} + +static int au_dpages_append(struct au_dcsub_pages *dpages, + struct dentry *dentry, gfp_t gfp) +{ + int err, sz; + struct au_dpage *dpage; + void *p; + + /* AuTraceEnter(); */ + + dpage = dpages->dpages + dpages->ndpage - 1; + AuDebugOn(!dpage); + sz = PAGE_SIZE / sizeof(dentry); + if (unlikely(dpage->ndentry >= sz)) { + LKTRLabel(new dpage); + err = -ENOMEM; + sz = dpages->ndpage * sizeof(*dpages->dpages); + p = au_kzrealloc(dpages->dpages, sz, + sz + sizeof(*dpages->dpages), gfp); + if (unlikely(!p)) + goto out; + dpages->dpages = p; + dpage = dpages->dpages + dpages->ndpage; + p = (void *)__get_free_page(gfp); + if (unlikely(!p)) + goto out; + dpage->ndentry = 0; + dpage->dentries = p; + dpages->ndpage++; + } + + dpage->dentries[dpage->ndentry++] = dget(dentry); + return 0; /* success */ + + out: + /* AuTraceErr(err); */ + return err; +} + +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, + au_dpages_test test, void *arg) +{ + int err; + struct dentry *this_parent = root; + struct list_head *next; + struct super_block *sb = root->d_sb; + + AuTraceEnter(); + + err = 0; + spin_lock(&dcache_lock); + repeat: + next = this_parent->d_subdirs.next; + resume: + if (this_parent->d_sb == sb + && !IS_ROOT(this_parent) + && atomic_read(&this_parent->d_count) + && this_parent->d_inode + && (!test || test(this_parent, arg))) { + err = au_dpages_append(dpages, this_parent, GFP_ATOMIC); + if (unlikely(err)) + goto out; + } + + while (next != &this_parent->d_subdirs) { + struct list_head *tmp = next; + struct dentry *dentry = list_entry(tmp, struct dentry, + d_u.d_child); + next = tmp->next; + if (unlikely(/*d_unhashed(dentry) || */!dentry->d_inode)) + continue; + if (!list_empty(&dentry->d_subdirs)) { + this_parent = dentry; + goto repeat; + } + if (dentry->d_sb == sb + && atomic_read(&dentry->d_count) + && (!test || test(dentry, arg))) { + err = au_dpages_append(dpages, dentry, GFP_ATOMIC); + if (unlikely(err)) + goto out; + } + } + + if (this_parent != root) { + next = this_parent->d_u.d_child.next; + this_parent = this_parent->d_parent; /* dcache_lock is locked */ + goto resume; + } + out: + spin_unlock(&dcache_lock); +#if 0 /* debug */ + if (!err) { + int i, j; + j = 0; + for (i = 0; i < dpages->ndpage; i++) { + if ((dpages->dpages + i)->ndentry) + AuDbg("%d: %d\n", + i, (dpages->dpages + i)->ndentry); + j += (dpages->dpages + i)->ndentry; + } + if (j) + AuDbg("ndpage %d, %d\n", dpages->ndpage, j); + } +#endif + AuTraceErr(err); + return err; +} + +int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, + int do_include, au_dpages_test test, void *arg) +{ + int err; + + AuTraceEnter(); + + err = 0; + spin_lock(&dcache_lock); + if (do_include && (!test || test(dentry, arg))) { + err = au_dpages_append(dpages, dentry, GFP_ATOMIC); + if (unlikely(err)) + goto out; + } + while (!IS_ROOT(dentry)) { + dentry = dentry->d_parent; /* dcache_lock is locked */ + if (!test || test(dentry, arg)) { + err = au_dpages_append(dpages, dentry, GFP_ATOMIC); + if (unlikely(err)) + break; + } + } + + out: + spin_unlock(&dcache_lock); + + AuTraceErr(err); + return err; +} + +struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2) +{ + struct dentry *trap, **dentries; + int err, i, j; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + + LKTRTrace("%.*s, %.*s\n", AuDLNPair(d1), AuDLNPair(d2)); + + trap = ERR_PTR(-ENOMEM); + err = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(err)) + goto out; + err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL); + if (unlikely(err)) + goto out_dpages; + + trap = d1; + for (i = 0; !err && i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + for (j = 0; !err && j < dpage->ndentry; j++) { + struct dentry *d; + d = dentries[j]; + err = (d == d2); + if (!err) + trap = d; + } + } + if (!err) + trap = NULL; + + out_dpages: + au_dpages_free(&dpages); + out: + AuTraceErrPtr(trap); + return trap; +} --- linux-2.6.27.orig/ubuntu/aufs/super.c +++ linux-2.6.27/ubuntu/aufs/super.c @@ -0,0 +1,863 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * mount and super_block operations + * + * $Id: super.c,v 1.16 2008/09/15 03:14:49 sfjro Exp $ + */ + +#include +#include +#include +#include +#include + +#include "aufs.h" + +/* + * super_operations + */ +static struct inode *aufs_alloc_inode(struct super_block *sb) +{ + struct aufs_icntnr *c; + + AuTraceEnter(); + + c = au_cache_alloc_icntnr(); + if (c) { + inode_init_once(&c->vfs_inode); + c->vfs_inode.i_version = 1; /* sigen(sb); */ + c->iinfo.ii_hinode = NULL; + return &c->vfs_inode; + } + return NULL; +} + +static void aufs_destroy_inode(struct inode *inode) +{ + int err; + + LKTRTrace("i%lu\n", inode->i_ino); + + if (!inode->i_nlink) { + struct super_block *sb = inode->i_sb; + int locked; + + /* in nowait task, sbi is write-locked */ + /* todo: test kernel thread */ + locked = si_noflush_read_trylock(sb); + err = au_xigen_inc(inode); + if (unlikely(err)) + AuWarn1("failed resetting i_generation, %d\n", err); + if (locked) + si_read_unlock(sb); + } + + au_iinfo_fin(inode); + au_cache_free_icntnr(container_of(inode, struct aufs_icntnr, + vfs_inode)); +} + +struct inode *au_iget_locked(struct super_block *sb, ino_t ino) +{ + struct inode *inode; + int err; + + LKTRTrace("i%lu\n", (unsigned long)ino); + + inode = iget_locked(sb, ino); + if (unlikely(!inode)) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + AuDebugOn(IS_ERR(inode)); + if (unlikely(!(inode->i_state & I_NEW))) + goto out; + + err = au_xigen_new(inode); + if (!err) + err = au_iinfo_init(inode); + if (!err) + inode->i_version++; + else { + iget_failed(inode); + inode = ERR_PTR(err); + } + + out: + /* never return NULL */ + AuDebugOn(!inode); + AuTraceErrPtr(inode); + return inode; +} + +static int au_show_brs(struct seq_file *seq, struct super_block *sb) +{ + int err; + aufs_bindex_t bindex, bend; + struct dentry *root; + struct path path; + + AuTraceEnter(); + + err = 0; + root = sb->s_root; + bend = au_sbend(sb); + for (bindex = 0; !err && bindex <= bend; bindex++) { + path.mnt = au_sbr_mnt(sb, bindex); + path.dentry = au_h_dptr(root, bindex); + err = seq_path(seq, &path, au_esc_chars); + if (err > 0) + err = seq_printf + (seq, "=%s", + au_optstr_br_perm(au_sbr_perm(sb, bindex))); + if (!err && bindex != bend) + err = seq_putc(seq, ':'); + } + + AuTraceErr(err); + return err; +} + +static void au_show_wbr_create(struct seq_file *m, int v, + struct au_sbinfo *sbinfo) +{ + const char *pat; + + AuDebugOn(v == AuWbrCreate_Def); + + seq_printf(m, ",create="); + pat = au_optstr_wbr_create(v); + switch (v) { + case AuWbrCreate_TDP: + case AuWbrCreate_RR: + case AuWbrCreate_MFS: + case AuWbrCreate_PMFS: + seq_printf(m, pat); + break; + case AuWbrCreate_MFSV: + seq_printf(m, /*pat*/"mfs:%lu", + sbinfo->si_wbr_mfs.mfs_expire / HZ); + break; + case AuWbrCreate_PMFSV: + seq_printf(m, /*pat*/"pmfs:%lu", + sbinfo->si_wbr_mfs.mfs_expire / HZ); + break; + case AuWbrCreate_MFSRR: + seq_printf(m, /*pat*/"mfsrr:%llu", + sbinfo->si_wbr_mfs.mfsrr_watermark); + break; + case AuWbrCreate_MFSRRV: + seq_printf(m, /*pat*/"mfsrr:%llu:%lu", + sbinfo->si_wbr_mfs.mfsrr_watermark, + sbinfo->si_wbr_mfs.mfs_expire / HZ); + break; + } +} + +/* seq_file will re-call me in case of too long string */ +static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + int err, n; + struct super_block *sb; + struct au_sbinfo *sbinfo; + struct dentry *root; + struct file *xino; + unsigned int mnt_flags, v; + struct path path; + + AuTraceEnter(); + + sb = mnt->mnt_sb; + root = sb->s_root; + if (!sysaufs_brs) + aufs_read_lock(root, !AuLock_IR); + else + si_noflush_read_lock(sb); + sbinfo = au_sbi(sb); + seq_printf(m, ",si=%lx", au_si_mask ^ (unsigned long)sbinfo); + mnt_flags = au_mntflags(sb); + if (au_opt_test(mnt_flags, XINO)) { + seq_puts(m, ",xino="); + xino = sbinfo->si_xib; + path.mnt = xino->f_vfsmnt; + path.dentry = xino->f_dentry; + err = seq_path(m, &path, au_esc_chars); + if (unlikely(err <= 0)) + goto out; + err = 0; +#define Deleted "\\040(deleted)" + m->count -= sizeof(Deleted) - 1; + AuDebugOn(memcmp(m->buf + m->count, Deleted, + sizeof(Deleted) - 1)); +#undef Deleted +#ifdef CONFIG_AUFS_EXPORT /* reserved for future use */ + } else if (au_opt_test(mnt_flags, XINODIR)) { + seq_puts(m, ",xinodir="); + seq_path(m, &sbinfo->si_xinodir, au_esc_chars); +#endif + } else + seq_puts(m, ",noxino"); + +#define AuBool(name, str) do { \ + v = au_opt_test(mnt_flags, name); \ + if (v != au_opt_test(AuOpt_Def, name)) \ + seq_printf(m, ",%s" #str, v ? "" : "no"); \ +} while (0) + +#define AuStr(name, str) do { \ + v = mnt_flags & AuOptMask_##name; \ + if (v != (AuOpt_Def & AuOptMask_##name)) \ + seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \ +} while (0) + +#ifdef CONFIG_AUFS_COMPAT +#define AuStr_BrOpt "dirs=" +#else +#define AuStr_BrOpt "br:" +#endif + + AuBool(TRUNC_XINO, trunc_xino); + AuBool(DIRPERM1, dirperm1); + AuBool(SHWH, shwh); + AuBool(PLINK, plink); + AuStr(UDBA, udba); + + v = sbinfo->si_wbr_create; + if (v != AuWbrCreate_Def) + au_show_wbr_create(m, v, sbinfo); + + v = sbinfo->si_wbr_copyup; + if (v != AuWbrCopyup_Def) + seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v)); + + v = au_opt_test(mnt_flags, ALWAYS_DIROPQ); + if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ)) + seq_printf(m, ",diropq=%c", v ? 'a' : 'w'); + AuBool(REFROF, refrof); + AuBool(DLGT, dlgt); + AuBool(WARN_PERM, warn_perm); + AuBool(VERBOSE, verbose); + + n = sbinfo->si_dirwh; + if (n != AUFS_DIRWH_DEF) + seq_printf(m, ",dirwh=%d", n); + n = sbinfo->si_rdcache / HZ; + if (n != AUFS_RDCACHE_DEF) + seq_printf(m, ",rdcache=%d", n); + + AuStr(COO, coo); + + out: + if (!sysaufs_brs) { + seq_puts(m, "," AuStr_BrOpt); + au_show_brs(m, sb); + aufs_read_unlock(root, !AuLock_IR); + } else + si_read_unlock(sb); + return 0; + +#undef AuBool +#undef AuStr +#undef AuStr_BrOpt +} + +/* todo: in case of round-robin policy, return the sum of all rw branches? */ +static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + int err; + + AuTraceEnter(); + + aufs_read_lock(dentry->d_sb->s_root, 0); + err = vfsub_statfs(au_h_dptr(dentry->d_sb->s_root, 0), buf, + !!au_test_dlgt(au_mntflags(dentry->d_sb))); + aufs_read_unlock(dentry->d_sb->s_root, 0); + if (!err) { + buf->f_type = AUFS_SUPER_MAGIC; + buf->f_namelen -= AUFS_WH_PFX_LEN; + memset(&buf->f_fsid, 0, sizeof(buf->f_fsid)); + } + /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */ + + AuTraceErr(err); + return err; +} + +static void au_fsync_br(struct super_block *sb) +{ +#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH + aufs_bindex_t bend, bindex; + int brperm; + struct super_block *h_sb; + + AuTraceEnter(); + + si_write_lock(sb); + bend = au_sbend(sb); + for (bindex = 0; bindex < bend; bindex++) { + brperm = au_sbr_perm(sb, bindex); + if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH) + continue; + h_sb = au_sbr_sb(sb, bindex); + if (bdev_read_only(h_sb->s_bdev)) + continue; + + lockdep_off(); + down_write(&h_sb->s_umount); + shrink_dcache_sb(h_sb); + fsync_super(h_sb); + up_write(&h_sb->s_umount); + lockdep_on(); + } + si_write_unlock(sb); +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +/* this IS NOT for super_operations */ +static void aufs_umount_begin(struct super_block *arg) +#define AuUmountBeginSb(arg) (arg) +#else +/* this IS for super_operations */ +static void aufs_umount_begin(struct vfsmount *arg, int flags) +#define AuUmountBeginSb(arg) (arg)->mnt_sb +#endif +{ + struct super_block *sb = AuUmountBeginSb(arg); + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + /* dont trust BKL */ + AuDebugOn(!kernel_locked()); + + sbinfo = au_sbi(sb); + if (unlikely(!sbinfo)) + return; + + au_fsync_br(sb); + + si_write_lock(sb); + if (au_opt_test(au_mntflags(sb), PLINK)) + au_plink_put(sb); + au_mnt_reset(sbinfo); +#if 0 /* reserved for future use */ + if (sbinfo->si_wbr_create_ops->fin) + sbinfo->si_wbr_create_ops->fin(sb); +#endif + si_write_unlock(sb); +} + +/* final actions when unmounting a file system */ +static void aufs_put_super(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + + sbinfo = au_sbi(sb); + if (unlikely(!sbinfo)) + return; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + aufs_umount_begin(sb); +#endif + kobject_put(&sbinfo->si_kobj); +} + +/* ---------------------------------------------------------------------- */ + +/* + * refresh dentry and inode at remount time. + */ +static int do_refresh(struct dentry *dentry, mode_t type, + unsigned int dir_flags) +{ + int err; + struct dentry *parent; + struct inode *inode; + + LKTRTrace("%.*s, 0%o\n", AuDLNPair(dentry), type); + inode = dentry->d_inode; + AuDebugOn(!inode); + + di_write_lock_child(dentry); + parent = dget_parent(dentry); + di_read_lock_parent(parent, AuLock_IR); + /* returns a number of positive dentries */ + err = au_refresh_hdentry(dentry, type); + if (err >= 0) { + err = au_refresh_hinode(inode, dentry); + if (!err && type == S_IFDIR) + au_reset_hinotify(inode, dir_flags); + } + if (unlikely(err)) + AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry)); + di_read_unlock(parent, AuLock_IR); + dput(parent); + di_write_unlock(dentry); + + AuTraceErr(err); + return err; +} + +static int test_dir(struct dentry *dentry, void *arg) +{ + return S_ISDIR(dentry->d_inode->i_mode); +} + +/* todo: merge with refresh_nondir()? */ +static int refresh_dir(struct dentry *root, au_gen_t sgen) +{ + int err, i, j, ndentry, e; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + struct inode *inode; + const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1); + + LKTRTrace("sgen %d\n", sgen); + SiMustWriteLock(root->d_sb); + /* dont trust BKL */ + AuDebugOn(au_digen(root) != sgen || !kernel_locked()); + + err = 0; + list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list) + if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) { + ii_write_lock_child(inode); + e = au_refresh_hinode_self(inode); + ii_write_unlock(inode); + if (unlikely(e)) { + LKTRTrace("e %d, i%lu\n", e, inode->i_ino); + if (!err) + err = e; + /* go on even if err */ + } + } + + e = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(e)) { + if (!err) + err = e; + goto out; + } + e = au_dcsub_pages(&dpages, root, test_dir, NULL); + if (unlikely(e)) { + if (!err) + err = e; + goto out_dpages; + } + + for (i = 0; !e && i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + ndentry = dpage->ndentry; + for (j = 0; !e && j < ndentry; j++) { + struct dentry *d; + d = dentries[j]; +#ifdef CONFIG_AUFS_DEBUG + { + struct dentry *parent; + parent = dget_parent(d); + AuDebugOn(!S_ISDIR(d->d_inode->i_mode) + || IS_ROOT(d) + || au_digen(parent) != sgen); + dput(parent); + } +#endif + if (au_digen(d) != sgen) { + e = do_refresh(d, S_IFDIR, flags); + if (unlikely(e && !err)) + err = e; + /* break on err */ + } + } + } + + out_dpages: + au_dpages_free(&dpages); + out: + AuTraceErr(err); + return err; +} + +static int test_nondir(struct dentry *dentry, void *arg) +{ + return !S_ISDIR(dentry->d_inode->i_mode); +} + +static int refresh_nondir(struct dentry *root, au_gen_t sgen, int do_dentry) +{ + int err, i, j, ndentry, e; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + struct inode *inode; + + LKTRTrace("sgen %d\n", sgen); + SiMustWriteLock(root->d_sb); + /* dont trust BKL */ + AuDebugOn(au_digen(root) != sgen || !kernel_locked()); + + err = 0; + list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list) + if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) { + ii_write_lock_child(inode); + e = au_refresh_hinode_self(inode); + ii_write_unlock(inode); + if (unlikely(e)) { + LKTRTrace("e %d, i%lu\n", e, inode->i_ino); + if (!err) + err = e; + /* go on even if err */ + } + } + + if (!do_dentry) + goto out; + + e = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(e)) { + if (!err) + err = e; + goto out; + } + e = au_dcsub_pages(&dpages, root, test_nondir, NULL); + if (unlikely(e)) { + if (!err) + err = e; + goto out_dpages; + } + + for (i = 0; i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + ndentry = dpage->ndentry; + for (j = 0; j < ndentry; j++) { + struct dentry *d; + d = dentries[j]; +#ifdef CONFIG_AUFS_DEBUG + { + struct dentry *parent; + parent = dget_parent(d); + AuDebugOn(S_ISDIR(d->d_inode->i_mode) + || au_digen(parent) != sgen); + dput(parent); + } +#endif + inode = d->d_inode; + if (inode && au_digen(d) != sgen) { + e = do_refresh(d, inode->i_mode & S_IFMT, 0); + if (unlikely(e && !err)) + err = e; + /* go on even err */ + } + } + } + + out_dpages: + au_dpages_free(&dpages); + out: + AuTraceErr(err); + return err; +} + +/* stop extra interpretation of errno in mount(8), and strange error messages */ +static int cvt_err(int err) +{ + AuTraceErr(err); + + switch (err) { + case -ENOENT: + case -ENOTDIR: + case -EEXIST: + case -EIO: + err = -EINVAL; + } + return err; +} + +/* protected by s_umount */ +static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) +{ + int err, rerr; + au_gen_t sigen; + struct dentry *root; + struct inode *inode; + struct au_opts opts; + struct au_sbinfo *sbinfo; + unsigned char dlgt; + + LKTRTrace("flags 0x%x, data %s, len %lu\n", + *flags, data ? data : "NULL", + (unsigned long)(data ? strlen(data) : 0)); + + au_fsync_br(sb); + + err = 0; + if (!data || !*data) + goto out; /* success */ + + err = -ENOMEM; + memset(&opts, 0, sizeof(opts)); + opts.opt = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!opts.opt)) + goto out; + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); + opts.flags = AuOpts_REMOUNT; + + /* parse it before aufs lock */ + err = au_opts_parse(sb, *flags, data, &opts); + if (unlikely(err)) + goto out_opts; + + sbinfo = au_sbi(sb); + root = sb->s_root; + inode = root->d_inode; + mutex_lock(&inode->i_mutex); + aufs_write_lock(root); + + /* au_do_opts() may return an error */ + err = au_opts_remount(sb, &opts); + au_opts_free(&opts); + + if (au_ftest_opts(opts.flags, REFRESH_DIR) + || au_ftest_opts(opts.flags, REFRESH_NONDIR)) { + dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT); + au_opt_clr(sbinfo->si_mntflags, DLGT); + au_sigen_inc(sb); + au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1)); + sigen = au_sigen(sb); + au_fclr_si(sbinfo, FAILED_REFRESH_DIRS); + + DiMustNoWaiters(root); + IiMustNoWaiters(root->d_inode); + di_write_unlock(root); + + rerr = refresh_dir(root, sigen); + if (unlikely(rerr)) { + au_fset_si(sbinfo, FAILED_REFRESH_DIRS); + AuWarn("Refreshing directories failed, ignores (%d)\n", + rerr); + } + + if (unlikely(au_ftest_opts(opts.flags, REFRESH_NONDIR))) { + rerr = refresh_nondir(root, sigen, !rerr); + if (unlikely(rerr)) + AuWarn("Refreshing non-directories failed," + " ignores (%d)\n", rerr); + } + + /* aufs_write_lock() calls ..._child() */ + di_write_lock_child(root); + + au_cpup_attr_all(inode); + if (unlikely(dlgt)) + au_opt_set(sbinfo->si_mntflags, DLGT); + } + + aufs_write_unlock(root); + mutex_unlock(&inode->i_mutex); + + out_opts: + free_page((unsigned long)opts.opt); + out: + err = cvt_err(err); + AuTraceErr(err); + return err; +} + +static struct super_operations aufs_sop = { + .alloc_inode = aufs_alloc_inode, + .destroy_inode = aufs_destroy_inode, + .drop_inode = generic_delete_inode, + + .show_options = aufs_show_options, + .statfs = aufs_statfs, + + .put_super = aufs_put_super, + .remount_fs = aufs_remount_fs, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + .umount_begin = aufs_umount_begin +#endif +}; + +/* ---------------------------------------------------------------------- */ + +static int alloc_root(struct super_block *sb) +{ + int err; + struct inode *inode; + struct dentry *root; + + AuTraceEnter(); + + err = -ENOMEM; + inode = au_iget_locked(sb, AUFS_ROOT_INO); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out; + inode->i_op = &aufs_dir_iop; + inode->i_fop = &aufs_dir_fop; + inode->i_mode = S_IFDIR; + unlock_new_inode(inode); + root = d_alloc_root(inode); + if (unlikely(!root)) + goto out_iput; + err = PTR_ERR(root); + if (IS_ERR(root)) + goto out_iput; + + err = au_alloc_dinfo(root); + if (!err) { + sb->s_root = root; + return 0; /* success */ + } + dput(root); + goto out; /* do not iput */ + + out_iput: + iget_failed(inode); + iput(inode); + out: + AuTraceErr(err); + return err; + +} + +static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent) +{ + int err; + struct dentry *root; + struct inode *inode; + struct au_opts opts; + char *arg = raw_data; + + if (unlikely(!arg || !*arg)) { + err = -EINVAL; + AuErr("no arg\n"); + goto out; + } + LKTRTrace("%s, silent %d\n", arg, silent); + + err = -ENOMEM; + memset(&opts, 0, sizeof(opts)); + opts.opt = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!opts.opt)) + goto out; + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); + + err = au_si_alloc(sb); + if (unlikely(err)) + goto out_opts; + SiMustWriteLock(sb); + /* all timestamps always follow the ones on the branch */ + sb->s_flags |= MS_NOATIME | MS_NODIRATIME; + sb->s_op = &aufs_sop; + sb->s_magic = AUFS_SUPER_MAGIC; + au_export_init(sb); + + err = alloc_root(sb); + if (unlikely(err)) { + AuDebugOn(sb->s_root); + si_write_unlock(sb); + goto out_info; + } + root = sb->s_root; + DiMustWriteLock(root); + inode = root->d_inode; + inode->i_nlink = 2; + + /* + * actually we can parse options regardless aufs lock here. + * but at remount time, parsing must be done before aufs lock. + * so we follow the same rule. + */ + ii_write_lock_parent(inode); + aufs_write_unlock(root); + err = au_opts_parse(sb, sb->s_flags, arg, &opts); + if (unlikely(err)) + goto out_root; + + /* lock vfs_inode first, then aufs. */ + mutex_lock(&inode->i_mutex); + inode->i_op = &aufs_dir_iop; + inode->i_fop = &aufs_dir_fop; + aufs_write_lock(root); + + sb->s_maxbytes = 0; + err = au_opts_mount(sb, &opts); + au_opts_free(&opts); + if (unlikely(err)) + goto out_unlock; + AuDebugOn(!sb->s_maxbytes); + + aufs_write_unlock(root); + mutex_unlock(&inode->i_mutex); + goto out_opts; /* success */ + + out_unlock: + aufs_write_unlock(root); + mutex_unlock(&inode->i_mutex); + out_root: + dput(root); + sb->s_root = NULL; + out_info: + kobject_put(&au_sbi(sb)->si_kobj); + sb->s_fs_info = NULL; + out_opts: + free_page((unsigned long)opts.opt); + out: + AuTraceErr(err); + err = cvt_err(err); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int aufs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data, + struct vfsmount *mnt) +{ + int err; + struct super_block *sb; + + /* all timestamps always follow the ones on the branch */ + /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ + err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt); + if (!err) { + sb = mnt->mnt_sb; + au_mnt_init(au_sbi(sb), mnt); + si_write_lock(sb); + sysaufs_brs_add(sb, 0); + si_write_unlock(sb); + } + return err; +} + +struct file_system_type aufs_fs_type = { + .name = AUFS_FSTYPE, + .fs_flags = + FS_RENAME_DOES_D_MOVE /* a race between rename and others*/ + | FS_REVAL_DOT, /* for NFS branch */ + .get_sb = aufs_get_sb, + .kill_sb = generic_shutdown_super, + /* no need to __module_get() and module_put(). */ + .owner = THIS_MODULE, +}; --- linux-2.6.27.orig/ubuntu/aufs/iinfo.c +++ linux-2.6.27/ubuntu/aufs/iinfo.c @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode private data + * + * $Id: iinfo.c,v 1.8 2008/09/15 03:16:36 sfjro Exp $ + */ + +#include "aufs.h" + +struct au_iinfo *au_ii(struct inode *inode) +{ + struct au_iinfo *iinfo; + + iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo); + /* bad_inode case */ + if (unlikely(!iinfo->ii_hinode)) + return NULL; + AuDebugOn(!iinfo->ii_hinode + /* || au_sbi(inode->i_sb)->si_bend < iinfo->ii_bend */ + || iinfo->ii_bend < iinfo->ii_bstart); + return iinfo; +} + +struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex) +{ + struct inode *hidden_inode; + + IiMustAnyLock(inode); + AuDebugOn(bindex < 0 || au_ibend(inode) < bindex); + hidden_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode; + AuDebugOn(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0); + return hidden_inode; +} + +aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex) +{ + IiMustAnyLock(inode); + AuDebugOn(bindex < 0 + || au_ibend(inode) < bindex + || !au_ii(inode)->ii_hinode[0 + bindex].hi_inode); + return au_ii(inode)->ii_hinode[0 + bindex].hi_id; +} + +/* todo: hard/soft set? */ +void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex) +{ + struct au_iinfo *iinfo = au_ii(inode); + struct inode *h_inode; + + IiMustWriteLock(inode); + AuDebugOn(au_sbend(inode->i_sb) < bindex); + iinfo->ii_bstart = bindex; + h_inode = iinfo->ii_hinode[bindex + 0].hi_inode; + if (h_inode) + au_cpup_igen(inode, h_inode); +} + +unsigned int au_hi_flags(struct inode *inode, int isdir) +{ + unsigned int flags; + const unsigned int mnt_flags = au_mntflags(inode->i_sb); + + flags = 0; + if (au_opt_test_xino(mnt_flags)) + au_fset_hi(flags, XINO); + if (unlikely(isdir && au_opt_test(mnt_flags, UDBA_INOTIFY))) + au_fset_hi(flags, NOTIFY); + return flags; +} + +void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, + struct inode *h_inode, unsigned int flags) +{ + struct au_hinode *hinode; + struct inode *hi; + struct au_iinfo *iinfo = au_ii(inode); + + LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n", + inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags); + IiMustWriteLock(inode); + hinode = iinfo->ii_hinode + bindex; + hi = hinode->hi_inode; + AuDebugOn(bindex < au_ibstart(inode) || au_ibend(inode) < bindex); + AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); + AuDebugOn(h_inode && hi); + + if (hi) + au_hiput(hinode); + hinode->hi_inode = h_inode; + if (h_inode) { + int err; + struct super_block *sb = inode->i_sb; + + if (bindex == iinfo->ii_bstart) + au_cpup_igen(inode, h_inode); + hinode->hi_id = au_sbr_id(sb, bindex); + if (au_ftest_hi(flags, XINO)) { + struct au_xino_entry xinoe = { + .ino = inode->i_ino, + /* .h_gen = h_inode->i_generation */ + }; + err = au_xino_write(sb, bindex, h_inode->i_ino, &xinoe); + if (unlikely(err)) + AuIOErr1("failed au_xino_write() %d\n", err); + } + + if (unlikely(au_ftest_hi(flags, NOTIFY) + && au_br_hinotifyable(au_sbr_perm(sb, bindex)))) { + err = au_hin_alloc(hinode, inode, h_inode); + if (unlikely(err)) + AuIOErr1("au_hin_alloc() %d\n", err); + } + } +} + +void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, + struct dentry *h_wh) +{ + struct au_hinode *hinode; + + IiMustWriteLock(inode); + hinode = au_ii(inode)->ii_hinode + bindex; + AuDebugOn(hinode->hi_whdentry); + hinode->hi_whdentry = h_wh; +} + +void au_update_iigen(struct inode *inode) +{ + AuDebugOn(!inode->i_sb); + atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb)); + /* smp_mb(); */ /* atomic_set */ +} + +/* it may be called at remount time, too */ +void au_update_brange(struct inode *inode, int do_put_zero) +{ + struct au_iinfo *iinfo; + + LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero); + IiMustWriteLock(inode); + + iinfo = au_ii(inode); + if (unlikely(!iinfo) || iinfo->ii_bstart < 0) + return; + + if (do_put_zero) { + aufs_bindex_t bindex; + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; + bindex++) { + struct inode *h_i; + h_i = iinfo->ii_hinode[0 + bindex].hi_inode; + if (h_i && !h_i->i_nlink) + au_set_h_iptr(inode, bindex, NULL, 0); + } + } + + iinfo->ii_bstart = -1; + while (++iinfo->ii_bstart <= iinfo->ii_bend) + if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode) + break; + if (iinfo->ii_bstart > iinfo->ii_bend) { + iinfo->ii_bstart = -1; + iinfo->ii_bend = -1; + return; + } + + iinfo->ii_bend++; + while (0 <= --iinfo->ii_bend) + if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode) + break; + AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0); +} + +/* ---------------------------------------------------------------------- */ + +int au_iinfo_init(struct inode *inode) +{ + struct au_iinfo *iinfo; + struct super_block *sb; + int nbr, i; + + sb = inode->i_sb; + AuDebugOn(!sb); + iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo); + AuDebugOn(iinfo->ii_hinode); + nbr = au_sbend(sb) + 1; + if (unlikely(nbr <= 0)) + nbr = 1; + iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS); + if (iinfo->ii_hinode) { + for (i = 0; i < nbr; i++) + iinfo->ii_hinode[i].hi_id = -1; + atomic_set(&iinfo->ii_generation, au_sigen(sb)); + /* smp_mb(); */ /* atomic_set */ + au_rw_init_nolock(&iinfo->ii_rwsem); + iinfo->ii_bstart = -1; + iinfo->ii_bend = -1; + iinfo->ii_vdir = NULL; + return 0; + } + return -ENOMEM; +} + +static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode, + ino_t ino) +{ + int err, locked; + aufs_bindex_t bindex; + + err = 0; + locked = si_noflush_read_trylock(sb); /* crucio! */ + bindex = au_br_index(sb, hinode->hi_id); + if (bindex >= 0) + err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino); + /* error action? */ + if (locked) + si_read_unlock(sb); + return err; +} + +void au_iinfo_fin(struct inode *inode) +{ + struct au_iinfo *iinfo; + aufs_bindex_t bend; + unsigned char unlinked; + struct au_hinode *hi; + struct super_block *sb; + ino_t ino; + + iinfo = au_ii(inode); + /* bad_inode case */ + if (unlikely(!iinfo)) + return; + + if (unlikely(iinfo->ii_vdir)) + au_vdir_free(iinfo->ii_vdir); + + if (iinfo->ii_bstart >= 0) { + sb = inode->i_sb; + unlinked = !inode->i_nlink; + ino = 0; + if (unlinked) + ino = inode->i_ino; + hi = iinfo->ii_hinode + iinfo->ii_bstart; + bend = iinfo->ii_bend; + while (iinfo->ii_bstart++ <= bend) { + if (hi->hi_inode) { + if (unlinked || !hi->hi_inode->i_nlink) { + au_iinfo_write0(sb, hi, ino); + /* ignore this error */ + ino = 0; + } + au_hiput(hi); + } + hi++; + } + } + + kfree(iinfo->ii_hinode); +} --- linux-2.6.27.orig/ubuntu/aufs/sysaufs.h +++ linux-2.6.27/ubuntu/aufs/sysaufs.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sysfs interface and lifetime management + * + * $Id: sysaufs.h,v 1.11 2008/09/15 03:14:55 sfjro Exp $ + */ + +#ifndef __SYSAUFS_H__ +#define __SYSAUFS_H__ + +#ifdef __KERNEL__ + +#include +#include +#include "module.h" +#include "super.h" + +#define SysaufsSb_PREFIX "si_" /* followed by %p */ + +struct au_sbi_attr { + struct attribute attr; + int (*show)(struct seq_file *seq, struct super_block *sb); +}; + +/* ---------------------------------------------------------------------- */ + +/* sysaufs.c */ +extern unsigned long au_si_mask; +extern struct kset *au_kset; +extern struct attribute *au_sbi_attrs[]; +int sysaufs_si_init(struct au_sbinfo *sbinfo); +int __init sysaufs_init(void); +void sysaufs_fin(void); + +/* ---------------------------------------------------------------------- */ + +struct au_branch; +#ifdef CONFIG_SYSFS +/* sysfs.c */ +extern struct attribute_group *au_attr_group; +extern struct kobj_type *au_ktype; + +int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb); +#ifdef CONFIG_AUFS_EXPORT +int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb); +#endif +int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb); +ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr, + char *buf); + +void sysaufs_br_init(struct au_branch *br); +void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); +void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); +#else +#define au_attr_group NULL +#define au_ktype NULL + +static inline +int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb) +{ + return 0; +} + +#ifdef CONFIG_AUFS_EXPORT +static inline +int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb) +{ + return 0; +} +#endif + +static inline +int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb) +{ + return 0; +} + +static inline +ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + return 0; +} + +static inline void sysaufs_br_init(struct au_branch *br) +{ + /* empty */ +} + +static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) +{ + /* nothing */ +} + +static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) +{ + /* nothing */ +} +#endif /* CONFIG_SYSFS */ + +#endif /* __KERNEL__ */ +#endif /* __SYSAUFS_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/sysfs.c +++ linux-2.6.27/ubuntu/aufs/sysfs.c @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sysfs interface + * + * $Id: sysfs.c,v 1.13 2008/09/15 03:14:55 sfjro Exp $ + */ + +#include +#include +#include +#include +#include "aufs.h" + + +#ifdef CONFIG_AUFS_LOCAL +static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ +#define conf_bool(name) "CONFIG_AUFS_" #name "=y\n" + static const char opt[] = +#ifdef CONFIG_AUFS + "CONFIG_AUFS=y\n" +#else + "CONFIG_AUFS=m\n" +#endif +#ifdef CONFIG_AUFS_BRANCH_MAX_127 + conf_bool(BRANCH_MAX_127) +#elif defined(CONFIG_AUFS_BRANCH_MAX_511) + conf_bool(BRANCH_MAX_511) +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) + conf_bool(BRANCH_MAX_1023) +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) + conf_bool(BRANCH_MAX_32767) +#endif +#ifdef CONFIG_AUFS_HINOTIFY + conf_bool(HINOTIFY) +#endif +#ifdef CONFIG_AUFS_EXPORT + conf_bool(EXPORT) +#endif +#ifdef CONFIG_AUFS_ROBR + conf_bool(ROBR) +#endif +#ifdef CONFIG_AUFS_SHWH + conf_bool(SHWH) +#endif +#ifdef CONFIG_AUFS_DLGT + conf_bool(DLGT) +#endif +#ifdef CONFIG_AUFS_HIN_OR_DLGT + conf_bool(HIN_OR_DLGT) +#endif +#ifdef CONFIG_AUFS_RR_SQUASHFS + conf_bool(RR_SQUASHFS) +#endif +#ifdef CONFIG_AUFS_SEC_PERM_PATCH + conf_bool(SEC_PERM_PATCH) +#endif +#ifdef CONFIG_AUFS_SPLICE_PATCH + conf_bool(SPLICE_PATCH) +#endif +#ifdef CONFIG_AUFS_PUT_FILP_PATCH + conf_bool(PUT_FILP_PATCH) +#endif +#ifdef CONFIG_AUFS_LHASH_PATCH + conf_bool(LHASH_PATCH) +#endif +#ifdef CONFIG_AUFS_BR_NFS + conf_bool(BR_NFS) +#endif +#ifdef CONFIG_AUFS_BR_XFS + conf_bool(BR_XFS) +#endif +#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH + conf_bool(FSYNC_SUPER_PATCH) +#endif +#ifdef CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH + conf_bool(DENY_WRITE_ACCESS_PATCH) +#endif +#ifdef CONFIG_AUFS_KSIZE_PATCH + conf_bool(KSIZE_PATCH) +#endif +#ifdef CONFIG_AUFS_WORKAROUND_FUSE + conf_bool(WORKAROUND_FUSE) +#endif +#ifdef CONFIG_AUFS_HIN_OR_FUSE + conf_bool(HIN_OR_FUSE) +#endif +#ifdef CONFIG_AUFS_STAT + conf_bool(STAT) +#endif +#ifdef CONFIG_AUFS_DEBUG + conf_bool(DEBUG) +#endif +#ifdef CONFIG_AUFS_MAGIC_SYSRQ + conf_bool(MAGIC_SYSRQ) +#endif +#ifdef CONFIG_AUFS_COMPAT + conf_bool(COMPAT) +#endif +#ifdef CONFIG_AUFS_UNIONFS22_PATCH + conf_bool(UNIONFS22_PATCH) +#endif +#ifdef CONFIG_AUFS_UNIONFS23_PATCH + conf_bool(UNIONFS23_PATCH) +#endif + ; +#undef conf_bool + + char *p = buf; + const char *end = buf + PAGE_SIZE; + + p += snprintf(p, end - p, "%s", opt); +#ifdef DbgUdbaRace + if (p < end) + p += snprintf(p, end - p, "DbgUdbaRace=%d\n", DbgUdbaRace); +#endif + if (p < end) + return p - buf; + else + return -EFBIG; +} + +static struct kobj_attribute au_config_attr = __ATTR_RO(config); +#endif + +#ifdef CONFIG_AUFS_STAT +static ssize_t stat_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + char *p = buf; + const char *end = buf + PAGE_SIZE; + int i; + + p += snprintf(p, end - p, "wkq max_busy:"); + for (i = 0; p < end && i < aufs_nwkq; i++) + p += snprintf(p, end - p, " %u", au_wkq[i].max_busy); + if (p < end) + p += snprintf(p, end - p, ", %u(generic)\n", + au_wkq[aufs_nwkq].max_busy); + + if (p < end) + return p - buf; + else + return -EFBIG; +} + +static struct kobj_attribute au_stat_attr = __ATTR_RO(stat); +#endif + +#ifdef CONFIG_AUFS_DEBUG +static ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", au_debug_test()); +} + +static ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t sz) +{ + LKTRTrace("%.*s\n", (unsigned int)sz, buf); + + if (unlikely(!sz || (*buf != '0' && *buf != '1'))) + return -EOPNOTSUPP; + + if (*buf == '0') + au_debug_off(); + else if (*buf == '1') + au_debug_on(); + return sz; +} + +static struct kobj_attribute au_debug_attr = __ATTR(debug, S_IRUGO | S_IWUSR, + debug_show, debug_store); +#endif + +static struct attribute *au_attr[] = { +#ifdef CONFIG_AUFS_LOCAL + &au_config_attr.attr, +#endif +#ifdef CONFIG_AUFS_STAT + &au_stat_attr.attr, +#endif +#ifdef CONFIG_AUFS_DEBUG + &au_debug_attr.attr, +#endif + NULL, /* need to NULL terminate the list of attributes */ +}; + +static struct attribute_group au_attr_group_body = { + .attrs = au_attr +}; + +struct attribute_group *au_attr_group = &au_attr_group_body; + +/* ---------------------------------------------------------------------- */ + +/* + * they are copied from linux/lib/kobject.c, + * and will be exported in the future. + */ +static ssize_t au_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct kobj_attribute *kattr; + ssize_t ret = -EIO; + + kattr = container_of(attr, struct kobj_attribute, attr); + if (kattr->show) + ret = kattr->show(kobj, kattr, buf); + return ret; +} + +#ifdef CONFIG_AUFS_DEBUG +static ssize_t au_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct kobj_attribute *kattr; + ssize_t ret = -EIO; + + kattr = container_of(attr, struct kobj_attribute, attr); + if (kattr->store) + ret = kattr->store(kobj, kattr, buf, count); + return ret; +} +#endif + +static struct sysfs_ops sysaufs_ops = { + .show = au_attr_show, +#ifdef CONFIG_AUFS_DEBUG + .store = au_attr_store +#endif +}; + +static struct kobj_type au_ktype_body = { + .sysfs_ops = &sysaufs_ops +}; +struct kobj_type *au_ktype = &au_ktype_body; + +/* ---------------------------------------------------------------------- */ + +static int sysaufs_sbi_xi(struct seq_file *seq, struct file *xf, int dlgt, + int print_path) +{ + int err; + struct kstat st; + struct path path; + + err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt); + if (!err) { + seq_printf(seq, "%llux%lu %lld", + st.blocks, st.blksize, (long long)st.size); + if (unlikely(print_path)) { + path.dentry = xf->f_dentry; + path.mnt = xf->f_vfsmnt; + seq_putc(seq, ' '); + seq_path(seq, &path, au_esc_chars); + } + seq_putc(seq, '\n'); + } else + seq_printf(seq, "err %d\n", err); + + AuTraceErr(err); + return err; +} + +int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb) +{ + int err; + unsigned int mnt_flags; + aufs_bindex_t bend, bindex; + unsigned char dlgt, xinodir; + struct kstat st; + struct path path; + struct au_sbinfo *sbinfo; + struct file *xf; + + AuTraceEnter(); + + sbinfo = au_sbi(sb); + mnt_flags = au_mntflags(sb); + xinodir = !!au_opt_test(mnt_flags, XINODIR); + if (unlikely(!au_opt_test_xino(mnt_flags))) { +#ifdef CONFIG_AUFS_DEBUG + AuDebugOn(sbinfo->si_xib); + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) + AuDebugOn(au_sbr(sb, bindex)->br_xino.xi_file); +#endif + err = 0; + goto out; /* success */ + } + + dlgt = !!au_test_dlgt(mnt_flags); + err = sysaufs_sbi_xi(seq, sbinfo->si_xib, dlgt, xinodir); + + bend = au_sbend(sb); + for (bindex = 0; !err && bindex <= bend; bindex++) { + xf = au_sbr(sb, bindex)->br_xino.xi_file; + if (!xf) + continue; + seq_printf(seq, "%d: ", bindex); + err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt); + if (!err) { + seq_printf(seq, "%ld, %llux%lu %lld", + (long)file_count(xf), st.blocks, st.blksize, + (long long)st.size); + if (unlikely(xinodir)) { + path.dentry = xf->f_dentry; + path.mnt = xf->f_vfsmnt; + seq_putc(seq, ' '); + seq_path(seq, &path, au_esc_chars); + } + seq_putc(seq, '\n'); + } else + seq_printf(seq, "err %d\n", err); + } + + out: + AuTraceErr(err); + return err; +} + +#ifdef CONFIG_AUFS_EXPORT +int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb) +{ + int err; + unsigned int mnt_flags; + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + + err = 0; + sbinfo = au_sbi(sb); + mnt_flags = au_mntflags(sb); + if (au_opt_test_xino(mnt_flags)) + err = sysaufs_sbi_xi(seq, sbinfo->si_xigen, + !!au_opt_test(mnt_flags, DLGT), + !!au_opt_test(mnt_flags, XINODIR)); + + AuTraceErr(err); + return err; +} +#endif + +/* + * the lifetime of branch is independent from the entry under sysfs. + * sysfs handles the lifetime of the entry, and never call ->show() after it is + * unlinked. + */ +#define SysaufsBr_PREFIX "br" +static int sysaufs_sbi_br(struct seq_file *seq, struct super_block *sb, + aufs_bindex_t bindex) +{ + int err; + struct dentry *root; + struct au_branch *br; + struct path path; + + LKTRTrace("b%d\n", bindex); + + err = -ENOENT; + if (unlikely(au_sbend(sb) < bindex)) + goto out; + + err = 0; + root = sb->s_root; + di_read_lock_parent(root, !AuLock_IR); + br = au_sbr(sb, bindex); + path.mnt = br->br_mnt; + path.dentry = au_h_dptr(root, bindex); + seq_path(seq, &path, au_esc_chars); + di_read_unlock(root, !AuLock_IR); + seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm)); + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static struct seq_file *au_seq(char *p, ssize_t len) +{ + struct seq_file *seq; + + seq = kzalloc(sizeof(*seq), GFP_NOFS); + if (seq) { + /* todo: necessary? */ + /* mutex_init(&seq.lock); */ + seq->buf = p; + seq->size = len; + return seq; /* success */ + } + + seq = ERR_PTR(-ENOMEM); + AuTraceErrPtr(seq); + return seq; +} + +/* todo: file size may exceed PAGE_SIZE */ +ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + ssize_t err; + struct au_sbinfo *sbinfo; + struct super_block *sb; + struct seq_file *seq; + char *name; + struct attribute **cattr; + + LKTRTrace("%s/%s\n", kobject_name(kobj), attr->name); + + sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); + sb = sbinfo->si_sb; + si_noflush_read_lock(sb); + + seq = au_seq(buf, PAGE_SIZE); + err = PTR_ERR(seq); + if (IS_ERR(seq)) + goto out; + + name = (void *)attr->name; + cattr = au_sbi_attrs; + while (*cattr) { + if (!strcmp(name, (*cattr)->name)) { + err = container_of(*cattr, struct au_sbi_attr, attr) + ->show(seq, sb); + goto out_seq; + } + cattr++; + } + + if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) { + name += sizeof(SysaufsBr_PREFIX) - 1; + err = sysaufs_sbi_br(seq, sb, simple_strtol(name, NULL, 10)); + goto out_seq; + } + BUG(); + + out_seq: + if (!err) { + err = seq->count; + /* sysfs limit */ + if (unlikely(err == PAGE_SIZE)) + err = -EFBIG; + } + kfree(seq); + out: + si_read_unlock(sb); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +void sysaufs_br_init(struct au_branch *br) +{ + br->br_attr.name = br->br_name; + br->br_attr.mode = S_IRUGO; + br->br_attr.owner = THIS_MODULE; +} + +void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) +{ + struct au_sbinfo *sbinfo; + aufs_bindex_t bend; + + LKTRTrace("b%d\n", bindex); + + if (!sysaufs_brs) + return; + + sbinfo = au_sbi(sb); + bend = au_sbend(sb); + for (; bindex <= bend; bindex++) + sysfs_remove_file(&sbinfo->si_kobj, + &au_sbr(sb, bindex)->br_attr); +} + +void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) +{ + int err; + struct kobject *kobj; + aufs_bindex_t bend; + struct au_branch *br; + + LKTRTrace("b%d\n", bindex); + + if (!sysaufs_brs) + return; + + kobj = &au_sbi(sb)->si_kobj; + bend = au_sbend(sb); + for (; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + snprintf(br->br_name, sizeof(br->br_name), + SysaufsBr_PREFIX "%d", bindex); + err = sysfs_create_file(kobj, &br->br_attr); + if (unlikely(err)) + AuWarn("failed %s under sysfs(%d)\n", br->br_name, err); + } +} --- linux-2.6.27.orig/ubuntu/aufs/Kconfig +++ linux-2.6.27/ubuntu/aufs/Kconfig @@ -0,0 +1,265 @@ +config AUFS + tristate "Another unionfs" + help + Aufs is a stackable unification filesystem such as Unionfs, + which unifies several directories and provides a merged single + directory. + In the early days, aufs was entirely re-designed and + re-implemented Unionfs Version 1.x series. After many original + ideas, approaches and improvements, it becomes totally + different from Unionfs while keeping the basic features. + See Unionfs for the basic features. +if AUFS +comment "These options are for 2.6.27-3-generic" +choice + prompt "Maximum number of branches" + default AUFS_BRANCH_MAX_127 + help + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance. +config AUFS_BRANCH_MAX_127 + bool "127" + help + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance. +config AUFS_BRANCH_MAX_511 + bool "511" + help + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance. +config AUFS_BRANCH_MAX_1023 + bool "1023" + help + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance. +config AUFS_BRANCH_MAX_32767 + bool "32767" + help + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance. +endchoice +config AUFS_STAT + bool "Use /fs/aufs/stat" + depends on SYSFS + help + Shows some statistic data via /fs/aufs/stat. + See detail in aufs.5. +comment "SYSFS and AUFS_STAT are disabled" + depends on SYSFS = n +config AUFS_HINOTIFY + bool "Use inotify to detect actions on a branch" + depends on INOTIFY + help + If you want to modify files on branches directly, eg. bypassing aufs, + and want aufs to detect the changes of them fully, then enable this + option and use 'udba=inotify' mount option. + It will have a negative impact to the performance. + See detail in aufs.5. +comment "INOTIFY and AUFS_HINOTIFY are disabled" + depends on INOTIFY = n +config AUFS_EXPORT + bool "NFS-exportable aufs" + depends on (AUFS = y && EXPORTFS = y) || (AUFS = m && EXPORTFS) + help + If you want to export your mounted aufs, then enable this + option. There are several requirements to export aufs. + See detail in aufs.5. +comment "EXPORTFS and AUFS_EXPORT are disabled" + depends on EXPORTFS = n +comment "AUFS_EXPORT is disabled since EXPORTFS is a module but AUFS" + depends on EXPORTFS = m && AUFS = y +config AUFS_INO_T_64 + bool + depends on 64BIT && !(ALPHA || S390) + default y +config AUFS_ROBR + bool "Aufs as an readonly branch of another aufs mount" + help + If you want make your aufs to be a part of another aufs, then + enable this option. In other words, you can specify your aufs + path in 'br:' mount option for another aufs, but cannot + specify 'rw' as the branch permission. + It will have a negative impact to the performance. + See detail in aufs.5. +config AUFS_DLGT + bool "Delegate the internal branch access the kernel thread" + help + If you want aufs to delegate + the internal access to the branches which is made by aufs, to + the kernel thread, in order to hide the access issued by your + application from your LSM or something or make your + application to be traced strictly by the task I/O accounting, + then enable this option and use 'dlgt' mount option. + It will have a negative impact to the performance. + See detail in aufs.5. +config AUFS_HIN_OR_DLGT + bool + depends on AUFS_HINOTIFY || AUFS_DLGT + default y + help + Automatic configuration for internal use. +config AUFS_SHWH + bool "Show whiteouts" + help + If you want to make the whiteouts in aufs visible, then enable + this option and specify 'shwh' mount option. Although it may + sounds like philosophy or something, but in technically it + simply shows the name of whiteout with keeping its behaviour. +config AUFS_RR_SQUASHFS + bool "Make squashfs branch RR (real readonly) by default" + default y + help + If you use squashfs or LZMA patched squashfs as an aufs branch + and want to set '=rr' to it by default, then enable this + configuration. + 'rr' stands for real readonly and it optimizes some aspects of + 'ro.' + See detail in aufs.5. +config AUFS_SEC_PERM_PATCH + bool "sec_perm-2.6.24.patch was applied or not" + depends on AUFS = m + depends on SECURITY + help + If you build aufs as a module and enabled CONFIG_SECURITY, + then you need to apply the patch + 'CVS_TREE/aufs/patch/sec_perm-2.6.24.patch' to your kernel + source, and enable this configuration. + The sec_perm-2.6.24.patch exports a kernel function + security_inode_permission() to modules. +comment "SECURITY and AUFS_SEC_PERM_PATCH are disabled" + depends on SECURITY = n +config AUFS_SPLICE_PATCH + bool "splice.patch for sendfile(2) and splice(2)" + help + If you use 'loopback mount' on a fs-image file, or use + splice(2) or sendfile(2) systemcall in aufs, then you need to + apply the patch 'CVS_TREE/aufs/patch/splice.patch' to your + kernel source, and enable this configuration. + The splice.patch makes the kernel function do_splice_to/from() + global and exports them to modules. +config AUFS_PUT_FILP_PATCH + bool "put_filp.patch for NFS branch" + depends on AUFS = m + depends on NFS_FS + help + If you build aufs as a module and use mounted NFS as an aufs + branch filesystem, then you need to apply the patch + 'CVS_TREE/aufs/patch/put_filp.patch' to your kernel source, + and enable this configuration. + The put_filp.patch exports a kernel function put_filp() to + modules. +comment "NFS_FS and AUFS_PUT_FILP_PATCH are disabled" + depends on NFS_FS = n +config AUFS_LHASH_PATCH + bool "lhash.patch for NFS branch" + depends on NFS_FS + help + If you use mounted NFS as an aufs branch filesystem, then you + need to apply the patch 'CVS_TREE/aufs/patch/lhash.patch' (or + lhash-2.6.22.patch for linux-2.6.22 and later) to your kernel + source, and enable this configuration. + The patch file makes the kernel function __lookup_hash() global + and exports it to modules. +comment "NFS_FS and AUFS_LHASH_PATCH are disabled" + depends on NFS_FS = n +config AUFS_BR_NFS + bool + depends on NFS_FS + default n if (!AUFS_LHASH_PATCH || !(AUFS = y || AUFS_PUT_FILP_PATCH)) + default y + help + Automatic configuration for internal use. + When aufs supports NFS branch, enabled automatically. +config AUFS_BR_XFS + bool + depends on XFS_FS + default y + help + Automatic configuration for internal use. + When aufs supports XFS branch, enabled automatically. +config AUFS_FSYNC_SUPER_PATCH + bool "fsync_super-2.6.xx.patch was applied or not" + depends on AUFS = m + help + If you build aufs as a module and want to flush everything for + branch filesystems which are not marked as 'rr' nor 'rr+wh' at + umount or remount time, then you need to apply the patch + 'CVS_TREE/aufs/patch/fsync_super-2.6.16.patch' or + '...-2.6.19.patch' to your kernel source, and enable this + configuration. + It may be helpful at shutdown time in case of your aufs is a + root filesystem. But this behaviour will not guarantee the + consistency of branch filesystems. To guarantee it, try the + approach described in the aufs manual, and do not forget + installing auplink script. + The fsync_super-2.6.xx.patch does nothing but exports a kernel + function fsync_super() to modules. +config AUFS_DENY_WRITE_ACCESS_PATCH + bool "deny_write_access.patch was applied or not" + depends on AUFS = m + help + A security enhancement to deny writing to a running executable + which exists on an aufs branch filesystem and executed through + aufs. If you applied + 'CVS_TREE/aufs/patch/deny_write_access.patch' to your kernel + and you are compiling aufs as a module, then enable this + option. + The write_deny_access.patch does nothing but export the + function. +config AUFS_WORKAROUND_FUSE + bool "Special handling for FUSE-based filesystem" + depends on FUSE_FS + help + A FUSE-based filesystem may not initialize its inode + attributes and the FUSE developer thinks the inode attributes + in a positive dentry which is returned by VFS lookup operation + are not reliable. + If you use a FUSE-based filesystem as an aufs branch, and it + customizes the inode attribute on it without overriding + fuse_lowlevel_ops.lookup, probably you need to enable this + configuration. + If you enable this configuration, aufs calls getattr operation + in every lookup and revalidate operation for the FUSE-based + filesystem branch. + It will have a negative impact to the performance even if you do + not use a FUSE-based filesystem branch. +config AUFS_HIN_OR_FUSE + bool + depends on AUFS_HINOTIFY || AUFS_WORKAROUND_FUSE + default y + help + Automatic configuration for internal use. +config AUFS_DEBUG + bool "Debug aufs" + default y + help + Enable this to compile aufs internal debug code. + It will have a negative impact to the performance. +config AUFS_MAGIC_SYSRQ + bool + depends on AUFS_DEBUG && MAGIC_SYSRQ + default y + help + Automatic configuration for internal use. + When aufs supports Magic SysRq, enabled automatically. +config AUFS_COMPAT + bool "Compatibility with Unionfs (obsolete)" + help + This makes aufs compatible with unionfs-style mount options and some + behaviours. + The dirs= mount option and =nfsro branch permission flag are always + interpreted as br: mount option and =ro flag respectively. The + 'debug', 'delete' and 'imap' mount options are ignored. + If you disable this option, you will get, + - aufs issues a warning about the ignored mount options + - the default branch permission flag is set. RW for the first branch, + and RO for the rests. + - the name of a internal file which represents the directory is + 'opaque', becomes '.wh..wh..opq' + - the 'diropq=w' mount option is set by default +config AUFS_UNIONFS22_PATCH + bool "Unionfs-2.2 or later patch is applied or not (obsolete)" + help + Unionfs version 2.2 (and later) patch introduces some changes in VFS layer which has an impact to aufs. If you have applied such patch to your kernel, you need to enable this configuration even if you disabled CONFIG_UNIONFS. +config AUFS_UNIONFS23_PATCH + bool "Unionfs-2.3 or later patch is applied or not (obsolete)" + select AUFS_SPLICE_PATCH + select AUFS_UNIONFS22_PATCH + help + Unionfs version 2.3 (and later) patch introduces some changes in VFS layer which has an impact to aufs. If you have applied such patch to your kernel, you need to enable this configuration even if you disabled CONFIG_UNIONFS. +endif --- linux-2.6.27.orig/ubuntu/aufs/debug.c +++ linux-2.6.27/ubuntu/aufs/debug.c @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * debug print functions + * + * $Id: debug.c,v 1.14 2008/09/22 03:52:03 sfjro Exp $ + */ + +#include "aufs.h" + +atomic_t au_cond = ATOMIC_INIT(0); + +char *au_plevel = KERN_DEBUG; +#define dpri(fmt, arg...) do { \ + if (LktrCond) \ + printk("%s" fmt, au_plevel, ##arg); \ +} while (0) + +/* ---------------------------------------------------------------------- */ + +void au_dpri_whlist(struct au_nhash *whlist) +{ + int i; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + + for (i = 0; i < AuSize_NHASH; i++) { + head = whlist->heads + i; + hlist_for_each_entry(tpos, pos, head, wh_hash) + dpri("b%d, %.*s, %d\n", + tpos->wh_bindex, + tpos->wh_str.len, tpos->wh_str.name, + tpos->wh_str.len); + } +} + +void au_dpri_vdir(struct au_vdir *vdir) +{ + int i; + union au_vdir_deblk_p p; + unsigned char *o; + + if (!vdir || IS_ERR(vdir)) { + dpri("err %ld\n", PTR_ERR(vdir)); + return; + } + + dpri("nblk %d, deblk %p, last{%d, %p}, ver %lu\n", + vdir->vd_nblk, vdir->vd_deblk, + vdir->vd_last.i, vdir->vd_last.p.p, vdir->vd_version); + for (i = 0; i < vdir->vd_nblk; i++) { + p.deblk = vdir->vd_deblk[i]; + o = p.p; + dpri("[%d]: %p\n", i, o); + } +} + +static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, + struct dentry *wh) +{ + char *n = NULL; + int l = 0, ntfy = 0; + + if (!inode || IS_ERR(inode)) { + dpri("i%d: err %ld\n", bindex, PTR_ERR(inode)); + return -1; + } + + /* the type of i_blocks depends upon CONFIG_LSF */ + BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long) + && sizeof(inode->i_blocks) != sizeof(u64)); + if (wh) { + n = (void *)wh->d_name.name; + l = wh->d_name.len; + } + + ntfy = au_test_inotify(inode); + dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, ntfy %d, sz %llu, blk %llu," + " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n", + bindex, + inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??", + atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode, + ntfy, + i_size_read(inode), (unsigned long long)inode->i_blocks, + (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff, + inode->i_mapping ? inode->i_mapping->nrpages : 0, + inode->i_state, inode->i_flags, inode->i_generation, + l ? ", wh " : "", l, n); + return 0; +} + +void au_dpri_inode(struct inode *inode) +{ + struct au_iinfo *iinfo; + aufs_bindex_t bindex; + int err; + + err = do_pri_inode(-1, inode, NULL); + if (err || !au_test_aufs(inode->i_sb)) + return; + + iinfo = au_ii(inode); + if (!iinfo) + return; + dpri("i-1: bstart %d, bend %d, gen %d\n", + iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode)); + if (iinfo->ii_bstart < 0) + return; + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++) + do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode, + iinfo->ii_hinode[0 + bindex].hi_whdentry); +} + +static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry, + struct list_head *intent) +{ + struct dentry *wh = NULL; + + if (!dentry || IS_ERR(dentry)) { + dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry)); + return -1; + } + /* do not call dget_parent() here */ + dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x, intent %d\n", + bindex, + AuDLNPair(dentry->d_parent), AuDLNPair(dentry), + dentry->d_sb ? au_sbtype(dentry->d_sb) : "??", + atomic_read(&dentry->d_count), dentry->d_flags, !!intent); + if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) { + struct au_iinfo *iinfo = au_ii(dentry->d_inode); + if (iinfo) + wh = iinfo->ii_hinode[0 + bindex].hi_whdentry; + } + do_pri_inode(bindex, dentry->d_inode, wh); + return 0; +} + +static struct list_head *au_dbg_h_intent(struct au_dinfo *dinfo, + aufs_bindex_t bindex) +{ +#ifdef CONFIG_AUFS_BR_NFS + return dinfo->di_hdentry[0 + bindex].hd_intent_list; +#else + return NULL; +#endif +} + +void au_dpri_dentry(struct dentry *dentry) +{ + struct au_dinfo *dinfo; + aufs_bindex_t bindex; + int err; + + err = do_pri_dentry(-1, dentry, NULL); + if (err || !au_test_aufs(dentry->d_sb)) + return; + + dinfo = au_di(dentry); + if (!dinfo) + return; + dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n", + dinfo->di_bstart, dinfo->di_bend, + dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry)); + if (dinfo->di_bstart < 0) + return; + for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++) + do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry, + au_dbg_h_intent(dinfo, bindex)); +} + +static int do_pri_file(aufs_bindex_t bindex, struct file *file) +{ + char a[32]; + + if (!file || IS_ERR(file)) { + dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); + return -1; + } + a[0] = 0; + if (bindex < 0 + && file->f_dentry + && au_test_aufs(file->f_dentry->d_sb) + && au_fi(file)) + snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file)); + dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n", + bindex, file->f_mode, file->f_flags, (long)file_count(file), + file->f_pos, a); + if (file->f_dentry) + do_pri_dentry(bindex, file->f_dentry, NULL); + return 0; +} + +void au_dpri_file(struct file *file) +{ + struct au_finfo *finfo; + aufs_bindex_t bindex; + int err; + + err = do_pri_file(-1, file); + if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb)) + return; + + finfo = au_fi(file); + if (!finfo) + return; + if (finfo->fi_bstart < 0) + return; + for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) { + struct au_hfile *hf; + hf = finfo->fi_hfile + bindex; + do_pri_file(bindex, hf ? hf->hf_file : NULL); + } +} + +static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br) +{ + struct vfsmount *mnt; + struct super_block *sb; + + if (!br || IS_ERR(br) + || !(mnt = br->br_mnt) || IS_ERR(mnt) + || !(sb = mnt->mnt_sb) || IS_ERR(sb)) { + dpri("s%d: err %ld\n", bindex, PTR_ERR(br)); + return -1; + } + + dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, " + "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, " + "xino %d\n", + bindex, br->br_perm, au_br_count(br), br->br_wbr, + au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev), + sb->s_flags, sb->s_count - S_BIAS, + atomic_read(&sb->s_active), !!br->br_xino.xi_file); + return 0; +} + +void au_dpri_sb(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + aufs_bindex_t bindex; + int err; + /* to reuduce stack size */ + struct { + struct vfsmount mnt; + struct au_branch fake; + } *a; + + /* this function can be called from magic sysrq */ + a = kzalloc(sizeof(*a), GFP_ATOMIC); + if (unlikely(!a)) { + dpri("no memory\n"); + return; + } + + a->mnt.mnt_sb = sb; + a->fake.br_perm = 0; + a->fake.br_mnt = &a->mnt; + a->fake.br_xino.xi_file = NULL; + atomic_set(&a->fake.br_count, 0); + smp_mb(); /* atomic_set */ + err = do_pri_br(-1, &a->fake); + kfree(a); + dpri("dev 0x%x\n", sb->s_dev); + if (err || !au_test_aufs(sb)) + return; + + sbinfo = au_sbi(sb); + if (!sbinfo) + return; + dpri("gen %u\n", sbinfo->si_generation); + for (bindex = 0; bindex <= sbinfo->si_bend; bindex++) + do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); +} + +/* ---------------------------------------------------------------------- */ + +void au_dbg_sleep(int sec) +{ + static DECLARE_WAIT_QUEUE_HEAD(wq); + wait_event_timeout(wq, 0, sec * HZ); +} + +void au_dbg_sleep_jiffy(int jiffy) +{ + static DECLARE_WAIT_QUEUE_HEAD(wq); + wait_event_timeout(wq, 0, jiffy); +} + +void au_dbg_iattr(struct iattr *ia) +{ +#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) dpri(#name "\n") + AuBit(MODE); + AuBit(UID); + AuBit(GID); + AuBit(SIZE); + AuBit(ATIME); + AuBit(MTIME); + AuBit(CTIME); + AuBit(ATIME_SET); + AuBit(MTIME_SET); + AuBit(FORCE); + AuBit(ATTR_FLAG); + AuBit(KILL_SUID); + AuBit(KILL_SGID); + AuBit(FILE); + AuBit(KILL_PRIV); + AuBit(OPEN); + AuBit(TIMES_SET); +#undef AuBit + dpri("ia_file %p\n", ia->ia_file); +} + +/* ---------------------------------------------------------------------- */ + +void au_debug_sbinfo_init(struct au_sbinfo *sbinfo) +{ +#ifdef ForceInotify + au_opt_set_udba(sbinfo->si_mntflags, UDBA_INOTIFY); +#endif +#ifdef ForceDlgt + au_opt_set(sbinfo->si_mntflags, DLGT); +#endif +#ifdef ForceNoPlink + au_opt_clr(sbinfo->si_mntflags, PLINK); +#endif +#ifdef ForceNoXino + au_opt_clr(sbinfo->si_mntflags, XINO); +#endif +#ifdef ForceNoRefrof + au_opt_clr(sbinfo->si_mntflags, REFROF); +#endif +#ifdef ForceShwh + au_opt_set(sbinfo->si_mntflags, SHWH); +#endif +} + +int __init au_debug_init(void) +{ + aufs_bindex_t bindex; + struct au_vdir_destr destr; + + bindex = -1; + AuDebugOn(bindex >= 0); + + destr.len = -1; + AuDebugOn(destr.len < NAME_MAX); + +#ifdef CONFIG_4KSTACKS + AuWarn("CONFIG_4KSTACKS is defined.\n"); +#endif + +#ifdef ForceBrs + sysaufs_brs = 1; +#endif + +#if 0 /* verbose debug */ + { + union { + struct au_branch *br; + struct au_dinfo *di; + struct au_finfo *fi; + struct au_iinfo *ii; + struct au_hinode *hi; + struct au_sbinfo *si; + struct au_vdir_destr *destr; + struct au_vdir_de *de; + struct au_vdir_wh *wh; + struct au_vdir *vd; + } u; + + pr_info("br{" + "xino %d, " + "id %d, perm %d, mnt %d, count %d, " + "wbr %d, " + "xup %d, xrun %d, " + "gen %d, " + "sa %d} %d\n", + offsetof(typeof(*u.br), br_xino), + offsetof(typeof(*u.br), br_id), + offsetof(typeof(*u.br), br_perm), + offsetof(typeof(*u.br), br_mnt), + offsetof(typeof(*u.br), br_count), + offsetof(typeof(*u.br), wbr), + offsetof(typeof(*u.br), br_xino_upper), + offsetof(typeof(*u.br), br_xino_running), + offsetof(typeof(*u.br), br_generation), + offsetof(typeof(*u.br), br_sabr), + sizeof(*u.br)); + pr_info("di{gen %d, rwsem %d, bstart %d, bend %d, bwh %d, " + "bdiropq %d, hdentry %d} %d\n", + offsetof(typeof(*u.di), di_generation), + offsetof(typeof(*u.di), di_rwsem), + offsetof(typeof(*u.di), di_bstart), + offsetof(typeof(*u.di), di_bend), + offsetof(typeof(*u.di), di_bwh), + offsetof(typeof(*u.di), di_bdiropq), + offsetof(typeof(*u.di), di_hdentry), + sizeof(*u.di)); + pr_info("fi{gen %d, rwsem %d, hfile %d, bstart %d, bend %d, " + "h_vm_ops %d, vdir_cach %d} %d\n", + offsetof(typeof(*u.fi), fi_generation), + offsetof(typeof(*u.fi), fi_rwsem), + offsetof(typeof(*u.fi), fi_hfile), + offsetof(typeof(*u.fi), fi_bstart), + offsetof(typeof(*u.fi), fi_bend), + offsetof(typeof(*u.fi), fi_h_vm_ops), + offsetof(typeof(*u.fi), fi_vdir_cache), + sizeof(*u.fi)); + pr_info("ii{gen %d, hsb %d, " + "rwsem %d, bstart %d, bend %d, hinode %d, vdir %d} " + "%d\n", + offsetof(typeof(*u.ii), ii_generation), + offsetof(typeof(*u.ii), ii_hsb1), + offsetof(typeof(*u.ii), ii_rwsem), + offsetof(typeof(*u.ii), ii_bstart), + offsetof(typeof(*u.ii), ii_bend), + offsetof(typeof(*u.ii), ii_hinode), + offsetof(typeof(*u.ii), ii_vdir), + sizeof(*u.ii)); + pr_info("hi{inode %d, id %d, notify %d, wh %d} %d\n", + offsetof(typeof(*u.hi), hi_inode), + offsetof(typeof(*u.hi), hi_id), + offsetof(typeof(*u.hi), hi_notify), + offsetof(typeof(*u.hi), hi_whdentry), + sizeof(*u.hi)); + pr_info("si{nwt %d, rwsem %d, gen %d, stat %d, " + "bend %d, last id %d, br %d, " + "cpup %d, creat %d, ops %d, ops %d, " + "rr %d, mfs %d, " + "mntflags %d, " + "xread %d, xwrite %d, xib %d, xmtx %d, buf %d, " + "xlast %d, xnext %d, " + "rdcache %d, " + "dirwh %d, " + "pl_lock %d, pl %d, " + "mnt %d, " + "sys %d, " + /* "lvma_l %d, lvma %d" */ + "} %d\n", + offsetof(typeof(*u.si), si_nowait), + offsetof(typeof(*u.si), si_rwsem), + offsetof(typeof(*u.si), si_generation), + offsetof(typeof(*u.si), au_si_status), + offsetof(typeof(*u.si), si_bend), + offsetof(typeof(*u.si), si_last_br_id), + offsetof(typeof(*u.si), si_branch), + offsetof(typeof(*u.si), si_wbr_copyup), + offsetof(typeof(*u.si), si_wbr_create), + offsetof(typeof(*u.si), si_wbr_copyup_ops), + offsetof(typeof(*u.si), si_wbr_create_ops), + offsetof(typeof(*u.si), si_wbr_rr_next), + offsetof(typeof(*u.si), si_wbr_mfs), + offsetof(typeof(*u.si), si_mntflags), + offsetof(typeof(*u.si), si_xread), + offsetof(typeof(*u.si), si_xwrite), + offsetof(typeof(*u.si), si_xib), + offsetof(typeof(*u.si), si_xib_mtx), + offsetof(typeof(*u.si), si_xib_buf), + offsetof(typeof(*u.si), si_xib_last_pindex), + offsetof(typeof(*u.si), si_xib_next_bit), + offsetof(typeof(*u.si), si_rdcache), + offsetof(typeof(*u.si), si_dirwh), + offsetof(typeof(*u.si), si_plink_lock), + offsetof(typeof(*u.si), si_plink), + offsetof(typeof(*u.si), si_mnt), + offsetof(typeof(*u.si), si_sa), + /*offsetof(typeof(*u.si), si_lvma_lock), + offsetof(typeof(*u.si), si_lvma),*/ + sizeof(*u.si)); + pr_info("destr{len %d, name %d} %d\n", + offsetof(typeof(*u.destr), len), + offsetof(typeof(*u.destr), name), + sizeof(*u.destr)); + pr_info("de{ino %d, type %d, str %d} %d\n", + offsetof(typeof(*u.de), de_ino), + offsetof(typeof(*u.de), de_type), + offsetof(typeof(*u.de), de_str), + sizeof(*u.de)); + pr_info("wh{hash %d, bindex %d, str %d} %d\n", + offsetof(typeof(*u.wh), wh_hash), + offsetof(typeof(*u.wh), wh_bindex), + offsetof(typeof(*u.wh), wh_str), + sizeof(*u.wh)); + pr_info("vd{deblk %d, nblk %d, last %d, ver %d, jiffy %d} %d\n", + offsetof(typeof(*u.vd), vd_deblk), + offsetof(typeof(*u.vd), vd_nblk), + offsetof(typeof(*u.vd), vd_last), + offsetof(typeof(*u.vd), vd_version), + offsetof(typeof(*u.vd), vd_jiffy), + sizeof(*u.vd)); + } +#endif + + return 0; +} --- linux-2.6.27.orig/ubuntu/aufs/hin_or_fuse.c +++ linux-2.6.27/ubuntu/aufs/hin_or_fuse.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode attributes on FUSE branch or HINOTIFY + * + * $Id: hin_or_fuse.c,v 1.6 2008/09/15 03:14:30 sfjro Exp $ + */ + +#include "aufs.h" + +static struct dentry * +au_h_dget_any(struct dentry *dentry, aufs_bindex_t *bindex) +{ + struct dentry *h_dentry; + struct inode *inode, *h_inode; + struct super_block *sb; + aufs_bindex_t ib, db; + + /* must be positive dentry */ + inode = dentry->d_inode; + LKTRTrace("%.*s, i%lu\n", AuDLNPair(dentry), inode->i_ino); + + sb = dentry->d_sb; + db = au_dbstart(dentry); + ib = au_ibstart(inode); + if (db == ib) { + *bindex = db; + h_dentry = dget(au_h_dptr(dentry, db)); + if (h_dentry) + goto out; /* success */ + } + + *bindex = ib; + h_inode = au_h_iptr(inode, ib); + h_dentry = d_find_alias(h_inode); + if (h_dentry) + goto out; /* success */ + +#if 0 + if (au_opt_test(au_mntflags(sb), PLINK) + && au_plink_test(sb, inode)) { + h_dentry = au_plink_lkup(sb, ib, inode); + if (IS_ERR(h_dentry)) + goto out; + AuDebugOn(!h_dentry->d_inode); + goto out; /* success */ + } +#endif + + h_dentry = dget(au_hi_wh(inode, ib)); + + out: + AuTraceErrPtr(h_dentry); + return h_dentry; +} + +int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st) +{ + int err; + unsigned int mnt_flags; + aufs_bindex_t bindex; + struct inode *inode; + struct dentry *h_dentry; + struct super_block *sb, *h_sb; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + err = 0; + inode = dentry->d_inode; + sb = dentry->d_sb; + aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR); + + /* todo: nfs branch too? */ + /* todo: test bit inotify option too? */ + mnt_flags = au_mntflags(sb); + bindex = au_ibstart(inode); + h_sb = au_sbr_sb(sb, bindex); + if (!au_test_fuse(h_sb) + //&& !au_test_nfs(h_sb) /* todo: fix me */ + && (au_iigen(inode) == au_sigen(sb) + || (au_opt_test(mnt_flags, PLINK) && au_plink_test(sb, inode)))) + goto fill; + + h_dentry = au_h_dget_any(dentry, &bindex); + err = PTR_ERR(h_dentry); + if (IS_ERR(h_dentry)) + goto out; + + err = -EIO; + if (h_dentry && h_dentry->d_inode) + err = vfsub_getattr(au_sbr_mnt(sb, bindex), h_dentry, st, + au_test_dlgt(mnt_flags)); + dput(h_dentry); + if (!err) { + au_cpup_attr_all(inode); + fill: + generic_fillattr(inode, st); + } + + out: + aufs_read_unlock(dentry, AuLock_IR); + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/branch.c +++ linux-2.6.27/ubuntu/aufs/branch.c @@ -0,0 +1,1025 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * branch management + * + * $Id: branch.c,v 1.16 2008/09/08 02:39:41 sfjro Exp $ + */ + +#include +#include +#include +#include +#include "aufs.h" + +static void au_br_do_free(struct au_branch *br) +{ + int i; + struct au_wbr *wbr; + + AuTraceEnter(); + + if (br->br_xino.xi_file) + fput(br->br_xino.xi_file); + wbr = br->br_wbr; + if (wbr) + for (i = 0; i < AuBrWh_Last; i++) + dput(wbr->wbr_wh[i]); + /* do not call au_br_nfs_lockdep_off() here */ + if (!au_test_nfs(br->br_mnt->mnt_sb)) + mntput(br->br_mnt); + else { + lockdep_off(); + mntput(br->br_mnt); + lockdep_on(); + } + AuDebugOn(au_br_count(br)); + if (wbr) + AuDebugOn(atomic_read(&wbr->wbr_wh_running)); + kfree(wbr); + kfree(br); +} + +/* + * frees all branches + */ +void au_br_free(struct au_sbinfo *sbinfo) +{ + aufs_bindex_t bmax; + struct au_branch **br; + + AuTraceEnter(); + bmax = sbinfo->si_bend + 1; + br = sbinfo->si_branch; + while (bmax--) + au_br_do_free(*br++); +} + +/* + * find the index of a branch which is specified by @br_id. + */ +int au_br_index(struct super_block *sb, aufs_bindex_t br_id) +{ + aufs_bindex_t bindex, bend; + + AuTraceEnter(); + + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) + if (au_sbr_id(sb, bindex) == br_id) + return bindex; + return -1; +} + +/* + * test if the @h_sb is real-readonly. + */ +int au_test_def_rr(struct super_block *h_sb) +{ + switch (h_sb->s_magic) { +#ifdef CONFIG_AUFS_RR_SQUASHFS + case SQUASHFS_MAGIC_LZMA: + case SQUASHFS_MAGIC: + case SQUASHFS_MAGIC_LZMA_SWAP: + case SQUASHFS_MAGIC_SWAP: + return 1; /* real readonly */ +#endif + +#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE) + case ISOFS_SUPER_MAGIC: + return 1; +#endif + +#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE) + case CRAMFS_MAGIC: + return 1; +#endif + +#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE) + case ROMFS_MAGIC: + return 1; +#endif + + default: + return 0; + } +} + +/* ---------------------------------------------------------------------- */ + +/* + * test if two hidden_dentries have overlapping branches. + */ +static int do_test_overlap(struct super_block *sb, struct dentry *h_d1, + struct dentry *h_d2) +{ + struct dentry *d; + + LKTRTrace("%.*s, %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2)); + + d = au_test_subdir(h_d1, h_d2); + if (unlikely(d)) { + AuDbgDentry(h_d1); + AuDbgDentry(h_d2); + } + return !!d; +} + +static int test_overlap_loopback(struct super_block *sb, struct dentry *h_d1, + struct dentry *h_d2) +{ +#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE) + struct inode *h_inode; + struct loop_device *l; + + LKTRTrace("%.*s, %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2)); + AuDbgDentry(h_d1); + AuDbgDentry(h_d2); + AuDbgSb(h_d1->d_sb); + AuDbgSb(h_d2->d_sb); + + h_inode = h_d1->d_inode; + if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR) + return 0; + + l = h_inode->i_sb->s_bdev->bd_disk->private_data; + h_d1 = l->lo_backing_file->f_dentry; + /* h_d1 can be local NFS. in this case aufs cannot detect the loop */ + AuDbgDentry(h_d1); + AuDbgDentry(h_d2); + AuDbgSb(h_d1->d_sb); + AuDbgSb(h_d2->d_sb); + if (unlikely(h_d1->d_sb == sb)) + return 1; + return do_test_overlap(sb, h_d1, h_d2); +#else + return 0; +#endif +} + +static int test_overlap(struct super_block *sb, struct dentry *h_d1, + struct dentry *h_d2) +{ + LKTRTrace("d1 %.*s, d2 %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2)); + + if (unlikely(h_d1 == h_d2)) { + AuDbgDentry(h_d1); + AuDbgDentry(h_d2); + return 1; + } + return do_test_overlap(sb, h_d1, h_d2) + || do_test_overlap(sb, h_d2, h_d1) + || test_overlap_loopback(sb, h_d1, h_d2) + || test_overlap_loopback(sb, h_d2, h_d1); +} + +/* ---------------------------------------------------------------------- */ + +static int au_br_init_wh(struct super_block *sb, aufs_bindex_t bindex, + struct au_branch *br, int new_perm, + struct dentry *h_root, struct vfsmount *h_mnt) +{ + int err, old_perm; + struct inode *h_dir; + struct au_wbr *wbr; + + LKTRTrace("b%d, new_perm %d\n", bindex, new_perm); + + wbr = br->br_wbr; + h_dir = h_root->d_inode; + old_perm = br->br_perm; + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + if (wbr) + wbr_wh_write_lock(wbr); + br->br_perm = new_perm; + err = au_wh_init(h_root, br, au_do_nfsmnt(h_mnt), sb, bindex); + br->br_perm = old_perm; + if (wbr) + wbr_wh_write_unlock(wbr); + mutex_unlock(&h_dir->i_mutex); + if (!err && wbr && !au_br_writable(new_perm)) { + AuDebugOn(wbr->wbr_whbase); + AuDebugOn(wbr->wbr_plink); + AuDebugOn(wbr->wbr_tmp); + kfree(wbr); + br->br_wbr = NULL; + } + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * returns a newly allocated branch. @new_nbranch is a number of branches + * after adding a branch. + */ +static struct au_branch *alloc_addbr(struct super_block *sb, int new_nbranch, + int perm) +{ + struct au_branch **branchp, *add_branch; + int sz; + void *p; + struct dentry *root; + struct inode *inode; + struct au_hinode *hinodep; + struct au_hdentry *hdentryp; + + LKTRTrace("new_nbranch %d\n", new_nbranch); + SiMustWriteLock(sb); + root = sb->s_root; + DiMustWriteLock(root); + inode = root->d_inode; + IiMustWriteLock(inode); + + add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS); + if (unlikely(!add_branch)) + goto out; + add_branch->br_wbr = NULL; + if (unlikely(au_br_writable(perm))) { + add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr), + GFP_NOFS); + if (unlikely(!add_branch->br_wbr)) + goto out_br; + } + + sz = sizeof(*branchp) * (new_nbranch - 1); + if (unlikely(!sz)) + sz = sizeof(*branchp); + p = au_sbi(sb)->si_branch; + branchp = au_kzrealloc(p, sz, sizeof(*branchp) * new_nbranch, GFP_NOFS); + if (unlikely(!branchp)) + goto out_wbr; + au_sbi(sb)->si_branch = branchp; + + sz = sizeof(*hdentryp) * (new_nbranch - 1); + if (unlikely(!sz)) + sz = sizeof(*hdentryp); + p = au_di(root)->di_hdentry; + hdentryp = au_kzrealloc(p, sz, sizeof(*hdentryp) * new_nbranch, + GFP_NOFS); + if (unlikely(!hdentryp)) + goto out_wbr; + au_di(root)->di_hdentry = hdentryp; + + sz = sizeof(*hinodep) * (new_nbranch - 1); + if (unlikely(!sz)) + sz = sizeof(*hinodep); + p = au_ii(inode)->ii_hinode; + hinodep = au_kzrealloc(p, sz, sizeof(*hinodep) * new_nbranch, GFP_NOFS); + if (unlikely(!hinodep)) + goto out_wbr; + au_ii(inode)->ii_hinode = hinodep; + return add_branch; /* success */ + + out_wbr: + kfree(add_branch->br_wbr); + out_br: + kfree(add_branch); + out: + AuTraceErr(-ENOMEM); + return ERR_PTR(-ENOMEM); +} + +/* + * test if the branch permission is legal or not. + */ +static int test_br(struct super_block *sb, struct inode *inode, int brperm, + char *path) +{ + int err; + + err = 0; + if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) { + AuErr("write permission for readonly fs or inode, %s\n", path); + err = -EINVAL; + } + + AuTraceErr(err); + return err; +} + +static int au_unsupported_fs(struct super_block *sb) +{ + return (sb->s_magic == PROC_SUPER_MAGIC +#ifdef SYSFS_MAGIC + || sb->s_magic == SYSFS_MAGIC +#endif + || !strcmp(au_sbtype(sb), "unionfs")); +} + +/* + * returns: + * 0: success, the caller will add it + * plus: success, it is already unified, the caller should ignore it + * minus: error + */ +static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) +{ + int err; + struct dentry *root; + struct inode *inode, *h_inode; + aufs_bindex_t bend, bindex; + + LKTRTrace("%s, remo%d\n", add->path, remount); + + root = sb->s_root; + bend = au_sbend(sb); + if (unlikely(bend >= 0 + && au_find_dbindex(root, add->nd.path.dentry) >= 0)) { + err = 1; + if (!remount) { + err = -EINVAL; + AuErr("%s duplicated\n", add->path); + } + goto out; + } + + err = -ENOSPC; /* -E2BIG; */ + if (unlikely(AUFS_BRANCH_MAX <= add->bindex + || AUFS_BRANCH_MAX - 1 <= bend)) { + AuErr("number of branches exceeded %s\n", add->path); + goto out; + } + + err = -EDOM; + if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) { + AuErr("bad index %d\n", add->bindex); + goto out; + } + + inode = add->nd.path.dentry->d_inode; + AuDebugOn(!inode || !S_ISDIR(inode->i_mode)); + err = -ENOENT; + if (unlikely(!inode->i_nlink)) { + AuErr("no existence %s\n", add->path); + goto out; + } + + err = -EINVAL; + if (unlikely(inode->i_sb == sb)) { + AuErr("%s must be outside\n", add->path); + goto out; + } + + if (unlikely(au_test_nested(inode->i_sb))) { + AuErr("nested " AUFS_NAME " %s\n", add->path); + goto out; + } + + if (unlikely(au_unsupported_fs(inode->i_sb))) { + AuErr("unsupported filesystem, %s\n", add->path); + goto out; + } + + if (unlikely(au_test_unsupported_nfs(inode->i_sb))) { + AuErr(AuNoNfsBranchMsg " %s\n", add->path); + goto out; + } + + err = test_br(sb, add->nd.path.dentry->d_inode, add->perm, add->path); + if (unlikely(err)) + goto out; + + if (bend < 0) + return 0; /* success */ + + err = -EINVAL; + for (bindex = 0; bindex <= bend; bindex++) + if (unlikely(test_overlap(sb, add->nd.path.dentry, + au_h_dptr(root, bindex)))) { + AuErr("%s is overlapped\n", add->path); + goto out; + } + + err = 0; + h_inode = au_h_dptr(root, 0)->d_inode; + if (unlikely(au_opt_test(au_mntflags(sb), WARN_PERM) + && ((h_inode->i_mode & S_IALLUGO) + != (inode->i_mode & S_IALLUGO) + || h_inode->i_uid != inode->i_uid + || h_inode->i_gid != inode->i_gid))) + AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", + add->path, + inode->i_uid, inode->i_gid, (inode->i_mode & S_IALLUGO), + h_inode->i_uid, h_inode->i_gid, + (h_inode->i_mode & S_IALLUGO)); + + out: + AuTraceErr(err); + return err; +} + +static int au_wbr_init(struct au_branch *br, struct super_block *sb, + int perm, struct path *path) +{ + int err; + struct au_wbr *wbr; + + AuTraceEnter(); + wbr = br->br_wbr; + AuDebugOn(!wbr); + + au_rw_init_nolock(&wbr->wbr_wh_rwsem); + memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh)); + atomic_set(&wbr->wbr_wh_running, 0); + wbr->wbr_bytes = 0; + + err = au_br_init_wh(sb, /*bindex*/-1, br, perm, + path->dentry, path->mnt); + + AuTraceErr(err); + return err; +} + +static int au_br_init(struct au_branch *br, struct super_block *sb, + struct au_opt_add *add) +{ + int err; + unsigned int mnt_flags; + + AuTraceEnter(); + + err = 0; + if (unlikely(au_br_writable(add->perm))) { + err = au_wbr_init(br, sb, add->perm, &add->nd.path); + if (unlikely(err)) + goto out; + } + + br->br_xino.xi_file = NULL; + mutex_init(&br->br_xino.xi_nondir_mtx); + br->br_mnt = mntget(add->nd.path.mnt); + mnt_flags = au_mntflags(sb); + if (au_opt_test(mnt_flags, XINO)) { + err = au_xino_br(sb, br, add->nd.path.dentry->d_inode->i_ino, + au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1); + if (unlikely(err)) { + AuDebugOn(br->br_xino.xi_file); + goto out; + } +#if 0 /* reserved for future use */ + } else if (au_opt_test(mnt_flags, XINODIR)) { + err = au_xinodir_br(sb, br, add->nd.path.dentry->d_inode->i_ino, + /*do_test*/1); + if (unlikely(err)) { + AuDebugOn(br->br_xino.xi_file); + goto out; + } +#endif + } + + br->br_id = au_new_br_id(sb); + br->br_perm = add->perm; + atomic_set(&br->br_count, 0); + br->br_xino_upper = AUFS_XINO_TRUNC_INIT; + atomic_set(&br->br_xino_running, 0); + sysaufs_br_init(br); + br->br_generation = au_sigen(sb); + /* smp_mb(); */ /* atomic_set */ + + out: + AuTraceErr(err); + return err; +} + +int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) +{ + int err, amount; + aufs_bindex_t bend, add_bindex; + struct dentry *root, *dentry; + struct au_iinfo *iinfo; + struct au_sbinfo *sbinfo; + struct au_dinfo *dinfo; + struct inode *root_inode; + unsigned long long maxb; + struct au_branch **branchp, *add_branch; + struct au_hdentry *hdentryp; + struct au_hinode *hinodep; + + dentry = add->nd.path.dentry; + LKTRTrace("b%d, %s, 0x%x, %.*s\n", + add->bindex, add->path, add->perm, AuDLNPair(dentry)); + SiMustWriteLock(sb); + root = sb->s_root; + DiMustWriteLock(root); + root_inode = root->d_inode; + IMustLock(root_inode); + IiMustWriteLock(root_inode); + + err = test_add(sb, add, remount); + if (unlikely(err < 0)) + goto out; + if (err) + return 0; /* success */ + + bend = au_sbend(sb); + add_branch = alloc_addbr(sb, bend + 2, add->perm); + err = PTR_ERR(add_branch); + if (IS_ERR(add_branch)) + goto out; + err = au_br_init(add_branch, sb, add); + if (unlikely(err)) { + au_br_do_free(add_branch); + goto out; + } + + add_bindex = add->bindex; + if (remount) + sysaufs_brs_del(sb, add_bindex); + + sbinfo = au_sbi(sb); + dinfo = au_di(root); + iinfo = au_ii(root_inode); + + amount = bend + 1 - add_bindex; + branchp = sbinfo->si_branch + add_bindex; + memmove(branchp + 1, branchp, sizeof(*branchp) * amount); + *branchp = add_branch; + hdentryp = dinfo->di_hdentry + add_bindex; + memmove(hdentryp + 1, hdentryp, sizeof(*hdentryp) * amount); + au_h_dentry_init(hdentryp); + hinodep = iinfo->ii_hinode + add_bindex; + memmove(hinodep + 1, hinodep, sizeof(*hinodep) * amount); + hinodep->hi_inode = NULL; + au_hin_init(hinodep, NULL); + + sbinfo->si_bend++; + dinfo->di_bend++; + iinfo->ii_bend++; + if (unlikely(bend < 0)) { + sbinfo->si_bend = 0; + dinfo->di_bstart = 0; + iinfo->ii_bstart = 0; + } + au_set_h_dptr(root, add_bindex, dget(dentry)); + au_set_h_iptr(root_inode, add_bindex, au_igrab(dentry->d_inode), 0); + if (remount) + sysaufs_brs_add(sb, add_bindex); + + if (!add_bindex) + au_cpup_attr_all(root_inode); + else + au_add_nlink(root_inode, dentry->d_inode); + maxb = dentry->d_sb->s_maxbytes; + if (sb->s_maxbytes < maxb) + sb->s_maxbytes = maxb; + + /* safe d_parent reference */ + if (!au_xino_def_br(sbinfo) + && add_branch->br_xino.xi_file + && add_branch->br_xino.xi_file->f_dentry->d_parent == dentry) + au_xino_def_br_set(add_branch, sbinfo); + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +#define AuVerbose(do_info, fmt, args...) do { \ + if (!do_info) \ + LKTRTrace(fmt, ##args); \ + else \ + AuInfo(fmt, ##args); \ +} while (0) + +/* + * test if the branch is deletable or not. + */ +static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, + au_gen_t sigen) +{ + int err, i, j, ndentry; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry *d; + aufs_bindex_t bstart, bend; + unsigned char verbose; + struct inode *inode; + + LKTRTrace("b%d, gen%d\n", bindex, sigen); + SiMustWriteLock(root->d_sb); + + err = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(err)) + goto out; + err = au_dcsub_pages(&dpages, root, NULL, NULL); + if (unlikely(err)) + goto out_dpages; + + verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE); + for (i = 0; !err && i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + ndentry = dpage->ndentry; + for (j = 0; !err && j < ndentry; j++) { + d = dpage->dentries[j]; + AuDebugOn(!atomic_read(&d->d_count)); + inode = d->d_inode; + AuDebugOn(!inode); + if (au_digen(d) == sigen + && au_iigen(inode) == sigen) + di_read_lock_child(d, AuLock_IR); + else { + di_write_lock_child(d); + err = au_reval_dpath(d, sigen); + if (!err) + di_downgrade_lock(d, AuLock_IR); + else { + di_write_unlock(d); + break; + } + } + + bstart = au_dbstart(d); + bend = au_dbend(d); + if (bstart <= bindex + && bindex <= bend + && au_h_dptr(d, bindex) + && (!S_ISDIR(d->d_inode->i_mode) + || bstart == bend)) { + err = -EBUSY; + AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d)); + } + di_read_unlock(d, AuLock_IR); + } + } + + out_dpages: + au_dpages_free(&dpages); + out: + AuTraceErr(err); + return err; +} + +static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, + au_gen_t sigen) +{ + int err; + struct inode *i; + aufs_bindex_t bstart, bend; + unsigned char verbose; + + LKTRTrace("b%d, gen%d\n", bindex, sigen); + SiMustWriteLock(sb); + + err = 0; + verbose = !!au_opt_test(au_mntflags(sb), VERBOSE); + list_for_each_entry(i, &sb->s_inodes, i_sb_list) { + AuDebugOn(!atomic_read(&i->i_count)); + if (!list_empty(&i->i_dentry)) + continue; + + if (au_iigen(i) == sigen) + ii_read_lock_child(i); + else { + ii_write_lock_child(i); + err = au_refresh_hinode_self(i); + if (!err) + ii_downgrade_lock(i); + else { + ii_write_unlock(i); + break; + } + } + + bstart = au_ibstart(i); + bend = au_ibend(i); + if (bstart <= bindex + && bindex <= bend + && au_h_iptr(i, bindex) + && (!S_ISDIR(i->i_mode) || bstart == bend)) { + err = -EBUSY; + AuVerbose(verbose, "busy i%lu\n", i->i_ino); + ii_read_unlock(i); + break; + } + ii_read_unlock(i); + } + + AuTraceErr(err); + return err; +} + +static int test_children_busy(struct dentry *root, aufs_bindex_t bindex) +{ + int err; + au_gen_t sigen; + + LKTRTrace("b%d\n", bindex); + SiMustWriteLock(root->d_sb); + DiMustWriteLock(root); + /* dont trust BKL */ + AuDebugOn(!kernel_locked()); + + sigen = au_sigen(root->d_sb); + DiMustNoWaiters(root); + IiMustNoWaiters(root->d_inode); + di_write_unlock(root); + err = test_dentry_busy(root, bindex, sigen); + if (!err) + err = test_inode_busy(root->d_sb, bindex, sigen); + di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */ + + AuTraceErr(err); + return err; +} + +int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount) +{ + int err, rerr, i; + aufs_bindex_t bindex, bend, br_id; + unsigned char do_wh, verbose; + struct au_sbinfo *sbinfo; + struct au_dinfo *dinfo; + struct au_iinfo *iinfo; + struct au_branch *br, **brp; + struct au_wbr *wbr; + struct au_hdentry *hdp; + struct au_hinode *hip; + + LKTRTrace("%s, %.*s\n", del->path, AuDLNPair(del->h_root)); + SiMustWriteLock(sb); + DiMustWriteLock(sb->s_root); + IiMustWriteLock(sb->s_root->d_inode); + + err = 0; + bindex = au_find_dbindex(sb->s_root, del->h_root); + if (bindex < 0) { + if (remount) + goto out; /* success */ + err = -ENOENT; + AuErr("%s no such branch\n", del->path); + goto out; + } + LKTRTrace("bindex b%d\n", bindex); + + err = -EBUSY; + verbose = !!au_opt_test(au_mntflags(sb), VERBOSE); + bend = au_sbend(sb); + if (unlikely(!bend)) { + AuVerbose(verbose, "no more branches left\n"); + goto out; + } + br = au_sbr(sb, bindex); + if (unlikely(au_br_count(br))) { + AuVerbose(verbose, "%d file(s) opened\n", au_br_count(br)); + goto out; + } + + wbr = br->br_wbr; + do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_tmp); + if (do_wh) { +#if 0 /* reserved for future use */ + /* remove whiteout base */ + err = au_br_init_wh(sb, bindex, br, AuBr_RO, del->h_root, + br->br_mnt); + if (unlikely(err)) + goto out; +#else + for (i = 0; i < AuBrWh_Last; i++) { + dput(wbr->wbr_wh[i]); + wbr->wbr_wh[i] = NULL; + } +#endif + } + + err = test_children_busy(sb->s_root, bindex); + if (unlikely(err)) { + if (unlikely(do_wh)) + goto out_wh; + goto out; + } + + err = 0; + if (remount) + sysaufs_brs_del(sb, bindex); + sbinfo = au_sbi(sb); + dinfo = au_di(sb->s_root); + iinfo = au_ii(sb->s_root->d_inode); + + dput(au_h_dptr(sb->s_root, bindex)); + au_hiput(iinfo->ii_hinode + bindex); + br_id = br->br_id; + au_br_do_free(br); + + /* todo: realloc and shrink memory? */ + if (bindex < bend) { + const aufs_bindex_t n = bend - bindex; + + brp = sbinfo->si_branch + bindex; + memmove(brp, brp + 1, sizeof(*brp) * n); + hdp = dinfo->di_hdentry + bindex; + memmove(hdp, hdp + 1, sizeof(*hdp) * n); + hip = iinfo->ii_hinode + bindex; + memmove(hip, hip + 1, sizeof(*hip) * n); + } + sbinfo->si_branch[0 + bend] = NULL; + dinfo->di_hdentry[0 + bend].hd_dentry = NULL; + iinfo->ii_hinode[0 + bend].hi_inode = NULL; + au_hin_init(iinfo->ii_hinode + bend, NULL); + + sbinfo->si_bend--; + dinfo->di_bend--; + iinfo->ii_bend--; + if (remount) + sysaufs_brs_add(sb, bindex); + + if (!bindex) + au_cpup_attr_all(sb->s_root->d_inode); + else + au_sub_nlink(sb->s_root->d_inode, del->h_root->d_inode); + if (au_opt_test(au_mntflags(sb), PLINK)) + au_plink_half_refresh(sb, br_id); + + if (sb->s_maxbytes == del->h_root->d_sb->s_maxbytes) { + bend--; + sb->s_maxbytes = 0; + for (bindex = 0; bindex <= bend; bindex++) { + unsigned long long maxb; + maxb = au_sbr_sb(sb, bindex)->s_maxbytes; + if (sb->s_maxbytes < maxb) + sb->s_maxbytes = maxb; + } + } + + if (au_xino_def_br(sbinfo) == br) + au_xino_def_br_set(NULL, sbinfo); + goto out; /* success */ + + out_wh: + /* revert */ + rerr = au_br_init_wh(sb, bindex, br, br->br_perm, del->h_root, + br->br_mnt); + if (rerr) + AuWarn("failed re-creating base whiteout, %s. (%d)\n", + del->path, rerr); + out: + AuTraceErr(err); + return err; +} + +static int do_need_sigen_inc(int a, int b) +{ + return (au_br_whable(a) && !au_br_whable(b)); +} + +static int need_sigen_inc(int old, int new) +{ + return (do_need_sigen_inc(old, new) + || do_need_sigen_inc(new, old)); +} + +static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) +{ + int err; + struct file *file, *hf; + + AuTraceEnter(); + SiMustWriteLock(sb); + + /* no need file_list_lock() since sbinfo is locked */ + err = 0; + list_for_each_entry(file, &sb->s_files, f_u.fu_list) { + LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry)); + if (!au_test_aufs_file(file)) + continue; + + fi_read_lock(file); + if (!S_ISREG(file->f_dentry->d_inode->i_mode) + || !(file->f_mode & FMODE_WRITE) + || au_fbstart(file) != bindex) { + FiMustNoWaiters(file); + fi_read_unlock(file); + continue; + } + + if (unlikely(au_test_mmapped(file))) { + err = -EBUSY; + FiMustNoWaiters(file); + fi_read_unlock(file); + break; + } + + /* todo: already flushed? */ + hf = au_h_fptr(file, au_fbstart(file)); + hf->f_flags = au_file_roflags(hf->f_flags); + hf->f_mode &= ~FMODE_WRITE; + put_write_access(hf->f_dentry->d_inode); + FiMustNoWaiters(file); + fi_read_unlock(file); + } + + AuTraceErr(err); + return err; +} + +int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, + int *do_update) +{ + int err; + struct dentry *root; + aufs_bindex_t bindex; + struct au_branch *br; + struct inode *hidden_dir; + + LKTRTrace("%s, %.*s, 0x%x\n", + mod->path, AuDLNPair(mod->h_root), mod->perm); + SiMustWriteLock(sb); + root = sb->s_root; + DiMustWriteLock(root); + IiMustWriteLock(root->d_inode); + + bindex = au_find_dbindex(root, mod->h_root); + if (bindex < 0) { + if (remount) + return 0; /* success */ + err = -ENOENT; + AuErr("%s no such branch\n", mod->path); + goto out; + } + LKTRTrace("bindex b%d\n", bindex); + + hidden_dir = mod->h_root->d_inode; + err = test_br(sb, hidden_dir, mod->perm, mod->path); + if (unlikely(err)) + goto out; + + br = au_sbr(sb, bindex); + if (br->br_perm == mod->perm) + return 0; /* success */ + + if (au_br_writable(br->br_perm)) { +#if 1 + /* remove whiteout base */ + err = au_br_init_wh(sb, bindex, br, mod->perm, mod->h_root, + br->br_mnt); + if (unlikely(err)) + goto out; +#else /* reserved for future use */ + struct au_wbr *wbr; + wbr = br->wbr; + if (wbr) + for (i = 0; i < AuBrWh_Last; i++) { + dput(wbr->wbr_wh[i]); + wbr->wbr_wh[i] = NULL; + } +#endif + + if (!au_br_writable(mod->perm)) { + /* rw --> ro, file might be mmapped */ + +#if 1 /* todo: test more? */ + DiMustNoWaiters(root); + IiMustNoWaiters(root->d_inode); + di_write_unlock(root); + err = au_br_mod_files_ro(sb, bindex); + /* aufs_write_lock() calls ..._child() */ + di_write_lock_child(root); +#endif + } + } else if (au_br_writable(mod->perm)) { + /* ro --> rw */ + err = -ENOMEM; + br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS); + if (br->br_wbr) { + struct path path = { + .mnt = br->br_mnt, + .dentry = mod->h_root + }; + + err = au_wbr_init(br, sb, mod->perm, &path); + if (unlikely(err)) { + kfree(br->br_wbr); + br->br_wbr = NULL; + } + } + } + + if (!err) { + *do_update |= need_sigen_inc(br->br_perm, mod->perm); + br->br_perm = mod->perm; + } + + out: + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/xino.c +++ linux-2.6.27/ubuntu/aufs/xino.c @@ -0,0 +1,1259 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * external inode number translation table and bitmap + * + * $Id: xino.c,v 1.16 2008/09/15 03:16:30 sfjro Exp $ + */ + +#include +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size, + loff_t *pos) +{ + ssize_t err; + mm_segment_t oldfs; + + LKTRTrace("%.*s, sz %lu, *pos %lld\n", + AuDLNPair(file->f_dentry), (unsigned long)size, *pos); + + oldfs = get_fs(); + set_fs(KERNEL_DS); + do { + /* todo: signal_pending? */ + err = func(file, (char __user *)buf, size, pos); + } while (err == -EAGAIN || err == -EINTR); + set_fs(oldfs); + +#if 0 /* reserved for future use */ + if (err > 0) + fsnotify_access(file->f_dentry); +#endif + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf, + size_t size, loff_t *pos) +{ + ssize_t err; + mm_segment_t oldfs; + + lockdep_off(); + oldfs = get_fs(); + set_fs(KERNEL_DS); + do { + /* todo: signal_pending? */ + err = func(file, (const char __user *)buf, size, pos); + } while (err == -EAGAIN || err == -EINTR); + set_fs(oldfs); + lockdep_on(); + + if (err >= 0) + au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry); + /*ignore*/ + +#if 0 /* reserved for future use */ + if (err > 0) + fsnotify_modify(file->f_dentry); +#endif + + AuTraceErr(err); + return err; +} + +struct do_xino_fwrite_args { + ssize_t *errp; + au_writef_t func; + struct file *file; + void *buf; + size_t size; + loff_t *pos; +}; + +static void call_do_xino_fwrite(void *args) +{ + struct do_xino_fwrite_args *a = args; + *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); +} + +ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size, + loff_t *pos) +{ + ssize_t err; + + LKTRTrace("%.*s, sz %lu, *pos %lld\n", + AuDLNPair(file->f_dentry), (unsigned long)size, *pos); + + /* todo: signal block and no wkq? */ + /* + * it breaks RLIMIT_FSIZE and normal user's limit, + * users should care about quota and real 'filesystem full.' + */ + if (!au_test_wkq(current)) { + int wkq_err; + struct do_xino_fwrite_args args = { + .errp = &err, + .func = func, + .file = file, + .buf = buf, + .size = size, + .pos = pos + }; + wkq_err = au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + } else + err = do_xino_fwrite(func, file, buf, size, pos); + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct xino_do_trunc_args { + struct super_block *sb; + struct au_branch *br; +}; + +static void xino_do_trunc(void *_args) +{ + struct xino_do_trunc_args *args = _args; + struct super_block *sb; + aufs_bindex_t bindex; + int err; + struct file *file; + struct inode *dir; + struct au_sbinfo *sbinfo; + struct kobject *kobj; + + err = 0; + sb = args->sb; + dir = sb->s_root->d_inode; + si_noflush_write_lock(sb); + ii_read_lock_parent(dir); + bindex = au_br_index(sb, args->br->br_id); + AuDebugOn(bindex < 0); + err = au_xino_trunc(sb, bindex); + if (unlikely(err)) + goto out; + + file = args->br->br_xino.xi_file; + au_update_fuse_h_inode(args->br->br_mnt, file->f_dentry); /*ignore*/ + if (file->f_dentry->d_inode->i_blocks >= args->br->br_xino_upper) + args->br->br_xino_upper += AUFS_XINO_TRUNC_STEP; + + out: + ii_read_unlock(dir); + if (unlikely(err)) + AuWarn("err b%d, (%d)\n", bindex, err); + atomic_dec_return(&args->br->br_xino_running); + au_br_put(args->br); + sbinfo = au_sbi(sb); + kobj = &sbinfo->si_kobj; + au_nwt_done(&sbinfo->si_nowait); + si_write_unlock(sb); + kobject_put(kobj); + kfree(args); +} + +static void xino_try_trunc(struct super_block *sb, struct au_branch *br) +{ + struct xino_do_trunc_args *args; + struct au_sbinfo *sbinfo; + struct file *file = br->br_xino.xi_file; + int wkq_err; + + au_update_fuse_h_inode(br->br_mnt, file->f_dentry); /*ignore*/ + if (file->f_dentry->d_inode->i_blocks < br->br_xino_upper) + return; + if (atomic_inc_return(&br->br_xino_running) > 1) + goto out; + + /* lock and kfree() will be called in trunc_xino() */ + args = kmalloc(sizeof(*args), GFP_NOFS); + if (unlikely(!args)) { + AuErr1("no memory\n"); + goto out_args; + } + + sbinfo = au_sbi(sb); + kobject_get(&sbinfo->si_kobj); + au_br_get(br); + args->sb = sb; + args->br = br; + wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*dlgt*/0); + if (!wkq_err) + return; /* success */ + + AuErr("wkq %d\n", wkq_err); + au_br_put(br); + kobject_put(&sbinfo->si_kobj); + + out_args: + kfree(args); + out: + atomic_dec_return(&br->br_xino_running); +} + +/* ---------------------------------------------------------------------- */ + +static int au_xino_do_write(au_writef_t write, struct file *file, + ino_t h_ino, struct au_xino_entry *xinoe) +{ + loff_t pos; + ssize_t sz; + + AuTraceEnter(); + + pos = h_ino; + if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) { + AuIOErr1("too large hi%lu\n", (unsigned long)h_ino); + return -EFBIG; + } + pos *= sizeof(*xinoe); + sz = xino_fwrite(write, file, xinoe, sizeof(*xinoe), &pos); + if (sz == sizeof(*xinoe)) + return 0; /* success */ + + AuIOErr("write failed (%ld)\n", (long)sz); + return -EIO; +} + +/* + * write @ino to the xinofile for the specified branch{@sb, @bindex} + * at the position of @_ino. + * when @ino is zero, it is written to the xinofile and means no entry. + */ +int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + struct au_xino_entry *xinoe) +{ + int err; + struct file *file; + struct au_branch *br; + unsigned int mnt_flags; + + LKTRTrace("b%d, hi%lu, i%lu\n", + bindex, (unsigned long)h_ino, (unsigned long)xinoe->ino); + BUILD_BUG_ON(sizeof(long long) != sizeof(Au_LOFF_MAX) + || ((loff_t)-1) > 0); + + mnt_flags = au_mntflags(sb); + if (unlikely(!au_opt_test_xino(mnt_flags))) + return 0; + + br = au_sbr(sb, bindex); + file = br->br_xino.xi_file; + AuDebugOn(!file); + + err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, h_ino, xinoe); + if (!err) { + if (unlikely(au_opt_test(mnt_flags, TRUNC_XINO) + && au_test_trunc_xino(br->br_mnt->mnt_sb))) + xino_try_trunc(sb, br); + return 0; /* success */ + } + + AuIOErr("write failed (%d)\n", err); + return -EIO; +} + +/* ---------------------------------------------------------------------- */ + +static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE; +static ino_t xib_calc_ino(unsigned long pindex, int bit) +{ + ino_t ino; + + AuDebugOn(bit < 0 || page_bits <= bit); + ino = AUFS_FIRST_INO + pindex * page_bits + bit; + return ino; +} + +static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit) +{ + AuDebugOn(ino < AUFS_FIRST_INO); + ino -= AUFS_FIRST_INO; + *pindex = ino / page_bits; + *bit = ino % page_bits; +} + +static int xib_pindex(struct super_block *sb, unsigned long pindex) +{ + int err; + struct au_sbinfo *sbinfo; + loff_t pos; + ssize_t sz; + struct file *xib; + unsigned long *p; + + LKTRTrace("pindex %lu\n", pindex); + sbinfo = au_sbi(sb); + MtxMustLock(&sbinfo->si_xib_mtx); + AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE + || !au_opt_test_xino(sbinfo->si_mntflags)); + + if (pindex == sbinfo->si_xib_last_pindex) + return 0; + + xib = sbinfo->si_xib; + p = sbinfo->si_xib_buf; + pos = sbinfo->si_xib_last_pindex; + pos *= PAGE_SIZE; + sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); + if (unlikely(sz != PAGE_SIZE)) + goto out; + + pos = pindex; + pos *= PAGE_SIZE; + if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE) + sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); + else { + memset(p, 0, PAGE_SIZE); + sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); + } + if (sz == PAGE_SIZE) { + sbinfo->si_xib_last_pindex = pindex; + return 0; /* success */ + } + + out: + AuIOErr1("write failed (%ld)\n", (long)sz); + err = sz; + if (sz >= 0) + err = -EIO; + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + ino_t ino) +{ + int err, bit; + unsigned long pindex; + struct au_sbinfo *sbinfo; + struct au_xino_entry xinoe = { + .ino = 0 + }; + + LKTRTrace("b%d, hi%lu, i%lu\n", + bindex, (unsigned long)h_ino, (unsigned long)ino); + + if (unlikely(!au_opt_test_xino(au_mntflags(sb)))) + return 0; + + err = 0; + sbinfo = au_sbi(sb); + if (unlikely(ino)) { + AuDebugOn(ino < AUFS_FIRST_INO); + xib_calc_bit(ino, &pindex, &bit); + AuDebugOn(page_bits <= bit); + mutex_lock(&sbinfo->si_xib_mtx); + err = xib_pindex(sb, pindex); + if (!err) { + clear_bit(bit, sbinfo->si_xib_buf); + sbinfo->si_xib_next_bit = bit; + } + mutex_unlock(&sbinfo->si_xib_mtx); + } + + if (!err) + err = au_xino_write(sb, bindex, h_ino, &xinoe); + return err; +} + +ino_t au_xino_new_ino(struct super_block *sb) +{ + ino_t ino; + struct au_sbinfo *sbinfo; + int free_bit, err; + unsigned long *p, pindex, ul, pend; + struct file *file; + + AuTraceEnter(); + + if (unlikely(!au_opt_test_xino(au_mntflags(sb)))) + return iunique(sb, AUFS_FIRST_INO); + + sbinfo = au_sbi(sb); + mutex_lock(&sbinfo->si_xib_mtx); + p = sbinfo->si_xib_buf; + free_bit = sbinfo->si_xib_next_bit; + if (free_bit < page_bits && !test_bit(free_bit, p)) + goto out; /* success */ + free_bit = find_first_zero_bit(p, page_bits); + if (free_bit < page_bits) + goto out; /* success */ + + pindex = sbinfo->si_xib_last_pindex; + for (ul = pindex - 1; ul < ULONG_MAX; ul--) { + err = xib_pindex(sb, ul); + if (unlikely(err)) + goto out_err; + free_bit = find_first_zero_bit(p, page_bits); + if (free_bit < page_bits) + goto out; /* success */ + } + + file = sbinfo->si_xib; + pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE; + for (ul = pindex + 1; ul <= pend; ul++) { + err = xib_pindex(sb, ul); + if (unlikely(err)) + goto out_err; + free_bit = find_first_zero_bit(p, page_bits); + if (free_bit < page_bits) + goto out; /* success */ + } + BUG(); + + out: + set_bit(free_bit, p); + sbinfo->si_xib_next_bit++; + pindex = sbinfo->si_xib_last_pindex; + mutex_unlock(&sbinfo->si_xib_mtx); + ino = xib_calc_ino(pindex, free_bit); + LKTRTrace("i%lu\n", (unsigned long)ino); + return ino; + out_err: + mutex_unlock(&sbinfo->si_xib_mtx); + LKTRTrace("i0\n"); + return 0; +} + +/* + * read @ino from xinofile for the specified branch{@sb, @bindex} + * at the position of @h_ino. + * if @ino does not exist and @do_new is true, get new one. + */ +int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + struct au_xino_entry *xinoe) +{ + int err; + struct file *file; + loff_t pos; + ssize_t sz; + struct au_sbinfo *sbinfo; + + LKTRTrace("b%d, hi%lu\n", bindex, (unsigned long)h_ino); + + xinoe->ino = 0; + if (unlikely(!au_opt_test_xino(au_mntflags(sb)))) + return 0; /* no ino */ + + err = 0; + sbinfo = au_sbi(sb); + pos = h_ino; + if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) { + AuIOErr1("too large hi%lu\n", (unsigned long)h_ino); + return -EFBIG; + } + pos *= sizeof(*xinoe); + + file = au_sbr(sb, bindex)->br_xino.xi_file; + AuDebugOn(!file); + if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xinoe)) + return 0; /* no ino */ + + sz = xino_fread(sbinfo->si_xread, file, xinoe, sizeof(*xinoe), &pos); + if (sz == sizeof(*xinoe)) + return 0; /* success */ + + err = sz; + if (unlikely(sz >= 0)) { + err = -EIO; + AuIOErr("xino read error (%ld)\n", (long)sz); + } + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct file *au_xino_create(struct super_block *sb, char *fname, int silent) +{ + struct file *file; + int err; + struct dentry *h_parent; + struct inode *h_dir; + struct vfsub_args vargs; + + LKTRTrace("%s\n", fname); + + /* + * at mount-time, and the xino file is the default path, + * hinotify is disabled so we have no inotify events to ignore. + * when a user specified the xino, we cannot get au_hdir to be ignored. + */ + vfsub_args_init(&vargs, /*ign*/NULL, /*dlgt*/0, 0); + file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE, + S_IRUGO | S_IWUGO); + if (IS_ERR(file)) { + if (!silent) + AuErr("open %s(%ld)\n", fname, PTR_ERR(file)); + return file; + } + + /* keep file count */ + h_parent = dget_parent(file->f_dentry); + h_dir = h_parent->d_inode; + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + err = vfsub_unlink(h_dir, file->f_dentry, &vargs); + mutex_unlock(&h_dir->i_mutex); + dput(h_parent); + if (unlikely(err)) { + if (!silent) + AuErr("unlink %s(%d)\n", fname, err); + goto out; + } + + if (sb != file->f_dentry->d_sb) + return file; /* success */ + + if (!silent) + AuErr("%s must be outside\n", fname); + err = -EINVAL; + + out: + fput(file); + file = ERR_PTR(err); + return file; +} + +/* + * find another branch who is on the same filesystem of the specified + * branch{@btgt}. search until @bend. + */ +static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, + aufs_bindex_t bend) +{ + aufs_bindex_t bindex; + struct super_block *tgt_sb = au_sbr_sb(sb, btgt); + + for (bindex = 0; bindex < btgt; bindex++) + if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) + return bindex; + for (bindex++; bindex <= bend; bindex++) + if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) + return bindex; + return -1; +} + +/* + * create a new xinofile at the same place/path as @base_file. + */ +struct file *au_xino_create2(struct super_block *sb, struct file *base_file, + struct file *copy_src) +{ + struct file *file; + int err; + struct dentry *base, *dentry, *parent; + struct inode *dir, *inode; + struct qstr *name; + struct au_hinode *hdir; + struct au_branch *br; + aufs_bindex_t bindex; + struct au_hin_ignore ign; + struct vfsub_args vargs; + struct au_ndx ndx = { + .nfsmnt = NULL, + .flags = 0, + .nd = NULL, + /* .br = NULL */ + }; + + base = base_file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(base)); + parent = base->d_parent; /* dir inode is locked */ + dir = parent->d_inode; + IMustLock(dir); + + file = ERR_PTR(-EINVAL); + if (unlikely(au_test_nfs(parent->d_sb))) + goto out; + + /* do not superio, nor NFS. */ + name = &base->d_name; + dentry = au_lkup_one(name->name, parent, name->len, &ndx); + if (IS_ERR(dentry)) { + file = (void *)dentry; + AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry)); + goto out; + } + + hdir = NULL; + br = au_xino_def_br(au_sbi(sb)); + if (br) { + bindex = au_find_bindex(sb, br); + if (bindex >= 0) + hdir = au_hi(sb->s_root->d_inode, bindex); + } + vfsub_args_init(&vargs, &ign, 0, 0); + vfsub_ign_hinode(&vargs, IN_CREATE, hdir); + err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, &vargs); + if (unlikely(err)) { + file = ERR_PTR(err); + AuErr("%.*s create err %d\n", AuLNPair(name), err); + goto out_dput; + } + file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt), + O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE); + if (IS_ERR(file)) { + AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file)); + goto out_dput; + } + vfsub_args_reinit(&vargs); + vfsub_ign_hinode(&vargs, IN_DELETE, hdir); + err = vfsub_unlink(dir, dentry, &vargs); + if (unlikely(err)) { + AuErr("%.*s unlink err %d\n", AuLNPair(name), err); + goto out_fput; + } + + if (copy_src) { + inode = copy_src->f_dentry->d_inode; + err = au_copy_file(file, copy_src, i_size_read(inode), + hdir, sb, &vargs); + if (unlikely(err)) { + AuErr("%.*s copy err %d\n", AuLNPair(name), err); + goto out_fput; + } + } + goto out_dput; /* success */ + + out_fput: + fput(file); + file = ERR_PTR(err); + out_dput: + dput(dentry); + out: + AuTraceErrPtr(file); + return file; +} + +/* ---------------------------------------------------------------------- */ + +/* + * initialize the xinofile for the specified branch{@sb, @bindex} + * at the place/path where @base_file indicates. + * test whether another branch is on the same filesystem or not, + * if @do_test is true. + */ +int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, + struct file *base_file, int do_test) +{ + int err; + struct au_branch *shared_br; + aufs_bindex_t bshared, bend, bindex; + unsigned char do_create; + struct inode *dir; + struct au_xino_entry xinoe; + struct dentry *parent; + struct file *file; + struct super_block *tgt_sb; + + LKTRTrace("base_file %p, do_test %d\n", base_file, do_test); + SiMustWriteLock(sb); + AuDebugOn(!au_opt_test_xino(au_mntflags(sb))); + AuDebugOn(br->br_xino.xi_file); + + do_create = 1; + bshared = -1; + shared_br = NULL; + bend = au_sbend(sb); + if (do_test) { + tgt_sb = br->br_mnt->mnt_sb; + for (bindex = 0; bindex <= bend; bindex++) + if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) { + bshared = bindex; + break; + } + } + if (unlikely(bshared >= 0)) { + shared_br = au_sbr(sb, bshared); + do_create = !shared_br->br_xino.xi_file; + } + + if (do_create) { + parent = dget_parent(base_file->f_dentry); + dir = parent->d_inode; + mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT); + file = au_xino_create2(sb, base_file, NULL); + mutex_unlock(&dir->i_mutex); + dput(parent); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + br->br_xino.xi_file = file; + } else { + br->br_xino.xi_file = shared_br->br_xino.xi_file; + get_file(br->br_xino.xi_file); + } + + xinoe.ino = AUFS_ROOT_INO; +#if 0 /* reserved for future use */ + xinoe.h_gen = h_inode->i_generation; + WARN_ON(xinoe.h_gen == AuXino_INVALID_HGEN); +#endif + err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file, + h_ino, &xinoe); + if (!err) + return 0; /* success */ + + + out: + AuTraceErr(err); + return err; +} + +/* too slow */ +static int do_xib_restore(struct super_block *sb, struct file *file, void *page) +{ + int err, bit; + struct au_sbinfo *sbinfo; + au_readf_t func; + loff_t pos, pend; + ssize_t sz; + struct au_xino_entry *xinoe; + unsigned long pindex; + + AuTraceEnter(); + SiMustWriteLock(sb); + + err = 0; + sbinfo = au_sbi(sb); + func = sbinfo->si_xread; + pend = i_size_read(file->f_dentry->d_inode); +#ifdef CONFIG_AUFS_DEBUG + if (unlikely(pend > (1 << 22))) + AuWarn("testing a large xino file %lld\n", (long long)pend); +#endif + pos = 0; + while (pos < pend) { + sz = xino_fread(func, file, page, PAGE_SIZE, &pos); + err = sz; + if (unlikely(sz <= 0)) + goto out; + + err = 0; + for (xinoe = page; sz > 0; xinoe++, sz -= sizeof(xinoe)) { + if (unlikely(xinoe->ino < AUFS_FIRST_INO)) + continue; + + xib_calc_bit(xinoe->ino, &pindex, &bit); + AuDebugOn(page_bits <= bit); + err = xib_pindex(sb, pindex); + if (!err) + set_bit(bit, sbinfo->si_xib_buf); + else + goto out; + } + } + + out: + AuTraceErr(err); + return err; +} + +static int xib_restore(struct super_block *sb) +{ + int err; + aufs_bindex_t bindex, bend; + void *page; + + AuTraceEnter(); + + err = -ENOMEM; + page = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!page)) + goto out; + + err = 0; + bend = au_sbend(sb); + for (bindex = 0; !err && bindex <= bend; bindex++) + if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) + err = do_xib_restore + (sb, au_sbr(sb, bindex)->br_xino.xi_file, page); + else + LKTRTrace("b%d\n", bindex); + free_page((unsigned long)page); + + out: + AuTraceErr(err); + return err; +} + +int au_xib_trunc(struct super_block *sb) +{ + int err; + struct au_sbinfo *sbinfo; + unsigned long *p; + loff_t pos; + ssize_t sz; + struct dentry *parent; + struct inode *dir; + struct file *file; + unsigned int mnt_flags; + + AuTraceEnter(); + SiMustWriteLock(sb); + + mnt_flags = au_mntflags(sb); + if (unlikely(!au_opt_test_xino(mnt_flags))) + return 0; + + sbinfo = au_sbi(sb); + parent = dget_parent(sbinfo->si_xib->f_dentry); + dir = parent->d_inode; + mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT); + file = au_xino_create2(sb, sbinfo->si_xib, NULL); + mutex_unlock(&dir->i_mutex); + dput(parent); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + fput(sbinfo->si_xib); + sbinfo->si_xib = file; + + p = sbinfo->si_xib_buf; + memset(p, 0, PAGE_SIZE); + pos = 0; + sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); + if (unlikely(sz != PAGE_SIZE)) { + err = sz; + AuIOErr("err %d\n", err); + if (sz >= 0) + err = -EIO; + goto out; + } + + if (au_opt_test_xino(mnt_flags)) { + mutex_lock(&sbinfo->si_xib_mtx); + err = xib_restore(sb); + mutex_unlock(&sbinfo->si_xib_mtx); +#if 0 /* reserved for future use */ + } else { + /* is it really safe? */ + /* dont trust BKL */ + AuDebugOn(!kernel_locked()); + ino = AUFS_FIRST_INO; + list_for_each_entry(inode, &sb->s_inodes, i_sb_list) + if (ino < inode->i_ino) + ino = inode->i_ino; + + /* make iunique to return larger than active max inode number */ + iunique(sb, ino); + err = 0; +#endif + } + +out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * xino mount option handlers + */ +static au_readf_t find_readf(struct file *h_file) +{ + const struct file_operations *fop = h_file->f_op; + + if (fop) { + if (fop->read) + return fop->read; + if (fop->aio_read) + return do_sync_read; + } + return ERR_PTR(-ENOSYS); +} + +static au_writef_t find_writef(struct file *h_file) +{ + const struct file_operations *fop = h_file->f_op; + + if (fop) { + if (fop->write) + return fop->write; + if (fop->aio_write) + return do_sync_write; + } + return ERR_PTR(-ENOSYS); +} + +/* xino bitmap */ +static void xino_clear_xib(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + sbinfo->si_xread = NULL; + sbinfo->si_xwrite = NULL; + if (sbinfo->si_xib) + fput(sbinfo->si_xib); + sbinfo->si_xib = NULL; + free_page((unsigned long)sbinfo->si_xib_buf); + sbinfo->si_xib_buf = NULL; +} + +static int au_xino_set_xib(struct super_block *sb, struct file *base) +{ + int err; + struct au_sbinfo *sbinfo; + struct file *file; + loff_t pos; + + LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry)); + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + file = au_xino_create2(sb, base, sbinfo->si_xib); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + if (sbinfo->si_xib) + fput(sbinfo->si_xib); + sbinfo->si_xib = file; + sbinfo->si_xread = find_readf(file); + AuDebugOn(IS_ERR(sbinfo->si_xread)); + sbinfo->si_xwrite = find_writef(file); + AuDebugOn(IS_ERR(sbinfo->si_xwrite)); + + err = -ENOMEM; + if (!sbinfo->si_xib_buf) + sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS); + if (unlikely(!sbinfo->si_xib_buf)) + goto out_unset; + + sbinfo->si_xib_last_pindex = 0; + sbinfo->si_xib_next_bit = 0; + + /* no need to lock for i_size_read() */ + if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) { + pos = 0; + err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, + PAGE_SIZE, &pos); + if (unlikely(err != PAGE_SIZE)) + goto out_free; + } + err = 0; + goto out; /* success */ + + out_free: + free_page((unsigned long)sbinfo->si_xib_buf); + sbinfo->si_xib_buf = NULL; + if (err >= 0) + err = -EIO; + out_unset: + fput(sbinfo->si_xib); + sbinfo->si_xib = NULL; + sbinfo->si_xread = NULL; + sbinfo->si_xwrite = NULL; + out: + AuTraceErr(err); + return err; +} + +/* xino for each branch */ +static void xino_clear_br(struct super_block *sb) +{ + aufs_bindex_t bindex, bend; + struct au_branch *br; + + AuTraceEnter(); + SiMustWriteLock(sb); + + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + if (unlikely(!br || !br->br_xino.xi_file)) + continue; + + fput(br->br_xino.xi_file); + br->br_xino.xi_file = NULL; + } +} + +static int au_xino_set_br(struct super_block *sb, struct file *base) +{ + int err; + aufs_bindex_t bindex, bend, bshared; + struct { + struct file *old, *new; + } *fpair, *p; + struct au_branch *br; + struct au_xino_entry xinoe; + struct inode *inode; + au_writef_t writef; + + LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry)); + SiMustWriteLock(sb); + + err = -ENOMEM; + bend = au_sbend(sb); + fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS); + if (unlikely(!fpair)) + goto out; + + inode = sb->s_root->d_inode; + xinoe.ino = AUFS_ROOT_INO; + writef = au_sbi(sb)->si_xwrite; + for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) { + br = au_sbr(sb, bindex); + bshared = is_sb_shared(sb, bindex, bindex - 1); + if (bshared >= 0) { + /* shared xino */ + *p = fpair[bshared]; + get_file(p->new); + } + + if (!p->new) { + /* new xino */ + p->old = br->br_xino.xi_file; + p->new = au_xino_create2(sb, base, br->br_xino.xi_file); + err = PTR_ERR(p->new); + if (IS_ERR(p->new)) { + p->new = NULL; + goto out_pair; + } + } + + err = au_xino_do_write(writef, p->new, + au_h_iptr(inode, bindex)->i_ino, &xinoe); + if (unlikely(err)) + goto out_pair; + } + + for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) { + br = au_sbr(sb, bindex); + AuDebugOn(p->old != br->br_xino.xi_file); + if (br->br_xino.xi_file) + fput(br->br_xino.xi_file); + get_file(p->new); + br->br_xino.xi_file = p->new; + } + + out_pair: + for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) + if (p->new) + fput(p->new); + else + break; + kfree(fpair); + out: + AuTraceErr(err); + return err; +} + +void au_xino_clr(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + SiMustWriteLock(sb); + + au_xigen_clr(sb); + xino_clear_xib(sb); + xino_clear_br(sb); + sbinfo = au_sbi(sb); + /* lvalue, do not call au_mntflags() */ + au_opt_clr(sbinfo->si_mntflags, XINO); + au_xino_def_br_set(NULL, sbinfo); +} + +int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount) +{ + int err, skip; + struct dentry *parent, *cur_parent; + struct qstr *dname, *cur_name; + struct file *cur_xino; + struct inode *dir; + struct au_sbinfo *sbinfo; + + LKTRTrace("remount %d\n", remount); + SiMustWriteLock(sb); + + err = 0; + sbinfo = au_sbi(sb); + parent = dget_parent(xino->file->f_dentry); + if (remount) { + skip = 0; + dname = &xino->file->f_dentry->d_name; + cur_xino = sbinfo->si_xib; + if (cur_xino) { + cur_parent = dget_parent(cur_xino->f_dentry); + cur_name = &cur_xino->f_dentry->d_name; + skip = (cur_parent == parent + && dname->len == cur_name->len + && !memcmp(dname->name, cur_name->name, + dname->len)); + dput(cur_parent); + } + if (skip) + goto out; + } + + au_opt_set(sbinfo->si_mntflags, XINO); + au_xino_def_br_set(NULL, sbinfo); + dir = parent->d_inode; + mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT); + err = au_xino_set_xib(sb, xino->file); + if (!err) + err = au_xigen_set(sb, xino->file); + if (!err) + err = au_xino_set_br(sb, xino->file); + mutex_unlock(&dir->i_mutex); + if (!err) + goto out; /* success */ + + /* reset all */ + AuIOErr("failed creating xino(%d).\n", err); + + out: + dput(parent); + AuTraceErr(err); + return err; +} + +int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex) +{ + int err; + struct au_branch *br; + struct file *new_xino; + struct super_block *h_sb; + aufs_bindex_t bi, bend; + struct dentry *parent; + struct inode *dir; + + LKTRTrace("b%d\n", bindex); + SiMustWriteLock(sb); + + err = -EINVAL; + bend = au_sbend(sb); + if (unlikely(bindex < 0 || bend < bindex)) + goto out; + br = au_sbr(sb, bindex); + if (unlikely(!br->br_xino.xi_file)) + goto out; + + parent = dget_parent(br->br_xino.xi_file->f_dentry); + dir = parent->d_inode; + mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT); + new_xino = au_xino_create2(sb, br->br_xino.xi_file, + br->br_xino.xi_file); + mutex_unlock(&dir->i_mutex); + dput(parent); + err = PTR_ERR(new_xino); + if (IS_ERR(new_xino)) + goto out; + err = 0; + fput(br->br_xino.xi_file); + br->br_xino.xi_file = new_xino; + + h_sb = br->br_mnt->mnt_sb; + for (bi = 0; bi <= bend; bi++) { + if (unlikely(bi == bindex)) + continue; + br = au_sbr(sb, bi); + if (br->br_mnt->mnt_sb != h_sb) + continue; + + fput(br->br_xino.xi_file); + br->br_xino.xi_file = new_xino; + get_file(new_xino); + } + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * create a xinofile at the default place/path. + */ +struct file *au_xino_def(struct super_block *sb) +{ + struct file *file; + aufs_bindex_t bend, bindex, bwr; + char *page, *p; + struct path path; + struct dentry *root; + + AuTraceEnter(); + + root = sb->s_root; + bend = au_sbend(sb); + bwr = -1; + for (bindex = 0; bindex <= bend; bindex++) + if (au_br_writable(au_sbr_perm(sb, bindex)) + && !au_test_nfs(au_h_dptr(root, bindex)->d_sb)) { + bwr = bindex; + break; + } + + if (bwr >= 0) { + file = ERR_PTR(-ENOMEM); + page = __getname(); + if (unlikely(!page)) + goto out; + path.mnt = au_sbr_mnt(sb, bwr); + path.dentry = au_h_dptr(root, bwr); + p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME)); + file = (void *)p; + if (!IS_ERR(p)) { + strcat(p, "/" AUFS_XINO_FNAME); + LKTRTrace("%s\n", p); + file = au_xino_create(sb, p, /*silent*/0); + if (!IS_ERR(file)) + au_xino_def_br_set(au_sbr(sb, bwr), au_sbi(sb)); + } + __putname(page); + } else { + file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0); + if (unlikely(au_test_nfs(file->f_dentry->d_sb))) { + AuErr("xino or noxino option is required " + "since %s is NFS\n", AUFS_XINO_DEFPATH); + fput(file); + file = ERR_PTR(-EINVAL); + } + if (!IS_ERR(file)) + au_xino_def_br_set(NULL, au_sbi(sb)); + } + + out: + AuTraceErrPtr(file); + return file; +} --- linux-2.6.27.orig/ubuntu/aufs/sysaufs.c +++ linux-2.6.27/ubuntu/aufs/sysaufs.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sysfs interface and lifetime management + * they are necessary regardless sysfs is disabled. + * + * $Id: sysaufs.c,v 1.10 2008/09/15 03:14:55 sfjro Exp $ + */ + +#include +#include +#include +#include +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +unsigned long au_si_mask; + +/* ---------------------------------------------------------------------- */ + +struct kset *au_kset; + +#define AuSbiAttr(_name) { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = sysaufs_sbi_##_name, \ +} + +static struct au_sbi_attr au_sbi_attr_xino = AuSbiAttr(xino); +#ifdef CONFIG_AUFS_EXPORT +static struct au_sbi_attr au_sbi_attr_xigen = AuSbiAttr(xigen); +#endif +struct attribute *au_sbi_attrs[] = { + &au_sbi_attr_xino.attr, +#ifdef CONFIG_AUFS_EXPORT + &au_sbi_attr_xigen.attr, +#endif + NULL, +}; + +static struct sysfs_ops au_sbi_ops = { + .show = sysaufs_sbi_show +}; + +static struct kobj_type au_sbi_ktype = { + .release = au_si_free, + .sysfs_ops = &au_sbi_ops, + .default_attrs = au_sbi_attrs +}; + +/* ---------------------------------------------------------------------- */ + +int sysaufs_si_init(struct au_sbinfo *sbinfo) +{ + int err; + + sbinfo->si_kobj.kset = au_kset; + /* some people doesn't like to show a pointer in kernel */ + err = kobject_init_and_add(&sbinfo->si_kobj, &au_sbi_ktype, + NULL/*&au_kset->kobj*/, + SysaufsSb_PREFIX "%lx", + au_si_mask ^ (unsigned long)sbinfo); + AuTraceErr(err); + return err; +} + + +/* ---------------------------------------------------------------------- */ + +void sysaufs_fin(void) +{ + sysfs_remove_group(&au_kset->kobj, au_attr_group); + kset_unregister(au_kset); +} + +int __init sysaufs_init(void) +{ + int err; + + get_random_bytes(&au_si_mask, sizeof(au_si_mask)); + + au_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj); + err = PTR_ERR(au_kset); + if (IS_ERR(au_kset)) + goto out; + err = sysfs_create_group(&au_kset->kobj, au_attr_group); + if (unlikely(err)) + kset_unregister(au_kset); + + out: + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/hinotify.c +++ linux-2.6.27/ubuntu/aufs/hinotify.c @@ -0,0 +1,1133 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * internal/hidden inotify handler + * + * $Id: hinotify.c,v 1.16 2008/09/08 02:39:54 sfjro Exp $ + */ + +#include "aufs.h" + +/* +#ifdef DbgInotify +#define AuDbgHin(args...) AuDbg(##args) +#else +#define AuDbgHin(args...) do {} while () +#endif +*/ + +static struct inotify_handle *in_handle; + +AuCacheFuncs(hinotify, AuCache_HINOTIFY); + +int au_hin_alloc(struct au_hinode *hinode, struct inode *inode, + struct inode *h_inode) +{ + int err; + struct au_hinotify *hin; + s32 wd; + + LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino); + + err = -ENOMEM; + hin = au_cache_alloc_hinotify(); + if (hin) { + AuDebugOn(hinode->hi_notify); + hinode->hi_notify = hin; + spin_lock_init(&hin->hin_ignore_lock); + INIT_LIST_HEAD(&hin->hin_ignore_list); + hin->hin_aufs_inode = inode; + + inotify_init_watch(&hin->hin_watch); + wd = inotify_add_watch(in_handle, &hin->hin_watch, h_inode, + AuInMask); + if (wd >= 0) + return 0; /* success */ + + err = wd; + put_inotify_watch(&hin->hin_watch); + au_cache_free_hinotify(hin); + hinode->hi_notify = NULL; + } + + AuTraceErr(err); + return err; +} + +void au_hin_free(struct au_hinode *hinode) +{ + int err; + struct au_hinotify *hin; + + AuTraceEnter(); + + hin = hinode->hi_notify; + if (unlikely(hin)) { + err = 0; + if (atomic_read(&hin->hin_watch.count)) + err = inotify_rm_watch(in_handle, &hin->hin_watch); + if (unlikely(err)) + /* it means the watch is already removed */ + LKTRTrace("failed inotify_rm_watch() %d\n", err); + au_cache_free_hinotify(hin); + hinode->hi_notify = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +void au_hin_ctl(struct au_hinode *hinode, const __u32 mask) +{ + struct inode *h_inode; + struct inotify_watch *watch; + + h_inode = hinode->hi_inode; + LKTRTrace("hi%lu, sb %p, 0x%x\n", h_inode->i_ino, h_inode->i_sb, mask); + IMustLock(h_inode); + if (!hinode->hi_notify) + return; + + watch = &hinode->hi_notify->hin_watch; +#if 0 /* reserved for future use */ + { + u32 wd; + wd = inotify_find_update_watch(in_handle, h_inode, mask); + AuTraceErr(wd); + /* ignore an err; */ + } +#else + /* struct inotify_handle is hidden */ + mutex_lock(&h_inode->inotify_mutex); + /* mutex_lock(&watch->ih->mutex); */ + watch->mask = mask; + /* mutex_unlock(&watch->ih->mutex); */ + mutex_unlock(&h_inode->inotify_mutex); +#endif + LKTRTrace("watch %p, mask %u\n", watch, watch->mask); +} + +void au_reset_hinotify(struct inode *inode, unsigned int flags) +{ + aufs_bindex_t bindex, bend; + struct inode *hi; + struct dentry *iwhdentry; + + LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags); + + bend = au_ibend(inode); + for (bindex = au_ibstart(inode); bindex <= bend; bindex++) { + hi = au_h_iptr(inode, bindex); + if (hi) { + /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */ + iwhdentry = au_hi_wh(inode, bindex); + if (unlikely(iwhdentry)) + dget(iwhdentry); + au_igrab(hi); + au_set_h_iptr(inode, bindex, NULL, 0); + au_set_h_iptr(inode, bindex, au_igrab(hi), + flags & ~AuHi_XINO); + iput(hi); + dput(iwhdentry); + /* mutex_unlock(&hi->i_mutex); */ + } + } +} + +/* ---------------------------------------------------------------------- */ + +void au_unpin_gp(struct au_pin *args) +{ + struct au_pin1 *gp; + + gp = au_pin_gp(args); + AuDebugOn(!gp); + if (gp->dentry) + LKTRTrace("%.*s\n", AuDLNPair(gp->dentry)); + else + AuTraceEnter(); + + au_do_unpin(gp, NULL); +} + +int au_hin_verify_gen(struct dentry *dentry) +{ + struct super_block *sb = dentry->d_sb; + au_gen_t sigen; + struct inode *inode; + + if (!au_opt_test(au_mntflags(sb), UDBA_INOTIFY)) + return 0; + + sigen = au_sigen(dentry->d_sb); + inode = dentry->d_inode; + return (au_digen(dentry) != sigen + || (inode && au_iigen(inode) != sigen)); +} + +/* ---------------------------------------------------------------------- */ + +/* cf. fsnotify_change() */ +__u32 vfsub_events_notify_change(struct iattr *ia) +{ + __u32 events; + const unsigned int amtime = (ATTR_ATIME | ATTR_MTIME); + + events = 0; + if ((ia->ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) + || (ia->ia_valid & amtime) == amtime) + events |= IN_ATTRIB; + if ((ia->ia_valid & ATTR_SIZE) + || (ia->ia_valid & amtime) == ATTR_MTIME) + events |= IN_MODIFY; + return events; +} + +void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events, + struct au_hinode *hinode) +{ + struct au_hinotify *hin; + struct super_block *sb; + struct au_hin_ignore *ign; + + if (!hinode) + return; + + hin = hinode->hi_notify; + if (!hin || !hin->hin_watch.mask) + return; + + sb = hin->hin_aufs_inode->i_sb; + AuDebugOn(!au_opt_test(au_mntflags(sb), UDBA_INOTIFY)); + + ign = vargs->ignore + vargs->nignore++; + ign->ign_events = events; + ign->ign_handled = 0; + ign->ign_hinode = hinode; + + { + struct inode *h_inode; + h_inode = hinode->hi_inode; + if (!mutex_is_locked(&h_inode->i_mutex)) + au_dbg_blocked(); + IMustLock(h_inode); + } +} + +static void au_hin_ignore(struct au_hin_ignore *ign) +{ + struct au_hinode *hinode; + __u32 events; + struct au_hinotify *hin; + struct inode *h_inode; + + hinode = ign->ign_hinode; + events = ign->ign_events; + LKTRTrace("0x%x\n", events); + AuDebugOn(!hinode || !events); + + hin = hinode->hi_notify; + h_inode = hinode->hi_inode; + if (h_inode && hin) { + LKTRTrace("hi%lu\n", h_inode->i_ino); +#ifdef DbgInotify + AuDbg("hi%lu, 0x%x\n", h_inode->i_ino, events); +#endif + + spin_lock(&hin->hin_ignore_lock); + list_add(&ign->ign_list, &hin->hin_ignore_list); + spin_unlock(&hin->hin_ignore_lock); + /* AuDbg("list_add %p, 0x%x\n", ign, events); */ + } +#if 1 /* todo: test dlgt */ + else + /* + * it may happen by this scenario. + * - a file and its parent dir exist on two branches + * - a file on the upper branch is opened + * - the parent dir and the file are removed by udba + * - the parent is re-accessed, and new dentry/inode in + * aufs is generated for it, based upon the one on the lower + * branch + * - the opened file is re-accessed, re-validated, and it may be + * re-connected to the new parent dentry + * it means the file in aufs cannot get the actual removed + * parent dir on the branch. + */ + INIT_LIST_HEAD(&ign->ign_list); +#endif +} + +static void au_hin_unignore(struct au_hin_ignore *ign) +{ + struct au_hinode *hinode; + __u32 events; + struct au_hinotify *hin; + struct inode *h_inode; + + hinode = ign->ign_hinode; + events = ign->ign_events; + LKTRTrace("0x%x\n", events); + /* AuDbg("0x%x\n", events); */ + AuDebugOn(!hinode || !events); + + hin = hinode->hi_notify; + h_inode = hinode->hi_inode; + if (unlikely(!h_inode || !hin)) + return; + LKTRTrace("hi%lu\n", h_inode->i_ino); +#ifdef DbgInotify + AuDbg("hi%lu, 0x%x\n", h_inode->i_ino, events); +#endif + + spin_lock(&hin->hin_ignore_lock); + au_hin_list_del(&ign->ign_list); + spin_unlock(&hin->hin_ignore_lock); + /* AuDbg("list_del %p, 0x%x\n", ign, events); */ +} + +static int au_hin_test_ignore(u32 mask, struct au_hinotify *hin) +{ + int do_ignore; + struct au_hin_ignore *ign, *tmp; + u32 events; + + do_ignore = 0; + spin_lock(&hin->hin_ignore_lock); + list_for_each_entry_safe(ign, tmp, &hin->hin_ignore_list, ign_list) { + /* AuDbg("ign %p\n", ign); */ + if (ign->ign_pid == current->pid) { + events = (mask & ign->ign_events); + if (events) { + do_ignore = 1; + ign->ign_handled |= events; + if (ign->ign_events == ign->ign_handled) { + list_del_init(&ign->ign_list); + /* + AuDbg("list_del %p, 0x%x\n", + ign, events); + */ + } + break; + } + } + } + spin_unlock(&hin->hin_ignore_lock); + + return do_ignore; +} + +void vfsub_ignore(struct vfsub_args *vargs) +{ + int n; + struct au_hin_ignore *ign; + struct super_block *sb; + struct au_hinode *hinode; + struct inode *h_inode; + + n = vargs->nignore; + if (!n) + return; + + ign = vargs->ignore; + hinode = ign->ign_hinode; + sb = hinode->hi_notify->hin_aufs_inode->i_sb; + h_inode = hinode->hi_inode; + if (unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY))) { + if (!mutex_is_locked(&h_inode->i_mutex)) + au_dbg_blocked(); + IMustLock(h_inode); + } + while (n-- > 0) { + ign->ign_pid = current->pid; + au_hin_ignore(ign++); + } +} + +void vfsub_unignore(struct vfsub_args *vargs) +{ + int n; + struct au_hin_ignore *ign; + + n = vargs->nignore; + if (!n) + return; + + ign = vargs->ignore; + while (n-- > 0) + au_hin_unignore(ign++); +} + +#ifdef CONFIG_AUFS_DEBUG +void au_dbg_hin_list(struct vfsub_args *vargs) +{ + int n; + struct au_hin_ignore *ign; + + n = vargs->nignore; + if (!n) + return; + + ign = vargs->ignore; + while (n-- > 0) { + /* AuDebugOn(!list_empty(&ign++->ign_list)); */ + if (list_empty(&ign++->ign_list)) + continue; + ign--; + AuDbg("%d: pid %d, 0x%x\n", + n + 1, ign->ign_pid, ign->ign_events); + ign++; + au_dbg_blocked(); + } +} +#endif + +/* ---------------------------------------------------------------------- */ + +static char *in_name(u32 mask) +{ +#ifdef CONFIG_AUFS_DEBUG +#define test_ret(flag) if (mask & flag) return #flag; + test_ret(IN_ACCESS); + test_ret(IN_MODIFY); + test_ret(IN_ATTRIB); + test_ret(IN_CLOSE_WRITE); + test_ret(IN_CLOSE_NOWRITE); + test_ret(IN_OPEN); + test_ret(IN_MOVED_FROM); + test_ret(IN_MOVED_TO); + test_ret(IN_CREATE); + test_ret(IN_DELETE); + test_ret(IN_DELETE_SELF); + test_ret(IN_MOVE_SELF); + test_ret(IN_UNMOUNT); + test_ret(IN_Q_OVERFLOW); + test_ret(IN_IGNORED); + return ""; +#undef test_ret +#else + return "??"; +#endif +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen, + struct inode *dir) +{ + struct dentry *dentry, *d, *parent; + struct qstr *dname; + + LKTRTrace("%.*s, dir%lu\n", nlen, name, dir->i_ino); + + parent = d_find_alias(dir); + if (!parent) + return NULL; + + dentry = NULL; + spin_lock(&dcache_lock); + list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) { + LKTRTrace("%.*s\n", AuDLNPair(d)); + dname = &d->d_name; + if (dname->len != nlen || memcmp(dname->name, name, nlen)) + continue; + if (!atomic_read(&d->d_count) || !d->d_fsdata) { + spin_lock(&d->d_lock); + __d_drop(d); + spin_unlock(&d->d_lock); + continue; + } + + dentry = dget(d); + break; + } + spin_unlock(&dcache_lock); + dput(parent); + + if (dentry) { +#if 0 + lktr_set_pid(current->pid, LktrArrayPid); + AuDbgDentry(dentry); + lktr_clear_pid(current->pid, LktrArrayPid); +#endif + di_write_lock_child(dentry); + } + return dentry; +} + +static struct inode *lookup_wlock_by_ino(struct super_block *sb, + aufs_bindex_t bindex, ino_t h_ino) +{ + struct inode *inode; + struct au_xino_entry xinoe; + int err; + + LKTRTrace("b%d, hi%lu\n", bindex, (unsigned long)h_ino); + AuDebugOn(!au_opt_test_xino(au_mntflags(sb))); + + inode = NULL; + err = au_xino_read(sb, bindex, h_ino, &xinoe); + if (!err && xinoe.ino) + inode = ilookup(sb, xinoe.ino); + if (!inode) + goto out; + if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { + AuWarn("wrong root branch\n"); + iput(inode); + inode = NULL; + goto out; + } + + ii_write_lock_child(inode); + + out: + return inode; +} + +static int hin_xino(struct inode *inode, struct inode *h_inode) +{ + int err; + aufs_bindex_t bindex, bend, bfound, bstart; + struct inode *h_i; + + LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino); + + err = 0; + if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { + AuWarn("branch root dir was changed\n"); + goto out; + } + + bfound = -1; + bend = au_ibend(inode); + bstart = au_ibstart(inode); +#if 0 /* reserved for future use */ + if (bindex == bend) { + /* keep this ino in rename case */ + goto out; + } +#endif + for (bindex = bstart; bindex <= bend; bindex++) { + if (au_h_iptr(inode, bindex) == h_inode) { + bfound = bindex; + break; + } + } + if (bfound < 0) + goto out; + + for (bindex = bstart; bindex <= bend; bindex++) { + h_i = au_h_iptr(inode, bindex); + if (h_i) + err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino, + 0); + /* ignore this error */ + /* bad action? */ + } + + /* children inode number will be broken */ + + out: + AuTraceErr(err); + return err; +} + +static int hin_gen_tree(struct dentry *dentry) +{ + int err, i, j, ndentry; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + err = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(err)) + goto out; + err = au_dcsub_pages(&dpages, dentry, NULL, NULL); + if (unlikely(err)) + goto out_dpages; + + for (i = 0; i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + ndentry = dpage->ndentry; + for (j = 0; j < ndentry; j++) { + struct dentry *d; + d = dentries[j]; + LKTRTrace("%.*s\n", AuDLNPair(d)); + if (IS_ROOT(d)) + continue; + + d_drop(d); + au_digen_dec(d); + if (d->d_inode) + /* todo: reset children xino? + cached children only? */ + au_iigen_dec(d->d_inode); + } + } + + out_dpages: + au_dpages_free(&dpages); + + /* discard children */ + dentry_unhash(dentry); + dput(dentry); + out: + AuTraceErr(err); + return err; +} + +/* + * return 0 if processed. + */ +static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, + const unsigned int isdir) +{ + int err; + struct dentry *d; + struct qstr *dname; + + LKTRTrace("%.*s, i%lu\n", nlen, name, inode->i_ino); + + err = 1; + if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { + AuWarn("branch root dir was changed\n"); + err = 0; + goto out; + } + + if (!isdir) { + AuDebugOn(!name); + au_iigen_dec(inode); + spin_lock(&dcache_lock); + list_for_each_entry(d, &inode->i_dentry, d_alias) { + dname = &d->d_name; + if (dname->len != nlen + && memcmp(dname->name, name, nlen)) + continue; + err = 0; + spin_lock(&d->d_lock); + __d_drop(d); + au_digen_dec(d); + spin_unlock(&d->d_lock); + break; + } + spin_unlock(&dcache_lock); + } else { + au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS); + d = d_find_alias(inode); + if (!d) { + au_iigen_dec(inode); + goto out; + } + + dname = &d->d_name; + if (dname->len == nlen && !memcmp(dname->name, name, nlen)) + err = hin_gen_tree(d); + dput(d); + } + + out: + AuTraceErr(err); + return err; +} + +static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir) +{ + int err; + struct inode *inode; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + inode = dentry->d_inode; + if (IS_ROOT(dentry) + /* || (inode && inode->i_ino == AUFS_ROOT_INO) */ + ) { + AuWarn("branch root dir was changed\n"); + return 0; + } + + err = 0; + if (!isdir) { + d_drop(dentry); + au_digen_dec(dentry); + if (inode) + au_iigen_dec(inode); + } else { + au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS); + if (inode) + err = hin_gen_tree(dentry); + } + + AuTraceErr(err); + return err; +} + +static void hin_attr(struct inode *inode, struct inode *h_inode) +{ + struct dentry *h_dentry; + + LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino); + + if (au_h_iptr(inode, au_ibstart(inode)) != h_inode) + return; + + h_dentry = d_find_alias(h_inode); + if (h_dentry) { + au_update_fuse_h_inode(NULL, h_dentry); + /* ignore an error*/ + dput(h_dentry); + } + + au_cpup_attr_all(inode); +} + +/* ---------------------------------------------------------------------- */ + +/* hinotify job flags */ +#define AuHinJob_XINO0 1 +#define AuHinJob_GEN (1 << 1) +#define AuHinJob_DIRENT (1 << 2) +#define AuHinJob_ATTR (1 << 3) +#define AuHinJob_ISDIR (1 << 4) +#define AuHinJob_TRYXINO0 (1 << 5) +#define AuHinJob_MNTPNT (1 << 6) +#define au_ftest_hinjob(flags, name) ((flags) & AuHinJob_##name) +#define au_fset_hinjob(flags, name) { (flags) |= AuHinJob_##name; } +#define au_fclr_hinjob(flags, name) { (flags) &= ~AuHinJob_##name; } + +struct hin_job_args { + unsigned int flags; + struct inode *inode, *h_inode, *dir, *h_dir; + struct dentry *dentry; + char *h_name; + int h_nlen; +}; + +static int hin_job(struct hin_job_args *a) +{ + const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR); + + /* reset xino */ + if (au_ftest_hinjob(a->flags, XINO0) && a->inode) + hin_xino(a->inode, a->h_inode); + /* ignore this error */ + + if (au_ftest_hinjob(a->flags, TRYXINO0) + && a->inode + && a->h_inode) { + mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); + if (!a->h_inode->i_nlink) + hin_xino(a->inode, a->h_inode); + /* ignore this error */ + mutex_unlock(&a->h_inode->i_mutex); + } + + /* make the generation obsolete */ + if (au_ftest_hinjob(a->flags, GEN)) { + int err = -1; + if (a->inode) + err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode, + isdir); + if (err && a->dentry) + hin_gen_by_name(a->dentry, isdir); + /* ignore this error */ + } + + /* make dir entries obsolete */ + if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) { + struct au_vdir *vdir; + IiMustWriteLock(a->inode); + vdir = au_ivdir(a->inode); + if (vdir) + vdir->vd_jiffy = 0; + /* IMustLock(a->inode); */ + /* a->inode->i_version++; */ + } + + /* update the attr */ + if (au_ftest_hinjob(a->flags, ATTR) && a->inode && a->h_inode) + hin_attr(a->inode, a->h_inode); + + /* can do nothing but warn */ + if (au_ftest_hinjob(a->flags, MNTPNT) + && a->dentry + && d_mountpoint(a->dentry)) + AuWarn("mount-point %.*s is removed or renamed\n", + AuDLNPair(a->dentry)); + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +enum { CHILD, PARENT }; +struct postproc_args { + struct inode *h_dir, *dir, *h_child_inode; + u32 mask; + unsigned int flags[2]; + unsigned int h_child_nlen; + char h_child_name[]; +}; + +static void postproc(void *_args) +{ + struct postproc_args *a = _args; + struct super_block *sb; + aufs_bindex_t bindex, bend, bfound; + unsigned char xino, try_iput; + int err; + struct inode *inode; + ino_t h_ino; + struct hin_job_args args; + struct dentry *dentry; + struct au_sbinfo *sbinfo; + + AuDebugOn(!_args); + AuDebugOn(!a->h_dir); + AuDebugOn(!a->dir); + AuDebugOn(!a->mask); + LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n", + a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino, + a->h_child_inode ? a->h_child_inode->i_ino : 0); + + inode = NULL; + dentry = NULL; + /* + * do not lock a->dir->i_mutex here + * because of d_revalidate() may cause a deadlock. + */ + sb = a->dir->i_sb; + AuDebugOn(!sb); + sbinfo = au_sbi(sb); + AuDebugOn(!sbinfo); + /* big aufs lock */ + si_noflush_write_lock(sb); + + ii_read_lock_parent(a->dir); + bfound = -1; + bend = au_ibend(a->dir); + for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++) + if (au_h_iptr(a->dir, bindex) == a->h_dir) { + bfound = bindex; + break; + } + ii_read_unlock(a->dir); + if (unlikely(bfound < 0)) + goto out; + + xino = !!au_opt_test_xino(au_mntflags(sb)); + h_ino = 0; + if (a->h_child_inode) + h_ino = a->h_child_inode->i_ino; + + if (a->h_child_nlen + && (au_ftest_hinjob(a->flags[CHILD], GEN) + || au_ftest_hinjob(a->flags[CHILD], MNTPNT))) + dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen, + a->dir); + try_iput = 0; + if (dentry) + inode = dentry->d_inode; + if (xino && !inode && h_ino + && (au_ftest_hinjob(a->flags[CHILD], XINO0) + || au_ftest_hinjob(a->flags[CHILD], TRYXINO0) + || au_ftest_hinjob(a->flags[CHILD], GEN) + || au_ftest_hinjob(a->flags[CHILD], ATTR))) { + inode = lookup_wlock_by_ino(sb, bfound, h_ino); + try_iput = 1; + } + + args.flags = a->flags[CHILD]; + args.dentry = dentry; + args.inode = inode; + args.h_inode = a->h_child_inode; + args.dir = a->dir; + args.h_dir = a->h_dir; + args.h_name = a->h_child_name; + args.h_nlen = a->h_child_nlen; + err = hin_job(&args); + if (dentry) { + if (dentry->d_fsdata) + di_write_unlock(dentry); + dput(dentry); + } + if (inode && try_iput) { + ii_write_unlock(inode); + iput(inode); + } + + ii_write_lock_parent(a->dir); + args.flags = a->flags[PARENT]; + args.dentry = NULL; + args.inode = a->dir; + args.h_inode = a->h_dir; + args.dir = NULL; + args.h_dir = NULL; + args.h_name = NULL; + args.h_nlen = 0; + err = hin_job(&args); + ii_write_unlock(a->dir); + + out: + au_nwt_done(&sbinfo->si_nowait); + si_write_unlock(sb); + + iput(a->h_child_inode); + iput(a->h_dir); + iput(a->dir); + kfree(a); +} + +static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask, + u32 cookie, const char *h_child_name, + struct inode *h_child_inode) +{ + struct au_hinotify *hinotify; + struct postproc_args *args; + int len, wkq_err; + unsigned char isdir, isroot, wh; + char *p; + struct inode *dir; + unsigned int flags[2]; + + LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n", + watch->inode->i_ino, wd, mask, in_name(mask), cookie, + h_child_name ? h_child_name : "", + h_child_inode ? h_child_inode->i_ino : 0); + + /* if IN_UNMOUNT happens, there must be another bug */ + if (mask & (IN_IGNORED | IN_UNMOUNT)) { + put_inotify_watch(watch); + return; + } + +#ifdef DbgInotify + if (!h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) + AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s," + " hi%lu\n", + watch->inode->i_ino, wd, mask, in_name(mask), cookie, + h_child_name ? h_child_name : "", + h_child_inode ? h_child_inode->i_ino : 0); +#endif + + hinotify = container_of(watch, struct au_hinotify, hin_watch); + AuDebugOn(!hinotify || !hinotify->hin_aufs_inode); + if (au_hin_test_ignore(mask, hinotify)) { +#ifdef DbgInotify + AuDbg("ignored\n"); +#endif + return; + } +#if 0 /* tmp debug */ + if (h_child_name && !strcmp(h_child_name, AUFS_XINO_FNAME)) + { + AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n", + watch->inode->i_ino, wd, mask, in_name(mask), cookie, + h_child_name ? h_child_name : "", + h_child_inode ? h_child_inode->i_ino : 0); + //au_dbg_blocked(); + } +#endif + + dir = igrab(hinotify->hin_aufs_inode); + if (!dir) + return; + isroot = (dir->i_ino == AUFS_ROOT_INO); + len = 0; + wh = 0; + if (h_child_name) { + len = strlen(h_child_name); + if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { + h_child_name += AUFS_WH_PFX_LEN; + len -= AUFS_WH_PFX_LEN; + wh = 1; + } + } + + isdir = 0; + if (h_child_inode) + isdir = !!S_ISDIR(h_child_inode->i_mode); + flags[PARENT] = AuHinJob_ISDIR; + flags[CHILD] = 0; + if (isdir) + flags[CHILD] = AuHinJob_ISDIR; + switch (mask & IN_ALL_EVENTS) { + case IN_MODIFY: + /*FALLTHROUGH*/ + case IN_ATTRIB: + if (h_child_inode) { + if (!wh) + au_fset_hinjob(flags[CHILD], ATTR); + } else + au_fset_hinjob(flags[PARENT], ATTR); + break; + + /* IN_MOVED_FROM is the first event in rename(2) */ + case IN_MOVED_FROM: + case IN_MOVED_TO: + AuDebugOn(!h_child_name || !h_child_inode); + au_fset_hinjob(flags[CHILD], GEN); + au_fset_hinjob(flags[CHILD], ATTR); + if (1 || isdir) + au_fset_hinjob(flags[CHILD], XINO0); + au_fset_hinjob(flags[CHILD], MNTPNT); + + au_fset_hinjob(flags[PARENT], ATTR); + au_fset_hinjob(flags[PARENT], DIRENT); + break; + + case IN_CREATE: + AuDebugOn(!h_child_name || !h_child_inode); + au_fset_hinjob(flags[PARENT], ATTR); + au_fset_hinjob(flags[PARENT], DIRENT); + au_fset_hinjob(flags[CHILD], GEN); + /* hard link */ + if (!isdir && h_child_inode->i_nlink > 1) + au_fset_hinjob(flags[CHILD], ATTR); + break; + + case IN_DELETE: + /* + * aufs never be able to get this child inode. + * revalidation should be in d_revalidate() + * by checking i_nlink, i_generation or d_unhashed(). + */ + AuDebugOn(!h_child_name); + au_fset_hinjob(flags[PARENT], ATTR); + au_fset_hinjob(flags[PARENT], DIRENT); + au_fset_hinjob(flags[CHILD], GEN); + au_fset_hinjob(flags[CHILD], TRYXINO0); + au_fset_hinjob(flags[CHILD], MNTPNT); + break; + + case IN_DELETE_SELF: +#if 0 + if (!isroot) + au_fset_hinjob(flags[PARENT], GEN); + /*FALLTHROUGH*/ +#endif + + case IN_MOVE_SELF: +#if 0 + /* + * when an inotify is set to an aufs inode, + * such inode can be isolated and this event can be fired + * solely. + */ + AuDebugOn(h_child_name || h_child_inode); + if (unlikely(isroot)) { + AuWarn("root branch was moved\n"); + iput(dir); + return; + } + au_fset_hinjob(flags[PARENT], XINO0); + au_fset_hinjob(flags[PARENT], GEN); + au_fset_hinjob(flags[PARENT], ATTR); + au_fset_hinjob(flags[PARENT], DIRENT); + /* au_fset_hinjob(flags[PARENT], MNTPNT); */ + break; +#endif + + case IN_ACCESS: + default: + AuDebugOn(1); + } + + if (wh) + h_child_inode = NULL; + + /* iput() and kfree() will be called in postproc() */ + /* + * inotify_mutex is already acquired and kmalloc/prune_icache may lock + * iprune_mutex. strange. + */ + lockdep_off(); + args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS); + lockdep_on(); + if (unlikely(!args)) { + AuErr1("no memory\n"); + iput(dir); + return; + } + args->flags[PARENT] = flags[PARENT]; + args->flags[CHILD] = flags[CHILD]; + args->mask = mask; + args->dir = dir; + args->h_dir = igrab(watch->inode); + if (h_child_inode) + h_child_inode = igrab(h_child_inode); /* can be NULL */ + args->h_child_inode = h_child_inode; + args->h_child_nlen = len; + if (len) { + p = (void *)args; + p += sizeof(*args); + memcpy(p, h_child_name, len + 1); + } + + lockdep_off(); + wkq_err = au_wkq_nowait(postproc, args, dir->i_sb, /*dlgt*/0); + lockdep_on(); + if (unlikely(wkq_err)) + AuErr("wkq %d\n", wkq_err); +} + +static void aufs_inotify_destroy(struct inotify_watch *watch) +{ + return; +} + +static struct inotify_operations aufs_inotify_ops = { + .handle_event = aufs_inotify, + .destroy_watch = aufs_inotify_destroy +}; + +/* ---------------------------------------------------------------------- */ + +static void au_hin_destroy_cache(void) +{ + kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]); + au_cachep[AuCache_HINOTIFY] = NULL; +} + +int __init au_inotify_init(void) +{ + int err; + + err = -ENOMEM; + au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify); + if (au_cachep[AuCache_HINOTIFY]) { + err = 0; + in_handle = inotify_init(&aufs_inotify_ops); + if (IS_ERR(in_handle)) { + err = PTR_ERR(in_handle); + au_hin_destroy_cache(); + } + } + AuTraceErr(err); + return err; +} + +void au_inotify_fin(void) +{ + inotify_destroy(in_handle); + if (au_cachep[AuCache_HINOTIFY]) + au_hin_destroy_cache(); +} --- linux-2.6.27.orig/ubuntu/aufs/whout.c +++ linux-2.6.27/ubuntu/aufs/whout.c @@ -0,0 +1,1118 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * whiteout for logical deletion and opaque directory + * + * $Id: whout.c,v 1.13 2008/09/08 02:40:12 sfjro Exp $ + */ + +#include +#include +#include "aufs.h" + +#define WH_MASK S_IRUGO + +/* If a directory contains this file, then it is opaque. We start with the + * .wh. flag so that it is blocked by lookup. + */ +static struct qstr diropq_name = { + .name = AUFS_WH_DIROPQ, + .len = sizeof(AUFS_WH_DIROPQ) - 1 +}; + +/* + * generate whiteout name, which is NOT terminated by NULL. + * @name: original d_name.name + * @len: original d_name.len + * @wh: whiteout qstr + * returns zero when succeeds, otherwise error. + * succeeded value as wh->name should be freed by au_wh_name_free(). + */ +int au_wh_name_alloc(const char *name, int len, struct qstr *wh) +{ + char *p; + + AuDebugOn(!name || !len || !wh); + + if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN)) + return -ENAMETOOLONG; + + wh->len = len + AUFS_WH_PFX_LEN; + p = kmalloc(wh->len, GFP_NOFS); + wh->name = p; + if (p) { + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); + memcpy(p + AUFS_WH_PFX_LEN, name, len); + /* smp_mb(); */ + return 0; + } + return -ENOMEM; +} + +void au_wh_name_free(struct qstr *wh) +{ + AuDebugOn(!wh || !wh->name); + kfree(wh->name); +} + +/* ---------------------------------------------------------------------- */ + +/* + * test if the @wh_name exists under @h_parent. + * @try_sio specifies the necessary of super-io. + */ +int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio, + struct au_ndx *ndx) +{ + int err; + struct dentry *wh_dentry; + struct inode *h_dir; + unsigned int flags; + + LKTRTrace("%.*s/%.*s, ndx{%p, 0x%x}\n", AuDLNPair(h_parent), + wh_name->len, wh_name->name, ndx->nfsmnt, ndx->flags); + h_dir = h_parent->d_inode; + AuDebugOn(!S_ISDIR(h_dir->i_mode)); + + flags = 0; + if (ndx && ndx->nd) { + flags = ndx->nd->flags; + ndx->nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE); + } + + if (!try_sio) + wh_dentry = au_lkup_one(wh_name->name, h_parent, + wh_name->len, ndx); + else + wh_dentry = au_sio_lkup_one(wh_name->name, h_parent, + wh_name->len, ndx); + if (flags) + ndx->nd->flags = flags; + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + err = 0; + if (!wh_dentry->d_inode) + goto out_wh; /* success */ + + err = 1; + if (S_ISREG(wh_dentry->d_inode->i_mode)) + goto out_wh; /* success */ + + err = -EIO; + AuIOErr("%.*s Invalid whiteout entry type 0%o.\n", + AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode); + + out_wh: + dput(wh_dentry); + out: + AuTraceErr(err); + return err; +} + +/* + * test if the @h_dentry sets opaque or not. + */ +int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx) +{ + int err, try_sio; + struct inode *h_dir; + + LKTRTrace("dentry %.*s\n", AuDLNPair(h_dentry)); + h_dir = h_dentry->d_inode; + AuDebugOn(!S_ISDIR(h_dir->i_mode)); + + try_sio = au_test_h_perm_sio(h_dir, MAY_EXEC, + au_ftest_ndx(ndx->flags, DLGT)); + err = au_wh_test(h_dentry, &diropq_name, try_sio, ndx); + AuTraceErr(err); + return err; +} + +/* + * returns a negative dentry whose name is unique and temporary. + */ +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix, + struct au_ndx *ndx) +{ +#define HEX_LEN 4 + struct dentry *dentry; + int len, i; + char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1 + + HEX_LEN + 1], *name, *p; + static unsigned char cnt; + + LKTRTrace("hp %.*s, prefix %.*s\n", + AuDLNPair(h_parent), prefix->len, prefix->name); + AuDebugOn(!h_parent->d_inode); + + name = defname; + len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1; + if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) { + dentry = ERR_PTR(-ENAMETOOLONG); + if (unlikely(len >= PATH_MAX)) + goto out; + dentry = ERR_PTR(-ENOMEM); + name = kmalloc(len + 1, GFP_NOFS); + if (unlikely(!name)) + goto out; + } + + /* doubly whiteout-ed */ + memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); + p = name + AUFS_WH_PFX_LEN * 2; + memcpy(p, prefix->name, prefix->len); + p += prefix->len; + *p++ = '.'; + AuDebugOn(name + len + 1 - p <= HEX_LEN); + + for (i = 0; i < 3; i++) { + sprintf(p, "%.*d", HEX_LEN, cnt++); + dentry = au_sio_lkup_one(name, h_parent, len, ndx); + if (IS_ERR(dentry) || !dentry->d_inode) + goto out_name; + dput(dentry); + } + /* AuWarn("could not get random name\n"); */ + dentry = ERR_PTR(-EEXIST); + AuDbg("%.*s\n", len, name); + BUG(); + + out_name: + if (unlikely(name != defname)) + kfree(name); + out: + AuTraceErrPtr(dentry); + return dentry; +#undef HEX_LEN +} + +/* + * rename the @dentry of @bindex to the whiteouted temporary name. + */ +int au_whtmp_ren(struct inode *dir, aufs_bindex_t bindex, + struct dentry *h_dentry) +{ + int err, dlgt; + struct inode *h_dir; + struct dentry *h_parent, *tmp_dentry; + struct super_block *sb; + unsigned int mnt_flags; + struct au_hin_ignore ign; + struct vfsub_args vargs; + struct au_ndx ndx = { + .flags = 0, + .nd = NULL, + /* .br = NULL */ + }; + + LKTRTrace("%.*s\n", AuDLNPair(h_dentry)); + AuDebugOn(!h_dentry->d_inode); + h_parent = h_dentry->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + + sb = dir->i_sb; + mnt_flags = au_mntflags(sb); + dlgt = !!au_test_dlgt(mnt_flags); + if (unlikely(dlgt)) + au_fset_ndx(ndx.flags, DLGT); + ndx.nfsmnt = au_nfsmnt(sb, bindex); + tmp_dentry = au_whtmp_lkup(h_parent, &h_dentry->d_name, &ndx); + err = PTR_ERR(tmp_dentry); + if (IS_ERR(tmp_dentry)) + goto out; + + /* under the same dir, no need to lock_rename() */ + vfsub_args_init(&vargs, &ign, dlgt, 0); + AuDebugOn(!S_ISDIR(h_dentry->d_inode->i_mode)); + vfsub_ign_hinode(&vargs, IN_MOVED_FROM | IN_MOVED_TO, + au_hi(dir, bindex)); + err = vfsub_rename(h_dir, h_dentry, h_dir, tmp_dentry, &vargs); + AuTraceErr(err); + dput(tmp_dentry); + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int do_unlink_wh(struct au_hinode *hdir, struct inode *h_dir, + struct dentry *wh_dentry, const int dlgt) +{ + int err; + struct au_hin_ignore ign; + struct vfsub_args vargs; + + AuDebugOn(hdir && h_dir); + AuDebugOn(!hdir && !h_dir); + if (!h_dir) + h_dir = hdir->hi_inode; + LKTRTrace("hi%lu, wh %.*s\n", h_dir->i_ino, AuDLNPair(wh_dentry)); + AuDebugOn(!wh_dentry->d_inode || !S_ISREG(wh_dentry->d_inode->i_mode)); + + /* + * forces superio when the dir has a sticky bit. + * this may be a violation of unix fs semantics. + */ + vfsub_args_init(&vargs, &ign, dlgt, + (h_dir->i_mode & S_ISVTX) + && wh_dentry->d_inode->i_uid != current->fsuid); + vfsub_ign_hinode(&vargs, IN_DELETE, hdir); + err = vfsub_unlink(h_dir, wh_dentry, &vargs); + AuTraceErr(err); + return err; +} + +int au_wh_unlink_dentry(struct au_hinode *hdir, struct dentry *wh_dentry, + struct dentry *dentry, int dlgt) +{ + int err; + + LKTRTrace("i%lu, wh %.*s, d %p\n", + hdir->hi_inode->i_ino, AuDLNPair(wh_dentry), dentry); + AuDebugOn((dentry && au_dbwh(dentry) < 0) + || !wh_dentry->d_inode + || !S_ISREG(wh_dentry->d_inode->i_mode)); + + err = do_unlink_wh(hdir, /*h_dir*/NULL, wh_dentry, dlgt); + if (!err && dentry) + au_set_dbwh(dentry, -1); + + AuTraceErr(err); + return err; +} + +static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, + struct au_ndx *ndx) +{ + int err; + struct dentry *wh_dentry; + + LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(wh)); + + /* au_test_h_perm() is already done */ + wh_dentry = au_lkup_one(wh->name, h_parent, wh->len, ndx); + if (IS_ERR(wh_dentry)) + err = PTR_ERR(wh_dentry); + else { + err = 0; + if (wh_dentry->d_inode && S_ISREG(wh_dentry->d_inode->i_mode)) + err = do_unlink_wh(/*hdir*/NULL, h_parent->d_inode, + wh_dentry, + au_ftest_ndx(ndx->flags, DLGT)); + dput(wh_dentry); + } + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static void clean_wh(struct inode *h_dir, struct dentry *wh, + struct au_hinode *hdir, struct vfsub_args *vargs) +{ + int err; + + AuTraceEnter(); + + if (wh->d_inode) { + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_DELETE, hdir); + err = vfsub_unlink(h_dir, wh, vargs); + if (unlikely(err)) + AuWarn("failed unlink %.*s (%d), ignored.\n", + AuDLNPair(wh), err); + } +} + +static void au_whdir_clean(struct inode *h_dir, struct dentry *dentry, + struct au_hinode *hdir, struct vfsub_args *vargs) +{ + int err; + + AuTraceEnter(); + + if (dentry->d_inode) { + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_DELETE, hdir); + err = vfsub_rmdir(h_dir, dentry, vargs); + if (unlikely(err)) + AuWarn("failed rmdir %.*s (%d), ignored.\n", + AuDLNPair(dentry), err); + } +} + +static int test_linkable(struct inode *h_dir) +{ + if (h_dir->i_op && h_dir->i_op->link) + return 0; + return -ENOSYS; +} + +/* todo: should this mkdir be done in /sbin/mount.aufs script? */ +static int au_whdir(struct inode *h_dir, struct dentry *dentry, + struct au_hinode *hdir, struct vfsub_args *vargs) +{ + int err; + + err = -EEXIST; + if (!dentry->d_inode) { + int mode = S_IRWXU; + if (unlikely(au_test_nfs(dentry->d_sb))) + mode |= S_IXUGO; + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_CREATE, hdir); + err = vfsub_mkdir(h_dir, dentry, mode, vargs); + } else if (S_ISDIR(dentry->d_inode->i_mode)) + err = 0; + else + AuErr("unknown %.*s exists\n", AuDLNPair(dentry)); + + return err; +} + +/* + * initialize the whiteout base file/dir for @br. + */ +int au_wh_init(struct dentry *h_root, struct au_branch *br, + struct vfsmount *nfsmnt, struct super_block *sb, + aufs_bindex_t bindex) +{ + int err, i; + struct inode *h_dir; + struct au_hin_ignore ign; + struct vfsub_args vargs; + struct au_hinode *hdir; + struct au_wbr *wbr = br->br_wbr; + static const struct qstr base_name[] = { + [AuBrWh_BASE] = { + .name = AUFS_WH_BASENAME, + .len = sizeof(AUFS_WH_BASENAME) - 1 + }, + [AuBrWh_PLINK] = { + .name = AUFS_WH_PLINKDIR, + .len = sizeof(AUFS_WH_PLINKDIR) - 1 + }, + [AuBrWh_TMP] = { + .name = AUFS_WH_TMPDIR, + .len = sizeof(AUFS_WH_TMPDIR) - 1 + } + }; + struct { + const struct qstr *name; + struct dentry *dentry; + } base[] = { + [AuBrWh_BASE] = { + .name = base_name + AuBrWh_BASE, + .dentry = NULL + }, + [AuBrWh_PLINK] = { + .name = base_name + AuBrWh_PLINK, + .dentry = NULL + }, + [AuBrWh_TMP] = { + .name = base_name + AuBrWh_TMP, + .dentry = NULL + } + }; + struct au_ndx ndx = { + .nfsmnt = nfsmnt, + .flags = 0, /* always no dlgt */ + .nd = NULL, + /* .br = NULL */ + }; + const unsigned int mnt_flags = au_mntflags(sb); + const int do_plink = au_opt_test(mnt_flags, PLINK); + const int do_hinotify = au_opt_test(mnt_flags, UDBA_INOTIFY); + + LKTRTrace("nfsmnt %p\n", nfsmnt); + WbrWhMustWriteLock(wbr); + SiMustWriteLock(sb); + h_dir = h_root->d_inode; + + for (i = 0; i < AuBrWh_Last; i++) { + /* doubly whiteouted */ + base[i].dentry = au_wh_lkup(h_root, (void *)base[i].name, &ndx); + err = PTR_ERR(base[i].dentry); + if (IS_ERR(base[i].dentry)) + goto out; + AuDebugOn(wbr + && wbr->wbr_wh[i] + && wbr->wbr_wh[i] != base[i].dentry); + } + + if (wbr) + for (i = 0; i < AuBrWh_Last; i++) { + dput(wbr->wbr_wh[i]); + wbr->wbr_wh[i] = NULL; + } + + err = 0; + hdir = NULL; + if (unlikely(bindex >= 0 && do_hinotify)) + hdir = au_hi(sb->s_root->d_inode, bindex); + vfsub_args_init(&vargs, &ign, au_test_dlgt(mnt_flags), 0); + + switch (br->br_perm) { + case AuBrPerm_RR: + case AuBrPerm_RO: + case AuBrPerm_RRWH: + case AuBrPerm_ROWH: + clean_wh(h_dir, base[AuBrWh_BASE].dentry, hdir, &vargs); + au_whdir_clean(h_dir, base[AuBrWh_PLINK].dentry, hdir, &vargs); + au_whdir_clean(h_dir, base[AuBrWh_TMP].dentry, hdir, &vargs); + break; + + case AuBrPerm_RWNoLinkWH: + clean_wh(h_dir, base[AuBrWh_BASE].dentry, hdir, &vargs); + if (do_plink) { + err = test_linkable(h_dir); + if (unlikely(err)) + goto out_nolink; + + err = au_whdir(h_dir, base[AuBrWh_PLINK].dentry, hdir, + &vargs); + if (unlikely(err)) + goto out_err; + wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); + } else + au_whdir_clean(h_dir, base[AuBrWh_PLINK].dentry, hdir, + &vargs); + err = au_whdir(h_dir, base[AuBrWh_TMP].dentry, hdir, &vargs); + if (unlikely(err)) + goto out_err; + wbr->wbr_tmp = dget(base[AuBrWh_TMP].dentry); + break; + + case AuBrPerm_RW: + /* + * for the moment, aufs supports the branch filesystem + * which does not support link(2). + * testing on FAT which does not support i_op->setattr() fully + * either, copyup failed. + * finally, such filesystem will not be used as the writable + * branch. + */ + err = test_linkable(h_dir); + if (unlikely(err)) + goto out_nolink; + + err = -EEXIST; + /* + * todo: should this create be done + * in /sbin/mount.aufs script? + */ + if (!base[AuBrWh_BASE].dentry->d_inode) { + vfsub_args_reinit(&vargs); + vfsub_ign_hinode(&vargs, IN_CREATE, hdir); + err = au_h_create(h_dir, base[AuBrWh_BASE].dentry, + WH_MASK, &vargs, /*nd*/NULL, nfsmnt); + } + else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode)) + err = 0; + else + AuErr("unknown %.*s/%.*s exists\n", + AuDLNPair(h_root), + AuDLNPair(base[AuBrWh_BASE].dentry)); + if (unlikely(err)) + goto out_err; + + if (do_plink) { + err = au_whdir(h_dir, base[AuBrWh_PLINK].dentry, hdir, + &vargs); + if (unlikely(err)) + goto out_err; + wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); + } else + au_whdir_clean(h_dir, base[AuBrWh_PLINK].dentry, hdir, + &vargs); + wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry); + + err = au_whdir(h_dir, base[AuBrWh_TMP].dentry, hdir, &vargs); + if (unlikely(err)) + goto out_err; + wbr->wbr_tmp = dget(base[AuBrWh_TMP].dentry); + break; + + default: + BUG(); + } + + out: + for (i = 0; i < AuBrWh_Last; i++) + dput(base[i].dentry); + AuTraceErr(err); + return err; + out_nolink: + AuErr("%.*s doesn't support link(2), use noplink and rw+nolwh\n", + AuDLNPair(h_root)); + goto out; + out_err: + AuErr("an error(%d) on the writable branch %.*s(%s)\n", + err, AuDLNPair(h_root), au_sbtype(h_root->d_sb)); + goto out; +} + +struct reinit_br_wh { + struct super_block *sb; + struct au_branch *br; +}; + +static void reinit_br_wh(void *arg) +{ + int err; + struct reinit_br_wh *a = arg; + struct au_wbr *wbr; + struct inode *h_dir, *dir; + struct dentry *h_root; + aufs_bindex_t bindex; + struct au_hin_ignore ign; + struct vfsub_args vargs; + + AuTraceEnter(); + AuDebugOn(current->fsuid); + + err = 0; + wbr = a->br->br_wbr; + /* big aufs lock */ + si_noflush_write_lock(a->sb); + if (unlikely(!au_br_writable(a->br->br_perm))) + goto out; + bindex = au_br_index(a->sb, a->br->br_id); + if (unlikely(bindex < 0)) + goto out; + + AuDebugOn(!wbr); + AuDebugOn(!wbr->wbr_whbase || !wbr->wbr_whbase->d_inode); + + dir = a->sb->s_root->d_inode; + ii_read_lock_parent(dir); + h_root = dget_parent(wbr->wbr_whbase); + h_dir = h_root->d_inode; + AuDebugOn(!h_dir->i_op || !h_dir->i_op->link); + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + wbr_wh_write_lock(wbr); + if (!au_verify_parent(wbr->wbr_whbase, h_dir)) { + vfsub_args_init(&vargs, &ign, /*dlgt*/0, 0); + vfsub_ign_hinode(&vargs, IN_DELETE, au_hi(dir, bindex)); + err = vfsub_unlink(h_dir, wbr->wbr_whbase, &vargs); + } else { + AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase)); + err = 0; + } + dput(wbr->wbr_whbase); + wbr->wbr_whbase = NULL; + if (!err) + err = au_wh_init(h_root, a->br, au_do_nfsmnt(a->br->br_mnt), + a->sb, bindex); + wbr_wh_write_unlock(wbr); + mutex_unlock(&h_dir->i_mutex); + dput(h_root); + ii_read_unlock(dir); + + out: + if (wbr) + atomic_dec_return(&wbr->wbr_wh_running); + au_br_put(a->br); + au_nwt_done(&au_sbi(a->sb)->si_nowait); + si_write_unlock(a->sb); + kfree(arg); + if (unlikely(err)) + AuIOErr("err %d\n", err); +} + +static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br) +{ + int do_dec, wkq_err; + struct reinit_br_wh *arg; + + AuTraceEnter(); + AuDebugOn(!br->br_wbr); + + do_dec = 1; + if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1) + goto out; + + /* ignore ENOMEM */ + arg = kmalloc(sizeof(*arg), GFP_NOFS); + if (arg) { + /* + * dec(wh_running), kfree(arg) and au_br_put() + * in reinit function + */ + arg->sb = sb; + arg->br = br; + au_br_get(br); + wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*dlgt*/0); + if (unlikely(wkq_err)) { + atomic_dec_return(&br->br_wbr->wbr_wh_running); + au_br_put(br); + kfree(arg); + } + do_dec = 0; + } + + out: + if (do_dec) + atomic_dec_return(&br->br_wbr->wbr_wh_running); +} + +/* + * create the whiteout @wh. + */ +static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex, + struct dentry *wh, struct inode *dir) +{ + int err, dlgt; + struct au_branch *br; + struct au_wbr *wbr; + struct dentry *h_parent; + struct inode *h_dir; + struct au_hin_ignore ign; + struct vfsub_args vargs; + + LKTRTrace("%.*s\n", AuDLNPair(wh)); + h_parent = wh->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + br = au_sbr(sb, bindex); + wbr = br->br_wbr; + AuDebugOn(!wbr); + + dlgt = !!au_test_dlgt(au_mntflags(sb)); + wbr_wh_read_lock(wbr); + if (wbr->wbr_whbase) { + vfsub_args_init(&vargs, &ign, dlgt, 0); + if (unlikely(dir)) + vfsub_ign_hinode(&vargs, IN_CREATE, au_hi(dir, bindex)); + err = vfsub_link(wbr->wbr_whbase, h_dir, wh, &vargs); + if (!err || err != -EMLINK) + goto out; + + /* link count full. re-initialize br_whbase. */ + kick_reinit_br_wh(sb, br); + } + + /* return this error in this context */ + vfsub_args_init(&vargs, &ign, dlgt, 0); + if (unlikely(dir)) + vfsub_ign_hinode(&vargs, IN_CREATE, au_hi(dir, bindex)); + err = au_h_create(h_dir, wh, WH_MASK, &vargs, /*nd*/NULL, + au_do_nfsmnt(br->br_mnt)); + + out: + wbr_wh_read_unlock(wbr); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * create or remove the diropq. + */ +static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, + unsigned int flags) +{ + struct dentry *opq_dentry, *h_dentry; + struct inode *h_dir; + int err, dlgt; + struct super_block *sb; + struct au_ndx ndx = { + .flags = 0, + .nd = NULL, + /* .br = NULL */ + }; + + LKTRTrace("%.*s, bindex %d, flags 0x%x\n", + AuDLNPair(dentry), bindex, flags); + h_dentry = au_h_dptr(dentry, bindex); + AuDebugOn(!h_dentry); + h_dir = h_dentry->d_inode; + AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode)); + + /* already checked by au_test_h_perm(). */ + sb = dentry->d_sb; + ndx.nfsmnt = au_nfsmnt(sb, bindex); + dlgt = 0; + if (unlikely(au_ftest_diropq(flags, DLGT))) { + dlgt = 1; + au_fset_ndx(ndx.flags, DLGT); + } + opq_dentry = au_lkup_one(diropq_name.name, h_dentry, diropq_name.len, + &ndx); + if (IS_ERR(opq_dentry)) + goto out; + + if (au_ftest_diropq(flags, CREATE)) { + AuDebugOn(opq_dentry->d_inode); + err = link_or_create_wh(dentry->d_sb, bindex, opq_dentry, + dentry->d_inode); + if (!err) { + au_set_dbdiropq(dentry, bindex); + goto out; /* success */ + } + } else { + AuDebugOn(/* !S_ISDIR(dentry->d_inode->i_mode) + * || */!opq_dentry->d_inode); + err = do_unlink_wh(au_hi(dentry->d_inode, bindex), + /*h_dir*/NULL, opq_dentry, dlgt); + if (!err) + au_set_dbdiropq(dentry, -1); + } + dput(opq_dentry); + opq_dentry = ERR_PTR(err); + + out: + AuTraceErrPtr(opq_dentry); + return opq_dentry; +} + +struct do_diropq_args { + struct dentry **errp; + struct dentry *dentry; + aufs_bindex_t bindex; + unsigned int flags; +}; + +static void call_do_diropq(void *args) +{ + struct do_diropq_args *a = args; + *a->errp = do_diropq(a->dentry, a->bindex, a->flags); +} + +struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, + unsigned int flags) +{ + struct dentry *diropq, *h_dentry; + + LKTRTrace("%.*s, bindex %d, flags 0x%x\n", + AuDLNPair(dentry), bindex, flags); + + h_dentry = au_h_dptr(dentry, bindex); + if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE, + au_ftest_diropq(flags, DLGT))) + diropq = do_diropq(dentry, bindex, flags); + else { + int wkq_err; + struct do_diropq_args args = { + .errp = &diropq, + .dentry = dentry, + .bindex = bindex, + .flags = flags + }; + wkq_err = au_wkq_wait(call_do_diropq, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + diropq = ERR_PTR(wkq_err); + } + + AuTraceErrPtr(diropq); + return diropq; +} + +/* ---------------------------------------------------------------------- */ + +/* + * lookup whiteout dentry. + * @h_parent: hidden parent dentry which must exist and be locked + * @base_name: name of dentry which will be whiteouted + * returns dentry for whiteout. + */ +struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, + struct au_ndx *ndx) +{ + int err; + struct qstr wh_name; + struct dentry *wh_dentry; + + LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(base_name)); + + err = au_wh_name_alloc(base_name->name, base_name->len, &wh_name); + wh_dentry = ERR_PTR(err); + if (!err) { + /* do not superio. */ + wh_dentry = au_lkup_one(wh_name.name, h_parent, + wh_name.len, ndx); + au_wh_name_free(&wh_name); + } + AuTraceErrPtr(wh_dentry); + return wh_dentry; +} + +/* + * link/create a whiteout for @dentry on @bindex. + */ +struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, struct au_ndx *ndx) +{ + struct dentry *wh_dentry; + struct inode *dir; + int err; + struct super_block *sb; + + LKTRTrace("%.*s/%.*s on b%d\n", AuDLNPair(h_parent), + AuDLNPair(dentry), bindex); + + sb = dentry->d_sb; + wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, ndx); + if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) { + dir = dentry->d_parent->d_inode; /* dir is locked */ + IMustLock(dir); + err = link_or_create_wh(sb, bindex, wh_dentry, dir); + if (!err) + au_set_dbwh(dentry, bindex); + else { + dput(wh_dentry); + wh_dentry = ERR_PTR(err); + } + } + + AuTraceErrPtr(wh_dentry); + return wh_dentry; +} + +/* ---------------------------------------------------------------------- */ + +/* Delete all whiteouts in this directory on branch bindex. */ +static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, + aufs_bindex_t bindex, struct au_ndx *ndx) +{ + int err, i; + struct qstr wh_name; + char *p; + struct inode *h_inode; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + struct au_vdir_destr *str; + + LKTRTrace("%.*s\n", AuDLNPair(h_dentry)); + h_inode = h_dentry->d_inode; + AuDebugOn(IS_RDONLY(h_inode)); + + err = -ENOMEM; + p = __getname(); + wh_name.name = p; + if (unlikely(!wh_name.name)) + goto out; + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); + p += AUFS_WH_PFX_LEN; + + /* already checked by au_test_h_perm(). */ + err = 0; + for (i = 0; !err && i < AuSize_NHASH; i++) { + head = whlist->heads + i; + hlist_for_each_entry(tpos, pos, head, wh_hash) { + if (tpos->wh_bindex != bindex) + continue; + str = &tpos->wh_str; + if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { + memcpy(p, str->name, str->len); + wh_name.len = AUFS_WH_PFX_LEN + str->len; + err = unlink_wh_name(h_dentry, &wh_name, ndx); + if (!err) + continue; + break; + } + AuIOErr("whiteout name too long %.*s\n", + str->len, str->name); + err = -EIO; + break; + } + } + __putname(wh_name.name); + + out: + AuTraceErr(err); + return err; +} + +struct del_wh_children_args { + int *errp; + struct dentry *h_dentry; + struct au_nhash *whlist; + aufs_bindex_t bindex; + struct au_ndx *ndx; +}; + +static void call_del_wh_children(void *args) +{ + struct del_wh_children_args *a = args; + *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->ndx); +} + +/* ---------------------------------------------------------------------- */ + +/* + * rmdir the whiteouted temporary named dir @h_dentry. + * @whlist: whiteouted children. + */ +int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_nhash *whlist) +{ + int err, dlgt; + struct inode *wh_inode, *h_dir; + struct super_block *sb; + unsigned int mnt_flags; + struct au_hin_ignore ign; + struct vfsub_args vargs; + struct au_ndx ndx = { + .flags = 0, + .nd = NULL, + /* .br = NULL */ + }; + + LKTRTrace("i%lu, %.*s, b%d\n", + dir->i_ino, AuDLNPair(wh_dentry), bindex); + /* IMustLock(dir); */ + IiMustAnyLock(dir); + h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */ + IMustLock(h_dir); + + sb = dir->i_sb; + mnt_flags = au_mntflags(sb); + dlgt = !!au_test_dlgt(mnt_flags); + if (unlikely(dlgt)) + au_fset_ndx(ndx.flags, DLGT); + ndx.nfsmnt = au_nfsmnt(sb, bindex); + wh_inode = wh_dentry->d_inode; + mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD); + + /* + * someone else might change some whiteouts while we were sleeping. + * it means this whlist may have an obsoleted entry. + */ + if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE, dlgt)) + err = del_wh_children(wh_dentry, whlist, bindex, &ndx); + else { + int wkq_err; + /* ugly */ + unsigned int flags = ndx.flags; + struct del_wh_children_args args = { + .errp = &err, + .h_dentry = wh_dentry, + .whlist = whlist, + .bindex = bindex, + .ndx = &ndx + }; + + ndx.flags = 0; + wkq_err = au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + ndx.flags = flags; + } + mutex_unlock(&wh_inode->i_mutex); + + if (!err) { + vfsub_args_init(&vargs, &ign, dlgt, 0); + vfsub_ign_hinode(&vargs, IN_DELETE, au_hi(dir, bindex)); + err = vfsub_rmdir(h_dir, wh_dentry, &vargs); + /* d_drop(h_dentry); */ + } + + if (!err) { + if (au_ibstart(dir) == bindex) { + au_cpup_attr_timesizes(dir); + /* au_cpup_attr_nlink(dir); */ + drop_nlink(dir); + } + return 0; /* success */ + } + + AuWarn("failed removing %.*s(%d), ignored\n", + AuDLNPair(wh_dentry), err); + return err; +} + +static void au_whtmp_rmdir_free_args(struct au_whtmp_rmdir_args *args) +{ + au_nhash_fin(&args->whlist); + dput(args->wh_dentry); + iput(args->dir); + kfree(args); +} + +static void call_rmdir_whtmp(void *args) +{ + int err; + struct au_whtmp_rmdir_args *a = args; + struct super_block *sb; + struct dentry *h_parent; + struct inode *h_dir; + + LKTRTrace("%.*s, b%d, dir i%lu\n", + AuDLNPair(a->wh_dentry), a->bindex, a->dir->i_ino); + + /* rmdir by nfsd may cause deadlock with this i_mutex */ + /* mutex_lock(&a->dir->i_mutex); */ + sb = a->dir->i_sb; + si_noflush_read_lock(sb); + err = au_test_ro(sb, a->bindex, NULL); + if (unlikely(err)) + goto out; + + err = -EIO; + ii_write_lock_parent(a->dir); + h_parent = dget_parent(a->wh_dentry); + h_dir = h_parent->d_inode; + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + if (!au_verify_parent(a->wh_dentry, h_dir)) + err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry, + &a->whlist); + mutex_unlock(&h_dir->i_mutex); + dput(h_parent); + ii_write_unlock(a->dir); + + out: + /* mutex_unlock(&a->dir->i_mutex); */ + au_nwt_done(&au_sbi(sb)->si_nowait); + si_read_unlock(sb); + au_whtmp_rmdir_free_args(a); + if (unlikely(err)) + AuIOErr("err %d\n", err); +} + +void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_nhash *whlist, + struct au_whtmp_rmdir_args *args) +{ + int wkq_err; + + LKTRTrace("%.*s\n", AuDLNPair(wh_dentry)); + IMustLock(dir); + + /* all post-process will be done in do_rmdir_whtmp(). */ + args->dir = au_igrab(dir); + args->bindex = bindex; + args->wh_dentry = dget(wh_dentry); + au_nhash_init(&args->whlist); + au_nhash_move(&args->whlist, whlist); + wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb, /*dlgt*/0); + if (unlikely(wkq_err)) { + AuWarn("rmdir error %.*s (%d), ignored\n", + AuDLNPair(wh_dentry), wkq_err); + au_whtmp_rmdir_free_args(args); + } +} --- linux-2.6.27.orig/ubuntu/aufs/dinfo.c +++ linux-2.6.27/ubuntu/aufs/dinfo.c @@ -0,0 +1,426 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * dentry private data + * + * $Id: dinfo.c,v 1.7 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include "aufs.h" + +int au_alloc_dinfo(struct dentry *dentry) +{ + struct au_dinfo *dinfo; + struct super_block *sb; + int nbr; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + AuDebugOn(dentry->d_fsdata); + + dinfo = au_cache_alloc_dinfo(); + if (dinfo) { + sb = dentry->d_sb; + nbr = au_sbend(sb) + 1; + if (unlikely(nbr <= 0)) + nbr = 1; + dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), + GFP_NOFS); + if (dinfo->di_hdentry) { + au_h_dentry_init_all(dinfo->di_hdentry, nbr); + atomic_set(&dinfo->di_generation, au_sigen(sb)); + /* smp_mb(); */ /* atomic_set */ + au_rw_init_wlock_nested(&dinfo->di_rwsem, + AuLsc_DI_CHILD); + dinfo->di_bstart = -1; + dinfo->di_bend = -1; + dinfo->di_bwh = -1; + dinfo->di_bdiropq = -1; + + dentry->d_fsdata = dinfo; + dentry->d_op = &aufs_dop; + return 0; /* success */ + } + au_cache_free_dinfo(dinfo); + } + AuTraceErr(-ENOMEM); + return -ENOMEM; +} + +struct au_dinfo *au_di(struct dentry *dentry) +{ + struct au_dinfo *dinfo = dentry->d_fsdata; + AuDebugOn(!dinfo + || !dinfo->di_hdentry + /* || au_sbi(dentry->d_sb)->si_bend < dinfo->di_bend */ + || dinfo->di_bend < dinfo->di_bstart + /* dbwh can be outside of this range */ + || (0 <= dinfo->di_bdiropq + && (dinfo->di_bdiropq < dinfo->di_bstart + /* || dinfo->di_bend < dinfo->di_bdiropq */)) + ); + return dinfo; +} + +/* ---------------------------------------------------------------------- */ + +static void do_ii_write_lock(struct inode *inode, unsigned int lsc) +{ + switch (lsc) { + case AuLsc_DI_CHILD: + ii_write_lock_child(inode); + break; + case AuLsc_DI_CHILD2: + ii_write_lock_child2(inode); + break; + case AuLsc_DI_CHILD3: + ii_write_lock_child3(inode); + break; + case AuLsc_DI_PARENT: + ii_write_lock_parent(inode); + break; + case AuLsc_DI_PARENT2: + ii_write_lock_parent2(inode); + break; + case AuLsc_DI_PARENT3: + ii_write_lock_parent3(inode); + break; + case AuLsc_DI_PARENT4: + ii_write_lock_parent4(inode); + break; + default: + BUG(); + } +} + +static void do_ii_read_lock(struct inode *inode, unsigned int lsc) +{ + switch (lsc) { + case AuLsc_DI_CHILD: + ii_read_lock_child(inode); + break; + case AuLsc_DI_CHILD2: + ii_read_lock_child2(inode); + break; + case AuLsc_DI_CHILD3: + ii_read_lock_child3(inode); + break; + case AuLsc_DI_PARENT: + ii_read_lock_parent(inode); + break; + case AuLsc_DI_PARENT2: + ii_read_lock_parent2(inode); + break; + case AuLsc_DI_PARENT3: + ii_read_lock_parent3(inode); + break; + case AuLsc_DI_PARENT4: + ii_read_lock_parent4(inode); + break; + default: + BUG(); + } +} + +void di_read_lock(struct dentry *d, int flags, unsigned int lsc) +{ + LKTRTrace("%.*s, %u\n", AuDLNPair(d), lsc); + SiMustAnyLock(d->d_sb); + + /* todo: always nested? */ + au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc); + if (d->d_inode) { + if (au_ftest_lock(flags, IW)) + do_ii_write_lock(d->d_inode, lsc); + else if (au_ftest_lock(flags, IR)) + do_ii_read_lock(d->d_inode, lsc); + } +} + +void di_read_unlock(struct dentry *d, int flags) +{ + LKTRTrace("%.*s\n", AuDLNPair(d)); + SiMustAnyLock(d->d_sb); + + if (d->d_inode) { + if (au_ftest_lock(flags, IW)) + ii_write_unlock(d->d_inode); + else if (au_ftest_lock(flags, IR)) + ii_read_unlock(d->d_inode); + } + au_rw_read_unlock(&au_di(d)->di_rwsem); +} + +void di_downgrade_lock(struct dentry *d, int flags) +{ + SiMustAnyLock(d->d_sb); + + au_rw_dgrade_lock(&au_di(d)->di_rwsem); + if (d->d_inode && au_ftest_lock(flags, IR)) + ii_downgrade_lock(d->d_inode); +} + +void di_write_lock(struct dentry *d, unsigned int lsc) +{ + LKTRTrace("%.*s, %u\n", AuDLNPair(d), lsc); + SiMustAnyLock(d->d_sb); + + /* todo: always nested? */ + au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc); + if (d->d_inode) + do_ii_write_lock(d->d_inode, lsc); +} + +void di_write_unlock(struct dentry *d) +{ + LKTRTrace("%.*s\n", AuDLNPair(d)); + SiMustAnyLock(d->d_sb); + + if (d->d_inode) + ii_write_unlock(d->d_inode); + au_rw_write_unlock(&au_di(d)->di_rwsem); +} + +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir) +{ + AuTraceEnter(); + AuDebugOn(d1 == d2 + || d1->d_inode == d2->d_inode + || d1->d_sb != d2->d_sb); + + if (isdir && au_test_subdir(d1, d2)) { + di_write_lock_child(d1); + di_write_lock_child2(d2); + } else { + /* there should be no races */ + di_write_lock_child(d2); + di_write_lock_child2(d1); + } +} + +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) +{ + AuTraceEnter(); + AuDebugOn(d1 == d2 + || d1->d_inode == d2->d_inode + || d1->d_sb != d2->d_sb); + + if (isdir && au_test_subdir(d1, d2)) { + di_write_lock_parent(d1); + di_write_lock_parent2(d2); + } else { + /* there should be no races */ + di_write_lock_parent(d2); + di_write_lock_parent2(d1); + } +} + +void di_write_unlock2(struct dentry *d1, struct dentry *d2) +{ + di_write_unlock(d1); + if (d1->d_inode == d2->d_inode) + au_rw_write_unlock(&au_di(d2)->di_rwsem); + else + di_write_unlock(d2); +} + +/* ---------------------------------------------------------------------- */ + +struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) +{ + struct dentry *d; + + DiMustAnyLock(dentry); + if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry)) + return NULL; + AuDebugOn(bindex < 0 + /* || bindex > au_sbend(dentry->d_sb) */); + d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry; + AuDebugOn(d && (atomic_read(&d->d_count) <= 0)); + return d; +} + +aufs_bindex_t au_dbtail(struct dentry *dentry) +{ + aufs_bindex_t bend, bwh; + + bend = au_dbend(dentry); + if (0 <= bend) { + bwh = au_dbwh(dentry); + if (!bwh) + return bwh; + if (0 < bwh && bwh < bend) + return bwh - 1; + } + return bend; +} + +aufs_bindex_t au_dbtaildir(struct dentry *dentry) +{ + aufs_bindex_t bend, bopq; + + AuDebugOn(dentry->d_inode + && dentry->d_inode->i_mode + && !S_ISDIR(dentry->d_inode->i_mode)); + + bend = au_dbtail(dentry); + if (0 <= bend) { + bopq = au_dbdiropq(dentry); + AuDebugOn(bend < bopq); + if (0 <= bopq && bopq < bend) + bend = bopq; + } + return bend; +} + +#if 0 /* reserved for future use */ +aufs_bindex_t au_dbtail_generic(struct dentry *dentry) +{ + struct inode *inode; + + inode = dentry->d_inode; + if (inode && S_ISDIR(inode->i_mode)) + return au_dbtaildir(dentry); + else + return au_dbtail(dentry); +} +#endif + +/* ---------------------------------------------------------------------- */ + +void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + AuDebugOn(au_sbend(dentry->d_sb) < bindex); + AuDebugOn((bindex >= 0 + && (bindex < au_dbstart(dentry) + || au_dbend(dentry) < bindex)) + || (dentry->d_inode + && dentry->d_inode->i_mode + && !S_ISDIR(dentry->d_inode->i_mode))); + au_di(dentry)->di_bdiropq = bindex; +} + +void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_dentry) +{ + struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex; + DiMustWriteLock(dentry); + AuDebugOn(bindex < au_di(dentry)->di_bstart + || bindex > au_di(dentry)->di_bend + || (h_dentry && atomic_read(&h_dentry->d_count) <= 0) + || (h_dentry && hd->hd_dentry) + ); + if (hd->hd_dentry) + au_hdput(hd, /*do_free*/0); + hd->hd_dentry = h_dentry; +} + +/* ---------------------------------------------------------------------- */ + +void au_update_dbrange(struct dentry *dentry, int do_put_zero) +{ + struct au_dinfo *dinfo; + aufs_bindex_t bindex; + struct dentry *h_d; + + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), do_put_zero); + DiMustWriteLock(dentry); + + dinfo = au_di(dentry); + if (unlikely(!dinfo) || dinfo->di_bstart < 0) + return; + + if (do_put_zero) { + for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; + bindex++) { + h_d = dinfo->di_hdentry[0 + bindex].hd_dentry; + if (h_d && !h_d->d_inode) + au_set_h_dptr(dentry, bindex, NULL); + } + } + + dinfo->di_bstart = -1; + while (++dinfo->di_bstart <= dinfo->di_bend) + if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry) + break; + if (dinfo->di_bstart > dinfo->di_bend) { + dinfo->di_bstart = -1; + dinfo->di_bend = -1; + return; + } + + dinfo->di_bend++; + while (0 <= --dinfo->di_bend) + if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry) + break; + AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0); +} + +void au_update_dbstart(struct dentry *dentry) +{ + aufs_bindex_t bindex, + bstart = au_dbstart(dentry), + bend = au_dbend(dentry); + struct dentry *h_dentry; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + DiMustWriteLock(dentry); + + for (bindex = bstart; bindex <= bend; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + if (h_dentry->d_inode) { + au_set_dbstart(dentry, bindex); + return; + } + au_set_h_dptr(dentry, bindex, NULL); + } +} + +void au_update_dbend(struct dentry *dentry) +{ + aufs_bindex_t bindex, + bstart = au_dbstart(dentry), + bend = au_dbend(dentry); + struct dentry *h_dentry; + + DiMustWriteLock(dentry); + for (bindex = bend; bindex <= bstart; bindex--) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + if (h_dentry->d_inode) { + au_set_dbend(dentry, bindex); + return; + } + au_set_h_dptr(dentry, bindex, NULL); + } +} + +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry) +{ + aufs_bindex_t bindex, bend; + + bend = au_dbend(dentry); + for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) + if (au_h_dptr(dentry, bindex) == h_dentry) + return bindex; + return -1; +} --- linux-2.6.27.orig/ubuntu/aufs/aufs.h +++ linux-2.6.27/ubuntu/aufs/aufs.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * main header files + * + * $Id: aufs.h,v 1.4 2008/06/30 03:58:55 sfjro Exp $ + */ + +#ifndef __AUFS_H__ +#define __AUFS_H__ + +#ifdef __KERNEL__ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) +#error you got wrong version +#endif + +#include "debug.h" + +#include "branch.h" +#include "cpup.h" +#include "dcsub.h" +#include "dentry.h" +#include "dir.h" +#include "file.h" +#include "hinode.h" +#include "inode.h" +#include "misc.h" +#include "module.h" +#include "opts.h" +#include "super.h" +#include "sysaufs.h" +#include "vfsub.h" +#include "whout.h" +#include "wkq.h" +/* reserved for future use */ +/* #include "xattr.h" */ + +#ifdef AuNoInlineForStack +#undef noinline_for_stack +#define noinline_for_stack /* */ +#endif + +#endif /* __KERNEL__ */ +#endif /* __AUFS_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/i_op_del.c +++ linux-2.6.27/ubuntu/aufs/i_op_del.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations (del entry) + * + * $Id: i_op_del.c,v 1.12 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include "aufs.h" + +/* returns, + * 0: wh is unnecessary + * plus: wh is necessary + * minus: error + */ +int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup) +{ + int need_wh, err; + aufs_bindex_t bstart; + struct dentry *h_dentry; + struct super_block *sb; + + LKTRTrace("%.*s, isdir %d, *bcpup %d\n", + AuDLNPair(dentry), isdir, *bcpup); + sb = dentry->d_sb; + + bstart = au_dbstart(dentry); + LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart); + h_dentry = au_h_dptr(dentry, bstart); + if (*bcpup < 0) { + *bcpup = bstart; + if (au_test_ro(sb, bstart, dentry->d_inode)) { + err = AuWbrCopyup(au_sbi(sb), dentry); + *bcpup = err; + if (unlikely(err < 0)) + goto out; + } + } else + AuDebugOn(bstart < *bcpup + || au_test_ro(sb, *bcpup, dentry->d_inode)); + LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart); + + if (*bcpup != bstart) { + err = au_cpup_dirs(dentry, *bcpup); + if (unlikely(err)) + goto out; + need_wh = 1; + } else { + aufs_bindex_t old_bend, new_bend, bdiropq = -1; + old_bend = au_dbend(dentry); + if (isdir) { + bdiropq = au_dbdiropq(dentry); + au_set_dbdiropq(dentry, -1); + } + need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0, + /*nd*/NULL); + err = need_wh; + if (isdir) + au_set_dbdiropq(dentry, bdiropq); + if (unlikely(err < 0)) + goto out; + new_bend = au_dbend(dentry); + if (!need_wh && old_bend != new_bend) { + au_set_h_dptr(dentry, new_bend, NULL); + au_set_dbend(dentry, old_bend); +#if 0 /* todo: remove this? */ + } else if (!au_h_dptr(dentry, new_bend)->d_inode) { + LKTRTrace("negative\n"); + au_set_h_dptr(dentry, new_bend, NULL); + au_set_dbend(dentry, old_bend); + need_wh = 0; +#endif + } + } + LKTRTrace("need_wh %d\n", need_wh); + err = need_wh; + + out: + AuTraceErr(err); + return err; +} + +/* + * simple tests for the removal inode operations. + * following the checks in vfs, plus the parent-child relationship. + */ +int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir, struct au_ndx *ndx) +{ + int err, exist; + struct super_block *sb; + struct dentry *h_dentry; + struct inode *h_inode; + umode_t h_mode; + + LKTRTrace("%.*s/%.*s, b%d, dir %d\n", + AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir); + + sb = dentry->d_sb; + exist = !!dentry->d_inode; + h_dentry = au_h_dptr(dentry, bindex); + h_inode = h_dentry->d_inode; + if (exist) { + err = -ENOENT; + if (unlikely(!h_inode || !h_inode->i_nlink)) + goto out; + + h_mode = h_inode->i_mode; + if (!isdir) { + err = -EISDIR; + if (unlikely(S_ISDIR(h_mode))) + goto out; + } else if (unlikely(!S_ISDIR(h_mode))) { + err = -ENOTDIR; + goto out; + } + } else { + /* rename(2) case */ + err = -EIO; + if (unlikely(h_inode)) + goto out; + } + + err = -ENOENT; + /* expected parent dir is locked */ + if (unlikely(h_parent != h_dentry->d_parent)) + goto out; + err = 0; + + /* + * some filesystem may unlink a dir and corrupt its consistency. + * so let's try heavy test. + */ + if (1 /*unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY))*/) { + struct dentry *h_latest; + struct qstr *qstr = &dentry->d_name; + + err = -EACCES; + if (unlikely(au_test_h_perm(h_parent->d_inode, + MAY_EXEC | MAY_WRITE, + au_ftest_ndx(ndx->flags, DLGT)))) + goto out; + + h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len, + ndx); + err = -EIO; + if (IS_ERR(h_latest)) + goto out; + dput(h_latest); + if (h_latest == h_dentry) + err = 0; + } + + out: + AuTraceErr(err); + return err; +} + +static struct dentry * +lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup, + struct au_dtime *dt, struct au_pin *pin) +{ + struct dentry *wh_dentry; + int err, need_wh; + struct dentry *h_parent; + struct au_ndx ndx; + struct super_block *sb; + aufs_bindex_t bcpup; + unsigned int mnt_flags; + + LKTRTrace("%.*s, isdir %d\n", AuDLNPair(dentry), isdir); + + need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup); + err = need_wh; + wh_dentry = ERR_PTR(err); + if (unlikely(err < 0)) + goto out; + + sb = dentry->d_sb; + mnt_flags = au_mntflags(sb); + bcpup = *rbcpup; + err = au_pin(pin, dentry, bcpup, /*di_locked*/1, + /*do_gp*/au_opt_test(mnt_flags, UDBA_INOTIFY)); + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out; + h_parent = au_pinned_h_parent(pin, bcpup); + if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) { + ndx.nfsmnt = au_nfsmnt(sb, bcpup); + ndx.flags = 0; + if (unlikely(au_test_dlgt(mnt_flags))) + au_fset_ndx(ndx.flags, DLGT); + ndx.nd = NULL; + /* ndx.br = au_sbr(sb, bcpup); */ + /* ndx.nd_file = NULL; */ + err = au_may_del(dentry, bcpup, h_parent, isdir, &ndx); + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_unpin; + } + + au_dtime_store(dt, au_pinned_parent(pin), h_parent, + au_pinned_hdir(pin, bcpup), au_pinned_hgdir(pin, bcpup)); + wh_dentry = NULL; + if (!need_wh) + goto out; /* success, no need to create whiteout */ + + ndx.nfsmnt = au_nfsmnt(sb, bcpup); + ndx.flags = 0; + if (unlikely(au_test_dlgt(mnt_flags))) + au_fset_ndx(ndx.flags, DLGT); + ndx.nd = NULL; + /* ndx.br = NULL; */ + wh_dentry = au_wh_create(dentry, bcpup, h_parent, &ndx); + if (!IS_ERR(wh_dentry)) + goto out; /* success */ + /* returns with the parent is locked and wh_dentry is DGETed */ + + out_unpin: + au_unpin(pin); + out: + AuTraceErrPtr(wh_dentry); + return wh_dentry; +} + +static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, + struct au_nhash *whlist, struct inode *dir) +{ + int rmdir_later, err; + struct dentry *h_dentry; + struct inode *inode, *h_inode; + struct super_block *sb; + + LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex); + + inode = NULL; + h_inode = NULL; + sb = dentry->d_sb; + if (unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY))) { + inode = dentry->d_inode; + h_inode = au_h_iptr(inode, bindex); + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + } + h_dentry = au_h_dptr(dentry, bindex); + err = au_whtmp_ren(dir, bindex, h_dentry); + if (unlikely(inode)) { + /* todo: bad approach? */ + if (!err) + au_hin_suspend(au_hi(inode, bindex)); + mutex_unlock(&h_inode->i_mutex); + } + if (unlikely(err)) + goto out; + + if (!au_test_nfs(h_dentry->d_sb)) { + const int dirwh = au_sbi(sb)->si_dirwh; + rmdir_later = (dirwh <= 1); + if (!rmdir_later) + rmdir_later = au_nhash_test_longer_wh(whlist, bindex, + dirwh); + if (rmdir_later) + return rmdir_later; + } + + err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist); + if (unlikely(err)) { + AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n", + AuDLNPair(h_dentry), bindex, err); + /* we do not revert the inotify watch */ + err = 0; + } + + out: + AuTraceErr(err); + return err; +} + +static void epilog(struct inode *dir, struct dentry *dentry, + aufs_bindex_t bindex) +{ + /* todo: unnecessary? */ + d_drop(dentry); + dentry->d_inode->i_ctime = dir->i_ctime; + + if (atomic_read(&dentry->d_count) == 1) { + au_set_h_dptr(dentry, au_dbstart(dentry), NULL); + au_update_dbstart(dentry); + } + if (au_ibstart(dir) == bindex) + au_cpup_attr_timesizes(dir); + dir->i_version++; +} + +/* revert flags */ +#define AuRev_DLGT 1 +#define au_ftest_rev(flags, name) ((flags) & AuRev_##name) +#define au_fset_rev(flags, name) { (flags) |= AuRev_##name; } +#define au_fclr_rev(flags, name) { (flags) &= ~AuRev_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef AuRev_DLGT +#define AuRev_DLGT 0 +#endif + +static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh, + struct dentry *wh_dentry, struct dentry *dentry, + struct au_dtime *dt, unsigned int flags) +{ + int rerr; + + rerr = au_wh_unlink_dentry(au_hi(dir, bwh), wh_dentry, dentry, + au_ftest_rev(flags, DLGT)); + if (!rerr) { + au_set_dbwh(dentry, bwh); + au_dtime_revert(dt); + return 0; + } + + AuIOErr("%.*s reverting whiteout failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + return -EIO; +} + +/* ---------------------------------------------------------------------- */ + +int aufs_unlink(struct inode *dir, struct dentry *dentry) +{ + int err; + struct inode *inode, *h_dir; + struct dentry *parent, *wh_dentry, *h_dentry; + struct au_dtime dt; + aufs_bindex_t bwh, bindex, bstart; + unsigned char dlgt; + struct super_block *sb; + struct au_hin_ignore ign; + struct vfsub_args vargs; + struct au_pin pin; + + LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); + IMustLock(dir); + inode = dentry->d_inode; + if (unlikely(!inode)) + return -ENOENT; /* possible? */ + IMustLock(inode); + + aufs_read_lock(dentry, AuLock_DW); + parent = dentry->d_parent; /* dir inode is locked */ + di_write_lock_parent(parent); + + bstart = au_dbstart(dentry); + bwh = au_dbwh(dentry); + bindex = -1; + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + sb = dir->i_sb; + dlgt = !!au_test_dlgt(au_mntflags(sb)); + AuDebugOn(au_dbstart(dentry) != bstart); + h_dentry = au_h_dptr(dentry, bstart); + dget(h_dentry); + + if (bindex == bstart) { + vfsub_args_init(&vargs, &ign, dlgt, 0); + vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin, + bstart)); + h_dir = au_pinned_h_dir(&pin); + err = vfsub_unlink(h_dir, h_dentry, &vargs); + } else { + /* dir inode is locked */ + AuDebugOn(!wh_dentry + || wh_dentry->d_parent != au_h_dptr(parent, bindex)); + h_dir = wh_dentry->d_parent->d_inode; + IMustLock(h_dir); + err = 0; + } + + if (!err) { + drop_nlink(inode); +#if 0 /* todo: update plink? */ + if (unlikely(!inode->i_nlink + && au_plink_test(sb, inode) + /* && atomic_read(&inode->i_count) == 2) */)) { + au_debug_on(); + DbgInode(inode); + au_debug_off(); + } +#endif +#if 0 + /* + * although this is not a dir, + * set it here since we need to detect + * the dead inode in d_revalidate(). + */ + if (!inode->i_nlink) + inode->i_flags |= S_DEAD; +#endif + epilog(dir, dentry, bindex); + + /* update target timestamps */ + if (bindex == bstart) { + au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/ + inode->i_ctime = h_dentry->d_inode->i_ctime; + } else + /* todo: this timestamp may be reverted later */ + inode->i_ctime = h_dir->i_ctime; + goto out_unlock; /* success */ + } + + /* revert */ + if (wh_dentry) { + int rerr; + unsigned int rev_flags; + + rev_flags = 0; + if (unlikely(dlgt)) + au_fset_rev(rev_flags, DLGT); + rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt, + rev_flags); + if (rerr) + err = rerr; + } + + out_unlock: + au_unpin(&pin); + dput(wh_dentry); + dput(h_dentry); + out: + di_write_unlock(parent); + aufs_read_unlock(dentry, AuLock_DW); + AuTraceErr(err); + return err; +} + +int aufs_rmdir(struct inode *dir, struct dentry *dentry) +{ + int err, rmdir_later; + struct inode *inode; + struct dentry *parent, *wh_dentry, *h_dentry; + struct au_dtime dt; + aufs_bindex_t bwh, bindex, bstart; + struct au_whtmp_rmdir_args *args; + struct au_nhash *whlist; + struct super_block *sb; + unsigned int mnt_flags; + struct au_pin pin; + + LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); + IMustLock(dir); +#if 0 + err = -ENOENT; /* possible? */ + if (unlikely(IS_DEADDIR(dir))) { + AuDbg("here\n"); + goto out; + } +#endif + inode = dentry->d_inode; + err = -ENOENT; /* possible? */ + if (unlikely(!inode + //|| IS_DEADDIR(inode) || IS_DEADDIR(dir) + )) { + //AuDbg("here\n"); + goto out; + } + IMustLock(inode); + + whlist = au_nhash_new(GFP_NOFS); + err = PTR_ERR(whlist); + if (IS_ERR(whlist)) + goto out; + + err = -ENOMEM; + args = kmalloc(sizeof(*args), GFP_NOFS); + if (unlikely(!args)) + goto out_whlist; + + aufs_read_lock(dentry, AuLock_DW); + parent = dentry->d_parent; /* dir inode is locked */ + di_write_lock_parent(parent); + err = au_test_empty(dentry, whlist); + if (unlikely(err)) + goto out_args; + + bstart = au_dbstart(dentry); + bwh = au_dbwh(dentry); + bindex = -1; + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out_args; + + AuDebugOn(au_dbstart(dentry) != bstart); + h_dentry = au_h_dptr(dentry, bstart); + dget(h_dentry); + + rmdir_later = 0; + if (bindex == bstart) { + err = renwh_and_rmdir(dentry, bstart, whlist, dir); + if (err > 0) { + rmdir_later = err; + err = 0; + } + } else { + /* dir inode is locked */ + AuDebugOn(!wh_dentry + || wh_dentry->d_parent != au_h_dptr(parent, bindex)); + IMustLock(wh_dentry->d_parent->d_inode); + err = 0; + } + + sb = dentry->d_sb; + mnt_flags = au_mntflags(sb); + if (!err) { + if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY) + && rmdir_later)) + au_reset_hinotify(inode, /*flags*/0); + clear_nlink(inode); + //inode->i_flags |= S_DEAD; + au_set_dbdiropq(dentry, -1); + epilog(dir, dentry, bindex); + + if (rmdir_later) { + au_whtmp_kick_rmdir(dir, bstart, h_dentry, whlist, + args); + args = NULL; + } + + goto out_unlock; /* success */ + } + + /* revert */ + LKTRLabel(revert); + if (wh_dentry) { + int rerr; + unsigned int rev_flags; + + rev_flags = 0; + if (unlikely(au_test_dlgt(mnt_flags))) + au_fset_rev(rev_flags, DLGT); + rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt, + rev_flags); + if (rerr) + err = rerr; + } + + out_unlock: + au_unpin(&pin); + dput(wh_dentry); + dput(h_dentry); + out_args: + di_write_unlock(parent); + aufs_read_unlock(dentry, AuLock_DW); + kfree(args); + out_whlist: + au_nhash_del(whlist); + out: + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/wkq.c +++ linux-2.6.27/ubuntu/aufs/wkq.c @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * workqueue for asynchronous/super-io/delegated operations + * + * $Id: wkq.c,v 1.13 2008/09/15 03:16:36 sfjro Exp $ + */ + +#include +#include "aufs.h" + +struct au_wkq *au_wkq; + +struct au_cred { +#ifdef CONFIG_AUFS_DLGT + int umask; + uid_t fsuid; + gid_t fsgid; + kernel_cap_t cap_effective, cap_inheritable, cap_permitted; +#if 0 /* reserved for future use */ + unsigned keep_capabilities:1; + struct user_struct *user; + struct fs_struct *fs; + struct nsproxy *nsproxy; +#endif +#endif +}; + +struct au_wkinfo { + struct work_struct wk; + struct super_block *sb; + + unsigned int flags; + struct au_cred cred; + + au_wkq_func_t func; + void *args; + + atomic_t *busyp; + struct completion *comp; +}; + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_DLGT +static void cred_store(struct au_cred *cred) +{ + cred->umask = current->fs->umask; + cred->fsuid = current->fsuid; + cred->fsgid = current->fsgid; + cred->cap_effective = current->cap_effective; + cred->cap_inheritable = current->cap_inheritable; + cred->cap_permitted = current->cap_permitted; +} + +static void cred_revert(struct au_cred *cred) +{ + AuDebugOn(!au_test_wkq(current)); + current->fs->umask = cred->umask; + current->fsuid = cred->fsuid; + current->fsgid = cred->fsgid; + current->cap_effective = cred->cap_effective; + current->cap_inheritable = cred->cap_inheritable; + current->cap_permitted = cred->cap_permitted; +} + +static void cred_switch(struct au_cred *old, struct au_cred *new) +{ + cred_store(old); + cred_revert(new); +} + +static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo) +{ + if (unlikely(au_ftest_wkq(flags, DLGT))) + cred_store(&wkinfo->cred); +} + +static void dlgt_func(struct au_wkinfo *wkinfo) +{ + if (!au_ftest_wkq(wkinfo->flags, DLGT)) + wkinfo->func(wkinfo->args); + else { + struct au_cred cred; + cred_switch(&cred, &wkinfo->cred); + wkinfo->func(wkinfo->args); + cred_revert(&cred); + } +} +#else +static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo) +{ + /* empty */ +} + +static void dlgt_func(struct au_wkinfo *wkinfo) +{ + wkinfo->func(wkinfo->args); +} +#endif /* CONFIG_AUFS_DLGT */ + +/* ---------------------------------------------------------------------- */ + +static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo) +{ +#ifdef CONFIG_AUFS_STAT + unsigned int new, old; + + do { + new = atomic_read(wkinfo->busyp); + old = wkq->max_busy; + if (new <= old) + break; + } while (cmpxchg(&wkq->max_busy, old, new) == old); +#endif +} + +static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo) +{ + AuTraceEnter(); + + wkinfo->busyp = &wkq->busy; + update_busy(wkq, wkinfo); + if (au_ftest_wkq(wkinfo->flags, WAIT)) + return !queue_work(wkq->q, &wkinfo->wk); + else + return !schedule_work(&wkinfo->wk); +} + +static void do_wkq(struct au_wkinfo *wkinfo) +{ + unsigned int idle, n; + int i, idle_idx; + + AuTraceEnter(); + + while (1) { + if (au_ftest_wkq(wkinfo->flags, WAIT)) { + idle_idx = 0; + idle = UINT_MAX; + for (i = 0; i < aufs_nwkq; i++) { + n = atomic_inc_return(&au_wkq[i].busy); + if (n == 1 && !enqueue(au_wkq + i, wkinfo)) + return; /* success */ + + if (n < idle) { + idle_idx = i; + idle = n; + } + atomic_dec_return(&au_wkq[i].busy); + } + } else + idle_idx = aufs_nwkq; + + atomic_inc_return(&au_wkq[idle_idx].busy); + if (!enqueue(au_wkq + idle_idx, wkinfo)) + return; /* success */ + + /* impossible? */ + AuWarn1("failed to queue_work()\n"); + yield(); + } +} + +static void wkq_func(struct work_struct *wk) +{ + struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); + + LKTRTrace("wkinfo{0x%x, %p, %p, %p}\n", + wkinfo->flags, wkinfo->func, wkinfo->busyp, wkinfo->comp); + + dlgt_func(wkinfo); + atomic_dec_return(wkinfo->busyp); + if (au_ftest_wkq(wkinfo->flags, WAIT)) + complete(wkinfo->comp); + else { + kobject_put(&au_sbi(wkinfo->sb)->si_kobj); + module_put(THIS_MODULE); + kfree(wkinfo); + } +} + +#if defined(CONFIG_4KSTACKS) || defined(Test4KSTACKS) +#define AuWkqCompDeclare(name) struct completion *comp = NULL + +static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) +{ + *comp = kmalloc(sizeof(**comp), GFP_NOFS); + if (*comp) { + init_completion(*comp); + wkinfo->comp = *comp; + return 0; + } + return -ENOMEM; +} + +static void au_wkq_comp_free(struct completion *comp) +{ + kfree(comp); +} + +#else + +#define AuWkqCompDeclare(name) \ + DECLARE_COMPLETION_ONSTACK(_ ## name); \ + struct completion *comp = &_ ## name + +static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) +{ + wkinfo->comp = *comp; + return 0; +} + +static void au_wkq_comp_free(struct completion *comp) +{ + /* empty */ +} +#endif /* 4KSTACKS */ + +/* todo: break to three funcs */ +int au_wkq_run(au_wkq_func_t func, void *args, struct super_block *sb, + unsigned int flags) +{ + int err; + AuWkqCompDeclare(comp); + struct au_wkinfo _wkinfo = { + .flags = flags, + .func = func, + .args = args + }, *wkinfo = &_wkinfo; + const unsigned char do_wait = au_ftest_wkq(flags, WAIT); + + LKTRTrace("0x%x\n", flags); +#if 1 /* tmp debug */ + if (au_test_wkq(current)) + au_dbg_blocked(); +#endif + AuDebugOn(au_test_wkq(current)); + + if (do_wait) { + err = au_wkq_comp_alloc(wkinfo, &comp); + if (unlikely(err)) + goto out; + } else { + AuDebugOn(!sb); + /* + * wkq_func() must free this wkinfo. + * it highly depends upon the implementation of workqueue. + */ + err = -ENOMEM; + wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS); + if (unlikely(!wkinfo)) + goto out; + + err = 0; + wkinfo->sb = sb; + wkinfo->flags = flags; + wkinfo->func = func; + wkinfo->args = args; + wkinfo->comp = NULL; + kobject_get(&au_sbi(sb)->si_kobj); + __module_get(THIS_MODULE); + } + + INIT_WORK(&wkinfo->wk, wkq_func); + dlgt_cred_store(flags, wkinfo); + do_wkq(wkinfo); + if (do_wait) { + /* no timeout, no interrupt */ + wait_for_completion(wkinfo->comp); + au_wkq_comp_free(comp); + } + out: + AuTraceErr(err); + return err; +} + +int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, + int dlgt) +{ + int err; + unsigned int flags = !AuWkq_WAIT; + + AuTraceEnter(); + + if (unlikely(dlgt)) + au_fset_wkq(flags, DLGT); + atomic_inc_return(&au_sbi(sb)->si_nowait.nw_len); + err = au_wkq_run(func, args, sb, flags); + if (unlikely(err)) + atomic_dec_return(&au_sbi(sb)->si_nowait.nw_len); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +void au_wkq_fin(void) +{ + int i; + + AuTraceEnter(); + + for (i = 0; i < aufs_nwkq; i++) + if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) + destroy_workqueue(au_wkq[i].q); + kfree(au_wkq); +} + +int __init au_wkq_init(void) +{ + int err, i; + struct au_wkq *nowaitq; + + LKTRTrace("%d\n", aufs_nwkq); + + /* '+1' is for accounting of nowait queue */ + err = -ENOMEM; + au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS); + if (unlikely(!au_wkq)) + goto out; + + err = 0; + for (i = 0; i < aufs_nwkq; i++) { + au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME); + if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) { + atomic_set(&au_wkq[i].busy, 0); + au_wkq_max_busy_init(au_wkq + i); + continue; + } + + err = PTR_ERR(au_wkq[i].q); + au_wkq_fin(); + break; + } + + /* nowait accounting */ + nowaitq = au_wkq + aufs_nwkq; + atomic_set(&nowaitq->busy, 0); + au_wkq_max_busy_init(nowaitq); + nowaitq->q = NULL; + /* smp_mb(); */ /* atomic_set */ + + out: + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/br_nfs.c +++ linux-2.6.27/ubuntu/aufs/br_nfs.c @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * lookup functions for NFS branch in linux-2.6.19 and later + * + * $Id: br_nfs.c,v 1.7 2008/07/21 02:54:22 sfjro Exp $ + */ + +#include "aufs.h" + +static struct file *au_find_h_intent(struct au_hdentry *hd, struct file *file) +{ + struct file *h_file, *hf; + struct au_hdintent *hdi, *tmp, *do_free; + + LKTRTrace("%.*s\n", AuDLNPair(hd->hd_dentry)); + + h_file = NULL; + do_free = NULL; + spin_lock(&hd->hd_lock); + list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list, hdi_list) { + hf = hdi->hdi_file[AuIntent_BRANCH]; + if (hdi->hdi_file[AuIntent_AUFS] == file + && hf->f_dentry == hd->hd_dentry) { + h_file = hf; + do_free = hdi; + list_del(&hdi->hdi_list); + break; + } + } + spin_unlock(&hd->hd_lock); + kfree(do_free); + + return h_file; +} + +struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex, + struct file *file) +{ + struct file *h_file; + struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex; + + LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file); + DiMustAnyLock(dentry); + AuDebugOn(bindex < au_di(dentry)->di_bstart + || bindex > au_di(dentry)->di_bend); + + h_file = NULL; + if (!hd->hd_intent_list || !file) + return h_file; /* success */ + + /* AuDebugOn(au_test_wkq(current)); */ + h_file = au_find_h_intent(hd, file); + return h_file; +} + +static int au_set_h_intent(struct dentry *dentry, aufs_bindex_t bindex, + struct file *file, struct file *h_file) +{ + int err; + struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex; + struct au_hdintent *hdi; + struct file *hf; + + LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file); + /* d_revalidate() holds read_lock */ + /* DiMustWriteLock(dentry); */ + AuDebugOn(bindex < au_di(dentry)->di_bstart + || bindex > au_di(dentry)->di_bend + || !file + || !h_file + /* || au_test_wkq(current) */); + + err = -ENOMEM; + if (hd->hd_intent_list) { + while (1) { + hf = au_find_h_intent(hd, file); + if (!hf) + break; + fput(hf); + AuWarn("freed hfile %.*s b%d left\n", + AuDLNPair(dentry), bindex); + } + } else { + spin_lock(&hd->hd_lock); + if (!hd->hd_intent_list) { + hd->hd_intent_list + = kmalloc(sizeof(*hd->hd_intent_list), + GFP_ATOMIC); + if (unlikely(!hd->hd_intent_list)) { + spin_unlock(&hd->hd_lock); + goto out; + } + INIT_LIST_HEAD(hd->hd_intent_list); + } + spin_unlock(&hd->hd_lock); + } + + hdi = kmalloc(sizeof(*hdi), GFP_NOFS); + if (unlikely(!hdi)) + goto out; + + err = 0; + /* hdi->hdi_pid = current->pid; */ + hdi->hdi_file[AuIntent_AUFS] = file; + hdi->hdi_file[AuIntent_BRANCH] = h_file; + spin_lock(&hd->hd_lock); + list_add(&hdi->hdi_list, hd->hd_intent_list); + spin_unlock(&hd->hd_lock); + + out: + AuTraceErr(err); + return err; +} + +int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry, + aufs_bindex_t bindex, struct nameidata *nd) +{ + int err; + + AuTraceEnter(); + + err = 0; + if (!nd_file) + goto out; + + AuDebugOn(!nd); + err = au_set_h_intent(dentry, bindex, nd->intent.open.file, nd_file); + if (unlikely(err)) { + fput(nd_file); + au_set_h_dptr(dentry, bindex, NULL); + /* todo: update bstart and bend? */ + } + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +void au_hintent_put(struct au_hdentry *hd, int do_free) +{ + struct au_hdintent *hdi, *tmp; + struct file *hf; + + if (unlikely(hd->hd_intent_list)) { + /* no spin lock */ + list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list, + hdi_list) { + LKTRTrace("hdi %p\n", hdi); + hf = hdi->hdi_file[AuIntent_BRANCH]; + if (unlikely(hf)) + fput(hf); + /* list_del(&hdi->hdi_list); */ + kfree(hdi); + } + if (do_free) + kfree(hd->hd_intent_list); + } +} + +/* ---------------------------------------------------------------------- */ + +int au_fake_intent(/* struct au_ndsub *save, */struct nameidata *nd, + int perm) +{ + int err; + + LKTRTrace("perm %d\n", perm); + + err = 0; + nd->intent.open.file = NULL; + if (nd->flags & LOOKUP_OPEN) { + err = -ENFILE; + nd->intent.open.file = get_empty_filp(); + if (unlikely(!nd->intent.open.file)) + goto out; + + err = 0; + if (!au_br_writable(perm)) { + nd->intent.open.flags = FMODE_READ + | au_file_roflags(nd->intent.open.flags); + nd->flags &= ~LOOKUP_CREATE; + } + } + + out: + AuTraceErr(err); + return err; +} + +int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry, + aufs_bindex_t bindex, struct file *file) +{ + int err; + + LKTRTrace("nd %p, %.*s, b%d, f %d\n", + nd, AuDLNPair(dentry), bindex, !!file); + + err = 0; + if ((nd->flags & LOOKUP_OPEN) + && nd->intent.open.file + && !IS_ERR(nd->intent.open.file)) { + if (nd->intent.open.file->f_dentry) { + err = au_set_h_intent(dentry, bindex, file, + nd->intent.open.file); + if (!err) + nd->intent.open.file = NULL; + } + if (unlikely(nd->intent.open.file)) + put_filp(nd->intent.open.file); + } + + return err; +} + +#ifdef CONFIG_AUFS_DLGT +struct au_lookup_hash_args { + struct dentry **errp; + struct qstr *name; + struct dentry *base; + struct nameidata *nd; +}; + +static void au_call_lookup_hash(void *args) +{ + struct au_lookup_hash_args *a = args; + *a->errp = vfsub__lookup_hash(a->name, a->base, a->nd); +} + +static struct dentry * +au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent, + struct nameidata *nd, unsigned int flags) +{ + struct dentry *dentry; + int dirperm1; + + dirperm1 = au_ftest_ndx(flags, DIRPERM1); + if (!dirperm1 && !au_ftest_ndx(flags, DLGT)) + dentry = vfsub__lookup_hash(this, parent, nd); + else { + int wkq_err; + struct au_lookup_hash_args args = { + .errp = &dentry, + .name = this, + .base = parent, + .nd = nd + }; + wkq_err = au_wkq_wait(au_call_lookup_hash, &args, + /*dlgt*/!dirperm1); + if (unlikely(wkq_err)) + dentry = ERR_PTR(wkq_err); + } + + AuTraceErrPtr(dentry); + return dentry; +} +#else +static struct dentry * +au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent, + struct nameidata *nd, unsigned int flags) +{ + return vfsub__lookup_hash(this, parent, nd); +} +#endif /* CONFIG_AUFS_DLGT */ + +struct dentry *au_lkup_hash(const char *name, struct dentry *parent, + int len, struct au_ndx *ndx) +{ + struct dentry *dentry; + char *p; + unsigned long hash; + struct qstr this; + unsigned int c; + struct nameidata tmp_nd, *ndo; + int err; + + LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name); + + /* todo: export and call __lookup_one_len() in fs/namei.c? */ + dentry = ERR_PTR(-EACCES); + this.name = name; + this.len = len; + if (unlikely(!len)) + goto out; + + p = (void *)name; + hash = init_name_hash(); + while (len--) { + c = *p++; + if (unlikely(c == '/' || c == '\0')) + goto out; + hash = partial_name_hash(c, hash); + } + this.hash = end_name_hash(hash); + + ndo = ndx->nd; + if (ndo) { + tmp_nd = *ndo; + err = au_fake_intent(&tmp_nd, ndx->br->br_perm); + dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_intent; + } else + memset(&tmp_nd, 0, sizeof(tmp_nd)); + + tmp_nd.path.dentry = parent; + tmp_nd.path.mnt = ndx->nfsmnt; + path_get(&tmp_nd.path); + dentry = au_lkup_hash_dlgt(&this, parent, &tmp_nd, ndx->flags); + if (!IS_ERR(dentry)) { + /* why negative dentry for a new dir was unhashed? */ + if (unlikely(d_unhashed(dentry))) + d_rehash(dentry); + if (tmp_nd.intent.open.file + && tmp_nd.intent.open.file->f_dentry) { + ndx->nd_file = tmp_nd.intent.open.file; + tmp_nd.intent.open.file = NULL; + /* au_br_get(ndx->br); */ + } + } + path_put(&tmp_nd.path); + + out_intent: + if (tmp_nd.intent.open.file) + put_filp(tmp_nd.intent.open.file); + out: + AuTraceErrPtr(dentry); + return dentry; +} --- linux-2.6.27.orig/ubuntu/aufs/dlgt.c +++ linux-2.6.27/ubuntu/aufs/dlgt.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * lookup functions in 'delegate' mode + * + * $Id: dlgt.c,v 1.5 2008/08/11 02:50:34 sfjro Exp $ + */ + +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +struct au_lookup_one_len_args { + struct dentry **errp; + const char *name; + struct dentry *parent; + int len; +}; + +static void au_call_lookup_one_len(void *args) +{ + struct au_lookup_one_len_args *a = args; + *a->errp = vfsub_lookup_one_len(a->name, a->parent, a->len); +} + +struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent, + int len, unsigned int flags) +{ + struct dentry *dentry; + int dirperm1; + + LKTRTrace("%.*s/%.*s, 0x%x\n", AuDLNPair(parent), len, name, flags); + + dirperm1 = au_ftest_ndx(flags, DIRPERM1); + if (!dirperm1 && !au_ftest_ndx(flags, DLGT)) + dentry = vfsub_lookup_one_len(name, parent, len); + else { + int wkq_err; + struct au_lookup_one_len_args args = { + .errp = &dentry, + .name = name, + .parent = parent, + .len = len + }; + wkq_err = au_wkq_wait(au_call_lookup_one_len, &args, + /*dlgt*/!dirperm1); + if (unlikely(wkq_err)) + dentry = ERR_PTR(wkq_err); + } + + AuTraceErrPtr(dentry); + return dentry; +} + +/* ---------------------------------------------------------------------- */ + +struct security_inode_permission_args { + int *errp; + struct inode *h_inode; + int mask; + struct nameidata *fake_nd; +}; + +static void call_security_inode_permission(void *args) +{ + struct security_inode_permission_args *a = args; + LKTRTrace("fsuid %d\n", current->fsuid); + *a->errp = vfsub_security_inode_permission(a->h_inode, a->mask, + a->fake_nd); +} + +int au_security_inode_permission(struct inode *h_inode, int mask, + struct nameidata *fake_nd, int dlgt) +{ + int err; + + AuTraceEnter(); + + if (!dlgt) + err = vfsub_security_inode_permission(h_inode, mask, fake_nd); + else { + int wkq_err; + struct security_inode_permission_args args = { + .errp = &err, + .h_inode = h_inode, + .mask = mask, + .fake_nd = fake_nd + }; + wkq_err = au_wkq_wait(call_security_inode_permission, &args, + /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/BOM +++ linux-2.6.27/ubuntu/aufs/BOM @@ -0,0 +1,3 @@ +Downloaded from: pserver:anonymous@aufs.cvs.sourceforge.net:/cvsroot/aufs +Current Version: Mon, 22 Sep 2008 +Comments: Unmodified upstream checkout --- linux-2.6.27.orig/ubuntu/aufs/super.h +++ linux-2.6.27/ubuntu/aufs/super.h @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * super_block operations + * + * $Id: super.h,v 1.14 2008/09/15 03:14:52 sfjro Exp $ + */ + +#ifndef __AUFS_SUPER_H__ +#define __AUFS_SUPER_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include "misc.h" +#include "wkq.h" + +typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *); +typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t, + loff_t *); + +struct au_wbr_copyup_operations { + int (*copyup)(struct dentry *dentry); +}; + +struct au_wbr_create_operations { + int (*create)(struct dentry *dentry, int isdir); + int (*init)(struct super_block *sb); + int (*fin)(struct super_block *sb); +}; + +struct au_wbr_mfs { + struct mutex mfs_lock; /* protect this structure */ + unsigned long mfs_jiffy; + unsigned long mfs_expire; + aufs_bindex_t mfs_bindex; + + unsigned long long mfsrr_bytes; + unsigned long long mfsrr_watermark; +}; + +/* sbinfo status flags */ +/* + * set true when refresh_dirs() failed at remount time. + * then try refreshing dirs at access time again. + * if it is false, refreshing dirs at access time is unnecesary + */ +#define AuSi_FAILED_REFRESH_DIRS 1 +#define au_ftest_si(sbinfo, name) ((sbinfo)->au_si_status & AuSi_##name) +#define au_fset_si(sbinfo, name) \ + { (sbinfo)->au_si_status |= AuSi_##name; } +#define au_fclr_si(sbinfo, name) \ + { (sbinfo)->au_si_status &= ~AuSi_##name; } + +struct au_branch; +struct au_sbinfo { + /* nowait tasks in the system-wide workqueue */ + struct au_nowait_tasks si_nowait; + + struct au_rwsem si_rwsem; + + /* branch management */ + au_gen_t si_generation; + + /* see above flags */ + unsigned char au_si_status; + + aufs_bindex_t si_bend; + aufs_bindex_t si_last_br_id; + struct au_branch **si_branch; + + /* policy to select a writable branch */ + unsigned char si_wbr_copyup; + unsigned char si_wbr_create; + struct au_wbr_copyup_operations *si_wbr_copyup_ops; + struct au_wbr_create_operations *si_wbr_create_ops; + + /* round robin */ + atomic_t si_wbr_rr_next; + + /* most free space */ + struct au_wbr_mfs si_wbr_mfs; + + /* mount flags */ + /* include/asm-ia64/siginfo.h defines a macro named si_flags */ + unsigned int si_mntflags; + + /* external inode number (bitmap and translation table) */ + au_readf_t si_xread; + au_writef_t si_xwrite; + struct file *si_xib; + struct mutex si_xib_mtx; /* protect xib members */ + unsigned long *si_xib_buf; + unsigned long si_xib_last_pindex; + int si_xib_next_bit; + /* reserved for future use */ + /* unsigned long long si_xib_limit; */ /* Max xib file size */ + +#ifdef CONFIG_AUFS_HINOTIFY + struct au_branch *si_xino_def_br; +#endif + +#ifdef CONFIG_AUFS_EXPORT + /* i_generation */ + struct file *si_xigen; + /* todo: atomic_t? */ + spinlock_t si_xigen_lock; + __u32 si_xigen_next; +#endif + + /* readdir cache time, max, in HZ */ + unsigned long si_rdcache; + + /* + * If the number of whiteouts are larger than si_dirwh, leave all of + * them after au_whtmp_ren to reduce the cost of rmdir(2). + * future fsck.aufs or kernel thread will remove them later. + * Otherwise, remove all whiteouts and the dir in rmdir(2). + */ + unsigned int si_dirwh; + + /* + * rename(2) a directory with all children. + */ + /* reserved for future use */ + /* int si_rendir; */ + + /* pseudo_link list */ /* todo: dirty? */ + spinlock_t si_plink_lock; + struct list_head si_plink; + +#if defined(CONFIG_AUFS_EXPORT) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + /* dirty, for export, async ops, and sysfs */ + spinlock_t si_mntcache_lock; + struct vfsmount *si_mntcache; /* no get/put */ +#endif + + /* + * sysfs and lifetime management. + * this is not a small structure and it may be a waste of memory in case + * of sysfs is disabled, particulary when many aufs-es are mounted. + */ + struct kobject si_kobj; + +#ifdef CONFIG_AUFS_ROBR + /* locked vma list for mmap() */ /* todo: dirty? */ + spinlock_t si_lvma_lock; + struct list_head si_lvma; +#endif + +#ifdef CONFIG_AUFS_EXPORT /* reserved for future use */ + struct path si_xinodir; +#endif + + /* dirty, necessary for unmounting, sysfs and sysrq */ + struct super_block *si_sb; +}; + +/* ---------------------------------------------------------------------- */ + +/* policy to select one among writable branches */ +#define AuWbrCopyup(sbinfo, args...) \ + (sbinfo)->si_wbr_copyup_ops->copyup(args) +#define AuWbrCreate(sbinfo, args...) \ + (sbinfo)->si_wbr_create_ops->create(args) + +/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ +#define AuLock_DW 1 /* write-lock dentry */ +#define AuLock_IR (1 << 1) /* read-lock inode */ +#define AuLock_IW (1 << 2) /* write-lock inode */ +#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ +#define AuLock_DIR (1 << 4) /* target is a dir */ +#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) +#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; } +#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; } + +/* ---------------------------------------------------------------------- */ + +/* super.c */ +extern struct file_system_type aufs_fs_type; +struct inode *au_iget_locked(struct super_block *sb, ino_t ino); + +/* sbinfo.c */ +void au_si_free(struct kobject *kobj); +int au_si_alloc(struct super_block *sb); +struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex); +au_gen_t au_sigen_inc(struct super_block *sb); +int au_find_bindex(struct super_block *sb, struct au_branch *br); + +void aufs_read_lock(struct dentry *dentry, int flags); +void aufs_read_unlock(struct dentry *dentry, int flags); +void aufs_write_lock(struct dentry *dentry); +void aufs_write_unlock(struct dentry *dentry); +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir); +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); + +aufs_bindex_t au_new_br_id(struct super_block *sb); + +/* wbr_policy.c */ +extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; +extern struct au_wbr_create_operations au_wbr_create_ops[]; +int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); + +/* ---------------------------------------------------------------------- */ + +#if defined(CONFIG_AUFS_EXPORT) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +static inline void au_mnt_init(struct au_sbinfo *sbinfo, struct vfsmount *mnt) +{ + spin_lock_init(&sbinfo->si_mntcache_lock); + sbinfo->si_mntcache = mnt; +} + +static inline void au_mnt_reset(struct au_sbinfo *sbinfo) +{ + spin_lock(&sbinfo->si_mntcache_lock); + sbinfo->si_mntcache = NULL; + spin_unlock(&sbinfo->si_mntcache_lock); +} +#else +static inline void au_mnt_init(struct au_sbinfo *sbinfo, struct vfsmount *mnt) +{ + /* emptr */ +} + +static inline void au_mnt_reset(struct au_sbinfo *sbinfo) +{ + /* emptr */ +} +#endif /* EXPORT && < 2.6.26 */ + +/* ---------------------------------------------------------------------- */ + +static inline struct au_sbinfo *au_sbi(struct super_block *sb) +{ + return sb->s_fs_info; +} + +static inline const char *au_sbtype(struct super_block *sb) +{ + return sb->s_type->name; +} + +static inline int au_test_aufs(struct super_block *sb) +{ + return (sb->s_magic == AUFS_SUPER_MAGIC); +} + +static inline int au_test_nfs(struct super_block *sb) +{ +#ifdef CONFIG_AUFS_BR_NFS + return (sb->s_magic == NFS_SUPER_MAGIC); +#else + return 0; +#endif +} + +static inline int au_test_fuse(struct super_block *sb) +{ +#ifdef CONFIG_AUFS_WORKAROUND_FUSE + return (sb->s_magic == FUSE_SUPER_MAGIC); +#else + return 0; +#endif +} + +static inline int au_test_xfs(struct super_block *sb) +{ +#ifdef CONFIG_AUFS_BR_XFS + return (sb->s_magic == XFS_SB_MAGIC); +#else + return 0; +#endif +} + +static inline int au_test_tmpfs(struct super_block *sb) +{ +#ifdef CONFIG_TMPFS + return (sb->s_magic == TMPFS_MAGIC); +#else + return 0; +#endif +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_HINOTIFY +static inline void au_xino_def_br_set(struct au_branch *br, + struct au_sbinfo *sbinfo) +{ + sbinfo->si_xino_def_br = br; +} + +static inline struct au_branch *au_xino_def_br(struct au_sbinfo *sbinfo) +{ + return sbinfo->si_xino_def_br; +} +#else +static inline void au_xino_def_br_set(struct au_branch *br, + struct au_sbinfo *sbinfo) +{ + /* empty */ +} + +static inline struct au_branch *au_xino_def_br(struct au_sbinfo *sbinfo) +{ + return NULL; +} +#endif + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_EXPORT +void au_export_init(struct super_block *sb); + +static inline int au_test_nfsd(struct task_struct *tsk) +{ + return (!tsk->mm && !strcmp(tsk->comm, "nfsd")); +} + +static inline void au_nfsd_lockdep_off(void) +{ + if (au_test_nfsd(current)) + lockdep_off(); +} + +static inline void au_nfsd_lockdep_on(void) +{ + if (au_test_nfsd(current)) + lockdep_on(); +} + +static inline void au_export_put(struct au_sbinfo *sbinfo) +{ + path_put(&sbinfo->si_xinodir); +} + +int au_xigen_inc(struct inode *inode); +int au_xigen_new(struct inode *inode); +int au_xigen_set(struct super_block *sb, struct file *base); +void au_xigen_clr(struct super_block *sb); + +#else +static inline void au_export_init(struct super_block *sb) +{ + /* nothing */ +} + +static inline int au_test_nfsd(struct task_struct *tsk) +{ + return 0; +} + +#define au_nfsd_lockdep_off() do {} while (0) +#define au_nfsd_lockdep_on() do {} while (0) + +static inline void au_export_put(struct au_sbinfo *sbinfo) +{ + /* nothing */ +} + +static inline int au_xigen_inc(struct inode *inode) +{ + return 0; +} + +static inline int au_xigen_new(struct inode *inode) +{ + return 0; +} + +static inline int au_xigen_set(struct super_block *sb, struct file *base) +{ + return 0; +} + +static inline void au_xigen_clr(struct super_block *sb) +{ + /* empty */ +} +#endif /* CONFIG_AUFS_EXPORT */ + +#ifdef CONFIG_AUFS_ROBR +static inline int au_test_nested(struct super_block *h_sb) +{ + return 0; +} + +static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo) +{ + spin_lock_init(&sbinfo->si_lvma_lock); + INIT_LIST_HEAD(&sbinfo->si_lvma); +} +#else +static inline int au_test_nested(struct super_block *h_sb) +{ + int err = 0; + if (unlikely(au_test_aufs(h_sb))) { + err = -EINVAL; + AuTraceErr(err); + } + return err; +} + +static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo) +{ + /* empty */ +} +#endif /* CONFIG_AUFS_ROBR */ + +/* ---------------------------------------------------------------------- */ + +/* lock superblock. mainly for entry point functions */ +/* + * si_noflush_read_lock, si_noflush_write_lock, + * si_read_unlock, si_write_unlock, si_downgrade_lock + */ +AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb, + au_sbi(sb)->si_rwsem); +AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, au_sbi(sb)->si_rwsem); + +static inline void si_read_lock(struct super_block *sb, int flags) +{ + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&au_sbi(sb)->si_nowait); + si_noflush_read_lock(sb); +} + +static inline void si_write_lock(struct super_block *sb) +{ + au_nwt_flush(&au_sbi(sb)->si_nowait); + si_noflush_write_lock(sb); +} + +static inline int si_read_trylock(struct super_block *sb, int flags) +{ + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&au_sbi(sb)->si_nowait); + return si_noflush_read_trylock(sb); +} + +static inline int si_write_trylock(struct super_block *sb, int flags) +{ + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&au_sbi(sb)->si_nowait); + return si_noflush_write_trylock(sb); +} + +/* to debug easier, do not make them inlined functions */ +#define SiMustReadLock(sb) AuRwMustReadLock(&au_sbi(sb)->si_rwsem) +#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) +#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) + +/* ---------------------------------------------------------------------- */ + +static inline aufs_bindex_t au_sbend(struct super_block *sb) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_bend; +} + +static inline unsigned int au_mntflags(struct super_block *sb) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_mntflags; +} + +static inline au_gen_t au_sigen(struct super_block *sb) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_generation; +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_SUPER_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/dentry.h +++ linux-2.6.27/ubuntu/aufs/dentry.h @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * lookup and dentry operations + * + * $Id: dentry.h,v 1.7 2008/09/01 02:54:54 sfjro Exp $ + */ + +#ifndef __AUFS_DENTRY_H__ +#define __AUFS_DENTRY_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include "misc.h" +#include "super.h" +#include "vfsub.h" + +/* nameidata open_intent */ +enum { + AuIntent_AUFS, + AuIntent_BRANCH, + AuIntent_Last +}; + +struct au_hdintent { + struct list_head hdi_list; + struct file *hdi_file[AuIntent_Last]; +}; + +struct au_hdentry { + struct dentry *hd_dentry; + +#ifdef CONFIG_AUFS_BR_NFS + spinlock_t hd_lock; /* intest_list */ + struct list_head *hd_intent_list; +#endif +}; + +struct au_dinfo { + atomic_t di_generation; + + struct au_rwsem di_rwsem; + aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq; + struct au_hdentry *di_hdentry; +}; + +/* nameidata extension flags */ +#define AuNdx_DLGT 1 +#define AuNdx_DIRPERM1 (1 << 1) +#define au_ftest_ndx(flags, name) ((flags) & AuNdx_##name) +#define au_fset_ndx(flags, name) { (flags) |= AuNdx_##name; } +#define au_fclr_ndx(flags, name) { (flags) &= ~AuNdx_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef AuNdx_DLGT +#define AuNdx_DLGT 0 +#undef AuNdx_DIRPERM1 +#define AuNdx_DIRPERM1 0 +#endif + +struct au_ndx { + struct vfsmount *nfsmnt; + unsigned int flags; + struct nameidata *nd; + struct au_branch *br; + struct file *nd_file; +}; + +/* ---------------------------------------------------------------------- */ + +static inline void au_do_h_dentry_init(struct au_hdentry *hdentry) +{ + hdentry->hd_dentry = NULL; +} + +#ifdef CONFIG_AUFS_BR_NFS +static inline void au_h_dentry_init(struct au_hdentry *hdentry) +{ + au_do_h_dentry_init(hdentry); + spin_lock_init(&hdentry->hd_lock); +} + +static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n) +{ + while (n--) + spin_lock_init(&hdentry[n].hd_lock); +} + +/* br_nfs.c */ +struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex, + struct file *file); +int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry, + aufs_bindex_t bindex, struct nameidata *nd); +void au_hintent_put(struct au_hdentry *hd, int do_free); +int au_fake_intent(struct nameidata *nd, int perm); +int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry, + aufs_bindex_t bindex, struct file *file); +struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len, + struct au_ndx *ndx); +#else + +static inline void au_h_dentry_init(struct au_hdentry *hdentry) +{ + au_do_h_dentry_init(hdentry); +} + +static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n) +{ + /* nothing */ +} + +static inline +struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex, + struct file *file) +{ + /* return ERR_PTR(-ENOSYS); */ + return NULL; +} + +static inline +int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry, + aufs_bindex_t bindex, struct nameidata *nd) +{ + return 0; +} + +static inline void au_hintent_put(struct au_hdentry *hd, int do_free) +{ + /* empty */ +} + +static inline int au_fake_intent(struct nameidata *nd, int perm) +{ + return 0; +} + +static inline +int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry, + aufs_bindex_t bindex, struct file *file) +{ + return 0; +} + +#ifdef CONFIG_AUFS_DLGT +static inline +struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len, + struct au_ndx *ndx) +{ + /* return ERR_PTR(-ENOSYS); */ + return vfsub_lookup_one_len(name, parent, len); +} +#endif +#endif /* CONFIG_AUFS_BR_NFS */ + +#ifdef CONFIG_AUFS_DLGT +/* dlgt.c */ +struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent, + int len, unsigned int flags); +#elif defined(CONFIG_AUFS_BR_NFS) +/* regardelss kernel version */ +static inline +struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent, + int len, unsigned int flags) +{ + return vfsub_lookup_one_len(name, parent, len); +} +#endif + +/* dentry.c */ +extern struct dentry_operations aufs_dop; +#if defined(CONFIG_AUFS_BR_NFS) || defined(CONFIG_AUFS_DLGT) +struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len, + struct au_ndx *ndx); +#else +static inline +struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len, + struct au_ndx *ndx) +{ + /* todo? ndx->nd_file = NULL; */ + return vfsub_lookup_one_len(name, parent, len); +} +#endif +struct dentry *au_sio_lkup_one(const char *name, struct dentry *parent, int len, + struct au_ndx *ndx); +int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type, + struct nameidata *nd); +int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex); +int au_refresh_hdentry(struct dentry *dentry, mode_t type); +int au_reval_dpath(struct dentry *dentry, au_gen_t sgen); + +/* dinfo.c */ +int au_alloc_dinfo(struct dentry *dentry); +struct au_dinfo *au_di(struct dentry *dentry); + +void di_read_lock(struct dentry *d, int flags, unsigned int lsc); +void di_read_unlock(struct dentry *d, int flags); +void di_downgrade_lock(struct dentry *d, int flags); +void di_write_lock(struct dentry *d, unsigned int lsc); +void di_write_unlock(struct dentry *d); +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir); +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir); +void di_write_unlock2(struct dentry *d1, struct dentry *d2); + +struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); + +aufs_bindex_t au_dbtail(struct dentry *dentry); +aufs_bindex_t au_dbtaildir(struct dentry *dentry); +#if 0 /* reserved for future use */ +aufs_bindex_t au_dbtail_generic(struct dentry *dentry); +#endif + +void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex); +void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_dentry); + +void au_update_dbrange(struct dentry *dentry, int do_put_zero); +void au_update_dbstart(struct dentry *dentry); +void au_update_dbend(struct dentry *dentry); +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry); + +/* ---------------------------------------------------------------------- */ + +/* todo: memory barrier? */ +static inline au_gen_t au_digen(struct dentry *d) +{ + return atomic_read(&au_di(d)->di_generation); +} + +#ifdef CONFIG_AUFS_HINOTIFY +static inline au_gen_t au_digen_dec(struct dentry *d) +{ + return atomic_dec_return(&au_di(d)->di_generation); +} + +static inline void au_hin_di_reinit(struct dentry *d) +{ + d->d_fsdata = NULL; +} +#else +static inline void au_hin_di_reinit(struct dentry *d) +{ + /* empty */ +} +#endif /* CONFIG_AUFS_HINOTIFY */ + +/* ---------------------------------------------------------------------- */ + +/* lock subclass for dinfo */ +enum { + AuLsc_DI_CHILD, /* child first */ + AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */ + AuLsc_DI_CHILD3, /* copyup dirs */ + AuLsc_DI_PARENT, + AuLsc_DI_PARENT2, + AuLsc_DI_PARENT3, + AuLsc_DI_PARENT4 +}; + +/* + * di_read_lock_child, di_write_lock_child, + * di_read_lock_child2, di_write_lock_child2, + * di_read_lock_child3, di_write_lock_child3, + * di_read_lock_parent, di_write_lock_parent, + * di_read_lock_parent2, di_write_lock_parent2, + * di_read_lock_parent3, di_write_lock_parent3, + * di_read_lock_parent4, di_write_lock_parent4, + */ +#define AuReadLockFunc(name, lsc) \ +static inline void di_read_lock_##name(struct dentry *d, int flags) \ +{ di_read_lock(d, flags, AuLsc_DI_##lsc); } + +#define AuWriteLockFunc(name, lsc) \ +static inline void di_write_lock_##name(struct dentry *d) \ +{ di_write_lock(d, AuLsc_DI_##lsc); } + +#define AuRWLockFuncs(name, lsc) \ + AuReadLockFunc(name, lsc) \ + AuWriteLockFunc(name, lsc) + +AuRWLockFuncs(child, CHILD); +AuRWLockFuncs(child2, CHILD2); +AuRWLockFuncs(child3, CHILD3); +AuRWLockFuncs(parent, PARENT); +AuRWLockFuncs(parent2, PARENT2); +AuRWLockFuncs(parent3, PARENT3); +AuRWLockFuncs(parent4, PARENT4); + +#undef AuReadLockFunc +#undef AuWriteLockFunc +#undef AuRWLockFuncs + +/* to debug easier, do not make them inlined functions */ +#define DiMustReadLock(d) do { \ + SiMustAnyLock((d)->d_sb); \ + AuRwMustReadLock(&au_di(d)->di_rwsem); \ +} while (0) + +#define DiMustWriteLock(d) do { \ + SiMustAnyLock((d)->d_sb); \ + AuRwMustWriteLock(&au_di(d)->di_rwsem); \ +} while (0) + +#define DiMustAnyLock(d) do { \ + SiMustAnyLock((d)->d_sb); \ + AuRwMustAnyLock(&au_di(d)->di_rwsem); \ +} while (0) + +#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem) + +/* ---------------------------------------------------------------------- */ + +static inline aufs_bindex_t au_dbstart(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + return au_di(dentry)->di_bstart; +} + +static inline aufs_bindex_t au_dbend(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + return au_di(dentry)->di_bend; +} + +static inline aufs_bindex_t au_dbwh(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + return au_di(dentry)->di_bwh; +} + +static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + AuDebugOn(dentry->d_inode + && dentry->d_inode->i_mode + && !S_ISDIR(dentry->d_inode->i_mode)); + return au_di(dentry)->di_bdiropq; +} + +/* todo: hard/soft set? */ +static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + AuDebugOn(au_sbend(dentry->d_sb) < bindex); + /* */ + au_di(dentry)->di_bstart = bindex; +} + +static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + AuDebugOn(au_sbend(dentry->d_sb) < bindex + || bindex < au_dbstart(dentry)); + au_di(dentry)->di_bend = bindex; +} + +static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + AuDebugOn(au_sbend(dentry->d_sb) < bindex); + /* dbwh can be outside of bstart - bend range */ + au_di(dentry)->di_bwh = bindex; +} + +static inline void au_hdput(struct au_hdentry *hd, int do_free) +{ + au_hintent_put(hd, do_free); + dput(hd->hd_dentry); +} + +static inline void au_update_digen(struct dentry *dentry) +{ + AuDebugOn(!dentry->d_sb); + atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb)); + /* smp_mb(); */ /* atomic_set */ +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DENTRY_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/misc.h +++ linux-2.6.27/ubuntu/aufs/misc.h @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * $Id: misc.h,v 1.7 2008/09/22 03:52:19 sfjro Exp $ + */ + +#ifndef __AUFS_MISC_H__ +#define __AUFS_MISC_H__ + +#ifdef __KERNEL__ + +#include +#include +#include + +/* ---------------------------------------------------------------------- */ + +typedef unsigned int au_gen_t; +/* see linux/include/linux/jiffies.h */ +#define AuGenYounger(a, b) ((int)(b) - (int)(a) < 0) +#define AuGenOlder(a, b) AufsGenYounger(b, a) + +/* ---------------------------------------------------------------------- */ + +struct au_rwsem { + struct rw_semaphore rwsem; +#ifdef CONFIG_AUFS_DEBUG + atomic_t rcnt; +#endif +}; + +#ifdef CONFIG_AUFS_DEBUG +#define AuDbgRcntInit(rw) do { \ + atomic_set(&(rw)->rcnt, 0); \ + smp_mb(); /* atomic set */ \ +} while (0) + +#define AuDbgRcntInc(rw) atomic_inc_return(&(rw)->rcnt) +#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0) +#else +#define AuDbgRcntInit(rw) do {} while (0) +#define AuDbgRcntInc(rw) do {} while (0) +#define AuDbgRcntDec(rw) do {} while (0) +#endif /* CONFIG_AUFS_DEBUG */ + +static inline void au_rw_init_nolock(struct au_rwsem *rw) +{ + AuDbgRcntInit(rw); + init_rwsem(&rw->rwsem); +} + +static inline void au_rw_init_wlock(struct au_rwsem *rw) +{ + au_rw_init_nolock(rw); + down_write(&rw->rwsem); +} + +static inline void au_rw_init_wlock_nested(struct au_rwsem *rw, + unsigned int lsc) +{ + au_rw_init_nolock(rw); + down_write_nested(&rw->rwsem, lsc); +} + +static inline void au_rw_read_lock(struct au_rwsem *rw) +{ + down_read(&rw->rwsem); + AuDbgRcntInc(rw); +} + +static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc) +{ + down_read_nested(&rw->rwsem, lsc); + AuDbgRcntInc(rw); +} + +static inline void au_rw_read_unlock(struct au_rwsem *rw) +{ + AuDbgRcntDec(rw); + up_read(&rw->rwsem); + //au_dbg_sleep_jiffy(1 * HZ / HZ); +} + +static inline void au_rw_dgrade_lock(struct au_rwsem *rw) +{ + AuDbgRcntInc(rw); + downgrade_write(&rw->rwsem); + //au_dbg_sleep_jiffy(1 * HZ / HZ); +} + +static inline void au_rw_write_lock(struct au_rwsem *rw) +{ + down_write(&rw->rwsem); +} + +static inline void au_rw_write_lock_nested(struct au_rwsem *rw, + unsigned int lsc) +{ + down_write_nested(&rw->rwsem, lsc); +} + +static inline void au_rw_write_unlock(struct au_rwsem *rw) +{ + up_write(&rw->rwsem); + //au_dbg_sleep_jiffy(1 * HZ / HZ); +} + +/* why is not _nested version defined */ +static inline int au_rw_read_trylock(struct au_rwsem *rw) +{ + int ret = down_read_trylock(&rw->rwsem); + if (ret) + AuDbgRcntInc(rw); + return ret; +} + +static inline int au_rw_write_trylock(struct au_rwsem *rw) +{ + return down_write_trylock(&rw->rwsem); +} + +#undef AuDbgRcntInit +#undef AuDbgRcntInc +#undef AuDbgRcntDec + +/* to debug easier, do not make them inlined functions */ +#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list)) +#define AuRwMustAnyLock(rw) AuDebugOn(down_write_trylock(&(rw)->rwsem)) +#ifdef CONFIG_AUFS_DEBUG +#define AuRwMustReadLock(rw) do { \ + AuRwMustAnyLock(rw); \ + AuDebugOn(!atomic_read(&(rw)->rcnt)); \ +} while (0) + +#define AuRwMustWriteLock(rw) do { \ + AuRwMustAnyLock(rw); \ + AuDebugOn(atomic_read(&(rw)->rcnt)); \ +} while (0) +#else +#define AuRwMustReadLock(rw) AuRwMustAnyLock(rw) +#define AuRwMustWriteLock(rw) AuRwMustAnyLock(rw) +#endif /* CONFIG_AUFS_DEBUG */ + +#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \ +static inline void prefix##_read_lock(param) \ +{ au_rw_read_lock(&(rwsem)); } \ +static inline void prefix##_write_lock(param) \ +{ au_rw_write_lock(&(rwsem)); } \ +static inline int prefix##_read_trylock(param) \ +{ return au_rw_read_trylock(&(rwsem)); } \ +static inline int prefix##_write_trylock(param) \ +{ return au_rw_write_trylock(&(rwsem)); } +/* static inline void prefix##_read_trylock_nested(param, lsc) +{au_rw_read_trylock_nested(&(rwsem, lsc));} +static inline void prefix##_write_trylock_nestd(param, lsc) +{au_rw_write_trylock_nested(&(rwsem), nested);} */ + +#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \ +static inline void prefix##_read_unlock(param) \ +{ au_rw_read_unlock(&(rwsem)); } \ +static inline void prefix##_write_unlock(param) \ +{ au_rw_write_unlock(&(rwsem)); } \ +static inline void prefix##_downgrade_lock(param) \ +{ au_rw_dgrade_lock(&(rwsem)); } + +#define AuSimpleRwsemFuncs(prefix, param, rwsem) \ + AuSimpleLockRwsemFuncs(prefix, param, rwsem) \ + AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) + +/* ---------------------------------------------------------------------- */ + +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp); + +struct au_nd_store { + unsigned int flags; + struct path path; + struct open_intent intent; +}; +struct au_sbinfo; +void au_nd_store(struct au_nd_store *store, struct nameidata *nd, + struct au_sbinfo *sbinfo); +void au_nd_revert(struct au_nd_store *store, struct nameidata *nd, + struct au_sbinfo *sbinfo); + +struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst, + struct nameidata *src); + +struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd, + struct super_block *sb, aufs_bindex_t bindex); +void au_fake_dm_release(struct nameidata *fake_nd); +struct vfsub_args; +int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode, + struct vfsub_args *vargs, struct nameidata *nd, + struct vfsmount *nfsmnt); + +struct au_hinode; +int au_copy_file(struct file *dst, struct file *src, loff_t len, + struct au_hinode *hdir, struct super_block *sb, + struct vfsub_args *vargs); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_MISC_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/br_xfs.c +++ linux-2.6.27/ubuntu/aufs/br_xfs.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * special handling inode attributes on XFS branch in linux-2.6.24 and later + * + * $Id: br_xfs.c,v 1.3 2008/07/07 01:12:38 sfjro Exp $ + */ + +#include "aufs.h" + +/* h_mnt can be NULL, is it safe? */ +dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt, + struct dentry *h_dentry) +{ + dev_t rdev; + int err; + struct kstat st; + + LKTRTrace("hi%lu\n", h_inode->i_ino); + if (h_dentry) + LKTRTrace("%.*s\n", AuDLNPair(h_dentry)); + + rdev = h_inode->i_rdev; + if (!rdev || !au_test_xfs(h_inode->i_sb)) + goto out; + + rdev = 0; + if (!h_dentry) { + err = 0; + h_dentry = d_find_alias(h_inode); + if (unlikely(!h_dentry)) + goto failure; + err = PTR_ERR(h_dentry); + if (IS_ERR(h_dentry)) { + h_dentry = NULL; + goto failure; + } + LKTRTrace("%.*s\n", AuDLNPair(h_dentry)); + } else + dget(h_dentry); + + err = vfsub_getattr(h_mnt, h_dentry, &st, /*dlgt*/0); + dput(h_dentry); + if (!err) { + rdev = st.rdev; + goto out; /* success */ + } + + failure: + AuIOErr("failed rdev for XFS inode, hi%lu, %d\n", h_inode->i_ino, err); + out: + return rdev; +} --- linux-2.6.27.orig/ubuntu/aufs/file.c +++ linux-2.6.27/ubuntu/aufs/file.c @@ -0,0 +1,762 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * handling file/dir, and address_space operation + * + * $Id: file.c,v 1.16 2008/09/22 03:52:09 sfjro Exp $ + */ + +#include +#include "aufs.h" + +/* + * a dirty trick for handling FMODE_EXEC and deny_write_access(). + * because FMODE_EXEC flag is not passed to f_op->open(), + * set it to file->private_data temporary. + */ +#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH) +int au_store_fmode_exec(struct nameidata *nd, struct inode *inode) +{ + int err; + union { + void *p; + unsigned long ul; + } u; + + err = 0; + if (nd + && (nd->flags & LOOKUP_OPEN) + && nd->intent.open.file + && (nd->intent.open.flags & FMODE_EXEC) + && inode + && S_ISREG(inode->i_mode)) { + u.ul = nd->intent.open.flags; + nd->intent.open.file->private_data = u.p; + /* smp_mb(); */ + err = 1; + } + + return err; +} +#endif + +/* drop flags for writing */ +unsigned int au_file_roflags(unsigned int flags) +{ + flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC); + flags |= O_RDONLY | O_NOATIME; + return flags; +} + +/* common functions to regular file and dir */ +struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, + struct file *file) +{ + struct file *h_file; + struct dentry *h_dentry; + struct inode *h_inode; + struct super_block *sb; + struct au_branch *br; + int err; + + LKTRTrace("%.*s, b%d, flags 0%o, f %d\n", + AuDLNPair(dentry), bindex, flags, !!file); + h_dentry = au_h_dptr(dentry, bindex); + AuDebugOn(!h_dentry); + h_inode = h_dentry->d_inode; + + /* a race condition can happen between open and unlink/rmdir */ + h_file = ERR_PTR(-ENOENT); + if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry)) + || !h_inode)) + goto out; + + sb = dentry->d_sb; + br = au_sbr(sb, bindex); + au_br_get(br); + /* drop flags for writing */ + if (au_test_ro(sb, bindex, dentry->d_inode)) + flags = au_file_roflags(flags); + flags &= ~O_CREAT; + + h_file = NULL; + if (unlikely(file && au_test_nfs(h_dentry->d_sb))) + h_file = au_h_intent(dentry, bindex, file); + if (!h_file) + h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags); + + /* + * a dirty trick for handling FMODE_EXEC and deny_write_access(). + */ + if (file && (file->f_mode & FMODE_EXEC)) { + h_file->f_mode |= FMODE_EXEC; + smp_mb(); /* flush f_mode */ + err = au_deny_write_access(h_file); + if (unlikely(err)) { + fput(h_file); + h_file = ERR_PTR(err); + } + } + if (IS_ERR(h_file)) + au_br_put(br); + +out: + AuTraceErrPtr(h_file); + return h_file; +} + +static int do_coo(struct dentry *dentry, aufs_bindex_t bstart) +{ + int err; + struct dentry *parent; + aufs_bindex_t bcpup; + struct mutex *h_mtx; + struct super_block *sb; + struct au_pin pin; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + AuDebugOn(IS_ROOT(dentry)); + DiMustWriteLock(dentry); + + parent = dget_parent(dentry); + di_write_lock_parent(parent); + sb = dentry->d_sb; + err = AuWbrCopyup(au_sbi(sb), dentry); + bcpup = err; + if (err < 0) { + err = 0; /* stop copyup, it is not an error */ + goto out_dgrade; + } + err = 0; + + if (!au_h_dptr(parent, bcpup)) { + err = au_cpup_dirs(dentry, bcpup); + if (unlikely(err)) + goto out_dgrade; + } + + di_downgrade_lock(parent, AuLock_IR); + err = au_pin(&pin, dentry, bcpup, /*di_locked*/1, + /*do_gp*/au_opt_test(au_mntflags(sb), UDBA_INOTIFY)); + if (unlikely(err)) + goto out; + h_mtx = &au_h_dptr(dentry, bstart)->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + AuDebugOn(au_h_dptr(dentry, bcpup)); + err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME); + AuTraceErr(err); + mutex_unlock(h_mtx); + au_unpin(&pin); + goto out; + + out_dgrade: + di_downgrade_lock(parent, AuLock_IR); + out: + di_read_unlock(parent, AuLock_IR); + dput(parent); + AuTraceErr(err); + return err; +} + +int au_do_open(struct inode *inode, struct file *file, + int (*open)(struct file *file, int flags)) +{ + int err; + struct dentry *dentry; + struct super_block *sb; + aufs_bindex_t bstart; + unsigned char coo; + + dentry = file->f_dentry; + LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry)); + + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + coo = 0; + switch (au_mntflags(sb) & AuOptMask_COO) { + case AuOpt_COO_LEAF: + coo = !S_ISDIR(inode->i_mode); + break; + case AuOpt_COO_ALL: + coo = 1; + break; + } + err = au_finfo_init(file); + if (unlikely(err)) + goto out; + + if (!coo) + di_read_lock_child(dentry, AuLock_IR); + else { + di_write_lock_child(dentry); + bstart = au_dbstart(dentry); + if (au_test_ro(sb, bstart, dentry->d_inode)) { + err = do_coo(dentry, bstart); + if (err) { + di_write_unlock(dentry); + goto out_finfo; + } + } + di_downgrade_lock(dentry, AuLock_IR); + } + + err = open(file, file->f_flags); + di_read_unlock(dentry, AuLock_IR); + + out_finfo: + fi_write_unlock(file); + if (unlikely(err)) + au_finfo_fin(file); + out: + si_read_unlock(sb); + AuTraceErr(err); + return err; +} + +int au_reopen_nondir(struct file *file) +{ + int err; + aufs_bindex_t bstart, bindex, bend; + struct dentry *dentry; + struct file *h_file, *h_file_tmp; + + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + bstart = au_dbstart(dentry); + //bstart = au_ibstart(inode); + AuDebugOn(S_ISDIR(dentry->d_inode->i_mode) + || !au_h_dptr(dentry, bstart)->d_inode); + + h_file_tmp = NULL; + if (au_fbstart(file) == bstart) { + h_file = au_h_fptr(file, bstart); + if (file->f_mode == h_file->f_mode) + return 0; /* success */ + h_file_tmp = h_file; + get_file(h_file_tmp); + au_set_h_fptr(file, bstart, NULL); + } + AuDebugOn(au_fbstart(file) < bstart + || au_fi(file)->fi_hfile[0 + bstart].hf_file); + + h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; /* todo: close all? */ + err = 0; + /* cpup_file_flags(h_file, file); */ + au_set_fbstart(file, bstart); + au_set_h_fptr(file, bstart, h_file); + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + + /* close lower files */ + bend = au_fbend(file); + for (bindex = bstart + 1; bindex <= bend; bindex++) + au_set_h_fptr(file, bindex, NULL); + au_set_fbend(file, bstart); + + out: + if (h_file_tmp) + fput(h_file_tmp); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_ready_to_write_wh(struct file *file, loff_t len, + aufs_bindex_t bcpup) +{ + int err; + aufs_bindex_t old_bstart; + struct inode *inode; + struct dentry *dentry, *hi_wh, *old_h_dentry; + struct au_dinfo *dinfo; + struct super_block *sb; + + AuTraceEnter(); + + dentry = file->f_dentry; + inode = dentry->d_inode; + hi_wh = au_hi_wh(inode, bcpup); + if (!hi_wh) + err = au_sio_cpup_wh(dentry, bcpup, len, file); + else { + /* already copied-up after unlink */ + dinfo = au_di(dentry); + old_bstart = dinfo->di_bstart; + dinfo->di_bstart = bcpup; + old_h_dentry = dinfo->di_hdentry[0 + bcpup].hd_dentry; + dinfo->di_hdentry[0 + bcpup].hd_dentry = hi_wh; + err = au_reopen_nondir(file); + dinfo->di_hdentry[0 + bcpup].hd_dentry = old_h_dentry; + dinfo->di_bstart = old_bstart; + } + + sb = dentry->d_sb; + if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK)) + au_plink_append(sb, inode, au_h_dptr(dentry, bcpup), bcpup); + + AuTraceErr(err); + return err; +} + +/* + * prepare the @file for writing. + */ +int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) +{ + int err; + struct dentry *dentry, *parent, *h_dentry; + struct inode *h_inode, *inode; + struct super_block *sb; + aufs_bindex_t bstart, bcpup; + + dentry = file->f_dentry; + LKTRTrace("%.*s, len %lld\n", AuDLNPair(dentry), len); + FiMustWriteLock(file); + + sb = dentry->d_sb; + bstart = au_fbstart(file); + AuDebugOn(au_fbr(file, bstart) != au_sbr(sb, bstart)); + + inode = dentry->d_inode; + AuDebugOn(S_ISDIR(inode->i_mode)); + LKTRTrace("rdonly %d, bstart %d\n", + au_test_ro(sb, bstart, inode), bstart); + + err = au_test_ro(sb, bstart, inode); + if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) { + err = au_pin(pin, dentry, bstart, /*di_locked*/0, /*dp_gp*/0); + goto out; + } + + /* need to cpup */ + parent = dget_parent(dentry); + di_write_lock_parent(parent); + err = AuWbrCopyup(au_sbi(sb), dentry); + bcpup = err; + if (unlikely(err < 0)) + goto out_dgrade; + err = 0; + + if (!au_h_dptr(parent, bcpup)) { + err = au_cpup_dirs(dentry, bcpup); + if (unlikely(err)) + goto out_dgrade; + } + + err = au_pin(pin, dentry, bcpup, /*di_locked*/1, + /*dp_gp*/au_opt_test(au_mntflags(sb), UDBA_INOTIFY)); + if (unlikely(err)) + goto out_dgrade; + + AuDebugOn(au_fbstart(file) != bstart); + h_dentry = au_h_fptr(file, bstart)->f_dentry; + h_inode = h_dentry->d_inode; + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */ + /* || !h_inode->i_nlink */) { + err = au_ready_to_write_wh(file, len, bcpup); + di_downgrade_lock(parent, AuLock_IR); + } else { + di_downgrade_lock(parent, AuLock_IR); + if (!au_h_dptr(dentry, bcpup)) + err = au_sio_cpup_simple(dentry, bcpup, len, + AuCpup_DTIME); + AuTraceErr(err); + if (!err) + err = au_reopen_nondir(file); + AuTraceErr(err); + } + mutex_unlock(&h_inode->i_mutex); + + if (!err) { + au_unpin_gp(pin); + au_pin_set_parent_lflag(pin, /*lflag*/0); + goto out_dput; /* success */ + } + au_unpin(pin); + goto out_unlock; + + out_dgrade: + di_downgrade_lock(parent, AuLock_IR); + out_unlock: + di_read_unlock(parent, AuLock_IR); + out_dput: + dput(parent); + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_file_refresh_by_inode(struct file *file, int *need_reopen) +{ + int err; + struct au_finfo *finfo; + struct dentry *dentry, *parent, *old_h_dentry, *hi_wh; + struct inode *inode, *dir; + aufs_bindex_t bstart, new_bstart, old_bstart; + struct super_block *sb; + struct au_dinfo *dinfo; + unsigned int mnt_flags; + struct au_pin pin; + + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + FiMustWriteLock(file); + + err = 0; + finfo = au_fi(file); + inode = dentry->d_inode; + sb = dentry->d_sb; + mnt_flags = au_mntflags(sb); + again: + bstart = au_ibstart(inode); + if (bstart == finfo->fi_bstart) + goto out; + + new_bstart = bstart; + parent = dget_parent(dentry); + dir = parent->d_inode; + if (au_test_ro(sb, bstart, inode)) { + di_read_lock_parent(parent, !AuLock_IR); + err = AuWbrCopyup(au_sbi(sb), dentry); + new_bstart = err; + di_read_unlock(parent, !AuLock_IR); + if (unlikely(err < 0)) + goto out_dput; + err = 0; + } + /* someone else might change our inode while we were sleeping */ + /* todo: test more? */ + if (bstart != au_ibstart(inode)) { + err = 0; + dput(parent); + goto again; + } + di_read_lock_parent(parent, AuLock_IR); + bstart = new_bstart; + + hi_wh = au_hi_wh(inode, bstart); + if (au_opt_test(mnt_flags, PLINK) + && au_plink_test(sb, inode) + && !d_unhashed(dentry)) { + err = au_test_and_cpup_dirs(dentry, bstart); + if (unlikely(err)) + goto out_unlock; + + /* always superio. */ +#if 1 + err = au_pin(&pin, dentry, bstart, /*di_locked*/1, + /*do_gp*/au_opt_test(mnt_flags, UDBA_INOTIFY)); + if (!err) + err = au_sio_cpup_simple(dentry, bstart, -1, AuCpup_DTIME); + au_unpin(&pin); +#else /* reserved for future use */ + if (!au_test_wkq(current)) { + int wkq_err; + struct cpup_pseudo_link_args args = { + .errp = &err, + .dentry = dentry, + .bdst = bstart, + .do_lock = 1 + }; + wkq_err = au_wkq_wait(call_cpup_pseudo_link, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } else + err = cpup_pseudo_link(dentry, bstart, /*do_lock*/1); +#endif + } else if (hi_wh) { + /* already copied-up after unlink */ + dinfo = au_di(dentry); + old_bstart = dinfo->di_bstart; + dinfo->di_bstart = bstart; + old_h_dentry = dinfo->di_hdentry[0 + bstart].hd_dentry; + dinfo->di_hdentry[0 + bstart].hd_dentry = hi_wh; + err = au_reopen_nondir(file); + dinfo->di_hdentry[0 + bstart].hd_dentry = old_h_dentry; + dinfo->di_bstart = old_bstart; + *need_reopen = 0; + } + + out_unlock: + di_read_unlock(parent, AuLock_IR); + out_dput: + dput(parent); + out: + AuTraceErr(err); + return err; +} + +/* + * after branch manipulating, refresh the file. + */ +static int refresh_file(struct file *file, int (*reopen)(struct file *file)) +{ + int err, new_sz, need_reopen; + struct dentry *dentry; + aufs_bindex_t bend, bindex, brid; + struct au_hfile *p; + struct au_finfo *finfo; + struct super_block *sb; + struct inode *inode; + + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + FiMustWriteLock(file); + DiMustAnyLock(dentry); + inode = dentry->d_inode; + IiMustAnyLock(inode); + + err = -ENOMEM; + sb = dentry->d_sb; + finfo = au_fi(file); + new_sz = sizeof(*finfo->fi_hfile) * (au_sbend(sb) + 1); + p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1), + new_sz, GFP_NOFS); + if (unlikely(!p)) + goto out; + finfo->fi_hfile = p; + + p += finfo->fi_bstart; + brid = p->hf_br->br_id; + bend = finfo->fi_bend; + for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) { + struct au_hfile tmp, *q; + aufs_bindex_t new_bindex; + + if (!p->hf_file) + continue; + new_bindex = au_find_bindex(sb, p->hf_br); + if (new_bindex == bindex) + continue; + /* todo: test more? */ + if (new_bindex < 0) { + au_set_h_fptr(file, bindex, NULL); + continue; + } + + /* swap two hidden inode, and loop again */ + q = finfo->fi_hfile + new_bindex; + tmp = *q; + *q = *p; + *p = tmp; + if (tmp.hf_file) { + bindex--; + p--; + } + } + { + aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend; + finfo->fi_bstart = 0; + finfo->fi_bend = au_sbend(sb); + finfo->fi_bstart = s; + finfo->fi_bend = e; + } + + p = finfo->fi_hfile; + if (!au_test_mmapped(file) && !d_unhashed(dentry)) { + bend = au_sbend(sb); + for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend; + finfo->fi_bstart++, p++) + if (p->hf_file) { + if (p->hf_file->f_dentry + && p->hf_file->f_dentry->d_inode) + break; + else + au_hfput(p); + } + } else { + bend = au_br_index(sb, brid); + for (finfo->fi_bstart = 0; finfo->fi_bstart < bend; + finfo->fi_bstart++, p++) + if (p->hf_file) + au_hfput(p); + bend = au_sbend(sb); + } + + p = finfo->fi_hfile + bend; + for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart; + finfo->fi_bend--, p--) + if (p->hf_file) { + if (p->hf_file->f_dentry + && p->hf_file->f_dentry->d_inode) + break; + else + au_hfput(p); + } + AuDebugOn(finfo->fi_bend < finfo->fi_bstart); + + err = 0; + need_reopen = 1; + if (!au_test_mmapped(file)) + err = au_file_refresh_by_inode(file, &need_reopen); + if (!err && need_reopen && !d_unhashed(dentry)) + err = reopen(file); + if (!err) { + au_update_figen(file); + return 0; /* success */ + } + + /* error, close all hidden files */ + bend = au_fbend(file); + for (bindex = au_fbstart(file); bindex <= bend; bindex++) + au_set_h_fptr(file, bindex, NULL); + + out: + AuTraceErr(err); + return err; +} + +/* common function to regular file and dir */ +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), + int wlock, int locked) +{ + int err; + struct dentry *dentry; + struct super_block *sb; + aufs_bindex_t bstart; + unsigned char pseudo_link; + au_gen_t sgen, fgen; + + dentry = file->f_dentry; + LKTRTrace("%.*s, w %d, l %d\n", AuDLNPair(dentry), wlock, locked); + sb = dentry->d_sb; + SiMustAnyLock(sb); + + err = 0; + sgen = au_sigen(sb); + fi_write_lock(file); + fgen = au_figen(file); + di_write_lock_child(dentry); + bstart = au_dbstart(dentry); + pseudo_link = (bstart != au_ibstart(dentry->d_inode)); + if (sgen == fgen && !pseudo_link && au_fbstart(file) == bstart) { + if (!wlock) { + di_downgrade_lock(dentry, AuLock_IR); + fi_downgrade_lock(file); + } + goto out; /* success */ + } + + LKTRTrace("sgen %d, fgen %d\n", sgen, fgen); + if (unlikely(sgen != au_digen(dentry) + || sgen != au_iigen(dentry->d_inode))) { + /* + * d_path() and path_lookup() is a simple and good approach + * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a + * deadlock. removed the code. + */ + err = au_reval_dpath(dentry, sgen); + if (unlikely(err < 0)) + goto out; + AuDebugOn(au_digen(dentry) != sgen + || au_iigen(dentry->d_inode) != sgen); + } + + err = refresh_file(file, reopen + /* , au_opt_test(au_mnt_flags(sb), REFROF) */); + if (!err) { + if (!wlock) { + di_downgrade_lock(dentry, AuLock_IR); + fi_downgrade_lock(file); + } + } else { + di_write_unlock(dentry); + fi_write_unlock(file); + } + + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* cf. aufs_nopage() */ +/* for madvise(2) */ +static int aufs_readpage(struct file *file, struct page *page) +{ + AuTraceEnter(); + unlock_page(page); + return 0; +} + +/* they will never be called. */ +#ifdef CONFIG_AUFS_DEBUG +static int aufs_prepare_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ AuUnsupport(); return 0; } +static int aufs_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ AuUnsupport(); return 0; } +static int aufs_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +{ AuUnsupport(); return 0; } +static int aufs_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) +{ AuUnsupport(); return 0; } +static int aufs_writepage(struct page *page, struct writeback_control *wbc) +{ AuUnsupport(); return 0; } +static void aufs_sync_page(struct page *page) +{ AuUnsupport(); } + +static int aufs_set_page_dirty(struct page *page) +{ AuUnsupport(); return 0; } +static void aufs_invalidatepage(struct page *page, unsigned long offset) +{ AuUnsupport(); } +static int aufs_releasepage(struct page *page, gfp_t gfp) +{ AuUnsupport(); return 0; } +static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, loff_t offset, + unsigned long nr_segs) +{ AuUnsupport(); return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +static struct page *aufs_get_xip_page(struct address_space *mapping, + sector_t offset, int create) +{ AuUnsupport(); return NULL; } +#endif +#endif /* CONFIG_AUFS_DEBUG */ + +struct address_space_operations aufs_aop = { + .readpage = aufs_readpage, +#ifdef CONFIG_AUFS_DEBUG + .writepage = aufs_writepage, + .sync_page = aufs_sync_page, + .set_page_dirty = aufs_set_page_dirty, + .prepare_write = aufs_prepare_write, + .commit_write = aufs_commit_write, + .write_begin = aufs_write_begin, + .write_end = aufs_write_end, + .invalidatepage = aufs_invalidatepage, + .releasepage = aufs_releasepage, + .direct_IO = aufs_direct_IO, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + .get_xip_page = aufs_get_xip_page, +#endif +#endif /* CONFIG_AUFS_DEBUG */ +}; --- linux-2.6.27.orig/ubuntu/aufs/br_fuse.c +++ linux-2.6.27/ubuntu/aufs/br_fuse.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * special handling for inode attributes on FUSE branch + * + * $Id: br_fuse.c,v 1.6 2008/07/27 22:49:28 sfjro Exp $ + */ + +#include "aufs.h" + +/* h_mnt can be NULL, is it safe? */ +int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry) +{ + int err; + struct kstat st; + + LKTRTrace("%.*s\n", AuDLNPair(h_dentry)); + + err = 0; + if (unlikely(h_dentry->d_inode + /* && atomic_read(&h_dentry->d_inode->i_count) */ + && au_test_fuse(h_dentry->d_sb))) { + err = vfsub_getattr(h_mnt, h_dentry, &st, /*dlgt*/0); + if (unlikely(err)) { + AuDbg("err %d\n", err); + au_debug_on(); + AuDbgDentry(h_dentry); + au_debug_off(); + WARN_ON(err); + } + } + return err; +} + +#if 0 /* temp */ +/* + * This function was born after a discussion with the FUSE developer. + * The inode attributes on a filesystem who defines i_op->getattr() + * is unreliable since such fs may not maintain the attributes at lookup. + * This function doesn't want the result of stat, instead wants the side-effect + * which refreshes the attributes. + * Hmm, there seems to be no such filesystem except fuse. + */ +int vfsub_i_attr(struct vfsmount *mnt, struct dentry *dentry, int dlgt) +{ + int err; + struct inode *inode; + struct inode_operations *op; + struct kstat st; + + inode = dentry->d_inode; + AuDebugOn(!inode); + + err = 0; + op = inode->i_op; + if (unlikely(op && op->getattr && !au_test_aufs(dentry->d_sb))) { + err = security_inode_getattr(mnt, dentry); + if (!err) + err = op->getattr(mnt, dentry, &st); + } + AuTraceErr(err); + return err; +} +#endif --- linux-2.6.27.orig/ubuntu/aufs/sbinfo.c +++ linux-2.6.27/ubuntu/aufs/sbinfo.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * superblock private data + * + * $Id: sbinfo.c,v 1.11 2008/07/27 22:49:36 sfjro Exp $ + */ + +#include +#include "aufs.h" + +/* + * they are necessary regardless sysfs is disabled. + */ +void au_si_free(struct kobject *kobj) +{ + struct au_sbinfo *sbinfo; + struct super_block *sb; + + LKTRTrace("kobj %p\n", kobj); + sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); + LKTRTrace("sbinfo %p\n", sbinfo); + AuDebugOn(!list_empty(&sbinfo->si_plink)); + + sb = sbinfo->si_sb; + si_write_lock(sb); + au_xino_clr(sb); + au_br_free(sbinfo); + kfree(sbinfo->si_branch); + au_export_put(sbinfo); + si_write_unlock(sb); + + kfree(sbinfo); +} + +int au_si_alloc(struct super_block *sb) +{ + int err; + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + + err = -ENOMEM; + sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS); + if (unlikely(!sbinfo)) + goto out; + sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); + if (unlikely(!sbinfo->si_branch)) + goto out_sbinfo; + + memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj)); + err = sysaufs_si_init(sbinfo); + if (unlikely(err)) + goto out_br; + + au_rw_init_wlock(&sbinfo->si_rwsem); + sbinfo->si_generation = 0; + sbinfo->au_si_status = 0; + sbinfo->si_bend = -1; + sbinfo->si_last_br_id = 0; + + sbinfo->si_wbr_copyup = AuWbrCopyup_Def; + sbinfo->si_wbr_create = AuWbrCreate_Def; + sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def; + sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def; + + sbinfo->si_mntflags = AuOpt_Def; + + sbinfo->si_xread = NULL; + sbinfo->si_xwrite = NULL; + sbinfo->si_xib = NULL; + mutex_init(&sbinfo->si_xib_mtx); + sbinfo->si_xib_buf = NULL; + au_xino_def_br_set(NULL, sbinfo); + /* leave si_xib_last_pindex and si_xib_next_bit */ + + au_nwt_init(&sbinfo->si_nowait); + + sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ; + sbinfo->si_dirwh = AUFS_DIRWH_DEF; + + spin_lock_init(&sbinfo->si_plink_lock); + INIT_LIST_HEAD(&sbinfo->si_plink); + + au_robr_lvma_init(sbinfo); + + /* leave other members for sysaufs and si_mnt. */ + sbinfo->si_sb = sb; + + sb->s_fs_info = sbinfo; + + au_debug_sbinfo_init(sbinfo); + return 0; /* success */ + + out_br: + kfree(sbinfo->si_branch); + out_sbinfo: + kfree(sbinfo); + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex) +{ + struct au_branch *br; + + SiMustAnyLock(sb); + AuDebugOn(bindex < 0 || au_sbend(sb) < bindex); + br = au_sbi(sb)->si_branch[0 + bindex]; + AuDebugOn(!br); + return br; +} + +au_gen_t au_sigen_inc(struct super_block *sb) +{ + au_gen_t gen; + + SiMustWriteLock(sb); + gen = ++au_sbi(sb)->si_generation; + au_update_digen(sb->s_root); + au_update_iigen(sb->s_root->d_inode); + sb->s_root->d_inode->i_version++; + return gen; +} + +int au_find_bindex(struct super_block *sb, struct au_branch *br) +{ + aufs_bindex_t bindex, bend; + + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) + if (au_sbr(sb, bindex) == br) + return bindex; + return -1; +} + +/* ---------------------------------------------------------------------- */ + +/* dentry and super_block lock. call at entry point */ +void aufs_read_lock(struct dentry *dentry, int flags) +{ + si_read_lock(dentry->d_sb, flags); + if (au_ftest_lock(flags, DW)) + di_write_lock_child(dentry); + else + di_read_lock_child(dentry, flags); +} + +void aufs_read_unlock(struct dentry *dentry, int flags) +{ + if (au_ftest_lock(flags, DW)) + di_write_unlock(dentry); + else + di_read_unlock(dentry, flags); + si_read_unlock(dentry->d_sb); +} + +void aufs_write_lock(struct dentry *dentry) +{ + si_write_lock(dentry->d_sb); + di_write_lock_child(dentry); +} + +void aufs_write_unlock(struct dentry *dentry) +{ + di_write_unlock(dentry); + si_write_unlock(dentry->d_sb); +} + +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) +{ + AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb); + si_read_lock(d1->d_sb, flags); + di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR)); +} + +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) +{ + AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb); + di_write_unlock2(d1, d2); + si_read_unlock(d1->d_sb); +} + +/* ---------------------------------------------------------------------- */ + +aufs_bindex_t au_new_br_id(struct super_block *sb) +{ + aufs_bindex_t br_id; + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + while (1) { + br_id = ++sbinfo->si_last_br_id; + if (br_id && au_br_index(sb, br_id) < 0) + return br_id; + } +} --- linux-2.6.27.orig/ubuntu/aufs/dentry.c +++ linux-2.6.27/ubuntu/aufs/dentry.c @@ -0,0 +1,1023 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * lookup and dentry operations + * + * $Id: dentry.c,v 1.15 2008/09/22 03:52:06 sfjro Exp $ + */ + +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +/* + * au_lkup_one() is a generic abstract entry function which calls + * lookup_one_len() or __lookup_hash() finally. it is some condisions that makes + * lookup complicated, which are nfs branch, open-intent and dlgt mode. + */ + +#if defined(CONFIG_AUFS_BR_NFS) || defined(CONFIG_AUFS_DLGT) +/* cf. lookup_one_len() in linux/fs/namei.c */ +struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len, + struct au_ndx *ndx) +{ + struct dentry *dentry; + + LKTRTrace("%.*s/%.*s, ndx{%d, 0x%x}\n", + AuDLNPair(parent), len, name, !!ndx->nfsmnt, ndx->flags); + + ndx->nd_file = NULL; + if (!ndx->nfsmnt) + dentry = au_lkup_one_dlgt(name, parent, len, ndx->flags); + else + dentry = au_lkup_hash(name, parent, len, ndx); + + AuTraceErrPtr(dentry); + return dentry; +} +#endif /* CONFIG_AUFS_BR_NFS || CONFIG_AUFS_DLGT */ + +struct au_lkup_one_args { + struct dentry **errp; + const char *name; + struct dentry *parent; + int len; + struct au_ndx *ndx; +}; + +static void au_call_lkup_one(void *args) +{ + struct au_lkup_one_args *a = args; + *a->errp = au_lkup_one(a->name, a->parent, a->len, a->ndx); +} + +#define AuLkup_ALLOW_NEG 1 +#define AuLkup_DLGT (1 << 1) +#define AuLkup_DIRPERM1 (1 << 2) +#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name) +#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; } +#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef AuLkup_DLGT +#define AuLkup_DLGT 0 +#undef AuLkup_DIRPERM1 +#define AuLkup_DIRPERM1 0 +#endif + +struct au_do_lookup_args { + unsigned int flags; + mode_t type; + struct nameidata *nd; +}; + +/* + * returns positive/negative dentry, NULL or an error. + * NULL means whiteout-ed or not-found. + */ +static /* noinline_for_stack */ +struct dentry *au_do_lookup(struct dentry *h_parent, struct dentry *dentry, + aufs_bindex_t bindex, struct qstr *wh_name, + struct au_do_lookup_args *args) +{ + struct dentry *h_dentry; + int err, wh_found, opq; + unsigned char wh_able; + struct inode *h_dir, *h_inode, *inode; + struct qstr *name; + struct super_block *sb; + unsigned int nd_flags; + struct au_ndx ndx = { + .flags = 0, + .nd = args->nd + }; + const int allow_neg = au_ftest_lkup(args->flags, ALLOW_NEG); + + LKTRTrace("%.*s/%.*s, b%d, {flags 0x%x, type 0%o, nd %d}\n", + AuDLNPair(h_parent), AuDLNPair(dentry), bindex, + args->flags, args->type, !!args->nd); + if (args->nd) + LKTRTrace("nd{0x%x}\n", args->nd->flags); + AuDebugOn(IS_ROOT(dentry)); + h_dir = h_parent->d_inode; + + nd_flags = 0; + wh_found = 0; + sb = dentry->d_sb; + ndx.nfsmnt = au_nfsmnt(sb, bindex); + if (unlikely(au_ftest_lkup(args->flags, DLGT))) + au_fset_ndx(ndx.flags, DLGT); + if (unlikely(au_ftest_lkup(args->flags, DIRPERM1))) + au_fset_ndx(ndx.flags, DIRPERM1); + LKTRTrace("nfsmnt %p\n", ndx.nfsmnt); + ndx.br = au_sbr(sb, bindex); + wh_able = !!au_br_whable(ndx.br->br_perm); + name = &dentry->d_name; + if (unlikely(wh_able)) + wh_found = au_test_robr_wh(name, h_parent, wh_name, + /*try_sio*/0, &ndx); + h_dentry = ERR_PTR(wh_found); + if (!wh_found) + goto real_lookup; + if (unlikely(wh_found < 0)) + goto out; + + /* We found a whiteout */ + /* au_set_dbend(dentry, bindex); */ + au_set_dbwh(dentry, bindex); + if (!allow_neg) + return NULL; /* success */ + if (unlikely(ndx.nd + && au_test_nfs(h_parent->d_sb) + && (ndx.nd->flags & LOOKUP_CREATE))) { + nd_flags = ndx.nd->flags; + ndx.nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE); + } + + real_lookup: + /* do not superio. */ + h_dentry = au_lkup_one(name->name, h_parent, name->len, &ndx); + if (IS_ERR(h_dentry)) + goto out; + AuDebugOn(d_unhashed(h_dentry)); + h_inode = h_dentry->d_inode; + if (!h_inode) { + if (!allow_neg) + goto out_neg; + } else if (wh_found + || (args->type && args->type != (h_inode->i_mode & S_IFMT))) + goto out_neg; + + if (au_dbend(dentry) <= bindex) + au_set_dbend(dentry, bindex); + if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry)) + au_set_dbstart(dentry, bindex); + au_set_h_dptr(dentry, bindex, h_dentry); + + err = au_br_nfs_h_intent(ndx.nd_file, dentry, bindex, args->nd); + if (unlikely(err)) { + h_dentry = ERR_PTR(err); + goto out; + } + + inode = dentry->d_inode; + if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able + || (inode && !S_ISDIR(inode->i_mode))) + goto out; /* success */ + + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + opq = au_diropq_test(h_dentry, &ndx); + mutex_unlock(&h_inode->i_mutex); + if (opq > 0) + au_set_dbdiropq(dentry, bindex); + else if (unlikely(opq < 0)) { + au_set_h_dptr(dentry, bindex, NULL); + h_dentry = ERR_PTR(opq); + } + goto out; + + out_neg: + dput(h_dentry); + h_dentry = NULL; + out: + if (unlikely(nd_flags)) + ndx.nd->flags |= (nd_flags & (LOOKUP_OPEN | LOOKUP_CREATE)); + AuTraceErrPtr(h_dentry); + return h_dentry; +} + +/* + * returns the number of hidden positive dentries, + * otherwise an error. + * can be called at unlinking with @type is zero. + */ +int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type, + struct nameidata *nd) +{ + int npositive, err; + unsigned int mnt_flags; + aufs_bindex_t bindex, btail, bdiropq; + unsigned char isdir; + struct qstr whname; + struct au_do_lookup_args args = { + .type = type, + .nd = nd + }; + const struct qstr *name = &dentry->d_name; + struct dentry *parent; + struct super_block *sb; + struct inode *inode; + + LKTRTrace("%.*s, b%d, type 0%o\n", AuLNPair(name), bstart, type); + AuDebugOn(bstart < 0 || IS_ROOT(dentry)); + + /* dir may not be locked */ + parent = dget_parent(dentry); + + err = au_test_robr_shwh(dentry->d_sb, name); + if (unlikely(err)) + goto out; + + err = au_wh_name_alloc(name->name, name->len, &whname); + if (unlikely(err)) + goto out; + + sb = dentry->d_sb; + mnt_flags = au_mntflags(sb); + inode = dentry->d_inode; + isdir = !!(inode && S_ISDIR(inode->i_mode)); + args.flags = 0; + if (unlikely(au_test_dlgt(mnt_flags))) + au_fset_lkup(args.flags, DLGT); + if (unlikely(au_test_dirperm1(mnt_flags))) + au_fset_lkup(args.flags, DIRPERM1); + if (!type) + au_fset_lkup(args.flags, ALLOW_NEG); + npositive = 0; + btail = au_dbtaildir(parent); + for (bindex = bstart; bindex <= btail; bindex++) { + struct dentry *h_parent, *h_dentry; + struct inode *h_inode, *h_dir; + + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry) { + if (h_dentry->d_inode) + npositive++; + if (type != S_IFDIR) + break; + continue; + } + h_parent = au_h_dptr(parent, bindex); + if (!h_parent) + continue; + h_dir = h_parent->d_inode; + if (!h_dir || !S_ISDIR(h_dir->i_mode)) + continue; + + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname, + &args); + mutex_unlock(&h_dir->i_mutex); + err = PTR_ERR(h_dentry); + if (IS_ERR(h_dentry)) + goto out_wh; + au_fclr_lkup(args.flags, ALLOW_NEG); + + if (au_dbwh(dentry) >= 0) + break; + if (!h_dentry) + continue; + h_inode = h_dentry->d_inode; + if (!h_inode) + continue; + npositive++; + if (!args.type) + args.type = h_inode->i_mode & S_IFMT; + if (args.type != S_IFDIR) + break; + else if (isdir) { + /* the type of lowers may be different */ + bdiropq = au_dbdiropq(dentry); + if (bdiropq >= 0 && bdiropq <= bindex) + break; + } + } + + if (npositive) { + LKTRLabel(positive); + au_update_dbstart(dentry); + } + err = npositive; + if (unlikely(!au_opt_test(mnt_flags, UDBA_NONE) + && au_dbstart(dentry) < 0)) + /* both of real entry and whiteout found */ + err = -EIO; + + out_wh: + au_wh_name_free(&whname); + out: + dput(parent); + AuTraceErr(err); + return err; +} + +struct dentry *au_sio_lkup_one(const char *name, struct dentry *parent, int len, + struct au_ndx *ndx) +{ + struct dentry *dentry; + int wkq_err; + + LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name); + + if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC, + au_ftest_ndx(ndx->flags, DLGT))) + dentry = au_lkup_one(name, parent, len, ndx); + else { + /* todo: ugly? */ + unsigned int flags = ndx->flags; + struct au_lkup_one_args args = { + .errp = &dentry, + .name = name, + .parent = parent, + .len = len, + .ndx = ndx + }; + + au_fclr_ndx(ndx->flags, DLGT); + au_fclr_ndx(ndx->flags, DIRPERM1); + wkq_err = au_wkq_wait(au_call_lkup_one, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + dentry = ERR_PTR(wkq_err); + ndx->flags = flags; + } + + AuTraceErrPtr(dentry); + return dentry; +} + +/* + * lookup @dentry on @bindex which should be negative. + */ +int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex) +{ + int err; + struct dentry *parent, *h_parent, *h_dentry; + struct inode *h_dir; + struct au_ndx ndx = { + .flags = 0, + .nd = NULL, + /* .br = NULL */ + }; + struct super_block *sb; + unsigned int mnt_flags; + + LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex); + /* dir may not be locked */ + parent = dget_parent(dentry); + AuDebugOn(!parent || !parent->d_inode + || !S_ISDIR(parent->d_inode->i_mode)); + h_parent = au_h_dptr(parent, bindex); + AuDebugOn(!h_parent); + h_dir = h_parent->d_inode; + AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode)); + + sb = dentry->d_sb; + mnt_flags = au_mntflags(sb); + ndx.nfsmnt = au_nfsmnt(sb, bindex); + if (unlikely(au_test_dlgt(mnt_flags))) + au_fset_ndx(ndx.flags, DLGT); + if (unlikely(au_test_dirperm1(mnt_flags))) + au_fset_ndx(ndx.flags, DIRPERM1); + h_dentry = au_sio_lkup_one(dentry->d_name.name, h_parent, + dentry->d_name.len, &ndx); + err = PTR_ERR(h_dentry); + if (IS_ERR(h_dentry)) + goto out; + if (unlikely(h_dentry->d_inode)) { + err = -EIO; + AuIOErr("b%d %.*s should be negative.\n", + bindex, AuDLNPair(h_dentry)); + dput(h_dentry); + goto out; + } + + if (bindex < au_dbstart(dentry)) + au_set_dbstart(dentry, bindex); + if (au_dbend(dentry) < bindex) + au_set_dbend(dentry, bindex); + au_set_h_dptr(dentry, bindex, h_dentry); + err = 0; + + out: + dput(parent); + AuTraceErr(err); + return err; +} + +/* + * returns the number of found hidden positive dentries, + * otherwise an error. + */ +int au_refresh_hdentry(struct dentry *dentry, mode_t type) +{ + int npositive, new_sz; + struct au_dinfo *dinfo; + struct super_block *sb; + struct dentry *parent; + aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend; + struct au_hdentry *p; + au_gen_t sgen; + + LKTRTrace("%.*s, type 0%o\n", AuDLNPair(dentry), type); + DiMustWriteLock(dentry); + sb = dentry->d_sb; + AuDebugOn(IS_ROOT(dentry)); + sgen = au_sigen(sb); + parent = dget_parent(dentry); + AuDebugOn(au_digen(parent) != sgen + || au_iigen(parent->d_inode) != sgen); + + npositive = -ENOMEM; + new_sz = sizeof(*dinfo->di_hdentry) * (au_sbend(sb) + 1); + dinfo = au_di(dentry); + p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1), + new_sz, GFP_NOFS); + if (unlikely(!p)) + goto out; + dinfo->di_hdentry = p; + + bend = dinfo->di_bend; + bwh = dinfo->di_bwh; + bdiropq = dinfo->di_bdiropq; + p += dinfo->di_bstart; + for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) { + struct dentry *hd, *hdp; + struct au_hdentry tmp, *q; + aufs_bindex_t new_bindex; + + hd = p->hd_dentry; + if (!hd) + continue; + hdp = dget_parent(hd); + if (hdp == au_h_dptr(parent, bindex)) { + dput(hdp); + continue; + } + + new_bindex = au_find_dbindex(parent, hdp); + dput(hdp); + AuDebugOn(new_bindex == bindex); + if (dinfo->di_bwh == bindex) + bwh = new_bindex; + if (dinfo->di_bdiropq == bindex) + bdiropq = new_bindex; + /* todo: test more? */ + if (new_bindex < 0) { + au_hdput(p, /*do_free*/0); + p->hd_dentry = NULL; + continue; + } + /* swap two hidden dentries, and loop again */ + q = dinfo->di_hdentry + new_bindex; + tmp = *q; + *q = *p; + *p = tmp; + if (tmp.hd_dentry) { + bindex--; + p--; + } + } + + /* todo: test more? */ + dinfo->di_bwh = -1; + if (unlikely(bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))) + dinfo->di_bwh = bwh; + dinfo->di_bdiropq = -1; + if (unlikely(bdiropq >= 0 && bdiropq <= au_sbend(sb) + && au_sbr_whable(sb, bdiropq))) + dinfo->di_bdiropq = bdiropq; + parent_bend = au_dbend(parent); + p = dinfo->di_hdentry; + for (bindex = 0; bindex <= parent_bend; bindex++, p++) + if (p->hd_dentry) { + dinfo->di_bstart = bindex; + break; + } + p = dinfo->di_hdentry + parent_bend; + for (bindex = parent_bend; bindex >= 0; bindex--, p--) + if (p->hd_dentry) { + dinfo->di_bend = bindex; + break; + } + + npositive = 0; + parent_bstart = au_dbstart(parent); + if (type != S_IFDIR && dinfo->di_bstart == parent_bstart) + goto out_dgen; /* success */ + + npositive = au_lkup_dentry(dentry, parent_bstart, type, /*nd*/NULL); + if (npositive < 0) + goto out; + if (unlikely(dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)) + d_drop(dentry); + + out_dgen: + au_update_digen(dentry); + out: + dput(parent); + AuTraceErr(npositive); + return npositive; +} + +static int au_lock_nd(struct dentry *dentry, struct nameidata *nd) +{ + int locked = 0; + if (nd && dentry != nd->path.dentry) { + di_read_lock_parent(nd->path.dentry, 0); + locked = 1; + } + return locked; +} + +static void au_unlock_nd(int locked, struct nameidata *nd) +{ + if (locked) + di_read_unlock(nd->path.dentry, 0); +} + +/* #define TestingFuse */ +static noinline_for_stack +int au_do_h_d_reval(struct dentry *dentry, aufs_bindex_t bindex, + struct nameidata *nd, struct dentry *h_dentry) +{ + int err, valid, e; + int (*reval)(struct dentry *, struct nameidata *); + struct super_block *sb; + struct nameidata fake_nd, *p; + + LKTRTrace("%.*s, b%d, nd %d\n", AuDLNPair(dentry), bindex, !!nd); + + err = 0; + reval = NULL; + if (h_dentry->d_op) + reval = h_dentry->d_op->d_revalidate; + if (!reval) + goto out; + + sb = dentry->d_sb; + if (nd) { + memcpy(&fake_nd, nd, sizeof(*nd)); + err = au_fake_intent(&fake_nd, au_sbr_perm(sb, bindex)); + if (unlikely(err)) { + err = -EINVAL; + goto out; + } + } + p = au_fake_dm(&fake_nd, nd, sb, bindex); + AuDebugOn(IS_ERR(p)); + AuDebugOn(nd && p != &fake_nd); + LKTRTrace("b%d\n", bindex); + + /* it may return tri-state */ +#if 1 + valid = reval(h_dentry, p); +#else + if (p /*&& !IS_ROOT(h_dentry)*/) { + struct dentry *h_parent = dget_parent(h_dentry); + struct mutex *h_mtx = &h_parent->d_inode->i_mutex; +#if 0 + lktr_set_pid(current->pid, LktrArrayPid); + AuDbgDentry(p->path.dentry); + AuDbgDentry(h_dentry); + lktr_clear_pid(current->pid, LktrArrayPid); +#endif + mutex_lock_nested(h_mtx, AuLsc_I_PARENT); + valid = reval(h_dentry, p); + mutex_unlock(h_mtx); + dput(h_parent); + } else + valid = reval(h_dentry, p); +#endif + if (unlikely(valid < 0)) + err = valid; + else if (!valid) + err = -EINVAL; + else + AuDebugOn(err); + + if (p) { + AuDebugOn(!nd); + e = au_hin_after_reval(p, dentry, bindex, nd->intent.open.file); +#ifndef TestingFuse + au_update_fuse_h_inode(p->path.mnt, h_dentry); /*ignore*/ +#endif + if (unlikely(e && !err)) + err = e; + } +#ifndef TestingFuse + else + au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/ +#endif + au_fake_dm_release(p); + + out: + AuTraceErr(err); + return err; +} + +static noinline_for_stack +int h_d_revalidate(struct dentry *dentry, struct inode *inode, + struct nameidata *nd, int do_udba) +{ + int err; + aufs_bindex_t bindex, btail, bstart, ibs, ibe; + unsigned char plus, locked, unhashed, is_root, h_plus; + struct super_block *sb; + struct inode *first, *h_inode, *h_cached_inode; + umode_t mode, h_mode; + struct dentry *h_dentry; + struct qstr *name; + + LKTRTrace("%.*s, nd %d\n", AuDLNPair(dentry), !!nd); + AuDebugOn(inode && au_digen(dentry) != au_iigen(inode)); + + err = 0; + sb = dentry->d_sb; + plus = 0; + mode = 0; + first = NULL; + ibs = -1; + ibe = -1; + unhashed = !!d_unhashed(dentry); + is_root = !!IS_ROOT(dentry); + name = &dentry->d_name; + + /* + * Theoretically, REVAL test should be unnecessary in case of INOTIFY. + * But inotify doesn't fire some necessary events, + * IN_ATTRIB for atime/nlink/pageio + * IN_DELETE for NFS dentry + * Let's do REVAL test too. + */ + if (do_udba && inode) { + mode = (inode->i_mode & S_IFMT); + plus = (inode->i_nlink > 0); + first = au_h_iptr(inode, au_ibstart(inode)); + ibs = au_ibstart(inode); + ibe = au_ibend(inode); + } + + bstart = au_dbstart(dentry); + btail = bstart; + if (inode && S_ISDIR(inode->i_mode)) + btail = au_dbtaildir(dentry); + locked = !!au_lock_nd(dentry, nd); + for (bindex = bstart; bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + + LKTRTrace("b%d, %.*s\n", bindex, AuDLNPair(h_dentry)); +#ifdef TestingFuse + /* force re-lookup for fuse, in order to update attributes */ + if (unlikely(au_test_fuse(h_dentry->d_sb))) + goto err; +#endif + + if (unlikely(do_udba + && !is_root + && (unhashed != !!d_unhashed(h_dentry) + || name->len != h_dentry->d_name.len + || memcmp(name->name, h_dentry->d_name.name, + name->len) + ))) { + LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n", + unhashed, d_unhashed(h_dentry), + AuDLNPair(dentry), AuDLNPair(h_dentry)); + goto err; + } + + err = au_do_h_d_reval(dentry, bindex, nd, h_dentry); + if (unlikely(err)) + /* do not goto err, to keep the errno */ + break; + + /* todo: plink too? */ + if (unlikely(!do_udba)) + continue; + + /* UDBA tests */ + h_inode = h_dentry->d_inode; + if (unlikely(!!inode != !!h_inode)) + goto err; + + h_plus = plus; + h_mode = mode; + h_cached_inode = h_inode; + if (h_inode) { + h_mode = (h_inode->i_mode & S_IFMT); + h_plus = (h_inode->i_nlink > 0); + } + if (inode && ibs <= bindex && bindex <= ibe) + h_cached_inode = au_h_iptr(inode, bindex); + + LKTRTrace("{%d, 0%o, %p}, h{%d, 0%o, %p}\n", + plus, mode, h_cached_inode, + h_plus, h_mode, h_inode); + if (unlikely(plus != h_plus + || mode != h_mode + || h_cached_inode != h_inode)) + goto err; + continue; + + err: + err = -EINVAL; + break; + } + au_unlock_nd(locked, nd); + + /* + * judging by timestamps is meaningless since some filesystem uses + * CURRENT_TIME_SEC instead of CURRENT_TIME. + */ + /* + * NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED. + */ + + AuTraceErr(err); + return err; +} + +static int simple_reval_dpath(struct dentry *dentry, au_gen_t sgen) +{ + int err; + mode_t type; + struct dentry *parent; + struct inode *inode; + + LKTRTrace("%.*s, sgen %d\n", AuDLNPair(dentry), sgen); + SiMustAnyLock(dentry->d_sb); + DiMustWriteLock(dentry); + inode = dentry->d_inode; + AuDebugOn(!inode); + + if (au_digen(dentry) == sgen && au_iigen(inode) == sgen) + return 0; + + parent = dget_parent(dentry); + di_read_lock_parent(parent, AuLock_IR); + AuDebugOn(au_digen(parent) != sgen + || au_iigen(parent->d_inode) != sgen); +#ifdef CONFIG_AUFS_DEBUG + { + int i, j; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + + err = au_dpages_init(&dpages, GFP_NOFS); + AuDebugOn(err); + err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, + NULL); + AuDebugOn(err); + for (i = dpages.ndpage - 1; !err && i >= 0; i--) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + for (j = dpage->ndentry - 1; !err && j >= 0; j--) + AuDebugOn(au_digen(dentries[j]) != sgen); + } + au_dpages_free(&dpages); + } +#endif + type = (inode->i_mode & S_IFMT); + /* returns a number of positive dentries */ + err = au_refresh_hdentry(dentry, type); + if (err >= 0) + err = au_refresh_hinode(inode, dentry); + di_read_unlock(parent, AuLock_IR); + dput(parent); + AuTraceErr(err); + return err; +} + +int au_reval_dpath(struct dentry *dentry, au_gen_t sgen) +{ + int err; + struct dentry *d, *parent; + struct inode *inode; + + LKTRTrace("%.*s, sgen %d\n", AuDLNPair(dentry), sgen); + AuDebugOn(!dentry->d_inode); + DiMustWriteLock(dentry); + + if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS)) + return simple_reval_dpath(dentry, sgen); + + /* slow loop, keep it simple and stupid */ + /* cf: au_cpup_dirs() */ + err = 0; + parent = NULL; + while (au_digen(dentry) != sgen || au_iigen(dentry->d_inode) != sgen) { + d = dentry; + while (1) { + dput(parent); + parent = dget_parent(d); + if (au_digen(parent) == sgen + && au_iigen(parent->d_inode) == sgen) + break; + d = parent; + } + + inode = d->d_inode; + if (d != dentry) + di_write_lock_child(d); + + /* someone might update our dentry while we were sleeping */ + if (au_digen(d) != sgen || au_iigen(d->d_inode) != sgen) { + di_read_lock_parent(parent, AuLock_IR); + /* returns a number of positive dentries */ + err = au_refresh_hdentry(d, inode->i_mode & S_IFMT); + if (err >= 0) + err = au_refresh_hinode(inode, d); + di_read_unlock(parent, AuLock_IR); + } + + if (d != dentry) + di_write_unlock(d); + dput(parent); + if (unlikely(err)) + break; + } + + AuTraceErr(err); + return err; +} + +/* + * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise. + * nfsd passes NULL as nameidata. + */ +static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd) +{ + int valid, err; + au_gen_t sgen; + unsigned char do_udba; + struct nameidata tmp_nd, *ndp; + struct super_block *sb; + struct inode *inode; + + LKTRTrace("dentry %.*s\n", AuDLNPair(dentry)); + if (nd && nd->path.dentry) + LKTRTrace("nd{%.*s, 0x%x}\n", + AuDLNPair(nd->path.dentry), nd->flags); + /* + * dir case: AuDebugOn(dentry->d_parent != nd->dentry); + * remove failure case:AuDebugOn(!IS_ROOT(dentry) + * && d_unhashed(dentry)); + */ + AuDebugOn(!dentry->d_fsdata); + + err = -EINVAL; +#if 0 + if (d_unhashed(dentry)) + goto __out; +#endif + sb = dentry->d_sb; +#if 1 + aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW); + inode = dentry->d_inode; +#else + si_read_lock(sb, AuLock_FLUSH); + //lktr_set_pid(current->pid, LktrArrayPid); + AuDbgDentry(dentry); + AuDbgInode(dentry->d_inode); + au_rw_write_lock_nested(&au_di(dentry)->di_rwsem, AuLsc_DI_CHILD); + LKTRLabel(clean); + //lktr_clear_pid(current->pid, LktrArrayPid); + inode = dentry->d_inode; + if (unlikely(inode && (!inode->i_nlink || IS_DEADDIR(inode)))) { + AuDbg("here\n"); + au_rw_write_unlock(&au_di(dentry)->di_rwsem); + si_read_unlock(sb); + goto __out; + } + if (inode) { + //lktr_set_pid(current->pid, LktrArrayPid); + AuDbgDentry(dentry); + AuDbgInode(inode); + ii_write_lock_child(inode); + LKTRLabel(clean); + //lktr_clear_pid(current->pid, LktrArrayPid); + } +#endif + + sgen = au_sigen(sb); + if (unlikely(au_digen(dentry) != sgen)) { + AuDebugOn(IS_ROOT(dentry)); +#ifdef ForceInotify + AuDbg("UDBA or digen, %.*s\n", AuDLNPair(dentry)); +#endif + if (inode) + err = au_reval_dpath(dentry, sgen); + if (unlikely(err)) + goto out_dgrade; + AuDebugOn(au_digen(dentry) != sgen); + } + if (unlikely(inode && au_iigen(inode) != sgen)) { + AuDebugOn(IS_ROOT(dentry)); +#ifdef ForceInotify + AuDbg("UDBA or survived, %.*s\n", AuDLNPair(dentry)); +#endif + err = au_refresh_hinode(inode, dentry); + if (unlikely(err)) + goto out_dgrade; + AuDebugOn(au_iigen(inode) != sgen); + } + di_downgrade_lock(dentry, AuLock_IR); + +#if 0 /* todo: support it? */ + /* parent dir i_nlink is not updated in the case of setattr */ + if (S_ISDIR(inode->i_mode)) { + mutex_lock(&inode->i_mutex); + ii_write_lock(inode); + au_cpup_attr_nlink(inode); + ii_write_unlock(inode); + mutex_unlock(&inode->i_mutex); + } +#endif + + AuDebugOn(au_digen(dentry) != sgen); + AuDebugOn(inode && au_iigen(inode) != sgen); + err = -EINVAL; + do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE); + if (do_udba && inode) { + aufs_bindex_t bstart = au_ibstart(inode); + if (bstart >= 0 + && au_test_higen(inode, au_h_iptr(inode, bstart))) + goto out; + } + ndp = au_dup_nd(au_sbi(sb), &tmp_nd, nd); +#if 0 + if (nd) { + path = nd->path; + nd->path.dentry = au_h_dptr(nd->path.dentry, bindex); + if (fake_nd->path.dentry) { + fake_nd->path.mnt = au_sbr_mnt(sb, bindex); + AuDebugOn(!fake_nd->path.mnt); + path_get(&fake_nd->path); + nd->path. + } + } +#endif + err = h_d_revalidate(dentry, inode, ndp, do_udba); + if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) + /* both of real entry and whiteout found */ + err = -EIO; + goto out; + + out_dgrade: + di_downgrade_lock(dentry, AuLock_IR); + out: + au_store_fmode_exec(nd, inode); + + aufs_read_unlock(dentry, AuLock_IR); + //__out: + AuTraceErr(err); + valid = !err; + if (!valid) + LKTRTrace("%.*s invalid\n", AuDLNPair(dentry)); + return valid; +} + +static void aufs_d_release(struct dentry *dentry) +{ + struct au_dinfo *dinfo; + aufs_bindex_t bend, bindex; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + AuDebugOn(!d_unhashed(dentry)); + + dinfo = dentry->d_fsdata; + if (unlikely(!dinfo)) + return; + + /* dentry may not be revalidated */ + bindex = dinfo->di_bstart; + if (bindex >= 0) { + struct au_hdentry *p; + bend = dinfo->di_bend; + AuDebugOn(bend < bindex); + p = dinfo->di_hdentry + bindex; + while (bindex++ <= bend) { + if (p->hd_dentry) + au_hdput(p, /*do_free*/1); + p++; + } + } + kfree(dinfo->di_hdentry); + au_cache_free_dinfo(dinfo); + au_hin_di_reinit(dentry); + /* todo: tmp code */ + //dentry->d_fsdata = NULL; +} + +struct dentry_operations aufs_dop = { + .d_revalidate = aufs_d_revalidate, + .d_release = aufs_d_release, + /* never use d_delete, especially in case of nfs server */ +}; --- linux-2.6.27.orig/ubuntu/aufs/dir.c +++ linux-2.6.27/ubuntu/aufs/dir.c @@ -0,0 +1,547 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * directory operations + * + * $Id: dir.c,v 1.13 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include +#include "aufs.h" + +static int reopen_dir(struct file *file) +{ + int err; + struct dentry *dentry, *h_dentry; + aufs_bindex_t bindex, btail, bstart; + struct file *h_file; + + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)); + + /* open all hidden dirs */ + bstart = au_dbstart(dentry); +#if 1 /* todo: necessary? */ + for (bindex = au_fbstart(file); bindex < bstart; bindex++) + au_set_h_fptr(file, bindex, NULL); +#endif + au_set_fbstart(file, bstart); + btail = au_dbtaildir(dentry); +#if 1 /* todo: necessary? */ + for (bindex = au_fbend(file); btail < bindex; bindex--) + au_set_h_fptr(file, bindex, NULL); +#endif + au_set_fbend(file, btail); + for (bindex = bstart; bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + h_file = au_h_fptr(file, bindex); + if (h_file) { + AuDebugOn(h_file->f_dentry != h_dentry); + continue; + } + + h_file = au_h_open(dentry, bindex, file->f_flags, file); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; /* close all? */ + /* cpup_file_flags(h_file, file); */ + au_set_h_fptr(file, bindex, h_file); + } + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + err = 0; + + out: + AuTraceErr(err); + return err; +} + +static int do_open_dir(struct file *file, int flags) +{ + int err; + aufs_bindex_t bindex, btail; + struct dentry *dentry, *h_dentry; + struct file *h_file; + + dentry = file->f_dentry; + LKTRTrace("%.*s, 0x%x\n", AuDLNPair(dentry), flags); + AuDebugOn(!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)); + + err = 0; + au_set_fvdir_cache(file, NULL); + file->f_version = dentry->d_inode->i_version; + bindex = au_dbstart(dentry); + au_set_fbstart(file, bindex); + btail = au_dbtaildir(dentry); + au_set_fbend(file, btail); + for (; !err && bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + + h_file = au_h_open(dentry, bindex, flags, file); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + break; + } + au_set_h_fptr(file, bindex, h_file); + } + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + if (!err) + return 0; /* success */ + + /* close all */ + for (bindex = au_fbstart(file); bindex <= btail; bindex++) + au_set_h_fptr(file, bindex, NULL); + au_set_fbstart(file, -1); + au_set_fbend(file, -1); + return err; +} + +static int aufs_open_dir(struct inode *inode, struct file *file) +{ + LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry)); + + return au_do_open(inode, file, do_open_dir); +} + +static int aufs_release_dir(struct inode *inode, struct file *file) +{ + struct au_vdir *vdir_cache; + struct super_block *sb; + + LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry)); + + sb = file->f_dentry->d_sb; + si_noflush_read_lock(sb); + fi_write_lock(file); + vdir_cache = au_fvdir_cache(file); + if (vdir_cache) + au_vdir_free(vdir_cache); + fi_write_unlock(file); + au_finfo_fin(file); + si_read_unlock(sb); + return 0; +} + +static int fsync_dir(struct dentry *dentry, int datasync) +{ + int err; + struct inode *inode; + struct super_block *sb; + aufs_bindex_t bend, bindex; + + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync); + DiMustAnyLock(dentry); + sb = dentry->d_sb; + SiMustAnyLock(sb); + inode = dentry->d_inode; + IMustLock(inode); + IiMustAnyLock(inode); + + err = 0; + bend = au_dbend(dentry); + for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) { + struct dentry *h_dentry; + struct inode *h_inode; + struct file_operations *fop; + + if (au_test_ro(sb, bindex, inode)) + continue; + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + h_inode = h_dentry->d_inode; + if (!h_inode) + continue; + + /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */ + /* todo: inotiry fired? */ + mutex_lock(&h_inode->i_mutex); + fop = (void *)h_inode->i_fop; + err = filemap_fdatawrite(h_inode->i_mapping); + if (!err && fop && fop->fsync) + err = fop->fsync(NULL, h_dentry, datasync); + if (!err) + err = filemap_fdatawrite(h_inode->i_mapping); + if (!err) + au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/ + mutex_unlock(&h_inode->i_mutex); + } + + AuTraceErr(err); + return err; +} + +/* + * @file may be NULL + */ +static int aufs_fsync_dir(struct file *file, struct dentry *dentry, + int datasync) +{ + int err; + struct inode *inode; + struct file *h_file; + struct super_block *sb; + aufs_bindex_t bend, bindex; + + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync); + inode = dentry->d_inode; + IMustLock(inode); + + err = 0; + sb = dentry->d_sb; + si_noflush_read_lock(sb); + if (file) { + err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, + /*locked*/1); + if (unlikely(err)) + goto out; + } else + di_write_lock_child(dentry); + + if (file) { + bend = au_fbend(file); + for (bindex = au_fbstart(file); !err && bindex <= bend; + bindex++) { + h_file = au_h_fptr(file, bindex); + if (!h_file || au_test_ro(sb, bindex, inode)) + continue; + + err = -EINVAL; + if (h_file->f_op && h_file->f_op->fsync) { + /* todo: try do_fsync() in fs/sync.c? */ + mutex_lock(&h_file->f_mapping->host->i_mutex); + err = h_file->f_op->fsync + (h_file, h_file->f_dentry, datasync); + if (!err) + au_update_fuse_h_inode + (h_file->f_vfsmnt, + h_file->f_dentry); + /*ignore*/ + mutex_unlock(&h_file->f_mapping->host->i_mutex); + } + } + } else + err = fsync_dir(dentry, datasync); + au_cpup_attr_timesizes(inode); + di_write_unlock(dentry); + if (file) + fi_write_unlock(file); + + out: + si_read_unlock(sb); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + int err, iflag; + struct dentry *dentry; + struct inode *inode; + struct super_block *sb; + + dentry = file->f_dentry; + LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos); + inode = dentry->d_inode; + IMustLock(inode); + + au_nfsd_lockdep_off(); + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*locked*/1); + if (unlikely(err)) + goto out; + + err = au_vdir_init(file); + if (unlikely(err)) { + di_write_unlock(dentry); + goto out_unlock; + } + + /* nfsd filldir calls lookup_one_len(). */ + iflag = AuLock_IW; + if (unlikely(au_test_nfsd(current))) + iflag = AuLock_IR; + di_downgrade_lock(dentry, iflag); + err = au_vdir_fill_de(file, dirent, filldir); + + fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode))); + di_read_unlock(dentry, iflag); + + out_unlock: + fi_write_unlock(file); + out: + si_read_unlock(sb); + au_nfsd_lockdep_on(); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +#define AuTestEmpty_WHONLY 1 +#define AuTestEmpty_DLGT (1 << 1) +#define AuTestEmpty_DIRPERM1 (1 << 2) +#define AuTestEmpty_CALLED (1 << 3) +#define AuTestEmpty_SHWH (1 << 4) +#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name) +#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; } +#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef AuTestEmpty_DLGT +#define AuTestEmpty_DLGT 0 +#undef AuTestEmpty_DIRPERM1 +#define AuTestEmpty_DIRPERM1 0 +#endif +#ifndef CONFIG_AUFS_SHWH +#undef AuTestEmpty_SHWH +#define AuTestEmpty_SHWH 0 +#endif + +struct test_empty_arg { + struct au_nhash *whlist; + unsigned int flags; + int err; + aufs_bindex_t bindex; +}; + +static int test_empty_cb(void *__arg, const char *__name, int namelen, + loff_t offset, u64 ino, unsigned int d_type) +{ + struct test_empty_arg *arg = __arg; + char *name = (void *)__name; + + LKTRTrace("%.*s\n", namelen, name); + + arg->err = 0; + au_fset_testempty(arg->flags, CALLED); + /* smp_mb(); */ + if (name[0] == '.' + && (namelen == 1 || (name[1] == '.' && namelen == 2))) + return 0; /* success */ + + if (namelen <= AUFS_WH_PFX_LEN + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { + if (au_ftest_testempty(arg->flags, WHONLY) + && !au_nhash_test_known_wh(arg->whlist, name, namelen)) + arg->err = -ENOTEMPTY; + goto out; + } + + name += AUFS_WH_PFX_LEN; + namelen -= AUFS_WH_PFX_LEN; + if (!au_nhash_test_known_wh(arg->whlist, name, namelen)) + arg->err = au_nhash_append_wh + (arg->whlist, name, namelen, ino, d_type, arg->bindex, + au_ftest_testempty(arg->flags, SHWH)); + + out: + /* smp_mb(); */ + AuTraceErr(arg->err); + return arg->err; +} + +static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg) +{ + int err, dlgt; + struct file *h_file; + + LKTRTrace("%.*s, {%p, 0x%x, %d}\n", + AuDLNPair(dentry), arg->whlist, arg->flags, arg->bindex); + + h_file = au_h_open(dentry, arg->bindex, + O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE, + /*file*/NULL); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; + err = 0; + if (unlikely(au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY) + && !h_file->f_dentry->d_inode->i_nlink)) + goto out_put; + + dlgt = au_ftest_testempty(arg->flags, DLGT); + do { + arg->err = 0; + au_fclr_testempty(arg->flags, CALLED); + /* smp_mb(); */ + err = vfsub_readdir(h_file, test_empty_cb, arg, dlgt); + if (err >= 0) + err = arg->err; + } while (!err && au_ftest_testempty(arg->flags, CALLED)); + + out_put: + fput(h_file); + au_sbr_put(dentry->d_sb, arg->bindex); + out: + AuTraceErr(err); + return err; +} + +struct do_test_empty_args { + int *errp; + struct dentry *dentry; + struct test_empty_arg *arg; +}; + +static void call_do_test_empty(void *args) +{ + struct do_test_empty_args *a = args; + *a->errp = do_test_empty(a->dentry, a->arg); +} + +static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) +{ + int err, wkq_err; + struct dentry *h_dentry; + struct inode *h_inode; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + h_dentry = au_h_dptr(dentry, arg->bindex); + AuDebugOn(!h_dentry); + h_inode = h_dentry->d_inode; + AuDebugOn(!h_inode); + + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ, + au_test_dlgt(au_mntflags(dentry->d_sb))); + mutex_unlock(&h_inode->i_mutex); + if (!err) + err = do_test_empty(dentry, arg); + else { + struct do_test_empty_args args = { + .errp = &err, + .dentry = dentry, + .arg = arg + }; + unsigned int flags = arg->flags; + + au_fclr_testempty(arg->flags, DLGT); + au_fclr_testempty(arg->flags, DIRPERM1); + wkq_err = au_wkq_wait(call_do_test_empty, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + arg->flags = flags; + } + + AuTraceErr(err); + return err; +} + +int au_test_empty_lower(struct dentry *dentry) +{ + int err; + struct inode *inode; + struct test_empty_arg arg; + struct au_nhash *whlist; + aufs_bindex_t bindex, bstart, btail; + unsigned int mnt_flags; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + inode = dentry->d_inode; + AuDebugOn(!inode || !S_ISDIR(inode->i_mode)); + + whlist = au_nhash_new(GFP_NOFS); + err = PTR_ERR(whlist); + if (IS_ERR(whlist)) + goto out; + + bstart = au_dbstart(dentry); + mnt_flags = au_mntflags(dentry->d_sb); + arg.whlist = whlist; + arg.flags = 0; + if (unlikely(au_test_dlgt(mnt_flags))) + au_fset_testempty(arg.flags, DLGT); + if (unlikely(au_opt_test(mnt_flags, SHWH))) + au_fset_testempty(arg.flags, SHWH); + arg.bindex = bstart; + err = do_test_empty(dentry, &arg); + if (unlikely(err)) + goto out_whlist; + + au_fset_testempty(arg.flags, WHONLY); + if (unlikely(au_test_dirperm1(mnt_flags))) + au_fset_testempty(arg.flags, DIRPERM1); + btail = au_dbtaildir(dentry); + for (bindex = bstart + 1; !err && bindex <= btail; bindex++) { + struct dentry *h_dentry; + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry && h_dentry->d_inode) { + arg.bindex = bindex; + err = do_test_empty(dentry, &arg); + } + } + + out_whlist: + au_nhash_del(whlist); + out: + AuTraceErr(err); + return err; +} + +int au_test_empty(struct dentry *dentry, struct au_nhash *whlist) +{ + int err; + struct inode *inode; + struct test_empty_arg arg; + aufs_bindex_t bindex, btail; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + inode = dentry->d_inode; + AuDebugOn(!inode || !S_ISDIR(inode->i_mode)); + + err = 0; + arg.whlist = whlist; + arg.flags = AuTestEmpty_WHONLY; + if (unlikely(au_opt_test(au_mntflags(dentry->d_sb), SHWH))) + au_fset_testempty(arg.flags, SHWH); + btail = au_dbtaildir(dentry); + for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) { + struct dentry *h_dentry; + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry && h_dentry->d_inode) { + arg.bindex = bindex; + err = sio_test_empty(dentry, &arg); + } + } + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct file_operations aufs_dir_fop = { + .read = generic_read_dir, + .readdir = aufs_readdir, + .open = aufs_open_dir, + .release = aufs_release_dir, + .flush = aufs_flush, + .fsync = aufs_fsync_dir, +}; --- linux-2.6.27.orig/ubuntu/aufs/sysrq.c +++ linux-2.6.27/ubuntu/aufs/sysrq.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * magic sysrq hanlder + * + * $Id: sysrq.c,v 1.10 2008/09/08 02:40:48 sfjro Exp $ + */ + +#include +#include +#include +/* #include */ +#include "aufs.h" + +static void sysrq_sb(struct super_block *sb) +{ + char *plevel; + struct inode *i; + + plevel = au_plevel; + au_plevel = KERN_WARNING; + au_debug_on(); + + pr_warning("si=%lx\n", au_si_mask ^ (unsigned long)au_sbi(sb)); + pr_warning(AUFS_NAME ": superblock\n"); + au_dpri_sb(sb); + pr_warning(AUFS_NAME ": root dentry\n"); + au_dpri_dentry(sb->s_root); + pr_warning(AUFS_NAME ": root inode\n"); + au_dpri_inode(sb->s_root->d_inode); + pr_warning(AUFS_NAME ": isolated inode\n"); + list_for_each_entry(i, &sb->s_inodes, i_sb_list) + if (list_empty(&i->i_dentry)) + au_dpri_inode(i); + + au_plevel = plevel; + au_debug_off(); +} + +/* ---------------------------------------------------------------------- */ + +/* module parameter */ +static char *aufs_sysrq_key = "a"; +module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO); +MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); + +static void au_sysrq(int key, struct tty_struct *tty) +{ + struct kobject *kobj; + struct au_sbinfo *sbinfo; + + /* spin_lock(&au_kset->list_lock); */ + list_for_each_entry(kobj, &au_kset->list, entry) { + sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); + sysrq_sb(sbinfo->si_sb); + } + /* spin_unlock(&au_kset->list_lock); */ +} + +static struct sysrq_key_op au_sysrq_op = { + .handler = au_sysrq, + .help_msg = "Aufs", + .action_msg = "Aufs", + /* todo: test mask? */ + .enable_mask = SYSRQ_ENABLE_DUMP +}; + +/* ---------------------------------------------------------------------- */ + +int __init au_sysrq_init(void) +{ + int err; + char key; + + err = -1; + key = *aufs_sysrq_key; + if ('a' <= key && key <= 'z') + err = register_sysrq_key(key, &au_sysrq_op); + if (unlikely(err)) + AuErr("err %d, sysrq=%c\n", err, key); + return err; +} + +void au_sysrq_fin(void) +{ + int err; + err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op); + if (unlikely(err)) + AuErr("err %d (ignored)\n", err); +} --- linux-2.6.27.orig/ubuntu/aufs/i_op.c +++ linux-2.6.27/ubuntu/aufs/i_op.c @@ -0,0 +1,1003 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations (except add/del/rename) + * + * $Id: i_op.c,v 1.19 2008/09/08 02:39:57 sfjro Exp $ + */ + +#include +#include +#include "aufs.h" + +static int silly_lock(struct inode *inode, struct nameidata *nd) +{ + int locked = 0; + struct super_block *sb = inode->i_sb; + + LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd); + + if (!nd || !nd->path.dentry) { + si_read_lock(sb, AuLock_FLUSH); + ii_read_lock_child(inode); + } else if (nd->path.dentry->d_inode != inode) { + locked = 1; + /* lock child first, then parent */ + si_read_lock(sb, AuLock_FLUSH); + ii_read_lock_child(inode); + di_read_lock_parent(nd->path.dentry, 0); + } else { + locked = 2; + aufs_read_lock(nd->path.dentry, AuLock_FLUSH | AuLock_IR); + } + return locked; +} + +static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd) +{ + struct super_block *sb = inode->i_sb; + + LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd); + + switch (locked) { + case 0: + ii_read_unlock(inode); + si_read_unlock(sb); + break; + case 1: + di_read_unlock(nd->path.dentry, 0); + ii_read_unlock(inode); + si_read_unlock(sb); + break; + case 2: + aufs_read_unlock(nd->path.dentry, AuLock_IR); + break; + default: + BUG(); + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +static int h_permission(struct inode *h_inode, int mask, + struct vfsmount *h_mnt, int brperm, int dlgt) +{ + int err, submask; + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND)); + + LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n", + h_inode->i_ino, mask, brperm); + + err = -EACCES; + if (unlikely((write_mask && IS_IMMUTABLE(h_inode)) + || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode) + && (h_mnt->mnt_flags & MNT_NOEXEC)) + )) + goto out; + + /* + * - skip hidden fs test in the case of write to ro branch. + * - nfs dir permission write check is optimized, but a policy for + * link/rename requires a real check. + */ + submask = mask & ~MAY_APPEND; + if ((write_mask && !au_br_writable(brperm)) + || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) + && write_mask && !(mask & MAY_READ)) + || !h_inode->i_op + || !h_inode->i_op->permission) { + /* LKTRLabel(generic_permission); */ + err = generic_permission(h_inode, submask, NULL); + } else { + /* LKTRLabel(h_inode->permission); */ + err = h_inode->i_op->permission(h_inode, submask); + AuTraceErr(err); + } + +#if 1 /* todo: export? */ + if (!err) + err = au_security_inode_permission(h_inode, mask, NULL, + dlgt); +#endif + + out: + AuTraceErr(err); + return err; +} + +static int aufs_permission(struct inode *inode, int mask) +{ + int err; + aufs_bindex_t bindex, bend; + unsigned char locked, dlgt; + const unsigned char isdir = S_ISDIR(inode->i_mode); + struct inode *h_inode; + struct super_block *sb; + unsigned int mnt_flags; + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND)); + + LKTRTrace("ino %lu, mask 0x%x, isdir %d, write_mask %d\n", + inode->i_ino, mask, isdir, write_mask); + + sb = inode->i_sb; + locked = silly_lock(inode, NULL); + mnt_flags = au_mntflags(sb); + dlgt = !!au_test_dlgt(mnt_flags); + + if (/* unlikely */(!isdir || write_mask + || au_test_dirperm1(mnt_flags))) { + h_inode = au_h_iptr(inode, au_ibstart(inode)); + AuDebugOn(!h_inode + || ((h_inode->i_mode & S_IFMT) + != (inode->i_mode & S_IFMT))); + err = 0; + bindex = au_ibstart(inode); + LKTRTrace("b%d\n", bindex); + err = h_permission(h_inode, mask, au_sbr_mnt(sb, bindex), + au_sbr_perm(sb, bindex), dlgt); + + if (write_mask && !err) { + /* test whether the upper writable branch exists */ + err = -EROFS; + for (; bindex >= 0; bindex--) + if (!au_br_rdonly(au_sbr(sb, bindex))) { + err = 0; + break; + } + } + goto out; + } + + /* non-write to dir */ + err = 0; + bend = au_ibend(inode); + for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) { + h_inode = au_h_iptr(inode, bindex); + if (!h_inode) + continue; + AuDebugOn(!S_ISDIR(h_inode->i_mode)); + + LKTRTrace("b%d\n", bindex); + err = h_permission(h_inode, mask, au_sbr_mnt(sb, bindex), + au_sbr_perm(sb, bindex), dlgt); + } + + out: + silly_unlock(locked, inode, NULL); + AuTraceErr(err); + return err; +} +#else + +static int h_permission(struct inode *h_inode, int mask, + struct nameidata *fake_nd, int brperm, int dlgt) +{ + int err, submask; + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND)); + + LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n", + h_inode->i_ino, mask, brperm); + + err = -EACCES; + if (unlikely((write_mask && IS_IMMUTABLE(h_inode)) + || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode) + && fake_nd && fake_nd->path.mnt + && (fake_nd->path.mnt->mnt_flags & MNT_NOEXEC)) + )) + goto out; + + /* + * - skip hidden fs test in the case of write to ro branch. + * - nfs dir permission write check is optimized, but a policy for + * link/rename requires a real check. + */ + submask = mask & ~MAY_APPEND; + if ((write_mask && !au_br_writable(brperm)) + || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) + && write_mask && !(mask & MAY_READ)) + || !h_inode->i_op + || !h_inode->i_op->permission) { + /* LKTRLabel(generic_permission); */ + err = generic_permission(h_inode, submask, NULL); + } else { + /* LKTRLabel(h_inode->permission); */ + err = h_inode->i_op->permission(h_inode, submask, fake_nd); + AuTraceErr(err); + } + +#if 1 /* todo: export? */ + if (!err) + err = au_security_inode_permission(h_inode, mask, fake_nd, + dlgt); +#endif + + out: + AuTraceErr(err); + return err; +} + +static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + int err; + aufs_bindex_t bindex, bend; + unsigned char locked, dlgt, do_nd; + const unsigned char isdir = S_ISDIR(inode->i_mode); + struct inode *h_inode; + struct super_block *sb; + unsigned int mnt_flags; + struct path path; + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND)); + + LKTRTrace("ino %lu, mask 0x%x, isdir %d, write_mask %d, " + "nd %d{%d, %d}\n", + inode->i_ino, mask, isdir, write_mask, + !!nd, nd ? !!nd->path.dentry : 0, nd ? !!nd->path.mnt : 0); + + sb = inode->i_sb; + locked = silly_lock(inode, nd); + do_nd = (nd && locked >= 1); + mnt_flags = au_mntflags(sb); + dlgt = !!au_test_dlgt(mnt_flags); + + if (/* unlikely */(!isdir || write_mask + || au_test_dirperm1(mnt_flags))) { + h_inode = au_h_iptr(inode, au_ibstart(inode)); + AuDebugOn(!h_inode + || ((h_inode->i_mode & S_IFMT) + != (inode->i_mode & S_IFMT))); + err = 0; + bindex = au_ibstart(inode); + LKTRTrace("b%d\n", bindex); + if (do_nd) { + path = nd->path; + nd->path.mnt = au_sbr_mnt(sb, bindex); + nd->path.dentry = au_h_dptr(nd->path.dentry, bindex); + path_get(&nd->path); + err = h_permission(h_inode, mask, nd, + au_sbr_perm(sb, bindex), dlgt); + path_put(&nd->path); + nd->path = path; + } else { + AuDebugOn(nd && nd->path.mnt); + err = h_permission(h_inode, mask, nd, + au_sbr_perm(sb, bindex), dlgt); + } + + if (write_mask && !err) { + /* test whether the upper writable branch exists */ + err = -EROFS; + for (; bindex >= 0; bindex--) + if (!au_br_rdonly(au_sbr(sb, bindex))) { + err = 0; + break; + } + } + goto out; + } + + /* non-write to dir */ + if (do_nd) + path = nd->path; + else { + path.mnt = NULL; + path.dentry = NULL; + } + err = 0; + bend = au_ibend(inode); + for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) { + h_inode = au_h_iptr(inode, bindex); + if (!h_inode) + continue; + AuDebugOn(!S_ISDIR(h_inode->i_mode)); + + LKTRTrace("b%d\n", bindex); + if (do_nd) { + nd->path.mnt = au_sbr_mnt(sb, bindex); + nd->path.dentry = au_h_dptr(path.dentry, bindex); + path_get(&nd->path); + err = h_permission(h_inode, mask, nd, + au_sbr_perm(sb, bindex), dlgt); + path_put(&nd->path); + } else { + AuDebugOn(nd && nd->path.mnt); + err = h_permission(h_inode, mask, nd, + au_sbr_perm(sb, bindex), dlgt); + } + } + if (do_nd) + nd->path = path; + + out: + silly_unlock(locked, inode, nd); + AuTraceErr(err); + return err; +} +#endif /* KERNEL_VERSION(2, 6, 27) */ + +/* ---------------------------------------------------------------------- */ + +static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + struct dentry *ret, *parent; + int err, npositive; + struct inode *inode, *h_inode; + struct nameidata tmp_nd, *ndp; + aufs_bindex_t bstart; + struct mutex *mtx; + struct super_block *sb; + + LKTRTrace("dir %lu, %.*s, nd{0x%x}\n", + dir->i_ino, AuDLNPair(dentry), nd ? nd->flags : 0); + AuDebugOn(IS_ROOT(dentry)); + IMustLock(dir); + + sb = dir->i_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_alloc_dinfo(dentry); + ret = ERR_PTR(err); + if (unlikely(err)) + goto out; + + /* nd can be NULL */ + ndp = au_dup_nd(au_sbi(sb), &tmp_nd, nd); + parent = dentry->d_parent; /* dir inode is locked */ + di_read_lock_parent(parent, AuLock_IR); + npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, ndp); + di_read_unlock(parent, AuLock_IR); + err = npositive; + ret = ERR_PTR(err); + if (unlikely(err < 0)) + goto out_unlock; + + inode = NULL; + if (npositive) { + bstart = au_dbstart(dentry); + h_inode = au_h_dptr(dentry, bstart)->d_inode; + AuDebugOn(!h_inode); + if (!S_ISDIR(h_inode->i_mode)) { + /* + * stop 'race'-ing between hardlinks under different + * parents. + */ + mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx; + mutex_lock(mtx); + inode = au_new_inode(dentry); + mutex_unlock(mtx); + } else + inode = au_new_inode(dentry); + ret = (void *)inode; + } + if (!IS_ERR(inode)) { + ret = d_splice_alias(inode, dentry); + if (unlikely(IS_ERR(ret) && inode)) + ii_write_unlock(inode); + AuDebugOn(nd + && (nd->flags & LOOKUP_OPEN) + && nd->intent.open.file + && nd->intent.open.file->f_dentry); + au_store_fmode_exec(nd, inode); + } + + out_unlock: + di_write_unlock(dentry); + out: + si_read_unlock(sb); + AuTraceErrPtr(ret); + return ret; +} + +/* ---------------------------------------------------------------------- */ + +/* + * decide the branch and the parent dir where we will create a new entry. + * returns new bindex or an error. + * copyup the parent dir if needed. + */ +int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, + struct au_wr_dir_args *args) +{ + int err; + aufs_bindex_t bcpup, bstart, src_bstart; + struct super_block *sb; + struct dentry *parent; + struct au_sbinfo *sbinfo; + const int add_entry = au_ftest_wrdir(args->flags, ADD_ENTRY); + + LKTRTrace("%.*s, src %p, {%d, 0x%x}\n", + AuDLNPair(dentry), src_dentry, args->force_btgt, args->flags); + + sb = dentry->d_sb; + sbinfo = au_sbi(sb); + parent = dget_parent(dentry); + bstart = au_dbstart(dentry); + bcpup = bstart; + if (args->force_btgt < 0) { + if (src_dentry) { + src_bstart = au_dbstart(src_dentry); + if (src_bstart < bstart) + bcpup = src_bstart; + } else if (add_entry) { + err = AuWbrCreate(sbinfo, dentry, + au_ftest_wrdir(args->flags, ISDIR)); + bcpup = err; + } + + if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) { + if (add_entry) + err = AuWbrCopyup(sbinfo, dentry); + else { + di_read_lock_parent(parent, !AuLock_IR); + err = AuWbrCopyup(sbinfo, dentry); + di_read_unlock(parent, !AuLock_IR); + } + bcpup = err; + if (unlikely(err < 0)) + goto out; + } + } else { + bcpup = args->force_btgt; + AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode)); + } + LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup); + if (bstart < bcpup) + au_update_dbrange(dentry, /*do_put_zero*/1); + + err = bcpup; + if (bcpup == bstart) + goto out; /* success */ + + /* copyup the new parent into the branch we process */ + if (add_entry) { + au_update_dbstart(dentry); + IMustLock(parent->d_inode); + DiMustWriteLock(parent); + IiMustWriteLock(parent->d_inode); + } else + di_write_lock_parent(parent); + + err = 0; + if (!au_h_dptr(parent, bcpup)) { + if (bstart < bcpup) + err = au_cpdown_dirs(dentry, bcpup); + else + err = au_cpup_dirs(dentry, bcpup); + } + if (!err && add_entry) { + struct dentry *h_parent; + struct inode *h_dir; + + h_parent = au_h_dptr(parent, bcpup); + AuDebugOn(!h_parent); + h_dir = h_parent->d_inode; + AuDebugOn(!h_dir); + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + err = au_lkup_neg(dentry, bcpup); + mutex_unlock(&h_dir->i_mutex); + if (bstart < bcpup && au_dbstart(dentry) < 0) { + au_set_dbstart(dentry, 0); + au_update_dbrange(dentry, /*do_put_zero*/0); + } + } + + if (!add_entry) + di_write_unlock(parent); + if (!err) + err = bcpup; /* success */ + out: + dput(parent); + LKTRTrace("err %d\n", err); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct dentry *au_do_pinned_h_parent(struct au_pin1 *pin, aufs_bindex_t bindex) +{ + if (pin && pin->parent) + return au_h_dptr(pin->parent, bindex); + return NULL; +} + +void au_do_unpin(struct au_pin1 *p, struct au_pin1 *gp) +{ + LKTRTrace("%p, %p\n", p, gp); + AuDebugOn(!p); + + if (unlikely(!p->h_dir)) + return; + + LKTRTrace("p{%.*s, %d, %d, %d, %d}\n", + AuDLNPair(p->dentry), p->lsc_di, p->lsc_hi, + !!p->parent, !!p->h_dir); + + mutex_unlock(&p->h_dir->i_mutex); + if (unlikely(gp)) + au_do_unpin(gp, NULL); + if (!p->di_locked) + di_read_unlock(p->parent, AuLock_IR); + iput(p->h_dir); + dput(p->parent); + p->parent = NULL; + p->h_dir = NULL; +} + +int au_do_pin(struct au_pin1 *p, struct au_pin1 *gp, const aufs_bindex_t bindex, + const int do_gp) +{ + int err; + struct dentry *h_dentry; + + LKTRTrace("%.*s, %d, b%d, %d\n", + AuDLNPair(p->dentry), !!gp, bindex, do_gp); + AuDebugOn(do_gp && !gp); + /* AuDebugOn(!do_gp && gp); */ + + err = 0; + if (unlikely(IS_ROOT(p->dentry))) + goto out; + + h_dentry = NULL; + if (bindex <= au_dbend(p->dentry)) + h_dentry = au_h_dptr(p->dentry, bindex); + + p->parent = dget_parent(p->dentry); + if (!p->di_locked) + di_read_lock(p->parent, AuLock_IR, p->lsc_di); + else + DiMustAnyLock(p->parent); + AuDebugOn(!p->parent->d_inode); + p->h_dir = au_igrab(au_h_iptr(p->parent->d_inode, bindex)); + /* udba case */ + if (unlikely(p->do_verify && !p->h_dir)) { + err = -EIO; + if (!p->di_locked) + di_read_unlock(p->parent, AuLock_IR); + dput(p->parent); + p->parent = NULL; + goto out; + } + + if (unlikely(do_gp)) { + gp->dentry = p->parent; + err = au_do_pin(gp, NULL, bindex, 0); + if (unlikely(err)) + gp->dentry = NULL; + } + mutex_lock_nested(&p->h_dir->i_mutex, p->lsc_hi); + if (!err) { + /* todo: call d_revalidate() here? */ + if (!h_dentry + || !p->do_verify + || !au_verify_parent(h_dentry, p->h_dir)) + goto out; /* success */ + else { + AuWarn1("bypassed %.*s/%.*s?\n", + AuDLNPair(p->parent), AuDLNPair(p->dentry)); + err = -EIO; + } + } + + AuDbgDentry(p->dentry); + AuDbgDentry(h_dentry); + AuDbgDentry(p->parent); + AuDbgInode(p->h_dir); + if (h_dentry) + AuDbgDentry(h_dentry->d_parent); + + au_do_unpin(p, gp); + if (unlikely(do_gp)) + gp->dentry = NULL; + + out: + AuTraceErr(err); + return err; +} + +void au_pin_init(struct au_pin *args, struct dentry *dentry, int di_locked, + int lsc_di, int lsc_hi, int do_gp) +{ + struct au_pin1 *p; + unsigned char do_verify; + + AuTraceEnter(); + + memset(args, 0, sizeof(*args)); + p = args->pin + AuPin_PARENT; + p->dentry = dentry; + p->di_locked = di_locked; + p->lsc_di = lsc_di; + p->lsc_hi = lsc_hi; + p->do_verify = !au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE); + if (!do_gp) + return; + + do_verify = p->do_verify; + p = au_pin_gp(args); + if (unlikely(p)) { + p->lsc_di = lsc_di + 1; /* child first */ + p->lsc_hi = lsc_hi - 1; /* parent first */ + p->do_verify = do_verify; + } +} + +int au_pin(struct au_pin *args, struct dentry *dentry, aufs_bindex_t bindex, + int di_locked, int do_gp) +{ + LKTRTrace("%.*s, b%d, di_locked %d, do_gp %d\n", + AuDLNPair(dentry), bindex, di_locked, do_gp); + + au_pin_init(args, dentry, di_locked, AuLsc_DI_PARENT, AuLsc_I_PARENT2, + do_gp); + return au_do_pin(args->pin + AuPin_PARENT, au_pin_gp(args), bindex, do_gp); +} + +/* ---------------------------------------------------------------------- */ + +struct au_icpup_args { + aufs_bindex_t btgt; + unsigned char isdir, hinotify, did_cpup; /* flags */ + struct dentry *h_dentry; + struct inode *h_inode; + struct au_pin pin; + struct au_hin_ignore ign[2]; + struct vfsub_args vargs; +}; + +/* todo: refine it */ +static int au_lock_and_icpup(struct dentry *dentry, loff_t sz, + struct au_icpup_args *a) +{ + int err; + aufs_bindex_t bstart; + struct super_block *sb; + struct dentry *hi_wh, *parent; + struct inode *inode; + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = 0 + }; + + LKTRTrace("%.*s, %lld\n", AuDLNPair(dentry), sz); + + di_write_lock_child(dentry); + bstart = au_dbstart(dentry); + sb = dentry->d_sb; + inode = dentry->d_inode; + a->isdir = !!S_ISDIR(inode->i_mode); + if (unlikely(a->isdir)) + au_fset_wrdir(wr_dir_args.flags, ISDIR); + /* plink or hi_wh() */ + if (bstart != au_ibstart(inode)) + wr_dir_args.force_btgt = au_ibstart(inode); + err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); + if (unlikely(err < 0)) + goto out_dentry; + a->btgt = err; + a->did_cpup = (err != bstart); + err = 0; + + /* crazy udba locks */ + a->hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY); + parent = NULL; + if (!IS_ROOT(dentry)) { + parent = dget_parent(dentry); + di_write_lock_parent(parent); + } + err = au_pin(&a->pin, dentry, a->btgt, /*di_locked*/!!parent, + /*dp_gp*/a->hinotify); + if (unlikely(err)) { + if (parent) { + di_write_unlock(parent); + dput(parent); + } + goto out_dentry; + } + a->h_dentry = au_h_dptr(dentry, bstart); + a->h_inode = a->h_dentry->d_inode; + AuDebugOn(!a->h_inode); + mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); + if (!a->did_cpup) { + au_unpin_gp(&a->pin); + if (parent) { + au_pin_set_parent_lflag(&a->pin, /*lflag*/0); + di_downgrade_lock(parent, AuLock_IR); + dput(parent); + } + goto out; /* success */ + } + + hi_wh = NULL; + if (!d_unhashed(dentry)) { + if (parent) { + au_pin_set_parent_lflag(&a->pin, /*lflag*/0); + di_downgrade_lock(parent, AuLock_IR); + dput(parent); + } + err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME); + if (!err) + a->h_dentry = au_h_dptr(dentry, a->btgt); + } else { + hi_wh = au_hi_wh(inode, a->btgt); + if (!hi_wh) { + err = au_sio_cpup_wh(dentry, a->btgt, sz, + /*file*/NULL); + if (!err) + hi_wh = au_hi_wh(inode, a->btgt); + /* todo: revalidate hi_wh? */ + } + if (parent) { + au_pin_set_parent_lflag(&a->pin, /*lflag*/0); + di_downgrade_lock(parent, AuLock_IR); + dput(parent); + } + if (!hi_wh) + a->h_dentry = au_h_dptr(dentry, a->btgt); + else + a->h_dentry = hi_wh; /* do not dget here */ + } + + mutex_unlock(&a->h_inode->i_mutex); + a->h_inode = a->h_dentry->d_inode; + AuDebugOn(!a->h_inode); + if (!err) { + mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); + au_unpin_gp(&a->pin); + goto out; /* success */ + } + + au_unpin(&a->pin); + + out_dentry: + di_write_unlock(dentry); + out: + AuTraceErr(err); + return err; +} + +static int aufs_setattr(struct dentry *dentry, struct iattr *ia) +{ + int err; + struct inode *inode; + struct super_block *sb; + __u32 events; + struct file *file; + loff_t sz; + struct au_icpup_args *a; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + inode = dentry->d_inode; + IMustLock(inode); + + err = -ENOMEM; + a = kzalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + file = NULL; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + vfsub_args_init(&a->vargs, a->ign, au_test_dlgt(au_mntflags(sb)), 0); + + if (ia->ia_valid & ATTR_FILE) { + /* currently ftruncate(2) only */ + file = ia->ia_file; + fi_write_lock(file); + ia->ia_file = au_h_fptr(file, au_fbstart(file)); + } + + sz = -1; + if ((ia->ia_valid & ATTR_SIZE) + && ia->ia_size < i_size_read(inode)) + sz = ia->ia_size; + err = au_lock_and_icpup(dentry, sz, a); + if (unlikely(err < 0)) + goto out_si; + if (a->did_cpup) { + ia->ia_file = NULL; + ia->ia_valid &= ~ATTR_FILE; + } + + if ((ia->ia_valid & ATTR_SIZE) + && ia->ia_size < i_size_read(inode)) { + err = vmtruncate(inode, ia->ia_size); + if (unlikely(err)) + goto out_unlock; + } + + if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) + ia->ia_valid &= ~ATTR_MODE; + + events = 0; + if (unlikely(a->hinotify)) { + events = vfsub_events_notify_change(ia); + if (events) { + if (unlikely(a->isdir)) + vfsub_ign_hinode(&a->vargs, events, + au_hi(inode, a->btgt)); + vfsub_ign_hinode(&a->vargs, events, + au_pinned_hdir(&a->pin, a->btgt)); + } + } + err = vfsub_notify_change(a->h_dentry, ia, &a->vargs); + if (!err) + au_cpup_attr_changeable(inode); + + out_unlock: + mutex_unlock(&a->h_inode->i_mutex); + au_unpin(&a->pin); + di_write_unlock(dentry); + out_si: + if (file) { + fi_write_unlock(file); + ia->ia_file = file; + ia->ia_valid |= ATTR_FILE; + } + si_read_unlock(sb); + kfree(a); + out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int h_readlink(struct dentry *dentry, int bindex, char __user *buf, + int bufsiz) +{ + struct super_block *sb; + struct dentry *h_dentry; + + LKTRTrace("%.*s, b%d, %d\n", AuDLNPair(dentry), bindex, bufsiz); + + h_dentry = au_h_dptr(dentry, bindex); + if (unlikely(/* !h_dentry + || !h_dentry->d_inode + || */ + !h_dentry->d_inode->i_op + || !h_dentry->d_inode->i_op->readlink)) + return -EINVAL; + + sb = dentry->d_sb; + if (!au_test_ro(sb, bindex, dentry->d_inode)) { + touch_atime(au_sbr_mnt(sb, bindex), h_dentry); + au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/ + fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode); + } + return h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz); +} + +static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) +{ + int err; + + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), bufsiz); + + aufs_read_lock(dentry, AuLock_IR); + err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz); + aufs_read_unlock(dentry, AuLock_IR); + AuTraceErr(err); + return err; +} + +static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + int err; + char *buf; + mm_segment_t old_fs; + + LKTRTrace("%.*s, nd %.*s\n", + AuDLNPair(dentry), AuDLNPair(nd->path.dentry)); + + err = -ENOMEM; + buf = __getname(); + if (unlikely(!buf)) + goto out; + + aufs_read_lock(dentry, AuLock_IR); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf, + PATH_MAX); + set_fs(old_fs); + aufs_read_unlock(dentry, AuLock_IR); + + if (err >= 0) { + buf[err] = 0; + /* will be freed by put_link */ + nd_set_link(nd, buf); + return NULL; /* success */ + } + __putname(buf); + + out: + path_put(&nd->path); + AuTraceErr(err); + return ERR_PTR(err); +} + +static void aufs_put_link(struct dentry *dentry, struct nameidata *nd, + void *cookie) +{ + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + __putname(nd_get_link(nd)); +} + +/* ---------------------------------------------------------------------- */ + +static void aufs_truncate_range(struct inode *inode, loff_t start, loff_t end) +{ + AuUnsupport(); +} + +/* ---------------------------------------------------------------------- */ + +struct inode_operations aufs_symlink_iop = { + .permission = aufs_permission, + .setattr = aufs_setattr, +#ifdef CONFIG_AUFS_HIN_OR_FUSE + .getattr = aufs_getattr, +#endif + + .readlink = aufs_readlink, + .follow_link = aufs_follow_link, + .put_link = aufs_put_link +}; + +struct inode_operations aufs_dir_iop = { + .create = aufs_create, + .lookup = aufs_lookup, + .link = aufs_link, + .unlink = aufs_unlink, + .symlink = aufs_symlink, + .mkdir = aufs_mkdir, + .rmdir = aufs_rmdir, + .mknod = aufs_mknod, + .rename = aufs_rename, + + .permission = aufs_permission, + .setattr = aufs_setattr, +#ifdef CONFIG_AUFS_HIN_OR_FUSE + .getattr = aufs_getattr, +#endif + +#if 0 /* reserved for future use */ + .setxattr = aufs_setxattr, + .getxattr = aufs_getxattr, + .listxattr = aufs_listxattr, + .removexattr = aufs_removexattr +#endif +}; + +struct inode_operations aufs_iop = { + .permission = aufs_permission, + .setattr = aufs_setattr, +#ifdef CONFIG_AUFS_HIN_OR_FUSE + .getattr = aufs_getattr, +#endif + +#if 0 /* reserved for future use */ + .setxattr = aufs_setxattr, + .getxattr = aufs_getxattr, + .listxattr = aufs_listxattr, + .removexattr = aufs_removexattr, +#endif + + .truncate_range = aufs_truncate_range +}; --- linux-2.6.27.orig/ubuntu/aufs/cpup.c +++ linux-2.6.27/ubuntu/aufs/cpup.c @@ -0,0 +1,1105 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * copy-up functions, see wbr_policy.c for copy-down + * + * $Id: cpup.c,v 1.17 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include +#include +#include "aufs.h" + +/* todo? violent cpup_attr_*() functions don't care inode lock */ + +void au_cpup_attr_timesizes(struct inode *inode) +{ + struct inode *h_inode; + + LKTRTrace("i%lu\n", inode->i_ino); + /* todo? IMustLock(inode); */ + h_inode = au_h_iptr(inode, au_ibstart(inode)); + AuDebugOn(!h_inode); + /* todo? IMustLock(!h_inode); */ + + fsstack_copy_attr_times(inode, h_inode); + vfsub_copy_inode_size(inode, h_inode); +} + +void au_cpup_attr_nlink(struct inode *inode) +{ + struct inode *h_inode; + + LKTRTrace("i%lu\n", inode->i_ino); + /* todo? IMustLock(inode); */ + AuDebugOn(!inode->i_mode); + + h_inode = au_h_iptr(inode, au_ibstart(inode)); + inode->i_nlink = h_inode->i_nlink; + + /* + * fewer nlink makes find(1) noisy, but larger nlink doesn't. + * it may includes whplink directory. + */ + if (unlikely(S_ISDIR(h_inode->i_mode))) { + aufs_bindex_t bindex, bend; + bend = au_ibend(inode); + for (bindex = au_ibstart(inode) + 1; bindex <= bend; bindex++) { + h_inode = au_h_iptr(inode, bindex); + if (h_inode) + au_add_nlink(inode, h_inode); + } + } +} + +void au_cpup_attr_changeable(struct inode *inode) +{ + struct inode *h_inode; + + LKTRTrace("i%lu\n", inode->i_ino); + /* todo? IMustLock(inode); */ + h_inode = au_h_iptr(inode, au_ibstart(inode)); + AuDebugOn(!h_inode); + + inode->i_mode = h_inode->i_mode; + inode->i_uid = h_inode->i_uid; + inode->i_gid = h_inode->i_gid; + au_cpup_attr_timesizes(inode); + + /* todo: remove this? */ + inode->i_flags = h_inode->i_flags; +} + +void au_cpup_igen(struct inode *inode, struct inode *h_inode) +{ + struct au_iinfo *iinfo = au_ii(inode); + iinfo->ii_higen = h_inode->i_generation; + iinfo->ii_hsb1 = h_inode->i_sb; +} + +void au_cpup_attr_all(struct inode *inode) +{ + struct inode *h_inode; + + LKTRTrace("i%lu\n", inode->i_ino); + /* todo? IMustLock(inode); */ + h_inode = au_h_iptr(inode, au_ibstart(inode)); + AuDebugOn(!h_inode); + + au_cpup_attr_changeable(inode); + if (inode->i_nlink > 0) + au_cpup_attr_nlink(inode); + + switch (inode->i_mode & S_IFMT) { + case S_IFBLK: + case S_IFCHR: + inode->i_rdev = au_h_rdev(h_inode, /*h_mnt*/NULL, + /*h_dentry*/NULL); + } + inode->i_blkbits = h_inode->i_blkbits; + au_cpup_igen(inode, h_inode); +} + +/* ---------------------------------------------------------------------- */ + +/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */ + +/* keep the timestamps of the parent dir when cpup */ +void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, + struct dentry *h_dentry, struct au_hinode *hinode, + struct au_hinode *hdir) +{ + struct inode *h_inode; + + LKTRTrace("%.*s, hdir %d\n", AuDLNPair(dentry), !!hdir); + AuDebugOn(!dentry || !h_dentry || !h_dentry->d_inode); + + dt->dt_dentry = dentry; + dt->dt_h_dentry = h_dentry; + dt->dt_hinode = hinode; + dt->dt_hdir = hdir; + h_inode = h_dentry->d_inode; + dt->dt_atime = h_inode->i_atime; + dt->dt_mtime = h_inode->i_mtime; + /* smp_mb(); */ +} + +void au_dtime_revert(struct au_dtime *dt) +{ + struct iattr attr; + int err; + struct au_hin_ignore ign[2]; + struct vfsub_args vargs; + + LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry)); + + attr.ia_atime = dt->dt_atime; + attr.ia_mtime = dt->dt_mtime; + attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET + | ATTR_ATIME | ATTR_ATIME_SET; + + vfsub_args_init(&vargs, ign, + au_test_dlgt(au_mntflags(dt->dt_dentry->d_sb)), 0); + /* + * IN_ATTRIB should be divided into + * IN_ATTRIB_ATIME, IN_ATTRIB_MTIME ..., + * and define all ORed new IN_ATTRIB macro. + */ + vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hinode); + vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hdir); + err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs); + if (unlikely(err)) + AuWarn("restoring timestamps failed(%d). ignored\n", err); +} + +/* ---------------------------------------------------------------------- */ + +static noinline_for_stack +int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, + struct au_hinode *hdir, struct vfsub_args *vargs) +{ + int err, sbits; + struct dentry *h_dst; + struct iattr ia; + struct inode *h_isrc, *h_idst; + + h_dst = au_h_dptr(dst, bindex); + LKTRTrace("%.*s\n", AuDLNPair(h_dst)); + h_idst = h_dst->d_inode; + /* todo? IMustLock(h_idst); */ + h_isrc = h_src->d_inode; + /* todo? IMustLock(h_isrc); */ + + ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID + | ATTR_ATIME | ATTR_MTIME + | ATTR_ATIME_SET | ATTR_MTIME_SET; + ia.ia_mode = h_isrc->i_mode; + ia.ia_uid = h_isrc->i_uid; + ia.ia_gid = h_isrc->i_gid; + ia.ia_atime = h_isrc->i_atime; + ia.ia_mtime = h_isrc->i_mtime; + sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); + + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_ATTRIB, hdir); + err = vfsub_notify_change(h_dst, &ia, vargs); + + /* is this nfs only? */ + if (!err && sbits && au_test_nfs(h_dst->d_sb)) { + ia.ia_valid = ATTR_FORCE | ATTR_MODE; + ia.ia_mode = h_isrc->i_mode; + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_ATTRIB, hdir); + err = vfsub_notify_change(h_dst, &ia, vargs); + } + + /* todo? remove this? */ + if (!err) + h_idst->i_flags = h_isrc->i_flags; + + AuTraceErr(err); + return err; +} + +/* + * to support a sparse file which is opened with O_APPEND, + * we need to close the file. + */ +static noinline_for_stack +int cpup_regular(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc, + loff_t len, struct au_hinode *hdir, struct vfsub_args *vargs) +{ + int err, i; + struct super_block *sb; + struct inode *h_inode; + enum { SRC, DST }; + struct { + aufs_bindex_t bindex; + unsigned int flags; + struct dentry *dentry; + struct file *file; + void *label, *label_file; + } *h, hidden[] = { + { + .bindex = bsrc, + .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, + .file = NULL, + .label = &&out, + .label_file = &&out_src_file + }, + { + .bindex = bdst, + .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, + .file = NULL, + .label = &&out_src_file, + .label_file = &&out_dst_file + } + }; + + LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n", + AuDLNPair(dentry), bdst, bsrc, len); + AuDebugOn(bsrc <= bdst); + AuDebugOn(!len); + sb = dentry->d_sb; + AuDebugOn(au_test_ro(sb, bdst, dentry->d_inode)); + /* bsrc branch can be ro/rw. */ + + h = hidden; + for (i = 0; i < 2; i++, h++) { + h->dentry = au_h_dptr(dentry, h->bindex); + AuDebugOn(!h->dentry); + h_inode = h->dentry->d_inode; + AuDebugOn(!h_inode || !S_ISREG(h_inode->i_mode)); + h->file = au_h_open(dentry, h->bindex, h->flags, /*file*/NULL); + err = PTR_ERR(h->file); + if (IS_ERR(h->file)) + goto *h->label; + err = -EINVAL; + if (unlikely(!h->file->f_op)) + goto *h->label_file; + } + + /* stop updating while we copyup */ + IMustLock(hidden[SRC].dentry->d_inode); + err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, hdir, sb, + vargs); + + out_dst_file: + fput(hidden[DST].file); + au_sbr_put(sb, hidden[DST].bindex); + out_src_file: + fput(hidden[SRC].file); + au_sbr_put(sb, hidden[SRC].bindex); + out: + AuTraceErr(err); + return err; +} + +static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, + struct au_hinode *hdir, struct dentry *h_dst, + struct vfsub_args *vargs) +{ + int err, rerr; + loff_t l; + + AuTraceEnter(); + + err = 0; + l = i_size_read(au_h_iptr(dentry->d_inode, bsrc)); + if (len == -1 || l < len) + len = l; + if (len) + err = cpup_regular(dentry, bdst, bsrc, len, hdir, vargs); + if (!err) + goto out; /* success */ + + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_DELETE, hdir); + rerr = vfsub_unlink(hdir->hi_inode, h_dst, vargs); + if (rerr) { + AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n", + AuDLNPair(h_dst), err, rerr); + err = -EIO; + } + + out: + AuTraceErr(err); + return err; +} + +static int au_do_cpup_symlink(struct dentry *h_dst, struct dentry *h_src, + struct inode *h_dir, umode_t mode, + struct vfsub_args *vargs) +{ + int err, symlen; + char *sym; + mm_segment_t old_fs; + + AuTraceEnter(); + + err = -ENOMEM; + sym = __getname(); + if (unlikely(!sym)) + goto out; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym, + PATH_MAX); + err = symlen; + set_fs(old_fs); + + if (symlen > 0) { + sym[symlen] = 0; + err = vfsub_symlink(h_dir, h_dst, sym, mode, vargs); + } + __putname(sym); + + out: + AuTraceErr(err); + return err; +} + +/* return with hidden dst inode is locked */ +static noinline_for_stack +int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc, + loff_t len, unsigned int flags, struct dentry *dst_parent, + struct vfsub_args *vargs) +{ + int err; + unsigned char isdir, hinotify; + struct dentry *h_src, *h_dst, *h_parent, *gparent; + struct inode *h_inode, *h_dir; + struct au_dtime dt; + umode_t mode; + struct super_block *sb; + struct au_hinode *hgdir, *hdir; + unsigned int mnt_flags; + const int do_dt = au_ftest_cpup(flags, DTIME); + + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %lld, dtime %u\n", + AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len, + do_dt); + sb = dentry->d_sb; + AuDebugOn(bdst >= bsrc || au_test_ro(sb, bdst, NULL)); + /* bsrc branch can be ro/rw. */ + + h_src = au_h_dptr(dentry, bsrc); + AuDebugOn(!h_src); + h_inode = h_src->d_inode; + AuDebugOn(!h_inode); + AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc)); + + /* stop referencing while we are creating */ + h_dst = au_h_dptr(dentry, bdst); + AuDebugOn(h_dst && h_dst->d_inode); + h_parent = h_dst->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + AuDebugOn(h_parent != h_dst->d_parent); + + hdir = NULL; + mnt_flags = au_mntflags(sb); + hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY); + if (unlikely(hinotify)) { + hdir = au_hi(dst_parent->d_inode, bdst); + AuDebugOn(hdir->hi_inode != h_dir); + } + + if (do_dt) { + hgdir = NULL; + if (unlikely(hinotify && !IS_ROOT(dst_parent))) { + gparent = dget_parent(dst_parent); + hgdir = au_hi(gparent->d_inode, bdst); + IMustLock(hgdir->hi_inode); + dput(gparent); + } + au_dtime_store(&dt, dst_parent, h_parent, hdir, hgdir); + } + + isdir = 0; + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_CREATE, hdir); + mode = h_inode->i_mode; + switch (mode & S_IFMT) { + case S_IFREG: + /* stop updating while we are referencing */ + IMustLock(h_inode); + err = au_h_create(h_dir, h_dst, mode | S_IWUSR, vargs, NULL, + au_nfsmnt(sb, bdst)); + if (!err) + err = au_do_cpup_regular(dentry, bdst, bsrc, len, + hdir, h_dst, vargs); + break; + case S_IFDIR: + isdir = 1; + err = vfsub_mkdir(h_dir, h_dst, mode, vargs); + if (!err) { + /* setattr case: dir is not locked */ + if (0 && au_ibstart(dst_parent->d_inode) == bdst) + au_cpup_attr_nlink(dst_parent->d_inode); + au_cpup_attr_nlink(dentry->d_inode); + } + break; + case S_IFLNK: + err = au_do_cpup_symlink(h_dst, h_src, h_dir, mode, vargs); + break; + case S_IFCHR: + case S_IFBLK: + AuDebugOn(!capable(CAP_MKNOD)); + /*FALLTHROUGH*/ + case S_IFIFO: + case S_IFSOCK: + err = vfsub_mknod(h_dir, h_dst, mode, + au_h_rdev(h_inode, /*h_mnt*/NULL, h_src), + vargs); + break; + default: + AuIOErr("Unknown inode type 0%o\n", mode); + err = -EIO; + } + + if (unlikely(hinotify + && !isdir + && au_opt_test_xino(mnt_flags) + && h_inode->i_nlink == 1 + //&& dentry->d_inode->i_nlink == 1 + && bdst < bsrc + && !au_ftest_cpup(flags, KEEPLINO))) + au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0); + /* ignore this error */ + + if (do_dt) + au_dtime_revert(&dt); + AuTraceErr(err); + return err; +} + +/* + * copyup the @dentry from @bsrc to @bdst. + * the caller must set the both of hidden dentries. + * @len is for truncating when it is -1 copyup the entire file. + */ +static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, unsigned int flags, + struct dentry *dst_parent, struct vfsub_args *vargs) +{ + int err, rerr; + unsigned int mnt_flags; + aufs_bindex_t old_ibstart; + unsigned char isdir, plink, hinotify; + struct au_dtime dt; + struct dentry *h_src, *h_dst, *h_parent, *gparent; + struct inode *dst_inode, *h_dir, *inode; + struct super_block *sb; + struct au_hinode *hgdir, *hdir; + + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %lld, flags 0x%x\n", + AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len, + flags); + sb = dentry->d_sb; + AuDebugOn(bsrc <= bdst); + h_dst = au_h_dptr(dentry, bdst); + AuDebugOn(!h_dst || h_dst->d_inode); + h_parent = h_dst->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + h_src = au_h_dptr(dentry, bsrc); + AuDebugOn(!h_src || !h_src->d_inode); + inode = dentry->d_inode; + IiMustWriteLock(inode); + if (!dst_parent) + dst_parent = dget_parent(dentry); + else + dget(dst_parent); + + mnt_flags = au_mntflags(sb); + plink = !!au_opt_test(mnt_flags, PLINK); + hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY); + hdir = NULL; + if (unlikely(hinotify)) + hdir = au_hi(dst_parent->d_inode, bdst); + dst_inode = au_h_iptr(inode, bdst); + if (unlikely(dst_inode)) { + if (unlikely(!plink)) { + err = -EIO; + AuIOErr("i%lu exists on a upper branch " + "but plink is disabled\n", inode->i_ino); + goto out; + } + + if (dst_inode->i_nlink) { + const int do_dt = au_ftest_cpup(flags, DTIME); + + h_src = au_plink_lkup(sb, bdst, inode); + err = PTR_ERR(h_src); + if (IS_ERR(h_src)) + goto out; + AuDebugOn(!h_src->d_inode); + + if (do_dt) { + hgdir = NULL; + if (unlikely(hinotify && !IS_ROOT(dst_parent))) { + gparent = dget_parent(dst_parent); + hgdir = au_hi(gparent->d_inode, bdst); + IMustLock(hgdir->hi_inode); + dput(gparent); + } + au_dtime_store(&dt, dst_parent, h_parent, hdir, + hgdir); + } + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_CREATE, hdir); + err = vfsub_link(h_src, h_dir, h_dst, vargs); + if (do_dt) + au_dtime_revert(&dt); + dput(h_src); + goto out; + } else + /* todo: cpup_wh_file? */ + /* udba work */ + au_update_brange(inode, 1); + } + + old_ibstart = au_ibstart(inode); + err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent, vargs); + if (unlikely(err)) + goto out; + dst_inode = h_dst->d_inode; + mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2); + + /* todo: test dlgt? */ + err = cpup_iattr(dentry, bdst, h_src, hdir, vargs); +#if 0 /* reserved for future use */ + if (0 && !err) + err = cpup_xattrs(h_src, h_dst); +#endif + isdir = S_ISDIR(dst_inode->i_mode); + if (!err) { + if (bdst < old_ibstart) + au_set_ibstart(inode, bdst); + au_set_h_iptr(inode, bdst, au_igrab(dst_inode), + au_hi_flags(inode, isdir)); + mutex_unlock(&dst_inode->i_mutex); + if (!isdir + && h_src->d_inode->i_nlink > 1 + && plink) + au_plink_append(sb, inode, h_dst, bdst); + goto out; /* success */ + } + + /* revert */ + mutex_unlock(&dst_inode->i_mutex); + hgdir = NULL; + if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY) + && !IS_ROOT(dst_parent))) { + gparent = dget_parent(dst_parent); + hgdir = au_hi(gparent->d_inode, bdst); + dput(gparent); + } + au_dtime_store(&dt, dst_parent, h_parent, hdir, hgdir); + vfsub_args_reinit(vargs); + vfsub_ign_hinode(vargs, IN_DELETE, hdir); + if (!isdir) + rerr = vfsub_unlink(h_dir, h_dst, vargs); + else + rerr = vfsub_rmdir(h_dir, h_dst, vargs); + au_dtime_revert(&dt); + if (rerr) { + AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr); + err = -EIO; + } + + out: + dput(dst_parent); + AuTraceErr(err); + return err; +} + +struct au_cpup_single_args { + int *errp; + struct dentry *dentry; + aufs_bindex_t bdst, bsrc; + loff_t len; + unsigned int flags; + struct dentry *dst_parent; + struct vfsub_args *vargs; +}; + +static void au_call_cpup_single(void *args) +{ + struct au_cpup_single_args *a = args; + *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len, + a->flags, a->dst_parent, a->vargs); +} + +int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, unsigned int flags, + struct dentry *dst_parent) +{ + int err, wkq_err; + struct dentry *h_dentry; + umode_t mode; + struct au_hin_ignore ign; + struct vfsub_args vargs; + + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %lld, flags 0x%x\n", + AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len, + flags); + + vfsub_args_init(&vargs, &ign, au_test_dlgt(au_mntflags(dentry->d_sb)), + /*force_unlink*/0); + h_dentry = au_h_dptr(dentry, bsrc); + mode = h_dentry->d_inode->i_mode & S_IFMT; + if ((mode != S_IFCHR && mode != S_IFBLK) + || capable(CAP_MKNOD)) + err = au_cpup_single(dentry, bdst, bsrc, len, flags, + dst_parent, &vargs); + else { + struct au_cpup_single_args args = { + .errp = &err, + .dentry = dentry, + .bdst = bdst, + .bsrc = bsrc, + .len = len, + .flags = flags, + .dst_parent = dst_parent, + .vargs = &vargs + }; + vfsub_fclr(vargs.flags, DLGT); + wkq_err = au_wkq_wait(au_call_cpup_single, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + } + + AuTraceErr(err); + return err; +} + +/* + * copyup the @dentry from the first active hidden branch to @bdst, + * using au_cpup_single(). + */ +static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + unsigned int flags, struct vfsub_args *vargs) +{ + int err; + struct inode *inode; + aufs_bindex_t bsrc, bend; + + LKTRTrace("%.*s, bdst %d, len %lld, flags 0x%x\n", + AuDLNPair(dentry), bdst, len, flags); + inode = dentry->d_inode; + AuDebugOn(!S_ISDIR(inode->i_mode) && au_dbstart(dentry) < bdst); + + bend = au_dbend(dentry); + for (bsrc = bdst + 1; bsrc <= bend; bsrc++) + if (au_h_dptr(dentry, bsrc)) + break; + AuDebugOn(!au_h_dptr(dentry, bsrc)); + + err = au_lkup_neg(dentry, bdst); + if (!err) { + err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL, + vargs); + if (!err) + return 0; /* success */ + + /* revert */ + au_set_h_dptr(dentry, bdst, NULL); + au_set_dbstart(dentry, bsrc); + } + + AuTraceErr(err); + return err; +} + +struct au_cpup_simple_args { + int *errp; + struct dentry *dentry; + aufs_bindex_t bdst; + loff_t len; + unsigned int flags; + struct vfsub_args *vargs; +}; + +static void au_call_cpup_simple(void *args) +{ + struct au_cpup_simple_args *a = args; + *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags, + a->vargs); +} + +int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + unsigned int flags) +{ + int err, wkq_err; + unsigned char do_sio, dlgt; + struct dentry *parent; + struct inode *h_dir, *dir; + struct au_hin_ignore ign; + struct vfsub_args vargs; + + LKTRTrace("%.*s, b%d, len %lld, flags 0x%x\n", + AuDLNPair(dentry), bdst, len, flags); + + parent = dget_parent(dentry); + dir = parent->d_inode; + h_dir = au_h_iptr(dir, bdst); + dlgt = !!au_test_dlgt(au_mntflags(dir->i_sb)); + do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE, dlgt); + if (!do_sio) { + /* + * testing CAP_MKNOD is for generic fs, + * but CAP_FSETID is for xfs only, currently. + */ + umode_t mode = dentry->d_inode->i_mode; + do_sio = (((mode & (S_IFCHR | S_IFBLK)) + && !capable(CAP_MKNOD)) + || ((mode & (S_ISUID | S_ISGID)) + && !capable(CAP_FSETID))); + } + vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0); + if (!do_sio) + err = au_cpup_simple(dentry, bdst, len, flags, &vargs); + else { + struct au_cpup_simple_args args = { + .errp = &err, + .dentry = dentry, + .bdst = bdst, + .len = len, + .flags = flags, + .vargs = &vargs + }; + vfsub_fclr(vargs.flags, DLGT); + wkq_err = au_wkq_wait(au_call_cpup_simple, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + } + + dput(parent); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *wh_dentry, struct file *file, + loff_t len, struct vfsub_args *vargs) +{ + int err; + struct au_dinfo *dinfo; + aufs_bindex_t bstart; + struct dentry *h_d_bdst, *h_d_bstart; + + AuTraceEnter(); + + dinfo = au_di(dentry); + bstart = dinfo->di_bstart; + h_d_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry; + dinfo->di_bstart = bdst; + dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry; + h_d_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry; + if (file) + dinfo->di_hdentry[0 + bstart].hd_dentry + = au_h_fptr(file, au_fbstart(file))->f_dentry; + err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME, + /*h_parent*/NULL, vargs); + if (!err && file) { + err = au_reopen_nondir(file); + dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_bstart; + } + dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_bdst; + dinfo->di_bstart = bstart; + + AuTraceErr(err); + return err; +} + +/* + * copyup the deleted file for writing. + */ +static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + struct file *file) +{ + int err; + unsigned char dlgt; + struct dentry *parent, *h_parent, *wh_dentry; + struct super_block *sb; + unsigned int mnt_flags; + struct au_dtime dt; + struct au_hin_ignore ign; + struct vfsub_args vargs; + struct au_hinode *hgdir, *hdir; + struct au_ndx ndx = { + .nd = NULL, + .flags = 0, + /* .br = NULL */ + }; + + LKTRTrace("%.*s, bdst %d, len %llu\n", AuDLNPair(dentry), bdst, len); + AuDebugOn(S_ISDIR(dentry->d_inode->i_mode) + || (file && !(file->f_mode & FMODE_WRITE))); + DiMustWriteLock(dentry); + + parent = dget_parent(dentry); + IiMustAnyLock(parent->d_inode); + h_parent = au_h_dptr(parent, bdst); + AuDebugOn(!h_parent); + + sb = parent->d_sb; + mnt_flags = au_mntflags(sb); + dlgt = 0; + ndx.nfsmnt = au_nfsmnt(sb, bdst); + if (unlikely(au_test_dlgt(mnt_flags))) { + dlgt = 1; + au_fset_ndx(ndx.flags, DLGT); + } + wh_dentry = au_whtmp_lkup(h_parent, &dentry->d_name, &ndx); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + hdir = NULL; + hgdir = NULL; + if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY))) { + hdir = au_hi(parent->d_inode, bdst); + if (!IS_ROOT(parent)) { + struct dentry *gparent; + gparent = dget_parent(parent); + hgdir = au_hi(gparent->d_inode, bdst); + dput(gparent); + } + } + au_dtime_store(&dt, parent, h_parent, hdir, hgdir); + vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0); + err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len, &vargs); + if (unlikely(err)) + goto out_wh; + + AuDebugOn(!d_unhashed(dentry)); + /* dget first to force sillyrename on nfs */ + dget(wh_dentry); + vfsub_args_reinit(&vargs); + vfsub_ign_hinode(&vargs, IN_DELETE, hdir); + err = vfsub_unlink(h_parent->d_inode, wh_dentry, &vargs); + if (unlikely(err)) { + AuIOErr("failed remove copied-up tmp file %.*s(%d)\n", + AuDLNPair(wh_dentry), err); + err = -EIO; + } + au_dtime_revert(&dt); + au_set_hi_wh(dentry->d_inode, bdst, wh_dentry); + + out_wh: + dput(wh_dentry); + out: + dput(parent); + AuTraceErr(err); + return err; +} + +struct au_cpup_wh_args { + int *errp; + struct dentry *dentry; + aufs_bindex_t bdst; + loff_t len; + struct file *file; +}; + +static void au_call_cpup_wh(void *args) +{ + struct au_cpup_wh_args *a = args; + *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file); +} + +int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + struct file *file) +{ + int err, wkq_err; + struct dentry *parent, *h_tmp, *h_parent; + struct inode *dir, *h_dir, *h_tmpdir; + struct au_wbr *wbr; + + AuTraceEnter(); + parent = dget_parent(dentry); + dir = parent->d_inode; + IiMustAnyLock(dir); + + h_tmp = NULL; + h_parent = NULL; + h_dir = au_igrab(au_h_iptr(dir, bdst)); + h_tmpdir = h_dir; + if (unlikely(!h_dir->i_nlink)) { + DiMustWriteLock(parent); + wbr = au_sbr(dentry->d_sb, bdst)->br_wbr; + AuDebugOn(!wbr); + h_tmp = wbr->wbr_tmp; + + h_parent = dget(au_h_dptr(parent, bdst)); + au_set_h_dptr(parent, bdst, NULL); + au_set_h_dptr(parent, bdst, dget(h_tmp)); + h_tmpdir = h_tmp->d_inode; + au_set_h_iptr(dir, bdst, NULL, 0); + au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); + mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3); + } + + if (!au_test_h_perm_sio + (h_tmpdir, MAY_EXEC | MAY_WRITE, + au_test_dlgt(au_mntflags(dentry->d_sb)))) + err = au_cpup_wh(dentry, bdst, len, file); + else { + struct au_cpup_wh_args args = { + .errp = &err, + .dentry = dentry, + .bdst = bdst, + .len = len, + .file = file + }; + wkq_err = au_wkq_wait(au_call_cpup_wh, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + } + + /* todo: is this restore safe? */ + if (unlikely(h_tmp)) { + mutex_unlock(&h_tmpdir->i_mutex); + au_set_h_iptr(dir, bdst, NULL, 0); + au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); + au_set_h_dptr(parent, bdst, NULL); + au_set_h_dptr(parent, bdst, h_parent); + } + iput(h_dir); + dput(parent); + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * generic routine for both of copy-up and copy-down. + * Although I've tried building a path by dcsub, I gave up this approach. + * Since the ancestor directory may be moved/renamed during copy. + */ +/* cf. revalidate function in file.c */ +int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, + int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent, void *arg), + void *arg) +{ + int err, hinotify; + struct super_block *sb; + struct dentry *d, *parent, *h_parent, *real_parent; + struct au_pin pin; + + LKTRTrace("%.*s, b%d, parent i%lu\n", + AuDLNPair(dentry), bdst, (unsigned long)parent_ino(dentry)); + sb = dentry->d_sb; + AuDebugOn(au_test_ro(sb, bdst, NULL)); + err = 0; + parent = dget_parent(dentry); + IiMustWriteLock(parent->d_inode); + if (unlikely(IS_ROOT(parent))) + goto out; + + /* do not use au_dpage */ + real_parent = parent; + hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY); + while (1) { + dput(parent); + parent = dget_parent(dentry); + h_parent = au_h_dptr(parent, bdst); + if (h_parent) + goto out; /* success */ + + /* find top dir which is needed to cpup */ + do { + d = parent; + dput(parent); + parent = dget_parent(d); + di_read_lock_parent3(parent, !AuLock_IR); + h_parent = au_h_dptr(parent, bdst); + di_read_unlock(parent, !AuLock_IR); + } while (!h_parent); + + if (d != real_parent) + di_write_lock_child3(d); + + /* somebody else might create while we were sleeping */ + if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) { + if (au_h_dptr(d, bdst)) + au_update_dbstart(d); + + au_pin_init(&pin, d, /*di_locked*/0, + AuLsc_DI_PARENT3, AuLsc_I_PARENT2, hinotify); + err = au_do_pin(pin.pin + AuPin_PARENT, au_pin_gp(&pin), + bdst, hinotify); + if (!err) { + err = cp(d, bdst, h_parent, arg); + au_unpin(&pin); + } + } + + if (d != real_parent) + di_write_unlock(d); + if (unlikely(err)) + break; + } + + out: + dput(parent); + AuTraceErr(err); + return err; +} + +static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent, void *arg) +{ + int err; + + err = au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME); + + AuTraceErr(err); + return err; +} + +int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) +{ + int err; + + err = au_cp_dirs(dentry, bdst, au_cpup_dir, NULL); + + AuTraceErr(err); + return err; +} + +int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) +{ + int err; + struct dentry *parent; + struct inode *dir; + + parent = dget_parent(dentry); + dir = parent->d_inode; + LKTRTrace("%.*s, b%d, parent i%lu\n", + AuDLNPair(dentry), bdst, dir->i_ino); + DiMustReadLock(parent); + IiMustReadLock(dir); + + err = 0; + if (au_h_iptr(dir, bdst)) + goto out; + + di_read_unlock(parent, AuLock_IR); + di_write_lock_parent(parent); + /* someone else might change our inode while we were sleeping */ + if (unlikely(!au_h_iptr(dir, bdst))) + err = au_cpup_dirs(dentry, bdst); + di_downgrade_lock(parent, AuLock_IR); + + out: + dput(parent); + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/export.c +++ linux-2.6.27/ubuntu/aufs/export.c @@ -0,0 +1,797 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * export via nfs + * + * $Id: export.c,v 1.15 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include +#include +#include +#include "aufs.h" + +union conv { +#ifdef CONFIG_AUFS_INO_T_64 + __u32 a[2]; +#else + __u32 a[1]; +#endif + ino_t ino; +}; + +static ino_t decode_ino(__u32 *a) +{ + union conv u; + + BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a)); + u.a[0] = a[0]; +#ifdef CONFIG_AUFS_INO_T_64 + u.a[1] = a[1]; +#endif + return u.ino; +} + +static void encode_ino(__u32 *a, ino_t ino) +{ + union conv u; + + u.ino = ino; + a[0] = u.a[0]; +#ifdef CONFIG_AUFS_INO_T_64 + a[1] = u.a[1]; +#endif +} + +/* NFS file handle */ +enum { + Fh_br_id, + Fh_sigen, +#ifdef CONFIG_AUFS_INO_T_64 + /* support 64bit inode number */ + Fh_ino1, + Fh_ino2, + Fh_dir_ino1, + Fh_dir_ino2, +#else + Fh_ino1, + Fh_dir_ino1, +#endif + Fh_igen, + Fh_h_type, + Fh_tail, + + Fh_ino = Fh_ino1, + Fh_dir_ino = Fh_dir_ino1 +}; + +static int au_test_anon(struct dentry *dentry) +{ + return !!(dentry->d_flags & DCACHE_DISCONNECTED); +} + +/* ---------------------------------------------------------------------- */ +/* inode generation external table */ + +int au_xigen_inc(struct inode *inode) +{ + int err; + loff_t pos; + ssize_t sz; + __u32 igen; + struct super_block *sb; + struct au_sbinfo *sbinfo; + + LKTRTrace("i%lu\n", (unsigned long)inode->i_ino); + + err = 0; + sb = inode->i_sb; + if (unlikely(!au_opt_test_xino(au_mntflags(sb)))) + goto out; + + pos = inode->i_ino; + pos *= sizeof(igen); + igen = inode->i_generation + 1; + sbinfo = au_sbi(sb); + sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, + sizeof(igen), &pos); + if (sz == sizeof(igen)) + goto out; /* success */ + + err = sz; + if (unlikely(sz >= 0)) { + err = -EIO; + AuIOErr("xigen error (%ld)\n", (long)sz); + } + + out: + AuTraceErr(err); + return err; +} + +int au_xigen_new(struct inode *inode) +{ + int err; + loff_t pos; + ssize_t sz; + struct super_block *sb; + struct au_sbinfo *sbinfo; + struct file *file; + + LKTRTrace("i%lu\n", (unsigned long)inode->i_ino); + + err = 0; + sb = inode->i_sb; + if (unlikely(!au_opt_test_xino(au_mntflags(sb)))) + goto out; + + err = -EFBIG; + pos = inode->i_ino; + if (unlikely(Au_LOFF_MAX / sizeof(inode->i_generation) - 1 < pos)) { + AuIOErr1("too large i%lld\n", pos); + goto out; + } + pos *= sizeof(inode->i_generation); + + err = 0; + sbinfo = au_sbi(sb); + file = sbinfo->si_xigen; + /* todo: dirty, at mount time */ + if (unlikely(!file)) { + if (inode->i_ino == AUFS_ROOT_INO) + goto out; + else + BUG(); + } + + if (i_size_read(file->f_dentry->d_inode) + < pos + sizeof(inode->i_generation)) { + spin_lock(&sbinfo->si_xigen_lock); + inode->i_generation = sbinfo->si_xigen_next++; + spin_unlock(&sbinfo->si_xigen_lock); + sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, + sizeof(inode->i_generation), &pos); + } else + sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, + sizeof(inode->i_generation), &pos); + if (sz == sizeof(inode->i_generation)) + goto out; /* success */ + + err = sz; + if (unlikely(sz >= 0)) { + err = -EIO; + AuIOErr("xigen error (%ld)\n", (long)sz); + } + + out: + AuTraceErr(err); + return err; +} + +int au_xigen_set(struct super_block *sb, struct file *base) +{ + int err; + struct au_sbinfo *sbinfo; + struct file *file; + + LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry)); + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + file = au_xino_create2(sb, base, sbinfo->si_xigen); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + err = 0; + if (sbinfo->si_xigen) + fput(sbinfo->si_xigen); + sbinfo->si_xigen = file; + + out: + AuTraceErr(err); + return err; +} + +void au_xigen_clr(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + sbinfo = au_sbi(sb); + if (sbinfo->si_xigen) { + fput(sbinfo->si_xigen); + sbinfo->si_xigen = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino, + ino_t dir_ino) +{ + struct dentry *dentry, *d; + struct inode *inode; + + LKTRTrace("i%lu, diri%lu\n", + (unsigned long)ino, (unsigned long)dir_ino); + + dentry = NULL; + inode = ilookup(sb, ino); + if (unlikely(!inode)) + goto out; + + dentry = ERR_PTR(-ESTALE); + if (unlikely(is_bad_inode(inode) || IS_DEADDIR(inode))) + goto out_iput; + AuDbgInode(inode); + + dentry = NULL; + if (!dir_ino || S_ISDIR(inode->i_mode)) + dentry = d_find_alias(inode); + else { + spin_lock(&dcache_lock); + list_for_each_entry(d, &inode->i_dentry, d_alias) + if (!au_test_anon(d) + && d->d_parent->d_inode->i_ino == dir_ino) { + dentry = dget_locked(d); + break; + } + spin_unlock(&dcache_lock); + } + AuDbgDentry(dentry); + + out_iput: + iput(inode); + out: + AuTraceErrPtr(dentry); + return dentry; +} + +/* ---------------------------------------------------------------------- */ + +/* todo: dirty? */ +/* + * when you mntput() for the return value of this function, + * you have to store it to your local var. + * ie. never mntput si_mntcache directly. + */ +static struct vfsmount *au_do_mnt_get(struct super_block *sb) +{ + struct mnt_namespace *ns; + struct vfsmount *pos, *mnt; + + AuTraceEnter(); + + /* vfsmount_lock is not exported */ + /* no get/put ?? */ + AuDebugOn(!current->nsproxy); + ns = current->nsproxy->mnt_ns; + AuDebugOn(!ns); + mnt = NULL; + /* the order (reverse) will not be a problem */ + list_for_each_entry(pos, &ns->list, mnt_list) + if (pos->mnt_sb == sb) { + mnt = pos; + break; + } + AuDebugOn(!mnt); + + return mntget(mnt); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +static struct vfsmount *au_mnt_get(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + struct vfsmount *mnt; + + sbinfo = au_sbi(sb); + spin_lock(&sbinfo->si_mntcache_lock); + if (sbinfo->si_mntcache) + mnt = mntget(sbinfo->si_mntcache); + else { + sbinfo->si_mntcache = au_do_mnt_get(sb); + mnt = sbinfo->si_mntcache; + } + spin_unlock(&sbinfo->si_mntcache_lock); + return mnt; +} +#else +static struct vfsmount *au_mnt_get(struct super_block *sb) +{ + return au_do_mnt_get(sb); +} +#endif + +struct find_name_by_ino { + int called, found; + ino_t ino; + char *name; + int namelen; +}; + +static int +find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset, + u64 ino, unsigned int d_type) +{ + struct find_name_by_ino *a = arg; + + a->called++; + if (a->ino != ino) + return 0; + + memcpy(a->name, name, namelen); + a->namelen = namelen; + a->found = 1; + return 1; +} + +static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino) +{ + struct dentry *dentry, *parent; + struct file *file; + struct inode *dir, *inode; + struct find_name_by_ino arg; + int err; + + parent = path->dentry; + LKTRTrace("%.*s, i%lu\n", AuDLNPair(parent), (unsigned long )ino); + + path_get(path); + file = dentry_open(parent, path->mnt, au_dir_roflags); + dentry = (void *)file; + if (IS_ERR(file)) + goto out; + + dentry = ERR_PTR(-ENOMEM); + arg.name = __getname(); + if (unlikely(!arg.name)) + goto out_file; + arg.ino = ino; + arg.found = 0; + do { + arg.called = 0; + /* smp_mb(); */ + err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0); + } while (!err && !arg.found && arg.called); + dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_name; + dentry = ERR_PTR(-ENOENT); + if (!arg.found) + goto out_name; + + /* do not call au_lkup_one(), nor dlgt */ + dir = parent->d_inode; + mutex_lock(&dir->i_mutex); + dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen); + mutex_unlock(&dir->i_mutex); + AuTraceErrPtr(dentry); + if (IS_ERR(dentry)) + goto out_name; + AuDebugOn(au_test_anon(dentry)); + inode = dentry->d_inode; + if (unlikely(!inode)) { + dput(dentry); + dentry = ERR_PTR(-ENOENT); + } + + out_name: + __putname(arg.name); + out_file: + fput(file); + out: + AuTraceErrPtr(dentry); + return dentry; +} + +static /* noinline_for_stack */ +struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino, + ino_t dir_ino) +{ + struct dentry *dentry, *parent; + struct path path; + + LKTRTrace("i%lu, diri%lu\n", + (unsigned long)ino, (unsigned long)dir_ino); + + parent = sb->s_root; + if (dir_ino != AUFS_ROOT_INO) { + parent = decode_by_ino(sb, dir_ino, 0); + AuDbgDentry(parent); + dentry = parent; + if (unlikely(!parent)) + goto out; + if (IS_ERR(parent)) + goto out; + AuDebugOn(au_test_anon(parent)); + } else + dget(parent); + + path.dentry = parent; + path.mnt = au_mnt_get(sb); + dentry = au_lkup_by_ino(&path, ino); + path_put(&path); + + out: + AuTraceErrPtr(dentry); + return dentry; +} + +/* ---------------------------------------------------------------------- */ + +static int h_acceptable(void *expv, struct dentry *dentry) +{ + return 1; +} + +static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath, + char *buf, int len, struct super_block *sb) +{ + char *p; + int n; + struct path path; + + AuTraceEnter(); + + p = d_path(h_rootpath, buf, len); + if (IS_ERR(p)) + goto out; + n = strlen(p); + + path.mnt = h_rootpath->mnt; + path.dentry = h_parent; + p = d_path(&path, buf, len); + if (IS_ERR(p)) + goto out; + LKTRTrace("%s\n", p); + if (n != 1) + p += n; + LKTRTrace("%p, %s, %ld\n", + p, p, (long)(p - buf)); + + path.mnt = au_mnt_get(sb); + path.dentry = sb->s_root; + p = d_path(&path, buf, len - strlen(p)); + mntput(path.mnt); + if (IS_ERR(p)) + goto out; + if (n != 1) + p[strlen(p)] = '/'; + LKTRTrace("%s\n", p); + + out: + AuTraceErrPtr(p); + return p; +} + +static noinline_for_stack +struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex, + ino_t ino, __u32 *fh, int fh_len) +{ + struct dentry *dentry, *h_parent, *root; + struct super_block *h_sb; + char *pathname, *p; + struct vfsmount *h_mnt; + struct au_branch *br; + int err; + struct nameidata nd; + + LKTRTrace("b%d\n", bindex); + SiMustAnyLock(sb); + + br = au_sbr(sb, bindex); + /* au_br_get(br); */ + h_mnt = br->br_mnt; + h_sb = h_mnt->mnt_sb; + LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb)); + /* in linux-2.6.24, it takes struct fid * as file handle */ + /* todo: call lower fh_to_dentry()? fh_to_parent()? */ + h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), + fh_len - Fh_tail, fh[Fh_h_type], + h_acceptable, /*context*/NULL); + dentry = h_parent; + if (unlikely(!h_parent || IS_ERR(h_parent))) { + AuWarn1("%s decode_fh failed, %ld\n", + au_sbtype(h_sb), PTR_ERR(h_parent)); + goto out; + } + dentry = NULL; + if (unlikely(au_test_anon(h_parent))) { + AuWarn1("%s decode_fh returned a disconnected dentry\n", + au_sbtype(h_sb)); + goto out_h_parent; + } + + dentry = ERR_PTR(-ENOMEM); + pathname = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!pathname)) + goto out_h_parent; + + root = sb->s_root; + nd.path.mnt = h_mnt; + di_read_lock_parent(root, !AuLock_IR); + nd.path.dentry = au_h_dptr(root, bindex); + di_read_unlock(root, !AuLock_IR); + p = au_build_path(h_parent, &nd.path, pathname, PAGE_SIZE, sb); + dentry = (void *)p; + if (IS_ERR(p)) + goto out_pathname; + + LKTRTrace("%s\n", p); + err = vfsub_path_lookup(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd); + dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_pathname; + + dentry = ERR_PTR(-ENOENT); + AuDebugOn(au_test_anon(nd.path.dentry)); + if (unlikely(!nd.path.dentry->d_inode)) + goto out_nd; + + if (ino != nd.path.dentry->d_inode->i_ino) + dentry = au_lkup_by_ino(&nd.path, ino); + else + dentry = dget(nd.path.dentry); + + out_nd: + path_put(&nd.path); + out_pathname: + free_page((unsigned long)pathname); + out_h_parent: + dput(h_parent); + out: + /* au_br_put(br); */ + AuTraceErrPtr(dentry); + return dentry; +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry * +aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, + int fh_type) +{ + struct dentry *dentry; + struct inode *inode; + __u32 *fh = fid->raw; + ino_t ino, dir_ino; + aufs_bindex_t bindex, br_id; + au_gen_t sigen; + + LKTRTrace("%d, fh{br_id %u, sigen %u, i%u, diri%u, g%u}\n", + fh_type, fh[Fh_br_id], fh[Fh_sigen], fh[Fh_ino], + fh[Fh_dir_ino], fh[Fh_igen]); + AuDebugOn(fh_len < Fh_tail); + + si_read_lock(sb, AuLock_FLUSH); + lockdep_off(); + + /* branch id may be wrapped around */ + dentry = ERR_PTR(-ESTALE); + br_id = fh[Fh_br_id]; + sigen = fh[Fh_sigen]; + bindex = au_br_index(sb, br_id); + LKTRTrace("b%d\n", bindex); + if (unlikely(bindex < 0 + || (0 && sigen != au_sigen(sb)) + || (1 && sigen + AUFS_BRANCH_MAX <= au_sigen(sb)) + )) + goto out; + + /* is this inode still cached? */ + ino = decode_ino(fh + Fh_ino); + AuDebugOn(ino == AUFS_ROOT_INO); + dir_ino = decode_ino(fh + Fh_dir_ino); + dentry = decode_by_ino(sb, ino, dir_ino); + if (IS_ERR(dentry)) + goto out; + if (dentry) + goto accept; + + /* is the parent dir cached? */ + dentry = decode_by_dir_ino(sb, ino, dir_ino); + if (IS_ERR(dentry)) + goto out; + if (dentry) + goto accept; + + /* lookup path */ + dentry = decode_by_path(sb, bindex, ino, fh, fh_len); + if (IS_ERR(dentry)) + goto out; + if (unlikely(!dentry)) + goto out; + + accept: + LKTRLabel(accept); + inode = dentry->d_inode; +#if 0 + /* support branch manupilation and udba on nfs server */ + sigen = au_sigen(sb); + if (unlikely(au_digen(dentry) != sigen + || au_iigen(inode) != sigen)) { + int err; + + //lktr_set_pid(current->pid, LktrArrayPid); + //au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS); + di_write_lock_child(dentry); + err = au_reval_dpath(dentry, sigen); + di_write_unlock(dentry); + //lktr_clear_pid(current->pid, LktrArrayPid); + if (unlikely(err < 0)) + goto out_dput; + } +#endif + + if (unlikely(inode->i_generation != fh[Fh_igen])) { + LKTRLabel(stale); + dput(dentry); + dentry = ERR_PTR(-ESTALE); + } + + out: + LKTRLabel(out); + lockdep_on(); + si_read_unlock(sb); + AuTraceErrPtr(dentry); + return dentry; +} + +#if 0 /* reserved for future use */ +/* support subtreecheck option */ +static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + struct dentry *parent; + __u32 *fh = fid->raw; + ino_t dir_ino; + + dir_ino = decode_ino(fh + Fh_dir_ino); + parent = decode_by_ino(sb, dir_ino, 0); + if (IS_ERR(parent)) + goto out; + if (!parent) + parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]), + dir_ino, fh, fh_len); + + out: + AuTraceErrPtr(parent); + return parent; +} +#endif + +/* ---------------------------------------------------------------------- */ + +static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, + int connectable) +{ + int err; + aufs_bindex_t bindex, bend; + struct super_block *sb, *h_sb; + struct inode *inode; + struct dentry *parent, *h_parent; + struct au_branch *br; + + LKTRTrace("%.*s, max %d, conn %d\n", + AuDLNPair(dentry), *max_len, connectable); + AuDebugOn(au_test_anon(dentry)); + + parent = NULL; + err = -ENOSPC; + if (unlikely(*max_len <= Fh_tail)) { + AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); + goto out; + } + + err = FILEID_ROOT; + inode = dentry->d_inode; + AuDebugOn(!inode); + if (inode->i_ino == AUFS_ROOT_INO) + goto out; + + err = -EIO; + h_parent = NULL; + sb = dentry->d_sb; + parent = dget_parent(dentry); + aufs_read_lock(parent, AuLock_FLUSH | AuLock_IR); +#ifdef CONFIG_AUFS_DEBUG + { + unsigned int mnt_flags = au_mntflags(sb); + + if (unlikely(!au_opt_test_xino(mnt_flags))) + AuWarn1("NFS-exporting requires xino\n"); + if (unlikely(0 && !au_opt_test(mnt_flags, UDBA_INOTIFY))) + AuWarn1("udba=inotify is recommended " + "for NFS-exporting\n"); + } +#endif + + bend = au_dbtaildir(parent); + for (bindex = au_dbstart(parent); bindex <= bend; bindex++) { + h_parent = au_h_dptr(parent, bindex); + if (h_parent) { + dget(h_parent); + break; + } + } + if (unlikely(!h_parent)) + goto out_unlock; + LKTRTrace("b%d\n", bindex); + + err = -EPERM; + br = au_sbr(sb, bindex); + h_sb = br->br_mnt->mnt_sb; + if (unlikely(!h_sb->s_export_op)) { + AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); + goto out_dput; + } + + fh[Fh_br_id] = br->br_id; + fh[Fh_sigen] = au_sigen(sb); + encode_ino(fh + Fh_ino, inode->i_ino); + encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino); + fh[Fh_igen] = inode->i_generation; + + *max_len -= Fh_tail; + /* in linux-2.6.24, it takes struct fid * as file handle */ + fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail), + max_len, connectable); + err = fh[Fh_h_type]; + *max_len += Fh_tail; + /* todo: macros? */ + if (err != 255) + err = 99; + else + AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); + + out_dput: + dput(h_parent); + out_unlock: + aufs_read_unlock(parent, AuLock_IR); + dput(parent); + out: + AuTraceErr(err); + if (unlikely(err < 0)) + err = 255; + return err; +} + +/* ---------------------------------------------------------------------- */ + +static struct export_operations aufs_export_op = { + .fh_to_dentry = aufs_fh_to_dentry, + //.fh_to_parent = aufs_fh_to_parent, + .encode_fh = aufs_encode_fh +}; + +void au_export_init(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + SiMustWriteLock(sb); + + sb->s_export_op = &aufs_export_op; + sbinfo = au_sbi(sb); + sbinfo->si_xigen = NULL; + spin_lock_init(&sbinfo->si_xigen_lock); + /* todo: meaningless? */ + get_random_bytes(&sbinfo->si_xigen_next, sizeof(sbinfo->si_xigen_next)); + memset(&sbinfo->si_xinodir, 0, sizeof(struct path)); +} --- linux-2.6.27.orig/ubuntu/aufs/inode.c +++ linux-2.6.27/ubuntu/aufs/inode.c @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode functions + * + * $Id: inode.c,v 1.13 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include "aufs.h" + +int au_refresh_hinode_self(struct inode *inode) +{ + int err, new_sz, update; + struct inode *first; + struct au_hinode *p, *q, tmp; + struct super_block *sb; + struct au_iinfo *iinfo; + aufs_bindex_t bindex, bend, new_bindex; + + LKTRTrace("i%lu\n", inode->i_ino); + IiMustWriteLock(inode); + + err = -ENOMEM; + update = 0; + sb = inode->i_sb; + bend = au_sbend(sb); + new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1); + iinfo = au_ii(inode); + p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1), + new_sz, GFP_NOFS); + if (unlikely(!p)) + goto out; + + iinfo->ii_hinode = p; + p = iinfo->ii_hinode + iinfo->ii_bstart; + first = p->hi_inode; + err = 0; + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; + bindex++, p++) { + if (!p->hi_inode) + continue; + + new_bindex = au_br_index(sb, p->hi_id); + if (new_bindex == bindex) + continue; + if (new_bindex < 0) { + update++; + au_hiput(p); + p->hi_inode = NULL; + continue; + } + + if (new_bindex < iinfo->ii_bstart) + iinfo->ii_bstart = new_bindex; + if (iinfo->ii_bend < new_bindex) + iinfo->ii_bend = new_bindex; + /* swap two hidden inode, and loop again */ + q = iinfo->ii_hinode + new_bindex; + tmp = *q; + *q = *p; + *p = tmp; + if (tmp.hi_inode) { + bindex--; + p--; + } + } + au_update_brange(inode, /*do_put_zero*/0); + + if (unlikely(err)) + goto out; + + if (1 || first != au_h_iptr(inode, iinfo->ii_bstart)) + au_cpup_attr_all(inode); + if (update && S_ISDIR(inode->i_mode)) + inode->i_version++; + au_update_iigen(inode); + + out: + AuTraceErr(err); + return err; +} + +int au_refresh_hinode(struct inode *inode, struct dentry *dentry) +{ + int err, update; + struct inode *first; + struct au_hinode *p; + struct super_block *sb; + struct au_iinfo *iinfo; + aufs_bindex_t bindex, bend; + unsigned char isdir; + unsigned int flags; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + IiMustWriteLock(inode); + + err = au_refresh_hinode_self(inode); + if (unlikely(err)) + goto out; + + sb = dentry->d_sb; + bend = au_sbend(sb); + iinfo = au_ii(inode); + update = 0; + p = iinfo->ii_hinode + iinfo->ii_bstart; + first = p->hi_inode; + isdir = S_ISDIR(inode->i_mode); + flags = au_hi_flags(inode, isdir); + bend = au_dbend(dentry); + for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) { + struct inode *hi; + struct dentry *hd; + + hd = au_h_dptr(dentry, bindex); + if (!hd || !hd->d_inode) + continue; + + if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) { + hi = au_h_iptr(inode, bindex); + if (hi) { + if (hi == hd->d_inode) + continue; + err = -ESTALE; + break; + } + } + if (bindex < iinfo->ii_bstart) + iinfo->ii_bstart = bindex; + if (iinfo->ii_bend < bindex) + iinfo->ii_bend = bindex; + au_set_h_iptr(inode, bindex, au_igrab(hd->d_inode), flags); + update++; + } + au_update_brange(inode, /*do_put_zero*/0); + + if (unlikely(err)) + goto out; + + if (1 || first != au_h_iptr(inode, iinfo->ii_bstart)) + au_cpup_attr_all(inode); + if (update && isdir) + inode->i_version++; + au_update_iigen(inode); + + out: + AuTraceErr(err); + return err; +} + +static int set_inode(struct inode *inode, struct dentry *dentry) +{ + int err; + struct dentry *h_dentry; + struct inode *h_inode; + umode_t mode; + aufs_bindex_t bindex, bstart, btail; + unsigned char isdir; + struct au_iinfo *iinfo; + unsigned int flags; + + LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry)); + AuDebugOn(!(inode->i_state & I_NEW)); + IiMustWriteLock(inode); + bstart = au_dbstart(dentry); + h_dentry = au_h_dptr(dentry, bstart); + AuDebugOn(!h_dentry); + h_inode = h_dentry->d_inode; + AuDebugOn(!h_inode); + + err = 0; + isdir = 0; + mode = h_inode->i_mode; + switch (mode & S_IFMT) { + case S_IFREG: + btail = au_dbtail(dentry); + inode->i_op = &aufs_iop; + inode->i_fop = &aufs_file_fop; + inode->i_mapping->a_ops = &aufs_aop; + break; + case S_IFDIR: + isdir = 1; + btail = au_dbtaildir(dentry); + inode->i_op = &aufs_dir_iop; + inode->i_fop = &aufs_dir_fop; + break; + case S_IFLNK: + btail = au_dbtail(dentry); + inode->i_op = &aufs_symlink_iop; + /* inode->i_fop = &aufs_file_fop; */ + break; + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + case S_IFSOCK: + btail = au_dbtail(dentry); + init_special_inode(inode, mode, + au_h_rdev(h_inode, /*h_mnt*/NULL, h_dentry)); + break; + default: + AuIOErr("Unknown file type 0%o\n", mode); + err = -EIO; + goto out; + } + + /* do not set inotify for whiteouted dirs (SHWH mode) */ + flags = au_hi_flags(inode, isdir); + if (unlikely(au_opt_test(au_mntflags(dentry->d_sb), SHWH) + && au_ftest_hi(flags, NOTIFY) + && dentry->d_name.len > AUFS_WH_PFX_LEN + && !memcmp(dentry->d_name.name, AUFS_WH_PFX, + AUFS_WH_PFX_LEN))) + au_fclr_hi(flags, NOTIFY); + iinfo = au_ii(inode); + iinfo->ii_bstart = bstart; + iinfo->ii_bend = btail; + for (bindex = bstart; bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + AuDebugOn(!h_dentry->d_inode); + au_set_h_iptr(inode, bindex, au_igrab(h_dentry->d_inode), + flags); + } + au_cpup_attr_all(inode); + + out: + AuTraceErr(err); + return err; +} + +/* successful returns with iinfo write_locked */ +/* todo: return with unlocked? */ +static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched) +{ + int err; + struct inode *h_inode, *h_dinode; + aufs_bindex_t bindex, bend; + + LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry)); + + *matched = 0; + + /* + * before this function, if aufs got any iinfo lock, it must be only + * one, the parent dir. + * it can happen by UDBA and the obsoleted inode number. + */ + err = -EIO; + if (unlikely(inode->i_ino == parent_ino(dentry))) + goto out; + /* todo: test here */ + //AuDebugOn(IS_DEADDIR(inode)); + + err = 0; + h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode; + /* mutex_lock_nested(&inode->i_mutex, AuLsc_I_CHILD); */ + ii_write_lock_new_child(inode); + bend = au_ibend(inode); + for (bindex = au_ibstart(inode); bindex <= bend; bindex++) { + h_inode = au_h_iptr(inode, bindex); + if (h_inode && h_inode == h_dinode) { + /* && (ibs != bstart + || !au_test_higen(inode, h_inode))); */ + *matched = 1; + err = 0; + if (unlikely(au_iigen(inode) != au_digen(dentry))) + err = au_refresh_hinode(inode, dentry); + break; + } + } + if (unlikely(err)) + ii_write_unlock(inode); + /* mutex_unlock(&inode->i_mutex); */ + + out: + AuTraceErr(err); + return err; +} + +/* successful returns with iinfo write_locked */ +/* todo: return with unlocked? */ +struct inode *au_new_inode(struct dentry *dentry) +{ + struct inode *inode, *h_inode; + struct dentry *h_dentry; + ino_t h_ino; + struct super_block *sb; + int err, match; + aufs_bindex_t bstart; + struct au_xino_entry xinoe; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + sb = dentry->d_sb; + bstart = au_dbstart(dentry); + h_dentry = au_h_dptr(dentry, bstart); + AuDebugOn(!h_dentry); + h_inode = h_dentry->d_inode; + AuDebugOn(!h_inode); + + h_ino = h_inode->i_ino; + err = au_xino_read(sb, bstart, h_ino, &xinoe); + inode = ERR_PTR(err); + if (unlikely(err)) + goto out; + new_ino: + if (!xinoe.ino) { + xinoe.ino = au_xino_new_ino(sb); + if (!xinoe.ino) { + inode = ERR_PTR(-EIO); + goto out; + } + } + + LKTRTrace("i%lu\n", (unsigned long)xinoe.ino); + inode = au_iget_locked(sb, xinoe.ino); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out; + /* todo: test here */ + //AuDebugOn(IS_DEADDIR(inode)); + + LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); + if (inode->i_state & I_NEW) { + ii_write_lock_new_child(inode); + err = set_inode(inode, dentry); + unlock_new_inode(inode); + if (!err) + goto out; /* success */ + iget_failed(inode); + ii_write_unlock(inode); + goto out_iput; + } else { + AuDebugOn(inode->i_state & I_LOCK); + err = reval_inode(inode, dentry, &match); + if (!err) + goto out; /* success */ + else if (match) + goto out_iput; + } + + if (unlikely(au_test_unique_ino(h_dentry, h_ino))) + AuWarn1("Un-notified UDBA or repeatedly renamed dir," + " b%d, %s, %.*s, hi%lu, i%lu.\n", + bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry), + (unsigned long)h_ino, (unsigned long)xinoe.ino); + xinoe.ino = 0; + err = au_xino_write0(sb, bstart, h_ino, 0); + if (!err) { + iput(inode); + goto new_ino; + } + /* force noxino? */ + + out_iput: + iput(inode); + inode = ERR_PTR(err); + out: + AuTraceErrPtr(inode); + return inode; +} + +/* ---------------------------------------------------------------------- */ + +int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, + struct inode *inode) +{ + int err; + + err = au_br_rdonly(au_sbr(sb, bindex)); + + /* pseudo-link after flushed may out of bounds */ + if (!err + && inode + && au_ibstart(inode) <= bindex + && bindex <= au_ibend(inode)) { + /* + * permission check is unnecessary since vfsub routine + * will be called later + */ + struct inode *hi = au_h_iptr(inode, bindex); + if (hi) + err = IS_IMMUTABLE(hi) ? -EROFS : 0; + } + + AuTraceErr(err); + return err; +} + +int au_test_h_perm(struct inode *h_inode, int mask, int dlgt) +{ + if (!current->fsuid) + return 0; + /* todo: fake nameidata? */ + return vfsub_permission(h_inode, mask, NULL, dlgt); +} + +int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt) +{ + if (unlikely(au_test_nfs(h_inode->i_sb) + && (mask & MAY_WRITE) + && S_ISDIR(h_inode->i_mode))) + mask |= MAY_READ; /* force permission check */ + return au_test_h_perm(h_inode, mask, dlgt); +} --- linux-2.6.27.orig/ubuntu/aufs/dcsub.h +++ linux-2.6.27/ubuntu/aufs/dcsub.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for dentry cache + * + * $Id: dcsub.h,v 1.4 2008/07/21 02:54:22 sfjro Exp $ + */ + +#ifndef __AUFS_DCSUB_H__ +#define __AUFS_DCSUB_H__ + +#ifdef __KERNEL__ + +#include + +struct au_dpage { + int ndentry; + struct dentry **dentries; +}; + +struct au_dcsub_pages { + int ndpage; + struct au_dpage *dpages; +}; + +/* ---------------------------------------------------------------------- */ + +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp); +void au_dpages_free(struct au_dcsub_pages *dpages); +typedef int (*au_dpages_test)(struct dentry *dentry, void *arg); +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, + au_dpages_test test, void *arg); +int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, + int do_include, au_dpages_test test, void *arg); +struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DCSUB_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/hin_or_dlgt.c +++ linux-2.6.27/ubuntu/aufs/hin_or_dlgt.c @@ -0,0 +1,737 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for vfs in hinotify or dlgt mode + * + * $Id: hin_or_dlgt.c,v 1.6 2008/07/14 00:15:10 sfjro Exp $ + */ + +#include +#include "aufs.h" + +#if !defined(CONFIG_AUFS_HINOTIFY) && !defined(CONFIG_AUFS_DLGT) +#error mis-configuraion or Makefile +#endif + +/* ---------------------------------------------------------------------- */ + +struct permission_args { + int *errp; + struct inode *inode; + int mask; + struct nameidata *nd; +}; + +static void call_permission(void *args) +{ + struct permission_args *a = args; + *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd); +} + +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd, + int dlgt) +{ + if (!dlgt) + return do_vfsub_permission(inode, mask, nd); + else { + int err, wkq_err; + struct permission_args args = { + .errp = &err, + .inode = inode, + .mask = mask, + .nd = nd + }; + wkq_err = au_wkq_wait(call_permission, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + return err; + } +} + +/* ---------------------------------------------------------------------- */ + +struct create_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + int mode; + struct nameidata *nd; + struct vfsub_args *vargs; +}; + +static void call_create(void *args) +{ + struct create_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd); + if (unlikely(*a->errp)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd, struct vfsub_args *vargs) +{ + int err; + struct create_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .mode = mode, + .nd = nd, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_create(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_create, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +struct symlink_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + const char *symname; + int mode; + struct vfsub_args *vargs; +}; + +static void call_symlink(void *args) +{ + struct symlink_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode); + if (unlikely(*a->errp)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname, + int mode, struct vfsub_args *vargs) +{ + int err; + struct symlink_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .symname = symname, + .mode = mode, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_symlink(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_symlink, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +struct mknod_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + int mode; + dev_t dev; + struct vfsub_args *vargs; +}; + +static void call_mknod(void *args) +{ + struct mknod_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev); + if (unlikely(*a->errp)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev, + struct vfsub_args *vargs) +{ + int err; + struct mknod_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .mode = mode, + .dev = dev, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_mknod(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_mknod, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +struct mkdir_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + int mode; + struct vfsub_args *vargs; +}; + +static void call_mkdir(void *args) +{ + struct mkdir_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode); + if (unlikely(*a->errp)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, + struct vfsub_args *vargs) +{ + int err; + struct mkdir_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .mode = mode, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_mkdir(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_mkdir, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct link_args { + int *errp; + struct inode *dir; + struct dentry *src_dentry, *dentry; + struct vfsub_args *vargs; +}; + +static void call_link(void *args) +{ + struct link_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry); + if (unlikely(*a->errp)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +int vfsub_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry, struct vfsub_args *vargs) +{ + int err; + struct link_args args = { + .errp = &err, + .src_dentry = src_dentry, + .dir = dir, + .dentry = dentry, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_link(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_link, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +struct rename_args { + int *errp; + struct inode *src_dir, *dir; + struct dentry *src_dentry, *dentry; + struct vfsub_args *vargs; +}; + +static void call_rename(void *args) +{ + struct rename_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir, + a->dentry); + if (unlikely(*a->errp)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs) +{ + int err; + struct rename_args args = { + .errp = &err, + .src_dir = src_dir, + .src_dentry = src_dentry, + .dir = dir, + .dentry = dentry, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_rename(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_rename, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +struct rmdir_args { + int *errp; + struct inode *dir; + struct dentry *dentry; + struct vfsub_args *vargs; +}; + +static void call_rmdir(void *args) +{ + struct rmdir_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_rmdir(a->dir, a->dentry); + if (unlikely(*a->errp)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs) +{ + int err; + struct rmdir_args args = { + .errp = &err, + .dir = dir, + .dentry = dentry, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_rmdir(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_rmdir, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct read_args { + ssize_t *errp; + struct file *file; + union { + void *kbuf; + char __user *ubuf; + }; + size_t count; + loff_t *ppos; +}; + +static void call_read_k(void *args) +{ + struct read_args *a = args; + LKTRTrace("%.*s, cnt %lu, pos %lld\n", + AuDLNPair(a->file->f_dentry), (unsigned long)a->count, + *a->ppos); + *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos); +} + +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, + loff_t *ppos, int dlgt) +{ + if (!dlgt) + return do_vfsub_read_u(file, ubuf, count, ppos); + else { + int wkq_err; + ssize_t err, read; + struct read_args args = { + .errp = &err, + .file = file, + .count = count, + .ppos = ppos + }; + + if (unlikely(!count)) + return 0; + + /* + * workaround an application bug. + * generally, read(2) or write(2) may return the value shorter + * than requested. But many applications don't support it, + * for example bash. + */ + err = -ENOMEM; + if (args.count > PAGE_SIZE) + args.count = PAGE_SIZE; + args.kbuf = kmalloc(args.count, GFP_NOFS); + if (unlikely(!args.kbuf)) + goto out; + + read = 0; + do { + wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + if (unlikely(err > 0 + && copy_to_user(ubuf, args.kbuf, err))) { + err = -EFAULT; + goto out_free; + } else if (!err) + break; + else if (unlikely(err < 0)) + goto out_free; + count -= err; + /* do not read too much because of file i/o pointer */ + if (count < args.count) + args.count = count; + ubuf += err; + read += err; + } while (count); + smp_mb(); /* flush ubuf */ + err = read; + + out_free: + kfree(args.kbuf); + out: + return err; + } +} + +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos, + int dlgt) +{ + if (!dlgt) + return do_vfsub_read_k(file, kbuf, count, ppos); + else { + ssize_t err; + int wkq_err; + struct read_args args = { + .errp = &err, + .file = file, + .count = count, + .ppos = ppos + }; + args.kbuf = kbuf; + wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + return err; + } +} + +struct write_args { + ssize_t *errp; + struct file *file; + union { + void *kbuf; + const char __user *ubuf; + }; + size_t count; + loff_t *ppos; + struct vfsub_args *vargs; +}; + +static void call_write_k(void *args) +{ + struct write_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos); + if (unlikely(*a->errp <= 0)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos, struct vfsub_args *vargs) +{ + ssize_t err; + + if (!vfsub_ftest(vargs->flags, DLGT)) { + vfsub_ignore(vargs); + err = do_vfsub_write_u(file, ubuf, count, ppos); + if (unlikely(err <= 0)) + vfsub_unignore(vargs); + au_dbg_hin_list(vargs); + } else { + ssize_t written; + int wkq_err; + struct write_args args = { + .errp = &err, + .file = file, + .count = count, + .ppos = ppos, + .vargs = vargs + }; + + if (unlikely(!count)) + return 0; + + /* + * workaround an application bug. + * generally, read(2) or write(2) may return the value shorter + * than requested. But many applications don't support it, + * for example bash. + */ + err = -ENOMEM; + if (args.count > PAGE_SIZE) + args.count = PAGE_SIZE; + args.kbuf = kmalloc(args.count, GFP_NOFS); + if (unlikely(!args.kbuf)) + goto out; + + written = 0; + do { + if (unlikely(copy_from_user(args.kbuf, ubuf, + args.count))) { + err = -EFAULT; + goto out_free; + } + + wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + if (err > 0) { + count -= err; + if (count < args.count) + args.count = count; + ubuf += err; + written += err; + } else if (!err) + break; + else if (unlikely(err < 0)) + goto out_free; + } while (count); + err = written; + + out_free: + kfree(args.kbuf); + } + out: + return err; +} + +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos, + struct vfsub_args *vargs) +{ + ssize_t err; + struct write_args args = { + .errp = &err, + .file = file, + .count = count, + .ppos = ppos, + .vargs = vargs + }; + + args.kbuf = kbuf; + if (!vfsub_ftest(vargs->flags, DLGT)) + call_write_k(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +struct readdir_args { + int *errp; + struct file *file; + filldir_t filldir; + void *arg; +}; + +static void call_readdir(void *args) +{ + struct readdir_args *a = args; + *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg); +} + +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt) +{ + if (!dlgt) + return do_vfsub_readdir(file, filldir, arg); + else { + int err, wkq_err; + struct readdir_args args = { + .errp = &err, + .file = file, + .filldir = filldir, + .arg = arg + }; + wkq_err = au_wkq_wait(call_readdir, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + return err; + } +} + +/* ---------------------------------------------------------------------- */ + +struct splice_to_args { + long *errp; + struct file *in; + loff_t *ppos; + struct pipe_inode_info *pipe; + size_t len; + unsigned int flags; +}; + +static void call_splice_to(void *args) +{ + struct splice_to_args *a = args; + *a->errp = do_vfsub_splice_to(a->in, a->ppos, a->pipe, a->len, + a->flags); +} + +long vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags, int dlgt) +{ + if (!dlgt) + return do_vfsub_splice_to(in, ppos, pipe, len, flags); + else { + long err; + int wkq_err; + struct splice_to_args args = { + .errp = &err, + .in = in, + .ppos = ppos, + .pipe = pipe, + .len = len, + .flags = flags + }; + wkq_err = au_wkq_wait(call_splice_to, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + return err; + } +} + +struct splice_from_args { + long *errp; + struct pipe_inode_info *pipe; + struct file *out; + loff_t *ppos; + size_t len; + unsigned int flags; + struct vfsub_args *vargs; +}; + +static void call_splice_from(void *args) +{ + struct splice_from_args *a = args; + vfsub_ignore(a->vargs); + *a->errp = do_vfsub_splice_from(a->pipe, a->out, a->ppos, a->len, + a->flags); + if (unlikely(*a->errp < 0)) + vfsub_unignore(a->vargs); + au_dbg_hin_list(a->vargs); +} + +long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags, + struct vfsub_args *vargs) +{ + long err; + struct splice_from_args args = { + .errp = &err, + .pipe = pipe, + .out = out, + .ppos = ppos, + .len = len, + .flags = flags, + .vargs = vargs + }; + + if (!vfsub_ftest(vargs->flags, DLGT)) + call_splice_from(&args); + else { + int wkq_err; + wkq_err = au_wkq_wait(call_splice_from, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + } + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct getattr_args { + int *errp; + struct vfsmount *mnt; + struct dentry *dentry; + struct kstat *st; +}; + +static void call_getattr(void *args) +{ + struct getattr_args *a = args; + *a->errp = do_vfsub_getattr(a->mnt, a->dentry, a->st); +} + +int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st, + int dlgt) +{ + if (!dlgt) + return do_vfsub_getattr(mnt, dentry, st); + else { + int err, wkq_err; + struct getattr_args args = { + .errp = &err, + .mnt = mnt, + .dentry = dentry, + .st = st + }; + wkq_err = au_wkq_wait(call_getattr, &args, /*dlgt*/1); + if (unlikely(wkq_err)) + err = wkq_err; + return err; + } +} --- linux-2.6.27.orig/ubuntu/aufs/wkq.h +++ linux-2.6.27/ubuntu/aufs/wkq.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * workqueue for asynchronous/super-io/delegated operations + * + * $Id: wkq.h,v 1.7 2008/09/15 03:16:36 sfjro Exp $ + */ + +#ifndef __AUFS_WKQ_H__ +#define __AUFS_WKQ_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +/* ---------------------------------------------------------------------- */ + +/* internal workqueue named AUFS_WKQ_NAME */ +struct au_wkq { + struct workqueue_struct *q; + + /* balancing */ + atomic_t busy; + + /* accounting */ +#ifdef CONFIG_AUFS_STAT + unsigned int max_busy; +#endif +}; + +/* + * in the next operation, wait for the 'nowait' tasks in system-wide workqueue + */ +struct au_nowait_tasks { + atomic_t nw_len; + wait_queue_head_t nw_wq; +}; + +/* ---------------------------------------------------------------------- */ + +extern struct au_wkq *au_wkq; +typedef void (*au_wkq_func_t)(void *args); + +/* wkq flags */ +#define AuWkq_WAIT 1 +#define AuWkq_DLGT (1 << 1) +#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name) +#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; } +#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef AuWkq_DLGT +#define AuWkq_DLGT 0 +#endif + +int au_wkq_run(au_wkq_func_t func, void *args, struct super_block *sb, + unsigned int flags); +int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, + int dlgt); +int __init au_wkq_init(void); +void au_wkq_fin(void); + +/* ---------------------------------------------------------------------- */ + +static inline int au_test_wkq(struct task_struct *tsk) +{ + return (!tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME)); +#if 0 /* reserved for future use, per-cpu workqueue */ + return (!tsk->mm + && !memcmp(tsk->comm, AUFS_WKQ_NAME "/", + sizeof(AUFS_WKQ_NAME))); +#endif +} + +static inline int au_wkq_wait(au_wkq_func_t func, void *args, int dlgt) +{ + unsigned int flags = AuWkq_WAIT; + if (unlikely(dlgt)) + au_fset_wkq(flags, DLGT); + return au_wkq_run(func, args, /*sb*/NULL, flags); +} + +static inline void au_wkq_max_busy_init(struct au_wkq *wkq) +{ +#ifdef CONFIG_AUFS_STAT + wkq->max_busy = 0; +#endif +} + +/* todo: memory barrier? */ +static inline void au_nwt_init(struct au_nowait_tasks *nwt) +{ + atomic_set(&nwt->nw_len, 0); + smp_mb(); /* atomic_set */ + init_waitqueue_head(&nwt->nw_wq); +} + +/* todo: make it void */ +static inline int au_nwt_done(struct au_nowait_tasks *nwt) +{ + int ret; + + AuTraceEnter(); + + ret = atomic_dec_return(&nwt->nw_len); + if (!ret) + wake_up_all(&nwt->nw_wq); + return ret; +} + +static inline int au_nwt_flush(struct au_nowait_tasks *nwt) +{ + wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len)); + return 0; +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_WKQ_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/finfo.c +++ linux-2.6.27/ubuntu/aufs/finfo.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * file private data + * + * $Id: finfo.c,v 1.4 2008/06/30 03:50:21 sfjro Exp $ + */ + +#include "aufs.h" + +struct au_finfo *au_fi(struct file *file) +{ + struct au_finfo *finfo = file->private_data; + AuDebugOn(!finfo + || !finfo->fi_hfile + || (0 < finfo->fi_bend + && (/* au_sbi(file->f_dentry->d_sb)->si_bend + < finfo->fi_bend + || */ finfo->fi_bend < finfo->fi_bstart))); + return finfo; +} + +struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex) +{ + struct au_finfo *finfo = au_fi(file); + struct au_hfile *hf; + + FiMustAnyLock(file); + AuDebugOn(!finfo + || finfo->fi_bstart < 0 + || bindex < finfo->fi_bstart + || finfo->fi_bend < bindex); + hf = finfo->fi_hfile + bindex; + AuDebugOn(hf->hf_br && au_br_count(hf->hf_br) <= 0); + return hf->hf_br; +} + +struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex) +{ + struct au_finfo *finfo = au_fi(file); + struct au_hfile *hf; + + FiMustAnyLock(file); + AuDebugOn(!finfo + || finfo->fi_bstart < 0 + || bindex < finfo->fi_bstart + || finfo->fi_bend < bindex); + hf = finfo->fi_hfile + bindex; + AuDebugOn(hf->hf_file + && file_count(hf->hf_file) <= 0 + && au_br_count(hf->hf_br) <= 0); + return hf->hf_file; +} + +void au_hfput(struct au_hfile *hf) +{ + if (hf->hf_file->f_mode & FMODE_EXEC) + au_allow_write_access(hf->hf_file); + fput(hf->hf_file); + hf->hf_file = NULL; + AuDebugOn(!hf->hf_br); + au_br_put(hf->hf_br); + hf->hf_br = NULL; +} + +void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) +{ + struct au_finfo *finfo = au_fi(file); + struct au_hfile *hf; + + FiMustWriteLock(file); + AuDebugOn(!finfo + || finfo->fi_bstart < 0 + || bindex < finfo->fi_bstart + || finfo->fi_bend < bindex); + AuDebugOn(val && file_count(val) <= 0); + hf = finfo->fi_hfile + bindex; + AuDebugOn(val && hf->hf_file); + if (hf->hf_file) + au_hfput(hf); + if (val) { + hf->hf_file = val; + hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex); + } +} + +void au_finfo_fin(struct file *file) +{ + struct au_finfo *finfo; + struct dentry *dentry; + aufs_bindex_t bindex, bend; + + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + SiMustAnyLock(dentry->d_sb); + + fi_write_lock(file); + bend = au_fbend(file); + bindex = au_fbstart(file); + if (bindex >= 0) + for (; bindex <= bend; bindex++) + au_set_h_fptr(file, bindex, NULL); + + finfo = au_fi(file); +#ifdef CONFIG_AUFS_DEBUG + if (finfo->fi_bstart >= 0) { + bend = au_fbend(file); + for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) { + struct au_hfile *hf; + hf = finfo->fi_hfile + bindex; + AuDebugOn(hf->hf_file || hf->hf_br); + } + } +#endif + + kfree(finfo->fi_hfile); + fi_write_unlock(file); + au_cache_free_finfo(finfo); +} + +int au_finfo_init(struct file *file) +{ + struct au_finfo *finfo; + struct dentry *dentry; + union { + void *p; + unsigned long ul; + } u; + + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + AuDebugOn(!dentry->d_inode); + + finfo = au_cache_alloc_finfo(); + if (finfo) { + finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1, + sizeof(*finfo->fi_hfile), GFP_NOFS); + if (finfo->fi_hfile) { + au_rw_init_wlock(&finfo->fi_rwsem); + finfo->fi_bstart = -1; + finfo->fi_bend = -1; + atomic_set(&finfo->fi_generation, au_digen(dentry)); + /* smp_mb(); */ /* atomic_set */ + + /* + * a dirty trick for handling FMODE_EXEC and + * deny_write_access(). + * because FMODE_EXEC flag is not passed to + * f_op->open(), + * aufs set it to file->private_data temporary in lookup + * or dentry revalidation operations. + * restore the flag to f_mode here. + */ + u.p = file->private_data; + if (u.ul & FMODE_EXEC) { + file->f_mode |= FMODE_EXEC; + smp_mb(); /* flush f_mode */ + } + + file->private_data = finfo; + return 0; /* success */ + } + au_cache_free_finfo(finfo); + } + + AuTraceErr(-ENOMEM); + return -ENOMEM; +} --- linux-2.6.27.orig/ubuntu/aufs/cpup.h +++ linux-2.6.27/ubuntu/aufs/cpup.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * copy-up/down functions + * + * $Id: cpup.h,v 1.5 2008/09/01 02:54:48 sfjro Exp $ + */ + +#ifndef __AUFS_CPUP_H__ +#define __AUFS_CPUP_H__ + +#ifdef __KERNEL__ + +#include +#include + +void au_cpup_attr_timesizes(struct inode *inode); +void au_cpup_attr_nlink(struct inode *inode); +void au_cpup_attr_changeable(struct inode *inode); +void au_cpup_igen(struct inode *inode, struct inode *h_inode); +void au_cpup_attr_all(struct inode *inode); + +/* ---------------------------------------------------------------------- */ + +/* cpup flags */ +#define AuCpup_DTIME 1 /* do dtime_store/revert */ +#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, + for link(2) */ +#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) +#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; } +#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; } + +int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, unsigned int flags, + struct dentry *dst_parent); +int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + unsigned int flags); +int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + struct file *file); + +int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, + int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent, void *arg), + void *arg); +int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); +int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); + +/* ---------------------------------------------------------------------- */ + +/* keep timestamps when copyup */ +struct au_dtime { + struct dentry *dt_dentry, *dt_h_dentry; + struct au_hinode *dt_hinode, *dt_hdir; + struct timespec dt_atime, dt_mtime; +}; +void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, + struct dentry *h_dentry, struct au_hinode *hinode, + struct au_hinode *hdir); +void au_dtime_revert(struct au_dtime *dt); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_CPUP_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/i_op_ren.c +++ linux-2.6.27/ubuntu/aufs/i_op_ren.c @@ -0,0 +1,1211 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operation (rename entry) + * todo: this is crazy monster + * + * $Id: i_op_ren.c,v 1.14 2008/09/22 03:52:12 sfjro Exp $ + */ + +#include "aufs.h" + +enum { SRC, DST }; + +#define AuRen_ISDIR 1 +#define AuRen_ISSAMEDIR (1 << 1) +#define AuRen_WHSRC (1 << 2) +#define AuRen_WHDST (1 << 3) +#define AuRen_DLGT (1 << 4) +#define AuRen_VFSLOCK (1 << 5) +#define AuRen_PINNED (1 << 6) +#define au_ftest_ren(flags, name) ((flags) & AuRen_##name) +#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; } +#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef AuRen_DLGT +#define AuRen_DLGT 0 +#endif + +struct au_ren_args { + /* original args */ + struct dentry *src_dentry, *dentry; + struct inode *src_dir, *dir; + + struct dentry *h_dentry[2], *h_parent[2], *h_trap, *h_locked[2]; + /* todo: remove them */ + struct dentry *parent[2], *gparent[2]; + struct au_pin pin[2]; + struct au_nhash whlist; + aufs_bindex_t btgt, bstart[2]; + /* do_rename() only */ + unsigned char need_diropq, bycpup; + struct super_block *sb; + unsigned int flags; + unsigned int mnt_flags; + struct au_ndx ndx; + + /* do_rename() only */ +#ifdef CONFIG_AUFS_BR_NFS + struct au_hin_ignore ign[3]; +#else + struct au_hin_ignore ign[2]; +#endif + struct vfsub_args vargs; + struct au_whtmp_rmdir_args *thargs; + struct dentry *wh_dentry[2], *h_dst, *h_src; +}; + +/* ---------------------------------------------------------------------- */ + +#define RevertFailure(fmt, args...) do { \ + AuIOErrWhck("revert failure: " fmt " (%d, %d)\n", \ + ##args, err, rerr); \ + err = -EIO; \ + } while (0) + +static noinline_for_stack +void au_ren_rev_diropq(int err, struct au_ren_args *a) +{ + int rerr; + struct mutex *h_mtx; + + /* lock inode simply since inotify is not set to h_inode. */ + h_mtx = &au_h_dptr(a->src_dentry, a->btgt)->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + rerr = au_diropq_remove(a->src_dentry, a->btgt, + au_ftest_ren(a->flags, DLGT)); + mutex_unlock(h_mtx); + if (rerr) + RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry)); +} + +static noinline_for_stack +void au_ren_rev_rename(int err, struct au_ren_args *a) +{ + int rerr; + struct dentry *h_d; + struct qstr *name = &a->src_dentry->d_name; + + h_d = au_lkup_one(name->name, a->h_parent[SRC], name->len, &a->ndx); + rerr = PTR_ERR(h_d); + if (IS_ERR(h_d)) { + RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry)); + return; + } + + AuDebugOn(h_d->d_inode); + vfsub_args_reinit(&a->vargs); + vfsub_ign_hinode(&a->vargs, IN_MOVED_FROM, au_pinned_hdir(a->pin + DST, + a->btgt)); + vfsub_ign_hinode(&a->vargs, IN_MOVED_TO, au_pinned_hdir(a->pin + SRC, + a->btgt)); + rerr = vfsub_rename(au_pinned_h_dir(a->pin + DST), + au_h_dptr(a->src_dentry, a->btgt), + au_pinned_h_dir(a->pin + SRC), h_d, &a->vargs); + d_drop(h_d); + dput(h_d); + /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */ + if (rerr) + RevertFailure("rename %.*s", AuDLNPair(a->src_dentry)); +} + +static noinline_for_stack +void au_ren_rev_cpup(int err, struct au_ren_args *a) +{ + int rerr; + + vfsub_args_reinit(&a->vargs); + vfsub_ign_hinode(&a->vargs, IN_DELETE, au_pinned_hdir(a->pin + DST, + a->btgt)); + rerr = vfsub_unlink(au_pinned_h_dir(a->pin + DST), a->h_dentry[DST], + &a->vargs); + au_set_h_dptr(a->src_dentry, a->btgt, NULL); + au_set_dbstart(a->src_dentry, a->bstart[SRC]); + if (rerr) + RevertFailure("unlink %.*s", AuDLNPair(a->h_dentry[DST])); +} + +static noinline_for_stack +void au_ren_rev_whtmp(int err, struct au_ren_args *a) +{ + int rerr; + struct dentry *h_d; + struct mutex *h_mtx; + struct qstr *name = &a->dentry->d_name; + + h_d = au_lkup_one(name->name, a->h_parent[DST], name->len, &a->ndx); + rerr = PTR_ERR(h_d); + if (IS_ERR(h_d)) { + RevertFailure("lookup %.*s", AuLNPair(name)); + return; + } + if (h_d->d_inode) { + d_drop(h_d); + dput(h_d); + return; + } + + h_mtx = &a->h_dst->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + au_hin_resume(au_hi(a->src_dentry->d_inode, a->btgt)); + mutex_unlock(h_mtx); + vfsub_args_reinit(&a->vargs); + vfsub_ign_hinode(&a->vargs, IN_MOVED_TO | IN_MOVED_FROM, + au_pinned_hdir(a->pin + DST, a->btgt)); + rerr = vfsub_rename(au_pinned_h_dir(a->pin + DST), a->h_dst, + au_pinned_h_dir(a->pin + DST), h_d, &a->vargs); + d_drop(h_d); + dput(h_d); + if (!rerr) { + au_set_h_dptr(a->dentry, a->btgt, NULL); + au_set_h_dptr(a->dentry, a->btgt, dget(a->h_dst)); + } else + RevertFailure("rename %.*s", AuDLNPair(a->h_dst)); +} + +static noinline_for_stack +void au_ren_rev_whsrc(int err, struct au_ren_args *a) +{ + int rerr; + + rerr = au_wh_unlink_dentry(au_pinned_hdir(a->pin + SRC, a->btgt), + a->wh_dentry[SRC], a->src_dentry, /*dlgt*/0); + if (rerr) + RevertFailure("unlink %.*s", AuDLNPair(a->wh_dentry[SRC])); +} +#undef RevertFailure + +/* ---------------------------------------------------------------------- */ + +static /* noinline_for_stack */ +int au_ren_or_cpup(struct au_ren_args *a) +{ + int err; + + AuTraceEnter(); + + if (au_dbstart(a->src_dentry) == a->btgt) { + if (a->need_diropq && au_dbdiropq(a->src_dentry) == a->btgt) + a->need_diropq = 0; + vfsub_ign_hinode(&a->vargs, IN_MOVED_FROM, + au_pinned_hdir(a->pin + SRC, a->btgt)); + vfsub_ign_hinode(&a->vargs, IN_MOVED_TO, + au_pinned_hdir(a->pin + DST, a->btgt)); + /* nfs_rename() calls d_delete() */ + if (au_test_nfs(au_pinned_h_dir(a->pin + DST)->i_sb) + && a->h_dentry[DST]->d_inode + && (S_ISDIR(a->h_dentry[DST]->d_inode->i_mode) + || atomic_read(&a->h_dentry[DST]->d_count) <= 2)) + vfsub_ign_hinode(&a->vargs, IN_DELETE, + au_pinned_hdir(a->pin + DST, a->btgt)); + AuDebugOn(au_dbstart(a->src_dentry) != a->btgt); + err = vfsub_rename(au_pinned_h_dir(a->pin + SRC), + au_h_dptr(a->src_dentry, a->btgt), + au_pinned_h_dir(a->pin + DST), + a->h_dentry[DST], &a->vargs); + } else { + struct mutex *h_mtx = &a->h_dentry[SRC]->d_inode->i_mutex; + + a->bycpup = 1; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + au_set_dbstart(a->src_dentry, a->btgt); + au_set_h_dptr(a->src_dentry, a->btgt, dget(a->h_dentry[DST])); + err = au_sio_cpup_single(a->src_dentry, a->btgt, a->bstart[SRC], + -1, !AuCpup_DTIME, a->parent[DST]); + if (unlikely(err)) { + au_set_h_dptr(a->src_dentry, a->btgt, NULL); + au_set_dbstart(a->src_dentry, a->bstart[SRC]); + } + mutex_unlock(h_mtx); + } + + return err; +} + +static /* noinline_for_stack */ +int au_ren_del_whtmp(struct au_ren_args *a) +{ + int err; + + AuTraceEnter(); + + if (au_test_nfs(a->h_dst->d_sb) + || !au_nhash_test_longer_wh(&a->whlist, a->btgt, + au_sbi(a->sb)->si_dirwh)) { + err = au_whtmp_rmdir(a->dir, a->btgt, a->h_dst, &a->whlist); + if (unlikely(err)) + AuWarn("failed removing whtmp dir %.*s (%d), " + "ignored.\n", AuDLNPair(a->h_dst), err); + } else { + au_whtmp_kick_rmdir(a->dir, a->btgt, a->h_dst, &a->whlist, + a->thargs); + dput(a->h_dst); + a->thargs = NULL; + } + + return 0; +} + +static /* noinline_for_stack */ +int au_ren_diropq(struct au_ren_args *a) +{ + int err; + struct dentry *diropq; + struct mutex *h_mtx; + + AuTraceEnter(); + + err = 0; + h_mtx = &au_h_dptr(a->src_dentry, a->btgt)->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + diropq = au_diropq_create(a->src_dentry, a->btgt, + au_ftest_ren(a->flags, DLGT)); + mutex_unlock(h_mtx); + if (IS_ERR(diropq)) + err = PTR_ERR(diropq); + dput(diropq); + + return err; +} + +static /* noinline_for_stack */ +int do_rename(struct au_ren_args *a) +{ + int err; + aufs_bindex_t bindex, bend; + struct dentry *h_d; + + LKTRTrace("%.*s/%.*s, %.*s/%.*s, " + "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, " + "flags 0x%x\n", + AuDLNPair(a->parent[SRC]), AuDLNPair(a->src_dentry), + AuDLNPair(a->parent[DST]), AuDLNPair(a->dentry), + a->h_dentry[SRC], a->h_dentry[DST], + a->h_parent[SRC], a->h_parent[DST], + &a->whlist, a->btgt, + a->bstart[SRC], a->bstart[DST], + a->flags); + + /* prepare workqueue args */ + if (au_ftest_ren(a->flags, ISDIR) && a->h_dentry[DST]->d_inode) { + err = -ENOMEM; + a->thargs = kmalloc(sizeof(*a->thargs), GFP_NOFS); + if (unlikely(!a->thargs)) + goto out; + a->h_dst = dget(a->h_dentry[DST]); + } + + a->ndx.nfsmnt = au_nfsmnt(a->sb, a->btgt); + if (unlikely(au_ftest_ren(a->flags, DLGT))) + au_fset_ndx(a->ndx.flags, DLGT); + + /* create whiteout for src_dentry */ + if (au_ftest_ren(a->flags, WHSRC)) { + a->wh_dentry[SRC] = au_wh_create(a->src_dentry, a->btgt, + a->h_parent[SRC], &a->ndx); + err = PTR_ERR(a->wh_dentry[SRC]); + if (IS_ERR(a->wh_dentry[SRC])) + goto out_thargs; + } + + /* lookup whiteout for dentry */ + if (au_ftest_ren(a->flags, WHDST)) { + h_d = au_wh_lkup(a->h_parent[DST], &a->dentry->d_name, &a->ndx); + err = PTR_ERR(h_d); + if (IS_ERR(h_d)) + goto out_whsrc; + if (!h_d->d_inode) + dput(h_d); + else + a->wh_dentry[DST] = h_d; + } + + /* rename dentry to tmpwh */ + if (a->thargs) { + struct au_hinode *hinode; + + AuDbgDentry(a->h_dentry[DST]); + err = au_whtmp_ren(a->dir, a->btgt, a->h_dentry[DST]); + if (unlikely(err)) + goto out_whdst; + AuDbgDentry(a->h_dentry[DST]); + hinode = au_hi(a->dentry->d_inode, a->btgt); + /* todo: bad approach? */ + mutex_lock_nested(&hinode->hi_inode->i_mutex, AuLsc_I_CHILD); + au_hin_suspend(hinode); + mutex_unlock(&hinode->hi_inode->i_mutex); + au_set_h_dptr(a->dentry, a->btgt, NULL); + AuDbgDentry(a->h_dentry[DST]); + err = au_lkup_neg(a->dentry, a->btgt); + if (unlikely(err)) + goto out_whtmp; + a->h_dentry[DST] = au_h_dptr(a->dentry, a->btgt); + } + + /* cpup src */ + if (a->h_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) { + struct mutex *h_mtx = &a->h_dentry[SRC]->d_inode->i_mutex; + + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1, + !AuCpup_DTIME); + mutex_unlock(h_mtx); + if (unlikely(err)) + goto out_whtmp; + } + + /* rename by vfs_rename or cpup */ + a->need_diropq = au_ftest_ren(a->flags, ISDIR) + && (a->wh_dentry[DST] + || au_dbdiropq(a->dentry) == a->btgt + /* hide the lower to keep xino */ + || a->btgt < au_dbend(a->dentry) + || au_opt_test(a->mnt_flags, ALWAYS_DIROPQ)); + a->bycpup = 0; + vfsub_args_init(&a->vargs, a->ign, au_ftest_ren(a->flags, DLGT), 0); + err = au_ren_or_cpup(a); + if (unlikely(err)) + goto out_whtmp; + + /* make dir opaque */ + if (a->need_diropq) { + err = au_ren_diropq(a); + if (unlikely(err)) + goto out_rename; + } + + /* update target timestamps */ + AuDebugOn(au_dbstart(a->src_dentry) != a->btgt); + a->h_src = au_h_dptr(a->src_dentry, a->btgt); + au_update_fuse_h_inode(NULL, a->h_src); /*ignore*/ + /* fsstack_copy_attr_atime(a->src_dentry->d_inode, a->h_src->d_inode); */ + a->src_dentry->d_inode->i_ctime = a->h_src->d_inode->i_ctime; + + /* remove whiteout for dentry */ + if (a->wh_dentry[DST]) { + err = au_wh_unlink_dentry(au_pinned_hdir(a->pin + DST, a->btgt), + a->wh_dentry[DST], a->dentry, + /*dlgt*/0); + if (unlikely(err)) + goto out_diropq; + } + + /* remove whtmp */ + if (a->thargs) + /* ignore this error */ + au_ren_del_whtmp(a); + + err = 0; + goto out_success; + + out_diropq: + if (a->need_diropq) + au_ren_rev_diropq(err, a); + out_rename: + if (!a->bycpup) + au_ren_rev_rename(err, a); + else + au_ren_rev_cpup(err, a); + out_whtmp: + if (a->thargs) + au_ren_rev_whtmp(err, a); + out_whdst: + dput(a->wh_dentry[DST]); + a->wh_dentry[DST] = NULL; + out_whsrc: + if (a->wh_dentry[SRC]) + au_ren_rev_whsrc(err, a); + d_drop(a->src_dentry); + bend = au_dbend(a->src_dentry); + for (bindex = au_dbstart(a->src_dentry); bindex <= bend; bindex++) { + h_d = au_h_dptr(a->src_dentry, bindex); + if (h_d) + d_drop(h_d); + } + d_drop(a->dentry); + bend = au_dbend(a->dentry); + for (bindex = au_dbstart(a->dentry); bindex <= bend; bindex++) { + h_d = au_h_dptr(a->dentry, bindex); + if (h_d) + d_drop(h_d); + } + au_update_dbstart(a->dentry); + if (a->thargs) + d_drop(a->h_dst); + out_success: + dput(a->wh_dentry[SRC]); + dput(a->wh_dentry[DST]); + out_thargs: + if (a->thargs) { + dput(a->h_dst); + kfree(a->thargs); + } + out: + AuTraceErr(err); + return err; +} + +/* + * test if @dentry dir can be rename destination or not. + * success means, it is a logically empty dir. + */ +static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt, + struct au_nhash *whlist) +{ + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + return au_test_empty(dentry, whlist); +} + +/* + * test if @dentry dir can be rename source or not. + * if it can, return 0 and @children is filled. + * success means, + * - or, it is a logically empty dir. + * - or, it exists on writable branch and has no children including whiteouts + * on the lower branch. + */ +static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt) +{ + int err; + aufs_bindex_t bstart; + + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + bstart = au_dbstart(dentry); + if (bstart != btgt) { + struct au_nhash *whlist; + + whlist = au_nhash_new(GFP_NOFS); + err = PTR_ERR(whlist); + if (IS_ERR(whlist)) + goto out; + err = au_test_empty(dentry, whlist); + au_nhash_del(whlist); + goto out; + } + + if (bstart == au_dbtaildir(dentry)) + return 0; /* success */ + + err = au_test_empty_lower(dentry); + + out: + if (/* unlikely */(err == -ENOTEMPTY)) { + AuWarn1("renaming dir who has child(ren) on multiple branches," + " is not supported\n"); + err = -EXDEV; + } + AuTraceErr(err); + return err; +} + +/* mainly for link(2) and rename(2) */ +int au_wbr(struct dentry *dentry, aufs_bindex_t btgt) +{ + aufs_bindex_t bdiropq, bwh; + struct dentry *parent; + + LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), btgt); + parent = dentry->d_parent; + IMustLock(parent->d_inode); /* dir is locked */ + + bdiropq = au_dbdiropq(parent); + bwh = au_dbwh(dentry); + if (au_br_rdonly(au_sbr(dentry->d_sb, btgt)) + || (0 <= bdiropq && bdiropq < btgt) + || (0 <= bwh && bwh < btgt)) + btgt = -1; + + LKTRTrace("btgt %d\n", btgt); + return btgt; +} + +/* + * simple tests for rename. + * following the checks in vfs, plus the parent-child relationship. + */ +static int au_may_ren(struct au_ren_args *a) +{ + int err; + struct inode *h_inode; + + AuTraceEnter(); + + if (a->bstart[SRC] == a->btgt) { + err = au_may_del(a->src_dentry, a->btgt, a->h_parent[SRC], + au_ftest_ren(a->flags, ISDIR), &a->ndx); + if (unlikely(err)) + goto out; + err = -EINVAL; + if (unlikely(a->h_dentry[SRC] == a->h_trap)) + goto out; + } + + err = 0; + if (a->bstart[DST] != a->btgt) + goto out; + + err = -EIO; + h_inode = a->h_dentry[DST]->d_inode; + if (!a->dentry->d_inode) { + if (unlikely(h_inode)) + goto out; + err = au_may_add(a->dentry, a->btgt, a->h_parent[DST], + au_ftest_ren(a->flags, ISDIR), &a->ndx); + } else { + if (unlikely(!h_inode || !h_inode->i_nlink)) + goto out; + err = au_may_del(a->dentry, a->btgt, a->h_parent[DST], + au_ftest_ren(a->flags, ISDIR), &a->ndx); + if (unlikely(err)) + goto out; + err = -ENOTEMPTY; + if (unlikely(a->h_dentry[DST] == a->h_trap)) + goto out; + err = 0; + } + + out: + if (unlikely(err == -ENOENT || err == -EEXIST)) + err = -EIO; + AuTraceErr(err); + return err; +} + +/* + * locking order + * (VFS) + * - src_dir and dir by lock_rename() + * - inode if exitsts + * (aufs) + * - lock all + * + src_dentry and dentry by aufs_read_and_write_lock2() which calls, + * + si_read_lock + * + di_write_lock2_child() + * + di_write_lock_child() + * + ii_write_lock_child() + * + di_write_lock_child2() + * + ii_write_lock_child2() + * + src_parent and parent + * + di_write_lock_parent() + * + ii_write_lock_parent() + * + di_write_lock_parent2() + * + ii_write_lock_parent2() + * + if udab=inotify is specified, lock grand parents (crazy) + * + di_read_lock_gparent() + * + ii_read_lock_gparent() + * + di_read_lock_gparent2() + * + ii_read_lock_gparent2() + * + mutex_lock_gparent() + * + mutex_lock_gparent2() + * + lower src_dir and dir by vfsub_lock_rename()? + * + verify the every relations between child, parent and grand parent. if any + * of them failed, unlock all and return -EBUSY. + */ +static void au_ren_pin_init(struct au_pin *first, struct dentry *d1, + struct au_pin *next, struct dentry *d2) +{ + AuTraceEnter(); + + /* AuLsc_DI_PARENT3 is for higher gparent initially */ + au_pin_init(first, d1, /*di_locked*/1, AuLsc_DI_PARENT2, + AuLsc_I_PARENT2, /*do_gp*/1); + /* AuLsc_DI_PARENT4 is for lower gparent initially */ + au_pin_init(next, d2, /*di_locked*/1, AuLsc_DI_PARENT3, + AuLsc_I_PARENT4, /*do_gp*/1); +} + +static void au_ren_fake_pin(struct au_ren_args *a) +{ + int i; + struct au_pin1 *p; + struct inode *h_i; + + AuTraceEnter(); + + /* they increment the ref counter */ + for (i = 0; i < 2; i++) { + p = a->pin[i].pin + AuPin_PARENT; + au_pin_set_parent(a->pin + i, a->parent[i]); + dput(a->parent[i]); + h_i = a->h_parent[i]->d_inode; + au_pin_set_h_dir(a->pin + i, h_i); + iput(h_i); + + if (!a->gparent[i]) { + au_pin_set_gparent(a->pin + i, NULL); + au_pin_set_h_gdir(a->pin + i, NULL); + } else { + au_pin_set_gparent(a->pin + i, a->gparent[i]); + dput(a->gparent[i]); + h_i = au_h_iptr(a->gparent[i]->d_inode, a->btgt); + au_pin_set_h_gdir(a->pin + i, h_i); + iput(h_i); + } + } +} + +/* crazy */ +/* cf. i_op.c: au_do_pin() */ +static int au_ren_pin4(int higher, int lower, struct au_ren_args *a) +{ + int err, i, lsc; + struct au_pin *p; + struct au_pin1 *p4[4]; + struct inode *h_dir; + + LKTRTrace("%d, %d\n", higher, lower); + + p = a->pin + higher; + p4[0] = au_pin_gp(p); /* highest */ + p4[1] = p->pin + AuPin_PARENT; + p = a->pin + lower; + p4[2] = au_pin_gp(p); + p4[3] = p->pin + AuPin_PARENT; + + if (a->gparent[higher]) { + au_pin_do_set_parent(p4[0], a->gparent[higher]); + au_pin_do_set_dentry(p4[0], a->parent[higher]); + } + au_pin_do_set_parent(p4[1], a->parent[higher]); + if (a->gparent[lower]) { + au_pin_do_set_parent(p4[2], a->gparent[lower]); + au_pin_do_set_dentry(p4[2], a->parent[lower]); + } + au_pin_do_set_parent(p4[3], a->parent[lower]); + + DiMustWriteLock(p4[3]->parent); + di_write_unlock(p4[1]->parent); + if (p4[2]->parent) + di_read_lock_parent2(p4[2]->parent, AuLock_IR); + di_write_lock_parent3(p4[1]->parent); + if (p4[0]->parent) + di_read_lock_parent4(p4[0]->parent, AuLock_IR); + + lsc = AuLsc_I_PARENT; + for (i = 0; i < 4; i++, lsc++) { + if (p4[i]->parent) { + h_dir = au_h_iptr(p4[i]->parent->d_inode, a->btgt); + au_pin_do_set_h_dir(p4[i], h_dir); + mutex_lock_nested(&h_dir->i_mutex, lsc); + } + } + + err = 0; + AuTraceErr(err); + return err; +} + +static struct dentry *au_ren_pin3(int higher, int lower, struct au_ren_args *a) +{ + struct dentry *h_trap; + struct au_pin *p; + int err; + + LKTRTrace("%d, %d\n", higher, lower); + + p = a->pin + higher; + err = au_do_pin(p->pin + AuPin_PARENT, au_pin_gp(p), a->btgt, + /*do_gp*/1); + h_trap = ERR_PTR(err); + if (unlikely(err)) + goto out; + p = a->pin + lower; + err = au_do_pin(p->pin + AuPin_PARENT, NULL, a->btgt, /*do_gp*/0); + h_trap = ERR_PTR(err); + if (unlikely(err)) { + au_do_unpin(p->pin + AuPin_PARENT, au_pin_gp(p)); + goto out; + } + h_trap = au_pinned_h_parent(p, a->btgt); + + out: + AuTraceErrPtr(h_trap); + return h_trap; +} + +static struct dentry *au_ren_pin(struct au_ren_args *a) +{ + struct dentry *h_trap; + struct inode *h_gdir; + int err, i, same_gp; + + AuTraceEnter(); + AuDebugOn(!au_opt_test(a->mnt_flags, UDBA_INOTIFY)); + + vfsub_lock_rename_mutex(a->h_dentry[SRC]->d_sb); + au_fset_ren(a->flags, VFSLOCK); + + /* gdir is not locked */ + same_gp = 0; + if (!IS_ROOT(a->parent[SRC])) + a->gparent[SRC] = dget_parent(a->parent[SRC]); + if (!IS_ROOT(a->parent[DST])) { + a->gparent[DST] = dget_parent(a->parent[DST]); + same_gp = (a->gparent[SRC] == a->gparent[DST]); + } + + /* + * patterns + * - gparent[SRC] is parent[DST] + * - parent[SRC] is gparent[DST] + * - gparent[SRC] is gparent[DST] + * - gparent[SRC] is a descendant of parent[DST] + * - parent[SRC] is an ancestor of gparent[DST] + * - not within grand parent range + */ + err = 0; + h_trap = ERR_PTR(-EBUSY); + if (a->gparent[SRC] == a->parent[DST]) { + LKTRLabel(here); + au_ren_pin_init(a->pin + DST, a->dentry, a->pin + SRC, + a->src_dentry); + h_trap = au_ren_pin3(DST, SRC, a); + if (!IS_ERR(h_trap)) { + h_gdir = au_pinned_h_dir(a->pin + DST); + err = au_verify_parent(a->h_parent[SRC], h_gdir); + if (unlikely(err)) + h_trap = ERR_PTR(-EBUSY); + } + } else if (a->parent[SRC] == a->gparent[DST] || same_gp) { + LKTRLabel(here); + au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST, + a->dentry); + h_trap = au_ren_pin3(SRC, DST, a); + if (!IS_ERR(h_trap)) { + if (!same_gp) + h_gdir = au_pinned_h_dir(a->pin + SRC); + else + h_gdir = au_pinned_h_gdir(a->pin + SRC); + err = au_verify_parent(a->h_parent[DST], h_gdir); + if (unlikely(err)) + h_trap = ERR_PTR(-EBUSY); + } + } else if (a->gparent[SRC] + && (h_trap = au_test_subdir(a->gparent[SRC], + a->parent[DST]))) { + LKTRLabel(here); + au_ren_pin_init(a->pin + DST, a->dentry, a->pin + SRC, + a->src_dentry); + if (a->gparent[DST]) { + err = au_ren_pin4(DST, SRC, a); + if (unlikely(err)) + h_trap = ERR_PTR(err); + } else { + struct dentry *t; + t = au_ren_pin3(DST, SRC, a); + AuDebugOn(t == h_trap); + } + } else /* if (a->gparent[DST] + && (h_trap = au_test_subdir(a->gparent[DST], + a->parent[SRC]))) */ { + LKTRLabel(here); + h_trap = NULL; + if (a->gparent[DST]) + h_trap = au_test_subdir(a->gparent[DST], + a->parent[SRC]); + au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST, + a->dentry); + err = au_ren_pin4(SRC, DST, a); + if (unlikely(err)) + h_trap = ERR_PTR(err); + } + au_fset_ren(a->flags, PINNED); + + if (!IS_ERR(h_trap)) { + err = 0; + for (i = 0; !err && i < 2; i++) { + h_gdir = au_pinned_h_gdir(a->pin + i); + if (h_gdir) + err = au_verify_parent(a->h_parent[i], h_gdir); + } + if (unlikely(err)) + h_trap = ERR_PTR(err); + } + + dput(a->gparent[SRC]); + dput(a->gparent[DST]); + /* memset(a->gparent, 0, sizeof(a->gparent)); */ + AuTraceErrPtr(h_trap); + return h_trap; +} + +static void au_ren_unlock(struct au_ren_args *a) +{ + int i; + + AuTraceEnter(); + + if (a->h_locked[0]) + vfsub_unlock_rename(a->h_locked[0], a->h_locked[1]); + if (au_ftest_ren(a->flags, PINNED)) { + au_unpin(a->pin + SRC); + au_unpin(a->pin + DST); + memset(a->gparent, 0, sizeof(a->gparent)); + } + if (au_ftest_ren(a->flags, VFSLOCK)) + vfsub_unlock_rename_mutex(a->h_dentry[SRC]->d_sb); + for (i = 0; i < 2; i++) + if (unlikely(a->gparent[i])) { + di_read_unlock(a->gparent[i], AuLock_IR); + dput(a->gparent[i]); + } +} + +static int au_ren_lock(struct au_ren_args *a) +{ + int err; + const int hinotify = au_opt_test(a->mnt_flags, UDBA_INOTIFY); + + AuTraceEnter(); + + err = 0; + if (!hinotify + || (au_ftest_ren(a->flags, ISSAMEDIR) && IS_ROOT(a->parent[SRC]))) { + au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST, + a->dentry); + LKTRLabel(here); + a->h_locked[0] = a->h_parent[SRC]; + a->h_locked[1] = a->h_parent[DST]; + a->h_trap = vfsub_lock_rename(a->h_locked[0], a->h_locked[1]); + au_ren_fake_pin(a); + } else if (au_ftest_ren(a->flags, ISSAMEDIR) + && !IS_ROOT(a->parent[SRC])) { + /* this and next block should not be compiled when + hinotify is not enabled */ + /* irregular/tricky rename lock */ + LKTRLabel(here); + au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST, + a->dentry); + a->gparent[SRC] = dget_parent(a->parent[SRC]); + di_read_lock_parent2(a->gparent[SRC], AuLock_IR); + a->h_locked[0] = a->h_parent[SRC]; + a->h_locked[1] = dget_parent(a->h_parent[SRC]); + a->h_trap = vfsub_lock_rename(a->h_locked[0], a->h_locked[1]); + err = au_verify_parent(a->h_parent[SRC], + a->h_locked[1]->d_inode); + dput(a->h_locked[1]); + if (!err) + au_ren_fake_pin(a); + } else { + /* 3 or 4 dir locks. crazy */ + LKTRLabel(here); + a->h_trap = au_ren_pin(a); + if (IS_ERR(a->h_trap)) + err = PTR_ERR(a->h_trap); + } + + if (!err && au_dbstart(a->src_dentry) == a->btgt) + err = au_verify_parent(a->h_dentry[SRC], + a->h_parent[SRC]->d_inode); + if (!err && au_dbstart(a->dentry) == a->btgt) + err = au_verify_parent(a->h_dentry[DST], + a->h_parent[DST]->d_inode); + if (unlikely(err)) { + err = -EBUSY; + au_ren_unlock(a); + } + AuTraceErr(err); + return err; +} + +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry) +{ + int err; + aufs_bindex_t bend, bindex; + unsigned char do_dt_dstdir, hinotify; + struct inode *inode[2]; + enum { PARENT, CHILD }; + /* reduce stack space */ + struct { + struct au_ren_args a; + struct au_dtime dt[2][2]; + } *p; + struct au_wr_dir_args wr_dir_args = { + /* .force_btgt = -1, */ + .flags = AuWrDir_ADD_ENTRY + }; + + //lktr_set_pid(current->pid, LktrArrayPid); + LKTRTrace("i%lu, %.*s, i%lu, %.*s\n", + src_dir->i_ino, AuDLNPair(src_dentry), + dir->i_ino, AuDLNPair(dentry)); + AuDebugOn(IS_ROOT(src_dentry) || IS_ROOT(dentry)); + IMustLock(src_dir); + IMustLock(dir); + inode[DST] = dentry->d_inode; + if (inode[DST]) { + IMustLock(inode[DST]); + au_igrab(inode[DST]); + } + + err = -ENOMEM; + BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE); + p = kzalloc(sizeof(*p), GFP_NOFS); + if (unlikely(!p)) + goto out; + + err = -ENOTDIR; + p->a.src_dir = src_dir; + p->a.src_dentry = src_dentry; + p->a.dir = dir; + p->a.dentry = dentry; + p->a.sb = src_dentry->d_sb; + inode[SRC] = src_dentry->d_inode; + p->a.flags = 0; + if (S_ISDIR(inode[SRC]->i_mode)) { + au_fset_ren(p->a.flags, ISDIR); + if (unlikely(inode[DST] && !S_ISDIR(inode[DST]->i_mode))) + goto out_free; + aufs_read_and_write_lock2(dentry, src_dentry, AuLock_DIR); + } else + aufs_read_and_write_lock2(dentry, src_dentry, 0); + + p->a.mnt_flags = au_mntflags(p->a.sb); + if (unlikely(au_test_dlgt(p->a.mnt_flags))) + au_fset_ren(p->a.flags, DLGT); + p->a.parent[SRC] = src_dentry->d_parent; /* dir inode is locked */ + p->a.parent[DST] = dentry->d_parent; /* dir inode is locked */ + au_fset_ren(p->a.flags, ISSAMEDIR); /* temporary */ + di_write_lock_parent(p->a.parent[DST]); + + /* which branch we process */ + p->a.bstart[SRC] = au_dbstart(src_dentry); + p->a.bstart[DST] = au_dbstart(dentry); + if (au_ftest_ren(p->a.flags, ISDIR)) + au_fset_wrdir(wr_dir_args.flags, ISDIR); + wr_dir_args.force_btgt = p->a.bstart[SRC]; + if (dentry->d_inode && p->a.bstart[DST] < p->a.bstart[SRC]) + wr_dir_args.force_btgt = p->a.bstart[DST]; + wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); + err = au_wr_dir(dentry, src_dentry, &wr_dir_args); + p->a.btgt = err; + if (unlikely(err < 0)) + goto out_unlock; + + /* are they available to be renamed */ + err = 0; + au_nhash_init(&p->a.whlist); + if (au_ftest_ren(p->a.flags, ISDIR) && inode[DST]) { + au_set_dbstart(dentry, p->a.bstart[DST]); + err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist); + au_set_dbstart(dentry, p->a.btgt); + } + p->a.h_dentry[DST] = au_h_dptr(dentry, au_dbstart(dentry)); + if (unlikely(err)) + goto out_unlock; + /* todo: minor optimize, + their sb may be same while their bindex differs? */ + p->a.h_dentry[SRC] = au_h_dptr(src_dentry, au_dbstart(src_dentry)); + if (au_ftest_ren(p->a.flags, ISDIR)) { + err = may_rename_srcdir(src_dentry, p->a.btgt); + if (unlikely(err)) + goto out_children; + } + + /* prepare the writable parent dir on the same branch */ + if (p->a.bstart[DST] == p->a.btgt) { + au_fset_ren(p->a.flags, WHDST); + } else { + err = au_cpup_dirs(dentry, p->a.btgt); + if (unlikely(err)) + goto out_children; + } + + if (src_dir != dir) { + /* + * this temporary unlock is safe, + * because dir->i_mutex is locked. + */ + di_write_unlock(p->a.parent[DST]); + di_write_lock_parent(p->a.parent[SRC]); + err = au_wr_dir_need_wh + (src_dentry, au_ftest_ren(p->a.flags, ISDIR), + &p->a.btgt); + di_write_unlock(p->a.parent[SRC]); + di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST], + /*isdir*/1); + au_fclr_ren(p->a.flags, ISSAMEDIR); + } else + err = au_wr_dir_need_wh + (src_dentry, au_ftest_ren(p->a.flags, ISDIR), + &p->a.btgt); + if (unlikely(err < 0)) + goto out_children; + if (err) + au_fset_ren(p->a.flags, WHSRC); + + hinotify = au_opt_test(p->a.mnt_flags, UDBA_INOTIFY); + p->a.h_parent[SRC] = au_h_dptr(p->a.parent[SRC], p->a.btgt); + p->a.h_parent[DST] = au_h_dptr(p->a.parent[DST], p->a.btgt); + err = au_ren_lock(&p->a); + if (unlikely(err)) + goto out_children; + + if (!au_opt_test(p->a.mnt_flags, UDBA_NONE)) { + p->a.ndx.nfsmnt = au_nfsmnt(p->a.sb, p->a.btgt); + if (unlikely(au_ftest_ren(p->a.flags, DLGT))) + au_fset_ndx(p->a.ndx.flags, DLGT); + err = au_may_ren(&p->a); + if (unlikely(err)) + goto out_hdir; + memset(&p->a.ndx, 0, sizeof(p->a.ndx)); + } + + /* store timestamps to be revertible */ + au_dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC], + p->a.h_parent[SRC], + au_pinned_hdir(p->a.pin + SRC, p->a.btgt), + au_pinned_hgdir(p->a.pin + SRC, p->a.btgt) + /* hgdir[SRC] */); + if (!au_ftest_ren(p->a.flags, ISSAMEDIR)) + au_dtime_store(p->dt[PARENT] + DST, p->a.parent[DST], + p->a.h_parent[DST], + au_pinned_hdir(p->a.pin + DST, p->a.btgt), + au_pinned_hgdir(p->a.pin + DST, p->a.btgt) + /* hgdir[DST] */); + do_dt_dstdir = 0; + if (au_ftest_ren(p->a.flags, ISDIR)) { + au_dtime_store(p->dt[CHILD] + SRC, src_dentry, + p->a.h_dentry[SRC], au_hi(inode[SRC], p->a.btgt), + au_pinned_hdir(p->a.pin + SRC, p->a.btgt)); + if (p->a.h_dentry[DST]->d_inode) { + do_dt_dstdir = 1; + au_dtime_store(p->dt[CHILD] + DST, dentry, + p->a.h_dentry[DST], + au_hi(inode[DST], p->a.btgt), + au_pinned_hdir(p->a.pin + DST, + p->a.btgt)); + } + } + + err = do_rename(&p->a); + if (unlikely(err)) + goto out_dt; + + /* update dir attributes */ + dir->i_version++; + if (au_ftest_ren(p->a.flags, ISDIR)) { + /* is this updating defined in POSIX? */ + /* mutex_lock(&inode[SRC]->i_mutex); */ + au_cpup_attr_timesizes(inode[SRC]); + /* mutex_unlock(&inode[SRC]->i_mutex); */ + + au_cpup_attr_nlink(dir); + if (inode[DST]) { + clear_nlink(inode[DST]); + au_cpup_attr_timesizes(inode[DST]); + } + } + if (au_ibstart(dir) == p->a.btgt) + au_cpup_attr_timesizes(dir); + + if (!au_ftest_ren(p->a.flags, ISSAMEDIR)) { + src_dir->i_version++; + if (au_ftest_ren(p->a.flags, ISDIR)) + au_cpup_attr_nlink(src_dir); + if (au_ibstart(src_dir) == p->a.btgt) + au_cpup_attr_timesizes(src_dir); + } + + /* todo: simple d_drop(src_dentry) is not enough? */ + /* dput/iput all lower dentries */ + au_set_dbwh(src_dentry, -1); + bend = au_dbend(src_dentry); + for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) { + struct dentry *hd; + hd = au_h_dptr(src_dentry, bindex); + if (hd) + au_set_h_dptr(src_dentry, bindex, NULL); + } + au_set_dbend(src_dentry, p->a.btgt); + + if (au_opt_test(p->a.mnt_flags, PLINK) + && !au_plink_test(src_dentry->d_sb, inode[SRC])) { + bend = au_ibend(inode[SRC]); + for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) { + struct inode *hi; + hi = au_h_iptr(inode[SRC], bindex); + if (hi) { + au_xino_write0(p->a.sb, bindex, hi->i_ino, 0); + /* ignore this error */ + au_set_h_iptr(inode[SRC], bindex, NULL, 0); + } + } + au_set_ibend(inode[SRC], p->a.btgt); + } + goto out_hdir; /* success */ + + out_dt: + au_dtime_revert(p->dt[PARENT] + SRC); + if (!au_ftest_ren(p->a.flags, ISSAMEDIR)) + au_dtime_revert(p->dt[PARENT] + DST); + if (au_ftest_ren(p->a.flags, ISDIR) && err != -EIO) { + struct dentry *hd; + + hd = p->dt[CHILD][SRC].dt_h_dentry; + mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD); + au_dtime_revert(p->dt[CHILD] + SRC); + mutex_unlock(&hd->d_inode->i_mutex); + if (do_dt_dstdir) { + hd = p->dt[CHILD][DST].dt_h_dentry; + mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD); + au_dtime_revert(p->dt[CHILD] + DST); + mutex_unlock(&hd->d_inode->i_mutex); + } + } + out_hdir: + au_ren_unlock(&p->a); + out_children: + au_nhash_fin(&p->a.whlist); + out_unlock: + if (unlikely(err && au_ftest_ren(p->a.flags, ISDIR))) { + au_update_dbstart(dentry); + d_drop(dentry); + } + if (!err) { + d_move(src_dentry, dentry); +#if 0 + lktr_set_pid(current->pid, LktrArrayPid); + AuDbgDentry(src_dentry); + AuDbgDentry(dentry); + lktr_clear_pid(current->pid, LktrArrayPid); +#endif +#if 0 + if (inode[DST]) { + inode[DST]->i_flags |= S_DEAD; + ii_write_unlock(inode[DST]); + } +#endif + } + if (au_ftest_ren(p->a.flags, ISSAMEDIR)) + di_write_unlock(p->a.parent[DST]); + else + di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]); + aufs_read_and_write_unlock2(dentry, src_dentry); + out_free: + kfree(p); + out: + iput(inode[DST]); + AuTraceErr(err); + //lktr_clear_pid(current->pid, LktrArrayPid); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/vfsub.h +++ linux-2.6.27/ubuntu/aufs/vfsub.h @@ -0,0 +1,518 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for VFS + * + * $Id: vfsub.h,v 1.11 2008/08/25 01:51:04 sfjro Exp $ + */ + +#ifndef __AUFS_VFSUB_H__ +#define __AUFS_VFSUB_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include + +/* ---------------------------------------------------------------------- */ + +/* vfsub flags */ +#define Vfsub_DLGT 1 /* operation with delegation */ +#define Vfsub_FORCE_UNLINK (1 << 1) /* force unlinking */ +#define vfsub_ftest(flags, name) ((flags) & Vfsub_##name) +#define vfsub_fset(flags, name) { (flags) |= Vfsub_##name; } +#define vfsub_fclr(flags, name) { (flags) &= ~Vfsub_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef Vfsub_DLGT +#define Vfsub_DLGT 0 +#endif + +struct au_hin_ignore; +struct vfsub_args { +#ifdef CONFIG_AUFS_HINOTIFY + /* inotify events to be ignored */ + int nignore; + struct au_hin_ignore *ignore; +#endif + + unsigned int flags; +}; + +struct au_hinode; +#ifdef CONFIG_AUFS_HINOTIFY +static inline +void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign) +{ + vargs->nignore = 0; + vargs->ignore = ign; +} + +static inline void vfsub_args_reinit(struct vfsub_args *vargs) +{ + vargs->nignore = 0; +} + +__u32 vfsub_events_notify_change(struct iattr *ia); +void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events, + struct au_hinode *hinode); +void vfsub_ignore(struct vfsub_args *vargs); +void vfsub_unignore(struct vfsub_args *vargs); +#else +static inline +void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign) +{ + /* empty */ +} + +static inline void vfsub_args_reinit(struct vfsub_args *vargs) +{ + /* empty */ +} + +static inline __u32 vfsub_events_notify_change(struct iattr *ia) +{ + return 0; +} + +static inline void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events, + struct au_hinode *hinode) +{ + /* empty */ +} + +static inline void vfsub_ignore(struct vfsub_args *vargs) +{ + /* empty */ +} + +static inline void vfsub_unignore(struct vfsub_args *vargs) +{ + /* empty */ +} +#endif /* CONFIG_AUFS_HINOTIFY */ + +void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign, + int dlgt, int force_unlink); + +/* ---------------------------------------------------------------------- */ + +/* inotify_inode_watched() is not exported */ +static inline int au_test_inotify(struct inode *inode) +{ +#ifdef CONFIG_INOTIFY + return !list_empty(&inode->inotify_watches); +#endif + return 0; +} + +/* ---------------------------------------------------------------------- */ + +/* lock subclass for hidden inode */ +/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ +/* reduce? gave up. */ +enum { + AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */ + AuLsc_I_PARENT, /* hidden inode, parent first */ + AuLsc_I_PARENT2, /* copyup dirs */ + AuLsc_I_PARENT3, /* rename with hinotify */ + AuLsc_I_PARENT4, /* ditto */ + AuLsc_I_CHILD, + AuLsc_I_CHILD2, + AuLsc_I_End +}; + +#define IMustLock(i) MtxMustLock(&(i)->i_mutex) + +static inline void vfsub_lock_rename_mutex(struct super_block *sb) +{ + lockdep_off(); + mutex_lock(&sb->s_vfs_rename_mutex); + lockdep_on(); +} + +static inline void vfsub_unlock_rename_mutex(struct super_block *sb) +{ + lockdep_off(); + mutex_unlock(&sb->s_vfs_rename_mutex); + lockdep_on(); +} + +static inline +struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2) +{ + struct dentry *d; + + lockdep_off(); + d = lock_rename(d1, d2); + lockdep_on(); + return d; +} + +static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2) +{ + lockdep_off(); + unlock_rename(d1, d2); + lockdep_on(); +} + +static inline int au_verify_parent(struct dentry *dentry, struct inode *dir) +{ + IMustLock(dir); + return (/* !dir->i_nlink || */ dentry->d_parent->d_inode != dir); +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_WORKAROUND_FUSE +/* br_fuse.c */ +int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry); +#else +static inline +int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry) +{ + return 0; +} +#endif + +#ifdef CONFIG_AUFS_BR_XFS +/* br_xfs.c */ +dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt, + struct dentry *h_dentry); +#else +static inline +dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt, + struct dentry *h_dentry) +{ + return h_inode->i_rdev; +} +#endif + +/* simple abstractions, for future use */ +static inline +int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + LKTRTrace("i%lu, mask 0x%x, nd %d\n", inode->i_ino, mask, !!nd); + IMustLock(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + return inode_permission(inode, mask); +#else + return permission(inode, mask, nd); +#endif +} + +static inline +int vfsub_security_inode_permission(struct inode *inode, int mask, + struct nameidata *nd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + return security_inode_permission(inode, mask); +#else + return security_inode_permission(inode, mask, nd); +#endif +} + +/* ---------------------------------------------------------------------- */ + +struct file *vfsub_filp_open(const char *path, int oflags, int mode); +int vfsub_path_lookup(const char *name, unsigned int flags, + struct nameidata *nd); +struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, + int len); + +#ifdef CONFIG_AUFS_LHASH_PATCH +struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent, + struct nameidata *nd); +#endif + +/* ---------------------------------------------------------------------- */ + +int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd); +int do_vfsub_symlink(struct inode *dir, struct dentry *dentry, + const char *symname, int mode); +int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, + dev_t dev); +int do_vfsub_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry); +int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry); +int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode); +int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry); +int do_vfsub_unlink(struct inode *dir, struct dentry *dentry); + +/* ---------------------------------------------------------------------- */ + +ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count, + loff_t *ppos); +/* todo: kernel_read()? */ +ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos); +ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos); +ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos); +int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg); + +/* ---------------------------------------------------------------------- */ + +#ifndef CONFIG_AUFS_UNIONFS22_PATCH +static inline void vfsub_copy_inode_size(struct inode *inode, + struct inode *h_inode) +{ + spin_lock(&inode->i_lock); + fsstack_copy_inode_size(inode, h_inode); + spin_unlock(&inode->i_lock); +} +#else +static inline void vfsub_copy_inode_size(struct inode *inode, + struct inode *h_inode) +{ + fsstack_copy_inode_size(inode, h_inode); +} +#endif + +#ifndef CONFIG_AUFS_UNIONFS23_PATCH +#define vfs_splice_to do_splice_to +#define vfs_splice_from do_splice_from +#endif + +#ifdef CONFIG_AUFS_SPLICE_PATCH +long do_vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); +long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags); +#else +static inline +long do_vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + return -ENOSYS; +} + +static inline +long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) +{ + return -ENOSYS; +} +#endif /* CONFIG_AUFS_SPLICE_PATCH */ + +/* ---------------------------------------------------------------------- */ + +static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) +{ + loff_t err; + + LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry)); + + lockdep_off(); + err = vfs_llseek(file, offset, origin); + lockdep_on(); + return err; +} + +static inline int do_vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *st) +{ + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + return vfs_getattr(mnt, dentry, st); +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_HIN_OR_DLGT +/* hin_or_dlgt.c */ +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd, + int dlgt); + +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd, struct vfsub_args *vargs); +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname, + int mode, struct vfsub_args *vargs); +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev, + struct vfsub_args *vargs); +int vfsub_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry, struct vfsub_args *vargs); +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs); +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, + struct vfsub_args *vargs); +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs); + +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, + loff_t *ppos, int dlgt); +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos, + int dlgt); +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos, struct vfsub_args *vargs); +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos, + struct vfsub_args *vargs); +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt); +long vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags, int dlgt); +long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags, + struct vfsub_args *vargs); + +int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st, + int dlgt); +#else + +static inline +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd, + int dlgt) +{ + return do_vfsub_permission(inode, mask, nd); +} + +static inline +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd, struct vfsub_args *vargs) +{ + return do_vfsub_create(dir, dentry, mode, nd); +} + +static inline +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname, + int mode, struct vfsub_args *vargs) +{ + return do_vfsub_symlink(dir, dentry, symname, mode); +} + +static inline +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev, + struct vfsub_args *vargs) +{ + return do_vfsub_mknod(dir, dentry, mode, dev); +} + +static inline +int vfsub_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry, struct vfsub_args *vargs) +{ + return do_vfsub_link(src_dentry, dir, dentry); +} + +static inline +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs) +{ + return do_vfsub_rename(src_dir, src_dentry, dir, dentry); +} + +static inline +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, + struct vfsub_args *vargs) +{ + return do_vfsub_mkdir(dir, dentry, mode); +} + +static inline +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs) +{ + return do_vfsub_rmdir(dir, dentry); +} + +static inline +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, + loff_t *ppos, int dlgt) +{ + return do_vfsub_read_u(file, ubuf, count, ppos); +} + +static inline +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos, + int dlgt) +{ + return do_vfsub_read_k(file, kbuf, count, ppos); +} + +static inline +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos, struct vfsub_args *vargs) +{ + return do_vfsub_write_u(file, ubuf, count, ppos); +} + +static inline +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos, + struct vfsub_args *vargs) +{ + return do_vfsub_write_k(file, kbuf, count, ppos); +} + +static inline +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt) +{ + return do_vfsub_readdir(file, filldir, arg); +} + +static inline +long vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags, int dlgt) +{ + return do_vfsub_splice_to(in, ppos, pipe, len, flags); +} + +static inline +long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags, + struct vfsub_args *vargs) +{ + return do_vfsub_splice_from(pipe, out, ppos, len, flags); +} + +static inline +int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st, + int dlgt) +{ + return do_vfsub_getattr(mnt, dentry, st); +} +#endif /* HIN_OR_DLGT */ + +/* ---------------------------------------------------------------------- */ + +int vfsub_sio_mkdir(struct au_hinode *hdir, struct dentry *dentry, int mode, + int dlgt); +int vfsub_sio_rmdir(struct au_hinode *hdir, struct dentry *dentry, int dlgt); +int vfsub_sio_notify_change(struct au_hinode *hdir, struct dentry *dentry, + struct iattr *ia); + +/* ---------------------------------------------------------------------- */ + +int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, + struct vfsub_args *vargs); +int vfsub_unlink(struct inode *dir, struct dentry *dentry, + struct vfsub_args *vargs); +int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_VFSUB_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/debug.h +++ linux-2.6.27/ubuntu/aufs/debug.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * debug print functions + * + * $Id: debug.h,v 1.8 2008/09/22 03:52:03 sfjro Exp $ + */ + +#ifndef __AUFS_DEBUG_H__ +#define __AUFS_DEBUG_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +/* to debug easier, do not make it an inlined function */ +#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) + +#ifdef CONFIG_AUFS_DEBUG +/* sparse warns about pointer */ +#define AuDebugOn(a) BUG_ON(!!(a)) +extern atomic_t au_cond; +#define au_debug_on() atomic_inc_return(&au_cond) +#define au_debug_off() atomic_dec_return(&au_cond) +static inline int au_debug_test(void) +{ + return atomic_read(&au_cond); +} +#else +#define AuDebugOn(a) do {} while (0) +#define au_debug_on() do {} while (0) +#define au_debug_off() do {} while (0) +static inline int au_debug_test(void) +{ + return 0; +} +#endif /* CONFIG_AUFS_DEBUG */ + +/* ---------------------------------------------------------------------- */ + +/* debug print */ +#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE) +#include +#ifdef CONFIG_AUFS_DEBUG +#undef LktrCond +#define LktrCond unlikely(au_debug_test() || (lktr_cond && lktr_cond())) +#endif +#else +#define LktrCond au_debug_test() +#define LKTRDumpVma(pre, vma, suf) do {} while (0) +#define LKTRDumpStack() do {} while (0) +#define LKTRTrace(fmt, args...) do { \ + if (LktrCond) \ + AuDbg(fmt, ##args); \ +} while (0) +#define LKTRLabel(label) LKTRTrace("%s\n", #label) +#endif /* CONFIG_LKTR */ + +#define AuTraceErr(e) do { \ + if (unlikely((e) < 0)) \ + LKTRTrace("err %d\n", (int)(e)); \ +} while (0) + +#define AuTraceErrPtr(p) do { \ + if (IS_ERR(p)) \ + LKTRTrace("err %ld\n", PTR_ERR(p)); \ +} while (0) + +#define AuTraceEnter() LKTRLabel(enter) + +/* dirty macros for debug print, use with "%.*s" and caution */ +#define AuLNPair(qstr) (qstr)->len, (qstr)->name +#define AuDLNPair(d) AuLNPair(&(d)->d_name) + +/* ---------------------------------------------------------------------- */ + +#define AuDpri(lvl, fmt, arg...) \ + printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \ + __func__, __LINE__, current->comm, current->pid, ##arg) +#define AuDbg(fmt, arg...) AuDpri(KERN_DEBUG, fmt, ##arg) +#define AuInfo(fmt, arg...) AuDpri(KERN_INFO, fmt, ##arg) +#define AuWarn(fmt, arg...) AuDpri(KERN_WARNING, fmt, ##arg) +#define AuErr(fmt, arg...) AuDpri(KERN_ERR, fmt, ##arg) +#define AuIOErr(fmt, arg...) AuErr("I/O Error, " fmt, ##arg) +#define AuIOErrWhck(fmt, arg...) AuErr("I/O Error, try whck. " fmt, ##arg) +#define AuWarn1(fmt, arg...) do { \ + static unsigned char _c; \ + if (!_c++) AuWarn(fmt, ##arg); \ +} while (0) + +#define AuErr1(fmt, arg...) do { \ + static unsigned char _c; \ + if (!_c++) AuErr(fmt, ##arg); \ +} while (0) + +#define AuIOErr1(fmt, arg...) do { \ + static unsigned char _c; \ + if (!_c++) AuIOErr(fmt, ##arg); \ +} while (0) + +#define AuUnsupportMsg "This operation is not supported." \ + " Please report this application to aufs-users ML." +#define AuUnsupport(fmt, args...) do { \ + AuErr(AuUnsupportMsg "\n" fmt, ##args); \ + dump_stack(); \ +} while (0) + +/* ---------------------------------------------------------------------- */ + +struct au_sbinfo; +#ifdef CONFIG_AUFS_DEBUG +extern char *au_plevel; +struct au_nhash; +void au_dpri_whlist(struct au_nhash *whlist); +struct au_vdir; +void au_dpri_vdir(struct au_vdir *vdir); +void au_dpri_inode(struct inode *inode); +void au_dpri_dentry(struct dentry *dentry); +void au_dpri_file(struct file *filp); +void au_dpri_sb(struct super_block *sb); +void au_dbg_sleep(int sec); +void au_dbg_sleep_jiffy(int jiffy); +#ifndef ATTR_TIMES_SET +#define ATTR_TIMES_SET 0 +#endif +void au_dbg_iattr(struct iattr *ia); +int __init au_debug_init(void); +void au_debug_sbinfo_init(struct au_sbinfo *sbinfo); +#define AuDbgWhlist(w) do { \ + LKTRTrace(#w "\n"); \ + au_dpri_whlist(w); \ +} while (0) + +#define AuDbgVdir(v) do { \ + LKTRTrace(#v "\n"); \ + au_dpri_vdir(v); \ +} while (0) + +#define AuDbgInode(i) do { \ + LKTRTrace(#i "\n"); \ + au_dpri_inode(i); \ +} while (0) + +#define AuDbgDentry(d) do { \ + LKTRTrace(#d "\n"); \ + au_dpri_dentry(d); \ +} while (0) + +#define AuDbgFile(f) do { \ + LKTRTrace(#f "\n"); \ + au_dpri_file(f); \ +} while (0) + +#define AuDbgSb(sb) do { \ + LKTRTrace(#sb "\n"); \ + au_dpri_sb(sb); \ +} while (0) + +#define AuDbgSleep(sec) do { \ + AuDbg("sleep %d sec\n", sec); \ + au_dbg_sleep(sec); \ +} while (0) + +#define AuDbgSleepJiffy(jiffy) do { \ + AuDbg("sleep %d jiffies\n", jiffy); \ + au_dbg_sleep_jiffy(jiffy); \ +} while (0) + +#define AuDbgIAttr(ia) do { \ + AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \ + au_dbg_iattr(ia); \ +} while (0) +#else +static inline int au_debug_init(void) +{ + return 0; +} +static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo) +{ + /* empty */ +} +#define AuDbgWhlist(w) do {} while (0) +#define AuDbgVdir(v) do {} while (0) +#define AuDbgInode(i) do {} while (0) +#define AuDbgDentry(d) do {} while (0) +#define AuDbgFile(f) do {} while (0) +#define AuDbgSb(sb) do {} while (0) +#define AuDbgSleep(sec) do {} while (0) +#define AuDbgSleepJiffy(jiffy) do {} while (0) +#define AuDbgIAttr(ia) do {} while (0) +#endif /* CONFIG_AUFS_DEBUG */ + +#ifdef DbgUdbaRace +#define AuDbgSleep_UdbaRace() AuDbgSleep(DbgUdbaRace) +#else +#define AuDbgSleep_UdbaRace() do {} while (0) +#endif + +#ifdef CONFIG_AUFS_MAGIC_SYSRQ +int __init au_sysrq_init(void); +void au_sysrq_fin(void); + +#ifdef CONFIG_HW_CONSOLE +#define au_dbg_blocked() do { \ + WARN_ON(1); \ + handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \ +} while (0) +#else +#define au_dbg_blocked() do {} while (0) +#endif + +#else +static inline int au_sysrq_init(void) +{ + return 0; +} +#define au_sysrq_fin() do {} while (0) +#define au_dbg_blocked() do {} while (0) +#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DEBUG_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/plink.c +++ linux-2.6.27/ubuntu/aufs/plink.c @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * pseudo-link + * + * $Id: plink.c,v 1.9 2008/09/01 02:55:35 sfjro Exp $ + */ + +#include "aufs.h" + +struct pseudo_link { + struct list_head list; + struct inode *inode; +}; + +#ifdef CONFIG_AUFS_DEBUG +void au_plink_list(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink; + + AuTraceEnter(); + SiMustAnyLock(sb); + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + + plink_list = &sbinfo->si_plink; + spin_lock(&sbinfo->si_plink_lock); + list_for_each_entry(plink, plink_list, list) + AuDbg("%lu\n", plink->inode->i_ino); + spin_unlock(&sbinfo->si_plink_lock); +} +#endif + +int au_plink_test(struct super_block *sb, struct inode *inode) +{ + int found; + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink; + + LKTRTrace("i%lu\n", inode->i_ino); + SiMustAnyLock(sb); + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + + found = 0; + plink_list = &sbinfo->si_plink; + spin_lock(&sbinfo->si_plink_lock); + list_for_each_entry(plink, plink_list, list) + if (plink->inode == inode) { + found = 1; + break; + } + spin_unlock(&sbinfo->si_plink_lock); + return found; +} + +/* 20 is max digits length of ulong 64 */ +#define PLINK_NAME_LEN ((20 + 1) * 2) + +static int plink_name(char *name, int len, struct inode *inode, + aufs_bindex_t bindex) +{ + int rlen; + struct inode *h_inode; + + LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex); + AuDebugOn(len != PLINK_NAME_LEN); + h_inode = au_h_iptr(inode, bindex); + AuDebugOn(!h_inode); + rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino); + AuDebugOn(rlen >= len); + return rlen; +} + +struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex, + struct inode *inode) +{ + struct dentry *h_dentry, *h_parent; + struct au_branch *br; + struct au_wbr *wbr; + struct inode *h_dir; + char tgtname[PLINK_NAME_LEN]; + int len; + struct au_ndx ndx = { + .flags = 0, + .nd = NULL, + /* .br = NULL */ + }; + + LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino); + br = au_sbr(sb, bindex); + wbr = br->br_wbr; + AuDebugOn(!wbr); + h_parent = wbr->wbr_plink; + AuDebugOn(!h_parent); + h_dir = h_parent->d_inode; + AuDebugOn(!h_dir); + + len = plink_name(tgtname, sizeof(tgtname), inode, bindex); + + /* always superio. */ + ndx.nfsmnt = au_do_nfsmnt(br->br_mnt); + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2); + h_dentry = au_sio_lkup_one(tgtname, h_parent, len, &ndx); + mutex_unlock(&h_dir->i_mutex); + return h_dentry; +} + +static int do_whplink(char *tgt, int len, struct dentry *h_parent, + struct dentry *h_dentry, struct vfsmount *nfsmnt, + struct super_block *sb) +{ + int err, dlgt; + struct dentry *h_tgt; + struct inode *h_dir; + struct vfsub_args vargs; + struct au_ndx ndx = { + .nfsmnt = nfsmnt, + .flags = 0, + .nd = NULL, + /* .br = NULL */ + }; + + AuTraceEnter(); + + dlgt = !!au_test_dlgt(au_mntflags(sb)); + if (unlikely(dlgt)) + au_fset_ndx(ndx.flags, DLGT); + h_tgt = au_lkup_one(tgt, h_parent, len, &ndx); + err = PTR_ERR(h_tgt); + if (IS_ERR(h_tgt)) + goto out; + + err = 0; + vfsub_args_init(&vargs, NULL, dlgt, 0); + /* wh.plink dir is not monitored */ + h_dir = h_parent->d_inode; + if (unlikely(h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode)) + err = vfsub_unlink(h_dir, h_tgt, &vargs); + if (!err && !h_tgt->d_inode) { + err = vfsub_link(h_dentry, h_dir, h_tgt, &vargs); + /* todo: unnecessary? */ + /* inc_nlink(inode); */ + } + dput(h_tgt); + + out: + AuTraceErr(err); + return err; +} + +struct do_whplink_args { + int *errp; + char *tgt; + int len; + struct dentry *h_parent; + struct dentry *h_dentry; + struct vfsmount *nfsmnt; + struct super_block *sb; +}; + +static void call_do_whplink(void *args) +{ + struct do_whplink_args *a = args; + *a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry, + a->nfsmnt, a->sb); +} + +static int whplink(struct dentry *h_dentry, struct inode *inode, + aufs_bindex_t bindex, struct super_block *sb) +{ + int err, len, wkq_err; + struct au_branch *br; + struct au_wbr *wbr; + struct dentry *h_parent; + struct inode *h_dir; + char tgtname[PLINK_NAME_LEN]; + + LKTRTrace("%.*s\n", AuDLNPair(h_dentry)); + br = au_sbr(inode->i_sb, bindex); + wbr = br->br_wbr; + AuDebugOn(!wbr); + h_parent = wbr->wbr_plink; + AuDebugOn(!h_parent); + h_dir = h_parent->d_inode; + AuDebugOn(!h_dir); + + len = plink_name(tgtname, sizeof(tgtname), inode, bindex); + + /* always superio. */ + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2); + if (!au_test_wkq(current)) { + struct do_whplink_args args = { + .errp = &err, + .tgt = tgtname, + .len = len, + .h_parent = h_parent, + .h_dentry = h_dentry, + .nfsmnt = au_do_nfsmnt(br->br_mnt), + .sb = sb + }; + wkq_err = au_wkq_wait(call_do_whplink, &args, /*dlgt*/0); + if (unlikely(wkq_err)) + err = wkq_err; + } else + err = do_whplink(tgtname, len, h_parent, h_dentry, + au_do_nfsmnt(br->br_mnt), sb); + mutex_unlock(&h_dir->i_mutex); + + AuTraceErr(err); + return err; +} + +void au_plink_append(struct super_block *sb, struct inode *inode, + struct dentry *h_dentry, aufs_bindex_t bindex) +{ + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink; + int found, err, cnt; + + LKTRTrace("i%lu\n", inode->i_ino); + SiMustAnyLock(sb); + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + + cnt = 0; + found = 0; + plink_list = &sbinfo->si_plink; + spin_lock(&sbinfo->si_plink_lock); + list_for_each_entry(plink, plink_list, list) { + cnt++; + if (plink->inode == inode) { + found = 1; + break; + } + } + + err = 0; + if (!found) { + plink = kmalloc(sizeof(*plink), GFP_ATOMIC); + if (plink) { + plink->inode = au_igrab(inode); + list_add(&plink->list, plink_list); + cnt++; + } else + err = -ENOMEM; + } + spin_unlock(&sbinfo->si_plink_lock); + +#if 0 /* todo: test here */ + if (found) + return; /* success */ +#endif + + if (!err) + err = whplink(h_dentry, inode, bindex, sb); + + if (unlikely(cnt > AUFS_PLINK_WARN)) + AuWarn1("unexpectedly many pseudo links, %d\n", cnt); + if (unlikely(err)) + AuWarn("err %d, damaged pseudo link. ignored.\n", err); +} + +static void do_put_plink(struct pseudo_link *plink, int do_del) +{ + AuTraceEnter(); + + iput(plink->inode); + if (do_del) + list_del(&plink->list); + kfree(plink); +} + +void au_plink_put(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink, *tmp; + + AuTraceEnter(); + SiMustWriteLock(sb); + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + + plink_list = &sbinfo->si_plink; + /* spin_lock(&sbinfo->si_plink_lock); */ + list_for_each_entry_safe(plink, tmp, plink_list, list) + do_put_plink(plink, 0); + INIT_LIST_HEAD(plink_list); + /* spin_unlock(&sbinfo->si_plink_lock); */ +} + +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id) +{ + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink, *tmp; + struct inode *inode; + aufs_bindex_t bstart, bend, bindex; + int do_put; + + AuTraceEnter(); + SiMustWriteLock(sb); + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + + plink_list = &sbinfo->si_plink; + /* spin_lock(&sbinfo->si_plink_lock); */ + list_for_each_entry_safe(plink, tmp, plink_list, list) { + do_put = 0; + inode = au_igrab(plink->inode); + ii_write_lock_child(inode); + bstart = au_ibstart(inode); + bend = au_ibend(inode); + if (bstart >= 0) { + for (bindex = bstart; bindex <= bend; bindex++) { + if (!au_h_iptr(inode, bindex) + || au_ii_br_id(inode, bindex) != br_id) + continue; + au_set_h_iptr(inode, bindex, NULL, 0); + do_put = 1; + break; + } + } else + do_put_plink(plink, 1); + + if (do_put) { + for (bindex = bstart; bindex <= bend; bindex++) + if (au_h_iptr(inode, bindex)) { + do_put = 0; + break; + } + if (do_put) + do_put_plink(plink, 1); + } + ii_write_unlock(inode); + iput(inode); + } + /* spin_unlock(&sbinfo->si_plink_lock); */ +} --- linux-2.6.27.orig/ubuntu/aufs/Makefile +++ linux-2.6.27/ubuntu/aufs/Makefile @@ -0,0 +1,74 @@ +# AUFS Makefile for the Linux 2.6.25 and later +# $Id: Makefile,v 1.8 2008/08/04 00:32:21 sfjro Exp $ + +# the environment variables are not inherited since 2.6.23 +ifdef AUFS_EXTRA_CFLAGS +ccflags-y += ${AUFS_EXTRA_CFLAGS} +endif + +######################################## + +ifdef CONFIG_AUFS_RR_SQUASHFS +# cf. squashfs3.2-r2 and sqlzma patch. +ccflags-y += -DSQUASHFS_MAGIC=0x73717368 +ccflags-y += -DSQUASHFS_MAGIC_SWAP=0x68737173 +ccflags-y += -DSQUASHFS_MAGIC_LZMA=0x71736873 +ccflags-y += -DSQUASHFS_MAGIC_LZMA_SWAP=0x73687371 +endif + +# defined in ${srctree}/fs/fuse/inode.c +ccflags-$(CONFIG_AUFS_WORKAROUND_FUSE) += -DFUSE_SUPER_MAGIC=0x65735546 + +# defined in ${srctree}/fs/xfs/xfs_sb.h +# tristate +ifdef CONFIG_XFS_FS +ccflags-y += -DXFS_SB_MAGIC=0x58465342 +endif + +# defined in ${srctree}/mm/shmem.c in linux-2.6.26 and earlier +# tristate +ifdef CONFIG_TMPFS +ccflags-y += -DTMPFS_MAGIC=0x01021994 +endif + +# defined in ${srctree}fs/sysfs/mount.c +# bool +ccflags-$(CONFIG_SYSFS) += -DSYSFS_MAGIC=0x62656572 + +ifndef EXTRAVERSION +EXTRAVERSION = $(shell echo ${KERNELVERSION} | cut -f3- -d. | cut -f2- -d-) +endif +# for -mm tree, support the latest version only +ifneq ($(strip $(shell echo ${EXTRAVERSION} | fgrep -- mm)),) +ccflags-y += -DCONFIG_AUFS_UNIONFS22_PATCH -DCONFIG_AUFS_UNIONFS23_PATCH +endif + +-include $(dir $(lastword ${MAKEFILE_LIST}))priv.mk +#$(warning ${ccflags-y}) + +######################################## + +obj-$(CONFIG_AUFS) += aufs.o +aufs-y := module.o super.o sbinfo.o branch.o xino.o sysaufs.o opts.o \ + wkq.o vfsub.o dcsub.o \ + cpup.o whout.o plink.o wbr_policy.o \ + dentry.o dinfo.o \ + file.o f_op.o finfo.o \ + dir.o vdir.o \ + inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \ + misc.o + +aufs-$(CONFIG_SYSFS) += sysfs.o +aufs-$(CONFIG_AUFS_BR_NFS) += br_nfs.o +aufs-$(CONFIG_AUFS_BR_XFS) += br_xfs.o +aufs-$(CONFIG_AUFS_WORKAROUND_FUSE) += br_fuse.o +aufs-$(CONFIG_AUFS_DLGT) += dlgt.o +aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o +aufs-$(CONFIG_AUFS_HIN_OR_DLGT) += hin_or_dlgt.o +aufs-$(CONFIG_AUFS_HIN_OR_FUSE) += hin_or_fuse.o +aufs-$(CONFIG_AUFS_EXPORT) += export.o +aufs-$(CONFIG_AUFS_ROBR) += robr.o +# reserved for future use +#aufs-$(CONFIG_AUFS_XATTR) += xattr.o +aufs-$(CONFIG_AUFS_DEBUG) += debug.o +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o --- linux-2.6.27.orig/ubuntu/aufs/opts.c +++ linux-2.6.27/ubuntu/aufs/opts.c @@ -0,0 +1,1570 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * mount options/flags + * + * $Id: opts.c,v 1.15 2008/09/01 02:55:31 sfjro Exp $ + */ + +#include /* a distribution requires */ +#include +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +enum { + Opt_br, + Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend, + Opt_idel, Opt_imod, Opt_ireorder, + Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash, Opt_rendir, + Opt_xino, Opt_zxino, Opt_noxino, + Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, + Opt_trunc_xino_path, Opt_itrunc_xino, + Opt_xinodir, + Opt_trunc_xib, Opt_notrunc_xib, + Opt_dirperm1, Opt_nodirperm1, + Opt_shwh, Opt_noshwh, + Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink, + Opt_udba, + /* Opt_lock, Opt_unlock, */ + Opt_cmd, Opt_cmd_args, + Opt_diropq_a, Opt_diropq_w, + Opt_warn_perm, Opt_nowarn_perm, + Opt_wbr_copyup, Opt_wbr_create, + Opt_coo, + Opt_dlgt, Opt_nodlgt, + Opt_refrof, Opt_norefrof, + Opt_verbose, Opt_noverbose, + Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err +}; + +static match_table_t options = { + {Opt_br, "br=%s"}, + {Opt_br, "br:%s"}, + + {Opt_add, "add=%d:%s"}, + {Opt_add, "add:%d:%s"}, + {Opt_add, "ins=%d:%s"}, + {Opt_add, "ins:%d:%s"}, + {Opt_append, "append=%s"}, + {Opt_append, "append:%s"}, + {Opt_prepend, "prepend=%s"}, + {Opt_prepend, "prepend:%s"}, + + {Opt_del, "del=%s"}, + {Opt_del, "del:%s"}, + /* {Opt_idel, "idel:%d"}, */ + {Opt_mod, "mod=%s"}, + {Opt_mod, "mod:%s"}, + {Opt_imod, "imod:%d:%s"}, + + {Opt_dirwh, "dirwh=%d"}, + {Opt_dirwh, "dirwh:%d"}, + + {Opt_xino, "xino=%s"}, + {Opt_xino, "xino:%s"}, +#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */ + {Opt_xinodir, "xinodir=%s"}, + {Opt_xinodir, "xinodir:%s"}, +#endif + {Opt_noxino, "noxino"}, + {Opt_trunc_xino, "trunc_xino"}, + {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, + {Opt_notrunc_xino, "notrunc_xino"}, + {Opt_trunc_xino_path, "trunc_xino=%s"}, + {Opt_trunc_xino_path, "trunc_xino:%s"}, + {Opt_itrunc_xino, "itrunc_xino=%d"}, + {Opt_itrunc_xino, "itrunc_xino:%d"}, + /* {Opt_zxino, "zxino=%s"}, */ + {Opt_trunc_xib, "trunc_xib"}, + {Opt_notrunc_xib, "notrunc_xib"}, + + {Opt_plink, "plink"}, + {Opt_noplink, "noplink"}, +#ifdef CONFIG_AUFS_DEBUG + {Opt_list_plink, "list_plink"}, +#endif + {Opt_clean_plink, "clean_plink"}, + + {Opt_udba, "udba=%s"}, + + {Opt_diropq_a, "diropq=always"}, + {Opt_diropq_a, "diropq=a"}, + {Opt_diropq_w, "diropq=whiteouted"}, + {Opt_diropq_w, "diropq=w"}, + + {Opt_warn_perm, "warn_perm"}, + {Opt_nowarn_perm, "nowarn_perm"}, + +#ifdef CONFIG_AUFS_DLGT + {Opt_dlgt, "dlgt"}, + {Opt_nodlgt, "nodlgt"}, + + {Opt_dirperm1, "dirperm1"}, + {Opt_nodirperm1, "nodirperm1"}, +#endif + +#ifdef CONFIG_AUFS_SHWH + {Opt_shwh, "shwh"}, + {Opt_noshwh, "noshwh"}, +#endif + + {Opt_rendir, "rendir=%d"}, + {Opt_rendir, "rendir:%d"}, + + {Opt_refrof, "refrof"}, + {Opt_norefrof, "norefrof"}, + + {Opt_verbose, "verbose"}, + {Opt_verbose, "v"}, + {Opt_noverbose, "noverbose"}, + {Opt_noverbose, "quiet"}, + {Opt_noverbose, "q"}, + {Opt_noverbose, "silent"}, + + {Opt_rdcache, "rdcache=%d"}, + {Opt_rdcache, "rdcache:%d"}, + + {Opt_coo, "coo=%s"}, + + {Opt_wbr_create, "create=%s"}, + {Opt_wbr_create, "create:%s"}, + {Opt_wbr_create, "create_policy=%s"}, + {Opt_wbr_create, "create_policy:%s"}, + {Opt_wbr_copyup, "cpup=%s"}, + {Opt_wbr_copyup, "cpup:%s"}, + {Opt_wbr_copyup, "copyup=%s"}, + {Opt_wbr_copyup, "copyup:%s"}, + {Opt_wbr_copyup, "copyup_policy=%s"}, + {Opt_wbr_copyup, "copyup_policy:%s"}, + + /* internal use for the scripts */ + {Opt_ignore_silent, "si=%s"}, + +#if 0 /* reserved for future use */ + {Opt_deblk, "deblk=%d"}, + {Opt_deblk, "deblk:%d"}, + {Opt_nhash, "nhash=%d"}, + {Opt_nhash, "nhash:%d"}, +#endif + + {Opt_br, "dirs=%s"}, + {Opt_ignore, "debug=%d"}, + {Opt_ignore, "delete=whiteout"}, + {Opt_ignore, "delete=all"}, + {Opt_ignore, "imap=%s"}, + + {Opt_err, NULL} +}; + +/* ---------------------------------------------------------------------- */ + +static const char *au_parser_pattern(int val, struct match_token *token) +{ + while (token->pattern) { + if (token->token == val) + return token->pattern; + token++; + } + BUG(); + return "??"; +} + +/* ---------------------------------------------------------------------- */ + +#define RW "rw" +#define RO "ro" +#define WH "wh" +#define RR "rr" +#define NoLinkWH "nolwh" + +static match_table_t brperms = { + {AuBrPerm_RR, RR}, + {AuBrPerm_RO, RO}, + {AuBrPerm_RW, RW}, + + {AuBrPerm_RRWH, RR "+" WH}, + {AuBrPerm_ROWH, RO "+" WH}, + {AuBrPerm_RWNoLinkWH, RW "+" NoLinkWH}, + + {AuBrPerm_ROWH, "nfsro"}, + {AuBrPerm_RO, NULL} +}; + +static noinline_for_stack int br_perm_val(char *perm) +{ + int val; + substring_t args[MAX_OPT_ARGS]; + + AuDebugOn(!perm || !*perm); + LKTRTrace("perm %s\n", perm); + val = match_token(perm, brperms, args); + AuTraceErr(val); + return val; +} + +const char *au_optstr_br_perm(int brperm) +{ + return au_parser_pattern(brperm, (void *)brperms); +} + +/* ---------------------------------------------------------------------- */ + +static match_table_t udbalevel = { + {AuOpt_UDBA_REVAL, "reval"}, +#ifdef CONFIG_AUFS_HINOTIFY + {AuOpt_UDBA_INOTIFY, "inotify"}, +#endif + {AuOpt_UDBA_NONE, "none"}, + {-1, NULL} +}; + +static noinline_for_stack int udba_val(char *str) +{ + substring_t args[MAX_OPT_ARGS]; + return match_token(str, udbalevel, args); +} + +const char *au_optstr_udba(int udba) +{ + return au_parser_pattern(udba, (void *)udbalevel); +} + +/* ---------------------------------------------------------------------- */ + +static match_table_t coolevel = { + {AuOpt_COO_NONE, "none"}, + {AuOpt_COO_LEAF, "leaf"}, + {AuOpt_COO_ALL, "all"}, + {-1, NULL} +}; + +static noinline_for_stack int coo_val(char *str) +{ + substring_t args[MAX_OPT_ARGS]; + return match_token(str, coolevel, args); +} + +const char *au_optstr_coo(int coo) +{ + return au_parser_pattern(coo, (void *)coolevel); +} + +/* ---------------------------------------------------------------------- */ + +static match_table_t au_wbr_create_policy = { + {AuWbrCreate_TDP, "tdp"}, + {AuWbrCreate_TDP, "top-down-parent"}, + {AuWbrCreate_RR, "rr"}, + {AuWbrCreate_RR, "round-robin"}, + {AuWbrCreate_MFS, "mfs"}, + {AuWbrCreate_MFS, "most-free-space"}, + {AuWbrCreate_MFSV, "mfs:%d"}, + {AuWbrCreate_MFSV, "most-free-space:%d"}, + + {AuWbrCreate_MFSRR, "mfsrr:%d"}, + {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"}, + {AuWbrCreate_PMFS, "pmfs"}, + {AuWbrCreate_PMFSV, "pmfs:%d"}, + + {-1, NULL} +}; + +/* cf. linux/lib/parser.c */ +static int au_match_ull(substring_t *s, unsigned long long *result, int base) +{ + char *endp; + char *buf; + int ret; + + buf = kmalloc(s->to - s->from + 1, GFP_NOFS); + if (!buf) + return -ENOMEM; + memcpy(buf, s->from, s->to - s->from); + buf[s->to - s->from] = '\0'; + *result = simple_strtoull(buf, &endp, base); + ret = 0; + if (endp == buf) + ret = -EINVAL; + kfree(buf); + return ret; +} + +static int au_wbr_mfs_wmark(substring_t *arg, char *str, + struct au_opt_wbr_create *create) +{ + int err; + unsigned long long ull; + + err = 0; + if (!au_match_ull(arg, &ull, 0)) + create->mfsrr_watermark = ull; + else { + AuErr("bad integer in %s\n", str); + err = -EINVAL; + } + + AuTraceErr(err); + return err; +} + +static int au_wbr_mfs_sec(substring_t *arg, char *str, + struct au_opt_wbr_create *create) +{ + int n, err; + + err = 0; + if (!match_int(arg, &n) && 0 <= n) + create->mfs_second = n; + else { + AuErr("bad integer in %s\n", str); + err = -EINVAL; + } + + AuTraceErr(err); + return err; +} + +static noinline_for_stack +int au_wbr_create_val(char *str, struct au_opt_wbr_create *create) +{ + int err, e; + substring_t args[MAX_OPT_ARGS]; + + err = match_token(str, au_wbr_create_policy, args); + create->wbr_create = err; + switch (err) { + case AuWbrCreate_MFSRRV: + e = au_wbr_mfs_wmark(&args[0], str, create); + if (!e) + e = au_wbr_mfs_sec(&args[1], str, create); + if (unlikely(e)) + err = e; + break; + case AuWbrCreate_MFSRR: + e = au_wbr_mfs_wmark(&args[0], str, create); + if (unlikely(e)) { + err = e; + break; + } + /*FALLTHROUGH*/ + case AuWbrCreate_MFS: + case AuWbrCreate_PMFS: + create->mfs_second = AUFS_MFS_SECOND_DEF; + break; + case AuWbrCreate_MFSV: + case AuWbrCreate_PMFSV: + e = au_wbr_mfs_sec(&args[0], str, create); + if (unlikely(e)) + err = e; + break; + } + + return err; +} + +const char *au_optstr_wbr_create(int wbr_create) +{ + return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy); +} + +static match_table_t au_wbr_copyup_policy = { + {AuWbrCopyup_TDP, "tdp"}, + {AuWbrCopyup_TDP, "top-down-parent"}, + {AuWbrCopyup_BUP, "bup"}, + {AuWbrCopyup_BUP, "bottom-up-parent"}, + {AuWbrCopyup_BU, "bu"}, + {AuWbrCopyup_BU, "bottom-up"}, + {-1, NULL} +}; + +static noinline_for_stack int au_wbr_copyup_val(char *str) +{ + substring_t args[MAX_OPT_ARGS]; + return match_token(str, au_wbr_copyup_policy, args); +} + +const char *au_optstr_wbr_copyup(int wbr_copyup) +{ + return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy); +} + +/* ---------------------------------------------------------------------- */ + +static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; + +static void dump_opts(struct au_opts *opts) +{ +#ifdef CONFIG_AUFS_DEBUG + /* reduce stack space */ + union { + struct au_opt_add *add; + struct au_opt_del *del; + struct au_opt_mod *mod; + struct au_opt_xino *xino; + struct au_opt_xinodir *xinodir; + struct au_opt_xino_itrunc *xino_itrunc; + struct au_opt_wbr_create *create; + } u; + struct au_opt *opt; + + AuTraceEnter(); + + opt = opts->opt; + while (/* opt < opts_tail && */ opt->type != Opt_tail) { + switch (opt->type) { + case Opt_add: + u.add = &opt->add; + LKTRTrace("add {b%d, %s, 0x%x, %p}\n", + u.add->bindex, u.add->path, u.add->perm, + u.add->nd.path.dentry); + break; + case Opt_del: + case Opt_idel: + u.del = &opt->del; + LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root); + break; + case Opt_mod: + case Opt_imod: + u.mod = &opt->mod; + LKTRTrace("mod {%s, 0x%x, %p}\n", + u.mod->path, u.mod->perm, u.mod->h_root); + break; + case Opt_append: + u.add = &opt->add; + LKTRTrace("append {b%d, %s, 0x%x, %p}\n", + u.add->bindex, u.add->path, u.add->perm, + u.add->nd.path.dentry); + break; + case Opt_prepend: + u.add = &opt->add; + LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n", + u.add->bindex, u.add->path, u.add->perm, + u.add->nd.path.dentry); + break; + case Opt_dirwh: + LKTRTrace("dirwh %d\n", opt->dirwh); + break; + case Opt_rdcache: + LKTRTrace("rdcache %d\n", opt->rdcache); + break; + case Opt_xino: + u.xino = &opt->xino; + LKTRTrace("xino {%s %.*s}\n", + u.xino->path, + AuDLNPair(u.xino->file->f_dentry)); + break; + case Opt_xinodir: + u.xinodir = &opt->xinodir; + LKTRTrace("xinodir {%s %.*s}\n", + u.xinodir->name, + AuDLNPair(u.xinodir->path.dentry)); + break; + case Opt_trunc_xino: + LKTRLabel(trunc_xino); + break; + case Opt_notrunc_xino: + LKTRLabel(notrunc_xino); + break; + case Opt_trunc_xino_path: + case Opt_itrunc_xino: + u.xino_itrunc = &opt->xino_itrunc; + LKTRTrace("trunc_xino %d\n", u.xino_itrunc->bindex); + break; + + case Opt_noxino: + LKTRLabel(noxino); + break; + case Opt_trunc_xib: + LKTRLabel(trunc_xib); + break; + case Opt_notrunc_xib: + LKTRLabel(notrunc_xib); + break; + case Opt_dirperm1: + LKTRLabel(dirperm1); + break; + case Opt_nodirperm1: + LKTRLabel(nodirperm1); + break; + case Opt_shwh: + LKTRLabel(shwh); + break; + case Opt_noshwh: + LKTRLabel(noshwh); + break; + case Opt_plink: + LKTRLabel(plink); + break; + case Opt_noplink: + LKTRLabel(noplink); + break; + case Opt_list_plink: + LKTRLabel(list_plink); + break; + case Opt_clean_plink: + LKTRLabel(clean_plink); + break; + case Opt_udba: + LKTRTrace("udba %d, %s\n", + opt->udba, au_optstr_udba(opt->udba)); + break; + case Opt_diropq_a: + LKTRLabel(diropq_a); + break; + case Opt_diropq_w: + LKTRLabel(diropq_w); + break; + case Opt_warn_perm: + LKTRLabel(warn_perm); + break; + case Opt_nowarn_perm: + LKTRLabel(nowarn_perm); + break; + case Opt_dlgt: + LKTRLabel(dlgt); + break; + case Opt_nodlgt: + LKTRLabel(nodlgt); + break; + case Opt_refrof: + LKTRLabel(refrof); + break; + case Opt_norefrof: + LKTRLabel(norefrof); + break; + case Opt_verbose: + LKTRLabel(verbose); + break; + case Opt_noverbose: + LKTRLabel(noverbose); + break; + case Opt_coo: + LKTRTrace("coo %d, %s\n", + opt->coo, au_optstr_coo(opt->coo)); + break; + case Opt_wbr_create: + u.create = &opt->wbr_create; + LKTRTrace("create %d, %s\n", u.create->wbr_create, + au_optstr_wbr_create(u.create->wbr_create)); + switch (u.create->wbr_create) { + case AuWbrCreate_MFSV: + case AuWbrCreate_PMFSV: + LKTRTrace("%d sec\n", u.create->mfs_second); + break; + case AuWbrCreate_MFSRR: + LKTRTrace("%llu watermark\n", + u.create->mfsrr_watermark); + break; + case AuWbrCreate_MFSRRV: + LKTRTrace("%llu watermark, %d sec\n", + u.create->mfsrr_watermark, + u.create->mfs_second); + break; + } + break; + case Opt_wbr_copyup: + LKTRTrace("copyup %d, %s\n", opt->wbr_copyup, + au_optstr_wbr_copyup(opt->wbr_copyup)); + break; + default: + BUG(); + } + opt++; + } +#endif +} + +void au_opts_free(struct au_opts *opts) +{ + struct au_opt *opt; + + AuTraceEnter(); + + opt = opts->opt; + while (opt->type != Opt_tail) { + switch (opt->type) { + case Opt_add: + case Opt_append: + case Opt_prepend: + path_put(&opt->add.nd.path); + break; + case Opt_del: + case Opt_idel: + dput(opt->del.h_root); + break; + case Opt_mod: + case Opt_imod: + dput(opt->mod.h_root); + break; + case Opt_xino: + fput(opt->xino.file); + break; + case Opt_xinodir: + path_put(&opt->xinodir.path); + break; + } + opt++; + } +} + +static int opt_add(struct au_opt *opt, char *opt_str, struct super_block *sb, + aufs_bindex_t bindex) +{ + int err; + struct au_opt_add *add = &opt->add; + char *p; + + LKTRTrace("%s, b%d\n", opt_str, bindex); + + add->bindex = bindex; + add->perm = AuBrPerm_Last; + add->path = opt_str; + p = strchr(opt_str, '='); + if (unlikely(p)) { + *p++ = 0; + if (*p) + add->perm = br_perm_val(p); + } + + /* LSM may detect it */ + /* do not superio. */ + err = vfsub_path_lookup(add->path, lkup_dirflags, &add->nd); + if (!err) { + if (!p /* && add->perm == AuBrPerm_Last */) { + add->perm = AuBrPerm_RO; + if (au_test_def_rr(add->nd.path.dentry->d_sb)) + add->perm = AuBrPerm_RR; + if (!bindex && !(sb->s_flags & MS_RDONLY)) + add->perm = AuBrPerm_RW; +#ifdef CONFIG_AUFS_COMPAT + add->perm = AuBrPerm_RW; +#endif + } + opt->type = Opt_add; + goto out; + } + AuErr("lookup failed %s (%d)\n", add->path, err); + err = -EINVAL; + + out: + AuTraceErr(err); + return err; +} + +/* called without aufs lock */ +int au_opts_parse(struct super_block *sb, unsigned long flags, char *str, + struct au_opts *opts) +{ + int err, n, token; + struct dentry *root; + struct au_opt *opt, *opt_tail; + char *opt_str, *p; + aufs_bindex_t bindex, bend; + unsigned char skipped; + union { + struct au_opt_del *del; + struct au_opt_mod *mod; + struct au_opt_xino *xino; + struct au_opt_xinodir *xinodir; + struct au_opt_xino_itrunc *xino_itrunc; + struct au_opt_wbr_create *create; + } u; + struct file *file; + /* reduce the stack space */ + struct { + substring_t args[MAX_OPT_ARGS]; + struct nameidata nd; + } *a; + + LKTRTrace("%s, nopts %d\n", str, opts->max_opt); + + err = -ENOMEM; + a = kmalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + root = sb->s_root; + err = 0; + bindex = 0; + opt = opts->opt; + opt_tail = opt + opts->max_opt - 1; + opt->type = Opt_tail; + while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { + err = -EINVAL; + token = match_token(opt_str, options, a->args); + LKTRTrace("%s, token %d, a->args[0]{%p, %p}\n", + opt_str, token, a->args[0].from, a->args[0].to); + + skipped = 0; + switch (token) { + case Opt_br: + err = 0; + while (!err && (opt_str = strsep(&a->args[0].from, ":")) + && *opt_str) { + err = opt_add(opt, opt_str, sb, bindex++); + if (unlikely(!err && ++opt > opt_tail)) { + err = -E2BIG; + break; + } + opt->type = Opt_tail; + skipped = 1; + } + break; + case Opt_add: + if (unlikely(match_int(&a->args[0], &n))) { + AuErr("bad integer in %s\n", opt_str); + break; + } + bindex = n; + err = opt_add(opt, a->args[1].from, sb, bindex); + break; + case Opt_append: + err = opt_add(opt, a->args[0].from, sb, + /*dummy bindex*/1); + if (!err) + opt->type = token; + break; + case Opt_prepend: + err = opt_add(opt, a->args[0].from, sb, /*bindex*/0); + if (!err) + opt->type = token; + break; + case Opt_del: + u.del = &opt->del; + u.del->path = a->args[0].from; + LKTRTrace("del path %s\n", u.del->path); + /* LSM may detect it */ + /* do not superio. */ + err = vfsub_path_lookup(u.del->path, lkup_dirflags, + &a->nd); + if (unlikely(err)) { + AuErr("lookup failed %s (%d)\n", + u.del->path, err); + break; + } + u.del->h_root = dget(a->nd.path.dentry); + path_put(&a->nd.path); + opt->type = token; + break; +#if 0 /* reserved for future use */ + case Opt_idel: + u.del = &opt->del; + u.del->path = "(indexed)"; + if (unlikely(match_int(&a->args[0], &n))) { + AuErr("bad integer in %s\n", opt_str); + break; + } + bindex = n; + aufs_read_lock(root, AuLock_FLUSH); + if (bindex < 0 || au_sbend(sb) < bindex) { + AuErr("out of bounds, %d\n", bindex); + aufs_read_unlock(root, !AuLock_IR); + break; + } + err = 0; + u.del->h_root = dget(au_h_dptr(root, bindex)); + opt->type = token; + aufs_read_unlock(root, !AuLock_IR); + break; +#endif + case Opt_mod: + u.mod = &opt->mod; + u.mod->path = a->args[0].from; + p = strchr(u.mod->path, '='); + if (unlikely(!p)) { + AuErr("no permssion %s\n", opt_str); + break; + } + *p++ = 0; + u.mod->perm = br_perm_val(p); + LKTRTrace("mod path %s, perm 0x%x, %s\n", + u.mod->path, u.mod->perm, p); + /* LSM may detect it */ + /* do not superio. */ + err = vfsub_path_lookup(u.mod->path, lkup_dirflags, + &a->nd); + if (unlikely(err)) { + AuErr("lookup failed %s (%d)\n", + u.mod->path, err); + break; + } + u.mod->h_root = dget(a->nd.path.dentry); + path_put(&a->nd.path); + opt->type = token; + break; +#ifdef IMOD /* reserved for future use */ + case Opt_imod: + u.mod = &opt->mod; + u.mod->path = "(indexed)"; + if (unlikely(match_int(&a->args[0], &n))) { + AuErr("bad integer in %s\n", opt_str); + break; + } + bindex = n; + aufs_read_lock(root, AuLock_FLUSH); + if (bindex < 0 || au_sbend(sb) < bindex) { + AuErr("out of bounds, %d\n", bindex); + aufs_read_unlock(root, !AuLock_IR); + break; + } + u.mod->perm = br_perm_val(a->args[1].from); + LKTRTrace("mod path %s, perm 0x%x, %s\n", + u.mod->path, u.mod->perm, a->args[1].from); + err = 0; + u.mod->h_root = dget(au_h_dptr(root, bindex)); + opt->type = token; + aufs_read_unlock(root, !AuLock_IR); + break; +#endif + case Opt_xino: + u.xino = &opt->xino; + file = au_xino_create(sb, a->args[0].from, /*silent*/0); + err = PTR_ERR(file); + if (IS_ERR(file)) + break; + err = -EINVAL; + if (unlikely(file->f_dentry->d_sb == sb)) { + fput(file); + AuErr("%s must be outside\n", a->args[0].from); + break; + } + err = 0; + u.xino->file = file; + u.xino->path = a->args[0].from; + opt->type = token; + break; + +#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */ + case Opt_xinodir: + u.xinodir = &opt->xinodir; + u.xinodir->name = a->args[0].from; + err = vfsub_path_lookup(u.xinodir->name, lkup_dirflags, + &a->nd); + if (unlikely(err)) { + AuErr("lookup failed %s (%d)\n", + u.xinodir->name, err); + break; + } + u.xinodir->path = a->nd.path; + /* do not path_put() */ + opt->type = token; + break; +#endif + + case Opt_trunc_xino_path: + u.xino_itrunc = &opt->xino_itrunc; + p = a->args[0].from; + LKTRTrace("trunc_xino path %s\n", p); + /* LSM may detect it */ + /* do not superio. */ + err = vfsub_path_lookup(p, lkup_dirflags, &a->nd); + if (unlikely(err)) { + AuErr("lookup failed %s (%d)\n", p , err); + break; + } + u.xino_itrunc->bindex = -1; + aufs_read_lock(root, AuLock_FLUSH); + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) { + if (au_h_dptr(root, bindex) + == a->nd.path.dentry) { + u.xino_itrunc->bindex = bindex; + break; + } + } + aufs_read_unlock(root, !AuLock_IR); + path_put(&a->nd.path); + if (unlikely(u.xino_itrunc->bindex < 0)) { + AuErr("no such branch %s\n", p); + err = -EINVAL; + break; + } + opt->type = token; + break; + + case Opt_itrunc_xino: + u.xino_itrunc = &opt->xino_itrunc; + if (unlikely(match_int(&a->args[0], &n))) { + AuErr("bad integer in %s\n", opt_str); + break; + } + u.xino_itrunc->bindex = n; + aufs_read_lock(root, AuLock_FLUSH); + if (n < 0 || au_sbend(sb) < n) { + AuErr("out of bounds, %d\n", n); + aufs_read_unlock(root, !AuLock_IR); + break; + } + aufs_read_unlock(root, !AuLock_IR); + err = 0; + opt->type = token; + break; + + case Opt_dirwh: + if (unlikely(match_int(&a->args[0], &opt->dirwh))) + break; + err = 0; + opt->type = token; + break; + + case Opt_rdcache: + if (unlikely(match_int(&a->args[0], &opt->rdcache))) + break; + err = 0; + opt->type = token; + break; + + case Opt_shwh: + if (flags & MS_RDONLY) { + err = 0; + opt->type = token; + } else + AuErr("shwh requires ro\n"); + break; + + case Opt_trunc_xino: + case Opt_notrunc_xino: + case Opt_noxino: + case Opt_trunc_xib: + case Opt_notrunc_xib: + case Opt_dirperm1: + case Opt_nodirperm1: + case Opt_noshwh: + case Opt_plink: + case Opt_noplink: + case Opt_list_plink: + case Opt_clean_plink: + case Opt_diropq_a: + case Opt_diropq_w: + case Opt_warn_perm: + case Opt_nowarn_perm: + case Opt_dlgt: + case Opt_nodlgt: + case Opt_refrof: + case Opt_norefrof: + case Opt_verbose: + case Opt_noverbose: + err = 0; + opt->type = token; + break; + + case Opt_udba: + opt->udba = udba_val(a->args[0].from); + if (opt->udba >= 0) { + err = 0; + opt->type = token; + } else + AuErr("wrong value, %s\n", opt_str); + break; + + case Opt_wbr_create: + u.create = &opt->wbr_create; + u.create->wbr_create + = au_wbr_create_val(a->args[0].from, u.create); + if (u.create->wbr_create >= 0) { + err = 0; + opt->type = token; + } else + AuErr("wrong value, %s\n", opt_str); + break; + case Opt_wbr_copyup: + opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); + if (opt->wbr_copyup >= 0) { + err = 0; + opt->type = token; + } else + AuErr("wrong value, %s\n", opt_str); + break; + + case Opt_coo: + opt->coo = coo_val(a->args[0].from); + if (opt->coo >= 0) { + err = 0; + opt->type = token; + } else + AuErr("wrong value, %s\n", opt_str); + break; + + case Opt_ignore: +#ifndef CONFIG_AUFS_COMPAT + AuWarn("ignored %s\n", opt_str); +#endif + case Opt_ignore_silent: + skipped = 1; + err = 0; + break; + case Opt_err: + AuErr("unknown option %s\n", opt_str); + break; + } + + if (!err && !skipped) { + if (unlikely(++opt > opt_tail)) { + err = -E2BIG; + opt--; + opt->type = Opt_tail; + break; + } + opt->type = Opt_tail; + } + } + + kfree(a); + dump_opts(opts); + if (unlikely(err)) + au_opts_free(opts); + + out: + AuTraceErr(err); + return err; +} + +/* + * returns, + * plus: processed without an error + * zero: unprocessed + */ +static int au_opt_simple(struct super_block *sb, struct au_opt *opt, + struct au_opts *opts) +{ + int err; + struct au_sbinfo *sbinfo; + struct au_opt_wbr_create *create; + + AuTraceEnter(); + + err = 1; /* handled */ + sbinfo = au_sbi(sb); + switch (opt->type) { + case Opt_udba: + sbinfo->si_mntflags &= ~AuOptMask_UDBA; + sbinfo->si_mntflags |= opt->udba; + opts->given_udba |= opt->udba; + break; + + case Opt_plink: + au_opt_set(sbinfo->si_mntflags, PLINK); + break; + case Opt_noplink: + if (au_opt_test(sbinfo->si_mntflags, PLINK)) + au_plink_put(sb); + au_opt_clr(sbinfo->si_mntflags, PLINK); + break; + case Opt_list_plink: + if (au_opt_test(sbinfo->si_mntflags, PLINK)) + au_plink_list(sb); + break; + case Opt_clean_plink: + if (au_opt_test(sbinfo->si_mntflags, PLINK)) + au_plink_put(sb); + break; + + case Opt_diropq_a: + au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); + break; + case Opt_diropq_w: + au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); + break; + + case Opt_dlgt: + au_opt_set(sbinfo->si_mntflags, DLGT); + break; + case Opt_nodlgt: + au_opt_clr(sbinfo->si_mntflags, DLGT); + break; + + case Opt_warn_perm: + au_opt_set(sbinfo->si_mntflags, WARN_PERM); + break; + case Opt_nowarn_perm: + au_opt_clr(sbinfo->si_mntflags, WARN_PERM); + break; + + case Opt_refrof: + au_opt_set(sbinfo->si_mntflags, REFROF); + break; + case Opt_norefrof: + /* au_opt_set(sbinfo->si_mntflags, COO_LEAF); */ + au_opt_clr(sbinfo->si_mntflags, REFROF); + break; + + case Opt_verbose: + au_opt_set(sbinfo->si_mntflags, VERBOSE); + break; + case Opt_noverbose: + au_opt_clr(sbinfo->si_mntflags, VERBOSE); + break; + + case Opt_wbr_create: + create = &opt->wbr_create; + if (sbinfo->si_wbr_create_ops->fin) { + err = sbinfo->si_wbr_create_ops->fin(sb); + if (!err) + err = 1; + } + sbinfo->si_wbr_create = create->wbr_create; + sbinfo->si_wbr_create_ops + = au_wbr_create_ops + create->wbr_create; + switch (create->wbr_create) { + case AuWbrCreate_MFSRRV: + case AuWbrCreate_MFSRR: + sbinfo->si_wbr_mfs.mfsrr_watermark + = create->mfsrr_watermark; + /*FALLTHROUGH*/ + case AuWbrCreate_MFS: + case AuWbrCreate_MFSV: + case AuWbrCreate_PMFS: + case AuWbrCreate_PMFSV: + sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ; + break; + } + if (sbinfo->si_wbr_create_ops->init) + sbinfo->si_wbr_create_ops->init(sb); /* ignore */ + break; + case Opt_wbr_copyup: + sbinfo->si_wbr_copyup = opt->wbr_copyup; + sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; + break; + + case Opt_coo: + sbinfo->si_mntflags &= ~AuOptMask_COO; + sbinfo->si_mntflags |= opt->coo; + break; + + case Opt_dirwh: + sbinfo->si_dirwh = opt->dirwh; + break; + + case Opt_rdcache: + sbinfo->si_rdcache = opt->rdcache * HZ; + break; + + case Opt_trunc_xino: + au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); + break; + case Opt_notrunc_xino: + au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); + break; + + case Opt_dirperm1: + au_opt_set(sbinfo->si_mntflags, DIRPERM1); + break; + case Opt_nodirperm1: + au_opt_clr(sbinfo->si_mntflags, DIRPERM1); + break; + + case Opt_shwh: + au_opt_set(sbinfo->si_mntflags, SHWH); + break; + case Opt_noshwh: + au_opt_clr(sbinfo->si_mntflags, SHWH); + break; + + case Opt_trunc_xino_path: + case Opt_itrunc_xino: + err = au_xino_trunc(sb, opt->xino_itrunc.bindex); + if (!err) + err = 1; + break; + + case Opt_trunc_xib: + au_fset_opts(opts->flags, TRUNC_XIB); + break; + case Opt_notrunc_xib: + au_fclr_opts(opts->flags, TRUNC_XIB); + break; + + default: + err = 0; + break; + } + + AuTraceErr(err); + return err; +} + +/* + * returns tri-state. + * plus: processed without an error + * zero: unprocessed + * minus: error + */ +static int au_opt_br(struct super_block *sb, struct au_opt *opt, + struct au_opts *opts) +{ + int err, do_refresh; + + AuTraceEnter(); + + err = 0; + switch (opt->type) { + case Opt_append: + opt->add.bindex = au_sbend(sb) + 1; + if (unlikely(opt->add.bindex < 0)) + opt->add.bindex = 0; + goto add; + case Opt_prepend: + opt->add.bindex = 0; + add: + case Opt_add: + err = au_br_add(sb, &opt->add, + au_ftest_opts(opts->flags, REMOUNT)); + if (!err) { + err = 1; + au_fset_opts(opts->flags, REFRESH_DIR); + if (unlikely(au_br_whable(opt->add.perm))) + au_fset_opts(opts->flags, REFRESH_NONDIR); + } + break; + + case Opt_del: + case Opt_idel: + err = au_br_del(sb, &opt->del, + au_ftest_opts(opts->flags, REMOUNT)); + if (!err) { + err = 1; + au_fset_opts(opts->flags, TRUNC_XIB); + au_fset_opts(opts->flags, REFRESH_DIR); + au_fset_opts(opts->flags, REFRESH_NONDIR); + } + break; + + case Opt_mod: + case Opt_imod: + err = au_br_mod(sb, &opt->mod, + au_ftest_opts(opts->flags, REMOUNT), + &do_refresh); + if (!err) { + err = 1; + if (unlikely(do_refresh)) { + au_fset_opts(opts->flags, REFRESH_DIR); + au_fset_opts(opts->flags, REFRESH_NONDIR); + } + } + break; + } + + AuTraceErr(err); + return err; +} + +static int au_opt_xino(struct super_block *sb, struct au_opt *opt, + struct au_opt_xino **opt_xino, + struct au_opt_xinodir **opt_xinodir, + struct au_opts *opts) +{ + int err; + const int remount = !!au_ftest_opts(opts->flags, REMOUNT); + + AuTraceEnter(); + + err = 0; + switch (opt->type) { + case Opt_xino: + err = au_xino_set(sb, &opt->xino, remount); + if (!err) + *opt_xino = &opt->xino; + break; +#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */ + case Opt_xinodir: + err = au_xinodir_set(sb, &opt->xinodir, remount); + if (!err) + *opt_xinodir = &opt->xinodir; + break; +#endif + case Opt_noxino: + au_xino_clr(sb); + *opt_xino = (void *)-1; + break; + } + + AuTraceErr(err); + return err; +} + +static int verify_opts(struct super_block *sb, unsigned int pending, + int remount) +{ + int err; + aufs_bindex_t bindex, bend; + unsigned char do_plink, skip, do_free; + struct au_branch *br; + struct au_wbr *wbr; + struct dentry *root; + struct inode *dir, *h_dir; + unsigned int mnt_flags; + + AuTraceEnter(); + mnt_flags = au_mntflags(sb); + AuDebugOn(!(mnt_flags & AuOptMask_COO)); + AuDebugOn(!(mnt_flags & AuOptMask_UDBA)); + + if (!(sb->s_flags & MS_RDONLY)) { + if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) + AuWarn("first branch should be rw\n"); + if (unlikely(au_opt_test(mnt_flags, SHWH))) + AuWarn("shwh should be used with ro\n"); + } + + if (unlikely(au_opt_test((mnt_flags | pending), UDBA_INOTIFY) + && !au_opt_test_xino(mnt_flags))) + AuWarn("udba=inotify requires xino\n"); + + err = 0; + root = sb->s_root; + dir = sb->s_root->d_inode; + do_plink = !!au_opt_test(mnt_flags, PLINK); + bend = au_sbend(sb); + for (bindex = 0; !err && bindex <= bend; bindex++) { + skip = 0; + h_dir = au_h_iptr(dir, bindex); + br = au_sbr(sb, bindex); + do_free = 0; + wbr = br->br_wbr; + if (wbr) + wbr_wh_read_lock(wbr); + switch (br->br_perm) { + case AuBrPerm_RR: + case AuBrPerm_RO: + case AuBrPerm_RRWH: + case AuBrPerm_ROWH: + do_free = !!wbr; + skip = (!wbr + || (!wbr->wbr_whbase + && !wbr->wbr_plink + && !wbr->wbr_tmp)); + break; + + case AuBrPerm_RWNoLinkWH: + /* skip = (!br->br_whbase && !br->br_tmp); */ + skip = (!wbr || !wbr->wbr_whbase); + if (skip && wbr) { + if (do_plink) + skip = !!wbr->wbr_plink; + else + skip = !wbr->wbr_plink; + } + break; + + case AuBrPerm_RW: + /* skip = (br->br_whbase && br->br_tmp); */ + skip = (wbr && wbr->wbr_whbase); + if (skip) { + if (do_plink) + skip = !!wbr->wbr_plink; + else + skip = !wbr->wbr_plink; + } + break; + + default: + BUG(); + } + if (wbr) + wbr_wh_read_unlock(wbr); + + if (skip) + continue; + + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + if (wbr) + wbr_wh_write_lock(wbr); + err = au_wh_init(au_h_dptr(root, bindex), br, + au_nfsmnt(sb, bindex), sb, bindex); + if (wbr) + wbr_wh_write_unlock(wbr); + mutex_unlock(&h_dir->i_mutex); + + if (!err && do_free) { + kfree(wbr); + br->br_wbr = NULL; + } + } + + AuTraceErr(err); + return err; +} + +int au_opts_mount(struct super_block *sb, struct au_opts *opts) +{ + int err; + struct inode *dir; + struct au_opt *opt; + struct au_opt_xino *opt_xino, xino; + struct au_opt_xinodir *opt_xinodir; + aufs_bindex_t bend; + struct au_sbinfo *sbinfo; + unsigned int tmp; + struct au_branch *br; + + AuTraceEnter(); + SiMustWriteLock(sb); + DiMustWriteLock(sb->s_root); + dir = sb->s_root->d_inode; + IiMustWriteLock(dir); + + err = 0; + opt_xino = NULL; + opt_xinodir = NULL; + opt = opts->opt; + while (err >= 0 && opt->type != Opt_tail) + err = au_opt_simple(sb, opt++, opts); + if (err > 0) + err = 0; + else if (unlikely(err < 0)) + goto out; + + /* disable xino, xinodir, hinotify, dlgt temporary */ + sbinfo = au_sbi(sb); + tmp = sbinfo->si_mntflags; + au_opt_clr(sbinfo->si_mntflags, XINO); + au_opt_clr(sbinfo->si_mntflags, XINODIR); + au_opt_clr(sbinfo->si_mntflags, DLGT); + au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); + + opt = opts->opt; + while (err >= 0 && opt->type != Opt_tail) + err = au_opt_br(sb, opt++, opts); + if (err > 0) + err = 0; + else if (unlikely(err < 0)) + goto out; + + bend = au_sbend(sb); + if (unlikely(bend < 0)) { + err = -EINVAL; + AuErr("no branches\n"); + goto out; + } + + if (au_opt_test(tmp, XINO)) + au_opt_set(sbinfo->si_mntflags, XINO); + else if (au_opt_test(tmp, XINODIR)) + au_opt_set(sbinfo->si_mntflags, XINODIR); + opt = opts->opt; + while (!err && opt->type != Opt_tail) + err = au_opt_xino(sb, opt++, &opt_xino, &opt_xinodir, opts); + if (unlikely(err)) + goto out; + + /* todo: test this error case? */ + err = verify_opts(sb, tmp, /*remount*/0); + if (unlikely(err)) + goto out; + + /* enable xino */ + if (au_opt_test(tmp, XINO) && !opt_xino) { + xino.file = au_xino_def(sb); + err = PTR_ERR(xino.file); + if (IS_ERR(xino.file)) + goto out; + + br = au_xino_def_br(sbinfo); + err = au_xino_set(sb, &xino, /*remount*/0); + fput(xino.file); + if (unlikely(err)) + goto out; + au_xino_def_br_set(br, sbinfo); + } + + /* restore hinotify */ + sbinfo->si_mntflags &= ~AuOptMask_UDBA; + sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA); + if (au_opt_test(tmp, UDBA_INOTIFY)) + au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AuHi_XINO); + + /* restore dlgt */ + if (au_opt_test(tmp, DLGT)) + au_opt_set(sbinfo->si_mntflags, DLGT); + + out: + AuTraceErr(err); + return err; +} + +int au_opts_remount(struct super_block *sb, struct au_opts *opts) +{ + int err, rerr; + struct inode *dir; + struct au_opt_xino *opt_xino; + struct au_opt_xinodir *opt_xinodir; + struct au_opt *opt; + unsigned char dlgt; + struct au_sbinfo *sbinfo; + + AuTraceEnter(); + SiMustWriteLock(sb); + DiMustWriteLock(sb->s_root); + dir = sb->s_root->d_inode; + IiMustWriteLock(dir); + sbinfo = au_sbi(sb); + + err = 0; + dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT); + opt_xino = NULL; + opt_xinodir = NULL; + opt = opts->opt; + while (err >= 0 && opt->type != Opt_tail) { + err = au_opt_simple(sb, opt, opts); + + /* disable it temporary */ + dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT); + au_opt_clr(sbinfo->si_mntflags, DLGT); + + if (!err) + err = au_opt_br(sb, opt, opts); + if (!err) + err = au_opt_xino(sb, opt, &opt_xino, &opt_xinodir, + opts); + + /* restore it */ + if (unlikely(dlgt)) + au_opt_set(sbinfo->si_mntflags, DLGT); + opt++; + } + if (err > 0) + err = 0; + AuTraceErr(err); + + /* go on even err */ + + /* todo: test this error case? */ + au_opt_clr(sbinfo->si_mntflags, DLGT); + rerr = verify_opts(sb, sbinfo->si_mntflags, /*remount*/1); + if (unlikely(dlgt)) + au_opt_set(sbinfo->si_mntflags, DLGT); + if (unlikely(rerr && !err)) + err = rerr; + + if (unlikely(au_ftest_opts(opts->flags, TRUNC_XIB))) { + rerr = au_xib_trunc(sb); + if (unlikely(rerr && !err)) + err = rerr; + } + + /* they are handled by the caller */ + if (!au_ftest_opts(opts->flags, REFRESH_DIR) + && (opts->given_udba || au_opt_test_xino(sbinfo->si_mntflags))) + au_fset_opts(opts->flags, REFRESH_DIR); + + LKTRTrace("status 0x%x\n", opts->flags); + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/i_op_add.c +++ linux-2.6.27/ubuntu/aufs/i_op_add.c @@ -0,0 +1,754 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations (add entry) + * + * $Id: i_op_add.c,v 1.14 2008/09/22 03:52:19 sfjro Exp $ + */ + +#include "aufs.h" + +/* + * final procedure of adding a new entry, except link(2). + * remove whiteout, instantiate, copyup the parent dir's times and size + * and update version. + * if it failed, re-create the removed whiteout. + */ +static int epilog(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct dentry *dentry) +{ + int err, rerr; + aufs_bindex_t bwh; + struct inode *inode, *h_dir; + struct dentry *wh; + struct au_ndx ndx; + struct super_block *sb; + + LKTRTrace("wh %p, %.*s\n", wh_dentry, AuDLNPair(dentry)); + + sb = dentry->d_sb; + bwh = -1; + if (wh_dentry) { + h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */ + IMustLock(h_dir); + AuDebugOn(au_h_iptr(dir, bindex) != h_dir); + bwh = au_dbwh(dentry); + err = au_wh_unlink_dentry(au_hi(dir, bindex), wh_dentry, dentry, + /*dlgt*/0); + if (unlikely(err)) + goto out; + } + + inode = au_new_inode(dentry); + if (!IS_ERR(inode)) { + d_instantiate(dentry, inode); + dir = dentry->d_parent->d_inode; /* dir inode is locked */ + IMustLock(dir); + /* or always cpup dir mtime? */ + if (au_ibstart(dir) == au_dbstart(dentry)) + au_cpup_attr_timesizes(dir); + dir->i_version++; + return 0; /* success */ + } + + err = PTR_ERR(inode); + if (!wh_dentry) + goto out; + + /* revert */ + ndx.flags = 0; + if (unlikely(au_test_dlgt(au_mntflags(sb)))) + au_fset_ndx(ndx.flags, DLGT); + ndx.nfsmnt = au_nfsmnt(sb, bwh); + ndx.nd = NULL; + /* ndx.br = NULL; */ + /* dir inode is locked */ + wh = au_wh_create(dentry, bwh, wh_dentry->d_parent, &ndx); + rerr = PTR_ERR(wh); + if (IS_ERR(wh)) { + AuIOErr("%.*s reverting whiteout failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } else { + err = 0; + dput(wh); + } + + out: + AuTraceErr(err); + return err; +} + +/* + * simple tests for the adding inode operations. + * following the checks in vfs, plus the parent-child relationship. + */ +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir, struct au_ndx *ndx) +{ + int err, exist; + struct dentry *h_dentry; + struct inode *h_inode; + umode_t h_mode; + + LKTRTrace("%.*s/%.*s, b%d, dir %d\n", + AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir); + + exist = !!dentry->d_inode; + h_dentry = au_h_dptr(dentry, bindex); + h_inode = h_dentry->d_inode; + if (!exist) { + err = -EEXIST; + if (unlikely(h_inode)) + goto out; + } else { + /* rename(2) case */ + err = -EIO; + if (unlikely(!h_inode || !h_inode->i_nlink)) + goto out; + + h_mode = h_inode->i_mode; + if (!isdir) { + err = -EISDIR; + if (unlikely(S_ISDIR(h_mode))) + goto out; + } else if (unlikely(!S_ISDIR(h_mode))) { + err = -ENOTDIR; + goto out; + } + } + + err = -EIO; + /* expected parent dir is locked */ + if (unlikely(h_parent != h_dentry->d_parent)) + goto out; + err = 0; + + if (unlikely(au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY))) { + struct dentry *h_latest; + struct qstr *qstr = &dentry->d_name; + + err = -EACCES; + if (unlikely(au_test_h_perm + (h_parent->d_inode, MAY_EXEC | MAY_WRITE, + au_ftest_ndx(ndx->flags, DLGT)))) + goto out; + + err = -EIO; + h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len, + ndx); + err = PTR_ERR(h_latest); + if (IS_ERR(h_latest)) + goto out; + err = -EIO; + dput(h_latest); + if (h_latest == h_dentry) + err = 0; + } + + out: + AuTraceErr(err); + return err; +} + +/* + * initial procedure of adding a new entry. + * prepare writable branch and the parent dir, lock it, + * lookup whiteout for the new entry. + */ +static struct dentry* +lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt, + struct dentry *src_dentry, struct au_pin *pin, + struct au_wr_dir_args *wr_dir_args) +{ + struct dentry *wh_dentry, *h_parent; + int err; + aufs_bindex_t bstart, bcpup; + struct au_ndx ndx; + struct super_block *sb; + unsigned int mnt_flags; + + LKTRTrace("%.*s, src %p\n", AuDLNPair(dentry), src_dentry); + + bstart = au_dbstart(dentry); + err = au_wr_dir(dentry, src_dentry, wr_dir_args); + bcpup = err; + wh_dentry = ERR_PTR(err); + if (unlikely(err < 0)) + goto out; + + sb = dentry->d_sb; + mnt_flags = au_mntflags(sb); + err = au_pin(pin, dentry, bcpup, /*di_locked*/1, + /*do_gp*/dt && au_opt_test(mnt_flags, UDBA_INOTIFY)); + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out; + + ndx.nfsmnt = au_nfsmnt(sb, bcpup); + ndx.flags = 0; + if (unlikely(au_test_dlgt(mnt_flags))) + au_fset_ndx(ndx.flags, DLGT); + ndx.nd = NULL; + /* ndx.br = NULL; */ + /* ndx.nd_file = NULL; */ + + h_parent = au_pinned_h_parent(pin, bcpup); + if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) { + struct nameidata nd; + + if (unlikely(ndx.nfsmnt)) { + /* todo: dirty? */ + ndx.nd = &nd; + ndx.br = au_sbr(sb, bcpup); + memset(&nd, 0, sizeof(nd)); + nd.flags = LOOKUP_CREATE; + nd.intent.open.flags = O_EXCL; + } + err = au_may_add(dentry, bcpup, h_parent, + au_ftest_wrdir(wr_dir_args->flags, ISDIR), + &ndx); + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_unpin; + ndx.nd = NULL; + ndx.br = NULL; + } + + if (dt) + au_dtime_store(dt, au_pinned_parent(pin), h_parent, + au_pinned_hdir(pin, bcpup), + au_pinned_hgdir(pin, bcpup)); + + wh_dentry = NULL; + if (/* bcpup != bstart || */ bcpup != au_dbwh(dentry)) + goto out; /* success */ + + wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, &ndx); + + out_unpin: + if (IS_ERR(wh_dentry)) + au_unpin(pin); + out: + AuTraceErrPtr(wh_dentry); + return wh_dentry; +} + +/* ---------------------------------------------------------------------- */ + +enum { Mknod, Symlink, Creat }; +struct simple_arg { + int type; + union { + struct { + int mode; + struct nameidata *nd; + } c; + struct { + const char *symname; + } s; + struct { + int mode; + dev_t dev; + } m; + } u; +}; + +static int add_simple(struct inode *dir, struct dentry *dentry, + struct simple_arg *arg) +{ + int err; + struct dentry *h_dentry, *wh_dentry, *parent; + struct inode *h_dir; + struct au_dtime dt; + struct vfsub_args vargs; + struct super_block *sb; + aufs_bindex_t bstart; + unsigned char created; + struct au_hin_ignore ign; + struct au_pin pin; + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = AuWrDir_ADD_ENTRY + }; + + LKTRTrace("type %d, %.*s\n", arg->type, AuDLNPair(dentry)); + IMustLock(dir); + + sb = dir->i_sb; + parent = dentry->d_parent; /* dir inode is locked */ + aufs_read_lock(dentry, AuLock_DW); + vfsub_args_init(&vargs, &ign, !!au_test_dlgt(au_mntflags(sb)), 0); + di_write_lock_parent(parent); + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin, + &wr_dir_args); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + bstart = au_dbstart(dentry); + h_dentry = au_h_dptr(dentry, bstart); + h_dir = au_pinned_h_dir(&pin); + vfsub_ign_hinode(&vargs, IN_CREATE, au_pinned_hdir(&pin, bstart)); + + switch (arg->type) { + case Creat: + AuDebugOn(au_test_nfs(h_dir->i_sb) && !arg->u.c.nd); + err = au_h_create(h_dir, h_dentry, arg->u.c.mode, &vargs, + arg->u.c.nd, au_nfsmnt(sb, bstart)); + break; + case Symlink: + err = vfsub_symlink(h_dir, h_dentry, arg->u.s.symname, + S_IALLUGO, &vargs); + break; + case Mknod: + err = vfsub_mknod(h_dir, h_dentry, arg->u.m.mode, arg->u.m.dev, + &vargs); + break; + default: + BUG(); + } + created = !err; + if (!err) + err = epilog(dir, bstart, wh_dentry, dentry); + + /* revert */ + if (unlikely(created && err && h_dentry->d_inode)) { + int rerr; + vfsub_args_reinit(&vargs); + vfsub_ign_hinode(&vargs, IN_DELETE, + au_pinned_hdir(&pin, bstart)); + rerr = vfsub_unlink(h_dir, h_dentry, &vargs); + if (rerr) { + AuIOErr("%.*s revert failure(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } + /* todo: inotify will be fired to the grand parent dir? */ + au_dtime_revert(&dt); + d_drop(dentry); + } + + au_unpin(&pin); + dput(wh_dentry); + + out: + if (unlikely(err)) { + au_update_dbstart(dentry); + d_drop(dentry); + } + di_write_unlock(parent); + aufs_read_unlock(dentry, AuLock_DW); + AuTraceErr(err); + return err; +} + +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +{ + struct simple_arg arg = { + .type = Mknod, + .u.m = { + .mode = mode, + .dev = dev + } + }; + return add_simple(dir, dentry, &arg); +} + +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +{ + struct simple_arg arg = { + .type = Symlink, + .u.s.symname = symname + }; + return add_simple(dir, dentry, &arg); +} + +int aufs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + struct simple_arg arg = { + .type = Creat, + .u.c = { + .mode = mode, + .nd = nd + } + }; + return add_simple(dir, dentry, &arg); +} + +/* ---------------------------------------------------------------------- */ + +struct au_link_args { + aufs_bindex_t bdst, bsrc; + struct dentry *h_dentry; + struct dentry *src_parent, *parent; + struct au_pin pin; + struct au_hin_ignore ign; + struct vfsub_args vargs; + unsigned int mnt_flags; +}; + +static int au_cpup_before_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry, struct au_link_args *a) +{ + int err; + struct mutex *h_mtx; + const int hinotify = au_opt_test(a->mnt_flags, UDBA_INOTIFY); + + LKTRTrace("src %.*s, i%lu, dst %.*s\n", + AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry)); + + di_read_lock_parent(a->src_parent, AuLock_IR); + err = au_test_and_cpup_dirs(src_dentry, a->bdst); + if (unlikely(err)) + goto out; + + AuDebugOn(au_dbstart(src_dentry) != a->bsrc); + h_mtx = &au_h_dptr(src_dentry, a->bsrc)->d_inode->i_mutex; + err = au_pin(&a->pin, src_dentry, a->bdst, /*di_locked*/1, + /*do_gp*/hinotify); + if (unlikely(err)) + goto out; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + /* todo: no KEEPLINO because of noplink? */ + err = au_sio_cpup_simple(src_dentry, a->bdst, -1, + AuCpup_DTIME /* | AuCpup_KEEPLINO */); + mutex_unlock(h_mtx); + au_unpin(&a->pin); + + out: + di_read_unlock(a->src_parent, AuLock_IR); + AuTraceErr(err); + return err; +} + +static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a) +{ + int err; + struct inode *h_inode; + aufs_bindex_t bstart; + struct dentry *h_src_dentry; + + AuTraceEnter(); + AuDebugOn(au_dbstart(src_dentry) != a->bsrc); + + bstart = au_ibstart(src_dentry->d_inode); + h_inode = NULL; + if (bstart <= a->bdst) + h_inode = au_h_iptr(src_dentry->d_inode, a->bdst); + if (!h_inode || !h_inode->i_nlink) { + /* copyup src_dentry as the name of dentry. */ + au_set_dbstart(src_dentry, a->bdst); + au_set_h_dptr(src_dentry, a->bdst, dget(a->h_dentry)); + h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode; + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1, + AuCpup_KEEPLINO, a->parent); + mutex_unlock(&h_inode->i_mutex); + au_set_h_dptr(src_dentry, a->bdst, NULL); + au_set_dbstart(src_dentry, a->bsrc); + } else { + /* the inode of src_dentry already exists on a.bdst branch */ + h_src_dentry = d_find_alias(h_inode); + if (h_src_dentry) { + /* vfsub_args_reinit(&a->vargs); */ + vfsub_ign_hinode(&a->vargs, IN_CREATE, + au_pinned_hdir(&a->pin, a->bdst)); + err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), + a->h_dentry, &a->vargs); + dput(h_src_dentry); + } else { + AuIOErr("no dentry found for i%lu on b%d\n", + h_inode->i_ino, a->bdst); + err = -EIO; + } + } + + if (!err) + au_plink_append(src_dentry->d_sb, src_dentry->d_inode, + a->h_dentry, a->bdst); + + AuTraceErr(err); + return err; +} + +int aufs_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry) +{ + int err, rerr; + struct dentry *wh_dentry, *h_src_dentry; + struct inode *inode; + struct au_dtime dt; + struct super_block *sb; + struct au_link_args *a; + struct au_wr_dir_args wr_dir_args = { + /* .force_btgt = -1, */ + .flags = AuWrDir_ADD_ENTRY + }; + + LKTRTrace("src %.*s, i%lu, dst %.*s\n", + AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry)); + IMustLock(dir); + inode = src_dentry->d_inode; + IMustLock(inode); + AuDebugOn(S_ISDIR(inode->i_mode)); + + err = -ENOMEM; + a = kzalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + sb = dentry->d_sb; + a->parent = dentry->d_parent; /* dir inode is locked */ + aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0); + a->src_parent = dget_parent(src_dentry); + wr_dir_args.force_btgt = au_dbstart(src_dentry); + a->mnt_flags = au_mntflags(sb); + vfsub_args_init(&a->vargs, &a->ign, au_test_dlgt(a->mnt_flags), 0); + + di_write_lock_parent(a->parent); + wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin, + &wr_dir_args); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out_unlock; + err = 0; + + a->bdst = au_dbstart(dentry); + a->h_dentry = au_h_dptr(dentry, a->bdst); + + /* todo: minor optimize, + their sb may be same while their bindex differs? */ + a->bsrc = au_dbstart(src_dentry); + if (au_opt_test(a->mnt_flags, PLINK)) { + if (a->bdst < a->bsrc + /* && h_src_dentry->d_sb != a->h_dentry->d_sb */) + err = au_cpup_or_link(src_dentry, a); + else { + h_src_dentry = au_h_dptr(src_dentry, a->bdst); + AuDebugOn(!h_src_dentry); + AuDebugOn(!h_src_dentry->d_inode); + vfsub_ign_hinode(&a->vargs, IN_CREATE, + au_pinned_hdir(&a->pin, a->bdst)); + err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), + a->h_dentry, &a->vargs); + } + } else { + /* + * copyup src_dentry to the branch we process, + * and then link(2) to it. + */ + if (a->bdst < a->bsrc + /* && h_src_dentry->d_sb != a->h_dentry->d_sb */) { + au_unpin(&a->pin); + di_write_unlock(a->parent); + err = au_cpup_before_link(src_dentry, dir, dentry, a); + if (!err) { + di_write_lock_parent(a->parent); + err = au_pin + (&a->pin, dentry, a->bdst, + /*di_locked*/1, + /*do_gp*/au_opt_test(a->mnt_flags, + UDBA_INOTIFY)); + if (unlikely(err)) + goto out_wh; + } + } + if (!err) { + /* vfsub_args_reinit(&a->vargs); */ + vfsub_ign_hinode(&a->vargs, IN_CREATE, + au_pinned_hdir(&a->pin, a->bdst)); + h_src_dentry = au_h_dptr(src_dentry, a->bdst); + err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), + a->h_dentry, &a->vargs); + } + } + if (unlikely(err)) + goto out_unpin; + + if (wh_dentry) { + err = au_wh_unlink_dentry(au_pinned_hdir(&a->pin, a->bdst), + wh_dentry, dentry, /*dlgt*/0); + if (unlikely(err)) + goto out_revert; + } + +#if 0 /* cannot support it */ + /* fuse has different memory inode for the same inode number */ + if (unlikely(au_test_fuse(a->h_dentry->d_sb))) { + LKTRLabel(here); + d_drop(a->h_dentry); + /*d_drop(h_src_dentry); + d_drop(src_dentry);*/ + inc_nlink(a->inode); + a->inode->i_ctime = dir->i_ctime; + } +#endif + + dir->i_version++; + if (au_ibstart(dir) == au_dbstart(dentry)) + au_cpup_attr_timesizes(dir); + if (!d_unhashed(a->h_dentry) + /* || h_old_inode->i_nlink <= nlink */ + /* || SB_NFS(h_src_dentry->d_sb) */) { + d_instantiate(dentry, au_igrab(inode)); + inc_nlink(inode); + inode->i_ctime = dir->i_ctime; + } else + /* nfs case (< 2.6.15) */ + d_drop(dentry); + goto out_unpin; /* success */ + + out_revert: + vfsub_args_reinit(&a->vargs); + vfsub_ign_hinode(&a->vargs, IN_DELETE, au_pinned_hdir(&a->pin, a->bdst)); + rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), a->h_dentry, &a->vargs); + if (!rerr) + goto out_dt; + AuIOErr("%.*s reverting failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + out_dt: + d_drop(dentry); + au_dtime_revert(&dt); + out_unpin: + au_unpin(&a->pin); + out_wh: + dput(wh_dentry); + out_unlock: + if (unlikely(err)) { + au_update_dbstart(dentry); + d_drop(dentry); + } + di_write_unlock(a->parent); + dput(a->src_parent); + aufs_read_and_write_unlock2(dentry, src_dentry); + kfree(a); + out: + AuTraceErr(err); + return err; +} + +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int err, rerr; + struct dentry *h_dentry, *wh_dentry, *parent, *opq_dentry; + struct mutex *h_mtx; + struct au_dtime dt; + aufs_bindex_t bindex; + unsigned char diropq, dlgt; + unsigned int mnt_flags; + struct au_hin_ignore ign; + struct vfsub_args vargs; + struct au_pin pin; + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR + }; + + LKTRTrace("i%lu, %.*s, mode 0%o\n", + dir->i_ino, AuDLNPair(dentry), mode); + IMustLock(dir); +#if 0 + if (IS_DEADDIR(dir)) { + AuDbg("here\n"); + return -ENOENT; + } +#endif + + aufs_read_lock(dentry, AuLock_DW); + parent = dentry->d_parent; /* dir inode is locked */ + mnt_flags = au_mntflags(dentry->d_sb); + dlgt = !!au_test_dlgt(mnt_flags); + vfsub_args_init(&vargs, &ign, dlgt, 0); + + di_write_lock_parent(parent); + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin, + &wr_dir_args); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + bindex = au_dbstart(dentry); + h_dentry = au_h_dptr(dentry, bindex); + vfsub_ign_hinode(&vargs, IN_CREATE, au_pinned_hdir(&pin, bindex)); + err = vfsub_mkdir(au_pinned_h_dir(&pin), h_dentry, mode, &vargs); + if (unlikely(err)) + goto out_unlock; + + /* make the dir opaque */ + diropq = 0; + h_mtx = &h_dentry->d_inode->i_mutex; + if (wh_dentry || au_opt_test(mnt_flags, ALWAYS_DIROPQ)) { + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + opq_dentry = au_diropq_create(dentry, bindex, /*dlgt*/0); + mutex_unlock(h_mtx); + err = PTR_ERR(opq_dentry); + if (IS_ERR(opq_dentry)) + goto out_dir; + dput(opq_dentry); + diropq = 1; + } + + err = epilog(dir, bindex, wh_dentry, dentry); + if (!err) { + inc_nlink(dir); + goto out_unlock; /* success */ + } + + /* revert */ + if (diropq) { + LKTRLabel(revert opq); + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + rerr = au_diropq_remove(dentry, bindex, dlgt); + mutex_unlock(h_mtx); + if (rerr) { + AuIOErr("%.*s reverting diropq failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } + } + + out_dir: + LKTRLabel(revert dir); + vfsub_args_reinit(&vargs); + vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin, bindex)); + rerr = vfsub_rmdir(au_pinned_h_dir(&pin), h_dentry, &vargs); + if (rerr) { + AuIOErr("%.*s reverting dir failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } + d_drop(dentry); + au_dtime_revert(&dt); + out_unlock: + au_unpin(&pin); + dput(wh_dentry); + out: + if (unlikely(err)) { + au_update_dbstart(dentry); + d_drop(dentry); + } + di_write_unlock(parent); + aufs_read_unlock(dentry, AuLock_DW); + AuTraceErr(err); + return err; +} --- linux-2.6.27.orig/ubuntu/aufs/dir.h +++ linux-2.6.27/ubuntu/aufs/dir.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * directory operations + * + * $Id: dir.h,v 1.3 2008/05/26 04:04:23 sfjro Exp $ + */ + +#ifndef __AUFS_DIR_H__ +#define __AUFS_DIR_H__ + +#ifdef __KERNEL__ + +#include +#include + +/* ---------------------------------------------------------------------- */ + +/* need to be faster and smaller */ + +/* todo: changeable? */ +#define AuSize_DEBLK 512 +#define AuSize_NHASH 32 +#if AuSize_DEBLK < NAME_MAX || PAGE_SIZE < AuSize_DEBLK +#error invalid size AuSize_DEBLK +#endif + +typedef char au_vdir_deblk_t[AuSize_DEBLK]; + +struct au_nhash { + struct hlist_head heads[AuSize_NHASH]; +}; + +struct au_vdir_destr { + unsigned char len; + char name[0]; +} __packed; + +struct au_vdir_dehstr { + struct hlist_node hash; + struct au_vdir_destr *str; +}; + +struct au_vdir_de { + ino_t de_ino; + unsigned char de_type; + /* caution: packed */ + struct au_vdir_destr de_str; +} __packed; + +struct au_vdir_wh { + struct hlist_node wh_hash; + aufs_bindex_t wh_bindex; +#ifdef CONFIG_AUFS_SHWH + ino_t wh_ino; + unsigned char wh_type; + /* caution: packed */ +#endif + struct au_vdir_destr wh_str; +} __packed; + +union au_vdir_deblk_p { + unsigned char *p; + au_vdir_deblk_t *deblk; + struct au_vdir_de *de; +}; + +struct au_vdir { + au_vdir_deblk_t **vd_deblk; + int vd_nblk; + struct { + int i; + union au_vdir_deblk_p p; + } vd_last; + + unsigned long vd_version; + unsigned long vd_jiffy; +}; + +/* ---------------------------------------------------------------------- */ + +/* dir.c */ +extern struct file_operations aufs_dir_fop; +int au_test_empty_lower(struct dentry *dentry); +int au_test_empty(struct dentry *dentry, struct au_nhash *whlist); + +/* vdir.c */ +struct au_nhash *au_nhash_new(gfp_t gfp); +void au_nhash_del(struct au_nhash *nhash); +void au_nhash_init(struct au_nhash *nhash); +void au_nhash_move(struct au_nhash *dst, struct au_nhash *src); +void au_nhash_fin(struct au_nhash *nhash); +int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, + int limit); +int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int namelen); +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int namelen, + ino_t ino, unsigned int d_type, aufs_bindex_t bindex, + unsigned char shwh); +void au_vdir_free(struct au_vdir *vdir); +int au_vdir_init(struct file *file); +int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir); + +/* ---------------------------------------------------------------------- */ + +static inline +void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, unsigned char d_type) +{ +#ifdef CONFIG_AUFS_SHWH + wh->wh_ino = ino; + wh->wh_type = d_type; +#endif +} + +static inline void au_add_nlink(struct inode *dir, struct inode *h_dir) +{ + AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); + dir->i_nlink += h_dir->i_nlink - 2; + if (unlikely(h_dir->i_nlink < 2)) + dir->i_nlink += 2; +} + +static inline void au_sub_nlink(struct inode *dir, struct inode *h_dir) +{ + AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); + dir->i_nlink -= h_dir->i_nlink - 2; + if (unlikely(h_dir->i_nlink < 2)) + dir->i_nlink -= 2; +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DIR_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/f_op.c +++ linux-2.6.27/ubuntu/aufs/f_op.c @@ -0,0 +1,670 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * file and vm operations + * + * $Id: f_op.c,v 1.11 2008/09/01 02:55:44 sfjro Exp $ + */ + +#include +#include +#include "aufs.h" + +/* common function to regular file and dir */ +int aufs_flush(struct file *file, fl_owner_t id) +{ + int err; + struct dentry *dentry; + aufs_bindex_t bindex, bend; + struct file *h_file; + + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + + si_noflush_read_lock(dentry->d_sb); + fi_read_lock(file); + di_read_lock_child(dentry, AuLock_IW); + + err = 0; + bend = au_fbend(file); + for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) { + h_file = au_h_fptr(file, bindex); + if (h_file && h_file->f_op && h_file->f_op->flush) { + err = h_file->f_op->flush(h_file, id); + if (!err) + au_update_fuse_h_inode + (h_file->f_vfsmnt, h_file->f_dentry); + /*ignore*/ + } + } + au_cpup_attr_timesizes(dentry->d_inode); + + di_read_unlock(dentry, AuLock_IW); + fi_read_unlock(file); + si_read_unlock(dentry->d_sb); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int do_open_nondir(struct file *file, int flags) +{ + int err; + aufs_bindex_t bindex; + struct super_block *sb; + struct file *h_file; + struct dentry *dentry; + struct inode *inode; + struct au_finfo *finfo; + + dentry = file->f_dentry; + LKTRTrace("%.*s, flags 0%o\n", AuDLNPair(dentry), flags); + FiMustWriteLock(file); + inode = dentry->d_inode; + AuDebugOn(!inode || S_ISDIR(inode->i_mode)); + + err = 0; + finfo = au_fi(file); + finfo->fi_h_vm_ops = NULL; + sb = dentry->d_sb; + bindex = au_dbstart(dentry); + AuDebugOn(!au_h_dptr(dentry, bindex)->d_inode); + /* O_TRUNC is processed already */ + BUG_ON(au_test_ro(sb, bindex, inode) && (flags & O_TRUNC)); + + h_file = au_h_open(dentry, bindex, flags, file); + if (IS_ERR(h_file)) + err = PTR_ERR(h_file); + else { + au_set_fbstart(file, bindex); + au_set_fbend(file, bindex); + au_set_h_fptr(file, bindex, h_file); + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + err = 0; + } + AuTraceErr(err); + return err; +} + +static int aufs_open_nondir(struct inode *inode, struct file *file) +{ + LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry)); + + return au_do_open(inode, file, do_open_nondir); +} + +static int aufs_release_nondir(struct inode *inode, struct file *file) +{ + struct super_block *sb = file->f_dentry->d_sb; + + LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry)); + + si_noflush_read_lock(sb); + au_finfo_fin(file); + si_read_unlock(sb); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + ssize_t err; + struct dentry *dentry; + struct file *h_file; + struct super_block *sb; + struct inode *h_inode; + + dentry = file->f_dentry; + LKTRTrace("%.*s, cnt %lu, pos %lld\n", + AuDLNPair(dentry), (unsigned long)count, *ppos); + + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, + /*locked*/0); + if (unlikely(err)) + goto out; + + /* support LSM and notify */ + h_file = au_h_fptr(file, au_fbstart(file)); + h_inode = h_file->f_dentry->d_inode; + err = vfsub_read_u(h_file, buf, count, ppos, + au_test_dlgt(au_mntflags(sb))); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode); + + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + out: + si_read_unlock(sb); + AuTraceErr(err); + return err; +} + +static ssize_t aufs_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + ssize_t err; + struct dentry *dentry; + struct inode *inode; + struct super_block *sb; + unsigned int mnt_flags; + struct file *h_file; + char __user *buf = (char __user *)ubuf; + struct au_hin_ignore ign; + struct vfsub_args vargs; + aufs_bindex_t bstart; + int hinotify; + struct au_pin pin; + + dentry = file->f_dentry; + LKTRTrace("%.*s, cnt %lu, pos %lld\n", + AuDLNPair(dentry), (unsigned long)count, *ppos); + + inode = dentry->d_inode; + mutex_lock(&inode->i_mutex); + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + mnt_flags = au_mntflags(sb); + hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY); + vfsub_args_init(&vargs, &ign, au_test_dlgt(mnt_flags), 0); + + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, + /*locked*/1); + if (unlikely(err)) + goto out; + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + + bstart = au_fbstart(file); + h_file = au_h_fptr(file, bstart); + if (!hinotify) { + au_unpin(&pin); + err = vfsub_write_u(h_file, buf, count, ppos, &vargs); + } else { + vfsub_ign_hinode(&vargs, IN_MODIFY, + au_pinned_hdir(&pin, bstart)); + err = vfsub_write_u(h_file, buf, count, ppos, &vargs); + au_unpin(&pin); + } + au_cpup_attr_timesizes(inode); + + out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); + out: + si_read_unlock(sb); + mutex_unlock(&inode->i_mutex); + AuTraceErr(err); + return err; +} + +#ifdef CONFIG_AUFS_SPLICE_PATCH +static int au_test_loopback(void) +{ + const char c = current->comm[4]; + /* true if a kernel thread named 'loop[0-9].*' accesses a file */ + const int loopback = (current->mm == NULL + && '0' <= c && c <= '9' + && strncmp(current->comm, "loop", 4) == 0); + return loopback; +} + +static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + ssize_t err; + struct file *h_file; + struct dentry *dentry; + struct super_block *sb; + + dentry = file->f_dentry; + LKTRTrace("%.*s, pos %lld, len %lu\n", + AuDLNPair(dentry), *ppos, (unsigned long)len); + + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, + /*locked*/0); + if (unlikely(err)) + goto out; + + err = -EINVAL; + /* support LSM and notify */ + h_file = au_h_fptr(file, au_fbstart(file)); + if (/* unlikely */(au_test_loopback())) { + file->f_mapping = h_file->f_mapping; + smp_mb(); /* unnecessary? */ + } + err = vfsub_splice_to(h_file, ppos, pipe, len, flags, + au_test_dlgt(au_mntflags(sb))); + /* todo: necessasry? */ + /* file->f_ra = h_file->f_ra; */ + fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode); + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + + out: + si_read_unlock(sb); + AuTraceErr(err); + return err; +} + +static ssize_t +aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, + size_t len, unsigned int flags) +{ + ssize_t err; + struct dentry *dentry; + struct inode *inode, *h_inode; + struct super_block *sb; + struct file *h_file; + /* struct au_hin_ignore ign; */ + struct vfsub_args vargs; + unsigned int mnt_flags; + struct au_pin pin; + + dentry = file->f_dentry; + LKTRTrace("%.*s, len %lu, pos %lld\n", + AuDLNPair(dentry), (unsigned long)len, *ppos); + + inode = dentry->d_inode; + mutex_lock(&inode->i_mutex); + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + mnt_flags = au_mntflags(sb); + vfsub_args_init(&vargs, /*&ign*/NULL, au_test_dlgt(mnt_flags), 0); + + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, + /*locked*/1); + if (unlikely(err)) + goto out; + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + + /* support LSM and notify */ + /* current vfs_splice_from() doesn't fire up the inotify event */ + h_file = au_h_fptr(file, au_fbstart(file)); + h_inode = h_file->f_dentry->d_inode; + if (1 || !au_opt_test(mnt_flags, UDBA_INOTIFY)) { + au_unpin(&pin); + err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs); + } +#if 0 /* reserved for future use */ + else { + struct dentry *parent = dget_parent(dentry); + vfsub_ign_hinode(&vargs, IN_MODIFY, + au_pinned_hdir(&pin, bstart)); + err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs); + au_unpin(&pin); + } +#endif + au_cpup_attr_timesizes(inode); + + out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); + out: + si_read_unlock(sb); + mutex_unlock(&inode->i_mutex); + AuTraceErr(err); + return err; +} +#endif /* CONFIG_AUFS_SPLICE_PATCH */ + +/* ---------------------------------------------------------------------- */ + +static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + int err; + struct dentry *dentry; + struct file *file, *h_file; + struct inode *inode; + static DECLARE_WAIT_QUEUE_HEAD(wq); + struct au_finfo *finfo; + + AuTraceEnter(); + AuDebugOn(!vma || !vma->vm_file); + /* todo: non-robr mode, user vm_file as it is? */ + wait_event(wq, (file = au_robr_safe_file(vma))); + AuDebugOn(!au_test_aufs(file->f_dentry->d_sb)); + dentry = file->f_dentry; + LKTRTrace("%.*s\n", AuDLNPair(dentry)); + inode = dentry->d_inode; + AuDebugOn(!S_ISREG(inode->i_mode)); + + /* do not revalidate, no si lock */ + finfo = au_fi(file); + h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file; + AuDebugOn(!h_file || !au_test_mmapped(file)); + fi_write_lock(file); + vma->vm_file = h_file; + err = finfo->fi_h_vm_ops->fault(vma, vmf); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + au_robr_reset_file(vma, file); + fi_write_unlock(file); +#if 0 /* def CONFIG_SMP */ + /* wake_up_nr(&wq, online_cpu - 1); */ + wake_up_all(&wq); +#else + wake_up(&wq); +#endif + + if (!(err & VM_FAULT_ERROR)) { +#if 0 /* debug */ + struct page *page; + page = vmf->page; + AuDbg("%p, %d\n", page, page_mapcount(page)); + + page->mapping = file->f_mapping; + get_page(page); + file->f_mapping = h_file->f_mapping; + touch_atime(NULL, dentry); + inode->i_atime = h_file->f_dentry->d_inode->i_atime; +#endif + } + AuTraceErr(err); + return err; +} + +static struct vm_operations_struct aufs_vm_ops = { + .fault = aufs_fault, +#if 0 /* reserved for future use */ + .open = aufs_vmaopen, + .close = aufs_vmaclose, + unsigned long (*nopfn)(struct vm_area_struct *area, + unsigned long address); + page_mkwrite(struct vm_area_struct *vma, struct page *page) +#endif +}; + +/* ---------------------------------------------------------------------- */ + +static struct vm_operations_struct *au_vm_ops(struct file *h_file, + struct vm_area_struct *vma) +{ + struct vm_operations_struct *vm_ops; + int err; + + AuTraceEnter(); + + au_br_nfs_lockdep_off(h_file->f_vfsmnt->mnt_sb); + err = h_file->f_op->mmap(h_file, vma); + au_br_nfs_lockdep_on(h_file->f_vfsmnt->mnt_sb); + vm_ops = ERR_PTR(err); + if (unlikely(err)) + goto out; + vm_ops = vma->vm_ops; + err = do_munmap(current->mm, vma->vm_start, + vma->vm_end - vma->vm_start); + if (unlikely(err)) { + AuIOErr("failed internal unmapping %.*s, %d\n", + AuDLNPair(h_file->f_dentry), err); + vm_ops = ERR_PTR(-EIO); + } + + out: + AuTraceErrPtr(vm_ops); + return vm_ops; +} + +static int aufs_mmap(struct file *file, struct vm_area_struct *vma) +{ + int err; + unsigned char wlock, mmapped; + struct dentry *dentry; + struct super_block *sb; + struct file *h_file; + struct vm_operations_struct *vm_ops; + + dentry = file->f_dentry; + LKTRTrace("%.*s, %lx, len %lu\n", + AuDLNPair(dentry), vma->vm_start, + vma->vm_end - vma->vm_start); + AuDebugOn(!S_ISREG(dentry->d_inode->i_mode)); + AuDebugOn(down_write_trylock(&vma->vm_mm->mmap_sem)); + + mmapped = au_test_mmapped(file); /* can be harmless race condition */ + wlock = !!(file->f_mode & FMODE_WRITE); + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, wlock | !mmapped, + /*locked*/0); + if (unlikely(err)) + goto out; + + if (wlock) { + struct au_pin pin; + + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + au_unpin(&pin); + } else if (!mmapped) + di_downgrade_lock(dentry, AuLock_IR); + + h_file = au_h_fptr(file, au_fbstart(file)); + if (unlikely(au_test_fuse(h_file->f_dentry->d_sb))) { + /* + * by this assignment, f_mapping will differs from aufs inode + * i_mapping. + * if someone else mixes the use of f_dentry->d_inode and + * f_mapping->host, then a problem may arise. + */ + file->f_mapping = h_file->f_mapping; + } + + if (0 && h_file->f_op->mmap == generic_file_mmap) { + err = generic_file_mmap(file, vma); /* instead of h_file */ + if (unlikely(err)) + goto out_unlock; + au_fi(file)->fi_h_vm_ops = vma->vm_ops; + } else { + vm_ops = NULL; + if (!mmapped) { + vm_ops = au_vm_ops(h_file, vma); + err = PTR_ERR(vm_ops); + if (IS_ERR(vm_ops)) + goto out_unlock; + } + + err = generic_file_mmap(file, vma); + if (unlikely(err)) + goto out_unlock; + vma->vm_ops = &aufs_vm_ops; + /* test again */ + if (!au_test_mmapped(file)) { + FiMustWriteLock(file); + au_fi(file)->fi_h_vm_ops = vm_ops; + } + } + + file_accessed(h_file); + au_update_fuse_h_inode(h_file->f_vfsmnt, h_file->f_dentry); /*ignore*/ + fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode); + + out_unlock: + di_read_unlock(dentry, AuLock_IR); + if (!wlock && mmapped) + fi_read_unlock(file); + else + fi_write_unlock(file); + out: + si_read_unlock(sb); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static unsigned int aufs_poll(struct file *file, poll_table *wait) +{ + unsigned int mask; + struct file *h_file; + int err; + struct dentry *dentry; + struct super_block *sb; + + dentry = file->f_dentry; + LKTRTrace("%.*s, wait %p\n", AuDLNPair(dentry), wait); + AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)); + + /* We should pretend an error happened. */ + mask = POLLERR /* | POLLIN | POLLOUT */; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, + /*locked*/0); + if (unlikely(err)) + goto out; + + /* it is not an error of hidden_file has no operation */ + mask = DEFAULT_POLLMASK; + h_file = au_h_fptr(file, au_fbstart(file)); + if (h_file->f_op && h_file->f_op->poll) + mask = h_file->f_op->poll(h_file, wait); + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + + out: + si_read_unlock(sb); + AuTraceErr((int)mask); + return mask; +} + +static int aufs_fsync_nondir(struct file *file, struct dentry *dentry, + int datasync) +{ + int err; + struct inode *inode; + struct file *h_file; + struct super_block *sb; + struct au_pin pin; + + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync); + inode = dentry->d_inode; + + IMustLock(file->f_mapping->host); + if (unlikely(inode != file->f_mapping->host)) { + mutex_unlock(&file->f_mapping->host->i_mutex); + mutex_lock(&inode->i_mutex); + } + IMustLock(inode); + + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = 0; /* -EBADF; */ /* posix? */ + if (unlikely(!(file->f_mode & FMODE_WRITE))) + goto out; + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, + /*locked*/1); + if (unlikely(err)) + goto out; + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + au_unpin(&pin); + + err = -EINVAL; + h_file = au_h_fptr(file, au_fbstart(file)); + if (h_file->f_op && h_file->f_op->fsync) { + struct mutex *h_mtx = &h_file->f_dentry->d_inode->i_mutex; + + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + err = h_file->f_op->fsync(h_file, h_file->f_dentry, datasync); + if (!err) + au_update_fuse_h_inode(h_file->f_vfsmnt, + h_file->f_dentry); + au_cpup_attr_timesizes(inode); + mutex_unlock(h_mtx); + } + + out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); + out: + si_read_unlock(sb); + if (unlikely(inode != file->f_mapping->host)) { + mutex_unlock(&inode->i_mutex); + mutex_lock(&file->f_mapping->host->i_mutex); + } + AuTraceErr(err); + return err; +} + +static int aufs_fasync(int fd, struct file *file, int flag) +{ + int err; + struct file *h_file; + struct dentry *dentry; + struct super_block *sb; + + dentry = file->f_dentry; + LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), flag); + + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, + /*locked*/0); + if (unlikely(err)) + goto out; + + h_file = au_h_fptr(file, au_fbstart(file)); + if (h_file->f_op && h_file->f_op->fasync) + err = h_file->f_op->fasync(fd, h_file, flag); + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + + out: + si_read_unlock(sb); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct file_operations aufs_file_fop = { + .read = aufs_read, + .write = aufs_write, + .poll = aufs_poll, + .mmap = aufs_mmap, + .open = aufs_open_nondir, + .flush = aufs_flush, + .release = aufs_release_nondir, + .fsync = aufs_fsync_nondir, + .fasync = aufs_fasync, +#ifdef CONFIG_AUFS_SPLICE_PATCH + .splice_write = aufs_splice_write, + .splice_read = aufs_splice_read, +#endif +}; --- linux-2.6.27.orig/ubuntu/aufs/hinode.h +++ linux-2.6.27/ubuntu/aufs/hinode.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * lower (branch filesystem) inode and setting inotify + * + * $Id: hinode.h,v 1.9 2008/08/25 01:49:59 sfjro Exp $ + */ + +#ifndef __AUFS_HINODE_H__ +#define __AUFS_HINODE_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include "super.h" +#include "vfsub.h" + +/* ---------------------------------------------------------------------- */ + +struct au_hinotify { +#ifdef CONFIG_AUFS_HINOTIFY + spinlock_t hin_ignore_lock; + struct list_head hin_ignore_list; + + struct inotify_watch hin_watch; + struct inode *hin_aufs_inode; /* no get/put */ +#endif +}; + +struct au_hinode { + struct inode *hi_inode; + aufs_bindex_t hi_id; +#ifdef CONFIG_AUFS_HINOTIFY + struct au_hinotify *hi_notify; +#endif + + /* reference to the copied-up whiteout with get/put */ + struct dentry *hi_whdentry; +}; + +struct au_hin_ignore { +#ifdef CONFIG_AUFS_HINOTIFY + struct list_head ign_list; + + pid_t ign_pid; + __u32 ign_events, ign_handled; + struct au_hinode *ign_hinode; +#endif +}; + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_HINOTIFY +/* inotify events */ +static const __u32 AuInMask = (IN_MOVE | IN_DELETE | IN_CREATE + /* | IN_ACCESS */ + | IN_MODIFY | IN_ATTRIB + /* | IN_DELETE_SELF | IN_MOVE_SELF */ + ); + +static inline +void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val) +{ + hinode->hi_notify = val; +} + +/* hinotify.c */ +int au_hin_alloc(struct au_hinode *hinode, struct inode *inode, + struct inode *h_inode); +void au_hin_free(struct au_hinode *hinode); +void au_hin_ctl(struct au_hinode *hinode, const __u32 mask); +void au_reset_hinotify(struct inode *inode, unsigned int flags); + +int au_hin_verify_gen(struct dentry *dentry); + +int __init au_inotify_init(void); +void au_inotify_fin(void); + +static inline void au_hin_suspend(struct au_hinode *hinode) +{ + au_hin_ctl(hinode, 0); +} + +static inline void au_hin_resume(struct au_hinode *hinode) +{ + au_hin_ctl(hinode, AuInMask); +} + +#else + +static inline +void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val) +{ + /* empty */ +} + +static inline +int au_hin_alloc(struct au_hinode *hinode, struct inode *inode, + struct inode *h_inode) +{ + return -EOPNOTSUPP; +} + +static inline void au_hin_free(struct au_hinode *hinode) +{ + /* nothing */ +} + +static inline void au_reset_hinotify(struct inode *inode, unsigned int flags) +{ + /* nothing */ +} + +static inline int au_hin_verify_gen(struct dentry *dentry) +{ + return 0; +} + +static inline int au_inotify_init(void) +{ + return 0; +} + +#define au_inotify_fin() do {} while (0) + +static inline void au_hin_suspend(struct au_hinode *hinode) +{ + /* empty */ +} + +static inline void au_hin_resume(struct au_hinode *hinode) +{ + /* empty */ +} +#endif /* CONFIG_AUFS_HINOTIFY */ + +#if defined(CONFIG_AUFS_HINOTIFY) && defined(CONFIG_AUFS_DEBUG) +static inline void au_hin_list_del(struct list_head *e) +{ + list_del_init(e); +} + +void au_dbg_hin_list(struct vfsub_args *vargs); +#else +static inline void au_hin_list_del(struct list_head *e) +{ + list_del(e); +} + +static inline void au_dbg_hin_list(struct vfsub_args *vargs) +{ + /* empty */ +} +#endif /* CONFIG_AUFS_DEBUG */ + +/* ---------------------------------------------------------------------- */ + +#endif /* __KERNEL__ */ +#endif /* __AUFS_HINODE_H__ */ --- linux-2.6.27.orig/ubuntu/aufs/whout.h +++ linux-2.6.27/ubuntu/aufs/whout.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2005-2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * whiteout for logical deletion and opaque directory + * + * $Id: whout.h,v 1.3 2008/06/30 03:57:35 sfjro Exp $ + */ + +#ifndef __AUFS_WHOUT_H__ +#define __AUFS_WHOUT_H__ + +#ifdef __KERNEL__ + +#include +#include +#include "dir.h" +#include "opts.h" +#include "super.h" + +int au_wh_name_alloc(const char *name, int len, struct qstr *wh); +void au_wh_name_free(struct qstr *wh); + +struct au_ndx; +int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio, + struct au_ndx *ndx); +int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx); + +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix, + struct au_ndx *ndx); +int au_whtmp_ren(struct inode *dir, aufs_bindex_t bindex, + struct dentry *h_dentry); +int au_wh_unlink_dentry(struct au_hinode *dir, struct dentry *wh_dentry, + struct dentry *dentry, int dlgt); + +struct au_branch; +int au_wh_init(struct dentry *h_parent, struct au_branch *br, + struct vfsmount *nfsmnt, struct super_block *sb, + aufs_bindex_t bindex); + +/* diropq flags */ +#define AuDiropq_CREATE 1 +#define AuDiropq_DLGT (1 << 1) +#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name) +#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; } +#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; } +#ifndef CONFIG_AUFS_DLGT +#undef AuDiropq_DLGT +#define AuDiropq_DLGT 0 +#endif + +struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, + unsigned int flags); + +struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, + struct au_ndx *ndx); +struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, struct au_ndx *ndx); + +/* real rmdir the whiteout-ed dir */ +struct au_whtmp_rmdir_args { + struct inode *dir; + aufs_bindex_t bindex; + struct dentry *wh_dentry; + struct au_nhash whlist; +}; + +struct au_nhash; +int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_nhash *whlist); +void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_nhash *whlist, + struct au_whtmp_rmdir_args *args); + +/* ---------------------------------------------------------------------- */ + +static inline +struct dentry *au_diropq_create(struct dentry *dentry, aufs_bindex_t bindex, + int dlgt) +{ + unsigned int flags = AuDiropq_CREATE; + if (unlikely(dlgt)) + au_fset_diropq(flags, DLGT); + return au_diropq_sio(dentry, bindex, flags); +} + +static inline +int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex, int dlgt) +{ + unsigned int flags = !AuDiropq_CREATE; + if (unlikely(dlgt)) + au_fset_diropq(flags, DLGT); + return PTR_ERR(au_diropq_sio(dentry, bindex, flags)); +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_ROBR +/* robr.c */ +int au_test_robr_wh(struct qstr *name, struct dentry *h_parent, + struct qstr *wh_name, int try_sio, struct au_ndx *ndx); +int au_test_robr_shwh(struct super_block *sb, const struct qstr *name); +#else +static inline +int au_test_robr_wh(struct qstr *name, struct dentry *h_parent, + struct qstr *wh_name, int try_sio, struct au_ndx *ndx) +{ + return au_wh_test(h_parent, wh_name, try_sio, ndx); +} + +static inline +int au_test_robr_shwh(struct super_block *sb, const struct qstr *name) +{ + if (unlikely(!au_opt_test(au_mntflags(sb), SHWH) + && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))) + return -EPERM; + return 0; +} +#endif /* CONFIG_AUFS_ROBR */ + +#endif /* __KERNEL__ */ +#endif /* __AUFS_WHOUT_H__ */ --- linux-2.6.27.orig/ubuntu/atl2/atl2.h +++ linux-2.6.27/ubuntu/atl2/atl2.h @@ -0,0 +1,120 @@ +/* atl2.h -- atl2 driver definitions + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ATL2_H_ +#define _ATL2_H_ + +#include +#include + +#include "atl2_hw.h" + +struct atl2_ring_header { + /* pointer to the descriptor ring memory */ + void *desc; + /* physical adress of the descriptor ring */ + dma_addr_t dma; + /* length of descriptor ring in bytes */ + unsigned int size; +}; + +/* board specific private data structure */ +struct atl2_adapter { + /* OS defined structs */ + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; +#ifdef NETIF_F_HW_VLAN_TX + struct vlan_group *vlgrp; +#endif + u32 wol; + u16 link_speed; + u16 link_duplex; + + spinlock_t stats_lock; + spinlock_t tx_lock; + + struct work_struct reset_task; + struct work_struct link_chg_task; + struct timer_list watchdog_timer; + struct timer_list phy_config_timer; + + unsigned long cfg_phy; + bool mac_disabled; + + /* All Descriptor memory */ + dma_addr_t ring_dma; + void *ring_vir_addr; + int ring_size; + + tx_pkt_header_t *txd_ring; + dma_addr_t txd_dma; + + tx_pkt_status_t *txs_ring; + dma_addr_t txs_dma; + + rx_desc_t *rxd_ring; + dma_addr_t rxd_dma; + + u32 txd_ring_size; // bytes per unit + u32 txs_ring_size; // dwords per unit + u32 rxd_ring_size; // 1536bytes per unit + + // read /write ptr: + // host + u32 txd_write_ptr; + u32 txs_next_clear; + u32 rxd_read_ptr; + + // nic + atomic_t txd_read_ptr; + atomic_t txs_write_ptr; + u32 rxd_write_ptr; + + /* Interrupt Moderator timer ( 2us resolution) */ + u16 imt; + /* Interrupt Clear timer (2us resolution) */ + u16 ict; + + unsigned long flags; + /* structs defined in atl2_hw.h */ + u32 bd_number; // board number; + bool pci_using_64; + bool have_msi; + struct atl2_hw hw; + + u32 usr_cmd; +// u32 regs_buff[ATL2_REGS_LEN]; + u32 pci_state[16]; + + u32 *config_space; +}; + +enum atl2_state_t { + __ATL2_TESTING, + __ATL2_RESETTING, + __ATL2_DOWN +}; + +#endif /* _ATL2_H_ */ --- linux-2.6.27.orig/ubuntu/atl2/Kconfig +++ linux-2.6.27/ubuntu/atl2/Kconfig @@ -0,0 +1,10 @@ +config ATL2 + tristate "Atheros L2 Fast Ethernet support (EXPERIMENTAL)" + depends on PCI && EXPERIMENTAL + select CRC32 + select MII + help + This driver supports the Atheros L2 fast ethernet adapter. + + To compile this driver as a module, choose M here. The module + will be called atl2. --- linux-2.6.27.orig/ubuntu/atl2/atl2_hw.c +++ linux-2.6.27/ubuntu/atl2/atl2_hw.c @@ -0,0 +1,760 @@ +/* atl2_hw.c -- atl2 hardware control functions + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include "atl2.h" +#include "atl2_hw.h" + +#define LBYTESWAP( a ) ( ( ( (a) & 0x00ff00ff ) << 8 ) | ( ( (a) & 0xff00ff00 ) >> 8 ) ) +#define LONGSWAP( a ) ( ( LBYTESWAP( a ) << 16 ) | ( LBYTESWAP( a ) >> 16 ) ) +#define SHORTSWAP( a ) ( ( (a) << 8 ) | ( (a) >> 8 ) ) + +/* + * Reset the transmit and receive units; mask and clear all interrupts. + * + * hw - Struct containing variables accessed by shared code + * return : ATL2_SUCCESS or idle status (if error) + */ +s32 +atl2_reset_hw(struct atl2_hw *hw) +{ + u32 icr; + u16 pci_cfg_cmd_word; + int i; + + /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ + atl2_read_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word); + if ((pci_cfg_cmd_word & + (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) != + (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) { + pci_cfg_cmd_word |= + (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER); + atl2_write_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word); + } + + /* Clear Interrupt mask to stop board from generating + * interrupts & Clear any pending interrupt events + */ +// ATL2_WRITE_REG(hw, REG_IMR, 0); +// ATL2_WRITE_REG(hw, REG_ISR, 0xffffffff); + + /* Issue Soft Reset to the MAC. This will reset the chip's + * transmit, receive, DMA. It will not effect + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ + ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST); + wmb(); + msec_delay(1); // delay about 1ms + + /* Wait at least 10ms for All module to be Idle */ + for (i=0; i < 10; i++) { + icr = ATL2_READ_REG(hw, REG_IDLE_STATUS); + if (!icr) + break; + msec_delay(1); // delay 1 ms + cpu_relax(); + } + + if (icr) + return icr; + + return ATL2_SUCCESS; +} + +#define CUSTOM_SPI_CS_SETUP 2 +#define CUSTOM_SPI_CLK_HI 2 +#define CUSTOM_SPI_CLK_LO 2 +#define CUSTOM_SPI_CS_HOLD 2 +#define CUSTOM_SPI_CS_HI 3 + +static struct atl2_spi_flash_dev flash_table[] = +{ +/* manu_name WRSR READ PROGRAM WREN WRDI RDSR RDID SECTOR_ERASE CHIP_ERASE */ + {"Atmel", 0x0, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62 }, + {"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60 }, + {"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7 }, +}; + +static bool +atl2_spi_read(struct atl2_hw* hw, u32 addr, u32* buf) +{ + int i; + u32 value; + + ATL2_WRITE_REG(hw, REG_SPI_DATA, 0); + ATL2_WRITE_REG(hw, REG_SPI_ADDR, addr); + + value = SPI_FLASH_CTRL_WAIT_READY | + (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) << SPI_FLASH_CTRL_CS_SETUP_SHIFT | + (CUSTOM_SPI_CLK_HI & SPI_FLASH_CTRL_CLK_HI_MASK) << SPI_FLASH_CTRL_CLK_HI_SHIFT | + (CUSTOM_SPI_CLK_LO & SPI_FLASH_CTRL_CLK_LO_MASK) << SPI_FLASH_CTRL_CLK_LO_SHIFT | + (CUSTOM_SPI_CS_HOLD & SPI_FLASH_CTRL_CS_HOLD_MASK) << SPI_FLASH_CTRL_CS_HOLD_SHIFT | + (CUSTOM_SPI_CS_HI & SPI_FLASH_CTRL_CS_HI_MASK) << SPI_FLASH_CTRL_CS_HI_SHIFT | + (0x1 & SPI_FLASH_CTRL_INS_MASK) << SPI_FLASH_CTRL_INS_SHIFT; + + ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); + + value |= SPI_FLASH_CTRL_START; + + ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); + + for (i = 0; i < 10; i++) + { + msec_delay(1); // 1ms + value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL); + if (!(value & SPI_FLASH_CTRL_START)) + break; + } + + if (value & SPI_FLASH_CTRL_START) + return false; + + *buf = ATL2_READ_REG(hw, REG_SPI_DATA); + + return true; +} + +/* + * get_permanent_address + * return 0 if get valid mac address, + */ +static int +get_permanent_address(struct atl2_hw *hw) +{ + u32 Addr[2]; + u32 i, Control; + u16 Register; + u8 EthAddr[NODE_ADDRESS_SIZE]; + bool KeyValid; + + if (is_valid_ether_addr(hw->perm_mac_addr)) + return 0; + + Addr[0] = 0; + Addr[1] = 0; + + if (!atl2_check_eeprom_exist(hw)) { /* eeprom exists */ + Register = 0; + KeyValid = false; + + /* Read out all EEPROM content */ + i = 0; + while (1) { + if (atl2_read_eeprom(hw, i + 0x100, &Control)) { + if (KeyValid) { + if (Register == REG_MAC_STA_ADDR) + Addr[0] = Control; + else if (Register == (REG_MAC_STA_ADDR + 4)) + Addr[1] = Control; + KeyValid = false; + } else if ((Control & 0xff) == 0x5A) { + KeyValid = true; + Register = (u16) (Control >> 16); + } else { + break; /* assume data end while encount an invalid KEYWORD */ + } + } else { + break; /* read error */ + } + i += 4; + } + + *(u32*) &EthAddr[2] = LONGSWAP(Addr[0]); + *(u16*) &EthAddr[0] = SHORTSWAP(*(u16*)&Addr[1]); + + if (is_valid_ether_addr(EthAddr)) { + memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); + return 0; + } + return 1; + } + + // see if SPI FLAHS exist ? + Addr[0] = 0; + Addr[1] = 0; + Register = 0; + KeyValid = false; + i = 0; + while (1) { + if (atl2_spi_read(hw, i + 0x1f000, &Control)) { + if (KeyValid) { + if (Register == REG_MAC_STA_ADDR) + Addr[0] = Control; + else if (Register == (REG_MAC_STA_ADDR + 4)) + Addr[1] = Control; + KeyValid = false; + } else if ((Control & 0xff) == 0x5A) { + KeyValid = true; + Register = (u16) (Control >> 16); + } else { + break; /* data end */ + } + } else { + break; /* read error */ + } + i += 4; + } + + *(u32*) &EthAddr[2] = LONGSWAP(Addr[0]); + *(u16*) &EthAddr[0] = SHORTSWAP(*(u16*)&Addr[1]); + if (is_valid_ether_addr(EthAddr)) { + memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); + return 0; + } + /* maybe MAC-address is from BIOS */ + Addr[0] = ATL2_READ_REG(hw,REG_MAC_STA_ADDR); + Addr[1] = ATL2_READ_REG(hw,REG_MAC_STA_ADDR+4); + *(u32*) &EthAddr[2] = LONGSWAP(Addr[0]); + *(u16*) &EthAddr[0] = SHORTSWAP(*(u16*)&Addr[1]); + + if (is_valid_ether_addr(EthAddr)) { + memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); + return 0; + } + + return 1; +} + +/* + * Reads the adapter's MAC address from the EEPROM + * + * hw - Struct containing variables accessed by shared code + */ +s32 +atl2_read_mac_addr(struct atl2_hw *hw) +{ + u16 i; + + if (get_permanent_address(hw)) { + // for test + hw->perm_mac_addr[0] = 0x00; + hw->perm_mac_addr[1] = 0x13; + hw->perm_mac_addr[2] = 0x74; + hw->perm_mac_addr[3] = 0x00; + hw->perm_mac_addr[4] = 0x5c; + hw->perm_mac_addr[5] = 0x38; + } + + for(i = 0; i < NODE_ADDRESS_SIZE; i++) + hw->mac_addr[i] = hw->perm_mac_addr[i]; + + return ATL2_SUCCESS; +} + +/* + * Hashes an address to determine its location in the multicast table + * + * hw - Struct containing variables accessed by shared code + * mc_addr - the multicast address to hash + * + * atl2_hash_mc_addr + * purpose + * set hash value for a multicast address + * hash calcu processing : + * 1. calcu 32bit CRC for multicast address + * 2. reverse crc with MSB to LSB + */ +u32 +atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr) +{ + u32 crc32, value=0; + int i; + + crc32 = ether_crc_le(6, mc_addr); + + for (i=0; i<32; i++) + value |= (((crc32>>i)&1)<<(31-i)); + + return value; +} + +/* + * Sets the bit in the multicast table corresponding to the hash value. + * + * hw - Struct containing variables accessed by shared code + * hash_value - Multicast address hash value + */ +void +atl2_hash_set(struct atl2_hw *hw, u32 hash_value) +{ + u32 hash_bit, hash_reg; + u32 mta; + + /* The HASH Table is a register array of 2 32-bit registers. + * It is treated like an array of 64 bits. We want to set + * bit BitArray[hash_value]. So we figure out what register + * the bit is in, read it, OR in the new bit, then write + * back the new value. The register is determined by the + * upper 7 bits of the hash value and the bit within that + * register are determined by the lower 5 bits of the value. + */ + hash_reg = (hash_value >> 31) & 0x1; + hash_bit = (hash_value >> 26) & 0x1F; + + mta = ATL2_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); + + mta |= (1 << hash_bit); + + ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); +} + +/* + * atl2_init_pcie - init PCIE module + */ +static void +atl2_init_pcie(struct atl2_hw *hw) +{ + u32 value; + value = LTSSM_TEST_MODE_DEF; + ATL2_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value); + + value = PCIE_DLL_TX_CTRL1_DEF; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, value); +} + +void +atl2_init_flash_opcode(struct atl2_hw *hw) +{ + if (hw->flash_vendor >= ARRAY_SIZE(flash_table)) { + hw->flash_vendor = 0; // ATMEL + } + // Init OP table + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_PROGRAM, flash_table[hw->flash_vendor].cmdPROGRAM); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_SC_ERASE, flash_table[hw->flash_vendor].cmdSECTOR_ERASE); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_CHIP_ERASE, flash_table[hw->flash_vendor].cmdCHIP_ERASE); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDID, flash_table[hw->flash_vendor].cmdRDID); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WREN, flash_table[hw->flash_vendor].cmdWREN); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDSR, flash_table[hw->flash_vendor].cmdRDSR); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WRSR, flash_table[hw->flash_vendor].cmdWRSR); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_READ, flash_table[hw->flash_vendor].cmdREAD); +} + +/******************************************************************** +* Performs basic configuration of the adapter. +* +* hw - Struct containing variables accessed by shared code +* Assumes that the controller has previously been reset and is in a +* post-reset uninitialized state. Initializes multicast table, +* and Calls routines to setup link +* Leaves the transmit and receive units disabled and uninitialized. +********************************************************************/ +s32 +atl2_init_hw(struct atl2_hw *hw) +{ + u32 ret_val = 0; + + atl2_init_pcie(hw); + + /* Zero out the Multicast HASH table */ + /* clear the old settings from the multicast hash table */ + ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); + ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); + + atl2_init_flash_opcode(hw); + + ret_val = atl2_phy_init(hw); + + return ret_val; +} + +/* + * Detects the current speed and duplex settings of the hardware. + * + * hw - Struct containing variables accessed by shared code + * speed - Speed of the connection + * duplex - Duplex setting of the connection + */ +s32 +atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed, u16 *duplex) +{ + s32 ret_val; + u16 phy_data; + + // ; --- Read PHY Specific Status Register (17) + ret_val = atl2_read_phy_reg(hw, MII_AT001_PSSR, &phy_data); + if (ret_val) + return ret_val; + + if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED)) + return ATL2_ERR_PHY_RES; + + switch(phy_data & MII_AT001_PSSR_SPEED) { + case MII_AT001_PSSR_100MBS: + *speed = SPEED_100; + break; + case MII_AT001_PSSR_10MBS: + *speed = SPEED_10; + break; + default: + return ATL2_ERR_PHY_SPEED; + break; + } + + if (phy_data & MII_AT001_PSSR_DPLX) { + *duplex = FULL_DUPLEX; + } else { + *duplex = HALF_DUPLEX; + } + + return ATL2_SUCCESS; +} + +/* + * Reads the value from a PHY register + * hw - Struct containing variables accessed by shared code + * reg_addr - address of the PHY register to read + */ +s32 +atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data) +{ + u32 val; + int i; + + val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | + MDIO_START | + MDIO_SUP_PREAMBLE | + MDIO_RW | + MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; + ATL2_WRITE_REG(hw, REG_MDIO_CTRL, val); + + wmb(); + + for (i=0; iMediaType) { + case MEDIA_TYPE_AUTO_SENSOR: + mii_autoneg_adv_reg |= + (MII_AR_10T_HD_CAPS | + MII_AR_10T_FD_CAPS | + MII_AR_100TX_HD_CAPS | + MII_AR_100TX_FD_CAPS); + hw->autoneg_advertised = + ADVERTISE_10_HALF | + ADVERTISE_10_FULL | + ADVERTISE_100_HALF | + ADVERTISE_100_FULL; + break; + case MEDIA_TYPE_100M_FULL: + mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS; + hw->autoneg_advertised = ADVERTISE_100_FULL; + break; + case MEDIA_TYPE_100M_HALF: + mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS; + hw->autoneg_advertised = ADVERTISE_100_HALF; + break; + case MEDIA_TYPE_10M_FULL: + mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS; + hw->autoneg_advertised = ADVERTISE_10_FULL; + break; + default: + mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS; + hw->autoneg_advertised = ADVERTISE_10_HALF; + break; + } + + /* flow control fixed to enable all */ + mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE); + + hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg; + + ret_val = atl2_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg); + + if(ret_val) + return ret_val; + + return ATL2_SUCCESS; +} + +/* + * Resets the PHY and make all config validate + * + * hw - Struct containing variables accessed by shared code + * + * Sets bit 15 and 12 of the MII Control regiser (for F001 bug) + */ +static s32 +atl2_phy_commit(struct atl2_hw *hw) +{ + s32 ret_val; + u16 phy_data; + +/* FIXME: use or remove -- CHS + if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR) { + phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN; + } else { + switch (hw->MediaType) + { + case MEDIA_TYPE_100M_FULL: + phy_data = MII_CR_FULL_DUPLEX|MII_CR_SPEED_100|MII_CR_RESET; + break; + case MEDIA_TYPE_100M_HALF: + phy_data = MII_CR_SPEED_100|MII_CR_RESET; + break; + case MEDIA_TYPE_10M_FULL: + phy_data = MII_CR_FULL_DUPLEX|MII_CR_SPEED_10|MII_CR_RESET; + break; + default: // MEDIA_TYPE_10M_HALF: + phy_data = MII_CR_SPEED_10|MII_CR_RESET; + break; + } + } +*/ + phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG; + ret_val = atl2_write_phy_reg(hw, MII_BMCR, phy_data); + if (ret_val) { // bug fixed + u32 val; + int i; + /* pcie serdes link may be down ! */ + for (i=0; i < 25; i++) { + msec_delay(1); + val = ATL2_READ_REG(hw, REG_MDIO_CTRL); + if (!(val & (MDIO_START | MDIO_BUSY))) + break; + } + + if (0 != (val & (MDIO_START | MDIO_BUSY))) { + printk(KERN_ERR "atl2: PCIe link down for at least 25ms !\n"); + return ret_val; + } + } + return ATL2_SUCCESS; +} + +s32 +atl2_phy_init(struct atl2_hw *hw) +{ + s32 ret_val; + u16 phy_val; + + if (hw->phy_configured) + return 0; + + /* Enable PHY */ + ATL2_WRITE_REGW(hw, REG_PHY_ENABLE, 1); + ATL2_WRITE_FLUSH(hw); + msec_delay(1); + + /* check if the PHY is in powersaving mode */ + atl2_write_phy_reg(hw, MII_DBG_ADDR, 0); + atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val); + + /* 024E / 124E 0r 0274 / 1274 ? */ + if (phy_val & 0x1000) { + phy_val &= ~0x1000; + atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val); + } + + msec_delay(1); + + + /*Enable PHY LinkChange Interrupt */ + ret_val = atl2_write_phy_reg(hw, 18, 0xC00); + if (ret_val) + return ret_val; + + /* setup AutoNeg parameters */ + ret_val = atl2_phy_setup_autoneg_adv(hw); + if(ret_val) + return ret_val; + + /* SW.Reset & En-Auto-Neg to restart Auto-Neg */ + ret_val = atl2_phy_commit(hw); + if (ret_val) + return ret_val; + + hw->phy_configured = true; + + return ret_val; +} + +void +atl2_set_mac_addr(struct atl2_hw *hw) +{ + u32 value; + // 00-0B-6A-F6-00-DC + // 0: 6AF600DC 1: 000B + // low dword + value = (((u32)hw->mac_addr[2]) << 24) | + (((u32)hw->mac_addr[3]) << 16) | + (((u32)hw->mac_addr[4]) << 8 ) | + (((u32)hw->mac_addr[5]) ) ; + ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); + // hight dword + value = (((u32)hw->mac_addr[0]) << 8 ) | + (((u32)hw->mac_addr[1]) ) ; + ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); +} + +/* + * check_eeprom_exist + * return 0 if eeprom exist + */ +int +atl2_check_eeprom_exist(struct atl2_hw *hw) +{ + u32 value; + + value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL); + if (value & SPI_FLASH_CTRL_EN_VPD) { + value &= ~SPI_FLASH_CTRL_EN_VPD; + ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); + } + value = ATL2_READ_REGW(hw, REG_PCIE_CAP_LIST); + return ((value & 0xFF00) == 0x6C00) ? 0 : 1; +} + +// FIXME: This doesn't look right. -- CHS +bool +atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value) +{ + return true; +} + +bool +atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue) +{ + int i; + u32 Control; + + if (Offset & 0x3) + return false; /* address do not align */ + + ATL2_WRITE_REG(hw, REG_VPD_DATA, 0); + Control = (Offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT; + ATL2_WRITE_REG(hw, REG_VPD_CAP, Control); + + for (i = 0; i < 10; i++) { + msec_delay(2); + Control = ATL2_READ_REG(hw, REG_VPD_CAP); + if (Control & VPD_CAP_VPD_FLAG) + break; + } + + if (Control & VPD_CAP_VPD_FLAG) { + *pValue = ATL2_READ_REG(hw, REG_VPD_DATA); + return true; + } + return false; /* timeout */ +} + +void +atl2_force_ps(struct atl2_hw *hw) +{ + u16 phy_val; + + atl2_write_phy_reg(hw, MII_DBG_ADDR, 0); + atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val); + atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val | 0x1000); + + atl2_write_phy_reg(hw, MII_DBG_ADDR, 2); + atl2_write_phy_reg(hw, MII_DBG_DATA, 0x3000); + atl2_write_phy_reg(hw, MII_DBG_ADDR, 3); + atl2_write_phy_reg(hw, MII_DBG_DATA, 0); +} --- linux-2.6.27.orig/ubuntu/atl2/atl2_hw.h +++ linux-2.6.27/ubuntu/atl2/atl2_hw.h @@ -0,0 +1,758 @@ +/* atl2_hw.h -- atl2 hardware definitions + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Some of these defines are unused for various reasons. Some describe + * hardware features we don't yet use. Some are specific to the cousin atl1 + * hardware, which we may merge this driver with in the future. Please + * remember this is a surrogate for hardware specs, and don't unnecessarily + * abuse the content or formatting. -- CHS + */ + +#ifndef _ATL2_HW_H_ +#define _ATL2_HW_H_ + +#include "atl2_osdep.h" + +struct atl2_adapter; +struct atl2_hw; + +/* function prototype */ +s32 atl2_reset_hw(struct atl2_hw *hw); +s32 atl2_read_mac_addr(struct atl2_hw *hw); +s32 atl2_init_hw(struct atl2_hw *hw); +s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed, u16 *duplex); +u32 atl2_auto_get_fc(struct atl2_adapter *adapter, u16 duplex); +u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr); +void atl2_hash_set(struct atl2_hw *hw, u32 hash_value); +s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data); +s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data); +void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value); +void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value); +s32 atl2_validate_mdi_setting(struct atl2_hw *hw); +void atl2_set_mac_addr(struct atl2_hw *hw); +bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue); +bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value); +s32 atl2_phy_init(struct atl2_hw *hw); +int atl2_check_eeprom_exist(struct atl2_hw *hw); +void atl2_force_ps(struct atl2_hw *hw); + +/* register definition */ +#define REG_PM_CTRLSTAT 0x44 + +#define REG_PCIE_CAP_LIST 0x58 + +#define REG_VPD_CAP 0x6C +#define VPD_CAP_ID_MASK 0xff +#define VPD_CAP_ID_SHIFT 0 +#define VPD_CAP_NEXT_PTR_MASK 0xFF +#define VPD_CAP_NEXT_PTR_SHIFT 8 +#define VPD_CAP_VPD_ADDR_MASK 0x7FFF +#define VPD_CAP_VPD_ADDR_SHIFT 16 +#define VPD_CAP_VPD_FLAG 0x80000000 + +#define REG_VPD_DATA 0x70 + +#define REG_SPI_FLASH_CTRL 0x200 +#define SPI_FLASH_CTRL_STS_NON_RDY 0x1 +#define SPI_FLASH_CTRL_STS_WEN 0x2 +#define SPI_FLASH_CTRL_STS_WPEN 0x80 +#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF +#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0 +#define SPI_FLASH_CTRL_INS_MASK 0x7 +#define SPI_FLASH_CTRL_INS_SHIFT 8 +#define SPI_FLASH_CTRL_START 0x800 +#define SPI_FLASH_CTRL_EN_VPD 0x2000 +#define SPI_FLASH_CTRL_LDSTART 0x8000 +#define SPI_FLASH_CTRL_CS_HI_MASK 0x3 +#define SPI_FLASH_CTRL_CS_HI_SHIFT 16 +#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3 +#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18 +#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3 +#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20 +#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3 +#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22 +#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3 +#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24 +#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3 +#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26 +#define SPI_FLASH_CTRL_WAIT_READY 0x10000000 + +#define REG_SPI_ADDR 0x204 + +#define REG_SPI_DATA 0x208 + +#define REG_SPI_FLASH_CONFIG 0x20C +#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF +#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0 +#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3 +#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24 +#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000 + +#define REG_SPI_FLASH_OP_PROGRAM 0x210 +#define REG_SPI_FLASH_OP_SC_ERASE 0x211 +#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212 +#define REG_SPI_FLASH_OP_RDID 0x213 +#define REG_SPI_FLASH_OP_WREN 0x214 +#define REG_SPI_FLASH_OP_RDSR 0x215 +#define REG_SPI_FLASH_OP_WRSR 0x216 +#define REG_SPI_FLASH_OP_READ 0x217 + +#define REG_TWSI_CTRL 0x218 +#define TWSI_CTRL_LD_OFFSET_MASK 0xFF +#define TWSI_CTRL_LD_OFFSET_SHIFT 0 +#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 +#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 +#define TWSI_CTRL_SW_LDSTART 0x800 +#define TWSI_CTRL_HW_LDSTART 0x1000 +#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x0x7F +#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 +#define TWSI_CTRL_LD_EXIST 0x400000 +#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 +#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 +#define TWSI_CTRL_FREQ_SEL_100K 0 +#define TWSI_CTRL_FREQ_SEL_200K 1 +#define TWSI_CTRL_FREQ_SEL_300K 2 +#define TWSI_CTRL_FREQ_SEL_400K 3 +#define TWSI_CTRL_SMB_SLV_ADDR +#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 +#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 + +#define REG_PCIE_DEV_MISC_CTRL 0x21C +#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2 +#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1 +#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4 +#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8 +#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10 + +#define REG_PCIE_PHYMISC 0x1000 +#define PCIE_PHYMISC_FORCE_RCV_DET 0x4 + +#define REG_PCIE_DLL_TX_CTRL1 0x1104 +#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK 0x0400 +#define PCIE_DLL_TX_CTRL1_DEF 0x0568 + +#define REG_LTSSM_TEST_MODE 0x12FC +#define LTSSM_TEST_MODE_DEF 0x6500 + +/* Master Control Register */ +#define REG_MASTER_CTRL 0x1400 +#define MASTER_CTRL_SOFT_RST 0x1 +#define MASTER_CTRL_MTIMER_EN 0x2 +#define MASTER_CTRL_ITIMER_EN 0x4 +#define MASTER_CTRL_MANUAL_INT 0x8 +#define MASTER_CTRL_REV_NUM_SHIFT 16 +#define MASTER_CTRL_REV_NUM_MASK 0xff +#define MASTER_CTRL_DEV_ID_SHIFT 24 +#define MASTER_CTRL_DEV_ID_MASK 0xff + +/* Timer Initial Value Register */ +#define REG_MANUAL_TIMER_INIT 0x1404 + +/* IRQ ModeratorTimer Initial Value Register */ +#define REG_IRQ_MODU_TIMER_INIT 0x1408 + +#define REG_PHY_ENABLE 0x140C +// IRQ Anti-Lost Timer Initial Value Register +//#define REG_IRQ_CLR_TIMER 0x140c // Maximum allowance for software to clear the interrupt. +// IRQ Anti-Lost Timer Initial Value Register +#define REG_CMBDISDMA_TIMER 0x140E + +/* Block IDLE Status Register */ +#define REG_IDLE_STATUS 0x1410 +#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */ +#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */ +#define IDLE_STATUS_DMAR 8 /* 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling */ +#define IDLE_STATUS_DMAW 4 /* 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling */ + +/* MDIO Control Register */ +#define REG_MDIO_CTRL 0x1414 +#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit control data to write to PHY MII management register */ +#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit status data that was read from the PHY MII management register. */ +#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ +#define MDIO_REG_ADDR_SHIFT 16 +#define MDIO_RW 0x200000 /* 1: read, 0: write */ +#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ +#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle. */ +#define MDIO_CLK_SEL_SHIFT 24 +#define MDIO_CLK_25_4 0 +#define MDIO_CLK_25_6 2 +#define MDIO_CLK_25_8 3 +#define MDIO_CLK_25_10 4 +#define MDIO_CLK_25_14 5 +#define MDIO_CLK_25_20 6 +#define MDIO_CLK_25_28 7 +#define MDIO_BUSY 0x8000000 +#define MDIO_WAIT_TIMES 10 + +/* SerDes Lock Detect Control and Status Register */ +#define REG_SERDES_LOCK 0x1424 +#define SERDES_LOCK_DETECT 1 /* 1: SerDes lock detected. This signal comes from Analog SerDes. */ +#define SERDES_LOCK_DETECT_EN 2 /* 1: Enable SerDes Lock detect function. */ + +/* MAC Control Register */ +#define REG_MAC_CTRL 0x1480 +#define MAC_CTRL_TX_EN 1 /* 1: Transmit Enable */ +#define MAC_CTRL_RX_EN 2 /* 1: Receive Enable */ +#define MAC_CTRL_TX_FLOW 4 /* 1: Transmit Flow Control Enable */ +#define MAC_CTRL_RX_FLOW 8 /* 1: Receive Flow Control Enable */ +#define MAC_CTRL_LOOPBACK 0x10 /* 1: Loop back at G/MII Interface */ +#define MAC_CTRL_DUPLX 0x20 /* 1: Full-duplex mode 0: Half-duplex mode */ +#define MAC_CTRL_ADD_CRC 0x40 /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */ +#define MAC_CTRL_PAD 0x80 /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */ +#define MAC_CTRL_PRMLEN_SHIFT 10 /* Preamble length, it's 0x07 by standard */ +#define MAC_CTRL_PRMLEN_MASK 0xf +#define MAC_CTRL_RMV_VLAN 0x4000 /* 1: to remove VLAN Tag automatically from all receive packets */ +#define MAC_CTRL_PROMIS_EN 0x8000 /* 1: Promiscuous Mode Enable */ +#define MAC_CTRL_DBG_TX_BKPRESURE 0x100000 /* 1: transmit maximum backoff (half-duplex test bit) */ +#define MAC_CTRL_MC_ALL_EN 0x2000000 /* 1: upload all multicast frame without error to system */ +#define MAC_CTRL_BC_EN 0x4000000 /* 1: upload all broadcast frame without error to system */ +#define MAC_CTRL_MACLP_CLK_PHY 0x8000000 /* 1: MAC-LoopBack clock from phy, 0:from sys_25M */ +#define MAC_CTRL_HALF_LEFT_BUF_SHIFT 28 +#define MAC_CTRL_HALF_LEFT_BUF_MASK 0xF /* When half-duplex mode, should hold some bytes for mac retry . (8*4bytes unit) */ + +/* MAC IPG/IFG Control Register */ +#define REG_MAC_IPG_IFG 0x1484 +#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back inter-packet gap. The default is 96-bit time. */ +#define MAC_IPG_IFG_IPGT_MASK 0x7f +#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to enforce in between RX frames. */ +#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped. */ +#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */ +#define MAC_IPG_IFG_IPGR1_MASK 0x7f +#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */ +#define MAC_IPG_IFG_IPGR2_MASK 0x7f + +/* MAC STATION ADDRESS */ +#define REG_MAC_STA_ADDR 0x1488 + +/* Hash table for multicast address */ +#define REG_RX_HASH_TABLE 0x1490 + +/* MAC Half-Duplex Control Register */ +#define REG_MAC_HALF_DUPLX_CTRL 0x1498 +#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window. */ +#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff +#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 /* Retransmission maximum, afterwards the packet will be discarded. */ +#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf +#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */ +#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 /* 1: No back-off on collision, immediately start the retransmission. */ +#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */ +#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */ +#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number. */ +#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf +#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */ +#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time. */ + +/* Maximum Frame Length Control Register */ +#define REG_MTU 0x149c + +/* Wake-On-Lan control register */ +#define REG_WOL_CTRL 0x14a0 +#define WOL_PATTERN_EN 0x00000001 +#define WOL_PATTERN_PME_EN 0x00000002 +#define WOL_MAGIC_EN 0x00000004 +#define WOL_MAGIC_PME_EN 0x00000008 +#define WOL_LINK_CHG_EN 0x00000010 +#define WOL_LINK_CHG_PME_EN 0x00000020 +#define WOL_PATTERN_ST 0x00000100 +#define WOL_MAGIC_ST 0x00000200 +#define WOL_LINKCHG_ST 0x00000400 +#define WOL_PT0_EN 0x00010000 +#define WOL_PT1_EN 0x00020000 +#define WOL_PT2_EN 0x00040000 +#define WOL_PT3_EN 0x00080000 +#define WOL_PT4_EN 0x00100000 +#define WOL_PT0_MATCH 0x01000000 +#define WOL_PT1_MATCH 0x02000000 +#define WOL_PT2_MATCH 0x04000000 +#define WOL_PT3_MATCH 0x08000000 +#define WOL_PT4_MATCH 0x10000000 + +/* Internal SRAM Partition Register */ +#define REG_SRAM_TXRAM_END 0x1500 /* Internal tail address of TXRAM default: 2byte*1024 */ +#define REG_SRAM_RXRAM_END 0x1502 /* Internal tail address of RXRAM default: 2byte*1024 */ + +/* +#define REG_SRAM_TCPH_PATH_ADDR (REG_SRAM_RFD_ADDR+48) +#define SRAM_TCPH_ADDR_MASK 0x0fff +#define SRAM_TCPH_ADDR_SHIFT 0 +#define SRAM_PATH_ADDR_MASK 0x0fff +#define SRAM_PATH_ADDR_SHIFT 16 +*/ + +/* Descriptor Control register */ +#define REG_DESC_BASE_ADDR_HI 0x1540 +#define REG_TXD_BASE_ADDR_LO 0x1544 /* The base address of the Transmit Data Memory low 32-bit(dword align) */ +#define REG_TXD_MEM_SIZE 0x1548 /* Transmit Data Memory size(by double word , max 256KB) */ +#define REG_TXS_BASE_ADDR_LO 0x154C /* The base address of the Transmit Status Memory low 32-bit(dword word align) */ +#define REG_TXS_MEM_SIZE 0x1550 /* double word unit, max 4*2047 bytes. */ +#define REG_RXD_BASE_ADDR_LO 0x1554 /* The base address of the Transmit Status Memory low 32-bit(unit 8 bytes) */ +#define REG_RXD_BUF_NUM 0x1558 /* Receive Data & Status Memory buffer number (unit 1536bytes, max 1536*2047) */ + +/* DMAR Control Register */ +#define REG_DMAR 0x1580 +#define DMAR_EN 0x1 /* 1: Enable DMAR */ + +/* TX Cur-Through (early tx threshold) Control Register */ +#define REG_TX_CUT_THRESH 0x1590 /* TxMac begin transmit packet threshold(unit word) */ + +/* DMAW Control Register */ +#define REG_DMAW 0x15A0 +#define DMAW_EN 0x1 + +/* Flow control register */ +#define REG_PAUSE_ON_TH 0x15A8 /* RXD high watermark of overflow threshold configuration register */ +#define REG_PAUSE_OFF_TH 0x15AA /* RXD lower watermark of overflow threshold configuration register */ + +/* Mailbox Register */ +#define REG_MB_TXD_WR_IDX 0x15f0 /* double word align */ +#define REG_MB_RXD_RD_IDX 0x15F4 /* RXD Read index (unit: 1536byets) */ + +/* Interrupt Status Register */ +#define REG_ISR 0x1600 +#define ISR_TIMER 1 /* Interrupt when Timer is counted down to zero */ +#define ISR_MANUAL 2 /* Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set in Table 51 Selene Master Control Register (Offset 0x1400). */ +#define ISR_RXF_OV 4 /* RXF overflow interrupt */ +#define ISR_TXF_UR 8 /* TXF underrun interrupt */ +#define ISR_TXS_OV 0x10 /* Internal transmit status buffer full interrupt */ +#define ISR_RXS_OV 0x20 /* Internal receive status buffer ful interrupt */ +#define ISR_LINK_CHG 0x40 /* Link Status Change Interrupt */ +#define ISR_HOST_TXD_UR 0x80 +#define ISR_HOST_RXD_OV 0x100 /* Host rx data memory full , one pulse */ +//#define ISR_HOST_TXS_OV 0x200 /* Host tx status memory full , one pulse */ +#define ISR_DMAR_TO_RST 0x200 /* DMAR op timeout interrupt. SW should do Reset */ +#define ISR_DMAW_TO_RST 0x400 +#define ISR_PHY 0x800 /* phy interrupt */ +#define ISR_TS_UPDATE 0x10000 /* interrupt after new tx pkt status written to host */ +#define ISR_RS_UPDATE 0x20000 /* interrupt ater new rx pkt status written to host. */ +#define ISR_TX_EARLY 0x40000 /* interrupt when txmac begin transmit one packet */ +#define ISR_UR_DETECTED 0x1000000 +#define ISR_FERR_DETECTED 0x2000000 +#define ISR_NFERR_DETECTED 0x4000000 +#define ISR_CERR_DETECTED 0x8000000 +#define ISR_PHY_LINKDOWN 0x10000000 +#define ISR_DIS_INT 0x80000000 + +#define ISR_TX_EVENT (ISR_TXF_UR|ISR_TXS_OV|ISR_HOST_TXD_UR|ISR_TS_UPDATE|ISR_TX_EARLY) +#define ISR_RX_EVENT (ISR_RXF_OV|ISR_RXS_OV|ISR_HOST_RXD_OV|ISR_RS_UPDATE) + +/* Interrupt Mask Register */ +#define REG_IMR 0x1604 + +#define IMR_NORMAL_MASK (\ + /*ISR_LINK_CHG |*/\ + ISR_MANUAL |\ + ISR_DMAR_TO_RST |\ + ISR_DMAW_TO_RST |\ + ISR_PHY |\ + ISR_PHY_LINKDOWN |\ + ISR_TS_UPDATE |\ + ISR_RS_UPDATE ) + +/* Receive MAC Statistics Registers */ +#define REG_STS_RX_PAUSE 0x1700 /* The number of Pause packet received */ +#define REG_STS_RXD_OV 0x1704 /* The number of frame dropped due to occurrence of RX FIFO overflow */ +#define REG_STS_RXS_OV 0x1708 /* The number of frame dropped due to occerrence of RX Status Buffer Overflow */ +#define REG_STS_RX_FILTER 0x170C /* The number of packet dropped due to address filtering */ + +/* MII definitions */ + +/* PHY Common Register */ +#define MII_AT001_CR 0x09 +#define MII_AT001_SR 0x0A +#define MII_AT001_ESR 0x0F +#define MII_AT001_PSCR 0x10 +#define MII_AT001_PSSR 0x11 +#define MII_SMARTSPEED 0x14 +#define MII_DBG_ADDR 0x1D +#define MII_DBG_DATA 0x1E + +/* PHY Control Register */ +#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ +#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ +#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ +#define MII_CR_SPEED_MASK 0x2040 +#define MII_CR_SPEED_1000 0x0040 +#define MII_CR_SPEED_100 0x2000 +#define MII_CR_SPEED_10 0x0000 + +/* PHY Status Register */ +#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ +#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ +#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ +#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ +#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ +#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ +#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ +#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ +#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ +#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ +#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ +#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ +#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ +#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ +#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ + +/* Link partner ability register. */ +#define MII_LPA_SLCT 0x001f /* Same as advertise selector */ +#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */ +#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */ +#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */ +#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */ +#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */ +#define MII_LPA_PAUSE 0x0400 /* PAUSE */ +#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */ +#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */ +#define MII_LPA_LPACK 0x4000 /* Link partner acked us */ +#define MII_LPA_NPAGE 0x8000 /* Next page bit */ + +/* Autoneg Advertisement Register */ +#define MII_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ +#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ +#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ +#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ +#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ +#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ +#define MII_AR_PAUSE 0x0400 /* Pause operation desired */ +#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ +#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ +#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ +#define MII_AR_SPEED_MASK 0x01E0 +#define MII_AR_DEFAULT_CAP_MASK 0x0DE0 + +/* 1000BASE-T Control Register */ +#define MII_AT001_CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ +#define MII_AT001_CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ +#define MII_AT001_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port, 0=DTE device */ +#define MII_AT001_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master, 0=Configure PHY as Slave */ +#define MII_AT001_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value, 0=Automatic Master/Slave config */ +#define MII_AT001_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ +#define MII_AT001_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ +#define MII_AT001_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ +#define MII_AT001_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ +#define MII_AT001_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ +#define MII_AT001_CR_1000T_SPEED_MASK 0x0300 +#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK 0x0300 + +/* 1000BASE-T Status Register */ +#define MII_AT001_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ +#define MII_AT001_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ +#define MII_AT001_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ +#define MII_AT001_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ +#define MII_AT001_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ +#define MII_AT001_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ +#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT 12 +#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT 13 + +/* Extended Status Register */ +#define MII_AT001_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ +#define MII_AT001_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ +#define MII_AT001_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ +#define MII_AT001_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ + +/* AT001 PHY Specific Control Register */ +#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ +#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ +#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled *// +#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008 +#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, 0=CLK125 toggling */ +#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5, Manual MDI configuration */ +#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ +#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ +#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled all speeds. */ +#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080 /* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T RX Threshold), 0=Normal 10BASE-T RX Threshold */ +#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100 /* 1=5-Bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */ +#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ +#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ +#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ +#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1 +#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5 +#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 + +/* AT001 PHY Specific Status Register */ +#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ +#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ +#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ +#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */ +#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */ +#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ + +/* PCI Command Register Bit Definitions */ +#define PCI_REG_COMMAND 0x04 +#define CMD_IO_SPACE 0x0001 +#define CMD_MEMORY_SPACE 0x0002 +#define CMD_BUS_MASTER 0x0004 + +/* Wake Up Filter Control */ +#define ATL2_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ +#define ATL2_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ +#define ATL2_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ +#define ATL2_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */ +#define ATL2_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ + +/* Error Codes */ +#define ATL2_SUCCESS 0 +#define ATL2_ERR_EEPROM 1 +#define ATL2_ERR_PHY 2 +#define ATL2_ERR_CONFIG 3 +#define ATL2_ERR_PARAM 4 +#define ATL2_ERR_MAC_TYPE 5 +#define ATL2_ERR_PHY_TYPE 6 +#define ATL2_ERR_PHY_SPEED 7 +#define ATL2_ERR_PHY_RES 8 + +#define SPEED_0 0xffff +#define SPEED_10 10 +#define SPEED_100 100 +#define HALF_DUPLEX 1 +#define FULL_DUPLEX 2 + +#define MEDIA_TYPE_AUTO_SENSOR 0 +#define MEDIA_TYPE_100M_FULL 1 +#define MEDIA_TYPE_100M_HALF 2 +#define MEDIA_TYPE_10M_FULL 3 +#define MEDIA_TYPE_10M_HALF 4 + +#define ADVERTISE_10_HALF 0x0001 +#define ADVERTISE_10_FULL 0x0002 +#define ADVERTISE_100_HALF 0x0004 +#define ADVERTISE_100_FULL 0x0008 +#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ +#define ADVERTISE_1000_FULL 0x0020 + +#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x000F /* Everything */ +#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/ +#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/ + +/* The size (in bytes) of a ethernet packet */ +#define ENET_HEADER_SIZE 14 +#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */ +#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */ +#define ETHERNET_FCS_SIZE 4 +#define MAX_JUMBO_FRAME_SIZE 0x2000 +#define VLAN_SIZE 4 + +#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ +#define PHY_FORCE_TIME 20 /* 2.0 Seconds */ + +/* For checksumming , the sum of all words in the EEPROM should equal 0xBABA */ +#define EEPROM_SUM 0xBABA +#define NODE_ADDRESS_SIZE 6 + +typedef struct _tx_pkt_header { + unsigned pkt_size : 11; + unsigned : 4; // reserved + unsigned ins_vlan : 1; // txmac should insert vlan + unsigned short vlan ; // vlan tag +} tx_pkt_header_t; +/* FIXME: replace above bitfields with MASK/SHIFT defines below */ +#define TX_PKT_HEADER_SIZE_MASK 0x7FF +#define TX_PKT_HEADER_SIZE_SHIFT 0 +#define TX_PKT_HEADER_INS_VLAN_MASK 0x1 +#define TX_PKT_HEADER_INS_VLAN_SHIFT 15 +#define TX_PKT_HEADER_VLAN_TAG_MASK 0xFFFF +#define TX_PKT_HEADER_VLAN_TAG_SHIFT 16 + +typedef struct _tx_pkt_status { + unsigned pkt_size : 11; + unsigned : 5; // reserved + unsigned ok : 1; // current packet is transmitted ok without error + unsigned bcast : 1; // current packet is broadcast + unsigned mcast : 1; // current packet is multicast + unsigned pause : 1; // transmiited a pause frame + unsigned ctrl : 1; + unsigned defer : 1; // current packet is xmitted with defer. + unsigned exc_defer : 1; + unsigned single_col : 1; + unsigned multi_col : 1; + unsigned late_col : 1; + unsigned abort_col : 1; + unsigned underun : 1; // current packet is abort due to txram underrun. + unsigned : 3; // reserved + unsigned update : 1; // always 1'b1 in tx_status_buf. +} tx_pkt_status_t; +/* FIXME: replace above bitfields with MASK/SHIFT defines below */ +#define TX_PKT_STATUS_SIZE_MASK 0x7FF +#define TX_PKT_STATUS_SIZE_SHIFT 0 +#define TX_PKT_STATUS_OK_MASK 0x1 +#define TX_PKT_STATUS_OK_SHIFT 16 +#define TX_PKT_STATUS_BCAST_MASK 0x1 +#define TX_PKT_STATUS_BCAST_SHIFT 17 +#define TX_PKT_STATUS_MCAST_MASK 0x1 +#define TX_PKT_STATUS_MCAST_SHIFT 18 +#define TX_PKT_STATUS_PAUSE_MASK 0x1 +#define TX_PKT_STATUS_PAUSE_SHIFT 19 +#define TX_PKT_STATUS_CTRL_MASK 0x1 +#define TX_PKT_STATUS_CTRL_SHIFT 20 +#define TX_PKT_STATUS_DEFER_MASK 0x1 +#define TX_PKT_STATUS_DEFER_SHIFT 21 +#define TX_PKT_STATUS_EXC_DEFER_MASK 0x1 +#define TX_PKT_STATUS_EXC_DEFER_SHIFT 22 +#define TX_PKT_STATUS_SINGLE_COL_MASK 0x1 +#define TX_PKT_STATUS_SINGLE_COL_SHIFT 23 +#define TX_PKT_STATUS_MULTI_COL_MASK 0x1 +#define TX_PKT_STATUS_MULTI_COL_SHIFT 24 +#define TX_PKT_STATUS_LATE_COL_MASK 0x1 +#define TX_PKT_STATUS_LATE_COL_SHIFT 25 +#define TX_PKT_STATUS_ABORT_COL_MASK 0x1 +#define TX_PKT_STATUS_ABORT_COL_SHIFT 26 +#define TX_PKT_STATUS_UNDERRUN_MASK 0x1 +#define TX_PKT_STATUS_UNDERRUN_SHIFT 27 +#define TX_PKT_STATUS_UPDATE_MASK 0x1 +#define TX_PKT_STATUS_UPDATE_SHIFT 31 + +typedef struct _rx_pkt_status { + unsigned pkt_size : 11; // packet size, max 2047bytes + unsigned : 5; // reserved + unsigned ok : 1; // current packet is received ok without error. + unsigned bcast : 1; // current packet is broadcast. + unsigned mcast : 1; // current packet is multicast. + unsigned pause : 1; + unsigned ctrl : 1; + unsigned crc : 1; // received a packet with crc error. + unsigned code : 1; // received a packet with code error. + unsigned runt : 1; // received a packet less than 64bytes with good crc + unsigned frag : 1; // ....................................with bad crc + unsigned trunc : 1; // current frame is cutted due to rxram full. + unsigned align : 1; // this packet is alignment error. + unsigned vlan : 1; // this packet has vlan + unsigned : 3; // reserved + unsigned update : 1; + unsigned short vtag ; // vlan tag + unsigned : 16; +} rx_pkt_status_t; +/* FIXME: replace above bitfields with MASK/SHIFT defines below */ +#define RX_PKT_STATUS_SIZE_MASK 0x7FF +#define RX_PKT_STATUS_SIZE_SHIFT 0 +#define RX_PKT_STATUS_OK_MASK 0x1 +#define RX_PKT_STATUS_OK_SHIFT 16 +#define RX_PKT_STATUS_BCAST_MASK 0x1 +#define RX_PKT_STATUS_BCAST_SHIFT 17 +#define RX_PKT_STATUS_MCAST_MASK 0x1 +#define RX_PKT_STATUS_MCAST_SHIFT 18 +#define RX_PKT_STATUS_PAUSE_MASK 0x1 +#define RX_PKT_STATUS_PAUSE_SHIFT 19 +#define RX_PKT_STATUS_CTRL_MASK 0x1 +#define RX_PKT_STATUS_CTRL_SHIFT 20 +#define RX_PKT_STATUS_CRC_MASK 0x1 +#define RX_PKT_STATUS_CRC_SHIFT 21 +#define RX_PKT_STATUS_CODE_MASK 0x1 +#define RX_PKT_STATUS_CODE_SHIFT 22 +#define RX_PKT_STATUS_RUNT_MASK 0x1 +#define RX_PKT_STATUS_RUNT_SHIFT 23 +#define RX_PKT_STATUS_FRAG_MASK 0x1 +#define RX_PKT_STATUS_FRAG_SHIFT 24 +#define RX_PKT_STATUS_TRUNK_MASK 0x1 +#define RX_PKT_STATUS_TRUNK_SHIFT 25 +#define RX_PKT_STATUS_ALIGN_MASK 0x1 +#define RX_PKT_STATUS_ALIGN_SHIFT 26 +#define RX_PKT_STATUS_VLAN_MASK 0x1 +#define RX_PKT_STATUS_VLAN_SHIFT 27 +#define RX_PKT_STATUS_UPDATE_MASK 0x1 +#define RX_PKT_STATUS_UPDATE_SHIFT 31 +#define RX_PKT_STATUS_VLAN_TAG_MASK 0xFFFF +#define RX_PKT_STATUS_VLAN_TAG_SHIFT 32 + +typedef struct _rx_desc { + rx_pkt_status_t status; + unsigned char packet[1536-sizeof(rx_pkt_status_t)]; +} rx_desc_t; + +typedef enum { + atl2_10_half = 0, + atl2_10_full = 1, + atl2_100_half = 2, + atl2_100_full = 3 +} atl2_speed_duplex_type; + +struct atl2_spi_flash_dev { + const char *manu_name; /* manufacturer id */ + /* op-code */ + u8 cmdWRSR; + u8 cmdREAD; + u8 cmdPROGRAM; + u8 cmdWREN; + u8 cmdWRDI; + u8 cmdRDSR; + u8 cmdRDID; + u8 cmdSECTOR_ERASE; + u8 cmdCHIP_ERASE; +}; + +/* Structure containing variables used by the shared code (atl2_hw.c) */ +struct atl2_hw { + u8 *hw_addr; + void *back; + + u8 preamble_len; + u8 max_retry; // Retransmission maximum , afterwards the packet will be discarded. + u8 jam_ipg; // IPG to start JAM for collision based flow control in half-duplex mode. In unit of 8-bit time. + u8 ipgt; // Desired back to back inter-packet gap. The default is 96-bit time. + u8 min_ifg; // Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped. + u8 ipgr1; // 64bit Carrier-Sense window + u8 ipgr2; // 96-bit IPG window + u8 retry_buf; // When half-duplex mode, should hold some bytes for mac retry . (8*4bytes unit) + + u16 fc_rxd_hi; + u16 fc_rxd_lo; + u16 lcol; // Collision Window + u16 max_frame_size; + + u16 MediaType; + u16 autoneg_advertised; + u16 pci_cmd_word; + + u16 mii_autoneg_adv_reg; + + u32 mem_rang; + u32 txcw; + u32 mc_filter_type; + u32 num_mc_addrs; + u32 collision_delta; + u32 tx_packet_delta; + u16 phy_spd_default; + + u16 device_id; + u16 vendor_id; + u16 subsystem_id; + u16 subsystem_vendor_id; + u8 revision_id; + + // spi flash + u8 flash_vendor; + + u8 dma_fairness; + u8 mac_addr[NODE_ADDRESS_SIZE]; + u8 perm_mac_addr[NODE_ADDRESS_SIZE]; + + // bool phy_preamble_sup; + bool phy_configured; +}; + +#endif /* _ATL2_HW_H_ */ --- linux-2.6.27.orig/ubuntu/atl2/atl2_param.c +++ linux-2.6.27/ubuntu/atl2/atl2_param.c @@ -0,0 +1,317 @@ +/* atl2_param.c -- atl2 parameter processing + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "atl2.h" + +/* This is the only thing that needs to be changed to adjust the + * maximum number of ports that the driver can manage. + */ +#define ATL2_MAX_NIC 4 + +#define OPTION_UNSET -1 +#define OPTION_DISABLED 0 +#define OPTION_ENABLED 1 + +/* All parameters are treated the same, as an integer array of values. + * This macro just reduces the need to repeat the same declaration code + * over and over (plus this helps to avoid typo bugs). + */ +#define ATL2_PARAM_INIT { [0 ... ATL2_MAX_NIC] = OPTION_UNSET } +#ifndef module_param_array +/* Module Parameters are always initialized to -1, so that the driver + * can tell the difference between no user specified value or the + * user asking for the default value. + * The true default values are loaded in when atl2_check_options is called. + * + * This is a GCC extension to ANSI C. + * See the item "Labeled Elements in Initializers" in the section + * "Extensions to the C Language Family" of the GCC documentation. + */ + +#define ATL2_PARAM(X, desc) \ + static const int __devinitdata X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \ + MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \ + MODULE_PARM_DESC(X, desc); +#else +#define ATL2_PARAM(X, desc) \ + static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \ + static int num_##X = 0; \ + module_param_array_named(X, X, int, &num_##X, 0); \ + MODULE_PARM_DESC(X, desc); +#endif + +/* Transmit Memory Size + * + * Valid Range: 64-2048 + * + * Default Value: 128 + */ +#define ATL2_MIN_TX_MEMSIZE 4 // 4KB +#define ATL2_MAX_TX_MEMSIZE 64 // 64KB +#define ATL2_DEFAULT_TX_MEMSIZE 8 // 8KB +ATL2_PARAM(TxMemSize, "Bytes of Transmit Memory"); + +/* Receive Memory Block Count + * + * Valid Range: 16-512 + * + * Default Value: 128 + */ +#define ATL2_MIN_RXD_COUNT 16 +#define ATL2_MAX_RXD_COUNT 512 +#define ATL2_DEFAULT_RXD_COUNT 64 +ATL2_PARAM(RxMemBlock, "Number of receive memory block"); + +/* User Specified MediaType Override + * + * Valid Range: 0-5 + * - 0 - auto-negotiate at all supported speeds + * - 1 - only link at 1000Mbps Full Duplex + * - 2 - only link at 100Mbps Full Duplex + * - 3 - only link at 100Mbps Half Duplex + * - 4 - only link at 10Mbps Full Duplex + * - 5 - only link at 10Mbps Half Duplex + * Default Value: 0 + */ +ATL2_PARAM(MediaType, "MediaType Select"); + +/* Interrupt Moderate Timer in units of 2 us + * + * Valid Range: 10-65535 + * + * Default Value: 45000(90ms) + */ +#define INT_MOD_DEFAULT_CNT 100 // 200us +#define INT_MOD_MAX_CNT 65000 +#define INT_MOD_MIN_CNT 50 +ATL2_PARAM(IntModTimer, "Interrupt Moderator Timer"); + +/* FlashVendor + * Valid Range: 0-2 + * 0 - Atmel + * 1 - SST + * 2 - ST + */ +ATL2_PARAM(FlashVendor, "SPI Flash Vendor"); + +#define AUTONEG_ADV_DEFAULT 0x2F +#define AUTONEG_ADV_MASK 0x2F +#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL + +#define FLASH_VENDOR_DEFAULT 0 +#define FLASH_VENDOR_MIN 0 +#define FLASH_VENDOR_MAX 2 + +struct atl2_option { + enum { enable_option, range_option, list_option } type; + char *name; + char *err; + int def; + union { + struct { /* range_option info */ + int min; + int max; + } r; + struct { /* list_option info */ + int nr; + struct atl2_opt_list { int i; char *str; } *p; + } l; + } arg; +}; + +static int __devinit +atl2_validate_option(int *value, struct atl2_option *opt) +{ + int i; + struct atl2_opt_list *ent; + + if(*value == OPTION_UNSET) { + *value = opt->def; + return 0; + } + + switch (opt->type) { + case enable_option: + switch (*value) { + case OPTION_ENABLED: + printk(KERN_INFO "%s Enabled\n", opt->name); + return 0; + break; + case OPTION_DISABLED: + printk(KERN_INFO "%s Disabled\n", opt->name); + return 0; + break; + } + break; + case range_option: + if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) { + printk(KERN_INFO "%s set to %i\n", opt->name, *value); + return 0; + } + break; + case list_option: + for(i = 0; i < opt->arg.l.nr; i++) { + ent = &opt->arg.l.p[i]; + if(*value == ent->i) { + if(ent->str[0] != '\0') + printk(KERN_INFO "%s\n", ent->str); + return 0; + } + } + break; + default: + BUG(); + } + + printk(KERN_INFO "Invalid %s specified (%i) %s\n", + opt->name, *value, opt->err); + *value = opt->def; + return -1; +} + +/** + * atl2_check_options - Range Checking for Command Line Parameters + * @adapter: board private structure + * + * This routine checks all command line parameters for valid user + * input. If an invalid value is given, or if no user specified + * value exists, a default value is used. The final value is stored + * in a variable in the adapter structure. + **/ +void __devinit +atl2_check_options(struct atl2_adapter *adapter) +{ + int val; + struct atl2_option opt; + int bd = adapter->bd_number; + if(bd >= ATL2_MAX_NIC) { + printk(KERN_NOTICE "Warning: no configuration for board #%i\n", bd); + printk(KERN_NOTICE "Using defaults for all values\n"); +#ifndef module_param_array + bd = ATL2_MAX_NIC; +#endif + } + + /* Bytes of Transmit Memory */ + opt.type = range_option; + opt.name = "Bytes of Transmit Memory"; + opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_TX_MEMSIZE); + opt.def = ATL2_DEFAULT_TX_MEMSIZE; + opt.arg.r.min = ATL2_MIN_TX_MEMSIZE; + opt.arg.r.max = ATL2_MAX_TX_MEMSIZE; +#ifdef module_param_array + if(num_TxMemSize > bd) { +#endif + val = TxMemSize[bd]; + atl2_validate_option(&val, &opt); + adapter->txd_ring_size = ((u32) val) * 1024; +#ifdef module_param_array + } else { + adapter->txd_ring_size = ((u32)opt.def) * 1024; + } +#endif + // txs ring size: + adapter->txs_ring_size = adapter->txd_ring_size / 128; + if (adapter->txs_ring_size > 160) + adapter->txs_ring_size = 160; + + /* Receive Memory Block Count */ + opt.type = range_option; + opt.name = "Number of receive memory block"; + opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_RXD_COUNT); + opt.def = ATL2_DEFAULT_RXD_COUNT; + opt.arg.r.min = ATL2_MIN_RXD_COUNT; + opt.arg.r.max = ATL2_MAX_RXD_COUNT; +#ifdef module_param_array + if(num_RxMemBlock > bd) { +#endif + val = RxMemBlock[bd]; + atl2_validate_option(&val, &opt); + adapter->rxd_ring_size = (u32)val; //((u16)val)&~1; // even number +#ifdef module_param_array + } else { + adapter->rxd_ring_size = (u32)opt.def; + } +#endif + // init RXD Flow control value + adapter->hw.fc_rxd_hi = (adapter->rxd_ring_size/8)*7; + adapter->hw.fc_rxd_lo = (ATL2_MIN_RXD_COUNT/8) > (adapter->rxd_ring_size/12) ? + (ATL2_MIN_RXD_COUNT/8) : (adapter->rxd_ring_size/12); + + /* Interrupt Moderate Timer */ + opt.type = range_option; + opt.name = "Interrupt Moderate Timer"; + opt.err = "using default of " __MODULE_STRING(INT_MOD_DEFAULT_CNT); + opt.def = INT_MOD_DEFAULT_CNT; + opt.arg.r.min = INT_MOD_MIN_CNT; + opt.arg.r.max = INT_MOD_MAX_CNT; +#ifdef module_param_array + if(num_IntModTimer > bd) { +#endif + val = IntModTimer[bd]; + atl2_validate_option(&val, &opt); + adapter->imt = (u16) val; +#ifdef module_param_array + } else { + adapter->imt = (u16)(opt.def); + } +#endif + /* Flash Vendor */ + opt.type = range_option; + opt.name = "SPI Flash Vendor"; + opt.err = "using default of " __MODULE_STRING(FLASH_VENDOR_DEFAULT); + opt.def = FLASH_VENDOR_DEFAULT; + opt.arg.r.min = FLASH_VENDOR_MIN; + opt.arg.r.max = FLASH_VENDOR_MAX; +#ifdef module_param_array + if(num_FlashVendor > bd) { +#endif + val = FlashVendor[bd]; + atl2_validate_option(&val, &opt); + adapter->hw.flash_vendor = (u8) val; +#ifdef module_param_array + } else { + adapter->hw.flash_vendor = (u8)(opt.def); + } +#endif + /* MediaType */ + opt.type = range_option; + opt.name = "Speed/Duplex Selection"; + opt.err = "using default of " __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR); + opt.def = MEDIA_TYPE_AUTO_SENSOR; + opt.arg.r.min = MEDIA_TYPE_AUTO_SENSOR; + opt.arg.r.max = MEDIA_TYPE_10M_HALF; +#ifdef module_param_array + if(num_MediaType > bd) { +#endif + val = MediaType[bd]; + atl2_validate_option(&val, &opt); + adapter->hw.MediaType = (u16) val; +#ifdef module_param_array + } else { + adapter->hw.MediaType = (u16)(opt.def); + } +#endif +} --- linux-2.6.27.orig/ubuntu/atl2/BOM +++ linux-2.6.27/ubuntu/atl2/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://people.redhat.com/csnook/atl2/ +Current Version: 2.0.4 --- linux-2.6.27.orig/ubuntu/atl2/atl2_ethtool.c +++ linux-2.6.27/ubuntu/atl2/atl2_ethtool.c @@ -0,0 +1,416 @@ +/* atl2_ethtool.c -- atl2 ethtool support + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "atl2.h" +#include "atl2_hw.h" + +extern char atl2_driver_name[]; +extern char atl2_driver_version[]; + +extern int atl2_up(struct atl2_adapter *adapter); +extern void atl2_down(struct atl2_adapter *adapter); +extern void atl2_reinit_locked(struct atl2_adapter *adapter); +extern s32 atl2_reset_hw(struct atl2_hw *hw); + +static int +atl2_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP); + ecmd->advertising = ADVERTISED_TP; + + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->advertising |= hw->autoneg_advertised; + + ecmd->port = PORT_TP; + ecmd->phy_address = 0; + ecmd->transceiver = XCVR_INTERNAL; + + if (adapter->link_speed != SPEED_0) { + ecmd->speed = adapter->link_speed; + if (adapter->link_duplex == FULL_DUPLEX) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; + } else { + ecmd->speed = -1; + ecmd->duplex = -1; + } + + ecmd->autoneg = AUTONEG_ENABLE; + return 0; +} + +static int +atl2_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + + while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags)) + msleep(1); + + if (ecmd->autoneg == AUTONEG_ENABLE) { +#define MY_ADV_MASK (ADVERTISE_10_HALF| \ + ADVERTISE_10_FULL| \ + ADVERTISE_100_HALF| \ + ADVERTISE_100_FULL) + + if ((ecmd->advertising&MY_ADV_MASK) == MY_ADV_MASK) { + hw->MediaType = MEDIA_TYPE_AUTO_SENSOR; + hw->autoneg_advertised = MY_ADV_MASK; + } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_100_FULL) { + hw->MediaType = MEDIA_TYPE_100M_FULL; + hw->autoneg_advertised = ADVERTISE_100_FULL; + } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_100_HALF) { + hw->MediaType = MEDIA_TYPE_100M_HALF; + hw->autoneg_advertised = ADVERTISE_100_HALF; + } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_10_FULL) { + hw->MediaType = MEDIA_TYPE_10M_FULL; + hw->autoneg_advertised = ADVERTISE_10_FULL; + } else if ((ecmd->advertising&MY_ADV_MASK) == ADVERTISE_10_HALF) { + hw->MediaType = MEDIA_TYPE_10M_HALF; + hw->autoneg_advertised = ADVERTISE_10_HALF; + } else { + clear_bit(__ATL2_RESETTING, &adapter->flags); + return -EINVAL; + } + ecmd->advertising = hw->autoneg_advertised | + ADVERTISED_TP | ADVERTISED_Autoneg; + } else { + clear_bit(__ATL2_RESETTING, &adapter->flags); + return -EINVAL; + } + + /* reset the link */ + if (netif_running(adapter->netdev)) { + atl2_down(adapter); + atl2_up(adapter); + } else + atl2_reset_hw(&adapter->hw); + + clear_bit(__ATL2_RESETTING, &adapter->flags); + return 0; +} + +static u32 +atl2_get_tx_csum(struct net_device *netdev) +{ + return (netdev->features & NETIF_F_HW_CSUM) != 0; +} + +static u32 +atl2_get_msglevel(struct net_device *netdev) +{ + return 0; +} + +/* + * It's sane for this to be empty, but we might want to take advantage of this. + */ +static void +atl2_set_msglevel(struct net_device *netdev, u32 data) +{ +} + +static int +atl2_get_regs_len(struct net_device *netdev) +{ +#define ATL2_REGS_LEN 42 + return ATL2_REGS_LEN * sizeof(u32); +} + +static void +atl2_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + u32 *regs_buff = p; + u16 phy_data; + + memset(p, 0, ATL2_REGS_LEN * sizeof(u32)); + + regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; + + regs_buff[0] = ATL2_READ_REG(hw, REG_VPD_CAP); + regs_buff[1] = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL); + regs_buff[2] = ATL2_READ_REG(hw, REG_SPI_FLASH_CONFIG); + regs_buff[3] = ATL2_READ_REG(hw, REG_TWSI_CTRL); + regs_buff[4] = ATL2_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL); + regs_buff[5] = ATL2_READ_REG(hw, REG_MASTER_CTRL); + regs_buff[6] = ATL2_READ_REG(hw, REG_MANUAL_TIMER_INIT); + regs_buff[7] = ATL2_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT); + regs_buff[8] = ATL2_READ_REG(hw, REG_PHY_ENABLE); + regs_buff[9] = ATL2_READ_REG(hw, REG_CMBDISDMA_TIMER); + regs_buff[10] = ATL2_READ_REG(hw, REG_IDLE_STATUS); + regs_buff[11] = ATL2_READ_REG(hw, REG_MDIO_CTRL); + regs_buff[12] = ATL2_READ_REG(hw, REG_SERDES_LOCK); + regs_buff[13] = ATL2_READ_REG(hw, REG_MAC_CTRL); + regs_buff[14] = ATL2_READ_REG(hw, REG_MAC_IPG_IFG); + regs_buff[15] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR); + regs_buff[16] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR+4); + regs_buff[17] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE); + regs_buff[18] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE+4); + regs_buff[19] = ATL2_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL); + regs_buff[20] = ATL2_READ_REG(hw, REG_MTU); + regs_buff[21] = ATL2_READ_REG(hw, REG_WOL_CTRL); + regs_buff[22] = ATL2_READ_REG(hw, REG_SRAM_TXRAM_END); + regs_buff[23] = ATL2_READ_REG(hw, REG_DESC_BASE_ADDR_HI); + regs_buff[24] = ATL2_READ_REG(hw, REG_TXD_BASE_ADDR_LO); + regs_buff[25] = ATL2_READ_REG(hw, REG_TXD_MEM_SIZE); + regs_buff[26] = ATL2_READ_REG(hw, REG_TXS_BASE_ADDR_LO); + regs_buff[27] = ATL2_READ_REG(hw, REG_TXS_MEM_SIZE); + regs_buff[28] = ATL2_READ_REG(hw, REG_RXD_BASE_ADDR_LO); + regs_buff[29] = ATL2_READ_REG(hw, REG_RXD_BUF_NUM); + regs_buff[30] = ATL2_READ_REG(hw, REG_DMAR); + regs_buff[31] = ATL2_READ_REG(hw, REG_TX_CUT_THRESH); + regs_buff[32] = ATL2_READ_REG(hw, REG_DMAW); + regs_buff[33] = ATL2_READ_REG(hw, REG_PAUSE_ON_TH); + regs_buff[34] = ATL2_READ_REG(hw, REG_PAUSE_OFF_TH); + regs_buff[35] = ATL2_READ_REG(hw, REG_MB_TXD_WR_IDX); + regs_buff[36] = ATL2_READ_REG(hw, REG_MB_RXD_RD_IDX); + regs_buff[38] = ATL2_READ_REG(hw, REG_ISR); + regs_buff[39] = ATL2_READ_REG(hw, REG_IMR); + + atl2_read_phy_reg(hw, MII_BMCR, &phy_data); + regs_buff[40] = (u32)phy_data; + atl2_read_phy_reg(hw, MII_BMSR, &phy_data); + regs_buff[41] = (u32)phy_data; +} + +static int +atl2_get_eeprom_len(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + if (!atl2_check_eeprom_exist(&adapter->hw)) { + return 512; + } else + return 0; +} + +static int +atl2_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + u32 *eeprom_buff; + int first_dword, last_dword; + int ret_val = 0; + int i; + + if (eeprom->len == 0) + return -EINVAL; + + if (atl2_check_eeprom_exist(hw)) { + return -EINVAL; + } + + eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + first_dword = eeprom->offset >> 2; + last_dword = (eeprom->offset + eeprom->len - 1) >> 2; + + eeprom_buff = kmalloc(sizeof(u32) * (last_dword - first_dword + 1), GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + for (i=first_dword; i < last_dword; i++) { + if (!atl2_read_eeprom(hw, i*4, &(eeprom_buff[i-first_dword]))) + return -EIO; + } + + memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), + eeprom->len); + kfree(eeprom_buff); + + return ret_val; +} + +static int +atl2_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + u32 *eeprom_buff; + u32 *ptr; + int max_len, first_dword, last_dword, ret_val = 0; + int i; + + if (eeprom->len == 0) + return -EOPNOTSUPP; + + if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + return -EFAULT; + + max_len = 512; + + first_dword = eeprom->offset >> 2; + last_dword = (eeprom->offset + eeprom->len - 1) >> 2; + eeprom_buff = kmalloc(max_len, GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + ptr = (u32 *)eeprom_buff; + + if (eeprom->offset & 3) { + /* need read/modify/write of first changed EEPROM word */ + /* only the second byte of the word is being modified */ + if (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0]))) + return -EIO; + ptr++; + } + if (((eeprom->offset + eeprom->len) & 3) ) { + /* need read/modify/write of last changed EEPROM word */ + /* only the first byte of the word is being modified */ + + if (!atl2_read_eeprom(hw, last_dword*4, &(eeprom_buff[last_dword - first_dword]))) + return -EIO; + } + + /* Device's eeprom is always little-endian, word addressable */ + memcpy(ptr, bytes, eeprom->len); + + for (i = 0; i < last_dword - first_dword + 1; i++) { + if (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i])) + return -EIO; + } + + kfree(eeprom_buff); + return ret_val; +} + +static void +atl2_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + strncpy(drvinfo->driver, atl2_driver_name, 32); + strncpy(drvinfo->version, atl2_driver_version, 32); + strncpy(drvinfo->fw_version, "L2", 32); + strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); + drvinfo->n_stats = 0; + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = atl2_get_regs_len(netdev); + drvinfo->eedump_len = atl2_get_eeprom_len(netdev); +} + +static void +atl2_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + wol->supported = WAKE_MAGIC; + wol->wolopts = 0; + + if (adapter->wol & ATL2_WUFC_EX) + wol->wolopts |= WAKE_UCAST; + if (adapter->wol & ATL2_WUFC_MC) + wol->wolopts |= WAKE_MCAST; + if (adapter->wol & ATL2_WUFC_BC) + wol->wolopts |= WAKE_BCAST; + if (adapter->wol & ATL2_WUFC_MAG) + wol->wolopts |= WAKE_MAGIC; + if (adapter->wol & ATL2_WUFC_LNKC) + wol->wolopts |= WAKE_PHY; +} + +static int +atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) + return -EOPNOTSUPP; + + if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST)) + return -EOPNOTSUPP; + + /* these settings will always override what we currently have */ + adapter->wol = 0; + + if (wol->wolopts & WAKE_MAGIC) + adapter->wol |= ATL2_WUFC_MAG; + if (wol->wolopts & WAKE_PHY) + adapter->wol |= ATL2_WUFC_LNKC; + + return 0; +} + +static int +atl2_nway_reset(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + if (netif_running(netdev)) + atl2_reinit_locked(adapter); + return 0; +} + +static struct ethtool_ops atl2_ethtool_ops = { + .get_settings = atl2_get_settings, + .set_settings = atl2_set_settings, + .get_drvinfo = atl2_get_drvinfo, + .get_regs_len = atl2_get_regs_len, + .get_regs = atl2_get_regs, + .get_wol = atl2_get_wol, + .set_wol = atl2_set_wol, + .get_msglevel = atl2_get_msglevel, + .set_msglevel = atl2_set_msglevel, + .nway_reset = atl2_nway_reset, + .get_link = ethtool_op_get_link, + .get_eeprom_len = atl2_get_eeprom_len, + .get_eeprom = atl2_get_eeprom, + .set_eeprom = atl2_set_eeprom, + .get_tx_csum = atl2_get_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ethtool_op_get_tso, +#endif +#if 0 //FIXME: not implemented? +//#ifdef ETHTOOL_GPERMADDR + .get_perm_addr = ethtool_op_get_perm_addr, +#endif +}; + +void +atl2_set_ethtool_ops(struct net_device *netdev) +{ + SET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops); +} --- linux-2.6.27.orig/ubuntu/atl2/Makefile +++ linux-2.6.27/ubuntu/atl2/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_ATL2) += atl2.o + +atl2-objs += atl2_main.o atl2_hw.o atl2_ethtool.o atl2_param.o --- linux-2.6.27.orig/ubuntu/atl2/atl2_osdep.h +++ linux-2.6.27/ubuntu/atl2/atl2_osdep.h @@ -0,0 +1,72 @@ +/* atl2_osdep.h -- atl2 compat cruft + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ATL2_OSDEP_H_ +#define _ATL2_OSDEP_H_ + +#include +#include +#include +#include + +#define usec_delay(x) udelay(x) +#ifndef msec_delay +#define msec_delay(x) do { \ + if(in_interrupt()) BUG(); \ + else msleep(x); \ + } while (0) + +/* Some workarounds require millisecond delays and are run during interrupt + * context. Most notably, when establishing link, the phy may need tweaking + * but cannot process phy register reads/writes faster than millisecond + * intervals...and we establish link due to a "link status change" interrupt. + */ +#define msec_delay_irq(x) mdelay(x) +#endif + +#define PCI_COMMAND_REGISTER PCI_COMMAND +#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE +#define ETH_ADDR_LEN ETH_ALEN + +#define ATL2_WRITE_REG(a, reg, value) (writel((value), ((a)->hw_addr + reg))) + +#define ATL2_WRITE_FLUSH(a) (readl((a)->hw_addr)) + +#define ATL2_READ_REG(a, reg) (readl((a)->hw_addr + reg)) + +#define ATL2_WRITE_REGB(a, reg, value) (writeb((value), ((a)->hw_addr + reg))) + +#define ATL2_READ_REGB(a, reg) (readb((a)->hw_addr + reg)) + +#define ATL2_WRITE_REGW(a, reg, value) (writew((value), ((a)->hw_addr + reg))) + +#define ATL2_READ_REGW(a, reg) (readw((a)->hw_addr + reg)) + +#define ATL2_WRITE_REG_ARRAY(a, reg, offset, value) \ + (writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) + +#define ATL2_READ_REG_ARRAY(a, reg, offset) \ + (readl(((a)->hw_addr + reg) + ((offset) << 2))) + +#endif /* _ATL2_OSDEP_H_ */ --- linux-2.6.27.orig/ubuntu/atl2/atl2_main.c +++ linux-2.6.27/ubuntu/atl2/atl2_main.c @@ -0,0 +1,1851 @@ +/* atl2_main.c -- atl2 driver main functions + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atl2.h" + +#define ATL2_DRV_VERSION "2.0.4" + +char atl2_driver_name[] = "atl2"; +static const char atl2_driver_string[] = "Atheros(R) L2 Ethernet Driver"; +static char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation."; +char atl2_driver_version[] = ATL2_DRV_VERSION; + +MODULE_AUTHOR("Atheros Corporation , Chris Snook "); +MODULE_DESCRIPTION("Atheros Fast Ethernet Network Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(ATL2_DRV_VERSION); + +/* FIXME: remove this after merging, goes in pci_ids.h */ +#ifndef PCI_DEVICE_ID_ATTANSIC_L2 +#define PCI_DEVICE_ID_ATTANSIC_L2 0x2048 +#endif + +/* + * atl2_pci_tbl - PCI Device ID Table + */ +static struct pci_device_id atl2_pci_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)}, + /* required last entry */ + {0,} +}; +MODULE_DEVICE_TABLE(pci, atl2_pci_tbl); + +extern void atl2_set_ethtool_ops(struct net_device *netdev); +#ifdef ETHTOOL_OPS_COMPAT +extern int ethtool_ioctl(struct ifreq *ifr); +#endif + +#define COPYBREAK_DEFAULT 256 +static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; +module_param(copybreak, uint, 0644); +MODULE_PARM_DESC(copybreak, "Maximum size of packet that is copied to a new buffer on receive"); + +extern void atl2_check_options(struct atl2_adapter *adapter); +#ifdef SIOCDEVPRIVATE +extern int atl2_priv_ioctl(struct net_device* netdev, struct ifreq* ifr); +#endif + +/** + * atl2_sw_init - Initialize general software structures (struct atl2_adapter) + * @adapter: board private structure to initialize + * + * atl2_sw_init initializes the Adapter private data structure. + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + **/ +static int __devinit +atl2_sw_init(struct atl2_adapter *adapter) +{ + struct atl2_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; + + /* PCI config space info */ + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_id = pdev->subsystem_device; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); + + adapter->wol = 0; + adapter->ict = 50000; // 100ms + adapter->link_speed = SPEED_0; // hardware init + adapter->link_duplex = FULL_DUPLEX; + + hw->phy_configured = false; + hw->preamble_len = 7; + hw->ipgt = 0x60; + hw->min_ifg = 0x50; + hw->ipgr1 = 0x40; + hw->ipgr2 = 0x60; + hw->retry_buf = 2; + hw->max_retry = 0xf; + hw->lcol = 0x37; + hw->jam_ipg = 7; + hw->fc_rxd_hi = 0; + hw->fc_rxd_lo = 0; + hw->max_frame_size = adapter->netdev->mtu; + + spin_lock_init(&adapter->stats_lock); + spin_lock_init(&adapter->tx_lock); + + set_bit(__ATL2_DOWN, &adapter->flags); + + return 0; +} + +/** + * atl2_set_multi - Multicast and Promiscuous mode set + * @netdev: network interface device structure + * + * The set_multi entry point is called whenever the multicast address + * list or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper multicast, + * promiscuous mode, and all-multi behavior. + **/ +static void +atl2_set_multi(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + struct dev_mc_list *mc_ptr; + u32 rctl; + u32 hash_value; + + /* Check for Promiscuous and All Multicast modes */ + rctl = ATL2_READ_REG(hw, REG_MAC_CTRL); + + if(netdev->flags & IFF_PROMISC) { + rctl |= MAC_CTRL_PROMIS_EN; + } else if(netdev->flags & IFF_ALLMULTI) { + rctl |= MAC_CTRL_MC_ALL_EN; + rctl &= ~MAC_CTRL_PROMIS_EN; + } else { + rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); + } + + ATL2_WRITE_REG(hw, REG_MAC_CTRL, rctl); + + /* clear the old settings from the multicast hash table */ + ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); + ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); + + /* comoute mc addresses' hash value ,and put it into hash table */ + for(mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + hash_value = atl2_hash_mc_addr(hw, mc_ptr->dmi_addr); + atl2_hash_set(hw, hash_value); + } +} + +static void +init_ring_ptrs(struct atl2_adapter *adapter) +{ + // Read / Write Ptr Initialize: + adapter->txd_write_ptr = 0; + atomic_set(&adapter->txd_read_ptr, 0); + + adapter->rxd_read_ptr = 0; + adapter->rxd_write_ptr = 0; + + atomic_set(&adapter->txs_write_ptr, 0); + adapter->txs_next_clear = 0; +} + +/** + * atl2_configure - Configure Transmit&Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Tx /Rx unit of the MAC after a reset. + **/ +static int +atl2_configure(struct atl2_adapter *adapter) +{ + struct atl2_hw * hw = &adapter->hw; + u32 value; + + // clear interrupt status + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0xffffffff); + + // set MAC Address + value = (((u32)hw->mac_addr[2]) << 24) | + (((u32)hw->mac_addr[3]) << 16) | + (((u32)hw->mac_addr[4]) << 8 ) | + (((u32)hw->mac_addr[5]) ) ; + ATL2_WRITE_REG(hw, REG_MAC_STA_ADDR, value); + value = (((u32)hw->mac_addr[0]) << 8 ) | + (((u32)hw->mac_addr[1]) ) ; + ATL2_WRITE_REG(hw, (REG_MAC_STA_ADDR+4), value); + + // HI base address + ATL2_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI, + (u32)((adapter->ring_dma & 0xffffffff00000000ULL) >> 32)); + + // LO base address + ATL2_WRITE_REG(hw, REG_TXD_BASE_ADDR_LO, + (u32)(adapter->txd_dma & 0x00000000ffffffffULL)); + ATL2_WRITE_REG(hw, REG_TXS_BASE_ADDR_LO, + (u32)(adapter->txs_dma & 0x00000000ffffffffULL)); + ATL2_WRITE_REG(hw, REG_RXD_BASE_ADDR_LO, + (u32)(adapter->rxd_dma & 0x00000000ffffffffULL)); + + // element count + ATL2_WRITE_REGW(hw, REG_TXD_MEM_SIZE, (u16)(adapter->txd_ring_size/4)); + ATL2_WRITE_REGW(hw, REG_TXS_MEM_SIZE, (u16)adapter->txs_ring_size); + ATL2_WRITE_REGW(hw, REG_RXD_BUF_NUM, (u16)adapter->rxd_ring_size); + + /* config Internal SRAM */ +/* + ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_tx_end); + ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_rx_end); +*/ + + /* config IPG/IFG */ + value = (((u32)hw->ipgt & MAC_IPG_IFG_IPGT_MASK) << MAC_IPG_IFG_IPGT_SHIFT) | + (((u32)hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) << MAC_IPG_IFG_MIFG_SHIFT) | + (((u32)hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) << MAC_IPG_IFG_IPGR1_SHIFT)| + (((u32)hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) << MAC_IPG_IFG_IPGR2_SHIFT); + ATL2_WRITE_REG(hw, REG_MAC_IPG_IFG, value); + + /* config Half-Duplex Control */ + value = ((u32)hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) | + (((u32)hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) << + MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) | + MAC_HALF_DUPLX_CTRL_EXC_DEF_EN | + (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) | + (((u32)hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) << + MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT); + ATL2_WRITE_REG(hw, REG_MAC_HALF_DUPLX_CTRL, value); + + /* set Interrupt Moderator Timer */ + ATL2_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, adapter->imt); + ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_ITIMER_EN); + + /* set Interrupt Clear Timer */ + ATL2_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, adapter->ict); + + /* set MTU */ + ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu + + ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE); + + /* 1590 */ + ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177); + + /* flow control */ + ATL2_WRITE_REGW(hw, REG_PAUSE_ON_TH, hw->fc_rxd_hi); + ATL2_WRITE_REGW(hw, REG_PAUSE_OFF_TH, hw->fc_rxd_lo); + + /* Init mailbox */ + ATL2_WRITE_REGW(hw, REG_MB_TXD_WR_IDX, (u16)adapter->txd_write_ptr); + ATL2_WRITE_REGW(hw, REG_MB_RXD_RD_IDX, (u16)adapter->rxd_read_ptr); + + /* enable DMA read/write */ + ATL2_WRITE_REGB(hw, REG_DMAR, DMAR_EN); + ATL2_WRITE_REGB(hw, REG_DMAW, DMAW_EN); + + value = ATL2_READ_REG(&adapter->hw, REG_ISR); + if ((value & ISR_PHY_LINKDOWN) != 0) { + value = 1; // config failed + } else { + value = 0; + } + + // clear all interrupt status + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0x3fffffff); + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0); + return value; +} + +/** + * atl2_setup_ring_resources - allocate Tx / RX descriptor resources + * @adapter: board private structure + * + * Return 0 on success, negative on failure + **/ +static s32 +atl2_setup_ring_resources(struct atl2_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + int size; + u8 offset = 0; + + /* real ring DMA buffer */ + adapter->ring_size = size = + adapter->txd_ring_size * 1 + 7 + // dword align + adapter->txs_ring_size * 4 + 7 + // dword align + adapter->rxd_ring_size * 1536 + 127; // 128bytes align + + adapter->ring_vir_addr = pci_alloc_consistent(pdev, size, &adapter->ring_dma); + if (!adapter->ring_vir_addr) { + return -ENOMEM; + } +#if 0 + if (adapter->pci_using_64) { + // test whether HIDWORD dma buffer is not cross boundary + if ( ((adapter->ring_dma &0xffffffff00000000ULL)>>32) + != (((adapter->ring_dma+size)&0xffffffff00000000ULL)>>32) ) { + pci_free_consistent(pdev, adapter->ring_size, adapter->ring_vir_addr, adapter->ring_dma); + DEBUGOUT("memory allocated cross 32bit boundary !"); + return -ENOMEM; + } + } +#endif + memset(adapter->ring_vir_addr, 0, adapter->ring_size); + + // Init TXD Ring + adapter->txd_dma = adapter->ring_dma ; + offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0; + adapter->txd_dma += offset; + adapter->txd_ring = (tx_pkt_header_t*) (adapter->ring_vir_addr + offset); + + // Init TXS Ring + adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size; + offset = (adapter->txs_dma & 0x7) ? (8- (adapter->txs_dma & 0x7)) : 0; + adapter->txs_dma += offset; + adapter->txs_ring = (tx_pkt_status_t*) + (((u8*)adapter->txd_ring) + (adapter->txd_ring_size+offset)); + + // Init RXD Ring + adapter->rxd_dma = adapter->txs_dma + adapter->txs_ring_size*4; + offset = (adapter->rxd_dma & 127) ? (128 - (adapter->rxd_dma & 127)) : 0; + if (offset > 7) { + offset -= 8; + } else { + offset += (128 - 8); + } + adapter->rxd_dma += offset; + adapter->rxd_ring = (rx_desc_t*) (((u8*)adapter->txs_ring) + + (adapter->txs_ring_size*4 + offset)); + +// Read / Write Ptr Initialize: +// init_ring_ptrs(adapter); + + return ATL2_SUCCESS; +} + +/** + * atl2_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ +static inline void +atl2_irq_enable(struct atl2_adapter *adapter) +{ + ATL2_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK); + ATL2_WRITE_FLUSH(&adapter->hw); +} + +/** + * atl2_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ +static inline void +atl2_irq_disable(struct atl2_adapter *adapter) +{ + ATL2_WRITE_REG(&adapter->hw, REG_IMR, 0); + ATL2_WRITE_FLUSH(&adapter->hw); + synchronize_irq(adapter->pdev->irq); +} + +#ifdef NETIF_F_HW_VLAN_TX +static void +atl2_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + u32 ctrl; + + atl2_irq_disable(adapter); + adapter->vlgrp = grp; + + if(grp) { + /* enable VLAN tag insert/strip */ + ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL); + ctrl |= MAC_CTRL_RMV_VLAN; + ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); + } else { + /* disable VLAN tag insert/strip */ + ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL); + ctrl &= ~MAC_CTRL_RMV_VLAN; + ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); + } + + atl2_irq_enable(adapter); +} + +static void +atl2_restore_vlan(struct atl2_adapter *adapter) +{ + atl2_vlan_rx_register(adapter->netdev, adapter->vlgrp); +} +#endif + +static void +atl2_intr_rx(struct atl2_adapter* adapter) +{ + struct net_device *netdev = adapter->netdev; + rx_desc_t* rxd; + struct sk_buff* skb; + + do { + rxd = adapter->rxd_ring+adapter->rxd_write_ptr; + if (!rxd->status.update) + break; // end of tx + + // clear this flag at once + rxd->status.update = 0; + + if (rxd->status.ok && rxd->status.pkt_size >= 60) { + int rx_size = (int)(rxd->status.pkt_size - 4); + // alloc new buffer + skb = netdev_alloc_skb(netdev, rx_size + NET_IP_ALIGN); + if (NULL == skb) { + printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n", + netdev->name); + /* We should check that some rx space is free. + * If not, free one and mark stats->rx_dropped++. */ + adapter->net_stats.rx_dropped++; + break; + } +/* FIXME: ??? + if (rx_size > 1400) { + int s,c; + c = 0; + printk("rx_size= %d\n", rx_size); + for (s=0; s < 800; s++) { + if (0 == c) { + printk("%04x ", s); + } + printk("%02x ", rxd->packet[s]); + if (++c == 16) { + c = 0; + printk("\n"); + } + } + printk(KERN_WARNING"\n"); + } +*/ + skb_reserve(skb, NET_IP_ALIGN); + skb->dev = netdev; +/* gone in 2.6.23, just use memcpy? -- CHS + eth_copy_and_sum(skb, rxd->packet, rx_size, 0); */ + memcpy(skb->data, rxd->packet, rx_size); /* totally untested -- CHS */ + skb_put(skb, rx_size); + /* FIXME ??? + memcpy(skb_put(skb, rx_size), + rxd->packet, + rx_size); + */ + skb->protocol = eth_type_trans(skb, netdev); +#ifdef NETIF_F_HW_VLAN_TX + if(adapter->vlgrp && (rxd->status.vlan)) { + u16 vlan_tag = (rxd->status.vtag>>4) | + ((rxd->status.vtag&7) << 13) | + ((rxd->status.vtag&8) << 9); + vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); + } else +#endif + netif_rx(skb); + adapter->net_stats.rx_bytes += rx_size; + adapter->net_stats.rx_packets++; + netdev->last_rx = jiffies; + } else { + adapter->net_stats.rx_errors++; + + if (rxd->status.ok && rxd->status.pkt_size <= 60) { + adapter->net_stats.rx_length_errors++; + } + if (rxd->status.mcast) adapter->net_stats.multicast++; + if (rxd->status.crc) adapter->net_stats.rx_crc_errors++; + if (rxd->status.align) adapter->net_stats.rx_frame_errors++; + } + + // advance write ptr + if (++adapter->rxd_write_ptr == adapter->rxd_ring_size) + adapter->rxd_write_ptr = 0; + } while (1); + + // update mailbox ? + adapter->rxd_read_ptr = adapter->rxd_write_ptr; + ATL2_WRITE_REGW(&adapter->hw, REG_MB_RXD_RD_IDX, adapter->rxd_read_ptr); +} + +static void +atl2_intr_tx(struct atl2_adapter* adapter) +{ + u32 txd_read_ptr; + u32 txs_write_ptr; + tx_pkt_status_t* txs; + tx_pkt_header_t* txph; + int free_hole = 0; + + do { + txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr); + txs = adapter->txs_ring + txs_write_ptr; + if (!txs->update) + break; // tx stop here + + free_hole = 1; + txs->update = 0; + + if (++txs_write_ptr == adapter->txs_ring_size) + txs_write_ptr = 0; + atomic_set(&adapter->txs_write_ptr, (int)txs_write_ptr); + + txd_read_ptr = (u32) atomic_read(&adapter->txd_read_ptr); + txph = (tx_pkt_header_t*) (((u8*)adapter->txd_ring) + txd_read_ptr); + + if ( txph->pkt_size != txs->pkt_size) { + tx_pkt_status_t* old_txs = txs; + printk(KERN_WARNING + "%s: txs packet size do not coinsist with txd" + " txd_:0x%08x, txs_:0x%08x!\n", + adapter->netdev->name, + *(u32*)txph, *(u32*)txs); + printk(KERN_WARNING + "txd read ptr: 0x%x\n", + txd_read_ptr); + txs = adapter->txs_ring + txs_write_ptr; + printk(KERN_WARNING + "txs-behind:0x%08x\n", + *(u32*)txs); + if (txs_write_ptr < 2) { + txs = adapter->txs_ring + + (adapter->txs_ring_size + + txs_write_ptr - 2); + } else { + txs = adapter->txs_ring + (txs_write_ptr - 2); + } + printk(KERN_WARNING + "txs-before:0x%08x\n", + *(u32*)txs); + txs = old_txs; + } + + txd_read_ptr += (((u32)(txph->pkt_size)+7)& ~3);//4for TPH + if (txd_read_ptr >= adapter->txd_ring_size) + txd_read_ptr -= adapter->txd_ring_size; + + atomic_set(&adapter->txd_read_ptr, (int)txd_read_ptr); + + // tx statistics: + if (txs->ok) + adapter->net_stats.tx_packets++; + else + adapter->net_stats.tx_errors++; + + if (txs->defer) adapter->net_stats.collisions++; + if (txs->abort_col) adapter->net_stats.tx_aborted_errors++; + if (txs->late_col) adapter->net_stats.tx_window_errors++; + if (txs->underun) adapter->net_stats.tx_fifo_errors++; + } while (1); + + if (free_hole) { + if(netif_queue_stopped(adapter->netdev) && + netif_carrier_ok(adapter->netdev)) + netif_wake_queue(adapter->netdev); + } +} + +static void +atl2_check_for_link(struct atl2_adapter* adapter) +{ + struct net_device *netdev = adapter->netdev; + u16 phy_data = 0; + + spin_lock(&adapter->stats_lock); + atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + spin_unlock(&adapter->stats_lock); + + // notify upper layer link down ASAP + if (!(phy_data & BMSR_LSTATUS)) { // Link Down + if (netif_carrier_ok(netdev)) { // old link state: Up + printk(KERN_INFO "%s: %s NIC Link is Down\n", + atl2_driver_name, netdev->name); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + } + schedule_work(&adapter->link_chg_task); +} + +static inline void +atl2_clear_phy_int(struct atl2_adapter *adapter) +{ + u16 phy_data; + spin_lock(&adapter->stats_lock); + atl2_read_phy_reg(&adapter->hw, 19, &phy_data); + spin_unlock(&adapter->stats_lock); +} + +/** + * atl2_intr - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure + **/ +static irqreturn_t +atl2_intr(int irq, void *data) +{ + struct atl2_adapter *adapter = netdev_priv(data); + struct atl2_hw *hw = &adapter->hw; + u32 status; + + status = ATL2_READ_REG(hw, REG_ISR); + if (0 == status) + return IRQ_NONE; + + // link event + if (status & ISR_PHY) { + atl2_clear_phy_int(adapter); + } + + // clear ISR status, and Enable CMB DMA/Disable Interrupt + ATL2_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT); + + // FIXME: if PCIe link is down, how did we read the register? -- CHS + // check if PCIE PHY Link down + if (status & ISR_PHY_LINKDOWN) { + if(netif_running(adapter->netdev)) { // reset MAC + ATL2_WRITE_REG(hw, REG_ISR, 0); + ATL2_WRITE_REG(hw, REG_IMR, 0); + ATL2_WRITE_FLUSH(hw); + schedule_work(&adapter->reset_task); + return IRQ_HANDLED; + } + } + + // check if DMA read/write error ? + if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) + { + //ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST); + ATL2_WRITE_REG(hw, REG_ISR, 0); + ATL2_WRITE_REG(hw, REG_IMR, 0); + ATL2_WRITE_FLUSH(hw); + schedule_work(&adapter->reset_task); + return IRQ_HANDLED; + } + + // link event + if (status & (ISR_PHY | ISR_MANUAL)) + { + adapter->net_stats.tx_carrier_errors++; + atl2_check_for_link(adapter); + } + + // transmit event + if (status & ISR_TX_EVENT) { + atl2_intr_tx(adapter); + } + + // rx exception + if (status & ISR_RX_EVENT) { + atl2_intr_rx(adapter); + } + + // re-enable Interrupt + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0); + return IRQ_HANDLED; +} + +static int +atl2_request_irq(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int flags, err = 0; + + flags = IRQF_SHARED; +#ifdef CONFIG_PCI_MSI + adapter->have_msi = true; + if ((err = pci_enable_msi(adapter->pdev))) + adapter->have_msi = false; + + if (adapter->have_msi) + flags &= ~IRQF_SHARED; +#endif + + return request_irq(adapter->pdev->irq, &atl2_intr, flags, netdev->name, netdev); +} + +/** + * atl2_free_ring_resources - Free Tx / RX descriptor Resources + * @adapter: board private structure + * + * Free all transmit software resources + **/ +static void +atl2_free_ring_resources(struct atl2_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + pci_free_consistent(pdev, adapter->ring_size, adapter->ring_vir_addr, adapter->ring_dma); +} + +/** + * atl2_open - Called when a network interface is made active + * @netdev: network interface device structure + * + * Returns 0 on success, negative value on failure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). At this point all resources needed + * for transmit and receive operations are allocated, the interrupt + * handler is registered with the OS, the watchdog timer is started, + * and the stack is notified that the interface is ready. + **/ +static int +atl2_open(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + int err; + u32 val; + + /* disallow open during test */ + if (test_bit(__ATL2_TESTING, &adapter->flags)) + return -EBUSY; + + /* allocate transmit descriptors */ + if((err = atl2_setup_ring_resources(adapter))) + return err; + + if((err = atl2_init_hw(&adapter->hw))) { + err = -EIO; + goto err_init_hw; + } + + /* hardware has been reset, we need to reload some things */ + atl2_set_multi(netdev); + init_ring_ptrs(adapter); + +#ifdef NETIF_F_HW_VLAN_TX + atl2_restore_vlan(adapter); +#endif + + if (atl2_configure(adapter)) { + err = -EIO; + goto err_config; + } + + if ((err = atl2_request_irq(adapter))) + goto err_req_irq; + + clear_bit(__ATL2_DOWN, &adapter->flags); + + mod_timer(&adapter->watchdog_timer, jiffies + 4*HZ); + + val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL); + ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val | MASTER_CTRL_MANUAL_INT); + + atl2_irq_enable(adapter); + + return 0; + +err_init_hw: +err_req_irq: +err_config: + atl2_free_ring_resources(adapter); + atl2_reset_hw(&adapter->hw); + + return err; +} + +void +atl2_down(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + + /* signal that we're down so the interrupt handler does not + * reschedule our watchdog timer */ + set_bit(__ATL2_DOWN, &adapter->flags); + +#ifdef NETIF_F_LLTX + netif_stop_queue(netdev); +#else + netif_tx_disable(netdev); +#endif + + /* reset MAC to disable all RX/TX */ + atl2_reset_hw(&adapter->hw); + msleep(1); + + atl2_irq_disable(adapter); + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_config_timer); + clear_bit(0, &adapter->cfg_phy); + + netif_carrier_off(netdev); + adapter->link_speed = SPEED_0; + adapter->link_duplex = -1; + +// atl2_reset(adapter); +} + +static void +atl2_free_irq(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + + free_irq(adapter->pdev->irq, netdev); + +#ifdef CONFIG_PCI_MSI + if (adapter->have_msi) + pci_disable_msi(adapter->pdev); +#endif +} + +/** + * atl2_close - Disables a network interface + * @netdev: network interface device structure + * + * Returns 0, this is not allowed to fail + * + * The close entry point is called when an interface is de-activated + * by the OS. The hardware is still under the drivers control, but + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + **/ +static int +atl2_close(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags)); + + atl2_down(adapter); + atl2_free_irq(adapter); + atl2_free_ring_resources(adapter); + + return 0; +} + +static inline int +TxsFreeUnit(struct atl2_adapter *adapter) +{ + u32 txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr); + + return (adapter->txs_next_clear >= txs_write_ptr) ? + (int) (adapter->txs_ring_size - adapter->txs_next_clear + + txs_write_ptr - 1) : + (int) (txs_write_ptr - adapter->txs_next_clear - 1); +} + +static inline int +TxdFreeBytes(struct atl2_adapter *adapter) +{ + u32 txd_read_ptr = (u32)atomic_read(&adapter->txd_read_ptr); + + return (adapter->txd_write_ptr >= txd_read_ptr) ? + (int) (adapter->txd_ring_size - adapter->txd_write_ptr + + txd_read_ptr - 1): + (int) (txd_read_ptr - adapter->txd_write_ptr - 1); +} + +static int +atl2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + tx_pkt_header_t* txph; + u32 offset, copy_len; + int txs_unused; + int txbuf_unused; + + if (test_bit(__ATL2_DOWN, &adapter->flags)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (unlikely(skb->len <= 0)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +#ifdef NETIF_F_LLTX + local_irq_save(flags); + if (!spin_trylock(&adapter->tx_lock)) { + /* Collision - tell upper layer to requeue */ + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } +#else + spin_lock_irqsave(&adapter->tx_lock, flags); +#endif + txs_unused = TxsFreeUnit(adapter); + txbuf_unused = TxdFreeBytes(adapter); + + if (txs_unused < 1 || skb->len > txbuf_unused) { + // no enough resource + netif_stop_queue(netdev); + spin_unlock_irqrestore(&adapter->tx_lock, flags); + return NETDEV_TX_BUSY; + } + + offset = adapter->txd_write_ptr; + + txph = (tx_pkt_header_t*) (((u8*)adapter->txd_ring)+offset); + + *(u32*)txph = 0; + txph->pkt_size = skb->len; + + offset += 4; + if (offset >= adapter->txd_ring_size) + offset -= adapter->txd_ring_size; + copy_len = adapter->txd_ring_size - offset; + if (copy_len >= skb->len) { + memcpy(((u8*)adapter->txd_ring)+offset, skb->data, skb->len); + offset += ((u32)(skb->len+3)&~3); + } else { + memcpy(((u8*)adapter->txd_ring)+offset, skb->data, copy_len); + memcpy((u8*)adapter->txd_ring, skb->data+copy_len, skb->len-copy_len); + offset = ((u32)(skb->len-copy_len+3)&~3); + } +#ifdef NETIF_F_HW_VLAN_TX + if (adapter->vlgrp && vlan_tx_tag_present(skb)) { + u16 vlan_tag = vlan_tx_tag_get(skb); + vlan_tag = (vlan_tag << 4) | + (vlan_tag >> 13) | + ((vlan_tag >>9) & 0x8); + txph->ins_vlan = 1; + txph->vlan = vlan_tag; + } +#endif + if (offset >= adapter->txd_ring_size) + offset -= adapter->txd_ring_size; + adapter->txd_write_ptr = offset; + + // clear txs before send + adapter->txs_ring[adapter->txs_next_clear].update = 0; + if (++adapter->txs_next_clear == adapter->txs_ring_size) + adapter->txs_next_clear = 0; + + ATL2_WRITE_REGW(&adapter->hw, REG_MB_TXD_WR_IDX, (adapter->txd_write_ptr >> 2)); + + spin_unlock_irqrestore(&adapter->tx_lock, flags); + + netdev->trans_start = jiffies; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +/** + * atl2_get_stats - Get System Network Statistics + * @netdev: network interface device structure + * + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. + **/ +static struct net_device_stats * +atl2_get_stats(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + return &adapter->net_stats; +} + +/** + * atl2_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + **/ +static int +atl2_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + + if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE))) + return -EINVAL; + + /* set MTU */ + if (hw->max_frame_size != new_mtu) { +// while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags)) +// msleep(1); + netdev->mtu = new_mtu; + + ATL2_WRITE_REG(hw, REG_MTU, + new_mtu + ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE); +// clear_bit(__ATL2_RESETTING, &adapter->flags); + } + + return 0; +} + +/** + * atl2_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + **/ +static int +atl2_set_mac(struct net_device *netdev, void *p) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + if (netif_running(netdev)) + return -EBUSY; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + + atl2_set_mac_addr(&adapter->hw); + + return 0; +} + +/** + * atl2_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + **/ +static int +atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct mii_ioctl_data *data = if_mii(ifr); + unsigned long flags; + + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = 0; + break; + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + spin_lock_irqsave(&adapter->stats_lock, flags); + if (atl2_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, &data->val_out)) { + spin_unlock_irqrestore(&adapter->stats_lock, flags); + return -EIO; + } + spin_unlock_irqrestore(&adapter->stats_lock, flags); + break; + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (data->reg_num & ~(0x1F)) + return -EFAULT; + spin_lock_irqsave(&adapter->stats_lock, flags); + if (atl2_write_phy_reg(&adapter->hw, data->reg_num, data->val_in)) { + spin_unlock_irqrestore(&adapter->stats_lock, flags); + return -EIO; + } + spin_unlock_irqrestore(&adapter->stats_lock, flags); + break; + default: + return -EOPNOTSUPP; + } + return ATL2_SUCCESS; +} + +/** + * atl2_ioctl - + * @netdev: + * @ifreq: + * @cmd: + **/ +static int +atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return atl2_mii_ioctl(netdev, ifr, cmd); +#ifdef ETHTOOL_OPS_COMPAT + case SIOCETHTOOL: + return ethtool_ioctl(ifr); +#endif + default: + return -EOPNOTSUPP; + } +} + +/** + * atl2_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + **/ +static void +atl2_tx_timeout(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + /* Do the reset outside of interrupt context */ + schedule_work(&adapter->reset_task); +} + +/** + * atl2_watchdog - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + **/ +static void +atl2_watchdog(unsigned long data) +{ + struct atl2_adapter *adapter = (struct atl2_adapter *) data; + u32 drop_rxd, drop_rxs; + unsigned long flags; + + if (!test_bit(__ATL2_DOWN, &adapter->flags)) { + spin_lock_irqsave(&adapter->stats_lock, flags); + drop_rxd = ATL2_READ_REG(&adapter->hw, REG_STS_RXD_OV); + drop_rxs = ATL2_READ_REG(&adapter->hw, REG_STS_RXS_OV); + adapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs); + spin_unlock_irqrestore(&adapter->stats_lock, flags); + + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, jiffies + 4 * HZ); + } +} + +/** + * atl2_phy_config - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + **/ +static void +atl2_phy_config(unsigned long data) +{ + struct atl2_adapter *adapter = (struct atl2_adapter *) data; + struct atl2_hw *hw = &adapter->hw; + unsigned long flags; + + spin_lock_irqsave(&adapter->stats_lock, flags); + atl2_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); + atl2_write_phy_reg(hw, MII_BMCR, MII_CR_RESET|MII_CR_AUTO_NEG_EN|MII_CR_RESTART_AUTO_NEG); + spin_unlock_irqrestore(&adapter->stats_lock, flags); + clear_bit(0, &adapter->cfg_phy); +} + +int +atl2_up(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int err = 0; + u32 val; + + /* hardware has been reset, we need to reload some things */ + + err = atl2_init_hw(&adapter->hw); + if (err) { + err = -EIO; + return err; + } + + atl2_set_multi(netdev); + init_ring_ptrs(adapter); + +#ifdef NETIF_F_HW_VLAN_TX + atl2_restore_vlan(adapter); +#endif + + if (atl2_configure(adapter)) { + err = -EIO; + goto err_up; + } + + clear_bit(__ATL2_DOWN, &adapter->flags); + + val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL); + ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val | MASTER_CTRL_MANUAL_INT); + + atl2_irq_enable(adapter); + +err_up: + return err; +} + +void +atl2_reinit_locked(struct atl2_adapter *adapter) +{ + WARN_ON(in_interrupt()); + while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags)) + msleep(1); + atl2_down(adapter); + atl2_up(adapter); + clear_bit(__ATL2_RESETTING, &adapter->flags); +} + +static void +atl2_reset_task(struct work_struct *work) +{ + struct atl2_adapter *adapter; + adapter = container_of(work, struct atl2_adapter, reset_task); + + atl2_reinit_locked(adapter); +} + +static inline void +atl2_setup_mac_ctrl(struct atl2_adapter *adapter) +{ + u32 value; + struct atl2_hw* hw = &adapter->hw; + struct net_device* netdev = adapter->netdev; + + /* Config MAC CTRL Register */ + value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY; + + // duplex + if (FULL_DUPLEX == adapter->link_duplex) + value |= MAC_CTRL_DUPLX; + + // flow control + value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); + + // PAD & CRC + value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); + + // preamble length + value |= (((u32)adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) << + MAC_CTRL_PRMLEN_SHIFT); + + // vlan + if (adapter->vlgrp) + value |= MAC_CTRL_RMV_VLAN; + + // filter mode + value |= MAC_CTRL_BC_EN; + if (netdev->flags & IFF_PROMISC) + value |= MAC_CTRL_PROMIS_EN; + else if (netdev->flags & IFF_ALLMULTI) + value |= MAC_CTRL_MC_ALL_EN; + + // half retry buffer + value |= (((u32)(adapter->hw.retry_buf & MAC_CTRL_HALF_LEFT_BUF_MASK)) << + MAC_CTRL_HALF_LEFT_BUF_SHIFT); + + ATL2_WRITE_REG(hw, REG_MAC_CTRL, value); +} + +static int +atl2_check_link(struct atl2_adapter *adapter) +{ + struct atl2_hw *hw = &adapter->hw; + struct net_device * netdev = adapter->netdev; + int ret_val; + u16 speed, duplex, phy_data; + int reconfig = 0; + + // MII_BMSR must read twise + atl2_read_phy_reg(hw, MII_BMSR, &phy_data); + atl2_read_phy_reg(hw, MII_BMSR, &phy_data); + if (!(phy_data&BMSR_LSTATUS)) { // link down + if (netif_carrier_ok(netdev)) { // old link state: Up + u32 value; + //disable rx + value = ATL2_READ_REG(hw, REG_MAC_CTRL); + value &= ~MAC_CTRL_RX_EN; + ATL2_WRITE_REG(hw, REG_MAC_CTRL, value); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + return ATL2_SUCCESS; + } + + // Link Up + ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) + return ret_val; + switch( hw->MediaType ) { + case MEDIA_TYPE_100M_FULL: + if (speed != SPEED_100 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_100M_HALF: + if (speed != SPEED_100 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_FULL: + if (speed != SPEED_10 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_HALF: + if (speed != SPEED_10 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + } + // link result is our setting + if (0 == reconfig) { + if (adapter->link_speed != speed || adapter->link_duplex != duplex ) { + adapter->link_speed = speed; + adapter->link_duplex = duplex; + atl2_setup_mac_ctrl(adapter); + printk(KERN_INFO "%s: %s NIC Link is Up<%d Mbps %s>\n", + atl2_driver_name, netdev->name, + adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? + "Full Duplex" : "Half Duplex"); + } + + if (!netif_carrier_ok(netdev)) { // Link down -> Up + netif_carrier_on(netdev); + netif_wake_queue(netdev); + } + return ATL2_SUCCESS; + } + + // change orignal link status + if (netif_carrier_ok(netdev)) { + u32 value; + // disable rx + value = ATL2_READ_REG(hw, REG_MAC_CTRL); + value &= ~MAC_CTRL_RX_EN; + ATL2_WRITE_REG(hw, REG_MAC_CTRL, value); + + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + + // auto-neg, insert timer to re-config phy (if interval smaller than 5 seconds, something strange) + if (!test_bit(__ATL2_DOWN, &adapter->flags)) { + if (!test_and_set_bit(0, &adapter->cfg_phy)) { + mod_timer(&adapter->phy_config_timer, jiffies + 5 * HZ); + } + } + + return ATL2_SUCCESS; +} + +/** + * atl2_link_chg_task - deal with link change event Out of interrupt context + * @netdev: network interface device structure + **/ +static void +atl2_link_chg_task(struct work_struct *work) +{ + struct atl2_adapter *adapter; + unsigned long flags; + + adapter = container_of(work, struct atl2_adapter, link_chg_task); + + spin_lock_irqsave(&adapter->stats_lock, flags); + atl2_check_link(adapter); + spin_unlock_irqrestore(&adapter->stats_lock, flags); +} + +static void +atl2_setup_pcicmd(struct pci_dev *pdev) +{ + u16 cmd; + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + + if (cmd & PCI_COMMAND_INTX_DISABLE) + cmd &= ~PCI_COMMAND_INTX_DISABLE; + if (cmd & PCI_COMMAND_IO) + cmd &= ~PCI_COMMAND_IO; + if (0 == (cmd & PCI_COMMAND_MEMORY)) + cmd |= PCI_COMMAND_MEMORY; + if (0 == (cmd & PCI_COMMAND_MASTER)) + cmd |= PCI_COMMAND_MASTER; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + + /* + * some motherboards BIOS(PXE/EFI) driver may set PME + * while they transfer control to OS (Windows/Linux) + * so we should clear this bit before NIC work normally + */ + pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0); +} + +/** + * atl2_probe - Device Initialization Routine + * @pdev: PCI device information struct + * @ent: entry in atl2_pci_tbl + * + * Returns 0 on success, negative on failure + * + * atl2_probe initializes an adapter identified by a pci_dev structure. + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ +static int __devinit +atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct atl2_adapter *adapter; + static int cards_found = 0; + unsigned long mmio_start; + int mmio_len; + int err; + + if((err = pci_enable_device(pdev))) + return err; + + /* + * atl2 is a shared-high-32-bit device, so we're stuck with 32-bit DMA + * until the kernel has the proper infrastructure to support 64-bit DMA + * on these devices. + */ + if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) && + (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) { + printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n"); + goto err_dma; + } + + // Mark all PCI regions associated with PCI device + // pdev as being reserved by owner atl2_driver_name + if((err = pci_request_regions(pdev, atl2_driver_name))) + goto err_pci_reg; + + // Enables bus-mastering on the device and calls + // pcibios_set_master to do the needed arch specific settings + pci_set_master(pdev); + + err = -ENOMEM; + netdev = alloc_etherdev(sizeof(struct atl2_adapter)); + if(!netdev) + goto err_alloc_etherdev; + + SET_NETDEV_DEV(netdev, &pdev->dev); + + pci_set_drvdata(pdev, netdev); + adapter = netdev_priv(netdev); + adapter->netdev = netdev; + adapter->pdev = pdev; + adapter->hw.back = adapter; + + mmio_start = pci_resource_start(pdev, 0x0); + mmio_len = pci_resource_len(pdev, 0x0); + + adapter->hw.mem_rang = (u32)mmio_len; + adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); + if(!adapter->hw.hw_addr) { + err = -EIO; + goto err_ioremap; + } + + atl2_setup_pcicmd(pdev); + + netdev->open = &atl2_open; + netdev->stop = &atl2_close; + netdev->hard_start_xmit = &atl2_xmit_frame; + netdev->get_stats = &atl2_get_stats; + netdev->set_multicast_list = &atl2_set_multi; + netdev->set_mac_address = &atl2_set_mac; + netdev->change_mtu = &atl2_change_mtu; + netdev->do_ioctl = &atl2_ioctl; + atl2_set_ethtool_ops(netdev); + +#ifdef HAVE_TX_TIMEOUT + netdev->tx_timeout = &atl2_tx_timeout; + netdev->watchdog_timeo = 5 * HZ; //FIXME -- CHS +#endif +#ifdef NETIF_F_HW_VLAN_TX + netdev->vlan_rx_register = atl2_vlan_rx_register; +#endif + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + netdev->mem_start = mmio_start; + netdev->mem_end = mmio_start + mmio_len; + //netdev->base_addr = adapter->io_base; + adapter->bd_number = cards_found; + adapter->pci_using_64 = false; + + /* setup the private structure */ + + if((err = atl2_sw_init(adapter))) + goto err_sw_init; + + err = -EIO; + +#ifdef NETIF_F_HW_VLAN_TX + netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ); +#endif + +#ifdef NETIF_F_LLTX + netdev->features |= NETIF_F_LLTX; +#endif + + /* Init PHY as early as possible due to power saving issue */ + atl2_phy_init(&adapter->hw); + + /* reset the controller to + * put the device in a known good starting state */ + + if (atl2_reset_hw(&adapter->hw)) { + err = -EIO; + goto err_reset; + } + + /* copy the MAC address out of the EEPROM */ + atl2_read_mac_addr(&adapter->hw); + memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); +//FIXME: do we still need this? +#ifdef ETHTOOL_GPERMADDR + memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); + + if (!is_valid_ether_addr(netdev->perm_addr)) { +#else + if (!is_valid_ether_addr(netdev->dev_addr)) { +#endif + err = -EIO; + goto err_eeprom; + } + + atl2_check_options(adapter); + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &atl2_watchdog; + adapter->watchdog_timer.data = (unsigned long) adapter; + + init_timer(&adapter->phy_config_timer); + adapter->phy_config_timer.function = &atl2_phy_config; + adapter->phy_config_timer.data = (unsigned long) adapter; + + INIT_WORK(&adapter->reset_task, atl2_reset_task); + INIT_WORK(&adapter->link_chg_task, atl2_link_chg_task); + + strcpy(netdev->name, "eth%d"); // ?? + if((err = register_netdev(netdev))) + goto err_register; + + /* assume we have no link for now */ + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + cards_found++; + + return 0; + +//err_init_hw: +err_reset: +err_register: +err_sw_init: +err_eeprom: + iounmap(adapter->hw.hw_addr); +err_ioremap: + free_netdev(netdev); +err_alloc_etherdev: + pci_release_regions(pdev); +err_pci_reg: +err_dma: + pci_disable_device(pdev); + return err; +} + +/** + * atl2_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * atl2_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. The could be caused by a + * Hot-Plug event, or because the driver is going to be removed from + * memory. + **/ +/* FIXME: write the original MAC address back in case it was changed from a + * BIOS-set value, as in atl1 -- CHS */ +static void __devexit +atl2_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl2_adapter *adapter = netdev_priv(netdev); + + /* flush_scheduled work may reschedule our watchdog task, so + * explicitly disable watchdog tasks from being rescheduled */ + set_bit(__ATL2_DOWN, &adapter->flags); + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_config_timer); + + flush_scheduled_work(); + + unregister_netdev(netdev); + + atl2_force_ps(&adapter->hw); + + iounmap(adapter->hw.hw_addr); + pci_release_regions(pdev); + + free_netdev(netdev); + + pci_disable_device(pdev); +} + +static int +atl2_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw * hw = &adapter->hw; + u16 speed, duplex; + u32 ctrl = 0; + u32 wufc = adapter->wol; + +#ifdef CONFIG_PM + int retval = 0; +#endif + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags)); + atl2_down(adapter); + } + +#ifdef CONFIG_PM + retval = pci_save_state(pdev); + if (retval) + return retval; +#endif + + atl2_read_phy_reg(hw, MII_BMSR, (u16*)&ctrl); + atl2_read_phy_reg(hw, MII_BMSR, (u16*)&ctrl); + if(ctrl & BMSR_LSTATUS) + wufc &= ~ATL2_WUFC_LNKC; + + if (0 != (ctrl & BMSR_LSTATUS) && 0 != wufc) { + u32 ret_val; + /* get current link speed & duplex */ + ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) { + printk(KERN_DEBUG "%s: get speed&duplex error while suspend\n", atl2_driver_name); + goto wol_dis; + } + + ctrl = 0; + + /* turn on magic packet wol */ + if (wufc & ATL2_WUFC_MAG) + ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN); + + /* ignore Link Chg event when Link is up */ + ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl); + + /* Config MAC CTRL Register */ + ctrl = MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY; + if (FULL_DUPLEX == adapter->link_duplex) + ctrl |= MAC_CTRL_DUPLX; + ctrl |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); + ctrl |= (((u32)adapter->hw.preamble_len & + MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); + ctrl |= (((u32)(adapter->hw.retry_buf & + MAC_CTRL_HALF_LEFT_BUF_MASK)) << + MAC_CTRL_HALF_LEFT_BUF_SHIFT); + if (wufc & ATL2_WUFC_MAG) { + /* magic packet maybe Broadcast&multicast&Unicast frame */ + ctrl |= MAC_CTRL_BC_EN; + } + + ATL2_WRITE_REG(hw, REG_MAC_CTRL, ctrl); + + /* pcie patch */ + ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); + ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1); + ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl); + + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); + goto suspend_exit; + } + + if (0 == (ctrl&BMSR_LSTATUS) && 0 != (wufc&ATL2_WUFC_LNKC)) { + /* link is down, so only LINK CHG WOL event enable */ + ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); + ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl); + ATL2_WRITE_REG(hw, REG_MAC_CTRL, 0); + + /* pcie patch */ + ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); + ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1); + ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl); + + hw->phy_configured = false; /* re-init PHY when resume */ + + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); + + goto suspend_exit; + } + +wol_dis: + /* WOL disabled */ + ATL2_WRITE_REG(hw, REG_WOL_CTRL, 0); + + /* pcie patch */ + ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); + ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1); + ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl); + + atl2_force_ps(hw); + hw->phy_configured = false; /* re-init PHY when resume */ + + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + +suspend_exit: + if (netif_running(netdev)) + atl2_free_irq(adapter); + + pci_disable_device(pdev); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +#ifdef CONFIG_PM +static int +atl2_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl2_adapter *adapter = netdev_priv(netdev); + u32 err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if ((err = pci_enable_device(pdev))) { + printk(KERN_ERR "atl2: Cannot enable PCI device from suspend\n"); + return err; + } + + pci_set_master(pdev); + + ATL2_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */ + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); + + if (netif_running(netdev) && (err = atl2_request_irq(adapter))) + return err; + + atl2_reset_hw(&adapter->hw); + + if(netif_running(netdev)) + atl2_up(adapter); + + netif_device_attach(netdev); + + return 0; +} +#endif + +static void +atl2_shutdown(struct pci_dev *pdev) +{ + atl2_suspend(pdev, PMSG_SUSPEND); +} + +static struct pci_driver atl2_driver = { + .name = atl2_driver_name, + .id_table = atl2_pci_tbl, + .probe = atl2_probe, + .remove = __devexit_p(atl2_remove), + /* Power Managment Hooks */ + .suspend = atl2_suspend, +#ifdef CONFIG_PM + .resume = atl2_resume, +#endif + .shutdown = atl2_shutdown, +}; + +/** + * atl2_init_module - Driver Registration Routine + * + * atl2_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + **/ +static int __init +atl2_init_module(void) +{ + int ret; + printk(KERN_INFO "%s - version %s\n", atl2_driver_string, atl2_driver_version); + printk(KERN_INFO "%s\n", atl2_copyright); + + ret = pci_register_driver(&atl2_driver); + if (copybreak != COPYBREAK_DEFAULT) { + if (copybreak == 0) + printk(KERN_INFO "atl2: copybreak disabled\n"); + else + printk(KERN_INFO "atl2: copybreak enabled for packets <= %u bytes\n", copybreak); + } + return ret; +} +module_init(atl2_init_module); + +/** + * atl2_exit_module - Driver Exit Cleanup Routine + * + * atl2_exit_module is called just before the driver is removed + * from memory. + **/ +static void __exit +atl2_exit_module(void) +{ + pci_unregister_driver(&atl2_driver); +} +module_exit(atl2_exit_module); + +void +atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value) +{ + struct atl2_adapter *adapter = hw->back; + pci_read_config_word(adapter->pdev, reg, value); +} + +void +atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value) +{ + struct atl2_adapter *adapter = hw->back; + pci_write_config_word(adapter->pdev, reg, *value); +} --- linux-2.6.27.orig/ubuntu/heci/heci.h +++ linux-2.6.27/ubuntu/heci/heci.h @@ -0,0 +1,141 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef _HECI_H_ +#define _HECI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "heci_data_structures.h" + + +extern const struct guid heci_pthi_guid; +extern const struct guid heci_wd_guid; +extern const __u8 start_wd_params[]; +extern const __u8 stop_wd_params[]; +extern const __u8 heci_wd_state_independence_msg[2][4]; + +/** + * memory IO BAR definition + */ +#define BAR_0 0 +#define BAR_1 1 +#define BAR_5 5 +/** + * Number of queue lists used by this driver + */ +#define PCI_HECI_DEVICE_ID1 0x2974 +#define PCI_HECI_DEVICE_ID2 0x2984 +#define PCI_HECI_DEVICE_ID3 0x2994 +#define PCI_HECI_DEVICE_ID4 0x29A4 +#define PCI_HECI_DEVICE_ID5 0x29B4 +#define PCI_HECI_DEVICE_ID6 0x29C4 +#define PCI_HECI_DEVICE_ID7 0x29E4 +#define PCI_HECI_DEVICE_ID8 0x29F4 + +/** + * heci init function prototypes + */ +struct iamt_heci_device *init_heci_device(struct pci_dev *pdev); +void heci_reset(struct iamt_heci_device * device_object, int interrupts); +int heci_hw_init(struct iamt_heci_device * device_object); +int heci_initialize_clients(void *data); +struct heci_file_private *alloc_priv(struct file *file); +int heci_disconnect_host_client(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); +void heci_initialize_list(struct io_heci_list *list, + struct iamt_heci_device * device_object); +void heci_flush_list(struct io_heci_list *list, + struct heci_file_private * file_extension); +void heci_flush_queues(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); + +void heci_remove_client_from_file_list(struct iamt_heci_device * device_object, + __u8 host_client_id); + +/** + * interrupt function prototype + */ +irqreturn_t heci_isr_interrupt(int irq, void *dev_id); +void heci_wd_timer(unsigned long data); +void heci_bh_handler(struct work_struct *work); +/** + * input output function prototype + */ +int heci_ioctl_get_version(struct iamt_heci_device * device, int if_num, + struct heci_message_data *u_msg, + struct heci_message_data k_msg, + struct heci_file_private * file_extension); +int heci_ioctl_connect_client(struct iamt_heci_device * device, int if_num, + struct heci_message_data *u_msg, + struct heci_message_data k_msg, + struct file *file); +int heci_ioctl_wd(struct iamt_heci_device * device, int if_num, + struct heci_message_data k_msg, + struct heci_file_private * file_extension); +int heci_ioctl_bypass_wd(struct iamt_heci_device * device, int if_num, + struct heci_message_data k_msg, + struct heci_file_private * file_extension); +int legacy_ioctl_send_message(struct iamt_heci_device * device, int if_num, + struct heci_message_data k_msg, + struct file *file); +int legacy_ioctl_receive_message(struct iamt_heci_device * device, int if_num, + struct heci_message_data *u_msg, + struct heci_message_data k_msg, + struct file *file); +int heci_start_read(struct iamt_heci_device * device, int if_num, + struct heci_file_private * file_extension); +int pthi_write(struct iamt_heci_device * device, + struct heci_cb_private *kernel_priv_cb); +int pthi_read(struct iamt_heci_device * device, int if_num, struct file *file, + char *ubuf, size_t length, loff_t* offset); +struct heci_cb_private* find_pthi_read_list_entry(struct iamt_heci_device* device, + struct file* file, struct heci_file_private* file_extension); +void run_next_legacy_cmd(struct iamt_heci_device * device); + +#endif /* _HECI_H_ */ --- linux-2.6.27.orig/ubuntu/heci/kcompat.h +++ linux-2.6.27/ubuntu/heci/kcompat.h @@ -0,0 +1,165 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef _KCOMPAT_H_ +#define _KCOMPAT_H_ + +#include +#include +#include +#include +#include +#include +#include + + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) ) +#undef INIT_WORK +#define INIT_WORK(_work, _func) \ +do { \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->pending = 0; \ + (_work)->func = (void (*)(void *))_func; \ + (_work)->data = _work; \ + init_timer(&(_work)->timer); \ +} while (0) +#undef PREPARE_WORK +#define PREPARE_WORK(_work, _func) \ + do { \ + (_work)->func = (void (*)(void *))_func;\ + (_work)->data = _work;\ + } while (0) + + +#endif + +#ifndef round_jiffies +#define round_jiffies(x) x +#endif + +#endif /* < 2.6.20 */ + + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) + +#ifndef IRQF_PROBE_SHARED +#ifdef SA_PROBEIRQ +#define IRQF_PROBE_SHARED SA_PROBEIRQ +#else +#define IRQF_PROBE_SHARED 0 +#endif +#endif + +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#endif /* < 2.6.18 */ + + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) + +#ifndef RHEL_VERSION +#define RHEL_VERSION 0 +#endif +#if (!(( RHEL_VERSION == 4 ) && ( RHEL_UPDATE >= 5 ))) +typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *); +#endif +typedef irqreturn_t (*new_handler_t)(int, void*); +static inline irqreturn_t _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) +{ + irq_handler_t new_handler = (irq_handler_t) handler; + return request_irq(irq, new_handler, flags, devname, dev_id); +} + +#undef request_irq +#define request_irq(irq, handler, flags, devname, dev_id) _kc_request_irq((irq), (handler), (flags), (devname), (dev_id)) + +#endif + + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) +#define SHUTDOWN_METHOD(method) +#define HECI_REBOOT_NOTIFIER(reboot_notifier, driver, reboot_function) \ +static int heci_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) \ +{ \ + struct pci_dev *pdev = NULL; \ +\ + switch(event){ \ + case SYS_DOWN: \ + case SYS_HALT: \ + case SYS_POWER_OFF: \ + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { \ + if (pci_dev_driver(pdev) == &driver) { \ + reboot_function(pdev); \ + } \ + } \ + } \ + return NOTIFY_DONE; \ +};\ +static struct notifier_block reboot_notifier = { \ + .notifier_call = heci_notify_reboot, \ + .next = NULL, \ + .priority = 0 \ +}; + +#define REGISTER_REBOOT_NOTIFIER(reboot_notifier) \ + register_reboot_notifier(&reboot_notifier); +#define UNREGISTER_REBOOT_NOTIFIER(reboot_notifier) \ + unregister_reboot_notifier(&reboot_notifier); +#else +#define SHUTDOWN_METHOD(method) .shutdown = method, +#define HECI_REBOOT_NOTIFIER(reboot_notifier, driver, reboot_function) +#define REGISTER_REBOOT_NOTIFIER(reboot_notifier) +#define UNREGISTER_REBOOT_NOTIFIER(reboot_notifier) +#define heci_reboot_notifier +#endif //( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) + + +#endif --- linux-2.6.27.orig/ubuntu/heci/Kconfig +++ linux-2.6.27/ubuntu/heci/Kconfig @@ -0,0 +1,3 @@ +config HECI + tristate "Intel(R) Manageability Engine Interface Driver" + default m --- linux-2.6.27.orig/ubuntu/heci/version.h +++ linux-2.6.27/ubuntu/heci/version.h @@ -0,0 +1,53 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2006-2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef HECI_VERSION_H +#define HECI_VERSION_H + +#define MAJOR_VERSION 3 +#define MINOR_VERSION 2 +#define QUICK_FIX_NUMBER 0 +#define VER_BUILD 24 + +#define str(s) name(s) +#define name(s) #s +#define DRIVER_VERSION str(MAJOR_VERSION) "." str(MINOR_VERSION) "." str(QUICK_FIX_NUMBER) "." str(VER_BUILD) + +#endif --- linux-2.6.27.orig/ubuntu/heci/heci_data_structures.h +++ linux-2.6.27/ubuntu/heci/heci_data_structures.h @@ -0,0 +1,538 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef _HECI_DATA_STRUCTURES_H_ +#define _HECI_DATA_STRUCTURES_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * error code definition + */ +#define ESUCCESS 0 +#define ESLOTS_OVERFLOW 1 +#define ECORRUPTED_MESSAGE_HEADER 1000 +#define ECOMPLETE_MESSAGE 1001 +#define FC_MESSAGE_RESERVED_LENGTH 5 + +/** + * Number of queue lists used by this driver + */ +#define NUMBER_OF_LISTS 7 + +#define LEGACY_MTU 4160 +#pragma pack(1) + + +/** + * HECI HW Section + */ + +/* HECI addresses and defines */ +#define H_CB_WW 0 +#define H_CSR 4 +#define ME_CB_RW 8 +#define ME_CSR_HA 0xC + + +/* register bits - H_CSR */ + +#define H_CBD 0xFF000000 +#define H_CBWP 0x00FF0000 +#define H_CBRP 0x0000FF00 +#define H_RST 0x00000010 +#define H_RDY 0x00000008 +#define H_IG 0x00000004 +#define H_IS 0x00000002 +#define H_IE 0x00000001 + + +/* register bits - ME_CSR_HA */ +#define ME_CBD_HRA 0xFF000000 +#define ME_CBWP_HRA 0x00FF0000 +#define ME_CBRP_HRA 0x0000FF00 +#define ME_RST_HRA 0x00000010 +#define ME_RDY_HRA 0x00000008 +#define ME_IG_HRA 0x00000004 +#define ME_IS_HRA 0x00000002 +#define ME_IE_HRA 0x00000001 + +/** + * heci driver use additional char device for legacy mode + */ +#define MINORS_COUNT 2 + +#define LEGACY_MINOR_NUMBER 0 +#define HECI_MINOR_NUMBER 1 +#define MAX_OPEN_HANDLE_COUNT 253 +/** + * debug kernel print macro define + */ +#define HECI_INFO(format, arg...) printk(KERN_INFO "%s: " format, THIS_MODULE->name, ## arg) +#define HECI_ERR(format, arg...) printk(KERN_ERR "%s: " format, THIS_MODULE->name, ## arg) +#define HECI_WARN(format, arg...) printk(KERN_WARNING "%s: " format, THIS_MODULE->name, ## arg) + + +/* Module Parameters */ +#define DEF_PARM(type, name, init, perm, desc) \ + type name = (init); \ + MODULE_PARM_DESC(name, desc); \ + module_param(name, type, perm) + +extern int debug; + +#define DBG(format, arg...) do {if (debug) \ +printk(KERN_ERR "%s: " format , __func__ , ## arg); \ +} while (0) + +#ifdef HECI_DEBUG +#define assert(expr) do {} while (0) +#else +#define assert(expr) \ + if (!(expr)) { \ + printk("Assertion failed! %s, %s, %s, line=%d\n", \ + #expr, __FILE__, __func__, __LINE__); \ + } +#endif + +/** + * time to wait event + */ +#define HECI_INTEROP_TIMEOUT (HZ * 7) + +/** + * watch dog definition + */ +#define HECI_WATCHDOG_DATA_SIZE 16 +#define HECI_START_WD_DATA_SIZE 20 +#define HECI_WD_PARAMS_SIZE 4 + +#define HECI_NO_MSG_SENT 0 +#define HECI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) + + +#define HECI_WD_HOST_CLIENT_ID 1 +#define HECI_LEGACY_HOST_CLIENT_ID 2 + +#undef FALSE +#undef TRUE +#define TRUE 1 +#define FALSE 0 + +struct guid { + __u32 data1; + __u16 data2; + __u16 data3; + __u8 data4[8]; +}; + +/* File state */ +enum file_state { + HECI_FILE_INITIALIZING = 0, + HECI_FILE_CONNECTING, + HECI_FILE_CONNECTED, + HECI_FILE_DISCONNECTING, + HECI_FILE_DISCONNECTED +}; + +/* HECI states */ +enum heci_states{ + HECI_INITIALIZING = 0, + HECI_ENABLED, + HECI_RESETING, + HECI_DISABLED, + HECI_RECOVERING_FROM_RESET, + HECI_POWER_DOWN, + HECI_POWER_UP +}; + +enum legacy_states { + HECI_LEGACY_IDLE, + HECI_LEGACY_WRITING, + HECI_LEGACY_FLOW_CONTROL, + HECI_LEGACY_READING, + HECI_LEGACY_READ_COMPLETE +}; + +enum heci_file_transaction_states { + HECI_IDLE, + HECI_WRITING, + HECI_WRITE_COMPLETE, + HECI_FLOW_CONTROL, + HECI_READING, + HECI_READ_COMPLETE +}; + +/* HECI CB */ +enum heci_cb_major_types { + HECI_READ = 0, + HECI_WRITE, + HECI_IOCTL, + HECI_OPEN, + HECI_CLOSE +}; + +/* HECI user data struct */ +struct heci_message_data { + __u32 size; + char *data; +}; +#define SECOND_TO_MILLI 1000 +#define SECOND_TO_MICRO SECOND_TO_MILLI * 1000 +#define SECOND_TO_100NANO SECOND_TO_MICRO * 10 + +#define CONNECT_TIMEOUT 3 /* at least 2 seconds */ + +#define LEGACY_STALL_TIMER 12 /* seconds */ +#define LEGACY_READ_TIMER 15 /* seconds */ + +struct heci_cb_private { + struct list_head cb_list; + enum heci_cb_major_types major_file_operations; + void *file_private; + struct heci_message_data request_buffer; + struct heci_message_data response_buffer; + unsigned long information; + unsigned long read_time; + struct file *file_object; +}; + +/* Private file struct */ +struct heci_file_private { + struct list_head link; + struct file *file; + enum file_state state; + wait_queue_head_t tx_wait; + wait_queue_head_t rx_wait; + wait_queue_head_t wait; + spinlock_t file_lock; + spinlock_t read_io_lock; + spinlock_t write_io_lock; + int read_pending; + int status; + /* ID of client connected */ + __u8 host_client_id; + __u8 me_client_id; + __u8 flow_control_credentials; + __u8 timer_count; + enum heci_file_transaction_states reading_state; + enum heci_file_transaction_states writing_state; + int sm_state; + struct heci_cb_private *read_cb; +}; + +struct io_heci_list { + struct heci_cb_private heci_cb; + int status; + struct iamt_heci_device *device_extension; +}; + +struct heci_driver_version { + __u8 major; + __u8 minor; + __u8 hotfix; + __u16 build; +}; + + +struct heci_client { + __u32 max_message_length; + __u8 protocol_version; +}; +/* + * HECI BUS Interface Section + */ +struct heci_message_header { + __u32 me_address:8; + __u32 host_address:8; + __u32 length:9; + __u32 reserved:6; + __u32 message_complete:1; +}; + + +struct hbm_command { + __u8 command:7; + __u8 is_response:1; +}; + + +struct heci_bus_message { + struct hbm_command command; + __u8 command_specific_data[]; +}; + +struct hbm_version { + __u8 minor_version; + __u8 major_version; +}; + +struct hbm_host_version_request { + struct hbm_command command; + __u8 reserved; + struct hbm_version host_version; +}; + +struct hbm_host_version_response { + struct hbm_command command; + int host_version_supported; + struct hbm_version me_max_version; +}; + +struct hbm_host_stop_request { + struct hbm_command command; + __u8 reason; + __u8 reserved[2]; +}; + +struct hbm_host_stop_response { + struct hbm_command command; + __u8 reserved[3]; +}; + +struct hbm_me_stop_request { + struct hbm_command command; + __u8 reason; + __u8 reserved[2]; +}; + +struct hbm_host_enumeration_request { + struct hbm_command command; + __u8 reserved[3]; +}; + +struct hbm_host_enumeration_response { + struct hbm_command command; + __u8 reserved[3]; + __u8 valid_addresses[32]; +}; + +struct heci_client_properties { + struct guid protocol_name; + __u8 protocol_version; + __u8 max_number_of_connections; + __u8 fixed_address; + __u8 single_receive_buffer; + __u32 max_message_length; +}; + +struct hbm_host_client_properties_request { + struct hbm_command command; + __u8 address; + __u8 reserved[2]; +}; + + +struct hbm_host_client_properties_response { + struct hbm_command command; + __u8 address; + __u8 status; + __u8 reserved[1]; + struct heci_client_properties client_properties; +}; + +struct hbm_client_connect_request { + struct hbm_command command; + __u8 me_address; + __u8 host_address; + __u8 reserved; +}; + +struct hbm_client_connect_response { + struct hbm_command command; + __u8 me_address; + __u8 host_address; + __u8 status; +}; + +struct hbm_client_disconnect_request { + struct hbm_command command; + __u8 me_address; + __u8 host_address; + __u8 reserved[1]; +}; + +struct hbm_flow_control { + struct hbm_command command; + __u8 me_address; + __u8 host_address; + __u8 reserved[FC_MESSAGE_RESERVED_LENGTH]; +}; + +struct heci_me_client { + struct heci_client_properties properteis; + __u8 client_id; + __u8 flow_control_credentials; +}; + +/* private device struct */ +struct iamt_heci_device { + struct pci_dev *pdev; /* pointer to pci device struct */ + /* + * lists of queues + */ + struct io_heci_list *io_list_array[NUMBER_OF_LISTS]; /* array of pointers to aio lists */ + struct io_heci_list read_list; /* driver read queue */ + struct io_heci_list write_list; /* driver write queue */ + struct io_heci_list write_waiting_list; /* driver write waiting queue */ + struct io_heci_list control_write_list; /* driver managed write IOCTL list */ + struct io_heci_list control_read_list; /* driver managed read IOCTL list */ + struct io_heci_list pthi_cmd_list; /* driver managed PTHI list for cmd waiting */ + struct io_heci_list pthi_read_complete_list; /* driver managed PTHI list for read completed pthi command data */ + /* + * list of files + */ + struct list_head file_list; + /* + * memory of device + */ + unsigned int mem_base; + unsigned int mem_length; + char *mem_addr; + /* + * lock for the device + */ + spinlock_t device_lock; + spinlock_t extra_lock; + /* + * intterupts + */ + int irq; + struct work_struct work; + int received_message; + + struct timer_list timer; + struct timer_list wd_timer; + /* + * hw states of host and fw(ME) + */ + __u32 host_hw_state; + __u32 me_hw_state; + /* + * waiting queue for receive message from FW + */ + wait_queue_head_t wait_received_message; + wait_queue_head_t wait_stop_wd; + /* + * heci device states + */ + enum heci_states heci_state; + int stop; + /** + * virtual void GetParam(const char* UserParam); + * read write messages to/from heci fw + */ + __u32 extra_write_index; + __u32 read_message_buffer[128]; /* used for control messages */ + __u32 write_message_buffer[128]; /* used for control messages */ + __u32 extra_message_buffer[8]; /* for control responses */ + __u32 read_message_header; + + struct hbm_version version; + + int host_buffer_is_empty; + struct heci_file_private wd_file_extension; + struct heci_me_client *me_clients; /* Note: memory has to be allocated */ + __u8 heci_me_clients[32]; /* list of existing clients */ + __u8 num_heci_me_clients; + __u8 heci_host_clients[32]; /* list of existing clients */ + __u8 current_host_client_id; + + int wd_pending; + int wd_stoped; + __u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ + unsigned char wd_data[HECI_START_WD_DATA_SIZE]; + + + __u16 wd_due_counter; + int asf_mode; + int wd_bypass; /* if true,don't refresh watchdog ME client */ + + /* maybe this is not required */ + struct file *legacy_file_object; + struct heci_file_private legacy_file_extension; + int legacy_ioctl; + int legacy_canceled; + __u32 legacy_timer; + __u32 legacy_stall_timer; + unsigned char legacy_message_buffer[LEGACY_MTU]; + __u32 legacy_message_buffer_size; + __u32 legacy_message_buffer_index; + int legacy_flow_control_pending; + enum legacy_states legacy_state; + + struct heci_cb_private *legacy_current_cb; + __u8 write_hang; + int need_reset; + long open_handle_count; + +}; + +/** + * read_heci_register - Read a byte from the heci device + * @device: the device structure + * @offset: offset from which to read the data + * + * Return: + * the byte read. + */ +__u32 read_heci_register(struct iamt_heci_device * device, + unsigned long offset); + +/** + * write_heci_register - Write 4 bytes to the heci device + * @device: the device structure + * @offset: offset from which to write the data + * + * @value: the byte to write + */ +void write_heci_register(struct iamt_heci_device * device, unsigned long offset, + __u32 value); + +#endif /* _HECI_DATA_STRUCTURES_H_ */ --- linux-2.6.27.orig/ubuntu/heci/interrupt.c +++ linux-2.6.27/ubuntu/heci/interrupt.c @@ -0,0 +1,1413 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2006-2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include +#include "kcompat.h" +#include "heci.h" +#include "heci_interface.h" + +/** + * interrupt function prototypes + */ + +void heci_bh_handler(struct work_struct *work); +int heci_bh_read_handler(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + __s32 * slots); +int heci_bh_write_handler(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + __s32 * slots); +void heci_bh_read_bus_message(struct iamt_heci_device * device_object, + struct heci_message_header * heci_header); +int heci_bh_read_pthi_message(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + struct heci_message_header * heci_header); +int heci_bh_read_client_message(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + struct heci_message_header * heci_header); +void heci_client_connect_response(struct iamt_heci_device * device_object, + struct hbm_client_connect_response * + connect_res); +void heci_client_disconnect_response(struct iamt_heci_device * device_object, + struct hbm_client_connect_response * + disconnect_res); +void heci_client_flow_control_response(struct iamt_heci_device * device_object, + struct hbm_flow_control * flow_control); +void heci_client_disconnect_request(struct iamt_heci_device * device_object, + struct hbm_client_disconnect_request * + disconnect_req); + + +/** + * heci_isr_interrupt - The ISR of the HECI device + * @irq: The irq number + * @dev_id: pointer to the device structure + * @regs: the register values + * + * @return : + * irqreturn_t + */ +irqreturn_t heci_isr_interrupt(int irq, void *dev_id) +{ + int err; + struct iamt_heci_device *device = (struct iamt_heci_device *) dev_id; + device->host_hw_state = read_heci_register(device, H_CSR); + + if ((device->host_hw_state & H_IS) != H_IS) + return IRQ_NONE; + + /* disable interrupts */ + device->host_hw_state &= ~H_IE; + /* acknowledge interrupt and stop interupts */ + write_heci_register(device, H_CSR, device->host_hw_state); + /** + * Our device interrupted, schedule work the heci_bh_handler + * to handle the interrupt processing. This needs to be a + * workqueue item since the handler can sleep. + */ + PREPARE_WORK(&device->work, heci_bh_handler); + DBG("schedule work the heci_bh_handler \n"); + err = schedule_work(&device->work); + if (!err) + HECI_ERR("schedule work the heci_bh_handler failed error=%x\n", + err); + return IRQ_HANDLED; +} + +/** + * heci_bh_handler - function called after ISR to handle the interrupt processing. + * @data: pointer to the device structure + * + * NOTE: This function is called by schedule work + * @return : + * none; + */ +void heci_bh_handler(struct work_struct *work) +{ + struct iamt_heci_device *device = container_of(work, struct iamt_heci_device, work); + struct io_heci_list complete_list; + __s32 slots; + int return_status; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + struct heci_file_private *file_extension = NULL; + int bus_message_received = FALSE; + struct task_struct *tsk; + + DBG("function called after ISR to handle the interrupt processing.\n"); + /* initialize our complete list */ + spin_lock_bh(&device->device_lock); + heci_initialize_list(&complete_list, device); + device->host_hw_state = read_heci_register(device, H_CSR); + device->me_hw_state = read_heci_register(device, ME_CSR_HA); + + /* check if ME wants a reset */ + if (((device->me_hw_state & ME_RDY_HRA) == 0) && + (device->heci_state != HECI_RESETING) + && (device->heci_state != HECI_INITIALIZING)) { + DBG("FW not ready.\n"); + heci_reset(device, TRUE); + spin_unlock_bh(&device->device_lock); + return; + } + + /* check if we need to start the device */ + if ((device->host_hw_state & H_RDY) == 0) { + + if ((device->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) { + DBG("we need to start the device.\n"); + device->host_hw_state |= (H_IE | H_IG | H_RDY); + write_heci_register(device, H_CSR, + device->host_hw_state); + if (device->heci_state == HECI_INITIALIZING) { + + device->received_message = TRUE; + spin_unlock_bh(&device->device_lock); + wake_up_interruptible(&device-> + wait_received_message); + return; + + } else { + spin_unlock_bh(&device->device_lock); + tsk = kthread_run(heci_initialize_clients, + device, "heci"); + if (IS_ERR(tsk)) { + int rc = PTR_ERR(tsk); + printk(KERN_WARNING "heci: " + "Unable to start the thread for heci: %d\n", + rc); + } + return; + } + + + } else { + DBG("Enable interrupt FW not ready \n"); + device->host_hw_state |= (H_IE); + write_heci_register(device, H_CSR, + device->host_hw_state); + spin_unlock_bh(&device->device_lock); + return; + } + } + /* check slots avalable for reading */ + slots = count_full_read_slots(device); + DBG("slots =%08x extra_write_index =%08x.\n", slots, + device->extra_write_index); + while ((slots > 0) && (!device->extra_write_index)) { + DBG("slots =%08x extra_write_index =%08x.\n", slots, + device->extra_write_index); + DBG("call heci_bh_read_handler.\n"); + return_status = + heci_bh_read_handler(&complete_list, device, &slots); + if (return_status != ESUCCESS) + goto end; + } + return_status = + heci_bh_write_handler(&complete_list, device, &slots); +end: + DBG("end of bottom half function.\n"); + device->host_hw_state = read_heci_register(device, H_CSR); + device->host_buffer_is_empty = host_buffer_is_empty(device); + + if ((device->host_hw_state & H_IS) == H_IS) { + PREPARE_WORK(&device->work, heci_bh_handler); + DBG("schedule work the heci_bh_handler.\n"); + return_status = schedule_work(&device->work); + if (!return_status) + HECI_ERR("schedule work the heci_bh_handler failed error=%x\n", return_status); + } else { + device->host_hw_state |= H_IE; + } + + write_heci_register(device, H_CSR, device->host_hw_state); + + + if (device->received_message + && waitqueue_active(&device->wait_received_message)) { + DBG("received waiting bus message\n"); + bus_message_received = TRUE; + } + spin_unlock_bh(&device->device_lock); + if (bus_message_received) { + DBG("wake up device->wait_received_message\n"); + wake_up_interruptible(&device->wait_received_message); + bus_message_received = FALSE; + } + if (complete_list.status != ESUCCESS || list_empty(&complete_list.heci_cb.cb_list)){ + return; + } + + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &complete_list.heci_cb.cb_list, cb_list){ + + file_extension = + (struct heci_file_private *) kernel_priv_cb_pos-> + file_private; + list_del(&kernel_priv_cb_pos->cb_list); + if (file_extension && file_extension != &device->legacy_file_extension) { + DBG("completing call back.\n"); + if (kernel_priv_cb_pos->major_file_operations == HECI_WRITE) { + + kfree(kernel_priv_cb_pos-> request_buffer.data); + kernel_priv_cb_pos->request_buffer.data = NULL; + kfree(kernel_priv_cb_pos); + kernel_priv_cb_pos = NULL; + DBG("completing write call back.\n"); + file_extension->writing_state = + HECI_WRITE_COMPLETE; + if (&file_extension->tx_wait && + waitqueue_active (&file_extension->tx_wait)) { + wake_up_interruptible + (&file_extension->tx_wait); + } + } else if (kernel_priv_cb_pos->major_file_operations == HECI_READ + && HECI_READING == file_extension->reading_state) { + DBG("completing read call back information= %lu\n", + kernel_priv_cb_pos->information); + file_extension->reading_state = HECI_READ_COMPLETE; + if (&file_extension->rx_wait + && waitqueue_active (&file_extension->rx_wait)) { + wake_up_interruptible + (&file_extension->rx_wait); + } + + } + } else if (file_extension == &device->legacy_file_extension) { + if (device->legacy_canceled != TRUE) { + device->legacy_state = HECI_LEGACY_READ_COMPLETE; + device->legacy_stall_timer = 0; + memcpy(kernel_priv_cb_pos->response_buffer. + data, + device-> + legacy_message_buffer, + device-> + legacy_message_buffer_index); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &device-> + pthi_read_complete_list. + heci_cb.cb_list); + DBG("pthi read completed\n"); + } else { + run_next_legacy_cmd(device); + } + if (&device->legacy_file_extension.wait) { + DBG("completing pthi call back.\n"); + wake_up_interruptible(&device-> + legacy_file_extension. + wait); + + } + + } + } + return; +} + + +/** + * heci_bh_read_handler - bottom half read routine after ISR to handle the read processing. + * + * + * @complete_list - An instance of our list structure + * @device_object - Device object for our driver + * @slots - slots to read. + * @return : + * 0 on success, + * negative on failure. + */ +int heci_bh_read_handler(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + __s32 * slots) +{ + struct heci_message_header *heci_header; + int ret = ESUCCESS; + struct heci_file_private *file_extension_pos = NULL; + struct heci_file_private *file_extension_next = NULL; + if (!device_object->read_message_header) { + device_object->read_message_header = + read_heci_register(device_object, ME_CB_RW); + DBG("slots=%08x.\n", *slots); + (*slots)--; + DBG("slots=%08x.\n", *slots); + } + heci_header = + (struct heci_message_header *) & device_object->read_message_header; + DBG("heci_header->length =%d\n", heci_header->length); + + if ((heci_header->reserved) + || !(device_object->read_message_header)) { + DBG("corrupted message header.\n"); + ret = -ECORRUPTED_MESSAGE_HEADER; + goto end; + } + if (heci_header->host_address || heci_header->me_address) { + + list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) { + DBG("list_for_each_entry_safe read host client = %d, ME client = %d\n", + file_extension_pos->host_client_id, + file_extension_pos->me_client_id); + if ((file_extension_pos->host_client_id == heci_header->host_address) + && (file_extension_pos->me_client_id == heci_header->me_address)) + break; + } + + if (&file_extension_pos->link==&device_object->file_list) { + DBG("corrupted message header\n"); + ret = -ECORRUPTED_MESSAGE_HEADER; + goto end; + + } + } + if (((*slots) * sizeof(__u32)) < heci_header->length) { + DBG("we can't read the message slots=%08x.\n", *slots); + /* we can't read the message */ + ret = -ERANGE; + goto end; + } + + + /* decide where to read the message too */ + if (!heci_header->host_address) { + DBG("call heci_bh_read_bus_message.\n"); + heci_bh_read_bus_message(device_object, heci_header); + DBG("end heci_bh_read_bus_message.\n"); + } else if (heci_header->host_address == + device_object->legacy_file_extension.host_client_id + && HECI_FILE_CONNECTED == + device_object->legacy_file_extension.state + && device_object->legacy_state == HECI_LEGACY_READING) { + DBG("call heci_bh_read_legacy_message.\n"); + DBG("heci_header->length =%d\n", heci_header->length); + ret = + heci_bh_read_pthi_message(complete_list, device_object, + heci_header); + if (ret != ESUCCESS) + goto end; + } else { + DBG("call heci_bh_read_client_message.\n"); + ret = heci_bh_read_client_message(complete_list, + device_object, + heci_header); + if (ret != ESUCCESS) + goto end; + } + + /* reset the number of slots and header */ + *slots = count_full_read_slots(device_object); + device_object->read_message_header = 0; + + if (*slots == -ESLOTS_OVERFLOW) { /* overflow - reset */ + DBG("reseting due to slots overflow\n"); + /* set the event since message has been read */ + ret = -ERANGE; + goto end; + } +end: + + return ret; + +} + + +/** + * heci_bh_read_bus_message - bottom half read routine after ISR to handle the read bus message + * command processing. + * + * + * @complete_list - An instance of our list structure + * @device_object - Device object for our driver + * @buffer - message buffer will be filled + * @heci_header - header of bus message + * + * @return : + * none; + */ +void heci_bh_read_bus_message(struct iamt_heci_device * device_object, + struct heci_message_header * heci_header) +{ + struct heci_bus_message *heci_message; + struct hbm_host_version_response *version_res; + struct hbm_client_connect_response *connect_res; + struct hbm_client_connect_response *disconnect_res; + struct hbm_flow_control *flow_control; + struct hbm_host_client_properties_response *properteis_res; + struct hbm_host_enumeration_response *enum_res; + struct hbm_client_disconnect_request *disconnect_req; + struct hbm_host_stop_request *h_stop_req; + int i; + unsigned char *buffer; + buffer = NULL; + /* read the message to our buffer */ + buffer = (unsigned char *) device_object->read_message_buffer; + BUG_ON(heci_header->length >= + sizeof(device_object->read_message_buffer)); + heci_read_slots(device_object, buffer, heci_header->length); + heci_message = (struct heci_bus_message *) buffer; + + switch (*(__u8 *) heci_message) { + case HOST_START_RES_CMD: + version_res = (struct hbm_host_version_response *) heci_message; + if (version_res->host_version_supported) { + device_object->version.major_version = + HBM_MAJOR_VERSION; + device_object->version.minor_version = + HBM_MINOR_VERSION; + } else { + device_object->version = + version_res->me_max_version; + } + device_object->received_message = TRUE; + DBG("host start response message received.\n"); + break; + + case CLIENT_CONNECT_RES_CMD: + connect_res = + (struct hbm_client_connect_response *) heci_message; + heci_client_connect_response(device_object, connect_res); + DBG("client connect response message received.\n"); + wake_up(&device_object->wait_received_message); + break; + + case CLIENT_DISCONNECT_RES_CMD: + disconnect_res = + (struct hbm_client_connect_response *) heci_message; + heci_client_disconnect_response(device_object, + disconnect_res); + DBG("client disconnect response message received.\n"); + wake_up(&device_object->wait_received_message); + break; + + case FLOW_CONTROL_CMD: + flow_control = (struct hbm_flow_control *) heci_message; + heci_client_flow_control_response(device_object, + flow_control); + DBG("client flow control response message received.\n"); + break; + case HOST_CLIENT_PROPERTEIS_RES_CMD: + properteis_res = + (struct hbm_host_client_properties_response *) heci_message; + + + if (properteis_res->status != 0) { + BUG_ON(1); + break; + } + for (i = 0; i < device_object->num_heci_me_clients; i++) { + if (device_object->me_clients[i].client_id == + properteis_res->address) { + device_object->me_clients[i].properteis = + properteis_res->client_properties; + break; + } + + } + device_object->received_message = TRUE; + break; + case HOST_ENUM_RES_CMD: + enum_res = + (struct hbm_host_enumeration_response *) heci_message; + memcpy(device_object->heci_me_clients, + enum_res->valid_addresses, 32); + device_object->received_message = TRUE; + break; + case HOST_STOP_RES_CMD: + device_object->heci_state = HECI_DISABLED; + DBG("Reseting becase of FW stop response\n"); + heci_reset(device_object, TRUE); + break; + case CLIENT_DISCONNECT_REQ_CMD: + /* search for client */ + disconnect_req = + (struct hbm_client_disconnect_request *) heci_message; + heci_client_disconnect_request(device_object, + disconnect_req); + break; + case ME_STOP_REQ_CMD: + /* prepare stop request */ + heci_header = + (struct heci_message_header *) & device_object-> + extra_message_buffer[0]; + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_host_stop_request); + heci_header->message_complete = 1; + heci_header->reserved = 0; + h_stop_req = + (struct hbm_host_stop_request *) & device_object-> + extra_message_buffer[1]; + memset(h_stop_req, 0, sizeof(struct hbm_host_stop_request)); + h_stop_req->command.command = HOST_STOP_REQ_CMD; + h_stop_req->reason = DRIVER_STOP_REQUEST; + h_stop_req->reserved[0] = 0; + h_stop_req->reserved[1] = 0; + device_object->extra_write_index = 2; + break; + + default: + BUG_ON(1); + break; + + } + + return; + +} + +/** + * heci_bh_read_legacy_message - bottom half read routine after ISR to handle the read legacy message + * data processing. + * + * + * @complete_list - An instance of our list structure + * @device_object - Device object for our driver + * @buffer - message buffer will be filled + * @heci_header - header of legacy message + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_bh_read_pthi_message(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + struct heci_message_header * heci_header) +{ + struct heci_file_private *file_extension = NULL; + struct heci_cb_private *priv_cb = NULL; + int return_status = ESUCCESS; + unsigned char *buffer = NULL; + BUG_ON(heci_header->me_address != + device_object->legacy_file_extension.me_client_id); + BUG_ON(device_object->legacy_state != HECI_LEGACY_READING); + buffer = + (unsigned char *) (device_object->legacy_message_buffer + + device_object->legacy_message_buffer_index); + BUG_ON(sizeof(device_object->legacy_message_buffer) < + (device_object->legacy_message_buffer_index + + heci_header->length)); + heci_read_slots(device_object, buffer, heci_header->length); + + device_object->legacy_message_buffer_index += heci_header->length; + + if (heci_header->message_complete) { + DBG("pthi_message_buffer_index=%d\n", heci_header->length); + DBG("completed pthi read.\n "); + if (!device_object->legacy_current_cb) + return -ENODEV; + priv_cb = device_object->legacy_current_cb; + device_object->legacy_current_cb = NULL; + file_extension = + (struct heci_file_private *) priv_cb->file_private; + if (!file_extension) + return -ENODEV; + device_object->legacy_stall_timer = 0; + priv_cb->information = + device_object->legacy_message_buffer_index; + priv_cb->read_time = get_seconds(); + if (device_object->legacy_ioctl + && file_extension == &device_object->legacy_file_extension) { + /* found the legacy cb */ + DBG("complete the pthi read cb.\n "); + if (&device_object->legacy_file_extension) { + DBG("add the pthi read cb to complete.\n "); + list_add_tail(&priv_cb->cb_list, + &complete_list->heci_cb. + cb_list); + + } + } + } + return return_status; + +} + +/** + * heci_bh_read_client_message - bottom half read routine after ISR to handle the read heci client message + * data processing. + * + * + * @complete_list - An instance of our list structure + * @device_object - Device object for our driver + * @buffer - message buffer will be filled + * @heci_header - header of heci client message + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_bh_read_client_message(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + struct heci_message_header * heci_header) +{ + struct heci_file_private *file_extension = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + unsigned char *buffer = NULL; + DBG ("Start client msg \n"); + if (device_object->read_list.status == ESUCCESS + && !list_empty(&device_object->read_list.heci_cb.cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object-> + read_list.heci_cb.cb_list, cb_list){ + file_extension = (struct heci_file_private *) kernel_priv_cb_pos->file_private; + if ((file_extension->host_client_id == heci_header->host_address) + && (file_extension->me_client_id == heci_header->me_address) + && (file_extension->state == HECI_FILE_CONNECTED) + && (HECI_READ_COMPLETE != file_extension->reading_state)) { + spin_lock(&file_extension->read_io_lock); + file_extension->reading_state = + HECI_READING; + buffer = (unsigned char *) (kernel_priv_cb_pos->response_buffer.data + + kernel_priv_cb_pos->information); + BUG_ON(kernel_priv_cb_pos->response_buffer.size < heci_header->length + + kernel_priv_cb_pos->information); + + if (kernel_priv_cb_pos->response_buffer.size < heci_header->length + + kernel_priv_cb_pos->information) { + DBG(" message overflow.\n"); + list_del(&kernel_priv_cb_pos->cb_list); + spin_unlock(&file_extension-> + read_io_lock); + return -ENOMEM; + } + if (buffer) + heci_read_slots(device_object, + buffer, + heci_header-> + length); + kernel_priv_cb_pos->information += + heci_header->length; + if (heci_header->message_complete) { + file_extension->status = ESUCCESS; + list_del(&kernel_priv_cb_pos->cb_list); + spin_unlock(&file_extension-> + read_io_lock); + DBG("completed read host client = %d, ME client = %d, data length = %lu\n", + file_extension->host_client_id, + file_extension->me_client_id, + kernel_priv_cb_pos->information); + *(kernel_priv_cb_pos->response_buffer.data + kernel_priv_cb_pos->information) = '\0'; + DBG("kernel_priv_cb_pos->response_buffer - %s\n", + kernel_priv_cb_pos->response_buffer.data); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &complete_list->heci_cb.cb_list); + } else { + spin_unlock(&file_extension-> + read_io_lock); + } + + break; + } + + } + + } + DBG ("Message read\n"); + if (!buffer) { + heci_read_slots(device_object, + (unsigned char *) device_object-> + read_message_buffer, heci_header->length); + DBG("discarding message, header=%08x.\n", + *(__u32 *) device_object->read_message_buffer); + } + + return ESUCCESS; +} + + +/** + * heci_bh_write_handler - bottom half write routine after ISR to handle the write processing. + * + * + * @complete_list - An instance of our list structure + * @device_object - Device object for our driver + * @slots - slots to write. + * @return : + * 0 on success, + * negative on failure. + */ +int heci_bh_write_handler(struct io_heci_list *complete_list, + struct iamt_heci_device * device_object, + __s32 * slots) +{ + + struct heci_message_header *heci_header = NULL; + struct heci_file_private *file_extension = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + + + if (!host_buffer_is_empty(device_object)) { + DBG("host buffer is not empty.\n"); + return ESUCCESS; + } + device_object->write_hang = -1; + *slots = count_empty_write_slots(device_object); + /* complete all waiting for write CB */ + DBG("complete all waiting for write CB.\n"); + if (device_object->write_waiting_list.status == ESUCCESS + && !list_empty(&device_object->write_waiting_list.heci_cb.cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object-> + write_waiting_list.heci_cb.cb_list, cb_list){ + file_extension = (struct heci_file_private *) kernel_priv_cb_pos->file_private; + file_extension->status = ESUCCESS; + list_del(&kernel_priv_cb_pos->cb_list); + if (HECI_WRITING == file_extension->writing_state + && kernel_priv_cb_pos->major_file_operations == HECI_WRITING + && file_extension != &device_object->legacy_file_extension) { + DBG("HECI WRITE COMPLETE\n"); + file_extension->writing_state = HECI_WRITE_COMPLETE; + list_add_tail(&kernel_priv_cb_pos->cb_list, + &complete_list->heci_cb. + cb_list); + } + if (file_extension == &device_object->legacy_file_extension) { + DBG("check legacy flow control\n"); + if (device_object-> legacy_flow_control_pending) { + if (((*slots) * sizeof(__u32)) >= (sizeof(struct heci_message_header) + + sizeof(struct hbm_flow_control))) { + *slots -= (sizeof(struct heci_message_header) + + sizeof(struct hbm_flow_control) + 3) / 4; + if (!heci_send_flow_control (device_object, + &device_object->legacy_file_extension)) { + DBG("legacy flow control failed\n"); + } else { + DBG("legacy flow control success\n"); + device_object->legacy_state = HECI_LEGACY_READING; + device_object->legacy_flow_control_pending = FALSE; + device_object->legacy_message_buffer_index = 0; + device_object->legacy_message_buffer_size = 0; + device_object->legacy_stall_timer = LEGACY_STALL_TIMER; + device_object->host_buffer_is_empty = + host_buffer_is_empty(device_object); + } + } else { + return -ECOMPLETE_MESSAGE; + } + } + } + + } + } + + if (device_object->stop && !device_object->wd_pending) { + device_object->wd_stoped = TRUE; + wake_up_interruptible(&device_object->wait_stop_wd); + return ESUCCESS; + } + + if (device_object->extra_write_index != 0) { + DBG("extra_write_index =%d\n", + device_object->extra_write_index); + heci_write_message(device_object, + (struct heci_message_header *) & + device_object->extra_message_buffer[0], + (unsigned char *) &device_object-> + extra_message_buffer[1], + (device_object->extra_write_index - + 1) * sizeof(__u32)); + *slots -= device_object->extra_write_index; + device_object->extra_write_index = 0; + } + if (device_object->heci_state == HECI_ENABLED){ + if (device_object->wd_pending + && flow_control_credentials(device_object, + &device_object->wd_file_extension)) { + if (!heci_send_wd(device_object)) + DBG("Wd send failed\n"); + else + flow_control_reduce(device_object, + &device_object-> + wd_file_extension); + device_object->wd_pending = 0; + + if (device_object->wd_timeout != 0) { + *slots -= + (sizeof(struct heci_message_header) + + HECI_START_WD_DATA_SIZE + 3) / 4; + device_object->wd_due_counter = 2; + } else { + *slots -= + (sizeof(struct heci_message_header) + + HECI_WD_PARAMS_SIZE + 3) / 4; + device_object->wd_due_counter = 0; + } + + } + } + if (device_object->stop) + return ~ENODEV; + + /* complete control write list CB */ + if (device_object->control_write_list.status == ESUCCESS) { + /* complete control write list CB */ + DBG("complete control write list CB\n "); + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object-> + control_write_list.heci_cb.cb_list, cb_list){ + file_extension = + (struct heci_file_private *) kernel_priv_cb_pos-> + file_private; + if (!file_extension) { + list_del(&kernel_priv_cb_pos->cb_list); + return -ENODEV; + } + switch (kernel_priv_cb_pos->major_file_operations) { + case HECI_CLOSE: + /* send disconnect message */ + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_message_header) + + sizeof(struct hbm_client_disconnect_request))) { + *slots -= (sizeof(struct heci_message_header) + + sizeof(struct hbm_client_disconnect_request) + 3) / 4; + if (!heci_disconnect(device_object, + file_extension)) { + file_extension->status = ESUCCESS; + kernel_priv_cb_pos->information = 0; + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &complete_list->heci_cb. + cb_list); + return -ECOMPLETE_MESSAGE; + } else { + file_extension->state = HECI_FILE_DISCONNECTING; + file_extension->status = ESUCCESS; + kernel_priv_cb_pos->information = 0; + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &device_object->control_read_list. + heci_cb.cb_list); + file_extension->timer_count = CONNECT_TIMEOUT; + } + } else { + /* return the cancel routine */ + return -ECORRUPTED_MESSAGE_HEADER; + } + break; + case HECI_READ: + /* send flow control message */ + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_message_header) + + sizeof(struct hbm_flow_control))) { + *slots -= (sizeof(struct heci_message_header) + + sizeof(struct hbm_flow_control) + 3) / 4; + if (!heci_send_flow_control(device_object, file_extension)) { + file_extension->status = -ENODEV; + kernel_priv_cb_pos->information = 0; + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &complete_list->heci_cb. + cb_list); + return -ENODEV; + + } else { + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &device_object->read_list. + heci_cb.cb_list); + } + } else { + /* return the cancel routine */ + list_del(&kernel_priv_cb_pos->cb_list); + return -ECORRUPTED_MESSAGE_HEADER; + } + break; + case HECI_IOCTL: + /* connect message */ + if (!other_client_is_connecting(device_object, file_extension)) { + continue; + } + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_message_header) + + sizeof(struct hbm_client_connect_request))) { + file_extension->state = HECI_FILE_CONNECTING; + *slots -= (sizeof(struct heci_message_header) + + sizeof(struct hbm_client_connect_request) + 3) / 4; + if (!heci_connect(device_object, file_extension)) { + file_extension->status = -ENODEV; + kernel_priv_cb_pos->information = 0; + list_del(&kernel_priv_cb_pos->cb_list); + return -ENODEV; + } else { + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &device_object->control_read_list. + heci_cb.cb_list); + file_extension->timer_count = CONNECT_TIMEOUT; + } + } else { + /* return the cancel routine */ + list_del(&kernel_priv_cb_pos->cb_list); + return -ECORRUPTED_MESSAGE_HEADER; + } + break; + + default: + BUG_ON(1); + } + + } + } + /* complete write list CB */ + if (device_object->write_list.status == ESUCCESS + && !list_empty(&device_object->write_list.heci_cb.cb_list)) { + DBG("complete write list CB \n"); + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object-> + write_list.heci_cb.cb_list, cb_list){ + file_extension = (struct heci_file_private *) kernel_priv_cb_pos->file_private; + + if ((file_extension != NULL) + && (file_extension != &device_object->legacy_file_extension)) { + if (!flow_control_credentials(device_object, + file_extension)) { + DBG("No flow control credentials for client %d, not sending\n", + file_extension->host_client_id); + continue; + } + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_message_header) + + (kernel_priv_cb_pos->request_buffer.size - kernel_priv_cb_pos->information))) { + heci_header = (struct heci_message_header *) & device_object->write_message_buffer[0]; + heci_header->host_address = file_extension->host_client_id; + heci_header->me_address = file_extension->me_client_id; + heci_header->length = ((kernel_priv_cb_pos->request_buffer.size) - + (kernel_priv_cb_pos->information)); + heci_header->message_complete = 1; + heci_header->reserved = 0; + DBG("kernel_priv_cb_pos->request_buffer.size =%d heci_header->message_complete= %d\n", + kernel_priv_cb_pos->request_buffer.size, + heci_header->message_complete); + DBG("kernel_priv_cb_pos->information =%lu\n", + kernel_priv_cb_pos->information); + DBG("heci_header->length =%d\n", + heci_header->length); + *slots -= (sizeof(struct heci_message_header) + heci_header->length + 3) / 4; + if (!heci_write_message (device_object, heci_header, + (unsigned char *) (kernel_priv_cb_pos-> request_buffer.data + kernel_priv_cb_pos->information), + heci_header->length)) { + file_extension->status = -ENODEV; + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &complete_list->heci_cb. + cb_list); + return -ENODEV; + } else { + flow_control_reduce + (device_object, file_extension); + file_extension->status = ESUCCESS; + kernel_priv_cb_pos->information += heci_header->length; + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, + &device_object->write_waiting_list. + heci_cb.cb_list); + } + } else if (*slots == ((device_object->host_hw_state & H_CBD) >> 24)) { /* buffer is still empty */ + heci_header = (struct heci_message_header *) & device_object->write_message_buffer[0]; + heci_header->host_address = file_extension->host_client_id; + heci_header->me_address = file_extension->me_client_id; + heci_header->length = (*slots * sizeof(__u32)) - sizeof(struct heci_message_header); + heci_header->message_complete = 0; + heci_header->reserved = 0; + + (*slots) -= (sizeof(struct heci_message_header) + heci_header->length + 3) / 4; + if (!heci_write_message(device_object, heci_header, + (unsigned char *) (kernel_priv_cb_pos->request_buffer. data + kernel_priv_cb_pos->information), + heci_header->length)) { + file_extension->status = -ENODEV; + list_del(&kernel_priv_cb_pos->cb_list); + list_add_tail(&kernel_priv_cb_pos->cb_list, &complete_list->heci_cb.cb_list); + return -ENODEV; + } else { + kernel_priv_cb_pos->information += heci_header->length; + DBG("kernel_priv_cb_pos->request_buffer.size =%d heci_header->message_complete= %d\n", + kernel_priv_cb_pos->request_buffer.size, + heci_header->message_complete); + DBG("kernel_priv_cb_pos->information =%lu\n", kernel_priv_cb_pos->information); + DBG("heci_header->length =%d\n", heci_header->length); + } + return -ECOMPLETE_MESSAGE; + } else { + return -ECORRUPTED_MESSAGE_HEADER; + } + } else if (file_extension == &device_object->legacy_file_extension) { /* LEGACY IOCTL */ + DBG("complete pthi write cb\n"); + if (!flow_control_credentials(device_object, file_extension)) { + DBG("No flow control credentials for pthi client %d, not sending\n", + file_extension->host_client_id); + continue; + } + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_message_header) + + device_object->legacy_message_buffer_size - device_object->legacy_message_buffer_index)) { + heci_header = (struct heci_message_header *) & device_object->write_message_buffer[0]; + heci_header->host_address = file_extension->host_client_id; + heci_header->me_address = file_extension->me_client_id; + heci_header->length = device_object->legacy_message_buffer_size - + device_object->legacy_message_buffer_index; + heci_header->message_complete = 1; + heci_header->reserved = 0; + + *slots -= (sizeof(struct heci_message_header) + heci_header->length + 3) / 4; + + if (!heci_write_message (device_object, heci_header, + (device_object->legacy_message_buffer + device_object->legacy_message_buffer_index), + heci_header->length)) { + device_object->legacy_state = HECI_LEGACY_IDLE; + file_extension->status = -ENODEV; + list_del(&kernel_priv_cb_pos->cb_list); + return -ENODEV; + } else { + flow_control_reduce (device_object, file_extension); + device_object->legacy_message_buffer_index += heci_header->length; + list_del(&kernel_priv_cb_pos->cb_list); + kernel_priv_cb_pos->information = device_object->legacy_message_buffer_index; + file_extension->status = ESUCCESS; + device_object->legacy_state = HECI_LEGACY_FLOW_CONTROL; + device_object->legacy_flow_control_pending = TRUE; + /* save legacy cb sent to pthi client */ + device_object->legacy_current_cb = kernel_priv_cb_pos; + list_add_tail(&kernel_priv_cb_pos->cb_list, + &device_object->write_waiting_list.heci_cb. cb_list); + + } + } else if (*slots == ((device_object->host_hw_state & H_CBD) >> 24)) { /* buffer is still empty */ + heci_header = (struct heci_message_header *) & device_object->write_message_buffer[0]; + heci_header->host_address = file_extension->host_client_id; + heci_header->me_address = file_extension->me_client_id; + heci_header->length = (*slots * sizeof(__u32)) - sizeof(struct heci_message_header); + heci_header->message_complete = 0; + heci_header->reserved = 0; + + *slots -= (sizeof(struct heci_message_header) + heci_header->length + 3) / 4; + + if (!heci_write_message (device_object, heci_header, (device_object->legacy_message_buffer + + device_object->legacy_message_buffer_index), heci_header->length)) { + file_extension->status = -ENODEV; + list_del(&kernel_priv_cb_pos->cb_list); + } else { + device_object->legacy_message_buffer_index += heci_header->length; + } + return -ECOMPLETE_MESSAGE; + } else { + return -ECORRUPTED_MESSAGE_HEADER;; + } + } + + } + + } + return ESUCCESS; +} + + +/** + * is_treat_specially_client - check if the message belong + * to the file extension . + * @file_extension -extension of the file object + * @connect_res -connect response bus message + * @device_object -Device object for our driver + * + * @return : + * TRUE if empty + * FALSE - otherwise. + */ +int is_treat_specially_client(struct heci_file_private * file_extension, + struct hbm_client_connect_response * + connect_res) +{ + int ret = FALSE; + if ((file_extension->host_client_id == connect_res->host_address) + && (file_extension->me_client_id == connect_res->me_address)) { + + if (connect_res->status == 0) { + DBG("client connect status = 0x%08x.\n", + connect_res->status); + file_extension->state = HECI_FILE_CONNECTED; + file_extension->status = ESUCCESS; + } else { + DBG("client connect status = 0x%08x.\n", + connect_res->status); + file_extension->state = HECI_FILE_DISCONNECTED; + file_extension->status = -ENODEV; + } + ret = TRUE; + } + DBG("client state = %d.\n", file_extension->state); + return ret; + +} + +/** + * heci_client_connect_response - connect response bh routine + * + * @device_object -Device object for our driver + * @connect_res -connect response bus message + * @complete_list - An instance of our list structure + * + * @return : + * none; + */ +void heci_client_connect_response(struct iamt_heci_device * device_object, + struct hbm_client_connect_response * + connect_res) +{ + + struct heci_file_private *file_extension = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + + /* if WD or legacy client treat specially */ + + if ((is_treat_specially_client(&(device_object->wd_file_extension), + connect_res)) + || (is_treat_specially_client(& + (device_object-> + legacy_file_extension), + connect_res))) { + return; + } + + if (device_object->control_read_list.status == ESUCCESS + && !list_empty(&device_object->control_read_list.heci_cb. + cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object->control_read_list.heci_cb.cb_list, cb_list){ + file_extension = + (struct heci_file_private *) kernel_priv_cb_pos-> + file_private; + if (!file_extension) { + list_del(&kernel_priv_cb_pos->cb_list); + return; + } + if (HECI_IOCTL == kernel_priv_cb_pos->major_file_operations) { + + if (is_treat_specially_client (file_extension, connect_res)) { + list_del(&kernel_priv_cb_pos->cb_list); + file_extension->status = ESUCCESS; + file_extension->timer_count = 0; + break; + } + } + } + } + return; +} + +/** + * heci_client_disconnect_response - disconnect response bh routine + * + * @device_object -Device object for our driver + * @disconnect_res -disconnect response bus message + * @complete_list - An instance of our list structure + * + * @return : + * none; + */ +void heci_client_disconnect_response(struct iamt_heci_device * device_object, + struct hbm_client_connect_response * + disconnect_res) +{ + struct heci_file_private *file_extension = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + if (device_object->control_read_list.status == ESUCCESS + && !list_empty(&device_object->control_read_list.heci_cb. + cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object->control_read_list.heci_cb.cb_list, cb_list){ + file_extension = + (struct heci_file_private *) kernel_priv_cb_pos-> + file_private; + + if (!file_extension) { + list_del(&kernel_priv_cb_pos->cb_list); + return; + } + + DBG("list_for_each_entry_safe in control_read_list.\n"); + if ((file_extension->host_client_id == disconnect_res->host_address) + && (file_extension->me_client_id == disconnect_res->me_address)) { + list_del(&kernel_priv_cb_pos->cb_list); + if (disconnect_res->status == 0) + file_extension->state = HECI_FILE_DISCONNECTED; + file_extension->status = ESUCCESS; + file_extension->timer_count = 0; + break; + } + } + } + return; +} + +/** + * heci_client_flow_control_response - flow control response bh routine + * + * @device_object -Device object for our driver + * @flow_control -flow control response bus message + * + * @return : + * none; + */ +void heci_client_flow_control_response(struct iamt_heci_device * device_object, + struct hbm_flow_control * flow_control) +{ + struct heci_file_private *file_extension_pos = NULL; + struct heci_file_private *file_extension_next = NULL; + int i; + if (flow_control->host_address == 0) { /* single receive buffer */ + for (i = 0; i < device_object->num_heci_me_clients; i++) { + if (flow_control->me_address == + device_object->me_clients[i].client_id) { + if (device_object->me_clients[i].properteis.single_receive_buffer != 0) { + device_object->me_clients[i]. + flow_control_credentials++; + DBG("received flow control message for ME client %d (single receive buffer).\n", + flow_control->me_address); + DBG("flow control credentials=%d.\n", + device_object->me_clients[i].flow_control_credentials); + } else { + BUG_ON(1); /* error in flow control */ + } + } + } + } else { /* normal connection */ + list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) { + DBG("list_for_each_entry_safe in file_list\n"); + + DBG("file_extension of host client %d ME client %d.\n", + file_extension_pos->host_client_id, + file_extension_pos->me_client_id); + DBG("flow control message for host client %d ME client %d.\n", + flow_control->host_address, + flow_control->me_address); + if ((file_extension_pos->host_client_id == flow_control->host_address) + && (file_extension_pos->me_client_id == flow_control->me_address)) { + DBG("received flow control message for host client %d ME client %d.\n", + flow_control->host_address, + flow_control->me_address); + file_extension_pos->flow_control_credentials++; + DBG("flow control credentials=%d.\n", + file_extension_pos->flow_control_credentials); + break; + } + } + } + return; +} + +/** + * heci_client_disconnect_request - disconnect request bh routine + * + * @device_object -Device object for our driver + * @disconnect_req -disconnect request bus message + * + * @return : + * none; + */ +void heci_client_disconnect_request(struct iamt_heci_device * device_object, + struct hbm_client_disconnect_request * + disconnect_req) +{ + struct heci_message_header *heci_header; + struct hbm_client_connect_response *disconnect_res; + struct heci_file_private *file_extension_pos = NULL; + struct heci_file_private *file_extension_next = NULL; + + list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) { + if ((file_extension_pos->host_client_id == disconnect_req->host_address) + && (file_extension_pos->me_client_id == disconnect_req->me_address)) { + DBG("received disconnect request for host client %d ME client %d.\n", + disconnect_req->host_address, + disconnect_req->me_address); + file_extension_pos->state = HECI_FILE_DISCONNECTED; + file_extension_pos->timer_count = 0; + if (file_extension_pos == &device_object->wd_file_extension) { + device_object->wd_due_counter = 0; + device_object->wd_pending = FALSE; + } else if (file_extension_pos == + &device_object->legacy_file_extension) { + device_object->legacy_timer = 0; + } + + /* prepare disconnect response */ + heci_header = (struct heci_message_header *) & device_object->extra_message_buffer[0]; + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_client_connect_response); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + disconnect_res = (struct hbm_client_connect_response *) & + device_object->extra_message_buffer[1]; + disconnect_res->host_address = + file_extension_pos->host_client_id; + disconnect_res->me_address = file_extension_pos->me_client_id; + *(__u8 *) (&disconnect_res->command) = CLIENT_DISCONNECT_RES_CMD; + disconnect_res->status = 0; + device_object->extra_write_index = 2; + break; + } + } + return; +} + + +/** + * heci_timer - timer function . + * @data: pointer to the device structure + * + * NOTE: This function is called by timer interrupt work + * @return : + * none; + */ +void heci_wd_timer(unsigned long data) +{ + struct iamt_heci_device *device = (struct iamt_heci_device *) data; + DBG("send watchdog.\n"); + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED) { + mod_timer(&device->wd_timer, round_jiffies(jiffies + 2 * HZ)); + spin_unlock_bh(&device->device_lock); + return; + } + if (device->wd_file_extension.state != HECI_FILE_CONNECTED) { + mod_timer(&device->wd_timer, round_jiffies(jiffies + 2 * HZ)); + spin_unlock_bh(&device->device_lock); + return; + } + /*** Watchdog ***/ + if (device->wd_due_counter != 0 && FALSE == device->wd_bypass) { + if (--device->wd_due_counter == 0) { + if (device->host_buffer_is_empty && + flow_control_credentials(device, + &device-> + wd_file_extension)) { + device->host_buffer_is_empty = FALSE; + + if (!heci_send_wd(device)) + DBG("Wd send failed\n"); + else + flow_control_reduce(device, + &device-> + wd_file_extension); + if (device->wd_timeout != 0) + device->wd_due_counter = 2; + else + device->wd_due_counter = 0; + } else { + device->wd_pending = TRUE; + } + } + } + if (device->legacy_stall_timer != 0) { + if (--device->legacy_stall_timer == 0) { + DBG("Reseting because of hang to PTHI\n"); + heci_reset(device, TRUE); + device->legacy_message_buffer_size = 0; + device->legacy_message_buffer_index = 0; + device->legacy_canceled = FALSE; + device->legacy_ioctl = TRUE; + device->legacy_state = HECI_LEGACY_IDLE; + device->legacy_timer = 0; + spin_unlock_bh(&device->device_lock); + + if (device->legacy_current_cb) { + kfree(device->legacy_current_cb->request_buffer.data); + device->legacy_current_cb->request_buffer.data = NULL; + kfree(device->legacy_current_cb->response_buffer.data); + device->legacy_current_cb->response_buffer.data = NULL; + kfree(device->legacy_current_cb); + } + spin_lock_bh(&device->device_lock); + device->legacy_file_object = NULL; + device->legacy_current_cb = NULL; + run_next_legacy_cmd(device); + } + } + mod_timer(&device->wd_timer, round_jiffies(jiffies + 2 * HZ)); + spin_unlock_bh(&device->device_lock); + return; +} --- linux-2.6.27.orig/ubuntu/heci/BOM +++ linux-2.6.27/ubuntu/heci/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=193428 +Current Version: 3.2.0.24 --- linux-2.6.27.orig/ubuntu/heci/heci_init.c +++ linux-2.6.27/ubuntu/heci/heci_init.c @@ -0,0 +1,1121 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcompat.h" +#include "heci_data_structures.h" +#include "heci_interface.h" +#include "heci.h" + + +const __u8 watch_dog_data[] = + { 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; +const __u8 start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; +const __u8 stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; +const __u8 heci_wd_state_independence_msg[2][4] = { + {0x05, 0x02, 0x51, 0x10}, + {0x05, 0x02, 0x52, 0x10} }; +const struct guid heci_asf_guid = + { 0x75B30CD6, 0xA29E, 0x4AF7, {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, + 0xC8, 0xA6} }; +const struct guid heci_wd_guid = + { 0x05B79A6F, 0x4628, 0x4D7F, {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, + 0x32, 0xAB} }; +const struct guid heci_pthi_guid = + { 0x12f80028, 0xb4b7, 0x4b2d, {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, + 0x81, 0x4c} }; + + +/** + * heci init function prototypes + */ +int host_start_message(struct iamt_heci_device * device_object); +int host_enum_clients_message(struct iamt_heci_device * device_object); +int allocate_me_clents_storage(struct iamt_heci_device * device_object); +void heci_disable(struct iamt_heci_device * device_object); +void host_init_wd(struct iamt_heci_device * device_object); +void host_init_legacy(struct iamt_heci_device * device_object); + + +/** + * heci_initialize_list - Sets up a queue list. + * + * @list - An instance of our list structure + * @device_object -Device object for our driver + * + * @return : + * none; + */ +void heci_initialize_list(struct io_heci_list *list, + struct iamt_heci_device * device_object) +{ + /* initialize our queue list */ + INIT_LIST_HEAD(&list->heci_cb.cb_list); + list->status = ESUCCESS; + list->device_extension = device_object; + return; +} + +/** + * heci_flush_queues - flush our queues list belong to file_extension. + * + * @device_object -Device object for our driver + * + * @return : + * none; + */ +void heci_flush_queues(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + int i; + if (!device_object || !file_extension) + return; + /* flush our queue list belong to file_extension */ + for (i = 0; i < NUMBER_OF_LISTS; i++) { + DBG("remove list etnry belong to file_extension\n"); + heci_flush_list(device_object->io_list_array[i], + file_extension); + } + +} + + +/** + * heci_flush_list - remove list etnry belong to file_extension. + * + * @list - An instance of our list structure + * @file_extension -extension of the file object + + * @return : + * none; + */ +void heci_flush_list(struct io_heci_list *list, + struct heci_file_private * file_extension) +{ + struct heci_file_private *file_extension_temp = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + + if (!list || !file_extension) + return; + if (list->status == ESUCCESS + && !list_empty(&list->heci_cb.cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &list->heci_cb.cb_list, cb_list){ + + if (kernel_priv_cb_pos) { + file_extension_temp = + (struct heci_file_private *) + kernel_priv_cb_pos->file_private; + } + if (file_extension_temp) { + if ((file_extension->host_client_id == file_extension_temp-> host_client_id) + && (file_extension->me_client_id == file_extension_temp-> me_client_id)) + list_del(&kernel_priv_cb_pos->cb_list); + } + + } + } + return; +} + +/** + * init_heci_device - allocates and initializes the heci device structure + * @pdev: The pci device structure + * + * @return : + * The heci_device_device pointer on success, NULL on failure. + */ +struct iamt_heci_device *init_heci_device(struct pci_dev * pdev) +{ + int i; + struct iamt_heci_device *device; + device = kmalloc(sizeof(struct iamt_heci_device), GFP_KERNEL); + if (!device) { + return NULL; + } + + /* setup our list array */ + device->io_list_array[0] = &device->read_list; + device->io_list_array[1] = &device->write_list; + device->io_list_array[2] = &device->write_waiting_list; + device->io_list_array[3] = &device->control_write_list; + device->io_list_array[4] = &device->control_read_list; + device->io_list_array[5] = &device->pthi_cmd_list; + device->io_list_array[6] = &device->pthi_read_complete_list; + INIT_LIST_HEAD(&device->file_list); + INIT_LIST_HEAD(&device->wd_file_extension.link); + INIT_LIST_HEAD(&device->legacy_file_extension.link); + spin_lock_init(&device->device_lock); + init_waitqueue_head(&device->wait_received_message); + init_waitqueue_head(&device->wait_stop_wd); + device->open_handle_count = 0; + device->num_heci_me_clients = 0; + device->mem_base = 0; + device->mem_length = 0; + device->extra_write_index = 0; + device->read_message_header = 0; + device->mem_addr = NULL; + device->asf_mode = FALSE; + device->need_reset = FALSE; + device->received_message = FALSE; + device->heci_state = HECI_INITIALIZING; + + device->num_heci_me_clients = 0; + device->legacy_current_cb = NULL; + device->legacy_file_object = NULL; + device->legacy_canceled = FALSE; + device->legacy_flow_control_pending = FALSE; + device->legacy_state = HECI_LEGACY_IDLE; + device->legacy_message_buffer_index = 0; + device->wd_pending = FALSE; + device->wd_stoped = FALSE; + device->wd_bypass = FALSE; + + device->me_clients = NULL; + /* init work for schedule work */ + INIT_WORK(&device->work, NULL); + for (i = 0; i < NUMBER_OF_LISTS; i++) + heci_initialize_list(device->io_list_array[i], device); + device->pdev = pdev; + return device; +} + +/** + * heci_hw_init - init host and fw to start work. + * + * @device_object -Device object for our driver + * + *@return: + * 0 on success. + * negative on failure + */ +int heci_hw_init(struct iamt_heci_device * device_object) +{ + int err = 0; + device_object->host_hw_state = + read_heci_register(device_object, H_CSR); + device_object->me_hw_state = + read_heci_register(device_object, ME_CSR_HA); + DBG("host_hw_state = 0x%08x, mestate = 0x%08x.\n", + device_object->host_hw_state, device_object->me_hw_state); + + if ((device_object->host_hw_state & H_IS) == H_IS) { + /* acknowledge interrupt and stop interupts */ + write_heci_register(device_object, H_CSR, + device_object->host_hw_state); + } + device_object->received_message = FALSE; + DBG("reset in start the heci device.\n"); + + heci_reset(device_object, TRUE); + + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + device_object->host_hw_state, device_object->me_hw_state); + + /* wait for ME to turn on ME_RDY */ + if (!device_object->received_message) { + err = + wait_event_interruptible_timeout(device_object-> + wait_received_message, + (device_object-> + received_message), + HECI_INTEROP_TIMEOUT); + } + + if (!err && !device_object->received_message) { + device_object->heci_state = HECI_DISABLED; + DBG("wait_event_interruptible_timeout failed on wait for ME to turn on ME_RDY.\n"); + return -ENODEV; + } else { + if (!(((device_object->host_hw_state & H_RDY) == H_RDY) + && ((device_object->me_hw_state & ME_RDY_HRA) == + ME_RDY_HRA))) { + device_object->heci_state = HECI_DISABLED; + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + device_object->host_hw_state, + device_object->me_hw_state); + + if (!(device_object->host_hw_state & H_RDY) != H_RDY) + DBG("host turn off H_RDY.\n"); + if (!(device_object->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + DBG("ME turn off ME_RDY.\n"); + HECI_ERR("link layer initialization failed.\n"); + return -ENODEV; + } + } + device_object->received_message = FALSE; + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + device_object->host_hw_state, device_object->me_hw_state); + DBG("ME turn on ME_RDY and host turn on H_RDY.\n"); + HECI_INFO("link layer has been established.\n"); + return ESUCCESS; +} + +/** + * heci_reset - reset host and fw. + * + * @device_object -Device object for our driver + * @interrupts - if interrupt should be enable after reset. + * + * @return: + * none; + */ +void heci_reset(struct iamt_heci_device * device_object, int interrupts) +{ + struct heci_file_private *file_extension_pos = NULL; + struct heci_file_private *file_extension_next = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + int unexpected = 0; + + if (device_object->heci_state == HECI_RECOVERING_FROM_RESET) { + device_object->need_reset = TRUE; + return; + } + + if (device_object->heci_state != HECI_INITIALIZING && + device_object->heci_state != HECI_DISABLED && + device_object->heci_state != HECI_POWER_DOWN && + device_object->heci_state != HECI_POWER_UP) + unexpected = 1; + + device_object->host_hw_state = + read_heci_register(device_object, H_CSR); + + DBG("before reset host_hw_state = 0x%08x.\n", + device_object->host_hw_state); + + device_object->host_hw_state |= (H_RST | H_IG); + + if (interrupts) + device_object->host_hw_state |= (H_IE); + else + device_object->host_hw_state &= ~(H_IE); + + write_heci_register(device_object, H_CSR, + device_object->host_hw_state); + + device_object->host_hw_state = + read_heci_register(device_object, H_CSR); + BUG_ON((device_object->host_hw_state & H_RST) != H_RST); + BUG_ON((device_object->host_hw_state & H_RDY) != 0); + + device_object->host_hw_state &= ~H_RST; + device_object->host_hw_state |= H_IG; + + write_heci_register(device_object, H_CSR, + device_object->host_hw_state); + + DBG("currently saved host_hw_state = 0x%08x.\n", + device_object->host_hw_state); + + device_object->need_reset = FALSE; + + if (device_object->heci_state != HECI_INITIALIZING) { + if (device_object->heci_state != HECI_DISABLED && + device_object->heci_state != HECI_POWER_DOWN) { + device_object->heci_state = HECI_RESETING; + } + list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) { + file_extension_pos->state =HECI_FILE_DISCONNECTED; + file_extension_pos->flow_control_credentials =0; + file_extension_pos->read_cb = NULL; + file_extension_pos->timer_count = 0; + } + /* remove entry if already in list */ + DBG("list del legacy and wd file list.\n"); + heci_remove_client_from_file_list(device_object, + device_object-> + wd_file_extension. + host_client_id); + + heci_remove_client_from_file_list(device_object, + device_object-> + legacy_file_extension. + host_client_id); + /* reset legacy parameters. */ + device_object->legacy_current_cb = NULL; + device_object->legacy_message_buffer_size = 0; + device_object->legacy_message_buffer_index = 0; + device_object->legacy_canceled = FALSE; + device_object->legacy_file_extension.file = NULL; + device_object->legacy_ioctl = FALSE; + device_object->legacy_state = HECI_LEGACY_IDLE; + device_object->legacy_timer = 0; + device_object->wd_due_counter = 0; + device_object->extra_write_index = 0; + device_object->wd_pending = FALSE; + } + + device_object->num_heci_me_clients = 0; + device_object->read_message_header = 0; + device_object->stop = FALSE; + device_object->wd_pending = 0; + + /* update the state of the registers after reset */ + device_object->host_hw_state = + read_heci_register(device_object, H_CSR); + device_object->me_hw_state = + read_heci_register(device_object, ME_CSR_HA); + + DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + device_object->host_hw_state, device_object->me_hw_state); + + if (unexpected) + HECI_ERR("unexpected heci reset.\n"); + //Wake up all readings so they can be interrupted + list_for_each_entry_safe(file_extension_pos,file_extension_next, &device_object->file_list,link) { + if (&file_extension_pos->rx_wait && + waitqueue_active (&file_extension_pos->rx_wait)) { + HECI_INFO("Waking up client!\n"); + wake_up_interruptible(&file_extension_pos->rx_wait); + } + } + // remove all waiting requests + if (device_object->write_list.status == ESUCCESS && !list_empty(&device_object->write_list.heci_cb.cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object->write_list.heci_cb.cb_list, cb_list){ + if (kernel_priv_cb_pos) { + list_del(&kernel_priv_cb_pos->cb_list); + kfree(kernel_priv_cb_pos->request_buffer.data); + kernel_priv_cb_pos->request_buffer.data = NULL; + kfree(kernel_priv_cb_pos->response_buffer.data); + kernel_priv_cb_pos->response_buffer.data = NULL; + kfree(kernel_priv_cb_pos); + kernel_priv_cb_pos = NULL; + } + } + } +} + +/** + * heci_disable - reseting in disable routine. + * + * @device_object -Device object for our driver + * + * @return: + * none; + */ +void heci_disable(struct iamt_heci_device * device_object) +{ + if (device_object->heci_state != HECI_INITIALIZING) + HECI_ERR("driver stop request heci state is disable.\n"); + device_object->heci_state = HECI_DISABLED; +} + +/** + * heci_initialize_clients - routine. + * + * @device_object -Device object for our driver + * + * @return: + * none; + */ +int heci_initialize_clients(void *data) +{ + + int status; + struct iamt_heci_device *device_object = (struct iamt_heci_device *) data; + DBG("link is established start sending messages.\n"); + /* link is established start sending messages. */ + status = host_start_message(device_object); + if (status) { + DBG("start sending messages failed.\n"); + return -ENODEV; + } + /* enumerate clients */ + + status = host_enum_clients_message(device_object); + if (status) { + DBG("enum clients failed.\n"); + return -ENODEV; + } + /* allocate storage for ME clients representation */ + status = allocate_me_clents_storage(device_object); + if (status) { + DBG("allocate clients failed.\n"); + return -ENODEV; + } + /*heci initialization wd */ + host_init_wd(device_object); + /*heci initialization legacy client */ + host_init_legacy(device_object); + if (device_object->need_reset) { + device_object->need_reset = FALSE; + device_object->heci_state = HECI_DISABLED; + return -ENODEV; + } + + memset(device_object->heci_host_clients, 0, + sizeof(device_object->heci_host_clients)); + device_object->open_handle_count = 0; + device_object->heci_host_clients[0] |= 7; + device_object->current_host_client_id = 3; + device_object->heci_state = HECI_ENABLED; + DBG("initialization heci clients successful.\n"); + return ESUCCESS; +} + +/** + * host_start_message - heci host send start message. + * + * @device_object - Device object for our driver + * + * @return : + * 0 on success, + * negative on failure. + */ +int host_start_message(struct iamt_heci_device * device_object) +{ + long timeout = 60; /* 60 second */ + + struct heci_message_header *heci_header; + struct hbm_host_version_request *host_start_req; + struct hbm_host_stop_request *host_stop_req; + int err = 0; + /* host start message */ + msleep(100); + heci_header = + (struct heci_message_header *) & device_object-> + write_message_buffer[0]; + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_host_version_request); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + host_start_req = + (struct hbm_host_version_request *) & device_object-> + write_message_buffer[1]; + memset(host_start_req, 0, sizeof(host_start_req)); + host_start_req->command.command = HOST_START_REQ_CMD; + host_start_req->reserved = 0; + host_start_req->host_version.major_version = HBM_MAJOR_VERSION; + host_start_req->host_version.minor_version = HBM_MINOR_VERSION; + device_object->received_message = FALSE; + if (!heci_write_message(device_object, heci_header, + (unsigned char *) (host_start_req), + heci_header->length)) { + device_object->heci_state = HECI_DISABLED; + DBG("send version to fw fail.\n"); + return -ENODEV; + } + DBG("call wait_event_interruptible_timeout for response message. \n"); + /* wait for response */ + err = + wait_event_interruptible_timeout(device_object-> + wait_received_message, + (device_object-> + received_message), + timeout * HZ); + if (!err && !device_object->received_message) { + device_object->heci_state = HECI_DISABLED; + DBG("wait_event_interruptible_timeout failed on host start response message. \n"); + return -ENODEV; + } + device_object->received_message = FALSE; + DBG("wait_event_interruptible_timeout successful on host start response message. \n"); + if ((device_object->version.major_version != HBM_MAJOR_VERSION) || + (device_object->version.minor_version != HBM_MINOR_VERSION)) { + /* send stop message */ + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_host_stop_request); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + host_stop_req = + (struct hbm_host_stop_request *) & device_object-> + write_message_buffer[1]; + + memset(host_stop_req, 0, sizeof(host_stop_req)); + host_stop_req->command.command = HOST_STOP_REQ_CMD; + host_stop_req->reason = DRIVER_STOP_REQUEST; + memset(host_stop_req->reserved, 0, + sizeof(host_stop_req->reserved)); + heci_write_message(device_object, heci_header, + (unsigned char *) (host_stop_req), + heci_header->length); + DBG("version mismatch.\n"); + return -ENODEV; + } + + return ESUCCESS; +} + +/** + * host_enum_clients_message - host send enumeration client request message. + * + * @device_object - Device object for our driver + * + * @return : + * 0 on success, + * negative on failure. + */ +int host_enum_clients_message(struct iamt_heci_device * device_object) +{ + long timeout = 5; /*5 second */ + + struct heci_message_header *heci_header; + struct hbm_host_enumeration_request *host_enum_req; + int err = 0; + __u8 i, j; + heci_header = + (struct heci_message_header *) & device_object-> + write_message_buffer[0]; + /* enumerate clients */ + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_host_enumeration_request); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + host_enum_req = + (struct hbm_host_enumeration_request *) & device_object-> + write_message_buffer[1]; + memset(host_enum_req, 0, sizeof(host_enum_req)); + host_enum_req->command.command = HOST_ENUM_REQ_CMD; + memset(host_enum_req->reserved, 0, + sizeof(host_enum_req->reserved)); + if (!heci_write_message(device_object, heci_header, + (unsigned char *) (host_enum_req), + heci_header->length)) { + device_object->heci_state = HECI_DISABLED; + DBG("send enumeration request fail.\n"); + return -ENODEV; + } + /* wait for response */ + device_object->received_message = FALSE; + err = + wait_event_interruptible_timeout(device_object-> + wait_received_message, + (device_object-> + received_message), + timeout * HZ); + if (!err && !device_object->received_message) { + + device_object->heci_state = HECI_DISABLED; + + DBG("wait_event_interruptible_timeout failed on enumeration cients response message. \n"); + return -ENODEV; + } + device_object->received_message = FALSE; + /* count how many ME clients we have */ + for (i = 0; i < sizeof(device_object->heci_me_clients); i++) + for (j = 0; j < 8; j++) + if ((device_object->heci_me_clients[i] & (1 << j)) != 0) + device_object->num_heci_me_clients++; + return ESUCCESS; +} + +/** + * allocate_me_clents_storage - allocate storage for me clients + * + * @device_object - Device object for our driver + * + * @return : + * 0 on success, + * negative on failure. + */ +int allocate_me_clents_storage(struct iamt_heci_device * device_object) +{ + long timeout = 10; /*10 second */ + struct heci_message_header *heci_header; + struct hbm_host_client_properties_request *host_cli_req; + __u8 client_num, i, j; + int err; + heci_header = + (struct heci_message_header *) & device_object-> + write_message_buffer[0]; + /* allocate storage for ME clients representation */ + if (device_object->num_heci_me_clients > 0) { + kfree(device_object->me_clients); + device_object->me_clients = + kcalloc(device_object->num_heci_me_clients, + sizeof(struct heci_me_client), + GFP_KERNEL); + if (!device_object->me_clients) { + device_object->heci_state = HECI_DISABLED; + DBG("allocate me clents memory failed.\n"); + return -ENOMEM; + } + + client_num = 0; + + for (i = 0; i < sizeof(device_object->heci_me_clients); + i++) { + for (j = 0; j < 8; j++) { + if ((device_object->heci_me_clients[i] & (1 << j)) != 0) { + device_object->me_clients[client_num].client_id = (i * 8) + j; + device_object->me_clients[client_num].flow_control_credentials = 0; + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_host_client_properties_request); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + host_cli_req = (struct hbm_host_client_properties_request *)& device_object->write_message_buffer[1]; + memset(host_cli_req, 0, sizeof(struct hbm_host_client_properties_request)); + host_cli_req->command.command = HOST_CLIENT_PROPERTEIS_REQ_CMD; + host_cli_req->address = device_object->me_clients[client_num].client_id; + memset(host_cli_req->reserved, 0, sizeof(host_cli_req->reserved)); + if (!heci_write_message(device_object, heci_header, + (unsigned char *) (host_cli_req), heci_header->length)) { + DBG("send client properteis request fail.\n"); + device_object->heci_state = HECI_DISABLED; + kfree(device_object->me_clients); + return -ENODEV; + } + /* wait for response */ + device_object->received_message = FALSE; + err = wait_event_interruptible_timeout (device_object->wait_received_message, + (device_object->received_message), timeout * HZ); + if (!err && !device_object->received_message) { + DBG("wait_event_interruptible_timeout failed on client properteis response message.\n"); + device_object->heci_state = HECI_DISABLED; + kfree(device_object->me_clients); + return -ENODEV; + } + device_object->received_message = FALSE; + client_num++; + } + } + } + } + return ESUCCESS; +} + +/** + * host_init_wd - heci initialization wd. + * + * @device_object - Device object for our driver + * + * @return : + * none; + */ +void host_init_wd(struct iamt_heci_device * device_object) +{ + long timeout = 15; /*15 second */ + __u8 i; + int err = 0; + /*look for WD client and connect to it */ + spin_lock_init(&device_object->wd_file_extension.file_lock); + init_waitqueue_head(&device_object->wd_file_extension.wait); + device_object->wd_file_extension.file = NULL; + device_object->wd_file_extension.state = HECI_FILE_DISCONNECTED; + device_object->wd_timeout = 0; + device_object->asf_mode = FALSE; + /*find ME ASF client - otherwise assume AMT mode */ + DBG("find ME ASF client - otherwise assume AMT mode.\n"); + for (i = 0; i < device_object->num_heci_me_clients; i++) { + if (memcmp(&heci_asf_guid, + &device_object->me_clients[i].properteis. + protocol_name, sizeof(struct guid))==0) { + device_object->asf_mode = TRUE; + DBG("found ME ASF client.\n"); + } + } + if (device_object->asf_mode) { + memcpy(device_object->wd_data, + stop_wd_params, HECI_WD_PARAMS_SIZE); + + } + else { /* AMT mode */ + + DBG("assume AMT mode.\n"); + device_object->wd_timeout = AMT_WD_VALUE; + DBG("device_object->wd_timeout=%d.\n", + device_object->wd_timeout); + memcpy(device_object->wd_data, start_wd_params, HECI_WD_PARAMS_SIZE); + memcpy(device_object->wd_data + HECI_WD_PARAMS_SIZE, + &device_object->wd_timeout, sizeof(__u16)); + } + + /* find ME WD client */ + for (i = 0; i < device_object->num_heci_me_clients; i++) { + if (0 == memcmp(&heci_wd_guid, &device_object->me_clients[i].properteis.protocol_name, sizeof(struct guid))) { + + spin_lock_bh(&device_object->device_lock); + device_object->wd_file_extension.me_client_id = + device_object->me_clients[i].client_id; + device_object->wd_file_extension.state = + HECI_FILE_CONNECTING; + + device_object->wd_file_extension.host_client_id = + HECI_WD_HOST_CLIENT_ID; + + device_object->wd_file_extension. + flow_control_credentials = 0; + device_object->wd_file_extension.timer_count = 0; + list_add_tail(&device_object->wd_file_extension. + link, &device_object->file_list); + spin_unlock_bh(&device_object->device_lock); + break; + } + } + DBG("check wd_file_ext\n"); + if (HECI_FILE_CONNECTING == device_object->wd_file_extension.state) { + if (heci_connect(device_object, + &device_object->wd_file_extension)) { + + err = + wait_event_timeout + (device_object->wait_received_message, + (HECI_FILE_CONNECTED == device_object->wd_file_extension.state ||HECI_FILE_DISCONNECTED == device_object->wd_file_extension.state), + timeout * HZ); + if (HECI_FILE_CONNECTED == device_object->wd_file_extension.state) { + DBG("device_object->wd_timeout=%d.\n", + device_object->wd_timeout); + if (device_object->wd_timeout != 0) + device_object->wd_due_counter = 1; + else + device_object->wd_due_counter = 0; + DBG("successfully to connect to WD client.\n"); + } else { + + heci_remove_client_from_file_list + (device_object, + device_object->wd_file_extension. + host_client_id); + if (HECI_FILE_CONNECTED != + device_object->wd_file_extension.state) + DBG("wrong status received for WD client.\n"); + if (!err) + DBG("wait_event_interruptible_timeout failed on client connect message fw response message err=%08x\n", err); + DBG("failed to connect to WD client.\n"); + device_object->wd_file_extension.state = + HECI_FILE_DISCONNECTED; + } + } else { + DBG("failed to call heci_connect for wd_file_extension.\n"); + heci_remove_client_from_file_list(device_object, + device_object-> + wd_file_extension. + host_client_id); + device_object->wd_file_extension.state = + HECI_FILE_DISCONNECTED; + } + } else { + DBG("failed to find WD client.\n"); + } + + device_object->wd_timer.function = &heci_wd_timer; + device_object->wd_timer.data = (unsigned long) device_object; + return; +} + + +/** + * host_init_legacy - heci initialization legacy client. + * + * @device_object - Device object for our driver + * + * @return : + * none; + */ +void host_init_legacy(struct iamt_heci_device * device_object) +{ + long timeout = 15; /*15 second */ + __u8 i; + int err; + + + spin_lock_init(&device_object->legacy_file_extension.file_lock); + init_waitqueue_head(&device_object->legacy_file_extension.wait); + spin_lock_init(&device_object->legacy_file_extension.read_io_lock); + spin_lock_init(&device_object->legacy_file_extension. + write_io_lock); + init_waitqueue_head(&device_object->legacy_file_extension.rx_wait); + init_waitqueue_head(&device_object->legacy_file_extension.tx_wait); + device_object->legacy_file_extension.reading_state = HECI_IDLE; + device_object->legacy_file_extension.writing_state = HECI_IDLE; + device_object->legacy_file_extension.read_pending = FALSE; + device_object->legacy_file_extension.flow_control_credentials = 0; + device_object->legacy_file_extension.read_cb = NULL; + /* look for legacy client and connect to it */ + device_object->legacy_file_extension.file = NULL; + device_object->legacy_file_extension.state = + HECI_FILE_DISCONNECTED; + + /* find ME PTHI client */ + for (i = 0; i < device_object->num_heci_me_clients; i++) { + if (0 == memcmp(&heci_pthi_guid, &device_object->me_clients[i].properteis. protocol_name, sizeof(struct guid))) { + spin_lock_bh(&device_object->device_lock); + device_object->legacy_file_extension.me_client_id = + device_object->me_clients[i].client_id; + device_object->legacy_file_extension.state = + HECI_FILE_CONNECTING; + device_object->legacy_file_extension. + host_client_id = HECI_LEGACY_HOST_CLIENT_ID; + device_object->legacy_file_extension. + flow_control_credentials = 0; + device_object->legacy_file_extension.timer_count = 0; + list_add_tail(&device_object-> + legacy_file_extension.link, + &device_object->file_list); + spin_unlock_bh(&device_object->device_lock); + break; + } + } + if (device_object->asf_mode){ + device_object->legacy_file_extension.state = + HECI_FILE_DISCONNECTED; + heci_remove_client_from_file_list(device_object, + device_object-> + legacy_file_extension. + host_client_id); + return; + + } + if (device_object->legacy_file_extension.state == HECI_FILE_CONNECTING) { + BUG_ON(device_object->me_clients[i].properteis.max_message_length != LEGACY_MTU); + + if (device_object->me_clients[i].properteis.max_message_length < LEGACY_MTU) { + device_object->legacy_file_extension.state = + HECI_FILE_DISCONNECTED; + DBG("legacy client buffer too small.\n"); + } else { + if (heci_connect(device_object, &device_object-> legacy_file_extension)) { + err = wait_event_timeout (device_object->wait_received_message, + (device_object->legacy_file_extension.state == HECI_FILE_CONNECTED || + device_object->legacy_file_extension.state == HECI_FILE_DISCONNECTED), timeout * HZ); + if ((device_object->legacy_file_extension.state != HECI_FILE_CONNECTED)) { + heci_remove_client_from_file_list + (device_object, + device_object-> + legacy_file_extension. + host_client_id); + DBG("failed to connect to legacy client.\n"); + device_object-> + legacy_file_extension.state = + HECI_FILE_DISCONNECTED; + } else { + DBG("successfully to connect to legacy client.\n"); + device_object->legacy_state = + HECI_LEGACY_IDLE; + } + } else { + DBG("failed to call heci_connect for legacy_file_extension.\n"); + heci_remove_client_from_file_list + (device_object, + device_object->legacy_file_extension. + host_client_id); + device_object->legacy_file_extension. + state = HECI_FILE_DISCONNECTED; + } + } + } else { + if (!device_object->asf_mode) + DBG("failed to find legacy client.\n"); + } + return; +} + +/** + * alloc_priv - allocates a private file structure and set it up. + * @file: the file structure + * + * @return : + * The allocated file or NULL on failure + */ +struct heci_file_private *alloc_priv(struct file * file) +{ + struct heci_file_private *priv; + + priv = kmalloc(sizeof(struct heci_file_private), GFP_KERNEL); + if (!priv) + return NULL; + + spin_lock_init(&priv->file_lock); + spin_lock_init(&priv->read_io_lock); + spin_lock_init(&priv->write_io_lock); + init_waitqueue_head(&priv->wait); + init_waitqueue_head(&priv->rx_wait); + DBG("priv->rx_wait =%p\n", &priv->rx_wait); + init_waitqueue_head(&priv->tx_wait); + INIT_LIST_HEAD(&priv->link); + priv->reading_state = HECI_IDLE; + priv->writing_state = HECI_IDLE; + priv->file = file; + priv->flow_control_credentials = 0; + priv->timer_count = 0; + priv->me_client_id = 0; + priv->read_cb = NULL; + priv->status = ESUCCESS; + priv->read_pending = FALSE; + return priv; +} + + + +/** + * heci_disconnect_host_client - send disconnect message to fw from host client. + * + * @device_object -Device object for our driver + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_disconnect_host_client(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + int return_status = ESUCCESS, err = 0; + long timeout = 15; /*15 second */ + + struct heci_cb_private *kernel_priv_cb = NULL; + + struct heci_file_private *file_extension_list_temp = NULL; + + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + + if ((!device_object) || (!file_extension)) + return -ENODEV; + kernel_priv_cb = kmalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!kernel_priv_cb) + return -ENOMEM; + if (file_extension->state == HECI_FILE_DISCONNECTING) { + INIT_LIST_HEAD(&kernel_priv_cb->cb_list); + kernel_priv_cb->file_private = file_extension; + kernel_priv_cb->major_file_operations = HECI_CLOSE; + spin_lock_bh(&device_object->device_lock); + if (device_object->host_buffer_is_empty){ + device_object->host_buffer_is_empty =FALSE; + if (heci_disconnect(device_object, file_extension)) { + list_add_tail(&kernel_priv_cb->cb_list, + &device_object->control_read_list. + heci_cb.cb_list); + } + else{ + spin_unlock_bh(&device_object->device_lock); + return_status = -ENODEV; + DBG("failed to call heci_disconnect for file_extension.\n"); + goto free; + } + } + else{ + kernel_priv_cb->file_private = file_extension; + DBG("add disconnect cb to control write list\n"); + list_add_tail(&kernel_priv_cb->cb_list, + &device_object->control_write_list.heci_cb.cb_list); + } + spin_unlock_bh(&device_object->device_lock); + + err = + wait_event_timeout + (device_object->wait_received_message, + (HECI_FILE_DISCONNECTED == file_extension->state), + timeout * HZ); + if (HECI_FILE_DISCONNECTED == file_extension->state) { + return_status = ESUCCESS; + DBG("successfully to disconnect from fw client.\n"); + } else { + return_status = -ENODEV; + if (HECI_FILE_DISCONNECTED != file_extension->state) + DBG("wrong status received for client disconnect.\n"); + if (!err) + DBG("wait_event_interruptible_timeout failed on client disconnect message fw response message err=%08x\n", err); + DBG("failed to diconnect to fw client.\n"); + } + + } + if (kernel_priv_cb) { + spin_lock_bh(&device_object->device_lock); + if (device_object->control_read_list.status == ESUCCESS + && !list_empty(&device_object->control_read_list.heci_cb.cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object->control_read_list.heci_cb.cb_list, cb_list){ + file_extension_list_temp = + (struct heci_file_private *) + kernel_priv_cb_pos->file_private; + if (file_extension_list_temp) { + if ((file_extension->host_client_id == file_extension_list_temp->host_client_id) + && (file_extension->me_client_id == file_extension_list_temp->me_client_id)) { + list_del(&kernel_priv_cb_pos->cb_list); + } + } + + } + } + spin_unlock_bh(&device_object->device_lock); +free: + kfree(kernel_priv_cb); + kernel_priv_cb = NULL; + + + } + + return return_status; +} + + +/** + * heci_remove_client_from_file_list - remove file extension from device file list + * + * @device_object -Device object for our driver + * @host_client_id -host client id to be removed + * + * @return : + * none; + */ +void heci_remove_client_from_file_list(struct iamt_heci_device * device_object, + __u8 host_client_id) +{ + struct heci_file_private *file_extension_pos = NULL; + struct heci_file_private *file_extension_next = NULL; + list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) { + if (host_client_id == file_extension_pos->host_client_id) { + DBG("remove file extension node host client = %d, ME client = %d\n", + file_extension_pos->host_client_id, + file_extension_pos->me_client_id); + list_del(&file_extension_pos->link); + break; + } + + + } +} --- linux-2.6.27.orig/ubuntu/heci/io_heci.c +++ linux-2.6.27/ubuntu/heci/io_heci.c @@ -0,0 +1,1138 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heci_data_structures.h" +#include "heci.h" +#include "heci_interface.h" +#include "version.h" + + +/** + * heci_ioctl_get_version - the get driver version IOCTL function + * @device_object -Device object for our driver + * @if_num minor number + * @*u_msg pointer to user data struct in user space + * @k_msg data in kernel on the stack + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_ioctl_get_version(struct iamt_heci_device * device, int if_num, + struct heci_message_data *u_msg, + struct heci_message_data k_msg, + struct heci_file_private * file_extension) +{ + + int return_status = ESUCCESS; + struct heci_driver_version *version; + struct heci_message_data res_msg; + res_msg.data = NULL; + if ((if_num != HECI_MINOR_NUMBER) || (!device) + || (!file_extension)) + return -ENODEV; + + + if (k_msg.size < (sizeof(struct heci_driver_version) - 2)) { + DBG("user buffer less than heci_driver_version.\n"); + return -EMSGSIZE; + } + + res_msg.data = kmalloc(sizeof(struct heci_driver_version), GFP_KERNEL); + if (!res_msg.data) { + DBG("failed allocation response buffer size = %d.\n", + (int) sizeof(struct heci_driver_version)); + return -ENOMEM; + + } + version = (struct heci_driver_version *) res_msg.data; + version->major = MAJOR_VERSION; + version->minor = MINOR_VERSION; + version->hotfix = QUICK_FIX_NUMBER; + if (k_msg.size < sizeof(struct heci_driver_version)) { + res_msg.size = sizeof(struct heci_driver_version) - 2; + } else { + version->build = VER_BUILD; + res_msg.size = sizeof(struct heci_driver_version); + } + return_status = file_extension->status; + /* now copy the data to user space */ + if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) { + return_status = -EFAULT; + goto end; + } + if (put_user(res_msg.size, &u_msg->size)) { + return_status = -EFAULT; + goto end; + } +end: + kfree(res_msg.data); + return return_status; +} + +/** + * heci_ioctl_connect_client - the connect to fw client IOCTL function + * @device_object -Device object for our driver + * @if_num minor number + * @*u_msg pointer to user data struct in user space + * @k_msg data in kernel on the stack + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_ioctl_connect_client(struct iamt_heci_device * device, int if_num, + struct heci_message_data *u_msg, + struct heci_message_data k_msg, + struct file *file) +{ + + int return_status = ESUCCESS; + struct heci_message_data req_msg, res_msg; + struct heci_cb_private *kernel_priv_cb = NULL; + struct heci_client *client; + struct heci_file_private *file_extension = NULL; + struct heci_file_private *file_extension_pos = NULL; + struct heci_file_private *file_extension_next = NULL; + struct heci_file_private *file_extension_list_temp = NULL; + + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + long timeout = 15; /*15 second */ + __u8 i; + int err = 0; + res_msg.data = NULL; + req_msg.data = NULL; + if ((if_num != HECI_MINOR_NUMBER) || (!device) + || (!file)) + return -ENODEV; + file_extension = file->private_data; + if (!file_extension) + return -ENODEV; + if (k_msg.size != sizeof(struct guid)) { + DBG("user buffer size is not equal to size of struct guid(16).\n"); + return -EMSGSIZE; + } + req_msg.data = kmalloc(sizeof(struct guid), GFP_KERNEL); + res_msg.data = kmalloc(sizeof(struct heci_client), GFP_KERNEL); + + + if (!res_msg.data) { + DBG("failed allocation response buffer size = %d.\n", + (int) sizeof(struct heci_client)); + if (req_msg.data) { + kfree(req_msg.data); + req_msg.data = NULL; + goto fail; + } + } + if (!req_msg.data) { + DBG("failed allocation request buffer size = %d.\n", + (int) sizeof(struct guid)); + if (res_msg.data) { + kfree(res_msg.data); + res_msg.data = NULL; + goto fail; + } + fail: + return -ENOMEM; + } + req_msg.size = sizeof(struct guid); + res_msg.size = sizeof(struct heci_client); + if (!k_msg.data) { + return_status = -EIO; + goto end; + } + + /* copy the message to kernel space - use a pointer already copied into kernel space */ + if (copy_from_user(req_msg.data, k_msg.data, k_msg.size)) { + return_status = -EFAULT; + goto end; + } + /* buffered ioctl cb */ + kernel_priv_cb = + kmalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!kernel_priv_cb) { + return_status = -ENOMEM; + goto end; + } + INIT_LIST_HEAD(&kernel_priv_cb->cb_list); + kernel_priv_cb->response_buffer.data = res_msg.data; + kernel_priv_cb->response_buffer.size = res_msg.size; + kernel_priv_cb->request_buffer.data = req_msg.data; + kernel_priv_cb->request_buffer.size = req_msg.size; + kernel_priv_cb->major_file_operations = HECI_IOCTL; + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED) { + return_status = -ENODEV; + spin_unlock_bh(&device->device_lock); + goto end; + } + if ((file_extension->state != HECI_FILE_INITIALIZING) && + (file_extension->state != HECI_FILE_DISCONNECTED)) { + return_status = -EBUSY; + spin_unlock_bh(&device->device_lock); + goto end; + } + + /* find ME client we're trying to connect to */ + for (i = 0; i < device->num_heci_me_clients; i++) { + if (0 == memcmp((struct guid *) req_msg.data, + &device->me_clients[i].properteis.protocol_name, + sizeof(struct guid))) { + if (device->me_clients[i].properteis.fixed_address == 0) { + file_extension->me_client_id = + device->me_clients[i].client_id; + file_extension->state = + HECI_FILE_CONNECTING; + } + break; + } + } + /*if we're connecting to PTHI client so we will use the exist connection */ + if (0 == memcmp((struct guid *) req_msg.data, &heci_pthi_guid, + sizeof(struct guid))) { + + if (device->legacy_file_extension.state != HECI_FILE_CONNECTED) { + return_status = -ENODEV; + spin_unlock_bh(&device->device_lock); + goto end; + } + device->heci_host_clients[file_extension->host_client_id / 8] &= + ~(1 << (file_extension->host_client_id % 8)); + list_for_each_entry_safe(file_extension_pos, file_extension_next, &device->file_list, link) { + if ((file_extension->host_client_id == + file_extension_pos->host_client_id) + && (file_extension->me_client_id == + file_extension_pos->me_client_id)) { + + DBG("remove file extension node host client = %d, ME client = %d\n", + file_extension_pos->host_client_id, + file_extension_pos->me_client_id); + list_del(&file_extension_pos->link); + } + + } + DBG("free file extension memory\n"); + kfree(file_extension); + file_extension = NULL; + file->private_data = &device->legacy_file_extension; + client = (struct heci_client *) res_msg.data; + client->max_message_length = + device->me_clients[i].properteis.max_message_length; + client->protocol_version = + device->me_clients[i].properteis.protocol_version; + return_status = device->legacy_file_extension.status; + spin_unlock_bh(&device->device_lock); + + /* now copy the data to user space */ + if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) { + return_status = -EFAULT; + goto end; + } + if (put_user(res_msg.size, &u_msg->size)) { + return_status = -EFAULT; + goto end; + } + goto end; + } + spin_lock(&file_extension->file_lock); + if (file_extension->state != HECI_FILE_CONNECTING) { + return_status = -ENODEV; + spin_unlock(&file_extension->file_lock); + spin_unlock_bh(&device->device_lock); + goto end; + } + spin_unlock(&file_extension->file_lock); + /* prepare the output buffer */ + client = (struct heci_client *) res_msg.data; + client->max_message_length = + device->me_clients[i].properteis.max_message_length; + client->protocol_version = + device->me_clients[i].properteis.protocol_version; + if (device->host_buffer_is_empty + && !other_client_is_connecting(device, file_extension)) { + device->host_buffer_is_empty = FALSE; + if (!heci_connect(device, file_extension)) { + return_status = -ENODEV; + spin_unlock_bh(&device->device_lock); + goto end; + } else { + file_extension->timer_count = CONNECT_TIMEOUT; + kernel_priv_cb->file_private = file_extension; + list_add_tail(&kernel_priv_cb->cb_list, + &device->control_read_list.heci_cb. + cb_list); + } + + + } else { + kernel_priv_cb->file_private = file_extension; + DBG("add connect cb to control write list\n"); + list_add_tail(&kernel_priv_cb->cb_list, + &device->control_write_list.heci_cb.cb_list); + } + spin_unlock_bh(&device->device_lock); + err = + wait_event_timeout(device->wait_received_message, + (HECI_FILE_CONNECTED == file_extension->state || HECI_FILE_DISCONNECTED == file_extension->state), + timeout * HZ); + if (HECI_FILE_CONNECTED == file_extension->state) { + DBG("successfully to connect to FW client.\n"); + return_status = file_extension->status; + /* now copy the data to user space */ + if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) { + return_status = -EFAULT; + goto end; + } + if (put_user(res_msg.size, &u_msg->size)) { + return_status = -EFAULT; + goto end; + } + goto end; + } else { + DBG("failed to connect to FW client.file_extension->state = %d\n", file_extension->state); + if (!err) + DBG("wait_event_interruptible_timeout failed on client connect message fw response message\n"); + + return_status = -EFAULT; + goto remove_list; + } + +remove_list: + if (kernel_priv_cb) { + spin_lock_bh(&device->device_lock); + if (device->control_read_list.status == ESUCCESS + && !list_empty(&device->control_read_list.heci_cb.cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device->control_read_list.heci_cb.cb_list, cb_list){ + file_extension_list_temp = + (struct heci_file_private *) + kernel_priv_cb_pos->file_private; + if (file_extension_list_temp) { + if ((file_extension->host_client_id == file_extension_list_temp->host_client_id) + && (file_extension->me_client_id == file_extension_list_temp->me_client_id)) + list_del(&kernel_priv_cb_pos->cb_list); + + } + + } + } + if (device->control_write_list.status == ESUCCESS + && !list_empty(&device->control_write_list.heci_cb.cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device->control_write_list.heci_cb.cb_list, cb_list){ + file_extension_list_temp = + (struct heci_file_private *) + kernel_priv_cb_pos->file_private; + if (file_extension_list_temp) { + if ((file_extension->host_client_id == file_extension_list_temp->host_client_id) + && (file_extension->me_client_id == file_extension_list_temp->me_client_id)) + list_del(&kernel_priv_cb_pos->cb_list); + + } + + } + } + spin_unlock_bh(&device->device_lock); + } +end: + DBG("free connect cb memory"); + kfree(req_msg.data); + req_msg.data = NULL; + kfree(res_msg.data); + res_msg.data = NULL; + kfree(kernel_priv_cb); + kernel_priv_cb = NULL; + return return_status; +} + +/** + * heci_ioctl_wd - the wd IOCTL function + * @device_object -Device object for our driver + * @if_num minor number + * @k_msg data in kernel on the stack + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_ioctl_wd(struct iamt_heci_device * device, int if_num, + struct heci_message_data k_msg, + struct heci_file_private * file_extension) +{ + int return_status = ESUCCESS; + struct heci_message_data req_msg; /*in kernel on the stack */ + if (if_num != HECI_MINOR_NUMBER) + return -ENODEV; + spin_lock(&file_extension->file_lock); + if (k_msg.size != HECI_WATCHDOG_DATA_SIZE) { + DBG("User buffer has invalid size.\n"); + spin_unlock(&file_extension->file_lock); + return -EMSGSIZE; + } + spin_unlock(&file_extension->file_lock); + req_msg.data = kmalloc(HECI_WATCHDOG_DATA_SIZE, GFP_KERNEL); + if (!req_msg.data) { + DBG("failed allocation request buffer size = %d.\n", + HECI_WATCHDOG_DATA_SIZE); + return -ENOMEM; + } + req_msg.size = HECI_WATCHDOG_DATA_SIZE; + + /* copy the message to kernel space - use a pointer already copied into kernel space */ + if (copy_from_user(req_msg.data, k_msg.data, req_msg.size)) { + return_status = -EFAULT; + goto end; + } + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED) { + return_status = -ENODEV; + spin_unlock_bh(&device->device_lock); + goto end; + } + + if (device->wd_file_extension.state != HECI_FILE_CONNECTED) { + return_status = -ENODEV; + spin_unlock_bh(&device->device_lock); + goto end; + } + if (!device->asf_mode) { + return_status = -EIO; + spin_unlock_bh(&device->device_lock); + goto end; + } + + memcpy(&device->wd_data[HECI_WD_PARAMS_SIZE], req_msg.data, + HECI_WATCHDOG_DATA_SIZE); + + device->wd_timeout = (req_msg.data[1] << 8) + + req_msg.data[0]; + if (device->wd_timeout == 0) { + memcpy(device->wd_data, &stop_wd_params, + HECI_WD_PARAMS_SIZE); + device->wd_pending = FALSE; + device->wd_due_counter = 1; /* next timer */ + } else { + memcpy(device->wd_data, &start_wd_params, + HECI_WD_PARAMS_SIZE); + device->wd_pending = FALSE; + device->wd_due_counter = 1; + } + spin_unlock_bh(&device->device_lock); +end: + kfree(req_msg.data); + req_msg.data = NULL; + return return_status; +} + + +/** + * heci_ioctl_bypass_wd - the bypass_wd IOCTL function + * @device_object -Device object for our driver + * @if_num minor number + * @k_msg data in kernel on the stack + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_ioctl_bypass_wd(struct iamt_heci_device * device, int if_num, + struct heci_message_data k_msg, + struct heci_file_private * file_extension) +{ + __u8 flag=0; + int return_status = ESUCCESS; + + if (if_num != HECI_MINOR_NUMBER) + return -ENODEV; + spin_lock(&file_extension->file_lock); + if (k_msg.size < 1) { + DBG("user buffer less than HECI_WATCHDOG_DATA_SIZE .\n"); + spin_unlock(&file_extension->file_lock); + return -EMSGSIZE; + } + spin_unlock(&file_extension->file_lock); + if (copy_from_user(&flag,k_msg.data,1)) { + return_status = -EFAULT; + goto end; + } + + spin_lock_bh(&device->device_lock); + flag = flag ?(TRUE):(FALSE); + device->wd_bypass = flag; + spin_unlock_bh(&device->device_lock); +end: + return return_status; +} + + +/** + * legacy_ioctl_send_message - send command data to pthi client + * @device_object -Device object for our driver + * @if_num minor number + * @*u_msg pointer to user data struct in user space + * @k_msg data in kernel on the stack + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int legacy_ioctl_send_message(struct iamt_heci_device * device, int if_num, + struct heci_message_data k_msg, + struct file *file) +{ + + int return_status = ESUCCESS; + struct heci_message_data req_msg, res_msg; /*in kernel on the stack */ + struct heci_cb_private *kernel_priv_cb = NULL; + struct heci_file_private *file_extension = file->private_data; + __u8 i; + req_msg.data = NULL; + res_msg.data = NULL; + if ((if_num != LEGACY_MINOR_NUMBER) || (!device)) + return -ENODEV; + if (!file_extension) + return -ENODEV; + spin_lock_bh(&device->device_lock); + for (i = 0; i < device->num_heci_me_clients; i++) { + if (device->me_clients[i].client_id == + device->legacy_file_extension.me_client_id) + break; + } + + BUG_ON(device->me_clients[i].client_id != file_extension->me_client_id); + if ((i == device->num_heci_me_clients) + || (device->me_clients[i].client_id != + device->legacy_file_extension.me_client_id)) { + spin_unlock_bh(&device->device_lock); + return -ENODEV; + } else if (k_msg.size > + device->me_clients[i].properteis.max_message_length + || k_msg.size <= 0) { + spin_unlock_bh(&device->device_lock); + return -EMSGSIZE; + } + + + spin_unlock_bh(&device->device_lock); + req_msg.data = kmalloc(k_msg.size, GFP_KERNEL); + res_msg.data = kmalloc(LEGACY_MTU, GFP_KERNEL); + + if (!res_msg.data) { + DBG("failed allocation response buffer size = %d.\n", + (int) sizeof(struct heci_client)); + if (req_msg.data) { + + kfree(req_msg.data); + req_msg.data = NULL; + return -ENOMEM; + } + } + if (!req_msg.data) { + DBG("failed allocation request buffer size = %d.\n", + (int) sizeof(struct guid)); + if (res_msg.data) { + kfree(res_msg.data); + res_msg.data = NULL; + return -ENOMEM; + } + } + req_msg.size = k_msg.size; + res_msg.size = LEGACY_MTU; + if (!k_msg.data) { + return_status = -EIO; + goto end; + } + + /* copy the message to kernel space - use a pointer already copied into kernel space */ + if (copy_from_user(req_msg.data, k_msg.data, k_msg.size)) { + return_status = -EFAULT; + goto end; + } + /* buffered ioctl cb */ + kernel_priv_cb = + kmalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!kernel_priv_cb) { + return_status = -ENOMEM; + goto end; + } + INIT_LIST_HEAD(&kernel_priv_cb->cb_list); + + kernel_priv_cb->request_buffer.data = req_msg.data; + kernel_priv_cb->request_buffer.size = req_msg.size; + kernel_priv_cb->response_buffer.data = res_msg.data; + kernel_priv_cb->response_buffer.size = res_msg.size; + kernel_priv_cb->major_file_operations = HECI_IOCTL; + kernel_priv_cb->information = 0; + kernel_priv_cb->file_object = file; + kernel_priv_cb->file_private = file_extension; + spin_lock_bh(&device->device_lock); + + if (device->heci_state != HECI_ENABLED) { + return_status = -ENODEV; + spin_unlock_bh(&device->device_lock); + goto end; + } + if (device->legacy_file_extension.state != HECI_FILE_CONNECTED) { + return_status = -ENODEV; + spin_unlock_bh(&device->device_lock); + goto end; + } + + + if (!list_empty(&device->pthi_cmd_list.heci_cb.cb_list) + || device->legacy_state != HECI_LEGACY_IDLE) { + DBG("pthi_state = %d\n", (int) device->legacy_state); + DBG("add PTHI cb to pthi cmd waiting list"); + list_add_tail(&kernel_priv_cb->cb_list, + &device->pthi_cmd_list.heci_cb.cb_list); + + } else { + DBG("call pthi write\n"); + return_status = pthi_write(device, kernel_priv_cb); + + if (ESUCCESS != return_status) { + DBG("pthi write failed with status = %d\n", + return_status); + spin_unlock_bh(&device->device_lock); + goto end; + } + } + spin_unlock_bh(&device->device_lock); + return return_status; +end: + kfree(req_msg.data); + req_msg.data = NULL; + kfree(res_msg.data); + res_msg.data = NULL; + kfree(kernel_priv_cb); + kernel_priv_cb = NULL; + return return_status; +} + + +/** + * legacy_ioctl_receive_message - receive command data from pthi client + * @device_object -Device object for our driver + * @if_num minor number + * @*u_msg pointer to user data struct in user space + * @k_msg data in kernel on the stack + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int legacy_ioctl_receive_message(struct iamt_heci_device * device, int if_num, + struct heci_message_data *u_msg, + struct heci_message_data k_msg, + struct file *file) +{ + + int return_status = ESUCCESS; + struct heci_message_data req_msg, res_msg; + struct heci_cb_private *kernel_priv_cb = NULL; + struct heci_file_private *file_extension = file->private_data; + __u8 i; + struct heci_file_private *file_extension_list_temp = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + + + res_msg.data = NULL; + req_msg.data = NULL; + + if ((if_num != LEGACY_MINOR_NUMBER) || (!device)) + return -ENODEV; + spin_lock_bh(&device->device_lock); + if (!file_extension) { + spin_unlock_bh(&device->device_lock); + return -ENODEV; + } + for (i = 0; i < device->num_heci_me_clients; i++) + if (device->me_clients[i].client_id == + device->legacy_file_extension.me_client_id) + break; + + BUG_ON(device->me_clients[i].client_id != + file_extension->me_client_id); + if ((i == device->num_heci_me_clients) + || (device->me_clients[i].client_id != + device->legacy_file_extension.me_client_id)) { + spin_unlock_bh(&device->device_lock); + return -ENODEV; + } + + if (device->pthi_read_complete_list.status == ESUCCESS) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device->pthi_read_complete_list.heci_cb.cb_list, cb_list){ + file_extension_list_temp = + (struct heci_file_private *) + kernel_priv_cb_pos->file_private; + if (file_extension_list_temp) { + if ((file_extension == &device->legacy_file_extension) + && (kernel_priv_cb_pos->file_object == file)) { + list_del(&kernel_priv_cb_pos->cb_list); + kernel_priv_cb = + kernel_priv_cb_pos; + break; + } + } + + } + } + if (!kernel_priv_cb) { + spin_unlock_bh(&device->device_lock); + return -EAGAIN; + } + + + res_msg.data = kernel_priv_cb->response_buffer.data; + res_msg.size = kernel_priv_cb->response_buffer.size; + req_msg.data = kernel_priv_cb->request_buffer.data; + req_msg.size = kernel_priv_cb->request_buffer.size; + DBG("pthi kernel_priv_cb->response_buffer size - %d\n", + kernel_priv_cb->response_buffer.size); + DBG("pthi kernel_priv_cb->information - %lu\n", + kernel_priv_cb->information); + spin_unlock_bh(&device->device_lock); + + if (res_msg.size < kernel_priv_cb->information) { + return_status = -EMSGSIZE; + goto end; + } + /* now copy the data to user space */ + if (copy_to_user(k_msg.data, + res_msg.data, + kernel_priv_cb->information)) { + return_status = -EFAULT; + goto end; + } + if (put_user(kernel_priv_cb->information, &u_msg->size)) { + return_status = -EFAULT; + goto end; + } +end: + kfree(req_msg.data); + kfree(res_msg.data); + kfree(kernel_priv_cb); + return return_status; +} + +/** + * find_pthi_read_list_entry - finds a PTHIlist entry for current file + * @device_object -Device object for our driver + * + * @return : + * returned a list entry on success, + * NULL on failure. + */ +struct heci_cb_private* find_pthi_read_list_entry(struct iamt_heci_device* device, + struct file* file, struct heci_file_private* file_extension) +{ + struct heci_file_private *file_extension_list_temp = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + + if (device->pthi_read_complete_list.status == ESUCCESS + && !list_empty(&device->pthi_read_complete_list.heci_cb. + cb_list)) { + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device->pthi_read_complete_list.heci_cb.cb_list, cb_list){ + file_extension_list_temp = + (struct heci_file_private *) + kernel_priv_cb_pos->file_private; + if (file_extension_list_temp) { + if ((file_extension == &device->legacy_file_extension) + && (kernel_priv_cb_pos->file_object == file)) { + return kernel_priv_cb_pos; + } + } + } + } + return NULL; +} +/** + * pthi_read - read data from pthi client + * @device_object -Device object for our driver + * @if_num minor number + * @*u_msg pointer to user data in user space + * @length-user data length + * + * @return : + * returned data length on success, + * zero if no data to read, + * negative on failure. + */ +int pthi_read(struct iamt_heci_device * device, int if_num, struct file *file, + char *ubuf, size_t length, loff_t * offset) +{ + + int return_status = ESUCCESS; + struct heci_cb_private *kernel_priv_cb = NULL; + struct heci_file_private *file_extension = file->private_data; + __u8 i; + unsigned long currtime = get_seconds(); + + if ((if_num != HECI_MINOR_NUMBER) || (!device)) + return -ENODEV; + + if (!file_extension) + return -ENODEV; + + spin_lock_bh(&device->device_lock); + for (i = 0; i < device->num_heci_me_clients; i++) + if (device->me_clients[i].client_id == + device->legacy_file_extension.me_client_id) + break; + BUG_ON(device->me_clients[i].client_id != file_extension->me_client_id); + if ((i == device->num_heci_me_clients) + || (device->me_clients[i].client_id != + device->legacy_file_extension.me_client_id)) { + DBG("PTHI client not found\n"); + spin_unlock_bh(&device->device_lock); + return -ENODEV; + } + kernel_priv_cb = find_pthi_read_list_entry(device, file, file_extension); + if (!kernel_priv_cb) { + spin_unlock_bh(&device->device_lock); + return 0; /* No more data to read */ + } + else { + /* 15 sec for the message has expired */ + if (kernel_priv_cb && currtime - kernel_priv_cb->read_time > LEGACY_READ_TIMER) { + list_del(&kernel_priv_cb->cb_list); + spin_unlock_bh(&device->device_lock); + return_status = -ETIMEDOUT; + goto free; + } + /* if the whole message will fit remove it from the list */ + if ((kernel_priv_cb->information >= *offset) && + (length >= (kernel_priv_cb->information - *offset))) { + list_del(&kernel_priv_cb->cb_list); + } + /* end of the message has been reached */ + else if ((kernel_priv_cb->information > 0) && + (kernel_priv_cb->information <= *offset)) { + list_del(&kernel_priv_cb->cb_list); + return_status = 0; + spin_unlock_bh(&device->device_lock); + goto free; + } + /* else means that not full buffer will be read and do not remove message from deletion list */ + } + DBG("pthi kernel_priv_cb->response_buffer size - %d\n", + kernel_priv_cb->response_buffer.size); + DBG("pthi kernel_priv_cb->information - %lu\n", + kernel_priv_cb->information); + spin_unlock_bh(&device->device_lock); + + /* length is being turncated to PAGE_SIZE, however, the information may be longer */ + length = length < (kernel_priv_cb->information - *offset) ? + length : (kernel_priv_cb->information - *offset); + + if (copy_to_user + (ubuf, kernel_priv_cb->response_buffer.data + *offset, length)) { + return_status = -EFAULT; + } else { + return_status = length; + if ((*offset + length) < kernel_priv_cb->information) { + *offset += length; + goto out; + } + } + DBG("free pthi cb memory\n"); +free: + *offset = 0; + kfree(kernel_priv_cb->request_buffer.data); + kfree(kernel_priv_cb->response_buffer.data); + kfree(kernel_priv_cb); +out: + return return_status; +} + +/** + * heci_start_read - the start read client message function. + * @device_object -Device object for our driver + * @if_num minor number + * @file_extension -extension of the file object + * + * @return : + * 0 on success, + * negative on failure. + */ +int heci_start_read(struct iamt_heci_device * device, int if_num, + struct heci_file_private * file_extension) +{ + int return_status = ESUCCESS; + __u8 i; + struct heci_cb_private *priv_cb = NULL; + if ((if_num != HECI_MINOR_NUMBER) || (!device) + || (!file_extension)) { + DBG("receive wrong function input param\n."); + return -ENODEV; + } + if (file_extension->state != HECI_FILE_CONNECTED) + return -ENODEV; + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED) { + spin_unlock_bh(&device->device_lock); + return -ENODEV; + } + spin_unlock_bh(&device->device_lock); + DBG("check if read is pending\n"); + if (file_extension->read_pending + || file_extension->read_cb != NULL) { + DBG("read is pending"); + return -EBUSY; + } + priv_cb = kmalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!priv_cb) + return -ENOMEM; + + DBG("allocation call back success\n"); + DBG("host client = %d, ME client = %d\n", + file_extension->host_client_id, file_extension->me_client_id); + spin_lock_bh(&device->device_lock); + for (i = 0; i < device->num_heci_me_clients; i++) + if (device->me_clients[i].client_id == + file_extension->me_client_id) + break; + + BUG_ON(device->me_clients[i].client_id != + file_extension->me_client_id); + if ((i == device->num_heci_me_clients)) { + return_status = -ENODEV; + goto unlock; + } + + priv_cb->response_buffer.size = + device->me_clients[i].properteis.max_message_length; + spin_unlock_bh(&device->device_lock); + priv_cb->response_buffer.data = + kmalloc(priv_cb->response_buffer.size, GFP_KERNEL); + if (!priv_cb->response_buffer.data) { + return_status = -ENOMEM; + goto fail; + } + DBG("allocation call back data success\n"); + priv_cb->major_file_operations = HECI_READ; + /* make sure information is zero before we start */ + priv_cb->information = 0; + priv_cb->file_private = (void *) file_extension; + file_extension->read_cb = priv_cb; + spin_lock_bh(&device->device_lock); + if (device->host_buffer_is_empty) { + device->host_buffer_is_empty = FALSE; + if (!heci_send_flow_control(device, file_extension)) { + return_status = -ENODEV; + goto unlock; + } else { + list_add_tail(&priv_cb->cb_list, + &device->read_list.heci_cb.cb_list); + } + } else { + list_add_tail(&priv_cb->cb_list, + &device->control_write_list.heci_cb.cb_list); + } + spin_unlock_bh(&device->device_lock); + return return_status; +unlock: + spin_unlock_bh(&device->device_lock); +fail: + kfree(priv_cb->response_buffer.data); + priv_cb->response_buffer.data = NULL; + priv_cb->file_private = NULL; + kfree(priv_cb); + return return_status; +} + +/** + * pthi_write - write legacy data to pthi client + * @device -Device object for our driver + * @kernel_priv_cb - heci call back struct + * @return : + * 0 on success, + * negative on failure. + */ +int pthi_write(struct iamt_heci_device * device, + struct heci_cb_private *kernel_priv_cb) +{ + int return_status = ESUCCESS; + struct heci_message_header heci_header; + + if ((!device) || (!kernel_priv_cb)) + return -ENODEV; + + DBG("write data to pthi client\n"); + + device->legacy_state = HECI_LEGACY_WRITING; + device->legacy_current_cb = kernel_priv_cb; + device->legacy_file_object = kernel_priv_cb->file_object; + device->legacy_canceled = FALSE; + device->legacy_ioctl = TRUE; + device->legacy_message_buffer_size = + kernel_priv_cb->request_buffer.size; + memcpy(device->legacy_message_buffer, + kernel_priv_cb->request_buffer.data, + kernel_priv_cb->request_buffer.size); + if (flow_control_credentials + (device, &device->legacy_file_extension) + && device->host_buffer_is_empty) { + device->host_buffer_is_empty = FALSE; + if (kernel_priv_cb->request_buffer.size > + (((device->host_hw_state & H_CBD) >> 24) * sizeof(__u32)) - sizeof(struct heci_message_header)) { + heci_header.length = + (((device->host_hw_state & H_CBD) >> 24) * sizeof(__u32)) - sizeof(struct heci_message_header); + heci_header.message_complete = 0; + } else { + heci_header.length = + kernel_priv_cb->request_buffer.size; + heci_header.message_complete = 1; + } + + heci_header.host_address = + device->legacy_file_extension.host_client_id; + heci_header.me_address = + device->legacy_file_extension.me_client_id; + heci_header.reserved = 0; + device->legacy_message_buffer_index += heci_header.length; + if (!heci_write_message(device, &heci_header, + (unsigned char *) (device->legacy_message_buffer), + heci_header.length)) + return -ENODEV; + + if (heci_header.message_complete) { + + flow_control_reduce(device, + &device-> + legacy_file_extension); + device->legacy_flow_control_pending = TRUE; + device->legacy_state = HECI_LEGACY_FLOW_CONTROL; + DBG("add pthi cb to write waiting list\n"); + device->legacy_current_cb = kernel_priv_cb; + device->legacy_file_object = kernel_priv_cb->file_object; + list_add_tail(&kernel_priv_cb->cb_list, + &device->write_waiting_list.heci_cb. + cb_list); + + } else { + DBG("message does not complete, so add pthi cb to write list\n"); + list_add_tail(&kernel_priv_cb->cb_list, + &device->write_list.heci_cb.cb_list); + } + + + + } else { + if (TRUE != device->host_buffer_is_empty) + DBG("host buffer is not empty"); + DBG("No flow control credentials, so add legacy cb to write list\n"); + list_add_tail(&kernel_priv_cb->cb_list, + &device->write_list.heci_cb.cb_list); + } + return return_status; +} + +/** + * legacy_ioctl_send_message - send command data to pthi client + * @device -Device object for our driver + * @return : + * 0 on success, + * negative on failure. + */ +void run_next_legacy_cmd(struct iamt_heci_device * device) +{ + struct heci_file_private *file_extension_temp = NULL; + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + int legacy_write_status = ESUCCESS; + + if (!device) + return; + device->legacy_message_buffer_size = 0; + device->legacy_message_buffer_index = 0; + device->legacy_canceled = FALSE; + device->legacy_ioctl = TRUE; + device->legacy_state = HECI_LEGACY_IDLE; + device->legacy_timer = 0; + device->legacy_file_object = NULL; + + if (device->pthi_cmd_list.status == ESUCCESS + && !list_empty(&device->pthi_cmd_list.heci_cb.cb_list)) { + DBG("complete pthi cmd_list CB\n "); + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device->pthi_cmd_list.heci_cb.cb_list, cb_list){ + list_del(&kernel_priv_cb_pos->cb_list); + file_extension_temp = (struct heci_file_private *) kernel_priv_cb_pos->file_private; + + if ((file_extension_temp) + && (file_extension_temp == &device->legacy_file_extension)) { + legacy_write_status = + pthi_write(device, kernel_priv_cb_pos); + if (legacy_write_status != ESUCCESS) { + DBG("pthi write failed with status = %d\n", + legacy_write_status); + return; + } + break; + } + } + } + return; +} --- linux-2.6.27.orig/ubuntu/heci/heci_interface.c +++ linux-2.6.27/ubuntu/heci/heci_interface.c @@ -0,0 +1,525 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + + +#include "heci.h" +#include "heci_interface.h" + + + +static const __u8 interface_start_wd_params[] = + { 0x02, 0x12, 0x13, 0x10 }; +static const __u8 interface_stop_wd_params[] = + { 0x02, 0x02, 0x14, 0x10 }; + +/** + * read_heci_register - Read a byte from the heci device + * @device: the device structure + * @offset: offset from which to read the data + * + * Return: + * the byte read. + */ +__u32 read_heci_register(struct iamt_heci_device * device, + unsigned long offset) +{ + return readl(device->mem_addr + offset); +} + +/** + * write_heci_register - Write 4 bytes to the heci device + * @device: the device structure + * @offset: offset from which to write the data + * + * @value: the byte to write + */ +void write_heci_register(struct iamt_heci_device * device, unsigned long offset, + __u32 value) +{ + writel(value, device->mem_addr + offset); +} + +/** + * host_buffer_is_empty - check if host buffer is empty. + * + * @device_object -Device object for our driver + * + * @return : + * TRUE if empty + * FALSE - otherwise. + */ +int host_buffer_is_empty(struct iamt_heci_device * device_object) +{ + char read_ptr, write_ptr; + unsigned char buffer_depth, filled_slots, empty_slots; + device_object->host_hw_state = + read_heci_register(device_object, H_CSR); + read_ptr = (char) ((device_object->host_hw_state & H_CBRP) >> 8); + write_ptr = (char) ((device_object->host_hw_state & H_CBWP) >> 16); + buffer_depth = + (unsigned char) ((device_object->host_hw_state & H_CBD) >> 24); + filled_slots = (unsigned char) (write_ptr - read_ptr); + empty_slots = buffer_depth - filled_slots; + + if (filled_slots > 0) + return FALSE; + return TRUE; +} + +/** + * count_empty_write_slots - count write empty slots. + * + * @device_object - Device object for our driver + * + * + * @return : + * -1(ESLOTS_OVERFLOW) if overflow + * otherwise filed slots count + */ +__s32 count_empty_write_slots(struct iamt_heci_device * device_object) +{ + char read_ptr, write_ptr; + unsigned char buffer_depth, filled_slots, empty_slots; + + read_ptr = (char) ((device_object->host_hw_state & H_CBRP) >> 8); + write_ptr = (char) ((device_object->host_hw_state & H_CBWP) >> 16); + buffer_depth = + (unsigned char) ((device_object->host_hw_state & H_CBD) >> 24); + filled_slots = (unsigned char) (write_ptr - read_ptr); + empty_slots = buffer_depth - filled_slots; + + if (filled_slots > buffer_depth) + /* overfolw */ + return -ESLOTS_OVERFLOW; + + return (__s32) empty_slots; +} + +/** + * heci_write_message - write a message to heci device. + * + * @heci_header - header of message + * @write_buffer - message buffer will be write + * @write_length - message size will be write + * + * @return : + * TRUE if success + * FALSE - otherwise. + */ +int heci_write_message(struct iamt_heci_device * device_object, + struct heci_message_header * header, + unsigned char *write_buffer, + unsigned long write_length) +{ + __u32 temp_msg = 0; + unsigned long bytes_written = 0; + char read_ptr, write_ptr; + unsigned char buffer_depth, filled_slots, empty_slots; + unsigned long dw_to_write; + dw_to_write = ((write_length + 3) / 4); + DBG("host_hw_state = 0x%08x.\n", device_object->host_hw_state); + DBG("heci_write_message header=%08x.\n", *((__u32 *) header)); + + read_ptr = (char) ((device_object->host_hw_state & H_CBRP) >> 8); + write_ptr = (char) ((device_object->host_hw_state & H_CBWP) >> 16); + buffer_depth = + (unsigned char) ((device_object->host_hw_state & H_CBD) >> 24); + filled_slots = (unsigned char) (write_ptr - read_ptr); + empty_slots = buffer_depth - filled_slots; + DBG("filled = %hu, empty = %hu.\n", filled_slots, empty_slots); + + if (dw_to_write > empty_slots) { + return FALSE; + } + + write_heci_register(device_object, H_CB_WW, + *((__u32 *) header)); + + while (write_length >= 4) { + write_heci_register(device_object, H_CB_WW, + *(__u32 *) (write_buffer + + bytes_written)); + bytes_written += 4; + write_length -= 4; + } + + if (write_length > 0) { + memcpy(&temp_msg, &write_buffer[bytes_written], write_length); + write_heci_register(device_object, H_CB_WW, temp_msg); + } + + device_object->host_hw_state |= H_IG; + write_heci_register(device_object, H_CSR, + device_object->host_hw_state); + device_object->me_hw_state = + read_heci_register(device_object, ME_CSR_HA); + if ((device_object->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + return FALSE; + + device_object->write_hang = 0; + return TRUE; +} + +/** + * count_full_read_slots - reset host and fw. + * + * @device_object -Device object for our driver + * + * + * @return : + * -1(ESLOTS_OVERFLOW) if overflow + * otherwise filed slots count + */ +__s32 count_full_read_slots(struct iamt_heci_device * device_object) +{ + + char read_ptr, write_ptr; + unsigned char buffer_depth, filled_slots, empty_slots; + + device_object->me_hw_state = read_heci_register(device_object, ME_CSR_HA); + read_ptr = (char) ((device_object->me_hw_state & ME_CBRP_HRA) >> 8); + write_ptr = (char) ((device_object->me_hw_state & ME_CBWP_HRA) >> 16); + buffer_depth = (unsigned char) ((device_object->me_hw_state & ME_CBD_HRA) >> + 24); + filled_slots = (unsigned char) (write_ptr - read_ptr); + empty_slots = buffer_depth - filled_slots; + + if (filled_slots > buffer_depth) + /* overflow */ + return -ESLOTS_OVERFLOW; + + DBG("filled_slots =%08x \n", filled_slots); + return (__s32) filled_slots; +} + +/** + * heci_read_slots - read a message from heci device. + * + * @device_object - device object for our driver + * @buffer - message buffer will be write + * @buffer_length - message size will be read + * + * @return : + * none; + */ +void heci_read_slots(struct iamt_heci_device * device_object, + unsigned char *buffer, unsigned long buffer_length) +{ + __u32 i = 0; + unsigned char temp_buf[sizeof(__u32)]; + + while (buffer_length >= sizeof(__u32)) { + ((__u32 *) buffer)[i] = + read_heci_register(device_object, ME_CB_RW); + DBG("buffer[%d]= %d\n", i, ((__u32 *) buffer)[i]); + i++; + buffer_length -= sizeof(__u32); + } + + if (buffer_length > 0) { + *((__u32 *) & temp_buf) = + read_heci_register(device_object, ME_CB_RW); + memcpy(&buffer[i * 4], temp_buf, buffer_length); + } + + device_object->host_hw_state |= H_IG; + write_heci_register(device_object, H_CSR, + device_object->host_hw_state); + return; +} + +/** + * flow_control_credentials - check flow_control credentials. + * + * @device_object -Device object for our driver + * @file_extension -extension of the file object + * + * @return : + * TRUE if flow_control_credentials >0 + * FALSE - otherwise. + */ +int flow_control_credentials(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + __u8 i; + + if (!device_object->num_heci_me_clients) + return FALSE; + if (file_extension == NULL) + return FALSE; + if (file_extension->flow_control_credentials > 0) + return TRUE; + + for (i = 0; i < device_object->num_heci_me_clients; i++) { + if (device_object->me_clients[i].client_id == + file_extension->me_client_id) { + if (device_object->me_clients[i].flow_control_credentials > 0) { + BUG_ON(device_object->me_clients[i]. + properteis.single_receive_buffer == 0); + return TRUE; + } + return FALSE; + } + } + BUG_ON(1); + return FALSE; +} + +/** + * flow_control_reduce - reduce flow_control . + * + * @device_object -Device object for our driver + * @file_extension -extension of the file object + * + * @return : + * none; + */ +void flow_control_reduce(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + __u8 i; + + if (!device_object->num_heci_me_clients) + return; + + for (i = 0; i < device_object->num_heci_me_clients; i++) { + if (device_object->me_clients[i].client_id == file_extension->me_client_id) { + if (device_object->me_clients[i].properteis.single_receive_buffer != 0) { + BUG_ON(device_object->me_clients[i]. + flow_control_credentials <= 0); + device_object->me_clients[i]. + flow_control_credentials--; + } else { + BUG_ON(file_extension-> + flow_control_credentials <= 0); + file_extension->flow_control_credentials--; + } + return; + } + } + BUG_ON(1); +} + +/** + * heci_send_flow_control - send flow control to fw. + * + * @device_object -Device object for our driver + * @file_extension -extension of the file object + * + * @return : + * TRUE if success + * FALSE - otherwise. + */ +int heci_send_flow_control(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + struct heci_message_header *heci_header; + struct hbm_flow_control *heci_flow_control; + + heci_header = + (struct heci_message_header *) & device_object-> + write_message_buffer[0]; + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_flow_control); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + heci_flow_control = + (struct hbm_flow_control *) & device_object-> + write_message_buffer[1]; + memset(heci_flow_control, 0, sizeof(heci_flow_control)); + heci_flow_control->host_address = file_extension->host_client_id; + heci_flow_control->me_address = file_extension->me_client_id; + heci_flow_control->command.command = FLOW_CONTROL_CMD; + memset(heci_flow_control->reserved, 0, sizeof(heci_flow_control->reserved)); + DBG("sending flow control host client = %d, me client = %d\n", + file_extension->host_client_id, file_extension->me_client_id); + if (!heci_write_message(device_object, heci_header, + (unsigned char *) heci_flow_control, sizeof(struct hbm_flow_control))) + return FALSE; + return TRUE; + +} + +/** + * other_client_is_connecting - check if other + * client with the same client id is connected. + * + * @device_object -Device object for our driver + * @file_extension -extension of the file object + * + * @return : + * TRUE if other client is connected. + * FALSE - otherwise. + */ +int other_client_is_connecting(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + + struct heci_file_private *file_extension_pos = NULL; + struct heci_file_private *file_extension_next = NULL; + list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) { + if ((file_extension_pos->state == HECI_FILE_CONNECTING) + && (file_extension_pos != file_extension) + && file_extension->me_client_id == + file_extension_pos->me_client_id) + return TRUE; + } + return FALSE; +} + +/** + * heci_send_wd - send watch dog message to fw. + * + * @device_object -Device object for our driver + * + * @return : + * TRUE if success + * FALSE - otherwise. + */ +int heci_send_wd(struct iamt_heci_device * device_object) +{ + struct heci_message_header *heci_header; + + heci_header = + (struct heci_message_header *) & device_object-> + write_message_buffer[0]; + heci_header->host_address = + device_object->wd_file_extension.host_client_id; + heci_header->me_address = + device_object->wd_file_extension.me_client_id; + heci_header->message_complete = 1; + heci_header->reserved = 0; + + if (!memcmp(device_object->wd_data, interface_start_wd_params, + HECI_WD_PARAMS_SIZE)) { + heci_header->length = HECI_START_WD_DATA_SIZE; + } else { + BUG_ON(memcmp(device_object->wd_data, interface_stop_wd_params, + HECI_WD_PARAMS_SIZE)); + heci_header->length = HECI_WD_PARAMS_SIZE; + } + + if (!heci_write_message(device_object, heci_header, + device_object->wd_data, + heci_header->length)) + return FALSE; + return TRUE; +} + + +/** + * heci_disconnect - send disconnect message to fw. + * + * @device_object -Device object for our driver + * @file_extension -extension of the file object + * + * @return : + * TRUE if success + * FALSE - otherwise. + */ +int heci_disconnect(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + struct heci_message_header *heci_header; + struct hbm_client_disconnect_request *heci_cli_disconnect; + + heci_header = + (struct heci_message_header *) & device_object-> + write_message_buffer[0]; + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_client_disconnect_request); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + heci_cli_disconnect = + (struct hbm_client_disconnect_request *) & device_object-> + write_message_buffer[1]; + memset(heci_cli_disconnect, 0, sizeof(heci_cli_disconnect)); + heci_cli_disconnect->host_address = file_extension->host_client_id; + heci_cli_disconnect->me_address = file_extension->me_client_id; + heci_cli_disconnect->command.command = CLIENT_DISCONNECT_REQ_CMD; + heci_cli_disconnect->reserved[0] = 0; + + if (TRUE != heci_write_message(device_object, heci_header, + (unsigned char *) heci_cli_disconnect, sizeof(struct hbm_client_disconnect_request))) + return FALSE; + return TRUE; +} + +/** + * heci_connect - send connect message to fw. + * + * @device_object -Device object for our driver + * @file_extension -extension of the file object + * + * @return : + * TRUE if success + * FALSE - otherwise. + */ +int heci_connect(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension) +{ + struct heci_message_header *heci_header; + struct hbm_client_connect_request *heci_cli_connect; + + heci_header = + (struct heci_message_header *) & device_object-> + write_message_buffer[0]; + heci_header->host_address = 0; + heci_header->me_address = 0; + heci_header->length = sizeof(struct hbm_client_connect_request); + heci_header->message_complete = 1; + heci_header->reserved = 0; + + heci_cli_connect = + (struct hbm_client_connect_request *) & device_object-> + write_message_buffer[1]; + heci_cli_connect->host_address = file_extension->host_client_id; + heci_cli_connect->me_address = file_extension->me_client_id; + heci_cli_connect->command.command = CLIENT_CONNECT_REQ_CMD; + heci_cli_connect->reserved = 0; + if (TRUE != heci_write_message(device_object, heci_header, + (unsigned char *) heci_cli_connect, sizeof(struct hbm_client_connect_request))) + return FALSE; + return TRUE; +} --- linux-2.6.27.orig/ubuntu/heci/heci_main.c +++ linux-2.6.27/ubuntu/heci/heci_main.c @@ -0,0 +1,1444 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcompat.h" +#include "heci.h" +#include "heci_interface.h" +#include "version.h" + + +#define HECI_READ_TIMEOUT 45 + +#define MAX_OPEN_HANDLE_COUNT 253 +/** + * heci driver strings + */ +char heci_driver_name[] = "heci"; +char heci_driver_string[] = "Intel(R) AMT Management Interface"; +char heci_driver_version[] = DRIVER_VERSION; +char heci_copyright[] = "Copyright (c) 2003 - 2007 Intel Corporation."; + + +#ifdef HECI_DEBUG +DEF_PARM(int, debug, 1, 0644, "Debug enabled or not"); +#else +DEF_PARM(int, debug, 0, 0644, "Debug enabled or not"); +#endif + +/* heci char device for registration */ +static struct cdev heci_cdev = { + .kobj = {.name = "heci", }, + .owner = THIS_MODULE, +}; + +/* iamt legacy char device for registration */ +static struct cdev iamt_legacy_cdev = { + .kobj = {.name = "iamt_legacy", }, + .owner = THIS_MODULE, +}; + +/* major number for device */ +static int heci_major; +/* The device pointer */ +static struct pci_dev *heci_device; + +/* heci_pci_tbl - PCI Device ID Table */ +static struct pci_device_id heci_pci_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID1)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID2)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID3)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID4)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID5)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID6)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID7)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID8)}, + /* required last entry */ + {0, } +}; + +MODULE_DEVICE_TABLE(pci, heci_pci_tbl); + +/** + * Local Function Prototypes + */ +static int __init heci_init_module(void); +static void __exit heci_exit_module(void); +static int __devinit heci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void __devexit heci_remove(struct pci_dev *pdev); +static int heci_open(struct inode *inode, struct file *file); +static int heci_release(struct inode *inode, struct file *file); +static unsigned int heci_legacy_poll(struct file *file, poll_table * wait); +static ssize_t heci_read(struct file *file, char __user * ubuf, + size_t length, loff_t * offset); +static int heci_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long data); +static ssize_t heci_write(struct file *file, const char __user * ubuf, + size_t length, loff_t * offset); +static unsigned int heci_poll(struct file *file, poll_table * wait); +#ifdef CONFIG_PM +static int heci_suspend(struct pci_dev* pdev, pm_message_t state); +static int heci_resume(struct pci_dev* pdev); +static __u16 g_sus_wd_timeout; +#endif +/** + * PCI driver structure + */ +static struct pci_driver heci_driver = { + .name = heci_driver_name, + .id_table = heci_pci_tbl, + .probe = heci_probe, + .remove = heci_remove, + SHUTDOWN_METHOD(heci_remove) +#ifdef CONFIG_PM + .suspend = heci_suspend, + .resume = heci_resume +#endif +}; + +/** + * file operations structure will be use heci char device. + */ +static struct file_operations heci_fops = { + .owner = THIS_MODULE, + .read = heci_read, + .ioctl = heci_ioctl, + .open = heci_open, + .release = heci_release, + .write = heci_write, + .poll = heci_poll, +}; + +/** + * file operations structure will be use iamt legacy char device. + */ +static struct file_operations iamt_legacy_fops = { + .owner = THIS_MODULE, + .ioctl = heci_ioctl, + .open = heci_open, + .release = heci_release, + .poll = heci_legacy_poll, +}; + +/** + * For kernels withouth PCI shutdown support reboot notifier is essential + */ +HECI_REBOOT_NOTIFIER(heci_reboot_notifier, heci_driver, heci_remove) + +/** + * Set up the cdev structure for heci device. + * @dev - char device struct + * @minor - minor number for registration char device + * @fops - file operations structure + * @return : + * 0 on success, + * negative on failure + */ +static int heci_registration_cdev(struct cdev *dev, int minor, + struct file_operations *fops) +{ + int ret = ESUCCESS, devno = MKDEV(heci_major, minor); + + cdev_init(dev, fops); + dev->owner = THIS_MODULE; + dev->ops = fops; + ret = cdev_add(dev, devno, 1); + /* Fail gracefully if need be */ + if (ret) { + kobject_put(&dev->kobj); + HECI_ERR("Error %d registering heci device %d", ret, minor); + } + return ret; +} + + + +/** + * heci_init_module - Driver Registration Routine + * + * heci_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + * + * @return : + * 0 on success, + * negative on failure + */ +static int __init heci_init_module(void) +{ + int ret = ESUCCESS; + dev_t dev; + HECI_INFO("%s - version %s\n", heci_driver_string, heci_driver_version); + HECI_INFO("%s\n", heci_copyright); + + /* init pci module */ + ret = pci_register_driver(&heci_driver); + if (ret < 0) + goto end; + + REGISTER_REBOOT_NOTIFIER(heci_reboot_notifier); + /* registration char devices */ + ret = alloc_chrdev_region(&dev, 0, MINORS_COUNT, "heci"); + + heci_major = MAJOR(dev); + /* Now registration two cdevs. */ + ret = heci_registration_cdev(&iamt_legacy_cdev, LEGACY_MINOR_NUMBER, + &iamt_legacy_fops); + if (ret) + goto unregister; + + ret = heci_registration_cdev(&heci_cdev, HECI_MINOR_NUMBER, + &heci_fops); + if (ret) { + cdev_del(&iamt_legacy_cdev); + goto unregister; + } + return ret; + +unregister: + pci_unregister_driver(&heci_driver); + unregister_chrdev_region(MKDEV(heci_major, 0), MINORS_COUNT); +end: + return ret; +} + +module_init(heci_init_module); + + +/** + * heci_exit_module - Driver Exit Cleanup Routine + * + * heci_exit_module is called just before the driver is removed + * from memory. + * + * @return : + * none; + */ + +static void __exit heci_exit_module(void) +{ + UNREGISTER_REBOOT_NOTIFIER(heci_reboot_notifier); + pci_unregister_driver(&heci_driver); + /* Now unregister two cdevs. */ + cdev_del(&iamt_legacy_cdev); + cdev_del(&heci_cdev); + unregister_chrdev_region(MKDEV(heci_major, 0), MINORS_COUNT); +} + +module_exit(heci_exit_module); + + +/** + * heci_probe - Device Initialization Routine + * + * @pdev: PCI device information struct + * @ent: entry in kcs_pci_tbl + * + * @return : + * 0 on success, + * negative on failure + */ +static int __devinit heci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct iamt_heci_device *device = NULL; + int i, err = 0; + if (heci_device) { + err = -EEXIST; + goto end; + } + /* enable pci device */ + err = pci_enable_device(pdev); + if (err) { + HECI_ERR("Failed to enable pci device\n"); + goto end; + } + /* set PCI host mastering */ + pci_set_master(pdev); + /* pci request regions for heci driver */ + err = pci_request_regions(pdev, heci_driver_name); + if (err) { + HECI_ERR("Failed to get pci regions\n"); + goto disable_device; + } + /* allocates and initializes the heci device structure */ + device = init_heci_device(pdev); + if (!device) { + err = -ENOMEM; + goto release_regions; + } + /* mapping IO device memory */ + for (i = BAR_0; i <= BAR_5; i++) { + if (pci_resource_len(pdev, i) == 0) { + continue; + } + if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { + HECI_ERR("heci has an IO ports.\n"); + goto free_device; + } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { + if (device->mem_base) { + HECI_ERR("Too many mem addresses.\n"); + goto free_device; + } + device->mem_base = pci_resource_start(pdev, i); + device->mem_length = pci_resource_len(pdev, i); + } + } + if (!device->mem_base) { + HECI_ERR("No address to use.\n"); + err = -ENODEV; + goto free_device; + } + device->mem_addr = ioremap_nocache(device->mem_base, device->mem_length); + if (!device->mem_addr) { + HECI_ERR(" Remap IO device memory failure.\n"); + err = -ENOMEM; + goto free_device; + } + /* request and enable interrupt */ + device->irq = pdev->irq; + err = request_irq(device->irq, heci_isr_interrupt, IRQF_SHARED, + heci_driver_name, device); + if (err) { + HECI_ERR("Request_irq failure. irq = %d \n", device->irq); + goto unmap_memory; + } + + if (heci_hw_init(device)) { + HECI_ERR("init hw failure.\n"); + err = -ENODEV; + goto release_irq; + } + init_timer(&device->wd_timer); + heci_initialize_clients(device); + if (device->heci_state != HECI_ENABLED) { + err = -ENODEV; + goto release_hw; + } + spin_lock_bh(&device->device_lock); + heci_device = pdev; + pci_set_drvdata(pdev, device); + spin_unlock_bh(&device->device_lock); + if (device->wd_timeout) { + mod_timer(&device->wd_timer, jiffies); + } +#ifdef CONFIG_PM + g_sus_wd_timeout = 0; +#endif + HECI_INFO("heci driver initialization successful.\n"); + return ESUCCESS; + +release_hw: + /* disable interrupts */ + device->host_hw_state = read_heci_register(device, H_CSR); + device->host_hw_state &= ~H_IE; + /* acknowledge interrupt and stop interupts */ + write_heci_register(device, H_CSR, device->host_hw_state); + + del_timer_sync(&device->wd_timer); + + + flush_scheduled_work(); + +release_irq: + free_irq(pdev->irq, device); +unmap_memory: + if (device->mem_addr) + iounmap(device->mem_addr); +free_device: + kfree(device); +release_regions: + pci_release_regions(pdev); +disable_device: + pci_disable_device(pdev); +end: + HECI_ERR("heci driver initialization failed.\n"); + return err; +} + +/** + * heci_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * heci_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. + * + * @return : + * none; + */ +static void __devexit heci_remove(struct pci_dev *pdev) +{ + struct iamt_heci_device *device = pci_get_drvdata(pdev); + int err = 0; + + if (heci_device != pdev) + return; + del_timer_sync(&device->wd_timer); + if (device->wd_file_extension.state == HECI_FILE_CONNECTED + && device->wd_timeout) { + spin_lock_bh(&device->device_lock); + device->wd_timeout = 0; + device->wd_due_counter = 0; + memcpy(device->wd_data, stop_wd_params, HECI_WD_PARAMS_SIZE); + device->stop = TRUE; + if (device->host_buffer_is_empty && + flow_control_credentials(device, &device->wd_file_extension)) { + device->host_buffer_is_empty = FALSE; + + if (!heci_send_wd(device)) + DBG("Send stop WD failed\n"); + else + flow_control_reduce(device, &device->wd_file_extension); + device->wd_pending = FALSE; + + } else { + device->wd_pending = TRUE; + } + spin_unlock_bh(&device->device_lock); + device->wd_stoped = FALSE; + + err = + wait_event_interruptible_timeout(device->wait_stop_wd, + (TRUE == + device->wd_stoped), + 10 * HZ); + if (!device->wd_stoped) + DBG("stop wd failed to complete.\n"); + else + DBG("stop wd complete.\n"); + } + + heci_device = NULL; + if (device->legacy_file_extension.status == HECI_FILE_CONNECTED) { + device->legacy_file_extension.status = HECI_FILE_DISCONNECTING; + heci_disconnect_host_client(device, + &device->legacy_file_extension); + } + if (device->wd_file_extension.status == HECI_FILE_CONNECTED) { + device->wd_file_extension.status = HECI_FILE_DISCONNECTING; + heci_disconnect_host_client(device, + &device->wd_file_extension); + } + /* remove entry if already in list */ + DBG("list del legacy and wd file list.\n"); + heci_remove_client_from_file_list(device, device->wd_file_extension. + host_client_id); + heci_remove_client_from_file_list(device, device->legacy_file_extension. + host_client_id); + flush_scheduled_work(); + /* disable interrupts */ + device->host_hw_state &= ~H_IE; + /* acknowledge interrupt and stop interupts */ + write_heci_register(device, H_CSR, device->host_hw_state); + free_irq(pdev->irq, device); + pci_set_drvdata(pdev, NULL); + + if (device->mem_addr) + iounmap(device->mem_addr); + kfree(device); + + pci_release_regions(pdev); + pci_disable_device(pdev); +} +/** + * heci_clear_list - remove all callbacks associated with file + * from heci_cb_list + * @file: file informtion struct + * @heci_cb_list: callbacks list + * heci_clear_list is called to clear resources associated with file + * when application calls close function or Ctrl-C was pressed + * + * @return :true if callback removed from the list, false otherwise + */ +static int heci_clear_list(struct iamt_heci_device *device, struct file *file, struct list_head *heci_cb_list) { + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + struct file *file_temp = NULL; + int return_status = FALSE; + + /* list all list member */ + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, heci_cb_list, cb_list){ + file_temp = (struct file *)kernel_priv_cb_pos->file_object; + /* check if list member associated with a file */ + if (file_temp == file) { + /* remove member from the list */ + list_del(&kernel_priv_cb_pos->cb_list); + /* check if cb equal to current legacy cb */ + if (device->legacy_current_cb == kernel_priv_cb_pos) { + device->legacy_current_cb = NULL; + /* send flow control to legacy client */ + heci_send_flow_control(device, &device->legacy_file_extension); + } + /* free all allocated buffers */ + kfree (kernel_priv_cb_pos->request_buffer.data); + kernel_priv_cb_pos->request_buffer.data = NULL; + kfree (kernel_priv_cb_pos->response_buffer.data); + kernel_priv_cb_pos->response_buffer.data = NULL; + kfree(kernel_priv_cb_pos); + return_status = TRUE; + } + } + return return_status; +} + +/** + * heci_clear_lists - remove all callbacks associated with file + * @device: device informtion struct + * @file: file informtion struct + * heci_clear_lists is called to clear resources associated with file + * when application calls close function or Ctrl-C was pressed + * + * @return :true if callback removed from the list, false otherwise + */ +static int heci_clear_lists(struct iamt_heci_device *device, struct file *file) +{ + int return_status = FALSE; + + /* remove callbacks associated with a file */ + heci_clear_list(device, file, &device->pthi_cmd_list.heci_cb.cb_list); + if (heci_clear_list(device, file, &device->pthi_read_complete_list.heci_cb.cb_list)) + return_status = TRUE; + heci_clear_list(device, file, &device->control_read_list.heci_cb.cb_list); + if (heci_clear_list(device, file, &device->control_write_list.heci_cb.cb_list)) + return_status = TRUE; + if (heci_clear_list(device, file, &device->write_waiting_list.heci_cb.cb_list)) + return_status = TRUE; + if (heci_clear_list(device, file, &device->write_list.heci_cb.cb_list)) + return_status = TRUE; + /* check if legacy_current_cb not NULL */ + if (device->legacy_current_cb && (!return_status)) { + /* check file and legacy current cb association */ + if (device->legacy_current_cb->file_object == file) { + /* remove cb */ + kfree (device->legacy_current_cb->request_buffer.data); + device->legacy_current_cb->request_buffer.data = NULL; + kfree (device->legacy_current_cb->response_buffer.data); + device->legacy_current_cb->response_buffer.data = NULL; + kfree(device->legacy_current_cb); + device->legacy_current_cb = NULL; + return_status = TRUE; + } + } + return return_status; +} + +/** + * heci_open - the open function + */ +static int heci_open(struct inode *inode, struct file *file) +{ + struct heci_file_private *file_extension = NULL; + int if_num = MINOR(inode->i_rdev); + struct iamt_heci_device *device = NULL; + if (!heci_device) + return -ENODEV; + device = pci_get_drvdata(heci_device); + if (((if_num != LEGACY_MINOR_NUMBER) + && (if_num != HECI_MINOR_NUMBER)) || (!device)) + return -ENODEV; + + if (if_num != LEGACY_MINOR_NUMBER) { + file_extension = alloc_priv(file); + if (!file_extension) + return -ENOMEM; + } else { + file->private_data = + (void *) &device->legacy_file_extension; + return ESUCCESS; + } + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED) { + spin_unlock_bh(&device->device_lock); + kfree(file_extension); + file_extension = NULL; + return -ENODEV; + } + if (device->open_handle_count >= MAX_OPEN_HANDLE_COUNT) { + spin_unlock_bh(&device->device_lock); + kfree(file_extension); + file_extension = NULL; + return -ENFILE; + }; + device->open_handle_count++; + list_add_tail(&file_extension->link, &device->file_list); + while ((device->heci_host_clients[device->current_host_client_id / 8] + & (1 << (device->current_host_client_id % 8))) != 0) { + device->current_host_client_id++; /* allow overflow */ + DBG("current_host_client_id = %d\n", device->current_host_client_id); + DBG("device->open_handle_count = %lu\n", device->open_handle_count); + } + DBG("current_host_client_id = %d\n", device->current_host_client_id); + file_extension->host_client_id = device->current_host_client_id; + device->heci_host_clients[file_extension->host_client_id / 8] |= + (1 << (file_extension->host_client_id % 8)); + spin_unlock_bh(&device->device_lock); + spin_lock(&file_extension->file_lock); + file_extension->state = HECI_FILE_INITIALIZING; + file_extension->sm_state = 0; + + file->private_data = file_extension; + spin_unlock(&file_extension->file_lock); + + return ESUCCESS; +} + +/** + * heci_release - the release function + */ +static int heci_release(struct inode *inode, struct file *file) +{ + int return_status = ESUCCESS; + int if_num = MINOR(inode->i_rdev); + struct heci_file_private *file_extension = file->private_data; + struct heci_cb_private *kernel_priv_cb = NULL; + struct iamt_heci_device *device = NULL; + + if (!heci_device) + return -ENODEV; + + device = pci_get_drvdata(heci_device); + if (((if_num != LEGACY_MINOR_NUMBER) + && (if_num != HECI_MINOR_NUMBER)) || (!device) + || (!file_extension)) + return -ENODEV; + if (file_extension != &device->legacy_file_extension) { + + spin_lock(&file_extension->file_lock); + if (file_extension->state == HECI_FILE_CONNECTED) { + file_extension->state = HECI_FILE_DISCONNECTING; + spin_unlock(&file_extension->file_lock); + DBG("disconnecting client host client = %d, ME client = %d\n", + file_extension->host_client_id, + file_extension->me_client_id); + return_status = + heci_disconnect_host_client(device, + file_extension); + spin_lock(&file_extension->file_lock); + } + spin_lock_bh(&device->device_lock); + heci_flush_queues(device, file_extension); + DBG("remove client host client = %d, ME client = %d\n", + file_extension->host_client_id, + file_extension->me_client_id); + device->heci_host_clients[file_extension->host_client_id / 8] &= ~(1 << (file_extension->host_client_id % 8)); + device->open_handle_count--; + heci_remove_client_from_file_list(device, file_extension->host_client_id); + spin_unlock_bh(&device->device_lock); + + /* free read cb */ + if (file_extension->read_cb != NULL) { + spin_unlock(&file_extension->file_lock); + kernel_priv_cb = file_extension->read_cb; + kfree(kernel_priv_cb->response_buffer.data); + kernel_priv_cb->response_buffer.data = NULL; + kfree(kernel_priv_cb); + kernel_priv_cb = NULL; + + file_extension->read_cb = NULL; + spin_lock(&file_extension->file_lock); + } + spin_unlock(&file_extension->file_lock); + kfree(file_extension); + file->private_data = NULL; + } else { + spin_lock_bh(&device->device_lock); + if (if_num != LEGACY_MINOR_NUMBER) { + device->open_handle_count--; + } + if (device->legacy_file_object == file + && device->legacy_state != HECI_LEGACY_IDLE) { + + DBG("pthi canceled legacy state %d\n", + device->legacy_state); + device->legacy_canceled = TRUE; + if (device->legacy_state == HECI_LEGACY_READ_COMPLETE) { + DBG("run next pthi legacy cb\n"); + run_next_legacy_cmd(device); + } + } + + if (heci_clear_lists(device, file)) { + device->legacy_state = HECI_LEGACY_IDLE; + } + spin_unlock_bh(&device->device_lock); + } + return return_status; +} + + +static struct heci_cb_private *find_read_list_entry(struct iamt_heci_device* device, + struct heci_file_private *file_extension) +{ + struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + struct heci_file_private *file_extension_list_temp = NULL; + + if (device->read_list.status == ESUCCESS + && !list_empty(&device->read_list.heci_cb.cb_list)) { + DBG("remove read_list CB \n"); + list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device->read_list.heci_cb.cb_list, cb_list){ + file_extension_list_temp = + (struct heci_file_private *) + kernel_priv_cb_pos->file_private; + if (file_extension_list_temp) { + if ((file_extension->host_client_id == file_extension_list_temp->host_client_id) + && (file_extension->me_client_id == file_extension_list_temp->me_client_id)) + return kernel_priv_cb_pos; + } + } + } + return NULL; +} +/** + * heci_read - the read client message function. + */ +static ssize_t heci_read(struct file *file, char __user * ubuf, + size_t length, loff_t * offset) +{ + int i; + int return_status = ESUCCESS, err = ESUCCESS; + int if_num = MINOR((file->f_dentry->d_inode->i_rdev)); + struct heci_file_private *file_extension = file->private_data; + struct heci_cb_private *kernel_priv_cb_pos = NULL; + struct heci_cb_private *kernel_priv_cb = NULL; + struct iamt_heci_device *device = NULL; + + if (!heci_device) + return -ENODEV; + + device = pci_get_drvdata(heci_device); + if ((if_num != HECI_MINOR_NUMBER) || (!device) || (!file_extension)) + return -ENODEV; + + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED) { + spin_unlock_bh(&device->device_lock); + return -ENODEV; + } + spin_unlock_bh(&device->device_lock); + if (!file_extension) + return -ENODEV; + + spin_lock(&file_extension->file_lock); + if((file_extension->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) { + spin_unlock(&file_extension->file_lock); + /* Do not allow to read watchdog client */ + for (i = 0; i < device->num_heci_me_clients; i++) { + if (0 == memcmp(&heci_wd_guid, &device->me_clients[i].properteis.protocol_name, sizeof(struct guid))) { + if (file_extension->me_client_id == device->me_clients[i].client_id) + return -EBADF; + } + } + } else { + file_extension->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT; + spin_unlock(&file_extension->file_lock); + } + if (file_extension == &device->legacy_file_extension) { + return_status = pthi_read(device, if_num, file, ubuf, length, offset); + goto out; + } + + if (file_extension->read_cb && file_extension->read_cb->information > *offset) { + kernel_priv_cb = file_extension->read_cb; + goto copy_buffer; + } + else if (file_extension->read_cb && file_extension->read_cb->information > 0 && + file_extension->read_cb->information <= *offset) { + kernel_priv_cb = file_extension->read_cb; + return_status = 0; + goto free; + } + else if ((!file_extension->read_cb || file_extension->read_cb->information == 0) && + *offset > 0) { + *offset = 0; /*Offset needs to be cleaned for contingous reads*/ + return_status = 0; + goto out; + } + + spin_lock(&file_extension->read_io_lock); + err = heci_start_read(device, if_num, file_extension); + if (err != ESUCCESS && err != -EBUSY) { + DBG("heci start read failure with status = %d\n", err); + spin_unlock(&file_extension->read_io_lock); + return_status = err; + goto out; + } + if (HECI_READ_COMPLETE != file_extension->reading_state && !waitqueue_active (&file_extension->rx_wait)) { + if (file->f_flags & O_NONBLOCK) { + return_status = -EAGAIN; + spin_unlock(&file_extension->read_io_lock); + goto out; + } + spin_unlock(&file_extension->read_io_lock); + + if (wait_event_interruptible(file_extension->rx_wait, + (HECI_READ_COMPLETE == file_extension->reading_state || + HECI_FILE_INITIALIZING == file_extension->state || + HECI_FILE_DISCONNECTED == file_extension->state || + HECI_FILE_DISCONNECTING == file_extension->state))) { + if (signal_pending (current)) { + return_status = -EINTR; + goto out; + } + return -ERESTARTSYS; + } + + if (HECI_FILE_INITIALIZING == file_extension->state || + HECI_FILE_DISCONNECTED == file_extension->state || + HECI_FILE_DISCONNECTING == file_extension->state) { + return_status = -EBUSY; + goto out; + } + spin_lock(&file_extension->read_io_lock); + } + + kernel_priv_cb = file_extension->read_cb; + + if (!kernel_priv_cb) { + spin_unlock(&file_extension->read_io_lock); + return -ENODEV; + } + if (file_extension->reading_state != HECI_READ_COMPLETE) { + spin_unlock(&file_extension->read_io_lock); + return ESUCCESS; + } + spin_unlock(&file_extension->read_io_lock); + /* now copy the data to user space */ +copy_buffer: + DBG("kernel_priv_cb->response_buffer size - %d\n", kernel_priv_cb->response_buffer.size); + DBG("kernel_priv_cb->information - %lu\n", kernel_priv_cb->information); + if (length == 0 || ubuf == NULL || *offset > kernel_priv_cb->information) { + return_status = -EMSGSIZE; + goto free; + } + + /* length is being turncated to PAGE_SIZE, however, information size may be longer */ + length = (length < (kernel_priv_cb->information - *offset) ? + length : (kernel_priv_cb->information - *offset)); + + if (copy_to_user(ubuf, kernel_priv_cb->response_buffer.data + *offset, length)) { + return_status = -EFAULT; + goto free; + } + else { + return_status = length; + *offset += length; + if ((unsigned long)*offset < kernel_priv_cb->information) { + goto out; + } + } +free: + spin_lock_bh(&device->device_lock); + kernel_priv_cb_pos = find_read_list_entry(device, file_extension); + /* Remove entry from read list */ + if (kernel_priv_cb_pos != NULL) + list_del(&kernel_priv_cb_pos->cb_list); + spin_unlock_bh(&device->device_lock); + kfree(kernel_priv_cb->response_buffer.data); + kernel_priv_cb->response_buffer.data = NULL; + kfree(kernel_priv_cb); + kernel_priv_cb = NULL; + spin_lock(&file_extension->read_io_lock); + file_extension->reading_state = HECI_IDLE; + file_extension->read_cb = NULL; + file_extension->read_pending = FALSE; + spin_unlock(&file_extension->read_io_lock); +out: DBG("end heci read return_status= %d\n", return_status); + return return_status; +} + +/** + * heci_write - the write function. + */ +static ssize_t heci_write(struct file *file, const char __user * ubuf, + size_t length, loff_t * offset) +{ + int return_status = ESUCCESS; + __u8 i; + int if_num = MINOR((file->f_dentry->d_inode->i_rdev)); + struct heci_file_private *file_extension = file->private_data; + struct heci_cb_private *priv_write_cb = NULL; + struct heci_message_header heci_header; + struct iamt_heci_device *device = NULL; + unsigned long currtime = get_seconds(); + + if (!heci_device) + return -ENODEV; + device = pci_get_drvdata(heci_device); + + if ((if_num != HECI_MINOR_NUMBER) || (!device) || (!file_extension)) + return -ENODEV; + spin_lock_bh(&device->device_lock); + + if (device->heci_state != HECI_ENABLED) { + spin_unlock_bh(&device->device_lock); + return -ENODEV; + } + if (file_extension == &device->legacy_file_extension) { + priv_write_cb = find_pthi_read_list_entry(device, file, file_extension); + if ((priv_write_cb && currtime - priv_write_cb->read_time > LEGACY_READ_TIMER) || + (priv_write_cb && file_extension->reading_state == HECI_READ_COMPLETE)) { + *offset = 0; + list_del(&priv_write_cb->cb_list); + kfree(priv_write_cb->request_buffer.data); + kfree(priv_write_cb->response_buffer.data); + kfree(priv_write_cb); + } + } + + //free entry used in read + if (file_extension->reading_state == HECI_READ_COMPLETE) + { + *offset = 0; + priv_write_cb = find_read_list_entry(device, file_extension); + if ( priv_write_cb != NULL) { + list_del(&priv_write_cb->cb_list); + kfree(priv_write_cb->response_buffer.data); + priv_write_cb->response_buffer.data = NULL; + kfree(priv_write_cb); + priv_write_cb = NULL; + spin_lock(&file_extension->read_io_lock); + file_extension->reading_state = HECI_IDLE; + file_extension->read_cb = NULL; + file_extension->read_pending = FALSE; + spin_unlock(&file_extension->read_io_lock); + } + } + else if (file_extension->reading_state == HECI_IDLE && + file_extension->read_pending == FALSE){ + *offset = 0; + } + + spin_unlock_bh(&device->device_lock); + + priv_write_cb = kmalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!priv_write_cb) + return -ENOMEM; + spin_lock(&file_extension->file_lock); + priv_write_cb->request_buffer.data = NULL; + priv_write_cb->response_buffer.data = NULL; + priv_write_cb->file_object = file; + priv_write_cb->file_private = file_extension; + spin_unlock(&file_extension->file_lock); + priv_write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL); + if (!priv_write_cb->request_buffer.data) { + kfree(priv_write_cb); + return -ENOMEM; + } + DBG("length =%d\n", (int) length); + + if (copy_from_user(priv_write_cb->request_buffer.data, + ubuf, length)) { + return_status = -EFAULT; + goto fail; + } + + spin_lock(&file_extension->file_lock); + file_extension->sm_state = 0; + if (length == 4 && + ((memcmp(heci_wd_state_independence_msg[0], ubuf, 4) == 0) || + (memcmp(heci_wd_state_independence_msg[1], ubuf, 4) == 0))) { + file_extension->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT; + } + spin_unlock(&file_extension->file_lock); + + INIT_LIST_HEAD(&priv_write_cb->cb_list); + if (file_extension == &device->legacy_file_extension) { + priv_write_cb->response_buffer.data = + kmalloc(LEGACY_MTU, GFP_KERNEL); + if (!priv_write_cb->response_buffer.data) { + return_status = -ENOMEM; + goto fail; + } + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED) { + spin_unlock_bh(&device->device_lock); + return_status = -ENODEV; + goto fail; + } + for (i = 0; i < device->num_heci_me_clients; i++) { + if (device->me_clients[i].client_id == + device->legacy_file_extension.me_client_id) + break; + } + + BUG_ON(device->me_clients[i].client_id != + file_extension->me_client_id); + if ((i == device->num_heci_me_clients) + || (device->me_clients[i].client_id != device->legacy_file_extension.me_client_id)) { + spin_unlock_bh(&device->device_lock); + return_status = -ENODEV; + goto fail; + } else if (length > device->me_clients[i].properteis.max_message_length || length <= 0) { + spin_unlock_bh(&device->device_lock); + return_status = -EMSGSIZE; + goto fail; + } + + + priv_write_cb->response_buffer.size = LEGACY_MTU; + priv_write_cb->major_file_operations = HECI_IOCTL; + priv_write_cb->information = 0; + priv_write_cb->request_buffer.size = length; + if (device->legacy_file_extension.state != HECI_FILE_CONNECTED) { + spin_unlock_bh(&device->device_lock); + return_status = -ENODEV; + goto fail; + } + + if (!list_empty(&device->pthi_cmd_list.heci_cb.cb_list) + || device->legacy_state != HECI_LEGACY_IDLE) { + DBG("pthi_state = %d\n", (int) device->legacy_state); + DBG("add PTHI cb to pthi cmd waiting list\n"); + list_add_tail(&priv_write_cb->cb_list, + &device->pthi_cmd_list.heci_cb. + cb_list); + return_status = length; + } else { + DBG("call pthi write"); + return_status = pthi_write(device, priv_write_cb); + + if (ESUCCESS != return_status) { + DBG("pthi write failed with status = %d\n", + return_status); + spin_unlock_bh(&device->device_lock); + goto fail; + }; + return_status = length; + } + spin_unlock_bh(&device->device_lock); + return return_status; + } + + priv_write_cb->major_file_operations = HECI_WRITE; + /* make sure information is zero before we start */ + + priv_write_cb->information = 0; + priv_write_cb->request_buffer.size = length; + + spin_lock(&file_extension->write_io_lock); + DBG("host client = %d, ME client = %d\n", + file_extension->host_client_id, file_extension->me_client_id); + if (file_extension->state != HECI_FILE_CONNECTED) { + return_status = -ENODEV; + DBG("host client = %d, is not connected to ME client = %d", + file_extension->host_client_id, + file_extension->me_client_id); + + goto unlock; + } + for (i = 0; i < device->num_heci_me_clients; i++) { + if (device->me_clients[i].client_id == + file_extension->me_client_id) + break; + } + BUG_ON(device->me_clients[i].client_id != file_extension->me_client_id); + if (i == device->num_heci_me_clients) { + return_status = -ENODEV; + goto unlock; + } + if (length > device->me_clients[i].properteis.max_message_length + || length <= 0) { + return_status = -EINVAL; + goto unlock; + } + priv_write_cb->file_private = file_extension; + + spin_lock_bh(&device->device_lock); + if (flow_control_credentials(device, file_extension) && + device->host_buffer_is_empty) { + spin_unlock_bh(&device->device_lock); + device->host_buffer_is_empty = FALSE; + if (length > ((((device->host_hw_state & H_CBD) >> 24) * sizeof(__u32)) - sizeof(struct heci_message_header))) { + heci_header.length = (((device->host_hw_state & H_CBD) >> 24) + * sizeof(__u32)) - sizeof(struct heci_message_header); + heci_header.message_complete = 0; + } else { + heci_header.length = length; + heci_header.message_complete = 1; + } + heci_header.host_address = file_extension->host_client_id; + heci_header.me_address = file_extension->me_client_id; + heci_header.reserved = 0; + DBG("call heci_write_message header=%08x.\n", + *((__u32 *) & heci_header)); + spin_unlock(&file_extension->write_io_lock); + /* protect heci low level write */ + spin_lock_bh(&device->device_lock); + if (!heci_write_message(device, &heci_header, (unsigned char *) (priv_write_cb->request_buffer.data), + heci_header.length)) { + spin_unlock_bh(&device->device_lock); + kfree(priv_write_cb->request_buffer.data); + priv_write_cb->request_buffer.data = NULL; + kfree(priv_write_cb); + return_status = -ENODEV; + priv_write_cb->information = 0; + return return_status; + } + file_extension->writing_state = HECI_WRITING; + priv_write_cb->information = heci_header.length; + if (heci_header.message_complete) { + flow_control_reduce(device, file_extension); + list_add_tail(&priv_write_cb->cb_list, + &device->write_waiting_list.heci_cb. + cb_list); + } else { + list_add_tail(&priv_write_cb->cb_list, + &device->write_list.heci_cb.cb_list); + } + spin_unlock_bh(&device->device_lock); + + } else { + + spin_unlock_bh(&device->device_lock); + priv_write_cb->information = 0; + file_extension->writing_state = HECI_WRITING; + spin_unlock(&file_extension->write_io_lock); + list_add_tail(&priv_write_cb->cb_list, + &device->write_list.heci_cb.cb_list); + } + return length; + +unlock: + spin_unlock(&file_extension->write_io_lock); +fail: + kfree(priv_write_cb->request_buffer.data); + priv_write_cb->request_buffer.data = NULL; + kfree(priv_write_cb->response_buffer.data); + priv_write_cb->response_buffer.data = NULL; + kfree(priv_write_cb); + return return_status; + +} + +/** + * heci_ioctl - the IOCTL function + */ +static int heci_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long data) +{ + + int return_status = ESUCCESS; + int if_num = MINOR(inode->i_rdev); + struct heci_file_private *file_extension = file->private_data; + struct heci_message_data *u_msg = (struct heci_message_data *) data; /* in user space */ + struct heci_message_data k_msg; /* all in kernel on the stack */ + struct iamt_heci_device *device = NULL; + + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!heci_device) + return -ENODEV; + device = pci_get_drvdata(heci_device); + if (((if_num != LEGACY_MINOR_NUMBER) + && (if_num != HECI_MINOR_NUMBER)) || (!device) + || (!file_extension)) + return -ENODEV; + if (device->heci_state != HECI_ENABLED) + return -ENODEV; + /* first copy from user all data needed */ + if (copy_from_user(&k_msg, u_msg, sizeof(k_msg))) { + DBG("first copy from user all data needed filed\n"); + return -EFAULT; + } + DBG("user message size is %d\n", k_msg.size); + + switch (cmd) { + case IOCTL_HECI_GET_VERSION: + DBG(": IOCTL_HECI_GET_VERSION\n"); + return_status = + heci_ioctl_get_version(device, if_num, u_msg, k_msg, + file_extension); + break; + case IOCTL_HECI_CONNECT_CLIENT: + DBG(": IOCTL_HECI_CONNECT_CLIENT.\n"); + return_status = + heci_ioctl_connect_client(device, if_num, u_msg, k_msg, + file); + break; + case IOCTL_HECI_WD: + DBG(": IOCTL_HECI_WD.\n"); + return_status = + heci_ioctl_wd(device, if_num, k_msg, file_extension); + break; + case IOCTL_HECI_BYPASS_WD: + DBG(":IOCTL_HECI_BYPASS_WD.\n"); + return_status = + heci_ioctl_bypass_wd(device,if_num,k_msg,file_extension); + break; + case IAMT_KCS_SEND_MESSAGE_COMMAND: + DBG(": IAMT_KCS_SEND_MESSAGE_COMMAND.\n"); + return_status = + legacy_ioctl_send_message(device, if_num, k_msg, file); + break; + case IAMT_KCS_RECEIVE_MESSAGE_COMMAND: + DBG(": IAMT_KCS_RECEIVE_MESSAGE_COMMAND.\n"); + return_status = + legacy_ioctl_receive_message(device, if_num, u_msg, + k_msg, file); + break; + + default: + return_status = -EINVAL; + break; + } + return return_status; +} + +/** + * heci_legacy_poll - the poll function + */ +static unsigned int heci_legacy_poll(struct file *file, poll_table * wait) +{ + int if_num = MINOR((file->f_dentry->d_inode->i_rdev)); + unsigned int mask = 0; + struct iamt_heci_device *device = NULL; + struct heci_file_private *file_extension = file->private_data; + + + if (!heci_device || !file_extension) + return mask; + + device = pci_get_drvdata(heci_device); + + if ((if_num != LEGACY_MINOR_NUMBER) || (!device)) + return mask; + + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED){ + spin_unlock_bh(&device->device_lock); + return mask; + } + spin_unlock_bh(&device->device_lock); + if (file_extension == &device->legacy_file_extension) { + + poll_wait(file, &device->legacy_file_extension.wait, wait); + spin_lock(&device->legacy_file_extension.file_lock); + if (device->legacy_state == HECI_LEGACY_READ_COMPLETE + && device->legacy_file_object == file) { + mask |= (POLLIN | POLLRDNORM); + spin_lock_bh(&device->device_lock); + DBG("run next pthi legacy cb\n"); + run_next_legacy_cmd(device); + spin_unlock_bh(&device->device_lock); + } + spin_unlock(&device->legacy_file_extension.file_lock); + } + return mask; +} + +/** + * heci_poll - the poll function + */ +static unsigned int heci_poll(struct file *file, poll_table * wait) +{ + int if_num = MINOR((file->f_dentry->d_inode->i_rdev)); + unsigned int mask = 0; + struct heci_file_private *file_extension = file->private_data; + struct iamt_heci_device *device = NULL; + + if (!heci_device) + return mask; + + + device = pci_get_drvdata(heci_device); + + if ((if_num != HECI_MINOR_NUMBER) || (!device) + || (!file_extension)) + return mask; + + spin_lock_bh(&device->device_lock); + if (device->heci_state != HECI_ENABLED){ + spin_unlock_bh(&device->device_lock); + return mask; + + } + spin_unlock_bh(&device->device_lock); + if (file_extension == &device->legacy_file_extension) { + + + poll_wait(file, &device->legacy_file_extension.wait, wait); + spin_lock(&device->legacy_file_extension.file_lock); + if (device->legacy_state == HECI_LEGACY_READ_COMPLETE + && device->legacy_file_object == file) { + mask |= (POLLIN | POLLRDNORM); + spin_lock_bh(&device->device_lock); + DBG("run next pthi cb"); + run_next_legacy_cmd(device); + spin_unlock_bh(&device->device_lock); + } + spin_unlock(&device->legacy_file_extension.file_lock); + + } else{ + poll_wait(file, &file_extension->tx_wait, wait); + spin_lock(&file_extension->write_io_lock); + if (HECI_WRITE_COMPLETE == file_extension->writing_state) + mask |= (POLLIN | POLLRDNORM); + spin_unlock(&file_extension->write_io_lock); + } + return mask; +} + +#ifdef CONFIG_PM +static int heci_suspend(struct pci_dev* pdev, pm_message_t state) +{ + struct iamt_heci_device *device = pci_get_drvdata(pdev); + int err = 0; + + //Stop watchdog if exists + del_timer_sync(&device->wd_timer); + if (device->wd_file_extension.state == HECI_FILE_CONNECTED + && device->wd_timeout) { + spin_lock_bh(&device->device_lock); + g_sus_wd_timeout = device->wd_timeout; + device->wd_timeout = 0; + device->wd_due_counter = 0; + memcpy(device->wd_data, stop_wd_params, HECI_WD_PARAMS_SIZE); + device->stop = TRUE; + if (device->host_buffer_is_empty && + flow_control_credentials(device, &device->wd_file_extension)) { + device->host_buffer_is_empty = FALSE; + + if (!heci_send_wd(device)) + DBG("Send stop WD failed\n"); + else + flow_control_reduce(device, &device->wd_file_extension); + device->wd_pending = FALSE; + } else { + device->wd_pending = TRUE; + } + spin_unlock_bh(&device->device_lock); + device->wd_stoped = FALSE; + + err = + wait_event_interruptible_timeout(device->wait_stop_wd, + (TRUE == device->wd_stoped), 10 * HZ); + if (!device->wd_stoped) + DBG("stop wd failed to complete.\n"); + else { + DBG("stop wd complete %d.\n", err); + err = 0; + } + } + //Set new heci state + spin_lock_bh(&device->device_lock); + if (device->heci_state == HECI_ENABLED || + device->heci_state == HECI_RECOVERING_FROM_RESET) { + device->heci_state = HECI_POWER_DOWN; + heci_reset(device, FALSE); + } + spin_unlock_bh(&device->device_lock); + + pci_save_state(pdev); + + + pci_disable_device(pdev); + free_irq(pdev->irq, device); + + pci_set_power_state(pdev, PCI_D3hot); + + return err; +} + +static int heci_resume(struct pci_dev* pdev) +{ + struct iamt_heci_device *device = NULL; + int err = 0; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + device = pci_get_drvdata(pdev); + if (!device) { + return -ENODEV; + } + + /* request and enable interrupt */ + device->irq = pdev->irq; + err = request_irq(device->irq, heci_isr_interrupt, IRQF_SHARED, + heci_driver_name, device); + if (err) { + HECI_ERR("Request_irq failure. irq = %d \n", device->irq); + return err; + } + + spin_lock_bh(&device->device_lock); + device->heci_state = HECI_POWER_UP; + heci_reset(device, TRUE); + spin_unlock_bh(&device->device_lock); + + //Start watchdog if stopped in suspend + if (g_sus_wd_timeout != 0) { + device->wd_timeout = g_sus_wd_timeout; + + memcpy(device->wd_data, start_wd_params, HECI_WD_PARAMS_SIZE); + memcpy(device->wd_data + HECI_WD_PARAMS_SIZE, &device->wd_timeout, + sizeof(__u16)); + device->wd_due_counter = 1; + + if (device->wd_timeout) + mod_timer(&device->wd_timer, jiffies); + g_sus_wd_timeout = 0; + } + return err; +} +#endif +MODULE_AUTHOR("Intel Corporation"); /* FIXME: Add email address here */ +MODULE_DESCRIPTION("Intel(R) AMT Management Interface"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(DRIVER_VERSION); --- linux-2.6.27.orig/ubuntu/heci/Makefile +++ linux-2.6.27/ubuntu/heci/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_HECI) += heci.o + +heci-objs := heci_init.o interrupt.o heci_interface.o io_heci.o heci_main.o --- linux-2.6.27.orig/ubuntu/heci/heci_interface.h +++ linux-2.6.27/ubuntu/heci/heci_interface.h @@ -0,0 +1,177 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2007 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + + +#ifndef _HECI_INTERFACE_H_ +#define _HECI_INTERFACE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "heci_data_structures.h" + + +#define HBM_MINOR_VERSION 0 +#define HBM_MAJOR_VERSION 1 +#define HBM_TIMEOUT 1 /* 1 second */ + + +#define HOST_START_REQ_CMD 0x01 +#define HOST_START_RES_CMD 0x81 + +#define HOST_STOP_REQ_CMD 0x02 +#define HOST_STOP_RES_CMD 0x82 + +#define ME_STOP_REQ_CMD 0x03 + +#define HOST_ENUM_REQ_CMD 0x04 +#define HOST_ENUM_RES_CMD 0x84 + +#define HOST_CLIENT_PROPERTEIS_REQ_CMD 0x05 +#define HOST_CLIENT_PROPERTEIS_RES_CMD 0x85 + +#define CLIENT_CONNECT_REQ_CMD 0x06 +#define CLIENT_CONNECT_RES_CMD 0x86 + +#define CLIENT_DISCONNECT_REQ_CMD 0x07 +#define CLIENT_DISCONNECT_RES_CMD 0x87 + +#define FLOW_CONTROL_CMD 0x08 + + +#define AMT_WD_VALUE 120 /* seconds */ + +#define HECI_WATCHDOG_DATA_SIZE 16 +#define HECI_START_WD_DATA_SIZE 20 +#define HECI_WD_PARAMS_SIZE 4 + +/* IOCTL commands */ +#define HECI_IOCTL_LETTER 'H' + + +#define IOCTL_HECI_GET_VERSION \ + _IOWR(HECI_IOCTL_LETTER , 0x800, struct heci_message_data) +#define IOCTL_HECI_CONNECT_CLIENT \ + _IOWR(HECI_IOCTL_LETTER , 0x801, struct heci_message_data) +#define IOCTL_HECI_WD \ + _IOWR(HECI_IOCTL_LETTER , 0x802, struct heci_message_data) +#define IOCTL_HECI_BYPASS_WD \ + _IOWR(HECI_IOCTL_LETTER , 0x810, struct heci_message_data) + +#define IAMT_IOC_MAGIC 'i' +#define IAMT_KCS_SEND_MESSAGE_COMMAND _IOR(IAMT_IOC_MAGIC, 1, struct heci_message_data) +#define IAMT_KCS_RECEIVE_MESSAGE_COMMAND _IOW(IAMT_IOC_MAGIC, 2, struct heci_message_data) + + +#pragma pack(1) + + +enum heci_stop_reason_types{ + DRIVER_STOP_REQUEST = 0x00, + DEVICE_D1_ENTRY = 0x01, + DEVICE_D2_ENTRY = 0x02, + DEVICE_D3_ENTRY = 0x03, + SYSTEM_S1_ENTRY = 0x04, + SYSTEM_S2_ENTRY = 0x05, + SYSTEM_S3_ENTRY = 0x06, + SYSTEM_S4_ENTRY = 0x07, + SYSTEM_S5_ENTRY = 0x08 +}; + +enum me_stop_reason_types{ + FW_UPDATE = 0x00 +}; + +enum client_connect_status_types{ + CCS_SUCCESS = 0x00, + CCS_NOT_FOUND = 0x01, + CCS_ALREADY_STARTED = 0x02, + CCS_OUT_OF_RESOURCES = 0x03, + CCS_MESSAGE_SMALL = 0x04 +}; + +enum client_disconnect_status_types{ + CDS_SUCCESS = 0x00 +}; + + +/** + * heci interface function prototypes + */ +void heci_read_slots(struct iamt_heci_device * device_object, + unsigned char *buffer, unsigned long buffer_length); + +int heci_write_message(struct iamt_heci_device * device_object, + struct heci_message_header * header, + unsigned char *write_buffer, + unsigned long write_length); + +int host_buffer_is_empty(struct iamt_heci_device * device_object); + +__s32 count_full_read_slots(struct iamt_heci_device * device_object); + +__s32 count_empty_write_slots(struct iamt_heci_device * device_object); + +int flow_control_credentials(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); + +int heci_send_wd(struct iamt_heci_device * device_object); + +void flow_control_reduce(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); + +int heci_send_flow_control(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); + +int heci_disconnect(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); +int other_client_is_connecting(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); +int heci_connect(struct iamt_heci_device * device_object, + struct heci_file_private * file_extension); + +#endif /* _HECI_INTERFACE_H_ */ --- linux-2.6.27.orig/ubuntu/ndiswrapper/pnp.c +++ linux-2.6.27/ubuntu/ndiswrapper/pnp.c @@ -0,0 +1,742 @@ +/* + * Copyright (C) 2005 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "usb.h" +#include "pnp.h" +#include "wrapndis.h" +#include "loader.h" + +/* Functions callable from the NDIS driver */ +wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo, + struct irp *irp); +wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp); +wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp); + +static NTSTATUS start_pdo(struct device_object *pdo) +{ + int i, ret, count, resources_size; + struct wrap_device *wd; + struct pci_dev *pdev; + struct cm_partial_resource_descriptor *entry; + struct cm_partial_resource_list *partial_resource_list; + + ENTER1("%p, %p", pdo, pdo->reserved); + wd = pdo->reserved; + if (ntoskernel_init_device(wd)) + EXIT1(return STATUS_FAILURE); + if (wrap_is_usb_bus(wd->dev_bus)) { +#ifdef ENABLE_USB + if (usb_init_device(wd)) { + ntoskernel_exit_device(wd); + EXIT1(return STATUS_FAILURE); + } +#endif + EXIT1(return STATUS_SUCCESS); + } + if (!wrap_is_pci_bus(wd->dev_bus)) + EXIT1(return STATUS_SUCCESS); + pdev = wd->pci.pdev; + ret = pci_enable_device(pdev); + if (ret) { + ERROR("couldn't enable PCI device: %x", ret); + return STATUS_FAILURE; + } + ret = pci_request_regions(pdev, DRIVER_NAME); + if (ret) { + ERROR("couldn't request PCI regions: %x", ret); + goto err_enable; + } + pci_set_power_state(pdev, PCI_D0); +#ifdef CONFIG_X86_64 + /* 64-bit broadcom driver doesn't work if DMA is allocated + * from over 1GB */ + if (wd->vendor == 0x14e4) { + if (pci_set_dma_mask(pdev, DMA_30BIT_MASK) || + pci_set_consistent_dma_mask(pdev, DMA_30BIT_MASK)) + WARNING("couldn't set DMA mask; this driver " + "may not work with more than 1GB RAM"); + } +#endif + /* IRQ resource entry is filled in from pdev, instead of + * pci_resource macros */ + for (i = count = 0; pci_resource_start(pdev, i); i++) + if ((pci_resource_flags(pdev, i) & IORESOURCE_MEM) || + (pci_resource_flags(pdev, i) & IORESOURCE_IO)) + count++; + /* space for entry for IRQ is already in + * cm_partial_resource_list */ + resources_size = sizeof(struct cm_resource_list) + + sizeof(struct cm_partial_resource_descriptor) * count; + TRACE2("resources: %d, %d", count, resources_size); + wd->resource_list = kzalloc(resources_size, GFP_KERNEL); + if (!wd->resource_list) { + WARNING("couldn't allocate memory"); + goto err_regions; + } + wd->resource_list->count = 1; + wd->resource_list->list[0].interface_type = PCIBus; + /* bus_number is not used by WDM drivers */ + wd->resource_list->list[0].bus_number = pdev->bus->number; + + partial_resource_list = + &wd->resource_list->list->partial_resource_list; + partial_resource_list->version = 1; + partial_resource_list->revision = 1; + partial_resource_list->count = count + 1; + + for (i = count = 0; pci_resource_start(pdev, i); i++) { + entry = &partial_resource_list->partial_descriptors[count]; + TRACE2("%d", count); + if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { + entry->type = CmResourceTypeMemory; + entry->flags = CM_RESOURCE_MEMORY_READ_WRITE; + entry->share = CmResourceShareDeviceExclusive; + } else if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { + entry->type = CmResourceTypePort; + entry->flags = CM_RESOURCE_PORT_IO; + entry->share = CmResourceShareDeviceExclusive; +#if 0 + } else if (pci_resource_flags(pdev, i) & IORESOURCE_DMA) { + /* it looks like no driver uses this resource */ + typeof(pci_resource_flags(pdev, 0)) flags; + entry->type = CmResourceTypeDma; + flags = pci_resource_flags(pdev, i); + if (flags & IORESOURCE_DMA_TYPEA) + entry->flags |= CM_RESOURCE_DMA_TYPE_A; + else if (flags & IORESOURCE_DMA_TYPEB) + entry->flags |= CM_RESOURCE_DMA_TYPE_B; + else if (flags & IORESOURCE_DMA_TYPEF) + entry->flags |= CM_RESOURCE_DMA_TYPE_F; + if (flags & IORESOURCE_DMA_8BIT) + entry->flags |= CM_RESOURCE_DMA_8; + else if (flags & IORESOURCE_DMA_16BIT) + entry->flags |= CM_RESOURCE_DMA_16; + /* what about 32bit DMA? */ + else if (flags & IORESOURCE_DMA_8AND16BIT) + entry->flags |= CM_RESOURCE_DMA_8_AND_16; + if (flags & IORESOURCE_DMA_MASTER) + entry->flags |= CM_RESOURCE_DMA_BUS_MASTER; + entry->u.dma.channel = pci_resource_start(pdev, i); + /* what should this be? */ + entry->u.dma.port = 1; +#endif + } else + continue; + /* TODO: Add other resource types? */ + entry->u.generic.start = + (ULONG_PTR)pci_resource_start(pdev, i); + entry->u.generic.length = pci_resource_len(pdev, i); + count++; + } + + /* put IRQ resource at the end */ + entry = &partial_resource_list->partial_descriptors[count++]; + entry->type = CmResourceTypeInterrupt; + entry->flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + /* we assume all devices use shared IRQ */ + entry->share = CmResourceShareShared; + /* as per documentation, interrupt level should be DIRQL, but + * examples from DDK as well some drivers, such as AR5211, + * RT8180L use interrupt level as interrupt vector also in + * NdisMRegisterInterrupt */ + entry->u.interrupt.level = pdev->irq; + entry->u.interrupt.vector = pdev->irq; + entry->u.interrupt.affinity = -1; + + TRACE2("resource list count %d, irq: %d", + partial_resource_list->count, pdev->irq); + pci_set_drvdata(pdev, wd); + EXIT1(return STATUS_SUCCESS); +err_regions: + pci_release_regions(pdev); +err_enable: + pci_disable_device(pdev); + wd->pci.pdev = NULL; + wd->pdo = NULL; + EXIT1(return STATUS_FAILURE); +} + +static void remove_pdo(struct device_object *pdo) +{ + struct wrap_device *wd = pdo->reserved; + + ntoskernel_exit_device(wd); + if (wrap_is_pci_bus(wd->dev_bus)) { + struct pci_dev *pdev = wd->pci.pdev; + pci_release_regions(pdev); + pci_disable_device(pdev); + wd->pci.pdev = NULL; + pci_set_drvdata(pdev, NULL); + } else if (wrap_is_usb_bus(wd->dev_bus)) { +#ifdef ENABLE_USB + usb_exit_device(wd); +#endif + } + if (wd->resource_list) + kfree(wd->resource_list); + wd->resource_list = NULL; + return; +} + +static NTSTATUS IoSendIrpTopDev(struct device_object *dev_obj, ULONG major_fn, + ULONG minor_fn, struct io_stack_location *sl) +{ + NTSTATUS status; + struct nt_event event; + struct irp *irp; + struct io_stack_location *irp_sl; + struct device_object *top_dev = IoGetAttachedDeviceReference(dev_obj); + + KeInitializeEvent(&event, NotificationEvent, FALSE); + irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, top_dev, NULL, 0, NULL, + &event, NULL); + irp->io_status.status = STATUS_NOT_IMPLEMENTED; + irp->io_status.info = 0; + irp_sl = IoGetNextIrpStackLocation(irp); + if (sl) + memcpy(irp_sl, sl, sizeof(*irp_sl)); + irp_sl->major_fn = major_fn; + irp_sl->minor_fn = minor_fn; + status = IoCallDriver(top_dev, irp); + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Executive, KernelMode, + FALSE, NULL); + status = irp->io_status.status; + } + ObDereferenceObject(top_dev); + return status; +} + +wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo, + struct irp *irp) +{ + struct io_stack_location *irp_sl; + NTSTATUS status; + + DUMP_IRP(irp); + irp_sl = IoGetCurrentIrpStackLocation(irp); +#ifdef ENABLE_USB + status = wrap_submit_irp(pdo, irp); + IOTRACE("status: %08X", status); + if (status != STATUS_PENDING) + IoCompleteRequest(irp, IO_NO_INCREMENT); +#else + status = irp->io_status.status = STATUS_NOT_IMPLEMENTED; + IoCompleteRequest(irp, IO_NO_INCREMENT); +#endif + IOEXIT(return status); +} +WIN_FUNC_DECL(pdoDispatchDeviceControl,2) + +wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct wrap_device *wd; + NTSTATUS status; +#ifdef ENABLE_USB + struct usbd_bus_interface_usbdi *usb_intf; +#endif + + irp_sl = IoGetCurrentIrpStackLocation(irp); + TRACE2("%p %d:%d", pdo, irp_sl->major_fn, irp_sl->minor_fn); + wd = pdo->reserved; + switch (irp_sl->minor_fn) { + case IRP_MN_START_DEVICE: + status = start_pdo(pdo); + break; + case IRP_MN_QUERY_STOP_DEVICE: + case IRP_MN_STOP_DEVICE: + case IRP_MN_QUERY_REMOVE_DEVICE: + status = STATUS_SUCCESS; + break; + case IRP_MN_REMOVE_DEVICE: + remove_pdo(pdo); + status = STATUS_SUCCESS; + break; + case IRP_MN_QUERY_INTERFACE: +#ifdef ENABLE_USB + if (!wrap_is_usb_bus(wd->dev_bus)) { + status = STATUS_NOT_IMPLEMENTED; + break; + } + TRACE2("type: %x, size: %d, version: %d", + irp_sl->params.query_intf.type->data1, + irp_sl->params.query_intf.size, + irp_sl->params.query_intf.version); + usb_intf = (struct usbd_bus_interface_usbdi *) + irp_sl->params.query_intf.intf; + usb_intf->Context = wd; + usb_intf->InterfaceReference = USBD_InterfaceReference; + usb_intf->InterfaceDereference = USBD_InterfaceDereference; + usb_intf->GetUSBDIVersion = USBD_InterfaceGetUSBDIVersion; + usb_intf->QueryBusTime = USBD_InterfaceQueryBusTime; + usb_intf->SubmitIsoOutUrb = USBD_InterfaceSubmitIsoOutUrb; + usb_intf->QueryBusInformation = + USBD_InterfaceQueryBusInformation; + if (irp_sl->params.query_intf.version >= + USB_BUSIF_USBDI_VERSION_1) + usb_intf->IsDeviceHighSpeed = + USBD_InterfaceIsDeviceHighSpeed; + if (irp_sl->params.query_intf.version >= + USB_BUSIF_USBDI_VERSION_2) + usb_intf->LogEntry = USBD_InterfaceLogEntry; + status = STATUS_SUCCESS; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + break; + default: + TRACE2("fn %d not implemented", irp_sl->minor_fn); + status = STATUS_SUCCESS; + break; + } + irp->io_status.status = status; + TRACE2("status: %08X", status); + IoCompleteRequest(irp, IO_NO_INCREMENT); + IOEXIT(return status); +} +WIN_FUNC_DECL(pdoDispatchPnp,2) + +wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct wrap_device *wd; + union power_state power_state; + struct pci_dev *pdev; + NTSTATUS status; + + irp_sl = IoGetCurrentIrpStackLocation(irp); + wd = pdo->reserved; + TRACE2("pdo: %p, fn: %d:%d, wd: %p", + pdo, irp_sl->major_fn, irp_sl->minor_fn, wd); + switch (irp_sl->minor_fn) { + case IRP_MN_WAIT_WAKE: + /* TODO: this is not complete/correct */ + TRACE2("state: %d, completion: %p", + irp_sl->params.power.state.system_state, + irp_sl->completion_routine); + IoMarkIrpPending(irp); + status = STATUS_PENDING; + break; + case IRP_MN_SET_POWER: + power_state = irp_sl->params.power.state; + if (power_state.device_state == PowerDeviceD0) { + TRACE2("resuming %p", wd); + if (wrap_is_pci_bus(wd->dev_bus)) { + pdev = wd->pci.pdev; + pci_restore_state(pdev); + if (wd->pci.wake_state == PowerDeviceD3) { + pci_enable_wake(wd->pci.pdev, + PCI_D3hot, 0); + pci_enable_wake(wd->pci.pdev, + PCI_D3cold, 0); + } + pci_set_power_state(pdev, PCI_D0); + } else { // usb device +#ifdef ENABLE_USB + wrap_resume_urbs(wd); +#endif + } + } else { + TRACE2("suspending device %p", wd); + if (wrap_is_pci_bus(wd->dev_bus)) { + pdev = wd->pci.pdev; + pci_save_state(pdev); + TRACE2("%d", wd->pci.wake_state); + if (wd->pci.wake_state == PowerDeviceD3) { + pci_enable_wake(wd->pci.pdev, + PCI_D3hot, 1); + pci_enable_wake(wd->pci.pdev, + PCI_D3cold, 1); + } + pci_set_power_state(pdev, PCI_D3hot); + } else { // usb device +#ifdef ENABLE_USB + wrap_suspend_urbs(wd); +#endif + } + } + status = STATUS_SUCCESS; + break; + case IRP_MN_QUERY_POWER: + status = STATUS_SUCCESS; + break; + default: + TRACE2("fn %d not implemented", irp_sl->minor_fn); + status = STATUS_SUCCESS; + break; + } + irp->io_status.status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return status; +} +WIN_FUNC_DECL(pdoDispatchPower,2) + +static NTSTATUS pnp_set_device_power_state(struct wrap_device *wd, + enum device_power_state state) +{ + NTSTATUS status; + struct device_object *pdo; + struct io_stack_location irp_sl; + + pdo = wd->pdo; + IOTRACE("%p, %p", pdo, IoGetAttachedDevice(pdo)); + memset(&irp_sl, 0, sizeof(irp_sl)); + irp_sl.params.power.state.device_state = state; + irp_sl.params.power.type = DevicePowerState; + if (state > PowerDeviceD0) { + status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_QUERY_POWER, + &irp_sl); + if (status != STATUS_SUCCESS) { + TRACE1("query of power to %d returns %08X", + state, status); + EXIT1(return status); + } + } + status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_SET_POWER, &irp_sl); + if (status != STATUS_SUCCESS) + WARNING("setting power to %d failed: %08X", state, status); + EXIT1(return status); +} + +NTSTATUS pnp_start_device(struct wrap_device *wd) +{ + struct device_object *fdo; + struct device_object *pdo; + struct io_stack_location irp_sl; + NTSTATUS status; + + pdo = wd->pdo; + /* TODO: for now we use same resources for both translated + * resources and raw resources */ + memset(&irp_sl, 0, sizeof(irp_sl)); + irp_sl.params.start_device.allocated_resources = + wd->resource_list; + irp_sl.params.start_device.allocated_resources_translated = + wd->resource_list; + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_START_DEVICE, &irp_sl); + fdo = IoGetAttachedDevice(pdo); + if (status == STATUS_SUCCESS) + fdo->drv_obj->drv_ext->count++; + else + WARNING("Windows driver couldn't initialize the device (%08X)", + status); + EXIT1(return status); +} + +NTSTATUS pnp_stop_device(struct wrap_device *wd) +{ + struct device_object *pdo; + NTSTATUS status; + + pdo = wd->pdo; + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE, + NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + /* for now we ignore query status */ + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_STOP_DEVICE, NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + EXIT2(return status); +} + +NTSTATUS pnp_remove_device(struct wrap_device *wd) +{ + struct device_object *pdo, *fdo; + struct driver_object *fdo_drv_obj; + NTSTATUS status; + + pdo = wd->pdo; + fdo = IoGetAttachedDevice(pdo); + fdo_drv_obj = fdo->drv_obj; + TRACE2("%p, %p, %p", pdo, fdo, fdo_drv_obj); + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_REMOVE_DEVICE, + NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE, NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + /* TODO: should we use count in drv_ext or driver's Object + * header reference count to keep count of devices associated + * with a driver? */ + if (status == STATUS_SUCCESS) + fdo_drv_obj->drv_ext->count--; + TRACE1("count: %d", fdo_drv_obj->drv_ext->count); + if (fdo_drv_obj->drv_ext->count < 0) + WARNING("wrong count: %d", fdo_drv_obj->drv_ext->count); + if (fdo_drv_obj->drv_ext->count == 0) { + struct wrap_driver *wrap_driver; + TRACE1("unloading driver: %p", fdo_drv_obj); + wrap_driver = + IoGetDriverObjectExtension(fdo_drv_obj, + (void *)WRAP_DRIVER_CLIENT_ID); + if (fdo_drv_obj->unload) + LIN2WIN1(fdo_drv_obj->unload, fdo_drv_obj); + if (wrap_driver) { + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + unload_wrap_driver(wrap_driver); + up(&loader_mutex); + } else + ERROR("couldn't get wrap_driver"); + ObDereferenceObject(fdo_drv_obj); + } + IoDeleteDevice(pdo); + unload_wrap_device(wd); + EXIT1(return status); +} + +WIN_FUNC_DECL(IoInvalidDeviceRequest,2) + +static struct device_object *alloc_pdo(struct driver_object *drv_obj) +{ + struct device_object *pdo; + NTSTATUS status ; + int i; + struct ansi_string ansi_name; + struct unicode_string unicode_name; + + RtlInitAnsiString(&ansi_name, "NDISpdo"); + if (RtlAnsiStringToUnicodeString(&unicode_name, &ansi_name, TRUE) == + STATUS_SUCCESS) { + status = IoCreateDevice(drv_obj, 0, &unicode_name, + FILE_DEVICE_UNKNOWN, + FILE_AUTOGENERATED_DEVICE_NAME, + FALSE, &pdo); + RtlFreeUnicodeString(&unicode_name); + } else { + status = IoCreateDevice(drv_obj, 0, NULL, + FILE_DEVICE_UNKNOWN, + FILE_AUTOGENERATED_DEVICE_NAME, + FALSE, &pdo); + } + TRACE1("%p, %d, %p", drv_obj, status, pdo); + if (status != STATUS_SUCCESS) + return NULL; + /* dispatch routines are called as Windows functions */ + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + drv_obj->major_func[i] = WIN_FUNC_PTR(IoInvalidDeviceRequest,2); + drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] = + WIN_FUNC_PTR(pdoDispatchDeviceControl,2); + drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] = + WIN_FUNC_PTR(pdoDispatchDeviceControl,2); + drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(pdoDispatchPower,2); + drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(pdoDispatchPnp,2); + return pdo; +} + +static int wrap_pnp_start_device(struct wrap_device *wd) +{ + struct wrap_driver *driver; + struct device_object *pdo; + struct driver_object *pdo_drv_obj; + + ENTER1("wd: %p", wd); + + if (!((wrap_is_pci_bus(wd->dev_bus)) || + (wrap_is_usb_bus(wd->dev_bus)))) { + ERROR("bus type %d (%d) not supported", + WRAP_BUS(wd->dev_bus), wd->dev_bus); + EXIT1(return -EINVAL); + } + driver = load_wrap_driver(wd); + if (!driver) + return -ENODEV; + + wd->driver = driver; + wd->dev_bus = WRAP_DEVICE_BUS(driver->dev_type, WRAP_BUS(wd->dev_bus)); + TRACE1("dev type: %d, bus type: %d, %d", WRAP_DEVICE(wd->dev_bus), + WRAP_BUS(wd->dev_bus), wd->dev_bus); + TRACE1("%d, %d", driver->dev_type, wrap_is_usb_bus(wd->dev_bus)); + /* first create pdo */ + if (wrap_is_pci_bus(wd->dev_bus)) + pdo_drv_obj = find_bus_driver("PCI"); + else // if (wrap_is_usb_bus(wd->dev_bus)) + pdo_drv_obj = find_bus_driver("USB"); + if (!pdo_drv_obj) + return -EINVAL; + pdo = alloc_pdo(pdo_drv_obj); + if (!pdo) + return -ENOMEM; + wd->pdo = pdo; + pdo->reserved = wd; + if (WRAP_DEVICE(wd->dev_bus) == WRAP_NDIS_DEVICE) { + if (init_ndis_driver(driver->drv_obj)) { + IoDeleteDevice(pdo); + return -EINVAL; + } + } + TRACE1("%p", driver->drv_obj->drv_ext->add_device); + if (driver->drv_obj->drv_ext->add_device(driver->drv_obj, pdo) != + STATUS_SUCCESS) { + IoDeleteDevice(pdo); + return -ENOMEM; + } + if (pnp_start_device(wd) != STATUS_SUCCESS) { + /* TODO: we need proper cleanup, to deallocate memory, + * for example */ + pnp_remove_device(wd); + return -EINVAL; + } + return 0; +} + +/* + * This function should not be marked __devinit because PCI IDs are + * added dynamically. + */ +int wrap_pnp_start_pci_device(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct load_device load_device; + struct wrap_device *wd; + + ENTER1("called for %04x:%04x:%04x:%04x", pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); + + load_device.bus = WRAP_PCI_BUS; + load_device.vendor = pdev->vendor; + load_device.device = pdev->device; + load_device.subvendor = pdev->subsystem_vendor; + load_device.subdevice = pdev->subsystem_device; + wd = load_wrap_device(&load_device); + if (!wd) + EXIT1(return -ENODEV); + wd->pci.pdev = pdev; + return wrap_pnp_start_device(wd); +} + +void wrap_pnp_remove_pci_device(struct pci_dev *pdev) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)pci_get_drvdata(pdev); + ENTER1("%p, %p", pdev, wd); + if (!wd) + EXIT1(return); + pnp_remove_device(wd); +} + +int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)pci_get_drvdata(pdev); + return pnp_set_device_power_state(wd, PowerDeviceD3); +} + +int wrap_pnp_resume_pci_device(struct pci_dev *pdev) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)pci_get_drvdata(pdev); + return pnp_set_device_power_state(wd, PowerDeviceD0); +} + +#ifdef ENABLE_USB +int wrap_pnp_start_usb_device(struct usb_interface *intf, + const struct usb_device_id *usb_id) +{ + struct wrap_device *wd; + int ret; + struct usb_device *udev = interface_to_usbdev(intf); + ENTER1("%04x, %04x, %04x", udev->descriptor.idVendor, + udev->descriptor.idProduct, udev->descriptor.bDeviceClass); + + /* USB device (e.g., RNDIS) may have multiple interfaces; + initialize one interface only (is there a way to know which + of these interfaces is for network?) */ + + if ((wd = get_wrap_device(udev, WRAP_USB_BUS))) { + TRACE1("device already initialized: %p", wd); + usb_set_intfdata(intf, NULL); + ret = 0; + } else { + struct load_device load_device; + + load_device.bus = WRAP_USB_BUS; + load_device.vendor = le16_to_cpu(udev->descriptor.idVendor); + load_device.device = le16_to_cpu(udev->descriptor.idProduct); + load_device.subvendor = 0; + load_device.subdevice = 0; + wd = load_wrap_device(&load_device); + TRACE2("%p", wd); + if (wd) { + /* some devices (e.g., TI 4150, RNDIS) need + * full reset */ + ret = usb_reset_device(udev); + if (ret) + WARNING("reset failed: %d", ret); + usb_set_intfdata(intf, wd); + wd->usb.intf = intf; + wd->usb.udev = udev; + ret = wrap_pnp_start_device(wd); + } else + ret = -ENODEV; + } + + TRACE2("ret: %d", ret); + if (ret) + EXIT1(return ret); + else + return 0; +} + +void __devexit wrap_pnp_remove_usb_device(struct usb_interface *intf) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)usb_get_intfdata(intf); + TRACE1("%p, %p", intf, wd); + if (wd == NULL) + EXIT1(return); + usb_set_intfdata(intf, NULL); + wd->usb.intf = NULL; + pnp_remove_device(wd); +} + +int wrap_pnp_suspend_usb_device(struct usb_interface *intf, pm_message_t state) +{ + struct wrap_device *wd; + struct device_object *pdo; + + wd = usb_get_intfdata(intf); + ENTER1("%p, %p", intf, wd); + if (!wd) + EXIT1(return 0); + pdo = wd->pdo; + if (pnp_set_device_power_state(wd, PowerDeviceD3)) + return -1; + return 0; +} + +int wrap_pnp_resume_usb_device(struct usb_interface *intf) +{ + struct wrap_device *wd; + wd = usb_get_intfdata(intf); + ENTER1("%p, %p", intf, wd); + if (!wd) + EXIT1(return 0); + if (pnp_set_device_power_state(wd, PowerDeviceD0)) + return -1; + return 0; +} + +#endif // USB --- linux-2.6.27.orig/ubuntu/ndiswrapper/mkstubs.sh +++ linux-2.6.27/ubuntu/ndiswrapper/mkstubs.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +for file in "$@"; do + echo + echo "# automatically generated from $file" + sed -n \ + -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/\ + win2lin(\1, \2)/p' \ + -e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/\ + win2lin(\1, \2)/p' \ + $file | sed -e 's/[ \t ]\+//' | sort -u; \ +done --- linux-2.6.27.orig/ubuntu/ndiswrapper/win2lin_stubs.S +++ linux-2.6.27/ubuntu/ndiswrapper/win2lin_stubs.S @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2005 Karl Vogel, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + +#ifdef CONFIG_X86_64 + +/* +# Windows <---> Linux register usage conversion when calling functions +# V = Volatile +# NV = Non Volatile (needs to be saved) +# +# Win Lin +# --------------------------------------- +# Rax Return V Return V +# Rbx NV NV +# Rcx Arg1 V Arg4 V +# Rdx Arg2 V Arg3 V +# Rsi NV Arg2 V +# Rdi NV Arg1 V +# Rsp NV NV +# Rbp NV NV +# R8 Arg3 V Arg5 V +# R9 Arg4 V Arg6 V +# R10 V V +# R11 V V +# R12 NV NV +# R13 NV NV +# R14 NV NV +# R15 NV NV +# +# In addition, Linux uses %rax to indicate number of SSE registers used +# when variadic functions are called. Since there is no way to obtain this +# from Windows, for now, we just assume this is 0 (hence %rax is cleared). +# +# Windows pushes arguments 5 and higher onto stack in case of integer +# variables and 4 and higher in case of floating point variabes (passed +# in SSE registers). + +In a windows function, the stackframe/registers look like this: + +# 0x0048 .... +# 0x0040 arg8 +# 0x0038 arg7 +# 0x0030 arg6 +# 0x0028 arg5 +# 0x0020 shadow/spill space for arg4 +# 0x0018 shadow/spill space for arg3 +# 0x0010 shadow/spill space for arg2 +# 0x0008 shadow/spill space for arg1 +# 0x0000 ret + +# register spill space is same irrespective of number of arguments - even +# if Windows function takes less than 4 arguments, 32 bytes above return +# address is reserved for the function + +In Linux it should look like: + +# 0x0018 .... +# 0x0010 arg8 +# 0x0008 arg7 +# 0x0000 ret + +*/ + +# +# setup for Windows to Linux function call +# + + .text + +.macro win2lin_prolog + push %rsi + push %rdi +.endm + +.macro win2lin_epilog + pop %rdi + pop %rsi +.endm + +# when Windows function calls Linux function, the function address is in %r10 + +.macro call_lin_func + xor %rax, %rax # rax indicates number of SSE regs + call *%r10 +.endm + +# before prolog, 0(%rsp) is return address, 8(%rsp) would be arg1 +# (but it is in register) and so on, so n'th arg would be at n*8(%rsp) +# for n > 4. But in prolog, we push 2 registers that are non-volaile in +# Windows, but volatile in Linux. So after prolog, args are at (n+2)*8(%rsp) + +#define win2lin_win_arg(n) (n+2)*8(%rsp) + +#define win2lin_arg1 mov %rcx, %rdi +#define win2lin_arg2 mov %rdx, %rsi +#define win2lin_arg3 mov %r8, %rdx +#define win2lin_arg4 mov %r9, %rcx +#define win2lin_arg5 mov win2lin_win_arg(5), %r8 +#define win2lin_arg6 mov win2lin_win_arg(6), %r9 + + .type win2lin0, @function +win2lin0: + win2lin_prolog + call_lin_func + win2lin_epilog + ret + .size win2lin0, .-win2lin0 + + .type win2lin1, @function +win2lin1: + win2lin_prolog + win2lin_arg1 + call_lin_func + win2lin_epilog + ret + .size win2lin1, .-win2lin1 + + .type win2lin2, @function +win2lin2: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + call_lin_func + win2lin_epilog + ret + .size win2lin2, .-win2lin2 + + .type win2lin3, @function +win2lin3: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + call_lin_func + win2lin_epilog + ret + .size win2lin3, .-win2lin3 + + .type win2lin4, @function +win2lin4: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + call_lin_func + win2lin_epilog + ret + .size win2lin4, .-win2lin4 + + .type win2lin5, @function +win2lin5: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + call_lin_func + win2lin_epilog + ret + .size win2lin5, .-win2lin5 + + .type win2lin6, @function +win2lin6: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + call_lin_func + win2lin_epilog + ret + .size win2lin6, .-win2lin6 + +# Allocate stack frame for Linux arguments before calling function. +# First 6 args are passed through registers, so we need space for 7 and above. +# The arguments should have been copied onto stack already. + +.macro call_lin_func_args n + sub $(\n-6)*8, %rsp + call_lin_func + add $(\n-6)*8, %rsp + .endm + +# m is index of Linux arg required, n is total number of args to function +# After stack frame is allocated, Linux arg 7 should be at 0(%rsp), +# arg 8 should be at 1*8(%rsp) and so on. So Linux arg m should be at (m-7)*8 +# Stack frame starts at -(n-6)*8(%rsp), so before stack frame is allocated +# Linux arg m should be at (6-n+m-7)*8(%rsp) + +#define win2lin_lin_arg(m,n) (m-1-n)*8(%rsp) + + .type win2lin7, @function +win2lin7: + win2lin_prolog + + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + + # copy windows argument 7 onto stack for Linux function + mov win2lin_win_arg(7), %r11 + mov %r11, win2lin_lin_arg(7,7) + + call_lin_func_args(7) + win2lin_epilog + ret + .size win2lin7, .-win2lin7 + + .type win2lin8, @function +win2lin8: + win2lin_prolog + + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + + # copy windows arguments 7 and 8 onto stack for Linux function + mov win2lin_win_arg(7), %r11 + mov %r11, win2lin_lin_arg(7,8) + mov win2lin_win_arg(8), %r11 + mov %r11, win2lin_lin_arg(8,8) + + call_lin_func_args(8) + win2lin_epilog + ret + .size win2lin8, .-win2lin8 + + .type win2lin9, @function +win2lin9: +win2lin10: +win2lin11: +win2lin12: + win2lin_prolog + + # since we destroy rsi and rdi here, first copy windows + # arguments 7 through 12 onto stack for Linux function + mov %rcx, %r11 # save rcx + lea win2lin_win_arg(7), %rsi # source (windows arg 7 and up) + lea win2lin_lin_arg(7,12), %rdi # = destination + mov $6, %rcx # 6 arguments + rep + movsq + mov %r11, %rcx # restore rcx + + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + + call_lin_func_args(12) + win2lin_epilog + ret + .size win2lin9, .-win2lin9 + +#define win2lin(name, argc) \ +ENTRY(win2lin_ ## name ## _ ## argc) \ + lea name(%rip), %r10 ; \ + jmp win2lin ## argc + +#include "win2lin_stubs.h" + +#endif // CONFIG_X86_64 --- linux-2.6.27.orig/ubuntu/ndiswrapper/iw_ndis.c +++ linux-2.6.27/ubuntu/ndiswrapper/iw_ndis.c @@ -0,0 +1,1956 @@ + /* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "iw_ndis.h" +#include "wrapndis.h" + +static int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; + +static const char *network_names[] = {"IEEE 802.11FH", "IEEE 802.11b", + "IEEE 802.11a", "IEEE 802.11g", "Auto"}; + +int set_essid(struct ndis_device *wnd, const char *ssid, int ssid_len) +{ + NDIS_STATUS res; + struct ndis_essid req; + + if (ssid_len > NDIS_ESSID_MAX_SIZE) + return -EINVAL; + + memset(&req, 0, sizeof(req)); + req.length = ssid_len; + if (ssid_len) + memcpy(&req.essid, ssid, ssid_len); + + res = mp_set(wnd, OID_802_11_SSID, &req, sizeof(req)); + if (res) { + WARNING("setting essid failed (%08X)", res); + EXIT2(return -EINVAL); + } + memcpy(&wnd->essid, &req, sizeof(req)); + EXIT2(return 0); +} + +static int set_assoc_params(struct ndis_device *wnd) +{ + TRACE2("wpa_version=0x%x auth_alg=0x%x key_mgmt=0x%x " + "cipher_pairwise=0x%x cipher_group=0x%x", + wnd->iw_auth_wpa_version, wnd->iw_auth_80211_alg, + wnd->iw_auth_key_mgmt, wnd->iw_auth_cipher_pairwise, + wnd->iw_auth_cipher_group); + set_auth_mode(wnd); + set_priv_filter(wnd); + set_encr_mode(wnd); + return 0; +} + +static int iw_set_essid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + char ssid[NDIS_ESSID_MAX_SIZE]; + int length; + + ENTER2(""); + memset(ssid, 0, sizeof(ssid)); + /* there is no way to turn off essid other than to set to + * random bytes; instead, we use off to mean any */ + if (wrqu->essid.flags) { + /* wireless-tools prior to version 20 add extra 1, and + * later than 20 don't! Deal with that mess */ + length = wrqu->essid.length - 1; + if (length > 0) + length--; + while (length < wrqu->essid.length && extra[length]) + length++; + TRACE2("%d", length); + if (length <= 0 || length > NDIS_ESSID_MAX_SIZE) + EXIT2(return -EINVAL); + } else + length = 0; + + set_assoc_params(wnd); + + memcpy(ssid, extra, length); + if (set_essid(wnd, ssid, length)) + EXIT2(return -EINVAL); + + EXIT2(return 0); +} + +static int iw_get_essid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + struct ndis_essid req; + + ENTER2(""); + memset(&req, 0, sizeof(req)); + res = mp_query(wnd, OID_802_11_SSID, &req, sizeof(req)); + if (res) { + WARNING("getting essid failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + memcpy(extra, req.essid, req.length); + if (req.length > 0) + wrqu->essid.flags = 1; + else + wrqu->essid.flags = 0; + wrqu->essid.length = req.length; + EXIT2(return 0); +} + +int set_infra_mode(struct ndis_device *wnd, + enum ndis_infrastructure_mode mode) +{ + NDIS_STATUS res; + unsigned int i; + + ENTER2("%d", mode); + res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, + &wnd->infrastructure_mode); + if (res != NDIS_STATUS_SUCCESS) { + WARNING("getting operating mode to failed (%08X)", res); + EXIT2(return -EINVAL); + } + if (wnd->infrastructure_mode == mode) + EXIT2(return 0); + res = mp_set_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, mode); + if (res) { + WARNING("setting operating mode to %d failed (%08X)", + mode, res); + EXIT2(return -EINVAL); + } + /* NDIS drivers clear keys when infrastructure mode is + * changed. But Linux tools assume otherwise. So set the + * keys */ + if (wnd->iw_auth_key_mgmt == 0 || + wnd->iw_auth_key_mgmt == IW_AUTH_KEY_MGMT_802_1X) { + for (i = 0; i < MAX_ENCR_KEYS; i++) { + if (wnd->encr_info.keys[i].length > 0) + add_wep_key(wnd, wnd->encr_info.keys[i].key, + wnd->encr_info.keys[i].length, i); + } + } + wnd->infrastructure_mode = mode; + EXIT2(return 0); +} + +static int iw_set_infra_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + enum ndis_infrastructure_mode ndis_mode; + + ENTER2("%d", wrqu->mode); + switch (wrqu->mode) { + case IW_MODE_ADHOC: + ndis_mode = Ndis802_11IBSS; + break; + case IW_MODE_INFRA: + ndis_mode = Ndis802_11Infrastructure; + break; + case IW_MODE_AUTO: + ndis_mode = Ndis802_11AutoUnknown; + break; + default: + EXIT2(return -EINVAL); + } + + if (set_infra_mode(wnd, ndis_mode)) + EXIT2(return -EINVAL); + + EXIT2(return 0); +} + +static int iw_get_infra_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int ndis_mode, iw_mode; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &ndis_mode); + if (res) { + WARNING("getting operating mode failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + + switch(ndis_mode) { + case Ndis802_11IBSS: + iw_mode = IW_MODE_ADHOC; + break; + case Ndis802_11Infrastructure: + iw_mode = IW_MODE_INFRA; + break; + case Ndis802_11AutoUnknown: + iw_mode = IW_MODE_AUTO; + break; + default: + ERROR("invalid operating mode (%u)", ndis_mode); + EXIT2(return -EINVAL); + } + wrqu->mode = iw_mode; + EXIT2(return 0); +} + +static const char *network_type_to_name(int net_type) +{ + if (net_type >= 0 && + net_type < (sizeof(network_names)/sizeof(network_names[0]))) + return network_names[net_type]; + else + return network_names[sizeof(network_names) / + sizeof(network_names[0]) - 1]; +} + +static int iw_get_network_type(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + unsigned int network_type; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, + &network_type); + if (res) { + WARNING("getting network type failed: %08X", res); + network_type = -1; + } + strncpy(wrqu->name, network_type_to_name(network_type), + sizeof(wrqu->name) - 1); + wrqu->name[sizeof(wrqu->name)-1] = 0; + return 0; +} + +static int iw_get_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + struct ndis_configuration req; + + ENTER2(""); + memset(&req, 0, sizeof(req)); + res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req)); + if (res) { + WARNING("getting configuration failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + + memset(&(wrqu->freq), 0, sizeof(struct iw_freq)); + + /* see comment in wireless.h above the "struct iw_freq" + definition for an explanation of this if + NOTE: 1000000 is due to the kHz + */ + if (req.ds_config > 1000000) { + wrqu->freq.m = req.ds_config / 10; + wrqu->freq.e = 1; + } + else + wrqu->freq.m = req.ds_config; + + /* convert from kHz to Hz */ + wrqu->freq.e += 3; + + return 0; +} + +static int iw_set_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + struct ndis_configuration req; + + ENTER2(""); + /* this OID is valid only when not associated */ + if (netif_carrier_ok(wnd->net_dev)) + EXIT2(return 0); + memset(&req, 0, sizeof(req)); + res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req)); + if (res) { + WARNING("getting configuration failed (%08X)", res); + EXIT2(return 0); + } + + if (wrqu->freq.m < 1000 && wrqu->freq.e == 0) { + if (wrqu->freq.m >= 1 && + wrqu->freq.m <= (sizeof(freq_chan) / sizeof(freq_chan[0]))) + req.ds_config = freq_chan[wrqu->freq.m - 1] * 1000; + else + return -EINVAL; + } else { + int i; + req.ds_config = wrqu->freq.m; + for (i = wrqu->freq.e; i > 0; i--) + req.ds_config *= 10; + req.ds_config /= 1000; + } + res = mp_set(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req)); + if (res) + WARNING("setting configuration failed (%08X)", res); + return 0; +} + +static int iw_get_tx_power(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_tx_power_level ndis_power; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL, + &ndis_power, sizeof(ndis_power)); + if (res) + return -EOPNOTSUPP; + wrqu->txpower.flags = IW_TXPOW_MWATT; + wrqu->txpower.disabled = 0; + wrqu->txpower.fixed = 0; + wrqu->txpower.value = ndis_power; + return 0; +} + +static int iw_set_tx_power(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_tx_power_level ndis_power; + NDIS_STATUS res; + + ENTER2(""); + if (wrqu->txpower.disabled) + ndis_power = 0; + else { + if (wrqu->txpower.flags == IW_TXPOW_MWATT) + ndis_power = wrqu->txpower.value; + else { // wrqu->txpower.flags == IW_TXPOW_DBM + if (wrqu->txpower.value > 20) + ndis_power = 128; + else if (wrqu->txpower.value < -43) + ndis_power = 127; + else { + signed char tmp; + tmp = wrqu->txpower.value; + tmp = -12 - tmp; + tmp <<= 2; + ndis_power = (unsigned char)tmp; + } + } + } + TRACE2("%d", ndis_power); + res = mp_set(wnd, OID_802_11_TX_POWER_LEVEL, + &ndis_power, sizeof(ndis_power)); + if (res) + EXIT2(return -EOPNOTSUPP); + if (ndis_power == 0) + res = disassociate(wnd, 0); + EXIT2(return 0); +} + +static int iw_get_bitrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ULONG ndis_rate; + int res; + + ENTER2(""); + res = mp_query(wnd, OID_GEN_LINK_SPEED, &ndis_rate, sizeof(ndis_rate)); + if (res) { + WARNING("getting bitrate failed (%08X)", res); + ndis_rate = 0; + } + + wrqu->bitrate.value = ndis_rate * 100; + return 0; +} + +static int iw_set_bitrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int i, n; + NDIS_STATUS res; + ndis_rates_ex rates; + + ENTER2(""); + if (wrqu->bitrate.fixed == 0) + EXIT2(return 0); + + res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES, &rates, + sizeof(rates), &n, NULL); + if (res) { + WARNING("getting bit rate failed (%08X)", res); + EXIT2(return 0); + } + for (i = 0; i < n; i++) { + if (rates[i] & 0x80) + continue; + if ((rates[i] & 0x7f) * 500000 > wrqu->bitrate.value) { + TRACE2("setting rate %d to 0", + (rates[i] & 0x7f) * 500000); + rates[i] = 0; + } + } + + res = mp_set(wnd, OID_802_11_DESIRED_RATES, &rates, n); + if (res) { + WARNING("setting bit rate failed (%08X)", res); + EXIT2(return 0); + } + + return 0; +} + +static int iw_set_dummy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* Do nothing. Used for ioctls that are not implemented. */ + return 0; +} + +static int iw_get_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_rts_threshold threshold; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_RTS_THRESHOLD, + &threshold, sizeof(threshold)); + if (res) + return -EOPNOTSUPP; + + wrqu->rts.value = threshold; + return 0; +} + +static int iw_set_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_rts_threshold threshold; + NDIS_STATUS res; + + ENTER2(""); + threshold = wrqu->rts.value; + res = mp_set(wnd, OID_802_11_RTS_THRESHOLD, + &threshold, sizeof(threshold)); + if (res == NDIS_STATUS_INVALID_DATA) + return -EINVAL; + if (res) + return -EOPNOTSUPP; + + return 0; +} + +static int iw_get_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_fragmentation_threshold frag_threshold; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, + &frag_threshold, sizeof(frag_threshold)); + if (res) + return -ENOTSUPP; + + wrqu->frag.value = frag_threshold; + return 0; +} + +static int iw_set_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_rts_threshold threshold; + NDIS_STATUS res; + + ENTER2(""); + threshold = wrqu->frag.value; + res = mp_set(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, + &threshold, sizeof(threshold)); + if (res == NDIS_STATUS_INVALID_DATA) + return -EINVAL; + if (res) + return -EOPNOTSUPP; + return 0; +} + +int get_ap_address(struct ndis_device *wnd, mac_address ap_addr) +{ + NDIS_STATUS res; + + res = mp_query(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN); + TRACE2(MACSTRSEP, MAC2STR(ap_addr)); + if (res) { + TRACE2("res: %08X", res); + memset(ap_addr, 0x0, ETH_ALEN); + EXIT2(return -EOPNOTSUPP); + } + EXIT2(return 0); +} + +static int iw_get_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + mac_address ap_addr; + + ENTER2(""); + get_ap_address(wnd, ap_addr); + memcpy(wrqu->ap_addr.sa_data, ap_addr, ETH_ALEN); + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + EXIT2(return 0); +} + +static int iw_set_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + mac_address ap_addr; + + ENTER2(""); + memcpy(ap_addr, wrqu->ap_addr.sa_data, ETH_ALEN); + TRACE2(MACSTRSEP, MAC2STR(ap_addr)); + res = mp_set(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN); + /* user apps may set ap's mac address, which is not required; + * they may fail to work if this function fails, so return + * success */ + if (res) + WARNING("setting AP mac address failed (%08X)", res); + + EXIT2(return 0); +} + +int set_iw_auth_mode(struct ndis_device *wnd, int wpa_version, + int auth_80211_alg) +{ + NDIS_STATUS res; + ULONG auth_mode; + + ENTER2("%d, %d", wpa_version, auth_80211_alg); + if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) { + if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X) + auth_mode = Ndis802_11AuthModeWPA2; + else + auth_mode = Ndis802_11AuthModeWPA2PSK; + } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) { + if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X) + auth_mode = Ndis802_11AuthModeWPA; + else if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_PSK) + auth_mode = Ndis802_11AuthModeWPAPSK; + else + auth_mode = Ndis802_11AuthModeWPANone; + } else if (auth_80211_alg & IW_AUTH_ALG_SHARED_KEY) { + if (auth_80211_alg & IW_AUTH_ALG_OPEN_SYSTEM) + auth_mode = Ndis802_11AuthModeAutoSwitch; + else + auth_mode = Ndis802_11AuthModeShared; + } else + auth_mode = Ndis802_11AuthModeOpen; + + res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode); + if (res) { + WARNING("setting auth mode to %u failed (%08X)", + auth_mode, res); + if (res == NDIS_STATUS_INVALID_DATA) + EXIT2(return -EINVAL); + return -EOPNOTSUPP; + } + wnd->iw_auth_wpa_version = wpa_version; + wnd->iw_auth_80211_alg = auth_80211_alg; + EXIT2(return 0); +} + +int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode) +{ + NDIS_STATUS res; + + ENTER2("%d", auth_mode); + res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode); + if (res) { + WARNING("setting auth mode to %u failed (%08X)", + auth_mode, res); + if (res == NDIS_STATUS_INVALID_DATA) + EXIT2(return -EINVAL); + return -EOPNOTSUPP; + } + switch (auth_mode) { + case Ndis802_11AuthModeWPA: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X; + break; + case Ndis802_11AuthModeWPAPSK: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; + case Ndis802_11AuthModeWPANone: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; + break; + case Ndis802_11AuthModeWPA2: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X; + break; + case Ndis802_11AuthModeWPA2PSK: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; + break; + case Ndis802_11AuthModeOpen: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_80211_alg = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case Ndis802_11AuthModeShared: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY; + break; + case Ndis802_11AuthModeAutoSwitch: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY; + wnd->iw_auth_80211_alg |= IW_AUTH_ALG_OPEN_SYSTEM; + break; + default: + WARNING("invalid authentication algorithm: %d", auth_mode); + break; + } + EXIT2(return 0); +} + +int set_auth_mode(struct ndis_device *wnd) +{ + return set_iw_auth_mode(wnd, wnd->iw_auth_wpa_version, + wnd->iw_auth_80211_alg); +} + +int get_ndis_auth_mode(struct ndis_device *wnd) +{ + ULONG mode; + NDIS_STATUS res; + + res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &mode); + if (res) { + WARNING("getting authentication mode failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + TRACE2("%d", mode); + return mode; +} + +int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise, + int cipher_groupwise) +{ + NDIS_STATUS res; + ULONG ndis_mode; + + ENTER2("%d, %d", cipher_pairwise, cipher_groupwise); + if (cipher_pairwise & IW_AUTH_CIPHER_CCMP) + ndis_mode = Ndis802_11Encryption3Enabled; + else if (cipher_pairwise & IW_AUTH_CIPHER_TKIP) + ndis_mode = Ndis802_11Encryption2Enabled; + else if (cipher_pairwise & + (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) + ndis_mode = Ndis802_11Encryption1Enabled; + else if (cipher_groupwise & IW_AUTH_CIPHER_CCMP) + ndis_mode = Ndis802_11Encryption3Enabled; + else if (cipher_groupwise & IW_AUTH_CIPHER_TKIP) + ndis_mode = Ndis802_11Encryption2Enabled; + else + ndis_mode = Ndis802_11EncryptionDisabled; + + res = mp_set_int(wnd, OID_802_11_ENCRYPTION_STATUS, ndis_mode); + if (res) { + WARNING("setting encryption mode to %u failed (%08X)", + ndis_mode, res); + if (res == NDIS_STATUS_INVALID_DATA) + EXIT2(return -EINVAL); + return -EOPNOTSUPP; + } + wnd->iw_auth_cipher_pairwise = cipher_pairwise; + wnd->iw_auth_cipher_group = cipher_groupwise; + EXIT2(return 0); +} + +int set_encr_mode(struct ndis_device *wnd) +{ + return set_iw_encr_mode(wnd, wnd->iw_auth_cipher_pairwise, + wnd->iw_auth_cipher_group); +} + +int get_ndis_encr_mode(struct ndis_device *wnd) +{ + ULONG mode; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &mode); + if (res) { + WARNING("getting encryption status failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } else + EXIT2(return mode); +} + +static int iw_get_encr(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int index, mode; + struct encr_info *encr_info = &wnd->encr_info; + + ENTER2("wnd = %p", wnd); + wrqu->data.length = 0; + extra[0] = 0; + + index = (wrqu->encoding.flags & IW_ENCODE_INDEX); + TRACE2("index = %u", index); + if (index > 0) + index--; + else + index = encr_info->tx_key_index; + + if (index < 0 || index >= MAX_ENCR_KEYS) { + WARNING("encryption index out of range (%u)", index); + EXIT2(return -EINVAL); + } + + if (index != encr_info->tx_key_index) { + if (encr_info->keys[index].length > 0) { + wrqu->data.flags |= IW_ENCODE_ENABLED; + wrqu->data.length = encr_info->keys[index].length; + memcpy(extra, encr_info->keys[index].key, + encr_info->keys[index].length); + } + else + wrqu->data.flags |= IW_ENCODE_DISABLED; + + EXIT2(return 0); + } + + /* transmit key */ + mode = get_ndis_encr_mode(wnd); + if (mode < 0) + EXIT2(return -EOPNOTSUPP); + + if (mode == Ndis802_11EncryptionDisabled || + mode == Ndis802_11EncryptionNotSupported) + wrqu->data.flags |= IW_ENCODE_DISABLED; + else { + if (mode == Ndis802_11Encryption1KeyAbsent || + mode == Ndis802_11Encryption2KeyAbsent || + mode == Ndis802_11Encryption3KeyAbsent) + wrqu->data.flags |= IW_ENCODE_NOKEY; + else { + wrqu->data.flags |= IW_ENCODE_ENABLED; + wrqu->encoding.flags |= index+1; + wrqu->data.length = encr_info->keys[index].length; + memcpy(extra, encr_info->keys[index].key, + encr_info->keys[index].length); + } + } + mode = get_ndis_auth_mode(wnd); + if (mode < 0) + EXIT2(return -EOPNOTSUPP); + + if (mode == Ndis802_11AuthModeOpen) + wrqu->data.flags |= IW_ENCODE_OPEN; + else if (mode == Ndis802_11AuthModeAutoSwitch) + wrqu->data.flags |= IW_ENCODE_RESTRICTED; + else // Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA etc. + wrqu->data.flags |= IW_ENCODE_RESTRICTED; + + EXIT2(return 0); +} + +/* index must be 0 - N, as per NDIS */ +int add_wep_key(struct ndis_device *wnd, char *key, int key_len, + int index) +{ + struct ndis_encr_key ndis_key; + NDIS_STATUS res; + + ENTER2("key index: %d, length: %d", index, key_len); + if (key_len <= 0 || key_len > NDIS_ENCODING_TOKEN_MAX) { + WARNING("invalid key length (%d)", key_len); + EXIT2(return -EINVAL); + } + if (index < 0 || index >= MAX_ENCR_KEYS) { + WARNING("invalid key index (%d)", index); + EXIT2(return -EINVAL); + } + ndis_key.struct_size = sizeof(ndis_key); + ndis_key.length = key_len; + memcpy(&ndis_key.key, key, key_len); + ndis_key.index = index; + + if (index == wnd->encr_info.tx_key_index) { + ndis_key.index |= (1 << 31); + res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, + IW_AUTH_CIPHER_NONE); + if (res) + WARNING("encryption couldn't be enabled (%08X)", res); + } + TRACE2("key %d: " MACSTRSEP, index, MAC2STR(key)); + res = mp_set(wnd, OID_802_11_ADD_WEP, &ndis_key, sizeof(ndis_key)); + if (res) { + WARNING("adding encryption key %d failed (%08X)", + index+1, res); + EXIT2(return -EINVAL); + } + + /* Atheros driver messes up ndis_key during ADD_WEP, so + * don't rely on that; instead use info in key and key_len */ + wnd->encr_info.keys[index].length = key_len; + memcpy(&wnd->encr_info.keys[index].key, key, key_len); + + EXIT2(return 0); +} + +/* remove_key is for both wep and wpa */ +static int remove_key(struct ndis_device *wnd, int index, + mac_address bssid) +{ + NDIS_STATUS res; + if (wnd->encr_info.keys[index].length == 0) + EXIT2(return 0); + wnd->encr_info.keys[index].length = 0; + memset(&wnd->encr_info.keys[index].key, 0, + sizeof(wnd->encr_info.keys[index].length)); + if (wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_TKIP || + wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_CCMP || + wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_TKIP || + wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_CCMP) { + struct ndis_remove_key remove_key; + remove_key.struct_size = sizeof(remove_key); + remove_key.index = index; + if (bssid) { + /* pairwise key */ + if (memcmp(bssid, "\xff\xff\xff\xff\xff\xff", + ETH_ALEN) != 0) + remove_key.index |= (1 << 30); + memcpy(remove_key.bssid, bssid, + sizeof(remove_key.bssid)); + } else + memset(remove_key.bssid, 0xff, + sizeof(remove_key.bssid)); + if (mp_set(wnd, OID_802_11_REMOVE_KEY, + &remove_key, sizeof(remove_key))) + EXIT2(return -EINVAL); + } else { + ndis_key_index keyindex = index; + res = mp_set_int(wnd, OID_802_11_REMOVE_WEP, keyindex); + if (res) { + WARNING("removing encryption key %d failed (%08X)", + keyindex, res); + EXIT2(return -EINVAL); + } + } + /* if it is transmit key, disable encryption */ + if (index == wnd->encr_info.tx_key_index) { + res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE, + IW_AUTH_CIPHER_NONE); + if (res) + WARNING("changing encr status failed (%08X)", res); + } + TRACE2("key %d removed", index); + EXIT2(return 0); +} + +static int iw_set_wep(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + unsigned int index, key_len; + struct encr_info *encr_info = &wnd->encr_info; + unsigned char *key; + + ENTER2(""); + index = (wrqu->encoding.flags & IW_ENCODE_INDEX); + TRACE2("index = %u", index); + + /* iwconfig gives index as 1 - N */ + if (index > 0) + index--; + else + index = encr_info->tx_key_index; + + if (index < 0 || index >= MAX_ENCR_KEYS) { + WARNING("encryption index out of range (%u)", index); + EXIT2(return -EINVAL); + } + + /* remove key if disabled */ + if (wrqu->data.flags & IW_ENCODE_DISABLED) { + if (remove_key(wnd, index, NULL)) + EXIT2(return -EINVAL); + else + EXIT2(return 0); + } + + /* global encryption state (for all keys) */ + if (wrqu->data.flags & IW_ENCODE_OPEN) + res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen); + else // if (wrqu->data.flags & IW_ENCODE_RESTRICTED) + res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeShared); + if (res) { + WARNING("setting authentication mode failed (%08X)", res); + EXIT2(return -EINVAL); + } + + TRACE2("key length: %d", wrqu->data.length); + + if (wrqu->data.length > 0) { + key_len = wrqu->data.length; + key = extra; + } else { // must be set as tx key + if (encr_info->keys[index].length == 0) { + WARNING("key %d is not set", index+1); + EXIT2(return -EINVAL); + } + key_len = encr_info->keys[index].length; + key = encr_info->keys[index].key; + encr_info->tx_key_index = index; + } + + if (add_wep_key(wnd, key, key_len, index)) + EXIT2(return -EINVAL); + + if (index == encr_info->tx_key_index) { + /* if transmit key is at index other than 0, some + * drivers, at least Atheros and TI, want another + * (global) non-transmit key to be set; don't know why */ + if (index != 0) { + int i; + for (i = 0; i < MAX_ENCR_KEYS; i++) + if (i != index && + encr_info->keys[i].length != 0) + break; + if (i == MAX_ENCR_KEYS) { + if (index == 0) + i = index + 1; + else + i = index - 1; + if (add_wep_key(wnd, key, key_len, i)) + WARNING("couldn't add broadcast key" + " at %d", i); + } + } + /* ndis drivers want essid to be set after setting encr */ + set_essid(wnd, wnd->essid.essid, wnd->essid.length); + } + EXIT2(return 0); +} + +static int iw_set_nick(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (wrqu->data.length >= IW_ESSID_MAX_SIZE || wrqu->data.length <= 0) + return -EINVAL; + memcpy(wnd->nick, extra, wrqu->data.length); + wnd->nick[wrqu->data.length] = 0; + return 0; +} + +static int iw_get_nick(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + + wrqu->data.length = strlen(wnd->nick); + memcpy(extra, wnd->nick, wrqu->data.length); + return 0; +} + +static char *ndis_translate_scan(struct net_device *dev, char *event, + char *end_buf, void *item, + struct iw_request_info *info) +{ + struct iw_event iwe; + char *current_val; + int i, nrates; + unsigned char buf[MAX_WPA_IE_LEN * 2 + 30]; + struct ndis_wlan_bssid *bssid; + struct ndis_wlan_bssid_ex *bssid_ex; + + ENTER2("%p, %p", event, item); + bssid = item; + bssid_ex = item; + /* add mac address */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + iwe.len = IW_EV_ADDR_LEN; + memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); + event = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_ADDR_LEN); + + /* add essid */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = bssid->ssid.length; + if (iwe.u.data.length > IW_ESSID_MAX_SIZE) + iwe.u.data.length = IW_ESSID_MAX_SIZE; + iwe.u.data.flags = 1; + iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; + event = iwe_stream_add_point(info, event, end_buf, &iwe, bssid->ssid.essid); + + /* add protocol name */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWNAME; + strncpy(iwe.u.name, network_type_to_name(bssid->net_type), IFNAMSIZ); + event = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_CHAR_LEN); + + /* add mode */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (bssid->mode == Ndis802_11IBSS) + iwe.u.mode = IW_MODE_ADHOC; + else if (bssid->mode == Ndis802_11Infrastructure) + iwe.u.mode = IW_MODE_INFRA; + else // if (bssid->mode == Ndis802_11AutoUnknown) + iwe.u.mode = IW_MODE_AUTO; + event = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_UINT_LEN); + + /* add freq */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = bssid->config.ds_config; + if (bssid->config.ds_config > 1000000) { + iwe.u.freq.m = bssid->config.ds_config / 10; + iwe.u.freq.e = 1; + } + else + iwe.u.freq.m = bssid->config.ds_config; + /* convert from kHz to Hz */ + iwe.u.freq.e += 3; + iwe.len = IW_EV_FREQ_LEN; + event = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_FREQ_LEN); + + /* add qual */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + i = 100 * (bssid->rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE); + if (i < 0) + i = 0; + else if (i > 100) + i = 100; + iwe.u.qual.level = bssid->rssi; + iwe.u.qual.noise = WL_NOISE; + iwe.u.qual.qual = i; + iwe.len = IW_EV_QUAL_LEN; + event = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_QUAL_LEN); + + /* add key info */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (bssid->privacy == Ndis802_11PrivFilterAcceptAll) + iwe.u.data.flags = IW_ENCODE_DISABLED; + else + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + iwe.u.data.length = 0; + iwe.len = IW_EV_POINT_LEN; + event = iwe_stream_add_point(info, event, end_buf, &iwe, bssid->ssid.essid); + + /* add rate */ + memset(&iwe, 0, sizeof(iwe)); + current_val = event + IW_EV_LCP_LEN; + iwe.cmd = SIOCGIWRATE; + if (bssid->length > sizeof(*bssid)) + nrates = NDIS_MAX_RATES_EX; + else + nrates = NDIS_MAX_RATES; + for (i = 0 ; i < nrates ; i++) { + if (bssid->rates[i] & 0x7f) { + iwe.u.bitrate.value = ((bssid->rates[i] & 0x7f) * + 500000); + current_val = iwe_stream_add_value(info, event, current_val, + end_buf, &iwe, + IW_EV_PARAM_LEN); + } + } + + if ((current_val - event) > IW_EV_LCP_LEN) + event = current_val; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "bcn_int=%d", bssid->config.beacon_period); + iwe.u.data.length = strlen(buf); + event = iwe_stream_add_point(info, event, end_buf, &iwe, buf); + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "atim=%u", bssid->config.atim_window); + iwe.u.data.length = strlen(buf); + event = iwe_stream_add_point(info, event, end_buf, &iwe, buf); + + TRACE2("%d, %u", bssid->length, (unsigned int)sizeof(*bssid)); + if (bssid->length > sizeof(*bssid)) { + unsigned char *iep = (unsigned char *)bssid_ex->ies + + sizeof(struct ndis_fixed_ies); + no_warn_unused unsigned char *end = iep + bssid_ex->ie_length; + + while (iep + 1 < end && iep + 2 + iep[1] <= end) { + unsigned char ielen = 2 + iep[1]; + + if (ielen > SSID_MAX_WPA_IE_LEN) { + iep += ielen; + continue; + } + if ((iep[0] == WLAN_EID_GENERIC && iep[1] >= 4 && + memcmp(iep + 2, "\x00\x50\xf2\x01", 4) == 0) || + iep[0] == RSN_INFO_ELEM) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ielen; + event = iwe_stream_add_point(info, event, end_buf, + &iwe, iep); + } + iep += ielen; + } + } + TRACE2("event = %p, current_val = %p", event, current_val); + EXIT2(return event); +} + +int set_scan(struct ndis_device *wnd) +{ + NDIS_STATUS res; + + ENTER2(""); + res = mp_set(wnd, OID_802_11_BSSID_LIST_SCAN, NULL, 0); + if (res) { + WARNING("scanning failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + wnd->scan_timestamp = jiffies; + EXIT2(return 0); +} + +static int iw_set_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + return set_scan(wnd); +} + +static int iw_get_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + unsigned int i, list_len, needed; + NDIS_STATUS res; + struct ndis_bssid_list *bssid_list = NULL; + char *event = extra; + struct ndis_wlan_bssid *cur_item ; + + ENTER2(""); + if (time_before(jiffies, wnd->scan_timestamp + 3 * HZ)) + return -EAGAIN; + /* try with space for a few scan items */ + list_len = sizeof(ULONG) + sizeof(struct ndis_wlan_bssid_ex) * 8; + bssid_list = kmalloc(list_len, GFP_KERNEL); + if (!bssid_list) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + /* some drivers don't set bssid_list->num_items to 0 if + OID_802_11_BSSID_LIST returns no items (prism54 driver, e.g.,) */ + memset(bssid_list, 0, list_len); + + needed = 0; + res = mp_query_info(wnd, OID_802_11_BSSID_LIST, + bssid_list, list_len, NULL, &needed); + if (res == NDIS_STATUS_INVALID_LENGTH || + res == NDIS_STATUS_BUFFER_TOO_SHORT) { + /* now try with required space */ + kfree(bssid_list); + list_len = needed; + bssid_list = kmalloc(list_len, GFP_KERNEL); + if (!bssid_list) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + memset(bssid_list, 0, list_len); + + res = mp_query(wnd, OID_802_11_BSSID_LIST, + bssid_list, list_len); + } + if (res) { + WARNING("getting BSSID list failed (%08X)", res); + kfree(bssid_list); + EXIT2(return -EOPNOTSUPP); + } + TRACE2("%d", bssid_list->num_items); + cur_item = &bssid_list->bssid[0]; + for (i = 0; i < bssid_list->num_items; i++) { + event = ndis_translate_scan(dev, event, + extra + IW_SCAN_MAX_DATA, cur_item, info); + cur_item = (struct ndis_wlan_bssid *)((char *)cur_item + + cur_item->length); + } + wrqu->data.length = event - extra; + wrqu->data.flags = 0; + kfree(bssid_list); + EXIT2(return 0); +} + +static int iw_set_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ULONG power_mode; + + if (wrqu->power.disabled == 1) + power_mode = NDIS_POWER_OFF; + else if (wrqu->power.flags & IW_POWER_MIN) + power_mode = NDIS_POWER_MIN; + else // if (wrqu->power.flags & IW_POWER_MAX) + power_mode = NDIS_POWER_MAX; + + TRACE2("%d", power_mode); + res = mp_set(wnd, OID_802_11_POWER_MODE, + &power_mode, sizeof(power_mode)); + if (res) + WARNING("setting power mode failed (%08X)", res); + return 0; +} + +static int iw_get_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ULONG power_mode; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_POWER_MODE, + &power_mode, sizeof(power_mode)); + if (res) + return -ENOTSUPP; + + if (power_mode == NDIS_POWER_OFF) + wrqu->power.disabled = 1; + else { + if (wrqu->power.flags != 0) + return 0; + wrqu->power.flags |= IW_POWER_ALL_R; + wrqu->power.flags |= IW_POWER_TIMEOUT; + wrqu->power.value = 0; + wrqu->power.disabled = 0; + + if (power_mode == NDIS_POWER_MIN) + wrqu->power.flags |= IW_POWER_MIN; + else // if (power_mode == NDIS_POWER_MAX) + wrqu->power.flags |= IW_POWER_MAX; + } + return 0; +} + +static int iw_get_sensitivity(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ndis_rssi rssi_trigger; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_RSSI_TRIGGER, + &rssi_trigger, sizeof(rssi_trigger)); + if (res) + return -EOPNOTSUPP; + wrqu->param.value = rssi_trigger; + wrqu->param.disabled = (rssi_trigger == 0); + wrqu->param.fixed = 1; + return 0; +} + +static int iw_set_sensitivity(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ndis_rssi rssi_trigger; + + ENTER2(""); + if (wrqu->param.disabled) + rssi_trigger = 0; + else + rssi_trigger = wrqu->param.value; + res = mp_set(wnd, OID_802_11_RSSI_TRIGGER, + &rssi_trigger, sizeof(rssi_trigger)); + if (res == NDIS_STATUS_INVALID_DATA) + return -EINVAL; + if (res) + return -EOPNOTSUPP; + return 0; +} + +static int iw_get_ndis_stats(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct iw_statistics *stats = &wnd->iw_stats; + memcpy(&wrqu->qual, &stats->qual, sizeof(stats->qual)); + return 0; +} + +static int iw_get_range(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + struct iw_point *data = &wrqu->data; + struct ndis_device *wnd = netdev_priv(dev); + unsigned int i, n; + NDIS_STATUS res; + ndis_rates_ex rates; + ndis_tx_power_level tx_power; + + ENTER2(""); + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + range->txpower_capa = IW_TXPOW_MWATT; + range->num_txpower = 0; + + res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL, + &tx_power, sizeof(tx_power)); + if (!res) { + range->num_txpower = 1; + range->txpower[0] = tx_power; + } + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 18; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; + + range->num_channels = 1; + + range->max_qual.qual = 100; + range->max_qual.level = 154; + range->max_qual.noise = 154; + range->sensitivity = 3; + + range->max_encoding_tokens = 4; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + range->num_bitrates = 0; + memset(&rates, 0, sizeof(rates)); + res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES, + &rates, sizeof(rates), &n, NULL); + if (res) + WARNING("getting bit rates failed: %08X", res); + else { + for (i = 0; i < n && range->num_bitrates < IW_MAX_BITRATES; i++) + if (rates[i] & 0x80) + continue; + else if (rates[i] & 0x7f) { + range->bitrate[range->num_bitrates] = + (rates[i] & 0x7f) * 500000; + range->num_bitrates++; + } + } + + range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0])); + + for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) && + i < IW_MAX_FREQUENCIES; i++) { + range->freq[i].i = i + 1; + range->freq[i].m = freq_chan[i] * 100000; + range->freq[i].e = 1; + } + range->num_frequency = i; + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) | + IW_EVENT_CAPA_MASK(IWEVCUSTOM) | + IW_EVENT_CAPA_MASK(IWEVREGISTERED) | + IW_EVENT_CAPA_MASK(IWEVEXPIRED)); + + range->enc_capa = 0; + + if (test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr)) + range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; + if (test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr)) + range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; + + if (test_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth) || + test_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth)) + range->enc_capa |= IW_ENC_CAPA_WPA; + if (test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) || + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth)) + range->enc_capa |= IW_ENC_CAPA_WPA2; + + return 0; +} + +void set_default_iw_params(struct ndis_device *wnd) +{ + wnd->iw_auth_key_mgmt = 0; + wnd->iw_auth_wpa_version = 0; + set_infra_mode(wnd, Ndis802_11Infrastructure); + set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen); + set_priv_filter(wnd); + set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE); +} + +static int deauthenticate(struct ndis_device *wnd) +{ + int ret; + + ENTER2(""); + ret = disassociate(wnd, 1); + set_default_iw_params(wnd); + EXIT2(return ret); +} + +NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid) +{ + NDIS_STATUS res; + u8 buf[NDIS_ESSID_MAX_SIZE]; + int i; + + TRACE2(""); + res = mp_set(wnd, OID_802_11_DISASSOCIATE, NULL, 0); + /* disassociate causes radio to be turned off; if reset_ssid + * is given, set ssid to random to enable radio */ + if (reset_ssid) { + get_random_bytes(buf, sizeof(buf)); + for (i = 0; i < sizeof(buf); i++) + buf[i] = 'a' + (buf[i] % 26); + set_essid(wnd, buf, sizeof(buf)); + } + return res; +} + +static ULONG ndis_priv_mode(struct ndis_device *wnd) +{ + if (wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2 || + wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA) + return Ndis802_11PrivFilter8021xWEP; + else + return Ndis802_11PrivFilterAcceptAll; +} + +int set_priv_filter(struct ndis_device *wnd) +{ + NDIS_STATUS res; + ULONG flags; + + flags = ndis_priv_mode(wnd); + ENTER2("filter: %d", flags); + res = mp_set_int(wnd, OID_802_11_PRIVACY_FILTER, flags); + if (res) + TRACE2("setting privacy filter to %d failed (%08X)", + flags, res); + EXIT2(return 0); +} + +static int iw_set_mlme(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + + ENTER2(""); + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + return deauthenticate(wnd); + case IW_MLME_DISASSOC: + TRACE2("cmd=%d reason_code=%d", mlme->cmd, mlme->reason_code); + return disassociate(wnd, 1); + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int iw_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* + * NDIS drivers do not allow IEs to be configured; this is + * done by the driver based on other configuration. Return 0 + * to avoid causing issues with user space programs that + * expect this function to succeed. + */ + return 0; +} + +static int iw_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + TRACE2("index=%d value=%d", wrqu->param.flags & IW_AUTH_INDEX, + wrqu->param.value); + switch (wrqu->param.flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + wnd->iw_auth_wpa_version = wrqu->param.value; + break; + case IW_AUTH_CIPHER_PAIRWISE: + wnd->iw_auth_cipher_pairwise = wrqu->param.value; + break; + case IW_AUTH_CIPHER_GROUP: + wnd->iw_auth_cipher_group = wrqu->param.value; + break; + case IW_AUTH_KEY_MGMT: + wnd->iw_auth_key_mgmt = wrqu->param.value; + break; + case IW_AUTH_80211_AUTH_ALG: + wnd->iw_auth_80211_alg = wrqu->param.value; + break; + case IW_AUTH_WPA_ENABLED: + if (wrqu->param.value) + deauthenticate(wnd); + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_PRIVACY_INVOKED: + TRACE2("%d not implemented: %d", + wrqu->param.flags & IW_AUTH_INDEX, wrqu->param.value); + break; + default: + WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX); + return -EOPNOTSUPP; + } + return 0; +} + +static int iw_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + + ENTER2("index=%d", wrqu->param.flags & IW_AUTH_INDEX); + switch (wrqu->param.flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + wrqu->param.value = wnd->iw_auth_wpa_version; + break; + case IW_AUTH_CIPHER_PAIRWISE: + wrqu->param.value = wnd->iw_auth_cipher_pairwise; + break; + case IW_AUTH_CIPHER_GROUP: + wrqu->param.value = wnd->iw_auth_cipher_group; + break; + case IW_AUTH_KEY_MGMT: + wrqu->param.value = wnd->iw_auth_key_mgmt; + break; + case IW_AUTH_80211_AUTH_ALG: + wrqu->param.value = wnd->iw_auth_80211_alg; + break; + default: + WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX); + return -EOPNOTSUPP; + } + return 0; +} + +static int iw_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct ndis_device *wnd = netdev_priv(dev); + struct ndis_add_key ndis_key; + int i, keyidx; + NDIS_STATUS res; + u8 *addr; + + keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; + ENTER2("%d", keyidx); + if (keyidx) + keyidx--; + else + keyidx = wnd->encr_info.tx_key_index; + + if (keyidx < 0 || keyidx >= MAX_ENCR_KEYS) + return -EINVAL; + + if (ext->alg == WPA_ALG_WEP) { + if (!test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr)) + EXIT2(return -1); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + wnd->encr_info.tx_key_index = keyidx; + if (add_wep_key(wnd, ext->key, ext->key_len, keyidx)) + EXIT2(return -1); + else + EXIT2(return 0); + } + if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) + EXIT2(return remove_key(wnd, keyidx, ndis_key.bssid)); + + if (ext->key_len > sizeof(ndis_key.key)) { + TRACE2("incorrect key length (%u)", ext->key_len); + EXIT2(return -1); + } + + memset(&ndis_key, 0, sizeof(ndis_key)); + + ndis_key.struct_size = + sizeof(ndis_key) - sizeof(ndis_key.key) + ext->key_len; + ndis_key.length = ext->key_len; + ndis_key.index = keyidx; + + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + for (i = 0; i < 6 ; i++) + ndis_key.rsc |= (((u64)ext->rx_seq[i]) << (i * 8)); + TRACE2("0x%Lx", ndis_key.rsc); + ndis_key.index |= 1 << 29; + } + + addr = ext->addr.sa_data; + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* group key */ + if (wnd->infrastructure_mode == Ndis802_11IBSS) + memset(ndis_key.bssid, 0xff, ETH_ALEN); + else + get_ap_address(wnd, ndis_key.bssid); + } else { + /* pairwise key */ + ndis_key.index |= (1 << 30); + memcpy(ndis_key.bssid, addr, ETH_ALEN); + } + TRACE2(MACSTRSEP, MAC2STR(ndis_key.bssid)); + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + ndis_key.index |= (1 << 31); + + if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) { + /* wpa_supplicant gives us the Michael MIC RX/TX keys in + * different order than NDIS spec, so swap the order here. */ + memcpy(ndis_key.key, ext->key, 16); + memcpy(ndis_key.key + 16, ext->key + 24, 8); + memcpy(ndis_key.key + 24, ext->key + 16, 8); + } else + memcpy(ndis_key.key, ext->key, ext->key_len); + + res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size); + if (res) { + TRACE2("adding key failed (%08X), %u", + res, ndis_key.struct_size); + EXIT2(return -1); + } + wnd->encr_info.keys[keyidx].length = ext->key_len; + memcpy(&wnd->encr_info.keys[keyidx].key, ndis_key.key, ext->key_len); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + wnd->encr_info.tx_key_index = keyidx; + TRACE2("key %d added", keyidx); + + EXIT2(return 0); +} + +static int iw_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; */ + /* TODO */ + ENTER2(""); + return 0; +} + +static int iw_set_pmksa(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; + struct ndis_pmkid pmkid; + NDIS_STATUS res; + struct ndis_device *wnd = netdev_priv(dev); + + /* TODO: must keep local list of PMKIDs since NDIS drivers + * expect that all PMKID entries are included whenever a new + * one is added. */ + + ENTER2("%d", pmksa->cmd); + if ((pmksa->cmd == IW_PMKSA_ADD || pmksa->cmd == IW_PMKSA_REMOVE) && + (!(wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2))) + EXIT2(return -EOPNOTSUPP); + + memset(&pmkid, 0, sizeof(pmkid)); + if (pmksa->cmd == IW_PMKSA_ADD) { + pmkid.bssid_info_count = 1; + memcpy(pmkid.bssid_info[0].bssid, pmksa->bssid.sa_data, + ETH_ALEN); + memcpy(pmkid.bssid_info[0].pmkid, pmksa->pmkid, IW_PMKID_LEN); + } + pmkid.length = sizeof(pmkid); + + res = mp_set(wnd, OID_802_11_PMKID, &pmkid, pmkid.length); + if (res == NDIS_STATUS_FAILURE) + EXIT2(return -EOPNOTSUPP); + TRACE2("OID_802_11_PMKID -> %d", res); + if (res) + return -EINVAL; + + return 0; +} + +#define WEXT(id) [id - SIOCIWFIRST] + +static const iw_handler ndis_handler[] = { + WEXT(SIOCGIWNAME) = iw_get_network_type, + WEXT(SIOCSIWESSID) = iw_set_essid, + WEXT(SIOCGIWESSID) = iw_get_essid, + WEXT(SIOCSIWMODE) = iw_set_infra_mode, + WEXT(SIOCGIWMODE) = iw_get_infra_mode, + WEXT(SIOCGIWFREQ) = iw_get_freq, + WEXT(SIOCSIWFREQ) = iw_set_freq, + WEXT(SIOCGIWTXPOW) = iw_get_tx_power, + WEXT(SIOCSIWTXPOW) = iw_set_tx_power, + WEXT(SIOCGIWRATE) = iw_get_bitrate, + WEXT(SIOCSIWRATE) = iw_set_bitrate, + WEXT(SIOCGIWRTS) = iw_get_rts_threshold, + WEXT(SIOCSIWRTS) = iw_set_rts_threshold, + WEXT(SIOCGIWFRAG) = iw_get_frag_threshold, + WEXT(SIOCSIWFRAG) = iw_set_frag_threshold, + WEXT(SIOCGIWAP) = iw_get_ap_address, + WEXT(SIOCSIWAP) = iw_set_ap_address, + WEXT(SIOCSIWENCODE) = iw_set_wep, + WEXT(SIOCGIWENCODE) = iw_get_encr, + WEXT(SIOCSIWSCAN) = iw_set_scan, + WEXT(SIOCGIWSCAN) = iw_get_scan, + WEXT(SIOCGIWPOWER) = iw_get_power_mode, + WEXT(SIOCSIWPOWER) = iw_set_power_mode, + WEXT(SIOCGIWRANGE) = iw_get_range, + WEXT(SIOCGIWSTATS) = iw_get_ndis_stats, + WEXT(SIOCGIWSENS) = iw_get_sensitivity, + WEXT(SIOCSIWSENS) = iw_set_sensitivity, + WEXT(SIOCGIWNICKN) = iw_get_nick, + WEXT(SIOCSIWNICKN) = iw_set_nick, + WEXT(SIOCSIWCOMMIT) = iw_set_dummy, + WEXT(SIOCSIWMLME) = iw_set_mlme, + WEXT(SIOCSIWGENIE) = iw_set_genie, + WEXT(SIOCSIWAUTH) = iw_set_auth, + WEXT(SIOCGIWAUTH) = iw_get_auth, + WEXT(SIOCSIWENCODEEXT) = iw_set_encodeext, + WEXT(SIOCGIWENCODEEXT) = iw_get_encodeext, + WEXT(SIOCSIWPMKSA) = iw_set_pmksa, +}; + +/* private ioctl's */ + +static int priv_reset(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int res; + ENTER2(""); + res = mp_reset(netdev_priv(dev)); + if (res) { + WARNING("reset failed: %08X", res); + return -EOPNOTSUPP; + } + return 0; +} + +static int priv_deauthenticate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int res; + ENTER2(""); + res = deauthenticate(netdev_priv(dev)); + return res; +} + +static int priv_power_profile(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct miniport *mp; + ULONG profile_inf; + + ENTER2(""); + mp = &wnd->wd->driver->ndis_driver->mp; + if (!mp->pnp_event_notify) + EXIT2(return -EOPNOTSUPP); + + /* 1 for AC and 0 for Battery */ + if (wrqu->param.value) + profile_inf = NdisPowerProfileAcOnLine; + else + profile_inf = NdisPowerProfileBattery; + + LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx, + NdisDevicePnPEventPowerProfileChanged, + &profile_inf, sizeof(profile_inf)); + EXIT2(return 0); +} + +static int priv_network_type(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + enum network_type network_type; + NDIS_STATUS res; + char type; + + ENTER2(""); + type = wrqu->param.value; + if (type == 'f') + network_type = Ndis802_11FH; + else if (type == 'b') + network_type = Ndis802_11DS; + else if (type == 'a') + network_type = Ndis802_11OFDM5; + else if (type == 'g' || type == 'n') + network_type = Ndis802_11OFDM24; + else + network_type = Ndis802_11Automode; + + res = mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, network_type); + if (res) { + WARNING("setting network type to %d failed (%08X)", + network_type, res); + EXIT2(return -EINVAL); + } + + EXIT2(return 0); +} + +static int priv_media_stream_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + int mode; + + ENTER2(""); + if (wrqu->param.value > 0) + mode = Ndis802_11MediaStreamOn; + else + mode = Ndis802_11MediaStreamOff; + res = mp_set_int(wnd, OID_802_11_MEDIA_STREAM_MODE, mode); + if (res) { + WARNING("oid failed (%08X)", res); + EXIT2(return -EINVAL); + } + EXIT2(return 0); +} + +static int priv_reload_defaults(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int res; + ENTER2(""); + res = mp_set_int(wnd, OID_802_11_RELOAD_DEFAULTS, + Ndis802_11ReloadWEPKeys); + if (res) { + WARNING("reloading defaults failed: %08X", res); + return -EOPNOTSUPP; + } + return 0; +} + +static const struct iw_priv_args priv_args[] = { + {PRIV_RESET, 0, 0, "ndis_reset"}, + {PRIV_POWER_PROFILE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "power_profile"}, + {PRIV_DEAUTHENTICATE, 0, 0, "deauthenticate"}, + {PRIV_NETWORK_TYPE, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, + "network_type"}, + {PRIV_MEDIA_STREAM_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "media_stream"}, + + {PRIV_RELOAD_DEFAULTS, 0, 0, "reload_defaults"}, +}; + +#define WEPRIV(id) [id - SIOCIWFIRSTPRIV] + +static const iw_handler priv_handler[] = { + WEPRIV(PRIV_RESET) = priv_reset, + WEPRIV(PRIV_POWER_PROFILE) = priv_power_profile, + WEPRIV(PRIV_DEAUTHENTICATE) = priv_deauthenticate, + WEPRIV(PRIV_NETWORK_TYPE) = priv_network_type, + WEPRIV(PRIV_MEDIA_STREAM_MODE) = priv_media_stream_mode, + WEPRIV(PRIV_RELOAD_DEFAULTS) = priv_reload_defaults, +}; + +const struct iw_handler_def ndis_handler_def = { + .num_standard = sizeof(ndis_handler) / sizeof(ndis_handler[0]), + .num_private = sizeof(priv_handler) / sizeof(priv_handler[0]), + .num_private_args = sizeof(priv_args) / sizeof(priv_args[0]), + + .standard = (iw_handler *)ndis_handler, + .private = (iw_handler *)priv_handler, + .private_args = (struct iw_priv_args *)priv_args, + .get_wireless_stats = get_iw_stats, +}; --- linux-2.6.27.orig/ubuntu/ndiswrapper/divdi3.c +++ linux-2.6.27/ubuntu/ndiswrapper/divdi3.c @@ -0,0 +1,329 @@ +/* 64-bit multiplication and division + Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#if BITS_PER_LONG != 32 +#error This is for 32-bit targets only +#endif + +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#define Wtype SItype +#define HWtype SItype +#define DWtype DItype +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#define W_TYPE_SIZE 32 + +#include "longlong.h" + +#if defined(__BIG_ENDIAN) +struct DWstruct { Wtype high, low;}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { Wtype low, high;}; +#else +#error Unhandled endianity +#endif +typedef union { struct DWstruct s; DWtype ll; } DWunion; + +/* Prototypes of exported functions. */ +extern DWtype __divdi3 (DWtype u, DWtype v); +extern DWtype __moddi3 (DWtype u, DWtype v); +extern UDWtype __udivdi3 (UDWtype u, UDWtype v); +extern UDWtype __umoddi3 (UDWtype u, UDWtype v); + +static UDWtype +__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) +{ + DWunion ww; + DWunion nn, dd; + DWunion rr; + UWtype d0, d1, n0, n1, n2; + UWtype q0, q1; + UWtype b, bm; + + nn.ll = n; + dd.ll = d; + + d0 = dd.s.low; + d1 = dd.s.high; + n0 = nn.s.low; + n1 = nn.s.high; + +#if !UDIV_NEEDS_NORMALIZATION + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + udiv_qrnnd (q1, n1, 0, n1, d0); + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0. */ + } + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = 0; + *rp = rr.ll; + } + } + +#else /* UDIV_NEEDS_NORMALIZATION */ + + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + count_leading_zeros (bm, d0); + + if (bm != 0) + { + /* Normalize, i.e. make the most significant bit of the + denominator set. */ + + d0 = d0 << bm; + n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); + n0 = n0 << bm; + } + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0 >> bm. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + count_leading_zeros (bm, d0); + + if (bm == 0) + { + /* From (n1 >= d0) /\ (the most significant bit of d0 is set), + conclude (the most significant bit of n1 is set) /\ (the + leading quotient digit q1 = 1). + + This special case is necessary, not an optimization. + (Shifts counts of W_TYPE_SIZE are undefined.) */ + + n1 -= d0; + q1 = 1; + } + else + { + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q1, n1, n2, n1, d0); + } + + /* n1 != d0... */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0 >> bm. */ + } + + if (rp != 0) + { + rr.s.low = n0 >> bm; + rr.s.high = 0; + *rp = rr.ll; + } + } +#endif /* UDIV_NEEDS_NORMALIZATION */ + + else + { + if (d1 > n1) + { + /* 00 = nn / DD */ + + q0 = 0; + q1 = 0; + + /* Remainder in n1n0. */ + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + /* 0q = NN / dd */ + + count_leading_zeros (bm, d1); + if (bm == 0) + { + /* From (n1 >= d1) /\ (the most significant bit of d1 is set), + conclude (the most significant bit of n1 is set) /\ (the + quotient digit q0 = 0 or 1). + + This special case is necessary, not an optimization. */ + + /* The condition on the next line takes advantage of that + n1 >= d1 (true due to program flow). */ + if (n1 > d1 || n0 >= d0) + { + q0 = 1; + sub_ddmmss (n1, n0, n1, n0, d1, d0); + } + else + q0 = 0; + + q1 = 0; + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + UWtype m1, m0; + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d1 = (d1 << bm) | (d0 >> b); + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q0, n1, n2, n1, d1); + umul_ppmm (m1, m0, q0, d0); + + if (m1 > n1 || (m1 == n1 && m0 > n0)) + { + q0--; + sub_ddmmss (m1, m0, m1, m0, d1, d0); + } + + q1 = 0; + + /* Remainder in (n1n0 - m1m0) >> bm. */ + if (rp != 0) + { + sub_ddmmss (n1, n0, n1, n0, m1, m0); + rr.s.low = (n1 << b) | (n0 >> bm); + rr.s.high = n1 >> bm; + *rp = rr.ll; + } + } + } + } + + ww.s.low = q0; + ww.s.high = q1; + return ww.ll; +} + +DWtype +__divdi3 (DWtype u, DWtype v) +{ + Wtype c = 0; + DWtype w; + + if (u < 0) + { + c = ~c; + u = -u; + } + if (v < 0) + { + c = ~c; + v = -v; + } + w = __udivmoddi4 (u, v, NULL); + if (c) + w = -w; + return w; +} + +DWtype +__moddi3 (DWtype u, DWtype v) +{ + Wtype c = 0; + DWtype w; + + if (u < 0) + { + c = ~c; + u = -u; + } + if (v < 0) + v = -v; + __udivmoddi4 (u, v, &w); + if (c) + w = -w; + return w; +} + +UDWtype +__udivdi3 (UDWtype u, UDWtype v) +{ + return __udivmoddi4 (u, v, NULL); +} + +UDWtype +__umoddi3 (UDWtype u, UDWtype v) +{ + UDWtype w; + + __udivmoddi4 (u, v, &w); + return w; +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/loader.c +++ linux-2.6.27/ubuntu/ndiswrapper/loader.c @@ -0,0 +1,877 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ndis.h" +#include "loader.h" +#include "wrapndis.h" +#include "pnp.h" + +#include +#include +#include +#include + +/* + Network adapter: ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318} + Network client: ClassGuid = {4d36e973-e325-11ce-bfc1-08002be10318} + PCMCIA adapter: ClassGuid = {4d36e977-e325-11ce-bfc1-08002be10318} + USB: ClassGuid = {36fc9e60-c465-11cf-8056-444553540000} +*/ + +/* the indices used here must match macros WRAP_NDIS_DEVICE etc. */ +static struct guid class_guids[] = { + /* Network */ + {0x4d36e972, 0xe325, 0x11ce, }, + /* USB WDM */ + {0x36fc9e60, 0xc465, 0x11cf, }, + /* Bluetooth */ + {0xe0cbf06c, 0xcd8b, 0x4647, }, + /* ivtcorporatino.com's bluetooth device claims this is + * bluetooth guid */ + {0xf12d3cf8, 0xb11d, 0x457e, }, +}; + +struct semaphore loader_mutex; +static struct completion loader_complete; + +static struct nt_list wrap_devices; +static struct nt_list wrap_drivers; + +static int wrap_device_type(int data1) +{ + int i; + for (i = 0; i < sizeof(class_guids) / sizeof(class_guids[0]); i++) + if (data1 == class_guids[i].data1) + return i; + ERROR("unknown device: 0x%x\n", data1); + return -1; +} + +/* load driver for given device, if not already loaded */ +struct wrap_driver *load_wrap_driver(struct wrap_device *wd) +{ + int ret; + struct nt_list *cur; + struct wrap_driver *wrap_driver; + + ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device, + wd->subvendor, wd->subdevice); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + wrap_driver = NULL; + nt_list_for_each(cur, &wrap_drivers) { + wrap_driver = container_of(cur, struct wrap_driver, list); + if (!stricmp(wrap_driver->name, wd->driver_name)) { + TRACE1("driver %s already loaded", wrap_driver->name); + break; + } else + wrap_driver = NULL; + } + up(&loader_mutex); + + if (!wrap_driver) { + char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER, +#if defined(DEBUG) && DEBUG >= 1 + "1", +#else + "0", +#endif + UTILS_VERSION, wd->driver_name, + wd->conf_file_name, NULL}; + char *env[] = {NULL}; + + TRACE1("loading driver %s", wd->driver_name); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + INIT_COMPLETION(loader_complete); + ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1); + if (ret) { + up(&loader_mutex); + ERROR("couldn't load driver %s; check system log " + "for messages from 'loadndisdriver'", + wd->driver_name); + EXIT1(return NULL); + } + wait_for_completion(&loader_complete); + TRACE1("%s", wd->driver_name); + wrap_driver = NULL; + nt_list_for_each(cur, &wrap_drivers) { + wrap_driver = container_of(cur, struct wrap_driver, + list); + if (!stricmp(wrap_driver->name, wd->driver_name)) { + wd->driver = wrap_driver; + break; + } else + wrap_driver = NULL; + } + up(&loader_mutex); + if (wrap_driver) + TRACE1("driver %s is loaded", wrap_driver->name); + else + ERROR("couldn't load driver '%s'", wd->driver_name); + } + EXIT1(return wrap_driver); +} + +/* load the driver files from userspace. */ +static int load_sys_files(struct wrap_driver *driver, + struct load_driver *load_driver) +{ + int i, err; + + TRACE1("num_pe_images = %d", load_driver->num_sys_files); + TRACE1("loading driver: %s", load_driver->name); + strncpy(driver->name, load_driver->name, sizeof(driver->name)); + driver->name[sizeof(driver->name)-1] = 0; + TRACE1("driver: %s", driver->name); + err = 0; + driver->num_pe_images = 0; + for (i = 0; i < load_driver->num_sys_files; i++) { + struct pe_image *pe_image; + pe_image = &driver->pe_images[driver->num_pe_images]; + + strncpy(pe_image->name, load_driver->sys_files[i].name, + sizeof(pe_image->name)); + pe_image->name[sizeof(pe_image->name)-1] = 0; + TRACE1("image size: %lu bytes", + (unsigned long)load_driver->sys_files[i].size); + +#ifdef CONFIG_X86_64 +#ifdef PAGE_KERNEL_EXECUTABLE + pe_image->image = + __vmalloc(load_driver->sys_files[i].size, + GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXECUTABLE); +#elif defined PAGE_KERNEL_EXEC + pe_image->image = + __vmalloc(load_driver->sys_files[i].size, + GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXEC); +#else +#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC +#endif +#else + /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is + * not available to modules! */ +#ifdef cpu_has_nx + if (cpu_has_nx) + pe_image->image = + __vmalloc(load_driver->sys_files[i].size, + GFP_KERNEL | __GFP_HIGHMEM, + __pgprot(__PAGE_KERNEL & ~_PAGE_NX)); + else + pe_image->image = + vmalloc(load_driver->sys_files[i].size); +#else + pe_image->image = + vmalloc(load_driver->sys_files[i].size); +#endif +#endif + if (!pe_image->image) { + ERROR("couldn't allocate memory"); + err = -ENOMEM; + break; + } + TRACE1("image is at %p", pe_image->image); + + if (copy_from_user(pe_image->image, + load_driver->sys_files[i].data, + load_driver->sys_files[i].size)) { + ERROR("couldn't load file %s", + load_driver->sys_files[i].name); + err = -EFAULT; + break; + } + pe_image->size = load_driver->sys_files[i].size; + driver->num_pe_images++; + } + + if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) { + ERROR("couldn't prepare driver '%s'", load_driver->name); + err = -EINVAL; + } + + if (driver->num_pe_images < load_driver->num_sys_files || err) { + for (i = 0; i < driver->num_pe_images; i++) + if (driver->pe_images[i].image) + vfree(driver->pe_images[i].image); + driver->num_pe_images = 0; + EXIT1(return err); + } else + EXIT1(return 0); +} + +struct wrap_bin_file *get_bin_file(char *bin_file_name) +{ + int i = 0; + struct wrap_driver *driver, *cur; + + ENTER1("%s", bin_file_name); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + driver = NULL; + nt_list_for_each_entry(cur, &wrap_drivers, list) { + for (i = 0; i < cur->num_bin_files; i++) + if (!stricmp(cur->bin_files[i].name, bin_file_name)) { + driver = cur; + break; + } + if (driver) + break; + } + up(&loader_mutex); + if (!driver) { + TRACE1("coudln't find bin file '%s'", bin_file_name); + return NULL; + } + + if (!driver->bin_files[i].data) { + char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE, +#if defined(DEBUG) && DEBUG >= 1 + "1", +#else + "0", +#endif + UTILS_VERSION, driver->name, + driver->bin_files[i].name, NULL}; + char *env[] = {NULL}; + int ret; + + TRACE1("loading bin file %s/%s", driver->name, + driver->bin_files[i].name); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + INIT_COMPLETION(loader_complete); + ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1); + if (ret) { + up(&loader_mutex); + ERROR("couldn't load file %s/%s; check system log " + "for messages from 'loadndisdriver' (%d)", + driver->name, driver->bin_files[i].name, ret); + EXIT1(return NULL); + } + wait_for_completion(&loader_complete); + up(&loader_mutex); + if (!driver->bin_files[i].data) { + WARNING("couldn't load binary file %s", + driver->bin_files[i].name); + EXIT1(return NULL); + } + } + EXIT2(return &(driver->bin_files[i])); +} + +/* called with loader_mutex down */ +static int add_bin_file(struct load_driver_file *driver_file) +{ + struct wrap_driver *driver, *cur; + struct wrap_bin_file *bin_file; + int i = 0; + + driver = NULL; + nt_list_for_each_entry(cur, &wrap_drivers, list) { + for (i = 0; i < cur->num_bin_files; i++) + if (!stricmp(cur->bin_files[i].name, + driver_file->name)) { + driver = cur; + break; + } + if (driver) + break; + } + if (!driver) { + ERROR("couldn't find %s", driver_file->name); + return -EINVAL; + } + bin_file = &driver->bin_files[i]; + strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name)); + bin_file->name[sizeof(bin_file->name)-1] = 0; + bin_file->data = vmalloc(driver_file->size); + if (!bin_file->data) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + bin_file->size = driver_file->size; + if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) { + ERROR("couldn't copy data"); + free_bin_file(bin_file); + return -EFAULT; + } + return 0; +} + +void free_bin_file(struct wrap_bin_file *bin_file) +{ + TRACE2("unloading %s", bin_file->name); + if (bin_file->data) + vfree(bin_file->data); + bin_file->data = NULL; + bin_file->size = 0; + EXIT2(return); +} + +/* load firmware files from userspace */ +static int load_bin_files_info(struct wrap_driver *driver, + struct load_driver *load_driver) +{ + struct wrap_bin_file *bin_files; + int i; + + ENTER1("%s, %d", load_driver->name, load_driver->num_bin_files); + driver->num_bin_files = 0; + driver->bin_files = NULL; + if (load_driver->num_bin_files == 0) + EXIT1(return 0); + bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files), + GFP_KERNEL); + if (!bin_files) { + ERROR("couldn't allocate memory"); + EXIT1(return -ENOMEM); + } + + for (i = 0; i < load_driver->num_bin_files; i++) { + strncpy(bin_files[i].name, load_driver->bin_files[i].name, + sizeof(bin_files[i].name)); + bin_files[i].name[sizeof(bin_files[i].name)-1] = 0; + TRACE2("loaded bin file %s", bin_files[i].name); + } + driver->num_bin_files = load_driver->num_bin_files; + driver->bin_files = bin_files; + EXIT1(return 0); +} + +/* load settnigs for a device. called with loader_mutex down */ +static int load_settings(struct wrap_driver *wrap_driver, + struct load_driver *load_driver) +{ + int i, num_settings; + + ENTER1("%p, %p", wrap_driver, load_driver); + + num_settings = 0; + for (i = 0; i < load_driver->num_settings; i++) { + struct load_device_setting *load_setting = + &load_driver->settings[i]; + struct wrap_device_setting *setting; + ULONG data1; + + setting = kzalloc(sizeof(*setting), GFP_KERNEL); + if (!setting) { + ERROR("couldn't allocate memory"); + break; + } + strncpy(setting->name, load_setting->name, + sizeof(setting->name)); + setting->name[sizeof(setting->name)-1] = 0; + strncpy(setting->value, load_setting->value, + sizeof(setting->value)); + setting->value[sizeof(setting->value)-1] = 0; + TRACE2("%p: %s=%s", setting, setting->name, setting->value); + + if (strcmp(setting->name, "driver_version") == 0) { + strncpy(wrap_driver->version, setting->value, + sizeof(wrap_driver->version)); + wrap_driver->version[sizeof(wrap_driver->version)-1] = 0; + } else if (strcmp(setting->name, "class_guid") == 0 && + sscanf(setting->value, "%x", &data1) == 1) { + wrap_driver->dev_type = wrap_device_type(data1); + if (wrap_driver->dev_type < 0) { + WARNING("unknown guid: %x", data1); + wrap_driver->dev_type = 0; + } + } + InsertTailList(&wrap_driver->settings, &setting->list); + num_settings++; + } + /* it is not a fatal error if some settings couldn't be loaded */ + if (num_settings > 0) + EXIT1(return 0); + else + EXIT1(return -EINVAL); +} + +void unload_wrap_device(struct wrap_device *wd) +{ + struct nt_list *cur; + ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd, + wd->vendor, wd->device, wd->subvendor, wd->subdevice, + wd->driver_name); + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + while ((cur = RemoveHeadList(&wd->settings))) { + struct wrap_device_setting *setting; + setting = container_of(cur, struct wrap_device_setting, list); + kfree(setting); + } + RemoveEntryList(&wd->list); + up(&loader_mutex); + kfree(wd); + EXIT1(return); +} + +/* should be called with loader_mutex down */ +void unload_wrap_driver(struct wrap_driver *driver) +{ + int i; + struct driver_object *drv_obj; + struct nt_list *cur, *next; + + ENTER1("unloading driver: %s (%p)", driver->name, driver); + TRACE1("freeing %d images", driver->num_pe_images); + drv_obj = driver->drv_obj; + for (i = 0; i < driver->num_pe_images; i++) + if (driver->pe_images[i].image) { + TRACE1("freeing image at %p", + driver->pe_images[i].image); + vfree(driver->pe_images[i].image); + } + + TRACE1("freeing %d bin files", driver->num_bin_files); + for (i = 0; i < driver->num_bin_files; i++) { + TRACE1("freeing image at %p", driver->bin_files[i].data); + if (driver->bin_files[i].data) + vfree(driver->bin_files[i].data); + } + if (driver->bin_files) + kfree(driver->bin_files); + RtlFreeUnicodeString(&drv_obj->name); + RemoveEntryList(&driver->list); + nt_list_for_each_safe(cur, next, &driver->settings) { + struct wrap_device_setting *setting; + struct ndis_configuration_parameter *param; + + setting = container_of(cur, struct wrap_device_setting, list); + TRACE2("%p", setting); + param = setting->encoded; + if (param) { + TRACE2("%p", param); + if (param->type == NdisParameterString) + RtlFreeUnicodeString(¶m->data.string); + ExFreePool(param); + } + kfree(setting); + } + /* this frees driver */ + free_custom_extensions(drv_obj->drv_ext); + kfree(drv_obj->drv_ext); + TRACE1("drv_obj: %p", drv_obj); + + EXIT1(return); +} + +/* call the entry point of the driver */ +static int start_wrap_driver(struct wrap_driver *driver) +{ + int i; + NTSTATUS ret, res; + struct driver_object *drv_obj; + typeof(driver->pe_images[0].entry) entry; + + ENTER1("%s", driver->name); + drv_obj = driver->drv_obj; + for (ret = res = 0, i = 0; i < driver->num_pe_images; i++) + /* dlls are already started by loader */ + if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) { + entry = driver->pe_images[i].entry; + drv_obj->start = driver->pe_images[i].entry; + drv_obj->driver_size = driver->pe_images[i].size; + TRACE1("entry: %p, %p, drv_obj: %p", + entry, *entry, drv_obj); + res = LIN2WIN2(entry, drv_obj, &drv_obj->name); + ret |= res; + TRACE1("entry returns %08X", res); + break; + } + if (ret) { + ERROR("driver initialization failed: %08X", ret); + RtlFreeUnicodeString(&drv_obj->name); + /* this frees ndis_driver */ + free_custom_extensions(drv_obj->drv_ext); + kfree(drv_obj->drv_ext); + TRACE1("drv_obj: %p", drv_obj); + ObDereferenceObject(drv_obj); + EXIT1(return -EINVAL); + } + EXIT1(return 0); +} + +/* + * add driver to list of loaded driver but make sure this driver is + * not loaded before. called with loader_mutex down + */ +static int add_wrap_driver(struct wrap_driver *driver) +{ + struct wrap_driver *tmp; + + ENTER1("name: %s", driver->name); + nt_list_for_each_entry(tmp, &wrap_drivers, list) { + if (stricmp(tmp->name, driver->name) == 0) { + ERROR("cannot add duplicate driver"); + EXIT1(return -EBUSY); + } + } + InsertHeadList(&wrap_drivers, &driver->list); + EXIT1(return 0); +} + +/* load a driver from userspace and initialize it. called with + * loader_mutex down */ +static int load_user_space_driver(struct load_driver *load_driver) +{ + struct driver_object *drv_obj; + struct ansi_string ansi_reg; + struct wrap_driver *wrap_driver = NULL; + + ENTER1("%p", load_driver); + drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL); + if (!drv_obj) { + ERROR("couldn't allocate memory"); + EXIT1(return -ENOMEM); + } + TRACE1("drv_obj: %p", drv_obj); + drv_obj->drv_ext = kzalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL); + if (!drv_obj->drv_ext) { + ERROR("couldn't allocate memory"); + ObDereferenceObject(drv_obj); + EXIT1(return -ENOMEM); + } + InitializeListHead(&drv_obj->drv_ext->custom_ext); + if (IoAllocateDriverObjectExtension(drv_obj, + (void *)WRAP_DRIVER_CLIENT_ID, + sizeof(*wrap_driver), + (void **)&wrap_driver) != + STATUS_SUCCESS) + EXIT1(return -ENOMEM); + TRACE1("driver: %p", wrap_driver); + memset(wrap_driver, 0, sizeof(*wrap_driver)); + InitializeListHead(&wrap_driver->list); + InitializeListHead(&wrap_driver->settings); + InitializeListHead(&wrap_driver->wrap_devices); + wrap_driver->drv_obj = drv_obj; + RtlInitAnsiString(&ansi_reg, "/tmp"); + if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) != + STATUS_SUCCESS) { + ERROR("couldn't initialize registry path"); + free_custom_extensions(drv_obj->drv_ext); + kfree(drv_obj->drv_ext); + TRACE1("drv_obj: %p", drv_obj); + ObDereferenceObject(drv_obj); + EXIT1(return -EINVAL); + } + strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name)); + wrap_driver->name[sizeof(wrap_driver->name)-1] = 0; + if (load_sys_files(wrap_driver, load_driver) || + load_bin_files_info(wrap_driver, load_driver) || + load_settings(wrap_driver, load_driver) || + start_wrap_driver(wrap_driver) || + add_wrap_driver(wrap_driver)) { + unload_wrap_driver(wrap_driver); + EXIT1(return -EINVAL); + } else { + printk(KERN_INFO "%s: driver %s (%s) loaded\n", + DRIVER_NAME, wrap_driver->name, wrap_driver->version); + add_taint(TAINT_PROPRIETARY_MODULE); + EXIT1(return 0); + } +} + +static struct pci_device_id wrap_pci_id_table[] = { + {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID}, +}; + +static struct pci_driver wrap_pci_driver = { + .name = DRIVER_NAME, + .id_table = wrap_pci_id_table, + .probe = wrap_pnp_start_pci_device, + .remove = __devexit_p(wrap_pnp_remove_pci_device), + .suspend = wrap_pnp_suspend_pci_device, + .resume = wrap_pnp_resume_pci_device, +}; + +#ifdef ENABLE_USB +static struct usb_device_id wrap_usb_id_table[] = { + { + .driver_info = 1 + }, +}; + +static struct usb_driver wrap_usb_driver = { + .name = DRIVER_NAME, + .id_table = wrap_usb_id_table, + .probe = wrap_pnp_start_usb_device, + .disconnect = __devexit_p(wrap_pnp_remove_usb_device), + .suspend = wrap_pnp_suspend_usb_device, + .resume = wrap_pnp_resume_usb_device, +}; +#endif + +/* register drivers for pci and usb */ +static void register_devices(void) +{ + int res; + + res = pci_register_driver(&wrap_pci_driver); + if (res < 0) { + ERROR("couldn't register pci driver: %d", res); + wrap_pci_driver.name = NULL; + } + +#ifdef ENABLE_USB + res = usb_register(&wrap_usb_driver); + if (res < 0) { + ERROR("couldn't register usb driver: %d", res); + wrap_usb_driver.name = NULL; + } +#endif + EXIT1(return); +} + +static void unregister_devices(void) +{ + struct nt_list *cur, *next; + + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_safe(cur, next, &wrap_devices) { + struct wrap_device *wd; + wd = container_of(cur, struct wrap_device, list); + set_bit(HW_PRESENT, &wd->hw_status); + } + up(&loader_mutex); + + if (wrap_pci_driver.name) + pci_unregister_driver(&wrap_pci_driver); +#ifdef ENABLE_USB + if (wrap_usb_driver.name) + usb_deregister(&wrap_usb_driver); +#endif +} + +struct wrap_device *load_wrap_device(struct load_device *load_device) +{ + int ret; + struct nt_list *cur; + struct wrap_device *wd = NULL; + char vendor[5], device[5], subvendor[5], subdevice[5], bus[5]; + + ENTER1("%04x, %04x, %04x, %04x", load_device->vendor, + load_device->device, load_device->subvendor, + load_device->subdevice); + if (sprintf(vendor, "%04x", load_device->vendor) == 4 && + sprintf(device, "%04x", load_device->device) == 4 && + sprintf(subvendor, "%04x", load_device->subvendor) == 4 && + sprintf(subdevice, "%04x", load_device->subdevice) == 4 && + sprintf(bus, "%04x", load_device->bus) == 4) { + char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE, +#if defined(DEBUG) && DEBUG >= 1 + "1", +#else + "0", +#endif + UTILS_VERSION, vendor, device, + subvendor, subdevice, bus, NULL}; + char *env[] = {NULL}; + TRACE2("%s, %s, %s, %s, %s", vendor, device, + subvendor, subdevice, bus); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + INIT_COMPLETION(loader_complete); + ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1); + if (ret) { + up(&loader_mutex); + TRACE1("couldn't load device %04x:%04x; check system " + "log for messages from 'loadndisdriver'", + load_device->vendor, load_device->device); + EXIT1(return NULL); + } + wait_for_completion(&loader_complete); + wd = NULL; + nt_list_for_each(cur, &wrap_devices) { + wd = container_of(cur, struct wrap_device, list); + TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor, + wd->device, wd->subvendor, wd->subdevice); + if (wd->vendor == load_device->vendor && + wd->device == load_device->device) + break; + else + wd = NULL; + } + up(&loader_mutex); + } else + wd = NULL; + EXIT1(return wd); +} + +struct wrap_device *get_wrap_device(void *dev, int bus) +{ + struct nt_list *cur; + struct wrap_device *wd; + + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + return NULL; + } + wd = NULL; + nt_list_for_each(cur, &wrap_devices) { + wd = container_of(cur, struct wrap_device, list); + if (bus == WRAP_PCI_BUS && + wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev) + break; + else if (bus == WRAP_USB_BUS && + wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev) + break; + else + wd = NULL; + } + up(&loader_mutex); + return wd; +} + +/* called with loader_mutex is down */ +static int wrapper_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct load_driver *load_driver; + struct load_device load_device; + struct load_driver_file load_bin_file; + int ret; + void __user *addr = (void __user *)arg; + + ENTER1("cmd: %u", cmd); + + ret = 0; + switch (cmd) { + case WRAP_IOCTL_LOAD_DEVICE: + if (copy_from_user(&load_device, addr, sizeof(load_device))) { + ret = -EFAULT; + break; + } + TRACE2("%04x, %04x, %04x, %04x", load_device.vendor, + load_device.device, load_device.subvendor, + load_device.subdevice); + if (load_device.vendor) { + struct wrap_device *wd; + wd = kzalloc(sizeof(*wd), GFP_KERNEL); + if (!wd) { + ret = -ENOMEM; + break; + } + InitializeListHead(&wd->settings); + wd->dev_bus = WRAP_BUS(load_device.bus); + wd->vendor = load_device.vendor; + wd->device = load_device.device; + wd->subvendor = load_device.subvendor; + wd->subdevice = load_device.subdevice; + strncpy(wd->conf_file_name, load_device.conf_file_name, + sizeof(wd->conf_file_name)); + wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0; + strncpy(wd->driver_name, load_device.driver_name, + sizeof(wd->driver_name)); + wd->driver_name[sizeof(wd->driver_name)-1] = 0; + InsertHeadList(&wrap_devices, &wd->list); + ret = 0; + } else + ret = -EINVAL; + break; + case WRAP_IOCTL_LOAD_DRIVER: + TRACE1("loading driver at %p", addr); + load_driver = vmalloc(sizeof(*load_driver)); + if (!load_driver) { + ret = -ENOMEM; + break; + } + if (copy_from_user(load_driver, addr, sizeof(*load_driver))) + ret = -EFAULT; + else + ret = load_user_space_driver(load_driver); + vfree(load_driver); + break; + case WRAP_IOCTL_LOAD_BIN_FILE: + if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file))) + ret = -EFAULT; + else + ret = add_bin_file(&load_bin_file); + break; + default: + ERROR("unknown ioctl %u", cmd); + ret = -EINVAL; + break; + } + complete(&loader_complete); + EXIT1(return ret); +} + +static int wrapper_ioctl_release(struct inode *inode, struct file *file) +{ + ENTER1(""); + return 0; +} + +static struct file_operations wrapper_fops = { + .owner = THIS_MODULE, + .ioctl = wrapper_ioctl, + .release = wrapper_ioctl_release, +}; + +static struct miscdevice wrapper_misc = { + .name = DRIVER_NAME, + .minor = MISC_DYNAMIC_MINOR, + .fops = &wrapper_fops +}; + +int loader_init(void) +{ + int err; + + InitializeListHead(&wrap_drivers); + InitializeListHead(&wrap_devices); + init_MUTEX(&loader_mutex); + init_completion(&loader_complete); + if ((err = misc_register(&wrapper_misc)) < 0 ) { + ERROR("couldn't register module (%d)", err); + unregister_devices(); + EXIT1(return err); + } + register_devices(); + EXIT1(return 0); +} + +void loader_exit(void) +{ + struct nt_list *cur, *next; + + ENTER1(""); + misc_deregister(&wrapper_misc); + unregister_devices(); + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_safe(cur, next, &wrap_drivers) { + struct wrap_driver *driver; + driver = container_of(cur, struct wrap_driver, list); + unload_wrap_driver(driver); + } + up(&loader_mutex); + EXIT1(return); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/pe_linker.c +++ linux-2.6.27/ubuntu/ndiswrapper/pe_linker.c @@ -0,0 +1,609 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifdef TEST_LOADER + +#include "usr_linker.h" + +#else + +#include +#include + +//#define DEBUGLINKER 2 + +#include "ntoskernel.h" + +#endif + +struct pe_exports { + char *dll; + char *name; + generic_func addr; +}; + +static struct pe_exports pe_exports[40]; +static int num_pe_exports; + +#define RVA2VA(image, rva, type) (type)(ULONG_PTR)((void *)image + rva) +#define CHECK_SZ(a,b) { if (sizeof(a) != b) { \ + ERROR("%s is bad, got %zd, expected %d", \ + #a , sizeof(a), (b)); return -EINVAL; } } + +#if defined(DEBUGLINKER) && DEBUGLINKER > 0 +#define DBGLINKER(fmt, ...) printk(KERN_INFO "%s (%s:%d): " fmt "\n", \ + DRIVER_NAME, __FUNCTION__, \ + __LINE__ , ## __VA_ARGS__); +static const char *image_directory_name[] = { + "EXPORT", + "IMPORT", + "RESOURCE", + "EXCEPTION", + "SECURITY", + "BASERELOC", + "DEBUG", + "COPYRIGHT", + "GLOBALPTR", + "TLS", + "LOAD_CONFIG", + "BOUND_IMPORT", + "IAT", + "DELAY_IMPORT", + "COM_DESCRIPTOR" }; +#else +#define DBGLINKER(fmt, ...) do { } while (0) +#endif + +#ifndef TEST_LOADER +extern struct wrap_export ntoskernel_exports[], ntoskernel_io_exports[], + ndis_exports[], crt_exports[], hal_exports[], rtl_exports[]; +#ifdef ENABLE_USB +extern struct wrap_export usb_exports[]; +#endif + +static char *get_export(char *name) +{ + int i; + + for (i = 0 ; ntoskernel_exports[i].name != NULL; i++) + if (strcmp(ntoskernel_exports[i].name, name) == 0) + return (char *)ntoskernel_exports[i].func; + + for (i = 0 ; ntoskernel_io_exports[i].name != NULL; i++) + if (strcmp(ntoskernel_io_exports[i].name, name) == 0) + return (char *)ntoskernel_io_exports[i].func; + + for (i = 0 ; ndis_exports[i].name != NULL; i++) + if (strcmp(ndis_exports[i].name, name) == 0) + return (char *)ndis_exports[i].func; + + for (i = 0 ; crt_exports[i].name != NULL; i++) + if (strcmp(crt_exports[i].name, name) == 0) + return (char *)crt_exports[i].func; + + for (i = 0 ; hal_exports[i].name != NULL; i++) + if (strcmp(hal_exports[i].name, name) == 0) + return (char *)hal_exports[i].func; + + for (i = 0 ; rtl_exports[i].name != NULL; i++) + if (strcmp(rtl_exports[i].name, name) == 0) + return (char *)rtl_exports[i].func; + +#ifdef ENABLE_USB + for (i = 0 ; usb_exports[i].name != NULL; i++) + if (strcmp(usb_exports[i].name, name) == 0) + return (char *)usb_exports[i].func; +#endif + + for (i = 0; i < num_pe_exports; i++) + if (strcmp(pe_exports[i].name, name) == 0) + return (char *)pe_exports[i].addr; + + return NULL; +} +#endif // TEST_LOADER + +static void *get_dll_init(char *name) +{ + int i; + for (i = 0; i < num_pe_exports; i++) + if ((strcmp(pe_exports[i].dll, name) == 0) && + (strcmp(pe_exports[i].name, "DllInitialize") == 0)) + return (void *)pe_exports[i].addr; + return NULL; +} + +/* + * Find and validate the coff header + * + */ +static int check_nt_hdr(IMAGE_NT_HEADERS *nt_hdr) +{ + int i; + WORD attr; + PIMAGE_OPTIONAL_HEADER opt_hdr; + + /* Validate the "PE\0\0" signature */ + if (nt_hdr->Signature != IMAGE_NT_SIGNATURE) { + ERROR("is this driver file? bad signature %08x", + nt_hdr->Signature); + return -EINVAL; + } + + opt_hdr = &nt_hdr->OptionalHeader; + /* Make sure Image is PE32 or PE32+ */ +#ifdef CONFIG_X86_64 + if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + ERROR("kernel is 64-bit, but Windows driver is not 64-bit;" + "bad magic: %04X", opt_hdr->Magic); + return -EINVAL; + } +#else + if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ERROR("kernel is 32-bit, but Windows driver is not 32-bit;" + "bad magic: %04X", opt_hdr->Magic); + return -EINVAL; + } +#endif + + /* Validate the image for the current architecture. */ +#ifdef CONFIG_X86_64 + if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) { + ERROR("kernel is 64-bit, but Windows driver is not 64-bit;" + " (PE signature is %04X)", nt_hdr->FileHeader.Machine); + return -EINVAL; + } +#else + if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) { + ERROR("kernel is 32-bit, but Windows driver is not 32-bit;" + " (PE signature is %04X)", nt_hdr->FileHeader.Machine); + return -EINVAL; + } +#endif + + /* Must have attributes */ +#ifdef CONFIG_X86_64 + attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE; +#else + attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE; +#endif + if ((nt_hdr->FileHeader.Characteristics & attr) != attr) + return -EINVAL; + + /* Must be relocatable */ + attr = IMAGE_FILE_RELOCS_STRIPPED; + if ((nt_hdr->FileHeader.Characteristics & attr)) + return -EINVAL; + + /* Make sure we have at least one section */ + if (nt_hdr->FileHeader.NumberOfSections == 0) + return -EINVAL; + + if (opt_hdr->SectionAlignment < opt_hdr->FileAlignment) { + ERROR("alignment mismatch: secion: 0x%x, file: 0x%x", + opt_hdr->SectionAlignment, opt_hdr->FileAlignment); + return -EINVAL; + } + + DBGLINKER("number of datadictionary entries %d", + opt_hdr->NumberOfRvaAndSizes); + for (i = 0; i < opt_hdr->NumberOfRvaAndSizes; i++) { + DBGLINKER("datadirectory %s RVA:%X Size:%d", + (i<=IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)? + image_directory_name[i] : "unknown", + opt_hdr->DataDirectory[i].VirtualAddress, + opt_hdr->DataDirectory[i].Size); + } + + if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_DLL)) + return IMAGE_FILE_DLL; + if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) + return IMAGE_FILE_EXECUTABLE_IMAGE; + return -EINVAL; +} + +static int import(void *image, IMAGE_IMPORT_DESCRIPTOR *dirent, char *dll) +{ + ULONG_PTR *lookup_tbl, *address_tbl; + char *symname = NULL; + int i; + int ret = 0; + void *adr; + + lookup_tbl = RVA2VA(image, dirent->u.OriginalFirstThunk, ULONG_PTR *); + address_tbl = RVA2VA(image, dirent->FirstThunk, ULONG_PTR *); + + for (i = 0; lookup_tbl[i]; i++) { + if (IMAGE_SNAP_BY_ORDINAL(lookup_tbl[i])) { + ERROR("ordinal import not supported: %Lu", + (uint64_t)lookup_tbl[i]); + return -1; + } + else { + symname = RVA2VA(image, + ((lookup_tbl[i] & + ~IMAGE_ORDINAL_FLAG) + 2), char *); + } + + adr = get_export(symname); + if (adr == NULL) { + ERROR("unknown symbol: %s:'%s'", dll, symname); + ret = -1; + } else { + DBGLINKER("found symbol: %s:%s: addr: %p, rva = %Lu", + dll, symname, adr, (uint64_t)address_tbl[i]); + address_tbl[i] = (ULONG_PTR)adr; + } + } + return ret; +} + +static int read_exports(struct pe_image *pe) +{ + IMAGE_EXPORT_DIRECTORY *export_dir_table; + uint32_t *export_addr_table; + int i; + uint32_t *name_table; + PIMAGE_OPTIONAL_HEADER opt_hdr; + IMAGE_DATA_DIRECTORY *export_data_dir; + + opt_hdr = &pe->nt_hdr->OptionalHeader; + export_data_dir = + &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + + if (export_data_dir->Size == 0) { + DBGLINKER("no exports"); + return 0; + } + + export_dir_table = + RVA2VA(pe->image, export_data_dir->VirtualAddress, + IMAGE_EXPORT_DIRECTORY *); + + name_table = (unsigned int *)(pe->image + + export_dir_table->AddressOfNames); + export_addr_table = (uint32_t *) + (pe->image + export_dir_table->AddressOfFunctions); + + for (i = 0; i < export_dir_table->NumberOfNames; i++) { + + if (export_data_dir->VirtualAddress <= *export_addr_table || + *export_addr_table >= (export_data_dir->VirtualAddress + + export_data_dir->Size)) + DBGLINKER("forwarder rva"); + + DBGLINKER("export symbol: %s, at %p", + (char *)(pe->image + *name_table), + pe->image + *export_addr_table); + + pe_exports[num_pe_exports].dll = pe->name; + pe_exports[num_pe_exports].name = pe->image + *name_table; + pe_exports[num_pe_exports].addr = + pe->image + *export_addr_table; + + num_pe_exports++; + name_table++; + export_addr_table++; + } + return 0; +} + +static int fixup_imports(void *image, IMAGE_NT_HEADERS *nt_hdr) +{ + int i; + char *name; + int ret = 0; + IMAGE_IMPORT_DESCRIPTOR *dirent; + IMAGE_DATA_DIRECTORY *import_data_dir; + PIMAGE_OPTIONAL_HEADER opt_hdr; + + opt_hdr = &nt_hdr->OptionalHeader; + import_data_dir = + &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + dirent = RVA2VA(image, import_data_dir->VirtualAddress, + IMAGE_IMPORT_DESCRIPTOR *); + + for (i = 0; dirent[i].Name; i++) { + name = RVA2VA(image, dirent[i].Name, char*); + + DBGLINKER("imports from dll: %s", name); + ret += import(image, &dirent[i], name); + } + return ret; +} + +static int fixup_reloc(void *image, IMAGE_NT_HEADERS *nt_hdr) +{ + ULONG_PTR base; + ULONG_PTR size; + IMAGE_BASE_RELOCATION *fixup_block; + IMAGE_DATA_DIRECTORY *base_reloc_data_dir; + PIMAGE_OPTIONAL_HEADER opt_hdr; + + opt_hdr = &nt_hdr->OptionalHeader; + base = opt_hdr->ImageBase; + base_reloc_data_dir = + &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if (base_reloc_data_dir->Size == 0) + return 0; + + fixup_block = RVA2VA(image, base_reloc_data_dir->VirtualAddress, + IMAGE_BASE_RELOCATION *); + DBGLINKER("fixup_block=%p, image=%p", fixup_block, image); + DBGLINKER("fixup_block info: %x %d", + fixup_block->VirtualAddress, fixup_block->SizeOfBlock); + + while (fixup_block->SizeOfBlock) { + int i; + WORD fixup, offset; + + size = (fixup_block->SizeOfBlock - + sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + DBGLINKER("found %Lu relocations in this block", + (uint64_t)size); + + for (i = 0; i < size; i++) { + fixup = fixup_block->TypeOffset[i]; + offset = fixup & 0xfff; + switch ((fixup >> 12) & 0x0f) { + case IMAGE_REL_BASED_ABSOLUTE: + break; + + case IMAGE_REL_BASED_HIGHLOW: { + uint32_t addr; + uint32_t *loc = + RVA2VA(image, + fixup_block->VirtualAddress + + offset, uint32_t *); + addr = RVA2VA(image, (*loc - base), uint32_t); + DBGLINKER("relocation: *%p (Val:%X)= %X", + loc, *loc, addr); + *loc = addr; + } + break; + + case IMAGE_REL_BASED_DIR64: { + uint64_t addr; + uint64_t *loc = + RVA2VA(image, + fixup_block->VirtualAddress + + offset, uint64_t *); + addr = RVA2VA(image, (*loc - base), uint64_t); + DBGLINKER("relocation: *%p (Val:%llX)= %llx", + loc, *loc, addr); + *loc = addr; + } + break; + + default: + ERROR("unknown fixup: %08X", + (fixup >> 12) & 0x0f); + return -EOPNOTSUPP; + break; + } + } + DBGLINKER("finished relocating block"); + + fixup_block = (IMAGE_BASE_RELOCATION *) + ((void *)fixup_block + fixup_block->SizeOfBlock); + }; + DBGLINKER("done relocating all"); + + return 0; +} + +/* Expand the image in memroy if necessary. The image on disk does not + * necessarily maps the image of the driver in memory, so we have to + * re-write it in order to fullfill the sections alignements. The + * advantage to do that is that rva_to_va becomes a simple + * addition. */ +static int fix_pe_image(struct pe_image *pe) +{ + void *image; + IMAGE_SECTION_HEADER *sect_hdr; + int i, sections; + int image_size; + + if (pe->size == pe->opt_hdr->SizeOfImage) { + /* Nothing to do */ + return 0; + } + + image_size = pe->opt_hdr->SizeOfImage; +#ifdef CONFIG_X86_64 +#ifdef PAGE_KERNEL_EXECUTABLE + image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXECUTABLE); +#elif defined PAGE_KERNEL_EXEC + image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXEC); +#else +#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC +#endif +#else +#ifdef cpu_has_nx + /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is + * not available to modules! */ + if (cpu_has_nx) + image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM, + __pgprot(__PAGE_KERNEL & ~_PAGE_NX)); + else + image = vmalloc(image_size); +#else + image = vmalloc(image_size); +#endif +#endif + if (image == NULL) { + ERROR("failed to allocate enough space for new image:" + " %d bytes", image_size); + return -ENOMEM; + } + + /* Copy all the headers, ie everything before the first section. */ + + sections = pe->nt_hdr->FileHeader.NumberOfSections; + sect_hdr = IMAGE_FIRST_SECTION(pe->nt_hdr); + + DBGLINKER("copying headers: %u bytes", sect_hdr->PointerToRawData); + + memcpy(image, pe->image, sect_hdr->PointerToRawData); + + /* Copy all the sections */ + for (i = 0; i < sections; i++) { + DBGLINKER("Copy section %s from %x to %x", + sect_hdr->Name, sect_hdr->PointerToRawData, + sect_hdr->VirtualAddress); + if (sect_hdr->VirtualAddress+sect_hdr->SizeOfRawData > + image_size) { + ERROR("Invalid section %s in driver", sect_hdr->Name); + vfree(image); + return -EINVAL; + } + + memcpy(image+sect_hdr->VirtualAddress, + pe->image + sect_hdr->PointerToRawData, + sect_hdr->SizeOfRawData); + sect_hdr++; + } + + vfree(pe->image); + pe->image = image; + pe->size = image_size; + + /* Update our internal pointers */ + pe->nt_hdr = (IMAGE_NT_HEADERS *) + (pe->image + ((IMAGE_DOS_HEADER *)pe->image)->e_lfanew); + pe->opt_hdr = &pe->nt_hdr->OptionalHeader; + + DBGLINKER("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p", + pe->nt_hdr, pe->opt_hdr, pe->image); + + return 0; +} + +#if defined(CONFIG_X86_64) +static void fix_user_shared_data_addr(char *driver, unsigned long length) +{ + unsigned long i, n, max_addr, *addr; + + n = length - sizeof(unsigned long); + max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data); + for (i = 0; i < n; i++) { + addr = (unsigned long *)(driver + i); + if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) { + *addr -= KI_USER_SHARED_DATA; + *addr += (unsigned long)&kuser_shared_data; + kuser_shared_data.reserved1 = 1; + } + } +} +#endif + +int link_pe_images(struct pe_image *pe_image, unsigned short n) +{ + int i; + struct pe_image *pe; + +#ifdef DEBUG + /* Sanity checkings */ + CHECK_SZ(IMAGE_SECTION_HEADER, IMAGE_SIZEOF_SECTION_HEADER); + CHECK_SZ(IMAGE_FILE_HEADER, IMAGE_SIZEOF_FILE_HEADER); + CHECK_SZ(IMAGE_OPTIONAL_HEADER, IMAGE_SIZEOF_NT_OPTIONAL_HEADER); + CHECK_SZ(IMAGE_NT_HEADERS, 4 + IMAGE_SIZEOF_FILE_HEADER + + IMAGE_SIZEOF_NT_OPTIONAL_HEADER); + CHECK_SZ(IMAGE_DOS_HEADER, 0x40); + CHECK_SZ(IMAGE_EXPORT_DIRECTORY, 40); + CHECK_SZ(IMAGE_BASE_RELOCATION, 8); + CHECK_SZ(IMAGE_IMPORT_DESCRIPTOR, 20); +#endif + + for (i = 0; i < n; i++) { + IMAGE_DOS_HEADER *dos_hdr; + pe = &pe_image[i]; + dos_hdr = pe->image; + + if (pe->size < sizeof(IMAGE_DOS_HEADER)) { + TRACE1("image too small: %d", pe->size); + return -EINVAL; + } + + pe->nt_hdr = + (IMAGE_NT_HEADERS *)(pe->image + dos_hdr->e_lfanew); + pe->opt_hdr = &pe->nt_hdr->OptionalHeader; + + pe->type = check_nt_hdr(pe->nt_hdr); + if (pe->type <= 0) { + TRACE1("type <= 0"); + return -EINVAL; + } + + if (fix_pe_image(pe)) { + TRACE1("bad PE image"); + return -EINVAL; + } + + if (read_exports(pe)) { + TRACE1("read exports failed"); + return -EINVAL; + } + } + + for (i = 0; i < n; i++) { + pe = &pe_image[i]; + + if (fixup_reloc(pe->image, pe->nt_hdr)) { + TRACE1("fixup reloc failed"); + return -EINVAL; + } + if (fixup_imports(pe->image, pe->nt_hdr)) { + TRACE1("fixup imports failed"); + return -EINVAL; + } +#if defined(CONFIG_X86_64) + INFO("fixing KI_USER_SHARED_DATA address in the driver"); + fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size); +#endif + flush_icache_range(pe->image, pe->size); + + pe->entry = + RVA2VA(pe->image, + pe->opt_hdr->AddressOfEntryPoint, void *); + TRACE1("entry is at %p, rva at %08X", pe->entry, + pe->opt_hdr->AddressOfEntryPoint); + } + + for (i = 0; i < n; i++) { + pe = &pe_image[i]; + + if (pe->type == IMAGE_FILE_DLL) { + struct unicode_string ustring; + char *buf = "0/0t0m0p00"; + int (*dll_entry)(struct unicode_string *ustring) + wstdcall; + + memset(&ustring, 0, sizeof(ustring)); + ustring.buf = (wchar_t *)buf; + dll_entry = (void *)get_dll_init(pe->name); + + TRACE1("calling dll_init at %p", dll_entry); + if (!dll_entry || dll_entry(&ustring)) + ERROR("DLL initialize failed for %s", + pe->name); + } + else if (pe->type != IMAGE_FILE_EXECUTABLE_IMAGE) + ERROR("illegal image type: %d", pe->type); + } + return 0; +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/ndis.c +++ linux-2.6.27/ubuntu/ndiswrapper/ndis.c @@ -0,0 +1,2988 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ndis.h" +#include "iw_ndis.h" +#include "wrapndis.h" +#include "pnp.h" +#include "loader.h" +#include +#include +#include "ndis_exports.h" + +#define MAX_ALLOCATED_NDIS_PACKETS TX_RING_SIZE +#define MAX_ALLOCATED_NDIS_BUFFERS TX_RING_SIZE + +static void ndis_worker(worker_param_t dummy); +static work_struct_t ndis_work; +static struct nt_list ndis_work_list; +static spinlock_t ndis_work_list_lock; + +workqueue_struct_t *ndis_wq; +static struct nt_thread *ndis_worker_thread; + +static void *ndis_get_routine_address(char *name); + +wstdcall void WIN_FUNC(NdisInitializeWrapper,4) + (void **driver_handle, struct driver_object *driver, + struct unicode_string *reg_path, void *unused) +{ + ENTER1("handle: %p, driver: %p", driver_handle, driver); + *driver_handle = driver; + EXIT1(return); +} + +wstdcall void WIN_FUNC(NdisTerminateWrapper,2) + (struct device_object *dev_obj, void *system_specific) +{ + EXIT1(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterMiniport,3) + (struct driver_object *drv_obj, struct miniport *mp, UINT length) +{ + int min_length; + struct wrap_driver *wrap_driver; + struct ndis_driver *ndis_driver; + + min_length = ((char *)&mp->co_create_vc) - ((char *)mp); + + ENTER1("%p %p %d", drv_obj, mp, length); + + if (mp->major_version < 4) { + ERROR("Driver is using ndis version %d which is too old.", + mp->major_version); + EXIT1(return NDIS_STATUS_BAD_VERSION); + } + + if (length < min_length) { + ERROR("Characteristics length %d is too small", length); + EXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS); + } + + TRACE1("%d.%d, %d, %u", mp->major_version, mp->minor_version, length, + (u32)sizeof(struct miniport)); + wrap_driver = IoGetDriverObjectExtension(drv_obj, + (void *)WRAP_DRIVER_CLIENT_ID); + if (!wrap_driver) { + ERROR("couldn't get wrap_driver"); + EXIT1(return NDIS_STATUS_RESOURCES); + } + if (IoAllocateDriverObjectExtension( + drv_obj, (void *)NDIS_DRIVER_CLIENT_ID, + sizeof(*ndis_driver), (void **)&ndis_driver) != + STATUS_SUCCESS) + EXIT1(return NDIS_STATUS_RESOURCES); + wrap_driver->ndis_driver = ndis_driver; + TRACE1("driver: %p", ndis_driver); + memcpy(&ndis_driver->mp, mp, min_t(int, sizeof(*mp), length)); + + DBG_BLOCK(2) { + int i; + void **func; + char *mp_funcs[] = { + "queryinfo", "reconfig", "reset", "send", "setinfo", + "tx_data", "return_packet", "send_packets", + "alloc_complete", "co_create_vc", "co_delete_vc", + "co_activate_vc", "co_deactivate_vc", + "co_send_packets", "co_request", "cancel_send_packets", + "pnp_event_notify", "shutdown", + }; + func = (void **)&ndis_driver->mp.queryinfo; + for (i = 0; i < (sizeof(mp_funcs) / sizeof(mp_funcs[0])); i++) + TRACE2("function '%s' is at %p", mp_funcs[i], func[i]); + } + EXIT1(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterDevice,6) + (struct driver_object *drv_obj, struct unicode_string *dev_name, + struct unicode_string *link, void **funcs, + struct device_object **dev_obj, void **dev_obj_handle) +{ + NTSTATUS status; + struct device_object *tmp; + int i; + + ENTER1("%p, %p, %p", drv_obj, dev_name, link); + status = IoCreateDevice(drv_obj, 0, dev_name, FILE_DEVICE_NETWORK, 0, + FALSE, &tmp); + + if (status != STATUS_SUCCESS) + EXIT1(return NDIS_STATUS_RESOURCES); + if (link) + status = IoCreateSymbolicLink(link, dev_name); + if (status != STATUS_SUCCESS) { + IoDeleteDevice(tmp); + EXIT1(return NDIS_STATUS_RESOURCES); + } + + *dev_obj = tmp; + *dev_obj_handle = *dev_obj; + for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) + if (funcs[i] && i != IRP_MJ_PNP && i != IRP_MJ_POWER) { + drv_obj->major_func[i] = funcs[i]; + TRACE1("mj_fn for 0x%x is at %p", i, funcs[i]); + } + EXIT1(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMDeregisterDevice,1) + (struct device_object *dev_obj) +{ + ENTER2("%p", dev_obj); + IoDeleteDevice(dev_obj); + return NDIS_STATUS_SUCCESS; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemoryWithTag,3) + (void **dest, UINT length, ULONG tag) +{ + void *addr; + + assert_irql(_irql_ <= DISPATCH_LEVEL); + addr = ExAllocatePoolWithTag(NonPagedPool, length, tag); + TRACE4("%p", addr); + if (addr) { + *dest = addr; + EXIT4(return NDIS_STATUS_SUCCESS); + } else + EXIT4(return NDIS_STATUS_FAILURE); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemory,4) + (void **dest, UINT length, UINT flags, NDIS_PHY_ADDRESS highest_address) +{ + return NdisAllocateMemoryWithTag(dest, length, 0); +} + +/* length_tag is either length or tag, depending on if + * NdisAllocateMemory or NdisAllocateMemoryTag is used to allocate + * memory */ +wstdcall void WIN_FUNC(NdisFreeMemory,3) + (void *addr, UINT length_tag, UINT flags) +{ + TRACE4("%p", addr); + ExFreePool(addr); +} + +noregparm void WIN_FUNC(NdisWriteErrorLogEntry,12) + (struct driver_object *drv_obj, ULONG error, ULONG count, ...) +{ + va_list args; + int i; + ULONG code; + + va_start(args, count); + ERROR("log: %08X, count: %d, return_address: %p", + error, count, __builtin_return_address(0)); + for (i = 0; i < count; i++) { + code = va_arg(args, ULONG); + ERROR("code: 0x%x", code); + } + va_end(args); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenConfiguration,3) + (NDIS_STATUS *status, struct ndis_mp_block **conf_handle, + struct ndis_mp_block *handle) +{ + ENTER2("%p", conf_handle); + *conf_handle = handle; + *status = NDIS_STATUS_SUCCESS; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenProtocolConfiguration,3) + (NDIS_STATUS *status, void **confhandle, + struct unicode_string *section) +{ + ENTER2("%p", confhandle); + *status = NDIS_STATUS_SUCCESS; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByName,4) + (NDIS_STATUS *status, void *handle, + struct unicode_string *key, void **subkeyhandle) +{ + struct ansi_string ansi; + ENTER2(""); + if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE) == STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + *subkeyhandle = handle; + *status = NDIS_STATUS_SUCCESS; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByIndex,5) + (NDIS_STATUS *status, void *handle, ULONG index, + struct unicode_string *key, void **subkeyhandle) +{ + ENTER2("%u", index); +// *subkeyhandle = handle; + *status = NDIS_STATUS_FAILURE; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisCloseConfiguration,1) + (void *handle) +{ + /* instead of freeing all configuration parameters as we are + * supposed to do here, we free them when the device is + * removed */ + ENTER2("%p", handle); + return; +} + +wstdcall void WIN_FUNC(NdisOpenFile,5) + (NDIS_STATUS *status, struct wrap_bin_file **file, + UINT *filelength, struct unicode_string *filename, + NDIS_PHY_ADDRESS highest_address) +{ + struct ansi_string ansi; + struct wrap_bin_file *bin_file; + + ENTER2("%p, %d, %llx, %p", status, *filelength, highest_address, *file); + if (RtlUnicodeStringToAnsiString(&ansi, filename, TRUE) != + STATUS_SUCCESS) { + *status = NDIS_STATUS_RESOURCES; + EXIT2(return); + } + TRACE2("%s", ansi.buf); + bin_file = get_bin_file(ansi.buf); + if (bin_file) { + *file = bin_file; + *filelength = bin_file->size; + *status = NDIS_STATUS_SUCCESS; + } else + *status = NDIS_STATUS_FILE_NOT_FOUND; + + RtlFreeAnsiString(&ansi); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisMapFile,3) + (NDIS_STATUS *status, void **mappedbuffer, struct wrap_bin_file *file) +{ + ENTER2("%p", file); + + if (!file) { + *status = NDIS_STATUS_ALREADY_MAPPED; + EXIT2(return); + } + + *status = NDIS_STATUS_SUCCESS; + *mappedbuffer = file->data; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisUnmapFile,1) + (struct wrap_bin_file *file) +{ + ENTER2("%p", file); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisCloseFile,1) + (struct wrap_bin_file *file) +{ + ENTER2("%p", file); + free_bin_file(file); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisGetSystemUpTime,1) + (ULONG *ms) +{ + *ms = 1000 * jiffies / HZ; + EXIT5(return); +} + +wstdcall ULONG WIN_FUNC(NDIS_BUFFER_TO_SPAN_PAGES,1) + (ndis_buffer *buffer) +{ + ULONG n, length; + + if (buffer == NULL) + EXIT2(return 0); + if (MmGetMdlByteCount(buffer) == 0) + EXIT2(return 1); + + length = MmGetMdlByteCount(buffer); + n = SPAN_PAGES(MmGetMdlVirtualAddress(buffer), length); + TRACE4("%p, %p, %d, %d", buffer->startva, buffer->mappedsystemva, + length, n); + EXIT3(return n); +} + +wstdcall void WIN_FUNC(NdisGetBufferPhysicalArraySize,2) + (ndis_buffer *buffer, UINT *arraysize) +{ + ENTER3("%p", buffer); + *arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer); + EXIT3(return); +} + +static struct ndis_configuration_parameter * +ndis_encode_setting(struct wrap_device_setting *setting, + enum ndis_parameter_type type) +{ + struct ansi_string ansi; + struct ndis_configuration_parameter *param; + + param = setting->encoded; + if (param) { + if (param->type == type) + EXIT2(return param); + if (param->type == NdisParameterString) + RtlFreeUnicodeString(¶m->data.string); + setting->encoded = NULL; + } else + param = ExAllocatePoolWithTag(NonPagedPool, sizeof(*param), 0); + if (!param) { + ERROR("couldn't allocate memory"); + return NULL; + } + switch(type) { + case NdisParameterInteger: + param->data.integer = simple_strtol(setting->value, NULL, 0); + TRACE2("0x%x", (ULONG)param->data.integer); + break; + case NdisParameterHexInteger: + param->data.integer = simple_strtol(setting->value, NULL, 16); + TRACE2("0x%x", (ULONG)param->data.integer); + break; + case NdisParameterString: + RtlInitAnsiString(&ansi, setting->value); + TRACE2("'%s'", ansi.buf); + if (RtlAnsiStringToUnicodeString(¶m->data.string, + &ansi, TRUE)) { + ExFreePool(param); + EXIT2(return NULL); + } + break; + case NdisParameterBinary: + param->data.integer = simple_strtol(setting->value, NULL, 2); + TRACE2("0x%x", (ULONG)param->data.integer); + break; + default: + ERROR("unknown type: %d", type); + ExFreePool(param); + return NULL; + } + param->type = type; + setting->encoded = param; + EXIT2(return param); +} + +static int ndis_decode_setting(struct wrap_device_setting *setting, + struct ndis_configuration_parameter *param) +{ + struct ansi_string ansi; + struct ndis_configuration_parameter *prev; + + ENTER2("%p, %p", setting, param); + prev = setting->encoded; + if (prev && prev->type == NdisParameterString) { + RtlFreeUnicodeString(&prev->data.string); + setting->encoded = NULL; + } + switch(param->type) { + case NdisParameterInteger: + snprintf(setting->value, sizeof(u32), "%u", + param->data.integer); + setting->value[sizeof(ULONG)] = 0; + break; + case NdisParameterHexInteger: + snprintf(setting->value, sizeof(u32), "%x", + param->data.integer); + setting->value[sizeof(ULONG)] = 0; + break; + case NdisParameterString: + ansi.buf = setting->value; + ansi.max_length = MAX_SETTING_VALUE_LEN; + if ((RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, + FALSE) != STATUS_SUCCESS) + || ansi.length >= MAX_SETTING_VALUE_LEN) { + EXIT1(return -1); + } + if (ansi.length == ansi.max_length) + ansi.length--; + setting->value[ansi.length] = 0; + break; + case NdisParameterBinary: + snprintf(setting->value, sizeof(u32), "%u", + param->data.integer); + setting->value[sizeof(ULONG)] = 0; + break; + default: + TRACE2("unknown setting type: %d", param->type); + return -1; + } + TRACE2("setting changed %s='%s', %d", setting->name, setting->value, + ansi.length); + return 0; +} + +static int read_setting(struct nt_list *setting_list, char *keyname, int length, + struct ndis_configuration_parameter **param, + enum ndis_parameter_type type) +{ + struct wrap_device_setting *setting; + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_entry(setting, setting_list, list) { + if (strnicmp(keyname, setting->name, length) == 0) { + TRACE2("setting %s='%s'", keyname, setting->value); + up(&loader_mutex); + *param = ndis_encode_setting(setting, type); + if (*param) + EXIT2(return 0); + else + EXIT2(return -1); + } + } + up(&loader_mutex); + EXIT2(return -1); +} + +wstdcall void WIN_FUNC(NdisReadConfiguration,5) + (NDIS_STATUS *status, struct ndis_configuration_parameter **param, + struct ndis_mp_block *nmb, struct unicode_string *key, + enum ndis_parameter_type type) +{ + struct ansi_string ansi; + int ret; + + ENTER2("nmb: %p", nmb); + ret = RtlUnicodeStringToAnsiString(&ansi, key, TRUE); + if (ret != STATUS_SUCCESS || ansi.buf == NULL) { + *param = NULL; + *status = NDIS_STATUS_FAILURE; + RtlFreeAnsiString(&ansi); + EXIT2(return); + } + TRACE2("%d, %s", type, ansi.buf); + + if (read_setting(&nmb->wnd->wd->settings, ansi.buf, + ansi.length, param, type) == 0 || + read_setting(&nmb->wnd->wd->driver->settings, ansi.buf, + ansi.length, param, type) == 0) + *status = NDIS_STATUS_SUCCESS; + else { + TRACE2("setting %s not found (type:%d)", ansi.buf, type); + *status = NDIS_STATUS_FAILURE; + } + RtlFreeAnsiString(&ansi); + EXIT2(return); + +} + +wstdcall void WIN_FUNC(NdisWriteConfiguration,4) + (NDIS_STATUS *status, struct ndis_mp_block *nmb, + struct unicode_string *key, struct ndis_configuration_parameter *param) +{ + struct ansi_string ansi; + char *keyname; + struct wrap_device_setting *setting; + + ENTER2("nmb: %p", nmb); + if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE)) { + *status = NDIS_STATUS_FAILURE; + EXIT2(return); + } + keyname = ansi.buf; + TRACE2("%s", keyname); + + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_entry(setting, &nmb->wnd->wd->settings, list) { + if (strnicmp(keyname, setting->name, ansi.length) == 0) { + up(&loader_mutex); + if (ndis_decode_setting(setting, param)) + *status = NDIS_STATUS_FAILURE; + else + *status = NDIS_STATUS_SUCCESS; + RtlFreeAnsiString(&ansi); + EXIT2(return); + } + } + up(&loader_mutex); + setting = kzalloc(sizeof(*setting), GFP_KERNEL); + if (setting) { + if (ansi.length == ansi.max_length) + ansi.length--; + memcpy(setting->name, keyname, ansi.length); + setting->name[ansi.length] = 0; + if (ndis_decode_setting(setting, param)) + *status = NDIS_STATUS_FAILURE; + else { + *status = NDIS_STATUS_SUCCESS; + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + InsertTailList(&nmb->wnd->wd->settings, &setting->list); + up(&loader_mutex); + } + } else + *status = NDIS_STATUS_RESOURCES; + + RtlFreeAnsiString(&ansi); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisReadNetworkAddress,4) + (NDIS_STATUS *status, void **addr, UINT *len, + struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + struct ndis_configuration_parameter *param; + struct unicode_string key; + struct ansi_string ansi; + typeof(wnd->mac) mac; + int i, ret; + + ENTER2("%p", nmb); + RtlInitAnsiString(&ansi, "NetworkAddress"); + *status = NDIS_STATUS_FAILURE; + if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS) + EXIT1(return); + + NdisReadConfiguration(&ret, ¶m, nmb, &key, NdisParameterString); + RtlFreeUnicodeString(&key); + if (ret != NDIS_STATUS_SUCCESS) + EXIT1(return); + ret = RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, TRUE); + if (ret != STATUS_SUCCESS) + EXIT1(return); + + i = 0; + if (ansi.length >= 2 * sizeof(mac)) { + for (i = 0; i < sizeof(mac); i++) { + char c[3]; + int x; + c[0] = ansi.buf[i*2]; + c[1] = ansi.buf[i*2+1]; + c[2] = 0; + ret = sscanf(c, "%x", &x); + if (ret != 1) + break; + mac[i] = x; + } + } + TRACE2("%s, %d, " MACSTR, ansi.buf, i, MAC2STR(mac)); + RtlFreeAnsiString(&ansi); + if (i == sizeof(mac)) { + memcpy(wnd->mac, mac, sizeof(wnd->mac)); + *len = sizeof(mac); + *addr = wnd->mac; + *status = NDIS_STATUS_SUCCESS; + } + EXIT1(return); +} + +wstdcall void WIN_FUNC(NdisInitializeString,2) + (struct unicode_string *dest, UCHAR *src) +{ + struct ansi_string ansi; + + ENTER2(""); + if (src == NULL) { + dest->length = dest->max_length = 0; + dest->buf = NULL; + } else { + RtlInitAnsiString(&ansi, src); + /* the string is freed with NdisFreeMemory */ + RtlAnsiStringToUnicodeString(dest, &ansi, TRUE); + } + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisInitAnsiString,2) + (struct ansi_string *dst, CHAR *src) +{ + RtlInitAnsiString(dst, src); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisInitUnicodeString,2) + (struct unicode_string *dest, const wchar_t *src) +{ + RtlInitUnicodeString(dest, src); + return; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisAnsiStringToUnicodeString,2) + (struct unicode_string *dst, struct ansi_string *src) +{ + ENTER2(""); + if (dst == NULL || src == NULL) + EXIT2(return NDIS_STATUS_FAILURE); + if (RtlAnsiStringToUnicodeString(dst, src, FALSE) == STATUS_SUCCESS) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisUnicodeStringToAnsiString,2) + (struct ansi_string *dst, struct unicode_string *src) +{ + ENTER2(""); + if (dst == NULL || src == NULL) + EXIT2(return NDIS_STATUS_FAILURE); + if (RtlUnicodeStringToAnsiString(dst, src, FALSE) == STATUS_SUCCESS) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + +wstdcall NTSTATUS WIN_FUNC(NdisUpcaseUnicodeString,2) + (struct unicode_string *dst, struct unicode_string *src) +{ + EXIT2(return RtlUpcaseUnicodeString(dst, src, FALSE)); +} + +wstdcall void WIN_FUNC(NdisMSetAttributesEx,5) + (struct ndis_mp_block *nmb, void *mp_ctx, + UINT hangcheck_interval, UINT attributes, ULONG adaptertype) +{ + struct ndis_device *wnd; + + ENTER1("%p, %p, %d, %08x, %d", nmb, mp_ctx, hangcheck_interval, + attributes, adaptertype); + wnd = nmb->wnd; + nmb->mp_ctx = mp_ctx; + wnd->attributes = attributes; + + if ((attributes & NDIS_ATTRIBUTE_BUS_MASTER) && + wrap_is_pci_bus(wnd->wd->dev_bus)) + pci_set_master(wnd->wd->pci.pdev); + + if (hangcheck_interval > 0) + wnd->hangcheck_interval = 2 * hangcheck_interval * HZ; + else + wnd->hangcheck_interval = 2 * HZ; + + EXIT1(return); +} + +wstdcall ULONG WIN_FUNC(NdisReadPciSlotInformation,5) + (struct ndis_mp_block *nmb, ULONG slot, + ULONG offset, char *buf, ULONG len) +{ + struct wrap_device *wd = nmb->wnd->wd; + ULONG i; + for (i = 0; i < len; i++) + if (pci_read_config_byte(wd->pci.pdev, offset + i, &buf[i]) != + PCIBIOS_SUCCESSFUL) + break; + DBG_BLOCK(2) { + if (i != len) + WARNING("%u, %u", i, len); + } + return i; +} + +wstdcall ULONG WIN_FUNC(NdisImmediateReadPciSlotInformation,5) + (struct ndis_mp_block *nmb, ULONG slot, + ULONG offset, char *buf, ULONG len) +{ + return NdisReadPciSlotInformation(nmb, slot, offset, buf, len); +} + +wstdcall ULONG WIN_FUNC(NdisWritePciSlotInformation,5) + (struct ndis_mp_block *nmb, ULONG slot, + ULONG offset, char *buf, ULONG len) +{ + struct wrap_device *wd = nmb->wnd->wd; + ULONG i; + for (i = 0; i < len; i++) + if (pci_write_config_byte(wd->pci.pdev, offset + i, buf[i]) != + PCIBIOS_SUCCESSFUL) + break; + DBG_BLOCK(2) { + if (i != len) + WARNING("%u, %u", i, len); + } + return i; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterIoPortRange,4) + (void **virt, struct ndis_mp_block *nmb, UINT start, UINT len) +{ + ENTER3("%08x %08x", start, len); + *virt = (void *)(ULONG_PTR)start; + return NDIS_STATUS_SUCCESS; +} + +wstdcall void WIN_FUNC(NdisMDeregisterIoPortRange,4) + (struct ndis_mp_block *nmb, UINT start, UINT len, void* virt) +{ + ENTER1("%08x %08x", start, len); +} + +wstdcall void WIN_FUNC(NdisReadPortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char *data) +{ + *data = inb(port); +} + +wstdcall void WIN_FUNC(NdisImmediateReadPortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char *data) +{ + *data = inb(port); +} + +wstdcall void WIN_FUNC(NdisWritePortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char data) +{ + outb(data, port); +} + +wstdcall void WIN_FUNC(NdisImmediateWritePortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char data) +{ + outb(data, port); +} + +wstdcall void WIN_FUNC(NdisMQueryAdapterResources,4) + (NDIS_STATUS *status, struct ndis_mp_block *nmb, + NDIS_RESOURCE_LIST *resource_list, UINT *size) +{ + struct ndis_device *wnd = nmb->wnd; + NDIS_RESOURCE_LIST *list; + UINT resource_length; + + list = &wnd->wd->resource_list->list->partial_resource_list; + resource_length = sizeof(struct cm_partial_resource_list) + + sizeof(struct cm_partial_resource_descriptor) * + (list->count - 1); + TRACE2("%p, %p,%d (%d), %p %d %d", wnd, resource_list, *size, + resource_length, &list->partial_descriptors[list->count-1], + list->partial_descriptors[list->count-1].u.interrupt.level, + list->partial_descriptors[list->count-1].u.interrupt.vector); + if (*size < sizeof(*list)) { + *size = resource_length; + *status = NDIS_STATUS_BUFFER_TOO_SHORT; + } else { + ULONG count; + if (*size >= resource_length) { + *size = resource_length; + count = list->count; + } else { + UINT n = sizeof(*list); + count = 1; + while (count++ < list->count && n < *size) + n += sizeof(list->partial_descriptors); + *size = n; + } + memcpy(resource_list, list, *size); + resource_list->count = count; + *status = NDIS_STATUS_SUCCESS; + } + EXIT2(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMPciAssignResources,3) + (struct ndis_mp_block *nmb, ULONG slot_number, + NDIS_RESOURCE_LIST **resources) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER2("%p, %p", wnd, wnd->wd->resource_list); + *resources = &wnd->wd->resource_list->list->partial_resource_list; + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMMapIoSpace,4) + (void __iomem **virt, struct ndis_mp_block *nmb, + NDIS_PHY_ADDRESS phy_addr, UINT len) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER2("%Lx, %d", phy_addr, len); + *virt = MmMapIoSpace(phy_addr, len, MmCached); + if (*virt == NULL) { + ERROR("ioremap failed"); + EXIT2(return NDIS_STATUS_FAILURE); + } + wnd->mem_start = phy_addr; + wnd->mem_end = phy_addr + len; + TRACE2("%p", *virt); + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMUnmapIoSpace,3) + (struct ndis_mp_block *nmb, void __iomem *virt, UINT len) +{ + ENTER2("%p, %d", virt, len); + MmUnmapIoSpace(virt, len); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisAllocateSpinLock,1) + (struct ndis_spinlock *lock) +{ + TRACE4("lock %p, %p", lock, &lock->klock); + KeInitializeSpinLock(&lock->klock); + lock->irql = PASSIVE_LEVEL; + return; +} + +wstdcall void WIN_FUNC(NdisFreeSpinLock,1) + (struct ndis_spinlock *lock) +{ + TRACE4("lock %p, %p", lock, &lock->klock); + return; +} + +wstdcall void WIN_FUNC(NdisAcquireSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p, %p", lock, &lock->klock); +// assert_irql(_irql_ <= DISPATCH_LEVEL); + lock->irql = nt_spin_lock_irql(&lock->klock, DISPATCH_LEVEL); + return; +} + +wstdcall void WIN_FUNC(NdisReleaseSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p, %p", lock, &lock->klock); +// assert_irql(_irql_ == DISPATCH_LEVEL); + nt_spin_unlock_irql(&lock->klock, lock->irql); + return; +} + +wstdcall void WIN_FUNC(NdisDprAcquireSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p", &lock->klock); +// assert_irql(_irql_ == DISPATCH_LEVEL); + nt_spin_lock(&lock->klock); + return; +} + +wstdcall void WIN_FUNC(NdisDprReleaseSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p", &lock->klock); +// assert_irql(_irql_ == DISPATCH_LEVEL); + nt_spin_unlock(&lock->klock); + return; +} + +wstdcall void WIN_FUNC(NdisInitializeReadWriteLock,1) + (struct ndis_rw_lock *rw_lock) +{ + ENTER3("%p", rw_lock); + memset(rw_lock, 0, sizeof(*rw_lock)); + KeInitializeSpinLock(&rw_lock->klock); + return; +} + +/* read/write locks are implemented in a rather simplisitic way - we + * should probably use Linux's rw_lock implementation */ + +wstdcall void WIN_FUNC(NdisAcquireReadWriteLock,3) + (struct ndis_rw_lock *rw_lock, BOOLEAN write, + struct lock_state *lock_state) +{ + if (write) { + while (1) { + if (cmpxchg(&rw_lock->count, 0, -1) == 0) + return; + while (rw_lock->count) + cpu_relax(); + } + return; + } + while (1) { + typeof(rw_lock->count) count; + while ((count = rw_lock->count) < 0) + cpu_relax(); + if (cmpxchg(&rw_lock->count, count, count + 1) == count) + return; + } +} + +wstdcall void WIN_FUNC(NdisReleaseReadWriteLock,2) + (struct ndis_rw_lock *rw_lock, struct lock_state *lock_state) +{ + if (rw_lock->count > 0) + pre_atomic_add(rw_lock->count, -1); + else if (rw_lock->count == -1) + rw_lock->count = 0; + else + WARNING("invalid state: %d", rw_lock->count); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateMapRegisters,5) + (struct ndis_mp_block *nmb, UINT dmachan, + NDIS_DMA_SIZE dmasize, ULONG basemap, ULONG max_buf_size) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER2("%p, %d %d %d %d", wnd, dmachan, dmasize, basemap, max_buf_size); + if (wnd->dma_map_count > 0) { + WARNING("%s: map registers already allocated: %u", + wnd->net_dev->name, wnd->dma_map_count); + EXIT2(return NDIS_STATUS_RESOURCES); + } + if (dmasize == NDIS_DMA_24BITS) { + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_24BIT_MASK) || + pci_set_consistent_dma_mask(wnd->wd->pci.pdev, + DMA_24BIT_MASK)) + WARNING("setting dma mask failed"); + } else if (dmasize == NDIS_DMA_32BITS) { + /* consistent dma is in low 32-bits by default */ + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_32BIT_MASK)) + WARNING("setting dma mask failed"); +#ifdef CONFIG_X86_64 + } else if (dmasize == NDIS_DMA_64BITS) { + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_64BIT_MASK) || + pci_set_consistent_dma_mask(wnd->wd->pci.pdev, + DMA_64BIT_MASK)) + WARNING("setting dma mask failed"); + else + wnd->net_dev->features |= NETIF_F_HIGHDMA; +#endif + } + /* since memory for buffer is allocated with kmalloc, buffer + * is physically contiguous, so entire map will fit in one + * register */ + if (basemap > 64) { + WARNING("Windows driver %s requesting too many (%u) " + "map registers", wnd->wd->driver->name, basemap); + /* As per NDIS, NDIS_STATUS_RESOURCES should be + * returned, but with that Atheros PCI driver fails - + * for now tolerate it */ +// EXIT2(return NDIS_STATUS_RESOURCES); + } + + wnd->dma_map_addr = kmalloc(basemap * sizeof(*(wnd->dma_map_addr)), + GFP_KERNEL); + if (!wnd->dma_map_addr) + EXIT2(return NDIS_STATUS_RESOURCES); + memset(wnd->dma_map_addr, 0, basemap * sizeof(*(wnd->dma_map_addr))); + wnd->dma_map_count = basemap; + TRACE2("%u", wnd->dma_map_count); + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMFreeMapRegisters,1) + (struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + int i; + + ENTER2("wnd: %p", wnd); + if (wnd->dma_map_addr) { + for (i = 0; i < wnd->dma_map_count; i++) { + if (wnd->dma_map_addr[i]) + WARNING("%s: dma addr %p not freed by " + "Windows driver", wnd->net_dev->name, + (void *)wnd->dma_map_addr[i]); + } + kfree(wnd->dma_map_addr); + wnd->dma_map_addr = NULL; + } else + WARNING("map registers already freed?"); + wnd->dma_map_count = 0; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisMStartBufferPhysicalMapping,6) + (struct ndis_mp_block *nmb, ndis_buffer *buf, + ULONG index, BOOLEAN write_to_dev, + struct ndis_phy_addr_unit *phy_addr_array, UINT *array_size) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER3("%p, %p, %u, %u", wnd, buf, index, wnd->dma_map_count); + if (unlikely(wnd->sg_dma_size || !write_to_dev || + index >= wnd->dma_map_count)) { + WARNING("invalid request: %d, %d, %d, %d", wnd->sg_dma_size, + write_to_dev, index, wnd->dma_map_count); + phy_addr_array[0].phy_addr = 0; + phy_addr_array[0].length = 0; + *array_size = 0; + return; + } + if (wnd->dma_map_addr[index]) { + TRACE2("buffer %p at %d is already mapped: %lx", buf, index, + (unsigned long)wnd->dma_map_addr[index]); +// *array_size = 1; + return; + } + TRACE3("%p, %p, %u", buf, MmGetSystemAddressForMdl(buf), + MmGetMdlByteCount(buf)); + DBG_BLOCK(4) { + dump_bytes(__FUNCTION__, MmGetSystemAddressForMdl(buf), + MmGetMdlByteCount(buf)); + } + wnd->dma_map_addr[index] = + PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, + MmGetSystemAddressForMdl(buf), + MmGetMdlByteCount(buf), PCI_DMA_TODEVICE); + phy_addr_array[0].phy_addr = wnd->dma_map_addr[index]; + phy_addr_array[0].length = MmGetMdlByteCount(buf); + TRACE4("%Lx, %d, %d", phy_addr_array[0].phy_addr, + phy_addr_array[0].length, index); + *array_size = 1; +} + +wstdcall void WIN_FUNC(NdisMCompleteBufferPhysicalMapping,3) + (struct ndis_mp_block *nmb, ndis_buffer *buf, ULONG index) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER3("%p, %p %u (%u)", wnd, buf, index, wnd->dma_map_count); + + if (unlikely(wnd->sg_dma_size)) + WARNING("buffer %p may have been unmapped already", buf); + if (index >= wnd->dma_map_count) { + ERROR("invalid map register (%u >= %u)", + index, wnd->dma_map_count); + return; + } + TRACE4("%lx", (unsigned long)wnd->dma_map_addr[index]); + if (wnd->dma_map_addr[index]) { + PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, wnd->dma_map_addr[index], + MmGetMdlByteCount(buf), PCI_DMA_TODEVICE); + wnd->dma_map_addr[index] = 0; + } else + WARNING("map registers at %u not used", index); +} + +wstdcall void WIN_FUNC(NdisMAllocateSharedMemory,5) + (struct ndis_mp_block *nmb, ULONG size, + BOOLEAN cached, void **virt, NDIS_PHY_ADDRESS *phys) +{ + dma_addr_t dma_addr; + struct wrap_device *wd = nmb->wnd->wd; + + ENTER3("size: %u, cached: %d", size, cached); + *virt = PCI_DMA_ALLOC_COHERENT(wd->pci.pdev, size, &dma_addr); + if (*virt) + *phys = dma_addr; + else + WARNING("couldn't allocate %d bytes of %scached DMA memory", + size, cached ? "" : "un-"); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisMFreeSharedMemory,5) + (struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached, + void *virt, NDIS_PHY_ADDRESS addr) +{ + struct wrap_device *wd = nmb->wnd->wd; + ENTER3("%p, %Lx, %u", virt, addr, size); + PCI_DMA_FREE_COHERENT(wd->pci.pdev, size, virt, addr); + EXIT3(return); +} + +wstdcall void alloc_shared_memory_async(void *arg1, void *arg2) +{ + struct ndis_device *wnd; + struct alloc_shared_mem *alloc_shared_mem; + struct miniport *mp; + void *virt; + NDIS_PHY_ADDRESS phys; + KIRQL irql; + + wnd = arg1; + alloc_shared_mem = arg2; + mp = &wnd->wd->driver->ndis_driver->mp; + NdisMAllocateSharedMemory(wnd->nmb, alloc_shared_mem->size, + alloc_shared_mem->cached, &virt, &phys); + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN5(mp->alloc_complete, wnd->nmb, virt, + &phys, alloc_shared_mem->size, alloc_shared_mem->ctx); + serialize_unlock_irql(wnd, irql); + kfree(alloc_shared_mem); +} +WIN_FUNC_DECL(alloc_shared_memory_async,2) + +wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateSharedMemoryAsync,4) + (struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached, void *ctx) +{ + struct ndis_device *wnd = nmb->wnd; + struct alloc_shared_mem *alloc_shared_mem; + + ENTER3("wnd: %p", wnd); + alloc_shared_mem = kmalloc(sizeof(*alloc_shared_mem), irql_gfp()); + if (!alloc_shared_mem) { + WARNING("couldn't allocate memory"); + return NDIS_STATUS_FAILURE; + } + + alloc_shared_mem->size = size; + alloc_shared_mem->cached = cached; + alloc_shared_mem->ctx = ctx; + if (schedule_ntos_work_item(WIN_FUNC_PTR(alloc_shared_memory_async,2), + wnd, alloc_shared_mem)) + EXIT3(return NDIS_STATUS_FAILURE); + EXIT3(return NDIS_STATUS_PENDING); +} + +/* Some drivers allocate NDIS_BUFFER (aka MDL) very often; instead of + * allocating and freeing with kernel functions, we chain them into + * ndis_buffer_pool. When an MDL is freed, it is added to the list of + * free MDLs. When allocated, we first check if there is one in free + * list and if so just return it; otherwise, we allocate a new one and + * return that. This reduces memory fragmentation. Windows DDK says + * that the driver itself shouldn't check what is returned in + * pool_handle, presumably because buffer pools are not used in + * XP. However, as long as driver follows rest of the semantics - that + * it should indicate maximum number of MDLs used with num_descr and + * pass the same pool_handle in other buffer functions, this should + * work. Sadly, though, NdisFreeBuffer doesn't pass the pool_handle, + * so we use 'process' field of MDL to store pool_handle. */ + +wstdcall void WIN_FUNC(NdisAllocateBufferPool,3) + (NDIS_STATUS *status, struct ndis_buffer_pool **pool_handle, + UINT num_descr) +{ + struct ndis_buffer_pool *pool; + + ENTER1("buffers: %d", num_descr); + pool = kmalloc(sizeof(*pool), irql_gfp()); + if (!pool) { + *status = NDIS_STATUS_RESOURCES; + EXIT3(return); + } + spin_lock_init(&pool->lock); + pool->max_descr = num_descr; + pool->num_allocated_descr = 0; + pool->free_descr = NULL; + *pool_handle = pool; + *status = NDIS_STATUS_SUCCESS; + TRACE1("pool: %p, num_descr: %d", pool, num_descr); + EXIT1(return); +} + +wstdcall void WIN_FUNC(NdisAllocateBuffer,5) + (NDIS_STATUS *status, ndis_buffer **buffer, + struct ndis_buffer_pool *pool, void *virt, UINT length) +{ + ndis_buffer *descr; + + ENTER4("pool: %p (%d)", pool, pool->num_allocated_descr); + /* NDIS drivers should call this at DISPATCH_LEVEL, but + * alloc_tx_packet calls at SOFT_IRQL */ + assert_irql(_irql_ <= SOFT_LEVEL); + if (!pool) { + *status = NDIS_STATUS_FAILURE; + *buffer = NULL; + EXIT4(return); + } + spin_lock_bh(&pool->lock); + if ((descr = pool->free_descr)) + pool->free_descr = descr->next; + spin_unlock_bh(&pool->lock); + if (descr) { + typeof(descr->flags) flags; + flags = descr->flags; + memset(descr, 0, sizeof(*descr)); + MmInitializeMdl(descr, virt, length); + if (flags & MDL_CACHE_ALLOCATED) + descr->flags |= MDL_CACHE_ALLOCATED; + } else { + if (pool->num_allocated_descr > pool->max_descr) { + TRACE2("pool %p is full: %d(%d)", pool, + pool->num_allocated_descr, pool->max_descr); +#ifndef ALLOW_POOL_OVERFLOW + *status = NDIS_STATUS_FAILURE; + *buffer = NULL; + return; +#endif + } + descr = allocate_init_mdl(virt, length); + if (!descr) { + WARNING("couldn't allocate buffer"); + *status = NDIS_STATUS_FAILURE; + *buffer = NULL; + EXIT4(return); + } + TRACE4("buffer %p for %p, %d", descr, virt, length); + atomic_inc_var(pool->num_allocated_descr); + } + /* TODO: make sure this mdl can map given buffer */ + MmBuildMdlForNonPagedPool(descr); +// descr->flags |= MDL_ALLOCATED_FIXED_SIZE | +// MDL_MAPPED_TO_SYSTEM_VA | MDL_PAGES_LOCKED; + descr->pool = pool; + *buffer = descr; + *status = NDIS_STATUS_SUCCESS; + TRACE4("buffer: %p", descr); + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisFreeBuffer,1) + (ndis_buffer *buffer) +{ + struct ndis_buffer_pool *pool; + + ENTER4("%p", buffer); + if (!buffer || !buffer->pool) { + ERROR("invalid buffer"); + EXIT4(return); + } + pool = buffer->pool; + if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_BUFFERS) { + /* NB NB NB: set mdl's 'pool' field to NULL before + * calling free_mdl; otherwise free_mdl calls + * NdisFreeBuffer back */ + atomic_dec_var(pool->num_allocated_descr); + buffer->pool = NULL; + free_mdl(buffer); + } else { + spin_lock_bh(&pool->lock); + buffer->next = pool->free_descr; + pool->free_descr = buffer; + spin_unlock_bh(&pool->lock); + } + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisFreeBufferPool,1) + (struct ndis_buffer_pool *pool) +{ + ndis_buffer *cur, *next; + + TRACE3("pool: %p", pool); + if (!pool) { + WARNING("invalid pool"); + EXIT3(return); + } + spin_lock_bh(&pool->lock); + cur = pool->free_descr; + while (cur) { + next = cur->next; + cur->pool = NULL; + free_mdl(cur); + cur = next; + } + spin_unlock_bh(&pool->lock); + kfree(pool); + pool = NULL; + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisAdjustBufferLength,2) + (ndis_buffer *buffer, UINT length) +{ + ENTER4("%p, %d", buffer, length); + buffer->bytecount = length; +} + +wstdcall void WIN_FUNC(NdisQueryBuffer,3) + (ndis_buffer *buffer, void **virt, UINT *length) +{ + ENTER4("buffer: %p", buffer); + if (virt) + *virt = MmGetSystemAddressForMdl(buffer); + *length = MmGetMdlByteCount(buffer); + TRACE4("%p, %u", virt? *virt : NULL, *length); + return; +} + +wstdcall void WIN_FUNC(NdisQueryBufferSafe,4) + (ndis_buffer *buffer, void **virt, UINT *length, + enum mm_page_priority priority) +{ + ENTER4("%p, %p, %p, %d", buffer, virt, length, priority); + if (virt) + *virt = MmGetSystemAddressForMdlSafe(buffer, priority); + *length = MmGetMdlByteCount(buffer); + TRACE4("%p, %u", virt? *virt : NULL, *length); +} + +wstdcall void *WIN_FUNC(NdisBufferVirtualAddress,1) + (ndis_buffer *buffer) +{ + ENTER3("%p", buffer); + return MmGetSystemAddressForMdl(buffer); +} + +wstdcall ULONG WIN_FUNC(NdisBufferLength,1) + (ndis_buffer *buffer) +{ + ENTER3("%p", buffer); + return MmGetMdlByteCount(buffer); +} + +wstdcall void WIN_FUNC(NdisQueryBufferOffset,3) + (ndis_buffer *buffer, UINT *offset, UINT *length) +{ + ENTER3("%p", buffer); + *offset = MmGetMdlByteOffset(buffer); + *length = MmGetMdlByteCount(buffer); + TRACE3("%d, %d", *offset, *length); +} + +wstdcall void WIN_FUNC(NdisUnchainBufferAtBack,2) + (struct ndis_packet *packet, ndis_buffer **buffer) +{ + ndis_buffer *b, *btail; + + ENTER3("%p", packet); + b = packet->private.buffer_head; + if (!b) { + /* no buffer in packet */ + *buffer = NULL; + EXIT3(return); + } + btail = packet->private.buffer_tail; + *buffer = btail; + if (b == btail) { + /* one buffer in packet */ + packet->private.buffer_head = NULL; + packet->private.buffer_tail = NULL; + } else { + while (b->next != btail) + b = b->next; + packet->private.buffer_tail = b; + b->next = NULL; + } + packet->private.valid_counts = FALSE; + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisUnchainBufferAtFront,2) + (struct ndis_packet *packet, ndis_buffer **buffer) +{ + ENTER3("%p", packet); + if (packet->private.buffer_head == NULL) { + /* no buffer in packet */ + *buffer = NULL; + EXIT3(return); + } + + *buffer = packet->private.buffer_head; + if (packet->private.buffer_head == packet->private.buffer_tail) { + /* one buffer in packet */ + packet->private.buffer_head = NULL; + packet->private.buffer_tail = NULL; + } else + packet->private.buffer_head = (*buffer)->next; + + packet->private.valid_counts = FALSE; + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacketSafe,6) + (struct ndis_packet *packet, ndis_buffer **first_buffer, + void **first_buffer_va, UINT *first_buffer_length, + UINT *total_buffer_length, enum mm_page_priority priority) +{ + ndis_buffer *b = packet->private.buffer_head; + + ENTER3("%p(%p)", packet, b); + *first_buffer = b; + if (b) { + *first_buffer_va = MmGetSystemAddressForMdlSafe(b, priority); + *first_buffer_length = *total_buffer_length = + MmGetMdlByteCount(b); + for (b = b->next; b; b = b->next) + *total_buffer_length += MmGetMdlByteCount(b); + } else { + *first_buffer_va = NULL; + *first_buffer_length = 0; + *total_buffer_length = 0; + } + TRACE3("%p, %d, %d", *first_buffer_va, *first_buffer_length, + *total_buffer_length); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacket,6) + (struct ndis_packet *packet, ndis_buffer **first_buffer, + void **first_buffer_va, UINT *first_buffer_length, + UINT *total_buffer_length, enum mm_page_priority priority) +{ + NdisGetFirstBufferFromPacketSafe(packet, first_buffer, + first_buffer_va, first_buffer_length, + total_buffer_length, + NormalPagePriority); +} + +wstdcall void WIN_FUNC(NdisAllocatePacketPoolEx,5) + (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, + UINT num_descr, UINT overflowsize, UINT proto_rsvd_length) +{ + struct ndis_packet_pool *pool; + + ENTER3("buffers: %d, length: %d", num_descr, proto_rsvd_length); + pool = kzalloc(sizeof(*pool), irql_gfp()); + if (!pool) { + *status = NDIS_STATUS_RESOURCES; + EXIT3(return); + } + spin_lock_init(&pool->lock); + pool->max_descr = num_descr; + pool->num_allocated_descr = 0; + pool->num_used_descr = 0; + pool->free_descr = NULL; + pool->proto_rsvd_length = proto_rsvd_length; + *pool_handle = pool; + *status = NDIS_STATUS_SUCCESS; + TRACE3("pool: %p", pool); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisAllocatePacketPool,4) + (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, + UINT num_descr, UINT proto_rsvd_length) +{ + NdisAllocatePacketPoolEx(status, pool_handle, num_descr, 0, + proto_rsvd_length); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisFreePacketPool,1) + (struct ndis_packet_pool *pool) +{ + struct ndis_packet *packet, *next; + + ENTER3("pool: %p", pool); + if (!pool) { + WARNING("invalid pool"); + EXIT3(return); + } + spin_lock_bh(&pool->lock); + packet = pool->free_descr; + while (packet) { + next = (struct ndis_packet *)packet->reserved[0]; + kfree(packet); + packet = next; + } + pool->num_allocated_descr = 0; + pool->num_used_descr = 0; + pool->free_descr = NULL; + spin_unlock_bh(&pool->lock); + kfree(pool); + EXIT3(return); +} + +wstdcall UINT WIN_FUNC(NdisPacketPoolUsage,1) + (struct ndis_packet_pool *pool) +{ + EXIT4(return pool->num_used_descr); +} + +wstdcall void WIN_FUNC(NdisAllocatePacket,3) + (NDIS_STATUS *status, struct ndis_packet **ndis_packet, + struct ndis_packet_pool *pool) +{ + struct ndis_packet *packet; + int packet_length; + + ENTER4("pool: %p", pool); + if (!pool) { + *status = NDIS_STATUS_RESOURCES; + *ndis_packet = NULL; + EXIT4(return); + } + assert_irql(_irql_ <= SOFT_LEVEL); + if (pool->num_used_descr > pool->max_descr) { + TRACE3("pool %p is full: %d(%d)", pool, + pool->num_used_descr, pool->max_descr); +#ifndef ALLOW_POOL_OVERFLOW + *status = NDIS_STATUS_RESOURCES; + *ndis_packet = NULL; + return; +#endif + } + /* packet has space for 1 byte in protocol_reserved field */ + packet_length = sizeof(*packet) - 1 + pool->proto_rsvd_length + + sizeof(struct ndis_packet_oob_data); + spin_lock_bh(&pool->lock); + if ((packet = pool->free_descr)) + pool->free_descr = (void *)packet->reserved[0]; + spin_unlock_bh(&pool->lock); + if (!packet) { + packet = kmalloc(packet_length, irql_gfp()); + if (!packet) { + WARNING("couldn't allocate packet"); + *status = NDIS_STATUS_RESOURCES; + *ndis_packet = NULL; + return; + } + atomic_inc_var(pool->num_allocated_descr); + } + TRACE4("%p, %p", pool, packet); + atomic_inc_var(pool->num_used_descr); + memset(packet, 0, packet_length); + packet->private.oob_offset = + packet_length - sizeof(struct ndis_packet_oob_data); + packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS; + packet->private.pool = pool; + *ndis_packet = packet; + *status = NDIS_STATUS_SUCCESS; + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisDprAllocatePacket,3) + (NDIS_STATUS *status, struct ndis_packet **packet, + struct ndis_packet_pool *pool) +{ + NdisAllocatePacket(status, packet, pool); +} + +wstdcall void WIN_FUNC(NdisFreePacket,1) + (struct ndis_packet *packet) +{ + struct ndis_packet_pool *pool; + + ENTER4("%p, %p", packet, packet->private.pool); + pool = packet->private.pool; + if (!pool) { + ERROR("invalid pool %p", packet); + EXIT4(return); + } + assert((int)pool->num_used_descr > 0); + atomic_dec_var(pool->num_used_descr); + if (packet->reserved[1]) { + TRACE3("%p, %p", packet, (void *)packet->reserved[1]); + kfree((void *)packet->reserved[1]); + packet->reserved[1] = 0; + } + if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) { + TRACE3("%p", pool); + atomic_dec_var(pool->num_allocated_descr); + kfree(packet); + } else { + TRACE4("%p, %p, %p", pool, packet, pool->free_descr); + spin_lock_bh(&pool->lock); + packet->reserved[0] = + (typeof(packet->reserved[0]))pool->free_descr; + pool->free_descr = packet; + spin_unlock_bh(&pool->lock); + } + EXIT4(return); +} + +wstdcall struct ndis_packet_stack *WIN_FUNC(NdisIMGetCurrentPacketStack,2) + (struct ndis_packet *packet, BOOLEAN *stacks_remain) +{ + struct ndis_packet_stack *stack; + + if (!packet->reserved[1]) { + stack = kzalloc(2 * sizeof(*stack), irql_gfp()); + TRACE3("%p, %p", packet, stack); + packet->reserved[1] = (typeof(packet->reserved[1]))stack; + } else { + stack = (void *)packet->reserved[1];; + if (xchg(&stack->ndis_reserved[0], 1)) { + stack++; + if (xchg(&stack->ndis_reserved[0], 1)) + stack = NULL; + } + TRACE3("%p", stack); + } + if (stack) + *stacks_remain = TRUE; + else + *stacks_remain = FALSE; + + EXIT3(return stack); +} + +wstdcall void WIN_FUNC(NdisCopyFromPacketToPacketSafe,7) + (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy, + struct ndis_packet *src, UINT src_offset, UINT *num_copied, + enum mm_page_priority priority) +{ + UINT dst_n, src_n, n, left; + ndis_buffer *dst_buf; + ndis_buffer *src_buf; + + ENTER4(""); + if (!dst || !src) { + *num_copied = 0; + EXIT4(return); + } + + dst_buf = dst->private.buffer_head; + src_buf = src->private.buffer_head; + + if (!dst_buf || !src_buf) { + *num_copied = 0; + EXIT4(return); + } + dst_n = MmGetMdlByteCount(dst_buf) - dst_offset; + src_n = MmGetMdlByteCount(src_buf) - src_offset; + + n = min(src_n, dst_n); + n = min(n, num_to_copy); + memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset, + MmGetSystemAddressForMdl(src_buf) + src_offset, n); + + left = num_to_copy - n; + while (left > 0) { + src_offset += n; + dst_offset += n; + dst_n -= n; + src_n -= n; + if (dst_n == 0) { + dst_buf = dst_buf->next; + if (!dst_buf) + break; + dst_n = MmGetMdlByteCount(dst_buf); + dst_offset = 0; + } + if (src_n == 0) { + src_buf = src_buf->next; + if (!src_buf) + break; + src_n = MmGetMdlByteCount(src_buf); + src_offset = 0; + } + + n = min(src_n, dst_n); + n = min(n, left); + memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset, + MmGetSystemAddressForMdl(src_buf) + src_offset, n); + left -= n; + } + *num_copied = num_to_copy - left; + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisCopyFromPacketToPacket,6) + (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy, + struct ndis_packet *src, UINT src_offset, UINT *num_copied) +{ + NdisCopyFromPacketToPacketSafe(dst, dst_offset, num_to_copy, + src, src_offset, num_copied, + NormalPagePriority); + return; +} + +wstdcall void WIN_FUNC(NdisIMCopySendPerPacketInfo,2) + (struct ndis_packet *dst, struct ndis_packet *src) +{ + struct ndis_packet_oob_data *dst_oob, *src_oob; + dst_oob = NDIS_PACKET_OOB_DATA(dst); + src_oob = NDIS_PACKET_OOB_DATA(src); + memcpy(&dst_oob->ext, &src_oob->ext, sizeof(dst_oob->ext)); + return; +} + +wstdcall void WIN_FUNC(NdisSend,3) + (NDIS_STATUS *status, struct ndis_mp_block *nmb, + struct ndis_packet *packet) +{ + struct ndis_device *wnd = nmb->wnd; + struct miniport *mp; + KIRQL irql; + + mp = &wnd->wd->driver->ndis_driver->mp; + if (mp->send_packets) { + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, &packet, 1); + serialize_unlock_irql(wnd, irql); + if (deserialized_driver(wnd)) + *status = NDIS_STATUS_PENDING; + else { + struct ndis_packet_oob_data *oob_data; + oob_data = NDIS_PACKET_OOB_DATA(packet); + *status = oob_data->status; + switch (*status) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, *status); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + break; + case NDIS_STATUS_FAILURE: + default: + free_tx_packet(wnd, packet, *status); + break; + } + } + } else { + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + *status = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, packet, 0); + serialize_unlock_irql(wnd, irql); + switch (*status) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, *status); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + break; + case NDIS_STATUS_FAILURE: + default: + free_tx_packet(wnd, packet, *status); + break; + } + } + EXIT3(return); +} + +/* called for serialized drivers only */ +wstdcall void mp_timer_dpc(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2) +{ + struct ndis_mp_timer *timer; + struct ndis_mp_block *nmb; + + timer = ctx; + TIMERENTER("%p, %p, %p, %p", timer, timer->func, timer->ctx, timer->nmb); + assert_irql(_irql_ == DISPATCH_LEVEL); + nmb = timer->nmb; + serialize_lock(nmb->wnd); + LIN2WIN4(timer->func, NULL, timer->ctx, NULL, NULL); + serialize_unlock(nmb->wnd); + TIMEREXIT(return); +} +WIN_FUNC_DECL(mp_timer_dpc,4) + +wstdcall void WIN_FUNC(NdisMInitializeTimer,4) + (struct ndis_mp_timer *timer, struct ndis_mp_block *nmb, + DPC func, void *ctx) +{ + TIMERENTER("%p, %p, %p, %p", timer, func, ctx, nmb); + assert_irql(_irql_ == PASSIVE_LEVEL); + timer->func = func; + timer->ctx = ctx; + timer->nmb = nmb; + if (deserialized_driver(nmb->wnd)) + KeInitializeDpc(&timer->kdpc, func, ctx); + else + KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(mp_timer_dpc,4), + timer); + wrap_init_timer(&timer->nt_timer, NotificationTimer, nmb); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2) + (struct ndis_mp_timer *timer, UINT period_ms) +{ + unsigned long expires = MSEC_TO_HZ(period_ms); + + TIMERENTER("%p, %u, %ld", timer, period_ms, expires); + assert_irql(_irql_ <= DISPATCH_LEVEL); + wrap_set_timer(&timer->nt_timer, expires, expires, &timer->kdpc); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisMCancelTimer,2) + (struct ndis_mp_timer *timer, BOOLEAN *canceled) +{ + TIMERENTER("%p", timer); + assert_irql(_irql_ <= DISPATCH_LEVEL); + *canceled = KeCancelTimer(&timer->nt_timer); + TIMERTRACE("%d", *canceled); + return; +} + +wstdcall void WIN_FUNC(NdisInitializeTimer,3) + (struct ndis_timer *timer, void *func, void *ctx) +{ + TIMERENTER("%p, %p, %p", timer, func, ctx); + assert_irql(_irql_ == PASSIVE_LEVEL); + KeInitializeDpc(&timer->kdpc, func, ctx); + wrap_init_timer(&timer->nt_timer, NotificationTimer, NULL); + TIMEREXIT(return); +} + +/* NdisMSetTimer is a macro that calls NdisSetTimer with + * ndis_mp_timer typecast to ndis_timer */ + +wstdcall void WIN_FUNC(NdisSetTimer,2) + (struct ndis_timer *timer, UINT duetime_ms) +{ + unsigned long expires = MSEC_TO_HZ(duetime_ms); + + TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer, + duetime_ms, expires); + assert_irql(_irql_ <= DISPATCH_LEVEL); + wrap_set_timer(&timer->nt_timer, expires, 0, &timer->kdpc); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisCancelTimer,2) + (struct ndis_timer *timer, BOOLEAN *canceled) +{ + TIMERENTER("%p", timer); + assert_irql(_irql_ <= DISPATCH_LEVEL); + *canceled = KeCancelTimer(&timer->nt_timer); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3) + (struct ndis_mp_block *nmb, void *ctx, void *func) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER1("%p", func); + wnd->wd->driver->ndis_driver->mp.shutdown = func; + wnd->shutdown_ctx = ctx; +} + +wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1) + (struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + wnd->wd->driver->ndis_driver->mp.shutdown = NULL; + wnd->shutdown_ctx = NULL; +} + +/* TODO: rt61 (serialized) driver doesn't want MiniportEnableInterrupt + * to be called in irq handler, but mrv800c (deserialized) driver + * wants. NDIS is confusing about when to call MiniportEnableInterrupt + * For now, handle these cases with two separate irq handlers based on + * observation of these two drivers. However, it is likely not + * correct. */ +wstdcall void deserialized_irq_handler(struct kdpc *kdpc, void *ctx, + void *arg1, void *arg2) +{ + struct ndis_device *wnd = ctx; + ndis_interrupt_handler irq_handler = arg1; + struct miniport *mp = arg2; + + TRACE6("%p", irq_handler); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN1(irq_handler, wnd->nmb->mp_ctx); + if (mp->enable_interrupt) + LIN2WIN1(mp->enable_interrupt, wnd->nmb->mp_ctx); + EXIT6(return); +} +WIN_FUNC_DECL(deserialized_irq_handler,4) + +wstdcall void serialized_irq_handler(struct kdpc *kdpc, void *ctx, + void *arg1, void *arg2) +{ + struct ndis_device *wnd = ctx; + ndis_interrupt_handler irq_handler = arg1; + + TRACE6("%p, %p, %p", wnd, irq_handler, arg2); + assert_irql(_irql_ == DISPATCH_LEVEL); + serialize_lock(wnd); + LIN2WIN1(irq_handler, arg2); + serialize_unlock(wnd); + EXIT6(return); +} +WIN_FUNC_DECL(serialized_irq_handler,4) + +wstdcall BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx) +{ + struct ndis_mp_interrupt *mp_interrupt = ctx; + struct ndis_device *wnd = mp_interrupt->nmb->wnd; + BOOLEAN recognized, queue_handler; + + TRACE6("%p", wnd); + /* kernel may call ISR when registering interrupt, in + * the same context if DEBUG_SHIRQ is enabled */ + assert_irql(_irql_ == DIRQL || _irql_ == PASSIVE_LEVEL); + if (mp_interrupt->shared) + LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler, + wnd->nmb->mp_ctx); + else { + struct miniport *mp; + mp = &wnd->wd->driver->ndis_driver->mp; + LIN2WIN1(mp->disable_interrupt, wnd->nmb->mp_ctx); + /* it is not shared interrupt, so handler must be called */ + recognized = queue_handler = TRUE; + } + if (recognized) { + if (queue_handler) { + TRACE5("%p", &wnd->irq_kdpc); + queue_kdpc(&wnd->irq_kdpc); + } + EXIT6(return TRUE); + } + EXIT6(return FALSE); +} +WIN_FUNC_DECL(ndis_isr,2) + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7) + (struct ndis_mp_interrupt *mp_interrupt, + struct ndis_mp_block *nmb, UINT vector, UINT level, + BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode) +{ + struct ndis_device *wnd = nmb->wnd; + struct miniport *mp; + + ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d", + mp_interrupt, vector, level, req_isr, shared, mode); + + mp = &wnd->wd->driver->ndis_driver->mp; + nt_spin_lock_init(&mp_interrupt->lock); + mp_interrupt->irq = vector; + mp_interrupt->isr = mp->isr; + mp_interrupt->mp_dpc = mp->handle_interrupt; + mp_interrupt->nmb = nmb; + mp_interrupt->req_isr = req_isr; + if (shared && !req_isr) + WARNING("shared but dynamic interrupt!"); + mp_interrupt->shared = shared; + wnd->mp_interrupt = mp_interrupt; + if (mp->enable_interrupt) + mp_interrupt->enable = TRUE; + else + mp_interrupt->enable = FALSE; + + if (deserialized_driver(wnd)) { + KeInitializeDpc(&wnd->irq_kdpc, + WIN_FUNC_PTR(deserialized_irq_handler,4), + nmb->wnd); + wnd->irq_kdpc.arg1 = mp->handle_interrupt; + wnd->irq_kdpc.arg2 = mp; + TRACE2("%p, %p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2, + nmb->wnd, nmb->mp_ctx); + } else { + KeInitializeDpc(&wnd->irq_kdpc, + WIN_FUNC_PTR(serialized_irq_handler,4), + nmb->wnd); + wnd->irq_kdpc.arg1 = mp->handle_interrupt; + wnd->irq_kdpc.arg2 = nmb->mp_ctx; + TRACE2("%p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2, + nmb->wnd); + } + + if (IoConnectInterrupt(&mp_interrupt->kinterrupt, + WIN_FUNC_PTR(ndis_isr,2), mp_interrupt, NULL, + vector, DIRQL, DIRQL, mode, shared, 0, FALSE) != + STATUS_SUCCESS) { + printk(KERN_WARNING "%s: request for IRQ %d failed\n", + DRIVER_NAME, vector); + return NDIS_STATUS_RESOURCES; + } + printk(KERN_INFO "%s: using IRQ %d\n", DRIVER_NAME, vector); + EXIT1(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMDeregisterInterrupt,1) + (struct ndis_mp_interrupt *mp_interrupt) +{ + struct ndis_mp_block *nmb; + + ENTER1("%p", mp_interrupt); + nmb = xchg(&mp_interrupt->nmb, NULL); + TRACE1("%p", nmb); + if (!nmb) { + WARNING("interrupt already freed?"); + return; + } + nmb->wnd->mp_interrupt = NULL; + if (dequeue_kdpc(&nmb->wnd->irq_kdpc)) + TRACE2("interrupt kdpc was pending"); + flush_workqueue(wrapndis_wq); + IoDisconnectInterrupt(mp_interrupt->kinterrupt); + EXIT1(return); +} + +wstdcall BOOLEAN WIN_FUNC(NdisMSynchronizeWithInterrupt,3) + (struct ndis_mp_interrupt *mp_interrupt, + PKSYNCHRONIZE_ROUTINE sync_func, void *ctx) +{ + return KeSynchronizeExecution(mp_interrupt->kinterrupt, sync_func, ctx); +} + +/* called via function pointer; but 64-bit RNDIS driver calls directly */ +wstdcall void WIN_FUNC(NdisMIndicateStatus,4) + (struct ndis_mp_block *nmb, NDIS_STATUS status, void *buf, UINT len) +{ + struct ndis_device *wnd = nmb->wnd; + struct ndis_status_indication *si; + + ENTER2("status=0x%x len=%d", status, len); + switch (status) { + case NDIS_STATUS_MEDIA_CONNECT: + netif_carrier_on(wnd->net_dev); + wnd->tx_ok = 1; + if (netif_queue_stopped(wnd->net_dev)) + netif_wake_queue(wnd->net_dev); + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + set_bit(LINK_STATUS_ON, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + break; + case NDIS_STATUS_MEDIA_DISCONNECT: + netif_carrier_off(wnd->net_dev); + netif_stop_queue(wnd->net_dev); + wnd->tx_ok = 0; + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + memset(&wnd->essid, 0, sizeof(wnd->essid)); + set_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + break; + case NDIS_STATUS_MEDIA_SPECIFIC_INDICATION: + if (!buf) + break; + si = buf; + TRACE2("status_type=%d", si->status_type); + switch (si->status_type) { + case Ndis802_11StatusType_MediaStreamMode: + break; +#ifdef CONFIG_WIRELESS_EXT + case Ndis802_11StatusType_Authentication: + buf = (char *)buf + sizeof(*si); + len -= sizeof(*si); + while (len > 0) { + int pairwise_error = 0, group_error = 0; + struct ndis_auth_req *auth_req = + (struct ndis_auth_req *)buf; + TRACE1(MACSTRSEP, MAC2STR(auth_req->bssid)); + if (auth_req->flags & 0x01) + TRACE2("reauth request"); + if (auth_req->flags & 0x02) + TRACE2("key update request"); + if (auth_req->flags & 0x06) { + pairwise_error = 1; + TRACE2("pairwise_error"); + } + if (auth_req->flags & 0x0E) { + group_error = 1; + TRACE2("group_error"); + } + if (pairwise_error || group_error) { + union iwreq_data wrqu; + struct iw_michaelmicfailure micfailure; + + memset(&micfailure, 0, sizeof(micfailure)); + if (pairwise_error) + micfailure.flags |= + IW_MICFAILURE_PAIRWISE; + if (group_error) + micfailure.flags |= + IW_MICFAILURE_GROUP; + memcpy(micfailure.src_addr.sa_data, + auth_req->bssid, ETH_ALEN); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(micfailure); + wireless_send_event(wnd->net_dev, + IWEVMICHAELMICFAILURE, + &wrqu, (u8 *)&micfailure); + } + len -= auth_req->length; + buf = (char *)buf + auth_req->length; + } + break; + case Ndis802_11StatusType_PMKID_CandidateList: + { + u8 *end; + unsigned long i; + struct ndis_pmkid_candidate_list *cand; + + cand = buf + sizeof(struct ndis_status_indication); + if (len < sizeof(struct ndis_status_indication) + + sizeof(struct ndis_pmkid_candidate_list) || + cand->version != 1) { + WARNING("unrecognized PMKID ignored"); + EXIT1(return); + } + + end = (u8 *)buf + len; + TRACE2("PMKID ver %d num_cand %d", + cand->version, cand->num_candidates); + for (i = 0; i < cand->num_candidates; i++) { + struct iw_pmkid_cand pcand; + union iwreq_data wrqu; + struct ndis_pmkid_candidate *c = + &cand->candidates[i]; + if ((u8 *)(c + 1) > end) { + TRACE2("truncated PMKID"); + break; + } + TRACE2("%ld: " MACSTRSEP " 0x%x", + i, MAC2STR(c->bssid), c->flags); + memset(&pcand, 0, sizeof(pcand)); + if (c->flags & 0x01) + pcand.flags |= IW_PMKID_CAND_PREAUTH; + pcand.index = i; + memcpy(pcand.bssid.sa_data, c->bssid, ETH_ALEN); + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(pcand); + wireless_send_event(wnd->net_dev, IWEVPMKIDCAND, + &wrqu, (u8 *)&pcand); + } + break; + } + case Ndis802_11StatusType_RadioState: + { + struct ndis_radio_status_indication *radio_status = buf; + if (radio_status->radio_state == + Ndis802_11RadioStatusOn) + INFO("radio is turned on"); + else if (radio_status->radio_state == + Ndis802_11RadioStatusHardwareOff) + INFO("radio is turned off by hardware"); + else if (radio_status->radio_state == + Ndis802_11RadioStatusSoftwareOff) + INFO("radio is turned off by software"); + break; + } +#endif + default: + /* is this RSSI indication? */ + TRACE2("unknown indication: %x", si->status_type); + break; + } + break; + default: + TRACE2("unknown status: %08X", status); + break; + } + + EXIT2(return); +} + +/* called via function pointer; but 64-bit RNDIS driver calls directly */ +wstdcall void WIN_FUNC(NdisMIndicateStatusComplete,1) + (struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER2("%p", wnd); + if (wnd->tx_ok) + schedule_wrapndis_work(&wnd->tx_work); +} + +/* called via function pointer */ +wstdcall void NdisMSendComplete(struct ndis_mp_block *nmb, + struct ndis_packet *packet, NDIS_STATUS status) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER4("%p, %08X", packet, status); + assert_irql(_irql_ <= DISPATCH_LEVEL); + if (deserialized_driver(wnd)) + free_tx_packet(wnd, packet, status); + else { + struct ndis_packet_oob_data *oob_data; + NDIS_STATUS pkt_status; + TRACE3("%p, %08x", packet, status); + oob_data = NDIS_PACKET_OOB_DATA(packet); + switch ((pkt_status = xchg(&oob_data->status, status))) { + case NDIS_STATUS_NOT_RECOGNIZED: + free_tx_packet(wnd, packet, status); + break; + case NDIS_STATUS_PENDING: + case 0: + break; + default: + WARNING("%p: invalid status: %08X", packet, pkt_status); + break; + } + /* In case a serialized driver has earlier requested a + * pause by returning NDIS_STATUS_RESOURCES during + * MiniportSend(Packets), wakeup tx worker now. + */ + if (xchg(&wnd->tx_ok, 1) == 0) { + TRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end); + schedule_wrapndis_work(&wnd->tx_work); + } + } + EXIT3(return); +} + +/* called via function pointer */ +wstdcall void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end); + wnd->tx_ok = 1; + schedule_wrapndis_work(&wnd->tx_work); + EXIT3(return); +} + +wstdcall void return_packet(void *arg1, void *arg2) +{ + struct ndis_device *wnd; + struct ndis_packet *packet; + struct miniport *mp; + KIRQL irql; + + wnd = arg1; + packet = arg2; + ENTER4("%p, %p", wnd, packet); + mp = &wnd->wd->driver->ndis_driver->mp; + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN2(mp->return_packet, wnd->nmb->mp_ctx, packet); + serialize_unlock_irql(wnd, irql); + EXIT4(return); +} +WIN_FUNC_DECL(return_packet,2) + +/* called via function pointer */ +wstdcall void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb, + struct ndis_packet **packets, + UINT nr_packets) +{ + struct ndis_device *wnd; + ndis_buffer *buffer; + struct ndis_packet *packet; + struct sk_buff *skb; + ULONG i, length, total_length; + struct ndis_packet_oob_data *oob_data; + void *virt; + struct ndis_tcp_ip_checksum_packet_info csum; + + ENTER3("%p, %d", nmb, nr_packets); + assert_irql(_irql_ <= DISPATCH_LEVEL); + wnd = nmb->wnd; + for (i = 0; i < nr_packets; i++) { + packet = packets[i]; + if (!packet) { + WARNING("empty packet ignored"); + continue; + } + wnd->net_dev->last_rx = jiffies; + /* get total number of bytes in packet */ + NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt, + &length, &total_length, + NormalPagePriority); + TRACE3("%d, %d", length, total_length); + oob_data = NDIS_PACKET_OOB_DATA(packet); + TRACE3("0x%x, 0x%x, %Lu", packet->private.flags, + packet->private.packet_flags, oob_data->time_rxed); + skb = dev_alloc_skb(total_length); + if (skb) { + while (buffer) { + memcpy_skb(skb, MmGetSystemAddressForMdl(buffer), + MmGetMdlByteCount(buffer)); + buffer = buffer->next; + } + skb->dev = wnd->net_dev; + skb->protocol = eth_type_trans(skb, wnd->net_dev); + pre_atomic_add(wnd->net_stats.rx_bytes, total_length); + atomic_inc_var(wnd->net_stats.rx_packets); + csum.value = (typeof(csum.value))(ULONG_PTR) + oob_data->ext.info[TcpIpChecksumPacketInfo]; + TRACE3("0x%05x", csum.value); + if (wnd->rx_csum.value && + (csum.rx.tcp_succeeded || csum.rx.udp_succeeded || + csum.rx.ip_succeeded)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + } else { + WARNING("couldn't allocate skb; packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + } + + /* serialized drivers check the status upon return + * from this function */ + if (!deserialized_driver(wnd)) { + oob_data->status = NDIS_STATUS_SUCCESS; + continue; + } + + /* if a deserialized driver sets + * NDIS_STATUS_RESOURCES, then it reclaims the packet + * upon return from this function */ + if (oob_data->status == NDIS_STATUS_RESOURCES) + continue; + + assert(oob_data->status == NDIS_STATUS_SUCCESS); + /* deserialized driver doesn't check the status upon + * return from this function; we need to call + * MiniportReturnPacket later for this packet. Calling + * MiniportReturnPacket from here is not correct - the + * driver doesn't expect it (at least Centrino driver + * crashes) */ + schedule_ntos_work_item(WIN_FUNC_PTR(return_packet,2), + wnd, packet); + } + EXIT3(return); +} + +/* called via function pointer (by NdisMEthIndicateReceive macro); the + * first argument is nmb->eth_db */ +wstdcall void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx, + char *header1, char *header, UINT header_size, + void *look_ahead, UINT look_ahead_size, + UINT packet_size) +{ + struct sk_buff *skb = NULL; + struct ndis_device *wnd; + unsigned int skb_size = 0; + KIRQL irql; + struct ndis_packet_oob_data *oob_data; + + ENTER3("nmb = %p, rx_ctx = %p, buf = %p, size = %d, buf = %p, " + "size = %d, packet = %d", nmb, rx_ctx, header, header_size, + look_ahead, look_ahead_size, packet_size); + + wnd = nmb->wnd; + TRACE3("wnd = %p", wnd); + if (!wnd) { + ERROR("nmb is NULL"); + EXIT3(return); + } + wnd->net_dev->last_rx = jiffies; + + if (look_ahead_size < packet_size) { + struct ndis_packet *packet; + struct miniport *mp; + unsigned int bytes_txed; + NDIS_STATUS res; + + NdisAllocatePacket(&res, &packet, wnd->tx_packet_pool); + if (res != NDIS_STATUS_SUCCESS) { + atomic_inc_var(wnd->net_stats.rx_dropped); + EXIT3(return); + } + oob_data = NDIS_PACKET_OOB_DATA(packet); + mp = &wnd->wd->driver->ndis_driver->mp; + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + res = LIN2WIN6(mp->tx_data, packet, &bytes_txed, nmb, + rx_ctx, look_ahead_size, packet_size); + serialize_unlock_irql(wnd, irql); + TRACE3("%d, %d, %d", header_size, look_ahead_size, bytes_txed); + if (res == NDIS_STATUS_SUCCESS) { + ndis_buffer *buffer; + struct ndis_tcp_ip_checksum_packet_info csum; + skb = dev_alloc_skb(header_size + look_ahead_size + + bytes_txed); + if (!skb) { + ERROR("couldn't allocate skb; packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + NdisFreePacket(packet); + return; + } + memcpy_skb(skb, header, header_size); + memcpy_skb(skb, look_ahead, look_ahead_size); + buffer = packet->private.buffer_head; + while (buffer) { + memcpy_skb(skb, + MmGetSystemAddressForMdl(buffer), + MmGetMdlByteCount(buffer)); + buffer = buffer->next; + } + skb_size = header_size + look_ahead_size + bytes_txed; + csum.value = (typeof(csum.value))(ULONG_PTR) + oob_data->ext.info[TcpIpChecksumPacketInfo]; + TRACE3("0x%05x", csum.value); + if (wnd->rx_csum.value && + (csum.rx.tcp_succeeded || csum.rx.udp_succeeded)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + NdisFreePacket(packet); + } else if (res == NDIS_STATUS_PENDING) { + /* driver will call td_complete */ + oob_data->look_ahead = kmalloc(look_ahead_size, + GFP_ATOMIC); + if (!oob_data->look_ahead) { + NdisFreePacket(packet); + ERROR("packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + EXIT3(return); + } + assert(sizeof(oob_data->header) == header_size); + memcpy(oob_data->header, header, + sizeof(oob_data->header)); + memcpy(oob_data->look_ahead, look_ahead, + look_ahead_size); + oob_data->look_ahead_size = look_ahead_size; + EXIT3(return); + } else { + WARNING("packet dropped: %08X", res); + atomic_inc_var(wnd->net_stats.rx_dropped); + NdisFreePacket(packet); + EXIT3(return); + } + } else { + skb_size = header_size + packet_size; + skb = dev_alloc_skb(skb_size); + if (skb) { + memcpy_skb(skb, header, header_size); + memcpy_skb(skb, look_ahead, packet_size); + } + } + + if (skb) { + skb->dev = wnd->net_dev; + skb->protocol = eth_type_trans(skb, wnd->net_dev); + pre_atomic_add(wnd->net_stats.rx_bytes, skb_size); + atomic_inc_var(wnd->net_stats.rx_packets); + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + } + + EXIT3(return); +} + +/* called via function pointer */ +wstdcall void NdisMTransferDataComplete(struct ndis_mp_block *nmb, + struct ndis_packet *packet, + NDIS_STATUS status, UINT bytes_txed) +{ + struct ndis_device *wnd = nmb->wnd; + struct sk_buff *skb; + unsigned int skb_size; + struct ndis_packet_oob_data *oob_data; + ndis_buffer *buffer; + struct ndis_tcp_ip_checksum_packet_info csum; + + ENTER3("wnd = %p, packet = %p, bytes_txed = %d", + wnd, packet, bytes_txed); + if (!packet) { + WARNING("illegal packet"); + EXIT3(return); + } + wnd->net_dev->last_rx = jiffies; + oob_data = NDIS_PACKET_OOB_DATA(packet); + skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size + + bytes_txed; + skb = dev_alloc_skb(skb_size); + if (!skb) { + kfree(oob_data->look_ahead); + NdisFreePacket(packet); + ERROR("couldn't allocate skb; packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + EXIT3(return); + } + memcpy_skb(skb, oob_data->header, sizeof(oob_data->header)); + memcpy_skb(skb, oob_data->look_ahead, oob_data->look_ahead_size); + buffer = packet->private.buffer_head; + while (buffer) { + memcpy_skb(skb, MmGetSystemAddressForMdl(buffer), + MmGetMdlByteCount(buffer)); + buffer = buffer->next; + } + kfree(oob_data->look_ahead); + NdisFreePacket(packet); + skb->dev = wnd->net_dev; + skb->protocol = eth_type_trans(skb, wnd->net_dev); + pre_atomic_add(wnd->net_stats.rx_bytes, skb_size); + atomic_inc_var(wnd->net_stats.rx_packets); + + csum.value = (typeof(csum.value))(ULONG_PTR) + oob_data->ext.info[TcpIpChecksumPacketInfo]; + TRACE3("0x%05x", csum.value); + if (wnd->rx_csum.value && + (csum.rx.tcp_succeeded || csum.rx.udp_succeeded)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); +} + +/* called via function pointer */ +wstdcall void EthRxComplete(struct ndis_mp_block *nmb) +{ + TRACE3(""); +} + +/* called via function pointer */ +wstdcall void NdisMQueryInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER2("nmb: %p, wnd: %p, %08X", nmb, wnd, status); + wnd->ndis_req_status = status; + wnd->ndis_req_done = 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT2(return); +} + +/* called via function pointer */ +wstdcall void NdisMSetInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER2("status = %08X", status); + wnd->ndis_req_status = status; + wnd->ndis_req_done = 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT2(return); +} + +/* called via function pointer */ +wstdcall void NdisMResetComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status, BOOLEAN address_reset) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER2("status: %08X, %u", status, address_reset); + wnd->ndis_req_status = status; + wnd->ndis_req_done = address_reset + 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisMSleep,1) + (ULONG us) +{ + unsigned long delay; + + ENTER4("%p: us: %u", current, us); + delay = USEC_TO_HZ(us); + sleep_hz(delay); + TRACE4("%p: done", current); +} + +wstdcall void WIN_FUNC(NdisGetCurrentSystemTime,1) + (LARGE_INTEGER *time) +{ + *time = ticks_1601(); + TRACE5("%Lu, %lu", *time, jiffies); +} + +wstdcall LONG WIN_FUNC(NdisInterlockedDecrement,1) + (LONG *val) +{ + return InterlockedDecrement(val); +} + +wstdcall LONG WIN_FUNC(NdisInterlockedIncrement,1) + (LONG *val) +{ + return InterlockedIncrement(val); +} + +wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertHeadList,3) + (struct nt_list *head, struct nt_list *entry, + struct ndis_spinlock *lock) +{ + return ExInterlockedInsertHeadList(head, entry, &lock->klock); +} + +wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertTailList,3) + (struct nt_list *head, struct nt_list *entry, + struct ndis_spinlock *lock) +{ + return ExInterlockedInsertTailList(head, entry, &lock->klock); +} + +wstdcall struct nt_list *WIN_FUNC(NdisInterlockedRemoveHeadList,2) + (struct nt_list *head, struct ndis_spinlock *lock) +{ + return ExInterlockedRemoveHeadList(head, &lock->klock); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMInitializeScatterGatherDma,3) + (struct ndis_mp_block *nmb, BOOLEAN dma_size, ULONG max_phy_map) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER2("dma_size=%d, maxtransfer=%u", dma_size, max_phy_map); +#ifdef CONFIG_X86_64 + if (dma_size != NDIS_DMA_64BITS) { + TRACE1("DMA size is not 64-bits"); + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_32BIT_MASK) || + pci_set_consistent_dma_mask(wnd->wd->pci.pdev, + DMA_32BIT_MASK)) + WARNING("setting dma mask failed"); + } +#endif + if ((wnd->attributes & NDIS_ATTRIBUTE_BUS_MASTER) && + wrap_is_pci_bus(wnd->wd->dev_bus)) { + wnd->sg_dma_size = max_phy_map; + return NDIS_STATUS_SUCCESS; + } else + EXIT1(return NDIS_STATUS_NOT_SUPPORTED); +} + +wstdcall ULONG WIN_FUNC(NdisMGetDmaAlignment,1) + (struct ndis_mp_block *nmb) +{ + ENTER3(""); + return dma_get_cache_alignment(); +} + +wstdcall CHAR WIN_FUNC(NdisSystemProcessorCount,0) + (void) +{ + return NR_CPUS; +} + +wstdcall void WIN_FUNC(NdisGetCurrentProcessorCounts,3) + (ULONG *idle, ULONG *kernel_user, ULONG *index) +{ + int cpu = smp_processor_id(); + *idle = kstat_cpu(cpu).cpustat.idle; + *kernel_user = kstat_cpu(cpu).cpustat.system + + kstat_cpu(cpu).cpustat.user; + *index = cpu; +} + +wstdcall void WIN_FUNC(NdisInitializeEvent,1) + (struct ndis_event *ndis_event) +{ + EVENTENTER("%p", ndis_event); + KeInitializeEvent(&ndis_event->nt_event, NotificationEvent, 0); +} + +wstdcall BOOLEAN WIN_FUNC(NdisWaitEvent,2) + (struct ndis_event *ndis_event, UINT ms) +{ + LARGE_INTEGER ticks; + NTSTATUS res; + + EVENTENTER("%p %u", ndis_event, ms); + ticks = -((LARGE_INTEGER)ms * TICKSPERMSEC); + res = KeWaitForSingleObject(&ndis_event->nt_event, 0, 0, TRUE, + ms == 0 ? NULL : &ticks); + if (res == STATUS_SUCCESS) + EXIT3(return TRUE); + else + EXIT3(return FALSE); +} + +wstdcall void WIN_FUNC(NdisSetEvent,1) + (struct ndis_event *ndis_event) +{ + EVENTENTER("%p", ndis_event); + KeSetEvent(&ndis_event->nt_event, 0, 0); +} + +wstdcall void WIN_FUNC(NdisResetEvent,1) + (struct ndis_event *ndis_event) +{ + EVENTENTER("%p", ndis_event); + KeResetEvent(&ndis_event->nt_event); +} + +static void ndis_worker(worker_param_t dummy) +{ + struct nt_list *ent; + struct ndis_work_item *ndis_work_item; + + WORKENTER(""); + while (1) { + spin_lock_bh(&ndis_work_list_lock); + ent = RemoveHeadList(&ndis_work_list); + spin_unlock_bh(&ndis_work_list_lock); + if (!ent) + break; + ndis_work_item = container_of(ent, struct ndis_work_item, list); + WORKTRACE("%p: %p, %p", ndis_work_item, + ndis_work_item->func, ndis_work_item->ctx); + LIN2WIN2(ndis_work_item->func, ndis_work_item, + ndis_work_item->ctx); + WORKTRACE("%p done", ndis_work_item); + } + WORKEXIT(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisScheduleWorkItem,1) + (struct ndis_work_item *ndis_work_item) +{ + ENTER3("%p", ndis_work_item); + spin_lock_bh(&ndis_work_list_lock); + InsertTailList(&ndis_work_list, &ndis_work_item->list); + spin_unlock_bh(&ndis_work_list_lock); + WORKTRACE("scheduling %p", ndis_work_item); + schedule_ndis_work(&ndis_work); + EXIT3(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMGetDeviceProperty,6) + (struct ndis_mp_block *nmb, void **phy_dev, void **func_dev, + void **next_dev, void **alloc_res, void**trans_res) +{ + ENTER2("nmb: %p, phy_dev = %p, func_dev = %p, next_dev = %p, " + "alloc_res = %p, trans_res = %p", nmb, phy_dev, func_dev, + next_dev, alloc_res, trans_res); + if (phy_dev) + *phy_dev = nmb->pdo; + if (func_dev) + *func_dev = nmb->fdo; + if (next_dev) + *next_dev = nmb->next_device; +} + +wstdcall void WIN_FUNC(NdisMRegisterUnloadHandler,2) + (struct driver_object *drv_obj, void *unload) +{ + if (drv_obj) + drv_obj->unload = unload; + return; +} + +wstdcall UINT WIN_FUNC(NdisGetVersion,0) + (void) +{ + return 0x00050001; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMQueryAdapterInstanceName,2) + (struct unicode_string *name, struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + struct ansi_string ansi; + + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + RtlInitAnsiString(&ansi, "PCI Ethernet Adapter"); + else + RtlInitAnsiString(&ansi, "USB Ethernet Adapter"); + + if (RtlAnsiStringToUnicodeString(name, &ansi, TRUE)) + EXIT2(return NDIS_STATUS_RESOURCES); + else + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisWriteEventLogEntry,7) + (void *handle, NDIS_STATUS code, ULONG value, USHORT n, + void *strings, ULONG datasize, void *data) +{ + TRACE1("0x%x, 0x%x, %u, %u", code, value, n, datasize); + return NDIS_STATUS_SUCCESS; +} + +wstdcall void *WIN_FUNC(NdisGetRoutineAddress,1) + (struct unicode_string *unicode_string) +{ + struct ansi_string ansi_string; + void *address; + + if (RtlUnicodeStringToAnsiString(&ansi_string, unicode_string, TRUE) != + STATUS_SUCCESS) + EXIT1(return NULL); + INFO("%s", ansi_string.buf); + address = ndis_get_routine_address(ansi_string.buf); + RtlFreeAnsiString(&ansi_string); + return address; +} + +wstdcall ULONG WIN_FUNC(NdisReadPcmciaAttributeMemory,4) + (struct ndis_mp_block *nmb, ULONG offset, void *buffer, + ULONG length) +{ + TODO(); + return 0; +} + +wstdcall ULONG WIN_FUNC(NdisWritePcmciaAttributeMemory,4) + (struct ndis_mp_block *nmb, ULONG offset, void *buffer, + ULONG length) +{ + TODO(); + return 0; +} + +wstdcall void WIN_FUNC(NdisMCoIndicateReceivePacket,3) + (struct ndis_mp_block *nmb, struct ndis_packet **packets, + UINT nr_packets) +{ + ENTER3("nmb = %p", nmb); + NdisMIndicateReceivePacket(nmb, packets, nr_packets); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisMCoSendComplete,3) + (NDIS_STATUS status, struct ndis_mp_block *nmb, + struct ndis_packet *packet) +{ + ENTER3("%08x", status); + NdisMSendComplete(nmb, packet, status); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisMCoRequestComplete,3) + (NDIS_STATUS status, struct ndis_mp_block *nmb, + struct ndis_request *ndis_request) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER3("%08X", status); + wnd->ndis_req_status = status; + wnd->ndis_req_done = 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT3(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisIMNotifiyPnPEvent,2) + (struct ndis_mp_block *nmb, struct net_pnp_event *event) +{ + ENTER2("%p, %d", nmb, event->code); + /* NdisWrapper never calls protocol's pnp event notifier, so + * nothing to do here */ + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisCompletePnPEvent,2) + (NDIS_STATUS status, void *handle, struct net_pnp_event *event) +{ + ENTER2("%d, %p, %d", status, handle, event->code); + /* NdisWrapper never calls protocol's pnp event notifier, so + * nothing to do here */ + EXIT2(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMSetMiniportSecondary,2) + (struct ndis_mp_block *nmb2, struct ndis_mp_block *nmb1) +{ + ENTER3("%p, %p", nmb1, nmb2); + TODO(); + EXIT3(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMPromoteMiniport,1) + (struct ndis_mp_block *nmb) +{ + ENTER3("%p", nmb); + TODO(); + EXIT3(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMCoActivateVcComplete,3) + (NDIS_STATUS status, void *handle, void *params) +{ + TODO(); +} + +wstdcall void WIN_FUNC(NdisMCoDeactivateVcComplete,2) + (NDIS_STATUS status, void *handle) +{ + TODO(); +} + +wstdcall void WIN_FUNC(NdisMRemoveMiniport,1) + (void *handle) +{ + TODO(); +} + +static void *ndis_get_routine_address(char *name) +{ + int i; + ENTER2("%p", name); + for (i = 0; i < sizeof(ndis_exports) / sizeof(ndis_exports[0]); i++) { + if (strcmp(name, ndis_exports[i].name) == 0) { + TRACE2("%p", ndis_exports[i].func); + return ndis_exports[i].func; + } + } + EXIT2(return NULL); +} + +/* ndis_init_device is called for each device */ +int ndis_init_device(struct ndis_device *wnd) +{ + struct ndis_mp_block *nmb = wnd->nmb; + + KeInitializeSpinLock(&nmb->lock); + wnd->mp_interrupt = NULL; + wnd->wrap_timer_slist.next = NULL; + if (wnd->wd->driver->ndis_driver) + wnd->wd->driver->ndis_driver->mp.shutdown = NULL; + + nmb->filterdbs.eth_db = nmb; + nmb->filterdbs.tr_db = nmb; + nmb->filterdbs.fddi_db = nmb; + nmb->filterdbs.arc_db = nmb; + + nmb->rx_packet = WIN_FUNC_PTR(NdisMIndicateReceivePacket,3); + nmb->send_complete = WIN_FUNC_PTR(NdisMSendComplete,3); + nmb->send_resource_avail = WIN_FUNC_PTR(NdisMSendResourcesAvailable,1); + nmb->status = WIN_FUNC_PTR(NdisMIndicateStatus,4); + nmb->status_complete = WIN_FUNC_PTR(NdisMIndicateStatusComplete,1); + nmb->queryinfo_complete = WIN_FUNC_PTR(NdisMQueryInformationComplete,2); + nmb->setinfo_complete = WIN_FUNC_PTR(NdisMSetInformationComplete,2); + nmb->reset_complete = WIN_FUNC_PTR(NdisMResetComplete,3); + nmb->eth_rx_indicate = WIN_FUNC_PTR(EthRxIndicateHandler,8); + nmb->eth_rx_complete = WIN_FUNC_PTR(EthRxComplete,1); + nmb->td_complete = WIN_FUNC_PTR(NdisMTransferDataComplete,4); + return 0; +} + +/* ndis_exit_device is called for each device */ +void ndis_exit_device(struct ndis_device *wnd) +{ + struct wrap_device_setting *setting; + ENTER2("%p", wnd); + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_entry(setting, &wnd->wd->settings, list) { + struct ndis_configuration_parameter *param; + param = setting->encoded; + if (param) { + if (param->type == NdisParameterString) + RtlFreeUnicodeString(¶m->data.string); + ExFreePool(param); + setting->encoded = NULL; + } + } + up(&loader_mutex); +} + +/* ndis_init is called once when module is loaded */ +int ndis_init(void) +{ + InitializeListHead(&ndis_work_list); + spin_lock_init(&ndis_work_list_lock); + initialize_work(&ndis_work, ndis_worker, NULL); + + ndis_wq = create_singlethread_workqueue("ndis_wq"); + if (!ndis_wq) { + WARNING("couldn't create worker thread"); + EXIT1(return -ENOMEM); + } + + ndis_worker_thread = wrap_worker_init(ndis_wq); + TRACE1("%p", ndis_worker_thread); + return 0; +} + +/* ndis_exit is called once when module is removed */ +void ndis_exit(void) +{ + ENTER1(""); + if (ndis_wq) + destroy_workqueue(ndis_wq); + TRACE1("%p", ndis_worker_thread); + if (ndis_worker_thread) + ObDereferenceObject(ndis_worker_thread); + EXIT1(return); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/wrapmem.h +++ linux-2.6.27/ubuntu/ndiswrapper/wrapmem.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2006 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _WRAPMEM_H_ + +/* set ALLOC_DEBUG to 1 to get information about memory used by both + * ndiswrapper and Windows driver by reading + * /proc/net/ndiswrapper/debug; this will also show memory leaks + * (memory allocated but not freed) when ndiswrapper module is + * unloaded. + + * ALLOC_DEBUG=2: details about individual allocations leaking is printed + * ALLOC_DEBUG=3: tags in ExAllocatePoolWithTag leaking printed +*/ + +//#ifndef ALLOC_DEBUG +//#define ALLOC_DEBUG 1 +//#endif + +enum alloc_type { ALLOC_TYPE_KMALLOC_ATOMIC, ALLOC_TYPE_KMALLOC_NON_ATOMIC, + ALLOC_TYPE_VMALLOC_ATOMIC, ALLOC_TYPE_VMALLOC_NON_ATOMIC, + ALLOC_TYPE_SLACK, ALLOC_TYPE_PAGES, ALLOC_TYPE_MAX }; + +int wrapmem_init(void); +void wrapmem_exit(void); +void *slack_kmalloc(size_t size); +void slack_kfree(void *ptr); +void wrapmem_info(void); + +#ifdef ALLOC_DEBUG +void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line); +void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line); +void wrap_kfree(void *ptr); +void *wrap_vmalloc(unsigned long size, const char *file, int line); +void *wrap__vmalloc(unsigned long size, gfp_t flags, pgprot_t prot, + const char *file, int line); +void wrap_vfree(void *ptr); +void *wrap_alloc_pages(gfp_t flags, unsigned int size, + const char *file, int line); +void wrap_free_pages(unsigned long ptr, int order); +int alloc_size(enum alloc_type type); + +#ifndef _WRAPMEM_C_ +#undef kmalloc +#undef kzalloc +#undef kfree +#undef vmalloc +#undef __vmalloc +#undef vfree +#define kmalloc(size, flags) \ + wrap_kmalloc(size, flags, __FILE__, __LINE__) +#define kzalloc(size, flags) \ + wrap_kzalloc(size, flags, __FILE__, __LINE__) +#define vmalloc(size) \ + wrap_vmalloc(size, __FILE__, __LINE__) +#define __vmalloc(size, flags, prot) \ + wrap__vmalloc(size, flags, prot, __FILE__, __LINE__) +#define kfree(ptr) wrap_kfree(ptr) +#define vfree(ptr) wrap_vfree(ptr) + +#define wrap_get_free_pages(flags, size) \ + wrap_alloc_pages(flags, size, __FILE__, __LINE__) +#undef free_pages +#define free_pages(ptr, order) wrap_free_pages(ptr, order) + +#if ALLOC_DEBUG > 1 +void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size, + ULONG tag, const char *file, int line); +#define ExAllocatePoolWithTag(pool_type, size, tag) \ + wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__) +#endif + +#endif // _WRAPMEM_C_ + +#else + +#define wrap_get_free_pages(flags, size) \ + (void *)__get_free_pages(flags, get_order(size)) + +#endif // ALLOC_DEBUG + +#endif --- linux-2.6.27.orig/ubuntu/ndiswrapper/winnt_types.h +++ linux-2.6.27/ubuntu/ndiswrapper/winnt_types.h @@ -0,0 +1,1702 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _WINNT_TYPES_H_ +#define _WINNT_TYPES_H_ + +#define TRUE 1 +#define FALSE 0 + +#define PASSIVE_LEVEL 0 +#define APC_LEVEL 1 +#define DISPATCH_LEVEL 2 +#define DEVICE_LEVEL_BASE 4 + +/* soft interrupts / bottom-half's are disabled at SOFT_IRQL */ +#define SOFT_IRQL (DEVICE_LEVEL_BASE + 1) +#define DIRQL (DEVICE_LEVEL_BASE + 2) + +#define STATUS_WAIT_0 0 +#define STATUS_SUCCESS 0 +#define STATUS_ALERTED 0x00000101 +#define STATUS_TIMEOUT 0x00000102 +#define STATUS_PENDING 0x00000103 +#define STATUS_FAILURE 0xC0000001 +#define STATUS_NOT_IMPLEMENTED 0xC0000002 +#define STATUS_INVALID_PARAMETER 0xC000000D +#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 +#define STATUS_ACCESS_DENIED 0xC0000022 +#define STATUS_BUFFER_TOO_SMALL 0xC0000023 +#define STATUS_OBJECT_NAME_INVALID 0xC0000023 +#define STATUS_MUTANT_NOT_OWNED 0xC0000046 +#define STATUS_RESOURCES 0xC000009A +#define STATUS_DELETE_PENDING 0xC0000056 +#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A +#define STATUS_NOT_SUPPORTED 0xC00000BB +#define STATUS_INVALID_PARAMETER_2 0xC00000F0 +#define STATUS_NO_MEMORY 0xC0000017 +#define STATUS_CANCELLED 0xC0000120 +#define STATUS_DEVICE_REMOVED 0xC00002B6 +#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D + +#define STATUS_BUFFER_OVERFLOW 0x80000005 + +#define SL_PENDING_RETURNED 0x01 +#define SL_INVOKE_ON_CANCEL 0x20 +#define SL_INVOKE_ON_SUCCESS 0x40 +#define SL_INVOKE_ON_ERROR 0x80 + +#define IRP_MJ_CREATE 0x00 +#define IRP_MJ_CREATE_NAMED_PIPE 0x01 +#define IRP_MJ_CLOSE 0x02 +#define IRP_MJ_READ 0x03 +#define IRP_MJ_WRITE 0x04 + +#define IRP_MJ_DEVICE_CONTROL 0x0E +#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0F +#define IRP_MJ_POWER 0x16 +#define IRP_MJ_SYSTEM_CONTROL 0x0E +#define IRP_MJ_PNP 0x1b +#define IRP_MJ_MAXIMUM_FUNCTION 0x1b + +#define IRP_MN_WAIT_WAKE 0x00 +#define IRP_MN_POWER_SEQUENCE 0x01 +#define IRP_MN_SET_POWER 0x02 +#define IRP_MN_QUERY_POWER 0x03 + +#define IRP_MN_REGINFO 0x08 +#define IRP_MN_REGINFO_EX 0x0b + +#define IRP_MN_START_DEVICE 0x00 +#define IRP_MN_QUERY_REMOVE_DEVICE 0x01 +#define IRP_MN_REMOVE_DEVICE 0x02 +#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03 +#define IRP_MN_STOP_DEVICE 0x04 +#define IRP_MN_QUERY_STOP_DEVICE 0x05 +#define IRP_MN_CANCEL_STOP_DEVICE 0x06 +#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07 +#define IRP_MN_QUERY_INTERFACE 0x08 + +#define IRP_BUFFERED_IO 0x00000010 +#define IRP_DEALLOCATE_BUFFER 0x00000020 +#define IRP_INPUT_OPERATION 0x00000040 + +#define IRP_DEFFER_IO_COMPLETION 0x00000800 + +#define THREAD_WAIT_OBJECTS 3 +#define MAX_WAIT_OBJECTS 64 + +#define LOW_PRIORITY 0 +#define LOW_REALTIME_PRIORITY 16 +#define HIGH_PRIORITY 31 +#define MAXIMUM_PRIORITY 32 + +#define PROCESSOR_FEATURE_MAX 64 + +#define IO_NO_INCREMENT 0 + +#define WMIREG_ACTION_REGISTER 1 +#define WMIREG_ACTION_DEREGISTER 2 +#define WMIREG_ACTION_REREGISTER 3 +#define WMIREG_ACTION_UPDATE_GUIDS 4 + +#define WMIREGISTER 0 +#define WMIUPDATE 1 + +#ifdef CONFIG_X86_64 +#define wstdcall +#define wfastcall +#define noregparm + +#define KI_USER_SHARED_DATA 0xfffff78000000000UL + +#else + +#define noregparm __attribute__((regparm(0))) +#define wstdcall __attribute__((__stdcall__, regparm(0))) +#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ > 3) || __GNUC__ > 3) +#undef fastcall +#define wfastcall __attribute__((fastcall)) +#else +#error "gcc 3.4 or newer should be used for compiling this module" +#endif + +#define KI_USER_SHARED_DATA 0xffdf0000 + +#endif + +#define packed __attribute__((packed)) +#define no_warn_unused __attribute__((unused)) + +typedef u8 BOOLEAN; +typedef u8 BYTE; +typedef u8 *LPBYTE; +typedef s8 CHAR; +typedef u8 UCHAR; +typedef s16 SHORT; +typedef u16 USHORT; +typedef u16 WORD; +typedef s32 INT; +typedef u32 UINT; +typedef u32 DWORD; +typedef s32 LONG; +typedef u32 ULONG; +typedef s64 LONGLONG; +typedef u64 ULONGLONG; +typedef u64 ULONGULONG; +typedef u64 ULONG64; + +typedef CHAR CCHAR; +typedef USHORT wchar_t; +typedef SHORT CSHORT; +typedef LONGLONG LARGE_INTEGER; + +typedef LONG NTSTATUS; + +typedef LONG KPRIORITY; +typedef LARGE_INTEGER PHYSICAL_ADDRESS; +typedef UCHAR KIRQL; +typedef CHAR KPROCESSOR_MODE; + +/* ULONG_PTR is 32 bits on 32-bit platforms and 64 bits on 64-bit + * platform, which is same as 'unsigned long' in Linux */ +typedef unsigned long ULONG_PTR; + +typedef ULONG_PTR SIZE_T; +typedef ULONG_PTR KAFFINITY; +typedef ULONG ACCESS_MASK; + +typedef ULONG_PTR PFN_NUMBER; +typedef ULONG SECURITY_INFORMATION; + +/* non-negative numbers indicate success */ +#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0) + +struct ansi_string { + USHORT length; + USHORT max_length; + char *buf; +}; + +struct unicode_string { + USHORT length; + USHORT max_length; + wchar_t *buf; +}; + +struct nt_slist { + struct nt_slist *next; +}; + +#ifdef CONFIG_X86_64 +/* it is not clear how nt_slist_head is used to store pointer to + * slists and depth; here we assume 'align' field is used to store + * depth and 'region' field is used to store slist pointers */ +struct nt_slist_head { + union { + USHORT depth; + ULONGLONG align; + }; + union { + ULONGLONG region; + struct nt_slist *next; + }; +} __attribute__((aligned(16))); +typedef struct nt_slist_head nt_slist_header; +#else +union nt_slist_head { + ULONGLONG align; + struct { + struct nt_slist *next; + USHORT depth; + USHORT sequence; + }; +}; +typedef union nt_slist_head nt_slist_header; +#endif + +struct nt_list { + struct nt_list *next; + struct nt_list *prev; +}; + +typedef ULONG_PTR NT_SPIN_LOCK; + +enum kdpc_importance {LowImportance, MediumImportance, HighImportance}; + +struct kdpc; +typedef void (*DPC)(struct kdpc *kdpc, void *ctx, void *arg1, + void *arg2) wstdcall; +struct kdpc { + SHORT type; + UCHAR nr_cpu; + UCHAR importance; + struct nt_list list; + DPC func; + void *ctx; + void *arg1; + void *arg2; + union { + NT_SPIN_LOCK *lock; + /* 'lock' is not used; 'queued' represents whether + * kdpc is queued or not */ + int queued; + }; +}; + +enum pool_type { + NonPagedPool, PagedPool, NonPagedPoolMustSucceed, DontUseThisType, + NonPagedPoolCacheAligned, PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS, MaxPoolType, + NonPagedPoolSession = 32, + PagedPoolSession = NonPagedPoolSession + 1, + NonPagedPoolMustSucceedSession = PagedPoolSession + 1, + DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1, + NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1, + PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1, + NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1 +}; + +enum memory_caching_type_orig { + MmFrameBufferCached = 2 +}; + +enum memory_caching_type { + MmNonCached = FALSE, MmCached = TRUE, + MmWriteCombined = MmFrameBufferCached, MmHardwareCoherentCached, + MmNonCachedUnordered, MmUSWCCached, MmMaximumCacheType +}; + +enum lock_operation { + IoReadAccess, IoWriteAccess, IoModifyAccess +}; + +enum mode { + KernelMode, UserMode, MaximumMode +}; + +struct mdl { + struct mdl *next; + CSHORT size; + CSHORT flags; + /* NdisFreeBuffer doesn't pass pool, so we store pool in + * unused field 'process' */ + union { + void *process; + void *pool; + }; + void *mappedsystemva; + void *startva; + ULONG bytecount; + ULONG byteoffset; +}; + +#define MDL_MAPPED_TO_SYSTEM_VA 0x0001 +#define MDL_PAGES_LOCKED 0x0002 +#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004 +#define MDL_ALLOCATED_FIXED_SIZE 0x0008 +#define MDL_PARTIAL 0x0010 +#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020 +#define MDL_IO_PAGE_READ 0x0040 +#define MDL_WRITE_OPERATION 0x0080 +#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100 +#define MDL_FREE_EXTRA_PTES 0x0200 +#define MDL_IO_SPACE 0x0800 +#define MDL_NETWORK_HEADER 0x1000 +#define MDL_MAPPING_CAN_FAIL 0x2000 +#define MDL_ALLOCATED_MUST_SUCCEED 0x4000 + +#define MDL_POOL_ALLOCATED 0x0400 +#define MDL_CACHE_ALLOCATED 0x8000 + +#define PAGE_START(ptr) ((void *)((ULONG_PTR)(ptr) & ~(PAGE_SIZE - 1))) +#define BYTE_OFFSET(ptr) ((ULONG)((ULONG_PTR)(ptr) & (PAGE_SIZE - 1))) + +#define MmGetMdlByteCount(mdl) ((mdl)->bytecount) +#define MmGetMdlVirtualAddress(mdl) ((mdl)->startva + (mdl)->byteoffset) +#define MmGetMdlByteOffset(mdl) ((mdl)->byteoffset) +#define MmGetSystemAddressForMdl(mdl) ((mdl)->mappedsystemva) +#define MmGetSystemAddressForMdlSafe(mdl, priority) ((mdl)->mappedsystemva) +#define MmGetMdlPfnArray(mdl) ((PFN_NUMBER *)(mdl + 1)) +#define MmInitializeMdl(mdl, baseva, length) \ +do { \ + (mdl)->next = NULL; \ + (mdl)->size = MmSizeOfMdl(baseva, length); \ + (mdl)->flags = 0; \ + (mdl)->startva = PAGE_START(baseva); \ + (mdl)->byteoffset = BYTE_OFFSET(baseva); \ + (mdl)->bytecount = length; \ + (mdl)->mappedsystemva = baseva; \ + TRACE4("%p %p %p %d %d", (mdl), baseva, (mdl)->startva, \ + (mdl)->byteoffset, length); \ +} while (0) + +struct kdevice_queue_entry { + struct nt_list list; + ULONG sort_key; + BOOLEAN inserted; +}; + +struct kdevice_queue { + USHORT type; + USHORT size; + struct nt_list list; + NT_SPIN_LOCK lock; + BOOLEAN busy; +}; + +struct wait_context_block { + struct kdevice_queue_entry wait_queue_entry; + void *device_routine; + void *device_context; + ULONG num_regs; + void *device_object; + void *current_irp; + void *buffer_chaining_dpc; +}; + +struct wait_block { + struct nt_list list; + struct task_struct *thread; + void *object; + int *wait_done; + USHORT wait_key; + USHORT wait_type; +}; + +struct dispatcher_header { + UCHAR type; + UCHAR absolute; + UCHAR size; + UCHAR inserted; + LONG signal_state; + struct nt_list wait_blocks; +}; + +enum event_type { + NotificationEvent, + SynchronizationEvent, +}; + +enum timer_type { + NotificationTimer = NotificationEvent, + SynchronizationTimer = SynchronizationEvent, +}; + +enum dh_type { + NotificationObject = NotificationEvent, + SynchronizationObject = SynchronizationEvent, + MutexObject, + SemaphoreObject, + ThreadObject, +}; + +enum wait_type { + WaitAll, WaitAny +}; + +/* objects that use dispatcher_header have it as the first field, so + * whenever we need to initialize dispatcher_header, we can convert + * that object into a nt_event and access dispatcher_header */ +struct nt_event { + struct dispatcher_header dh; +}; + +struct wrap_timer; + +#define WRAP_TIMER_MAGIC 47697249 + +struct nt_timer { + struct dispatcher_header dh; + /* We can't fit Linux timer in this structure. Instead of + * padding the nt_timer structure, we replace due_time field + * with *wrap_timer and allocate memory for it when nt_timer is + * initialized */ + union { + ULONGLONG due_time; + struct wrap_timer *wrap_timer; + }; + struct nt_list nt_timer_list; + struct kdpc *kdpc; + union { + LONG period; + LONG wrap_timer_magic; + }; +}; + +struct nt_mutex { + struct dispatcher_header dh; + struct nt_list list; + struct task_struct *owner_thread; + BOOLEAN abandoned; + BOOLEAN apc_disable; +}; + +struct nt_semaphore { + struct dispatcher_header dh; + LONG limit; +}; + +struct nt_thread { + struct dispatcher_header dh; + /* the rest in Windows is a long structure; since this + * structure is opaque to drivers, we just define what we + * need */ + int pid; + NTSTATUS status; + struct task_struct *task; + struct nt_list irps; + NT_SPIN_LOCK lock; + KPRIORITY prio; +}; + +#define set_object_type(dh, type) ((dh)->type = (type)) +#define is_notify_object(dh) ((dh)->type == NotificationObject) +#define is_synch_object(dh) ((dh)->type == SynchronizationObject) +#define is_mutex_object(dh) ((dh)->type == MutexObject) +#define is_semaphore_object(dh) ((dh)->type == SemaphoreObject) +#define is_nt_thread_object(dh) ((dh)->type == ThreadObject) + +#define IO_TYPE_ADAPTER 1 +#define IO_TYPE_CONTROLLER 2 +#define IO_TYPE_DEVICE 3 +#define IO_TYPE_DRIVER 4 +#define IO_TYPE_FILE 5 +#define IO_TYPE_IRP 6 +#define IO_TYPE_DEVICE_OBJECT_EXTENSION 13 + +struct irp; +struct dev_obj_ext; +struct driver_object; + +struct device_object { + CSHORT type; + USHORT size; + LONG ref_count; + struct driver_object *drv_obj; + struct device_object *next; + struct device_object *attached; + struct irp *current_irp; + void *io_timer; + ULONG flags; + ULONG characteristics; + void *vpb; + void *dev_ext; + CCHAR stack_count; + union { + struct nt_list queue_list; + struct wait_context_block wcb; + } queue; + ULONG align_req; + struct kdevice_queue dev_queue; + struct kdpc dpc; + ULONG active_threads; + void *security_desc; + struct nt_event lock; + USHORT sector_size; + USHORT spare1; + struct dev_obj_ext *dev_obj_ext; + void *reserved; +}; + +struct dev_obj_ext { + CSHORT type; + CSHORT size; + struct device_object *dev_obj; + struct device_object *attached_to; +}; + +struct io_status_block { + union { + NTSTATUS status; + void *pointer; + }; + ULONG_PTR info; +}; + +#ifdef CONFIG_X86_64 +struct io_status_block32 { + NTSTATUS status; + ULONG info; +}; +#endif + +#define DEVICE_TYPE ULONG + +struct driver_extension; + +typedef NTSTATUS driver_dispatch_t(struct device_object *dev_obj, + struct irp *irp) wstdcall; + +struct driver_object { + CSHORT type; + CSHORT size; + struct device_object *dev_obj; + ULONG flags; + void *start; + ULONG driver_size; + void *section; + struct driver_extension *drv_ext; + struct unicode_string name; + struct unicode_string *hardware_database; + void *fast_io_dispatch; + void *init; + void *start_io; + void (*unload)(struct driver_object *driver) wstdcall; + driver_dispatch_t *major_func[IRP_MJ_MAXIMUM_FUNCTION + 1]; +}; + +struct driver_extension { + struct driver_object *drv_obj; + NTSTATUS (*add_device)(struct driver_object *drv_obj, + struct device_object *dev_obj) wstdcall; + ULONG count; + struct unicode_string service_key_name; + struct nt_list custom_ext; +}; + +struct custom_ext { + struct nt_list list; + void *client_id; +}; + +struct wrap_bin_file; + +struct file_object { + CSHORT type; + CSHORT size; + struct device_object *dev_obj; + void *volume_parameter_block; + void *fs_context; + void *fs_context2; + void *section_object_pointer; + void *private_cache_map; + NTSTATUS final_status; + union { + struct file_object *related_file_object; + struct wrap_bin_file *wrap_bin_file; + }; + BOOLEAN lock_operation; + BOOLEAN delete_pending; + BOOLEAN read_access; + BOOLEAN write_access; + BOOLEAN delete_access; + BOOLEAN shared_read; + BOOLEAN shared_write; + BOOLEAN shared_delete; + ULONG flags; + struct unicode_string _name_; + LARGE_INTEGER current_byte_offset; + ULONG waiters; + ULONG busy; + void *last_lock; + struct nt_event lock; + struct nt_event event; + void *completion_context; +}; + +#ifdef CONFIG_X86_64 +#define POINTER_ALIGN __attribute__((aligned(8))) +#else +#define POINTER_ALIGN +#endif + +#define CACHE_ALIGN __attribute__((aligned(128))) + +enum system_power_state { + PowerSystemUnspecified = 0, + PowerSystemWorking, PowerSystemSleeping1, PowerSystemSleeping2, + PowerSystemSleeping3, PowerSystemHibernate, PowerSystemShutdown, + PowerSystemMaximum, +}; + +enum device_power_state { + PowerDeviceUnspecified = 0, + PowerDeviceD0, PowerDeviceD1, PowerDeviceD2, PowerDeviceD3, + PowerDeviceMaximum, +}; + +union power_state { + enum system_power_state system_state; + enum device_power_state device_state; +}; + +enum power_state_type { + SystemPowerState = 0, DevicePowerState, +}; + +enum power_action { + PowerActionNone = 0, + PowerActionReserved, PowerActionSleep, PowerActionHibernate, + PowerActionShutdown, PowerActionShutdownReset, PowerActionShutdownOff, + PowerActionWarmEject, +}; + +struct guid { + ULONG data1; + USHORT data2; + USHORT data3; + UCHAR data4[8]; +}; + +struct nt_interface { + USHORT size; + USHORT version; + void *context; + void (*reference)(void *context) wstdcall; + void (*dereference)(void *context) wstdcall; +}; + +enum interface_type { + InterfaceTypeUndefined = -1, Internal, Isa, Eisa, MicroChannel, + TurboChannel, PCIBus, VMEBus, NuBus, PCMCIABus, CBus, MPIBus, + MPSABus, ProcessorInternal, InternalPowerBus, PNPISABus, + PNPBus, MaximumInterfaceType, +}; + +#define CmResourceTypeNull 0 +#define CmResourceTypePort 1 +#define CmResourceTypeInterrupt 2 +#define CmResourceTypeMemory 3 +#define CmResourceTypeDma 4 +#define CmResourceTypeDeviceSpecific 5 +#define CmResourceTypeBusNumber 6 +#define CmResourceTypeMaximum 7 + +#define CmResourceTypeNonArbitrated 128 +#define CmResourceTypeConfigData 128 +#define CmResourceTypeDevicePrivate 129 +#define CmResourceTypePcCardConfig 130 +#define CmResourceTypeMfCardConfig 131 + +enum cm_share_disposition { + CmResourceShareUndetermined = 0, CmResourceShareDeviceExclusive, + CmResourceShareDriverExclusive, CmResourceShareShared +}; + +#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0 +#define CM_RESOURCE_INTERRUPT_LATCHED 1 +#define CM_RESOURCE_MEMORY_READ_WRITE 0x0000 +#define CM_RESOURCE_MEMORY_READ_ONLY 0x0001 +#define CM_RESOURCE_MEMORY_WRITE_ONLY 0x0002 +#define CM_RESOURCE_MEMORY_PREFETCHABLE 0x0004 + +#define CM_RESOURCE_MEMORY_COMBINEDWRITE 0x0008 +#define CM_RESOURCE_MEMORY_24 0x0010 +#define CM_RESOURCE_MEMORY_CACHEABLE 0x0020 + +#define CM_RESOURCE_PORT_MEMORY 0x0000 +#define CM_RESOURCE_PORT_IO 0x0001 +#define CM_RESOURCE_PORT_10_BIT_DECODE 0x0004 +#define CM_RESOURCE_PORT_12_BIT_DECODE 0x0008 +#define CM_RESOURCE_PORT_16_BIT_DECODE 0x0010 +#define CM_RESOURCE_PORT_POSITIVE_DECODE 0x0020 +#define CM_RESOURCE_PORT_PASSIVE_DECODE 0x0040 +#define CM_RESOURCE_PORT_WINDOW_DECODE 0x0080 + +#define CM_RESOURCE_DMA_8 0x0000 +#define CM_RESOURCE_DMA_16 0x0001 +#define CM_RESOURCE_DMA_32 0x0002 +#define CM_RESOURCE_DMA_8_AND_16 0x0004 +#define CM_RESOURCE_DMA_BUS_MASTER 0x0008 +#define CM_RESOURCE_DMA_TYPE_A 0x0010 +#define CM_RESOURCE_DMA_TYPE_B 0x0020 +#define CM_RESOURCE_DMA_TYPE_F 0x0040 + +#define MAX_RESOURCES 20 + +#pragma pack(push,4) +struct cm_partial_resource_descriptor { + UCHAR type; + UCHAR share; + USHORT flags; + union { + struct { + PHYSICAL_ADDRESS start; + ULONG length; + } generic; + struct { + PHYSICAL_ADDRESS start; + ULONG length; + } port; + struct { + ULONG level; + ULONG vector; + KAFFINITY affinity; + } interrupt; + struct { + PHYSICAL_ADDRESS start; + ULONG length; + } memory; + struct { + ULONG channel; + ULONG port; + ULONG reserved1; + } dma; + struct { + ULONG data[3]; + } device_private; + struct { + ULONG start; + ULONG length; + ULONG reserved; + } bus_number; + struct { + ULONG data_size; + ULONG reserved1; + ULONG reserved2; + } device_specific_data; + } u; +}; +#pragma pack(pop) + +struct cm_partial_resource_list { + USHORT version; + USHORT revision; + ULONG count; + struct cm_partial_resource_descriptor partial_descriptors[1]; +}; + +struct cm_full_resource_descriptor { + enum interface_type interface_type; + ULONG bus_number; + struct cm_partial_resource_list partial_resource_list; +}; + +struct cm_resource_list { + ULONG count; + struct cm_full_resource_descriptor list[1]; +}; + +enum file_info_class { + FileDirectoryInformation = 1, + FileBasicInformation = 4, + FileStandardInformation = 5, + FileNameInformation = 9, + FilePositionInformation = 14, + FileAlignmentInformation = 17, + FileNetworkOpenInformation = 34, + FileAttributeTagInformation = 35, + FileMaximumInformation = 41, +}; + +enum fs_info_class { + FileFsVolumeInformation = 1, + /* ... */ + FileFsMaximumInformation = 9, +}; + +enum device_relation_type { + BusRelations, EjectionRelations, PowerRelations, RemovalRelations, + TargetDeviceRelation, SingleBusRelations, +}; + +enum bus_query_id_type { + BusQueryDeviceID = 0, BusQueryHardwareIDs = 1, + BusQueryCompatibleIDs = 2, BusQueryInstanceID = 3, + BusQueryDeviceSerialNumber = 4, +}; + +enum device_text_type { + DeviceTextDescription = 0, DeviceTextLocationInformation = 1, +}; + +enum device_usage_notification_type { + DeviceUsageTypeUndefined, DeviceUsageTypePaging, + DeviceUsageTypeHibernation, DevbiceUsageTypeDumpFile, +}; + +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +#define CTL_CODE(dev_type, func, method, access) \ + (((dev_type) << 16) | ((access) << 14) | ((func) << 2) | (method)) + +#define IO_METHOD_FROM_CTL_CODE(code) (code & 0x3) + +#ifndef CONFIG_X86_64 +#pragma pack(push,4) +#endif +struct io_stack_location { + UCHAR major_fn; + UCHAR minor_fn; + UCHAR flags; + UCHAR control; + union { + struct { + void *security_context; + ULONG options; + USHORT POINTER_ALIGN file_attributes; + USHORT share_access; + ULONG POINTER_ALIGN ea_length; + } create; + struct { + ULONG length; + ULONG POINTER_ALIGN key; + LARGE_INTEGER byte_offset; + } read; + struct { + ULONG length; + ULONG POINTER_ALIGN key; + LARGE_INTEGER byte_offset; + } write; + struct { + ULONG length; + enum file_info_class POINTER_ALIGN file_info_class; + } query_file; + struct { + ULONG length; + enum file_info_class POINTER_ALIGN file_info_class; + struct file_object *file_object; + union { + struct { + BOOLEAN replace_if_exists; + BOOLEAN advance_only; + }; + ULONG cluster_count; + void *delete_handle; + }; + } set_file; + struct { + ULONG length; + enum fs_info_class POINTER_ALIGN fs_info_class; + } query_volume; + struct { + ULONG output_buf_len; + ULONG POINTER_ALIGN input_buf_len; + ULONG POINTER_ALIGN code; + void *type3_input_buf; + } dev_ioctl; + struct { + SECURITY_INFORMATION security_info; + ULONG POINTER_ALIGN length; + } query_security; + struct { + SECURITY_INFORMATION security_info; + void *security_descriptor; + } set_security; + struct { + void *vpb; + struct device_object *device_object; + } mount_volume; + struct { + void *vpb; + struct device_object *device_object; + } verify_volume; + struct { + void *srb; + } scsi; + struct { + enum device_relation_type type; + } query_device_relations; + struct { + const struct guid *type; + USHORT size; + USHORT version; + struct nt_interface *intf; + void *intf_data; + } query_intf; + struct { + void *capabilities; + } device_capabilities; + struct { + void *io_resource_requirement_list; + } filter_resource_requirements; + struct { + ULONG which_space; + void *buffer; + ULONG offset; + ULONG POINTER_ALIGN length; + } read_write_config; + struct { + BOOLEAN lock; + } set_lock; + struct { + enum bus_query_id_type id_type; + } query_id; + struct { + enum device_text_type device_text_type; + ULONG POINTER_ALIGN locale_id; + } query_device_text; + struct { + BOOLEAN in_path; + BOOLEAN reserved[3]; + enum device_usage_notification_type POINTER_ALIGN type; + } usage_notification; + struct { + enum system_power_state power_state; + } wait_wake; + struct { + void *power_sequence; + } power_sequence; + struct { + ULONG sys_context; + enum power_state_type POINTER_ALIGN type; + union power_state POINTER_ALIGN state; + enum power_action POINTER_ALIGN shutdown_type; + } power; + struct { + struct cm_resource_list *allocated_resources; + struct cm_resource_list *allocated_resources_translated; + } start_device; + struct { + ULONG_PTR provider_id; + void *data_path; + ULONG buf_len; + void *buf; + } wmi; + struct { + void *arg1; + void *arg2; + void *arg3; + void *arg4; + } others; + } params; + struct device_object *dev_obj; + struct file_object *file_obj; + NTSTATUS (*completion_routine)(struct device_object *, + struct irp *, void *) wstdcall; + void *context; +}; +#ifndef CONFIG_X86_64 +#pragma pack(pop) +#endif + +struct kapc { + CSHORT type; + CSHORT size; + ULONG spare0; + struct nt_thread *thread; + struct nt_list list; + void *kernele_routine; + void *rundown_routine; + void *normal_routine; + void *normal_context; + void *sys_arg1; + void *sys_arg2; + CCHAR apc_state_index; + KPROCESSOR_MODE apc_mode; + BOOLEAN inserted; +}; + +#define IRP_NOCACHE 0x00000001 +#define IRP_SYNCHRONOUS_API 0x00000004 +#define IRP_ASSOCIATED_IRP 0x00000008 + +enum urb_state { + URB_INVALID = 1, URB_ALLOCATED, URB_SUBMITTED, + URB_COMPLETED, URB_FREE, URB_SUSPEND, URB_INT_UNLINKED }; + +struct wrap_urb { + struct nt_list list; + enum urb_state state; + struct nt_list complete_list; + unsigned int flags; + struct urb *urb; + struct irp *irp; +#ifdef USB_DEBUG + unsigned int id; +#endif +}; + +struct irp { + SHORT type; + USHORT size; + struct mdl *mdl; + ULONG flags; + union { + struct irp *master_irp; + LONG irp_count; + void *system_buffer; + } associated_irp; + struct nt_list thread_list; + struct io_status_block io_status; + KPROCESSOR_MODE requestor_mode; + BOOLEAN pending_returned; + CHAR stack_count; + CHAR current_location; + BOOLEAN cancel; + KIRQL cancel_irql; + CCHAR apc_env; + UCHAR alloc_flags; + struct io_status_block *user_status; + struct nt_event *user_event; + union { + struct { + void *user_apc_routine; + void *user_apc_context; + } async_params; + LARGE_INTEGER alloc_size; + } overlay; + void (*cancel_routine)(struct device_object *, struct irp *) wstdcall; + void *user_buf; + union { + struct { + union { + struct kdevice_queue_entry dev_q_entry; + struct { + void *driver_context[4]; + }; + }; + void *thread; + char *aux_buf; + struct { + struct nt_list list; + union { + struct io_stack_location *csl; + ULONG packet_type; + }; + }; + struct file_object *file_object; + } overlay; + union { + struct kapc apc; + /* space for apc is used for ndiswrapper + * specific fields */ + struct { + struct wrap_urb *wrap_urb; + struct wrap_device *wrap_device; + }; + }; + void *completion_key; + } tail; +}; + +#define IoSizeOfIrp(stack_count) \ + ((USHORT)(sizeof(struct irp) + \ + ((stack_count) * sizeof(struct io_stack_location)))) +#define IoGetCurrentIrpStackLocation(irp) \ + (irp)->tail.overlay.csl +#define IoGetNextIrpStackLocation(irp) \ + (IoGetCurrentIrpStackLocation(irp) - 1) +#define IoGetPreviousIrpStackLocation(irp) \ + (IoGetCurrentIrpStackLocation(irp) + 1) + +#define IoSetNextIrpStackLocation(irp) \ +do { \ + KIRQL _irql_; \ + IoAcquireCancelSpinLock(&_irql_); \ + (irp)->current_location--; \ + IoGetCurrentIrpStackLocation(irp)--; \ + IoReleaseCancelSpinLock(_irql_); \ +} while (0) + +#define IoSkipCurrentIrpStackLocation(irp) \ +do { \ + KIRQL _irql_; \ + IoAcquireCancelSpinLock(&_irql_); \ + (irp)->current_location++; \ + IoGetCurrentIrpStackLocation(irp)++; \ + IoReleaseCancelSpinLock(_irql_); \ +} while (0) + +static inline void +IoCopyCurrentIrpStackLocationToNext(struct irp *irp) +{ + struct io_stack_location *next; + next = IoGetNextIrpStackLocation(irp); + memcpy(next, IoGetCurrentIrpStackLocation(irp), + offsetof(struct io_stack_location, completion_routine)); + next->control = 0; +} + +static inline void +IoSetCompletionRoutine(struct irp *irp, void *routine, void *context, + BOOLEAN success, BOOLEAN error, BOOLEAN cancel) +{ + struct io_stack_location *irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->completion_routine = routine; + irp_sl->context = context; + irp_sl->control = 0; + if (success) + irp_sl->control |= SL_INVOKE_ON_SUCCESS; + if (error) + irp_sl->control |= SL_INVOKE_ON_ERROR; + if (cancel) + irp_sl->control |= SL_INVOKE_ON_CANCEL; +} + +#define IoMarkIrpPending(irp) \ + (IoGetCurrentIrpStackLocation((irp))->control |= SL_PENDING_RETURNED) +#define IoUnmarkIrpPending(irp) \ + (IoGetCurrentIrpStackLocation((irp))->control &= ~SL_PENDING_RETURNED) + +#define IRP_SL(irp, n) (((struct io_stack_location *)((irp) + 1)) + (n)) +#define IRP_DRIVER_CONTEXT(irp) (irp)->tail.overlay.driver_context +#define IoIrpThread(irp) ((irp)->tail.overlay.thread) + +#define IRP_URB(irp) \ + (union nt_urb *)(IoGetCurrentIrpStackLocation(irp)->params.others.arg1) + +#define IRP_WRAP_DEVICE(irp) (irp)->tail.wrap_device +#define IRP_WRAP_URB(irp) (irp)->tail.wrap_urb + +struct wmi_guid_reg_info { + struct guid *guid; + ULONG instance_count; + ULONG flags; +}; + +struct wmilib_context { + ULONG guid_count; + struct wmi_guid_reg_info *guid_list; + void *query_wmi_reg_info; + void *query_wmi_data_block; + void *set_wmi_data_block; + void *set_wmi_data_item; + void *execute_wmi_method; + void *wmi_function_control; +}; + +enum key_value_information_class { + KeyValueBasicInformation, KeyValueFullInformation, + KeyValuePartialInformation, KeyValueFullInformationAlign64, + KeyValuePartialInformationAlign64 +}; + +struct file_name_info { + ULONG length; + wchar_t *name; +}; + +struct file_std_info { + LARGE_INTEGER alloc_size; + LARGE_INTEGER eof; + ULONG num_links; + BOOLEAN delete_pending; + BOOLEAN dir; +}; + +enum nt_obj_type { + NT_OBJ_EVENT = 10, NT_OBJ_MUTEX, NT_OBJ_THREAD, NT_OBJ_TIMER, + NT_OBJ_SEMAPHORE, +}; + +enum common_object_type { + OBJECT_TYPE_NONE, OBJECT_TYPE_DEVICE, OBJECT_TYPE_DRIVER, + OBJECT_TYPE_NT_THREAD, OBJECT_TYPE_FILE, OBJECT_TYPE_CALLBACK, +}; + +struct common_object_header { + struct nt_list list; + enum common_object_type type; + UINT size; + UINT ref_count; + BOOLEAN close_in_process; + BOOLEAN permanent; + struct unicode_string name; +}; + +#define OBJECT_TO_HEADER(object) \ + (struct common_object_header *)((void *)(object) - \ + sizeof(struct common_object_header)) +#define OBJECT_SIZE(size) \ + ((size) + sizeof(struct common_object_header)) +#define HEADER_TO_OBJECT(hdr) \ + ((void *)(hdr) + sizeof(struct common_object_header)) +#define HANDLE_TO_OBJECT(handle) HEADER_TO_OBJECT(handle) +#define HANDLE_TO_HEADER(handle) (handle) + +enum work_queue_type { + CriticalWorkQueue, DelayedWorkQueue, HyperCriticalWorkQueue, + MaximumWorkQueue +}; + +typedef void (*NTOS_WORK_FUNC)(void *arg1, void *arg2) wstdcall; + +struct io_workitem { + enum work_queue_type type; + struct device_object *dev_obj; + NTOS_WORK_FUNC worker_routine; + void *context; +}; + +struct io_workitem_entry { + struct nt_list list; + struct io_workitem *io_workitem; +}; + +enum mm_page_priority { + LowPagePriority, NormalPagePriority = 16, HighPagePriority = 32 +}; + +enum kinterrupt_mode { + LevelSensitive, Latched +}; + +enum ntos_wait_reason { + Executive, FreePage, PageIn, PoolAllocation, DelayExecution, + Suspended, UserRequest, WrExecutive, WrFreePage, WrPageIn, + WrPoolAllocation, WrDelayExecution, WrSuspended, WrUserRequest, + WrEventPair, WrQueue, WrLpcReceive, WrLpcReply, WrVirtualMemory, + WrPageOut, WrRendezvous, Spare2, Spare3, Spare4, Spare5, Spare6, + WrKernel, MaximumWaitReason +}; + +typedef enum ntos_wait_reason KWAIT_REASON; + +typedef void *LOOKASIDE_ALLOC_FUNC(enum pool_type pool_type, + SIZE_T size, ULONG tag) wstdcall; +typedef void LOOKASIDE_FREE_FUNC(void *) wstdcall; + +struct npaged_lookaside_list { + nt_slist_header head; + USHORT depth; + USHORT maxdepth; + ULONG totalallocs; + union { + ULONG allocmisses; + ULONG allochits; + } u1; + ULONG totalfrees; + union { + ULONG freemisses; + ULONG freehits; + } u2; + enum pool_type pool_type; + ULONG tag; + ULONG size; + LOOKASIDE_ALLOC_FUNC *alloc_func; + LOOKASIDE_FREE_FUNC *free_func; + struct nt_list list; + ULONG lasttotallocs; + union { + ULONG lastallocmisses; + ULONG lastallochits; + } u3; + ULONG pad[2]; +#ifndef CONFIG_X86_64 + NT_SPIN_LOCK obsolete; +#endif +} +#ifdef CONFIG_X86_64 +CACHE_ALIGN +#endif +; + +enum device_registry_property { + DevicePropertyDeviceDescription, DevicePropertyHardwareID, + DevicePropertyCompatibleIDs, DevicePropertyBootConfiguration, + DevicePropertyBootConfigurationTranslated, + DevicePropertyClassName, DevicePropertyClassGuid, + DevicePropertyDriverKeyName, DevicePropertyManufacturer, + DevicePropertyFriendlyName, DevicePropertyLocationInformation, + DevicePropertyPhysicalDeviceObjectName, DevicePropertyBusTypeGuid, + DevicePropertyLegacyBusType, DevicePropertyBusNumber, + DevicePropertyEnumeratorName, DevicePropertyAddress, + DevicePropertyUINumber, DevicePropertyInstallState, + DevicePropertyRemovalPolicy +}; + +enum trace_information_class { + TraceIdClass, TraceHandleClass, TraceEnableFlagsClass, + TraceEnableLevelClass, GlobalLoggerHandleClass, EventLoggerHandleClass, + AllLoggerHandlesClass, TraceHandleByNameClass +}; + +struct kinterrupt; +typedef BOOLEAN (*PKSERVICE_ROUTINE)(struct kinterrupt *interrupt, + void *context) wstdcall; +typedef BOOLEAN (*PKSYNCHRONIZE_ROUTINE)(void *context) wstdcall; + +struct kinterrupt { + ULONG vector; + KAFFINITY cpu_mask; + NT_SPIN_LOCK lock; + NT_SPIN_LOCK *actual_lock; + BOOLEAN shared; + BOOLEAN save_fp; + union { + CHAR processor_number; +#ifdef CONFIG_DEBUG_SHIRQ + CHAR enabled; +#endif + } u; + PKSERVICE_ROUTINE isr; + void *isr_ctx; + struct nt_list list; + KIRQL irql; + KIRQL synch_irql; + enum kinterrupt_mode mode; +}; + +struct time_fields { + CSHORT year; + CSHORT month; + CSHORT day; + CSHORT hour; + CSHORT minute; + CSHORT second; + CSHORT milliseconds; + CSHORT weekday; +}; + +struct object_attributes { + ULONG length; + void *root_dir; + struct unicode_string *name; + ULONG attributes; + void *security_descr; + void *security_qos; +}; + +typedef void (*PCALLBACK_FUNCTION)(void *context, void *arg1, + void *arg2) wstdcall; + +struct callback_object; +struct callback_func { + PCALLBACK_FUNCTION func; + void *context; + struct nt_list list; + struct callback_object *object; +}; + +struct callback_object { + NT_SPIN_LOCK lock; + struct nt_list list; + struct nt_list callback_funcs; + BOOLEAN allow_multiple_callbacks; + struct object_attributes *attributes; +}; + +enum section_inherit { + ViewShare = 1, ViewUnmap = 2 +}; + +struct ksystem_time { + ULONG low_part; + LONG high1_time; + LONG high2_time; +}; + +enum nt_product_type { + nt_product_win_nt = 1, nt_product_lan_man_nt, nt_product_server +}; + +enum alt_arch_type { + arch_type_standard, arch_type_nex98x86, end_alternatives +}; + +struct kuser_shared_data { + ULONG tick_count; + ULONG tick_count_multiplier; + volatile struct ksystem_time interrupt_time; + volatile struct ksystem_time system_time; + volatile struct ksystem_time time_zone_bias; + USHORT image_number_low; + USHORT image_number_high; + wchar_t nt_system_root[260]; + ULONG max_stack_trace_depth; + ULONG crypto_exponent; + ULONG time_zone_id; + ULONG large_page_min; + ULONG reserved2[7]; + enum nt_product_type nt_product_type; + BOOLEAN product_type_is_valid; + ULONG nt_major_version; + ULONG nt_minor_version; + BOOLEAN processor_features[PROCESSOR_FEATURE_MAX]; + ULONG reserved1; + ULONG reserved3; + volatile LONG time_slip; + enum alt_arch_type alt_arch_type; + LARGE_INTEGER system_expiration_date; + ULONG suite_mask; + BOOLEAN kdbg_enabled; + volatile ULONG active_console; + volatile ULONG dismount_count; + ULONG com_plus_package; + ULONG last_system_rite_event_tick_count; + ULONG num_phys_pages; + BOOLEAN safe_boot_mode; + ULONG trace_log; + ULONGLONG fill0; + ULONGLONG sys_call[4]; + union { + volatile struct ksystem_time tick_count; + volatile ULONG64 tick_count_quad; + } tick; +}; + +#define REG_NONE (0) +#define REG_SZ (1) +#define REG_EXPAND_SZ (2) +#define REG_BINARY (3) +#define REG_DWORD (4) + +#define RTL_REGISTRY_ABSOLUTE 0 +#define RTL_REGISTRY_SERVICES 1 +#define RTL_REGISTRY_CONTROL 2 +#define RTL_REGISTRY_WINDOWS_NT 3 +#define RTL_REGISTRY_DEVICEMAP 4 +#define RTL_REGISTRY_USER 5 +#define RTL_REGISTRY_MAXIMUM 6 +#define RTL_REGISTRY_HANDLE 0x40000000 +#define RTL_REGISTRY_OPTIONAL 0x80000000 + +#define RTL_QUERY_REGISTRY_SUBKEY 0x00000001 +#define RTL_QUERY_REGISTRY_TOPKEY 0x00000002 +#define RTL_QUERY_REGISTRY_REQUIRED 0x00000004 +#define RTL_QUERY_REGISTRY_NOVALUE 0x00000008 +#define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010 +#define RTL_QUERY_REGISTRY_DIRECT 0x00000020 +#define RTL_QUERY_REGISTRY_DELETE 0x00000040 + +typedef NTSTATUS (*PRTL_QUERY_REGISTRY_ROUTINE)(wchar_t *name, ULONG type, + void *data, ULONG length, + void *context, + void *entry) wstdcall; + +struct rtl_query_registry_table { + PRTL_QUERY_REGISTRY_ROUTINE query_func; + ULONG flags; + wchar_t *name; + void *context; + ULONG def_type; + void *def_data; + ULONG def_length; +}; + +struct io_remove_lock { + BOOLEAN removed; + BOOLEAN reserved[3]; + LONG io_count; + struct nt_event remove_event; +}; + +struct io_error_log_packet { + UCHAR major_fn_code; + UCHAR retry_count; + USHORT dump_data_size; + USHORT nr_of_strings; + USHORT string_offset; + USHORT event_category; + NTSTATUS error_code; + ULONG unique_error_value; + NTSTATUS final_status; + ULONG sequence_number; + ULONG io_control_code; + LARGE_INTEGER device_offset; + ULONG dump_data[1]; +}; + +/* some of the functions below are slightly different from DDK's + * implementation; e.g., Insert functions return appropriate + * pointer */ + +/* instead of using Linux's lists, we implement list manipulation + * functions because nt_list is used by drivers and we don't want to + * worry about Linux's list being different from nt_list (right now + * they are same, but in future they could be different) */ + +static inline void InitializeListHead(struct nt_list *head) +{ + head->next = head->prev = head; +} + +static inline BOOLEAN IsListEmpty(struct nt_list *head) +{ + if (head == head->next) + return TRUE; + else + return FALSE; +} + +static inline void RemoveEntryList(struct nt_list *entry) +{ + entry->prev->next = entry->next; + entry->next->prev = entry->prev; +} + +static inline struct nt_list *RemoveHeadList(struct nt_list *head) +{ + struct nt_list *entry; + + entry = head->next; + if (entry == head) + return NULL; + else { + RemoveEntryList(entry); + return entry; + } +} + +static inline struct nt_list *RemoveTailList(struct nt_list *head) +{ + struct nt_list *entry; + + entry = head->prev; + if (entry == head) + return NULL; + else { + RemoveEntryList(entry); + return entry; + } +} + +static inline void InsertListEntry(struct nt_list *entry, struct nt_list *prev, + struct nt_list *next) +{ + next->prev = entry; + entry->next = next; + entry->prev = prev; + prev->next = entry; +} + +static inline struct nt_list *InsertHeadList(struct nt_list *head, + struct nt_list *entry) +{ + struct nt_list *ret; + + if (IsListEmpty(head)) + ret = NULL; + else + ret = head->next; + + InsertListEntry(entry, head, head->next); + return ret; +} + +static inline struct nt_list *InsertTailList(struct nt_list *head, + struct nt_list *entry) +{ + struct nt_list *ret; + + if (IsListEmpty(head)) + ret = NULL; + else + ret = head->prev; + + InsertListEntry(entry, head->prev, head); + return ret; +} + +#define nt_list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#define nt_list_for_each_entry(pos, head, member) \ + for (pos = container_of((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, typeof(*pos), member)) + +#define nt_list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/* device object flags */ +#define DO_VERIFY_VOLUME 0x00000002 +#define DO_BUFFERED_IO 0x00000004 +#define DO_EXCLUSIVE 0x00000008 +#define DO_DIRECT_IO 0x00000010 +#define DO_MAP_IO_BUFFER 0x00000020 +#define DO_DEVICE_HAS_NAME 0x00000040 +#define DO_DEVICE_INITIALIZING 0x00000080 +#define DO_SYSTEM_BOOT_PARTITION 0x00000100 +#define DO_LONG_TERM_REQUESTS 0x00000200 +#define DO_NEVER_LAST_DEVICE 0x00000400 +#define DO_SHUTDOWN_REGISTERED 0x00000800 +#define DO_BUS_ENUMERATED_DEVICE 0x00001000 +#define DO_POWER_PAGABLE 0x00002000 +#define DO_POWER_INRUSH 0x00004000 +#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 + +/* Various supported device types (used with IoCreateDevice()) */ + +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000A +#define FILE_DEVICE_KEYBOARD 0x0000000B +#define FILE_DEVICE_MAILSLOT 0x0000000C +#define FILE_DEVICE_MIDI_IN 0x0000000D +#define FILE_DEVICE_MIDI_OUT 0x0000000E +#define FILE_DEVICE_MOUSE 0x0000000F +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A +#define FILE_DEVICE_SERIAL_PORT 0x0000001B +#define FILE_DEVICE_SCREEN 0x0000001C +#define FILE_DEVICE_SOUND 0x0000001D +#define FILE_DEVICE_STREAMS 0x0000001E +#define FILE_DEVICE_TAPE 0x0000001F +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002A +#define FILE_DEVICE_MODEM 0x0000002B +#define FILE_DEVICE_VDM 0x0000002C +#define FILE_DEVICE_MASS_STORAGE 0x0000002D +#define FILE_DEVICE_SMB 0x0000002E +#define FILE_DEVICE_KS 0x0000002F +#define FILE_DEVICE_CHANGER 0x00000030 +#define FILE_DEVICE_SMARTCARD 0x00000031 +#define FILE_DEVICE_ACPI 0x00000032 +#define FILE_DEVICE_DVD 0x00000033 +#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 +#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 +#define FILE_DEVICE_DFS_VOLUME 0x00000036 +#define FILE_DEVICE_SERENUM 0x00000037 +#define FILE_DEVICE_TERMSRV 0x00000038 +#define FILE_DEVICE_KSEC 0x00000039 +#define FILE_DEVICE_FIPS 0x0000003A + +/* Device characteristics */ + +#define FILE_REMOVABLE_MEDIA 0x00000001 +#define FILE_READ_ONLY_DEVICE 0x00000002 +#define FILE_FLOPPY_DISKETTE 0x00000004 +#define FILE_WRITE_ONCE_MEDIA 0x00000008 +#define FILE_REMOTE_DEVICE 0x00000010 +#define FILE_DEVICE_IS_MOUNTED 0x00000020 +#define FILE_VIRTUAL_VOLUME 0x00000040 +#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 +#define FILE_DEVICE_SECURE_OPEN 0x00000100 + +#define FILE_READ_DATA 0x0001 +#define FILE_WRITE_DATA 0x0002 + +#define FILE_SUPERSEDED 0x00000000 +#define FILE_OPENED 0x00000001 +#define FILE_CREATED 0x00000002 +#define FILE_OVERWRITTEN 0x00000003 +#define FILE_EXISTS 0x00000004 +#define FILE_DOES_NOT_EXIST 0x00000005 + + +#endif /* WINNT_TYPES_H */ --- linux-2.6.27.orig/ubuntu/ndiswrapper/mkexport.sh +++ linux-2.6.27/ubuntu/ndiswrapper/mkexport.sh @@ -0,0 +1,42 @@ +#! /bin/sh + +# Generate exports symbol table from C files + +input="$1" +output="$2" +exports=$(basename "$output" .h) +exec >"$output" + +echo "/* automatically generated from src */"; + +sed -n -e '/^\(wstdcall\|wfastcall\|noregparm\|__attribute__\)/{ +:more +N +s/\([^{]\)$/\1/ +t more +s/\n{$/;/ +p +}' $input + +echo "#ifdef CONFIG_X86_64"; + +sed -n \ + -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +'WIN_FUNC_DECL(\1, \2)/p' \ + -e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +'WIN_FUNC_DECL(\1, \2)/p' $input | sort -u + +echo "#endif" +echo "extern struct wrap_export $exports[];" +echo "struct wrap_export $exports[] = {" + +sed -n \ + -e 's/.*WIN_FUNC(_win_\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +' WIN_WIN_SYMBOL(\1, \2),/p' \ + -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +' WIN_SYMBOL(\1, \2),/p' \ + -e 's/.*WIN_SYMBOL_MAP(\("[^"]\+"\)[ ,\n]\+\([^)]\+\)).*/'\ +' {\1, (generic_func)\2},/p' $input | sort -u + +echo " {NULL, NULL}" +echo "};" --- linux-2.6.27.orig/ubuntu/ndiswrapper/ndiswrapper.h +++ linux-2.6.27/ubuntu/ndiswrapper/ndiswrapper.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _NDISWRAPPER_H_ +#define _NDISWRAPPER_H_ + +#define DRIVER_VERSION "1.53" +#define UTILS_VERSION "1.9" + +#define DRIVER_NAME "ndiswrapper" +#define DRIVER_CONFIG_DIR "/etc/ndiswrapper" + +#define SSID_MAX_WPA_IE_LEN 40 +#define NDIS_ESSID_MAX_SIZE 32 +#define NDIS_ENCODING_TOKEN_MAX 32 +#define MAX_ENCR_KEYS 4 +#define TX_RING_SIZE 16 +#define NDIS_MAX_RATES 8 +#define NDIS_MAX_RATES_EX 16 +#define WLAN_EID_GENERIC 221 +#define MAX_WPA_IE_LEN 64 +#define MAX_STR_LEN 512 + +#define WRAP_PCI_BUS 5 +#define WRAP_PCMCIA_BUS 8 +/* some USB devices, e.g., DWL-G120 have BusType as 0 */ +#define WRAP_INTERNAL_BUS 0 +/* documentation at msdn says 15 is PNP bus, but inf files from all + * vendors say 15 is USB; which is correct? */ +#define WRAP_USB_BUS 15 + +/* NDIS device must be 0, for compatability with old versions of + * ndiswrapper where device type for NDIS drivers is 0 */ +#define WRAP_NDIS_DEVICE 0 +#define WRAP_USB_DEVICE 1 +#define WRAP_BLUETOOTH_DEVICE1 2 +#define WRAP_BLUETOOTH_DEVICE2 3 + +#define WRAP_DEVICE_BUS(dev, bus) ((dev) << 8 | (bus)) +#define WRAP_BUS(dev_bus) ((dev_bus) & 0x000FF) +#define WRAP_DEVICE(dev_bus) ((dev_bus) >> 8) + +#define MAX_DRIVER_NAME_LEN 32 +#define MAX_VERSION_STRING_LEN 64 +#define MAX_SETTING_NAME_LEN 128 +#define MAX_SETTING_VALUE_LEN 256 + +#define MAX_DRIVER_PE_IMAGES 4 +#define MAX_DRIVER_BIN_FILES 5 +#define MAX_DEVICE_SETTINGS 512 + +#define MAX_ALLOCATED_URBS 15 + +#define DEV_ANY_ID -1 + +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTRSEP "%02x:%02x:%02x:%02x:%02x:%02x" +#define MACSTR "%02x%02x%02x%02x%02x%02x" +#define MACINTADR(a) (int*)&((a)[0]), (int*)&((a)[1]), (int*)&((a)[2]), \ + (int*)&((a)[3]), (int*)&((a)[4]), (int*)&((a)[5]) + +#ifdef __KERNEL__ +/* DEBUG macros */ + +#define MSG(level, fmt, ...) \ + printk(level "ndiswrapper (%s:%d): " fmt "\n", \ + __FUNCTION__, __LINE__ , ## __VA_ARGS__) + +#define WARNING(fmt, ...) MSG(KERN_WARNING, fmt, ## __VA_ARGS__) +#define ERROR(fmt, ...) MSG(KERN_ERR, fmt , ## __VA_ARGS__) +#define INFO(fmt, ...) MSG(KERN_INFO, fmt , ## __VA_ARGS__) +#define TODO() WARNING("not fully implemented (yet)") + +#define TRACE(fmt, ...) do { } while (0) +#define TRACE1(fmt, ...) do { } while (0) +#define TRACE2(fmt, ...) do { } while (0) +#define TRACE3(fmt, ...) do { } while (0) +#define TRACE4(fmt, ...) do { } while (0) +#define TRACE5(fmt, ...) do { } while (0) +#define TRACE6(fmt, ...) do { } while (0) + +/* for a block of code */ +#define DBG_BLOCK(level) while (0) + +extern int debug; + +#if defined DEBUG +#undef TRACE +#define TRACE(level, fmt, ...) \ +do { \ + if (debug >= level) \ + printk(KERN_INFO "%s (%s:%d): " fmt "\n", DRIVER_NAME, \ + __FUNCTION__, __LINE__ , ## __VA_ARGS__); \ +} while (0) +#undef DBG_BLOCK +#define DBG_BLOCK(level) if (debug >= level) +#endif + +#if defined(DEBUG) && DEBUG >= 1 +#undef TRACE1 +#define TRACE1(fmt, ...) TRACE(1, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 2 +#undef TRACE2 +#define TRACE2(fmt, ...) TRACE(2, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 3 +#undef TRACE3 +#define TRACE3(fmt, ...) TRACE(3, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 4 +#undef TRACE4 +#define TRACE4(fmt, ...) TRACE(4, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 5 +#undef TRACE5 +#define TRACE5(fmt, ...) TRACE(5, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 6 +#undef TRACE6 +#define TRACE6(fmt, ...) TRACE(6, fmt , ## __VA_ARGS__) +#endif + +#define ENTER1(fmt, ...) TRACE1("Enter " fmt , ## __VA_ARGS__) +#define ENTER2(fmt, ...) TRACE2("Enter " fmt , ## __VA_ARGS__) +#define ENTER3(fmt, ...) TRACE3("Enter " fmt , ## __VA_ARGS__) +#define ENTER4(fmt, ...) TRACE4("Enter " fmt , ## __VA_ARGS__) +#define ENTER5(fmt, ...) TRACE5("Enter " fmt , ## __VA_ARGS__) +#define ENTER6(fmt, ...) TRACE6("Enter " fmt , ## __VA_ARGS__) + +#define EXIT1(stmt) do { TRACE1("Exit"); stmt; } while(0) +#define EXIT2(stmt) do { TRACE2("Exit"); stmt; } while(0) +#define EXIT3(stmt) do { TRACE3("Exit"); stmt; } while(0) +#define EXIT4(stmt) do { TRACE4("Exit"); stmt; } while(0) +#define EXIT5(stmt) do { TRACE5("Exit"); stmt; } while(0) +#define EXIT6(stmt) do { TRACE6("Exit"); stmt; } while(0) + +#if defined(USB_DEBUG) +#define USBTRACE TRACE1 +#define USBENTER ENTER1 +#define USBEXIT EXIT1 +#else +#define USBTRACE(fmt, ...) +#define USBENTER(fmt, ...) +#define USBEXIT(stmt) stmt +#endif + +#if defined(EVENT_DEBUG) +#define EVENTTRACE TRACE1 +#define EVENTENTER ENTER1 +#define EVENTEXIT EXIT1 +#else +#define EVENTTRACE(fmt, ...) +#define EVENTENTER(fmt, ...) +#define EVENTEXIT(stmt) stmt +#endif + +#if defined(TIMER_DEBUG) +#define TIMERTRACE TRACE1 +#define TIMERENTER ENTER1 +#define TIMEREXIT EXIT1 +#else +#define TIMERTRACE(fmt, ...) +#define TIMERENTER(fmt, ...) +#define TIMEREXIT(stmt) stmt +#endif + +#if defined(IO_DEBUG) +#define IOTRACE TRACE1 +#define IOENTER ENTER1 +#define IOEXIT EXIT1 +#else +#define IOTRACE(fmt, ...) +#define IOENTER(fmt, ...) +#define IOEXIT(stmt) stmt +#endif + +#if defined(WORK_DEBUG) +#define WORKTRACE TRACE1 +#define WORKENTER ENTER1 +#define WORKEXIT EXIT1 +#else +#define WORKTRACE(fmt, ...) +#define WORKENTER(fmt, ...) +#define WORKEXIT(stmt) stmt +#endif + +#ifdef DEBUG +#define assert(expr) \ +do { \ + if (!(expr)) { \ + ERROR("assertion '%s' failed", #expr); \ + dump_stack(); \ + } \ +} while (0) +#else +#define assert(expr) do { } while (0) +#endif + +#endif // __KERNEL__ + +#endif // NDISWRAPPER_H --- linux-2.6.27.orig/ubuntu/ndiswrapper/Kconfig +++ linux-2.6.27/ubuntu/ndiswrapper/Kconfig @@ -0,0 +1,4 @@ +config NDISWRAPPER + tristate "Wrapper for Windows NDIS network drivers" + depends on NET + default m --- linux-2.6.27.orig/ubuntu/ndiswrapper/wrapper.c +++ linux-2.6.27/ubuntu/ndiswrapper/wrapper.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ndis.h" +#include "iw_ndis.h" +#include "loader.h" +#include "pnp.h" +#include "wrapper.h" + +char *if_name = "wlan%d"; +int proc_uid, proc_gid; +int hangcheck_interval; +static char *utils_version = UTILS_VERSION; + +#if defined(DEBUG) && (DEBUG > 0) +int debug = DEBUG; +#else +int debug = 0; +#endif + +WRAP_MODULE_PARM_STRING(if_name, 0400); +MODULE_PARM_DESC(if_name, "Network interface name or template " + "(default: wlan%d)"); +WRAP_MODULE_PARM_INT(proc_uid, 0600); +MODULE_PARM_DESC(proc_uid, "The uid of the files created in /proc " + "(default: 0)."); +WRAP_MODULE_PARM_INT(proc_gid, 0600); +MODULE_PARM_DESC(proc_gid, "The gid of the files created in /proc " + "(default: 0)."); +WRAP_MODULE_PARM_INT(debug, 0600); +MODULE_PARM_DESC(debug, "debug level"); + +/* 0 - default value provided by NDIS driver, + * positive value - force hangcheck interval to that many seconds + * negative value - disable hangcheck + */ +WRAP_MODULE_PARM_INT(hangcheck_interval, 0600); +MODULE_PARM_DESC(hangcheck_interval, "The interval, in seconds, for checking" + " if driver is hung. (default: 0)"); + +WRAP_MODULE_PARM_STRING(utils_version, 0400); +MODULE_PARM_DESC(utils_version, "Compatible version of utils " + "(read only: " UTILS_VERSION ")"); + +MODULE_AUTHOR("ndiswrapper team "); +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION("NDIS wrapper driver"); +#endif +#ifdef MODULE_VERSION +MODULE_VERSION(DRIVER_VERSION); +#endif +MODULE_LICENSE("GPL"); + +static void module_cleanup(void) +{ + loader_exit(); +#ifdef ENABLE_USB + usb_exit(); +#endif + + wrap_procfs_remove(); + wrapndis_exit(); + ndis_exit(); + rtl_exit(); + crt_exit(); + ntoskernel_exit(); + wrapmem_exit(); +} + +static int __init wrapper_init(void) +{ + printk(KERN_INFO "%s version %s loaded (smp=%s, preempt=%s)\n", + DRIVER_NAME, DRIVER_VERSION, +#ifdef CONFIG_SMP + "yes" +#else + "no" +#endif + , +#ifdef CONFIG_PREEMPT_RT + "rt" +#elif defined(CONFIG_PREEMPT) + "yes" +#else + "no" +#endif + ); + + if (wrapmem_init() || ntoskernel_init() || crt_init() || + rtl_init() || ndis_init() || wrapndis_init() || +#ifdef ENABLE_USB + usb_init() || +#endif + wrap_procfs_init() || loader_init()) { + module_cleanup(); + ERROR("%s: initialization failed", DRIVER_NAME); + return -EINVAL; + } + EXIT1(return 0); +} + +static void __exit wrapper_exit(void) +{ + ENTER1(""); + module_cleanup(); +} + +module_init(wrapper_init); +module_exit(wrapper_exit); --- linux-2.6.27.orig/ubuntu/ndiswrapper/ntoskernel.c +++ linux-2.6.27/ubuntu/ndiswrapper/ntoskernel.c @@ -0,0 +1,2677 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ntoskernel.h" +#include "ndis.h" +#include "usb.h" +#include "pnp.h" +#include "loader.h" +#include "ntoskernel_exports.h" + +/* MDLs describe a range of virtual address with an array of physical + * pages right after the header. For different ranges of virtual + * addresses, the number of entries of physical pages may be different + * (depending on number of entries required). If we want to allocate + * MDLs from a pool, the size has to be constant. So we assume that + * maximum range used by a driver is MDL_CACHE_PAGES; if a driver + * requests an MDL for a bigger region, we allocate it with kmalloc; + * otherwise, we allocate from the pool */ + +#define MDL_CACHE_PAGES 3 +#define MDL_CACHE_SIZE (sizeof(struct mdl) + \ + (sizeof(PFN_NUMBER) * MDL_CACHE_PAGES)) +struct wrap_mdl { + struct nt_list list; + struct mdl mdl[0]; +}; + +/* everything here is for all drivers/devices - not per driver/device */ +static spinlock_t dispatcher_lock; +spinlock_t ntoskernel_lock; +static void *mdl_cache; +static struct nt_list wrap_mdl_list; + +static work_struct_t kdpc_work; +static void kdpc_worker(worker_param_t dummy); + +static struct nt_list kdpc_list; +static spinlock_t kdpc_list_lock; + +static struct nt_list callback_objects; + +struct nt_list object_list; + +struct bus_driver { + struct nt_list list; + char name[MAX_DRIVER_NAME_LEN]; + struct driver_object drv_obj; +}; + +static struct nt_list bus_driver_list; + +static work_struct_t ntos_work; +static struct nt_list ntos_work_list; +static spinlock_t ntos_work_lock; +static void ntos_work_worker(worker_param_t dummy); +static struct nt_thread *ntos_worker_thread; +spinlock_t irp_cancel_lock; +static NT_SPIN_LOCK nt_list_lock; +static struct nt_slist wrap_timer_slist; + +/* compute ticks (100ns) since 1601 until when system booted into + * wrap_ticks_to_boot */ +u64 wrap_ticks_to_boot; + +#if defined(CONFIG_X86_64) +static struct timer_list shared_data_timer; +struct kuser_shared_data kuser_shared_data; +static void update_user_shared_data_proc(unsigned long data); +#endif + +WIN_SYMBOL_MAP("KeTickCount", &jiffies) + +WIN_SYMBOL_MAP("NlsMbCodePageTag", FALSE) + +workqueue_struct_t *ntos_wq; + +#ifdef WRAP_PREEMPT +DEFINE_PER_CPU(irql_info_t, irql_info); +#endif + +#if defined(CONFIG_X86_64) +static void update_user_shared_data_proc(unsigned long data) +{ + /* timer is supposed to be scheduled every 10ms, but bigger + * intervals seem to work (tried upto 50ms) */ + *((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601(); + *((ULONG64 *)&kuser_shared_data.interrupt_time) = + jiffies * TICKSPERSEC / HZ; + *((ULONG64 *)&kuser_shared_data.tick) = jiffies; + + mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30)); +} +#endif + +void *allocate_object(ULONG size, enum common_object_type type, + struct unicode_string *name) +{ + struct common_object_header *hdr; + void *body; + + /* we pad header as prefix to body */ + hdr = ExAllocatePoolWithTag(NonPagedPool, OBJECT_SIZE(size), 0); + if (!hdr) { + WARNING("couldn't allocate memory"); + return NULL; + } + memset(hdr, 0, OBJECT_SIZE(size)); + if (name) { + hdr->name.buf = ExAllocatePoolWithTag(NonPagedPool, + name->max_length, 0); + if (!hdr->name.buf) { + ExFreePool(hdr); + return NULL; + } + memcpy(hdr->name.buf, name->buf, name->max_length); + hdr->name.length = name->length; + hdr->name.max_length = name->max_length; + } + hdr->type = type; + hdr->ref_count = 1; + spin_lock_bh(&ntoskernel_lock); + /* threads are looked up often (in KeWaitForXXX), so optimize + * for fast lookups of threads */ + if (type == OBJECT_TYPE_NT_THREAD) + InsertHeadList(&object_list, &hdr->list); + else + InsertTailList(&object_list, &hdr->list); + spin_unlock_bh(&ntoskernel_lock); + body = HEADER_TO_OBJECT(hdr); + TRACE3("allocated hdr: %p, body: %p", hdr, body); + return body; +} + +void free_object(void *object) +{ + struct common_object_header *hdr; + + hdr = OBJECT_TO_HEADER(object); + spin_lock_bh(&ntoskernel_lock); + RemoveEntryList(&hdr->list); + spin_unlock_bh(&ntoskernel_lock); + TRACE3("freed hdr: %p, body: %p", hdr, object); + if (hdr->name.buf) + ExFreePool(hdr->name.buf); + ExFreePool(hdr); +} + +static int add_bus_driver(const char *name) +{ + struct bus_driver *bus_driver; + + bus_driver = kzalloc(sizeof(*bus_driver), GFP_KERNEL); + if (!bus_driver) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + strncpy(bus_driver->name, name, sizeof(bus_driver->name)); + bus_driver->name[sizeof(bus_driver->name)-1] = 0; + spin_lock_bh(&ntoskernel_lock); + InsertTailList(&bus_driver_list, &bus_driver->list); + spin_unlock_bh(&ntoskernel_lock); + TRACE1("bus driver %s is at %p", name, &bus_driver->drv_obj); + return STATUS_SUCCESS; +} + +struct driver_object *find_bus_driver(const char *name) +{ + struct bus_driver *bus_driver; + struct driver_object *drv_obj; + + spin_lock_bh(&ntoskernel_lock); + drv_obj = NULL; + nt_list_for_each_entry(bus_driver, &bus_driver_list, list) { + if (strcmp(bus_driver->name, name) == 0) { + drv_obj = &bus_driver->drv_obj; + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + return drv_obj; +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertHeadList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + struct nt_list *first; + unsigned long flags; + + ENTER5("head = %p, entry = %p", head, entry); + nt_spin_lock_irqsave(lock, flags); + first = InsertHeadList(head, entry); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, old = %p", head, first); + return first; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertHeadList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedInsertHeadList(head, entry, lock); +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertTailList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + struct nt_list *last; + unsigned long flags; + + ENTER5("head = %p, entry = %p", head, entry); + nt_spin_lock_irqsave(lock, flags); + last = InsertTailList(head, entry); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, old = %p", head, last); + return last; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertTailList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedInsertTailList(head, entry, lock); +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveHeadList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + struct nt_list *ret; + unsigned long flags; + + ENTER5("head = %p", head); + nt_spin_lock_irqsave(lock, flags); + ret = RemoveHeadList(head); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, ret = %p", head, ret); + return ret; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveHeadList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedRemoveHeadList(head, lock); +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveTailList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + struct nt_list *ret; + unsigned long flags; + + ENTER5("head = %p", head); + nt_spin_lock_irqsave(lock, flags); + ret = RemoveTailList(head); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, ret = %p", head, ret); + return ret; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveTailList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedRemoveTailList(head, lock); +} + +wfastcall void WIN_FUNC(InitializeSListHead,1) + (nt_slist_header *head) +{ + memset(head, 0, sizeof(*head)); +} + +wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPushEntrySList,3) + (nt_slist_header *head, struct nt_slist *entry, NT_SPIN_LOCK *lock) +{ + struct nt_slist *ret; + + ret = PushEntrySList(head, entry, lock); + return ret; +} + +wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPushEntrySList,2) + (nt_slist_header *head, struct nt_slist *entry) +{ + struct nt_slist *ret; + + ret = PushEntrySList(head, entry, &nt_list_lock); + return ret; +} + +wfastcall struct nt_slist *WIN_FUNC(InterlockedPushEntrySList,2) + (nt_slist_header *head, struct nt_slist *entry) +{ + struct nt_slist *ret; + + ret = PushEntrySList(head, entry, &nt_list_lock); + return ret; +} + +wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPopEntrySList,2) + (nt_slist_header *head, NT_SPIN_LOCK *lock) +{ + struct nt_slist *ret; + + ret = PopEntrySList(head, lock); + return ret; +} + +wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPopEntrySList,1) + (nt_slist_header *head) +{ + struct nt_slist *ret; + + ret = PopEntrySList(head, &nt_list_lock); + return ret; +} + +wfastcall struct nt_slist *WIN_FUNC(InterlockedPopEntrySList,1) + (nt_slist_header *head) +{ + struct nt_slist *ret; + + ret = PopEntrySList(head, &nt_list_lock); + return ret; +} + +wstdcall USHORT WIN_FUNC(ExQueryDepthSList,1) + (nt_slist_header *head) +{ + USHORT depth; + ENTER5("%p", head); + depth = head->depth; + TRACE5("%d, %p", depth, head->next); + return depth; +} + +wfastcall LONG WIN_FUNC(InterlockedIncrement,1) + (LONG volatile *val) +{ + return post_atomic_add(*val, 1); +} + +wfastcall LONG WIN_FUNC(InterlockedDecrement,1) + (LONG volatile *val) +{ + return post_atomic_add(*val, -1); +} + +wfastcall LONG WIN_FUNC(InterlockedExchange,2) + (LONG volatile *target, LONG val) +{ + return xchg(target, val); +} + +wfastcall LONG WIN_FUNC(InterlockedCompareExchange,3) + (LONG volatile *dest, LONG new, LONG old) +{ + return cmpxchg(dest, old, new); +} + +wfastcall void WIN_FUNC(ExInterlockedAddLargeStatistic,2) + (LARGE_INTEGER volatile *plint, ULONG n) +{ + unsigned long flags; + + local_irq_save(flags); +#ifdef CONFIG_X86_64 + __asm__ __volatile__( + "\n" + LOCK_PREFIX "add %1, %0\n\t" + : "+m" (*plint) + : "r" (n)); +#else + __asm__ __volatile__( + "1:\t" + " movl %1, %%ebx\n\t" + " movl %%edx, %%ecx\n\t" + " addl %%eax, %%ebx\n\t" + " adcl $0, %%ecx\n\t" + LOCK_PREFIX "cmpxchg8b %0\n\t" + " jnz 1b\n\t" + : "+m" (*plint) + : "m" (n), "A" (*plint) + : "ebx", "ecx"); +#endif + local_irq_restore(flags); +} + +static void initialize_object(struct dispatcher_header *dh, enum dh_type type, + int state) +{ + memset(dh, 0, sizeof(*dh)); + set_object_type(dh, type); + dh->signal_state = state; + InitializeListHead(&dh->wait_blocks); +} + +static void timer_proc(unsigned long data) +{ + struct wrap_timer *wrap_timer = (struct wrap_timer *)data; + struct nt_timer *nt_timer; + struct kdpc *kdpc; + + nt_timer = wrap_timer->nt_timer; + TIMERENTER("%p(%p), %lu", wrap_timer, nt_timer, jiffies); +#ifdef TIMER_DEBUG + BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC); + BUG_ON(nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC); +#endif + kdpc = nt_timer->kdpc; + if (kdpc) + queue_kdpc(kdpc); + KeSetEvent((struct nt_event *)nt_timer, 0, FALSE); + if (wrap_timer->repeat) + mod_timer(&wrap_timer->timer, jiffies + wrap_timer->repeat); + TIMEREXIT(return); +} + +void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type, + struct ndis_mp_block *nmb) +{ + struct wrap_timer *wrap_timer; + + /* TODO: if a timer is initialized more than once, we allocate + * memory for wrap_timer more than once for the same nt_timer, + * wasting memory. We can check if nt_timer->wrap_timer_magic is + * set and not allocate, but it is not guaranteed always to be + * safe */ + TIMERENTER("%p", nt_timer); + /* we allocate memory for wrap_timer behind driver's back and + * there is no NDIS/DDK function where this memory can be + * freed, so we use slack_kmalloc so it gets freed when driver + * is unloaded */ + if (nmb) + wrap_timer = kmalloc(sizeof(*wrap_timer), irql_gfp()); + else + wrap_timer = slack_kmalloc(sizeof(*wrap_timer)); + if (!wrap_timer) { + ERROR("couldn't allocate memory for timer"); + return; + } + + memset(wrap_timer, 0, sizeof(*wrap_timer)); + init_timer(&wrap_timer->timer); + wrap_timer->timer.data = (unsigned long)wrap_timer; + wrap_timer->timer.function = timer_proc; + wrap_timer->nt_timer = nt_timer; +#ifdef TIMER_DEBUG + wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC; +#endif + nt_timer->wrap_timer = wrap_timer; + nt_timer->kdpc = NULL; + initialize_object(&nt_timer->dh, type, 0); + nt_timer->wrap_timer_magic = WRAP_TIMER_MAGIC; + TIMERTRACE("timer %p (%p)", wrap_timer, nt_timer); + spin_lock_bh(&ntoskernel_lock); + if (nmb) { + wrap_timer->slist.next = nmb->wnd->wrap_timer_slist.next; + nmb->wnd->wrap_timer_slist.next = &wrap_timer->slist; + } else { + wrap_timer->slist.next = wrap_timer_slist.next; + wrap_timer_slist.next = &wrap_timer->slist; + } + spin_unlock_bh(&ntoskernel_lock); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(KeInitializeTimerEx,2) + (struct nt_timer *nt_timer, enum timer_type type) +{ + TIMERENTER("%p", nt_timer); + wrap_init_timer(nt_timer, type, NULL); +} + +wstdcall void WIN_FUNC(KeInitializeTimer,1) + (struct nt_timer *nt_timer) +{ + TIMERENTER("%p", nt_timer); + wrap_init_timer(nt_timer, NotificationTimer, NULL); +} + +/* expires and repeat are in HZ */ +BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz, + unsigned long repeat_hz, struct kdpc *kdpc) +{ + struct wrap_timer *wrap_timer; + + TIMERENTER("%p, %lu, %lu, %p, %lu", + nt_timer, expires_hz, repeat_hz, kdpc, jiffies); + + wrap_timer = nt_timer->wrap_timer; + TIMERTRACE("%p", wrap_timer); +#ifdef TIMER_DEBUG + if (wrap_timer->nt_timer != nt_timer) + WARNING("bad timers: %p, %p, %p", wrap_timer, nt_timer, + wrap_timer->nt_timer); + if (nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) { + WARNING("buggy Windows timer didn't initialize timer %p", + nt_timer); + return FALSE; + } + if (wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) { + WARNING("timer %p is not initialized (%lx)?", + wrap_timer, wrap_timer->wrap_timer_magic); + wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC; + } +#endif + KeClearEvent((struct nt_event *)nt_timer); + nt_timer->kdpc = kdpc; + wrap_timer->repeat = repeat_hz; + if (mod_timer(&wrap_timer->timer, jiffies + expires_hz)) + TIMEREXIT(return TRUE); + else + TIMEREXIT(return FALSE); +} + +wstdcall BOOLEAN WIN_FUNC(KeSetTimerEx,4) + (struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + LONG period_ms, struct kdpc *kdpc) +{ + unsigned long expires_hz, repeat_hz; + + TIMERENTER("%p, %Ld, %d", nt_timer, duetime_ticks, period_ms); + expires_hz = SYSTEM_TIME_TO_HZ(duetime_ticks); + repeat_hz = MSEC_TO_HZ(period_ms); + return wrap_set_timer(nt_timer, expires_hz, repeat_hz, kdpc); +} + +wstdcall BOOLEAN WIN_FUNC(KeSetTimer,3) + (struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + struct kdpc *kdpc) +{ + TIMERENTER("%p, %Ld, %p", nt_timer, duetime_ticks, kdpc); + return KeSetTimerEx(nt_timer, duetime_ticks, 0, kdpc); +} + +wstdcall BOOLEAN WIN_FUNC(KeCancelTimer,1) + (struct nt_timer *nt_timer) +{ + struct wrap_timer *wrap_timer; + int ret; + + TIMERENTER("%p", nt_timer); + wrap_timer = nt_timer->wrap_timer; + if (!wrap_timer) { + ERROR("invalid wrap_timer"); + return TRUE; + } +#ifdef TIMER_DEBUG + BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC); +#endif + TIMERTRACE("canceling timer %p(%p)", wrap_timer, nt_timer); + /* disable timer before deleting so if it is periodic timer, it + * won't be re-armed after deleting */ + wrap_timer->repeat = 0; + ret = del_timer(&wrap_timer->timer); + /* the documentation for KeCancelTimer suggests the DPC is + * deqeued, but actually DPC is left to run */ + if (ret) + TIMEREXIT(return TRUE); + else + TIMEREXIT(return FALSE); +} + +wstdcall BOOLEAN WIN_FUNC(KeReadStateTimer,1) + (struct nt_timer *nt_timer) +{ + if (nt_timer->dh.signal_state) + return TRUE; + else + return FALSE; +} + +wstdcall void WIN_FUNC(KeInitializeDpc,3) + (struct kdpc *kdpc, void *func, void *ctx) +{ + ENTER3("%p, %p, %p", kdpc, func, ctx); + memset(kdpc, 0, sizeof(*kdpc)); + kdpc->func = func; + kdpc->ctx = ctx; + InitializeListHead(&kdpc->list); +} + +static void kdpc_worker(worker_param_t dummy) +{ + struct nt_list *entry; + struct kdpc *kdpc; + unsigned long flags; + KIRQL irql; + + WORKENTER(""); + irql = raise_irql(DISPATCH_LEVEL); + while (1) { + spin_lock_irqsave(&kdpc_list_lock, flags); + entry = RemoveHeadList(&kdpc_list); + if (entry) { + kdpc = container_of(entry, struct kdpc, list); + assert(kdpc->queued); + kdpc->queued = 0; + } else + kdpc = NULL; + spin_unlock_irqrestore(&kdpc_list_lock, flags); + if (!kdpc) + break; + WORKTRACE("%p, %p, %p, %p, %p", kdpc, kdpc->func, kdpc->ctx, + kdpc->arg1, kdpc->arg2); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN4(kdpc->func, kdpc, kdpc->ctx, kdpc->arg1, kdpc->arg2); + assert_irql(_irql_ == DISPATCH_LEVEL); + } + lower_irql(irql); + WORKEXIT(return); +} + +wstdcall void WIN_FUNC(KeFlushQueuedDpcs,0) + (void) +{ + kdpc_worker(NULL); +} + +BOOLEAN queue_kdpc(struct kdpc *kdpc) +{ + BOOLEAN ret; + unsigned long flags; + + WORKENTER("%p", kdpc); + spin_lock_irqsave(&kdpc_list_lock, flags); + if (kdpc->queued) + ret = FALSE; + else { + if (unlikely(kdpc->importance == HighImportance)) + InsertHeadList(&kdpc_list, &kdpc->list); + else + InsertTailList(&kdpc_list, &kdpc->list); + kdpc->queued = 1; + ret = TRUE; + } + spin_unlock_irqrestore(&kdpc_list_lock, flags); + if (ret == TRUE) + schedule_ntos_work(&kdpc_work); + WORKTRACE("%d", ret); + return ret; +} + +BOOLEAN dequeue_kdpc(struct kdpc *kdpc) +{ + BOOLEAN ret; + unsigned long flags; + + WORKENTER("%p", kdpc); + spin_lock_irqsave(&kdpc_list_lock, flags); + if (kdpc->queued) { + RemoveEntryList(&kdpc->list); + kdpc->queued = 0; + ret = TRUE; + } else + ret = FALSE; + spin_unlock_irqrestore(&kdpc_list_lock, flags); + WORKTRACE("%d", ret); + return ret; +} + +wstdcall BOOLEAN WIN_FUNC(KeInsertQueueDpc,3) + (struct kdpc *kdpc, void *arg1, void *arg2) +{ + WORKENTER("%p, %p, %p", kdpc, arg1, arg2); + kdpc->arg1 = arg1; + kdpc->arg2 = arg2; + return queue_kdpc(kdpc); +} + +wstdcall BOOLEAN WIN_FUNC(KeRemoveQueueDpc,1) + (struct kdpc *kdpc) +{ + return dequeue_kdpc(kdpc); +} + +wstdcall void WIN_FUNC(KeSetImportanceDpc,2) + (struct kdpc *kdpc, enum kdpc_importance importance) +{ + kdpc->importance = importance; +} + +static void ntos_work_worker(worker_param_t dummy) +{ + struct ntos_work_item *ntos_work_item; + struct nt_list *cur; + + while (1) { + spin_lock_bh(&ntos_work_lock); + cur = RemoveHeadList(&ntos_work_list); + spin_unlock_bh(&ntos_work_lock); + if (!cur) + break; + ntos_work_item = container_of(cur, struct ntos_work_item, list); + WORKTRACE("%p: executing %p, %p, %p", current, + ntos_work_item->func, ntos_work_item->arg1, + ntos_work_item->arg2); + LIN2WIN2(ntos_work_item->func, ntos_work_item->arg1, + ntos_work_item->arg2); + kfree(ntos_work_item); + } + WORKEXIT(return); +} + +int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2) +{ + struct ntos_work_item *ntos_work_item; + + WORKENTER("adding work: %p, %p, %p", func, arg1, arg2); + ntos_work_item = kmalloc(sizeof(*ntos_work_item), irql_gfp()); + if (!ntos_work_item) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + ntos_work_item->func = func; + ntos_work_item->arg1 = arg1; + ntos_work_item->arg2 = arg2; + spin_lock_bh(&ntos_work_lock); + InsertTailList(&ntos_work_list, &ntos_work_item->list); + spin_unlock_bh(&ntos_work_lock); + schedule_ntos_work(&ntos_work); + WORKEXIT(return 0); +} + +wstdcall void WIN_FUNC(KeInitializeSpinLock,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + nt_spin_lock_init(lock); +} + +wstdcall void WIN_FUNC(KeAcquireSpinLock,2) + (NT_SPIN_LOCK *lock, KIRQL *irql) +{ + ENTER6("%p", lock); + *irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL); +} + +wstdcall void WIN_FUNC(KeReleaseSpinLock,2) + (NT_SPIN_LOCK *lock, KIRQL oldirql) +{ + ENTER6("%p", lock); + nt_spin_unlock_irql(lock, oldirql); +} + +wstdcall void WIN_FUNC(KeAcquireSpinLockAtDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + nt_spin_lock(lock); +} + +wstdcall void WIN_FUNC(KeReleaseSpinLockFromDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + nt_spin_unlock(lock); +} + +wstdcall void WIN_FUNC(KeRaiseIrql,2) + (KIRQL newirql, KIRQL *oldirql) +{ + ENTER6("%d", newirql); + *oldirql = raise_irql(newirql); +} + +wstdcall KIRQL WIN_FUNC(KeRaiseIrqlToDpcLevel,0) + (void) +{ + return raise_irql(DISPATCH_LEVEL); +} + +wstdcall void WIN_FUNC(KeLowerIrql,1) + (KIRQL irql) +{ + ENTER6("%d", irql); + lower_irql(irql); +} + +wstdcall KIRQL WIN_FUNC(KeAcquireSpinLockRaiseToDpc,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + return nt_spin_lock_irql(lock, DISPATCH_LEVEL); +} + +#undef ExAllocatePoolWithTag + +wstdcall void *WIN_FUNC(ExAllocatePoolWithTag,3) + (enum pool_type pool_type, SIZE_T size, ULONG tag) +{ + void *addr; + + ENTER4("pool_type: %d, size: %lu, tag: 0x%x", pool_type, size, tag); + assert_irql(_irql_ <= DISPATCH_LEVEL); + if (size < PAGE_SIZE) + addr = kmalloc(size, irql_gfp()); + else { + if (irql_gfp() & GFP_ATOMIC) { + addr = __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, + PAGE_KERNEL); + TRACE1("%p, %lu", addr, size); + } else { + addr = vmalloc(size); + TRACE1("%p, %lu", addr, size); + } + } + DBG_BLOCK(1) { + if (addr) + TRACE4("addr: %p, %lu", addr, size); + else + TRACE1("failed: %lu", size); + } + return addr; +} +WIN_FUNC_DECL(ExAllocatePoolWithTag,3) + +wstdcall void WIN_FUNC(ExFreePoolWithTag,2) + (void *addr, ULONG tag) +{ + TRACE4("%p", addr); + if ((unsigned long)addr < VMALLOC_START || + (unsigned long)addr >= VMALLOC_END) + kfree(addr); + else + vfree(addr); + + EXIT4(return); +} + +wstdcall void WIN_FUNC(ExFreePool,1) + (void *addr) +{ + ExFreePoolWithTag(addr, 0); +} +WIN_FUNC_DECL(ExFreePool,1) + +wstdcall void WIN_FUNC(ExInitializeNPagedLookasideList,7) + (struct npaged_lookaside_list *lookaside, + LOOKASIDE_ALLOC_FUNC *alloc_func, LOOKASIDE_FREE_FUNC *free_func, + ULONG flags, SIZE_T size, ULONG tag, USHORT depth) +{ + ENTER3("lookaside: %p, size: %lu, flags: %u, head: %p, " + "alloc: %p, free: %p", lookaside, size, flags, + lookaside, alloc_func, free_func); + + memset(lookaside, 0, sizeof(*lookaside)); + + lookaside->size = size; + lookaside->tag = tag; + lookaside->depth = 4; + lookaside->maxdepth = 256; + lookaside->pool_type = NonPagedPool; + + if (alloc_func) + lookaside->alloc_func = alloc_func; + else + lookaside->alloc_func = WIN_FUNC_PTR(ExAllocatePoolWithTag,3); + if (free_func) + lookaside->free_func = free_func; + else + lookaside->free_func = WIN_FUNC_PTR(ExFreePool,1); + +#ifndef CONFIG_X86_64 + nt_spin_lock_init(&lookaside->obsolete); +#endif + EXIT3(return); +} + +wstdcall void WIN_FUNC(ExDeleteNPagedLookasideList,1) + (struct npaged_lookaside_list *lookaside) +{ + struct nt_slist *entry; + + ENTER3("lookaside = %p", lookaside); + while ((entry = ExpInterlockedPopEntrySList(&lookaside->head))) + LIN2WIN1(lookaside->free_func, entry); + EXIT3(return); +} + +#if defined(ALLOC_DEBUG) && ALLOC_DEBUG > 1 +#define ExAllocatePoolWithTag(pool_type, size, tag) \ + wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__) +#endif + +wstdcall NTSTATUS WIN_FUNC(ExCreateCallback,4) + (struct callback_object **object, struct object_attributes *attributes, + BOOLEAN create, BOOLEAN allow_multiple_callbacks) +{ + struct callback_object *obj; + + ENTER2(""); + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(obj, &callback_objects, callback_funcs) { + if (obj->attributes == attributes) { + spin_unlock_bh(&ntoskernel_lock); + *object = obj; + return STATUS_SUCCESS; + } + } + spin_unlock_bh(&ntoskernel_lock); + obj = allocate_object(sizeof(struct callback_object), + OBJECT_TYPE_CALLBACK, NULL); + if (!obj) + EXIT2(return STATUS_INSUFFICIENT_RESOURCES); + InitializeListHead(&obj->callback_funcs); + nt_spin_lock_init(&obj->lock); + obj->allow_multiple_callbacks = allow_multiple_callbacks; + obj->attributes = attributes; + *object = obj; + EXIT2(return STATUS_SUCCESS); +} + +wstdcall void *WIN_FUNC(ExRegisterCallback,3) + (struct callback_object *object, PCALLBACK_FUNCTION func, void *context) +{ + struct callback_func *callback; + KIRQL irql; + + ENTER2(""); + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + if (object->allow_multiple_callbacks == FALSE && + !IsListEmpty(&object->callback_funcs)) { + nt_spin_unlock_irql(&object->lock, irql); + EXIT2(return NULL); + } + nt_spin_unlock_irql(&object->lock, irql); + callback = kmalloc(sizeof(*callback), GFP_KERNEL); + if (!callback) { + ERROR("couldn't allocate memory"); + return NULL; + } + callback->func = func; + callback->context = context; + callback->object = object; + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + InsertTailList(&object->callback_funcs, &callback->list); + nt_spin_unlock_irql(&object->lock, irql); + EXIT2(return callback); +} + +wstdcall void WIN_FUNC(ExUnregisterCallback,1) + (struct callback_func *callback) +{ + struct callback_object *object; + KIRQL irql; + + ENTER3("%p", callback); + if (!callback) + return; + object = callback->object; + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + RemoveEntryList(&callback->list); + nt_spin_unlock_irql(&object->lock, irql); + kfree(callback); + return; +} + +wstdcall void WIN_FUNC(ExNotifyCallback,3) + (struct callback_object *object, void *arg1, void *arg2) +{ + struct callback_func *callback; + KIRQL irql; + + ENTER3("%p", object); + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + nt_list_for_each_entry(callback, &object->callback_funcs, list) { + LIN2WIN3(callback->func, callback->context, arg1, arg2); + } + nt_spin_unlock_irql(&object->lock, irql); + return; +} + +/* check and set signaled state; should be called with dispatcher_lock held */ +/* @grab indicates if the event should be grabbed or checked + * - note that a semaphore may stay in signaled state for multiple + * 'grabs' if the count is > 1 */ +static int grab_object(struct dispatcher_header *dh, + struct task_struct *thread, int grab) +{ + EVENTTRACE("%p, %p, %d, %d", dh, thread, grab, dh->signal_state); + if (unlikely(is_mutex_object(dh))) { + struct nt_mutex *nt_mutex; + nt_mutex = container_of(dh, struct nt_mutex, dh); + EVENTTRACE("%p, %p, %d, %p, %d", nt_mutex, + nt_mutex->owner_thread, dh->signal_state, + thread, grab); + /* either no thread owns the mutex or this thread owns + * it */ + assert(dh->signal_state == 1 && nt_mutex->owner_thread == NULL); + assert(dh->signal_state < 1 && nt_mutex->owner_thread != NULL); + if ((dh->signal_state == 1 && nt_mutex->owner_thread == NULL) || + nt_mutex->owner_thread == thread) { + if (grab) { + dh->signal_state--; + nt_mutex->owner_thread = thread; + } + EVENTEXIT(return 1); + } + } else if (dh->signal_state > 0) { + /* to grab, decrement signal_state for synchronization + * or semaphore objects */ + if (grab && (is_synch_object(dh) || is_semaphore_object(dh))) + dh->signal_state--; + EVENTEXIT(return 1); + } + EVENTEXIT(return 0); +} + +/* this function should be called holding dispatcher_lock */ +static void object_signalled(struct dispatcher_header *dh) +{ + struct nt_list *cur, *next; + struct wait_block *wb; + + EVENTENTER("%p", dh); + nt_list_for_each_safe(cur, next, &dh->wait_blocks) { + wb = container_of(cur, struct wait_block, list); + assert(wb->thread != NULL); + assert(wb->object == NULL); + if (!grab_object(dh, wb->thread, 1)) + continue; + EVENTTRACE("%p (%p): waking %p", dh, wb, wb->thread); + RemoveEntryList(cur); + wb->object = dh; + *(wb->wait_done) = 1; + wake_up_process(wb->thread); + } + EVENTEXIT(return); +} + +wstdcall NTSTATUS WIN_FUNC(KeWaitForMultipleObjects,8) + (ULONG count, void *object[], enum wait_type wait_type, + KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode, + BOOLEAN alertable, LARGE_INTEGER *timeout, + struct wait_block *wait_block_array) +{ + int i, res = 0, wait_count, wait_done; + typeof(jiffies) wait_hz = 0; + struct wait_block *wb, wb_array[THREAD_WAIT_OBJECTS]; + struct dispatcher_header *dh; + + EVENTENTER("%p, %d, %u, %p", current, count, wait_type, timeout); + + if (count > MAX_WAIT_OBJECTS || + (count > THREAD_WAIT_OBJECTS && wait_block_array == NULL)) + EVENTEXIT(return STATUS_INVALID_PARAMETER); + + if (wait_block_array == NULL) + wb = wb_array; + else + wb = wait_block_array; + + /* If *timeout == 0: In the case of WaitAny, if an object can + * be grabbed (object is in signaled state), grab and + * return. In the case of WaitAll, we have to first make sure + * all objects can be grabbed. If any/some of them can't be + * grabbed, either we return STATUS_TIMEOUT or wait for them, + * depending on how to satisfy wait. If all of them can be + * grabbed, we will grab them in the next loop below */ + + spin_lock_bh(&dispatcher_lock); + for (i = wait_count = 0; i < count; i++) { + dh = object[i]; + EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state); + /* wait_type == 1 for WaitAny, 0 for WaitAll */ + if (grab_object(dh, current, wait_type)) { + if (wait_type == WaitAny) { + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return STATUS_WAIT_0 + i); + } + } else { + EVENTTRACE("%p: wait for %p", current, dh); + wait_count++; + } + } + + if (timeout && *timeout == 0 && wait_count) { + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return STATUS_TIMEOUT); + } + + /* get the list of objects the thread needs to wait on and add + * the thread on the wait list for each such object */ + /* if *timeout == 0, this step will grab all the objects */ + wait_done = 0; + for (i = 0; i < count; i++) { + dh = object[i]; + EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state); + wb[i].object = NULL; + if (grab_object(dh, current, 1)) { + EVENTTRACE("%p: no wait for %p (%d)", + current, dh, dh->signal_state); + /* mark that we are not waiting on this object */ + wb[i].thread = NULL; + } else { + wb[i].wait_done = &wait_done; + wb[i].thread = current; + EVENTTRACE("%p: wait for %p", current, dh); + InsertTailList(&dh->wait_blocks, &wb[i].list); + } + } + spin_unlock_bh(&dispatcher_lock); + if (wait_count == 0) + EVENTEXIT(return STATUS_SUCCESS); + + assert(timeout == NULL || *timeout != 0); + if (timeout == NULL) + wait_hz = 0; + else + wait_hz = SYSTEM_TIME_TO_HZ(*timeout); + + DBG_BLOCK(2) { + KIRQL irql = current_irql(); + if (irql >= DISPATCH_LEVEL) { + TRACE2("wait in atomic context: %lu, %d, %ld", + wait_hz, in_atomic(), in_interrupt()); + } + } + assert_irql(_irql_ < DISPATCH_LEVEL); + EVENTTRACE("%p: sleep for %ld on %p", current, wait_hz, &wait_done); + /* we don't honor 'alertable' - according to decription for + * this, even if waiting in non-alertable state, thread may be + * alerted in some circumstances */ + while (wait_count) { + res = wait_condition(wait_done, wait_hz, TASK_INTERRUPTIBLE); + spin_lock_bh(&dispatcher_lock); + EVENTTRACE("%p woke up: %d, %d", current, res, wait_done); + /* the event may have been set by the time + * wrap_wait_event returned and spinlock obtained, so + * don't rely on value of 'res' - check event status */ + if (!wait_done) { + assert(res <= 0); + /* timed out or interrupted; remove from wait list */ + for (i = 0; i < count; i++) { + if (!wb[i].thread) + continue; + EVENTTRACE("%p: timedout, dequeue %p (%p)", + current, object[i], wb[i].object); + assert(wb[i].object == NULL); + RemoveEntryList(&wb[i].list); + } + spin_unlock_bh(&dispatcher_lock); + if (res < 0) + EVENTEXIT(return STATUS_ALERTED); + else + EVENTEXIT(return STATUS_TIMEOUT); + } + assert(res > 0); + /* woken because object(s) signalled */ + for (i = 0; wait_count && i < count; i++) { + if (!wb[i].thread || !wb[i].object) + continue; + DBG_BLOCK(1) { + if (wb[i].object != object[i]) { + EVENTTRACE("oops %p != %p", + wb[i].object, object[i]); + continue; + } + } + wait_count--; + if (wait_type == WaitAny) { + int j; + /* done; remove from rest of wait list */ + for (j = i + 1; j < count; j++) { + if (wb[j].thread && !wb[j].object) + RemoveEntryList(&wb[j].list); + } + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return STATUS_WAIT_0 + i); + } + } + wait_done = 0; + spin_unlock_bh(&dispatcher_lock); + if (wait_count == 0) + EVENTEXIT(return STATUS_SUCCESS); + + /* this thread is still waiting for more objects, so + * let it wait for remaining time and those objects */ + if (timeout) + wait_hz = res; + else + wait_hz = 0; + } + /* should never reach here, but compiler wants return value */ + ERROR("%p: wait_hz: %ld", current, wait_hz); + EVENTEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(KeWaitForSingleObject,5) + (void *object, KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode, + BOOLEAN alertable, LARGE_INTEGER *timeout) +{ + return KeWaitForMultipleObjects(1, &object, WaitAny, wait_reason, + wait_mode, alertable, timeout, NULL); +} + +wstdcall void WIN_FUNC(KeInitializeEvent,3) + (struct nt_event *nt_event, enum event_type type, BOOLEAN state) +{ + EVENTENTER("event = %p, type = %d, state = %d", nt_event, type, state); + initialize_object(&nt_event->dh, type, state); + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeSetEvent,3) + (struct nt_event *nt_event, KPRIORITY incr, BOOLEAN wait) +{ + LONG old_state; + + EVENTENTER("%p, %d", nt_event, nt_event->dh.type); + if (wait == TRUE) + WARNING("wait = %d, not yet implemented", wait); + spin_lock_bh(&dispatcher_lock); + old_state = nt_event->dh.signal_state; + nt_event->dh.signal_state = 1; + if (old_state == 0) + object_signalled(&nt_event->dh); + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return old_state); +} + +wstdcall void WIN_FUNC(KeClearEvent,1) + (struct nt_event *nt_event) +{ + EVENTENTER("%p", nt_event); + nt_event->dh.signal_state = 0; + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeResetEvent,1) + (struct nt_event *nt_event) +{ + LONG old_state; + + EVENTENTER("%p", nt_event); + old_state = xchg(&nt_event->dh.signal_state, 0); + EVENTEXIT(return old_state); +} + +wstdcall LONG WIN_FUNC(KeReadStateEvent,1) + (struct nt_event *nt_event) +{ + LONG state; + + state = nt_event->dh.signal_state; + EVENTTRACE("%d", state); + return state; +} + +wstdcall void WIN_FUNC(KeInitializeMutex,2) + (struct nt_mutex *mutex, ULONG level) +{ + EVENTENTER("%p", mutex); + initialize_object(&mutex->dh, MutexObject, 1); + mutex->dh.size = sizeof(*mutex); + InitializeListHead(&mutex->list); + mutex->abandoned = FALSE; + mutex->apc_disable = 1; + mutex->owner_thread = NULL; + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeReleaseMutex,2) + (struct nt_mutex *mutex, BOOLEAN wait) +{ + LONG ret; + struct task_struct *thread; + + EVENTENTER("%p, %d, %p", mutex, wait, current); + if (wait == TRUE) + WARNING("wait: %d", wait); + thread = current; + spin_lock_bh(&dispatcher_lock); + EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread, + mutex->dh.signal_state); + if ((mutex->owner_thread == thread) && (mutex->dh.signal_state <= 0)) { + ret = mutex->dh.signal_state++; + if (ret == 0) { + mutex->owner_thread = NULL; + object_signalled(&mutex->dh); + } + } else { + ret = STATUS_MUTANT_NOT_OWNED; + WARNING("invalid mutex: %p, %p, %p", mutex, mutex->owner_thread, + thread); + } + EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread, + mutex->dh.signal_state); + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return ret); +} + +wstdcall void WIN_FUNC(KeInitializeSemaphore,3) + (struct nt_semaphore *semaphore, LONG count, LONG limit) +{ + EVENTENTER("%p: %d", semaphore, count); + /* if limit > 1, we need to satisfy as many waits (until count + * becomes 0); so we keep decrementing count everytime a wait + * is satisified */ + initialize_object(&semaphore->dh, SemaphoreObject, count); + semaphore->dh.size = sizeof(*semaphore); + semaphore->limit = limit; + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeReleaseSemaphore,4) + (struct nt_semaphore *semaphore, KPRIORITY incr, LONG adjustment, + BOOLEAN wait) +{ + LONG ret; + + EVENTENTER("%p", semaphore); + spin_lock_bh(&dispatcher_lock); + ret = semaphore->dh.signal_state; + assert(ret >= 0); + if (semaphore->dh.signal_state + adjustment <= semaphore->limit) + semaphore->dh.signal_state += adjustment; + else { + WARNING("releasing %d over limit %d", adjustment, + semaphore->limit); + semaphore->dh.signal_state = semaphore->limit; + } + if (semaphore->dh.signal_state > 0) + object_signalled(&semaphore->dh); + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return ret); +} + +wstdcall NTSTATUS WIN_FUNC(KeDelayExecutionThread,3) + (KPROCESSOR_MODE wait_mode, BOOLEAN alertable, LARGE_INTEGER *interval) +{ + int res; + long timeout; + + if (wait_mode != 0) + ERROR("invalid wait_mode %d", wait_mode); + + timeout = SYSTEM_TIME_TO_HZ(*interval); + EVENTTRACE("%p, %Ld, %ld", current, *interval, timeout); + if (timeout <= 0) + EVENTEXIT(return STATUS_SUCCESS); + + if (alertable) + set_current_state(TASK_INTERRUPTIBLE); + else + set_current_state(TASK_UNINTERRUPTIBLE); + + res = schedule_timeout(timeout); + EVENTTRACE("%p, %d", current, res); + if (res == 0) + EVENTEXIT(return STATUS_SUCCESS); + else + EVENTEXIT(return STATUS_ALERTED); +} + +wstdcall ULONGLONG WIN_FUNC(KeQueryInterruptTime,0) + (void) +{ + EXIT5(return jiffies * TICKSPERJIFFY); +} + +wstdcall ULONG WIN_FUNC(KeQueryTimeIncrement,0) + (void) +{ + EXIT5(return TICKSPERSEC / HZ); +} + +wstdcall void WIN_FUNC(KeQuerySystemTime,1) + (LARGE_INTEGER *time) +{ + *time = ticks_1601(); + TRACE5("%Lu, %lu", *time, jiffies); +} + +wstdcall void WIN_FUNC(KeQueryTickCount,1) + (LARGE_INTEGER *count) +{ + *count = jiffies; +} + +wstdcall LARGE_INTEGER WIN_FUNC(KeQueryPerformanceCounter,1) + (LARGE_INTEGER *counter) +{ + if (counter) + *counter = HZ; + return jiffies; +} + +wstdcall KAFFINITY WIN_FUNC(KeQueryActiveProcessors,0) + (void) +{ + int i, n; + KAFFINITY bits = 0; +#ifdef num_online_cpus + n = num_online_cpus(); +#else + n = NR_CPUS; +#endif + for (i = 0; i < n; i++) + bits = (bits << 1) | 1; + return bits; +} + +struct nt_thread *get_current_nt_thread(void) +{ + struct task_struct *task = current; + struct nt_thread *thread; + struct common_object_header *header; + + TRACE6("task: %p", task); + thread = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(header, &object_list, list) { + TRACE6("%p, %d", header, header->type); + if (header->type != OBJECT_TYPE_NT_THREAD) + break; + thread = HEADER_TO_OBJECT(header); + TRACE6("%p, %p", thread, thread->task); + if (thread->task == task) + break; + else + thread = NULL; + } + spin_unlock_bh(&ntoskernel_lock); + if (thread == NULL) + TRACE4("couldn't find thread for task %p, %d", task, task->pid); + TRACE6("%p", thread); + return thread; +} + +static struct task_struct *get_nt_thread_task(struct nt_thread *thread) +{ + struct task_struct *task; + struct common_object_header *header; + + TRACE6("%p", thread); + task = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(header, &object_list, list) { + TRACE6("%p, %d", header, header->type); + if (header->type != OBJECT_TYPE_NT_THREAD) + break; + if (thread == HEADER_TO_OBJECT(header)) { + task = thread->task; + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + if (task == NULL) + TRACE2("%p: couldn't find task for %p", current, thread); + return task; +} + +static struct nt_thread *create_nt_thread(struct task_struct *task) +{ + struct nt_thread *thread; + thread = allocate_object(sizeof(*thread), OBJECT_TYPE_NT_THREAD, NULL); + if (!thread) { + ERROR("couldn't allocate thread object"); + EXIT2(return NULL); + } + thread->task = task; + if (task) + thread->pid = task->pid; + else + thread->pid = 0; + nt_spin_lock_init(&thread->lock); + InitializeListHead(&thread->irps); + initialize_object(&thread->dh, ThreadObject, 0); + thread->dh.size = sizeof(*thread); + thread->prio = LOW_PRIORITY; + return thread; +} + +wstdcall struct nt_thread *WIN_FUNC(KeGetCurrentThread,0) + (void) +{ + struct nt_thread *thread = get_current_nt_thread(); + TRACE2("%p, %p", thread, current); + return thread; +} + +wstdcall KPRIORITY WIN_FUNC(KeQueryPriorityThread,1) + (struct nt_thread *thread) +{ + KPRIORITY prio; + struct task_struct *task; + + TRACE2("%p", thread); +#ifdef CONFIG_X86_64 + /* sis163u driver for amd64 passes 0x1f from thread created by + * PsCreateSystemThread - no idea what is 0x1f */ + if (thread == (void *)0x1f) + thread = get_current_nt_thread(); +#endif + if (!thread) { + TRACE2("invalid thread"); + EXIT2(return LOW_REALTIME_PRIORITY); + } + task = get_nt_thread_task(thread); + if (!task) { + TRACE2("couldn't find task for thread: %p", thread); + EXIT2(return LOW_REALTIME_PRIORITY); + } + + prio = thread->prio; + + TRACE2("%d", prio); + return prio; +} + +wstdcall KPRIORITY WIN_FUNC(KeSetPriorityThread,2) + (struct nt_thread *thread, KPRIORITY prio) +{ + KPRIORITY old_prio; + struct task_struct *task; + + TRACE2("thread: %p, priority = %u", thread, prio); +#ifdef CONFIG_X86_64 + if (thread == (void *)0x1f) + thread = get_current_nt_thread(); +#endif + if (!thread) { + TRACE2("invalid thread"); + EXIT2(return LOW_REALTIME_PRIORITY); + } + task = get_nt_thread_task(thread); + if (!task) { + TRACE2("couldn't find task for thread: %p", thread); + EXIT2(return LOW_REALTIME_PRIORITY); + } + + old_prio = thread->prio; + thread->prio = prio; + + TRACE2("%d, %d", old_prio, thread->prio); + return old_prio; +} + +struct thread_trampoline { + void (*func)(void *) wstdcall; + void *ctx; + struct nt_thread *thread; + struct completion started; +}; + +static int ntdriver_thread(void *data) +{ + struct thread_trampoline *thread_tramp = data; + /* yes, a tramp! */ + typeof(thread_tramp->func) func = thread_tramp->func; + typeof(thread_tramp->ctx) ctx = thread_tramp->ctx; + + thread_tramp->thread->task = current; + thread_tramp->thread->pid = current->pid; + TRACE2("thread: %p, task: %p (%d)", thread_tramp->thread, + current, current->pid); + complete(&thread_tramp->started); + +#ifdef PF_NOFREEZE + current->flags |= PF_NOFREEZE; +#endif + strncpy(current->comm, "ntdriver", sizeof(current->comm)); + current->comm[sizeof(current->comm)-1] = 0; + LIN2WIN1(func, ctx); + ERROR("task: %p", current); + return 0; +} + +wstdcall NTSTATUS WIN_FUNC(PsCreateSystemThread,7) + (void **handle, ULONG access, void *obj_attr, void *process, + void *client_id, void (*func)(void *) wstdcall, void *ctx) +{ + struct thread_trampoline thread_tramp; + + ENTER2("handle = %p, access = %u, obj_attr = %p, process = %p, " + "client_id = %p, func = %p, context = %p", handle, access, + obj_attr, process, client_id, func, ctx); + + thread_tramp.thread = create_nt_thread(NULL); + if (!thread_tramp.thread) { + ERROR("couldn't allocate thread object"); + EXIT2(return STATUS_RESOURCES); + } + TRACE2("thread: %p", thread_tramp.thread); + thread_tramp.func = func; + thread_tramp.ctx = ctx; + init_completion(&thread_tramp.started); + + thread_tramp.thread->task = kthread_run(ntdriver_thread, + &thread_tramp, "ntdriver"); + if (IS_ERR(thread_tramp.thread->task)) { + free_object(thread_tramp.thread); + EXIT2(return STATUS_FAILURE); + } + TRACE2("created task: %p", thread_tramp.thread->task); + + wait_for_completion(&thread_tramp.started); + *handle = OBJECT_TO_HEADER(thread_tramp.thread); + TRACE2("created thread: %p, %p", thread_tramp.thread, *handle); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(PsTerminateSystemThread,1) + (NTSTATUS status) +{ + struct nt_thread *thread; + + TRACE2("%p, %08X", current, status); + thread = get_current_nt_thread(); + TRACE2("%p", thread); + if (thread) { + KeSetEvent((struct nt_event *)&thread->dh, 0, FALSE); + while (1) { + struct nt_list *ent; + struct irp *irp; + KIRQL irql; + irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL); + ent = RemoveHeadList(&thread->irps); + nt_spin_unlock_irql(&thread->lock, irql); + if (!ent) + break; + irp = container_of(ent, struct irp, thread_list); + IOTRACE("%p", irp); + IoCancelIrp(irp); + } + /* the driver may later query this status with + * ZwQueryInformationThread */ + thread->status = status; + } else + ERROR("couldn't find thread for task: %p", current); + + complete_and_exit(NULL, status); + ERROR("oops: %p, %d", thread->task, thread->pid); + return STATUS_FAILURE; +} + +wstdcall BOOLEAN WIN_FUNC(KeRemoveEntryDeviceQueue,2) + (struct kdevice_queue *dev_queue, struct kdevice_queue_entry *entry) +{ + struct kdevice_queue_entry *e; + KIRQL irql; + + irql = nt_spin_lock_irql(&dev_queue->lock, DISPATCH_LEVEL); + nt_list_for_each_entry(e, &dev_queue->list, list) { + if (e == entry) { + RemoveEntryList(&e->list); + nt_spin_unlock_irql(&dev_queue->lock, irql); + return TRUE; + } + } + nt_spin_unlock_irql(&dev_queue->lock, irql); + return FALSE; +} + +wstdcall BOOLEAN WIN_FUNC(KeSynchronizeExecution,3) + (struct kinterrupt *interrupt, PKSYNCHRONIZE_ROUTINE synch_routine, + void *ctx) +{ + BOOLEAN ret; + unsigned long flags; + + nt_spin_lock_irqsave(interrupt->actual_lock, flags); + ret = LIN2WIN1(synch_routine, ctx); + nt_spin_unlock_irqrestore(interrupt->actual_lock, flags); + TRACE6("%d", ret); + return ret; +} + +wstdcall void *WIN_FUNC(MmAllocateContiguousMemorySpecifyCache,5) + (SIZE_T size, PHYSICAL_ADDRESS lowest, PHYSICAL_ADDRESS highest, + PHYSICAL_ADDRESS boundary, enum memory_caching_type cache_type) +{ + void *addr; + gfp_t flags; + + ENTER2("%lu, 0x%lx, 0x%lx, 0x%lx, %d", size, (long)lowest, + (long)highest, (long)boundary, cache_type); + flags = irql_gfp(); + addr = wrap_get_free_pages(flags, size); + TRACE2("%p, %lu, 0x%x", addr, size, flags); + if (addr && ((virt_to_phys(addr) + size) <= highest)) + EXIT2(return addr); +#ifdef CONFIG_X86_64 + /* GFP_DMA is really only 16MB even on x86-64, but there is no + * other zone available */ + if (highest <= DMA_31BIT_MASK) + flags |= __GFP_DMA; + else if (highest <= DMA_32BIT_MASK) + flags |= __GFP_DMA32; +#else + if (highest <= DMA_24BIT_MASK) + flags |= __GFP_DMA; + else if (highest > DMA_30BIT_MASK) + flags |= __GFP_HIGHMEM; +#endif + addr = wrap_get_free_pages(flags, size); + TRACE2("%p, %lu, 0x%x", addr, size, flags); + return addr; +} + +wstdcall void WIN_FUNC(MmFreeContiguousMemorySpecifyCache,3) + (void *base, SIZE_T size, enum memory_caching_type cache_type) +{ + TRACE2("%p, %lu", base, size); + free_pages((unsigned long)base, get_order(size)); +} + +wstdcall PHYSICAL_ADDRESS WIN_FUNC(MmGetPhysicalAddress,1) + (void *base) +{ + unsigned long phy = virt_to_phys(base); + TRACE2("%p, %p", base, (void *)phy); + return phy; +} + +/* Atheros card with pciid 168C:0014 calls this function with 0xf0000 + * and 0xf6ef0 address, and then check for things that seem to be + * related to ACPI: "_SM_" and "_DMI_". This may be the hack they do + * to check if this card is installed in IBM thinkpads; we can + * probably get this device to work if we create a buffer with the + * strings as required by the driver and return virtual address for + * that address instead */ +wstdcall void __iomem *WIN_FUNC(MmMapIoSpace,3) + (PHYSICAL_ADDRESS phys_addr, SIZE_T size, + enum memory_caching_type cache) +{ + void __iomem *virt; + ENTER1("cache type: %d", cache); + if (cache == MmCached) + virt = ioremap(phys_addr, size); + else + virt = ioremap_nocache(phys_addr, size); + TRACE1("%Lx, %lu, %p", phys_addr, size, virt); + return virt; +} + +wstdcall void WIN_FUNC(MmUnmapIoSpace,2) + (void __iomem *addr, SIZE_T size) +{ + ENTER1("%p, %lu", addr, size); + iounmap(addr); + return; +} + +wstdcall ULONG WIN_FUNC(MmSizeOfMdl,2) + (void *base, ULONG length) +{ + return (sizeof(struct mdl) + + (sizeof(PFN_NUMBER) * SPAN_PAGES(base, length))); +} + +struct mdl *allocate_init_mdl(void *virt, ULONG length) +{ + struct wrap_mdl *wrap_mdl; + struct mdl *mdl; + int mdl_size = MmSizeOfMdl(virt, length); + + if (mdl_size <= MDL_CACHE_SIZE) { + wrap_mdl = kmem_cache_alloc(mdl_cache, irql_gfp()); + if (!wrap_mdl) + return NULL; + spin_lock_bh(&dispatcher_lock); + InsertHeadList(&wrap_mdl_list, &wrap_mdl->list); + spin_unlock_bh(&dispatcher_lock); + mdl = wrap_mdl->mdl; + TRACE3("allocated mdl from cache: %p(%p), %p(%d)", + wrap_mdl, mdl, virt, length); + memset(mdl, 0, MDL_CACHE_SIZE); + MmInitializeMdl(mdl, virt, length); + /* mark the MDL as allocated from cache pool so when + * it is freed, we free it back to the pool */ + mdl->flags = MDL_ALLOCATED_FIXED_SIZE | MDL_CACHE_ALLOCATED; + } else { + wrap_mdl = + kmalloc(sizeof(*wrap_mdl) + mdl_size, irql_gfp()); + if (!wrap_mdl) + return NULL; + mdl = wrap_mdl->mdl; + TRACE3("allocated mdl from memory: %p(%p), %p(%d)", + wrap_mdl, mdl, virt, length); + spin_lock_bh(&dispatcher_lock); + InsertHeadList(&wrap_mdl_list, &wrap_mdl->list); + spin_unlock_bh(&dispatcher_lock); + memset(mdl, 0, mdl_size); + MmInitializeMdl(mdl, virt, length); + mdl->flags = MDL_ALLOCATED_FIXED_SIZE; + } + return mdl; +} + +void free_mdl(struct mdl *mdl) +{ + /* A driver may allocate Mdl with NdisAllocateBuffer and free + * with IoFreeMdl (e.g., 64-bit Broadcom). Since we need to + * treat buffers allocated with Ndis calls differently, we + * must call NdisFreeBuffer if it is allocated with Ndis + * function. We set 'pool' field in Ndis functions. */ + if (!mdl) + return; + if (mdl->pool) + NdisFreeBuffer(mdl); + else { + struct wrap_mdl *wrap_mdl = (struct wrap_mdl *) + ((char *)mdl - offsetof(struct wrap_mdl, mdl)); + spin_lock_bh(&dispatcher_lock); + RemoveEntryList(&wrap_mdl->list); + spin_unlock_bh(&dispatcher_lock); + + if (mdl->flags & MDL_CACHE_ALLOCATED) { + TRACE3("freeing mdl cache: %p, %p, %p", + wrap_mdl, mdl, mdl->mappedsystemva); + kmem_cache_free(mdl_cache, wrap_mdl); + } else { + TRACE3("freeing mdl: %p, %p, %p", + wrap_mdl, mdl, mdl->mappedsystemva); + kfree(wrap_mdl); + } + } + return; +} + +wstdcall void WIN_FUNC(IoBuildPartialMdl,4) + (struct mdl *source, struct mdl *target, void *virt, ULONG length) +{ + MmInitializeMdl(target, virt, length); + target->flags |= MDL_PARTIAL; +} + +wstdcall void WIN_FUNC(MmBuildMdlForNonPagedPool,1) + (struct mdl *mdl) +{ + PFN_NUMBER *mdl_pages; + int i, n; + + ENTER4("%p", mdl); + /* already mapped */ +// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl); + mdl->flags |= MDL_SOURCE_IS_NONPAGED_POOL; + TRACE4("%p, %p, %p, %d, %d", mdl, mdl->mappedsystemva, mdl->startva, + mdl->byteoffset, mdl->bytecount); + n = SPAN_PAGES(MmGetSystemAddressForMdl(mdl), MmGetMdlByteCount(mdl)); + if (n > MDL_CACHE_PAGES) + WARNING("%p, %d, %d", MmGetSystemAddressForMdl(mdl), + MmGetMdlByteCount(mdl), n); + mdl_pages = MmGetMdlPfnArray(mdl); + for (i = 0; i < n; i++) + mdl_pages[i] = (ULONG_PTR)mdl->startva + (i * PAGE_SIZE); + EXIT4(return); +} + +wstdcall void *WIN_FUNC(MmMapLockedPages,2) + (struct mdl *mdl, KPROCESSOR_MODE access_mode) +{ + /* already mapped */ +// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl); + mdl->flags |= MDL_MAPPED_TO_SYSTEM_VA; + /* what is the need for MDL_PARTIAL_HAS_BEEN_MAPPED? */ + if (mdl->flags & MDL_PARTIAL) + mdl->flags |= MDL_PARTIAL_HAS_BEEN_MAPPED; + return mdl->mappedsystemva; +} + +wstdcall void *WIN_FUNC(MmMapLockedPagesSpecifyCache,6) + (struct mdl *mdl, KPROCESSOR_MODE access_mode, + enum memory_caching_type cache_type, void *base_address, + ULONG bug_check, enum mm_page_priority priority) +{ + return MmMapLockedPages(mdl, access_mode); +} + +wstdcall void WIN_FUNC(MmUnmapLockedPages,2) + (void *base, struct mdl *mdl) +{ + mdl->flags &= ~MDL_MAPPED_TO_SYSTEM_VA; + return; +} + +wstdcall void WIN_FUNC(MmProbeAndLockPages,3) + (struct mdl *mdl, KPROCESSOR_MODE access_mode, + enum lock_operation operation) +{ + /* already locked */ + mdl->flags |= MDL_PAGES_LOCKED; + return; +} + +wstdcall void WIN_FUNC(MmUnlockPages,1) + (struct mdl *mdl) +{ + mdl->flags &= ~MDL_PAGES_LOCKED; + return; +} + +wstdcall BOOLEAN WIN_FUNC(MmIsAddressValid,1) + (void *virt_addr) +{ + if (virt_addr_valid(virt_addr)) + return TRUE; + else + return FALSE; +} + +wstdcall void *WIN_FUNC(MmLockPagableDataSection,1) + (void *address) +{ + return address; +} + +wstdcall void WIN_FUNC(MmUnlockPagableImageSection,1) + (void *handle) +{ + return; +} + +wstdcall NTSTATUS WIN_FUNC(ObReferenceObjectByHandle,6) + (void *handle, ACCESS_MASK desired_access, void *obj_type, + KPROCESSOR_MODE access_mode, void **object, void *handle_info) +{ + struct common_object_header *hdr; + + TRACE2("%p", handle); + hdr = HANDLE_TO_HEADER(handle); + atomic_inc_var(hdr->ref_count); + *object = HEADER_TO_OBJECT(hdr); + TRACE2("%p, %p, %d, %p", hdr, object, hdr->ref_count, *object); + return STATUS_SUCCESS; +} + +/* DDK doesn't say if return value should be before incrementing or + * after incrementing reference count, but according to #reactos + * devels, it should be return value after incrementing */ +wfastcall LONG WIN_FUNC(ObfReferenceObject,1) + (void *object) +{ + struct common_object_header *hdr; + LONG ret; + + hdr = OBJECT_TO_HEADER(object); + ret = post_atomic_add(hdr->ref_count, 1); + TRACE2("%p, %d, %p", hdr, hdr->ref_count, object); + return ret; +} + +static int dereference_object(void *object) +{ + struct common_object_header *hdr; + int ref_count; + + ENTER2("object: %p", object); + hdr = OBJECT_TO_HEADER(object); + TRACE2("hdr: %p", hdr); + ref_count = post_atomic_add(hdr->ref_count, -1); + TRACE2("object: %p, %d", object, ref_count); + if (ref_count < 0) + ERROR("invalid object: %p (%d)", object, ref_count); + if (ref_count <= 0) { + free_object(object); + return 1; + } else + return 0; +} + +wfastcall void WIN_FUNC(ObfDereferenceObject,1) + (void *object) +{ + TRACE2("%p", object); + dereference_object(object); +} + +wstdcall NTSTATUS WIN_FUNC(ZwCreateFile,11) + (void **handle, ACCESS_MASK access_mask, + struct object_attributes *obj_attr, struct io_status_block *iosb, + LARGE_INTEGER *size, ULONG file_attr, ULONG share_access, + ULONG create_disposition, ULONG create_options, void *ea_buffer, + ULONG ea_length) +{ + struct common_object_header *coh; + struct file_object *fo; + struct ansi_string ansi; + struct wrap_bin_file *bin_file; + char *file_basename; + NTSTATUS status; + + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(coh, &object_list, list) { + if (coh->type != OBJECT_TYPE_FILE) + continue; + /* TODO: check if file is opened in shared mode */ + if (!RtlCompareUnicodeString(&coh->name, obj_attr->name, TRUE)) { + fo = HEADER_TO_OBJECT(coh); + bin_file = fo->wrap_bin_file; + *handle = coh; + spin_unlock_bh(&ntoskernel_lock); + ObReferenceObject(fo); + iosb->status = FILE_OPENED; + iosb->info = bin_file->size; + EXIT2(return STATUS_SUCCESS); + } + } + spin_unlock_bh(&ntoskernel_lock); + + if (RtlUnicodeStringToAnsiString(&ansi, obj_attr->name, TRUE) != + STATUS_SUCCESS) + EXIT2(return STATUS_INSUFFICIENT_RESOURCES); + + file_basename = strrchr(ansi.buf, '\\'); + if (file_basename) + file_basename++; + else + file_basename = ansi.buf; + TRACE2("file: '%s', '%s'", ansi.buf, file_basename); + + fo = allocate_object(sizeof(struct file_object), OBJECT_TYPE_FILE, + obj_attr->name); + if (!fo) { + RtlFreeAnsiString(&ansi); + iosb->status = STATUS_INSUFFICIENT_RESOURCES; + iosb->info = 0; + EXIT2(return STATUS_FAILURE); + } + coh = OBJECT_TO_HEADER(fo); + bin_file = get_bin_file(file_basename); + if (bin_file) { + TRACE2("%s, %s", bin_file->name, file_basename); + fo->flags = FILE_OPENED; + } else if (access_mask & FILE_WRITE_DATA) { + bin_file = kzalloc(sizeof(*bin_file), GFP_KERNEL); + if (bin_file) { + strncpy(bin_file->name, file_basename, + sizeof(bin_file->name)); + bin_file->name[sizeof(bin_file->name)-1] = 0; + bin_file->data = vmalloc(*size); + if (bin_file->data) { + memset(bin_file->data, 0, *size); + bin_file->size = *size; + fo->flags = FILE_CREATED; + } else { + kfree(bin_file); + bin_file = NULL; + } + } + } else + bin_file = NULL; + + RtlFreeAnsiString(&ansi); + if (!bin_file) { + iosb->status = FILE_DOES_NOT_EXIST; + iosb->info = 0; + free_object(fo); + EXIT2(return STATUS_FAILURE); + } + + fo->wrap_bin_file = bin_file; + fo->current_byte_offset = 0; + if (access_mask & FILE_READ_DATA) + fo->read_access = TRUE; + if (access_mask & FILE_WRITE_DATA) + fo->write_access = TRUE; + iosb->status = FILE_OPENED; + iosb->info = bin_file->size; + *handle = coh; + TRACE2("handle: %p", *handle); + status = STATUS_SUCCESS; + EXIT2(return status); +} + +wstdcall NTSTATUS WIN_FUNC(ZwOpenFile,6) + (void **handle, ACCESS_MASK access_mask, + struct object_attributes *obj_attr, struct io_status_block *iosb, + ULONG share_access, ULONG open_options) +{ + LARGE_INTEGER size; + return ZwCreateFile(handle, access_mask, obj_attr, iosb, &size, 0, + share_access, 0, open_options, NULL, 0); +} + +wstdcall NTSTATUS WIN_FUNC(ZwReadFile,9) + (void *handle, struct nt_event *event, void *apc_routine, + void *apc_context, struct io_status_block *iosb, void *buffer, + ULONG length, LARGE_INTEGER *byte_offset, ULONG *key) +{ + struct file_object *fo; + struct common_object_header *coh; + ULONG count; + size_t offset; + struct wrap_bin_file *file; + + TRACE2("%p", handle); + coh = handle; + if (coh->type != OBJECT_TYPE_FILE) { + ERROR("handle %p is invalid: %d", handle, coh->type); + EXIT2(return STATUS_FAILURE); + } + fo = HANDLE_TO_OBJECT(coh); + file = fo->wrap_bin_file; + TRACE2("file: %s (%zu)", file->name, file->size); + spin_lock_bh(&ntoskernel_lock); + if (byte_offset) + offset = *byte_offset; + else + offset = fo->current_byte_offset; + count = min((size_t)length, file->size - offset); + TRACE2("count: %u, offset: %zu, length: %u", count, offset, length); + memcpy(buffer, ((void *)file->data) + offset, count); + fo->current_byte_offset = offset + count; + spin_unlock_bh(&ntoskernel_lock); + iosb->status = STATUS_SUCCESS; + iosb->info = count; + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(ZwWriteFile,9) + (void *handle, struct nt_event *event, void *apc_routine, + void *apc_context, struct io_status_block *iosb, void *buffer, + ULONG length, LARGE_INTEGER *byte_offset, ULONG *key) +{ + struct file_object *fo; + struct common_object_header *coh; + struct wrap_bin_file *file; + unsigned long offset; + + TRACE2("%p", handle); + coh = handle; + if (coh->type != OBJECT_TYPE_FILE) { + ERROR("handle %p is invalid: %d", handle, coh->type); + EXIT2(return STATUS_FAILURE); + } + fo = HANDLE_TO_OBJECT(coh); + file = fo->wrap_bin_file; + TRACE2("file: %zu, %u", file->size, length); + spin_lock_bh(&ntoskernel_lock); + if (byte_offset) + offset = *byte_offset; + else + offset = fo->current_byte_offset; + if (length + offset > file->size) { + WARNING("%lu, %u", length + offset, (unsigned int)file->size); + /* TODO: implement writing past end of current size */ + iosb->status = STATUS_FAILURE; + iosb->info = 0; + } else { + memcpy(file->data + offset, buffer, length); + iosb->status = STATUS_SUCCESS; + iosb->info = length; + fo->current_byte_offset = offset + length; + } + spin_unlock_bh(&ntoskernel_lock); + EXIT2(return iosb->status); +} + +wstdcall NTSTATUS WIN_FUNC(ZwClose,1) + (void *handle) +{ + struct common_object_header *coh; + + TRACE2("%p", handle); + if (handle == NULL) { + TRACE1(""); + EXIT2(return STATUS_SUCCESS); + } + coh = handle; + if (coh->type == OBJECT_TYPE_FILE) { + struct file_object *fo; + struct wrap_bin_file *bin_file; + typeof(fo->flags) flags; + + fo = HANDLE_TO_OBJECT(handle); + flags = fo->flags; + bin_file = fo->wrap_bin_file; + if (dereference_object(fo)) { + if (flags == FILE_CREATED) { + vfree(bin_file->data); + kfree(bin_file); + } else + free_bin_file(bin_file); + } + } else if (coh->type == OBJECT_TYPE_NT_THREAD) { + struct nt_thread *thread = HANDLE_TO_OBJECT(handle); + TRACE2("thread: %p (%p)", thread, handle); + ObDereferenceObject(thread); + } else { + /* TODO: can we just dereference object here? */ + WARNING("closing handle 0x%x not implemented", coh->type); + } + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(ZwQueryInformationFile,5) + (void *handle, struct io_status_block *iosb, void *info, + ULONG length, enum file_info_class class) +{ + struct file_object *fo; + struct file_name_info *fni; + struct file_std_info *fsi; + struct wrap_bin_file *file; + struct common_object_header *coh; + + ENTER2("%p", handle); + coh = handle; + if (coh->type != OBJECT_TYPE_FILE) { + ERROR("handle %p is invalid: %d", coh, coh->type); + EXIT2(return STATUS_FAILURE); + } + fo = HANDLE_TO_OBJECT(handle); + TRACE2("fo: %p, %d", fo, class); + switch (class) { + case FileNameInformation: + fni = info; + fni->length = min(length, (typeof(length))coh->name.length); + memcpy(fni->name, coh->name.buf, fni->length); + iosb->status = STATUS_SUCCESS; + iosb->info = fni->length; + break; + case FileStandardInformation: + fsi = info; + file = fo->wrap_bin_file; + fsi->alloc_size = file->size; + fsi->eof = file->size; + fsi->num_links = 1; + fsi->delete_pending = FALSE; + fsi->dir = FALSE; + iosb->status = STATUS_SUCCESS; + iosb->info = 0; + break; + default: + WARNING("type %d not implemented yet", class); + iosb->status = STATUS_FAILURE; + iosb->info = 0; + break; + } + EXIT2(return iosb->status); +} + +wstdcall NTSTATUS WIN_FUNC(ZwOpenSection,3) + (void **handle, ACCESS_MASK access, struct object_attributes *obj_attrs) +{ + INFO("%p, 0x%x, %d", obj_attrs, obj_attrs->attributes, access); + TODO(); + *handle = obj_attrs; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwMapViewOfSection,10) + (void *secn_handle, void *process_handle, void **base_address, + ULONG zero_bits, LARGE_INTEGER *secn_offset, SIZE_T *view_size, + enum section_inherit inherit, ULONG alloc_type, ULONG protect) +{ + INFO("%p, %p, %p", secn_handle, process_handle, base_address); + TODO(); + *base_address = (void *)0xdeadbeef; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwUnmapViewOfSection,2) + (void *process_handle, void *base_address) +{ + INFO("%p, %p", process_handle, base_address); + TODO(); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwCreateKey,7) + (void **handle, ACCESS_MASK desired_access, + struct object_attributes *attr, ULONG title_index, + struct unicode_string *class, ULONG create_options, + ULONG *disposition) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) == + STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + *handle = NULL; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwOpenKey,3) + (void **handle, ACCESS_MASK desired_access, + struct object_attributes *attr) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) == + STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + *handle = NULL; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwSetValueKey,6) + (void *handle, struct unicode_string *name, ULONG title_index, + ULONG type, void *data, ULONG data_size) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == + STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwQueryValueKey,6) + (void *handle, struct unicode_string *name, + enum key_value_information_class class, void *info, + ULONG length, ULONG *res_length) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + TODO(); + return STATUS_INVALID_PARAMETER; +} + +wstdcall NTSTATUS WIN_FUNC(ZwDeleteKey,1) + (void *handle) +{ + ENTER2("%p", handle); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwPowerInformation,4) + (INT info_level, void *in_buf, ULONG in_buf_len, void *out_buf, + ULONG out_buf_len) +{ + INFO("%d, %u, %u", info_level, in_buf_len, out_buf_len); + TODO(); + return STATUS_ACCESS_DENIED; +} + +wstdcall NTSTATUS WIN_FUNC(WmiSystemControl,4) + (struct wmilib_context *info, struct device_object *dev_obj, + struct irp *irp, void *irp_disposition) +{ + TODO(); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(WmiCompleteRequest,5) + (struct device_object *dev_obj, struct irp *irp, NTSTATUS status, + ULONG buffer_used, CCHAR priority_boost) +{ + TODO(); + return STATUS_SUCCESS; +} + +noregparm NTSTATUS WIN_FUNC(WmiTraceMessage,12) + (void *tracehandle, ULONG message_flags, + void *message_guid, USHORT message_no, ...) +{ + TODO(); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(WmiQueryTraceInformation,4) + (enum trace_information_class trace_info_class, void *trace_info, + ULONG *req_length, void *buf) +{ + TODO(); + EXIT2(return STATUS_SUCCESS); +} + +/* this function can't be wstdcall as it takes variable number of args */ +noregparm ULONG WIN_FUNC(DbgPrint,12) + (char *format, ...) +{ +#ifdef DEBUG + va_list args; + static char buf[100]; + + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + printk(KERN_DEBUG "%s (%s): %s", DRIVER_NAME, __FUNCTION__, buf); + va_end(args); +#endif + return STATUS_SUCCESS; +} + +wstdcall void WIN_FUNC(KeBugCheckEx,5) + (ULONG code, ULONG_PTR param1, ULONG_PTR param2, + ULONG_PTR param3, ULONG_PTR param4) +{ + TODO(); + return; +} + +wstdcall void WIN_FUNC(ExSystemTimeToLocalTime,2) + (LARGE_INTEGER *system_time, LARGE_INTEGER *local_time) +{ + *local_time = *system_time; +} + +wstdcall ULONG WIN_FUNC(ExSetTimerResolution,2) + (ULONG time, BOOLEAN set) +{ + /* why a driver should change system wide timer resolution is + * beyond me */ + return time; +} + +wstdcall void WIN_FUNC(DbgBreakPoint,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(_except_handler3,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(__C_specific_handler,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(_purecall,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(__chkstk,0) + (void) +{ + TODO(); +} + +struct worker_init_struct { + work_struct_t work; + struct completion completion; + struct nt_thread *nt_thread; +}; + +static void wrap_worker_init_func(worker_param_t param) +{ + struct worker_init_struct *worker_init_struct; + + worker_init_struct = + worker_param_data(param, struct worker_init_struct, work); + TRACE1("%p", worker_init_struct); + worker_init_struct->nt_thread = create_nt_thread(current); + if (!worker_init_struct->nt_thread) + WARNING("couldn't create worker thread"); + complete(&worker_init_struct->completion); +} + +struct nt_thread *wrap_worker_init(workqueue_struct_t *wq) +{ + struct worker_init_struct worker_init_struct; + + TRACE1("%p", &worker_init_struct); + init_completion(&worker_init_struct.completion); + initialize_work(&worker_init_struct.work, wrap_worker_init_func, + &worker_init_struct); + worker_init_struct.nt_thread = NULL; + if (wq) + queue_work(wq, &worker_init_struct.work); + else + schedule_work(&worker_init_struct.work); + wait_for_completion(&worker_init_struct.completion); + TRACE1("%p", worker_init_struct.nt_thread); + return worker_init_struct.nt_thread; +} + +int ntoskernel_init(void) +{ + struct timeval now; + + spin_lock_init(&dispatcher_lock); + spin_lock_init(&ntoskernel_lock); + spin_lock_init(&ntos_work_lock); + spin_lock_init(&kdpc_list_lock); + spin_lock_init(&irp_cancel_lock); + InitializeListHead(&wrap_mdl_list); + InitializeListHead(&kdpc_list); + InitializeListHead(&callback_objects); + InitializeListHead(&bus_driver_list); + InitializeListHead(&object_list); + InitializeListHead(&ntos_work_list); + + nt_spin_lock_init(&nt_list_lock); + + initialize_work(&kdpc_work, kdpc_worker, NULL); + initialize_work(&ntos_work, ntos_work_worker, NULL); + wrap_timer_slist.next = NULL; + + do_gettimeofday(&now); + wrap_ticks_to_boot = TICKS_1601_TO_1970; + wrap_ticks_to_boot += (u64)now.tv_sec * TICKSPERSEC; + wrap_ticks_to_boot += now.tv_usec * 10; + wrap_ticks_to_boot -= jiffies * TICKSPERJIFFY; + TRACE2("%Lu", wrap_ticks_to_boot); + +#ifdef WRAP_PREEMPT + do { + int cpu; + for_each_possible_cpu(cpu) { + irql_info_t *info; + info = &per_cpu(irql_info, cpu); + mutex_init(&(info->lock)); + info->task = NULL; + info->count = 0; + } + } while (0); +#endif + + ntos_wq = create_singlethread_workqueue("ntos_wq"); + if (!ntos_wq) { + WARNING("couldn't create ntos_wq thread"); + return -ENOMEM; + } + ntos_worker_thread = wrap_worker_init(ntos_wq); + TRACE1("%p", ntos_worker_thread); + + if (add_bus_driver("PCI") +#ifdef ENABLE_USB + || add_bus_driver("USB") +#endif + ) { + ntoskernel_exit(); + return -ENOMEM; + } + mdl_cache = + wrap_kmem_cache_create("wrap_mdl", + sizeof(struct wrap_mdl) + MDL_CACHE_SIZE, + 0, 0); + TRACE2("%p", mdl_cache); + if (!mdl_cache) { + ERROR("couldn't allocate MDL cache"); + ntoskernel_exit(); + return -ENOMEM; + } + +#if defined(CONFIG_X86_64) + memset(&kuser_shared_data, 0, sizeof(kuser_shared_data)); + *((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601(); + init_timer(&shared_data_timer); + shared_data_timer.function = update_user_shared_data_proc; + shared_data_timer.data = (unsigned long)0; +#endif + return 0; +} + +int ntoskernel_init_device(struct wrap_device *wd) +{ +#if defined(CONFIG_X86_64) + if (kuser_shared_data.reserved1) + mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30)); +#endif + return 0; +} + +void ntoskernel_exit_device(struct wrap_device *wd) +{ + ENTER2(""); + + KeFlushQueuedDpcs(); + EXIT2(return); +} + +void ntoskernel_exit(void) +{ + struct nt_list *cur; + + ENTER2(""); + + /* free kernel (Ke) timers */ + TRACE2("freeing timers"); + while (1) { + struct wrap_timer *wrap_timer; + struct nt_slist *slist; + + spin_lock_bh(&ntoskernel_lock); + if ((slist = wrap_timer_slist.next)) + wrap_timer_slist.next = slist->next; + spin_unlock_bh(&ntoskernel_lock); + TIMERTRACE("%p", slist); + if (!slist) + break; + wrap_timer = container_of(slist, struct wrap_timer, slist); + if (del_timer_sync(&wrap_timer->timer)) + WARNING("Buggy Windows driver left timer %p running", + wrap_timer->nt_timer); + memset(wrap_timer, 0, sizeof(*wrap_timer)); + slack_kfree(wrap_timer); + } + + TRACE2("freeing MDLs"); + if (mdl_cache) { + spin_lock_bh(&ntoskernel_lock); + if (!IsListEmpty(&wrap_mdl_list)) + ERROR("Windows driver didn't free all MDLs; " + "freeing them now"); + while ((cur = RemoveHeadList(&wrap_mdl_list))) { + struct wrap_mdl *wrap_mdl; + wrap_mdl = container_of(cur, struct wrap_mdl, list); + if (wrap_mdl->mdl->flags & MDL_CACHE_ALLOCATED) + kmem_cache_free(mdl_cache, wrap_mdl); + else + kfree(wrap_mdl); + } + spin_unlock_bh(&ntoskernel_lock); + kmem_cache_destroy(mdl_cache); + mdl_cache = NULL; + } + + TRACE2("freeing callbacks"); + spin_lock_bh(&ntoskernel_lock); + while ((cur = RemoveHeadList(&callback_objects))) { + struct callback_object *object; + struct nt_list *ent; + object = container_of(cur, struct callback_object, list); + while ((ent = RemoveHeadList(&object->callback_funcs))) { + struct callback_func *f; + f = container_of(ent, struct callback_func, list); + kfree(f); + } + kfree(object); + } + spin_unlock_bh(&ntoskernel_lock); + + spin_lock_bh(&ntoskernel_lock); + while ((cur = RemoveHeadList(&bus_driver_list))) { + struct bus_driver *bus_driver; + bus_driver = container_of(cur, struct bus_driver, list); + /* TODO: make sure all all drivers are shutdown/removed */ + kfree(bus_driver); + } + spin_unlock_bh(&ntoskernel_lock); + +#if defined(CONFIG_X86_64) + del_timer_sync(&shared_data_timer); +#endif + if (ntos_wq) + destroy_workqueue(ntos_wq); + TRACE1("%p", ntos_worker_thread); + if (ntos_worker_thread) + ObDereferenceObject(ntos_worker_thread); + ENTER2("freeing objects"); + spin_lock_bh(&ntoskernel_lock); + while ((cur = RemoveHeadList(&object_list))) { + struct common_object_header *hdr; + hdr = container_of(cur, struct common_object_header, list); + if (hdr->type == OBJECT_TYPE_NT_THREAD) + TRACE1("object %p(%d) was not freed, freeing it now", + HEADER_TO_OBJECT(hdr), hdr->type); + else + WARNING("object %p(%d) was not freed, freeing it now", + HEADER_TO_OBJECT(hdr), hdr->type); + ExFreePool(hdr); + } + spin_unlock_bh(&ntoskernel_lock); + + EXIT2(return); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/longlong.h +++ linux-2.6.27/ubuntu/ndiswrapper/longlong.h @@ -0,0 +1,1333 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000 + Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + UQItype -- Unsigned 8 bit type. + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +#ifndef W_TYPE_SIZE +#define W_TYPE_SIZE 32 +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first nonzero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! + (E.g. WE32100, IBM360.) */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#ifdef __alpha_cix__ +#define count_leading_zeros(COUNT,X) \ + __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X)) +#define count_trailing_zeros(COUNT,X) \ + __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X)) +#define COUNT_LEADING_ZEROS_0 64 +#else +extern const UQItype __clz_tab[]; +#define count_leading_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ + __a = __clz_tab[__t ^ 0xff] - 1; \ + __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ + (COUNT) = 64 - (__clz_tab[__t] + __a*8); \ + } while (0) +#define count_trailing_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ + __t = ~__t & -~__t; \ + __a = ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ + __a <<= 3; \ + __t &= -__t; \ + __a += ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + (COUNT) = __a; \ + } while (0) +#endif /* __alpha_cix__ */ +#endif /* __alpha */ + +#if defined (__arc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +/* Call libgcc routine. */ +#define umul_ppmm(w1, w0, u, v) \ +do { \ + DWunion __w; \ + __w.ll = __umulsidi3 (u, v); \ + w1 = __w.s.high; \ + w0 = __w.s.low; \ +} while (0) +#define __umulsidi3 __umulsidi3 +UDItype __umulsidi3 (USItype, USItype); +#endif + +#if defined (__arm__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rI" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rI" ((USItype) (bl))) +#define umul_ppmm(xh, xl, a, b) \ +{register USItype __t0, __t1, __t2; \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + " mov %2, %5, lsr #16\n" \ + " mov %0, %6, lsr #16\n" \ + " bic %3, %5, %2, lsl #16\n" \ + " bic %4, %6, %0, lsl #16\n" \ + " mul %1, %3, %4\n" \ + " mul %4, %2, %4\n" \ + " mul %3, %0, %3\n" \ + " mul %0, %2, %0\n" \ + " adds %3, %4, %3\n" \ + " addcs %0, %0, #65536\n" \ + " adds %1, %1, %3, lsl #16\n" \ + " adc %0, %0, %3, lsr #16" \ + : "=&r" ((USItype) (xh)), \ + "=r" ((USItype) (xl)), \ + "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ + : "r" ((USItype) (a)), \ + "r" ((USItype) (b)));} +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#endif /* __arm__ */ + +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "%rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + union \ + { \ + UDItype __f; \ + struct {USItype __w1, __w0;} __w1w0; \ + } __t; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=x" (__t.__f) \ + : "x" ((USItype) (u)), \ + "x" ((USItype) (v))); \ + (w1) = __t.__w1w0.__w1; \ + (w0) = __t.__w1w0.__w0; \ + } while (0) +#define UMUL_TIME 8 +#else +#define UMUL_TIME 30 +#endif +#define UDIV_TIME 40 +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0\n" \ +" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\ +" ldo 16(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\ +" ldo 8(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\ +" ldo 4(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\ +" ldo 2(%0),%0 ; Yes. Perform add.\n" \ +" extru %1,30,1,%1 ; Extract bit 1.\n" \ +" sub %0,%1,%0 ; Subtract it.\n" \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif + +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1\n\tadcl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "rm" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("divl %4" \ + : "=a" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "rm" ((USItype) (dv))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#endif /* 80x86 */ + +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + __w; }) +#endif /* __i960__ */ + +#if defined (__M32R__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\taddx %%5,%1\n\taddx %%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\tsubx %5,%1\n\tsubx %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#endif /* __M32R__ */ + +#if defined (__mc68000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) + +/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r. */ +#if defined (__mc68020__) || defined(mc68020) \ + || defined(__mc68030__) || defined(mc68030) \ + || defined(__mc68040__) || defined(mc68040) \ + || defined(__mcpu32__) || defined(mcpu32) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "dmi" ((USItype) (v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) + +#else /* not mc68020 */ +#if !defined(__mcf5200__) +/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("| Inlined umul_ppmm\n" \ + " move%.l %2,%/d0\n" \ + " move%.l %3,%/d1\n" \ + " move%.l %/d0,%/d2\n" \ + " swap %/d0\n" \ + " move%.l %/d1,%/d3\n" \ + " swap %/d1\n" \ + " move%.w %/d2,%/d4\n" \ + " mulu %/d3,%/d4\n" \ + " mulu %/d1,%/d2\n" \ + " mulu %/d0,%/d3\n" \ + " mulu %/d0,%/d1\n" \ + " move%.l %/d4,%/d0\n" \ + " eor%.w %/d0,%/d0\n" \ + " swap %/d0\n" \ + " add%.l %/d0,%/d2\n" \ + " add%.l %/d3,%/d2\n" \ + " jcc 1f\n" \ + " add%.l %#65536,%/d1\n" \ + "1: swap %/d2\n" \ + " moveq %#0,%/d0\n" \ + " move%.w %/d2,%/d0\n" \ + " move%.w %/d4,%/d2\n" \ + " move%.l %/d2,%1\n" \ + " add%.l %/d1,%/d0\n" \ + " move%.l %/d0,%0" \ + : "=g" ((USItype) (xh)), \ + "=g" ((USItype) (xl)) \ + : "g" ((USItype) (a)), \ + "g" ((USItype) (b)) \ + : "d0", "d1", "d2", "d3", "d4") +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mcf5200 */ +#endif /* not mc68020 */ + +/* The '020, '030, '040 and '060 have bitfield insns. */ +#if defined (__mc68020__) || defined(mc68020) \ + || defined(__mc68030__) || defined(mc68030) \ + || defined(__mc68040__) || defined(mc68040) \ + || defined(__mc68060__) || defined(mc68060) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype) (count)) \ + : "od" ((USItype) (x)), "n" (0)) +#endif +#endif /* mc68000 */ + +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__mc88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mulu.d %0,%1,%2" \ + : "=r" (__xx.__ll) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __q; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q) \ + : "r" (__xx.__ll), \ + "r" ((USItype) (d))); \ + (r) = (n0) - __q * (d); (q) = __q; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __mc88110__ */ +#endif /* __m88000__ */ + +#if defined (__mips__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype) (w0)), \ + "=h" ((USItype) (w1)) \ + : "d" ((USItype) (u)), \ + "d" ((USItype) (v))) +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype) (d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { \ + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + +/* FIXME: We should test _IBMR2 here when we add assembly support for the + system vendor compilers. + FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good + enough, since that hits ARM and m68k too. */ +#if (defined (_ARCH_PPC) /* AIX */ \ + || defined (_ARCH_PWR) /* AIX */ \ + || defined (_ARCH_COM) /* AIX */ \ + || defined (__powerpc__) /* gcc */ \ + || defined (__POWERPC__) /* BEOS */ \ + || defined (__ppc__) /* Darwin */ \ + || defined (PPC) /* GNU/Linux, SysV */ \ + ) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \ + || defined (__ppc__) || defined (PPC) || defined (__vxworks__) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#elif defined (_ARCH_PWR) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d)) +#define UDIV_TIME 100 +#endif +#endif /* 32-bit POWER architecture variants. */ + +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ + +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5\n\tae %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n\tse %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2\n" \ +" mts r10,%2\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" cas %0,r2,r0\n" \ +" mfs r10,%1" \ + : "=r" ((USItype) (ph)), \ + "=r" ((USItype) (pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + (count) += 16; \ + } \ + } while (0) +#endif + +#if defined (__sh2__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32 +#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v) +#define count_leading_zeros(count, x) \ + do \ + { \ + UDItype x_ = (USItype)(x); \ + SItype c_; \ + \ + __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_)); \ + (count) = c_ - 31; \ + } \ + while (0) +#define COUNT_LEADING_ZEROS_0 32 +#endif + +#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__n1)), \ + "r" ((USItype) (__n0)), \ + "r" ((USItype) (__d))) +#else +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \ +" tst %%g0\n" \ +" divscc %3,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%0\n" \ +" rd %%y,%1\n" \ +" bl,a 1f\n" \ +" add %1,%4,%1\n" \ +"1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype) (q)), \ + "=r" ((USItype) (r)) \ + : "r" ((USItype) (n1)), \ + "r" ((USItype) (n0)), \ + "rI" ((USItype) (d)) \ + : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + do { \ + __asm__ ("scan %1,1,%0" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + } while (0) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#else +/* SPARC without integer multiplication and divide instructions. + (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm\n" \ +" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\ +" sra %3,31,%%o5 ! Don't move this insn\n" \ +" and %2,%%o5,%%o5 ! Don't move this insn\n" \ +" andcc %%g0,0,%%g1 ! Don't move this insn\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,0,%%g1\n" \ +" add %%g1,%%o5,%0\n" \ +" rd %%y,%1" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "%rI" ((USItype) (u)), \ + "r" ((USItype) (v)) \ + : "g1", "o5" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +/* It's quite necessary to add this much assembler for the sparc. + The default udiv_qrnnd (in C) is more than 10 times slower! */ +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" mov 32,%%g1\n" \ +" subcc %1,%2,%%g0\n" \ +"1: bcs 5f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +" addx %1,%1,%1 ! so this can't give carry\n" \ +" subcc %%g1,1,%%g1\n" \ +"2: bne 1b\n" \ +" subcc %1,%2,%%g0\n" \ +" bcs 3f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" b 3f\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +"4: sub %1,%2,%1\n" \ +"5: addxcc %1,%1,%1\n" \ +" bcc 2b\n" \ +" subcc %%g1,1,%%g1\n" \ +"! Got carry from n. Subtract next step to cancel this carry.\n" \ +" bne 4b\n" \ +" addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n" \ +" sub %1,%2,%1\n" \ +"3: xnor %0,0,%0\n" \ +" ! End of inline udiv_qrnnd" \ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__d)), \ + "1" ((USItype) (__n1)), \ + "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +#endif /* sparc32 */ + +#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \ + && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\t" \ + "add %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "add %0, 1, %0\n" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "%rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\t" \ + "sub %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "sub %0, 1, %0\n\t" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define umul_ppmm(wh, wl, u, v) \ + do { \ + UDItype tmp1, tmp2, tmp3, tmp4; \ + __asm__ __volatile__ ( \ + "srl %7,0,%3\n\t" \ + "mulx %3,%6,%1\n\t" \ + "srlx %6,32,%2\n\t" \ + "mulx %2,%3,%4\n\t" \ + "sllx %4,32,%5\n\t" \ + "srl %6,0,%3\n\t" \ + "sub %1,%5,%5\n\t" \ + "srlx %5,32,%5\n\t" \ + "addcc %4,%5,%4\n\t" \ + "srlx %7,32,%5\n\t" \ + "mulx %3,%5,%3\n\t" \ + "mulx %2,%5,%5\n\t" \ + "sethi %%hi(0x80000000),%2\n\t" \ + "addcc %4,%3,%4\n\t" \ + "srlx %4,32,%4\n\t" \ + "add %2,%2,%2\n\t" \ + "movcc %%xcc,%%g0,%2\n\t" \ + "addcc %5,%4,%5\n\t" \ + "sllx %3,32,%3\n\t" \ + "add %1,%3,%1\n\t" \ + "add %5,%2,%0" \ + : "=r" ((UDItype)(wh)), \ + "=&r" ((UDItype)(wl)), \ + "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \ + : "r" ((UDItype)(u)), \ + "r" ((UDItype)(v)) \ + __CLOBBER_CC); \ + } while (0) +#define UMUL_TIME 96 +#define UDIV_TIME 230 +#endif /* sparc64 */ + +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union { \ + UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=r" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; \ + (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({DWunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0; \ + UWtype __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + USItype __r; \ + (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern const UQItype __clz_tab[]; +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype)1<<2*__BITS4) \ + ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif --- linux-2.6.27.orig/ubuntu/ndiswrapper/loader.h +++ linux-2.6.27/ubuntu/ndiswrapper/loader.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _LOADER_H_ +#define _LOADER_H_ + +#include "ndiswrapper.h" + +#ifndef __KERNEL__ +#define __user +#endif + +struct load_driver_file { + char driver_name[MAX_DRIVER_NAME_LEN]; + char name[MAX_DRIVER_NAME_LEN]; + size_t size; + void __user *data; +}; + +struct load_device_setting { + char name[MAX_SETTING_NAME_LEN]; + char value[MAX_SETTING_VALUE_LEN]; +}; + +struct load_device { + int bus; + int vendor; + int device; + int subvendor; + int subdevice; + char conf_file_name[MAX_DRIVER_NAME_LEN]; + char driver_name[MAX_DRIVER_NAME_LEN]; +}; + +struct load_devices { + int count; + struct load_device *devices; +}; + +struct load_driver { + char name[MAX_DRIVER_NAME_LEN]; + char conf_file_name[MAX_DRIVER_NAME_LEN]; + unsigned int num_sys_files; + struct load_driver_file sys_files[MAX_DRIVER_PE_IMAGES]; + unsigned int num_settings; + struct load_device_setting settings[MAX_DEVICE_SETTINGS]; + unsigned int num_bin_files; + struct load_driver_file bin_files[MAX_DRIVER_BIN_FILES]; +}; + +#define WRAP_IOCTL_LOAD_DEVICE _IOW(('N' + 'd' + 'i' + 'S'), 0, \ + struct load_device *) +#define WRAP_IOCTL_LOAD_DRIVER _IOW(('N' + 'd' + 'i' + 'S'), 1, \ + struct load_driver *) +#define WRAP_IOCTL_LOAD_BIN_FILE _IOW(('N' + 'd' + 'i' + 'S'), 2, \ + struct load_driver_file *) + +#define WRAP_CMD_LOAD_DEVICE "load_device" +#define WRAP_CMD_LOAD_DRIVER "load_driver" +#define WRAP_CMD_LOAD_BIN_FILE "load_bin_file" + +int loader_init(void); +void loader_exit(void); + +#ifdef __KERNEL__ +struct wrap_device *load_wrap_device(struct load_device *load_device); +struct wrap_driver *load_wrap_driver(struct wrap_device *device); +struct wrap_bin_file *get_bin_file(char *bin_file_name); +void free_bin_file(struct wrap_bin_file *bin_file); +void unload_wrap_driver(struct wrap_driver *driver); +void unload_wrap_device(struct wrap_device *wd); +struct wrap_device *get_wrap_device(void *dev, int bus_type); + +extern struct semaphore loader_mutex; +#endif + +#endif /* LOADER_H */ + --- linux-2.6.27.orig/ubuntu/ndiswrapper/BOM +++ linux-2.6.27/ubuntu/ndiswrapper/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=93482 +Current Version: 1.53 --- linux-2.6.27.orig/ubuntu/ndiswrapper/usb.c +++ linux-2.6.27/ubuntu/ndiswrapper/usb.c @@ -0,0 +1,1457 @@ +/* + * Copyright (C) 2004 Jan Kiszka + * Copyright (C) 2005 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ndis.h" +#include "usb.h" +#include "usb_exports.h" + +#ifdef USB_DEBUG +static unsigned int urb_id = 0; + +#define DUMP_WRAP_URB(wrap_urb, dir) \ + USBTRACE("urb %p (%d) %s: buf: %p, len: %d, pipe: 0x%x, %d", \ + (wrap_urb)->urb, (wrap_urb)->id, \ + (dir == USB_DIR_OUT) ? "going down" : "coming back", \ + (wrap_urb)->urb->transfer_buffer, \ + (wrap_urb)->urb->transfer_buffer_length, \ + (wrap_urb)->urb->pipe, (wrap_urb)->urb->status) + +#define DUMP_URB_BUFFER(urb, dir) \ + while (debug >= 2) { \ + int i; \ + char msg[20], *t; \ + if (!urb->transfer_buffer) \ + break; \ + if (!((usb_pipein(urb->pipe) && dir == USB_DIR_IN) || \ + (usb_pipeout(urb->pipe) && dir == USB_DIR_OUT))) \ + break; \ + t = msg; \ + t += sprintf(t, "%d: ", (urb)->actual_length); \ + for (i = 0; i < urb->actual_length && \ + t < &msg[sizeof(msg) - 4]; i++) \ + t += sprintf(t, "%02X ", \ + ((char *)urb->transfer_buffer)[i]); \ + *t = 0; \ + USBTRACE("%s", msg); \ + break; \ + } + +#else + +#define DUMP_WRAP_URB(wrap_urb, dir) (void)0 +#define DUMP_URB_BUFFER(urb, dir) (void)0 + +#endif + +#define CUR_ALT_SETTING(intf) (intf)->cur_altsetting + +#ifndef USB_CTRL_SET_TIMEOUT +#define USB_CTRL_SET_TIMEOUT 5000 +#endif + +#ifndef USB_CTRL_GET_TIMEOUT +#define USB_CTRL_GET_TIMEOUT 5000 +#endif + +#ifndef URB_NO_TRANSFER_DMA_MAP +#define URB_NO_TRANSFER_DMA_MAP 0 +#endif + +/* wrap_urb->flags */ +/* transfer_buffer for urb is allocated; free it in wrap_free_urb */ +#define WRAP_URB_COPY_BUFFER 0x01 + +static int inline wrap_cancel_urb(struct wrap_urb *wrap_urb) +{ + int ret; + USBTRACE("%p, %p, %d", wrap_urb, wrap_urb->urb, wrap_urb->state); + if (wrap_urb->state != URB_SUBMITTED) + USBEXIT(return -1); + ret = usb_unlink_urb(wrap_urb->urb); + USBTRACE("ret: %d", ret); + if (ret == -EINPROGRESS) + return 0; + else { + WARNING("unlink failed: %d", ret); + return ret; + } +} + +#define URB_STATUS(wrap_urb) (wrap_urb->urb->status) + +static struct nt_list wrap_urb_complete_list; +static spinlock_t wrap_urb_complete_list_lock; + +static work_struct_t wrap_urb_complete_work; +static void wrap_urb_complete_worker(worker_param_t dummy); + +static void kill_all_urbs(struct wrap_device *wd, int complete) +{ + struct nt_list *ent; + struct wrap_urb *wrap_urb; + KIRQL irql; + + USBTRACE("%d", wd->usb.num_alloc_urbs); + while (1) { + IoAcquireCancelSpinLock(&irql); + ent = RemoveHeadList(&wd->usb.wrap_urb_list); + IoReleaseCancelSpinLock(irql); + if (!ent) + break; + wrap_urb = container_of(ent, struct wrap_urb, list); + if (wrap_urb->state == URB_SUBMITTED) { + WARNING("Windows driver %s didn't free urb: %p", + wd->driver->name, wrap_urb->urb); + if (!complete) + wrap_urb->urb->complete = NULL; + usb_kill_urb(wrap_urb->urb); + } + USBTRACE("%p, %p", wrap_urb, wrap_urb->urb); + usb_free_urb(wrap_urb->urb); + kfree(wrap_urb); + } + wd->usb.num_alloc_urbs = 0; +} + +/* for a given Linux urb status code, return corresponding NT urb status */ +static USBD_STATUS wrap_urb_status(int urb_status) +{ + switch (urb_status) { + case 0: + return USBD_STATUS_SUCCESS; + case -EPROTO: + return USBD_STATUS_TIMEOUT; + case -EILSEQ: + return USBD_STATUS_CRC; + case -EPIPE: + return USBD_STATUS_INVALID_PIPE_HANDLE; + case -ECOMM: + return USBD_STATUS_DATA_OVERRUN; + case -ENOSR: + return USBD_STATUS_DATA_UNDERRUN; + case -EOVERFLOW: + return USBD_STATUS_BABBLE_DETECTED; + case -EREMOTEIO: + return USBD_STATUS_ERROR_SHORT_TRANSFER;; + case -ENODEV: + case -ESHUTDOWN: + case -ENOENT: + return USBD_STATUS_DEVICE_GONE; + case -ENOMEM: + return USBD_STATUS_NO_MEMORY; + case -EINVAL: + return USBD_STATUS_REQUEST_FAILED; + default: + return USBD_STATUS_NOT_SUPPORTED; + } +} + +/* for a given USBD_STATUS, return its corresponding NTSTATUS (for irp) */ +static NTSTATUS nt_urb_irp_status(USBD_STATUS nt_urb_status) +{ + switch (nt_urb_status) { + case USBD_STATUS_SUCCESS: + return STATUS_SUCCESS; + case USBD_STATUS_DEVICE_GONE: + return STATUS_DEVICE_REMOVED; + case USBD_STATUS_PENDING: + return STATUS_PENDING; + case USBD_STATUS_NOT_SUPPORTED: + return STATUS_NOT_IMPLEMENTED; + case USBD_STATUS_NO_MEMORY: + return STATUS_NO_MEMORY; + case USBD_STATUS_REQUEST_FAILED: + return STATUS_NOT_SUPPORTED; + default: + return STATUS_FAILURE; + } +} + +static void wrap_free_urb(struct urb *urb) +{ + struct irp *irp; + struct wrap_urb *wrap_urb; + + USBTRACE("freeing urb: %p", urb); + wrap_urb = urb->context; + irp = wrap_urb->irp; + if (wrap_urb->flags & WRAP_URB_COPY_BUFFER) { + USBTRACE("freeing DMA buffer for URB: %p %p", + urb, urb->transfer_buffer); + usb_buffer_free(IRP_WRAP_DEVICE(irp)->usb.udev, + urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + } + if (urb->setup_packet) + kfree(urb->setup_packet); + if (IRP_WRAP_DEVICE(irp)->usb.num_alloc_urbs > MAX_ALLOCATED_URBS) { + IoAcquireCancelSpinLock(&irp->cancel_irql); + RemoveEntryList(&wrap_urb->list); + IRP_WRAP_DEVICE(irp)->usb.num_alloc_urbs--; + IoReleaseCancelSpinLock(irp->cancel_irql); + usb_free_urb(urb); + kfree(wrap_urb); + } else { + wrap_urb->state = URB_FREE; + wrap_urb->flags = 0; + wrap_urb->irp = NULL; + } + return; +} + +void wrap_suspend_urbs(struct wrap_device *wd) +{ + /* TODO: do we need to cancel urbs? */ + USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs); +} + +void wrap_resume_urbs(struct wrap_device *wd) +{ + /* TODO: do we need to resubmit urbs? */ + USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs); +} + +wstdcall void wrap_cancel_irp(struct device_object *dev_obj, struct irp *irp) +{ + struct urb *urb; + + /* NB: this function is called holding Cancel spinlock */ + USBENTER("irp: %p", irp); + urb = IRP_WRAP_URB(irp)->urb; + USBTRACE("canceling urb %p", urb); + if (wrap_cancel_urb(IRP_WRAP_URB(irp))) { + irp->cancel = FALSE; + ERROR("urb %p can't be canceld: %d", urb, + IRP_WRAP_URB(irp)->state); + } else + USBTRACE("urb %p canceled", urb); + IoReleaseCancelSpinLock(irp->cancel_irql); + return; +} +WIN_FUNC_DECL(wrap_cancel_irp,2) + +static struct urb *wrap_alloc_urb(struct irp *irp, unsigned int pipe, + void *buf, unsigned int buf_len) +{ + struct urb *urb; + gfp_t alloc_flags; + struct wrap_urb *wrap_urb; + struct wrap_device *wd; + + USBENTER("irp: %p", irp); + wd = IRP_WRAP_DEVICE(irp); + alloc_flags = irql_gfp(); + IoAcquireCancelSpinLock(&irp->cancel_irql); + urb = NULL; + nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) { + if (cmpxchg(&wrap_urb->state, URB_FREE, + URB_ALLOCATED) == URB_FREE) { + urb = wrap_urb->urb; + usb_init_urb(urb); + break; + } + } + if (!urb) { + IoReleaseCancelSpinLock(irp->cancel_irql); + wrap_urb = kzalloc(sizeof(*wrap_urb), alloc_flags); + if (!wrap_urb) { + WARNING("couldn't allocate memory"); + return NULL; + } + urb = usb_alloc_urb(0, alloc_flags); + if (!urb) { + WARNING("couldn't allocate urb"); + kfree(wrap_urb); + return NULL; + } + IoAcquireCancelSpinLock(&irp->cancel_irql); + wrap_urb->urb = urb; + wrap_urb->state = URB_ALLOCATED; + InsertTailList(&wd->usb.wrap_urb_list, &wrap_urb->list); + wd->usb.num_alloc_urbs++; + } + +#ifdef URB_ASYNC_UNLINK + urb->transfer_flags |= URB_ASYNC_UNLINK; +#elif defined(USB_ASYNC_UNLINK) + urb->transfer_flags |= USB_ASYNC_UNLINK; +#endif + urb->context = wrap_urb; + wrap_urb->irp = irp; + IRP_WRAP_URB(irp) = wrap_urb; + /* called as Windows function */ + irp->cancel_routine = WIN_FUNC_PTR(wrap_cancel_irp,2); + IoReleaseCancelSpinLock(irp->cancel_irql); + USBTRACE("urb: %p", urb); + + urb->transfer_buffer_length = buf_len; + if (buf_len && buf && (!virt_addr_valid(buf) +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_HIGHMEM4G) + || PageHighMem(virt_to_page(buf)) +#endif + )) { + urb->transfer_buffer = + usb_buffer_alloc(wd->usb.udev, buf_len, alloc_flags, + &urb->transfer_dma); + if (!urb->transfer_buffer) { + WARNING("couldn't allocate dma buf"); + IoAcquireCancelSpinLock(&irp->cancel_irql); + wrap_urb->state = URB_FREE; + wrap_urb->irp = NULL; + IRP_WRAP_URB(irp) = NULL; + IoReleaseCancelSpinLock(irp->cancel_irql); + return NULL; + } + if (urb->transfer_dma) + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + wrap_urb->flags |= WRAP_URB_COPY_BUFFER; + if (usb_pipeout(pipe)) + memcpy(urb->transfer_buffer, buf, buf_len); + USBTRACE("DMA buf for urb %p: %p", urb, urb->transfer_buffer); + } else + urb->transfer_buffer = buf; + return urb; +} + +static USBD_STATUS wrap_submit_urb(struct irp *irp) +{ + int ret; + struct urb *urb; + union nt_urb *nt_urb; + + urb = IRP_WRAP_URB(irp)->urb; + nt_urb = IRP_URB(irp); +#ifdef USB_DEBUG + if (IRP_WRAP_URB(irp)->state != URB_ALLOCATED) { + ERROR("urb %p is in wrong state: %d", + urb, IRP_WRAP_URB(irp)->state); + NT_URB_STATUS(nt_urb) = USBD_STATUS_REQUEST_FAILED; + return NT_URB_STATUS(nt_urb); + } + IRP_WRAP_URB(irp)->id = pre_atomic_add(urb_id, 1); +#endif + DUMP_WRAP_URB(IRP_WRAP_URB(irp), USB_DIR_OUT); + irp->io_status.status = STATUS_PENDING; + irp->io_status.info = 0; + NT_URB_STATUS(nt_urb) = USBD_STATUS_PENDING; + IoMarkIrpPending(irp); + DUMP_URB_BUFFER(urb, USB_DIR_OUT); + USBTRACE("%p", urb); + IRP_WRAP_URB(irp)->state = URB_SUBMITTED; + ret = usb_submit_urb(urb, irql_gfp()); + if (ret) { + USBTRACE("ret: %d", ret); + wrap_free_urb(urb); + /* we assume that IRP was not in pending state before */ + IoUnmarkIrpPending(irp); + NT_URB_STATUS(nt_urb) = wrap_urb_status(ret); + USBEXIT(return NT_URB_STATUS(nt_urb)); + } else + USBEXIT(return USBD_STATUS_PENDING); +} + +static void wrap_urb_complete(struct urb *urb ISR_PT_REGS_PARAM_DECL) +{ + struct irp *irp; + struct wrap_urb *wrap_urb; + + wrap_urb = urb->context; + USBTRACE("%p (%p) completed", wrap_urb, urb); + irp = wrap_urb->irp; + DUMP_WRAP_URB(wrap_urb, USB_DIR_IN); + irp->cancel_routine = NULL; +#ifdef USB_DEBUG + if (wrap_urb->state != URB_SUBMITTED) { + WARNING("urb %p in wrong state: %d (%d)", urb, wrap_urb->state, + urb->status); + return; + } +#endif + wrap_urb->state = URB_COMPLETED; + spin_lock(&wrap_urb_complete_list_lock); + InsertTailList(&wrap_urb_complete_list, &wrap_urb->complete_list); + spin_unlock(&wrap_urb_complete_list_lock); + schedule_ntos_work(&wrap_urb_complete_work); +} + +/* one worker for all devices */ +static void wrap_urb_complete_worker(worker_param_t dummy) +{ + struct irp *irp; + struct urb *urb; + struct usbd_bulk_or_intr_transfer *bulk_int_tx; + struct usbd_vendor_or_class_request *vc_req; + union nt_urb *nt_urb; + struct wrap_urb *wrap_urb; + struct nt_list *ent; + unsigned long flags; + + USBENTER(""); + while (1) { + spin_lock_irqsave(&wrap_urb_complete_list_lock, flags); + ent = RemoveHeadList(&wrap_urb_complete_list); + spin_unlock_irqrestore(&wrap_urb_complete_list_lock, flags); + if (!ent) + break; + wrap_urb = container_of(ent, struct wrap_urb, complete_list); + urb = wrap_urb->urb; +#ifdef USB_DEBUG + if (wrap_urb->state != URB_COMPLETED && + wrap_urb->state != URB_INT_UNLINKED) + WARNING("urb %p in wrong state: %d", + urb, wrap_urb->state); +#endif + irp = wrap_urb->irp; + DUMP_IRP(irp); + nt_urb = IRP_URB(irp); + USBTRACE("urb: %p, nt_urb: %p, status: %d", + urb, nt_urb, urb->status); + switch (urb->status) { + case 0: + /* succesfully transferred */ + irp->io_status.info = urb->actual_length; + if (nt_urb->header.function == + URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) { + bulk_int_tx = &nt_urb->bulk_int_transfer; + bulk_int_tx->transfer_buffer_length = + urb->actual_length; + DUMP_URB_BUFFER(urb, USB_DIR_IN); + if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) && + usb_pipein(urb->pipe)) + memcpy(bulk_int_tx->transfer_buffer, + urb->transfer_buffer, + urb->actual_length); + } else { // vendor or class request + vc_req = &nt_urb->vendor_class_request; + vc_req->transfer_buffer_length = + urb->actual_length; + DUMP_URB_BUFFER(urb, USB_DIR_IN); + if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) && + usb_pipein(urb->pipe)) + memcpy(vc_req->transfer_buffer, + urb->transfer_buffer, + urb->actual_length); + } + NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS; + irp->io_status.status = STATUS_SUCCESS; + break; + case -ENOENT: + case -ECONNRESET: + /* urb canceled */ + irp->io_status.info = 0; + TRACE2("urb %p canceled", urb); + NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS; + irp->io_status.status = STATUS_CANCELLED; + break; + default: + TRACE2("irp: %p, urb: %p, status: %d/%d", + irp, urb, urb->status, wrap_urb->state); + irp->io_status.info = 0; + NT_URB_STATUS(nt_urb) = wrap_urb_status(urb->status); + irp->io_status.status = + nt_urb_irp_status(NT_URB_STATUS(nt_urb)); + break; + } + wrap_free_urb(urb); + IoCompleteRequest(irp, IO_NO_INCREMENT); + } + USBEXIT(return); +} + +static USBD_STATUS wrap_bulk_or_intr_trans(struct irp *irp) +{ + usbd_pipe_handle pipe_handle; + struct urb *urb; + unsigned int pipe; + struct usbd_bulk_or_intr_transfer *bulk_int_tx; + USBD_STATUS status; + struct usb_device *udev; + union nt_urb *nt_urb; + + nt_urb = IRP_URB(irp); + udev = IRP_WRAP_DEVICE(irp)->usb.udev; + bulk_int_tx = &nt_urb->bulk_int_transfer; + pipe_handle = bulk_int_tx->pipe_handle; + USBTRACE("flags: 0x%x, length: %u, buffer: %p, handle: %p", + bulk_int_tx->transfer_flags, + bulk_int_tx->transfer_buffer_length, + bulk_int_tx->transfer_buffer, pipe_handle); + + if (USBD_IS_BULK_PIPE(pipe_handle)) { + if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN) + pipe = usb_rcvbulkpipe(udev, + pipe_handle->bEndpointAddress); + else + pipe = usb_sndbulkpipe(udev, + pipe_handle->bEndpointAddress); + } else { + if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN) + pipe = usb_rcvintpipe(udev, + pipe_handle->bEndpointAddress); + else + pipe = usb_sndintpipe(udev, + pipe_handle->bEndpointAddress); + } + + DUMP_IRP(irp); + urb = wrap_alloc_urb(irp, pipe, bulk_int_tx->transfer_buffer, + bulk_int_tx->transfer_buffer_length); + if (!urb) { + ERROR("couldn't allocate urb"); + return USBD_STATUS_NO_MEMORY; + } + if (usb_pipein(pipe) && + (!(bulk_int_tx->transfer_flags & USBD_SHORT_TRANSFER_OK))) { + USBTRACE("short not ok"); + urb->transfer_flags |= URB_SHORT_NOT_OK; + } + if (usb_pipebulk(pipe)) { + usb_fill_bulk_urb(urb, udev, pipe, urb->transfer_buffer, + bulk_int_tx->transfer_buffer_length, + wrap_urb_complete, urb->context); + USBTRACE("submitting bulk urb %p on pipe 0x%x (ep 0x%x)", + urb, urb->pipe, pipe_handle->bEndpointAddress); + } else { + usb_fill_int_urb(urb, udev, pipe, urb->transfer_buffer, + bulk_int_tx->transfer_buffer_length, + wrap_urb_complete, urb->context, + pipe_handle->bInterval); + USBTRACE("submitting interrupt urb %p on pipe 0x%x (ep 0x%x), " + "intvl: %d", urb, urb->pipe, + pipe_handle->bEndpointAddress, pipe_handle->bInterval); + } + status = wrap_submit_urb(irp); + USBTRACE("status: %08X", status); + USBEXIT(return status); +} + +static USBD_STATUS wrap_vendor_or_class_req(struct irp *irp) +{ + u8 req_type; + unsigned int pipe; + struct usbd_vendor_or_class_request *vc_req; + struct usb_device *udev; + union nt_urb *nt_urb; + USBD_STATUS status; + struct urb *urb; + struct usb_ctrlrequest *dr; + + nt_urb = IRP_URB(irp); + udev = IRP_WRAP_DEVICE(irp)->usb.udev; + vc_req = &nt_urb->vendor_class_request; + USBTRACE("bits: %x, req: %x, val: %08x, index: %08x, flags: %x," + "buf: %p, len: %d", vc_req->reserved_bits, vc_req->request, + vc_req->value, vc_req->index, vc_req->transfer_flags, + vc_req->transfer_buffer, vc_req->transfer_buffer_length); + + USBTRACE("%x", nt_urb->header.function); + switch (nt_urb->header.function) { + case URB_FUNCTION_VENDOR_DEVICE: + req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE; + break; + case URB_FUNCTION_VENDOR_INTERFACE: + req_type = USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + break; + case URB_FUNCTION_VENDOR_ENDPOINT: + req_type = USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; + break; + case URB_FUNCTION_VENDOR_OTHER: + req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER; + break; + case URB_FUNCTION_CLASS_DEVICE: + req_type = USB_TYPE_CLASS | USB_RECIP_DEVICE; + break; + case URB_FUNCTION_CLASS_INTERFACE: + req_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; + break; + case URB_FUNCTION_CLASS_ENDPOINT: + req_type = USB_TYPE_CLASS | USB_RECIP_ENDPOINT; + break; + case URB_FUNCTION_CLASS_OTHER: + req_type = USB_TYPE_CLASS | USB_RECIP_OTHER; + break; + default: + ERROR("unknown request type: %x", nt_urb->header.function); + req_type = 0; + break; + } + + req_type |= vc_req->reserved_bits; + USBTRACE("req type: %08x", req_type); + + if (vc_req->transfer_flags & USBD_TRANSFER_DIRECTION_IN) { + pipe = usb_rcvctrlpipe(udev, 0); + req_type |= USB_DIR_IN; + USBTRACE("pipe: %x, dir in", pipe); + } else { + pipe = usb_sndctrlpipe(udev, 0); + req_type |= USB_DIR_OUT; + USBTRACE("pipe: %x, dir out", pipe); + } + urb = wrap_alloc_urb(irp, pipe, vc_req->transfer_buffer, + vc_req->transfer_buffer_length); + if (!urb) { + ERROR("couldn't allocate urb"); + return USBD_STATUS_NO_MEMORY; + } + + if (usb_pipein(pipe) && + (!(vc_req->transfer_flags & USBD_SHORT_TRANSFER_OK))) { + USBTRACE("short not ok"); + urb->transfer_flags |= URB_SHORT_NOT_OK; + } + + dr = kzalloc(sizeof(*dr), GFP_ATOMIC); + if (!dr) { + ERROR("couldn't allocate memory"); + wrap_free_urb(urb); + return USBD_STATUS_NO_MEMORY; + } + dr->bRequestType = req_type; + dr->bRequest = vc_req->request; + dr->wValue = cpu_to_le16(vc_req->value); + dr->wIndex = cpu_to_le16((u16)vc_req->index); + dr->wLength = cpu_to_le16((u16)urb->transfer_buffer_length); + + usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr, + urb->transfer_buffer, urb->transfer_buffer_length, + wrap_urb_complete, urb->context); + status = wrap_submit_urb(irp); + USBTRACE("status: %08X", status); + USBEXIT(return status); +} + +static USBD_STATUS wrap_reset_pipe(struct usb_device *udev, struct irp *irp) +{ + int ret; + union nt_urb *nt_urb; + usbd_pipe_handle pipe_handle; + unsigned int pipe1, pipe2; + + nt_urb = IRP_URB(irp); + pipe_handle = nt_urb->pipe_req.pipe_handle; + /* TODO: not clear if both directions should be cleared? */ + if (USBD_IS_BULK_PIPE(pipe_handle)) { + pipe1 = usb_rcvbulkpipe(udev, pipe_handle->bEndpointAddress); + pipe2 = usb_sndbulkpipe(udev, pipe_handle->bEndpointAddress); + } else if (USBD_IS_INT_PIPE(pipe_handle)) { + pipe1 = usb_rcvintpipe(udev, pipe_handle->bEndpointAddress); + pipe2 = pipe1; + } else { + WARNING("invalid pipe %d", pipe_handle->bEndpointAddress); + return USBD_STATUS_INVALID_PIPE_HANDLE; + } + USBTRACE("ep: %d, pipe: 0x%x", pipe_handle->bEndpointAddress, pipe1); + ret = usb_clear_halt(udev, pipe1); + if (ret) + USBTRACE("resetting pipe %d failed: %d", pipe1, ret); + if (pipe2 != pipe1) { + ret = usb_clear_halt(udev, pipe2); + if (ret) + USBTRACE("resetting pipe %d failed: %d", pipe2, ret); + } +// return wrap_urb_status(ret); + return USBD_STATUS_SUCCESS; +} + +static USBD_STATUS wrap_abort_pipe(struct usb_device *udev, struct irp *irp) +{ + union nt_urb *nt_urb; + usbd_pipe_handle pipe_handle; + struct wrap_urb *wrap_urb; + struct wrap_device *wd; + KIRQL irql; + + wd = IRP_WRAP_DEVICE(irp); + nt_urb = IRP_URB(irp); + pipe_handle = nt_urb->pipe_req.pipe_handle; + USBENTER("%p, %x", irp, pipe_handle->bEndpointAddress); + IoAcquireCancelSpinLock(&irql); + nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) { + USBTRACE("%p, %p, %d, %x, %x", wrap_urb, wrap_urb->urb, + wrap_urb->state, wrap_urb->urb->pipe, + usb_pipeendpoint(wrap_urb->urb->pipe)); + /* for WG111T driver, urbs for endpoint 0 should also + * be canceled */ + if ((usb_pipeendpoint(wrap_urb->urb->pipe) == + pipe_handle->bEndpointAddress) || + (usb_pipeendpoint(wrap_urb->urb->pipe) == 0)) { + if (wrap_cancel_urb(wrap_urb) == 0) + USBTRACE("canceled wrap_urb: %p", wrap_urb); + } + } + IoReleaseCancelSpinLock(irql); + NT_URB_STATUS(nt_urb) = USBD_STATUS_CANCELED; + USBEXIT(return USBD_STATUS_SUCCESS); +} + +static USBD_STATUS wrap_set_clear_feature(struct usb_device *udev, + struct irp *irp) +{ + union nt_urb *nt_urb; + struct urb_control_feature_request *feat_req; + int ret = 0; + __u8 request, type; + __u16 feature; + + nt_urb = IRP_URB(irp); + feat_req = &nt_urb->feat_req; + feature = feat_req->feature_selector; + switch (nt_urb->header.function) { + case URB_FUNCTION_SET_FEATURE_TO_DEVICE: + request = USB_REQ_SET_FEATURE; + type = USB_DT_DEVICE; + break; + case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: + request = USB_REQ_SET_FEATURE; + type = USB_DT_INTERFACE; + break; + case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: + request = USB_REQ_SET_FEATURE; + type = USB_DT_ENDPOINT; + break; + case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE: + request = USB_REQ_CLEAR_FEATURE; + type = USB_DT_DEVICE; + break; + case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: + request = USB_REQ_CLEAR_FEATURE; + type = USB_DT_INTERFACE; + break; + case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: + request = USB_REQ_CLEAR_FEATURE; + type = USB_DT_ENDPOINT; + break; + default: + WARNING("invalid function: %x", nt_urb->header.function); + NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED; + return NT_URB_STATUS(nt_urb); + } + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, type, + feature, feat_req->index, NULL, 0, 1000); + NT_URB_STATUS(nt_urb) = wrap_urb_status(ret); + USBEXIT(return NT_URB_STATUS(nt_urb)); +} + +static USBD_STATUS wrap_get_status_request(struct usb_device *udev, + struct irp *irp) +{ + union nt_urb *nt_urb; + struct urb_control_get_status_request *status_req; + int ret = 0; + __u8 type; + + nt_urb = IRP_URB(irp); + status_req = &nt_urb->status_req; + switch (nt_urb->header.function) { + case URB_FUNCTION_GET_STATUS_FROM_DEVICE: + type = USB_RECIP_DEVICE; + break; + case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: + type = USB_RECIP_INTERFACE; + break; + case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: + type = USB_RECIP_ENDPOINT; + break; + default: + WARNING("invalid function: %x", nt_urb->header.function); + NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED; + return NT_URB_STATUS(nt_urb); + } + assert(status_req->transfer_buffer_length == sizeof(u16)); + ret = usb_get_status(udev, type, status_req->index, + status_req->transfer_buffer); + if (ret >= 0) { + assert(ret <= status_req->transfer_buffer_length); + status_req->transfer_buffer_length = ret; + NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS; + } else + NT_URB_STATUS(nt_urb) = wrap_urb_status(ret); + USBEXIT(return NT_URB_STATUS(nt_urb)); +} + +static void set_intf_pipe_info(struct wrap_device *wd, + struct usb_interface *usb_intf, + struct usbd_interface_information *intf) +{ + int i; + struct usb_endpoint_descriptor *ep; + struct usbd_pipe_information *pipe; + + for (i = 0; i < CUR_ALT_SETTING(usb_intf)->desc.bNumEndpoints; i++) { + ep = &(CUR_ALT_SETTING(usb_intf)->endpoint[i]).desc; + if (i >= intf->bNumEndpoints) { + ERROR("intf %p has only %d endpoints, " + "ignoring endpoints above %d", + intf, intf->bNumEndpoints, i); + break; + } + pipe = &intf->pipes[i]; + + if (pipe->flags & USBD_PF_CHANGE_MAX_PACKET) + USBTRACE("pkt_sz: %d: %d", pipe->wMaxPacketSize, + pipe->max_tx_size); + USBTRACE("driver wants max_tx_size to %d", + pipe->max_tx_size); + + pipe->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); + pipe->bEndpointAddress = ep->bEndpointAddress; + pipe->type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (pipe->type == UsbdPipeTypeInterrupt) { + /* Windows and Linux differ in how the + * bInterval is interpretted */ + /* for low speed: + interval (Windows) -> frames per ms (Linux) + 0 to 15 -> 8 + 16 to 35 -> 16 + 36 to 255 -> 32 + + for full speed: interval -> frames per ms + 1 -> 1 + 2 to 3 -> 2 + 4 to 7 -> 4 + 8 to 15 -> 8 + 16 to 31 -> 16 + 32 to 255 -> 32 + + for high speed: interval -> microframes + 1 -> 1 + 2 -> 2 + 3 -> 4 + 4 -> 8 + 5 -> 16 + 6 -> 32 + 7 to 255 -> 32 + */ + if (wd->usb.udev->speed == USB_SPEED_LOW) + pipe->bInterval = ep->bInterval + 5; + else if (wd->usb.udev->speed == USB_SPEED_FULL) + pipe->bInterval = ep->bInterval; + else { + int j, k; + for (j = k = 1; j < ep->bInterval; k++) + j *= 2; + pipe->bInterval = k; + } + } + pipe->handle = ep; + USBTRACE("%d: ep 0x%x, type %d, pkt_sz %d, intv %d (%d)," + "type: %d, handle %p", i, ep->bEndpointAddress, + ep->bmAttributes, pipe->wMaxPacketSize, ep->bInterval, + pipe->bInterval, pipe->type, pipe->handle); + } +} + +static USBD_STATUS wrap_select_configuration(struct wrap_device *wd, + union nt_urb *nt_urb, + struct irp *irp) +{ + int i, ret; + struct usbd_select_configuration *sel_conf; + struct usb_device *udev; + struct usbd_interface_information *intf; + struct usb_config_descriptor *config; + struct usb_interface *usb_intf; + + udev = wd->usb.udev; + sel_conf = &nt_urb->select_conf; + config = sel_conf->config; + USBTRACE("%p", config); + if (config == NULL) { + kill_all_urbs(wd, 1); + ret = usb_reset_configuration(udev); + return wrap_urb_status(ret); + } + + USBTRACE("conf: %d, type: %d, length: %d, numif: %d, attr: %08x", + config->bConfigurationValue, config->bDescriptorType, + config->wTotalLength, config->bNumInterfaces, + config->bmAttributes); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_CONFIGURATION, 0, + config->bConfigurationValue, 0, + NULL, 0, USB_CTRL_SET_TIMEOUT); + if (ret < 0) { + ERROR("ret: %d", ret); + return wrap_urb_status(ret); + } + sel_conf->handle = udev->actconfig; + intf = &sel_conf->intf; + for (i = 0; i < config->bNumInterfaces && intf->bLength > 0; + i++, intf = (((void *)intf) + intf->bLength)) { + + USBTRACE("intf: %d, alt setting: %d", + intf->bInterfaceNumber, intf->bAlternateSetting); + ret = usb_set_interface(udev, intf->bInterfaceNumber, + intf->bAlternateSetting); + if (ret < 0) { + ERROR("failed with %d", ret); + return wrap_urb_status(ret); + } + usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber); + if (!usb_intf) { + ERROR("couldn't obtain ifnum"); + return USBD_STATUS_REQUEST_FAILED; + } + USBTRACE("intf: %p, num ep: %d", intf, intf->bNumEndpoints); + set_intf_pipe_info(wd, usb_intf, intf); + } + return USBD_STATUS_SUCCESS; +} + +static USBD_STATUS wrap_select_interface(struct wrap_device *wd, + union nt_urb *nt_urb, + struct irp *irp) +{ + int ret; + struct usbd_select_interface *sel_intf; + struct usb_device *udev; + struct usbd_interface_information *intf; + struct usb_interface *usb_intf; + + udev = wd->usb.udev; + sel_intf = &nt_urb->select_intf; + intf = &sel_intf->intf; + + ret = usb_set_interface(udev, intf->bInterfaceNumber, + intf->bAlternateSetting); + if (ret < 0) { + ERROR("failed with %d", ret); + return wrap_urb_status(ret); + } + usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber); + if (!usb_intf) { + ERROR("couldn't get interface information"); + return USBD_STATUS_REQUEST_FAILED; + } + USBTRACE("intf: %p, num ep: %d", usb_intf, intf->bNumEndpoints); + set_intf_pipe_info(wd, usb_intf, intf); + return USBD_STATUS_SUCCESS; +} + +static int wrap_usb_get_string(struct usb_device *udev, unsigned short langid, + unsigned char index, void *buf, int size) +{ + int i, ret; + /* if langid is 0, return array of langauges supported in + * buf */ + for (i = 0; i < 3; i++) { + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, + buf, size, USB_CTRL_GET_TIMEOUT); + if (ret > 0 || ret == -EPIPE) + break; + } + return ret; +} + +static USBD_STATUS wrap_get_descriptor(struct wrap_device *wd, + union nt_urb *nt_urb, struct irp *irp) +{ + struct usbd_control_descriptor_request *control_desc; + int ret = 0; + struct usb_device *udev; + + udev = wd->usb.udev; + control_desc = &nt_urb->control_desc; + USBTRACE("desctype = %d, descindex = %d, transfer_buffer = %p," + "transfer_buffer_length = %d", control_desc->desc_type, + control_desc->index, control_desc->transfer_buffer, + control_desc->transfer_buffer_length); + + if (control_desc->desc_type == USB_DT_STRING) { + USBTRACE("langid: %x", control_desc->language_id); + ret = wrap_usb_get_string(udev, control_desc->language_id, + control_desc->index, + control_desc->transfer_buffer, + control_desc->transfer_buffer_length); + } else { + ret = usb_get_descriptor(udev, control_desc->desc_type, + control_desc->index, + control_desc->transfer_buffer, + control_desc->transfer_buffer_length); + } + if (ret < 0) { + USBTRACE("request %d failed: %d", control_desc->desc_type, ret); + control_desc->transfer_buffer_length = 0; + return wrap_urb_status(ret); + } else { + USBTRACE("ret: %08x", ret); + control_desc->transfer_buffer_length = ret; + irp->io_status.info = ret; + return USBD_STATUS_SUCCESS; + } +} + +static USBD_STATUS wrap_process_nt_urb(struct irp *irp) +{ + union nt_urb *nt_urb; + struct usb_device *udev; + USBD_STATUS status; + struct wrap_device *wd; + + wd = IRP_WRAP_DEVICE(irp); + udev = wd->usb.udev; + nt_urb = IRP_URB(irp); + USBENTER("nt_urb = %p, irp = %p, length = %d, function = %x", + nt_urb, irp, nt_urb->header.length, nt_urb->header.function); + + DUMP_IRP(irp); + switch (nt_urb->header.function) { + /* bulk/int and vendor/class urbs are submitted to + * Linux USB core; if the call is sucessful, urb's + * completion worker will return IRP later */ + case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: + USBTRACE("submitting bulk/int irp: %p", irp); + status = wrap_bulk_or_intr_trans(irp); + break; + + case URB_FUNCTION_VENDOR_DEVICE: + case URB_FUNCTION_VENDOR_INTERFACE: + case URB_FUNCTION_VENDOR_ENDPOINT: + case URB_FUNCTION_VENDOR_OTHER: + case URB_FUNCTION_CLASS_DEVICE: + case URB_FUNCTION_CLASS_INTERFACE: + case URB_FUNCTION_CLASS_ENDPOINT: + case URB_FUNCTION_CLASS_OTHER: + USBTRACE("submitting vendor/class irp: %p", irp); + status = wrap_vendor_or_class_req(irp); + break; + + /* rest are synchronous */ + case URB_FUNCTION_SELECT_CONFIGURATION: + status = wrap_select_configuration(wd, nt_urb, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_SELECT_INTERFACE: + status = wrap_select_interface(wd, nt_urb, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: + status = wrap_get_descriptor(wd, nt_urb, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: + status = wrap_reset_pipe(udev, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_ABORT_PIPE: + status = wrap_abort_pipe(udev, irp); + break; + + case URB_FUNCTION_SET_FEATURE_TO_DEVICE: + case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: + case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: + case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE: + case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: + case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: + status = wrap_set_clear_feature(udev, irp); + break; + + case URB_FUNCTION_GET_STATUS_FROM_DEVICE: + case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: + case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: + status = wrap_get_status_request(udev, irp); + break; + + default: + ERROR("function %x not implemented", nt_urb->header.function); + status = NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED; + break; + } + USBTRACE("status: %08X", status); + return status; +} + +static USBD_STATUS wrap_reset_port(struct irp *irp) +{ + no_warn_unused int ret, lock = 0; + struct wrap_device *wd; + + wd = IRP_WRAP_DEVICE(irp); + USBENTER("%p, %p", wd, wd->usb.udev); + lock = usb_lock_device_for_reset(wd->usb.udev, wd->usb.intf); + if (lock < 0) { + WARNING("locking failed: %d", lock); +// return wrap_urb_status(lock); + return USBD_STATUS_SUCCESS; + } + ret = usb_reset_device(wd->usb.udev); + if (ret < 0) + USBTRACE("reset failed: %d", ret); + /* TODO: should reconfigure? */ + if (lock) + usb_unlock_device(wd->usb.udev); +// return wrap_urb_status(ret); + return USBD_STATUS_SUCCESS; +} + +static USBD_STATUS wrap_get_port_status(struct irp *irp) +{ + struct wrap_device *wd; + ULONG *status; + enum usb_device_state state; + + wd = IRP_WRAP_DEVICE(irp); + USBENTER("%p, %p", wd, wd->usb.udev); + status = IoGetCurrentIrpStackLocation(irp)->params.others.arg1; + state = wd->usb.udev->state; + if (state != USB_STATE_NOTATTACHED && + state != USB_STATE_SUSPENDED) { + *status |= USBD_PORT_CONNECTED; + if (state == USB_STATE_CONFIGURED) + *status |= USBD_PORT_ENABLED; + } + USBTRACE("state: %d, *status: %08X", state, *status); + return USBD_STATUS_SUCCESS; +} + +NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct wrap_device *wd; + USBD_STATUS status; + struct usbd_idle_callback *idle_callback; + + USBENTER("%p, %p", pdo, irp); + wd = pdo->reserved; + if (wd->usb.intf == NULL) { + USBTRACE("%p", irp); + irp->io_status.status = STATUS_DEVICE_REMOVED; + irp->io_status.info = 0; + USBEXIT(return STATUS_DEVICE_REMOVED); + } + IRP_WRAP_DEVICE(irp) = wd; + irp_sl = IoGetCurrentIrpStackLocation(irp); + switch (irp_sl->params.dev_ioctl.code) { + case IOCTL_INTERNAL_USB_SUBMIT_URB: + status = wrap_process_nt_urb(irp); + break; + case IOCTL_INTERNAL_USB_RESET_PORT: + status = wrap_reset_port(irp); + break; + case IOCTL_INTERNAL_USB_GET_PORT_STATUS: + status = wrap_get_port_status(irp); + break; + case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: + idle_callback = irp_sl->params.dev_ioctl.type3_input_buf; + USBTRACE("suspend function: %p", idle_callback->callback); + status = USBD_STATUS_NOT_SUPPORTED; + break; + default: + ERROR("ioctl %08X NOT IMPLEMENTED", + irp_sl->params.dev_ioctl.code); + status = USBD_STATUS_NOT_SUPPORTED; + break; + } + + USBTRACE("status: %08X", status); + if (status == USBD_STATUS_PENDING) { + /* don't touch this IRP - it may have been already + * completed/returned */ + return STATUS_PENDING; + } else { + irp->io_status.status = nt_urb_irp_status(status); + if (status != USBD_STATUS_SUCCESS) + irp->io_status.info = 0; + USBEXIT(return irp->io_status.status); + } +} + +/* TODO: The example on msdn in reference section suggests that second + * argument should be an array of usbd_interface_information, but + * description and examples elsewhere suggest that it should be + * usbd_interface_list_entry structre. Which is correct? */ + +wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequestEx,2) + (struct usb_config_descriptor *config, + struct usbd_interface_list_entry *intf_list) +{ + int size, i, n; + struct usbd_interface_information *intf; + struct usbd_pipe_information *pipe; + struct usb_interface_descriptor *intf_desc; + struct usbd_select_configuration *select_conf; + + USBENTER("config = %p, intf_list = %p", config, intf_list); + + /* calculate size required; select_conf already has space for + * one intf structure */ + size = sizeof(*select_conf) - sizeof(*intf); + for (n = 0; n < config->bNumInterfaces; n++) { + i = intf_list[n].intf_desc->bNumEndpoints; + /* intf already has space for one pipe */ + size += sizeof(*intf) + (i - 1) * sizeof(*pipe); + } + /* don't use kmalloc - driver frees it with ExFreePool */ + select_conf = ExAllocatePoolWithTag(NonPagedPool, size, + POOL_TAG('L', 'U', 'S', 'B')); + if (!select_conf) { + WARNING("couldn't allocate memory"); + return NULL; + } + memset(select_conf, 0, size); + intf = &select_conf->intf; + select_conf->handle = config; + for (n = 0; n < config->bNumInterfaces && intf_list[n].intf_desc; n++) { + /* initialize 'intf' fields in intf_list so they point + * to appropriate entry; these may be read/written by + * driver after this function returns */ + intf_list[n].intf = intf; + intf_desc = intf_list[n].intf_desc; + + i = intf_desc->bNumEndpoints; + intf->bLength = sizeof(*intf) + (i - 1) * sizeof(*pipe); + + intf->bInterfaceNumber = intf_desc->bInterfaceNumber; + intf->bAlternateSetting = intf_desc->bAlternateSetting; + intf->bInterfaceClass = intf_desc->bInterfaceClass; + intf->bInterfaceSubClass = intf_desc->bInterfaceSubClass; + intf->bInterfaceProtocol = intf_desc->bInterfaceProtocol; + intf->bNumEndpoints = intf_desc->bNumEndpoints; + + pipe = &intf->pipes[0]; + for (i = 0; i < intf->bNumEndpoints; i++) { + memset(&pipe[i], 0, sizeof(*pipe)); + pipe[i].max_tx_size = + USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; + } + intf->handle = intf_desc; + intf = (((void *)intf) + intf->bLength); + } + select_conf->header.function = URB_FUNCTION_SELECT_CONFIGURATION; + select_conf->header.length = size; + select_conf->config = config; + USBEXIT(return (union nt_urb *)select_conf); +} + +WIN_SYMBOL_MAP("_USBD_CreateConfigurationRequestEx@8", USBD_CreateConfigurationRequestEx) + +wstdcall struct usb_interface_descriptor * +WIN_FUNC(USBD_ParseConfigurationDescriptorEx,7) + (struct usb_config_descriptor *config, void *start, + LONG bInterfaceNumber, LONG bAlternateSetting, LONG bInterfaceClass, + LONG bInterfaceSubClass, LONG bInterfaceProtocol) +{ + void *pos; + struct usb_interface_descriptor *intf; + + USBENTER("config = %p, start = %p, ifnum = %d, alt_setting = %d," + " class = %d, subclass = %d, proto = %d", config, start, + bInterfaceNumber, bAlternateSetting, bInterfaceClass, + bInterfaceSubClass, bInterfaceProtocol); + + for (pos = start; + pos < ((void *)config + le16_to_cpu(config->wTotalLength)); + pos += intf->bLength) { + + intf = pos; + + if ((intf->bDescriptorType == USB_DT_INTERFACE) && + ((bInterfaceNumber == -1) || + (intf->bInterfaceNumber == bInterfaceNumber)) && + ((bAlternateSetting == -1) || + (intf->bAlternateSetting == bAlternateSetting)) && + ((bInterfaceClass == -1) || + (intf->bInterfaceClass == bInterfaceClass)) && + ((bInterfaceSubClass == -1) || + (intf->bInterfaceSubClass == bInterfaceSubClass)) && + ((bInterfaceProtocol == -1) || + (intf->bInterfaceProtocol == bInterfaceProtocol))) { + USBTRACE("selected interface = %p", intf); + USBEXIT(return intf); + } + } + USBEXIT(return NULL); +} + +WIN_SYMBOL_MAP("_USBD_ParseConfigurationDescriptorEx@28", USBD_ParseConfigurationDescriptorEx) + +wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequest,2) + (struct usb_config_descriptor *config, USHORT *size) +{ + union nt_urb *nt_urb; + struct usbd_interface_list_entry intf_list[2]; + struct usb_interface_descriptor *intf_desc; + + USBENTER("config = %p, urb_size = %p", config, size); + + intf_desc = USBD_ParseConfigurationDescriptorEx(config, config, -1, -1, + -1, -1, -1); + intf_list[0].intf_desc = intf_desc; + intf_list[0].intf = NULL; + intf_list[1].intf_desc = NULL; + intf_list[1].intf = NULL; + nt_urb = USBD_CreateConfigurationRequestEx(config, intf_list); + if (!nt_urb) + return NULL; + + *size = nt_urb->select_conf.header.length; + USBEXIT(return nt_urb); +} + +wstdcall struct usb_interface_descriptor * +WIN_FUNC(USBD_ParseConfigurationDescriptor,3) + (struct usb_config_descriptor *config, UCHAR bInterfaceNumber, + UCHAR bAlternateSetting) +{ + return USBD_ParseConfigurationDescriptorEx(config, config, + bInterfaceNumber, + bAlternateSetting, + -1, -1, -1); +} + +wstdcall usb_common_descriptor_t *WIN_FUNC(USBD_ParseDescriptors,4) + (void *buf, ULONG length, void *start, LONG type) +{ + usb_common_descriptor_t *descr = start; + + while ((void *)descr < buf + length) { + if (descr->bDescriptorType == type) + return descr; + if (descr->bLength == 0) + break; + descr = (void *)descr + descr->bLength; + } + USBEXIT(return NULL); +} + +WIN_SYMBOL_MAP("_USBD_ParseDescriptors@16", USBD_ParseDescriptors) + +wstdcall void WIN_FUNC(USBD_GetUSBDIVersion,1) + (struct usbd_version_info *version_info) +{ + /* this function is obsolete in Windows XP */ + if (version_info) { + version_info->usbdi_version = USBDI_VERSION_XP; + /* TODO: how do we get this correctly? */ + version_info->supported_usb_version = 0x110; + } + USBEXIT(return); +} + +wstdcall void +USBD_InterfaceGetUSBDIVersion(void *context, + struct usbd_version_info *version_info, + ULONG *hcd_capa) +{ + struct wrap_device *wd = context; + + if (version_info) { + version_info->usbdi_version = USBDI_VERSION_XP; + if (wd->usb.udev->speed == USB_SPEED_HIGH) + version_info->supported_usb_version = 0x200; + else + version_info->supported_usb_version = 0x110; + } + *hcd_capa = USB_HCD_CAPS_SUPPORTS_RT_THREADS; + USBEXIT(return); +} + +wstdcall BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context) +{ + struct wrap_device *wd = context; + + USBTRACE("wd: %p", wd); + if (wd->usb.udev->speed == USB_SPEED_HIGH) + USBEXIT(return TRUE); + else + USBEXIT(return FALSE); +} + +wstdcall void USBD_InterfaceReference(void *context) +{ + USBTRACE("%p", context); + TODO(); +} + +wstdcall void USBD_InterfaceDereference(void *context) +{ + USBTRACE("%p", context); + TODO(); +} + +wstdcall NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame) +{ + struct wrap_device *wd = context; + + *frame = usb_get_current_frame_number(wd->usb.udev); + USBEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context, + union nt_urb *nt_urb) +{ + /* TODO: implement this */ + TODO(); + USBEXIT(return STATUS_NOT_IMPLEMENTED); +} + +wstdcall NTSTATUS +USBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf, + ULONG *buf_length, ULONG *buf_actual_length) +{ + struct wrap_device *wd = context; + struct usb_bus_information_level *bus_info; + struct usb_bus *bus; + + bus = wd->usb.udev->bus; + bus_info = buf; + TODO(); + USBEXIT(return STATUS_NOT_IMPLEMENTED); +} + +wstdcall NTSTATUS +USBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag, + ULONG p1, ULONG p2) +{ + ERROR("%p, %x, %x, %x, %x", context, driver_tag, enum_tag, p1, p2); + USBEXIT(return STATUS_SUCCESS); +} + +int usb_init(void) +{ + InitializeListHead(&wrap_urb_complete_list); + spin_lock_init(&wrap_urb_complete_list_lock); + initialize_work(&wrap_urb_complete_work, wrap_urb_complete_worker, NULL); +#ifdef USB_DEBUG + urb_id = 0; +#endif + return 0; +} + +void usb_exit(void) +{ + USBEXIT(return); +} + +int usb_init_device(struct wrap_device *wd) +{ + InitializeListHead(&wd->usb.wrap_urb_list); + wd->usb.num_alloc_urbs = 0; + USBEXIT(return 0); +} + +void usb_exit_device(struct wrap_device *wd) +{ + kill_all_urbs(wd, 0); + USBEXIT(return); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/wrapmem.c +++ linux-2.6.27/ubuntu/ndiswrapper/wrapmem.c @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2006 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define _WRAPMEM_C_ + +#include "ntoskernel.h" + +struct slack_alloc_info { + struct nt_list list; + size_t size; +}; + +static struct nt_list allocs; +static struct nt_list slack_allocs; +static spinlock_t alloc_lock; + +struct vmem_block { + struct nt_list list; + int size; +}; + +static struct nt_list vmem_list; + +#if defined(ALLOC_DEBUG) +struct alloc_info { + enum alloc_type type; + size_t size; +#if ALLOC_DEBUG > 1 + struct nt_list list; + const char *file; + int line; + ULONG tag; +#endif +}; + +static atomic_t alloc_sizes[ALLOC_TYPE_MAX]; +#endif + +void wrapmem_info(void) +{ +#ifdef ALLOC_DEBUG + enum alloc_type type; + for (type = 0; type < ALLOC_TYPE_MAX; type++) + INFO("total size of allocations in %d: %d", + type, atomic_read(&alloc_sizes[type])); +#endif +} + +/* allocate memory and add it to list of allocated pointers; if a + * driver doesn't free this memory for any reason (buggy driver or we + * allocate space behind driver's back since we need more space than + * corresponding Windows structure provides etc.), this gets freed + * automatically when module is unloaded + */ +void *slack_kmalloc(size_t size) +{ + struct slack_alloc_info *info; + gfp_t flags; + + ENTER4("size = %lu", (unsigned long)size); + + if (irql_gfp() & GFP_ATOMIC) + flags = GFP_ATOMIC; + else + flags = GFP_KERNEL; + info = kmalloc(size + sizeof(*info), flags); + if (!info) + return NULL; + info->size = size; + spin_lock_bh(&alloc_lock); + InsertTailList(&slack_allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#ifdef ALLOC_DEBUG + atomic_add(size, &alloc_sizes[ALLOC_TYPE_SLACK]); +#endif + TRACE4("%p, %p", info, info + 1); + EXIT4(return info + 1); +} + +/* free pointer and remove from list of allocated pointers */ +void slack_kfree(void *ptr) +{ + struct slack_alloc_info *info; + + ENTER4("%p", ptr); + info = ptr - sizeof(*info); + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); +#ifdef ALLOC_DEBUG + atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]); +#endif + kfree(info); + EXIT4(return); +} + +#if defined(ALLOC_DEBUG) +void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line) +{ + struct alloc_info *info; + + info = kmalloc(size + sizeof(*info), flags); + if (!info) + return NULL; + if (flags & GFP_ATOMIC) + info->type = ALLOC_TYPE_KMALLOC_ATOMIC; + else + info->type = ALLOC_TYPE_KMALLOC_NON_ATOMIC; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + TRACE4("%p", info + 1); + return (info + 1); +} + +void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line) +{ + void *ptr = wrap_kmalloc(size, flags, file, line); + if (ptr) + memset(ptr, 0, size); + return ptr; +} + +void wrap_kfree(void *ptr) +{ + struct alloc_info *info; + + TRACE4("%p", ptr); + if (!ptr) + return; + info = ptr - sizeof(*info); + atomic_sub(info->size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); + if (!(info->type == ALLOC_TYPE_KMALLOC_ATOMIC || + info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC)) + WARNING("invliad type: %d", info->type); +#endif + kfree(info); +} + +void *wrap_vmalloc(unsigned long size, const char *file, int line) +{ + struct alloc_info *info; + + info = vmalloc(size + sizeof(*info)); + if (!info) + return NULL; + info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + return (info + 1); +} + +void *wrap__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot, + const char *file, int line) +{ + struct alloc_info *info; + + info = __vmalloc(size + sizeof(*info), gfp_mask, prot); + if (!info) + return NULL; + if (gfp_mask & GFP_ATOMIC) + info->type = ALLOC_TYPE_VMALLOC_ATOMIC; + else + info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + return (info + 1); +} + +void wrap_vfree(void *ptr) +{ + struct alloc_info *info; + + info = ptr - sizeof(*info); + atomic_sub(info->size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); + if (!(info->type == ALLOC_TYPE_VMALLOC_ATOMIC || + info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC)) + WARNING("invliad type: %d", info->type); +#endif + vfree(info); +} + +void *wrap_alloc_pages(gfp_t flags, unsigned int size, + const char *file, int line) +{ + struct alloc_info *info; + + size += sizeof(*info); + info = (struct alloc_info *)__get_free_pages(flags, get_order(size)); + if (!info) + return NULL; + info->type = ALLOC_TYPE_PAGES; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + return info + 1; +} + +void wrap_free_pages(unsigned long ptr, int order) +{ + struct alloc_info *info; + + info = (void *)ptr - sizeof(*info); + atomic_sub(info->size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); + if (info->type != ALLOC_TYPE_PAGES) + WARNING("invliad type: %d", info->type); +#endif + free_pages((unsigned long)info, get_order(info->size)); +} + +#if ALLOC_DEBUG > 1 +#undef ExAllocatePoolWithTag +void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size, + ULONG tag, const char *file, int line) +{ + void *addr; + struct alloc_info *info; + + ENTER4("pool_type: %d, size: %lu, tag: %u", pool_type, size, tag); + addr = ExAllocatePoolWithTag(pool_type, size, tag); + if (!addr) + return NULL; + info = addr - sizeof(*info); + info->file = file; + info->line = line; + info->tag = tag; + EXIT4(return addr); +} +#endif + +int alloc_size(enum alloc_type type) +{ + if (type >= 0 && type < ALLOC_TYPE_MAX) + return atomic_read(&alloc_sizes[type]); + else + return -EINVAL; +} + +#endif // ALLOC_DEBUG + +int wrapmem_init(void) +{ + InitializeListHead(&allocs); + InitializeListHead(&slack_allocs); + InitializeListHead(&vmem_list); + spin_lock_init(&alloc_lock); + return 0; +} + +void wrapmem_exit(void) +{ + enum alloc_type type; + struct nt_list *ent; + + /* free all pointers on the slack list */ + while (1) { + struct slack_alloc_info *info; + spin_lock_bh(&alloc_lock); + ent = RemoveHeadList(&slack_allocs); + spin_unlock_bh(&alloc_lock); + if (!ent) + break; + info = container_of(ent, struct slack_alloc_info, list); +#ifdef ALLOC_DEBUG + atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]); +#endif + kfree(info); + } + type = 0; +#ifdef ALLOC_DEBUG + for (type = 0; type < ALLOC_TYPE_MAX; type++) { + int n = atomic_read(&alloc_sizes[type]); + if (n) + WARNING("%d bytes of memory in %d leaking", n, type); + } + +#if ALLOC_DEBUG > 1 + while (1) { + struct alloc_info *info; + + spin_lock_bh(&alloc_lock); + ent = RemoveHeadList(&allocs); + spin_unlock_bh(&alloc_lock); + if (!ent) + break; + info = container_of(ent, struct alloc_info, list); + atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]); + WARNING("%p in %d of size %zu allocated at %s(%d) " + "with tag 0x%08X leaking; freeing it now", + info + 1, info->type, info->size, info->file, + info->line, info->tag); + if (info->type == ALLOC_TYPE_KMALLOC_ATOMIC || + info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC) + kfree(info); + else if (info->type == ALLOC_TYPE_VMALLOC_ATOMIC || + info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC) + vfree(info); + else if (info->type == ALLOC_TYPE_PAGES) + free_pages((unsigned long)info, get_order(info->size)); + else + WARNING("invalid type: %d; not freed", info->type); + } +#endif +#endif + return; +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/rtl.c +++ linux-2.6.27/ubuntu/ndiswrapper/rtl.c @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ntoskernel.h" +#include "rtl_exports.h" + +wstdcall SIZE_T WIN_FUNC(RtlCompareMemory,3) + (const void *a, const void *b, SIZE_T len) +{ + size_t i; + char *x, *y; + + x = (char *)a; + y = (char *)b; + /* MSDN says this should return number of bytes that compare as + * equal. This can be interpretted as either all bytes that are + * equal in 'len' bytes or that only until the bytes compare as + * not equal. Initially we had it the former way, but Realtek driver + * doesn't like it that way - it takes many attempts to associate + * with WPA. ReactOS returns the number of bytes that are equal + * upto when they compare as not equal. + * According to lords at #reactos, that is the way it should be + * and that msdn is wrong about it! + */ + for (i = 0; i < len && x[i] == y[i]; i++) + ; + return i; +} + +wstdcall void WIN_FUNC(RtlCopyMemory,3) + (void *dst, const void *src, SIZE_T length) +{ + memcpy(dst, src, length); +} + +wstdcall void WIN_FUNC(RtlZeroMemory,2) + (void *dst, SIZE_T length) +{ + memset(dst, 0, length); +} + +wstdcall void WIN_FUNC(RtlSecureZeroMemory,2) + (void *dst, SIZE_T length) +{ + memset(dst, 0, length); +} + +wstdcall void WIN_FUNC(RtlFillMemory,3) + (void *dest, SIZE_T length, UCHAR fill) +{ + memset(dest, fill, length); +} + +wstdcall void WIN_FUNC(RtlMoveMemory,3) + (void *dest, const void *src, SIZE_T length) +{ + memmove(dest, src, length); +} + +wstdcall LONG WIN_FUNC(RtlCompareString,3) + (const struct ansi_string *s1, const struct ansi_string *s2, + BOOLEAN case_insensitive) +{ + unsigned int len; + LONG ret = 0; + const char *p1, *p2; + + ENTER2(""); + len = min(s1->length, s2->length); + p1 = s1->buf; + p2 = s2->buf; + if (case_insensitive) + while (!ret && len--) + ret = toupper(*p1++) - toupper(*p2++); + else + while (!ret && len--) + ret = *p1++ - *p2++; + if (!ret) + ret = s1->length - s2->length; + EXIT2(return ret); +} + +wstdcall LONG WIN_FUNC(RtlCompareUnicodeString,3) + (const struct unicode_string *s1, const struct unicode_string *s2, + BOOLEAN case_insensitive) +{ + unsigned int len; + LONG ret = 0; + const wchar_t *p1, *p2; + + ENTER2(""); + + len = min(s1->length, s2->length) / sizeof(wchar_t); + p1 = s1->buf; + p2 = s2->buf; + if (case_insensitive) + while (!ret && len--) + ret = toupper((u8)*p1++) - toupper((u8)*p2++); + else + while (!ret && len--) + ret = (u8)*p1++ - (u8)*p2++; + if (!ret) + ret = s1->length - s2->length; + TRACE2("len: %d, ret: %d", len, ret); + EXIT2(return ret); +} + +wstdcall BOOLEAN WIN_FUNC(RtlEqualString,3) + (const struct ansi_string *s1, const struct ansi_string *s2, + BOOLEAN case_insensitive) +{ + ENTER1(""); + if (s1->length != s2->length) + return FALSE; + return !RtlCompareString(s1, s2, case_insensitive); +} + +wstdcall BOOLEAN WIN_FUNC(RtlEqualUnicodeString,3) + (const struct unicode_string *s1, const struct unicode_string *s2, + BOOLEAN case_insensitive) +{ + if (s1->length != s2->length) + return FALSE; + return !RtlCompareUnicodeString(s1, s2, case_insensitive); +} + +wstdcall void WIN_FUNC(RtlCopyUnicodeString,2) + (struct unicode_string *dst, struct unicode_string *src) +{ + ENTER1("%p, %p", dst, src); + if (src && src->buf && dst->buf) { + dst->length = min(src->length, dst->max_length); + memcpy(dst->buf, src->buf, dst->length); + if (dst->length < dst->max_length) + dst->buf[dst->length / sizeof(dst->buf[0])] = 0; + } else + dst->length = 0; + EXIT1(return); +} + +wstdcall void WIN_FUNC(RtlCopyString,2) + (struct ansi_string *dst, struct ansi_string *src) +{ + ENTER1("%p, %p", dst, src); + if (src && src->buf && dst->buf) { + dst->length = min(src->length, dst->max_length); + memcpy(dst->buf, src->buf, dst->length); + if (dst->length < dst->max_length) + dst->buf[dst->length] = 0; + } else + dst->length = 0; + EXIT1(return); +} + +wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeToString,2) + (struct unicode_string *dst, wchar_t *src) +{ + if (src) { + int len; + for (len = 0; src[len]; len++) + ; + if (dst->length + (len * sizeof(dst->buf[0])) > dst->max_length) + return STATUS_BUFFER_TOO_SMALL; + memcpy(&dst->buf[dst->length], src, len * sizeof(dst->buf[0])); + dst->length += len * sizeof(dst->buf[0]); + if (dst->max_length > dst->length) + dst->buf[dst->length / sizeof(dst->buf[0])] = 0; + } + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeStringToString,2) + (struct unicode_string *dst, struct unicode_string *src) +{ + if (dst->max_length < src->length + dst->length) + return STATUS_BUFFER_TOO_SMALL; + if (src->length) { + memcpy(&dst->buf[dst->length], src->buf, src->length); + dst->length += src->length; + if (dst->max_length > dst->length) + dst->buf[dst->length / sizeof(dst->buf[0])] = 0; + } + EXIT2(return STATUS_SUCCESS); +} + +wstdcall ULONG WIN_FUNC(RtlxAnsiStringToUnicodeSize,1) + (const struct ansi_string *string) +{ + int i; + + for (i = 0; i < string->max_length && string->buf[i]; i++) + ; + return (i * sizeof(wchar_t)); +} + +wstdcall ULONG WIN_FUNC(RtlxUnicodeStringToAnsiSize,1) + (const struct unicode_string *string) +{ + int i; + + for (i = 0; i < string->max_length && string->buf[i]; i++) + ; + return i; +} + +wstdcall NTSTATUS WIN_FUNC(RtlAnsiStringToUnicodeString,3) + (struct unicode_string *dst, const struct ansi_string *src, + BOOLEAN alloc) +{ + int i, n; + + n = RtlxAnsiStringToUnicodeSize(src); + TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length, + src->max_length, src->buf); + if (alloc == TRUE) { +#if 0 + if (n == 0) { + dst->length = dst->max_length = 0; + dst->buf = NULL; + EXIT2(return STATUS_SUCCESS); + } +#endif + dst->max_length = n + sizeof(dst->buf[0]); + dst->buf = ExAllocatePoolWithTag(NonPagedPool, + dst->max_length, 0); + if (!dst->buf) { + dst->max_length = dst->length = 0; + EXIT2(return STATUS_NO_MEMORY); + } + } else if (dst->max_length < n) + EXIT2(return STATUS_BUFFER_TOO_SMALL); + + dst->length = n; + n /= sizeof(dst->buf[0]); + for (i = 0; i < n; i++) + dst->buf[i] = src->buf[i]; + if (i * sizeof(dst->buf[0]) < dst->max_length) + dst->buf[i] = 0; + TRACE2("dst: length: %d, max_length: %d, string: %p", + dst->length, dst->max_length, src->buf); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToAnsiString,3) + (struct ansi_string *dst, const struct unicode_string *src, + BOOLEAN alloc) +{ + int i, n; + + n = RtlxUnicodeStringToAnsiSize(src); + TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length, + src->max_length, src->buf); + if (alloc == TRUE) { +#if 0 + if (n == 0) { + dst->length = dst->max_length = 0; + dst->buf = NULL; + EXIT2(return STATUS_SUCCESS); + } +#endif + dst->max_length = n + sizeof(dst->buf[0]); + dst->buf = ExAllocatePoolWithTag(NonPagedPool, + dst->max_length, 0); + if (!dst->buf) { + dst->max_length = dst->length = 0; + EXIT1(return STATUS_NO_MEMORY); + } + } else if (dst->max_length < n) + EXIT2(return STATUS_BUFFER_TOO_SMALL); + + dst->length = n; + for (i = 0; i < n; i++) + dst->buf[i] = src->buf[i]; + if (i < dst->max_length) + dst->buf[i] = 0; + TRACE2("string: %p, len: %d(%d)", dst->buf, dst->length, + dst->max_length); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToInteger,3) + (struct unicode_string *ustring, ULONG base, ULONG *value) +{ + int i, sign = 1; + ULONG res; + typeof(ustring->buf) string; + + if (ustring->length == 0) { + *value = 0; + return STATUS_SUCCESS; + } + + string = ustring->buf; + i = 0; + while (i < (ustring->length / sizeof(*string)) && string[i] == ' ') + i++; + if (string[i] == '+') + i++; + else if (string[i] == '-') { + i++; + sign = -1; + } + if (base == 0) { + base = 10; + if (i <= ((ustring->length / sizeof(*string)) - 2) && + string[i] == '0') { + i++; + if (string[i] == 'b') { + base = 2; + i++; + } else if (string[i] == 'o') { + base = 8; + i++; + } else if (string[i] == 'x') { + base = 16; + i++; + } + } + } + if (!(base == 2 || base == 8 || base == 10 || base == 16)) + EXIT2(return STATUS_INVALID_PARAMETER); + + for (res = 0; i < (ustring->length / sizeof(*string)); i++) { + int v; + if (isdigit((char)string[i])) + v = string[i] - '0'; + else if (isxdigit((char)string[i])) + v = tolower((char)string[i]) - 'a' + 10; + else + v = base; + if (v >= base) + EXIT2(return STATUS_INVALID_PARAMETER); + res = res * base + v; + } + *value = sign * res; + EXIT3(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlCharToInteger,3) + (const char *string, ULONG base, ULONG *value) +{ + int sign = 1; + ULONG res; + + if (!string || !value) + EXIT2(return STATUS_INVALID_PARAMETER); + while (*string == ' ') + string++; + if (*string == '+') + string++; + else if (*string == '-') { + string++; + sign = -1; + } + if (base == 0) { + base = 10; + if (*string == '0') { + string++; + if (*string == 'b') { + base = 2; + string++; + } else if (*string == 'o') { + base = 8; + string++; + } else if (*string == 'x') { + base = 16; + string++; + } + } + } + if (!(base == 2 || base == 8 || base == 10 || base == 16)) + EXIT2(return STATUS_INVALID_PARAMETER); + + for (res = 0; *string; string++) { + int v; + if (isdigit(*string)) + v = *string - '0'; + else if (isxdigit(*string)) + v = tolower(*string) - 'a' + 10; + else + v = base; + if (v >= base) + EXIT2(return STATUS_INVALID_PARAMETER); + res = res * base + v; + } + *value = sign * res; + EXIT3(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlIntegerToUnicodeString,3) + (ULONG value, ULONG base, struct unicode_string *ustring) +{ + typeof(ustring->buf) buf = ustring->buf; + int i; + + if (base == 0) + base = 10; + if (!(base == 2 || base == 8 || base == 10 || base == 16)) + return STATUS_INVALID_PARAMETER; + for (i = 0; value && i < ustring->max_length / sizeof(*buf); i++) { + int r; + r = value % base; + value /= base; + if (r < 10) + buf[i] = r + '0'; + else + buf[i] = r + 'a' - 10; + } + if (value) + return STATUS_BUFFER_OVERFLOW; + ustring->length = i * sizeof(*buf); + return STATUS_SUCCESS; +} + +wstdcall LARGE_INTEGER WIN_FUNC(RtlConvertUlongToLargeInteger,1) + (ULONG ul) +{ + LARGE_INTEGER li = ul; + return li; +} + +wfastcall USHORT WIN_FUNC(RtlUshortByteSwap,1) + (USHORT src) +{ + return __swab16(src); +} + +wfastcall ULONG WIN_FUNC(RtlUlongByteSwap,1) + (ULONG src) +{ + /* ULONG is 32 bits for both 32-bit and 64-bit architectures */ + return __swab32(src); +} + +wstdcall NTSTATUS WIN_FUNC(RtlUpcaseUnicodeString,3) + (struct unicode_string *dst, struct unicode_string *src, BOOLEAN alloc) +{ + USHORT i, n; + + if (alloc) { + dst->buf = ExAllocatePoolWithTag(NonPagedPool, src->length, 0); + if (dst->buf) { + dst->max_length = src->length; + } else + EXIT2(return STATUS_NO_MEMORY); + } else { + if (dst->max_length < src->length) + EXIT2(return STATUS_BUFFER_OVERFLOW); + } + + n = src->length / sizeof(src->buf[0]); + for (i = 0; i < n; i++) + dst->buf[i] = toupper(src->buf[i]); + + dst->length = src->length; + EXIT3(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(RtlInitUnicodeString,2) + (struct unicode_string *dst, const wchar_t *src) +{ + ENTER2("%p", dst); + if (dst == NULL) + EXIT1(return); + if (src == NULL) { + dst->max_length = dst->length = 0; + dst->buf = NULL; + } else { + int i; + for (i = 0; (char)src[i]; i++) + ; + dst->buf = (typeof(dst->buf))src; + dst->length = i * sizeof(dst->buf[0]); + dst->max_length = (i + 1) * sizeof(dst->buf[0]); + } + EXIT1(return); +} + +wstdcall void WIN_FUNC(RtlInitAnsiString,2) + (struct ansi_string *dst, const char *src) +{ + ENTER2("%p", dst); + if (dst == NULL) + EXIT2(return); + if (src == NULL) { + dst->max_length = dst->length = 0; + dst->buf = NULL; + } else { + int i; + for (i = 0; src[i]; i++) + ; + dst->buf = (typeof(dst->buf))src; + dst->length = i; + dst->max_length = i + 1; + } + TRACE2("%p", dst->buf); + EXIT2(return); +} + +wstdcall void WIN_FUNC(RtlInitString,2) + (struct ansi_string *dst, const char *src) +{ + ENTER2("%p", dst); + RtlInitAnsiString(dst, src); + EXIT2(return); +} + +wstdcall void WIN_FUNC(RtlFreeUnicodeString,1) + (struct unicode_string *string) +{ + ENTER2("%p", string); + if (string == NULL) + return; + if (string->buf) + ExFreePool(string->buf); + string->length = string->max_length = 0; + string->buf = NULL; + return; +} + +wstdcall void WIN_FUNC(RtlFreeAnsiString,1) + (struct ansi_string *string) +{ + ENTER2("%p", string); + if (string == NULL) + return; + if (string->buf) + ExFreePool(string->buf); + string->length = string->max_length = 0; + string->buf = NULL; + return; +} + +/* guid string is of the form: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */ +wstdcall NTSTATUS WIN_FUNC(RtlGUIDFromString,2) + (struct unicode_string *guid_string, struct guid *guid) +{ + struct ansi_string ansi; + NTSTATUS ret; + int i, j, k, l, m; + + ret = RtlUnicodeStringToAnsiString(&ansi, guid_string, TRUE); + if (ret != STATUS_SUCCESS) + return ret; + if (ansi.length != 37 || ansi.buf[0] != '{' || + ansi.buf[36] != '}' || ansi.buf[9] != '-' || + ansi.buf[14] != '-' || ansi.buf[19] != '-' || + ansi.buf[24] != '-') { + RtlFreeAnsiString(&ansi); + EXIT2(return STATUS_INVALID_PARAMETER); + } + memcpy(&guid->data4, &ansi.buf[29], sizeof(guid->data3)); + /* set end of data3 for scanf */ + ansi.buf[29] = 0; + if (sscanf(&ansi.buf[1], "%x", &i) == 1 && + sscanf(&ansi.buf[10], "%x", &j) == 1 && + sscanf(&ansi.buf[15], "%x", &k) == 1 && + sscanf(&ansi.buf[20], "%x", &l) == 1 && + sscanf(&ansi.buf[25], "%x", &m) == 1) { + guid->data1 = (i << 16) | (j < 8) | k; + guid->data2 = l; + guid->data3 = m; + ret = STATUS_SUCCESS; + } else + ret = STATUS_INVALID_PARAMETER; + RtlFreeAnsiString(&ansi); + return ret; +} + +wstdcall NTSTATUS WIN_FUNC(RtlQueryRegistryValues,5) + (ULONG relative, wchar_t *path, struct rtl_query_registry_table *tbl, + void *context, void *env) +{ + struct ansi_string ansi; + struct unicode_string unicode; + NTSTATUS status, ret; + static int i = 0; + + ENTER3("%x, %p", relative, tbl); +// TODO(); + + RtlInitUnicodeString(&unicode, path); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + ret = STATUS_SUCCESS; + for (; tbl->name; tbl++) { + RtlInitUnicodeString(&unicode, tbl->name); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("name: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + TRACE2("flags: %08X", tbl->flags); + if (tbl->flags == RTL_QUERY_REGISTRY_DIRECT) { + TRACE2("type: %08X", tbl->def_type); + if (tbl->def_type == REG_DWORD) { + /* Atheros USB driver needs this, but + * don't know where and how to get its + * value */ + if (tbl->def_data) { + TRACE2("def_data: %x", + *(int *)tbl->def_data); + *(DWORD *)tbl->context = 0x5f292a + i++; +// *(DWORD *)tbl->def_data; + } else + *(DWORD *)tbl->context = 0x2345dbe; + } + } else { + void *data; + ULONG type, length; + + if (!tbl->query_func) { + ERROR("oops: no query_func"); + ret = STATUS_INVALID_PARAMETER; + break; + } + if (tbl->flags & RTL_QUERY_REGISTRY_NOVALUE) { + data = NULL; + type = REG_NONE; + length = 0; + } else { + data = tbl->def_data; + type = tbl->def_type; + length = tbl->def_length;; + } + TRACE2("calling query_func: %p", tbl->query_func); + status = LIN2WIN6(tbl->query_func, tbl->name, type, + data, length, context, env); + TRACE2("status: %08X", status); + if (status) { + if (status == STATUS_BUFFER_TOO_SMALL) + ret = STATUS_BUFFER_TOO_SMALL; + else + EXIT2(return STATUS_INVALID_PARAMETER); + } + } + } + EXIT3(return ret); +} + +wstdcall NTSTATUS WIN_FUNC(RtlWriteRegistryValue,6) + (ULONG relative, wchar_t *path, wchar_t *name, ULONG type, + void *data, ULONG length) +{ + struct ansi_string ansi; + struct unicode_string unicode; + + ENTER3("%d", relative); + TODO(); + + RtlInitUnicodeString(&unicode, path); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + RtlInitUnicodeString(&unicode, name); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + EXIT5(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlDeleteRegistryValue,3) + (ULONG relative, wchar_t *path, wchar_t *name) +{ + return STATUS_SUCCESS; +} + +wstdcall void WIN_FUNC(RtlAssert,4) + (char *failed_assertion, char *file_name, ULONG line_num, char *message) +{ + ERROR("assertion '%s' failed at %s line %d%s", + failed_assertion, file_name, line_num, message ? message : ""); + return; +} + +wstdcall void WIN_FUNC(RtlUnwind,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(RtlRaiseException,1) + (void *exception_record) +{ + TODO(); +} + +int rtl_init(void) +{ + return 0; +} + +/* called when module is being removed */ +void rtl_exit(void) +{ + EXIT4(return); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/pe_linker.h +++ linux-2.6.27/ubuntu/ndiswrapper/pe_linker.h @@ -0,0 +1,993 @@ +/* + * This file is an excerpt of winnt.h from WINE, which bears the + * following copyright: + * + * Win32 definitions for Windows NT + * + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * File formats definitions + */ +typedef struct _IMAGE_DOS_HEADER { + WORD e_magic; /* 00: MZ Header signature */ + WORD e_cblp; /* 02: Bytes on last page of file */ + WORD e_cp; /* 04: Pages in file */ + WORD e_crlc; /* 06: Relocations */ + WORD e_cparhdr; /* 08: Size of header in paragraphs */ + WORD e_minalloc; /* 0a: Minimum extra paragraphs needed */ + WORD e_maxalloc; /* 0c: Maximum extra paragraphs needed */ + WORD e_ss; /* 0e: Initial (relative) SS value */ + WORD e_sp; /* 10: Initial SP value */ + WORD e_csum; /* 12: Checksum */ + WORD e_ip; /* 14: Initial IP value */ + WORD e_cs; /* 16: Initial (relative) CS value */ + WORD e_lfarlc; /* 18: File address of relocation table */ + WORD e_ovno; /* 1a: Overlay number */ + WORD e_res[4]; /* 1c: Reserved words */ + WORD e_oemid; /* 24: OEM identifier (for e_oeminfo) */ + WORD e_oeminfo; /* 26: OEM information; e_oemid specific */ + WORD e_res2[10]; /* 28: Reserved words */ + DWORD e_lfanew; /* 3c: Offset to extended header */ +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */ +#define IMAGE_OS2_SIGNATURE 0x454E /* NE */ +#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */ +#define IMAGE_OS2_SIGNATURE_LX 0x584C /* LX */ +#define IMAGE_VXD_SIGNATURE 0x454C /* LE */ +#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ + +/* + * This is the Windows executable (NE) header. + * the name IMAGE_OS2_HEADER is misleading, but in the SDK this way. + */ +typedef struct +{ + WORD ne_magic; /* 00 NE signature 'NE' */ + BYTE ne_ver; /* 02 Linker version number */ + BYTE ne_rev; /* 03 Linker revision number */ + WORD ne_enttab; /* 04 Offset to entry table relative to NE */ + WORD ne_cbenttab; /* 06 Length of entry table in bytes */ + LONG ne_crc; /* 08 Checksum */ + WORD ne_flags; /* 0c Flags about segments in this file */ + WORD ne_autodata; /* 0e Automatic data segment number */ + WORD ne_heap; /* 10 Initial size of local heap */ + WORD ne_stack; /* 12 Initial size of stack */ + DWORD ne_csip; /* 14 Initial CS:IP */ + DWORD ne_sssp; /* 18 Initial SS:SP */ + WORD ne_cseg; /* 1c # of entries in segment table */ + WORD ne_cmod; /* 1e # of entries in module reference tab. */ + WORD ne_cbnrestab; /* 20 Length of nonresident-name table */ + WORD ne_segtab; /* 22 Offset to segment table */ + WORD ne_rsrctab; /* 24 Offset to resource table */ + WORD ne_restab; /* 26 Offset to resident-name table */ + WORD ne_modtab; /* 28 Offset to module reference table */ + WORD ne_imptab; /* 2a Offset to imported name table */ + DWORD ne_nrestab; /* 2c Offset to nonresident-name table */ + WORD ne_cmovent; /* 30 # of movable entry points */ + WORD ne_align; /* 32 Logical sector alignment shift count */ + WORD ne_cres; /* 34 # of resource segments */ + BYTE ne_exetyp; /* 36 Flags indicating target OS */ + BYTE ne_flagsothers; /* 37 Additional information flags */ + WORD ne_pretthunks; /* 38 Offset to return thunks */ + WORD ne_psegrefbytes; /* 3a Offset to segment ref. bytes */ + WORD ne_swaparea; /* 3c Reserved by Microsoft */ + WORD ne_expver; /* 3e Expected Windows version number */ +} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +typedef struct _IMAGE_VXD_HEADER { + WORD e32_magic; + BYTE e32_border; + BYTE e32_worder; + DWORD e32_level; + WORD e32_cpu; + WORD e32_os; + DWORD e32_ver; + DWORD e32_mflags; + DWORD e32_mpages; + DWORD e32_startobj; + DWORD e32_eip; + DWORD e32_stackobj; + DWORD e32_esp; + DWORD e32_pagesize; + DWORD e32_lastpagesize; + DWORD e32_fixupsize; + DWORD e32_fixupsum; + DWORD e32_ldrsize; + DWORD e32_ldrsum; + DWORD e32_objtab; + DWORD e32_objcnt; + DWORD e32_objmap; + DWORD e32_itermap; + DWORD e32_rsrctab; + DWORD e32_rsrccnt; + DWORD e32_restab; + DWORD e32_enttab; + DWORD e32_dirtab; + DWORD e32_dircnt; + DWORD e32_fpagetab; + DWORD e32_frectab; + DWORD e32_impmod; + DWORD e32_impmodcnt; + DWORD e32_impproc; + DWORD e32_pagesum; + DWORD e32_datapage; + DWORD e32_preload; + DWORD e32_nrestab; + DWORD e32_cbnrestab; + DWORD e32_nressum; + DWORD e32_autodata; + DWORD e32_debuginfo; + DWORD e32_debuglen; + DWORD e32_instpreload; + DWORD e32_instdemand; + DWORD e32_heapsize; + BYTE e32_res3[12]; + DWORD e32_winresoff; + DWORD e32_winreslen; + WORD e32_devid; + WORD e32_ddkver; +} IMAGE_VXD_HEADER, *PIMAGE_VXD_HEADER; + +/* These defines describe the meanings of the bits in the + Characteristics field */ + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* No relocation info */ +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 +#define IMAGE_FILE_16BIT_MACHINE 0x0040 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +/* These are the settings of the Machine field. */ +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I860 0x014d +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_R3000 0x0162 +#define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_R10000 0x0168 +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 +#define IMAGE_FILE_MACHINE_ALPHA 0x0184 +#define IMAGE_FILE_MACHINE_SH3 0x01a2 +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 +#define IMAGE_FILE_MACHINE_SH4 0x01a6 +#define IMAGE_FILE_MACHINE_SH5 0x01a8 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_AM33 0x01d3 +#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 +#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 +#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 +#define IMAGE_FILE_MACHINE_TRICORE 0x0520 +#define IMAGE_FILE_MACHINE_CEF 0x0cef +#define IMAGE_FILE_MACHINE_EBC 0x0ebc +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_M32R 0x9041 +#define IMAGE_FILE_MACHINE_CEE 0xc0ee + +#define IMAGE_SIZEOF_FILE_HEADER 20 +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER32 224 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER64 240 +#define IMAGE_SIZEOF_SHORT_NAME 8 +#define IMAGE_SIZEOF_SECTION_HEADER 40 +#define IMAGE_SIZEOF_SYMBOL 18 +#define IMAGE_SIZEOF_AUX_SYMBOL 18 +#define IMAGE_SIZEOF_RELOCATION 10 +#define IMAGE_SIZEOF_BASE_RELOCATION 8 +#define IMAGE_SIZEOF_LINENUMBER 6 +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +/* Possible Magic values */ +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x010b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x020b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x0107 + +#ifdef CONFIG_X86_64 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER64 +#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC +#else +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER32 +#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC +#endif + +/* These are indexes into the DataDirectory array */ +#define IMAGE_FILE_EXPORT_DIRECTORY 0 +#define IMAGE_FILE_IMPORT_DIRECTORY 1 +#define IMAGE_FILE_RESOURCE_DIRECTORY 2 +#define IMAGE_FILE_EXCEPTION_DIRECTORY 3 +#define IMAGE_FILE_SECURITY_DIRECTORY 4 +#define IMAGE_FILE_BASE_RELOCATION_TABLE 5 +#define IMAGE_FILE_DEBUG_DIRECTORY 6 +#define IMAGE_FILE_DESCRIPTION_STRING 7 +#define IMAGE_FILE_MACHINE_VALUE 8 /* Mips */ +#define IMAGE_FILE_THREAD_LOCAL_STORAGE 9 +#define IMAGE_FILE_CALLBACK_DIRECTORY 10 + +/* Directory Entries, indices into the DataDirectory array */ + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */ +#define IMAGE_DIRECTORY_ENTRY_TLS 9 +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 +#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */ +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 + +/* Subsystem Values */ + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows GUI subsystem */ +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows character subsystem */ +#define IMAGE_SUBSYSTEM_OS2_CUI 5 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 /* native Win9x driver */ +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 /* Windows CE subsystem */ +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define IMAGE_SUBSYSTEM_EFI_ROM 13 +#define IMAGE_SUBSYSTEM_XBOX 14 + +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +typedef struct _IMAGE_OPTIONAL_HEADER32 { + + /* Standard fields */ + + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + + /* NT additional fields */ + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; + +typedef struct _IMAGE_OPTIONAL_HEADER64 { + + /* Standard fields */ + + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + + /* NT additional fields */ + ULONGLONG ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; + +#ifdef CONFIG_X86_64 +typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER; +#else +typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER; +#endif + +typedef struct _IMAGE_NT_HEADERS32 { + DWORD Signature; /* "PE"\0\0 */ /* 0x00 */ + IMAGE_FILE_HEADER FileHeader; /* 0x04 */ + IMAGE_OPTIONAL_HEADER32 OptionalHeader; /* 0x18 */ +} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; + +typedef struct _IMAGE_NT_HEADERS64 { + DWORD Signature; /* "PE"\0\0 */ /* 0x00 */ + IMAGE_FILE_HEADER FileHeader; /* 0x04 */ + IMAGE_OPTIONAL_HEADER64 OptionalHeader; /* 0x18 */ +} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; + +#ifdef CONFIG_X86_64 +typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS; +typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; +#else +typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS; +typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS; +#endif + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_FIRST_SECTION(ntheader) \ +((PIMAGE_SECTION_HEADER)((LPBYTE)&((PIMAGE_NT_HEADERS)(ntheader))->OptionalHeader + \ +((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader)) + +/* These defines are for the Characteristics bitfield. */ +/* #define IMAGE_SCN_TYPE_REG 0x00000000 - Reserved */ +/* #define IMAGE_SCN_TYPE_DSECT 0x00000001 - Reserved */ +/* #define IMAGE_SCN_TYPE_NOLOAD 0x00000002 - Reserved */ +/* #define IMAGE_SCN_TYPE_GROUP 0x00000004 - Reserved */ +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved */ +/* #define IMAGE_SCN_TYPE_COPY 0x00000010 - Reserved */ + +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define IMAGE_SCN_LNK_OTHER 0x00000100 +#define IMAGE_SCN_LNK_INFO 0x00000200 +/* #define IMAGE_SCN_TYPE_OVER 0x00000400 - Reserved */ +#define IMAGE_SCN_LNK_REMOVE 0x00000800 +#define IMAGE_SCN_LNK_COMDAT 0x00001000 + +/* 0x00002000 - Reserved */ +/* #define IMAGE_SCN_MEM_PROTECTED 0x00004000 - Obsolete */ +#define IMAGE_SCN_MEM_FARDATA 0x00008000 + +/* #define IMAGE_SCN_MEM_SYSHEAP 0x00010000 - Obsolete */ +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 +#define IMAGE_SCN_MEM_16BIT 0x00020000 +#define IMAGE_SCN_MEM_LOCKED 0x00040000 +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default */ +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 +/* 0x00F00000 - Unused */ +#define IMAGE_SCN_ALIGN_MASK 0x00F00000 + +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 + + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +typedef struct _IMAGE_SYMBOL { + union { + BYTE ShortName[8]; + struct { + DWORD Short; + DWORD Long; + } Name; + DWORD LongName[2]; + } N; + DWORD Value; + SHORT SectionNumber; + WORD Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; +} IMAGE_SYMBOL; +typedef IMAGE_SYMBOL *PIMAGE_SYMBOL; + +#define IMAGE_SIZEOF_SYMBOL 18 + +typedef struct _IMAGE_LINENUMBER { + union { + DWORD SymbolTableIndex; + DWORD VirtualAddress; + } Type; + WORD Linenumber; +} IMAGE_LINENUMBER; +typedef IMAGE_LINENUMBER *PIMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +typedef union _IMAGE_AUX_SYMBOL { + struct { + DWORD TagIndex; + union { + struct { + WORD Linenumber; + WORD Size; + } LnSz; + DWORD TotalSize; + } Misc; + union { + struct { + DWORD PointerToLinenumber; + DWORD PointerToNextFunction; + } Function; + struct { + WORD Dimension[4]; + } Array; + } FcnAry; + WORD TvIndex; + } Sym; + struct { + BYTE Name[IMAGE_SIZEOF_SYMBOL]; + } File; + struct { + DWORD Length; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD CheckSum; + SHORT Number; + BYTE Selection; + } Section; +} IMAGE_AUX_SYMBOL; +typedef IMAGE_AUX_SYMBOL *PIMAGE_AUX_SYMBOL; + +#define IMAGE_SIZEOF_AUX_SYMBOL 18 + +#define IMAGE_SYM_UNDEFINED (SHORT)0 +#define IMAGE_SYM_ABSOLUTE (SHORT)-1 +#define IMAGE_SYM_DEBUG (SHORT)-2 + +#define IMAGE_SYM_TYPE_NULL 0x0000 +#define IMAGE_SYM_TYPE_VOID 0x0001 +#define IMAGE_SYM_TYPE_CHAR 0x0002 +#define IMAGE_SYM_TYPE_SHORT 0x0003 +#define IMAGE_SYM_TYPE_INT 0x0004 +#define IMAGE_SYM_TYPE_LONG 0x0005 +#define IMAGE_SYM_TYPE_FLOAT 0x0006 +#define IMAGE_SYM_TYPE_DOUBLE 0x0007 +#define IMAGE_SYM_TYPE_STRUCT 0x0008 +#define IMAGE_SYM_TYPE_UNION 0x0009 +#define IMAGE_SYM_TYPE_ENUM 0x000A +#define IMAGE_SYM_TYPE_MOE 0x000B +#define IMAGE_SYM_TYPE_BYTE 0x000C +#define IMAGE_SYM_TYPE_WORD 0x000D +#define IMAGE_SYM_TYPE_UINT 0x000E +#define IMAGE_SYM_TYPE_DWORD 0x000F +#define IMAGE_SYM_TYPE_PCODE 0x8000 + +#define IMAGE_SYM_DTYPE_NULL 0 +#define IMAGE_SYM_DTYPE_POINTER 1 +#define IMAGE_SYM_DTYPE_FUNCTION 2 +#define IMAGE_SYM_DTYPE_ARRAY 3 + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0x0000 +#define IMAGE_SYM_CLASS_AUTOMATIC 0x0001 +#define IMAGE_SYM_CLASS_EXTERNAL 0x0002 +#define IMAGE_SYM_CLASS_STATIC 0x0003 +#define IMAGE_SYM_CLASS_REGISTER 0x0004 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 0x0005 +#define IMAGE_SYM_CLASS_LABEL 0x0006 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 0x0007 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 0x0008 +#define IMAGE_SYM_CLASS_ARGUMENT 0x0009 +#define IMAGE_SYM_CLASS_STRUCT_TAG 0x000A +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 0x000B +#define IMAGE_SYM_CLASS_UNION_TAG 0x000C +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 0x000D +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 0x000E +#define IMAGE_SYM_CLASS_ENUM_TAG 0x000F +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 0x0010 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 0x0011 +#define IMAGE_SYM_CLASS_BIT_FIELD 0x0012 + +#define IMAGE_SYM_CLASS_FAR_EXTERNAL 0x0044 +#define IMAGE_SYM_CLASS_BLOCK 0x0064 +#define IMAGE_SYM_CLASS_FUNCTION 0x0065 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 0x0066 +#define IMAGE_SYM_CLASS_FILE 0x0067 +#define IMAGE_SYM_CLASS_SECTION 0x0068 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x0069 + +#define N_BTMASK 0x000F +#define N_TMASK 0x0030 +#define N_TMASK1 0x00C0 +#define N_TMASK2 0x00F0 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +#define BTYPE(x) ((x) & N_BTMASK) + +#ifndef ISPTR +#define ISPTR(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT)) +#endif + +#ifndef ISFCN +#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT)) +#endif + +#ifndef ISARY +#define ISARY(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT)) +#endif + +#ifndef ISTAG +#define ISTAG(x) ((x)==IMAGE_SYM_CLASS_STRUCT_TAG || (x)==IMAGE_SYM_CLASS_UNION_TAG || (x)==IMAGE_SYM_CLASS_ENUM_TAG) +#endif + +#ifndef INCREF +#define INCREF(x) ((((x)&~N_BTMASK)<>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK)) +#endif + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 +#define IMAGE_COMDAT_SELECT_LARGEST 6 +#define IMAGE_COMDAT_SELECT_NEWEST 7 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + +/* Export module directory */ + +typedef struct _IMAGE_EXPORT_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + DWORD AddressOfFunctions; + DWORD AddressOfNames; + DWORD AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; + +/* Import name entry */ +typedef struct _IMAGE_IMPORT_BY_NAME { + WORD Hint; + BYTE Name[1]; +} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME; + +/* Import thunk */ +typedef struct _IMAGE_THUNK_DATA32 { + union { + DWORD ForwarderString; + DWORD Function; + DWORD Ordinal; + DWORD AddressOfData; + } u1; +} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32; + +typedef struct _IMAGE_THUNK_DATA64 { + union { + ULONGLONG ForwarderString; + ULONGLONG Function; + ULONGLONG Ordinal; + ULONGLONG AddressOfData; + } u1; +} IMAGE_THUNK_DATA64,*PIMAGE_THUNK_DATA64; + +#ifdef CONFIG_X86_64 +typedef IMAGE_THUNK_DATA32 IMAGE_THUNK_DATA; +typedef PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA; +#else +typedef IMAGE_THUNK_DATA64 IMAGE_THUNK_DATA; +typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA; +#endif + +/* Import module directory */ + +typedef struct packed _IMAGE_IMPORT_DESCRIPTOR { + union { + DWORD Characteristics; /* 0 for terminating null + * import descriptor */ + DWORD OriginalFirstThunk; /* RVA to original unbound + * IAT */ + } u; + DWORD TimeDateStamp; /* 0 if not bound, + * -1 if bound, and real date\time stamp + * in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT + * (new BIND) + * otherwise date/time stamp of DLL bound to + * (Old BIND) + */ + DWORD ForwarderChain; /* -1 if no forwarders */ + DWORD Name; + /* RVA to IAT (if bound this IAT has actual addresses) */ + DWORD FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; + +#define IMAGE_ORDINAL_FLAG32 0x80000000 +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000UL +#define IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0) +#define IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +#ifdef CONFIG_X86_64 +#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG64 +#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL64 +#else +#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG32 +#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL32 +#endif + +typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR +{ + DWORD TimeDateStamp; + WORD OffsetModuleName; + WORD NumberOfModuleForwarderRefs; +/* Array of zero or more IMAGE_BOUND_FORWARDER_REF follows */ +} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR; + +typedef struct _IMAGE_BOUND_FORWARDER_REF +{ + DWORD TimeDateStamp; + WORD OffsetModuleName; + WORD Reserved; +} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF; + +typedef struct _IMAGE_BASE_RELOCATION +{ + DWORD VirtualAddress; + DWORD SizeOfBlock; + WORD TypeOffset[0]; +} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; + +typedef struct _IMAGE_RELOCATION +{ + union { + DWORD VirtualAddress; + DWORD RelocCount; + } DUMMYUNIONNAME; + DWORD SymbolTableIndex; + WORD Type; +} IMAGE_RELOCATION, *PIMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +/* generic relocation types */ +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_SECTION 6 +#define IMAGE_REL_BASED_REL 7 +#define IMAGE_REL_BASED_MIPS_JMPADDR16 9 +#define IMAGE_REL_BASED_IA64_IMM64 9 /* yes, 9 too */ +#define IMAGE_REL_BASED_DIR64 10 +#define IMAGE_REL_BASED_HIGH3ADJ 11 + +/* I386 relocation types */ +#define IMAGE_REL_I386_ABSOLUTE 0 +#define IMAGE_REL_I386_DIR16 1 +#define IMAGE_REL_I386_REL16 2 +#define IMAGE_REL_I386_DIR32 6 +#define IMAGE_REL_I386_DIR32NB 7 +#define IMAGE_REL_I386_SEG12 9 +#define IMAGE_REL_I386_SECTION 10 +#define IMAGE_REL_I386_SECREL 11 +#define IMAGE_REL_I386_REL32 20 + +/* MIPS relocation types */ +#define IMAGE_REL_MIPS_ABSOLUTE 0x0000 +#define IMAGE_REL_MIPS_REFHALF 0x0001 +#define IMAGE_REL_MIPS_REFWORD 0x0002 +#define IMAGE_REL_MIPS_JMPADDR 0x0003 +#define IMAGE_REL_MIPS_REFHI 0x0004 +#define IMAGE_REL_MIPS_REFLO 0x0005 +#define IMAGE_REL_MIPS_GPREL 0x0006 +#define IMAGE_REL_MIPS_LITERAL 0x0007 +#define IMAGE_REL_MIPS_SECTION 0x000A +#define IMAGE_REL_MIPS_SECREL 0x000B +#define IMAGE_REL_MIPS_SECRELLO 0x000C +#define IMAGE_REL_MIPS_SECRELHI 0x000D +#define IMAGE_REL_MIPS_JMPADDR16 0x0010 +#define IMAGE_REL_MIPS_REFWORDNB 0x0022 +#define IMAGE_REL_MIPS_PAIR 0x0025 + +/* ALPHA relocation types */ +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0000 +#define IMAGE_REL_ALPHA_REFLONG 0x0001 +#define IMAGE_REL_ALPHA_REFQUAD 0x0002 +#define IMAGE_REL_ALPHA_GPREL 0x0003 +#define IMAGE_REL_ALPHA_LITERAL 0x0004 +#define IMAGE_REL_ALPHA_LITUSE 0x0005 +#define IMAGE_REL_ALPHA_GPDISP 0x0006 +#define IMAGE_REL_ALPHA_BRADDR 0x0007 +#define IMAGE_REL_ALPHA_HINT 0x0008 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x0009 +#define IMAGE_REL_ALPHA_REFHI 0x000A +#define IMAGE_REL_ALPHA_REFLO 0x000B +#define IMAGE_REL_ALPHA_PAIR 0x000C +#define IMAGE_REL_ALPHA_MATCH 0x000D +#define IMAGE_REL_ALPHA_SECTION 0x000E +#define IMAGE_REL_ALPHA_SECREL 0x000F +#define IMAGE_REL_ALPHA_REFLONGNB 0x0010 +#define IMAGE_REL_ALPHA_SECRELLO 0x0011 +#define IMAGE_REL_ALPHA_SECRELHI 0x0012 +#define IMAGE_REL_ALPHA_REFQ3 0x0013 +#define IMAGE_REL_ALPHA_REFQ2 0x0014 +#define IMAGE_REL_ALPHA_REFQ1 0x0015 +#define IMAGE_REL_ALPHA_GPRELLO 0x0016 +#define IMAGE_REL_ALPHA_GPRELHI 0x0017 + +/* PowerPC relocation types */ +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 +#define IMAGE_REL_PPC_ADDR64 0x0001 +#define IMAGE_REL_PPC_ADDR 0x0002 +#define IMAGE_REL_PPC_ADDR24 0x0003 +#define IMAGE_REL_PPC_ADDR16 0x0004 +#define IMAGE_REL_PPC_ADDR14 0x0005 +#define IMAGE_REL_PPC_REL24 0x0006 +#define IMAGE_REL_PPC_REL14 0x0007 +#define IMAGE_REL_PPC_TOCREL16 0x0008 +#define IMAGE_REL_PPC_TOCREL14 0x0009 +#define IMAGE_REL_PPC_ADDR32NB 0x000A +#define IMAGE_REL_PPC_SECREL 0x000B +#define IMAGE_REL_PPC_SECTION 0x000C +#define IMAGE_REL_PPC_IFGLUE 0x000D +#define IMAGE_REL_PPC_IMGLUE 0x000E +#define IMAGE_REL_PPC_SECREL16 0x000F +#define IMAGE_REL_PPC_REFHI 0x0010 +#define IMAGE_REL_PPC_REFLO 0x0011 +#define IMAGE_REL_PPC_PAIR 0x0012 +#define IMAGE_REL_PPC_SECRELLO 0x0013 +#define IMAGE_REL_PPC_SECRELHI 0x0014 +#define IMAGE_REL_PPC_GPREL 0x0015 +#define IMAGE_REL_PPC_TYPEMASK 0x00FF +/* modifier bits */ +#define IMAGE_REL_PPC_NEG 0x0100 +#define IMAGE_REL_PPC_BRTAKEN 0x0200 +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 +#define IMAGE_REL_PPC_TOCDEFN 0x0800 + +/* SH3 ? relocation type */ +#define IMAGE_REL_SH3_ABSOLUTE 0x0000 +#define IMAGE_REL_SH3_DIRECT16 0x0001 +#define IMAGE_REL_SH3_DIRECT 0x0002 +#define IMAGE_REL_SH3_DIRECT8 0x0003 +#define IMAGE_REL_SH3_DIRECT8_WORD 0x0004 +#define IMAGE_REL_SH3_DIRECT8_LONG 0x0005 +#define IMAGE_REL_SH3_DIRECT4 0x0006 +#define IMAGE_REL_SH3_DIRECT4_WORD 0x0007 +#define IMAGE_REL_SH3_DIRECT4_LONG 0x0008 +#define IMAGE_REL_SH3_PCREL8_WORD 0x0009 +#define IMAGE_REL_SH3_PCREL8_LONG 0x000A +#define IMAGE_REL_SH3_PCREL12_WORD 0x000B +#define IMAGE_REL_SH3_STARTOF_SECTION 0x000C +#define IMAGE_REL_SH3_SIZEOF_SECTION 0x000D +#define IMAGE_REL_SH3_SECTION 0x000E +#define IMAGE_REL_SH3_SECREL 0x000F +#define IMAGE_REL_SH3_DIRECT32_NB 0x0010 + +/* ARM (Archimedes?) relocation types */ +#define IMAGE_REL_ARM_ABSOLUTE 0x0000 +#define IMAGE_REL_ARM_ADDR 0x0001 +#define IMAGE_REL_ARM_ADDR32NB 0x0002 +#define IMAGE_REL_ARM_BRANCH24 0x0003 +#define IMAGE_REL_ARM_BRANCH11 0x0004 +#define IMAGE_REL_ARM_SECTION 0x000E +#define IMAGE_REL_ARM_SECREL 0x000F + +/* IA64 relocation types */ +#define IMAGE_REL_IA64_ABSOLUTE 0x0000 +#define IMAGE_REL_IA64_IMM14 0x0001 +#define IMAGE_REL_IA64_IMM22 0x0002 +#define IMAGE_REL_IA64_IMM64 0x0003 +#define IMAGE_REL_IA64_DIR 0x0004 +#define IMAGE_REL_IA64_DIR64 0x0005 +#define IMAGE_REL_IA64_PCREL21B 0x0006 +#define IMAGE_REL_IA64_PCREL21M 0x0007 +#define IMAGE_REL_IA64_PCREL21F 0x0008 +#define IMAGE_REL_IA64_GPREL22 0x0009 +#define IMAGE_REL_IA64_LTOFF22 0x000A +#define IMAGE_REL_IA64_SECTION 0x000B +#define IMAGE_REL_IA64_SECREL22 0x000C +#define IMAGE_REL_IA64_SECREL64I 0x000D +#define IMAGE_REL_IA64_SECREL 0x000E +#define IMAGE_REL_IA64_LTOFF64 0x000F +#define IMAGE_REL_IA64_DIR32NB 0x0010 +#define IMAGE_REL_IA64_RESERVED_11 0x0011 +#define IMAGE_REL_IA64_RESERVED_12 0x0012 +#define IMAGE_REL_IA64_RESERVED_13 0x0013 +#define IMAGE_REL_IA64_RESERVED_14 0x0014 +#define IMAGE_REL_IA64_RESERVED_15 0x0015 +#define IMAGE_REL_IA64_RESERVED_16 0x0016 +#define IMAGE_REL_IA64_ADDEND 0x001F + +/* archive format */ + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER +{ + BYTE Name[16]; + BYTE Date[12]; + BYTE UserID[6]; + BYTE GroupID[6]; + BYTE Mode[8]; + BYTE Size[10]; + BYTE EndHeader[2]; +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +/* + * Resource directory stuff + */ +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; + /* IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; */ +} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY; + +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + union { + struct { +#ifdef BITFIELDS_BIGENDIAN + unsigned NameIsString:1; + unsigned NameOffset:31; +#else + unsigned NameOffset:31; + unsigned NameIsString:1; +#endif + } DUMMYSTRUCTNAME1; + DWORD Name; + struct { +#ifdef WORDS_BIGENDIAN + WORD __pad; + WORD Id; +#else + WORD Id; + WORD __pad; +#endif + } DUMMYSTRUCTNAME2; + } DUMMYUNIONNAME1; + union { + DWORD OffsetToData; + struct { +#ifdef BITFIELDS_BIGENDIAN + unsigned DataIsDirectory:1; + unsigned OffsetToDirectory:31; +#else + unsigned OffsetToDirectory:31; + unsigned DataIsDirectory:1; +#endif + } DUMMYSTRUCTNAME3; + } DUMMYUNIONNAME2; +} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY; + + +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + WORD Length; + CHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING; + --- linux-2.6.27.orig/ubuntu/ndiswrapper/crt.c +++ linux-2.6.27/ubuntu/ndiswrapper/crt.c @@ -0,0 +1,578 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ntoskernel.h" +#include "crt_exports.h" + +#ifdef CONFIG_X86_64 +/* Windows long is 32-bit, so strip single 'l' in integer formats */ +static void strip_l_modifier(char *str) +{ + char *ptr = str; + int in_format = 0; + char *lptr = NULL; + char last = 0; + char *end_ptr; + char *wptr; + + /* Replace single 'l' inside integer formats with '\0' */ + for (ptr = str; *ptr; ptr++) { + if (!in_format) { + if (*ptr == '%') + in_format = 1; + last = *ptr; + continue; + } + switch (*ptr) { + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + case 'p': + case 'n': + case 'm': + if (lptr) { + *lptr = '\0'; + lptr = NULL; + } + in_format = 0; + break; + case 'c': + case 'C': + case 's': + case 'S': + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + case 'a': + case 'A': + lptr = NULL; + in_format = 0; + break; + case '%': + lptr = NULL; + if (last == '%') + in_format = 0; + else + in_format = 1; /* ignore previous junk */ + break; + case 'l': + if (last == 'l') + lptr = NULL; + else + lptr = ptr; + break; + default: + break; + } + last = *ptr; + } + + /* Purge zeroes from the resulting string */ + end_ptr = ptr; + wptr = str; + for (ptr = str; ptr < end_ptr; ptr++) + if (*ptr != 0) + *(wptr++) = *ptr; + *wptr = 0; +} + +/* + * va_list on x86_64 Linux is designed to allow passing arguments in registers + * even to variadic functions. va_list is a structure holding pointers to the + * register save area, which holds the arguments passed in registers, and to + * the stack, which may have the arguments that did not fit the registers. + * va_list also holds offsets in the register save area for the next general + * purpose and floating point registers that the next va_arg() would fetch. + * + * Unlike Linux, the Windows va_list is just a pointer to the stack. No + * arguments are passed in the registers. That's why we construct the Linux + * va_list so that the register save area is never used. For that goal, we set + * the offsets to the maximal allowed values, meaning that the arguments passed + * in the registers have been exhausted. The values are 48 for general purpose + * registers (6 registers, 8 bytes each) and 304 for floating point registers + * (16 registers, 16 bytes each, on top of general purpose register). + */ + +struct x86_64_va_list { + int gp_offset; + int fp_offset; + void *overflow_arg_area; + void *reg_save_area; +}; + +#define VA_LIST_DECL(_args) \ + va_list _args##new; \ + struct x86_64_va_list *_args##x; +#define VA_LIST_PREP(_args) \ +do { \ + _args##x = (struct x86_64_va_list *)&_args##new; \ + _args##x->gp_offset = 6 * 8; /* GP registers exhausted */ \ + _args##x->fp_offset = 6 * 8 + 16 * 16; /* FP registers exhausted */ \ + _args##x->overflow_arg_area = (void *)_args; \ + _args##x->reg_save_area = NULL; \ +} while (0) +#define VA_LIST_CONV(_args) (_args##new) +#define VA_LIST_FREE(_args) +#define FMT_DECL(_fmt) \ + char *_fmt##copy; \ + int _fmt##len; +#define FMT_PREP(_fmt) \ +do { \ + _fmt##len = strlen(format) + 1; \ + _fmt##copy = kmalloc(_fmt##len, GFP_KERNEL); \ + if (_fmt##copy) { \ + memcpy(_fmt##copy, format, _fmt##len); \ + strip_l_modifier(_fmt##copy); \ + } \ +} while (0) +#define FMT_CONV(_fmt) (_fmt##copy ? _fmt##copy : format) +#define FMT_FREE(_fmt) kfree(_fmt##copy) + +#else /* !CONFIG_X86_64 */ + +#define VA_LIST_DECL(_args) +#define VA_LIST_PREP(_args) +#define VA_LIST_CONV(_args) (_args) +#define VA_LIST_FREE(_args) +#define FMT_DECL(_fmt) +#define FMT_PREP(_fmt) +#define FMT_CONV(_fmt) (format) +#define FMT_FREE(_fmt) + +#endif /* !CONFIG_X86_64 */ + +noregparm INT WIN_FUNC(_win_sprintf,12) + (char *buf, const char *format, ...) +{ + va_list args; + int res; + FMT_DECL(format) + + FMT_PREP(format); + va_start(args, format); + res = vsprintf(buf, FMT_CONV(format), args); + va_end(args); + FMT_FREE(format); + + TRACE2("buf: %p: %s", buf, buf); + return res; +} + +noregparm INT WIN_FUNC(swprintf,12) + (wchar_t *buf, const wchar_t *format, ...) +{ + TODO(); + EXIT2(return 0); +} + +noregparm INT WIN_FUNC(_win_vsprintf,3) + (char *str, const char *format, va_list ap) +{ + INT i; + VA_LIST_DECL(ap) + FMT_DECL(format) + + VA_LIST_PREP(ap); + FMT_PREP(format); + + i = vsprintf(str, FMT_CONV(format), VA_LIST_CONV(ap)); + TRACE2("str: %p: %s", str, str); + + FMT_FREE(format); + VA_LIST_FREE(ap); + EXIT2(return i); +} + +noregparm INT WIN_FUNC(_win_snprintf,12) + (char *buf, SIZE_T count, const char *format, ...) +{ + va_list args; + int res; + FMT_DECL(format) + + FMT_PREP(format); + va_start(args, format); + res = vsnprintf(buf, count, FMT_CONV(format), args); + va_end(args); + TRACE2("buf: %p: %s", buf, buf); + + FMT_FREE(format); + return res; +} + +noregparm INT WIN_FUNC(_win__snprintf,12) + (char *buf, SIZE_T count, const char *format, ...) +{ + va_list args; + int res; + FMT_DECL(format) + + FMT_PREP(format); + va_start(args, format); + res = vsnprintf(buf, count, FMT_CONV(format), args); + va_end(args); + TRACE2("buf: %p: %s", buf, buf); + + FMT_FREE(format); + return res; +} + +noregparm INT WIN_FUNC(_win_vsnprintf,4) + (char *str, SIZE_T size, const char *format, va_list ap) +{ + INT i; + VA_LIST_DECL(ap) + FMT_DECL(format) + + VA_LIST_PREP(ap); + FMT_PREP(format); + + i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap)); + TRACE2("str: %p: %s", str, str); + + FMT_FREE(format); + VA_LIST_FREE(ap); + EXIT2(return i); +} + +noregparm INT WIN_FUNC(_win__vsnprintf,4) + (char *str, SIZE_T size, const char *format, va_list ap) +{ + INT i; + VA_LIST_DECL(ap) + FMT_DECL(format) + + VA_LIST_PREP(ap); + FMT_PREP(format); + + i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap)); + TRACE2("str: %p: %s", str, str); + + FMT_FREE(format); + VA_LIST_FREE(ap); + EXIT2(return i); +} + +noregparm char *WIN_FUNC(_win_strncpy,3) + (char *dst, char *src, SIZE_T n) +{ + return strncpy(dst, src, n); +} + +noregparm SIZE_T WIN_FUNC(_win_strlen,1) + (const char *s) +{ + return strlen(s); +} + +noregparm INT WIN_FUNC(_win_strncmp,3) + (const char *s1, const char *s2, SIZE_T n) +{ + return strncmp(s1, s2, n); +} + +noregparm INT WIN_FUNC(_win_strcmp,2) + (const char *s1, const char *s2) +{ + return strcmp(s1, s2); +} + +noregparm INT WIN_FUNC(_win_stricmp,2) + (const char *s1, const char *s2) +{ + return stricmp(s1, s2); +} + +noregparm char *WIN_FUNC(_win_strncat,3) + (char *dest, const char *src, SIZE_T n) +{ + return strncat(dest, src, n); +} + +noregparm INT WIN_FUNC(_win_wcscmp,2) + (const wchar_t *s1, const wchar_t *s2) +{ + while (*s1 && *s1 == *s2) { + s1++; + s2++; + } + return *s1 - *s2; +} + +noregparm INT WIN_FUNC(_win_wcsicmp,2) + (const wchar_t *s1, const wchar_t *s2) +{ + while (*s1 && tolower((char)*s1) == tolower((char)*s2)) { + s1++; + s2++; + } + return tolower((char)*s1) - tolower((char)*s2); +} + +noregparm SIZE_T WIN_FUNC(_win_wcslen,1) + (const wchar_t *s) +{ + const wchar_t *t = s; + while (*t) + t++; + return t - s; +} + +noregparm wchar_t *WIN_FUNC(_win_wcsncpy,3) + (wchar_t *dest, const wchar_t *src, SIZE_T n) +{ + const wchar_t *s; + wchar_t *d; + s = src + n; + d = dest; + while (src < s && (*d++ = *src++)) + ; + if (s > src) + memset(d, 0, (s - src) * sizeof(wchar_t)); + return dest; +} + +noregparm wchar_t *WIN_FUNC(_win_wcscpy,2) + (wchar_t *dest, const wchar_t *src) +{ + wchar_t *d = dest; + while ((*d++ = *src++)) + ; + return dest; +} + +noregparm wchar_t *WIN_FUNC(_win_wcscat,2) + (wchar_t *dest, const wchar_t *src) +{ + wchar_t *d; + d = dest; + while (*d) + d++; + while ((*d++ = *src++)) + ; + return dest; +} + +noregparm INT WIN_FUNC(_win_towupper,1) + (wchar_t c) +{ + return toupper(c); +} + +noregparm INT WIN_FUNC(_win_towlower,1) + (wchar_t c) +{ + return tolower(c); +} + +noregparm INT WIN_FUNC(_win_tolower,1) + (INT c) +{ + return tolower(c); +} + +noregparm INT WIN_FUNC(_win_toupper,1) + (INT c) +{ + return toupper(c); +} + +noregparm void *WIN_FUNC(_win_strcpy,2) + (void *to, const void *from) +{ + return strcpy(to, from); +} + +noregparm char *WIN_FUNC(_win_strstr,2) + (const char *s1, const char *s2) +{ + return strstr(s1, s2); +} + +noregparm char *WIN_FUNC(_win_strchr,2) + (const char *s, int c) +{ + return strchr(s, c); +} + +noregparm char *WIN_FUNC(_win_strrchr,2) + (const char *s, int c) +{ + return strrchr(s, c); +} + +noregparm void *WIN_FUNC(_win_memmove,3) + (void *to, void *from, SIZE_T count) +{ + return memmove(to, from, count); +} + +noregparm void *WIN_FUNC(_win_memchr,3) + (const void *s, INT c, SIZE_T n) +{ + return memchr(s, c, n); +} + +noregparm void *WIN_FUNC(_win_memcpy,3) + (void *to, const void *from, SIZE_T n) +{ + return memcpy(to, from, n); +} + +noregparm void *WIN_FUNC(_win_memset,3) + (void *s, char c, SIZE_T count) +{ + return memset(s, c, count); +} + +noregparm int WIN_FUNC(_win_memcmp,3) + (void *s1, void *s2, SIZE_T n) +{ + return memcmp(s1, s2, n); +} + +noregparm void WIN_FUNC(_win_srand,1) + (UINT seed) +{ + net_srandom(seed); +} + +noregparm int WIN_FUNC(rand,0) + (void) +{ + char buf[6]; + int i, n; + + get_random_bytes(buf, sizeof(buf)); + for (n = i = 0; i < sizeof(buf) ; i++) + n += buf[i]; + return n; +} + +noregparm int WIN_FUNC(_win_atoi,1) + (const char *ptr) +{ + int i = simple_strtol(ptr, NULL, 10); + return i; +} + +noregparm int WIN_FUNC(_win_isprint,1) + (int c) +{ + return isprint(c); +} + +wstdcall s64 WIN_FUNC(_alldiv,2) + (s64 a, s64 b) +{ + return (a / b); +} + +wstdcall u64 WIN_FUNC(_aulldiv,2) + (u64 a, u64 b) +{ + return (a / b); +} + +wstdcall s64 WIN_FUNC(_allmul,2) + (s64 a, s64 b) +{ + return (a * b); +} + +wstdcall u64 WIN_FUNC(_aullmul,2) + (u64 a, u64 b) +{ + return (a * b); +} + +wstdcall s64 WIN_FUNC(_allrem,2) + (s64 a, s64 b) +{ + return (a % b); +} + +wstdcall u64 WIN_FUNC(_aullrem,2) + (u64 a, u64 b) +{ + return (a % b); +} + +__attribute__((regparm(3))) s64 WIN_FUNC(_allshl,2) + (s64 a, u8 b) +{ + return (a << b); +} + +__attribute__((regparm(3))) u64 WIN_FUNC(_aullshl,2) + (u64 a, u8 b) +{ + return (a << b); +} + +__attribute__((regparm(3))) s64 WIN_FUNC(_allshr,2) + (s64 a, u8 b) +{ + return (a >> b); +} + +__attribute__((regparm(3))) u64 WIN_FUNC(_aullshr,2) + (u64 a, u8 b) +{ + return (a >> b); +} + +int stricmp(const char *s1, const char *s2) +{ + while (*s1 && tolower(*s1) == tolower(*s2)) { + s1++; + s2++; + } + return *s1 - *s2; +} + +void dump_bytes(const char *ctx, const u8 *from, int len) +{ + int i, j; + u8 *buf; + + buf = kmalloc(len * 3 + 1, irql_gfp()); + if (!buf) { + ERROR("couldn't allocate memory"); + return; + } + for (i = j = 0; i < len; i++, j += 3) { + sprintf(&buf[j], "%02x ", from[i]); + } + buf[j] = 0; + printk(KERN_DEBUG "%s: %p: %s\n", ctx, from, buf); + kfree(buf); +} + +int crt_init(void) +{ + return 0; +} + +/* called when module is being removed */ +void crt_exit(void) +{ + EXIT4(return); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/hal.c +++ linux-2.6.27/ubuntu/ndiswrapper/hal.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ntoskernel.h" +#include "hal_exports.h" + +wstdcall void WIN_FUNC(WRITE_PORT_ULONG,2) + (ULONG_PTR port, ULONG value) +{ + outl(value, port); +} + +wstdcall ULONG WIN_FUNC(READ_PORT_ULONG,1) + (ULONG_PTR port) +{ + return inl(port); +} + +wstdcall void WIN_FUNC(WRITE_PORT_USHORT,2) + (ULONG_PTR port, USHORT value) +{ + outw(value, port); +} + +wstdcall USHORT WIN_FUNC(READ_PORT_USHORT,1) + (ULONG_PTR port) +{ + return inw(port); +} + +wstdcall void WIN_FUNC(WRITE_PORT_UCHAR,2) + (ULONG_PTR port, UCHAR value) +{ + outb(value, port); +} + +wstdcall UCHAR WIN_FUNC(READ_PORT_UCHAR,1) + (ULONG_PTR port) +{ + return inb(port); +} + +wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_USHORT,3) + (ULONG_PTR port, USHORT *buf, ULONG count) +{ + outsw(port, buf, count); +} + +wstdcall void WIN_FUNC(READ_PORT_BUFFER_USHORT,3) + (ULONG_PTR port, USHORT *buf, ULONG count) +{ + insw(port, buf, count); +} + +wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_ULONG,3) + (ULONG_PTR port, ULONG *buf, ULONG count) +{ + outsl(port, buf, count); +} + +wstdcall void WIN_FUNC(READ_PORT_BUFFER_ULONG,3) + (ULONG_PTR port, ULONG *buf, ULONG count) +{ + insl(port, buf, count); +} + +wstdcall USHORT WIN_FUNC(READ_REGISTER_USHORT,1) + (void __iomem *reg) +{ + return readw(reg); +} + +wstdcall void WIN_FUNC(WRITE_REGISTER_ULONG,2) + (void __iomem *reg, UINT val) +{ + writel(val, reg); +} + +wstdcall void WIN_FUNC(WRITE_REGISTER_USHORT,2) + (void __iomem *reg, USHORT val) +{ + writew(val, reg); +} + +wstdcall void WIN_FUNC(WRITE_REGISTER_UCHAR,2) + (void __iomem *reg, UCHAR val) +{ + writeb(val, reg); +} + +wstdcall void WIN_FUNC(KeStallExecutionProcessor,1) + (ULONG usecs) +{ + udelay(usecs); +} + +wstdcall KIRQL WIN_FUNC(KeGetCurrentIrql,0) + (void) +{ + return current_irql(); +} + +wfastcall KIRQL WIN_FUNC(KfRaiseIrql,1) + (KIRQL newirql) +{ + return raise_irql(newirql); +} + +wfastcall void WIN_FUNC(KfLowerIrql,1) + (KIRQL oldirql) +{ + lower_irql(oldirql); +} + +wfastcall KIRQL WIN_FUNC(KfAcquireSpinLock,1) + (NT_SPIN_LOCK *lock) +{ + return nt_spin_lock_irql(lock, DISPATCH_LEVEL); +} + +wfastcall void WIN_FUNC(KfReleaseSpinLock,2) + (NT_SPIN_LOCK *lock, KIRQL oldirql) +{ + nt_spin_unlock_irql(lock, oldirql); +} + +wfastcall void WIN_FUNC(KefAcquireSpinLockAtDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ +#ifdef DEBUG_IRQL + if (current_irql() != DISPATCH_LEVEL) + ERROR("irql != DISPATCH_LEVEL"); +#endif + nt_spin_lock(lock); +} + +wfastcall void WIN_FUNC(KefReleaseSpinLockFromDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ +#ifdef DEBUG_IRQL + if (current_irql() != DISPATCH_LEVEL) + ERROR("irql != DISPATCH_LEVEL"); +#endif + nt_spin_unlock(lock); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/wrapndis.c +++ linux-2.6.27/ubuntu/ndiswrapper/wrapndis.c @@ -0,0 +1,2085 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ndis.h" +#include "iw_ndis.h" +#include "pnp.h" +#include "loader.h" +#include "wrapndis.h" +#include +#include +#include +#include +#include +#include "wrapper.h" + +/* Functions callable from the NDIS driver */ +wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo, + struct irp *irp); +wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp); +wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp); + +workqueue_struct_t *wrapndis_wq; +static struct nt_thread *wrapndis_worker_thread; + +static int set_packet_filter(struct ndis_device *wnd, + ULONG packet_filter); +static void add_iw_stats_timer(struct ndis_device *wnd); +static void del_iw_stats_timer(struct ndis_device *wnd); +static NDIS_STATUS ndis_start_device(struct ndis_device *wnd); +static int ndis_remove_device(struct ndis_device *wnd); +static void set_multicast_list(struct ndis_device *wnd); +static int ndis_net_dev_open(struct net_device *net_dev); +static int ndis_net_dev_close(struct net_device *net_dev); + +/* MiniportReset */ +NDIS_STATUS mp_reset(struct ndis_device *wnd) +{ + NDIS_STATUS res; + struct miniport *mp; + BOOLEAN reset_address; + KIRQL irql; + + ENTER2("wnd: %p", wnd); + if (down_interruptible(&wnd->tx_ring_mutex)) + EXIT3(return NDIS_STATUS_FAILURE); + if (down_interruptible(&wnd->ndis_req_mutex)) { + up(&wnd->tx_ring_mutex); + EXIT3(return NDIS_STATUS_FAILURE); + } + mp = &wnd->wd->driver->ndis_driver->mp; + prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0); + WARNING("%s is being reset", wnd->net_dev->name); + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + res = LIN2WIN2(mp->reset, &reset_address, wnd->nmb->mp_ctx); + serialize_unlock_irql(wnd, irql); + + TRACE2("%08X, %08X", res, reset_address); + if (res == NDIS_STATUS_PENDING) { + /* wait for NdisMResetComplete */ + if (wait_condition((wnd->ndis_req_done > 0), 0, + TASK_INTERRUPTIBLE) < 0) + res = NDIS_STATUS_FAILURE; + else { + res = wnd->ndis_req_status; + reset_address = wnd->ndis_req_done - 1; + } + TRACE2("%08X, %08X", res, reset_address); + } + up(&wnd->ndis_req_mutex); + if (res == NDIS_STATUS_SUCCESS && reset_address) { + set_packet_filter(wnd, wnd->packet_filter); + set_multicast_list(wnd); + } + up(&wnd->tx_ring_mutex); + EXIT3(return res); +} + +/* MiniportRequest(Query/Set)Information */ +NDIS_STATUS mp_request(enum ndis_request_type request, + struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen, ULONG *written, ULONG *needed) +{ + NDIS_STATUS res; + ULONG w, n; + struct miniport *mp; + KIRQL irql; + + if (down_interruptible(&wnd->ndis_req_mutex)) + EXIT3(return NDIS_STATUS_FAILURE); + if (!written) + written = &w; + if (!needed) + needed = &n; + mp = &wnd->wd->driver->ndis_driver->mp; + prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0); + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + switch (request) { + case NdisRequestQueryInformation: + TRACE2("%p, %08X, %p", mp->queryinfo, oid, wnd->nmb->mp_ctx); + res = LIN2WIN6(mp->queryinfo, wnd->nmb->mp_ctx, oid, buf, + buflen, written, needed); + break; + case NdisRequestSetInformation: + TRACE2("%p, %08X, %p", mp->setinfo, oid, wnd->nmb->mp_ctx); + res = LIN2WIN6(mp->setinfo, wnd->nmb->mp_ctx, oid, buf, + buflen, written, needed); + break; + default: + WARNING("invalid request %d, %08X", request, oid); + res = NDIS_STATUS_NOT_SUPPORTED; + break; + } + serialize_unlock_irql(wnd, irql); + TRACE2("%08X, %08X", res, oid); + if (res == NDIS_STATUS_PENDING) { + /* wait for NdisMQueryInformationComplete */ + if (wait_condition((wnd->ndis_req_done > 0), 0, + TASK_INTERRUPTIBLE) < 0) + res = NDIS_STATUS_FAILURE; + else + res = wnd->ndis_req_status; + TRACE2("%08X, %08X", res, oid); + } + up(&wnd->ndis_req_mutex); + DBG_BLOCK(2) { + if (res || needed) + TRACE2("%08X, %d, %d, %d", res, buflen, *written, + *needed); + } + EXIT3(return res); +} + +/* MiniportPnPEventNotify */ +static NDIS_STATUS mp_pnp_event(struct ndis_device *wnd, + enum ndis_device_pnp_event event, + ULONG power_profile) +{ + struct miniport *mp; + + ENTER1("%p, %d", wnd, event); + mp = &wnd->wd->driver->ndis_driver->mp; + if (!mp->pnp_event_notify) { + TRACE1("Windows driver %s doesn't support " + "MiniportPnpEventNotify", wnd->wd->driver->name); + return NDIS_STATUS_FAILURE; + } + /* RNDIS driver doesn't like to be notified if device is + * already halted */ + if (!test_bit(HW_INITIALIZED, &wnd->wd->hw_status)) + EXIT1(return NDIS_STATUS_SUCCESS); + switch (event) { + case NdisDevicePnPEventSurpriseRemoved: + TRACE1("%u, %p", + (wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK), + mp->pnp_event_notify); + if ((wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK) && + !test_bit(HW_PRESENT, &wnd->wd->hw_status) && + mp->pnp_event_notify) { + TRACE1("calling surprise_removed"); + LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx, + NdisDevicePnPEventSurpriseRemoved, NULL, 0); + } else + TRACE1("Windows driver %s doesn't support " + "MiniportPnpEventNotify for safe unplugging", + wnd->wd->driver->name); + return NDIS_STATUS_SUCCESS; + case NdisDevicePnPEventPowerProfileChanged: + if (power_profile) + power_profile = NdisPowerProfileAcOnLine; + LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx, + NdisDevicePnPEventPowerProfileChanged, + &power_profile, (ULONG)sizeof(power_profile)); + return NDIS_STATUS_SUCCESS; + default: + WARNING("event %d not yet implemented", event); + return NDIS_STATUS_SUCCESS; + } +} + +/* MiniportInitialize */ +static NDIS_STATUS mp_init(struct ndis_device *wnd) +{ + NDIS_STATUS error_status, status; + UINT medium_index; + enum ndis_medium medium_array[] = {NdisMedium802_3}; + struct miniport *mp; + + ENTER1("irql: %d", current_irql()); + if (test_bit(HW_INITIALIZED, &wnd->wd->hw_status)) { + WARNING("device %p already initialized!", wnd); + return NDIS_STATUS_FAILURE; + } + + if (!wnd->wd->driver->ndis_driver || + !wnd->wd->driver->ndis_driver->mp.init) { + WARNING("assuming WDM (non-NDIS) driver"); + EXIT1(return NDIS_STATUS_NOT_RECOGNIZED); + } + mp = &wnd->wd->driver->ndis_driver->mp; + status = LIN2WIN6(mp->init, &error_status, &medium_index, medium_array, + sizeof(medium_array) / sizeof(medium_array[0]), + wnd->nmb, wnd->nmb); + TRACE1("init returns: %08X, irql: %d", status, current_irql()); + if (status != NDIS_STATUS_SUCCESS) { + WARNING("couldn't initialize device: %08X", status); + EXIT1(return NDIS_STATUS_FAILURE); + } + + /* Wait a little to let card power up otherwise ifup might + * fail after boot */ + sleep_hz(HZ / 5); + status = mp_pnp_event(wnd, NdisDevicePnPEventPowerProfileChanged, + NdisPowerProfileAcOnLine); + if (status != NDIS_STATUS_SUCCESS) + TRACE1("setting power failed: %08X", status); + set_bit(HW_INITIALIZED, &wnd->wd->hw_status); + /* the description about NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND is + * misleading/confusing */ + status = mp_query(wnd, OID_PNP_CAPABILITIES, + &wnd->pnp_capa, sizeof(wnd->pnp_capa)); + if (status == NDIS_STATUS_SUCCESS) { + TRACE1("%d, %d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup, + wnd->pnp_capa.wakeup.min_pattern_wakeup); + wnd->attributes |= NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + status = mp_query_int(wnd, OID_PNP_ENABLE_WAKE_UP, + &wnd->ndis_wolopts); + TRACE1("%08X, %x", status, wnd->ndis_wolopts); + } else if (status == NDIS_STATUS_NOT_SUPPORTED) + wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + TRACE1("%d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup); + /* although some NDIS drivers support suspend, Linux kernel + * has issues with suspending USB devices */ + if (wrap_is_usb_bus(wnd->wd->dev_bus)) { + wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + wnd->ndis_wolopts = 0; + } + mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF); + EXIT1(return NDIS_STATUS_SUCCESS); +} + +/* MiniportHalt */ +static void mp_halt(struct ndis_device *wnd) +{ + struct miniport *mp; + + ENTER1("%p", wnd); + if (!test_and_clear_bit(HW_INITIALIZED, &wnd->wd->hw_status)) { + WARNING("device %p is not initialized - not halting", wnd); + return; + } + hangcheck_del(wnd); + del_iw_stats_timer(wnd); + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan && + wrap_is_pci_bus(wnd->wd->dev_bus)) { + up(&wnd->ndis_req_mutex); + disassociate(wnd, 0); + if (down_interruptible(&wnd->ndis_req_mutex)) + WARNING("couldn't obtain ndis_req_mutex"); + } + mp = &wnd->wd->driver->ndis_driver->mp; + TRACE1("halt: %p", mp->mp_halt); + LIN2WIN1(mp->mp_halt, wnd->nmb->mp_ctx); + /* if a driver doesn't call NdisMDeregisterInterrupt during + * halt, deregister it now */ + if (wnd->mp_interrupt) + NdisMDeregisterInterrupt(wnd->mp_interrupt); + /* cancel any timers left by bugyy windows driver; also free + * the memory for timers */ + while (1) { + struct nt_slist *slist; + struct wrap_timer *wrap_timer; + + spin_lock_bh(&ntoskernel_lock); + if ((slist = wnd->wrap_timer_slist.next)) + wnd->wrap_timer_slist.next = slist->next; + spin_unlock_bh(&ntoskernel_lock); + TIMERTRACE("%p", slist); + if (!slist) + break; + wrap_timer = container_of(slist, struct wrap_timer, slist); + wrap_timer->repeat = 0; + /* ktimer that this wrap_timer is associated to can't + * be touched, as it may have been freed by the driver + * already */ + if (del_timer_sync(&wrap_timer->timer)) + WARNING("Buggy Windows driver left timer %p " + "running", wrap_timer->nt_timer); + memset(wrap_timer, 0, sizeof(*wrap_timer)); + kfree(wrap_timer); + } + EXIT1(return); +} + +static NDIS_STATUS mp_set_power_state(struct ndis_device *wnd, + enum ndis_power_state state) +{ + NDIS_STATUS status; + + TRACE1("%d", state); + if (state == NdisDeviceStateD0) { + status = NDIS_STATUS_SUCCESS; + up(&wnd->ndis_req_mutex); + if (test_and_clear_bit(HW_HALTED, &wnd->wd->hw_status)) { + status = mp_init(wnd); + if (status == NDIS_STATUS_SUCCESS) { + set_packet_filter(wnd, wnd->packet_filter); + set_multicast_list(wnd); + } + } else if (test_and_clear_bit(HW_SUSPENDED, + &wnd->wd->hw_status)) { + status = mp_set_int(wnd, OID_PNP_SET_POWER, state); + if (status != NDIS_STATUS_SUCCESS) + WARNING("%s: setting power to state %d failed? " + "%08X", wnd->net_dev->name, state, + status); + } else + return NDIS_STATUS_FAILURE; + + if (wrap_is_pci_bus(wnd->wd->dev_bus)) { + pci_enable_wake(wnd->wd->pci.pdev, PCI_D3hot, 0); + pci_enable_wake(wnd->wd->pci.pdev, PCI_D3cold, 0); + } + if (status == NDIS_STATUS_SUCCESS) { + up(&wnd->tx_ring_mutex); + netif_device_attach(wnd->net_dev); + hangcheck_add(wnd); + add_iw_stats_timer(wnd); + } else + WARNING("%s: couldn't set power to state %d; device not" + " resumed", wnd->net_dev->name, state); + EXIT1(return status); + } else { + if (down_interruptible(&wnd->tx_ring_mutex)) + EXIT1(return NDIS_STATUS_FAILURE); + netif_device_detach(wnd->net_dev); + hangcheck_del(wnd); + del_iw_stats_timer(wnd); + status = NDIS_STATUS_NOT_SUPPORTED; + if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) { + status = mp_set_int(wnd, OID_PNP_ENABLE_WAKE_UP, + wnd->ndis_wolopts); + TRACE2("0x%x, 0x%x", status, wnd->ndis_wolopts); + if (status == NDIS_STATUS_SUCCESS) { + if (wnd->ndis_wolopts) + wnd->wd->pci.wake_state = + PowerDeviceD3; + else + wnd->wd->pci.wake_state = + PowerDeviceUnspecified; + } else + WARNING("couldn't set wake-on-lan options: " + "0x%x, %08X", wnd->ndis_wolopts, status); + status = mp_set_int(wnd, OID_PNP_SET_POWER, state); + if (status == NDIS_STATUS_SUCCESS) + set_bit(HW_SUSPENDED, &wnd->wd->hw_status); + else + WARNING("suspend failed: %08X", status); + } + if (status != NDIS_STATUS_SUCCESS) { + WARNING("%s does not support power management; " + "halting the device", wnd->net_dev->name); + mp_halt(wnd); + set_bit(HW_HALTED, &wnd->wd->hw_status); + status = STATUS_SUCCESS; + } + if (down_interruptible(&wnd->ndis_req_mutex)) + WARNING("couldn't lock ndis_req_mutex"); + EXIT1(return status); + } +} + +static int ndis_set_mac_address(struct net_device *dev, void *p) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct sockaddr *addr = p; + struct ndis_configuration_parameter param; + struct unicode_string key; + struct ansi_string ansi; + NDIS_STATUS res; + unsigned char mac_string[2 * ETH_ALEN + 1]; + mac_address mac; + + memcpy(mac, addr->sa_data, sizeof(mac)); + memset(mac_string, 0, sizeof(mac_string)); + res = snprintf(mac_string, sizeof(mac_string), MACSTR, MAC2STR(mac)); + if (res != (sizeof(mac_string) - 1)) + EXIT1(return -EINVAL); + TRACE1("new mac: %s", mac_string); + + RtlInitAnsiString(&ansi, mac_string); + if (RtlAnsiStringToUnicodeString(¶m.data.string, &ansi, + TRUE) != STATUS_SUCCESS) + EXIT1(return -EINVAL); + + param.type = NdisParameterString; + RtlInitAnsiString(&ansi, "NetworkAddress"); + if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS) { + RtlFreeUnicodeString(¶m.data.string); + EXIT1(return -EINVAL); + } + NdisWriteConfiguration(&res, wnd->nmb, &key, ¶m); + RtlFreeUnicodeString(&key); + RtlFreeUnicodeString(¶m.data.string); + + if (res != NDIS_STATUS_SUCCESS) + EXIT1(return -EFAULT); + if (ndis_reinit(wnd) == NDIS_STATUS_SUCCESS) { + res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, + mac, sizeof(mac)); + if (res == NDIS_STATUS_SUCCESS) { + TRACE1("mac:" MACSTRSEP, MAC2STR(mac)); + memcpy(dev->dev_addr, mac, sizeof(mac)); + } else + ERROR("couldn't get mac address: %08X", res); + } + EXIT1(return 0); +} + +static int setup_tx_sg_list(struct ndis_device *wnd, struct sk_buff *skb, + struct ndis_packet_oob_data *oob_data) +{ + struct ndis_sg_element *sg_element; + struct ndis_sg_list *sg_list; + int i; + + ENTER3("%p, %d", skb, skb_shinfo(skb)->nr_frags); + if (skb_shinfo(skb)->nr_frags <= 1) { + sg_element = &oob_data->wrap_tx_sg_list.elements[0]; + sg_element->address = + PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); + sg_element->length = skb->len; + oob_data->wrap_tx_sg_list.nent = 1; + oob_data->ext.info[ScatterGatherListPacketInfo] = + &oob_data->wrap_tx_sg_list; + TRACE3("%Lx, %u", sg_element->address, sg_element->length); + return 0; + } + sg_list = kmalloc(sizeof(*sg_list) + + (skb_shinfo(skb)->nr_frags + 1) * sizeof(*sg_element), + GFP_ATOMIC); + if (!sg_list) + return -ENOMEM; + sg_list->nent = skb_shinfo(skb)->nr_frags + 1; + TRACE3("%p, %d", sg_list, sg_list->nent); + sg_element = sg_list->elements; + sg_element->length = skb_headlen(skb); + sg_element->address = + PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data, + skb_headlen(skb), PCI_DMA_TODEVICE); + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + sg_element++; + sg_element->length = frag->size; + sg_element->address = + pci_map_page(wnd->wd->pci.pdev, frag->page, + frag->page_offset, frag->size, + PCI_DMA_TODEVICE); + TRACE3("%Lx, %u", sg_element->address, sg_element->length); + } + oob_data->ext.info[ScatterGatherListPacketInfo] = sg_list; + return 0; +} + +static void free_tx_sg_list(struct ndis_device *wnd, + struct ndis_packet_oob_data *oob_data) +{ + int i; + struct ndis_sg_element *sg_element; + struct ndis_sg_list *sg_list = + oob_data->ext.info[ScatterGatherListPacketInfo]; + sg_element = sg_list->elements; + TRACE3("%p, %d", sg_list, sg_list->nent); + PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, sg_element->address, + sg_element->length, PCI_DMA_TODEVICE); + if (sg_list->nent == 1) + EXIT3(return); + for (i = 1; i < sg_list->nent; i++, sg_element++) { + TRACE3("%Lx, %u", sg_element->address, sg_element->length); + pci_unmap_page(wnd->wd->pci.pdev, sg_element->address, + sg_element->length, PCI_DMA_TODEVICE); + } + TRACE3("%p", sg_list); + kfree(sg_list); +} + +static struct ndis_packet *alloc_tx_packet(struct ndis_device *wnd, + struct sk_buff *skb) +{ + struct ndis_packet *packet; + ndis_buffer *buffer; + struct ndis_packet_oob_data *oob_data; + NDIS_STATUS status; + + NdisAllocatePacket(&status, &packet, wnd->tx_packet_pool); + if (status != NDIS_STATUS_SUCCESS) + return NULL; + NdisAllocateBuffer(&status, &buffer, wnd->tx_buffer_pool, + skb->data, skb->len); + if (status != NDIS_STATUS_SUCCESS) { + NdisFreePacket(packet); + return NULL; + } + packet->private.buffer_head = buffer; + packet->private.buffer_tail = buffer; + + oob_data = NDIS_PACKET_OOB_DATA(packet); + oob_data->tx_skb = skb; + if (wnd->sg_dma_size) { + if (setup_tx_sg_list(wnd, skb, oob_data)) { + NdisFreeBuffer(buffer); + NdisFreePacket(packet); + return NULL; + } + } + if (skb->ip_summed == CHECKSUM_PARTIAL) { + struct ndis_tcp_ip_checksum_packet_info csum; + int protocol; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + protocol = ntohs(skb->protocol); +#else + protocol = skb->nh.iph->protocol; +#endif + csum.value = 0; + csum.tx.v4 = 1; + if (protocol == IPPROTO_TCP) + csum.tx.tcp = 1; + else if (protocol == IPPROTO_UDP) + csum.tx.udp = 1; +// csum->tx.ip = 1; + packet->private.flags |= NDIS_PROTOCOL_ID_TCP_IP; + oob_data->ext.info[TcpIpChecksumPacketInfo] = + (void *)(ULONG_PTR)csum.value; + } + DBG_BLOCK(4) { + dump_bytes(__FUNCTION__, skb->data, skb->len); + } + TRACE4("%p, %p, %p", packet, buffer, skb); + return packet; +} + +void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet, + NDIS_STATUS status) +{ + ndis_buffer *buffer; + struct ndis_packet_oob_data *oob_data; + struct sk_buff *skb; + struct ndis_packet_pool *pool; + + assert_irql(_irql_ <= DISPATCH_LEVEL); + assert(packet->private.packet_flags); + oob_data = NDIS_PACKET_OOB_DATA(packet); + skb = oob_data->tx_skb; + buffer = packet->private.buffer_head; + TRACE4("%p, %p, %p, %08X", packet, buffer, skb, status); + if (status == NDIS_STATUS_SUCCESS) { + pre_atomic_add(wnd->net_stats.tx_bytes, packet->private.len); + atomic_inc_var(wnd->net_stats.tx_packets); + } else { + TRACE1("packet dropped: %08X", status); + atomic_inc_var(wnd->net_stats.tx_dropped); + } + if (wnd->sg_dma_size) + free_tx_sg_list(wnd, oob_data); + NdisFreeBuffer(buffer); + dev_kfree_skb_any(skb); + pool = packet->private.pool; + NdisFreePacket(packet); + if (netif_queue_stopped(wnd->net_dev) && + ((pool->max_descr - pool->num_used_descr) >= + (wnd->max_tx_packets / 4))) { + set_bit(NETIF_WAKEQ, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + EXIT4(return); +} + +/* MiniportSend and MiniportSendPackets */ +/* this function is called holding tx_ring_mutex. start and n are such + * that start + n < TX_RING_SIZE; i.e., packets don't wrap around + * ring */ +static u8 mp_tx_packets(struct ndis_device *wnd, u8 start, u8 n) +{ + NDIS_STATUS res; + struct miniport *mp; + struct ndis_packet *packet; + u8 sent; + KIRQL irql; + + ENTER3("%d, %d", start, n); + mp = &wnd->wd->driver->ndis_driver->mp; + if (mp->send_packets) { + if (deserialized_driver(wnd)) { + LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, + &wnd->tx_ring[start], n); + sent = n; + } else { + irql = serialize_lock_irql(wnd); + LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, + &wnd->tx_ring[start], n); + serialize_unlock_irql(wnd, irql); + for (sent = 0; sent < n && wnd->tx_ok; sent++) { + struct ndis_packet_oob_data *oob_data; + packet = wnd->tx_ring[start + sent]; + oob_data = NDIS_PACKET_OOB_DATA(packet); + switch ((res = + xchg(&oob_data->status, + NDIS_STATUS_NOT_RECOGNIZED))) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, + NDIS_STATUS_SUCCESS); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + /* resubmit this packet and + * the rest when resources + * become available */ + sent--; + break; + case NDIS_STATUS_FAILURE: + free_tx_packet(wnd, packet, + NDIS_STATUS_FAILURE); + break; + default: + ERROR("%p: invalid status: %08X", + packet, res); + free_tx_packet(wnd, packet, + oob_data->status); + break; + } + TRACE3("%p, %d", packet, res); + } + } + TRACE3("sent: %d(%d)", sent, n); + } else { + for (sent = 0; sent < n && wnd->tx_ok; sent++) { + struct ndis_packet_oob_data *oob_data; + packet = wnd->tx_ring[start + sent]; + oob_data = NDIS_PACKET_OOB_DATA(packet); + oob_data->status = NDIS_STATUS_NOT_RECOGNIZED; + irql = serialize_lock_irql(wnd); + res = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, + packet, packet->private.flags); + serialize_unlock_irql(wnd, irql); + switch (res) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, res); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + /* resend this packet when resources + * become available */ + sent--; + break; + case NDIS_STATUS_FAILURE: + free_tx_packet(wnd, packet, res); + break; + default: + ERROR("packet %p: invalid status: %08X", + packet, res); + break; + } + } + } + EXIT3(return sent); +} + +static void tx_worker(worker_param_t param) +{ + struct ndis_device *wnd; + s8 n; + + wnd = worker_param_data(param, struct ndis_device, tx_work); + ENTER3("tx_ok %d", wnd->tx_ok); + while (wnd->tx_ok) { + if (down_interruptible(&wnd->tx_ring_mutex)) + break; + spin_lock_bh(&wnd->tx_ring_lock); + n = wnd->tx_ring_end - wnd->tx_ring_start; + TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n); + /* end == start if either ring is empty or full; in + * the latter case is_tx_ring_full is set */ + if (n == 0) { + if (wnd->is_tx_ring_full) + n = TX_RING_SIZE - wnd->tx_ring_start; + else { + spin_unlock_bh(&wnd->tx_ring_lock); + up(&wnd->tx_ring_mutex); + break; + } + } else if (n < 0) + n = TX_RING_SIZE - wnd->tx_ring_start; + spin_unlock_bh(&wnd->tx_ring_lock); + if (unlikely(n > wnd->max_tx_packets)) + n = wnd->max_tx_packets; + n = mp_tx_packets(wnd, wnd->tx_ring_start, n); + if (n) { + wnd->net_dev->trans_start = jiffies; + wnd->tx_ring_start = + (wnd->tx_ring_start + n) % TX_RING_SIZE; + wnd->is_tx_ring_full = 0; + } + up(&wnd->tx_ring_mutex); + TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n); + } + EXIT3(return); +} + +static int tx_skbuff(struct sk_buff *skb, struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct ndis_packet *packet; + + packet = alloc_tx_packet(wnd, skb); + if (!packet) { + TRACE2("couldn't allocate packet"); + netif_tx_lock(dev); + netif_stop_queue(dev); + netif_tx_unlock(dev); + return NETDEV_TX_BUSY; + } + spin_lock(&wnd->tx_ring_lock); + wnd->tx_ring[wnd->tx_ring_end++] = packet; + if (wnd->tx_ring_end == TX_RING_SIZE) + wnd->tx_ring_end = 0; + if (wnd->tx_ring_end == wnd->tx_ring_start) { + netif_tx_lock(dev); + wnd->is_tx_ring_full = 1; + netif_stop_queue(dev); + netif_tx_unlock(dev); + } + spin_unlock(&wnd->tx_ring_lock); + TRACE4("ring: %d, %d", wnd->tx_ring_start, wnd->tx_ring_end); + schedule_wrapndis_work(&wnd->tx_work); + return NETDEV_TX_OK; +} + +static int set_packet_filter(struct ndis_device *wnd, ULONG packet_filter) +{ + NDIS_STATUS res; + + while (1) { + res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, + packet_filter); + if (res == NDIS_STATUS_SUCCESS) + break; + TRACE2("couldn't set filter 0x%08x", packet_filter); + /* NDIS_PACKET_TYPE_PROMISCUOUS may not work with 802.11 */ + if (packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS) { + packet_filter &= ~NDIS_PACKET_TYPE_PROMISCUOUS; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_ALL_LOCAL) { + packet_filter &= ~NDIS_PACKET_TYPE_ALL_LOCAL; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) { + packet_filter &= ~NDIS_PACKET_TYPE_ALL_FUNCTIONAL; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_MULTICAST) { + packet_filter &= ~NDIS_PACKET_TYPE_MULTICAST; + packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) { + packet_filter &= ~NDIS_PACKET_TYPE_ALL_MULTICAST; + continue; + } + break; + } + + wnd->packet_filter = packet_filter; + res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter); + if (packet_filter != wnd->packet_filter) { + WARNING("filter not set: 0x%08x, 0x%08x", + packet_filter, wnd->packet_filter); + wnd->packet_filter = packet_filter; + } + if (wnd->packet_filter) + EXIT3(return 0); + else + EXIT3(return -1); +} + +static int ndis_net_dev_open(struct net_device *net_dev) +{ + ENTER1("%p", netdev_priv(net_dev)); + netif_start_queue(net_dev); + netif_poll_enable(net_dev); + EXIT1(return 0); +} + +static int ndis_net_dev_close(struct net_device *net_dev) +{ + ENTER1("%p", netdev_priv(net_dev)); + netif_poll_disable(net_dev); + netif_tx_disable(net_dev); + EXIT1(return 0); +} + +static int ndis_change_mtu(struct net_device *net_dev, int mtu) +{ + struct ndis_device *wnd = netdev_priv(net_dev); + int max; + + if (mtu < ETH_ZLEN) + return -EINVAL; + if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &max) != + NDIS_STATUS_SUCCESS) + return -EOPNOTSUPP; + TRACE1("%d", max); + max -= ETH_HLEN; + if (max <= ETH_ZLEN) + return -EINVAL; + if (mtu + ETH_HLEN > max) + return -EINVAL; + net_dev->mtu = mtu; + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void ndis_poll_controller(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + + disable_irq(dev->irq); + ndis_isr(wnd->mp_interrupt->kinterrupt, wnd->mp_interrupt); + enable_irq(dev->irq); +} +#endif + +/* called from BH context */ +static struct net_device_stats *ndis_get_stats(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + return &wnd->net_stats; +} + +/* called from BH context */ +static void ndis_set_multicast_list(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + set_bit(SET_MULTICAST_LIST, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); +} + +/* called from BH context */ +struct iw_statistics *get_iw_stats(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + return &wnd->iw_stats; +} + +static void update_iw_stats(struct ndis_device *wnd) +{ + struct iw_statistics *iw_stats = &wnd->iw_stats; + struct ndis_wireless_stats ndis_stats; + NDIS_STATUS res; + ndis_rssi rssi; + int qual; + + ENTER2("%p", wnd); + if (wnd->iw_stats_enabled == FALSE || !netif_carrier_ok(wnd->net_dev)) { + memset(iw_stats, 0, sizeof(*iw_stats)); + EXIT2(return); + } + res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi)); + if (res == NDIS_STATUS_SUCCESS) + iw_stats->qual.level = rssi; + + qual = 100 * (rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE); + if (qual < 0) + qual = 0; + else if (qual > 100) + qual = 100; + + iw_stats->qual.noise = WL_NOISE; + iw_stats->qual.qual = qual; + + res = mp_query(wnd, OID_802_11_STATISTICS, + &ndis_stats, sizeof(ndis_stats)); + if (res != NDIS_STATUS_SUCCESS) + EXIT2(return); + iw_stats->discard.retries = (unsigned long)ndis_stats.retry + + (unsigned long)ndis_stats.multi_retry; + iw_stats->discard.misc = (unsigned long)ndis_stats.fcs_err + + (unsigned long)ndis_stats.rtss_fail + + (unsigned long)ndis_stats.ack_fail + + (unsigned long)ndis_stats.frame_dup; + + EXIT2(return); +} + +static void set_multicast_list(struct ndis_device *wnd) +{ + struct net_device *net_dev; + ULONG packet_filter; + NDIS_STATUS res; + + net_dev = wnd->net_dev; + packet_filter = wnd->packet_filter; + + TRACE2("0x%08x", packet_filter); + if (net_dev->flags & IFF_PROMISC) { + packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS | + NDIS_PACKET_TYPE_ALL_LOCAL; + } else if (net_dev->flags & IFF_ALLMULTI || + net_dev->mc_count > wnd->multicast_size) { + packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; + TRACE2("0x%08x", packet_filter); + } else if (net_dev->mc_count > 0) { + int i, size; + char *buf; + struct dev_mc_list *mclist; + size = min(wnd->multicast_size, net_dev->mc_count); + TRACE2("%d, %d", wnd->multicast_size, net_dev->mc_count); + buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); + if (!buf) { + WARNING("couldn't allocate memory"); + EXIT2(return); + } + mclist = net_dev->mc_list; + for (i = 0; i < size && mclist; mclist = mclist->next) { + if (mclist->dmi_addrlen != ETH_ALEN) + continue; + memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); + TRACE2(MACSTRSEP, MAC2STR(mclist->dmi_addr)); + i++; + } + res = mp_set(wnd, OID_802_3_MULTICAST_LIST, buf, i * ETH_ALEN); + if (res == NDIS_STATUS_SUCCESS && i > 0) + packet_filter |= NDIS_PACKET_TYPE_MULTICAST; + else + packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; + kfree(buf); + } + TRACE2("0x%08x", packet_filter); + res = set_packet_filter(wnd, packet_filter); + if (res) + TRACE1("couldn't set packet filter (%08X)", res); + EXIT2(return); +} + +static void link_status_off(struct ndis_device *wnd) +{ +#ifdef CONFIG_WIRELESS_EXT + union iwreq_data wrqu; + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); +#endif + EXIT2(return); +} + +static void link_status_on(struct ndis_device *wnd) +{ +#ifdef CONFIG_WIRELESS_EXT + struct ndis_assoc_info *ndis_assoc_info; + union iwreq_data wrqu; + NDIS_STATUS res; + const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX + 32; +#endif + + ENTER2(""); +#ifdef CONFIG_WIRELESS_EXT + memset(&wrqu, 0, sizeof(wrqu)); + ndis_assoc_info = kzalloc(assoc_size, GFP_KERNEL); + if (!ndis_assoc_info) { + ERROR("couldn't allocate memory"); + goto send_assoc_event; + } + res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION, + ndis_assoc_info, assoc_size); + if (res) { + TRACE2("query assoc_info failed (%08X)", res); + kfree(ndis_assoc_info); + goto send_assoc_event; + } + TRACE2("%u, 0x%x, %u, 0x%x, %u", ndis_assoc_info->length, + ndis_assoc_info->req_ies, ndis_assoc_info->req_ie_length, + ndis_assoc_info->resp_ies, ndis_assoc_info->resp_ie_length); + if (ndis_assoc_info->req_ie_length > 0) { + wrqu.data.length = ndis_assoc_info->req_ie_length; + wireless_send_event(wnd->net_dev, IWEVASSOCREQIE, &wrqu, + ((char *)ndis_assoc_info) + + ndis_assoc_info->offset_req_ies); + } + if (ndis_assoc_info->resp_ie_length > 0) { + wrqu.data.length = ndis_assoc_info->resp_ie_length; + wireless_send_event(wnd->net_dev, IWEVASSOCRESPIE, &wrqu, + ((char *)ndis_assoc_info) + + ndis_assoc_info->offset_resp_ies); + } + kfree(ndis_assoc_info); + +send_assoc_event: + get_ap_address(wnd, wrqu.ap_addr.sa_data); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + TRACE2(MACSTRSEP, MAC2STR(wrqu.ap_addr.sa_data)); + wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); +#endif + EXIT2(return); +} + +static void iw_stats_timer_proc(unsigned long data) +{ + struct ndis_device *wnd = (struct ndis_device *)data; + + ENTER2("%d", wnd->iw_stats_interval); + if (wnd->iw_stats_interval > 0) { + set_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval); +} + +static void add_iw_stats_timer(struct ndis_device *wnd) +{ + if (wnd->physical_medium != NdisPhysicalMediumWirelessLan) + return; + if (wnd->iw_stats_interval < 0) + wnd->iw_stats_interval *= -1; + wnd->iw_stats_timer.data = (unsigned long)wnd; + wnd->iw_stats_timer.function = iw_stats_timer_proc; + mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval); +} + +static void del_iw_stats_timer(struct ndis_device *wnd) +{ + ENTER2("%d", wnd->iw_stats_interval); + wnd->iw_stats_interval *= -1; + del_timer_sync(&wnd->iw_stats_timer); + EXIT2(return); +} + +static void hangcheck_proc(unsigned long data) +{ + struct ndis_device *wnd = (struct ndis_device *)data; + + ENTER3("%d", wnd->hangcheck_interval); + if (wnd->hangcheck_interval > 0) { + set_bit(HANGCHECK, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval); + EXIT3(return); +} + +void hangcheck_add(struct ndis_device *wnd) +{ + if (!wnd->wd->driver->ndis_driver->mp.hangcheck || + hangcheck_interval < 0) + EXIT2(return); + + if (hangcheck_interval > 0) + wnd->hangcheck_interval = hangcheck_interval * HZ; + if (wnd->hangcheck_interval < 0) + wnd->hangcheck_interval *= -1; + wnd->hangcheck_timer.data = (unsigned long)wnd; + wnd->hangcheck_timer.function = hangcheck_proc; + mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval); + EXIT2(return); +} + +void hangcheck_del(struct ndis_device *wnd) +{ + ENTER2("%d", wnd->hangcheck_interval); + if (wnd->hangcheck_interval > 0) + wnd->hangcheck_interval *= -1; + del_timer_sync(&wnd->hangcheck_timer); + EXIT2(return); +} + +/* worker procedure to take care of setting/checking various states */ +static void ndis_worker(worker_param_t param) +{ + struct ndis_device *wnd; + + wnd = worker_param_data(param, struct ndis_device, ndis_work); + WORKTRACE("0x%lx", wnd->ndis_pending_work); + + if (test_and_clear_bit(NETIF_WAKEQ, &wnd->ndis_pending_work)) { + netif_tx_lock_bh(wnd->net_dev); + netif_wake_queue(wnd->net_dev); + netif_tx_unlock_bh(wnd->net_dev); + } + + if (test_and_clear_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work)) + link_status_off(wnd); + + if (test_and_clear_bit(LINK_STATUS_ON, &wnd->ndis_pending_work)) + link_status_on(wnd); + + if (test_and_clear_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work)) + update_iw_stats(wnd); + + if (test_and_clear_bit(SET_MULTICAST_LIST, + &wnd->ndis_pending_work)) + set_multicast_list(wnd); + + if (test_and_clear_bit(HANGCHECK, &wnd->ndis_pending_work)) { + struct miniport *mp; + BOOLEAN reset; + KIRQL irql; + + mp = &wnd->wd->driver->ndis_driver->mp; + irql = serialize_lock_irql(wnd); + reset = LIN2WIN1(mp->hangcheck, wnd->nmb->mp_ctx); + serialize_unlock_irql(wnd, irql); + if (reset) { + TRACE2("%s needs reset", wnd->net_dev->name); + mp_reset(wnd); + } + } + WORKEXIT(return); +} + +NDIS_STATUS ndis_reinit(struct ndis_device *wnd) +{ + NDIS_STATUS status; + + wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + status = mp_set_power_state(wnd, NdisDeviceStateD3); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("halting device %s failed: %08X", wnd->net_dev->name, + status); + return status; + } + status = mp_set_power_state(wnd, NdisDeviceStateD0); + if (status != NDIS_STATUS_SUCCESS) + ERROR("starting device %s failed: %08X", wnd->net_dev->name, + status); + return status; +} + +static void get_encryption_capa(struct ndis_device *wnd, char *buf, + const int buf_len) +{ + int i, mode; + NDIS_STATUS res; + struct ndis_assoc_info ndis_assoc_info; + struct ndis_add_key ndis_key; + struct ndis_capability *c; + + ENTER1("%p", wnd); + /* set network type to g, b, or a, in that order */ + res = mp_query(wnd, OID_802_11_NETWORK_TYPES_SUPPORTED, buf, buf_len); + if (res == NDIS_STATUS_SUCCESS) { + struct network_type_list *net_types; + unsigned long types = 0; + net_types = (typeof(net_types))buf; + for (i = 0; i < net_types->num; i++) { + TRACE2("%d", net_types->types[i]); + set_bit(net_types->types[i], &types); + } + if (types & Ndis802_11OFDM24) + mode = Ndis802_11OFDM24; + else if (types & Ndis802_11DS) + mode = Ndis802_11DS; + else if (types & Ndis802_11OFDM5) + mode = Ndis802_11OFDM5; + else + mode = Ndis802_11DS; + mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, mode); + } + /* check if WEP is supported */ + if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, + IW_AUTH_CIPHER_NONE) == 0 && + get_ndis_encr_mode(wnd) == Ndis802_11Encryption1KeyAbsent) + set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); + + /* check if WPA is supported */ + if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPA) == 0 && + get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPA) + set_bit(Ndis802_11AuthModeWPA, &wnd->capa.encr); + else + EXIT1(return); + + if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPAPSK) == 0 && + get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPAPSK) + set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.encr); + + /* check for highest encryption */ + mode = 0; + if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_CCMP, + IW_AUTH_CIPHER_NONE) == 0 && + (i = get_ndis_encr_mode(wnd)) > 0 && + (i == Ndis802_11Encryption3KeyAbsent || + i == Ndis802_11Encryption3Enabled)) + mode = Ndis802_11Encryption3Enabled; + else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_TKIP, + IW_AUTH_CIPHER_NONE) == 0 && + (i = get_ndis_encr_mode(wnd)) > 0 && + (i == Ndis802_11Encryption2KeyAbsent || + i == Ndis802_11Encryption2Enabled)) + mode = Ndis802_11Encryption2Enabled; + else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, + IW_AUTH_CIPHER_NONE) == 0 && + (i = get_ndis_encr_mode(wnd)) > 0 && + (i == Ndis802_11Encryption1KeyAbsent || + i == Ndis802_11Encryption1Enabled)) + mode = Ndis802_11Encryption1Enabled; + + TRACE1("mode: %d", mode); + if (mode == 0) + EXIT1(return); + set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); + if (mode == Ndis802_11Encryption1Enabled) + EXIT1(return); + + ndis_key.length = 32; + ndis_key.index = 0xC0000001; + ndis_key.struct_size = sizeof(ndis_key); + res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size); + TRACE2("%08X, %lu", res, (unsigned long)sizeof(ndis_key)); + if (res && res != NDIS_STATUS_INVALID_DATA) + EXIT1(return); + res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION, + &ndis_assoc_info, sizeof(ndis_assoc_info)); + TRACE1("%08X", res); + if (res == NDIS_STATUS_NOT_SUPPORTED) + EXIT1(return); + + set_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr); + if (mode == Ndis802_11Encryption3Enabled) + set_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr); + /* not all drivers support OID_802_11_CAPABILITY, so we don't + * know for sure if driver support WPA or WPAPSK; assume + * WPAPSK */ + set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth); + wnd->max_pmkids = 1; + + memset(buf, 0, buf_len); + c = (struct ndis_capability *)buf; + res = mp_query(wnd, OID_802_11_CAPABILITY, buf, buf_len); + if (!(res == NDIS_STATUS_SUCCESS && c->version == 2)) + EXIT1(return); + wnd->max_pmkids = c->num_PMKIDs; + + for (i = 0; i < c->num_auth_encr_pair; i++) { + struct ndis_auth_encr_pair *ae; + + ae = &c->auth_encr_pair[i]; + if ((char *)(ae + 1) > buf + buf_len) + break; + switch (ae->auth_mode) { + case Ndis802_11AuthModeOpen: + case Ndis802_11AuthModeShared: + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPANone: + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + set_bit(ae->auth_mode, &wnd->capa.auth); + break; + default: + WARNING("unknown auth_mode: %d", ae->auth_mode); + break; + } + switch (ae->encr_mode) { + case Ndis802_11EncryptionDisabled: + case Ndis802_11Encryption1Enabled: + case Ndis802_11Encryption2Enabled: + case Ndis802_11Encryption3Enabled: + set_bit(ae->encr_mode, &wnd->capa.encr); + break; + default: + WARNING("unknown encr_mode: %d", ae->encr_mode); + break; + } + } + EXIT1(return); +} + +wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo, + struct irp *irp) +{ + struct ndis_device *wnd; + + TRACE3("fdo: %p", fdo); + /* for now, we don't have anything intresting here, so pass it + * down to bus driver */ + wnd = fdo->reserved; + return IoPassIrpDown(wnd->nmb->pdo, irp); +} +WIN_FUNC_DECL(NdisDispatchDeviceControl,2) + +wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct ndis_device *wnd; + enum ndis_power_state state; + NTSTATUS status; + NDIS_STATUS ndis_status; + + irp_sl = IoGetCurrentIrpStackLocation(irp); + wnd = fdo->reserved; + IOTRACE("fdo: %p, fn: %d:%d, wnd: %p", fdo, irp_sl->major_fn, + irp_sl->minor_fn, wnd); + if ((irp_sl->params.power.type == SystemPowerState && + irp_sl->params.power.state.system_state > PowerSystemWorking) || + (irp_sl->params.power.type == DevicePowerState && + irp_sl->params.power.state.device_state > PowerDeviceD0)) + state = NdisDeviceStateD3; + else + state = NdisDeviceStateD0; + switch (irp_sl->minor_fn) { + case IRP_MN_SET_POWER: + if (state == NdisDeviceStateD0) { + status = IoSyncForwardIrp(wnd->nmb->pdo, irp); + if (status != STATUS_SUCCESS) + break; + ndis_status = mp_set_power_state(wnd, state); + if (ndis_status != NDIS_STATUS_SUCCESS) + WARNING("couldn't set power to %d: %08X", + state, ndis_status); + TRACE2("%s: device resumed", wnd->net_dev->name); + irp->io_status.status = status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + break; + } else { + ndis_status = mp_set_power_state(wnd, state); + /* TODO: handle error case */ + if (ndis_status != NDIS_STATUS_SUCCESS) + WARNING("setting power to %d failed: %08X", + state, ndis_status); + status = IoAsyncForwardIrp(wnd->nmb->pdo, irp); + } + break; + case IRP_MN_QUERY_POWER: + if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) { + ndis_status = mp_query(wnd, OID_PNP_QUERY_POWER, + &state, sizeof(state)); + TRACE2("%d, %08X", state, ndis_status); + /* this OID must always succeed */ + if (ndis_status != NDIS_STATUS_SUCCESS) + TRACE1("query power returns %08X", ndis_status); + irp->io_status.status = STATUS_SUCCESS; + } else + irp->io_status.status = STATUS_SUCCESS; + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + case IRP_MN_WAIT_WAKE: + case IRP_MN_POWER_SEQUENCE: + /* TODO: implement WAIT_WAKE */ + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + default: + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + } + IOEXIT(return status); +} +WIN_FUNC_DECL(NdisDispatchPower,2) + +wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct ndis_device *wnd; + struct device_object *pdo; + NTSTATUS status; + + IOTRACE("fdo: %p, irp: %p", fdo, irp); + irp_sl = IoGetCurrentIrpStackLocation(irp); + wnd = fdo->reserved; + pdo = wnd->nmb->pdo; + switch (irp_sl->minor_fn) { + case IRP_MN_START_DEVICE: + status = IoSyncForwardIrp(pdo, irp); + if (status != STATUS_SUCCESS) + break; + if (ndis_start_device(wnd) == NDIS_STATUS_SUCCESS) + status = STATUS_SUCCESS; + else + status = STATUS_FAILURE; + irp->io_status.status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + break; + case IRP_MN_QUERY_STOP_DEVICE: + /* TODO: implement in NDIS */ + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + case IRP_MN_STOP_DEVICE: + mp_halt(wnd); + irp->io_status.status = STATUS_SUCCESS; + status = IoAsyncForwardIrp(pdo, irp); + break; + case IRP_MN_REMOVE_DEVICE: + TRACE1("%s", wnd->net_dev->name); + mp_pnp_event(wnd, NdisDevicePnPEventSurpriseRemoved, 0); + if (ndis_remove_device(wnd)) { + status = STATUS_FAILURE; + break; + } + /* wnd is already freed */ + status = IoAsyncForwardIrp(pdo, irp); + IoDetachDevice(fdo); + IoDeleteDevice(fdo); + break; + default: + status = IoAsyncForwardIrp(pdo, irp); + break; + } + IOTRACE("status: %08X", status); + IOEXIT(return status); +} +WIN_FUNC_DECL(NdisDispatchPnp,2) + +static void set_task_offload(struct ndis_device *wnd, void *buf, + const int buf_size) +{ + struct ndis_task_offload_header *task_offload_header; + struct ndis_task_offload *task_offload; + struct ndis_task_tcp_ip_checksum *csum = NULL; + struct ndis_task_tcp_large_send *tso = NULL; + NDIS_STATUS status; + + memset(buf, 0, buf_size); + task_offload_header = buf; + task_offload_header->version = NDIS_TASK_OFFLOAD_VERSION; + task_offload_header->size = sizeof(*task_offload_header); + task_offload_header->encap_format.flags.fixed_header_size = 1; + task_offload_header->encap_format.header_size = sizeof(struct ethhdr); + task_offload_header->encap_format.encap = IEEE_802_3_Encapsulation; + status = mp_query(wnd, OID_TCP_TASK_OFFLOAD, buf, buf_size); + TRACE1("%08X", status); + if (status != NDIS_STATUS_SUCCESS) + EXIT1(return); + if (task_offload_header->offset_first_task == 0) + EXIT1(return); + task_offload = ((void *)task_offload_header + + task_offload_header->offset_first_task); + while (1) { + TRACE1("%d, %d", task_offload->version, task_offload->task); + switch(task_offload->task) { + case TcpIpChecksumNdisTask: + csum = (void *)task_offload->task_buf; + break; + case TcpLargeSendNdisTask: + tso = (void *)task_offload->task_buf; + break; + default: + TRACE1("%d", task_offload->task); + break; + } + if (task_offload->offset_next_task == 0) + break; + task_offload = (void *)task_offload + + task_offload->offset_next_task; + } + if (tso) + TRACE1("%u, %u, %d, %d", tso->max_size, tso->min_seg_count, + tso->tcp_opts, tso->ip_opts); + if (!csum) + EXIT1(return); + TRACE1("%08x, %08x", csum->v4_tx.value, csum->v4_rx.value); + task_offload_header->encap_format.flags.fixed_header_size = 1; + task_offload_header->encap_format.header_size = sizeof(struct ethhdr); + task_offload_header->offset_first_task = sizeof(*task_offload_header); + task_offload = ((void *)task_offload_header + + task_offload_header->offset_first_task); + task_offload->offset_next_task = 0; + task_offload->size = sizeof(*task_offload); + task_offload->task = TcpIpChecksumNdisTask; + memcpy(task_offload->task_buf, csum, sizeof(*csum)); + task_offload->task_buf_length = sizeof(*csum); + status = mp_set(wnd, OID_TCP_TASK_OFFLOAD, task_offload_header, + sizeof(*task_offload_header) + + sizeof(*task_offload) + sizeof(*csum)); + TRACE1("%08X", status); + if (status != NDIS_STATUS_SUCCESS) + EXIT2(return); + wnd->tx_csum = csum->v4_tx; + if (csum->v4_tx.tcp_csum && csum->v4_tx.udp_csum) { + if (csum->v4_tx.ip_csum) { + wnd->net_dev->features |= NETIF_F_HW_CSUM; + TRACE1("hw checksum enabled"); + } else { + wnd->net_dev->features |= NETIF_F_IP_CSUM; + TRACE1("IP checksum enabled"); + } + if (wnd->sg_dma_size) + wnd->net_dev->features |= NETIF_F_SG; + } + wnd->rx_csum = csum->v4_rx; + EXIT1(return); +} + +static void get_supported_oids(struct ndis_device *wnd) +{ + NDIS_STATUS res; + int i, n, needed; + ndis_oid *oids; + + res = mp_query_info(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0, NULL, + &needed); + if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT || + res == NDIS_STATUS_INVALID_LENGTH)) + EXIT1(return); + oids = kmalloc(needed, GFP_KERNEL); + if (!oids) { + TRACE1("couldn't allocate memory"); + EXIT1(return); + } + res = mp_query(wnd, OID_GEN_SUPPORTED_LIST, oids, needed); + if (res) { + TRACE1("failed: %08X", res); + kfree(oids); + EXIT1(return); + } + for (i = 0, n = needed / sizeof(*oids); i < n; i++) { + TRACE1("oid: %08X", oids[i]); + /* if a wireless device didn't say so for + * OID_GEN_PHYSICAL_MEDIUM (they should, but in case) */ + if (wnd->physical_medium != NdisPhysicalMediumWirelessLan && + oids[i] == OID_802_11_SSID) + wnd->physical_medium = NdisPhysicalMediumWirelessLan; + } + kfree(oids); + EXIT1(return); +} + +static void ndis_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct ndis_device *wnd = netdev_priv(dev); + strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 2); + strcat(info->driver, "+"); + strncat(info->driver, wnd->wd->driver->name, + sizeof(info->driver) - strlen(DRIVER_NAME) - 1); + strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 2); + strcat(info->version, "+"); + strncat(info->version, wnd->wd->driver->version, + sizeof(info->version) - strlen(DRIVER_VERSION) - 1); + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + strncpy(info->bus_info, pci_name(wnd->wd->pci.pdev), + sizeof(info->bus_info) - 1); +#ifdef ENABLE_USB + else + usb_make_path(wnd->wd->usb.udev, info->bus_info, + sizeof(info->bus_info) - 1); +#endif + return; +} + +static u32 ndis_get_link(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + return netif_carrier_ok(wnd->net_dev); +} + +static void ndis_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct ndis_device *wnd = netdev_priv(dev); + + wol->supported = 0; + wol->wolopts = 0; + if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND)) + EXIT2(return); + if (!wrap_is_pci_bus(wnd->wd->dev_bus)) + EXIT2(return); + /* we always suspend to D3 */ + if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3) + return; + wol->supported |= WAKE_MAGIC; + if (wnd->ndis_wolopts & NDIS_PNP_WAKE_UP_MAGIC_PACKET) + wol->wolopts |= WAKE_MAGIC; + return; +} + +static int ndis_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND)) + return -EOPNOTSUPP; + if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3) + EXIT2(return -EOPNOTSUPP); + TRACE2("0x%x", wol->wolopts); + if (wol->wolopts & WAKE_MAGIC) { + wnd->ndis_wolopts |= NDIS_PNP_WAKE_UP_MAGIC_PACKET; + if (wol->wolopts != WAKE_MAGIC) + WARNING("ignored wake-on-lan options: 0x%x", + wol->wolopts & ~WAKE_MAGIC); + } else if (!wol->wolopts) + wnd->ndis_wolopts = 0; + else + return -EOPNOTSUPP; + TRACE2("0x%x", wnd->ndis_wolopts); + return 0; +} + +static u32 ndis_get_tx_csum(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->tx_csum.tcp_csum && wnd->tx_csum.udp_csum) + return 1; + else + return 0; +} + +static u32 ndis_get_rx_csum(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->rx_csum.value) + return 1; + else + return 0; +} + +static int ndis_set_tx_csum(struct net_device *dev, u32 data) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (data && (wnd->tx_csum.value == 0)) + return -EOPNOTSUPP; + + if (wnd->tx_csum.ip_csum) { + ethtool_op_set_tx_hw_csum(dev, data); + } else + ethtool_op_set_tx_csum(dev, data); + return 0; +} + +static int ndis_set_rx_csum(struct net_device *dev, u32 data) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (data && (wnd->tx_csum.value == 0)) + return -EOPNOTSUPP; + + /* TODO: enable/disable rx csum through NDIS */ + return 0; +} + +static u32 ndis_get_sg(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->sg_dma_size) + return ethtool_op_get_sg(dev); + else + return 0; +} + +static int ndis_set_sg(struct net_device *dev, u32 data) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->sg_dma_size) + return ethtool_op_set_sg(dev, data); + else + return -EOPNOTSUPP; +} + +static struct ethtool_ops ndis_ethtool_ops = { + .get_drvinfo = ndis_get_drvinfo, + .get_link = ndis_get_link, + .get_wol = ndis_get_wol, + .set_wol = ndis_set_wol, + .get_tx_csum = ndis_get_tx_csum, + .get_rx_csum = ndis_get_rx_csum, + .set_tx_csum = ndis_set_tx_csum, + .set_rx_csum = ndis_set_rx_csum, + .get_sg = ndis_get_sg, + .set_sg = ndis_set_sg, +}; + +static int notifier_event(struct notifier_block *notifier, unsigned long event, + void *ptr) +{ + struct net_device *net_dev = ptr; + + ENTER2("0x%lx", event); + if (net_dev->open == ndis_net_dev_open && event == NETDEV_CHANGENAME) { + struct ndis_device *wnd = netdev_priv(net_dev); + /* called with rtnl lock held, so no need to lock */ + wrap_procfs_remove_ndis_device(wnd); + printk(KERN_INFO "%s: changing interface name from '%s' to " + "'%s'\n", DRIVER_NAME, wnd->netdev_name, net_dev->name); + memcpy(wnd->netdev_name, net_dev->name, + sizeof(wnd->netdev_name)); + wrap_procfs_add_ndis_device(wnd); + } + return NOTIFY_DONE; +} + +static struct notifier_block netdev_notifier = { + .notifier_call = notifier_event, +}; + +static NDIS_STATUS ndis_start_device(struct ndis_device *wnd) +{ + struct wrap_device *wd; + struct net_device *net_dev; + NDIS_STATUS status; + char *buf; + const int buf_len = 256; + mac_address mac; + struct transport_header_offset *tx_header_offset; + int n; + + ENTER2("%d", in_atomic()); + status = mp_init(wnd); + if (status == NDIS_STATUS_NOT_RECOGNIZED) + EXIT1(return NDIS_STATUS_SUCCESS); + if (status != NDIS_STATUS_SUCCESS) + EXIT1(return status); + wd = wnd->wd; + net_dev = wnd->net_dev; + + get_supported_oids(wnd); + memset(mac, 0, sizeof(mac)); + status = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac)); + if (memcmp(mac, "\x00\x00\x00\x00\x00\x00", sizeof(mac)) == 0) { + status = mp_query(wnd, OID_802_3_PERMANENT_ADDRESS, mac, + sizeof(mac)); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("couldn't get mac address: %08X", status); + goto err_start; + } + } + TRACE1("mac:" MACSTRSEP, MAC2STR(mac)); + memcpy(net_dev->dev_addr, mac, ETH_ALEN); + + strncpy(net_dev->name, if_name, IFNAMSIZ - 1); + net_dev->name[IFNAMSIZ - 1] = 0; + + wnd->packet_filter = NDIS_PACKET_TYPE_DIRECTED | + NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_MULTICAST; + net_dev->open = ndis_net_dev_open; + net_dev->hard_start_xmit = tx_skbuff; + net_dev->stop = ndis_net_dev_close; + net_dev->get_stats = ndis_get_stats; + net_dev->change_mtu = ndis_change_mtu; + net_dev->do_ioctl = NULL; + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + net_dev->wireless_handlers = &ndis_handler_def; + } + net_dev->set_multicast_list = ndis_set_multicast_list; + net_dev->set_mac_address = ndis_set_mac_address; + net_dev->ethtool_ops = &ndis_ethtool_ops; + if (wnd->mp_interrupt) + net_dev->irq = wnd->mp_interrupt->irq; + net_dev->mem_start = wnd->mem_start; + net_dev->mem_end = wnd->mem_end; + status = mp_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE, + &wnd->multicast_size); + if (status != NDIS_STATUS_SUCCESS || wnd->multicast_size < 0) + wnd->multicast_size = 0; + if (wnd->multicast_size > 0) + net_dev->flags |= IFF_MULTICAST; + else + net_dev->flags &= ~IFF_MULTICAST; +#ifdef CONFIG_NET_POLL_CONTROLLER + net_dev->poll_controller = ndis_poll_controller; +#endif + + buf = kmalloc(buf_len, GFP_KERNEL); + if (!buf) { + WARNING("couldn't allocate memory"); + goto err_start; + } + + set_task_offload(wnd, buf, buf_len); +#ifdef NETIF_F_LLTX + net_dev->features |= NETIF_F_LLTX; +#endif + + if (register_netdev(net_dev)) { + ERROR("cannot register net device %s", net_dev->name); + goto err_register; + } + memcpy(wnd->netdev_name, net_dev->name, sizeof(wnd->netdev_name)); + memset(buf, 0, buf_len); + status = mp_query(wnd, OID_GEN_VENDOR_DESCRIPTION, buf, buf_len); + if (status != NDIS_STATUS_SUCCESS) { + WARNING("couldn't get vendor information: 0x%x", status); + buf[0] = 0; + } + wnd->drv_ndis_version = n = 0; + mp_query_int(wnd, OID_GEN_DRIVER_VERSION, &wnd->drv_ndis_version); + mp_query_int(wnd, OID_GEN_VENDOR_DRIVER_VERSION, &n); + + printk(KERN_INFO "%s: ethernet device " MACSTRSEP " using %sNDIS " + "driver: %s, version: 0x%x, NDIS version: 0x%x, vendor: '%s', " + "%s\n", net_dev->name, MAC2STR(net_dev->dev_addr), + deserialized_driver(wnd) ? "" : "serialized ", + wnd->wd->driver->name, n, wnd->drv_ndis_version, buf, + wnd->wd->conf_file_name); + + if (deserialized_driver(wnd)) { + /* deserialized drivers don't have a limit, but we + * keep max at TX_RING_SIZE */ + wnd->max_tx_packets = TX_RING_SIZE; + } else { + status = mp_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS, + &wnd->max_tx_packets); + if (status != NDIS_STATUS_SUCCESS) + wnd->max_tx_packets = 1; + if (wnd->max_tx_packets > TX_RING_SIZE) + wnd->max_tx_packets = TX_RING_SIZE; + } + TRACE2("maximum send packets: %d", wnd->max_tx_packets); + NdisAllocatePacketPoolEx(&status, &wnd->tx_packet_pool, + wnd->max_tx_packets, 0, + PROTOCOL_RESERVED_SIZE_IN_PACKET); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("couldn't allocate packet pool"); + goto packet_pool_err; + } + NdisAllocateBufferPool(&status, &wnd->tx_buffer_pool, + wnd->max_tx_packets + 4); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("couldn't allocate buffer pool"); + goto buffer_pool_err; + } + TRACE1("pool: %p", wnd->tx_buffer_pool); + + if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &n) == + NDIS_STATUS_SUCCESS && n > ETH_HLEN) + ndis_change_mtu(wnd->net_dev, n - ETH_HLEN); + + if (mp_query_int(wnd, OID_GEN_MAC_OPTIONS, &n) == NDIS_STATUS_SUCCESS) + TRACE2("mac options supported: 0x%x", n); + + tx_header_offset = (typeof(tx_header_offset))buf; + tx_header_offset->protocol_type = NDIS_PROTOCOL_ID_TCP_IP; + tx_header_offset->header_offset = sizeof(ETH_HLEN); + status = mp_set(wnd, OID_GEN_TRANSPORT_HEADER_OFFSET, + tx_header_offset, sizeof(*tx_header_offset)); + TRACE2("%08X", status); + + status = mp_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM, + &wnd->physical_medium); + if (status != NDIS_STATUS_SUCCESS) + wnd->physical_medium = NdisPhysicalMediumUnspecified; + + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF); + get_encryption_capa(wnd, buf, buf_len); + TRACE1("capbilities = %ld", wnd->capa.encr); + printk(KERN_INFO "%s: encryption modes supported: " + "%s%s%s%s%s%s%s\n", net_dev->name, + test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ? + "WEP" : "none", + + test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ? + "; TKIP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : "", + + test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ? + "; AES/CCMP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : ""); + + set_default_iw_params(wnd); + } + kfree(buf); + wrap_procfs_add_ndis_device(wnd); + hangcheck_add(wnd); + add_iw_stats_timer(wnd); + EXIT1(return NDIS_STATUS_SUCCESS); + +buffer_pool_err: + wnd->tx_buffer_pool = NULL; + if (wnd->tx_packet_pool) { + NdisFreePacketPool(wnd->tx_packet_pool); + wnd->tx_packet_pool = NULL; + } +packet_pool_err: +err_register: + kfree(buf); +err_start: + ndis_remove_device(wnd); + EXIT1(return NDIS_STATUS_FAILURE); +} + +static int ndis_remove_device(struct ndis_device *wnd) +{ + s8 tx_pending; + + /* prevent setting essid during disassociation */ + memset(&wnd->essid, 0, sizeof(wnd->essid)); + wnd->tx_ok = 0; + if (wnd->max_tx_packets) + unregister_netdev(wnd->net_dev); + netif_carrier_off(wnd->net_dev); + /* if device is suspended, but resume failed, tx_ring_mutex + * may already be locked */ + if (down_trylock(&wnd->tx_ring_mutex)) + WARNING("couldn't obtain tx_ring_mutex"); + spin_lock_bh(&wnd->tx_ring_lock); + tx_pending = wnd->tx_ring_end - wnd->tx_ring_start; + if (tx_pending < 0) + tx_pending += TX_RING_SIZE; + else if (tx_pending == 0 && wnd->is_tx_ring_full) + tx_pending = TX_RING_SIZE - 1; + wnd->is_tx_ring_full = 0; + /* throw away pending packets */ + while (tx_pending-- > 0) { + struct ndis_packet *packet; + + packet = wnd->tx_ring[wnd->tx_ring_start]; + free_tx_packet(wnd, packet, NDIS_STATUS_CLOSING); + wnd->tx_ring_start = (wnd->tx_ring_start + 1) % TX_RING_SIZE; + } + spin_unlock_bh(&wnd->tx_ring_lock); + up(&wnd->tx_ring_mutex); + wrap_procfs_remove_ndis_device(wnd); + mp_halt(wnd); + ndis_exit_device(wnd); + + if (wnd->tx_packet_pool) { + NdisFreePacketPool(wnd->tx_packet_pool); + wnd->tx_packet_pool = NULL; + } + if (wnd->tx_buffer_pool) { + NdisFreeBufferPool(wnd->tx_buffer_pool); + wnd->tx_buffer_pool = NULL; + } + if (wnd->pmkids) + kfree(wnd->pmkids); + printk(KERN_INFO "%s: device %s removed\n", DRIVER_NAME, + wnd->net_dev->name); + kfree(wnd->nmb); + free_netdev(wnd->net_dev); + EXIT2(return 0); +} + +static wstdcall NTSTATUS NdisAddDevice(struct driver_object *drv_obj, + struct device_object *pdo) +{ + struct device_object *fdo; + struct ndis_mp_block *nmb; + NTSTATUS status; + struct ndis_device *wnd; + struct net_device *net_dev; + struct wrap_device *wd; + unsigned long i; + + ENTER2("%p, %p", drv_obj, pdo); + if (strlen(if_name) >= IFNAMSIZ) { + ERROR("interface name '%s' is too long", if_name); + return STATUS_INVALID_PARAMETER; + } + net_dev = alloc_etherdev(sizeof(*wnd)); + if (!net_dev) { + ERROR("couldn't allocate device"); + return STATUS_RESOURCES; + } + wd = pdo->reserved; + if (wrap_is_pci_bus(wd->dev_bus)) + SET_NETDEV_DEV(net_dev, &wd->pci.pdev->dev); + if (wrap_is_usb_bus(wd->dev_bus)) + SET_NETDEV_DEV(net_dev, &wd->usb.intf->dev); + status = IoCreateDevice(drv_obj, 0, NULL, FILE_DEVICE_UNKNOWN, 0, + FALSE, &fdo); + if (status != STATUS_SUCCESS) { + free_netdev(net_dev); + EXIT2(return status); + } + wnd = netdev_priv(net_dev); + TRACE1("wnd: %p", wnd); + + nmb = kmalloc(sizeof(*nmb), GFP_KERNEL); + if (!nmb) { + WARNING("couldn't allocate memory"); + IoDeleteDevice(fdo); + free_netdev(net_dev); + return STATUS_RESOURCES; + } +#if defined(DEBUG) && DEBUG >= 6 + /* poison nmb so if a driver accesses uninitialized pointers, we + * know what it is */ + for (i = 0; i < sizeof(*nmb) / sizeof(unsigned long); i++) + ((unsigned long *)nmb)[i] = i + 0x8a3fc1; +#endif + + wnd->nmb = nmb; + nmb->wnd = wnd; + nmb->pdo = pdo; + wd->wnd = wnd; + wnd->wd = wd; + wnd->net_dev = net_dev; + fdo->reserved = wnd; + nmb->fdo = fdo; + if (ndis_init_device(wnd)) { + IoDeleteDevice(fdo); + kfree(nmb); + free_netdev(net_dev); + EXIT1(return STATUS_RESOURCES); + } + nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo); + spin_lock_init(&wnd->tx_ring_lock); + init_MUTEX(&wnd->tx_ring_mutex); + init_MUTEX(&wnd->ndis_req_mutex); + wnd->ndis_req_done = 0; + initialize_work(&wnd->tx_work, tx_worker, wnd); + wnd->tx_ring_start = 0; + wnd->tx_ring_end = 0; + wnd->is_tx_ring_full = 0; + wnd->capa.encr = 0; + wnd->capa.auth = 0; + wnd->attributes = 0; + wnd->dma_map_count = 0; + wnd->dma_map_addr = NULL; + wnd->nick[0] = 0; + init_timer(&wnd->hangcheck_timer); + wnd->scan_timestamp = 0; + init_timer(&wnd->iw_stats_timer); + wnd->iw_stats_interval = 10 * HZ; + wnd->ndis_pending_work = 0; + memset(&wnd->essid, 0, sizeof(wnd->essid)); + memset(&wnd->encr_info, 0, sizeof(wnd->encr_info)); + wnd->infrastructure_mode = Ndis802_11Infrastructure; + initialize_work(&wnd->ndis_work, ndis_worker, wnd); + wnd->iw_stats_enabled = TRUE; + + TRACE1("nmb: %p, pdo: %p, fdo: %p, attached: %p, next: %p", + nmb, pdo, fdo, fdo->attached, nmb->next_device); + + /* dispatch routines are called as Windows functions */ + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + drv_obj->major_func[i] = WIN_FUNC_PTR(IoPassIrpDown,2); + + drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(NdisDispatchPnp,2); + drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(NdisDispatchPower,2); + drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] = + WIN_FUNC_PTR(NdisDispatchDeviceControl,2); +// drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] = +// WIN_FUNC_PTR(NdisDispatchDeviceControl,2); + EXIT2(return STATUS_SUCCESS); +} + +int init_ndis_driver(struct driver_object *drv_obj) +{ + ENTER1("%p", drv_obj); + drv_obj->drv_ext->add_device = NdisAddDevice; + return 0; +} + +int wrapndis_init(void) +{ + wrapndis_wq = create_singlethread_workqueue("wrapndis_wq"); + if (!wrapndis_wq) + EXIT1(return -ENOMEM); + wrapndis_worker_thread = wrap_worker_init(wrapndis_wq); + TRACE1("%p", wrapndis_worker_thread); + register_netdevice_notifier(&netdev_notifier); + return 0; +} + +void wrapndis_exit(void) +{ + unregister_netdevice_notifier(&netdev_notifier); + if (wrapndis_wq) + destroy_workqueue(wrapndis_wq); + TRACE1("%p", wrapndis_worker_thread); + if (wrapndis_worker_thread) + ObDereferenceObject(wrapndis_worker_thread); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/ndis.h +++ linux-2.6.27/ubuntu/ndiswrapper/ndis.h @@ -0,0 +1,1309 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _NDIS_H_ +#define _NDIS_H_ + +#include "ntoskernel.h" + +//#define ALLOW_POOL_OVERFLOW 1 + +#define NDIS_DMA_24BITS 0 +#define NDIS_DMA_32BITS 1 +#define NDIS_DMA_64BITS 2 + +#ifdef CONFIG_X86_64 +#define MAXIMUM_PROCESSORS 64 +#else +#define MAXIMUM_PROCESSORS 32 +#endif + +typedef UINT NDIS_STATUS; +typedef UCHAR NDIS_DMA_SIZE; +typedef LONG ndis_rssi; +typedef ULONG ndis_key_index; +typedef ULONG ndis_tx_power_level; +typedef ULONGULONG ndis_key_rsc; +typedef UCHAR ndis_rates[NDIS_MAX_RATES]; +typedef UCHAR ndis_rates_ex[NDIS_MAX_RATES_EX]; +typedef UCHAR mac_address[ETH_ALEN]; +typedef ULONG ndis_fragmentation_threshold; +typedef ULONG ndis_rts_threshold; +typedef ULONG ndis_antenna; +typedef ULONG ndis_oid; + +typedef UCHAR ndis_pmkid_vavlue[16]; + +typedef uint64_t NDIS_PHY_ADDRESS; + +struct ndis_sg_element { + PHYSICAL_ADDRESS address; + ULONG length; + ULONG_PTR reserved; +}; + +struct ndis_sg_list { + ULONG nent; + ULONG_PTR reserved; + struct ndis_sg_element elements[]; +}; + +/* when sending packets, ndiswrapper associates exactly one sg element + * in sg list */ +struct wrap_tx_sg_list { + ULONG nent; + ULONG_PTR reserved; + struct ndis_sg_element elements[1]; +}; + +struct ndis_phy_addr_unit { + NDIS_PHY_ADDRESS phy_addr; + UINT length; +}; + +typedef struct mdl ndis_buffer; + +struct ndis_buffer_pool { + ndis_buffer *free_descr; +// NT_SPIN_LOCK lock; + spinlock_t lock; + UINT max_descr; + UINT num_allocated_descr; +}; + +#define NDIS_PROTOCOL_ID_DEFAULT 0x00 +#define NDIS_PROTOCOL_ID_TCP_IP 0x02 +#define NDIS_PROTOCOL_ID_IPX 0x06 +#define NDIS_PROTOCOL_ID_NBF 0x07 +#define NDIS_PROTOCOL_ID_MAX 0x0F +#define NDIS_PROTOCOL_ID_MASK 0x0F + +#define fPACKET_WRAPPER_RESERVED 0x3F +#define fPACKET_CONTAINS_MEDIA_SPECIFIC_INFO 0x40 +#define fPACKET_ALLOCATED_BY_NDIS 0x80 + +#define PROTOCOL_RESERVED_SIZE_IN_PACKET (4 * sizeof(void *)) + +struct transport_header_offset { + USHORT protocol_type; + USHORT header_offset; +}; + +struct ndis_network_address { + USHORT length; + USHORT type; + UCHAR address[1]; +}; + +struct ndis_network_address_list { + LONG count; + USHORT type; + struct ndis_network_address address[1]; +}; + +struct ndis_tcp_ip_checksum_packet_info { + union { + struct { + ULONG v4:1; + ULONG v6:1; + ULONG tcp:1; + ULONG udp:1; + ULONG ip:1; + } tx; + struct { + ULONG tcp_failed:1; + ULONG udp_failed:1; + ULONG ip_failed:1; + ULONG tcp_succeeded:1; + ULONG udp_succeeded:1; + ULONG ip_succeeded:1; + ULONG loopback:1; + } rx; + ULONG value; + }; +}; + +enum ndis_task { + TcpIpChecksumNdisTask, IpSecNdisTask, TcpLargeSendNdisTask, MaxNdisTask +}; + +enum ndis_encapsulation { + UNSPECIFIED_Encapsulation, NULL_Encapsulation, + IEEE_802_3_Encapsulation, IEEE_802_5_Encapsulation, + LLC_SNAP_ROUTED_Encapsulation, LLC_SNAP_BRIDGED_Encapsulation +}; + +#define NDIS_TASK_OFFLOAD_VERSION 1 + +struct ndis_encapsulation_format { + enum ndis_encapsulation encap; + struct { + ULONG fixed_header_size:1; + ULONG reserved:31; + } flags; + ULONG header_size; +}; + +struct ndis_task_offload_header { + ULONG version; + ULONG size; + ULONG reserved; + ULONG offset_first_task; + struct ndis_encapsulation_format encap_format; +}; + +struct ndis_task_offload { + ULONG version; + ULONG size; + enum ndis_task task; + ULONG offset_next_task; + ULONG task_buf_length; + UCHAR task_buf[1]; +}; + +struct v4_checksum { + union { + struct { + ULONG ip_opts:1; + ULONG tcp_opts:1; + ULONG tcp_csum:1; + ULONG udp_csum:1; + ULONG ip_csum:1; + }; + ULONG value; + }; +}; + +struct v6_checksum { + ULONG ip_supported:1; + ULONG tcp_supported:1; + ULONG tcp_csum:1; + ULONG udp_csum:1; +}; + +struct ndis_task_tcp_ip_checksum { + struct v4_checksum v4_tx; + struct v4_checksum v4_rx; + struct v6_checksum v6_tx; + struct v6_checksum v6_rx; +}; + +struct ndis_task_tcp_large_send { + ULONG version; + ULONG max_size; + ULONG min_seg_count; + BOOLEAN tcp_opts; + BOOLEAN ip_opts; +}; + +struct ndis_packet; + +struct ndis_packet_pool { + struct ndis_packet *free_descr; +// NT_SPIN_LOCK lock; + spinlock_t lock; + UINT max_descr; + UINT num_allocated_descr; + UINT num_used_descr; + UINT proto_rsvd_length; +}; + +struct ndis_packet_stack { + ULONG_PTR IM_reserved[2]; + ULONG_PTR ndis_reserved[4]; +}; + +enum ndis_per_packet_info { + TcpIpChecksumPacketInfo, IpSecPacketInfo, TcpLargeSendPacketInfo, + ClassificationHandlePacketInfo, NdisReserved, + ScatterGatherListPacketInfo, Ieee8021QInfo, OriginalPacketInfo, + PacketCancelId, MaxPerPacketInfo +}; + +struct ndis_packet_extension { + void *info[MaxPerPacketInfo]; +}; + +struct ndis_packet_private { + UINT nr_pages; + UINT len; + ndis_buffer *buffer_head; + ndis_buffer *buffer_tail; + struct ndis_packet_pool *pool; + UINT count; + ULONG flags; + BOOLEAN valid_counts; + UCHAR packet_flags; + USHORT oob_offset; +}; + +struct ndis_packet { + struct ndis_packet_private private; + /* for use by miniport */ + union { + /* for connectionless mininports */ + struct { + UCHAR miniport_reserved[2 * sizeof(void *)]; + UCHAR wrapper_reserved[2 * sizeof(void *)]; + } cl_reserved; + /* for deserialized miniports */ + struct { + UCHAR miniport_reserved_ex[3 * sizeof(void *)]; + UCHAR wrapper_reserved_ex[sizeof(void *)]; + } deserailized_reserved; + struct { + UCHAR mac_reserved[4 * sizeof(void *)]; + } mac_reserved; + }; + ULONG_PTR reserved[2]; + UCHAR protocol_reserved[1]; +}; + +/* OOB data */ +struct ndis_packet_oob_data { + union { + ULONGLONG time_to_tx; + ULONGLONG time_txed; + }; + ULONGLONG time_rxed; + UINT header_size; + UINT media_size; + void *media; + NDIS_STATUS status; + + /* ndiswrapper specific info; extension should be right after + * ndis's oob_data */ + struct ndis_packet_extension ext; + union { + /* used for tx only */ + struct { + struct sk_buff *tx_skb; + union { + struct wrap_tx_sg_list wrap_tx_sg_list; + struct ndis_sg_list *tx_sg_list; + }; + }; + /* used for rx only */ + struct { + unsigned char header[ETH_HLEN]; + unsigned char *look_ahead; + UINT look_ahead_size; + }; + }; +}; + +#define NDIS_PACKET_OOB_DATA(packet) \ + (struct ndis_packet_oob_data *)(((void *)(packet)) + \ + (packet)->private.oob_offset) + +enum ndis_device_pnp_event { + NdisDevicePnPEventQueryRemoved, NdisDevicePnPEventRemoved, + NdisDevicePnPEventSurpriseRemoved, NdisDevicePnPEventQueryStopped, + NdisDevicePnPEventStopped, NdisDevicePnPEventPowerProfileChanged, + NdisDevicePnPEventMaximum +}; + +enum ndis_request_type { + NdisRequestQueryInformation, NdisRequestSetInformation, + NdisRequestQueryStatistics, NdisRequestOpen, NdisRequestClose, + NdisRequestSend, NdisRequestTransferData, NdisRequestReset, + NdisRequestGeneric1, NdisRequestGeneric2, NdisRequestGeneric3, + NdisRequestGeneric4 +}; + +struct ndis_request { + mac_address mac; + enum ndis_request_type request_type; + union data { + struct query_info { + UINT oid; + void *buf; + UINT buf_len; + UINT written; + UINT needed; + } query_info; + struct set_info { + UINT oid; + void *buf; + UINT buf_len; + UINT written; + UINT needed; + } set_info; + } data; +}; + +enum ndis_medium { + NdisMedium802_3, NdisMedium802_5, NdisMediumFddi, NdisMediumWan, + NdisMediumLocalTalk, NdisMediumDix, NdisMediumArcnetRaw, + NdisMediumArcnet878_2, NdisMediumAtm, NdisMediumWirelessWan, + NdisMediumIrda, NdisMediumBpc, NdisMediumCoWan, + NdisMedium1394, NdisMediumMax +}; + +enum ndis_physical_medium { + NdisPhysicalMediumUnspecified, NdisPhysicalMediumWirelessLan, + NdisPhysicalMediumCableModem, NdisPhysicalMediumPhoneLine, + NdisPhysicalMediumPowerLine, NdisPhysicalMediumDSL, + NdisPhysicalMediumFibreChannel, NdisPhysicalMedium1394, + NdisPhysicalMediumWirelessWan, NdisPhysicalMediumMax +}; + +enum ndis_power_state { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, NdisDeviceStateD1, NdisDeviceStateD2, + NdisDeviceStateD3, NdisDeviceStateMaximum +}; + +enum ndis_power_profile { + NdisPowerProfileBattery, NdisPowerProfileAcOnLine +}; + +struct ndis_pm_wakeup_capabilities { + enum ndis_power_state min_magic_packet_wakeup; + enum ndis_power_state min_pattern_wakeup; + enum ndis_power_state min_link_change_wakeup; +}; + +#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001 +#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002 +#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004 + +enum net_pnp_event_code { + NetEventSetPower, NetEventQueryPower, NetEventQueryRemoveDevice, + NetEventCancelRemoveDevice, NetEventReconfigure, NetEventBindList, + NetEventBindsComplete, NetEventPnPCapabilities, NetEventMaximum +}; + +struct net_pnp_event { + enum net_pnp_event_code code; + void *buf; + ULONG buf_length; + ULONG_PTR ndis_reserved[4]; + ULONG_PTR transport_reserved[4]; + ULONG_PTR tdi_reserved[4]; + ULONG_PTR tdi_client_reserved[4]; +}; + +struct ndis_pnp_capabilities { + ULONG flags; + struct ndis_pm_wakeup_capabilities wakeup; +}; + +typedef void (*ndis_isr_handler)(BOOLEAN *recognized, BOOLEAN *queue_handler, + void *handle) wstdcall; +typedef void (*ndis_interrupt_handler)(void *ctx) wstdcall; + +struct miniport { + /* NDIS 3.0 */ + UCHAR major_version; + UCHAR minor_version; + USHORT filler; + UINT reserved; + BOOLEAN (*hangcheck)(void *ctx) wstdcall; + void (*disable_interrupt)(void *ctx) wstdcall; + void (*enable_interrupt)(void *ctx) wstdcall; + void (*mp_halt)(void *ctx) wstdcall; + ndis_interrupt_handler handle_interrupt; + NDIS_STATUS (*init)(NDIS_STATUS *error_status, UINT *medium_index, + enum ndis_medium medium[], UINT medium_array_size, + void *handle, void *conf_handle) wstdcall; + ndis_isr_handler isr; + NDIS_STATUS (*queryinfo)(void *ctx, ndis_oid oid, void *buffer, + ULONG buflen, ULONG *written, + ULONG *needed) wstdcall; + void *reconfig; + NDIS_STATUS (*reset)(BOOLEAN *reset_address, void *ctx) wstdcall; + NDIS_STATUS (*send)(void *ctx, struct ndis_packet *packet, + UINT flags) wstdcall; + NDIS_STATUS (*setinfo)(void *ctx, ndis_oid oid, void *buffer, + ULONG buflen, ULONG *written, + ULONG *needed) wstdcall; + NDIS_STATUS (*tx_data)(struct ndis_packet *ndis_packet, + UINT *bytes_txed, void *mp_ctx, void *rx_ctx, + UINT offset, UINT bytes_to_tx) wstdcall; + /* NDIS 4.0 extensions */ + void (*return_packet)(void *ctx, void *packet) wstdcall; + void (*send_packets)(void *ctx, struct ndis_packet **packets, + INT nr_of_packets) wstdcall; + void (*alloc_complete)(void *handle, void *virt, + NDIS_PHY_ADDRESS *phys, + ULONG size, void *ctx) wstdcall; + /* NDIS 5.0 extensions */ + NDIS_STATUS (*co_create_vc)(void *ctx, void *vc_handle, + void *vc_ctx) wstdcall; + NDIS_STATUS (*co_delete_vc)(void *vc_ctx) wstdcall; + NDIS_STATUS (*co_activate_vc)(void *vc_ctx, void *call_params) wstdcall; + NDIS_STATUS (*co_deactivate_vc)(void *vc_ctx) wstdcall; + NDIS_STATUS (*co_send_packets)(void *vc_ctx, void **packets, + UINT nr_of_packets) wstdcall; + NDIS_STATUS (*co_request)(void *ctx, void *vc_ctx, UINT *req) wstdcall; + /* NDIS 5.1 extensions */ + void (*cancel_send_packets)(void *ctx, void *id) wstdcall; + void (*pnp_event_notify)(void *ctx, enum ndis_device_pnp_event event, + void *inf_buf, ULONG inf_buf_len) wstdcall; + void (*shutdown)(void *ctx) wstdcall; + void *reserved1; + void *reserved2; + void *reserved3; + void *reserved4; +}; + +struct ndis_spinlock { + NT_SPIN_LOCK klock; + KIRQL irql; +}; + +union ndis_rw_lock_refcount { + UCHAR cache_line[16]; +}; + +struct ndis_rw_lock { + union { + struct { + NT_SPIN_LOCK klock; + void *context; + }; + UCHAR reserved[16]; + }; + union { + union ndis_rw_lock_refcount ref_count[MAXIMUM_PROCESSORS]; + /* ndiswrapper specific */ + volatile int count; + }; +}; + +struct lock_state { + USHORT state; + KIRQL irql; +}; + +struct ndis_work_item; +typedef void (*NDIS_PROC)(struct ndis_work_item *, void *) wstdcall; + +struct ndis_work_item { + void *ctx; + NDIS_PROC func; + union { + UCHAR reserved[8 * sizeof(void *)]; + /* ndiswrapper specific */ + struct nt_list list; + }; +}; + +struct alloc_shared_mem { + void *ctx; + ULONG size; + BOOLEAN cached; +}; + +struct ndis_mp_block; + +/* this is opaque to drivers, so we can use it as we please */ +struct ndis_mp_interrupt { + struct kinterrupt *kinterrupt; + NT_SPIN_LOCK lock; + union { + void *reserved; + unsigned int irq; + }; + ndis_isr_handler isr; + ndis_interrupt_handler mp_dpc; + struct kdpc intr_dpc; + struct ndis_mp_block *nmb; + UCHAR dpc_count; + BOOLEAN enable; + struct nt_event dpc_completed_event; + BOOLEAN shared; + BOOLEAN req_isr; +}; + +struct ndis_binary_data { + USHORT len; + void *buf; +}; + +enum ndis_parameter_type { + NdisParameterInteger, NdisParameterHexInteger, + NdisParameterString, NdisParameterMultiString, NdisParameterBinary, +}; + +typedef struct unicode_string NDIS_STRING; + +struct ndis_configuration_parameter { + enum ndis_parameter_type type; + union { + ULONG integer; + NDIS_STRING string; + } data; +}; + +struct ndis_driver { + struct miniport mp; +}; + +/* IDs used to store extensions in driver_object's custom extension */ +#define NDIS_DRIVER_CLIENT_ID 10 + +struct ndis_wireless_stats { + ULONG length; + LARGE_INTEGER tx_frag; + LARGE_INTEGER tx_multi_frag; + LARGE_INTEGER failed; + LARGE_INTEGER retry; + LARGE_INTEGER multi_retry; + LARGE_INTEGER rtss_succ; + LARGE_INTEGER rtss_fail; + LARGE_INTEGER ack_fail; + LARGE_INTEGER frame_dup; + LARGE_INTEGER rx_frag; + LARGE_INTEGER rx_multi_frag; + LARGE_INTEGER fcs_err; + LARGE_INTEGER tkip_local_mic_failures; + LARGE_INTEGER tkip_icv_errors; + LARGE_INTEGER tkip_counter_measures_invoked; + LARGE_INTEGER tkip_replays; + LARGE_INTEGER ccmp_format_errors; + LARGE_INTEGER ccmp_replays; + LARGE_INTEGER ccmp_decrypt_errors; + LARGE_INTEGER fourway_handshake_failures; + LARGE_INTEGER wep_undecryptable_count; + LARGE_INTEGER wep_icv_errorcount; + LARGE_INTEGER decrypt_success_count; + LARGE_INTEGER decrypt_failure_count; +}; + +enum ndis_status_type { + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusType_RadioState, +}; + +struct ndis_status_indication { + enum ndis_status_type status_type; +}; + +enum ndis_radio_status { + Ndis802_11RadioStatusOn, Ndis802_11RadioStatusHardwareOff, + Ndis802_11RadioStatusSoftwareOff, +}; + +struct ndis_radio_status_indication +{ + enum ndis_status_type status_type; + enum ndis_radio_status radio_state; +}; + +enum ndis_media_stream_mode { + Ndis802_11MediaStreamOff, Ndis802_11MediaStreamOn +}; + +enum wrapper_work { + LINK_STATUS_OFF, LINK_STATUS_ON, SET_MULTICAST_LIST, COLLECT_IW_STATS, + HANGCHECK, NETIF_WAKEQ, +}; + +struct encr_info { + struct encr_key { + ULONG length; + UCHAR key[NDIS_ENCODING_TOKEN_MAX]; + } keys[MAX_ENCR_KEYS]; + unsigned short tx_key_index; +}; + +struct ndis_essid { + ULONG length; + UCHAR essid[NDIS_ESSID_MAX_SIZE]; +}; + +enum ndis_infrastructure_mode { + Ndis802_11IBSS, Ndis802_11Infrastructure, Ndis802_11AutoUnknown, + Ndis802_11InfrastructureMax +}; + +enum authentication_mode { + Ndis802_11AuthModeOpen, Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeMax +}; + +enum encryption_status { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, Ndis802_11Encryption3KeyAbsent +}; + +struct ndis_auth_encr_pair { + enum authentication_mode auth_mode; + enum encryption_status encr_mode; +}; + +struct ndis_capability { + ULONG length; + ULONG version; + ULONG num_PMKIDs; + ULONG num_auth_encr_pair; + struct ndis_auth_encr_pair auth_encr_pair[1]; +}; + +struct ndis_guid { + struct guid guid; + union { + ndis_oid oid; + NDIS_STATUS status; + }; + ULONG size; + ULONG flags; +}; + +struct ndis_timer { + struct nt_timer nt_timer; + struct kdpc kdpc; +}; + +struct ndis_mp_timer { + struct nt_timer nt_timer; + struct kdpc kdpc; + DPC func; + void *ctx; + struct ndis_mp_block *nmb; + struct ndis_mp_timer *next; +}; + +typedef struct cm_partial_resource_list NDIS_RESOURCE_LIST; + +struct ndis_event { + struct nt_event nt_event; +}; + +struct ndis_bind_paths { + UINT number; + struct unicode_string paths[1]; +}; + +struct ndis_reference { + NT_SPIN_LOCK lock; + USHORT ref_count; + BOOLEAN closing; +}; + +struct ndis_filterdbs { + union { + void *eth_db; + void *null_db; + }; + void *tr_db; + void *fddi_db; + void *arc_db; +}; + +enum ndis_interface_type { + NdisInterfaceInternal, NdisInterfaceIsa, NdisInterfaceEisa, + NdisInterfaceMca, NdisInterfaceTurboChannel, NdisInterfacePci, + NdisInterfacePcMcia, +}; + +struct auth_encr_capa { + unsigned long auth; + unsigned long encr; +}; + +struct ndis_pmkid_candidate { + mac_address bssid; + DWORD flags; +}; + +struct ndis_pmkid_candidate_list { + ULONG version; + ULONG num_candidates; + struct ndis_pmkid_candidate candidates[1]; +}; + +/* + * This struct contains function pointers that the drivers references + * directly via macros, so it's important that they are at the correct + * position. + */ +struct ndis_mp_block { + void *signature; + struct ndis_mp_block *next; + struct driver_object *drv_obj; + void *mp_ctx; + struct unicode_string name; + struct ndis_bind_paths *bindpaths; + void *openqueue; + struct ndis_reference reference; + void *device_ctx; + UCHAR padding; + UCHAR lock_acquired; + UCHAR pmode_opens; + UCHAR assigned_cpu; + NT_SPIN_LOCK lock; + enum ndis_request_type *mediarequest; + struct ndis_mp_interrupt *interrupt; + ULONG flags; + ULONG pnp_flags; + struct nt_list packet_list; + struct ndis_packet *first_pending_tx_packet; + struct ndis_packet *return_packet_queue; + ULONG request_buffer; + void *set_mcast_buffer; + struct ndis_mp_block *primary_mp; + void *wrapper_ctx; + void *bus_data_ctx; + ULONG pnp_capa; + void *resources; + struct ndis_timer wakeup_dpc_timer; + struct unicode_string basename; + struct unicode_string symlink_name; + ULONG ndis_hangcheck_interval; + USHORT hanghcheck_ticks; + USHORT hangcheck_tick; + NDIS_STATUS ndis_reset_status; + void *resetopen; + struct ndis_filterdbs filterdbs; + void *rx_packet; + void *send_complete; + void *send_resource_avail; + void *reset_complete; + + enum ndis_medium media_type; + ULONG bus_number; + enum ndis_interface_type bus_type; + enum ndis_interface_type adapter_type; + struct device_object *fdo; + struct device_object *pdo; + struct device_object *next_device; + void *mapreg; + void *call_mgraflist; + void *mp_thread; + void *setinfobuf; + USHORT setinfo_buf_len; + USHORT max_send_pkts; + NDIS_STATUS fake_status; + void *lock_handler; + struct unicode_string *adapter_instance_name; + void *timer_queue; + UINT mac_options; + void *pending_req; + UINT max_long_addrs; + UINT max_short_addrs; + UINT cur_lookahead; + UINT max_lookahead; + + ndis_interrupt_handler irq_bh; + void *disable_intr; + void *enable_intr; + void *send_pkts; + void *deferred_send; + void *eth_rx_indicate; + void *tr_rx_indicate; + void *fddi_rx_indicate; + void *eth_rx_complete; + void *tr_rx_complete; + void *fddi_rx_complete; + + void *status; + void *status_complete; + void *td_complete; + + void *queryinfo_complete; + void *setinfo_complete; + void *wan_tx_complete; + void *wan_rx; + void *wan_rx_complete; + /* ndiswrapper specific */ + struct ndis_device *wnd; +}; + +struct ndis_device { + struct ndis_mp_block *nmb; + struct wrap_device *wd; + struct net_device *net_dev; + void *shutdown_ctx; + struct ndis_mp_interrupt *mp_interrupt; + struct kdpc irq_kdpc; + unsigned long mem_start; + unsigned long mem_end; + + struct net_device_stats net_stats; + struct iw_statistics iw_stats; + BOOLEAN iw_stats_enabled; + struct ndis_wireless_stats ndis_stats; + + work_struct_t tx_work; + struct ndis_packet *tx_ring[TX_RING_SIZE]; + u8 tx_ring_start; + u8 tx_ring_end; + u8 is_tx_ring_full; + u8 tx_ok; + spinlock_t tx_ring_lock; + struct semaphore tx_ring_mutex; + unsigned int max_tx_packets; + struct semaphore ndis_req_mutex; + struct task_struct *ndis_req_task; + int ndis_req_done; + NDIS_STATUS ndis_req_status; + ULONG packet_filter; + + ULONG sg_dma_size; + ULONG dma_map_count; + dma_addr_t *dma_map_addr; + + int hangcheck_interval; + struct timer_list hangcheck_timer; + int iw_stats_interval; + struct timer_list iw_stats_timer; + unsigned long scan_timestamp; + struct encr_info encr_info; + char nick[IW_ESSID_MAX_SIZE + 1]; + struct ndis_essid essid; + struct auth_encr_capa capa; + enum ndis_infrastructure_mode infrastructure_mode; + int max_pmkids; + int num_pmkids; + struct ndis_pmkid *pmkids; + mac_address mac; + struct proc_dir_entry *procfs_iface; + + work_struct_t ndis_work; + unsigned long ndis_pending_work; + UINT attributes; + int iw_auth_wpa_version; + int iw_auth_cipher_pairwise; + int iw_auth_cipher_group; + int iw_auth_key_mgmt; + int iw_auth_80211_alg; + struct ndis_packet_pool *tx_packet_pool; + struct ndis_buffer_pool *tx_buffer_pool; + int multicast_size; + struct v4_checksum rx_csum; + struct v4_checksum tx_csum; + enum ndis_physical_medium physical_medium; + ULONG ndis_wolopts; + struct nt_slist wrap_timer_slist; + int drv_ndis_version; + struct ndis_pnp_capabilities pnp_capa; + char netdev_name[IFNAMSIZ]; +}; + +BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx) wstdcall; + +int ndis_init(void); +void ndis_exit(void); +int ndis_init_device(struct ndis_device *wnd); +void ndis_exit_device(struct ndis_device *wnd); + +int wrap_procfs_add_ndis_device(struct ndis_device *wnd); +void wrap_procfs_remove_ndis_device(struct ndis_device *wnd); + +void NdisAllocatePacketPoolEx(NDIS_STATUS *status, + struct ndis_packet_pool **pool_handle, + UINT num_descr, UINT overflowsize, + UINT proto_rsvd_length) wstdcall; +void NdisFreePacketPool(struct ndis_packet_pool *pool) wstdcall; +void NdisAllocatePacket(NDIS_STATUS *status, struct ndis_packet **packet, + struct ndis_packet_pool *pool) wstdcall; +void NdisFreePacket(struct ndis_packet *descr) wstdcall; +void NdisAllocateBufferPool(NDIS_STATUS *status, + struct ndis_buffer_pool **pool_handle, + UINT num_descr) wstdcall; +void NdisFreeBufferPool(struct ndis_buffer_pool *pool) wstdcall; +void NdisAllocateBuffer(NDIS_STATUS *status, ndis_buffer **buffer, + struct ndis_buffer_pool *pool, void *virt, + UINT length) wstdcall; +void NdisFreeBuffer(ndis_buffer *descr) wstdcall; +void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb, + struct ndis_packet **packets, + UINT nr_packets) wstdcall; +void NdisMSendComplete(struct ndis_mp_block *nmb, struct ndis_packet *packet, + NDIS_STATUS status) wstdcall; +void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb) wstdcall; +void NdisMIndicateStatus(struct ndis_mp_block *nmb, + NDIS_STATUS status, void *buf, UINT len) wstdcall; +void NdisMIndicateStatusComplete(struct ndis_mp_block *nmb) wstdcall; +void NdisMQueryInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) wstdcall; +void NdisMSetInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) wstdcall; +void NdisMResetComplete(struct ndis_mp_block *nmb, NDIS_STATUS status, + BOOLEAN address_reset) wstdcall; +ULONG NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *buffer) wstdcall; +BOOLEAN NdisWaitEvent(struct ndis_event *event, UINT timeout) wstdcall; +void NdisSetEvent(struct ndis_event *event) wstdcall; +void NdisMDeregisterInterrupt(struct ndis_mp_interrupt *mp_interrupt) wstdcall; +void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx, + char *header1, char *header, UINT header_size, + void *look_ahead, UINT look_ahead_size, + UINT packet_size) wstdcall; +void EthRxComplete(struct ndis_mp_block *nmb) wstdcall; +void NdisMTransferDataComplete(struct ndis_mp_block *nmb, + struct ndis_packet *packet, NDIS_STATUS status, + UINT bytes_txed) wstdcall; +void NdisWriteConfiguration(NDIS_STATUS *status, struct ndis_mp_block *nmb, + struct unicode_string *key, + struct ndis_configuration_parameter *param) wstdcall; +void NdisReadConfiguration(NDIS_STATUS *status, + struct ndis_configuration_parameter **param, + struct ndis_mp_block *nmb, + struct unicode_string *key, + enum ndis_parameter_type type) wstdcall; + +/* Required OIDs */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 /* Set only */ +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 /* Set only */ +#define OID_GEN_MACHINE_NAME 0x0001021A +#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B /* Set only */ +#define OID_GEN_VLAN_ID 0x0001021C + +/* Optional OIDs. */ +#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Required statistics OIDs. */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional OID statistics */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +#define OID_GEN_NETCARD_LOAD 0x00020211 +#define OID_GEN_DEVICE_PROFILE 0x00020212 + +/* 802.3 (ethernet) OIDs */ +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* PnP and power management OIDs */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_WAKE_UP_PATTERN_LIST 0xFD010105 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + +/* PnP/PM Statistics (Optional). */ +#define OID_PNP_WAKE_UP_OK 0xFD020200 +#define OID_PNP_WAKE_UP_ERROR 0xFD020201 + +/* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */ +#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001 +#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002 +#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004 + +/* 802.11 OIDs */ +#define OID_802_11_BSSID 0x0D010101 +#define OID_802_11_SSID 0x0D010102 +#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0D010203 +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 +#define OID_802_11_TX_POWER_LEVEL 0x0D010205 +#define OID_802_11_RSSI 0x0D010206 +#define OID_802_11_RSSI_TRIGGER 0x0D010207 +#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 +#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0D010209 +#define OID_802_11_RTS_THRESHOLD 0x0D01020A +#define OID_802_11_NUMBER_OF_ANTENNAS 0x0D01020B +#define OID_802_11_RX_ANTENNA_SELECTED 0x0D01020C +#define OID_802_11_TX_ANTENNA_SELECTED 0x0D01020D +#define OID_802_11_SUPPORTED_RATES 0x0D01020E +#define OID_802_11_DESIRED_RATES 0x0D010210 +#define OID_802_11_CONFIGURATION 0x0D010211 +#define OID_802_11_STATISTICS 0x0D020212 +#define OID_802_11_ADD_WEP 0x0D010113 +#define OID_802_11_REMOVE_WEP 0x0D010114 +#define OID_802_11_DISASSOCIATE 0x0D010115 +#define OID_802_11_POWER_MODE 0x0D010216 +#define OID_802_11_BSSID_LIST 0x0D010217 +#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 +#define OID_802_11_PRIVACY_FILTER 0x0D010119 +#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A +#define OID_802_11_WEP_STATUS 0x0D01011B +#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS +#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C +#define OID_802_11_ADD_KEY 0x0D01011D +#define OID_802_11_REMOVE_KEY 0x0D01011E +#define OID_802_11_ASSOCIATION_INFORMATION 0x0D01011F +#define OID_802_11_TEST 0x0D010120 +#define OID_802_11_MEDIA_STREAM_MODE 0x0D010121 +#define OID_802_11_CAPABILITY 0x0D010122 +#define OID_802_11_PMKID 0x0D010123 + +#define NDIS_STATUS_SUCCESS 0 +#define NDIS_STATUS_PENDING 0x00000103 +#define NDIS_STATUS_NOT_RECOGNIZED 0x00010001 +#define NDIS_STATUS_NOT_COPIED 0x00010002 +#define NDIS_STATUS_NOT_ACCEPTED 0x00010003 +#define NDIS_STATUS_CALL_ACTIVE 0x00010007 +#define NDIS_STATUS_ONLINE 0x40010003 +#define NDIS_STATUS_RESET_START 0x40010004 +#define NDIS_STATUS_RESET_END 0x40010005 +#define NDIS_STATUS_RING_STATUS 0x40010006 +#define NDIS_STATUS_CLOSED 0x40010007 +#define NDIS_STATUS_WAN_LINE_UP 0x40010008 +#define NDIS_STATUS_WAN_LINE_DOWN 0x40010009 +#define NDIS_STATUS_WAN_FRAGMENT 0x4001000A +#define NDIS_STATUS_MEDIA_CONNECT 0x4001000B +#define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C +#define NDIS_STATUS_HARDWARE_LINE_UP 0x4001000D +#define NDIS_STATUS_HARDWARE_LINE_DOWN 0x4001000E +#define NDIS_STATUS_INTERFACE_UP 0x4001000F +#define NDIS_STATUS_INTERFACE_DOWN 0x40010010 +#define NDIS_STATUS_MEDIA_BUSY 0x40010011 +#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012 +#define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION +#define NDIS_STATUS_LINK_SPEED_CHANGE 0x40010013 +#define NDIS_STATUS_WAN_GET_STATS 0x40010014 +#define NDIS_STATUS_WAN_CO_FRAGMENT 0x40010015 +#define NDIS_STATUS_WAN_CO_LINKPARAMS 0x40010016 +#define NDIS_STATUS_NOT_RESETTABLE 0x80010001 +#define NDIS_STATUS_SOFT_ERRORS 0x80010003 +#define NDIS_STATUS_HARD_ERRORS 0x80010004 +#define NDIS_STATUS_BUFFER_OVERFLOW 0x80000005 +#define NDIS_STATUS_FAILURE 0xC0000001 +#define NDIS_STATUS_INVALID_PARAMETER 0xC000000D +#define NDIS_STATUS_RESOURCES 0xC000009A +#define NDIS_STATUS_CLOSING 0xC0010002 +#define NDIS_STATUS_BAD_VERSION 0xC0010004 +#define NDIS_STATUS_BAD_CHARACTERISTICS 0xC0010005 +#define NDIS_STATUS_ADAPTER_NOT_FOUND 0xC0010006 +#define NDIS_STATUS_OPEN_FAILED 0xC0010007 +#define NDIS_STATUS_DEVICE_FAILED 0xC0010008 +#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 +#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A +#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B +#define NDIS_STATUS_REQUEST_ABORTED 0xC001000C +#define NDIS_STATUS_RESET_IN_PROGRESS 0xC001000D +#define NDIS_STATUS_CLOSING_INDICATING 0xC001000E +#define NDIS_STATUS_BAD_VERSION 0xC0010004 +#define NDIS_STATUS_NOT_SUPPORTED 0xC00000BB +#define NDIS_STATUS_INVALID_PACKET 0xC001000F +#define NDIS_STATUS_OPEN_LIST_FULL 0xC0010010 +#define NDIS_STATUS_ADAPTER_NOT_READY 0xC0010011 +#define NDIS_STATUS_ADAPTER_NOT_OPEN 0xC0010012 +#define NDIS_STATUS_NOT_INDICATING 0xC0010013 +#define NDIS_STATUS_INVALID_LENGTH 0xC0010014 +#define NDIS_STATUS_INVALID_DATA 0xC0010015 +#define NDIS_STATUS_BUFFER_TOO_SHORT 0xC0010016 +#define NDIS_STATUS_INVALID_OID 0xC0010017 +#define NDIS_STATUS_ADAPTER_REMOVED 0xC0010018 +#define NDIS_STATUS_UNSUPPORTED_MEDIA 0xC0010019 +#define NDIS_STATUS_GROUP_ADDRESS_IN_USE 0xC001001A +#define NDIS_STATUS_FILE_NOT_FOUND 0xC001001B +#define NDIS_STATUS_ERROR_READING_FILE 0xC001001C +#define NDIS_STATUS_ALREADY_MAPPED 0xC001001D +#define NDIS_STATUS_RESOURCE_CONFLICT 0xC001001E +#define NDIS_STATUS_NO_CABLE 0xC001001F +#define NDIS_STATUS_INVALID_SAP 0xC0010020 +#define NDIS_STATUS_SAP_IN_USE 0xC0010021 +#define NDIS_STATUS_INVALID_ADDRESS 0xC0010022 +#define NDIS_STATUS_VC_NOT_ACTIVATED 0xC0010023 +#define NDIS_STATUS_DEST_OUT_OF_ORDER 0xC0010024 +#define NDIS_STATUS_VC_NOT_AVAILABLE 0xC0010025 +#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE 0xC0010026 +#define NDIS_STATUS_INCOMPATABLE_QOS 0xC0010027 +#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED 0xC0010028 +#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION 0xC0010029 +#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR 0xC0011000 +#define NDIS_STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define NDIS_STATUS_NETWORK_UNREACHABLE 0xC000023C + +/* Event codes */ + +#define EVENT_NDIS_RESOURCE_CONFLICT 0xC0001388 +#define EVENT_NDIS_OUT_OF_RESOURCE 0xC0001389 +#define EVENT_NDIS_HARDWARE_FAILURE 0xC000138A +#define EVENT_NDIS_ADAPTER_NOT_FOUND 0xC000138B +#define EVENT_NDIS_INTERRUPT_CONNECT 0xC000138C +#define EVENT_NDIS_DRIVER_FAILURE 0xC000138D +#define EVENT_NDIS_BAD_VERSION 0xC000138E +#define EVENT_NDIS_TIMEOUT 0x8000138F +#define EVENT_NDIS_NETWORK_ADDRESS 0xC0001390 +#define EVENT_NDIS_UNSUPPORTED_CONFIGURATION 0xC0001391 +#define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER 0xC0001392 +#define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER 0xC0001393 +#define EVENT_NDIS_BAD_IO_BASE_ADDRESS 0xC0001394 +#define EVENT_NDIS_RECEIVE_SPACE_SMALL 0x40001395 +#define EVENT_NDIS_ADAPTER_DISABLED 0x80001396 +#define EVENT_NDIS_IO_PORT_CONFLICT 0x80001397 +#define EVENT_NDIS_PORT_OR_DMA_CONFLICT 0x80001398 +#define EVENT_NDIS_MEMORY_CONFLICT 0x80001399 +#define EVENT_NDIS_INTERRUPT_CONFLICT 0x8000139A +#define EVENT_NDIS_DMA_CONFLICT 0x8000139B +#define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR 0xC000139C +#define EVENT_NDIS_MAXRECEIVES_ERROR 0x8000139D +#define EVENT_NDIS_MAXTRANSMITS_ERROR 0x8000139E +#define EVENT_NDIS_MAXFRAMESIZE_ERROR 0x8000139F +#define EVENT_NDIS_MAXINTERNALBUFS_ERROR 0x800013A0 +#define EVENT_NDIS_MAXMULTICAST_ERROR 0x800013A1 +#define EVENT_NDIS_PRODUCTID_ERROR 0x800013A2 +#define EVENT_NDIS_LOBE_FAILUE_ERROR 0x800013A3 +#define EVENT_NDIS_SIGNAL_LOSS_ERROR 0x800013A4 +#define EVENT_NDIS_REMOVE_RECEIVED_ERROR 0x800013A5 +#define EVENT_NDIS_TOKEN_RING_CORRECTION 0x400013A6 +#define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7 +#define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8 +#define EVENT_NDIS_CABLE_DISCONNECTED_ERROR 0x800013A9 +#define EVENT_NDIS_RESET_FAILURE_CORRECTION 0x800013AA + +/* packet filter bits used by NDIS_OID_PACKET_FILTER */ +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00001000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000 + +/* memory allocation flags */ +#define NDIS_MEMORY_CONTIGUOUS 0x00000001 +#define NDIS_MEMORY_NONCACHED 0x00000002 + +/* Atrribute flags to NdisMSetAtrributesEx */ +#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT 0x00000001 +#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002 +#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004 +#define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008 +#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER 0x00000010 +#define NDIS_ATTRIBUTE_DESERIALIZE 0x00000020 +#define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND 0x00000040 +#define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK 0x00000080 +#define NDIS_ATTRIBUTE_NOT_CO_NDIS 0x00000100 +#define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS 0x00000200 + +#define OID_TCP_TASK_OFFLOAD 0xFC010201 + +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00000080 +#define NDIS_MAC_OPTION_RECEIVE_AT_DPC 0x00000100 +#define NDIS_MAC_OPTION_8021Q_VLAN 0x00000200 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +#define deserialized_driver(wnd) (wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE) + +static inline void serialize_lock(struct ndis_device *wnd) +{ + nt_spin_lock(&wnd->nmb->lock); +} + +static inline void serialize_unlock(struct ndis_device *wnd) +{ + nt_spin_unlock(&wnd->nmb->lock); +} + +static inline KIRQL serialize_lock_irql(struct ndis_device *wnd) +{ + if (deserialized_driver(wnd)) + return raise_irql(DISPATCH_LEVEL); + else + return nt_spin_lock_irql(&wnd->nmb->lock, DISPATCH_LEVEL); +} + +static inline void serialize_unlock_irql(struct ndis_device *wnd, + KIRQL irql) +{ + if (deserialized_driver(wnd)) + lower_irql(irql); + else + nt_spin_unlock_irql(&wnd->nmb->lock, irql); +} + +static inline void if_serialize_lock(struct ndis_device *wnd) +{ + if (!deserialized_driver(wnd)) + nt_spin_lock(&wnd->nmb->lock); +} + +static inline void if_serialize_unlock(struct ndis_device *wnd) +{ + if (!deserialized_driver(wnd)) + nt_spin_unlock(&wnd->nmb->lock); +} + +#endif /* NDIS_H */ --- linux-2.6.27.orig/ubuntu/ndiswrapper/ntoskernel.h +++ linux-2.6.27/ubuntu/ndiswrapper/ntoskernel.h @@ -0,0 +1,1165 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _NTOSKERNEL_H_ +#define _NTOSKERNEL_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_X86) && !defined(CONFIG_X86_64) +#error "this module is for x86 or x86_64 architectures only" +#endif + +/* Interrupt backwards compatibility stuff */ +#include +#ifndef IRQ_HANDLED +#define IRQ_HANDLED +#define IRQ_NONE +#define irqreturn_t void +#endif + +/* pci functions in 2.6 kernels have problems allocating dma buffers, + * but seem to work fine with dma functions + */ +#include + +#define PCI_DMA_ALLOC_COHERENT(pci_dev,size,dma_handle) \ + dma_alloc_coherent(&pci_dev->dev,size,dma_handle, \ + GFP_KERNEL | __GFP_REPEAT) +#define PCI_DMA_FREE_COHERENT(pci_dev,size,cpu_addr,dma_handle) \ + dma_free_coherent(&pci_dev->dev,size,cpu_addr,dma_handle) +#define PCI_DMA_MAP_SINGLE(pci_dev,addr,size,direction) \ + dma_map_single(&pci_dev->dev,addr,size,direction) +#define PCI_DMA_UNMAP_SINGLE(pci_dev,dma_handle,size,direction) \ + dma_unmap_single(&pci_dev->dev,dma_handle,size,direction) +#define MAP_SG(pci_dev, sglist, nents, direction) \ + dma_map_sg(&pci_dev->dev, sglist, nents, direction) +#define UNMAP_SG(pci_dev, sglist, nents, direction) \ + dma_unmap_sg(&pci_dev->dev, sglist, nents, direction) +#define PCI_DMA_MAP_ERROR(dma_addr) dma_mapping_error(dma_addr) + + +#if defined(CONFIG_NET_RADIO) && !defined(CONFIG_WIRELESS_EXT) +#define CONFIG_WIRELESS_EXT +#endif + +#define prepare_wait_condition(task, var, value) \ +do { \ + var = value; \ + task = current; \ + barrier(); \ +} while (0) + +/* Wait in wait_state (e.g., TASK_INTERRUPTIBLE) for condition to + * become true; timeout is either jiffies (> 0) to wait or 0 to wait + * forever. + * When timeout == 0, return value is + * > 0 if condition becomes true, or + * < 0 if signal is pending on the thread. + * When timeout > 0, return value is + * > 0 if condition becomes true before timeout, + * < 0 if signal is pending on the thread before timeout, or + * 0 if timedout (condition may have become true at the same time) + */ + +#define wait_condition(condition, timeout, wait_state) \ +({ \ + long ret = timeout ? timeout : 1; \ + while (1) { \ + if (signal_pending(current)) { \ + ret = -ERESTARTSYS; \ + break; \ + } \ + set_current_state(wait_state); \ + if (condition) { \ + __set_current_state(TASK_RUNNING); \ + break; \ + } \ + if (timeout) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + } else \ + schedule(); \ + } \ + ret; \ +}) + +#ifdef WRAP_WQ + +struct workqueue_struct; + +struct workqueue_thread { + spinlock_t lock; + struct task_struct *task; + struct completion *completion; + char name[16]; + int pid; + /* whether any work_structs pending? <0 implies quit */ + s8 pending; + /* list of work_structs pending */ + struct list_head work_list; +}; + +typedef struct workqueue_struct { + u8 singlethread; + u8 qon; + int num_cpus; + struct workqueue_thread threads[0]; +} workqueue_struct_t; + +typedef struct { + struct list_head list; + void (*func)(void *data); + void *data; + /* whether/on which thread scheduled */ + struct workqueue_thread *thread; +} work_struct_t; + +#define initialize_work(work, pfunc, pdata) \ + do { \ + (work)->func = (pfunc); \ + (work)->data = (pdata); \ + (work)->thread = NULL; \ + } while (0) + +#undef create_singlethread_workqueue +#define create_singlethread_workqueue(name) wrap_create_wq(name, 1, 0) +#undef create_workqueue +#define create_workqueue(name) wrap_create_wq(name, 0, 0) +#undef destroy_workqueue +#define destroy_workqueue wrap_destroy_wq +#undef queue_work +#define queue_work wrap_queue_work +#undef flush_workqueue +#define flush_workqueue wrap_flush_wq + +workqueue_struct_t *wrap_create_wq(const char *name, u8 singlethread, u8 freeze); +void wrap_destroy_wq_on(workqueue_struct_t *workq, int cpu); +void wrap_destroy_wq(workqueue_struct_t *workq); +int wrap_queue_work_on(workqueue_struct_t *workq, work_struct_t *work, + int cpu); +int wrap_queue_work(workqueue_struct_t *workq, work_struct_t *work); +void wrap_cancel_work(work_struct_t *work); +void wrap_flush_wq_on(workqueue_struct_t *workq, int cpu); +void wrap_flush_wq(workqueue_struct_t *workq); +typedef void *worker_param_t; +#define worker_param_data(param, type, member) param + +#else // WRAP_WQ + +typedef struct workqueue_struct workqueue_struct_t; +typedef struct work_struct work_struct_t; + +#if defined(INIT_WORK_NAR) || defined(INIT_DELAYED_WORK_DEFERRABLE) +#define initialize_work(work, func, data) INIT_WORK(work, func) +typedef struct work_struct *worker_param_t; +#define worker_param_data(param, type, member) \ + container_of(param, type, member) +#else +#define initialize_work(work, func, data) INIT_WORK(work, func, data) +typedef void *worker_param_t; +#define worker_param_data(param, type, member) param +#endif // INIT_WORK_NAR + +#endif // WRAP_WQ + +struct nt_thread *wrap_worker_init(workqueue_struct_t *wq); + +#ifdef module_param +#define WRAP_MODULE_PARM_INT(name, perm) module_param(name, int, perm) +#define WRAP_MODULE_PARM_STRING(name, perm) module_param(name, charp, perm) +#else +#define WRAP_MODULE_PARM_INT(name, perm) MODULE_PARM(name, "i") +#define WRAP_MODULE_PARM_STRING(name, perm) MODULE_PARM(name, "s") +#endif + +#ifndef LOCK_PREFIX +#ifdef LOCK +#define LOCK_PREFIX LOCK +#else +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif +#endif +#endif + +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 +#endif + +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 +#endif + +#ifndef CHECKSUM_HW +#define CHECKSUM_HW CHECKSUM_PARTIAL +#endif + +#ifndef offset_in_page +#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) +#endif + +#ifndef PMSG_SUSPEND +#ifdef PM_SUSPEND +/* this is not correct - the value of PM_SUSPEND is different from + * PMSG_SUSPEND, but ndiswrapper doesn't care about the value when + * suspending */ +#define PMSG_SUSPEND PM_SUSPEND +#define PSMG_ON PM_ON +#else +typedef u32 pm_message_t; +#define PMSG_SUSPEND 2 +#define PMSG_ON 0 +#endif +#endif + +#ifndef PCI_D0 +#define PCI_D0 0 +#endif + +#ifndef PCI_D3hot +#define PCI_D3hot 3 +#endif + +#ifndef PCI_D3cold +#define PCI_D3cold 3 +#endif + +#ifndef PM_EVENT_SUSPEND +#define PM_EVENT_SUSPEND 2 +#endif + +#if !defined(HAVE_NETDEV_PRIV) +#define netdev_priv(dev) ((dev)->priv) +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) +#define ISR_PT_REGS_PARAM_DECL +#define ISR_PT_REGS_ARG +#else +#define ISR_PT_REGS_PARAM_DECL , struct pt_regs *regs +#define ISR_PT_REGS_ARG , NULL +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) +#define for_each_possible_cpu(_cpu) for_each_cpu(_cpu) +#endif + +#ifndef flush_icache_range +#define flush_icache_range(start, end) do { } while (0) +#endif + +#ifndef CHECKSUM_PARTIAL +#define CHECKSUM_PARTIAL CHECKSUM_HW +#endif + +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +#define memcpy_skb(skb, from, length) \ + memcpy(skb_put(skb, length), from, length) + +#ifndef DMA_24BIT_MASK +#define DMA_24BIT_MASK 0x0000000000ffffffULL +#endif + +#ifndef DMA_30BIT_MASK +#define DMA_30BIT_MASK 0x000000003fffffffULL +#endif + +#ifndef DMA_31BIT_MASK +#define DMA_31BIT_MASK 0x000000007fffffffULL +#endif + +#ifndef DMA_32BIT_MASK +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#endif + +#ifndef __GFP_DMA32 +#define __GFP_DMA32 GFP_DMA +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) +#define wrap_kmem_cache_create(name, size, align, flags) \ + kmem_cache_create(name, size, align, flags, NULL, NULL) +#else +#define wrap_kmem_cache_create(name, size, align, flags) \ + kmem_cache_create(name, size, align, flags, NULL) +#endif + +#include "winnt_types.h" +#include "ndiswrapper.h" +#include "pe_linker.h" +#include "wrapmem.h" +#include "lin2win.h" +#include "loader.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +static inline void netif_tx_lock(struct net_device *dev) +{ + spin_lock(&dev->xmit_lock); +} +static inline void netif_tx_unlock(struct net_device *dev) +{ + spin_unlock(&dev->xmit_lock); +} +static inline void netif_tx_lock_bh(struct net_device *dev) +{ + spin_lock_bh(&dev->xmit_lock); +} +static inline void netif_tx_unlock_bh(struct net_device *dev) +{ + spin_unlock_bh(&dev->xmit_lock); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +static inline void netif_poll_enable(struct net_device *dev) +{ +} +static inline void netif_poll_disable(struct net_device *dev) +{ +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#define proc_net_root init_net.proc_net +#else +#define proc_net_root proc_net +#endif + +/* TICK is 100ns */ +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 +#define SECSPERDAY 86400 +#define TICKSPERJIFFY ((TICKSPERSEC + HZ - 1) / HZ) + +#define int_div_round(x, y) (((x) + (y - 1)) / (y)) + +/* 1601 to 1970 is 369 years plus 89 leap days */ +#define SECS_1601_TO_1970 ((369 * 365 + 89) * (u64)SECSPERDAY) +#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) + +/* 100ns units to HZ; if sys_time is negative, relative to current + * clock, otherwise from year 1601 */ +#define SYSTEM_TIME_TO_HZ(sys_time) \ + (((sys_time) <= 0) ? \ + int_div_round(((u64)HZ * (-(sys_time))), TICKSPERSEC) : \ + int_div_round(((s64)HZ * ((sys_time) - ticks_1601())), TICKSPERSEC)) + +#define MSEC_TO_HZ(ms) int_div_round((ms * HZ), 1000) +#define USEC_TO_HZ(us) int_div_round((us * HZ), 1000000) + +extern u64 wrap_ticks_to_boot; + +static inline u64 ticks_1601(void) +{ + return wrap_ticks_to_boot + (u64)jiffies * TICKSPERJIFFY; +} + +typedef void (*generic_func)(void); + +struct wrap_export { + const char *name; + generic_func func; +}; + +#ifdef CONFIG_X86_64 + +#define WIN_SYMBOL(name, argc) \ + {#name, (generic_func) win2lin_ ## name ## _ ## argc} +#define WIN_WIN_SYMBOL(name, argc) \ + {#name, (generic_func) win2lin__win_ ## name ## _ ## argc} +#define WIN_FUNC_DECL(name, argc) \ + extern typeof(name) win2lin_ ## name ## _ ## argc; +#define WIN_FUNC_PTR(name, argc) win2lin_ ## name ## _ ## argc + +#else + +#define WIN_SYMBOL(name, argc) {#name, (generic_func)name} +#define WIN_WIN_SYMBOL(name, argc) {#name, (generic_func)_win_ ## name} +#define WIN_FUNC_DECL(name, argc) +#define WIN_FUNC_PTR(name, argc) name + +#endif + +#define WIN_FUNC(name, argc) name +/* map name s to f - if f is different from s */ +#define WIN_SYMBOL_MAP(s, f) + +#define POOL_TAG(A, B, C, D) \ + ((ULONG)((A) + ((B) << 8) + ((C) << 16) + ((D) << 24))) + +struct pe_image { + char name[MAX_DRIVER_NAME_LEN]; + UINT (*entry)(struct driver_object *, struct unicode_string *) wstdcall; + void *image; + int size; + int type; + + IMAGE_NT_HEADERS *nt_hdr; + IMAGE_OPTIONAL_HEADER *opt_hdr; +}; + +struct ndis_mp_block; + +struct wrap_timer { + struct nt_slist slist; + struct timer_list timer; + struct nt_timer *nt_timer; + long repeat; +#ifdef TIMER_DEBUG + unsigned long wrap_timer_magic; +#endif +}; + +struct ntos_work_item { + struct nt_list list; + void *arg1; + void *arg2; + NTOS_WORK_FUNC func; +}; + +struct wrap_device_setting { + struct nt_list list; + char name[MAX_SETTING_NAME_LEN]; + char value[MAX_SETTING_VALUE_LEN]; + void *encoded; +}; + +struct wrap_bin_file { + char name[MAX_DRIVER_NAME_LEN]; + size_t size; + void *data; +}; + +#define WRAP_DRIVER_CLIENT_ID 1 + +struct wrap_driver { + struct nt_list list; + struct driver_object *drv_obj; + char name[MAX_DRIVER_NAME_LEN]; + char version[MAX_SETTING_VALUE_LEN]; + unsigned short num_pe_images; + struct pe_image pe_images[MAX_DRIVER_PE_IMAGES]; + unsigned short num_bin_files; + struct wrap_bin_file *bin_files; + struct nt_list wrap_devices; + struct nt_list settings; + int dev_type; + struct ndis_driver *ndis_driver; +}; + +enum hw_status { + HW_INITIALIZED = 1, HW_SUSPENDED, HW_HALTED, HW_PRESENT, +}; + +struct wrap_device { + /* first part is (de)initialized once by loader */ + struct nt_list list; + int dev_bus; + int vendor; + int device; + int subvendor; + int subdevice; + char conf_file_name[MAX_DRIVER_NAME_LEN]; + char driver_name[MAX_DRIVER_NAME_LEN]; + struct wrap_driver *driver; + struct nt_list settings; + + /* rest should be (de)initialized when a device is + * (un)plugged */ + struct cm_resource_list *resource_list; + unsigned long hw_status; + struct device_object *pdo; + union { + struct { + struct pci_dev *pdev; + enum device_power_state wake_state; + } pci; + struct { + struct usb_device *udev; + struct usb_interface *intf; + int num_alloc_urbs; + struct nt_list wrap_urb_list; + } usb; + }; + union { + struct ndis_device *wnd; + }; +}; + +#define wrap_is_pci_bus(dev_bus) \ + (WRAP_BUS(dev_bus) == WRAP_PCI_BUS || \ + WRAP_BUS(dev_bus) == WRAP_PCMCIA_BUS) +#ifdef ENABLE_USB +/* earlier versions of ndiswrapper used 0 as USB_BUS */ +#define wrap_is_usb_bus(dev_bus) \ + (WRAP_BUS(dev_bus) == WRAP_USB_BUS || \ + WRAP_BUS(dev_bus) == WRAP_INTERNAL_BUS) +#else +#define wrap_is_usb_bus(dev_bus) 0 +#endif +#define wrap_is_bluetooth_device(dev_bus) \ + (WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE1 || \ + WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE2) + +extern workqueue_struct_t *ntos_wq; +#define schedule_ntos_work(work_struct) queue_work(ntos_wq, work_struct) +#define schedule_work(work_struct) queue_work(ntos_wq, work_struct) + +extern workqueue_struct_t *ndis_wq; +#define schedule_ndis_work(work_struct) queue_work(ndis_wq, work_struct) + +extern workqueue_struct_t *wrapndis_wq; +#define schedule_wrapndis_work(work_struct) queue_work(wrapndis_wq, work_struct) + +#define atomic_unary_op(var, size, oper) \ +do { \ + if (size == 1) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "b %b0\n\t" : "+m" (var)); \ + else if (size == 2) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "w %w0\n\t" : "+m" (var)); \ + else if (size == 4) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "l %0\n\t" : "+m" (var)); \ + else if (size == 8) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "q %q0\n\t" : "+m" (var)); \ + else { \ + extern void _invalid_op_size_(void); \ + _invalid_op_size_(); \ + } \ +} while (0) + +#define atomic_inc_var_size(var, size) atomic_unary_op(var, size, "inc") + +#define atomic_inc_var(var) atomic_inc_var_size(var, sizeof(var)) + +#define atomic_dec_var_size(var, size) atomic_unary_op(var, size, "dec") + +#define atomic_dec_var(var) atomic_dec_var_size(var, sizeof(var)) + +#define pre_atomic_add(var, i) \ +({ \ + typeof(var) pre; \ + __asm__ __volatile__( \ + LOCK_PREFIX "xadd %0, %1\n\t" \ + : "=r"(pre), "+m"(var) \ + : "0"(i)); \ + pre; \ +}) + +#define post_atomic_add(var, i) (pre_atomic_add(var, i) + i) + +#ifndef in_atomic +#define in_atomic() in_interrupt() +#endif + +#ifndef preempt_enable_no_resched +#define preempt_enable_no_resched() preempt_enable() +#endif + +//#define DEBUG_IRQL 1 + +#ifdef DEBUG_IRQL +#define assert_irql(cond) \ +do { \ + KIRQL _irql_ = current_irql(); \ + if (!(cond)) { \ + WARNING("assertion '%s' failed: %d", #cond, _irql_); \ + DBG_BLOCK(4) { \ + dump_stack(); \ + } \ + } \ +} while (0) +#else +#define assert_irql(cond) do { } while (0) +#endif + +/* When preempt is enabled, we should preempt_disable to raise IRQL to + * DISPATCH_LEVEL, to be consistent with the semantics. However, using + * a mutex instead, so that only ndiswrapper threads run one at a time + * on a processor when at DISPATCH_LEVEL seems to be enough. So that + * is what we will use until we learn otherwise. If + * preempt_(en|dis)able is required for some reason, comment out + * following #define. */ + +#define WRAP_PREEMPT 1 + +#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PREEMPT_RT) +#ifndef WRAP_PREEMPT +#define WRAP_PREEMPT 1 +#endif +#endif + +//#undef WRAP_PREEMPT + +#ifdef WRAP_PREEMPT + +typedef struct { + int count; + struct mutex lock; +#ifdef CONFIG_SMP + typeof(current->cpus_allowed) cpus_allowed; +#endif + struct task_struct *task; +} irql_info_t; + +DECLARE_PER_CPU(irql_info_t, irql_info); + +static inline KIRQL raise_irql(KIRQL newirql) +{ + irql_info_t *info; + + assert(newirql == DISPATCH_LEVEL); + info = &get_cpu_var(irql_info); + if (info->task == current) { + assert(info->count > 0); + assert(mutex_is_locked(&info->lock)); +#if defined(CONFIG_SMP) && defined(DEBUG) + do { + cpumask_t cpumask; + cpumask = cpumask_of_cpu(smp_processor_id()); + cpus_xor(cpumask, cpumask, current->cpus_allowed); + assert(cpus_empty(cpumask)); + } while (0); +#endif + info->count++; + put_cpu_var(irql_info); + return DISPATCH_LEVEL; + } + /* TODO: is this enough to pin down to current cpu? */ +#ifdef CONFIG_SMP + assert(task_cpu(current) == smp_processor_id()); + info->cpus_allowed = current->cpus_allowed; + current->cpus_allowed = cpumask_of_cpu(smp_processor_id()); +#endif + put_cpu_var(irql_info); + mutex_lock(&info->lock); + assert(info->count == 0); + assert(info->task == NULL); + info->count = 1; + info->task = current; + return PASSIVE_LEVEL; +} + +static inline void lower_irql(KIRQL oldirql) +{ + irql_info_t *info; + + assert(oldirql <= DISPATCH_LEVEL); + info = &get_cpu_var(irql_info); + assert(info->task == current); + assert(mutex_is_locked(&info->lock)); + assert(info->count > 0); + if (--info->count == 0) { + info->task = NULL; +#ifdef CONFIG_SMP + current->cpus_allowed = info->cpus_allowed; +#endif + mutex_unlock(&info->lock); + } + put_cpu_var(irql_info); +} + +static inline KIRQL current_irql(void) +{ + int count; + if (in_irq() || irqs_disabled()) + EXIT4(return DIRQL); + if (in_atomic() || in_interrupt()) + EXIT4(return SOFT_IRQL); + count = get_cpu_var(irql_info).count; + put_cpu_var(irql_info); + if (count) + EXIT6(return DISPATCH_LEVEL); + else + EXIT6(return PASSIVE_LEVEL); +} + +#else + +static inline KIRQL current_irql(void) +{ + if (in_irq() || irqs_disabled()) + EXIT4(return DIRQL); + if (in_interrupt()) + EXIT4(return SOFT_IRQL); + if (in_atomic()) + EXIT6(return DISPATCH_LEVEL); + else + EXIT6(return PASSIVE_LEVEL); +} + +static inline KIRQL raise_irql(KIRQL newirql) +{ + KIRQL ret = in_atomic() ? DISPATCH_LEVEL : PASSIVE_LEVEL; + assert(newirql == DISPATCH_LEVEL); + assert(current_irql() <= DISPATCH_LEVEL); + preempt_disable(); + return ret; +} + +static inline void lower_irql(KIRQL oldirql) +{ + assert(current_irql() == DISPATCH_LEVEL); + preempt_enable(); +} + +#endif + +#define irql_gfp() (in_atomic() ? GFP_ATOMIC : GFP_KERNEL) + +/* Windows spinlocks are of type ULONG_PTR which is not big enough to + * store Linux spinlocks; so we implement Windows spinlocks using + * ULONG_PTR space with our own functions/macros */ + +/* Windows seems to use 0 for unlocked state of spinlock - if Linux + * convention of 1 for unlocked state is used, at least prism54 driver + * crashes */ + +#define NT_SPIN_LOCK_UNLOCKED 0 +#define NT_SPIN_LOCK_LOCKED 1 + +static inline void nt_spin_lock_init(NT_SPIN_LOCK *lock) +{ + *lock = NT_SPIN_LOCK_UNLOCKED; +} + +#ifdef CONFIG_SMP + +static inline void nt_spin_lock(NT_SPIN_LOCK *lock) +{ + __asm__ __volatile__( + "1:\t" + " xchgl %1, %0\n\t" + " testl %1, %1\n\t" + " jz 3f\n" + "2:\t" + " rep; nop\n\t" + " cmpl %2, %0\n\t" + " je 1b\n\t" + " jmp 2b\n" + "3:\n\t" + : "+m" (*lock) + : "r" (NT_SPIN_LOCK_LOCKED), "i" (NT_SPIN_LOCK_UNLOCKED)); +} + +static inline void nt_spin_unlock(NT_SPIN_LOCK *lock) +{ + *lock = NT_SPIN_LOCK_UNLOCKED; +} + +#else // CONFIG_SMP + +#define nt_spin_lock(lock) do { } while (0) + +#define nt_spin_unlock(lock) do { } while (0) + +#endif // CONFIG_SMP + +/* When kernel would've disabled preempt (e.g., in interrupt + * handlers), we need to fake preempt so driver thinks it is running + * at right IRQL */ + +/* raise IRQL to given (higher) IRQL if necessary before locking */ +static inline KIRQL nt_spin_lock_irql(NT_SPIN_LOCK *lock, KIRQL newirql) +{ + KIRQL oldirql = raise_irql(newirql); + nt_spin_lock(lock); + return oldirql; +} + +/* lower IRQL to given (lower) IRQL if necessary after unlocking */ +static inline void nt_spin_unlock_irql(NT_SPIN_LOCK *lock, KIRQL oldirql) +{ + nt_spin_unlock(lock); + lower_irql(oldirql); +} + +#define nt_spin_lock_irqsave(lock, flags) \ +do { \ + local_irq_save(flags); \ + preempt_disable(); \ + nt_spin_lock(lock); \ +} while (0) + +#define nt_spin_unlock_irqrestore(lock, flags) \ +do { \ + nt_spin_unlock(lock); \ + preempt_enable_no_resched(); \ + local_irq_restore(flags); \ + preempt_check_resched(); \ +} while (0) + +static inline ULONG SPAN_PAGES(void *ptr, SIZE_T length) +{ + return PAGE_ALIGN(((unsigned long)ptr & (PAGE_SIZE - 1)) + length) + >> PAGE_SHIFT; +} + +#ifdef CONFIG_X86_64 + +/* TODO: can these be implemented without using spinlock? */ + +static inline struct nt_slist *PushEntrySList(nt_slist_header *head, + struct nt_slist *entry, + NT_SPIN_LOCK *lock) +{ + KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL); + entry->next = head->next; + head->next = entry; + head->depth++; + nt_spin_unlock_irql(lock, irql); + TRACE4("%p, %p, %p", head, entry, entry->next); + return entry->next; +} + +static inline struct nt_slist *PopEntrySList(nt_slist_header *head, + NT_SPIN_LOCK *lock) +{ + struct nt_slist *entry; + KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL); + entry = head->next; + if (entry) { + head->next = entry->next; + head->depth--; + } + nt_spin_unlock_irql(lock, irql); + TRACE4("%p, %p", head, entry); + return entry; +} + +#else + +#define u64_low_32(x) ((u32)x) +#define u64_high_32(x) ((u32)(x >> 32)) + +static inline u64 cmpxchg8b(volatile u64 *ptr, u64 old, u64 new) +{ + u64 prev; + + __asm__ __volatile__( + "\n" + LOCK_PREFIX "cmpxchg8b %0\n" + : "+m" (*ptr), "=A" (prev) + : "A" (old), "b" (u64_low_32(new)), "c" (u64_high_32(new))); + return prev; +} + +/* slist routines below update slist atomically - no need for + * spinlocks */ + +static inline struct nt_slist *PushEntrySList(nt_slist_header *head, + struct nt_slist *entry, + NT_SPIN_LOCK *lock) +{ + nt_slist_header old, new; + do { + old.align = head->align; + entry->next = old.next; + new.next = entry; + new.depth = old.depth + 1; + } while (cmpxchg8b(&head->align, old.align, new.align) != old.align); + TRACE4("%p, %p, %p", head, entry, old.next); + return old.next; +} + +static inline struct nt_slist *PopEntrySList(nt_slist_header *head, + NT_SPIN_LOCK *lock) +{ + struct nt_slist *entry; + nt_slist_header old, new; + do { + old.align = head->align; + entry = old.next; + if (!entry) + break; + new.next = entry->next; + new.depth = old.depth - 1; + } while (cmpxchg8b(&head->align, old.align, new.align) != old.align); + TRACE4("%p, %p", head, entry); + return entry; +} + +#endif + +#define sleep_hz(n) \ +do { \ + set_current_state(TASK_INTERRUPTIBLE); \ + schedule_timeout(n); \ +} while (0) + +int ntoskernel_init(void); +void ntoskernel_exit(void); +int ntoskernel_init_device(struct wrap_device *wd); +void ntoskernel_exit_device(struct wrap_device *wd); +void *allocate_object(ULONG size, enum common_object_type type, + struct unicode_string *name); +void free_object(void *object); + +int usb_init(void); +void usb_exit(void); +int usb_init_device(struct wrap_device *wd); +void usb_exit_device(struct wrap_device *wd); +void usb_cancel_pending_urbs(void); + +int crt_init(void); +void crt_exit(void); +int rtl_init(void); +void rtl_exit(void); +int wrap_procfs_init(void); +void wrap_procfs_remove(void); + +int link_pe_images(struct pe_image *pe_image, unsigned short n); + +int stricmp(const char *s1, const char *s2); +void dump_bytes(const char *name, const u8 *from, int len); +struct mdl *allocate_init_mdl(void *virt, ULONG length); +void free_mdl(struct mdl *mdl); +struct driver_object *find_bus_driver(const char *name); +void free_custom_extensions(struct driver_extension *drv_obj_ext); +struct nt_thread *get_current_nt_thread(void); +u64 ticks_1601(void); +int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2); +void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type, + struct ndis_mp_block *nmb); +BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz, + unsigned long repeat_hz, struct kdpc *kdpc); + +LONG InterlockedDecrement(LONG volatile *val) wfastcall; +LONG InterlockedIncrement(LONG volatile *val) wfastcall; +struct nt_list *ExInterlockedInsertHeadList + (struct nt_list *head, struct nt_list *entry, + NT_SPIN_LOCK *lock) wfastcall; +struct nt_list *ExInterlockedInsertTailList + (struct nt_list *head, struct nt_list *entry, + NT_SPIN_LOCK *lock) wfastcall; +struct nt_list *ExInterlockedRemoveHeadList + (struct nt_list *head, NT_SPIN_LOCK *lock) wfastcall; +NTSTATUS IofCallDriver(struct device_object *dev_obj, struct irp *irp) wfastcall; +KIRQL KfRaiseIrql(KIRQL newirql) wfastcall; +void KfLowerIrql(KIRQL oldirql) wfastcall; +KIRQL KfAcquireSpinLock(NT_SPIN_LOCK *lock) wfastcall; +void KfReleaseSpinLock(NT_SPIN_LOCK *lock, KIRQL oldirql) wfastcall; +void IofCompleteRequest(struct irp *irp, CHAR prio_boost) wfastcall; +void KefReleaseSpinLockFromDpcLevel(NT_SPIN_LOCK *lock) wfastcall; + +LONG ObfReferenceObject(void *object) wfastcall; +void ObfDereferenceObject(void *object) wfastcall; + +#define ObReferenceObject(object) ObfReferenceObject(object) +#define ObDereferenceObject(object) ObfDereferenceObject(object) + +void WRITE_PORT_UCHAR(ULONG_PTR port, UCHAR value) wstdcall; +UCHAR READ_PORT_UCHAR(ULONG_PTR port) wstdcall; + +#undef ExAllocatePoolWithTag +void *ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size, + ULONG tag) wstdcall; +#if defined(ALLOC_DEBUG) && ALLOC_DEBUG > 1 +#define ExAllocatePoolWithTag(pool_type, size, tag) \ + wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__) +#endif + +void ExFreePool(void *p) wstdcall; +ULONG MmSizeOfMdl(void *base, ULONG length) wstdcall; +void __iomem *MmMapIoSpace(PHYSICAL_ADDRESS phys_addr, SIZE_T size, + enum memory_caching_type cache) wstdcall; +void MmUnmapIoSpace(void __iomem *addr, SIZE_T size) wstdcall; +void MmProbeAndLockPages(struct mdl *mdl, KPROCESSOR_MODE access_mode, + enum lock_operation operation) wstdcall; +void MmUnlockPages(struct mdl *mdl) wstdcall; +void KeInitializeEvent(struct nt_event *nt_event, + enum event_type type, BOOLEAN state) wstdcall; +LONG KeSetEvent(struct nt_event *nt_event, KPRIORITY incr, + BOOLEAN wait) wstdcall; +LONG KeResetEvent(struct nt_event *nt_event) wstdcall; +void KeClearEvent(struct nt_event *nt_event) wstdcall; +void KeInitializeDpc(struct kdpc *kdpc, void *func, void *ctx) wstdcall; +BOOLEAN queue_kdpc(struct kdpc *kdpc); +BOOLEAN dequeue_kdpc(struct kdpc *kdpc); + +void KeFlushQueuedDpcs(void) wstdcall; +NTSTATUS IoConnectInterrupt(struct kinterrupt **kinterrupt, + PKSERVICE_ROUTINE service_routine, + void *service_context, NT_SPIN_LOCK *lock, + ULONG vector, KIRQL irql, KIRQL synch_irql, + enum kinterrupt_mode interrupt_mode, + BOOLEAN shareable, KAFFINITY processor_enable_mask, + BOOLEAN floating_save) wstdcall; +void IoDisconnectInterrupt(struct kinterrupt *interrupt) wstdcall; +BOOLEAN KeSynchronizeExecution(struct kinterrupt *interrupt, + PKSYNCHRONIZE_ROUTINE synch_routine, + void *ctx) wstdcall; + +NTSTATUS KeWaitForSingleObject(void *object, KWAIT_REASON reason, + KPROCESSOR_MODE waitmode, BOOLEAN alertable, + LARGE_INTEGER *timeout) wstdcall; +struct mdl *IoAllocateMdl(void *virt, ULONG length, BOOLEAN second_buf, + BOOLEAN charge_quota, struct irp *irp) wstdcall; +void MmBuildMdlForNonPagedPool(struct mdl *mdl) wstdcall; +void IoFreeMdl(struct mdl *mdl) wstdcall; +NTSTATUS IoCreateDevice(struct driver_object *driver, ULONG dev_ext_length, + struct unicode_string *dev_name, DEVICE_TYPE dev_type, + ULONG dev_chars, BOOLEAN exclusive, + struct device_object **dev_obj) wstdcall; +NTSTATUS IoCreateSymbolicLink(struct unicode_string *link, + struct unicode_string *dev_name) wstdcall; +void IoDeleteDevice(struct device_object *dev) wstdcall; +void IoDetachDevice(struct device_object *topdev) wstdcall; +struct device_object *IoGetAttachedDevice(struct device_object *dev) wstdcall; +struct device_object *IoGetAttachedDeviceReference + (struct device_object *dev) wstdcall; +NTSTATUS IoAllocateDriverObjectExtension + (struct driver_object *drv_obj, void *client_id, ULONG extlen, + void **ext) wstdcall; +void *IoGetDriverObjectExtension(struct driver_object *drv, + void *client_id) wstdcall; +struct device_object *IoAttachDeviceToDeviceStack + (struct device_object *src, struct device_object *dst) wstdcall; +void KeInitializeEvent(struct nt_event *nt_event, enum event_type type, + BOOLEAN state) wstdcall; +struct irp *IoAllocateIrp(char stack_count, BOOLEAN charge_quota) wstdcall; +void IoFreeIrp(struct irp *irp) wstdcall; +BOOLEAN IoCancelIrp(struct irp *irp) wstdcall; +struct irp *IoBuildSynchronousFsdRequest + (ULONG major_func, struct device_object *dev_obj, void *buf, + ULONG length, LARGE_INTEGER *offset, struct nt_event *event, + struct io_status_block *status) wstdcall; +struct irp *IoBuildAsynchronousFsdRequest + (ULONG major_func, struct device_object *dev_obj, void *buf, + ULONG length, LARGE_INTEGER *offset, + struct io_status_block *status) wstdcall; +NTSTATUS PoCallDriver(struct device_object *dev_obj, struct irp *irp) wstdcall; + +NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp) wstdcall; +WIN_FUNC_DECL(IoPassIrpDown,2); +NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) wstdcall; +NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) wstdcall; +NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj, + struct irp *irp) wstdcall; + +KIRQL KeGetCurrentIrql(void) wstdcall; +void KeInitializeSpinLock(NT_SPIN_LOCK *lock) wstdcall; +void KeAcquireSpinLock(NT_SPIN_LOCK *lock, KIRQL *irql) wstdcall; +void KeReleaseSpinLock(NT_SPIN_LOCK *lock, KIRQL oldirql) wstdcall; +KIRQL KeAcquireSpinLockRaiseToDpc(NT_SPIN_LOCK *lock) wstdcall; + +void IoAcquireCancelSpinLock(KIRQL *irql) wstdcall; +void IoReleaseCancelSpinLock(KIRQL irql) wstdcall; + +void RtlCopyMemory(void *dst, const void *src, SIZE_T length) wstdcall; +NTSTATUS RtlUnicodeStringToAnsiString + (struct ansi_string *dst, const struct unicode_string *src, + BOOLEAN dup) wstdcall; +NTSTATUS RtlAnsiStringToUnicodeString + (struct unicode_string *dst, const struct ansi_string *src, + BOOLEAN dup) wstdcall; +void RtlInitAnsiString(struct ansi_string *dst, const char *src) wstdcall; +void RtlInitString(struct ansi_string *dst, const char *src) wstdcall; +void RtlInitUnicodeString(struct unicode_string *dest, + const wchar_t *src) wstdcall; +void RtlFreeUnicodeString(struct unicode_string *string) wstdcall; +void RtlFreeAnsiString(struct ansi_string *string) wstdcall; +LONG RtlCompareUnicodeString(const struct unicode_string *s1, + const struct unicode_string *s2, + BOOLEAN case_insensitive) wstdcall; +void RtlCopyUnicodeString(struct unicode_string *dst, + struct unicode_string *src) wstdcall; +NTSTATUS RtlUpcaseUnicodeString(struct unicode_string *dst, + struct unicode_string *src, + BOOLEAN alloc) wstdcall; +void KeInitializeTimer(struct nt_timer *nt_timer) wstdcall; +void KeInitializeTimerEx(struct nt_timer *nt_timer, + enum timer_type type) wstdcall; +BOOLEAN KeSetTimerEx(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + LONG period_ms, struct kdpc *kdpc) wstdcall; +BOOLEAN KeSetTimer(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + struct kdpc *kdpc) wstdcall; +BOOLEAN KeCancelTimer(struct nt_timer *nt_timer) wstdcall; +void KeInitializeDpc(struct kdpc *kdpc, void *func, void *ctx) wstdcall; +struct nt_thread *KeGetCurrentThread(void) wstdcall; +NTSTATUS ObReferenceObjectByHandle(void *handle, ACCESS_MASK desired_access, + void *obj_type, KPROCESSOR_MODE access_mode, + void **object, void *handle_info) wstdcall; + +void adjust_user_shared_data_addr(char *driver, unsigned long length); + +extern spinlock_t ntoskernel_lock; +extern spinlock_t irp_cancel_lock; +extern struct nt_list object_list; +#ifdef CONFIG_X86_64 +extern struct kuser_shared_data kuser_shared_data; +#endif + +#define IoCompleteRequest(irp, prio) IofCompleteRequest(irp, prio) +#define IoCallDriver(dev, irp) IofCallDriver(dev, irp) + +#if defined(IO_DEBUG) +#define DUMP_IRP(_irp) \ +do { \ + struct io_stack_location *_irp_sl; \ + _irp_sl = IoGetCurrentIrpStackLocation(_irp); \ + IOTRACE("irp: %p, stack size: %d, cl: %d, sl: %p, dev_obj: %p, " \ + "mj_fn: %d, minor_fn: %d, nt_urb: %p, event: %p", \ + _irp, _irp->stack_count, (_irp)->current_location, \ + _irp_sl, _irp_sl->dev_obj, _irp_sl->major_fn, \ + _irp_sl->minor_fn, IRP_URB(_irp), \ + (_irp)->user_event); \ +} while (0) +#else +#define DUMP_IRP(_irp) do { } while (0) +#endif + +#endif // _NTOSKERNEL_H_ --- linux-2.6.27.orig/ubuntu/ndiswrapper/lin2win.h +++ linux-2.6.27/ubuntu/ndiswrapper/lin2win.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2006 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifdef CONFIG_X86_64 + +/* Windows functions must have 32 bytes of shadow space for arguments + * above return address, irrespective of number of args. So argc >= 4 + */ + +#define alloc_win_stack_frame(argc) \ + "sub $(" #argc "+1)*8, %%rsp\n\t" +#define free_win_stack_frame(argc) \ + "add $(" #argc "+1)*8, %%rsp\n\t" + +/* m is index of Windows arg required; Windows arg 1 should be at + * 0(%rsp), arg 2 at 8(%rsp) and so on after the frame is allocated. +*/ + +#define lin2win_win_arg(m) "(" #m "-1)*8(%%rsp)" + +/* args for Windows function must be in clobber / output list */ + +#define outputs() \ + "=a" (_ret), "=c" (_dummy), "=d" (_dummy), \ + "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11) + +#define clobbers() "cc" + +#define LIN2WIN0(func) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8"); \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN1(func, arg1) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8"); \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN2(func, arg1, arg2) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8"); \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), "d" (arg2), [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN3(func, arg1, arg2, arg3) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN4(func, arg1, arg2, arg3, arg4) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9") = (u64)arg4; \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), "r" (r9), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9") = (u64)arg4; \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(5) \ + "movq %[rarg5], " lin2win_win_arg(5) "\n\t" \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(5) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), "r" (r9), \ + [rarg5] "ri" ((u64)arg5), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9") = (u64)arg4; \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(6) \ + "movq %[rarg5], " lin2win_win_arg(5) "\n\t" \ + "movq %[rarg6], " lin2win_win_arg(6) "\n\t" \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(6) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), "r" (r9), \ + [rarg5] "ri" ((u64)arg5), [rarg6] "ri" ((u64)arg6), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#else // CONFIG_X86_64 + +#define LIN2WIN1(func, arg1) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1); \ +}) +#define LIN2WIN2(func, arg1, arg2) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2); \ +}) +#define LIN2WIN3(func, arg1, arg2, arg3) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3); \ +}) +#define LIN2WIN4(func, arg1, arg2, arg3, arg4) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3, arg4); \ +}) +#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3, arg4, arg5); \ +}) +#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3, arg4, arg5, arg6); \ +}) + +#endif // CONFIG_X86_64 --- linux-2.6.27.orig/ubuntu/ndiswrapper/ntoskernel_io.c +++ linux-2.6.27/ubuntu/ndiswrapper/ntoskernel_io.c @@ -0,0 +1,1106 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ntoskernel.h" +#include "ndis.h" +#include "wrapndis.h" +#include "usb.h" +#include "loader.h" +#include "ntoskernel_io_exports.h" + +wstdcall void WIN_FUNC(IoAcquireCancelSpinLock,1) + (KIRQL *irql) __acquires(irql) +{ + spin_lock_bh(&irp_cancel_lock); + *irql = 0; +} + +wstdcall void WIN_FUNC(IoReleaseCancelSpinLock,1) + (KIRQL irql) __releases(irql) +{ + spin_unlock_bh(&irp_cancel_lock); +} + +wstdcall int WIN_FUNC(IoIsWdmVersionAvailable,2) + (UCHAR major, UCHAR minor) +{ + IOENTER("%d, %x", major, minor); + if (major == 1 && + (minor == 0x30 || // Windows 2003 + minor == 0x20 || // Windows XP + minor == 0x10)) // Windows 2000 + IOEXIT(return TRUE); + IOEXIT(return FALSE); +} + +wstdcall BOOLEAN WIN_FUNC(IoIs32bitProcess,1) + (struct irp *irp) +{ +#ifdef CONFIG_X86_64 + return FALSE; +#else + return TRUE; +#endif +} + +wstdcall void WIN_FUNC(IoInitializeIrp,3) + (struct irp *irp, USHORT size, CCHAR stack_count) +{ + IOENTER("irp: %p, %d, %d", irp, size, stack_count); + + memset(irp, 0, size); + irp->size = size; + irp->stack_count = stack_count; + irp->current_location = stack_count; + IoGetCurrentIrpStackLocation(irp) = IRP_SL(irp, stack_count); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoReuseIrp,2) + (struct irp *irp, NTSTATUS status) +{ + IOENTER("%p, %d", irp, status); + if (irp) { + UCHAR alloc_flags; + + alloc_flags = irp->alloc_flags; + IoInitializeIrp(irp, irp->size, irp->stack_count); + irp->alloc_flags = alloc_flags; + irp->io_status.status = status; + } + IOEXIT(return); +} + +wstdcall struct irp *WIN_FUNC(IoAllocateIrp,2) + (char stack_count, BOOLEAN charge_quota) +{ + struct irp *irp; + int irp_size; + + IOENTER("count: %d", stack_count); + stack_count++; + irp_size = IoSizeOfIrp(stack_count); + irp = kmalloc(irp_size, irql_gfp()); + if (irp) + IoInitializeIrp(irp, irp_size, stack_count); + IOTRACE("irp %p", irp); + IOEXIT(return irp); +} + +wstdcall BOOLEAN WIN_FUNC(IoCancelIrp,1) + (struct irp *irp) +{ + typeof(irp->cancel_routine) cancel_routine; + + /* NB: this function may be called at DISPATCH_LEVEL */ + IOTRACE("irp: %p", irp); + if (!irp) + return FALSE; + DUMP_IRP(irp); + IoAcquireCancelSpinLock(&irp->cancel_irql); + cancel_routine = xchg(&irp->cancel_routine, NULL); + IOTRACE("%p", cancel_routine); + irp->cancel = TRUE; + if (cancel_routine) { + struct io_stack_location *irp_sl; + irp_sl = IoGetCurrentIrpStackLocation(irp); + IOTRACE("%p, %p", irp_sl, irp_sl->dev_obj); + /* cancel_routine will release the spin lock */ + __release(irp->cancel_irql); + LIN2WIN2(cancel_routine, irp_sl->dev_obj, irp); + /* in usb's cancel, irp->cancel is set to indicate + * status of cancel */ + IOEXIT(return xchg(&irp->cancel, TRUE)); + } else { + IOTRACE("irp %p already canceled", irp); + IoReleaseCancelSpinLock(irp->cancel_irql); + IOEXIT(return FALSE); + } +} + +wstdcall void IoQueueThreadIrp(struct irp *irp) +{ + struct nt_thread *thread; + KIRQL irql; + + thread = get_current_nt_thread(); + if (thread) { + IOTRACE("thread: %p, task: %p", thread, thread->task); + irp->flags |= IRP_SYNCHRONOUS_API; + irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL); + InsertTailList(&thread->irps, &irp->thread_list); + IoIrpThread(irp) = thread; + nt_spin_unlock_irql(&thread->lock, irql); + } else + IoIrpThread(irp) = NULL; +} + +wstdcall void IoDequeueThreadIrp(struct irp *irp) +{ + struct nt_thread *thread; + KIRQL irql; + + thread = IoIrpThread(irp); + if (thread) { + irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL); + RemoveEntryList(&irp->thread_list); + nt_spin_unlock_irql(&thread->lock, irql); + } +} + +wstdcall void WIN_FUNC(IoFreeIrp,1) + (struct irp *irp) +{ + IOENTER("irp = %p", irp); + if (irp->flags & IRP_SYNCHRONOUS_API) + IoDequeueThreadIrp(irp); + kfree(irp); + + IOEXIT(return); +} + +wstdcall struct irp *WIN_FUNC(IoBuildAsynchronousFsdRequest,6) + (ULONG major_fn, struct device_object *dev_obj, void *buffer, + ULONG length, LARGE_INTEGER *offset, + struct io_status_block *user_status) +{ + struct irp *irp; + struct io_stack_location *irp_sl; + + IOENTER("%p", dev_obj); + if (!dev_obj) + IOEXIT(return NULL); + irp = IoAllocateIrp(dev_obj->stack_count, FALSE); + if (irp == NULL) { + WARNING("couldn't allocate irp"); + IOEXIT(return NULL); + } + + irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->major_fn = major_fn; + IOTRACE("major_fn: %d", major_fn); + irp_sl->minor_fn = 0; + irp_sl->flags = 0; + irp_sl->control = 0; + irp_sl->dev_obj = dev_obj; + irp_sl->file_obj = NULL; + irp_sl->completion_routine = NULL; + + if (dev_obj->flags & DO_DIRECT_IO) { + irp->mdl = IoAllocateMdl(buffer, length, FALSE, FALSE, irp); + if (irp->mdl == NULL) { + IoFreeIrp(irp); + return NULL; + } + MmProbeAndLockPages(irp->mdl, KernelMode, + major_fn == IRP_MJ_WRITE ? + IoReadAccess : IoWriteAccess); + IOTRACE("mdl: %p", irp->mdl); + } else if (dev_obj->flags & DO_BUFFERED_IO) { + irp->associated_irp.system_buffer = buffer; + irp->flags = IRP_BUFFERED_IO; + irp->mdl = NULL; + IOTRACE("buffer: %p", buffer); + } + if (major_fn == IRP_MJ_READ) { + irp_sl->params.read.length = length; + irp_sl->params.read.byte_offset = *offset; + } else if (major_fn == IRP_MJ_WRITE) { + irp_sl->params.write.length = length; + irp_sl->params.write.byte_offset = *offset; + } + irp->user_status = user_status; + IOTRACE("irp: %p", irp); + return irp; +} + +wstdcall struct irp *WIN_FUNC(IoBuildSynchronousFsdRequest,7) + (ULONG major_fn, struct device_object *dev_obj, void *buf, + ULONG length, LARGE_INTEGER *offset, struct nt_event *event, + struct io_status_block *user_status) +{ + struct irp *irp; + + irp = IoBuildAsynchronousFsdRequest(major_fn, dev_obj, buf, length, + offset, user_status); + if (irp == NULL) + return NULL; + irp->user_event = event; + IoQueueThreadIrp(irp); + return irp; +} + +wstdcall struct irp *WIN_FUNC(IoBuildDeviceIoControlRequest,9) + (ULONG ioctl, struct device_object *dev_obj, + void *input_buf, ULONG input_buf_len, void *output_buf, + ULONG output_buf_len, BOOLEAN internal_ioctl, + struct nt_event *event, struct io_status_block *io_status) +{ + struct irp *irp; + struct io_stack_location *irp_sl; + ULONG buf_len; + + IOENTER("%p, 0x%08x, %d", dev_obj, ioctl, internal_ioctl); + if (!dev_obj) + IOEXIT(return NULL); + irp = IoAllocateIrp(dev_obj->stack_count, FALSE); + if (irp == NULL) { + WARNING("couldn't allocate irp"); + return NULL; + } + irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->params.dev_ioctl.code = ioctl; + irp_sl->params.dev_ioctl.input_buf_len = input_buf_len; + irp_sl->params.dev_ioctl.output_buf_len = output_buf_len; + irp_sl->major_fn = (internal_ioctl) ? + IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL; + IOTRACE("%d", IO_METHOD_FROM_CTL_CODE(ioctl)); + + switch (IO_METHOD_FROM_CTL_CODE(ioctl)) { + case METHOD_BUFFERED: + buf_len = max(input_buf_len, output_buf_len); + if (buf_len) { + irp->associated_irp.system_buffer = + ExAllocatePoolWithTag(NonPagedPool, buf_len, 0); + if (!irp->associated_irp.system_buffer) { + IoFreeIrp(irp); + IOEXIT(return NULL); + } + irp->associated_irp.system_buffer = input_buf; + if (input_buf) + memcpy(irp->associated_irp.system_buffer, + input_buf, input_buf_len); + irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + if (output_buf) + irp->flags = IRP_INPUT_OPERATION; + irp->user_buf = output_buf; + } else + irp->user_buf = NULL; + break; + case METHOD_IN_DIRECT: + case METHOD_OUT_DIRECT: + if (input_buf) { + irp->associated_irp.system_buffer = + ExAllocatePoolWithTag(NonPagedPool, + input_buf_len, 0); + if (!irp->associated_irp.system_buffer) { + IoFreeIrp(irp); + IOEXIT(return NULL); + } + memcpy(irp->associated_irp.system_buffer, + input_buf, input_buf_len); + irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + } + /* TODO: we are supposed to setup MDL, but USB layer + * doesn't use MDLs. Moreover, USB layer mirrors + * non-DMAable buffers, so no need to allocate + * DMAable buffer here */ + if (output_buf) { + irp->associated_irp.system_buffer = + ExAllocatePoolWithTag(NonPagedPool, + output_buf_len, 0); + if (!irp->associated_irp.system_buffer) { + IoFreeIrp(irp); + IOEXIT(return NULL); + } + irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + } + break; + case METHOD_NEITHER: + irp->user_buf = output_buf; + irp_sl->params.dev_ioctl.type3_input_buf = input_buf; + break; + } + + irp->user_status = io_status; + irp->user_event = event; + IoQueueThreadIrp(irp); + + IOTRACE("irp: %p", irp); + IOEXIT(return irp); +} + +wfastcall NTSTATUS WIN_FUNC(IofCallDriver,2) + (struct device_object *dev_obj, struct irp *irp) +{ + struct io_stack_location *irp_sl; + NTSTATUS status; + driver_dispatch_t *major_func; + struct driver_object *drv_obj; + + if (irp->current_location <= 0) { + ERROR("invalid irp: %p, %d", irp, irp->current_location); + return STATUS_INVALID_PARAMETER; + } + IOTRACE("%p, %p, %p, %d, %d, %p", dev_obj, irp, dev_obj->drv_obj, + irp->current_location, irp->stack_count, + IoGetCurrentIrpStackLocation(irp)); + IoSetNextIrpStackLocation(irp); + DUMP_IRP(irp); + irp_sl = IoGetCurrentIrpStackLocation(irp); + drv_obj = dev_obj->drv_obj; + irp_sl->dev_obj = dev_obj; + major_func = drv_obj->major_func[irp_sl->major_fn]; + IOTRACE("major_func: %p, dev_obj: %p", major_func, dev_obj); + if (major_func) + status = LIN2WIN2(major_func, dev_obj, irp); + else { + ERROR("major_function %d is not implemented", + irp_sl->major_fn); + status = STATUS_NOT_SUPPORTED; + } + IOEXIT(return status); +} + +wfastcall void WIN_FUNC(IofCompleteRequest,2) + (struct irp *irp, CHAR prio_boost) +{ + struct io_stack_location *irp_sl; + +#ifdef IO_DEBUG + DUMP_IRP(irp); + if (irp->io_status.status == STATUS_PENDING) { + ERROR("invalid irp: %p, STATUS_PENDING", irp); + return; + } + if (irp->current_location < 0 || + irp->current_location >= irp->stack_count) { + ERROR("invalid irp: %p, %d", irp, irp->current_location); + return; + } +#endif + for (irp_sl = IoGetCurrentIrpStackLocation(irp); + irp->current_location < irp->stack_count; irp_sl++) { + struct device_object *dev_obj; + NTSTATUS status; + + DUMP_IRP(irp); + if (irp_sl->control & SL_PENDING_RETURNED) + irp->pending_returned = TRUE; + + /* current_location and dev_obj must be same as when + * driver called IoSetCompletionRoutine, which sets + * completion routine at next (lower) location, which + * is what we are going to call below; so we set + * current_location and dev_obj for the previous + * (higher) location */ + IoSkipCurrentIrpStackLocation(irp); + if (irp->current_location < irp->stack_count) + dev_obj = IoGetCurrentIrpStackLocation(irp)->dev_obj; + else + dev_obj = NULL; + + IOTRACE("%d, %d, %p", irp->current_location, irp->stack_count, + dev_obj); + if (irp_sl->completion_routine && + ((irp->io_status.status == STATUS_SUCCESS && + irp_sl->control & SL_INVOKE_ON_SUCCESS) || + (irp->io_status.status != STATUS_SUCCESS && + irp_sl->control & SL_INVOKE_ON_ERROR) || + (irp->cancel == TRUE && + irp_sl->control & SL_INVOKE_ON_CANCEL))) { + IOTRACE("calling completion_routine at: %p, %p", + irp_sl->completion_routine, irp_sl->context); + status = LIN2WIN3(irp_sl->completion_routine, + dev_obj, irp, irp_sl->context); + IOTRACE("status: %08X", status); + if (status == STATUS_MORE_PROCESSING_REQUIRED) + IOEXIT(return); + } else { + /* propagate pending status to next irp_sl */ + if (irp->pending_returned && + irp->current_location < irp->stack_count) + IoMarkIrpPending(irp); + } + } + + if (irp->user_status) { + irp->user_status->status = irp->io_status.status; + irp->user_status->info = irp->io_status.info; + } + + if (irp->user_event) { + IOTRACE("setting event %p", irp->user_event); + KeSetEvent(irp->user_event, prio_boost, FALSE); + } + + if (irp->associated_irp.system_buffer && + (irp->flags & IRP_DEALLOCATE_BUFFER)) + ExFreePool(irp->associated_irp.system_buffer); + else { + struct mdl *mdl; + while ((mdl = irp->mdl)) { + irp->mdl = mdl->next; + MmUnlockPages(mdl); + IoFreeMdl(mdl); + } + } + IOTRACE("freeing irp %p", irp); + IoFreeIrp(irp); + IOEXIT(return); +} + +wstdcall NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp) +{ + IoSkipCurrentIrpStackLocation(irp); + IOEXIT(return IoCallDriver(dev_obj, irp)); +} + +wstdcall NTSTATUS IoIrpSyncComplete(struct device_object *dev_obj, + struct irp *irp, void *context) +{ + if (irp->pending_returned == TRUE) + KeSetEvent(context, IO_NO_INCREMENT, FALSE); + IOEXIT(return STATUS_MORE_PROCESSING_REQUIRED); +} +WIN_FUNC_DECL(IoIrpSyncComplete,3) + +wstdcall NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) +{ + struct nt_event event; + NTSTATUS status; + + IoCopyCurrentIrpStackLocationToNext(irp); + KeInitializeEvent(&event, SynchronizationEvent, FALSE); + /* completion function is called as Windows function */ + IoSetCompletionRoutine(irp, WIN_FUNC_PTR(IoIrpSyncComplete,3), &event, + TRUE, TRUE, TRUE); + status = IoCallDriver(dev_obj, irp); + IOTRACE("%08X", status); + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, + NULL); + status = irp->io_status.status; + } + IOTRACE("%08X", status); + IOEXIT(return status); +} +WIN_FUNC_DECL(IoSyncForwardIrp,2) + +wstdcall NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) +{ + NTSTATUS status; + + IoCopyCurrentIrpStackLocationToNext(irp); + status = IoCallDriver(dev_obj, irp); + IOEXIT(return status); +} +WIN_FUNC_DECL(IoAsyncForwardIrp,2) + +wstdcall NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj, + struct irp *irp) +{ + struct io_stack_location *irp_sl; + NTSTATUS status; + + irp_sl = IoGetCurrentIrpStackLocation(irp); + WARNING("%d:%d not implemented", irp_sl->major_fn, irp_sl->minor_fn); + irp->io_status.status = STATUS_SUCCESS; + irp->io_status.info = 0; + status = irp->io_status.status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + IOEXIT(return status); +} +WIN_FUNC_DECL(IoInvalidDeviceRequest,2) + +static irqreturn_t io_irq_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL) +{ + struct kinterrupt *interrupt = data; + BOOLEAN ret; + +#ifdef CONFIG_DEBUG_SHIRQ + if (!interrupt->u.enabled) + EXIT1(return IRQ_NONE); +#endif + TRACE6("%p", interrupt); + nt_spin_lock(interrupt->actual_lock); + ret = LIN2WIN2(interrupt->isr, interrupt, interrupt->isr_ctx); + nt_spin_unlock(interrupt->actual_lock); + if (ret == TRUE) + EXIT6(return IRQ_HANDLED); + else + EXIT6(return IRQ_NONE); +} + +wstdcall NTSTATUS WIN_FUNC(IoConnectInterrupt,11) + (struct kinterrupt **kinterrupt, PKSERVICE_ROUTINE isr, void *isr_ctx, + NT_SPIN_LOCK *lock, ULONG vector, KIRQL irql, KIRQL synch_irql, + enum kinterrupt_mode mode, BOOLEAN shared, KAFFINITY cpu_mask, + BOOLEAN save_fp) +{ + struct kinterrupt *interrupt; + IOENTER(""); + interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL); + if (!interrupt) + IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); + interrupt->vector = vector; + interrupt->cpu_mask = cpu_mask; + nt_spin_lock_init(&interrupt->lock); + if (lock) + interrupt->actual_lock = lock; + else + interrupt->actual_lock = &interrupt->lock; + interrupt->shared = shared; + interrupt->save_fp = save_fp; + interrupt->isr = isr; + interrupt->isr_ctx = isr_ctx; + InitializeListHead(&interrupt->list); + interrupt->irql = irql; + interrupt->synch_irql = synch_irql; + interrupt->mode = mode; + if (request_irq(vector, io_irq_isr, shared ? IRQF_SHARED : 0, + "ndiswrapper", interrupt)) { + WARNING("request for irq %d failed", vector); + kfree(interrupt); + IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); + } + *kinterrupt = interrupt; +#ifdef CONFIG_DEBUG_SHIRQ + interrupt->u.enabled = 1; +#endif + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(IoDisconnectInterrupt,1) + (struct kinterrupt *interrupt) +{ +#ifdef CONFIG_DEBUG_SHIRQ + interrupt->u.enabled = 0; +#endif + free_irq(interrupt->vector, interrupt); + kfree(interrupt); +} + +wstdcall struct mdl *WIN_FUNC(IoAllocateMdl,5) + (void *virt, ULONG length, BOOLEAN second_buf, BOOLEAN charge_quota, + struct irp *irp) +{ + struct mdl *mdl; + mdl = allocate_init_mdl(virt, length); + if (!mdl) + return NULL; + if (irp) { + if (second_buf == TRUE) { + struct mdl *last; + + last = irp->mdl; + while (last->next) + last = last->next; + last->next = mdl; + } else + irp->mdl = mdl; + } + IOTRACE("%p", mdl); + return mdl; +} + +wstdcall void WIN_FUNC(IoFreeMdl,1) + (struct mdl *mdl) +{ + IOTRACE("%p", mdl); + free_mdl(mdl); +} + +wstdcall struct io_workitem *WIN_FUNC(IoAllocateWorkItem,1) + (struct device_object *dev_obj) +{ + struct io_workitem *io_workitem; + + IOENTER("%p", dev_obj); + io_workitem = kmalloc(sizeof(*io_workitem), irql_gfp()); + if (!io_workitem) + IOEXIT(return NULL); + io_workitem->dev_obj = dev_obj; + IOEXIT(return io_workitem); +} + +wstdcall void WIN_FUNC(IoFreeWorkItem,1) + (struct io_workitem *io_workitem) +{ + kfree(io_workitem); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoQueueWorkItem,4) + (struct io_workitem *io_workitem, void *func, + enum work_queue_type queue_type, void *context) +{ + IOENTER("%p, %p", io_workitem, io_workitem->dev_obj); + io_workitem->worker_routine = func; + io_workitem->context = context; + schedule_ntos_work_item(func, io_workitem->dev_obj, context); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(ExQueueWorkItem,2) + (struct io_workitem *io_workitem, enum work_queue_type queue_type) +{ + IOENTER("%p", io_workitem); + schedule_ntos_work_item(io_workitem->worker_routine, + io_workitem->dev_obj, io_workitem->context); +} + +wstdcall NTSTATUS WIN_FUNC(IoAllocateDriverObjectExtension,4) + (struct driver_object *drv_obj, void *client_id, ULONG extlen, + void **ext) +{ + struct custom_ext *ce; + + IOENTER("%p, %p", drv_obj, client_id); + ce = kmalloc(sizeof(*ce) + extlen, irql_gfp()); + if (ce == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + IOTRACE("custom_ext: %p", ce); + ce->client_id = client_id; + spin_lock_bh(&ntoskernel_lock); + InsertTailList(&drv_obj->drv_ext->custom_ext, &ce->list); + spin_unlock_bh(&ntoskernel_lock); + + *ext = (void *)ce + sizeof(*ce); + IOTRACE("ext: %p", *ext); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall void *WIN_FUNC(IoGetDriverObjectExtension,2) + (struct driver_object *drv_obj, void *client_id) +{ + struct custom_ext *ce; + void *ret; + + IOENTER("drv_obj: %p, client_id: %p", drv_obj, client_id); + ret = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(ce, &drv_obj->drv_ext->custom_ext, list) { + if (ce->client_id == client_id) { + ret = (void *)ce + sizeof(*ce); + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + IOTRACE("ret: %p", ret); + return ret; +} + +void free_custom_extensions(struct driver_extension *drv_ext) +{ + struct nt_list *ent; + + IOENTER("%p", drv_ext); + spin_lock_bh(&ntoskernel_lock); + while ((ent = RemoveHeadList(&drv_ext->custom_ext))) + kfree(ent); + spin_unlock_bh(&ntoskernel_lock); + IOEXIT(return); +} + +wstdcall NTSTATUS WIN_FUNC(IoCreateDevice,7) + (struct driver_object *drv_obj, ULONG dev_ext_length, + struct unicode_string *dev_name, DEVICE_TYPE dev_type, + ULONG dev_chars, BOOLEAN exclusive, struct device_object **newdev) +{ + struct device_object *dev; + struct dev_obj_ext *dev_obj_ext; + int size; + + IOENTER("%p, %u, %p", drv_obj, dev_ext_length, dev_name); + + size = sizeof(*dev) + dev_ext_length + sizeof(*dev_obj_ext); + dev = allocate_object(size, OBJECT_TYPE_DEVICE, dev_name); + if (!dev) + IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); + if (dev_ext_length) + dev->dev_ext = dev + 1; + else + dev->dev_ext = NULL; + + dev_obj_ext = ((void *)(dev + 1)) + dev_ext_length; + dev_obj_ext->dev_obj = dev; + dev_obj_ext->size = 0; + dev_obj_ext->type = IO_TYPE_DEVICE; + dev->dev_obj_ext = dev_obj_ext; + + dev->type = dev_type; + dev->flags = 0; + dev->size = sizeof(*dev) + dev_ext_length; + dev->ref_count = 1; + dev->attached = NULL; + dev->stack_count = 1; + + dev->drv_obj = drv_obj; + dev->next = drv_obj->dev_obj; + drv_obj->dev_obj = dev; + + dev->align_req = 1; + dev->characteristics = dev_chars; + dev->io_timer = NULL; + KeInitializeEvent(&dev->lock, SynchronizationEvent, TRUE); + dev->vpb = NULL; + + IOTRACE("dev: %p, ext: %p", dev, dev->dev_ext); + *newdev = dev; + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoCreateUnprotectedSymbolicLink,2) + (struct unicode_string *link, struct unicode_string *dev_name) +{ + struct ansi_string ansi; + + IOENTER("%p, %p", dev_name, link); + if (dev_name && (RtlUnicodeStringToAnsiString(&ansi, dev_name, TRUE) == + STATUS_SUCCESS)) { + IOTRACE("dev_name: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) == + STATUS_SUCCESS)) { + IOTRACE("link: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } +// TODO(); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoCreateSymbolicLink,2) + (struct unicode_string *link, struct unicode_string *dev_name) +{ + IOEXIT(return IoCreateUnprotectedSymbolicLink(link, dev_name)); +} + +wstdcall NTSTATUS WIN_FUNC(IoDeleteSymbolicLink,1) + (struct unicode_string *link) +{ + struct ansi_string ansi; + + IOENTER("%p", link); + if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) == + STATUS_SUCCESS)) { + IOTRACE("dev_name: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(IoDeleteDevice,1) + (struct device_object *dev) +{ + IOENTER("%p", dev); + if (dev == NULL) + IOEXIT(return); + IOTRACE("drv_obj: %p", dev->drv_obj); + if (dev->drv_obj) { + struct device_object *prev; + + prev = dev->drv_obj->dev_obj; + IOTRACE("dev_obj: %p", prev); + if (prev == dev) + dev->drv_obj->dev_obj = dev->next; + else if (prev) { + while (prev->next != dev) + prev = prev->next; + prev->next = dev->next; + } + } + ObDereferenceObject(dev); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoDetachDevice,1) + (struct device_object *tgt) +{ + struct device_object *tail; + + IOENTER("%p", tgt); + if (!tgt) + IOEXIT(return); + tail = tgt->attached; + if (!tail) + IOEXIT(return); + IOTRACE("tail: %p", tail); + + spin_lock_bh(&ntoskernel_lock); + tgt->attached = tail->attached; + IOTRACE("attached:%p", tgt->attached); + for ( ; tail; tail = tail->attached) { + IOTRACE("tail:%p", tail); + tail->stack_count--; + } + spin_unlock_bh(&ntoskernel_lock); + IOEXIT(return); +} + +wstdcall struct device_object *WIN_FUNC(IoGetAttachedDevice,1) + (struct device_object *dev) +{ + IOENTER("%p", dev); + if (!dev) + IOEXIT(return NULL); + spin_lock_bh(&ntoskernel_lock); + while (dev->attached) + dev = dev->attached; + spin_unlock_bh(&ntoskernel_lock); + IOEXIT(return dev); +} + +wstdcall struct device_object *WIN_FUNC(IoGetAttachedDeviceReference,1) + (struct device_object *dev) +{ + IOENTER("%p", dev); + if (!dev) + IOEXIT(return NULL); + dev = IoGetAttachedDevice(dev); + ObReferenceObject(dev); + IOEXIT(return dev); +} + +wstdcall struct device_object *WIN_FUNC(IoAttachDeviceToDeviceStack,2) + (struct device_object *src, struct device_object *tgt) +{ + struct device_object *attached; + struct dev_obj_ext *src_dev_ext; + + IOENTER("%p, %p", src, tgt); + attached = IoGetAttachedDevice(tgt); + IOTRACE("%p", attached); + src_dev_ext = src->dev_obj_ext; + spin_lock_bh(&ntoskernel_lock); + if (attached) + attached->attached = src; + src->attached = NULL; + src->stack_count = attached->stack_count + 1; + src_dev_ext->attached_to = attached; + spin_unlock_bh(&ntoskernel_lock); + IOTRACE("stack_count: %d -> %d", attached->stack_count, + src->stack_count); + IOEXIT(return attached); +} + +wstdcall NTSTATUS WIN_FUNC(IoGetDeviceProperty,5) + (struct device_object *pdo, enum device_registry_property dev_property, + ULONG buffer_len, void *buffer, ULONG *result_len) +{ + struct ansi_string ansi; + struct unicode_string unicode; + struct wrap_device *wd; + ULONG need; + + IOENTER("dev_obj = %p, dev_property = %d, buffer_len = %u, " + "buffer = %p, result_len = %p", pdo, dev_property, + buffer_len, buffer, result_len); + + wd = pdo->reserved; + switch (dev_property) { + case DevicePropertyDeviceDescription: + case DevicePropertyFriendlyName: + case DevicePropertyDriverKeyName: + if (wrap_is_pci_bus(wd->dev_bus)) + RtlInitAnsiString(&ansi, "PCI"); + else // if (wrap_is_usb_bus(wd->dev_bus)) + RtlInitAnsiString(&ansi, "USB"); + need = sizeof(wchar_t) * (ansi.max_length + 1); + if (buffer_len < need) { + *result_len = need; + IOEXIT(return STATUS_BUFFER_TOO_SMALL); + } + unicode.max_length = buffer_len; + unicode.buf = buffer; + if (RtlAnsiStringToUnicodeString(&unicode, &ansi, + FALSE) != STATUS_SUCCESS) { + *result_len = unicode.length; + IOEXIT(return STATUS_BUFFER_TOO_SMALL); + } + IOEXIT(return STATUS_SUCCESS); + default: + WARNING("%d not implemented", dev_property); + IOEXIT(return STATUS_INVALID_PARAMETER_2); + } +} + +wstdcall NTSTATUS WIN_FUNC(IoGetDeviceObjectPointer,4) + (struct unicode_string *name, ACCESS_MASK desired_access, + void *file_obj, struct device_object *dev_obj) +{ + struct common_object_header *coh; + + dev_obj = NULL; + /* TODO: access is not checked and file_obj is set to NULL */ + file_obj = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(coh, &object_list, list) { + TRACE5("header: %p, type: %d", coh, coh->type); + if (coh->type != OBJECT_TYPE_DEVICE) + continue; + if (!RtlCompareUnicodeString(&coh->name, name, TRUE)) { + dev_obj = HEADER_TO_OBJECT(coh); + TRACE5("dev_obj: %p", dev_obj); + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + if (dev_obj) + IOEXIT(return STATUS_SUCCESS); + else + IOEXIT(return STATUS_OBJECT_NAME_INVALID); +} + +/* NOTE: Make sure to compile with -freg-struct-return, so gcc will + * return union in register, like Windows */ +wstdcall union power_state WIN_FUNC(PoSetPowerState,3) + (struct device_object *dev_obj, enum power_state_type type, + union power_state state) +{ + IOEXIT(return state); +} + +wstdcall NTSTATUS WIN_FUNC(PoCallDriver,2) + (struct device_object *dev_obj, struct irp *irp) +{ + return IoCallDriver(dev_obj, irp); +} + +wstdcall NTSTATUS WIN_FUNC(PoRequestPowerIrp,6) + (struct device_object *dev_obj, UCHAR minor_fn, + union power_state power_state, void *completion_func, + void *context, struct irp **pirp) +{ + struct irp *irp; + struct io_stack_location *irp_sl; + + TRACE1("%p, %d, %p", dev_obj, dev_obj->stack_count, dev_obj->drv_obj); + irp = IoAllocateIrp(dev_obj->stack_count, FALSE); + if (!irp) + return STATUS_INSUFFICIENT_RESOURCES; + irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->major_fn = IRP_MJ_POWER; + irp_sl->minor_fn = minor_fn; + if (minor_fn == IRP_MN_WAIT_WAKE) + irp_sl->params.power.type = SystemPowerState; + else + irp_sl->params.power.type = DevicePowerState; + irp_sl->params.power.state = power_state; + irp_sl->completion_routine = completion_func; + irp->io_status.status = STATUS_NOT_SUPPORTED; + *pirp = irp; + return PoCallDriver(dev_obj, irp); +} + +wstdcall void WIN_FUNC(PoStartNextPowerIrp,1) + (struct irp *irp) +{ + IOENTER("irp = %p", irp); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoInitializeRemoveLockEx,5) + (struct io_remove_lock *lock, ULONG alloc_tag, ULONG max_locked_min, + ULONG high_mark, ULONG lock_size) +{ + TODO(); +} + +wstdcall void *WIN_FUNC(IoAllocateErrorLogEntry,2) + (void *io_object, UCHAR entry_size) +{ + /* not implemented fully */ + void *ret = kmalloc(sizeof(struct io_error_log_packet) + entry_size, + irql_gfp()); + TRACE2("%p", ret); + if (ret) + return ret + sizeof(struct io_error_log_packet); + else + return NULL; +} + +wstdcall void WIN_FUNC(IoWriteErrorLogEntry,1) + (void *entry) +{ + /* TODO: log error with codes and message */ + ERROR(""); +} + +wstdcall void WIN_FUNC(IoFreeErrorLogEntry,1) + (void *entry) +{ + TRACE2("%p", entry); + kfree(entry - sizeof(struct io_error_log_packet)); +} + +wstdcall NTSTATUS WIN_FUNC(IoAcquireRemoveLockEx,5) + (struct io_remove_lock lock, void *tag, char *file, ULONG line, + ULONG lock_size) +{ + TODO(); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoReleaseRemoveLockEx,3) + (struct io_remove_lock lock, void *tag, ULONG lock_size) +{ + TODO(); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoRegisterDeviceInterface,4) + (struct device_object *pdo, struct guid *guid_class, + struct unicode_string *reference, struct unicode_string *link) +{ + struct ansi_string ansi; + + /* TODO: check if pdo is valid */ + RtlInitAnsiString(&ansi, "ndis"); + ENTER1("pdo: %p, ref: %p, link: %p, %x, %x, %x", pdo, reference, link, + guid_class->data1, guid_class->data2, guid_class->data3); + return RtlAnsiStringToUnicodeString(link, &ansi, TRUE); +} + +wstdcall NTSTATUS WIN_FUNC(IoSetDeviceInterfaceState,2) + (struct unicode_string *link, BOOLEAN enable) +{ + ENTER1("link: %p, enable: %d", link, enable); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(IoOpenDeviceRegistryKey,4) + (struct device_object *dev_obj, ULONG type, ACCESS_MASK mask, + void **handle) +{ + ENTER1("dev_obj: %p", dev_obj); + *handle = dev_obj; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(IoWMIRegistrationControl,2) + (struct device_object *dev_obj, ULONG action) +{ + ENTER2("%p, %d", dev_obj, action); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(IoInvalidateDeviceRelations,2) + (struct device_object *dev_obj, enum device_relation_type type) +{ + INFO("%p, %d", dev_obj, type); + TODO(); +} + +wstdcall void WIN_FUNC(IoInvalidateDeviceState,1) + (struct device_object *pdo) +{ + INFO("%p", pdo); + TODO(); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/proc.c +++ linux-2.6.27/ubuntu/ndiswrapper/proc.c @@ -0,0 +1,565 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include + +#include "ndis.h" +#include "iw_ndis.h" +#include "wrapndis.h" +#include "pnp.h" +#include "wrapper.h" + +#define MAX_PROC_STR_LEN 32 + +static struct proc_dir_entry *wrap_procfs_entry; + +static int procfs_read_ndis_stats(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + struct ndis_wireless_stats stats; + NDIS_STATUS res; + ndis_rssi rssi; + + if (off != 0) { + *eof = 1; + return 0; + } + + res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi)); + if (!res) + p += sprintf(p, "signal_level=%d dBm\n", (s32)rssi); + + res = mp_query(wnd, OID_802_11_STATISTICS, &stats, sizeof(stats)); + if (!res) { + + p += sprintf(p, "tx_frames=%Lu\n", stats.tx_frag); + p += sprintf(p, "tx_multicast_frames=%Lu\n", + stats.tx_multi_frag); + p += sprintf(p, "tx_failed=%Lu\n", stats.failed); + p += sprintf(p, "tx_retry=%Lu\n", stats.retry); + p += sprintf(p, "tx_multi_rerty=%Lu\n", stats.multi_retry); + p += sprintf(p, "tx_rtss_success=%Lu\n", stats.rtss_succ); + p += sprintf(p, "tx_rtss_fail=%Lu\n", stats.rtss_fail); + p += sprintf(p, "ack_fail=%Lu\n", stats.ack_fail); + p += sprintf(p, "frame_duplicates=%Lu\n", stats.frame_dup); + p += sprintf(p, "rx_frames=%Lu\n", stats.rx_frag); + p += sprintf(p, "rx_multicast_frames=%Lu\n", + stats.rx_multi_frag); + p += sprintf(p, "fcs_errors=%Lu\n", stats.fcs_err); + } + + if (p - page > count) { + ERROR("wrote %lu bytes (limit is %u)\n", + (unsigned long)(p - page), count); + *eof = 1; + } + + return (p - page); +} + +static int procfs_read_ndis_encr(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + int i, encr_status, auth_mode, infra_mode; + NDIS_STATUS res; + struct ndis_essid essid; + mac_address ap_address; + + if (off != 0) { + *eof = 1; + return 0; + } + + res = mp_query(wnd, OID_802_11_BSSID, + &ap_address, sizeof(ap_address)); + if (res) + memset(ap_address, 0, ETH_ALEN); + p += sprintf(p, "ap_address=%2.2X", ap_address[0]); + for (i = 1 ; i < ETH_ALEN ; i++) + p += sprintf(p, ":%2.2X", ap_address[i]); + p += sprintf(p, "\n"); + + res = mp_query(wnd, OID_802_11_SSID, &essid, sizeof(essid)); + if (!res) + p += sprintf(p, "essid=%.*s\n", essid.length, essid.essid); + + res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &encr_status); + if (!res) { + typeof(&wnd->encr_info.keys[0]) tx_key; + p += sprintf(p, "tx_key=%u\n", wnd->encr_info.tx_key_index); + p += sprintf(p, "key="); + tx_key = &wnd->encr_info.keys[wnd->encr_info.tx_key_index]; + if (tx_key->length > 0) + for (i = 0; i < tx_key->length; i++) + p += sprintf(p, "%2.2X", tx_key->key[i]); + else + p += sprintf(p, "off"); + p += sprintf(p, "\n"); + p += sprintf(p, "encr_mode=%d\n", encr_status); + } + res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &auth_mode); + if (!res) + p += sprintf(p, "auth_mode=%d\n", auth_mode); + res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &infra_mode); + p += sprintf(p, "mode=%s\n", (infra_mode == Ndis802_11IBSS) ? + "adhoc" : (infra_mode == Ndis802_11Infrastructure) ? + "managed" : "auto"); + if (p - page > count) { + WARNING("wrote %lu bytes (limit is %u)", + (unsigned long)(p - page), count); + *eof = 1; + } + + return (p - page); +} + +static int procfs_read_ndis_hw(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + struct ndis_configuration config; + unsigned int power_mode; + NDIS_STATUS res; + ndis_tx_power_level tx_power; + ULONG bit_rate; + ndis_rts_threshold rts_threshold; + ndis_fragmentation_threshold frag_threshold; + ndis_antenna antenna; + ULONG packet_filter; + int n; + mac_address mac; + char *hw_status[] = {"ready", "initializing", "resetting", "closing", + "not ready"}; + + if (off != 0) { + *eof = 1; + return 0; + } + + res = mp_query_int(wnd, OID_GEN_HARDWARE_STATUS, &n); + if (res == NDIS_STATUS_SUCCESS && + n >= 0 && n < sizeof(hw_status) / sizeof(hw_status[0])) + p += sprintf(p, "status=%s\n", hw_status[n]); + + res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac)); + if (!res) + p += sprintf(p, "mac: " MACSTRSEP "\n", MAC2STR(mac)); + res = mp_query(wnd, OID_802_11_CONFIGURATION, &config, sizeof(config)); + if (!res) { + p += sprintf(p, "beacon_period=%u msec\n", + config.beacon_period); + p += sprintf(p, "atim_window=%u msec\n", config.atim_window); + p += sprintf(p, "frequency=%u kHZ\n", config.ds_config); + p += sprintf(p, "hop_pattern=%u\n", + config.fh_config.hop_pattern); + p += sprintf(p, "hop_set=%u\n", + config.fh_config.hop_set); + p += sprintf(p, "dwell_time=%u msec\n", + config.fh_config.dwell_time); + } + + res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL, + &tx_power, sizeof(tx_power)); + if (!res) + p += sprintf(p, "tx_power=%u mW\n", tx_power); + + res = mp_query(wnd, OID_GEN_LINK_SPEED, &bit_rate, sizeof(bit_rate)); + if (!res) + p += sprintf(p, "bit_rate=%u kBps\n", (u32)bit_rate / 10); + + res = mp_query(wnd, OID_802_11_RTS_THRESHOLD, + &rts_threshold, sizeof(rts_threshold)); + if (!res) + p += sprintf(p, "rts_threshold=%u bytes\n", rts_threshold); + + res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, + &frag_threshold, sizeof(frag_threshold)); + if (!res) + p += sprintf(p, "frag_threshold=%u bytes\n", frag_threshold); + + res = mp_query_int(wnd, OID_802_11_POWER_MODE, &power_mode); + if (!res) + p += sprintf(p, "power_mode=%s\n", + (power_mode == NDIS_POWER_OFF) ? "always_on" : + (power_mode == NDIS_POWER_MAX) ? + "max_savings" : "min_savings"); + + res = mp_query(wnd, OID_802_11_NUMBER_OF_ANTENNAS, + &antenna, sizeof(antenna)); + if (!res) + p += sprintf(p, "num_antennas=%u\n", antenna); + + res = mp_query(wnd, OID_802_11_TX_ANTENNA_SELECTED, + &antenna, sizeof(antenna)); + if (!res) + p += sprintf(p, "tx_antenna=%u\n", antenna); + + res = mp_query(wnd, OID_802_11_RX_ANTENNA_SELECTED, + &antenna, sizeof(antenna)); + if (!res) + p += sprintf(p, "rx_antenna=%u\n", antenna); + + p += sprintf(p, "encryption_modes=%s%s%s%s%s%s%s\n", + test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ? + "WEP" : "none", + + test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ? + "; TKIP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : "", + + test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ? + "; AES/CCMP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : ""); + + res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter); + if (!res) { + if (packet_filter != wnd->packet_filter) + WARNING("wrong packet_filter? 0x%08x, 0x%08x\n", + packet_filter, wnd->packet_filter); + p += sprintf(p, "packet_filter: 0x%08x\n", packet_filter); + } + if (p - page > count) { + WARNING("wrote %lu bytes (limit is %u)", + (unsigned long)(p - page), count); + *eof = 1; + } + + return (p - page); +} + +static int procfs_read_ndis_settings(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + struct wrap_device_setting *setting; + + if (off != 0) { + *eof = 1; + return 0; + } + + p += sprintf(p, "hangcheck_interval=%d\n", + hangcheck_interval == 0 ? + (int)(wnd->hangcheck_interval / HZ) : -1); + + list_for_each_entry(setting, &wnd->wd->settings, list) { + p += sprintf(p, "%s=%s\n", setting->name, setting->value); + } + + list_for_each_entry(setting, &wnd->wd->driver->settings, list) { + p += sprintf(p, "%s=%s\n", setting->name, setting->value); + } + + return (p - page); +} + +static int procfs_write_ndis_settings(struct file *file, const char __user *buf, + unsigned long count, void *data) +{ + struct ndis_device *wnd = (struct ndis_device *)data; + char setting[MAX_PROC_STR_LEN], *p; + unsigned int i; + NDIS_STATUS res; + + if (count > MAX_PROC_STR_LEN) + return -EINVAL; + + memset(setting, 0, sizeof(setting)); + if (copy_from_user(setting, buf, count)) + return -EFAULT; + + if ((p = strchr(setting, '\n'))) + *p = 0; + + if ((p = strchr(setting, '='))) + *p = 0; + + if (!strcmp(setting, "hangcheck_interval")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + hangcheck_del(wnd); + if (i > 0) { + wnd->hangcheck_interval = i * HZ; + hangcheck_add(wnd); + } + } else if (!strcmp(setting, "suspend")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + if (i <= 0 || i > 3) + return -EINVAL; + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + i = wrap_pnp_suspend_pci_device(wnd->wd->pci.pdev, + PMSG_SUSPEND); + else +#ifdef ENABLE_USB + i = wrap_pnp_suspend_usb_device(wnd->wd->usb.intf, + PMSG_SUSPEND); +#else + i = -1; +#endif + if (i) + return -EINVAL; + } else if (!strcmp(setting, "resume")) { + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + i = wrap_pnp_resume_pci_device(wnd->wd->pci.pdev); + else +#ifdef ENABLE_USB + i = wrap_pnp_resume_usb_device(wnd->wd->usb.intf); +#else + i = -1; +#endif + if (i) + return -EINVAL; + } else if (!strcmp(setting, "stats_enabled")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + if (i > 0) + wnd->iw_stats_enabled = TRUE; + else + wnd->iw_stats_enabled = FALSE; + } else if (!strcmp(setting, "packet_filter")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, i); + if (res) + WARNING("setting packet_filter failed: %08X", res); + } else if (!strcmp(setting, "reinit")) { + if (ndis_reinit(wnd) != NDIS_STATUS_SUCCESS) + return -EFAULT; + } else { + struct ndis_configuration_parameter param; + struct unicode_string key; + struct ansi_string ansi; + + if (!p) + return -EINVAL; + p++; + RtlInitAnsiString(&ansi, p); + if (RtlAnsiStringToUnicodeString(¶m.data.string, &ansi, + TRUE) != STATUS_SUCCESS) + EXIT1(return -EFAULT); + param.type = NdisParameterString; + RtlInitAnsiString(&ansi, setting); + if (RtlAnsiStringToUnicodeString(&key, &ansi, + TRUE) != STATUS_SUCCESS) { + RtlFreeUnicodeString(¶m.data.string); + EXIT1(return -EINVAL); + } + NdisWriteConfiguration(&res, wnd->nmb, &key, ¶m); + RtlFreeUnicodeString(&key); + RtlFreeUnicodeString(¶m.data.string); + if (res != NDIS_STATUS_SUCCESS) + return -EFAULT; + } + return count; +} + +int wrap_procfs_add_ndis_device(struct ndis_device *wnd) +{ + struct proc_dir_entry *procfs_entry; + + if (wrap_procfs_entry == NULL) + return -ENOMEM; + + if (wnd->procfs_iface) { + ERROR("%s already registered?", wnd->netdev_name); + return -EINVAL; + } + wnd->procfs_iface = proc_mkdir(wnd->netdev_name, wrap_procfs_entry); + if (wnd->procfs_iface == NULL) { + ERROR("couldn't create proc directory"); + return -ENOMEM; + } + wnd->procfs_iface->uid = proc_uid; + wnd->procfs_iface->gid = proc_gid; + + procfs_entry = create_proc_entry("hw", S_IFREG | S_IRUSR | S_IRGRP, + wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'hw'"); + goto err_hw; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_hw; + } + + procfs_entry = create_proc_entry("stats", S_IFREG | S_IRUSR | S_IRGRP, + wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'stats'"); + goto err_stats; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_stats; + } + + procfs_entry = create_proc_entry("encr", S_IFREG | S_IRUSR | S_IRGRP, + wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'encr'"); + goto err_encr; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_encr; + } + + procfs_entry = create_proc_entry("settings", S_IFREG | + S_IRUSR | S_IRGRP | + S_IWUSR | S_IWGRP, wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'settings'"); + goto err_settings; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_settings; + procfs_entry->write_proc = procfs_write_ndis_settings; + } + return 0; + +err_settings: + remove_proc_entry("encr", wnd->procfs_iface); +err_encr: + remove_proc_entry("stats", wnd->procfs_iface); +err_stats: + remove_proc_entry("hw", wnd->procfs_iface); +err_hw: + remove_proc_entry(wnd->netdev_name, wrap_procfs_entry); + wnd->procfs_iface = NULL; + return -ENOMEM; +} + +void wrap_procfs_remove_ndis_device(struct ndis_device *wnd) +{ + struct proc_dir_entry *procfs_iface = xchg(&wnd->procfs_iface, NULL); + + if (procfs_iface == NULL) + return; + remove_proc_entry("hw", procfs_iface); + remove_proc_entry("stats", procfs_iface); + remove_proc_entry("encr", procfs_iface); + remove_proc_entry("settings", procfs_iface); + if (wrap_procfs_entry) + remove_proc_entry(wnd->netdev_name, wrap_procfs_entry); +} + +static int procfs_read_debug(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + enum alloc_type type; + + if (off != 0) { + *eof = 1; + return 0; + } + p += sprintf(p, "%d\n", debug); + type = 0; +#ifdef ALLOC_DEBUG + for (type = 0; type < ALLOC_TYPE_MAX; type++) + p += sprintf(p, "total size of allocations in %d: %d\n", + type, alloc_size(type)); +#endif + return (p - page); +} + +static int procfs_write_debug(struct file *file, const char __user *buf, + unsigned long count, void *data) +{ + int i; + char setting[MAX_PROC_STR_LEN], *p; + + if (count > MAX_PROC_STR_LEN) + return -EINVAL; + + memset(setting, 0, sizeof(setting)); + if (copy_from_user(setting, buf, count)) + return -EFAULT; + + if ((p = strchr(setting, '\n'))) + *p = 0; + + if ((p = strchr(setting, '='))) + *p = 0; + + i = simple_strtol(setting, NULL, 10); + if (i >= 0 && i < 10) + debug = i; + else + return -EINVAL; + return count; +} + +int wrap_procfs_init(void) +{ + struct proc_dir_entry *procfs_entry; + + wrap_procfs_entry = proc_mkdir(DRIVER_NAME, proc_net_root); + if (wrap_procfs_entry == NULL) { + ERROR("couldn't create procfs directory"); + return -ENOMEM; + } + wrap_procfs_entry->uid = proc_uid; + wrap_procfs_entry->gid = proc_gid; + + procfs_entry = create_proc_entry("debug", S_IFREG | S_IRUSR | S_IRGRP, + wrap_procfs_entry); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'debug'"); + return -ENOMEM; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->read_proc = procfs_read_debug; + procfs_entry->write_proc = procfs_write_debug; + } + return 0; +} + +void wrap_procfs_remove(void) +{ + if (wrap_procfs_entry == NULL) + return; + remove_proc_entry("debug", wrap_procfs_entry); + remove_proc_entry(DRIVER_NAME, proc_net_root); +} --- linux-2.6.27.orig/ubuntu/ndiswrapper/iw_ndis.h +++ linux-2.6.27/ubuntu/ndiswrapper/iw_ndis.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _IW_NDIS_H_ +#define _IW_NDIS_H_ + +#include "ndis.h" + +#define WL_NOISE -96 /* typical noise level in dBm */ +#define WL_SIGMAX -32 /* typical maximum signal level in dBm */ + +struct ndis_encr_key { + ULONG struct_size; + ULONG index; + ULONG length; + UCHAR key[NDIS_ENCODING_TOKEN_MAX]; +}; + +struct ndis_add_key { + ULONG struct_size; + ndis_key_index index; + ULONG length; + mac_address bssid; + UCHAR pad[6]; + ndis_key_rsc rsc; + UCHAR key[NDIS_ENCODING_TOKEN_MAX]; +}; + +struct ndis_remove_key { + ULONG struct_size; + ndis_key_index index; + mac_address bssid; +}; + +struct ndis_fixed_ies { + UCHAR time_stamp[8]; + USHORT beacon_interval; + USHORT capa; +}; + +struct ndis_variable_ies { + ULONG elem_id; + UCHAR length; + UCHAR data[1]; +}; + +enum ndis_reload_defaults { Ndis802_11ReloadWEPKeys }; + +struct ndis_assoc_info { + ULONG length; + USHORT req_ies; + struct req_ie { + USHORT capa; + USHORT listen_interval; + mac_address cur_ap_address; + } req_ie; + ULONG req_ie_length; + ULONG offset_req_ies; + USHORT resp_ies; + struct resp_ie { + USHORT capa; + USHORT status_code; + USHORT assoc_id; + } resp_ie; + ULONG resp_ie_length; + ULONG offset_resp_ies; +}; + +struct ndis_configuration_fh { + ULONG length; + ULONG hop_pattern; + ULONG hop_set; + ULONG dwell_time; +}; + +struct ndis_configuration { + ULONG length; + ULONG beacon_period; + ULONG atim_window; + ULONG ds_config; + struct ndis_configuration_fh fh_config; +}; + +struct ndis_wlan_bssid { + ULONG length; + mac_address mac; + UCHAR reserved[2]; + struct ndis_essid ssid; + ULONG privacy; + ndis_rssi rssi; + UINT net_type; + struct ndis_configuration config; + UINT mode; + ndis_rates rates; +}; + +struct ndis_wlan_bssid_ex { + ULONG length; + mac_address mac; + UCHAR reserved[2]; + struct ndis_essid ssid; + ULONG privacy; + ndis_rssi rssi; + UINT net_type; + struct ndis_configuration config; + UINT mode; + ndis_rates_ex rates_ex; + ULONG ie_length; + UCHAR ies[1]; +}; + +/* we use bssid_list as bssid_list_ex also */ +struct ndis_bssid_list { + ULONG num_items; + struct ndis_wlan_bssid bssid[1]; +}; + +enum ndis_priv_filter { + Ndis802_11PrivFilterAcceptAll, Ndis802_11PrivFilter8021xWEP +}; + +enum network_type { + Ndis802_11FH, Ndis802_11DS, Ndis802_11OFDM5, Ndis802_11OFDM24, + /* MSDN site uses Ndis802_11Automode, which is not mentioned + * in DDK, so add one and assign it to + * Ndis802_11NetworkTypeMax */ + Ndis802_11Automode, Ndis802_11NetworkTypeMax = Ndis802_11Automode +}; + +struct network_type_list { + ULONG num; + enum network_type types[1]; +}; + +enum ndis_power { + NDIS_POWER_OFF = 0, NDIS_POWER_MAX, NDIS_POWER_MIN, +}; + +struct ndis_auth_req { + ULONG length; + mac_address bssid; + ULONG flags; +}; + +struct ndis_bssid_info { + mac_address bssid; + ndis_pmkid_vavlue pmkid; +}; + +struct ndis_pmkid { + ULONG length; + ULONG bssid_info_count; + struct ndis_bssid_info bssid_info[1]; +}; + +int add_wep_key(struct ndis_device *wnd, char *key, int key_len, + int index); +int set_essid(struct ndis_device *wnd, const char *ssid, int ssid_len); +int set_infra_mode(struct ndis_device *wnd, + enum ndis_infrastructure_mode mode); +int get_ap_address(struct ndis_device *wnd, mac_address mac); +int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode); +int set_iw_auth_mode(struct ndis_device *wnd, int wpa_version, + int auth_80211_alg); +int set_auth_mode(struct ndis_device *wnd); +int set_ndis_encr_mode(struct ndis_device *wnd, int cipher_pairwise, + int cipher_groupwise); +int get_ndis_encr_mode(struct ndis_device *wnd); +int set_encr_mode(struct ndis_device *wnd); +int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise, + int cipher_groupwise); +int get_ndis_auth_mode(struct ndis_device *wnd); +int set_priv_filter(struct ndis_device *wnd); +int set_scan(struct ndis_device *wnd); +NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid); +void set_default_iw_params(struct ndis_device *wnd); +extern const struct iw_handler_def ndis_handler_def; + +#define PRIV_RESET SIOCIWFIRSTPRIV+16 +#define PRIV_POWER_PROFILE SIOCIWFIRSTPRIV+17 +#define PRIV_NETWORK_TYPE SIOCIWFIRSTPRIV+18 +#define PRIV_DEAUTHENTICATE SIOCIWFIRSTPRIV+19 +#define PRIV_MEDIA_STREAM_MODE SIOCIWFIRSTPRIV+20 +#define PRIV_RELOAD_DEFAULTS SIOCIWFIRSTPRIV+23 + +#define RSN_INFO_ELEM 0x30 + +/* these have to match what is in wpa_supplicant */ + +typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; +typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, + CIPHER_WEP104 } wpa_cipher; +typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, + KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt; + +#endif // IW_NDIS_H --- linux-2.6.27.orig/ubuntu/ndiswrapper/usb.h +++ linux-2.6.27/ubuntu/ndiswrapper/usb.h @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2004 Jan Kiszka + * Copyright (C) 2005 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _USB_H_ +#define _USB_H_ + +#include "ntoskernel.h" + +#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003 +#define IOCTL_INTERNAL_USB_RESET_PORT 0x00220007 +#define IOCTL_INTERNAL_USB_GET_PORT_STATUS 0x00220013 +#define IOCTL_INTERNAL_USB_CYCLE_PORT 0x0022001F +#define IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION 0x00220027 + +#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000 +#define URB_FUNCTION_SELECT_INTERFACE 0x0001 +#define URB_FUNCTION_ABORT_PIPE 0x0002 +#define URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL 0x0003 +#define URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL 0x0004 +#define URB_FUNCTION_GET_FRAME_LENGTH 0x0005 +#define URB_FUNCTION_SET_FRAME_LENGTH 0x0006 +#define URB_FUNCTION_GET_CURRENT_FRAME_NUMBER 0x0007 +#define URB_FUNCTION_CONTROL_TRANSFER 0x0008 +#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER 0x0009 +#define URB_FUNCTION_ISOCH_TRANSFER 0x000A +#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 0x000B +#define URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE 0x000C +#define URB_FUNCTION_SET_FEATURE_TO_DEVICE 0x000D +#define URB_FUNCTION_SET_FEATURE_TO_INTERFACE 0x000E +#define URB_FUNCTION_SET_FEATURE_TO_ENDPOINT 0x000F +#define URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE 0x0010 +#define URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE 0x0011 +#define URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT 0x0012 +#define URB_FUNCTION_GET_STATUS_FROM_DEVICE 0x0013 +#define URB_FUNCTION_GET_STATUS_FROM_INTERFACE 0x0014 +#define URB_FUNCTION_GET_STATUS_FROM_ENDPOINT 0x0015 +#define URB_FUNCTION_RESERVED_0X0016 0x0016 +#define URB_FUNCTION_VENDOR_DEVICE 0x0017 +#define URB_FUNCTION_VENDOR_INTERFACE 0x0018 +#define URB_FUNCTION_VENDOR_ENDPOINT 0x0019 +#define URB_FUNCTION_CLASS_DEVICE 0x001A +#define URB_FUNCTION_CLASS_INTERFACE 0x001B +#define URB_FUNCTION_CLASS_ENDPOINT 0x001C +#define URB_FUNCTION_RESERVE_0X001D 0x001D +#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL 0x001E +#define URB_FUNCTION_CLASS_OTHER 0x001F +#define URB_FUNCTION_VENDOR_OTHER 0x0020 +#define URB_FUNCTION_GET_STATUS_FROM_OTHER 0x0021 +#define URB_FUNCTION_CLEAR_FEATURE_TO_OTHER 0x0022 +#define URB_FUNCTION_SET_FEATURE_TO_OTHER 0x0023 +#define URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT 0x0024 +#define URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT 0x0025 +#define URB_FUNCTION_GET_CONFIGURATION 0x0026 +#define URB_FUNCTION_GET_INTERFACE 0x0027 +#define URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE 0x0028 +#define URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE 0x0029 +#define URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR 0x002A +#define URB_FUNCTION_RESERVE_0X002B 0x002B +#define URB_FUNCTION_RESERVE_0X002C 0x002C +#define URB_FUNCTION_RESERVE_0X002D 0x002D +#define URB_FUNCTION_RESERVE_0X002E 0x002E +#define URB_FUNCTION_RESERVE_0X002F 0x002F +// USB 2.0 calls start at 0x0030 +#define URB_FUNCTION_SYNC_RESET_PIPE 0x0030 +#define URB_FUNCTION_SYNC_CLEAR_STALL 0x0031 +#define URB_FUNCTION_CONTROL_TRANSFER_EX 0x0032 + +#define USBD_PF_CHANGE_MAX_PACKET 0x00000001 + +#define USBD_TRANSFER_DIRECTION_OUT 0 +#define USBD_TRANSFER_DIRECTION_IN 1 + +#define USBD_SHORT_TRANSFER_OK 0x00000002 +#define USBD_START_ISO_TRANSFER_ASAP 0x00000004 +#define USBD_DEFAULT_PIPE_TRANSFER 0x00000008 + +#define USBD_TRANSFER_DIRECTION(flags) \ + ((flags) & USBD_TRANSFER_DIRECTION_IN) + +enum pipe_type {UsbdPipeTypeControl = USB_ENDPOINT_XFER_CONTROL, + UsbdPipeTypeIsochronous = USB_ENDPOINT_XFER_ISOC, + UsbdPipeTypeBulk = USB_ENDPOINT_XFER_BULK, + UsbdPipeTypeInterrupt = USB_ENDPOINT_XFER_INT}; + +#define USBD_IS_BULK_PIPE(pipe_handle) \ + (((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) \ + == USB_ENDPOINT_XFER_BULK) + +#define USBD_IS_INT_PIPE(pipe_handle) \ + (((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) \ + == USB_ENDPOINT_XFER_INT) + +#define USBD_PORT_ENABLED 0x00000001 +#define USBD_PORT_CONNECTED 0x00000002 + +typedef LONG USBD_STATUS; + +#define USBD_STATUS_SUCCESS 0x0 +#define USBD_STATUS_PENDING 0x40000000 +#define USBD_STATUS_CANCELED 0x00010000 + +#define USBD_STATUS_CRC 0xC0000001 +#define USBD_STATUS_BTSTUFF 0xC0000002 +#define USBD_STATUS_DATA_TOGGLE_MISMATCH 0xC0000003 +#define USBD_STATUS_STALL_PID 0xC0000004 +#define USBD_STATUS_DEV_NOT_RESPONDING 0xC0000005 +#define USBD_STATUS_PID_CHECK_FAILURE 0xC0000006 +#define USBD_STATUS_UNEXPECTED_PID 0xC0000007 +#define USBD_STATUS_DATA_OVERRUN 0xC0000008 +#define USBD_STATUS_DATA_UNDERRUN 0xC0000009 +#define USBD_STATUS_RESERVED1 0xC000000A +#define USBD_STATUS_RESERVED2 0xC000000B +#define USBD_STATUS_BUFFER_OVERRUN 0xC000000C +#define USBD_STATUS_BUFFER_UNDERRUN 0xC000000D +#define USBD_STATUS_NOT_ACCESSED 0xC000000F +#define USBD_STATUS_FIFO 0xC0000010 +#define USBD_STATUS_XACT_ERROR 0xC0000011 +#define USBD_STATUS_BABBLE_DETECTED 0xC0000012 +#define USBD_STATUS_DATA_BUFFER_ERROR 0xC0000013 + +#define USBD_STATUS_NOT_SUPPORTED 0xC0000E00 +#define USBD_STATUS_BUFFER_TOO_SMALL 0xC0003000 +#define USBD_STATUS_TIMEOUT 0xC0006000 +#define USBD_STATUS_DEVICE_GONE 0xC0007000 + +#define USBD_STATUS_NO_MEMORY 0x80000100 +#define USBD_STATUS_INVALID_URB_FUNCTION 0x80000200 +#define USBD_STATUS_INVALID_PARAMETER 0x80000300 +#define USBD_STATUS_REQUEST_FAILED 0x80000500 +#define USBD_STATUS_INVALID_PIPE_HANDLE 0x80000600 +#define USBD_STATUS_ERROR_SHORT_TRANSFER 0x80000900 + +#define USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE PAGE_SIZE + +struct urb_hcd_area { + void *reserved8[8]; +}; + +typedef struct usb_endpoint_descriptor *usbd_pipe_handle; +typedef struct usb_descriptor_header usb_common_descriptor_t; + +struct usbd_pipe_information { + USHORT wMaxPacketSize; + UCHAR bEndpointAddress; + UCHAR bInterval; + enum pipe_type type; + usbd_pipe_handle handle; + ULONG max_tx_size; + ULONG flags; +}; + +struct usbd_interface_information { + USHORT bLength; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR reserved; + void *handle; + ULONG bNumEndpoints; + struct usbd_pipe_information pipes[1]; +}; + +struct usbd_interface_list_entry { + struct usb_interface_descriptor *intf_desc; + struct usbd_interface_information *intf; +}; + +struct nt_urb_header { + USHORT length; + USHORT function; + USBD_STATUS status; + void *usbd_dev_handle; + ULONG usbd_flags; +}; + +struct usbd_select_interface { + struct nt_urb_header header; + void *handle; + struct usbd_interface_information intf; +}; + +struct usbd_select_configuration { + struct nt_urb_header header; + struct usb_config_descriptor *config; + void *handle; + struct usbd_interface_information intf; +}; + +struct usbd_control_descriptor_request { + struct nt_urb_header header; + void *reserved; + ULONG reserved0; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *urb_link; + struct urb_hcd_area hca; + USHORT reserved1; + UCHAR index; + UCHAR desc_type; + USHORT language_id; + USHORT reserved2; +}; + +struct usbd_bulk_or_intr_transfer { + struct nt_urb_header header; + usbd_pipe_handle pipe_handle; + ULONG transfer_flags; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *urb_link; + struct urb_hcd_area hca; +}; + +struct usbd_pipe_request { + struct nt_urb_header header; + usbd_pipe_handle pipe_handle; +}; + +struct usbd_vendor_or_class_request { + struct nt_urb_header header; + void *reserved; + ULONG transfer_flags; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *link; + struct urb_hcd_area hca; + UCHAR reserved_bits; + UCHAR request; + USHORT value; + USHORT index; + USHORT reserved1; +}; + +struct urb_control_feature_request { + struct nt_urb_header header; + void *reserved; + ULONG reserved2; + ULONG reserved3; + void *reserved4; + struct mdl *reserved5; + union nt_urb *link; + struct urb_hcd_area hca; + USHORT reserved0; + USHORT feature_selector; + USHORT index; + USHORT reserved1; +}; + +struct urb_control_get_status_request { + struct nt_urb_header header; + void *reserved; + ULONG reserved0; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *link; + struct urb_hcd_area hca; + UCHAR reserved1[4]; + USHORT index; + USHORT reserved2; +}; + +struct usbd_iso_packet_desc { + ULONG offset; + ULONG length; + USBD_STATUS status; +}; + +struct usbd_isochronous_transfer { + struct nt_urb_header header; + usbd_pipe_handle pipe_handle; + ULONG transfer_flags; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *urb_link; + struct urb_hcd_area hca; + ULONG start_frame; + ULONG number_of_packets; + ULONG error_count; + struct usbd_iso_packet_desc iso_packet[1]; +}; + +union nt_urb { + struct nt_urb_header header; + struct usbd_select_interface select_intf; + struct usbd_select_configuration select_conf; + struct usbd_bulk_or_intr_transfer bulk_int_transfer; + struct usbd_control_descriptor_request control_desc; + struct usbd_vendor_or_class_request vendor_class_request; + struct usbd_isochronous_transfer isochronous; + struct usbd_pipe_request pipe_req; + struct urb_control_feature_request feat_req; + struct urb_control_get_status_request status_req; +}; + +struct usbd_bus_interface_usbdi { + USHORT Size; + USHORT Version; + void *Context; + void *InterfaceReference; + void *InterfaceDereference; + void *GetUSBDIVersion; + void *QueryBusTime; + void *SubmitIsoOutUrb; + void *QueryBusInformation; + /* version 1 and above have following field */ + void *IsDeviceHighSpeed; + /* version 2 (and above) have following field */ + void *LogEntry; +}; + +struct usbd_bus_information_level { + ULONG TotalBandwidth; + ULONG ConsumedBandwidth; + /* level 1 and above have following fields */ + ULONG ControllerNameLength; + wchar_t ControllerName[1]; +}; + +#define USBDI_VERSION_XP 0x00000500 // Windows XP +#define USB_HCD_CAPS_SUPPORTS_RT_THREADS 0x00000001 +#define USB_BUSIF_USBDI_VERSION_0 0x0000 +#define USB_BUSIF_USBDI_VERSION_1 0x0001 +#define USB_BUSIF_USBDI_VERSION_2 0x0002 + +struct usbd_version_info { + ULONG usbdi_version; + ULONG supported_usb_version; +}; + +struct usbd_idle_callback { + void *callback; + void *context; +}; + +#define NT_URB_STATUS(nt_urb) ((nt_urb)->header.status) + +NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp); +void wrap_suspend_urbs(struct wrap_device *wd); +void wrap_resume_urbs(struct wrap_device *wd); + +void USBD_InterfaceGetUSBDIVersion(void *context, + struct usbd_version_info *version_info, + ULONG *hcd_capa) wstdcall; +BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context) wstdcall; +void USBD_InterfaceReference(void *context) wstdcall; +void USBD_InterfaceDereference(void *context) wstdcall; +NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame) wstdcall; +NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context, + union nt_urb *nt_urb) wstdcall; +NTSTATUS USBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf, + ULONG *buf_length, + ULONG *buf_actual_length) wstdcall; +NTSTATUS USBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag, + ULONG p1, ULONG p2) wstdcall; + +#endif /* USB_H */ --- linux-2.6.27.orig/ubuntu/ndiswrapper/wrapndis.h +++ linux-2.6.27/ubuntu/ndiswrapper/wrapndis.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _WRAPNDIS_H_ +#define _WRAPNDIS_H_ + +#include "ndis.h" +#include "pnp.h" + +int wrapndis_init(void); +void wrapndis_exit(void); + +NDIS_STATUS mp_reset(struct ndis_device *wnd); + +NDIS_STATUS mp_request(enum ndis_request_type request, + struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen, ULONG *written, ULONG *needed); + +static inline NDIS_STATUS mp_query_info(struct ndis_device *wnd, + ndis_oid oid, void *buf, ULONG buflen, + ULONG *written, ULONG *needed) +{ + return mp_request(NdisRequestQueryInformation, wnd, oid, + buf, buflen, written, needed); +} + +static inline NDIS_STATUS mp_set_info(struct ndis_device *wnd, + ndis_oid oid, void *buf, ULONG buflen, + ULONG *written, ULONG *needed) +{ + return mp_request(NdisRequestSetInformation, wnd, oid, + buf, buflen, written, needed); +} + +static inline NDIS_STATUS mp_query(struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen) +{ + return mp_request(NdisRequestQueryInformation, wnd, oid, + buf, buflen, NULL, NULL); +} + +static inline NDIS_STATUS mp_query_int(struct ndis_device *wnd, + ndis_oid oid, ULONG *data) +{ + return mp_request(NdisRequestQueryInformation, wnd, oid, + data, sizeof(ULONG), NULL, NULL); +} + +static inline NDIS_STATUS mp_set(struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen) +{ + return mp_request(NdisRequestSetInformation, wnd, oid, + buf, buflen, NULL, NULL); +} + +static inline NDIS_STATUS mp_set_int(struct ndis_device *wnd, + ndis_oid oid, ULONG data) +{ + return mp_request(NdisRequestSetInformation, wnd, oid, + &data, sizeof(ULONG), NULL, NULL); +} + +void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet, + NDIS_STATUS status); +int init_ndis_driver(struct driver_object *drv_obj); +NDIS_STATUS ndis_reinit(struct ndis_device *wnd); + +void hangcheck_add(struct ndis_device *wnd); +void hangcheck_del(struct ndis_device *wnd); + +driver_dispatch_t winNdisDispatchPnp; +driver_dispatch_t winNdisDispatchPower; +driver_dispatch_t winNdisDispatchDeviceControl; + +struct iw_statistics *get_iw_stats(struct net_device *dev); + +#endif --- linux-2.6.27.orig/ubuntu/ndiswrapper/Makefile +++ linux-2.6.27/ubuntu/ndiswrapper/Makefile @@ -0,0 +1,38 @@ +ndiswrapper-objs := crt.o hal.o iw_ndis.o loader.o ndis.o ntoskernel.o ntoskernel_io.o \ + pe_linker.o pnp.o proc.o rtl.o wrapmem.o wrapndis.o wrapper.o usb.o + +EXPORTS = crt_exports.h hal_exports.h ndis_exports.h ntoskernel_exports.h \ + ntoskernel_io_exports.h rtl_exports.h usb_exports.h + +STUB_SRCS = crt.c hal.c ndis.c ntoskernel.c ntoskernel_io.c \ + pnp.c rtl.c wrapndis.c usb.c + + +EXTRA_CFLAGS += -DENABLE_USB -I$(obj) +EXTRA_AFLAGS += -I$(obj) + +# generate exports symbol table from C files +quiet_cmd_mkexport = MKEXPORT $@ +cmd_mkexport = $(SHELL) $(srctree)/$(src)/mkexport.sh $< $@ + +%_exports.h: %.c $(srctree)/$(src)/mkexport.sh FORCE + $(call if_changed,mkexport) + +$(addprefix $(obj)/,$(EXPORTS:_exports.h=.o)): %.o: %_exports.h +extra-y += $(EXPORTS) + +ifeq ($(CONFIG_X86_64),y) +quiet_cmd_mkstubs = MKSTUBS $@ +cmd_mkstubs = $(SHELL) $(srctree)/$(src)/mkstubs.sh $(addprefix $(srctree)/$(src)/,$(STUB_SRCS)) >$@ + +$(obj)/win2lin_stubs.h: $(addprefix $(srctree)/$(src)/,$(STUB_SRCS)) FORCE + $(call if_changed,mkstubs) + +$(obj)/win2lin_stubs.o: $(obj)/win2lin_stubs.h +extra-y += win2lin_stubs.h +ndiswrapper-objs += win2lin_stubs.o +else +ndiswrapper-objs += divdi3.o +endif + +obj-$(CONFIG_NDISWRAPPER) := ndiswrapper.o --- linux-2.6.27.orig/ubuntu/ndiswrapper/pnp.h +++ linux-2.6.27/ubuntu/ndiswrapper/pnp.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _PNP_H_ +#define _PNP_H_ + +#include "ntoskernel.h" +#include "ndis.h" +#include "wrapndis.h" + +NTSTATUS pnp_start_device(struct wrap_device *wd); +NTSTATUS pnp_stop_device(struct wrap_device *wd); +NTSTATUS pnp_remove_device(struct wrap_device *wd); + +int wrap_pnp_start_pci_device(struct pci_dev *pdev, + const struct pci_device_id *ent); +void __devexit wrap_pnp_remove_pci_device(struct pci_dev *pdev); +int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state); +int wrap_pnp_resume_pci_device(struct pci_dev *pdev); + +#ifdef ENABLE_USB +int wrap_pnp_start_usb_device(struct usb_interface *intf, + const struct usb_device_id *usb_id); +void wrap_pnp_remove_usb_device(struct usb_interface *intf); +int wrap_pnp_suspend_usb_device(struct usb_interface *intf, + pm_message_t state); +int wrap_pnp_resume_usb_device(struct usb_interface *intf); +#endif + +#endif --- linux-2.6.27.orig/ubuntu/ndiswrapper/wrapper.h +++ linux-2.6.27/ubuntu/ndiswrapper/wrapper.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef WRAPPER_H +#define WRAPPER_H + +extern char *if_name; +extern int proc_uid; +extern int proc_gid; +extern int hangcheck_interval; + +#endif /* WRAPPER_H */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_netdev.c +++ linux-2.6.27/ubuntu/et131x/et131x_netdev.c @@ -0,0 +1,1624 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_netdev.c - Routines and data required by all Linux network devices. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2007/01/22 23:13:56 $ + $Revision: 1.21 $ + $Name: T_20060131_v1-2-3 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/******************************************************************************* + Includes + ******************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#include +#endif + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" +#include "ET1310_mac.h" +#include "ET1310_tx.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_isr.h" +#include "et131x_initpci.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Prototypes for functions with local scope + *****************************************************************************/ +int et131x_init( struct net_device *netdev ); + +int et131x_config( struct net_device *netdev, struct ifmap *map ); + +struct net_device_stats *et131x_stats( struct net_device *netdev ); + +int et131x_open( struct net_device *netdev ); + +int et131x_close( struct net_device *netdev ); + +int et131x_ioctl( struct net_device *netdev, struct ifreq *reqbuf, int cmd ); + +void et131x_multicast( struct net_device *netdev ); + +int et131x_tx( struct sk_buff *skb, struct net_device *netdev ); + +void et131x_tx_timeout( struct net_device *netdev ); + +int et131x_change_mtu( struct net_device *netdev, int new_mtu ); + +int et131x_set_mac_addr( struct net_device *netdev, void *new_mac ); + +void et131x_vlan_rx_register( struct net_device *netdev, struct vlan_group *grp ); + +void et131x_vlan_rx_add_vid( struct net_device *netdev, UINT16 vid ); + +void et131x_vlan_rx_kill_vid( struct net_device *netdev, UINT16 vid ); + + + + +/****************************************************************************** + ROUTINE : et131x_device_alloc() + ****************************************************************************** + + DESCRIPTION : Create instances of net_device and wl_private for the + new adapter and register the device's entry points in + the net_device structure. + + PARAMETERS : N/A + + RETURNS : pointer to the allocated and initialized net_device + struct for this device. + + REUSE INFORMATION : + + *****************************************************************************/ +struct net_device * et131x_device_alloc( void ) +{ + struct net_device *netdev = NULL; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_device_alloc" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Alloc net_device and adapter structs + *************************************************************************/ + netdev = alloc_etherdev( sizeof( ET131X_ADAPTER )); + + if( netdev == NULL ) + { + DBG_ERROR( et131x_dbginfo, + "Alloc of net_device struct failed\n" ); + DBG_LEAVE( et131x_dbginfo ); + return NULL; + } + + + /************************************************************************** + Setup the function registration table (and other data) for a net_device + *************************************************************************/ + //netdev->init = &et131x_init; + netdev->set_config = &et131x_config; + netdev->get_stats = &et131x_stats; + netdev->open = &et131x_open; + netdev->stop = &et131x_close; + netdev->do_ioctl = &et131x_ioctl; + netdev->set_multicast_list = &et131x_multicast; + netdev->hard_start_xmit = &et131x_tx; + netdev->tx_timeout = &et131x_tx_timeout; + netdev->watchdog_timeo = ET131X_TX_TIMEOUT; + netdev->change_mtu = &et131x_change_mtu; + netdev->set_mac_address = &et131x_set_mac_addr; + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + netdev->vlan_rx_register = &et131x_vlan_rx_register; + netdev->vlan_rx_add_vid = &et131x_vlan_rx_add_vid; + netdev->vlan_rx_kill_vid = &et131x_vlan_rx_kill_vid; +#endif + + //netdev->ethtool_ops = &et131x_ethtool_ops; + + // Poll? + //netdev->poll = &et131x_poll; + //netdev->poll_controller = &et131x_poll_controller; + + + DBG_LEAVE( et131x_dbginfo ); + return netdev; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_device_free() + ****************************************************************************** + + DESCRIPTION : Free the net_device and adapter private resources for + an adapter and perform basic cleanup. + + PARAMETERS : netdev - a pointer to the net_device structure + representing the device whose resources should + be freed. + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_device_free( struct net_device *netdev ) +{ + + DBG_FUNC( "et131x_device_free" ); + DBG_ENTER( et131x_dbginfo ); + + if( netdev == NULL ) + { + DBG_WARNING( et131x_dbginfo, "Pointer to net_device == NULL\n" ); + DBG_LEAVE( et131x_dbginfo ); + return; + } + else + { + free_netdev( netdev ); + } + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_init + ****************************************************************************** + + DESCRIPTION : This function is called by the kernel to initialize a + device + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device to be initialized. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : At the moment, this routine does nothing, as most init + processing needs to be performed before this point. + + *****************************************************************************/ +int et131x_init( struct net_device *netdev ) +{ + + DBG_FUNC( "et131x_init" ); + DBG_ENTER( et131x_dbginfo ); + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_config + ****************************************************************************** + + DESCRIPTION : Implement the SIOCSIFMAP interface. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device to be configured. + map - a pointer to an ifmap struct + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_config( struct net_device *netdev, struct ifmap *map ) +{ + DBG_FUNC( "et131x_config" ); + DBG_ENTER( et131x_dbginfo ); + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_stats + ****************************************************************************** + + DESCRIPTION : Return the current device statistics. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device whose stats are being queried. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +struct net_device_stats *et131x_stats( struct net_device *netdev ) +{ + ET131X_ADAPTER *adapter = netdev_priv(netdev); + struct net_device_stats *stats = &adapter->net_stats; + CE_STATS_t *devstat = &adapter->Stats; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_stats" ); + DBG_ENTER( et131x_dbginfo ); + + + stats->rx_packets = devstat->ipackets; + stats->tx_packets = devstat->opackets; + stats->rx_errors = devstat->length_err + devstat->alignment_err + + devstat->crc_err + devstat->code_violations + + devstat->other_errors; + stats->tx_errors = devstat->max_pkt_error; + stats->multicast = devstat->multircv; + stats->collisions = devstat->collisions; + + stats->rx_length_errors = devstat->length_err; + stats->rx_over_errors = devstat->rx_ov_flow; + stats->rx_crc_errors = devstat->crc_err; + + // NOTE: These stats don't have corresponding values in CE_STATS, so we're + // going to have to update these directly from within the TX/RX code + //stats->rx_bytes = 20; //devstat->; + //stats->tx_bytes = 20; //devstat->; + //stats->rx_dropped = devstat->; + //stats->tx_dropped = devstat->; + + // NOTE: Not used, can't find analogous statistics + //stats->rx_frame_errors = devstat->; + //stats->rx_fifo_errors = devstat->; + //stats->rx_missed_errors = devstat->; + + //stats->tx_aborted_errors = devstat->; + //stats->tx_carrier_errors = devstat->; + //stats->tx_fifo_errors = devstat->; + //stats->tx_heartbeat_errors = devstat->; + //stats->tx_window_errors = devstat->; + + + DBG_LEAVE( et131x_dbginfo ); + return stats; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_open + ****************************************************************************** + + DESCRIPTION : Open the device for use. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device to be opened. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_open( struct net_device *netdev ) +{ + int result = 0; + ET131X_ADAPTER *adapter = NULL; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_open" ); + DBG_ENTER( et131x_dbginfo ); + + + adapter = netdev_priv( netdev ); + + + /************************************************************************** + Start the timer to track NIC errors + *************************************************************************/ + add_timer( &adapter->ErrorTimer ); + + + /************************************************************************** + Register our ISR + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Registering ISR...\n" ); + + result = request_irq( netdev->irq, et131x_isr, IRQF_SHARED, netdev->name, netdev ); + if( result ) + { + DBG_ERROR( et131x_dbginfo, "Could not register ISR\n" ); + DBG_LEAVE( et131x_dbginfo ); + return result; + } + + + /************************************************************************** + Enable the Tx and Rx DMA engines (if not already enabled) + *************************************************************************/ + et131x_rx_dma_enable( adapter ); + et131x_tx_dma_enable( adapter ); + + + /************************************************************************** + Enable device interrupts + *************************************************************************/ + et131x_enable_interrupts( adapter ); + + MP_SET_FLAG( adapter, fMP_ADAPTER_INTERRUPT_IN_USE ); + + + /************************************************************************** + We're ready to move some data, so start the queue + *************************************************************************/ + netif_start_queue( netdev ); + + + DBG_LEAVE( et131x_dbginfo ); + return result; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_close + ****************************************************************************** + + DESCRIPTION : Close the device. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device to be opened. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_close( struct net_device *netdev ) +{ + ET131X_ADAPTER *adapter = NULL; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_close" ); + DBG_ENTER( et131x_dbginfo ); + + + adapter = netdev_priv( netdev ); + + + /************************************************************************** + First thing is to stop the queue + *************************************************************************/ + netif_stop_queue( netdev ); + + + /************************************************************************** + Stop the Tx and Rx DMA engines + *************************************************************************/ + et131x_rx_dma_disable( adapter ); + et131x_tx_dma_disable( adapter ); + + + /************************************************************************** + Disable device interrupts + *************************************************************************/ + et131x_disable_interrupts( adapter ); + + + /************************************************************************** + Deregistering ISR + *************************************************************************/ + MP_CLEAR_FLAG( adapter, fMP_ADAPTER_INTERRUPT_IN_USE ); + + DBG_TRACE( et131x_dbginfo, "Deregistering ISR...\n" ); + free_irq( netdev->irq, netdev ); + + + /************************************************************************** + Stop the error timer + *************************************************************************/ + del_timer_sync( &adapter->ErrorTimer ); + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_ioctl_mii + ****************************************************************************** + + DESCRIPTION : The function which handles MII IOCTLs + + PARAMETERS : netdev - the net_device struct corresponding to the + device on which the query is being made + reqbuf - the request-specific data buffer + cmd - the command request code + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_ioctl_mii( struct net_device *netdev, struct ifreq *reqbuf, int cmd ) +{ + int status = 0; + ET131X_ADAPTER *pAdapter = netdev_priv(netdev); + struct mii_ioctl_data *data = if_mii( reqbuf ); + UINT16 mii_reg; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_ioctl_mii" ); + DBG_ENTER( et131x_dbginfo ); + + + switch( cmd ) + { + case SIOCGMIIPHY: + DBG_VERBOSE( et131x_dbginfo, "SIOCGMIIPHY\n" ); + data->phy_id = pAdapter->Stats.xcvr_addr; + break; + + + case SIOCGMIIREG: + DBG_VERBOSE( et131x_dbginfo, "SIOCGMIIREG\n" ); + if( !capable( CAP_NET_ADMIN )) + { + status = -EPERM; + } + else + { + status = MiRead( pAdapter, + pAdapter->Stats.xcvr_addr, + data->reg_num, + &data->val_out ); + } + + break; + + + case SIOCSMIIREG: + DBG_VERBOSE( et131x_dbginfo, "SIOCSMIIREG\n" ); + if( !capable( CAP_NET_ADMIN )) + { + status = -EPERM; + } + else + { + mii_reg = data->val_in; + + status = MiWrite( pAdapter, + pAdapter->Stats.xcvr_addr, + data->reg_num, + mii_reg ); + } + + break; + + + default: + status = -EOPNOTSUPP; + } + + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_ioctl + ****************************************************************************** + + DESCRIPTION : The I/O Control handler for the driver. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device on which the control request is + being made. + reqbuf - a pointer to the IOCTL request buffer. + cmd - the IOCTL command code. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_ioctl( struct net_device *netdev, struct ifreq *reqbuf, int cmd ) +{ + int status = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_ioctl" ); + DBG_ENTER( et131x_dbginfo ); + + + switch( cmd ) + { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + status = et131x_ioctl_mii( netdev, reqbuf, cmd ); + break; + + default: +/* DBG_WARNING( et131x_dbginfo, "Unhandled IOCTL Code: 0x%04x\n", cmd );*/ + status = -EOPNOTSUPP; + } + + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_set_packet_filter + ****************************************************************************** + + DESCRIPTION : Configures the Rx Packet filtering on the device + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success, errno on failure + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_set_packet_filter( ET131X_ADAPTER *adapter ) +{ + int status = 0; + UINT32 filter = adapter->PacketFilter; + RXMAC_CTRL_t ctrl = adapter->CSRAddress->rxmac.ctrl; + RXMAC_PF_CTRL_t pf_ctrl = adapter->CSRAddress->rxmac.pf_ctrl; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_set_packet_filter" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Default to disabled packet filtering. Enable it in the individual case + statements that require the device to filter something + *************************************************************************/ + ctrl.bits.pkt_filter_disable = 1; + + + /************************************************************************** + Set us to be in promiscuous mode so we receive everything, + this is also true when we get a packet filter of 0 + *************************************************************************/ + if(( filter & ET131X_PACKET_TYPE_PROMISCUOUS ) || filter == 0 ) + { + pf_ctrl.bits.filter_broad_en = 0; + pf_ctrl.bits.filter_multi_en = 0; + pf_ctrl.bits.filter_uni_en = 0; + } + else + { + /********************************************************************** + Set us up with Multicast packet filtering. Three cases are + possible - (1) we have a multi-cast list, (2) we receive ALL + multicast entries or (3) we receive none. + *********************************************************************/ + if( filter & ET131X_PACKET_TYPE_ALL_MULTICAST ) + { + DBG_VERBOSE( et131x_dbginfo, + "Multicast filtering OFF (Rx ALL MULTICAST)\n" ); + pf_ctrl.bits.filter_multi_en = 0; + } + else + { + DBG_VERBOSE( et131x_dbginfo, "Multicast filtering ON\n" ); + SetupDeviceForMulticast( adapter ); + pf_ctrl.bits.filter_multi_en = 1; + ctrl.bits.pkt_filter_disable = 0; + } + + + /********************************************************************** + Set us up with Unicast packet filtering + *********************************************************************/ + if( filter & ET131X_PACKET_TYPE_DIRECTED ) + { + DBG_VERBOSE( et131x_dbginfo, "Unicast Filtering ON\n" ); + SetupDeviceForUnicast( adapter ); + pf_ctrl.bits.filter_uni_en = 1; + ctrl.bits.pkt_filter_disable = 0; + } + + + /********************************************************************** + Set us up with Broadcast packet filtering + *********************************************************************/ + if( filter & ET131X_PACKET_TYPE_BROADCAST ) + { + DBG_VERBOSE( et131x_dbginfo, "Broadcast Filtering ON\n" ); + pf_ctrl.bits.filter_broad_en = 1; + ctrl.bits.pkt_filter_disable = 0; + } + else + { + DBG_VERBOSE( et131x_dbginfo, "Broadcast Filtering OFF\n" ); + pf_ctrl.bits.filter_broad_en = 0; + } + + + /********************************************************************** + Setup the receive mac configuration registers - Packet Filter + control + the enable / disable for packet filter in the control + reg. + *********************************************************************/ + adapter->CSRAddress->rxmac.pf_ctrl.value = pf_ctrl.value; + adapter->CSRAddress->rxmac.ctrl = ctrl; + } + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_multicast + ****************************************************************************** + + DESCRIPTION : The handler to configure multicasting on the interface. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device. + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_multicast( struct net_device *netdev ) +{ + ET131X_ADAPTER *adapter = NULL; + UINT32 PacketFilter = 0; + UINT32 count; + unsigned long lockflags; + struct dev_mc_list *mclist = netdev->mc_list; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_multicast" ); + DBG_ENTER( et131x_dbginfo ); + + + adapter = netdev_priv( netdev ); + + + spin_lock_irqsave( &adapter->Lock, lockflags ); + + + /************************************************************************** + Before we modify the platform-independent filter flags, store them + locally. This allows us to determine if anything's changed and if we + even need to bother the hardware + *************************************************************************/ + PacketFilter = adapter->PacketFilter; + + + /************************************************************************** + Clear the 'multicast' flag locally; becuase we only have a single flag + to check multicast, and multiple multicast addresses can be set, this is + the easiest way to determine if more than one multicast address is being + set. + *************************************************************************/ + PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; + + + /************************************************************************** + Check the net_device flags and set the device independent flags + accordingly + *************************************************************************/ + DBG_VERBOSE( et131x_dbginfo, + "MULTICAST ADDR COUNT: %d\n", + netdev->mc_count ); + + if( netdev->flags & IFF_PROMISC ) + { + DBG_VERBOSE( et131x_dbginfo, "Request: PROMISCUOUS MODE ON\n" ); + adapter->PacketFilter |= ET131X_PACKET_TYPE_PROMISCUOUS; + } + else + { + DBG_VERBOSE( et131x_dbginfo, "Request: PROMISCUOUS MODE OFF\n" ); + adapter->PacketFilter &= ~ET131X_PACKET_TYPE_PROMISCUOUS; + } + + + if( netdev->flags & IFF_ALLMULTI ) + { + DBG_VERBOSE( et131x_dbginfo, "Request: ACCEPT ALL MULTICAST\n" ); + adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; + } + + + if( netdev->mc_count > NIC_MAX_MCAST_LIST ) + { + DBG_WARNING( et131x_dbginfo, + "ACCEPT ALL MULTICAST for now, as there's more Multicast " + "addresses than the HW supports\n" ); + + adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; + } + + + if( netdev->mc_count < 1 ) + { + DBG_VERBOSE( et131x_dbginfo, "Request: REJECT ALL MULTICAST\n" ); + adapter->PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST; + adapter->PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; + } + else + { + DBG_VERBOSE( et131x_dbginfo, "Request: SET MULTICAST FILTER(S)\n" ); + adapter->PacketFilter |= ET131X_PACKET_TYPE_MULTICAST; + } + + + /************************************************************************** + Set values in the private adapter struct + *************************************************************************/ + adapter->MCAddressCount = netdev->mc_count; + + if( netdev->mc_count ) + { + if( mclist->dmi_addrlen != ETH_ALEN ) + { + DBG_WARNING( et131x_dbginfo, "Multicast addrs are not ETH_ALEN in size\n" ); + } + else + { + count = netdev->mc_count - 1; + memcpy( adapter->MCList[count], mclist->dmi_addr, ETH_ALEN ); + } + } + + + /************************************************************************** + Are the new flags different from the previous ones? If not, then no + action is required + + NOTE - This block will always update the MCList with the hardware, even + if the addresses aren't the same. + *************************************************************************/ + if( PacketFilter != adapter->PacketFilter ) + { + /********************************************************************** + Call the device's filter function + *********************************************************************/ + DBG_VERBOSE( et131x_dbginfo, + "UPDATE REQUIRED, FLAGS changed\n" ); + + et131x_set_packet_filter( adapter ); + } + else + { + DBG_VERBOSE( et131x_dbginfo, + "NO UPDATE REQUIRED, FLAGS didn't change\n" ); + } + + + spin_unlock_irqrestore( &adapter->Lock, lockflags ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_tx + ****************************************************************************** + + DESCRIPTION : The handler called when the Linux network layer wants + to a Tx a packet on the device. + + PARAMETERS : skb - a pointer to the sk_buff structure which + represents the data to be Tx'd. + netdev - a pointer to a net_device struct representing + the device on which data is to be Tx'd. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_tx( struct sk_buff *skb, struct net_device *netdev ) +{ + int status = 0; + ET131X_ADAPTER *adapter; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_tx" ); + DBG_TX_ENTER( et131x_dbginfo ); + + + adapter = netdev_priv( netdev ); + + + /************************************************************************** + Save the timestamp for the TX timeout watchdog + *************************************************************************/ + netdev->trans_start = jiffies; + + + /************************************************************************** + Call the device-specific data Tx routine + *************************************************************************/ + status = et131x_send_packets( skb, netdev ); + + + /************************************************************************** + Check status and manage the netif queue if necessary + *************************************************************************/ + if( status != 0 ) + { + if( status == -ENOMEM ) + { + DBG_VERBOSE( et131x_dbginfo, "OUT OF TCBs; STOP NETIF QUEUE\n" ); + + /* Put the queue to sleep until resources are available */ + netif_stop_queue( netdev ); + status = 1; + } + else + { + DBG_WARNING( et131x_dbginfo, "Misc error; drop packet\n" ); + status = 0; + } + } + + DBG_TX_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_tx_timeout + ****************************************************************************** + + DESCRIPTION : The handler called when a Tx request times out. The + timeout period is specified by the 'tx_timeo" element in + the net_device structure (see et131x_alloc_device() to + see how this value is set). + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device. + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_tx_timeout( struct net_device *netdev ) +{ + ET131X_ADAPTER *pAdapter = netdev_priv( netdev ); + PMP_TCB pMpTcb; + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_tx_timeout" ); + DBG_WARNING( et131x_dbginfo, "TX TIMEOUT\n" ); + + + /************************************************************************** + Just skip this part if the adapter is doing link detection + *************************************************************************/ + if( MP_TEST_FLAG( pAdapter, fMP_ADAPTER_LINK_DETECTION )) + { + DBG_ERROR( et131x_dbginfo, "Still doing link detection\n" ); + return; + } + + + /************************************************************************** + Any nonrecoverable hardware error? + Checks adapter->flags for any failure in phy reading + *************************************************************************/ + if( MP_TEST_FLAG( pAdapter, fMP_ADAPTER_NON_RECOVER_ERROR )) + { + DBG_WARNING( et131x_dbginfo, "Non recoverable error - remove\n" ); + return; + } + + + /************************************************************************** + Hardware failure? + *************************************************************************/ + if( MP_TEST_FLAG( pAdapter, fMP_ADAPTER_HARDWARE_ERROR )) + { + DBG_WARNING( et131x_dbginfo, "hardware error - reset\n" ); + return; + } + + /************************************************************************** + Is send stuck? + *************************************************************************/ + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags ); + + pMpTcb = pAdapter->TxRing.CurrSendHead; + + if( pMpTcb != NULL ) + { + pMpTcb->Count++; + + if( pMpTcb->Count > NIC_SEND_HANG_THRESHOLD ) + { +#ifdef ET131X_DBG + TX_STATUS_BLOCK_t txDmaComplete = *( pAdapter->TxRing.pTxStatusVa ); + PTX_DESC_ENTRY_t pDesc = pAdapter->TxRing.pTxDescRingVa + + pMpTcb->WrIndex.bits.serv_req; +#endif + TX_DESC_ENTRY_t StuckDescriptors[10]; + + if( pMpTcb->WrIndex.bits.serv_req > 7 ) + { + memcpy( StuckDescriptors, + pAdapter->TxRing.pTxDescRingVa + pMpTcb->WrIndex.bits.serv_req - 6, + sizeof( TX_DESC_ENTRY_t ) * 10 ); + } + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + + DBG_WARNING( et131x_dbginfo, + "Send stuck - reset. pMpTcb->WrIndex %x, Flags 0x%08x\n", + pMpTcb->WrIndex.bits.serv_req, pMpTcb->Flags ); + + DBG_WARNING( et131x_dbginfo, + "pDesc 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + pDesc->DataBufferPtrHigh, pDesc->DataBufferPtrLow, + pDesc->word2.value, pDesc->word3.value ); + + DBG_WARNING( et131x_dbginfo, + "WbStatus 0x%08x\n", + txDmaComplete.value ); + +#ifdef ET131X_DBG + DumpDeviceBlock( DBG_WARNING_ON, pAdapter, 0 ); + DumpDeviceBlock( DBG_WARNING_ON, pAdapter, 1 ); + DumpDeviceBlock( DBG_WARNING_ON, pAdapter, 3 ); + DumpDeviceBlock( DBG_WARNING_ON, pAdapter, 5 ); +#endif + et131x_close( netdev ); + et131x_open( netdev ); + + return; + } + } + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_change_mtu + ****************************************************************************** + + DESCRIPTION : The handler called to change the MTU for the device. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device whose MTU is to be changed. + + new_mtu - the desired MTU. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_change_mtu( struct net_device *netdev, int new_mtu ) +{ + int result = 0; + ET131X_ADAPTER *adapter = NULL; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_change_mtu" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Get the private adapter structure + *************************************************************************/ + adapter = netdev_priv( netdev ); + + if( adapter == NULL ) + { + DBG_LEAVE( et131x_dbginfo ); + return -ENODEV; + } + + + /************************************************************************** + Make sure the requested MTU is valid + *************************************************************************/ + if( new_mtu == 0 || new_mtu > 9216 ) + { + DBG_LEAVE( et131x_dbginfo ); + return -EINVAL; + } + + + /************************************************************************** + Stop the netif queue + *************************************************************************/ + netif_stop_queue( netdev ); + + + /************************************************************************** + Stop the Tx and Rx DMA engines + *************************************************************************/ + et131x_rx_dma_disable( adapter ); + et131x_tx_dma_disable( adapter ); + + + /************************************************************************** + Disable device interrupts + *************************************************************************/ + et131x_disable_interrupts( adapter ); + et131x_handle_send_interrupt( adapter ); + et131x_handle_recv_interrupt( adapter ); + + + /************************************************************************** + Set the new MTU + *************************************************************************/ + netdev->mtu = new_mtu; + + + /************************************************************************** + Free Rx DMA memory + *************************************************************************/ + et131x_adapter_memory_free( adapter ); + + + /************************************************************************** + Set the config parameter for Jumbo Packet support + *************************************************************************/ + adapter->RegistryJumboPacket = new_mtu + 14; + et131x_soft_reset( adapter ); + + + /************************************************************************** + Alloc and init Rx DMA memory + *************************************************************************/ + result = et131x_adapter_memory_alloc( adapter ); + if( result != 0 ) + { + DBG_WARNING( et131x_dbginfo, + "Change MTU failed; couldn't re-alloc DMA memory\n" ); + return result; + } + + et131x_init_send( adapter ); + + + et131x_setup_hardware_properties( adapter ); + memcpy( netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN ); + et131x_init_enet_crc_calc( ); + + + /************************************************************************** + Init the device with the new settings + *************************************************************************/ + et131x_adapter_setup( adapter ); + + + /************************************************************************** + Enable interrupts + *************************************************************************/ + if( MP_TEST_FLAG( adapter, fMP_ADAPTER_INTERRUPT_IN_USE )) + { + et131x_enable_interrupts( adapter ); + } + + + /************************************************************************** + Restart the Tx and Rx DMA engines + *************************************************************************/ + et131x_rx_dma_enable( adapter ); + et131x_tx_dma_enable( adapter ); + + + /************************************************************************** + Restart the netif queue + *************************************************************************/ + netif_wake_queue( netdev ); + + + DBG_LEAVE( et131x_dbginfo ); + return result; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_set_mac_addr + ****************************************************************************** + + DESCRIPTION : The handler called to change the MAC address for the + device. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device whose MAC is to be changed. + + new_mac - a buffer containing a sock_addr struct in which + the desired MAC address is stored. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + IMPLEMENTED BY : blux http://berndlux.de 22.01.2007 21:14 + + *****************************************************************************/ +int et131x_set_mac_addr( struct net_device *netdev, void *new_mac ) +{ + int result = 0; + ET131X_ADAPTER *adapter = NULL; + struct sockaddr *address = new_mac; + + DBG_FUNC( "et131x_set_mac_addr" ); + DBG_ENTER( et131x_dbginfo ); + // begin blux + // DBG_VERBOSE( et131x_dbginfo, "Function not implemented!!\n" ); + + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + Get the private adapter structure + *************************************************************************/ + adapter = netdev_priv( netdev ); + + if( adapter == NULL ) + { + DBG_LEAVE( et131x_dbginfo ); + return -ENODEV; + } + + + /************************************************************************** + Make sure the requested MAC is valid + *************************************************************************/ + if (!is_valid_ether_addr(address->sa_data)) + { + DBG_LEAVE( et131x_dbginfo ); + return -EINVAL; + } + + + /************************************************************************** + Stop the netif queue + *************************************************************************/ + netif_stop_queue( netdev ); + + + /************************************************************************** + Stop the Tx and Rx DMA engines + *************************************************************************/ + et131x_rx_dma_disable( adapter ); + et131x_tx_dma_disable( adapter ); + + + /************************************************************************** + Disable device interrupts + *************************************************************************/ + et131x_disable_interrupts( adapter ); + et131x_handle_send_interrupt( adapter ); + et131x_handle_recv_interrupt( adapter ); + + + /************************************************************************** + Set the new MAC + *************************************************************************/ + // netdev->set_mac_address = &new_mac; + // netdev->mtu = new_mtu; + + + memcpy(netdev->dev_addr, address->sa_data, netdev->addr_len); + + printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", netdev->name, + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); + + + /************************************************************************** + Free Rx DMA memory + *************************************************************************/ + et131x_adapter_memory_free( adapter ); + + + /************************************************************************** + Set the config parameter for Jumbo Packet support + *************************************************************************/ + //adapter->RegistryJumboPacket = new_mtu + 14; + // blux: not needet here, w'll change the MAC + + et131x_soft_reset( adapter ); + + + /************************************************************************** + Alloc and init Rx DMA memory + *************************************************************************/ + result = et131x_adapter_memory_alloc( adapter ); + if( result != 0 ) + { + DBG_WARNING( et131x_dbginfo, + "Change MAC failed; couldn't re-alloc DMA memory\n" ); + return result; + } + + et131x_init_send( adapter ); + + + et131x_setup_hardware_properties( adapter ); + // memcpy( netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN ); + // blux: no, do not override our nice address + et131x_init_enet_crc_calc( ); + + + /************************************************************************** + Init the device with the new settings + *************************************************************************/ + et131x_adapter_setup( adapter ); + + + /************************************************************************** + Enable interrupts + *************************************************************************/ + if( MP_TEST_FLAG( adapter, fMP_ADAPTER_INTERRUPT_IN_USE )) + { + et131x_enable_interrupts( adapter ); + } + + + /************************************************************************** + Restart the Tx and Rx DMA engines + *************************************************************************/ + et131x_rx_dma_enable( adapter ); + et131x_tx_dma_enable( adapter ); + + + /************************************************************************** + Restart the netif queue + *************************************************************************/ + netif_wake_queue( netdev ); + + + + DBG_LEAVE( et131x_dbginfo ); + return result; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + NOTE: The ET1310 doesn't support hardware VLAN tagging, so these functions + are currently not used; they are in place to eventually support the + feature if needed. + *****************************************************************************/ + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + +/****************************************************************************** + ROUTINE : et131x_vlan_rx_register + ****************************************************************************** + + DESCRIPTION : The handler called to enable or disable VLAN support on + the device. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device on which VLAN should be enabled or + disabled. + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_vlan_rx_register( struct net_device *netdev, struct vlan_group *grp ) +{ + ET131X_ADAPTER *pAdapter = netdev_priv( netdev ); + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_vlan_rx_register" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Track the vlan_group struct in the adapter private structure; if this + element is NULL, then VLAN is disabled; otherwise, it is enabled. + *************************************************************************/ + if( grp ) + { + DBG_VERBOSE( et131x_dbginfo, "VLAN: Enable, 0x%p\n", grp ); + } + else + { + DBG_VERBOSE( et131x_dbginfo, "VLAN: Disable\n" ); + } + + pAdapter->vlgrp = grp; + + + /************************************************************************** + This is where any interfacing with the hardware to enable or disable + VLAN would be done. Since the ET1310 doesn't handle this in hardware, + nothing else needs to be done. + *************************************************************************/ + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_vlan_rx_add_vid + ****************************************************************************** + + DESCRIPTION : The handler called to register a VLAN tag. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device on which a VLAN tag should be added. + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_vlan_rx_add_vid( struct net_device *netdev, UINT16 vid ) +{ + DBG_FUNC( "et131x_vlan_rx_add_vid" ); + DBG_ENTER( et131x_dbginfo ); + + + DBG_VERBOSE( et131x_dbginfo, "VLAN, Add VID: %d\n", vid ); + + + /************************************************************************** + This is where any interfacing with the hardware to register VLAN IDs + would take place. Since the ET1310 doesn't handle this in hardware, + nothing else needs to be done here; the vlan_group structure's + vlan_devices element can be used in the TX/RX routines to determine if + a VLAN tag has been 'registered' with the device. + *************************************************************************/ + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_vlan_rx_kill_vid + ****************************************************************************** + + DESCRIPTION : The handler called to deregister a VLAN tag. + + PARAMETERS : netdev - a pointer to a net_device struct representing + the device on which a VLAN tag should be + removed. + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_vlan_rx_kill_vid( struct net_device *netdev, UINT16 vid ) +{ + ET131X_ADAPTER *pAdapter = netdev_priv( netdev ); + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_vlan_rx_kill_vid" ); + DBG_ENTER( et131x_dbginfo ); + + + DBG_VERBOSE( et131x_dbginfo, "VLAN, Remove VID: %d\n", vid ); + + if( pAdapter->vlgrp ) + { + pAdapter->vlgrp->vlan_devices_arrays[vid] = NULL; + } + + + /************************************************************************** + This is where any interfacing with the hardware to deregister VLAN IDs + would take place. Since the ET1310 doesn't handle this in hardware, + nothing else needs to be done here. + *************************************************************************/ + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + +#endif --- linux-2.6.27.orig/ubuntu/et131x/ET1310_rx.c +++ linux-2.6.27/ubuntu/et131x/ET1310_rx.c @@ -0,0 +1,2056 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_rx.c - Routines used to perform data reception + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/20 21:29:44 $ + $Revision: 1.21 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#include +#endif + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" + +#include "ET1310_rx.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Prototypes for functions local to this module + *****************************************************************************/ +void nic_return_rfd( ET131X_ADAPTER *pAdapter, PMP_RFD pMpRfd ); + + + + +/****************************************************************************** + ROUTINE : et131x_rx_dma_memory_alloc + ****************************************************************************** + + DESCRIPTION : Allocates Free buffer ring 1 for sure, free buffer ring + 0 if required, and the Packet Status Ring + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_rx_dma_memory_alloc( ET131X_ADAPTER *adapter ) +{ + UINT32 OuterLoop, InnerLoop; + UINT32 bufsize; + UINT32 pktStatRingSize, FBRChunkSize; + RX_RING_t *rx_ring; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_rx_dma_memory_alloc" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Setup some convenience pointers + *************************************************************************/ + rx_ring = (RX_RING_t *)&adapter->RxRing; + + + /************************************************************************** + Alloc memory for the lookup table + *************************************************************************/ +#ifdef USE_FBR0 + rx_ring->Fbr[0] = kmalloc( sizeof( FBRLOOKUPTABLE ), GFP_KERNEL ); +#endif + + rx_ring->Fbr[1] = kmalloc( sizeof( FBRLOOKUPTABLE ), GFP_KERNEL ); + + + /************************************************************************** + The first thing we will do is configure the sizes of the buffer rings. + These will change based on jumbo packet support. Larger jumbo packets + increases the size of each entry in FBR0, and the number of entries in + FBR0, while at the same time decreasing the number of entries in FBR1. + + FBR1 holds "large" frames, FBR0 holds "small" frames. If FBR1 entries + are huge in order to accomodate a "jumbo" frame, then it will have less + entries. Conversely, FBR1 will now be relied upon to carry more + "normal" frames, thus it's entry size also increases and the number + of entries goes up too (since it now carries "small" + "regular" + packets. + + In this scheme, we try to maintain 512 entries between the two rings. + Also, FBR1 remains a constant size - when it's size doubles the + number of entries halves. FBR0 increases in size, however. + *************************************************************************/ + + if( adapter->RegistryJumboPacket < 2048 ) + { +#ifdef USE_FBR0 + rx_ring->Fbr0BufferSize = 256; + rx_ring->Fbr0NumEntries = 512; +#endif + rx_ring->Fbr1BufferSize = 2048; + rx_ring->Fbr1NumEntries = 512; + } + else if( adapter->RegistryJumboPacket < 4096 ) + { +#ifdef USE_FBR0 + rx_ring->Fbr0BufferSize = 512; + rx_ring->Fbr0NumEntries = 1024; +#endif + rx_ring->Fbr1BufferSize = 4096; + rx_ring->Fbr1NumEntries = 512; + } + else + { +#ifdef USE_FBR0 + rx_ring->Fbr0BufferSize = 1024; + rx_ring->Fbr0NumEntries = 768; +#endif + rx_ring->Fbr1BufferSize = 16384; + rx_ring->Fbr1NumEntries = 128; + } + +#ifdef USE_FBR0 + adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr0NumEntries + + adapter->RxRing.Fbr1NumEntries; +#else + adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr1NumEntries; +#endif + + + /************************************************************************** + Allocate an area of memory for Free Buffer Ring 1 + *************************************************************************/ + bufsize = ( sizeof( FBR_DESC_t ) * rx_ring->Fbr1NumEntries) + 0xfff; + rx_ring->pFbr1RingVa = pci_alloc_consistent( adapter->pdev, + bufsize, + &rx_ring->pFbr1RingPa ); + if( !rx_ring->pFbr1RingVa ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for Free Buffer Ring 1\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Save physical address + + NOTE : pci_alloc_consistent(), used above to alloc DMA regions, ALWAYS + returns SAC (32-bit) addresses. If DAC (64-bit) addresses are + ever returned, make sure the high part is retrieved here before + storing the adjusted address. + *************************************************************************/ + rx_ring->Fbr1Realpa = rx_ring->pFbr1RingPa; + + + /************************************************************************** + Align Free Buffer Ring 1 on a 4K boundary + *************************************************************************/ + et131x_align_allocated_memory( adapter, + &rx_ring->Fbr1Realpa, + &rx_ring->Fbr1offset, + 0x0FFF ); + + rx_ring->pFbr1RingVa = (void *)( (PUCHAR)rx_ring->pFbr1RingVa + + rx_ring->Fbr1offset ); + + +#ifdef USE_FBR0 + /************************************************************************** + Allocate an area of memory for Free Buffer Ring 0 + *************************************************************************/ + bufsize = ( sizeof( FBR_DESC_t ) * rx_ring->Fbr0NumEntries ) + 0xfff; + rx_ring->pFbr0RingVa = pci_alloc_consistent( adapter->pdev, + bufsize, + &rx_ring->pFbr0RingPa ); + if( !rx_ring->pFbr0RingVa ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for Free Buffer Ring 0\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Save physical address + + NOTE : pci_alloc_consistent(), used above to alloc DMA regions, ALWAYS + returns SAC (32-bit) addresses. If DAC (64-bit) addresses are + ever returned, make sure the high part is retrieved here before + storing the adjusted address. + *************************************************************************/ + rx_ring->Fbr0Realpa = rx_ring->pFbr0RingPa; + + + /************************************************************************** + Align Free Buffer Ring 0 on a 4K boundary + *************************************************************************/ + et131x_align_allocated_memory( adapter, + &rx_ring->Fbr0Realpa, + &rx_ring->Fbr0offset, + 0x0FFF ); + + rx_ring->pFbr0RingVa = (void *)( (PUCHAR)rx_ring->pFbr0RingVa + + rx_ring->Fbr0offset ); + +#endif + + + for( OuterLoop = 0; OuterLoop < (rx_ring->Fbr1NumEntries / FBR_CHUNKS); OuterLoop++ ) + { + UINT64 Fbr1Offset; + UINT64 Fbr1TempPa; + UINT32 Fbr1Align; + + /********************************************************************** + This code allocates an area of memory big enough for N free + buffers + (buffer_size - 1) so that the buffers can be aligned + on 4k boundaries. If each buffer were aligned + to a buffer_size boundary, the effect would be to double the size + of FBR0. By allocating N buffers at once, we reduce this overhead. + *********************************************************************/ + if( rx_ring->Fbr1BufferSize > 4096 ) + { + Fbr1Align = 4096; + } + else + { + Fbr1Align = rx_ring->Fbr1BufferSize; + } + + FBRChunkSize = ( FBR_CHUNKS * rx_ring->Fbr1BufferSize ) + Fbr1Align - 1; + rx_ring->Fbr1MemVa[OuterLoop] = pci_alloc_consistent( adapter->pdev, + FBRChunkSize, + &rx_ring->Fbr1MemPa[OuterLoop] ); + + if( !rx_ring->Fbr1MemVa[OuterLoop] ) + { + DBG_ERROR( et131x_dbginfo, "Could not alloc memory\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /********************************************************************** + See NOTE in "Save Physical Address" comment above + *********************************************************************/ + Fbr1TempPa = rx_ring->Fbr1MemPa[OuterLoop]; + + et131x_align_allocated_memory( adapter, + &Fbr1TempPa, + &Fbr1Offset, + (Fbr1Align - 1)); + + + for( InnerLoop = 0; InnerLoop < FBR_CHUNKS; InnerLoop++ ) + { + UINT32 index = (OuterLoop * FBR_CHUNKS) + InnerLoop; + + + /****************************************************************** + Save the Virtual address of this index for quick access later + *****************************************************************/ + rx_ring->Fbr[1]->Va[index] = (PUCHAR)rx_ring->Fbr1MemVa[OuterLoop] + + ( InnerLoop * rx_ring->Fbr1BufferSize ) + + Fbr1Offset; + + + /****************************************************************** + now store the physical address in the descriptor so the device + can access it + *****************************************************************/ + rx_ring->Fbr[1]->PAHigh[index] = (UINT32)(Fbr1TempPa >> 32); + rx_ring->Fbr[1]->PALow[index] = (UINT32) Fbr1TempPa; + + Fbr1TempPa += rx_ring->Fbr1BufferSize; + + rx_ring->Fbr[1]->Buffer1[index] = rx_ring->Fbr[1]->Va[index]; + rx_ring->Fbr[1]->Buffer2[index] = rx_ring->Fbr[1]->Va[index] - 4; + } + } + +#ifdef USE_FBR0 + /************************************************************************** + Same for FBR0 (if in use) + *************************************************************************/ + for( OuterLoop = 0; OuterLoop < (rx_ring->Fbr0NumEntries / FBR_CHUNKS); OuterLoop++ ) + { + UINT64 Fbr0Offset; + UINT64 Fbr0TempPa; + + FBRChunkSize = (( FBR_CHUNKS + 1 ) * rx_ring->Fbr0BufferSize ) - 1; + rx_ring->Fbr0MemVa[OuterLoop] = pci_alloc_consistent( adapter->pdev, + FBRChunkSize, + &rx_ring->Fbr0MemPa[OuterLoop] ); + + if( !rx_ring->Fbr0MemVa[OuterLoop] ) + { + DBG_ERROR( et131x_dbginfo, "Could not alloc memory\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /********************************************************************** + See NOTE in "Save Physical Address" comment above + *********************************************************************/ + Fbr0TempPa = rx_ring->Fbr0MemPa[OuterLoop]; + + et131x_align_allocated_memory( adapter, + &Fbr0TempPa, + &Fbr0Offset, + rx_ring->Fbr0BufferSize - 1 ); + + + for( InnerLoop = 0; InnerLoop < FBR_CHUNKS; InnerLoop++ ) + { + UINT32 index = (OuterLoop * FBR_CHUNKS) + InnerLoop; + + rx_ring->Fbr[0]->Va[index] = (PUCHAR)rx_ring->Fbr0MemVa[OuterLoop] + + ( InnerLoop * rx_ring->Fbr0BufferSize ) + + Fbr0Offset; + + rx_ring->Fbr[0]->PAHigh[index] = (UINT32)(Fbr0TempPa >> 32); + rx_ring->Fbr[0]->PALow[index] = (UINT32) Fbr0TempPa; + + Fbr0TempPa += rx_ring->Fbr0BufferSize; + + rx_ring->Fbr[0]->Buffer1[index] = rx_ring->Fbr[0]->Va[index]; + rx_ring->Fbr[0]->Buffer2[index] = rx_ring->Fbr[0]->Va[index] - 4; + } + } +#endif + + /************************************************************************** + Allocate an area of memory for the FIFO of Packet Status ring entries + *************************************************************************/ + pktStatRingSize = sizeof( PKT_STAT_DESC_t ) * adapter->RxRing.PsrNumEntries; + + rx_ring->pPSRingVa = pci_alloc_consistent( adapter->pdev, + pktStatRingSize + 0x0fff, + &rx_ring->pPSRingPa ); + + if( !rx_ring->pPSRingVa ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for Packet Status Ring\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Save physical address + + NOTE : pci_alloc_consistent(), used above to alloc DMA regions, ALWAYS + returns SAC (32-bit) addresses. If DAC (64-bit) addresses are + ever returned, make sure the high part is retrieved here before + storing the adjusted address. + *************************************************************************/ + rx_ring->pPSRingRealPa = rx_ring->pPSRingPa; + + + /************************************************************************** + Align Packet Status Ring on a 4K boundary + *************************************************************************/ + et131x_align_allocated_memory( adapter, + &rx_ring->pPSRingRealPa, + &rx_ring->pPSRingOffset, + 0x0FFF ); + + rx_ring->pPSRingVa = (void *)( (PUCHAR)rx_ring->pPSRingVa + + rx_ring->pPSRingOffset ); + + + /************************************************************************** + Allocate an area of memory for the writeback of status information + *************************************************************************/ + rx_ring->pRxStatusVa = pci_alloc_consistent( adapter->pdev, + sizeof( RX_STATUS_BLOCK_t ) + 0x7, + &rx_ring->pRxStatusPa ); + if( !rx_ring->pRxStatusVa ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for Status Block\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Save physical address + *************************************************************************/ + rx_ring->RxStatusRealPA = rx_ring->pRxStatusPa; + + + /************************************************************************** + Align write back on an 8 byte boundary + *************************************************************************/ + et131x_align_allocated_memory( adapter, + &rx_ring->RxStatusRealPA, + &rx_ring->RxStatusOffset, + 0x07 ); + + rx_ring->pRxStatusVa = (void *)( (PUCHAR)rx_ring->pRxStatusVa + + rx_ring->RxStatusOffset ); + rx_ring->NumRfd = NIC_DEFAULT_NUM_RFD; + + + /************************************************************************** + Recv + pci_pool_create initializes a lookaside list. + After successful creation, nonpaged fixed-size blocks can be + allocated from and freed to the lookaside list. + + RFDs will be allocated from this pool. + *************************************************************************/ + rx_ring->RecvLookaside = + #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) + kmem_cache_create( adapter->netdev->name, + sizeof( MP_RFD ), + 0, + SLAB_CACHE_DMA | + SLAB_HWCACHE_ALIGN, + NULL, + NULL ); + #endif + #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)) + kmem_cache_create( adapter->netdev->name, + sizeof( MP_RFD ), + 0, + SLAB_CACHE_DMA | + SLAB_HWCACHE_ALIGN, + NULL); + #endif + + MP_SET_FLAG( adapter, fMP_ADAPTER_RECV_LOOKASIDE ); + + + /************************************************************************** + The RFDs are going to be put on lists later on, so initialize the lists + now. + *************************************************************************/ + INIT_LIST_HEAD( &rx_ring->RecvList ); + INIT_LIST_HEAD( &rx_ring->RecvPendingList ); + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_rx_dma_memory_free + ****************************************************************************** + + DESCRIPTION : Should basically free all memory allocated within this + module. + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_rx_dma_memory_free( ET131X_ADAPTER *adapter ) +{ + UINT32 index; + UINT32 bufsize; + UINT32 pktStatRingSize; + PMP_RFD pMpRfd; + RX_RING_t *rx_ring; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_rx_dma_memory_free" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Setup some convenience pointers + *************************************************************************/ + rx_ring = (RX_RING_t *)&adapter->RxRing; + + + /************************************************************************** + Free RFDs and associated packet descriptors + *************************************************************************/ + DBG_ASSERT( rx_ring->nReadyRecv == rx_ring->NumRfd ); + + while( !list_empty( &rx_ring->RecvList )) + { + pMpRfd = (MP_RFD *)list_entry( rx_ring->RecvList.next, + MP_RFD, + list_node ); + + list_del( &pMpRfd->list_node ); + et131x_rfd_resources_free( adapter, pMpRfd ); + } + + while( !list_empty( &rx_ring->RecvPendingList )) + { + pMpRfd = (MP_RFD *)list_entry( rx_ring->RecvPendingList.next, + MP_RFD, + list_node ); + list_del( &pMpRfd->list_node ); + et131x_rfd_resources_free( adapter, pMpRfd ); + } + + + /************************************************************************** + Free Free Buffer Ring 1 + *************************************************************************/ + if( rx_ring->pFbr1RingVa ) + { + /********************************************************************** + First the packet memory + *********************************************************************/ + for( index = 0; index < + (rx_ring->Fbr1NumEntries / FBR_CHUNKS); index++ ) + { + if( rx_ring->Fbr1MemVa[index] ) + { + UINT32 Fbr1Align; + + if( rx_ring->Fbr1BufferSize > 4096 ) + { + Fbr1Align = 4096; + } + else + { + Fbr1Align = rx_ring->Fbr1BufferSize; + } + + bufsize = ( rx_ring->Fbr1BufferSize * FBR_CHUNKS ) + + Fbr1Align - 1; + + pci_free_consistent( adapter->pdev, + bufsize, + rx_ring->Fbr1MemVa[index], + rx_ring->Fbr1MemPa[index] ); + + rx_ring->Fbr1MemVa[index] = 0; + } + } + + + /********************************************************************** + Now the FIFO itself + *********************************************************************/ + rx_ring->pFbr1RingVa = (void *)( (PUCHAR)rx_ring->pFbr1RingVa - + rx_ring->Fbr1offset ); + + bufsize = ( sizeof( FBR_DESC_t ) * rx_ring->Fbr1NumEntries ) + 0xfff; + + pci_free_consistent( adapter->pdev, + bufsize, + rx_ring->pFbr1RingVa, + rx_ring->pFbr1RingPa ); + + rx_ring->pFbr1RingVa = NULL; + } + + +#ifdef USE_FBR0 + /********************************************************************** + Now the same for Free Buffer Ring 0 + *********************************************************************/ + if( rx_ring->pFbr0RingVa ) + { + /********************************************************************** + First the packet memory + *********************************************************************/ + for( index = 0; index < + (rx_ring->Fbr0NumEntries / FBR_CHUNKS); index++ ) + { + if( rx_ring->Fbr0MemVa[index] ) + { + bufsize = ( rx_ring->Fbr0BufferSize * ( FBR_CHUNKS + 1 )) - 1; + + pci_free_consistent( adapter->pdev, + bufsize, + rx_ring->Fbr0MemVa[index], + rx_ring->Fbr0MemPa[index] ); + + rx_ring->Fbr0MemVa[index] = 0; + } + } + + + /********************************************************************** + Now the FIFO itself + *********************************************************************/ + rx_ring->pFbr0RingVa = (void *)( (PUCHAR)rx_ring->pFbr0RingVa - + rx_ring->Fbr0offset ); + + bufsize = ( sizeof( FBR_DESC_t ) * rx_ring->Fbr0NumEntries ) + 0xfff; + + pci_free_consistent( adapter->pdev, + bufsize, + rx_ring->pFbr0RingVa, + rx_ring->pFbr0RingPa ); + + rx_ring->pFbr0RingVa = NULL; + } +#endif + + + /************************************************************************** + Free Packet Status Ring + *************************************************************************/ + if( rx_ring->pPSRingVa ) + { + rx_ring->pPSRingVa = (void *)( (PUCHAR)rx_ring->pPSRingVa - + rx_ring->pPSRingOffset ); + + pktStatRingSize = sizeof( PKT_STAT_DESC_t ) * adapter->RxRing.PsrNumEntries; + + pci_free_consistent( adapter->pdev, + pktStatRingSize + 0x0fff, + rx_ring->pPSRingVa, + rx_ring->pPSRingPa ); + + rx_ring->pPSRingVa = NULL; + } + + + /********************************************************************** + Free area of memory for the writeback of status information + *********************************************************************/ + if( rx_ring->pRxStatusVa ) + { + rx_ring->pRxStatusVa = (void *)( (PUCHAR)rx_ring->pRxStatusVa - + rx_ring->RxStatusOffset ); + + pci_free_consistent( adapter->pdev, + sizeof( RX_STATUS_BLOCK_t ) + 0x7, + rx_ring->pRxStatusVa, + rx_ring->pRxStatusPa ); + + rx_ring->pRxStatusVa = NULL; + } + + + /************************************************************************** + Free receive buffer pool + *************************************************************************/ + + + /************************************************************************** + Free receive packet pool + *************************************************************************/ + + + /************************************************************************** + Destroy the lookaside (RFD) pool + *************************************************************************/ + if( MP_TEST_FLAG( adapter, fMP_ADAPTER_RECV_LOOKASIDE )) + { + kmem_cache_destroy( rx_ring->RecvLookaside ); + MP_CLEAR_FLAG( adapter, fMP_ADAPTER_RECV_LOOKASIDE ); + } + + + /************************************************************************** + Free the FBR Lookup Table + *************************************************************************/ +#ifdef USE_FBR0 + kfree( rx_ring->Fbr[0] ); +#endif + + kfree( rx_ring->Fbr[1] ); + + + /************************************************************************** + Reset Counters + *************************************************************************/ + rx_ring->nReadyRecv = 0; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_init_recv + ****************************************************************************** + + DESCRIPTION : Initialize receive data structures. + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_init_recv( ET131X_ADAPTER *adapter ) +{ + int status = -ENOMEM; + PMP_RFD pMpRfd = NULL; + UINT32 RfdCount; + UINT32 TotalNumRfd = 0; + RX_RING_t *rx_ring = NULL; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_init_recv" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Setup some convenience pointers + *************************************************************************/ + rx_ring = (RX_RING_t *)&adapter->RxRing; + + + /************************************************************************** + Setup each RFD + *************************************************************************/ + for( RfdCount = 0; RfdCount < rx_ring->NumRfd; RfdCount++ ) + { + pMpRfd = ( MP_RFD * )kmem_cache_alloc( rx_ring->RecvLookaside, + GFP_ATOMIC | GFP_DMA ); + + if( !pMpRfd ) + { + DBG_ERROR( et131x_dbginfo, "Couldn't alloc RFD out of kmem_cache\n" ); + + status = -ENOMEM; + continue; + } + + status = et131x_rfd_resources_alloc( adapter,pMpRfd ); + if( status != 0 ) + { + DBG_ERROR( et131x_dbginfo, "Couldn't alloc packet for RFD\n" ); + kmem_cache_free( rx_ring->RecvLookaside, pMpRfd ); + continue; + } + + + /********************************************************************** + Add this RFD to the RecvList + *********************************************************************/ + list_add_tail( &pMpRfd->list_node, &rx_ring->RecvList ); + + + /********************************************************************** + Increment both the available RFD's, and the total RFD's. + *********************************************************************/ + rx_ring->nReadyRecv++; + TotalNumRfd++; + } + + if( TotalNumRfd > NIC_MIN_NUM_RFD ) + { + status = 0; + } + + rx_ring->NumRfd = TotalNumRfd; + + if( status != 0 ) + { + kmem_cache_free( rx_ring->RecvLookaside, pMpRfd ); + DBG_ERROR( et131x_dbginfo, "Allocation problems in et131x_init_recv\n" ); + } + + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_rfd_resources_alloc + ****************************************************************************** + + DESCRIPTION : + + PARAMETERS : adapter - pointer to our private adapter structure + pMpRfd - pointer to a RFD + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_rfd_resources_alloc( ET131X_ADAPTER *adapter, MP_RFD *pMpRfd ) +{ + pMpRfd->Packet = NULL; + + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_rfd_resources_free + ****************************************************************************** + + DESCRIPTION : Free the packet allocated for the given RFD + + PARAMETERS : adapter - pointer to our private adapter structure + pMpRfd - pointer to a RFD + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_rfd_resources_free( ET131X_ADAPTER *adapter, MP_RFD *pMpRfd ) +{ + pMpRfd->Packet = NULL; + kmem_cache_free( adapter->RxRing.RecvLookaside, pMpRfd ); + + return; +} +/*===========================================================================*/ + + + + + +/****************************************************************************** + ROUTINE: ConfigRxDmaRegs + ****************************************************************************** + DESCRIPTION: + START OF Rx_DMA INIT SEQUENCE + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + + + *****************************************************************************/ +void ConfigRxDmaRegs( ET131X_ADAPTER *pAdapter ) +{ + PRXDMA_t pRxDma; + PFBR_DESC_t pFbrEntry; + UINT32 iEntry; + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigRxDmaRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Let's get our pointer to the RxDma section of regs + *************************************************************************/ + pRxDma = &pAdapter->CSRAddress->rxdma; + + + /************************************************************************** + Halt RXDMA to perform the reconfigure. + *************************************************************************/ + et131x_rx_dma_disable( pAdapter ); + + + /************************************************************************** + Load the completion writeback physical address + + NOTE : pci_alloc_consistent(), used above to alloc DMA regions, ALWAYS + returns SAC (32-bit) addresses. If DAC (64-bit) addresses are + ever returned, make sure the high part is retrieved here before + storing the adjusted address. + *************************************************************************/ + pRxDma->dma_wb_base_hi.addr_hi = (UINT32)( pAdapter->RxRing.RxStatusRealPA >> 32 ); + pRxDma->dma_wb_base_lo.addr_lo = (UINT32)( pAdapter->RxRing.RxStatusRealPA ); + + memset( pAdapter->RxRing.pRxStatusVa, 0, sizeof( RX_STATUS_BLOCK_t )); + + + /************************************************************************** + Set the address and parameters of the packet status ring into the 1310's + registers + *************************************************************************/ + pRxDma->psr_base_hi.addr_hi = (UINT32)( pAdapter->RxRing.pPSRingRealPa >> 32 ); + pRxDma->psr_base_lo.addr_lo = (UINT32)( pAdapter->RxRing.pPSRingRealPa ); + + pRxDma->psr_num_des.value = pAdapter->RxRing.PsrNumEntries - 1; + + pRxDma->psr_full_offset.value = 0; + + pRxDma->psr_min_des.value = + ( pRxDma->psr_num_des.bits.psr_ndes * LO_MARK_PERCENT_FOR_PSR ) / 100; + + spin_lock_irqsave( &pAdapter->RcvLock, lockflags ); + + + /************************************************************************** + These local variables track the PSR in the adapter structure + *************************************************************************/ + pAdapter->RxRing.local_psr_full.bits.psr_full = 0; + pAdapter->RxRing.local_psr_full.bits.psr_full_wrap = 0; + + + /************************************************************************** + Now's the best time to initialize FBR1 contents + *************************************************************************/ + pFbrEntry = (PFBR_DESC_t) pAdapter->RxRing.pFbr1RingVa; + + for (iEntry=0; iEntry < pAdapter->RxRing.Fbr1NumEntries; iEntry++) + { + pFbrEntry->addr_hi = pAdapter->RxRing.Fbr[1]->PAHigh[ iEntry ]; + pFbrEntry->addr_lo = pAdapter->RxRing.Fbr[1]->PALow [ iEntry ]; + pFbrEntry->word2.bits.bi = iEntry; + pFbrEntry++; + } + + + /************************************************************************** + Set the address and parameters of Free buffer ring 1 (and 0 if required) + into the 1310's registers + *************************************************************************/ + pRxDma->fbr1_base_hi.addr_hi = (UINT32)( pAdapter->RxRing.Fbr1Realpa >> 32 ); + pRxDma->fbr1_base_lo.addr_lo = (UINT32)( pAdapter->RxRing.Fbr1Realpa ); + + pRxDma->fbr1_num_des.value = pAdapter->RxRing.Fbr1NumEntries - 1; + + { + RXDMA_FBR_FULL_OFFSET_t fbr1_full; + + fbr1_full.bits.fbr_full = 0; + fbr1_full.bits.fbr_full_wrap = 1; + + pRxDma->fbr1_full_offset = fbr1_full; + } + + + /************************************************************************** + This variable tracks the free buffer ring 1 full position, so it has to + match the above. + *************************************************************************/ + pAdapter->RxRing.local_Fbr1_full.bits.fbr_full = 0; + pAdapter->RxRing.local_Fbr1_full.bits.fbr_full_wrap = 1; + + pRxDma->fbr1_min_des.bits.fbr_min = + (( pAdapter->RxRing.Fbr1NumEntries * LO_MARK_PERCENT_FOR_RX ) / 100) - 1; + + +#ifdef USE_FBR0 + /************************************************************************** + Now's the best time to initialize FBR0 contents + *************************************************************************/ + pFbrEntry = (PFBR_DESC_t) pAdapter->RxRing.pFbr0RingVa; + + for (iEntry=0; iEntry < pAdapter->RxRing.Fbr0NumEntries; iEntry++) + { + pFbrEntry->addr_hi = pAdapter->RxRing.Fbr[0]->PAHigh[iEntry]; + pFbrEntry->addr_lo = pAdapter->RxRing.Fbr[0]->PALow [iEntry]; + pFbrEntry->word2.bits.bi = iEntry; + pFbrEntry++; + } + + pRxDma->fbr0_base_hi.addr_hi = (UINT32)( pAdapter->RxRing.Fbr0Realpa >> 32 ); + pRxDma->fbr0_base_lo.addr_lo = (UINT32)( pAdapter->RxRing.Fbr0Realpa ); + + pRxDma->fbr0_num_des.bits.fbr_ndesc = pAdapter->RxRing.Fbr0NumEntries - 1; + + { + RXDMA_FBR_FULL_OFFSET_t fbr0_full; + + fbr0_full.bits.fbr_full = 0; + fbr0_full.bits.fbr_full_wrap = 1; + + pRxDma->fbr0_full_offset = fbr0_full; + } + + + /************************************************************************** + This variable tracks the free buffer ring 0 full position, so it has to + match the above. + *************************************************************************/ + pAdapter->RxRing.local_Fbr0_full.bits.fbr_full = 0; + pAdapter->RxRing.local_Fbr0_full.bits.fbr_full_wrap = 1; + + pRxDma->fbr0_min_des.bits.fbr_min = + (( pAdapter->RxRing.Fbr0NumEntries * LO_MARK_PERCENT_FOR_RX ) / 100) - 1; +#endif + + + /************************************************************************** + Program the number of packets we will receive before generating an + interrupt. + + For version B silicon, this value gets updated once autoneg is complete. + *************************************************************************/ + pRxDma->num_pkt_done.value = pAdapter->RegistryRxNumBuffers; + + + /************************************************************************** + The "time_done" is not working correctly to coalesce interrupts after + a given time period, but rather is giving us an interrupt regardless + of whether we have received packets. + + This value gets updated once autoneg is complete. + *************************************************************************/ + pRxDma->max_pkt_time.value = pAdapter->RegistryRxTimeInterval; + + spin_unlock_irqrestore( &pAdapter->RcvLock, lockflags ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: SetRxDmaTimer + ****************************************************************************** + DESCRIPTION: + SET the heartbeat timer according to line rate. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + N/A + + *****************************************************************************/ +void SetRxDmaTimer( ET131X_ADAPTER *pAdapter ) +{ + /************************************************************************** + For version B silicon, we do not use the RxDMA timer for 10 and 100 + Mbits/s line rates. We do not enable and RxDMA interrupt coalescing. + *************************************************************************/ + if(( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_100MBPS ) || + ( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS )) + { + pAdapter->CSRAddress->rxdma.max_pkt_time.value = 0; + pAdapter->CSRAddress->rxdma.num_pkt_done.value = 1; + } + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_rx_dma_disable + ****************************************************************************** + DESCRIPTION: + Stop OF Rx_DMA on the ET1310 + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + + + *****************************************************************************/ +void et131x_rx_dma_disable( ET131X_ADAPTER *pAdapter ) +{ + DBG_FUNC( "et131x_rx_dma_disable" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Setup the receive dma configuration register + *************************************************************************/ + pAdapter->CSRAddress->rxdma.csr.value = 0x00002001; + + if( pAdapter->CSRAddress->rxdma.csr.bits.halt_status != 1 ) + { + udelay( 5 ); + if( pAdapter->CSRAddress->rxdma.csr.bits.halt_status != 1 ) + { + DBG_ERROR( et131x_dbginfo, + "RX Dma failed to enter halt state. CSR 0x%08x\n", + pAdapter->CSRAddress->rxdma.csr.value ); + } + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_rx_dma_enable + ****************************************************************************** + DESCRIPTION: + re-start OF Rx_DMA on the ET1310. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + + + *****************************************************************************/ +void et131x_rx_dma_enable( ET131X_ADAPTER *pAdapter ) +{ + DBG_FUNC( "et131x_rx_dma_enable" ); + DBG_RX_ENTER( et131x_dbginfo ); + + + if( pAdapter->RegistryPhyLoopbk ) + { + /********************************************************************** + RxDMA is disabled for loopback operation. + *********************************************************************/ + pAdapter->CSRAddress->rxdma.csr.value = 0x1; + } + else + { + /********************************************************************** + Setup the receive dma configuration register for normal operation. + *********************************************************************/ + { + RXDMA_CSR_t csr = {0}; + + csr.bits.fbr1_enable = 1; + + if( pAdapter->RxRing.Fbr1BufferSize == 4096 ) + { + csr.bits.fbr1_size = 1; + } + else if( pAdapter->RxRing.Fbr1BufferSize == 8192 ) + { + csr.bits.fbr1_size = 2; + } + else if( pAdapter->RxRing.Fbr1BufferSize == 16384 ) + { + csr.bits.fbr1_size = 3; + } +#ifdef USE_FBR0 + csr.bits.fbr0_enable = 1; + + if( pAdapter->RxRing.Fbr0BufferSize == 256 ) + { + csr.bits.fbr0_size = 1; + } + else if( pAdapter->RxRing.Fbr0BufferSize == 512 ) + { + csr.bits.fbr0_size = 2; + } + else if( pAdapter->RxRing.Fbr0BufferSize == 1024 ) + { + csr.bits.fbr0_size = 3; + } +#endif + pAdapter->CSRAddress->rxdma.csr = csr; + } + + if( pAdapter->CSRAddress->rxdma.csr.bits.halt_status != 0 ) + { + udelay( 5 ); + if( pAdapter->CSRAddress->rxdma.csr.bits.halt_status != 0 ) + { + DBG_ERROR( et131x_dbginfo, + "RX Dma failed to exit halt state. CSR 0x%08x\n", + pAdapter->CSRAddress->rxdma.csr.value ); + } + } + } + + + DBG_RX_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: nic_rx_pkts + ****************************************************************************** + DESCRIPTION: + Checks the hardware for available packets, using completion ring + If packets are available, it gets an RFD from the RecvList, attaches + the packet to it, puts the RFD in the RecvPendList, and also returns + the pointer to the RFD. + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURNS : + pMpRfd - pointer to our MPRFD + + *****************************************************************************/ +PMP_RFD nic_rx_pkts( ET131X_ADAPTER *pAdapter ) +{ + PRX_STATUS_BLOCK_t pRxStatusBlock; + PPKT_STAT_DESC_t pPSREntry; + PMP_RFD pMpRfd; + UINT32 nIndex; + PUCHAR pBufVa; + PUINT16 pShBufVa; + unsigned long lockflags; + struct list_head *element; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "nic_rx_pkts" ); + DBG_RX_ENTER( et131x_dbginfo ); + + + /************************************************************************** + RX Status block is written by the DMA engine prior to every interrupt. + It contains the next to be used entry in the Packet Status Ring, and + also the two Free Buffer rings. + *************************************************************************/ + pRxStatusBlock = (PRX_STATUS_BLOCK_t)pAdapter->RxRing.pRxStatusVa; + + if(( pRxStatusBlock->Word1.bits.PSRoffset != + pAdapter->RxRing.local_psr_full.bits.psr_full ) || + ( pRxStatusBlock->Word1.bits.PSRwrap != + pAdapter->RxRing.local_psr_full.bits.psr_full_wrap )) + { + UINT8 ringIndex; + UINT16 bufferIndex; + UINT32 localLen; + PKT_STAT_DESC_WORD0_t Word0; + + + /********************************************************************** + The packet status ring indicates that data is available. + *********************************************************************/ + pPSREntry = (PPKT_STAT_DESC_t)( pAdapter->RxRing.pPSRingVa ) + + pAdapter->RxRing.local_psr_full.bits.psr_full; + + + /********************************************************************** + Grab any information that is required once the PSR is advanced, + since we can no longer rely on the memory being accurate + *********************************************************************/ + localLen = pPSREntry->word1.bits.length; + ringIndex = (UINT8)pPSREntry->word1.bits.ri; + bufferIndex = (UINT16)pPSREntry->word1.bits.bi; + Word0 = pPSREntry->word0; + + DBG_RX( et131x_dbginfo, "RX PACKET STATUS\n" ); + DBG_RX( et131x_dbginfo, "\tlength : %d\n", localLen ); + DBG_RX( et131x_dbginfo, "\tringIndex : %d\n", ringIndex ); + DBG_RX( et131x_dbginfo, "\tbufferIndex : %d\n", bufferIndex ); + DBG_RX( et131x_dbginfo, "\tword0 : 0x%08x\n", Word0.value ); + + +#if 0 + /********************************************************************** + Check the Status Word that the MAC has appended to the PSR entry in + case the MAC has detected errors. + *********************************************************************/ + if( Word0.value & ALCATEL_BAD_STATUS ) + { + DBG_ERROR( et131x_dbginfo, + "NICRxPkts >> Alcatel Status Word error." + "Value 0x%08x\n", + pPSREntry->word0.value ); + } +#endif + + + /********************************************************************** + Indicate that we have used this PSR entry. + *********************************************************************/ + if( ++pAdapter->RxRing.local_psr_full.bits.psr_full > + ( pAdapter->RxRing.PsrNumEntries - 1 )) + { + pAdapter->RxRing.local_psr_full.bits.psr_full = 0; + pAdapter->RxRing.local_psr_full.bits.psr_full_wrap ^= 1; + } + + pAdapter->CSRAddress->rxdma.psr_full_offset = + pAdapter->RxRing.local_psr_full; + +#ifndef USE_FBR0 + if( ringIndex != 1 ) + { + DBG_ERROR( et131x_dbginfo, + "NICRxPkts PSR Entry %d indicates " + "Buffer Ring 0 in use\n", + pAdapter->RxRing.local_psr_full.bits.psr_full ); + + DBG_RX_LEAVE( et131x_dbginfo ); + return NULL; + } +#endif + +#ifdef USE_FBR0 + if(( ringIndex > 1 ) || + (( ringIndex == 0 ) && ( bufferIndex > ( pAdapter->RxRing.Fbr0NumEntries - 1 ))) || + (( ringIndex == 1 ) && ( bufferIndex > ( pAdapter->RxRing.Fbr1NumEntries - 1 )))) +#else + if(( ringIndex != 1 ) || ( bufferIndex > ( pAdapter->RxRing.Fbr1NumEntries - 1 ))) +#endif + { + /****************************************************************** + Illegal buffer or ring index cannot be used by the S/W + *****************************************************************/ + DBG_ERROR( et131x_dbginfo, + "NICRxPkts PSR Entry %d indicates " + "length of %d and/or bad bi(%d)\n", + pAdapter->RxRing.local_psr_full.bits.psr_full, + localLen, + bufferIndex ); + + DBG_RX_LEAVE( et131x_dbginfo ); + return NULL; + } + + + /********************************************************************** + Get and fill the RFD. + *********************************************************************/ + spin_lock_irqsave( &pAdapter->RcvLock, lockflags ); + + pMpRfd = NULL; + element = pAdapter->RxRing.RecvList.next; + pMpRfd = (PMP_RFD)list_entry( element, MP_RFD, list_node ); + + if( pMpRfd == NULL ) + { + DBG_RX( et131x_dbginfo, + "NULL RFD returned from RecvList via list_entry()\n" ); + DBG_RX_LEAVE( et131x_dbginfo ); + return NULL; + } + + list_del( &pMpRfd->list_node ); + pAdapter->RxRing.nReadyRecv--; + + spin_unlock_irqrestore( &pAdapter->RcvLock, lockflags ); + + pMpRfd->iBufferIndex = bufferIndex; + pMpRfd->iRingIndex = ringIndex; + + + /********************************************************************** + In V1 silicon, there is a bug which screws up filtering of runt + packets. Therefore runt packet filtering is disabled in the MAC + and the packets are dropped here. They are also counted here. + *********************************************************************/ + if( localLen < ( NIC_MIN_PACKET_SIZE + 4 )) + { + pAdapter->Stats.other_errors++; + localLen = 0; + } + + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + if( localLen ) + { + pShBufVa = pAdapter->RxRing.Fbr[ringIndex]->Va[bufferIndex]; + + pMpRfd->bHasVLANTag = FALSE; + + + /****************************************************************** + The protocol value of 0x8100 means there is a VLAN tag in the + packet. Also the original protocol value will be present four + bytes further on. + *****************************************************************/ + if( pShBufVa[6] == 0x0081 ) + { + UINT16 LocalShort = (( pShBufVa[7] & 0xff00 ) >> 8 ) + + (( pShBufVa[7] & 0x00ff ) << 8 ); + UINT16 vlan_tag = LocalShort & 0x0fff; + + pMpRfd->bHasVLANTag = TRUE; + + DBG_RX( et131x_dbginfo, + "VLAN: RX packet Tag: %d\n", vlan_tag ); + + + /************************************************************** + The rules are: + - if our VLAN tag is zero we can pass anything up + - if our VLAN tag matches the incoming we can pass it + - If the packet is a protocol 802.3ad we pass it + regardless (802.3ad had protocol val of 0x8809. + proto val is now in ShBuf [8]) + - If the packet is a GARP VLAN Registration Protocol + (GVRP) packet, we pass it regardless. + 01:80:c2:00:00:21 is the GVRP address. + + NOTE: Because the ET1310 doesn't perform VLAN tagging + (it's done in the kernel) always pass packets up. + We'll leave this code in, however, just in case it's + needed in the future. + *************************************************************/ + if(( 1 ) || + ( pShBufVa[8] == 0x0988 ) || + (( pShBufVa[0] == 0x8001 ) && + ( pShBufVa[1] == 0x00c2 ) && + ( pShBufVa[2] == 0x2100 ))) + { + DBG_RX( et131x_dbginfo, + "VLAN: Passed test, send pkt up\n" ); + pMpRfd->VLANTag = vlan_tag; + } + else + { + /********************************************************* + Our VLAN tag is non-zero, AND the incoming tag does + not match it. Drop the packet. + ********************************************************/ + DBG_RX( et131x_dbginfo, + "VLAN: no match, drop pkt\n" ); + localLen = 0; + } + } + else if(( pShBufVa[6] == 0x0988 ) || + (( pShBufVa[0] == 0x8001 ) && + ( pShBufVa[1] == 0x00c2 ) && + ( pShBufVa[2] == 0x2100 ))) + { + /****************************************************************** + The protocol type (ethertype) of 0x8809 corresponds to 802.3ad + The MAC address of 01:80:c2:00:00:21 is the GARP VLAN + registration protocol (GVRP) address. + + Both of these message types should be passed up regardless + of their VLAN tagging. + *****************************************************************/ + DBG_RX( et131x_dbginfo, + "VLAN: No tag, but 802.3ad/GVRP, send pkt up\n" ); + } + else + { + /****************************************************************** + Our VLAN tag is non-zero. no VLAN header on incoming. + Packet is not GVRP or 802.3ad. Drop the packet. + *****************************************************************/ + DBG_RX( et131x_dbginfo, + "VLAN: No RX packet tag\n" ); + // NOTE: Same as the note above; never drop a packet for now. + // localLen = 0; + } + } +#endif + + if( localLen ) + { + if ( pAdapter->ReplicaPhyLoopbk == 1 ) + { + pBufVa = pAdapter->RxRing.Fbr[ringIndex]->Va[bufferIndex]; + + if( memcmp( &pBufVa[6], &pAdapter->CurrentAddress[0], ETH_ALEN ) == 0 ) + { + if( memcmp( &pBufVa[42], "Replica packet", ETH_HLEN )) + { + pAdapter->ReplicaPhyLoopbkPF = 1; + } + } + DBG_WARNING( et131x_dbginfo, + "pBufVa:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + pBufVa[6], + pBufVa[7], + pBufVa[8], + pBufVa[9], + pBufVa[10], + pBufVa[11] ); + + DBG_WARNING( et131x_dbginfo, + "CurrentAddr:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + pAdapter->CurrentAddress[0], + pAdapter->CurrentAddress[1], + pAdapter->CurrentAddress[2], + pAdapter->CurrentAddress[3], + pAdapter->CurrentAddress[4], + pAdapter->CurrentAddress[5] ); + } + + /****************************************************************** + Determine if this is a multicast packet coming in + *****************************************************************/ + if(( Word0.value & ALCATEL_MULTICAST_PKT ) && + !( Word0.value & ALCATEL_BROADCAST_PKT )) + { + /************************************************************** + Promiscuous mode and Multicast mode are not mutually + exclusive as was first thought. I guess Promiscuous is + just considered a super-set of the other filters. + Generally filter is 0x2b when in promiscuous mode. + *************************************************************/ + if(( pAdapter->PacketFilter & ET131X_PACKET_TYPE_MULTICAST ) && + !( pAdapter->PacketFilter & ET131X_PACKET_TYPE_PROMISCUOUS ) && + !( pAdapter->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST )) + { + pBufVa = pAdapter->RxRing.Fbr[ringIndex]->Va[bufferIndex]; + + /********************************************************** + Loop through our list to see if the destination address + of this packet matches one in our list. + *********************************************************/ + for( nIndex = 0; nIndex < pAdapter->MCAddressCount; nIndex++ ) + { + if( pBufVa[0] == pAdapter->MCList[nIndex][0] && + pBufVa[1] == pAdapter->MCList[nIndex][1] && + pBufVa[2] == pAdapter->MCList[nIndex][2] && + pBufVa[3] == pAdapter->MCList[nIndex][3] && + pBufVa[4] == pAdapter->MCList[nIndex][4] && + pBufVa[5] == pAdapter->MCList[nIndex][5] ) + { + break; + } + } + + /********************************************************** + If our index is equal to the number of Multicast + address we have, then this means we did not find this + packet's matching address in our list. Set the + PacketSize to zero, so we free our RFD when we return + from this function. + *********************************************************/ + if( nIndex == pAdapter->MCAddressCount ) + { + localLen = 0; + } + } + + if( localLen > 0 ) + { + pAdapter->Stats.multircv++; + } + } + else if( Word0.value & ALCATEL_BROADCAST_PKT ) + { + pAdapter->Stats.brdcstrcv++; + } + else + { + /************************************************************** + Not sure what this counter measures in promiscuous mode. + Perhaps we should check the MAC address to see if it is + directed to us in promiscuous mode. + *************************************************************/ + pAdapter->Stats.unircv++; + } + } + + if( localLen > 0 ) + { + struct sk_buff *skb = NULL; + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#ifdef __vlan_get_tag + unsigned short vlan_tag = 0; +#endif +#endif + + //vlan_tag = 0; + + //pMpRfd->PacketSize = localLen - 4; + pMpRfd->PacketSize = localLen; + + skb = dev_alloc_skb( pMpRfd->PacketSize + 2 ); + if( !skb ) + { + DBG_ERROR( et131x_dbginfo, "Couldn't alloc an SKB for Rx\n" ); + DBG_RX_LEAVE( et131x_dbginfo ); + return NULL; + } + + pAdapter->net_stats.rx_bytes += pMpRfd->PacketSize; + + memcpy( skb_put( skb, pMpRfd->PacketSize ), + pAdapter->RxRing.Fbr[ringIndex]->Va[bufferIndex], + pMpRfd->PacketSize ); + + skb->dev = pAdapter->netdev; + skb->protocol = eth_type_trans( skb, pAdapter->netdev ); + skb->ip_summed = CHECKSUM_NONE; + + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#if defined __vlan_get_tag + if( __vlan_get_tag( skb, &vlan_tag ) == -EINVAL ) + { + DBG_RX( et131x_dbginfo, + "VLAN: No Rx packet tag\n" ); + } + else + { + DBG_RX( et131x_dbginfo, + "VLAN: Rx packet tag: %d\n", vlan_tag ); + } +#endif +#endif + + netif_rx( skb ); + } + else + { + pMpRfd->PacketSize = 0; + } + + nic_return_rfd( pAdapter, pMpRfd ); + + + DBG_RX( et131x_dbginfo, "(1)\n" ); + DBG_RX_LEAVE( et131x_dbginfo ); + return pMpRfd; + } + else + { + /********************************************************************** + Looks like this ring is not updated yet + *********************************************************************/ + DBG_RX( et131x_dbginfo, "(0)\n" ); + DBG_RX_LEAVE( et131x_dbginfo ); + return NULL; + } +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_reset_recv + ****************************************************************************** + DESCRIPTION: + Reset the receive list + + Assumption: Rcv spinlock has been acquired + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURNS : + NONE + + *****************************************************************************/ +void et131x_reset_recv( ET131X_ADAPTER *pAdapter ) +{ + PMP_RFD pMpRfd; + struct list_head *element; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_reset_recv" ); + DBG_ENTER( et131x_dbginfo ); + + + DBG_ASSERT( !list_empty( &pAdapter->RxRing.RecvList )); + + + /************************************************************************** + Take all the RFD's from the pending list, and stick them on the + RecvList. + *************************************************************************/ + while( !list_empty( &pAdapter->RxRing.RecvPendingList ) ) + { + element = pAdapter->RxRing.RecvPendingList.next; + + pMpRfd = (PMP_RFD)list_entry( element, MP_RFD, list_node ); + + list_del( &pMpRfd->list_node ); + list_add_tail( &pMpRfd->list_node, &pAdapter->RxRing.RecvList ); + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_handle_recv_interrupt + ****************************************************************************** + DESCRIPTION: + Interrupt handler for receive processing + + Assumption: Rcv spinlock has been acquired + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURNS : + NONE + + *****************************************************************************/ +void et131x_handle_recv_interrupt( ET131X_ADAPTER *pAdapter ) +{ + PMP_RFD pMpRfd = NULL; + struct sk_buff *PacketArray [NUM_PACKETS_HANDLED]; + PMP_RFD RFDFreeArray[NUM_PACKETS_HANDLED]; + UINT32 PacketArrayCount = 0; + UINT32 PacketsToHandle; + UINT32 PacketFreeCount = 0; + BOOL_t TempUnfinishedRec = FALSE; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_handle_recv_interrupt" ); + DBG_RX_ENTER( et131x_dbginfo ); + + + PacketsToHandle = NUM_PACKETS_HANDLED; + + + /************************************************************************** + Process up to available RFD's + *************************************************************************/ + while( PacketArrayCount < PacketsToHandle ) + { + if( list_empty( &pAdapter->RxRing.RecvList )) + { + DBG_ASSERT( pAdapter->RxRing.nReadyRecv == 0 ); + DBG_ERROR( et131x_dbginfo, "NO RFD's !!!!!!!!!!!!!\n" ); + TempUnfinishedRec = TRUE; + break; + } + + pMpRfd = nic_rx_pkts( pAdapter ); + + if( pMpRfd == NULL) + { + break; + } + + + /********************************************************************** + Do not receive any packets until a filter has been set. + Do not receive any packets until we are at D0. + Do not receive any packets until we have link. + If length is zero, return the RFD in order to advance the Free + buffer ring. + *********************************************************************/ + if(( !pAdapter->PacketFilter ) || + ( pAdapter->PoMgmt.PowerState != NdisDeviceStateD0 ) || + ( !MP_LINK_DETECTED( pAdapter )) || + ( pMpRfd->PacketSize == 0 )) + { + continue; + } + + + /********************************************************************** + Increment the number of packets we received + *********************************************************************/ + pAdapter->Stats.ipackets++; + + + /********************************************************************** + Set the status on the packet, either resources or success + *********************************************************************/ + if( pAdapter->RxRing.nReadyRecv >= RFD_LOW_WATER_MARK ) + { + /****************************************************************** + Put this RFD on the pending list + + NOTE - nic_rx_pkts() above is already returning the RFD to the + RecvList, so don't additionally do that here. + + Besides, we don't really need (at this point) the pending list + anyway. + *****************************************************************/ + //spin_lock_irqsave( &pAdapter->RcvPendLock, lockflags ); + //list_add_tail( &pMpRfd->list_node, &pAdapter->RxRing.RecvPendingList ); + //spin_unlock_irqrestore( &pAdapter->RcvPendLock, lockflags ); + + + /****************************************************************** + Update the number of outstanding Recvs + *****************************************************************/ + //MP_INC_RCV_REF( pAdapter ); + } + else + { + RFDFreeArray[PacketFreeCount] = pMpRfd; + PacketFreeCount++; + + DBG_WARNING( et131x_dbginfo, "RFD's are running out !!!!!!!!!!!!!\n" ); + } + + PacketArray[PacketArrayCount] = pMpRfd->Packet; + PacketArrayCount++; + } + + + if(( PacketArrayCount == NUM_PACKETS_HANDLED ) || TempUnfinishedRec ) + { + pAdapter->RxRing.UnfinishedReceives = TRUE; + pAdapter->CSRAddress->global.watchdog_timer = + pAdapter->RegistryTxTimeInterval * NANO_IN_A_MICRO; + } + else + { + /********************************************************************** + Watchdog timer will disable itself if appropriate. + *********************************************************************/ + pAdapter->RxRing.UnfinishedReceives = FALSE; + } + + + DBG_RX_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: NICReturnRFD + ****************************************************************************** + DESCRIPTION: + Recycle a RFD and put it back onto the receive list + + PARAMETERS : + pAdapter - pointer to our adapter + pMpRfd - pointer to the RFD + + RETURNS : + NONE + + *****************************************************************************/ +void nic_return_rfd( ET131X_ADAPTER *pAdapter, PMP_RFD pMpRfd ) +{ + UINT16 ReturnedBI = pMpRfd->iBufferIndex; + UINT8 ReturnedRI = pMpRfd->iRingIndex; + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "nic_return_rfd" ); + DBG_RX_ENTER( et131x_dbginfo ); + + + /************************************************************************** + We don't use any of the OOB data besides status + Otherwise, we need to clean up OOB data + *************************************************************************/ + if( +#ifdef USE_FBR0 + (( ReturnedRI == 0 ) && ( ReturnedBI < pAdapter->RxRing.Fbr0NumEntries )) || +#endif + (( ReturnedRI == 1 ) && ( ReturnedBI < pAdapter->RxRing.Fbr1NumEntries ))) + { + spin_lock_irqsave( &pAdapter->FbrLock, lockflags ); + + if( ReturnedRI == 1 ) + { + PFBR_DESC_t pNextDesc = (PFBR_DESC_t)(pAdapter->RxRing.pFbr1RingVa) + + pAdapter->RxRing.local_Fbr1_full.bits.fbr_full; + + /****************************************************************** + Handle the Free Buffer Ring advancement here. Write the + PA / Buffer Index for the returned buffer into the oldest + (next to be freed)FBR entry + *****************************************************************/ + pNextDesc->addr_hi = pAdapter->RxRing.Fbr[1]->PAHigh[ReturnedBI]; + pNextDesc->addr_lo = pAdapter->RxRing.Fbr[1]->PALow[ReturnedBI]; + pNextDesc->word2.value = ReturnedBI; + + if( ++pAdapter->RxRing.local_Fbr1_full.bits.fbr_full > + ( pAdapter->RxRing.Fbr1NumEntries - 1 )) + { + pAdapter->RxRing.local_Fbr1_full.bits.fbr_full = 0; + pAdapter->RxRing.local_Fbr1_full.bits.fbr_full_wrap ^= 1; + } + + pAdapter->CSRAddress->rxdma.fbr1_full_offset = + pAdapter->RxRing.local_Fbr1_full; + } +#ifdef USE_FBR0 + else + { + PFBR_DESC_t pNextDesc = (PFBR_DESC_t)(pAdapter->RxRing.pFbr0RingVa) + + pAdapter->RxRing.local_Fbr0_full.bits.fbr_full; + + /****************************************************************** + Handle the Free Buffer Ring advancement here. Write the + PA / Buffer Index for the returned buffer into the oldest + (next to be freed) FBR entry + *****************************************************************/ + pNextDesc->addr_hi = pAdapter->RxRing.Fbr[0]->PAHigh[ReturnedBI]; + pNextDesc->addr_lo = pAdapter->RxRing.Fbr[0]->PALow[ReturnedBI]; + pNextDesc->word2.value = ReturnedBI; + + if( ++pAdapter->RxRing.local_Fbr0_full.bits.fbr_full > + (pAdapter->RxRing.Fbr0NumEntries - 1)) + { + pAdapter->RxRing.local_Fbr0_full.bits.fbr_full = 0; + pAdapter->RxRing.local_Fbr0_full.bits.fbr_full_wrap ^= 1; + } + + pAdapter->CSRAddress->rxdma.fbr0_full_offset = + pAdapter->RxRing.local_Fbr0_full; + } +#endif + spin_unlock_irqrestore( &pAdapter->FbrLock, lockflags ); + } + else + { + DBG_ERROR( et131x_dbginfo, + "NICReturnRFD illegal Buffer Index returned\n" ); + } + + + /************************************************************************** + The processing on this RFD is done, so put it back on the tail of + our list + *************************************************************************/ + spin_lock_irqsave( &pAdapter->RcvLock, lockflags ); + + list_add_tail( &pMpRfd->list_node, &pAdapter->RxRing.RecvList ); + pAdapter->RxRing.nReadyRecv++; + + spin_unlock_irqrestore( &pAdapter->RcvLock, lockflags ); + + DBG_ASSERT( pAdapter->RxRing.nReadyRecv <= pAdapter->RxRing.NumRfd ); + + + DBG_RX_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_common.h +++ linux-2.6.27/ubuntu/et131x/ET1310_common.h @@ -0,0 +1,97 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310.h - Common defines, structs, enums, prototypes, etc. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:10 $ + $Revision: 1.5 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET1310_COMMON_H__ +#define __ET1310_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/****************************************************************************** + INCLUDES + *****************************************************************************/ +#include "ET1310_address_map.h" + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ET1310_COMMON_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_initpci.c +++ linux-2.6.27/ubuntu/et131x/et131x_initpci.c @@ -0,0 +1,1839 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_initpci.c - Routines and data used to register the driver with the + * PCI (and PCI Express) subsystem, as well as basic driver + * init and startup. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/25 20:48:56 $ + $Revision: 1.22 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#include +#endif + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_netdev.h" +#include "et131x_config.h" +#include "et131x_isr.h" + +#include "ET1310_address_map.h" +#include "ET1310_jagcore.h" +#include "ET1310_tx.h" +#include "ET1310_rx.h" +#include "ET1310_mac.h" +#include "ET1310_eeprom.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Prototypes for functions with local scope + *****************************************************************************/ +int __devinit et131x_pci_probe( struct pci_dev *pdev, + const struct pci_device_id *ent ); + +void __devexit et131x_pci_remove( struct pci_dev *pdev ); + +int et131x_pci_setup( struct pci_dev *pdev ); + + + + +/****************************************************************************** + Data for PCI registration + *****************************************************************************/ +enum et131x_pci_versions +{ + Agere_Systems_PCI_V1 = 0, +}; + + +static struct pci_device_id et131x_pci_table[] __devinitdata = +{ + { ET131X_PCI_VENDOR_ID, ET131X_PCI_DEVICE_ID_GIG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { ET131X_PCI_VENDOR_ID, ET131X_PCI_DEVICE_ID_FAST, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0, } +}; + +MODULE_DEVICE_TABLE( pci, et131x_pci_table ); + + +static struct pci_driver et131x_driver = +{ + name: DRIVER_NAME, + id_table: et131x_pci_table, + probe: et131x_pci_probe, + remove: __devexit_p( et131x_pci_remove ), + suspend: NULL, //et131x_pci_suspend, + resume: NULL, //et131x_pci_resume, +}; + + + + +/****************************************************************************** + ROUTINE : et131x_find_adapter + ****************************************************************************** + + DESCRIPTION : Find the adapter and get all the assigned resources + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_find_adapter( ET131X_ADAPTER *adapter, struct pci_dev *pdev ) +{ + int result; + UCHAR eepromStat = 0; + UCHAR maxPayload = 0; + UCHAR latencyTimers = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_find_adapter" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Allow disabling of Non-Maskable Interrupts in I/O space, to + support validation. + *************************************************************************/ + if( adapter->RegistryNMIDisable ) + { + UCHAR RegisterVal; + + RegisterVal = inb( ET1310_NMI_DISABLE ); + RegisterVal &= 0xf3; + + if( adapter->RegistryNMIDisable == 2 ) + { + RegisterVal |= 0xc; + } + + outb( ET1310_NMI_DISABLE, RegisterVal ); + } + + + /************************************************************************** + We first need to check the EEPROM Status code located at offset 0xB2 + of config space + *************************************************************************/ + + result = pci_slot_information_read( pdev, + ET1310_PCI_EEPROM_STATUS, + &eepromStat, + sizeof( UCHAR )); + /************************************************************************* + THIS IS A WORKAROUND: + * I need to call this function twice to get my card in a + LG M1 Express Dual running. I tried also a msleep before this + function, because I thougth there could be some time condidions + but it didn't work. Call the whole function twice also work. + *************************************************************************/ + result = pci_slot_information_read( pdev, + ET1310_PCI_EEPROM_STATUS, + &eepromStat, + sizeof( UCHAR )); + + if( result != sizeof( UCHAR )) + { + DBG_ERROR( et131x_dbginfo, "Could not read PCI config space for " + "EEPROM Status\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + + /************************************************************************** + Determine if the error(s) we care about are present. If they are + present, we need to fail. + *************************************************************************/ + if( eepromStat & 0x4C ) + { + result = pci_slot_information_read( pdev, + PCI_REVISION_ID, + &adapter->RevisionID, + sizeof( UCHAR )); + if( result != sizeof( UCHAR )) + { + DBG_ERROR( et131x_dbginfo, + "Could not read PCI config space for " + "Revision ID\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + else if( adapter->RevisionID == 0x01 ) + { + INT32 nLoop; + UCHAR ucTemp[4] = {0xFE, 0x13, 0x10, 0xFF}; + + /****************************************************************** + Re-write the first 4 bytes if we have an eeprom present and + the revision id is 1, this fixes the corruption seen with + 1310 B Silicon + *****************************************************************/ + for( nLoop = 0; nLoop < 3; nLoop++ ) + { + EepromWriteByte( adapter, nLoop, ucTemp[nLoop], 0, SINGLE_BYTE ); + } + } + + DBG_ERROR( et131x_dbginfo, "Fatal EEPROM Status Error - 0x%04x\n", + eepromStat ); + + /********************************************************************** + This error could mean that there was an error reading the eeprom + or that the eeprom doesn't exist. We will treat each case the + same and not try to gather additional information that normally + would come from the eeprom, like MAC Address + *********************************************************************/ + adapter->bEepromPresent = FALSE; + + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + else + { + DBG_TRACE( et131x_dbginfo, "EEPROM Status Code - 0x%04x\n", eepromStat ); + adapter->bEepromPresent = TRUE; + } + + + /************************************************************************** + Read the EEPROM for information regarding LED behavior. Refer to + ET1310_phy.c, et131x_xcvr_init(), for its use. + *************************************************************************/ + EepromReadByte( adapter, 0x70, &adapter->eepromData [0], 0, SINGLE_BYTE ); + EepromReadByte( adapter, 0x71, &adapter->eepromData [1], 0, SINGLE_BYTE ); + + if( adapter->eepromData[0] != 0xcd ) + { + adapter->eepromData[1] = 0x00; // Disable all optional features + } + + + /************************************************************************** + Let's set up the PORT LOGIC Register. First we need to know what the + max_payload_size is + *************************************************************************/ + result = pci_slot_information_read( pdev, + ET1310_PCI_MAX_PYLD, + &maxPayload, + sizeof( UCHAR )); + + if( result != sizeof( UCHAR )) + { + DBG_ERROR( et131x_dbginfo, "Could not read PCI config space for " + "Max Payload Size\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + else + { + UINT16 AckNak [2] = {0x76, 0xD0}; + UINT16 Replay [2] = {0x1E0, 0x2ED}; + + + /********************************************************************** + Program the Ack/Nak latency and replay timers + *********************************************************************/ + maxPayload &= 0x07; // Only the lower 3 bits are valid + + if( maxPayload < 2 ) + { + result = pci_slot_information_write( pdev, + ET1310_PCI_ACK_NACK, + (UINT8 *)&AckNak[maxPayload], + sizeof( UINT16 )); + if( result != sizeof( UINT16 )) + { + DBG_ERROR( et131x_dbginfo, "Could not write PCI config space " + "for ACK/NAK\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + result = pci_slot_information_write( pdev, + ET1310_PCI_REPLAY, + (UINT8 *)&Replay[maxPayload], + sizeof( UINT16 )); + if( result != sizeof( UINT16 )) + { + DBG_ERROR( et131x_dbginfo, "Could not write PCI config space " + "for Replay Timer\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + } + } + + + /************************************************************************** + l0s and l1 latency timers. We are using default values. + *************************************************************************/ + latencyTimers = 0x11; // Representing 001 for L0s and 010 for L1 + + result = pci_slot_information_write( pdev, + ET1310_PCI_L0L1LATENCY, + (UINT8 *)&latencyTimers, + sizeof( UCHAR )); + if( result != sizeof( UCHAR )) + { + DBG_ERROR( et131x_dbginfo, "Could not write PCI config space for " + "Latency Timers\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + + /************************************************************************** + Archive Power management capability values for later use + *************************************************************************/ + result = pci_slot_information_read( pdev, + ET1310_PCI_PM_CAPABILITY, + (UINT8 *)&adapter->PoMgmt.pmConfigRegs, + sizeof( MP_PM_CONFIG_SPACE_INFO_t )); + if( result != sizeof( MP_PM_CONFIG_SPACE_INFO_t )) + { + DBG_ERROR( et131x_dbginfo, + "Could not read PCI config space for PM Capability\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + else + { + UCHAR read_size_reg; + + /****************************************************************** + Change the max read size to 2k + *****************************************************************/ + result = pci_slot_information_read( pdev, + 0x51, + (void *)&read_size_reg, + sizeof( UCHAR )); + + if( result != sizeof( UCHAR )) + { + DBG_ERROR( et131x_dbginfo, + "Could not read PCI config space for Max read size\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + read_size_reg &= 0x8f; + read_size_reg |= 0x40; + + result = pci_slot_information_write( pdev, + 0x51, + &read_size_reg, + sizeof( UCHAR )); + if( result != sizeof( UCHAR )) + { + DBG_ERROR( et131x_dbginfo, + "Could not write PCI config space for Max read size\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + } + + + /************************************************************************** + PCI Express Configuration registers 0x48-0x5B (Device Control) + *************************************************************************/ + result = pci_slot_information_read( pdev, + ET1310_PCI_DEV_CTRL, + (UINT8 *)&adapter->PciXDevCtl, + sizeof( UINT16 )); + + if( result != sizeof( UINT16 )) + { + DBG_ERROR( et131x_dbginfo, + "Could not read PCI config space for PCI Express Dev Ctl\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + + /************************************************************************** + Get MAC address from config space if an eeprom exists, otherwise the + MAC address there will not be valid + *************************************************************************/ + if( adapter->bEepromPresent ) + { + result = pci_slot_information_read( pdev, + ET1310_PCI_MAC_ADDRESS, + (UINT8 *)adapter->PermanentAddress, + ETH_ALEN ); + if( result != ETH_ALEN ) + { + DBG_ERROR( et131x_dbginfo, + "Could not read PCI config space for MAC address\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + } + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_error_timer_handler + ****************************************************************************** + + DESCRIPTION : The routine called when the error timer expires, to + track the number of recurring errors. + + PARAMETERS : data - a timer-specific variable; in this case, a + pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_error_timer_handler( unsigned long data ) +{ + ET131X_ADAPTER *pAdapter = (ET131X_ADAPTER *)data; + PM_CSR_t pm_csr; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_error_timer_handler" ); + + + pm_csr = pAdapter->CSRAddress->global.pm_csr; + + if( pm_csr.bits.pm_phy_sw_coma == 0 ) + { + if( pAdapter->RegistryMACStat ) + { + UpdateMacStatHostCounters( pAdapter ); + } + } + else + { + DBG_VERBOSE( et131x_dbginfo, + "No interrupts, in PHY coma, pm_csr = 0x%x\n", + pm_csr.value ); + } + + + if( !pAdapter->Bmsr.bits.link_status && + pAdapter->RegistryPhyComa && + pAdapter->PoMgmt.TransPhyComaModeOnBoot < 11 ) + { + pAdapter->PoMgmt.TransPhyComaModeOnBoot++; + } + + if( pAdapter->PoMgmt.TransPhyComaModeOnBoot == 10 ) + { + if( !pAdapter->Bmsr.bits.link_status && pAdapter->RegistryPhyComa ) + { + if( pAdapter->CSRAddress->global.pm_csr.bits.phy_sw_coma == 0 ) + { + // NOTE - This was originally a 'sync with interrupt'. How + // to do that under Linux? + et131x_enable_interrupts( pAdapter ); + EnablePhyComa( pAdapter ); + } + } + } + + + /************************************************************************** + This is a periodic timer, so reschedule + *************************************************************************/ + add_timer( &pAdapter->ErrorTimer ); + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_link_detection_handler + ****************************************************************************** + DESCRIPTION: + Timer function for handling link up at driver load time + + PARAMETERS : + SystemSpecific1 Not used + FunctionContext Pointer to our adapter + SystemSpecific2 Not used + SystemSpecific3 Not used + + RETURNS : + NONE + + *****************************************************************************/ +void et131x_link_detection_handler( unsigned long data ) +{ + ET131X_ADAPTER *pAdapter = (ET131X_ADAPTER *)data; + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + Let everyone know that we have run + *************************************************************************/ + pAdapter->bLinkTimerActive = FALSE; + + if( pAdapter->MediaState == 0 ) + { + spin_lock_irqsave( &pAdapter->Lock, lockflags ); + + pAdapter->MediaState = NETIF_STATUS_MEDIA_DISCONNECT; + MP_CLEAR_FLAG( pAdapter, fMP_ADAPTER_LINK_DETECTION ); + + spin_unlock_irqrestore( &pAdapter->Lock, lockflags ); + + netif_indicate_status( pAdapter->netdev, pAdapter->MediaState ); + + if( pAdapter->bSetPending ) + { + pAdapter->bSetPending = FALSE; + } + } + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_adapter_setup + ****************************************************************************** + + DESCRIPTION : Used to set the adapter up as per cassini+ documentation + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_adapter_setup( ET131X_ADAPTER *pAdapter ) +{ + int status = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_adapter_setup" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Configure the JAGCore + *************************************************************************/ + ConfigGlobalRegs( pAdapter ); + + ConfigMACRegs1( pAdapter ); + ConfigMMCRegs( pAdapter ); + + ConfigRxMacRegs( pAdapter ); + ConfigTxMacRegs( pAdapter ); + + ConfigRxDmaRegs( pAdapter ); + ConfigTxDmaRegs( pAdapter ); + + ConfigMacStatRegs( pAdapter ); + + + /************************************************************************** + Move the following code to Timer function?? + *************************************************************************/ + status = et131x_xcvr_find( pAdapter ); + + if( status != 0 ) + { + DBG_WARNING( et131x_dbginfo, "Could not find the xcvr\n" ); + } + + + /********************************************************************** + Prepare the TRUEPHY library. + *********************************************************************/ + ET1310_PhyInit( pAdapter ); + + + /************************************************************************** + Reset the phy now so changes take place + *************************************************************************/ + ET1310_PhyReset( pAdapter ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + + /************************************************************************** + We need to turn off 1000 base half dulplex, the mac does not + support it + For the 10/100 part, turn off all gig advertisement + *************************************************************************/ + if( pAdapter->DeviceID != ET131X_PCI_DEVICE_ID_FAST ) + { + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_FULL ); + } + else + { + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + } + + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + et131x_setphy_normal( pAdapter ); + + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_setup_hardware_properties + ****************************************************************************** + + DESCRIPTION : Used to set up the MAC Address on the ET1310 + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_setup_hardware_properties( ET131X_ADAPTER *adapter ) +{ + DBG_FUNC( "et131x_setup_hardware_properties" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + If have our default mac from registry and no mac address from EEPROM + then we need to generate the last octet and set it on the device + *************************************************************************/ + if( !adapter->bOverrideAddress ) + { + if (adapter->PermanentAddress[0] == 0x00 && + adapter->PermanentAddress[1] == 0x00 && + adapter->PermanentAddress[2] == 0x00 && + adapter->PermanentAddress[3] == 0x00 && + adapter->PermanentAddress[4] == 0x00 && + adapter->PermanentAddress[5] == 0x00 ) + { + /****************************************************************** + We need to randomly generate the last octet so we decrease our + chances of setting the mac address to same as another one of + our cards in the system + *****************************************************************/ + get_random_bytes( &adapter->CurrentAddress[5], 1 ); + + + /****************************************************************** + We have the default value in the register we are working with + so we need to copy the current address into the permanent + address + *****************************************************************/ + memcpy( adapter->PermanentAddress, + adapter->CurrentAddress, + ETH_ALEN ); + } + else + { + /****************************************************************** + We do not have an override address, so set the current address + to the permanent address and add it to the device + *****************************************************************/ + memcpy( adapter->CurrentAddress, + adapter->PermanentAddress, + ETH_ALEN ); + } + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_soft_reset + ****************************************************************************** + + DESCRIPTION : Issue a soft reset to the hardware, complete for ET1310. + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_soft_reset( ET131X_ADAPTER *adapter ) +{ + DBG_FUNC( "et131x_soft_reset" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Disable MAC Core + *************************************************************************/ + adapter->CSRAddress->mac.cfg1.value = 0xc00f0000; + + + /************************************************************************** + Set everything to a reset value + *************************************************************************/ + adapter->CSRAddress->global.sw_reset.value = 0x7F; + adapter->CSRAddress->mac.cfg1.value = 0x000f0000; + adapter->CSRAddress->mac.cfg1.value = 0x00000000; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_align_allocated_memory + ****************************************************************************** + + DESCRIPTION : Align an allocated block of memory on a given boundary + + PARAMETERS : adapter - pointer to our adapter structure + phys_addr - pointer to Physical address + offset - pointer to the offset variable + mask - correct mask + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_align_allocated_memory( ET131X_ADAPTER *adapter, + UINT64 *phys_addr, + UINT64 *offset, + UINT64 mask ) +{ + UINT64 new_addr; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_align_allocated_memory" ); + DBG_ENTER( et131x_dbginfo ); + + + *offset = 0; + + new_addr = *phys_addr & ~mask; + + if( new_addr != *phys_addr ) + { + new_addr += mask+1; // Move to next aligned block + *offset = new_addr - *phys_addr; // Return offset for adjusting virt addr + *phys_addr = new_addr; // Return new physical address + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_adapter_memory_alloc + ****************************************************************************** + + DESCRIPTION : Allocate all the memory blocks for send, receive and + others. + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_adapter_memory_alloc( ET131X_ADAPTER *adapter ) +{ + int status = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_adapter_memory_alloc" ); + DBG_ENTER( et131x_dbginfo ); + + do + { + /********************************************************************** + Allocate memory for the Tx Ring + *********************************************************************/ + status = et131x_tx_dma_memory_alloc( adapter ); + if( status != 0 ) + { + DBG_ERROR( et131x_dbginfo, "et131x_tx_dma_memory_alloc FAILED\n" ); + break; + } + + + /********************************************************************** + Receive buffer memory allocation + *********************************************************************/ + status = et131x_rx_dma_memory_alloc( adapter ); + if( status != 0 ) + { + DBG_ERROR( et131x_dbginfo, "et131x_rx_dma_memory_alloc FAILED\n" ); + et131x_tx_dma_memory_free( adapter ); + break; + } + + + /********************************************************************** + Init receive data structures + *********************************************************************/ + status = et131x_init_recv( adapter ); + if( status != 0 ) + { + DBG_ERROR( et131x_dbginfo, "et131x_init_recv FAILED\n" ); + et131x_tx_dma_memory_free( adapter ); + et131x_rx_dma_memory_free( adapter ); + break; + } + } while( 0 ); + + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_adapter_memory_free + ****************************************************************************** + + DESCRIPTION : Free all memory allocated for use by Tx & Rx code + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_adapter_memory_free( ET131X_ADAPTER *adapter ) +{ + DBG_FUNC( "et131x_adapter_memory_free" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Free DMA memory + *************************************************************************/ + et131x_tx_dma_memory_free( adapter ); + et131x_rx_dma_memory_free( adapter ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_pci_register + ****************************************************************************** + + DESCRIPTION : This function uses the above data to regsiter the PCI + function table and PCI Vendor/Product ID(s) with the PCI + subsystem to match corresponding devices to this driver. + + PARAMETERS : N/A + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_pci_register( void ) +{ + int result; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_pci_register" ); + DBG_ENTER( et131x_dbginfo ); + + + result = pci_register_driver( &et131x_driver ); + DBG_TRACE( et131x_dbginfo, + " pci_register_driver( ) returns %d \n", + result ); + + + DBG_LEAVE( et131x_dbginfo ); + return result; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_pci_cleanup + ****************************************************************************** + + DESCRIPTION : This function deregisters the PCI function table and + related PCI Vendor/Product ID(s) with the PCI subsytem. + + PARAMETERS : N/A + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_pci_unregister( void ) +{ + DBG_FUNC( "et131x_pci_unregister" ); + DBG_ENTER( et131x_dbginfo ); + + + pci_unregister_driver( &et131x_driver ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_pci_probe + ****************************************************************************** + + DESCRIPTION : Registered in the pci_driver structure, this function is + called when the PCI subsystem finds a new PCI device + which matches the information contained in the + pci_device_id table. This routine is the equivalent to + a device insertion routine. + + PARAMETERS : pdev - a pointer to the device's pci_dev structure + ent - this device's entry in the pci_device_id table + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int __devinit et131x_pci_probe( struct pci_dev *pdev, + const struct pci_device_id *ent ) +{ + int result; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_pci_probe" ); + DBG_ENTER( et131x_dbginfo ); + + + result = et131x_pci_setup( pdev ); + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_pci_remove + ****************************************************************************** + + DESCRIPTION : Registered in the pci_driver structure, this function is + called when the PCI subsystem detects that a PCI device + which matches the information contained in the + pci_device_id table has been removed. + + PARAMETERS : pdev - a pointer to the device's pci_dev structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void __devexit et131x_pci_remove( struct pci_dev *pdev ) +{ + struct net_device *netdev = NULL; + ET131X_ADAPTER *adapter = NULL; + BOOL_t bar_workaround; + unsigned long bar_addr_orig = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_pci_remove" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Make sure the pci_dev pointer is valid + *************************************************************************/ + if( pdev == NULL ) + { + DBG_ERROR( et131x_dbginfo, + "PCI subsys passed in an invalid pci_dev pointer\n" ); + DBG_LEAVE( et131x_dbginfo ); + return; + } + + + /************************************************************************** + Retrieve the net_device pointer from the pci_dev struct, as well as the + private adapter struct + *************************************************************************/ + netdev = (struct net_device *)pci_get_drvdata( pdev ); + if( netdev == NULL ) + { + DBG_ERROR( et131x_dbginfo, + "Could not retrieve net_device struct\n" ); + DBG_LEAVE( et131x_dbginfo ); + return; + } + + adapter = netdev_priv( netdev ); + if( adapter == NULL ) + { + DBG_ERROR( et131x_dbginfo, + "Could not retrieve private adapter struct\n" ); + DBG_LEAVE( et131x_dbginfo ); + return; + } + + + /************************************************************************** + Retrieve config space workaround info before deleting the private + adapter struct + *************************************************************************/ + bar_workaround = adapter->pci_bar_workaround; + bar_addr_orig = adapter->pci_bar_addr_orig; + + + /************************************************************************** + Perform device cleanup + *************************************************************************/ + unregister_netdev( netdev ); + et131x_adapter_memory_free( adapter ); + iounmap( (void *)adapter->CSRAddress ); + et131x_device_free( netdev ); + + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_pci_setup + ****************************************************************************** + + DESCRIPTION : Called by et131x_pci_probe() to perform device + initialization. + + PARAMETERS : pdev - a pointer to the device's pci_dev structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_pci_setup( struct pci_dev *pdev ) +{ + int result = 0; + int pm_cap; + BOOL_t pci_using_dac; + unsigned long et131x_reg_base; + unsigned long et131x_reg_len; + struct net_device *netdev = NULL; + ET131X_ADAPTER *adapter = NULL; + BOOL_t bar_workaround = FALSE; + unsigned long bar_addr_orig = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_pci_setup" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Make sure the device pointer is valid + *************************************************************************/ + if( pdev == NULL ) + { + DBG_ERROR( et131x_dbginfo, + "PCI subsys passed in an invalid pci_dev pointer\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENODEV; + } + + + /************************************************************************** + On some systems, the base address for a PCI device's config space which + is stored in the pci_dev structure is incorrect and different from + what's actually in the config space. If they're different, workaround + the issue by correcting the address. + *************************************************************************/ + pci_read_config_dword( pdev, PCI_BASE_ADDRESS_0, (u32 *)&et131x_reg_base ); + et131x_reg_base &= ~0x07; + + if( (u32)pdev->resource[0].start != (u32)et131x_reg_base ) + { + DBG_WARNING( et131x_dbginfo, "PCI CONFIG SPACE WORKAROUND REQUIRED\n" ); + DBG_WARNING( et131x_dbginfo, "pdev->resource[0].start : 0x%08x\n", + (unsigned int)pdev->resource[0].start ); + DBG_WARNING( et131x_dbginfo, "et131x_reg_base : 0x%08x\n", + (unsigned int)et131x_reg_base ); + bar_workaround = TRUE; + bar_addr_orig = pdev->resource[0].start; + pdev->resource[0].start = et131x_reg_base; + } + + + /************************************************************************** + Enable the device via the PCI subsystem + *************************************************************************/ + result = pci_enable_device( pdev ); + if( result != 0 ) + { + if( bar_workaround ) + { + pdev->resource[0].start = bar_addr_orig; + } + + DBG_ERROR( et131x_dbginfo, "pci_enable_device() failed\n" ); + DBG_LEAVE( et131x_dbginfo ); + return result; + } + + + /************************************************************************** + Perform some basic PCI checks + *************************************************************************/ + if( !( pci_resource_flags( pdev, 0 ) & IORESOURCE_MEM )) + { + if( bar_workaround ) + { + pdev->resource[0].start = bar_addr_orig; + } + + DBG_ERROR( et131x_dbginfo, + "Can't find PCI device's base address\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENODEV; + } + + if( bar_workaround == FALSE ) + { + result = pci_request_regions( pdev, DRIVER_NAME ); + if( result != 0 ) + { + DBG_ERROR( et131x_dbginfo, + "Can't get PCI resources\n" ); + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return result; + } + } + + + /************************************************************************** + Enable PCI bus mastering + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Setting PCI Bus Mastering...\n" ); + pci_set_master( pdev ); + + + /************************************************************************** + Query PCI for Power Mgmt Capabilities + + NOTE: Now reading PowerMgmt in another location; is this still needed? + *************************************************************************/ + pm_cap = pci_find_capability( pdev, PCI_CAP_ID_PM ); + if( pm_cap == 0 ) + { + DBG_ERROR( et131x_dbginfo, + "Cannot find Power Management capabilities\n" ); + + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + + /************************************************************************** + Check the DMA addressing support of this device + *************************************************************************/ + if( !pci_set_dma_mask( pdev, 0xffffffffffffffffULL )) + { + DBG_TRACE( et131x_dbginfo, + "64-bit DMA addressing supported\n" ); + pci_using_dac = TRUE; + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,0 )) + result = pci_set_consistent_dma_mask( pdev, 0xffffffffffffffffULL ); + if( result != 0 ) + { + DBG_ERROR( et131x_dbginfo, + "Unable to obtain 64 bit DMA for consistent allocations\n" ); + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } +#endif + } + else if( !pci_set_dma_mask( pdev, 0xffffffffULL )) + { + DBG_TRACE( et131x_dbginfo, + "64-bit DMA addressing NOT supported\n" ); + DBG_TRACE( et131x_dbginfo, + "32-bit DMA addressing will be used\n" ); + pci_using_dac = FALSE; + } + else + { + DBG_ERROR( et131x_dbginfo, "No usable DMA addressing method\n" ); + + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + + /************************************************************************** + Allocate netdev and private adapter structs + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Allocate netdev and private adapter structs...\n" ); + netdev = et131x_device_alloc( ); + + if( netdev == NULL ) + { + DBG_ERROR( et131x_dbginfo, "Couldn't alloc netdev struct\n" ); + + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Setup the fundamental net_device and private adapter structure elements + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Setting fundamental net_device info...\n" ); + + #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + SET_MODULE_OWNER( netdev ); + #endif + #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)) + SET_NETDEV_DEV( netdev, &pdev->dev ); + #endif + if( pci_using_dac ) + { + //netdev->features |= NETIF_F_HIGHDMA; + } + + + /************************************************************************** + NOTE - Turn this on when we're ready to deal with SG-DMA + + NOTE: According to "Linux Device Drivers", 3rd ed, Rubini et al, if + checksumming is not performed in HW, then the kernel will not use SG. + From pp 510-511: + + "Note that the kernel does not perform scatter/gather I/O to your device + if it does not also provide some form of checksumming as well. The + reason is that, if the kernel has to make a pass over a fragmented + ("nonlinear") packet to calculate the checksum, it might as well copy + the data and coalesce the packet at the same time." + + This has been verified by setting the flags below and still not + receiving a scattered buffer from the network stack, so leave it off + until checksums are calculated in HW. + *************************************************************************/ + //netdev->features |= NETIF_F_SG; + //netdev->features |= NETIF_F_NO_CSUM; + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,0 )) + //netdev->features |= NETIF_F_LLTX; +#endif + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + /************************************************************************** + The ET1310 does not perform VLAN tagging in hardware, so these flags are + not set. + *************************************************************************/ + /* + netdev->features |= NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER; + */ +#endif + + /************************************************************************** + Allocate private adapter struct and copy in relevant information + *************************************************************************/ + adapter = netdev_priv( netdev ); + adapter->pdev = pdev; + adapter->netdev = netdev; + adapter->VendorID = pdev->vendor; + adapter->DeviceID = pdev->device; + + adapter->pci_bar_workaround = bar_workaround; + adapter->pci_bar_addr_orig = bar_addr_orig; + + + /************************************************************************** + Do the same for the netdev struct + *************************************************************************/ + netdev->irq = pdev->irq; + netdev->base_addr = pdev->resource[0].start; + + + /************************************************************************** + Initialize spinlocks here + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Initialize spinlocks...\n" ); + + spin_lock_init( &adapter->Lock ); + spin_lock_init( &adapter->TCBSendQLock ); + spin_lock_init( &adapter->TCBReadyQLock ); + spin_lock_init( &adapter->SendHWLock ); + spin_lock_init( &adapter->SendWaitLock ); + spin_lock_init( &adapter->RcvLock ); + spin_lock_init( &adapter->RcvPendLock ); + spin_lock_init( &adapter->FbrLock ); + spin_lock_init( &adapter->PHYLock ); + + + /************************************************************************** + Parse configuration parameters into the private adapter struct + *************************************************************************/ + et131x_config_parse( adapter ); + + + /************************************************************************** + Find the physical adapter + + NOTE: This is the equivalent of the MpFindAdapter() routine; can we + lump it's init with the device specific init below into a single + init function? + *************************************************************************/ + //while(et131x_find_adapter( adapter, pdev ) != 0); + et131x_find_adapter( adapter, pdev ); + + /************************************************************************** + Map the bus-relative registers to system virtual memory + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Mapping bus-relative registers to virtual memory...\n" ); + + if( bar_workaround == FALSE ) + { + et131x_reg_base = pci_resource_start( pdev, 0 ); + et131x_reg_len = pci_resource_len( pdev, 0 ); + } + else + { + et131x_reg_len = 0x00200000; + } + + adapter->CSRAddress = (ADDRESS_MAP_t *)ioremap_nocache( et131x_reg_base, + et131x_reg_len ); + if( adapter->CSRAddress == NULL ) + { + DBG_ERROR( et131x_dbginfo, "Cannot map device registers\n" ); + + et131x_device_free( netdev ); + + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Perform device-specific initialization here (See code below) + *************************************************************************/ + + /************************************************************************** + If Phy COMA mode was enabled when we went down, disable it here. + *************************************************************************/ + { + PM_CSR_t GlobalPmCSR = {0}; + + GlobalPmCSR.bits.pm_sysclk_gate = 1; + GlobalPmCSR.bits.pm_txclk_gate = 1; + GlobalPmCSR.bits.pm_rxclk_gate = 1; + + adapter->CSRAddress->global.pm_csr = GlobalPmCSR; + } + + + /************************************************************************** + Issue a global reset to the et1310 + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Issuing soft reset...\n" ); + et131x_soft_reset( adapter ); + + + /************************************************************************** + Disable all interrupts (paranoid) + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Disable device interrupts...\n" ); + et131x_disable_interrupts( adapter ); + + + /************************************************************************** + Allocate DMA memory + *************************************************************************/ + result = et131x_adapter_memory_alloc( adapter ); + if( result != 0 ) + { + DBG_ERROR( et131x_dbginfo, + "Could not alloc adapater memory (DMA)\n" ); + + iounmap( (void *)adapter->CSRAddress ); + + et131x_device_free( netdev ); + + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Init send data structures + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Init send data structures...\n" ); + et131x_init_send( adapter ); + + adapter->PoMgmt.PowerState = NdisDeviceStateD0; + + + /************************************************************************** + Register the interrupt + + NOTE - This is being done in the open routine, where most other Linux + drivers setup IRQ handlers. Make sure device interrupts are not + turned on before the IRQ is registered!!!! + + What we will do here is setup the task structure for the ISR's + deferred handler + *************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) + adapter->task.routine = (void (*)(void *))et131x_isr_handler; + adapter->task.data = adapter; +#else + INIT_WORK( &adapter->task, et131x_isr_handler ); +#endif + + + /************************************************************************** + Determine MAC Address, and copy into the net_device struct + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Retrieve MAC address...\n" ); + et131x_setup_hardware_properties( adapter ); + + memcpy( netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN ); + + + /************************************************************************** + Setup up our lookup table for CRC Calculations + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Setup CRC lookup table...\n" ); + et131x_init_enet_crc_calc( ); + + + /************************************************************************** + Setup et1310 as per the documentation + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Setup the adapter...\n" ); + et131x_adapter_setup( adapter ); + + + /************************************************************************** + Create a timer to count errors received by the NIC + *************************************************************************/ + init_timer( &adapter->ErrorTimer ); + + adapter->ErrorTimer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000; + adapter->ErrorTimer.function = et131x_error_timer_handler; + adapter->ErrorTimer.data = (unsigned long)adapter; + + + /************************************************************************** + Initialize link state + *************************************************************************/ + et131x_link_detection_handler( (unsigned long)adapter ); + + + /************************************************************************** + Intialize variable for counting how long we do not have link status + *************************************************************************/ + adapter->PoMgmt.TransPhyComaModeOnBoot = 0; + + + /************************************************************************** + We can enable interrupts now + + NOTE - Because registration of interrupt handler is done in the device's + open(), defer enabling device interrupts to that point + *************************************************************************/ + + + /************************************************************************** + Register the net_device struct with the Linux network layer + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, "Registering net_device...\n" ); + + + if(( result = register_netdev( netdev )) != 0 ) + { + DBG_ERROR( et131x_dbginfo, "register_netdev() failed\n" ); + + et131x_adapter_memory_free( adapter ); + + iounmap( (void *)adapter->CSRAddress ); + + et131x_device_free( netdev ); + + if( bar_workaround == FALSE ) + { + pci_release_regions( pdev ); + } + else + { + pdev->resource[0].start = bar_addr_orig; + } + + pci_disable_device( pdev ); + + DBG_LEAVE( et131x_dbginfo ); + return result; + } + + + /************************************************************************** + Register the net_device struct with the PCI subsystem. Save a copy + of the PCI config space for this device now that the device has been + initialized, just in case it needs to be quickly restored. + *************************************************************************/ + pci_set_drvdata( pdev, netdev ); + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,10 )) + pci_save_state( adapter->pdev, adapter->pci_cfg_state); +#else + pci_save_state( adapter->pdev ); +#endif + + + /************************************************************************** + Print out some information about this device + *************************************************************************/ + DBG_TRACE( et131x_dbginfo, + "DEVICE FOUND\n" ); + DBG_TRACE( et131x_dbginfo, + "------------------------------\n" ); + DBG_TRACE( et131x_dbginfo, + "Device Vendor ID : 0x%04x\n", + pdev->vendor ); + DBG_TRACE( et131x_dbginfo, + "Device Product ID : 0x%04x\n", + pdev->device ); + DBG_TRACE( et131x_dbginfo, + "Device SubVendor ID : 0x%04x\n", + pdev->subsystem_vendor ); + DBG_TRACE( et131x_dbginfo, + "Device SubProduct ID : 0x%04x\n", + pdev->subsystem_device ); + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) + DBG_TRACE( et131x_dbginfo, + "Device Name : %s\n", + pdev->name ); +#endif + + DBG_TRACE( et131x_dbginfo, + "Device on Bus # : %d\n", + pdev->bus->number ); + DBG_TRACE( et131x_dbginfo, + " Bus Name : %s\n", + pdev->bus->name ); + DBG_TRACE( et131x_dbginfo, + "Device in Slot # : %d\n", + PCI_SLOT( pdev->devfn )); + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,11 )) + DBG_TRACE( et131x_dbginfo, + " Slot Name : %s\n", + pdev->slot_name ); +#endif + + DBG_TRACE( et131x_dbginfo, + "Device Base Address : 0x%#03lx\n", + netdev->base_addr ); + DBG_TRACE( et131x_dbginfo, + "Device IRQ : %d\n", + netdev->irq ); + DBG_TRACE( et131x_dbginfo, + "Device MAC Address : %02x:%02x:%02x:%02x:%02x:%02x\n", + adapter->CurrentAddress[0], adapter->CurrentAddress[1], + adapter->CurrentAddress[2], adapter->CurrentAddress[3], + adapter->CurrentAddress[4], adapter->CurrentAddress[5] ); + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ --- linux-2.6.27.orig/ubuntu/et131x/Kconfig +++ linux-2.6.27/ubuntu/et131x/Kconfig @@ -0,0 +1,3 @@ +config NET_ET131X + tristate "Agere Systems 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs" + depends on PCI && NET --- linux-2.6.27.orig/ubuntu/et131x/et131x_supp.c +++ linux-2.6.27/ubuntu/et131x/et131x_supp.c @@ -0,0 +1,440 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_supp.c - Misc. support routines. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:13 $ + $Revision: 1.6 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" +#include "ET1310_mac.h" + +#include "et131x_supp.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Global look-up table used to calculate CRC. Preset with the appropriate + XORs from the 256 possible byte values that might be in the message. + *****************************************************************************/ +static UINT32 SynDrome [256]; + + + + +/****************************************************************************** + Prototypes for functions with local scope + *****************************************************************************/ +static UINT32 crc32byte( UINT32 remainder, UCHAR data ); + + + + +/****************************************************************************** + ROUTINE : et131x_init_enet_crc_calc + ****************************************************************************** + + DESCRIPTION : Initializes the look-up table (syndrome) for CRC + calculation. + + PARAMETERS : N/A + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_init_enet_crc_calc( void ) +{ + UINT32 EthernetKey = 0x04c11db7; + UINT32 i; + UINT32 j; + UINT32 reg; + BOOL_t topBit; + /*-----------------------------------------------------------------------*/ + + + for( i = 0; i < 256; i++ ) + { + reg = i << 24; + + for( j = 0; j < 8; j++ ) + { + topBit = ( reg & 0x80000000 ) != 0; + + reg <<= 1; + + if( topBit ) + { + reg ^= EthernetKey; + } + } + SynDrome[i] = reg; + } + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : crc32byte + ****************************************************************************** + + DESCRIPTION : + + PARAMETERS : + + RETURNS : + + REUSE INFORMATION : + + *****************************************************************************/ +#define CRC32_POLY 0x4C11DB7 + +static UINT32 crc32byte( UINT32 remainder, UCHAR data ) +{ + int index; + UINT32 remndr, hitbit; + /*-----------------------------------------------------------------------*/ + + + remndr = remainder; + + for( index = 0; index < 8; index++ ) + { + hitbit = (remndr >> 31) ^ (data & 0x01); + + data = data >> 1; // get the next data bit + remndr = remndr << 1; // get the next remainder bit + + if( hitbit ) + { + remndr = remndr ^ CRC32_POLY; + } + } + + return remndr; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_calc_enet_crc + ****************************************************************************** + + DESCRIPTION : Used to calculate the CRC of an ethernet message. Used + in the device's filtering of multi-cast packets. + + PARAMETERS : Message - A pointer to the Ethernet bytes to be encoded + MessageSize - The number of bytes in the message + + RETURNS : The computed CRC + + REUSE INFORMATION : + + *****************************************************************************/ +UINT32 et131x_calc_enet_crc( PUCHAR Message, UINT32 MessageSize ) +{ + UINT32 Result = 0xFFFFFFFF; + UINT32 i; + /*-----------------------------------------------------------------------*/ + + for( i = 0; i < MessageSize; i++ ) + { + Result = crc32byte( Result, *Message ); + Message++; + } + + return Result; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : pci_slot_information_read + ****************************************************************************** + + DESCRIPTION : Reads a segment of the PCI configuration space for a + device. + + This is a port of the NDIS function + NdisReadPciSlotInformation + + This function does not begin with 'et131x_' in order to + remain consistent with other system pci_xxx() calls. + + PARAMETERS : pdev - pointer to a pci_dev structure for the device + whose PCI config space is to be read + where - the offset to read + buf - a pointer to a buffer in which the data will be + returned + len - the length of the above buffer + + RETURNS : The length of the buffer read + + REUSE INFORMATION : + + *****************************************************************************/ +UINT32 pci_slot_information_read( struct pci_dev *pdev, UINT32 where, + UINT8 *buf, UINT32 len ) +{ + int i; + int status; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "pci_slot_information_read" ); + + + for( i = 0; i < len; i++ ) + { + status = pci_read_config_byte( pdev, where+i, &buf[i] ); + + if( status != 0 ) + { + DBG_ERROR( et131x_dbginfo, "Cannot Read PCI config space...\n" ); + break; + } + } + + return len; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : pci_slot_information_write + ****************************************************************************** + + DESCRIPTION : Writes a segment of the PCI configuration space for a + device. + + This is a port of the NDIS function + NdisWritePciSlotInformation + + This function does not begin with 'et131x_' in order to + remain consistent with other system pci_xxx() calls. + + PARAMETERS : pdev - pointer to a pci_dev structure for the device + whose PCI config space is to be written + where - the offset to write + buf - a pointer to a buffer containing the data to be + written + len - the length of the above buffer + + RETURNS : The length of the buffer written + + REUSE INFORMATION : + + *****************************************************************************/ +UINT32 pci_slot_information_write( struct pci_dev *pdev, UINT32 where, + UINT8 *buf, UINT32 len ) +{ + int i; + int status; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "pci_slot_information_write" ); + + + for( i = 0; i < len; i++ ) + { + status = pci_write_config_byte( pdev, where+i, buf[i] ); + + if( status != 0 ) + { + DBG_ERROR( et131x_dbginfo, "Cannot Write PCI config space...\n" ); + break; + } + } + + return len; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : netif_indicate_status + ****************************************************************************** + + DESCRIPTION : Provides the network stack with link status for the + given device. + + This is a port of the NDIS function + NdisMIndicateStatus. Unlike NDIS, there is no + corresponding status completion function. + + This function does not begin with 'et131x_' in order to + remain consistent with other system netif_xxx() calls. + + PARAMETERS : netdev - a pointer to the net_device struct representing + the device whose status we wosh to indicate. + status - the link status + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void netif_indicate_status( struct net_device *netdev, NETIF_STATUS status ) +{ + DBG_FUNC( "netif_indicate_status" ); + + + if( netdev != NULL ) + { + switch( status ) + { + case NETIF_STATUS_MEDIA_CONNECT: + DBG_VERBOSE( et131x_dbginfo, "Indicating Link UP\n" ); + netif_carrier_on( netdev ); + break; + + case NETIF_STATUS_MEDIA_DISCONNECT: + DBG_VERBOSE( et131x_dbginfo, "Indicating Link DOWN\n" ); + netif_carrier_off( netdev ); + break; + + default: + DBG_WARNING( et131x_dbginfo, + "Unknown link status code: %d\n", + status ); + break; + } + } + else + { + DBG_WARNING( et131x_dbginfo, "net_device pointer is NULL\n" ); + } + + return; +} +/*===========================================================================*/ --- linux-2.6.27.orig/ubuntu/et131x/et131x_adapter.h +++ linux-2.6.27/ubuntu/et131x/et131x_adapter.h @@ -0,0 +1,508 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_adapter.h - Header which includes the private adapter structure, along + * with related support structures, macros, definitions, etc. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/25 20:48:56 $ + $Revision: 1.15 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_ADAPTER_H__ +#define __ET131X_ADAPTER_H__ + + + + +#include "ET1310_address_map.h" +#include "ET1310_tx.h" +#include "ET1310_rx.h" + + + + +/****************************************************************************** + Do not change these values: if changed, then change also in respective + TXdma and Rxdma engines + *****************************************************************************/ +#define NUM_DESC_PER_RING_TX 512 // TX Do not change these values +#define NUM_TCB 64 + + + + +/****************************************************************************** + These values are all superseded by registry entries to facilitate tuning. + Once the desired performance has been achieved, the optimal registry values + should be re-populated to these #defines: + *****************************************************************************/ +#define NUM_TRAFFIC_CLASSES 1 + + + + +/****************************************************************************** + There are three ways of counting errors - if there are more than X errors + in Y packets (represented by the "SAMPLE" macros), if there are more than + N errors in a S mSec time period (the "PERIOD" macros), or if there are + consecutive packets with errors (CONSEC_ERRORED_THRESH). This last covers + for "Bursty" errors, and the errored packets may well not be contiguous, + but several errors where the packet counter has changed by less than a + small amount will cause this count to increment. + *****************************************************************************/ +#define TX_PACKETS_IN_SAMPLE 10000 +#define TX_MAX_ERRORS_IN_SAMPLE 50 + +#define TX_ERROR_PERIOD 1000 +#define TX_MAX_ERRORS_IN_PERIOD 10 + +#define LINK_DETECTION_TIMER 5000 + +#define TX_CONSEC_RANGE 5 +#define TX_CONSEC_ERRORED_THRESH 10 + +#define LO_MARK_PERCENT_FOR_PSR 15 +#define LO_MARK_PERCENT_FOR_RX 15 + + + + +/****************************************************************************** + Macros for flag and ref count operations + *****************************************************************************/ +#define MP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) +#define MP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) +#define MP_CLEAR_FLAGS(_M) ((_M)->Flags = 0) +#define MP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) +#define MP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) +#define MP_IS_FLAG_CLEAR(_M, _F) (((_M)->Flags & (_F)) == 0) + +#define MP_INC_RCV_REF(_A) atomic_inc(&(_A)->RcvRefCount) +#define MP_DEC_RCV_REF(_A) atomic_dec(&(_A)->RcvRefCount) +#define MP_GET_RCV_REF(_A) atomic_read(&(_A)->RcvRefCount) + + + + +/****************************************************************************** + Macros specific to the private adapter structure + *****************************************************************************/ +#define MP_TCB_RESOURCES_AVAILABLE(_M) ((_M)->TxRing.nBusySend < NUM_TCB) +#define MP_TCB_RESOURCES_NOT_AVAILABLE(_M) ((_M)->TxRing.nBusySend >= NUM_TCB) + +#define MP_SHOULD_FAIL_SEND(_M) ((_M)->Flags & fMP_ADAPTER_FAIL_SEND_MASK) +#define MP_IS_NOT_READY(_M) ((_M)->Flags & fMP_ADAPTER_NOT_READY_MASK) +#define MP_IS_READY(_M) !((_M)->Flags & fMP_ADAPTER_NOT_READY_MASK) + +#define MP_HAS_CABLE(_M) !((_M)->Flags & fMP_ADAPTER_NO_CABLE) +#define MP_LINK_DETECTED(_M) !((_M)->Flags & fMP_ADAPTER_LINK_DETECTION) + + + + +/****************************************************************************** + Counters for error rate monitoring + *****************************************************************************/ +typedef struct _MP_ERR_COUNTERS +{ + UINT32 PktCountTxPackets; + UINT32 PktCountTxErrors; + UINT32 TimerBasedTxErrors; + UINT32 PktCountLastError; + UINT32 ErredConsecPackets; +} MP_ERR_COUNTERS, *PMP_ERR_COUNTERS; + + + + +/****************************************************************************** + RFD (Receive Frame Descriptor) + *****************************************************************************/ +typedef struct _MP_RFD +{ + struct list_head list_node; + struct sk_buff *Packet; + UINT32 PacketSize; // total size of receive frame + UINT16 iBufferIndex; + UINT8 iRingIndex; +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + BOOL_t bHasVLANTag; + UINT16 VLANTag; +#endif +} MP_RFD, *PMP_RFD; + + + + +/****************************************************************************** + Enum for Flow Control + *****************************************************************************/ +typedef enum _eflow_control_t { + Both = 0, + TxOnly = 1, + RxOnly = 2, + None = 3 +} eFLOW_CONTROL_t, *PeFLOW_CONTROL_t; + + + + +/****************************************************************************** + Struct to define some device statistics + *****************************************************************************/ +typedef struct _ce_stats_t +{ + /************************************************************************** + Link Input/Output stats + *************************************************************************/ + UINT64 ipackets; // # of in packets + UINT64 opackets; // # of out packets + + + /************************************************************************** + MIB II variables + *************************************************************************/ + /************************************************************************** + NOTE - atomic_t types are only guaranteed to store 24-bits; if we MUST + have 32, then we'll need another way to perform atomic operations + *************************************************************************/ + UINT32 unircv; // # multicast packets received + atomic_t unixmt; // # multicast packets for Tx + UINT32 multircv; // # multicast packets received + atomic_t multixmt; // # multicast packets for Tx + UINT32 brdcstrcv; // # broadcast packets received + atomic_t brdcstxmt; // # broadcast packets for Tx + UINT32 norcvbuf; // # Rx packets discarded + UINT32 noxmtbuf; // # Tx packets discarded + + + /************************************************************************** + Transciever state informations. + *************************************************************************/ + UINT32 xcvr_addr; + UINT32 xcvr_id; + + + /************************************************************************** + Tx Statistics. + *************************************************************************/ + UINT32 tx_uflo; //Tx Underruns + + UINT32 collisions; + UINT32 excessive_collisions; + UINT32 first_collision; + UINT32 late_collisions; + UINT32 max_pkt_error; + UINT32 tx_deferred; + + + /************************************************************************** + Rx Statistics. + *************************************************************************/ + UINT32 rx_ov_flow; //Rx Over Flow + + UINT32 length_err; + UINT32 alignment_err; + UINT32 crc_err; + UINT32 code_violations; + UINT32 other_errors; + +#ifdef ET131X_DBG + UINT32 UnhandledInterruptsPerSec; + UINT32 RxDmaInterruptsPerSec; + UINT32 TxDmaInterruptsPerSec; + UINT32 WatchDogInterruptsPerSec; +#endif /* ET131X_DBG */ + + UINT32 SynchrounousIterations; + INT_STATUS_t InterruptStatus; +} +CE_STATS_t, *PCE_STATS_t; + + + + +/****************************************************************************** + The private adapter structure + *****************************************************************************/ +typedef struct et131x_adapter +{ + struct net_device *netdev; + struct pci_dev *pdev; + + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) + struct tq_struct task; +#else + struct work_struct task; +#endif + + + /************************************************************************** + Flags that indicate current state of the adapter + *************************************************************************/ + UINT32 Flags; + UINT32 HwErrCount; + + + /************************************************************************** + Configuration + *************************************************************************/ + UCHAR PermanentAddress[ETH_ALEN]; + UCHAR CurrentAddress[ETH_ALEN]; + BOOL_t bOverrideAddress; + BOOL_t bEepromPresent; + UCHAR eepromData[2]; + + + /************************************************************************** + Spinlocks + *************************************************************************/ + spinlock_t Lock; + + spinlock_t TCBSendQLock; + spinlock_t TCBReadyQLock; + spinlock_t SendHWLock; + spinlock_t SendWaitLock; + + spinlock_t RcvLock; + spinlock_t RcvPendLock; + spinlock_t FbrLock; + + spinlock_t PHYLock; + + + /************************************************************************** + Packet Filter and look ahead size + *************************************************************************/ + UINT32 PacketFilter; + UINT32 ulLookAhead; + UINT32 uiLinkSpeed; + UINT32 uiDuplexMode; + UINT32 uiAutoNegStatus; + UCHAR ucLinkStatus; + + + /************************************************************************** + multicast list + *************************************************************************/ + UINT32 MCAddressCount; + UCHAR MCList[NIC_MAX_MCAST_LIST][ETH_ALEN]; + + + /************************************************************************** + MAC test + *************************************************************************/ + TXMAC_TXTEST_t TxMacTest; + + + /************************************************************************** + Pointer to the device's PCI register space + *************************************************************************/ + ADDRESS_MAP_t *CSRAddress; + + + /************************************************************************** + PCI config space info, for debug purposes only. + *************************************************************************/ + UCHAR RevisionID; + UINT16 VendorID; + UINT16 DeviceID; + UINT16 SubVendorID; + UINT16 SubSystemID; + UINT32 CacheFillSize; + UINT16 PciXDevCtl; + UCHAR pci_lat_timer; + UCHAR pci_hdr_type; + UCHAR pci_bist; + UINT32 pci_cfg_state[64 / sizeof(u32)]; + + + /************************************************************************** + Registry parameters + *************************************************************************/ + UCHAR SpeedDuplex; // speed/duplex + eFLOW_CONTROL_t RegistryFlowControl; // for 802.3x flow control + UCHAR RegistryWOLMatch; // Enable WOL pattern-matching + UCHAR RegistryWOLLink; // Link state change is independant + UCHAR RegistryPhyComa; // Phy Coma mode enable/disable + + UINT32 RegistryRxMemEnd; // Size of internal rx memory + UCHAR RegistryMACStat; // If set, read MACSTAT, else don't + UINT32 RegistryVlanTag; // 802.1q Vlan TAG + UINT32 RegistryJumboPacket; // Max supported ethernet packet size + + UINT32 RegistryTxNumBuffers; + UINT32 RegistryTxTimeInterval; + + UINT32 RegistryRxNumBuffers; + UINT32 RegistryRxTimeInterval; + + + /************************************************************************** + Validation helpers + *************************************************************************/ + UCHAR RegistryPMWOL; + UCHAR RegistryNMIDisable; + UINT32 RegistryDMACache; + UINT32 RegistrySCGain; + UCHAR RegistryPhyLoopbk; // Enable Phy loopback + + + /************************************************************************** + Derived from the registry: + *************************************************************************/ + UCHAR AiForceDpx; // duplex setting + UINT16 AiForceSpeed; // 'Speed', user over-ride of line speed + eFLOW_CONTROL_t FlowControl; // flow control validated by the far-end + NETIF_STATUS MediaState; + UCHAR DriverNoPhyAccess; + + + /************************************************************************** + Minimize init-time + *************************************************************************/ + BOOL_t bQueryPending; + BOOL_t bSetPending; + BOOL_t bResetPending; + struct timer_list ErrorTimer; + BOOL_t bLinkTimerActive; + MP_POWER_MGMT PoMgmt; + INT_MASK_t CachedMaskValue; + + atomic_t RcvRefCount; // Num packets not yet returned + + + /************************************************************************** + Xcvr status at last poll + *************************************************************************/ + MI_BMSR_t Bmsr; + + + /************************************************************************** + Tx Memory Variables + *************************************************************************/ + TX_RING_t TxRing; + + + /************************************************************************** + Rx Memory Variables + *************************************************************************/ + RX_RING_t RxRing; + + + /************************************************************************** + ET1310 register Access + *************************************************************************/ + JAGCORE_ACCESS_REGS JagCoreRegs; + PCI_CFG_SPACE_REGS PciCfgRegs; + + + /************************************************************************** + Loopback specifics + *************************************************************************/ + UCHAR ReplicaPhyLoopbk; // Replica Enable + UCHAR ReplicaPhyLoopbkPF; // Replica Enable Pass/Fail + + + /************************************************************************** + Stats + *************************************************************************/ + CE_STATS_t Stats; + + struct net_device_stats net_stats; + struct net_device_stats net_stats_prev; + + + /************************************************************************** + VLAN + *************************************************************************/ +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + struct vlan_group *vlgrp; +#endif + + /************************************************************************** + Data to support workaround for bad config space addresses; see + et131x_pci_setup() for more information + *************************************************************************/ + BOOL_t pci_bar_workaround; + unsigned long pci_bar_addr_orig; +} ET131X_ADAPTER, *PET131X_ADAPTER; + + + + +#define MPSendPacketsHandler MPSendPackets +#define MP_FREE_SEND_PACKET_FUN(Adapter, pMpTcb) et131x_free_send_packet(Adapter, pMpTcb) +#define MpSendPacketFun(Adapter,Packet) MpSendPacket(Adapter, Packet) + + + + +#endif /* __ET131X_ADAPTER_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_eeprom.h +++ linux-2.6.27/ubuntu/et131x/ET1310_eeprom.h @@ -0,0 +1,127 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_eeprom.h - Defines, structs, enums, prototypes, etc. used for EEPROM + * access routines + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:10 $ + $Revision: 1.4 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET1310_EEPROM_H__ +#define __ET1310_EEPROM_H__ + + + + +/****************************************************************************** + INCLUDES + *****************************************************************************/ +#include "ET1310_common.h" + + +#ifndef SUCCESS + #define SUCCESS 0 + #define FAILURE 1 +#endif + +#ifndef READ + #define READ 0 + #define WRITE 1 +#endif + +#ifndef SINGLE_BYTE + #define SINGLE_BYTE 0 + #define DUAL_BYTE 1 +#endif + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + + + +UINT32 EEPROM_access( struct et131x_adapter *pAdapter, UCHAR bAccessFlag, + UINT32 unOffset, UCHAR bWidth, void *pData ); + +INT32 EepromWriteByte( struct et131x_adapter *pAdapter, UINT32 unAddress, + UCHAR bData, UINT32 unEepromId, UINT32 unAddressingMode ); + +INT32 EepromReadByte( struct et131x_adapter *pAdapter, UINT32 unAddress, + PUCHAR pbData, UINT32 unEepromId, UINT32 unAddressingMode ); + + + + +#endif /* _ET1310_EEPROM_H_ */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_netdev.h +++ linux-2.6.27/ubuntu/et131x/et131x_netdev.h @@ -0,0 +1,91 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_netdev.h - Defines, structs, enums, prototypes, etc. related to the + * driver's net_device support. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:13 $ + $Revision: 1.3 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_NETDEV_H__ +#define __ET131X_NETDEV_H__ + + + + +struct net_device * et131x_device_alloc( void ); + +void et131x_device_free( struct net_device *netdev ); + + + + +#endif /* __ET131X_NETDEV_H__ */ + --- linux-2.6.27.orig/ubuntu/et131x/ET1310_pm.c +++ linux-2.6.27/ubuntu/et131x/ET1310_pm.c @@ -0,0 +1,1723 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_pm.c - All power management related code (not completely implemented) + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/20 21:29:44 $ + $Revision: 1.8 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" +#include "ET1310_mac.h" +#include "ET1310_rx.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + ROUTINE: CalculateCCITCRC16 + ****************************************************************************** + DESCRIPTION: + This routine calculates the CCIT CRC-16 value required for power + management. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +UINT16 CalculateCCITCRC16( PUCHAR Pattern, PUCHAR Mask, UINT32 MaskSize ) +{ + UINT32 i, j, k, HitBit; + UINT16 RemainderCRC = 0xFFFF; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "CalculateCCITCRC16" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + There is one bit in the mask for every byte in the pattern. Therefore, + this first loop (the "i" loop) iterates over every byte in the mask, + the inner "j" loop iterates over every bit in each byte. If that bit + in the mask is clear, then we skip over this byte of packet date (the + "continue"). + *************************************************************************/ + for( i = 0; i < MaskSize; i++ ) + { + for( j = 0; j < 8; j++ ) + { + if(( Mask[i] & ( 1 << j )) == 0 ) + { + continue; + } + + /****************************************************************** + Following 10 lines iterates over every bit in this byte of the + pattern, and applies the CRC-16 calculation as defined by CCIT. + It could be optimized using a look-up-table, but this function + will be called infrequently, so the memory overhead of + optimization can be avoided. + *****************************************************************/ + for( k = 0; k < 8; k++ ) + { + HitBit = (( RemainderCRC >> 15 ) & 1 ); + HitBit ^= ( Pattern[(i*8)+j] >> k ) & 1; + + RemainderCRC <<= 1; + + if( HitBit ) + { + RemainderCRC ^= CRC16_POLY; + } + } + } + } + + DBG_LEAVE( et131x_dbginfo ); + return( RemainderCRC ); +} + +/*===========================================================================*/ + + + +#if 0 +/****************************************************************************** + ROUTINE: MPSetPowerD0 + ****************************************************************************** + DESCRIPTION: + Used to set the power state to D0, Updated for the ET1310 + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +VOID MPSetPowerD0( IN PMP_ADAPTER pAdapter ) +{ + UINT32 uPmCsr; + NDIS_DEVICE_POWER_STATE ComingBackFrom; + PM_CSR_t pm_csr = pAdapter->CSRAddress->global.pm_csr; + RXMAC_CTRL_t ctrl; + MI_ISR_t isr; + MI_BMSR_t Bmsr, BmsrInts; + UINT32 delay = 0; + + /*-----------------------------------------------------------------------*/ + + DBGPRINT( MP_TRACE, ( "----> MPSetPowerD0\n" )); + + /************************************************************************** + Archive the power-state we are returning from, and then set the + "current" power state back to fully operational + *************************************************************************/ + ComingBackFrom = pAdapter->PoMgmt.PowerState; + pAdapter->PoMgmt.PowerState = NdisDeviceStateD0; + + + /********************************************************************** + Allow disabling of Non-Maskable Interrupts in I/O space, to + support validation. + *********************************************************************/ + if( pAdapter->RegistryNMIDisable ) + { + UCHAR RegisterVal; + + NdisRawReadPortUchar( ET1310_NMI_DISABLE, &RegisterVal ); + + RegisterVal &= 0xf3; + + if( pAdapter->RegistryNMIDisable == 2 ) + { + RegisterVal |= 0xc; + } + + NdisRawWritePortUchar( ET1310_NMI_DISABLE, RegisterVal ); + } + + { + UCHAR read_size_reg; + + /****************************************************************** + Change the max read size to 2k + *****************************************************************/ + NdisReadPciSlotInformation( pAdapter->AdapterHandle, + 0, // not used + 0x51, + (PVOID)&read_size_reg, + sizeof( UCHAR )); + + read_size_reg &= 0x8f; + read_size_reg |= 0x40; + + NdisWritePciSlotInformation( pAdapter->AdapterHandle, + 0, + 0x51, + &read_size_reg, + sizeof( UCHAR )); + } + + + /************************************************************************** + Sample read of pmcsr to aid validation. Will be catured by PCI-e + analyzer + *************************************************************************/ + NdisReadPciSlotInformation( pAdapter->AdapterHandle, + 0, // Slot no. Reserved. Ndis ignores. + ET1310_PCI_PM_CSR, + (PVOID)&uPmCsr, + sizeof( UINT32 )); + + /************************************************************************** + we now need to set the JAGCore gating control registers for this power + state. Bypass this for nonwake device since in that case the JAGCore + and gigE PHY have been reset + + This is only supposeto be for wake mode, when in non-wake mode, the + device enters L1 which causes a reset of the jagcore which basically + clears the PM_STATE. But due to issue with system not staying in L1 the + hardware reset is not happening. So we take care of it here. + *************************************************************************/ + if( TRUE ) //pAdapter->PoMgmt.WOLEnabled ) + { + pm_csr.bits.pm_gigephy_en = 0; + pm_csr.bits.pm_jagcore_rx_en = 0; + pm_csr.bits.pm_jagcore_tx_en = 0; + pm_csr.bits.pm_phy_lped_en = 0; + pm_csr.bits.pm_phy_sw_coma = 0; + + /********************************************************************** + enable clock first + *********************************************************************/ + pm_csr.bits.pm_sysclk_gate = 1; + pm_csr.bits.pm_txclk_gate = 1; + pm_csr.bits.pm_rxclk_gate = 1; + + /********************************************************************** + tx_en and rx_en should remain the same as in power down + *********************************************************************/ + pAdapter->CSRAddress->global.pm_csr = pm_csr; + + /********************************************************************** + poll the PMSTATE until JAGCore is in normal state + *********************************************************************/ + while(( pAdapter->CSRAddress->global.pm_csr.bits.pm_jagcore_rx_rdy != 0 ) && + ( pAdapter->CSRAddress->global.pm_csr.bits.pm_jagcore_tx_rdy != 0 ) && + ( delay < 100 )) + { + NdisStallExecution( 10 ); + delay++; + } + + if( delay >= 100 ) + { + pm_csr = pAdapter->CSRAddress->global.pm_csr; + + pm_csr.bits.pm_jagcore_rx_en = 0; + pm_csr.bits.pm_jagcore_tx_en = 0; + pAdapter->CSRAddress->global.pm_csr.value = pm_csr.value; + } + } + + /************************************************************************** + now lets set up JAGcore pm control for D0 + *************************************************************************/ + pm_csr.bits.pm_gigephy_en = 0; + + pm_csr.bits.pm_jagcore_rx_en = pAdapter->PoMgmt.rx_en; + pm_csr.bits.pm_jagcore_tx_en = pAdapter->PoMgmt.tx_en; + + pAdapter->CSRAddress->global.pm_csr = pm_csr; + + /************************************************************************** + we also need to read and clear the phy_interrupt register in case of + wakeup on link status change + *************************************************************************/ + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, isr ), &isr.value ); + + /************************************************************************** + disable WOL + *************************************************************************/ + ctrl = pAdapter->CSRAddress->rxmac.ctrl; + + ctrl.bits.wol_disable = 1; + ctrl.bits.mif_disable = 0; + ctrl.bits.async_disable = 0; + + pAdapter->CSRAddress->rxmac.ctrl = ctrl; + + /************************************************************************** + Set the power state to 0 (d0), and flip the PME status pin. Clear the + PME Enable pin, if it were set. + *************************************************************************/ + uPmCsr = 0x00008000; + NdisWritePciSlotInformation( pAdapter->AdapterHandle, + 0, // Slot no. Reserved. Ndis ignores. + ET1310_PCI_PM_CSR, + &uPmCsr, + sizeof( UINT32 )); + + /************************************************************************** + When the adapter is placed in D3 wake, it is set in 10 Base-T + half-duplex mode. However, we archived the speed and duplex settings + that were current prior to that, so restore them now and then tell + the phy to do it's thing. + *************************************************************************/ + if(( ComingBackFrom == NdisDeviceStateD3 ) || + ( ComingBackFrom == NdisDeviceStateD1 && !pAdapter->PoMgmt.WOLEnabledByCurrentState )) + { + pAdapter->AiForceSpeed = pAdapter->PoMgmt.PowerDownSpeed; + pAdapter->AiForceDpx = pAdapter->PoMgmt.PowerDownDuplex; + + /********************************************************************** + Re-initialize the send structures + **********************************************************************/ + MPInitSend( pAdapter ); + + /********************************************************************** + Reset the RFD list and re-start RU + *********************************************************************/ + NICResetRecv( pAdapter ); + + /********************************************************************** + Bring the device back to the state it was during init prior + to autonegotiation being complete. This way, when we get the + auto-neg complete interrupt, we can complete init by calling + ConfigMacREGS2. + *********************************************************************/ + HwSoftwareReset( pAdapter ); + + /********************************************************************** + setup et1310 as per the documentation + *********************************************************************/ + NICSetAdapterUp( pAdapter ); + } + + /************************************************************************** + Allow Tx to restart + *************************************************************************/ + MP_CLEAR_FLAG( pAdapter, fMP_ADAPTER_LOWER_POWER ); + + /************************************************************************** + Check to see if the link status bit is set in the BMSR register, if it + is not, this means we had a cable pull when at a lower power state and + need to indicate that we are disconnected to NDIS + *************************************************************************/ + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, bmsr ), &Bmsr.value ); + + if( !Bmsr.bits.link_status ) + { + + pAdapter->Bmsr.value = Bmsr.value; + + NdisAcquireSpinLock( &pAdapter->Lock ); + MP_SET_FLAG( pAdapter, fMP_ADAPTER_LINK_DETECTION ); + pAdapter->MediaState = 0; + + NdisReleaseSpinLock( &pAdapter->Lock ); + + // get timer going again... + NdisMSetPeriodicTimer( &pAdapter->PeriodicTimer, + TX_ERROR_PERIOD ); + + // setup for possible disconnect + NdisMSetTimer( &pAdapter->LinkDetectionTimer, + LINK_DETECTION_TIMER ); + + pAdapter->bLinkTimerActive = TRUE; + + if( pAdapter->RegistryPhyComa ) + { + MPSetPhyComa( pAdapter ); + } + /********************************************************************** + In the case of link-in before sleep, link-out after sleep, we need + to re-start the start-of-day timer so that we eventually flop + into PhyComa. In this case, the above state change gets overwritten + since we get a PHY interrupt almost straight away, and PHY interrupt + handling pulls us out of PHY coma mode. + *********************************************************************/ + pAdapter->PoMgmt.TransPhyComaModeOnBoot = 0; + } + + /************************************************************************** + we need to enable interrupts + *************************************************************************/ + NdisMSynchronizeWithInterrupt( &pAdapter->Interrupt, + (PVOID)NICEnableInterrupts, + pAdapter ); + + DBGPRINT( MP_TRACE, ( "<---- MPSetPowerD0\n" )); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MPSetLowPower + ****************************************************************************** + DESCRIPTION: + This routine is called when the adapter receives a SetPower to any + state other than d0. Most of the common stuff for setting to a lower + power state should be handled in here. + + PARAMETERS : + pAdapter - pointer to our adapter structure + PowerState - NewPowerState + + RETURNS : + NONE + + *****************************************************************************/ +VOID MPSetLowPower( IN PMP_ADAPTER pAdapter, + IN NDIS_DEVICE_POWER_STATE PowerState ) +{ + PM_CSR_t GlobalPmCSR; + RXMAC_CTRL_t ctrl; + MI_ISR_t isr; + MI_BMSR_t lBmsr; + BOOLEAN bDummy; + /*-----------------------------------------------------------------------*/ + + /************************************************************************** + if we are in coma mode when we get this request, we need to disable it + *************************************************************************/ + if( pAdapter->CSRAddress->global.pm_csr.bits.pm_phy_sw_coma == 1 ) + { + /********************************************************************** + check to see if we are in coma mode and if so, disable it because + we will not be able to read phy values until we are out. + *********************************************************************/ + MPDisablePhyComa( pAdapter ); + } + + /************************************************************************** + interrupts will be queued until after this routine completes. May as + well disable them now, since we do not want any of the queued interrupts. + *************************************************************************/ + NdisMSynchronizeWithInterrupt( &pAdapter->Interrupt, + (PVOID)NICDisableInterrupts, + pAdapter ); + + /************************************************************************** + Set the adapter power state to requested, lower state + *************************************************************************/ + pAdapter->PoMgmt.PowerState = PowerState; + + /************************************************************************** + Cancel timers - start them again when power restored + *************************************************************************/ + NdisMCancelTimer( &pAdapter->PeriodicTimer, &bDummy ); + + if( pAdapter->bLinkTimerActive == TRUE ){ + NdisMCancelTimer( &pAdapter->LinkDetectionTimer, &bDummy ); + } + + /************************************************************************** + Save the GbE PHY speed and duplex modes + + Need to restore this for: D1 nonwake, D3 wake and nonwake modes + *************************************************************************/ + pAdapter->PoMgmt.PowerDownSpeed = pAdapter->AiForceSpeed; + pAdapter->PoMgmt.PowerDownDuplex = pAdapter->AiForceDpx; + + NdisAcquireSpinLock( &pAdapter->SendHWLock ); + + /************************************************************************** + Stop sending packets. + *************************************************************************/ + MP_SET_FLAG( pAdapter, fMP_ADAPTER_LOWER_POWER ); + + NdisReleaseSpinLock( &pAdapter->SendHWLock ); + + /************************************************************************** + Free the packets being actively sent & stopped + **************************************************************************/ + MpFreeBusySendPackets( pAdapter ); + + /************************************************************************** + Save Rx/Tx enable condition. Used during restore to D0 state. + *************************************************************************/ + pAdapter->PoMgmt.tx_en = pAdapter->CSRAddress->global.pm_csr.bits.pm_jagcore_tx_en; + pAdapter->PoMgmt.rx_en = pAdapter->CSRAddress->global.pm_csr.bits.pm_jagcore_rx_en; + + /************************************************************************** + set the JAGCore gating control registers for this power state + *************************************************************************/ + GlobalPmCSR = pAdapter->CSRAddress->global.pm_csr; + + if( pAdapter->PoMgmt.WOLEnabledByCurrentState ) + { + GlobalPmCSR.bits.pm_gigephy_en = 0; + } + else + { + GlobalPmCSR.bits.pm_gigephy_en = 1; + } + + /************************************************************************** + only exercise the PM state machine when the link is up + *************************************************************************/ + if( pAdapter->Bmsr.bits.link_status ) + { + GlobalPmCSR.bits.pm_jagcore_tx_en = 1; + GlobalPmCSR.bits.pm_jagcore_rx_en = 1; + + } + pAdapter->CSRAddress->global.pm_csr = GlobalPmCSR; + + ctrl = pAdapter->CSRAddress->rxmac.ctrl; + + /************************************************************************** + only exercise the PM state machine when the link is up + *************************************************************************/ + if( pAdapter->Bmsr.bits.link_status ) + { + /********************************************************************** + disable MIF so power state can transition + *********************************************************************/ + ctrl.bits.mif_disable = 1; + pAdapter->CSRAddress->rxmac.ctrl = ctrl; + + while(( pAdapter->CSRAddress->global.pm_csr.bits.pm_jagcore_rx_rdy != 1 ) + && ( pAdapter->CSRAddress->global.pm_csr.bits.pm_jagcore_tx_rdy != 1 )) + { + NdisStallExecution( 10 ); + } + } + + /************************************************************************** + Stop hardware from receiving packets - Set the RU to idle + *************************************************************************/ + NICRxDmaDisable( pAdapter ); + + /************************************************************************** + Wait for outstanding Receive packets + *************************************************************************/ + while( MP_GET_RCV_REF( pAdapter ) != 0 ) + { + /********************************************************************** + Sleep for 2 Ms; + *********************************************************************/ + NdisStallExecution( 2000 ); + } + + /************************************************************************** + D3Wake only - set the MAC and Phy to 10BaseT half-duplex operation. + Archive the current settings in the pAdapter structure so we can + restore them when done. + *************************************************************************/ + if(( PowerState == NdisDeviceStateD3 ) && pAdapter->PoMgmt.WOLEnabledByCurrentState && + pAdapter->Bmsr.bits.link_status ) + { + /********************************************************************** + initialize variable for testing if we failed to go to specific link + *********************************************************************/ + pAdapter->PoMgmt.Failed10Half = FALSE; + + /********************************************************************** + set the phy properly + *********************************************************************/ + pAdapter->AiForceSpeed = 10; + pAdapter->AiForceDpx = 1; + + TPAL_SetPhy10HalfDuplex( pAdapter ); + + /********************************************************************** + get the link status here, we need to wait until the link comes back + after reconfiguring it. + *********************************************************************/ + TPAL_GetLinkStatusInfo( pAdapter ); + + if( pAdapter->PoMgmt.Failed10Half ) + { + /****************************************************************** + re-initialize variable for testing if we failed to go to + specific link speed + *****************************************************************/ + pAdapter->PoMgmt.Failed10Half = FALSE; + + /****************************************************************** + set the phy properly + *****************************************************************/ + pAdapter->AiForceSpeed = 100; + pAdapter->AiForceDpx = 1; + + TPAL_SetPhy100HalfDuplex( pAdapter ); + + /****************************************************************** + get the link status here, we need to wait until the link comes + back after reconfiguring it. + *****************************************************************/ + TPAL_GetLinkStatusInfo( pAdapter ); + } + + // SetRxDmaTimer( pAdapter ); + ConfigMACRegs2( pAdapter ); + } + + if( pAdapter->PoMgmt.WOLEnabledByCurrentState ) + { + RXMAC_WOL_CTL_CRC0_t rxmac_ctl_crc0 = pAdapter->CSRAddress->rxmac.crc0; + RXMAC_WOL_CRC12_t crc12; + RXMAC_WOL_CRC34_t crc34; + ULONG ulResult; + UINT32 SerdesPhyControl; + UINT mask; + + ulResult = NdisReadPciSlotInformation( pAdapter->AdapterHandle, + 0, // not used + ET1310_PCI_PHY_INDEX_REG, + (PVOID)&SerdesPhyControl, + sizeof( UINT32 )); + + if( pAdapter->RegistryPMWOL ) + { + SerdesPhyControl |= 0x00010000; + } + else + { + SerdesPhyControl &= 0xfffeffff; + } + + ulResult = NdisWritePciSlotInformation( + pAdapter->AdapterHandle, + 0, + ET1310_PCI_PHY_INDEX_REG, + (PVOID)&SerdesPhyControl, + sizeof( UINT32 )); + + if( pAdapter->Bmsr.bits.link_status ) + { + /********************************************************************** + need to do this for all wake devices + make sure all ignore bits are set + *********************************************************************/ + rxmac_ctl_crc0.bits.ignore_broad = 1; + rxmac_ctl_crc0.bits.ignore_multi = 1; + rxmac_ctl_crc0.bits.ignore_uni = 1; + + if( pAdapter->RegistryWOLMatch & 0x1 ) + { + rxmac_ctl_crc0.bits.ignore_mp = 0; + } + else + { + rxmac_ctl_crc0.bits.ignore_mp = 1; + } + + if( pAdapter->RegistryWOLMatch & 0x2 ) + { + rxmac_ctl_crc0.bits.ignore_pp = 0; + } + else + { + rxmac_ctl_crc0.bits.ignore_pp = 1; + } + + if( pAdapter->RegistryWOLLink & 0x1 ) + { + rxmac_ctl_crc0.bits.ignore_link_chg = 0; + } + else + { + rxmac_ctl_crc0.bits.ignore_link_chg = 1; + } + + /****************************************************************** + Clear the pattern match validity bits - i.e. make all patterns + invalid + *****************************************************************/ + rxmac_ctl_crc0.value &= ~0x1f; + + if(( pAdapter->RegistryWOLMatch & 0x2 ) && + ( pAdapter->PoMgmt.localWolAndCrc0 & 0x1f )) + { + /************************************************************** + set the validity bits based on what has been enabled in + the adapter + *************************************************************/ + rxmac_ctl_crc0.value |= (pAdapter->PoMgmt.localWolAndCrc0 & 0x1f); + + /************************************************************** + Copy the five CRCs from the adapter + *************************************************************/ + rxmac_ctl_crc0.bits.crc0 = pAdapter->PoMgmt.WOLPatternList [0]; + crc12.bits.crc1 = pAdapter->PoMgmt.WOLPatternList [1]; + crc12.bits.crc2 = pAdapter->PoMgmt.WOLPatternList [2]; + crc34.bits.crc3 = pAdapter->PoMgmt.WOLPatternList [3]; + crc34.bits.crc4 = pAdapter->PoMgmt.WOLPatternList [4]; + + for( mask = 0; mask < 5; mask++) + { + UINT i; + PUINT32 pDevicePatternMask = (PUINT32) + (&pAdapter->CSRAddress->rxmac.mask0_word0) + + (mask * MAX_WOL_MASK_SIZE / 4); + if(( pAdapter->PoMgmt.localWolAndCrc0 >> mask ) & 0x1 ) + { + UINT32 Temp[ MAX_WOL_MASK_SIZE / 4 ]; + PUCHAR pNdisPatternMask; + + pNdisPatternMask = (PUCHAR)&pAdapter->PoMgmt.WOLMaskList[ mask ][ 0 ]; + + NdisZeroMemory( Temp, sizeof( Temp )); + NdisMoveMemory( Temp, pNdisPatternMask, + pAdapter->PoMgmt.WOLMaskSize[ mask ] ); + + /************************************************************** + Write the mask to the device using the pointer calculated + above. + *************************************************************/ + for( i=0; i<( MAX_WOL_MASK_SIZE / 4 ); i++ ) + { + pDevicePatternMask[ i ] = Temp[ i ]; + } + } + } + } + + pAdapter->CSRAddress->rxmac.crc0 = rxmac_ctl_crc0; + pAdapter->CSRAddress->rxmac.crc12 = crc12; + pAdapter->CSRAddress->rxmac.crc34 = crc34; + + /****************************************************************** + we also need to read and clear the phy_interrupt register in + case of wakeup on link status change + *****************************************************************/ + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, isr ), &isr.value ); + + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, bmsr ), &lBmsr.value ); + + /****************************************************************** + disable mif and async + *****************************************************************/ + ctrl.bits.mif_disable = 1; + ctrl.bits.async_disable = 1; + ctrl.bits.wol_disable = 0; + pAdapter->CSRAddress->rxmac.ctrl = ctrl; + + rxmac_ctl_crc0.bits.clr_intr = 1; + pAdapter->CSRAddress->rxmac.crc0.value = rxmac_ctl_crc0.value; + + DBGPRINT( MP_SPEC, ("Going down - ctrl 0x%x, crc0_ctl 0x%x\n", + pAdapter->CSRAddress->rxmac.ctrl.value, + pAdapter->CSRAddress->rxmac.crc0.value )); + + pAdapter->Stats.InterruptStatus.value = pAdapter->CSRAddress->global.int_status.value; + + DBGPRINT( MP_SPEC, ("Going down - int stat was 0x%x, now 0x%x\n", + pAdapter->Stats.InterruptStatus.value, + pAdapter->CSRAddress->global.int_status.value )); + } + else if( pAdapter->RegistryWOLLink & 0x1 ) + { + GlobalPmCSR = pAdapter->CSRAddress->global.pm_csr; + + /************************************************************************** + Gate off JAGCore 3 clock domains + *************************************************************************/ + GlobalPmCSR.bits.pm_sysclk_gate = 0; + GlobalPmCSR.bits.pm_txclk_gate = 0; + GlobalPmCSR.bits.pm_rxclk_gate = 0; + pAdapter->CSRAddress->global.pm_csr = GlobalPmCSR; + + /************************************************************************** + Program gigE PHY in to Coma mode + *************************************************************************/ + GlobalPmCSR.bits.pm_phy_sw_coma = 1; + GlobalPmCSR.bits.pm_phy_lped_en = 1; + + pAdapter->CSRAddress->global.pm_csr = GlobalPmCSR; + } + } +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MPSetPowerD1Wake + ****************************************************************************** + DESCRIPTION: + This routine is called when the adapter receives a SetPower to + D1 PowerState, and there is a set of wake-up patterns programmed + in the adapter. The set could consist of a single wake-up pattern. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +VOID MPSetPowerD1Wake( PMP_ADAPTER pAdapter ) +{ + UINT32 uPmCsr; + PM_CSR_t pm_csr; + /*-----------------------------------------------------------------------*/ + + DBGPRINT( MP_TRACE, ( "----> MPSetPowerD1Wake\n" )); + + /************************************************************************** + common power down functionality; disable Tx & Rx, disable wol while + it is being provisioned, archive Tx and Rx enable, and do some of the + gating into jagcore. + *************************************************************************/ + MPSetLowPower( pAdapter, NdisDeviceStateD1 ); + + if((( pAdapter->RegistryWOLLink & 0x1) == 0 ) || ( pAdapter->Bmsr.bits.link_status )) + { + /********************************************************************** + gate off paths we do not want active and leave ones we do + *********************************************************************/ + pm_csr = pAdapter->CSRAddress->global.pm_csr; + + pm_csr.bits.pm_sysclk_gate = 0; + pm_csr.bits.pm_txclk_gate = 0; + pm_csr.bits.pm_rxclk_gate = 1; + + pAdapter->CSRAddress->global.pm_csr = pm_csr; + } + + /************************************************************************** + Set the power state to 1 (d1), and blip the PME status pin. Set the + PME Enable pin, which indicates wake state to PCI. + *************************************************************************/ + uPmCsr = 0x00008100; + NdisWritePciSlotInformation( pAdapter->AdapterHandle, + 0, // Slot no. Reserved. Ndis ignores. + ET1310_PCI_PM_CSR, + &uPmCsr, + sizeof( UINT32 )); + + DBGPRINT( MP_TRACE, ( "<---- MPSetPowerD1Wake\n" )); + return; +} +/*===========================================================================*/ + + + + + +/****************************************************************************** + ROUTINE: MPSetPowerD1NonWake + ****************************************************************************** + DESCRIPTION: + This routine is called when the adapter receives a SetPower to + D1 PowerState, and there are no wake-up patterns programmed + in the adapter. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +VOID MPSetPowerD1NonWake( PMP_ADAPTER pAdapter ) +{ + UINT32 uPmCsr; + PM_CSR_t pm_csr; + /*-----------------------------------------------------------------------*/ + + DBGPRINT( MP_TRACE, ( "----> MPSetPowerD1NonWake\n" )); + + /************************************************************************** + common power down functionality; disable Tx & Rx, disable wol, + archive Tx and Rx enable, and do some of the gating into jagcore. + *************************************************************************/ + MPSetLowPower( pAdapter, NdisDeviceStateD1 ); + + /************************************************************************** + gate off paths we do not want active and leave ones we do + *************************************************************************/ + pm_csr = pAdapter->CSRAddress->global.pm_csr; + + pm_csr.bits.pm_sysclk_gate = 1; + pm_csr.bits.pm_txclk_gate = 1; + pm_csr.bits.pm_rxclk_gate = 1; + + pAdapter->CSRAddress->global.pm_csr = pm_csr; + + /************************************************************************** + Set the power state to 1 (d1), and blip the PME status pin. Leave the + PME Enable pin clear, which indicates non-wake state to PCI. + *************************************************************************/ + uPmCsr = 0x00008000; + NdisWritePciSlotInformation( pAdapter->AdapterHandle, + 0, // Slot no. Reserved. Ndis ignores. + ET1310_PCI_PM_CSR, + &uPmCsr, + sizeof( UINT32 )); + + DBGPRINT( MP_TRACE, ( "<---- MPSetPowerD1NonWake\n" )); + return; +} +/*===========================================================================*/ + + + + + +/****************************************************************************** + ROUTINE: MPSetPowerD3Wake + ****************************************************************************** + DESCRIPTION: + This routine is called when the adapter receives a SetPower to + D3 PowerState, and there is a set of wake-up patterns programmed + in the adapter. The set could consist of a single wake-up pattern. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +VOID MPSetPowerD3Wake( PMP_ADAPTER pAdapter ) +{ + UINT32 uPmCsr; + PM_CSR_t pm_csr; + /*-----------------------------------------------------------------------*/ + + DBGPRINT( MP_TRACE, ( "----> MPSetPowerD3Wake\n" )); + + /************************************************************************** + common power down functionality; disable Tx & Rx, disable wol while + it is being provisioned, archive Tx and Rx enable, and do some of the + gating into jagcore. + *************************************************************************/ + MPSetLowPower( pAdapter, NdisDeviceStateD3 ); + + if((( pAdapter->RegistryWOLLink & 0x1) == 0 ) || ( pAdapter->Bmsr.bits.link_status )) + { + /********************************************************************** + gate off paths we do not want active and leave ones we do + *********************************************************************/ + pm_csr = pAdapter->CSRAddress->global.pm_csr; + + pm_csr.bits.pm_sysclk_gate = 0; + pm_csr.bits.pm_txclk_gate = 0; + pm_csr.bits.pm_rxclk_gate = 1; + + pAdapter->CSRAddress->global.pm_csr = pm_csr; + } + + /************************************************************************** + Set the power state to 3 (d3), and blip the PME status pin. Set the + PME Enable pin, which indicates wake state to PCI. + *************************************************************************/ + uPmCsr = 0x00008100; + NdisWritePciSlotInformation( pAdapter->AdapterHandle, + 0, // Slot no. Reserved. Ndis ignores. + ET1310_PCI_PM_CSR, + &uPmCsr, + sizeof( UINT32 )); + + DBGPRINT( MP_TRACE, ( "<---- MPSetPowerD3Wake\n" )); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MPSetPowerD3NonWake + ****************************************************************************** + DESCRIPTION: + This routine is called when the adapter receives a SetPower to + D3 PowerState, and there are no wake-up patterns programmed + in the adapter. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +VOID MPSetPowerD3NonWake( PMP_ADAPTER pAdapter ) +{ + UINT32 uPmCsr; + PM_CSR_t pm_csr; + /*-----------------------------------------------------------------------*/ + + DBGPRINT( MP_TRACE, ( "----> MPSetPowerD3NonWake\n" )); + + /************************************************************************** + common power down functionality; disable Tx & Rx, disable wol, + archive Tx and Rx enable, and do some of the gating into jagcore. + *************************************************************************/ + MPSetLowPower( pAdapter, NdisDeviceStateD3 ); + + /************************************************************************** + gate off paths we do not want active and leave ones we do + *************************************************************************/ + pm_csr = pAdapter->CSRAddress->global.pm_csr; + pm_csr.bits.pm_sysclk_gate = 1; + pm_csr.bits.pm_txclk_gate = 1; + pm_csr.bits.pm_rxclk_gate = 1; + + pAdapter->CSRAddress->global.pm_csr = pm_csr; + + /************************************************************************** + Set the power state to 3 (d3), and blip the PME status pin. Leave the + PME Enable pin clear, which indicates non-wake state to PCI. + *************************************************************************/ + uPmCsr = 0x00008000; + NdisWritePciSlotInformation( pAdapter->AdapterHandle, + 0, // Slot no. Reserved. Ndis ignores. + ET1310_PCI_PM_CSR, + &uPmCsr, + sizeof( UINT32 )); + + DBGPRINT( MP_TRACE, ( "<---- MPSetPowerD3NonWake\n" )); + + return; +} +/*===========================================================================*/ + +#endif + + +/****************************************************************************** + ROUTINE: EnablePhyComa + ****************************************************************************** + DESCRIPTION: + This routine is called when network cable is unplugged -- driver + receive an phy status change interrupt while in D0 and check that + phy_status is down. + + -- gate off JAGCore; + -- set gigE PHY in Coma mode + -- wake on phy_interrupt; Perform software reset JAGCore, + re-initialize jagcore and gigE PHY + + Add D0-ASPM-PhyLinkDown Support: + -- while in D0, when there is a phy_interrupt indicating phy link + down status, call the MPSetPhyComa routine to enter this active + state power saving mode + -- while in D0-ASPM-PhyLinkDown mode, when there is a phy_interrupt + indicating linkup status, call the MPDisablePhyComa routine to + restore JAGCore and gigE PHY + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void EnablePhyComa( ET131X_ADAPTER *pAdapter ) +{ + unsigned long lockflags; + PM_CSR_t GlobalPmCSR = pAdapter->CSRAddress->global.pm_csr; + INT32 LoopCounter = 10; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "EnablePhyComa" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Save the GbE PHY speed and duplex modes + Need to restore this when cable is plugged back in + *************************************************************************/ + pAdapter->PoMgmt.PowerDownSpeed = pAdapter->AiForceSpeed; + pAdapter->PoMgmt.PowerDownDuplex = pAdapter->AiForceDpx; + + + /************************************************************************** + Stop sending packets. + *************************************************************************/ + spin_lock_irqsave( &pAdapter->SendHWLock, lockflags ); + + MP_SET_FLAG( pAdapter, fMP_ADAPTER_LOWER_POWER ); + + spin_unlock_irqrestore( &pAdapter->SendHWLock, lockflags ); + + + /************************************************************************** + Wait for outstanding Receive packets + *************************************************************************/ + while(( MP_GET_RCV_REF( pAdapter ) != 0 ) && ( LoopCounter-- > 0 )) + { + /********************************************************************** + Sleep for 2 Ms; + *********************************************************************/ + mdelay( 2 ); + } + + + /************************************************************************** + Gate off JAGCore 3 clock domains + *************************************************************************/ + GlobalPmCSR.bits.pm_sysclk_gate = 0; + GlobalPmCSR.bits.pm_txclk_gate = 0; + GlobalPmCSR.bits.pm_rxclk_gate = 0; + pAdapter->CSRAddress->global.pm_csr = GlobalPmCSR; + + + /************************************************************************** + Program gigE PHY in to Coma mode + *************************************************************************/ + GlobalPmCSR.bits.pm_phy_sw_coma = 1; + + pAdapter->CSRAddress->global.pm_csr = GlobalPmCSR; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: DisablePhyComa + ****************************************************************************** + DESCRIPTION: + This routine is used to disable the Phy Coma Mode + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void DisablePhyComa( ET131X_ADAPTER *pAdapter ) +{ + PM_CSR_t GlobalPmCSR = pAdapter->CSRAddress->global.pm_csr; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "DisablePhyComa" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************* + Disable phy_sw_coma register and re-enable JAGCore clocks + ************************************************************************/ + GlobalPmCSR.bits.pm_sysclk_gate = 1; + GlobalPmCSR.bits.pm_txclk_gate = 1; + GlobalPmCSR.bits.pm_rxclk_gate = 1; + GlobalPmCSR.bits.pm_phy_sw_coma = 0; + + pAdapter->CSRAddress->global.pm_csr = GlobalPmCSR; + + + /************************************************************************** + Restore the GbE PHY speed and duplex modes; + Reset JAGCore; re-configure and initialize JAGCore and gigE PHY + *************************************************************************/ + pAdapter->AiForceSpeed = pAdapter->PoMgmt.PowerDownSpeed; + pAdapter->AiForceDpx = pAdapter->PoMgmt.PowerDownDuplex; + + + /************************************************************************** + Re-initialize the send structures + *************************************************************************/ + et131x_init_send( pAdapter ); + + + /************************************************************************** + Reset the RFD list and re-start RU + *************************************************************************/ + et131x_reset_recv( pAdapter ); + + + /************************************************************************** + Bring the device back to the state it was during init prior to + autonegotiation being complete. This way, when we get the auto-neg + complete interrupt, we can complete init by calling ConfigMacREGS2. + *************************************************************************/ + et131x_soft_reset( pAdapter ); + + + /************************************************************************** + setup et1310 as per the documentation ?? + *************************************************************************/ + et131x_adapter_setup( pAdapter ); + + + /************************************************************************** + Allow Tx to restart + *************************************************************************/ + MP_CLEAR_FLAG( pAdapter, fMP_ADAPTER_LOWER_POWER ); + + + /************************************************************************** + Need to re-enable Rx. + *************************************************************************/ + et131x_rx_dma_enable( pAdapter ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + +#if 0 +/****************************************************************************** + ROUTINE: MPSetPower + ****************************************************************************** + + DESCRIPTION: + This routine is called when the adapter receives a SetPower + request. It redirects the call to an appropriate routine to + Set the New PowerState + + PARAMETERS : + pAdapter - pointer to the adapter structure + PowerState - NewPowerState + + RETURN : + NONE + + *****************************************************************************/ +VOID MPSetPower( IN PMP_ADAPTER pAdapter, + IN NDIS_DEVICE_POWER_STATE PowerState ) +{ + DBGPRINT( MP_TRACE, ( "====> MPSetPower()\n" )); + + /************************************************************************** + determine what power state we are going to and go there + *************************************************************************/ + pAdapter->PoMgmt.WOLEnabledByCurrentState = TRUE; + + if( !pAdapter->PoMgmt.WOLEnabledByNdis ) + { + pAdapter->PoMgmt.WOLEnabledByCurrentState = FALSE; + } + + if(( pAdapter->RegistryWOLMatch == 0 ) && ( pAdapter->RegistryWOLLink == 0 )) + { + pAdapter->PoMgmt.WOLEnabledByCurrentState = FALSE; + } + + if(( pAdapter->PoMgmt.localWolAndCrc0 & 0x1f ) == 0 ) + { + /********************************************************************** + There are no wake patterns programmed. + *********************************************************************/ + if( pAdapter->RegistryWOLLink == 0 ) + { + pAdapter->PoMgmt.WOLEnabledByCurrentState = FALSE; + } + } + + /************************************************************************** + If the link is pulled, then the only wake event that will wake us + up is wake on link state change. If this change is disabled (0), go + to a non-wake state. + *************************************************************************/ + if( !pAdapter->ucLinkStatus && ( pAdapter->RegistryWOLLink == 0 )) + { + pAdapter->PoMgmt.WOLEnabledByCurrentState = 0; + } + + if( PowerState == NdisDeviceStateD0 ) + { + MPSetPowerD0( pAdapter ); + } + else if( PowerState == NdisDeviceStateD1 ) + { + if( pAdapter->PoMgmt.WOLEnabledByCurrentState ) + { + MPSetPowerD1Wake( pAdapter ); + } + else + { + MPSetPowerD1NonWake( pAdapter ); + } + } + else if( PowerState == NdisDeviceStateD3 ) + { + if( pAdapter->PoMgmt.WOLEnabledByCurrentState ) + { + MPSetPowerD3Wake( pAdapter ); + } + else + { + MPSetPowerD3NonWake( pAdapter ); + } + } + + DBGPRINT( MP_TRACE, ( "<==== MPSetPower()\n" )); +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MPFillPoMgmtCaps + ****************************************************************************** + + DESCRIPTION: + Fills in the Power Managment structure depending the capabilities of + the software driver and the card. MGS CURRENTLY NOT SUPPORTED + + + PARAMETERS : + pAdapter - pointer to the adapter structure + pPowManageCaps - power management struct as defined in the DDK, + pStatus - status to be returned by the request, + pulInfoLen - length of the pPowerManagmentCapabilites + + RETURN : + Success or failure + + NOTE: + If the driver returns NDIS_STATUS_SUCCESS in response to a query of + this OID, NDIS treats a miniport driver as power management-aware. + If the driver returns NDIS_STATUS_NOT_SUPPORTED, NDIS treats the + miniport driver as a legacy driver that is not power + management-aware. + + The Bus driver is the power policy owner here so we do not have to + perform our mapping of System States to Device states, that is + accomplished by NDIS, we need to worry more about our wake-up + capabilities + + *****************************************************************************/ +VOID MPFillPoMgmtCaps( IN PMP_ADAPTER pAdapter, + IN OUT PNDIS_PNP_CAPABILITIES pPowMgmtCaps, + IN OUT PNDIS_STATUS pStatus, + IN OUT PULONG pulInfoLen ) +{ + BOOLEAN bIsPoMgmtSupported = TRUE; + /*-----------------------------------------------------------------------*/ + + bIsPoMgmtSupported = MPIsPoMgmtSupported( pAdapter ); + + if( bIsPoMgmtSupported ) + { + /********************************************************************** + NDIS_DEVICE_WAKE_UP_ENABLE; + *********************************************************************/ + pPowMgmtCaps->Flags = 0; + + /********************************************************************** + Magic Packet wakeups + *********************************************************************/ + pPowMgmtCaps->WakeUpCapabilities.MinMagicPacketWakeUp = + NdisDeviceStateD3; + + /********************************************************************** + NdisDeviceStateD3; + *********************************************************************/ + pPowMgmtCaps->WakeUpCapabilities.MinPatternWakeUp = + NdisDeviceStateD3; + pPowMgmtCaps->WakeUpCapabilities.MinLinkChangeWakeUp = + NdisDeviceStateD3; + + *pulInfoLen = sizeof( *pPowMgmtCaps ); + *pStatus = NDIS_STATUS_SUCCESS; + } + else + { + NdisZeroMemory( pPowMgmtCaps, sizeof( *pPowMgmtCaps )); + + *pStatus = NDIS_STATUS_NOT_SUPPORTED; + *pulInfoLen = 0; + } +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MPAddWakeUpPattern + ****************************************************************************** + + DESCRIPTION: + This routine will allocate a local memory structure, copy the pattern, + insert the pattern into a linked list and return success + + We are gauranteed that we wll get only one request at a time, so this + is implemented without locks. + + PARAMETERS : + pAdapter - pointer to the adapter structure + InformationBuffer - Wake up Pattern + InformationBufferLength - Wake Up Pattern Length + + RETURN : + Success - if successful + NDIS_STATUS_FAILURE - if memory allocation fails + + *****************************************************************************/ +NDIS_STATUS MPAddWakeUpPattern( IN PMP_ADAPTER pAdapter, + IN PVOID InfoBuf, + IN UINT InfoBufLen ) +{ + NDIS_STATUS Status; + PNDIS_PM_PACKET_PATTERN pPmPattern = NULL; + UINT Slot = 0, FreeSlot = 0xff; + PUCHAR pNdisPatternMask; + PUINT32 pDevicePatternMask; + UINT16 DevMagicNumber; + UINT i; + + PUCHAR TempBuf; + ULONG offset; + + /*-----------------------------------------------------------------------*/ + + pPmPattern = (PNDIS_PM_PACKET_PATTERN)InfoBuf; + + /************************************************************************** + Check that the wake-up pattern is not too large for us. Also, not + sure how to deal with a pattern whose mask is smaller than the pattern + *************************************************************************/ + if(( pPmPattern->MaskSize < (( pPmPattern->PatternSize / 8) + 1)) || + ( pPmPattern->PatternSize > MAX_WOL_PACKET_SIZE)) + { + return( NDIS_STATUS_RESOURCES ); + } + + NdisAcquireSpinLock( &pAdapter->Lock ); + + /************************************************************************** + Check to see if there is an empty slot on the device to store this + pattern. Store the slot number for later use. + *************************************************************************/ + while ((FreeSlot == 0xff) && (Slot < NUM_WOL_PATTERNS)) + { + if (!((pAdapter->PoMgmt.localWolAndCrc0 >> Slot) & 0x1)) + { + FreeSlot = Slot; + } + else + { + Slot++; + } + } + + if( FreeSlot == 0xff ) + { + /********************************************************************** + Failed to find a free slot. + *********************************************************************/ + NdisReleaseSpinLock( &pAdapter->Lock ); + return( NDIS_STATUS_RESOURCES ); + } + + pNdisPatternMask = (PUCHAR)InfoBuf + sizeof( NDIS_PM_PACKET_PATTERN ); + + /************************************************************************** + Make a copy of what Ndis sent us + *************************************************************************/ + for( i=0; iMaskSize; i++ ) + { + pAdapter->PoMgmt.WOLMaskList[ FreeSlot ][ i ] = pNdisPatternMask[ i ]; + } + + /************************************************************************** + Calculate the CRC that will be used by the device to identify this + packet + *************************************************************************/ + offset = 0; + TempBuf = (PUCHAR)( InfoBuf ) + pPmPattern->PatternOffset; + + DevMagicNumber = MPCalculateCCITCRC16( TempBuf, + (PUCHAR )( InfoBuf ) + + sizeof( NDIS_PM_PACKET_PATTERN ), + pPmPattern->MaskSize ); + + DBGPRINT( MP_SPEC, ( "DevMagicNumber 0x%08x\n", DevMagicNumber )); + DBGPRINT( MP_SPEC, ( "Pattern Size : 0x%08x, MaskSize : 0x%08x\n", + pPmPattern->PatternSize, pPmPattern->MaskSize )); + + pAdapter->PoMgmt.localWolAndCrc0 |= ( 1 << FreeSlot ); + + /************************************************************************** + Now handle storing the pattern in our adapter. Only store what makes + the pattern unique to our device. (the CRC, the mask and the mask + size. The pattern is irrelevant, since it is not stored in the + device). The mask is stored above. + *************************************************************************/ + pAdapter->PoMgmt.WOLPatternList[ FreeSlot ] = DevMagicNumber; + pAdapter->PoMgmt.WOLMaskSize[ FreeSlot ] = pPmPattern->MaskSize; + + NdisReleaseSpinLock( &pAdapter->Lock ); + return( NDIS_STATUS_SUCCESS ); +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MPRemoveWakeUpPattern + ****************************************************************************** + + DESCRIPTION: + This routine will scan the array of wake up patterns and attempt to + match the wake up pattern. If it finds a copy , it will remove that + WakeUpPattern + + PARAMETERS: + pAdapter - pointer to the Adapter structure + InformationBuffer - Wake up Pattern + InformationBufferLength - Wake Up Pattern Length + + RETURN: + Success - if successful. + NDIS_STATUS_FAILURE - if memory allocation fails. + + *****************************************************************************/ +NDIS_STATUS MPRemoveWakeUpPattern( IN PMP_ADAPTER pAdapter, + IN PVOID InformationBuffer, + IN UINT InformationBufferLength ) +{ + + PNDIS_PM_PACKET_PATTERN pPmPattern = NULL; + UINT Slot = 0, FoundSlot = 0xff; + UINT16 DevMagicNumber; + /*-----------------------------------------------------------------------*/ + + pPmPattern = (PNDIS_PM_PACKET_PATTERN)InformationBuffer; + + /************************************************************************** + Check that the wake-up pattern is not too large for us. Also, not + sure how to deal with a pattern whose mask is not the same size + as the pattern. + *************************************************************************/ + if(( pPmPattern->MaskSize < (( pPmPattern->PatternSize / 8) + 1)) || + ( pPmPattern->PatternSize > MAX_WOL_PACKET_SIZE)) + { + return NDIS_STATUS_FAILURE; + } + + /************************************************************************** + Calculate the CRC that will be used by the device to identify this + packet + *************************************************************************/ + DevMagicNumber = MPCalculateCCITCRC16( (PUCHAR )( InformationBuffer ) + + pPmPattern->PatternOffset , + (PUCHAR )( InformationBuffer ) + + sizeof( NDIS_PM_PACKET_PATTERN ), + pPmPattern->MaskSize ); + + NdisAcquireSpinLock( &pAdapter->Lock ); + + while ((FoundSlot == 0xff) && (Slot < NUM_WOL_PATTERNS)) + { + if(( pAdapter->PoMgmt.WOLPatternList[ Slot ] == DevMagicNumber ) && + ( pAdapter->PoMgmt.WOLMaskSize[ Slot ] == pPmPattern->MaskSize ) && + (( pAdapter->PoMgmt.localWolAndCrc0 >> Slot ) & 0x1) ) + { + UINT i; + PUCHAR pIncomingMask = (PUCHAR)( InformationBuffer ) + + sizeof( NDIS_PM_PACKET_PATTERN ); + + for( i=0; iMaskSize; i++ ) + { + if( pAdapter->PoMgmt.WOLMaskList[ Slot ][ i ] != + pIncomingMask[ i ] ) + { + break; + } + } + if( i >= pPmPattern->MaskSize ) + { + FoundSlot = Slot; + } + } + + Slot++; + } + + if( FoundSlot == 0xff ) + { + /********************************************************************** + Failed to find this packet in the list coinciding with a valid + entry in the device. + *********************************************************************/ + NdisReleaseSpinLock( &pAdapter->Lock ); + return( NDIS_STATUS_FAILURE ); + } + + pAdapter->PoMgmt.localWolAndCrc0 &= ~( 1 << FoundSlot ); + + NdisReleaseSpinLock( &pAdapter->Lock ); + + return( NDIS_STATUS_SUCCESS ); +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MPRemoveAllWakeUpPatterns + ****************************************************************************** + + DESCRIPTION: + This routine disables all wake-up on the device. Probably not + required. + + PARAMETERS: + pAdapter - pointer to the adapter structure + + RETURN: + Nothing + + *****************************************************************************/ +VOID MPRemoveAllWakeUpPatterns( IN PMP_ADAPTER pAdapter ) +{ + RXMAC_WOL_CTL_CRC0_t crc0; + /*-----------------------------------------------------------------------*/ + + if( pAdapter ) + { + NdisAcquireSpinLock( &pAdapter->Lock ); + + pAdapter->PoMgmt.localWolAndCrc0 = 0; + + NdisReleaseSpinLock( &pAdapter->Lock ); + } +} +/*===========================================================================*/ + +#endif --- linux-2.6.27.orig/ubuntu/et131x/et131x_version.h +++ linux-2.6.27/ubuntu/et131x/et131x_version.h @@ -0,0 +1,124 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_version.h - This file provides system and device version information. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/31 20:58:43 $ + $Revision: 1.16 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_VERSION_H__ +#define __ET131X_VERSION_H__ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include +#include + + + + +/****************************************************************************** + Constant Definitions + *****************************************************************************/ +#define DRIVER_AUTHOR "Victor Soriano (vjsoriano@agere.com)" +#define DRIVER_LICENSE "BSD" +#define DRIVER_DEVICE_STRING "ET1310" +#define DRIVER_NAME "et131x" +#define DRIVER_MAJOR_VERSION 1 +#define DRIVER_MINOR_VERSION 2 +#define DRIVER_PATCH_VERSION 3 +#define DRIVER_VERSION_STRING "1.2.3" +#define DRIVER_VENDOR "Agere Systems, http://www.agere.com" +#define DRIVER_BUILD_DATE "01/31/2006 15:40:00" +#define DRIVER_DESC "10/100/1000 Base-T Ethernet Driver" + +#define STRUCT_MODULE "net" // blux: missed by the kernel + +#define DRIVER_INFO DRIVER_DESC " for the "\ + DRIVER_DEVICE_STRING ", v" \ + DRIVER_VERSION_STRING " " \ + DRIVER_BUILD_DATE " by " \ + DRIVER_VENDOR + + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#define DRIVER_NAME_EXT "et131x.o" +#else +#define DRIVER_NAME_EXT "et131x.ko" +#endif + + + + +#endif /* __ET131X_VERSION_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_debug.c +++ linux-2.6.27/ubuntu/et131x/et131x_debug.c @@ -0,0 +1,328 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_debug.c - Routines used for debugging. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:12 $ + $Revision: 1.6 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifdef ET131X_DBG + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_netdev.h" +#include "et131x_config.h" +#include "et131x_isr.h" + +#include "ET1310_address_map.h" +#include "ET1310_jagcore.h" +#include "ET1310_tx.h" +#include "ET1310_rx.h" +#include "ET1310_mac.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +extern dbg_info_t *et131x_dbginfo; + + + + +/****************************************************************************** + ROUTINE: DumpTxQueueContents + ****************************************************************************** + DESCRIPTION: + Used to dump out hte tx queue and the shadow pointers + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void DumpTxQueueContents( int dbgLvl, ET131X_ADAPTER *pAdapter ) +{ + UINT32 TxQueueAddr; + /*-----------------------------------------------------------------------*/ + + + if( DBG_FLAGS( et131x_dbginfo ) & dbgLvl ) + { + + for( TxQueueAddr = 0x200; TxQueueAddr< 0x3ff; TxQueueAddr++ ) + { + pAdapter->CSRAddress->mmc.sram_access.bits.req_addr = TxQueueAddr; + pAdapter->CSRAddress->mmc.sram_access.bits.req_access = 1; + + + DBG_PRINT( "Addr 0x%x, Access 0x%08x\t" + "Value 1 0x%08x, Value 2 0x%08x, " + "Value 3 0x%08x, Value 4 0x%08x, \n", + TxQueueAddr, + pAdapter->CSRAddress->mmc.sram_access.value, + pAdapter->CSRAddress->mmc.sram_word1.data, + pAdapter->CSRAddress->mmc.sram_word2.data, + pAdapter->CSRAddress->mmc.sram_word3.data, + pAdapter->CSRAddress->mmc.sram_word4.data ); + + } + + DBG_PRINT( "Shadow Pointers 0x%08x\n", + pAdapter->CSRAddress->txmac.shadow_ptr.value ); + } + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: DumpDeviceBlock + ****************************************************************************** + + DESCRIPTION: + Dumps the first 64 regs of each block of the et-1310 (each block is + mapped to a new page, each page is 4096 bytes). + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURN : + VOID + *****************************************************************************/ +#define NUM_BLOCKS 8 +void DumpDeviceBlock( int dbgLvl, ET131X_ADAPTER *pAdapter, UINT32 Block ) +{ + UINT32 Address1, Address2; + UINT32 *BigDevicePointer = (UINT32 *)pAdapter->CSRAddress; + /*-----------------------------------------------------------------------*/ + + + char* BlockNames[NUM_BLOCKS] = + {"Global", "Tx DMA", "Rx DMA", "Tx MAC", + "Rx MAC", "MAC", "MAC Stat", "MMC" }; + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + Output the debug counters to the debug terminal + *************************************************************************/ + if( DBG_FLAGS( et131x_dbginfo ) & dbgLvl ) + { + DBG_PRINT( "%s block\n", BlockNames[Block] ); + + for( Address1 = 0; Address1 < 8; Address1++ ) + { + for( Address2 = 0; Address2 < 8; Address2++ ) + { + if( Block == 0 ) + { + if((( Address1 * 8 ) + Address2 ) == 6 ) + { + DBG_PRINT( " ISR , " ); + } + else + { + DBG_PRINT( "0x%08x, ", + BigDevicePointer[( Block * 1024 ) + + ( Address1 * 8 ) + Address2] ); + + } + } + else + { + DBG_PRINT( "0x%08x, ", + BigDevicePointer[( Block * 1024 ) + + ( Address1 * 8 ) + Address2] ); + } + } + + DBG_PRINT( "\n" ); + } + + DBG_PRINT( "\n" ); + } + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: DumpDeviceReg + ****************************************************************************** + + DESCRIPTION: + Dumps the first 64 regs of each block of the et-1310 (each block is + mapped to a new page, each page is 4096 bytes). + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURN : + VOID + *****************************************************************************/ +void DumpDeviceReg( int dbgLvl, ET131X_ADAPTER *pAdapter ) +{ + UINT32 Address1, Address2; + UINT32 Block; + UINT32 *BigDevicePointer = (UINT32 *)pAdapter->CSRAddress; + + char* BlockNames[NUM_BLOCKS] = + {"Global", "Tx DMA", "Rx DMA", "Tx MAC", + "Rx MAC", "MAC", "MAC Stat", "MMC" }; + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + Output the debug counters to the debug terminal + *************************************************************************/ + if( DBG_FLAGS( et131x_dbginfo ) & dbgLvl ) + { + for( Block = 0; Block < NUM_BLOCKS; Block++ ) + { + DBG_PRINT( "%s block\n", BlockNames[Block] ); + + for( Address1 = 0; Address1 < 8; Address1++ ) + { + for( Address2 = 0; Address2 < 8; Address2++ ) + { + DBG_PRINT( "0x%08x, ", + BigDevicePointer[( Block * 1024 ) + + ( Address1 * 8 ) + Address2] ); + } + + DBG_PRINT( "\n" ); + } + + DBG_PRINT( "\n" ); + } + } + + return; +} +/*==========================================================================*/ + + + + +#endif // ET131X_DBG --- linux-2.6.27.orig/ubuntu/et131x/et131x_initpci.h +++ linux-2.6.27/ubuntu/et131x/et131x_initpci.h @@ -0,0 +1,103 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_initpci.h - Header which includes common data and function prototypes + * related to the driver's PCI (and PCI Express) information. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 17:31:23 $ + $Revision: 1.4 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_INITPCI_H__ +#define __ET131X_INITPCI_H__ + + + + +/****************************************************************************** + Function Prototypes + *****************************************************************************/ +int et131x_pci_register( void ); +void et131x_pci_unregister( void ); + +void et131x_align_allocated_memory( ET131X_ADAPTER *adapter, + UINT64 *phys_addr, + UINT64 *offset, + UINT64 mask ); + + + + +int et131x_adapter_setup( ET131X_ADAPTER *pAdapter ); +int et131x_adapter_memory_alloc( ET131X_ADAPTER *adapter ); +void et131x_adapter_memory_free( ET131X_ADAPTER *adapter ); +void et131x_setup_hardware_properties( ET131X_ADAPTER *adapter ); +void et131x_soft_reset( ET131X_ADAPTER *adapter ); + +#endif /* __ET131X_INITPCI_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_config.h +++ linux-2.6.27/ubuntu/et131x/et131x_config.h @@ -0,0 +1,99 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_config.h - Defines, structs, enums, prototypes, etc. to support + * et131x_config.c + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:12 $ + $Revision: 1.4 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_CONFIG_H__ +#define __ET131X_CONFIG_H__ + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + + + +/****************************************************************************** + PROTOTYPES for et131x_config.c + *****************************************************************************/ +void et131x_config_parse( struct et131x_adapter *pAdapter ); + + + + +#endif /* __ET131X_CONFIG_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_phy.c +++ linux-2.6.27/ubuntu/et131x/ET1310_phy.c @@ -0,0 +1,2728 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_phy.c - Routines for configuring and accessing the PHY + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/20 21:29:44 $ + $Revision: 1.13 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_netdev.h" +#include "et131x_initpci.h" + +#include "ET1310_address_map.h" +#include "ET1310_jagcore.h" +#include "ET1310_tx.h" +#include "ET1310_rx.h" +#include "ET1310_mac.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Prototypes for functions with local scope + *****************************************************************************/ +int et131x_xcvr_init( ET131X_ADAPTER *adapter ); + + + + +/****************************************************************************** + ROUTINE : MiRead + ****************************************************************************** + + DESCRIPTION : Used to read from the PHY through the MII Interface on + the MAC. + + PARAMETERS : adapter - pointer to our private adapter structure + xcvrAddr - the address of the transciever + xcvrReg - the register to read + value - pointer to a 16-bit value in which the value + will be stored. + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int MiRead( ET131X_ADAPTER *adapter, UINT8 xcvrAddr, UINT8 xcvrReg, UINT16 *value ) +{ + int status = 0; + UINT32 delay; + MII_MGMT_ADDR_t miiAddr; + MII_MGMT_CMD_t miiCmd; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "MiRead" ); + + + /************************************************************************** + Save a local copy of the registers we are dealing with so we can set + them back + *************************************************************************/ + miiAddr.value = adapter->CSRAddress->mac.mii_mgmt_addr.value; + miiCmd.value = adapter->CSRAddress->mac.mii_mgmt_cmd.value; + + + /************************************************************************** + Stop the current operation + *************************************************************************/ + adapter->CSRAddress->mac.mii_mgmt_cmd.value = 0x0; + + + /************************************************************************** + Set up the register we need to read from on the correct PHY + *************************************************************************/ + { + MII_MGMT_ADDR_t mii_mgmt_addr = {0}; + + mii_mgmt_addr.bits.phy_addr = xcvrAddr; + mii_mgmt_addr.bits.reg_addr = xcvrReg; + + adapter->CSRAddress->mac.mii_mgmt_addr = mii_mgmt_addr; + } + + + /************************************************************************** + Kick the read cycle off + *************************************************************************/ + delay = 0; + + adapter->CSRAddress->mac.mii_mgmt_cmd.value = 0x1; + + do + { + udelay( 50 ); + delay++; + } while(( adapter->CSRAddress->mac.mii_mgmt_indicator.bits.not_valid || + adapter->CSRAddress->mac.mii_mgmt_indicator.bits.busy ) && + ( delay < 50 )); + + + /************************************************************************** + If we hit the max delay, we could not read the register + *************************************************************************/ + if( delay >= 50 ) + { + DBG_WARNING( et131x_dbginfo, "xcvrReg 0x%08x could not be read\n", xcvrReg ); + DBG_WARNING( et131x_dbginfo, "status is 0x%08x\n", + adapter->CSRAddress->mac.mii_mgmt_indicator.value ); + + status = -EIO; + } + + + /************************************************************************** + If we hit here we were able to read the register and we need to return + the value to the caller + *************************************************************************/ + *value = (UINT16)adapter->CSRAddress->mac.mii_mgmt_stat.bits.phy_stat; + + + /************************************************************************** + Stop the read operation + *************************************************************************/ + adapter->CSRAddress->mac.mii_mgmt_cmd.value = 0x0; + + DBG_VERBOSE( et131x_dbginfo, " xcvr_addr = 0x%02x, " + "xcvr_reg = 0x%02x, " + "value = 0x%04x.\n", + xcvrAddr, xcvrReg, *value ); + + + /************************************************************************** + set the registers we touched back to the state at which we entered + this function + *************************************************************************/ + adapter->CSRAddress->mac.mii_mgmt_addr.value = miiAddr.value; + adapter->CSRAddress->mac.mii_mgmt_cmd.value = miiCmd.value; + + + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : MiWrite + ****************************************************************************** + + DESCRIPTION : Used to write to a PHY register through the MII + interface of the MAC. Updated for the ET1310. + + PARAMETERS : adapter - pointer to our private adapter structure + xcvrAddr - the address of the transciever + xcvrReg - the register to read + value - 16-bit value to write + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int MiWrite( ET131X_ADAPTER *adapter, UINT8 xcvrAddr, UINT8 xcvrReg, UINT16 value ) +{ + int status = 0; + UINT32 delay; + MII_MGMT_ADDR_t miiAddr; + MII_MGMT_CMD_t miiCmd; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "MiWrite" ); + + + /************************************************************************** + Save a local copy of the registers we are dealing with so we can set + them back + *************************************************************************/ + miiAddr.value = adapter->CSRAddress->mac.mii_mgmt_addr.value; + miiCmd.value = adapter->CSRAddress->mac.mii_mgmt_cmd.value; + + + /************************************************************************** + Stop the current operation + *************************************************************************/ + adapter->CSRAddress->mac.mii_mgmt_cmd.value = 0x0; + + + /************************************************************************** + Set up the register we need to write to on the correct PHY + *************************************************************************/ + { + MII_MGMT_ADDR_t mii_mgmt_addr = {0}; + + mii_mgmt_addr.bits.phy_addr = xcvrAddr; + mii_mgmt_addr.bits.reg_addr = xcvrReg; + + adapter->CSRAddress->mac.mii_mgmt_addr = mii_mgmt_addr; + } + + + /************************************************************************** + Add the value to write to the registers to the mac + *************************************************************************/ + adapter->CSRAddress->mac.mii_mgmt_ctrl.value = value; + delay = 0; + + do + { + udelay( 50 ); + delay++; + } while(( adapter->CSRAddress->mac.mii_mgmt_indicator.bits.busy ) && + ( delay < 100 )); + + + /************************************************************************** + If we hit the max delay, we could not write the register + *************************************************************************/ + if( delay == 100 ) + { + UINT16 TempValue; + + DBG_WARNING( et131x_dbginfo, "xcvrReg 0x%08x could not be written", + xcvrReg ); + DBG_WARNING( et131x_dbginfo, "status is 0x%08x\n", + adapter->CSRAddress->mac.mii_mgmt_indicator.value ); + DBG_WARNING( et131x_dbginfo, "command is 0x%08x\n", + adapter->CSRAddress->mac.mii_mgmt_cmd.value ); + + MiRead( adapter, xcvrAddr, xcvrReg, &TempValue ); + + status = -EIO; + } + + + /************************************************************************** + Stop the write operation + *************************************************************************/ + adapter->CSRAddress->mac.mii_mgmt_cmd.value = 0x0; + + + /************************************************************************** + set the registers we touched back to the state at which we entered + this function + *************************************************************************/ + adapter->CSRAddress->mac.mii_mgmt_addr.value = miiAddr.value; + adapter->CSRAddress->mac.mii_mgmt_cmd.value = miiCmd.value; + + + DBG_VERBOSE( et131x_dbginfo, " xcvr_addr = 0x%02x, " + "xcvr_reg = 0x%02x, " + "value = 0x%04x.\n", + xcvrAddr, xcvrReg, value ); + + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_xcvr_find + ****************************************************************************** + + DESCRIPTION : Used to find the PHY ID + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_xcvr_find( ET131X_ADAPTER *adapter ) +{ + int status = -ENODEV; + UINT8 xcvr_addr; + MI_IDR1_t idr1; + MI_IDR2_t idr2; + UINT32 xcvr_id; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_xcvr_find" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + We need to get xcvr id and address we just get the first one + *************************************************************************/ + for( xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++ ) + { + /********************************************************************** + Read the ID from the PHY + *********************************************************************/ + MiRead( adapter, xcvr_addr, (UINT8)FIELD_OFFSET(MI_REGS_t, idr1), &idr1.value ); + MiRead( adapter, xcvr_addr, (UINT8)FIELD_OFFSET(MI_REGS_t, idr2), &idr2.value ); + + xcvr_id = (UINT32)(( idr1.value << 16 ) | idr2.value ); + + if(( idr1.value != 0) && ( idr1.value != 0xffff )) + { + DBG_TRACE( et131x_dbginfo, "Xcvr addr: 0x%02x\tXcvr_id: 0x%08x\n", + xcvr_addr, xcvr_id ); + + adapter->Stats.xcvr_id = xcvr_id; + adapter->Stats.xcvr_addr = (UINT32)xcvr_addr; + + status = 0; + break; + } + } + + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_setphy_normal + ****************************************************************************** + + DESCRIPTION : Used by Power Management to force the PHY into 10 Base T + half-duplex mode, when going to D3 in WOL mode. Also + used during initialization to set the PHY for normal + operation. + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_setphy_normal( ET131X_ADAPTER *adapter ) +{ + int status; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_setphy_normal" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Make sure the PHY is powered up + *************************************************************************/ + ET1310_PhyPowerDown( adapter, 0 ); + status = et131x_xcvr_init( adapter ); + + + DBG_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_xcvr_init + ****************************************************************************** + + DESCRIPTION : Used to init the phy if we are setting it into force mode + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_xcvr_init( ET131X_ADAPTER *adapter ) +{ + int status = 0; + MI_IMR_t imr; + MI_ISR_t isr; + MI_LCR2_t lcr2; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_xcvr_init" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Zero out the adapter structure variable representing BMSR + *************************************************************************/ + adapter->Bmsr.value = 0; + + MiRead( adapter, (UINT8)adapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, isr ), &isr.value ); + + MiRead( adapter, (UINT8)adapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, imr ), &imr.value ); + + + /************************************************************************** + Set the link status interrupt only. Bad behavior when link status and + auto neg are set, we run into a nested interrupt problem + *************************************************************************/ + imr.bits.int_en = 0x1; + imr.bits.link_status = 0x1; + imr.bits.autoneg_status = 0x1; + + MiWrite( adapter, (UINT8)adapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, imr ), imr.value ); + + + /************************************************************************** + Set the LED behavior such that LED 1 indicates speed (off = 10Mbits, + blink = 100Mbits, on = 1000Mbits) and LED 2 indicates link and + activity (on for link, blink off for activity). + + NOTE: Some customizations have been added here for specific vendors; + The LED behavior is now determined by vendor data in the EEPROM. However, + the above description is the default. + *************************************************************************/ + if(( adapter->eepromData[1] & 0x4 ) == 0 ) + { + MiRead( adapter, (UINT8)adapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, lcr2 ), &lcr2.value ); + + if(( adapter->eepromData[1] & 0x8 ) == 0 ) + { + lcr2.bits.led_tx_rx = 0x3; + } + else + { + lcr2.bits.led_tx_rx = 0x4; + } + + lcr2.bits.led_link = 0xa; + + MiWrite( adapter, (UINT8)adapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, lcr2 ), lcr2.value ); + } + + + /************************************************************************** + Determine if we need to go into a force mode and set it + *************************************************************************/ + if( adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0 ) + { + if(( adapter->RegistryFlowControl == TxOnly ) || + ( adapter->RegistryFlowControl == Both )) + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_SET, 4, 11, NULL ); + } + else + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_CLEAR, 4, 11, NULL ); + } + + if( adapter->RegistryFlowControl == Both ) + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_SET, 4, 10, NULL ); + } + else + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_CLEAR, 4, 10, NULL ); + } + + + /********************************************************************** + Set the phy to autonegotiation + *********************************************************************/ + ET1310_PhyAutoNeg( adapter, TRUE ); + + + /* NOTE - Do we need this? */ + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_SET, 0, 9, NULL ); + + DBG_LEAVE( et131x_dbginfo ); + return status; + } + else + { + ET1310_PhyAutoNeg( adapter, FALSE ); + + /********************************************************************** + Set to the correct force mode. + *********************************************************************/ + if( adapter->AiForceDpx != 1 ) + { + if(( adapter->RegistryFlowControl == TxOnly ) || + ( adapter->RegistryFlowControl == Both )) + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_SET, 4, 11, NULL ); + } + else + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_CLEAR, 4, 11, NULL ); + } + + if( adapter->RegistryFlowControl == Both ) + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_SET, 4, 10, NULL ); + } + else + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_CLEAR, 4, 10, NULL ); + } + } + else + { + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_CLEAR, 4, 10, NULL ); + ET1310_PhyAccessMiBit( adapter, + TRUEPHY_BIT_CLEAR, 4, 11, NULL ); + } + + switch( adapter->AiForceSpeed ) + { + case 10: + if( adapter->AiForceDpx == 1 ) + { + TPAL_SetPhy10HalfDuplex( adapter ); + } + else if( adapter->AiForceDpx == 2 ) + { + TPAL_SetPhy10FullDuplex( adapter ); + } + else + { + TPAL_SetPhy10Force( adapter ); + } + break; + + case 100: + if( adapter->AiForceDpx == 1 ) + { + TPAL_SetPhy100HalfDuplex( adapter ); + } + else if( adapter->AiForceDpx == 2 ) + { + TPAL_SetPhy100FullDuplex( adapter ); + } + else + { + TPAL_SetPhy100Force( adapter ); + } + break; + + case 1000: + TPAL_SetPhy1000FullDuplex( adapter ); + break; + } + + + DBG_LEAVE( et131x_dbginfo ); + return status; + } +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_Mii_check + ****************************************************************************** + + DESCRIPTION: + used to + + PARAMETERS : + pAdapter - pointer to our adapter + bmsr - + + RETURNS : + Nothing + + *****************************************************************************/ +void et131x_Mii_check( ET131X_ADAPTER *pAdapter, + MI_BMSR_t bmsr, + MI_BMSR_t bmsr_ints ) +{ + UCHAR ucLinkStatus; + INT32 nAutoNegStatus; + INT32 nSpeed; + INT32 nDuplex; + INT32 nMdiMdix; + INT32 nMasterSlave; + INT32 nPolarity; + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_Mii_check" ); + DBG_ENTER( et131x_dbginfo ); + + + if( bmsr_ints.bits.link_status ) + { + if( bmsr.bits.link_status ) + { + pAdapter->PoMgmt.TransPhyComaModeOnBoot = 20; + + + /****************************************************************** + Update our state variables and indicate the connected state + *****************************************************************/ + spin_lock_irqsave( &pAdapter->Lock, lockflags ); + + pAdapter->MediaState = NETIF_STATUS_MEDIA_CONNECT; + MP_CLEAR_FLAG( pAdapter, fMP_ADAPTER_LINK_DETECTION ); + + spin_unlock_irqrestore( &pAdapter->Lock, lockflags ); + + if( pAdapter->RegistryPhyLoopbk == FALSE ) + { + /************************************************************** + Don't indicate state if we're in loopback mode + *************************************************************/ + netif_indicate_status( pAdapter->netdev, pAdapter->MediaState ); + } + } + else + { + DBG_WARNING( et131x_dbginfo, "Link down cable problem\n" ); + + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS ) + { + // NOTE - Is there a way to query this without TruePHY? + //if( TRU_QueryCoreType ( pAdapter->hTruePhy, 0 ) == EMI_TRUEPHY_A13O ) + { + UINT16 Register18; + + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x12, &Register18 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x12, Register18 | 0x4 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x10, Register18 | 0x8402 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x11, Register18 | 511 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x12, Register18 ); + } + } + + /****************************************************************** + For the first N seconds of life, we are in "link detection" + When we are in this state, we should only report "connected". + When the LinkDetection Timer expires, we can report + disconnected (handled in the LinkDetectionDPC). + *****************************************************************/ + if(( MP_IS_FLAG_CLEAR( pAdapter, fMP_ADAPTER_LINK_DETECTION )) || + ( pAdapter->MediaState == NETIF_STATUS_MEDIA_DISCONNECT )) + { + spin_lock_irqsave( &pAdapter->Lock, lockflags ); + pAdapter->MediaState = NETIF_STATUS_MEDIA_DISCONNECT; + spin_unlock_irqrestore( &pAdapter->Lock, lockflags ); + + /************************************************************** + Only indicate state if we're in loopback mode + *************************************************************/ + if( pAdapter->RegistryPhyLoopbk == FALSE ) + { + netif_indicate_status( pAdapter->netdev, pAdapter->MediaState ); + } + } + + pAdapter->uiLinkSpeed = 0; + pAdapter->uiDuplexMode = 0; + + + /****************************************************************** + Free the packets being actively sent & stopped + *****************************************************************/ + et131x_free_busy_send_packets( pAdapter ); + + + /****************************************************************** + Re-initialize the send structures + *****************************************************************/ + et131x_init_send( pAdapter ); + + + /****************************************************************** + Reset the RFD list and re-start RU + *****************************************************************/ + et131x_reset_recv( pAdapter ); + + + /****************************************************************** + Bring the device back to the state it was during init prior + to autonegotiation being complete. This way, when we get the + auto-neg complete interrupt, we can complete init by calling + ConfigMacREGS2. + *****************************************************************/ + et131x_soft_reset( pAdapter ); + + + /****************************************************************** + Setup ET1310 as per the documentation + *****************************************************************/ + et131x_adapter_setup( pAdapter ); + + + /****************************************************************** + Setup the PHY into coma mode until the cable is plugged back in + *****************************************************************/ + if( pAdapter->RegistryPhyComa == 1 ) + { + EnablePhyComa( pAdapter ); + } + } + } + + if( bmsr_ints.bits.auto_neg_complete || + (( pAdapter->AiForceDpx == 3 ) && ( bmsr_ints.bits.link_status ))) + { + if( bmsr.bits.auto_neg_complete || + ( pAdapter->AiForceDpx == 3 )) + { + ET1310_PhyLinkStatus( pAdapter, + &ucLinkStatus, + &nAutoNegStatus, + &nSpeed, + &nDuplex, + &nMdiMdix, + &nMasterSlave, + &nPolarity ); + + + pAdapter->uiLinkSpeed = nSpeed; + pAdapter->uiDuplexMode = nDuplex; + + DBG_TRACE( et131x_dbginfo, + "pAdapter->uiLinkSpeed 0x%04x, pAdapter->uiDuplex 0x%08x\n", + pAdapter->uiLinkSpeed, pAdapter->uiDuplexMode ); + + pAdapter->PoMgmt.TransPhyComaModeOnBoot = 20; + + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS ) + { + // NOTE - Is there a way to query this without TruePHY? + //if( TRU_QueryCoreType ( pAdapter->hTruePhy, 0 ) == EMI_TRUEPHY_A13O ) + { + UINT16 Register18; + + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x12, &Register18 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x12, Register18 | 0x4 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x10, Register18 | 0x8402 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x11, Register18 | 511 ); + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + 0x12, Register18 ); + } + } + + ConfigFlowControl( pAdapter ); + + + if(( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS ) && + ( pAdapter->RegistryJumboPacket > 2048 )) + + { + ET1310_PhyAndOrReg( pAdapter, 0x16, 0xcfff, 0x2000 ); + } + + SetRxDmaTimer( pAdapter ); + ConfigMACRegs2( pAdapter ); + } + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : TPAL_MiAccessRegs + ****************************************************************************** + + DESCRIPTION : Used to perform a single or series of MI Register + transactions on the specified PHY + + PARAMETERS : hPlatform - handle to platform resources + nPhyId - logical PHY ID (if >= 0) or + logical PHY group ID (if <0) + pbyAccessFlags - Pointer to a list of flags, which + specify the transaction type associated + with each register contained in the + 'pbyRegisters' array. Valid values: + TRUEPHY_READ + TRUEPHY_WRITE + TRUEPHY_MASK + If a logical PHY Group ID is specified + in 'nPhyId', the value of these flags + must be TRUEPHY_WRITE + pbyRegisters - Pointer to a list of MI registers + addressess (0-31), one of each register + specified by 'nRegCount' + pwData - Pointer to a buffer that contains the + data required by or resulting from each + transaction, the contents of which are + dependent upon the 'pbyAccessFlags' + parameter. Specifically: + + If 'pbyAccessFlags[i]' is TRUEPHY_READ, + the contents of the register specified + by 'pbyRegisters[i]' is read and stored + in 'pwData[i]'. + + If 'pbyAccessFlags[i]' is TRUEPHY_WRITE, + the contents of 'pwData[i]' is written + to the register specified by + 'pbyRegisters[i]'. + + If 'pbyAccessFlags[i]' is TRUEPHY_MASK, + the contents of the register specified + by 'pbyRegisters[i]' is read and stored + in 'pwData [i]', which is then + logically AND'ed with the contents of + 'pwAndMasks[i]' and logically OR'ed + with the contents of 'pwOrMasks[i]' + before it is written back to the + register specified by 'pbyRegisters[i]' + + This allows the calling function to + interleave a register read, logical + and/or, and write operation within a + single transaction. + + pwAndMasks - Pointer to buffer containing AND masks, + which is required if the corresponding + transaction type is TRUEPHY_MASK; + otherwise, this parameter is ignored. + pwOrMasks - Pointer to buffer containing OR masks, + which is required if the corresponding + transaction type is TRUEPHY_MASK; + otherwise, this parameter is ignored. + nRegCount - Specifies the number of register + transactions to be performed. + + RETURNS : TRUEPHY_SUCCESS + TRUEPHY_FAILURE + + REUSE INFORMATION : + + *****************************************************************************/ +INT32 TPAL_MiAccessRegs( TPAL_HANDLE hPlatform, + INT32 nPhyId, + PUCHAR pbyAccessFlags, + PUCHAR pbyRegisters, + PUINT16 pwData, + PUINT16 pwAndMasks, + PUINT16 pwOrMasks, + INT32 nRegCount ) +{ + INT32 nStatus = TRUEPHY_FAILURE; + INT32 index; + INT16 wTemp; + UINT8 xcvrAddr; + ET131X_ADAPTER *pAdapter = hPlatform; + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_MiAccessRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Validate Input parameters. We are not worried about nPhyId because we + can only access the one we control + *************************************************************************/ + if( pbyAccessFlags != NULL && pwData != NULL ) + { + /********************************************************************** + Convert nPhyId into a PHY physical address(nPhyAddress) + *********************************************************************/ + + + /********************************************************************** + Convert nPhyId into a MI bus address (nBusAddress). + + NOTE: This is only needed for platforms that support multiple MI + buses + *********************************************************************/ + + + /********************************************************************** + Get the xcvr addr for all transactions to go to + *********************************************************************/ + xcvrAddr = (UINT8)pAdapter->Stats.xcvr_addr; + + + /********************************************************************** + Go through all registers performing specific transaction indicated + in the corresponding pbyAccessFlags array. + *********************************************************************/ + for( index = 0; index < nRegCount; index++ ) + { + /****************************************************************** + Validate MI register + *****************************************************************/ + if( pbyRegisters[index] > 31 ) + { + break; + } + + + /****************************************************************** + Is this a read? + *****************************************************************/ + if( pbyAccessFlags[index] == TRUEPHY_READ ) + { + /************************************************************** + Group reads are not allowed + *************************************************************/ + if( nPhyId < 0 ) + { + break; + } + + + /************************************************************** + Make sure we acquire the spin lock + *************************************************************/ + spin_lock_irqsave( &pAdapter->PHYLock, lockflags ); + + + /************************************************************** + Let's perform the read operation + *************************************************************/ + MiRead( pAdapter, xcvrAddr, pbyRegisters[index], + (PUINT16)&pwData[index] ); + + spin_unlock_irqrestore( &pAdapter->PHYLock, lockflags ); + + } + else if( pbyAccessFlags[index] == TRUEPHY_WRITE ) + { + /************************************************************** + Make sure we acquire the spin lock + *************************************************************/ + spin_lock_irqsave( &pAdapter->PHYLock, lockflags ); + + + /************************************************************** + Let's perform the write operation + *************************************************************/ + MiWrite( pAdapter, xcvrAddr, pbyRegisters[index], + (UINT16)pwData[index] ); + + spin_unlock_irqrestore( &pAdapter->PHYLock, lockflags ); + } + else if( pbyAccessFlags[index] == TRUEPHY_MASK ) + { + /************************************************************** + Group masks are not allowed + *************************************************************/ + if( nPhyId < 0 ) + { + break; + } + + /************************************************************** + Pointer to AND and OR masks must not be NULL + *************************************************************/ + if(( pwOrMasks == NULL ) || ( pwAndMasks == NULL )) + { + break; + } + + /************************************************************** + Make sure we acquire the spin lock + *************************************************************/ + spin_lock_irqsave( &pAdapter->PHYLock, lockflags ); + + + /************************************************************** + Perform read + *************************************************************/ + MiRead( pAdapter, xcvrAddr, pbyRegisters[index], + (PUINT16)&pwData[index] ); + + + /************************************************************** + Perform and/or masks and write it back + *************************************************************/ + wTemp = (( pwData[index] & pwAndMasks[index] ) | + pwOrMasks[index] ); + + MiWrite( pAdapter, xcvrAddr, pbyRegisters[index], + (UINT16)wTemp ); + + spin_unlock_irqrestore( &pAdapter->PHYLock, lockflags ); + } + else + { + /************************************************************** + Invalid transaction type, just break out of the loop + *************************************************************/ + break; + } + }//end for loop + + /********************************************************************** + If we completed all the transactions, indicate success + *********************************************************************/ + if( index == nRegCount ) + { + nStatus = TRUEPHY_SUCCESS; + } + }//end if + + + DBG_LEAVE( et131x_dbginfo ); + return nStatus; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : TPAL_PlatformExit + ****************************************************************************** + + DESCRIPTION : Used to exit the TRUEPHY library which will de-allocate + any system resources allocated. + + PARAMETERS : hPlatform - handle to the platform resources + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ + +void TPAL_PlatformExit( TRUEPHY_OSAL_HANDLE hPlatform ) +{ + DBG_FUNC( "TPAL_PlatformExit" ); + DBG_ENTER( et131x_dbginfo ); + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + +/////////////////////////////////////////////////////////////////////////////// +//// OS Specific Functions //// +/////////////////////////////////////////////////////////////////////////////// +/****************************************************************************** + ROUTINE : TPAL_AllocMem + ****************************************************************************** + + DESCRIPTION : Used so the TRUEPHY library can allocate memory + + PARAMETERS : ulNumBytes - number of bytes to allocate + + RETURNS : pointer to allocated memory block on success, or + NULL on failure + + REUSE INFORMATION : + + *****************************************************************************/ +void * TPAL_AllocMem( TRUEPHY_OSAL_HANDLE hPlatform, u_long ulNumBytes ) +{ + void *pBuffer = NULL; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_AllocMem" ); + DBG_ENTER( et131x_dbginfo ); + + + pBuffer = kmalloc( ulNumBytes, GFP_ATOMIC ); + + + DBG_LEAVE( et131x_dbginfo ); + return pBuffer; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : TPAL_FreeMem + ****************************************************************************** + + DESCRIPTION : Used to free a previously allocated block of memory + + PARAMETERS : pMemBlock - the pointer to the buffer to free + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void TPAL_FreeMem( TRUEPHY_OSAL_HANDLE hPlatform, void *pMemBlock ) +{ + DBG_FUNC( "TPAL_FreeMem" ); + DBG_ENTER( et131x_dbginfo ); + + + kfree( pMemBlock ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_Sleep + ****************************************************************************** + + DESCRIPTION: + Used to delay execution for a specified number of milliseconds + + PARAMETERS : + ulMsec - Number of milliseconds to delay. This parameter can be zero + + RETURNS : + NONE + + *****************************************************************************/ +void TPAL_Sleep( TRUEPHY_OSAL_HANDLE hPlatform, u_long ulMsec ) +{ + DBG_FUNC( "TPAL_Sleep" ); + DBG_ENTER( et131x_dbginfo ); + + + mdelay( ulMsec ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_GetSystemUpTime + ****************************************************************************** + + DESCRIPTION: + Used to get the numberr of milliseconds that have elapsed since the + system was started + + PARAMETERS : + NONE + + RETURNS : + number of milliseconds since system was started + + *****************************************************************************/ +u_long TPAL_GetSystemUpTime( TRUEPHY_OSAL_HANDLE hPlatform ) +{ + UINT32 uptime; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_GetSystemUpTime" ); + DBG_ENTER( et131x_dbginfo ); + + + uptime = 10 * jiffies / HZ; + + + DBG_LEAVE( et131x_dbginfo ); + return uptime; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_GetLinkStatusInfo + ****************************************************************************** + + DESCRIPTION: + used to determine what link speed and duplex the phy is set to + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void TPAL_GetLinkStatusInfo( ET131X_ADAPTER *pAdapter ) +{ + UINT32 index = 0; + INT32 MdiMdix; + INT32 MasterSlave; + INT32 Polarity; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_GetLinkStatusInfo" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Get the link status information from the phy. Loop until the + autonegstatus is complete or link status is up. + + If looping for 50 uSec, break out, we have a problem + *************************************************************************/ + do + { + ET1310_PhyLinkStatus( pAdapter, + &pAdapter->ucLinkStatus, + &pAdapter->uiAutoNegStatus, + &pAdapter->uiLinkSpeed, + &pAdapter->uiDuplexMode, + &MdiMdix, + &MasterSlave, + &Polarity ); + + DBG_VERBOSE( et131x_dbginfo, + "uiAutoNegStatus 0x%08x ucLinkStatus 0x%04x\n " + "uiLinkSpeed 0x%04x, uiDuplexMode 0x%08x\n", + pAdapter->uiAutoNegStatus, + pAdapter->ucLinkStatus, + pAdapter->uiLinkSpeed, + pAdapter->uiDuplexMode ); + + udelay( 100 ); + index++; + + if( index == 10000 ) + { + /****************************************************************** + We hit our limit, we need to set a variable so during power + management we know to try 100/half + *****************************************************************/ + pAdapter->PoMgmt.Failed10Half = TRUE; + break; + } + } while( pAdapter->uiAutoNegStatus != TRUEPHY_ANEG_COMPLETE || + pAdapter->ucLinkStatus == 0 ); + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhy10HalfDuplex + ****************************************************************************** + + DESCRIPTION: + Used to force the phy into 10 Base T Half Duplex mode. Also sets the + MAC so it is syncd up properly + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + TRUEPHY_SUCCESS - if everything goes according to plan + TRUEPHY_FALIURE -if something goes wrong + + *****************************************************************************/ +INT32 TPAL_SetPhy10HalfDuplex( ET131X_ADAPTER *pAdapter ) +{ + INT32 returnValue = TRUEPHY_SUCCESS; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_SetPhy10HalfDuplex" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power down the PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + /************************************************************************** + First we need to turn off all other advertisement + *************************************************************************/ + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 1000 BaseT\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 100 BaseT " + "for forcing 10 BaseT Half Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Set our advertise values accordingly + *************************************************************************/ + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_HALF ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not set Advertise of 10 Half\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power up the PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + DBG_LEAVE( et131x_dbginfo ); + return returnValue ; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhy10FullDuplex + ****************************************************************************** + + DESCRIPTION: + Used to force the phy into 10 Base T Full Duplex mode. Also sets the + MAC so it is syncd up properly + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + TRUEPHY_SUCCESS - if everything goes according to plan + TRUEPHY_FALIURE -if somethign goes wrong during the procedures + + *****************************************************************************/ +INT32 TPAL_SetPhy10FullDuplex( ET131X_ADAPTER *pAdapter ) +{ + INT32 returnValue = TRUEPHY_SUCCESS; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_SetPhy10FullDuplex" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power down the PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + First we need to turn off all other advertisement + *************************************************************************/ + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 1000 BaseT " + "for Forcing 10 BaseT Full Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 100 BaseT " + "for Forcing 10 BaseT Full Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Set our advertise values accordingly + *************************************************************************/ + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_FULL ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not set Advertise of 10 Full\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power up the phy\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + DBG_LEAVE( et131x_dbginfo ); + return returnValue; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhy10Force + ****************************************************************************** + + DESCRIPTION: + Used to force the phy into 10 Base T Full Duplex mode WITHOUT using + autonegotiation. + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + + *****************************************************************************/ +void TPAL_SetPhy10Force( ET131X_ADAPTER *pAdapter ) +{ + DBG_FUNC( "TPAL_SetPhy10Force" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + + /************************************************************************** + Disable autoneg + *************************************************************************/ + ET1310_PhyAutoNeg( pAdapter, FALSE ); + + + /************************************************************************** + Disable all advertisement + *************************************************************************/ + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + + /************************************************************************** + Force 10 Mbps + *************************************************************************/ + ET1310_PhySpeedSelect( pAdapter, TRUEPHY_SPEED_10MBPS ); + + + /************************************************************************** + Force Full duplex + *************************************************************************/ + ET1310_PhyDuplexMode( pAdapter, TRUEPHY_DUPLEX_FULL ); + + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhy100HalfDuplex + ****************************************************************************** + + DESCRIPTION: + Used to force the phy into 100 Base T Half Duplex mode. Also sets the + MAC so it is syncd up properly + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + TRUEPHY_SUCCESS - if everything goes according to plan + TRUEPHY_FALIURE -if somethign goes wrong during the procedures + + *****************************************************************************/ +INT32 TPAL_SetPhy100HalfDuplex( ET131X_ADAPTER *pAdapter ) +{ + INT32 returnValue = TRUEPHY_SUCCESS; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_SetPhy100HalfDuplex" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + + DBG_ERROR( et131x_dbginfo, "Could not power down the PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return( returnValue ); + } + + + /************************************************************************** + first we need to turn off all other advertisement + *************************************************************************/ + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 1000 BaseT " + "for Forcing 100 BaseT Half Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 10 BaseT " + "for Forcing 100 BaseT Half Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Set our advertise values accordingly + *************************************************************************/ + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_HALF ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not set Advertise of 100 Half\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /* Set speed */ + ET1310_PhySpeedSelect( pAdapter, TRUEPHY_SPEED_100MBPS ); + + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power up the PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + DBG_LEAVE( et131x_dbginfo ); + return returnValue; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhy100FullDuplex + ****************************************************************************** + + DESCRIPTION: + Used to force the phy into 100 Base T Full Duplex mode. Also sets the + MAC so it is syncd up properly + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + TRUEPHY_SUCCESS - if everything goes according to plan + TRUEPHY_FALIURE -if somethign goes wrong during the procedures + + *****************************************************************************/ +INT32 TPAL_SetPhy100FullDuplex( ET131X_ADAPTER *pAdapter ) +{ + INT32 returnValue = TRUEPHY_SUCCESS; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_SetPhy100FullDuplex" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power down PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + First we need to turn off all other advertisement + *************************************************************************/ + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 1000 BaseT " + "for Forcing 100 BaseT Full Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 10 BaseT " + "for Forcing 100 BaseT Full Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Set our advertise values accordingly + *************************************************************************/ + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_FULL ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not set Advertise of 100 Full\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power up PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + DBG_LEAVE( et131x_dbginfo ); + return returnValue; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhy100Force + ****************************************************************************** + + DESCRIPTION: + Used to force the phy into 100 Base T Full Duplex mode WITHOUT using + autonegotiation. + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + + *****************************************************************************/ +void TPAL_SetPhy100Force( ET131X_ADAPTER *pAdapter ) +{ + DBG_FUNC( "TPAL_SetPhy100Force" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + + /************************************************************************** + Disable autoneg + *************************************************************************/ + ET1310_PhyAutoNeg( pAdapter, FALSE ); + + + /************************************************************************** + Disable all advertisement + *************************************************************************/ + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + + /************************************************************************** + Force 100 Mbps + *************************************************************************/ + ET1310_PhySpeedSelect( pAdapter, TRUEPHY_SPEED_100MBPS ); + + + /************************************************************************** + Force Full duplex + *************************************************************************/ + ET1310_PhyDuplexMode( pAdapter, TRUEPHY_DUPLEX_FULL ); + + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhy1000FullDuplex + ****************************************************************************** + + DESCRIPTION: + Used to force the phy into 1000 Base T Full Duplex mode. Also sets the + MAC so it is syncd up properly + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + TRUEPHY_SUCCESS - if everything goes according to plan + TRUEPHY_FALIURE -if somethign goes wrong during the procedures + + *****************************************************************************/ +INT32 TPAL_SetPhy1000FullDuplex( ET131X_ADAPTER *pAdapter ) +{ + INT32 returnValue = TRUEPHY_SUCCESS; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_SetPhy1000FullDuplex" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power down phy\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + first we need to turn off all other advertisement + *************************************************************************/ + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 100 BaseT " + "for Forcing 1000 BaseT Full Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not turn off advertisement of 10 BaseT " + "for Forcing 1000 BaseT Full Duplex\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + set our advertise values accordingly + *************************************************************************/ + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_FULL ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not set Advertise of 1000 Full\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power up PHY\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + DBG_LEAVE( et131x_dbginfo ); + return returnValue; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: TPAL_SetPhyAutoNeg + ****************************************************************************** + + DESCRIPTION: + Used to set phy to autonegotiation mode. + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + TRUEPHY_SUCCESS - if everything goes according to plan + TRUEPHY_FALIURE -if somethign goes wrong during the procedures + + *****************************************************************************/ +INT32 TPAL_SetPhyAutoNeg( ET131X_ADAPTER *pAdapter ) +{ + INT32 returnValue = TRUEPHY_SUCCESS; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "TPAL_SetPhyAutoNeg" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Power down PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 1 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power down phy\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Turn on advertisement of all capabilities + *************************************************************************/ + ET1310_PhyAdvertise10BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_BOTH ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not Turn on Advertisement of 10 BaseT " + "from Setting to Auto Negotiation\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + ET1310_PhyAdvertise100BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_BOTH ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not Turn on Advertisement of 100 BaseT " + "from Setting to Auto Negotiation\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + if( pAdapter->DeviceID != ET131X_PCI_DEVICE_ID_FAST ) + { + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_FULL ); + } + else + { + ET1310_PhyAdvertise1000BaseT( pAdapter, TRUEPHY_ADV_DUPLEX_NONE ); + } + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, + "Could not Turn on Advertisement of 1000 BaseT " + "from Setting to Auto Negotiation\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + /************************************************************************** + Make sure auto-neg is ON (it is disabled in FORCE modes) + *************************************************************************/ + ET1310_PhyAutoNeg( pAdapter, TRUE ); + + + /************************************************************************** + Power up PHY + *************************************************************************/ + ET1310_PhyPowerDown( pAdapter, 0 ); + + if( returnValue == TRUEPHY_FAILURE ) + { + /********************************************************************** + HANDLE ERROR HERE + *********************************************************************/ + DBG_ERROR( et131x_dbginfo, "Could not power up phy\n" ); + DBG_LEAVE( et131x_dbginfo ); + return returnValue; + } + + + DBG_LEAVE( et131x_dbginfo ); + return returnValue; +} +/*===========================================================================*/ + + + + +/****************************************************************************** +******************************************************************************* + + The routines which follow provide low-level access to the PHY, and are used + primarily by the routines above (although there are a few places elsewhere in + the driver where this level of access is required). + +******************************************************************************* +******************************************************************************/ + +static UINT16 ConfigPhy[25][2] = +{ + /* Reg Value Register */ + /* Addr */ + {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */ + {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */ + {0x880D, 0x0926}, /* AfeIfCreg4B10Msbs */ + + {0x880E, 0xB4D3}, /* AfeIfCreg4B1000Lsbs */ + {0x880F, 0xB4D3}, /* AfeIfCreg4B100Lsbs */ + {0x8810, 0xB4D3}, /* AfeIfCreg4B10Lsbs */ + + {0x8805, 0xB03E}, /* AfeIfCreg3B1000Msbs */ + {0x8806, 0xB03E}, /* AfeIfCreg3B100Msbs */ + {0x8807, 0xFF00}, /* AfeIfCreg3B10Msbs */ + + {0x8808, 0xE090}, /* AfeIfCreg3B1000Lsbs */ + {0x8809, 0xE110}, /* AfeIfCreg3B100Lsbs */ + {0x880A, 0x0000}, /* AfeIfCreg3B10Lsbs */ + + {0x300D, 1 }, /* DisableNorm */ + + {0x280C, 0x0180}, /* LinkHoldEnd */ + + {0x1C21, 0x0002}, /* AlphaM */ + + {0x3821, 6 }, /* FfeLkgTx0 */ + {0x381D, 1 }, /* FfeLkg1g4 */ + {0x381E, 1 }, /* FfeLkg1g5 */ + {0x381F, 1 }, /* FfeLkg1g6 */ + {0x3820, 1 }, /* FfeLkg1g7 */ + + {0x8402, 0x01F0}, /* Btinact */ + {0x800E, 20 }, /* LftrainTime */ + {0x800F, 24 }, /* DvguardTime */ + {0x8010, 46 }, /* IdlguardTime */ + + {0, 0 } + +}; +// +// condensed version of the phy initialization routine +// +void ET1310_PhyInit( ET131X_ADAPTER *pAdapter ) +{ + UINT16 usData, usIndex; + + + if( pAdapter == NULL ) + { + return; + } + + + // get the identity (again ?) + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_ID_1, &usData ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_ID_2, &usData ); + + // what does this do/achieve ? + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, &usData ); // should read 0002 + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, 0x0006 ); + + // read modem register 0402, should I do something with the return data ? + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_INDEX_REG, 0x0402 ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_DATA_REG, &usData ); + + // what does this do/achieve ? + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, 0x0002 ); + + // get the identity (again ?) + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_ID_1, &usData ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_ID_2, &usData ); + + // what does this achieve ? + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, &usData ); // should read 0002 + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, 0x0006 ); + + // read modem register 0402, should I do something with the return data ? + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_INDEX_REG, 0x0402 ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_DATA_REG, &usData ); + + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, 0x0002 ); + + // what does this achieve (should return 0x1040) + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, &usData ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, &usData ); // should read 0002 + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, 0x1840 ); + + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, 0x0007 ); + + // here the writing of the array starts.... + usIndex = 0; + while( ConfigPhy[usIndex][0] != 0x0000 ) + { + // write value + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_INDEX_REG, ConfigPhy[usIndex][0] ); + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_DATA_REG, ConfigPhy[usIndex][1] ); + + // read it back + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_INDEX_REG, ConfigPhy[usIndex][0] ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_DATA_REG, &usData ); + + // do a check on the value read back ? + usIndex++; + } + // here the writing of the array ends... + + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, &usData ); // 0x1840 + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, &usData ); // should read 0007 + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, 0x1040 ); + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_MPHY_CONTROL_REG, 0x0002 ); + + return; + +} + + + + +void ET1310_PhyReset( ET131X_ADAPTER *pAdapter ) +{ + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, 0x8000 ); + return; +} + + + + +void ET1310_PhyPowerDown( ET131X_ADAPTER *pAdapter, BOOL_t down ) +{ + UINT16 usData; + + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, &usData ); + + if( down == FALSE ) + { + // Power UP + usData &= ~0x0800; + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, usData ); + } + else + { + // Power DOWN + usData |= 0x0800; + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, usData ); + } + + return; +} + + +void ET1310_PhyAutoNeg( ET131X_ADAPTER *pAdapter, BOOL_t enable ) +{ + UINT16 usData; + + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, &usData ); + + if( enable == TRUE ) + { + // Autonegotiation ON + usData |= 0x1000; + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, usData ); + } + else + { + // Autonegotiation OFF + usData &= ~0x1000; + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, usData ); + } + + return; +} + +void ET1310_PhyDuplexMode( ET131X_ADAPTER *pAdapter, UINT16 duplex ) +{ + UINT16 usData; + + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, &usData ); + + if( duplex == TRUEPHY_DUPLEX_FULL ) + { + // Set Full Duplex + usData |= 0x100; + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, usData ); + } + else + { + // Set Half Duplex + usData &= ~0x100; + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, usData ); + } + + return; +} + + +void ET1310_PhySpeedSelect( ET131X_ADAPTER *pAdapter, UINT16 speed ) +{ + UINT16 usData; + + // Read the PHY control register + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, &usData ); + + // Clear all Speed settings (Bits 6, 13) + usData &= ~0x2040; + + // Reset the speed bits based on user selection + switch( speed ) + { + case TRUEPHY_SPEED_10MBPS: + // Bits already cleared above, do nothing + break; + + case TRUEPHY_SPEED_100MBPS: + // 100M == Set bit 13 + usData |= 0x2000; + break; + + case TRUEPHY_SPEED_1000MBPS: + default: + usData |= 0x0040; + break; + } + + // Write back the new speed + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, usData ); + + return; +} + + +void ET1310_PhyAdvertise1000BaseT( ET131X_ADAPTER *pAdapter, UINT16 duplex ) +{ + UINT16 usData; + + // Read the PHY 1000 Base-T Control Register + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_1000_CONTROL, &usData ); + + // Clear Bits 8,9 + usData &= ~0x0300; + + switch( duplex ) + { + case TRUEPHY_ADV_DUPLEX_NONE: + // Duplex already cleared, do nothing + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + // Set Bit 9 + usData |= 0x0200; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + // Set Bit 8 + usData |= 0x0100; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + usData |= 0x0300; + break; + } + + // Write back advertisement + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_1000_CONTROL, usData ); + + return; +} + + +void ET1310_PhyAdvertise100BaseT( ET131X_ADAPTER *pAdapter, UINT16 duplex ) +{ + UINT16 usData; + + // Read the Autonegotiation Register (10/100) + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_AUTO_ADVERTISEMENT, &usData ); + + // Clear bits 7,8 + usData &= ~0x0180; + + switch( duplex ) + { + case TRUEPHY_ADV_DUPLEX_NONE: + // Duplex already cleared, do nothing + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + // Set Bit 8 + usData |= 0x0100; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + // Set Bit 7 + usData |= 0x0080; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + // Set Bits 7,8 + usData |= 0x0180; + break; + } + + // Write back advertisement + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_AUTO_ADVERTISEMENT, usData ); + + return; +} + + +void ET1310_PhyAdvertise10BaseT( ET131X_ADAPTER *pAdapter, UINT16 duplex ) +{ + UINT16 usData; + + // Read the Autonegotiation Register (10/100) + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_AUTO_ADVERTISEMENT, &usData ); + + // Clear bits 5,6 + usData &= ~0x0060; + + switch( duplex ) + { + case TRUEPHY_ADV_DUPLEX_NONE: + // Duplex already cleared, do nothing + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + // Set Bit 6 + usData |= 0x0040; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + // Set Bit 5 + usData |= 0x0020; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + // Set Bits 5,6 + usData |= 0x0060; + break; + } + + // Write back advertisement + MiWrite( pAdapter, pAdapter->Stats.xcvr_addr, PHY_AUTO_ADVERTISEMENT, usData ); + + return; +} + + + + +void ET1310_PhyLinkStatus( ET131X_ADAPTER *pAdapter, + UCHAR *ucLinkStatus, + UINT32 *uiAutoNeg, + UINT32 *uiLinkSpeed, + UINT32 *uiDuplexMode, + UINT32 *uiMdiMdix, + UINT32 *uiMasterSlave, + UINT32 *uiPolarity ) +{ + UINT16 usMiStatus = 0; + UINT16 us1000BaseT = 0; + UINT16 usVmiPhyStatus = 0; + UINT16 usControl = 0; + + + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_STATUS, &usMiStatus ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_1000_STATUS, &us1000BaseT ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_PHY_STATUS, &usVmiPhyStatus ); + MiRead( pAdapter, pAdapter->Stats.xcvr_addr, PHY_CONTROL, &usControl ); + + if( ucLinkStatus ) + { + *ucLinkStatus = (unsigned char)(( usVmiPhyStatus & 0x0040 ) ? 1 : 0 ); + } + + if( uiAutoNeg ) + { + *uiAutoNeg = ( usControl & 0x1000 ) ? (( usVmiPhyStatus & 0x0020 ) ? TRUEPHY_ANEG_COMPLETE : TRUEPHY_ANEG_NOT_COMPLETE ) : TRUEPHY_ANEG_DISABLED; + } + + if( uiLinkSpeed ) + { + *uiLinkSpeed = ( usVmiPhyStatus & 0x0300 ) >> 8; + } + + if( uiDuplexMode ) + { + *uiDuplexMode = ( usVmiPhyStatus & 0x0080 ) >> 7; + } + + if( uiMdiMdix ) + { + /* NOTE: Need to complete this */ + *uiMdiMdix = 0; + } + + if( uiMasterSlave ) + { + *uiMasterSlave = ( us1000BaseT & 0x4000 ) ? TRUEPHY_CFG_MASTER : TRUEPHY_CFG_SLAVE; + } + + if( uiPolarity ) + { + *uiPolarity = ( usVmiPhyStatus & 0x0400 ) ? TRUEPHY_POLARITY_INVERTED : TRUEPHY_POLARITY_NORMAL; + } + + return; +} + + +void ET1310_PhyAndOrReg( ET131X_ADAPTER *pAdapter, + UINT16 regnum, + UINT16 andMask, + UINT16 orMask ) +{ + UINT16 reg; + + // Read the requested register + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + regnum, ® ); + + // Apply the AND mask + reg &= andMask; + + // Apply the OR mask + reg |= orMask; + + // Write the value back to the register + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + regnum, reg ); + + return; +} + + +void ET1310_PhyAccessMiBit( ET131X_ADAPTER *pAdapter, + UINT16 action, + UINT16 regnum, + UINT16 bitnum, + UINT8 *value ) +{ + UINT16 reg; + UINT16 mask = 0; + + // Create a mask to isolate the requested bit + mask = 0x0001 << bitnum; + + // Read the requested register + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + regnum, ® ); + + switch( action ) + { + case TRUEPHY_BIT_READ: + if( value != NULL ) + { + *value = ( reg & mask ) >> bitnum; + } + + break; + + case TRUEPHY_BIT_SET: + reg |= mask; + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, regnum, reg ); + break; + + case TRUEPHY_BIT_CLEAR: + reg &= ~mask; + MiWrite( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, regnum, reg ); + break; + + default: + break; + } + + return; +} + --- linux-2.6.27.orig/ubuntu/et131x/BOM +++ linux-2.6.27/ubuntu/et131x/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://sourceforge.net/project/platformdownload.php?group_id=179406 +Current Version: 1.2.3-3 --- linux-2.6.27.orig/ubuntu/et131x/et131x_isr.h +++ linux-2.6.27/ubuntu/et131x/et131x_isr.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_isr.h - Defines, structs, enums, prototypes, etc. pertaining to the + * ISR processing code. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:13 $ + $Revision: 1.3 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_ISR_H__ +#define __ET131X_ISR_H__ + + + + +/****************************************************************************** + Function Prototypes + *****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +void et131x_isr( int irq, void *dev_id, struct pt_regs *regs ); +#else +irqreturn_t et131x_isr( int irq, void *dev_id ); +#endif + +void et131x_isr_handler( struct work_struct *work ); + + +#endif /* __ET131X_ISR_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_main.c +++ linux-2.6.27/ubuntu/et131x/et131x_main.c @@ -0,0 +1,258 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_main.c - This file contains the driver's main Linux entry points. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:13 $ + $Revision: 1.6 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" + + + + +/****************************************************************************** + Modinfo parameters (filled out using defines from et131x_version.h) + *****************************************************************************/ +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_INFO ); +MODULE_LICENSE( DRIVER_LICENSE ); + + + + +/****************************************************************************** + Module Parameters and related data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG + +static u32 et131x_debug_level = DBG_LVL; +static u32 et131x_debug_flags = DBG_DEFAULTS; + +module_param( et131x_debug_level, uint, 0 ); +module_param( et131x_debug_flags, uint, 0 ); + +MODULE_PARM_DESC( et131x_debug_level, + "Level of debugging desired (0-7)" ); + +dbg_info_t et131x_info = { DRIVER_NAME_EXT, 0, 0 }; +dbg_info_t *et131x_dbginfo = &et131x_info; + +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + ROUTINE : et131x_init_module + ****************************************************************************** + + DESCRIPTION : The "main" entry point called on driver initialization + + PARAMETERS : N/A + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_init_module( void ) +{ + int result; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_init_module" ); + + +#ifdef ET131X_DBG + /************************************************************************** + Set the level of debug messages displayed using the module parameter + *************************************************************************/ + et131x_dbginfo->dbgFlags = et131x_debug_flags; + + switch( et131x_debug_level ) + { + case 7: + et131x_dbginfo->dbgFlags |= ( DBG_RX_ON | DBG_TX_ON ); + + case 6: + et131x_dbginfo->dbgFlags |= DBG_PARAM_ON; + + case 5: + et131x_dbginfo->dbgFlags |= DBG_VERBOSE_ON; + + case 4: + et131x_dbginfo->dbgFlags |= DBG_TRACE_ON; + + case 3: + et131x_dbginfo->dbgFlags |= DBG_NOTICE_ON; + + case 2: + case 1: + case 0: + default: + break; + } +#endif /* ET131X_DBG */ + + DBG_ENTER( et131x_dbginfo ); + DBG_PRINT( "%s\n", DRIVER_INFO ); + + + result = et131x_pci_register( ); + + + DBG_LEAVE( et131x_dbginfo ); + return result; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_cleanup_module + ****************************************************************************** + + DESCRIPTION : The entry point called on driver cleanup + + PARAMETERS : N/A + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_cleanup_module( void ) +{ + DBG_FUNC( "et131x_cleanup_module" ); + DBG_ENTER( et131x_dbginfo ); + + + et131x_pci_unregister( ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + These macros map the driver-specific init_module() and cleanup_module() + routines so they can be called by the kernel. + *****************************************************************************/ +module_init(et131x_init_module); +module_exit(et131x_cleanup_module); --- linux-2.6.27.orig/ubuntu/et131x/ET1310_phy.h +++ linux-2.6.27/ubuntu/et131x/ET1310_phy.h @@ -0,0 +1,1228 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_phy.h - Defines, structs, enums, prototypes, etc. pertaining to the + * PHY. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/18 22:18:33 $ + $Revision: 1.10 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef _ET1310_PHY_H_ +#define _ET1310_PHY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/****************************************************************************** + INCLUDES + *****************************************************************************/ +#include "ET1310_common.h" + + + + +#define TRUEPHY_SUCCESS 0 +#define TRUEPHY_FAILURE 1 +typedef void *TRUEPHY_HANDLE; +typedef void *TRUEPHY_PLATFORM_HANDLE; +typedef void *TRUEPHY_OSAL_HANDLE; + + + + +/****************************************************************************** + CONSTANTS for PHY Register + *****************************************************************************/ +/* MI Register Addresses */ +#define MI_CONTROL_REG 0 +#define MI_STATUS_REG 1 +#define MI_PHY_IDENTIFIER_1_REG 2 +#define MI_PHY_IDENTIFIER_2_REG 3 +#define MI_AUTONEG_ADVERTISEMENT_REG 4 +#define MI_AUTONEG_LINK_PARTNER_ABILITY_REG 5 +#define MI_AUTONEG_EXPANSION_REG 6 +#define MI_AUTONEG_NEXT_PAGE_TRANSMIT_REG 7 +#define MI_LINK_PARTNER_NEXT_PAGE_REG 8 +#define MI_1000BASET_CONTROL_REG 9 +#define MI_1000BASET_STATUS_REG 10 +#define MI_RESERVED11_REG 11 +#define MI_RESERVED12_REG 12 +#define MI_RESERVED13_REG 13 +#define MI_RESERVED14_REG 14 +#define MI_EXTENDED_STATUS_REG 15 + +/* VMI Register Addresses */ +#define VMI_RESERVED16_REG 16 +#define VMI_RESERVED17_REG 17 +#define VMI_RESERVED18_REG 18 +#define VMI_LOOPBACK_CONTROL_REG 19 +#define VMI_RESERVED20_REG 20 +#define VMI_MI_CONTROL_REG 21 +#define VMI_PHY_CONFIGURATION_REG 22 +#define VMI_PHY_CONTROL_REG 23 +#define VMI_INTERRUPT_MASK_REG 24 +#define VMI_INTERRUPT_STATUS_REG 25 +#define VMI_PHY_STATUS_REG 26 +#define VMI_LED_CONTROL_1_REG 27 +#define VMI_LED_CONTROL_2_REG 28 +#define VMI_RESERVED29_REG 29 +#define VMI_RESERVED30_REG 30 +#define VMI_RESERVED31_REG 31 + + + + +/****************************************************************************** + PHY Register Mapping(MI) Management Interface Regs + *****************************************************************************/ +typedef struct _MI_REGS_t +{ + UCHAR bmcr; // Basic mode control reg(Reg 0x00) + UCHAR bmsr; // Basic mode status reg(Reg 0x01) + UCHAR idr1; // Phy identifier reg 1(Reg 0x02) + UCHAR idr2; // Phy identifier reg 2(Reg 0x03) + UCHAR anar; // Auto-Negotiation advertisement(Reg 0x04) + UCHAR anlpar; // Auto-Negotiation link Partner Ability(Reg 0x05) + UCHAR aner; // Auto-Negotiation expansion reg(Reg 0x06) + UCHAR annptr; // Auto-Negotiation next page transmit reg(Reg 0x07) + UCHAR lpnpr; // link partner next page reg(Reg 0x08) + UCHAR gcr; // Gigabit basic mode control reg(Reg 0x09) + UCHAR gsr; // Gigabit basic mode status reg(Reg 0x0A) + UCHAR mi_res1[4]; // Future use by MI working group(Reg 0x0B - 0x0E) + UCHAR esr; // Extended status reg(Reg 0x0F) + UCHAR mi_res2[3]; // Future use by MI working group(Reg 0x10 - 0x12) + UCHAR loop_ctl; // Loopback Control Reg(Reg 0x13) + UCHAR mi_res3; // Future use by MI working group(Reg 0x14) + UCHAR mcr; // MI Control Reg(Reg 0x15) + UCHAR pcr; // Configuration Reg(Reg 0x16) + UCHAR phy_ctl; // PHY Control Reg(Reg 0x17) + UCHAR imr; // Interrupt Mask Reg(Reg 0x18) + UCHAR isr; // Interrupt Status Reg(Reg 0x19) + UCHAR psr; // PHY Status Reg(Reg 0x1A) + UCHAR lcr1; // LED Control 1 Reg(Reg 0x1B) + UCHAR lcr2; // LED Control 2 Reg(Reg 0x1C) + UCHAR mi_res4[3]; // Future use by MI working group(Reg 0x1D - 0x1F) +} +MI_REGS_t, *PMI_REGS_t; + + + + +/****************************************************************************** + MI Register 0: Basic mode control register + *****************************************************************************/ +typedef union _MI_BMCR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 reset:1; //bit 15 + UINT16 loopback:1; //bit 14 + UINT16 speed_sel:1; //bit 13 + UINT16 enable_autoneg:1; //bit 12 + UINT16 power_down:1; //bit 11 + UINT16 isolate:1; //bit 10 + UINT16 restart_autoneg:1; //bit 9 + UINT16 duplex_mode:1; //bit 8 + UINT16 col_test:1; //bit 7 + UINT16 speed_1000_sel:1; //bit 6 + UINT16 res1:6; //bits 0-5 + #else + UINT16 res1:6; //bits 0-5 + UINT16 speed_1000_sel:1; //bit 6 + UINT16 col_test:1; //bit 7 + UINT16 duplex_mode:1; //bit 8 + UINT16 restart_autoneg:1; //bit 9 + UINT16 isolate:1; //bit 10 + UINT16 power_down:1; //bit 11 + UINT16 enable_autoneg:1; //bit 12 + UINT16 speed_sel:1; //bit 13 + UINT16 loopback:1; //bit 14 + UINT16 reset:1; //bit 15 + #endif + } bits; +} +MI_BMCR_t, *PMI_BMCR_t; + + + + +/****************************************************************************** + MI Register 1: Basic mode status register + *****************************************************************************/ +typedef union _MI_BMSR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 link_100T4:1; //bit 15 + UINT16 link_100fdx:1; //bit 14 + UINT16 link_100hdx:1; //bit 13 + UINT16 link_10fdx:1; //bit 12 + UINT16 link_10hdx:1; //bit 11 + UINT16 link_100T2fdx:1; //bit 10 + UINT16 link_100T2hdx:1; //bit 9 + UINT16 extend_status:1; //bit 8 + UINT16 res1:1; //bit 7 + UINT16 preamble_supress:1; //bit 6 + UINT16 auto_neg_complete:1; //bit 5 + UINT16 remote_fault:1; //bit 4 + UINT16 auto_neg_able:1; //bit 3 + UINT16 link_status:1; //bit 2 + UINT16 jabber_detect:1; //bit 1 + UINT16 ext_cap:1; //bit 0 + #else + UINT16 ext_cap:1; //bit 0 + UINT16 jabber_detect:1; //bit 1 + UINT16 link_status:1; //bit 2 + UINT16 auto_neg_able:1; //bit 3 + UINT16 remote_fault:1; //bit 4 + UINT16 auto_neg_complete:1; //bit 5 + UINT16 preamble_supress:1; //bit 6 + UINT16 res1:1; //bit 7 + UINT16 extend_status:1; //bit 8 + UINT16 link_100T2hdx:1; //bit 9 + UINT16 link_100T2fdx:1; //bit 10 + UINT16 link_10hdx:1; //bit 11 + UINT16 link_10fdx:1; //bit 12 + UINT16 link_100hdx:1; //bit 13 + UINT16 link_100fdx:1; //bit 14 + UINT16 link_100T4:1; //bit 15 + #endif + } bits; +} +MI_BMSR_t, *PMI_BMSR_t; + + + + +/****************************************************************************** + MI Register 2: Physical Identifier 1 + *****************************************************************************/ +typedef union _MI_IDR1_t +{ + UINT16 value; + struct + { + UINT16 ieee_address:16; //0x0282 default(bits 0-15) + } bits; +} +MI_IDR1_t, *PMI_IDR1_t; + + + + +/****************************************************************************** + MI Register 3: Physical Identifier 2 + *****************************************************************************/ +typedef union _MI_IDR2_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 ieee_address:6; //111100 default(bits 10-15) + UINT16 model_no:6; //000001 default(bits 4-9) + UINT16 rev_no:4; //0010 default(bits 0-3) + #else + UINT16 rev_no:4; //0010 default(bits 0-3) + UINT16 model_no:6; //000001 default(bits 4-9) + UINT16 ieee_address:6; //111100 default(bits 10-15) + #endif + } bits; +} +MI_IDR2_t, *PMI_IDR2_t; + + + + +/****************************************************************************** + MI Register 4: Auto-negotiation advertisement register + *****************************************************************************/ +typedef union _MI_ANAR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 np_indication:1; //bit 15 + UINT16 res2:1; //bit 14 + UINT16 remote_fault:1; //bit 13 + UINT16 res1:1; //bit 12 + UINT16 cap_asmpause:1; //bit 11 + UINT16 cap_pause:1; //bit 10 + UINT16 cap_100T4:1; //bit 9 + UINT16 cap_100fdx:1; //bit 8 + UINT16 cap_100hdx:1; //bit 7 + UINT16 cap_10fdx:1; //bit 6 + UINT16 cap_10hdx:1; //bit 5 + UINT16 selector:5; //bits 0-4 + #else + UINT16 selector:5; //bits 0-4 + UINT16 cap_10hdx:1; //bit 5 + UINT16 cap_10fdx:1; //bit 6 + UINT16 cap_100hdx:1; //bit 7 + UINT16 cap_100fdx:1; //bit 8 + UINT16 cap_100T4:1; //bit 9 + UINT16 cap_pause:1; //bit 10 + UINT16 cap_asmpause:1; //bit 11 + UINT16 res1:1; //bit 12 + UINT16 remote_fault:1; //bit 13 + UINT16 res2:1; //bit 14 + UINT16 np_indication:1; //bit 15 + #endif + } bits; +} +MI_ANAR_t, *PMI_ANAR_t; + + + + +/****************************************************************************** + MI Register 5: Auto-negotiation link partner advertisement register + *****************************************************************************/ +typedef struct _MI_ANLPAR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 np_indication:1; //bit 15 + UINT16 acknowledge:1; //bit 14 + UINT16 remote_fault:1; //bit 13 + UINT16 res1:1; //bit 12 + UINT16 cap_asmpause:1; //bit 11 + UINT16 cap_pause:1; //bit 10 + UINT16 cap_100T4:1; //bit 9 + UINT16 cap_100fdx:1; //bit 8 + UINT16 cap_100hdx:1; //bit 7 + UINT16 cap_10fdx:1; //bit 6 + UINT16 cap_10hdx:1; //bit 5 + UINT16 selector:5; //bits 0-4 + #else + UINT16 selector:5; //bits 0-4 + UINT16 cap_10hdx:1; //bit 5 + UINT16 cap_10fdx:1; //bit 6 + UINT16 cap_100hdx:1; //bit 7 + UINT16 cap_100fdx:1; //bit 8 + UINT16 cap_100T4:1; //bit 9 + UINT16 cap_pause:1; //bit 10 + UINT16 cap_asmpause:1; //bit 11 + UINT16 res1:1; //bit 12 + UINT16 remote_fault:1; //bit 13 + UINT16 acknowledge:1; //bit 14 + UINT16 np_indication:1; //bit 15 + #endif + } bits; +} +MI_ANLPAR_t, *PMI_ANLPAR_t; + + + + +/****************************************************************************** + MI Register 6: Auto-negotiation expansion register + *****************************************************************************/ +typedef union _MI_ANER_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res:11; //bits 5-15 + UINT16 pdf:1; //bit 4 + UINT16 lp_np_able:1; //bit 3 + UINT16 np_able:1; //bit 2 + UINT16 page_rx:1; //bit 1 + UINT16 lp_an_able:1; //bit 0 + #else + UINT16 lp_an_able:1; //bit 0 + UINT16 page_rx:1; //bit 1 + UINT16 np_able:1; //bit 2 + UINT16 lp_np_able:1; //bit 3 + UINT16 pdf:1; //bit 4 + UINT16 res:11; //bits 5-15 + #endif + } bits; +} +MI_ANER_t, *PMI_ANER_t; + + + + +/****************************************************************************** + MI Register 7: Auto-negotiation next page transmit reg(0x07) + *****************************************************************************/ +typedef union _MI_ANNPTR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 np:1; //bit 15 + UINT16 res1:1; //bit 14 + UINT16 msg_page:1; //bit 13 + UINT16 ack2:1; //bit 12 + UINT16 toggle:1; //bit 11 + UINT16 msg:11; //bits 0-10 + #else + UINT16 msg:11; //bits 0-10 + UINT16 toggle:1; //bit 11 + UINT16 ack2:1; //bit 12 + UINT16 msg_page:1; //bit 13 + UINT16 res1:1; //bit 14 + UINT16 np:1; //bit 15 + #endif + } bits; +} +MI_ANNPTR_t, *PMI_ANNPTR_t; + + + + +/****************************************************************************** + MI Register 8: Link Partner Next Page Reg(0x08) + *****************************************************************************/ +typedef union _MI_LPNPR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 np:1; //bit 15 + UINT16 ack:1; //bit 14 + UINT16 msg_page:1; //bit 13 + UINT16 ack2:1; //bit 12 + UINT16 toggle:1; //bit 11 + UINT16 msg:11; //bits 0-10 + #else + UINT16 msg:11; //bits 0-10 + UINT16 toggle:1; //bit 11 + UINT16 ack2:1; //bit 12 + UINT16 msg_page:1; //bit 13 + UINT16 ack:1; //bit 14 + UINT16 np:1; //bit 15 + #endif + } bits; +} +MI_LPNPR_t, *PMI_LPNPR_t; + + + + +/****************************************************************************** + MI Register 9: 1000BaseT Control Reg(0x09) + *****************************************************************************/ +typedef union _MI_GCR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 test_mode:3; //bits 13-15 + UINT16 ms_config_en:1; //bit 12 + UINT16 ms_value:1; //bit 11 + UINT16 port_type:1; //bit 10 + UINT16 link_1000fdx:1; //bit 9 + UINT16 link_1000hdx:1; //bit 8 + UINT16 res:8; //bit 0-7 + #else + UINT16 res:8; //bit 0-7 + UINT16 link_1000hdx:1; //bit 8 + UINT16 link_1000fdx:1; //bit 9 + UINT16 port_type:1; //bit 10 + UINT16 ms_value:1; //bit 11 + UINT16 ms_config_en:1; //bit 12 + UINT16 test_mode:3; //bits 13-15 + #endif + } bits; +} +MI_GCR_t, *PMI_GCR_t; + + + + +/****************************************************************************** + MI Register 10: 1000BaseT Status Reg(0x0A) + *****************************************************************************/ +typedef union _MI_GSR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 ms_config_fault:1; //bit 15 + UINT16 ms_resolve:1; //bit 14 + UINT16 local_rx_status:1; //bit 13 + UINT16 remote_rx_status:1; //bit 12 + UINT16 link_1000fdx:1; //bit 11 + UINT16 link_1000hdx:1; //bit 10 + UINT16 res:2; //bits 8-9 + UINT16 idle_err_cnt:8; //bits 0-7 + #else + UINT16 idle_err_cnt:8; //bits 0-7 + UINT16 res:2; //bits 8-9 + UINT16 link_1000hdx:1; //bit 10 + UINT16 link_1000fdx:1; //bit 11 + UINT16 remote_rx_status:1; //bit 12 + UINT16 local_rx_status:1; //bit 13 + UINT16 ms_resolve:1; //bit 14 + UINT16 ms_config_fault:1; //bit 15 + #endif + } bits; +} +MI_GSR_t, *PMI_GSR_t; + + + + +/****************************************************************************** + MI Register 11 - 14: Reserved Regs(0x0B - 0x0E) + *****************************************************************************/ +typedef union _MI_RES_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res15:1; //bit 15 + UINT16 res14:1; //bit 14 + UINT16 res13:1; //bit 13 + UINT16 res12:1; //bit 12 + UINT16 res11:1; //bit 11 + UINT16 res10:1; //bit 10 + UINT16 res9:1; //bit 9 + UINT16 res8:1; //bit 8 + UINT16 res7:1; //bit 7 + UINT16 res6:1; //bit 6 + UINT16 res5:1; //bit 5 + UINT16 res4:1; //bit 4 + UINT16 res3:1; //bit 3 + UINT16 res2:1; //bit 2 + UINT16 res1:1; //bit 1 + UINT16 res0:1; //bit 0 + #else + UINT16 res0:1; //bit 0 + UINT16 res1:1; //bit 1 + UINT16 res2:1; //bit 2 + UINT16 res3:1; //bit 3 + UINT16 res4:1; //bit 4 + UINT16 res5:1; //bit 5 + UINT16 res6:1; //bit 6 + UINT16 res7:1; //bit 7 + UINT16 res8:1; //bit 8 + UINT16 res9:1; //bit 9 + UINT16 res10:1; //bit 10 + UINT16 res11:1; //bit 11 + UINT16 res12:1; //bit 12 + UINT16 res13:1; //bit 13 + UINT16 res14:1; //bit 14 + UINT16 res15:1; //bit 15 + #endif + } bits; +} +MI_RES_t, *PMI_RES_t; + + + + +/****************************************************************************** + MI Register 15: Extended status Reg(0x0F) + *****************************************************************************/ +typedef union _MI_ESR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 link_1000Xfdx:1; //bit 15 + UINT16 link_1000Xhdx:1; //bit 14 + UINT16 link_1000fdx:1; //bit 13 + UINT16 link_1000hdx:1; //bit 12 + UINT16 res:12; //bit 0-11 + #else + UINT16 res:12; //bit 0-11 + UINT16 link_1000hdx:1; //bit 12 + UINT16 link_1000fdx:1; //bit 13 + UINT16 link_1000Xhdx:1; //bit 14 + UINT16 link_1000Xfdx:1; //bit 15 + #endif + } bits; +} +MI_ESR_t, *PMI_ESR_t; + + + + +/****************************************************************************** + MI Register 16 - 18: Reserved Reg(0x10-0x12) + *****************************************************************************/ + + + + +/****************************************************************************** + MI Register 19: Loopback Control Reg(0x13) + *****************************************************************************/ +typedef union _MI_LCR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 mii_en:1; //bit 15 + UINT16 pcs_en:1; //bit 14 + UINT16 pmd_en:1; //bit 13 + UINT16 all_digital_en:1; //bit 12 + UINT16 replica_en:1; //bit 11 + UINT16 line_driver_en:1; //bit 10 + UINT16 res:10; //bit 0-9 + #else + UINT16 res:10; //bit 0-9 + UINT16 line_driver_en:1; //bit 10 + UINT16 replica_en:1; //bit 11 + UINT16 all_digital_en:1; //bit 12 + UINT16 pmd_en:1; //bit 13 + UINT16 pcs_en:1; //bit 14 + UINT16 mii_en:1; //bit 15 + #endif + } bits; +} +MI_LCR_t, *PMI_LCR_t; + + + + +/****************************************************************************** + MI Register 20: Reserved Reg(0x14) + *****************************************************************************/ + + + + +/****************************************************************************** + MI Register 21: Management Interface Control Reg(0x15) + *****************************************************************************/ +typedef union _MI_MICR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res1:5; //bits 11-15 + UINT16 mi_error_count:7; //bits 4-10 + UINT16 res2:1; //bit 3 + UINT16 ignore_10g_fr:1; //bit 2 + UINT16 res3:1; //bit 1 + UINT16 preamble_supress_en:1; //bit 0 + #else + UINT16 preamble_supress_en:1; //bit 0 + UINT16 res3:1; //bit 1 + UINT16 ignore_10g_fr:1; //bit 2 + UINT16 res2:1; //bit 3 + UINT16 mi_error_count:7; //bits 4-10 + UINT16 res1:5; //bits 11-15 + #endif + } bits; +} +MI_MICR_t, *PMI_MICR_t; + + + + +/****************************************************************************** + MI Register 22: PHY Configuration Reg(0x16) + *****************************************************************************/ +typedef union _MI_PHY_CONFIG_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 crs_tx_en:1; //bit 15 + UINT16 res1:1; //bit 14 + UINT16 tx_fifo_depth:2; //bits 12-13 + UINT16 speed_downshift:2; //bits 10-11 + UINT16 pbi_detect:1; //bit 9 + UINT16 tbi_rate:1; //bit 8 + UINT16 alternate_np:1; //bit 7 + UINT16 group_mdio_en:1; //bit 6 + UINT16 tx_clock_en:1; //bit 5 + UINT16 sys_clock_en:1; //bit 4 + UINT16 res2:1; //bit 3 + UINT16 mac_if_mode:3; //bits 0-2 + #else + UINT16 mac_if_mode:3; //bits 0-2 + UINT16 res2:1; //bit 3 + UINT16 sys_clock_en:1; //bit 4 + UINT16 tx_clock_en:1; //bit 5 + UINT16 group_mdio_en:1; //bit 6 + UINT16 alternate_np:1; //bit 7 + UINT16 tbi_rate:1; //bit 8 + UINT16 pbi_detect:1; //bit 9 + UINT16 speed_downshift:2; //bits 10-11 + UINT16 tx_fifo_depth:2; //bits 12-13 + UINT16 res1:1; //bit 14 + UINT16 crs_tx_en:1; //bit 15 + #endif + } bits; +} +MI_PHY_CONFIG_t, *PMI_PHY_CONFIG_t; + + + + +/****************************************************************************** + MI Register 23: PHY CONTROL Reg(0x17) + *****************************************************************************/ +typedef union _MI_PHY_CONTROL_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res1:1; //bit 15 + UINT16 tdr_en:1; //bit 14 + UINT16 res2:1; //bit 13 + UINT16 downshift_attempts:2; //bits 11-12 + UINT16 res3:5; //bit 6-10 + UINT16 jabber_10baseT:1; //bit 5 + UINT16 sqe_10baseT:1; //bit 4 + UINT16 tp_loopback_10baseT:1; //bit 3 + UINT16 preamble_gen_en:1; //bit 2 + UINT16 res4:1; //bit 1 + UINT16 force_int:1; //bit 0 + #else + UINT16 force_int:1; //bit 0 + UINT16 res4:1; //bit 1 + UINT16 preamble_gen_en:1; //bit 2 + UINT16 tp_loopback_10baseT:1; //bit 3 + UINT16 sqe_10baseT:1; //bit 4 + UINT16 jabber_10baseT:1; //bit 5 + UINT16 res3:5; //bit 6-10 + UINT16 downshift_attempts:2; //bits 11-12 + UINT16 res2:1; //bit 13 + UINT16 tdr_en:1; //bit 14 + UINT16 res1:1; //bit 15 + #endif + } bits; +} +MI_PHY_CONTROL_t, *PMI_PHY_CONTROL_t; + + + + +/****************************************************************************** + MI Register 24: Interrupt Mask Reg(0x18) + *****************************************************************************/ +typedef union _MI_IMR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res1:6; //bits 10-15 + UINT16 mdio_sync_lost:1; //bit 9 + UINT16 autoneg_status:1; //bit 8 + UINT16 hi_bit_err:1; //bit 7 + UINT16 np_rx:1; //bit 6 + UINT16 err_counter_full:1; //bit 5 + UINT16 fifo_over_underflow:1; //bit 4 + UINT16 rx_status:1; //bit 3 + UINT16 link_status:1; //bit 2 + UINT16 automatic_speed:1; //bit 1 + UINT16 int_en:1; //bit 0 + #else + UINT16 int_en:1; //bit 0 + UINT16 automatic_speed:1; //bit 1 + UINT16 link_status:1; //bit 2 + UINT16 rx_status:1; //bit 3 + UINT16 fifo_over_underflow:1; //bit 4 + UINT16 err_counter_full:1; //bit 5 + UINT16 np_rx:1; //bit 6 + UINT16 hi_bit_err:1; //bit 7 + UINT16 autoneg_status:1; //bit 8 + UINT16 mdio_sync_lost:1; //bit 9 + UINT16 res1:6; //bits 10-15 + #endif + } bits; +} +MI_IMR_t, *PMI_IMR_t; + + + + +/****************************************************************************** + MI Register 25: Interrupt Status Reg(0x19) + *****************************************************************************/ +typedef union _MI_ISR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res1:6; //bits 10-15 + UINT16 mdio_sync_lost:1; //bit 9 + UINT16 autoneg_status:1; //bit 8 + UINT16 hi_bit_err:1; //bit 7 + UINT16 np_rx:1; //bit 6 + UINT16 err_counter_full:1; //bit 5 + UINT16 fifo_over_underflow:1; //bit 4 + UINT16 rx_status:1; //bit 3 + UINT16 link_status:1; //bit 2 + UINT16 automatic_speed:1; //bit 1 + UINT16 int_en:1; //bit 0 + #else + UINT16 int_en:1; //bit 0 + UINT16 automatic_speed:1; //bit 1 + UINT16 link_status:1; //bit 2 + UINT16 rx_status:1; //bit 3 + UINT16 fifo_over_underflow:1; //bit 4 + UINT16 err_counter_full:1; //bit 5 + UINT16 np_rx:1; //bit 6 + UINT16 hi_bit_err:1; //bit 7 + UINT16 autoneg_status:1; //bit 8 + UINT16 mdio_sync_lost:1; //bit 9 + UINT16 res1:6; //bits 10-15 + #endif + } bits; +} +MI_ISR_t, *PMI_ISR_t; + + + + +/****************************************************************************** + MI Register 26: PHY Status Reg(0x1A) + *****************************************************************************/ +typedef union _MI_PSR_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res1:1; //bit 15 + UINT16 autoneg_fault:2; //bit 13-14 + UINT16 autoneg_status:1; //bit 12 + UINT16 mdi_x_status:1; //bit 11 + UINT16 polarity_status:1; //bit 10 + UINT16 speed_status:2; //bits 8-9 + UINT16 duplex_status:1; //bit 7 + UINT16 link_status:1; //bit 6 + UINT16 tx_status:1; //bit 5 + UINT16 rx_status:1; //bit 4 + UINT16 collision_status:1; //bit 3 + UINT16 autoneg_en:1; //bit 2 + UINT16 pause_en:1; //bit 1 + UINT16 asymmetric_dir:1; //bit 0 + #else + UINT16 asymmetric_dir:1; //bit 0 + UINT16 pause_en:1; //bit 1 + UINT16 autoneg_en:1; //bit 2 + UINT16 collision_status:1; //bit 3 + UINT16 rx_status:1; //bit 4 + UINT16 tx_status:1; //bit 5 + UINT16 link_status:1; //bit 6 + UINT16 duplex_status:1; //bit 7 + UINT16 speed_status:2; //bits 8-9 + UINT16 polarity_status:1; //bit 10 + UINT16 mdi_x_status:1; //bit 11 + UINT16 autoneg_status:1; //bit 12 + UINT16 autoneg_fault:2; //bit 13-14 + UINT16 res1:1; //bit 15 + #endif + } bits; +} +MI_PSR_t, *PMI_PSR_t; + + + + +/****************************************************************************** + MI Register 27: LED Control Reg 1(0x1B) + *****************************************************************************/ +typedef union _MI_LCR1_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 res1:2; //bits 14-15 + UINT16 led_dup_indicate:2; //bits 12-13 + UINT16 led_10baseT:2; //bits 10-11 + UINT16 led_collision:2; //bits 8-9 + UINT16 res2:2; //bits 6-7 + UINT16 res3:2; //bits 4-5 + UINT16 pulse_dur:2; //bits 2-3 + UINT16 pulse_stretch1:1; //bit 1 + UINT16 pulse_stretch0:1; //bit 0 + #else + UINT16 pulse_stretch0:1; //bit 0 + UINT16 pulse_stretch1:1; //bit 1 + UINT16 pulse_dur:2; //bits 2-3 + UINT16 res3:2; //bits 4-5 + UINT16 res2:2; //bits 6-7 + UINT16 led_collision:2; //bits 8-9 + UINT16 led_10baseT:2; //bits 10-11 + UINT16 led_dup_indicate:2; //bits 12-13 + UINT16 res1:2; //bits 14-15 + #endif + } bits; +} +MI_LCR1_t, *PMI_LCR1_t; + + + + +/****************************************************************************** + MI Register 28: LED Control Reg 2(0x1C) + *****************************************************************************/ +typedef union _MI_LCR2_t +{ + UINT16 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT16 led_link:4; //bits 12-15 + UINT16 led_tx_rx:4; //bits 8-11 + UINT16 led_100BaseTX:4; //bits 4-7 + UINT16 led_1000BaseT:4; //bits 0-3 + #else + UINT16 led_1000BaseT:4; //bits 0-3 + UINT16 led_100BaseTX:4; //bits 4-7 + UINT16 led_tx_rx:4; //bits 8-11 + UINT16 led_link:4; //bits 12-15 + #endif + } bits; +} +MI_LCR2_t, *PMI_LCR2_t; + + + + +/****************************************************************************** + MI Register 29 - 31: Reserved Reg(0x1D - 0x1E) + *****************************************************************************/ + + + + +/****************************************************************************** + TruePHY headers + *****************************************************************************/ +typedef struct _TRUEPHY_ACCESS_MI_REGS_ +{ + TRUEPHY_HANDLE hTruePhy; + INT32 nPhyId; + UCHAR bReadWrite; + PUCHAR pbyRegs; + PUCHAR pwData; + INT32 nRegCount; +} +TRUEPHY_ACCESS_MI_REGS, *PTRUEPHY_ACCESS_MI_REGS; + + + + +/****************************************************************************** + TruePHY headers + *****************************************************************************/ +typedef struct _TAG_TPAL_ACCESS_MI_REGS_ +{ + UINT32 nPhyId; + UCHAR bReadWrite; + UINT32 nRegCount; + UINT16 Data[4096]; + UCHAR Regs[4096]; +} TPAL_ACCESS_MI_REGS, *PTPAL_ACCESS_MI_REGS; + + + + +/****************************************************************************** + Required TruePHY PROTOTYPES + *****************************************************************************/ +/****************************************************************************** + TYPE DEFINITIONS + *****************************************************************************/ +typedef TRUEPHY_HANDLE TPAL_HANDLE; + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + +/////////////////////////////////////////////////////////////////////////////// +//// TruePHY Platform Specific Functions //// +/////////////////////////////////////////////////////////////////////////////// +//TRUEPHY_HANDLE TPAL_PlatformInit( void * pPlatformInfo, +// PTRUEPHY_PLATFORM_FUNCTIONS pPlatFunctions ); + +INT32 TPAL_MiAccessRegs( TPAL_HANDLE hPlatform, + INT32 nPhyId, + PUCHAR pbyAccessFlags, + PUCHAR pbyRegisters, + PUINT16 pwData, + PUINT16 pwAndMasks, + PUINT16 pwOrMasks, + INT32 nRegCount ); + +void TPAL_PlatformExit( TRUEPHY_PLATFORM_HANDLE hPlatform ); + + + + +/////////////////////////////////////////////////////////////////////////////// +//// OS Specific Functions //// +/////////////////////////////////////////////////////////////////////////////// +void *TPAL_AllocMem( TRUEPHY_PLATFORM_HANDLE hPlatform, u_long ulNumBytes ); +void TPAL_FreeMem( TRUEPHY_PLATFORM_HANDLE hPlatform, void *pMemBlock ); +void TPAL_Sleep( TRUEPHY_PLATFORM_HANDLE hPlatform, u_long ulMsec ); +u_long TPAL_GetSystemUpTime( TRUEPHY_PLATFORM_HANDLE hPlatform ); +void TPAL_GetLinkStatusInfo( struct et131x_adapter *adapter ); + +INT32 TPAL_SetPhy10HalfDuplex( struct et131x_adapter *adapter ); +INT32 TPAL_SetPhy10FullDuplex( struct et131x_adapter *adapter ); +void TPAL_SetPhy10Force( struct et131x_adapter * pAdapter ); +INT32 TPAL_SetPhy100HalfDuplex( struct et131x_adapter *adapter ); +INT32 TPAL_SetPhy100FullDuplex( struct et131x_adapter *adapter ); +void TPAL_SetPhy100Force( struct et131x_adapter * pAdapter ); +INT32 TPAL_SetPhy1000FullDuplex( struct et131x_adapter *adapter); +INT32 TPAL_SetPhyAutoNeg( struct et131x_adapter *adapter ); + + + + +/****************************************************************************** + PROTOTYPES for ET1310_phy.c + *****************************************************************************/ +int et131x_xcvr_find( struct et131x_adapter *adapter ); + +int et131x_setphy_normal( struct et131x_adapter *adapter ); +INT32 et131x_xcvr_init( struct et131x_adapter *adapter ); + +INT32 MiRead( struct et131x_adapter *adapter, + UINT8 xcvrAddr, + UINT8 xcvrReg, + UINT16 *value ); + +INT32 MiWrite( struct et131x_adapter *adapter, + UINT8 xcvrAddr, + UINT8 xcvReg, + UINT16 value ); + +void et131x_Mii_check( struct et131x_adapter *pAdapter, + MI_BMSR_t bmsr, + MI_BMSR_t bmsr_ints ); + + + + +/****************************************************************************** + This last is not strictly required (the driver could call the TPAL + version instead), but this sets the adapter up correctly, and calls the + access routine indirectly. This protects the driver from changes in TPAL. + *****************************************************************************/ +void SetPhy_10BaseTHalfDuplex( struct et131x_adapter *adapter ); + + + + +/****************************************************************************** + Defines for PHY access routines + *****************************************************************************/ +// Define bit operation flags +#define TRUEPHY_BIT_CLEAR 0 +#define TRUEPHY_BIT_SET 1 +#define TRUEPHY_BIT_READ 2 + +// Define read/write operation flags +#ifndef TRUEPHY_READ +#define TRUEPHY_READ 0 +#define TRUEPHY_WRITE 1 +#define TRUEPHY_MASK 2 +#endif + +// Define speeds +#define TRUEPHY_SPEED_10MBPS 0 +#define TRUEPHY_SPEED_100MBPS 1 +#define TRUEPHY_SPEED_1000MBPS 2 + +// Define duplex modes +#define TRUEPHY_DUPLEX_HALF 0 +#define TRUEPHY_DUPLEX_FULL 1 + +// Define master/slave configuration values +#define TRUEPHY_CFG_SLAVE 0 +#define TRUEPHY_CFG_MASTER 1 + +// Define MDI/MDI-X settings +#define TRUEPHY_MDI 0 +#define TRUEPHY_MDIX 1 +#define TRUEPHY_AUTO_MDI_MDIX 2 + +// Define 10Base-T link polarities +#define TRUEPHY_POLARITY_NORMAL 0 +#define TRUEPHY_POLARITY_INVERTED 1 + +// Define auto-negotiation results +#define TRUEPHY_ANEG_NOT_COMPLETE 0 +#define TRUEPHY_ANEG_COMPLETE 1 +#define TRUEPHY_ANEG_DISABLED 2 + +/* Define duplex advertisment flags */ +#define TRUEPHY_ADV_DUPLEX_NONE 0x00 +#define TRUEPHY_ADV_DUPLEX_FULL 0x01 +#define TRUEPHY_ADV_DUPLEX_HALF 0x02 +#define TRUEPHY_ADV_DUPLEX_BOTH \ + (TRUEPHY_ADV_DUPLEX_FULL | TRUEPHY_ADV_DUPLEX_HALF) + +#define PHY_CONTROL 0x00 //#define TRU_MI_CONTROL_REGISTER 0 +#define PHY_STATUS 0x01 //#define TRU_MI_STATUS_REGISTER 1 +#define PHY_ID_1 0x02 //#define TRU_MI_PHY_IDENTIFIER_1_REGISTER 2 +#define PHY_ID_2 0x03 //#define TRU_MI_PHY_IDENTIFIER_2_REGISTER 3 +#define PHY_AUTO_ADVERTISEMENT 0x04 //#define TRU_MI_ADVERTISEMENT_REGISTER 4 +#define PHY_AUTO_LINK_PARTNER 0x05 //#define TRU_MI_LINK_PARTNER_ABILITY_REGISTER 5 +#define PHY_AUTO_EXPANSION 0x06 //#define TRU_MI_EXPANSION_REGISTER 6 +#define PHY_AUTO_NEXT_PAGE_TX 0x07 //#define TRU_MI_NEXT_PAGE_TRANSMIT_REGISTER 7 +#define PHY_LINK_PARTNER_NEXT_PAGE 0x08 //#define TRU_MI_LINK_PARTNER_NEXT_PAGE_REGISTER 8 +#define PHY_1000_CONTROL 0x09 //#define TRU_MI_1000BASET_CONTROL_REGISTER 9 +#define PHY_1000_STATUS 0x0A //#define TRU_MI_1000BASET_STATUS_REGISTER 10 + + +#define PHY_EXTENDED_STATUS 0x0F //#define TRU_MI_EXTENDED_STATUS_REGISTER 15 + +// some defines for modem registers that seem to be 'reserved' +#define PHY_INDEX_REG 0x10 +#define PHY_DATA_REG 0x11 + +#define PHY_MPHY_CONTROL_REG 0x12 //#define TRU_VMI_MPHY_CONTROL_REGISTER 18 + +#define PHY_LOOPBACK_CONTROL 0x13 //#define TRU_VMI_LOOPBACK_CONTROL_1_REGISTER 19 + //#define TRU_VMI_LOOPBACK_CONTROL_2_REGISTER 20 +#define PHY_REGISTER_MGMT_CONTROL 0x15 //#define TRU_VMI_MI_SEQ_CONTROL_REGISTER 21 +#define PHY_CONFIG 0x16 //#define TRU_VMI_CONFIGURATION_REGISTER 22 +#define PHY_PHY_CONTROL 0x17 //#define TRU_VMI_PHY_CONTROL_REGISTER 23 +#define PHY_INTERRUPT_MASK 0x18 //#define TRU_VMI_INTERRUPT_MASK_REGISTER 24 +#define PHY_INTERRUPT_STATUS 0x19 //#define TRU_VMI_INTERRUPT_STATUS_REGISTER 25 +#define PHY_PHY_STATUS 0x1A //#define TRU_VMI_PHY_STATUS_REGISTER 26 +#define PHY_LED_1 0x1B //#define TRU_VMI_LED_CONTROL_1_REGISTER 27 +#define PHY_LED_2 0x1C //#define TRU_VMI_LED_CONTROL_2_REGISTER 28 + //#define TRU_VMI_LINK_CONTROL_REGISTER 29 + //#define TRU_VMI_TIMING_CONTROL_REGISTER + + + + +/****************************************************************************** + Prototypes for PHY access routines + *****************************************************************************/ +void ET1310_PhyInit( struct et131x_adapter *pAdapter ); +void ET1310_PhyReset( struct et131x_adapter *pAdapter ); +void ET1310_PhyPowerDown( struct et131x_adapter *pAdapter, BOOL_t down ); +void ET1310_PhyAutoNeg( struct et131x_adapter *pAdapter, BOOL_t enable ); +void ET1310_PhyDuplexMode( struct et131x_adapter *pAdapter, UINT16 duplex ); +void ET1310_PhySpeedSelect( struct et131x_adapter *pAdapter, UINT16 speed ); +void ET1310_PhyAdvertise1000BaseT( struct et131x_adapter *pAdapter, UINT16 duplex ); +void ET1310_PhyAdvertise100BaseT( struct et131x_adapter *pAdapter, UINT16 duplex ); +void ET1310_PhyAdvertise10BaseT( struct et131x_adapter *pAdapter, UINT16 duplex ); +void ET1310_PhyLinkStatus( struct et131x_adapter *pAdapter, + UCHAR *ucLinkStatus, + UINT32 *uiAutoNeg, + UINT32 *uiLinkSpeed, + UINT32 *uiDuplexMode, + UINT32 *uiMdiMdix, + UINT32 *uiMasterSlave, + UINT32 *uiPolarity ); +void ET1310_PhyAndOrReg( struct et131x_adapter *pAdapter, + UINT16 regnum, + UINT16 andMask, + UINT16 orMask ); +void ET1310_PhyAccessMiBit( struct et131x_adapter *pAdapter, + UINT16 action, + UINT16 regnum, + UINT16 bitnum, + UINT8 *value ); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _ET1310_PHY_H_ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_pm.h +++ linux-2.6.27/ubuntu/et131x/ET1310_pm.h @@ -0,0 +1,216 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_pm.h - Defines, structs, enums, prototypes, etc. pertaining to power + * management. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:11 $ + $Revision: 1.5 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef _ET1310_PM_H_ +#define _ET1310_PM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/****************************************************************************** + INCLUDES + *****************************************************************************/ +#include "ET1310_common.h" + + + + +/****************************************************************************** + CONSTANTS FOR POWER MANAGEMENT + *****************************************************************************/ +#define MAX_WOL_PACKET_SIZE 0x80 +#define MAX_WOL_MASK_SIZE ( MAX_WOL_PACKET_SIZE / 8 ) +#define NUM_WOL_PATTERNS 0x5 +#define CRC16_POLY 0x1021 + + + + +/****************************************************************************** + Definition of NDIS_DEVICE_POWER_STATE + *****************************************************************************/ +typedef enum +{ + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3 +} NDIS_DEVICE_POWER_STATE; + + + + +/****************************************************************************** + Structure for Power Management Info + *****************************************************************************/ +typedef struct _MP_PM_CONFIG_SPACE_INFO_t +{ + UCHAR capId; + UCHAR nextItemPtr; + UINT16 pmcr; + UINT16 pmcsr; + UCHAR pmscr_bse; + UCHAR pm_data_regs; +} +MP_PM_CONFIG_SPACE_INFO_t, *pMP_PM_CONFIG_SPACE_INFO_t; + + + + +typedef struct _MP_POWER_MGMT +{ + /************************************************************************** + variable putting the phy into coma mode when boot up with no cable + plugged in after 5 seconds + *************************************************************************/ + UCHAR TransPhyComaModeOnBoot; + + + /************************************************************************** + Array holding the five CRC values that the device is currently using + for WOL. This will be queried when a pattern is to be removed. + *************************************************************************/ + UINT32 localWolAndCrc0; + UINT16 WOLPatternList[ NUM_WOL_PATTERNS ]; + UCHAR WOLMaskList[ NUM_WOL_PATTERNS ][ MAX_WOL_MASK_SIZE ]; + UINT32 WOLMaskSize[ NUM_WOL_PATTERNS ]; + + + /************************************************************************** + IP address + *************************************************************************/ + union + { + UINT32 u32; + UCHAR u8[4]; + } IPAddress; + + + /************************************************************************** + Current Power state of the adapter. + *************************************************************************/ + NDIS_DEVICE_POWER_STATE PowerState; + BOOL_t WOLState; + BOOL_t WOLEnabled; + BOOL_t Failed10Half; + BOOL_t bFailedStateTransition; + + /************************************************************************** + Next two used to save power information at power down. + This information will be used during power up to set up parts of Power + Management in JAGCore + *************************************************************************/ + UINT32 tx_en; + UINT32 rx_en; + UINT16 PowerDownSpeed; + UCHAR PowerDownDuplex; + + MP_PM_CONFIG_SPACE_INFO_t pmConfigRegs; +} MP_POWER_MGMT, *PMP_POWER_MGMT; + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + ( IS THERE A WAY TO DO THIS WITH A TYPEDEF??? ) + *****************************************************************************/ +struct et131x_adapter; + + + + +/****************************************************************************** + PROTOTYPES for ET1310_pm.c + *****************************************************************************/ +UINT16 CalculateCCITCRC16( PUCHAR Pattern, PUCHAR Mask, UINT32 MaskSize ); + +void EnablePhyComa( struct et131x_adapter *pAdapter ); + +void DisablePhyComa( struct et131x_adapter *pAdapter ); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _ET1310_PM_H_ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_eeprom.c +++ linux-2.6.27/ubuntu/et131x/ET1310_eeprom.c @@ -0,0 +1,710 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_eeprom.c - Code used to access the device's EEPROM + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/18 22:18:33 $ + $Revision: 1.6 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" +#include "ET1310_eeprom.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" +#include "et131x_isr.h" + +#include "ET1310_tx.h" + + + + +/****************************************************************************** + EEPROM Defines + *****************************************************************************/ +/* LBCIF Register Groups (addressed via 32-bit offsets) */ +#define LBCIF_DWORD0_GROUP_OFFSET 0xAC +#define LBCIF_DWORD1_GROUP_OFFSET 0xB0 + +/* LBCIF Registers (addressed via 8-bit offsets) */ +#define LBCIF_ADDRESS_REGISTER_OFFSET 0xAC +#define LBCIF_DATA_REGISTER_OFFSET 0xB0 +#define LBCIF_CONTROL_REGISTER_OFFSET 0xB1 +#define LBCIF_STATUS_REGISTER_OFFSET 0xB2 + +/* LBCIF Control Register Bits */ +#define LBCIF_CONTROL_SEQUENTIAL_READ 0x01 +#define LBCIF_CONTROL_PAGE_WRITE 0x02 +#define LBCIF_CONTROL_UNUSED1 0x04 +#define LBCIF_CONTROL_EEPROM_RELOAD 0x08 +#define LBCIF_CONTROL_UNUSED2 0x10 +#define LBCIF_CONTROL_TWO_BYTE_ADDR 0x20 +#define LBCIF_CONTROL_I2C_WRITE 0x40 +#define LBCIF_CONTROL_LBCIF_ENABLE 0x80 + +/* LBCIF Status Register Bits */ +#define LBCIF_STATUS_PHY_QUEUE_AVAIL 0x01 +#define LBCIF_STATUS_I2C_IDLE 0x02 +#define LBCIF_STATUS_ACK_ERROR 0x04 +#define LBCIF_STATUS_GENERAL_ERROR 0x08 +#define LBCIF_STATUS_UNUSED 0x30 +#define LBCIF_STATUS_CHECKSUM_ERROR 0x40 +#define LBCIF_STATUS_EEPROM_PRESENT 0x80 + +/* Miscellaneous Constraints */ +#define MAX_NUM_REGISTER_POLLS 1000 +#define MAX_NUM_WRITE_RETRIES 2 + + + + +/****************************************************************************** + Define macros that allow individual register values to be extracted from a + DWORD1 register grouping + *****************************************************************************/ +#define EXTRACT_DATA_REGISTER(x) (UCHAR)(x & 0xFF) +#define EXTRACT_STATUS_REGISTER(x) (UCHAR)((x >> 16) & 0xFF) +#define EXTRACT_CONTROL_REG(x) (UCHAR)((x >> 8) & 0xFF) + + + + +static INT32 LbcifWriteByte( ET131X_ADAPTER *pAdapter, UINT32 unOffset, UCHAR bByte ) +{ + return EEPROM_access( pAdapter, WRITE, unOffset, 8, &bByte ); +} + + +static INT32 LbcifReadDword( ET131X_ADAPTER *pAdapter, UINT32 unOffset, PUINT32 punData ) +{ + return EEPROM_access( pAdapter, READ, unOffset, 32, punData ); +} + + +static INT32 LbcifWriteDword( ET131X_ADAPTER *pAdapter,UINT32 unOffset, UINT32 unData ) +{ + return EEPROM_access( pAdapter, WRITE, unOffset, 32, &unData ); +} + + + + +/****************************************************************************** + ROUTINE : EepromWriteByte + ****************************************************************************** + + DESCRIPTION : Write a byte to the ET1310's EEPROM + + PARAMETERS : pAdapter - pointer to our private adapter structure + unAddress - the address to write + bData - the value to write + unEepronId - the ID of the EEPROM + unAddressingMode - how the EEPROM is to be accessed + + RETURNS : SUCCESS or FAILURE + + REUSE INFORMATION : + + *****************************************************************************/ +INT32 EepromWriteByte( ET131X_ADAPTER *pAdapter, UINT32 unAddress, UCHAR bData, + UINT32 unEepromId, UINT32 unAddressingMode ) +{ + INT32 nIndex; + INT32 nRetries; + INT32 nError = FALSE; + INT32 nI2CWriteActive = 0; + INT32 nWriteSuccessful = 0; + UCHAR bControl; + UCHAR bStatus = 0; + UINT32 unDword1 = 0; + + UINT32 unData = 0; + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + The following excerpt is from "Serial EEPROM HW Design Specification" + Version 0.92 (9/20/2004): + + Single Byte Writes + + For an EEPROM, an I2C single byte write is defined as a START + condition followed by the device address, EEPROM address, one byte + of data and a STOP condition. The STOP condition will trigger the + EEPROM's internally timed write cycle to the nonvolatile memory. + All inputs are disabled during this write cycle and the EEPROM will + not respond to any access until the internal write is complete. + The steps to execute a single byte write are as follows: + + 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and + bits 7,1:0 both equal to 1, at least once after reset. Subsequent + operations need only to check that bits 1:0 are equal to 1 prior + to starting a single byte write. + + 2. Write to the LBCIF Control Register: bit 7=1, bit 6=1, bit 3=0, + and bits 1:0 both =0. Bit 5 should be set according to the type + of EEPROM being accessed (1=two byte addressing, 0=one byte + addressing). + + 3. Write the address to the LBCIF Address Register. + + 4. Write the data to the LBCIF Data Register (the I2C write will + begin). + + 5. Monitor bit 1:0 of the LBCIF Status Register. When bits 1:0 are + both equal to 1, the I2C write has completed and the internal + write cycle of the EEPROM is about to start. (bits 1:0 = 01 is a + legal state while waiting from both equal to 1, but bits 1:0 = 10 + is invalid and implies that something is broken). + + 6. Check bit 3 of the LBCIF Status Register. If equal to 1, an + error has occurred. + + 7. Check bit 2 of the LBCIF Status Register. If equal to 1 an ACK + error has occurred on the address phase of the write. This could + be due to an actual hardware failure or the EEPROM may still be in + its internal write cycle from a previous write. This write oper- + ation was ignored and must be repeated later. + + 8. Set bit 6 of the LBCIF Control Register = 0. If another write is + required, go to step 1. + *************************************************************************/ + + + /************************************************************************** + Step 1: + *************************************************************************/ + for( nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++) + { + /********************************************************************** + Read registers grouped in DWORD1 + *********************************************************************/ + if( LbcifReadDword( pAdapter, LBCIF_DWORD1_GROUP_OFFSET, &unDword1 )) + { + nError = 1; + break; + } + + bStatus = EXTRACT_STATUS_REGISTER( unDword1 ); + + if( bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL && + bStatus & LBCIF_STATUS_I2C_IDLE ) + { + /****************************************************************** + bits 1:0 are equal to 1 + *****************************************************************/ + break; + } + } + + if( nError || ( nIndex >= MAX_NUM_REGISTER_POLLS )) + { + return( FAILURE ); + } + + + /************************************************************************** + Step 2: + *************************************************************************/ + bControl = 0; + bControl |= LBCIF_CONTROL_LBCIF_ENABLE | LBCIF_CONTROL_I2C_WRITE; + + if( unAddressingMode == DUAL_BYTE ) + { + bControl |= LBCIF_CONTROL_TWO_BYTE_ADDR; + } + + if( LbcifWriteByte( pAdapter, LBCIF_CONTROL_REGISTER_OFFSET, bControl )) + { + return( FAILURE ); + } + + nI2CWriteActive = 1; + + + /************************************************************************** + Prepare EEPROM address for Step 3 + *************************************************************************/ + unAddress |= ( unAddressingMode == DUAL_BYTE ) ? + ( unEepromId << 16 ) : ( unEepromId << 8 ); + + for( nRetries = 0; nRetries < MAX_NUM_WRITE_RETRIES; nRetries++ ) + { + /********************************************************************** + Step 3: + *********************************************************************/ + if( LbcifWriteDword( pAdapter, LBCIF_ADDRESS_REGISTER_OFFSET, unAddress )) + { + break; + } + + /********************************************************************** + Step 4: + *********************************************************************/ + if( LbcifWriteByte( pAdapter, LBCIF_DATA_REGISTER_OFFSET, bData )) + { + break; + } + + /********************************************************************** + Step 5: + *********************************************************************/ + for( nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++ ) + { + /****************************************************************** + Read registers grouped in DWORD1 + *****************************************************************/ + if( LbcifReadDword( pAdapter, LBCIF_DWORD1_GROUP_OFFSET, + &unDword1 )) + { + nError = 1; + break; + } + + bStatus = EXTRACT_STATUS_REGISTER( unDword1 ); + + if( bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL && + bStatus & LBCIF_STATUS_I2C_IDLE ) + { + /************************************************************** + I2C write complete + *************************************************************/ + break; + } + } + + if( nError || ( nIndex >= MAX_NUM_REGISTER_POLLS )) + { + break; + } + + + /********************************************************************** + Step 6: Don't break here if we are revision 1, this is so we do a + blind write for load bug. + *********************************************************************/ + if( bStatus & LBCIF_STATUS_GENERAL_ERROR && pAdapter->RevisionID == 0 ) + { + break; + } + + + /********************************************************************** + Step 7: + *********************************************************************/ + if( bStatus & LBCIF_STATUS_ACK_ERROR ) + { + /****************************************************************** + This could be due to an actual hardware failure or the EEPROM + may still be in its internal write cycle from a previous write. + This write operation was ignored and must be repeated later. + *****************************************************************/ + udelay( 10 ); + continue; + } + + nWriteSuccessful = 1; + break; + } + + + /************************************************************************** + Step 8: + *************************************************************************/ + udelay( 10 ); + nIndex = 0; + while( nI2CWriteActive ) + { + bControl &= ~LBCIF_CONTROL_I2C_WRITE; + + if( LbcifWriteByte( pAdapter, LBCIF_CONTROL_REGISTER_OFFSET, bControl )) + { + nWriteSuccessful = 0; + } + + /* Do read until internal ACK_ERROR goes away meaning write completed */ + for( ;; ) + { + /* unAddress */ + LbcifWriteDword( pAdapter, LBCIF_ADDRESS_REGISTER_OFFSET, unAddress ); + + for( ;; ) + { + LbcifReadDword( pAdapter, LBCIF_DATA_REGISTER_OFFSET, &unData ); + + if( unData & 0x00010000 ) + { + break; + } + } + + if(( unData & 0x00040000 ) == 0x0 ) + { + break; + } + } + + bControl = EXTRACT_CONTROL_REG( unData ); + + if( bControl != 0xC0 || nIndex == 10000 ) + { + break; + } + + nIndex++; + } + + return(( nWriteSuccessful ) ? SUCCESS : FAILURE ); +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : EepromReadByte + ****************************************************************************** + + DESCRIPTION : Read a byte from the ET1310's EEPROM + + PARAMETERS : pAdapter - pointer to our private adapter structure + unAddress - the address from which to read + pbData - a pointer to a byte in which to store the + value of the read + unEepronId - the ID of the EEPROM + unAddressingMode - how the EEPROM is to be accessed + + RETURNS : SUCCESS or FAILURE + + REUSE INFORMATION : + + *****************************************************************************/ +INT32 EepromReadByte( ET131X_ADAPTER *pAdapter, UINT32 unAddress, PUCHAR pbData, + UINT32 unEepromId, UINT32 unAddressingMode ) +{ + INT32 nIndex; + INT32 nError = 0; + INT32 nReadSuccessful = 0; + UCHAR bControl; + UCHAR bStatus = 0; + UINT32 unDword1 = 0; + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + The following excerpt is from "Serial EEPROM HW Design Specification" + Version 0.92 (9/20/2004): + + Single Byte Reads + + A single byte read is similar to the single byte write, with the + exception of the data flow: + + 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and + bits 7,1:0 both equal to 1, at least once after reset. Subsequent + operations need only to check that bits 1:0 are equal to 1 prior + to starting a single byte read. + + 2. Write to the LBCIF Control Register: bit 7=1, bit 6=0, bit 3=0, + and bits 1:0 both =0. Bit 5 should be set according to the type + of EEPROM being accessed (1=two byte addressing, 0=one byte addr- + essing). + + 3. Write the address to the LBCIF Address Register (I2C read will + begin). + + 4. Monitor bit 0 of the LBCIF Status Register. When =1, I2C read is + complete. (if bit 1 =1 and bit 0 stays =0, a hardware failure has + occurred). + + 5. Check bit 2 of the LBCIF Status Register. If =1, then an error has + occurred. The data that has been returned from the PHY may be + invalid. + + 6. Regardless of error status, read data byte from LBCIF Data Register. + If another byte is required, go to step 1. + *************************************************************************/ + + + /************************************************************************** + Step 1: + *************************************************************************/ + for( nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++) + { + /********************************************************************** + Read registers grouped in DWORD1 + *********************************************************************/ + if( LbcifReadDword( pAdapter, LBCIF_DWORD1_GROUP_OFFSET, &unDword1 )) + { + nError = 1; + break; + } + + bStatus = EXTRACT_STATUS_REGISTER( unDword1 ); + + if( bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL && + bStatus & LBCIF_STATUS_I2C_IDLE ) + { + /****************************************************************** + bits 1:0 are equal to 1 + *****************************************************************/ + break; + } + } + + if( nError || ( nIndex >= MAX_NUM_REGISTER_POLLS )) + { + return( FAILURE ); + } + + + /************************************************************************** + Step 2: + *************************************************************************/ + bControl = 0; + bControl |= LBCIF_CONTROL_LBCIF_ENABLE; + + if( unAddressingMode == DUAL_BYTE ) + { + bControl |= LBCIF_CONTROL_TWO_BYTE_ADDR; + } + + if( LbcifWriteByte( pAdapter, LBCIF_CONTROL_REGISTER_OFFSET, bControl )) + { + return( FAILURE ); + } + + + /************************************************************************** + Step 3: + *************************************************************************/ + unAddress |= ( unAddressingMode == DUAL_BYTE ) ? + ( unEepromId << 16 ) : ( unEepromId << 8 ); + + if( LbcifWriteDword( pAdapter, LBCIF_ADDRESS_REGISTER_OFFSET, unAddress )) + { + return( FAILURE ); + } + + + /************************************************************************** + Step 4: + *************************************************************************/ + for( nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++ ) + { + /********************************************************************** + Read registers grouped in DWORD1 + *********************************************************************/ + if( LbcifReadDword( pAdapter, LBCIF_DWORD1_GROUP_OFFSET, &unDword1 )) + { + nError = 1; + break; + } + + bStatus = EXTRACT_STATUS_REGISTER( unDword1 ); + + if( bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL + && bStatus & LBCIF_STATUS_I2C_IDLE ) + { + /****************************************************************** + I2C read complete + *****************************************************************/ + break; + } + } + + if( nError || ( nIndex >= MAX_NUM_REGISTER_POLLS )) + { + return( FAILURE ); + } + + + /************************************************************************** + Step 5: + *************************************************************************/ + nReadSuccessful = ( bStatus & LBCIF_STATUS_ACK_ERROR ) ? 0 : 1; + + + /************************************************************************** + Step 6: + *************************************************************************/ + *pbData = EXTRACT_DATA_REGISTER( unDword1 ); + + return( nReadSuccessful ) ? SUCCESS : FAILURE; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : EEPROM_access + ****************************************************************************** + + DESCRIPTION : + Performs a read or write of a given data width at a specified offset + from EEPROM + + PARAMETERS : + pAdapter - [in] pointer to the adapter structure + bAccessFlag - [in] A flag indicating what type of transaction + READ/WRITE + unOffset - [in] Specifies the offset within the EEPROM + bWidth - [in] Defines the width (in bits) of the requested + access. Valid values are 8 or 32. + pData - [in/out] Pointer to a buffer that contains the data + requested by or resulting from the transaction + specified by 'bAccessFlag'. + Method in which this parameter is processed + (de-referenced) is determined by the value of + 'bWidth', i.e. 8-bit or 32-bit read/write + accesses. + + RETURNS : + result from PCI Config space access + + REUSE INFORMATION : + YES + + *****************************************************************************/ +UINT32 EEPROM_access( ET131X_ADAPTER *pAdapter, UCHAR bAccessFlag, + UINT32 unOffset, UCHAR bWidth, void *pData ) +{ + UINT32 ulResult; + /*-----------------------------------------------------------------------*/ + + if( bAccessFlag == WRITE ) + { + /********************************************************************** + we are doing a write + *********************************************************************/ + ulResult = pci_slot_information_write( pAdapter->pdev, + unOffset, + pData, + ( bWidth / 8 )); + } + else + { + /********************************************************************** + do the read read + *********************************************************************/ + ulResult = pci_slot_information_read( pAdapter->pdev, + unOffset, + pData, + ( bWidth / 8 )); + } + if( ulResult != 0 ) + { + return( 0 ); + } + else + { + return( ulResult ); + } +} +/*===========================================================================*/ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_mac.c +++ linux-2.6.27/ubuntu/et131x/ET1310_mac.c @@ -0,0 +1,1247 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_mac.c - All code and routines pertaining to the MAC + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 18:43:44 $ + $Revision: 1.11 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" +#include "ET1310_mac.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" +#include "et131x_supp.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + ROUTINE: ConfigMacRegs1 + ****************************************************************************** + + DESCRIPTION: + Used to configure the first part of MAC regs to a known initialized + state + + PARAMETERS : + pAdpater - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigMACRegs1( ET131X_ADAPTER *pAdapter ) +{ + PMAC_t pMac; + MAC_STATION_ADDR1_t station1; + MAC_STATION_ADDR2_t station2; + MAC_IPG_t ipg; + MAC_HFDP_t hfdp; + MII_MGMT_CFG_t mii_mgmt_cfg; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigMACRegs1" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Let's get our pointer to the MAC regs + *************************************************************************/ + pMac = &pAdapter->CSRAddress->mac; + + + /************************************************************************** + First we need to reset everything. Write to MAC configuration register + 1 to perform reset. + *************************************************************************/ + pMac->cfg1.value = 0xC00F0000; + + + /************************************************************************** + Next lets configure the MAC Inter-packet gap register + *************************************************************************/ + ipg.bits.non_B2B_ipg_1 = 0x38; //58d + ipg.bits.non_B2B_ipg_2 = 0x58; //88d + ipg.bits.min_ifg_enforce = 0x50; //80d + ipg.bits.B2B_ipg = 0x60; //96d + + pMac->ipg.value = ipg.value; + + + /************************************************************************** + Next lets configure the MAC Half Duplex register + *************************************************************************/ + hfdp.bits.alt_beb_trunc = 0xA; + hfdp.bits.alt_beb_enable = 0x0; + hfdp.bits.bp_no_backoff = 0x0; + hfdp.bits.no_backoff = 0x0; + hfdp.bits.excess_defer = 0x1; + hfdp.bits.rexmit_max = 0xF; + hfdp.bits.coll_window = 0x37; //55d + + pMac->hfdp.value = hfdp.value; + + + /************************************************************************** + Next lets configure the MAC Interface Control register + *************************************************************************/ + pMac->if_ctrl.value = 0x0; + + + /************************************************************************** + Let's move on to setting up the mii managment configuration + *************************************************************************/ + mii_mgmt_cfg.bits.reset_mii_mgmt = 0; + mii_mgmt_cfg.bits.scan_auto_incremt = 0; + mii_mgmt_cfg.bits.preamble_suppress = 0; + mii_mgmt_cfg.bits.mgmt_clk_reset = 0x7; + + pMac->mii_mgmt_cfg.value = mii_mgmt_cfg.value; + + + /************************************************************************** + Next lets configure the MAC Station Address register. These values are + read from the EEPROM during initialization and stored in the adapter + structure. We write what is stored in the adapter structure to the MAC + Station Address registers high and low. This station address is used + for generating and checking pause control packets. + *************************************************************************/ + station2.bits.Octet1 = pAdapter->CurrentAddress[0]; + station2.bits.Octet2 = pAdapter->CurrentAddress[1]; + station1.bits.Octet3 = pAdapter->CurrentAddress[2]; + station1.bits.Octet4 = pAdapter->CurrentAddress[3]; + station1.bits.Octet5 = pAdapter->CurrentAddress[4]; + station1.bits.Octet6 = pAdapter->CurrentAddress[5]; + + pMac->station_addr_1.value = station1.value; + pMac->station_addr_2.value = station2.value; + + + /************************************************************************** + Max ethernet packet in bytes that will passed by the mac without being + truncated. Allow the MAC to pass 8 more than our max packet size. This + is 4 for the Ethernet CRC and 4 for the VLAN ID. + + Packets larger than (RegistryJumboPacket) that do not contain a VLAN + ID will be dropped by the Rx function. + *************************************************************************/ +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + pMac->max_fm_len.value = pAdapter->RegistryJumboPacket + 8; +#else + pMac->max_fm_len.value = pAdapter->RegistryJumboPacket + 4; +#endif + + + /************************************************************************** + clear out MAC config reset + *************************************************************************/ + pAdapter->CSRAddress->mac.cfg1.value = 0x0; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: ConfigMacRegs2 + ****************************************************************************** + + DESCRIPTION: + Used to configure the second part of MAC regs to a known initialized + state + + PARAMETERS : + pAdpater - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigMACRegs2( ET131X_ADAPTER *pAdapter ) +{ + INT32 delay = 0; + PMAC_t pMac; + MAC_CFG1_t cfg1; + MAC_CFG2_t cfg2; + MAC_IF_CTRL_t ifctrl; + TXMAC_CTL_t ctl = pAdapter->CSRAddress->txmac.ctl; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigMACRegs2" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Let's get our pointer to the MAC regs + *************************************************************************/ + pMac = &pAdapter->CSRAddress->mac; + + cfg1.value = pMac->cfg1.value; + cfg2.value = pMac->cfg2.value; + ifctrl.value = pMac->if_ctrl.value; + + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS ) + { + cfg2.bits.if_mode = 0x2; + ifctrl.bits.phy_mode = 0x0; + } + else + { + cfg2.bits.if_mode = 0x1; + ifctrl.bits.phy_mode = 0x1; + } + + + /************************************************************************** + We need to enable Rx/Tx + *************************************************************************/ + cfg1.bits.rx_enable = 0x1; + cfg1.bits.tx_enable = 0x1; + + + /************************************************************************** + Set up flow control + *************************************************************************/ + cfg1.bits.tx_flow = 0x1; + + if( ( pAdapter->FlowControl == RxOnly ) || + ( pAdapter->FlowControl == Both )) + { + cfg1.bits.rx_flow = 0x1; + } + else + { + cfg1.bits.rx_flow = 0x0; + } + + + /************************************************************************** + Initialize loop back to off + *************************************************************************/ + cfg1.bits.loop_back = 0; + + pAdapter->CSRAddress->mac.cfg1.value = cfg1.value; + + + /************************************************************************** + Now we need to initialize the MAC Configuration 2 register + *************************************************************************/ + cfg2.bits.preamble_len = 0x7; + cfg2.bits.huge_frame = 0x0; + /* LENGTH FIELD CHECKING bit4: Set this bit to cause the MAC to check the + * frame’s length field to ensure it matches the actual data field length. Clear this bit if no + * length field checking is desired. Its default is ‘0’. + */ + cfg2.bits.len_check = 0x1; + + if ( pAdapter->RegistryPhyLoopbk == FALSE ) + { + cfg2.bits.pad_crc = 0x1; + cfg2.bits.crc_enable = 0x1; + } + else + { + cfg2.bits.pad_crc = 0; + cfg2.bits.crc_enable = 0; + } + + + /************************************************************************** + 1 – full duplex, 0 – half-duplex + *************************************************************************/ + cfg2.bits.full_duplex = pAdapter->uiDuplexMode; + ifctrl.bits.ghd_mode = !pAdapter->uiDuplexMode; + + pAdapter->CSRAddress->mac.if_ctrl = ifctrl; + pAdapter->CSRAddress->mac.cfg2.value = cfg2.value; + + do + { + udelay( 10 ); + delay++; + } while(( !pAdapter->CSRAddress->mac.cfg1.bits.syncd_rx_en || + !pAdapter->CSRAddress->mac.cfg1.bits.syncd_tx_en ) && + ( delay < 100 )); + + if( delay == 100 ) + { + DBG_ERROR( et131x_dbginfo, + "Syncd bits did not respond correctly cfg1 word 0x%08x\n", + pAdapter->CSRAddress->mac.cfg1.value ); + } + + DBG_TRACE( et131x_dbginfo, + "Speed %d, Dup %d, CFG1 0x%08x, CFG2 0x%08x, if_ctrl 0x%08x\n", + pAdapter->uiLinkSpeed, pAdapter->uiDuplexMode, + pAdapter->CSRAddress->mac.cfg1.value, + pAdapter->CSRAddress->mac.cfg2.value, + pAdapter->CSRAddress->mac.if_ctrl.value ); + + + /************************************************************************** + Enable TXMAC + *************************************************************************/ + ctl.bits.txmac_en = 0x1; + ctl.bits.fc_disable = 0x1; + pAdapter->CSRAddress->txmac.ctl = ctl; + + + /************************************************************************** + Ready to start the RXDMA/TXDMA engine + *************************************************************************/ + if( !MP_TEST_FLAG( pAdapter, fMP_ADAPTER_LOWER_POWER )) + { + et131x_rx_dma_enable( pAdapter ); + et131x_tx_dma_enable( pAdapter ); + } + else + { + DBG_WARNING( et131x_dbginfo, + "Didn't enable Rx/Tx due to low-power mode\n" ); + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: ConfigRxMacRegs + ****************************************************************************** + + DESCRIPTION: + Used to configure the RX MAC registers in the JAGCore + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigRxMacRegs( ET131X_ADAPTER *pAdapter ) +{ + PRXMAC_t pRxMac; + RXMAC_WOL_SA_LO_t sa_lo; + RXMAC_WOL_SA_HI_t sa_hi; + RXMAC_PF_CTRL_t pf_ctrl = {0}; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigRxMacRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Let's get a local pointer to the RX MAC Registers + *************************************************************************/ + pRxMac = &pAdapter->CSRAddress->rxmac; + + + /************************************************************************** + Disable the MAC while it is being configured (also disable WOL) + *************************************************************************/ + pRxMac->ctrl.value = 0x8; + + + /************************************************************************** + Initialize WOL to disabled. + *************************************************************************/ + + pRxMac->crc0.value = 0x0; + pRxMac->crc12.value = 0x0000; + pRxMac->crc34.value = 0x0000; + + + /************************************************************************** + We need to set the WOL mask0 – mask4 next. We initialize it to its + default Values of 0x00000000 because there are not WOL masks as of + this time. + *************************************************************************/ + pRxMac->mask0_word0.mask = 0x00000000; + pRxMac->mask0_word1.mask = 0x00000000; + pRxMac->mask0_word2.mask = 0x00000000; + pRxMac->mask0_word3.mask = 0x00000000; + + pRxMac->mask1_word0.mask = 0x00000000; + pRxMac->mask1_word1.mask = 0x00000000; + pRxMac->mask1_word2.mask = 0x00000000; + pRxMac->mask1_word3.mask = 0x00000000; + + pRxMac->mask2_word0.mask = 0x00000000; + pRxMac->mask2_word1.mask = 0x00000000; + pRxMac->mask2_word2.mask = 0x00000000; + pRxMac->mask2_word3.mask = 0x00000000; + + pRxMac->mask3_word0.mask = 0x00000000; + pRxMac->mask3_word1.mask = 0x00000000; + pRxMac->mask3_word2.mask = 0x00000000; + pRxMac->mask3_word3.mask = 0x00000000; + + pRxMac->mask4_word0.mask = 0x00000000; + pRxMac->mask4_word1.mask = 0x00000000; + pRxMac->mask4_word2.mask = 0x00000000; + pRxMac->mask4_word3.mask = 0x00000000; + + + /************************************************************************** + Lets setup the WOL Source Address + *************************************************************************/ + sa_lo.bits.sa3 = pAdapter->CurrentAddress[2]; + sa_lo.bits.sa4 = pAdapter->CurrentAddress[3]; + sa_lo.bits.sa5 = pAdapter->CurrentAddress[4]; + sa_lo.bits.sa6 = pAdapter->CurrentAddress[5]; + pRxMac->sa_lo.value = sa_lo.value; + + sa_hi.bits.sa1 = pAdapter->CurrentAddress[0]; + sa_hi.bits.sa2 = pAdapter->CurrentAddress[1]; + pRxMac->sa_hi.value = sa_hi.value; + + + /************************************************************************** + Disable all Packet Filtering + *************************************************************************/ + pRxMac->pf_ctrl.value = 0; + + + /************************************************************************** + Let's initialize the Unicast Packet filtering address + *************************************************************************/ + if( pAdapter->PacketFilter & ET131X_PACKET_TYPE_DIRECTED ) + { + SetupDeviceForUnicast( pAdapter ); + pf_ctrl.bits.filter_uni_en = 1; + } + else + { + pRxMac->uni_pf_addr1.value = 0x00000000; + pRxMac->uni_pf_addr2.value = 0x00000000; + pRxMac->uni_pf_addr3.value = 0x00000000; + } + + + /************************************************************************** + Let's initialize the Multicast hash + *************************************************************************/ + if( pAdapter->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST ) + { + pf_ctrl.bits.filter_multi_en = 0; + } + else + { + pf_ctrl.bits.filter_multi_en = 1; + SetupDeviceForMulticast( pAdapter ); + } + + + /************************************************************************** + Runt packet filtering. Didn't work in version A silicon. + *************************************************************************/ + pf_ctrl.bits.min_pkt_size = NIC_MIN_PACKET_SIZE + 4; + pf_ctrl.bits.filter_frag_en = 1; + + if( pAdapter->RegistryJumboPacket > 8192 ) + { + RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg; + + + /********************************************************************** + In order to transmit jumbo packets greater than 8k, the FIFO + between RxMAC and RxDMA needs to be reduced in size to (16k - + Jumbo packet size). In order to implement this, we must use + "cut through" mode in the RxMAC, which chops packets down into + segments which are (max_size * 16). In this case we selected + 256 bytes, since this is the size of the PCI-Express TLP's that + the 1310 uses. + *********************************************************************/ + mcif_ctrl_max_seg.bits.seg_en = 0x1; + mcif_ctrl_max_seg.bits.fc_en = 0x0; + mcif_ctrl_max_seg.bits.max_size = 0x10; + + pRxMac->mcif_ctrl_max_seg.value = mcif_ctrl_max_seg.value; + } + else + { + pRxMac->mcif_ctrl_max_seg.value = 0x0; + } + + + /************************************************************************** + Initialize the MCIF water marks + *************************************************************************/ + pRxMac->mcif_water_mark.value = 0x0; + + + /************************************************************************** + Initialize the MIF control + *************************************************************************/ + pRxMac->mif_ctrl.value = 0x0; + + + /************************************************************************** + Initialize the Space Available Register + *************************************************************************/ + pRxMac->space_avail.value = 0x0; + + /* Initialize the the mif_ctrl register + * bit 3 - Receive code error. One or more nibbles were signaled as errors + during the reception of the packet. Clear this bit in Gigabit, + set it in 100Mbit. This was derived experimentally at UNH. + * bit 4 - Receive CRC error. The packet’s CRC did not match the + internally generated CRC. + * bit 5 - Receive length check error. Indicates that frame length field + value in the packet does not match the actual data byte length + and is not a type field. + * bit 16 - Receive frame truncated. + * bit 17 - Drop packet enable + */ + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_100MBPS ) + { + pRxMac->mif_ctrl.value = 0x30038; + } + else + { + pRxMac->mif_ctrl.value = 0x30030; + } + + + /************************************************************************** + Finally we initialize RxMac to be enabled & WOL disabled. Packet filter + is always enabled since it is where the runt packets are supposed to be + dropped. For version A silicon, runt packet dropping doesn't work, so + it is disabled in the pf_ctrl register, but we still leave the packet + filter on. + *************************************************************************/ + pRxMac->pf_ctrl = pf_ctrl; + pRxMac->ctrl.value = 0x9; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: ConfigTxMacRegs + ****************************************************************************** + + DESCRIPTION: + used to configure the TX MAC registers of the JAGCore + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigTxMacRegs( ET131X_ADAPTER *pAdapter ) +{ + PTXMAC_t pTxMac; + TXMAC_CF_PARAM_t Local; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigTxMacRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Let's get the pointer to tx mac section of regs + *************************************************************************/ + pTxMac = &pAdapter->CSRAddress->txmac; + + + /************************************************************************** + We need to update the Control Frame Parameters + cfpt - control frame pause timer set to 64 (0x40) + cfep - control frame extended pause timer set to 0x0 + *************************************************************************/ + if( pAdapter->FlowControl == None ) + { + pTxMac->cf_param.value = 0x0; + } + else + { + Local.bits.cfpt = 0x40; + Local.bits.cfep = 0x0; + pTxMac->cf_param.value = Local.value; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: ConfigMacStatRegs + ****************************************************************************** + + DESCRIPTION: + Used to configure the MAC STAT section of the JAGCore + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigMacStatRegs( ET131X_ADAPTER *pAdapter ) +{ + PMAC_STAT_t pDevMacStat; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigMacStatRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + pDevMacStat = &pAdapter->CSRAddress->macStat; + + + /************************************************************************** + Next we need to initialize all the MAC_STAT registers to zero on the + device. + *************************************************************************/ + pDevMacStat->RFcs = 0x0; + pDevMacStat->RAln = 0x0; + pDevMacStat->RFlr = 0x0; + pDevMacStat->RDrp = 0x0; + pDevMacStat->RCde = 0x0; + pDevMacStat->ROvr = 0x0; + pDevMacStat->RFrg = 0x0; + + pDevMacStat->TScl = 0x0; + pDevMacStat->TDfr = 0x0; + pDevMacStat->TMcl = 0x0; + pDevMacStat->TLcl = 0x0; + pDevMacStat->TNcl = 0x0; + pDevMacStat->TOvr = 0x0; + pDevMacStat->TUnd = 0x0; + + + /*************************************************************************** + Unmask any counters that we want to track the overflow of. Initially + this will be all counters. It may become clear later that we do not + need to track all counters. + **************************************************************************/ + { + MAC_STAT_REG_1_t Carry1M = {0xffffffff}; + + Carry1M.bits.rdrp = 0x0; + Carry1M.bits.rjbr = 0x1; + Carry1M.bits.rfrg = 0x0; + Carry1M.bits.rovr = 0x0; + Carry1M.bits.rund = 0x1; + Carry1M.bits.rcse = 0x1; + Carry1M.bits.rcde = 0x0; + Carry1M.bits.rflr = 0x0; + Carry1M.bits.raln = 0x0; + Carry1M.bits.rxuo = 0x1; + Carry1M.bits.rxpf = 0x1; + Carry1M.bits.rxcf = 0x1; + Carry1M.bits.rbca = 0x1; + Carry1M.bits.rmca = 0x1; + Carry1M.bits.rfcs = 0x0; + Carry1M.bits.rpkt = 0x1; + Carry1M.bits.rbyt = 0x1; + Carry1M.bits.trmgv = 0x1; + Carry1M.bits.trmax = 0x1; + Carry1M.bits.tr1k = 0x1; + Carry1M.bits.tr511 = 0x1; + Carry1M.bits.tr255 = 0x1; + Carry1M.bits.tr127 = 0x1; + Carry1M.bits.tr64 = 0x1; + + pDevMacStat->Carry1M = Carry1M; + } + + { + MAC_STAT_REG_2_t Carry2M = {0xffffffff}; + + Carry2M.bits.tdrp = 0x1; + Carry2M.bits.tpfh = 0x1; + Carry2M.bits.tncl = 0x0; + Carry2M.bits.txcl = 0x1; + Carry2M.bits.tlcl = 0x0; + Carry2M.bits.tmcl = 0x0; + Carry2M.bits.tscl = 0x0; + Carry2M.bits.tedf = 0x1; + Carry2M.bits.tdfr = 0x0; + Carry2M.bits.txpf = 0x1; + Carry2M.bits.tbca = 0x1; + Carry2M.bits.tmca = 0x1; + Carry2M.bits.tpkt = 0x1; + Carry2M.bits.tbyt = 0x1; + Carry2M.bits.tfrg = 0x1; + Carry2M.bits.tund = 0x0; + Carry2M.bits.tovr = 0x0; + Carry2M.bits.txcf = 0x1; + Carry2M.bits.tfcs = 0x1; + Carry2M.bits.tjbr = 0x1; + + pDevMacStat->Carry2M = Carry2M; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: ConfigFlowControl + ****************************************************************************** + + DESCRIPTION: + Used to configure the MAC STAT section of the JAGCore + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigFlowControl( ET131X_ADAPTER *pAdapter ) +{ + if( pAdapter->uiDuplexMode == 0 ) + { + pAdapter->FlowControl = None; + } + else + { + char RemotePause, RemoteAsyncPause; + + ET1310_PhyAccessMiBit( pAdapter, + TRUEPHY_BIT_READ, 5, 10, &RemotePause ); + ET1310_PhyAccessMiBit( pAdapter, + TRUEPHY_BIT_READ, 5, 11, &RemoteAsyncPause ); + + if(( RemotePause == TRUEPHY_BIT_SET ) && + ( RemoteAsyncPause == TRUEPHY_BIT_SET )) + { + pAdapter->FlowControl = pAdapter->RegistryFlowControl; + } + else if(( RemotePause == TRUEPHY_BIT_SET ) && + ( RemoteAsyncPause == TRUEPHY_BIT_CLEAR )) + { + if( pAdapter->RegistryFlowControl == Both ) + { + pAdapter->FlowControl = Both; + } + else + { + pAdapter->FlowControl = None; + } + } + else if(( RemotePause == TRUEPHY_BIT_CLEAR ) && + ( RemoteAsyncPause == TRUEPHY_BIT_CLEAR )) + { + pAdapter->FlowControl = None; + } + else /* if (( RemotePause == TRUEPHY_CLEAR_BIT ) && + ( RemoteAsyncPause == TRUEPHY_SET_BIT )) */ + { + if( pAdapter->RegistryFlowControl == Both ) + { + pAdapter->FlowControl = RxOnly; + } + else + { + pAdapter->FlowControl = None; + } + } + } +} +/*===========================================================================*/ + + + + + + +/****************************************************************************** + ROUTINE: UpdateMacStatHostCounters + ****************************************************************************** + + DESCRIPTION: + used to update the local copy of the statistics held in the adapter + structure + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void UpdateMacStatHostCounters( ET131X_ADAPTER *pAdapter ) +{ + PMAC_STAT_t pDevMacStat; + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + Get a local pointer to the adapter macstat regs and update stats + *************************************************************************/ + pDevMacStat = &pAdapter->CSRAddress->macStat; + + pAdapter->Stats.collisions += pDevMacStat->TNcl; + pAdapter->Stats.first_collision += pDevMacStat->TScl; + pAdapter->Stats.tx_deferred += pDevMacStat->TDfr; + pAdapter->Stats.excessive_collisions += pDevMacStat->TMcl; + pAdapter->Stats.late_collisions += pDevMacStat->TLcl; + pAdapter->Stats.tx_uflo += pDevMacStat->TUnd; + pAdapter->Stats.max_pkt_error += pDevMacStat->TOvr; + + pAdapter->Stats.alignment_err += pDevMacStat->RAln; + pAdapter->Stats.crc_err += pDevMacStat->RCde; + pAdapter->Stats.norcvbuf += pDevMacStat->RDrp; + pAdapter->Stats.rx_ov_flow += pDevMacStat->ROvr; + pAdapter->Stats.code_violations += pDevMacStat->RFcs; + pAdapter->Stats.length_err += pDevMacStat->RFlr; + + pAdapter->Stats.other_errors += pDevMacStat->RFrg; + + return; +} +/*===========================================================================*/ + + + + + +/****************************************************************************** + ROUTINE: HandleMacStatInterrupt + ****************************************************************************** + + DESCRIPTION: + One of the MACSTAT counters has wrapped. Update the local copy of + the statistics held in the adapter structure, checking the "wrap" + bit for each counter. + + PARAMETERS : + pAdapter - pointer to the adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void HandleMacStatInterrupt( ET131X_ADAPTER *pAdapter ) +{ + MAC_STAT_REG_1_t Carry1; + MAC_STAT_REG_2_t Carry2; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "HandleMacStatInterrupt" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Read the interrupt bits from the register(s). These are Clear On Write. + *************************************************************************/ + Carry1 = pAdapter->CSRAddress->macStat.Carry1; + Carry2 = pAdapter->CSRAddress->macStat.Carry2; + + pAdapter->CSRAddress->macStat.Carry1 = Carry1; + pAdapter->CSRAddress->macStat.Carry2 = Carry2; + + + /************************************************************************** + We need to do update the host copy of all the MAC_STAT counters. For + each counter, check it's overflow bit. If the overflow bit is set, then + increment the host version of the count by one complete revolution of the + counter. This routine is called when the counter block indicates that + one of the counters has wrapped. + *************************************************************************/ + if( Carry1.bits.rfcs ) + { + pAdapter->Stats.code_violations += COUNTER_WRAP_16_BIT; + } + + if( Carry1.bits.raln ) + { + pAdapter->Stats.alignment_err += COUNTER_WRAP_12_BIT; + } + + if( Carry1.bits.rflr ) + { + pAdapter->Stats.length_err += COUNTER_WRAP_16_BIT; + } + + if( Carry1.bits.rfrg ) + { + pAdapter->Stats.other_errors += COUNTER_WRAP_16_BIT; + } + + if( Carry1.bits.rcde ) + { + pAdapter->Stats.crc_err += COUNTER_WRAP_16_BIT; + } + + if( Carry1.bits.rovr ) + { + pAdapter->Stats.rx_ov_flow += COUNTER_WRAP_16_BIT; + } + + if( Carry1.bits.rdrp ) + { + pAdapter->Stats.norcvbuf += COUNTER_WRAP_16_BIT; + } + + if( Carry2.bits.tovr ) + { + pAdapter->Stats.max_pkt_error += COUNTER_WRAP_12_BIT; + } + + if( Carry2.bits.tund ) + { + pAdapter->Stats.tx_uflo += COUNTER_WRAP_12_BIT; + } + + if( Carry2.bits.tscl ) + { + pAdapter->Stats.first_collision += COUNTER_WRAP_12_BIT; + } + + if( Carry2.bits.tdfr ) + { + pAdapter->Stats.tx_deferred += COUNTER_WRAP_12_BIT; + } + + if( Carry2.bits.tmcl ) + { + pAdapter->Stats.excessive_collisions += COUNTER_WRAP_12_BIT; + } + + if( Carry2.bits.tlcl ) + { + pAdapter->Stats.late_collisions += COUNTER_WRAP_12_BIT; + } + + if( Carry2.bits.tncl ) + { + pAdapter->Stats.collisions += COUNTER_WRAP_12_BIT; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : SetupDeviceForMulticast + ****************************************************************************** + + DESCRIPTION : + Use to set the ET1310 to do multicast filtering + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + REUSE INFORMATION : + NONE + + *****************************************************************************/ +void SetupDeviceForMulticast( ET131X_ADAPTER *pAdapter ) +{ + UINT32 nIndex; + UINT32 result; + RXMAC_MULTI_HASH_t hash1 = {0}; + RXMAC_MULTI_HASH_t hash2 = {0}; + RXMAC_MULTI_HASH_t hash3 = {0}; + RXMAC_MULTI_HASH_t hash4 = {0}; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "SetupDeviceForMulticast" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + If ET131X_PACKET_TYPE_MULTICAST is specified, then we provision the + multi-cast LIST. If it is NOT specified, (and "ALL" is not specified) + then we should pass NO multi-cast addresses to the driver. + *************************************************************************/ + if( pAdapter->PacketFilter & ET131X_PACKET_TYPE_MULTICAST ) + { + DBG_VERBOSE( et131x_dbginfo, "MULTICAST flag is set, MCCount: %d\n", + pAdapter->MCAddressCount ); + + + /********************************************************************** + Loop through our multicast array and set up the device + **********************************************************************/ + for( nIndex = 0; nIndex < pAdapter->MCAddressCount; nIndex++ ) + { + DBG_VERBOSE( et131x_dbginfo, + "MCList[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n", + nIndex, + pAdapter->MCList[nIndex][0], + pAdapter->MCList[nIndex][1], + pAdapter->MCList[nIndex][2], + pAdapter->MCList[nIndex][3], + pAdapter->MCList[nIndex][4], + pAdapter->MCList[nIndex][5] ); + + result = et131x_calc_enet_crc( pAdapter->MCList[nIndex], 6 ); + + result = ( result & 0x3F800000 ) >> 23; + + if( result < 32 ) + { + hash1.hash |= ( 1 << result ); + } + else if(( 31 < result ) && ( result < 64 )) + { + result -= 32; + hash2.hash |= ( 1 << result ); + } + else if(( 63 < result ) && ( result < 96 )) + { + result -= 64; + hash3.hash |= ( 1 << result ); + } + else + { + result -= 96; + hash4.hash |= ( 1 << result ); + } + } + } + + + /************************************************************************** + Write out the new hash to the device + *************************************************************************/ + if( pAdapter->CSRAddress->global.pm_csr.bits.pm_phy_sw_coma == 0 ) + { + pAdapter->CSRAddress->rxmac.multi_hash1.hash = hash1.hash; + pAdapter->CSRAddress->rxmac.multi_hash2.hash = hash2.hash; + pAdapter->CSRAddress->rxmac.multi_hash3.hash = hash3.hash; + pAdapter->CSRAddress->rxmac.multi_hash4.hash = hash4.hash; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : SetupDeviceForUnicast + ****************************************************************************** + + DESCRIPTION : + Use to set the ET1310 to do unicast filtering + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + REUSE INFORMATION : + NONE + + *****************************************************************************/ +void SetupDeviceForUnicast( ET131X_ADAPTER *pAdapter ) +{ + RXMAC_UNI_PF_ADDR1_t uni_pf1; + RXMAC_UNI_PF_ADDR2_t uni_pf2; + RXMAC_UNI_PF_ADDR3_t uni_pf3; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "SetupDeviceForUnicast" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Set up unicast packet filter reg 3 to be the first two octets of the + MAC address for both address + *************************************************************************/ + /************************************************************************** + Set up unicast packet filter reg 2 to be the octets 2 - 5 of the + MAC address for second address + *************************************************************************/ + /************************************************************************** + Set up unicast packet filter reg 3 to be the octets 2 - 5 of the + MAC address for first address + *************************************************************************/ + uni_pf3.bits.addr1_1 = pAdapter->CurrentAddress[0]; + uni_pf3.bits.addr1_2 = pAdapter->CurrentAddress[1]; + uni_pf3.bits.addr2_1 = pAdapter->CurrentAddress[0]; + uni_pf3.bits.addr2_2 = pAdapter->CurrentAddress[1]; + + uni_pf2.bits.addr2_3 = pAdapter->CurrentAddress[2]; + uni_pf2.bits.addr2_4 = pAdapter->CurrentAddress[3]; + uni_pf2.bits.addr2_5 = pAdapter->CurrentAddress[4]; + uni_pf2.bits.addr2_6 = pAdapter->CurrentAddress[5]; + + uni_pf1.bits.addr1_3 = pAdapter->CurrentAddress[2]; + uni_pf1.bits.addr1_4 = pAdapter->CurrentAddress[3]; + uni_pf1.bits.addr1_5 = pAdapter->CurrentAddress[4]; + uni_pf1.bits.addr1_6 = pAdapter->CurrentAddress[5]; + + if( pAdapter->CSRAddress->global.pm_csr.bits.pm_phy_sw_coma == 0 ) + { + pAdapter->CSRAddress->rxmac.uni_pf_addr1 = uni_pf1; + pAdapter->CSRAddress->rxmac.uni_pf_addr2 = uni_pf2; + pAdapter->CSRAddress->rxmac.uni_pf_addr3 = uni_pf3; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ --- linux-2.6.27.orig/ubuntu/et131x/et131x_config.c +++ linux-2.6.27/ubuntu/et131x/et131x_config.c @@ -0,0 +1,383 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_config.c - Handles parsing of configuration data during + * initialization. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 18:43:46 $ + $Revision: 1.8 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" + +#include "ET1310_tx.h" + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Defines for Parameter Default/Min/Max vaules + *****************************************************************************/ +#define PARM_SPEED_DUPLEX_DEF 0 +#define PARM_SPEED_DUPLEX_MIN 0 +#define PARM_SPEED_DUPLEX_MAX 5 + +#define PARM_VLAN_TAG_DEF 0 +#define PARM_VLAN_TAG_MIN 0 +#define PARM_VLAN_TAG_MAX 4095 + +#define PARM_FLOW_CTL_DEF 0 +#define PARM_FLOW_CTL_MIN 0 +#define PARM_FLOW_CTL_MAX 3 + +#define PARM_WOL_LINK_DEF 3 +#define PARM_WOL_LINK_MIN 0 +#define PARM_WOL_LINK_MAX 3 + +#define PARM_WOL_MATCH_DEF 7 +#define PARM_WOL_MATCH_MIN 0 +#define PARM_WOL_MATCH_MAX 7 + +#define PARM_JUMBO_PKT_DEF 1514 +#define PARM_JUMBO_PKT_MIN 1514 +#define PARM_JUMBO_PKT_MAX 9216 + +#define PARM_PHY_COMA_DEF 0 +#define PARM_PHY_COMA_MIN 0 +#define PARM_PHY_COMA_MAX 1 + +#define PARM_RX_NUM_BUFS_DEF 4 +#define PARM_RX_NUM_BUFS_MIN 1 +#define PARM_RX_NUM_BUFS_MAX 64 + +#define PARM_RX_TIME_INT_DEF 10 +#define PARM_RX_TIME_INT_MIN 2 +#define PARM_RX_TIME_INT_MAX 320 + +#define PARM_TX_NUM_BUFS_DEF 4 +#define PARM_TX_NUM_BUFS_MIN 1 +#define PARM_TX_NUM_BUFS_MAX 40 + +#define PARM_TX_TIME_INT_DEF 40 +#define PARM_TX_TIME_INT_MIN 1 +#define PARM_TX_TIME_INT_MAX 140 + +#define PARM_RX_MEM_END_DEF 0x2bc +#define PARM_RX_MEM_END_MIN 0 +#define PARM_RX_MEM_END_MAX 0x3ff + +#define PARM_MAC_STAT_DEF 1 +#define PARM_MAC_STAT_MIN 0 +#define PARM_MAC_STAT_MAX 1 + +#define PARM_SC_GAIN_DEF 7 +#define PARM_SC_GAIN_MIN 0 +#define PARM_SC_GAIN_MAX 7 + +#define PARM_PM_WOL_DEF 0 +#define PARM_PM_WOL_MIN 0 +#define PARM_PM_WOL_MAX 1 + +#define PARM_NMI_DISABLE_DEF 0 +#define PARM_NMI_DISABLE_MIN 0 +#define PARM_NMI_DISABLE_MAX 2 + +#define PARM_DMA_CACHE_DEF 0 +#define PARM_DMA_CACHE_MIN 0 +#define PARM_DMA_CACHE_MAX 15 + +#define PARM_PHY_LOOPBK_DEF 0 +#define PARM_PHY_LOOPBK_MIN 0 +#define PARM_PHY_LOOPBK_MAX 1 + + +#define PARM_MAC_ADDRESS_DEF { 0x00, 0x05, 0x3d, 0x00, 0x02, 0x00 } + + + + +/****************************************************************************** + Module parameter for disabling NMI + *****************************************************************************/ +static u32 et131x_nmi_disable = PARM_NMI_DISABLE_DEF; + +module_param ( et131x_nmi_disable, uint, 0 ); +MODULE_PARM_DESC( et131x_nmi_disable, "Disable NMI (0-2) [0]" ); + + +/***************************************************************************** + Module parameter for manual speed setting + ****************************************************************************/ +static u32 et131x_speed_set = PARM_SPEED_DUPLEX_DEF; +module_param (et131x_speed_set, uint, 0); +MODULE_PARM_DESC( et131x_speed_set, "Set Link speed and dublex manually (0-5) [0] \n 1 : 10Mb Half-Duplex \n 2 : 10Mb Full-Duplex \n 3 : 100Mb Half-Duplex \n 4 : 100Mb Full-Duplex \n 5 : 1000Mb Full-Duplex \n 0 : Auto Speed Auto Dublex"); + + +/****************************************************************************** + ROUTINE : et131x_config_parse + ****************************************************************************** + + DESCRIPTION : Parses a configuration from some location (module + parameters, for example) into the private adapter struct + + PARAMETERS : pAdapter - pointer to the private adapter struct + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_config_parse( ET131X_ADAPTER *pAdapter ) +{ + UINT8 macAddrDef[] = PARM_MAC_ADDRESS_DEF; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_config_parse" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + The NDIS driver uses the registry to store persistent per-device + configuration, and reads this configuration into the appropriate + elements of the private adapter structure on initialization. Because + Linux has no analog to the registry, use this function to initialize the + private adapter structure with a default configuration. + + One other possibility is to use a series of module parameters which can + be passed in by the caller when the module is initialized. However, this + implementation does not allow for seperate configurations in the event + multiple devices are present, and hence will not suffice. + + If another method is derived which addresses this problem, this is where + it should be implemented. + *************************************************************************/ + + /************************************************************************** + Set the private adapter struct with default values for the corresponding + parameters + *************************************************************************/ + if( et131x_speed_set != PARM_SPEED_DUPLEX_DEF ) + { + DBG_VERBOSE( et131x_dbginfo, "Speed set manually to : %d \n",et131x_speed_set ); + pAdapter->SpeedDuplex = et131x_speed_set; + } + else + { + pAdapter->SpeedDuplex = PARM_SPEED_DUPLEX_DEF; + } + + // pAdapter->SpeedDuplex = PARM_SPEED_DUPLEX_DEF; + + pAdapter->RegistryVlanTag = PARM_VLAN_TAG_DEF; + pAdapter->RegistryFlowControl = PARM_FLOW_CTL_DEF; + pAdapter->RegistryWOLLink = PARM_WOL_LINK_DEF; + pAdapter->RegistryWOLMatch = PARM_WOL_MATCH_DEF; + pAdapter->RegistryJumboPacket = PARM_JUMBO_PKT_DEF; + pAdapter->RegistryPhyComa = PARM_PHY_COMA_DEF; + pAdapter->RegistryRxNumBuffers = PARM_RX_NUM_BUFS_DEF; + pAdapter->RegistryRxTimeInterval = PARM_RX_TIME_INT_DEF; + pAdapter->RegistryTxNumBuffers = PARM_TX_NUM_BUFS_DEF; + pAdapter->RegistryTxTimeInterval = PARM_TX_TIME_INT_DEF; + pAdapter->RegistryRxMemEnd = PARM_RX_MEM_END_DEF; + pAdapter->RegistryMACStat = PARM_MAC_STAT_DEF; + pAdapter->RegistrySCGain = PARM_SC_GAIN_DEF; + pAdapter->RegistryPMWOL = PARM_PM_WOL_DEF; + + if( et131x_nmi_disable != PARM_NMI_DISABLE_DEF ) + { + pAdapter->RegistryNMIDisable = et131x_nmi_disable; + } + else + { + pAdapter->RegistryNMIDisable = PARM_NMI_DISABLE_DEF; + } + + pAdapter->RegistryDMACache = PARM_DMA_CACHE_DEF; + pAdapter->RegistryPhyLoopbk = PARM_PHY_LOOPBK_DEF; + + + /************************************************************************** + Set the MAC address to a default + *************************************************************************/ + memcpy( pAdapter->CurrentAddress, macAddrDef, ETH_ALEN ); + pAdapter->bOverrideAddress = FALSE; + + DBG_TRACE( et131x_dbginfo, + "Default MAC Address : %02x:%02x:%02x:%02x:%02x:%02x\n", + pAdapter->CurrentAddress[0], pAdapter->CurrentAddress[1], + pAdapter->CurrentAddress[2], pAdapter->CurrentAddress[3], + pAdapter->CurrentAddress[4], pAdapter->CurrentAddress[5] ); + + + /************************************************************************** + Decode SpeedDuplex + + Set up as if we are auto negotiating always and then change if we go + into force mode + *************************************************************************/ + pAdapter->AiForceSpeed = 0; // Auto speed + pAdapter->AiForceDpx = 0; // Auto FDX + + + /************************************************************************** + If we are the 10/100 device, and gigabit is somehow requested then + knock it down to 100 full. + *************************************************************************/ + if(( pAdapter->DeviceID == ET131X_PCI_DEVICE_ID_FAST ) && + ( pAdapter->SpeedDuplex == 5 )) + { + pAdapter->SpeedDuplex = 4; + } + + + switch( pAdapter->SpeedDuplex ) + { + case 1: // 10Mb Half-Duplex + pAdapter->AiForceSpeed = 10; + pAdapter->AiForceDpx = 1; + break; + + case 2: // 10Mb Full-Duplex + pAdapter->AiForceSpeed = 10; + pAdapter->AiForceDpx = 2; + break; + + case 3: // 100Mb Half-Duplex + pAdapter->AiForceSpeed = 100; + pAdapter->AiForceDpx = 1; + break; + + case 4: // 100Mb Full-Duplex + pAdapter->AiForceSpeed = 100; + pAdapter->AiForceDpx = 2; + break; + + case 5: // 1000Mb Full-Duplex + pAdapter->AiForceSpeed = 1000; + pAdapter->AiForceDpx = 2; + break; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + --- linux-2.6.27.orig/ubuntu/et131x/et131x_isr.c +++ linux-2.6.27/ubuntu/et131x/et131x_isr.c @@ -0,0 +1,656 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_isr.c - File which contains the ISR, ISR handler, and related routines + * for processing interrupts from the device. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/31 20:58:43 $ + $Revision: 1.13 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" +#include "ET1310_mac.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Prototypes for functions with local scope + *****************************************************************************/ + + + + +/****************************************************************************** + Defines for 2.4 compatibility with the new 2.6 IRQ handler return values + *****************************************************************************/ +#ifndef IRQ_RETVAL + +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) + +#endif /* IRQ_RETVAL */ + + + + +/****************************************************************************** + ROUTINE : et131x_isr + ****************************************************************************** + + DESCRIPTION : The Interrupt Service Routine for the driver. + + PARAMETERS : irq - the IRQ on which the interrupt was received. + dev_id - a buffer containing device-specific info (in + this case, a pointer to a net_device struct) + regs - + + RETURNS : For 2.4.x kernels - N/A + For 2.6.x kernels - A value indicating if the interrupt + was handled. + + REUSE INFORMATION : + + *****************************************************************************/ +irqreturn_t et131x_isr( int irq, void *dev_id ) +{ + BOOL_t handled = TRUE; + struct net_device *netdev = (struct net_device *)dev_id; + ET131X_ADAPTER *adapter = NULL; + INT_STATUS_t status; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_isr" ); + + + do + { + if(( netdev == NULL ) || ( !netif_device_present( netdev ))) + { + DBG_WARNING( et131x_dbginfo, + "No net_device struct or device not present\n" ); + handled = FALSE; + break; + } + + adapter = netdev_priv( netdev ); + + + /********************************************************************** + If the adapter is in low power state, then it should not recognize + any interrupt + + NOTE + *********************************************************************/ + + + /********************************************************************** + Disable Device Interrupts + *********************************************************************/ + et131x_disable_interrupts( adapter ); + + + /********************************************************************** + Get a copy of the value in the interrupt status register so we can + process the interrupting section + *********************************************************************/ + status.value = adapter->CSRAddress->global.int_status.value; + + if(( adapter->FlowControl == TxOnly ) || + ( adapter->FlowControl == Both )) + { + status.value &= ~INT_MASK_ENABLE; + } + else + { + status.value &= ~INT_MASK_ENABLE_NO_FLOW; + } + + + /********************************************************************** + Make sure this is our interrupt + *********************************************************************/ + if( !status.value ) + { +#ifdef ET131X_DBG + adapter->Stats.UnhandledInterruptsPerSec++; +#endif + handled = FALSE; + DBG_VERBOSE( et131x_dbginfo, "NOT OUR INTERRUPT\n" ); + et131x_enable_interrupts( adapter ); + break; + } + + /********************************************************************** + This is our interrupt, so process accordingly + *********************************************************************/ +#ifdef ET131X_DBG + if( status.bits.rxdma_xfr_done ) + { + adapter->Stats.RxDmaInterruptsPerSec++; + } + + if( status.bits.txdma_isr ) + { + adapter->Stats.TxDmaInterruptsPerSec++; + } +#endif + + if( status.bits.watchdog_interrupt ) + { + PMP_TCB pMpTcb = adapter->TxRing.CurrSendHead; + + if( pMpTcb ) + { + if( ++pMpTcb->PacketStaleCount > 1 ) + { + status.bits.txdma_isr = 1; + } + } + + if( adapter->RxRing.UnfinishedReceives ) + { + status.bits.rxdma_xfr_done = 1; + } + else if( pMpTcb == 0 ) + { + adapter->CSRAddress->global.watchdog_timer = 0; + } + + status.bits.watchdog_interrupt = 0; +#ifdef ET131X_DBG + adapter->Stats.WatchDogInterruptsPerSec++; +#endif + } + + if( status.value == 0 ) + { + /****************************************************************** + This interrupt has in some way been "handled" by the ISR. Either + it was a spurious Rx interrupt, or it was a Tx interrupt that + has been filtered by the ISR. + *****************************************************************/ + et131x_enable_interrupts( adapter ); + break; + } + + /********************************************************************** + We need to save the interrupt status value for use in our DPC. We + will clear the software copy of that in that routine. + *********************************************************************/ + adapter->Stats.InterruptStatus = status; + + + /********************************************************************** + Schedule the ISR handler as a bottom-half task in the kernel's + tq_immediate queue, and mark the queue for execution + *********************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) + schedule_task( &adapter->task ); +#else + schedule_work( &adapter->task ); +#endif + + } while( 0 ); + + return IRQ_RETVAL( handled ); +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_isr_handler + ****************************************************************************** + + DESCRIPTION : The ISR handler, scheduled to run in a deferred context + by the ISR. This is where the ISR's work actually gets + done. + + PARAMETERS : p_adapter - a pointer to the device's private adapter + structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_isr_handler( struct work_struct *work ) +{ + ET131X_ADAPTER *pAdapter = container_of( work, ET131X_ADAPTER, task ); + + INT_STATUS_t GlobStatus = pAdapter->Stats.InterruptStatus; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_isr_handler" ); + + + /************************************************************************** + These first two are by far the most common. Once handled, we clear + their two bits in the status word. If the word is now zero, we exit. + *************************************************************************/ + /************************************************************************** + Handle all the completed Transmit interrupts + *************************************************************************/ + if( GlobStatus.bits.txdma_isr ) + { + DBG_TX( et131x_dbginfo, "TXDMA_ISR interrupt\n" ); + et131x_handle_send_interrupt( pAdapter ); + } + + + /************************************************************************** + Handle all the completed Receives interrupts + *************************************************************************/ + if( GlobStatus.bits.rxdma_xfr_done ) + { + DBG_RX( et131x_dbginfo, "RXDMA_XFR_DONE interrupt\n" ); + et131x_handle_recv_interrupt( pAdapter ); + } + + GlobStatus.value &= 0xffffffd7; + + if( GlobStatus.value ) + { + + /********************************************************************** + Handle the TXDMA Error interrupt + *********************************************************************/ + if( GlobStatus.bits.txdma_err ) + { + TXDMA_ERROR_t TxDmaErr; + + + /****************************************************************** + Following read also clears the register (COR register) + *****************************************************************/ + TxDmaErr.value = pAdapter->CSRAddress->txdma.TxDmaError.value; + + DBG_WARNING( et131x_dbginfo, "TXDMA_ERR interrupt, error = %d\n", + TxDmaErr.value ); + } + + + /********************************************************************** + Handle Free Buffer Ring 0 and 1 Low interrupt + *********************************************************************/ + if( GlobStatus.bits.rxdma_fb_ring0_low || + GlobStatus.bits.rxdma_fb_ring1_low ) + { + /****************************************************************** + This indicates the number of unused buffers in RXDMA free buffer + ring 0 is <= the limit you programmed. Free buffer resources + need to be returned. Free buffers are consumed as packets are + passed from the network to the host. The host becomes aware of + the packets from the contents of the packet status ring. This + ring is queried when the packet done interrupt occurs. Packets + are then passed to the OS. When the OS is done with the packets + the resources can be returned to the ET1310 for re-use. This + interrupt is one method of returning resources. + *****************************************************************/ + DBG_WARNING( et131x_dbginfo, + "RXDMA_FB_RING0_LOW or " + "RXDMA_FB_RING1_LOW interrupt\n" ); + + + /****************************************************************** + If the user has flow control on, then we will send a pause + packet, otherwise just exit + *****************************************************************/ + if(( pAdapter->FlowControl == TxOnly ) || + ( pAdapter->FlowControl == Both )) + { + /************************************************************** + Tell the device to send a pause packet via the back pressure + register + *************************************************************/ + if( pAdapter->CSRAddress->global.pm_csr.bits.pm_phy_sw_coma == 0 ) + { + TXMAC_BP_CTRL_t bp_ctrl; + + bp_ctrl.bits.bp_req = 1; + bp_ctrl.bits.bp_xonxoff = 1; + + pAdapter->CSRAddress->txmac.bp_ctrl.value = bp_ctrl.value; + } + } + } + + + /********************************************************************** + Handle Packet Status Ring Low Interrupt + *********************************************************************/ + if( GlobStatus.bits.rxdma_pkt_stat_ring_low ) + { + DBG_WARNING( et131x_dbginfo, + "RXDMA_PKT_STAT_RING_LOW interrupt\n" ); + + + /****************************************************************** + Same idea as with the two Free Buffer Rings. Packets going from + the network to the host each consume a free buffer resource and + a packet status resource. These resoures are passed to the OS. + When the OS is done with the resources, they need to be returned + to the ET1310. This is one method of returning the resources. + *****************************************************************/ + } + + + /********************************************************************** + Handle RXDMA Error Interrupt + *********************************************************************/ + if( GlobStatus.bits.rxdma_err ) + { + /****************************************************************** + The rxdma_error interrupt is sent when a time-out on a request + issued by the JAGCore has occurred or a completion is returned + with an un-successful status. In both cases the request is + considered complete. The JAGCore will automatically re-try the + request in question. Normally information on events like these + are sent to the host using the "Advanced Error Reporting" + capability. This interrupt is another way of getting similar + information. The only thing required is to clear the interrupt + by reading the ISR in the global resources. The JAGCore will do + a re-try on the request. Normally you should never see this + interrupt. If you start to see this interrupt occurring + frequently then something bad has occurred. + A reset might be the thing to do. + *****************************************************************/ + // TRAP(); + + pAdapter->TxMacTest = pAdapter->CSRAddress->txmac.tx_test; + DBG_WARNING( et131x_dbginfo, + "RxDMA_ERR interrupt, error %x\n", + pAdapter->TxMacTest.value ); + } + + + /********************************************************************** + Handle the Wake on LAN Event + *********************************************************************/ + if( GlobStatus.bits.wake_on_lan ) + { + /****************************************************************** + This is a secondary interrupt for wake on LAN. The driver + should never see this, if it does, something serious is wrong. + We will TRAP the message when we are in DBG mode, otherwise we + will ignore it. + *****************************************************************/ + DBG_ERROR( et131x_dbginfo, "WAKE_ON_LAN interrupt\n" ); + } + + + /********************************************************************** + Handle the PHY interrupt + *********************************************************************/ + if( GlobStatus.bits.phy_interrupt ) + { + MI_BMSR_t BmsrInts, BmsrData; + MI_ISR_t myIsr; + + DBG_VERBOSE( et131x_dbginfo, "PHY interrupt\n" ); + + /****************************************************************** + If we are in coma mode when we get this interrupt, we need to + disable it. + *****************************************************************/ + if( pAdapter->CSRAddress->global.pm_csr.bits.phy_sw_coma == 1 ) + { + /************************************************************** + Check to see if we are in coma mode and if so, disable it + because we will not be able to read PHY values until we are + out. + *************************************************************/ + DBG_VERBOSE( et131x_dbginfo, "Device is in COMA mode, " + "need to wake up\n" ); + DisablePhyComa( pAdapter ); + } + + + /****************************************************************** + Read the PHY ISR to clear the reason for the interrupt. + *****************************************************************/ + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, isr ), &myIsr.value ); + + if( !pAdapter->ReplicaPhyLoopbk ) + { + MiRead( pAdapter, (UINT8)pAdapter->Stats.xcvr_addr, + (UINT8)FIELD_OFFSET( MI_REGS_t, bmsr ), &BmsrData.value ); + + BmsrInts.value = pAdapter->Bmsr.value ^ BmsrData.value; + pAdapter->Bmsr.value = BmsrData.value; + + DBG_VERBOSE( et131x_dbginfo, + "Bmsr.value = 0x%04x," + "Bmsr_ints.value = 0x%04x\n", + BmsrData.value, + BmsrInts.value ); + + + /************************************************************** + Do all the cable in / cable out stuff + *************************************************************/ + et131x_Mii_check( pAdapter, BmsrData, BmsrInts ); + } + } + + + /********************************************************************** + Let's move on to the TxMac + *********************************************************************/ + if( GlobStatus.bits.txmac_interrupt ) + { + pAdapter->TxRing.TxMacErr.value = pAdapter->CSRAddress->txmac.err.value; + + /****************************************************************** + When any of the errors occur and TXMAC generates an interrupt to + report these errors, it usually means that TXMAC has detected an + error in the data stream retrieved from the on-chip Tx Q. All of + these errors are catastrophic and TXMAC won’t be able to recover + data when these errors occur. In a nutshell, the whole Tx path + will have to be reset and re-configured afterwards. + *****************************************************************/ + DBG_WARNING( et131x_dbginfo, + "TXMAC interrupt, error 0x%08x\n", + pAdapter->TxRing.TxMacErr.value ); + + + /******************************************************************* + If we are debugging, we want to see this error, otherwise we just + want the device to be reset and continue + *****************************************************************/ + //DBG_TRAP(); + + } + + /********************************************************************** + Handle RXMAC Interrupt + *********************************************************************/ + if( GlobStatus.bits.rxmac_interrupt ) + { + /****************************************************************** + These interrupts are catastrophic to the device, what we need to + do is disable the interrupts and set the flag to cause us to + reset so we can solve this issue. + ******************************************************************/ + // MP_SET_FLAG( pAdapter, fMP_ADAPTER_HARDWARE_ERROR ); + + DBG_WARNING( et131x_dbginfo, + "RXMAC interrupt, error 0x%08x. Requesting reset\n", + pAdapter->CSRAddress->rxmac.err_reg.value ); + + DBG_WARNING( et131x_dbginfo, + "Enable 0x%08x, Diag 0x%p\n", + pAdapter->CSRAddress->rxmac.ctrl.value, + &pAdapter->CSRAddress->rxmac.rxq_diag ); + + + /******************************************************************* + If we are debugging, we want to see this error, otherwise we just + want the device to be reset and continue + *****************************************************************/ + // TRAP(); + } + + /********************************************************************** + Handle MAC_STAT Interrupt + *********************************************************************/ + if( GlobStatus.bits.mac_stat_interrupt ) + { + /****************************************************************** + This means at least one of the un-masked counters in the MAC_STAT + block has rolled over. Use this to maintain the top, software + managed bits of the counter(s). + *****************************************************************/ + DBG_VERBOSE( et131x_dbginfo, "MAC_STAT interrupt\n" ); + HandleMacStatInterrupt( pAdapter ); + } + + + /********************************************************************** + Handle SLV Timeout Interrupt + *********************************************************************/ + if( GlobStatus.bits.slv_timeout ) + { + /****************************************************************** + This means a timeout has occured on a read or write request to + one of the JAGCore registers. The Global Resources block has + terminated the request and on a read request, returned a "fake" + value. The most likely reasons are: Bad Address or the + addressed module is in a power-down state and can't respond. + *****************************************************************/ + DBG_VERBOSE( et131x_dbginfo, "SLV_TIMEOUT interrupt\n" ); + } + } + + + if( pAdapter->PoMgmt.PowerState == NdisDeviceStateD0 ) + { + et131x_enable_interrupts( pAdapter ); + } + + return; +} +/*===========================================================================*/ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_rx.h +++ linux-2.6.27/ubuntu/et131x/ET1310_rx.h @@ -0,0 +1,488 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_rx.h - Defines, structs, enums, prototypes, etc. pertaining to data + * reception. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 18:43:45 $ + $Revision: 1.10 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET1310_RX_H__ +#define __ET1310_RX_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/****************************************************************************** + INCLUDES + *****************************************************************************/ +#include "ET1310_common.h" + +#define USE_FBR0 TRUE + +#ifdef USE_FBR0 +//#define FBR0_BUFFER_SIZE 256 +#endif + +//#define FBR1_BUFFER_SIZE 2048 + +#define FBR_CHUNKS 32 + +#define MAX_DESC_PER_RING_RX 1024 + + + + +/****************************************************************************** + number of RFDs - default and min + *****************************************************************************/ +#ifdef USE_FBR0 + #define RFD_LOW_WATER_MARK 40 + #define NIC_MIN_NUM_RFD 64 + #define NIC_DEFAULT_NUM_RFD 1024 +#else + #define RFD_LOW_WATER_MARK 20 + #define NIC_MIN_NUM_RFD 64 + #define NIC_DEFAULT_NUM_RFD 256 +#endif + +#define NUM_PACKETS_HANDLED 256 + +#define ALCATEL_BAD_STATUS 0xe47f0000 +#define ALCATEL_MULTICAST_PKT 0x01000000 +#define ALCATEL_BROADCAST_PKT 0x02000000 + + + + +/****************************************************************************** + typedefs for Free Buffer Descriptors + *****************************************************************************/ +typedef union _FBR_WORD2_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:22; //bits 10-31 + UINT32 bi:10; //bits 0-9(Buffer Index) + #else + UINT32 bi:10; //bits 0-9(Buffer Index) + UINT32 reserved:22; //bit 10-31 + #endif + } bits; +} +FBR_WORD2_t, *PFBR_WORD2_t; + +typedef struct _FBR_DESC_t +{ + UINT32 addr_lo; + UINT32 addr_hi; + FBR_WORD2_t word2; +} +FBR_DESC_t, *PFBR_DESC_t; +/*===========================================================================*/ + + + + +/****************************************************************************** + Typedefs for Packet Status Ring Descriptors + *****************************************************************************/ +typedef union _PKT_STAT_DESC_WORD0_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + // top 16 bits are from the Alcatel Status Word as enumerated in + // PE-MCXMAC Data Sheet IPD DS54 0210-1 (also IPD-DS80 0205-2) +#if 0 + UINT32 asw_trunc:1; //bit 31(Rx frame truncated) +#endif + UINT32 asw_long_evt:1; //bit 31(Rx long event) + UINT32 asw_VLAN_tag:1; //bit 30(VLAN tag detected) + UINT32 asw_unsupported_op:1; //bit 29(unsupported OP code) + UINT32 asw_pause_frame:1; //bit 28(is a pause frame) + UINT32 asw_control_frame:1; //bit 27(is a control frame) + UINT32 asw_dribble_nibble:1; //bit 26(spurious bits after EOP) + UINT32 asw_broadcast:1; //bit 25(has a broadcast address) + UINT32 asw_multicast:1; //bit 24(has a multicast address) + UINT32 asw_OK:1; //bit 23(valid CRC + no code error) + UINT32 asw_too_long:1; //bit 22(frame length > 1518 bytes) + UINT32 asw_len_chk_err:1; //bit 21(frame length field incorrect) + UINT32 asw_CRC_err:1; //bit 20(CRC error) + UINT32 asw_code_err:1; //bit 19(one or more nibbles signalled as errors) + UINT32 asw_false_carrier_event:1; //bit 18(bad carrier since last good packet) + UINT32 asw_RX_DV_event:1; //bit 17(short receive event detected) + UINT32 asw_prev_pkt_dropped:1; //bit 16(e.g. IFG too small on previous) + UINT32 unused:5; //bits 11-15 + UINT32 vp:1; //bit 10(VLAN Packet) + UINT32 jp:1; //bit 9(Jumbo Packet) + UINT32 ft:1; //bit 8(Frame Truncated) + UINT32 drop:1; //bit 7(Drop packet) + UINT32 rxmac_error:1; //bit 6(RXMAC Error Indicator) + UINT32 wol:1; //bit 5(WOL Event) + UINT32 tcpp:1; //bit 4(TCP checksum pass) + UINT32 tcpa:1; //bit 3(TCP checksum assist) + UINT32 ipp:1; //bit 2(IP checksum pass) + UINT32 ipa:1; //bit 1(IP checksum assist) + UINT32 hp:1; //bit 0(hash pass) + #else + UINT32 hp:1; //bit 0(hash pass) + UINT32 ipa:1; //bit 1(IP checksum assist) + UINT32 ipp:1; //bit 2(IP checksum pass) + UINT32 tcpa:1; //bit 3(TCP checksum assist) + UINT32 tcpp:1; //bit 4(TCP checksum pass) + UINT32 wol:1; //bit 5(WOL Event) + UINT32 rxmac_error:1; //bit 6(RXMAC Error Indicator) + UINT32 drop:1; //bit 7(Drop packet) + UINT32 ft:1; //bit 8(Frame Truncated) + UINT32 jp:1; //bit 9(Jumbo Packet) + UINT32 vp:1; //bit 10(VLAN Packet) + UINT32 unused:5; //bits 11-15 + UINT32 asw_prev_pkt_dropped:1; //bit 16(e.g. IFG too small on previous) + UINT32 asw_RX_DV_event:1; //bit 17(short receive event detected) + UINT32 asw_false_carrier_event:1; //bit 18(bad carrier since last good packet) + UINT32 asw_code_err:1; //bit 19(one or more nibbles signalled as errors) + UINT32 asw_CRC_err:1; //bit 20(CRC error) + UINT32 asw_len_chk_err:1; //bit 21(frame length field incorrect) + UINT32 asw_too_long:1; //bit 22(frame length > 1518 bytes) + UINT32 asw_OK:1; //bit 23(valid CRC + no code error) + UINT32 asw_multicast:1; //bit 24(has a multicast address) + UINT32 asw_broadcast:1; //bit 25(has a broadcast address) + UINT32 asw_dribble_nibble:1; //bit 26(spurious bits after EOP) + UINT32 asw_control_frame:1; //bit 27(is a control frame) + UINT32 asw_pause_frame:1; //bit 28(is a pause frame) + UINT32 asw_unsupported_op:1; //bit 29(unsupported OP code) + UINT32 asw_VLAN_tag:1; //bit 30(VLAN tag detected) + UINT32 asw_long_evt:1; //bit 31(Rx long event) +#if 0 + UINT32 asw_trunc:1; //bit 31(Rx frame truncated) +#endif + #endif + } bits; +} +PKT_STAT_DESC_WORD0_t, *PPKT_STAT_WORD0_t; + +typedef union _PKT_STAT_DESC_WORD1_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:4; //bits 28-31 + UINT32 ri:2; //bits 26-27(Ring Index) + UINT32 bi:10; //bits 16-25(Buffer Index) + UINT32 length:16; //bit 0-15(length in bytes) + #else + UINT32 length:16; //bit 0-15(length in bytes) + UINT32 bi:10; //bits 16-25(Buffer Index) + UINT32 ri:2; //bits 26-27(Ring Index) + UINT32 unused:4; //bits 28-31 + #endif + } bits; +} +PKT_STAT_DESC_WORD1_t, *PPKT_STAT_WORD1_t; + +typedef struct _PKT_STAT_DESC_t +{ + PKT_STAT_DESC_WORD0_t word0; + PKT_STAT_DESC_WORD1_t word1; +} +PKT_STAT_DESC_t, *PPKT_STAT_DESC_t; +/*===========================================================================*/ + + + + +/****************************************************************************** + Typedefs for the RX DMA status word + *****************************************************************************/ +/****************************************************************************** + RXSTAT_WORD0_t structure holds part of the status bits of the Rx DMA engine + that get copied out to memory by the ET-1310. Word 0 is a 32 bit word which + contains Free Buffer ring 0 and 1 available offset. + *****************************************************************************/ +typedef union _rxstat_word0_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 FBR1unused:5; //bits 27-31 + UINT32 FBR1wrap:1; //bit 26 + UINT32 FBR1offset:10; //bits 16-25 + UINT32 FBR0unused:5; //bits 11-15 + UINT32 FBR0wrap:1; //bit 10 + UINT32 FBR0offset:10; //bits 0-9 + #else + UINT32 FBR0offset:10; //bits 0-9 + UINT32 FBR0wrap:1; //bit 10 + UINT32 FBR0unused:5; //bits 11-15 + UINT32 FBR1offset:10; //bits 16-25 + UINT32 FBR1wrap:1; //bit 26 + UINT32 FBR1unused:5; //bits 27-31 + #endif + } bits; +}RXSTAT_WORD0_t, *PRXSTAT_WORD0_t; + + + + +/****************************************************************************** + RXSTAT_WORD1_t structure holds part of the status bits of the Rx DMA engine + that get copied out to memory by the ET-1310. Word 3 is a 32 bit word which + contains the Packet Status Ring available offset. + *****************************************************************************/ +typedef union _rxstat_word1_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 PSRunused:3; //bits 29-31 + UINT32 PSRwrap:1; //bit 28 + UINT32 PSRoffset:12; //bits 16-27 + UINT32 reserved:16; //bits 0-15 + #else + UINT32 reserved:16; //bits 0-15 + UINT32 PSRoffset:12; //bits 16-27 + UINT32 PSRwrap:1; //bit 28 + UINT32 PSRunused:3; //bits 29-31 + #endif + } bits; +}RXSTAT_WORD1_t, *PRXSTAT_WORD1_t; + + + + +/****************************************************************************** + RX_STATUS_BLOCK_t is sructure representing the status of the Rx DMA engine + it sits in free memory, and is pointed to by 0x101c / 0x1020 + *****************************************************************************/ + +typedef struct _rx_status_block_t +{ + RXSTAT_WORD0_t Word0; + RXSTAT_WORD1_t Word1; +} +RX_STATUS_BLOCK_t, *PRX_STATUS_BLOCK_t; + + + + +/****************************************************************************** + Structure for look-up table holding free buffer ring pointers + *****************************************************************************/ +typedef struct _FbrLookupTable +{ + void *Va [MAX_DESC_PER_RING_RX]; + void *Buffer1 [MAX_DESC_PER_RING_RX]; + void *Buffer2 [MAX_DESC_PER_RING_RX]; + UINT32 PAHigh [MAX_DESC_PER_RING_RX]; + UINT32 PALow [MAX_DESC_PER_RING_RX]; +} FBRLOOKUPTABLE, *PFBRLOOKUPTABLE; + +typedef enum { + ONE_PACKET_INTERRUPT, + FOUR_PACKET_INTERRUPT +} +eRX_INTERRUPT_STATE_t, *PeRX_INTERRUPT_STATE_t; + + + + +/****************************************************************************** + Structure to hold the skb's in a list + *****************************************************************************/ +typedef struct rx_skb_list_elem +{ + struct list_head skb_list_elem; + dma_addr_t dma_addr; + struct sk_buff *skb; +} RX_SKB_LIST_ELEM, *PRX_SKB_LIST_ELEM; + + + + +/****************************************************************************** + RX_RING_t is sructure representing the adaptor's local reference(s) to the + rings + *****************************************************************************/ +typedef struct _rx_ring_t +{ +#ifdef USE_FBR0 + void *pFbr0RingVa; + dma_addr_t pFbr0RingPa; + void *Fbr0MemVa[ MAX_DESC_PER_RING_RX / FBR_CHUNKS ]; + dma_addr_t Fbr0MemPa[ MAX_DESC_PER_RING_RX / FBR_CHUNKS ]; + UINT64 Fbr0Realpa; + UINT64 Fbr0offset; + RXDMA_FBR_FULL_OFFSET_t local_Fbr0_full; + UINT32 Fbr0NumEntries; + UINT32 Fbr0BufferSize; +#endif + void *pFbr1RingVa; + dma_addr_t pFbr1RingPa; + void *Fbr1MemVa[ MAX_DESC_PER_RING_RX / FBR_CHUNKS ]; + dma_addr_t Fbr1MemPa[ MAX_DESC_PER_RING_RX / FBR_CHUNKS ]; + UINT64 Fbr1Realpa; + UINT64 Fbr1offset; + FBRLOOKUPTABLE *Fbr[2]; + RXDMA_FBR_FULL_OFFSET_t local_Fbr1_full; + UINT32 Fbr1NumEntries; + UINT32 Fbr1BufferSize; + + void *pPSRingVa; + dma_addr_t pPSRingPa; + UINT64 pPSRingRealPa; + UINT64 pPSRingOffset; + RXDMA_PSR_FULL_OFFSET_t local_psr_full; + UINT32 PsrNumEntries; + + void *pRxStatusVa; + dma_addr_t pRxStatusPa; + UINT64 RxStatusRealPA; + UINT64 RxStatusOffset; + + struct list_head RecvBufferPool; + + + /************************************************************************** + RECV + *************************************************************************/ + struct list_head RecvList; + struct list_head RecvPendingList; + UINT32 nReadyRecv; + + UINT32 NumRfd; + + BOOL_t UnfinishedReceives; + + struct list_head RecvPacketPool; + + + /************************************************************************** + lookaside lists + *************************************************************************/ + struct kmem_cache *RecvLookaside; +} +RX_RING_t, *PRX_RING_t; + + + + +/****************************************************************************** + Forward reference of RFD + *****************************************************************************/ +struct _MP_RFD; + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + + + +/****************************************************************************** + PROTOTYPES for Initialization + *****************************************************************************/ +int et131x_rx_dma_memory_alloc( struct et131x_adapter *adapter ); +void et131x_rx_dma_memory_free( struct et131x_adapter *adapter ); +int et131x_rfd_resources_alloc( struct et131x_adapter *adapter, struct _MP_RFD *pMpRfd ); +void et131x_rfd_resources_free( struct et131x_adapter *adapter, struct _MP_RFD *pMpRfd ); +int et131x_init_recv( struct et131x_adapter *adapter ); + +void ConfigRxDmaRegs( struct et131x_adapter *pAdapter ); +void SetRxDmaTimer( struct et131x_adapter *pAdapter ); +void et131x_rx_dma_disable( struct et131x_adapter *pAdapter ); +void et131x_rx_dma_enable( struct et131x_adapter *pAdapter ); + +void et131x_reset_recv( struct et131x_adapter *pAdapter ); + +void et131x_handle_recv_interrupt( struct et131x_adapter *pAdapter ); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ET1310_RX_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_address_map.h +++ linux-2.6.27/ubuntu/et131x/ET1310_address_map.h @@ -0,0 +1,3216 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_address_map.h - Contains the register mapping for the ET1310 + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 18:43:43 $ + $Revision: 1.8 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef _ET1310_ADDRESS_MAP_H_ +#define _ET1310_ADDRESS_MAP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + some typedefs for compiler + *****************************************************************************/ +typedef s8 INT8, *PINT8; +typedef s16 INT16, *PINT16; +typedef s32 INT32, *PINT32; +typedef s64 INT64, *PINT64; + +typedef u8 UINT8, *PUINT8; +typedef u16 UINT16, *PUINT16; +typedef u32 UINT32, *PUINT32; +typedef u64 UINT64, *PUINT64; + +typedef u8 UCHAR, *PUCHAR; + + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF GLOBAL REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for tx queue start address reg in global address map + located at address 0x0000 + *****************************************************************************/ +typedef union _TXQ_START_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 txq_start:10; //bits 0-9 + #else + UINT32 txq_start:10; //bits 0-9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +TXQ_START_ADDR_t, *PTXQ_START_ADDR_t; + + +/****************************************************************************** + structure for tx queue end address reg in global address map + located at address 0x0004 + *****************************************************************************/ +typedef union _TXQ_END_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 txq_end:10; //bits 0-9 + #else + UINT32 txq_end:10; //bits 0-9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +TXQ_END_ADDR_t, *PTXQ_END_ADDR_t; + + +/****************************************************************************** + structure for rx queue start address reg in global address map + located at address 0x0008 + *****************************************************************************/ +typedef union _RXQ_START_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 rxq_start_addr:10; //bits 0-9 + #else + UINT32 rxq_start_addr:10; //bits 0-9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +RXQ_START_ADDR_t, *PRXQ_START_ADDR_t; + + +/****************************************************************************** + structure for rx queue end address reg in global address map + located at address 0x000C + *****************************************************************************/ +typedef union _RXQ_END_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 rxq_end_addr:10; //bits 0-9 + #else + UINT32 rxq_end_addr:10; //bits 0-9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +RXQ_END_ADDR_t, *PRXQ_END_ADDR_t; + + +/****************************************************************************** + structure for power management control status reg in global address map + located at address 0x0010 + *****************************************************************************/ +typedef union _PM_CSR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 pm_jagcore_rx_rdy:1; //bit 9 + UINT32 pm_jagcore_tx_rdy:1; //bit 8 + UINT32 pm_phy_lped_en:1; //bit 7 + UINT32 pm_phy_sw_coma:1; //bit 6 + UINT32 pm_rxclk_gate:1; //bit 5 + UINT32 pm_txclk_gate:1; //bit 4 + UINT32 pm_sysclk_gate:1; //bit 3 + UINT32 pm_jagcore_rx_en:1; //bit 2 + UINT32 pm_jagcore_tx_en:1; //bit 1 + UINT32 pm_gigephy_en:1; //bit 0 + #else + UINT32 pm_gigephy_en:1; //bit 0 + UINT32 pm_jagcore_tx_en:1; //bit 1 + UINT32 pm_jagcore_rx_en:1; //bit 2 + UINT32 pm_sysclk_gate:1; //bit 3 + UINT32 pm_txclk_gate:1; //bit 4 + UINT32 pm_rxclk_gate:1; //bit 5 + UINT32 pm_phy_sw_coma:1; //bit 6 + UINT32 pm_phy_lped_en:1; //bit 7 + UINT32 pm_jagcore_tx_rdy:1; //bit 8 + UINT32 pm_jagcore_rx_rdy:1; //bit 9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +PM_CSR_t, *PPM_CSR_t; + + +/****************************************************************************** + structure for interrupt status reg in global address map + located at address 0x0018 + *****************************************************************************/ +typedef union _INT_STATUS_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused5:11; //bits 21-31 + UINT32 slv_timeout:1; //bit 20 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 phy_interrupt:1; //bit 16 + UINT32 wake_on_lan:1; //bit 15 + UINT32 watchdog_interrupt:1; //bit 14 + UINT32 unused4:4; //bits 10-13 + UINT32 rxdma_err:1; //bit 9 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 txdma_err:1; //bit 4 + UINT32 txdma_isr:1; //bit 3 + UINT32 unused3:1; //bit 2 + UINT32 unused2:1; //bit 1 + UINT32 unused1:1; //bit 0 + #else + UINT32 unused1:1; //bit 0 + UINT32 unused2:1; //bit 1 + UINT32 unused3:1; //bit 2 + UINT32 txdma_isr:1; //bit 3 + UINT32 txdma_err:1; //bit 4 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_err:1; //bit 9 + UINT32 unused4:4; //bits 10-13 + UINT32 watchdog_interrupt:1; //bit 14 + UINT32 wake_on_lan:1; //bit 15 + UINT32 phy_interrupt:1; //bit 16 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 slv_timeout:1; //bit 20 + UINT32 unused5:11; //bits 21-31 + #endif + } bits; +} +INT_STATUS_t, *PINT_STATUS_t; + + +/****************************************************************************** + structure for interrupt mask reg in global address map + located at address 0x001C + *****************************************************************************/ +typedef union _INT_MASK_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused5:11; //bits 21-31 + UINT32 slv_timeout:1; //bit 20 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 phy_interrupt:1; //bit 16 + UINT32 wake_on_lan:1; //bit 15 + UINT32 unused4:5; //bits 10-14 + UINT32 rxdma_err:1; //bit 9 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 txdma_err:1; //bit 4 + UINT32 txdma_isr:1; //bit 3 + UINT32 unused3:1; //bit 2 + UINT32 unused2:1; //bit 1 + UINT32 unused1:1; //bit 0 + #else + UINT32 unused1:1; //bit 0 + UINT32 unused2:1; //bit 1 + UINT32 unused3:1; //bit 2 + UINT32 txdma_isr:1; //bit 3 + UINT32 txdma_err:1; //bit 4 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_err:1; //bit 9 + UINT32 unused4:5; //bits 10-14 + UINT32 wake_on_lan:1; //bit 15 + UINT32 phy_interrupt:1; //bit 16 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 slv_timeout:1; //bit 20 + UINT32 unused5:11; //bits 21-31 + #endif + } bits; +} +INT_MASK_t, *PINT_MASK_t; + + +/****************************************************************************** + structure for interrupt alias clear mask reg in global address map + located at address 0x0020 + *****************************************************************************/ +typedef union _INT_ALIAS_CLR_EN_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused5:11; //bits 21-31 + UINT32 slv_timeout:1; //bit 20 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 phy_interrupt:1; //bit 16 + UINT32 wake_on_lan:1; //bit 15 + UINT32 watchdog_interrupt:1; //bit 14 + UINT32 unused4:4; //bits 10-13 + UINT32 rxdma_err:1; //bit 9 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 txdma_err:1; //bit 4 + UINT32 txdma_isr:1; //bit 3 + UINT32 unused3:1; //bit 2 + UINT32 unused2:1; //bit 1 + UINT32 unused1:1; //bit 0 + #else + UINT32 unused1:1; //bit 0 + UINT32 unused2:1; //bit 1 + UINT32 unused3:1; //bit 2 + UINT32 txdma_isr:1; //bit 3 + UINT32 txdma_err:1; //bit 4 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_err:1; //bit 9 + UINT32 unused4:4; //bits 10-13 + UINT32 watchdog_interrupt:1; //bit 14 + UINT32 wake_on_lan:1; //bit 15 + UINT32 phy_interrupt:1; //bit 16 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 slv_timeout:1; //bit 20 + UINT32 unused5:11; //bits 21-31 + #endif + } bits; +} +INT_ALIAS_CLR_EN_t, *PINT_ALIAS_CLR_EN_t; + + +/****************************************************************************** + structure for interrupt status alias reg in global address map + located at address 0x0024 + *****************************************************************************/ +typedef union _INT_STATUS_ALIAS_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused5:11; //bits 21-31 + UINT32 slv_timeout:1; //bit 20 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 phy_interrupt:1; //bit 16 + UINT32 wake_on_lan:1; //bit 15 + UINT32 watchdog_interrupt:1; //bit 14 + UINT32 unused4:4; //bits 10-13 + UINT32 rxdma_err:1; //bit 9 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 txdma_err:1; //bit 4 + UINT32 txdma_isr:1; //bit 3 + UINT32 unused3:1; //bit 2 + UINT32 unused2:1; //bit 1 + UINT32 unused1:1; //bit 0 + #else + UINT32 unused1:1; //bit 0 + UINT32 unused2:1; //bit 1 + UINT32 unused3:1; //bit 2 + UINT32 txdma_isr:1; //bit 3 + UINT32 txdma_err:1; //bit 4 + UINT32 rxdma_xfr_done:1; //bit 5 + UINT32 rxdma_fb_ring0_low:1; //bit 6 + UINT32 rxdma_fb_ring1_low:1; //bit 7 + UINT32 rxdma_pkt_stat_ring_low:1; //bit 8 + UINT32 rxdma_err:1; //bit 9 + UINT32 unused4:4; //bits 10-13 + UINT32 watchdog_interrupt:1; //bit 14 + UINT32 wake_on_lan:1; //bit 15 + UINT32 phy_interrupt:1; //bit 16 + UINT32 txmac_interrupt:1; //bit 17 + UINT32 rxmac_interrupt:1; //bit 18 + UINT32 mac_stat_interrupt:1; //bit 19 + UINT32 slv_timeout:1; //bit 20 + UINT32 unused5:11; //bits 21-31 + #endif + } bits; +} +INT_STATUS_ALIAS_t, *PINT_STATUS_ALIAS_t; + + +/****************************************************************************** + structure for software reset reg in global address map + located at address 0x0028 + *****************************************************************************/ +typedef union _SW_RESET_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 selfclr_disable:1; //bit 31 + UINT32 unused:24; //bits 7-30 + UINT32 mmc_sw_reset:1; //bit 6 + UINT32 mac_stat_sw_reset:1; //bit 5 + UINT32 mac_sw_reset:1; //bit 4 + UINT32 rxmac_sw_reset:1; //bit 3 + UINT32 txmac_sw_reset:1; //bit 2 + UINT32 rxdma_sw_reset:1; //bit 1 + UINT32 txdma_sw_reset:1; //bit 0 + #else + UINT32 txdma_sw_reset:1; //bit 0 + UINT32 rxdma_sw_reset:1; //bit 1 + UINT32 txmac_sw_reset:1; //bit 2 + UINT32 rxmac_sw_reset:1; //bit 3 + UINT32 mac_sw_reset:1; //bit 4 + UINT32 mac_stat_sw_reset:1; //bit 5 + UINT32 mmc_sw_reset:1; //bit 6 + UINT32 unused:24; //bits 7-30 + UINT32 selfclr_disable:1; //bit 31 + #endif + } bits; +} +SW_RESET_t, *PSW_RESET_t; + + +/****************************************************************************** + structure for SLV Timer reg in global address map + located at address 0x002C + *****************************************************************************/ +typedef union _SLV_TIMER_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:8; //bits 24-31 + UINT32 timer_ini:24; //bits 0-23 + #else + UINT32 timer_ini:24; //bits 0-23 + UINT32 unused:8; //bits 24-31 + #endif + } bits; +} +SLV_TIMER_t, *PSLV_TIMER_t; + + +/****************************************************************************** + structure for MSI Configuration reg in global address map + located at address 0x0030 + *****************************************************************************/ +typedef union _MSI_CONFIG_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused1:13; //bits 19-31 + UINT32 msi_tc:3; //bits 16-18 + UINT32 unused2:11; //bits 5-15 + UINT32 msi_vector:5; //bits 0-4 + #else + UINT32 msi_vector:5; //bits 0-4 + UINT32 unused2:11; //bits 5-15 + UINT32 msi_tc:3; //bits 16-18 + UINT32 unused1:13; //bits 19-31 + #endif + } bits; +} +MSI_CONFIG_t, *PMSI_CONFIG_t; + + +/****************************************************************************** + structure for Loopback reg in global address map + located at address 0x0034 + *****************************************************************************/ +typedef union _LOOPBACK_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:30; //bits 2-31 + UINT32 dma_loopback:1; //bit 1 + UINT32 mac_loopback:1; //bit 0 + #else + UINT32 mac_loopback:1; //bit 0 + UINT32 dma_loopback:1; //bit 1 + UINT32 unused:30; //bits 2-31 + #endif + } bits; +} +LOOPBACK_t, *PLOOPBACK_t; + + +/****************************************************************************** + GLOBAL Module of JAGCore Address Mapping + Located at address 0x0000 + *****************************************************************************/ +typedef struct _GLOBAL_t +{ //Location: + TXQ_START_ADDR_t txq_start_addr; // 0x0000 + TXQ_END_ADDR_t txq_end_addr; // 0x0004 + RXQ_START_ADDR_t rxq_start_addr; // 0x0008 + RXQ_END_ADDR_t rxq_end_addr; // 0x000C + PM_CSR_t pm_csr; // 0x0010 + UINT32 unused; // 0x0014 + INT_STATUS_t int_status; // 0x0018 + INT_MASK_t int_mask; // 0x001C + INT_ALIAS_CLR_EN_t int_alias_clr_en; // 0x0020 + INT_STATUS_ALIAS_t int_status_alias; // 0x0024 + SW_RESET_t sw_reset; // 0x0028 + SLV_TIMER_t slv_timer; // 0x002C + MSI_CONFIG_t msi_config; // 0x0030 + LOOPBACK_t loopback; // 0x0034 + UINT32 watchdog_timer; // 0x0038 +} +GLOBAL_t, *PGLOBAL_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF GLOBAL REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF TXDMA REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for txdma control status reg in txdma address map + located at address 0x1000 + *****************************************************************************/ +typedef union _TXDMA_CSR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused2:19; //bits 13-31 + UINT32 traffic_class:4; //bits 9-12 + UINT32 sngl_epkt_mode:1; //bit 8 + UINT32 cache_thrshld:4; //bits 4-7 + UINT32 unused1:2; //bits 2-3 + UINT32 drop_TLP_disable:1; //bit 1 + UINT32 halt:1; //bit 0 + #else + UINT32 halt:1; //bit 0 + UINT32 drop_TLP_disable:1; //bit 1 + UINT32 unused1:2; //bits 2-3 + UINT32 cache_thrshld:4; //bits 4-7 + UINT32 sngl_epkt_mode:1; //bit 8 + UINT32 traffic_class:4; //bits 9-12 + UINT32 unused2:19; //bits 13-31 + #endif + } bits; +} +TXDMA_CSR_t, *PTXDMA_CSR_t; + + +/****************************************************************************** + structure for txdma packet ring base address hi reg in txdma address map + located at address 0x1004 + *****************************************************************************/ +typedef struct _TXDMA_PR_BASE_HI_t +{ + UINT32 addr_hi; //bits 0-31 +} +TXDMA_PR_BASE_HI_t, *PTXDMA_PR_BASE_HI_t; + + +/****************************************************************************** + structure for txdma packet ring base address low reg in txdma address map + located at address 0x1008 + *****************************************************************************/ +typedef struct _TXDMA_PR_BASE_LO_t +{ + UINT32 addr_lo; //bits 0-31 +} +TXDMA_PR_BASE_LO_t, *PTXDMA_PR_BASE_LO_t; + + +/****************************************************************************** + structure for txdma packet ring number of descriptor reg in txdma address + map. Located at address 0x100C + *****************************************************************************/ +typedef union _TXDMA_PR_NUM_DES_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 pr_ndes:10; //bits 0-9 + #else + UINT32 pr_ndes:10; //bits 0-9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +TXDMA_PR_NUM_DES_t, *PTXDMA_PR_NUM_DES_t; + + +/****************************************************************************** + structure for txdma tx queue write address reg in txdma address map + located at address 0x1010 + *****************************************************************************/ +typedef union _TXDMA_TXQ_WR_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 txq_wr_wrap:1; //bit 10 + UINT32 txq_wr:10; //bits 0-9 + #else + UINT32 txq_wr:10; //bits 0-9 + UINT32 txq_wr_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +TXDMA_TXQ_WR_ADDR_t, *PTXDMA_TXQ_WR_ADDR_t; + + +/****************************************************************************** + structure for txdma tx queue write address external reg in txdma address map + located at address 0x1014 + *****************************************************************************/ +typedef union _TXDMA_TXQ_WR_ADDR_EXT_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 txq_wr_ext_wrap:1; //bit 10 + UINT32 txq_wr_ext:10; //bits 0-9 + #else + UINT32 txq_wr_ext:10; //bits 0-9 + UINT32 txq_wr_ext_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +TXDMA_TXQ_WR_ADDR_EXT_t, *PTXDMA_TXQ_WR_ADDR_EXT_t; + + +/****************************************************************************** + structure for txdma tx queue read address reg in txdma address map + located at address 0x1018 + *****************************************************************************/ +typedef union _TXDMA_TXQ_RD_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 txq_rd_wrap:1; //bit 10 + UINT32 txq_rd:10; //bits 0-9 + #else + UINT32 txq_rd:10; //bits 0-9 + UINT32 txq_rd_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +TXDMA_TXQ_RD_ADDR_t, *PTXDMA_TXQ_RD_ADDR_t; + + +/****************************************************************************** + structure for txdma status writeback address hi reg in txdma address map + located at address 0x101C + *****************************************************************************/ +typedef struct _TXDMA_DMA_WB_ADDR_HI_t +{ + UINT32 addr_hi; //bits 0-31 +} +TXDMA_DMA_WB_ADDR_HI_t, *PTXDMA_DMA_WB_ADDR_HI_t; + + +/****************************************************************************** + structure for txdma status writeback address lo reg in txdma address map + located at address 0x1020 + *****************************************************************************/ +typedef struct _TXDMA_DMA_WB_ADDR_LO_t +{ + UINT32 addr_lo; //bits 0-31 +} +TXDMA_DMA_WB_ADDR_LO_t, *PTXDMA_DMA_WB_ADDR_LO_t; + + +/****************************************************************************** + structure for txdma service request reg in txdma address map + located at address 0x1024 + *****************************************************************************/ +typedef union _TXDMA_SERVICE_REQUEST_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 serv_req_wrap:1; //bit 10 + UINT32 serv_req:10; //bits 0-9 + #else + UINT32 serv_req:10; //bits 0-9 + UINT32 serv_req_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +TXDMA_SERVICE_REQUEST_t, *PTXDMA_SERVICE_REQUEST_t; + + +/****************************************************************************** + structure for txdma service complete reg in txdma address map + located at address 0x1028 + *****************************************************************************/ +typedef union _TXDMA_SERVICE_COMPLETE_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 serv_cpl_wrap:1; //bit 10 + UINT32 serv_cpl:10; //bits 0-9 + #else + UINT32 serv_cpl:10; //bits 0-9 + UINT32 serv_cpl_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +TXDMA_SERVICE_COMPLETE_t, *PTXDMA_SERVICE_COMPLETE_t; + + +/****************************************************************************** + structure for txdma tx descriptor cache read index reg in txdma address map + located at address 0x102C + *****************************************************************************/ +typedef union _TXDMA_CACHE_RD_INDEX_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:27; //bits 5-31 + UINT32 rdi_wrap:1; //bit 4 + UINT32 rdi:4; //bit 0-3 + #else + UINT32 rdi:4; //bits 0-3 + UINT32 rdi_wrap:1; //bit 4 + UINT32 unused:27; //bits 5-31 + #endif + } bits; +} +TXDMA_CACHE_RD_INDEX_t, *PTXDMA_CACHE_RD_INDEX_t; + + +/****************************************************************************** + structure for txdma tx descriptor cache write index reg in txdma address map + located at address 0x1030 + *****************************************************************************/ +typedef union _TXDMA_CACHE_WR_INDEX_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:27; //bits 5-31 + UINT32 wri_wrap:1; //bit 4 + UINT32 wri:4; //bit 0-3 + #else + UINT32 wri:4; //bits 0-3 + UINT32 wri_wrap:1; //bit 4 + UINT32 unused:27; //bits 5-31 + #endif + } bits; +} +TXDMA_CACHE_WR_INDEX_t, *PTXDMA_CACHE_WR_INDEX_t; + + +/****************************************************************************** + structure for txdma error reg in txdma address map + located at address 0x1034 + *****************************************************************************/ +typedef union _TXDMA_ERROR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused3:22; //bits 10-31 + UINT32 WrbkRewind:1; //bit 9 + UINT32 WrbkResend:1; //bit 8 + UINT32 unused2:2; //bits 6-7 + UINT32 DescrRewind:1; //bit 5 + UINT32 DescrResend:1; //bit 4 + UINT32 unused1:2; //bits 2-3 + UINT32 PyldRewind:1; //bit 1 + UINT32 PyldResend:1; //bit 0 + #else + UINT32 PyldResend:1; //bit 0 + UINT32 PyldRewind:1; //bit 1 + UINT32 unused1:2; //bits 2-3 + UINT32 DescrResend:1; //bit 4 + UINT32 DescrRewind:1; //bit 5 + UINT32 unused2:2; //bits 6-7 + UINT32 WrbkResend:1; //bit 8 + UINT32 WrbkRewind:1; //bit 9 + UINT32 unused3:22; //bits 10-31 + #endif + } bits; +} +TXDMA_ERROR_t, *PTXDMA_ERROR_t; + + +/****************************************************************************** + Tx DMA Module of JAGCore Address Mapping + Located at address 0x1000 + *****************************************************************************/ +typedef struct _TXDMA_t +{ //Location: + TXDMA_CSR_t csr; // 0x1000 + TXDMA_PR_BASE_HI_t pr_base_hi; // 0x1004 + TXDMA_PR_BASE_LO_t pr_base_lo; // 0x1008 + TXDMA_PR_NUM_DES_t pr_num_des; // 0x100C + TXDMA_TXQ_WR_ADDR_t txq_wr_addr; // 0x1010 + TXDMA_TXQ_WR_ADDR_EXT_t txq_wr_addr_ext; // 0x1014 + TXDMA_TXQ_RD_ADDR_t txq_rd_addr; // 0x1018 + TXDMA_DMA_WB_ADDR_HI_t dma_wb_base_hi; // 0x101C + TXDMA_DMA_WB_ADDR_LO_t dma_wb_base_lo; // 0x1020 + TXDMA_SERVICE_REQUEST_t service_request; // 0x1024 + TXDMA_SERVICE_COMPLETE_t service_complete; // 0x1028 + TXDMA_CACHE_RD_INDEX_t cache_rd_index; // 0x102C + TXDMA_CACHE_WR_INDEX_t cache_wr_index; // 0x1030 + TXDMA_ERROR_t TxDmaError; // 0x1034 + UINT32 DescAbortCount; // 0x1038 + UINT32 PayloadAbortCnt; // 0x103c + UINT32 WriteBackAbortCnt; // 0x1040 + UINT32 DescTimeoutCnt; // 0x1044 + UINT32 PayloadTimeoutCnt; // 0x1048 + UINT32 WriteBackTimeoutCnt;// 0x104c + UINT32 DescErrorCount; // 0x1050 + UINT32 PayloadErrorCnt; // 0x1054 + UINT32 WriteBackErrorCnt; // 0x1058 + UINT32 DroppedTLPCount; // 0x105c + TXDMA_SERVICE_COMPLETE_t NewServiceComplete; // 0x1060 + UINT32 EthernetPacketCount;// 0x1064 +} +TXDMA_t, *PTXDMA_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF TXDMA REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF RXDMA REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for control status reg in rxdma address map + Located at address 0x2000 + *****************************************************************************/ +typedef union _RXDMA_CSR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused2:14; //bits 18-31 + UINT32 halt_status:1; //bit 17 + UINT32 pkt_done_flush:1; //bit 16 + UINT32 pkt_drop_disable:1; //bit 15 + UINT32 unused1:1; //bit 14 + UINT32 fbr1_enable:1; //bit 13 + UINT32 fbr1_size:2; //bits 11-12 + UINT32 fbr0_enable:1; //bit 10 + UINT32 fbr0_size:2; //bits 8-9 + UINT32 dma_big_endian:1; //bit 7 + UINT32 pkt_big_endian:1; //bit 6 + UINT32 psr_big_endian:1; //bit 5 + UINT32 fbr_big_endian:1; //bit 4 + UINT32 tc:3; //bits 1-3 + UINT32 halt:1; //bit 0 + #else + UINT32 halt:1; //bit 0 + UINT32 tc:3; //bits 1-3 + UINT32 fbr_big_endian:1; //bit 4 + UINT32 psr_big_endian:1; //bit 5 + UINT32 pkt_big_endian:1; //bit 6 + UINT32 dma_big_endian:1; //bit 7 + UINT32 fbr0_size:2; //bits 8-9 + UINT32 fbr0_enable:1; //bit 10 + UINT32 fbr1_size:2; //bits 11-12 + UINT32 fbr1_enable:1; //bit 13 + UINT32 unused1:1; //bit 14 + UINT32 pkt_drop_disable:1; //bit 15 + UINT32 pkt_done_flush:1; //bit 16 + UINT32 halt_status:1; //bit 17 + UINT32 unused2:14; //bits 18-31 + #endif + } bits; +} +RXDMA_CSR_t, *PRXDMA_CSR_t; + + +/****************************************************************************** + structure for dma writeback lo reg in rxdma address map + located at address 0x2004 + *****************************************************************************/ +typedef struct _RXDMA_DMA_WB_BASE_LO_t +{ + UINT32 addr_lo; //bits 0-31 +} +RXDMA_DMA_WB_BASE_LO_t, *PRXDMA_DMA_WB_BASE_LO_t; + + +/****************************************************************************** + structure for dma writeback hi reg in rxdma address map + located at address 0x2008 + *****************************************************************************/ +typedef struct _RXDMA_DMA_WB_BASE_HI_t +{ + UINT32 addr_hi; //bits 0-31 +} +RXDMA_DMA_WB_BASE_HI_t, *PRXDMA_DMA_WB_BASE_HI_t; + + +/****************************************************************************** + structure for number of packets done reg in rxdma address map + located at address 0x200C + *****************************************************************************/ +typedef union _RXDMA_NUM_PKT_DONE_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:24; //bits 8-31 + UINT32 num_done:8; //bits 0-7 + #else + UINT32 num_done:8; //bits 0-7 + UINT32 unused:24; //bits 8-31 + #endif + } bits; +} +RXDMA_NUM_PKT_DONE_t, *PRXDMA_NUM_PKT_DONE_t; + + +/****************************************************************************** + structure for max packet time reg in rxdma address map + located at address 0x2010 + *****************************************************************************/ +typedef union _RXDMA_MAX_PKT_TIME_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:14; //bits 18-31 + UINT32 time_done:18; //bits 0-17 + #else + UINT32 time_done:18; //bits 0-17 + UINT32 unused:14; //bits 18-31 + #endif + } bits; +} +RXDMA_MAX_PKT_TIME_t, *PRXDMA_MAX_PKT_TIME_t; + + +/****************************************************************************** + structure for rx queue read address reg in rxdma address map + located at address 0x2014 + *****************************************************************************/ +typedef union _RXDMA_RXQ_RD_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 rxq_rd_wrap:1; //bit 10 + UINT32 rxq_rd:10; //bits 0-9 + #else + UINT32 rxq_rd:10; //bits 0-9 + UINT32 rxq_rd_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +RXDMA_RXQ_RD_ADDR_t, *PRXDMA_RXQ_RD_ADDR_t; + + +/****************************************************************************** + structure for rx queue read address external reg in rxdma address map + located at address 0x2018 + *****************************************************************************/ +typedef union _RXDMA_RXQ_RD_ADDR_EXT_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 rxq_rd_ext_wrap:1; //bit 10 + UINT32 rxq_rd_ext:10; //bits 0-9 + #else + UINT32 rxq_rd_ext:10; //bits 0-9 + UINT32 rxq_rd_ext_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +RXDMA_RXQ_RD_ADDR_EXT_t, *PRXDMA_RXQ_RD_ADDR_EXT_t; + + +/****************************************************************************** + structure for rx queue write address reg in rxdma address map + located at address 0x201C + *****************************************************************************/ +typedef union _RXDMA_RXQ_WR_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 rxq_wr_wrap:1; //bit 10 + UINT32 rxq_wr:10; //bits 0-9 + #else + UINT32 rxq_wr:10; //bits 0-9 + UINT32 rxq_wr_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +RXDMA_RXQ_WR_ADDR_t, *PRXDMA_RXQ_WR_ADDR_t; + + +/****************************************************************************** + structure for packet status ring base address lo reg in rxdma address map + located at address 0x2020 + *****************************************************************************/ +typedef struct _RXDMA_PSR_BASE_LO_t +{ + UINT32 addr_lo; //bits 0-31 +} +RXDMA_PSR_BASE_LO_t, *PRXDMA_PSR_BASE_LO_t; + + +/****************************************************************************** + structure for packet status ring base address hi reg in rxdma address map + located at address 0x2024 + *****************************************************************************/ +typedef struct _RXDMA_PSR_BASE_HI_t +{ + UINT32 addr_hi; //bits 0-31 +} +RXDMA_PSR_BASE_HI_t, *PRXDMA_PSR_BASE_HI_t; + + +/****************************************************************************** + structure for packet status ring number of descriptors reg in rxdma address + map. Located at address 0x2028 + *****************************************************************************/ +typedef union _RXDMA_PSR_NUM_DES_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:20; //bits 12-31 + UINT32 psr_ndes:12; //bit 0-11 + #else + UINT32 psr_ndes:12; //bit 0-11 + UINT32 unused:20; //bits 12-31 + #endif + } bits; +} +RXDMA_PSR_NUM_DES_t, *PRXDMA_PSR_NUM_DES_t; + + +/****************************************************************************** + structure for packet status ring available offset reg in rxdma address map + located at address 0x202C + *****************************************************************************/ +typedef union _RXDMA_PSR_AVAIL_OFFSET_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:19; //bits 13-31 + UINT32 psr_avail_wrap:1; //bit 12 + UINT32 psr_avail:12; //bit 0-11 + #else + UINT32 psr_avail:12; //bit 0-11 + UINT32 psr_avail_wrap:1; //bit 12 + UINT32 unused:19; //bits 13-31 + #endif + } bits; +} +RXDMA_PSR_AVAIL_OFFSET_t, *PRXDMA_PSR_AVAIL_OFFSET_t; + + +/****************************************************************************** + structure for packet status ring full offset reg in rxdma address map + located at address 0x2030 + *****************************************************************************/ +typedef union _RXDMA_PSR_FULL_OFFSET_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:19; //bits 13-31 + UINT32 psr_full_wrap:1; //bit 12 + UINT32 psr_full:12; //bit 0-11 + #else + UINT32 psr_full:12; //bit 0-11 + UINT32 psr_full_wrap:1; //bit 12 + UINT32 unused:19; //bits 13-31 + #endif + } bits; +} +RXDMA_PSR_FULL_OFFSET_t, *PRXDMA_PSR_FULL_OFFSET_t; + + +/****************************************************************************** + structure for packet status ring access index reg in rxdma address map + located at address 0x2034 + *****************************************************************************/ +typedef union _RXDMA_PSR_ACCESS_INDEX_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:27; //bits 5-31 + UINT32 psr_ai:5; //bits 0-4 + #else + UINT32 psr_ai:5; //bits 0-4 + UINT32 unused:27; //bits 5-31 + #endif + } bits; +} +RXDMA_PSR_ACCESS_INDEX_t, *PRXDMA_PSR_ACCESS_INDEX_t; + + +/****************************************************************************** + structure for packet status ring minimum descriptors reg in rxdma address + map. Located at address 0x2038 + *****************************************************************************/ +typedef union _RXDMA_PSR_MIN_DES_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:20; //bits 12-31 + UINT32 psr_min:12; //bits 0-11 + #else + UINT32 psr_min:12; //bits 0-11 + UINT32 unused:20; //bits 12-31 + #endif + } bits; +} +RXDMA_PSR_MIN_DES_t, *PRXDMA_PSR_MIN_DES_t; + + +/****************************************************************************** + structure for free buffer ring base lo address reg in rxdma address map + located at address 0x203C + *****************************************************************************/ +typedef struct _RXDMA_FBR_BASE_LO_t +{ + UINT32 addr_lo; //bits 0-31 +} +RXDMA_FBR_BASE_LO_t, *PRXDMA_FBR_BASE_LO_t; + + +/****************************************************************************** + structure for free buffer ring base hi address reg in rxdma address map + located at address 0x2040 + *****************************************************************************/ +typedef struct _RXDMA_FBR_BASE_HI_t +{ + UINT32 addr_hi; //bits 0-31 +} +RXDMA_FBR_BASE_HI_t, *PRXDMA_FBR_BASE_HI_t; + + +/****************************************************************************** + structure for free buffer ring number of descriptors reg in rxdma address + map. Located at address 0x2044 + *****************************************************************************/ +typedef union _RXDMA_FBR_NUM_DES_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 fbr_ndesc:10; //bits 0-9 + #else + UINT32 fbr_ndesc:10; //bits 0-9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +RXDMA_FBR_NUM_DES_t, *PRXDMA_FBR_NUM_DES_t; + + +/****************************************************************************** + structure for free buffer ring 0 available offset reg in rxdma address map + located at address 0x2048 + *****************************************************************************/ +typedef union _RXDMA_FBR_AVAIL_OFFSET_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 fbr_avail_wrap:1; //bit 10 + UINT32 fbr_avail:10; //bit 0-9 + #else + UINT32 fbr_avail:10; //bit 0-9 + UINT32 fbr_avail_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +RXDMA_FBR_AVAIL_OFFSET_t, *PRXDMA_FBR_AVAIL_OFFSET_t; + + +/****************************************************************************** + structure for free buffer ring 0 full offset reg in rxdma address map + located at address 0x204C + *****************************************************************************/ +typedef union _RXDMA_FBR_FULL_OFFSET_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 fbr_full_wrap:1; //bit 10 + UINT32 fbr_full:10; //bit 0-9 + #else + UINT32 fbr_full:10; //bit 0-9 + UINT32 fbr_full_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +RXDMA_FBR_FULL_OFFSET_t, *PRXDMA_FBR_FULL_OFFSET_t; + + +/****************************************************************************** + structure for free buffer cache 0 full offset reg in rxdma address map + located at address 0x2050 + *****************************************************************************/ +typedef union _RXDMA_FBC_RD_INDEX_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:27; //bits 5-31 + UINT32 fbc_rdi:5; //bit 0-4 + #else + UINT32 fbc_rdi:5; //bit 0-4 + UINT32 unused:27; //bits 5-31 + #endif + } bits; +} +RXDMA_FBC_RD_INDEX_t, *PRXDMA_FBC_RD_INDEX_t; + + +/****************************************************************************** + structure for free buffer ring 0 minimum descriptor reg in rxdma address map + located at address 0x2054 + *****************************************************************************/ +typedef union _RXDMA_FBR_MIN_DES_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:22; //bits 10-31 + UINT32 fbr_min:10; //bits 0-9 + #else + UINT32 fbr_min:10; //bits 0-9 + UINT32 unused:22; //bits 10-31 + #endif + } bits; +} +RXDMA_FBR_MIN_DES_t, *PRXDMA_FBR_MIN_DES_t; + + +/****************************************************************************** + structure for free buffer ring 1 base address lo reg in rxdma address map + located at address 0x2058 - 0x205C + Defined earlier (RXDMA_FBR_BASE_LO_t and RXDMA_FBR_BASE_HI_t) + *****************************************************************************/ + +/****************************************************************************** + structure for free buffer ring 1 number of descriptors reg in rxdma address + map. Located at address 0x2060 + Defined earlier (RXDMA_FBR_NUM_DES_t) + *****************************************************************************/ + +/****************************************************************************** + structure for free buffer ring 1 available offset reg in rxdma address map + located at address 0x2064 + Defined Earlier (RXDMA_FBR_AVAIL_OFFSET_t) + *****************************************************************************/ + +/****************************************************************************** + structure for free buffer ring 1 full offset reg in rxdma address map + located at address 0x2068 + Defined Earlier (RXDMA_FBR_FULL_OFFSET_t) + *****************************************************************************/ + +/****************************************************************************** + structure for free buffer cache 1 read index reg in rxdma address map + located at address 0x206C + Defined Earlier (RXDMA_FBC_RD_INDEX_t) + *****************************************************************************/ + +/****************************************************************************** + structure for free buffer ring 1 minimum descriptor reg in rxdma address map + located at address 0x2070 + Defined Earlier (RXDMA_FBR_MIN_DES_t) + *****************************************************************************/ + + +/****************************************************************************** + Rx DMA Module of JAGCore Address Mapping + Located at address 0x2000 + *****************************************************************************/ +typedef struct _RXDMA_t +{ //Location: + RXDMA_CSR_t csr; // 0x2000 + RXDMA_DMA_WB_BASE_LO_t dma_wb_base_lo; // 0x2004 + RXDMA_DMA_WB_BASE_HI_t dma_wb_base_hi; // 0x2008 + RXDMA_NUM_PKT_DONE_t num_pkt_done; // 0x200C + RXDMA_MAX_PKT_TIME_t max_pkt_time; // 0x2010 + RXDMA_RXQ_RD_ADDR_t rxq_rd_addr; // 0x2014 + RXDMA_RXQ_RD_ADDR_EXT_t rxq_rd_addr_ext; // 0x2018 + RXDMA_RXQ_WR_ADDR_t rxq_wr_addr; // 0x201C + RXDMA_PSR_BASE_LO_t psr_base_lo; // 0x2020 + RXDMA_PSR_BASE_HI_t psr_base_hi; // 0x2024 + RXDMA_PSR_NUM_DES_t psr_num_des; // 0x2028 + RXDMA_PSR_AVAIL_OFFSET_t psr_avail_offset; // 0x202C + RXDMA_PSR_FULL_OFFSET_t psr_full_offset; // 0x2030 + RXDMA_PSR_ACCESS_INDEX_t psr_access_index; // 0x2034 + RXDMA_PSR_MIN_DES_t psr_min_des; // 0x2038 + RXDMA_FBR_BASE_LO_t fbr0_base_lo; // 0x203C + RXDMA_FBR_BASE_HI_t fbr0_base_hi; // 0x2040 + RXDMA_FBR_NUM_DES_t fbr0_num_des; // 0x2044 + RXDMA_FBR_AVAIL_OFFSET_t fbr0_avail_offset; // 0x2048 + RXDMA_FBR_FULL_OFFSET_t fbr0_full_offset; // 0x204C + RXDMA_FBC_RD_INDEX_t fbr0_rd_index; // 0x2050 + RXDMA_FBR_MIN_DES_t fbr0_min_des; // 0x2054 + RXDMA_FBR_BASE_LO_t fbr1_base_lo; // 0x2058 + RXDMA_FBR_BASE_HI_t fbr1_base_hi; // 0x205C + RXDMA_FBR_NUM_DES_t fbr1_num_des; // 0x2060 + RXDMA_FBR_AVAIL_OFFSET_t fbr1_avail_offset; // 0x2064 + RXDMA_FBR_FULL_OFFSET_t fbr1_full_offset; // 0x2068 + RXDMA_FBC_RD_INDEX_t fbr1_rd_index; // 0x206C + RXDMA_FBR_MIN_DES_t fbr1_min_des; // 0x2070 +} +RXDMA_t, *PRXDMA_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF RXDMA REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF TXMAC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for control reg in txmac address map + located at address 0x3000 + *****************************************************************************/ +typedef union _TXMAC_CTL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:24; //bits 8-31 + UINT32 cklseg_diable:1; //bit 7 + UINT32 ckbcnt_disable:1; //bit 6 + UINT32 cksegnum:1; //bit 5 + UINT32 async_disable:1; //bit 4 + UINT32 fc_disable:1; //bit 3 + UINT32 mcif_disable:1; //bit 2 + UINT32 mif_disable:1; //bit 1 + UINT32 txmac_en:1; //bit 0 + #else + UINT32 txmac_en:1; //bit 0 + UINT32 mif_disable:1; //bit 1 mac interface + UINT32 mcif_disable:1; //bit 2 memory controller interface + UINT32 fc_disable:1; //bit 3 + UINT32 async_disable:1; //bit 4 + UINT32 cksegnum:1; //bit 5 + UINT32 ckbcnt_disable:1; //bit 6 + UINT32 cklseg_diable:1; //bit 7 + UINT32 unused:24; //bits 8-31 + #endif + } bits; +} +TXMAC_CTL_t, *PTXMAC_CTL_t; + + +/****************************************************************************** + structure for shadow pointer reg in txmac address map + located at address 0x3004 + *****************************************************************************/ +typedef union _TXMAC_SHADOW_PTR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved2:5; //bits 27-31 + UINT32 txq_rd_ptr:11; //bits 16-26 + UINT32 reserved:5; //bits 11-15 + UINT32 txq_wr_ptr:11; //bits 0-10 + #else + UINT32 txq_wr_ptr:11; //bits 0-10 + UINT32 reserved:5; //bits 11-15 + UINT32 txq_rd_ptr:11; //bits 16-26 + UINT32 reserved2:5; //bits 27-31 + #endif + } bits; +} +TXMAC_SHADOW_PTR_t, *PTXMAC_SHADOW_PTR_t; + + +/****************************************************************************** + structure for error count reg in txmac address map + located at address 0x3008 + *****************************************************************************/ +typedef union _TXMAC_ERR_CNT_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:20; //bits 12-31 + UINT32 reserved:4; //bits 8-11 + UINT32 txq_underrun:4; //bits 4-7 + UINT32 fifo_underrun:4; //bits 0-3 + #else + UINT32 fifo_underrun:4; //bits 0-3 + UINT32 txq_underrun:4; //bits 4-7 + UINT32 reserved:4; //bits 8-11 + UINT32 unused:20; //bits 12-31 + #endif + } bits; +} TXMAC_ERR_CNT_t, *PTXMAC_ERR_CNT_t; + + +/****************************************************************************** + structure for max fill reg in txmac address map + located at address 0x300C + *****************************************************************************/ +typedef union _TXMAC_MAX_FILL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:20; //bits 12-31 + UINT32 max_fill:12; //bits 0-11 + #else + UINT32 max_fill:12; //bits 0-11 + UINT32 unused:20; //bits 12-31 + #endif + } bits; +} +TXMAC_MAX_FILL_t, *PTXMAC_MAX_FILL_t; + + +/****************************************************************************** + structure for cf parameter reg in txmac address map + located at address 0x3010 + *****************************************************************************/ +typedef union _TXMAC_CF_PARAM_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 cfep:16; //bits 16-31 + UINT32 cfpt:16; //bits 0-15 + #else + UINT32 cfpt:16; //bits 0-15 + UINT32 cfep:16; //bits 16-31 + #endif + } bits; +} +TXMAC_CF_PARAM_t, *PTXMAC_CF_PARAM_t; + + +/****************************************************************************** + structure for tx test reg in txmac address map + located at address 0x3014 + *****************************************************************************/ +typedef union _TXMAC_TXTEST_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused2:15; //bits 17-31 + UINT32 reserved1:1; //bit 16 + UINT32 txtest_en:1; //bit 15 + UINT32 unused1:4; //bits 11-14 + UINT32 txqtest_ptr:11; //bits 0-11 + #else + UINT32 txqtest_ptr:11; //bits 0-10 + UINT32 unused1:4; //bits 11-14 + UINT32 txtest_en:1; //bit 15 + UINT32 reserved1:1; //bit 16 + UINT32 unused2:15; //bits 17-31 + #endif + } bits; +} +TXMAC_TXTEST_t, *PTXMAC_TXTEST_t; + + +/****************************************************************************** + structure for error reg in txmac address map + located at address 0x3018 + *****************************************************************************/ +typedef union _TXMAC_ERR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused2:23; //bits 9-31 + UINT32 fifo_underrun:1; //bit 8 + UINT32 unused1:2; //bits 6-7 + UINT32 ctrl2_err:1; //bit 5 + UINT32 txq_underrun:1; //bit 4 + UINT32 bcnt_err:1; //bit 3 + UINT32 lseg_err:1; //bit 2 + UINT32 segnum_err:1; //bit 1 + UINT32 seg0_err:1; //bit 0 + #else + UINT32 seg0_err:1; //bit 0 + UINT32 segnum_err:1; //bit 1 + UINT32 lseg_err:1; //bit 2 + UINT32 bcnt_err:1; //bit 3 + UINT32 txq_underrun:1; //bit 4 + UINT32 ctrl2_err:1; //bit 5 + UINT32 unused1:2; //bits 6-7 + UINT32 fifo_underrun:1; //bit 8 + UINT32 unused2:23; //bits 9-31 + #endif + } bits; +} +TXMAC_ERR_t, *PTXMAC_ERR_t; + + +/****************************************************************************** + structure for error interrupt reg in txmac address map + located at address 0x301C + *****************************************************************************/ +typedef union _TXMAC_ERR_INT_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused2:23; //bits 9-31 + UINT32 fifo_underrun:1; //bit 8 + UINT32 unused1:2; //bits 6-7 + UINT32 ctrl2_err:1; //bit 5 + UINT32 txq_underrun:1; //bit 4 + UINT32 bcnt_err:1; //bit 3 + UINT32 lseg_err:1; //bit 2 + UINT32 segnum_err:1; //bit 1 + UINT32 seg0_err:1; //bit 0 + #else + UINT32 seg0_err:1; //bit 0 + UINT32 segnum_err:1; //bit 1 + UINT32 lseg_err:1; //bit 2 + UINT32 bcnt_err:1; //bit 3 + UINT32 txq_underrun:1; //bit 4 + UINT32 ctrl2_err:1; //bit 5 + UINT32 unused1:2; //bits 6-7 + UINT32 fifo_underrun:1; //bit 8 + UINT32 unused2:23; //bits 9-31 + #endif + } bits; +} +TXMAC_ERR_INT_t, *PTXMAC_ERR_INT_t; + + +/****************************************************************************** + structure for error interrupt reg in txmac address map + located at address 0x3020 + *****************************************************************************/ +typedef union _TXMAC_CP_CTRL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:30; //bits 2-31 + UINT32 bp_req:1; //bit 1 + UINT32 bp_xonxoff:1; //bit 0 + #else + UINT32 bp_xonxoff:1; //bit 0 + UINT32 bp_req:1; //bit 1 + UINT32 unused:30; //bits 2-31 + #endif + } bits; +} +TXMAC_BP_CTRL_t, *PTXMAC_BP_CTRL_t; + + +/****************************************************************************** + Tx MAC Module of JAGCore Address Mapping + *****************************************************************************/ +typedef struct _TXMAC_t +{ //Location: + TXMAC_CTL_t ctl; // 0x3000 + TXMAC_SHADOW_PTR_t shadow_ptr; // 0x3004 + TXMAC_ERR_CNT_t err_cnt; // 0x3008 + TXMAC_MAX_FILL_t max_fill; // 0x300C + TXMAC_CF_PARAM_t cf_param; // 0x3010 + TXMAC_TXTEST_t tx_test; // 0x3014 + TXMAC_ERR_t err; // 0x3018 + TXMAC_ERR_INT_t err_int; // 0x301C + TXMAC_BP_CTRL_t bp_ctrl; // 0x3020 +} +TXMAC_t, *PTXMAC_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF TXMAC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF RXMAC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for rxmac control reg in rxmac address map + located at address 0x4000 + *****************************************************************************/ +typedef union _RXMAC_CTRL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:25; //bits 7-31 + UINT32 rxmac_int_disable:1; //bit 6 + UINT32 async_disable:1; //bit 5 + UINT32 mif_disable:1; //bit 4 + UINT32 wol_disable:1; //bit 3 + UINT32 pkt_filter_disable:1; //bit 2 + UINT32 mcif_disable:1; //bit 1 + UINT32 rxmac_en:1; //bit 0 + #else + UINT32 rxmac_en:1; //bit 0 + UINT32 mcif_disable:1; //bit 1 + UINT32 pkt_filter_disable:1; //bit 2 + UINT32 wol_disable:1; //bit 3 + UINT32 mif_disable:1; //bit 4 + UINT32 async_disable:1; //bit 5 + UINT32 rxmac_int_disable:1; //bit 6 + UINT32 reserved:25; //bits 7-31 + #endif + } bits; +} +RXMAC_CTRL_t, *PRXMAC_CTRL_t; + + +/****************************************************************************** + structure for Wake On Lan Control and CRC 0 reg in rxmac address map + located at address 0x4004 + *****************************************************************************/ +typedef union _RXMAC_WOL_CTL_CRC0_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 crc0:16; //bits 16-31 + UINT32 reserve:4; //bits 12-15 + UINT32 ignore_pp:1; //bit 11 + UINT32 ignore_mp:1; //bit 10 + UINT32 clr_intr:1; //bit 9 + UINT32 ignore_link_chg:1; //bit 8 + UINT32 ignore_uni:1; //bit 7 + UINT32 ignore_multi:1; //bit 6 + UINT32 ignore_broad:1; //bit 5 + UINT32 valid_crc4:1; //bit 4 + UINT32 valid_crc3:1; //bit 3 + UINT32 valid_crc2:1; //bit 2 + UINT32 valid_crc1:1; //bit 1 + UINT32 valid_crc0:1; //bit 0 + #else + UINT32 valid_crc0:1; //bit 0 + UINT32 valid_crc1:1; //bit 1 + UINT32 valid_crc2:1; //bit 2 + UINT32 valid_crc3:1; //bit 3 + UINT32 valid_crc4:1; //bit 4 + UINT32 ignore_broad:1; //bit 5 + UINT32 ignore_multi:1; //bit 6 + UINT32 ignore_uni:1; //bit 7 + UINT32 ignore_link_chg:1; //bit 8 + UINT32 clr_intr:1; //bit 9 + UINT32 ignore_mp:1; //bit 10 + UINT32 ignore_pp:1; //bit 11 + UINT32 reserve:4; //bits 12-15 + UINT32 crc0:16; //bits 16-31 + #endif + } bits; +} +RXMAC_WOL_CTL_CRC0_t, *PRXMAC_WOL_CTL_CRC0_t; + + +/****************************************************************************** + structure for CRC 1 and CRC 2 reg in rxmac address map + located at address 0x4008 + *****************************************************************************/ +typedef union _RXMAC_WOL_CRC12_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 crc2:16; //bits 16-31 + UINT32 crc1:16; //bits 0-15 + #else + UINT32 crc1:16; //bits 0-15 + UINT32 crc2:16; //bits 16-31 + #endif + } bits; +} +RXMAC_WOL_CRC12_t, *PRXMAC_WOL_CRC12_t; + + +/****************************************************************************** + structure for CRC 3 and CRC 4 reg in rxmac address map + located at address 0x400C + *****************************************************************************/ +typedef union _RXMAC_WOL_CRC34_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 crc4:16; //bits 16-31 + UINT32 crc3:16; //bits 0-15 + #else + UINT32 crc3:16; //bits 0-15 + UINT32 crc4:16; //bits 16-31 + #endif + } bits; +} +RXMAC_WOL_CRC34_t, *PRXMAC_WOL_CRC34_t; + + +/****************************************************************************** + structure for Wake On Lan Source Address Lo reg in rxmac address map + located at address 0x4010 + *****************************************************************************/ +typedef union _RXMAC_WOL_SA_LO_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 sa3:8; //bits 24-31 + UINT32 sa4:8; //bits 16-23 + UINT32 sa5:8; //bits 8-15 + UINT32 sa6:8; //bits 0-7 + #else + UINT32 sa6:8; //bits 0-7 + UINT32 sa5:8; //bits 8-15 + UINT32 sa4:8; //bits 16-23 + UINT32 sa3:8; //bits 24-31 + #endif + } bits; +} +RXMAC_WOL_SA_LO_t, *PRXMAC_WOL_SA_LO_t; + + +/****************************************************************************** + structure for Wake On Lan Source Address Hi reg in rxmac address map + located at address 0x4014 + *****************************************************************************/ +typedef union _RXMAC_WOL_SA_HI_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:16; //bits 16-31 + UINT32 sa1:8; //bits 8-15 + UINT32 sa2:8; //bits 0-7 + #else + UINT32 sa2:8; //bits 0-7 + UINT32 sa1:8; //bits 8-15 + UINT32 reserved:16; //bits 16-31 + #endif + } bits; +} +RXMAC_WOL_SA_HI_t, *PRXMAC_WOL_SA_HI_t; + + +/****************************************************************************** + structure for Wake On Lan mask reg in rxmac address map + located at address 0x4018 - 0x4064 + *****************************************************************************/ +typedef struct _RXMAC_WOL_MASK_t +{ + UINT32 mask; //bits 0-31 +} +RXMAC_WOL_MASK_t, *PRXMAC_WOL_MASK_t; + + +/****************************************************************************** + structure for Unicast Paket Filter Address 1 reg in rxmac address map + located at address 0x4068 + *****************************************************************************/ +typedef union _RXMAC_UNI_PF_ADDR1_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 addr1_3:8; //bits 24-31 + UINT32 addr1_4:8; //bits 16-23 + UINT32 addr1_5:8; //bits 8-15 + UINT32 addr1_6:8; //bits 0-7 + #else + UINT32 addr1_6:8; //bits 0-7 + UINT32 addr1_5:8; //bits 8-15 + UINT32 addr1_4:8; //bits 16-23 + UINT32 addr1_3:8; //bits 24-31 + #endif + } bits; +} +RXMAC_UNI_PF_ADDR1_t, *PRXMAC_UNI_PF_ADDR1_t; + + +/****************************************************************************** + structure for Unicast Paket Filter Address 2 reg in rxmac address map + located at address 0x406C + *****************************************************************************/ +typedef union _RXMAC_UNI_PF_ADDR2_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 addr2_3:8; //bits 24-31 + UINT32 addr2_4:8; //bits 16-23 + UINT32 addr2_5:8; //bits 8-15 + UINT32 addr2_6:8; //bits 0-7 + #else + UINT32 addr2_6:8; //bits 0-7 + UINT32 addr2_5:8; //bits 8-15 + UINT32 addr2_4:8; //bits 16-23 + UINT32 addr2_3:8; //bits 24-31 + #endif + } bits; +} +RXMAC_UNI_PF_ADDR2_t, *PRXMAC_UNI_PF_ADDR2_t; + + +/****************************************************************************** + structure for Unicast Paket Filter Address 1 & 2 reg in rxmac address map + located at address 0x4070 + *****************************************************************************/ +typedef union _RXMAC_UNI_PF_ADDR3_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 addr2_1:8; //bits 24-31 + UINT32 addr2_2:8; //bits 16-23 + UINT32 addr1_1:8; //bits 8-15 + UINT32 addr1_2:8; //bits 0-7 + #else + UINT32 addr1_2:8; //bits 0-7 + UINT32 addr1_1:8; //bits 8-15 + UINT32 addr2_2:8; //bits 16-23 + UINT32 addr2_1:8; //bits 24-31 + #endif + } bits; +} +RXMAC_UNI_PF_ADDR3_t, *PRXMAC_UNI_PF_ADDR3_t; + + +/****************************************************************************** + structure for Multicast Hash reg in rxmac address map + located at address 0x4074 - 0x4080 + *****************************************************************************/ +typedef struct _RXMAC_MULTI_HASH_t +{ + UINT32 hash; //bits 0-31 +} +RXMAC_MULTI_HASH_t, *PRXMAC_MULTI_HASH_t; + + +/****************************************************************************** + structure for Packet Filter Control reg in rxmac address map + located at address 0x4084 + *****************************************************************************/ +typedef union _RXMAC_PF_CTRL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused2:9; //bits 23-31 + UINT32 min_pkt_size:7; //bits 16-22 + UINT32 unused1:12; //bits 4-15 + UINT32 filter_frag_en:1; //bit 3 + UINT32 filter_uni_en:1; //bit 2 + UINT32 filter_multi_en:1; //bit 1 + UINT32 filter_broad_en:1; //bit 0 + #else + UINT32 filter_broad_en:1; //bit 0 + UINT32 filter_multi_en:1; //bit 1 + UINT32 filter_uni_en:1; //bit 2 + UINT32 filter_frag_en:1; //bit 3 + UINT32 unused1:12; //bits 4-15 + UINT32 min_pkt_size:7; //bits 16-22 + UINT32 unused2:9; //bits 23-31 + #endif + } bits; +} +RXMAC_PF_CTRL_t, *PRXMAC_PF_CTRL_t; + + +/****************************************************************************** + structure for Memory Controller Interface Control Max Segment reg in rxmac + address map. Located at address 0x4088 + *****************************************************************************/ +typedef union _RXMAC_MCIF_CTRL_MAX_SEG_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:22; //bits 10-31 + UINT32 max_size:8; //bits 2-9 + UINT32 fc_en:1; //bit 1 + UINT32 seg_en:1; //bit 0 + #else + UINT32 seg_en:1; //bit 0 + UINT32 fc_en:1; //bit 1 + UINT32 max_size:8; //bits 2-9 + UINT32 reserved:22; //bits 10-31 + #endif + } bits; +} +RXMAC_MCIF_CTRL_MAX_SEG_t, *PRXMAC_MCIF_CTRL_MAX_SEG_t; + + +/****************************************************************************** + structure for Memory Controller Interface Water Mark reg in rxmac address + map. Located at address 0x408C + *****************************************************************************/ +typedef union _RXMAC_MCIF_WATER_MARK_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved2:6; //bits 26-31 + UINT32 mark_hi:10; //bits 16-25 + UINT32 reserved1:6; //bits 10-15 + UINT32 mark_lo:10; //bits 0-9 + #else + UINT32 mark_lo:10; //bits 0-9 + UINT32 reserved1:6; //bits 10-15 + UINT32 mark_hi:10; //bits 16-25 + UINT32 reserved2:6; //bits 26-31 + #endif + } bits; +} +RXMAC_MCIF_WATER_MARK_t, *PRXMAC_MCIF_WATER_MARK_t; + + +/****************************************************************************** + structure for Rx Queue Dialog reg in rxmac address map. + located at address 0x4090 + *****************************************************************************/ +typedef union _RXMAC_RXQ_DIAG_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved2:6; //bits 26-31 + UINT32 rd_ptr:10; //bits 16-25 + UINT32 reserved1:6; //bits 10-15 + UINT32 wr_ptr:10; //bits 0-9 + #else + UINT32 wr_ptr:10; //bits 0-9 + UINT32 reserved1:6; //bits 10-15 + UINT32 rd_ptr:10; //bits 16-25 + UINT32 reserved2:6; //bits 26-31 + #endif + } bits; +} +RXMAC_RXQ_DIAG_t, *PRXMAC_RXQ_DIAG_t; + + +/****************************************************************************** + structure for space availiable reg in rxmac address map. + located at address 0x4094 + *****************************************************************************/ +typedef union _RXMAC_SPACE_AVAIL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved2:15; //bits 17-31 + UINT32 space_avail_en:1; //bit 16 + UINT32 reserved1:6; //bits 10-15 + UINT32 space_avail:10; //bits 0-9 + #else + UINT32 space_avail:10; //bits 0-9 + UINT32 reserved1:6; //bits 10-15 + UINT32 space_avail_en:1; //bit 16 + UINT32 reserved2:15; //bits 17-31 + #endif + } bits; +} +RXMAC_SPACE_AVAIL_t, *PRXMAC_SPACE_AVAIL_t; + + +/****************************************************************************** + structure for management interface reg in rxmac address map. + located at address 0x4098 + *****************************************************************************/ +typedef union _RXMAC_MIF_CTL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserve:14; //bits 18-31 + UINT32 drop_pkt_en:1; //bit 17 + UINT32 drop_pkt_mask:17; //bits 0-16 + #else + UINT32 drop_pkt_mask:17; //bits 0-16 + UINT32 drop_pkt_en:1; //bit 17 + UINT32 reserve:14; //bits 18-31 + #endif + } bits; +} +RXMAC_MIF_CTL_t, *PRXMAC_MIF_CTL_t; + + +/****************************************************************************** + structure for Error reg in rxmac address map. + located at address 0x409C + *****************************************************************************/ +typedef union _RXMAC_ERROR_REG_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserve:28; //bits 4-31 + UINT32 mif:1; //bit 3 + UINT32 async:1; //bit 2 + UINT32 pkt_filter:1; //bit 1 + UINT32 mcif:1; //bit 0 + #else + UINT32 mcif:1; //bit 0 + UINT32 pkt_filter:1; //bit 1 + UINT32 async:1; //bit 2 + UINT32 mif:1; //bit 3 + UINT32 reserve:28; //bits 4-31 + #endif + } bits; +} +RXMAC_ERROR_REG_t, *PRXMAC_ERROR_REG_t; + + +/****************************************************************************** + Rx MAC Module of JAGCore Address Mapping + *****************************************************************************/ +typedef struct _RXMAC_t +{ //Location: + RXMAC_CTRL_t ctrl; // 0x4000 + RXMAC_WOL_CTL_CRC0_t crc0; // 0x4004 + RXMAC_WOL_CRC12_t crc12; // 0x4008 + RXMAC_WOL_CRC34_t crc34; // 0x400C + RXMAC_WOL_SA_LO_t sa_lo; // 0x4010 + RXMAC_WOL_SA_HI_t sa_hi; // 0x4014 + RXMAC_WOL_MASK_t mask0_word0; // 0x4018 + RXMAC_WOL_MASK_t mask0_word1; // 0x401C + RXMAC_WOL_MASK_t mask0_word2; // 0x4020 + RXMAC_WOL_MASK_t mask0_word3; // 0x4024 + RXMAC_WOL_MASK_t mask1_word0; // 0x4028 + RXMAC_WOL_MASK_t mask1_word1; // 0x402C + RXMAC_WOL_MASK_t mask1_word2; // 0x4030 + RXMAC_WOL_MASK_t mask1_word3; // 0x4034 + RXMAC_WOL_MASK_t mask2_word0; // 0x4038 + RXMAC_WOL_MASK_t mask2_word1; // 0x403C + RXMAC_WOL_MASK_t mask2_word2; // 0x4040 + RXMAC_WOL_MASK_t mask2_word3; // 0x4044 + RXMAC_WOL_MASK_t mask3_word0; // 0x4048 + RXMAC_WOL_MASK_t mask3_word1; // 0x404C + RXMAC_WOL_MASK_t mask3_word2; // 0x4050 + RXMAC_WOL_MASK_t mask3_word3; // 0x4054 + RXMAC_WOL_MASK_t mask4_word0; // 0x4058 + RXMAC_WOL_MASK_t mask4_word1; // 0x405C + RXMAC_WOL_MASK_t mask4_word2; // 0x4060 + RXMAC_WOL_MASK_t mask4_word3; // 0x4064 + RXMAC_UNI_PF_ADDR1_t uni_pf_addr1; // 0x4068 + RXMAC_UNI_PF_ADDR2_t uni_pf_addr2; // 0x406C + RXMAC_UNI_PF_ADDR3_t uni_pf_addr3; // 0x4070 + RXMAC_MULTI_HASH_t multi_hash1; // 0x4074 + RXMAC_MULTI_HASH_t multi_hash2; // 0x4078 + RXMAC_MULTI_HASH_t multi_hash3; // 0x407C + RXMAC_MULTI_HASH_t multi_hash4; // 0x4080 + RXMAC_PF_CTRL_t pf_ctrl; // 0x4084 + RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg; // 0x4088 + RXMAC_MCIF_WATER_MARK_t mcif_water_mark; // 0x408C + RXMAC_RXQ_DIAG_t rxq_diag; // 0x4090 + RXMAC_SPACE_AVAIL_t space_avail; // 0x4094 + + RXMAC_MIF_CTL_t mif_ctrl; // 0x4098 + RXMAC_ERROR_REG_t err_reg; // 0x409C +} +RXMAC_t, *PRXMAC_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF TXMAC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF MAC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for configuration #1 reg in mac address map. + located at address 0x5000 + *****************************************************************************/ +typedef union _MAC_CFG1_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 soft_reset:1; //bit 31 + UINT32 sim_reset:1; //bit 30 + UINT32 reserved3:10; //bits 20-29 + UINT32 reset_rx_mc:1; //bit 19 + UINT32 reset_tx_mc:1; //bit 18 + UINT32 reset_rx_fun:1; //bit 17 + UINT32 reset_tx_fun:1; //bit 16 + UINT32 reserved2:7; //bits 9-15 + UINT32 loop_back:1; //bit 8 + UINT32 reserved1:2; //bits 6-7 + UINT32 rx_flow:1; //bit 5 + UINT32 tx_flow:1; //bit 4 + UINT32 syncd_rx_en:1; //bit 3 + UINT32 rx_enable:1; //bit 2 + UINT32 syncd_tx_en:1; //bit 1 + UINT32 tx_enable:1; //bit 0 + #else + UINT32 tx_enable:1; //bit 0 + UINT32 syncd_tx_en:1; //bit 1 + UINT32 rx_enable:1; //bit 2 + UINT32 syncd_rx_en:1; //bit 3 + UINT32 tx_flow:1; //bit 4 + UINT32 rx_flow:1; //bit 5 + UINT32 reserved1:2; //bits 6-7 + UINT32 loop_back:1; //bit 8 + UINT32 reserved2:7; //bits 9-15 + UINT32 reset_tx_fun:1; //bit 16 + UINT32 reset_rx_fun:1; //bit 17 + UINT32 reset_tx_mc:1; //bit 18 + UINT32 reset_rx_mc:1; //bit 19 + UINT32 reserved3:10; //bits 20-29 + UINT32 sim_reset:1; //bit 30 + UINT32 soft_reset:1; //bit 31 + #endif + } bits; +} +MAC_CFG1_t, *PMAC_CFG1_t; + + +/****************************************************************************** + structure for configuration #2 reg in mac address map. + located at address 0x5004 + *****************************************************************************/ +typedef union _MAC_CFG2_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved3:16; //bits 16-31 + UINT32 preamble_len:4; //bits 12-15 + UINT32 reserved2:2; //bits 10-11 + UINT32 if_mode:2; //bits 8-9 + UINT32 reserved1:2; //bits 6-7 + UINT32 huge_frame:1; //bit 5 + UINT32 len_check:1; //bit 4 + UINT32 undefined:1; //bit 3 + UINT32 pad_crc:1; //bit 2 + UINT32 crc_enable:1; //bit 1 + UINT32 full_duplex:1; //bit 0 + #else + UINT32 full_duplex:1; //bit 0 + UINT32 crc_enable:1; //bit 1 + UINT32 pad_crc:1; //bit 2 + UINT32 undefined:1; //bit 3 + UINT32 len_check:1; //bit 4 + UINT32 huge_frame:1; //bit 5 + UINT32 reserved1:2; //bits 6-7 + UINT32 if_mode:2; //bits 8-9 + UINT32 reserved2:2; //bits 10-11 + UINT32 preamble_len:4; //bits 12-15 + UINT32 reserved3:16; //bits 16-31 + #endif + } bits; +} +MAC_CFG2_t, *PMAC_CFG2_t; + + +/****************************************************************************** + structure for Interpacket gap reg in mac address map. + located at address 0x5008 + *****************************************************************************/ +typedef union _MAC_IPG_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:1; //bit 31 + UINT32 non_B2B_ipg_1:7; //bits 24-30 + UINT32 undefined2:1; //bit 23 + UINT32 non_B2B_ipg_2:7; //bits 16-22 + UINT32 min_ifg_enforce:8; //bits 8-15 + UINT32 undefined1:1; //bit 7 + UINT32 B2B_ipg:7; //bits 0-6 + #else + UINT32 B2B_ipg:7; //bits 0-6 + UINT32 undefined1:1; //bit 7 + UINT32 min_ifg_enforce:8; //bits 8-15 + UINT32 non_B2B_ipg_2:7; //bits 16-22 + UINT32 undefined2:1; //bit 23 + UINT32 non_B2B_ipg_1:7; //bits 24-30 + UINT32 reserved:1; //bit 31 + #endif + } bits; +} +MAC_IPG_t, *PMAC_IPG_t; + + +/****************************************************************************** + structure for half duplex reg in mac address map. + located at address 0x500C + *****************************************************************************/ +typedef union _MAC_HFDP_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved2:8; //bits 24-31 + UINT32 alt_beb_trunc:4; //bits 23-20 + UINT32 alt_beb_enable:1; //bit 19 + UINT32 bp_no_backoff:1; //bit 18 + UINT32 no_backoff:1; //bit 17 + UINT32 excess_defer:1; //bit 16 + UINT32 rexmit_max:4; //bits 12-15 + UINT32 reserved1:2; //bits 10-11 + UINT32 coll_window:10; //bits 0-9 + #else + UINT32 coll_window:10; //bits 0-9 + UINT32 reserved1:2; //bits 10-11 + UINT32 rexmit_max:4; //bits 12-15 + UINT32 excess_defer:1; //bit 16 + UINT32 no_backoff:1; //bit 17 + UINT32 bp_no_backoff:1; //bit 18 + UINT32 alt_beb_enable:1; //bit 19 + UINT32 alt_beb_trunc:4; //bits 23-20 + UINT32 reserved2:8; //bits 24-31 + #endif + } bits; +} +MAC_HFDP_t, *PMAC_HFDP_t; + + +/****************************************************************************** + structure for Maximum Frame Length reg in mac address map. + located at address 0x5010 + *****************************************************************************/ +typedef union _MAC_MAX_FM_LEN_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:16; //bits 16-31 + UINT32 max_len:16; //bits 0-15 + #else + UINT32 max_len:16; //bits 0-15 + UINT32 reserved:16; //bits 16-31 + #endif + } bits; +} +MAC_MAX_FM_LEN_t, *PMAC_MAX_FM_LEN_t; + + +/****************************************************************************** + structure for Reserve 1 reg in mac address map. + located at address 0x5014 - 0x5018 + *****************************************************************************/ +typedef struct _MAC_RSV_t +{ + UINT32 value; //bits 0-31 +} +MAC_RSV_t, *PMAC_RSV_t; + + +/****************************************************************************** + structure for Test reg in mac address map. + located at address 0x501C + *****************************************************************************/ +typedef union _MAC_TEST_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:29; //bits 3-31 + UINT32 mac_test:3; //bits 0-2 + #else + UINT32 mac_test:3; //bits 0-2 + UINT32 unused:29; //bits 3-31 + #endif + } bits; +} +MAC_TEST_t, *PMAC_TEST_t; + + +/****************************************************************************** + structure for MII Management Configuration reg in mac address map. + located at address 0x5020 + *****************************************************************************/ +typedef union _MII_MGMT_CFG_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reset_mii_mgmt:1; //bit 31 + UINT32 reserved:25; //bits 6-30 + UINT32 scan_auto_incremt:1; //bit 5 + UINT32 preamble_suppress:1; //bit 4 + UINT32 undefined:1; //bit 3 + UINT32 mgmt_clk_reset:3; //bits 0-2 + #else + UINT32 mgmt_clk_reset:3; //bits 0-2 + UINT32 undefined:1; //bit 3 + UINT32 preamble_suppress:1; //bit 4 + UINT32 scan_auto_incremt:1; //bit 5 + UINT32 reserved:25; //bits 6-30 + UINT32 reset_mii_mgmt:1; //bit 31 + #endif + } bits; +} +MII_MGMT_CFG_t, *PMII_MGMT_CFG_t; + + +/****************************************************************************** + structure for MII Management Command reg in mac address map. + located at address 0x5024 + *****************************************************************************/ +typedef union _MII_MGMT_CMD_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:30; //bits 2-31 + UINT32 scan_cycle:1; //bit 1 + UINT32 read_cycle:1; //bit 0 + #else + UINT32 read_cycle:1; //bit 0 + UINT32 scan_cycle:1; //bit 1 + UINT32 reserved:30; //bits 2-31 + #endif + } bits; +} +MII_MGMT_CMD_t, *PMII_MGMT_CMD_t; + + +/****************************************************************************** + structure for MII Management Address reg in mac address map. + located at address 0x5028 + *****************************************************************************/ +typedef union _MII_MGMT_ADDR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved2:19; //bit 13-31 + UINT32 phy_addr:5; //bits 8-12 + UINT32 reserved1:3; //bits 5-7 + UINT32 reg_addr:5; //bits 0-4 + #else + UINT32 reg_addr:5; //bits 0-4 + UINT32 reserved1:3; //bits 5-7 + UINT32 phy_addr:5; //bits 8-12 + UINT32 reserved2:19; //bit 13-31 + #endif + } bits; +} +MII_MGMT_ADDR_t, *PMII_MGMT_ADDR_t; + + +/****************************************************************************** + structure for MII Management Control reg in mac address map. + located at address 0x502C + *****************************************************************************/ +typedef union _MII_MGMT_CTRL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:16; //bits 16-31 + UINT32 phy_ctrl:16; //bits 0-15 + #else + UINT32 phy_ctrl:16; //bits 0-15 + UINT32 reserved:16; //bits 16-31 + #endif + } bits; +} +MII_MGMT_CTRL_t, *PMII_MGMT_CTRL_t; + + +/****************************************************************************** + structure for MII Management Status reg in mac address map. + located at address 0x5030 + *****************************************************************************/ +typedef union _MII_MGMT_STAT_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:16; //bits 16-31 + UINT32 phy_stat:16; //bits 0-15 + #else + UINT32 phy_stat:16; //bits 0-15 + UINT32 reserved:16; //bits 16-31 + #endif + } bits; +} +MII_MGMT_STAT_t, *PMII_MGMT_STAT_t; + + +/****************************************************************************** + structure for MII Management Indicators reg in mac address map. + located at address 0x5034 + *****************************************************************************/ +typedef union _MII_MGMT_INDICATOR_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:29; //bits 3-31 + UINT32 not_valid:1; //bit 2 + UINT32 scanning:1; //bit 1 + UINT32 busy:1; //bit 0 + #else + UINT32 busy:1; //bit 0 + UINT32 scanning:1; //bit 1 + UINT32 not_valid:1; //bit 2 + UINT32 reserved:29; //bits 3-31 + #endif + } bits; +} +MII_MGMT_INDICATOR_t, *PMII_MGMT_INDICATOR_t; + + +/****************************************************************************** + structure for Interface Control reg in mac address map. + located at address 0x5038 + *****************************************************************************/ +typedef union _MAC_IF_CTRL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reset_if_module:1; //bit 31 + UINT32 reserved4:3; //bit 28-30 + UINT32 tbi_mode:1; //bit 27 + UINT32 ghd_mode:1; //bit 26 + UINT32 lhd_mode:1; //bit 25 + UINT32 phy_mode:1; //bit 24 + UINT32 reset_per_mii:1; //bit 23 + UINT32 reserved3:6; //bits 17-22 + UINT32 speed:1; //bit 16 + UINT32 reset_pe100x:1; //bit 15 + UINT32 reserved2:4; //bits 11-14 + UINT32 force_quiet:1; //bit 10 + UINT32 no_cipher:1; //bit 9 + UINT32 disable_link_fail:1; //bit 8 + UINT32 reset_gpsi:1; //bit 7 + UINT32 reserved1:6; //bits 1-6 + UINT32 enab_jab_protect:1; //bit 0 + #else + UINT32 enab_jab_protect:1; //bit 0 + UINT32 reserved1:6; //bits 1-6 + UINT32 reset_gpsi:1; //bit 7 + UINT32 disable_link_fail:1; //bit 8 + UINT32 no_cipher:1; //bit 9 + UINT32 force_quiet:1; //bit 10 + UINT32 reserved2:4; //bits 11-14 + UINT32 reset_pe100x:1; //bit 15 + UINT32 speed:1; //bit 16 + UINT32 reserved3:6; //bits 17-22 + UINT32 reset_per_mii:1; //bit 23 + UINT32 phy_mode:1; //bit 24 + UINT32 lhd_mode:1; //bit 25 + UINT32 ghd_mode:1; //bit 26 + UINT32 tbi_mode:1; //bit 27 + UINT32 reserved4:3; //bit 28-30 + UINT32 reset_if_module:1; //bit 31 + #endif + } bits; +} +MAC_IF_CTRL_t, *PMAC_IF_CTRL_t; + + +/****************************************************************************** + structure for Interface Status reg in mac address map. + located at address 0x503C + *****************************************************************************/ +typedef union _MAC_IF_STAT_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:22; //bits 10-31 + UINT32 excess_defer:1; //bit 9 + UINT32 clash:1; //bit 8 + UINT32 phy_jabber:1; //bit 7 + UINT32 phy_link_ok:1; //bit 6 + UINT32 phy_full_duplex:1; //bit 5 + UINT32 phy_speed:1; //bit 4 + UINT32 pe100x_link_fail:1; //bit 3 + UINT32 pe10t_loss_carrie:1; //bit 2 + UINT32 pe10t_sqe_error:1; //bit 1 + UINT32 pe10t_jabber:1; //bit 0 + #else + UINT32 pe10t_jabber:1; //bit 0 + UINT32 pe10t_sqe_error:1; //bit 1 + UINT32 pe10t_loss_carrie:1; //bit 2 + UINT32 pe100x_link_fail:1; //bit 3 + UINT32 phy_speed:1; //bit 4 + UINT32 phy_full_duplex:1; //bit 5 + UINT32 phy_link_ok:1; //bit 6 + UINT32 phy_jabber:1; //bit 7 + UINT32 clash:1; //bit 8 + UINT32 excess_defer:1; //bit 9 + UINT32 reserved:22; //bits 10-31 + #endif + } bits; +} +MAC_IF_STAT_t, *PMAC_IF_STAT_t; + + +/****************************************************************************** + structure for Mac Station Address, Part 1 reg in mac address map. + located at address 0x5040 + *****************************************************************************/ +typedef union _MAC_STATION_ADDR1_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 Octet6:8; //bits 24-31 + UINT32 Octet5:8; //bits 16-23 + UINT32 Octet4:8; //bits 8-15 + UINT32 Octet3:8; //bits 0-7 + #else + UINT32 Octet3:8; //bits 0-7 + UINT32 Octet4:8; //bits 8-15 + UINT32 Octet5:8; //bits 16-23 + UINT32 Octet6:8; //bits 24-31 + #endif + } bits; +} +MAC_STATION_ADDR1_t, *PMAC_STATION_ADDR1_t; + + +/****************************************************************************** + structure for Mac Station Address, Part 2 reg in mac address map. + located at address 0x5044 + *****************************************************************************/ +typedef union _MAC_STATION_ADDR2_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 Octet2:8; //bits 24-31 + UINT32 Octet1:8; //bits 16-23 + UINT32 reserved:16; //bits 0-15 + #else + UINT32 reserved:16; //bit 0-15 + UINT32 Octet1:8; //bits 16-23 + UINT32 Octet2:8; //bits 24-31 + #endif + } bits; +} +MAC_STATION_ADDR2_t, *PMAC_STATION_ADDR2_t; + + +/****************************************************************************** + MAC Module of JAGCore Address Mapping + *****************************************************************************/ +typedef struct _MAC_t +{ //Location: + MAC_CFG1_t cfg1; // 0x5000 + MAC_CFG2_t cfg2; // 0x5004 + MAC_IPG_t ipg; // 0x5008 + MAC_HFDP_t hfdp; // 0x500C + MAC_MAX_FM_LEN_t max_fm_len; // 0x5010 + MAC_RSV_t rsv1; // 0x5014 + MAC_RSV_t rsv2; // 0x5018 + MAC_TEST_t mac_test; // 0x501C + MII_MGMT_CFG_t mii_mgmt_cfg; // 0x5020 + MII_MGMT_CMD_t mii_mgmt_cmd; // 0x5024 + MII_MGMT_ADDR_t mii_mgmt_addr; // 0x5028 + MII_MGMT_CTRL_t mii_mgmt_ctrl; // 0x502C + MII_MGMT_STAT_t mii_mgmt_stat; // 0x5030 + MII_MGMT_INDICATOR_t mii_mgmt_indicator; // 0x5034 + MAC_IF_CTRL_t if_ctrl; // 0x5038 + MAC_IF_STAT_t if_stat; // 0x503C + MAC_STATION_ADDR1_t station_addr_1; // 0x5040 + MAC_STATION_ADDR2_t station_addr_2; // 0x5044 +} +MAC_t, *PMAC_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF MAC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF MAC STAT REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for Carry Register One and it's Mask Register reg located in mac + stat address map address 0x6130 and 0x6138. + *****************************************************************************/ +typedef union _MAC_STAT_REG_1_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 tr64:1; //bit 31 + UINT32 tr127:1; //bit 30 + UINT32 tr255:1; //bit 29 + UINT32 tr511:1; //bit 28 + UINT32 tr1k:1; //bit 27 + UINT32 trmax:1; //bit 26 + UINT32 trmgv:1; //bit 25 + UINT32 unused:8; //bits 17-24 + UINT32 rbyt:1; //bit 16 + UINT32 rpkt:1; //bit 15 + UINT32 rfcs:1; //bit 14 + UINT32 rmca:1; //bit 13 + UINT32 rbca:1; //bit 12 + UINT32 rxcf:1; //bit 11 + UINT32 rxpf:1; //bit 10 + UINT32 rxuo:1; //bit 9 + UINT32 raln:1; //bit 8 + UINT32 rflr:1; //bit 7 + UINT32 rcde:1; //bit 6 + UINT32 rcse:1; //bit 5 + UINT32 rund:1; //bit 4 + UINT32 rovr:1; //bit 3 + UINT32 rfrg:1; //bit 2 + UINT32 rjbr:1; //bit 1 + UINT32 rdrp:1; //bit 0 + #else + UINT32 rdrp:1; //bit 0 + UINT32 rjbr:1; //bit 1 + UINT32 rfrg:1; //bit 2 + UINT32 rovr:1; //bit 3 + UINT32 rund:1; //bit 4 + UINT32 rcse:1; //bit 5 + UINT32 rcde:1; //bit 6 + UINT32 rflr:1; //bit 7 + UINT32 raln:1; //bit 8 + UINT32 rxuo:1; //bit 9 + UINT32 rxpf:1; //bit 10 + UINT32 rxcf:1; //bit 11 + UINT32 rbca:1; //bit 12 + UINT32 rmca:1; //bit 13 + UINT32 rfcs:1; //bit 14 + UINT32 rpkt:1; //bit 15 + UINT32 rbyt:1; //bit 16 + UINT32 unused:8; //bits 17-24 + UINT32 trmgv:1; //bit 25 + UINT32 trmax:1; //bit 26 + UINT32 tr1k:1; //bit 27 + UINT32 tr511:1; //bit 28 + UINT32 tr255:1; //bit 29 + UINT32 tr127:1; //bit 30 + UINT32 tr64:1; //bit 31 + #endif + } bits; +} +MAC_STAT_REG_1_t, *PMAC_STAT_REG_1_t; + + +/****************************************************************************** + structure for Carry Register Two Mask Register reg in mac stat address map. + located at address 0x613C + *****************************************************************************/ +typedef union _MAC_STAT_REG_2_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:12; //bit 20-31 + UINT32 tjbr:1; //bit 19 + UINT32 tfcs:1; //bit 18 + UINT32 txcf:1; //bit 17 + UINT32 tovr:1; //bit 16 + UINT32 tund:1; //bit 15 + UINT32 tfrg:1; //bit 14 + UINT32 tbyt:1; //bit 13 + UINT32 tpkt:1; //bit 12 + UINT32 tmca:1; //bit 11 + UINT32 tbca:1; //bit 10 + UINT32 txpf:1; //bit 9 + UINT32 tdfr:1; //bit 8 + UINT32 tedf:1; //bit 7 + UINT32 tscl:1; //bit 6 + UINT32 tmcl:1; //bit 5 + UINT32 tlcl:1; //bit 4 + UINT32 txcl:1; //bit 3 + UINT32 tncl:1; //bit 2 + UINT32 tpfh:1; //bit 1 + UINT32 tdrp:1; //bit 0 + #else + UINT32 tdrp:1; //bit 0 + UINT32 tpfh:1; //bit 1 + UINT32 tncl:1; //bit 2 + UINT32 txcl:1; //bit 3 + UINT32 tlcl:1; //bit 4 + UINT32 tmcl:1; //bit 5 + UINT32 tscl:1; //bit 6 + UINT32 tedf:1; //bit 7 + UINT32 tdfr:1; //bit 8 + UINT32 txpf:1; //bit 9 + UINT32 tbca:1; //bit 10 + UINT32 tmca:1; //bit 11 + UINT32 tpkt:1; //bit 12 + UINT32 tbyt:1; //bit 13 + UINT32 tfrg:1; //bit 14 + UINT32 tund:1; //bit 15 + UINT32 tovr:1; //bit 16 + UINT32 txcf:1; //bit 17 + UINT32 tfcs:1; //bit 18 + UINT32 tjbr:1; //bit 19 + UINT32 unused:12; //bit 20-31 + #endif + } bits; +} +MAC_STAT_REG_2_t, *PMAC_STAT_REG_2_t; + + + + +/****************************************************************************** + MAC STATS Module of JAGCore Address Mapping + *****************************************************************************/ +typedef struct _MAC_STAT_t +{ //Location: + UINT32 pad[32]; // 0x6000 - 607C + + //Tx/Rx 0-64 Byte Frame Counter + UINT32 TR64; // 0x6080 + + //Tx/Rx 65-127 Byte Frame Counter + UINT32 TR127; // 0x6084 + + //Tx/Rx 128-255 Byte Frame Counter + UINT32 TR255; // 0x6088 + + //Tx/Rx 256-511 Byte Frame Counter + UINT32 TR511; // 0x608C + + //Tx/Rx 512-1023 Byte Frame Counter + UINT32 TR1K; // 0x6090 + + //Tx/Rx 1024-1518 Byte Frame Counter + UINT32 TRMax; // 0x6094 + + //Tx/Rx 1519-1522 Byte Good VLAN Frame Count + UINT32 TRMgv; // 0x6098 + + //Rx Byte Counter + UINT32 RByt; // 0x609C + + //Rx Packet Counter + UINT32 RPkt; // 0x60A0 + + //Rx FCS Error Counter + UINT32 RFcs; // 0x60A4 + + //Rx Multicast Packet Counter + UINT32 RMca; // 0x60A8 + + //Rx Broadcast Packet Counter + UINT32 RBca; // 0x60AC + + //Rx Control Frame Packet Counter + UINT32 RxCf; // 0x60B0 + + //Rx Pause Frame Packet Counter + UINT32 RxPf; // 0x60B4 + + //Rx Unknown OP Code Counter + UINT32 RxUo; // 0x60B8 + + //Rx Alignment Error Counter + UINT32 RAln; // 0x60BC + + //Rx Frame Length Error Counter + UINT32 RFlr; // 0x60C0 + + //Rx Code Error Counter + UINT32 RCde; // 0x60C4 + + //Rx Carrier Sense Error Counter + UINT32 RCse; // 0x60C8 + + //Rx Undersize Packet Counter + UINT32 RUnd; // 0x60CC + + //Rx Oversize Packet Counter + UINT32 ROvr; // 0x60D0 + + //Rx Fragment Counter + UINT32 RFrg; // 0x60D4 + + //Rx Jabber Counter + UINT32 RJbr; // 0x60D8 + + //Rx Drop + UINT32 RDrp; // 0x60DC + + //Tx Byte Counter + UINT32 TByt; // 0x60E0 + + //Tx Packet Counter + UINT32 TPkt; // 0x60E4 + + //Tx Multicast Packet Counter + UINT32 TMca; // 0x60E8 + + //Tx Broadcast Packet Counter + UINT32 TBca; // 0x60EC + + //Tx Pause Control Frame Counter + UINT32 TxPf; // 0x60F0 + + //Tx Deferral Packet Counter + UINT32 TDfr; // 0x60F4 + + //Tx Excessive Deferral Packet Counter + UINT32 TEdf; // 0x60F8 + + //Tx Single Collision Packet Counter + UINT32 TScl; // 0x60FC + + //Tx Multiple Collision Packet Counter + UINT32 TMcl; // 0x6100 + + //Tx Late Collision Packet Counter + UINT32 TLcl; // 0x6104 + + //Tx Excessive Collision Packet Counter + UINT32 TXcl; // 0x6108 + + //Tx Total Collision Packet Counter + UINT32 TNcl; // 0x610C + + //Tx Pause Frame Honored Counter + UINT32 TPfh; // 0x6110 + + //Tx Drop Frame Counter + UINT32 TDrp; // 0x6114 + + //Tx Jabber Frame Counter + UINT32 TJbr; // 0x6118 + + //Tx FCS Error Counter + UINT32 TFcs; // 0x611C + + //Tx Control Frame Counter + UINT32 TxCf; // 0x6120 + + //Tx Oversize Frame Counter + UINT32 TOvr; // 0x6124 + + //Tx Undersize Frame Counter + UINT32 TUnd; // 0x6128 + + //Tx Fragments Frame Counter + UINT32 TFrg; // 0x612C + + //Carry Register One Register + MAC_STAT_REG_1_t Carry1; // 0x6130 + + //Carry Register Two Register + MAC_STAT_REG_2_t Carry2; // 0x6134 + + //Carry Register One Mask Register + MAC_STAT_REG_1_t Carry1M; // 0x6138 + + //Carry Register Two Mask Register + MAC_STAT_REG_2_t Carry2M; // 0x613C +} +MAC_STAT_t, *PMAC_STAT_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF MAC STAT REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF MMC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + structure for Main Memory Controller Control reg in mmc address map. + located at address 0x7000 + *****************************************************************************/ +typedef union _MMC_CTRL_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 reserved:25; //bits 7-31 + UINT32 force_ce:1; //bit 6 + UINT32 rxdma_disable:1; //bit 5 + UINT32 txdma_disable:1; //bit 4 + UINT32 txmac_disable:1; //bit 3 + UINT32 rxmac_disable:1; //bit 2 + UINT32 arb_disable:1; //bit 1 + UINT32 mmc_enable:1; //bit 0 + #else + UINT32 mmc_enable:1; //bit 0 + UINT32 arb_disable:1; //bit 1 + UINT32 rxmac_disable:1; //bit 2 + UINT32 txmac_disable:1; //bit 3 + UINT32 txdma_disable:1; //bit 4 + UINT32 rxdma_disable:1; //bit 5 + UINT32 force_ce:1; //bit 6 + UINT32 reserved:25; //bits 7-31 + #endif + } bits; +} +MMC_CTRL_t, *PMMC_CTRL_t; + + +/****************************************************************************** + structure for Main Memory Controller Host Memory Access Address reg in mmc + address map. Located at address 0x7004 + *****************************************************************************/ +typedef union _MMC_SRAM_ACCESS_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 byte_enable:16; //bits 16-31 + UINT32 reserved2:2; //bits 14-15 + UINT32 req_addr:10; //bits 4-13 + UINT32 reserved1:1; //bit 3 + UINT32 is_ctrl_word:1; //bit 2 + UINT32 wr_access:1; //bit 1 + UINT32 req_access:1; //bit 0 + #else + UINT32 req_access:1; //bit 0 + UINT32 wr_access:1; //bit 1 + UINT32 is_ctrl_word:1; //bit 2 + UINT32 reserved1:1; //bit 3 + UINT32 req_addr:10; //bits 4-13 + UINT32 reserved2:2; //bits 14-15 + UINT32 byte_enable:16; //bits 16-31 + #endif + } bits; +} +MMC_SRAM_ACCESS_t, *PMMC_SRAM_ACCESS_t; + + +/****************************************************************************** + structure for Main Memory Controller Host Memory Access Data reg in mmc + address map. Located at address 0x7008 - 0x7014 + *****************************************************************************/ +typedef struct _MMC_SRAM_WORD_t +{ + UINT32 data; //bits 0-31 +} MMC_SRAM_WORD_t, *PMMC_SRAM_WORD_t; + + +/****************************************************************************** + Memory Control Module of JAGCore Address Mapping + *****************************************************************************/ +typedef struct _MMC_t +{ //Location: + MMC_CTRL_t mmc_ctrl; // 0x7000 + MMC_SRAM_ACCESS_t sram_access; // 0x7004 + MMC_SRAM_WORD_t sram_word1; // 0x7008 + MMC_SRAM_WORD_t sram_word2; // 0x700C + MMC_SRAM_WORD_t sram_word3; // 0x7010 + MMC_SRAM_WORD_t sram_word4; // 0x7014 +} +MMC_t, *PMMC_t; +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF MMC REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + +/*===========================================================================*/ +/*===========================================================================*/ +/*=== START OF EXP ROM REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ +/****************************************************************************** + Expansion ROM Module of JAGCore Address Mapping + *****************************************************************************/ + +/* Take this out until it is not empty */ +#if 0 +typedef struct _EXP_ROM_t +{ + +} +EXP_ROM_t, *PEXP_ROM_t; +#endif +/*===========================================================================*/ +/*===========================================================================*/ +/*=== END OF EXP ROM REGISTER ADDRESS MAP ===*/ +/*===========================================================================*/ +/*===========================================================================*/ + + + + +/****************************************************************************** + JAGCore Address Mapping + *****************************************************************************/ +typedef struct _ADDRESS_MAP_t +{ + GLOBAL_t global; + UCHAR unused_global[4096 - sizeof (GLOBAL_t)]; //unused section of global address map + TXDMA_t txdma; + UCHAR unused_txdma[4096 - sizeof (TXDMA_t)]; //unused section of txdma address map + RXDMA_t rxdma; + UCHAR unused_rxdma[4096 - sizeof (RXDMA_t)]; //unused section of rxdma address map + TXMAC_t txmac; + UCHAR unused_txmac[4096 - sizeof (TXMAC_t)]; //unused section of txmac address map + RXMAC_t rxmac; + UCHAR unused_rxmac[4096 - sizeof (RXMAC_t)]; //unused section of rxmac address map + MAC_t mac; + UCHAR unused_mac[4096 - sizeof (MAC_t)]; //unused section of mac address map + MAC_STAT_t macStat; + UCHAR unused_mac_stat[4096 - sizeof (MAC_STAT_t)]; //unused section of mac stat address map + MMC_t mmc; + UCHAR unused_mmc[4096 - sizeof (MMC_t)]; //unused section of mmc address map + UCHAR unused_[1015808]; //unused section of address map + +/* Take this out until it is not empty */ +#if 0 + EXP_ROM_t exp_rom; +#endif + + UCHAR unused_exp_rom[4096]; //MGS-size TBD + UCHAR unused__[524288]; //unused section of address map +} +ADDRESS_MAP_t, *PADDRESS_MAP_t; +/*===========================================================================*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _ET1310_ADDRESS_MAP_H_ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_jagcore.h +++ linux-2.6.27/ubuntu/et131x/ET1310_jagcore.h @@ -0,0 +1,180 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_jagcore.h - Defines, structs, enums, prototypes, etc. pertaining to + * the JAGCore + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 18:43:44 $ + $Revision: 1.7 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET1310_JAGCORE_H__ +#define __ET1310_JAGCORE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/****************************************************************************** + INCLUDES + *****************************************************************************/ +#include "ET1310_common.h" + + + + +/****************************************************************************** + CONSTANTS FOR JAGCORE + *****************************************************************************/ +#define INTERNAL_MEM_SIZE 0x400 //1024 of internal memory +#define INTERNAL_MEM_RX_OFFSET 0x1FF //50% Tx, 50% Rx + +#define REGS_MAX_ARRAY 4096 + + + + +/****************************************************************************** + For interrupts, normal running is: + rxdma_xfr_done, phy_interrupt, mac_stat_interrupt, + watchdog_interrupt & txdma_xfer_done + + In both cases, when flow control is enabled for either Tx or bi-direction, + we additional enable rx_fbr0_low and rx_fbr1_low, so we know when the + buffer rings are running low. + *****************************************************************************/ +#define INT_MASK_DISABLE 0xffffffff + +// NOTE: Masking out MAC_STAT Interrupt for now... +//#define INT_MASK_ENABLE 0xfff6bf17 +//#define INT_MASK_ENABLE_NO_FLOW 0xfff6bfd7 +#define INT_MASK_ENABLE 0xfffebf17 +#define INT_MASK_ENABLE_NO_FLOW 0xfffebfd7 + + + + +/****************************************************************************** + DATA STRUCTURES FOR DIRECT REGISTER ACCESS + *****************************************************************************/ +typedef struct +{ + u8 bReadWrite; + u32 nRegCount; + u32 nData [REGS_MAX_ARRAY]; + u32 nOffsets [REGS_MAX_ARRAY]; +} JAGCORE_ACCESS_REGS, *PJAGCORE_ACCESS_REGS; + + +typedef struct +{ + u8 bReadWrite; + u32 nDataWidth; + u32 nRegCount; + u32 nOffsets [REGS_MAX_ARRAY]; + u32 nData [REGS_MAX_ARRAY]; +} PCI_CFG_SPACE_REGS, *PPCI_CFG_SPACE_REGS; + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + + + +/****************************************************************************** + PROTOTYPES + *****************************************************************************/ +void ConfigGlobalRegs(struct et131x_adapter *pAdapter ); + +void ConfigMMCRegs( struct et131x_adapter *pAdapter ); + +void et131x_enable_interrupts( struct et131x_adapter *adapter ); + +void et131x_disable_interrupts( struct et131x_adapter *adapter ); + +void * et131x_get_regs( struct et131x_adapter *pAdapter, void *InfoBuf, + PUINT32 ulBytesAvailable, PUINT32 ulInfoLen ); + +void et131x_set_regs( struct et131x_adapter *pAdapter, void *InfoBuf ); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ET1310_JAGCORE_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_mac.h +++ linux-2.6.27/ubuntu/et131x/ET1310_mac.h @@ -0,0 +1,140 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_mac.h - Defines, structs, enums, prototypes, etc. pertaining to the + * MAC. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:11 $ + $Revision: 1.5 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef _ET1310_MAC_H_ +#define _ET1310_MAC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/****************************************************************************** + INCLUDES + *****************************************************************************/ +#include "ET1310_common.h" + + + + +/****************************************************************************** + MACSTAT #defines + *****************************************************************************/ +#define COUNTER_WRAP_28_BIT 0x10000000 +#define COUNTER_WRAP_22_BIT 0x400000 +#define COUNTER_WRAP_16_BIT 0x10000 +#define COUNTER_WRAP_12_BIT 0x1000 + +#define COUNTER_MASK_28_BIT (COUNTER_WRAP_28_BIT - 1) +#define COUNTER_MASK_22_BIT (COUNTER_WRAP_22_BIT - 1) +#define COUNTER_MASK_16_BIT (COUNTER_WRAP_16_BIT - 1) +#define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1) + +#define UPDATE_COUNTER(HostCnt,DevCnt) \ + HostCnt = HostCnt + DevCnt; + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + +/****************************************************************************** + PROTOTYPES + *****************************************************************************/ +void ConfigMACRegs1( struct et131x_adapter *pAdapter ); +void ConfigMACRegs2( struct et131x_adapter *pAdapter ); +void ConfigRxMacRegs( struct et131x_adapter *pAdapter ); +void ConfigTxMacRegs( struct et131x_adapter *pAdapter ); +void ConfigMacStatRegs( struct et131x_adapter *pAdapter ); +void ConfigFlowControl( struct et131x_adapter *pAdapter ); +void UpdateMacStatHostCounters( struct et131x_adapter *pAdapter ); +void HandleMacStatInterrupt( struct et131x_adapter *pAdapter ); +void SetupDeviceForMulticast( struct et131x_adapter *pAdapter ); +void SetupDeviceForUnicast( struct et131x_adapter *pAdapter ); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _ET1310_MAC_H_ */ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_tx.c +++ linux-2.6.27/ubuntu/et131x/ET1310_tx.c @@ -0,0 +1,2084 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_tx.c - Routines used to perform data transmission. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2006/01/20 21:29:44 $ + $Revision: 1.24 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#include +#endif + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" +#include "et131x_isr.h" + +#include "ET1310_tx.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Prototypes for functions local to this module + *****************************************************************************/ +void et131x_update_tcb_list( ET131X_ADAPTER *pAdapter ); +void et131x_check_send_wait_list( ET131X_ADAPTER *pAdapter ); +__inline void et131x_free_send_packet( ET131X_ADAPTER *pAdapter, PMP_TCB pMpTcb ); + +int et131x_send_packet( struct sk_buff *skb, ET131X_ADAPTER *pAdapter ); +int nic_send_packet( ET131X_ADAPTER *pAdapter, PMP_TCB pMpTcb ); + + + + +/****************************************************************************** + ROUTINE : et131x_tx_dma_memory_alloc + ****************************************************************************** + + DESCRIPTION : Allocates memory that will be visible both to the device + and to the CPU. The OS will pass us packets, pointers to + which we will insert in the Tx Descriptor queue. The + device will read this queue to find the packets in + memory. The device will update the "status" in memory + each time it xmits a packet. + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +int et131x_tx_dma_memory_alloc( ET131X_ADAPTER *adapter ) +{ + int desc_size = 0; + TX_RING_t *tx_ring; + MP_TCB *tcb; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_tx_dma_memory_alloc" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Allocate memory for the TCB's (Transmit Control Block) + *************************************************************************/ + adapter->TxRing.MpTcbMem = kmalloc( NUM_TCB * sizeof( MP_TCB ), + GFP_ATOMIC | GFP_DMA ); + if( !adapter->TxRing.MpTcbMem ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for TCBs\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + memset( adapter->TxRing.MpTcbMem, 0, ( NUM_TCB * sizeof( MP_TCB ))); + + + /************************************************************************** + Setup some convenience pointers + *************************************************************************/ + tx_ring = (TX_RING_t *)&adapter->TxRing; + tcb = (MP_TCB *)adapter->TxRing.MpTcbMem; + + + /************************************************************************** + Allocate enough memory for the Tx descriptor ring, and allocate some + extra so that the ring can be aligned on a 4k boundary. + *************************************************************************/ + desc_size = ( sizeof( TX_DESC_ENTRY_t ) * NUM_DESC_PER_RING_TX ) + 4096 - 1; + tx_ring->pTxDescRingVa = (PTX_DESC_ENTRY_t)pci_alloc_consistent( adapter->pdev, + desc_size, + &tx_ring->pTxDescRingPa ); + if( !adapter->TxRing.pTxDescRingVa ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for Tx Ring\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Save physical address + + NOTE : pci_alloc_consistent(), used above to alloc DMA regions, ALWAYS + returns SAC (32-bit) addresses. If DAC (64-bit) addresses are + ever returned, make sure the high part is retrieved here before + storing the adjusted address. + *************************************************************************/ + tx_ring->pTxDescRingAdjustedPa = tx_ring->pTxDescRingPa; + + + /************************************************************************** + Align Tx Descriptor Ring on a 4k (0x1000) byte boundary + *************************************************************************/ + et131x_align_allocated_memory( adapter, + &tx_ring->pTxDescRingAdjustedPa, + &tx_ring->TxDescOffset, + 0x0FFF ); + + tx_ring->pTxDescRingVa += tx_ring->TxDescOffset; + + + /************************************************************************** + Allocate memory for the Tx status block + *************************************************************************/ + tx_ring->pTxStatusVa = pci_alloc_consistent( adapter->pdev, + sizeof( TX_STATUS_BLOCK_t ), + &tx_ring->pTxStatusPa ); + if( !adapter->TxRing.pTxStatusPa ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for Tx status block\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + /************************************************************************** + Allocate memory for a dummy buffer + *************************************************************************/ + tx_ring->pTxDummyBlkVa = pci_alloc_consistent( adapter->pdev, + NIC_MIN_PACKET_SIZE, + &tx_ring->pTxDummyBlkPa ); + if( !adapter->TxRing.pTxDummyBlkPa ) + { + DBG_ERROR( et131x_dbginfo, "Cannot alloc memory for Tx dummy buffer\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + + DBG_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_tx_dma_memory_free + ****************************************************************************** + + DESCRIPTION : Free all memory allocated within this module + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : 0 on success + errno on failure (as defined in errno.h) + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_tx_dma_memory_free( ET131X_ADAPTER *adapter ) +{ + int desc_size = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_tx_dma_memory_free" ); + DBG_ENTER( et131x_dbginfo ); + + + if( adapter->TxRing.pTxDescRingVa ) + { + /********************************************************************** + Free memory relating to Tx rings here + *********************************************************************/ + adapter->TxRing.pTxDescRingVa -= adapter->TxRing.TxDescOffset; + + desc_size = ( sizeof( TX_DESC_ENTRY_t ) * NUM_DESC_PER_RING_TX ) + 4096 - 1; + + pci_free_consistent( adapter->pdev, + desc_size, + adapter->TxRing.pTxDescRingVa, + adapter->TxRing.pTxDescRingPa ); + + adapter->TxRing.pTxDescRingVa = NULL ; + } + + + /************************************************************************** + Free memory for the Tx status block + *************************************************************************/ + if( adapter->TxRing.pTxStatusVa ) + { + pci_free_consistent( adapter->pdev, + sizeof( TX_STATUS_BLOCK_t ), + adapter->TxRing.pTxStatusVa, + adapter->TxRing.pTxStatusPa ); + + adapter->TxRing.pTxStatusVa = NULL ; + } + + + /************************************************************************** + Free memory for the dummy buffer + *************************************************************************/ + if( adapter->TxRing.pTxDummyBlkVa ) + { + pci_free_consistent( adapter->pdev, + NIC_MIN_PACKET_SIZE, + adapter->TxRing.pTxDummyBlkVa, + adapter->TxRing.pTxDummyBlkPa ); + + adapter->TxRing.pTxDummyBlkVa = NULL ; + } + + + /************************************************************************** + Free the memory for MP_TCB structures + *************************************************************************/ + if( adapter->TxRing.MpTcbMem ) + { + kfree( adapter->TxRing.MpTcbMem ); + adapter->TxRing.MpTcbMem = NULL; + } + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : ConfigTxDmaRegs + ****************************************************************************** + + DESCRIPTION : Used to set up the tx dma section of the JAGCore. + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void ConfigTxDmaRegs( ET131X_ADAPTER *pAdapter ) +{ + PTXDMA_t pTxDma; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigTxDmaRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + First lets get a copy of the pointer + *************************************************************************/ + pTxDma = &pAdapter->CSRAddress->txdma; + + + /************************************************************************** + Load the hardware with the start of the transmit descriptor ring. + *************************************************************************/ + pTxDma->pr_base_hi.addr_hi = + (UINT32)( pAdapter->TxRing.pTxDescRingAdjustedPa >> 32 ); + pTxDma->pr_base_lo.addr_lo = + (UINT32)( pAdapter->TxRing.pTxDescRingAdjustedPa ); + + + /************************************************************************** + Initialise the transmit DMA engine + *************************************************************************/ + pTxDma->pr_num_des.value = NUM_DESC_PER_RING_TX - 1; + + + /************************************************************************** + Load the completion writeback physical address + + NOTE : pci_alloc_consistent(), used above to alloc DMA regions, ALWAYS + returns SAC (32-bit) addresses. If DAC (64-bit) addresses are + ever returned, make sure the high part is retrieved here before + storing the adjusted address. + *************************************************************************/ + pTxDma->dma_wb_base_hi.addr_hi = 0x0; + pTxDma->dma_wb_base_lo.addr_lo = pAdapter->TxRing.pTxStatusPa; + + memset( pAdapter->TxRing.pTxStatusVa, 0, sizeof( TX_STATUS_BLOCK_t )); + + + pTxDma->service_request.value = 0x0; + pAdapter->TxRing.txDmaReadyToSend.value = 0x0; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_tx_dma_disable + ****************************************************************************** + DESCRIPTION: + Stop OF Tx_DMA on the ET1310 + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + N/A + + *****************************************************************************/ +void et131x_tx_dma_disable( ET131X_ADAPTER *pAdapter ) +{ + DBG_FUNC( "et131x_tx_dma_disable" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Setup the tramsmit dma configuration register + *************************************************************************/ + pAdapter->CSRAddress->txdma.csr.value = 0x101; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_tx_dma_enable + ****************************************************************************** + DESCRIPTION: + re-start OF Tx_DMA on the ET1310. Mainly used after a return to the + D0 (full-power) state from a lower state. + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + N/A + + *****************************************************************************/ +void et131x_tx_dma_enable( ET131X_ADAPTER *pAdapter ) +{ + TXDMA_CSR_t csr = {0}; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_tx_dma_enable" ); + DBG_ENTER( et131x_dbginfo ); + + + if( pAdapter->RegistryPhyLoopbk ) + { + /********************************************************************** + TxDMA is disabled for loopback operation. + *********************************************************************/ + pAdapter->CSRAddress->txdma.csr.value = 0x101; + + } + else + { + /********************************************************************** + Setup the transmit dma configuration register for normal operation + *********************************************************************/ + csr.bits.sngl_epkt_mode = 1; + csr.bits.halt = 0; + csr.bits.cache_thrshld = pAdapter->RegistryDMACache; + + pAdapter->CSRAddress->txdma.csr.value = csr.value; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_init_send + ****************************************************************************** + + DESCRIPTION : Initialize send data structures + + PARAMETERS : adapter - pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_init_send( ET131X_ADAPTER *adapter ) +{ + PMP_TCB pMpTcb; + UINT32 TcbCount; + TX_RING_t *tx_ring; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_init_send" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Setup some convenience pointers + *************************************************************************/ + tx_ring = (TX_RING_t *)&adapter->TxRing; + pMpTcb = (PMP_TCB)adapter->TxRing.MpTcbMem; + + + tx_ring->TCBReadyQueueHead = pMpTcb; + + + /************************************************************************** + Go through and set up each TCB + *************************************************************************/ + for( TcbCount = 0; TcbCount < NUM_TCB; TcbCount++ ) + { + memset( pMpTcb, 0, sizeof( MP_TCB )); + + + /********************************************************************** + Set the link pointer in HW TCB to the next TCB in the chain. If + this is the last TCB in the chain, also set the tail pointer. + *********************************************************************/ + if( TcbCount < NUM_TCB - 1 ) + { + pMpTcb->Next = pMpTcb + 1; + } + else + { + tx_ring->TCBReadyQueueTail = pMpTcb; + pMpTcb->Next = (PMP_TCB)NULL; + } + + pMpTcb++; + } + + /************************************************************************** + Curr send queue should now be empty + *************************************************************************/ + tx_ring->CurrSendHead = (PMP_TCB)NULL; + tx_ring->CurrSendTail = (PMP_TCB)NULL; + + INIT_LIST_HEAD( &adapter->TxRing.SendWaitQueue ); + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_send_packets + ****************************************************************************** + + DESCRIPTION: + This function is called by the OS to send packets + + PARAMETERS : + skb - the packet(s) to send + netdev - the net_device struct corresponding to the device on which to + TX the above packet(s) + + RETURN : + 0 in almost all cases + non-zero value in extreme hard failure only + + *****************************************************************************/ +int et131x_send_packets( struct sk_buff *skb, struct net_device *netdev ) +{ + int status = 0; + ET131X_ADAPTER *pAdapter = NULL; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_send_packets" ); + DBG_TX_ENTER( et131x_dbginfo ); + + + pAdapter = netdev_priv( netdev ); + + + /************************************************************************** + Send these packets + + NOTE: The Linux Tx entry point is only given one packet at a time + to Tx, so the PacketCount and it's array used makes no sense here + *************************************************************************/ + + /************************************************************************** + Queue is not empty or TCB is not available + *************************************************************************/ + if( !list_empty( &pAdapter->TxRing.SendWaitQueue ) || + MP_TCB_RESOURCES_NOT_AVAILABLE( pAdapter )) + { + /********************************************************************** + NOTE - If there's an error on send, no need to queue the + packet under Linux; if we just send an error up to the netif + layer, it will resend the skb to us. + *********************************************************************/ + DBG_VERBOSE( et131x_dbginfo, + "TCB Resources Not Available\n" ); + status = -ENOMEM; + } + else + { + /********************************************************************** + We need to see if the link is up; if it's not, make the netif layer + think we're good and drop the packet + *********************************************************************/ + //if( MP_SHOULD_FAIL_SEND( pAdapter ) || pAdapter->DriverNoPhyAccess ) + if( MP_SHOULD_FAIL_SEND( pAdapter ) || pAdapter->DriverNoPhyAccess || + !netif_carrier_ok( netdev )) + { + DBG_VERBOSE( et131x_dbginfo, + "Can't Tx, Link is DOWN; drop the packet\n" ); + + dev_kfree_skb_any( skb ); + skb = NULL; + + pAdapter->net_stats.tx_dropped++; + } + else + { + status = et131x_send_packet( skb, pAdapter ); + + if( status == -ENOMEM ) + { + + /************************************************************** + NOTE - If there's an error on send, no need to queue the + packet under Linux; if we just send an error up to the netif + layer, it will resend the skb to us. + *************************************************************/ + DBG_WARNING( et131x_dbginfo, + "Resources problem, Queue tx packet\n" ); + } + else if( status != 0 ) + { + /************************************************************** + On any other error, make netif think we're OK and drop the + packet + *************************************************************/ + DBG_WARNING( et131x_dbginfo, + "General error, drop packet\n" ); + + dev_kfree_skb_any( skb ); + skb = NULL; + + pAdapter->net_stats.tx_dropped++; + } + } + } + + + DBG_TX_LEAVE( et131x_dbginfo ); + return status; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_send_packet + ****************************************************************************** + DESCRIPTION: + Do the work to send a packet + + Assumption: Send spinlock has been acquired + + PARAMETERS : + skb - the packet(s) to send + pAdapter - a pointer to the device's private adapter structure + + RETURN : + 0 in almost all cases + non-zero value in extreme hard failure only + + *****************************************************************************/ +int et131x_send_packet( struct sk_buff *skb, ET131X_ADAPTER *pAdapter ) +{ + int status = 0; + PMP_TCB pMpTcb = NULL; + PUINT16 pShBufVa; + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_send_packet" ); + DBG_TX_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Is our buffer scattered, or continuous? + *************************************************************************/ + if( skb_shinfo( skb )->nr_frags == 0 ) + { + DBG_TX( et131x_dbginfo, "Scattered buffer: NO\n" ); + } + else + { + DBG_TX( et131x_dbginfo, "Scattered buffer: YES, Num Frags: %d\n", + skb_shinfo( skb )->nr_frags ); + } + + + /************************************************************************** + All packets must have at least a MAC address and a protocol type + *************************************************************************/ + if( skb->len < ETH_HLEN ) + { + DBG_ERROR( et131x_dbginfo, "Packet size < ETH_HLEN (14 bytes)\n" ); + DBG_LEAVE( et131x_dbginfo ); + return -EIO; + } + + + /************************************************************************** + Is this packet VLAN tagged? If so, is it a tag previously registered? + If not, drop the packet + + NOTE - We need not worry about the above note for now, as VLAN is handled + by the linux kernel (for the most part). + *************************************************************************/ +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#if defined __vlan_get_tag + { + unsigned short vlan_tag; + + if( __vlan_get_tag( skb, &vlan_tag ) == -EINVAL ) + { + DBG_TX( et131x_dbginfo, + "VLAN: No TX packet tag\n" ); + } + else + { + DBG_TX( et131x_dbginfo, + "VLAN: TX packet tag: %d\n", vlan_tag ); + } + } +#endif +#endif + + + /************************************************************************** + Get a TCB for this packet + *************************************************************************/ + spin_lock_irqsave( &pAdapter->TCBReadyQLock, lockflags ); + + pMpTcb = pAdapter->TxRing.TCBReadyQueueHead; + + if( pMpTcb == NULL ) + { + spin_unlock_irqrestore( &pAdapter->TCBReadyQLock, lockflags ); + + DBG_WARNING( et131x_dbginfo, "Can't obtain a TCB\n" ); + DBG_TX_LEAVE( et131x_dbginfo ); + return -ENOMEM; + } + + pAdapter->TxRing.TCBReadyQueueHead = pMpTcb->Next; + + if( pAdapter->TxRing.TCBReadyQueueHead == NULL ) + { + pAdapter->TxRing.TCBReadyQueueTail = NULL; + } + + spin_unlock_irqrestore( &pAdapter->TCBReadyQLock, lockflags ); + + pMpTcb->PacketLength = skb->len; + pMpTcb->Packet = skb; + + if(( skb->data != NULL ) && (( skb->len - skb->data_len ) >= 6 )) + { + pShBufVa = (PUINT16)skb->data; + + if(( pShBufVa [0] == 0xffff ) && + ( pShBufVa [1] == 0xffff ) && + ( pShBufVa [2] == 0xffff )) + { + MP_SET_FLAG( pMpTcb, fMP_DEST_BROAD ); + } + else if(( pShBufVa [0] & 0x3 ) == 0x0001 ) + { + MP_SET_FLAG( pMpTcb, fMP_DEST_MULTI ); + } + } + + pMpTcb->Next = NULL; + + + /************************************************************************** + Call the NIC specific send handler. + *************************************************************************/ + if( status == 0 ) + { + status = nic_send_packet( pAdapter, pMpTcb ); + } + + if( status != 0 ) + { + spin_lock_irqsave( &pAdapter->TCBReadyQLock, lockflags ); + + if( pAdapter->TxRing.TCBReadyQueueTail ) + { + pAdapter->TxRing.TCBReadyQueueTail->Next = pMpTcb; + } + else + { + /****************************************************************** + Apparently ready Q is empty. + *****************************************************************/ + pAdapter->TxRing.TCBReadyQueueHead = pMpTcb; + } + + pAdapter->TxRing.TCBReadyQueueTail = pMpTcb; + + spin_unlock_irqrestore( &pAdapter->TCBReadyQLock, lockflags ); + + DBG_TX_LEAVE( et131x_dbginfo ); + return status ; + } + + DBG_ASSERT( pAdapter->TxRing.nBusySend <= NUM_TCB ); + + + DBG_TX_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: nic_send_packet + ****************************************************************************** + DESCRIPTION: + NIC specific send handler. This version of the send routine is designed + for version B silicon. + + PARAMETERS : + pAdapter - pointer to our adapter + pMpTcb - pointer to MP_TCB + + RETURNS : + 0 or errno + + *****************************************************************************/ +int nic_send_packet( ET131X_ADAPTER *pAdapter, PMP_TCB pMpTcb ) +{ + UINT32 loopIndex; + TX_DESC_ENTRY_t CurDesc[24]; + UINT32 FragmentNumber = 0; + UINT32 iThisCopy, iRemainder; + struct sk_buff *pPacket = pMpTcb->Packet; + UINT32 FragListCount = skb_shinfo( pPacket )->nr_frags + 1; + struct skb_frag_struct *pFragList = &skb_shinfo( pPacket )->frags[0]; + unsigned long lockflags1, lockflags2; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "nic_send_packet" ); + DBG_TX_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Part of the optimizations of this send routine restrict us to + sending 24 fragments at a pass. In practice we should never see more + than 5 fragments. + + NOTE: The older version of this function (below) can handle any number + of fragments. If needed, we can call this function, although it is less + efficient. + *************************************************************************/ + if( FragListCount > 23 ) + { + DBG_TX_LEAVE( et131x_dbginfo ); + return -EIO; + } + + memset( CurDesc, 0, sizeof( TX_DESC_ENTRY_t ) * ( FragListCount + 1 )); + + for( loopIndex = 0; loopIndex < FragListCount; loopIndex++ ) + { + /********************************************************************** + If there is something in this element, lets get a descriptor from + the ring and get the necessary data + *********************************************************************/ + if( loopIndex == 0 ) + { + /****************************************************************** + If the fragments are smaller than a standard MTU, then map them + to a single descriptor in the Tx Desc ring. However, if they're + larger, as is possible with support for jumbo packets, then + split them each across 2 descriptors. + + This will work until we determine why the hardware doesn't seem + to like large fragments. + *****************************************************************/ + if(( pPacket->len - pPacket->data_len ) <= 1514 ) + { + DBG_TX( et131x_dbginfo, + "Got packet of length %d, " + "filling desc entry %d, " + "TCB: 0x%p\n", + ( pPacket->len - pPacket->data_len ), + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req, + pMpTcb ); + + CurDesc[FragmentNumber].DataBufferPtrHigh = 0; + + CurDesc[FragmentNumber].word2.bits.length_in_bytes = + pPacket->len - pPacket->data_len; + + /****************************************************************** + NOTE - Here, the dma_addr_t returned from pci_map_single() is + implicitly cast as a UINT32. Although dma_addr_t can be 64-bit, + the address returned by pci_map_single() is always 32-bit + addressable (as defined by the pci/dma subsystem) + ******************************************************************/ + CurDesc[FragmentNumber++].DataBufferPtrLow = pci_map_single( pAdapter->pdev, + pPacket->data, + pPacket->len - pPacket->data_len, + PCI_DMA_TODEVICE ); + } + else + { + DBG_TX( et131x_dbginfo, + "Got packet of length %d, " + "filling desc entry %d, " + "TCB: 0x%p\n", + ( pPacket->len - pPacket->data_len ), + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req, + pMpTcb ); + + CurDesc[FragmentNumber].DataBufferPtrHigh = 0; + + CurDesc[FragmentNumber].word2.bits.length_in_bytes = + (( pPacket->len - pPacket->data_len ) / 2 ); + + /****************************************************************** + NOTE - Here, the dma_addr_t returned from pci_map_single() is + implicitly cast as a UINT32. Although dma_addr_t can be 64-bit, + the address returned by pci_map_single() is always 32-bit + addressable (as defined by the pci/dma subsystem) + ******************************************************************/ + CurDesc[FragmentNumber++].DataBufferPtrLow = pci_map_single( pAdapter->pdev, + pPacket->data, + (( pPacket->len - pPacket->data_len ) / 2 ), + PCI_DMA_TODEVICE ); + CurDesc[FragmentNumber].DataBufferPtrHigh = 0; + + CurDesc[FragmentNumber].word2.bits.length_in_bytes = + (( pPacket->len - pPacket->data_len ) / 2 ); + + /****************************************************************** + NOTE - Here, the dma_addr_t returned from pci_map_single() is + implicitly cast as a UINT32. Although dma_addr_t can be 64-bit, + the address returned by pci_map_single() is always 32-bit + addressable (as defined by the pci/dma subsystem) + ******************************************************************/ + CurDesc[FragmentNumber++].DataBufferPtrLow = pci_map_single( pAdapter->pdev, + pPacket->data + (( pPacket->len - pPacket->data_len ) / 2 ), + (( pPacket->len - pPacket->data_len ) / 2 ), + PCI_DMA_TODEVICE ); + } + } + else + { + DBG_TX( et131x_dbginfo, + "Got packet of length %d," + "filling desc entry %d\n" + "TCB: 0x%p\n", + pFragList[loopIndex].size, + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req, + pMpTcb ); + + CurDesc[FragmentNumber].DataBufferPtrHigh = 0; + + + CurDesc[FragmentNumber].word2.bits.length_in_bytes = + pFragList[loopIndex - 1].size; + + /****************************************************************** + NOTE - Here, the dma_addr_t returned from pci_map_page() is + implicitly cast as a UINT32. Although dma_addr_t can be 64-bit, + the address returned by pci_map_page() is always 32-bit + addressable (as defined by the pci/dma subsystem) + ******************************************************************/ + CurDesc[FragmentNumber++].DataBufferPtrLow = pci_map_page( pAdapter->pdev, + pFragList[loopIndex - 1].page, + pFragList[loopIndex - 1].page_offset, + pFragList[loopIndex - 1].size, + PCI_DMA_TODEVICE ); + } + } + + if( FragmentNumber == 0 ) + { + DBG_WARNING( et131x_dbginfo, "No. frags is 0\n" ); + return -EIO; + } + + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS ) + { + if( ++pAdapter->TxRing.TxPacketsSinceLastinterrupt == + pAdapter->RegistryTxNumBuffers ) + { + CurDesc[FragmentNumber - 1].word3.value = 0x5; + pAdapter->TxRing.TxPacketsSinceLastinterrupt = 0; + } + else + { + CurDesc[FragmentNumber - 1].word3.value = 0x1; + } + } + else + { + CurDesc[FragmentNumber - 1].word3.value = 0x5; + } + + CurDesc[0].word3.bits.f = 1; + + pMpTcb->WrIndexStart = pAdapter->TxRing.txDmaReadyToSend; + + pMpTcb->PacketStaleCount = 0; + + spin_lock_irqsave( &pAdapter->SendHWLock, lockflags1 ); + + iThisCopy = NUM_DESC_PER_RING_TX - pAdapter->TxRing.txDmaReadyToSend.bits.serv_req; + + if( iThisCopy >= FragmentNumber ) + { + iRemainder = 0; + iThisCopy = FragmentNumber; + } + else + { + iRemainder = FragmentNumber - iThisCopy; + } + + memcpy( pAdapter->TxRing.pTxDescRingVa + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req, + CurDesc, + sizeof( TX_DESC_ENTRY_t ) * iThisCopy ); + + + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req += iThisCopy; + + if(( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req == 0 ) || + ( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req == NUM_DESC_PER_RING_TX)) + { + if( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req_wrap ) + { + pAdapter->TxRing.txDmaReadyToSend.value = 0; + } + else + { + pAdapter->TxRing.txDmaReadyToSend.value = 0x400; + } + } + + if( iRemainder ) + { + memcpy( pAdapter->TxRing.pTxDescRingVa, + CurDesc + iThisCopy, + sizeof( TX_DESC_ENTRY_t ) * iRemainder ); + + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req += iRemainder; + } + + if( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req == 0 ) + { + if( pAdapter->TxRing.txDmaReadyToSend.value ) + { + pMpTcb->WrIndex.value = NUM_DESC_PER_RING_TX - 1; + } + else + { + pMpTcb->WrIndex.value = 0x400 | ( NUM_DESC_PER_RING_TX - 1 ); + } + } + else + { + pMpTcb->WrIndex.value = pAdapter->TxRing.txDmaReadyToSend.value - 1; + } + + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags2 ); + + if( pAdapter->TxRing.CurrSendTail ) + { + pAdapter->TxRing.CurrSendTail->Next = pMpTcb; + } + else + { + pAdapter->TxRing.CurrSendHead = pMpTcb; + } + + pAdapter->TxRing.CurrSendTail = pMpTcb; + + DBG_ASSERT( pMpTcb->Next == NULL ); + + pAdapter->TxRing.nBusySend++; + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags2 ); + + + /************************************************************************** + Write the new write pointer back to the device. + *************************************************************************/ + pAdapter->CSRAddress->txdma.service_request.value = + pAdapter->TxRing.txDmaReadyToSend.value; + + + /************************************************************************** + For Gig only, we use Tx Interrupt coalescing. Enable the software + timer to wake us up if this packet isn't followed by N more. + *************************************************************************/ + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS ) + { + pAdapter->CSRAddress->global.watchdog_timer = + pAdapter->RegistryTxTimeInterval * NANO_IN_A_MICRO; + } + + spin_unlock_irqrestore( &pAdapter->SendHWLock, lockflags1 ); + + + DBG_TX_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ + + + + +/* NOTE - For now, keep this older version of NICSendPacket around for + reference, even though it's not used */ +#if 0 + +/****************************************************************************** + ROUTINE: NICSendPacket + ****************************************************************************** + DESCRIPTION: + NIC specific send handler. This version of the send routine is designed + for version A silicon. + + Assumption: Send spinlock has been acquired + + PARAMETERS : + pAdapter - pointer to our adapter + pMpTcb - pointer to MP_TCB + pFragList - pointer to the frag list to be filled + + RETURNS : + 0 on succes, errno on failure + + *****************************************************************************/ +int nic_send_packet( ET131X_ADAPTER *pAdapter, PMP_TCB pMpTcb ) +{ + UINT32 loopIndex, fragIndex, loopEnd; + UINT32 iSplitFirstElement = 0; + UINT32 SegmentSize = 0; + TX_DESC_ENTRY_t CurDesc; + TX_DESC_ENTRY_t *CurDescPostCopy = NULL; + UINT32 SlotsAvailable; + TXDMA_SERVICE_COMPLETE_t ServiceComplete = pAdapter->CSRAddress->txdma.NewServiceComplete; + unsigned int lockflags1, lockflags2; + struct sk_buff *pPacket = pMpTcb->Packet; + UINT32 FragListCount = skb_shinfo( pPacket )->nr_frags + 1; + struct skb_frag_struct *pFragList = &skb_shinfo( pPacket )->frags[0]; + PGLOBAL_t pGbl; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "nic_send_packet" ); + DBG_TX_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Attempt to fix TWO hardware bugs: + 1) NEVER write an odd number of descriptors. + 2) If packet length is less than NIC_MIN_PACKET_SIZE, then pad the + packet to NIC_MIN_PACKET_SIZE bytes by adding a new last + descriptor IN HALF DUPLEX MODE ONLY + NOTE that (2) interacts with (1). If the packet is less than + NIC_MIN_PACKET_SIZE bytes then we will append a descriptor. Therefore + if it is even now, it will eventually end up odd, and so will need + adjusting. + + VLAN tags get involved since VLAN tags add another one or two + segments. + *************************************************************************/ + DBG_TX( et131x_dbginfo, + "pMpTcb->PacketLength: %d\n", pMpTcb->PacketLength ); + + if(( pAdapter->uiDuplexMode == 0 ) && ( pMpTcb->PacketLength < NIC_MIN_PACKET_SIZE )) + { + DBG_TX( et131x_dbginfo, + "HALF DUPLEX mode AND len < MIN_PKT_SIZE\n" ); + if(( FragListCount & 0x1 ) == 0 ) + { + DBG_TX( et131x_dbginfo, + "Even number of descs, split 1st elem\n" ); + iSplitFirstElement = 1; + //SegmentSize = pFragList[0].size / 2; + SegmentSize = ( pPacket->len - pPacket->data_len ) / 2; + } + } + else if( FragListCount & 0x1 ) + { + DBG_TX( et131x_dbginfo, + "Odd number of descs, split 1st elem\n" ); + + iSplitFirstElement = 1; + //SegmentSize = pFragList[0].size / 2; + SegmentSize = ( pPacket->len - pPacket->data_len ) / 2; + } + + spin_lock_irqsave( &pAdapter->SendHWLock, lockflags1 ); + + if( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req_wrap == + ServiceComplete.bits.serv_cpl_wrap ) + { + /********************************************************************** + The ring hasn't wrapped. Slots available should be (RING_SIZE) - + the difference between the two pointers. + *********************************************************************/ + SlotsAvailable = NUM_DESC_PER_RING_TX - + ( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req - ServiceComplete.bits.serv_cpl); + } + else + { + /********************************************************************** + The ring has wrapped. Slots available should be the difference + between the two pointers. + *********************************************************************/ + SlotsAvailable = ServiceComplete.bits.serv_cpl - + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req; + } + + if(( FragListCount + iSplitFirstElement ) > SlotsAvailable ) + { + DBG_WARNING( et131x_dbginfo, "Not Enough Space in Tx Desc Ring\n" ); + spin_unlock_irqrestore( &pAdapter->SendHWLock, lockflags1 ); + return -ENOMEM; + } + + loopEnd = ( FragListCount ) + iSplitFirstElement; + fragIndex = 0; + + DBG_TX( et131x_dbginfo, + "TCB : 0x%p\n", pMpTcb ); + DBG_TX( et131x_dbginfo, + "Packet (SKB) : 0x%p\t Packet->len: %d\t Packet->data_len: %d\n", + pPacket, pPacket->len, pPacket->data_len ); + + DBG_TX( et131x_dbginfo, + "FragListCount : %d\t iSplitFirstElement: %d\t loopEnd:%d\n", + FragListCount, iSplitFirstElement, loopEnd ); + + for( loopIndex = 0; loopIndex < loopEnd; loopIndex++ ) + { + if( loopIndex > iSplitFirstElement ) + { + fragIndex++; + } + + DBG_TX( et131x_dbginfo, "In loop, loopIndex: %d\t fragIndex: %d\n", + loopIndex, fragIndex ); + + + /********************************************************************** + If there is something in this element, let's get a descriptor from + the ring and get the necessary data + *********************************************************************/ + DBG_TX( et131x_dbginfo, + "Packet Length %d," + "filling desc entry %d\n", + pPacket->len, + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req ); + + // NOTE - Should we do a paranoia check here to make sure the fragment + // actually has a length? It's HIGHLY unlikely the fragment would + // contain no data... + if( 1 ) + { + // NOTE - Currently always getting 32-bit addrs, and dma_addr_t is + // only 32-bit, so leave "high" ptr value out for now + CurDesc.DataBufferPtrHigh = 0; + + CurDesc.word2.value = 0; + CurDesc.word3.value = 0; + + + if( fragIndex == 0 ) + { + if( iSplitFirstElement ) + { + DBG_TX( et131x_dbginfo, "Split first element: YES\n" ); + + if( loopIndex == 0 ) + { + DBG_TX( et131x_dbginfo, + "Got fragment of length %d, fragIndex: %d\n", + pPacket->len - pPacket->data_len, + fragIndex ); + DBG_TX( et131x_dbginfo, + "SegmentSize: %d\n", SegmentSize ); + + + CurDesc.word2.bits.length_in_bytes = SegmentSize; + CurDesc.DataBufferPtrLow = pci_map_single( pAdapter->pdev, + pPacket->data, + SegmentSize, + PCI_DMA_TODEVICE ); + DBG_TX( et131x_dbginfo, "pci_map_single() returns: 0x%08x\n", + CurDesc.DataBufferPtrLow ); + } + else + { + DBG_TX( et131x_dbginfo, + "Got fragment of length %d, fragIndex: %d\n", + pPacket->len - pPacket->data_len, + fragIndex ); + DBG_TX( et131x_dbginfo, + "Leftover Size: %d\n", + ( pPacket->len - pPacket->data_len - SegmentSize )); + + CurDesc.word2.bits.length_in_bytes = (( pPacket->len - pPacket->data_len ) - + SegmentSize ); + CurDesc.DataBufferPtrLow = pci_map_single( pAdapter->pdev, + ( pPacket->data + SegmentSize ), + ( pPacket->len - pPacket->data_len - + SegmentSize ), + PCI_DMA_TODEVICE ); + DBG_TX( et131x_dbginfo, "pci_map_single() returns: 0x%08x\n", + CurDesc.DataBufferPtrLow ); + } + } + else + { + DBG_TX( et131x_dbginfo, "Split first element: NO\n" ); + + CurDesc.word2.bits.length_in_bytes = pPacket->len - + pPacket->data_len; + + CurDesc.DataBufferPtrLow = pci_map_single( pAdapter->pdev, + pPacket->data, + ( pPacket->len - + pPacket->data_len ), + PCI_DMA_TODEVICE ); + DBG_TX( et131x_dbginfo, "pci_map_single() returns: 0x%08x\n", + CurDesc.DataBufferPtrLow ); + } + } + else + { + + CurDesc.word2.bits.length_in_bytes = pFragList[fragIndex - 1].size; + CurDesc.DataBufferPtrLow = pci_map_page( pAdapter->pdev, + pFragList[fragIndex - 1].page, + pFragList[fragIndex - 1].page_offset, + pFragList[fragIndex - 1].size, + PCI_DMA_TODEVICE ); + DBG_TX( et131x_dbginfo, "pci_map_page() returns: 0x%08x\n", + CurDesc.DataBufferPtrLow ); + } + + if( loopIndex == 0 ) + { + /************************************************************** + This is the first descriptor of the packet + *************************************************************/ + /************************************************************** + Set the "f" bit to indicate this is the first descriptor in + the packet. + *************************************************************/ + DBG_TX( et131x_dbginfo, "This is our FIRST descriptor\n" ); + CurDesc.word3.bits.f = 1; + + pMpTcb->WrIndexStart = pAdapter->TxRing.txDmaReadyToSend; + } + + if(( loopIndex == (loopEnd - 1 )) && + ( pAdapter->uiDuplexMode || + ( pMpTcb->PacketLength >= NIC_MIN_PACKET_SIZE ))) + { + /************************************************************** + This is the Last descriptor of the packet + *************************************************************/ + DBG_TX( et131x_dbginfo, "THIS is our LAST descriptor\n" ); + + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS ) + { + if( ++pAdapter->TxRing.TxPacketsSinceLastinterrupt >= pAdapter->RegistryTxNumBuffers ) + { + CurDesc.word3.value = 0x5; + pAdapter->TxRing.TxPacketsSinceLastinterrupt = 0; + } + else + { + CurDesc.word3.value = 0x1; + } + } + else + { + CurDesc.word3.value = 0x5; + } + + + /************************************************************** + Following index will be used during freeing of packet + *************************************************************/ + pMpTcb->WrIndex = pAdapter->TxRing.txDmaReadyToSend; + pMpTcb->PacketStaleCount = 0; + } + + /****************************************************************** + Copy the descriptor (filled above) into the descriptor ring + at the next free entry. Advance the "next free entry" variable + *****************************************************************/ + memcpy( pAdapter->TxRing.pTxDescRingVa + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req, + &CurDesc, + sizeof( TX_DESC_ENTRY_t )); + + CurDescPostCopy = pAdapter->TxRing.pTxDescRingVa + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req; + + DBG_TX( et131x_dbginfo, "CURRENT DESCRIPTOR\n" ); + DBG_TX( et131x_dbginfo, "\tAddress : 0x%p\n", CurDescPostCopy ); + DBG_TX( et131x_dbginfo, "\tDataBufferPtrHigh : 0x%08x\n", CurDescPostCopy->DataBufferPtrHigh ); + DBG_TX( et131x_dbginfo, "\tDataBufferPtrLow : 0x%08x\n", CurDescPostCopy->DataBufferPtrLow ); + DBG_TX( et131x_dbginfo, "\tword2 : 0x%08x\n", CurDescPostCopy->word2.value ); + DBG_TX( et131x_dbginfo, "\tword3 : 0x%08x\n", CurDescPostCopy->word3.value ); + + + if( ++pAdapter->TxRing.txDmaReadyToSend.bits.serv_req >= NUM_DESC_PER_RING_TX ) + { + if( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req_wrap ) + { + pAdapter->TxRing.txDmaReadyToSend.value = 0; + } + else + { + pAdapter->TxRing.txDmaReadyToSend.value = 0x400; + } + } + } + } + + + if(( pAdapter->uiDuplexMode == 0 ) && ( pMpTcb->PacketLength < NIC_MIN_PACKET_SIZE )) + { + // NOTE - Same 32/64-bit issue as above... + CurDesc.DataBufferPtrHigh = 0x0; + CurDesc.DataBufferPtrLow = pAdapter->TxRing.pTxDummyBlkPa; + CurDesc.word2.value = 0; + + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS ) + { + if( ++pAdapter->TxRing.TxPacketsSinceLastinterrupt >= pAdapter->RegistryTxNumBuffers ) + { + CurDesc.word3.value = 0x5; + pAdapter->TxRing.TxPacketsSinceLastinterrupt = 0; + } + else + { + CurDesc.word3.value = 0x1; + } + } + else + { + CurDesc.word3.value = 0x5; + } + + CurDesc.word2.bits.length_in_bytes = NIC_MIN_PACKET_SIZE - pMpTcb->PacketLength; + + pMpTcb->WrIndex = pAdapter->TxRing.txDmaReadyToSend; + + memcpy( pAdapter->TxRing.pTxDescRingVa + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req, + &CurDesc, + sizeof( TX_DESC_ENTRY_t )); + + CurDescPostCopy = pAdapter->TxRing.pTxDescRingVa + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req; + + DBG_TX( et131x_dbginfo, "CURRENT DESCRIPTOR\n" ); + DBG_TX( et131x_dbginfo, "\tAddress : 0x%p\n", CurDescPostCopy ); + DBG_TX( et131x_dbginfo, "\tDataBufferPtrHigh : 0x%08x\n", CurDescPostCopy->DataBufferPtrHigh ); + DBG_TX( et131x_dbginfo, "\tDataBufferPtrLow : 0x%08x\n", CurDescPostCopy->DataBufferPtrLow ); + DBG_TX( et131x_dbginfo, "\tword2 : 0x%08x\n", CurDescPostCopy->word2.value ); + DBG_TX( et131x_dbginfo, "\tword3 : 0x%08x\n", CurDescPostCopy->word3.value ); + + + if( ++pAdapter->TxRing.txDmaReadyToSend.bits.serv_req >= NUM_DESC_PER_RING_TX ) + { + if( pAdapter->TxRing.txDmaReadyToSend.bits.serv_req_wrap ) + { + pAdapter->TxRing.txDmaReadyToSend.value = 0; + } + else + { + pAdapter->TxRing.txDmaReadyToSend.value = 0x400; + } + } + + DBG_TX( et131x_dbginfo, "Padding descriptor %d by %d bytes\n", + //pAdapter->TxRing.txDmaReadyToSend.value, + pAdapter->TxRing.txDmaReadyToSend.bits.serv_req, + NIC_MIN_PACKET_SIZE - pMpTcb->PacketLength ); + } + + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags2 ); + + if( pAdapter->TxRing.CurrSendTail ) + { + pAdapter->TxRing.CurrSendTail->Next = pMpTcb; + } + else + { + pAdapter->TxRing.CurrSendHead = pMpTcb; + } + + pAdapter->TxRing.CurrSendTail = pMpTcb; + + DBG_ASSERT( pMpTcb->Next == NULL ); + + pAdapter->TxRing.nBusySend++; + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags2 ); + + + /************************************************************************** + Write the new write pointer back to the device. + *************************************************************************/ + pAdapter->CSRAddress->txdma.service_request.value = pAdapter->TxRing.txDmaReadyToSend.value; + +#if ( ET131X_DBG == 1 ) + DumpDeviceBlock( DBG_TX_ON, pAdapter, 1 ); +#endif + + + /************************************************************************** + Map a local pointer to the global section of the JAGCore + *************************************************************************/ + pGbl = &pAdapter->CSRAddress->global; + + + /************************************************************************** + For Gig only, we use Tx Interrupt coalescing. Enable the software + timer to wake us up if this packet isn't followed by N more. + *************************************************************************/ + if( pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS ) + { + pAdapter->CSRAddress->global.watchdog_timer = + pAdapter->RegistryTxTimeInterval * NANO_IN_A_MICRO; + } + + spin_unlock_irqrestore( &pAdapter->SendHWLock, lockflags1 ); + + + DBG_TX_LEAVE( et131x_dbginfo ); + return 0; +} +/*===========================================================================*/ +#endif + + + + +/****************************************************************************** + ROUTINE: et131x_free_send_packet + ****************************************************************************** + DESCRIPTION: + Recycle a MP_TCB and complete the packet if necessary + + Assumption: Send spinlock has been acquired + + PARAMETERS : + pAdapter - pointer to our adapter + pMpTcb - pointer to MP_TCB + + RETURNS : + NONE + + *****************************************************************************/ +__inline void et131x_free_send_packet( ET131X_ADAPTER *pAdapter, PMP_TCB pMpTcb ) +{ + unsigned long lockflags; + TX_DESC_ENTRY_t *desc = NULL; + struct net_device_stats *stats = &pAdapter->net_stats; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_free_send_packet" ); + + + if( MP_TEST_FLAG( pMpTcb, fMP_DEST_BROAD ) ) + { + atomic_inc( &pAdapter->Stats.brdcstxmt ); + } + else if( MP_TEST_FLAG( pMpTcb, fMP_DEST_MULTI )) + { + atomic_inc( &pAdapter->Stats.multixmt ); + } + else + { + atomic_inc( &pAdapter->Stats.unixmt ); + } + + if( pMpTcb->Packet ) + { + stats->tx_bytes += pMpTcb->Packet->len; + + + /********************************************************************** + Iterate through the TX descriptors on the ring corresponding to this + packet and umap the fragments they point to + *********************************************************************/ + DBG_TX( et131x_dbginfo, "Unmap descriptors Here\n" ); + + DBG_TX( et131x_dbginfo, + "TCB : 0x%p\n", pMpTcb ); + + DBG_TX( et131x_dbginfo, + "TCB Next : 0x%p\n", pMpTcb->Next ); + + DBG_TX( et131x_dbginfo, + "TCB PacketLength : %d\n", pMpTcb->PacketLength ); + + DBG_TX( et131x_dbginfo, + "TCB WrIndex.value : 0x%08x\n", pMpTcb->WrIndexStart.value ); + DBG_TX( et131x_dbginfo, + "TCB WrIndex.serv_req : %d\n", pMpTcb->WrIndexStart.bits.serv_req ); + + DBG_TX( et131x_dbginfo, + "TCB WrIndex.value : 0x%08x\n", pMpTcb->WrIndex.value ); + DBG_TX( et131x_dbginfo, + "TCB WrIndex.serv_req : %d\n", pMpTcb->WrIndex.bits.serv_req ); + + do + { + desc = (TX_DESC_ENTRY_t *)( pAdapter->TxRing.pTxDescRingVa + + pMpTcb->WrIndexStart.bits.serv_req ); + + DBG_TX( et131x_dbginfo, "CURRENT DESCRIPTOR\n" ); + DBG_TX( et131x_dbginfo, "\tAddress : 0x%p\n", desc ); + DBG_TX( et131x_dbginfo, "\tDataBufferPtrHigh : 0x%08x\n", desc->DataBufferPtrHigh ); + DBG_TX( et131x_dbginfo, "\tDataBufferPtrLow : 0x%08x\n", desc->DataBufferPtrLow ); + DBG_TX( et131x_dbginfo, "\tword2 : 0x%08x\n", desc->word2.value ); + DBG_TX( et131x_dbginfo, "\tword3 : 0x%08x\n", desc->word3.value ); + + pci_unmap_single( pAdapter->pdev, + desc->DataBufferPtrLow, + desc->word2.value, + PCI_DMA_TODEVICE ); + + if( ++pMpTcb->WrIndexStart.bits.serv_req >= NUM_DESC_PER_RING_TX ) + { + if( pMpTcb->WrIndexStart.bits.serv_req_wrap ) + { + pMpTcb->WrIndexStart.value = 0; + } + else + { + pMpTcb->WrIndexStart.value = 0x400; + } + } + } + while( desc != ( pAdapter->TxRing.pTxDescRingVa + + pMpTcb->WrIndex.bits.serv_req )); + + DBG_TX( et131x_dbginfo, + "Free Packet (SKB) : 0x%p\n", pMpTcb->Packet ); + + dev_kfree_skb_any( pMpTcb->Packet ); + } + + memset( pMpTcb, 0, sizeof( MP_TCB )); + + + /************************************************************************** + Add the TCB to the Ready Q + *************************************************************************/ + spin_lock_irqsave( &pAdapter->TCBReadyQLock, lockflags ); + + pAdapter->Stats.opackets++; + + if( pAdapter->TxRing.TCBReadyQueueTail ) + { + pAdapter->TxRing.TCBReadyQueueTail->Next = pMpTcb; + } + else + { + /********************************************************************** + Apparently ready Q is empty. + *********************************************************************/ + pAdapter->TxRing.TCBReadyQueueHead = pMpTcb; + } + + pAdapter->TxRing.TCBReadyQueueTail = pMpTcb; + + spin_unlock_irqrestore( &pAdapter->TCBReadyQLock, lockflags ); + + + DBG_ASSERT( pAdapter->TxRing.nBusySend >= 0 ); + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_free_busy_send_packets + ****************************************************************************** + DESCRIPTION: + Free and complete the stopped active sends + + Assumption: Send spinlock has been acquired + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURNS : + NONE + + *****************************************************************************/ +void et131x_free_busy_send_packets( ET131X_ADAPTER *pAdapter ) +{ + PMP_TCB pMpTcb; + struct list_head *pEntry; + struct sk_buff *pPacket = NULL; + unsigned long lockflags; + UINT32 FreeCounter = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_free_busy_send_packets" ); + DBG_ENTER( et131x_dbginfo ); + + + while( !list_empty( &pAdapter->TxRing.SendWaitQueue )) + { + spin_lock_irqsave( &pAdapter->SendWaitLock, lockflags ); + + pAdapter->TxRing.nWaitSend--; + spin_unlock_irqrestore( &pAdapter->SendWaitLock, lockflags ); + + pEntry = pAdapter->TxRing.SendWaitQueue.next; + + pPacket = NULL; + } + + pAdapter->TxRing.nWaitSend = 0; + + + /************************************************************************** + Any packets being sent? Check the first TCB on the send list + *************************************************************************/ + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags ); + + pMpTcb = pAdapter->TxRing.CurrSendHead; + + while(( pMpTcb != NULL ) && ( FreeCounter < NUM_TCB )) + { + PMP_TCB pNext = pMpTcb->Next; + + pAdapter->TxRing.CurrSendHead = pNext; + + if( pNext == NULL ) + { + pAdapter->TxRing.CurrSendTail = NULL; + } + + pAdapter->TxRing.nBusySend--; + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + + DBG_VERBOSE( et131x_dbginfo, + "pMpTcb = 0x%p\n", + pMpTcb ); + + FreeCounter++; + MP_FREE_SEND_PACKET_FUN( pAdapter, pMpTcb ); + + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags ); + + pMpTcb = pAdapter->TxRing.CurrSendHead; + } + + if( FreeCounter == NUM_TCB ) + { + DBG_ERROR( et131x_dbginfo, + "MpFreeBusySendPackets exitted loop for a bad reason\n" ); + BUG(); + } + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + + pAdapter->TxRing.nBusySend = 0; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_handle_send_interrupt + ****************************************************************************** + DESCRIPTION: + Interrupt handler for sending processing + Re-claim the send resources, complete sends and get more to send from + the send wait queue + + Assumption: Send spinlock has been acquired + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURNS : + Nothing + + *****************************************************************************/ +void et131x_handle_send_interrupt( ET131X_ADAPTER *pAdapter ) +{ + DBG_FUNC( "et131x_handle_send_interrupt" ); + DBG_TX_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Mark as completed any packets which have been sent by the device. + *************************************************************************/ + et131x_update_tcb_list( pAdapter ); + + + /************************************************************************** + If we queued any transmits because we didn't have any TCBs earlier, + dequeue and send those packets now, as long as we have free TCBs. + *************************************************************************/ + et131x_check_send_wait_list( pAdapter ); + + + DBG_TX_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_update_tcb_list + ****************************************************************************** + DESCRIPTION: + Helper routine for Send Interrupt handler. Re-claims the send + resources and completes sends. Can also be called as part of the NIC + send routine when the "ServiceComplete" indication has wrapped. + + Assumption: + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURNS : + Nothing + + *****************************************************************************/ +void et131x_update_tcb_list( ET131X_ADAPTER *pAdapter ) +{ + unsigned long lockflags; + TXDMA_SERVICE_COMPLETE_t ServiceComplete = pAdapter->CSRAddress->txdma.NewServiceComplete; + PMP_TCB pMpTcb; + /*-----------------------------------------------------------------------*/ + + + /************************************************************************** + Has the ring wrapped? Process any descriptors that do not have + the same "wrap" indicator as the current completion indicator + *************************************************************************/ + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags ); + + pMpTcb = pAdapter->TxRing.CurrSendHead; + + if( ServiceComplete.bits.serv_cpl_wrap ) + { + while( pMpTcb && + !pMpTcb->WrIndex.bits.serv_req_wrap && + ( pMpTcb->WrIndex.bits.serv_req > ServiceComplete.bits.serv_cpl )) + { + PMP_TCB pNext = pMpTcb->Next; + + pAdapter->TxRing.CurrSendHead = pNext; + + if( pNext == NULL ) + { + pAdapter->TxRing.CurrSendTail = NULL; + } + + pAdapter->TxRing.nBusySend--; + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + MP_FREE_SEND_PACKET_FUN( pAdapter, pMpTcb ); + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags ); + + + /****************************************************************** + Goto the next packet + *****************************************************************/ + pMpTcb = pAdapter->TxRing.CurrSendHead; + } + } + else + { + while( pMpTcb && + pMpTcb->WrIndex.bits.serv_req_wrap && + ( pMpTcb->WrIndex.bits.serv_req > ServiceComplete.bits.serv_cpl )) + { + PMP_TCB pNext = pMpTcb->Next; + + pAdapter->TxRing.CurrSendHead = pNext; + + if( pNext == NULL ) + { + pAdapter->TxRing.CurrSendTail = NULL; + } + + pAdapter->TxRing.nBusySend--; + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + MP_FREE_SEND_PACKET_FUN( pAdapter, pMpTcb ); + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags ); + + + /****************************************************************** + Goto the next packet + *****************************************************************/ + pMpTcb = pAdapter->TxRing.CurrSendHead; + } + } + + while( pMpTcb && + ( ServiceComplete.bits.serv_cpl_wrap == pMpTcb->WrIndex.bits.serv_req_wrap ) && + ( ServiceComplete.bits.serv_cpl > pMpTcb->WrIndex.bits.serv_req )) + { + PMP_TCB pNext = pMpTcb->Next; + + pAdapter->TxRing.CurrSendHead = pNext; + + if( pNext == NULL ) + { + pAdapter->TxRing.CurrSendTail = NULL; + } + + pAdapter->TxRing.nBusySend--; + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + MP_FREE_SEND_PACKET_FUN( pAdapter, pMpTcb ); + spin_lock_irqsave( &pAdapter->TCBSendQLock, lockflags ); + + + /********************************************************************** + Goto the next packet + *********************************************************************/ + pMpTcb = pAdapter->TxRing.CurrSendHead; + } + + + /* Wake up the queue when we hit a low-water mark */ + if( pAdapter->TxRing.nBusySend <= ( NUM_TCB / 3 )) + { + netif_wake_queue( pAdapter->netdev ); + } + + spin_unlock_irqrestore( &pAdapter->TCBSendQLock, lockflags ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_check_send_wait_list + ****************************************************************************** + DESCRIPTION: + Helper routine for the interrupt handler. Takes packets from the send + wait queue and posts them to the device (if room available). + + Assumption: + + PARAMETERS : + pAdapter - pointer to our adapter + + RETURNS : + Nothing + + *****************************************************************************/ +void et131x_check_send_wait_list( ET131X_ADAPTER *pAdapter ) +{ + unsigned long lockflags; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_check_send_wait_list" ); + + + spin_lock_irqsave( &pAdapter->SendWaitLock, lockflags ); + + while( !list_empty( &pAdapter->TxRing.SendWaitQueue ) && + MP_TCB_RESOURCES_AVAILABLE( pAdapter )) + { + struct list_head *pEntry; + + DBG_VERBOSE( et131x_dbginfo, + "Tx packets on the wait queue\n" ); + + pEntry = pAdapter->TxRing.SendWaitQueue.next; + + pAdapter->TxRing.nWaitSend--; + + DBG_WARNING( et131x_dbginfo, + "MpHandleSendInterrupt - sent a queued pkt. Waiting %d\n", + pAdapter->TxRing.nWaitSend ); + } + + spin_unlock_irqrestore( &pAdapter->SendWaitLock, lockflags ); + + return; +} +/*===========================================================================*/ + --- linux-2.6.27.orig/ubuntu/et131x/et131x_supp.h +++ linux-2.6.27/ubuntu/et131x/et131x_supp.h @@ -0,0 +1,133 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_supp.h - Misc. defines, structs, enums, prototypes, etc. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:13 $ + $Revision: 1.5 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + +#ifndef __ET131X_SUPP_H__ +#define __ET131X_SUPP_H__ + + + + +/****************************************************************************** + Enum for use with netif_indicate_status + *****************************************************************************/ +typedef enum netif_status +{ + NETIF_STATUS_INVALID = 0, + NETIF_STATUS_MEDIA_CONNECT, + NETIF_STATUS_MEDIA_DISCONNECT, + NETIF_STATUS_MAX +} NETIF_STATUS; + + + + +/****************************************************************************** + Definitions to maintain compatibility with older versions of the kernel + *****************************************************************************/ +#ifndef netdev_priv +#define netdev_priv(x) (ET131X_ADAPTER *)netdev->priv +#endif + +#ifndef SET_NETDEV_DEV +#define SET_NETDEV_DEV(net, pdev) +#endif + +#ifndef free_netdev +#define free_netdev(x) kfree(x) +#endif + +#ifndef if_mii +#define if_mii(x) (struct mii_ioctl_data *)&x->ifr_ifru +#endif + + + + +/****************************************************************************** + PROTOTYPES + *****************************************************************************/ +void et131x_init_enet_crc_calc( void ); + +UINT32 et131x_calc_enet_crc( PUCHAR Message, UINT32 MessageSize ); + +UINT32 pci_slot_information_read( struct pci_dev *pdev, UINT32 where, + UINT8 *buf, UINT32 len ); + +UINT32 pci_slot_information_write( struct pci_dev *pdev, UINT32 where, + UINT8 *buf, UINT32 len ); + +void netif_indicate_status( struct net_device *netdev, NETIF_STATUS status ); + + + + +#endif /* __ET131X_SUPP_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_defs.h +++ linux-2.6.27/ubuntu/et131x/et131x_defs.h @@ -0,0 +1,223 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_defs.h - Defines, structs, enums, prototypes, etc. to assist with OS + * compatibility + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 18:43:46 $ + $Revision: 1.8 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_DEFS_H__ +#define __ET131X_DEFS_H__ + + + + +/****************************************************************************** + Define a boolean type + *****************************************************************************/ +typedef enum { FALSE, TRUE } __attribute__ ((packed)) BOOL_t; + + + + +/****************************************************************************** + Packet and header sizes + *****************************************************************************/ +#define NIC_MIN_PACKET_SIZE 60 +#define NIC_HEADER_SIZE ETH_HLEN //14 + + + + +/****************************************************************************** + Multicast list size + *****************************************************************************/ +#define NIC_MAX_MCAST_LIST 128 + + + + +/****************************************************************************** + Supported Filters + *****************************************************************************/ +#define ET131X_PACKET_TYPE_DIRECTED 0x0001 +#define ET131X_PACKET_TYPE_MULTICAST 0x0002 +#define ET131X_PACKET_TYPE_BROADCAST 0x0004 +#define ET131X_PACKET_TYPE_PROMISCUOUS 0x0008 +#define ET131X_PACKET_TYPE_ALL_MULTICAST 0x0010 + + + + +/****************************************************************************** + Tx Timeout + *****************************************************************************/ +#define ET131X_TX_TIMEOUT (1 * HZ) +#define NIC_SEND_HANG_THRESHOLD 0 + + + + +/****************************************************************************** + MP_TCB flags + *****************************************************************************/ +#define fMP_DEST_MULTI 0x00000001 +#define fMP_DEST_BROAD 0x00000002 + + + + +/****************************************************************************** + MP_ADAPTER flags + *****************************************************************************/ +#define fMP_ADAPTER_RECV_LOOKASIDE 0x00000004 +#define fMP_ADAPTER_INTERRUPT_IN_USE 0x00000008 +#define fMP_ADAPTER_SECONDARY 0x00000010 + + + + +/****************************************************************************** + MP_SHARED flags + *****************************************************************************/ +#define fMP_ADAPTER_SHUTDOWN 0x00100000 +#define fMP_ADAPTER_LOWER_POWER 0x00200000 + +#define fMP_ADAPTER_NON_RECOVER_ERROR 0x00800000 +#define fMP_ADAPTER_RESET_IN_PROGRESS 0x01000000 +#define fMP_ADAPTER_NO_CABLE 0x02000000 +#define fMP_ADAPTER_HARDWARE_ERROR 0x04000000 +#define fMP_ADAPTER_REMOVE_IN_PROGRESS 0x08000000 +#define fMP_ADAPTER_HALT_IN_PROGRESS 0x10000000 +#define fMP_ADAPTER_LINK_DETECTION 0x20000000 + +#define fMP_ADAPTER_FAIL_SEND_MASK 0x3ff00000 +#define fMP_ADAPTER_NOT_READY_MASK 0x3ff00000 + + + + +/****************************************************************************** + Some offsets in PCI config space that are actually used. + *****************************************************************************/ +#define ET1310_PCI_PM_CAPABILITY (UINT32)0x40 +#define ET1310_PCI_PM_CSR (UINT32)0x44 +#define ET1310_PCI_MAX_PYLD (UINT32)0x4C +#define ET1310_PCI_DEV_CTRL (UINT32)0x50 +#define ET1310_PCI_DEV_STAT (UINT32)0x52 +#define ET1310_NMI_DISABLE (UINT32)0x61 +#define ET1310_PCI_MAC_ADDRESS (UINT32)0xA4 +#define ET1310_PCI_EEPROM_STATUS (UINT32)0xB2 +#define ET1310_PCI_PHY_INDEX_REG (UINT32)0xB4 +#define ET1310_PCI_ACK_NACK (UINT32)0xC0 +#define ET1310_PCI_REPLAY (UINT32)0xC2 +#define ET1310_PCI_L0L1LATENCY (UINT32)0xCF +#define ET1310_PCI_SEL_PHY_CTRL (UINT32)0xE4 +#define ET1310_PCI_ADVANCED_ERR (UINT32)0x100 + + + + +/****************************************************************************** + PCI Vendor/Product IDs + *****************************************************************************/ +#define ET131X_PCI_VENDOR_ID 0x11C1 // Agere Systems +#define ET131X_PCI_DEVICE_ID_GIG 0xED00 // ET1310 1000 Base-T +#define ET131X_PCI_DEVICE_ID_FAST 0xED01 // ET1310 100 Base-T + + + + +/****************************************************************************** + Define FIELD_OFFSET macro + *****************************************************************************/ +#define FIELD_OFFSET(type,field) ((int)(&((type *)0)->field)) + + + + +/****************************************************************************** + Handle name change of some regsiter bits + *****************************************************************************/ +#define phy_sw_coma pm_phy_sw_coma + + + + +/****************************************************************************** + Define order of magnitude converter + *****************************************************************************/ +#define NANO_IN_A_MICRO 1000 + + + + +#endif /* __ET131X_DEFS_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/Makefile +++ linux-2.6.27/ubuntu/et131x/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_NET_ET131X) += et131x.o + +et131x-objs += et131x_main.o et131x_initpci.o et131x_isr.o et131x_netdev.o \ + et131x_supp.o et131x_config.o et131x_debug.o ET1310_jagcore.o \ + ET1310_tx.o ET1310_rx.o ET1310_phy.o ET1310_mac.o ET1310_pm.o \ + ET1310_eeprom.o --- linux-2.6.27.orig/ubuntu/et131x/ET1310_jagcore.c +++ linux-2.6.27/ubuntu/et131x/ET1310_jagcore.c @@ -0,0 +1,642 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_jagcore.c - All code pertaining to the ET1301/ET131x's JAGcore + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/28 18:43:44 $ + $Revision: 1.9 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +/****************************************************************************** + Includes + *****************************************************************************/ +#include "et131x_version.h" +#include "et131x_debug.h" +#include "et131x_defs.h" + +#include +#include +#include +#include + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,0 )) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ET1310_phy.h" +#include "ET1310_pm.h" +#include "ET1310_jagcore.h" + +#include "et131x_supp.h" +#include "et131x_adapter.h" +#include "et131x_initpci.h" + + + + +/****************************************************************************** + Data for debugging facilities + *****************************************************************************/ +#ifdef ET131X_DBG +extern dbg_info_t *et131x_dbginfo; +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + ROUTINE: ConfigGlobalRegs + ****************************************************************************** + + DESCRIPTION: + Used to configure the global registers on the JAGCore + + PARAMETERS : + pAdpater - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigGlobalRegs( ET131X_ADAPTER *pAdapter ) +{ + PGLOBAL_t pGbl; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigGlobalRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Map a local pointer to the global section of the JAGCore + *************************************************************************/ + pGbl = &pAdapter->CSRAddress->global; + + if( pAdapter->RegistryPhyLoopbk == FALSE ) + { + if( pAdapter->RegistryJumboPacket < 2048 ) + { + /****************************************************************** + Tx / RxDMA and Tx/Rx MAC interfaces have a 1k word block of RAM + that the driver can split between Tx and Rx as it desires. Our + default is to split it 50/50: + *****************************************************************/ + pGbl->rxq_start_addr.value = 0; + pGbl->rxq_end_addr.value = pAdapter->RegistryRxMemEnd; + pGbl->txq_start_addr.value = pGbl->rxq_end_addr.bits.rxq_end_addr + 1; + pGbl->txq_end_addr.value = INTERNAL_MEM_SIZE - 1; + } + else if( pAdapter->RegistryJumboPacket < 8192 ) + { + /****************************************************************** + For jumbo packets > 2k in length, but < 8k, split 50-50. + *****************************************************************/ + pGbl->rxq_start_addr.value = 0; + pGbl->rxq_end_addr.value = INTERNAL_MEM_RX_OFFSET; + pGbl->txq_start_addr.value = INTERNAL_MEM_RX_OFFSET + 1; + pGbl->txq_end_addr.value = INTERNAL_MEM_SIZE - 1; + } + else + { + /****************************************************************** + 9216 is the only packet size greater than 8k that is available. + The Tx buffer has to be big enough for one whole packet on the + Tx side. We'll make the Tx 9408, and give the rest to Rx + *****************************************************************/ + pGbl->rxq_start_addr.value = 0x0000; + pGbl->rxq_end_addr.value = 0x01b3; + pGbl->txq_start_addr.value = 0x01b4; + pGbl->txq_end_addr.value = INTERNAL_MEM_SIZE - 1; + } + + /********************************************************************** + Initialize the loopback register. Disable all loopbacks. + *********************************************************************/ + pGbl->loopback.value = 0x0; + } + else + { + /************************************************************************** + For PHY Line loopback, the memory is configured as if Tx and Rx both + have all the memory. This is because the RxMAC will write data into + the space, and the TxMAC will read it out. + *************************************************************************/ + pGbl->rxq_start_addr.value = 0; + pGbl->rxq_end_addr.value = INTERNAL_MEM_SIZE - 1; + pGbl->txq_start_addr.value = 0; + pGbl->txq_end_addr.value = INTERNAL_MEM_SIZE - 1; + + /************************************************************************** + Initialize the loopback register (MAC loopback). + *************************************************************************/ + pGbl->loopback.value = 0x1; + } + + /************************************************************************** + MSI Register + *************************************************************************/ + pGbl->msi_config.value = 0x0; + + + /************************************************************************** + By default, disable the watchdog timer. It will be enabled when + a packet is queued. + *************************************************************************/ + pGbl->watchdog_timer = 0; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: ConfigMMCRegs + ****************************************************************************** + + DESCRIPTION: + Used to configure the main memory registers in the JAGCore + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURNS : + NONE + + *****************************************************************************/ +void ConfigMMCRegs( ET131X_ADAPTER *pAdapter ) +{ + MMC_CTRL_t mmc_ctrl = {0}; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "ConfigMMCRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + All we need to do is initialize the Memory Control Register + *************************************************************************/ + mmc_ctrl.bits.force_ce = 0x0; + mmc_ctrl.bits.rxdma_disable = 0x0; + mmc_ctrl.bits.txdma_disable = 0x0; + mmc_ctrl.bits.txmac_disable = 0x0; + mmc_ctrl.bits.rxmac_disable = 0x0; + mmc_ctrl.bits.arb_disable = 0x0; + mmc_ctrl.bits.mmc_enable = 0x1; + + pAdapter->CSRAddress->mmc.mmc_ctrl.value = mmc_ctrl.value; + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_enable_interrupts + ****************************************************************************** + + DESCRIPTION : Enable interupts on the ET131x + + PARAMETERS : adapter - a pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ +void et131x_enable_interrupts( ET131X_ADAPTER *adapter ) +{ + UINT32 MaskValue; + + + /************************************************************************** + Enable all global interrupts + *************************************************************************/ + if(( adapter->FlowControl == TxOnly ) || + ( adapter->FlowControl == Both )) + { + MaskValue = INT_MASK_ENABLE; + } + else + { + MaskValue = INT_MASK_ENABLE_NO_FLOW; + } + + if( adapter->DriverNoPhyAccess ) + { + MaskValue |= 0x10000; + } + + adapter->CachedMaskValue.value = MaskValue; + adapter->CSRAddress->global.int_mask.value = MaskValue; + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE : et131x_disable_interrupts + ****************************************************************************** + + DESCRIPTION : Enable interrupts on the ET131x + + PARAMETERS : adapter - a pointer to our private adapter structure + + RETURNS : N/A + + REUSE INFORMATION : + + *****************************************************************************/ + +void et131x_disable_interrupts( ET131X_ADAPTER *adapter ) +{ + /************************************************************************** + Disable all global interrupts + *************************************************************************/ + adapter->CachedMaskValue.value = INT_MASK_DISABLE; + adapter->CSRAddress->global.int_mask.value = INT_MASK_DISABLE; + + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: NICGetRegs + ****************************************************************************** + + DESCRIPTION: + function used to get register data + + PARAMETERS : + pAdapter - pointer to our adapter structure + InfoBuf - pointer to data struct containing registers to get + ulBytesAvailable - + ulInfoLen - + + RETURN : + NONE + + *****************************************************************************/ +void * et131x_get_regs( ET131X_ADAPTER *pAdapter, void *InfoBuf, + PUINT32 ulBytesAvailable, PUINT32 ulInfoLen ) +{ + INT32 nRegCount; + PINT8 pJCBase; + INT32 x; + PUINT32 pReg; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_get_regs" ); + DBG_ENTER( et131x_dbginfo ); + + + memset( (void *)&pAdapter->JagCoreRegs, 0, sizeof( JAGCORE_ACCESS_REGS )); + + + /************************************************************************** + Get the user supplied data + *************************************************************************/ + pAdapter->JagCoreRegs = *(PJAGCORE_ACCESS_REGS)InfoBuf; + nRegCount = pAdapter->JagCoreRegs.nRegCount; + + pJCBase = (PINT8)&pAdapter->CSRAddress->global; + + for( x = 0; x < nRegCount; x++ ) + { + pReg = (PUINT32)( pJCBase+pAdapter->JagCoreRegs.nOffsets[x] ); + + pAdapter->JagCoreRegs.nData[x] = *pReg; + } + + *ulBytesAvailable = sizeof( JAGCORE_ACCESS_REGS ); + *ulInfoLen = sizeof( JAGCORE_ACCESS_REGS ); + + + DBG_LEAVE( et131x_dbginfo ); + return( (void *)&pAdapter->JagCoreRegs ); +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: et131x_set_regs + ****************************************************************************** + + DESCRIPTION: + function used to set register data + + PARAMETERS : + pAdapter - pointer to our adapter structure + InfoBuf - pointer to data struct containing register offset and data + to set + RETURN : + N/A + + *****************************************************************************/ +void et131x_set_regs( ET131X_ADAPTER *pAdapter, void *InfoBuf ) +{ + INT32 nRegCount; + PINT8 pJCBase; + INT32 x; + PUINT32 pReg; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "et131x_set_regs" ); + DBG_ENTER( et131x_dbginfo ); + + + memset( (void *)&pAdapter->JagCoreRegs, 0, sizeof( JAGCORE_ACCESS_REGS )); + + + /************************************************************************** + Get the user supplied data + *************************************************************************/ + pAdapter->JagCoreRegs = *(PJAGCORE_ACCESS_REGS)InfoBuf; + + nRegCount = pAdapter->JagCoreRegs.nRegCount; + + pJCBase = (PINT8)&pAdapter->CSRAddress->global; + + for( x = 0; x < nRegCount; x++ ) + { + pReg = (PUINT32)(pJCBase+pAdapter->JagCoreRegs.nOffsets[x]); + *pReg = pAdapter->JagCoreRegs.nData[x]; + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: GetPciCfgRegs + ****************************************************************************** + + DESCRIPTION: + function used to get register data + + PARAMETERS : + pAdapter - pointer to our adapter structure + InfoBuf - pointer to data struct containing registers to get + ulBytesAvailable - + ulInfoLen - + + RETURN : + NONE + + *****************************************************************************/ +void * GetPciCfgRegs( ET131X_ADAPTER *pAdapter, void * InfoBuf, + PUINT32 ulBytesAvailable, PUINT32 ulInfoLen ) +{ + INT32 nRegCount; + UINT32 ByteLength = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "GetPciCfgRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + /************************************************************************** + Get the user supplied data + *************************************************************************/ + pAdapter->PciCfgRegs = *(PPCI_CFG_SPACE_REGS)InfoBuf; + nRegCount = pAdapter->PciCfgRegs.nRegCount; + + + /************************************************************************** + Support for 8,16,32 bit widths + *************************************************************************/ + ByteLength = pAdapter->PciCfgRegs.nDataWidth/8; + + pci_slot_information_read( pAdapter->pdev, + pAdapter->PciCfgRegs.nOffsets[0], + (UINT8 *)&pAdapter->PciCfgRegs.nData, + ByteLength * nRegCount ); + + *ulBytesAvailable = sizeof( PCI_CFG_SPACE_REGS ); + *ulInfoLen = sizeof( PCI_CFG_SPACE_REGS ); + + + DBG_LEAVE( et131x_dbginfo ); + return( (void *)&pAdapter->PciCfgRegs ); +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: SetPciCfgRegs + ****************************************************************************** + + DESCRIPTION: + function used to set register data + + PARAMETERS : + pAdapter - pointer to our adapter structure + InfoBuf - pointer to data struct containing register offset and data + to set + RETURN : + N/A + + *****************************************************************************/ +void SetPciCfgRegs( ET131X_ADAPTER *pAdapter, void * InfoBuf ) +{ + INT32 nRegCount; + INT32 x; + UINT32 ByteLength = 0; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "SetPciCfgRegs" ); + DBG_ENTER( et131x_dbginfo ); + + + memset( (void *)&pAdapter->PciCfgRegs, 0, sizeof( PCI_CFG_SPACE_REGS )); + + + /************************************************************************** + Get the user supplied data + *************************************************************************/ + pAdapter->PciCfgRegs = *(PPCI_CFG_SPACE_REGS)InfoBuf; + + nRegCount = pAdapter->PciCfgRegs.nRegCount; + ByteLength = pAdapter->PciCfgRegs.nDataWidth/8; + + for( x = 0; x < nRegCount; x++ ) + { + pci_slot_information_write( pAdapter->pdev, + pAdapter->PciCfgRegs.nOffsets[x], + (UINT8 *)&pAdapter->PciCfgRegs.nData[x * ByteLength], + ByteLength ); + } + + + DBG_LEAVE( et131x_dbginfo ); + return; +} +/*===========================================================================*/ + + + + +/****************************************************************************** + ROUTINE: MemTest + ****************************************************************************** + + DESCRIPTION: + function used to test rx/tx queue memory at 0x0 and 0x200 + + PARAMETERS : + pAdapter - pointer to our adapter structure + + RETURN : + TRUE or FALSE + + *****************************************************************************/ +BOOL_t MemTest( ET131X_ADAPTER *pAdapter, UINT32 addr ) +{ + UINT32 data; + /*-----------------------------------------------------------------------*/ + + + DBG_FUNC( "MemTest" ); + DBG_ENTER( et131x_dbginfo ); + + + // Read initial value + pAdapter->CSRAddress->mmc.sram_access.value = 1; + data = pAdapter->CSRAddress->mmc.sram_word1.data; + + + // Write test value + pAdapter->CSRAddress->mmc.sram_word1.data = 0xdeadbeef; + pAdapter->CSRAddress->mmc.sram_access.value = 0xf003; + + + // Read back test value + pAdapter->CSRAddress->mmc.sram_access.bits.req_access = 1; + if ( pAdapter->CSRAddress->mmc.sram_word1.data != 0xdeadbeef ) + { + DBG_LEAVE( et131x_dbginfo ); + return FALSE; + } + + // Restore initial value + pAdapter->CSRAddress->mmc.sram_word1.data = data; + pAdapter->CSRAddress->mmc.sram_access.value = 0xf003; + + + DBG_LEAVE( et131x_dbginfo ); + return TRUE; +} +/*===========================================================================*/ --- linux-2.6.27.orig/ubuntu/et131x/ET1310_tx.h +++ linux-2.6.27/ubuntu/et131x/ET1310_tx.h @@ -0,0 +1,354 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * ET1310_tx.h - Defines, structs, enums, prototypes, etc. pertaining to data + * transmission. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/10/07 21:26:45 $ + $Revision: 1.9 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET1310_TX_H__ +#define __ET1310_TX_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/****************************************************************************** + Typedefs for Tx Descriptor Ring + *****************************************************************************/ +/****************************************************************************** + TXDESC_WORD2_t structure holds part of the control bits in the Tx Descriptor + ring for the ET-1310 + *****************************************************************************/ +typedef union _txdesc_word2_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 vlan_prio:3; //bits 29-31(VLAN priority) + UINT32 vlan_cfi:1; //bit 28(cfi) + UINT32 vlan_tag:12; //bits 16-27(VLAN tag) + UINT32 length_in_bytes:16; //bits 0-15(packet length) + #else + UINT32 length_in_bytes:16; //bits 0-15(packet length) + UINT32 vlan_tag:12; //bits 16-27(VLAN tag) + UINT32 vlan_cfi:1; //bit 28(cfi) + UINT32 vlan_prio:3; //bits 29-31(VLAN priority) + #endif /* _BIT_FIELDS_HTOL */ + } bits; +}TXDESC_WORD2_t, *PTXDESC_WORD2_t; + + + + +/****************************************************************************** + TXDESC_WORD3_t structure holds part of the control bits in the Tx Descriptor + ring for the ET-1310 + *****************************************************************************/ +typedef union _txdesc_word3_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:17; //bits 15-31 + UINT32 udpa:1; //bit 14(UDP checksum assist) + UINT32 tcpa:1; //bit 13(TCP checksum assist) + UINT32 ipa:1; //bit 12(IP checksum assist) + UINT32 vlan:1; //bit 11(append VLAN tag) + UINT32 hp:1; //bit 10(Packet is a Huge packet) + UINT32 pp:1; //bit 9(pad packet) + UINT32 mac:1; //bit 8(MAC override) + UINT32 crc:1; //bit 7(append CRC) + UINT32 e:1; //bit 6(Tx frame has error) + UINT32 pf:1; //bit 5(send pause frame) + UINT32 bp:1; //bit 4(Issue half-duplex backpressure (XON/XOFF) + UINT32 cw:1; //bit 3(Control word - no packet data) + UINT32 ir:1; //bit 2(interrupt the processor when this pkt sent) + UINT32 f:1; //bit 1(first packet in the sequence) + UINT32 l:1; //bit 0(last packet in the sequence) + #else + UINT32 l:1; //bit 0(last packet in the sequence) + UINT32 f:1; //bit 1(first packet in the sequence) + UINT32 ir:1; //bit 2(interrupt the processor when this pkt sent) + UINT32 cw:1; //bit 3(Control word - no packet data) + UINT32 bp:1; //bit 4(Issue half-duplex backpressure (XON/XOFF) + UINT32 pf:1; //bit 5(send pause frame) + UINT32 e:1; //bit 6(Tx frame has error) + UINT32 crc:1; //bit 7(append CRC) + UINT32 mac:1; //bit 8(MAC override) + UINT32 pp:1; //bit 9(pad packet) + UINT32 hp:1; //bit 10(Packet is a Huge packet) + UINT32 vlan:1; //bit 11(append VLAN tag) + UINT32 ipa:1; //bit 12(IP checksum assist) + UINT32 tcpa:1; //bit 13(TCP checksum assist) + UINT32 udpa:1; //bit 14(UDP checksum assist) + UINT32 unused:17; //bits 15-31 + #endif /* _BIT_FIELDS_HTOL */ + } bits; +}TXDESC_WORD3_t, *PTXDESC_WORD3_t; + + + + +/****************************************************************************** + TX_DESC_ENTRY_t is sructure representing each descriptor on the ring + *****************************************************************************/ +typedef struct _tx_desc_entry_t +{ + UINT32 DataBufferPtrHigh; + UINT32 DataBufferPtrLow; + TXDESC_WORD2_t word2; // control words how to xmit the + TXDESC_WORD3_t word3; // data (detailed above) +} +TX_DESC_ENTRY_t, *PTX_DESC_ENTRY_t; +/*===========================================================================*/ + + + + +/****************************************************************************** + Typedefs for Tx DMA engine status writeback + *****************************************************************************/ +/****************************************************************************** + TX_STATUS_BLOCK_t is sructure representing the status of the Tx DMA engine + it sits in free memory, and is pointed to by 0x101c / 0x1020 + *****************************************************************************/ + +typedef union _tx_status_block_t +{ + UINT32 value; + struct + { + #ifdef _BIT_FIELDS_HTOL + UINT32 unused:21; //bits 11-31 + UINT32 serv_cpl_wrap:1; //bit 10 + UINT32 serv_cpl:10; //bits 0-9 + #else + UINT32 serv_cpl:10; //bits 0-9 + UINT32 serv_cpl_wrap:1; //bit 10 + UINT32 unused:21; //bits 11-31 + #endif + } bits; +} +TX_STATUS_BLOCK_t, *PTX_STATUS_BLOCK_t; +/*===========================================================================*/ + + + + +/****************************************************************************** + TCB (Transmit Control Block) + *****************************************************************************/ +typedef struct _MP_TCB +{ + struct _MP_TCB *Next; + UINT32 Flags; + UINT32 Count; + UINT32 PacketStaleCount; + struct sk_buff *Packet; + UINT32 PacketLength; + TXDMA_SERVICE_REQUEST_t WrIndex; + TXDMA_SERVICE_REQUEST_t WrIndexStart; +} MP_TCB, *PMP_TCB; + + + + +/****************************************************************************** + Structure to hold the skb's in a list + *****************************************************************************/ +typedef struct tx_skb_list_elem +{ + struct list_head skb_list_elem; + struct sk_buff *skb; +} TX_SKB_LIST_ELEM, *PTX_SKB_LIST_ELEM; + + + + +/****************************************************************************** + TX_RING_t is sructure representing our local reference(s) to the ring + *****************************************************************************/ +typedef struct _tx_ring_t +{ + /************************************************************************** + TCB (Transmit Control Block) memory and lists + *************************************************************************/ + PUCHAR MpTcbMem; + + + /************************************************************************** + List of TCBs that are ready to be used + *************************************************************************/ + PMP_TCB TCBReadyQueueHead; + PMP_TCB TCBReadyQueueTail; + + + /************************************************************************** + list of TCBs that are currently being sent. NOTE that access to all + three of these (including nBusySend) are controlled via the + TCBSendQLock. This lock should be secured prior to incementing / + decrementing nBusySend, or any queue manipulation on CurrSendHead / Tail + *************************************************************************/ + PMP_TCB CurrSendHead; + PMP_TCB CurrSendTail; + INT32 nBusySend; + + + /************************************************************************** + List of packets (not TCBs) that were queued for lack of resources + *************************************************************************/ + struct list_head SendWaitQueue; + INT32 nWaitSend; + + + /************************************************************************** + The actual descriptor ring + *************************************************************************/ + PTX_DESC_ENTRY_t pTxDescRingVa; + dma_addr_t pTxDescRingPa; + UINT64 pTxDescRingAdjustedPa; + UINT64 TxDescOffset; + + + /************************************************************************** + ReadyToSend indicates where we last wrote to in the descriptor ring. + *************************************************************************/ + TXDMA_SERVICE_REQUEST_t txDmaReadyToSend; + + + /************************************************************************** + The location of the write-back status block + *************************************************************************/ + PTX_STATUS_BLOCK_t pTxStatusVa; + dma_addr_t pTxStatusPa; + + + /************************************************************************** + A Block of zeroes, used to pad packets that are less than 60 bytes. + *************************************************************************/ + void *pTxDummyBlkVa; + dma_addr_t pTxDummyBlkPa; + + TXMAC_ERR_t TxMacErr; + + + /************************************************************************** + Variables to track the Tx interrupt coalescing features + *************************************************************************/ + INT32 TxPacketsSinceLastinterrupt; +} +TX_RING_t, *PTX_RING_t; + + + + +/****************************************************************************** + Forward declaration of the frag-list for the following prototypes + *****************************************************************************/ +typedef struct _MP_FRAG_LIST MP_FRAG_LIST, *PMP_FRAG_LIST; + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + + + +/****************************************************************************** + PROTOTYPES for et1310_tx.c + *****************************************************************************/ +int et131x_tx_dma_memory_alloc( struct et131x_adapter *adapter ); +void et131x_tx_dma_memory_free( struct et131x_adapter *adapter ); +void ConfigTxDmaRegs( struct et131x_adapter *pAdapter ); +void et131x_init_send( struct et131x_adapter *adapter ); +void et131x_tx_dma_disable( struct et131x_adapter *pAdapter ); +void et131x_tx_dma_enable( struct et131x_adapter *pAdapter ); +void et131x_handle_send_interrupt( struct et131x_adapter *pAdapter ); +void et131x_free_busy_send_packets( struct et131x_adapter *pAdapter ); +int et131x_send_packets( struct sk_buff *skb, struct net_device *netdev ); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ET1310_TX_H__ */ --- linux-2.6.27.orig/ubuntu/et131x/et131x_debug.h +++ linux-2.6.27/ubuntu/et131x/et131x_debug.h @@ -0,0 +1,267 @@ +/******************************************************************************* + * Agere Systems Inc. + * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + *------------------------------------------------------------------------------ + * + * et131x_debug.h - Defines, structs, enums, prototypes, etc. used for + * outputting debug messages to the system logging facility + * (ksyslogd) + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2005 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following Disclaimer as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following Disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + + + + +/****************************************************************************** + * VERSION CONTROL INFORMATION + ****************************************************************************** + + $RCSFile: $ + $Date: 2005/08/01 19:35:12 $ + $Revision: 1.10 $ + $Name: T_20060131_v1-2-2 $ + $Author: vjs $ + + *****************************************************************************/ + + + + +#ifndef __ET131X_DBG_H__ +#define __ET131X_DBG_H__ + + + + +/****************************************************************************** + Define Masks for debugging types/levels + *****************************************************************************/ +#define DBG_ERROR_ON 0x00000001L +#define DBG_WARNING_ON 0x00000002L +#define DBG_NOTICE_ON 0x00000004L +#define DBG_TRACE_ON 0x00000008L +#define DBG_VERBOSE_ON 0x00000010L +#define DBG_PARAM_ON 0x00000020L +#define DBG_BREAK_ON 0x00000040L +#define DBG_RX_ON 0x00000100L +#define DBG_TX_ON 0x00000200L + + + + +#ifdef ET131X_DBG + + +/****************************************************************************** + Set the level of debugging if not done with a preprocessor define. See + et131x_main.c, function et131x_init_module() for how the debug level + translates into the types of messages displayed. + *****************************************************************************/ +#ifndef DBG_LVL +#define DBG_LVL 3 +#endif /* DBG_LVL */ + + +#define DBG_DEFAULTS (DBG_ERROR_ON | DBG_WARNING_ON | DBG_BREAK_ON ) + +#define DBG_FLAGS(A) (A)->dbgFlags +#define DBG_NAME(A) (A)->dbgName +#define DBG_LEVEL(A) (A)->dbgLevel + + +#ifndef PRINTK +# define PRINTK(S...) printk(S) +#endif /* PRINTK */ + + +#ifndef DBG_PRINT +# define DBG_PRINT(S...) PRINTK(KERN_DEBUG S) +#endif /* DBG_PRINT */ + + +#ifndef DBG_PRINTC +# define DBG_PRINTC(S...) PRINTK(S) +#endif /* DBG_PRINTC */ + + +#ifndef DBG_TRAP +# define DBG_TRAP {} //BUG() +#endif /* DBG_TRAP */ + + +#define _ENTER_STR ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" +#define _LEAVE_STR "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" + + +#define _DBG_ENTER(A) DBG_PRINT("%s:%.*s:%s\n",DBG_NAME(A),++DBG_LEVEL(A),_ENTER_STR,__FUNC__) +#define _DBG_LEAVE(A) DBG_PRINT("%s:%.*s:%s\n",DBG_NAME(A),DBG_LEVEL(A)--,_LEAVE_STR,__FUNC__) + + +#define DBG_FUNC(F) static const char __FUNC__[] = F; + + +#define DBG_ENTER(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \ + _DBG_ENTER(A);} + + +#define DBG_LEAVE(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \ + _DBG_LEAVE(A);} + + +#define DBG_PARAM(A,N,F,S...) {if (DBG_FLAGS(A) & DBG_PARAM_ON) \ + DBG_PRINT(" %s -- "F"\n",N,S);} + + +#define DBG_ERROR(A,S...) {if (DBG_FLAGS(A) & DBG_ERROR_ON) \ + {DBG_PRINT("%s:ERROR:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);DBG_TRAP;}} + + +#define DBG_WARNING(A,S...) {if (DBG_FLAGS(A) & DBG_WARNING_ON) \ + {DBG_PRINT("%s:WARNING:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);}} + + +#define DBG_NOTICE(A,S...) {if (DBG_FLAGS(A) & DBG_NOTICE_ON) \ + {DBG_PRINT("%s:NOTICE:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);}} + + +#define DBG_TRACE(A,S...) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \ + {DBG_PRINT("%s:TRACE:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);}} + +#define DBG_VERBOSE(A,S...) {if (DBG_FLAGS(A) & DBG_VERBOSE_ON) \ + {DBG_PRINT("%s:VERBOSE:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);}} + + +#define DBG_RX(A,S...) {if (DBG_FLAGS(A) & DBG_RX_ON) \ + {DBG_PRINT(S);}} + +#define DBG_RX_ENTER(A) {if (DBG_FLAGS(A) & DBG_RX_ON) \ + _DBG_ENTER(A);} + +#define DBG_RX_LEAVE(A) {if (DBG_FLAGS(A) & DBG_RX_ON) \ + _DBG_LEAVE(A);} + +#define DBG_TX(A,S...) {if (DBG_FLAGS(A) & DBG_TX_ON) \ + {DBG_PRINT(S);}} + +#define DBG_TX_ENTER(A) {if (DBG_FLAGS(A) & DBG_TX_ON) \ + _DBG_ENTER(A);} + +#define DBG_TX_LEAVE(A) {if (DBG_FLAGS(A) & DBG_TX_ON) \ + _DBG_LEAVE(A);} + + +#define DBG_ASSERT(C) {if (!(C)) \ + {DBG_PRINT("ASSERT(%s) -- %s#%d (%s)\n", \ + #C,__FILE__,__LINE__,__FUNC__); \ + DBG_TRAP;}} +#define STATIC + + +typedef struct +{ + char *dbgName; + int dbgLevel; + unsigned long dbgFlags; +} dbg_info_t; + + + + +#else /* ET131X_DBG */ + + + + +#define DBG_DEFN +#define DBG_TRAP +#define DBG_FUNC(F) +#define DBG_PRINT(S...) +#define DBG_ENTER(A) +#define DBG_LEAVE(A) +#define DBG_PARAM(A,N,F,S...) +#define DBG_ERROR(A,S...) +#define DBG_WARNING(A,S...) +#define DBG_NOTICE(A,S...) +#define DBG_TRACE(A,S...) +#define DBG_VERBOSE(A,S...) +#define DBG_RX(A,S...) +#define DBG_RX_ENTER(A) +#define DBG_RX_LEAVE(A) +#define DBG_TX(A,S...) +#define DBG_TX_ENTER(A) +#define DBG_TX_LEAVE(A) +#define DBG_ASSERT(C) +#define STATIC static + +#endif /* ET131X_DBG */ + + + + +/****************************************************************************** + Forward declaration of the private adapter structure + *****************************************************************************/ +struct et131x_adapter; + + + + +/****************************************************************************** + PROTOTYPES for et131x_debug.c + *****************************************************************************/ +void DumpTxQueueContents( int dbgLvl, struct et131x_adapter *pAdapter ); +void DumpDeviceBlock( int dbgLvl, struct et131x_adapter *pAdapter, unsigned int Block ); +void DumpDeviceReg( int dbgLvl, struct et131x_adapter *pAdapter ); + + + + +#endif /* __ET131X_DBG_H__ */ --- linux-2.6.27.orig/ubuntu/include/README +++ linux-2.6.27/ubuntu/include/README @@ -0,0 +1,4 @@ +Only use this directory for things which need to share their headers with +other parts of the kernel or other modules in ubuntu/ + +Otherwise, keep them local to the module directory. --- linux-2.6.27.orig/ubuntu/include/linux/tlsf.h +++ linux-2.6.27/ubuntu/include/linux/tlsf.h @@ -0,0 +1,93 @@ +/* + * Two Levels Segregate Fit memory allocator (TLSF) + * Version 2.3.2 + * + * Written by Miguel Masmano Tello + * + * Thanks to Ismael Ripoll for his suggestions and reviews + * + * Copyright (C) 2007, 2006, 2005, 2004 + * + * This code is released using a dual license strategy: GPL/LGPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of the GNU General Public License Version 2.0 + * Released under the terms of the GNU Lesser General Public License Version 2.1 + * + * This is kernel port of TLSF allocator. + * Original code can be found at: http://rtportal.upv.es/rtmalloc/ + * - Nitin Gupta (nitingupta910@gmail.com) + */ + +#ifndef _TLSF_H_ +#define _TLSF_H_ + +typedef void* (get_memory)(size_t bytes); +typedef void (put_memory)(void *ptr); + +/** + * tlsf_create_memory_pool - create dynamic memory pool + * @name: name of the pool + * @get_mem: callback function used to expand pool + * @put_mem: callback function used to shrink pool + * @init_size: inital pool size (in bytes) + * @max_size: maximum pool size (in bytes) - set this as 0 for no limit + * @grow_size: amount of memory (in bytes) added to pool whenever required + * + * All size values are rounded up to next page boundary. + */ +extern void *tlsf_create_memory_pool(const char *name, + get_memory get_mem, + put_memory put_mem, + size_t init_size, + size_t max_size, + size_t grow_size); +/** + * tlsf_destory_memory_pool - cleanup given pool + * @mem_pool: Pool to be destroyed + * + * Data structures associated with pool are freed. + * All memory allocated from pool must be freed before + * destorying it. + */ +extern void tlsf_destroy_memory_pool(void *mem_pool); + +/** + * tlsf_malloc - allocate memory from given pool + * @size: no. of bytes + * @mem_pool: pool to allocate from + */ +extern void *tlsf_malloc(size_t size, void *mem_pool); + +/** + * tlsf_calloc - allocate and zero-out memory from given pool + * @size: no. of bytes + * @mem_pool: pool to allocate from + */ +extern void *tlsf_calloc(size_t nelem, size_t elem_size, void *mem_pool); + +/** + * tlsf_free - free memory from given pool + * @ptr: address of memory to be freed + * @mem_pool: pool to free from + */ +extern void tlsf_free(void *ptr, void *mem_pool); + +/** + * tlsf_get_used_size - get memory currently used by given pool + * + * Used memory includes stored data + metadata + internal fragmentation + */ +extern size_t tlsf_get_used_size(void *mem_pool); + +/** + * tlsf_get_total_size - get total memory currently allocated for given pool + * + * This is the total memory currently allocated for this pool which includes + * used size + free size. + * + * (Total - Used) is good indicator of memory efficiency of allocator. + */ +extern size_t tlsf_get_total_size(void *mem_pool); + +#endif --- linux-2.6.27.orig/ubuntu/include/linux/squashfs_fs_i.h +++ linux-2.6.27/ubuntu/include/linux/squashfs_fs_i.h @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif --- linux-2.6.27.orig/ubuntu/include/linux/squashfs_fs.h +++ linux-2.6.27/ubuntu/include/linux/squashfs_fs.h @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif --- linux-2.6.27.orig/ubuntu/include/linux/aufs_types.h +++ linux-2.6.27/ubuntu/include/linux/aufs_types.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008 Junjiro Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* $Id: aufs_type.h,v 1.110 2008/06/09 01:11:58 sfjro Exp $ */ + +#include + +#ifndef __AUFS_TYPE_H__ +#define __AUFS_TYPE_H__ + +#define AUFS_VERSION "20080609" + +/* move this to linux-2.6.19/include/magic.h */ +#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_BRANCH_MAX_127 +/* some environments treat 'char' as 'unsigned char' by default */ +typedef signed char aufs_bindex_t; +#define AUFS_BRANCH_MAX 127 +#else +typedef short aufs_bindex_t; +#ifdef CONFIG_AUFS_BRANCH_MAX_511 +#define AUFS_BRANCH_MAX 511 +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) +#define AUFS_BRANCH_MAX 1023 +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) +#define AUFS_BRANCH_MAX 32767 +#else +#error unknown CONFIG_AUFS_BRANCH_MAX value +#endif +#endif + +#define AUFS_NAME "aufs" +#define AUFS_FSTYPE AUFS_NAME + +#define AUFS_ROOT_INO 2 +#define AUFS_FIRST_INO 11 + +#define AUFS_WH_PFX ".wh." +#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) +#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" +#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME +#define AUFS_XINO_TRUNC_INIT 64 /* blocks */ +#define AUFS_XINO_TRUNC_STEP 4 /* blocks */ +#define AUFS_DIRWH_DEF 3 +#define AUFS_RDCACHE_DEF 10 /* seconds */ +#define AUFS_WKQ_NAME AUFS_NAME "d" +#define AUFS_NWKQ_DEF 4 +#define AUFS_MFS_SECOND_DEF 30 /* seconds */ +#define AUFS_PLINK_WARN 100 /* number of plinks */ + +#ifdef CONFIG_AUFS_COMPAT +#define AUFS_DIROPQ_NAME "__dir_opaque" +#else +#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ +#endif +#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME + +/* will be whiteouted doubly */ +#define AUFS_WH_BASENAME AUFS_WH_PFX AUFS_NAME +#define AUFS_WH_PLINKDIR AUFS_WH_PFX "plink" + +/* ---------------------------------------------------------------------- */ + +/* ioctl */ +#if 0 /* reserved for future use */ +enum { + AuCtlErr, + AuCtlErr_Last +}; +enum { + AuCtl_REFRESH, AuCtl_REFRESHV, + AuCtl_FLUSH_PLINK, + AuCtl_CPUP, + AuCtl_CPDOWN, AuCtl_MVDOWN, + AuCtl_DIROPQ +}; + +struct aufs_ctl_cp { + int bsrc, bdst; + int err; +}; + +#define AuCtlType 'A' +#define AUFS_CTL_REFRESH _IO(AuCtlType, AuCtl_REFRESH) +#define AUFS_CTL_REFRESHV _IO(AuCtlType, AuCtl_REFRESHV) +#define AUFS_CTL_FLUSH_PLINK _IOR(AuCtlType, AuCtl_FLUSH_PLINK) +#define AUFS_CTL_CPUP _IOWR(AuCtlType, AuCtl_CPUP, struct aufs_ctl_cp) +#define AUFS_CTL_CPDOWN \ + _IOWR(AuCtlType, AuCtl_CPDOWN, struct aufs_ctl_cp) +#define AUFS_CTL_MVDOWN \ + _IOWR(AuCtlType, AuCtl_MVDOWN, struct aufs_ctl_cp) +#define AUFS_CTL_DIROPQ _IO(AuCtlType, AuCtl_DIROPQ) +#endif + +#endif /* __AUFS_TYPE_H__ */ --- linux-2.6.27.orig/ubuntu/include/linux/squashfs_fs_sb.h +++ linux-2.6.27/ubuntu/include/linux/squashfs_fs_sb.h @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex block_cache_mutex; + struct mutex fragment_mutex; + struct mutex meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif --- linux-2.6.27.orig/ubuntu/iscsitarget/target_disk.c +++ linux-2.6.27/ubuntu/iscsitarget/target_disk.c @@ -0,0 +1,482 @@ +/* + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + * + * heavily based on code from kernel/iscsi.c: + * Copyright (C) 2002-2003 Ardis Technolgies , + * licensed under the terms of the GNU GPL v2.0, + */ + +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" + +static int insert_disconnect_pg(u8 *ptr) +{ + unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + memcpy(ptr, disconnect_pg, sizeof(disconnect_pg)); + return sizeof(disconnect_pg); +} + +static int insert_caching_pg(u8 *ptr, int async) +{ + unsigned char caching_pg[] = {0x08, 0x12, 0x10, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + + memcpy(ptr, caching_pg, sizeof(caching_pg)); + if (async) + ptr[2] |= 0x04; /* set WCE bit if we're caching writes */ + return sizeof(caching_pg); +} + +static int insert_ctrl_m_pg(u8 *ptr) +{ + unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x4b}; + + memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg)); + return sizeof(ctrl_m_pg); +} + +static int insert_iec_m_pg(u8 *ptr) +{ + unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}; + + memcpy(ptr, iec_m_pg, sizeof(iec_m_pg)); + return sizeof(iec_m_pg); +} + +static int insert_format_m_pg(u8 *ptr) +{ + unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00}; + memcpy(ptr, format_m_pg, sizeof(format_m_pg)); + return sizeof(format_m_pg); +} + +static int insert_geo_m_pg(u8 *ptr, u64 sec) +{ + unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00}; + u32 ncyl; + u32 n; + + /* assume 0xff heads, 15krpm. */ + memcpy(ptr, geo_m_pg, sizeof(geo_m_pg)); + ncyl = sec >> 14; /* 256 * 64 */ + memcpy(&n, ptr+1, sizeof(u32)); + n = n | cpu_to_be32(ncyl); + memcpy(ptr+1, &n, sizeof(u32)); + return sizeof(geo_m_pg); +} + +static int build_mode_sense_response(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct tio *tio = cmnd->tio; + u8 *data, *scb = req->scb; + int len = 4, err = 0; + u8 pcode; + + pcode = req->scb[2] & 0x3f; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + + if (LUReadonly(cmnd->lun)) + data[2] = 0x80; + + if ((scb[1] & 0x8)) + data[3] = 0; + else { + data[3] = 8; + len += 8; + *(u32 *)(data + 4) = (cmnd->lun->blk_cnt >> 32) ? + cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt); + *(u32 *)(data + 8) = cpu_to_be32(1 << cmnd->lun->blk_shift); + } + + switch (pcode) { + case 0x0: + break; + case 0x2: + len += insert_disconnect_pg(data + len); + break; + case 0x3: + len += insert_format_m_pg(data + len); + break; + case 0x4: + len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt); + break; + case 0x8: + len += insert_caching_pg(data + len, LUAsync(cmnd->lun)); + break; + case 0xa: + len += insert_ctrl_m_pg(data + len); + break; + case 0x1c: + len += insert_iec_m_pg(data + len); + break; + case 0x3f: + len += insert_disconnect_pg(data + len); + len += insert_format_m_pg(data + len); + len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt); + len += insert_caching_pg(data + len, LUAsync(cmnd->lun)); + len += insert_ctrl_m_pg(data + len); + len += insert_iec_m_pg(data + len); + break; + default: + err = -1; + } + + data[0] = len - 1; + + tio_set(tio, len, 0); + + return err; +} + +static int build_inquiry_response(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct tio *tio = cmnd->tio; + u8 *data; + u8 *scb = req->scb; + int err = -1; + + if (((req->scb[1] & 0x3) == 0x3) || (!(req->scb[1] & 0x3) && req->scb[2])) + return err; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + + if (!(scb[1] & 0x3)) { + data[2] = 4; + data[3] = 0x42; + data[4] = 59; + data[7] = 0x02; + memset(data + 8, 0x20, 28); + memcpy(data + 8, + VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8)); + memcpy(data + 16, + PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16)); + memcpy(data + 32, + PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4)); + data[58] = 0x03; + data[59] = 0x20; + data[60] = 0x09; + data[61] = 0x60; + data[62] = 0x03; + data[63] = 0x00; + tio_set(tio, 64, 0); + err = 0; + } else if (scb[1] & 0x2) { + /* CmdDt bit is set */ + /* We do not support it now. */ + data[1] = 0x1; + data[5] = 0; + tio_set(tio, 6, 0); + err = 0; + } else if (scb[1] & 0x1) { + /* EVPD bit set */ + if (scb[2] == 0x0) { + data[1] = 0x0; + data[3] = 3; + data[4] = 0x0; + data[5] = 0x80; + data[6] = 0x83; + tio_set(tio, 7, 0); + err = 0; + } else if (scb[2] == 0x80) { + int len = (cmnd->lun && strlen(cmnd->lun->scsi_sn)) ? + SCSI_SN_LEN : 4; + + data[1] = 0x80; + data[3] = len; + memset(data + 4, 0x20, len); + tio_set(tio, len + 4, 0); + err = 0; + + if (len == SCSI_SN_LEN) { + char *p, *q; + + p = data + 4 + len - 1; + q = cmnd->lun->scsi_sn + len - 1; + + for (; len > 0; len--, q--) + if (isascii(*q) && isprint(*q)) + *(p--) = *q; + } + } else if (scb[2] == 0x83) { + u32 len = SCSI_ID_LEN * sizeof(u8); + + data[1] = 0x83; + data[3] = len + 4; + data[4] = 0x1; + data[5] = 0x1; + data[7] = len; + if (cmnd->lun) /* We need this ? */ + memcpy(data + 8, cmnd->lun->scsi_id, len); + tio_set(tio, len + 8, 0); + err = 0; + } + } + + tio_set(tio, min_t(u8, tio->size, scb[4]), 0); + if (!cmnd->lun) + data[0] = TYPE_NO_LUN; + + return err; +} + +static int build_report_luns_response(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct tio *tio = cmnd->tio; + u32 *data, size, len; + struct iet_volume *lun; + int rest, idx = 0; + + size = (u32)req->scb[6] << 24 | (u32)req->scb[7] << 16 | + (u32)req->scb[8] << 8 | (u32)req->scb[9]; + if (size < 16) + return -1; + + len = atomic_read(&cmnd->conn->session->target->nr_volumes) * 8; + size = min(size & ~(8 - 1), len + 8); + + assert(!tio); + tio = cmnd->tio = tio_alloc(get_pgcnt(size, 0)); + tio_set(tio, size, 0); + + data = page_address(tio->pvec[idx]); + assert(data); + *data++ = cpu_to_be32(len); + *data++ = 0; + size -= 8; + rest = PAGE_CACHE_SIZE - 8; + list_for_each_entry(lun, &cmnd->conn->session->target->volumes, list) { + if (lun->l_state != IDEV_RUNNING) + continue; + + *data++ = cpu_to_be32((0x3ff & lun->lun) << 16 | + ((lun->lun > 0xff) ? (0x1 << 30) : 0)); + *data++ = 0; + if ((size -= 8) == 0) + break; + if ((rest -= 8) == 0) { + idx++; + data = page_address(tio->pvec[idx]); + rest = PAGE_CACHE_SIZE; + } + } + + return 0; +} + +static int build_read_capacity_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + u32 *data; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + + data[0] = (cmnd->lun->blk_cnt >> 32) ? + cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt - 1); + data[1] = cpu_to_be32(1U << cmnd->lun->blk_shift); + + tio_set(tio, 8, 0); + return 0; +} + +static int build_request_sense_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + u8 *data; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + memset(data, 0, 18); + data[0] = 0xf0; + data[1] = 0; + data[2] = NO_SENSE; + data[7] = 10; + tio_set(tio, 18, 0); + + return 0; +} + +static int build_service_action_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + u32 *data; + u64 *data64; + +/* assert((req->scb[1] & 0x1f) == 0x10); */ + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + data64 = (u64*) data; + data64[0] = cpu_to_be64(cmnd->lun->blk_cnt - 1); + data[2] = cpu_to_be32(1UL << cmnd->lun->blk_shift); + + tio_set(tio, 12, 0); + return 0; +} + +static int build_read_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + + assert(tio); + assert(cmnd->lun); + + return tio_read(cmnd->lun, tio); +} + +static int build_write_response(struct iscsi_cmnd *cmnd) +{ + int err; + struct tio *tio = cmnd->tio; + + assert(tio); + assert(cmnd->lun); + + list_del_init(&cmnd->list); + err = tio_write(cmnd->lun, tio); + if (!err && !LUAsync(cmnd->lun)) + err = tio_sync(cmnd->lun, tio); + + return err; +} + +static int build_sync_cache_response(struct iscsi_cmnd *cmnd) +{ + assert(cmnd->lun); + return tio_sync(cmnd->lun, NULL); +} + +static int build_generic_response(struct iscsi_cmnd *cmnd) +{ + return 0; +} + +static int build_reserve_response(struct iscsi_cmnd *cmnd) +{ + return volume_reserve(cmnd->lun, cmnd->conn->session->sid); +} + +static int build_release_response(struct iscsi_cmnd *cmnd) +{ + return volume_release(cmnd->lun, + cmnd->conn->session->sid, 0); +} + +static int build_reservation_conflict_response(struct iscsi_cmnd *cmnd) +{ + return -EBUSY; +} + +static int disk_execute_cmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + + req->opcode &= ISCSI_OPCODE_MASK; + + if (is_volume_reserved(cmnd->lun, + cmnd->conn->session->sid)) { + switch (req->scb[0]) { + case INQUIRY: + case RELEASE: + case REPORT_LUNS: + case REQUEST_SENSE: + /* allowed commands when reserved */ + break; + default: + /* return reservation conflict for all others */ + send_scsi_rsp(cmnd, + build_reservation_conflict_response); + return 0; + } + } + + switch (req->scb[0]) { + case INQUIRY: + send_data_rsp(cmnd, build_inquiry_response); + break; + case REPORT_LUNS: + send_data_rsp(cmnd, build_report_luns_response); + break; + case READ_CAPACITY: + send_data_rsp(cmnd, build_read_capacity_response); + break; + case MODE_SENSE: + send_data_rsp(cmnd, build_mode_sense_response); + break; + case REQUEST_SENSE: + send_data_rsp(cmnd, build_request_sense_response); + break; + case SERVICE_ACTION_IN: + send_data_rsp(cmnd, build_service_action_response); + break; + case READ_6: + case READ_10: + case READ_16: + send_data_rsp(cmnd, build_read_response); + break; + case WRITE_6: + case WRITE_10: + case WRITE_16: + case WRITE_VERIFY: + send_scsi_rsp(cmnd, build_write_response); + break; + case SYNCHRONIZE_CACHE: + send_scsi_rsp(cmnd, build_sync_cache_response); + break; + case RESERVE: + send_scsi_rsp(cmnd, build_reserve_response); + break; + case RELEASE: + send_scsi_rsp(cmnd, build_release_response); + break; + case START_STOP: + case TEST_UNIT_READY: + case VERIFY: + case VERIFY_16: + send_scsi_rsp(cmnd, build_generic_response); + break; + default: + eprintk("%s\n", "we should not come here!"); + break; + } + + return 0; +} + +struct target_type disk_ops = +{ + .id = 0, + .execute_cmnd = disk_execute_cmnd, +}; --- linux-2.6.27.orig/ubuntu/iscsitarget/nthread.c +++ linux-2.6.27/ubuntu/iscsitarget/nthread.c @@ -0,0 +1,700 @@ +/* + * Network thread. + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "digest.h" + +enum daemon_state_bit { + D_ACTIVE, + D_DATA_READY, +}; + +void nthread_wakeup(struct iscsi_target *target) +{ + struct network_thread_info *info = &target->nthread_info; + + spin_lock_bh(&info->nthread_lock); + set_bit(D_DATA_READY, &info->flags); + wake_up_process(info->task); + spin_unlock_bh(&info->nthread_lock); +} + +static inline void iscsi_conn_init_read(struct iscsi_conn *conn, void *data, size_t len) +{ + len = (len + 3) & -4; // XXX ??? + conn->read_iov[0].iov_base = data; + conn->read_iov[0].iov_len = len; + conn->read_msg.msg_iov = conn->read_iov; + conn->read_msg.msg_iovlen = 1; + conn->read_size = (len + 3) & -4; +} + +static void iscsi_conn_read_ahs(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + cmnd->pdu.ahs = kmalloc(cmnd->pdu.ahssize, __GFP_NOFAIL|GFP_KERNEL); + assert(cmnd->pdu.ahs); + iscsi_conn_init_read(conn, cmnd->pdu.ahs, cmnd->pdu.ahssize); +} + +static struct iscsi_cmnd * iscsi_get_send_cmnd(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd = NULL; + + spin_lock(&conn->list_lock); + if (!list_empty(&conn->write_list)) { + cmnd = list_entry(conn->write_list.next, struct iscsi_cmnd, list); + list_del_init(&cmnd->list); + } + spin_unlock(&conn->list_lock); + + return cmnd; +} + +static int is_data_available(struct iscsi_conn *conn) +{ + int avail, res; + mm_segment_t oldfs; + struct socket *sock = conn->sock; + + oldfs = get_fs(); + set_fs(get_ds()); + res = sock->ops->ioctl(sock, SIOCINQ, (unsigned long) &avail); + set_fs(oldfs); + return (res >= 0) ? avail : res; +} + +static void forward_iov(struct msghdr *msg, int len) +{ + while (msg->msg_iov->iov_len <= len) { + len -= msg->msg_iov->iov_len; + msg->msg_iov++; + msg->msg_iovlen--; + } + + msg->msg_iov->iov_base = (char *) msg->msg_iov->iov_base + len; + msg->msg_iov->iov_len -= len; +} + +static int do_recv(struct iscsi_conn *conn, int state) +{ + mm_segment_t oldfs; + struct msghdr msg; + struct iovec iov[ISCSI_CONN_IOV_MAX]; + int i, len, res; + + if (!test_bit(CONN_ACTIVE, &conn->state)) { + res = -EIO; + goto out; + } + + if (is_data_available(conn) <= 0) { + res = -EAGAIN; + goto out; + } + + msg.msg_iov = iov; + msg.msg_iovlen = min_t(size_t, conn->read_msg.msg_iovlen, ISCSI_CONN_IOV_MAX); + for (i = 0, len = 0; i < msg.msg_iovlen; i++) { + iov[i] = conn->read_msg.msg_iov[i]; + len += iov[i].iov_len; + } + + oldfs = get_fs(); + set_fs(get_ds()); + res = sock_recvmsg(conn->sock, &msg, len, MSG_DONTWAIT | MSG_NOSIGNAL); + set_fs(oldfs); + + if (res <= 0) { + switch (res) { + case -EAGAIN: + case -ERESTARTSYS: + break; + default: + eprintk("%d\n", res); + conn_close(conn); + break; + } + } else { + conn->read_size -= res; + if (conn->read_size) + forward_iov(&conn->read_msg, res); + else + conn->read_state = state; + } + +out: + dprintk(D_IOD, "%d\n", res); + + return res; +} + +enum rx_state { + RX_INIT_BHS, /* Must be zero. */ + RX_BHS, + + RX_INIT_AHS, + RX_AHS, + + RX_INIT_HDIGEST, + RX_HDIGEST, + RX_CHECK_HDIGEST, + + RX_INIT_DATA, + RX_DATA, + + RX_INIT_DDIGEST, + RX_DDIGEST, + RX_CHECK_DDIGEST, + + RX_END, +}; + +static void rx_ddigest(struct iscsi_conn *conn, int state) +{ + struct iscsi_cmnd *cmnd = conn->read_cmnd; + int res = digest_rx_data(cmnd); + + if (!res) + conn->read_state = state; + else + conn_close(conn); +} + +static void rx_hdigest(struct iscsi_conn *conn, int state) +{ + struct iscsi_cmnd *cmnd = conn->read_cmnd; + int res = digest_rx_header(cmnd); + + if (!res) + conn->read_state = state; + else + conn_close(conn); +} + +static struct iscsi_cmnd *create_cmnd(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd; + + cmnd = cmnd_alloc(conn, 1); + iscsi_conn_init_read(cmnd->conn, &cmnd->pdu.bhs, sizeof(cmnd->pdu.bhs)); + conn->read_state = RX_BHS; + + return cmnd; +} + +static int recv(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd = conn->read_cmnd; + int hdigest, ddigest, res = 1; + + if (!test_bit(CONN_ACTIVE, &conn->state)) + return -EIO; + + hdigest = conn->hdigest_type & DIGEST_NONE ? 0 : 1; + ddigest = conn->ddigest_type & DIGEST_NONE ? 0 : 1; + + switch (conn->read_state) { + case RX_INIT_BHS: + assert(!cmnd); + cmnd = conn->read_cmnd = create_cmnd(conn); + case RX_BHS: + res = do_recv(conn, RX_INIT_AHS); + if (res <= 0 || conn->read_state != RX_INIT_AHS) + break; + case RX_INIT_AHS: + iscsi_cmnd_get_length(&cmnd->pdu); + if (cmnd->pdu.ahssize) { + iscsi_conn_read_ahs(conn, cmnd); + conn->read_state = RX_AHS; + } else + conn->read_state = hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA; + + if (conn->read_state != RX_AHS) + break; + case RX_AHS: + res = do_recv(conn, hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA); + if (res <= 0 || conn->read_state != RX_INIT_HDIGEST) + break; + case RX_INIT_HDIGEST: + iscsi_conn_init_read(conn, &cmnd->hdigest, sizeof(u32)); + conn->read_state = RX_HDIGEST; + case RX_HDIGEST: + res = do_recv(conn, RX_CHECK_HDIGEST); + if (res <= 0 || conn->read_state != RX_CHECK_HDIGEST) + break; + case RX_CHECK_HDIGEST: + rx_hdigest(conn, RX_INIT_DATA); + if (conn->read_state != RX_INIT_DATA) + break; + case RX_INIT_DATA: + cmnd_rx_start(cmnd); + conn->read_state = cmnd->pdu.datasize ? RX_DATA : RX_END; + if (conn->read_state != RX_DATA) + break; + case RX_DATA: + res = do_recv(conn, ddigest ? RX_INIT_DDIGEST : RX_END); + if (res <= 0 || conn->read_state != RX_INIT_DDIGEST) + break; + case RX_INIT_DDIGEST: + iscsi_conn_init_read(conn, &cmnd->ddigest, sizeof(u32)); + conn->read_state = RX_DDIGEST; + case RX_DDIGEST: + res = do_recv(conn, RX_CHECK_DDIGEST); + if (res <= 0 || conn->read_state != RX_CHECK_DDIGEST) + break; + case RX_CHECK_DDIGEST: + rx_ddigest(conn, RX_END); + break; + default: + eprintk("%d %d %x\n", res, conn->read_state, cmnd_opcode(cmnd)); + assert(0); + } + + if (res <= 0) + return res; + + if (conn->read_state != RX_END) + return res; + + if (conn->read_size) { + eprintk("%d %x %d\n", res, cmnd_opcode(cmnd), conn->read_size); + assert(0); + } + + cmnd_rx_end(cmnd); + if (conn->read_size) { + eprintk("%x %d\n", cmnd_opcode(cmnd), conn->read_size); + conn->read_state = RX_DATA; + return 1; + } + + conn->read_cmnd = NULL; + conn->read_state = RX_INIT_BHS; + + return 0; +} + +/* This is taken from the Ardis code. */ +static int write_data(struct iscsi_conn *conn) +{ + mm_segment_t oldfs; + struct file *file; + struct socket *sock; + ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); + struct tio *tio; + struct iovec *iop; + int saved_size, size, sendsize; + int offset, idx; + int flags, res; + + file = conn->file; + saved_size = size = conn->write_size; + iop = conn->write_iop; + + if (iop) while (1) { + loff_t off = 0; + unsigned long count; + struct iovec *vec; + int rest; + + vec = iop; + for (count = 0; vec->iov_len; count++, vec++) + ; + oldfs = get_fs(); + set_fs(KERNEL_DS); + res = vfs_writev(file, (struct iovec __user *) iop, count, &off); + set_fs(oldfs); + dprintk(D_DATA, "%#Lx:%u: %d(%ld)\n", + (unsigned long long) conn->session->sid, conn->cid, + res, (long) iop->iov_len); + if (unlikely(res <= 0)) { + if (res == -EAGAIN || res == -EINTR) { + conn->write_iop = iop; + goto out_iov; + } + goto err; + } + + rest = res; + size -= res; + while (iop->iov_len <= rest && rest) { + rest -= iop->iov_len; + iop++; + } + iop->iov_base += rest; + iop->iov_len -= rest; + + if (!iop->iov_len) { + conn->write_iop = NULL; + if (size) + break; + goto out_iov; + } + } + + if (!(tio = conn->write_tcmnd)) { + eprintk("%s\n", "warning data missing!"); + return 0; + } + offset = conn->write_offset; + idx = offset >> PAGE_CACHE_SHIFT; + offset &= ~PAGE_CACHE_MASK; + + sock = conn->sock; + sendpage = sock->ops->sendpage ? : sock_no_sendpage; + flags = MSG_DONTWAIT; + + while (1) { + sendsize = PAGE_CACHE_SIZE - offset; + if (size <= sendsize) { + res = sendpage(sock, tio->pvec[idx], offset, size, flags); + dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n", + sock->ops->sendpage ? "sendpage" : "writepage", + (unsigned long long ) conn->session->sid, conn->cid, + res, tio->pvec[idx]->index, offset, size); + if (unlikely(res <= 0)) { + if (res == -EAGAIN || res == -EINTR) { + goto out; + } + goto err; + } + if (res == size) { + conn->write_tcmnd = NULL; + conn->write_size = 0; + return saved_size; + } + offset += res; + size -= res; + continue; + } + + res = sendpage(sock, tio->pvec[idx], offset,sendsize, flags | MSG_MORE); + dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n", + sock->ops->sendpage ? "sendpage" : "writepage", + (unsigned long long ) conn->session->sid, conn->cid, + res, tio->pvec[idx]->index, offset, sendsize); + if (unlikely(res <= 0)) { + if (res == -EAGAIN || res == -EINTR) { + goto out; + } + goto err; + } + if (res == sendsize) { + idx++; + offset = 0; + } else + offset += res; + size -= res; + } + out: + conn->write_offset = (idx << PAGE_CACHE_SHIFT) + offset; + out_iov: + conn->write_size = size; + if ((saved_size == size) && res == -EAGAIN) + return res; + + return saved_size - size; + + err: + eprintk("error %d at %#Lx:%u\n", res, + (unsigned long long) conn->session->sid, conn->cid); + return res; +} + +static void exit_tx(struct iscsi_conn *conn, int res) +{ + if (res > 0) + return; + + switch (res) { + case -EAGAIN: + case -ERESTARTSYS: + break; + default: + eprintk("%d %d %d\n", conn->write_size, conn->write_state, res); + conn_close(conn); + break; + } +} + +static int tx_ddigest(struct iscsi_cmnd *cmnd, int state) +{ + int res, rest = cmnd->conn->write_size; + struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT}; + struct kvec iov; + + iov.iov_base = (char *) (&cmnd->ddigest) + (sizeof(u32) - rest); + iov.iov_len = rest; + + res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest); + + if (res > 0) { + cmnd->conn->write_size -= res; + if (!cmnd->conn->write_size) + cmnd->conn->write_state = state; + } else + exit_tx(cmnd->conn, res); + + return res; +} + +static void init_tx_hdigest(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iovec *iop; + + if (conn->hdigest_type & DIGEST_NONE) + return; + + digest_tx_header(cmnd); + + for (iop = conn->write_iop; iop->iov_len; iop++) + ; + iop->iov_base = &(cmnd->hdigest); + iop->iov_len = sizeof(u32); + conn->write_size += sizeof(u32); + iop++; + iop->iov_len = 0; + + return; +} + +enum tx_state { + TX_INIT, /* Must be zero. */ + TX_BHS_DATA, + TX_INIT_DDIGEST, + TX_DDIGEST, + TX_END, +}; + +static int do_send(struct iscsi_conn *conn, int state) +{ + int res; + + res = write_data(conn); + + if (res > 0) { + if (!conn->write_size) + conn->write_state = state; + } else + exit_tx(conn, res); + + return res; +} + +static int send(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd = conn->write_cmnd; + int ddigest, res = 0; + + ddigest = conn->ddigest_type != DIGEST_NONE ? 1 : 0; + + switch (conn->write_state) { + case TX_INIT: + assert(!cmnd); + cmnd = conn->write_cmnd = iscsi_get_send_cmnd(conn); + if (!cmnd) + return 0; + cmnd_tx_start(cmnd); + init_tx_hdigest(cmnd); + conn->write_state = TX_BHS_DATA; + case TX_BHS_DATA: + res = do_send(conn, ddigest && cmnd->pdu.datasize ? TX_INIT_DDIGEST : TX_END); + if (res <= 0 || conn->write_state != TX_INIT_DDIGEST) + break; + case TX_INIT_DDIGEST: + digest_tx_data(cmnd); + assert(!cmnd->conn->write_size); + cmnd->conn->write_size += sizeof(u32); + conn->write_state = TX_DDIGEST; + case TX_DDIGEST: + res = tx_ddigest(cmnd, TX_END); + break; + default: + eprintk("%d %d %x\n", res, conn->write_state, cmnd_opcode(cmnd)); + assert(0); + } + + if (res <= 0) + return res; + + if (conn->write_state != TX_END) + return res; + + if (conn->write_size) { + eprintk("%d %x %u\n", res, cmnd_opcode(cmnd), conn->write_size); + assert(!conn->write_size); + } + cmnd_tx_end(cmnd); + cmnd_release(cmnd, 0); + conn->write_cmnd = NULL; + conn->write_state = TX_INIT; + + return 0; +} + +static void process_io(struct iscsi_conn *conn) +{ + struct iscsi_target *target = conn->session->target; + int res, wakeup = 0; + + res = recv(conn); + + if (is_data_available(conn) > 0 || res > 0) + wakeup = 1; + + if (!test_bit(CONN_ACTIVE, &conn->state)) { + wakeup = 1; + goto out; + } + + res = send(conn); + + if (!list_empty(&conn->write_list) || conn->write_cmnd) + wakeup = 1; + +out: + if (wakeup) + nthread_wakeup(target); + + return; +} + +static void close_conn(struct iscsi_conn *conn) +{ + struct iscsi_session *session = conn->session; + struct iscsi_cmnd *cmnd; + + assert(conn); + + conn->sock->ops->shutdown(conn->sock, 2); + + write_lock_bh(&conn->sock->sk->sk_callback_lock); + conn->sock->sk->sk_state_change = session->target->nthread_info.old_state_change; + conn->sock->sk->sk_data_ready = session->target->nthread_info.old_data_ready; + write_unlock_bh(&conn->sock->sk->sk_callback_lock); + + fput(conn->file); + conn->file = NULL; + conn->sock = NULL; + + while (atomic_read(&conn->nr_busy_cmnds)) + yield(); + + while (!list_empty(&conn->pdu_list)) { + cmnd = list_entry(conn->pdu_list.next, struct iscsi_cmnd, conn_list); + + list_del_init(&cmnd->list); + cmnd_release(cmnd, 1); + } + + if (atomic_read(&conn->nr_cmnds)) { + eprintk("%u\n", atomic_read(&conn->nr_cmnds)); + list_for_each_entry(cmnd, &conn->pdu_list, conn_list) + eprintk("%x %x\n", cmnd_opcode(cmnd), cmnd_itt(cmnd)); + assert(0); + } + + event_send(session->target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0); + conn_free(conn); + + if (list_empty(&session->conn_list)) + session_del(session->target, session->sid); +} + +static int istd(void *arg) +{ + struct iscsi_target *target = arg; + struct network_thread_info *info = &target->nthread_info; + struct iscsi_conn *conn, *tmp; + + __set_current_state(TASK_RUNNING); + do { + spin_lock_bh(&info->nthread_lock); + __set_current_state(TASK_INTERRUPTIBLE); + + if (!test_bit(D_DATA_READY, &info->flags)) { + spin_unlock_bh(&info->nthread_lock); + schedule(); + spin_lock_bh(&info->nthread_lock); + } + __set_current_state(TASK_RUNNING); + clear_bit(D_DATA_READY, &info->flags); + spin_unlock_bh(&info->nthread_lock); + + target_lock(target, 0); + list_for_each_entry_safe(conn, tmp, &info->active_conns, poll_list) { + if (test_bit(CONN_ACTIVE, &conn->state)) + process_io(conn); + else + close_conn(conn); + } + target_unlock(target); + + } while (!kthread_should_stop()); + + return 0; +} + +int nthread_init(struct iscsi_target *target) +{ + struct network_thread_info *info = &target->nthread_info; + + info->flags = 0; + info->task = NULL; + + info->old_state_change = NULL; + info->old_data_ready = NULL; + + INIT_LIST_HEAD(&info->active_conns); + + spin_lock_init(&info->nthread_lock); + + return 0; +} + +int nthread_start(struct iscsi_target *target) +{ + int err = 0; + struct network_thread_info *info = &target->nthread_info; + struct task_struct *task; + + if (info->task) { + eprintk("Target (%u) already runs\n", target->tid); + return -EALREADY; + } + + task = kthread_run(istd, target, "istd%d", target->tid); + + if (IS_ERR(task)) + err = PTR_ERR(task); + else + info->task = task; + + return err; +} + +int nthread_stop(struct iscsi_target *target) +{ + int err; + struct network_thread_info *info = &target->nthread_info; + + if (!info->task) + return -ESRCH; + + err = kthread_stop(info->task); + + if (!err) + info->task = NULL; + + return err; +} --- linux-2.6.27.orig/ubuntu/iscsitarget/target.c +++ linux-2.6.27/ubuntu/iscsitarget/target.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include "iscsi.h" +#include "digest.h" +#include "iscsi_dbg.h" + +#define MAX_NR_TARGETS (1UL << 30) + +static LIST_HEAD(target_list); +static DECLARE_MUTEX(target_list_sem); +static u32 next_target_id; +static u32 nr_targets; + +static struct iscsi_sess_param default_session_param = { + .initial_r2t = 1, + .immediate_data = 1, + .max_connections = 1, + .max_recv_data_length = 8192, + .max_xmit_data_length = 8192, + .max_burst_length = 262144, + .first_burst_length = 65536, + .default_wait_time = 2, + .default_retain_time = 20, + .max_outstanding_r2t = 1, + .data_pdu_inorder = 1, + .data_sequence_inorder = 1, + .error_recovery_level = 0, + .header_digest = DIGEST_NONE, + .data_digest = DIGEST_NONE, + .ofmarker = 0, + .ifmarker = 0, + .ofmarkint = 2048, + .ifmarkint = 2048, +}; + +static struct iscsi_trgt_param default_target_param = { + .wthreads = DEFAULT_NR_WTHREADS, + .target_type = 0, + .queued_cmnds = DEFAULT_NR_QUEUED_CMNDS, +}; + +inline int target_lock(struct iscsi_target *target, int interruptible) +{ + int err = 0; + + if (interruptible) + err = down_interruptible(&target->target_sem); + else + down(&target->target_sem); + + return err; +} + +inline void target_unlock(struct iscsi_target *target) +{ + up(&target->target_sem); +} + +static struct iscsi_target *__target_lookup_by_id(u32 id) +{ + struct iscsi_target *target; + + list_for_each_entry(target, &target_list, t_list) { + if (target->tid == id) + return target; + } + return NULL; +} + +static struct iscsi_target *__target_lookup_by_name(char *name) +{ + struct iscsi_target *target; + + list_for_each_entry(target, &target_list, t_list) { + if (!strcmp(target->name, name)) + return target; + } + return NULL; +} + +struct iscsi_target *target_lookup_by_id(u32 id) +{ + struct iscsi_target *target; + + down(&target_list_sem); + target = __target_lookup_by_id(id); + up(&target_list_sem); + + return target; +} + +static int target_thread_start(struct iscsi_target *target) +{ + int err; + + if ((err = nthread_start(target)) < 0) + return err; + + if ((err = wthread_start(target)) < 0) { + nthread_stop(target); + } + + return err; +} + +static void target_thread_stop(struct iscsi_target *target) +{ + wthread_stop(target); + nthread_stop(target); +} + +static int iscsi_target_create(struct target_info *info, u32 tid) +{ + int err = -EINVAL, len; + char *name = info->name; + struct iscsi_target *target; + + dprintk(D_SETUP, "%u %s\n", tid, name); + + if (!(len = strlen(name))) { + eprintk("The length of the target name is zero %u\n", tid); + return err; + } + + if (!try_module_get(THIS_MODULE)) { + eprintk("Fail to get module %u\n", tid); + return err; + } + + target = kzalloc(sizeof(*target), GFP_KERNEL); + if (!target) { + err = -ENOMEM; + goto out; + } + + target->tid = info->tid = tid; + + memcpy(&target->sess_param, &default_session_param, sizeof(default_session_param)); + memcpy(&target->trgt_param, &default_target_param, sizeof(default_target_param)); + + strncpy(target->name, name, sizeof(target->name) - 1); + + init_MUTEX(&target->target_sem); + + INIT_LIST_HEAD(&target->session_list); + INIT_LIST_HEAD(&target->volumes); + + atomic_set(&target->nr_volumes, 0); + + list_add(&target->t_list, &target_list); + + nthread_init(target); + wthread_init(target); + + if ((err = target_thread_start(target)) < 0) { + target_thread_stop(target); + goto out; + } + + return 0; +out: + kfree(target); + module_put(THIS_MODULE); + + return err; +} + +int target_add(struct target_info *info) +{ + int err = -EEXIST; + u32 tid = info->tid; + + down(&target_list_sem); + + if (nr_targets > MAX_NR_TARGETS) { + err = -EBUSY; + goto out; + } + + if (__target_lookup_by_name(info->name)) + goto out; + + if (tid && __target_lookup_by_id(tid)) + goto out; + + if (!tid) { + do { + if (!++next_target_id) + ++next_target_id; + } while (__target_lookup_by_id(next_target_id)); + + tid = next_target_id; + } + + if (!(err = iscsi_target_create(info, tid))) + nr_targets++; +out: + up(&target_list_sem); + + return err; +} + +static void target_destroy(struct iscsi_target *target) +{ + dprintk(D_SETUP, "%u\n", target->tid); + + target_thread_stop(target); + + while (!list_empty(&target->volumes)) { + struct iet_volume *volume; + volume = list_entry(target->volumes.next, struct iet_volume, list); + volume->l_state = IDEV_DEL; + iscsi_volume_destroy(volume); + } + + kfree(target); + + module_put(THIS_MODULE); +} + +int target_del(u32 id) +{ + struct iscsi_target *target; + int err; + + if ((err = down_interruptible(&target_list_sem)) < 0) + return err; + + if (!(target = __target_lookup_by_id(id))) { + err = -ENOENT; + goto out; + } + + target_lock(target, 0); + + if (!list_empty(&target->session_list)) { + err = -EBUSY; + target_unlock(target); + goto out; + } + + list_del(&target->t_list); + nr_targets--; + + target_unlock(target); + up(&target_list_sem); + + target_destroy(target); + return 0; +out: + up(&target_list_sem); + return err; +} + +int iet_info_show(struct seq_file *seq, iet_show_info_t *func) +{ + int err; + struct iscsi_target *target; + + if ((err = down_interruptible(&target_list_sem)) < 0) + return err; + + list_for_each_entry(target, &target_list, t_list) { + seq_printf(seq, "tid:%u name:%s\n", target->tid, target->name); + + if ((err = target_lock(target, 1)) < 0) + break; + + func(seq, target); + + target_unlock(target); + } + + up(&target_list_sem); + + return 0; +} --- linux-2.6.27.orig/ubuntu/iscsitarget/tio.c +++ linux-2.6.27/ubuntu/iscsitarget/tio.c @@ -0,0 +1,121 @@ +/* + * Target I/O. + * (C) 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +static int tio_add_pages(struct tio *tio, int count) +{ + int i; + struct page *page; + + dprintk(D_GENERIC, "%p %d (%d)\n", tio, count, tio->pg_cnt); + + tio->pg_cnt = count; + + count *= sizeof(struct page *); + + do { + tio->pvec = kzalloc(count, GFP_KERNEL); + if (!tio->pvec) + yield(); + } while (!tio->pvec); + + for (i = 0; i < tio->pg_cnt; i++) { + do { + if (!(page = alloc_page(GFP_KERNEL))) + yield(); + } while (!page); + tio->pvec[i] = page; + } + return 0; +} + +static struct kmem_cache *tio_cache; + +struct tio *tio_alloc(int count) +{ + struct tio *tio; + + tio = kmem_cache_alloc(tio_cache, GFP_KERNEL | __GFP_NOFAIL); + + tio->pg_cnt = 0; + tio->idx = 0; + tio->offset = 0; + tio->size = 0; + tio->pvec = NULL; + + atomic_set(&tio->count, 1); + + if (count) + tio_add_pages(tio, count); + + return tio; +} + +static void tio_free(struct tio *tio) +{ + int i; + for (i = 0; i < tio->pg_cnt; i++) { + assert(tio->pvec[i]); + __free_page(tio->pvec[i]); + } + kfree(tio->pvec); + kmem_cache_free(tio_cache, tio); +} + +void tio_put(struct tio *tio) +{ + assert(atomic_read(&tio->count)); + if (atomic_dec_and_test(&tio->count)) + tio_free(tio); +} + +void tio_get(struct tio *tio) +{ + atomic_inc(&tio->count); +} + +void tio_set(struct tio *tio, u32 size, loff_t offset) +{ + tio->idx = offset >> PAGE_CACHE_SHIFT; + tio->offset = offset & ~PAGE_CACHE_MASK; + tio->size = size; +} + +int tio_read(struct iet_volume *lu, struct tio *tio) +{ + struct iotype *iot = lu->iotype; + assert(iot); + return iot->make_request ? iot->make_request(lu, tio, READ) : 0; +} + +int tio_write(struct iet_volume *lu, struct tio *tio) +{ + struct iotype *iot = lu->iotype; + assert(iot); + return iot->make_request ? iot->make_request(lu, tio, WRITE) : 0; +} + +int tio_sync(struct iet_volume *lu, struct tio *tio) +{ + struct iotype *iot = lu->iotype; + assert(iot); + return iot->sync ? iot->sync(lu, tio) : 0; +} + +int tio_init(void) +{ + tio_cache = KMEM_CACHE(tio, 0); + return tio_cache ? 0 : -ENOMEM; +} + +void tio_exit(void) +{ + if (tio_cache) + kmem_cache_destroy(tio_cache); +} --- linux-2.6.27.orig/ubuntu/iscsitarget/null-io.c +++ linux-2.6.27/ubuntu/iscsitarget/null-io.c @@ -0,0 +1,113 @@ +/* + * Target device null I/O. + * (C) 2005 MING Zhang + * This code is licenced under the GPL. + * + * The nullio mode will not return any meaningful or previous written + * data. It is only for performance measurement purpose. + */ + +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +struct nullio_data { + u64 sectors; +}; + +enum { + Opt_sectors, Opt_ignore, Opt_err, +}; + +static match_table_t tokens = { + {Opt_sectors, "Sectors=%u"}, + {Opt_ignore, "Type=%s"}, + {Opt_err, NULL}, +}; + +static int parse_nullio_params(struct iet_volume *volume, char *params) +{ + int err = 0; + char *p, *q; + struct nullio_data *data = volume->private; + + while ((p = strsep(¶ms, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + if (!*p) + continue; + token = match_token(p, tokens, args); + switch (token) { + case Opt_sectors: + q = match_strdup(&args[0]); + if (!q) + return -ENOMEM; + data->sectors = simple_strtoull(q, NULL, 10); + kfree(q); + break; + case Opt_ignore: + break; + default: + eprintk("Unknown %s\n", p); + return -EINVAL; + break; + } + } + return err; +} + +static void nullio_detach(struct iet_volume *lu) +{ + struct nullio_data *p = lu->private; + + kfree(p); + lu->private = NULL; +} + +static int nullio_attach(struct iet_volume *lu, char *args) +{ + int err = 0; + struct nullio_data *p; + + if (lu->private) { + printk("already attached ? %d\n", lu->lun); + return -EBUSY; + } + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + lu->private = p; + + if ((err = parse_nullio_params(lu, args)) < 0) { + eprintk("%d\n", err); + goto out; + } + + lu->blk_shift = SECTOR_SIZE_BITS; + lu->blk_cnt = (p->sectors = p->sectors ? : 1 << 27); /* 64 GB */ + +out: + if (err < 0) + nullio_detach(lu); + return err; +} + +void nullio_show(struct iet_volume *lu, struct seq_file *seq) +{ + struct nullio_data *p = lu->private; + seq_printf(seq, " sectors:%llu\n", p->sectors); +} + +struct iotype nullio = +{ + .name = "nullio", + .attach = nullio_attach, + .detach = nullio_detach, + .show = nullio_show, +}; --- linux-2.6.27.orig/ubuntu/iscsitarget/Kconfig +++ linux-2.6.27/ubuntu/iscsitarget/Kconfig @@ -0,0 +1,3 @@ +config SCSI_ISCSITARGET + tristate "iSCSI Target Driver" + depends on SCSI --- linux-2.6.27.orig/ubuntu/iscsitarget/iscsi.c +++ linux-2.6.27/ubuntu/iscsitarget/iscsi.c @@ -0,0 +1,1787 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +unsigned long debug_enable_flags; + +static struct kmem_cache *iscsi_cmnd_cache; +static char dummy_data[1024]; + +static int ctr_major; +static char ctr_name[] = "ietctl"; +extern struct file_operations ctr_fops; + +static u32 cmnd_write_size(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); + + if (hdr->flags & ISCSI_CMD_WRITE) + return be32_to_cpu(hdr->data_length); + return 0; +} + +static u32 cmnd_read_size(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); + + if (hdr->flags & ISCSI_CMD_READ) { + struct iscsi_rlength_ahdr *ahdr = + (struct iscsi_rlength_ahdr *)cmnd->pdu.ahs; + + if (!(hdr->flags & ISCSI_CMD_WRITE)) + return be32_to_cpu(hdr->data_length); + if (ahdr && ahdr->ahstype == ISCSI_AHSTYPE_RLENGTH) + return be32_to_cpu(ahdr->read_length); + } + return 0; +} + +static void iscsi_device_queue_cmnd(struct iscsi_cmnd *cmnd) +{ + set_cmnd_waitio(cmnd); + wthread_queue(cmnd); +} + +static void iscsi_scsi_queuecmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_queue *queue = &cmnd->lun->queue; + + dprintk(D_GENERIC, "%p\n", cmnd); + + if ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_UNTAGGED && + (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_SIMPLE) { + cmnd->pdu.bhs.flags &= ~ISCSI_CMD_ATTR_MASK; + cmnd->pdu.bhs.flags |= ISCSI_CMD_UNTAGGED; + } + + spin_lock(&queue->queue_lock); + + set_cmnd_queued(cmnd); + + switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) { + case ISCSI_CMD_UNTAGGED: + case ISCSI_CMD_SIMPLE: + if (!list_empty(&queue->wait_list) || queue->ordered_cmnd) + goto pending; + queue->active_cnt++; + break; + + default: + BUG(); + } + spin_unlock(&queue->queue_lock); + + iscsi_device_queue_cmnd(cmnd); + return; + pending: + assert(list_empty(&cmnd->list)); + + list_add_tail(&cmnd->list, &queue->wait_list); + spin_unlock(&queue->queue_lock); + return; +} + +static void iscsi_scsi_dequeuecmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_queue *queue; + + if (!cmnd->lun) + return; + queue = &cmnd->lun->queue; + spin_lock(&queue->queue_lock); + switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) { + case ISCSI_CMD_UNTAGGED: + case ISCSI_CMD_SIMPLE: + --queue->active_cnt; + break; + case ISCSI_CMD_ORDERED: + case ISCSI_CMD_HEAD_OF_QUEUE: + case ISCSI_CMD_ACA: + BUG(); + default: + /* Should the iscsi_scsi_queuecmnd func reject this ? */ + break; + } + + while (!list_empty(&queue->wait_list)) { + cmnd = list_entry(queue->wait_list.next, struct iscsi_cmnd, list); + switch ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK)) { + case ISCSI_CMD_UNTAGGED: + case ISCSI_CMD_SIMPLE: + list_del_init(&cmnd->list); + queue->active_cnt++; + iscsi_device_queue_cmnd(cmnd); + break; + case ISCSI_CMD_ORDERED: + case ISCSI_CMD_HEAD_OF_QUEUE: + case ISCSI_CMD_ACA: + BUG(); + } + } + + spin_unlock(&queue->queue_lock); + + return; +} + +/** + * create a new command. + * + * iscsi_cmnd_create - + * @conn: ptr to connection (for i/o) + * + * @return ptr to command or NULL + */ + +struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *conn, int req) +{ + struct iscsi_cmnd *cmnd; + + /* TODO: async interface is necessary ? */ + cmnd = kmem_cache_alloc(iscsi_cmnd_cache, GFP_KERNEL|__GFP_NOFAIL); + + memset(cmnd, 0, sizeof(*cmnd)); + INIT_LIST_HEAD(&cmnd->list); + INIT_LIST_HEAD(&cmnd->pdu_list); + INIT_LIST_HEAD(&cmnd->conn_list); + INIT_LIST_HEAD(&cmnd->hash_list); + cmnd->conn = conn; + spin_lock(&conn->list_lock); + atomic_inc(&conn->nr_cmnds); + if (req) + list_add_tail(&cmnd->conn_list, &conn->pdu_list); + spin_unlock(&conn->list_lock); + cmnd->tio = NULL; + + dprintk(D_GENERIC, "%p:%p\n", conn, cmnd); + + return cmnd; +} + +/** + * create a new command used as response. + * + * iscsi_cmnd_create_rsp_cmnd - + * @cmnd: ptr to request command + * + * @return ptr to response command or NULL + */ + +static struct iscsi_cmnd *iscsi_cmnd_create_rsp_cmnd(struct iscsi_cmnd *cmnd, int final) +{ + struct iscsi_cmnd *rsp = cmnd_alloc(cmnd->conn, 0); + + if (final) + set_cmnd_final(rsp); + list_add_tail(&rsp->pdu_list, &cmnd->pdu_list); + rsp->req = cmnd; + return rsp; +} + +static struct iscsi_cmnd *get_rsp_cmnd(struct iscsi_cmnd *req) +{ + return list_entry(req->pdu_list.prev, struct iscsi_cmnd, pdu_list); +} + +static void iscsi_cmnds_init_write(struct list_head *send) +{ + struct iscsi_cmnd *cmnd = list_entry(send->next, struct iscsi_cmnd, list); + struct iscsi_conn *conn = cmnd->conn; + struct list_head *pos, *next; + + spin_lock(&conn->list_lock); + + list_for_each_safe(pos, next, send) { + cmnd = list_entry(pos, struct iscsi_cmnd, list); + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + + list_del_init(&cmnd->list); + assert(conn == cmnd->conn); + list_add_tail(&cmnd->list, &conn->write_list); + } + + spin_unlock(&conn->list_lock); + + nthread_wakeup(conn->session->target); +} + +static void iscsi_cmnd_init_write(struct iscsi_cmnd *cmnd) +{ + LIST_HEAD(head); + + if (!list_empty(&cmnd->list)) { + eprintk("%x %x %x %x %lx %u %u %u %u %u %u %u %d %d\n", + cmnd_itt(cmnd), cmnd_ttt(cmnd), cmnd_opcode(cmnd), + cmnd_scsicode(cmnd), cmnd->flags, cmnd->r2t_sn, + cmnd->r2t_length, cmnd->is_unsolicited_data, + cmnd->target_task_tag, cmnd->outstanding_r2t, + cmnd->hdigest, cmnd->ddigest, + list_empty(&cmnd->pdu_list), list_empty(&cmnd->hash_list)); + + assert(list_empty(&cmnd->list)); + } + list_add(&cmnd->list, &head); + iscsi_cmnds_init_write(&head); +} + +static void do_send_data_rsp(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iscsi_cmnd *data_cmnd; + struct tio *tio = cmnd->tio; + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct iscsi_data_in_hdr *rsp; + u32 pdusize, expsize, scsisize, size, offset, sn; + LIST_HEAD(send); + + dprintk(D_GENERIC, "%p\n", cmnd); + pdusize = conn->session->param.max_xmit_data_length; + expsize = cmnd_read_size(cmnd); + size = min(expsize, tio->size); + offset = 0; + sn = 0; + + while (1) { + data_cmnd = iscsi_cmnd_create_rsp_cmnd(cmnd, size <= pdusize); + tio_get(tio); + data_cmnd->tio = tio; + rsp = (struct iscsi_data_in_hdr *)&data_cmnd->pdu.bhs; + + rsp->opcode = ISCSI_OP_SCSI_DATA_IN; + rsp->itt = req->itt; + rsp->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); + rsp->buffer_offset = offset; + rsp->data_sn = cpu_to_be32(sn); + + if (size <= pdusize) { + data_cmnd->pdu.datasize = size; + rsp->flags = ISCSI_FLG_FINAL | ISCSI_FLG_STATUS; + + scsisize = tio->size; + if (scsisize < expsize) { + rsp->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + size = expsize - scsisize; + } else if (scsisize > expsize) { + rsp->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW; + size = scsisize - expsize; + } else + size = 0; + rsp->residual_count = cpu_to_be32(size); + list_add_tail(&data_cmnd->list, &send); + + break; + } + + data_cmnd->pdu.datasize = pdusize; + + size -= pdusize; + offset += pdusize; + sn++; + + list_add_tail(&data_cmnd->list, &send); + } + + iscsi_cmnds_init_write(&send); +} + +static struct iscsi_cmnd *create_scsi_rsp(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req); + struct iscsi_scsi_rsp_hdr *rsp_hdr; + + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + + rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_SCSI_RSP; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->response = ISCSI_RESPONSE_COMMAND_COMPLETED; + rsp_hdr->cmd_status = SAM_STAT_GOOD; + rsp_hdr->itt = req_hdr->itt; + + return rsp; +} + +static struct iscsi_cmnd *create_sense_rsp(struct iscsi_cmnd *req, + u8 sense_key, u8 asc, u8 ascq) +{ + struct iscsi_cmnd *rsp; + struct iscsi_scsi_rsp_hdr *rsp_hdr; + struct tio *tio; + struct iscsi_sense_data *sense; + + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + + rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_SCSI_RSP; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->response = ISCSI_RESPONSE_COMMAND_COMPLETED; + rsp_hdr->cmd_status = SAM_STAT_CHECK_CONDITION; + rsp_hdr->itt = cmnd_hdr(req)->itt; + + tio = rsp->tio = tio_alloc(1); + sense = (struct iscsi_sense_data *) page_address(tio->pvec[0]); + assert(sense); + clear_page(sense); + sense->length = cpu_to_be16(14); + sense->data[0] = 0xf0; + sense->data[2] = sense_key; + sense->data[7] = 6; // Additional sense length + sense->data[12] = asc; + sense->data[13] = ascq; + + rsp->pdu.datasize = sizeof(struct iscsi_sense_data) + 14; + tio->size = (rsp->pdu.datasize + 3) & -4; + tio->offset = 0; + + return rsp; +} + +void send_scsi_rsp(struct iscsi_cmnd *req, int (*func)(struct iscsi_cmnd *)) +{ + struct iscsi_cmnd *rsp; + struct iscsi_scsi_rsp_hdr *rsp_hdr; + u32 size; + int ret = func(req); + + switch (ret) { + case 0: + case -EBUSY: + rsp = create_scsi_rsp(req); + rsp_hdr = (struct iscsi_scsi_rsp_hdr *) &rsp->pdu.bhs; + if ((size = cmnd_read_size(req)) != 0) { + rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + rsp_hdr->residual_count = cpu_to_be32(size); + } + if (ret == -EBUSY) + rsp_hdr->cmd_status = SAM_STAT_RESERVATION_CONFLICT; + break; + case -EIO: + /* Medium Error/Write Fault */ + rsp = create_sense_rsp(req, MEDIUM_ERROR, 0x03, 0x0); + break; + default: + rsp = create_sense_rsp(req, ILLEGAL_REQUEST, 0x24, 0x0); + } + iscsi_cmnd_init_write(rsp); +} + +void send_data_rsp(struct iscsi_cmnd *req, int (*func)(struct iscsi_cmnd *)) +{ + struct iscsi_cmnd *rsp; + + switch (func(req)) { + case 0: + do_send_data_rsp(req); + return; + case -EIO: + /* Medium Error/Unrecovered Read Error */ + rsp = create_sense_rsp(req, MEDIUM_ERROR, 0x11, 0x0); + break; + default: + rsp = create_sense_rsp(req, ILLEGAL_REQUEST, 0x24, 0x0); + } + iscsi_cmnd_init_write(rsp); +} + +/** + * Free a command. + * Also frees the additional header. + * + * iscsi_cmnd_remove - + * @cmnd: ptr to command + */ + +static void iscsi_cmnd_remove(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn; + + if (!cmnd) + return; + dprintk(D_GENERIC, "%p\n", cmnd); + conn = cmnd->conn; + kfree(cmnd->pdu.ahs); + + if (!list_empty(&cmnd->list)) { + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + + eprintk("cmnd %p still on some list?, %x, %x, %x, %x, %x, %x, %x %lx\n", + cmnd, req->opcode, req->scb[0], req->flags, req->itt, + be32_to_cpu(req->data_length), + req->cmd_sn, be32_to_cpu(cmnd->pdu.datasize), + conn->state); + + if (cmnd->req) { + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd->req); + eprintk("%p %x %u\n", req, req->opcode, req->scb[0]); + } + dump_stack(); + BUG(); + } + list_del(&cmnd->list); + spin_lock(&conn->list_lock); + atomic_dec(&conn->nr_cmnds); + list_del(&cmnd->conn_list); + spin_unlock(&conn->list_lock); + + if (cmnd->tio) + tio_put(cmnd->tio); + + kmem_cache_free(iscsi_cmnd_cache, cmnd); +} + +static void cmnd_skip_pdu(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct tio *tio = cmnd->tio; + char *addr; + u32 size; + int i; + + eprintk("%x %x %x %u\n", cmnd_itt(cmnd), cmnd_opcode(cmnd), + cmnd_hdr(cmnd)->scb[0], cmnd->pdu.datasize); + + if (!(size = cmnd->pdu.datasize)) + return; + + if (tio) + assert(tio->pg_cnt > 0); + else + tio = cmnd->tio = tio_alloc(1); + + addr = page_address(tio->pvec[0]); + assert(addr); + size = (size + 3) & -4; + conn->read_size = size; + for (i = 0; size > PAGE_CACHE_SIZE; i++, size -= PAGE_CACHE_SIZE) { + assert(i < ISCSI_CONN_IOV_MAX); + conn->read_iov[i].iov_base = addr; + conn->read_iov[i].iov_len = PAGE_CACHE_SIZE; + } + conn->read_iov[i].iov_base = addr; + conn->read_iov[i].iov_len = size; + conn->read_msg.msg_iov = conn->read_iov; + conn->read_msg.msg_iovlen = ++i; +} + +static void iscsi_cmnd_reject(struct iscsi_cmnd *req, int reason) +{ + struct iscsi_cmnd *rsp; + struct iscsi_reject_hdr *rsp_hdr; + struct tio *tio; + char *addr; + + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + rsp_hdr = (struct iscsi_reject_hdr *)&rsp->pdu.bhs; + + rsp_hdr->opcode = ISCSI_OP_REJECT; + rsp_hdr->ffffffff = ISCSI_RESERVED_TAG; + rsp_hdr->reason = reason; + + rsp->tio = tio = tio_alloc(1); + addr = page_address(tio->pvec[0]); + clear_page(addr); + memcpy(addr, &req->pdu.bhs, sizeof(struct iscsi_hdr)); + tio->size = rsp->pdu.datasize = sizeof(struct iscsi_hdr); + cmnd_skip_pdu(req); + + req->pdu.bhs.opcode = ISCSI_OP_PDU_REJECT; +} + +static void cmnd_set_sn(struct iscsi_cmnd *cmnd, int set_stat_sn) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iscsi_session *sess = conn->session; + + if (set_stat_sn) + cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn++); + cmnd->pdu.bhs.exp_sn = cpu_to_be32(sess->exp_cmd_sn); + cmnd->pdu.bhs.max_sn = cpu_to_be32(sess->exp_cmd_sn + sess->max_queued_cmnds); +} + +static void update_stat_sn(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + u32 exp_stat_sn; + + cmnd->pdu.bhs.exp_sn = exp_stat_sn = be32_to_cpu(cmnd->pdu.bhs.exp_sn); + dprintk(D_GENERIC, "%x,%x\n", cmnd_opcode(cmnd), exp_stat_sn); + if ((int)(exp_stat_sn - conn->exp_stat_sn) > 0 && + (int)(exp_stat_sn - conn->stat_sn) <= 0) { + // free pdu resources + cmnd->conn->exp_stat_sn = exp_stat_sn; + } +} + +static int check_cmd_sn(struct iscsi_cmnd *cmnd) +{ + struct iscsi_session *session = cmnd->conn->session; + u32 cmd_sn; + + cmnd->pdu.bhs.sn = cmd_sn = be32_to_cpu(cmnd->pdu.bhs.sn); + dprintk(D_GENERIC, "%d(%d)\n", cmd_sn, session->exp_cmd_sn); + if ((s32)(cmd_sn - session->exp_cmd_sn) >= 0) + return 0; + eprintk("sequence error (%x,%x)\n", cmd_sn, session->exp_cmd_sn); + return -ISCSI_REASON_PROTOCOL_ERROR; +} + +static struct iscsi_cmnd *__cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt) +{ + struct list_head *head; + struct iscsi_cmnd *cmnd; + + head = &session->cmnd_hash[cmnd_hashfn(itt)]; + + list_for_each_entry(cmnd, head, hash_list) { + if (cmnd->pdu.bhs.itt == itt) { + if ((ttt != ISCSI_RESERVED_TAG) && (ttt != cmnd->target_task_tag)) + continue; + return cmnd; + } + } + + return NULL; +} + +static struct iscsi_cmnd *cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt) +{ + struct iscsi_cmnd *cmnd; + + spin_lock(&session->cmnd_hash_lock); + + cmnd = __cmnd_find_hash(session, itt, ttt); + + spin_unlock(&session->cmnd_hash_lock); + + return cmnd; +} + +static int cmnd_insert_hash(struct iscsi_cmnd *cmnd) +{ + struct iscsi_session *session = cmnd->conn->session; + struct iscsi_cmnd *tmp; + struct list_head *head; + int err = 0; + u32 itt = cmnd->pdu.bhs.itt; + + dprintk(D_GENERIC, "%p:%x\n", cmnd, itt); + if (itt == ISCSI_RESERVED_TAG) { + err = -ISCSI_REASON_PROTOCOL_ERROR; + goto out; + } + + head = &session->cmnd_hash[cmnd_hashfn(cmnd->pdu.bhs.itt)]; + + spin_lock(&session->cmnd_hash_lock); + + tmp = __cmnd_find_hash(session, itt, ISCSI_RESERVED_TAG); + if (!tmp) { + list_add_tail(&cmnd->hash_list, head); + set_cmnd_hashed(cmnd); + } else + err = -ISCSI_REASON_TASK_IN_PROGRESS; + + spin_unlock(&session->cmnd_hash_lock); + + if (!err) { + update_stat_sn(cmnd); + err = check_cmd_sn(cmnd); + } + +out: + return err; +} + +static void __cmnd_remove_hash(struct iscsi_cmnd *cmnd) +{ + list_del(&cmnd->hash_list); +} + +static void cmnd_remove_hash(struct iscsi_cmnd *cmnd) +{ + struct iscsi_session *session = cmnd->conn->session; + struct iscsi_cmnd *tmp; + + spin_lock(&session->cmnd_hash_lock); + + tmp = __cmnd_find_hash(session, cmnd->pdu.bhs.itt, ISCSI_RESERVED_TAG); + + if (tmp && tmp == cmnd) + __cmnd_remove_hash(tmp); + else + eprintk("%p:%x not found\n", cmnd, cmnd_itt(cmnd)); + + spin_unlock(&session->cmnd_hash_lock); +} + +static void cmnd_skip_data(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + struct iscsi_scsi_rsp_hdr *rsp_hdr; + u32 size; + + rsp = get_rsp_cmnd(req); + rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs; + if (cmnd_opcode(rsp) != ISCSI_OP_SCSI_RSP) { + eprintk("unexpected response command %u\n", cmnd_opcode(rsp)); + return; + } + + size = cmnd_write_size(req); + if (size) { + rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + rsp_hdr->residual_count = cpu_to_be32(size); + } + size = cmnd_read_size(req); + if (size) { + if (cmnd_hdr(req)->flags & ISCSI_CMD_WRITE) { + rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW; + rsp_hdr->bi_residual_count = cpu_to_be32(size); + } else { + rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + rsp_hdr->residual_count = cpu_to_be32(size); + } + } + req->pdu.bhs.opcode = + (req->pdu.bhs.opcode & ~ISCSI_OPCODE_MASK) | ISCSI_OP_SCSI_REJECT; + + cmnd_skip_pdu(req); +} + +static int cmnd_recv_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size) +{ + int idx, i; + char *addr; + + dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size); + offset += tio->offset; + + if (!(offset < tio->offset + tio->size) || + !(offset + size <= tio->offset + tio->size)) { + eprintk("%u %u %u %u", offset, size, tio->offset, tio->size); + return -EIO; + } + assert(offset < tio->offset + tio->size); + assert(offset + size <= tio->offset + tio->size); + + idx = offset >> PAGE_CACHE_SHIFT; + offset &= ~PAGE_CACHE_MASK; + + conn->read_msg.msg_iov = conn->read_iov; + conn->read_size = size = (size + 3) & -4; + conn->read_overflow = 0; + + i = 0; + while (1) { + assert(tio->pvec[idx]); + addr = page_address(tio->pvec[idx]); + assert(addr); + conn->read_iov[i].iov_base = addr + offset; + if (offset + size <= PAGE_CACHE_SIZE) { + conn->read_iov[i].iov_len = size; + conn->read_msg.msg_iovlen = ++i; + break; + } + conn->read_iov[i].iov_len = PAGE_CACHE_SIZE - offset; + size -= conn->read_iov[i].iov_len; + offset = 0; + if (++i >= ISCSI_CONN_IOV_MAX) { + conn->read_msg.msg_iovlen = i; + conn->read_overflow = size; + conn->read_size -= size; + break; + } + + idx++; + } + + return 0; +} + +static void set_offset_and_length(struct iet_volume *lu, u8 *cmd, loff_t *off, u32 *len) +{ + assert(lu); + + switch (cmd[0]) { + case READ_6: + case WRITE_6: + *off = ((cmd[1] & 0x1f) << 16) + (cmd[2] << 8) + cmd[3]; + *len = cmd[4]; + if (!*len) + *len = 256; + break; + case READ_10: + case WRITE_10: + case WRITE_VERIFY: + *off = (u32)cmd[2] << 24 | (u32)cmd[3] << 16 | + (u32)cmd[4] << 8 | (u32)cmd[5]; + *len = (cmd[7] << 8) + cmd[8]; + break; + case READ_16: + case WRITE_16: + *off = (u64)cmd[2] << 56 | (u64)cmd[3] << 48 | + (u64)cmd[4] << 40 | (u64)cmd[5] << 32 | + (u64)cmd[6] << 24 | (u64)cmd[7] << 16 | + (u64)cmd[8] << 8 | (u64)cmd[9]; + *len = (u32)cmd[10] << 24 | (u32)cmd[11] << 16 | + (u32)cmd[12] << 8 | (u32)cmd[13]; + break; + default: + BUG(); + } + + *off <<= lu->blk_shift; + *len <<= lu->blk_shift; +} + +static u32 translate_lun(u16 * data) +{ + u8 *p = (u8 *) data; + u32 lun = ~0U; + + switch (*p >> 6) { + case 0: + lun = p[1]; + break; + case 1: + lun = (0x3f & p[0]) << 8 | p[1]; + break; + case 2: + case 3: + default: + eprintk("%u %u %u %u\n", data[0], data[1], data[2], data[3]); + break; + } + + return lun; +} + +static void send_r2t(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + struct iscsi_r2t_hdr *rsp_hdr; + u32 length, offset, burst; + LIST_HEAD(send); + + length = req->r2t_length; + burst = req->conn->session->param.max_burst_length; + offset = be32_to_cpu(cmnd_hdr(req)->data_length) - length; + + do { + rsp = iscsi_cmnd_create_rsp_cmnd(req, 0); + rsp->pdu.bhs.ttt = req->target_task_tag; + + rsp_hdr = (struct iscsi_r2t_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_R2T; + rsp_hdr->flags = ISCSI_FLG_FINAL; + memcpy(rsp_hdr->lun, cmnd_hdr(req)->lun, 8); + rsp_hdr->itt = cmnd_hdr(req)->itt; + rsp_hdr->r2t_sn = cpu_to_be32(req->r2t_sn++); + rsp_hdr->buffer_offset = cpu_to_be32(offset); + if (length > burst) { + rsp_hdr->data_length = cpu_to_be32(burst); + length -= burst; + offset += burst; + } else { + rsp_hdr->data_length = cpu_to_be32(length); + length = 0; + } + + dprintk(D_WRITE, "%x %u %u %u %u\n", cmnd_itt(req), + be32_to_cpu(rsp_hdr->data_length), + be32_to_cpu(rsp_hdr->buffer_offset), + be32_to_cpu(rsp_hdr->r2t_sn), req->outstanding_r2t); + + list_add_tail(&rsp->list, &send); + + if (++req->outstanding_r2t >= req->conn->session->param.max_outstanding_r2t) + break; + + } while (length); + + iscsi_cmnds_init_write(&send); +} + +static void scsi_cmnd_exec(struct iscsi_cmnd *cmnd) +{ + if (cmnd->r2t_length) { + if (!cmnd->is_unsolicited_data) + send_r2t(cmnd); + } else { + if (cmnd->lun) { + iscsi_scsi_queuecmnd(cmnd); + } else { + iscsi_device_queue_cmnd(cmnd); + } + } +} + +static int noop_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + u32 size, tmp; + int i, err = 0; + + if (cmnd_ttt(cmnd) != cpu_to_be32(ISCSI_RESERVED_TAG)) { + /* + * We don't request a NOP-Out by sending a NOP-In. + * See 10.18.2 in the draft 20. + */ + eprintk("initiator bug %x\n", cmnd_itt(cmnd)); + err = -ISCSI_REASON_PROTOCOL_ERROR; + goto out; + } + + if (cmnd_itt(cmnd) == cpu_to_be32(ISCSI_RESERVED_TAG)) { + if (!(cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE)) + eprintk("%s\n","initiator bug!"); + update_stat_sn(cmnd); + err = check_cmd_sn(cmnd); + if (err) + goto out; + } else if ((err = cmnd_insert_hash(cmnd)) < 0) { + eprintk("ignore this request %x\n", cmnd_itt(cmnd)); + goto out; + } + + if ((size = cmnd->pdu.datasize)) { + size = (size + 3) & -4; + conn->read_msg.msg_iov = conn->read_iov; + if (cmnd->pdu.bhs.itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + struct tio *tio; + int pg_cnt = get_pgcnt(size, 0); + + assert(pg_cnt < ISCSI_CONN_IOV_MAX); + cmnd->tio = tio = tio_alloc(pg_cnt); + tio_set(tio, size, 0); + + for (i = 0; i < pg_cnt; i++) { + conn->read_iov[i].iov_base + = page_address(tio->pvec[i]); + tmp = min_t(u32, size, PAGE_CACHE_SIZE); + conn->read_iov[i].iov_len = tmp; + conn->read_size += tmp; + size -= tmp; + } + } else { + for (i = 0; i < ISCSI_CONN_IOV_MAX; i++) { + conn->read_iov[i].iov_base = dummy_data; + tmp = min_t(u32, size, sizeof(dummy_data)); + conn->read_iov[i].iov_len = tmp; + conn->read_size += tmp; + size -= tmp; + } + } + assert(!size); + conn->read_overflow = size; + conn->read_msg.msg_iovlen = i; + } + +out: + return err; +} + +static u32 get_next_ttt(struct iscsi_session *session) +{ + u32 ttt; + + if (session->next_ttt == ISCSI_RESERVED_TAG) + session->next_ttt++; + ttt = session->next_ttt++; + + return cpu_to_be32(ttt); +} + +static void scsi_cmnd_start(struct iscsi_conn *conn, struct iscsi_cmnd *req) +{ + struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req); + + dprintk(D_GENERIC, "scsi command: %02x\n", req_hdr->scb[0]); + + req->lun = volume_get(conn->session->target, translate_lun(req_hdr->lun)); + if (!req->lun) { + switch (req_hdr->scb[0]) { + case INQUIRY: + case REPORT_LUNS: + break; + default: + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + create_sense_rsp(req, ILLEGAL_REQUEST, 0x25, 0x0); + cmnd_skip_data(req); + goto out; + } + } else + set_cmnd_lunit(req); + + switch (req_hdr->scb[0]) { + case SERVICE_ACTION_IN: + if ((req_hdr->scb[1] & 0x1f) != 0x10) + goto error; + case INQUIRY: + case REPORT_LUNS: + case TEST_UNIT_READY: + case SYNCHRONIZE_CACHE: + case VERIFY: + case VERIFY_16: + case START_STOP: + case READ_CAPACITY: + case MODE_SENSE: + case REQUEST_SENSE: + case RESERVE: + case RELEASE: + { + if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) { + /* unexpected unsolicited data */ + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc); + cmnd_skip_data(req); + } + break; + } + case READ_6: + case READ_10: + case READ_16: + { + loff_t offset; + u32 length; + + if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) { + /* unexpected unsolicited data */ + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc); + cmnd_skip_data(req); + break; + } + + set_offset_and_length(req->lun, req_hdr->scb, &offset, &length); + req->tio = tio_alloc(get_pgcnt(length, offset)); + tio_set(req->tio, length, offset); + break; + } + case WRITE_6: + case WRITE_10: + case WRITE_16: + case WRITE_VERIFY: + { + struct iscsi_sess_param *param = &conn->session->param; + loff_t offset; + u32 length; + + req->r2t_length = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize; + req->is_unsolicited_data = !(req_hdr->flags & ISCSI_CMD_FINAL); + req->target_task_tag = get_next_ttt(conn->session); + + if (LUReadonly(req->lun)) { + create_sense_rsp(req, DATA_PROTECT, 0x27, 0x0); + cmnd_skip_data(req); + break; + } + + if (!param->immediate_data && req->pdu.datasize) + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + + if (param->initial_r2t && !(req_hdr->flags & ISCSI_CMD_FINAL)) + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + + if (req_hdr->scb[0] == WRITE_VERIFY && req_hdr->scb[1] & 0x02) + eprintk("Verification is ignored %x\n", cmnd_itt(req)); + + set_offset_and_length(req->lun, req_hdr->scb, &offset, &length); + if (cmnd_write_size(req) != length) + eprintk("%x %u %u\n", cmnd_itt(req), cmnd_write_size(req), length); + + req->tio = tio_alloc(get_pgcnt(length, offset)); + tio_set(req->tio, length, offset); + + if (req->pdu.datasize) { + if (cmnd_recv_pdu(conn, req->tio, 0, req->pdu.datasize) < 0) + assert(0); + } + break; + } + error: + default: + eprintk("Unsupported %x\n", req_hdr->scb[0]); + create_sense_rsp(req, ILLEGAL_REQUEST, 0x20, 0x0); + cmnd_skip_data(req); + break; + } + +out: + return; +} + +static void data_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs; + struct iscsi_cmnd *scsi_cmnd = NULL; + u32 offset = be32_to_cpu(req->buffer_offset); + + update_stat_sn(cmnd); + + cmnd->req = scsi_cmnd = cmnd_find_hash(conn->session, req->itt, req->ttt); + if (!scsi_cmnd) { + eprintk("unable to find scsi task %x %x\n", + cmnd_itt(cmnd), cmnd_ttt(cmnd)); + goto skip_data; + } + + if (scsi_cmnd->r2t_length < cmnd->pdu.datasize) { + eprintk("invalid data len %x %u %u\n", + cmnd_itt(scsi_cmnd), cmnd->pdu.datasize, scsi_cmnd->r2t_length); + goto skip_data; + } + + if (scsi_cmnd->r2t_length + offset != cmnd_write_size(scsi_cmnd)) { + eprintk("%x %u %u %u\n", cmnd_itt(scsi_cmnd), scsi_cmnd->r2t_length, + offset, cmnd_write_size(scsi_cmnd)); + goto skip_data; + } + + scsi_cmnd->r2t_length -= cmnd->pdu.datasize; + + if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + /* unsolicited burst data */ + if (scsi_cmnd->pdu.bhs.flags & ISCSI_FLG_FINAL) { + eprintk("unexpected data from %x %x\n", + cmnd_itt(cmnd), cmnd_ttt(cmnd)); + goto skip_data; + } + } + + dprintk(D_WRITE, "%u %p %p %p %u %u\n", req->ttt, cmnd, scsi_cmnd, + scsi_cmnd->tio, offset, cmnd->pdu.datasize); + + if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, cmnd->pdu.datasize) < 0) + goto skip_data; + return; + +skip_data: + cmnd->pdu.bhs.opcode = ISCSI_OP_DATA_REJECT; + cmnd_skip_pdu(cmnd); + return; +} + +static void data_out_end(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs; + struct iscsi_cmnd *scsi_cmnd; + u32 offset; + + assert(cmnd); + scsi_cmnd = cmnd->req; + assert(scsi_cmnd); + + if (conn->read_overflow) { + eprintk("%x %u\n", cmnd_itt(cmnd), conn->read_overflow); + assert(scsi_cmnd->tio); + offset = be32_to_cpu(req->buffer_offset); + offset += cmnd->pdu.datasize - conn->read_overflow; + if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, conn->read_overflow) < 0) + assert(0); + return; + } + + if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + if (req->flags & ISCSI_FLG_FINAL) { + scsi_cmnd->is_unsolicited_data = 0; + if (!cmnd_pending(scsi_cmnd)) + scsi_cmnd_exec(scsi_cmnd); + } + } else { + /* TODO : proper error handling */ + if (!(req->flags & ISCSI_FLG_FINAL) && scsi_cmnd->r2t_length == 0) + eprintk("initiator error %x\n", cmnd_itt(scsi_cmnd)); + + if (!(req->flags & ISCSI_FLG_FINAL)) + goto out; + + scsi_cmnd->outstanding_r2t--; + + if (scsi_cmnd->r2t_length == 0) + assert(list_empty(&scsi_cmnd->pdu_list)); + + scsi_cmnd_exec(scsi_cmnd); + } + +out: + iscsi_cmnd_remove(cmnd); + return; +} + +static int __cmnd_abort(struct iscsi_cmnd *cmnd) +{ + if (cmnd_waitio(cmnd)) + return -ISCSI_RESPONSE_UNKNOWN_TASK; + + if (cmnd->conn->read_cmnd != cmnd) + cmnd_release(cmnd, 1); + else if (cmnd_rxstart(cmnd)) + set_cmnd_tmfabort(cmnd); + else + return -ISCSI_RESPONSE_UNKNOWN_TASK; + + return 0; +} + +static int cmnd_abort(struct iscsi_session *session, u32 itt) +{ + struct iscsi_cmnd *cmnd; + int err = -ISCSI_RESPONSE_UNKNOWN_TASK; + + if ((cmnd = cmnd_find_hash(session, itt, ISCSI_RESERVED_TAG))) { + eprintk("%x %x %x %u %u %u %u\n", cmnd_itt(cmnd), cmnd_opcode(cmnd), + cmnd->r2t_length, cmnd_scsicode(cmnd), + cmnd_write_size(cmnd), cmnd->is_unsolicited_data, + cmnd->outstanding_r2t); + err = __cmnd_abort(cmnd); + } + + return err; +} + +static int target_reset(struct iscsi_cmnd *req, u32 lun, int all) +{ + struct iscsi_target *target = req->conn->session->target; + struct iscsi_session *session; + struct iscsi_conn *conn; + struct iscsi_cmnd *cmnd, *tmp; + struct iet_volume *volumes; + + list_for_each_entry(session, &target->session_list, list) { + list_for_each_entry(conn, &session->conn_list, list) { + list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) { + if (cmnd == req) + continue; + + if (all) + __cmnd_abort(cmnd); + else if (translate_lun(cmnd_hdr(cmnd)->lun) == lun) + __cmnd_abort(cmnd); + } + } + } + + list_for_each_entry(volumes, &target->volumes, list) + if (all || volumes->lun == lun) + /* force release */ + volume_release(volumes, 0, 1); + + return 0; +} + +static void task_set_abort(struct iscsi_cmnd *req) +{ + struct iscsi_session *session = req->conn->session; + struct iscsi_conn *conn; + struct iscsi_cmnd *cmnd, *tmp; + + list_for_each_entry(conn, &session->conn_list, list) { + list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) { + if (cmnd != req) + __cmnd_abort(cmnd); + } + } +} + +static inline char *tmf_desc(int fun) +{ + static char *tmf_desc[] = { + "Unknown Function", + "Abort Task", + "Abort Task Set", + "Clear ACA", + "Clear Task Set", + "Logical Unit Reset", + "Target Warm Reset", + "Target Cold Reset", + "Task Reassign", + }; + + if ((fun < ISCSI_FUNCTION_ABORT_TASK) || + (fun > ISCSI_FUNCTION_TASK_REASSIGN)) + fun = 0; + + return tmf_desc[fun]; +} + +static inline char *rsp_desc(int rsp) +{ + static char *rsp_desc[] = { + "Function Complete", + "Unknown Task", + "Unknown LUN", + "Task Allegiant", + "Failover Unsupported", + "Function Unsupported", + "No Authorization", + "Function Rejected", + "Unknown Response", + }; + + if (((rsp < ISCSI_RESPONSE_FUNCTION_COMPLETE) || + (rsp > ISCSI_RESPONSE_NO_AUTHORIZATION)) && + (rsp != ISCSI_RESPONSE_FUNCTION_REJECTED)) + rsp = 8; + else if (rsp == ISCSI_RESPONSE_FUNCTION_REJECTED) + rsp = 7; + + return rsp_desc[rsp]; +} + +static void execute_task_management(struct iscsi_cmnd *req) +{ + struct iscsi_conn *conn = req->conn; + struct iscsi_session *session = conn->session; + struct iscsi_target *target = session->target; + struct iscsi_cmnd *rsp; + struct iscsi_task_mgt_hdr *req_hdr = (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; + struct iscsi_task_rsp_hdr *rsp_hdr; + u32 lun; + int err, function = req_hdr->function & ISCSI_FUNCTION_MASK; + + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs; + + rsp_hdr->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->itt = req_hdr->itt; + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_COMPLETE; + + switch (function) { + case ISCSI_FUNCTION_ABORT_TASK: + case ISCSI_FUNCTION_ABORT_TASK_SET: + case ISCSI_FUNCTION_CLEAR_ACA: + case ISCSI_FUNCTION_CLEAR_TASK_SET: + case ISCSI_FUNCTION_LOGICAL_UNIT_RESET: + lun = translate_lun(req_hdr->lun); + if (!volume_lookup(target, lun)) { + rsp_hdr->response = ISCSI_RESPONSE_UNKNOWN_LUN; + goto out; + } + } + + switch (function) { + case ISCSI_FUNCTION_ABORT_TASK: + if ((err = cmnd_abort(conn->session, req_hdr->rtt)) < 0) + rsp_hdr->response = -err; + break; + case ISCSI_FUNCTION_ABORT_TASK_SET: + task_set_abort(req); + break; + case ISCSI_FUNCTION_CLEAR_ACA: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; + break; + case ISCSI_FUNCTION_CLEAR_TASK_SET: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; + break; + case ISCSI_FUNCTION_LOGICAL_UNIT_RESET: + target_reset(req, translate_lun(req_hdr->lun), 0); + break; + case ISCSI_FUNCTION_TARGET_WARM_RESET: + case ISCSI_FUNCTION_TARGET_COLD_RESET: + target_reset(req, 0, 1); + if (function == ISCSI_FUNCTION_TARGET_COLD_RESET) + set_cmnd_close(rsp); + break; + case ISCSI_FUNCTION_TASK_REASSIGN: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; + break; + default: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_REJECTED; + break; + } +out: + iprintk("%s (%02x) issued on tid:%d lun:%d by sid:%llu (%s)\n", + tmf_desc(function), function, target->tid, + translate_lun(req_hdr->lun), session->sid, + rsp_desc(rsp_hdr->response)); + + iscsi_cmnd_init_write(rsp); +} + +static void noop_out_exec(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + struct iscsi_nop_in_hdr *rsp_hdr; + + if (cmnd_itt(req) != cpu_to_be32(ISCSI_RESERVED_TAG)) { + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + + rsp_hdr = (struct iscsi_nop_in_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_NOOP_IN; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->itt = req->pdu.bhs.itt; + rsp_hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); + + if (req->pdu.datasize) + assert(req->tio); + else + assert(!req->tio); + + if (req->tio) { + tio_get(req->tio); + rsp->tio = req->tio; + } + + assert(get_pgcnt(req->pdu.datasize, 0) < ISCSI_CONN_IOV_MAX); + rsp->pdu.datasize = req->pdu.datasize; + iscsi_cmnd_init_write(rsp); + } else + iscsi_cmnd_remove(req); +} + +static void logout_exec(struct iscsi_cmnd *req) +{ + struct iscsi_logout_req_hdr *req_hdr; + struct iscsi_cmnd *rsp; + struct iscsi_logout_rsp_hdr *rsp_hdr; + + req_hdr = (struct iscsi_logout_req_hdr *)&req->pdu.bhs; + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + rsp_hdr = (struct iscsi_logout_rsp_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_LOGOUT_RSP; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->itt = req_hdr->itt; + set_cmnd_close(rsp); + iscsi_cmnd_init_write(rsp); +} + +static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd) +{ + dprintk(D_GENERIC, "%p,%x,%u\n", cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn); + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOOP_OUT: + noop_out_exec(cmnd); + break; + case ISCSI_OP_SCSI_CMD: + scsi_cmnd_exec(cmnd); + break; + case ISCSI_OP_SCSI_TASK_MGT_MSG: + execute_task_management(cmnd); + break; + case ISCSI_OP_LOGOUT_CMD: + logout_exec(cmnd); + break; + case ISCSI_OP_SCSI_REJECT: + iscsi_cmnd_init_write(get_rsp_cmnd(cmnd)); + break; + case ISCSI_OP_TEXT_CMD: + case ISCSI_OP_SNACK_CMD: + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + break; + } +} + +static void __cmnd_send_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size) +{ + dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size); + offset += tio->offset; + + assert(offset <= tio->offset + tio->size); + assert(offset + size <= tio->offset + tio->size); + + conn->write_tcmnd = tio; + conn->write_offset = offset; + conn->write_size += size; +} + +static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + u32 size; + struct tio *tio; + + if (!cmnd->pdu.datasize) + return; + + size = (cmnd->pdu.datasize + 3) & -4; + tio = cmnd->tio; + assert(tio); + assert(tio->size == size); + __cmnd_send_pdu(conn, tio, 0, size); +} + +static void set_cork(struct socket *sock, int on) +{ + int opt = on; + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(get_ds()); + sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK, (void *)&opt, sizeof(opt)); + set_fs(oldfs); +} + +void cmnd_release(struct iscsi_cmnd *cmnd, int force) +{ + struct iscsi_cmnd *req, *rsp; + int is_last = 0; + + if (!cmnd) + return; + +/* eprintk("%x %lx %d\n", cmnd_opcode(cmnd), cmnd->flags, force); */ + + req = cmnd->req; + is_last = cmnd_final(cmnd); + + if (force) { + while (!list_empty(&cmnd->pdu_list)) { + rsp = list_entry(cmnd->pdu_list.next, struct iscsi_cmnd, pdu_list); + list_del_init(&rsp->list); + list_del(&rsp->pdu_list); + iscsi_cmnd_remove(rsp); + } + list_del_init(&cmnd->list); + } else + if (cmnd_queued(cmnd)) + iscsi_scsi_dequeuecmnd(cmnd); + + if (cmnd_hashed(cmnd)) + cmnd_remove_hash(cmnd); + + if (cmnd_lunit(cmnd)) { + assert(cmnd->lun); + volume_put(cmnd->lun); + } + + list_del_init(&cmnd->pdu_list); + iscsi_cmnd_remove(cmnd); + + if (is_last) { + assert(!force); + assert(req); + cmnd_release(req, 0); + } + + return; +} + +void cmnd_tx_start(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iovec *iop; + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + assert(cmnd); + iscsi_cmnd_set_length(&cmnd->pdu); + + set_cork(conn->sock, 1); + + conn->write_iop = iop = conn->write_iov; + iop->iov_base = &cmnd->pdu.bhs; + iop->iov_len = sizeof(cmnd->pdu.bhs); + iop++; + conn->write_size = sizeof(cmnd->pdu.bhs); + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOOP_IN: + cmnd_set_sn(cmnd, 1); + cmnd_send_pdu(conn, cmnd); + break; + case ISCSI_OP_SCSI_RSP: + cmnd_set_sn(cmnd, 1); + cmnd_send_pdu(conn, cmnd); + break; + case ISCSI_OP_SCSI_TASK_MGT_RSP: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_TEXT_RSP: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_SCSI_DATA_IN: + { + struct iscsi_data_in_hdr *rsp = (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs; + u32 offset; + + cmnd_set_sn(cmnd, (rsp->flags & ISCSI_FLG_FINAL) ? 1 : 0); + offset = rsp->buffer_offset; + rsp->buffer_offset = cpu_to_be32(offset); + __cmnd_send_pdu(conn, cmnd->tio, offset, cmnd->pdu.datasize); + break; + } + case ISCSI_OP_LOGOUT_RSP: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_R2T: + cmnd_set_sn(cmnd, 0); + cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn); + break; + case ISCSI_OP_ASYNC_MSG: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_REJECT: + cmnd_set_sn(cmnd, 1); + cmnd_send_pdu(conn, cmnd); + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + break; + } + + iop->iov_len = 0; + // move this? + conn->write_size = (conn->write_size + 3) & -4; + iscsi_dump_pdu(&cmnd->pdu); +} + +void cmnd_tx_end(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOOP_IN: + case ISCSI_OP_SCSI_RSP: + case ISCSI_OP_SCSI_TASK_MGT_RSP: + case ISCSI_OP_TEXT_RSP: + case ISCSI_OP_R2T: + case ISCSI_OP_ASYNC_MSG: + case ISCSI_OP_REJECT: + case ISCSI_OP_SCSI_DATA_IN: + case ISCSI_OP_LOGOUT_RSP: + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + assert(0); + break; + } + + if (cmnd_close(cmnd)) + conn_close(conn); + + list_del_init(&cmnd->list); + set_cork(cmnd->conn->sock, 0); +} + +/** + * Push the command for execution. + * This functions reorders the commands. + * Called from the read thread. + * + * iscsi_session_push_cmnd - + * @cmnd: ptr to command + */ + +static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_session *session = cmnd->conn->session; + struct list_head *entry; + u32 cmd_sn; + + dprintk(D_GENERIC, "%p:%x %u,%u\n", + cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn); + + if (cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) { + iscsi_cmnd_exec(cmnd); + return; + } + + cmd_sn = cmnd->pdu.bhs.sn; + if (cmd_sn == session->exp_cmd_sn) { + while (1) { + session->exp_cmd_sn = ++cmd_sn; + iscsi_cmnd_exec(cmnd); + + if (list_empty(&session->pending_list)) + break; + cmnd = list_entry(session->pending_list.next, struct iscsi_cmnd, list); + if (cmnd->pdu.bhs.sn != cmd_sn) + break; +/* eprintk("find out-of-order %x %u %u\n", */ +/* cmnd_itt(cmnd), cmd_sn, cmnd->pdu.bhs.sn); */ + list_del_init(&cmnd->list); + clear_cmnd_pending(cmnd); + } + } else { +/* eprintk("out-of-order %x %u %u\n", */ +/* cmnd_itt(cmnd), cmd_sn, session->exp_cmd_sn); */ + + set_cmnd_pending(cmnd); + if (before(cmd_sn, session->exp_cmd_sn)) /* close the conn */ + eprintk("unexpected cmd_sn (%u,%u)\n", cmd_sn, session->exp_cmd_sn); + + if (after(cmd_sn, session->exp_cmd_sn + session->max_queued_cmnds)) + eprintk("too large cmd_sn (%u,%u)\n", cmd_sn, session->exp_cmd_sn); + + list_for_each(entry, &session->pending_list) { + struct iscsi_cmnd *tmp = list_entry(entry, struct iscsi_cmnd, list); + if (before(cmd_sn, tmp->pdu.bhs.sn)) + break; + } + + assert(list_empty(&cmnd->list)); + + list_add_tail(&cmnd->list, entry); + } +} + +static int check_segment_length(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iscsi_sess_param *param = &conn->session->param; + + if (cmnd->pdu.datasize > param->max_recv_data_length) { + eprintk("data too long %x %u %u\n", cmnd_itt(cmnd), + cmnd->pdu.datasize, param->max_recv_data_length); + + if (get_pgcnt(cmnd->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX) { + conn_close(conn); + return -EINVAL; + } + } + + return 0; +} + +void cmnd_rx_start(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + int err = 0; + + iscsi_dump_pdu(&cmnd->pdu); + + set_cmnd_rxstart(cmnd); + if (check_segment_length(cmnd) < 0) + return; + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOOP_OUT: + err = noop_out_start(conn, cmnd); + break; + case ISCSI_OP_SCSI_CMD: + if (!(err = cmnd_insert_hash(cmnd))) + scsi_cmnd_start(conn, cmnd); + break; + case ISCSI_OP_SCSI_TASK_MGT_MSG: + err = cmnd_insert_hash(cmnd); + break; + case ISCSI_OP_SCSI_DATA_OUT: + data_out_start(conn, cmnd); + break; + case ISCSI_OP_LOGOUT_CMD: + err = cmnd_insert_hash(cmnd); + break; + case ISCSI_OP_TEXT_CMD: + case ISCSI_OP_SNACK_CMD: + err = -ISCSI_REASON_UNSUPPORTED_COMMAND; + break; + default: + err = -ISCSI_REASON_UNSUPPORTED_COMMAND; + break; + } + + if (err < 0) { + eprintk("%x %x %d\n", cmnd_opcode(cmnd), cmnd_itt(cmnd), err); + iscsi_cmnd_reject(cmnd, -err); + } +} + +void cmnd_rx_end(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + + if (cmnd_tmfabort(cmnd)) { + cmnd_release(cmnd, 1); + return; + } + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_SCSI_REJECT: + case ISCSI_OP_NOOP_OUT: + case ISCSI_OP_SCSI_CMD: + case ISCSI_OP_SCSI_TASK_MGT_MSG: + case ISCSI_OP_TEXT_CMD: + case ISCSI_OP_LOGOUT_CMD: + iscsi_session_push_cmnd(cmnd); + break; + case ISCSI_OP_SCSI_DATA_OUT: + data_out_end(conn, cmnd); + break; + case ISCSI_OP_SNACK_CMD: + break; + case ISCSI_OP_PDU_REJECT: + iscsi_cmnd_init_write(get_rsp_cmnd(cmnd)); + break; + case ISCSI_OP_DATA_REJECT: + cmnd_release(cmnd, 0); + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + BUG(); + break; + } +} + +static void iscsi_exit(void) +{ + unregister_chrdev(ctr_major, ctr_name); + + iet_procfs_exit(); + + event_exit(); + + tio_exit(); + + iotype_exit(); + + if (iscsi_cmnd_cache) + kmem_cache_destroy(iscsi_cmnd_cache); +} + +static int iscsi_init(void) +{ + int err = -ENOMEM; + + printk("iSCSI Enterprise Target Software - version %s\n", IET_VERSION_STRING); + + if ((ctr_major = register_chrdev(0, ctr_name, &ctr_fops)) < 0) { + eprintk("failed to register the control device %d\n", ctr_major); + return ctr_major; + } + + if ((err = iet_procfs_init()) < 0) + goto err; + + if ((err = event_init()) < 0) + goto err; + + iscsi_cmnd_cache = KMEM_CACHE(iscsi_cmnd, 0); + if (!iscsi_cmnd_cache) + goto err; + + if ((err = tio_init()) < 0) + goto err; + + if ((err = iotype_init()) < 0) + goto err; + + return 0; + +err: + iscsi_exit(); + return err; +} + +module_param(debug_enable_flags, ulong, S_IRUGO); + +module_init(iscsi_init); +module_exit(iscsi_exit); + +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/iscsitarget/digest.h +++ linux-2.6.27/ubuntu/iscsitarget/digest.h @@ -0,0 +1,20 @@ +/* + * iSCSI digest handling. + * (C) 2004 Xiranet Communications GmbH + * This code is licensed under the GPL. + */ + +#ifndef __IET_DIGEST_H__ +#define __IET_DIGEST_H__ + +extern void digest_alg_available(unsigned int *val); +extern int digest_init(struct iscsi_conn *conn); +extern void digest_cleanup(struct iscsi_conn *conn); + +extern int digest_rx_header(struct iscsi_cmnd *cmnd); +extern int digest_rx_data(struct iscsi_cmnd *cmnd); + +extern void digest_tx_header(struct iscsi_cmnd *cmnd); +extern void digest_tx_data(struct iscsi_cmnd *cmnd); + +#endif /* __IET_DIGEST_H__ */ --- linux-2.6.27.orig/ubuntu/iscsitarget/iscsi_dbg.h +++ linux-2.6.27/ubuntu/iscsitarget/iscsi_dbg.h @@ -0,0 +1,130 @@ +#ifndef ISCSI_DBG_H +#define ISCSI_DBG_H + +#define D_SETUP (1UL << 0) +#define D_EXIT (1UL << 1) +#define D_GENERIC (1UL << 2) +#define D_READ (1UL << 3) +#define D_WRITE (1UL << 4) +#define D_IOD (1UL << 5) +#define D_THREAD (1UL << 6) +#define D_TASK_MGT (1UL << 7) +#define D_IOMODE (1UL << 8) + +#define D_DATA (D_READ | D_WRITE) + +extern unsigned long debug_enable_flags; + +#define PFX "iscsi_trgt: " + +#define dprintk(debug, fmt, args...) do { \ + if ((debug) & debug_enable_flags) { \ + printk(KERN_DEBUG PFX "%s(%d) " fmt, __FUNCTION__,\ + __LINE__, args);\ + } \ +} while (0) + +#define eprintk(fmt, args...) do { \ + printk(KERN_ERR PFX "%s(%d) " fmt, __FUNCTION__, \ + __LINE__, args);\ +} while (0) + +#define iprintk(X...) printk(KERN_INFO PFX X) + +#define assert(p) do { \ + if (!(p)) { \ + printk(KERN_CRIT PFX "BUG at %s:%d assert(%s)\n",\ + __FILE__, __LINE__, #p); \ + dump_stack(); \ + BUG(); \ + } \ +} while (0) + +#ifdef D_IOV +static inline void iscsi_dump_iov(struct msghdr *msg) +{ + int i; + printk(PFX "%p, %d\n", msg->msg_iov, msg->msg_iovlen); + for (i = 0; i < min_t(size_t, msg->msg_iovlen, ISCSI_CONN_IOV_MAX); i++) + printk(PFX "%d: %p,%d\n", i, msg->msg_iov[i].iov_base, + msg->msg_iov[i].iov_len); +} +#else +#define iscsi_dump_iov(x) do {} while (0) +#endif + +#ifdef D_DUMP_PDU +static void iscsi_dump_char(int ch) +{ + static unsigned char text[16]; + static int i = 0; + + if (ch < 0) { + while ((i % 16) != 0) { + printk(" "); + text[i] = ' '; + i++; + if ((i % 16) == 0) + printk(" | %.16s |\n", text); + else if ((i % 4) == 0) + printk(" |"); + } + i = 0; + return; + } + + text[i] = (ch < 0x20 || (ch >= 0x80 && ch <= 0xa0)) ? ' ' : ch; + printk(" %02x", ch); + i++; + if ((i % 16) == 0) { + printk(" | %.16s |\n", text); + i = 0; + } else if ((i % 4) == 0) + printk(" |"); +} + +static inline void iscsi_dump_pdu(struct iscsi_pdu *pdu) +{ + unsigned char *buf; + int i; + + buf = (void *)&pdu->bhs; + printk(PFX "BHS: (%p,%d)\n", buf, sizeof(pdu->bhs)); + for (i = 0; i < sizeof(pdu->bhs); i++) + iscsi_dump_char(*buf++); + iscsi_dump_char(-1); + + buf = (void *)pdu->ahs; + printk(PFX "AHS: (%p,%d)\n", buf, pdu->ahssize); + for (i = 0; i < pdu->ahssize; i++) + iscsi_dump_char(*buf++); + iscsi_dump_char(-1); + + printk(PFX "Data: (%d)\n", pdu->datasize); +} + +#else +#define iscsi_dump_pdu(x) do {} while (0) +#endif + +#define show_param(param)\ +{\ + dprintk(D_SETUP, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",\ + (param)->initial_r2t,\ + (param)->immediate_data,\ + (param)->max_connections,\ + (param)->max_recv_data_length,\ + (param)->max_xmit_data_length,\ + (param)->max_burst_length,\ + (param)->first_burst_length,\ + (param)->default_wait_time,\ + (param)->default_retain_time,\ + (param)->max_outstanding_r2t,\ + (param)->data_pdu_inorder,\ + (param)->data_sequence_inorder,\ + (param)->error_recovery_level,\ + (param)->header_digest,\ + (param)->data_digest);\ +} + +#endif --- linux-2.6.27.orig/ubuntu/iscsitarget/iscsi.h +++ linux-2.6.27/ubuntu/iscsitarget/iscsi.h @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef __ISCSI_H__ +#define __ISCSI_H__ + +#include +#include +#include +#include +#include +#include + +#include "iscsi_hdr.h" +#include "iet_u.h" + +struct iscsi_sess_param { + int initial_r2t; + int immediate_data; + int max_connections; + int max_recv_data_length; + int max_xmit_data_length; + int max_burst_length; + int first_burst_length; + int default_wait_time; + int default_retain_time; + int max_outstanding_r2t; + int data_pdu_inorder; + int data_sequence_inorder; + int error_recovery_level; + int header_digest; + int data_digest; + int ofmarker; + int ifmarker; + int ofmarkint; + int ifmarkint; +}; + +struct iscsi_trgt_param { + int wthreads; + int target_type; + int queued_cmnds; +}; + +struct tio { + u32 pg_cnt; + + pgoff_t idx; + u32 offset; + u32 size; + + struct page **pvec; + + atomic_t count; +}; + +struct network_thread_info { + struct task_struct *task; + unsigned long flags; + struct list_head active_conns; + + spinlock_t nthread_lock; + + void (*old_state_change)(struct sock *); + void (*old_data_ready)(struct sock *, int); +}; + +struct worker_thread_info; + +struct worker_thread { + struct task_struct *w_task; + struct list_head w_list; + struct worker_thread_info *w_info; +}; + +struct worker_thread_info { + spinlock_t wthread_lock; + + u32 nr_running_wthreads; + + struct list_head wthread_list; + struct list_head work_queue; + + wait_queue_head_t wthread_sleep; +}; + +struct iscsi_cmnd; + +struct target_type { + int id; + int (*execute_cmnd) (struct iscsi_cmnd *); +}; + +enum iscsi_device_state { + IDEV_RUNNING, + IDEV_DEL, +}; + +struct iscsi_target { + struct list_head t_list; + u32 tid; + + char name[ISCSI_NAME_LEN]; + + struct iscsi_sess_param sess_param; + struct iscsi_trgt_param trgt_param; + + atomic_t nr_volumes; + struct list_head volumes; + struct list_head session_list; + + struct network_thread_info nthread_info; + struct worker_thread_info wthread_info; + + struct semaphore target_sem; +}; + +struct iscsi_queue { + spinlock_t queue_lock; + struct iscsi_cmnd *ordered_cmnd; + struct list_head wait_list; + int active_cnt; +}; + +struct iet_volume { + u32 lun; + + enum iscsi_device_state l_state; + atomic_t l_count; + + struct iscsi_target *target; + struct list_head list; + + struct iscsi_queue queue; + + u8 scsi_id[SCSI_ID_LEN]; + u8 scsi_sn[SCSI_SN_LEN]; + + u32 blk_shift; + u64 blk_cnt; + + u64 reserve_sid; + spinlock_t reserve_lock; + + unsigned long flags; + + struct iotype *iotype; + void *private; +}; + +enum lu_flags { + LU_READONLY, + LU_ASYNC, +}; + +#define LUReadonly(lu) test_bit(LU_READONLY, &(lu)->flags) +#define SetLUReadonly(lu) set_bit(LU_READONLY, &(lu)->flags) + +#define LUAsync(lu) test_bit(LU_ASYNC, &(lu)->flags) +#define SetLUAsync(lu) set_bit(LU_ASYNC, &(lu)->flags) + +#define IET_HASH_ORDER 8 +#define cmnd_hashfn(itt) hash_long((itt), IET_HASH_ORDER) + +struct iscsi_session { + struct list_head list; + struct iscsi_target *target; + + char *initiator; + u64 sid; + + u32 exp_cmd_sn; + u32 max_cmd_sn; + + struct iscsi_sess_param param; + u32 max_queued_cmnds; + + struct list_head conn_list; + + struct list_head pending_list; + + spinlock_t cmnd_hash_lock; + struct list_head cmnd_hash[1 << IET_HASH_ORDER]; + + u32 next_ttt; +}; + +enum connection_state_bit { + CONN_ACTIVE, + CONN_CLOSING, +}; + +#define ISCSI_CONN_IOV_MAX (((256 << 10) >> PAGE_SHIFT) + 1) + +struct iscsi_conn { + struct list_head list; /* list entry in session list */ + struct iscsi_session *session; /* owning session */ + + u16 cid; + unsigned long state; + + u32 stat_sn; + u32 exp_stat_sn; + + int hdigest_type; + int ddigest_type; + + struct list_head poll_list; + + struct file *file; + struct socket *sock; + spinlock_t list_lock; + atomic_t nr_cmnds; + atomic_t nr_busy_cmnds; + struct list_head pdu_list; /* in/outcoming pdus */ + struct list_head write_list; /* list of data pdus to be sent */ + + struct iscsi_cmnd *read_cmnd; + struct msghdr read_msg; + struct iovec read_iov[ISCSI_CONN_IOV_MAX]; + u32 read_size; + u32 read_overflow; + int read_state; + + struct iscsi_cmnd *write_cmnd; + struct iovec write_iov[ISCSI_CONN_IOV_MAX]; + struct iovec *write_iop; + struct tio *write_tcmnd; + u32 write_size; + u32 write_offset; + int write_state; + + struct hash_desc rx_hash; + struct hash_desc tx_hash; + struct scatterlist hash_sg[ISCSI_CONN_IOV_MAX]; +}; + +struct iscsi_pdu { + struct iscsi_hdr bhs; + void *ahs; + unsigned int ahssize; + unsigned int datasize; +}; + +typedef void (iet_show_info_t)(struct seq_file *seq, struct iscsi_target *target); + +struct iscsi_cmnd { + struct list_head list; + struct list_head conn_list; + unsigned long flags; + struct iscsi_conn *conn; + struct iet_volume *lun; + + struct iscsi_pdu pdu; + struct list_head pdu_list; + + struct list_head hash_list; + + struct tio *tio; + + u32 r2t_sn; + u32 r2t_length; + u32 is_unsolicited_data; + u32 target_task_tag; + u32 outstanding_r2t; + + u32 hdigest; + u32 ddigest; + + struct iscsi_cmnd *req; +}; + +#define ISCSI_OP_SCSI_REJECT ISCSI_OP_VENDOR1_CMD +#define ISCSI_OP_PDU_REJECT ISCSI_OP_VENDOR2_CMD +#define ISCSI_OP_DATA_REJECT ISCSI_OP_VENDOR3_CMD +#define ISCSI_OP_SCSI_ABORT ISCSI_OP_VENDOR4_CMD + +/* iscsi.c */ +extern struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *, int); +extern void cmnd_rx_start(struct iscsi_cmnd *); +extern void cmnd_rx_end(struct iscsi_cmnd *); +extern void cmnd_tx_start(struct iscsi_cmnd *); +extern void cmnd_tx_end(struct iscsi_cmnd *); +extern void cmnd_release(struct iscsi_cmnd *, int); +extern void send_data_rsp(struct iscsi_cmnd *, int (*)(struct iscsi_cmnd *)); +extern void send_scsi_rsp(struct iscsi_cmnd *, int (*)(struct iscsi_cmnd *)); + +/* conn.c */ +extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16); +extern int conn_add(struct iscsi_session *, struct conn_info *); +extern int conn_del(struct iscsi_session *, struct conn_info *); +extern int conn_free(struct iscsi_conn *); +extern void conn_close(struct iscsi_conn *); +extern void conn_info_show(struct seq_file *, struct iscsi_session *); + +/* nthread.c */ +extern int nthread_init(struct iscsi_target *); +extern int nthread_start(struct iscsi_target *); +extern int nthread_stop(struct iscsi_target *); +extern void nthread_wakeup(struct iscsi_target *); + +/* wthread.c */ +extern int wthread_init(struct iscsi_target *); +extern int wthread_start(struct iscsi_target *); +extern int wthread_stop(struct iscsi_target *); +extern void wthread_queue(struct iscsi_cmnd *); +extern struct target_type *target_type_array[]; + +/* target.c */ +extern int target_lock(struct iscsi_target *, int); +extern void target_unlock(struct iscsi_target *); +struct iscsi_target *target_lookup_by_id(u32); +extern int target_add(struct target_info *); +extern int target_del(u32 id); + +/* config.c */ +extern int iet_procfs_init(void); +extern void iet_procfs_exit(void); +extern int iet_info_show(struct seq_file *, iet_show_info_t *); + +/* session.c */ +extern struct file_operations session_seq_fops; +extern struct iscsi_session *session_lookup(struct iscsi_target *, u64); +extern int session_add(struct iscsi_target *, struct session_info *); +extern int session_del(struct iscsi_target *, u64); + +/* volume.c */ +extern struct file_operations volume_seq_fops; +extern int volume_add(struct iscsi_target *, struct volume_info *); +extern int iscsi_volume_del(struct iscsi_target *, struct volume_info *); +extern void iscsi_volume_destroy(struct iet_volume *); +extern struct iet_volume *volume_lookup(struct iscsi_target *, u32); +extern struct iet_volume *volume_get(struct iscsi_target *, u32); +extern void volume_put(struct iet_volume *); +extern int volume_reserve(struct iet_volume *volume, u64 sid); +extern int volume_release(struct iet_volume *volume, u64 sid, int force); +extern int is_volume_reserved(struct iet_volume *volume, u64 sid); + +/* tio.c */ +extern int tio_init(void); +extern void tio_exit(void); +extern struct tio *tio_alloc(int); +extern void tio_get(struct tio *); +extern void tio_put(struct tio *); +extern void tio_set(struct tio *, u32, loff_t); +extern int tio_read(struct iet_volume *, struct tio *); +extern int tio_write(struct iet_volume *, struct tio *); +extern int tio_sync(struct iet_volume *, struct tio *); + +/* iotype.c */ +extern struct iotype *get_iotype(const char *name); +extern void put_iotype(struct iotype *iot); + +/* params.c */ +extern int iscsi_param_set(struct iscsi_target *, struct iscsi_param_info *, int); + +/* target_disk.c */ +extern struct target_type disk_ops; + +/* event.c */ +extern int event_send(u32, u64, u32, u32, int); +extern int event_init(void); +extern void event_exit(void); + +#define get_pgcnt(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) + +static inline void iscsi_cmnd_get_length(struct iscsi_pdu *pdu) +{ +#if defined(__BIG_ENDIAN) + pdu->ahssize = pdu->bhs.length.ahslength * 4; + pdu->datasize = pdu->bhs.length.datalength; +#elif defined(__LITTLE_ENDIAN) + pdu->ahssize = (pdu->bhs.length & 0xff) * 4; + pdu->datasize = be32_to_cpu(pdu->bhs.length & ~0xff); +#else +#error +#endif +} + +static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu) +{ +#if defined(__BIG_ENDIAN) + pdu->bhs.length.ahslength = pdu->ahssize / 4; + pdu->bhs.length.datalength = pdu->datasize; +#elif defined(__LITTLE_ENDIAN) + pdu->bhs.length = cpu_to_be32(pdu->datasize) | (pdu->ahssize / 4); +#else +#error +#endif +} + +#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs))) +#define cmnd_ttt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.ttt) +#define cmnd_itt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.itt) +#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK) +#define cmnd_scsicode(cmnd) cmnd_hdr(cmnd)->scb[0] + +#define SECTOR_SIZE_BITS 9 + +enum cmnd_flags { + CMND_hashed, + CMND_queued, + CMND_final, + CMND_waitio, + CMND_close, + CMND_lunit, + CMND_pending, + CMND_tmfabort, + CMND_rxstart, +}; + +#define set_cmnd_hashed(cmnd) set_bit(CMND_hashed, &(cmnd)->flags) +#define cmnd_hashed(cmnd) test_bit(CMND_hashed, &(cmnd)->flags) + +#define set_cmnd_queued(cmnd) set_bit(CMND_queued, &(cmnd)->flags) +#define cmnd_queued(cmnd) test_bit(CMND_queued, &(cmnd)->flags) + +#define set_cmnd_final(cmnd) set_bit(CMND_final, &(cmnd)->flags) +#define cmnd_final(cmnd) test_bit(CMND_final, &(cmnd)->flags) + +#define set_cmnd_waitio(cmnd) set_bit(CMND_waitio, &(cmnd)->flags) +#define cmnd_waitio(cmnd) test_bit(CMND_waitio, &(cmnd)->flags) + +#define set_cmnd_close(cmnd) set_bit(CMND_close, &(cmnd)->flags) +#define cmnd_close(cmnd) test_bit(CMND_close, &(cmnd)->flags) + +#define set_cmnd_lunit(cmnd) set_bit(CMND_lunit, &(cmnd)->flags) +#define cmnd_lunit(cmnd) test_bit(CMND_lunit, &(cmnd)->flags) + +#define set_cmnd_pending(cmnd) set_bit(CMND_pending, &(cmnd)->flags) +#define clear_cmnd_pending(cmnd) clear_bit(CMND_pending, &(cmnd)->flags) +#define cmnd_pending(cmnd) test_bit(CMND_pending, &(cmnd)->flags) + +#define set_cmnd_tmfabort(cmnd) set_bit(CMND_tmfabort, &(cmnd)->flags) +#define cmnd_tmfabort(cmnd) test_bit(CMND_tmfabort, &(cmnd)->flags) + +#define set_cmnd_rxstart(cmnd) set_bit(CMND_rxstart, &(cmnd)->flags) +#define cmnd_rxstart(cmnd) test_bit(CMND_rxstart, &(cmnd)->flags) + +#define VENDOR_ID "IET" +#define PRODUCT_ID "VIRTUAL-DISK" +#define PRODUCT_REV "0" + +#endif /* __ISCSI_H__ */ --- linux-2.6.27.orig/ubuntu/iscsitarget/iet_u.h +++ linux-2.6.27/ubuntu/iscsitarget/iet_u.h @@ -0,0 +1,139 @@ +#ifndef _IET_U_H +#define _IET_U_H + +#define IET_VERSION_STRING "0.4.15" + +/* The maximum length of 223 bytes in the RFC. */ +#define ISCSI_NAME_LEN 256 +#define ISCSI_ARGS_LEN 2048 + +#define ISCSI_LISTEN_PORT 3260 + +#define VENDOR_ID_LEN 8 +#define SCSI_ID_LEN 24 +#define SCSI_SN_LEN 16 + +#ifndef aligned_u64 +#define aligned_u64 unsigned long long __attribute__((aligned(8))) +#endif + +struct target_info { + u32 tid; + char name[ISCSI_NAME_LEN]; +}; + +struct volume_info { + u32 tid; + u32 lun; + aligned_u64 args_ptr; + u32 args_len; +}; + +struct session_info { + u32 tid; + + aligned_u64 sid; + char initiator_name[ISCSI_NAME_LEN]; + u32 exp_cmd_sn; + u32 max_cmd_sn; +}; + +#define DIGEST_ALL (DIGEST_NONE | DIGEST_CRC32C) +#define DIGEST_NONE (1 << 0) +#define DIGEST_CRC32C (1 << 1) + +struct conn_info { + u32 tid; + aligned_u64 sid; + + u32 cid; + u32 stat_sn; + u32 exp_stat_sn; + int header_digest; + int data_digest; + int fd; +}; + +enum { + key_initial_r2t, + key_immediate_data, + key_max_connections, + key_max_recv_data_length, + key_max_xmit_data_length, + key_max_burst_length, + key_first_burst_length, + key_default_wait_time, + key_default_retain_time, + key_max_outstanding_r2t, + key_data_pdu_inorder, + key_data_sequence_inorder, + key_error_recovery_level, + key_header_digest, + key_data_digest, + key_ofmarker, + key_ifmarker, + key_ofmarkint, + key_ifmarkint, + session_key_last, +}; + +enum { + key_wthreads, + key_target_type, + key_queued_cmnds, + target_key_last, +}; + +enum { + key_session, + key_target, +}; + +struct iscsi_param_info { + u32 tid; + aligned_u64 sid; + + u32 param_type; + u32 partial; + + u32 session_param[session_key_last]; + u32 target_param[target_key_last]; +}; + +enum iet_event_state { + E_CONN_CLOSE, +}; + +struct iet_event { + u32 tid; + aligned_u64 sid; + u32 cid; + u32 state; +}; + +#define DEFAULT_NR_WTHREADS 8 +#define MIN_NR_WTHREADS 1 +#define MAX_NR_WTHREADS 128 + +#define DEFAULT_NR_QUEUED_CMNDS 32 +#define MIN_NR_QUEUED_CMNDS 1 +#define MAX_NR_QUEUED_CMNDS 256 + +#define NETLINK_IET 21 + +#define ADD_TARGET _IOW('i', 0, struct target_info) +#define DEL_TARGET _IOW('i', 1, struct target_info) +#define START_TARGET _IO('i', 2) +#define STOP_TARGET _IO('i', 3) +#define ADD_VOLUME _IOW('i', 4, struct volume_info) +#define DEL_VOLUME _IOW('i', 5, struct volume_info) +#define ADD_SESSION _IOW('i', 6, struct session_info) +#define DEL_SESSION _IOW('i', 7, struct session_info) +#define GET_SESSION_INFO _IOWR('i', 8, struct session_info) +#define ADD_CONN _IOW('i', 9, struct conn_info) +#define DEL_CONN _IOW('i', 10, struct conn_info) +#define GET_CONN_INFO _IOWR('i', 11, struct conn_info) +#define ISCSI_PARAM_SET _IOW('i', 12, struct iscsi_param_info) +#define ISCSI_PARAM_GET _IOWR('i', 13, struct iscsi_param_info) + +#endif --- linux-2.6.27.orig/ubuntu/iscsitarget/event.c +++ linux-2.6.27/ubuntu/iscsitarget/event.c @@ -0,0 +1,113 @@ +/* + * Event notification code. + * (C) 2005 FUJITA Tomonori + * This code is licenced under the GPL. + * + * Some functions are based on audit code. + */ + +#include +#include "iet_u.h" +#include "iscsi_dbg.h" + +static struct sock *nl; +static u32 ietd_pid; + +static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) +{ + u32 uid, pid, seq; + char *data; + + pid = NETLINK_CREDS(skb)->pid; + uid = NETLINK_CREDS(skb)->uid; + seq = nlh->nlmsg_seq; + data = NLMSG_DATA(nlh); + + ietd_pid = pid; + + return 0; +} + +static void event_recv_skb(struct sk_buff *skb) +{ + int err; + struct nlmsghdr *nlh; + u32 rlen; + + while (skb->len >= NLMSG_SPACE(0)) { + nlh = (struct nlmsghdr *)skb->data; + if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + return; + rlen = NLMSG_ALIGN(nlh->nlmsg_len); + if (rlen > skb->len) + rlen = skb->len; + if ((err = event_recv_msg(skb, nlh))) { + netlink_ack(skb, nlh, -err); + } else if (nlh->nlmsg_flags & NLM_F_ACK) + netlink_ack(skb, nlh, 0); + skb_pull(skb, rlen); + } + return; +} + +#if 0 +static void event_recv(struct sock *sk, int length) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(&sk->sk_receive_queue))) { + if (event_recv_skb(skb) && skb->len) + skb_queue_head(&sk->sk_receive_queue, skb); + else + kfree_skb(skb); + } +} +#endif + +static int notify(void *data, int len, int gfp_mask) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + static u32 seq = 0; + + if (!(skb = alloc_skb(NLMSG_SPACE(len), gfp_mask))) + return -ENOMEM; + + nlh = __nlmsg_put(skb, ietd_pid, seq++, NLMSG_DONE, len - sizeof(*nlh), 0); + + memcpy(NLMSG_DATA(nlh), data, len); + + return netlink_unicast(nl, skb, ietd_pid, 0); +} + +int event_send(u32 tid, u64 sid, u32 cid, u32 state, int atomic) +{ + int err; + struct iet_event event; + + event.tid = tid; + event.sid = sid; + event.cid = cid; + event.state = state; + + err = notify(&event, NLMSG_SPACE(sizeof(struct iet_event)), 0); + + return err; +} + +int event_init(void) +{ + nl = netlink_kernel_create(&init_net, NETLINK_IET, 1, event_recv_skb, + NULL, THIS_MODULE); + + if (!nl) + return -ENOMEM; + else + return 0; +} + +void event_exit(void) +{ + if (nl) + sock_release(nl->sk_socket); +} --- linux-2.6.27.orig/ubuntu/iscsitarget/BOM +++ linux-2.6.27/ubuntu/iscsitarget/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://www.amherst.edu/~swplotner/iscsitarget/download/iscsitarget/ +Current Version: 0.4.15.145 --- linux-2.6.27.orig/ubuntu/iscsitarget/config.c +++ linux-2.6.27/ubuntu/iscsitarget/config.c @@ -0,0 +1,316 @@ +/* + * (C) 2004 - 2005 FUJITA Tomonori + * + * This code is licenced under the GPL. + */ + +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" + +struct proc_entries { + const char *name; + struct file_operations *fops; +}; + +static struct proc_entries iet_proc_entries[] = +{ + {"volume", &volume_seq_fops}, + {"session", &session_seq_fops}, +}; + +static struct proc_dir_entry *proc_iet_dir; + +void iet_procfs_exit(void) +{ + int i; + + if (!proc_iet_dir) + return; + + for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++) + remove_proc_entry(iet_proc_entries[i].name, proc_iet_dir); + + remove_proc_entry(proc_iet_dir->name, proc_iet_dir->parent); +} + +int iet_procfs_init(void) +{ + int i; + struct proc_dir_entry *ent; + + if (!(proc_iet_dir = proc_mkdir("net/iet", 0))) + goto err; + + proc_iet_dir->owner = THIS_MODULE; + + for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++) { + ent = create_proc_entry(iet_proc_entries[i].name, 0, proc_iet_dir); + if (ent) + ent->proc_fops = iet_proc_entries[i].fops; + else + goto err; + } + + return 0; + +err: + if (proc_iet_dir) + iet_procfs_exit(); + + return -ENOMEM; +} + +static int get_conn_info(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct iscsi_session *session; + struct conn_info info; + struct iscsi_conn *conn; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + session = session_lookup(target, info.sid); + if (!session) + return -ENOENT; + conn = conn_lookup(session, info.cid); + + info.cid = conn->cid; + info.stat_sn = conn->stat_sn; + info.exp_stat_sn = conn->exp_stat_sn; + + if (copy_to_user((void *) ptr, &info, sizeof(info))) + return -EFAULT; + + return 0; +} + +static int add_conn(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct iscsi_session *session; + struct conn_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + if (!(session = session_lookup(target, info.sid))) + return -ENOENT; + + return conn_add(session, &info); +} + +static int del_conn(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct iscsi_session *session; + struct conn_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + if (!(session = session_lookup(target, info.sid))) + return -ENOENT; + + return conn_del(session, &info); +} + +static int get_session_info(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct iscsi_session *session; + struct session_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + session = session_lookup(target, info.sid); + + if (!session) + return -ENOENT; + + info.exp_cmd_sn = session->exp_cmd_sn; + info.max_cmd_sn = session->max_cmd_sn; + + if (copy_to_user((void *) ptr, &info, sizeof(info))) + return -EFAULT; + + return 0; +} + +static int add_session(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct session_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + return session_add(target, &info); +} + +static int del_session(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct session_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + return session_del(target, info.sid); +} + +static int add_volume(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct volume_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + return volume_add(target, &info); +} + +static int del_volume(struct iscsi_target *target, unsigned long ptr) +{ + int err; + struct volume_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + return iscsi_volume_del(target, &info); +} + +static int iscsi_param_config(struct iscsi_target *target, unsigned long ptr, int set) +{ + int err; + struct iscsi_param_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + goto out; + + if ((err = iscsi_param_set(target, &info, set)) < 0) + goto out; + + if (!set) + err = copy_to_user((void *) ptr, &info, sizeof(info)); + +out: + return err; +} + +static int add_target(unsigned long ptr) +{ + int err; + struct target_info info; + + if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) + return err; + + if (!(err = target_add(&info))) + err = copy_to_user((void *) ptr, &info, sizeof(info)); + + return err; +} + +static long ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct iscsi_target *target = NULL; + long err; + u32 id; + + if ((err = get_user(id, (u32 *) arg)) != 0) + goto done; + + if (cmd == DEL_TARGET) { + err = target_del(id); + goto done; + } + + target = target_lookup_by_id(id); + + if (cmd == ADD_TARGET) + if (target) { + err = -EEXIST; + eprintk("Target %u already exist!\n", id); + goto done; + } + + switch (cmd) { + case ADD_TARGET: + assert(!target); + err = add_target(arg); + goto done; + } + + if (!target) { + eprintk("can't find the target %u\n", id); + err = -EINVAL; + goto done; + } + + if ((err = target_lock(target, 1)) < 0) { + eprintk("interrupted %ld %d\n", err, cmd); + goto done; + } + + switch (cmd) { + case ADD_VOLUME: + err = add_volume(target, arg); + break; + + case DEL_VOLUME: + err = del_volume(target, arg); + break; + + case ADD_SESSION: + err = add_session(target, arg); + break; + + case DEL_SESSION: + err = del_session(target, arg); + break; + + case GET_SESSION_INFO: + err = get_session_info(target, arg); + break; + + case ISCSI_PARAM_SET: + err = iscsi_param_config(target, arg, 1); + break; + + case ISCSI_PARAM_GET: + err = iscsi_param_config(target, arg, 0); + break; + + case ADD_CONN: + err = add_conn(target, arg); + break; + + case DEL_CONN: + err = del_conn(target, arg); + break; + + case GET_CONN_INFO: + err = get_conn_info(target, arg); + break; + default: + eprintk("invalid ioctl cmd %x\n", cmd); + err = -EINVAL; + } + + if (target) + target_unlock(target); + +done: + return err; +} + +struct file_operations ctr_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = ioctl, + .compat_ioctl = ioctl, +}; --- linux-2.6.27.orig/ubuntu/iscsitarget/block-io.c +++ linux-2.6.27/ubuntu/iscsitarget/block-io.c @@ -0,0 +1,378 @@ +/* + * Target device block I/O. + * + * Based on file I/O driver from FUJITA Tomonori + * (C) 2004 - 2005 FUJITA Tomonori + * (C) 2006 Andre Brinkmann + * (C) 2007 Ross Walker + * (C) 2007 Ming Zhang + * This code is licenced under the GPL. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +struct blockio_data { + char *path; + struct block_device *bdev; +}; + +struct tio_work { + atomic_t error; + atomic_t bios_remaining; + struct completion tio_complete; +}; + +static void +blockio_bio_endio(struct bio *bio, int error) +{ + struct tio_work *tio_work = bio->bi_private; + + /* Ignore partials */ + if (bio->bi_size) + return; + + error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO; + + if (error) + atomic_set(&tio_work->error, error); + + /* If last bio signal completion */ + if (atomic_dec_and_test(&tio_work->bios_remaining)) + complete(&tio_work->tio_complete); + + bio_put(bio); +} + +/* + * Blockio_make_request(): The function translates an iscsi-request into + * a number of requests to the corresponding block device. + */ +static int +blockio_make_request(struct iet_volume *volume, struct tio *tio, int rw) +{ + struct blockio_data *bio_data = volume->private; + struct request_queue *bdev_q = bdev_get_queue(bio_data->bdev); + struct tio_work *tio_work; + struct bio *tio_bio = NULL, *bio = NULL, *biotail = NULL; + + u32 offset = tio->offset; + u32 size = tio->size; + u32 tio_index = 0; + + int max_pages = 1; + int err = 0; + + loff_t ppos = ((loff_t) tio->idx << PAGE_SHIFT) + offset; + + /* Calculate max_pages for bio_alloc (memory saver) */ + if (bdev_q) + max_pages = bio_get_nr_vecs(bio_data->bdev); + + tio_work = kzalloc(sizeof (*tio_work), GFP_KERNEL); + if (!tio_work) + return -ENOMEM; + + atomic_set(&tio_work->error, 0); + atomic_set(&tio_work->bios_remaining, 0); + init_completion(&tio_work->tio_complete); + + /* Main processing loop, allocate and fill all bios */ + while (tio_index < tio->pg_cnt) { + bio = bio_alloc(GFP_KERNEL, min(max_pages, BIO_MAX_PAGES)); + if (!bio) { + err = -ENOMEM; + goto out; + } + + bio->bi_sector = ppos >> volume->blk_shift; + bio->bi_bdev = bio_data->bdev; + bio->bi_end_io = blockio_bio_endio; + bio->bi_private = tio_work; + + if (tio_bio) + biotail = biotail->bi_next = bio; + else + tio_bio = biotail = bio; + + atomic_inc(&tio_work->bios_remaining); + + /* Loop for filling bio */ + while (tio_index < tio->pg_cnt) { + unsigned int bytes = PAGE_SIZE - offset; + + if (bytes > size) + bytes = size; + + if (!bio_add_page(bio, tio->pvec[tio_index], bytes, offset)) + break; + + size -= bytes; + ppos += bytes; + + offset = 0; + + tio_index++; + } + } + + /* Walk the list, submitting bios 1 by 1 */ + while (tio_bio) { + bio = tio_bio; + tio_bio = tio_bio->bi_next; + bio->bi_next = NULL; + + submit_bio(rw, bio); + } + + if (bdev_q && bdev_q->unplug_fn) + bdev_q->unplug_fn(bdev_q); + + wait_for_completion(&tio_work->tio_complete); + + err = atomic_read(&tio_work->error); + + kfree(tio_work); + + return err; +out: + while (tio_bio) { + bio = tio_bio; + tio_bio = tio_bio->bi_next; + + bio_put(bio); + } + + kfree(tio_work); + + return err; +} + +static int +blockio_open_path(struct iet_volume *volume, const char *path) +{ + struct blockio_data *bio_data = volume->private; + struct block_device *bdev; + int flags = LUReadonly(volume) ? MS_RDONLY : 0; + int err = 0; + + bio_data->path = kstrdup(path, GFP_KERNEL); + if (!bio_data->path) + return -ENOMEM; + + bdev = open_bdev_excl(path, flags, THIS_MODULE); + if (IS_ERR(bdev)) { + err = PTR_ERR(bdev); + eprintk("Can't open device %s, error %d\n", path, err); + bio_data->bdev = NULL; + } else { + bio_data->bdev = bdev; + fsync_bdev(bio_data->bdev); + } + + return err; +} + +static int +set_scsiid(struct iet_volume *volume, const char *id) +{ + size_t len; + + if ((len = strlen(id)) > SCSI_ID_LEN - VENDOR_ID_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max\n", len, + SCSI_ID_LEN - VENDOR_ID_LEN); + return -EINVAL; + } + + memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len); + + return 0; +} + +static void +gen_scsiid(struct iet_volume *volume, struct inode *inode) +{ + int i; + u32 *p; + + strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); + + for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++) + if (volume->scsi_id[i]) + return; + + /* If a scsi id doesn't exist generate a 16 byte one: + * Bytes 1-4: target type + * Bytes 5-8: target id + * Bytes 9-12: inode number + * Bytes 13-16: device type + */ + p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN); + *(p + 0) = volume->target->trgt_param.target_type; + *(p + 1) = volume->target->tid; + *(p + 2) = volume->lun; + *(p + 3) = (unsigned int) inode->i_sb->s_dev; +} + +static int +set_scsisn(struct iet_volume *volume, const char *sn) +{ + size_t len; + + if ((len = strlen(sn)) > SCSI_SN_LEN) { + eprintk("SCSI SN too long, %zd provided, %u max\n", len, + SCSI_SN_LEN); + return -EINVAL; + } + + memcpy(volume->scsi_sn, sn, len); + + return 0; +} + +/* Create an enumeration of our accepted actions */ +enum +{ + Opt_scsiid, Opt_scsisn, Opt_path, Opt_ignore, Opt_err, +}; + +/* Create a match table using our action enums and their matching options */ +static match_table_t tokens = { + {Opt_scsiid, "ScsiId=%s"}, + {Opt_scsisn, "ScsiSN=%s"}, + {Opt_path, "Path=%s"}, + {Opt_ignore, "Type=%s"}, + {Opt_ignore, "IOMode=%s"}, + {Opt_err, NULL}, +}; + +static int +parse_blockio_params (struct iet_volume *volume, char *params) +{ + int err = 0; + char *p, *q; + + /* Loop through parameters separated by commas, look up our + * parameter in match table, return enumeration and arguments + * select case based on the returned enum and run the action */ + while ((p = strsep(¶ms, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + if (!*p) + continue; + token = match_token(p, tokens, args); + switch (token) { + case Opt_scsiid: + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = set_scsiid(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case Opt_scsisn: + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = set_scsisn(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case Opt_path: + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = blockio_open_path(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case Opt_ignore: + break; + default: + eprintk("Bad option %s for Lun %u on Target %s \n", + p, volume->lun, volume->target->name); + return -EINVAL; + } + } + + out: + return err; +} + +static void +blockio_detach(struct iet_volume *volume) +{ + struct blockio_data *bio_data = volume->private; + + if (bio_data->bdev) + close_bdev_excl(bio_data->bdev); + kfree(bio_data->path); + + kfree(volume->private); +} + +static int +blockio_attach (struct iet_volume *volume, char *args) +{ + struct blockio_data *bio_data; + int err = 0; + + if (volume->private) { + eprintk("Lun %u already attached on Target %s \n", + volume->lun, volume->target->name); + return -EBUSY; + } + + bio_data = kzalloc(sizeof (*bio_data), GFP_KERNEL); + if (!bio_data) + return -ENOMEM; + + volume->private = bio_data; + + if ((err = parse_blockio_params(volume, args)) < 0) { + eprintk("Error attaching Lun %u to Target %s \n", + volume->lun, volume->target->name); + goto out; + } + + /* Assign a vendor id, generate scsi id if none exists */ + gen_scsiid(volume, bio_data->bdev->bd_inode); + + volume->blk_shift = SECTOR_SIZE_BITS; + volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift; + + out: + if (err < 0) + blockio_detach(volume); + + return err; +} + +static void +blockio_show(struct iet_volume *volume, struct seq_file *seq) +{ + struct blockio_data *bio_data = volume->private; + + /* Used to display blockio volume info in /proc/net/iet/volumes */ + seq_printf(seq, " path:%s\n", bio_data->path); +} + +struct iotype blockio = { + .name = "blockio", + .attach = blockio_attach, + .make_request = blockio_make_request, + .detach = blockio_detach, + .show = blockio_show, +}; --- linux-2.6.27.orig/ubuntu/iscsitarget/file-io.c +++ linux-2.6.27/ubuntu/iscsitarget/file-io.c @@ -0,0 +1,307 @@ +/* + * Target device file I/O. + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +struct fileio_data { + char *path; + struct file *filp; +}; + +static int fileio_make_request(struct iet_volume *lu, struct tio *tio, int rw) +{ + struct fileio_data *p = lu->private; + struct file *filp; + mm_segment_t oldfs; + struct page *page; + u32 offset, size; + loff_t ppos, count; + char *buf; + int i, err = 0; + ssize_t ret; + + assert(p); + filp = p->filp; + size = tio->size; + offset= tio->offset; + + ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT; + ppos += offset; + + for (i = 0; i < tio->pg_cnt; i++) { + page = tio->pvec[i]; + assert(page); + buf = page_address(page); + buf += offset; + + if (offset + size > PAGE_CACHE_SIZE) + count = PAGE_CACHE_SIZE - offset; + else + count = size; + + oldfs = get_fs(); + set_fs(get_ds()); + + if (rw == READ) + ret = do_sync_read(filp, buf, count, &ppos); + else + ret = do_sync_write(filp, buf, count, &ppos); + + set_fs(oldfs); + + if (ret != count) { + eprintk("I/O error %lld, %ld\n", count, (long) ret); + err = -EIO; + } + + size -= count; + offset = 0; + } + assert(!size); + + return err; +} + +static int fileio_sync(struct iet_volume *lu, struct tio *tio) +{ + struct fileio_data *p = lu->private; + struct inode *inode = p->filp->f_dentry->d_inode; + struct address_space *mapping = inode->i_mapping; + loff_t ppos, count; + int res; + + if (tio) { + ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT; + count = tio->size; + } else { + ppos = 0; + count = lu->blk_cnt << lu->blk_shift; + } + + res = sync_page_range(inode, mapping, ppos, count); + if (res) { + eprintk("I/O error: syncing pages failed: %d\n", res); + return -EIO; + } else + return 0; +} + +static int open_path(struct iet_volume *volume, const char *path) +{ + int err = 0; + struct fileio_data *info = volume->private; + struct file *filp; + mm_segment_t oldfs; + int flags; + + info->path = kstrdup(path, GFP_KERNEL); + if (!info->path) + return -ENOMEM; + + oldfs = get_fs(); + set_fs(get_ds()); + flags = (LUReadonly(volume) ? O_RDONLY : O_RDWR) | O_LARGEFILE; + filp = filp_open(path, flags, 0); + set_fs(oldfs); + + if (IS_ERR(filp)) { + err = PTR_ERR(filp); + eprintk("Can't open %s %d\n", path, err); + info->filp = NULL; + } else + info->filp = filp; + + return err; +} + +static int set_scsiid(struct iet_volume *volume, const char *id) +{ + size_t len; + + if ((len = strlen(id)) > SCSI_ID_LEN - VENDOR_ID_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max\n", len, + SCSI_ID_LEN - VENDOR_ID_LEN); + return -EINVAL; + } + + memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len); + + return 0; +} + +static void gen_scsiid(struct iet_volume *volume, struct inode *inode) +{ + int i; + u32 *p; + + strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); + + for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++) + if (volume->scsi_id[i]) + return; + + p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN); + *(p + 0) = volume->target->trgt_param.target_type; + *(p + 1) = volume->target->tid; + *(p + 2) = (unsigned int) inode->i_ino; + *(p + 3) = (unsigned int) inode->i_sb->s_dev; +} + +static int set_scsisn(struct iet_volume *volume, const char *sn) +{ + size_t len; + + if ((len = strlen(sn)) > SCSI_SN_LEN) { + eprintk("SCSI SN too long, %zd provided, %u max\n", len, + SCSI_SN_LEN); + return -EINVAL; + } + memcpy(volume->scsi_sn, sn, len); + return 0; +} + +enum { + Opt_scsiid, Opt_scsisn, Opt_path, Opt_ignore, Opt_err, +}; + +static match_table_t tokens = { + {Opt_scsiid, "ScsiId=%s"}, + {Opt_scsisn, "ScsiSN=%s"}, + {Opt_path, "Path=%s"}, + {Opt_ignore, "Type=%s"}, + {Opt_ignore, "IOMode=%s"}, + {Opt_err, NULL}, +}; + +static int parse_fileio_params(struct iet_volume *volume, char *params) +{ + int err = 0; + char *p, *q; + + while ((p = strsep(¶ms, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + if (!*p) + continue; + token = match_token(p, tokens, args); + switch (token) { + case Opt_scsiid: + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = set_scsiid(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case Opt_scsisn: + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = set_scsisn(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case Opt_path: + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = open_path(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case Opt_ignore: + break; + default: + eprintk("Unknown %s\n", p); + return -EINVAL; + } + } + +out: + return err; +} + +static void fileio_detach(struct iet_volume *lu) +{ + struct fileio_data *p = lu->private; + + kfree(p->path); + if (p->filp) + filp_close(p->filp, NULL); + kfree(p); + lu->private = NULL; +} + +static int fileio_attach(struct iet_volume *lu, char *args) +{ + int err = 0; + struct fileio_data *p; + struct inode *inode; + + if (lu->private) { + printk("already attached ? %d\n", lu->lun); + return -EBUSY; + } + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + lu->private = p; + + if ((err = parse_fileio_params(lu, args)) < 0) { + eprintk("%d\n", err); + goto out; + } + inode = p->filp->f_dentry->d_inode; + + gen_scsiid(lu, inode); + + if (S_ISREG(inode->i_mode)) + ; + else if (S_ISBLK(inode->i_mode)) + inode = inode->i_bdev->bd_inode; + else { + err = -EINVAL; + goto out; + } + + lu->blk_shift = SECTOR_SIZE_BITS; + lu->blk_cnt = inode->i_size >> lu->blk_shift; + +out: + if (err < 0) + fileio_detach(lu); + return err; +} + +void fileio_show(struct iet_volume *lu, struct seq_file *seq) +{ + struct fileio_data *p = lu->private; + seq_printf(seq, " path:%s\n", p->path); +} + +struct iotype fileio = +{ + .name = "fileio", + .attach = fileio_attach, + .make_request = fileio_make_request, + .sync = fileio_sync, + .detach = fileio_detach, + .show = fileio_show, +}; --- linux-2.6.27.orig/ubuntu/iscsitarget/session.c +++ linux-2.6.27/ubuntu/iscsitarget/session.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include "iscsi.h" +#include "iscsi_dbg.h" + +struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid) +{ + struct iscsi_session *session; + + list_for_each_entry(session, &target->session_list, list) { + if (session->sid == sid) + return session; + } + return NULL; +} + +static struct iscsi_session * +iet_session_alloc(struct iscsi_target *target, struct session_info *info) +{ + int i; + struct iscsi_session *session; + + dprintk(D_SETUP, "%p %u %#Lx\n", target, target->tid, + (unsigned long long) info->sid); + + session = kzalloc(sizeof(*session), GFP_KERNEL); + if (!session) + return NULL; + + session->target = target; + session->sid = info->sid; + memcpy(&session->param, &target->sess_param, sizeof(session->param)); + session->max_queued_cmnds = target->trgt_param.queued_cmnds; + + session->exp_cmd_sn = info->exp_cmd_sn; + session->max_cmd_sn = info->max_cmd_sn; + + session->initiator = kstrdup(info->initiator_name, GFP_KERNEL); + if (!session->initiator) { + kfree(session); + return NULL; + } + + INIT_LIST_HEAD(&session->conn_list); + INIT_LIST_HEAD(&session->pending_list); + + spin_lock_init(&session->cmnd_hash_lock); + for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) + INIT_LIST_HEAD(&session->cmnd_hash[i]); + + session->next_ttt = 1; + + list_add(&session->list, &target->session_list); + + return session; +} + +static int session_free(struct iscsi_session *session) +{ + int i; + + dprintk(D_SETUP, "%#Lx\n", (unsigned long long) session->sid); + + assert(list_empty(&session->conn_list)); + + for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) { + if (!list_empty(&session->cmnd_hash[i])) + BUG(); + } + + list_del(&session->list); + + kfree(session->initiator); + kfree(session); + + return 0; +} + +int session_add(struct iscsi_target *target, struct session_info *info) +{ + struct iscsi_session *session; + int err = -EEXIST; + + session = session_lookup(target, info->sid); + if (session) + return err; + + session = iet_session_alloc(target, info); + if (!session) + err = -ENOMEM; + + return err; +} + +int session_del(struct iscsi_target *target, u64 sid) +{ + struct iscsi_session *session; + + session = session_lookup(target, sid); + if (!session) + return -ENOENT; + + if (!list_empty(&session->conn_list)) { + eprintk("%llu still have connections\n", (unsigned long long) session->sid); + return -EBUSY; + } + + return session_free(session); +} + +static void iet_session_info_show(struct seq_file *seq, struct iscsi_target *target) +{ + struct iscsi_session *session; + + list_for_each_entry(session, &target->session_list, list) { + seq_printf(seq, "\tsid:%llu initiator:%s\n", + (unsigned long long) session->sid, session->initiator); + conn_info_show(seq, session); + } +} + +static int iet_sessions_info_show(struct seq_file *seq, void *v) +{ + return iet_info_show(seq, iet_session_info_show); +} + +static int iet_session_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, iet_sessions_info_show, NULL); +} + +struct file_operations session_seq_fops = { + .owner = THIS_MODULE, + .open = iet_session_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; --- linux-2.6.27.orig/ubuntu/iscsitarget/param.c +++ linux-2.6.27/ubuntu/iscsitarget/param.c @@ -0,0 +1,194 @@ +/* + * (C) 2005 FUJITA Tomonori + * + * This code is licenced under the GPL. + */ + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "digest.h" + +struct target_type *target_type_array[] = { + &disk_ops, +}; + +#define CHECK_PARAM(info, iparam, word, min, max) \ +do { \ + if (!info->partial || (info->partial & 1 << key_##word)) \ + if (iparam[key_##word] < min || \ + iparam[key_##word] > max) { \ + eprintk("%s: %u is out of range (%u %u)\n", \ + #word, iparam[key_##word], min, max); \ + iparam[key_##word] = min; \ + } \ +} while (0) + +#define SET_PARAM(param, info, iparam, word) \ +({ \ + int changed = 0; \ + if (!info->partial || (info->partial & 1 << key_##word)) { \ + if (param->word != iparam[key_##word]) \ + changed = 1; \ + param->word = iparam[key_##word]; \ + } \ + changed; \ +}) + +#define GET_PARAM(param, info, iparam, word) \ +do { \ + iparam[key_##word] = param->word; \ +} while (0) + +static void sess_param_check(struct iscsi_param_info *info) +{ + u32 *iparam = info->session_param; + + CHECK_PARAM(info, iparam, max_connections, 1, 1); + CHECK_PARAM(info, iparam, max_recv_data_length, 512, + (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE)); + CHECK_PARAM(info, iparam, max_xmit_data_length, 512, + (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE)); + CHECK_PARAM(info, iparam, error_recovery_level, 0, 0); + CHECK_PARAM(info, iparam, data_pdu_inorder, 1, 1); + CHECK_PARAM(info, iparam, data_sequence_inorder, 1, 1); + + digest_alg_available(&iparam[key_header_digest]); + digest_alg_available(&iparam[key_data_digest]); + + CHECK_PARAM(info, iparam, ofmarker, 0, 0); + CHECK_PARAM(info, iparam, ifmarker, 0, 0); +} + +static void sess_param_set(struct iscsi_sess_param *param, struct iscsi_param_info *info) +{ + u32 *iparam = info->session_param; + + SET_PARAM(param, info, iparam, initial_r2t); + SET_PARAM(param, info, iparam, immediate_data); + SET_PARAM(param, info, iparam, max_connections); + SET_PARAM(param, info, iparam, max_recv_data_length); + SET_PARAM(param, info, iparam, max_xmit_data_length); + SET_PARAM(param, info, iparam, max_burst_length); + SET_PARAM(param, info, iparam, first_burst_length); + SET_PARAM(param, info, iparam, default_wait_time); + SET_PARAM(param, info, iparam, default_retain_time); + SET_PARAM(param, info, iparam, max_outstanding_r2t); + SET_PARAM(param, info, iparam, data_pdu_inorder); + SET_PARAM(param, info, iparam, data_sequence_inorder); + SET_PARAM(param, info, iparam, error_recovery_level); + SET_PARAM(param, info, iparam, header_digest); + SET_PARAM(param, info, iparam, data_digest); + SET_PARAM(param, info, iparam, ofmarker); + SET_PARAM(param, info, iparam, ifmarker); + SET_PARAM(param, info, iparam, ofmarkint); + SET_PARAM(param, info, iparam, ifmarkint); +} + +static void sess_param_get(struct iscsi_sess_param *param, struct iscsi_param_info *info) +{ + u32 *iparam = info->session_param; + + GET_PARAM(param, info, iparam, initial_r2t); + GET_PARAM(param, info, iparam, immediate_data); + GET_PARAM(param, info, iparam, max_connections); + GET_PARAM(param, info, iparam, max_recv_data_length); + GET_PARAM(param, info, iparam, max_xmit_data_length); + GET_PARAM(param, info, iparam, max_burst_length); + GET_PARAM(param, info, iparam, first_burst_length); + GET_PARAM(param, info, iparam, default_wait_time); + GET_PARAM(param, info, iparam, default_retain_time); + GET_PARAM(param, info, iparam, max_outstanding_r2t); + GET_PARAM(param, info, iparam, data_pdu_inorder); + GET_PARAM(param, info, iparam, data_sequence_inorder); + GET_PARAM(param, info, iparam, error_recovery_level); + GET_PARAM(param, info, iparam, header_digest); + GET_PARAM(param, info, iparam, data_digest); + GET_PARAM(param, info, iparam, ofmarker); + GET_PARAM(param, info, iparam, ifmarker); + GET_PARAM(param, info, iparam, ofmarkint); + GET_PARAM(param, info, iparam, ifmarkint); +} + +static void trgt_param_check(struct iscsi_param_info *info) +{ + u32 *iparam = info->target_param; + + CHECK_PARAM(info, iparam, wthreads, MIN_NR_WTHREADS, MAX_NR_WTHREADS); + CHECK_PARAM(info, iparam, target_type, 0, + (unsigned int) ARRAY_SIZE(target_type_array) - 1); + CHECK_PARAM(info, iparam, queued_cmnds, MIN_NR_QUEUED_CMNDS, MAX_NR_QUEUED_CMNDS); +} + +static void trgt_param_set(struct iscsi_target *target, struct iscsi_param_info *info) +{ + struct iscsi_trgt_param *param = &target->trgt_param; + u32 *iparam = info->target_param; + + if (SET_PARAM(param, info, iparam, wthreads)) + wthread_start(target); + SET_PARAM(param, info, iparam, target_type); + SET_PARAM(param, info, iparam, queued_cmnds); +} + +static void trgt_param_get(struct iscsi_trgt_param *param, struct iscsi_param_info *info) +{ + u32 *iparam = info->target_param; + + GET_PARAM(param, info, iparam, wthreads); + GET_PARAM(param, info, iparam, target_type); + GET_PARAM(param, info, iparam, queued_cmnds); +} + +static int trgt_param(struct iscsi_target *target, struct iscsi_param_info *info, int set) +{ + + if (set) { + trgt_param_check(info); + trgt_param_set(target, info); + } else + trgt_param_get(&target->trgt_param, info); + + return 0; +} + +static int sess_param(struct iscsi_target *target, struct iscsi_param_info *info, int set) +{ + struct iscsi_session *session = NULL; + struct iscsi_sess_param *param; + int err = -ENOENT; + + if (set) + sess_param_check(info); + + if (info->sid) { + if (!(session = session_lookup(target, info->sid))) + goto out; + param = &session->param; + } else { + param = &target->sess_param; + } + + if (set) { + sess_param_set(param, info); + show_param(param); + } else + sess_param_get(param, info); + + err = 0; +out: + return err; +} + +int iscsi_param_set(struct iscsi_target *target, struct iscsi_param_info *info, int set) +{ + int err; + + if (info->param_type == key_session) + err = sess_param(target, info, set); + else if (info->param_type == key_target) + err = trgt_param(target, info, set); + else + err = -EINVAL; + + return err; +} --- linux-2.6.27.orig/ubuntu/iscsitarget/iotype.h +++ linux-2.6.27/ubuntu/iscsitarget/iotype.h @@ -0,0 +1,29 @@ +/* + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include "iscsi.h" + +#ifndef __IOTYPE_H__ +#define __IOTYPE_H__ + +struct iotype { + const char *name; + struct list_head iot_list; + + int (*attach)(struct iet_volume *dev, char *args); + int (*make_request)(struct iet_volume *dev, struct tio *tio, int rw); + int (*sync)(struct iet_volume *dev, struct tio *tio); + void (*detach)(struct iet_volume *dev); + void (*show)(struct iet_volume *dev, struct seq_file *seq); +}; + +extern struct iotype fileio; +extern struct iotype nullio; +extern struct iotype blockio; + +extern int iotype_init(void); +extern void iotype_exit(void); + +#endif --- linux-2.6.27.orig/ubuntu/iscsitarget/wthread.c +++ linux-2.6.27/ubuntu/iscsitarget/wthread.c @@ -0,0 +1,187 @@ +/* + * Worker thread. + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" + +void wthread_queue(struct iscsi_cmnd *cmnd) +{ + struct worker_thread_info *info = &cmnd->conn->session->target->wthread_info; + + if (!list_empty(&cmnd->list)) { + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + eprintk("%x %p %x %x %x %x %lx %x\n", + cmnd_itt(cmnd), req, req->opcode, req->scb[0], cmnd->pdu.datasize, + be32_to_cpu(req->data_length), cmnd->flags, req->flags); + + if (cmnd->lun) + eprintk("%u\n", cmnd->lun->lun); + assert(list_empty(&cmnd->list)); + } + + spin_lock(&info->wthread_lock); + list_add_tail(&cmnd->list, &info->work_queue); + spin_unlock(&info->wthread_lock); + + atomic_inc(&cmnd->conn->nr_busy_cmnds); + + wake_up(&info->wthread_sleep); +} + +static struct iscsi_cmnd * get_ready_cmnd(struct worker_thread_info *info) +{ + struct iscsi_cmnd *cmnd = NULL; + + spin_lock(&info->wthread_lock); + if (!list_empty(&info->work_queue)) { + cmnd = list_entry(info->work_queue.next, struct iscsi_cmnd, list); + list_del_init(&cmnd->list); + + assert(cmnd->conn); + } + spin_unlock(&info->wthread_lock); + + return cmnd; +} + +static int cmnd_execute(struct iscsi_cmnd *cmnd) +{ + int type = cmnd->conn->session->target->trgt_param.target_type; + + assert(target_type_array[type]->execute_cmnd); + return target_type_array[type]->execute_cmnd(cmnd); +} + +static int worker_thread(void *arg) +{ + struct worker_thread *wt = (struct worker_thread *) arg; + struct worker_thread_info *info = wt->w_info; + struct iscsi_cmnd *cmnd; + struct iscsi_conn *conn; + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&info->wthread_sleep, &wait); + + __set_current_state(TASK_RUNNING); + do { + while (!list_empty(&info->work_queue) && + (cmnd = get_ready_cmnd(info))) { + conn = cmnd->conn; + cmnd_execute(cmnd); + assert(conn); + atomic_dec(&conn->nr_busy_cmnds); + } + + __set_current_state(TASK_INTERRUPTIBLE); + if (list_empty(&info->work_queue)) + schedule(); + + __set_current_state(TASK_RUNNING); + } while (!kthread_should_stop()); + + remove_wait_queue(&info->wthread_sleep, &wait); + + return 0; +} + +static int start_one_worker_thread(struct iscsi_target *target) +{ + struct worker_thread_info *info = &target->wthread_info; + struct worker_thread *wt; + struct task_struct *task; + + if (!(wt = kmalloc(sizeof(struct worker_thread), GFP_KERNEL))) + return -ENOMEM; + + wt->w_info = info; + task = kthread_create(worker_thread, wt, "istiod%d", target->tid); + if (IS_ERR(task)) { + kfree(wt); + return PTR_ERR(task); + } + + wt->w_task = task; + list_add(&wt->w_list, &info->wthread_list); + info->nr_running_wthreads++; + + wake_up_process(task); + + return 0; +} + +static int stop_one_worker_thread(struct worker_thread *wt) +{ + struct worker_thread_info *info = wt->w_info; + int err; + + assert(wt->w_task); + if ((err = kthread_stop(wt->w_task)) < 0) + return err; + + list_del(&wt->w_list); + kfree(wt); + info->nr_running_wthreads--; + + return 0; +} + +int wthread_init(struct iscsi_target *target) +{ + struct worker_thread_info *info = &target->wthread_info; + + spin_lock_init(&info->wthread_lock); + + info->nr_running_wthreads = 0; + + INIT_LIST_HEAD(&info->work_queue); + INIT_LIST_HEAD(&info->wthread_list); + + init_waitqueue_head(&info->wthread_sleep); + + return 0; +} + +int wthread_start(struct iscsi_target *target) +{ + int err = 0; + struct worker_thread_info *info = &target->wthread_info; + + while (info->nr_running_wthreads < target->trgt_param.wthreads) { + if ((err = start_one_worker_thread(target)) < 0) { + eprintk("Fail to create a worker thread %d\n", err); + goto out; + } + } + + while (info->nr_running_wthreads > target->trgt_param.wthreads) { + struct worker_thread *wt; + wt = list_entry(info->wthread_list.next, struct worker_thread, w_list); + if ((err = stop_one_worker_thread(wt)) < 0) { + eprintk("Fail to stop a worker thread %d\n", err); + break; + } + } +out: + return err; +} + +int wthread_stop(struct iscsi_target *target) +{ + struct worker_thread *wt, *tmp; + int err = 0; + struct worker_thread_info *info = &target->wthread_info; + + list_for_each_entry_safe(wt, tmp, &info->wthread_list, w_list) { + if ((err = stop_one_worker_thread(wt)) < 0) { + eprintk("Fail to stop a worker thread %d\n", err); + return err; + } + } + + return err; +} --- linux-2.6.27.orig/ubuntu/iscsitarget/digest.c +++ linux-2.6.27/ubuntu/iscsitarget/digest.c @@ -0,0 +1,277 @@ +/* + * iSCSI digest handling. + * (C) 2004 - 2006 Xiranet Communications GmbH + * This code is licensed under the GPL. + */ + +#include +#include + +#include "iscsi.h" +#include "digest.h" +#include "iscsi_dbg.h" + +void digest_alg_available(unsigned int *val) +{ + if (*val & DIGEST_CRC32C && + !crypto_has_alg("crc32c", 0, CRYPTO_ALG_ASYNC)) { + printk("CRC32C digest algorithm not available in kernel\n"); + *val |= ~DIGEST_CRC32C; + } +} + +/** + * initialize support for digest calculation. + * + * digest_init - + * @conn: ptr to connection to make use of digests + * + * @return: 0 on success, < 0 on error + */ +int digest_init(struct iscsi_conn *conn) +{ + int err = 0; + + if (!(conn->hdigest_type & DIGEST_ALL)) + conn->hdigest_type = DIGEST_NONE; + + if (!(conn->ddigest_type & DIGEST_ALL)) + conn->ddigest_type = DIGEST_NONE; + + if (conn->hdigest_type & DIGEST_CRC32C || + conn->ddigest_type & DIGEST_CRC32C) { + conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, + CRYPTO_ALG_ASYNC); + conn->rx_hash.flags = 0; + if (IS_ERR(conn->rx_hash.tfm)) { + conn->rx_hash.tfm = NULL; + err = -ENOMEM; + goto out; + } + + conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, + CRYPTO_ALG_ASYNC); + conn->tx_hash.flags = 0; + if (IS_ERR(conn->tx_hash.tfm)) { + conn->tx_hash.tfm = NULL; + err = -ENOMEM; + goto out; + } + } + +out: + if (err) + digest_cleanup(conn); + + return err; +} + +/** + * free resources used for digest calculation. + * + * digest_cleanup - + * @conn: ptr to connection that made use of digests + */ +void digest_cleanup(struct iscsi_conn *conn) +{ + if (conn->tx_hash.tfm) + crypto_free_hash(conn->tx_hash.tfm); + if (conn->rx_hash.tfm) + crypto_free_hash(conn->rx_hash.tfm); +} + +/** + * debug handling of header digest errors: + * simulates a digest error after n PDUs / every n-th PDU of type + * HDIGEST_ERR_CORRUPT_PDU_TYPE. + */ +static inline void __dbg_simulate_header_digest_error(struct iscsi_cmnd *cmnd) +{ +#define HDIGEST_ERR_AFTER_N_CMNDS 1000 +#define HDIGEST_ERR_ONLY_ONCE 1 +#define HDIGEST_ERR_CORRUPT_PDU_TYPE ISCSI_OP_SCSI_CMD +#define HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY 0 + + static int num_cmnds = 0; + static int num_errs = 0; + + if (cmnd_opcode(cmnd) == HDIGEST_ERR_CORRUPT_PDU_TYPE) { + if (HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY) { + if (cmnd->pdu.datasize) + num_cmnds++; + } else + num_cmnds++; + } + + if ((num_cmnds == HDIGEST_ERR_AFTER_N_CMNDS) + && (!(HDIGEST_ERR_ONLY_ONCE && num_errs))) { + printk("*** Faking header digest error ***\n"); + printk("\tcmnd: 0x%x, itt 0x%x, sn 0x%x\n", + cmnd_opcode(cmnd), + be32_to_cpu(cmnd->pdu.bhs.itt), + be32_to_cpu(cmnd->pdu.bhs.sn)); + cmnd->hdigest = ~cmnd->hdigest; + /* make things even worse by manipulating header fields */ + cmnd->pdu.datasize += 8; + num_errs++; + num_cmnds = 0; + } + return; +} + +/** + * debug handling of data digest errors: + * simulates a digest error after n PDUs / every n-th PDU of type + * DDIGEST_ERR_CORRUPT_PDU_TYPE. + */ +static inline void __dbg_simulate_data_digest_error(struct iscsi_cmnd *cmnd) +{ +#define DDIGEST_ERR_AFTER_N_CMNDS 50 +#define DDIGEST_ERR_ONLY_ONCE 1 +#define DDIGEST_ERR_CORRUPT_PDU_TYPE ISCSI_OP_SCSI_DATA_OUT +#define DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY 0 + + static int num_cmnds = 0; + static int num_errs = 0; + + if ((cmnd->pdu.datasize) + && (cmnd_opcode(cmnd) == DDIGEST_ERR_CORRUPT_PDU_TYPE)) { + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_SCSI_DATA_OUT: + if ((DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY) + && (cmnd->pdu.bhs.ttt != ISCSI_RESERVED_TAG)) + break; + default: + num_cmnds++; + } + } + + if ((num_cmnds == DDIGEST_ERR_AFTER_N_CMNDS) + && (!(DDIGEST_ERR_ONLY_ONCE && num_errs)) + && (cmnd->pdu.datasize) + && (!cmnd->conn->read_overflow)) { + printk("*** Faking data digest error: ***"); + printk("\tcmnd 0x%x, itt 0x%x, sn 0x%x\n", + cmnd_opcode(cmnd), + be32_to_cpu(cmnd->pdu.bhs.itt), + be32_to_cpu(cmnd->pdu.bhs.sn)); + cmnd->ddigest = ~cmnd->ddigest; + num_errs++; + num_cmnds = 0; + } +} + +static void digest_header(struct hash_desc *hash, struct iscsi_pdu *pdu, + u8 *crc) +{ + struct scatterlist sg[2]; + unsigned int nbytes = sizeof(struct iscsi_hdr); + + sg_init_table(sg, pdu->ahssize ? 2 : 1); + + sg_set_buf(&sg[0], &pdu->bhs, nbytes); + if (pdu->ahssize) { + sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize); + nbytes += pdu->ahssize; + } + + crypto_hash_init(hash); + crypto_hash_update(hash, sg, nbytes); + crypto_hash_final(hash, crc); +} + +int digest_rx_header(struct iscsi_cmnd *cmnd) +{ + u32 crc; + + digest_header(&cmnd->conn->rx_hash, &cmnd->pdu, (u8 *) &crc); + if (crc != cmnd->hdigest) + return -EIO; + + return 0; +} + +void digest_tx_header(struct iscsi_cmnd *cmnd) +{ + digest_header(&cmnd->conn->tx_hash, &cmnd->pdu, (u8 *) &cmnd->hdigest); +} + +static void digest_data(struct hash_desc *hash, struct iscsi_cmnd *cmnd, + struct tio *tio, u32 offset, u8 *crc) +{ + struct scatterlist *sg = cmnd->conn->hash_sg; + u32 size, length; + int i, idx, count; + unsigned int nbytes; + + size = cmnd->pdu.datasize; + nbytes = size = (size + 3) & ~3; + + offset += tio->offset; + idx = offset >> PAGE_CACHE_SHIFT; + offset &= ~PAGE_CACHE_MASK; + count = get_pgcnt(size, offset); + assert(idx + count <= tio->pg_cnt); + + assert(count <= ISCSI_CONN_IOV_MAX); + + crypto_hash_init(hash); + + for (i = 0; size; i++) { + if (offset + size > PAGE_CACHE_SIZE) + length = PAGE_CACHE_SIZE - offset; + else + length = size; + + sg_set_page(&sg[i], tio->pvec[idx + i], length, offset); + size -= length; + offset = 0; + } + + crypto_hash_update(hash, sg, nbytes); + crypto_hash_final(hash, crc); +} + +int digest_rx_data(struct iscsi_cmnd *cmnd) +{ + struct tio *tio; + struct iscsi_cmnd *scsi_cmnd; + struct iscsi_data_out_hdr *req; + u32 offset, crc; + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_SCSI_REJECT: + case ISCSI_OP_PDU_REJECT: + case ISCSI_OP_DATA_REJECT: + return 0; + case ISCSI_OP_SCSI_DATA_OUT: + scsi_cmnd = cmnd->req; + req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs; + tio = scsi_cmnd->tio; + offset = be32_to_cpu(req->buffer_offset); + break; + default: + tio = cmnd->tio; + offset = 0; + } + + digest_data(&cmnd->conn->rx_hash, cmnd, tio, offset, (u8 *) &crc); + + if (!cmnd->conn->read_overflow && + (cmnd_opcode(cmnd) != ISCSI_OP_PDU_REJECT)) { + if (crc != cmnd->ddigest) + return -EIO; + } + + return 0; +} + +void digest_tx_data(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs; + + assert(tio); + digest_data(&cmnd->conn->tx_hash, cmnd, tio, + be32_to_cpu(req->buffer_offset), (u8 *) &cmnd->ddigest); +} --- linux-2.6.27.orig/ubuntu/iscsitarget/iotype.c +++ linux-2.6.27/ubuntu/iscsitarget/iotype.c @@ -0,0 +1,110 @@ +/* + * Manager for various I/O types. + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include "iscsi.h" +#include "iotype.h" +#include "iscsi_dbg.h" + +static LIST_HEAD(iotypes); +static rwlock_t iotypes_lock = RW_LOCK_UNLOCKED; + +static struct iotype *find_iotype(const char *name) +{ + struct iotype *iot = NULL; + + list_for_each_entry(iot, &iotypes, iot_list) { + if (strcmp(iot->name, name) == 0) + return iot; + } + return NULL; +} + +struct iotype *get_iotype(const char *name) +{ + struct iotype *iot; + + read_lock(&iotypes_lock); + iot = find_iotype(name); + read_unlock(&iotypes_lock); + + return iot; +} + +void put_iotype(struct iotype *iot) +{ + if (!iot) + return; + return; +} + +static int register_iotype(struct iotype *iot) +{ + int err = 0; + struct iotype *p; + + write_lock(&iotypes_lock); + + p = find_iotype(iot->name); + if (p) + err = -EBUSY; + else + list_add_tail(&iot->iot_list, &iotypes); + + write_unlock(&iotypes_lock); + + return err; +} + +static int unregister_iotype(struct iotype *iot) +{ + int err = 0; + struct iotype *p; + + write_lock(&iotypes_lock); + + p = find_iotype(iot->name); + if (p && p == iot) + list_del_init(&iot->iot_list); + else + err = -EINVAL; + + write_unlock(&iotypes_lock); + + + return err; +} + +struct iotype *iotype_array[] = { + &fileio, + &blockio, + &nullio, +}; + +int iotype_init(void) +{ + int i, err; + + for (i = 0; i < ARRAY_SIZE(iotype_array); i++) { + if (!(err = register_iotype(iotype_array[i]))) + iprintk("Registered io type %s\n", + iotype_array[i]->name); + else { + eprintk("Failed to register io type %s\n", + iotype_array[i]->name); + break; + } + } + + return err; +} + +void iotype_exit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(iotype_array); i++) + unregister_iotype(iotype_array[i]); +} --- linux-2.6.27.orig/ubuntu/iscsitarget/iscsi_hdr.h +++ linux-2.6.27/ubuntu/iscsitarget/iscsi_hdr.h @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef __ISCSI_HDR_H__ +#define __ISCSI_HDR_H__ + +#include +#include + +#define ISCSI_VERSION 0 + +#ifndef __packed +#define __packed __attribute__ ((packed)) +#endif + +struct iscsi_hdr { + u8 opcode; /* 0 */ + u8 flags; + u8 spec1[2]; +#if defined(__BIG_ENDIAN_BITFIELD) + struct { /* 4 */ + unsigned ahslength : 8; + unsigned datalength : 24; + } length; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + u32 length; /* 4 */ +#endif + u16 lun[4]; /* 8 */ + u32 itt; /* 16 */ + u32 ttt; /* 20 */ + u32 sn; /* 24 */ + u32 exp_sn; /* 28 */ + u32 max_sn; /* 32 */ + u32 spec3[3]; /* 36 */ +} __packed; /* 48 */ + +/* Opcode encoding bits */ +#define ISCSI_OP_RETRY 0x80 +#define ISCSI_OP_IMMEDIATE 0x40 +#define ISCSI_OPCODE_MASK 0x3F + +/* Client to Server Message Opcode values */ +#define ISCSI_OP_NOOP_OUT 0x00 +#define ISCSI_OP_SCSI_CMD 0x01 +#define ISCSI_OP_SCSI_TASK_MGT_MSG 0x02 +#define ISCSI_OP_LOGIN_CMD 0x03 +#define ISCSI_OP_TEXT_CMD 0x04 +#define ISCSI_OP_SCSI_DATA_OUT 0x05 +#define ISCSI_OP_LOGOUT_CMD 0x06 +#define ISCSI_OP_SNACK_CMD 0x10 + +#define ISCSI_OP_VENDOR1_CMD 0x1c +#define ISCSI_OP_VENDOR2_CMD 0x1d +#define ISCSI_OP_VENDOR3_CMD 0x1e +#define ISCSI_OP_VENDOR4_CMD 0x1f + +/* Server to Client Message Opcode values */ +#define ISCSI_OP_NOOP_IN 0x20 +#define ISCSI_OP_SCSI_RSP 0x21 +#define ISCSI_OP_SCSI_TASK_MGT_RSP 0x22 +#define ISCSI_OP_LOGIN_RSP 0x23 +#define ISCSI_OP_TEXT_RSP 0x24 +#define ISCSI_OP_SCSI_DATA_IN 0x25 +#define ISCSI_OP_LOGOUT_RSP 0x26 +#define ISCSI_OP_R2T 0x31 +#define ISCSI_OP_ASYNC_MSG 0x32 +#define ISCSI_OP_REJECT 0x3f + +struct iscsi_ahs_hdr { + u16 ahslength; + u8 ahstype; +} __packed; + +#define ISCSI_AHSTYPE_CDB 1 +#define ISCSI_AHSTYPE_RLENGTH 2 + +union iscsi_sid { + struct { + u8 isid[6]; /* Initiator Session ID */ + u16 tsih; /* Target Session ID */ + } id; + u64 id64; +} __packed; + +struct iscsi_scsi_cmd_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 data_length; + u32 cmd_sn; + u32 exp_stat_sn; + u8 scb[16]; +} __packed; + +#define ISCSI_CMD_FINAL 0x80 +#define ISCSI_CMD_READ 0x40 +#define ISCSI_CMD_WRITE 0x20 +#define ISCSI_CMD_ATTR_MASK 0x07 +#define ISCSI_CMD_UNTAGGED 0x00 +#define ISCSI_CMD_SIMPLE 0x01 +#define ISCSI_CMD_ORDERED 0x02 +#define ISCSI_CMD_HEAD_OF_QUEUE 0x03 +#define ISCSI_CMD_ACA 0x04 + +struct iscsi_cdb_ahdr { + u16 ahslength; + u8 ahstype; + u8 reserved; + u8 cdb[0]; +} __packed; + +struct iscsi_rlength_ahdr { + u16 ahslength; + u8 ahstype; + u8 reserved; + u32 read_length; +} __packed; + +struct iscsi_scsi_rsp_hdr { + u8 opcode; + u8 flags; + u8 response; + u8 cmd_status; + u8 ahslength; + u8 datalength[3]; + u32 rsvd1[2]; + u32 itt; + u32 snack; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 exp_data_sn; + u32 bi_residual_count; + u32 residual_count; +} __packed; + +#define ISCSI_FLG_RESIDUAL_UNDERFLOW 0x02 +#define ISCSI_FLG_RESIDUAL_OVERFLOW 0x04 +#define ISCSI_FLG_BIRESIDUAL_UNDERFLOW 0x08 +#define ISCSI_FLG_BIRESIDUAL_OVERFLOW 0x10 + +#define ISCSI_RESPONSE_COMMAND_COMPLETED 0x00 +#define ISCSI_RESPONSE_TARGET_FAILURE 0x01 + +struct iscsi_sense_data { + u16 length; + u8 data[0]; +} __packed; + +struct iscsi_task_mgt_hdr { + u8 opcode; + u8 function; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 rtt; + u32 cmd_sn; + u32 exp_stat_sn; + u32 ref_cmd_sn; + u32 exp_data_sn; + u32 rsvd2[2]; +} __packed; + +#define ISCSI_FUNCTION_MASK 0x7f + +#define ISCSI_FUNCTION_ABORT_TASK 1 +#define ISCSI_FUNCTION_ABORT_TASK_SET 2 +#define ISCSI_FUNCTION_CLEAR_ACA 3 +#define ISCSI_FUNCTION_CLEAR_TASK_SET 4 +#define ISCSI_FUNCTION_LOGICAL_UNIT_RESET 5 +#define ISCSI_FUNCTION_TARGET_WARM_RESET 6 +#define ISCSI_FUNCTION_TARGET_COLD_RESET 7 +#define ISCSI_FUNCTION_TASK_REASSIGN 8 + +struct iscsi_task_rsp_hdr { + u8 opcode; + u8 flags; + u8 response; + u8 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 rsvd3; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd4[3]; +} __packed; + +#define ISCSI_RESPONSE_FUNCTION_COMPLETE 0 +#define ISCSI_RESPONSE_UNKNOWN_TASK 1 +#define ISCSI_RESPONSE_UNKNOWN_LUN 2 +#define ISCSI_RESPONSE_TASK_ALLEGIANT 3 +#define ISCSI_RESPONSE_FAILOVER_UNSUPPORTED 4 +#define ISCSI_RESPONSE_FUNCTION_UNSUPPORTED 5 +#define ISCSI_RESPONSE_NO_AUTHORIZATION 6 +#define ISCSI_RESPONSE_FUNCTION_REJECTED 255 + +struct iscsi_data_out_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 rsvd2; + u32 exp_stat_sn; + u32 rsvd3; + u32 data_sn; + u32 buffer_offset; + u32 rsvd4; +} __packed; + +struct iscsi_data_in_hdr { + u8 opcode; + u8 flags; + u8 rsvd1; + u8 cmd_status; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 data_sn; + u32 buffer_offset; + u32 residual_count; +} __packed; + +#define ISCSI_FLG_STATUS 0x01 + +struct iscsi_r2t_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 r2t_sn; + u32 buffer_offset; + u32 data_length; +} __packed; + +struct iscsi_async_msg_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 ffffffff; + u32 rsvd2; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u8 async_event; + u8 async_vcode; + u16 param1; + u16 param2; + u16 param3; + u32 rsvd3; +} __packed; + +#define ISCSI_ASYNC_SCSI 0 +#define ISCSI_ASYNC_LOGOUT 1 +#define ISCSI_ASYNC_DROP_CONNECTION 2 +#define ISCSI_ASYNC_DROP_SESSION 3 +#define ISCSI_ASYNC_PARAM_REQUEST 4 +#define ISCSI_ASYNC_VENDOR 255 + +struct iscsi_text_req_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd3[4]; +} __packed; + +struct iscsi_text_rsp_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd3[3]; +} __packed; + +struct iscsi_login_req_hdr { + u8 opcode; + u8 flags; + u8 max_version; /* Max. version supported */ + u8 min_version; /* Min. version supported */ + u8 ahslength; + u8 datalength[3]; + union iscsi_sid sid; + u32 itt; /* Initiator Task Tag */ + u16 cid; /* Connection ID */ + u16 rsvd1; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd2[4]; +} __packed; + +struct iscsi_login_rsp_hdr { + u8 opcode; + u8 flags; + u8 max_version; /* Max. version supported */ + u8 active_version; /* Active version */ + u8 ahslength; + u8 datalength[3]; + union iscsi_sid sid; + u32 itt; /* Initiator Task Tag */ + u32 rsvd1; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u8 status_class; /* see Login RSP ststus classes below */ + u8 status_detail; /* see Login RSP Status details below */ + u8 rsvd2[10]; +} __packed; + +#define ISCSI_FLG_FINAL 0x80 +#define ISCSI_FLG_TRANSIT 0x80 +#define ISCSI_FLG_CSG_SECURITY 0x00 +#define ISCSI_FLG_CSG_LOGIN 0x04 +#define ISCSI_FLG_CSG_FULL_FEATURE 0x0c +#define ISCSI_FLG_CSG_MASK 0x0c +#define ISCSI_FLG_NSG_SECURITY 0x00 +#define ISCSI_FLG_NSG_LOGIN 0x01 +#define ISCSI_FLG_NSG_FULL_FEATURE 0x03 +#define ISCSI_FLG_NSG_MASK 0x03 + +/* Login Status response classes */ +#define ISCSI_STATUS_SUCCESS 0x00 +#define ISCSI_STATUS_REDIRECT 0x01 +#define ISCSI_STATUS_INITIATOR_ERR 0x02 +#define ISCSI_STATUS_TARGET_ERR 0x03 + +/* Login Status response detail codes */ +/* Class-0 (Success) */ +#define ISCSI_STATUS_ACCEPT 0x00 + +/* Class-1 (Redirection) */ +#define ISCSI_STATUS_TGT_MOVED_TEMP 0x01 +#define ISCSI_STATUS_TGT_MOVED_PERM 0x02 + +/* Class-2 (Initiator Error) */ +#define ISCSI_STATUS_INIT_ERR 0x00 +#define ISCSI_STATUS_AUTH_FAILED 0x01 +#define ISCSI_STATUS_TGT_FORBIDDEN 0x02 +#define ISCSI_STATUS_TGT_NOT_FOUND 0x03 +#define ISCSI_STATUS_TGT_REMOVED 0x04 +#define ISCSI_STATUS_NO_VERSION 0x05 +#define ISCSI_STATUS_TOO_MANY_CONN 0x06 +#define ISCSI_STATUS_MISSING_FIELDS 0x07 +#define ISCSI_STATUS_CONN_ADD_FAILED 0x08 +#define ISCSI_STATUS_INV_SESSION_TYPE 0x09 +#define ISCSI_STATUS_SESSION_NOT_FOUND 0x0a +#define ISCSI_STATUS_INV_REQ_TYPE 0x0b + +/* Class-3 (Target Error) */ +#define ISCSI_STATUS_TARGET_ERROR 0x00 +#define ISCSI_STATUS_SVC_UNAVAILABLE 0x01 +#define ISCSI_STATUS_NO_RESOURCES 0x02 + +struct iscsi_logout_req_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u16 cid; + u16 rsvd3; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd4[4]; +} __packed; + +struct iscsi_logout_rsp_hdr { + u8 opcode; + u8 flags; + u8 response; + u8 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 rsvd3; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd4; + u16 time2wait; + u16 time2retain; + u32 rsvd5; +} __packed; + +struct iscsi_snack_req_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 rsvd3; + u32 exp_stat_sn; + u32 rsvd4[2]; + u32 beg_run; + u32 run_length; +} __packed; + +struct iscsi_reject_hdr { + u8 opcode; + u8 flags; + u8 reason; + u8 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 ffffffff; + u32 rsvd3; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 data_sn; + u32 rsvd4[2]; +} __packed; + +#define ISCSI_REASON_NO_FULL_FEATURE_PHASE 0x01 +#define ISCSI_REASON_DATA_DIGEST_ERROR 0x02 +#define ISCSI_REASON_DATA_SNACK_REJECT 0x03 +#define ISCSI_REASON_PROTOCOL_ERROR 0x04 +#define ISCSI_REASON_UNSUPPORTED_COMMAND 0x05 +#define ISCSI_REASON_IMMEDIATE_COMMAND_REJECT 0x06 +#define ISCSI_REASON_TASK_IN_PROGRESS 0x07 +#define ISCSI_REASON_INVALID_SNACK 0x08 +#define ISCSI_REASON_NO_BOOKMARK 0x09 +#define ISCSI_REASON_BOOKMARK_REJECT 0x0a +#define ISCSI_REASON_NEGOTIATION_RESET 0x0b +#define ISCSI_REASON_WAITING_LOGOUT 0x0c + + +struct iscsi_nop_out_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd2[4]; +} __packed; + +struct iscsi_nop_in_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd2[3]; +} __packed; + +#define ISCSI_RESERVED_TAG (0xffffffffU) + +#endif /* __ISCSI_HDR_H__ */ --- linux-2.6.27.orig/ubuntu/iscsitarget/volume.c +++ linux-2.6.27/ubuntu/iscsitarget/volume.c @@ -0,0 +1,262 @@ +/* + * Volume manager + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +#include + +struct iet_volume *volume_lookup(struct iscsi_target *target, u32 lun) +{ + struct iet_volume *volume; + + list_for_each_entry(volume, &target->volumes, list) { + if (volume->lun == lun) + return volume; + } + return NULL; +} + +enum { + Opt_type, + Opt_iomode, + Opt_err, +}; + +static match_table_t tokens = { + {Opt_type, "Type=%s"}, + {Opt_iomode, "IOMode=%s"}, + {Opt_err, NULL}, +}; + +static int set_iotype(struct iet_volume *volume, char *params) +{ + int err = 0; + substring_t args[MAX_OPT_ARGS]; + char *p, *argp = NULL, *buf = (char *) get_zeroed_page(GFP_USER); + + if (!buf) + return -ENOMEM; + strncpy(buf, params, PAGE_CACHE_SIZE); + + while ((p = strsep(&buf, ",")) != NULL) { + int token; + + if (!*p) + continue; + token = match_token(p, tokens, args); + switch (token) { + case Opt_type: + if (!(argp = match_strdup(&args[0]))) + err = -ENOMEM; + if (argp && !(volume->iotype = get_iotype(argp))) + err = -ENOENT; + kfree(argp); + break; + case Opt_iomode: + if (!(argp = match_strdup(&args[0]))) + err = -ENOMEM; + if (argp && !strcmp(argp, "ro")) + SetLUReadonly(volume); + else if (argp && !strcmp(argp, "wb")) + SetLUAsync(volume); + kfree(argp); + break; + default: + break; + } + } + + if (!err && !volume->iotype && !(volume->iotype = get_iotype("fileio"))) { + eprintk("%s\n", "Cannot find fileio"); + err = -EINVAL; + } + + free_page((unsigned long) buf); + + return err; +} + +int volume_add(struct iscsi_target *target, struct volume_info *info) +{ + int ret; + struct iet_volume *volume; + char *args; + + volume = volume_lookup(target, info->lun); + if (volume) + return -EEXIST; + + if (info->lun > 0x3fff) + return -EINVAL; + + volume = kzalloc(sizeof(*volume), GFP_KERNEL); + if (!volume) + return -ENOMEM; + + volume->target = target; + volume->lun = info->lun; + + args = kzalloc(info->args_len + 1, GFP_KERNEL); + if (!args) { + ret = -ENOMEM; + goto free_volume; + } + + ret = copy_from_user(args, (void *)(unsigned long)info->args_ptr, + info->args_len); + if (ret) { + ret = -EFAULT; + goto free_args; + } + + ret = set_iotype(volume, args); + if (ret < 0) + goto free_args; + + ret = volume->iotype->attach(volume, args); + if (ret < 0) + goto free_args; + + INIT_LIST_HEAD(&volume->queue.wait_list); + spin_lock_init(&volume->queue.queue_lock); + spin_lock_init(&volume->reserve_lock); + + volume->l_state = IDEV_RUNNING; + atomic_set(&volume->l_count, 0); + + list_add_tail(&volume->list, &target->volumes); + atomic_inc(&target->nr_volumes); + + kfree(args); + + return 0; +free_args: + kfree(args); +free_volume: + put_iotype(volume->iotype); + kfree(volume); + + return ret; +} + +void iscsi_volume_destroy(struct iet_volume *volume) +{ + assert(volume->l_state == IDEV_DEL); + assert(!atomic_read(&volume->l_count)); + + volume->iotype->detach(volume); + put_iotype(volume->iotype); + list_del(&volume->list); + kfree(volume); +} + +int iscsi_volume_del(struct iscsi_target *target, struct volume_info *info) +{ + struct iet_volume *volume; + + eprintk("%x %x\n", target->tid, info->lun); + if (!(volume = volume_lookup(target, info->lun))) + return -ENOENT; + + volume->l_state = IDEV_DEL; + atomic_dec(&target->nr_volumes); + if (!atomic_read(&volume->l_count)) + iscsi_volume_destroy(volume); + + return 0; +} + +struct iet_volume *volume_get(struct iscsi_target *target, u32 lun) +{ + struct iet_volume *volume; + + if ((volume = volume_lookup(target, lun))) { + if (volume->l_state == IDEV_RUNNING) + atomic_inc(&volume->l_count); + else + volume = NULL; + } + return volume; +} + +void volume_put(struct iet_volume *volume) +{ + if (atomic_dec_and_test(&volume->l_count) && volume->l_state == IDEV_DEL) + iscsi_volume_destroy(volume); +} + +int volume_reserve(struct iet_volume *volume, u64 sid) +{ + if (!volume) + return -ENOENT; + + spin_lock(&volume->reserve_lock); + if (volume->reserve_sid && volume->reserve_sid != sid) { + spin_unlock(&volume->reserve_lock); + return -EBUSY; + } + + volume->reserve_sid = sid; + spin_unlock(&volume->reserve_lock); + + return 0; +} + +int is_volume_reserved(struct iet_volume *volume, u64 sid) +{ + if (!volume || !volume->reserve_sid || volume->reserve_sid == sid) + return 0; + + return -EBUSY; +} + +int volume_release(struct iet_volume *volume, u64 sid, int force) +{ + if (force || volume->reserve_sid == sid) + volume->reserve_sid = 0; + + return 0; +} + +static void iet_volume_info_show(struct seq_file *seq, struct iscsi_target *target) +{ + struct iet_volume *volume; + + list_for_each_entry(volume, &target->volumes, list) { + seq_printf(seq, "\tlun:%u state:%x iotype:%s", + volume->lun, volume->l_state, volume->iotype->name); + if (LUReadonly(volume)) + seq_printf(seq, " iomode:ro"); + else if (LUAsync(volume)) + seq_printf(seq, " iomode:wb"); + else + seq_printf(seq, " iomode:wt"); + if (volume->iotype->show) + volume->iotype->show(volume, seq); + else + seq_printf(seq, "\n"); + } +} + +static int iet_volumes_info_show(struct seq_file *seq, void *v) +{ + return iet_info_show(seq, iet_volume_info_show); +} + +static int iet_volume_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, iet_volumes_info_show, NULL); +} + +struct file_operations volume_seq_fops = { + .owner = THIS_MODULE, + .open = iet_volume_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; --- linux-2.6.27.orig/ubuntu/iscsitarget/conn.c +++ linux-2.6.27/ubuntu/iscsitarget/conn.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "digest.h" + +static void print_conn_state(char *p, size_t size, unsigned long state) +{ + if (test_bit(CONN_ACTIVE, &state)) + snprintf(p, size, "%s", "active"); + else if (test_bit(CONN_CLOSING, &state)) + snprintf(p, size, "%s", "closing"); + else + snprintf(p, size, "%s", "unknown"); +} + +static void print_digest_state(char *p, size_t size, unsigned long flags) +{ + if (DIGEST_NONE & flags) + snprintf(p, size, "%s", "none"); + else if (DIGEST_CRC32C & flags) + snprintf(p, size, "%s", "crc32c"); + else + snprintf(p, size, "%s", "unknown"); +} + +void conn_info_show(struct seq_file *seq, struct iscsi_session *session) +{ + struct iscsi_conn *conn; + struct sock *sk; + char buf[64]; + + list_for_each_entry(conn, &session->conn_list, list) { + sk = conn->sock->sk; + switch (sk->sk_family) { + case AF_INET: + snprintf(buf, sizeof(buf), + "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr)); + break; + case AF_INET6: + snprintf(buf, sizeof(buf), + "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]", + NIP6(inet6_sk(sk)->daddr)); + break; + default: + break; + } + seq_printf(seq, "\t\tcid:%u ip:%s ", conn->cid, buf); + print_conn_state(buf, sizeof(buf), conn->state); + seq_printf(seq, "state:%s ", buf); + print_digest_state(buf, sizeof(buf), conn->hdigest_type); + seq_printf(seq, "hd:%s ", buf); + print_digest_state(buf, sizeof(buf), conn->ddigest_type); + seq_printf(seq, "dd:%s\n", buf); + } +} + +struct iscsi_conn *conn_lookup(struct iscsi_session *session, u16 cid) +{ + struct iscsi_conn *conn; + + list_for_each_entry(conn, &session->conn_list, list) { + if (conn->cid == cid) + return conn; + } + return NULL; +} + +static void iet_state_change(struct sock *sk) +{ + struct iscsi_conn *conn = sk->sk_user_data; + struct iscsi_target *target = conn->session->target; + + if (sk->sk_state != TCP_ESTABLISHED) + conn_close(conn); + else + nthread_wakeup(target); + + target->nthread_info.old_state_change(sk); +} + +static void iet_data_ready(struct sock *sk, int len) +{ + struct iscsi_conn *conn = sk->sk_user_data; + struct iscsi_target *target = conn->session->target; + + nthread_wakeup(target); + target->nthread_info.old_data_ready(sk, len); +} + +static void iet_socket_bind(struct iscsi_conn *conn) +{ + int opt = 1; + mm_segment_t oldfs; + struct iscsi_session *session = conn->session; + struct iscsi_target *target = session->target; + + dprintk(D_GENERIC, "%llu\n", (unsigned long long) session->sid); + + conn->sock = SOCKET_I(conn->file->f_dentry->d_inode); + conn->sock->sk->sk_user_data = conn; + + write_lock_bh(&conn->sock->sk->sk_callback_lock); + target->nthread_info.old_state_change = conn->sock->sk->sk_state_change; + conn->sock->sk->sk_state_change = iet_state_change; + + target->nthread_info.old_data_ready = conn->sock->sk->sk_data_ready; + conn->sock->sk->sk_data_ready = iet_data_ready; + write_unlock_bh(&conn->sock->sk->sk_callback_lock); + + oldfs = get_fs(); + set_fs(get_ds()); + conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)); + set_fs(oldfs); +} + +int conn_free(struct iscsi_conn *conn) +{ + dprintk(D_GENERIC, "%p %#Lx %u\n", conn->session, + (unsigned long long) conn->session->sid, conn->cid); + + assert(atomic_read(&conn->nr_cmnds) == 0); + assert(list_empty(&conn->pdu_list)); + assert(list_empty(&conn->write_list)); + + list_del(&conn->list); + list_del(&conn->poll_list); + + digest_cleanup(conn); + kfree(conn); + + return 0; +} + +static int iet_conn_alloc(struct iscsi_session *session, struct conn_info *info) +{ + struct iscsi_conn *conn; + + dprintk(D_SETUP, "%#Lx:%u\n", (unsigned long long) session->sid, info->cid); + + conn = kzalloc(sizeof(*conn), GFP_KERNEL); + if (!conn) + return -ENOMEM; + + conn->session = session; + conn->cid = info->cid; + conn->stat_sn = info->stat_sn; + conn->exp_stat_sn = info->exp_stat_sn; + + conn->hdigest_type = info->header_digest; + conn->ddigest_type = info->data_digest; + if (digest_init(conn) < 0) { + kfree(conn); + return -ENOMEM; + } + + spin_lock_init(&conn->list_lock); + atomic_set(&conn->nr_cmnds, 0); + atomic_set(&conn->nr_busy_cmnds, 0); + INIT_LIST_HEAD(&conn->pdu_list); + INIT_LIST_HEAD(&conn->write_list); + INIT_LIST_HEAD(&conn->poll_list); + + list_add(&conn->list, &session->conn_list); + + set_bit(CONN_ACTIVE, &conn->state); + + conn->file = fget(info->fd); + iet_socket_bind(conn); + + list_add(&conn->poll_list, &session->target->nthread_info.active_conns); + + nthread_wakeup(conn->session->target); + + return 0; +} + +void conn_close(struct iscsi_conn *conn) +{ + if (test_and_clear_bit(CONN_ACTIVE, &conn->state)) + set_bit(CONN_CLOSING, &conn->state); + + nthread_wakeup(conn->session->target); +} + +int conn_add(struct iscsi_session *session, struct conn_info *info) +{ + struct iscsi_conn *conn; + int err = -EEXIST; + + conn = conn_lookup(session, info->cid); + if (conn) + return err; + + return iet_conn_alloc(session, info); +} + +int conn_del(struct iscsi_session *session, struct conn_info *info) +{ + struct iscsi_conn *conn; + int err = -EEXIST; + + conn = conn_lookup(session, info->cid); + if (!conn) + return err; + + conn_close(conn); + + return 0; +} --- linux-2.6.27.orig/ubuntu/iscsitarget/Makefile +++ linux-2.6.27/ubuntu/iscsitarget/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the Linux kernel device drivers. +# + +obj-$(CONFIG_SCSI_ISCSITARGET) += iscsi_trgt.o +iscsi_trgt-objs := tio.o iscsi.o nthread.o wthread.o config.o digest.o \ + conn.o session.o target.o volume.o iotype.o \ + file-io.o null-io.o target_disk.o event.o param.o \ + block-io.o --- linux-2.6.27.orig/ubuntu/unionfs/unionfs_imap.h +++ linux-2.6.27/ubuntu/unionfs/unionfs_imap.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef Sipek + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: unionfs_imap.h,v 1.1 2006/05/30 21:38:45 jsipek Exp $ + */ + +#ifndef __UNIONFS_H_ +#error This file should only be included from unionfs.h! +#endif + +#ifdef UNIONFS_IMAP + +/*UUID typedef needed later*/ +typedef uint8_t uuid_t[16]; + +/* +* Defines,structs,and functions for persistent used by kernel and user +*/ +#define MAX_MAPS 256 +#define UUID_LEN 16 +#define FORWARDMAP_MAGIC 0x4b1cb38f +#define REVERSEMAP_MAGIC 0Xfcafad71 +#define FORWARDMAP_VERSION 0x02 +#define REVERSEMAP_VERSION 0x01 +#define FIRST_VALID_INODE 3 +struct fmaphdr { + uint32_t magic; + uint32_t version; + uint8_t usedbranches; + uint8_t uuid[UUID_LEN]; +}; + +struct rmaphdr { + uint32_t magic; + uint32_t version; + uint8_t fwduuid[UUID_LEN]; + uint8_t revuuid[UUID_LEN]; + fsid_t fsid; +}; +struct bmapent { + fsid_t fsid; + uint8_t uuid[UUID_LEN]; +}; +struct fmapent { + uint8_t fsnum; + uint64_t inode; +}; + +/* Persistant Inode functions */ +extern int read_uin(struct super_block *sb, uint8_t branchnum, + ino_t inode_number, int flag, ino_t * uino); +extern int write_uin(struct super_block *sb, ino_t ino, int bindex, + ino_t hidden_ino); +extern int get_lin(struct super_block *sb, ino_t inode_number, + struct fmapent *entry); +extern int parse_imap_option(struct super_block *sb, + struct unionfs_dentry_info *hidden_root_info, + char *options); +extern void cleanup_imap_data(struct super_block *sb); + +#endif /*#ifdef UNIONFS_IMAP */ + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/unionfs_debug.h +++ linux-2.6.27/ubuntu/unionfs/unionfs_debug.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef Sipek + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: unionfs_debug.h,v 1.3 2006/06/01 21:25:18 jsipek Exp $ + */ + +#ifndef __UNIONFS_H_ +#error This file should only be included from unionfs.h! +#endif + +#ifdef UNIONFS_DEBUG +#define DEFAULT_DEBUG_MASK 0 +#else +#define DEFAULT_DEBUG_MASK (~0) +#endif + +/* debug print levels */ +#define PRINT_NONE 0x0000 +#define PRINT_MAIN_ENTRY 0x0001 +#define PRINT_MAIN_EXIT 0x0002 +#define PRINT_UTILITY_ENTRY 0x0004 +#define PRINT_UTILITY_EXIT 0x0008 +#define PRINT_MISC_ENTRY 0x0010 +#define PRINT_MISC_EXIT 0x0020 +#define PRINT_DATA_DENTRY 0x0040 +#define PRINT_DATA_FILE 0x0080 +#define PRINT_DATA_INODE 0x0100 +#define PRINT_DATA_SB 0x0200 +#define PRINT_DEBUG 0x0400 +#define __PRINT_DEBUG_XATTR 0x0800 +#define PRINT_DEBUG_XATTR (PRINT_DEBUG | __PRINT_DEBUG_XATTR) +#define __PRINT_DEBUG_WHITEOUT 0x1000 +#define PRINT_DEBUG_WHITEOUT (PRINT_DEBUG | __PRINT_DEBUG_WHITEOUT) + +#define PRINT_MAX (0x2000 - 1) +#define PRINT_ALL (~PRINT_NONE) + +extern unsigned int get_debug_mask(void); +extern int set_debug_mask(int val); + +/* print inode */ +extern void unionfs_print_inode(const unsigned int req, const char *prefix, const struct inode *inode); + +/* check inode */ +extern void unionfs_checkinode(const unsigned int req, const struct inode *inode, const char *msg); + +/* prunt file */ +extern void unionfs_print_file(const unsigned int req, const char *prefix, const struct file *file); + +/* print dentry */ +extern void unionfs_print_dentry(const unsigned int req, const char *prefix, const struct dentry *dentry); + +extern void unionfs_print_dentry_nocheck(const unsigned int req, const char *prefix, const struct dentry *dentry); + +/* print superblock */ +extern void unionfs_print_sb(const unsigned int req, const char *prefix, const struct super_block *sb); + +/* print message */ +extern int unionfs_print(const unsigned int req, const char *fmt, ...); + +/* forced print-debugging functions */ +#define force_print_dentry(prefix, ptr) \ + unionfs_print_dentry(PRINT_ALL, (prefix), (ptr)) +#define force_print_dentry_nocheck(prefix, ptr) \ + unionfs_print_dentry_nocheck(PRINT_ALL, (prefix), (ptr)) +#define force_print_file(prefix, ptr) \ + unionfs_print_file(PRINT_ALL, (prefix), (ptr)) +#define force_print_inode(prefix, ptr) \ + unionfs_print_inode(PRINT_ALL, (prefix), (ptr)) +#define force_print_sb(prefix, ptr) \ + unionfs_print_sb(PRINT_ALL, (prefix), (ptr)) + +#ifdef UNIONFS_DEBUG +/* + * Full-fledged debugging enabled + */ + +#define print_dentry(prefix, ptr) \ + unionfs_print_dentry(PRINT_DATA_DENTRY, (prefix), (ptr)) +#define print_dentry_nocheck(prefix, ptr) \ + unionfs_print_dentry_nocheck(PRINT_DATA_DENTRY, (prefix), (ptr)) +#define print_file(prefix, ptr) \ + unionfs_print_file(PRINT_DATA_FILE, (prefix), (ptr)) +#define print_inode(prefix, ptr) \ + unionfs_print_inode(PRINT_DATA_INODE, (prefix), (ptr)) +#define print_sb(prefix, ptr) \ + unionfs_print_sb(PRINT_DATA_SB, (prefix), (ptr)) +#define dprint(req, fmt, args...) \ + unionfs_print(req, fmt, ## args) + +#define checkinode(ptr, msg) \ + unionfs_checkinode(PRINT_DEBUG, (ptr), (msg)) + +#define __print_entryexit(req, ee, fmt, args...) \ + unionfs_print((req), \ + ee " %s %s:%d" fmt "\n", \ + __FUNCTION__, \ + __FILE__, \ + __LINE__, \ + ##args) + +#define print_entry(fmt, args...) \ + __print_entryexit(PRINT_MAIN_ENTRY, \ + "IN: ", " " fmt, ##args) + +#define print_entry_location() \ + __print_entryexit(PRINT_MAIN_ENTRY, \ + "IN: ", "") + +#define print_exit_location() \ + __print_entryexit(PRINT_MAIN_EXIT, \ + "OUT:", "") + +#define print_exit_status(status) \ + __print_entryexit(PRINT_MAIN_EXIT, \ + "OUT:", ", STATUS: %d", status) + +static inline void __print_exit_pointer(unsigned int req, void *status) +{ + if (IS_ERR(status)) + __print_entryexit(req, "OUT:", ", STATUS: %ld", + PTR_ERR(status)); + else + __print_entryexit(req, "OUT:", ", STATUS: 0x%p", + status); +} +#define print_exit_pointer(status) \ + __print_exit_pointer(PRINT_MAIN_EXIT, status) + +#define print_util_entry(fmt, args...) \ + __print_entryexit(PRINT_UTILITY_ENTRY, \ + "IN: ", " " fmt, ##args) + +#define print_util_entry_location() \ + __print_entryexit(PRINT_UTILITY_ENTRY, \ + "IN: ", "") + +#define print_util_exit_location() \ + __print_entryexit(PRINT_UTILITY_EXIT, \ + "OUT:", "") + +#define print_util_exit_status(status) \ + __print_entryexit(PRINT_UTILITY_EXIT, \ + "OUT:", ", STATUS: %d", status) + +#define print_util_exit_pointer(status) \ + __print_exit_pointer(PRINT_UTILITY_EXIT, status) + +#else /* UNIONFS_DEBUG */ +/* + * Full-fledged debugging disabled + */ + +#define print_dentry(prefix, ptr) +#define print_dentry_nocheck(prefix, ptr) +#define print_file(prefix, ptr) +#define print_inode(prefix, ptr) +#define print_sb(prefix, ptr) +#define dprint(req, fmt, args...) + +#define checkinode(ptr, msg) + +#define print_entry(args...) +#define print_entry_location() +#define print_exit_location() +#define print_exit_status(status) +#define print_exit_pointer(status) +#define print_util_entry(args...) +#define print_util_entry_location() +#define print_util_exit_location() +#define print_util_exit_status(status) +#define print_util_exit_pointer(status) + +#endif /* ! UNIONFS_DEBUG */ + + --- linux-2.6.27.orig/ubuntu/unionfs/stale_inode.c +++ linux-2.6.27/ubuntu/unionfs/stale_inode.c @@ -0,0 +1,133 @@ +/* + * Adpated from linux/fs/bad_inode.c + * + * Copyright (C) 1997, Stephen Tweedie + * + * Provide stub functions for "stale" inodes, a bit friendlier than the + * -EIO that bad_inode.c does. + */ +/* + * $Id: stale_inode.c,v 1.13 2006/03/21 09:22:11 jsipek Exp $ + */ + +#include + +#include +#include +#include + +static struct address_space_operations unionfs_stale_aops; + +/* declarations for "sparse */ +extern struct inode_operations stale_inode_ops; + +/* + * The follow_link operation is special: it must behave as a no-op + * so that a stale root inode can at least be unmounted. To do this + * we must dput() the base and return the dentry with a dget(). + */ +static void *stale_follow_link(struct dentry *dent, struct nameidata *nd) +{ + int err = vfs_follow_link(nd, ERR_PTR(-ESTALE)); + return ERR_PTR(err); +} + +static int return_ESTALE(void) +{ + return -ESTALE; +} + +#define ESTALE_ERROR ((void *) (return_ESTALE)) + +static struct file_operations stale_file_ops = { + .llseek = ESTALE_ERROR, + .read = ESTALE_ERROR, + .write = ESTALE_ERROR, + .readdir = ESTALE_ERROR, + .poll = ESTALE_ERROR, + .ioctl = ESTALE_ERROR, + .mmap = ESTALE_ERROR, + .open = ESTALE_ERROR, + .flush = ESTALE_ERROR, + .release = ESTALE_ERROR, + .fsync = ESTALE_ERROR, + .fasync = ESTALE_ERROR, + .lock = ESTALE_ERROR, +}; + +struct inode_operations stale_inode_ops = { + .create = ESTALE_ERROR, + .lookup = ESTALE_ERROR, + .link = ESTALE_ERROR, + .unlink = ESTALE_ERROR, + .symlink = ESTALE_ERROR, + .mkdir = ESTALE_ERROR, + .rmdir = ESTALE_ERROR, + .mknod = ESTALE_ERROR, + .rename = ESTALE_ERROR, + .readlink = ESTALE_ERROR, + .follow_link = stale_follow_link, + .truncate = ESTALE_ERROR, + .permission = ESTALE_ERROR, +}; + +/* + * When a filesystem is unable to read an inode due to an I/O error in + * its read_inode() function, it can call make_stale_inode() to return a + * set of stubs which will return ESTALE errors as required. + * + * We only need to do limited initialisation: all other fields are + * preinitialised to zero automatically. + */ + +/** + * make_stale_inode - mark an inode stale due to an I/O error + * @inode: Inode to mark stale + * + * When an inode cannot be read due to a media or remote network + * failure this function makes the inode "stale" and causes I/O operations + * on it to fail from this point on. + */ + +void make_stale_inode(struct inode *inode) +{ + inode->i_mode = S_IFREG; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_op = &stale_inode_ops; + inode->i_fop = &stale_file_ops; + inode->i_mapping->a_ops = &unionfs_stale_aops; +} + +/* + * This tests whether an inode has been flagged as stale. The test uses + * &stale_inode_ops to cover the case of invalidated inodes as well as + * those created by make_stale_inode() above. + */ + +/** + * is_stale_inode - is an inode errored + * @inode: inode to test + * + * Returns true if the inode in question has been marked as stale. + */ + +int is_stale_inode(struct inode *inode) +{ + return (inode->i_op == &stale_inode_ops); +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/unlink.c +++ linux-2.6.27/ubuntu/unionfs/unlink.c @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: unlink.c,v 1.44 2006/08/05 01:28:46 jro Exp $ + */ + +#include "unionfs.h" + +#ifdef UNIONFS_DELETE_ALL +static int unionfs_unlink_all(struct inode *dir, struct dentry *dentry) +{ + struct dentry *hidden_dentry; + struct dentry *hidden_dir_dentry; + int bstart, bend, bindex; + int err = 0; + int global_err = 0; + + print_entry_location(); + + if ((err = unionfs_partial_lookup(dentry))) + goto out; + + bstart = dbstart(dentry); + bend = dbend(dentry); + + for (bindex = bend; bindex >= bstart; bindex--) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + + hidden_dir_dentry = lock_parent(hidden_dentry); + + /* avoid destroying the hidden inode if the file is in use */ + DGET(hidden_dentry); + if (!(err = is_robranch_super(dentry->d_sb, bindex))) + err = vfs_unlink(hidden_dir_dentry->d_inode, + hidden_dentry, NULL); + DPUT(hidden_dentry); + fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); + unlock_dir(hidden_dir_dentry); + + if (err) { + /* passup the last error we got */ + if (!IS_COPYUP_ERR(err)) + goto out; + global_err = err; + } + } + + /* check if encountered error in the above loop */ + if (global_err) { + /* If we failed in the leftmost branch, then err will be set + * and we should move one over to create the whiteout. + * Otherwise, we should try in the leftmost branch. */ + if (err) { + if (dbstart(dentry) == 0) { + goto out; + } + err = create_whiteout(dentry, dbstart(dentry) - 1); + } else { + err = create_whiteout(dentry, dbstart(dentry)); + } + } else if (dbopaque(dentry) != -1) { + /* There is a hidden lower-priority file with the same name. */ + err = create_whiteout(dentry, dbopaque(dentry)); + } + out: + /* propagate number of hard-links */ + if (dentry->d_inode->i_nlink != 0) { + dentry->d_inode->i_nlink = get_nlinks(dentry->d_inode); + if (!err && global_err) + dentry->d_inode->i_nlink--; + } + /* We don't want to leave negative leftover dentries for revalidate. */ + if (!err && (global_err || dbopaque(dentry) != -1)) + update_bstart(dentry); + + print_exit_status(err); + return err; +} +#endif +static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry) +{ + struct dentry *hidden_dentry; + struct dentry *hidden_dir_dentry; + int bindex; + int err = 0; + + print_entry_location(); + + if ((err = unionfs_partial_lookup(dentry))) + goto out; + + bindex = dbstart(dentry); + + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + goto out; + + hidden_dir_dentry = lock_parent(hidden_dentry); + + /* avoid destroying the hidden inode if the file is in use */ + DGET(hidden_dentry); + if (!(err = is_robranch_super(dentry->d_sb, bindex))) + err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry, + NULL); + DPUT(hidden_dentry); + fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); + unlock_dir(hidden_dir_dentry); + + if (err && !IS_COPYUP_ERR(err)) + goto out; + + if (err) { + if (dbstart(dentry) == 0) + goto out; + + err = create_whiteout(dentry, dbstart(dentry) - 1); + } else if (dbopaque(dentry) != -1) { + /* There is a hidden lower-priority file with the same name. */ + err = create_whiteout(dentry, dbopaque(dentry)); + } else { + err = create_whiteout(dentry, dbstart(dentry)); + } + + out: + if (!err) + dentry->d_inode->i_nlink--; + + /* We don't want to leave negative leftover dentries for revalidate. */ + if (!err && (dbopaque(dentry) != -1)) + update_bstart(dentry); + + print_exit_status(err); + return err; + +} + +int unionfs_unlink(struct inode *dir, struct dentry *dentry) +{ + int err = 0; + + print_entry_location(); + lock_dentry(dentry); + print_dentry("IN unionfs_unlink", dentry); + +#ifdef UNIONFS_DELETE_ALL + if (IS_SET(dir->i_sb, DELETE_ALL)) + err = unionfs_unlink_all(dir, dentry); + else +#endif + err = unionfs_unlink_whiteout(dir, dentry); + /* call d_drop so the system "forgets" about us */ + if (!err) + d_drop(dentry); + + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry, + struct unionfs_dir_state *namelist) +{ + int err; + struct dentry *hidden_dentry; + struct dentry *hidden_dir_dentry = NULL; + + print_entry_location(); + print_dentry("IN unionfs_rmdir_first: ", dentry); + + /* Here we need to remove whiteout entries. */ + err = delete_whiteouts(dentry, dbstart(dentry), namelist); + if (err) { + goto out; + } + + hidden_dentry = dtohd(dentry); + + hidden_dir_dentry = lock_parent(hidden_dentry); + + /* avoid destroying the hidden inode if the file is in use */ + DGET(hidden_dentry); + if (!(err = is_robranch(dentry))) { + err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry, + NULL); + } + DPUT(hidden_dentry); + + fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); + /* propagate number of hard-links */ + dentry->d_inode->i_nlink = get_nlinks(dentry->d_inode); + + out: + if (hidden_dir_dentry) { + unlock_dir(hidden_dir_dentry); + } + print_dentry("OUT unionfs_rmdir_first: ", dentry); + print_exit_status(err); + return err; +} + +#ifdef UNIONFS_DELETE_ALL +static int unionfs_rmdir_all(struct inode *dir, struct dentry *dentry, + struct unionfs_dir_state *namelist) +{ + struct dentry *hidden_dentry; + struct dentry *hidden_dir_dentry; + int bstart, bend, bindex; + int err = 0; + int global_err = 0; + + print_entry_location(); + print_dentry("IN unionfs_rmdir_all: ", dentry); + + bstart = dbstart(dentry); + bend = dbend(dentry); + + for (bindex = bend; bindex >= bstart; bindex--) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + + hidden_dir_dentry = lock_parent(hidden_dentry); + if (S_ISDIR(hidden_dentry->d_inode->i_mode)) { + err = delete_whiteouts(dentry, bindex, namelist); + if (!err + && !(err = + is_robranch_super(dentry->d_sb, bindex))) { + err = + vfs_rmdir(hidden_dir_dentry->d_inode, + hidden_dentry, NULL); + } + } else { + err = -EISDIR; + } + + fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); + unlock_dir(hidden_dir_dentry); + if (err) { + int local_err = + unionfs_refresh_hidden_dentry(dentry, bindex); + if (local_err) { + err = local_err; + goto out; + } + + if (!IS_COPYUP_ERR(err) && err != -ENOTEMPTY + && err != -EISDIR) + goto out; + + global_err = err; + } + } + + /* check if encountered error in the above loop */ + if (global_err) { + /* If we failed in the leftmost branch, then err will be set and we should + * move one over to create the whiteout. Otherwise, we should try in the + * leftmost branch. + */ + if (err) { + if (dbstart(dentry) == 0) { + goto out; + } + err = create_whiteout(dentry, dbstart(dentry) - 1); + } else { + err = create_whiteout(dentry, dbstart(dentry)); + } + } else { + err = create_whiteout(dentry, dbstart(dentry)); + } + + out: + /* propagate number of hard-links */ + dentry->d_inode->i_nlink = get_nlinks(dentry->d_inode); + + print_dentry("OUT unionfs_rmdir_all: ", dentry); + print_exit_status(err); + return err; +} +#endif +int unionfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + int err = 0; + struct unionfs_dir_state *namelist = NULL; + + print_entry_location(); + lock_dentry(dentry); + print_dentry("IN unionfs_rmdir: ", dentry); + + /* check if this unionfs directory is empty or not */ + err = check_empty(dentry, &namelist); + if (err) { +#if 0 + /* vfs_rmdir(our caller) unhashed the dentry. This will recover + * the Unionfs inode number for the directory itself, but the + * children are already lost. It seems that tmpfs manages its + * way around this by upping the refcount on everything. + * + * Even if we do this, we still lose the inode numbers of the + * children. The best way to fix this is to fix the VFS (or + * use persistent inode maps). */ + if (d_unhashed(dentry)) + d_rehash(dentry); +#endif + goto out; + } +#ifdef UNIONFS_DELETE_ALL + if (IS_SET(dir->i_sb, DELETE_ALL)) { + /* delete all. */ + err = unionfs_rmdir_all(dir, dentry, namelist); + } else { /* Delete the first directory. */ +#endif + err = unionfs_rmdir_first(dir, dentry, namelist); + /* create whiteout */ + if (!err) { + err = create_whiteout(dentry, dbstart(dentry)); + } else { + int new_err; + + if (dbstart(dentry) == 0) + goto out; + + /* exit if the error returned was NOT -EROFS */ + if (!IS_COPYUP_ERR(err)) + goto out; + + new_err = create_whiteout(dentry, dbstart(dentry) - 1); + if (new_err != -EEXIST) + err = new_err; + } + +#ifdef UNIONFS_DELETE_ALL + } +#endif + out: + /* call d_drop so the system "forgets" about us */ + if (!err) + d_drop(dentry); + + if (namelist) + free_rdstate(namelist); + + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/super.c +++ linux-2.6.27/ubuntu/unionfs/super.c @@ -0,0 +1,762 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: super.c,v 1.101 2006/11/04 22:27:51 jsipek Exp $ + */ + +#include "unionfs.h" + +/* The inode cache is used with alloc_inode for both our inode info and the + * vfs inode. */ +static struct kmem_cache *unionfs_inode_cachep; + +void unionfs_read_inode(struct inode *inode) +{ +#ifdef UNIONFS_MMAP + /* SP: use real address operations */ + extern struct address_space_operations unionfs_aops; +#else + static struct address_space_operations unionfs_empty_aops; +#endif + int size; + + print_entry_location(); + + if (!itopd(inode)) { + printk(KERN_ERR + "No kernel memory when allocating inode private data!\n"); + BUG(); + } + + memset(itopd(inode), 0, sizeof(struct unionfs_inode_info)); + itopd(inode)->b_start = -1; + itopd(inode)->b_end = -1; + atomic_set(&itopd(inode)->uii_generation, + atomic_read(&stopd(inode->i_sb)->usi_generation)); + itopd(inode)->uii_rdlock = SPIN_LOCK_UNLOCKED; + itopd(inode)->uii_rdcount = 1; + itopd(inode)->uii_hashsize = -1; + INIT_LIST_HEAD(&itopd(inode)->uii_readdircache); + + size = sbmax(inode->i_sb) * sizeof(struct inode *); + itohi_ptr(inode) = KZALLOC(size, GFP_KERNEL); + if (!itohi_ptr(inode)) { + printk(KERN_ERR + "No kernel memory when allocating lower-pointer array!\n"); + BUG(); + } + + inode->i_version++; + inode->i_op = &unionfs_main_iops; + inode->i_fop = &unionfs_main_fops; +#ifdef UNIONFS_MMAP + inode->i_mapping->a_ops = &unionfs_aops; +#else + /* I don't think ->a_ops is ever allowed to be NULL */ + inode->i_mapping->a_ops = &unionfs_empty_aops; + dprint(PRINT_DEBUG, "setting inode 0x%p a_ops to empty (0x%p)\n", + inode, inode->i_mapping->a_ops); +#endif + + print_exit_location(); +} + +#if 0 +static void unionfs_put_inode(struct inode *inode) +{ + print_entry_location(); + + dprint(PRINT_DEBUG, "%s i_count = %d, i_nlink = %d\n", __FUNCTION__, + atomic_read(&inode->i_count), inode->i_nlink); + + /* + * This is really funky stuff: + * Basically, if i_count == 1, iput will then decrement it and this + * inode will be destroyed. It is currently holding a reference to the + * hidden inode. Therefore, it needs to release that reference by + * calling iput on the hidden inode. iput() _will_ do it for us (by + * calling our clear_inode), but _only_ if i_nlink == 0. The problem + * is, NFS keeps i_nlink == 1 for silly_rename'd files. So we must for + * our i_nlink to 0 here to trick iput() into calling our clear_inode. + */ + + if (atomic_read(&inode->i_count) == 1) + inode->i_nlink = 0; + + print_exit_location(); +} +#endif + +/* + * we now define delete_inode, because there are two VFS paths that may + * destroy an inode: one of them calls clear inode before doing everything + * else that's needed, and the other is fine. This way we truncate the inode + * size (and its pages) and then clear our own inode, which will do an iput + * on our and the lower inode. + */ +static void unionfs_delete_inode(struct inode *inode) +{ + print_entry_location(); + + checkinode(inode, "unionfs_delete_inode IN"); + inode->i_size = 0; /* every f/s seems to do that */ + +#ifdef UNIONFS_MMAP + /* SP: if you try to clear_inode() when + * inode->i_data.nrpages != 0, you'll hit a BUG + * this is also what generic_delete_inode does */ + if (inode->i_data.nrpages) + truncate_inode_pages(&inode->i_data, 0); +#endif + clear_inode(inode); + + print_exit_location(); +} + +/* final actions when unmounting a file system */ +static void unionfs_put_super(struct super_block *sb) +{ + int bindex, bstart, bend; + struct unionfs_sb_info *spd; + + print_entry_location(); + + if ((spd = stopd(sb))) { +#ifdef UNIONFS_IMAP + /* XXX: Free persistent inode stuff. */ + cleanup_imap_data(sb); +#endif + bstart = sbstart(sb); + bend = sbend(sb); + for (bindex = bstart; bindex <= bend; bindex++) + mntput(stohiddenmnt_index(sb, bindex)); + + /* Make sure we have no leaks of branchget/branchput. */ + for (bindex = bstart; bindex <= bend; bindex++) + BUG_ON(branch_count(sb, bindex) != 0); + + KFREE(spd->usi_data); + KFREE(spd); + stopd_lhs(sb) = NULL; + } + dprint(PRINT_DEBUG, "unionfs: released super\n"); + + print_exit_location(); +} + +/* Since people use this to answer the "How big of a file can I write?" + * question, we report the size of the highest priority branch as the size of + * the union. + */ +static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + int err = 0; + struct super_block *sb, *hidden_sb; + + sb = dentry->d_sb; + + hidden_sb = stohs_index(sb, sbstart(sb)); + err = vfs_statfs(hidden_sb->s_root, buf); + + buf->f_type = UNIONFS_SUPER_MAGIC; + buf->f_namelen -= WHLEN; + + memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t)); + memset(&buf->f_spare, 0, sizeof(buf->f_spare)); + + return err; +} + +static int do_binary_remount(struct super_block *sb, int *flags, char *data) +{ + unsigned long *uldata = (unsigned long *)data; + int err; + + uldata++; + + switch (*uldata) { + case UNIONFS_IOCTL_DELBRANCH: + err = unionfs_ioctl_delbranch(sb, *(uldata + 1)); + break; + default: + err = -ENOTTY; + } + + return err; +} + +/* We don't support a standard text remount, but we do have a magic remount + * for unionctl. The idea is that you can remove a branch without opening + * the union. Eventually it would be nice to support a full-on remount, so + * that you can have all of the directories change at once, but that would + * require some pretty complicated matching code. */ +static int unionfs_remount_fs(struct super_block *sb, int *flags, char *data) +{ + if (data && *((unsigned long *)data) == UNIONFS_REMOUNT_MAGIC) + return do_binary_remount(sb, flags, data); + printk("Warning! dirs delete and imap options to remount are ignored\n"); + return 0; +} + +/* + * Called by iput() when the inode reference count reached zero + * and the inode is not hashed anywhere. Used to clear anything + * that needs to be, before the inode is completely destroyed and put + * on the inode free list. + */ +static void unionfs_clear_inode(struct inode *inode) +{ + int bindex, bstart, bend; + struct inode *hidden_inode; + struct list_head *pos, *n; + struct unionfs_dir_state *rdstate; + + print_entry_location(); + + checkinode(inode, "unionfs_clear_inode IN"); + + list_for_each_safe(pos, n, &itopd(inode)->uii_readdircache) { + rdstate = list_entry(pos, struct unionfs_dir_state, uds_cache); + list_del(&rdstate->uds_cache); + free_rdstate(rdstate); + } + + /* Decrement a reference to a hidden_inode, which was incremented + * by our read_inode when it was created initially. */ + bstart = ibstart(inode); + bend = ibend(inode); + if (bstart >= 0) { + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_inode = itohi_index(inode, bindex); + if (!hidden_inode) + continue; + IPUT(hidden_inode); + } + } + // XXX: why this assertion fails? + // because it doesn't like us + // BUG_ON((inode->i_state & I_DIRTY) != 0); + KFREE(itohi_ptr(inode)); + itohi_ptr(inode) = NULL; + + print_exit_location(); +} + +static struct inode *unionfs_alloc_inode(struct super_block *sb) +{ + struct unionfs_inode_container *c; + + print_entry_location(); + + c = (struct unionfs_inode_container *) + kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL); + if (!c) { + print_exit_pointer(NULL); + return NULL; + } + + memset(&c->info, 0, sizeof(c->info)); + + c->vfs_inode.i_version = 1; + print_exit_pointer(&c->vfs_inode); + return &c->vfs_inode; +} + +static void unionfs_destroy_inode(struct inode *inode) +{ + print_entry("inode = %p", inode); + kmem_cache_free(unionfs_inode_cachep, itopd(inode)); + print_exit_location(); +} + +static void init_once(void *v) +{ + struct unionfs_inode_container *c = (struct unionfs_inode_container *)v; + + print_entry_location(); + + inode_init_once(&c->vfs_inode); + + print_exit_location(); +} + +int init_inode_cache(void) +{ + int err = 0; + + print_entry_location(); + + unionfs_inode_cachep = + kmem_cache_create("unionfs_inode_cache", + sizeof(struct unionfs_inode_container), 0, + SLAB_RECLAIM_ACCOUNT, init_once); + if (!unionfs_inode_cachep) + err = -ENOMEM; + print_exit_status(err); + return err; +} + +void destroy_inode_cache(void) +{ + print_entry_location(); + if (!unionfs_inode_cachep) + goto out; + kmem_cache_destroy(unionfs_inode_cachep); + out: + print_exit_location(); + return; +} + +/* Called when we have a dirty inode, right here we only throw out + * parts of our readdir list that are too old. + */ +static int unionfs_write_inode(struct inode *inode, int sync) +{ + struct list_head *pos, *n; + struct unionfs_dir_state *rdstate; + + print_entry_location(); + + spin_lock(&itopd(inode)->uii_rdlock); + list_for_each_safe(pos, n, &itopd(inode)->uii_readdircache) { + rdstate = list_entry(pos, struct unionfs_dir_state, uds_cache); + /* We keep this list in LRU order. */ + if ((rdstate->uds_access + RDCACHE_JIFFIES) > jiffies) + break; + itopd(inode)->uii_rdcount--; + list_del(&rdstate->uds_cache); + free_rdstate(rdstate); + } + spin_unlock(&itopd(inode)->uii_rdlock); + + print_exit_location(); + return 0; +} + +/* + * Used only in nfs, to kill any pending RPC tasks, so that subsequent + * code can actually succeed and won't leave tasks that need handling. + * + * PS. I wonder if this is somehow useful to undo damage that was + * left in the kernel after a user level file server (such as amd) + * dies. + */ +static void unionfs_umount_begin(struct super_block *sb) +{ + struct super_block *hidden_sb; + int bindex, bstart, bend; + + print_entry_location(); +#if 0 + if (!(flags & MNT_FORCE)) + /* we are not being MNT_FORCEd, therefore we should emulate old + * behaviour + */ + goto out; +#endif + bstart = sbstart(sb); + bend = sbend(sb); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_sb = stohs_index(sb, bindex); + + if (hidden_sb && hidden_sb->s_op && + hidden_sb->s_op->umount_begin) + hidden_sb->s_op->umount_begin(hidden_sb); + } + + print_exit_location(); +} + +static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + struct super_block *sb = mnt->mnt_sb; + int ret = 0; + unsigned long tmp = 0; + char *hidden_path; + int bindex, bstart, bend; + int perms; + + lock_dentry(sb->s_root); + + tmp = __get_free_page(GFP_KERNEL); + if (!tmp) { + ret = -ENOMEM; + goto out; + } + + bindex = bstart = sbstart(sb); + bend = sbend(sb); + + seq_printf(m, ",dirs="); + for (bindex = bstart; bindex <= bend; bindex++) { + struct path tp; + tp.dentry = dtohd_index(sb->s_root, bindex); + tp.mnt = stohiddenmnt_index(sb, bindex); + + hidden_path = + d_path(&tp, (char *)tmp, PAGE_SIZE); + perms = branchperms(sb, bindex); + seq_printf(m, "%s=%s", hidden_path, + perms & MAY_WRITE ? "rw" : + perms & MAY_NFSRO ? "nfsro" : "ro"); + if (bindex != bend) { + seq_printf(m, ":"); + } + } + + seq_printf(m, ",debug=%u", get_debug_mask()); + +#ifdef UNIONFS_DELETE_ALL + if (IS_SET(sb, DELETE_ALL)) + seq_printf(m, ",delete=all"); + else +#endif + seq_printf(m, ",delete=whiteout"); + out: + if (tmp) + free_page(tmp); + unlock_dentry(sb->s_root); + return ret; +} + +#ifdef CONFIG_EXPORTFS +/* + * export operations. + * unionfs cannot handle disconnected dentry, since it has no hidden dentries. + */ +/* un-tested 64 bit environment (pointer and inode number) */ + +#define is_anon(d) ((d)->d_flags & DCACHE_DISCONNECTED) +extern struct export_operations export_op_default; + +static void prepend_path(char **path, const char *name, int len) +{ + *path -= len; + memcpy(*path, name, len); + (*path)--; + **path = '/'; +} + +struct filldir_arg { + int found, called; + char *path; + ino_t ino, parent_ino; +}; + +static int filldir(void *arg, const char *name, int len, loff_t pos, ino_t ino, + unsigned int d_type) +{ + struct filldir_arg *a = arg; + + a->called++; + if (len == 2 && !strncmp(name, "..", 2)) { + a->parent_ino = ino; + a->found++; + } else if (ino == a->ino) { + if (len != 1 || *name != '.') + prepend_path(&a->path, name, len); + a->found++; + } + return (a->found == 2) ? 1 : 0; +} + +static struct dentry *get_hidden_parent(struct super_block *hidden_sb, + ino_t hidden_parent_ino) +{ + __u32 fh[2]; + + if (hidden_sb->s_root->d_inode->i_ino == hidden_parent_ino) + return DGET(hidden_sb->s_root); + + fh[0] = hidden_parent_ino; + fh[1] = 0; + return export_op_default.get_dentry(hidden_sb, fh); +} + +static struct dentry *do_get_dentry(struct super_block *sb, ino_t ino, + __u32 gen, struct dentry *hidden_root, + ino_t hidden_ino, ino_t hidden_parent_ino) +{ + struct dentry *dentry, *hidden_parent, *parent; + char *path, *p; + struct filldir_arg arg = { + .ino = hidden_ino, + .parent_ino = hidden_parent_ino + }; + int open_flags, err, bindex, bend, found; + struct file *hidden_file; + struct super_block *hidden_sb; + + print_entry("hr%p, hi%lu, hpi%lu", + hidden_root, hidden_ino, hidden_parent_ino); + + dentry = ERR_PTR(-ENOMEM); + path = __getname(); + if (!path) + goto out; + arg.path = path + PATH_MAX - 1; + *arg.path = 0; + + open_flags = O_RDONLY | O_DIRECTORY /* | O_NOATIME */ ; + if (force_o_largefile()) + open_flags |= O_LARGEFILE; + + dentry = ERR_PTR(-ESTALE); + unionfs_read_lock(sb); + lock_dentry(sb->s_root); + bend = dbend(sb->s_root); + found = -1; + for (bindex = 0; found == -1 && bindex <= bend; bindex++) + if (hidden_root == dtohd_index(sb->s_root, bindex)) + found = bindex; + unlock_dentry(sb->s_root); + if (found == -1) + goto out_unlock; + + bindex = found; + hidden_sb = stohs_index(sb, bindex); + while (1) { + hidden_parent = get_hidden_parent(hidden_sb, hidden_parent_ino); + dentry = hidden_parent; + if (IS_ERR(hidden_parent)) + goto out_unlock; + + branchget(sb, bindex); + hidden_file = DENTRY_OPEN(DGET(hidden_parent), NULL, + open_flags); + if (IS_ERR(hidden_file)) { + dentry = (void *)hidden_file; + DPUT(hidden_parent); + branchput(sb, bindex); + goto out_unlock; + } + + arg.found = 0; + while (arg.found != 2) { + arg.called = 0; + err = vfs_readdir(hidden_file, filldir, &arg); + if (!arg.called || err < 0) + break; + } + fput(hidden_file); + branchput(sb, bindex); + if (arg.found != 2) { + dentry = ERR_PTR(-ESTALE); + DPUT(hidden_parent); + goto out_unlock; + } + + DPUT(hidden_parent); + if (hidden_parent_ino == hidden_root->d_inode->i_ino) + break; + arg.ino = hidden_parent_ino; + hidden_parent_ino = arg.parent_ino; + } + BUG_ON(arg.path < path); + + parent = DGET(sb->s_root); + p = strchr(++arg.path, '/'); + while (p) { + mutex_lock(&parent->d_inode->i_mutex); + dentry = LOOKUP_ONE_LEN(arg.path, parent, p - arg.path); + mutex_unlock(&parent->d_inode->i_mutex); + DPUT(parent); + if (IS_ERR(dentry)) + goto out_unlock; + if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) { + DPUT(dentry); + dentry = ERR_PTR(-ESTALE); + goto out_unlock; + } + parent = dentry; + arg.path = p + 1; + p = strchr(arg.path, '/'); + } + mutex_lock(&parent->d_inode->i_mutex); + dentry = LOOKUP_ONE_LEN(arg.path, parent, strlen(arg.path)); + mutex_unlock(&parent->d_inode->i_mutex); + DPUT(parent); + if (!IS_ERR(dentry) + && (!dentry->d_inode + || dentry->d_inode->i_ino != ino + || dentry->d_inode->i_generation != gen)) { + DPUT(dentry); + dentry = ERR_PTR(-ESTALE); + } + + out_unlock: + unionfs_read_unlock(sb); + __putname(path); + out: + print_exit_pointer(dentry); + return dentry; +} + +enum { + FhHead = 4, FhHRoot1 = FhHead, FhHRoot2, + FhHIno1, FhHIno2, FhHPIno1, FhHPIno2, + FhTail +}; + +static void do_decode(__u32 * fh, struct dentry **hidden_root, + ino_t * hidden_ino, ino_t * hidden_parent_ino) +{ + unsigned long root; + + root = fh[FhHRoot2]; + *hidden_ino = fh[FhHIno2]; + *hidden_parent_ino = fh[FhHPIno2]; +#if BITS_PER_LONG == 64 + root |= ((unsigned long)fh[FhHRoot1]) << 32; + *hidden_ino |= ((unsigned long) fh[FhHIno1]) << 32; + *hidden_parent_ino |= ((unsigned long) fh[FhHPIno1]) << 32; +#elif BITS_PER_LONG == 32 + /* ok */ +#else +#error unknown size +#endif + + *hidden_root = (struct dentry*) root; +} + +static int unionfs_encode_fh(struct dentry *dentry, __u32 * fh, int *max_len, + int connectable) +{ + int type, len, bindex; + struct super_block *sb; + struct dentry *h_root; + ino_t h_ino, hp_ino; + static int warn; + + print_entry("dentry %p", dentry); + BUG_ON(is_anon(dentry) || !dentry->d_inode + || is_anon(dentry->d_parent)); + +#ifdef UNIONFS_IMAP + if (!warn && stopd(dentry->d_sb)->usi_persistent) + warn++; +#endif + if (!warn) { + printk(KERN_WARNING "Exporting Unionfs without imap" + " option may stop your NFS server or client"); + warn++; + } + + sb = dentry->d_sb; + unionfs_read_lock(sb); + lock_dentry(dentry); + + len = *max_len; + type = export_op_default.encode_fh(dentry, fh, max_len, connectable); + if (type == 255 || *max_len > FhHead || len < FhTail) { + type = 255; + goto out; + } + + *max_len = FhTail; + bindex = dbstart(dentry); + lock_dentry(sb->s_root); + h_root = dtohd_index(sb->s_root, bindex); + unlock_dentry(sb->s_root); + h_ino = itohi_index(dentry->d_inode, bindex)->i_ino; + hp_ino = parent_ino(dtohd(dentry)); + fh[FhHRoot2] = (unsigned long) h_root; + fh[FhHIno2] = h_ino; + fh[FhHPIno2] = hp_ino; +#if BITS_PER_LONG == 64 + fh[FhHRoot1] = ((unsigned long) h_root) >> 32; + fh[FhHIno1] = h_ino >> 32; + fh[FhHPIno1] = hp_ino >> 32; +#endif + + out: + unionfs_print(PRINT_MAIN_EXIT, "%d, fh{i%u, g%d, hr%x, hi%u, hpi%u}\n", + type, fh[0], fh[1], fh[FhHRoot2], fh[FhHIno2], + fh[FhHPIno2]); + unlock_dentry(dentry); + unionfs_read_unlock(sb); + return type; +} + +static struct dentry *unionfs_decode_fh(struct super_block *sb, __u32 * fh, + int fh_len, int fh_type, + int (*acceptable) (void *context, + struct dentry * de), + void *context) +{ + struct dentry *dentry, *hidden_root; + ino_t hidden_ino, hidden_parent_ino; + + print_entry("%d, fh{i%u, g%d, hr%x, hi%u, hpi%u}", + fh_type, fh[0], fh[1], fh[FhHRoot2], fh[FhHIno2], + fh[FhHPIno2]); + + dentry = export_op_default.get_dentry(sb, fh); + if (!dentry || IS_ERR(dentry) || (dentry->d_inode && !is_anon(dentry))) + return dentry; + + d_drop(dentry); + DPUT(dentry); + do_decode(fh, &hidden_root, &hidden_ino, &hidden_parent_ino); + dentry = do_get_dentry(sb, fh[0], fh[1], hidden_root, hidden_ino, + hidden_parent_ino); + if (!IS_ERR(dentry)) { + if (acceptable(context, dentry)) + return dentry; /* success */ + DPUT(dentry); + dentry = NULL; + } + return dentry; +} + +struct export_operations unionfs_export_ops = { + .decode_fh = unionfs_decode_fh, + .encode_fh = unionfs_encode_fh +}; +#endif + +struct super_operations unionfs_sops = { + //.put_inode = unionfs_put_inode, + .delete_inode = unionfs_delete_inode, + .put_super = unionfs_put_super, + .statfs = unionfs_statfs, + .remount_fs = unionfs_remount_fs, + .clear_inode = unionfs_clear_inode, + .umount_begin = unionfs_umount_begin, + .show_options = unionfs_show_options, + .write_inode = unionfs_write_inode, + .alloc_inode = unionfs_alloc_inode, + .destroy_inode = unionfs_destroy_inode, +}; + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/persistent_inode.c +++ linux-2.6.27/ubuntu/unionfs/persistent_inode.c @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef Sipek + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: persistent_inode.c,v 1.36 2006/07/08 17:58:31 ezk Exp $ + */ +#ifdef UNIONFS_IMAP + +#include "unionfs.h" + +static ssize_t __fread(struct file *filp, void *buf, size_t size, loff_t * pos) +{ + int err; + mm_segment_t oldfs; + ssize_t(*func) (struct file *, char __user *, size_t, loff_t *); + + func = do_sync_read; + if (filp->f_op && filp->f_op->read) + func = filp->f_op->read; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + do { + err = func(filp, (char __user *)buf, size, pos); + } while (err == -EAGAIN || err == -EINTR); + set_fs(oldfs); + return err; +} + +static ssize_t __fwrite(struct file *filp, void *buf, size_t size, loff_t * pos) +{ + int err; + mm_segment_t oldfs; + unsigned long flim; + struct rlimit *rl; + ssize_t(*func) (struct file *, const char __user *, size_t, loff_t *); + + func = do_sync_write; + if (filp->f_op && filp->f_op->write) + func = filp->f_op->write; + + /* + * it breaks RLIMIT_FSIZE, + * but users should be careful to quota. + */ + rl = current->signal->rlim + RLIMIT_FSIZE; + flim = rl->rlim_cur; + rl->rlim_cur = RLIM_INFINITY; + oldfs = get_fs(); + set_fs(KERNEL_DS); + do { + err = func(filp, (const char __user *)buf, size, pos); + } while (err == -EAGAIN || err == -EINTR); + set_fs(oldfs); + rl->rlim_cur = flim; + return err; +} + +/* + * verify_forwardmap(super_block *sb) + * sb: pointer to a superblock containing the forwardmap. + * returns: 0 on success EINVAL or ENOMEM on failure; + */ +static int verify_forwardmap(struct super_block *sb) +{ + int err = 0, bytesread = 0, bindex = 0, mallocsize = 0; + loff_t readpos = 0; + struct file *forwardmap = NULL; + struct fmaphdr header; + struct unionfs_sb_info *spd = NULL; + print_entry_location(); + + spd = stopd(sb); + BUG_ON(!spd); + + forwardmap = spd->usi_forwardmap; + if (!forwardmap) { + err = -EINVAL; + goto out; + } + bytesread = __fread(forwardmap, &header, sizeof(struct fmaphdr), + &readpos); + if (bytesread < sizeof(struct fmaphdr)) { + err = -EINVAL; + goto out; + } + if (header.magic != FORWARDMAP_MAGIC + || header.version != FORWARDMAP_VERSION) { + err = -EINVAL; + goto out; + } + spd->usi_bmap = + KMALLOC(sizeof(struct bmapent) * header.usedbranches, GFP_KERNEL); + + if (!spd->usi_bmap) { + err = -ENOMEM; + goto out; + } + + while (bindex < header.usedbranches) { + bytesread = __fread(forwardmap, &stopd(sb)->usi_bmap[bindex], + sizeof(struct bmapent), &readpos); + if (bytesread < sizeof(struct bmapent)) { + err = -EINVAL; + goto out_err; + } + bindex++; + } + + mallocsize = sizeof(int) * header.usedbranches; + goto out; + out_err: + if (spd->usi_bmap) + KFREE(spd->usi_bmap); + out: + print_exit_status(err); + return err; +} + +/* + * verify_reversemap(struct super_block sb, int rmapindex) + * + * sb: The unionfs superblock containing all of the current imap info + * rmapindex: the index in the usi_reversemaps array that we wish to + * verify + * + * Assumes the reverse maps less than rmapindex are valid. + * + * returns: 0 if the opperation succeds + * -EINVAL if the map file does not belong to the forward map + * + */ +static int verify_reversemap(struct super_block *sb, int rmapindex, + struct unionfs_dentry_info *hidden_root_info) +{ + int err = 0, i = 0, bindex = 0, found = 0, bytesread; + loff_t readpos = 0; + struct file *forwardmap, *reversemap; + struct fmaphdr fheader; + struct rmaphdr rheader; + struct kstatfs st; + struct unionfs_sb_info *spd = NULL; + + print_entry_location(); + + spd = stopd(sb); + BUG_ON(!spd); + + forwardmap = spd->usi_forwardmap; + if (!forwardmap) { + err = -EINVAL; + goto out; + } + reversemap = spd->usi_reversemaps[rmapindex]; + if (!reversemap) { + err = -EINVAL; + goto out; + } + bytesread = __fread(forwardmap, &fheader, sizeof(struct fmaphdr), + &readpos); + if (bytesread < sizeof(struct fmaphdr)) { + err = -EINVAL; + goto out; + } + readpos = 0; + bytesread = __fread(reversemap, &rheader, sizeof(struct rmaphdr), + &readpos); + if (bytesread < sizeof(struct rmaphdr)) { + err = -EINVAL; + goto out; + } + if (rheader.magic != REVERSEMAP_MAGIC + || rheader.version != REVERSEMAP_VERSION) { + err = -EINVAL; + goto out; + } + if (memcmp(fheader.uuid, rheader.fwduuid, sizeof(fheader.uuid))) { + err = -EINVAL; + goto out; + } + + /* XXX: Ok so here we take the new map and read the fsid from it. Then + * we go through all the branches in the union and see which ones it + * matches with*/ + for (i = 0; i < spd->usi_num_bmapents && !found; i++) { + if (memcmp + (rheader.revuuid, spd->usi_bmap[i].uuid, + sizeof(rheader.revuuid))) + continue; + + found = 1; + for (bindex = 0; bindex <= hidden_root_info->udi_bend; bindex++) { + struct dentry *d; + fsid_t fsid; + dev_t dev; + memset(&st, 0, sizeof(struct kstatfs)); + + d = hidden_root_info->udi_dentry[bindex]; + + err = d->d_sb->s_op->statfs(d->d_sb, &st); + if (err) + goto out; + + if (st.f_fsid.val[0] || st.f_fsid.val[1]) { + fsid = st.f_fsid; + } else { + + dev = d->d_sb->s_dev; + fsid.val[0] = MAJOR(dev); + fsid.val[1] = MINOR(dev); + } + + if (memcmp(&fsid, &rheader.fsid, sizeof(fsid))) + continue; + + if (spd->usi_bnum_table[bindex] == -1) + spd->usi_bnum_table[bindex] = i; + if (spd->usi_map_table[bindex]) { + printk(KERN_WARNING + "Two reverse maps share fsid %u%u!\n", + rheader.fsid.val[0], + rheader.fsid.val[1]); + err = -EINVAL; + goto out; + } else { + spd->usi_map_table[bindex] = reversemap; + } + } + } + if (!found) { + printk(KERN_WARNING + "Could not match the reversemap uuid with an entry in the forwardmap table\n"); + err = -EINVAL; + } + out: + print_exit_status(err); + return err; +} + +int init_imap_data(struct super_block *sb, + struct unionfs_dentry_info *hidden_root_info) +{ + int i, err = 0, mallocsize = 0; + struct unionfs_sb_info *spd; + + print_entry_location(); + + spd = stopd(sb); + + spd->usi_forwardmap = NULL; + spd->usi_reversemaps = NULL; + spd->usi_bnum_table = NULL; + + mallocsize = sizeof(struct file *) * (hidden_root_info->udi_bend + 1); + spd->usi_reversemaps = KZALLOC(mallocsize, GFP_KERNEL); + if (!spd->usi_reversemaps) { + err = -ENOMEM; + goto out_error; + } + + spd->usi_map_table = KZALLOC(mallocsize, GFP_KERNEL); + if (!spd->usi_map_table) { + err = -ENOMEM; + goto out_error; + } + + mallocsize = sizeof(int) * (hidden_root_info->udi_bend + 1); + spd->usi_bnum_table = KMALLOC(mallocsize, GFP_KERNEL); + if (!spd->usi_bnum_table) { + err = -ENOMEM; + goto out_error; + } + + for (i = 0; i <= hidden_root_info->udi_bend; i++) { + spd->usi_bnum_table[i] = -1; + } + + if (!err) + goto out; + out_error: + + if (spd->usi_reversemaps) { + KFREE(spd->usi_reversemaps); + spd->usi_reversemaps = NULL; + } + + if (spd->usi_map_table) { + KFREE(spd->usi_map_table); + spd->usi_map_table = NULL; + } + + if (spd->usi_bnum_table) { + KFREE(spd->usi_bnum_table); + spd->usi_bnum_table = NULL; + + } + + out: + print_exit_status(err); + return err; + +} + +void cleanup_imap_data(struct super_block *sb) +{ + int count = 0; + struct unionfs_sb_info *spd; + + print_entry_location(); + + spd = stopd(sb); + + spd->usi_persistent = 0; + count = spd->usi_num_bmapents; + while (count - 1 >= 0) { + if (spd->usi_reversemaps[count - 1]) { + filp_close(spd->usi_reversemaps[count - 1], NULL); + spd->usi_reversemaps[count - 1] = NULL; + } + count--; + } + if (spd->usi_reversemaps) { + KFREE(spd->usi_reversemaps); + spd->usi_reversemaps = NULL; + } + + if (spd->usi_map_table) { + KFREE(spd->usi_map_table); + spd->usi_map_table = NULL; + } + + if (spd->usi_bnum_table) { + KFREE(spd->usi_bnum_table); + spd->usi_bnum_table = NULL; + } + if (spd->usi_forwardmap) { + filp_close(spd->usi_forwardmap, NULL); + spd->usi_forwardmap = NULL; + } + print_exit_location(); +} + +int parse_imap_option(struct super_block *sb, + struct unionfs_dentry_info *hidden_root_info, + char *options) +{ + int count = 0, err = 0; + char *name; + struct unionfs_sb_info *spd = NULL; + + print_entry_location(); + spd = stopd(sb); + BUG_ON(!spd); + + err = init_imap_data(sb, hidden_root_info); + if (err) + goto out_error; + while ((name = strsep(&options, ":")) != NULL) { + if (!*name) + continue; + if (!spd->usi_forwardmap) { + spd->usi_forwardmap = filp_open(name, O_RDWR, 0); + if (IS_ERR(spd->usi_forwardmap)) { + err = PTR_ERR(spd->usi_forwardmap); + spd->usi_forwardmap = NULL; + goto out_error; + } + } else { + spd->usi_reversemaps[count] = + filp_open(name, O_RDWR, 0); + if (IS_ERR(spd->usi_reversemaps[count])) { + err = PTR_ERR(spd->usi_reversemaps[count]); + spd->usi_reversemaps[count] = NULL; + goto out_error; + + } + count++; + } + } + if (count <= 0) { + printk(KERN_WARNING "unionfs: no reverse maps specified.\n"); + err = -EINVAL; + } + if (err) + goto out_error; + + /* Initialize the super block's next_avail field */ + /* Dave, you can't use 64-bit division here because the i386 doesn't + * support it natively. Instead you need to punt if the size is + * greater than unsigned long, and then cast it down. Then you should + * be able to assign to this value, without having these problems. */ + + if (spd->usi_forwardmap->f_dentry->d_inode->i_size > ULONG_MAX) { + err = -EFBIG; + goto out_error; + } + spd->usi_next_avail = + ((unsigned long)(spd->usi_forwardmap->f_dentry->d_inode-> + i_size - (sizeof(struct fmaphdr) + + sizeof(struct bmapent[256]))) + / sizeof(struct fmapent)); + + if (spd->usi_next_avail < FIRST_VALID_INODE) + spd->usi_next_avail = FIRST_VALID_INODE; + + spd->usi_num_bmapents = count; + err = verify_forwardmap(sb); + if (err) + goto out_error; + while (count > 0) { + err = verify_reversemap(sb, --count, hidden_root_info); + if (err) + goto out_error; + } + spd->usi_persistent = 1; + + goto out; + + out_error: + spd->usi_num_bmapents = count; + cleanup_imap_data(sb); + + out: + print_exit_status(err); + return err; +} + + /* + * get @ino from @hidden_ino. + */ +static int __read_uin(struct unionfs_sb_info *sbi, ino_t hidden_ino, int bindex, + ino_t * ino) +{ + int err; + struct file *rev; + loff_t pos; + ssize_t sz; + uint64_t ino64; + const int elmnt = sizeof(ino64); + + rev = sbi->usi_map_table[bindex]; + pos = sizeof(struct rmaphdr) + elmnt * hidden_ino; + *ino = 0; + err = 0; + if (pos + elmnt > rev->f_dentry->d_inode->i_size) + goto out; + + sz = __fread(rev, &ino64, elmnt, &pos); + err = sz; + if (err < 0) + goto out; + err = 0; + *ino = -1; + if (sz != elmnt || ino64 > *ino) + err = -EIO; + *ino = ino64; + out: + print_exit_status(err); + return err; +} + +/* + * put unionfs @ino for @hidden_ino on @bindex. + */ +static int __write_uin(struct unionfs_sb_info *sbi, ino_t ino, int bindex, + ino_t hidden_ino) +{ + struct file *fwd, *rev; + struct fmapent ent; + loff_t pos; + ssize_t sz; + int err; + uint64_t ino64; + const int fwdhdr = sizeof(struct fmaphdr) + sizeof(struct bmapent[256]); + const int fwd_elmnt = sizeof(ent); + const int rev_elmnt = sizeof(ino64); + + err = -ENOSPC; + if (ino < FIRST_VALID_INODE) + goto out; + + fwd = sbi->usi_forwardmap; + ent.fsnum = sbi->usi_bnum_table[bindex]; + ent.inode = hidden_ino; + pos = fwdhdr + fwd_elmnt * ino; + sz = __fwrite(fwd, &ent, fwd_elmnt, &pos); + err = sz; + if (err < 0) + goto out; + err = -EIO; + if (sz != fwd_elmnt) + goto out; + + rev = sbi->usi_map_table[bindex]; + pos = sizeof(struct rmaphdr) + rev_elmnt * hidden_ino; + ino64 = ino; + sz = __fwrite(rev, &ino64, rev_elmnt, &pos); + err = sz; + if (err < 0) + goto out; + err = 0; + if (sz != rev_elmnt) + err = -EIO; + out: + print_exit_status(err); + return err; +} + +/* + * read_uin(struct super_block *sb, uint8_t branchnum, ino_t inode_number, int flag, ino_t *uino) + * fsnum: branch to reference when getting the inode number + * inode_number: lower level inode number use to reference the proper inode. + * flag: if set to O_CREAT it will creat the entry if it doesent exist + * otherwise it will return the existing one. + * returns: the unionfs inode number either created or retrieved based on + * the information. + */ +int read_uin(struct super_block *sb, uint8_t branchnum, ino_t inode_number, + int flag, ino_t * uino) +{ + int err = 0; + struct unionfs_sb_info *spd; + + print_entry_location(); + + spd = stopd(sb); + BUG_ON(!spd); + + /* Find appropriate reverse map and then read from the required position */ + /* get it from the array. */ + err = __read_uin(spd, inode_number, branchnum, uino); + if (err || *uino) + goto out; + + err = -EIO; + if (!(flag & O_CREAT)) + goto out; + + /* If we haven't found an entry and we have the O_CREAT flag set we want to + * create a new entry write it out to the file and return its index + */ + mutex_lock(&sb->s_lock); + *uino = spd->usi_next_avail++; + err = __write_uin(spd, *uino, branchnum, inode_number); + if (err) + spd->usi_next_avail--; + mutex_unlock(&sb->s_lock); + out: + print_exit_status(err); + return err; +} + +int write_uin(struct super_block *sb, ino_t ino, int bindex, ino_t hidden_ino) +{ + int err; + + print_entry_location(); + err = __write_uin(stopd(sb), ino, bindex, hidden_ino); + print_exit_status(err); + return err; +} + +/* + * get_lin(ino_t inode_number) + * inode_number : inode number for the unionfs inode + * returns: the lower level inode# and branch# + */ +/* entry should use a poiner on the stack. should be staticly allocated one + * level up*/ +int get_lin(struct super_block *sb, ino_t inode_number, struct fmapent *entry) +{ + struct file *forwardmap; + loff_t seek_size; + mm_segment_t oldfs; + int err = 0, bytesread = 0; + + print_entry_location(); + + if (!entry) { + entry = ERR_PTR(-ENOMEM); + goto out; + } + forwardmap = stopd(sb)->usi_forwardmap; + seek_size = + sizeof(struct fmaphdr) + sizeof(struct bmapent[256]) + + (sizeof(struct fmapent) * inode_number); + oldfs = get_fs(); + set_fs(KERNEL_DS); + bytesread = __fread(forwardmap, entry, sizeof(*entry), &seek_size); + set_fs(oldfs); + if (bytesread != sizeof(*entry)) + err = -EINVAL; + + out: + print_exit_location(); + return err; +} + +/* + * remove_map(struct super_block *sb,int bindex) + * + * sb: The super block containing all the current imap info + * bindex: the index of the branch that is being removed. + * + * This assumes that end hasen't been decremented yet. + * + * Returns: This function really can't fail. The only thing + * that could possibly happen is that it will oops but that + * requires unionfs to be in an inconsistant state which + * shoulden't happen. + */ +int remove_map(struct super_block *sb, int bindex) +{ + int i; + struct unionfs_sb_info *spd; + + print_entry_location(); + + spd = stopd(sb); + BUG_ON(!spd); + + for (i = bindex; i < sbend(sb); i++) { + spd->usi_map_table[i] = spd->usi_map_table[i + 1]; + spd->usi_bnum_table[i] = spd->usi_bnum_table[i + 1]; + } + return 0; +} + +#endif +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/Kconfig +++ linux-2.6.27/ubuntu/unionfs/Kconfig @@ -0,0 +1,9 @@ +config FS_UNIONFS + tristate "UnionFS 1.4 Legacy" + default m + help + This is the v1.4 module, forward ported and beaten into + AppArmor submission. It is a fallback for aufs in case it ends + up being broken. We know this one works for the LiveCD, so + this is to keep the release managers from having to spend + long nights and pushing off deadlines. --- linux-2.6.27.orig/ubuntu/unionfs/unionfs.h +++ linux-2.6.27/ubuntu/unionfs/unionfs.h @@ -0,0 +1,736 @@ +#ifndef __UNIONFS_H_ +#define __UNIONFS_H_ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#ifndef UNIONFS_UNSUPPORTED +#if LINUX_VERSION_CODE != KERNEL_VERSION(SUP_MAJOR,SUP_MINOR,SUP_PATCH) +#warning You are compiling Unionfs on an unsupported kernel version. +#warning To compile Unionfs, you will need to define UNIONFS_UNSUPPORTED. +#warning Try adding: EXTRACFLAGS=-DUNIONFS_UNSUPPORTED to fistdev.mk +#endif +#endif + +/* the file system name */ +#define UNIONFS_NAME "unionfs" + +/* unionfs file systems superblock magic */ +#define UNIONFS_SUPER_MAGIC 0xf15f083d + +/* unionfs root inode number */ +#define UNIONFS_ROOT_INO 1 + +/* Mount time flags */ +#define MOUNT_FLAG(sb) (stopd(sb)->usi_mount_flag) + +/* number of characters while generating unique temporary file names */ +#define UNIONFS_TMPNAM_LEN 12 + +/* Operations vectors defined in specific files. */ +extern struct file_operations unionfs_main_fops; +extern struct file_operations unionfs_dir_fops; +extern struct inode_operations unionfs_main_iops; +extern struct inode_operations unionfs_dir_iops; +extern struct inode_operations unionfs_symlink_iops; +extern struct super_operations unionfs_sops; +extern struct dentry_operations unionfs_dops; +#ifdef CONFIG_EXPORTFS +extern struct export_operations unionfs_export_ops; +#endif + +/* How long should an entry be allowed to persist */ +#define RDCACHE_JIFFIES 5*HZ + +/* file private data. */ +struct unionfs_file_info { + int b_start; + int b_end; + atomic_t ufi_generation; + + struct unionfs_dir_state *rdstate; + struct file **ufi_file; +}; + +/* unionfs inode data in memory */ +struct unionfs_inode_info { + int b_start; + int b_end; + atomic_t uii_generation; + int uii_stale; + /* Stuff for readdir over NFS. */ + spinlock_t uii_rdlock; + struct list_head uii_readdircache; + int uii_rdcount; + int uii_hashsize; + int uii_cookie; + /* The hidden inodes */ + struct inode **uii_inode; + /* to keep track of reads/writes for unlinks before closes */ + atomic_t uii_totalopens; +}; + +struct unionfs_inode_container { + struct unionfs_inode_info info; + struct inode vfs_inode; +}; + +/* unionfs dentry data in memory */ +struct unionfs_dentry_info { + /* The semaphore is used to lock the dentry as soon as we get into a + * unionfs function from the VFS. Our lock ordering is that children + * go before their parents. */ + struct semaphore udi_sem; + int udi_bstart; + int udi_bend; + int udi_bopaque; + int udi_bcount; + atomic_t udi_generation; + struct dentry **udi_dentry; +}; + +/* A putmap is used so that older files can still do branchput correctly. */ +struct putmap { + atomic_t count; + int bend; + int map[0]; +}; + +/* These are the pointers to our various objects. */ +struct unionfs_usi_data { + struct super_block *sb; + struct vfsmount *hidden_mnt; + atomic_t sbcount; + int branchperms; +}; + +/* unionfs super-block data in memory */ +struct unionfs_sb_info { + int b_end; + + atomic_t usi_generation; + unsigned long usi_mount_flag; + struct rw_semaphore usi_rwsem; + + struct unionfs_usi_data *usi_data; + + /* These map branch numbers for old generation numbers to the new bindex, + * so that branchput will behave properly. */ + int usi_firstputmap; + int usi_lastputmap; + struct putmap **usi_putmaps; + +#ifdef UNIONFS_IMAP + int usi_persistent; + /* These will need a lock. */ + uint64_t usi_next_avail; + uint8_t usi_num_bmapents; + struct bmapent *usi_bmap; + struct file *usi_forwardmap; + struct file **usi_reversemaps; + struct file **usi_map_table; + int *usi_bnum_table; //This is a table of branches to fsnums. +#endif /* UNIONFS_IMAP */ +}; + +/* + * structure for making the linked list of entries by readdir on left branch + * to compare with entries on right branch + */ +struct filldir_node { + struct list_head file_list; // list for directory entries + char *name; // name entry + int hash; // name hash + int namelen; // name len since name is not 0 terminated + int bindex; // we can check for duplicate whiteouts and files in the same branch in order to return -EIO. + int whiteout; // is this a whiteout entry? + char iname[DNAME_INLINE_LEN_MIN]; // Inline name, so we don't need to separately kmalloc small ones +}; + +/* Directory hash table. */ +struct unionfs_dir_state { + unsigned int uds_cookie; /* The cookie, which is based off of uii_rdversion */ + unsigned int uds_offset; /* The entry we have returned. */ + int uds_bindex; + loff_t uds_dirpos; /* The offset within the lower level directory. */ + int uds_size; /* How big is the hash table? */ + int uds_hashentries; /* How many entries have been inserted? */ + unsigned long uds_access; + /* This cache list is used when the inode keeps us around. */ + struct list_head uds_cache; + struct list_head uds_list[0]; +}; + +/* privileged io workqueue */ +#include "sioq.h" + +/* include miscellaneous macros */ +#include "unionfs_macros.h" + +/* include debug macros */ +#include "unionfs_debug.h" + +/* include persistent imap code */ +#include "unionfs_imap.h" + +/* Cache creation/deletion routines. */ +void destroy_filldir_cache(void); +int init_filldir_cache(void); +int init_inode_cache(void); +void destroy_inode_cache(void); +int init_dentry_cache(void); +void destroy_dentry_cache(void); + +/* Initialize and free readdir-specific state. */ +int init_rdstate(struct file *file); +struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex); +struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos); +void free_rdstate(struct unionfs_dir_state *state); +int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name, + int namelen, int bindex, int whiteout); +struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate, + const char *name, int namelen); + +struct dentry **alloc_new_dentries(int objs); +struct unionfs_usi_data *alloc_new_data(int objs); + +#ifdef FIST_MALLOC_DEBUG + +extern void *unionfs_kzalloc(size_t size, gfp_t flags, int line, + const char *file); +extern void *unionfs_kmalloc(size_t size, gfp_t flags, int line, + const char *file); +extern void unionfs_kfree(void *ptr, int line, const char *file); + +extern struct dentry *unionfs_dget_parent(struct dentry *child, int line, + const char *file); +extern struct dentry *unionfs_dget(struct dentry *ptr, int line, + const char *file); +extern void unionfs_dput(struct dentry *ptr, int line, const char *file); +extern struct inode *unionfs_igrab(struct inode *inode, int line, char *file); +extern void unionfs_iput(struct inode *inode, int line, char *file); +extern struct dentry *unionfs_lookup_one_len(const char *name, + struct dentry *parent, int len, + int line, const char *file); +void record_path_lookup(struct nameidata *nd, int line, const char *file); +void record_path_release(struct nameidata *nd, int line, const char *file); +struct file *unionfs_dentry_open(struct dentry *ptr, struct vfsmount *mnt, + int flags, int line, const char *file); +void record_set(struct dentry *upper, int index, struct dentry *ptr, + struct dentry *old, int line, const char *file); + +#define KZALLOC(size,flags) unionfs_kzalloc((size),(flags),__LINE__,__FILE__) +#define KMALLOC(size,flags) unionfs_kmalloc((size),(flags),__LINE__,__FILE__) +#define KFREE(ptr) unionfs_kfree((ptr),__LINE__,__FILE__) +#define DGET(d) unionfs_dget((d),__LINE__,__FILE__) +#define DPUT(d) unionfs_dput((d),__LINE__,__FILE__) +# define IPUT(a) unionfs_iput((a),__LINE__,__FILE__) +# define IGRAB(a) unionfs_igrab((a),__LINE__,__FILE__) +#define LOOKUP_ONE_LEN(name,parent,len) unionfs_lookup_one_len((name),(parent),(len),__LINE__,__FILE__) +# define RECORD_PATH_LOOKUP(nd) record_path_lookup((nd),__LINE__,__FILE__) +# define RECORD_PATH_RELEASE(nd) record_path_release((nd),__LINE__,__FILE__) +/* This has the effect of reducing the reference count sooner or later, + * if the file is closed. If it isn't then the mount will be busy and + * you can't unmount. + */ +# define DENTRY_OPEN(d,m,f) unionfs_dentry_open((d),(m),(f),__LINE__,__FILE__) +# define GET_PARENT(dentry) unionfs_dget_parent((dentry),__LINE__,__FILE__) +#else /* not FIST_MALLOC_DEBUG */ +# define KZALLOC(a,b) kzalloc((a),(b)) +# define KMALLOC(a,b) kmalloc((a),(b)) +# define KFREE(a) kfree((a)) +# define DPUT(a) dput((a)) +# define DGET(a) dget((a)) +# define IPUT(a) iput((a)) +# define IGRAB(a) igrab((a)) +# define LOOKUP_ONE_LEN(a,b,c) lookup_one_len((a),(b),(c)) +# define RECORD_PATH_LOOKUP(a) +# define RECORD_PATH_RELEASE(a) +# define DENTRY_OPEN(d,m,f) dentry_open((d),(m),(f)) +# define GET_PARENT(d) dget_parent(d) +#endif /* not FIST_MALLOC_DEBUG */ + +/* We can only use 32-bits of offset for rdstate --- blech! */ +#define DIREOF (0xfffff) +#define RDOFFBITS 20 /* This is the number of bits in DIREOF. */ +#define MAXRDCOOKIE (0xfff) +/* Turn an rdstate into an offset. */ +static inline off_t rdstate2offset(struct unionfs_dir_state *buf) +{ + off_t tmp; + tmp = + ((buf->uds_cookie & MAXRDCOOKIE) << RDOFFBITS) | (buf-> + uds_offset & + DIREOF); + return tmp; +} + +#define unionfs_read_lock(sb) down_read(&stopd(sb)->usi_rwsem) +#define unionfs_read_unlock(sb) up_read(&stopd(sb)->usi_rwsem) +#define unionfs_write_lock(sb) down_write(&stopd(sb)->usi_rwsem) +#define unionfs_write_unlock(sb) up_write(&stopd(sb)->usi_rwsem) + +/* The double lock function needs to go after the debugmacros, so that + * dtopd is defined. */ +static inline void double_lock_dentry(struct dentry *d1, struct dentry *d2) +{ + if (d2 < d1) { + struct dentry *tmp = d1; + d1 = d2; + d2 = tmp; + } + lock_dentry(d1); + lock_dentry(d2); +} + +extern int new_dentry_private_data(struct dentry *dentry); +void free_dentry_private_data(struct unionfs_dentry_info *udi); +void update_bstart(struct dentry *dentry); +#define sbt(sb) ((sb)->s_type->name) + +/* + * EXTERNALS: + */ +/* replicates the directory structure upto given dentry in given branch */ +extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry, + int bindex); +struct dentry *create_parents_named(struct inode *dir, struct dentry *dentry, + const char *name, int bindex); + +/* check if two branches overlap */ +extern int is_branch_overlap(struct dentry *dent1, struct dentry *dent2); + +/* partial lookup */ +extern int unionfs_partial_lookup(struct dentry *dentry); + +/* Pass an unionfs dentry and an index and it will try to create a whiteout in branch 'index'. + On error, it will proceed to a branch to the left */ +extern int create_whiteout(struct dentry *dentry, int start); +/* copies a file from dbstart to newbindex branch */ +extern int copyup_file(struct inode *dir, struct file *file, int bstart, + int newbindex, loff_t size); +extern int copyup_named_file(struct inode *dir, struct file *file, + char *name, int bstart, int new_bindex, + loff_t len); + +/* copies a dentry from dbstart to newbindex branch */ +extern int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart, + int new_bindex, struct file **copyup_file, loff_t len); +extern int copyup_named_dentry(struct inode *dir, struct dentry *dentry, + int bstart, int new_bindex, const char *name, + int namelen, struct file **copyup_file, + loff_t len); + +extern int remove_whiteouts(struct dentry *dentry, struct dentry *hidden_dentry, + int bindex); + +/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */ +extern int check_empty(struct dentry *dentry, + struct unionfs_dir_state **namelist); +/* Delete whiteouts from this directory in branch bindex. */ +extern int delete_whiteouts(struct dentry *dentry, int bindex, + struct unionfs_dir_state *namelist); + +/* Re-lookup a hidden dentry. */ +extern int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex); + +extern void unionfs_reinterpose(struct dentry *this_dentry); +extern struct super_block *unionfs_duplicate_super(struct super_block *sb); + +/* Locking functions. */ +extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl); +extern int unionfs_getlk(struct file *file, struct file_lock *fl); + +/* Common file operations. */ +extern int unionfs_file_revalidate(struct file *file, int willwrite); +extern int unionfs_open(struct inode *inode, struct file *file); +extern int unionfs_file_release(struct inode *inode, struct file *file); +extern int unionfs_flush(struct file *file, fl_owner_t id); +extern long unionfs_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); + +/* Inode operations */ +extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry); +int unionfs_unlink(struct inode *dir, struct dentry *dentry); +int unionfs_rmdir(struct inode *dir, struct dentry *dentry); + +int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd); + +/* The values for unionfs_interpose's flag. */ +#define INTERPOSE_DEFAULT 0 +#define INTERPOSE_LOOKUP 1 +#define INTERPOSE_REVAL 2 +#define INTERPOSE_REVAL_NEG 3 +#define INTERPOSE_PARTIAL 4 + +extern int unionfs_interpose(struct dentry *this_dentry, struct super_block *sb, + int flag); + +/* Branch management ioctls. */ +int unionfs_ioctl_branchcount(struct file *file, unsigned int cmd, + unsigned long arg); +int unionfs_ioctl_incgen(struct file *file, unsigned int cmd, + unsigned long arg); +int unionfs_ioctl_addbranch(struct inode *inode, unsigned int cmd, + unsigned long arg); +int unionfs_ioctl_delbranch(struct super_block *sb, unsigned long arg); +int unionfs_ioctl_rdwrbranch(struct inode *inode, unsigned int cmd, + unsigned long arg); +int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd, + unsigned long arg); + +/* Verify that a branch is valid. */ +int check_branch(struct nameidata *nd); + +/* Extended attribute functions. */ +extern void *xattr_alloc(size_t size, size_t limit); +extern void xattr_free(void *ptr, size_t size); + +extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, + void *value, size_t size); +extern int unionfs_removexattr(struct dentry *dentry, const char *name); +extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list, + size_t size); + +int unionfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags); + +/* The root directory is unhashed, but isn't deleted. */ +static inline int d_deleted(struct dentry *d) +{ + return d_unhashed(d) && (d != d->d_sb->s_root); +} + +/* returns the sum of the n_link values of all the underlying inodes of the passed inode */ +static inline int get_nlinks(struct inode *inode) +{ + int sum_nlinks = 0; + int dirs = 0; + int bindex; + struct inode *hidden_inode; + + if (!S_ISDIR(inode->i_mode)) + return itohi(inode)->i_nlink; + + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) { + hidden_inode = itohi_index(inode, bindex); + if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode)) + continue; + BUG_ON(hidden_inode->i_nlink < 0); + + /* A deleted directory. */ + if (hidden_inode->i_nlink == 0) + continue; + dirs++; + /* A broken directory (e.g., squashfs). */ + if (hidden_inode->i_nlink == 1) + sum_nlinks += 2; + else + sum_nlinks += (hidden_inode->i_nlink - 2); + } + + if (!dirs) + return 0; + return sum_nlinks + 2; +} + +static inline void fist_copy_attr_atime(struct inode *dest, + const struct inode *src) +{ + dest->i_atime = src->i_atime; +} +static inline void fist_copy_attr_times(struct inode *dest, + const struct inode *src) +{ + dest->i_atime = src->i_atime; + dest->i_mtime = src->i_mtime; + dest->i_ctime = src->i_ctime; +} +static inline void fist_copy_attr_timesizes(struct inode *dest, + const struct inode *src) +{ + dest->i_atime = src->i_atime; + dest->i_mtime = src->i_mtime; + dest->i_ctime = src->i_ctime; + dest->i_size = src->i_size; + dest->i_blocks = src->i_blocks; +} +static inline void fist_copy_attr_all(struct inode *dest, + const struct inode *src) +{ + print_entry_location(); + + dest->i_mode = src->i_mode; + /* we do not need to copy if the file is a deleted file */ + if (dest->i_nlink > 0) + dest->i_nlink = get_nlinks(dest); + dest->i_uid = src->i_uid; + dest->i_gid = src->i_gid; + dest->i_rdev = src->i_rdev; + dest->i_atime = src->i_atime; + dest->i_mtime = src->i_mtime; + dest->i_ctime = src->i_ctime; + dest->i_blkbits = src->i_blkbits; + dest->i_size = src->i_size; + dest->i_blocks = src->i_blocks; + dest->i_flags = src->i_flags; + + print_exit_location(); +} + +struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *nd, int lookupmode); +int is_stale_inode(struct inode *inode); +void make_stale_inode(struct inode *inode); + +#define IS_SET(sb, check_flag) (check_flag & MOUNT_FLAG(sb)) + +/* unionfs_permission, check if we should bypass error to facilitate copyup */ +#define IS_COPYUP_ERR(err) (err == -EROFS) + +/* unionfs_open, check if we need to copyup the file */ +#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND) +#define IS_WRITE_FLAG(flag) (flag & (OPEN_WRITE_FLAGS)) + +static inline int branchperms(struct super_block *sb, int index) +{ + BUG_ON(index < 0); + + return stopd(sb)->usi_data[index].branchperms; +} +static inline int set_branchperms(struct super_block *sb, int index, int perms) +{ + BUG_ON(index < 0); + + stopd(sb)->usi_data[index].branchperms = perms; + + return perms; +} + +/* Is this file on a read-only branch? */ +static inline int __is_robranch_super(struct super_block *sb, int index, + char *file, const char *function, + int line) +{ + int err = 0; + + print_util_entry_location(); + + if (!(branchperms(sb, index) & MAY_WRITE)) + err = -EROFS; + + print_util_exit_status(err); + return err; +} + +/* Is this file on a read-only branch? */ +static inline int __is_robranch_index(struct dentry *dentry, int index, + char *file, const char *function, + int line) +{ + int err = 0; + int perms; + + print_util_entry_location(); + + BUG_ON(index < 0); + + perms = stopd(dentry->d_sb)->usi_data[index].branchperms; + + if ((!(perms & MAY_WRITE)) + || (IS_RDONLY(dtohd_index(dentry, index)->d_inode))) + err = -EROFS; + + print_util_exit_status(err); + + return err; +} +static inline int __is_robranch(struct dentry *dentry, char *file, + const char *function, int line) +{ + int index; + int err; + + print_util_entry_location(); + + index = dtopd(dentry)->udi_bstart; + BUG_ON(index < 0); + + err = __is_robranch_index(dentry, index, file, function, line); + + print_util_exit_status(err); + + return err; +} + +#define is_robranch(d) __is_robranch(d, __FILE__, __FUNCTION__, __LINE__) +#define is_robranch_super(s, n) __is_robranch_super(s, n, __FILE__, __FUNCTION__, __LINE__) + +/* What do we use for whiteouts. */ +#define WHPFX ".wh." +#define WHLEN 4 +/* If a directory contains this file, then it is opaque. We start with the + * .wh. flag so that it is blocked by loomkup. + */ +#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque" +#define UNIONFS_DIR_OPAQUE WHPFX UNIONFS_DIR_OPAQUE_NAME + +/* construct whiteout filename */ +static inline char *alloc_whname(const char *name, int len) +{ + char *buf; + + buf = KMALLOC(len + WHLEN + 1, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + strcpy(buf, WHPFX); + strlcat(buf, name, len + WHLEN + 1); + + return buf; +} + +/* Definitions for various ways to handle errors. + Each flag's value is its bit position */ + +/* 1 = DELETE_ALL, 0 = check for DELETE_WHITEOUT */ +#ifdef UNIONFS_DELETE_ALL +#define DELETE_ALL 4 +#else +#define DELETE_ALL 0 +#endif + +#define VALID_MOUNT_FLAGS (DELETE_ALL) + +/* + * MACROS: + */ + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif /* not SEEK_SET */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif /* not SEEK_CUR */ + +#ifndef SEEK_END +#define SEEK_END 2 +#endif /* not SEEK_END */ + +#ifndef DEFAULT_POLLMASK +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) +#endif + +/* + * EXTERNALS: + */ + +/* JS: These two functions are here because it is kind of daft to copy and paste the + * contents of the two functions to 32+ places in unionfs + */ +static inline struct dentry *lock_parent(struct dentry *dentry) +{ + struct dentry *dir = DGET(dentry->d_parent); + + mutex_lock(&dir->d_inode->i_mutex); + return dir; +} + +static inline void unlock_dir(struct dentry *dir) +{ + mutex_unlock(&dir->d_inode->i_mutex); + DPUT(dir); +} + +extern int make_dir_opaque(struct dentry *dir, int bindex); + +#endif /* __KERNEL__ */ + +/* + * DEFINITIONS FOR USER AND KERNEL CODE: + * (Note: ioctl numbers 1--9 are reserved for fistgen, the rest + * are auto-generated automatically based on the user's .fist file.) + */ +# define FIST_IOCTL_GET_DEBUG_VALUE _IOR(0x15, 1, int) +# define FIST_IOCTL_SET_DEBUG_VALUE _IOW(0x15, 2, int) +# define UNIONFS_IOCTL_BRANCH_COUNT _IOR(0x15, 10, int) +# define UNIONFS_IOCTL_INCGEN _IOR(0x15, 11, int) +# define UNIONFS_IOCTL_ADDBRANCH _IOW(0x15, 12, int) +# define UNIONFS_IOCTL_DELBRANCH _IOW(0x15, 13, int) +# define UNIONFS_IOCTL_RDWRBRANCH _IOW(0x15, 14, int) +# define UNIONFS_IOCTL_QUERYFILE _IOR(0x15, 15, int) + +/* We don't support normal remount, but unionctl uses it. */ +# define UNIONFS_REMOUNT_MAGIC 0x4a5a4380 + +/* should be at least LAST_USED_UNIONFS_PERMISSION<<1 */ +#define MAY_NFSRO 16 + +struct unionfs_addbranch_args { + unsigned int ab_branch; + char *ab_path; + unsigned int ab_perms; +}; + +struct unionfs_rdwrbranch_args { + unsigned int rwb_branch; + unsigned int rwb_perms; +}; + +#endif /* not __UNIONFS_H_ */ +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/lookup.c +++ linux-2.6.27/ubuntu/unionfs/lookup.c @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: lookup.c,v 1.49 2006/10/31 18:05:33 yiannos Exp $ + */ + +#include "unionfs.h" + +static int is_opaque_dir(struct dentry *dentry, int bindex); +static int is_validname(const char *name); + +struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *nd, int lookupmode) +{ + int err = 0; + struct dentry *hidden_dentry = NULL; + struct dentry *wh_hidden_dentry = NULL; + struct dentry *hidden_dir_dentry = NULL; + struct dentry *parent_dentry = NULL; + int bindex, bstart, bend, bopaque; + int dentry_count = 0; /* Number of positive dentries. */ + int first_dentry_offset = -1; + struct dentry *first_hidden_dentry = NULL; + int locked_parent = 0; + int locked_child = 0; + + int opaque; + char *whname = NULL; + const char *name; + int namelen; + + print_entry("mode = %d", lookupmode); + + /* We should already have a lock on this dentry in the case of a + * partial lookup, or a revalidation. Otherwise it is returned from + * new_dentry_private_data already locked. */ + if (lookupmode == INTERPOSE_PARTIAL || lookupmode == INTERPOSE_REVAL + || lookupmode == INTERPOSE_REVAL_NEG) { + verify_locked(dentry); + } else { + BUG_ON(dtopd_nocheck(dentry) != NULL); + locked_child = 1; + } + if (lookupmode != INTERPOSE_PARTIAL) + if ((err = new_dentry_private_data(dentry))) + goto out; + /* must initialize dentry operations */ + dentry->d_op = &unionfs_dops; + + parent_dentry = GET_PARENT(dentry); + /* We never partial lookup the root directory. */ + if (parent_dentry != dentry) { + lock_dentry(parent_dentry); + locked_parent = 1; + } else { + DPUT(parent_dentry); + parent_dentry = NULL; + goto out; + } + + print_dentry("IN unionfs_lookup (parent)", parent_dentry); + print_dentry("IN unionfs_lookup (child)", dentry); + + name = dentry->d_name.name; + namelen = dentry->d_name.len; + + /* No dentries should get created for possible whiteout names. */ + if (!is_validname(name)) { + err = -EPERM; + goto out_free; + } + + /* Now start the actual lookup procedure. */ + bstart = dbstart(parent_dentry); + bend = dbend(parent_dentry); + bopaque = dbopaque(parent_dentry); + BUG_ON(bstart < 0); + + /* It would be ideal if we could convert partial lookups to only have + * to do this work when they really need to. It could probably improve + * performance quite a bit, and maybe simplify the rest of the code. */ + if (lookupmode == INTERPOSE_PARTIAL) { + bstart++; + if ((bopaque != -1) && (bopaque < bend)) + bend = bopaque; + } + + dprint(PRINT_DEBUG, "bstart = %d, bend = %d\n", bstart, bend); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (lookupmode == INTERPOSE_PARTIAL && hidden_dentry) + continue; + BUG_ON(hidden_dentry != NULL); + + hidden_dir_dentry = dtohd_index(parent_dentry, bindex); + + /* if the parent hidden dentry does not exist skip this */ + if (!(hidden_dir_dentry && hidden_dir_dentry->d_inode)) + continue; + + /* also skip it if the parent isn't a directory. */ + if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode)) + continue; + + /* Reuse the whiteout name because its value doesn't change. */ + if (!whname) { + whname = alloc_whname(name, namelen); + if (IS_ERR(whname)) { + err = PTR_ERR(whname); + goto out_free; + } + } + + /* check if whiteout exists in this branch: lookup .wh.foo */ + wh_hidden_dentry = LOOKUP_ONE_LEN(whname, hidden_dir_dentry, + namelen + WHLEN); + if (IS_ERR(wh_hidden_dentry)) { + DPUT(first_hidden_dentry); + err = PTR_ERR(wh_hidden_dentry); + goto out_free; + } + + if (wh_hidden_dentry->d_inode) { + /* We found a whiteout so lets give up. */ + dprint(PRINT_DEBUG, "whiteout found in %d\n", bindex); + if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) { + set_dbend(dentry, bindex); + set_dbopaque(dentry, bindex); + DPUT(wh_hidden_dentry); + break; + } + err = -EIO; + printk(KERN_NOTICE "EIO: Invalid whiteout entry type" + " %d.\n", wh_hidden_dentry->d_inode->i_mode); + DPUT(wh_hidden_dentry); + DPUT(first_hidden_dentry); + goto out_free; + } + + DPUT(wh_hidden_dentry); + wh_hidden_dentry = NULL; + + /* Now do regular lookup; lookup foo */ + nd->path.dentry = dtohd_index(dentry, bindex); + /* FIXME: fix following line for mount point crossing */ + nd->path.mnt = stohiddenmnt_index(parent_dentry->d_sb, bindex); + + hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry, namelen); + print_dentry("hidden result", hidden_dentry); + if (IS_ERR(hidden_dentry)) { + DPUT(first_hidden_dentry); + err = PTR_ERR(hidden_dentry); + goto out_free; + } + + /* Store the first negative dentry specially, because if they + * are all negative we need this for future creates. */ + if (!hidden_dentry->d_inode) { + if (!first_hidden_dentry && (dbstart(dentry) == -1)) { + first_hidden_dentry = hidden_dentry; + first_dentry_offset = bindex; + } else { + DPUT(hidden_dentry); + } + continue; + } + + /* number of positive dentries */ + dentry_count++; + + /* store underlying dentry */ + if (dbstart(dentry) == -1) + set_dbstart(dentry, bindex); + set_dtohd_index(dentry, bindex, hidden_dentry); + set_dbend(dentry, bindex); + + /* update parent directory's atime with the bindex */ + fist_copy_attr_atime(parent_dentry->d_inode, + hidden_dir_dentry->d_inode); + + /* We terminate file lookups here. */ + if (!S_ISDIR(hidden_dentry->d_inode->i_mode)) { + if (lookupmode == INTERPOSE_PARTIAL) + continue; + if (dentry_count == 1) + goto out_positive; + /* This can only happen with mixed D-*-F-* */ + BUG_ON(!S_ISDIR(dtohd(dentry)->d_inode->i_mode)); + continue; + } + + opaque = is_opaque_dir(dentry, bindex); + if (opaque < 0) { + DPUT(first_hidden_dentry); + err = opaque; + goto out_free; + } + if (opaque) { + set_dbend(dentry, bindex); + set_dbopaque(dentry, bindex); + break; + } + } + + if (dentry_count) + goto out_positive; + else + goto out_negative; + + out_negative: + if (lookupmode == INTERPOSE_PARTIAL) + goto out; + + /* If we've only got negative dentries, then use the leftmost one. */ + if (lookupmode == INTERPOSE_REVAL) { + if (dentry->d_inode) { + itopd(dentry->d_inode)->uii_stale = 1; + } + goto out; + } + /* This should only happen if we found a whiteout. */ + if (first_dentry_offset == -1) { + nd->path.dentry = dentry; + /* FIXME: fix following line for mount point crossing */ + nd->path.mnt = stohiddenmnt_index(parent_dentry->d_sb, bindex); + + first_hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry, + namelen); + + first_dentry_offset = bindex; + if (IS_ERR(first_hidden_dentry)) { + err = PTR_ERR(first_hidden_dentry); + goto out; + } + } + set_dtohd_index(dentry, first_dentry_offset, first_hidden_dentry); + set_dbstart(dentry, first_dentry_offset); + set_dbend(dentry, first_dentry_offset); + + if (lookupmode == INTERPOSE_REVAL_NEG) + BUG_ON(dentry->d_inode != NULL); + else + d_add(dentry, NULL); + goto out; + +/* This part of the code is for positive dentries. */ + out_positive: + BUG_ON(dentry_count <= 0); + + /* If we're holding onto the first negative dentry throw it out. */ + DPUT(first_hidden_dentry); + + /* Partial lookups need to reinterpose, or throw away older negs. */ + if (lookupmode == INTERPOSE_PARTIAL) { + if (dentry->d_inode) { + unionfs_reinterpose(dentry); + goto out; + } + + /* This somehow turned positive, so it is as if we had a + * negative revalidation. */ + lookupmode = INTERPOSE_REVAL_NEG; + + update_bstart(dentry); + bstart = dbstart(dentry); + bend = dbend(dentry); + } + + err = unionfs_interpose(dentry, dentry->d_sb, lookupmode); + if (err) + goto out_drop; + + checkinode(dentry->d_inode, "unionfs_lookup OUT: child"); + checkinode(parent_dentry->d_inode, "unionfs_lookup OUT: dir"); + goto out; + + out_drop: + d_drop(dentry); + + out_free: + /* should dput all the underlying dentries on error condition */ + bstart = dbstart(dentry); + if (bstart >= 0) { + bend = dbend(dentry); + for (bindex = bstart; bindex <= bend; bindex++) + DPUT(dtohd_index(dentry, bindex)); + } + KFREE(dtohd_ptr(dentry)); + dtohd_ptr(dentry) = NULL; + set_dbstart(dentry, -1); + set_dbend(dentry, -1); + + out: + if (!err && dtopd(dentry)) { + BUG_ON(dbend(dentry) > dtopd(dentry)->udi_bcount); + BUG_ON(dbend(dentry) > sbmax(dentry->d_sb)); + BUG_ON(dbstart(dentry) < 0); + } + KFREE(whname); + print_dentry("OUT unionfs_lookup (parent)", parent_dentry); + print_dentry("OUT unionfs_lookup (child)", dentry); + if (locked_parent) + unlock_dentry(parent_dentry); + DPUT(parent_dentry); + if (locked_child) + unlock_dentry(dentry); + print_exit_status(err); + return ERR_PTR(err); +} + +/* This is a utility function that fills in a unionfs dentry.*/ +int unionfs_partial_lookup(struct dentry *dentry) +{ + struct dentry *tmp; + struct nameidata nd = { .flags = 0 }; + + tmp = unionfs_lookup_backend(dentry, &nd, INTERPOSE_PARTIAL); + if (!tmp) + return 0; + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + /* need to change the interface */ + BUG_ON(tmp != dentry); + return -ENOSYS; +} + +/* The rest of these are utility functions for lookup. */ +static int is_opaque_dir(struct dentry *dentry, int bindex) +{ + int err = 0; + struct dentry *hidden_dentry; + struct dentry *wh_hidden_dentry; + struct inode *hidden_inode; + struct sioq_args args; + + print_entry_location(); + + hidden_dentry = dtohd_index(dentry, bindex); + hidden_inode = hidden_dentry->d_inode; + + BUG_ON(!S_ISDIR(hidden_inode->i_mode)); + + mutex_lock(&hidden_inode->i_mutex); + if (!inode_permission(hidden_inode, MAY_EXEC)) + wh_hidden_dentry = LOOKUP_ONE_LEN(UNIONFS_DIR_OPAQUE, + hidden_dentry, + sizeof(UNIONFS_DIR_OPAQUE) - 1); + else { + args.isopaque.dentry = hidden_dentry; + run_sioq(__is_opaque_dir, &args); + wh_hidden_dentry = args.ret; + } + + mutex_unlock(&hidden_inode->i_mutex); + if (IS_ERR(wh_hidden_dentry)) { + err = PTR_ERR(wh_hidden_dentry); + dprint(PRINT_DEBUG, "LOOKUP_ONE_LEN returned: %d\n", err); + goto out; + } + if (wh_hidden_dentry->d_inode) + err = 1; + DPUT(wh_hidden_dentry); + out: + print_exit_status(err); + return err; +} + +static int is_validname(const char *name) +{ + if (!strncmp(name, WHPFX, WHLEN)) + return 0; + if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME, + sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1)) + return 0; + return 1; +} + +/* The dentry cache is just so we have properly sized dentries. */ +static struct kmem_cache *unionfs_dentry_cachep; +int init_dentry_cache(void) +{ + unionfs_dentry_cachep = + kmem_cache_create("unionfs_dentry", + sizeof(struct unionfs_dentry_info), 0, + SLAB_RECLAIM_ACCOUNT, NULL); + + if (!unionfs_dentry_cachep) + return -ENOMEM; + return 0; +} + +void destroy_dentry_cache(void) +{ + if (!unionfs_dentry_cachep) + return; + kmem_cache_destroy(unionfs_dentry_cachep); + return; +} + +void free_dentry_private_data(struct unionfs_dentry_info *udi) +{ + if (!udi) + return; + kmem_cache_free(unionfs_dentry_cachep, udi); +} + +int new_dentry_private_data(struct dentry *dentry) +{ + int newsize; + int oldsize = 0; + + spin_lock(&dentry->d_lock); + if (!dtopd_nocheck(dentry)) { + dtopd_lhs(dentry) = (struct unionfs_dentry_info *) + kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC); + if (!dtopd_nocheck(dentry)) + goto out; +#ifdef CONFIG_PREEMPT_RT + init_MUTEX(&dtopd_nocheck(dentry)->udi_sem); + down(&dtopd_nocheck(dentry)->udi_sem); +#else + init_MUTEX_LOCKED(&dtopd_nocheck(dentry)->udi_sem); +#endif + +#ifdef TRACKLOCK + printk("INITLOCK:%p\n", dentry); +#endif + dtohd_ptr(dentry) = NULL; + } else { + oldsize = sizeof(struct dentry *) * dtopd(dentry)->udi_bcount; + } + + dtopd_nocheck(dentry)->udi_bstart = -1; + dtopd_nocheck(dentry)->udi_bend = -1; + dtopd_nocheck(dentry)->udi_bopaque = -1; + dtopd_nocheck(dentry)->udi_bcount = sbmax(dentry->d_sb); + atomic_set(&dtopd_nocheck(dentry)->udi_generation, + atomic_read(&stopd(dentry->d_sb)->usi_generation)); + newsize = sizeof(struct dentry *) * sbmax(dentry->d_sb); + + /* Don't reallocate when we already have enough space. */ + /* It would be ideal if we could actually use the slab macros to + * determine what our object sizes is, but those are not exported. + */ + if (oldsize) { + int minsize = 128; + + if (!newsize || ((oldsize < newsize) && (newsize > minsize))) { + KFREE(dtohd_ptr(dentry)); + dtohd_ptr(dentry) = NULL; + } + } + + if (!dtohd_ptr(dentry) && newsize) { + dtohd_ptr(dentry) = KMALLOC(newsize, GFP_ATOMIC); + if (!dtohd_ptr(dentry)) + goto out; + } + + if (oldsize > newsize) + memset(dtohd_ptr(dentry), 0, oldsize); + else + memset(dtohd_ptr(dentry), 0, newsize); + + spin_unlock(&dentry->d_lock); + return 0; + + out: + free_dentry_private_data(dtopd_nocheck(dentry)); + dtopd_lhs(dentry) = NULL; + spin_unlock(&dentry->d_lock); + return -ENOMEM; +} + +void update_bstart(struct dentry *dentry) +{ + int bindex; + int bstart = dbstart(dentry); + int bend = dbend(dentry); + struct dentry *hidden_dentry; + + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + if (hidden_dentry->d_inode) { + set_dbstart(dentry, bindex); + break; + } + DPUT(hidden_dentry); + set_dtohd_index(dentry, bindex, NULL); + } +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/main.c +++ linux-2.6.27/ubuntu/unionfs/main.c @@ -0,0 +1,869 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: main.c,v 1.176 2006/10/10 07:28:13 jsipek Exp $ + */ + +#include "unionfs.h" +#include +#include + +/* declarations added for "sparse" */ +extern void unionfs_kill_block_super(struct super_block *sb); + +/* declarations added for malloc_debugging */ + +#ifdef FIST_MALLOC_DEBUG +extern atomic_t unionfs_malloc_counter; +extern atomic_t unionfs_mallocs_outstanding; +#endif + +extern void unionfs_read_inode(struct inode *inode); + +static struct inode *unionfs_iget(struct super_block *sb, ino_t ino) +{ + struct inode *inode; + + inode = iget_locked(sb, ino); + if (!inode) + return ERR_PTR(-ENOMEM); + if (inode->i_state & I_NEW) { + unionfs_read_inode(inode); + unlock_new_inode(inode); + } + return inode; +} + +/* sb we pass is unionfs's super_block */ +int unionfs_interpose(struct dentry *dentry, struct super_block *sb, int flag) +{ + struct inode *hidden_inode; + struct dentry *hidden_dentry; + int err = 0; + struct inode *inode; + int is_negative_dentry = 1; + int bindex, bstart, bend; + + print_entry("flag = %d", flag); + + verify_locked(dentry); + + print_dentry("In unionfs_interpose", dentry); + + bstart = dbstart(dentry); + bend = dbend(dentry); + + /* Make sure that we didn't get a negative dentry. */ + for (bindex = bstart; bindex <= bend; bindex++) { + if (dtohd_index(dentry, bindex) && + dtohd_index(dentry, bindex)->d_inode) { + is_negative_dentry = 0; + break; + } + } + BUG_ON(is_negative_dentry); + + /* We allocate our new inode below, by calling iget. + * iget will call our read_inode which will initialize some + * of the new inode's fields + */ + + /* On revalidate we've already got our own inode and just need + * to fix it up. */ + if (flag == INTERPOSE_REVAL) { + inode = dentry->d_inode; + itopd(inode)->b_start = -1; + itopd(inode)->b_end = -1; + atomic_set(&itopd(inode)->uii_generation, + atomic_read(&stopd(sb)->usi_generation)); + + itohi_ptr(inode) = + KZALLOC(sbmax(sb) * sizeof(struct inode *), GFP_KERNEL); + if (!itohi_ptr(inode)) { + err = -ENOMEM; + goto out; + } + mutex_lock(&inode->i_mutex); + } else { + ino_t ino; + /* get unique inode number for unionfs */ +#ifdef UNIONFS_IMAP + if (stopd(sb)->usi_persistent) { + err = read_uin(sb, bindex, + dtohd_index(dentry, + bindex)->d_inode->i_ino, + O_CREAT, &ino); + if (err) + goto out; + } else +#endif + ino = iunique(sb, UNIONFS_ROOT_INO); + + inode = unionfs_iget(sb, ino); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + + mutex_lock(&inode->i_mutex); + if (atomic_read(&inode->i_count) > 1) + goto skip; + } + + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) { + set_itohi_index(inode, bindex, NULL); + continue; + } + /* Initialize the hidden inode to the new hidden inode. */ + if (!hidden_dentry->d_inode) + continue; + set_itohi_index(inode, bindex, IGRAB(hidden_dentry->d_inode)); + } + + ibstart(inode) = dbstart(dentry); + ibend(inode) = dbend(dentry); + + /* Use attributes from the first branch. */ + hidden_inode = itohi(inode); + + /* Use different set of inode ops for symlinks & directories */ + if (S_ISLNK(hidden_inode->i_mode)) + inode->i_op = &unionfs_symlink_iops; + else if (S_ISDIR(hidden_inode->i_mode)) + inode->i_op = &unionfs_dir_iops; + + /* Use different set of file ops for directories */ + if (S_ISDIR(hidden_inode->i_mode)) + inode->i_fop = &unionfs_dir_fops; + + /* properly initialize special inodes */ + if (S_ISBLK(hidden_inode->i_mode) || S_ISCHR(hidden_inode->i_mode) || + S_ISFIFO(hidden_inode->i_mode) || S_ISSOCK(hidden_inode->i_mode)) + init_special_inode(inode, hidden_inode->i_mode, + hidden_inode->i_rdev); +#ifndef UNIONFS_MMAP + /* Fix our inode's address operations to that of the lower inode (Unionfs is FiST-Lite) */ + if (inode->i_mapping->a_ops != hidden_inode->i_mapping->a_ops) { + dprint(PRINT_DEBUG, "fixing inode 0x%p a_ops (0x%p -> 0x%p)\n", + inode, inode->i_mapping->a_ops, + hidden_inode->i_mapping->a_ops); + inode->i_mapping->a_ops = hidden_inode->i_mapping->a_ops; + } +#endif + /* all well, copy inode attributes */ + fist_copy_attr_all(inode, hidden_inode); + + skip: + /* only (our) lookup wants to do a d_add */ + switch (flag) { + case INTERPOSE_DEFAULT: + case INTERPOSE_REVAL_NEG: + d_instantiate(dentry, inode); + break; + case INTERPOSE_LOOKUP: + err = PTR_ERR(d_splice_alias(inode, dentry)); + break; + case INTERPOSE_REVAL: + /* Do nothing. */ + break; + default: + printk(KERN_ERR "Invalid interpose flag passed!"); + BUG(); + } + + print_dentry("Leaving unionfs_interpose", dentry); + print_inode("Leaving unionfs_interpose", inode); + mutex_unlock(&inode->i_mutex); + + out: + print_exit_status(err); + return err; +} + +void unionfs_reinterpose(struct dentry *dentry) +{ + struct dentry *hidden_dentry; + struct inode *inode; + int bindex, bstart, bend; + + print_entry_location(); + verify_locked(dentry); + print_dentry("IN: unionfs_reinterpose: ", dentry); + + /* This is pre-allocated inode */ + inode = dentry->d_inode; + + bstart = dbstart(dentry); + bend = dbend(dentry); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + + if (!hidden_dentry->d_inode) + continue; + if (itohi_index(inode, bindex)) + continue; + set_itohi_index(inode, bindex, IGRAB(hidden_dentry->d_inode)); + } + ibstart(inode) = dbstart(dentry); + ibend(inode) = dbend(dentry); + + print_dentry("OUT: unionfs_reinterpose: ", dentry); + print_inode("OUT: unionfs_reinterpose: ", inode); + + print_exit_location(); +} + +int check_branch(struct nameidata *nd) +{ + if (!strcmp(nd->path.dentry->d_sb->s_type->name, "unionfs")) + return -EINVAL; + if (!nd->path.dentry->d_inode) + return -ENOENT; + if (!S_ISDIR(nd->path.dentry->d_inode->i_mode)) + return -ENOTDIR; + return 0; +} + +/* checks if two hidden_dentries have overlapping branches */ +int is_branch_overlap(struct dentry *dent1, struct dentry *dent2) +{ + struct dentry *dent = NULL; + + dent = dent1; + while ((dent != dent2) && (dent->d_parent != dent)) { + dent = dent->d_parent; + } + if (dent == dent2) { + return 1; + } + + dent = dent2; + while ((dent != dent1) && (dent->d_parent != dent)) { + dent = dent->d_parent; + } + if (dent == dent1) { + return 1; + } + + return 0; +} +static int parse_branch_mode(char *name) +{ + int perms; + int l = strlen(name); + if (!strcmp(name + l - 3, "=ro")) { + perms = MAY_READ; + name[l - 3] = '\0'; + } else if (!strcmp(name + l - 6, "=nfsro")) { + perms = MAY_READ | MAY_NFSRO; + name[l - 6] = '\0'; + } else if (!strcmp(name + l - 3, "=rw")) { + perms = MAY_READ | MAY_WRITE; + name[l - 3] = '\0'; + } else { + perms = MAY_READ | MAY_WRITE; + } + + return perms; +} +static int get_separator_count(char *options, char *separator) +{ + char *token, *locopts, *locsep = NULL; + int count = 0; + /* + * We copy options so we dont destroy our pointer for parsing + */ + if (separator == NULL) { + locsep = KMALLOC(2, GFP_KERNEL); + if (!locsep) { + count = -ENOMEM; + goto out; + } + strcpy(locsep, ":"); + } else { + locsep = separator; + } + locopts = KMALLOC(strlen(options) + 1, GFP_KERNEL); + if (!locopts) { + count = -ENOMEM; + goto out; + } + strcpy(locopts, options); + while ((token = strsep(&locopts, locsep)) != NULL) + count++; + out: + KFREE(locopts); + return count; +} +static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info + *hidden_root_info, char *options, char *separator) +{ + struct nameidata nd; + char *name, *locsep = NULL; + int err = 0; + int branches = 1; + int bindex = 0; + int i = 0; + int j = 0; + + struct dentry *dent1 = NULL; + struct dentry *dent2 = NULL; + + if (options[0] == '\0') { + printk(KERN_WARNING "unionfs: no branches specified\n"); + err = -EINVAL; + goto out; + } + /* + * Check to see if separator is specified otherwise use ':' + */ + if (separator == NULL) { + locsep = KMALLOC(2, GFP_KERNEL); + if (!locsep) { + err = -ENOMEM; + goto out; + } + strcpy(locsep, ":"); + } else { + locsep = separator; + } + branches = get_separator_count(options, separator); + /* allocate space for underlying pointers to hidden dentry */ + if (!(stopd(sb)->usi_data = alloc_new_data(branches))) { + err = -ENOMEM; + goto out; + } + + if (!(hidden_root_info->udi_dentry = alloc_new_dentries(branches))) { + err = -ENOMEM; + goto out; + } + + /* now parsing the string b1:b2=rw:b3=ro:b4 */ + branches = 0; + while ((name = strsep(&options, locsep)) != NULL) { + int perms; + + if (!*name) + continue; + branches++; + + /* strip off =rw or =ro if it is specified. */ + perms = parse_branch_mode(name); + if (!bindex && !(perms & MAY_WRITE)) { + err = -EINVAL; + goto out; + } + + dprint(PRINT_DEBUG, "using directory: %s (%c%c%c)\n", + name, perms & MAY_READ ? 'r' : '-', + perms & MAY_WRITE ? 'w' : '-', + perms & MAY_NFSRO ? 'n' : '-'); + + err = path_lookup(name, LOOKUP_FOLLOW, &nd); + RECORD_PATH_LOOKUP(&nd); + if (err) { + printk(KERN_WARNING "unionfs: error accessing " + "hidden directory '%s' (error %d)\n", name, err); + goto out; + } + + if ((err = check_branch(&nd))) { + printk(KERN_WARNING "unionfs: hidden directory " + "'%s' is not a valid branch\n", name); + path_put(&nd.path); + RECORD_PATH_RELEASE(&nd); + goto out; + } + + hidden_root_info->udi_dentry[bindex] = nd.path.dentry; + + set_stohiddenmnt_index(sb, bindex, nd.path.mnt); + set_branchperms(sb, bindex, perms); + set_branch_count(sb, bindex, 0); + + if (hidden_root_info->udi_bstart < 0) + hidden_root_info->udi_bstart = bindex; + hidden_root_info->udi_bend = bindex; + bindex++; + } + + if (branches == 0) { + printk(KERN_WARNING "unionfs: no branches specified\n"); + err = -EINVAL; + goto out; + } + + BUG_ON(branches != (hidden_root_info->udi_bend + 1)); + + /* ensure that no overlaps exist in the branches */ + for (i = 0; i < branches; i++) { + for (j = i + 1; j < branches; j++) { + dent1 = hidden_root_info->udi_dentry[i]; + dent2 = hidden_root_info->udi_dentry[j]; + + if (is_branch_overlap(dent1, dent2)) { + goto out_overlap; + } + } + } + + out_overlap: + + if (i != branches) { + printk(KERN_WARNING "unionfs: branches %d and %d overlap\n", i, + j); + err = -EINVAL; + goto out; + } + + out: + if (err) { + for (i = 0; i < branches; i++) { + if (hidden_root_info->udi_dentry[i]) + DPUT(hidden_root_info->udi_dentry[i]); + } + + KFREE(hidden_root_info->udi_dentry); + KFREE(stopd(sb)->usi_data); + + /* MUST clear the pointers to prevent potential double free if + * the caller dies later on + */ + hidden_root_info->udi_dentry = NULL; + stopd(sb)->usi_data = NULL; + } + if (!separator) + KFREE(locsep); + return err; +} + +/* + * Parse mount options. See the manual page for usage instructions. + * + * Returns the dentry object of the lower-level (hidden) directory; + * We want to mount our stackable file system on top of that hidden directory. + * + * Sets default debugging level to N, if any. + */ +static struct unionfs_dentry_info *unionfs_parse_options(struct super_block *sb, + char *options) +{ + struct unionfs_dentry_info *hidden_root_info; + char *optname, *separator = NULL; + int err = 0; + int bindex; + int sepfound = 0; + int dirsfound = 0; +#ifdef UNIONFS_IMAP + int imapfound = 0; +#endif + print_entry_location(); + + /* allocate private data area */ + err = -ENOMEM; + hidden_root_info = + KZALLOC(sizeof(struct unionfs_dentry_info), GFP_KERNEL); + if (!hidden_root_info) + goto out_error; + hidden_root_info->udi_bstart = -1; + hidden_root_info->udi_bend = -1; + hidden_root_info->udi_bopaque = -1; + + while ((optname = strsep(&options, ",")) != NULL) { + char *optarg; + char *endptr; + int intval; + + if (!*optname) { + continue; + } + + optarg = strchr(optname, '='); + if (optarg) { + *optarg++ = '\0'; + } + + /* All of our options take an argument now. Insert ones that + * don't, above this check. */ + if (!optarg) { + printk("unionfs: %s requires an argument.\n", optname); + err = -EINVAL; + goto out_error; + } + + if (!strcmp("dirs", optname)) { + if (++dirsfound > 1) { + printk(KERN_WARNING + "unionfs: multiple dirs specified\n"); + err = -EINVAL; + goto out_error; + } + err = + parse_dirs_option(sb, hidden_root_info, optarg, + separator); + if (err) + goto out_error; + continue; + } +#ifdef UNIONFS_IMAP + if (!strcmp("imap", optname)) { + if (++imapfound > 1) { + printk(KERN_WARNING + "unionfs: multiple imap specified\n"); + err = -EINVAL; + goto out_error; + } + err = parse_imap_option(sb, hidden_root_info, optarg); + if (err) + goto out_error; + continue; + } +#endif + if (!strcmp("delete", optname)) { + if (!strcmp("whiteout", optarg)) { + /* default */ +#ifdef UNIONFS_DELETE_ALL + } else if (!strcmp("all", optarg)) { + MOUNT_FLAG(sb) |= DELETE_ALL; +#endif + } else { + printk(KERN_WARNING + "unionfs: invalid delete option '%s'\n", + optarg); + err = -EINVAL; + goto out_error; + } + continue; + } + + if (!strcmp("separator", optname)) { + if (dirsfound) { + printk(KERN_WARNING + "unionfs: dirs= already parsed separator '%s' will have no effect\n", + optarg); + continue; + } + sepfound = 1; + separator = KMALLOC(strlen(optarg) + 1, GFP_KERNEL); + if (!separator) { + err = -ENOMEM; + goto out_error; + } + strcpy(separator, optarg); + continue; + } + /* All of these options require an integer argument. */ + intval = simple_strtoul(optarg, &endptr, 0); + if (*endptr) { + printk(KERN_WARNING + "unionfs: invalid %s option '%s'\n", + optname, optarg); + err = -EINVAL; + goto out_error; + } + + if (!strcmp("debug", optname)) { + set_debug_mask(intval); + continue; + } + + err = -EINVAL; + printk(KERN_WARNING + "unionfs: unrecognized option '%s'\n", optname); + goto out_error; + } + if (dirsfound != 1) { + printk(KERN_WARNING "unionfs: dirs option required\n"); + err = -EINVAL; + goto out_error; + } + goto out; + + out_error: + if (hidden_root_info && hidden_root_info->udi_dentry) { + for (bindex = hidden_root_info->udi_bstart; + bindex >= 0 && bindex <= hidden_root_info->udi_bend; + bindex++) { + struct dentry *d; + d = hidden_root_info->udi_dentry[bindex]; + DPUT(d); + if (stohiddenmnt_index(sb, bindex)) + mntput(stohiddenmnt_index(sb, bindex)); + } + } + + KFREE(hidden_root_info->udi_dentry); + KFREE(hidden_root_info); + + KFREE(stopd(sb)->usi_data); + stopd(sb)->usi_data = NULL; + + hidden_root_info = ERR_PTR(err); + KFREE(separator); + out: + print_exit_location(); + return hidden_root_info; +} + +static struct dentry *unionfs_d_alloc_root(struct super_block *sb) +{ + struct dentry *ret = NULL; + + if (sb) { + static const struct qstr name = {.name = "/",.len = 1 }; + + ret = d_alloc(NULL, &name); + if (ret) { + ret->d_op = &unionfs_dops; + ret->d_sb = sb; + ret->d_parent = ret; + } + } + return ret; +} + +static int unionfs_read_super(struct super_block *sb, void *raw_data, + int silent) +{ + int err = 0; + + struct unionfs_dentry_info *hidden_root_info = NULL; + int bindex, bstart, bend; + unsigned long long maxbytes; + + print_entry_location(); + + if (!raw_data) { + printk(KERN_WARNING + "unionfs_read_super: missing data argument\n"); + err = -EINVAL; + goto out; + } + + /* + * Allocate superblock private data + */ + stopd_lhs(sb) = KZALLOC(sizeof(struct unionfs_sb_info), GFP_KERNEL); + if (!stopd(sb)) { + printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); + err = -ENOMEM; + goto out; + } + stopd(sb)->b_end = -1; + atomic_set(&stopd(sb)->usi_generation, 1); + init_rwsem(&stopd(sb)->usi_rwsem); + + hidden_root_info = unionfs_parse_options(sb, raw_data); + if (IS_ERR(hidden_root_info)) { + printk(KERN_WARNING + "unionfs_read_super: error while parsing options (err = %ld)\n", + PTR_ERR(hidden_root_info)); + err = PTR_ERR(hidden_root_info); + hidden_root_info = NULL; + goto out_free; + } + if (hidden_root_info->udi_bstart == -1) { + err = -ENOENT; + goto out_free; + } + + /* set the hidden superblock field of upper superblock */ + bstart = hidden_root_info->udi_bstart; + BUG_ON(bstart != 0); + sbend(sb) = bend = hidden_root_info->udi_bend; + for (bindex = bstart; bindex <= bend; bindex++) { + struct dentry *d; + + d = hidden_root_info->udi_dentry[bindex]; + + set_stohs_index(sb, bindex, d->d_sb); + } + + /* Unionfs: Max Bytes is the maximum bytes from among all the branches */ + maxbytes = -1; + for (bindex = bstart; bindex <= bend; bindex++) + if (maxbytes < stohs_index(sb, bindex)->s_maxbytes) + maxbytes = stohs_index(sb, bindex)->s_maxbytes; + sb->s_maxbytes = maxbytes; + + sb->s_op = &unionfs_sops; +#ifdef CONFIG_EXPORTFS + sb->s_export_op = &unionfs_export_ops; +#endif + + /* + * we can't use d_alloc_root if we want to use + * our own interpose function unchanged, + * so we simply call our own "fake" d_alloc_root + */ + sb->s_root = unionfs_d_alloc_root(sb); + if (!sb->s_root) { + err = -ENOMEM; + goto out_dput; + } + + /* link the upper and lower dentries */ + dtopd_lhs(sb->s_root) = NULL; + if ((err = new_dentry_private_data(sb->s_root))) + goto out_freedpd; + + /* Set the hidden dentries for s_root */ + for (bindex = bstart; bindex <= bend; bindex++) { + struct dentry *d; + + d = hidden_root_info->udi_dentry[bindex]; + + set_dtohd_index(sb->s_root, bindex, d); + } + set_dbstart(sb->s_root, bstart); + set_dbend(sb->s_root, bend); + + /* Set the generation number to one, since this is for the mount. */ + atomic_set(&dtopd(sb->s_root)->udi_generation, 1); + + /* call interpose to create the upper level inode */ + if ((err = unionfs_interpose(sb->s_root, sb, 0))) + goto out_freedpd; + unlock_dentry(sb->s_root); + goto out; + + out_freedpd: + if (dtopd(sb->s_root)) { + KFREE(dtohd_ptr(sb->s_root)); + free_dentry_private_data(dtopd(sb->s_root)); + } + DPUT(sb->s_root); + out_dput: + if (hidden_root_info && !IS_ERR(hidden_root_info)) { + for (bindex = hidden_root_info->udi_bstart; + bindex <= hidden_root_info->udi_bend; bindex++) { + struct dentry *d; + + d = hidden_root_info->udi_dentry[bindex]; + + if (d) + DPUT(d); + + if (stopd(sb) && stohiddenmnt_index(sb, bindex)) + mntput(stohiddenmnt_index(sb, bindex)); + } + KFREE(hidden_root_info->udi_dentry); + KFREE(hidden_root_info); + hidden_root_info = NULL; + } + out_free: + KFREE(stopd(sb)->usi_data); + KFREE(stopd(sb)); + stopd_lhs(sb) = NULL; + out: + if (hidden_root_info && !IS_ERR(hidden_root_info)) { + KFREE(hidden_root_info->udi_dentry); + KFREE(hidden_root_info); + } + print_exit_status(err); + return err; +} + +static int unionfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *raw_data, struct vfsmount *mnt) +{ + return get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt); +} + +static struct file_system_type unionfs_fs_type = { + .owner = THIS_MODULE, + .name = "unionfs", + .get_sb = unionfs_get_sb, + .kill_sb = kill_anon_super, + .fs_flags = FS_REVAL_DOT, +}; + +static int init_debug = 0; +module_param_named(debug, init_debug, int, S_IRUGO); +MODULE_PARM_DESC(debug, "Initial Unionfs debug value."); + +static int __init init_unionfs_fs(void) +{ + int err; + printk("Registering unionfs " UNIONFS_VERSION "\n"); + + set_debug_mask(init_debug); + +#ifdef FIST_MALLOC_DEBUG + atomic_set(&unionfs_malloc_counter, 0); + atomic_set(&unionfs_mallocs_outstanding, 0); +#endif /* FIST_MALLOC_DEBUG */ + + if ((err = init_filldir_cache())) + goto out; + if ((err = init_inode_cache())) + goto out; + if ((err = init_dentry_cache())) + goto out; + if ((err = init_sioq())) + goto out; + err = register_filesystem(&unionfs_fs_type); + out: + if (err) { + fin_sioq(); + destroy_filldir_cache(); + destroy_inode_cache(); + destroy_dentry_cache(); + } + return err; +} +static void __exit exit_unionfs_fs(void) +{ + fin_sioq(); + destroy_filldir_cache(); + destroy_inode_cache(); + destroy_dentry_cache(); + unregister_filesystem(&unionfs_fs_type); + printk("Completed unionfs module unload.\n"); +} + +MODULE_AUTHOR + ("Filesystems and Storage Lab, Stony Brook University (http://www.fsl.cs.sunysb.edu/)"); +MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION + " (http://unionfs.filesystems.org/)"); +MODULE_LICENSE("GPL"); + +module_init(init_unionfs_fs); +module_exit(exit_unionfs_fs); +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/print.c +++ linux-2.6.27/ubuntu/unionfs/print.c @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef Sipek + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: print.c,v 1.77 2006/07/08 17:58:31 ezk Exp $ + */ + +/* Print debugging functions */ + +#include "unionfs.h" + +static unsigned int debug_mask = DEFAULT_DEBUG_MASK; + +/* get value of debugging variable */ +unsigned int get_debug_mask(void) +{ + return debug_mask; +} + +/* set debug level variable and return the previous value */ +int set_debug_mask(int val) +{ +#ifdef UNIONFS_DEBUG + int prev = debug_mask; + + debug_mask = val; + + printk(KERN_INFO UNIONFS_NAME ": debug mask set to %u\n", debug_mask); + + return prev; +#else /* UNIONFS_DEBUG */ + printk(KERN_WARNING UNIONFS_NAME ": debugging is not enabled\n"); + return -ENOTSUPP; +#endif /* ! UNIONFS_DEBUG */ +} + +static inline int should_print(const unsigned int req) +{ + return (req & debug_mask); +} + +static void unionfs_print_generic_inode(const char *prefix, + const char *prefix2, const struct inode *inode) +{ + if (!inode) { + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: NULL INODE PASSED!\n", prefix, prefix2); + return; + } + + if (IS_ERR(inode)) { + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: ERROR INODE PASSED: %ld\n", prefix, prefix2, + PTR_ERR(inode)); + return; + } + + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: i_ino=%lu\n", + prefix, prefix2, inode->i_ino); + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: i_count=%u\n", + prefix, prefix2, atomic_read(&inode->i_count)); + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: i_nlink=%u\n", + prefix, prefix2, inode->i_nlink); + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: i_mode=%o\n", + prefix, prefix2, inode->i_mode); + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: i_size=%llu\n", + prefix, prefix2, inode->i_size); + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: i_op=%p\n", + prefix, prefix2, inode->i_op); + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s%s: i_sb=%p (%s)\n", + prefix, prefix2, inode->i_sb, (inode->i_sb ? sbt(inode->i_sb) : "NullTypeSB")); +} + +void unionfs_print_inode(const unsigned int req, const char *prefix, const struct inode *inode) +{ + int bindex; + + if (!should_print(req)) + return; + + if (!inode) { + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s: NULL INODE PASSED!\n", prefix); + return; + } + if (IS_ERR(inode)) { + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s: ERROR INODE PASSED: %ld\n", prefix, PTR_ERR(inode)); + return; + } + + unionfs_print_generic_inode(prefix, "", inode); + + if (strcmp("unionfs", sbt(inode->i_sb))) { + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s: Not a " UNIONFS_NAME " inode.\n", prefix); + return; + } + + if (!itopd(inode)) + return; + + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s: ibstart=%d, ibend=%d\n", prefix, ibstart(inode), ibend(inode)); + + if (ibstart(inode) == -1) + return; + + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) { + struct inode *hidden_inode = itohi_index(inode, bindex); + char newstr[10]; + if (!hidden_inode) { + printk(KERN_DEBUG UNIONFS_NAME ": PI:%s: HI#%d: NULL\n", prefix, bindex); + continue; + } + snprintf(newstr, 10, ": HI%d", bindex); + unionfs_print_generic_inode(prefix, newstr, hidden_inode); + } +} + +static void unionfs_print_generic_file(const char *prefix, const char *prefix2, + const struct file *file) +{ + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_dentry=0x%p\n", prefix, prefix2, file->f_dentry); + + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: name=%s\n", prefix, prefix2, file->f_dentry->d_name.name); + if (file->f_dentry->d_inode) { + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_dentry->d_inode->i_ino=%lu\n", prefix, prefix2, file->f_dentry->d_inode->i_ino); + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_dentry->d_inode->i_mode=%o\n", prefix, prefix2, file->f_dentry->d_inode->i_mode); + } + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_op=0x%p\n", prefix, prefix2, file->f_op); + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_mode=0x%x\n", prefix, prefix2, file->f_mode); + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_pos=0x%llu\n", prefix, prefix2, file->f_pos); + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_count=%u\n", prefix, prefix2, atomic_read(&file->f_count)); + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_flags=0x%x\n", prefix, prefix2, file->f_flags); + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s%s: f_version=%llu\n", prefix, prefix2, file->f_version); +} + +void unionfs_print_file(const unsigned int req, const char *prefix, const struct file *file) +{ + struct file *hidden_file; + + if (!should_print(req)) + return; + + if (!file) { + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s: NULL FILE PASSED!\n", prefix); + return; + } + + unionfs_print_generic_file(prefix, "", file); + + if (strcmp("unionfs", sbt(file->f_dentry->d_sb))) { + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s: Not a " UNIONFS_NAME " file.\n", prefix); + return; + } + + if (ftopd(file)) { + int bindex; + + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s: fbstart=%d, fbend=%d\n", prefix, fbstart(file), fbend(file)); + + for (bindex = fbstart(file); bindex <= fbend(file); bindex++) { + char newstr[10]; + hidden_file = ftohf_index(file, bindex); + if (!hidden_file) { + printk(KERN_DEBUG UNIONFS_NAME ": PF:%s: HF#%d is NULL\n", prefix, bindex); + continue; + } + snprintf(newstr, 10, ": HF%d", bindex); + unionfs_print_generic_file(prefix, newstr, hidden_file); + } + } +} + +static char mode_to_type(mode_t mode) +{ + if (S_ISDIR(mode)) + return 'd'; + if (S_ISLNK(mode)) + return 'l'; + if (S_ISCHR(mode)) + return 'c'; + if (S_ISBLK(mode)) + return 'b'; + if (S_ISREG(mode)) + return 'f'; + return '?'; +} + +static void unionfs_print_generic_dentry(const char *prefix, const char *prefix2, const + struct dentry *dentry, int check) +{ + if (!dentry) { + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: NULL DENTRY PASSED!\n", prefix, prefix2); + return; + } + + if (IS_ERR(dentry)) { + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: ERROR DENTRY (%ld)!\n", prefix, prefix2, + PTR_ERR(dentry)); + return; + } + + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: dentry = %p\n", prefix, prefix2, dentry); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_count=%d\n", prefix, prefix2, atomic_read(&dentry->d_count)); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_flags=%x\n", prefix, prefix2, (int)dentry->d_flags); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_name.name=\"%s\" (len = %d)\n", prefix, prefix2, dentry->d_name.name, dentry->d_name.len); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_sb=%p (%s)\n", prefix, prefix2, dentry->d_sb, sbt(dentry->d_sb)); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_inode=%p\n", prefix, prefix2, dentry->d_inode); + + if (dentry->d_inode) { + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_inode->i_ino=%ld (%s)\n", prefix, prefix2, + dentry->d_inode->i_ino, + sbt(dentry->d_inode->i_sb)); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: dentry->d_inode->i_mode: %c%o\n", prefix, + prefix2, mode_to_type(dentry->d_inode->i_mode), + dentry->d_inode->i_mode); + } + + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_parent=%p (%s)\n", prefix, prefix2, + dentry->d_parent, + (dentry->d_parent ? sbt(dentry->d_parent->d_sb) : "nil")); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_parent->d_name.name=\"%s\"\n", prefix, prefix2, + dentry->d_parent->d_name.name); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_parent->d_count=%d\n", prefix, prefix2, + atomic_read(&dentry->d_parent->d_count)); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_op=%p\n", prefix, prefix2, dentry->d_op); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: d_fsdata=%p\n", prefix, prefix2, + dentry->d_fsdata); + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s%s: hlist_unhashed(d_hash)=%d\n", prefix, prefix2, + hlist_unhashed(&((struct dentry *)dentry)->d_hash)); + + /* After we have printed it, we can assert something about it. */ + if (check) + BUG_ON(atomic_read(&dentry->d_count) <= 0); +} + +static void __unionfs_print_dentry(const char *prefix, const struct dentry *dentry, + int check) +{ + if (!dentry) { + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s: NULL DENTRY PASSED!\n", prefix); + return; + } + + if (IS_ERR(dentry)) { + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s: ERROR DENTRY (%ld)!\n", prefix, + PTR_ERR(dentry)); + return; + } + + unionfs_print_generic_dentry(prefix, "", dentry, check); + + if (strcmp("unionfs", sbt(dentry->d_sb))) { + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s: Not a " UNIONFS_NAME " dentry.\n", prefix); + return; + } + + if (!dtopd(dentry)) + return; + + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s: dbstart=%d, dbend=%d, dbopaque=%d\n", + prefix, dbstart(dentry), dbend(dentry), dbopaque(dentry)); + + if (dbstart(dentry) != -1) { + int bindex; + char newstr[10]; + struct dentry *hidden_dentry; + + for (bindex = dbstart(dentry); bindex <= dbend(dentry); + bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) { + printk(KERN_DEBUG UNIONFS_NAME ": PD:%s: HD#%d: NULL\n", prefix, bindex); + continue; + } + snprintf(newstr, 10, ": HD%d", bindex); + unionfs_print_generic_dentry(prefix, newstr, hidden_dentry, check); + } + } +} + +void unionfs_print_dentry(const unsigned int req, const char *prefix, const struct dentry *dentry) +{ + if (!should_print(req)) + return; + + __unionfs_print_dentry(prefix, dentry, 1); +} + +void unionfs_print_dentry_nocheck(const unsigned int req, const char *prefix, const struct dentry *dentry) +{ + if (!should_print(req)) + return; + + __unionfs_print_dentry(prefix, dentry, 0); +} + +void unionfs_checkinode(const unsigned int req, const struct inode *inode, const char *msg) +{ + if (!should_print(req)) + return; + + if (!inode) { + printk(KERN_DEBUG UNIONFS_NAME ": unionfs_checkinode - inode is NULL! (%s)\n", + msg); + return; + } + + if (!itopd(inode)) { + printk(KERN_DEBUG UNIONFS_NAME ": unionfs_checkinode(%ld) - no private data (%s)\n", + inode->i_ino, msg); + return; + } + + if ((itopd(inode)->b_start < 0) || !itohi(inode)) { + printk(KERN_DEBUG UNIONFS_NAME + "unionfs_checkinode(%ld) - underlying is NULL! (%s)\n", + inode->i_ino, msg); + return; + } + + if (!inode->i_sb) { + printk(KERN_DEBUG UNIONFS_NAME + ": unionfs_checkinode(%ld) - inode->i_sb is NULL! (%s)\n", + inode->i_ino, msg); + return; + } + + printk(KERN_DEBUG UNIONFS_NAME ": inode->i_sb->s_type %p\n", inode->i_sb->s_type); + if (!inode->i_sb->s_type) { + printk(KERN_DEBUG UNIONFS_NAME + ": unionfs_checkinode(%ld) - inode->i_sb->s_type is NULL! (%s)\n", + inode->i_ino, msg); + return; + } + + printk(KERN_DEBUG UNIONFS_NAME + ": CI: %s: inode->i_count = %d, hidden_inode->i_count = %d, inode = %lu, sb = %s, hidden_sb = %s\n", + msg, atomic_read(&inode->i_count), + itopd(inode)->b_start >= + 0 ? atomic_read(&itohi(inode)->i_count) : -1, inode->i_ino, + inode->i_sb->s_type->name, + itopd(inode)->b_start >= + 0 ? itohi(inode)->i_sb->s_type->name : "(none)"); +} + +void unionfs_print_sb(const unsigned int req, const char *prefix, const struct super_block *sb) +{ + struct super_block *hidden_superblock; + + if (!should_print(req)) + return; + + if (!sb) { + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: NULL SB PASSED!\n", prefix); + return; + } + + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: s_blocksize=%lu\n", prefix, sb->s_blocksize); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: s_blocksize_bits=%u\n", prefix, sb->s_blocksize_bits); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: s_flags=0x%lx\n", prefix, sb->s_flags); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: s_magic=0x%lx\n", prefix, sb->s_magic); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: s_maxbytes=%llu\n", prefix, sb->s_maxbytes); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: s_count=%d\n", prefix, sb->s_count); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: s_active=%d\n", prefix, atomic_read(&sb->s_active)); + + if (stopd(sb)) + printk(KERN_DEBUG UNIONFS_NAME ": sbstart=%d, sbend=%d\n", sbstart(sb), + sbend(sb)); + + if (stopd(sb)) { + int bindex; + for (bindex = sbstart(sb); bindex <= sbend(sb); bindex++) { + hidden_superblock = stohs_index(sb, bindex); + if (!hidden_superblock) { + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d is NULL", prefix, + bindex); + continue; + } + + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d: s_blocksize=%lu\n", prefix, bindex, + hidden_superblock->s_blocksize); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d: s_blocksize_bits=%u\n", prefix, bindex, + hidden_superblock->s_blocksize_bits); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d: s_flags=0x%lx\n", prefix, bindex, + hidden_superblock->s_flags); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d: s_magic=0x%lx\n", prefix, bindex, + hidden_superblock->s_magic); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d: s_maxbytes=%llu\n", prefix, bindex, + hidden_superblock->s_maxbytes); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d: s_count=%d\n", prefix, bindex, + hidden_superblock->s_count); + printk(KERN_DEBUG UNIONFS_NAME ": PSB:%s: HS#%d: s_active=%d\n", prefix, bindex, + atomic_read(&hidden_superblock->s_active)); + } + } +} + +int unionfs_print(const unsigned int req, const char *fmt, ...) +{ + va_list ap; + int r; + + if (!should_print(req)) + return 0; + + printk(KERN_DEBUG UNIONFS_NAME ": "); + va_start(ap, fmt); + r = vprintk(fmt, ap); + va_end(ap); + + return r; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/rename.c +++ linux-2.6.27/ubuntu/unionfs/rename.c @@ -0,0 +1,943 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: rename.c,v 1.47 2006/08/05 01:28:46 jro Exp $ + */ + +#include "unionfs.h" + +static int do_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + int bindex, struct dentry **wh_old) +{ + int err = 0; + struct dentry *hidden_old_dentry; + struct dentry *hidden_new_dentry; + struct dentry *hidden_old_dir_dentry; + struct dentry *hidden_new_dir_dentry; + struct dentry *hidden_wh_dentry; + struct dentry *hidden_wh_dir_dentry; + char *wh_name = NULL; + + print_entry(" bindex=%d", bindex); + + print_dentry("IN: do_rename, old_dentry", old_dentry); + print_dentry("IN: do_rename, new_dentry", new_dentry); + dprint(PRINT_DEBUG, "do_rename for bindex = %d\n", bindex); + + hidden_new_dentry = dtohd_index(new_dentry, bindex); + hidden_old_dentry = dtohd_index(old_dentry, bindex); + + if (!hidden_new_dentry) { + hidden_new_dentry = + create_parents(new_dentry->d_parent->d_inode, new_dentry, + bindex); + if (IS_ERR(hidden_new_dentry)) { + dprint(PRINT_DEBUG, + "error creating directory tree for rename, bindex = %d\n", + bindex); + err = PTR_ERR(hidden_new_dentry); + goto out; + } + } + + wh_name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len); + if (IS_ERR(wh_name)) { + err = PTR_ERR(wh_name); + goto out; + } + + hidden_wh_dentry = + LOOKUP_ONE_LEN(wh_name, hidden_new_dentry->d_parent, + new_dentry->d_name.len + WHLEN); + if (IS_ERR(hidden_wh_dentry)) { + err = PTR_ERR(hidden_wh_dentry); + goto out; + } + + if (hidden_wh_dentry->d_inode) { + /* get rid of the whiteout that is existing */ + if (hidden_new_dentry->d_inode) { + printk(KERN_WARNING + "Both a whiteout and a dentry exist when doing a rename!\n"); + err = -EIO; + + DPUT(hidden_wh_dentry); + goto out; + } + + hidden_wh_dir_dentry = lock_parent(hidden_wh_dentry); + if (!(err = is_robranch_super(old_dentry->d_sb, bindex))) { + err = + vfs_unlink(hidden_wh_dir_dentry->d_inode, + hidden_wh_dentry, NULL); + } + DPUT(hidden_wh_dentry); + unlock_dir(hidden_wh_dir_dentry); + if (err) + goto out; + } else + DPUT(hidden_wh_dentry); + + DGET(hidden_old_dentry); + hidden_old_dir_dentry = GET_PARENT(hidden_old_dentry); + hidden_new_dir_dentry = GET_PARENT(hidden_new_dentry); + + lock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry); + + err = is_robranch_super(old_dentry->d_sb, bindex); + if (err) + goto out_unlock; + + /* ready to whiteout for old_dentry. + caller will create the actual whiteout, + and must dput(*wh_old) */ + if (wh_old) { + char *whname; + whname = alloc_whname(old_dentry->d_name.name, + old_dentry->d_name.len); + err = PTR_ERR(whname); + if (IS_ERR(whname)) + goto out_unlock; + *wh_old = LOOKUP_ONE_LEN(whname, hidden_old_dir_dentry, + old_dentry->d_name.len + WHLEN); + KFREE(whname); + err = PTR_ERR(*wh_old); + if (IS_ERR(*wh_old)) { + *wh_old = NULL; + goto out_unlock; + } + } + + print_dentry("NEWBEF", new_dentry); + print_dentry("OLDBEF", old_dentry); + err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry, + NULL, hidden_new_dir_dentry->d_inode, + hidden_new_dentry, NULL); + print_dentry("NEWAFT", new_dentry); + print_dentry("OLDAFT", old_dentry); + + out_unlock: + unlock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry); + + DPUT(hidden_old_dir_dentry); + DPUT(hidden_new_dir_dentry); + DPUT(hidden_old_dentry); + + out: + if (!err) { + /* Fixup the newdentry. */ + if (bindex < dbstart(new_dentry)) + set_dbstart(new_dentry, bindex); + else if (bindex > dbend(new_dentry)) + set_dbend(new_dentry, bindex); + } + + KFREE(wh_name); + + print_dentry("OUT: do_rename, old_dentry", old_dentry); + print_dentry("OUT: do_rename, new_dentry", new_dentry); + + print_exit_status(err); + return err; +} + +static int unionfs_rename_whiteout(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry) +{ + int err = 0; + int bindex, bwh_old; + int old_bstart, old_bend; + int new_bstart, new_bend; + int do_copyup = -1; + struct dentry *parent_dentry; + int local_err = 0; + int eio = 0; + int revert = 0; + struct dentry *wh_old = NULL; + + print_entry_location(); + + old_bstart = dbstart(old_dentry); + bwh_old = old_bstart; + old_bend = dbend(old_dentry); + parent_dentry = old_dentry->d_parent; + + new_bstart = dbstart(new_dentry); + new_bend = dbend(new_dentry); + + /* Rename source to destination. */ + err = do_rename(old_dir, old_dentry, new_dir, new_dentry, old_bstart, + &wh_old); + if (err) { + if (!IS_COPYUP_ERR(err)) { + goto out; + } + do_copyup = old_bstart - 1; + } else { + revert = 1; + } + + /* Unlink all instances of destination that exist to the left of + * bstart of source. On error, revert back, goto out. + */ + for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) { + struct dentry *unlink_dentry; + struct dentry *unlink_dir_dentry; + + unlink_dentry = dtohd_index(new_dentry, bindex); + if (!unlink_dentry) { + continue; + } + + unlink_dir_dentry = lock_parent(unlink_dentry); + if (!(err = is_robranch_super(old_dir->i_sb, bindex))) { + err = + vfs_unlink(unlink_dir_dentry->d_inode, + unlink_dentry, NULL); + } + + fist_copy_attr_times(new_dentry->d_parent->d_inode, + unlink_dir_dentry->d_inode); + /* propagate number of hard-links */ + new_dentry->d_parent->d_inode->i_nlink = + get_nlinks(new_dentry->d_parent->d_inode); + + unlock_dir(unlink_dir_dentry); + if (!err) { + if (bindex != new_bstart) { + DPUT(unlink_dentry); + set_dtohd_index(new_dentry, bindex, NULL); + } + } else if (IS_COPYUP_ERR(err)) { + do_copyup = bindex - 1; + } else if (revert) { + DPUT(wh_old); + goto revert; + } + } + + if (do_copyup != -1) { + for (bindex = do_copyup; bindex >= 0; bindex--) { + /* copyup the file into some left directory, so that you can rename it */ + err = + copyup_dentry(old_dentry->d_parent->d_inode, + old_dentry, old_bstart, bindex, NULL, + old_dentry->d_inode->i_size); + if (!err) { + DPUT(wh_old); + bwh_old = bindex; + err = + do_rename(old_dir, old_dentry, new_dir, + new_dentry, bindex, &wh_old); + break; + } + } + } + + /* make it opaque */ + if (S_ISDIR(old_dentry->d_inode->i_mode)) { + err = make_dir_opaque(old_dentry, dbstart(old_dentry)); + if (err) + goto revert; + } + + /* Create whiteout for source, only if: + * (1) There is more than one underlying instance of source. + * (2) We did a copy_up + */ + if ((old_bstart != old_bend) || (do_copyup != -1)) { + struct dentry *hidden_parent; + BUG_ON(!wh_old || IS_ERR(wh_old) || wh_old->d_inode + || bwh_old < 0); + hidden_parent = lock_parent(wh_old); + local_err = vfs_create(hidden_parent->d_inode, wh_old, S_IRUGO, + NULL); + unlock_dir(hidden_parent); + if (!local_err) + set_dbopaque(old_dentry, bwh_old); + else { + /* We can't fix anything now, so we cop-out and use -EIO. */ + printk + ("<0>We can't create a whiteout for the source in rename!\n"); + err = -EIO; + } + } + + out: + DPUT(wh_old); + print_exit_status(err); + return err; + + revert: + /* Do revert here. */ + local_err = unionfs_refresh_hidden_dentry(new_dentry, old_bstart); + if (local_err) { + printk(KERN_WARNING + "Revert failed in rename: the new refresh failed.\n"); + eio = -EIO; + } + + local_err = unionfs_refresh_hidden_dentry(old_dentry, old_bstart); + if (local_err) { + printk(KERN_WARNING + "Revert failed in rename: the old refresh failed.\n"); + eio = -EIO; + goto revert_out; + } + + if (!dtohd_index(new_dentry, bindex) + || !dtohd_index(new_dentry, bindex)->d_inode) { + printk(KERN_WARNING + "Revert failed in rename: the object disappeared from under us!\n"); + eio = -EIO; + goto revert_out; + } + + if (dtohd_index(old_dentry, bindex) + && dtohd_index(old_dentry, bindex)->d_inode) { + printk(KERN_WARNING + "Revert failed in rename: the object was created underneath us!\n"); + eio = -EIO; + goto revert_out; + } + + local_err = + do_rename(new_dir, new_dentry, old_dir, old_dentry, old_bstart, + NULL); + + /* If we can't fix it, then we cop-out with -EIO. */ + if (local_err) { + printk(KERN_WARNING "Revert failed in rename!\n"); + eio = -EIO; + } + + local_err = unionfs_refresh_hidden_dentry(new_dentry, bindex); + if (local_err) + eio = -EIO; + local_err = unionfs_refresh_hidden_dentry(old_dentry, bindex); + if (local_err) + eio = -EIO; + + revert_out: + if (eio) + err = eio; + print_exit_status(err); + return err; +} + +/* + * Unfortunately, we cannot simply call things like dbstart() in different + * places of the rename code because we move things around. So, we use this + * structure to pass the necessary information around to all the places that + * need it. + */ +struct rename_info { + int do_copyup; + int do_whiteout; + int rename_ok; + + int old_bstart; + int old_bend; + int new_bstart; + int new_bend; + + int isdir; /* Is the source a directory? */ + int clobber; /* Are we clobbering the destination? */ + + int bwh_old; /* where we create the whiteout */ + struct dentry *wh_old; /* lookup and set by do_rename() */ +}; +#ifdef UNIONFS_DELETE_ALL +/* + * Rename all occurences of source except for the leftmost destination + */ +static int __rename_all(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + fd_set * success_mask, struct rename_info *info) +{ + int bindex; + int err = 0; + + print_entry_location(); + + /* Loop through all the branches from right to left and rename all + * instances of source to destination, except the leftmost destination + */ + for (bindex = info->old_bend; bindex >= info->old_bstart; bindex--) { + /* We don't rename if there is no source. */ + if (dtohd_index(old_dentry, bindex) == NULL) + continue; + + /* we rename the bstart of destination only at the last of + * all operations, so that we don't lose it on error + */ + if (info->clobber && (bindex == info->new_bstart)) + continue; + + DPUT(info->wh_old); + info->bwh_old = bindex; + /* We shouldn't have a handle on this if there is no inode. */ + err = + do_rename(old_dir, old_dentry, new_dir, new_dentry, bindex, + &info->wh_old); + if (!err) { + /* For reverting. */ + FD_SET(bindex, success_mask); + /* So we know not to copyup on failures the right */ + info->rename_ok = bindex; + } else if (IS_COPYUP_ERR(err)) { + if (info->isdir) { + err = -EXDEV; + break; + } + + /* we need a whiteout... */ + info->do_whiteout = bindex - 1; + + if (bindex == info->old_bstart) + /* ...and a copyup */ + info->do_copyup = bindex - 1; + + err = 0; /* reset error */ + } else + break; /* error is set by do_rename */ + } + + print_exit_status(err); + return err; +} + +/* + * Unlink all destinations (if they exist) to the left of the left-most + * source + */ +static int __rename_all_unlink(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + struct rename_info *info) +{ + int bindex; + + struct dentry *unlink_dentry; + struct dentry *unlink_dir_dentry; + + int err = 0; + + print_entry_location(); + + for (bindex = info->old_bstart - 1; bindex > info->new_bstart; bindex--) { + unlink_dentry = dtohd_index(new_dentry, bindex); + if (!unlink_dentry) + continue; + + /* lock, unlink if possible, copyup times, unlock */ + unlink_dir_dentry = lock_parent(unlink_dentry); + if (!(err = is_robranch_super(old_dir->i_sb, bindex))) + err = + vfs_unlink(unlink_dir_dentry->d_inode, + unlink_dentry, NULL); + + fist_copy_attr_times(new_dentry->d_parent->d_inode, + unlink_dir_dentry->d_inode); + new_dentry->d_parent->d_inode->i_nlink = + get_nlinks(new_dentry->d_parent->d_inode); + + unlock_dir(unlink_dir_dentry); + + if (!err) { + if (bindex != info->new_bstart) { + DPUT(unlink_dentry); + set_dtohd_index(new_dentry, bindex, NULL); + } + } else if (IS_COPYUP_ERR(err)) { + if (info->isdir) { + err = -EXDEV; + break; + } + info->do_copyup = bindex - 1; + + err = 0; /* reset error */ + } else + break; /* err is set by is_ro_branch_super or vfs_unlink */ + } + + print_exit_status(err); + return err; +} + +/* + * Try to revert everything we have done in __rename_all and __rename_all_unlink + */ +static int __rename_all_revert(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + fd_set * success_mask, struct rename_info *info) +{ + int bindex; + + int err; + int eio = 0; + + print_entry_location(); + + for (bindex = info->old_bstart; bindex <= info->old_bend; bindex++) { + if (!FD_ISSET(bindex, success_mask)) + continue; + + err = unionfs_refresh_hidden_dentry(new_dentry, bindex); + if (err) { + printk(KERN_WARNING "Revert failed in rename: " + "the new refresh failed.\n"); + eio = -EIO; + } + + err = unionfs_refresh_hidden_dentry(old_dentry, bindex); + if (err) { + printk(KERN_WARNING "Revert failed in rename: " + "the old refresh failed.\n"); + eio = -EIO; + continue; + } + + if (!dtohd_index(new_dentry, bindex) + || !dtohd_index(new_dentry, bindex)->d_inode) { + printk(KERN_WARNING "Revert failed in rename: " + "the object disappeared from under us!\n"); + eio = -EIO; + continue; + } + + if (dtohd_index(old_dentry, bindex) + && dtohd_index(old_dentry, bindex)->d_inode) { + printk(KERN_WARNING "Revert failed in rename: " + "the object was created underneath us!\n"); + eio = -EIO; + continue; + } + + err = + do_rename(new_dir, new_dentry, old_dir, old_dentry, bindex, + NULL); + /* If we can't fix it, then we cop-out with -EIO. */ + if (err) { + printk(KERN_WARNING "Revert failed in rename!\n"); + eio = -EIO; + } + + err = unionfs_refresh_hidden_dentry(new_dentry, bindex); + if (err) + eio = -EIO; + err = unionfs_refresh_hidden_dentry(old_dentry, bindex); + if (err) + eio = -EIO; + } + + print_exit_status(eio); + return eio; +} + +/* + * Finish off the rename, by either over writing the last destination or + * unlinking the last destination to the left of us + */ +static int __rename_all_clobber(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry, + struct rename_info *info) +{ + int err = 0; + + print_entry_location(); + + if (dtohd_index(old_dentry, info->new_bstart)) { + /* rename the last source, knowing we're overwriting something */ + DPUT(info->wh_old); + info->bwh_old = info->new_bstart; + err = + do_rename(old_dir, old_dentry, new_dir, new_dentry, + info->new_bstart, &info->wh_old); + if (IS_COPYUP_ERR(err)) { + if (info->isdir) { + err = -EXDEV; + goto out; + } + if (info->rename_ok > info->new_bstart) { + if ((info->do_copyup == -1) + || (info->new_bstart - 1 < info->do_copyup)) + info->do_copyup = info->new_bstart - 1; + } + if ((info->do_whiteout == -1) + || (info->new_bstart - 1 < info->do_whiteout)) { + info->do_whiteout = info->new_bstart - 1; + } + err = 0; // reset error + } + } else if (info->new_bstart < info->old_bstart) { + /* the newly renamed file would get hidden, let's unlink the + * file to the left of it */ + struct dentry *unlink_dentry; + struct dentry *unlink_dir_dentry; + + unlink_dentry = dtohd_index(new_dentry, info->new_bstart); + + unlink_dir_dentry = lock_parent(unlink_dentry); + if (!(err = is_robranch_super(old_dir->i_sb, info->new_bstart))) + err = vfs_unlink(unlink_dir_dentry->d_inode, + unlink_dentry, NULL); + + fist_copy_attr_times(new_dentry->d_parent->d_inode, + unlink_dir_dentry->d_inode); + new_dentry->d_parent->d_inode->i_nlink = + get_nlinks(new_dentry->d_parent->d_inode); + + unlock_dir(unlink_dir_dentry); + + if (IS_COPYUP_ERR(err)) { + if (info->isdir) { + err = -EXDEV; + goto out; + } + if ((info->do_copyup == -1) + || (info->new_bstart - 1 < info->do_copyup)) + info->do_copyup = info->new_bstart - 1; + + err = 0; // reset error + } + } + + out: + print_exit_status(err); + return err; +} + +/* + * The function is nasty, nasty, nasty, but so is rename. :( + */ +static int unionfs_rename_all(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + struct dentry *parent_dentry = NULL; + int err = 0; + int eio; + + /* These variables control error handling. */ + fd_set success_mask; + char *name = NULL; + + /* unfortunately, we have to resort to this, because dbstart/dbend would + return different things in different place of the rename code */ + struct rename_info info; + + info.rename_ok = FD_SETSIZE; /* The last rename that is ok. */ + info.do_copyup = -1; /* Where we should start copyup. */ + info.do_whiteout = -1; /* Where we should start whiteouts of the source. */ + info.wh_old = NULL; + info.bwh_old = -1; + + print_entry_location(); + + parent_dentry = old_dentry->d_parent; + name = KMALLOC(old_dentry->d_name.len + 1, GFP_KERNEL); + if (!name) { + err = -ENOMEM; + goto out; + } + strncpy(name, old_dentry->d_name.name, old_dentry->d_name.len + 1); + + info.new_bstart = dbstart(new_dentry); + info.new_bend = dbend(new_dentry); + + info.old_bstart = dbstart(old_dentry); + info.old_bend = dbend(old_dentry); + + BUG_ON(info.new_bstart < 0); + BUG_ON(info.old_bstart < 0); + + /* The failure mask only can deal with FD_SETSIZE entries. */ + BUG_ON(info.old_bend > FD_SETSIZE); + BUG_ON(info.new_bend > FD_SETSIZE); + FD_ZERO(&success_mask); + + /* Life is simpler if the dentry doesn't exist. */ + info.clobber = + (dtohd_index(new_dentry, info.new_bstart)->d_inode) ? 1 : 0; + info.isdir = S_ISDIR(old_dentry->d_inode->i_mode); + + /* rename everything we can */ + err = + __rename_all(old_dir, old_dentry, new_dir, new_dentry, + &success_mask, &info); + if (err) + goto revert; + + /* unlink destinations even further left */ + err = + __rename_all_unlink(old_dir, old_dentry, new_dir, new_dentry, + &info); + if (err) + goto revert; + + if (info.clobber) { + /* Now we need to handle the leftmost of the destination. */ + err = + __rename_all_clobber(old_dir, old_dentry, new_dir, + new_dentry, &info); + if (err) + goto revert; + } + + /* Copy up if necessary */ + if (info.do_copyup != -1) { + int bindex; + + for (bindex = info.do_copyup; bindex >= 0; bindex--) { + err = + copyup_dentry(old_dentry->d_parent->d_inode, + old_dentry, info.old_bstart, bindex, + NULL, old_dentry->d_inode->i_size); + if (!err) { + DPUT(info.wh_old); + info.bwh_old = bindex; + err = + do_rename(old_dir, old_dentry, new_dir, + new_dentry, bindex, &info.wh_old); + break; + } + } + } + + /* make it opaque */ + if (S_ISDIR(old_dentry->d_inode->i_mode)) { + err = make_dir_opaque(old_dentry, dbstart(old_dentry)); + if (err) + goto revert; + } + + /* Create a whiteout for the source. */ + if (info.do_whiteout != -1) { + struct dentry *hidden_parent; + BUG_ON(info.do_whiteout < 0 + || !info.wh_old || IS_ERR(info.wh_old) + || info.wh_old->d_inode || info.bwh_old < 0); + hidden_parent = lock_parent(info.wh_old); + err = vfs_create(hidden_parent->d_inode, info.wh_old, S_IRUGO, + NULL); + unlock_dir(hidden_parent); + if (!err) + set_dbopaque(old_dentry, info.bwh_old); + else { + /* We can't fix anything now, so we -EIO. */ + printk(KERN_WARNING "We can't create a whiteout for the" + "source in rename!\n"); + err = -EIO; + goto out; + } + } + + /* We are at the point where reverting doesn't happen. */ + goto out; + + revert: + /* something bad happened, try to revert */ + eio = + __rename_all_revert(old_dir, old_dentry, new_dir, new_dentry, + &success_mask, &info); + if (eio) + err = eio; + + out: + DPUT(info.wh_old); + KFREE(name); + print_exit_status(err); + return err; +} +#endif + +static struct dentry *lookup_whiteout(struct dentry *dentry) +{ + char *whname; + int bindex = -1, bstart = -1, bend = -1; + struct dentry *parent, *hidden_parent, *wh_dentry; + + whname = alloc_whname(dentry->d_name.name, dentry->d_name.len); + if (IS_ERR(whname)) + return (void *)whname; + + parent = GET_PARENT(dentry); + lock_dentry(parent); + bstart = dbstart(parent); + bend = dbend(parent); + wh_dentry = ERR_PTR(-ENOENT); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_parent = dtohd_index(parent, bindex); + if (!hidden_parent) + continue; + wh_dentry = + LOOKUP_ONE_LEN(whname, hidden_parent, + dentry->d_name.len + WHLEN); + if (IS_ERR(wh_dentry)) + continue; + if (wh_dentry->d_inode) + break; + DPUT(wh_dentry); + wh_dentry = ERR_PTR(-ENOENT); + } + unlock_dentry(parent); + DPUT(parent); + KFREE(whname); + return wh_dentry; +} + +/* We can't copyup a directory, because it may involve huge + * numbers of children, etc. Doing that in the kernel would + * be bad, so instead we let the userspace recurse and ask us + * to copy up each file separately + */ +static int may_rename_dir(struct dentry *dentry) +{ + int err, bstart; + + err = check_empty(dentry, NULL); + if (err == -ENOTEMPTY) { + if (is_robranch(dentry)) + return -EXDEV; + } else if (err) + return err; + + bstart = dbstart(dentry); + if (dbend(dentry) == bstart || dbopaque(dentry) == bstart) + return 0; + + set_dbstart(dentry, bstart + 1); + err = check_empty(dentry, NULL); + set_dbstart(dentry, bstart); + if (err == -ENOTEMPTY) + err = -EXDEV; + return err; +} + +int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + int err = 0; + struct dentry *wh_dentry; + + print_entry_location(); + + double_lock_dentry(old_dentry, new_dentry); + + checkinode(old_dir, "unionfs_rename-old_dir"); + checkinode(new_dir, "unionfs_rename-new_dir"); + print_dentry("IN: unionfs_rename, old_dentry", old_dentry); + print_dentry("IN: unionfs_rename, new_dentry", new_dentry); + + if (!S_ISDIR(old_dentry->d_inode->i_mode)) + err = unionfs_partial_lookup(old_dentry); + else + err = may_rename_dir(old_dentry); + + if (err) + goto out; + + err = unionfs_partial_lookup(new_dentry); + if (err) + goto out; + + /* + * if new_dentry is already hidden because of whiteout, + * simply override it even if the whiteouted dir is not empty. + */ + wh_dentry = lookup_whiteout(new_dentry); + if (!IS_ERR(wh_dentry)) + DPUT(wh_dentry); + else if (new_dentry->d_inode) { + if (S_ISDIR(old_dentry->d_inode->i_mode) != + S_ISDIR(new_dentry->d_inode->i_mode)) { + err = + S_ISDIR(old_dentry->d_inode-> + i_mode) ? -ENOTDIR : -EISDIR; + goto out; + } + + if (S_ISDIR(new_dentry->d_inode->i_mode)) { + struct unionfs_dir_state *namelist; + /* check if this unionfs directory is empty or not */ + err = check_empty(new_dentry, &namelist); + if (err) + goto out; + + if (!is_robranch(new_dentry)) + err = delete_whiteouts(new_dentry, + dbstart(new_dentry), + namelist); + + free_rdstate(namelist); + + if (err) + goto out; + } + } +#ifdef UNIONFS_DELETE_ALL + if (IS_SET(old_dir->i_sb, DELETE_ALL)) + err = unionfs_rename_all(old_dir, old_dentry, new_dir, + new_dentry); + else +#endif + err = unionfs_rename_whiteout(old_dir, old_dentry, new_dir, + new_dentry); + + out: + checkinode(new_dir, "post unionfs_rename-new_dir"); + print_dentry("OUT: unionfs_rename, old_dentry", old_dentry); + + if (err) { + /* clear the new_dentry stuff created */ + d_drop(new_dentry); + } else { + /* force re-lookup since the dir on ro branch is not renamed, + and hidden dentries still indicate the un-renamed ones. */ + if (S_ISDIR(old_dentry->d_inode->i_mode)) + atomic_dec(&dtopd(old_dentry)->udi_generation); + print_dentry("OUT: unionfs_rename, new_dentry", + new_dentry); + } + + unlock_dentry(new_dentry); + unlock_dentry(old_dentry); + print_exit_status(err); + return err; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/BOM +++ linux-2.6.27/ubuntu/unionfs/BOM @@ -0,0 +1,7 @@ +Downloaded from: http://www.filesystems.org/project-unionfs.html +Current Version: 1.4 + +Don't bother updating this code. No, we do not want 2.3.x. Yes, this is +heavily patched to account for upstream VFS API changes and AppArmor. + +DO NOT TOUCH :) --- linux-2.6.27.orig/ubuntu/unionfs/file.c +++ linux-2.6.27/ubuntu/unionfs/file.c @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: file.c,v 1.143 2006/08/05 01:28:46 jro Exp $ + */ + +#include "unionfs.h" + +/* declarations for sparse */ +extern ssize_t unionfs_read(struct file *, char __user *, size_t, loff_t *); +extern ssize_t unionfs_write(struct file *, const char __user *, size_t, + loff_t *); + +/******************* + * File Operations * + *******************/ + +#ifndef UNIONFS_MMAP +/* SP: Disable unionfs_llseek, as use generic_file_llseek on upper file */ +static loff_t unionfs_llseek(struct file *file, loff_t offset, int origin) +{ + loff_t err; + struct file *hidden_file = NULL; + + print_entry_location(); + + dprint(PRINT_DEBUG, "unionfs_llseek: file=%p, offset=0x%llx, origin=%d\n", + file, offset, origin); + + if ((err = unionfs_file_revalidate(file, 0))) + goto out; + + hidden_file = ftohf(file); + /* always set hidden position to this one */ + hidden_file->f_pos = file->f_pos; + + memcpy(&(hidden_file->f_ra), &(file->f_ra), + sizeof(struct file_ra_state)); + + if (hidden_file->f_op && hidden_file->f_op->llseek) + err = hidden_file->f_op->llseek(hidden_file, offset, origin); + else + err = generic_file_llseek(hidden_file, offset, origin); + + if (err < 0) + goto out; + if (err != file->f_pos) { + file->f_pos = err; + // ION maybe this? + // file->f_pos = hidden_file->f_pos; + + file->f_version++; + } + out: + print_exit_status((int)err); + return err; +} +#endif +ssize_t __unionfs_read(struct file * file, char __user * buf, size_t count, + loff_t * ppos) +{ + int err = -EINVAL; + struct file *hidden_file = NULL; + loff_t pos = *ppos; + + print_file("entering __unionfs_read()", file); + + hidden_file = ftohf(file); + if (!hidden_file->f_op || !hidden_file->f_op->read) + goto out; + + err = hidden_file->f_op->read(hidden_file, buf, count, &pos); + *ppos = pos; + + out: + print_file("leaving __unionfs_read()", file); + + print_exit_status(err); + return err; +} + +ssize_t unionfs_read(struct file * file, char __user * buf, size_t count, + loff_t * ppos) +{ + int err = -EINVAL; + + print_entry_location(); + + if ((err = unionfs_file_revalidate(file, 0))) + goto out; + +#ifdef UNIONFS_MMAP + err = generic_file_read(file, buf, count, ppos); + if (err >= 0) + file_accessed(ftohf(file)); +#else + err = __unionfs_read(file, buf, count, ppos); +#endif + + out: + + print_exit_status(err); + return err; +} + +/* SP: Sendfile code not updated, but should be able to use + * generic_file_sendfile, as it would use readpage, which we now have */ +#ifdef SUPPORT_BROKEN_LOSETUP +static ssize_t unionfs_sendfile(struct file *file, loff_t * ppos, + size_t count, read_actor_t actor, void *target) +{ + ssize_t err; + struct file *hidden_file = NULL; + + print_entry_location(); + + if ((err = unionfs_file_revalidate(file, 0))) + goto out; + + hidden_file = ftohf(file); + + err = -EINVAL; + if (!hidden_file->f_op || !hidden_file->f_op->sendfile) + goto out; + + err = hidden_file->f_op->sendfile(hidden_file, ppos, count, actor, + target); + + out: + print_exit_status(err); + return err; +} +#endif +ssize_t __unionfs_write(struct file * file, const char __user * buf, + size_t count, loff_t * ppos) +{ + int err = -EINVAL; + struct file *hidden_file = NULL; + struct inode *inode; + struct inode *hidden_inode; + loff_t pos = *ppos; + int bstart, bend; + + print_entry_location(); + + inode = file->f_dentry->d_inode; + + bstart = fbstart(file); + bend = fbend(file); + + BUG_ON(bstart == -1); + + hidden_file = ftohf(file); + hidden_inode = hidden_file->f_dentry->d_inode; + + if (!hidden_file->f_op || !hidden_file->f_op->write) + goto out; + + /* adjust for append -- seek to the end of the file */ + if (file->f_flags & O_APPEND) + pos = inode->i_size; + + err = hidden_file->f_op->write(hidden_file, buf, count, &pos); + + /* + * copy ctime and mtime from lower layer attributes + * atime is unchanged for both layers + */ + if (err >= 0) + fist_copy_attr_times(inode, hidden_inode); + + *ppos = pos; + + /* update this inode's size */ + if (pos > inode->i_size) + inode->i_size = pos; + out: + print_exit_status(err); + return err; +} + +ssize_t unionfs_write(struct file * file, const char __user * buf, size_t count, + loff_t * ppos) +{ + int err = 0; + + print_entry_location(); + + if ((err = unionfs_file_revalidate(file, 1))) + goto out; +#ifdef UNIONFS_MMAP + err = generic_file_write(file, buf, count, ppos); +#else + err = __unionfs_write(file, buf, count, ppos); +#endif + out: + print_exit_status(err); + return err; +} + +static int unionfs_file_readdir(struct file *file, void *dirent, + filldir_t filldir) +{ + int err = -ENOTDIR; + print_entry_location(); + print_exit_status(err); + return err; +} + +static unsigned int unionfs_poll(struct file *file, poll_table * wait) +{ + unsigned int mask = DEFAULT_POLLMASK; + struct file *hidden_file = NULL; + + print_entry_location(); + + if (unionfs_file_revalidate(file, 0)) { + /* We should pretend an error happend. */ + mask = POLLERR | POLLIN | POLLOUT; + goto out; + } + + hidden_file = ftohf(file); + + if (!hidden_file->f_op || !hidden_file->f_op->poll) + goto out; + + mask = hidden_file->f_op->poll(hidden_file, wait); + + out: + print_exit_status(mask); + return mask; +} + +#ifndef UNIONFS_MMAP +static int __do_mmap(struct file *file, struct vm_area_struct *vma) +{ + int err; + struct file *hidden_file; + + print_entry_location(); + hidden_file = ftohf(file); + + err = -ENODEV; + if (!hidden_file->f_op || !hidden_file->f_op->mmap) + goto out; + + vma->vm_file = hidden_file; + err = hidden_file->f_op->mmap(hidden_file, vma); + get_file(hidden_file); /* make sure it doesn't get freed on us */ + fput(file); /* no need to keep extra ref on ours */ + out: + print_exit_status(err); + return err; +} +#endif +/* SP: mmap code now maps upper file + * like old code, will only copyup at this point, it's possible to copyup + * in writepage(), but I haven't bothered with that, as only apt-get seem + * to want to write to a shared/write mapping + */ +static int unionfs_mmap(struct file *file, struct vm_area_struct *vma) +{ + int err = 0; + int willwrite; + + print_entry_location(); + + /* This might could be deferred to mmap's writepage. */ + willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags); + if ((err = unionfs_file_revalidate(file, willwrite))) + goto out; +#ifdef UNIONFS_MMAP + err = generic_file_mmap(file, vma); + if (err) { + printk("unionfs_mmap: generic_file_mmap failed\n"); + } +#else + err = __do_mmap(file, vma); +#endif + + out: + print_exit_status(err); + return err; +} + +/* SP: disabled as use the generic file_fsync */ +#ifndef UNIONFS_MMAP +static int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + int err; + struct file *hidden_file = NULL; + + print_entry_location(); + + if ((err = unionfs_file_revalidate(file, 1))) + goto out; + + hidden_file = ftohf(file); + + err = -EINVAL; + if (!hidden_file->f_op || !hidden_file->f_op->fsync) + goto out; + + mutex_lock(&hidden_file->f_dentry->d_inode->i_mutex); + err = hidden_file->f_op->fsync(hidden_file, hidden_file->f_dentry, + datasync); + mutex_unlock(&hidden_file->f_dentry->d_inode->i_mutex); + + out: + print_exit_status(err); + return err; +} +#endif + +/* SP: disabled as none of the other in kernel fs's seem to use it */ +static int unionfs_fasync(int fd, struct file *file, int flag) +{ + int err = 0; + struct file *hidden_file = NULL; + + print_entry_location(); + + if ((err = unionfs_file_revalidate(file, 1))) + goto out; + + hidden_file = ftohf(file); + + if (hidden_file->f_op && hidden_file->f_op->fasync) + err = hidden_file->f_op->fasync(fd, hidden_file, flag); + + out: + print_exit_status(err); + return err; +} + +struct file_operations unionfs_main_fops = { +#ifdef UNIONFS_MMAP + .llseek = generic_file_llseek, +#else + .llseek = unionfs_llseek, +#endif + .read = unionfs_read, + .write = unionfs_write, + .readdir = unionfs_file_readdir, + .poll = unionfs_poll, + .unlocked_ioctl = unionfs_ioctl, + .mmap = unionfs_mmap, + .open = unionfs_open, + .flush = unionfs_flush, + .release = unionfs_file_release, +#ifdef UNIONFS_MMAP + .fsync = file_fsync, +#else + .fsync = unionfs_fsync, +#endif + .fasync = unionfs_fasync, +#ifdef SUPPORT_BROKEN_LOSETUP + .sendfile = unionfs_sendfile, +#endif +}; + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/dirhelper.c +++ linux-2.6.27/ubuntu/unionfs/dirhelper.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: dirhelper.c,v 1.32 2006/10/31 18:05:33 yiannos Exp $ + */ + +#include "unionfs.h" + +/* Delete all of the whiteouts in a given directory for rmdir. */ +int do_delete_whiteouts(struct dentry *dentry, int bindex, + struct unionfs_dir_state *namelist) +{ + int err = 0; + struct dentry *hidden_dir_dentry = NULL; + struct dentry *hidden_dentry; + char *name = NULL, *p; + struct inode *hidden_dir; + + int i; + struct list_head *pos; + struct filldir_node *cursor; + + /* Find out hidden parent dentry */ + hidden_dir_dentry = dtohd_index(dentry, bindex); + BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode)); + hidden_dir = hidden_dir_dentry->d_inode; + BUG_ON(!S_ISDIR(hidden_dir->i_mode)); + + err = -ENOMEM; + name = __getname(); + if (!name) + goto out; + strcpy(name, WHPFX); + p = name + WHLEN; + + err = 0; + for (i = 0; !err && i < namelist->uds_size; i++) { + list_for_each(pos, &namelist->uds_list[i]) { + cursor = + list_entry(pos, struct filldir_node, file_list); + /* Only operate on whiteouts in this branch. */ + if (cursor->bindex != bindex) + continue; + if (!cursor->whiteout) + continue; + + strcpy(p, cursor->name); + hidden_dentry = + lookup_one_len(name, hidden_dir_dentry, + cursor->namelen + WHLEN); + if (IS_ERR(hidden_dentry)) { + err = PTR_ERR(hidden_dentry); + break; + } + if (hidden_dentry->d_inode) + err = vfs_unlink(hidden_dir, hidden_dentry, + NULL); + dput(hidden_dentry); + if (err) + break; + } + } + + __putname(name); + + /* After all of the removals, we should copy the attributes once. */ + fist_copy_attr_times(dentry->d_inode, hidden_dir_dentry->d_inode); + +out: + return err; +} + +/* Delete all of the whiteouts in a given directory for rmdir. */ +int delete_whiteouts(struct dentry *dentry, int bindex, + struct unionfs_dir_state *namelist) +{ + int err = 0; + struct dentry *hidden_dir_dentry = NULL; + struct super_block *sb; + char *name = NULL, *p; + struct inode *hidden_dir; + + struct sioq_args args; + + print_entry_location(); + + sb = dentry->d_sb; + unionfs_read_lock(sb); + + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode)); + BUG_ON(bindex < dbstart(dentry)); + BUG_ON(bindex > dbend(dentry)); + err = is_robranch_super(sb, bindex); + if (err) + goto out; + + /* Find out hidden parent dentry */ + hidden_dir_dentry = dtohd_index(dentry, bindex); + BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode)); + hidden_dir = hidden_dir_dentry->d_inode; + BUG_ON(!S_ISDIR(hidden_dir->i_mode)); + + err = -ENOMEM; + name = __getname(); + if (!name) + goto out; + strcpy(name, WHPFX); + p = name + WHLEN; + + err = 0; + mutex_lock(&hidden_dir->i_mutex); + + if (!inode_permission(hidden_dir, MAY_WRITE | MAY_EXEC)) + err = do_delete_whiteouts(dentry, bindex, namelist); + else { + args.deletewh.namelist = namelist; + args.deletewh.dentry = dentry; + args.deletewh.bindex = bindex; + run_sioq(__delete_whiteouts, &args); + err = args.err; + } + + mutex_unlock(&hidden_dir->i_mutex); + + out: + unionfs_read_unlock(sb); + print_exit_status(err); + return err; +} + +#define RD_NONE 0 +#define RD_CHECK_EMPTY 1 +/* The callback structure for check_empty. */ +struct unionfs_rdutil_callback { + int err; + int filldir_called; + struct unionfs_dir_state *rdstate; + int mode; +}; + +/* This filldir function makes sure only whiteouts exist within a directory. */ +static int readdir_util_callback(void *dirent, const char *name, int namelen, + loff_t offset, u64 ino, unsigned int d_type) +{ + int err = 0; + struct unionfs_rdutil_callback *buf = + (struct unionfs_rdutil_callback *)dirent; + int whiteout = 0; + struct filldir_node *found; + + print_entry_location(); + + buf->filldir_called = 1; + + if (name[0] == '.' + && (namelen == 1 || (name[1] == '.' && namelen == 2))) + goto out; + + if ((namelen > WHLEN) && !strncmp(name, WHPFX, WHLEN)) { + namelen -= WHLEN; + name += WHLEN; + whiteout = 1; + } + + found = find_filldir_node(buf->rdstate, name, namelen); + /* If it was found in the table there was a previous whiteout. */ + if (found) + goto out; + + /* If it wasn't found and isn't a whiteout, the directory isn't empty. */ + err = -ENOTEMPTY; + if ((buf->mode == RD_CHECK_EMPTY) && !whiteout) + goto out; + + err = add_filldir_node(buf->rdstate, name, namelen, + buf->rdstate->uds_bindex, whiteout); + + out: + buf->err = err; + print_exit_status(err); + return err; +} + +/* Is a directory logically empty? */ +int check_empty(struct dentry *dentry, struct unionfs_dir_state **namelist) +{ + int err = 0; + struct dentry *hidden_dentry = NULL; + struct super_block *sb; + struct file *hidden_file; + struct unionfs_rdutil_callback *buf = NULL; + int bindex, bstart, bend, bopaque; + + print_entry_location(); + + sb = dentry->d_sb; + + unionfs_read_lock(sb); + + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode)); + + if ((err = unionfs_partial_lookup(dentry))) + goto out; + + bstart = dbstart(dentry); + bend = dbend(dentry); + bopaque = dbopaque(dentry); + if (0 <= bopaque && bopaque < bend) + bend = bopaque; + + buf = KMALLOC(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto out; + } + buf->err = 0; + buf->mode = RD_CHECK_EMPTY; + buf->rdstate = alloc_rdstate(dentry->d_inode, bstart); + if (!buf->rdstate) { + err = -ENOMEM; + goto out; + } + + /* Process the hidden directories with rdutil_callback as a filldir. */ + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + if (!hidden_dentry->d_inode) + continue; + if (!S_ISDIR(hidden_dentry->d_inode->i_mode)) + continue; + + DGET(hidden_dentry); + mntget(stohiddenmnt_index(sb, bindex)); + branchget(sb, bindex); + hidden_file = + DENTRY_OPEN(hidden_dentry, stohiddenmnt_index(sb, bindex), + O_RDONLY); + if (IS_ERR(hidden_file)) { + err = PTR_ERR(hidden_file); + DPUT(hidden_dentry); + branchput(sb, bindex); + goto out; + } + + do { + buf->filldir_called = 0; + buf->rdstate->uds_bindex = bindex; + err = vfs_readdir(hidden_file, + readdir_util_callback, buf); + if (buf->err) + err = buf->err; + } while ((err >= 0) && buf->filldir_called); + + /* fput calls dput for hidden_dentry */ + fput(hidden_file); + branchput(sb, bindex); + + if (err < 0) + goto out; + } + + out: + if (buf) { + if (namelist && !err) + *namelist = buf->rdstate; + else if (buf->rdstate) + free_rdstate(buf->rdstate); + KFREE(buf); + } + + unionfs_read_unlock(sb); + + print_exit_status(err); + return err; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/dentry.c +++ linux-2.6.27/ubuntu/unionfs/dentry.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: dentry.c,v 1.77 2006/08/05 01:28:46 jro Exp $ + */ + +#include "unionfs.h" + +/* declarations added for "sparse" */ +extern int unionfs_d_revalidate_wrap(struct dentry *dentry, + struct nameidata *nd); +extern void unionfs_d_release(struct dentry *dentry); +extern void unionfs_d_iput(struct dentry *dentry, struct inode *inode); + +/* + * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise. + */ +int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) +{ + int valid = 1; /* default is valid (1); invalid is 0. */ + struct dentry *hidden_dentry; + int bindex, bstart, bend; + int sbgen, dgen; + int positive = 0; + int locked = 0; + int restart = 0; + int interpose_flag; + + struct nameidata lowernd; + + if(nd) + memcpy(&lowernd, nd, sizeof(struct nameidata)); + else + memset(&lowernd, 0, sizeof(struct nameidata)); + + print_util_entry_location(); + + restart: + verify_locked(dentry); + + /* if the dentry is unhashed, do NOT revalidate */ + if (d_deleted(dentry)) { + dprint(PRINT_DEBUG, "unhashed dentry being revalidated: %*s\n", + dentry->d_name.len, dentry->d_name.name); + goto out; + } + + BUG_ON(dbstart(dentry) == -1); + if (dentry->d_inode) + positive = 1; + dgen = atomic_read(&dtopd(dentry)->udi_generation); + sbgen = atomic_read(&stopd(dentry->d_sb)->usi_generation); + /* If we are working on an unconnected dentry, then there is no + * revalidation to be done, because this file does not exist within the + * namespace, and Unionfs operates on the namespace, not data. + */ + if (sbgen != dgen) { + struct dentry *result; + int pdgen; + + unionfs_read_lock(dentry->d_sb); + locked = 1; + + /* The root entry should always be valid */ + BUG_ON(IS_ROOT(dentry)); + + /* We can't work correctly if our parent isn't valid. */ + pdgen = atomic_read(&dtopd(dentry->d_parent)->udi_generation); + if (!restart && (pdgen != sbgen)) { + unionfs_read_unlock(dentry->d_sb); + locked = 0; + /* We must be locked before our parent. */ + if (! + (dentry->d_parent->d_op-> + d_revalidate(dentry->d_parent, nd))) { + valid = 0; + goto out; + } + restart = 1; + goto restart; + } + BUG_ON(pdgen != sbgen); + + /* Free the pointers for our inodes and this dentry. */ + bstart = dbstart(dentry); + bend = dbend(dentry); + if (bstart >= 0) { + struct dentry *hidden_dentry; + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = + dtohd_index_nocheck(dentry, bindex); + if (!hidden_dentry) + continue; + DPUT(hidden_dentry); + } + } + set_dbstart(dentry, -1); + set_dbend(dentry, -1); + + interpose_flag = INTERPOSE_REVAL_NEG; + if (positive) { + interpose_flag = INTERPOSE_REVAL; + mutex_lock(&dentry->d_inode->i_mutex); + bstart = ibstart(dentry->d_inode); + bend = ibend(dentry->d_inode); + if (bstart >= 0) { + struct inode *hidden_inode; + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_inode = + itohi_index(dentry->d_inode, + bindex); + if (!hidden_inode) + continue; + IPUT(hidden_inode); + } + } + KFREE(itohi_ptr(dentry->d_inode)); + itohi_ptr(dentry->d_inode) = NULL; + ibstart(dentry->d_inode) = -1; + ibend(dentry->d_inode) = -1; + mutex_unlock(&dentry->d_inode->i_mutex); + } + + result = unionfs_lookup_backend(dentry, &lowernd, interpose_flag); + if (result) { + if (IS_ERR(result)) { + valid = 0; + goto out; + } + /* current unionfs_lookup_backend() doesn't return + a valid dentry */ + DPUT(dentry); + dentry = result; + } + + if (positive && itopd(dentry->d_inode)->uii_stale) { + make_stale_inode(dentry->d_inode); + d_drop(dentry); + valid = 0; + goto out; + } + goto out; + } + + /* The revalidation must occur across all branches */ + bstart = dbstart(dentry); + bend = dbend(dentry); + BUG_ON(bstart == -1); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry || !hidden_dentry->d_op + || !hidden_dentry->d_op->d_revalidate) + continue; + + if (!hidden_dentry->d_op->d_revalidate(hidden_dentry, nd)) + valid = 0; + } + + if (!dentry->d_inode) + valid = 0; + if (valid) + fist_copy_attr_all(dentry->d_inode, itohi(dentry->d_inode)); + + out: + if (locked) + unionfs_read_unlock(dentry->d_sb); + print_dentry("revalidate out", dentry); + print_util_exit_status(valid); + return valid; +} + +int unionfs_d_revalidate_wrap(struct dentry *dentry, struct nameidata *nd) +{ + int err; + + print_entry_location(); + lock_dentry(dentry); + + err = unionfs_d_revalidate(dentry, nd); + + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +void unionfs_d_release(struct dentry *dentry) +{ + struct dentry *hidden_dentry; + int bindex, bstart, bend; + + print_entry_location(); + /* There is no reason to lock the dentry, because we have the only + * reference, but the printing functions verify that we have a lock + * on the dentry before calling dbstart, etc. */ + lock_dentry(dentry); + print_dentry_nocheck("unionfs_d_release IN dentry", dentry); + + /* this could be a negative dentry, so check first */ + if (!dtopd(dentry)) { + dprint(PRINT_DEBUG, "dentry without private data: %*s", + dentry->d_name.len, dentry->d_name.name); + goto out; + } else if (dbstart(dentry) < 0) { + /* this is due to a failed lookup */ + /* the failed lookup has a dtohd_ptr set to null, + but this is a better check */ + dprint(PRINT_DEBUG, "dentry without hidden dentries : %*s", + dentry->d_name.len, dentry->d_name.name); + goto out_free; + } + + /* Release all the hidden dentries */ + bstart = dbstart(dentry); + bend = dbend(dentry); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + DPUT(hidden_dentry); + set_dtohd_index(dentry, bindex, NULL); + } + /* free private data (unionfs_dentry_info) here */ + KFREE(dtohd_ptr(dentry)); + dtohd_ptr(dentry) = NULL; + out_free: + /* No need to unlock it, because it is disappeared. */ +#ifdef TRACKLOCK + printk("DESTROYLOCK:%p\n", dentry); +#endif + free_dentry_private_data(dtopd(dentry)); + dtopd_lhs(dentry) = NULL; /* just to be safe */ + out: + print_exit_location(); +} + +/* + * we don't really need unionfs_d_iput, because dentry_iput will call iput() if + * unionfs_d_iput is not defined. We left this implemented for ease of + * tracing/debugging. + */ +void unionfs_d_iput(struct dentry *dentry, struct inode *inode) +{ + print_entry_location(); + IPUT(inode); + print_exit_location(); +} + +struct dentry_operations unionfs_dops = { + .d_revalidate = unionfs_d_revalidate_wrap, + .d_release = unionfs_d_release, + .d_iput = unionfs_d_iput, +}; + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/branchman.c +++ linux-2.6.27/ubuntu/unionfs/branchman.c @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: branchman.c,v 1.66 2006/10/31 00:05:22 yiannos Exp $ + */ + +#include "unionfs.h" + +struct dentry **alloc_new_dentries(int objs) +{ + if (!objs) + return NULL; + + return KZALLOC(sizeof(struct dentry *) * objs, GFP_KERNEL); +} + +struct unionfs_usi_data *alloc_new_data(int objs) +{ + if (!objs) + return NULL; + + return KZALLOC(sizeof(struct unionfs_usi_data) * objs, GFP_KERNEL); +} + +static void fixputmaps(struct super_block *sb) +{ + struct unionfs_sb_info *spd; + struct putmap *cur; + int gen; + int i; + + print_entry_location(); + + spd = stopd(sb); + cur = spd->usi_putmaps[spd->usi_lastputmap - spd->usi_firstputmap]; + + for (gen = 0; gen < spd->usi_lastputmap - spd->usi_firstputmap; gen++) { + if (!spd->usi_putmaps[gen]) + continue; + for (i = 0; i <= spd->usi_putmaps[gen]->bend; i++) + spd->usi_putmaps[gen]->map[i] = + cur->map[spd->usi_putmaps[gen]->map[i]]; + } + + print_exit_location(); +} + +static int newputmap(struct super_block *sb) +{ + struct unionfs_sb_info *spd; + struct putmap *newmap; + int count = 0; + int i; + + print_entry_location(); + + spd = stopd(sb); + + i = sizeof(int) * (sbend(sb) + 1); + newmap = KMALLOC(sizeof(struct putmap) + i, GFP_KERNEL); + if (!newmap) { + print_exit_status(-ENOMEM); + return -ENOMEM; + } + + if (!spd->usi_firstputmap) { + spd->usi_firstputmap = 1; + spd->usi_lastputmap = 1; + + spd->usi_putmaps = KMALLOC(sizeof(struct putmap *), GFP_KERNEL); + if (!spd->usi_putmaps) { + KFREE(newmap); + print_exit_status(-ENOMEM); + return -ENOMEM; + } + } else { + struct putmap **newlist; + int newfirst = spd->usi_firstputmap; + + while (!spd->usi_putmaps[newfirst - spd->usi_firstputmap] && + newfirst <= spd->usi_lastputmap) { + newfirst++; + } + + newlist = + KMALLOC(sizeof(struct putmap *) * + (1 + spd->usi_lastputmap - newfirst), GFP_KERNEL); + if (!newlist) { + KFREE(newmap); + print_exit_status(-ENOMEM); + return -ENOMEM; + } + + for (i = newfirst; i <= spd->usi_lastputmap; i++) { + newlist[i - newfirst] = + spd->usi_putmaps[i - spd->usi_firstputmap]; + } + + KFREE(spd->usi_putmaps); + spd->usi_putmaps = newlist; + spd->usi_firstputmap = newfirst; + spd->usi_lastputmap++; + } + + newmap->bend = sbend(sb); + for (i = 0; i <= sbend(sb); i++) { + count += branch_count(sb, i); + newmap->map[i] = i; + } + for (i = spd->usi_firstputmap; i < spd->usi_lastputmap; i++) { + struct putmap *cur; + cur = spd->usi_putmaps[i - spd->usi_firstputmap]; + if (!cur) + continue; + count -= atomic_read(&cur->count); + } + atomic_set(&newmap->count, count); + spd->usi_putmaps[spd->usi_lastputmap - spd->usi_firstputmap] = newmap; + + print_exit_status(0); + return 0; +} + +/* XXX: this function needs to go. There is no reason for this to be here */ +int unionfs_ioctl_branchcount(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int err = 0; + int bstart, bend; + int i; + struct super_block *sb = file->f_dentry->d_sb; + + print_entry_location(); + + bstart = sbstart(sb); + bend = sbend(sb); + + err = bend + 1; + if (!arg) + goto out; + + for (i = bstart; i <= bend; i++) { + if (put_user(branch_count(sb, i), ((int __user *)arg) + i)) { + err = -EFAULT; + goto out; + } + } + + out: + print_exit_status(err); + return err; +} + +int unionfs_ioctl_incgen(struct file *file, unsigned int cmd, unsigned long arg) +{ + int err = 0; + struct super_block *sb; + + print_entry_location(); + + sb = file->f_dentry->d_sb; + + unionfs_write_lock(sb); + if ((err = newputmap(sb))) + goto out; + + atomic_inc(&stopd(sb)->usi_generation); + err = atomic_read(&stopd(sb)->usi_generation); + + atomic_set(&dtopd(sb->s_root)->udi_generation, err); + atomic_set(&itopd(sb->s_root->d_inode)->uii_generation, err); + + out: + unionfs_write_unlock(sb); + print_exit_status(err); + return err; +} + +int unionfs_ioctl_addbranch(struct inode *inode, unsigned int cmd, + unsigned long arg) +{ + int err; + struct unionfs_addbranch_args *addargs = NULL; + struct nameidata nd; + char *path = NULL; + int gen; + int i; + + int pobjects; + + struct unionfs_usi_data *new_data = NULL; + struct dentry **new_udi_dentry = NULL; + struct inode **new_uii_inode = NULL; + + struct dentry *root = NULL; + struct dentry *hidden_root = NULL; + + print_entry_location(); + +#ifdef UNIONFS_IMAP + if (stopd(sb)->usi_persistent) { + printk(KERN_ERR "Cannot manipulate branches if imap is used\n"); + err = -EPERM; + goto out; + } +#endif + + err = -ENOMEM; + addargs = KMALLOC(sizeof(struct unionfs_addbranch_args), GFP_KERNEL); + if (!addargs) + goto out; + + err = -EFAULT; + if (copy_from_user + (addargs, (const void __user *)arg, + sizeof(struct unionfs_addbranch_args))) + goto out; + + err = -EINVAL; + if (addargs->ab_perms & ~(MAY_READ | MAY_WRITE | MAY_NFSRO)) + goto out; + if (!(addargs->ab_perms & MAY_READ)) + goto out; + + err = -E2BIG; + if (sbend(inode->i_sb) > FD_SETSIZE) + goto out; + + err = -ENOMEM; + if (!(path = getname((const char __user *)addargs->ab_path))) + goto out; + + err = path_lookup(path, LOOKUP_FOLLOW, &nd); + + RECORD_PATH_LOOKUP(&nd); + if (err) + goto out; + if ((err = check_branch(&nd))) { + path_put(&nd.path); + RECORD_PATH_RELEASE(&nd); + goto out; + } + + unionfs_write_lock(inode->i_sb); + lock_dentry(inode->i_sb->s_root); + + root = inode->i_sb->s_root; + for (i = dbstart(inode->i_sb->s_root); i <= dbend(inode->i_sb->s_root); + i++) { + hidden_root = dtohd_index(root, i); + if (is_branch_overlap(hidden_root, nd.path.dentry)) { + err = -EINVAL; + goto out; + } + } + + err = -EINVAL; + if (addargs->ab_branch < 0 + || (addargs->ab_branch > (sbend(inode->i_sb) + 1))) + goto out; + + if ((err = newputmap(inode->i_sb))) + goto out; + + stopd(inode->i_sb)->b_end++; + dtopd(inode->i_sb->s_root)->udi_bcount++; + set_dbend(inode->i_sb->s_root, dbend(inode->i_sb->s_root) + 1); + itopd(inode->i_sb->s_root->d_inode)->b_end++; + + atomic_inc(&stopd(inode->i_sb)->usi_generation); + gen = atomic_read(&stopd(inode->i_sb)->usi_generation); + + pobjects = sbend(inode->i_sb) + 1; + + /* Reallocate the dynamic structures. */ + new_data = alloc_new_data(pobjects); + new_udi_dentry = alloc_new_dentries(pobjects); + new_uii_inode = KZALLOC(sizeof(struct inode *) * pobjects, GFP_KERNEL); + + if (!new_udi_dentry || !new_uii_inode || !new_data) { + err = -ENOMEM; + goto out; + } + + /* Copy the in-place values to our new structure. */ + for (i = 0; i < addargs->ab_branch; i++) { + atomic_set(&(new_data[i].sbcount), + branch_count(inode->i_sb, i)); + + new_data[i].branchperms = branchperms(inode->i_sb, i); + new_data[i].hidden_mnt = stohiddenmnt_index(inode->i_sb, i); + new_data[i].sb = stohs_index(inode->i_sb, i); + + new_udi_dentry[i] = dtohd_index(inode->i_sb->s_root, i); + new_uii_inode[i] = itohi_index(inode->i_sb->s_root->d_inode, i); + } + + /* Shift the ends to the right (only handle reallocated bits). */ + for (i = sbend(inode->i_sb) - 1; i >= (int)addargs->ab_branch; i--) { + int j = i + 1; + int pmindex; + + atomic_set(&new_data[j].sbcount, branch_count(inode->i_sb, i)); + + new_data[j].branchperms = branchperms(inode->i_sb, i); + new_data[j].hidden_mnt = stohiddenmnt_index(inode->i_sb, i); + new_data[j].sb = stohs_index(inode->i_sb, i); + new_udi_dentry[j] = dtohd_index(inode->i_sb->s_root, i); + new_uii_inode[j] = itohi_index(inode->i_sb->s_root->d_inode, i); + + /* Update the newest putmap, so it is correct for later. */ + pmindex = stopd(inode->i_sb)->usi_lastputmap; + pmindex -= stopd(inode->i_sb)->usi_firstputmap; + stopd(inode->i_sb)->usi_putmaps[pmindex]->map[i] = j; + + } + + /* Now we can free the old ones. */ + KFREE(dtopd(inode->i_sb->s_root)->udi_dentry); + KFREE(itopd(inode->i_sb->s_root->d_inode)->uii_inode); + KFREE(stopd(inode->i_sb)->usi_data); + + /* Update the real pointers. */ + dtohd_ptr(inode->i_sb->s_root) = new_udi_dentry; + itohi_ptr(inode->i_sb->s_root->d_inode) = new_uii_inode; + stopd(inode->i_sb)->usi_data = new_data; + + /* Re-NULL the new ones so we don't try to free them. */ + new_data = NULL; + new_udi_dentry = NULL; + new_uii_inode = NULL; + + /* Put the new dentry information into it's slot. */ + set_dtohd_index(inode->i_sb->s_root, addargs->ab_branch, nd.path.dentry); + set_itohi_index(inode->i_sb->s_root->d_inode, addargs->ab_branch, + IGRAB(nd.path.dentry->d_inode)); + set_branchperms(inode->i_sb, addargs->ab_branch, addargs->ab_perms); + set_branch_count(inode->i_sb, addargs->ab_branch, 0); + set_stohiddenmnt_index(inode->i_sb, addargs->ab_branch, nd.path.mnt); + set_stohs_index(inode->i_sb, addargs->ab_branch, nd.path.dentry->d_sb); + + atomic_set(&dtopd(inode->i_sb->s_root)->udi_generation, gen); + atomic_set(&itopd(inode->i_sb->s_root->d_inode)->uii_generation, gen); + + fixputmaps(inode->i_sb); + + out: + unlock_dentry(inode->i_sb->s_root); + unionfs_write_unlock(inode->i_sb); + + KFREE(new_udi_dentry); + KFREE(new_uii_inode); + KFREE(new_data); + KFREE(addargs); + if (path) + putname(path); + + print_exit_status(err); + + return err; +} + +/* This must be called with the super block already locked. */ +int unionfs_ioctl_delbranch(struct super_block *sb, unsigned long arg) +{ + struct dentry *hidden_dentry; + struct inode *hidden_inode; + struct vfsmount *hidden_mnt; + struct dentry *root_dentry; + struct inode *root_inode; + int err = 0; + int pmindex, i, gen; + + print_entry("branch = %lu ", arg); + lock_dentry(sb->s_root); + +#ifdef UNIONFS_IMAP + if (stopd(sb)->usi_persistent) { + printk(KERN_ERR "Cannot manipulate branches if imap is used\n"); + err = -EPERM; + goto out; + } +#endif + err = -EBUSY; + if (sbmax(sb) == 1) + goto out; + err = -EINVAL; + if (arg < 0 || arg > stopd(sb)->b_end) + goto out; + err = -EBUSY; + if (branch_count(sb, arg)) + goto out; + if ((err = newputmap(sb))) + goto out; + + pmindex = stopd(sb)->usi_lastputmap; + pmindex -= stopd(sb)->usi_firstputmap; + + atomic_inc(&stopd(sb)->usi_generation); + gen = atomic_read(&stopd(sb)->usi_generation); + + root_dentry = sb->s_root; + root_inode = sb->s_root->d_inode; + + hidden_dentry = dtohd_index(root_dentry, arg); + hidden_mnt = stohiddenmnt_index(sb, arg); + hidden_inode = itohi_index(root_inode, arg); + + DPUT(hidden_dentry); + IPUT(hidden_inode); + mntput(hidden_mnt); + + for (i = arg; i <= (sbend(sb) - 1); i++) { + set_branch_count(sb, i, branch_count(sb, i + 1)); + set_stohiddenmnt_index(sb, i, stohiddenmnt_index(sb, i + 1)); + set_stohs_index(sb, i, stohs_index(sb, i + 1)); + set_branchperms(sb, i, branchperms(sb, i + 1)); + set_dtohd_index(root_dentry, i, + dtohd_index(root_dentry, i + 1)); + set_itohi_index(root_inode, i, itohi_index(root_inode, i + 1)); + stopd(sb)->usi_putmaps[pmindex]->map[i + 1] = i; + } + + set_dtohd_index(root_dentry, sbend(sb), NULL); + set_itohi_index(root_inode, sbend(sb), NULL); + set_stohiddenmnt_index(sb, sbend(sb), NULL); + set_stohs_index(sb, sbend(sb), NULL); + + //XXX: Place check for inode maps and removal of branch here + + stopd(sb)->b_end--; + set_dbend(root_dentry, dbend(root_dentry) - 1); + dtopd(root_dentry)->udi_bcount--; + itopd(root_inode)->b_end--; + + atomic_set(&dtopd(root_dentry)->udi_generation, gen); + atomic_set(&itopd(root_inode)->uii_generation, gen); + + fixputmaps(sb); + + /* This doesn't open a file, so we might have to free the map here. */ + if (atomic_read(&stopd(sb)->usi_putmaps[pmindex]->count) == 0) { + KFREE(stopd(sb)->usi_putmaps[pmindex]); + stopd(sb)->usi_putmaps[pmindex] = NULL; + } + + out: + unlock_dentry(sb->s_root); + print_exit_status(err); + + return err; +} + +int unionfs_ioctl_rdwrbranch(struct inode *inode, unsigned int cmd, + unsigned long arg) +{ + int err; + struct unionfs_rdwrbranch_args *rdwrargs = NULL; + int gen; + + print_entry_location(); + + unionfs_write_lock(inode->i_sb); + lock_dentry(inode->i_sb->s_root); + + if ((err = newputmap(inode->i_sb))) + goto out; + + err = -ENOMEM; + rdwrargs = KMALLOC(sizeof(struct unionfs_rdwrbranch_args), GFP_KERNEL); + if (!rdwrargs) + goto out; + + err = -EFAULT; + if (copy_from_user + (rdwrargs, (const void __user *)arg, + sizeof(struct unionfs_rdwrbranch_args))) + goto out; + + err = -EINVAL; + if (rdwrargs->rwb_branch < 0 + || (rdwrargs->rwb_branch > (sbend(inode->i_sb) + 1))) + goto out; + if (rdwrargs->rwb_perms & ~(MAY_READ | MAY_WRITE | MAY_NFSRO)) + goto out; + if (!(rdwrargs->rwb_perms & MAY_READ)) + goto out; + + set_branchperms(inode->i_sb, rdwrargs->rwb_branch, rdwrargs->rwb_perms); + + atomic_inc(&stopd(inode->i_sb)->usi_generation); + gen = atomic_read(&stopd(inode->i_sb)->usi_generation); + atomic_set(&dtopd(inode->i_sb->s_root)->udi_generation, gen); + atomic_set(&itopd(inode->i_sb->s_root->d_inode)->uii_generation, gen); + + err = 0; + + out: + unlock_dentry(inode->i_sb->s_root); + unionfs_write_unlock(inode->i_sb); + KFREE(rdwrargs); + + print_exit_status(err); + + return err; +} + +int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int err = 0; + fd_set branchlist; + + int bstart = 0, bend = 0, bindex = 0; + struct dentry *dentry, *hidden_dentry; + + print_entry_location(); + + dentry = file->f_dentry; + lock_dentry(dentry); + if ((err = unionfs_partial_lookup(dentry))) + goto out; + bstart = dbstart(dentry); + bend = dbend(dentry); + + FD_ZERO(&branchlist); + + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + if (hidden_dentry->d_inode) + FD_SET(bindex, &branchlist); + } + + err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set)); + if (err) { + err = -EFAULT; + goto out; + } + + out: + unlock_dentry(dentry); + err = err < 0 ? err : bend; + print_exit_status(err); + return (err); +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/commonfops.c +++ linux-2.6.27/ubuntu/unionfs/commonfops.c @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: commonfops.c,v 1.61 2006/08/05 01:28:46 jro Exp $ + */ + +#include "unionfs.h" + +/* We only need this function here, but it could get promoted to unionfs.h, if + * other things need a generation specific branch putting function. */ +static inline void branchput_gen(int generation, struct super_block *sb, + int index) +{ + struct putmap *putmap; + + if (generation == atomic_read(&stopd(sb)->usi_generation)) { + branchput(sb, index); + return; + } + + BUG_ON(stopd(sb)->usi_firstputmap > generation); + BUG_ON(stopd(sb)->usi_lastputmap < generation); + + putmap = + stopd(sb)->usi_putmaps[generation - stopd(sb)->usi_firstputmap]; + BUG_ON(index < 0); + BUG_ON(index > putmap->bend); + BUG_ON(putmap->map[index] < 0); + branchput(sb, putmap->map[index]); + if (atomic_dec_and_test(&putmap->count)) { + stopd(sb)->usi_putmaps[generation - stopd(sb)->usi_firstputmap] + = NULL; + dprint(PRINT_DEBUG, "Freeing putmap %d.\n", generation); + KFREE(putmap); + } +} + +static char *get_random_name(int size, unsigned char *name) +{ + int i; + int j; + unsigned char *tmpbuf = NULL; + + if (size <= WHLEN) + return NULL; + + if (!name) + name = KMALLOC(size + 1, GFP_KERNEL); + if (!name) { + name = ERR_PTR(-ENOMEM); + goto out; + } + strncpy(name, WHPFX, WHLEN); + + tmpbuf = KMALLOC(size, GFP_KERNEL); + if (!tmpbuf) { + KFREE(name); + name = ERR_PTR(-ENOMEM); + goto out; + } + + get_random_bytes((void *)tmpbuf, (size - 3) / 2); + + j = WHLEN; + i = 0; + while ((i < (size - 3) / 2) && (j < size)) { + /* get characters in the 0-9, A-F range */ + + name[j] = + (tmpbuf[i] % 16) < + 10 ? (tmpbuf[i] % 16) + '0' : (tmpbuf[i] % 16) + 'a'; + j++; + if (j == size) + break; + name[j] = + (tmpbuf[i] >> 4) < + 10 ? (tmpbuf[i] >> 4) + '0' : (tmpbuf[i] >> 4) + 'a'; + j++; + + i++; + } + + name[size] = '\0'; + + out: + KFREE(tmpbuf); + return (name); + +} + +static int copyup_deleted_file(struct file *file, struct dentry *dentry, + int bstart, int bindex) +{ + int attempts = 0; + int err; + int exists = 1; + char *name = NULL; + struct dentry *tmp_dentry = NULL; + struct dentry *hidden_dentry = NULL; + struct dentry *hidden_dir_dentry = NULL; + + print_entry_location(); + + /* Try five times to get a unique file name, fail after that. Five is + * simply a magic number, because we shouldn't try forever. */ + while (exists) { + /* The first call allocates, the subsequent ones reuse. */ + name = get_random_name(UNIONFS_TMPNAM_LEN, name); + err = -ENOMEM; + if (!name) + goto out; + //XXX: Why do we do this every time? bstart never changes? + hidden_dentry = dtohd_index(dentry, bstart); + + tmp_dentry = LOOKUP_ONE_LEN(name, hidden_dentry->d_parent, + UNIONFS_TMPNAM_LEN); + err = PTR_ERR(tmp_dentry); + if (IS_ERR(tmp_dentry)) + goto out; + exists = tmp_dentry->d_inode ? 1 : 0; + DPUT(tmp_dentry); + + err = -EEXIST; + if (++attempts > 5) + goto out; + } + + err = copyup_named_file(dentry->d_parent->d_inode, file, name, bstart, + bindex, file->f_dentry->d_inode->i_size); + if (err) + goto out; + + /* bring it to the same state as an unlinked file */ + hidden_dentry = dtohd_index(dentry, dbstart(dentry)); + hidden_dir_dentry = lock_parent(hidden_dentry); + err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry, NULL); + unlock_dir(hidden_dir_dentry); + + out: + KFREE(name); + print_exit_status(err); + return err; +} + +int unionfs_file_revalidate(struct file *file, int willwrite) +{ + struct super_block *sb; + struct dentry *dentry; + int sbgen, fgen, dgen; + int bindex, bstart, bend; + struct file *hidden_file; + struct dentry *hidden_dentry; + int size; + + int err = 0; + + print_entry(" file = %p", file); + + dentry = file->f_dentry; + lock_dentry(dentry); + sb = dentry->d_sb; + unionfs_read_lock(sb); + if (!unionfs_d_revalidate(dentry, NULL) && !d_deleted(dentry)) { + err = -ESTALE; + goto out; + } + print_dentry("file revalidate in", dentry); + + sbgen = atomic_read(&stopd(sb)->usi_generation); + dgen = atomic_read(&dtopd(dentry)->udi_generation); + fgen = atomic_read(&ftopd(file)->ufi_generation); + + BUG_ON(sbgen > dgen); + + /* There are two cases we are interested in. The first is if the + * generation is lower than the super-block. The second is if someone + * has copied up this file from underneath us, we also need to refresh + * things. */ + if (!d_deleted(dentry) && + ((sbgen > fgen) || (dbstart(dentry) != fbstart(file)))) { + /* First we throw out the existing files. */ + bstart = fbstart(file); + bend = fbend(file); + for (bindex = bstart; bindex <= bend; bindex++) { + if (ftohf_index(file, bindex)) { + branchput_gen(fgen, dentry->d_sb, bindex); + fput(ftohf_index(file, bindex)); + } + } + + if (ftohf_ptr(file)) { + KFREE(ftohf_ptr(file)); + ftohf_ptr(file) = NULL; + } + + /* Now we reopen the file(s) as in unionfs_open. */ + bstart = fbstart(file) = dbstart(dentry); + bend = fbend(file) = dbend(dentry); + + size = sizeof(struct file *) * sbmax(sb); + ftohf_ptr(file) = KZALLOC(size, GFP_KERNEL); + if (!ftohf_ptr(file)) { + err = -ENOMEM; + goto out; + } + + if (S_ISDIR(dentry->d_inode->i_mode)) { + /* We need to open all the files. */ + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + + DGET(hidden_dentry); + mntget(stohiddenmnt_index(sb, bindex)); + branchget(sb, bindex); + + hidden_file = + DENTRY_OPEN(hidden_dentry, + stohiddenmnt_index(sb, bindex), + file->f_flags); + if (IS_ERR(hidden_file)) { + err = PTR_ERR(hidden_file); + goto out; + } else { + set_ftohf_index(file, bindex, + hidden_file); + } + } + } else { + /* We only open the highest priority branch. */ + hidden_dentry = dtohd(dentry); + if (willwrite && IS_WRITE_FLAG(file->f_flags) + && is_robranch(dentry)) { + for (bindex = bstart - 1; bindex >= 0; bindex--) { + + err = copyup_file(dentry-> + d_parent-> + d_inode, + file, + bstart, + bindex, + file-> + f_dentry-> + d_inode->i_size); + + if (!err) + break; + else + continue; + + } + atomic_set(&ftopd(file)->ufi_generation, + atomic_read(&itopd(dentry->d_inode)-> + uii_generation)); + goto out; + } + + DGET(hidden_dentry); + mntget(stohiddenmnt_index(sb, bstart)); + branchget(sb, bstart); + hidden_file = + DENTRY_OPEN(hidden_dentry, + stohiddenmnt_index(sb, bstart), + file->f_flags); + if (IS_ERR(hidden_file)) { + err = PTR_ERR(hidden_file); + goto out; + } + set_ftohf(file, hidden_file); + /* Fix up the position. */ + hidden_file->f_pos = file->f_pos; + + memcpy(&(hidden_file->f_ra), &(file->f_ra), + sizeof(struct file_ra_state)); + } + atomic_set(&ftopd(file)->ufi_generation, + atomic_read(&itopd(dentry->d_inode)-> + uii_generation)); + } + + /* Copyup on the first write to a file on a readonly branch. */ + if (willwrite && IS_WRITE_FLAG(file->f_flags) + && !IS_WRITE_FLAG(ftohf(file)->f_flags) && is_robranch(dentry)) { + dprint(PRINT_DEBUG, + "Doing delayed copyup of a read-write file on a read-only branch.\n"); + bstart = fbstart(file); + bend = fbend(file); + + BUG_ON(!S_ISREG(file->f_dentry->d_inode->i_mode)); + + for (bindex = bstart - 1; bindex >= 0; bindex--) { + if (!d_deleted(file->f_dentry)) { + err = + copyup_file(dentry->d_parent-> + d_inode, file, bstart, + bindex, + file->f_dentry-> + d_inode->i_size); + } else { + err = + copyup_deleted_file(file, dentry, bstart, + bindex); + } + + if (!err) + break; + else + continue; + + } + if (!err && (bstart > fbstart(file))) { + bend = fbend(file); + for (bindex = bstart; bindex <= bend; bindex++) { + if (ftohf_index(file, bindex)) { + branchput(dentry->d_sb, bindex); + fput(ftohf_index(file, bindex)); + set_ftohf_index(file, bindex, NULL); + } + } + fbend(file) = bend; + } + } + + out: + print_dentry("file revalidate out", dentry); + unlock_dentry(dentry); + unionfs_read_unlock(dentry->d_sb); + print_exit_status(err); + return err; +} + +int unionfs_open(struct inode *inode, struct file *file) +{ + int err = 0; + int hidden_flags; + struct file *hidden_file = NULL; + struct dentry *hidden_dentry = NULL; + struct dentry *dentry = NULL; + int bindex = 0, bstart = 0, bend = 0; + int locked = 0; + int size; + + print_entry_location(); + + ftopd_lhs(file) = KZALLOC(sizeof(struct unionfs_file_info), GFP_KERNEL); + if (!ftopd(file)) { + err = -ENOMEM; + goto out; + } + fbstart(file) = -1; + fbend(file) = -1; + atomic_set(&ftopd(file)->ufi_generation, + atomic_read(&itopd(inode)->uii_generation)); + + size = sizeof(struct file *) * sbmax(inode->i_sb); + ftohf_ptr(file) = KZALLOC(size, GFP_KERNEL); + if (!ftohf_ptr(file)) { + err = -ENOMEM; + goto out; + } + + hidden_flags = file->f_flags; + + dentry = file->f_dentry; + dprint(PRINT_DEBUG, "dentry to open is %p\n", dentry); + lock_dentry(dentry); + unionfs_read_lock(inode->i_sb); + locked = 1; + + bstart = fbstart(file) = dbstart(dentry); + bend = fbend(file) = dbend(dentry); + + /* increment to show the kind of open, so that we can + * flush appropriately + */ + atomic_inc(&itopd(dentry->d_inode)->uii_totalopens); + + /* open all directories and make the unionfs file struct point to these hidden file structs */ + if (S_ISDIR(inode->i_mode)) { + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + + DGET(hidden_dentry); + mntget(stohiddenmnt_index(inode->i_sb, bindex)); + hidden_file = + DENTRY_OPEN(hidden_dentry, + stohiddenmnt_index(inode->i_sb, bindex), + hidden_flags); + if (IS_ERR(hidden_file)) { + err = PTR_ERR(hidden_file); + goto out; + } + + set_ftohf_index(file, bindex, hidden_file); + /* The branchget goes after the open, because otherwise + * we would miss the reference on release. */ + branchget(inode->i_sb, bindex); + } + } else { + /* open a file */ + hidden_dentry = dtohd(dentry); + + /* check for the permission for hidden file. If the error is COPYUP_ERR, + * copyup the file. + */ + if (hidden_dentry->d_inode && is_robranch(dentry)) { + /* if the open will change the file, copy it up otherwise defer it. */ + if (hidden_flags & O_TRUNC) { + int size = 0; + + err = -EROFS; + /* copyup the file */ + for (bindex = bstart - 1; bindex >= 0; bindex--) { + err = + copyup_file(dentry-> + d_parent-> + d_inode, file, + bstart, bindex, size); + if (!err) { + break; + } + } + goto out; + } else { + hidden_flags &= ~(OPEN_WRITE_FLAGS); + } + } + + DGET(hidden_dentry); + /* dentry_open will decrement mnt refcnt if err. + * otherwise fput() will do an mntput() for us upon file close. + */ + mntget(stohiddenmnt_index(inode->i_sb, bstart)); + hidden_file = DENTRY_OPEN(hidden_dentry, + stohiddenmnt_index(inode->i_sb, + bstart), + hidden_flags); + if (IS_ERR(hidden_file)) { + err = PTR_ERR(hidden_file); + goto out; + } else { + set_ftohf(file, hidden_file); + branchget(inode->i_sb, bstart); + } + } + + out: + /* freeing the allocated resources, and fput the opened files */ + if (err < 0 && ftopd(file)) { + if (!locked) + unionfs_read_lock(file->f_dentry->d_sb); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_file = ftohf_index(file, bindex); + if (hidden_file) { + branchput(file->f_dentry->d_sb, bindex); + /* fput calls dput for hidden_dentry */ + fput(hidden_file); + } + } + if (!locked) + unionfs_read_unlock(file->f_dentry->d_sb); + KFREE(ftohf_ptr(file)); + KFREE(ftopd(file)); + } + + print_file("OUT: unionfs_open", file); + + if (locked) { + unlock_dentry(dentry); + unionfs_read_unlock(inode->i_sb); + } + print_exit_status(err); + return err; +} + +int unionfs_file_release(struct inode *inode, struct file *file) +{ + int err = 0; + struct file *hidden_file = NULL; + int bindex, bstart, bend; + int fgen; + + print_entry_location(); + + checkinode(inode, "unionfs_release"); + + /* fput all the hidden files */ + fgen = atomic_read(&ftopd(file)->ufi_generation); + bstart = fbstart(file); + bend = fbend(file); + + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_file = ftohf_index(file, bindex); + + if (hidden_file) { + fput(hidden_file); + unionfs_read_lock(inode->i_sb); + branchput_gen(fgen, inode->i_sb, bindex); + unionfs_read_unlock(inode->i_sb); + } + } + KFREE(ftohf_ptr(file)); + + if (ftopd(file)->rdstate) { + ftopd(file)->rdstate->uds_access = jiffies; + dprint(PRINT_DEBUG, "Saving rdstate with cookie %u [%d.%lld]\n", + ftopd(file)->rdstate->uds_cookie, + ftopd(file)->rdstate->uds_bindex, + (long long)ftopd(file)->rdstate->uds_dirpos); + spin_lock(&itopd(inode)->uii_rdlock); + itopd(inode)->uii_rdcount++; + list_add_tail(&ftopd(file)->rdstate->uds_cache, + &itopd(inode)->uii_readdircache); + mark_inode_dirty(inode); + spin_unlock(&itopd(inode)->uii_rdlock); + ftopd(file)->rdstate = NULL; + } + KFREE(ftopd(file)); + + checkinode(inode, "post unionfs_release"); + + print_exit_status(err); + return err; +} + +long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long err = 0; /* don't fail by default */ + struct file *hidden_file = NULL; + int val; + + print_entry_location(); + + if ((err = unionfs_file_revalidate(file, 1))) + goto out; + + /* check if asked for local commands */ + switch (cmd) { + case FIST_IOCTL_GET_DEBUG_VALUE: + if (!capable(CAP_SYS_ADMIN)) { + err = -EACCES; + goto out; + } + val = get_debug_mask(); + err = put_user(val, (int __user *)arg); + break; + + case FIST_IOCTL_SET_DEBUG_VALUE: + if (!capable(CAP_SYS_ADMIN)) { + err = -EACCES; + goto out; + } + err = get_user(val, (int __user *)arg); + if (err) + break; + dprint(PRINT_DEBUG, "IOCTL SET: got arg %d\n", val); + if (val < 0 || val > PRINT_MAX) { + err = -EINVAL; + break; + } + set_debug_mask(val); + break; + + /* add non-debugging fist ioctl's here */ + + case UNIONFS_IOCTL_BRANCH_COUNT: + if (!capable(CAP_SYS_ADMIN)) { + err = -EACCES; + goto out; + } + err = unionfs_ioctl_branchcount(file, cmd, arg); + break; + + case UNIONFS_IOCTL_INCGEN: + if (!capable(CAP_SYS_ADMIN)) { + err = -EACCES; + goto out; + } + err = unionfs_ioctl_incgen(file, cmd, arg); + break; + + case UNIONFS_IOCTL_ADDBRANCH: + if (!capable(CAP_SYS_ADMIN)) { + err = -EACCES; + goto out; + } + err = + unionfs_ioctl_addbranch(file->f_dentry->d_inode, cmd, arg); + break; + + case UNIONFS_IOCTL_RDWRBRANCH: + if (!capable(CAP_SYS_ADMIN)) { + err = -EACCES; + goto out; + } + err = + unionfs_ioctl_rdwrbranch(file->f_dentry->d_inode, cmd, arg); + break; + + case UNIONFS_IOCTL_QUERYFILE: + /* XXX: This should take the file. */ + err = unionfs_ioctl_queryfile(file, cmd, arg); + break; + + default: + hidden_file = ftohf(file); + + err = -ENOTTY; + if (!hidden_file || !hidden_file->f_op) + goto out; + if (hidden_file->f_op->unlocked_ioctl) { + err = + hidden_file->f_op->unlocked_ioctl(hidden_file, cmd, + arg); + } else if (hidden_file->f_op->ioctl) { + lock_kernel(); + err = + hidden_file->f_op->ioctl(hidden_file->f_dentry-> + d_inode, hidden_file, cmd, + arg); + unlock_kernel(); + } + } /* end of outer switch statement */ + + out: + print_exit_status((int)err); + return err; +} + +int unionfs_flush(struct file *file, fl_owner_t id) +{ + int err = 0; /* assume ok (see open.c:close_fp) */ + struct file *hidden_file = NULL; + int bindex, bstart, bend; + + print_entry_location(); + + if ((err = unionfs_file_revalidate(file, 1))) + goto out; + if (!atomic_dec_and_test + (&itopd(file->f_dentry->d_inode)->uii_totalopens)) + goto out; + + lock_dentry(file->f_dentry); + + bstart = fbstart(file); + bend = fbend(file); + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_file = ftohf_index(file, bindex); + + if (hidden_file && hidden_file->f_op + && hidden_file->f_op->flush) { + err = hidden_file->f_op->flush(hidden_file, id); + if (err) + goto out_lock; + /* This was earlier done in the unlink_all function in unlink.c */ + /* if there are no more references to the dentry, dput it */ + if (d_deleted(file->f_dentry)) { + DPUT(dtohd_index(file->f_dentry, bindex)); + set_dtohd_index(file->f_dentry, bindex, NULL); + } + } + + } + + out_lock: + unlock_dentry(file->f_dentry); + out: + print_exit_status(err); + return err; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/inode.c +++ linux-2.6.27/ubuntu/unionfs/inode.c @@ -0,0 +1,1034 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: inode.c,v 1.275 2006/10/31 18:05:33 yiannos Exp $ + */ + +#include "unionfs.h" + +/* declarations added for "sparse" */ +extern struct dentry *unionfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +extern int unionfs_readlink(struct dentry *dentry, char __user * buf, + int bufsiz); +extern void unionfs_put_link(struct dentry *dentry, struct nameidata *nd, + void *cookie); + +static int unionfs_create(struct inode *parent, struct dentry *dentry, + int mode, struct nameidata *nd) +{ + int err = 0; + struct dentry *hidden_dentry = NULL; + struct dentry *whiteout_dentry = NULL; + struct dentry *new_hidden_dentry; + struct dentry *hidden_parent_dentry = NULL; + int bindex = 0, bstart; + char *name = NULL; + + print_entry_location(); + lock_dentry(dentry); + print_dentry("IN unionfs_create", dentry); + + /* We start out in the leftmost branch. */ + bstart = dbstart(dentry); + hidden_dentry = dtohd(dentry); + + /* check if whiteout exists in this branch, i.e. lookup .wh.foo first */ + name = alloc_whname(dentry->d_name.name, dentry->d_name.len); + if (IS_ERR(name)) { + err = PTR_ERR(name); + goto out; + } + + whiteout_dentry = + LOOKUP_ONE_LEN(name, hidden_dentry->d_parent, + dentry->d_name.len + WHLEN); + if (IS_ERR(whiteout_dentry)) { + err = PTR_ERR(whiteout_dentry); + whiteout_dentry = NULL; + goto out; + } + + if (whiteout_dentry->d_inode) { + /* .wh.foo has been found. */ + /* First truncate it and then rename it to foo (hence having + * the same overall effect as a normal create. + * + * XXX: This is not strictly correct. If we have unlinked the + * file and it still has a reference count, then we should + * actually unlink the whiteout so that user's data isn't + * hosed over. + */ + struct dentry *hidden_dir_dentry; + struct iattr newattrs; + + mutex_lock(&whiteout_dentry->d_inode->i_mutex); + newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME + | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE + | ATTR_KILL_SUID | ATTR_KILL_SGID; + + newattrs.ia_mode = mode & ~current->fs->umask; + newattrs.ia_uid = current->fsuid; + newattrs.ia_gid = current->fsgid; + + if (whiteout_dentry->d_inode->i_size != 0) { + newattrs.ia_valid |= ATTR_SIZE; + newattrs.ia_size = 0; + } + + err = notify_change(whiteout_dentry, NULL, &newattrs); + + mutex_unlock(&whiteout_dentry->d_inode->i_mutex); + + if (err) + printk(KERN_WARNING + "unionfs: %s:%d: notify_change failed: %d, ignoring..\n", + __FILE__, __LINE__, err); + + new_hidden_dentry = dtohd(dentry); + DGET(new_hidden_dentry); + + hidden_dir_dentry = GET_PARENT(whiteout_dentry); + lock_rename(hidden_dir_dentry, hidden_dir_dentry); + + if (!(err = is_robranch_super(dentry->d_sb, bstart))) { + err = + vfs_rename(hidden_dir_dentry->d_inode, + whiteout_dentry, NULL, + hidden_dir_dentry->d_inode, + new_hidden_dentry, NULL); + } + if (!err) { + fist_copy_attr_timesizes(parent, + new_hidden_dentry->d_parent-> + d_inode); + parent->i_nlink = get_nlinks(parent); + } + + unlock_rename(hidden_dir_dentry, hidden_dir_dentry); + DPUT(hidden_dir_dentry); + + DPUT(new_hidden_dentry); + + if (err) { + /* exit if the error returned was NOT -EROFS */ + if (!IS_COPYUP_ERR(err)) + goto out; + /* We were not able to create the file in this branch, + * so, we try to create it in one branch to left + */ + bstart--; + } else { + /* reset the unionfs dentry to point to the .wh.foo entry. */ + + /* Discard any old reference. */ + DPUT(dtohd(dentry)); + + /* Trade one reference to another. */ + set_dtohd_index(dentry, bstart, whiteout_dentry); + whiteout_dentry = NULL; + + err = unionfs_interpose(dentry, parent->i_sb, 0); + goto out; + } + } + + for (bindex = bstart; bindex >= 0; bindex--) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) { + /* if hidden_dentry is NULL, create the entire + * dentry directory structure in branch 'bindex'. + * hidden_dentry will NOT be null when bindex == bstart + * because lookup passed as a negative unionfs dentry + * pointing to a lone negative underlying dentry */ + hidden_dentry = create_parents(parent, dentry, bindex); + if (!hidden_dentry || IS_ERR(hidden_dentry)) { + if (IS_ERR(hidden_dentry)) + err = PTR_ERR(hidden_dentry); + continue; + } + } + + checkinode(parent, "unionfs_create"); + + hidden_parent_dentry = lock_parent(hidden_dentry); + if (IS_ERR(hidden_parent_dentry)) { + err = PTR_ERR(hidden_parent_dentry); + goto out; + } + /* We shouldn't create things in a read-only branch. */ + if (!(err = is_robranch_super(dentry->d_sb, bindex))) { + //DQ: vfs_create has a different prototype in 2.6 + err = vfs_create(hidden_parent_dentry->d_inode, + hidden_dentry, mode, nd); + } + if (err || !hidden_dentry->d_inode) { + unlock_dir(hidden_parent_dentry); + + /* break out of for loop if the error wasn't -EROFS */ + if (!IS_COPYUP_ERR(err)) + break; + } else { + err = unionfs_interpose(dentry, parent->i_sb, 0); + if (!err) { + fist_copy_attr_timesizes(parent, + hidden_parent_dentry-> + d_inode); + /* update number of links on parent directory */ + parent->i_nlink = get_nlinks(parent); + } + unlock_dir(hidden_parent_dentry); + break; + } + } + + out: + DPUT(whiteout_dentry); + KFREE(name); + + print_dentry("OUT unionfs_create :", dentry); + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +struct dentry *unionfs_lookup(struct inode *parent, struct dentry *dentry, + struct nameidata *nd) +{ + struct nameidata lowernd; + + if(nd) + memcpy(&lowernd, nd, sizeof(struct nameidata)); + else + memset(&lowernd, 0, sizeof(struct nameidata)); + + /* The locking is done by unionfs_lookup_backend. */ + return unionfs_lookup_backend(dentry, &lowernd, INTERPOSE_LOOKUP); +} + +static int unionfs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *new_dentry) +{ + int err = 0; + struct dentry *hidden_old_dentry = NULL; + struct dentry *hidden_new_dentry = NULL; + struct dentry *hidden_dir_dentry = NULL; + struct dentry *whiteout_dentry; + char *name = NULL; + + print_entry_location(); + double_lock_dentry(new_dentry, old_dentry); + + hidden_new_dentry = dtohd(new_dentry); + + /* check if whiteout exists in the branch of new dentry, i.e. lookup + * .wh.foo first. If present, delete it */ + name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len); + if (IS_ERR(name)) { + err = PTR_ERR(name); + goto out; + } + + whiteout_dentry = + LOOKUP_ONE_LEN(name, hidden_new_dentry->d_parent, + new_dentry->d_name.len + WHLEN); + if (IS_ERR(whiteout_dentry)) { + err = PTR_ERR(whiteout_dentry); + goto out; + } + + if (!whiteout_dentry->d_inode) { + DPUT(whiteout_dentry); + whiteout_dentry = NULL; + } else { + /* found a .wh.foo entry, unlink it and then call vfs_link() */ + hidden_dir_dentry = lock_parent(whiteout_dentry); + if (! + (err = + is_robranch_super(new_dentry->d_sb, + dbstart(new_dentry)))) { + err = + vfs_unlink(hidden_dir_dentry->d_inode, + whiteout_dentry, NULL); + } + fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); + dir->i_nlink = get_nlinks(dir); + unlock_dir(hidden_dir_dentry); + hidden_dir_dentry = NULL; + DPUT(whiteout_dentry); + if (err) + goto out; + } + + if (dbstart(old_dentry) != dbstart(new_dentry)) { + hidden_new_dentry = + create_parents(dir, new_dentry, dbstart(old_dentry)); + err = PTR_ERR(hidden_new_dentry); + if (IS_COPYUP_ERR(err)) + goto docopyup; + if (!hidden_new_dentry || IS_ERR(hidden_new_dentry)) + goto out; + } + hidden_new_dentry = dtohd(new_dentry); + hidden_old_dentry = dtohd(old_dentry); + + BUG_ON(dbstart(old_dentry) != dbstart(new_dentry)); + hidden_dir_dentry = lock_parent(hidden_new_dentry); + if (!(err = is_robranch(old_dentry))) + err = + vfs_link(hidden_old_dentry, NULL, + hidden_dir_dentry->d_inode, + hidden_new_dentry, NULL); + unlock_dir(hidden_dir_dentry); + + docopyup: + if (IS_COPYUP_ERR(err)) { + int old_bstart = dbstart(old_dentry); + int bindex; + + for (bindex = old_bstart - 1; bindex >= 0; bindex--) { + err = + copyup_dentry(old_dentry->d_parent-> + d_inode, old_dentry, + old_bstart, bindex, NULL, + old_dentry->d_inode->i_size); + if (!err) { + hidden_new_dentry = + create_parents(dir, new_dentry, bindex); + hidden_old_dentry = dtohd(old_dentry); + hidden_dir_dentry = + lock_parent(hidden_new_dentry); + /* do vfs_link */ + err = vfs_link(hidden_old_dentry, NULL, + hidden_dir_dentry->d_inode, + hidden_new_dentry, NULL); + unlock_dir(hidden_dir_dentry); + goto check_link; + } + } + goto out; + } + check_link: + if (err || !hidden_new_dentry->d_inode) + goto out; + + /* Its a hard link, so use the same inode */ + new_dentry->d_inode = IGRAB(old_dentry->d_inode); + d_instantiate(new_dentry, new_dentry->d_inode); + fist_copy_attr_all(dir, hidden_new_dentry->d_parent->d_inode); + /* propagate number of hard-links */ + old_dentry->d_inode->i_nlink = get_nlinks(old_dentry->d_inode); + + out: + if (!new_dentry->d_inode) + d_drop(new_dentry); + + KFREE(name); + + unlock_dentry(new_dentry); + unlock_dentry(old_dentry); + + print_exit_status(err); + return err; +} + +static int unionfs_symlink(struct inode *dir, struct dentry *dentry, + const char *symname) +{ + int err = 0; + struct dentry *hidden_dentry = NULL; + struct dentry *whiteout_dentry = NULL; + struct dentry *hidden_dir_dentry = NULL; + umode_t mode; + int bindex = 0, bstart; + char *name = NULL; + + print_entry_location(); + lock_dentry(dentry); + print_dentry("IN unionfs_symlink", dentry); + + /* We start out in the leftmost branch. */ + bstart = dbstart(dentry); + + hidden_dentry = dtohd(dentry); + + /* check if whiteout exists in this branch, i.e. lookup .wh.foo first. If present, delete it */ + name = alloc_whname(dentry->d_name.name, dentry->d_name.len); + if (IS_ERR(name)) { + err = PTR_ERR(name); + goto out; + } + + whiteout_dentry = + LOOKUP_ONE_LEN(name, hidden_dentry->d_parent, + dentry->d_name.len + WHLEN); + if (IS_ERR(whiteout_dentry)) { + err = PTR_ERR(whiteout_dentry); + goto out; + } + + if (!whiteout_dentry->d_inode) { + DPUT(whiteout_dentry); + whiteout_dentry = NULL; + } else { + /* found a .wh.foo entry, unlink it and then call vfs_symlink() */ + hidden_dir_dentry = lock_parent(whiteout_dentry); + + print_dentry("HDD", hidden_dir_dentry); + print_dentry("WD", whiteout_dentry); + + if (!(err = is_robranch_super(dentry->d_sb, bstart))) { + err = + vfs_unlink(hidden_dir_dentry->d_inode, + whiteout_dentry, NULL); + } + DPUT(whiteout_dentry); + + fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); + /* propagate number of hard-links */ + dir->i_nlink = get_nlinks(dir); + + unlock_dir(hidden_dir_dentry); + + if (err) { + /* exit if the error returned was NOT -EROFS */ + if (!IS_COPYUP_ERR(err)) + goto out; + /* should now try to create symlink in the another branch */ + bstart--; + } + } + + /* deleted whiteout if it was present, now do a normal vfs_symlink() with + possible recursive directory creation */ + for (bindex = bstart; bindex >= 0; bindex--) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) { + /* if hidden_dentry is NULL, create the entire + * dentry directory structure in branch 'bindex'. hidden_dentry will NOT be null when + * bindex == bstart because lookup passed as a negative unionfs dentry pointing to a + * lone negative underlying dentry */ + hidden_dentry = create_parents(dir, dentry, bindex); + if (!hidden_dentry || IS_ERR(hidden_dentry)) { + if (IS_ERR(hidden_dentry)) { + err = PTR_ERR(hidden_dentry); + } + dprint(PRINT_DEBUG, + "hidden dentry NULL (or error) for bindex = %d\n", + bindex); + continue; + } + } + + hidden_dir_dentry = lock_parent(hidden_dentry); + + if (!(err = is_robranch_super(dentry->d_sb, bindex))) { + mode = S_IALLUGO; + err = + vfs_symlink(hidden_dir_dentry->d_inode, + hidden_dentry, NULL, symname); + } + unlock_dir(hidden_dir_dentry); + + if (err || !hidden_dentry->d_inode) { + /* break out of for loop if error returned was NOT -EROFS */ + if (!IS_COPYUP_ERR(err)) + break; + } else { + err = unionfs_interpose(dentry, dir->i_sb, 0); + if (!err) { + fist_copy_attr_timesizes(dir, + hidden_dir_dentry-> + d_inode); + /* update number of links on parent directory */ + dir->i_nlink = get_nlinks(dir); + } + break; + } + } + + out: + if (!dentry->d_inode) + d_drop(dentry); + + KFREE(name); + print_dentry("OUT unionfs_symlink :", dentry); + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +static int unionfs_mkdir(struct inode *parent, struct dentry *dentry, int mode) +{ + int err = 0; + struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL; + struct dentry *hidden_parent_dentry = NULL; + int bindex = 0, bstart; + char *name = NULL; + int whiteout_unlinked = 0; + struct sioq_args args; + + print_entry_location(); + lock_dentry(dentry); + print_dentry("IN unionfs_mkdir", dentry); + bstart = dbstart(dentry); + + hidden_dentry = dtohd(dentry); + + // check if whiteout exists in this branch, i.e. lookup .wh.foo first + name = alloc_whname(dentry->d_name.name, dentry->d_name.len); + if (IS_ERR(name)) { + err = PTR_ERR(name); + goto out; + } + + whiteout_dentry = + LOOKUP_ONE_LEN(name, hidden_dentry->d_parent, + dentry->d_name.len + WHLEN); + if (IS_ERR(whiteout_dentry)) { + err = PTR_ERR(whiteout_dentry); + goto out; + } + + if (!whiteout_dentry->d_inode) { + DPUT(whiteout_dentry); + whiteout_dentry = NULL; + } else { + hidden_parent_dentry = lock_parent(whiteout_dentry); + + //found a.wh.foo entry, remove it then do vfs_mkdir + if (!(err = is_robranch_super(dentry->d_sb, bstart))) { + args.unlink.parent = hidden_parent_dentry->d_inode; + args.unlink.dentry = whiteout_dentry; + run_sioq(__unionfs_unlink, &args); + err = args.err; + } + DPUT(whiteout_dentry); + + unlock_dir(hidden_parent_dentry); + + if (err) { + /* exit if the error returned was NOT -EROFS */ + if (!IS_COPYUP_ERR(err)) + goto out; + bstart--; + } else { + whiteout_unlinked = 1; + } + } + + for (bindex = bstart; bindex >= 0; bindex--) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) { + hidden_dentry = create_parents(parent, dentry, bindex); + if (!hidden_dentry || IS_ERR(hidden_dentry)) { + dprint(PRINT_DEBUG, + "hidden dentry NULL for bindex = %d\n", + bindex); + continue; + } + } + + hidden_parent_dentry = lock_parent(hidden_dentry); + if (IS_ERR(hidden_parent_dentry)) { + err = PTR_ERR(hidden_parent_dentry); + goto out; + } + if (!(err = is_robranch_super(dentry->d_sb, bindex))) { + err = + vfs_mkdir(hidden_parent_dentry->d_inode, + hidden_dentry, NULL, mode); + } + unlock_dir(hidden_parent_dentry); + + /* XXX this could potentially return a negative hidden_dentry! */ + if (err || !hidden_dentry->d_inode) { + /* break out of for loop if error returned was NOT -EROFS */ + if (!IS_COPYUP_ERR(err)) + break; + } else { + int i; + int bend = dbend(dentry); + + for (i = bindex + 1; i < bend; i++) { + if (dtohd_index(dentry, i)) { + DPUT(dtohd_index(dentry, i)); + set_dtohd_index(dentry, i, NULL); + } + } + bend = bindex; + set_dbend(dentry, bend); + + err = unionfs_interpose(dentry, parent->i_sb, 0); + if (!err) { + fist_copy_attr_timesizes(parent, + hidden_parent_dentry-> + d_inode); + /* update number of links on parent directory */ + parent->i_nlink = get_nlinks(parent); + } + + err = make_dir_opaque(dentry, dbstart(dentry)); + if (err) { + dprint(PRINT_DEBUG, + "mkdir: error creating directory override entry: %d\n", + err); + goto out; + } + break; + } + } + + out: + if (!dentry->d_inode) + d_drop(dentry); + + KFREE(name); + + print_dentry("OUT unionfs_mkdir :", dentry); + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode, + dev_t dev) +{ + int err = 0; + struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL; + struct dentry *hidden_parent_dentry = NULL; + int bindex = 0, bstart; + char *name = NULL; + int whiteout_unlinked = 0; + + print_entry_location(); + lock_dentry(dentry); + print_dentry("IN unionfs_mknod", dentry); + bstart = dbstart(dentry); + + hidden_dentry = dtohd(dentry); + + // check if whiteout exists in this branch, i.e. lookup .wh.foo first + name = alloc_whname(dentry->d_name.name, dentry->d_name.len); + if (IS_ERR(name)) { + err = PTR_ERR(name); + goto out; + } + + whiteout_dentry = + LOOKUP_ONE_LEN(name, hidden_dentry->d_parent, + dentry->d_name.len + WHLEN); + if (IS_ERR(whiteout_dentry)) { + err = PTR_ERR(whiteout_dentry); + goto out; + } + + if (!whiteout_dentry->d_inode) { + DPUT(whiteout_dentry); + whiteout_dentry = NULL; + } else { + /* found .wh.foo, unlink it */ + hidden_parent_dentry = lock_parent(whiteout_dentry); + + //found a.wh.foo entry, remove it then do vfs_mkdir + if (!(err = is_robranch_super(dentry->d_sb, bstart))) + err = vfs_unlink(hidden_parent_dentry->d_inode, + whiteout_dentry, NULL); + DPUT(whiteout_dentry); + + unlock_dir(hidden_parent_dentry); + + if (err) { + if (!IS_COPYUP_ERR(err)) + goto out; + + bstart--; + } else { + whiteout_unlinked = 1; + } + } + + for (bindex = bstart; bindex >= 0; bindex--) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) { + hidden_dentry = create_parents(dir, dentry, bindex); + if (!hidden_dentry || IS_ERR(hidden_dentry)) { + dprint(PRINT_DEBUG, + "hidden dentry NULL for bindex = %d\n", + bindex); + continue; + } + } + + hidden_parent_dentry = lock_parent(hidden_dentry); + if (IS_ERR(hidden_parent_dentry)) { + err = PTR_ERR(hidden_parent_dentry); + goto out; + } + if (!(err = is_robranch_super(dentry->d_sb, bindex))) { + err = vfs_mknod(hidden_parent_dentry->d_inode, + hidden_dentry, NULL, mode, dev); + } + /* XXX this could potentially return a negative hidden_dentry! */ + if (err || !hidden_dentry->d_inode) { + unlock_dir(hidden_parent_dentry); + /* break out of for, if error was NOT -EROFS */ + if (!IS_COPYUP_ERR(err)) + break; + } else { + err = unionfs_interpose(dentry, dir->i_sb, 0); + if (!err) { + fist_copy_attr_timesizes(dir, + hidden_parent_dentry-> + d_inode); + /* update number of links on parent directory */ + dir->i_nlink = get_nlinks(dir); + } + unlock_dir(hidden_parent_dentry); + + break; + } + } + + out: + if (!dentry->d_inode) + d_drop(dentry); + + if (name) { + KFREE(name); + } + + print_dentry("OUT unionfs_mknod :", dentry); + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +int unionfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz) +{ + int err; + struct dentry *hidden_dentry; + + print_entry_location(); + lock_dentry(dentry); + hidden_dentry = dtohd(dentry); + print_dentry("unionfs_readlink IN", dentry); + + if (!hidden_dentry->d_inode->i_op || + !hidden_dentry->d_inode->i_op->readlink) { + err = -EINVAL; + goto out; + } + + err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry, + buf, bufsiz); + if (err > 0) + fist_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode); + + out: + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +/* We don't lock the dentry here, because readlink does the heavy lifting. */ +static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + char *buf; + int len = PAGE_SIZE, err; + mm_segment_t old_fs; + + print_entry_location(); + + /* This is freed by the put_link method assuming a successful call. */ + buf = (char *)KMALLOC(len, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto out; + } + + /* read the symlink, and then we will follow it */ + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); + set_fs(old_fs); + if (err < 0) { + KFREE(buf); + buf = NULL; + goto out; + } + buf[err] = 0; + nd_set_link(nd, buf); + err = 0; + + out: + print_exit_status(err); + return ERR_PTR(err); +} + +void unionfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) +{ + char *link; + print_entry_location(); + link = nd_get_link(nd); + KFREE(link); + print_exit_location(); +} + +/* Basically copied from the kernel vfs permission(), but we've changed + * the following: (1) the IS_RDONLY check is skipped, and (2) if you set + * the mount option `nfsperms=insceure', we assume that -EACCES means that + * the export is read-only and we should check standard Unix permissions. + * This means that NFS ACL checks (or other advanced permission features) + * are bypassed. + */ +static int unionfs_inode_permission(struct inode *inode, int mask, struct nameidata *nd, + int bindex) +{ + int retval, submask; + + if (mask & MAY_WRITE) { + /* The first branch is allowed to be really readonly. */ + if (bindex == 0) { + umode_t mode = inode->i_mode; + if (IS_RDONLY(inode) && (S_ISREG(mode) || S_ISDIR(mode) + || S_ISLNK(mode))) + return -EROFS; + } + /* + * Nobody gets write access to an immutable file. + */ + if (IS_IMMUTABLE(inode)) + return -EACCES; + } + + /* Ordinary permission routines do not understand MAY_APPEND. */ + submask = mask & ~MAY_APPEND; + if (inode->i_op && inode->i_op->permission) { + retval = inode->i_op->permission(inode, submask); + if ((retval == -EACCES) && (submask & MAY_WRITE) && + (!strcmp("nfs", (inode)->i_sb->s_type->name)) && + (nd) && (nd->path.mnt) && (nd->path.mnt->mnt_sb) && + (branchperms(nd->path.mnt->mnt_sb, bindex) & MAY_NFSRO)) { + retval = generic_permission(inode, submask, NULL); + } + } else { + retval = generic_permission(inode, submask, NULL); + } + + if (retval && retval != -EROFS) /* ignore EROFS */ + return retval; + + /* + * skip the LSM permission check. This means unionfs will wrongly + * copy up a LSM non-writable/non-readable file on a readonly branch + * to a read-write branch leading to odd behaviour. Until the mess + * of the LSM interface changes are resolved, there's nothing else + * that can be done. + * retval = security_inode_permission(inode, mask, nd); + */ + return ((retval == -EROFS) ? 0 : retval); /* ignore EROFS */ +} + +static int unionfs_permission(struct inode *inode, int mask) +{ + struct inode *hidden_inode = NULL; + int err = 0; + int bindex, bstart, bend; + const int is_file = !S_ISDIR(inode->i_mode); + const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ); + + print_entry_location(); + + bstart = ibstart(inode); + bend = ibend(inode); + + print_inode("IN unionfs_permission", inode); + + for (bindex = bstart; bindex <= bend; bindex++) { + hidden_inode = itohi_index(inode, bindex); + if (!hidden_inode) + continue; + + /* check the condition for D-F-D underlying files/directories, + * we dont have to check for files, if we are checking for + * directories. + */ + if (!is_file && !S_ISDIR(hidden_inode->i_mode)) + continue; + /* We use our own special version of permission, such that + * only the first branch returns -EROFS. */ + err = unionfs_inode_permission(hidden_inode, mask, NULL, bindex); + /* The permissions are an intersection of the overall directory + * permissions, so we fail if one fails. */ + if (err) + goto out; + /* only the leftmost file matters. */ + if (is_file || write_mask) { + if (is_file && write_mask) { + err = get_write_access(hidden_inode); + if (!err) + put_write_access(hidden_inode); + } + break; + } + } + + out: + print_exit_status(err); + return err; +} + +static int unionfs_setattr(struct dentry *dentry, struct iattr *ia) +{ + int err = 0; + struct dentry *hidden_dentry; + struct inode *inode = NULL; + struct inode *hidden_inode = NULL; + int bstart, bend, bindex; + int i; + int copyup = 0; + + print_entry_location(); + lock_dentry(dentry); + bstart = dbstart(dentry); + bend = dbend(dentry); + inode = dentry->d_inode; + + for (bindex = bstart; (bindex <= bend) || (bindex == bstart); bindex++) { + hidden_dentry = dtohd_index(dentry, bindex); + if (!hidden_dentry) + continue; + BUG_ON(hidden_dentry->d_inode == NULL); + + /* If the file is on a read only branch */ + if (is_robranch_super(dentry->d_sb, bindex) + || IS_RDONLY(hidden_dentry->d_inode)) { + if (copyup || (bindex != bstart)) + continue; + /* Only if its the leftmost file, copyup the file */ + for (i = bstart - 1; i >= 0; i--) { + loff_t size = dentry->d_inode->i_size; + if (ia->ia_valid & ATTR_SIZE) + size = ia->ia_size; + err = copyup_dentry(dentry->d_parent->d_inode, + dentry, bstart, i, NULL, + size); + + if (!err) { + copyup = 1; + hidden_dentry = dtohd(dentry); + break; + } + /* if error is in the leftmost f/s, pass it up */ + if (i == 0) + goto out; + } + + } + /* + * mode change is for clearing setuid/setgid bits. Allow lower fs + * to interpret this in its own way. + */ + if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) + ia->ia_valid &= ~ATTR_MODE; + + err = notify_change(hidden_dentry, NULL, ia); + if (err) + goto out; + break; + } +#ifdef UNIONFS_MMAP + /* + * SP: notify_change will change the lower file's size, + * but we need to truncate the page tables, so need to call + * vmtruncate() + */ + + if (ia->ia_valid & ATTR_SIZE) { + if (ia->ia_size != i_size_read(inode)) { + err = vmtruncate(inode, ia->ia_size); + if (err) { + printk("unionfs_setattr: vmtruncate failed\n"); + } + } + } +#endif + /* get the size from the first hidden inode */ + hidden_inode = itohi(dentry->d_inode); + checkinode(inode, "unionfs_setattr"); + fist_copy_attr_all(inode, hidden_inode); + + out: + unlock_dentry(dentry); + checkinode(inode, "post unionfs_setattr"); + print_exit_status(err); + return err; +} + +struct inode_operations unionfs_symlink_iops = { + .readlink = unionfs_readlink, + .permission = unionfs_permission, + .follow_link = unionfs_follow_link, + .setattr = unionfs_setattr, + .put_link = unionfs_put_link, +}; + +struct inode_operations unionfs_dir_iops = { + .create = unionfs_create, + .lookup = unionfs_lookup, + .link = unionfs_link, + .unlink = unionfs_unlink, + .symlink = unionfs_symlink, + .mkdir = unionfs_mkdir, + .rmdir = unionfs_rmdir, + .mknod = unionfs_mknod, + .rename = unionfs_rename, + .permission = unionfs_permission, + .setattr = unionfs_setattr, + .setxattr = unionfs_setxattr, + .getxattr = unionfs_getxattr, + .removexattr = unionfs_removexattr, + .listxattr = unionfs_listxattr, +}; + +struct inode_operations unionfs_main_iops = { + .permission = unionfs_permission, + .setattr = unionfs_setattr, + .setxattr = unionfs_setxattr, + .getxattr = unionfs_getxattr, + .removexattr = unionfs_removexattr, + .listxattr = unionfs_listxattr, +}; + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/sioq.c +++ linux-2.6.27/ubuntu/unionfs/sioq.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2004-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ + +#include "unionfs.h" + +struct workqueue_struct *sioq; + +int __init init_sioq(void) +{ + int err; + + sioq = create_workqueue("unionfs_siod"); + if (!IS_ERR(sioq)) + return 0; + + err = PTR_ERR(sioq); + printk(KERN_ERR "create_workqueue failed %d\n", err); + sioq = NULL; + return err; +} + +void fin_sioq(void) +{ + if (sioq) + destroy_workqueue(sioq); +} + +void run_sioq(work_func_t func, struct sioq_args *args) +{ + INIT_WORK(&args->wk, func); + + init_completion(&args->comp); + while (!queue_work(sioq, &args->wk)) { + // TODO: do accounting if needed + schedule(); + } + wait_for_completion(&args->comp); +} + +void __unionfs_create(struct work_struct *work) +{ + struct sioq_args *args = container_of(work, struct sioq_args, wk); + struct create_args *c = &args->create; + args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd); + complete(&args->comp); +} + +void __unionfs_mkdir(struct work_struct *work) +{ + struct sioq_args *args = container_of(work, struct sioq_args, wk); + struct mkdir_args *m = &args->mkdir; + args->err = vfs_mkdir(m->parent, m->dentry, NULL, m->mode); + complete(&args->comp); +} + +void __unionfs_mknod(struct work_struct *work) +{ + struct sioq_args *args = container_of(work, struct sioq_args, wk); + struct mknod_args *m = &args->mknod; + args->err = vfs_mknod(m->parent, m->dentry, NULL, m->mode, m->dev); + complete(&args->comp); +} +void __unionfs_symlink(struct work_struct *work) +{ + struct sioq_args *args = container_of(work, struct sioq_args, wk); + struct symlink_args *s = &args->symlink; + args->err = vfs_symlink(s->parent, s->dentry, NULL, s->symbuf); + complete(&args->comp); +} + +void __unionfs_unlink(struct work_struct *work) +{ + struct sioq_args *args = container_of(work, struct sioq_args, wk); + struct unlink_args *u = &args->unlink; + args->err = vfs_unlink(u->parent, u->dentry, NULL); + complete(&args->comp); +} + +void __delete_whiteouts(struct work_struct *work) { + struct sioq_args *args = container_of(work, struct sioq_args, wk); + struct deletewh_args *d = &args->deletewh; + args->err = delete_whiteouts(d->dentry, d->bindex, d->namelist); + complete(&args->comp); +} + +void __is_opaque_dir(struct work_struct *work) +{ + struct sioq_args *args = container_of(work, struct sioq_args, wk); + + args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->isopaque.dentry, + sizeof(UNIONFS_DIR_OPAQUE) - 1); + complete(&args->comp); +} --- linux-2.6.27.orig/ubuntu/unionfs/dirfops.c +++ linux-2.6.27/ubuntu/unionfs/dirfops.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: dirfops.c,v 1.25 2006/08/05 01:28:46 jro Exp $ + */ + +#include "unionfs.h" + +/* Make sure our rdstate is playing by the rules. */ +static void verify_rdstate_offset(struct unionfs_dir_state *rdstate) +{ + BUG_ON(rdstate->uds_offset >= DIREOF); + BUG_ON(rdstate->uds_cookie >= MAXRDCOOKIE); +} + +struct unionfs_getdents_callback { + struct unionfs_dir_state *rdstate; + void *dirent; + int entries_written; + int filldir_called; + int filldir_error; + filldir_t filldir; + struct super_block *sb; +}; + +/* copied from generic filldir in fs/readir.c */ +static int unionfs_filldir(void *dirent, const char *name, int namelen, + loff_t offset, u64 ino, unsigned int d_type) +{ + struct unionfs_getdents_callback *buf = + (struct unionfs_getdents_callback *)dirent; + struct filldir_node *found = NULL; + int err = 0; + int is_wh_entry = 0; + + dprint(PRINT_DEBUG, "unionfs_filldir name=%*s\n", namelen, name); + + buf->filldir_called++; + + if ((namelen > WHLEN) && !strncmp(name, WHPFX, WHLEN)) { + name += WHLEN; + namelen -= WHLEN; + is_wh_entry = 1; + } + + found = find_filldir_node(buf->rdstate, name, namelen); + + if (found) + goto out; + + /* if 'name' isn't a whiteout filldir it. */ + if (!is_wh_entry) { + off_t pos = rdstate2offset(buf->rdstate); + ino_t unionfs_ino = ino; +#ifdef UNIONFS_IMAP + if (stopd(buf->sb)->usi_persistent) + err = read_uin(buf->sb, buf->rdstate->uds_bindex, + ino, O_CREAT, &unionfs_ino); +#endif + if (!err) { + err = buf->filldir(buf->dirent, name, namelen, pos, + unionfs_ino, d_type); + buf->rdstate->uds_offset++; + verify_rdstate_offset(buf->rdstate); + } + } + /* If we did fill it, stuff it in our hash, otherwise return an error */ + if (err) { + buf->filldir_error = err; + goto out; + } + buf->entries_written++; + if ((err = add_filldir_node(buf->rdstate, name, namelen, + buf->rdstate->uds_bindex, is_wh_entry))) + buf->filldir_error = err; + + out: + return err; +} + +static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + int err = 0; + struct file *hidden_file = NULL; + struct inode *inode = NULL; + struct unionfs_getdents_callback buf; + struct unionfs_dir_state *uds; + int bend; + loff_t offset; + + print_entry("file = %p, pos = %llx", file, file->f_pos); + + print_file("In unionfs_readdir()", file); + + if ((err = unionfs_file_revalidate(file, 0))) + goto out; + + inode = file->f_dentry->d_inode; + checkinode(inode, "unionfs_readdir"); + + uds = ftopd(file)->rdstate; + if (!uds) { + if (file->f_pos == DIREOF) { + goto out; + } else if (file->f_pos > 0) { + uds = find_rdstate(inode, file->f_pos); + if (!uds) { + err = -ESTALE; + goto out; + } + ftopd(file)->rdstate = uds; + } else { + init_rdstate(file); + uds = ftopd(file)->rdstate; + } + } + bend = fbend(file); + + while (uds->uds_bindex <= bend) { + hidden_file = ftohf_index(file, uds->uds_bindex); + if (!hidden_file) { + dprint(PRINT_DEBUG, + "Incremented bindex to %d of %d," + " because hidden file is NULL.\n", + uds->uds_bindex, bend); + uds->uds_bindex++; + uds->uds_dirpos = 0; + continue; + } + + /* prepare callback buffer */ + buf.filldir_called = 0; + buf.filldir_error = 0; + buf.entries_written = 0; + buf.dirent = dirent; + buf.filldir = filldir; + buf.rdstate = uds; + buf.sb = inode->i_sb; + + /* Read starting from where we last left off. */ + offset = vfs_llseek(hidden_file, uds->uds_dirpos, 0); + if (offset < 0) { + err = offset; + goto out; + } + dprint(PRINT_DEBUG, "calling readdir for %d.%lld (offset = %lld)\n", + uds->uds_bindex, uds->uds_dirpos, offset); + err = vfs_readdir(hidden_file, unionfs_filldir, (void *)&buf); + dprint(PRINT_DEBUG, + "readdir on %d.%lld = %d (entries written %d, filldir called %d)\n", + uds->uds_bindex, (long long)uds->uds_dirpos, err, + buf.entries_written, buf.filldir_called); + /* Save the position for when we continue. */ + + offset = vfs_llseek(hidden_file, 0, 1); + if (offset < 0) { + err = offset; + goto out; + } + uds->uds_dirpos = offset; + + /* Copy the atime. */ + fist_copy_attr_atime(inode, hidden_file->f_dentry->d_inode); + + if (err < 0) { + goto out; + } + + if (buf.filldir_error) { + break; + } + + if (!buf.entries_written) { + uds->uds_bindex++; + uds->uds_dirpos = 0; + } + } + + if (!buf.filldir_error && uds->uds_bindex >= bend) { + dprint(PRINT_DEBUG, + "Discarding rdstate because readdir is over (hashsize = %d)\n", + uds->uds_hashentries); + /* Save the number of hash entries for next time. */ + itopd(inode)->uii_hashsize = uds->uds_hashentries; + free_rdstate(uds); + ftopd(file)->rdstate = NULL; + file->f_pos = DIREOF; + } else { + file->f_pos = rdstate2offset(uds); + dprint(PRINT_DEBUG, "rdstate now has a cookie of %u (err = %d)\n", + uds->uds_cookie, err); + } + + out: + checkinode(inode, "post unionfs_readdir"); + print_exit_status(err); + return err; +} + +/* This is not meant to be a generic repositioning function. If you do + * things that aren't supported, then we return EINVAL. + * + * What is allowed: + * (1) seeking to the same position that you are currently at + * This really has no effect, but returns where you are. + * (2) seeking to the end of the file, if you've read everything + * This really has no effect, but returns where you are. + * (3) seeking to the beginning of the file + * This throws out all state, and lets you begin again. + */ +static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin) +{ + struct unionfs_dir_state *rdstate; + loff_t err; + + print_entry(" file=%p, offset=0x%llx, origin = %d", file, offset, + origin); + + if ((err = unionfs_file_revalidate(file, 0))) + goto out; + + rdstate = ftopd(file)->rdstate; + + /* We let users seek to their current position, but not anywhere else. */ + if (!offset) { + switch (origin) { + case SEEK_SET: + if (rdstate) { + free_rdstate(rdstate); + ftopd(file)->rdstate = NULL; + } + init_rdstate(file); + err = 0; + break; + case SEEK_CUR: + if (file->f_pos) { + if (file->f_pos == DIREOF) + err = DIREOF; + else + BUG_ON(file->f_pos != + rdstate2offset(rdstate)); + err = file->f_pos; + } else { + err = 0; + } + break; + case SEEK_END: + /* Unsupported, because we would break everything. */ + err = -EINVAL; + break; + } + } else { + switch (origin) { + case SEEK_SET: + if (rdstate) { + if (offset == rdstate2offset(rdstate)) { + err = offset; + } else if (file->f_pos == DIREOF) { + err = DIREOF; + } else { + err = -EINVAL; + } + } else { + if ((rdstate = + find_rdstate(file->f_dentry->d_inode, + offset))) { + ftopd(file)->rdstate = rdstate; + err = rdstate->uds_offset; + } else { + err = -EINVAL; + } + } + break; + case SEEK_CUR: + case SEEK_END: + /* Unsupported, because we would break everything. */ + err = -EINVAL; + break; + } + } + + out: + print_exit_status((int)err); + return err; +} + +/* Trimmed directory options, we shouldn't pass everything down since + * we don't want to operate on partial directories. + */ +struct file_operations unionfs_dir_fops = { + .llseek = unionfs_dir_llseek, + .read = generic_read_dir, + .readdir = unionfs_readdir, + .unlocked_ioctl = unionfs_ioctl, + .open = unionfs_open, + .release = unionfs_file_release, + .flush = unionfs_flush, +}; + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/unionfs_macros.h +++ linux-2.6.27/ubuntu/unionfs/unionfs_macros.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef Sipek + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: unionfs_macros.h,v 1.13 2006/06/01 03:11:03 jsipek Exp $ + */ + +#ifndef __UNIONFS_H_ +#error This file should only be included from unionfs.h! +#endif + +/* Inode to private data */ +static inline struct unionfs_inode_info *itopd(const struct inode *inode) +{ + return + &(container_of(inode, struct unionfs_inode_container, vfs_inode)-> + info); +} + +#define itohi_ptr(ino) (itopd(ino)->uii_inode) +#define ibstart(ino) (itopd(ino)->b_start) +#define ibend(ino) (itopd(ino)->b_end) + +/* Superblock to private data */ +#define stopd(super) ((struct unionfs_sb_info *)(super)->s_fs_info) +#define stopd_lhs(super) ((super)->s_fs_info) +#define sbstart(sb) 0 +#define sbend(sb) stopd(sb)->b_end +#define sbmax(sb) (stopd(sb)->b_end + 1) + +/* File to private Data */ +#define ftopd(file) ((struct unionfs_file_info *)((file)->private_data)) +#define ftopd_lhs(file) ((file)->private_data) +#define ftohf_ptr(file) (ftopd(file)->ufi_file) +#define fbstart(file) (ftopd(file)->b_start) +#define fbend(file) (ftopd(file)->b_end) + +/* File to hidden file. */ +static inline struct file *ftohf(struct file *f) +{ + return ftopd(f)->ufi_file[fbstart(f)]; +} + +static inline struct file *ftohf_index(const struct file *f, int index) +{ + return ftopd(f)->ufi_file[index]; +} + +static inline void set_ftohf_index(struct file *f, int index, struct file *val) +{ + ftopd(f)->ufi_file[index] = val; +} + +static inline void set_ftohf(struct file *f, struct file *val) +{ + ftopd(f)->ufi_file[fbstart(f)] = val; +} + +/* Inode to hidden inode. */ +static inline struct inode *itohi(const struct inode *i) +{ + return itopd(i)->uii_inode[ibstart(i)]; +} + +static inline struct inode *itohi_index(const struct inode *i, int index) +{ + return itopd(i)->uii_inode[index]; +} + +static inline void set_itohi_index(struct inode *i, int index, + struct inode *val) +{ + itopd(i)->uii_inode[index] = val; +} + +static inline void set_itohi(struct inode *i, struct inode *val) +{ + itopd(i)->uii_inode[ibstart(i)] = val; +} + +/* Superblock to hidden superblock. */ +static inline struct super_block *stohs(const struct super_block *o) +{ + return stopd(o)->usi_data[sbstart(o)].sb; +} + +static inline struct super_block *stohs_index(const struct super_block *o, int index) +{ + return stopd(o)->usi_data[index].sb; +} + +static inline void set_stohs_index(struct super_block *o, int index, + struct super_block *val) +{ + stopd(o)->usi_data[index].sb = val; +} + +static inline void set_stohs(struct super_block *o, struct super_block *val) +{ + stopd(o)->usi_data[sbstart(o)].sb = val; +} + +/* Super to hidden mount. */ +static inline struct vfsmount *stohiddenmnt_index(struct super_block *o, + int index) +{ + return stopd(o)->usi_data[index].hidden_mnt; +} + +static inline void set_stohiddenmnt_index(struct super_block *o, int index, + struct vfsmount *val) +{ + stopd(o)->usi_data[index].hidden_mnt = val; +} + +/* Branch count macros. */ +static inline int branch_count(struct super_block *o, int index) +{ + return atomic_read(&stopd(o)->usi_data[index].sbcount); +} + +static inline void set_branch_count(struct super_block *o, int index, int val) +{ + atomic_set(&stopd(o)->usi_data[index].sbcount, val); +} + +static inline void branchget(struct super_block *o, int index) +{ + atomic_inc(&stopd(o)->usi_data[index].sbcount); +} + +static inline void branchput(struct super_block *o, int index) +{ + atomic_dec(&stopd(o)->usi_data[index].sbcount); +} + +/* Dentry macros */ +static inline struct unionfs_dentry_info *dtopd(const struct dentry *dent) +{ + return (struct unionfs_dentry_info *)dent->d_fsdata; +} + +#define dtopd_lhs(dent) ((dent)->d_fsdata) +#define dtopd_nocheck(dent) dtopd(dent) +#define dbstart(dent) (dtopd(dent)->udi_bstart) +#define set_dbstart(dent, val) do { dtopd(dent)->udi_bstart = val; } while(0) +#define dbend(dent) (dtopd(dent)->udi_bend) +#define set_dbend(dent, val) do { dtopd(dent)->udi_bend = val; } while(0) +#define dbopaque(dent) (dtopd(dent)->udi_bopaque) +#define set_dbopaque(dent, val) do { dtopd(dent)->udi_bopaque = val; } while (0) + +static inline void set_dtohd_index(struct dentry *dent, int index, + struct dentry *val) +{ + dtopd(dent)->udi_dentry[index] = val; +} + +static inline struct dentry *dtohd_index(const struct dentry *dent, int index) +{ + return dtopd(dent)->udi_dentry[index]; +} + +static inline struct dentry *dtohd(const struct dentry *dent) +{ + return dtopd(dent)->udi_dentry[dbstart(dent)]; +} + +#define set_dtohd_index_nocheck(dent, index, val) set_dtohd_index(dent, index, val) +#define dtohd_index_nocheck(dent, index) dtohd_index(dent, index) + +#define dtohd_ptr(dent) (dtopd_nocheck(dent)->udi_dentry) + +/* Macros for locking a dentry. */ +#define lock_dentry(d) down(&dtopd(d)->udi_sem) +#define unlock_dentry(d) up(&dtopd(d)->udi_sem) +#define verify_locked(d) + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/copyup.c +++ linux-2.6.27/ubuntu/unionfs/copyup.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York* + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: copyup.c,v 1.78 2006/10/31 18:05:33 yiannos Exp $ + */ + +#include "unionfs.h" + +/*Not Working Yet*/ +static int copyup_xattrs(struct dentry *old_hidden_dentry, + struct dentry *new_hidden_dentry) +{ + int err = 0; + ssize_t list_size = -1; + char *name_list = NULL; + char *attr_value = NULL; + char *name_list_orig = NULL; + + print_entry_location(); + + list_size = vfs_listxattr(old_hidden_dentry, NULL, NULL, 0, NULL); + + if (list_size <= 0) { + err = list_size; + goto out; + } + + name_list = xattr_alloc(list_size + 1, XATTR_LIST_MAX); + if (!name_list || IS_ERR(name_list)) { + err = PTR_ERR(name_list); + goto out; + } + list_size = vfs_listxattr(old_hidden_dentry, NULL, name_list, + list_size, NULL); + attr_value = xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX); + if (!attr_value || IS_ERR(attr_value)) { + err = PTR_ERR(name_list); + goto out; + } + name_list_orig = name_list; + while (*name_list) { + ssize_t size; + + //We need to lock here since vfs_getxattr doesn't lock for us. + mutex_lock(&old_hidden_dentry->d_inode->i_mutex); + size = vfs_getxattr(old_hidden_dentry, NULL, name_list, + attr_value, XATTR_SIZE_MAX, NULL); + mutex_unlock(&old_hidden_dentry->d_inode->i_mutex); + if (size < 0) { + err = size; + goto out; + } + + if (size > XATTR_SIZE_MAX) { + err = -E2BIG; + goto out; + } + //We don't need to lock here since vfs_setxattr does it for us. + err = vfs_setxattr(new_hidden_dentry, NULL, name_list, + attr_value, size, 0, NULL); + + if (err < 0) + goto out; + name_list += strlen(name_list) + 1; + } + out: + name_list = name_list_orig; + + if (name_list) + xattr_free(name_list, list_size + 1); + if (attr_value) + xattr_free(attr_value, XATTR_SIZE_MAX); + /* It is no big deal if this fails, we just roll with the punches. */ + if (err == -ENOTSUPP || err == -EOPNOTSUPP) + err = 0; + return err; +} + +/* Determine the mode based on the copyup flags, and the existing dentry. */ +static int copyup_permissions(struct super_block *sb, + struct dentry *old_hidden_dentry, + struct dentry *new_hidden_dentry) +{ + struct iattr newattrs; + int err; + + print_entry_location(); + + newattrs.ia_atime = old_hidden_dentry->d_inode->i_atime; + newattrs.ia_mtime = old_hidden_dentry->d_inode->i_mtime; + newattrs.ia_ctime = old_hidden_dentry->d_inode->i_ctime; + newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME | + ATTR_ATIME_SET | ATTR_MTIME_SET; + /* original mode of old file */ + newattrs.ia_mode = old_hidden_dentry->d_inode->i_mode; + newattrs.ia_gid = old_hidden_dentry->d_inode->i_gid; + newattrs.ia_uid = old_hidden_dentry->d_inode->i_uid; + newattrs.ia_valid |= ATTR_FORCE | ATTR_GID | ATTR_UID | ATTR_MODE; + if (newattrs.ia_valid & ATTR_MODE) { + newattrs.ia_mode = + (newattrs.ia_mode & S_IALLUGO) | (old_hidden_dentry-> + d_inode-> + i_mode & ~S_IALLUGO); + } + + err = notify_change(new_hidden_dentry, NULL, &newattrs); + + print_exit_status(err); + return err; +} + +int copyup_dentry(struct inode *dir, struct dentry *dentry, + int bstart, int new_bindex, + struct file **copyup_file, loff_t len) +{ + return copyup_named_dentry(dir, dentry, bstart, new_bindex, + dentry->d_name.name, + dentry->d_name.len, copyup_file, len); +} + +int copyup_named_dentry(struct inode *dir, struct dentry *dentry, + int bstart, int new_bindex, const char *name, + int namelen, struct file **copyup_file, loff_t len) +{ + struct dentry *new_hidden_dentry; + struct dentry *old_hidden_dentry = NULL; + struct super_block *sb; + struct file *input_file = NULL; + struct file *output_file = NULL; + struct sioq_args args; + ssize_t read_bytes, write_bytes; + mm_segment_t old_fs; + int err = 0; + char *buf; + int old_bindex; + int got_branch_input = -1; + int got_branch_output = -1; + int old_bstart; + int old_bend; + int old_mode; + loff_t size = len; + struct dentry *new_hidden_parent_dentry = NULL; + mm_segment_t oldfs; + char *symbuf = NULL; + + print_entry_location(); + verify_locked(dentry); + print_dentry("IN: copyup_named_dentry", dentry); + + old_bindex = bstart; + old_bstart = dbstart(dentry); + old_bend = dbend(dentry); + + BUG_ON(new_bindex < 0); + BUG_ON(new_bindex >= old_bindex); + + sb = dir->i_sb; + + unionfs_read_lock(sb); + + if ((err = is_robranch_super(sb, new_bindex))) + goto out; + + /* Create the directory structure above this dentry. */ + new_hidden_dentry = create_parents_named(dir, dentry, name, new_bindex); + if (IS_ERR(new_hidden_dentry)) { + err = PTR_ERR(new_hidden_dentry); + goto out; + } + + print_dentry("Copyup Object", new_hidden_dentry); + + /* Now we actually create the object. */ + old_hidden_dentry = dtohd_index(dentry, old_bindex); + DGET(old_hidden_dentry); + + old_mode = old_hidden_dentry->d_inode->i_mode; + + /* For symlinks, we must read the link before we lock the directory. */ + if (S_ISLNK(old_mode)) { + + symbuf = KMALLOC(PATH_MAX, GFP_KERNEL); + if (!symbuf) { + err = -ENOMEM; + goto copyup_readlink_err; + } + + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = + old_hidden_dentry->d_inode->i_op-> + readlink(old_hidden_dentry, (char __user *)symbuf, + PATH_MAX); + set_fs(oldfs); + if (err < 0) + goto copyup_readlink_err; + symbuf[err] = '\0'; + } + + /* Now we lock the parent, and create the object in the new branch. */ + new_hidden_parent_dentry = lock_parent(new_hidden_dentry); + if (S_ISDIR(old_mode)) { + args.mkdir.parent = new_hidden_parent_dentry->d_inode; + args.mkdir.dentry = new_hidden_dentry; + args.mkdir.mode = old_mode; /*S_IRWXU*/ + run_sioq(__unionfs_mkdir, &args); + err = args.err; + } else if (S_ISLNK(old_mode)) { + args.symlink.parent = new_hidden_parent_dentry->d_inode; + args.symlink.dentry = new_hidden_dentry; + args.symlink.symbuf = symbuf; + args.symlink.mode = old_mode; + run_sioq(__unionfs_symlink, &args); + err = args.err; + } else if (S_ISBLK(old_mode) + || S_ISCHR(old_mode) + || S_ISFIFO(old_mode) + || S_ISSOCK(old_mode)) { + args.mknod.parent = new_hidden_parent_dentry->d_inode; + args.mknod.dentry = new_hidden_dentry; + args.mknod.mode = old_mode; + args.mknod.dev = old_hidden_dentry->d_inode->i_rdev; + run_sioq(__unionfs_mknod, &args); + err = args.err; + } else if (S_ISREG(old_mode)) { + args.create.parent = new_hidden_parent_dentry->d_inode; + args.create.dentry = new_hidden_dentry; + args.create.mode = old_mode; + args.create.nd = NULL; + run_sioq(__unionfs_create, &args); + err = args.err; + } else { + printk(KERN_ERR "Unknown inode type %d\n", + old_hidden_dentry->d_inode->i_mode); + BUG(); + } + + copyup_readlink_err: + KFREE(symbuf); + if (err) { + /* get rid of the hidden dentry and all its traces */ + DPUT(new_hidden_dentry); + set_dtohd_index(dentry, new_bindex, NULL); + set_dbstart(dentry, old_bstart); + set_dbend(dentry, old_bend); + goto out_dir; + } +#ifdef UNIONFS_IMAP + if (stopd(sb)->usi_persistent) { + err = write_uin(dentry->d_sb, dentry->d_inode->i_ino, + new_bindex, new_hidden_dentry->d_inode->i_ino); + if (err) + goto out_dir; + } +#endif + /* We actually copyup the file here. */ + if (S_ISREG(old_hidden_dentry->d_inode->i_mode)) { + mntget(stohiddenmnt_index(sb, old_bindex)); + branchget(sb, old_bindex); + got_branch_input = old_bindex; + input_file = + DENTRY_OPEN(old_hidden_dentry, + stohiddenmnt_index(sb, old_bindex), + O_RDONLY | O_LARGEFILE); + if (IS_ERR(input_file)) { + err = PTR_ERR(input_file); + goto out_dir; + } + if (!input_file->f_op || !input_file->f_op->read) { + err = -EINVAL; + goto out_dir; + } + + /* copy the new file */ + DGET(new_hidden_dentry); + mntget(stohiddenmnt_index(sb, new_bindex)); + branchget(sb, new_bindex); + got_branch_output = new_bindex; + output_file = + DENTRY_OPEN(new_hidden_dentry, + stohiddenmnt_index(sb, new_bindex), + O_WRONLY | O_LARGEFILE); + if (IS_ERR(output_file)) { + err = PTR_ERR(output_file); + goto out_dir; + } + if (!output_file->f_op || !output_file->f_op->write) { + err = -EINVAL; + goto out_dir; + } + + /* allocating a buffer */ + buf = (char *)KMALLOC(PAGE_SIZE, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto out_dir; + } + + /* now read PAGE_SIZE bytes from offset 0 in a loop */ + old_fs = get_fs(); + + input_file->f_pos = 0; + output_file->f_pos = 0; + + err = 0; // reset error just in case + set_fs(KERNEL_DS); + do { + if (len >= PAGE_SIZE) + size = PAGE_SIZE; + else if ((len < PAGE_SIZE) && (len > 0)) + size = len; + + len -= PAGE_SIZE; + + read_bytes = + input_file->f_op->read(input_file, + (char __user *)buf, size, + &input_file->f_pos); + if (read_bytes <= 0) { + err = read_bytes; + break; + } + + write_bytes = + output_file->f_op->write(output_file, + (char __user *)buf, + read_bytes, + &output_file->f_pos); + if (write_bytes < 0 || (write_bytes < read_bytes)) { + err = write_bytes; + break; + } + } while ((read_bytes > 0) && (len > 0)); + set_fs(old_fs); + KFREE(buf); +#ifdef UNIONFS_MMAP + /* SP: Now that we copied up the file, have to sync its data + * as otherwise when we do a read_cache_page(), we'll possibly + * read crap. + * + * another posisble solution would be in the address op code + * would be to check the "lower" page to see if its dirty, + * and if it's dirty, use it directl + */ + if (!err) { + err = + output_file->f_op->fsync(output_file, + new_hidden_dentry, 0); + } +#endif + if (err) { + /* copyup failed, because we ran out of space or quota, + * or something else happened so let's unlink; we don't + * really care about the return value of vfs_unlink */ + vfs_unlink(new_hidden_parent_dentry->d_inode, + new_hidden_dentry, NULL); + + goto out_dir; + } + } + + /* Set permissions. */ + if ((err = + copyup_permissions(sb, old_hidden_dentry, new_hidden_dentry))) + goto out_dir; + /* Selinux uses extended attributes for permissions. */ + if ((err = copyup_xattrs(old_hidden_dentry, new_hidden_dentry))) + goto out_dir; + + /* do not allow files getting deleted to be reinterposed */ + if (!d_deleted(dentry)) + unionfs_reinterpose(dentry); + + out_dir: + if (new_hidden_parent_dentry) + unlock_dir(new_hidden_parent_dentry); + + out: + if (input_file && !IS_ERR(input_file)) { + fput(input_file); + } else { + /* since input file was not opened, we need to explicitly + * dput the old_hidden_dentry + */ + DPUT(old_hidden_dentry); + } + + /* in any case, we have to branchput */ + if (got_branch_input >= 0) + branchput(sb, got_branch_input); + + if (output_file) { + if (copyup_file && !err) { + *copyup_file = output_file; + } else { + /* close the file if there was no error, or if we ran + * out of space in which case we unlinked the file */ + if (!IS_ERR(output_file)) + fput(output_file); + branchput(sb, got_branch_output); + } + } + + unionfs_read_unlock(sb); + + print_dentry("OUT: copyup_dentry", dentry); + print_inode("OUT: copyup_dentry", dentry->d_inode); + + print_exit_status(err); + return err; +} + +/* This function creates a copy of a file represented by 'file' which currently + * resides in branch 'bstart' to branch 'new_bindex. The copy will be named + * "name". */ +int copyup_named_file(struct inode *dir, struct file *file, char *name, + int bstart, int new_bindex, loff_t len) +{ + int err = 0; + struct file *output_file = NULL; + + print_entry_location(); + + err = copyup_named_dentry(dir, file->f_dentry, bstart, + new_bindex, name, strlen(name), &output_file, + len); + if (!err) { + fbstart(file) = new_bindex; + set_ftohf_index(file, new_bindex, output_file); + } + + print_exit_status(err); + return err; +} + +/* This function creates a copy of a file represented by 'file' which currently + * resides in branch 'bstart' to branch 'new_bindex. + */ +int copyup_file(struct inode *dir, struct file *file, int bstart, + int new_bindex, loff_t len) +{ + int err = 0; + struct file *output_file = NULL; + + print_entry_location(); + + err = copyup_dentry(dir, file->f_dentry, bstart, new_bindex, + &output_file, len); + if (!err) { + fbstart(file) = new_bindex; + set_ftohf_index(file, new_bindex, output_file); + } + + print_exit_status(err); + return err; +} + +/* This function replicates the directory structure upto given dentry + * in the bindex branch. Can create directory structure recursively to the right + * also. + */ +struct dentry *create_parents(struct inode *dir, struct dentry *dentry, + int bindex) +{ + struct dentry *hidden_dentry; + + print_entry_location(); + hidden_dentry = + create_parents_named(dir, dentry, dentry->d_name.name, bindex); + print_exit_location(); + + return (hidden_dentry); +} + +/* This function replicates the directory structure upto given dentry + * in the bindex branch. */ +struct dentry *create_parents_named(struct inode *dir, struct dentry *dentry, + const char *name, int bindex) +{ + int err; + struct dentry *child_dentry; + struct dentry *parent_dentry; + struct dentry *hidden_parent_dentry = NULL; + struct dentry *hidden_dentry = NULL; + struct sioq_args args; + const char *childname; + unsigned int childnamelen; + + int old_kmalloc_size; + int kmalloc_size; + int num_dentry; + int count; + + int old_bstart; + int old_bend; + struct dentry **path = NULL; + struct dentry **tmp_path; + struct super_block *sb; +#ifdef UNIONFS_IMAP + int persistent; +#endif + print_entry_location(); + + verify_locked(dentry); + + /* There is no sense allocating any less than the minimum. */ + kmalloc_size = 128; + num_dentry = kmalloc_size / sizeof(struct dentry *); + + if ((err = is_robranch_super(dir->i_sb, bindex))) { + hidden_dentry = ERR_PTR(err); + goto out; + } + + print_dentry("IN: create_parents_named", dentry); + dprint(PRINT_DEBUG, "name = %s\n", name); + + old_bstart = dbstart(dentry); + old_bend = dbend(dentry); + + hidden_dentry = ERR_PTR(-ENOMEM); + path = (struct dentry **)KZALLOC(kmalloc_size, GFP_KERNEL); + if (!path) + goto out; + + /* assume the negative dentry of unionfs as the parent dentry */ + parent_dentry = dentry; + + count = 0; + /* This loop finds the first parent that exists in the given branch. + * We start building the directory structure from there. At the end + * of the loop, the following should hold: + * child_dentry is the first nonexistent child + * parent_dentry is the first existent parent + * path[0] is the = deepest child + * path[count] is the first child to create + */ + do { + child_dentry = parent_dentry; + + /* find the parent directory dentry in unionfs */ + parent_dentry = child_dentry->d_parent; + lock_dentry(parent_dentry); + + /* find out the hidden_parent_dentry in the given branch */ + hidden_parent_dentry = dtohd_index(parent_dentry, bindex); + + /* store the child dentry */ + path[count++] = child_dentry; + if (count == num_dentry) { + old_kmalloc_size = kmalloc_size; + kmalloc_size *= 2; + num_dentry = kmalloc_size / sizeof(struct dentry *); + + tmp_path = + (struct dentry **)KZALLOC(kmalloc_size, GFP_KERNEL); + if (!tmp_path) { + hidden_dentry = ERR_PTR(-ENOMEM); + goto out; + } + memcpy(tmp_path, path, old_kmalloc_size); + KFREE(path); + path = tmp_path; + tmp_path = NULL; + } + + } while (!hidden_parent_dentry); + count--; + + sb = dentry->d_sb; +#ifdef UNIONFS_IMAP + persistent = stopd(sb)->usi_persistent; +#endif + /* This is basically while(child_dentry != dentry). This loop is + * horrible to follow and should be replaced with cleaner code. */ + while (1) { + // get hidden parent dir in the current branch + hidden_parent_dentry = dtohd_index(parent_dentry, bindex); + unlock_dentry(parent_dentry); + + // init the values to lookup + childname = child_dentry->d_name.name; + childnamelen = child_dentry->d_name.len; + + if (child_dentry != dentry) { + // lookup child in the underlying file system + hidden_dentry = + LOOKUP_ONE_LEN(childname, hidden_parent_dentry, + childnamelen); + if (IS_ERR(hidden_dentry)) + goto out; + } else { + int loop_start; + int loop_end; + int new_bstart = -1; + int new_bend = -1; + int i; + + /* is the name a whiteout of the childname ? */ + //lookup the whiteout child in the underlying file system + hidden_dentry = + LOOKUP_ONE_LEN(name, hidden_parent_dentry, + strlen(name)); + if (IS_ERR(hidden_dentry)) + goto out; + + /* Replace the current dentry (if any) with the new one. */ + DPUT(dtohd_index(dentry, bindex)); + set_dtohd_index(dentry, bindex, hidden_dentry); + + loop_start = + (old_bstart < bindex) ? old_bstart : bindex; + loop_end = (old_bend > bindex) ? old_bend : bindex; + + /* This loop sets the bstart and bend for the new + * dentry by traversing from left to right. + * It also dputs all negative dentries except + * bindex (the newly looked dentry + */ + for (i = loop_start; i <= loop_end; i++) { + if (!dtohd_index(dentry, i)) + continue; + + if (i == bindex) { + new_bend = i; + if (new_bstart < 0) + new_bstart = i; + continue; + } + + if (!dtohd_index(dentry, i)->d_inode) { + DPUT(dtohd_index(dentry, i)); + set_dtohd_index(dentry, i, NULL); + } else { + if (new_bstart < 0) + new_bstart = i; + new_bend = i; + } + } + + if (new_bstart < 0) + new_bstart = bindex; + if (new_bend < 0) + new_bend = bindex; + set_dbstart(dentry, new_bstart); + set_dbend(dentry, new_bend); + break; + } + + if (hidden_dentry->d_inode) { + /* since this already exists we dput to avoid + * multiple references on the same dentry */ + DPUT(hidden_dentry); + } else { + + /* its a negative dentry, create a new dir */ + hidden_parent_dentry = lock_parent(hidden_dentry); + args.mkdir.parent = hidden_parent_dentry->d_inode; + args.mkdir.dentry = hidden_dentry; + args.mkdir.mode = child_dentry->d_inode->i_mode; + run_sioq(__unionfs_mkdir, &args); + err = args.err; + if (!err) + err = copyup_permissions + (dir->i_sb, child_dentry, hidden_dentry); + unlock_dir(hidden_parent_dentry); + if (err) { + DPUT(hidden_dentry); + hidden_dentry = ERR_PTR(err); + goto out; + } +#ifdef UNIONFS_IMAP + if (persistent) { + err = write_uin + (sb, child_dentry->d_inode->i_ino, + bindex, hidden_dentry->d_inode->i_ino); + if (err) { + DPUT(hidden_dentry); + hidden_dentry = ERR_PTR(err); + goto out; + } + } +#endif + set_itohi_index(child_dentry->d_inode, bindex, + IGRAB(hidden_dentry->d_inode)); + if (ibstart(child_dentry->d_inode) > bindex) + ibstart(child_dentry->d_inode) = bindex; + if (ibend(child_dentry->d_inode) < bindex) + ibend(child_dentry->d_inode) = bindex; + + set_dtohd_index(child_dentry, bindex, hidden_dentry); + if (dbstart(child_dentry) > bindex) + set_dbstart(child_dentry, bindex); + if (dbend(child_dentry) < bindex) + set_dbend(child_dentry, bindex); + } + + parent_dentry = child_dentry; + child_dentry = path[--count]; + } + out: + KFREE(path); + print_dentry("OUT: create_parents_named", dentry); + print_exit_pointer(hidden_dentry); + return hidden_dentry; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/sioq.h +++ linux-2.6.27/ubuntu/unionfs/sioq.h @@ -0,0 +1,80 @@ +#ifndef _SIOQ_H +#define _SIOQ_H + +struct deletewh_args { + struct unionfs_dir_state *namelist; + struct dentry *dentry; + int bindex; +}; + +struct isopaque_args { + struct dentry *dentry; +}; + +struct create_args { + struct inode *parent; + struct dentry *dentry; + umode_t mode; + struct nameidata *nd; +}; + +struct mkdir_args { + struct inode *parent; + struct dentry *dentry; + umode_t mode; +}; + +struct mknod_args { + struct inode *parent; + struct dentry *dentry; + umode_t mode; + dev_t dev; +}; + +struct symlink_args { + struct inode *parent; + struct dentry *dentry; + char *symbuf; + umode_t mode; +}; + +struct unlink_args { + struct inode *parent; + struct dentry *dentry; +}; + + +struct sioq_args { + + struct completion comp; + struct work_struct wk; + int err; + void *ret; + + union { + struct deletewh_args deletewh; + struct isopaque_args isopaque; + struct create_args create; + struct mkdir_args mkdir; + struct mknod_args mknod; + struct symlink_args symlink; + struct unlink_args unlink; + }; //} u; +}; + +extern struct workqueue_struct *sioq; +int __init init_sioq(void); +extern void fin_sioq(void); +extern void run_sioq(work_func_t func, struct sioq_args *args); + +/* Extern definitions for our privledge escalation helpers */ +extern void __unionfs_create(struct work_struct *work); +extern void __unionfs_mkdir(struct work_struct *work); +extern void __unionfs_mknod(struct work_struct *work); +extern void __unionfs_symlink(struct work_struct *work); +extern void __unionfs_unlink(struct work_struct *work); +extern void __delete_whiteouts(struct work_struct *work); +extern void __is_opaque_dir(struct work_struct *work); + +#endif /* _SIOQ_H */ + --- linux-2.6.27.orig/ubuntu/unionfs/Makefile +++ linux-2.6.27/ubuntu/unionfs/Makefile @@ -0,0 +1,16 @@ +UNIONFS_VERSION = 1.4 +SUP_MAJOR= 2 +SUP_MINOR= 6 +SUP_PATCH= 18 + +EXTRA_CFLAGS+=-DUNIONFS_VERSION=\"${UNIONFS_VERSION}\" -DSUP_MAJOR=${SUP_MAJOR} -DSUP_MINOR=${SUP_MINOR} -DSUP_PATCH=${SUP_PATCH} -DUNIONFS_UNSUPPORTED + +# This will enable full debugging support +# EXTRA_CFLAGS+=-DUNIONFS_DEBUG + +obj-$(CONFIG_FS_UNIONFS) += unionfs.o + +unionfs-objs := subr.o dentry.o file.o inode.o main.o super.o \ + stale_inode.o branchman.o xattr.o rdstate.o copyup.o \ + dirhelper.o rename.o unlink.o lookup.o persistent_inode.o \ + commonfops.o dirfops.o print.o sioq.o --- linux-2.6.27.orig/ubuntu/unionfs/rdstate.c +++ linux-2.6.27/ubuntu/unionfs/rdstate.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: rdstate.c,v 1.34 2006/08/05 01:28:46 jro Exp $ + */ + +#include "unionfs.h" + +/* This file contains the routines for maintaining readdir state. */ +/* There are two structures here, rdstate which is a hash table + * of the second structure which is a filldir_node. */ + +/* This is a struct kmem_cache for filldir nodes, because we allocate a lot of them + * and they shouldn't waste memory. If the node has a small name (as defined + * by the dentry structure), then we use an inline name to preserve kmalloc + * space. */ +static struct kmem_cache *unionfs_filldir_cachep; +int init_filldir_cache(void) +{ + unionfs_filldir_cachep = + kmem_cache_create("unionfs_filldir", sizeof(struct filldir_node), 0, + SLAB_RECLAIM_ACCOUNT, NULL); + + if (!unionfs_filldir_cachep) + return -ENOMEM; + + return 0; +} + +void destroy_filldir_cache(void) +{ + if (!unionfs_filldir_cachep) + return; + kmem_cache_destroy(unionfs_filldir_cachep); + return; +} + +/* This is a tuning parameter that tells us roughly how big to make the + * hash table in directory entries per page. This isn't perfect, but + * at least we get a hash table size that shouldn't be too overloaded. + * The following averages are based on my home directory. + * 14.44693 Overall + * 12.29 Single Page Directories + * 117.93 Multi-page directories + */ +#define DENTPAGE 4096 +#define DENTPERONEPAGE 12 +#define DENTPERPAGE 118 +#define MINHASHSIZE 1 +static int guesstimate_hash_size(struct inode *inode) +{ + struct inode *hidden_inode; + int bindex; + int hashsize = MINHASHSIZE; + + if (itopd(inode)->uii_hashsize > 0) + return itopd(inode)->uii_hashsize; + + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) { + if (!(hidden_inode = itohi_index(inode, bindex))) + continue; + + if (hidden_inode->i_size == DENTPAGE) { + hashsize += DENTPERONEPAGE; + } else { + hashsize += + (hidden_inode->i_size / DENTPAGE) * DENTPERPAGE; + } + } + + return hashsize; +} + +int init_rdstate(struct file *file) +{ + BUG_ON(sizeof(loff_t) != (sizeof(unsigned int) + sizeof(unsigned int))); + BUG_ON(ftopd(file)->rdstate != NULL); + + ftopd(file)->rdstate = + alloc_rdstate(file->f_dentry->d_inode, fbstart(file)); + if (!ftopd(file)->rdstate) + return -ENOMEM; + return 0; +} + +struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos) +{ + struct unionfs_dir_state *rdstate = NULL; + struct list_head *pos; + + print_entry("f_pos: %lld", fpos); + spin_lock(&itopd(inode)->uii_rdlock); + list_for_each(pos, &itopd(inode)->uii_readdircache) { + struct unionfs_dir_state *r = + list_entry(pos, struct unionfs_dir_state, uds_cache); + if (fpos == rdstate2offset(r)) { + itopd(inode)->uii_rdcount--; + list_del(&r->uds_cache); + rdstate = r; + break; + } + } + spin_unlock(&itopd(inode)->uii_rdlock); + print_exit_pointer(rdstate); + return rdstate; +} + +struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex) +{ + int i = 0; + int hashsize; + int mallocsize = sizeof(struct unionfs_dir_state); + struct unionfs_dir_state *rdstate; + + hashsize = guesstimate_hash_size(inode); + mallocsize += hashsize * sizeof(struct list_head); + /* Round it up to the next highest power of two. */ + mallocsize--; + mallocsize |= mallocsize >> 1; + mallocsize |= mallocsize >> 2; + mallocsize |= mallocsize >> 4; + mallocsize |= mallocsize >> 8; + mallocsize |= mallocsize >> 16; + mallocsize++; + + /* This should give us about 500 entries anyway. */ + if (mallocsize > PAGE_SIZE) + mallocsize = PAGE_SIZE; + + hashsize = + (mallocsize - + sizeof(struct unionfs_dir_state)) / sizeof(struct list_head); + + rdstate = KMALLOC(mallocsize, GFP_KERNEL); + if (!rdstate) + return NULL; + + spin_lock(&itopd(inode)->uii_rdlock); + if (itopd(inode)->uii_cookie >= (MAXRDCOOKIE - 1)) + itopd(inode)->uii_cookie = 1; + else + itopd(inode)->uii_cookie++; + + rdstate->uds_cookie = itopd(inode)->uii_cookie; + spin_unlock(&itopd(inode)->uii_rdlock); + rdstate->uds_offset = 1; + rdstate->uds_access = jiffies; + rdstate->uds_bindex = bindex; + rdstate->uds_dirpos = 0; + rdstate->uds_hashentries = 0; + rdstate->uds_size = hashsize; + for (i = 0; i < rdstate->uds_size; i++) + INIT_LIST_HEAD(&rdstate->uds_list[i]); + + return rdstate; +} + +static void free_filldir_node(struct filldir_node *node) +{ + if (node->namelen >= DNAME_INLINE_LEN_MIN) + KFREE(node->name); + kmem_cache_free(unionfs_filldir_cachep, node); +} + +void free_rdstate(struct unionfs_dir_state *state) +{ + struct filldir_node *tmp; + int i; + + for (i = 0; i < state->uds_size; i++) { + struct list_head *head = &(state->uds_list[i]); + struct list_head *pos, *n; + + /* traverse the list and deallocate space */ + list_for_each_safe(pos, n, head) { + tmp = list_entry(pos, struct filldir_node, file_list); + list_del(&tmp->file_list); + free_filldir_node(tmp); + } + } + + KFREE(state); +} + +struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate, + const char *name, int namelen) +{ + int index; + unsigned int hash; + struct list_head *head; + struct list_head *pos; + struct filldir_node *cursor = NULL; + int found = 0; + + /* If we print entry, we end up with spurious data. */ + /* print_entry("name = %*s", namelen, name); */ + print_entry_location(); + + BUG_ON(namelen <= 0); + + hash = full_name_hash(name, namelen); + index = hash % rdstate->uds_size; + + head = &(rdstate->uds_list[index]); + list_for_each(pos, head) { + cursor = list_entry(pos, struct filldir_node, file_list); + + if (cursor->namelen == namelen && cursor->hash == hash + && !strncmp(cursor->name, name, namelen)) { + /* a duplicate exists, and hence no need to create entry to the list */ + found = 1; + /* if the duplicate is in this branch, then the file system is corrupted. */ + if (cursor->bindex == rdstate->uds_bindex) { + //buf->error = err = -EIO; + dprint(PRINT_DEBUG, + "Possible I/O error unionfs_filldir: a file is duplicated in the same branch %d: %s\n", + rdstate->uds_bindex, cursor->name); + } + break; + } + } + + if (!found) { + cursor = NULL; + } + print_exit_pointer(cursor); + return cursor; +} + +inline struct filldir_node *alloc_filldir_node(const char *name, int namelen, + unsigned int hash, int bindex) +{ + struct filldir_node *newnode; + + newnode = + (struct filldir_node *)kmem_cache_alloc(unionfs_filldir_cachep, + GFP_KERNEL); + if (!newnode) + goto out; + + out: + return newnode; +} + +int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name, + int namelen, int bindex, int whiteout) +{ + struct filldir_node *new; + unsigned int hash; + int index; + int err = 0; + struct list_head *head; + + /* We can't print this because we end up Oopsing. */ + /* print_entry("name = %*s", namelen, name); */ + print_entry_location(); + + BUG_ON(namelen <= 0); + + hash = full_name_hash(name, namelen); + index = hash % rdstate->uds_size; + head = &(rdstate->uds_list[index]); + + new = alloc_filldir_node(name, namelen, hash, bindex); + if (!new) { + err = -ENOMEM; + goto out; + } + + INIT_LIST_HEAD(&new->file_list); + new->namelen = namelen; + new->hash = hash; + new->bindex = bindex; + new->whiteout = whiteout; + + if (namelen < DNAME_INLINE_LEN_MIN) { + new->name = new->iname; + } else { + new->name = (char *)KMALLOC(namelen + 1, GFP_KERNEL); + if (!new->name) { + kmem_cache_free(unionfs_filldir_cachep, new); + new = NULL; + goto out; + } + } + + memcpy(new->name, name, namelen); + new->name[namelen] = '\0'; + + rdstate->uds_hashentries++; + + list_add(&(new->file_list), head); + out: + print_exit_status(err); + return err; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/xattr.c +++ linux-2.6.27/ubuntu/unionfs/xattr.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef Sipek + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: xattr.c,v 1.32 2006/06/01 03:11:03 jsipek Exp $ + */ + +#include "unionfs.h" + +/* This is lifted from fs/xattr.c */ +void *xattr_alloc(size_t size, size_t limit) +{ + void *ptr; + + if (size > limit) + return ERR_PTR(-E2BIG); + + if (!size) /* size request, no buffer is needed */ + return NULL; + else if (size <= PAGE_SIZE) + ptr = KMALLOC((unsigned long)size, GFP_KERNEL); + else + ptr = vmalloc((unsigned long)size); + if (!ptr) + return ERR_PTR(-ENOMEM); + return ptr; +} + +void xattr_free(void *ptr, size_t size) +{ + if (!size) /* size request, no buffer was needed */ + return; + else if (size <= PAGE_SIZE) + KFREE(ptr); + else + vfree(ptr); +} + +/* BKL held by caller. + * dentry->d_inode->i_mutex locked + * ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); + */ +ssize_t unionfs_getxattr(struct dentry * dentry, const char *name, void *value, + size_t size) +{ + struct dentry *hidden_dentry = NULL; + int err = -EOPNOTSUPP; + + print_entry_location(); + + dprint(PRINT_DEBUG_XATTR, "getxattr: name=\"%s\", value %lu bytes\n", + name, size); + + lock_dentry(dentry); + + hidden_dentry = dtohd(dentry); + + err = vfs_getxattr(hidden_dentry, NULL, (char*)name, value, size, + NULL); + + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +/* BKL held by caller. + * dentry->d_inode->i_mutex locked + */ +int +unionfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) +{ + struct dentry *hidden_dentry = NULL; + int err = -EOPNOTSUPP; + + print_entry_location(); + + lock_dentry(dentry); + hidden_dentry = dtohd(dentry); + + dprint(PRINT_DEBUG_XATTR, "setxattr: name=\"%s\", value %lu bytes," + "flags=%x\n", name, (unsigned long)size, flags); + + err = + vfs_setxattr(hidden_dentry, NULL, (char *)name, (char *)value, + size, flags, NULL); + + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +/* BKL held by caller. + * dentry->d_inode->i_mutex locked + */ +int unionfs_removexattr(struct dentry *dentry, const char *name) +{ + struct dentry *hidden_dentry = NULL; + int err = -EOPNOTSUPP; + + print_entry_location(); + + lock_dentry(dentry); + hidden_dentry = dtohd(dentry); + + dprint(PRINT_DEBUG_XATTR, "removexattr: name=\"%s\"\n", name); + + err = vfs_removexattr(hidden_dentry, NULL, (char*)name, NULL); + + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +/* BKL held by caller. + * dentry->d_inode->i_mutex locked + */ +ssize_t unionfs_listxattr(struct dentry * dentry, char *list, size_t size) +{ + struct dentry *hidden_dentry = NULL; + int err = -EOPNOTSUPP; + char *encoded_list = NULL; + + print_entry_location(); + lock_dentry(dentry); + + hidden_dentry = dtohd(dentry); + + encoded_list = list; + err = vfs_listxattr(hidden_dentry, NULL, encoded_list, size, NULL); + + unlock_dentry(dentry); + print_exit_status(err); + return err; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/unionfs/subr.c +++ linux-2.6.27/ubuntu/unionfs/subr.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2003-2006 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2006 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2005-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2006 Stony Brook University + * Copyright (c) 2003-2006 The Research Foundation of State University of New York + * + * For specific licensing information, see the COPYING file distributed with + * this package. + * + * This Copyright notice must be kept intact and distributed with all sources. + */ +/* + * $Id: subr.c,v 1.142 2006/09/21 18:19:36 jsipek Exp $ + */ + +#include "unionfs.h" +#include + +/* Pass an unionfs dentry and an index. It will try to create a whiteout + * for the filename in dentry, and will try in branch 'index'. On error, + * it will proceed to a branch to the left. + */ +int create_whiteout(struct dentry *dentry, int start) +{ + int bstart, bend, bindex; + struct dentry *hidden_dir_dentry; + struct dentry *hidden_dentry; + struct dentry *hidden_wh_dentry; + char *name = NULL; + int err = -EINVAL; + + print_entry("start = %d", start); + + verify_locked(dentry); + + print_dentry("IN create_whiteout", dentry); + bstart = dbstart(dentry); + bend = dbend(dentry); + + /* create dentry's whiteout equivalent */ + name = alloc_whname(dentry->d_name.name, dentry->d_name.len); + if (IS_ERR(name)) { + err = PTR_ERR(name); + goto out; + } + + for (bindex = start; bindex >= 0; bindex--) { + hidden_dentry = dtohd_index(dentry, bindex); + + if (!hidden_dentry) { + /* if hidden dentry is not present, create the entire + * hidden dentry directory structure and go ahead. + * Since we want to just create whiteout, we only want + * the parent dentry, and hence get rid of this dentry. + */ + hidden_dentry = create_parents(dentry->d_inode, + dentry, bindex); + if (!hidden_dentry || IS_ERR(hidden_dentry)) { + dprint(PRINT_DEBUG_WHITEOUT, + "create_parents failed for bindex = %d\n", + bindex); + continue; + } + } + hidden_wh_dentry = + LOOKUP_ONE_LEN(name, hidden_dentry->d_parent, + dentry->d_name.len + WHLEN); + if (IS_ERR(hidden_wh_dentry)) + continue; + + /* The whiteout already exists. This used to be impossible, but + * now is possible because of opaqueness. */ + if (hidden_wh_dentry->d_inode) { + DPUT(hidden_wh_dentry); + err = 0; + goto out; + } + + hidden_dir_dentry = lock_parent(hidden_wh_dentry); + if (!(err = is_robranch_super(dentry->d_sb, bindex))) { + err = + vfs_create(hidden_dir_dentry->d_inode, + hidden_wh_dentry, + ~current->fs->umask & S_IRWXUGO, NULL); + + } + unlock_dir(hidden_dir_dentry); + DPUT(hidden_wh_dentry); + + if (!err) + break; + + if (!IS_COPYUP_ERR(err)) + break; + } + + /* set dbopaque so that lookup will not proceed after this branch */ + if (!err) + set_dbopaque(dentry, bindex); + + print_dentry("OUT create_whiteout", dentry); + out: + KFREE(name); + print_exit_status(err); + return err; +} + +/* This is a helper function for rename, which ends up with hosed over dentries + * when it needs to revert. */ +int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex) +{ + struct dentry *hidden_dentry; + struct dentry *hidden_parent; + int err = 0; + + print_entry(" bindex = %d", bindex); + + verify_locked(dentry); + lock_dentry(dentry->d_parent); + hidden_parent = dtohd_index(dentry->d_parent, bindex); + unlock_dentry(dentry->d_parent); + + BUG_ON(!S_ISDIR(hidden_parent->d_inode->i_mode)); + + hidden_dentry = + LOOKUP_ONE_LEN(dentry->d_name.name, hidden_parent, + dentry->d_name.len); + if (IS_ERR(hidden_dentry)) { + err = PTR_ERR(hidden_dentry); + goto out; + } + + if (dtohd_index(dentry, bindex)) + DPUT(dtohd_index(dentry, bindex)); + if (itohi_index(dentry->d_inode, bindex)) { + IPUT(itohi_index(dentry->d_inode, bindex)); + set_itohi_index(dentry->d_inode, bindex, NULL); + } + if (!hidden_dentry->d_inode) { + DPUT(hidden_dentry); + set_dtohd_index(dentry, bindex, NULL); + } else { + set_dtohd_index(dentry, bindex, hidden_dentry); + set_itohi_index(dentry->d_inode, bindex, + IGRAB(hidden_dentry->d_inode)); + } + + out: + print_exit_status(err); + return err; +} + +int make_dir_opaque(struct dentry *dentry, int bindex) +{ + int err; + struct dentry *hidden_dentry, *diropq; + struct inode *hidden_dir; + + hidden_dentry = dtohd_index(dentry, bindex); + hidden_dir = hidden_dentry->d_inode; + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) + || !S_ISDIR(hidden_dir->i_mode)); + + mutex_lock(&hidden_dir->i_mutex); + diropq = LOOKUP_ONE_LEN(UNIONFS_DIR_OPAQUE, hidden_dentry, + sizeof(UNIONFS_DIR_OPAQUE) - 1); + err = PTR_ERR(diropq); + if (IS_ERR(diropq)) + goto out; + err = 0; + + if (!diropq->d_inode) + err = vfs_create(hidden_dir, diropq, S_IRUGO, NULL); + DPUT(diropq); + if (!err) + set_dbopaque(dentry, bindex); + + out: + mutex_unlock(&hidden_dir->i_mutex); + return err; +} + +/* + * + * vim:shiftwidth=8 + * vim:tabstop=8 + * + * For Emacs: + * Local variables: + * c-basic-offset: 8 + * c-comment-only-line-offset: 0 + * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0) + * (substatement-open . 0) (label . 0) (statement-cont . +)) + * indent-tabs-mode: t + * tab-width: 8 + * End: + */ --- linux-2.6.27.orig/ubuntu/qc-usb/videodevfix.h +++ linux-2.6.27/ubuntu/qc-usb/videodevfix.h @@ -0,0 +1,15 @@ +#ifndef VIDEODEVFIX_H +#define VIDEODEVFIX_H + +#include + +typedef int8_t __s8; +typedef u_int8_t __u8; +typedef int16_t __s16; +typedef u_int16_t __u16; +typedef int32_t __s32; +typedef u_int32_t __u32; +typedef int64_t __s64; +typedef u_int64_t __u64; + +#endif --- linux-2.6.27.orig/ubuntu/qc-usb/qc-memory.c +++ linux-2.6.27/ubuntu/qc-usb/qc-memory.c @@ -0,0 +1,252 @@ +/* Start of file */ + +/* {{{ [fold] Comments */ +/* + * qce-ga, linux V4L driver for the QuickCam Express and Dexxa QuickCam + * + * memory.c - contains all needed memory management functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* These routines have been derived from the ov511 driver, into which they + * were derived from the bttv driver. + */ +/* }}} */ +/* {{{ [fold] Includes */ +#include +#include + +#ifdef CONFIG_SMP +#define __SMP__ +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) +#define MODVERSIONS +#endif +#ifdef MODVERSIONS +#include +#endif +#endif + +#include "qc-memory.h" +#include +#include /* Required on Alpha, from Bob McElrath */ +#include /* Required on Alpha */ +#include /* Required on Alpha */ +#include /* pmd_offset requires this on SuSE supplied kernels */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#include /* For proper mem_map_(un)reserve define, the compatibility define below might not work */ +#endif +/* }}} */ +/* {{{ [fold] Compatibility wrappers */ +#ifndef HAVE_VMA +#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,5,3) || (defined(RED_HAT_LINUX_KERNEL) && defined(pte_offset_map)) +#define HAVE_VMA 1 +#else +#define HAVE_VMA 0 +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +#if HAVE_VMA +#warning "HAVE_VMA=1" +/* remap_page_range is still emulated in 2.6.10, in 2.6.11 it's completely removed */ +static inline int qc_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot) { return remap_page_range(vma, from, pfn<=KERNEL_VERSION(2,5,3) || defined(pte_offset_map) +#define pte_offset(pmd,adr) pte_offset_map(pmd,adr) /* Emulation for a kernel using the new rmap-vm */ +#endif /* Fix by Michele Balistreri */ + +/* }}} */ + +/* {{{ [fold] kvirt_to_pa(): obtain physical address from virtual address obtained by vmalloc() */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +/* {{{ [fold] kvirt_to_pa(), 2.4.x and 2.6.x */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) +static struct page *vmalloc_to_page(void * vmalloc_addr); +#endif + +/* Here we want the physical address of the memory obtained by vmalloc(). + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long kva, ret; + + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ + ret = __pa(kva); + return ret; +} +/* }}} */ +#else +/* {{{ [fold] kvirt_to_pa() for 2.2.x */ +#define page_address(x) (x | PAGE_OFFSET) /* Damn ugly hack from kcomp.h; replaces original page_address() that made different thing! */ + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) +{ + unsigned long ret = 0UL; + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if (pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + } + } + } + + return ret; +} + +/* Here we want the physical address of the memory obtained by vmalloc(). + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + return ret; +} +/* }}} */ +#endif +/* }}} */ +/* {{{ [fold] vmalloc_to_page(): obtain pointer to struct page from virtual address obtained by vmalloc() */ +#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,4,0) && LINUX_VERSION_CODE 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} +/* }}} */ +/* {{{ [fold] qc_mm_rvfree(mem, size) */ +void qc_mm_rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} +/* }}} */ +/* {{{ [fold] qc_mm_remap(vma, src, src_size, dst, dst_size) */ +int qc_mm_remap(struct vm_area_struct *vma, void *src, unsigned long src_size, const void *dst, unsigned long dst_size) +{ + unsigned long start = (unsigned long)dst; + unsigned long size = dst_size; + unsigned long physaddr, pos; + + pos = (unsigned long)src; + while ((long)size > 0) { + physaddr = kvirt_to_pa(pos); +#if 1 + if ((physaddr & ~PAGE_MASK)!=0) { + printk(KERN_CRIT "qc_mm_remap: physaddr=%08X not page aligned!\n", (int)physaddr); + return -EIO; + } +#endif + if (remap_pfn_range(vma, start, physaddr>>PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + return 0; +} +/* }}} */ + +/* End of file */ --- linux-2.6.27.orig/ubuntu/qc-usb/Kconfig +++ linux-2.6.27/ubuntu/qc-usb/Kconfig @@ -0,0 +1,4 @@ +config QC_USB + tristate "Quickcam USB Driver" + default m + depends on USB --- linux-2.6.27.orig/ubuntu/qc-usb/qc-pb0100.c +++ linux-2.6.27/ubuntu/qc-usb/qc-pb0100.c @@ -0,0 +1,377 @@ +/* Start of file */ + +/* {{{ [fold] Comments */ +/* + * qce-ga, linux V4L driver for the QuickCam Express and Dexxa QuickCam + * + * pb0100.c - PB0100 Sensor Implementation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* }}} */ + +#include "quickcam.h" + +/* I2C Address */ +#define PB_ADDR 0xBA + +/* {{{ [fold] I2C Registers */ +#define PB_IDENT 0x00 /* R0 Chip Version */ +#define PB_RSTART 0x01 /* R1 Row Window Start */ +#define PB_CSTART 0x02 /* R2 Column Window Start */ +#define PB_RWSIZE 0x03 /* R3 Row Window Size */ +#define PB_CWSIZE 0x04 /* R4 Column Window Size */ +#define PB_CFILLIN 0x05 /* R5 Column Fill-In */ +#define PB_VBL 0x06 /* R6 Vertical Blank Count */ +#define PB_CONTROL 0x07 /* R7 Control Mode */ +#define PB_FINTTIME 0x08 /* R8 Integration Time/Frame Unit Count */ +#define PB_RINTTIME 0x09 /* R9 Integration Time/Row Unit Count */ +#define PB_ROWSPEED 0x0A /* R10 Row Speed Control */ +#define PB_ABORTFRAME 0x0B /* R11 Abort Frame */ +/* #define PB_R12 0x0C R12 Reserved */ +#define PB_RESET 0x0D /* R13 Reset */ +#define PB_EXPGAIN 0x0E /* R14 Exposure Gain Command */ +#define PB_R15 0x0F /* R15 Expose0 */ +#define PB_R16 0x10 /* R16 Expose1 */ +#define PB_R17 0x11 /* R17 Expose2 */ +#define PB_R18 0x12 /* R18 Low0_DAC */ +#define PB_R19 0x13 /* R19 Low1_DAC */ +#define PB_R20 0x14 /* R20 Low2_DAC */ +#define PB_R21 0x15 /* R21 Threshold11 */ +#define PB_R22 0x16 /* R22 Threshold0x */ +#define PB_UPDATEINT 0x17 /* R23 Update Interval */ +#define PB_R24 0x18 /* R24 High_DAC */ +#define PB_R25 0x19 /* R25 Trans0H */ +#define PB_R26 0x1A /* R26 Trans1L */ +#define PB_R27 0x1B /* R27 Trans1H */ +#define PB_R28 0x1C /* R28 Trans2L */ +/* #define PB_R29 0x1D R29 Reserved */ +/* #define PB_R30 0x1E R30 Reserved */ +#define PB_R31 0x1F /* R31 Wait to Read */ +#define PB_PREADCTRL 0x20 /* R32 Pixel Read Control Mode */ +#define PB_R33 0x21 /* R33 IREF_VLN */ +#define PB_R34 0x22 /* R34 IREF_VLP */ +#define PB_R35 0x23 /* R35 IREF_VLN_INTEG */ +#define PB_R36 0x24 /* R36 IREF_MASTER */ +#define PB_R37 0x25 /* R37 IDACP */ +#define PB_R38 0x26 /* R38 IDACN */ +#define PB_R39 0x27 /* R39 DAC_Control_Reg */ +#define PB_R40 0x28 /* R40 VCL */ +#define PB_R41 0x29 /* R41 IREF_VLN_ADCIN */ +/* #define PB_R42 0x2A R42 Reserved */ +#define PB_G1GAIN 0x2B /* R43 Green 1 Gain */ +#define PB_BGAIN 0x2C /* R44 Blue Gain */ +#define PB_RGAIN 0x2D /* R45 Red Gain */ +#define PB_G2GAIN 0x2E /* R46 Green 2 Gain */ +#define PB_R47 0x2F /* R47 Dark Row Address */ +#define PB_R48 0x30 /* R48 Dark Row Options */ +/* #define PB_R49 0x31 R49 Reserved */ +#define PB_R50 0x32 /* R50 Image Test Data */ +#define PB_ADCMAXGAIN 0x33 /* R51 Maximum Gain */ +#define PB_ADCMINGAIN 0x34 /* R52 Minimum Gain */ +#define PB_ADCGLOBALGAIN 0x35 /* R53 Global Gain */ +#define PB_R54 0x36 /* R54 Maximum Frame */ +#define PB_R55 0x37 /* R55 Minimum Frame */ +/* #define PB_R56 0x38 R56 Reserved */ +#define PB_VOFFSET 0x39 /* R57 VOFFSET */ +#define PB_R58 0x3A /* R58 Snap-Shot Sequence Trigger */ +#define PB_ADCGAINH 0x3B /* R59 VREF_HI */ +#define PB_ADCGAINL 0x3C /* R60 VREF_LO */ +/* #define PB_R61 0x3D R61 Reserved */ +/* #define PB_R62 0x3E R62 Reserved */ +/* #define PB_R63 0x3F R63 Reserved */ +#define PB_R64 0x40 /* R64 Red/Blue Gain */ +#define PB_R65 0x41 /* R65 Green 2/Green 1 Gain */ +#define PB_R66 0x42 /* R66 VREF_HI/LO */ +#define PB_R67 0x43 /* R67 Integration Time/Row Unit Count */ +#define PB_R240 0xF0 /* R240 ADC Test */ +#define PB_R241 0xF1 /* R241 Chip Enable */ +/* #define PB_R242 0xF2 R242 Reserved */ +/* }}} */ + +#define I2C_SETW_CHECK(reg,val) if ((r = qc_i2c_setw(qc,(reg),(val)))<0) goto fail +#define STV_SET_CHECK(reg,val) if ((r = qc_stv_set(qc,(reg),(val)))<0) goto fail +#define STV_SETW_CHECK(reg,val) if ((r = qc_stv_setw(qc,(reg),(val)))<0) goto fail + +/* + * The spec file for the PB-0100 suggests the following for best quality + * images after the sensor has been reset : + * + * PB_ADCGAINL = R60 = 0x03 (3 dec) : sets low reference of ADC to produce good black level + * PB_PREADCTRL = R32 = 0x1400 (5120 dec) : Enables global gain changes through R53 + * PB_ADCMINGAIN = R52 = 0x10 (16 dec) : Sets the minimum gain for auto-exposure + * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec) : Sets the global gain + * PB_EXPGAIN = R14 = 0x11 (17 dec) : Sets the auto-exposure value + * PB_UPDATEINT = R23 = 0x02 (2 dec) : Sets the speed on auto-exposure routine + * PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate + */ + +/* {{{ [fold] pb0100_init: Initialise parameters of PB100 sensor */ +static int pb0100_init(struct quickcam *qc) +{ + static const Bool natural = TRUE; /* Disable flicker control for natural lighting? */ + struct qc_sensor_data *sd = &qc->sensor_data; + int r; + + if (sd->compress) return -EINVAL; + sd->maxwidth = 360; + sd->maxheight = 288; /* Sensor has 296 rows but top 8 are opaque */ + if (sd->subsample) { + sd->maxwidth /= 2; + sd->maxheight /= 2; + } + sd->exposure = 0; + + STV_SET_CHECK(STV_REG00, 1); + STV_SET_CHECK(STV_SCAN_RATE, 0); + + /* Reset sensor */ + I2C_SETW_CHECK(PB_RESET, 1); + if ((r = qc_i2c_wait(qc))<0) goto fail; + I2C_SETW_CHECK(PB_RESET, 0); + if ((r = qc_i2c_wait(qc))<0) goto fail; + + /* Disable chip */ + I2C_SETW_CHECK(PB_CONTROL, BIT(5)|BIT(3)); + if ((r = qc_i2c_wait(qc))<0) goto fail; + + /* Gain stuff...*/ + I2C_SETW_CHECK(PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6)); + I2C_SETW_CHECK(PB_ADCGLOBALGAIN, 12); + if ((r = qc_i2c_wait(qc))<0) goto fail; + + /* Set up auto-exposure */ + I2C_SETW_CHECK(PB_R28, 12); /* ADC VREF_HI new setting for a transition from the Expose1 to the Expose2 setting */ + I2C_SETW_CHECK(PB_ADCMAXGAIN, 180); /* gain max for autoexposure */ + I2C_SETW_CHECK(PB_ADCMINGAIN, 12); /* gain min for autoexposure */ + I2C_SETW_CHECK(PB_R54, 3); /* Maximum frame integration time (programmed into R8) allowed for auto-exposure routine */ + I2C_SETW_CHECK(PB_R55, 0); /* Minimum frame integration time (programmed into R8) allowed for auto-exposure routine */ + I2C_SETW_CHECK(PB_UPDATEINT, 1); + I2C_SETW_CHECK(PB_R15, 800); /* R15 Expose0 (maximum that auto-exposure may use) */ + I2C_SETW_CHECK(PB_R17, 10); /* R17 Expose2 (minimum that auto-exposure may use) */ + + if (qc->settings.adaptive) { + I2C_SETW_CHECK(PB_EXPGAIN, (natural?BIT(6):0)|BIT(4)|BIT(0)); + } else { + I2C_SETW_CHECK(PB_EXPGAIN, 0); + } + if ((r = qc_i2c_wait(qc))<0) goto fail; + + I2C_SETW_CHECK(PB_VOFFSET, 0); /* 0x14 */ + I2C_SETW_CHECK(PB_ADCGAINH, 11); /* 0x0D */ + I2C_SETW_CHECK(PB_ADCGAINL, 0); /* Set black level (important!) */ + + /* ??? */ + STV_SET_CHECK(STV_REG04, 0x07); + STV_SET_CHECK(STV_REG03, 0x45); + STV_SET_CHECK(STV_REG00, 0x11); + + /* Set mode */ + STV_SET_CHECK(STV_Y_CTRL, sd->subsample ? 2 : 1); /* 0x02: half, 0x01: full FIXME: this doesn't work! */ + STV_SET_CHECK(STV_X_CTRL, sd->subsample ? 6 : 0x0A); /* 0x06: Half, 0x0A: Full */ + + /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */ + STV_SETW_CHECK(STV_ISO_SIZE, 847); + + /* Setup sensor window */ + I2C_SETW_CHECK(PB_RSTART, 0); + I2C_SETW_CHECK(PB_CSTART, 0); + I2C_SETW_CHECK(PB_RWSIZE, 240-1); /* 0xF7: 240 */ + I2C_SETW_CHECK(PB_CWSIZE, 320-1); /* 0x13F: 320 */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + + /* Scan rate? */ + STV_SET_CHECK(STV_SCAN_RATE, sd->subsample ? 0x10 : 0x20); /* larger -> slower */ + + /* Scan/timing for the sensor */ + I2C_SETW_CHECK(PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); + I2C_SETW_CHECK(PB_CFILLIN, 14); + I2C_SETW_CHECK(PB_VBL, 0); + I2C_SETW_CHECK(PB_FINTTIME, 0); + I2C_SETW_CHECK(PB_RINTTIME, 123); + if ((r = qc_i2c_wait(qc))<0) goto fail; + + STV_SET_CHECK(STV_REG01, 0xC2); + STV_SET_CHECK(STV_REG02, 0xB0); + +fail: return r; +} +/* }}} */ +/* {{{ [fold] pb0100_set_exposure() */ +static int pb0100_set_exposure(struct quickcam *qc, unsigned int val) +{ + int r; + struct qc_sensor_data *sd = &qc->sensor_data; + val >>= 7; + if (val==sd->exposure) return 0; + sd->exposure = val; + I2C_SETW_CHECK(PB_RINTTIME, val); /* R9 */ +fail: return r; +} +/* }}} */ +/* {{{ [fold] pb0100_set_gains() */ +static int pb0100_set_gains(struct quickcam *qc, u16 hue, u16 sat, u16 val) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + unsigned int rgain, bgain, ggain; + int r; + qc_hsv2rgb(hue, sat, val, &rgain, &bgain, &ggain); + rgain >>= 8; /* After this the values are 0..255 */ + ggain >>= 8; + bgain >>= 8; + if (rgain==sd->rgain && ggain==sd->ggain && bgain==sd->bgain) return 0; + sd->rgain = rgain; + sd->ggain = ggain; + sd->bgain = bgain; + I2C_SETW_CHECK(PB_RGAIN, rgain); /* R43 */ + I2C_SETW_CHECK(PB_G1GAIN, ggain); /* R44 */ + I2C_SETW_CHECK(PB_G2GAIN, ggain); /* R45 */ + I2C_SETW_CHECK(PB_BGAIN, bgain); /* R46 */ +fail: return r; +} +/* }}} */ +/* {{{ [fold] pb0100_set_levels() */ +static int pb0100_set_levels(struct quickcam *qc, unsigned int exp, unsigned int gain, unsigned int hue, unsigned int sat) +{ + int r; + /* When automatic exposure control in Photobit is used, the exposure/gain + * registers shouldn't be touched. The sensor may update them only rarely + * and if they're changed they may be incorrect until the sensor updates + * the registers next time. + * FIXME: shouldn't qc-driver.c ensure this function isnt called when adaptive is used? + */ + if (qc->settings.adaptive) return 0; + if ((r = pb0100_set_exposure(qc, exp))<0) goto fail; + pb0100_set_gains(qc, hue, sat, gain); +fail: return r; +} +/* }}} */ +/* {{{ [fold] pb0100_set_target: Set target brightness for sensor autoexposure, val=0..65535 */ +static int pb0100_set_target(struct quickcam *qc, unsigned int val) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + unsigned int totalpixels, brightpixels, darkpixels; + int r; + + val >>= 8; /* val = 0..255 (0-50% of bright pixels) */ + if (val==sd->exposure) return 0; + sd->exposure = val; + + /* Number of pixels counted by the sensor when subsampling the pixels. + * Slightly larger than the real value to avoid oscillation */ + totalpixels = sd->width * sd->height; + totalpixels = totalpixels/(8*8) + totalpixels/(64*64); + + brightpixels = (totalpixels * val) >> 8; + darkpixels = totalpixels - brightpixels; + I2C_SETW_CHECK(PB_R21, brightpixels); /* R21 */ + I2C_SETW_CHECK(PB_R22, darkpixels); /* R22 */ +fail: return r; +} +/* }}} */ +/* {{{ [fold] pb0100_set_size: Set window size */ +/* Window location and size are controlled by R1, R2, R3 and R4. + * The default size is CIF (352x288) with to right at (4,12) + * and bottom left at (355, 299) + * + * We try to ensure that the captured area is in the center of + * the camera purely because that's nicer. It would be better + * if the PB0100 sensor supported capture scaling! + * + * We do it in on step otherwise size change may take more + * than one frame (like xawtv who tests 64x48 and uses 352x288) + * 3072 = 64x48, 16896 = 352x48, 101376 = 352x288. + */ +static int pb0100_set_size(struct quickcam *qc, unsigned int w, unsigned int h) +{ + static const unsigned int originx = 0; /* First visible pixel */ + static const unsigned int originy = 8; + static const unsigned int maxwidth = 360; /* Visible sensor size */ + static const unsigned int maxheight = 288; + struct qc_sensor_data *sd = &qc->sensor_data; + int x, y; + int r; + + sd->width = w; + sd->height = h; + if (sd->subsample) { + w *= 2; + h *= 2; + } + x = (maxwidth - w)/2; /* Center image by computing upper-left corner */ + y = (maxheight - h)/2; + x = (x + originx) & ~1; /* Must be even to align to the Bayer pattern */ + y = (y + originy) & ~1; + I2C_SETW_CHECK(PB_RSTART, y); /* PB_RSTART = 12 + y */ + I2C_SETW_CHECK(PB_CSTART, x); /* PB_CSTART = 4 + x */ + I2C_SETW_CHECK(PB_RWSIZE, h - 1); /* PB_RWSIZE = h - 1 */ + I2C_SETW_CHECK(PB_CWSIZE, w - 1); /* PB_CWSIZE = w - 1 */ + + if (qc->settings.adaptive) { + /* The automatic exposure counts need to be recomputed when size is changed */ + x = sd->exposure << 8; + sd->exposure = -1; + if ((r = pb0100_set_target(qc, x))<0) goto fail; + } + + r = qc_i2c_wait(qc); +fail: return r; +} +/* }}} */ +/* {{{ [fold] pb0100_start: Start grabbing */ +static int pb0100_start(struct quickcam *qc) +{ + int r; + I2C_SETW_CHECK(PB_CONTROL, BIT(5)|BIT(3)|BIT(1)); + r = qc_i2c_wait(qc); +fail: return r; +} +/* }}} */ +/* {{{ [fold] pb0100_stop: Stop grabbing */ +static int pb0100_stop(struct quickcam *qc) +{ + int r; + I2C_SETW_CHECK(PB_ABORTFRAME, 1); + if ((r = qc_i2c_wait(qc))<0) goto fail; + I2C_SETW_CHECK(PB_CONTROL, BIT(5)|BIT(3)); /* Set bit 1 to zero */ + r = qc_i2c_wait(qc); +fail: return r; +} +/* }}} */ + +/* {{{ [fold] struct qc_sensor qc_sensor_pb0100 */ +const struct qc_sensor qc_sensor_pb0100 = { + name: "PB-0100/0101", + manufacturer: "Photobit", + init: pb0100_init, + start: pb0100_start, + stop: pb0100_stop, + set_size: pb0100_set_size, + set_levels: pb0100_set_levels, + set_target: pb0100_set_target, + /* Exposure and gain control information */ + autoexposure: TRUE, + /* Information needed to access the sensor via I2C */ + reg23: 1, + i2c_addr: PB_ADDR, + /* Identification information used for auto-detection */ + id_reg: PB_IDENT, + id: 0x64, + length_id: 2, +}; +/* }}} */ + +/* End of file */ --- linux-2.6.27.orig/ubuntu/qc-usb/quickcam.h +++ linux-2.6.27/ubuntu/qc-usb/quickcam.h @@ -0,0 +1,585 @@ +#ifndef _LINUX_QUICKCAM_H +#define _LINUX_QUICKCAM_H + +/* {{{ [fold] SECTION: common definitions with userspace applications */ +#define QC_LUT_SIZE (3*256) /* Lookup table definition for equalization */ +#define QC_LUT_RED 0 +#define QC_LUT_GREEN 256 +#define QC_LUT_BLUE 512 + +struct qc_userlut { + unsigned int flags; +#define QC_USERLUT_DEFAULT 1 /* If set, change default settings or the current camera otherwise */ +#define QC_USERLUT_ENABLE 2 /* If set, enable user-specified LUT, or otherwise disable it */ +#define QC_USERLUT_VALUES 4 /* Load new (or store old) values into the lookup-table */ + unsigned char lut[QC_LUT_SIZE]; /* Lookup table to set or read */ +}; + +#define VIDEO_PALETTE_BAYER (('q'<<8) | 1) /* Grab video in raw Bayer format */ +#define VIDEO_PALETTE_MJPEG (('q'<<8) | 2) /* Grab video in compressed MJPEG format */ +#define VID_HARDWARE_QCAM_USB (('q'<<8) | 50) /* Device type */ + +/* Private IOCTL calls */ +#define QC_IOCTLBASE 220 /* Don't use same numbers as Philips driver */ +#define VIDIOCQCGDEBUG _IOR ('v',QC_IOCTLBASE+0, int) /* Gets the debug output, bitfield */ +#define VIDIOCQCSDEBUG _IOWR('v',QC_IOCTLBASE+0, int) /* Sets the debug output, bitfield */ +#define VIDIOCQCGKEEPSETTINGS _IOR ('v',QC_IOCTLBASE+1, int) /* Get keep picture settings across one open to another (0-1) */ +#define VIDIOCQCSKEEPSETTINGS _IOWR('v',QC_IOCTLBASE+1, int) /* Set keep picture settings across one open to another (0-1) */ +#define VIDIOCQCGSETTLE _IOR ('v',QC_IOCTLBASE+2, int) /* Get if we let image brightness settle (0-1) */ +#define VIDIOCQCSSETTLE _IOWR('v',QC_IOCTLBASE+2, int) /* Set if we let image brightness settle (0-1) */ +#define VIDIOCQCGSUBSAMPLE _IOR ('v',QC_IOCTLBASE+3, int) /* Gets the speed (0-1) */ +#define VIDIOCQCSSUBSAMPLE _IOWR('v',QC_IOCTLBASE+3, int) /* Sets the speed (0-1) */ +#define VIDIOCQCGCOMPRESS _IOR ('v',QC_IOCTLBASE+4, int) /* Gets the compression mode (0-1) */ +#define VIDIOCQCSCOMPRESS _IOWR('v',QC_IOCTLBASE+4, int) /* Sets the compression mode (0-1) */ +#define VIDIOCQCGFRAMESKIP _IOR ('v',QC_IOCTLBASE+5, int) /* Get frame capture frequency (0-10) */ +#define VIDIOCQCSFRAMESKIP _IOWR('v',QC_IOCTLBASE+5, int) /* Set frame capture frequency (0-10) */ +#define VIDIOCQCGQUALITY _IOR ('v',QC_IOCTLBASE+6, int) /* Gets the interpolation mode (0-2) */ +#define VIDIOCQCSQUALITY _IOWR('v',QC_IOCTLBASE+6, int) /* Sets the interpolation mode (0-2) */ +#define VIDIOCQCGADAPTIVE _IOR ('v',QC_IOCTLBASE+7, int) /* Get automatic adaptive brightness control (0-1) */ +#define VIDIOCQCSADAPTIVE _IOWR('v',QC_IOCTLBASE+7, int) /* Set automatic adaptive brightness control (0-1) */ +#define VIDIOCQCGEQUALIZE _IOR ('v',QC_IOCTLBASE+8, int) /* Get equalize image (0-1) */ +#define VIDIOCQCSEQUALIZE _IOWR('v',QC_IOCTLBASE+8, int) /* Set equalize image (0-1) */ +#define VIDIOCQCGRETRYERRORS _IOR ('v',QC_IOCTLBASE+9, int) /* Get if we retry when capture fails (0-1) */ +#define VIDIOCQCSRETRYERRORS _IOWR('v',QC_IOCTLBASE+9, int) /* Set if we retry when capture fails (0-1) */ +#define VIDIOCQCGCOMPATIBLE _IOR ('v',QC_IOCTLBASE+10,int) /* Get enable workaround for bugs, bitfield */ +#define VIDIOCQCSCOMPATIBLE _IOWR('v',QC_IOCTLBASE+10,int) /* Set enable workaround for bugs, bitfield */ +#define VIDIOCQCGVIDEONR _IOR ('v',QC_IOCTLBASE+11,int) /* Get videodevice number (/dev/videoX) */ +#define VIDIOCQCSVIDEONR _IOWR('v',QC_IOCTLBASE+11,int) /* Set videodevice number (/dev/videoX) */ +#define VIDIOCQCGUSERLUT _IOR ('v',QC_IOCTLBASE+12,struct qc_userlut) /* Get user-specified lookup-table correction */ +#define VIDIOCQCSUSERLUT _IOWR('v',QC_IOCTLBASE+12,struct qc_userlut) /* Set user-specified lookup-table correction */ + +#define VIDIOCQCGSTV _IOWR('v',QC_IOCTLBASE+20,int) /* Read STV chip register */ +#define VIDIOCQCSSTV _IOW ('v',QC_IOCTLBASE+20,int) /* Write STV chip register */ +#define VIDIOCQCGI2C _IOWR('v',QC_IOCTLBASE+21,int) /* Read I2C chip register */ +#define VIDIOCQCSI2C _IOW ('v',QC_IOCTLBASE+21,int) /* Write I2C chip register */ + +/* Debugging message choices */ +#define QC_DEBUGUSER (1<<0) /* Messages for interaction with user space (system calls) */ +#define QC_DEBUGCAMERA (1<<1) /* Messages for interaction with the camera */ +#define QC_DEBUGINIT (1<<2) /* Messages for each submodule initialization/deinit */ +#define QC_DEBUGLOGIC (1<<3) /* Messages for entering and failing important functions */ +#define QC_DEBUGERRORS (1<<4) /* Messages for all error conditions */ +#define QC_DEBUGADAPTATION (1<<5) /* Messages for automatic exposure control workings */ +#define QC_DEBUGCONTROLURBS (1<<6) /* Messages for sending I2C control messages via USB */ +#define QC_DEBUGBITSTREAM (1<<7) /* Messages for finding chunk codes from camera bitstream */ +#define QC_DEBUGINTERRUPTS (1<<8) /* Messages for each interrupt */ +#define QC_DEBUGMUTEX (1<<9) /* Messages for acquiring/releasing the mutex */ +#define QC_DEBUGCOMMON (1<<10) /* Messages for some common warnings */ +#define QC_DEBUGFRAME (1<<11) /* Messages related to producer-consumer in qc_frame_* functions */ +#define QC_DEBUGALL (~0) /* Messages for everything */ + +/* Compatibility choices */ +#define QC_COMPAT_16X (1<<0) +#define QC_COMPAT_DBLBUF (1<<1) +#define QC_COMPAT_TORGB (1<<2) /* Video4Linux API is buggy and doesn't specify byte order for RGB images */ +/* }}} */ + +#ifdef __KERNEL__ + +#include +#include + +#ifdef CONFIG_SMP +#define __SMP__ +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) +#define MODVERSIONS +#endif +#ifdef MODVERSIONS +#include +#endif +#endif + +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) +#include +#endif +#include +#include /* This is required for testing pte_offset_map */ +#include + +/* {{{ [fold] SECTION: user configuration */ +#define VERSION "QuickCam USB 0.6.6 $Date: 2006/11/04 08:38:14 $" +#ifndef COMPRESS +#define COMPRESS 1 /* 1=include compression support, 0=otherwise */ +#endif +#ifndef DEBUGLEVEL +#define DEBUGLEVEL QC_DEBUGCOMMON +#endif +#ifdef NDEBUG /* Enable debugging if DEBUG is defined; if (also) NDEBUG is defined, disable debugging */ +#undef DEBUG +#endif +//#define DEBUG /* Enable debug code */ +#ifdef DEBUG +#define PARANOID 1 /* Check consistency of driver state */ +#else +#define PARANOID 0 +#endif +/* Default (initial) values */ +#define DEFAULT_BGR TRUE /* Use BGR byte order by default (and torgb converts to RGB)? */ + +#define DUMPDATA 0 /* Dump data from camera to user, no conversion nor length checks (see show.c) */ +/* }}} */ +/* {{{ [fold] SECTION: general utility definitions and macros */ +#define FALSE 0 +#define TRUE (!FALSE) +typedef unsigned char Bool; +//#define BIT(x) (1<<(x)) +#define SIZE(a) (sizeof(a)/sizeof((a)[0])) +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX3(a,b,c) (MAX(a,MAX(b,c))) +#define MIN3(a,b,c) (MIN(a,MIN(b,c))) +#define CLIP(a,low,high) MAX((low),MIN((high),(a))) +#define ABS(a) ((a)>0?(a):-(a)) +#define SGN(a) ((a)<0 ? -1 : ((a)>0 ? 1 : 0)) +#define CHECK_ERROR(cond,jump,msg,args...) if (cond) { PDEBUG(msg, ## args); goto jump; } +#define GET_VENDORID(qc) ((qc)->dev->descriptor.idVendor) +#define GET_PRODUCTID(qc) ((qc)->dev->descriptor.idProduct) +/* }}} */ +/* {{{ [fold] SECTION: compatibility */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) +#error "Too old kernel. At least Linux 2.2.18 is required." +#endif + +#if LINUX_VERSION_CODE==KERNEL_VERSION(2,4,19) || LINUX_VERSION_CODE==KERNEL_VERSION(2,4,20) +#warning "Kernels 2.4.19 and 2.4.20 are buggy! Be sure to install patch from:" +#warning "http://www.ee.oulu.fi/~tuukkat/quickcam/linux-2.4.20-videodevfix.patch" +#endif + +#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,5,0) && LINUX_VERSION_CODE=KERNEL_VERSION(2,7,0) +#warning "Unsupported kernel, may or may not work. Good luck!" +#endif + +#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,4,0) && defined(CONFIG_PROC_FS) +#define HAVE_PROCFS 1 /* FIXME: I don't think there's any reason to disable procfs with 2.2.x */ +#else +#define HAVE_PROCFS 0 +#warning "procfs support disabled" +#endif + +#ifndef HAVE_VMA +#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,5,3) || (defined(RED_HAT_LINUX_KERNEL) && defined(pte_offset_map)) +/* Some RedHat 9 2.4.x patched-to-death kernels need this too */ +#define HAVE_VMA 1 +#else +#define HAVE_VMA 0 +#endif +#endif + +#if HAVE_VMA && LINUX_VERSION_CODE=KERNEL_VERSION(2,6,0) +/* Things come and go... */ +/* Used only for debugging, so this could be actually removed if needed */ +#define sem_getcount(sem) atomic_read(&(sem)->count) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +static inline int qc_usb_submit_urb(struct urb *urb) { return usb_submit_urb(urb); } +static inline struct urb *qc_usb_alloc_urb(int packets) { return usb_alloc_urb(packets); } +#undef usb_submit_urb +#undef usb_alloc_urb +#define usb_submit_urb(u,f) qc_usb_submit_urb(u) +#define usb_alloc_urb(u,f) qc_usb_alloc_urb(u) +#define URB_ISO_ASAP USB_ISO_ASAP +#endif + +#ifndef list_for_each_entry +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#undef MOD_INC_USE_COUNT +#undef MOD_DEC_USE_COUNT +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#define GET_USE_COUNT(module) 1 +#define EXPORT_NO_SYMBOLS +#endif + +/* }}} */ +/* {{{ [fold] SECTION: debugging */ +#undef PDEBUG /* undef it, just in case */ +#define POISON_VAL 0x5B + +#ifdef DEBUG + +#include +/* PDEBUG is rather heavyweight macro and should be used only for debugging--not for general messages */ +/* Based on timestamp by Roger Wolff */ +#define PDEBUG(fmt, args...) \ + do { \ + struct timeval __tv_val; \ + do_gettimeofday(&__tv_val); \ + printk(KERN_DEBUG "quickcam [%2ld.%06ld]: ", __tv_val.tv_sec%60, __tv_val.tv_usec); \ + printk(fmt, ## args); \ + printk("\n"); \ + } while(0) +#define IDEBUG_VAR char *idebug_var; +#define IDEBUG_INIT(x) do { \ + if ((x).idebug_var==((char*)&((x).idebug_var)) + 0xB967E57D) printk(KERN_CRIT __FILE__ ":%i: Init already done\n",__LINE__); \ + (x).idebug_var = ((char*)&((x).idebug_var)) + 0xB967E57D; \ +} while(0) +#define IDEBUG_TEST(x) do { \ + if ((x).idebug_var!=((char*)&((x).idebug_var)) + 0xB967E57D) printk(KERN_CRIT __FILE__ ":%i: Init missing\n",__LINE__); \ +} while(0) +#define IDEBUG_EXIT(x) do { \ + IDEBUG_TEST(x); \ + (x).idebug_var = NULL; \ + POISON(x); \ +} while(0) +#define IDEBUG_EXIT_NOPOISON(x) do { \ + IDEBUG_TEST(x); \ + (x).idebug_var = NULL; \ +} while(0) +#define TEST_BUG(condition) \ + do { \ + if ((condition)!=0) { \ + PDEBUG("Badness in %s at %s:%d", __FUNCTION__, __FILE__, __LINE__); \ + return; \ + } \ + } while (0) +#define TEST_BUGR(condition) \ + do { \ + if ((condition)!=0) { \ + PDEBUG("Badness in %s at %s:%d", __FUNCTION__, __FILE__, __LINE__); \ + return -EFAULT; \ + } \ + } while (0) +#define TEST_BUG_MSG(cond, fmt, args...) \ + do { \ + if ((cond)!=0) { \ + PDEBUG(fmt, ## args); \ + PDEBUG("Badness in %s at %s:%d", __FUNCTION__, __FILE__, __LINE__); \ + return; \ + } \ + } while (0) +#define TEST_BUGR_MSG(cond, fmt, args...) \ + do { \ + if ((cond)!=0) { \ + PDEBUG(fmt, ## args); \ + PDEBUG("Badness in %s at %s:%d", __FUNCTION__, __FILE__, __LINE__); \ + return -EFAULT; \ + } \ + } while (0) +#define POISON(obj) do { memset(&(obj),POISON_VAL,sizeof(obj)); } while(0) + +#else + +#define PDEBUG(fmt, args...) +#define IDEBUG_VAR +#define IDEBUG_INIT(x) +#define IDEBUG_TEST(x) +#define IDEBUG_EXIT(x) +#define IDEBUG_EXIT_NOPOISON(x) +#define TEST_BUG(x) +#define TEST_BUGR(x) +#define TEST_BUG_MSG(cond, fmt, args...) +#define TEST_BUGR_MSG(cond, fmt, args...) +#define POISON(obj) + +#endif /* DEBUG */ + +//gcc is buggy? This doesn't work +//#define PRINTK(lvl, fmt, args...) printk(lvl "quickcam: " fmt "\n", ## args) +#define PRINTK(lvl, fmt, args...) do { printk(lvl "quickcam: " fmt, ## args); printk("\n"); } while (0) +/* }}} */ +/* {{{ [fold] SECTION: hardware related stuff */ +#define QUICKCAM_ISOPIPE 0x81 + +/* Control register of the STV0600 ASIC */ +#define STV_ISO_ENABLE 0x1440 +#define STV_SCAN_RATE 0x1443 +#define STV_ISO_SIZE 0x15C1 +#define STV_Y_CTRL 0x15C3 +#define STV_X_CTRL 0x1680 +#define STV_REG00 0x1500 +#define STV_REG01 0x1501 +#define STV_REG02 0x1502 +#define STV_REG03 0x1503 +#define STV_REG04 0x1504 +#define STV_REG23 0x0423 + +/* Maximum frame size that any sensor can deliver */ +#define MAX_FRAME_WIDTH 360 +#define MAX_FRAME_HEIGHT 296 +/* }}} */ +/* {{{ [fold] SECTION: struct quickcam datatype and related values */ + +/* {{{ [fold] qc_sensor_data: Sensor related data (unique to each camera) */ +struct qc_sensor_data { + const struct qc_sensor *sensor; /* Autodetected when camera is plugged in */ + int maxwidth; /* Maximum size the sensor can deliver */ + int maxheight; + int width; /* Size delivered by the sensor (-1=unknown) */ + int height; + int exposure; /* Current exposure in effect (sensor-specific value, -1=unknown) */ + int rgain, ggain, bgain; /* Current gains in effect (sensor-specific values, -1=unknown) */ + unsigned int subsample : 1; /* Set into subsampling mode? */ + unsigned int compress : 1; /* Set into compressed mode? */ +}; +/* }}} */ +/* {{{ [fold] qc_i2c_data: I2C command queue for writing commands to camera */ +#define I2C_MAXCOMMANDS 16 /* Should be about 1-2 times the size of transfer buffer (=16) for maximum performance */ +#define I2C_FLAG_WORD BIT(0) /* Set if a 16-bit value is sent, otherwise 8-bit value */ +#define I2C_FLAG_BREAK BIT(1) /* Set if this is the last command in a packet */ +struct qc_i2c_data { + struct urb *urb; + struct { + u8 loval; + u8 hival; + u8 regnum; + u8 flags; + } commands[I2C_MAXCOMMANDS]; + /* 2=URB scheduled, need to schedule extra packet for QuickCam Web at completion */ + volatile int packets; /* 0=no URBs scheduled, 1=URB scheduled */ + volatile unsigned int newhead; /* Points to first free buffer position */ + volatile unsigned int head; /* Points to oldest command which was not yet flushed */ + volatile unsigned int tail; /* Points to next position which needs to be send, modified from interrupt */ + wait_queue_head_t wq; /* Woken up when all pending data is sent */ + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_isoc_data: Isochronous transfer queue control data for reading from camera */ +#define ISOC_URBS 2 /* Number of URBs to use */ +#define ISOC_PACKETS 10 /* How many isochronous data packets per URB */ +#define ISOC_PACKET_SIZE 1023 /* Max size of one packet (shouldn't be hardcoded JFC was 960) */ +struct qc_isoc_data { + struct urb *urbs[ISOC_URBS]; + unsigned char *buffer; /* Isochronous data transfer buffers */ + int errorcount; + Bool streaming; /* TRUE if URBs are allocated and submitted */ + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_stream_data: Camera data stream control data */ +struct qc_stream_data { + Bool capturing; /* Are we capturing data for a frame? */ + int frameskip; /* How frequently to capture frames? 0=each frame, 1=every other */ + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_frame_data: Raw frame (bayer/mjpeg) buffers */ +#define FRAME_BUFFERS 2 /* We are double buffering */ +#define FRAME_DATASIZE (MAX_FRAME_WIDTH*MAX_FRAME_HEIGHT) /* About 101 kilobytes (assume that compressed frame is always smaller) */ +struct qc_frame_data { + struct { + int rawdatalen; /* Number of used bytes of this frame buffer */ + } buffers[FRAME_BUFFERS]; + unsigned char *rawdatabuf; /* vmalloc'd chunk containing the all raw frame data buffers concatenated */ + int maxrawdatalen; /* Maximum amount of data we are willing to accept in bytes, */ + /* zero indicates that we are not grabbing current frame (but just throwing data away) */ + volatile unsigned int head; /* The buffer to be captured next (empty or grabbing, if full, then whole buffer is full) */ + volatile unsigned int tail; /* The buffer to be consumed next (full, unless equals head, then it is empty/grabbing) */ + spinlock_t tail_lock; /* Protects tail changes */ + volatile Bool tail_in_use; /* TRUE, when consumer is processing the frame pointed to by tail */ + + wait_queue_head_t wq; /* Processes waiting for more data in the buffer */ + volatile int waiting; /* Number of processes waiting in the wait queues */ + volatile Bool exiting; /* Set to TRUE when we want to quit */ + volatile int lost_frames; /* Increased by one for every lost (non-captured by applications) frame, reset when a frame is captured */ + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_mjpeg_data: MJPEG decoding data */ +struct qc_mjpeg_data { + int depth; /* Bits per pixel in the final RGB image: 16 or 24 */ + u8 *encV; /* Temporary buffers for holding YUV image data */ + u8 *encU; + u8 *encY; + /* yuv2rgb private data */ + void *table; + void *table_rV[256]; + void *table_gU[256]; + int table_gV[256]; + void *table_bU[256]; + void (*yuv2rgb_func)(struct qc_mjpeg_data *, u8 *, u8 *, u8 *, u8 *, void *, void *, int); + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_fmt_data: Format conversion routines private data */ +struct qc_fmt_data { + unsigned char userlut[QC_LUT_SIZE]; /* User specified fixed look-up table, initialized when camera is plugged in */ + unsigned char lut[QC_LUT_SIZE]; /* Dynamically calculated LUT, for which userlut is applied to */ +#if COMPRESS + struct qc_mjpeg_data mjpeg_data; + Bool compress; /* Was compression subsystem initialized? */ +#endif + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_capt_data: Formatted image capturing control data */ +/* qc_capt_data: Formatted image capturing control data. */ +#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH*MAX_FRAME_HEIGHT*4) /* Video Size 356x292x4 bytes for 0RGB 32 bpp mode */ +struct qc_capt_data { + unsigned char *frame; /* Final image data buffer given to application, size MAX_FRAME_SIZE (mmappable) */ + Bool settled; /* Has the picture settled after last open? */ + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_adapt_data: Automatic exposure control data */ +/* There are three different exposure control algorithms for different cases */ +struct qc_adapt_data { + int olddelta; + int oldmidvalue, midvaluesum; + int oldexposure, exposure; + int gain; + int framecounter; + enum { + EXPCONTROL_SATURATED, /* Picture is over/undersaturated, halve/double brightness */ + EXPCONTROL_NEWTON, /* Using Newton linear estimation */ + EXPCONTROL_FLOAT, /* Very near correct brightness, float exposure slightly */ + } controlalg; + IDEBUG_VAR +}; +/* }}} */ +/* {{{ [fold] qc_settings_data: User settings given by qcset or module parameters, initialized when camera is plugged in */ +struct qc_settings_data { + unsigned int keepsettings : 1; /* Keep all settings at each camera open (or reset most of them) */ + unsigned int subsample : 1; /* Normal or sub-sample (sub-sample to increase the speed) */ + unsigned int compress : 1; /* Enable compressed mode if available (higher framerate) */ + unsigned int frameskip : 4; /* How many frames to skip (higher=lower framerate) */ + unsigned int quality : 3; /* Quality of format conversion (higher=better but slower) */ + unsigned int adaptive : 1; /* Use automatic exposure control */ + unsigned int equalize : 1; /* Equalize images */ + unsigned int userlut : 1; /* Apply user-specified lookup-table */ + unsigned int retryerrors : 1; /* If errors happen when capturing an image, retry a few times? */ + unsigned int compat_16x : 1; /* Compatibility: force image size to multiple of 16 */ + unsigned int compat_dblbuf : 1; /* Compatibility: fake doublebuffering for applications */ + unsigned int compat_torgb : 1; /* Compatibility: use RGB data order, not BGR */ + unsigned int settle : 8; /* Maximum number of frames to wait image brightness to settle */ + /* Total: 25 bits */ +}; +/* }}} */ + +/* Main per-camera data structure, most important thing in whole driver */ +struct quickcam { + /* The following entries are initialized in qc_usb_init() when camera is plugged in */ + struct semaphore lock; /* Allow only one process to access quickcam at a time */ + struct list_head list; /* All cameras are in a doubly linked list */ + int users; /* User count (simultaneous open count) */ + struct usb_device *dev; /* USB device, set to NULL when camera disconnected and interrupts disabled */ + unsigned char iface; /* The interface number in the camera device we are bound to */ + Bool connected; /* Set to FALSE immediately when the camera is disconnected (even before interrupts are disabled) */ + struct video_device vdev; /* Used for registering the camera driver for Video4Linux */ + struct qc_settings_data settings; /* General user settings set with e.g. qcset */ +#if HAVE_PROCFS + struct proc_dir_entry *proc_entry; +#endif + /* The following entries are initialized in qc_v4l_init() when the camera device is opened */ + struct video_picture vpic; /* Contains the last values set by user (which is reported to user) */ + Bool vpic_pending; /* Settings in vpic were changed but are not yet in effect */ + struct video_window vwin; /* Contains the image size and position the user is expecting */ + + /* Private structures for each module, initialized in corresponding init-function */ + struct qc_i2c_data i2c_data; /* Filled when the camera is plugged in or driver loaded */ + struct qc_adapt_data adapt_data; /* Filled when the camera is plugged in or driver loaded */ + struct qc_sensor_data sensor_data; /* Mostly filled when the device is opened */ + struct qc_stream_data stream_data; /* Filled when the device is opened */ + struct qc_frame_data frame_data; /* Filled when the device is opened */ + struct qc_capt_data capt_data; /* Filled when the device is opened */ + struct qc_isoc_data isoc_data; /* Filled when the device is opened */ + struct qc_fmt_data fmt_data; /* Mostly filled when the device is opened, except for userlut */ + + u8 dmabuf[35]; /* Temporary buffer which may be used for DMA transfer */ +}; +/* }}} */ +/* {{{ [fold] SECTION: miscelleneous */ +/* Constant information related to a sensor type */ +struct qc_sensor { + char *name; + char *manufacturer; + int (*init)(struct quickcam *qc); /* Initialize sensor */ + int (*start)(struct quickcam *qc); /* Start sending image data */ + int (*stop)(struct quickcam *qc); /* Stop sending image data */ + int (*set_size)(struct quickcam *qc, unsigned int w, unsigned int h); /* Request camera to send the given image size */ + /* Set primary brightness value exp (usually exposure time) and HSV 0-65535 (usually gains) */ + int (*set_levels)(struct quickcam *qc, unsigned int exp, unsigned int gain, unsigned int hue, unsigned int sat); + int (*set_target)(struct quickcam *qc, unsigned int val); /* Set target brightness for sensor autoexposure 0-65535 */ + /* Exposure and gain control information */ + Bool autoexposure; /* Sensor has automatic exposure control */ + int adapt_gainlow; /* (0-65535) How eagerly to decrease gain when necessary */ + int adapt_gainhigh; /* (0-65535) How eagerly to increase gain when necessary */ + /* Information needed to access the sensor via I2C */ + int reg23; + unsigned char i2c_addr; + /* Identification information used for auto-detection */ + int id_reg; + unsigned char id; + int length_id; + int flag; /* May be used by sensor driver for private purposes */ +}; +/* }}} */ +/* {{{ [fold] SECTION: function prototypes */ +/* USB interface chip control */ +int qc_i2c_break(struct quickcam *qc); +int qc_i2c_wait(struct quickcam *qc); +int qc_i2c_set(struct quickcam *qc, unsigned char reg, unsigned char val); +int qc_i2c_setw(struct quickcam *qc, unsigned char reg, unsigned short val); + +int qc_stv_set(struct quickcam *qc, unsigned short reg, unsigned char val); +int qc_stv_setw(struct quickcam *qc, unsigned short reg, unsigned short val); +int qc_stv_get(struct quickcam *qc, unsigned short reg); + +/* Image format conversion routines */ +int qc_fmt_convert(struct quickcam *qc, unsigned char *src, unsigned int src_len, unsigned char *dst, unsigned int dst_len, int *midvalue); +int qc_fmt_issupported(int format); +const char *qc_fmt_getname(int format); +int qc_fmt_getdepth(int format); +int qc_fmt_init(struct quickcam *qc); +void qc_fmt_exit(struct quickcam *qc); + +int qc_mjpeg_decode(struct qc_mjpeg_data *md, unsigned char *src, int src_len, unsigned char *dst); +int qc_mjpeg_init(struct qc_mjpeg_data *md, int depth, Bool tobgr); +void qc_mjpeg_exit(struct qc_mjpeg_data *md); + +void qc_hsv2rgb(s16 hue, u16 sat, u16 val, int *red, int *green, int *blue); +int qc_get_i2c(struct quickcam *qc, const struct qc_sensor *sensor, int reg); +void qc_frame_flush(struct quickcam *qc); + +void qc_usleep(unsigned long usec); +extern int qcdebug; /* Driver debuglevel */ +/* }}} */ + +#endif /* __KERNEL__ */ + +#endif /* __LINUX_QUICKCAM_H */ --- linux-2.6.27.orig/ubuntu/qc-usb/qc-driver.c +++ linux-2.6.27/ubuntu/qc-usb/qc-driver.c @@ -0,0 +1,3410 @@ +/* Start of file */ + +/* {{{ [fold] Comments */ + +/* + * qc-usb, Logitech QuickCam video driver with V4L support + * Derived from qce-ga, linux V4L driver for the QuickCam Express and Dexxa QuickCam + * + * qc-driver.c - main driver part + * + * Copyright (C) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (C) 2002,2003 Tuukka Toivonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Cam variations of Logitech QuickCam: + P/N 861037: Sensor HDCS1000 ASIC STV0600 + P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 ("QuickCam Express") + P/N 861055: Sensor ST VV6410 ASIC STV0610 ("LEGO cam") + P/N 861075-0040: Sensor HDCS1000 ASIC + P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 (Dexxa WebCam USB) + P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 ("QuickCam Web") + + For any questions ask + qce-ga-devel@lists.sourceforge.net - about code + qce-ga-discussion@lists.sourceforge.net - about usage +*/ +/* }}} */ +/* {{{ [fold] Includes */ +#include "quickcam.h" + +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) +#include +#endif +#include + +#include "qc-memory.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include +#endif +/* }}} */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +/* Make this a bit backwards compatible... hack hack... */ +#ifndef module_param +#define module_param(a, b, c) MODULE_PARM(a, "i") +#endif +#endif + +/* {{{ [fold] Module parameters */ +MODULE_PARM_DESC(qcdebug, "Sets the debug output (bitfield)"); +int qcdebug = DEBUGLEVEL; +module_param(qcdebug, int, 0444); + +MODULE_PARM_DESC(keepsettings, "Keep picture settings across one open to another (0-1)"); +static int keepsettings = 0; +module_param(keepsettings, int, 0444); + +MODULE_PARM_DESC(settle, "Maximum number of frames to wait picture brightness to settle (0-255)"); +static int settle = 0; +module_param(settle, int, 0444); + +/* Subsampling is used to allow higher scan rate with smaller images. */ +MODULE_PARM_DESC(subsample, "Sets subsampling (0-1)"); +static int subsample = 0; /* normal or sub-sample (sub-sample to increase the speed) */ +module_param(subsample, int, 0444); + +MODULE_PARM_DESC(compress, "Enable compressed mode (0-1)"); +static int compress = 0; /* Enable compressed mode if available (higher framerate) */ +module_param(compress, int, 0444); + +MODULE_PARM_DESC(frameskip, "How frequently capture frames (0-10)"); +static int frameskip = 0; +module_param(frameskip, int, 0444); + +MODULE_PARM_DESC(quality, "Sets the picture quality (0-5)"); +static int quality = 5; /* 5 = generalized adjustable Pei-Tam method */ +module_param(quality, int, 0444); + +MODULE_PARM_DESC(adaptive, "Automatic adaptive brightness control (0-1)"); +static int adaptive = 1; +module_param(adaptive, int, 0444); + +MODULE_PARM_DESC(equalize, "Equalize image (0-1)"); +static int equalize = 0; /* Disabled by default */ +module_param(equalize, int, 0444); + +MODULE_PARM_DESC(userlut, "Apply user-specified lookup-table (0-1)"); +static int userlut = 0; /* Disabled by default */ +module_param(userlut, int, 0444); + +MODULE_PARM_DESC(retryerrors, "Retry if image capture fails, otherwise return error code (0-1)"); +static int retryerrors = 1; /* Enabled by default */ +module_param(retryerrors, int, 0444); + +/* Bug in Xvideo(?): if the width is not divisible by 8 and Xvideo is used, the frame is shown wrongly */ +MODULE_PARM_DESC(compatible, "Enable workaround for bugs in application programs (bitfield)"); +static int compatible = 0; /* Disabled by default */ +module_param(compatible, int, 0444); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5) +MODULE_PARM_DESC(video_nr, "Set videodevice number (/dev/videoX)"); +static int video_nr = -1; +module_param(video_nr, int, 0444); +/* video_nr option allows to specify a certain /dev/videoX device */ +/* (like /dev/video0 or /dev/video1 ...) */ +/* for autodetect first available use video_nr=-1 (defaultvalue) */ +#endif +/* }}} */ +/* {{{ [fold] Miscellaneous data */ +#ifndef MODULE_LICENSE /* Appeared in 2.4.10 */ +#ifdef MODULE +#define MODULE_LICENSE(license) \ +static const char __module_license[] __attribute__((section(".modinfo"))) = \ + "license=" license +#else +#define MODULE_LICENSE(license) +#endif +#endif + +MODULE_SUPPORTED_DEVICE("video"); +MODULE_DESCRIPTION("Logitech QuickCam USB driver"); +MODULE_AUTHOR("See README"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; + +static const int min_framewidth = 32; /* Minimum image size we allow delivering to user application */ +static const int min_frameheight = 32; + +static const char qc_proc_name[] = "video/quickcam"; +#define qc_name (&qc_proc_name[6]) + +static struct usb_device_id qc_device_table[] = { + { USB_DEVICE(0x046D, 0x0840) }, /* QuickCam Express */ + { USB_DEVICE(0x046D, 0x0850) }, /* LEGO cam / QuickCam Web */ + { USB_DEVICE(0x046D, 0x0870) }, /* Dexxa WebCam USB */ + { USB_DEVICE(0x046D, 0x08F6) }, /* Logitech QuickCam Messenger */ + { } +}; +MODULE_DEVICE_TABLE(usb, qc_device_table); + +extern const struct qc_sensor qc_sensor_pb0100; +extern const struct qc_sensor qc_sensor_hdcs1000; +extern const struct qc_sensor qc_sensor_hdcs1020; +extern const struct qc_sensor qc_sensor_vv6410; + +static const struct qc_sensor *sensors[] = { + &qc_sensor_hdcs1000, + &qc_sensor_hdcs1020, + &qc_sensor_pb0100, + &qc_sensor_vv6410, +}; + +static LIST_HEAD(quickcam_list); /* Linked list containing all QuickCams */ +static DECLARE_MUTEX(quickcam_list_lock); /* Always lock first quickcam_list_lock, then qc->lock */ + +/* Default values for user-specified lookup-table; may be overwritten by user */ +static unsigned char userlut_contents[QC_LUT_SIZE] = { + /* Red */ + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, + 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, + 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87, + 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, + 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, + 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, + 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159, + 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166, + 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173, + 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179, + 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186, + 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192, + 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197, + 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204, + 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209, + 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, + 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219, + 220, 220, 221, 221, + + /* Green */ + 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, + 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, + 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97, + 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113, + 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, + 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, + 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, + 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, + 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, + 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, + 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, + 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, + 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, + 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, + 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, + 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, + 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, + 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, + 245, 245, 246, 246, + + /* Blue */ + 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, + 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, + 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106, + 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124, + 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, + 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, + 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, + 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, + 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203, + 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212, + 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220, + 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, + 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235, + 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242, + 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249, + 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255 +}; + +static void qc_usb_exit(struct quickcam *qc); +static int qc_capt_init(struct quickcam *qc); +static void qc_capt_exit(struct quickcam *qc); +static int qc_capt_get(struct quickcam *qc, unsigned char **frame); +static int qc_isoc_init(struct quickcam *qc); +static void qc_isoc_exit(struct quickcam *qc); +/* }}} */ + +/* {{{ [fold] **** Miscellaneous functions ************************************** */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) +/* {{{ [fold] usb_kill_urb(struct urb *urb) */ +/* Unlink URB synchronously (usb_unlink_urb may not be synchronous). + * Note: at this moment the URB completion handler must not resubmit the same URB. + */ +static void qc_usb_kill_urb(struct urb *urb) { + int r; + while ((r=usb_unlink_urb(urb)) == -EBUSY) { + /* The URB is not anymore linked (status!=-EINPROGRESS) but + * usb_unlink_urb() was asynchronous and URB's completion handler still will run */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout( (HZ/100)==0 ? 1 : HZ/100); + } + /* if (r!=-EBUSY), + * usb_unlink_urb() called synchronously the completion handler and + * there's no need to wait or anything else */ + if (r) PDEBUG("qc_usb_kill_urb(%p): r=%i", urb, r); +} +#undef usb_kill_urb +#define usb_kill_urb(urb) qc_usb_kill_urb(urb) +/* }}} */ +#endif +/* {{{ [fold] qc_usleep(long usec) */ +void qc_usleep(unsigned long usec) +{ + wait_queue_head_t wq; + init_waitqueue_head(&wq); + interruptible_sleep_on_timeout(&wq, usec*HZ/1000000); +} +/* }}} */ +/* {{{ [fold] int qc_get_i2c(struct quickcam *qc, const struct qc_sensor *sensor, int reg) */ +/* Read a sensor byte or word wide register value via STV0600 I2C bus + * qc_i2c_init() must be called first! + */ +int qc_get_i2c(struct quickcam *qc, const struct qc_sensor *sensor, int reg) +{ + struct usb_device *dev = qc->dev; + int ret; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_get_i2c(qc=%p,sensor=%p,reg=0x%04X)",qc,sensor,reg); + TEST_BUGR(dev==NULL); + if (sizeof(qc->dmabuf)<35) BUG(); + + /* We need here extra write to the STV register before reading the I2C register */ + /* Also wait until there are no pending control URB requests */ + if ((ret = qc_stv_set(qc, STV_REG23, sensor->reg23))<0) goto fail; + + memset(qc->dmabuf, 0, 35); + qc->dmabuf[0] = reg; + qc->dmabuf[0x20] = sensor->i2c_addr; + qc->dmabuf[0x21] = 0; /* 0+1 = 1 value, one byte or word wide register */ + qc->dmabuf[0x22] = 3; /* Read I2C register */ + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x04, + 0x40, + 0x1400, 0, /* Write I2C register address, 35 bytes */ + qc->dmabuf, 0x23, 3*HZ); + if (ret < 0) goto fail; + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + 0x04, + 0xC0, + 0x1410, 0, /* Read register contents from I2C, 1 or 2 bytes */ + qc->dmabuf, sensor->length_id, 3*HZ); + if (ret < 0) goto fail; + ret = qc->dmabuf[0]; + if (sensor->length_id>1) ret |= qc->dmabuf[1]<<8; /* Assume LSB is always first from data received via USB */ + if (qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_get_i2c(reg=0x%04X) = %04X", reg, ret); + return ret; + +fail: PDEBUG("qc_get_i2c failed, code=%i",ret); + return ret; +} +/* }}} */ +/* {{{ [fold] int qc_stv_set(struct quickcam *qc, unsigned short reg, unsigned char val) */ +/* + * Set one byte register in the STV-chip. qc_i2c_init() must be called first! + */ +int qc_stv_set(struct quickcam *qc, unsigned short reg, unsigned char val) +{ + int ret; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_set(qc=%p,reg=0x%04X,val=%u)",qc,(int)reg,(int)val); + TEST_BUGR(qc==NULL); + if (sizeof(qc->dmabuf)<1) BUG(); + qc_i2c_wait(qc); /* Wait until no pending commands from qc_i2c_* */ + qc->dmabuf[0] = val; + ret = usb_control_msg(qc->dev, usb_sndctrlpipe(qc->dev, 0), + 0x04, /* Request */ + 0x40, /* RequestType */ + reg, 0, /* Value, Index */ + qc->dmabuf, 1, 3*HZ); + if ((qcdebug&QC_DEBUGERRORS || qcdebug&QC_DEBUGLOGIC) && ret<0) PDEBUG("Failed qc_stv_set()=%i", ret); + if (ret<0) return ret; + return 0; +} +/* }}} */ +/* {{{ [fold] int qc_stv_get(struct quickcam *qc, unsigned short reg) */ +/* + * Read one byte register in the STV-chip. qc_i2c_init() must be called first! + * Return the unsigned register value or negative error code on error. + */ +int qc_stv_get(struct quickcam *qc, unsigned short reg) +{ + int ret; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_get(qc=%p,reg=0x%04X)",qc,(int)reg); + TEST_BUGR(qc==NULL); + if (sizeof(qc->dmabuf)<1) BUG(); + qc_i2c_wait(qc); /* Wait until no pending commands from qc_i2c_* */ + ret = usb_control_msg(qc->dev, usb_rcvctrlpipe(qc->dev, 0), + 0x04, /* Request */ + 0xC0, /* RequestType */ + reg, 0, /* Value, Index */ + qc->dmabuf, 1, 3*HZ); + if ((qcdebug&QC_DEBUGERRORS || qcdebug&QC_DEBUGLOGIC) && ret<0) PDEBUG("Failed qc_stv_get()=%i", ret); + if (ret<0) return ret; + if (qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_get(reg=0x%04X)=%02X", reg, qc->dmabuf[0]); + return qc->dmabuf[0]; +} +/* }}} */ +/* {{{ [fold] int qc_stv_setw(struct quickcam *qc, unsigned short reg, unsigned short val) */ +/* + * Set two byte register in the STV-chip. qc_i2c_init() must be called first! + * "w" means either "word" or "wide", depending on your religion ;) + */ +int qc_stv_setw(struct quickcam *qc, unsigned short reg, unsigned short val) +{ + int ret; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_setw(qc=%p,reg=0x%04X,val=%i)",qc,(int)reg,(int)val); + TEST_BUGR(qc==NULL); + if (sizeof(qc->dmabuf)<2) BUG(); + qc_i2c_wait(qc); + qc->dmabuf[0] = val & 0xFF; + qc->dmabuf[1] = (val >> 8) & 0xFF; + ret = usb_control_msg(qc->dev, usb_sndctrlpipe(qc->dev, 0), + 0x04, + 0x40, + reg, 0, + qc->dmabuf, 2, 3*HZ); + if ((qcdebug&QC_DEBUGERRORS || qcdebug&QC_DEBUGLOGIC) && ret<0) PDEBUG("Failed qc_stv_setw()=%i", ret); + if (ret<0) return ret; + return 0; +} +/* }}} */ +/* {{{ [fold] void qc_hsv2rgb(s16 hue, u16 sat, u16 val, int *red, int *green, int *blue) */ +/* Convert HSI (hue, saturation, intensity) to RGB (red, green, blue). + * All input and output values are 0..65535. + * Hue is actually signed, so it is -32768..32767, but this is equivalent + * since it is the angle around full circle (0=Red, 21845=Green, 43690=Blue). + * Based on libgimp, converted to 16.16 fixed point by tuukkat. + */ +void qc_hsv2rgb(s16 hue, u16 sat, u16 val, int *red, int *green, int *blue) +{ + unsigned int segment, valsat; + signed int h = (u16)hue; + unsigned int s = (sat<32768) ? 0 : (sat-32768)*2; /* 32768 or less = no saturation */ + unsigned int v = val; /* value = intensity */ + unsigned int p; + +#if 1 /* Make common case more efficient */ + if (s == 0) { + *red = v; + *green = v; + *blue = v; + return; + } +#endif + segment = (h + 10923) & 0xFFFF; + segment = segment*3 >> 16; /* 0..2: 0=R, 1=G, 2=B */ + hue -= segment * 21845; /* -10923..10923 */ + h = hue; + h *= 3; + valsat = v*s >> 16; /* 0..65534 */ + p = v - valsat; + if (h>=0) { + unsigned int t = v - (valsat * (32769 - h) >> 15); + switch (segment) { + default: + PDEBUG("hsi2rgb: this can never happen!"); + case 0: /* R-> */ + *red = v; + *green = t; + *blue = p; + break; + case 1: /* G-> */ + *red = p; + *green = v; + *blue = t; + break; + case 2: /* B-> */ + *red = t; + *green = p; + *blue = v; + break; + } + } else { + unsigned int q = v - (valsat * (32769 + h) >> 15); + switch (segment) { + default: + PDEBUG("hsi2rgb: this can never happen!"); + case 0: /* ->R */ + *red = v; + *green = p; + *blue = q; + break; + case 1: /* ->G */ + *red = q; + *green = v; + *blue = p; + break; + case 2: /* ->B */ + *red = p; + *green = q; + *blue = v; + break; + } + } + //PDEBUG("hue=%i sat=%i val=%i segment=%i h=%i r=%i g=%i b=%i",hue,sat,val, segment,h, *red,*green,*blue); +} + +/* }}} */ +/* {{{ [fold] int qc_lock(struct quickcam *qc) */ +/* Takes a lock on quickcam_list_lock and verifies that the given qc is available */ +/* Returns 0 on success in which case the lock must be freed later or negative error code */ +static int qc_lock(struct quickcam *qc) +{ + struct quickcam *q; + + if (down_interruptible(&quickcam_list_lock)) return -ERESTARTSYS; + + /* Search for the device in the list of plugged quickcams (this prevents a race condition) */ + list_for_each_entry(q, &quickcam_list, list) { + if (q == qc) break; /* Found it? */ + } + if (q != qc) { + PDEBUG("can not find the device to open"); + up(&quickcam_list_lock); + return -ENODEV; + } + return 0; +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_i2c: I2C URB messaging routines (qc_i2c_*) ************* */ + +/* We have here a quite typical producer-consumer scheme: + * URB interrupt handler routine consumes i2c data, while + * kernel mode processes create more of it. + * Ref: Linux Device Drivers, Alessandro Rubini et al, 2nd edition, pg. 279 + * "Using Circular Buffers" + */ + +static const int qc_i2c_maxbufsize = 0x23; + +/* {{{ [fold] (private) qc_i2c_nextpacket(struct quickcam *qc) */ +/* Fill URB and submit it, if there are more data to send + * Consume data from "commands" array. May be called from interrupt context. + * Return standard error code. + */ +static int qc_i2c_nextpacket(struct quickcam *qc) +{ + struct qc_i2c_data *id = &qc->i2c_data; + struct urb *urb = id->urb; + u8 *tb = urb->transfer_buffer, flags; + struct usb_ctrlrequest *cr = (struct usb_ctrlrequest *)urb->setup_packet; + unsigned int newtail, length, regnum, i, j; + signed int r; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_i2c_nextpacket(quickcam=%p), tail=%i, head=%i, interrupt=%i",qc,id->tail,id->head,(int)in_interrupt()); + IDEBUG_TEST(*id); + + if (!qc->connected) { + /* Device was disconnected, cancel all pending packets and return */ + id->tail = id->head = id->newhead = 0; + id->packets = 0; + return -ENODEV; + } + + newtail = id->tail; /* First data to fetch */ + if (id->packets<=1 && newtail==id->head) { /* packets==0 or 1: no extra URB need to be scheduled */ + if (qcdebug&QC_DEBUGCONTROLURBS) PDEBUG("No more control URBs to send"); + r = 0; + goto nourbs; + } + if (id->packets<=1) { + /* Collect data from circular buffer to URB transfer buffer */ + /* Now id->tail!=id->head: there's at least one packet to send */ + TEST_BUGR(newtail==id->head); + id->packets = 1; + if (GET_PRODUCTID(qc)==0x0850) id->packets = 2; + regnum = 0x0400; + length = qc_i2c_maxbufsize; + + i = 0; /* Transfer buffer position */ + if (!(id->commands[newtail].flags & I2C_FLAG_WORD)) { + /* Normal byte-wide register write */ + if (qcdebug&QC_DEBUGCONTROLURBS) PDEBUG("Setting byte-wide registers"); + do { + tb[i] = id->commands[newtail].regnum; + tb[i+0x10] = id->commands[newtail].loval; + flags = id->commands[newtail].flags; + i++; + newtail = (newtail + 1) % I2C_MAXCOMMANDS; /* Next data to fetch */ + if (flags & I2C_FLAG_BREAK) break; /* Start new packet */ + if (newtail == id->head) break; /* No more data? */ + if (i > 0x0F) break; /* Transfer buffer full? */ + if (id->commands[newtail].flags & I2C_FLAG_WORD) break; + } while (TRUE); +/*if (flags&I2C_FLAG_BREAK) PDEBUG("breaking!!!!!!!!!!"); +{ +int mm; +for(mm=0;mmcommands[newtail].regnum; + tb[i*2+0x10] = id->commands[newtail].loval; + tb[i*2+0x11] = id->commands[newtail].hival; + flags = id->commands[newtail].flags; + i++; + newtail = (newtail + 1) % I2C_MAXCOMMANDS; /* Next data to fetch */ + if (flags & I2C_FLAG_BREAK) break; /* Start new packet */ + if (newtail == id->head) break; /* No more data? */ + if (i > 0x07) break; /* Transfer buffer full? */ + if (!(id->commands[newtail].flags & I2C_FLAG_WORD)) break; + } while (TRUE); + for (j=i*2; j<0x10; j++) tb[j+0x10] = 0; /* Zero out unused register values just to be sure */ + } + for (j=i; j<0x10; j++) tb[j] = 0; /* Zero out unused register addresses just to be sure */ + tb[0x20] = qc->sensor_data.sensor->i2c_addr; + tb[0x21] = i-1; /* Number of commands to send - 1 */ + tb[0x22] = 1; /* Write cmd, 03 would be read. */ + id->tail = newtail; + if (qcdebug&QC_DEBUGCONTROLURBS) PDEBUG("sending i2c packet, cmds=%i, reg0=%02X, val0=%02X",tb[0x21]+1,tb[0],tb[0x10]); + } else { + /* id->packets==2: send extra packet for QuickCam Web */ + if (qcdebug&QC_DEBUGCONTROLURBS) PDEBUG("sending finalization packet"); + id->packets = 1; + regnum = 0x1704; + length = 1; + tb[0] = 1; + } + urb->dev = qc->dev; /* 2.4.x zeroes urb->dev after submission */ + urb->pipe = usb_sndctrlpipe(qc->dev, 0); + urb->transfer_buffer_length = length; + cr->wValue = cpu_to_le16(regnum); + cr->wLength = cpu_to_le16(length); + r = usb_submit_urb(urb,GFP_ATOMIC); + CHECK_ERROR(r<0, nourbs, "Failed qc_i2c_nextpacket()=%i", r); + return 0; + +nourbs: id->packets = 0; /* No more URBs are scheduled */ + wake_up(&id->wq); //FIXME: race condition: now packets=0, so id could be freed and wake_up do oops + return r; +} +/* }}} */ +/* {{{ [fold] (private) qc_i2c_handler(struct urb *urb) */ +/* This is URB completion handler and is called in interrupt context. + * For each submitted URB, this function is guaranteed to be called exactly once. + * This function may not be called reentrantly for the same qc (should be ok, IRQs don't nest). + * It will resubmit the same URB, if + * - The previous URB completed without error + * - Camera is still connected (qc->connected == TRUE) + * - There is still commands to be sent in commands buffer or pid=0x850 and finalization packet is not yet sent. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void qc_i2c_handler(struct urb *urb, struct pt_regs *ptregs) +#else +static void qc_i2c_handler(struct urb *urb) +#endif +{ + struct quickcam *qc = urb->context; + + if (qcdebug&QC_DEBUGINTERRUPTS) PDEBUG("[INTR] qc_i2c_handler(urb=%p)",urb); + TEST_BUG(urb==NULL); + TEST_BUG(qc==NULL); + IDEBUG_TEST(qc->i2c_data); + if (urb->status<0) { + switch (urb->status) { + default: + /* Seen here: ECONNABORTED 103 Software caused connection abort */ + PRINTK(KERN_ERR,"Unhandled control URB error %i",urb->status); + case -EPROTO: /* Bitstuff error or unknown USB error */ + case -EILSEQ: /* CRC mismatch */ + case -ETIMEDOUT: /* Transfer timed out */ + case -EREMOTEIO: /* Short packet detected */ + case -EPIPE: /* Babble detect or endpoint stalled */ + /* We could try resubmitting the URB here */ + case -ENOENT: /* URB was unlinked */ + case -ENODEV: /* Device was removed */ + case -ECONNRESET: /* Asynchronous unlink, should not happen */ + PRINTK(KERN_ERR,"Control URB error %i",urb->status); + qc->i2c_data.packets = 0; /* Don't schedule more URBs */ + wake_up(&qc->i2c_data.wq); + return; + } + } + qc_i2c_nextpacket(qc); +} +/* }}} */ +/* {{{ [fold] qc_i2c_flush(struct quickcam *qc) */ +/* Allow all register settings set earlier to be scheduled and sent to camera */ +static int qc_i2c_flush(struct quickcam *qc) +{ + struct qc_i2c_data *id = &qc->i2c_data; + int r = 0; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_i2c_flush(quickcam=%p,regs=%i)",qc, + (id->newhead+I2C_MAXCOMMANDS-id->head)%I2C_MAXCOMMANDS); + IDEBUG_TEST(*id); + id->head = id->newhead; + if (id->packets==0) /* Schedule URB if there aren't any in progress */ + r = qc_i2c_nextpacket(qc); + return r; +} +/* }}} */ +/* {{{ [fold] qc_i2c_wait(struct quickcam *qc) */ +/* Wait until all previosly set registers are set or abort all transmissions + * and return error code. + * After this function returns, there will not be uncompleted I2C URBs. + */ +int qc_i2c_wait(struct quickcam *qc) +{ + struct qc_i2c_data *id = &qc->i2c_data; + int r; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_i2c_wait(quickcam=%p)",qc); + TEST_BUGR(in_interrupt()); + TEST_BUGR(qc==NULL); + IDEBUG_TEST(*id); + + if (!qc->connected) goto cancel; + r = qc_i2c_flush(qc); + if (r>=0) r = wait_event_interruptible(id->wq, id->packets==0); + if (r<0) goto cancel; + return 0; + +cancel: if (qcdebug&QC_DEBUGLOGIC) PDEBUG("Canceling pending URB %p, packets=%i", id->urb, id->packets); + PDEBUG("i2c_cancel: qc=%p, id=%p",qc,id); + PDEBUG("i2c_cancel: id->urb=%p", id->urb); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + if (qc->connected) { + PDEBUG("i2c_cancel: id->urb->dev=%p", id->urb->dev); + if (id->urb->dev!=NULL) { + PDEBUG("i2c_cancel: id->urb->dev->bus=%p", id->urb->dev->bus); + if (id->urb->dev->bus!=NULL) { + PDEBUG("i2c_cancel: id->urb->dev->bus->op=%p", id->urb->dev->bus->op); + //PDEBUG("id->urb->dev->bus->op->unlink=%p", id->urb->dev->bus->op->unlink); + } + } + } +#endif + /* Cancel URB if it is in progress or in completion handler */ + if (id->packets > 0) usb_kill_urb(id->urb); + TEST_BUGR_MSG(id->packets!=0, "i2c_wait: packets=%i", id->packets); + return 0; +} +/* }}} */ +/* {{{ [fold] (private) qc_i2c_set0(struct quickcam *qc, unsigned char regnum, unsigned char loval, unsigned char hival, int flags) */ +/* Called from qc_i2c_set and qc_i2c_setw, should not be called elsewhere */ +static int qc_i2c_set0(struct quickcam *qc, unsigned char regnum, unsigned char loval, unsigned char hival, int flags) +{ + struct qc_i2c_data *id = &qc->i2c_data; + unsigned int newhead; + signed int r; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_i2c_set0(quickcam=%p,reg=%02X,val=%02X%02X)",qc,regnum,hival,loval); + TEST_BUGR(qc==NULL); + IDEBUG_TEST(*id); + newhead = id->newhead; + id->commands[newhead].loval = loval; + id->commands[newhead].hival = hival; + id->commands[newhead].regnum = regnum; + id->commands[newhead].flags = flags; + newhead = (newhead + 1) % I2C_MAXCOMMANDS; + if (newhead == id->tail) { /* If buffer is full, wait until it's empty */ + if (qcdebug&QC_DEBUGCONTROLURBS) PDEBUG("i2c buffer is full, waiting"); + r = qc_i2c_wait(qc); + if (r<0) return r; + } + TEST_BUGR(newhead==id->tail); /* no i2c buffer space but nothing to send!!! */ + id->newhead = newhead; + return 0; +} +/* }}} */ +/* {{{ [fold] qc_i2c_set(struct quickcam *qc, unsigned char reg, unsigned char val) */ +/* Set an I2C register to desired value */ +/* (queue setting to be sent later when qc_i2c_flush() is called) */ +inline int qc_i2c_set(struct quickcam *qc, unsigned char reg, unsigned char val) +{ + return qc_i2c_set0(qc, reg, val, 0, 0); +} +/* }}} */ +/* {{{ [fold] qc_i2c_setw(struct quickcam *qc, unsigned char reg, unsigned short val) */ +/* Set a two-byte (word length) I2C register to desired value (queue setting to be sent later) */ +/* (queue setting to be sent later when qc_i2c_flush() is called) */ +inline int qc_i2c_setw(struct quickcam *qc, unsigned char reg, unsigned short val) +{ + return qc_i2c_set0(qc, reg, val & 0xFF, (val >> 8) & 0xFF, I2C_FLAG_WORD); +} +/* }}} */ +/* {{{ [fold] qc_i2c_break(struct quickcam *qc) */ +/* The next register written will be sent in another packet */ +int qc_i2c_break(struct quickcam *qc) +{ + struct qc_i2c_data *id = &qc->i2c_data; + unsigned int prevhead; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_i2c_break(quickcam=%p)",qc); + TEST_BUGR(qc==NULL); + IDEBUG_TEST(*id); + /* We access an entry that may be already submitted and even finished */ + /* But it should not harm */ + prevhead = (id->newhead + I2C_MAXCOMMANDS - 1) % I2C_MAXCOMMANDS; + id->commands[prevhead].flags |= I2C_FLAG_BREAK; + barrier(); + return qc_i2c_flush(qc); +} +/* }}} */ +/* {{{ [fold] qc_i2c_init(struct quickcam *qc) */ +/* Initialize structures and hardware for I2C communication */ +static int qc_i2c_init(struct quickcam *qc) +{ + struct qc_i2c_data *id = &qc->i2c_data; + struct urb *urb; + struct usb_ctrlrequest *cr; + int r = -ENOMEM; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_i2c_init(quickcam=%p)",qc); + TEST_BUGR(qc==NULL); + + id->tail = id->head = id->newhead = 0; /* Next position to be filled and sent is 0 */ + id->packets = 0; + init_waitqueue_head(&id->wq); + + /* Allocate an URB and associated buffers and fill them */ + urb = id->urb = usb_alloc_urb(0,GFP_KERNEL); + if (!urb) goto fail1; + cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + urb->setup_packet = (unsigned char *)cr; + if (!cr) goto fail2; + urb->transfer_buffer = kmalloc(qc_i2c_maxbufsize*sizeof(u8), GFP_KERNEL); /* Allocate maximum ever needed */ + if (!urb->transfer_buffer) goto fail3; + urb->complete = qc_i2c_handler; + urb->context = qc; +#if (LINUX_VERSION_CODEtimeout = 3*HZ; /* 1 s */ +#endif + cr->bRequestType = 0x40; + cr->bRequest = 0x04; + cr->wIndex = 0; + IDEBUG_INIT(*id); + return 0; + +fail3: kfree(cr); +fail2: usb_free_urb(urb); + POISON(id->urb); +fail1: return r; +} +/* }}} */ +/* {{{ [fold] qc_i2c_exit(struct quickcam *qc) */ +/* Close messaging, free up memory, stop messaging */ +static void qc_i2c_exit(struct quickcam *qc) +{ + struct qc_i2c_data *id = &qc->i2c_data; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_i2c_exit(qc=%p)",qc); + TEST_BUG(qc==NULL); + qc_i2c_wait(qc); + kfree(id->urb->setup_packet); + kfree(id->urb->transfer_buffer); + POISON(id->urb->setup_packet); + POISON(id->urb->transfer_buffer); + usb_free_urb(id->urb); + IDEBUG_EXIT(*id); +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_proc: /proc interface *********************************** */ +#if HAVE_PROCFS + +static struct proc_dir_entry *qc_proc_entry = NULL; /* Initialization should not be necessary, but just in case... */ + +/* {{{ [fold] qc_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) */ +static inline const char *qc_proc_yesno(Bool b) +{ + return b ? "Yes" : "No"; +} + +static int qc_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + struct quickcam *qc = data; + char *out = page; + int len; + + if (qc_lock(qc) < 0) return 0; + + out += sprintf(out, "\tGeneral driver status\n"); + out += sprintf(out, "Driver version : %s\n", VERSION); + out += sprintf(out, "Kernel version : %s\n", UTS_RELEASE); + if (qc->dev!=NULL) { + out += sprintf(out, "Device Id : %04X:%04X\n", (int)GET_VENDORID(qc), (int)GET_PRODUCTID(qc)); + out += sprintf(out, "USB bus number : %i\n", qc->dev->bus->busnum); + } + out += sprintf(out, "Users : %i\n", qc->users); + out += sprintf(out, "Connected : %s\n", qc_proc_yesno(qc->connected)); + + out += sprintf(out, "\n\tPicture settings set by user\n"); + out += sprintf(out, "Brightness : %d\n", (int)qc->vpic.brightness); + out += sprintf(out, "Hue : %d\n", (int)qc->vpic.hue); + out += sprintf(out, "Color : %d\n", (int)qc->vpic.colour); + out += sprintf(out, "Contrast : %d\n", (int)qc->vpic.contrast); + out += sprintf(out, "Whiteness : %d\n", (int)qc->vpic.whiteness); + if (qc->users > 0) { + out += sprintf(out, "Depth : %d\n", (int)qc->vpic.depth); + out += sprintf(out, "Palette : %s\n", qc_fmt_getname(qc->vpic.palette)); + } + + if (qc->users > 0) { + out += sprintf(out, "\n\tOutput window\n"); + out += sprintf(out, "Width : %d\n", (int)qc->vwin.width); + out += sprintf(out, "Height : %d\n", (int)qc->vwin.height); + } + + out += sprintf(out, "\n\tSensor\n"); + out += sprintf(out, "Type : %s\n", qc->sensor_data.sensor->name); + out += sprintf(out, "Manufacturer : %s\n", qc->sensor_data.sensor->manufacturer); + if (qc->users > 0) { + out += sprintf(out, "Maximum width : %d\n", qc->sensor_data.maxwidth); + out += sprintf(out, "Maximum height : %d\n", qc->sensor_data.maxheight); + out += sprintf(out, "Current width : %d\n", qc->sensor_data.width); + out += sprintf(out, "Current height : %d\n", qc->sensor_data.height); + } + + out += sprintf(out, "\n\tI2C command stream\n"); + out += sprintf(out, "Scheduled packets: %d\n", qc->i2c_data.packets); + out += sprintf(out, "Packets on queue : %d\n", (I2C_MAXCOMMANDS + qc->i2c_data.head - qc->i2c_data.tail) % I2C_MAXCOMMANDS); + + if (qc->users > 0) { + out += sprintf(out, "\n\tIsochronous data stream\n"); + out += sprintf(out, "Stream enabled : %s\n", qc_proc_yesno(qc->isoc_data.streaming)); + out += sprintf(out, "Transfer errors : %d\n", qc->isoc_data.errorcount); + + out += sprintf(out, "\n\tFrame buffering\n"); + out += sprintf(out, "Frames on queue : %d\n", (FRAME_BUFFERS + qc->frame_data.head - qc->frame_data.tail) % FRAME_BUFFERS); + out += sprintf(out, "Capturing : %s\n", qc_proc_yesno(qc->stream_data.capturing)); + out += sprintf(out, "Waiting processes: %d\n", qc->frame_data.waiting); + } + + out += sprintf(out, "\n\tAutomatic exposure control\n"); + out += sprintf(out, "Picture intensity: %d\n", qc->adapt_data.oldmidvalue); + out += sprintf(out, "Exposure setting : %d\n", qc->adapt_data.exposure); + out += sprintf(out, "Gain setting : %d\n", qc->adapt_data.gain); + out += sprintf(out, "Delta value : %d\n", qc->adapt_data.olddelta); + out += sprintf(out, "Control algorithm: "); + switch (qc->adapt_data.controlalg) { + case EXPCONTROL_SATURATED: out += sprintf(out, "Saturated\n"); break; + case EXPCONTROL_NEWTON: out += sprintf(out, "Newton\n"); break; + case EXPCONTROL_FLOAT: out += sprintf(out, "Float\n"); break; + default: out += sprintf(out, "?\n"); break; + } + + out += sprintf(out, "\n\tDefault settings\n"); + out += sprintf(out, "Debug : 0x%02X\n", qcdebug); + out += sprintf(out, "Keep settings : %s\n", qc_proc_yesno(qc->settings.keepsettings)); + out += sprintf(out, "Settle max frames: %i\n", qc->settings.settle); + out += sprintf(out, "Subsampling : %s\n", qc_proc_yesno(qc->settings.subsample)); + out += sprintf(out, "Compress : %s\n", qc_proc_yesno(qc->settings.compress)); + out += sprintf(out, "Frame skipping : %i\n", qc->settings.frameskip); + out += sprintf(out, "Image quality : %i\n", qc->settings.quality); + out += sprintf(out, "Adaptive : %s\n", qc_proc_yesno(qc->settings.adaptive)); + out += sprintf(out, "Equalize : %s\n", qc_proc_yesno(qc->settings.equalize)); + out += sprintf(out, "User lookup-table: %s\n", qc_proc_yesno(qc->settings.userlut)); + out += sprintf(out, "Retryerrors : %s\n", qc_proc_yesno(qc->settings.retryerrors)); + out += sprintf(out, "Compatible 16x : %s\n", qc_proc_yesno(qc->settings.compat_16x)); + out += sprintf(out, "Compatible DblBuf: %s\n", qc_proc_yesno(qc->settings.compat_dblbuf)); + out += sprintf(out, "Compatible ToRgb : %s\n", qc_proc_yesno(qc->settings.compat_torgb)); + + up(&quickcam_list_lock); + + len = out - page; + len -= off; + if (len < count) { + *eof = 1; + if (len <= 0) return 0; + } else + len = count; + *start = page + off; + return len; +} +/* }}} */ +/* {{{ [fold] qc_proc_write(struct file *file, const char *buffer, unsigned long count, void *data) */ +static int qc_proc_write(struct file *file, const char *buffer, unsigned long count, void *data) +{ + /* we don't support this....yet? Might replace qcset some day */ + return -EINVAL; +} +/* }}} */ +/* {{{ [fold] qc_proc_create(struct quickcam *qc) */ +/* Called for each camera plugged in, create file containing information of the camera */ +static int qc_proc_create(struct quickcam *qc) +{ + char name[9]; + struct proc_dir_entry *entry; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_proc_create(quickcam=%p)",qc); + TEST_BUGR(!qc); + qc->proc_entry = NULL; + if (qc_proc_entry==NULL) return -ENOTDIR; + sprintf(name, "video%d", qc->vdev.minor); + entry = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, qc_proc_entry); + if (!entry) { + PRINTK(KERN_WARNING,"Could not register procfs file entry"); + return -ENXIO; + } + entry->owner = THIS_MODULE; + entry->data = qc; + entry->read_proc = qc_proc_read; + entry->write_proc = qc_proc_write; + qc->proc_entry = entry; + return 0; +} +/* }}} */ +/* {{{ [fold] qc_proc_destroy(struct quickcam *qc) */ +/* qc_proc_destroy may be called after qc_proc_create for given quickcam even if it failed */ +static void qc_proc_destroy(struct quickcam *qc) +{ + char name[9]; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_proc_destroy(quickcam=%p)",qc); + TEST_BUG(!qc); + if (!qc->proc_entry) return; + TEST_BUG(!qc_proc_entry); + sprintf(name, "video%d", qc->vdev.minor); + remove_proc_entry(name, qc_proc_entry); + POISON(qc->proc_entry); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_proc_destroy() done"); +} +/* }}} */ +/* {{{ [fold] qc_proc_init(void) */ +/* Called when the driver is initially loaded, creates "/proc/video/quickcam" subdirectory */ +static int qc_proc_init(void) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_proc_init()"); + qc_proc_entry = create_proc_entry(qc_proc_name, S_IFDIR, NULL); /* Create /proc/video/quickcam */ + if (!qc_proc_entry) { + /* create_proc_entry failed, possibly because /proc/video is missing (patch by aceJacek ) */ + proc_mkdir("video", NULL); /* Might fail, if the directory already exists, but we don't care */ + qc_proc_entry = create_proc_entry(qc_proc_name, S_IFDIR, NULL); + if (!qc_proc_entry) { + PRINTK(KERN_WARNING,"Could not register procfs dir entry"); + return -ENXIO; + } + } + qc_proc_entry->owner = THIS_MODULE; + return 0; +} +/* }}} */ +/* {{{ [fold] qc_proc_exit(void) */ +/* Can be called after qc_proc_init() even if it has failed, in which case this does nothing */ +static void qc_proc_exit(void) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_proc_exit()"); + if (!qc_proc_entry) return; + remove_proc_entry(qc_proc_name, NULL); + POISON(qc_proc_entry); +} +/* }}} */ + +#else +static inline int qc_proc_create(struct quickcam *qc) { return 0; } +static inline void qc_proc_destroy(struct quickcam *qc) { } +static inline int qc_proc_init(void) { return 0; } +static inline void qc_proc_exit(void) { } +#endif /* HAVE_PROCFS */ +/* }}} */ +/* {{{ [fold] **** qc_adapt: Automatic exposure control ************************ */ + +#define MEASURE_ADAPT_DELAY 0 /* Measure adaptation delay, only for test purposes */ + +/* {{{ [fold] qc_adapt_init(struct quickcam *qc) */ +/* Initialize automatic exposure control structure. */ +static int qc_adapt_init(struct quickcam *qc) +{ + struct qc_adapt_data *ctrl = &qc->adapt_data; + ctrl->gain = 32768; + ctrl->olddelta = 4*256; /* best guess */ + ctrl->exposure = 32768; + ctrl->oldexposure = ctrl->exposure + 1; /* Slightly different for _issettled() */ + ctrl->midvaluesum = ctrl->oldmidvalue = 0; + ctrl->framecounter = 0; + ctrl->controlalg = EXPCONTROL_SATURATED; + IDEBUG_INIT(*ctrl); + return 0; +} +/* }}} */ +/* {{{ [fold] qc_adapt_exit(struct quickcam *qc) */ + +static inline void qc_adapt_exit(struct quickcam *qc) +{ +#ifdef DEBUG + struct qc_adapt_data *ctrl = &qc->adapt_data; + if (qcdebug&QC_DEBUGINIT) PDEBUG("qc_adapt_exit(ctrl=%p)",ctrl); + IDEBUG_EXIT(*ctrl); +#endif +} + +/* }}} */ +/* {{{ [fold] qc_adapt_reset(struct quickcam *qc) */ +/* Must be called each time just before starting video adaptation */ +static inline void qc_adapt_reset(struct quickcam *qc) +{ + IDEBUG_TEST(qc->adapt_data); + if (!qc->settings.keepsettings) { + IDEBUG_EXIT(qc->adapt_data); + qc_adapt_init(qc); + } +} +/* }}} */ +/* {{{ [fold] qc_adapt_hassettled(struct quickcam *qc) */ +/* Return TRUE if the image brightness has settled */ +static inline Bool qc_adapt_hassettled(struct quickcam *qc) +{ + struct qc_adapt_data *ctrl = &qc->adapt_data; + IDEBUG_TEST(*ctrl); + if (ctrl->framecounter != 0) return FALSE; +//PDEBUG("control=%i oldexp=%i exp=%i",ctrl->controlalg,ctrl->oldexposure,ctrl->exposure); + return ctrl->controlalg==EXPCONTROL_FLOAT || ctrl->oldexposure==ctrl->exposure; +} +/* }}} */ +/* {{{ [fold] qc_adapt(struct quickcam *qc, int midvalue, int target, int *ret_exposure, int *ret_gain) */ + +/* Set image exposure and gain so that computed midvalue approaches the target value. + * midvalue = average pixel intensity on image 0..255 + * target = user settable preferable intensity 0..255 + * *ret_exposure = the exposure value to use for the camera, 0..65535 + * *ret_gain = the gain to use for the camera, 0..65535. + */ +static void qc_adapt(struct quickcam *qc, int midvalue, int target, int *ret_exposure, int *ret_gain) +{ +#if !MEASURE_ADAPT_DELAY + struct qc_adapt_data *ctrl = &qc->adapt_data; + /* Here are some constant for controlling the adaptation algorithm. You may play with them. */ + static const int saturation_min = 32; /* (0-127) If midvalue is out of this range, image is */ + static const int saturation_max = 256 - 8; /* (128-255) considered saturated and no Newton is used */ + + static const int adaptation_min = 5; /* (0-128) For small variations, do not change exposure */ + + static const int delta_min = 256/2; /* (2-16*256) Minimum and maximum value for delta */ + static const int delta_max = 256*256; /* (4*256-1024*256) */ + + static const int dmidvalue_min = 400; /* (1-128) Minimum differences, under which delta estimation (FIXME:disabled by changing values very big) */ + static const int dexposure_min = 400; /* (1-32000) will not be done due to inaccuracies */ + + static const int delta_speed = 256; /* (0-256) How fast or slowly delta can change */ + static const int small_adapt = 4; /* (0-1024) When very near optimal, exposure change size */ + static const int underestimate = 16; /* (0-250) Underestimation, may prevent oscillation */ + static const int bestguess = 256/2; /* (2-1024*256) If delta can not be computed, guess this */ + static const int midvalueaccum = 2; /* (1-100) How many frames to use for midvalue averaging */ + static const int framedelay = 5; /* (0-8) How many frames there are before a new exposure setting in effect */ + /* With QuickCam Web: if set at frame #0, it will be in effect at frame #4; skip 3 frames #1,#2,#3 */ + /* -> should be 3 with QuickCam Web, but it oscillates, FIXME:why? Setting to 4 fixes this */ + static const int gainstep = 256; /* (0-32768) Amount to change gain at one step */ + static const int gainneeded = 10; /* (0-255) How eagerly to change brightness with gain */ + /* End of tunable constants */ + + int newexposure, delta=0; + int dexposure=0, dmidvalue=0; + int deviation=0; /* Deviation of actual brightness from target brightness */ + int smoothdelta=0; /* Final, smoothed, value of delta */ + + TEST_BUG(ctrl==NULL || ret_gain==NULL || ret_exposure==NULL); + IDEBUG_TEST(*ctrl); + + if (ctrl->framecounter >= framedelay) + ctrl->midvaluesum += midvalue; + ctrl->framecounter++; + if (ctrl->framecounter < framedelay+midvalueaccum) { + *ret_exposure = ctrl->exposure; + *ret_gain = ctrl->gain; + return; + } + + midvalue = ctrl->midvaluesum / midvalueaccum; + ctrl->framecounter = 0; + ctrl->midvaluesum = 0; + + if (ctrl->exposure >= qc->sensor_data.sensor->adapt_gainhigh && + ctrl->oldexposure >= qc->sensor_data.sensor->adapt_gainhigh && + target - ctrl->oldmidvalue > gainneeded && + target - midvalue > gainneeded) + { + /* Exposure is at maximum, but image is still too dark. Increase gain.*/ + ctrl->gain = ctrl->gain + ctrl->gain/2 + gainstep; + if (ctrl->gain > 65535) ctrl->gain = 65535; + if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("increasing gain to %i", ctrl->gain); + } else + if (ctrl->exposure <= qc->sensor_data.sensor->adapt_gainlow && + ctrl->oldexposure <= qc->sensor_data.sensor->adapt_gainlow && + target - ctrl->oldmidvalue <= gainneeded && + target - midvalue <= gainneeded) + { + /* Decrease gain if unnecessarily high */ + ctrl->gain = ctrl->gain - ctrl->gain/2 - gainstep; + if (ctrl->gain < 0) ctrl->gain = 0; + if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("decreasing gain to %i", ctrl->gain); + } + + if (ctrl->oldmidvaluecontrolalg = EXPCONTROL_SATURATED; + newexposure = ctrl->exposure * 2; + } else + if (ctrl->oldmidvalue>=saturation_max || midvalue>=saturation_max) { + /* Image is oversaturated, Newton method would give inaccurate results */ + if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("Decreasing exposure"); + ctrl->controlalg = EXPCONTROL_SATURATED; + newexposure = ctrl->exposure / 2; + } else { + deviation = target - midvalue; + if (ABS(deviation) < adaptation_min) { + /* For small variations, adapt linearly */ + if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("Small deviation %i",deviation); + ctrl->controlalg = EXPCONTROL_FLOAT; + newexposure = small_adapt * SGN(deviation) + ctrl->exposure; + } else { + /* Try using Newton method for estimating correct exposure value */ + ctrl->controlalg = EXPCONTROL_NEWTON; + dmidvalue = midvalue - ctrl->oldmidvalue; + dexposure = ctrl->exposure - ctrl->oldexposure; + if (ABS(dmidvalue) < dmidvalue_min || + ABS(dexposure) < dexposure_min || + SGN(dmidvalue) != SGN(dexposure)) + { + /* Can not estimate delta with Newton method, just guess */ + if (ctrl->olddelta < 2) { + if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("Best guessing"); + smoothdelta = bestguess; + } else { + Bool cross = SGN(midvalue-target) != SGN(ctrl->oldmidvalue-target); + smoothdelta = cross ? (ctrl->olddelta / 2) : (ctrl->olddelta * 3 / 2); + if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("Change more exposure, smoothdelta=%i",smoothdelta); + } + } else { + /* Everything is well, use here actual Newton method */ + delta = (256 - underestimate) * dexposure / dmidvalue; + smoothdelta = (delta_speed*delta + (256-delta_speed)*ctrl->olddelta) / 256; + if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("Using Newton, delta=%i",delta); + } + } + /* Compute new exposure based on guessed/computed delta */ + smoothdelta = CLIP(smoothdelta, delta_min,delta_max); + dexposure = deviation * smoothdelta / 256; + /* Newton works linearly, but exposure/brightness are not linearly related */ + /* The following test fixes the worst deficiencies due to that (I hope) */ + if (-dexposure > ctrl->exposure/2) + dexposure = -ctrl->exposure/2; + newexposure = dexposure + ctrl->exposure; + ctrl->olddelta = smoothdelta; + } + + newexposure = CLIP(newexposure, 2,65535); + + if (qcdebug&QC_DEBUGADAPTATION) + PDEBUG("midval=%i dev=%i dmidv=%i dexp=%i smdelta=%i olddelta=%i newexp=%i gain=%i", + midvalue,deviation,dmidvalue,dexposure,smoothdelta,ctrl->olddelta,newexposure,ctrl->gain); + + ctrl->oldexposure = ctrl->exposure; + ctrl->exposure = newexposure; + ctrl->oldmidvalue = midvalue; + *ret_exposure = newexposure; + *ret_gain = ctrl->gain; +#else + /* This code is for measuring the delay between an exposure settings and until + * it becomes in effect. Only useful for developing the adaptation algorithm. */ + /* Some delays: when a setting is changed at frame number #0, + * it becomes in effect in frame xx for exposure gain + * QuickCam Web/0850/normal mode 4 4 + * QuickCam Web/0850/compressed mode 5 5 + * QuickCam Express/840 2 1-5 + * + */ + static int exp = 0; + static int gain = 0; + static const int changedel = 20; + static int state = 0; + static int framenum = 0; + PRINTK(KERN_CRIT,"Measuring: framenum=%i, midvalue=%i",framenum,midvalue); + if ((framenum%changedel)==0) { + switch (state) { + default: + case 0: + PRINTK(KERN_CRIT,"Measuring: set to black"); + exp = 0; + gain = 0; + break; + case 1: + PRINTK(KERN_CRIT,"Measuring: changing exposure"); + exp = 65535; + break; + case 2: + PRINTK(KERN_CRIT,"Measuring: changing gain"); + gain = 32535; + break; + } + state = ((state+1) % 3); + } + *ret_exposure = exp; + *ret_gain = gain; + framenum++; +#endif +} + +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_frame: Frame capturing functions ************************* */ + +/* From /usr/src/linux/Documentation/smp.tex: + * + Kernel mode process (e.g. system calls): + * - No other kernel mode processes may run simultaneously/pre-empt + * (kernel mode processes are atomic with respect to each other) + * (Does not hold for 2.6.x) + * - Exception is voluntary sleeping, in which case re-entry is allowed + * (Does not hold for 2.6.x) + * - Interrupts may pre-empt (but return to same process) + * (interrupts can be disabled if necessary) + * + Interrupt mode execution + * - Kernel mode process may not pre-empt/execute simultaneously + * - Other interrupts may pre-empt, however same interrupt is not nested + */ + +/* We have here a quite typical producer-consumer scheme: + * Interrupt routine produces more frame data, while + * kernel mode processes consume it + * Read: Linux Device Drivers, Alessandro Rubini et al, 2nd edition, pg. 279 + * "Using Circular Buffers" + */ + +/* Initialization and cleanup routines, called from kernel mode processes */ +/* {{{ [fold] qc_frame_init(struct quickcam *qc) */ +static int qc_frame_init(struct quickcam *qc) +{ + struct qc_frame_data *fd = &qc->frame_data; + int n; + + if (qcdebug&QC_DEBUGFRAME || qcdebug&QC_DEBUGINIT) PDEBUG("qc_frame_init(qc=%p)",qc); + TEST_BUGR(qc==NULL || fd==NULL); + TEST_BUGR(in_interrupt()); + fd->rawdatabuf = vmalloc(FRAME_DATASIZE * FRAME_BUFFERS); + if (!fd->rawdatabuf) return -ENOMEM; + memset(fd->rawdatabuf, 0, FRAME_DATASIZE * FRAME_BUFFERS); /* Never let user access random kernel data */ + fd->head = 0; /* First buffer to fill */ + fd->tail = 0; /* First buffer to get */ + spin_lock_init(&fd->tail_lock); + fd->tail_in_use= FALSE; + init_waitqueue_head(&fd->wq); + fd->waiting = 0; + fd->exiting = FALSE; + for (n=0; nbuffers[n].rawdatalen = 0; + fd->lost_frames = 0; + IDEBUG_INIT(*fd); + return 0; +} +/* }}} */ +/* {{{ [fold] qc_frame_exit(struct quickcam *qc) */ +/* This function must be called with qc->lock acquired + * (it may release it temporarily and sleep) */ +static void qc_frame_exit(struct quickcam *qc) +{ + struct qc_frame_data *fd = &qc->frame_data; +#if PARANOID + unsigned long startjiffy = jiffies; +#endif + if (qcdebug&QC_DEBUGFRAME || qcdebug&QC_DEBUGINIT) PDEBUG("qc_frame_exit(qc=%p,tail=%i,head=%i)",qc,fd->tail,fd->head); + TEST_BUG(in_interrupt()); + TEST_BUG(qc==NULL || fd==NULL); + fd->exiting = TRUE; + fd->maxrawdatalen = 0; /* Hopefully stops all ongoing captures, might need locking though */ + wake_up(&fd->wq); + if (qcdebug&QC_DEBUGFRAME) PDEBUG("waiting=%i",fd->waiting); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_frame_exit() : %i", qc, sem_getcount(&qc->lock)); + up(&qc->lock); /* The lock was down when entering this function */ + while (fd->waiting > 0) { + schedule(); +#if PARANOID + if (jiffies-startjiffy > 60*HZ) { + PRINTK(KERN_CRIT,"Wait queue never completing!! (waiting=%i)",fd->waiting); + break; + } +#endif + } + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down(%p) in qc_frame_exit() : %i", qc, sem_getcount(&qc->lock)); + down(&qc->lock); + vfree(fd->rawdatabuf); + POISON(fd->rawdatabuf); + IDEBUG_EXIT(*fd); +} +/* }}} */ + +/* Consumer routines, called from kernel mode processes */ +/* {{{ [fold] qc_frame_get(struct quickcam *qc, unsigned char **buf) */ +/* Wait until next frame is ready and return the frame length + * and set buf to point to the frame. If error happens, + * return standard Linux negative error number. + * qc_frame_free() must be called after the frame is not needed anymore. + * qc->lock must be acquired when entering this routine + * (it may release it temporarily and sleep). + */ +static int qc_frame_get(struct quickcam *qc, unsigned char **buf) +{ + struct qc_frame_data *fd = &qc->frame_data; + int ret; + + TEST_BUGR(qc==NULL || fd==NULL || fd->tail_in_use); + TEST_BUGR(in_interrupt()); + IDEBUG_TEST(*fd); + + /* Wait until the next frame is available */ + if (qcdebug&QC_DEBUGFRAME) PDEBUG("qc_frame_get/consume(qc=%p,tail=%i,head=%i)",qc,fd->tail,fd->head); + fd->waiting++; + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_frame_get() : %i", qc, sem_getcount(&qc->lock)); + up(&qc->lock); /* Release lock while waiting */ + + ret = wait_event_interruptible(fd->wq, fd->head!=fd->tail || fd->exiting); //FIXME:What if we get -ERESTARTSYS? + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down(%p) in qc_frame_get() : %i", qc, sem_getcount(&qc->lock)); + down(&qc->lock); + if (!ret) { + if (!fd->exiting) { + unsigned int t; + unsigned long flags; + spin_lock_irqsave(&fd->tail_lock, flags); + fd->tail_in_use = TRUE; + t = fd->tail; + spin_unlock_irqrestore(&fd->tail_lock, flags); + if (qcdebug&QC_DEBUGFRAME) PDEBUG("qc_frame_get/consume(qc=%p,tail=%i,head=%i,tail->rawdatalen=%i), got frame",qc,t,fd->head,fd->buffers[t].rawdatalen); + *buf = fd->rawdatabuf + t*FRAME_DATASIZE; + ret = fd->buffers[t].rawdatalen; + } else { + ret = -ENODATA; + } + } + fd->waiting--; + fd->lost_frames = 0; + if (ret<0 && (qcdebug&(QC_DEBUGERRORS|QC_DEBUGFRAME))) PDEBUG("failed qc_frame_get()=%i",ret); + return ret; +} +/* }}} */ +/* {{{ [fold] qc_frame_free(struct quickcam *qc) */ +/* Free up the last frame returned from qc_frame_get() (it must be called first) */ +static inline void qc_frame_free(struct quickcam *qc) +{ + struct qc_frame_data *fd = &qc->frame_data; + unsigned long flags; + TEST_BUG(qc==NULL || fd==NULL); + TEST_BUG(in_interrupt()); + TEST_BUG(fd->head==fd->tail); /* The current fd->tail is not available to be freed! */ + IDEBUG_TEST(*fd); + if (qcdebug&QC_DEBUGFRAME) PDEBUG("qc_frame_free/consume(qc=%p,tail=%i,head=%i)",qc,fd->tail,fd->head); + /* Free up previous frame and advance to next */ + spin_lock_irqsave(&fd->tail_lock, flags); + fd->tail_in_use = FALSE; + fd->tail = (fd->tail + 1) % FRAME_BUFFERS; + spin_unlock_irqrestore(&fd->tail_lock, flags); +} +/* }}} */ +/* {{{ [fold] qc_frame_test(struct quickcam *qc) */ +/* Return TRUE if next frame is immediately available, FALSE otherwise. */ +static inline Bool qc_frame_test(struct quickcam *qc) +{ + struct qc_frame_data *fd = &qc->frame_data; + IDEBUG_TEST(*fd); + if (qcdebug&QC_DEBUGFRAME) PDEBUG("qc_frame_test/consume(qc=%p,tail=%i,head=%i)",qc,fd->tail,fd->head); + return fd->head != fd->tail; +} +/* }}} */ + +/* Producer routines, called from interrupt context */ +/* {{{ [fold] qc_frame_begin(struct quickcam *qc) */ +/* Begin capturing next frame from camera. If buffer is full, the frame will be lost */ +static void qc_frame_begin(struct quickcam *qc) +{ + struct qc_frame_data *fd = &qc->frame_data; + int framesize, h; + TEST_BUG(qc==NULL || fd==NULL); + IDEBUG_TEST(*fd); + if (qcdebug&QC_DEBUGFRAME) PDEBUG("qc_frame_begin/produce(qc=%p,tail=%i,head=%i)",qc,fd->tail,fd->head); + if (fd->exiting) return; + TEST_BUG(fd->rawdatabuf==NULL); + h = fd->head; + fd->buffers[h].rawdatalen = 0; + + /* Use sensor information to get the framesize (i.e. how much we expect to receive bytes per image) */ + /* FIXME: should compute data size differently in compressed mode */ + framesize = qc->sensor_data.width * qc->sensor_data.height; + fd->maxrawdatalen = MIN(framesize, FRAME_DATASIZE); +} +/* }}} */ +/* {{{ [fold] qc_frame_add(struct quickcam *qc, unsigned char *data, int datalen) */ +/* Store more data for a frame, return nonzero if too much data or other error */ +static int qc_frame_add(struct quickcam *qc, unsigned char *data, int datalen) +{ + struct qc_frame_data *fd = &qc->frame_data; + int h = fd->head; + int bytes; + + TEST_BUGR(qc==NULL || fd==NULL); + IDEBUG_TEST(*fd); + TEST_BUGR(fd->rawdatabuf==NULL); + if (fd->maxrawdatalen <= fd->buffers[h].rawdatalen) { + if (qcdebug&QC_DEBUGERRORS) PDEBUG("buffer disabled, maxrawdatalen=%i rawdatalen=%i datalen=%i",fd->maxrawdatalen,fd->buffers[h].rawdatalen, datalen); + return -EBUSY; + } + bytes = MIN(datalen, fd->maxrawdatalen - fd->buffers[h].rawdatalen); + memcpy(fd->rawdatabuf + h*FRAME_DATASIZE + fd->buffers[h].rawdatalen, data, bytes); + fd->buffers[h].rawdatalen += bytes; + if (bytes < datalen) { + if (qcdebug&QC_DEBUGERRORS) PRINTK(KERN_ERR,"out of buffer space by %i, maxrawdatalen=%i rawdatalen=%i datalen=%i", datalen-bytes,fd->maxrawdatalen,fd->buffers[h].rawdatalen, datalen); + return -ENOSPC; + } + return 0; +} +/* }}} */ +/* {{{ [fold] qc_frame_end(struct quickcam *qc) */ +/* Finished capturing most recent frame from camera */ +/* (may be premature end, in which case some data is missing) */ +static void qc_frame_end(struct quickcam *qc) +{ + static const int minrawdatalen = 32*32; /* If frame length is less than this many bytes, discard it */ + struct qc_frame_data *fd = &qc->frame_data; + unsigned int t, h; + unsigned long flags; + Bool lost_frame; + TEST_BUG(qc==NULL || fd==NULL); + h = fd->head; + if (qcdebug&QC_DEBUGFRAME) PDEBUG("qc_frame_end/produce(qc=%p,tail=%i,head=%i), got %i bytes",qc,fd->tail,h,fd->buffers[h].rawdatalen); + IDEBUG_TEST(*fd); + fd->maxrawdatalen = 0; /* Stop frame data capturing */ +#if DUMPDATA + PDEBUG("frame_end: got %i bytes", fd->buffers[h].rawdatalen); +#endif + if (fd->buffers[h].rawdatalen < minrawdatalen) { + /* No enough data in buffer, don't advance index */ + if (qcdebug&QC_DEBUGERRORS) PDEBUG("discarding frame with only %u bytes", fd->buffers[h].rawdatalen); + return; + } + h = (h + 1) % FRAME_BUFFERS; /* Select next frame buffer to fill */ + + lost_frame = FALSE; + spin_lock_irqsave(&fd->tail_lock, flags); + t = fd->tail; + if (t == h) { + lost_frame = TRUE; + /* FIXME: the below should work fine for two buffers, but not so well for more. It should be possible + * to drop oldest frame even when the current tail is in use. */ + if (fd->tail_in_use) { + /* Can not drop the oldest frame, it is in use. Drop the newest frame */ + h = (h + FRAME_BUFFERS - 1) % FRAME_BUFFERS; /* Decrease head by one back to the original */ + if (qcdebug&QC_DEBUGFRAME) PDEBUG("dropping newest frame"); + } else { + /* Drop the oldest frame */ + fd->tail = (t + 1) % FRAME_BUFFERS; /* Drop the oldest frame away */ + if (qcdebug&QC_DEBUGFRAME) PDEBUG("dropping oldest frame"); + } + } + spin_unlock_irqrestore(&fd->tail_lock, flags); + if (lost_frame) { + if (qcdebug&QC_DEBUGCOMMON || qcdebug&QC_DEBUGFRAME) PRINTK(KERN_NOTICE,"frame lost"); + fd->lost_frames++; + if (fd->lost_frames > 10) { + /* Here we should call qc_isoc_stop() to stop isochronous + * streaming since the application is clearly not reading frames at all. + * However, we are now in interrupt context but qc_isoc_stop() has + * to be in process context... so we can't do that. + * FIXME: add tasklet/bottomhalf/whatever needed to do it. + */ + if (qcdebug&QC_DEBUGFRAME) PDEBUG("too many lost frames: %i", fd->lost_frames); + } + } + fd->head = h; + wake_up(&fd->wq); +} +/* }}} */ +/* {{{ [fold] qc_frame_flush(struct quickcam *qc) */ +/* Reject the current data already captured into buffer and end frame */ +void qc_frame_flush(struct quickcam *qc) +{ + struct qc_frame_data *fd = &qc->frame_data; + unsigned int h = fd->head; + TEST_BUG(qc==NULL || fd==NULL); + IDEBUG_TEST(*fd); + if (qcdebug&QC_DEBUGFRAME) PDEBUG("qc_frame_flush/produce(qc=%p,tail=%i,head=%i), flush %i bytes",qc,fd->tail,h,fd->buffers[h].rawdatalen); + fd->buffers[h].rawdatalen = 0; /* Empty buffer */ + fd->maxrawdatalen = 0; /* Stop frame data capturing */ +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_stream: USB datastream processing functions *************** */ + +/* {{{ [fold] qc_stream_init(struct quickcam *qc) */ +/* Initialize datastream processing */ +static int qc_stream_init(struct quickcam *qc) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_stream_init(quickcam=%p)",qc); + qc->stream_data.capturing = FALSE; + qc->stream_data.frameskip = qc->settings.frameskip; + IDEBUG_INIT(qc->stream_data); + return 0; +} +/* }}} */ +/* {{{ [fold] qc_stream_exit(struct quickcam *qc) */ +/* Stop datastream processing, after this qc_stream_add should not be called */ +static void qc_stream_exit(struct quickcam *qc) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_stream_exit(quickcam=%p)",qc); + if (qc->stream_data.capturing) + qc_frame_end(qc); + IDEBUG_EXIT(qc->stream_data); +} +/* }}} */ +/* {{{ [fold] qc_stream_error(struct quickcam *qc) */ +/* This is called when there are data lost due to errors in the stream */ +static void qc_stream_error(struct quickcam *qc) +{ + /* Skip rest of data for this frame */ + if (qcdebug&QC_DEBUGERRORS) PDEBUG("qc_stream_error(qc=%p)", qc); + if (qc->stream_data.capturing) + qc_frame_end(qc); + IDEBUG_EXIT(qc->stream_data); + qc_stream_init(qc); +} +/* }}} */ +/* {{{ [fold] qc_stream_add(struct quickcam *qc, unsigned char *data, int datalen) */ +/* + * Analyse an USB packet of the data stream and store it appropriately. + * Each packet contains an integral number of chunks. Each chunk has + * 2-bytes identification, followed by 2-bytes that describe the chunk + * length. Known/guessed chunk identifications are: + * 8001/8005/C001/C005 - Begin new frame + * 8002/8006/C002/C006 - End frame + * 0200/4200 - Contains actual image data, bayer or compressed + * 0005 - 11 bytes of unknown data + * 0100 - 2 bytes of unknown data + * The 0005 and 0100 chunks seem to appear only in compressed stream. + * Return the amount of image data received or negative value on error. + */ +static int qc_stream_add(struct quickcam *qc, unsigned char *data, int datalen) +{ + struct qc_stream_data *sd = &qc->stream_data; + int id, len, error, totaldata = 0; + + IDEBUG_TEST(*sd); + while (datalen) { + if (datalen < 4) { + if (qcdebug&QC_DEBUGBITSTREAM) PRINTK(KERN_ERR,"missing chunk header"); + break; + } + id = (data[0]<<8) | data[1]; + len = (data[2]<<8) | data[3]; + data += 4; + datalen -= 4; + if (datalen < len) { + if (qcdebug&QC_DEBUGBITSTREAM) PRINTK(KERN_ERR,"missing chunk contents"); + break; + } + switch (id) { + case 0x8001: + case 0x8005: + case 0xC001: + case 0xC005: + /* Begin new frame, len should be zero */ + if (PARANOID && len!=0) PDEBUG("New frame: len!=0"); + if (sd->capturing) { + if (qcdebug&QC_DEBUGBITSTREAM) PDEBUG("Missing frame end mark in stream"); + qc_frame_end(qc); + } + sd->capturing = TRUE; + if (--sd->frameskip < 0) sd->frameskip = qc->settings.frameskip; + if (sd->frameskip==0) qc_frame_begin(qc); + break; + case 0x8002: + case 0x8006: + case 0xC002: + case 0xC006: + /* End frame, len should be zero */ + if (PARANOID && len!=0) PDEBUG("End frame: len!=0"); + if (sd->capturing) { + if (sd->frameskip==0) qc_frame_end(qc); + } else { + if (qcdebug&QC_DEBUGBITSTREAM) PDEBUG("Missing frame begin mark in stream"); + } + sd->capturing = FALSE; + break; + case 0x0200: + case 0x4200: + /* Image data */ + if (!sd->capturing && (qcdebug&QC_DEBUGBITSTREAM)) PDEBUG("Chunk of data outside frames!"); + if (sd->capturing && sd->frameskip==0) { + error = qc_frame_add(qc, data, len); + } else { + error = 0; + } + if (error) { + /* If qc_frame_add returns error, there is more data than the frame may have, + * in which case we assume stream is corrupted and skip rest packet */ + if (qcdebug&QC_DEBUGERRORS) PDEBUG("qc_frame_add error %i",error); + } else { + totaldata += len; + } + break; + case 0x0005: + /* Unknown chunk with 11 bytes of data, occurs just before end of each frame in compressed mode */ + if (len==11) break; + case 0x0100: + /* Unknown chunk with 2 bytes of data, occurs 2-3 times per USB interrupt */ + if (len==2) break; + default: + /* Unknown chunk */ + #ifdef DEBUG + if (qcdebug&QC_DEBUGBITSTREAM) { + static char dump[4*1024]; + char *dump_p = dump; + int i; + for (i=0; i= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void qc_isoc_handler(struct urb *urb, struct pt_regs *ptregs) +#else +static void qc_isoc_handler(struct urb *urb) +#endif +{ + struct quickcam *qc; + int payload = 0; /* Amount of all data camera sent */ + int totaldata = 0; /* Amount of image data camera sent */ + int i; +#ifdef DEBUG + /* Check for nested interrupts, shouldn't happen */ + volatile static Bool in_progress = FALSE; + TEST_BUG(in_progress); + in_progress = TRUE; +#endif + + if (qcdebug&QC_DEBUGINTERRUPTS) PDEBUG("[INTR] qc_isoc_handler(urb=%p)",urb); + TEST_BUG(urb==NULL); + qc = urb->context; + TEST_BUG(qc==NULL); + IDEBUG_TEST(qc->isoc_data); + + if (!qc->connected || !qc->isoc_data.streaming) { + /* Camera was disconnected or isochronous stream just disabled--must not resubmit urb */ + PDEBUG("Ignoring isoc interrupt, dev=%p streaming=%i status=%i", qc->dev, qc->isoc_data.streaming, urb->status); + goto out; + } + + if (urb->status<0) { + qc->isoc_data.errorcount++; + switch (urb->status) { + case -EXDEV: /* Partially completed, look at individual frame status */ + break; + default: + /* Seen here: -EOVERFLOW (75): Value too large for defined data type */ + case -EPROTO: /* Bitstuff error or unknown USB error */ + case -EILSEQ: /* CRC mismatch */ + case -ETIMEDOUT: /* Transfer timed out */ + case -EREMOTEIO: /* Short packet detected */ + case -EPIPE: /* Babble detect or endpoint stalled */ + case -ECONNRESET: /* Asynchronous unlink, should not happen, but does with 2.6.x */ + if (qcdebug&QC_DEBUGERRORS) PRINTK(KERN_ERR,"isoc URB error %i, resubmitting",urb->status); + goto resubmit; + case -ESHUTDOWN: + case -ENOENT: /* URB was unlinked */ + case -ENODEV: /* Device was removed */ + if (qcdebug&QC_DEBUGERRORS) PRINTK(KERN_ERR,"isoc URB error %i, returning",urb->status); + goto out; + } + } + + for (i=0; inumber_of_packets; i++) { + if ((int)urb->iso_frame_desc[i].status<0) { /* Note that the cast to int MUST be here! */ + if (qcdebug&QC_DEBUGERRORS) PDEBUG("USB transfer error %i", urb->iso_frame_desc[i].status); + qc->isoc_data.errorcount++; + qc_stream_error(qc); + continue; + } + qc->isoc_data.errorcount = 0; + payload += urb->iso_frame_desc[i].actual_length; +#if PARANOID +{ +int xx = urb->iso_frame_desc[i].actual_length; +if (xx>2000) { +PDEBUG("i=%i status=%i transfer_buffer=%p transfer_buffer_length=%i actual_length=%i number_of_packets=%i", + i, urb->status, urb->transfer_buffer, urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets); +PDEBUG("offset=%i length=%i actual_length=%i pstatus=%i", +urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].length, urb->iso_frame_desc[i].actual_length, urb->iso_frame_desc[i].status); +goto out; +} +} +#endif + totaldata += qc_stream_add(qc, urb->transfer_buffer + urb->iso_frame_desc[i].offset, + urb->iso_frame_desc[i].actual_length); + } + if (qcdebug&QC_DEBUGBITSTREAM) PDEBUG("payload=%i totaldata=%i",payload,totaldata); + if (qcdebug&(QC_DEBUGBITSTREAM|QC_DEBUGERRORS)) if (payload==0) PDEBUG("USB interrupt, but no data received!"); +resubmit: + /* Resubmit URB */ + if (qc->isoc_data.errorcount < ISOC_PACKETS*ISOC_URBS*8) { + urb->dev = qc->dev; /* Required for 2.4.x */ + i = usb_submit_urb(urb,GFP_ATOMIC); + if (i) PDEBUG("failed to resubmit URB, code=%i, dev=%p",i,urb->dev); + } else { + PDEBUG("Too many errors, giving up"); + } +out: +#ifdef DEBUG + in_progress = FALSE; +#endif + return; +} +/* }}} */ +/* {{{ [fold] qc_isoc_start(struct quickcam *qc) */ +/* + * Start USB isochronous image transfer from camera to computer + * (Set USB camera interface and allocate URBs and submit them) + * Sensor must be initialized beforehand (qc_init_sensor) + */ +static int qc_isoc_start(struct quickcam *qc) +{ + struct qc_isoc_data *id = &qc->isoc_data; + int ret = -ENOMEM; /* Return value on error */ + struct urb *urb; + int i, b; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_isoc_start(qc=%p)",qc); + TEST_BUGR_MSG(qc==NULL || id==NULL, "qc||id==NULL"); + IDEBUG_TEST(*id); + + if (id->streaming) return 0; /* Already started */ + id->streaming = TRUE; + id->errorcount = 0; + + /* Allocate transfer buffer */ + id->buffer = kmalloc(ISOC_URBS * ISOC_PACKETS * ISOC_PACKET_SIZE, GFP_KERNEL); + CHECK_ERROR(!id->buffer, fail1, "Out of memory allocating id->buffer"); + + /* Allocate URBs, fill them, and put them in the URB array */ + for (b=0; burbs[b] = usb_alloc_urb(ISOC_PACKETS,GFP_KERNEL); /* Zeroes the allocated data up to iso_frame_desc[], *not* including the last! */ + CHECK_ERROR(!urb, fail2, "Out of memory allocating urbs"); + urb->dev = qc->dev; + urb->context = qc; + urb->pipe = usb_rcvisocpipe(qc->dev, QUICKCAM_ISOPIPE); + urb->transfer_flags = URB_ISO_ASAP; /* Leave URB_ASYNC_UNLINK clear and never call usb_unlink_urb() */ + urb->complete = qc_isoc_handler; + urb->number_of_packets = ISOC_PACKETS; + urb->transfer_buffer = id->buffer; + urb->transfer_buffer_length = ISOC_URBS * ISOC_PACKETS * ISOC_PACKET_SIZE; + urb->interval = 1; /* See Table 9-10 of the USB 1.1 specification */ + for (i=0; iiso_frame_desc[i].offset = b*ISOC_PACKETS*ISOC_PACKET_SIZE + i*ISOC_PACKET_SIZE; + urb->iso_frame_desc[i].length = ISOC_PACKET_SIZE; + } + } + + /* Alternate interface 3 is the biggest frame size */ + /* JFC use 1: but do not know why */ + /* QuickCam Web: Interface 0, alternate 1, endpoint 0x81 -tuukkat */ + qc_i2c_wait(qc); /* There must not be control URBs going when calling set_interface() */ + ret = usb_set_interface(qc->dev, qc->iface, 1); + CHECK_ERROR(ret<0, fail3, "set_interface failed"); + + /* Submit URBs */ + for (b=0; burbs[b],GFP_KERNEL); + CHECK_ERROR(ret<0, fail4, "submit urbs failed"); + } + + /* Tell camera to start sending data */ + ret = qc->sensor_data.sensor->start(qc); /* Start current frame */ + CHECK_ERROR(ret<0, fail5, "sensor_data.start failed"); + ret = qc_stv_set(qc, STV_ISO_ENABLE, 1); /* Start isochronous streaming */ + CHECK_ERROR(ret<0, fail6, "qc_stv_set() failed"); + return 0; + + /* Cleanup and return error code on failure */ +fail6: qc->sensor_data.sensor->stop(qc); /* stop current frame. */ +fail5: b = ISOC_URBS; +fail4: while (--b >= 0) usb_kill_urb(id->urbs[b]); + usb_set_interface(qc->dev, qc->iface, 0); /* Set packet size to 0 (Interface 0, alternate 0, endpoint 0x81 -tuukkat) */ +fail3: b = ISOC_URBS; +fail2: while (--b >= 0) usb_free_urb(id->urbs[b]); + kfree(id->buffer); +fail1: if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGERRORS) PDEBUG("failed qc_isoc_init()=%i",ret); + return ret; +} +/* }}} */ +/* {{{ [fold] qc_isoc_stop(struct quickcam *qc) */ +/* + * Stop USB isochronous image transfer from camera to computer + * (Tell camera to stop sending images, set idle USB interface and free URBs) + * There must be no more isochronous transfer interrupts after this returns + * nor any running handlers anymore. + */ +static void qc_isoc_stop(struct quickcam *qc) +{ + struct qc_isoc_data *id = &qc->isoc_data; + int b, r; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_isoc_stop(quickcam=%p)",qc); + TEST_BUG_MSG(qc==NULL || id==NULL, "qc||id==NULL"); + IDEBUG_TEST(*id); + + if (!id->streaming) return; /* Already stopped */ + if (qc->connected) { + if ((r=qc_stv_set(qc, STV_ISO_ENABLE, 0))<0) /* stop ISO-streaming. */ + PRINTK(KERN_ERR,"qc_stv_set error %i",r); + if ((r=qc->sensor_data.sensor->stop(qc))<0) /* stop current frame. */ + PRINTK(KERN_ERR,"sensor_data.stop error %i",r); + qc_i2c_wait(qc); /* When calling set_interface(), there must not be control URBs on way */ + if (usb_set_interface(qc->dev, qc->iface, 0) < 0) /* Set packet size to 0 (Interface 0, alternate 0, endpoint 0x81 -tuukkat) */ + PRINTK(KERN_ERR,"usb_set_interface error"); + } + id->streaming = FALSE; /* Ensure that no more isochronous URBs will be submitted from the interrupt handler */ + mb(); + for (b=0; bstatus = %i", b, id->urbs[b]->status); + usb_kill_urb(id->urbs[b]); + usb_free_urb(id->urbs[b]); + POISON(id->urbs[b]); + } + + kfree(id->buffer); + POISON(id->buffer); + return; +} +/* }}} */ +/* {{{ [fold] qc_isoc_init(struct quickcam *qc) */ +/* + * Initialize isochronous streaming functions + */ +static int qc_isoc_init(struct quickcam *qc) +{ + struct qc_isoc_data *id = &qc->isoc_data; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_isoc_init(quickcam=%p)",qc); + TEST_BUGR_MSG(qc==NULL || id==NULL, "qc||id==NULL"); + IDEBUG_INIT(*id); + id->streaming = FALSE; + return 0; +} +/* }}} */ +/* {{{ [fold] qc_isoc_exit(struct quickcam *qc) */ +/* + * Uninitialize isochronous streaming functions + */ +static inline void qc_isoc_exit(struct quickcam *qc) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_isoc_exit(quickcam=%p)",qc); + qc_isoc_stop(qc); + IDEBUG_EXIT(qc->isoc_data); +} +/* }}} */ +/* {{{ [fold] Bool qc_isoc_streaming(struct quickcam *qc) */ +static inline Bool qc_isoc_streaming(struct quickcam *qc) +{ + struct qc_isoc_data *id = &qc->isoc_data; + + TEST_BUGR_MSG(qc==NULL || id==NULL, "qc||id==NULL"); + IDEBUG_TEST(*id); + return id->streaming; +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_sensor: Common routines for all sensors ******************* */ + +/* {{{ [fold] qc_sensor_setsize0(struct quickcam *qc, unsigned int width, unsigned int height) */ +/* Called when the application requests a specific image size. Should set the + * actual delivered image size to as close to the requested as possible. + * The image size, as delivered from the camera, can be also set to reduce + * required bandwidth, if possible, but it is not necessary. + * This is a private function to qc_sensor_*, other modules should use qc_sensor_setsize() + * If capt is TRUE, then qc_capt_get may be called (and qc_capt_init must be called before). + */ +static int qc_sensor_setsize0(struct quickcam *qc, unsigned int width, unsigned int height, Bool capt) +{ + unsigned char *f; + int r; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_sensor_setsize(qc=%p,width=%i,height=%i)",qc,width,height); + TEST_BUGR_MSG(qc==NULL, "qc==NULL!"); + + if (width < min_framewidth || width > qc->sensor_data.maxwidth) return -EINVAL; + if (height < min_frameheight || height > qc->sensor_data.maxheight) return -EINVAL; + + /* Applications require, when using Xvideo extension, that the + * frame size is multiple of 8. This is a bug in apps or Xvideo. -tuukkat */ + if (qc->settings.compat_16x) { + width = (width /16)*16; + height = (height/16)*16; + } + /* Set the size only if changed */ + if (qc->vwin.width==width && qc->vwin.height==height) return 0; + + /* For HDCS-1000 we must wait for frame before setting size */ + if (capt) qc_capt_get(qc, &f); + + qc->sensor_data.width = width; /* The sensor-specific code may modify these if not suitable */ + qc->sensor_data.height = height; + if ((r = qc->sensor_data.sensor->set_size(qc, width, height))<0) { + PDEBUG("set_size sensor failed"); + return r; + } + + /* Set the closest size we can actually deliver to application */ + qc->vwin.width = width; + qc->vwin.height = height; + if ((r = qc_i2c_wait(qc))<0) return r; + qc_frame_flush(qc); + return 0; +} +/* }}} */ +/* {{{ [fold] qc_sensor_setsize(struct quickcam *qc, unsigned int width, unsigned int height) */ +/* Called when the application requests a specific image size. Should set the + * actual delivered image size to as close to the requested as possible. + * The image size, as delivered from the camera, can be also set to reduce + * required bandwidth, if possible, but it is not necessary. + * qc_isoc_init() and qc_capt_init() have to be called before this function. + */ +static inline int qc_sensor_setsize(struct quickcam *qc, unsigned int width, unsigned int height) +{ + int r; + r = qc_sensor_setsize0(qc, width, height, qc_isoc_streaming(qc)); + return r; +} +/* }}} */ +/* {{{ [fold] qc_sensor_init(struct quickcam *qc) */ +/* + * Initialise sensor. Initializes all data in qc->sensor which is common to all + * types of sensors and calls the sensor-specific initialization routine. + * The Photobit starts the pixel integration immediately after the reset. + * Note: must call qc_i2c_init() and qc_frame_init() before this function! + */ +static int qc_sensor_init(struct quickcam *qc) +{ + int r; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_init_sensor(qc=%p)",qc); + TEST_BUGR_MSG(qc==NULL, "qc==NULL!"); + + qc->sensor_data.width = -1; + qc->sensor_data.height = -1; + qc->sensor_data.exposure = -1; + qc->sensor_data.rgain = -1; + qc->sensor_data.ggain = -1; + qc->sensor_data.bgain = -1; + qc->sensor_data.subsample = qc->settings.subsample; + qc->sensor_data.compress = qc->settings.compress; + + if ((r = qc->sensor_data.sensor->init(qc))<0) goto fail; + if ((r = qc_stv_set(qc, STV_ISO_ENABLE, 0))<0) goto fail; /* Stop isochronous streaming */ + if ((r = qc->sensor_data.sensor->stop(qc))<0) goto fail; /* Stop current frame */ + + /* Set capture size */ + qc->vwin.width = 0; /* Set to illegal value (ensures resetting) */ + qc->vwin.height = 0; + if ((r = qc_sensor_setsize0(qc, qc->sensor_data.maxwidth, qc->sensor_data.maxheight, FALSE))<0) goto fail; + + /* Set brightness settings */ + if ((r = qc->sensor_data.sensor->set_levels(qc, qc->vpic.brightness, qc->vpic.contrast, qc->vpic.hue, qc->vpic.colour))<0) goto fail; + if (qc->sensor_data.sensor->set_target!=NULL) + if ((r = qc->sensor_data.sensor->set_target(qc, qc->vpic.brightness))<0) goto fail; + return 0; + +fail: PRINTK(KERN_ERR,"sensor initialization failed: %i",r); + return r; +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_capt: User image capturing functions ******************** */ + +/* {{{ [fold] qc_capt_get(struct quickcam *qc, unsigned char **frame) */ +/* Wait until next image is ready and return the image length in bytes + * and set "frame" to point to the image. If error happens, + * return standard Linux negative error number. The image will be in + * palette and size requested by the user (quickcam->vpic,vwin). + */ +static int qc_capt_get(struct quickcam *qc, unsigned char **frame) +{ + struct qc_capt_data *cd = &qc->capt_data; + unsigned char *rawdata=NULL; /* Raw data from camera */ + int rawdatalen; + int retrycount = qc->settings.retryerrors ? 8 : 0; + int settlecount = cd->settled ? 0 : qc->settings.settle; /* If the picture has already settled, do not wait for it again */ + int midvalue; + int r; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_capt_get(quickcam=%p)",qc); + IDEBUG_TEST(*cd); + if ((r = qc_isoc_start(qc))<0) goto fail; /* Start receiving data */ + + do { + r = qc_frame_get(qc, &rawdata); + if (r < 0) goto error; + rawdatalen = r; + r = qc_fmt_convert(qc, rawdata, rawdatalen, cd->frame, MAX_FRAME_SIZE, &midvalue); + if (r < 0) { + qc_frame_free(qc); + goto error; + } + + if (qc->vpic_pending) { + qc->vpic_pending = FALSE; + if (!qc->settings.adaptive) { + /* Set new values now */ + qc->sensor_data.sensor->set_levels(qc, qc->vpic.brightness, qc->vpic.contrast, qc->vpic.hue, qc->vpic.colour); + } else { + if (qc->sensor_data.sensor->set_target!=NULL) + qc->sensor_data.sensor->set_target(qc, qc->vpic.brightness); + } + } + + if (qc->settings.adaptive && !qc->sensor_data.sensor->autoexposure && r>=0 && midvalue>=0) { + int ex, gn; + qc_adapt(qc, midvalue, qc->vpic.brightness>>8, &ex, &gn); + qc->sensor_data.sensor->set_levels(qc, ex, gn, qc->vpic.hue, qc->vpic.colour); + } + qc_frame_free(qc); + + if (qc_adapt_hassettled(qc) || settlecount<=0) break; + settlecount--; + +error: if (r < 0) { + if (qcdebug&QC_DEBUGERRORS) PDEBUG("retrying failed qc_frame_get... rounds=%i", retrycount); + if (r==-ERESTARTSYS || retrycount<=0) break; + retrycount--; + } + qc_i2c_flush(qc); /* Send all pending I2C transfers */ + schedule(); + } while (TRUE); + if (r<0) goto fail; + qc_i2c_flush(qc); /* Send all pending I2C transfers */ + cd->settled = TRUE; + if (frame) *frame = cd->frame; + return r; + +fail: if (qcdebug&(QC_DEBUGERRORS|QC_DEBUGLOGIC)) PDEBUG("failed qc_capt_get()=%i", r); + return r; +} +/* }}} */ +/* {{{ [fold] qc_capt_frameaddr(struct quickcam *qc, unsigned char **frame) */ +/* Return size and address of the capture buffer that is suitable for mmapping, + * Standard Linux errno on error */ +static inline int qc_capt_frameaddr(struct quickcam *qc, unsigned char **frame) +{ + IDEBUG_TEST(qc->capt_data); + if (frame!=NULL) *frame = qc->capt_data.frame; + return MAX_FRAME_SIZE; +} +/* }}} */ +/* {{{ [fold] qc_capt_test(struct quickcam *qc) */ +/* Return TRUE if next image is immediately available, FALSE otherwise. + * Also starts streaming video from camera if not already done so. + * Before calling this function, qc_isoc_init() must be called first. */ +static inline Bool qc_capt_test(struct quickcam *qc) +{ + int e; + IDEBUG_TEST(qc->capt_data); + e = qc_isoc_start(qc); + if (qcdebug&QC_DEBUGERRORS && e<0) PDEBUG("qc_capt_test: qc_isoc_start failed"); + return qc_frame_test(qc); +} +/* }}} */ +/* {{{ [fold] qc_capt_init(struct quickcam *qc) */ +static int qc_capt_init(struct quickcam *qc) +{ + struct qc_capt_data *cd = &qc->capt_data; + int r; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_capt_init(quickcam=%p)",qc); + + cd->settled = !(qc->settings.settle>0 && qc->settings.adaptive); + + /* Allocate memory for the (mmappable) capture buffer */ + cd->frame = qc_mm_rvmalloc(MAX_FRAME_SIZE); + if (!cd->frame) { + PRINTK(KERN_ERR, "unable to allocate frame"); + r = -ENOMEM; + goto fail1; + } + + /* Initialize submodules */ + if ((r=qc_frame_init(qc))<0) goto fail2; /* Must be before sensor_init() */ + r = qc_sensor_init(qc); /* Start the sensor (must be after qc_i2c_init but before qc_adapt_init) */ + if (r<0 && qc->settings.compress) { + /* Sensor init failed with compression. Try again without compression */ + PRINTK(KERN_NOTICE, "sensor init failed, disabling compression"); + qc->settings.compress = 0; + r = qc_sensor_init(qc); + } + if (r<0) goto fail3; + if ((r=qc_stream_init(qc))<0) goto fail3; + if ((r=qc_fmt_init(qc))<0) goto fail4; + if ((r=qc_isoc_init(qc))<0) goto fail5; + IDEBUG_INIT(*cd); + return 0; + +fail5: qc_fmt_exit(qc); +fail4: qc_stream_exit(qc); +fail3: qc_frame_exit(qc); +fail2: qc_mm_rvfree(cd->frame, MAX_FRAME_SIZE); +fail1: PDEBUG("failed qc_capt_init()=%i",r); + return r; +} +/* }}} */ +/* {{{ [fold] qc_capt_exit(struct quickcam *qc) */ +static void qc_capt_exit(struct quickcam *qc) +{ + struct qc_capt_data *cd = &qc->capt_data; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_capt_exit(quickcam=%p)",qc); + qc_isoc_exit(qc); + qc_fmt_exit(qc); + qc_stream_exit(qc); + qc_frame_exit(qc); + qc_mm_rvfree(cd->frame, MAX_FRAME_SIZE); + POISON(cd->frame); + IDEBUG_EXIT(*cd); +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_v4l: Start of Video 4 Linux API ************************ */ + +/* {{{ [fold] qc_v4l_poll(struct video_device *dev, struct file *file, poll_table *wait) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static unsigned int qc_v4l_poll(struct file *file, poll_table *wait) +#else +static unsigned int qc_v4l_poll(struct video_device *dev, struct file *file, poll_table *wait) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct video_device *dev = video_devdata(file); +#endif + struct quickcam *qc = (struct quickcam *)dev->priv; + struct qc_frame_data *fd = &qc->frame_data; + int mask; + + if (qcdebug&QC_DEBUGUSER) PDEBUG("qc_v4l_poll(dev=%p,file=%p,wait=%p)",dev,file,wait); + if (down_interruptible(&qc->lock)) return -ERESTARTSYS; + poll_wait(file, &fd->wq, wait); + mask = qc_capt_test(qc) ? (POLLIN | POLLRDNORM) : 0; + up(&qc->lock); + return mask; +} +/* }}} */ +/* {{{ [fold] qc_v4l_init(struct quickcam *qc) */ +/* Called when the device is opened */ +static int qc_v4l_init(struct quickcam *qc) +{ + int r, fps; + + if (!qc->settings.keepsettings) { + /* Reset brightness settings */ + qc->vpic.brightness = 32768; + qc->vpic.hue = 32768; + qc->vpic.colour = 32768; + qc->vpic.contrast = 32768; + qc->vpic.whiteness = 32768; + qc_adapt_reset(qc); /* qc_adapt_init() is called from qc_usb_init() */ + } + qc->vpic.palette = VIDEO_PALETTE_RGB24; + qc->vpic.depth = qc_fmt_getdepth(qc->vpic.palette); + qc->vpic_pending = FALSE; + + fps = qc->settings.subsample ? 30 : 8; /* May actually vary depending on image size */ + fps = qc->settings.compress ? 15 : fps; /* Actually 7.5 fps, but we must round it */ + qc->vwin.flags = fps << 16; /* Bits 22..16 contain framerate in Philips driver. We do the same. */ + + if ((r = qc_capt_init(qc))<0) goto fail; + return 0; + +fail: if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGERRORS) PDEBUG("failed qc_v4l_init()=%i",r); + return r; +} +/* }}} */ +/* {{{ [fold] qc_v4l_open(struct video_device *dev, int flags) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int qc_v4l_open(struct inode *inode, struct file *file) +#else +static int qc_v4l_open(struct video_device *dev, int flags) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct video_device *dev = video_devdata(file); +#endif + struct quickcam *qc = dev->priv; + int r; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGUSER) PDEBUG("qc_v4l_open(qc=%p)", qc); +//PDEBUG("sleeping 10 sec..."); +//qc_usleep(1000000*10); +//PDEBUG("sleep done"); + // FIXME: if the module is tried to be unloaded at this point, + // v4l_close() and MOD_DEC_USE_COUNT will never be called + // According to "Linux Device drivers" pg.70, it's ok if called before sleeping? + // 2.2 will crash, 2.4 will hang and show "quickcam 1 (deleted)" if sleeping + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("MOD_INC_USE_COUNT in qc_v4l_open() : %i",GET_USE_COUNT(THIS_MODULE)); + MOD_INC_USE_COUNT; + + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down_intr(quickcam_list) in qc_v4l_open() : %i", sem_getcount(&quickcam_list_lock)); + + r = qc_lock(qc); + if (r<0) goto fail1; + + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down_intr(%p) in qc_v4l_open() : %i", qc, sem_getcount(&qc->lock)); + if (down_interruptible(&qc->lock)) { + r = -ERESTARTSYS; + goto fail2; + } + if (!qc->connected) { + r = -ENODEV; + goto fail3; + } + qc->users++; + PDEBUG("open users=%i", qc->users); + if (qc->users == 1) { + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("First user, initializing"); + if ((r = qc_v4l_init(qc))<0) goto fail4; + } + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_v4l_open() : %i",qc, sem_getcount(&qc->lock)); + up(&qc->lock); + up(&quickcam_list_lock); + return 0; + +fail4: qc->users--; +fail3: if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_v4l_open()=failed : %i",qc, sem_getcount(&qc->lock)); + up(&qc->lock); +fail2: if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(quickcam_list) in qc_v4l_open()=failed : %i", sem_getcount(&qc->lock)); + up(&quickcam_list_lock); +fail1: if (qcdebug&QC_DEBUGMUTEX) PDEBUG("MOD_DEC_USE_COUNT in qc_v4l_open() : %i",GET_USE_COUNT(THIS_MODULE)); + MOD_DEC_USE_COUNT; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGERRORS) PDEBUG("failed qc_v4l_open()=%i",r); + return r; +} +/* }}} */ +/* {{{ [fold] qc_v4l_exit(struct quickcam *qc) */ +/* Release all resources allocated at qc_v4l_init() */ +static inline void qc_v4l_exit(struct quickcam *qc) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_v4l_cleanup(%p)", qc); + qc_capt_exit(qc); +} +/* }}} */ +/* {{{ [fold] qc_v4l_close(struct video_device *dev) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int qc_v4l_close(struct inode *inode, struct file *file) +#else +static void qc_v4l_close(struct video_device *dev) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct video_device *dev = video_devdata(file); +#endif + struct quickcam *qc = (struct quickcam *)dev->priv; + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGUSER) PDEBUG("qc_v4l_close(dev=%p,qc=%p)",dev,qc); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + TEST_BUGR_MSG(qc==NULL, "qc==NULL"); +#else + TEST_BUG_MSG(qc==NULL, "qc==NULL"); +#endif + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down(quickcam_list) in qc_v4l_close() : %i", sem_getcount(&quickcam_list_lock)); + down(&quickcam_list_lock); /* Can not interrupt, we must success */ + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down(%p) in qc_v4l_close() : %i", qc, sem_getcount(&qc->lock)); + down(&qc->lock); /* Can not interrupt, we must success */ + qc->users--; + PDEBUG("close users=%i", qc->users); + if (qc->users == 0) { + /* No more users, device is deallocated */ + qc_v4l_exit(qc); + if (qc->dev == NULL) { /* Test qc->dev instead of qc->connected because disconnection routine sets the latter before locking camera */ + /* Camera was unplugged and freeing was postponed: free resources now here */ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("Performing postponed free"); + qc_usb_exit(qc); + qc = NULL; + } + } + if (qc) { + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_v4l_close() : %i", qc, sem_getcount(&qc->lock)); + up(&qc->lock); + } + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(quickcam_list) in qc_v4l_close() : %i", sem_getcount(&quickcam_list_lock)); + up(&quickcam_list_lock); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("MOD_DEC_USE_COUNT in qc_v4l_close() : %i", GET_USE_COUNT(THIS_MODULE)); + MOD_DEC_USE_COUNT; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("v4l_close() ok"); +#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,0) + return 0; +#endif +} +/* }}} */ +/* {{{ [fold] qc_v4l_read(struct video_device *dev, char *buf, unsigned long count, int noblock) */ +static ssize_t qc_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct video_device *dev = video_devdata(file); + int noblock = file->f_flags & O_NONBLOCK; +#endif + struct quickcam *qc = (struct quickcam *)dev->priv; + int frame_len; + unsigned char *frame; + long r = 0; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGUSER) + PDEBUG("qc_v4l_read(dev=%p,buf=%p,count=%li,noblock=%i,qc=%p)",dev,buf,(long)count,noblock,qc); + if (!qc || !buf) { + PDEBUG("qc_read: no video_device available or no buffer attached :( EFAULT"); + return -EFAULT; + } + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down_intr(%p) in qc_v4l_read() : %i", qc, sem_getcount(&qc->lock)); + if (down_interruptible(&qc->lock)) return -ERESTARTSYS; + if (!qc->connected) { + r = -ENODEV; + goto fail; + } + if (noblock && !qc_capt_test(qc)) { + r = -EAGAIN; + goto fail; + } + frame_len = qc_capt_get(qc, &frame); + if (frame_len < 0) { + r = frame_len; + goto fail; + } + if (count > frame_len) count = frame_len; + if (copy_to_user(buf, frame, count)) { + r = -EFAULT; + goto fail; + } + r = count; + +fail: if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_v4l_read() : %i", qc, sem_getcount(&qc->lock)); + up(&qc->lock); + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGERRORS) if (r<0) PDEBUG("failed qc_v4l_read()=%i", (int)r); + return r; +} +/* }}} */ +/* {{{ [fold] qc_v4l_mmap(struct vm_area_struct *vma, struct video_device *dev, const char *adr, unsigned long size) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int qc_v4l_mmap(struct file *file, struct vm_area_struct *vma) +#else +static int qc_v4l_mmap( +#if HAVE_VMA + struct vm_area_struct *vma, +#endif + struct video_device *dev, const char *start, unsigned long size) +#endif /* 2.6.x */ +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct video_device *dev = video_devdata(file); + const void *start = (void *)vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; +#endif + struct quickcam *qc = (struct quickcam *)dev->priv; + unsigned char *frame; + int ret = 0, frame_size; +#if !HAVE_VMA && LINUX_VERSION_CODElock)); + if (down_interruptible(&qc->lock)) return -ERESTARTSYS; + if (!qc->connected) { ret = -ENODEV; goto fail; } + frame_size = qc_capt_frameaddr(qc, &frame); + if (frame_size<0) { ret = frame_size; goto fail; } /* Should never happen */ + ret = qc_mm_remap(vma, frame, frame_size, start, size); + +fail: if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_v4l_mmap() : %i", qc, sem_getcount(&qc->lock)); + up(&qc->lock); + if (ret<0) if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGERRORS) PDEBUG("failed qc_v4l_mmap()=%i",ret); + return ret; +} +/* }}} */ +/* {{{ [fold] qc_v4l_ioctl(struct video_device *dev, unsigned int cmd, void *arg) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int qc_v4l_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +#else +static int qc_v4l_ioctl(struct video_device *dev, unsigned int cmd, void *argp) +#endif +{ + static const Bool ignore_channel = TRUE; /* RealProducer is reported to fail if driver doesn't accept channel change */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct video_device *dev = video_devdata(file); + void *argp = (void *)arg; +#endif + struct quickcam *qc = (struct quickcam *)dev->priv; + int i, retval = 0; + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGUSER) PDEBUG("qc_v4l_ioctl(dev=%p,cmd=%u,arg=%p,qc=%p)",dev,cmd,argp,qc); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down_intr(%p) in qc_v4l_ioctl() : %i", qc, sem_getcount(&qc->lock)); + if (down_interruptible(&qc->lock)) return -ERESTARTSYS; + if (!qc->connected) { + retval = -ENODEV; + goto fail; + } + switch (cmd) { +/* {{{ [fold] VIDIOCGCAP: Capability query */ + case VIDIOCGCAP: /* Capability query */ + { + struct video_capability b; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGCAP"); + memset(&b, 0, sizeof(b)); + strcpy(b.name, "Logitech QuickCam USB"); /* Max 31 characters */ + b.type = qc->vdev.vfl_type; + b.channels = 1; + b.audios = 0; + b.maxwidth = qc->sensor_data.maxwidth; + b.maxheight = qc->sensor_data.maxheight; + if (qc->settings.compat_16x) { + b.maxwidth = (b.maxwidth /16)*16; + b.maxheight = (b.maxheight/16)*16; + } + b.minwidth = min_framewidth; + b.minheight = min_frameheight; + if (copy_to_user(argp, &b, sizeof(b))) retval = -EFAULT; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCGCHAN: Get properties of the specified channel */ + case VIDIOCGCHAN: /* Get properties of the specified channel */ + { + struct video_channel v; + if (copy_from_user(&v, argp, sizeof(v))) { + retval = -EFAULT; + break; + } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGCHAN channel:%i",v.channel); + if (!ignore_channel && v.channel != 0) { + retval = -EINVAL; + break; + } + v.flags = 0; + v.tuners = 0; + v.type = VIDEO_TYPE_CAMERA; + strcpy(v.name, "Camera"); + if (copy_to_user(argp, &v, sizeof(v))) retval = -EFAULT; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCSCHAN: Select channel to capture */ + case VIDIOCSCHAN: /* Select channel to capture */ + { + if (copy_from_user(&i, argp, sizeof(i))) { + retval = -EFAULT; + break; + } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCSCHAN channel:%i",i); + if (!ignore_channel && i!=0) retval = -EINVAL; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCGPICT: Get image properties (brightness, palette, etc.) */ + case VIDIOCGPICT: /* Get image properties */ + { + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGPICT"); + if (copy_to_user(argp, &qc->vpic, sizeof(qc->vpic))) retval = -EFAULT; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCSPICT: Set image properties */ + case VIDIOCSPICT: /* Set image properties */ + { + struct video_picture p; + if (copy_from_user(&p, argp, sizeof(p))) { + retval = -EFAULT; + break; + } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCSPICT depth:%d palette:%s(%i) bright=%i",p.depth,qc_fmt_getname(p.palette),p.palette,p.brightness); + + if (p.palette != 0) { /* 0 = do not change palette */ + retval = qc_fmt_issupported(p.palette); + if (retval<0) break; + qc->vpic.palette = p.palette; + qc->vpic.depth = qc_fmt_getdepth(p.palette); + if (qc->vpic.depth != p.depth) PDEBUG("warning: palette depth mismatch"); + } + qc->vpic.brightness = p.brightness; + qc->vpic.hue = p.hue; + qc->vpic.colour = p.colour; + qc->vpic.contrast = p.contrast; + qc->vpic.whiteness = p.whiteness; /* Used for sharpness */ + qc->vpic_pending = TRUE; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCSWIN: Set capture area width and height */ + case VIDIOCSWIN: /* Set capture area width and height */ + { + struct video_window vw; + int fps; + if (copy_from_user(&vw, argp, sizeof(vw))) { + retval = -EFAULT; + break; + } + fps = (vw.flags>>16) & 0x3F; /* 6 bits for framerate */ + if (fps && ((qc->vwin.flags>>16)&0x3F)!=fps) { + PDEBUG("Application tries to change framerate"); + } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCSWIN width:%i height:%i flags:%d clipcount:%d",vw.width,vw.height,vw.flags,vw.clipcount); + retval = qc_sensor_setsize(qc, vw.width, vw.height); + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCGWIN: Get current capture area */ + case VIDIOCGWIN: /* Get current capture area */ + { + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGWIN"); + if (copy_to_user(argp, &qc->vwin, sizeof(qc->vwin))) retval = -EFAULT; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCGMBUF: Get mmap buffer size and frame offsets */ + case VIDIOCGMBUF: /* Get mmap buffer size and frame offsets */ + { + struct video_mbuf vm; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGMBUF"); + memset(&vm, 0, sizeof(vm)); + vm.size = qc_capt_frameaddr(qc, NULL); + if (vm.size<0) { /* Negative value denotes error */ + retval = vm.size; + break; + } + vm.frames = 1; + vm.offsets[0] = 0; + if (qc->settings.compat_dblbuf) { + /* Really many applications are broken and don't work with a single buffer */ + vm.frames = 2; + vm.offsets[1] = 0; + } + if (copy_to_user(argp, &vm, sizeof(vm))) retval = -EFAULT; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCMCAPTURE: Start capturing specified frame in the mmap buffer with specified size */ + case VIDIOCMCAPTURE: /* Start capturing specified frame in the mmap buffer with specified size */ + { + struct video_mmap vm; + if (copy_from_user(&vm, argp, sizeof(vm))) { + retval = -EFAULT; + break; + } + /* Bug in V4L: sometimes it's called palette, sometimes format. We'll stick with palette */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCMCAPTURE frame:%d size:%dx%d palette:%s", vm.frame, vm.width, vm.height, qc_fmt_getname(vm.format)); + if (vm.frame!=0 && !(qc->settings.compat_dblbuf)) { + PRINTK(KERN_NOTICE,"Bug detected in user program, use qcset compat=dblbuf"); + retval = -EINVAL; + break; + } + if (vm.format!=0 && qc->vpic.palette!=vm.format) { /* 0 = do not change palette */ + retval = qc_fmt_issupported(vm.format); + if (retval) { + if (qcdebug&QC_DEBUGERRORS) PDEBUG("unsupported image format"); + break; + } + qc->vpic.palette = vm.format; + qc->vpic.depth = qc_fmt_getdepth(vm.format); + } + retval = qc_sensor_setsize(qc, vm.width, vm.height); + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCSYNC: Wait until specified frame in the mmap buffer has been captured */ + case VIDIOCSYNC: /* Wait until specified frame in the mmap buffer has been captured */ + { + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCSYNC"); + retval = qc_capt_get(qc, NULL); + if (retval>0) retval = 0; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCGFBUF: Get currently used frame buffer parameters */ + case VIDIOCGFBUF: /* Get currently used frame buffer parameters */ + { + struct video_buffer vb; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGFBUF"); + memset(&vb, 0, sizeof(vb)); + if (copy_to_user(argp, &vb, sizeof(vb))) retval = -EFAULT; + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCKEY: Undocumented? */ + case VIDIOCKEY: /* Undocumented? */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCKEY"); + retval = -EINVAL; + break; +/* }}} */ +/* {{{ [fold] VIDIOCCAPTURE: Activate overlay capturing directly to framebuffer */ + case VIDIOCCAPTURE: /* Activate overlay capturing directly to framebuffer */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCCAPTURE"); + retval = -EINVAL; + break; +/* }}} */ +/* {{{ [fold] VIDIOCSFBUF: Set frame buffer parameters for the capture card */ + case VIDIOCSFBUF: /* Set frame buffer parameters for the capture card */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCSFBUF"); + retval = -EINVAL; + break; +/* }}} */ +/* {{{ [fold] VIDIOCxTUNER: Get properties of the specified tuner / Select tuner to use */ + case VIDIOCGTUNER: /* Get properties of the specified tuner */ + case VIDIOCSTUNER: /* Select tuner to use */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxTUNER"); + retval = -EINVAL; + break; +/* }}} */ +/* {{{ [fold] VIDIOCxFREQ: Get current tuner frequency / Set tuner frequency */ + case VIDIOCGFREQ: /* Get current tuner frequency */ + case VIDIOCSFREQ: /* Set tuner frequency */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxFREQ"); + retval = -EINVAL; + break; +/* }}} */ +/* {{{ [fold] VIDIOCxAUDIO: Get/Set audio properties */ + case VIDIOCGAUDIO: /* Get audio properties */ + case VIDIOCSAUDIO: /* Set audio properties */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxAUDIO"); + retval = -EINVAL; + break; +/* }}} */ + /********** Private IOCTLs ***********/ +/* {{{ [fold] VIDIOCQCxDEBUG: Sets/gets the qcdebug output (1,2,4,8,16,32) */ + case VIDIOCQCSDEBUG: /* Sets the qcdebug output (1,2,4,8,16,32) */ + if (get_user(qcdebug, (int *)argp)) { retval=-EFAULT; break; } + case VIDIOCQCGDEBUG: /* Gets the qcdebug output (1,2,4,8,16,32) */ + if (put_user(qcdebug, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxDEBUG"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxKEEPSETTINGS: Set/get keep gain settings across one open to another (0-1) */ + case VIDIOCQCSKEEPSETTINGS: /* Set keep gain settings across one open to another (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.keepsettings = i; + case VIDIOCQCGKEEPSETTINGS: /* Get keep gain settings across one open to another (0-1) */ + i = qc->settings.keepsettings; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxKEEPSETTINGS"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxSETTLE: Set/get if we let image brightness to settle (0-1) */ + case VIDIOCQCSSETTLE: /* Set if we let image brightness to settle (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.settle = i; + case VIDIOCQCGSETTLE: /* Get if we let image brightness to settle (0-1) */ + i = qc->settings.settle; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxSETTLE"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxSUBSAMPLE: Sets/gets the speed (0-1) */ + case VIDIOCQCSSUBSAMPLE: /* Sets the speed (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.subsample = i; + case VIDIOCQCGSUBSAMPLE: /* Gets the speed (0-1) */ + i = qc->settings.subsample; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxSUBSAMPLE"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxCOMPRESS: Sets/gets the compression mode (0-1) */ + case VIDIOCQCSCOMPRESS: /* Sets the compression mode (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.compress = i; + case VIDIOCQCGCOMPRESS: /* Gets the compression mode (0-1) */ + i = qc->settings.compress; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxCOMPRESS"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxFRAMESKIP: Set/get frame capture frequency (0-10) */ + case VIDIOCQCSFRAMESKIP: /* Set frame capture frequency (0-10) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.frameskip = i; + case VIDIOCQCGFRAMESKIP: /* Get frame capture frequency (0-10) */ + i = qc->settings.frameskip; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxFRAMESKIP"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxQUALITY: Sets/gets the interpolation mode (0-2) */ + case VIDIOCQCSQUALITY: /* Sets the interpolation mode (0-5) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.quality = i; + case VIDIOCQCGQUALITY: /* Gets the interpolation mode (0-5) */ + i = qc->settings.quality; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxQUALITY"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxADAPTIVE: Set/get automatic adaptive brightness control (0-1) */ + case VIDIOCQCSADAPTIVE: /* Set automatic adaptive brightness control (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.adaptive = i; + case VIDIOCQCGADAPTIVE: /* Get automatic adaptive brightness control (0-1) */ + i = qc->settings.adaptive; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxADAPTIVE"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxEQUALIZE: Set/get equalize image (0-1) */ + case VIDIOCQCSEQUALIZE: /* Set equalize image (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.equalize = i; + case VIDIOCQCGEQUALIZE: /* Get equalize image (0-1) */ + i = qc->settings.equalize; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxEQUALIZE"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxUSERLUT: Set/get user-specified lookup-table */ + case VIDIOCQCSUSERLUT: /* Set user-specified lookup-table [struct qc_userlut] */ + { + unsigned int flags; + retval = -EFAULT; + if (get_user(flags, &(((struct qc_userlut*)argp)->flags))) break; + if (flags & QC_USERLUT_DEFAULT) { + userlut = ((flags & QC_USERLUT_ENABLE) != 0); + } else { + qc->settings.userlut = ((flags & QC_USERLUT_ENABLE) != 0); + } + if (flags & QC_USERLUT_VALUES) { + for (i=0; ilut[i]))) break; + if (flags & QC_USERLUT_DEFAULT) { + userlut_contents[i] = p; + } else { + qc->fmt_data.userlut[i] = p; + } + } + if (i < QC_LUT_SIZE) break; + } + retval = 0; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCSUSERLUT"); + break; + } + case VIDIOCQCGUSERLUT: /* Get user-specified lookup-table [struct qc_userlut] */ + { + unsigned int flags; + retval = -EFAULT; + if (get_user(flags, &(((struct qc_userlut*)argp)->flags))) break; + flags &= (~QC_USERLUT_ENABLE); + if ((flags & QC_USERLUT_DEFAULT) ? userlut : qc->settings.userlut) flags |= QC_USERLUT_ENABLE; + if (put_user(flags, &(((struct qc_userlut*)argp)->flags))) break; + if (flags & QC_USERLUT_VALUES) { + for (i=0; ifmt_data.userlut[i]; + } + if (put_user(p, &(((struct qc_userlut*)argp)->lut[i]))) break; + } + if (i < QC_LUT_SIZE) break; + } + retval = 0; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGUSERLUT"); + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCQCxRETRYERRORS: Set/get if we retry when error happen in capture (0-1) */ + case VIDIOCQCSRETRYERRORS: /* Set if we retry when error happen in capture (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.retryerrors = i; + case VIDIOCQCGRETRYERRORS: /* Get if we retry when error happen in capture (0-1) */ + i = qc->settings.retryerrors; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxRETRYERRORS"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxCOMPATIBLE: Set enable workaround for Xawtv/Motv bugs (0-1) */ + case VIDIOCQCSCOMPATIBLE: /* Set enable workaround for Xawtv/Motv bugs (0-1) */ + if (get_user(i, (int *)argp)) { retval=-EFAULT; break; } + qc->settings.compat_16x = (i & QC_COMPAT_16X) != 0; + qc->settings.compat_dblbuf = (i & QC_COMPAT_DBLBUF) != 0; + qc->settings.compat_torgb = (i & QC_COMPAT_TORGB) != 0; + case VIDIOCQCGCOMPATIBLE: /* Get enable workaround for Xawtv/Motv bugs (0-1) */ + i = ~(qc->settings.compat_16x -1) & QC_COMPAT_16X; + i |= ~(qc->settings.compat_dblbuf-1) & QC_COMPAT_DBLBUF; + i |= ~(qc->settings.compat_torgb -1) & QC_COMPAT_TORGB; + if (put_user(i, (int *)argp)) { retval=-EFAULT; break; } + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCxCOMPATIBLE"); + break; +/* }}} */ +/* {{{ [fold] VIDIOCQCxVIDEONR: Set videodevice number (/dev/videoX) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5) + case VIDIOCQCSVIDEONR: /* Set videodevice number (/dev/videoX) */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCSVIDEONR"); + retval = -EINVAL; /* Can not set after the module is loaded */ + break; + case VIDIOCQCGVIDEONR: /* Get videodevice number (/dev/videoX) */ + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCGVIDEONR"); + if (put_user(video_nr, (int *)argp)) { retval=-EFAULT; break; } + break; +#endif +/* }}} */ +/* {{{ [fold] VIDIOCQCxSTV: Read/write STV chip register value */ + /* Encoding: bits 31..16 of the int argument contain register value, 15..0 the reg number */ + case VIDIOCQCGSTV: /* Read STV chip register value */ + { + int reg, val; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCQCGSTV"); + if (get_user(reg, (int *)argp)) { retval=-EFAULT; break; } + reg &= 0xFFFF; + val = qc_stv_get(qc, reg); + if (val<0) { retval=val; break; } + val = (val<<16) | reg; + if (put_user(val, (int *)argp)) { retval=-EFAULT; break; } + break; + } + case VIDIOCQCSSTV: /* Write STV chip register value */ + { + int regval; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCQCSSTV"); + if (!capable(CAP_SYS_RAWIO)) { retval=-EPERM; break; } + if (get_user(regval, (int *)argp)) { retval=-EFAULT; break; } + retval = qc_stv_set(qc, regval & 0xFFFF, regval >> 16); + break; + } +/* }}} */ +/* {{{ [fold] VIDIOCQCxI2C: Read/write sensor chip register value via I2C */ + case VIDIOCQCGI2C: /* Read sensor chip register value via I2C */ + { + int reg, val; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCQCGI2C"); + if (get_user(reg, (int *)argp)) { retval=-EFAULT; break; } + reg &= 0xFFFF; + val = qc_get_i2c(qc, qc->sensor_data.sensor, reg); + if (val<0) { retval=val; break; } + val = (val<<16) | reg; + if (put_user(val, (int *)argp)) { retval=-EFAULT; break; } + break; + } + case VIDIOCQCSI2C: /* Write sensor chip register value via I2C */ + { + int regval; + if (qcdebug&QC_DEBUGUSER) PDEBUG("VIDIOCQCSI2C"); + if (!capable(CAP_SYS_RAWIO)) { retval=-EPERM; break; } + if (get_user(regval, (int *)argp)) { retval=-EFAULT; break; } + retval = qc_i2c_set(qc, regval & 0xFFFF, regval >> 16); + if (retval<0) break; + retval = qc_i2c_wait(qc); + break; + } +/* }}} */ + default: + if (qcdebug&QC_DEBUGUSER) PDEBUG("Unknown IOCTL %08X",cmd); + retval = -ENOIOCTLCMD; + break; + } +fail: if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_v4l_ioctl() : %i", qc, sem_getcount(&qc->lock)); + up(&qc->lock); + if (retval<0) if (qcdebug&(QC_DEBUGLOGIC|QC_DEBUGUSER|QC_DEBUGERRORS)) PDEBUG("failed qc_v4l_ioctl()=%i",retval); + return retval; +} +/* }}} */ +/* {{{ [fold] qc_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) */ +#if LINUX_VERSION_CODE= KERNEL_VERSION(2,6,0) +static void qc_v4l_release(struct video_device *vfd) { } +static struct file_operations qc_v4l_fops = { + owner: THIS_MODULE, + open: qc_v4l_open, + release: qc_v4l_close, + read: qc_v4l_read, +// write: qc_v4l_write, + ioctl: qc_v4l_ioctl, + mmap: qc_v4l_mmap, + poll: qc_v4l_poll, +}; +#endif + +static struct video_device qc_v4l_template = { + name: "QuickCam USB", + minor: -1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + release: qc_v4l_release, + fops: &qc_v4l_fops, +#else + initialize: NULL, + open: qc_v4l_open, + close: qc_v4l_close, + read: qc_v4l_read, + write: qc_v4l_write, + ioctl: qc_v4l_ioctl, + mmap: qc_v4l_mmap, + poll: qc_v4l_poll, +#endif +}; +/* }}} */ +/* {{{ [fold] **** qc_usb: Start of USB API ********************************** */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int qc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +static void *qc_usb_probe(struct usb_device *dev, unsigned int iface, const struct usb_device_id *id); +#else +static void *qc_usb_probe(struct usb_device *dev, unsigned int iface); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static void qc_usb_disconnect(struct usb_interface *intf); +#else +static void qc_usb_disconnect(struct usb_device *dev, void *ptr); +#endif + +static struct usb_driver qc_usb_driver = { + name: qc_name, + probe: qc_usb_probe, + disconnect: qc_usb_disconnect, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) \ + && LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) + owner: THIS_MODULE, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + id_table: qc_device_table, +#endif +}; + +/* {{{ [fold] qc_usb_init(struct usb_device *dev, unsigned int ifacenum) */ +/* Detect sensor, initialize the quickcam structure, register V4L device, create /proc entry. + * Return pointer to the allocated quickcam structure or NULL on error. + * If there is some camera already open but disconnected, reuse the quickcam structure. */ +static struct quickcam *qc_usb_init(struct usb_device *usbdev, unsigned int ifacenum) +{ + struct quickcam *qc; + Bool reuse_qc; + int i, r = 0; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_usb_init(usbdev=%p)", usbdev); + if (PARANOID && usbdev==NULL) { PRINTK(KERN_CRIT,"usbdev==NULL"); return NULL; } + + /* Check if there is already a suitable quickcam struct that can be reused */ + reuse_qc = FALSE; + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down_intr(quickcam_list_lock) in qc_usb_init() : %i", sem_getcount(&quickcam_list_lock)); + if (down_interruptible(&quickcam_list_lock)) return NULL; + list_for_each_entry(qc, &quickcam_list, list) { + if (qc->dev!=NULL) continue; /* quickcam_list_lock protects this test */ + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down_intr(%p) in qc_usb_init() : %i",qc, sem_getcount(&qc->lock)); + if (down_interruptible(&qc->lock)) { + /* Failed to lock the camera. Move on in the list, skipping this camera */ + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("failed locking the camera %p in qc_usb_init() : %i",qc,sem_getcount(&qc->lock)); + continue; + } + if (qc->users<=0) { + PRINTK(KERN_NOTICE, "Unplugged unused camera detected!"); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_usb_init() : %i",qc, sem_getcount(&qc->lock)); + up(&qc->lock); + continue; + } + /* Found and locked unplugged but used camera */ + reuse_qc = TRUE; + break; + } + + if (reuse_qc) { + /* Reuse existing quickcam (which is already opened) */ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("Reusing existing quickcam"); + if (PARANOID && qc->users<=0) PRINTK(KERN_CRIT, "Unplugged JUST closed camera detected!"); + qc_isoc_stop(qc); + qc_i2c_wait(qc); + qc_frame_flush(qc); + } else { + /* Allocate and initialize some members of the new qc */ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("Allocating new quickcam"); + qc = kmalloc(sizeof(*qc), GFP_KERNEL); + CHECK_ERROR(qc==NULL, fail1, "couldn't kmalloc quickcam struct"); + memset(qc, 0, sizeof(*qc)); /* No garbage to user */ +PDEBUG("poisoning qc in qc_usb_init"); + POISON(*qc); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("init down(%p) in qc_usb_init()", qc); +#ifdef CONFIG_PREEMPT_RT + init_MUTEX(&qc->lock); + down(&qc->lock); +#else + init_MUTEX_LOCKED(&qc->lock); +#endif + qc->users = 0; + if ((r=qc_i2c_init(qc))<0) goto fail2; + } + qc->dev = usbdev; + qc->iface = ifacenum; + qc->connected = TRUE; + + /* Probe for the sensor type */ + qc_i2c_wait(qc); /* Necessary before set_interface() */ + if ((r=usb_set_interface(usbdev, qc->iface, 0))<0) goto fail3; /* Set altsetting 0 */ + if ((r=qc_stv_set(qc, STV_ISO_ENABLE, 0))<0) goto fail3; /* Disable isochronous stream */ + for (i=0; iid_reg))<0) goto fail3; + r = (r >> (sensors[i]->length_id-1) * 8) & 0xFF; /* Get MSB of received value */ + if (qcdebug&QC_DEBUGCAMERA) PDEBUG("Probing %s: expecting %02X, got %02X", sensors[i]->name, sensors[i]->id, r); + if (r == sensors[i]->id) break; + } + if (i>=SIZE(sensors)) { + PRINTK(KERN_INFO,"unsupported sensor"); + goto fail3; + } + qc->sensor_data.sensor = sensors[i]; + PRINTK(KERN_INFO,"Sensor %s detected", sensors[i]->name); + + if ((r=qc_stv_set(qc, STV_ISO_ENABLE, 0))<0) goto fail3; /* Disable isochronous streaming */ + if ((r=qc_stv_set(qc, STV_REG23, 1))<0) goto fail3; + + if (!reuse_qc) { + /* Set default settings */ + qc->vpic.brightness = 32768; + qc->vpic.hue = 32768; + qc->vpic.colour = 32768; + qc->vpic.contrast = 32768; + qc->vpic.whiteness = 32768; /* Used for sharpness at quality=5 */ + qc->settings.keepsettings = keepsettings; + qc->settings.settle = settle; + qc->settings.subsample = subsample; + qc->settings.compress = compress; + qc->settings.frameskip = frameskip; + qc->settings.quality = quality; + qc->settings.adaptive = adaptive; + qc->settings.equalize = equalize; + qc->settings.userlut = userlut; + qc->settings.retryerrors = retryerrors; + qc->settings.compat_16x = compatible & QC_COMPAT_16X ? 1 : 0; + qc->settings.compat_dblbuf = compatible & QC_COMPAT_DBLBUF ? 1 : 0; + qc->settings.compat_torgb = compatible & QC_COMPAT_TORGB ? 1 : 0; + memcpy(&qc->fmt_data.userlut, userlut_contents, sizeof(qc->fmt_data.userlut)); + + /* Register V4L video device */ + memcpy(&qc->vdev, &qc_v4l_template, sizeof(qc_v4l_template)); + qc->vdev.priv = qc; + r = video_register_device(&qc->vdev, VFL_TYPE_GRABBER, video_nr); + if (r<0) goto fail3; + PRINTK(KERN_INFO, "Registered device: /dev/video%i", qc->vdev.minor); + if ((r=qc_adapt_init(qc))<0) goto fail4; + qc_proc_create(qc); /* Create /proc entry, ignore if it fails */ + list_add(&qc->list, &quickcam_list); + } + + if (reuse_qc && qc->frame_data.waiting>0) { + /* Restart capturing */ + int width = qc->vwin.width; + int height = qc->vwin.height; +//qc_usleep(1000000); + qc_isoc_stop(qc); + r = qc_sensor_init(qc); + r = qc_isoc_start(qc); + r = qc_sensor_setsize(qc, width, height); + /* Ignore return codes for now, if it fails, too bad, but shouldn't crash */ + /* FIXME: proper error handling */ + +/*qc_usleep(1000000); + qc_sensor_setsize(qc, width, height); +qc_usleep(1000000); + qc_sensor_setsize(qc, 32, 32); +qc_usleep(1000000); + qc_sensor_setsize(qc, width, height); +qc_usleep(1000000);*/ + +#if 0 +/* The following tries to initialize VV6410 really hard. still doesn't work */ +{ +int r,c; +for(c=0;c<10;c++) { +//r = qc_sensor_init(qc); +//PDEBUG("c=%i init=%i",c,r); +//r = qc_sensor_setsize(qc, width, height); +//PDEBUG("size=%i",r); +//r = usb_set_interface(qc->dev, qc->iface, 1); +//PDEBUG("set_interf=%i",r); +//r = qc->sensor_data.sensor->start(qc); /* Start current frame */ +//PDEBUG("start=%i",r); +//r = qc_stv_set(qc, STV_ISO_ENABLE, 1); +//PDEBUG("stv_set=%i",r); +//qc_isoc_stop(qc); +//qc_usleep(1000000); +//qc_isoc_start(qc); +//qc_usleep(1000000); +}} +#endif + } + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_usb_init() : %i",qc, sem_getcount(&qc->lock)); + up(&qc->lock); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(quickcam_list) in qc_usb_init() : %i", sem_getcount(&quickcam_list_lock)); + up(&quickcam_list_lock); + return qc; + +fail4: video_unregister_device(&qc->vdev); +fail3: if (!reuse_qc) qc_i2c_exit(qc); + qc->dev = NULL; + qc->connected = FALSE; + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_usb_init()=failed : %i",qc, sem_getcount(&qc->lock)); + up(&qc->lock); +fail2: if (!reuse_qc) kfree(qc); +fail1: if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGERRORS) PDEBUG("failed qc_usb_init()=%i",r); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(quickcam_list) in qc_usb_init()=failed : %i", sem_getcount(&quickcam_list_lock)); + up(&quickcam_list_lock); + return NULL; +} +/* }}} */ +/* FIXME: can usb_disconnect and usb_probe pre-empt other kernel mode processes? Assume no */ +/* {{{ [fold] qc_usb_probe(...) */ +/* Called when any USB device is connected, check if it is a supported camera */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int qc_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +static void *qc_usb_probe(struct usb_device *usbdev, unsigned int ifacenum, const struct usb_device_id *id) +#else /* 2.2.x */ +static void *qc_usb_probe(struct usb_device *usbdev, unsigned int ifacenum) +#endif +{ + struct quickcam *qc; + struct usb_interface_descriptor *ifacedesc; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + unsigned int ifacenum; + struct usb_device *usbdev = interface_to_usbdev(interface); + static const int ERROR_CODE = -ENODEV; +#else + static void * const ERROR_CODE = NULL; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + /* Check if the device has a product number that we support */ + struct usb_device_id *i; + for (i=qc_device_table; i->idVendor; i++) { + if (usbdev->descriptor.idVendor == i->idVendor && + usbdev->descriptor.idProduct == i->idProduct) break; + } + if (!i->idVendor) return ERROR_CODE; +#endif + if (PARANOID && usbdev==NULL) { PRINTK(KERN_CRIT,"usbdev==NULL"); return ERROR_CODE; } + + /* We don't handle multi-config cameras */ + if (usbdev->descriptor.bNumConfigurations != 1) return ERROR_CODE; + + /* + * Checking vendor/product is not enough + * In case on QuickCam Web the audio is at class 1 and subclass 1/2. + * one /dev/dsp and one /dev/mixer + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + ifacedesc = &interface->altsetting[0].desc; + ifacenum = ifacedesc->bInterfaceNumber; +#else + ifacedesc = &usbdev->actconfig->interface[ifacenum].altsetting[0]; +#endif + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_usb_probe(usbdev=%p,ifacenum=%i)", usbdev, ifacenum); + if (PARANOID && ifacedesc->bInterfaceNumber!=ifacenum) PRINTK(KERN_CRIT,"bInterfaceNumber(%i)!=ifacenum(%i)!!",ifacedesc->bInterfaceNumber,ifacenum); + if (ifacedesc->bInterfaceClass != 0xFF) return ERROR_CODE; + if (ifacedesc->bInterfaceSubClass != 0xFF) return ERROR_CODE; + + /* We found a QuickCam */ + PRINTK(KERN_INFO,"QuickCam USB camera found (driver version %s)", VERSION); + PRINTK(KERN_INFO,"Kernel:%s bus:%i class:%02X subclass:%02X vendor:%04X product:%04X", + UTS_RELEASE, usbdev->bus->busnum, ifacedesc->bInterfaceClass, ifacedesc->bInterfaceSubClass, + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); + + /* The interface is claimed (bound) automatically to us when we return from this function (without error code) */ + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("MOD_INC_USE_COUNT in qc_usb_probe() : %i",GET_USE_COUNT(THIS_MODULE)); + MOD_INC_USE_COUNT; /* Increase count to 1, which locks the module--it can't be removed */ + qc = qc_usb_init(usbdev, ifacenum); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("MOD_DEC_USE_COUNT in qc_usb_probe() : %i",GET_USE_COUNT(THIS_MODULE)); + MOD_DEC_USE_COUNT; /* Release lock: module can be now removed again */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + if (!qc) return ERROR_CODE; + usb_set_intfdata(interface, qc); /* FIXME: why? */ + return 0; +#else + return qc; +#endif +} +/* }}} */ +/* {{{ [fold] qc_usb_exit(struct quickcam *qc) */ +/* Free up resources allocated in qc_usb_init() when not needed anymore + * Note: quickcam_list_lock and qc->lock must be acquired before entering this function! + * qc may not be accessed after this function returns! + */ +static void qc_usb_exit(struct quickcam *qc) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_usb_exit(qc=%p)",qc); + TEST_BUG_MSG(qc==NULL, "qc==NULL"); + + qc_proc_destroy(qc); + qc_adapt_exit(qc); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("video_unregister_device(%p)", &qc->vdev); + video_unregister_device(&qc->vdev); + qc_i2c_exit(qc); + list_del(&qc->list); +PDEBUG("poisoning qc in qc_usb_exit"); + POISON(*qc); + kfree(qc); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_usb_exit() done"); +} +/* }}} */ +/* {{{ [fold] qc_usb_disconnect(...) */ +/* Called when the camera is disconnected. We might not free struct quickcam here, + * because the camera might be in use (open() called). In that case, the freeing is + * postponed to the last close() call. However, all submitted URBs must be unlinked. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static void qc_usb_disconnect(struct usb_interface *interface) +#else +static void qc_usb_disconnect(struct usb_device *usbdev, void *ptr) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct quickcam *qc = usb_get_intfdata(interface); +#ifdef DEBUG + struct usb_device *usbdev = interface_to_usbdev(interface); +#endif +#else + struct quickcam *qc = (struct quickcam *)ptr; +#endif + + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_usb_disconnect(qc=%p)",qc); + TEST_BUG_MSG(qc==NULL, "qc==NULL in qc_usb_disconnect!"); + TEST_BUG_MSG(qc->dev==NULL || qc->connected==FALSE, "disconnecting disconnected device!!"); + TEST_BUG_MSG(usbdev!=qc->dev, "disconnecting not our device!!"); + + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("MOD_INC_USE_COUNT in qc_usb_disconnect() : %i",GET_USE_COUNT(THIS_MODULE)); + MOD_INC_USE_COUNT; /* Increase count to 1, which locks the module--it can't be removed */ + + /* + * When the camera is unplugged (maybe even when it is capturing), quickcam->connected is set to FALSE. + * All functions called from user mode and all _exit functions must check for this. + */ + qc->connected = FALSE; + + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down(quickcam_list) in qc_usb_disconnect() : %i", sem_getcount(&quickcam_list_lock)); + down(&quickcam_list_lock); /* Also avoids race condition with open() */ + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("down(%p) in qc_usb_disconnect() : %i", qc, sem_getcount(&qc->lock)); + down(&qc->lock); /* Can not interrupt, we must success */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + usb_set_intfdata(interface, NULL); /* FIXME: why? */ +#endif + if (qc->users <= 0) { + /* Free resources */ + qc_usb_exit(qc); + } else { + /* Can not free resources if device is open: postpone to when it is closed */ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("Disconnect while device open: postponing cleanup"); + qc_isoc_stop(qc); /* Unlink and free isochronous URBs */ + qc_i2c_wait(qc); /* Wait until there are no more I2C packets on way */ + qc->dev = NULL; /* Must be set to NULL only after interrupts are guaranteed to be disabled! */ + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(%p) in qc_usb_disconnect() : %i",qc, sem_getcount(&qc->lock)); + up(&qc->lock); + } + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("up(quickcam_list) in qc_usb_disconnect() : %i", sem_getcount(&quickcam_list_lock)); + up(&quickcam_list_lock); + if (qcdebug&QC_DEBUGMUTEX) PDEBUG("MOD_DEC_USE_COUNT in qc_usb_disconnect() : %i",GET_USE_COUNT(THIS_MODULE)); + MOD_DEC_USE_COUNT; /* Release lock--if device is not open, module can be now freed */ + /* The interface is released automatically when we return from this function */ +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc: Start of module API ******************************* */ + +/* {{{ [fold] qc_init(void) */ +static int __init qc_init(void) +{ + int r; + if (qcdebug) PDEBUG("----------LOADING QUICKCAM MODULE------------"); + if (qcdebug) PDEBUG("struct quickcam size: %i", (int)sizeof(struct quickcam)); + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_init()"); + qc_proc_init(); /* Ignore if procfs entry creation fails */ + r = usb_register(&qc_usb_driver); + if (r<0) qc_proc_exit(); + if (r<0) if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGERRORS) PDEBUG("failed qc_init()=%i",r); + return r; +} +/* }}} */ +/* {{{ [fold] qc_exit(void) */ +static void __exit qc_exit(void) +{ + if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGINIT) PDEBUG("qc_exit()"); + usb_deregister(&qc_usb_driver); /* Will also call qc_usb_disconnect() if necessary */ + qc_proc_exit(); +} +/* }}} */ + +module_init(qc_init); +module_exit(qc_exit); +/* }}} */ + +/* End of file */ --- linux-2.6.27.orig/ubuntu/qc-usb/qc-hdcs.c +++ linux-2.6.27/ubuntu/qc-usb/qc-hdcs.c @@ -0,0 +1,734 @@ +/* Start of file */ + +/* {{{ [fold] Comments */ +/* + * qc-usb, linux V4L driver for the Logitech QuickCam USB camera family + * + * qc-hdcs.c - HDCS Sensor Implementation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* }}} */ + +#include "quickcam.h" + +/* LSB bit of I2C or register address signifies write (0) or read (1) */ + +/* I2C Address */ +#define HDCS_ADDR (0x55<<1) + +/* {{{ [fold] I2C registers */ +/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */ +#define HDCS_IDENT (0x00<<1) /* Identifications Register */ +#define HDCS_STATUS (0x01<<1) /* Status Register */ +#define HDCS_IMASK (0x02<<1) /* Interrupt Mask Register */ +#define HDCS_PCTRL (0x03<<1) /* Pad Control Register */ +#define HDCS_PDRV (0x04<<1) /* Pad Drive Control Register */ +#define HDCS_ICTRL (0x05<<1) /* Interface Control Register */ +#define HDCS_ITMG (0x06<<1) /* Interface Timing Register */ +#define HDCS_BFRAC (0x07<<1) /* Baud Fraction Register */ +#define HDCS_BRATE (0x08<<1) /* Baud Rate Register */ +#define HDCS_ADCCTRL (0x09<<1) /* ADC Control Register */ +#define HDCS_FWROW (0x0A<<1) /* First Window Row Register */ +#define HDCS_FWCOL (0x0B<<1) /* First Window Column Register */ +#define HDCS_LWROW (0x0C<<1) /* Last Window Row Register */ +#define HDCS_LWCOL (0x0D<<1) /* Last Window Column Register */ +#define HDCS_TCTRL (0x0E<<1) /* Timing Control Register */ +#define HDCS_ERECPGA (0x0F<<1) /* PGA Gain Register: Even Row, Even Column */ +#define HDCS_EROCPGA (0x10<<1) /* PGA Gain Register: Even Row, Odd Column */ +#define HDCS_ORECPGA (0x11<<1) /* PGA Gain Register: Odd Row, Even Column */ +#define HDCS_OROCPGA (0x12<<1) /* PGA Gain Register: Odd Row, Odd Column */ +#define HDCS_ROWEXPL (0x13<<1) /* Row Exposure Low Register */ +#define HDCS_ROWEXPH (0x14<<1) /* Row Exposure High Register */ + +/* I2C Registers only for HDCS-1000/1100 */ +#define HDCS00_SROWEXPL (0x15<<1) /* Sub-Row Exposure Low Register */ +#define HDCS00_SROWEXPH (0x16<<1) /* Sub-Row Exposure High Register */ +#define HDCS00_CONFIG (0x17<<1) /* Configuration Register */ +#define HDCS00_CONTROL (0x18<<1) /* Control Register */ + +/* I2C Registers only for HDCS-1020 */ +#define HDCS20_SROWEXP (0x15<<1) /* Sub-Row Exposure Register */ +#define HDCS20_ERROR (0x16<<1) /* Error Control Register */ +#define HDCS20_ITMG2 (0x17<<1) /* Interface Timing 2 Register */ +#define HDCS20_ICTRL2 (0x18<<1) /* Interface Control 2 Register */ +#define HDCS20_HBLANK (0x19<<1) /* Horizontal Blank Register */ +#define HDCS20_VBLANK (0x1A<<1) /* Vertical Blank Register */ +#define HDCS20_CONFIG (0x1B<<1) /* Configuration Register */ +#define HDCS20_CONTROL (0x1C<<1) /* Control Register */ +/* }}} */ + +#define IS_870(qc) (GET_PRODUCTID(qc)==0x870) +#define IS_1020(qc) ((qc)->sensor_data.sensor->flag != 0) +#define GET_CONTROL (IS_1020(qc) ? HDCS20_CONTROL : HDCS00_CONTROL) +#define GET_CONFIG (IS_1020(qc) ? HDCS20_CONFIG : HDCS00_CONFIG) + +#define I2C_SET_CHECK(reg,val) if ((r = qc_i2c_set(qc,(reg),(val)))<0) goto fail +#define STV_SET_CHECK(reg,val) if ((r = qc_stv_set(qc,(reg),(val)))<0) goto fail +#define STV_SETW_CHECK(reg,val) if ((r = qc_stv_setw(qc,(reg),(val)))<0) goto fail + +/* Enables experimental compressed mode, works with HDCS-1000/0x840, + mode derived from USB logs obtained from HDCS-1020/0x870 + (should give 640x480), not tested with HDCS-1020. + On HDCS-1000, gives 30 fps but data is in unknown format, + observed image width 163 bytes (how many pixels?). + Frame length appears to vary, typically 3300-4550 bytes. + (apparently quite simple, however). + Use this with DUMPDATA mode. */ +#define HDCS_COMPRESS 0 + +#if HDCS_COMPRESS +/* {{{ [fold] hdcs_compress_init(struct quickcam *qc, int flags) */ +static int hdcs_compress_init(struct quickcam *qc, int flags) +{ + int r; + + if (flags & 1) { + /************************************** Plugin camera **************************************/ + + STV_SET_CHECK(0x1440, 0x00); /* Turn on/off isochronous stream */ + // if ((r = qc_stv_getw(qc, 0xE00A)) != 0x0870) /* ProductId */ + // PDEBUG("Bad value 0x%02X in reg 0xE00A, should be 0x0870", r); + + STV_SET_CHECK(0x0423, 0x05); /* Unknown (sometimes 4, sometimes 5) */ + // Warning: I2C address 0xBA is invalid + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x0a) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x0a", r); + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + + if ((r = qc_stv_get(qc, 0x1444)) != 0x10) /* ? */ + PDEBUG("Bad value 0x%02X in reg 0x1444, should be 0x10", r); + if ((r = qc_stv_get(qc, 0x1444)) != 0x10) /* ? */ + PDEBUG("Bad value 0x%02X in reg 0x1444, should be 0x10", r); + if ((r = qc_stv_get(qc, 0x1444)) != 0x10) /* ? */ + PDEBUG("Bad value 0x%02X in reg 0x1444, should be 0x10", r); + + STV_SET_CHECK(0x0423, 0x05); /* Unknown (sometimes 4, sometimes 5) */ + // Warning: I2C address 0x20 is invalid + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x0a) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x0a", r); + // Warning: I2C address 0x20 is invalid + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x0a) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x0a", r); + // Warning: I2C address 0x20 is invalid + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x0a) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x0a", r); + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x02) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x02", r); + // if ((r = qc_stv_get(qc, 0x1410)) != 0x10) /* I2C area, first reg value */ + // PDEBUG("Bad value 0x%02X in reg 0x1410, should be 0x10", r); + + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x02) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x02", r); + // if ((r = qc_stv_get(qc, 0x1410)) != 0x10) /* I2C area, first reg value */ + // PDEBUG("Bad value 0x%02X in reg 0x1410, should be 0x10", r); + + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + if ((r = qc_stv_get(qc, 0x0424)) != 0x02) /* Successfully transmitted I2C commands */ + PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x02", r); + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x02) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x02", r); + // if ((r = qc_stv_get(qc, 0x1410)) != 0x10) /* I2C area, first reg value */ + // PDEBUG("Bad value 0x%02X in reg 0x1410, should be 0x10", r); + + // if ((r = qc_get_i2c(qc, qc->sensor_data.sensor, HDCS_IDENT))<0) /* Identifications Register */ + // PDEBUG("error reading sensor reg HDCS_IDENT"); + // if ((r = qc_stv_get(qc, 0x0424)) != 0x02) /* Successfully transmitted I2C commands */ + // PDEBUG("Bad value 0x%02X in reg 0x0424, should be 0x02", r); + // if ((r = qc_stv_get(qc, 0x1410)) != 0x10) /* I2C area, first reg value */ + // PDEBUG("Bad value 0x%02X in reg 0x1410, should be 0x10", r); + + STV_SET_CHECK(0x1500, 0x1D); /* ? */ + if ((r = qc_stv_get(qc, 0x1443)) != 0x00) /* Scan rate? */ + PDEBUG("Bad value 0x%02X in reg 0x1443, should be 0x00", r); + STV_SET_CHECK(0x1443, 0x01); /* Scan rate? */ + if ((r = qc_stv_get(qc, 0x1443)) != 0x01) /* Scan rate? */ + PDEBUG("Bad value 0x%02X in reg 0x1443, should be 0x01", r); + STV_SET_CHECK(0x1443, 0x00); /* Scan rate? */ + + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + I2C_SET_CHECK(GET_CONTROL, 0x04); /* Control Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + I2C_SET_CHECK(GET_CONTROL, 0x00); /* Control Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1446, 0x00); /* ? */ + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + if ((r = qc_stv_get(qc, 0x1445)) != 0x04) /* Turn LED on/off? */ + PDEBUG("Bad value 0x%02X in reg 0x1445, should be 0x04", r); + I2C_SET_CHECK(HDCS_ERECPGA, 0x3B); /* PGA Gain Register: Even Row, Even Column */ + I2C_SET_CHECK(HDCS_EROCPGA, 0x3B); /* PGA Gain Register: Even Row, Odd Column */ + I2C_SET_CHECK(HDCS_ORECPGA, 0x3B); /* PGA Gain Register: Odd Row, Even Column */ + I2C_SET_CHECK(HDCS_OROCPGA, 0x3B); /* PGA Gain Register: Odd Row, Odd Column */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1504, 0x07); /* ? */ + STV_SET_CHECK(0x1503, 0x45); /* ? */ + if ((r = qc_stv_get(qc, 0x1500)) != 0x1d) /* ? */ + PDEBUG("Bad value 0x%02X in reg 0x1500, should be 0x1d", r); + STV_SET_CHECK(0x1500, 0x1D); /* ? */ + // if ((r = qc_stv_getw(qc, 0xE00A)) != 0x0870) /* ProductId */ + // PDEBUG("Bad value 0x%02X in reg 0xE00A, should be 0x0870", r); + } + + if (flags & 2) { + /************************************** Start grabbing **************************************/ + + // if ((r = qc_stv_getw(qc, 0xE00A)) != 0x0870) /* ProductId */ + // PDEBUG("Bad value 0x%02X in reg 0xE00A, should be 0x0870", r); + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + STV_SET_CHECK(0x1500, 0x1D); /* ? */ + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x15C3, 0x02); /* Y-Control, 1: 288 lines, 2: 144 lines */ + STV_SETW_CHECK(0x15C1, 0x027B); /* Max. ISO packet size */ + I2C_SET_CHECK(HDCS_FWROW, 0x00); /* First Window Row Register */ + I2C_SET_CHECK(HDCS_FWCOL, 0x0B); /* First Window Column Register */ + I2C_SET_CHECK(HDCS_LWROW, 0x3D); /* Last Window Row Register */ + I2C_SET_CHECK(HDCS_LWCOL, 0x5A); /* Last Window Column Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1680, 0x00); /* X-Control, 0xa: 352 columns, 6: 176 columns */ + I2C_SET_CHECK(HDCS_TCTRL, IS_1020(qc) ? 0xCB : 0x6B); /* Timing Control Register */ + I2C_SET_CHECK(HDCS_ICTRL, 0x00); /* Interface Control Register */ + I2C_SET_CHECK(HDCS_ITMG, 0x16); /* Interface Timing Register */ + if (IS_1020(qc)) I2C_SET_CHECK(HDCS20_HBLANK, 0xD6); /* Horizontal Blank Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1446, 0x00); /* ? */ + if ((r = qc_stv_get(qc, 0x1446)) != 0x00) /* ? */ + PDEBUG("Bad value 0x%02X in reg 0x1446, should be 0x00", r); + STV_SET_CHECK(0x1446, 0x00); /* ? */ + I2C_SET_CHECK(HDCS_ROWEXPL, 0x7B); /* Row Exposure Low Register */ + I2C_SET_CHECK(HDCS_ROWEXPH, 0x00); /* Row Exposure High Register */ + if (IS_1020(qc)) { + I2C_SET_CHECK(HDCS20_SROWEXP, 0x01); /* Sub-Row Exposure Register */ + } else { + I2C_SET_CHECK(HDCS00_SROWEXPL, 0x01<<2); + I2C_SET_CHECK(HDCS00_SROWEXPH, 0x00); + } + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1501, 0xC2); /* ? */ + STV_SET_CHECK(0x1502, 0xB0); /* ? */ + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + + /* Start isochronous streaming */ + I2C_SET_CHECK(GET_CONTROL, 0x04); /* Control Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1440, 0x01); /* Turn on/off isochronous stream */ + + if ((r = qc_stv_get(qc, 0x1445)) != 0x04) /* Turn LED on/off? */ + PDEBUG("Bad value 0x%02X in reg 0x1445, should be 0x04", r); + if ((r = qc_stv_get(qc, 0x1445)) != 0x04) /* Turn LED on/off? */ + PDEBUG("Bad value 0x%02X in reg 0x1445, should be 0x04", r); + if ((r = qc_stv_get(qc, 0x1445)) != 0x04) /* Turn LED on/off? */ + PDEBUG("Bad value 0x%02X in reg 0x1445, should be 0x04", r); + + /* Stop isochronous streaming */ + STV_SET_CHECK(0x1440, 0x00); /* Turn on/off isochronous stream */ + I2C_SET_CHECK(GET_CONTROL, 0x00); /* Control Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + STV_SET_CHECK(0x1500, 0x1D); /* ? */ + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x15C3, 0x02); /* Y-Control, 1: 288 lines, 2: 144 lines */ + STV_SETW_CHECK(0x15C1, 0x027B); /* Max. ISO packet size */ + I2C_SET_CHECK(HDCS_FWROW, 0x00); /* First Window Row Register */ + I2C_SET_CHECK(HDCS_FWCOL, 0x0B); /* First Window Column Register */ + I2C_SET_CHECK(HDCS_LWROW, 0x3D); /* Last Window Row Register */ + I2C_SET_CHECK(HDCS_LWCOL, 0x5A); /* Last Window Column Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1680, 0x00); /* X-Control, 0xa: 352 columns, 6: 176 columns */ + I2C_SET_CHECK(HDCS_TCTRL, IS_1020(qc) ? 0xCB : 0x6B); /* Timing Control Register */ + I2C_SET_CHECK(HDCS_ICTRL, 0x00); /* Interface Control Register */ + I2C_SET_CHECK(HDCS_ITMG, 0x16); /* Interface Timing Register */ + if (IS_1020(qc)) I2C_SET_CHECK(HDCS20_HBLANK, 0xD6); /* Horizontal Blank Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1446, 0x00); /* ? */ + if ((r = qc_stv_get(qc, 0x1446)) != 0x00) /* ? */ + PDEBUG("Bad value 0x%02X in reg 0x1446, should be 0x00", r); + STV_SET_CHECK(0x1446, 0x00); /* ? */ + I2C_SET_CHECK(HDCS_ROWEXPL, 0x7B); /* Row Exposure Low Register */ + I2C_SET_CHECK(HDCS_ROWEXPH, 0x00); /* Row Exposure High Register */ + if (IS_1020(qc)) { + I2C_SET_CHECK(HDCS20_SROWEXP, 0x01); /* Sub-Row Exposure Register */ + } else { + I2C_SET_CHECK(HDCS00_SROWEXPL, 0x01<<2); + I2C_SET_CHECK(HDCS00_SROWEXPH, 0x00); + } + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1501, 0xC2); /* ? */ + STV_SET_CHECK(0x1502, 0xB0); /* ? */ + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + + /* Start isochronous streaming */ + I2C_SET_CHECK(GET_CONTROL, 0x04); /* Control Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + if ((r = qc_stv_get(qc, 0x1445)) != 0x04) /* Turn LED on/off? */ + PDEBUG("Bad value 0x%02X in reg 0x1445, should be 0x04", r); + STV_SET_CHECK(0x1440, 0x01); /* Turn on/off isochronous stream */ + + /* Stop isochronous streaming */ + STV_SET_CHECK(0x1440, 0x00); /* Turn on/off isochronous stream */ + I2C_SET_CHECK(GET_CONTROL, 0x00); /* Control Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + + STV_SET_CHECK(0x0423, 0x04); /* Unknown (sometimes 4, sometimes 5) */ + STV_SET_CHECK(0x1500, 0x1D); /* ? */ + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x15C3, 0x02); /* Y-Control, 1: 288 lines, 2: 144 lines */ + STV_SETW_CHECK(0x15C1, 0x0230); /* Max. ISO packet size */ + I2C_SET_CHECK(HDCS_FWROW, 0x00); /* First Window Row Register */ + I2C_SET_CHECK(HDCS_FWCOL, 0x07); /* First Window Column Register */ + I2C_SET_CHECK(HDCS_LWROW, 0x49); /* Last Window Row Register */ + I2C_SET_CHECK(HDCS_LWCOL, 0x5E); /* Last Window Column Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1680, 0x00); /* X-Control, 0xa: 352 columns, 6: 176 columns */ + I2C_SET_CHECK(HDCS_TCTRL, IS_1020(qc) ? 0xCE : 0x6E); /* Timing Control Register */ + I2C_SET_CHECK(HDCS_ICTRL, 0x00); /* Interface Control Register */ + I2C_SET_CHECK(HDCS_ITMG, 0x16); /* Interface Timing Register */ + if (IS_1020(qc)) I2C_SET_CHECK(HDCS20_HBLANK, 0xCF); /* Horizontal Blank Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1446, 0x00); /* ? */ + if ((r = qc_stv_get(qc, 0x1446)) != 0x00) /* ? */ + PDEBUG("Bad value 0x%02X in reg 0x1446, should be 0x00", r); + STV_SET_CHECK(0x1446, 0x00); /* ? */ + I2C_SET_CHECK(HDCS_ROWEXPL, 0x62); /* Row Exposure Low Register */ + I2C_SET_CHECK(HDCS_ROWEXPH, 0x00); /* Row Exposure High Register */ + if (IS_1020(qc)) { + I2C_SET_CHECK(HDCS20_SROWEXP, 0x1A); /* Sub-Row Exposure Register */ + } else { + I2C_SET_CHECK(HDCS00_SROWEXPL, 0x1A<<2); + I2C_SET_CHECK(HDCS00_SROWEXPH, 0x00); + } + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1501, 0xB6); /* ? */ + STV_SET_CHECK(0x1502, 0xA8); /* ? */ + I2C_SET_CHECK(HDCS_PCTRL, 0x63); /* Pad Control Register */ + I2C_SET_CHECK(HDCS_PDRV, 0x00); /* Pad Drive Control Register */ + I2C_SET_CHECK(GET_CONFIG, 0x08); /* Configuration Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + + /* Start isochronous streaming */ + I2C_SET_CHECK(GET_CONTROL, 0x04); /* Control Register */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + STV_SET_CHECK(0x1440, 0x01); /* Turn on/off isochronous stream */ + + if ((r = qc_stv_get(qc, 0x1445)) != 0x04) /* Turn LED on/off? */ + PDEBUG("Bad value 0x%02X in reg 0x1445, should be 0x04", r); + } + + return 0; +fail: return r; +} +/* }}} */ +#endif +/* {{{ [fold] hdcs_init: Initialise parameters (from Georg Acher's user module for hdcs sensor) */ +static int hdcs_init(struct quickcam *qc) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + unsigned char control = GET_CONTROL; + unsigned char config = GET_CONFIG; + int r,tctrl,astrt,psmp; + + if (sd->compress) return -EINVAL; + sd->maxwidth = IS_1020(qc) ? 352 : 360; /* CIF */ + sd->maxheight = IS_1020(qc) ? 292 : 296; + if (sd->subsample) { + sd->maxwidth /= 2; /* QCIF */ + sd->maxheight /= 2; + } + if ((r = qc_i2c_break(qc))<0) goto fail; /* The following setting must go into same I2C packet */ +#if HDCS_COMPRESS +r = hdcs_compress_init(qc, 3); +qc_i2c_wait(qc); +qc_i2c_break(qc); +qc_stv_set(qc, 0x1440, 0x00); /* Turn on/off isochronous stream */ +qc_i2c_set(qc, GET_CONTROL, BIT(1)); /* Stop and enter sleep mode */ +qc_i2c_wait(qc); +if (r) PDEBUG("hdcs_compress_init(1) = %i", r); +return 0; +#endif + STV_SET_CHECK(STV_REG23, 0); + + /* Set the STV0602AA in STV0600 emulation mode */ + if (IS_870(qc)) STV_SET_CHECK(0x1446, 1); + + /* Reset the image sensor (keeping it to 1 is a problem) */ + I2C_SET_CHECK(control, 1); + if ((r = qc_i2c_wait(qc))<0) goto fail; + I2C_SET_CHECK(control, 0); + if ((r = qc_i2c_wait(qc))<0) goto fail; + + I2C_SET_CHECK(HDCS_STATUS, BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)); /* Clear status (writing 1 will clear the corresponding status bit) */ + + I2C_SET_CHECK(HDCS_IMASK, 0x00); /* Disable all interrupts */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + + STV_SET_CHECK(STV_REG00, 0x1D); + STV_SET_CHECK(STV_REG04, 0x07); + STV_SET_CHECK(STV_REG03, 0x95); + + STV_SET_CHECK(STV_REG23, 0); + + STV_SET_CHECK(STV_SCAN_RATE, 0x20); /* Larger -> slower */ + + STV_SETW_CHECK(STV_ISO_SIZE, 847); /* ISO-Size, 0x34F = 847 .. 0x284 = 644 */ + + /* Set mode */ + STV_SET_CHECK(STV_Y_CTRL, 0x01); /* 0x02: half, 0x01: full */ + STV_SET_CHECK(STV_X_CTRL, 0x0A); /* 0x06: half, 0x0A: full */ + + /* These are not good final values, which will be set in set_size */ + /* However, it looks like it's best to set some values at this point nevertheless */ + I2C_SET_CHECK(HDCS_FWROW, 0); /* Start at row 0 */ + I2C_SET_CHECK(HDCS_FWCOL, 0); /* Start at column 0 */ + I2C_SET_CHECK(HDCS_LWROW, 0x47); /* End at row 288 */ + I2C_SET_CHECK(HDCS_LWCOL, 0x57); /* End at column 352 */ + + /* 0x07 - 0x50 */ + astrt = 3; /* 0..3, doesn't seem to have any effect... hmm.. smaller is slower with subsampling */ + if (!IS_1020(qc)) { + /* HDCS-1000 (tctrl was 0x09, but caused some HDCS-1000 not to work) */ + /* Frame rate on HDCS-1000 0x46D:0x840 depending on PSMP: + * 4 = doesn't work at all + * 5 = 7.8 fps, + * 6 = 6.9 fps, + * 8 = 6.3 fps, + * 10 = 5.5 fps, + * 15 = 4.4 fps, + * 31 = 2.8 fps */ + /* Frame rate on HDCS-1000 0x46D:0x870 depending on PSMP: + * 15 = doesn't work at all + * 18 = doesn't work at all + * 19 = 7.3 fps + * 20 = 7.4 fps + * 21 = 7.4 fps + * 22 = 7.4 fps + * 24 = 6.3 fps + * 30 = 5.4 fps */ + psmp = IS_870(qc) ? 20 : 5; /* 4..31 (was 30, changed to 20) */ + tctrl = (astrt<<5) | psmp; + } else { + /* HDCS-1020 (tctrl was 0x7E, but causes slow frame rate on HDCS-1020) */ + /* Changed to 6 which should give 8.1 fps */ + psmp = 6; /* 4..31 (was 9, changed to 6 to improve fps */ + tctrl = (astrt<<6) | psmp; + } + I2C_SET_CHECK(HDCS_TCTRL, tctrl); /* Set PGA sample duration (was 0x7E for IS_870, but caused slow framerate with HDCS-1020) */ + + I2C_SET_CHECK(control, 0); /* FIXME:should not be anymore necessary (already done) */ + + I2C_SET_CHECK(HDCS_ROWEXPL, 0); + I2C_SET_CHECK(HDCS_ROWEXPH, 0); + if (IS_1020(qc)) { + I2C_SET_CHECK(HDCS20_SROWEXP, 0); + I2C_SET_CHECK(HDCS20_ERROR, BIT(0)|BIT(2)); /* Clear error conditions by writing 1 */ + } else { + I2C_SET_CHECK(HDCS00_SROWEXPL, 0); + I2C_SET_CHECK(HDCS00_SROWEXPH, 0); + } + if ((r = qc_i2c_wait(qc))<0) goto fail; + + STV_SET_CHECK(STV_REG01, 0xB5); + STV_SET_CHECK(STV_REG02, 0xA8); + + I2C_SET_CHECK(HDCS_PCTRL, BIT(6)|BIT(5)|BIT(1)|BIT(0)); + I2C_SET_CHECK(HDCS_PDRV, 0x00); + I2C_SET_CHECK(HDCS_ICTRL, (sd->subsample ? BIT(7) : 0) | BIT(5)); + I2C_SET_CHECK(HDCS_ITMG, BIT(4)|BIT(1)); + + /* CONFIG: Bit 3: continous frame capture, bit 2: stop when frame complete */ + I2C_SET_CHECK(config, (sd->subsample ? BIT(5) : 0) | BIT(3)); + I2C_SET_CHECK(HDCS_ADCCTRL, 10); /* ADC output resolution to 10 bits */ + if ((r = qc_i2c_wait(qc))<0) goto fail; +fail: return r; +} +/* }}} */ +/* {{{ [fold] hdcs_start: Start grabbing */ +static int hdcs_start(struct quickcam *qc) +{ + int r; +#if HDCS_COMPRESS +r = hdcs_compress_init(qc, 2); +qc_i2c_wait(qc); +if (r) PDEBUG("hdcs_compress_init(1) = %i", r); +return 0; +#endif + if ((r = qc_i2c_break(qc))<0) goto fail; + I2C_SET_CHECK(GET_CONTROL, BIT(2)); /* Run enable */ + if ((r = qc_i2c_break(qc))<0) goto fail; +fail: return r; +} +/* }}} */ +/* {{{ [fold] hdcs_stop: Stop grabbing */ +static int hdcs_stop(struct quickcam *qc) +{ + int r; + if ((r = qc_i2c_break(qc))<0) goto fail; + I2C_SET_CHECK(GET_CONTROL, BIT(1)); /* Stop and enter sleep mode */ + r = qc_i2c_wait(qc); +fail: return r; +} +/* }}} */ +/* {{{ [fold] hdcs_set_exposure: Set exposure time, val=0..65535 */ +static int hdcs_set_exposure(struct quickcam *qc, unsigned int val) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + unsigned char control = GET_CONTROL; + unsigned int rowexp; /* rowexp,srowexp = 15 bits (0..32767) */ + unsigned int srowexp; /* sub-row exposure (smaller is brighter) */ + unsigned int max_srowexp; /* Maximum srowexp value + 1 */ + int r; + + /* Absolute black at srowexp=2672,width=360; 2616, width=352; 1896, width=256 for hdcs1000 */ + + if (val==sd->exposure) return 0; + sd->exposure = val; + val *= 16; /* 16 seems to be the smallest change that actually affects brightness */ + max_srowexp = sd->width*15/2 - 104 + 1; + srowexp = max_srowexp - (val % max_srowexp) - 1; + rowexp = val / max_srowexp; + if (qcdebug&QC_DEBUGCAMERA) PDEBUG("width=%i height=%i rowexp=%i srowexp=%i",sd->width,sd->height,rowexp,srowexp); + if ((r = qc_i2c_break(qc))<0) goto fail; /* The following setting must go into same I2C packet */ + I2C_SET_CHECK(control, 0); /* Stop grabbing */ + I2C_SET_CHECK(HDCS_ROWEXPL, rowexp & 0xFF); /* Number of rows to expose */ + I2C_SET_CHECK(HDCS_ROWEXPH, rowexp >> 8); + if (IS_1020(qc)) { + srowexp = 0; //FIXME:need formula to compute srowexp for HDCS1020! + srowexp >>= 2; /* Bits 0..1 are hardwired to 0 */ + I2C_SET_CHECK(HDCS20_SROWEXP, srowexp & 0xFF); /* Number of pixels to expose */ + } else { + I2C_SET_CHECK(HDCS00_SROWEXPL, srowexp & 0xFF); /* Number of pixels to expose */ + I2C_SET_CHECK(HDCS00_SROWEXPH, srowexp >> 8); + } + if (IS_1020(qc)) { + I2C_SET_CHECK(HDCS20_ERROR, BIT(0)); /* Reset exposure error flag */ + } else { + I2C_SET_CHECK(HDCS_STATUS, BIT(4)); /* Reset exposure error flag */ + } + I2C_SET_CHECK(control, BIT(2)); /* Restart grabbing */ + if ((r = qc_i2c_break(qc))<0) goto fail; +#if 0 + /* Warning: the code below will cause about 0.1 second delay and may cause lost frames */ + if (PARANOID) { + /* Check if the new exposure setting is valid */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + if (IS_1020(qc)) { + if ((r = qc_get_i2c(qc,qc->sensor_data.sensor, HDCS20_ERROR))<0) goto fail; + if (r & BIT(0)) PDEBUG("exposure error (1020)"); + } else { + if ((r = qc_get_i2c(qc,qc->sensor_data.sensor, HDCS_STATUS))<0) goto fail; + if (r & BIT(4)) PDEBUG("exposure error (1000)"); + } + } + if ((r = qc_i2c_wait(qc))<0) goto fail; +#endif + qc_frame_flush(qc); +fail: return (r<0) ? r : 0; +} +/* }}} */ +/* {{{ [fold] hdcs_set_gains: Set gains */ +static int hdcs_set_gains(struct quickcam *qc, unsigned int hue, unsigned int sat, unsigned int val) +{ + static const unsigned int min_gain = 8; + struct qc_sensor_data *sd = &qc->sensor_data; + unsigned int rgain, bgain, ggain; + int r; + qc_hsv2rgb(hue, sat, val, &rgain, &bgain, &ggain); + rgain >>= 8; /* After this the values are 0..255 */ + ggain >>= 8; + bgain >>= 8; + rgain = MAX(rgain, min_gain); /* Do not allow very small values, they cause bad (low-contrast) image */ + ggain = MAX(ggain, min_gain); + bgain = MAX(bgain, min_gain); + if (rgain==sd->rgain && ggain==sd->ggain && bgain==sd->bgain) return 0; + sd->rgain = rgain; + sd->ggain = ggain; + sd->bgain = bgain; + if (rgain > 127) rgain = rgain/2 | BIT(7); /* Bit 7 doubles the programmed values */ + if (ggain > 127) ggain = ggain/2 | BIT(7); /* Double programmed value if necessary */ + if (bgain > 127) bgain = bgain/2 | BIT(7); + if ((r = qc_i2c_break(qc))<0) goto fail; + I2C_SET_CHECK(HDCS_ERECPGA, ggain); + I2C_SET_CHECK(HDCS_EROCPGA, rgain); + I2C_SET_CHECK(HDCS_ORECPGA, bgain); + I2C_SET_CHECK(HDCS_OROCPGA, ggain); +fail: return r; +} +/* }}} */ +/* {{{ [fold] hdcs_set_levels() */ +static int hdcs_set_levels(struct quickcam *qc, unsigned int exp, unsigned int gain, unsigned int hue, unsigned int sat) +{ + int r = 0; +//#if !HDCS_COMPRESS + if ((r = hdcs_set_exposure(qc, gain))<0) goto fail; +//#endif + hdcs_set_gains(qc, hue, sat, exp); +fail: return r; +} +/* }}} */ +/* {{{ [fold] hdcs_set_size: Sets the size of the capture window */ +/* + * Sets the size (scaling) of the capture window. + * If subsample could return the image size we use subsample. + */ +static int hdcs_set_size(struct quickcam *qc, unsigned int width, unsigned int height) +{ + /* The datasheet doesn't seem to say this, but HDCS-1000 + * has visible windows size of 360x296 pixels, the first upper-left + * visible pixel is at 8,8. + * From Andrey's test image: looks like HDCS-1020 upper-left + * visible pixel is at 24,8 (y maybe even smaller?) and lower-right + * visible pixel at 375,299 (x maybe even larger?) + */ + unsigned int originx = IS_1020(qc) ? 24 : 8; /* First visible pixel */ + unsigned int maxwidth = IS_1020(qc) ? 352 : 360; /* Visible sensor size */ + unsigned int originy = 8; + unsigned int maxheight = IS_1020(qc) ? 292 : 296; + + unsigned char control = GET_CONTROL; + struct qc_sensor_data *sd = &qc->sensor_data; + int r; + unsigned int x, y; + +#if HDCS_COMPRESS + return 0; +#endif + if (sd->subsample) { + width *= 2; + height *= 2; + width = (width + 3)/4*4; /* Width must be multiple of 4 */ + height = (height + 3)/4*4; /* Height must be multiple of 4 */ + sd->width = width / 2; + sd->height = height / 2; /* The image sent will be subsampled by 2 */ + } else { + sd->width = width = (width + 3)/4*4; /* Width must be multiple of 4 */ + sd->height = height = (height + 3)/4*4; /* Height must be multiple of 4 */ + } + x = (maxwidth - width)/2; /* Center image by computing upper-left corner */ + y = (maxheight - height)/2; + width /= 4; + height /= 4; + x = (x + originx)/4; /* Must be multiple of 4 (low bits wired to 0) */ + y = (y + originy)/4; + + if ((r = qc_i2c_break(qc))<0) goto fail; + I2C_SET_CHECK(control, 0); /* Stop grabbing */ + I2C_SET_CHECK(HDCS_FWROW, y); + I2C_SET_CHECK(HDCS_FWCOL, x); + I2C_SET_CHECK(HDCS_LWROW, y+height-1); + I2C_SET_CHECK(HDCS_LWCOL, x+width-1); + I2C_SET_CHECK(control, BIT(2)); /* Restart grabbing */ + + /* The exposure timings need to be recomputed when size is changed */ + x = sd->exposure; + sd->exposure = -1; + if ((r = hdcs_set_exposure(qc, x))<0) goto fail; +fail: return r; +} +/* }}} */ + +/* {{{ [fold] struct qc_sensor qc_sensor_hdcs1000 */ +const struct qc_sensor qc_sensor_hdcs1000 = { + name: "HDCS-1000/1100", + manufacturer: "Hewlett Packard", + init: hdcs_init, + start: hdcs_start, + stop: hdcs_stop, + set_size: hdcs_set_size, + set_levels: hdcs_set_levels, + /* Exposure and gain control information */ + autoexposure: FALSE, + adapt_gainlow: 20, + adapt_gainhigh: 20000, + /* Information needed to access the sensor via I2C */ + reg23: 0, + i2c_addr: HDCS_ADDR, + /* Identification information used for auto-detection */ + id_reg: HDCS_IDENT | 1, + id: 0x08, + length_id: 1, + flag: 0, +}; +/* }}} */ +/* {{{ [fold] struct qc_sensor qc_sensor_hdcs1020 */ +const struct qc_sensor qc_sensor_hdcs1020 = { + name: "HDCS-1020", + manufacturer: "Agilent Technologies", + init: hdcs_init, + start: hdcs_start, + stop: hdcs_stop, + set_size: hdcs_set_size, + set_levels: hdcs_set_levels, + /* Exposure and gain control information */ + autoexposure: FALSE, + adapt_gainlow: 20, + adapt_gainhigh: 20000, + /* Information needed to access the sensor via I2C */ + reg23: 0, + i2c_addr: HDCS_ADDR, + /* Identification information used for auto-detection */ + id_reg: HDCS_IDENT | 1, + id: 0x10, + length_id: 1, + flag: 1, +}; +/* }}} */ + +/* End of file */ --- linux-2.6.27.orig/ubuntu/qc-usb/BOM +++ linux-2.6.27/ubuntu/qc-usb/BOM @@ -0,0 +1,4 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=12924 +Current Version: 0.6.6 + +Took a bit of forward porting. Upstream project seems dead anyway. --- linux-2.6.27.orig/ubuntu/qc-usb/qc-formats.c +++ linux-2.6.27/ubuntu/qc-usb/qc-formats.c @@ -0,0 +1,1545 @@ +/* Start of file */ + +/* {{{ [fold] Comments */ +/* + * qc-usb, linux V4L driver for the Logitech QuickCam family + * + * qc-formats.c - converts color formats + * + * Copyright (c) 2001 Jean-Frederic Clere (RGB->YUV conversion) + * 2001 Aaron Holtzman (YUV->RGB conversion, from mpeg2dec) + * 2003 Tuukka Toivonen (Bayer->RGB conversion) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* }}} */ + +#include "quickcam.h" +#include + +#ifndef v4l2_fourcc +/* Four-character-code (FOURCC) */ +#define v4l2_fourcc(a,b,c,d)\ + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) +#endif + +/* {{{ [fold] **** qc_yuv: Start of RGB to YUV conversion functions ******************** */ + +/* {{{ [fold] qc_yuv_interp[256][8] */ +static signed short qc_yuv_interp[256][8] = { +{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,1,0,0,0,1,0,0},{0,1,0,0,0,1,-1,0}, +{1,2,0,0,-1,2,-1,0},{1,2,0,0,-1,2,-2,0},{1,3,0,-1,-1,3,-2,0},{2,3,0,-1,-2,3,-2,0}, +{2,4,0,-1,-2,4,-3,0},{2,5,1,-1,-2,4,-3,0},{2,5,1,-1,-3,5,-4,0},{3,6,1,-1,-3,5,-4,0}, +{3,6,1,-2,-3,6,-5,0},{3,7,1,-2,-4,6,-5,-1},{4,7,1,-2,-4,7,-5,-1},{4,8,1,-2,-4,7,-6,-1}, +{4,9,1,-2,-5,8,-6,-1},{5,9,1,-2,-5,8,-7,-1},{5,10,2,-3,-5,9,-7,-1},{5,10,2,-3,-6,9,-7,-1}, +{5,11,2,-3,-6,10,-8,-1},{6,11,2,-3,-6,10,-8,-1},{6,12,2,-3,-7,11,-9,-1},{6,13,2,-3,-7,11,-9,-1}, +{7,13,2,-4,-7,12,-10,-1},{7,14,2,-4,-8,12,-10,-2},{7,14,2,-4,-8,13,-10,-2},{8,15,3,-4,-8,13,-11,-2}, +{8,15,3,-4,-9,14,-11,-2},{8,16,3,-4,-9,14,-12,-2},{8,17,3,-5,-9,15,-12,-2},{9,17,3,-5,-10,15,-12,-2}, +{9,18,3,-5,-10,16,-13,-2},{9,18,3,-5,-10,16,-13,-2},{10,19,3,-5,-11,17,-14,-2},{10,19,3,-5,-11,17,-14,-2}, +{10,20,4,-6,-11,18,-15,-2},{11,20,4,-6,-12,18,-15,-3},{11,21,4,-6,-12,19,-15,-3},{11,22,4,-6,-12,19,-16,-3}, +{11,22,4,-6,-13,20,-16,-3},{12,23,4,-6,-13,20,-17,-3},{12,23,4,-7,-13,21,-17,-3},{12,24,4,-7,-14,21,-18,-3}, +{13,24,5,-7,-14,22,-18,-3},{13,25,5,-7,-14,22,-18,-3},{13,26,5,-7,-15,23,-19,-3},{14,26,5,-7,-15,23,-19,-3}, +{14,27,5,-8,-15,24,-20,-3},{14,27,5,-8,-16,24,-20,-3},{14,28,5,-8,-16,25,-20,-4},{15,28,5,-8,-16,25,-21,-4}, +{15,29,5,-8,-17,26,-21,-4},{15,30,6,-8,-17,26,-22,-4},{16,30,6,-9,-17,27,-22,-4},{16,31,6,-9,-18,27,-23,-4}, +{16,31,6,-9,-18,28,-23,-4},{17,32,6,-9,-18,28,-23,-4},{17,32,6,-9,-19,29,-24,-4},{17,33,6,-9,-19,29,-24,-4}, +{17,34,6,-10,-19,30,-25,-4},{18,34,6,-10,-20,30,-25,-4},{18,35,7,-10,-20,31,-25,-5},{18,35,7,-10,-20,31,-26,-5}, +{19,36,7,-10,-21,32,-26,-5},{19,36,7,-10,-21,32,-27,-5},{19,37,7,-11,-21,33,-27,-5},{20,37,7,-11,-22,33,-28,-5}, +{20,38,7,-11,-22,34,-28,-5},{20,39,7,-11,-22,34,-28,-5},{20,39,7,-11,-23,35,-29,-5},{21,40,8,-11,-23,35,-29,-5}, +{21,40,8,-12,-23,36,-30,-5},{21,41,8,-12,-24,36,-30,-5},{22,41,8,-12,-24,37,-30,-6},{22,42,8,-12,-24,37,-31,-6}, +{22,43,8,-12,-25,38,-31,-6},{23,43,8,-12,-25,38,-32,-6},{23,44,8,-13,-25,39,-32,-6},{23,44,9,-13,-26,39,-33,-6}, +{23,45,9,-13,-26,40,-33,-6},{24,45,9,-13,-26,40,-33,-6},{24,46,9,-13,-27,41,-34,-6},{24,47,9,-14,-27,41,-34,-6}, +{25,47,9,-14,-27,42,-35,-6},{25,48,9,-14,-28,42,-35,-6},{25,48,9,-14,-28,43,-36,-6},{26,49,9,-14,-28,43,-36,-7}, +{26,49,10,-14,-29,44,-36,-7},{26,50,10,-15,-29,44,-37,-7},{26,51,10,-15,-29,45,-37,-7},{27,51,10,-15,-30,45,-38,-7}, +{27,52,10,-15,-30,46,-38,-7},{27,52,10,-15,-30,46,-38,-7},{28,53,10,-15,-31,47,-39,-7},{28,53,10,-16,-31,47,-39,-7}, +{28,54,10,-16,-31,48,-40,-7},{29,54,11,-16,-32,48,-40,-7},{29,55,11,-16,-32,49,-41,-7},{29,56,11,-16,-32,49,-41,-8}, +{29,56,11,-16,-33,50,-41,-8},{30,57,11,-17,-33,50,-42,-8},{30,57,11,-17,-33,51,-42,-8},{30,58,11,-17,-34,51,-43,-8}, +{31,58,11,-17,-34,52,-43,-8},{31,59,11,-17,-34,52,-43,-8},{31,60,12,-17,-35,53,-44,-8},{31,60,12,-18,-35,53,-44,-8}, +{32,61,12,-18,-35,54,-45,-8},{32,61,12,-18,-36,54,-45,-8},{32,62,12,-18,-36,55,-46,-8},{33,62,12,-18,-36,55,-46,-9}, +{33,63,12,-18,-37,56,-46,-9},{33,64,12,-19,-37,56,-47,-9},{34,64,12,-19,-37,57,-47,-9},{34,65,13,-19,-38,57,-48,-9}, +{34,65,13,-19,-38,58,-48,-9},{34,66,13,-19,-38,58,-48,-9},{35,66,13,-19,-39,59,-49,-9},{35,67,13,-20,-39,59,-49,-9}, +{35,68,13,-20,-39,60,-50,-9},{36,68,13,-20,-40,60,-50,-9},{36,69,13,-20,-40,61,-51,-9},{36,69,14,-20,-40,61,-51,-9}, +{37,70,14,-20,-41,62,-51,-10},{37,70,14,-21,-41,62,-52,-10},{37,71,14,-21,-41,63,-52,-10},{37,72,14,-21,-42,63,-53,-10}, +{38,72,14,-21,-42,64,-53,-10},{38,73,14,-21,-42,64,-54,-10},{38,73,14,-21,-43,65,-54,-10},{39,74,14,-22,-43,65,-54,-10}, +{39,74,15,-22,-43,66,-55,-10},{39,75,15,-22,-44,66,-55,-10},{40,75,15,-22,-44,67,-56,-10},{40,76,15,-22,-44,67,-56,-10}, +{40,77,15,-22,-45,68,-56,-11},{40,77,15,-23,-45,68,-57,-11},{41,78,15,-23,-45,69,-57,-11},{41,78,15,-23,-46,69,-58,-11}, +{41,79,15,-23,-46,70,-58,-11},{42,79,16,-23,-46,70,-59,-11},{42,80,16,-23,-47,71,-59,-11},{42,81,16,-24,-47,71,-59,-11}, +{43,81,16,-24,-47,72,-60,-11},{43,82,16,-24,-48,72,-60,-11},{43,82,16,-24,-48,73,-61,-11},{43,83,16,-24,-48,73,-61,-11}, +{44,83,16,-24,-49,74,-61,-12},{44,84,16,-25,-49,74,-62,-12},{44,85,17,-25,-49,75,-62,-12},{45,85,17,-25,-50,75,-63,-12}, +{45,86,17,-25,-50,76,-63,-12},{45,86,17,-25,-50,76,-64,-12},{46,87,17,-25,-51,77,-64,-12},{46,87,17,-26,-51,77,-64,-12}, +{46,88,17,-26,-51,78,-65,-12},{46,89,17,-26,-52,78,-65,-12},{47,89,18,-26,-52,79,-66,-12},{47,90,18,-26,-52,79,-66,-12}, +{47,90,18,-26,-53,80,-66,-13},{48,91,18,-27,-53,80,-67,-13},{48,91,18,-27,-53,81,-67,-13},{48,92,18,-27,-54,81,-68,-13}, +{49,92,18,-27,-54,82,-68,-13},{49,93,18,-27,-54,82,-69,-13},{49,94,18,-28,-54,83,-69,-13},{49,94,19,-28,-55,83,-69,-13}, +{50,95,19,-28,-55,84,-70,-13},{50,95,19,-28,-55,84,-70,-13},{50,96,19,-28,-56,85,-71,-13},{51,96,19,-28,-56,85,-71,-13}, +{51,97,19,-29,-56,86,-72,-13},{51,98,19,-29,-57,86,-72,-14},{52,98,19,-29,-57,87,-72,-14},{52,99,19,-29,-57,87,-73,-14}, +{52,99,20,-29,-58,88,-73,-14},{52,100,20,-29,-58,88,-74,-14},{53,100,20,-30,-58,89,-74,-14},{53,101,20,-30,-59,89,-74,-14}, +{53,102,20,-30,-59,90,-75,-14},{54,102,20,-30,-59,90,-75,-14},{54,103,20,-30,-60,91,-76,-14},{54,103,20,-30,-60,91,-76,-14}, +{55,104,20,-31,-60,92,-77,-14},{55,104,21,-31,-61,92,-77,-15},{55,105,21,-31,-61,93,-77,-15},{55,106,21,-31,-61,93,-78,-15}, +{56,106,21,-31,-62,94,-78,-15},{56,107,21,-31,-62,94,-79,-15},{56,107,21,-32,-62,95,-79,-15},{57,108,21,-32,-63,95,-79,-15}, +{57,108,21,-32,-63,96,-80,-15},{57,109,22,-32,-63,96,-80,-15},{58,109,22,-32,-64,97,-81,-15},{58,110,22,-32,-64,97,-81,-15}, +{58,111,22,-33,-64,98,-82,-15},{58,111,22,-33,-65,98,-82,-16},{59,112,22,-33,-65,99,-82,-16},{59,112,22,-33,-65,99,-83,-16}, +{59,113,22,-33,-66,100,-83,-16},{60,113,22,-33,-66,100,-84,-16},{60,114,23,-34,-66,101,-84,-16},{60,115,23,-34,-67,101,-84,-16}, +{60,115,23,-34,-67,102,-85,-16},{61,116,23,-34,-67,102,-85,-16},{61,116,23,-34,-68,103,-86,-16},{61,117,23,-34,-68,103,-86,-16}, +{62,117,23,-35,-68,104,-87,-16},{62,118,23,-35,-69,104,-87,-16},{62,119,23,-35,-69,105,-87,-17},{63,119,24,-35,-69,105,-88,-17}, +{63,120,24,-35,-70,106,-88,-17},{63,120,24,-35,-70,106,-89,-17},{63,121,24,-36,-70,107,-89,-17},{64,121,24,-36,-71,107,-90,-17}, +{64,122,24,-36,-71,108,-90,-17},{64,123,24,-36,-71,108,-90,-17},{65,123,24,-36,-72,109,-91,-17},{65,124,24,-36,-72,109,-91,-17}, +{65,124,25,-37,-72,110,-92,-17},{66,125,25,-37,-73,110,-92,-17},{66,125,25,-37,-73,111,-92,-18},{66,126,25,-37,-73,111,-93,-18}, +{66,127,25,-37,-74,112,-93,-18},{67,127,25,-37,-74,112,-94,-18},{67,128,25,-38,-74,113,-94,-18},{67,128,25,-38,-75,113,-95,-18}, +{68,129,25,-38,-75,114,-95,-18},{68,129,26,-38,-75,114,-95,-18},{68,130,26,-38,-76,115,-96,-18},{69,130,26,-38,-76,115,-96,-18}, +{69,131,26,-39,-76,116,-97,-18},{69,132,26,-39,-77,116,-97,-18},{69,132,26,-39,-77,117,-97,-19},{70,133,26,-39,-77,117,-98,-19}, +{70,133,26,-39,-78,118,-98,-19},{70,134,27,-39,-78,118,-99,-19},{71,134,27,-40,-78,119,-99,-19},{71,135,27,-40,-79,119,-100,-19}, +{71,136,27,-40,-79,120,-100,-19},{72,136,27,-40,-79,120,-100,-19},{72,137,27,-40,-80,121,-101,-19},{72,137,27,-40,-80,121,-101,-19}, +{72,138,27,-41,-80,122,-102,-19},{73,138,27,-41,-81,122,-102,-19},{73,139,28,-41,-81,123,-103,-19},{73,140,28,-41,-81,123,-103,-20}, +{74,140,28,-41,-82,124,-103,-20},{74,141,28,-42,-82,124,-104,-20},{74,141,28,-42,-82,125,-104,-20},{75,142,28,-42,-83,125,-105,-20}, +{75,142,28,-42,-83,126,-105,-20},{75,143,28,-42,-83,126,-105,-20},{75,144,28,-42,-84,127,-106,-20},{76,144,29,-43,-84,127,-106,-20}}; +/* }}} */ + +/* {{{ [fold] qc_yuv_toplanar(unsigned char *rgb24frame, int length, int format) */ +/* + * Convert to planar formats + * The input is an YCbYCr format. + * Input: len : 2/3 maxi. + * | YUYV | free | + * | 2/3 | 1/3 | + * 1th conversion: + * | YY | free | U|V | + * | 1/3 | 1/3 | 1/3 | + * 2d conversion: + * | YY | U | V | free | + * | 1/3 | 1/6|1/6 | 1/3 | + * That the Y422P conversion. + */ +static int qc_yuv_toplanar(unsigned char *rgb24frame, int length, int format) +{ + unsigned char *ptr; + int n = 0, l = 0, i; + unsigned char *cr; + unsigned char *cb; + unsigned char *crptr, *cbptr; + int mode = 0; + + l = length/2; + switch(format) { + case VIDEO_PALETTE_YUV411P: + n = length/8; + mode = 1; + break; + case VIDEO_PALETTE_YUV422P: + n = length/4; + break; + } + + ptr = rgb24frame; + crptr = &rgb24frame[length]; + cr = crptr; + cbptr = &rgb24frame[length+n]; + cb = cbptr; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_yuv_toplanar: %d (%d + 2 * %d)",length, l, n); + + /* separate Y , U and V */ + for (i=0; iscanlength = length/2+ (2 * n); + return length; +} +/* }}} */ +/* {{{ [fold] qc_yuv_rgb2yuv(unsigned char *rgb24frame, int length, int format) */ +/* + * Convert the RGB24 image to YUV422. + * return the size of the converted frame + */ +int qc_yuv_rgb2yuv(unsigned char *rgb24frame, int length, int format) +{ + int i; + int l; /* Data length */ + short Y; + short U; + short V; + unsigned char *ptr; + unsigned short w; + + //if (qcdebug&QC_DEBUGLOGIC)PDEBUG("qc_yuv_rgb2yuv(frame=%p,length=%i,palette=%s)",rgb24frame,length,qc_fmt_getname(format)); + ptr = rgb24frame; + l = 0; + + if (format==VIDEO_PALETTE_RGB32) { + /* we need to convert in reverse so as to not overwrite ourselves */ + for (ptr=ptr+length*4/3,i=length-3; i>=0; i-=3) { + *--ptr = 0; + *--ptr = (unsigned char) rgb24frame[i + 2]; + *--ptr = (unsigned char) rgb24frame[i + 1]; + *--ptr = (unsigned char) rgb24frame[i + 0]; + l += 4; + } + } else + for (i=0; i> 3))); + *ptr++ = (unsigned char) (w & 0xFF); + *ptr++ = (unsigned char) (w >> 8); + l += 2; + break; + case VIDEO_PALETTE_RGB555: + w = ((unsigned short) + ((unsigned short) (rgb24frame[i + 2] & 0xf8) << (10 - 3)) | + ((unsigned short) (rgb24frame[i + 1] & 0xf8) << (5 - 3)) | + ((unsigned short) (rgb24frame[i + 0] >> 3))); + *ptr++ = (unsigned char) (w & 0xFF); + *ptr++ = (unsigned char) (w >> 8); + l += 2; + break; + default: + *ptr++ = (219 * Y)/255 + 16; + l++; + *ptr = (112 * U)/127 + 128; /* Cb */ + ptr++; + l++; + *ptr = (112 * V)/127 + 128; /* Cr */ + ptr++; + l++; + } + } + if (format >= VIDEO_PALETTE_PLANAR) { + length = qc_yuv_toplanar(rgb24frame, l, format); + } else { + length = l; + } + return length; +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_imag: Start of image processing functions ************************** */ + +/* {{{ [fold] qc_imag_bayer_midvalue(char *bay, int bay_line, int columns, int rows) */ +/* Compute and return the average pixel intensity from the bayer data. + * The result can be used for automatic software exposure/gain control. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + */ +static unsigned char qc_imag_bayer_midvalue(unsigned char *bay, int bay_line, + unsigned int columns, unsigned int rows) +{ + static const unsigned int stepsize = 8; /* Larger = faster and less accurate */ + unsigned char *cur_bay; + unsigned int sum = 0; + int column_cnt; + int row_cnt; + + /* Skip 1/4 of left, right, top, and bottom pixels (use only center pixels) */ + columns /= 2; + rows /= 2; + bay += rows/4*2*bay_line + columns/4*2; + + columns /= stepsize*2; + rows /= stepsize*2; + + row_cnt = rows; + do { + column_cnt = columns; + cur_bay = bay; + do { + sum += cur_bay[0] + cur_bay[1] + cur_bay[bay_line]; /* R + G + B */ + cur_bay += 2*stepsize; + } while (--column_cnt > 0); + bay += 2*stepsize*bay_line; + } while (--row_cnt > 0); + sum /= 3 * columns * rows; + return sum; +} +/* }}} */ +#if COMPRESS +/* {{{ [fold] qc_imag_rgb24_midvalue(char *rgb, int rgb_line, int columns, int rows) */ +/* Compute and return the average pixel intensity from the RGB/BGR24 data. + * The result can be used for automatic software exposure/gain control. + * rgb = points to the RGB image data + * rgb_line = bytes between the beginnings of two consecutive rows + * columns, rows = RGB image size + */ +static unsigned char qc_imag_rgb24_midvalue(unsigned char *rgb, int rgb_line, + unsigned int columns, unsigned int rows) +{ + static const unsigned int stepsize = 8; /* Larger = faster and less accurate */ + unsigned char *cur_rgb; + unsigned int sum = 0; + int column_cnt; + int row_cnt; + + /* Skip 1/4 of left, right, top, and bottom pixels (use only center pixels) */ + columns /= 2; + rows /= 2; + rgb += rows/2*rgb_line + columns/2*3; + + columns /= stepsize; + rows /= stepsize; + + row_cnt = rows; + do { + column_cnt = columns; + cur_rgb = rgb; + do { + sum += cur_rgb[0] + cur_rgb[1] + cur_rgb[2]; /* R + G + B */ + cur_rgb += 3*stepsize; + } while (--column_cnt > 0); + rgb += stepsize*rgb_line; + } while (--row_cnt > 0); + sum /= 3 * columns * rows; + return sum; +} +/* }}} */ +#endif +/* {{{ [fold] qc_imag_userlut(unsigned char (*userlut)[QC_LUT_SIZE], unsigned char (*lut)[QC_LUT_SIZE]) */ +/* Apply user-defined lookup-table to the given preinitialized lut */ +static inline void qc_imag_userlut(unsigned char (*userlut)[QC_LUT_SIZE], unsigned char (*lut)[QC_LUT_SIZE]) +{ + unsigned int i,p; + for (i=0; i<256; i++) { + p = (*lut)[QC_LUT_RED + i]; + p = (*userlut)[QC_LUT_RED + p]; + (*lut)[QC_LUT_RED + i] = p; + } + for (i=0; i<256; i++) { + p = (*lut)[QC_LUT_GREEN + i]; + p = (*userlut)[QC_LUT_GREEN + p]; + (*lut)[QC_LUT_GREEN + i] = p; + } + for (i=0; i<256; i++) { + p = (*lut)[QC_LUT_BLUE + i]; + p = (*userlut)[QC_LUT_BLUE + p]; + (*lut)[QC_LUT_BLUE + i] = p; + } +} +/* }}} */ +/* {{{ [fold] qc_imag_bayer_equalize(char *bay, int bay_line, int columns, int rows, char (*lut)[]) */ +/* Compute and fill a lookup table which will equalize the image. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * lut = lookup table to be filled, 3*256 char array + */ +static void qc_imag_bayer_equalize(unsigned char *bay, int bay_line, + unsigned int columns, unsigned int rows, unsigned char (*lut)[QC_LUT_SIZE]) +{ + static const unsigned int stepsize = 4; /* Larger = faster and less accurate */ + unsigned short red_cnt[256], green_cnt[256], blue_cnt[256]; /* FIXME: how much we can use stack? */ + unsigned int red_sum, green_sum, blue_sum; + unsigned int red_tot, green_tot, blue_tot; + unsigned char *cur_bay; + int i, column_cnt, row_cnt; + + memset(red_cnt, 0, sizeof(red_cnt)); + memset(green_cnt, 0, sizeof(green_cnt)); + memset(blue_cnt, 0, sizeof(blue_cnt)); + + columns /= 2*stepsize; + rows /= 2*stepsize; + + /* Compute histogram */ + row_cnt = rows; + do { + column_cnt = columns; + cur_bay = bay; + do { + green_cnt[cur_bay[0]]++; + red_cnt [cur_bay[1]]++; + blue_cnt [cur_bay[bay_line]]++; + green_cnt[cur_bay[bay_line+1]]++; + cur_bay += 2*stepsize; + } while (--column_cnt > 0); + bay += 2*stepsize*bay_line; + } while (--row_cnt > 0); + + /* Compute lookup table based on the histogram */ + red_tot = columns * rows; /* Total number of pixels of each primary color */ + green_tot = red_tot * 2; + blue_tot = red_tot; + red_sum = 0; + green_sum = 0; + blue_sum = 0; + for (i=0; i<256; i++) { + (*lut)[QC_LUT_RED + i] = 255 * red_sum / red_tot; + (*lut)[QC_LUT_GREEN + i] = 255 * green_sum / green_tot; + (*lut)[QC_LUT_BLUE + i] = 255 * blue_sum / blue_tot; + red_sum += red_cnt[i]; + green_sum += green_cnt[i]; + blue_sum += blue_cnt[i]; + } +} +/* }}} */ +/* {{{ [fold] qc_imag_bayer_lut(char *bay, int bay_line, int columns, int rows, char (*lut)[]) */ +/* Transform pixel values in a bayer image with a given lookup table. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * lut = lookup table to be used, 3*256 char array + */ +static void qc_imag_bayer_lut(unsigned char *bay, int bay_line, + unsigned int columns, unsigned int rows, unsigned char (*lut)[QC_LUT_SIZE]) +{ + unsigned char *cur_bay; + unsigned int total_columns; + + total_columns = columns / 2; /* Number of 2x2 bayer blocks */ + rows /= 2; + do { + columns = total_columns; + cur_bay = bay; + do { + cur_bay[0] = (*lut)[QC_LUT_GREEN + cur_bay[0]]; + cur_bay[1] = (*lut)[QC_LUT_RED + cur_bay[1]]; + cur_bay += 2; + } while (--columns); + bay += bay_line; + columns = total_columns; + cur_bay = bay; + do { + cur_bay[0] = (*lut)[QC_LUT_BLUE + cur_bay[0]]; + cur_bay[1] = (*lut)[QC_LUT_GREEN + cur_bay[1]]; + cur_bay += 2; + } while (--columns); + bay += bay_line; + } while (--rows); +} +/* }}} */ +/* {{{ [fold] qc_imag_writergb(void *addr, int bpp, unsigned char r, unsigned char g, unsigned char b) */ +/* Write RGB pixel value to the given address. + * addr = memory address, to which the pixel is written + * bpp = number of bytes in the pixel (should be 3 or 4) + * r, g, b = pixel component values to be written (red, green, blue) + * Looks horribly slow but the compiler should be able to inline optimize it. + */ +static inline void qc_imag_writergb(void *addr, int bpp, + unsigned char r, unsigned char g, unsigned char b) +{ + if (DEFAULT_BGR) { + /* Blue is first (in the lowest memory address */ + if (bpp==4) { +#if defined(__LITTLE_ENDIAN) + *(unsigned int *)addr = + (unsigned int)r << 16 | + (unsigned int)g << 8 | + (unsigned int)b; +#elif defined(__BIG_ENDIAN) + *(unsigned int *)addr = + (unsigned int)r << 8 | + (unsigned int)g << 16 | + (unsigned int)b << 24; +#else + unsigned char *addr2 = (unsigned char *)addr; + addr2[0] = b; + addr2[1] = g; + addr2[2] = r; + addr2[3] = 0; +#endif + } else { + unsigned char *addr2 = (unsigned char *)addr; + addr2[0] = b; + addr2[1] = g; + addr2[2] = r; + } + } else { + /* Red is first (in the lowest memory address */ + if (bpp==4) { +#if defined(__LITTLE_ENDIAN) + *(unsigned int *)addr = + (unsigned int)b << 16 | + (unsigned int)g << 8 | + (unsigned int)r; +#elif defined(__BIG_ENDIAN) + *(unsigned int *)addr = + (unsigned int)b << 8 | + (unsigned int)g << 16 | + (unsigned int)r << 24; +#else + unsigned char *addr2 = (unsigned char *)addr; + addr2[0] = r; + addr2[1] = g; + addr2[2] = b; + addr2[3] = 0; +#endif + } else { + unsigned char *addr2 = (unsigned char *)addr; + addr2[0] = r; + addr2[1] = g; + addr2[2] = b; + } + } +} +/* }}} */ + +/* + * Raw image data for Bayer-RGB-matrix: + * G R for even rows + * B G for odd rows + */ + +#if 0 +/* {{{ [fold] qc_imag_bay2rgb_noip(char *bay, int bay_line, char *rgb, int rgb_line, int columns, rows, bpp) */ +/* Convert bayer image to RGB image without using interpolation. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * rgb = points to the rgb image data that is written + * rgb_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * bpp = number of bytes in each pixel in the RGB image (should be 3 or 4) + */ +/* Execution time: 2391747-2653574 clock cycles for CIF image (Pentium II) */ +/* Do NOT use this routine: cottnoip is faster with better image quality */ +static inline void qc_imag_bay2rgb_noip(unsigned char *bay, int bay_line, + unsigned char *rgb, int rgb_line, + int columns, int rows, int bpp) +{ + unsigned char *cur_bay, *cur_rgb; + int bay_line2, rgb_line2; + int total_columns; + + /* Process 2 lines and rows per each iteration */ + total_columns = columns >> 1; + rows >>= 1; + bay_line2 = 2*bay_line; + rgb_line2 = 2*rgb_line; + do { + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + bay += bay_line2; + rgb += rgb_line2; + } while (--rows); +} +/* }}} */ +#endif +/* {{{ [fold] qc_imag_bay2rgb_horip(char *bay, int bay_line, char *rgb, int rgb_line, columns, rows, bpp) */ +/* Convert bayer image to RGB image using fast horizontal-only interpolation. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * rgb = points to the rgb image data that is written + * rgb_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * bpp = number of bytes in each pixel in the RGB image (should be 3 or 4) + */ +/* Execution time: 2735776-3095322 clock cycles for CIF image (Pentium II) */ +/* Not recommended: ip seems to be somewhat faster, probably with better image quality. + * cott is quite much faster, but possibly with slightly worse image quality */ +static inline void qc_imag_bay2rgb_horip(unsigned char *bay, int bay_line, + unsigned char *rgb, int rgb_line, + unsigned int columns, unsigned int rows, int bpp) +{ + unsigned char *cur_bay, *cur_rgb; + int bay_line2, rgb_line2; + int total_columns; + unsigned char red, green, blue; + unsigned int column_cnt, row_cnt; + + /* Process 2 lines and rows per each iteration */ + total_columns = (columns-2) / 2; + row_cnt = rows / 2; + bay_line2 = 2*bay_line; + rgb_line2 = 2*rgb_line; + + do { + qc_imag_writergb(rgb+0, bpp, bay[1], bay[0], bay[bay_line]); + qc_imag_writergb(rgb+rgb_line, bpp, bay[1], bay[0], bay[bay_line]); + cur_bay = bay + 1; + cur_rgb = rgb + bpp; + column_cnt = total_columns; + do { + green = ((unsigned int)cur_bay[-1]+cur_bay[1]) / 2; + blue = ((unsigned int)cur_bay[bay_line-1]+cur_bay[bay_line+1]) / 2; + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[0], green, blue); + red = ((unsigned int)cur_bay[0]+cur_bay[2]) / 2; + qc_imag_writergb(cur_rgb+bpp, bpp, red, cur_bay[1], cur_bay[bay_line+1]); + green = ((unsigned int)cur_bay[bay_line]+cur_bay[bay_line+2]) / 2; + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[0], cur_bay[bay_line], blue); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, red, cur_bay[1], cur_bay[bay_line+1]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--column_cnt); + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[0], cur_bay[-1], cur_bay[bay_line-1]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[0], cur_bay[bay_line], cur_bay[bay_line-1]); + bay += bay_line2; + rgb += rgb_line2; + } while (--row_cnt); +} +/* }}} */ +/* {{{ [fold] qc_imag_bay2rgb_ip(char *bay, int bay_line, char *rgb, int rgb_line, columns, rows, bpp) */ +/* Convert bayer image to RGB image using full (slow) linear interpolation. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * rgb = points to the rgb image data that is written + * rgb_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * bpp = number of bytes in each pixel in the RGB image (should be 3 or 4) + */ +/* Execution time: 2714077-2827455 clock cycles for CIF image (Pentium II) */ +static inline void qc_imag_bay2rgb_ip(unsigned char *bay, int bay_line, + unsigned char *rgb, int rgb_line, + unsigned int columns, unsigned int rows, int bpp) +{ + unsigned char *cur_bay, *cur_rgb; + int bay_line2, rgb_line2; + int total_columns; + unsigned char red, green, blue; + unsigned int column_cnt, row_cnt; + + /* Process 2 rows and columns each iteration */ + total_columns = (columns-2) / 2; + row_cnt = (rows-2) / 2; + bay_line2 = 2*bay_line; + rgb_line2 = 2*rgb_line; + + /* First scanline is handled here as a special case */ + qc_imag_writergb(rgb, bpp, bay[1], bay[0], bay[bay_line]); + cur_bay = bay + 1; + cur_rgb = rgb + bpp; + column_cnt = total_columns; + do { + green = ((unsigned int)cur_bay[-1] + cur_bay[1] + cur_bay[bay_line]) / 3; + blue = ((unsigned int)cur_bay[bay_line-1] + cur_bay[bay_line+1]) / 2; + qc_imag_writergb(cur_rgb, bpp, cur_bay[0], green, blue); + red = ((unsigned int)cur_bay[0] + cur_bay[2]) / 2; + qc_imag_writergb(cur_rgb+bpp, bpp, red, cur_bay[1], cur_bay[bay_line+1]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--column_cnt); + green = ((unsigned int)cur_bay[-1] + cur_bay[bay_line]) / 2; + qc_imag_writergb(cur_rgb, bpp, cur_bay[0], green, cur_bay[bay_line-1]); + + /* Process here all other scanlines except first and last */ + bay += bay_line; + rgb += rgb_line; + do { + red = ((unsigned int)bay[-bay_line+1] + bay[bay_line+1]) / 2; + green = ((unsigned int)bay[-bay_line] + bay[1] + bay[bay_line]) / 3; + qc_imag_writergb(rgb+0, bpp, red, green, bay[0]); + blue = ((unsigned int)bay[0] + bay[bay_line2]) / 2; + qc_imag_writergb(rgb+rgb_line, bpp, bay[bay_line+1], bay[bay_line], blue); + cur_bay = bay + 1; + cur_rgb = rgb + bpp; + column_cnt = total_columns; + do { + red = ((unsigned int)cur_bay[-bay_line]+cur_bay[bay_line]) / 2; + blue = ((unsigned int)cur_bay[-1]+cur_bay[1]) / 2; + qc_imag_writergb(cur_rgb+0, bpp, red, cur_bay[0], blue); + red = ((unsigned int)cur_bay[-bay_line]+cur_bay[-bay_line+2]+cur_bay[bay_line]+cur_bay[bay_line+2]) / 4; + green = ((unsigned int)cur_bay[0]+cur_bay[2]+cur_bay[-bay_line+1]+cur_bay[bay_line+1]) / 4; + qc_imag_writergb(cur_rgb+bpp, bpp, red, green, cur_bay[1]); + green = ((unsigned int)cur_bay[0]+cur_bay[bay_line2]+cur_bay[bay_line-1]+cur_bay[bay_line+1]) / 4; + blue = ((unsigned int)cur_bay[-1]+cur_bay[1]+cur_bay[bay_line2-1]+cur_bay[bay_line2+1]) / 4; + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[bay_line], green, blue); + red = ((unsigned int)cur_bay[bay_line]+cur_bay[bay_line+2]) / 2; + blue = ((unsigned int)cur_bay[1]+cur_bay[bay_line2+1]) / 2; + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, red, cur_bay[bay_line+1], blue); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--column_cnt); + red = ((unsigned int)cur_bay[-bay_line] + cur_bay[bay_line]) / 2; + qc_imag_writergb(cur_rgb, bpp, red, cur_bay[0], cur_bay[-1]); + green = ((unsigned int)cur_bay[0] + cur_bay[bay_line-1] + cur_bay[bay_line2]) / 3; + blue = ((unsigned int)cur_bay[-1] + cur_bay[bay_line2-1]) / 2; + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[bay_line], green, blue); + bay += bay_line2; + rgb += rgb_line2; + } while (--row_cnt); + + /* Last scanline is handled here as a special case */ + green = ((unsigned int)bay[-bay_line] + bay[1]) / 2; + qc_imag_writergb(rgb, bpp, bay[-bay_line+1], green, bay[0]); + cur_bay = bay + 1; + cur_rgb = rgb + bpp; + column_cnt = total_columns; + do { + blue = ((unsigned int)cur_bay[-1] + cur_bay[1]) / 2; + qc_imag_writergb(cur_rgb, bpp, cur_bay[-bay_line], cur_bay[0], blue); + red = ((unsigned int)cur_bay[-bay_line] + cur_bay[-bay_line+2]) / 2; + green = ((unsigned int)cur_bay[0] + cur_bay[-bay_line+1] + cur_bay[2]) / 3; + qc_imag_writergb(cur_rgb+bpp, bpp, red, green, cur_bay[1]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--column_cnt); + qc_imag_writergb(cur_rgb, bpp, cur_bay[-bay_line], cur_bay[0], cur_bay[-1]); +} +/* }}} */ +/* {{{ [fold] qc_imag_bay2rgb_cott(unsigned char *bay, int bay_line, unsigned char *rgb, int rgb_line, int columns, int rows, int bpp) */ +/* Convert bayer image to RGB image using 0.5 displaced light linear interpolation. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * rgb = points to the rgb image data that is written + * rgb_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * bpp = number of bytes in each pixel in the RGB image (should be 3 or 4) + */ +/* Execution time: 2167685 clock cycles for CIF image (Pentium II) */ +/* Original idea for this routine from Cagdas Ogut */ +static inline void qc_imag_bay2rgb_cott(unsigned char *bay, int bay_line, + unsigned char *rgb, int rgb_line, + int columns, int rows, int bpp) +{ + unsigned char *cur_bay, *cur_rgb; + int bay_line2, rgb_line2; + int total_columns; + + /* Process 2 lines and rows per each iteration, but process the last row and column separately */ + total_columns = (columns>>1) - 1; + rows = (rows>>1) - 1; + bay_line2 = 2*bay_line; + rgb_line2 = 2*rgb_line; + do { + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], ((unsigned int)cur_bay[0] + cur_bay[bay_line+1]) /2, cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], ((unsigned int)cur_bay[2] + cur_bay[bay_line+1]) /2, cur_bay[bay_line+2]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[bay_line2+1], ((unsigned int)cur_bay[bay_line2] + cur_bay[bay_line+1]) /2, cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[bay_line2+1], ((unsigned int)cur_bay[bay_line2+2] + cur_bay[bay_line+1])/2, cur_bay[bay_line+2]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], ((unsigned int)cur_bay[0] + cur_bay[bay_line+1])/2, cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[bay_line2+1], ((unsigned int)cur_bay[bay_line2] + cur_bay[bay_line+1])/2, cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[bay_line2+1], cur_bay[bay_line+1], cur_bay[bay_line]); + bay += bay_line2; + rgb += rgb_line2; + } while (--rows); + /* Last scanline handled here as special case */ + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], ((unsigned int)cur_bay[0] + cur_bay[bay_line+1])/2, cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], ((unsigned int)cur_bay[2] + cur_bay[bay_line+1])/2, cur_bay[bay_line+2]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line+2]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + /* Last lower-right pixel is handled here as special case */ + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], ((unsigned int)cur_bay[0] + cur_bay[bay_line+1])/2, cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); +} +/* }}} */ +/* {{{ [fold] qc_imag_bay2rgb_cottnoip(unsigned char *bay, int bay_line, unsigned char *rgb, int rgb_line, int columns, int rows, int bpp) */ +/* Convert bayer image to RGB image using 0.5 displaced nearest neighbor. + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * rgb = points to the rgb image data that is written + * rgb_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * bpp = number of bytes in each pixel in the RGB image (should be 3 or 4) + */ +/* Execution time: 2133302 clock cycles for CIF image (Pentium II), fastest */ +static inline void qc_imag_bay2rgb_cottnoip(unsigned char *bay, int bay_line, + unsigned char *rgb, int rgb_line, + int columns, int rows, int bpp) +{ + unsigned char *cur_bay, *cur_rgb; + int bay_line2, rgb_line2; + int total_columns; + + /* Process 2 lines and rows per each iteration, but process the last row and column separately */ + total_columns = (columns>>1) - 1; + rows = (rows>>1) - 1; + bay_line2 = 2*bay_line; + rgb_line2 = 2*rgb_line; + do { + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[2], cur_bay[bay_line+2]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[bay_line2+1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[bay_line2+1], cur_bay[bay_line+1], cur_bay[bay_line+2]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[bay_line2+1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[bay_line2+1], cur_bay[bay_line+1], cur_bay[bay_line]); + bay += bay_line2; + rgb += rgb_line2; + } while (--rows); + /* Last scanline handled here as special case */ + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[2], cur_bay[bay_line+2]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line+2]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + /* Last lower-right pixel is handled here as special case */ + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); +} +/* }}} */ +/* {{{ [fold] qc_imag_bay2rgb_gptm_fast(unsigned char *bay, int bay_line, unsigned char *rgb, int rgb_line, int columns, int rows, int bpp) */ +/* Convert Bayer image to RGB image using Generalized Pei-Tam method + * Uses fixed weights */ +/* Execution time: 3795517 clock cycles */ +static inline void qc_imag_bay2rgb_gptm_fast(unsigned char *bay, int bay_line, + unsigned char *rgb, int rgb_line, + int columns, int rows, int bpp) +{ + int r,g,b,w; + unsigned char *cur_bay, *cur_rgb; + int bay_line2, bay_line3, rgb_line2; + int total_columns; + + /* Process 2 lines and rows per each iteration, but process the first and last two columns and rows separately */ + total_columns = (columns>>1) - 2; + rows = (rows>>1) - 2; + bay_line2 = 2*bay_line; + bay_line3 = 3*bay_line; + rgb_line2 = 2*rgb_line; + + /* Process first two pixel rows here */ + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns + 2; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + bay += bay_line2; + rgb += rgb_line2; + + do { + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns; + + /* Process first 2x2 pixel block in a row here */ + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + cur_bay += 2; + cur_rgb += 2*bpp; + + do { + w = 4*cur_bay[0] - (cur_bay[-bay_line-1] + cur_bay[-bay_line+1] + cur_bay[bay_line-1] + cur_bay[bay_line+1]); + r = (2*(cur_bay[-1] + cur_bay[1]) + w) >> 2; + b = (2*(cur_bay[-bay_line] + cur_bay[bay_line]) + w) >> 2; + qc_imag_writergb(cur_rgb+0, bpp, CLIP(r,0,255), cur_bay[0], CLIP(b,0,255)); + + w = 4*cur_bay[1] - (cur_bay[-bay_line2+1] + cur_bay[-1] + cur_bay[3] + cur_bay[bay_line2+1]); + g = (2*(cur_bay[-bay_line+1] + cur_bay[0] + cur_bay[2] + cur_bay[bay_line+1]) + w) >> 3; + b = (2*(cur_bay[-bay_line] + cur_bay[-bay_line+2] + cur_bay[bay_line] + cur_bay[bay_line+2]) + w) >> 3; + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], CLIP(g,0,255), CLIP(b,0,255)); + + w = 4*cur_bay[bay_line] - (cur_bay[-bay_line] + cur_bay[bay_line-2] + cur_bay[bay_line+2] + cur_bay[bay_line3]); + r = ((cur_bay[-1] + cur_bay[1] + cur_bay[bay_line2-1] + cur_bay[bay_line2+1]) + w) >> 2; + g = ((cur_bay[0] + cur_bay[bay_line-1] + cur_bay[bay_line+1] + cur_bay[bay_line2]) + w) >> 2; + qc_imag_writergb(cur_rgb+rgb_line, bpp, CLIP(r,0,255), CLIP(g,0,255), cur_bay[bay_line]); + + w = 4*cur_bay[bay_line+1] - (cur_bay[0] + cur_bay[2] + cur_bay[bay_line2] + cur_bay[bay_line2+2]); + r = (2*(cur_bay[1] + cur_bay[bay_line2+1]) + w) >> 2; + b = (2*(cur_bay[bay_line] + cur_bay[bay_line+2]) + w) >> 2; + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, CLIP(r,0,255), cur_bay[bay_line+1], CLIP(b,0,255)); + + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + + /* Process last 2x2 pixel block in a row here */ + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + + bay += bay_line2; + rgb += rgb_line2; + } while (--rows); + + /* Process last two pixel rows here */ + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns + 2; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); +} +/* }}} */ +/* {{{ [fold] qc_imag_bay2rgb_gptm(unsigned char *bay, int bay_line, unsigned char *rgb, int rgb_line, int columns, int rows, int bpp, int sharpness) */ +/* Convert Bayer image to RGB image using Generalized Pei-Tam method (See: + * "Effective Color Interpolation in CCD Color Filter Arrays Using Signal Correlation" + * IEEE Transactions on Circuits and Systems for Video Technology, vol. 13, no. 6, June 2003. + * Note that this is much improved version of the algorithm described in the paper) + * bay = points to the bayer image data (upper left pixel is green) + * bay_line = bytes between the beginnings of two consecutive rows + * rgb = points to the rgb image data that is written + * rgb_line = bytes between the beginnings of two consecutive rows + * columns, rows = bayer image size (both must be even) + * bpp = number of bytes in each pixel in the RGB image (should be 3 or 4) + * sharpness = how sharp the image should be, between 0..65535 inclusive. + * 23170 gives in theory image that corresponds to the original + * best, but human eye likes slightly sharper picture... 32768 is a good bet. + * When sharpness = 0, this routine is same as bilinear interpolation. + */ +/* Execution time: 4344042 clock cycles for CIF image (Pentium II) */ +static inline void qc_imag_bay2rgb_gptm(unsigned char *bay, int bay_line, + unsigned char *rgb, int rgb_line, + int columns, int rows, int bpp, unsigned int sharpness) +{ + + /* 0.8 fixed point weights, should be between 0-256. Larger value = sharper, zero corresponds to bilinear interpolation. */ + /* Best PSNR with sharpness = 23170 */ + static const int wrg0 = 144; /* Weight for Red on Green */ + static const int wbg0 = 160; + static const int wgr0 = 120; + static const int wbr0 = 192; + static const int wgb0 = 120; + static const int wrb0 = 168; + + int wrg; + int wbg; + int wgr; + int wbr; + int wgb; + int wrb; + + unsigned int wu; + int r,g,b,w; + unsigned char *cur_bay, *cur_rgb; + int bay_line2, bay_line3, rgb_line2; + int total_columns; + + /* Compute weights */ + wu = (sharpness * sharpness) >> 16; + wu = (wu * wu) >> 16; + wrg = (wrg0 * wu) >> 10; + wbg = (wbg0 * wu) >> 10; + wgr = (wgr0 * wu) >> 10; + wbr = (wbr0 * wu) >> 10; + wgb = (wgb0 * wu) >> 10; + wrb = (wrb0 * wu) >> 10; + + /* Process 2 lines and rows per each iteration, but process the first and last two columns and rows separately */ + total_columns = (columns>>1) - 2; + rows = (rows>>1) - 2; + bay_line2 = 2*bay_line; + bay_line3 = 3*bay_line; + rgb_line2 = 2*rgb_line; + + /* Process first two pixel rows here */ + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns + 2; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + bay += bay_line2; + rgb += rgb_line2; + + do { + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns; + + /* Process first 2x2 pixel block in a row here */ + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + cur_bay += 2; + cur_rgb += 2*bpp; + + do { + w = 4*cur_bay[0] - (cur_bay[-bay_line-1] + cur_bay[-bay_line+1] + cur_bay[bay_line-1] + cur_bay[bay_line+1]); + r = (512*(cur_bay[-1] + cur_bay[1]) + w*wrg) >> 10; + b = (512*(cur_bay[-bay_line] + cur_bay[bay_line]) + w*wbg) >> 10; + qc_imag_writergb(cur_rgb+0, bpp, CLIP(r,0,255), cur_bay[0], CLIP(b,0,255)); + + w = 4*cur_bay[1] - (cur_bay[-bay_line2+1] + cur_bay[-1] + cur_bay[3] + cur_bay[bay_line2+1]); + g = (256*(cur_bay[-bay_line+1] + cur_bay[0] + cur_bay[2] + cur_bay[bay_line+1]) + w*wgr) >> 10; + b = (256*(cur_bay[-bay_line] + cur_bay[-bay_line+2] + cur_bay[bay_line] + cur_bay[bay_line+2]) + w*wbr) >> 10; + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], CLIP(g,0,255), CLIP(b,0,255)); + + w = 4*cur_bay[bay_line] - (cur_bay[-bay_line] + cur_bay[bay_line-2] + cur_bay[bay_line+2] + cur_bay[bay_line3]); + r = (256*(cur_bay[-1] + cur_bay[1] + cur_bay[bay_line2-1] + cur_bay[bay_line2+1]) + w*wrb) >> 10; + g = (256*(cur_bay[0] + cur_bay[bay_line-1] + cur_bay[bay_line+1] + cur_bay[bay_line2]) + w*wgb) >> 10; + qc_imag_writergb(cur_rgb+rgb_line, bpp, CLIP(r,0,255), CLIP(g,0,255), cur_bay[bay_line]); + + w = 4*cur_bay[bay_line+1] - (cur_bay[0] + cur_bay[2] + cur_bay[bay_line2] + cur_bay[bay_line2+2]); + r = (512*(cur_bay[1] + cur_bay[bay_line2+1]) + w*wrg) >> 10; + b = (512*(cur_bay[bay_line] + cur_bay[bay_line+2]) + w*wbg) >> 10; + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, CLIP(r,0,255), cur_bay[bay_line+1], CLIP(b,0,255)); + + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); + + /* Process last 2x2 pixel block in a row here */ + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + + bay += bay_line2; + rgb += rgb_line2; + } while (--rows); + + /* Process last two pixel rows here */ + cur_bay = bay; + cur_rgb = rgb; + columns = total_columns + 2; + do { + qc_imag_writergb(cur_rgb+0, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+bpp, bpp, cur_bay[1], cur_bay[0], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + qc_imag_writergb(cur_rgb+rgb_line+bpp, bpp, cur_bay[1], cur_bay[bay_line+1], cur_bay[bay_line]); + cur_bay += 2; + cur_rgb += 2*bpp; + } while (--columns); +} +/* }}} */ +/* {{{ [fold] qc_imag_rgbbgr(unsigned char *dst, int pixels, int bpp) */ +/* Convert RGB image to BGR or vice versa with the given number of pixels and + * bytes per pixel + */ +static void inline qc_imag_rgbbgr(unsigned char *dst, int pixels, int bpp) +{ + unsigned char r,b; + do { + r = dst[0]; + b = dst[2]; + dst[0] = b; + dst[2] = r; + dst += bpp; + } while (--pixels); +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_fmt: Start of generic format query functions ********************** */ + +/* {{{ [fold] struct qc_fmt_format: a format definition */ +struct qc_fmt_format { + u32 fcc; /* M$ defined fourcc code, see http://www.fourcc.org */ + signed char bpp; /* 0=variable, -1=unknown (FIXME:what bpps do AVIs use here?) */ + char order; /* 'R' = RGB, 'B'=BGR, 0=not specified */ + unsigned char nr, ng, nb; /* Number of red, green, blue levels (0=256 levels) */ + char *name; /* Human-readable name */ + Bool supported; /* Can be converted to? */ + /* Here we could add a pointer to list containing conversion routines to other fourcc's */ + /* Then write code to create minimum spanning tree of format conversions */ + /* Include estimated cost per pixel to apply a conversion routine to weight edges */ +}; +/* }}} */ +/* {{{ [fold] List of supported formats */ +#define BF_RGB(r,g,b) 'R', (b)&0xFF, (g)&0xFF, (r)&0xFF +#define BF_BGR(r,g,b) 'B', (b)&0xFF, (g)&0xFF, (r)&0xFF +#define NO_BF 0, 0, 0, 0 +#define FORMAT(ID,FCC1,FCC2,FCC3,FCC4,BPP,BF,NAME,SUPP) \ +static const struct qc_fmt_format qc_fmt_formats_##ID = { v4l2_fourcc(FCC1,FCC2,FCC3,FCC4), BPP, BF, NAME, SUPP } +FORMAT(Y800, 'Y','8','0','0', 8, NO_BF, "GREY", TRUE); +FORMAT(RGB_HI, 'q','c','R','B', 8, BF_RGB(6, 6, 6), "HI240", FALSE); /* Not sure: BF_RGB or BF_BGR? Same as BT20? Don't think so */ +FORMAT(RGB_332, 3,0,0,0, 8, BF_RGB(8, 8, 4), "RGB332", FALSE); +/* Little endian RGB formats (least significant byte at lowest address) */ +FORMAT(RGB_555L, 3,0,0,0, 16, BF_RGB(32, 32, 32), "RGB555L",TRUE); /* Should this be 15 or 16 bpp? Is this same as RGB2? */ +FORMAT(RGB_565L, 3,0,0,0, 16, BF_RGB(32, 64, 32), "RGB565L",TRUE); /* Is this same as RGB2? */ +FORMAT(RGB_24L, 'R','G','B','2', 24, BF_RGB(256, 256, 256), "RGB24L", TRUE); +FORMAT(BGR_24L, 'R','G','B','2', 24, BF_BGR(256, 256, 256), "BGR24L", TRUE); +FORMAT(RGB_32L, 'R','G','B','2', 32, BF_RGB(256, 256, 256), "RGB32L", TRUE); +FORMAT(BGR_32L, 'R','G','B','2', 32, BF_BGR(256, 256, 256), "BGR32L", TRUE); +/* Big endian RGB formats (most significant byte at lowest address) */ +FORMAT(RGB_555B, 'q','c','R','B', 16, BF_RGB(32, 32, 32), "RGB555B",FALSE); +FORMAT(RGB_565B, 'q','c','R','B', 16, BF_RGB(32, 64, 32), "RGB565B",FALSE); +/* Component YUV formats */ +FORMAT(YUY2, 'Y','U','Y','2', 16, NO_BF, "YUV422", TRUE); /* 4:2:2 packed pixel YUYV */ +FORMAT(UYVY, 'U','Y','V','Y', 16, NO_BF, "UYVY", FALSE); +FORMAT(IYUV, 'I','Y','U','V', 12, NO_BF, "YUV420", FALSE); +/* Planar YUV formats */ +FORMAT(YV12, 'Y','V','1','2', 12, NO_BF, "YV12", FALSE); +FORMAT(YVU9, 'Y','V','U','9', 9, NO_BF, "YVU9", FALSE); +FORMAT(Y41P, 'Y','4','1','P', 12, NO_BF, "Y41P", FALSE); /* 4:1:1 packed pixel UYVY UYVY YYYY */ +FORMAT(qcY1, 'q','c','Y','1', 12, NO_BF, "YUV411P", FALSE); /* Like Y41P but planar and Y, U and V planes are in this order */ +FORMAT(qcY2, 'q','c','Y','2', 16, NO_BF, "YUV422P", TRUE); /* Like YUY2 but planar */ +FORMAT(qcV1, 'q','c','V','1', 12, NO_BF, "YVU411P", FALSE); /* Like qcY1 but V and U planes are in this order */ +FORMAT(qcV2, 'q','c','V','2', 16, NO_BF, "YVU422P", FALSE); /* Like qcY2 but V and U planes are in this order */ +FORMAT(qcU9, 'q','c','U','9', 9, NO_BF, "YUV410P", TRUE); /* Like YVU9 but U and V planes are in this order */ +FORMAT(qcYY, 'q','c','Y','Y', 12, NO_BF, "YYUV", FALSE); /* Packed 4:2:2 sampling, Y, Y, U, V */ +FORMAT(NV12, 'N','V','1','2', 12, NO_BF, "NV12", FALSE); +FORMAT(NV21, 'N','V','2','1', 12, NO_BF, "NV21", FALSE); +/* Special formats */ +FORMAT(qcBT, 'q','c','B','T', -1, NO_BF, "BT848 RAW", FALSE); /* RAW is raw scanline data sampled (before PAL decoding) */ +FORMAT(qcBR, 'q','c','B','R', 8, NO_BF, "BAYER", TRUE); /* Same as STVA? */ +FORMAT(qcMJ, 'q','c','M','J', 0, NO_BF, "MJPEG", TRUE); /* Same as MJPG? */ +FORMAT(qcWN, 'q','c','W','N', -1, NO_BF, "Winnov hw", FALSE); /* Same as WNV1 (or CHAM, WINX, YUV8)? */ +/* }}} */ +/* {{{ [fold] struct qc_fmt_alias: Alias fourcc codes for above formats */ +static struct qc_fmt_alias { + u32 fcc; + struct qc_fmt_format const *format; +} const qc_fmt_aliases[] = { + { v4l2_fourcc(0,0,0,0), &qc_fmt_formats_RGB_24L }, /* Could be any format with fourcc 'RGB2' */ + { v4l2_fourcc('Y','8',' ',' '), &qc_fmt_formats_Y800 }, + { v4l2_fourcc('Y','U','N','V'), &qc_fmt_formats_YUY2 }, + { v4l2_fourcc('V','4','2','2'), &qc_fmt_formats_YUY2 }, + { v4l2_fourcc('Y','4','2','2'), &qc_fmt_formats_UYVY }, + { v4l2_fourcc('U','Y','N','V'), &qc_fmt_formats_UYVY }, + { v4l2_fourcc('I','4','2','0'), &qc_fmt_formats_IYUV }, +}; +/* }}} */ +/* {{{ [fold] struct qc_fmt_palette: table to convert V4L code into fourcc, supported formats */ +static struct qc_fmt_palette { + int palette; /* V4L1 standard palette type */ + struct qc_fmt_format const *format; +} const qc_fmt_palettes[] = { + { VIDEO_PALETTE_GREY, &qc_fmt_formats_Y800 }, + { VIDEO_PALETTE_HI240, &qc_fmt_formats_RGB_HI }, + /* RGB formats */ + { VIDEO_PALETTE_RGB565, &qc_fmt_formats_RGB_565L }, + { VIDEO_PALETTE_RGB24, &qc_fmt_formats_BGR_24L }, + { VIDEO_PALETTE_RGB32, &qc_fmt_formats_BGR_32L }, + { VIDEO_PALETTE_RGB555, &qc_fmt_formats_RGB_555L }, + /* Component YUV formats */ + { VIDEO_PALETTE_YUV422, &qc_fmt_formats_YUY2 }, /* Assume this is YUY2, even though V4L1 docs say this is 8 bpp format */ + { VIDEO_PALETTE_YUYV, &qc_fmt_formats_YUY2 }, /* Benedict Bridgwater : Bt848 maps this to Y41P, but it is simply wrong--we follow V4L2 v4l_compat.c */ + { VIDEO_PALETTE_UYVY, &qc_fmt_formats_UYVY }, + { VIDEO_PALETTE_YUV420, &qc_fmt_formats_IYUV }, /* Assume this is planar, even though V4L1 header file indicates otherwise */ + { VIDEO_PALETTE_YUV411, &qc_fmt_formats_qcY1 }, /* Assume this is planar, even though V4L1 header file indicates otherwise (could be also fourcc 'Y41P') -from benedict */ + { VIDEO_PALETTE_RAW, &qc_fmt_formats_qcBT }, + /* Planar YUV formats */ + { VIDEO_PALETTE_YUV422P, &qc_fmt_formats_qcY2 }, + { VIDEO_PALETTE_YUV411P, &qc_fmt_formats_qcY1 }, + { VIDEO_PALETTE_YUV420P, &qc_fmt_formats_IYUV }, + { VIDEO_PALETTE_YUV410P, &qc_fmt_formats_qcU9 }, + /* Special formats */ + { VIDEO_PALETTE_BAYER, &qc_fmt_formats_qcBR }, + { VIDEO_PALETTE_MJPEG, &qc_fmt_formats_qcMJ }, +}; +/* }}} */ +/* {{{ [fold] struct qc_fmt_v4l2: V4L2 defines its own conflicting format codes */ +static struct qc_fmt_v4l2 { + u32 v4l2code; + struct qc_fmt_format const *format; +} const qc_fmt_v4l2s[] = { + { v4l2_fourcc('R','G','B','1'), &qc_fmt_formats_RGB_332 }, /* V4L2_PIX_FMT_RGB332 8 RGB-3-3-2 */ + { v4l2_fourcc('R','G','B','O'), &qc_fmt_formats_RGB_555L }, /* V4L2_PIX_FMT_RGB555 16 RGB-5-5-5 */ + { v4l2_fourcc('R','G','B','P'), &qc_fmt_formats_RGB_565L }, /* V4L2_PIX_FMT_RGB565 16 RGB-5-6-5 */ + { v4l2_fourcc('R','G','B','Q'), &qc_fmt_formats_RGB_555B }, /* V4L2_PIX_FMT_RGB555X 16 RGB-5-5-5 BE */ + { v4l2_fourcc('R','G','B','R'), &qc_fmt_formats_RGB_565B }, /* V4L2_PIX_FMT_RGB565X 16 RGB-5-6-5 BE */ + { v4l2_fourcc('B','G','R','3'), &qc_fmt_formats_BGR_24L }, /* V4L2_PIX_FMT_BGR24 24 BGR-8-8-8 */ + { v4l2_fourcc('R','G','B','3'), &qc_fmt_formats_RGB_24L }, /* V4L2_PIX_FMT_RGB24 24 RGB-8-8-8 */ + { v4l2_fourcc('B','G','R','4'), &qc_fmt_formats_BGR_32L }, /* V4L2_PIX_FMT_BGR32 32 BGR-8-8-8-8 */ + { v4l2_fourcc('R','G','B','4'), &qc_fmt_formats_RGB_32L }, /* V4L2_PIX_FMT_RGB32 32 RGB-8-8-8-8 */ + { v4l2_fourcc('G','R','E','Y'), &qc_fmt_formats_Y800 }, /* V4L2_PIX_FMT_GREY 8 Greyscale */ + { v4l2_fourcc('Y','V','U','9'), &qc_fmt_formats_YVU9 }, /* V4L2_PIX_FMT_YVU410 9 YVU 4:1:0 */ + { v4l2_fourcc('Y','V','1','2'), &qc_fmt_formats_YV12 }, /* V4L2_PIX_FMT_YVU420 12 YVU 4:2:0 */ + { v4l2_fourcc('Y','U','Y','V'), &qc_fmt_formats_YUY2 }, /* V4L2_PIX_FMT_YUYV 16 YUV 4:2:2 */ + { v4l2_fourcc('Y','U','Y','2'), &qc_fmt_formats_YUY2 }, /* V4L2_PIX_FMT_YUY2 16 YUV 4:2:2: undocumented, guess same as YUY2 */ + { v4l2_fourcc('U','Y','V','Y'), &qc_fmt_formats_UYVY }, /* V4L2_PIX_FMT_UYVY 16 YUV 4:2:2 */ + { v4l2_fourcc('Y','4','1','P'), &qc_fmt_formats_Y41P }, /* V4L2_PIX_FMT_Y41P 12 YUV 4:1:1 */ + { v4l2_fourcc('Y','U','V','9'), &qc_fmt_formats_qcU9 }, /* V4L2_PIX_FMT_YUV410 9 YUV 4:1:0 */ + { v4l2_fourcc('Y','U','1','2'), &qc_fmt_formats_IYUV }, /* V4L2_PIX_FMT_YUV420 12 YUV 4:2:0 */ + { v4l2_fourcc('P','4','2','2'), &qc_fmt_formats_qcY2 }, /* V4L2_PIX_FMT_YUV422P 16 YUV422 planar */ + { v4l2_fourcc('P','4','1','1'), &qc_fmt_formats_qcY1 }, /* V4L2_PIX_FMT_YUV411P 16 YUV411 planar: assume bpp should be 12 */ + { v4l2_fourcc('N','V','1','2'), &qc_fmt_formats_NV12 }, /* V4L2_PIX_FMT_NV12 12 Y/UV 4:2:0 */ + { v4l2_fourcc('4','2','2','P'), &qc_fmt_formats_qcV2 }, /* V4L2_PIX_FMT_YVU422P 16 YVU422 planar */ + { v4l2_fourcc('4','1','1','P'), &qc_fmt_formats_qcV1 }, /* V4L2_PIX_FMT_YVU411P 16 YVU411 planar: assume bpp should be 12 */ + { v4l2_fourcc('Y','Y','U','V'), &qc_fmt_formats_qcYY }, /* V4L2_PIX_FMT_YYUV 16 YUV 4:2:2: undocumented, guess this is qc YY */ + { v4l2_fourcc('H','I','2','4'), &qc_fmt_formats_RGB_HI }, /* V4L2_PIX_FMT_HI240 8 8-bit color */ + { v4l2_fourcc('N','V','2','1'), &qc_fmt_formats_NV21 }, /* V4L2_PIX_FMT_NV21 12 Y/UV 4:2:0 */ + { v4l2_fourcc('W','N','V','A'), &qc_fmt_formats_qcWN }, /* V4L2_PIX_FMT_WNVA Winnov hw compres */ +}; +/* }}} */ + +/* {{{ [fold] qc_fmt_issupported(int palette) */ +/* Check the format (can be called even before qc_fmt_init) */ +int qc_fmt_issupported(int palette) +{ + int i; + for (i=0; isupported) + return 0; + } + return -EINVAL; +} +/* }}} */ +/* {{{ [fold] qc_fmt_getname(int palette) */ +/* Return the format name (can be called even before qc_fmt_init) */ +const char *qc_fmt_getname(int palette) +{ + int i; + for (i=0; iname; + } + return "Unknown"; +} +/* }}} */ +/* {{{ [fold] qc_fmt_getdepth(int palette) */ +/* Return bits per pixel for the format, or + * 0=variable number (compressed formats), -1=unknown + * (can be called even before qc_fmt_init) */ +int qc_fmt_getdepth(int palette) +{ + int i; + for (i=0; ibpp; + } + return -1; /* Unknown bit depth */ +} +/* }}} */ +/* {{{ [fold] qc_fmt_init(struct quickcam *qc) */ +int qc_fmt_init(struct quickcam *qc) +{ + int r = 0; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_fmt_init(qc=%p/compr=%i)",qc,qc->settings.compress); +#if COMPRESS + if (qc->settings.compress) { + qc->fmt_data.compress = TRUE; + r = qc_mjpeg_init(&qc->fmt_data.mjpeg_data, 24, DEFAULT_BGR); + } else { + qc->fmt_data.compress = FALSE; + } +#endif + if (r>=0) IDEBUG_INIT(qc->fmt_data); + return r; +} +/* }}} */ +/* {{{ [fold] qc_fmt_exit(struct quickcam *qc) */ +void qc_fmt_exit(struct quickcam *qc) +{ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_fmt_exit(qc=%p)",qc); +#if COMPRESS + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_fmt_exit/compress=%i",qc->fmt_data.compress); + if (qc->fmt_data.compress) qc_mjpeg_exit(&qc->fmt_data.mjpeg_data); + POISON(qc->fmt_data.compress); + POISON(qc->fmt_data.mjpeg_data); +#endif + POISON(qc->fmt_data.lut); + IDEBUG_EXIT_NOPOISON(qc->fmt_data); +} +/* }}} */ +/* {{{ [fold] qc_fmt_convert(struct quickcam *qc, unsigned char *src, unsigned int src_len, unsigned char *dst, unsigned int dst_len, int *midvalue) */ +/* Called after each full frame of bayer or compressed image obtained */ +/* Convert camera data in src to the application requested palette in dst */ +/* Return negative error code if failure, otherwise data length stored in dst */ +/* src_len is the length of actual data in src, dst_len is the maximum data size storable in dst */ +/* Also src buffer may be modified */ +/* Return image average brightness in midvalue (or -1 if not computed) */ +int qc_fmt_convert(struct quickcam *qc, unsigned char *src, unsigned int src_len, unsigned char *dst, unsigned int dst_len, int *midvalue) +{ + signed int originx, originy; /* Upper-left corner coordinates of the capture window in the bayer image */ + unsigned char *bayerwin; + int length; /* Converted image data length in bytes */ + int r = 0; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_imag_convert(qc=%p,src=%p,src_len=%i,dst=%p,dst_len=%i)",qc,src,src_len,dst,dst_len); + if (PARANOID && (qc==NULL || src==NULL || dst==NULL)) { PRINTK(KERN_CRIT,"NULL"); return -EINVAL; } + if (PARANOID && midvalue==NULL) { PRINTK(KERN_CRIT,"NULL"); return -EINVAL; } + IDEBUG_TEST(qc->fmt_data); + *midvalue = -1; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("sensor_width=%i sensor_height=%i vwin.width=%i vwin.height=%i", + qc->sensor_data.width,qc->sensor_data.height,qc->vwin.width,qc->vwin.height); + + if (qc->sensor_data.width < qc->vwin.width || qc->sensor_data.height < qc->vwin.height) { + if (qcdebug&QC_DEBUGERRORS) PDEBUG("sensor window is smaller than requested"); + r = -ENOMSG; + goto fail; + } + +#if DUMPDATA + if (midvalue) *midvalue = -1; + memset(dst, 0, dst_len); + memcpy(dst, src, src_len>dst_len ? dst_len : src_len); + length = (int)qc->vwin.width * (int)qc->vwin.height * 3; + return length; +#endif + +#if COMPRESS + if (!qc->sensor_data.compress) { +#endif + /* src buffer contains fixed length data in bayer format */ + /* sensor_data.height/width = frame size that is captured from the camera */ + /* vwin.height/width = frame size that the application is expecting */ + + /* Check if src buffer contains enough data */ + if (src_len < qc->sensor_data.width * qc->sensor_data.height) { + if (qcdebug&QC_DEBUGERRORS) PDEBUG("too little data by %i (expected %i)", qc->sensor_data.width*qc->sensor_data.height - src_len, qc->sensor_data.width * qc->sensor_data.height); + r = -EBADE; + goto fail; + } + /* calculate view window origin inside the whole frame */ + originy = ((signed int)qc->sensor_data.height - (signed int)qc->vwin.height) / 2; + originx = ((signed int)qc->sensor_data.width - (signed int)qc->vwin.width) / 2; + originx &= ~1; /* Set upper-left corner to a even coordinate */ + originy &= ~1; /* so that the first bayer pixel is green */ + bayerwin = src + originy * qc->sensor_data.width + originx; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("originy=%i originx=%i", originy,originx); + + if (qc->settings.adaptive && midvalue!=NULL) + *midvalue = qc_imag_bayer_midvalue(bayerwin, qc->sensor_data.width, qc->vwin.width, qc->vwin.height); + if (qc->settings.equalize || qc->settings.userlut) { + if (qc->settings.equalize) { + qc_imag_bayer_equalize(bayerwin, qc->sensor_data.width, qc->vwin.width, qc->vwin.height, &qc->fmt_data.lut); + } else { + /* Initialize LUT */ + int i; + for (i=0; i<256; i++) qc->fmt_data.lut[QC_LUT_RED+i] = i; + for (i=0; i<256; i++) qc->fmt_data.lut[QC_LUT_GREEN+i] = i; + for (i=0; i<256; i++) qc->fmt_data.lut[QC_LUT_BLUE+i] = i; + } + if (qc->settings.userlut) { + qc_imag_userlut(&qc->fmt_data.userlut, &qc->fmt_data.lut); + } + /* Could do here other effects to the lookup table */ + qc_imag_bayer_lut(bayerwin, qc->sensor_data.width, qc->vwin.width, qc->vwin.height, &qc->fmt_data.lut); + } + + if (qc->vpic.palette==VIDEO_PALETTE_BAYER) { + int i; + length = (int)qc->vwin.width * (int)qc->vwin.height; + if (length > dst_len) { + r = -ENOSPC; + goto fail; + } + /* It would be more efficient to capture data directly to the mmapped buffer, + * but more complex and hardly any application will use bayer palette anyway */ + for (i=0; ivwin.height; i++) { + memcpy(dst, bayerwin, qc->vwin.width); + bayerwin += qc->sensor_data.width; + dst += qc->vwin.width; + } + } else { + /* Convert the current frame to RGB */ + length = (int)qc->vwin.width * (int)qc->vwin.height * 3; + if (length > dst_len) { + r = -ENOSPC; + goto fail; + } + switch (qc->settings.quality) { + case 0: + qc_imag_bay2rgb_cottnoip(bayerwin, qc->sensor_data.width, + dst, 3*qc->vwin.width, + qc->vwin.width, qc->vwin.height, 3); + break; + case 1: + qc_imag_bay2rgb_cott(bayerwin, qc->sensor_data.width, + dst, 3*qc->vwin.width, + qc->vwin.width, qc->vwin.height, 3); + break; + case 2: + qc_imag_bay2rgb_horip(bayerwin, qc->sensor_data.width, + dst, 3*qc->vwin.width, + qc->vwin.width, qc->vwin.height, 3); + break; + case 3: + qc_imag_bay2rgb_ip(bayerwin, qc->sensor_data.width, + dst, 3*qc->vwin.width, + qc->vwin.width, qc->vwin.height, 3); + break; + default: + case 4: + qc_imag_bay2rgb_gptm_fast(bayerwin, qc->sensor_data.width, + dst, 3*qc->vwin.width, + qc->vwin.width, qc->vwin.height, 3); + break; + case 5: + qc_imag_bay2rgb_gptm(bayerwin, qc->sensor_data.width, + dst, 3*qc->vwin.width, + qc->vwin.width, qc->vwin.height, 3, qc->vpic.whiteness); + break; + } + goto rgb24; + } + +#if COMPRESS + } else { + /* src buffer contains variable length data in mjpeg format */ + if (qc->vpic.palette==VIDEO_PALETTE_MJPEG) { + /* Directly copy data from src to dst, can not resize */ + length = src_len; + if (length > dst_len) { + r = -ENOSPC; + goto fail; + } + memcpy(dst, src, src_len); + } else { + /* Decode compressed images */ + if (!qc->fmt_data.compress) { + r = -EINVAL; + goto fail; + } + length = qc->sensor_data.width * qc->sensor_data.height * 3; + if (length > dst_len) { + r = -ENOSPC; + goto fail; + } + r = qc_mjpeg_decode(&qc->fmt_data.mjpeg_data, src, src_len, dst); + if (r<0) goto fail; + + if ((int)qc->vwin.width < qc->sensor_data.width || (int)qc->vwin.height < qc->sensor_data.height) { + /* User requested smaller image than camera sent, so crop the image */ + unsigned char *s, *d = dst; + int i; + s = dst; + s += (qc->sensor_data.height - (int)qc->vwin.height)/2 * qc->sensor_data.width*3; + s += (qc->sensor_data.width - (int)qc->vwin.width)/2 * 3; + for (i=0; ivwin.height; i++) { + memcpy(d, s, (int)qc->vwin.width*3); + s += qc->sensor_data.width * 3; + d += (int)qc->vwin.width * 3; + } + /* vwin.width/height is always smaller or equal to sensor_data.width/height */ + length = (int)qc->vwin.width * (int)qc->vwin.height * 3; + } + if (qc->settings.adaptive && midvalue!=NULL) *midvalue = qc_imag_rgb24_midvalue(dst, 3*qc->sensor_data.width, (int)qc->vwin.width, (int)qc->vwin.height); + goto rgb24; + } + } +#endif + return length; + +rgb24: /* We have now RGB (24 bpp) data in dst. If some other format is desired, */ + /* convert the RGB image to it (e.g. YUV) */ + +#ifdef DEBUG +#if 1 +{ +/* Draw red rectangle around image (useful for debugging boundaries) */ +static const int R = 255; +static const int G = 0; +static const int B = 0; + int ty,tx; + for (tx=0; txvwin.width; tx++) { + ty=0; + dst[ty*qc->vwin.width*3+tx*3] = B; + dst[ty*qc->vwin.width*3+tx*3+1] = G; + dst[ty*qc->vwin.width*3+tx*3+2] = R; + ty=qc->vwin.height-1; + dst[ty*qc->vwin.width*3+tx*3] = B; + dst[ty*qc->vwin.width*3+tx*3+1] = G; + dst[ty*qc->vwin.width*3+tx*3+2] = R; + } + for (ty=0; tyvwin.height; ty++) { + tx=0; + dst[ty*qc->vwin.width*3+tx*3] = B; + dst[ty*qc->vwin.width*3+tx*3+1] = G; + dst[ty*qc->vwin.width*3+tx*3+2] = R; + tx=qc->vwin.width-1; + dst[ty*qc->vwin.width*3+tx*3] = B; + dst[ty*qc->vwin.width*3+tx*3+1] = G; + dst[ty*qc->vwin.width*3+tx*3+2] = R; + } +} +#endif +#endif + + if (qc->vpic.palette != VIDEO_PALETTE_RGB24) { + // FIXME: should check here that dst_len <= resulted image length + length = qc_yuv_rgb2yuv(dst, length, qc->vpic.palette); + } else if (qc->settings.compat_torgb) { + qc_imag_rgbbgr(dst, length/3, 3); + } + return length; + +fail: if (qcdebug&(QC_DEBUGERRORS|QC_DEBUGLOGIC)) PDEBUG("failed qc_imag_convert()=%i",r); + return r; +} +/* }}} */ + +/* }}} */ + +/* End of file */ --- linux-2.6.27.orig/ubuntu/qc-usb/qc-vv6410.c +++ linux-2.6.27/ubuntu/qc-usb/qc-vv6410.c @@ -0,0 +1,650 @@ +/* Start of file */ + +/* {{{ [fold] Comments */ +/* + * qce-ga, linux V4L driver for the QuickCam Express and Dexxa QuickCam + * + * vv6410.c - VV6410 Sensor Implementation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* }}} */ + +#include "quickcam.h" + +#ifndef QCEGA_MODE +#define QCEGA_MODE 0 /* If the driver doesn't work for you, try changing this to "1" */ +#endif + +/* LSB bit of I2C address signifies write (0) or read (1) */ + +/* I2C Address */ +#define VV6410_ADDR (0x10<<1) + +/* {{{ [fold] I2C Registers */ +/* Status registers */ +#define VV6410_DEVICEH 0x00 /* Chip identification number including revision indicator */ +#define VV6410_DEVICEL 0x01 +#define VV6410_STATUS0 0x02 /* User can determine whether timed I2C data has been consumed by interrogating flag states */ +#define VV6410_LINECOUNTH 0x03 /* Current line counter value */ +#define VV6410_LINECOUNTL 0x04 +#define VV6410_XENDH 0x05 /* End x coordinate of image size */ +#define VV6410_XENDL 0x06 +#define VV6410_YENDH 0x07 /* End y coordinate of image size */ +#define VV6410_YENDL 0x08 +#define VV6410_DARKAVGH 0x09 /* This is the average pixel value returned from the dark line offset cancellation algorithm */ +#define VV6410_DARKAVGL 0x0A +#define VV6410_BLACKAVGH 0x0B /* This is the average pixel value returned from the black line offset cancellation algorithm */ +#define VV6410_BLACKAVGL 0x0C +#define VV6410_STATUS1 0x0D /* Flags to indicate whether the x or y image coordinates have been clipped */ + +/* Setup registers */ +#define VV6410_SETUP0 0x10 /* Low-power/sleep modes & video timing */ +#define VV6410_SETUP1 0x11 /* Various parameters */ +#define VV6410_SYNCVALUE 0x12 /* Contains pixel counter reset value used by external sync */ +#define VV6410_FGMODES 0x14 /* Frame grabbing modes (FST, LST and QCK) */ +#define VV6410_PINMAPPING 0x15 /* FST and QCK mapping modes. */ +#define VV6410_DATAFORMAT 0x16 /* Data resolution */ +#define VV6410_OPFORMAT 0x17 /* Output coding formats */ +#define VV6410_MODESELECT 0x18 /* Various mode select bits */ + +/* Exposure registers */ +#define VV6410_FINEH 0x20 /* Fine exposure. */ +#define VV6410_FINEL 0x21 +#define VV6410_COARSEH 0x22 /* Coarse exposure */ +#define VV6410_COARSEL 0x23 +#define VV6410_ANALOGGAIN 0x24 /* Analog gain setting */ +#define VV6410_CLKDIV 0x25 /* Clock division */ +#define VV6410_DARKOFFSETH 0x2C /* Dark line offset cancellation value */ +#define VV6410_DARKOFFSETL 0x2D +#define VV6410_DARKOFFSETSETUP 0x2E /* Dark line offset cancellation enable */ + +/* Colour registers (none on this camera!) */ + +/* Video timing registers */ +#define VV6410_LINELENGTHH 0x52 /* Line Length (Pixel Clocks) */ +#define VV6410_LINELENGTHL 0x53 +#define VV6410_XOFFSETH 0x57 /* X-co-ordinate of top left corner of region of interest (x-offset) */ +#define VV6410_XOFFSETL 0x58 +#define VV6410_YOFFSETH 0x59 /* Y-co-ordinate of top left corner of region of interest (y-offset) */ +#define VV6410_YOFFSETL 0x5A +#define VV6410_FIELDLENGTHH 0x61 /* Field length (Lines) */ +#define VV6410_FIELDLENGTHL 0x62 + +/* Text overlay registers (none on this camera!) */ + +/* I2C autoload registers (none on this camera!) */ + +/* System registers */ +#define VV6410_BLACKOFFSETH 0x70 /* Black offset cancellation default value */ +#define VV6410_BLACKOFFSETL 0x71 +#define VV6410_BLACKOFFSETSETUP 0x72 /* Black offset cancellation setup */ +#define VV6410_CR0 0x75 /* Analog Control Register 0 */ +#define VV6410_CR1 0x76 /* Analog Control Register 1 */ +#define VV6410_AS0 0x77 /* ADC Setup Register */ +#define VV6410_AT0 0x78 /* Analog Test Register */ +#define VV6410_AT1 0x79 /* Audio Amplifier Setup Register */ +/* }}} */ + +#define I2C_SET_CHECK(reg,val) if ((r = qc_i2c_set(qc,(reg),(val)))<0) goto fail +#define STV_SET_CHECK(reg,val) if ((r = qc_stv_set(qc,(reg),(val)))<0) goto fail +#define STV_SETW_CHECK(reg,val) if ((r = qc_stv_setw(qc,(reg),(val)))<0) goto fail +#define IS_850(qc) (GET_PRODUCTID(qc)==0x850) /* Is it QuickCam Web/Legocam? */ + +#if QCEGA_MODE +#warning "Using old compatible code (QCEGA_MODE=1)" +#warning "If this works but otherwise it doesn't work, let me know!" +static int mode = 0; +#define VV6410_CONTROL 0x10 // Setup0 +#define VV6410_GAIN 0x24 +/* {{{ [fold] vv6410_set_window() */ +static int vv6410_set_window(struct quickcam *qc, int x, int y,int width, int height) +{ + int r = 0; + + // x offset + x = MAX(1,x); + I2C_SET_CHECK(0x57,x >> 8); + I2C_SET_CHECK(0x58,x & 0xff); + + // y offset + y = MAX(1,y); + I2C_SET_CHECK(0x59,y >> 8); + I2C_SET_CHECK(0x5a,y & 0xff); + + // Set the real + if (qc->sensor_data.subsample) { + qc->sensor_data.width=180; + qc->sensor_data.height=148; + } else { + qc->sensor_data.width=356; + qc->sensor_data.height=292; + } + + // line length + if (qc->sensor_data.subsample) { + if (IS_850(qc)) + width=250; + else + width=360; /* 180 * 2 (CLK-DIV is 2) */ + } + else { + if (IS_850(qc)) + width=416; + else + width=712; /* 356 * 2 */ + } + + I2C_SET_CHECK(0x52, width >> 8); + I2C_SET_CHECK(0x53, width & 0xff); + + // field length (num lines) + if (qc->sensor_data.subsample) + height=160; /* nearest of 148 = 10 * 16 */ + else + height=320; // 304; /* nearest of 292 = 19 * 16 */ + + I2C_SET_CHECK(0x61,height >> 8); + I2C_SET_CHECK(0x62,height & 0xff); + + // usb_quickcam_i2c_add(&i2cbuff,0x25,0x02); + if ((r = qc_i2c_wait(qc))<0) goto fail; + + return 0; +fail: + return -ENAMETOOLONG; //some silly code just for testing +} +/* }}} */ +#endif + +/* {{{ [fold] vv6410_set_size: Set window size */ +static int vv6410_set_size(struct quickcam *qc, unsigned int width, unsigned int height) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6410_set_size(qc=%p,width=%i,height=%i)",qc,width,height); + /* VV6410 appears to always give fixed 356*292 pixels */ + sd->width = sd->maxwidth; + sd->height = sd->maxheight; + return 0; +} +/* }}} */ +/* {{{ [fold] vv6410_start: Start grabbing */ +static int vv6410_start(struct quickcam *qc) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + int r; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6410_start(qc=%p)",qc); + if (PARANOID && !qc) { PDEBUG("qc==NULL"); return -EINVAL; } + I2C_SET_CHECK(VV6410_SETUP0, sd->subsample ? (BIT(7)|BIT(6)) : 0x00); + if (IS_850(qc)) qc_stv_set(qc, 0x1445, 1); /* Turn on LED */ + r = qc_i2c_wait(qc); +fail: return r; +} +/* }}} */ +/* {{{ [fold] vv6410_stop: Stop grabbing */ +static int vv6410_stop(struct quickcam *qc) +{ + static const int low_power_mode = 0; //1; + static const int sleep_mode = 1; + struct qc_sensor_data *sd = &qc->sensor_data; + unsigned char cmd; + int r; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6410_stop(qc=%p)",qc); + if (IS_850(qc)) qc_stv_set(qc, 0x1445, 0); /* Turn off LED */ + cmd = (sleep_mode << 1) | low_power_mode; + if (sd->subsample) cmd |= BIT(7)|BIT(6); /* sub-sampled QCIF mode */ + I2C_SET_CHECK(VV6410_SETUP0, cmd); + r = qc_i2c_wait(qc); +fail: return r; +} +/* }}} */ +#if COMPRESS +struct stv_init { + const u8 *data; /* If NULL, only single value to write, stored in len */ + u16 start; + u8 len; +}; +#endif +/* {{{ [fold] vv6410_init: Initialise parameters for vv6410 sensor. */ +/* Just try to send the same commands as Windoze QuickCam soft */ +static int vv6410_init(struct quickcam *qc) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + int r; + +#if COMPRESS + if (IS_850(qc)) { +/* {{{ [fold] Initialization with compression support */ + +/* {{{ [fold] [fold] stv_init[] */ + static const u8 x0540[] = { /* 0x0540 - 0x0551 */ + 0x97,0x0B,0x4C,0xFC,0x36,0x00,0x75,0x00,0x59,0x02,0x32,0x01,0x56,0xFD,0xEE,0xFF, + 0xB8,0x05 }; + static const u8 x0560[] = { /* 0x0560 - 0x0563 */ + 0x40,0xFF,0xBF,0xBF }; + static const u8 x1500[] = { /* 0x1500 - 0x150F */ + 0x0B,0xA7,0xB7,0x00,0x00,0x00,0x14,0x14,0x14,0x14,0x2B,0x02,0x2B,0x02,0x2B,0x02 }; + static const u8 x1520[] = { /* 0x1520 - 0x152A */ + 0x05,0x14,0x0F,0x0F,0x98,0x98,0x98,0x98,0x2D,0x00,0x01 }; + static const u8 x1530[] = { /* 0x1530 - 0x153B */ + 0x08,0x02,0x00,0x00,0x02,0x00,0x02,0x00,0x60,0x01,0x20,0x01 }; + static const u8 x1552[] = { /* 0x1552 - 0x1558 */ + 0x72,0x90,0x00,0xB0,0xF0,0x77,0x72 }; + static const u8 x1564[] = { /* 0x1564 - 0x1567 */ + 0x00,0xFF,0x0C,0x00 }; + static const u8 x1580[] = { /* 0x1580 - 0x158F */ + 0x02,0x40,0x01,0xF0,0x00,0xD1,0x01,0xAC,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00 }; + static const u8 x1590[] = { /* 0x1590 - 0x15A5 */ + 0xA8,0x05,0x64,0x07,0x0F,0x03,0xD8,0x07,0xA6,0x06,0x71,0x04,0x8F,0x01,0xFF,0xFB, + 0xEC,0xE6,0xE0,0xD9,0xC4,0xB8 }; + static const u8 x15C1[] = { /* 0x15C1 - 0x15C2 */ + 0x4B, 0x02 }; /* Output word 0x024B=587 (ISO size) */ + static const struct stv_init stv_init[] = { + { NULL, 0x1620, 0x80 }, /* This reg is written twice. Some kind of reset? */ + { NULL, 0x1620, 0x00 }, + { x0540, 0x0540, SIZE(x0540) }, + { x0560, 0x0560, SIZE(x0560) }, + { NULL, 0x1423, 0x04 }, + { NULL, 0x1440, 0x00 }, + { NULL, 0x1443, 0x00 }, + { NULL, 0x1445, 0x01 }, + { x1500, 0x1500, SIZE(x1500) }, + { x1520, 0x1520, SIZE(x1520) }, + { x1530, 0x1530, SIZE(x1530) }, + { x1552, 0x1552, SIZE(x1552) }, + { x1564, 0x1564, SIZE(x1564) }, + { x1580, 0x1580, SIZE(x1580) }, + { x1590, 0x1590, SIZE(x1590) }, + { x15C1, 0x15C1, SIZE(x15C1) }, + { NULL, 0x15C3, 0x00 }, + { NULL, 0x15C9, 0x01 }, + { NULL, 0x1704, 0x00 }, + }; +/* }}} */ +/* {{{ [fold] vv_init[][2] */ + static const u8 vv_init[][2] = { + /* Setup registers */ + { VV6410_SETUP0, BIT(2) }, /* Soft reset */ + { VV6410_SETUP0, BIT(1)|BIT(0) }, /* 25 fps PAL (30 fps NTSC doesn't work!), sleep mode */ + { VV6410_SETUP1, BIT(6) }, /* Use unsuffled read-out mode */ + { VV6410_FGMODES, BIT(6)|BIT(4)|BIT(2)|BIT(0) }, /* All modes to 1 */ + { VV6410_PINMAPPING, 0x00 }, + { VV6410_DATAFORMAT, BIT(7)|BIT(0) }, /* Pre-clock generator divide off */ + { VV6410_OPFORMAT, BIT(3)|BIT(4) }, + /* Exposure registers */ + { VV6410_FINEH, 320 >> 8 }, /* Initial exposure */ + { VV6410_FINEL, 320 & 0xFF }, + { VV6410_COARSEH, 192 >> 8 }, + { VV6410_COARSEL, 192 & 0xFF }, + { VV6410_ANALOGGAIN, 0xF0 | 11 }, /* Gain to 11 */ + { VV6410_CLKDIV, 0x01 }, /* Pixel clock divisor 2 */ + /* Video timing registers */ + { VV6410_LINELENGTHH, (416-1) >> 8 }, /* Set line length (columns) to 417 */ + { VV6410_LINELENGTHL, (416-1) & 0xFF }, + { VV6410_FIELDLENGTHH, (320-1) >> 8 }, /* Set field length (rows) to 320 */ + { VV6410_FIELDLENGTHL, (320-1) & 0xFF }, + /* System registers */ + { VV6410_AS0, BIT(6)|BIT(4)|BIT(3)|BIT(2)|BIT(1) }, /* Enable voltage doubler */ + { VV6410_AT0, 0x00 }, + { VV6410_AT1, BIT(4)|BIT(0) }, /* Power up audio, differential */ + }; +/* }}} */ + + unsigned int cols = 416; + unsigned int rows = 320; + unsigned int x = 1; + unsigned int y = 1; + int i,j; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6410_init(qc=%p)",qc); + if (PARANOID && !qc) { PDEBUG("qc==NULL"); return -EINVAL; } + + sd->width = 320; /* Default to compressed mode */ + sd->height = 240; + + for (i=0; isubsample ? 0x10 : 0x20); /* Scan rate */ + STV_SET_CHECK(0x1446,1); + STV_SETW_CHECK(0x15C1,600); /* ISO size, 0x380|orig:600 */ + STV_SET_CHECK(0x1680,0x14); /* X ctrl */ + } + + for (i=0; icompress) { + /* Disable compression */ + STV_SET_CHECK(0x1443, sd->subsample ? 0x00 : 0x10); /* Scan rate: Larger -> slower */ + STV_SETW_CHECK(0x15C1, 1023); /* ISO-Size */ + STV_SET_CHECK(0x15C3, 1); /* Y control */ + sd->width = 356; + sd->height = 292; + if (qc->settings.subsample) { + //FIXME:subsampling (still) doesn't work yet + cols=250; + rows=160; + sd->width = 180; + sd->height = 148; + I2C_SET_CHECK(VV6410_SETUP0, BIT(7)|BIT(6)|BIT(1)|BIT(0)); /* Subsampled timing mode */ + } + } + I2C_SET_CHECK(VV6410_XOFFSETH, x >> 8); + I2C_SET_CHECK(VV6410_XOFFSETL, x & 0xFF); + I2C_SET_CHECK(VV6410_YOFFSETH, y >> 8); + I2C_SET_CHECK(VV6410_YOFFSETL, y & 0xFF); + I2C_SET_CHECK(VV6410_LINELENGTHH, (cols-1) >> 8); + I2C_SET_CHECK(VV6410_LINELENGTHL, (cols-1) & 0xFF); + I2C_SET_CHECK(VV6410_FIELDLENGTHH, (rows-1) >> 8); + I2C_SET_CHECK(VV6410_FIELDLENGTHL, (rows-1) & 0xFF); + sd->maxwidth = sd->width; + sd->maxheight = sd->height; + return 0; +/* }}} */ + } else { +#endif +/* {{{ [fold] Initialization without compression support */ + if (sd->compress) return -EINVAL; + if (sd->subsample) { + sd->maxwidth = 180; + sd->maxheight = 148; + } else { + sd->maxwidth = 356; + sd->maxheight = 292; + } + + +#if QCEGA_MODE +{ +int line_length = mode?250:416;//415; + + if (mode) { + sd->subsample=1; // quater. + sd->width = 180; + sd->height = 148; + } else { + sd->subsample=0; + sd->width = 356; + sd->height = 292; + } + + STV_SET_CHECK(STV_REG23, 5); // was 5. + + + if (!IS_850(qc)) { + /* logitech quickcam web has 0x850 as idProduct */ + STV_SET_CHECK(0x1446, 1); + } + + + STV_SET_CHECK(STV_SCAN_RATE, 0x00); + + + STV_SET_CHECK(0x1423, 0x04); + + + STV_SET_CHECK(STV_REG00, 0x1b); // 0x0b + + + + I2C_SET_CHECK(VV6410_CONTROL,0x04); // reset to defaults + if ((r = qc_i2c_wait(qc))<0) goto fail; + + + + + // CIF or QCIF and sleep. + if (IS_850(qc)) { + I2C_SET_CHECK(VV6410_CONTROL,(mode?0xa2:0x02)); + } else { + I2C_SET_CHECK(VV6410_CONTROL,(mode?0xc2:0x02)); + } + + if ((r = qc_i2c_wait(qc))<0) goto fail; + + + + I2C_SET_CHECK(VV6410_GAIN,0xfb); + if ((r = qc_i2c_wait(qc))<0) goto fail; + + + + + + STV_SET_CHECK(STV_REG04, 0x07); + + + STV_SET_CHECK(STV_REG03, 0x45); + + + /* set window size */ + if ((r=vv6410_set_window(qc,0,0,48,64)) < 0) { + PRINTK(KERN_ERR, "vv6410_set_window failed"); + goto fail; + } + + + /* EXPERIMENTAL */ + /* + * line length default is 415 so it's the value we use to + * calculate values for registers 0x20-0x21 + * Ref. DS Pag. 67 + */ + I2C_SET_CHECK(0x20,mode? ((line_length-23)>>8):((line_length-51)>>8)); + + I2C_SET_CHECK(0x21,mode?((line_length-23)&0xff):((line_length-51)&0xff)); + + I2C_SET_CHECK(0x22,mode?0x00:0x01); + //usb_quickcam_i2c_add(&i2cbuff,0x23,mode?0x9e:0x3e); + I2C_SET_CHECK(0x23,mode?158:318&0xff); + I2C_SET_CHECK(0x24,0xfa); + // clock divisor. + I2C_SET_CHECK(0x25,0x01); + + if ((r = qc_i2c_wait(qc))<0) goto fail; + + + /* + if (isaweb(dev)) + { + //EXPERIMENTAL: dark/black pixel cancellation + usb_quickcam_i2c_add(&i2cbuff,0x3e,0x01); + usb_quickcam_i2c_add(&i2cbuff,0x72,0x01); + if (usb_quickcam_i2c_send(dev,&i2cbuff,VV6410_ADDR) < 0) { + printk(KERN_ERR "usb_control_msg dark/black pixel failed"); + goto error; + } + } + */ + STV_SET_CHECK(STV_REG01, 0xb7); + + STV_SET_CHECK(STV_REG02, 0xa7); + + + + // setup + I2C_SET_CHECK(0x11,0x18); // 0x18 or Jochen 0x40 + I2C_SET_CHECK(0x14,0x55); // was 0x55 + I2C_SET_CHECK(0x15,0x10); // 0x10 or Jochen:0x00 + I2C_SET_CHECK(0x16,0x81); // Pre clock dividor. + I2C_SET_CHECK(0x17,0x18); // they are reserved. + I2C_SET_CHECK(0x18,0x00); + I2C_SET_CHECK(0x77,0x5e); + I2C_SET_CHECK(0x78,0x04);// 0x04 or Jochen:0x00 + if (IS_850(qc)) { + I2C_SET_CHECK(0x79,0x11);//audio init + } + if ((r = qc_i2c_wait(qc))<0) goto fail; + + + + + STV_SETW_CHECK(STV_ISO_SIZE, IS_850(qc)?1023:600); // 0x380|orig:600 + + + + + STV_SET_CHECK(STV_Y_CTRL, 1); + + + STV_SET_CHECK(STV_SCAN_RATE, mode?0x00:0x10); + + + + if (!IS_850(qc)) { + /* logitech quickam web has 0x0850 as idProduct */ + STV_SET_CHECK(STV_X_CTRL, 0x14); + } +} + +#else + STV_SET_CHECK(0x0423,0x05); /* Unknown register, 0x04 or 0x05 */ + STV_SET_CHECK(0x1423,0x04); /* Unknown register, 0x04 or 0x05 */ + STV_SET_CHECK(0x1443,0x00); /* Scan rate */ + STV_SET_CHECK(0x1500,0x1B); /* 0x0B */ + STV_SET_CHECK(0x1501,0xB7); + STV_SET_CHECK(0x1502,0xA7); + STV_SET_CHECK(0x1503,0x45); + STV_SET_CHECK(0x1504,0x07); + STV_SET_CHECK(0x15C3,1); /* Y ctrl */ + if (IS_850(qc)) { + STV_SET_CHECK(0x1443, sd->subsample ? 0x20 : 0x10); /* Scan rate */ + STV_SETW_CHECK(0x15C1,1023); /* ISO size, 0x380|orig:600 */ + } else { + STV_SET_CHECK(0x1443, sd->subsample ? 0x10 : 0x20); /* Scan rate */ + STV_SET_CHECK(0x1446,1); + STV_SETW_CHECK(0x15C1,600); /* ISO size, 0x380|orig:600 */ + STV_SET_CHECK(0x1680,0x14); /* X ctrl */ + } + + I2C_SET_CHECK(0x10,0x04); /* Control register: reset to defaults */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + I2C_SET_CHECK(0x10,sd->subsample ? 0xC2 : 0x02);/* Control register: CIF or QCIF and sleep */ + if ((r = qc_i2c_wait(qc))<0) goto fail; + I2C_SET_CHECK(0x11,0x18); /* 0x18 or Jochen 0x40 */ + I2C_SET_CHECK(0x14,0x55); + I2C_SET_CHECK(0x15,0x10); /* 0x10 or Jochen:0x00 */ + I2C_SET_CHECK(0x16,0x81); /* Pre clock dividor. */ + I2C_SET_CHECK(0x17,0x18); /* they are reserved. */ + I2C_SET_CHECK(0x18,0x00); + I2C_SET_CHECK(0x24,0xFB); /* Set gain value */ + I2C_SET_CHECK(0x25,0x01); /* Clock divisor value */ + I2C_SET_CHECK(0x77,0x5E); + I2C_SET_CHECK(0x78,0x04); /* 0x04 or Jochen:0x00 */ + if (IS_850(qc)) { + I2C_SET_CHECK(0x3E,0x01); /* EXPERIMENTAL: dark/black pixel cancellation */ + I2C_SET_CHECK(0x72,0x01); + } + + if ((r = qc_i2c_wait(qc))<0) goto fail; +#endif + + return 0; +/* }}} */ +#if COMPRESS + } +#endif + +fail: return r; +} +/* }}} */ +/* {{{ [fold] vv6410_set_exposure() */ +static int vv6410_set_exposure(struct quickcam *qc, unsigned int val) +{ + struct qc_sensor_data *sd = &qc->sensor_data; + static const unsigned int linelength = 415; /* For CIF */ + unsigned int fine; + unsigned int coarse; + int r; + + val = (val*val >> 14) + val/4; + if (sd->exposure==val) return 0; + sd->exposure = val; + fine = val % linelength; + coarse = val / linelength; + if (coarse>=512) coarse = 512; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6410_set_exposure %d (%i,%i)",val,coarse,fine); + I2C_SET_CHECK(VV6410_FINEH, fine >> 8); + I2C_SET_CHECK(VV6410_FINEL, fine & 0xFF); + I2C_SET_CHECK(VV6410_COARSEH, coarse >> 8); + I2C_SET_CHECK(VV6410_COARSEL, coarse & 0xFF); +fail: return r; +} +/* }}} */ +/* {{{ [fold] vv6410_set_gains() */ +static int vv6410_set_gains(struct quickcam *qc, unsigned int hue, unsigned int sat, unsigned int val) +{ + static const int maxgain = 13; /* Absolute maximum is 14, recommended is 12 */ + struct qc_sensor_data *sd = &qc->sensor_data; + unsigned int gain; + int r; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6410_set_gains %d %d %d", hue, sat, val); + gain = val / 256; + gain >>= 4; + if (gain > maxgain) gain = maxgain; + if (sd->rgain==gain) return 0; + sd->rgain = gain; + r = qc_i2c_set(qc, VV6410_ANALOGGAIN, 0xF0 | gain); + return r; +} +/* }}} */ +/* {{{ [fold] vv6410_set_levels() */ +static int vv6410_set_levels(struct quickcam *qc, unsigned int exp, unsigned int gain, unsigned int hue, unsigned int sat) +{ + int r; + if ((r = vv6410_set_exposure(qc, exp))<0) goto fail; + vv6410_set_gains(qc, hue, sat, gain); +fail: return r; +} +/* }}} */ + +/* {{{ [fold] struct qc_sensor qc_sensor_vv6410 */ +const struct qc_sensor qc_sensor_vv6410 = { + name: "VV6410", + manufacturer: "ST Microelectronics", + init: vv6410_init, + start: vv6410_start, + stop: vv6410_stop, + set_size: vv6410_set_size, + set_levels: vv6410_set_levels, + /* Exposure and gain control information */ + autoexposure: FALSE, + adapt_gainlow: 40000, + adapt_gainhigh: 65535, + /* Information needed to access the sensor via I2C */ + reg23: 5, + i2c_addr: VV6410_ADDR, + /* Identification information used for auto-detection */ + id_reg: VV6410_DEVICEH, + id: 0x19, + length_id: 1, +}; +/* }}} */ + +/* End of file */ --- linux-2.6.27.orig/ubuntu/qc-usb/videodev2.h +++ linux-2.6.27/ubuntu/qc-usb/videodev2.h @@ -0,0 +1,1156 @@ +/* + * Video for Linux Two + * + * Header file for V4L2 drivers and applications. + * + * Author: Bill Dirks + */ + +#ifndef __LINUX_VIDEODEV_H +#define __LINUX_VIDEODEV_H + +#define V4L2_MAJOR_VERSION 0 +#define V4L2_MINOR_VERSION 20 + +#include "videodevfix.h" + + +/* + * M I S C E L L A N E O U S + */ + +/* Four-character-code (FOURCC) */ +#define fourcc(a,b,c,d)\ + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) + +/* Open flag for non-capturing opens on capture devices */ +#define O_NONCAP O_TRUNC +#define O_NOIO O_TRUNC + +/* Timestamp data type, 64-bit signed integer */ +/* Should be removed from here when UST is added to kernel */ +#ifndef STAMP_T +#define STAMP_T +typedef __s64 stamp_t; +#endif + +/* + * D R I V E R C A P A B I L I T I E S + */ +struct v4l2_capability +{ + char name[32]; /* Descriptive, and unique */ + int type; /* Device type, see below */ + int inputs; /* Num video inputs */ + int outputs; /* Num video outputs */ + int audios; /* Num audio devices */ + int maxwidth; + int maxheight; + int minwidth; + int minheight; + int maxframerate; + __u32 flags; /* Feature flags, see below */ + __u32 reserved[4]; +}; +/* Values for 'type' field */ +#define V4L2_TYPE_CAPTURE 0 /* Is a video capture device */ +#define V4L2_TYPE_CODEC 1 /* Is a CODEC device */ +#define V4L2_TYPE_OUTPUT 2 /* Is a video output device */ +#define V4L2_TYPE_FX 3 /* Is a video effects device */ +#define V4L2_TYPE_VBI 4 /* Is a VBI capture device */ +#define V4L2_TYPE_VTR 5 /* Is a tape recorder controller */ +#define V4L2_TYPE_VTX 6 /* Is a teletext device */ +#define V4L2_TYPE_RADIO 7 /* Is a radio device */ +#define V4L2_TYPE_PRIVATE 1000 /* Start of driver private types */ +/* Flags for 'flags' field */ +#define V4L2_FLAG_READ 0x00001 /* Can capture via read() call */ +#define V4L2_FLAG_WRITE 0x00002 /* Can accept data via write() */ +#define V4L2_FLAG_STREAMING 0x00004 /* Can capture streaming video */ +#define V4L2_FLAG_PREVIEW 0x00008 /* Can do automatic preview */ +#define V4L2_FLAG_SELECT 0x00010 /* Supports the select() call */ +#define V4L2_FLAG_TUNER 0x00020 /* Can tune */ +#define V4L2_FLAG_MONOCHROME 0x00040 /* Monochrome only */ +#define V4L2_FLAG_DATA_SERVICE 0x00080 /* Has a related data service dev. */ + + +/* + * V I D E O I M A G E F O R M A T + */ +struct v4l2_pix_format +{ + __u32 width; + __u32 height; + __u32 depth; + __u32 pixelformat; + __u32 flags; + __u32 bytesperline; /* only used when there are pad bytes */ + __u32 sizeimage; + __u32 priv; /* private data, depends on pixelformat */ +}; +/* Pixel format FOURCC depth Description */ +#define V4L2_PIX_FMT_RGB332 fourcc('R','G','B','1') /* 8 RGB-3-3-2 */ +#define V4L2_PIX_FMT_RGB555 fourcc('R','G','B','O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_RGB565 fourcc('R','G','B','P') /* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_BGR24 fourcc('B','G','R','3') /* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 fourcc('R','G','B','3') /* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_GREY fourcc('G','R','E','Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_YVU410 fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YVU420 fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YUYV fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_UYVY fourcc('U','Y','V','Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YVU422P fourcc('4','2','2','P') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YVU411P fourcc('4','1','1','P') /* 16 YVU411 planar */ + +/* The following formats are not defined in the V4L2 specification */ +#define V4L2_PIX_FMT_YUV410 fourcc('Y','U','V','9') /* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YUV420 fourcc('Y','U','1','2') /* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_YYUV fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_HI240 fourcc('H','I','2','4') /* 8 8-bit color */ + + +/* Flags */ +#define V4L2_FMT_FLAG_COMPRESSED 0x0001 /* Compressed format */ +#define V4L2_FMT_FLAG_BYTESPERLINE 0x0002 /* bytesperline field valid */ +#define V4L2_FMT_FLAG_INTERLACED 0x0004 /* Image is interlaced */ +#define V4L2_FMT_FLAG_TOPFIELD 0x0008 /* is a top field only */ +#define V4L2_FMT_FLAG_BOTFIELD 0x0010 /* is a bottom field only */ +#define V4L2_FMT_FLAG_ODDFIELD V4L2_FMT_FLAG_TOPFIELD +#define V4L2_FMT_FLAG_EVENFIELD V4L2_FMT_FLAG_BOTFIELD +#define V4L2_FMT_FLAG_COMBINED V4L2_FMT_FLAG_INTERLACED +#define V4L2_FMT_CS_field 0xF000 /* Color space field mask */ +#define V4L2_FMT_CS_601YUV 0x1000 /* ITU YCrCb color space */ +#define V4L2_FMT_FLAG_SWCONVERSION 0x0800 /* used only in format enum. */ +/* SWCONVERSION indicates the format is not natively supported by the */ +/* driver and the driver uses software conversion to support it */ + + +/* + * F O R M A T E N U M E R A T I O N + */ +struct v4l2_fmtdesc +{ + int index; /* Format number */ + char description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 flags; /* Format flags */ + __u32 depth; /* Bits per pixel */ + __u32 reserved[2]; +}; + +struct v4l2_cvtdesc +{ + int index; + struct + { + __u32 pixelformat; + __u32 flags; + __u32 depth; + __u32 reserved[2]; + } in, out; +}; + +struct v4l2_fxdesc +{ + int index; + char name[32]; + __u32 flags; + __u32 inputs; + __u32 controls; + __u32 reserved[2]; +}; + + +/* + * T I M E C O D E + */ +struct v4l2_timecode +{ + __u8 frames; + __u8 seconds; + __u8 minutes; + __u8 hours; + __u8 userbits[4]; + __u32 flags; + __u32 type; +}; +/* Type */ +#define V4L2_TC_TYPE_24FPS 1 +#define V4L2_TC_TYPE_25FPS 2 +#define V4L2_TC_TYPE_30FPS 3 +#define V4L2_TC_TYPE_50FPS 4 +#define V4L2_TC_TYPE_60FPS 5 + + +/* Flags */ +#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */ +#define V4L2_TC_FLAG_COLORFRAME 0x0002 +#define V4L2_TC_USERBITS_field 0x000C +#define V4L2_TC_USERBITS_USERDEFINED 0x0000 +#define V4L2_TC_USERBITS_8BITCHARS 0x0008 +/* The above is based on SMPTE timecodes */ + + +/* + * C O M P R E S S I O N P A R A M E T E R S + */ +struct v4l2_compression +{ + int quality; + int keyframerate; + int pframerate; + __u32 reserved[5]; +}; + + +/* + * M E M O R Y - M A P P I N G B U F F E R S + */ +struct v4l2_requestbuffers +{ + int count; + __u32 type; + __u32 reserved[2]; +}; +struct v4l2_buffer +{ + int index; + __u32 type; + __u32 offset; + __u32 length; + __u32 bytesused; + __u32 flags; + stamp_t timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + __u32 reserved[3]; +}; +/* Buffer type codes and flags for 'type' field */ +#define V4L2_BUF_TYPE_field 0x00001FFF /* Type field mask */ +#define V4L2_BUF_TYPE_CAPTURE 0x00000001 +#define V4L2_BUF_TYPE_CODECIN 0x00000002 +#define V4L2_BUF_TYPE_CODECOUT 0x00000003 +#define V4L2_BUF_TYPE_EFFECTSIN 0x00000004 +#define V4L2_BUF_TYPE_EFFECTSIN2 0x00000005 +#define V4L2_BUF_TYPE_EFFECTSOUT 0x00000006 +#define V4L2_BUF_TYPE_VIDEOOUT 0x00000007 +#define V4L2_BUF_TYPE_FXCONTROL 0x00000008 + +/* Starting value of driver private buffer types */ +#define V4L2_BUF_TYPE_PRIVATE 0x00001000 + +#define V4L2_BUF_ATTR_DEVICEMEM 0x00010000 /* Buffer is on device (flag) */ + +/* Flags used only in VIDIOC_REQBUFS */ +#define V4L2_BUF_REQ_field 0xF0000000 +#define V4L2_BUF_REQ_CONTIG 0x10000000 /* Map all buffers in one + contiguous mmap(). This flag + only used in VIDIOC_REQBUFS */ + +/* Flags for 'flags' field */ +#define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */ +#define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */ +#define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */ +#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ +#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ +#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ +#define V4L2_BUF_FLAG_TOPFIELD 0x0040 /* Image is a top field only */ +#define V4L2_BUF_FLAG_BOTFIELD 0x0080 /* Image is a bottom field only */ +#define V4L2_BUF_FLAG_ODDFIELD V4L2_BUF_FLAG_TOPFIELD +#define V4L2_BUF_FLAG_EVENFIELD V4L2_BUF_FLAG_BOTFIELD +#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ + +/* + * O V E R L A Y P R E V I E W + */ +struct v4l2_framebuffer +{ + __u32 capability; + __u32 flags; + void *base[3]; + struct v4l2_pix_format fmt; +}; +/* Flags for the 'capability' field. Read only */ +#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 +#define V4L2_FBUF_CAP_CHROMAKEY 0x0002 +#define V4L2_FBUF_CAP_CLIPPING 0x0004 +#define V4L2_FBUF_CAP_SCALEUP 0x0008 +#define V4L2_FBUF_CAP_SCALEDOWN 0x0010 +#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0020 +/* Flags for the 'flags' field. */ +#define V4L2_FBUF_FLAG_PRIMARY 0x0001 +#define V4L2_FBUF_FLAG_OVERLAY 0x0002 +#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 + +struct v4l2_clip +{ + int x; + int y; + int width; + int height; + struct v4l2_clip *next; +}; +struct v4l2_window +{ + int x; + int y; + int width; + int height; + __u32 chromakey; + struct v4l2_clip *clips; + int clipcount; + void *bitmap; +}; + + +/* + * D E V I C E P E R F O R M A N C E + */ +struct v4l2_performance +{ + int frames; + int framesdropped; + __u64 bytesin; + __u64 bytesout; + __u32 reserved[4]; +}; + +/* + * C A P T U R E P A R A M E T E R S + */ +struct v4l2_captureparm +{ + __u32 capability; /* Supported modes */ + __u32 capturemode; /* Current mode */ + unsigned long timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 reserved[4]; +}; +/* Flags for 'capability' and 'capturemode' fields */ +#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */ +//#define V4L2_MODE_VFLIP 0x0002 /* Flip image vertically */ +//#define V4L2_MODE_HFLIP 0x0004 /* Flip image horizontally */ +#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ + +struct v4l2_outputparm +{ + __u32 capability; /* Supported modes */ + __u32 outputmode; /* Current mode */ + unsigned long timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 reserved[4]; +}; + +/* + * I N P U T I M A G E C R O P P I N G + */ +struct v4l2_cropcap +{ + __u32 capability; + int min_x; + int min_y; + int max_x; + int max_y; + int default_left; + int default_top; + int default_right; + int default_bottom; + __u32 reserved[2]; +}; +struct v4l2_crop +{ + int left; + int top; + int right; + int bottom; + __u32 reserved; +}; + +/* + * D I G I T A L Z O O M + */ +struct v4l2_zoomcap +{ + __u32 capability; + __u32 maxwidth; + __u32 maxheight; + __u32 minwidth; + __u32 minheight; + __u32 reserved[2]; +}; +/* Flags for the capability field */ +#define V4L2_ZOOM_NONCAP 0x0001 +#define V4L2_ZOOM_WHILESTREAMING 0x0002 + +struct v4l2_zoom +{ + __u32 x; + __u32 y; + __u32 width; + __u32 height; + __u32 reserved; +}; + + +/* + * A N A L O G V I D E O S T A N D A R D + */ +struct v4l2_standard +{ + __u8 name[24]; + struct { + __u32 numerator; + __u32 denominator; /* >= 1 */ + } framerate; /* Frames, not fields */ + __u32 framelines; + __u32 reserved1; + __u32 colorstandard; + union { + struct { + __u32 colorsubcarrier; /* Hz */ + } pal; + struct { + __u32 colorsubcarrier; /* Hz */ + } ntsc; + struct { + __u32 f0b; /* Hz (blue) */ + __u32 f0r; /* Hz (red) */ + } secam; + __u8 reserved[12]; + } colorstandard_data; + __u32 transmission; /* Bit field. Must be zero for + non-modulators/demodulators. */ + __u32 reserved2; /* Must be set to zero */ +}; + +/* Values for the 'colorstandard' field */ +#define V4L2_COLOR_STD_PAL 1 +#define V4L2_COLOR_STD_NTSC 2 +#define V4L2_COLOR_STD_SECAM 3 + +/* Values for the color subcarrier fields */ +#define V4L2_COLOR_SUBC_PAL 4433619 /* PAL BGHI, NTSC-44 */ +#define V4L2_COLOR_SUBC_PAL_M 3575611 /* PAL M (Brazil) */ +#define V4L2_COLOR_SUBC_PAL_N 3582056 /* PAL N */ +#define V4L2_COLOR_SUBC_NTSC 3579545 /* NTSC M, NTSC-Japan */ +#define V4L2_COLOR_SUBC_SECAMB 4250000 /* SECAM B - Y carrier */ +#define V4L2_COLOR_SUBC_SECAMR 4406250 /* SECAM R - Y carrier */ + +/* Flags for the 'transmission' field */ +#define V4L2_TRANSM_STD_B (1<<1) +#define V4L2_TRANSM_STD_D (1<<3) +#define V4L2_TRANSM_STD_G (1<<6) +#define V4L2_TRANSM_STD_H (1<<7) +#define V4L2_TRANSM_STD_I (1<<8) +#define V4L2_TRANSM_STD_K (1<<10) +#define V4L2_TRANSM_STD_K1 (1<<11) +#define V4L2_TRANSM_STD_L (1<<12) +#define V4L2_TRANSM_STD_M (1<<13) +#define V4L2_TRANSM_STD_N (1<<14) + + +/* Used in the VIDIOC_ENUMSTD ioctl for querying supported standards */ +struct v4l2_enumstd +{ + int index; + struct v4l2_standard std; + __u32 inputs; /* set of inputs that */ + /* support this standard */ + __u32 outputs; /* set of outputs that */ + /* support this standard */ + __u32 reserved[2]; +}; + + +/* + * V I D E O I N P U T S + */ +struct v4l2_input +{ + int index; /* Which input */ + char name[32]; /* Label */ + int type; /* Type of input */ + __u32 capability; /* Capability flags */ + int assoc_audio; /* Associated audio input */ + __u32 reserved[4]; +}; +/* Values for the 'type' field */ +#define V4L2_INPUT_TYPE_TUNER 1 +#define V4L2_INPUT_TYPE_CAMERA 2 + +/* Flags for the 'capability' field */ +#define V4L2_INPUT_CAP_AUDIO 0x0001 /* assoc_audio */ + + +/* + * V I D E O O U T P U T S + */ +struct v4l2_output +{ + int index; /* Which output */ + char name[32]; /* Label */ + int type; /* Type of output */ + __u32 capability; /* Capability flags */ + int assoc_audio; /* Associated audio */ + __u32 reserved[4]; +}; +/* Values for the 'type' field */ +#define V4L2_OUTPUT_TYPE_MODULATOR 1 +#define V4L2_OUTPUT_TYPE_ANALOG 2 +#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 + +/* Flags for the 'capability' field */ +#define V4L2_OUTPUT_CAP_AUDIO 0x0001 /* assoc_audio */ + + +/* + * C O N T R O L S + */ +struct v4l2_control +{ + __u32 id; + int value; +}; + +/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ +struct v4l2_queryctrl +{ + __u32 id; + __u8 name[32]; /* Whatever */ + int minimum; /* Note signedness */ + int maximum; + unsigned int step; + int default_value; + __u32 type; + __u32 flags; + __u32 category; /* Automatically filled in by V4L2 */ + __u8 group[32]; /* for pre-defined controls */ + __u32 reserved[2]; +}; + +/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ +struct v4l2_querymenu +{ + __u32 id; + int index; + __u8 name[32]; /* Whatever */ + int reserved; +}; + +/* Used in V4L2_BUF_TYPE_FXCONTROL buffers */ +struct v4l2_fxcontrol +{ + __u32 id; + __u32 value; +}; + +/* Control types */ +#define V4L2_CTRL_TYPE_INTEGER 0 +#define V4L2_CTRL_TYPE_BOOLEAN 1 +#define V4L2_CTRL_TYPE_MENU 2 +#define V4L2_CTRL_TYPE_BUTTON 3 + +/* Control flags */ +#define V4L2_CTRL_FLAG_DISABLED 0x0001 +#define V4L2_CTRL_FLAG_GRABBED 0x0002 + +/* Control categories */ +#define V4L2_CTRL_CAT_VIDEO 1 /* "Video" */ +#define V4L2_CTRL_CAT_AUDIO 2 /* "Audio" */ +#define V4L2_CTRL_CAT_EFFECT 3 /* "Effect" */ + +/* Control IDs defined by V4L2 */ +#define V4L2_CID_BASE 0x00980900 +/* IDs reserved for driver specific controls */ +#define V4L2_CID_PRIVATE_BASE 0x08000000 +/* IDs reserved for effect-specific controls on effects devices */ +#define V4L2_CID_EFFECT_BASE 0x0A00B000 + +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) +#define V4L2_CID_HUE (V4L2_CID_BASE+3) +#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) +#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6) +#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7) +#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) +#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) +#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) +#define V4l2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) +#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) +#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) +#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) +#define V4L2_CID_GAMMA (V4L2_CID_BASE+16) +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */ +#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) +#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) +#define V4L2_CID_GAIN (V4L2_CID_BASE+19) +#define V4L2_CID_HFLIP (V4L2_CID_BASE+20) +#define V4L2_CID_VFLIP (V4L2_CID_BASE+21) +#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER (V4l2_CID_BASE+23) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ +/* Remember to change fill_ctrl_category() in videodev.c */ + +/* + * T U N I N G + */ +struct v4l2_tuner +{ + int input; + char name[32]; + struct v4l2_standard std; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 rxsubchans; + __u32 audmode; + int signal; + int afc; + __u32 reserved[4]; +}; +struct v4l2_modulator +{ + int output; + char name[32]; + struct v4l2_standard std; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 txsubchans; + __u32 reserved[4]; +}; +/* Flags for the 'capability' field */ +#define V4L2_TUNER_CAP_LOW 0x0001 +#define V4L2_TUNER_CAP_NORM 0x0002 +#define V4L2_TUNER_CAP_STEREO 0x0010 +#define V4L2_TUNER_CAP_LANG2 0x0020 +#define V4L2_TUNER_CAP_SAP 0x0020 +#define V4L2_TUNER_CAP_LANG1 0x0040 + +/* Flags for the 'rxsubchans' field */ +#define V4L2_TUNER_SUB_MONO 0x0001 +#define V4L2_TUNER_SUB_STEREO 0x0002 +#define V4L2_TUNER_SUB_LANG2 0x0004 +#define V4L2_TUNER_SUB_SAP 0x0004 +#define V4L2_TUNER_SUB_LANG1 0x0008 + +/* Values for the 'audmode' field */ +#define V4L2_TUNER_MODE_MONO 0x0000 +#define V4L2_TUNER_MODE_STEREO 0x0001 +#define V4L2_TUNER_MODE_LANG2 0x0002 +#define V4L2_TUNER_MODE_SAP 0x0002 +#define V4L2_TUNER_MODE_LANG1 0x0003 + +struct v4l2_frequency +{ + int port; + __u32 frequency; + __u32 reserved[2]; +}; + +/* + * A U D I O + */ +struct v4l2_audio +{ + int audio; + char name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; +/* Flags for the 'capability' field */ +#define V4L2_AUDCAP_EFFECTS 0x0020 +#define V4L2_AUDCAP_LOUDNESS 0x0040 +#define V4L2_AUDCAP_AVL 0x0080 + +/* Flags for the 'mode' field */ +#define V4L2_AUDMODE_LOUDNESS 0x00002 +#define V4L2_AUDMODE_AVL 0x00004 +#define V4L2_AUDMODE_STEREO_field 0x0FF00 +#define V4L2_AUDMODE_STEREO_LINEAR 0x00100 +#define V4L2_AUDMODE_STEREO_PSEUDO 0x00200 +#define V4L2_AUDMODE_STEREO_SPATIAL30 0x00300 +#define V4L2_AUDMODE_STEREO_SPATIAL50 0x00400 + +struct v4l2_audioout +{ + int audio; + char name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* + * D A T A S E R V I C E S ( V B I ) + */ + +struct v4l2_vbi_format +{ + __u32 sampling_rate; /* in 1 Hz */ + __u32 reserved1; /* must be zero */ + __u32 samples_per_line; + __u32 sample_format; /* V4L2_VBI_SF_* */ + __s32 start[2]; + __u32 count[2]; + __u32 flags; /* V4L2_VBI_* */ + __u32 reserved2; /* must be zero */ +}; + +/* VBI sampling formats */ +#define V4L2_VBI_SF_UBYTE 1 + +/* VBI flags */ +#define V4L2_VBI_UNSYNC (1<< 0) +#define V4L2_VBI_INTERLACED (1<< 1) + + +/* + * A G G R E G A T E S T R U C T U R E S + */ + +/* Stream data format + */ +struct v4l2_format +{ + __u32 type; + union + { + struct v4l2_pix_format pix; /* image format */ + struct v4l2_vbi_format vbi; /* VBI data */ + /* add more */ + __u8 raw_data[200]; /* user-defined */ + } fmt; +}; + + +/* Stream type-dependent parameters + */ +struct v4l2_streamparm +{ + __u32 type; + union + { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + /* add more */ + __u8 raw_data[200]; /* user-defined */ + } parm; +}; + + + +/* + * I O C T L C O D E S F O R V I D E O D E V I C E S + * + */ +#define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability) +#define VIDIOC_RESERVED _IO ('V', 1) +#define VIDIOC_ENUM_PIXFMT _IOWR ('V', 2, struct v4l2_fmtdesc) +#define VIDIOC_ENUM_FBUFFMT _IOWR ('V', 3, struct v4l2_fmtdesc) +#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format) +#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format) +#define VIDIOC_G_COMP _IOR ('V', 6, struct v4l2_compression) +#define VIDIOC_S_COMP _IOW ('V', 7, struct v4l2_compression) +#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers) +#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer) +#define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer) +#define VIDIOC_S_FBUF _IOW ('V', 11, struct v4l2_framebuffer) +#define VIDIOC_G_WIN _IOR ('V', 12, struct v4l2_window) +#define VIDIOC_S_WIN _IOW ('V', 13, struct v4l2_window) +#define VIDIOC_PREVIEW _IOWR ('V', 14, int) +#define VIDIOC_QBUF _IOWR ('V', 15, struct v4l2_buffer) +#define VIDIOC_DQBUF _IOWR ('V', 17, struct v4l2_buffer) +#define VIDIOC_STREAMON _IOW ('V', 18, int) +#define VIDIOC_STREAMOFF _IOW ('V', 19, int) +#define VIDIOC_G_PERF _IOR ('V', 20, struct v4l2_performance) +#define VIDIOC_G_PARM _IOWR ('V', 21, struct v4l2_streamparm) +#define VIDIOC_S_PARM _IOW ('V', 22, struct v4l2_streamparm) +#define VIDIOC_G_STD _IOR ('V', 23, struct v4l2_standard) +#define VIDIOC_S_STD _IOW ('V', 24, struct v4l2_standard) +#define VIDIOC_ENUMSTD _IOWR ('V', 25, struct v4l2_enumstd) +#define VIDIOC_ENUMINPUT _IOWR ('V', 26, struct v4l2_input) +#define VIDIOC_G_CTRL _IOWR ('V', 27, struct v4l2_control) +#define VIDIOC_S_CTRL _IOW ('V', 28, struct v4l2_control) +#define VIDIOC_G_TUNER _IOWR ('V', 29, struct v4l2_tuner) +#define VIDIOC_S_TUNER _IOW ('V', 30, struct v4l2_tuner) +#define VIDIOC_G_FREQ _IOR ('V', 31, int) +#define VIDIOC_S_FREQ _IOWR ('V', 32, int) +#define VIDIOC_G_AUDIO _IOWR ('V', 33, struct v4l2_audio) +#define VIDIOC_S_AUDIO _IOW ('V', 34, struct v4l2_audio) +#define VIDIOC_QUERYCTRL _IOWR ('V', 36, struct v4l2_queryctrl) +#define VIDIOC_QUERYMENU _IOWR ('V', 37, struct v4l2_querymenu) +#define VIDIOC_G_INPUT _IOR ('V', 38, int) +#define VIDIOC_S_INPUT _IOWR ('V', 39, int) +#define VIDIOC_ENUMCVT _IOWR ('V', 40, struct v4l2_cvtdesc) +#define VIDIOC_G_OUTPUT _IOR ('V', 46, int) +#define VIDIOC_S_OUTPUT _IOWR ('V', 47, int) +#define VIDIOC_ENUMOUTPUT _IOWR ('V', 48, struct v4l2_output) +#define VIDIOC_G_AUDOUT _IOWR ('V', 49, struct v4l2_audioout) +#define VIDIOC_S_AUDOUT _IOW ('V', 50, struct v4l2_audioout) +#define VIDIOC_ENUMFX _IOWR ('V', 51, struct v4l2_fxdesc) +#define VIDIOC_G_EFFECT _IOR ('V', 52, int) +#define VIDIOC_S_EFFECT _IOWR ('V', 53, int) +#define VIDIOC_G_MODULATOR _IOWR ('V', 54, struct v4l2_modulator) +#define VIDIOC_S_MODULATOR _IOW ('V', 55, struct v4l2_modulator) + +#define VIDIOC_ENUM_CAPFMT VIDIOC_ENUM_PIXFMT +#define VIDIOC_ENUM_OUTFMT VIDIOC_ENUM_PIXFMT +#define VIDIOC_ENUM_SRCFMT VIDIOC_ENUM_PIXFMT +#define VIDIOC_ENUMFMT VIDIOC_ENUM_PIXFMT + +#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ + + +#ifdef __KERNEL__ +/* + * These things are used only by drivers. + */ + +extern int videodev_init(void); + +/* + * + * V 4 L 2 D R I V E R H E L P E R A P I + * + * Some commonly needed functions for drivers. + */ + +extern void v4l2_version(int *major, int *minor); +extern int v4l2_major_number(void); + +/* Memory management */ +extern unsigned long v4l2_vmalloc_to_bus(void *virt); +extern unsigned long v4l2_vmalloc_to_page(void *virt); + +/* Simple queue management */ +struct v4l2_q_node +{ + struct v4l2_q_node *forw, *back; +}; +struct v4l2_queue +{ + struct v4l2_q_node *forw, *back; + rwlock_t qlock; +}; +extern void v4l2_q_init(struct v4l2_queue *q); +extern void v4l2_q_add_head(struct v4l2_queue *q, struct v4l2_q_node *node); +extern void v4l2_q_add_tail(struct v4l2_queue *q, struct v4l2_q_node *node); +extern void *v4l2_q_del_head(struct v4l2_queue *q); +extern void *v4l2_q_del_tail(struct v4l2_queue *q); +extern void *v4l2_q_peek_head(struct v4l2_queue *q); +extern void *v4l2_q_peek_tail(struct v4l2_queue *q); +extern void *v4l2_q_yank_node(struct v4l2_queue *q, struct v4l2_q_node *node); + +/* Math functions */ +extern u32 v4l2_math_div6432(u64 a, u32 d, u32 *r); + +/* Time functions */ +extern unsigned long v4l2_timestamp_divide(stamp_t t, + unsigned long p_100ns); +extern unsigned long v4l2_timestamp_correct(stamp_t *t, + unsigned long p_100ns); + +/* Master Clock functions */ +struct v4l2_clock +{ + void (*gettime)(stamp_t *); +}; +extern int v4l2_masterclock_register(struct v4l2_clock *clock); +extern void v4l2_masterclock_unregister(struct v4l2_clock *clock); +extern void v4l2_masterclock_gettime(stamp_t *curr); + +/* Video standard functions */ +extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs); +extern unsigned long v4l2_video_std_tpf(struct v4l2_standard *vs); +extern int v4l2_video_std_confirm(struct v4l2_standard *vs); +extern int v4l2_video_std_construct(struct v4l2_standard *vs, + int id, __u32 transmission); + +#define V4L2_STD_PAL 1 /* PAL B, G, H, I (...) */ +#define V4L2_STD_PAL_M 5 /* (Brazil) */ +#define V4L2_STD_PAL_N 6 /* (Argentina, Paraguay, Uruguay) */ +#define V4L2_STD_PAL_60 10 /* PAL/NTSC hybrid */ +#define V4L2_STD_NTSC 11 /* NTSC M (USA, ...) */ +#define V4L2_STD_NTSC_N 12 /* (Barbados, Bolivia, Colombia, + S. Korea) */ +#define V4L2_STD_NTSC_44 15 /* PAL/NTSC hybrid */ +#define V4L2_STD_SECAM 21 /* SECAM B, D, G, K, K1 (...) */ +//#define V4L2_STD_SECAM_H 27 /* (Greece, Iran, Morocco) */ +//#define V4L2_STD_SECAM_L 28 /* (France, Luxembourg, Monaco) */ +//#define V4L2_STD_SECAM_M 29 /* (Jamaica) */ + +/* + * D E V I C E D R I V E R R E G I S T R A T I O N + * + */ +struct v4l2_device +{ + char name[32]; + int type; + int minor; + + int (*open)(struct v4l2_device *v, + int flags, void **idptr); + void (*close)(void *id); + long (*read)(void *id, + char *buf, unsigned long count, int noblock); + long (*write)(void *id, + const char *buf, unsigned long count, int noblock); + int (*ioctl)(void *id, + unsigned int cmd, void *arg); + int (*mmap)(void *id, + struct vm_area_struct *vma); + int (*poll)(void *id, + struct file *file, poll_table *table); + + int (*initialize)(struct v4l2_device *v); + void *priv; /* may be used by the driver */ + + int busy; /* open count maintained by videodev.c */ + void *v4l2_priv; /* for V4L2 use */ + int v4l2_reserved[4]; /* for V4L2 use */ +}; + +/* Size of kernel ioctl arg buffer used in ioctl handler */ +#define V4L2_MAX_IOCTL_SIZE 256 + +extern int v4l2_register_device(struct v4l2_device *); +extern void v4l2_unregister_device(struct v4l2_device *); + +/* V4L2 structures */ +extern struct v4l2_device *v4l2_device_from_file(struct file *file); +extern void *v4l2_openid_from_file(struct file *file); + +#endif/*ifdef __KERNEL__ */ + + +/*---------------------------------------------------------------------- + Old Video for Linux backward compatibility below this line. + ---------------------------------------------------------------------- + + All new applications should use the new API calls. + + (These definitions taken from 2.2.1.) + + */ + + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ + +struct video_capability +{ + char name[32]; + int type; + int channels; /* Num channels */ + int audios; /* Num audio devices */ + int maxwidth; /* Supported width */ + int maxheight; /* And height */ + int minwidth; /* Supported width */ + int minheight; /* And height */ +}; + + +struct video_channel +{ + int channel; + char name[32]; + int tuners; + __u32 flags; +#define VIDEO_VC_TUNER 1 /* Channel has a tuner */ +#define VIDEO_VC_AUDIO 2 /* Channel has audio */ + __u16 type; +#define VIDEO_TYPE_TV 1 +#define VIDEO_TYPE_CAMERA 2 + __u16 norm; /* Norm set by channel */ +}; + +struct video_tuner +{ + int tuner; + char name[32]; + ulong rangelow, rangehigh; /* Tuner range */ + __u32 flags; +#define VIDEO_TUNER_PAL 1 +#define VIDEO_TUNER_NTSC 2 +#define VIDEO_TUNER_SECAM 4 +#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */ +#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */ +#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */ +#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */ +#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */ + __u16 mode; /* PAL/NTSC/SECAM/OTHER */ +#define VIDEO_MODE_PAL 0 +#define VIDEO_MODE_NTSC 1 +#define VIDEO_MODE_SECAM 2 +#define VIDEO_MODE_AUTO 3 + __u16 signal; /* Signal strength 16bit scale */ +}; + +struct video_picture +{ + __u16 brightness; + __u16 hue; + __u16 colour; + __u16 contrast; + __u16 whiteness; /* Black and white only */ + __u16 depth; /* Capture depth */ + __u16 palette; /* Palette in use */ +#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ +#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ +#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ +#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ +#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ +#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ +#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ +#define VIDEO_PALETTE_YUYV 8 +#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ +#define VIDEO_PALETTE_YUV420 10 +#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ +#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ +#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ +#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ +#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ +#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ +#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ +#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ +}; + +struct video_audio +{ + int audio; /* Audio channel */ + __u16 volume; /* If settable */ + __u16 bass, treble; + __u32 flags; +#define VIDEO_AUDIO_MUTE 1 +#define VIDEO_AUDIO_MUTABLE 2 +#define VIDEO_AUDIO_VOLUME 4 +#define VIDEO_AUDIO_BASS 8 +#define VIDEO_AUDIO_TREBLE 16 +#define VIDEO_AUDIO_BALANCE 32 + char name[16]; +#define VIDEO_SOUND_MONO 1 +#define VIDEO_SOUND_STEREO 2 +#define VIDEO_SOUND_LANG1 4 +#define VIDEO_SOUND_LANG2 8 + __u16 mode; + __u16 balance; /* Stereo balance */ + __u16 step; /* Step actual volume uses */ +}; + +struct video_clip +{ + __s32 x,y; + __s32 width, height; + struct video_clip *next; /* For user use/driver use only */ +}; + +struct video_window +{ + __u32 x,y; /* Position of window */ + __u32 width,height; /* Its size */ + __u32 chromakey; + __u32 flags; + struct video_clip *clips; /* Set only */ + int clipcount; +#define VIDEO_WINDOW_INTERLACE 1 +#define VIDEO_CLIP_BITMAP -1 +/* bitmap is 1024x625, a '1' bit represents a clipped pixel */ +#define VIDEO_CLIPMAP_SIZE (128 * 625) +}; + +struct video_capture +{ + __u32 x,y; /* Offsets into image */ + __u32 width, height; /* Area to capture */ + __u16 decimation; /* Decimation divder */ + __u16 flags; /* Flags for capture */ +#define VIDEO_CAPTURE_ODD 0 /* Temporal */ +#define VIDEO_CAPTURE_EVEN 1 +}; + +struct video_buffer +{ + void *base; + int height,width; + int depth; + int bytesperline; +}; + +struct video_mmap +{ + unsigned int frame; /* Frame (0 - n) for double buffer */ + int height,width; + unsigned int format; /* should be VIDEO_PALETTE_* */ +}; + +struct video_key +{ + __u8 key[8]; + __u32 flags; +}; + + +#define VIDEO_MAX_FRAME 32 + +struct video_mbuf +{ + int size; /* Total memory to map */ + int frames; /* Frames */ + int offsets[VIDEO_MAX_FRAME]; +}; + + +#define VIDEO_NO_UNIT (-1) + + +struct video_unit +{ + int video; /* Video minor */ + int vbi; /* VBI minor */ + int radio; /* Radio minor */ + int audio; /* Audio minor */ + int teletext; /* Teletext minor */ +}; + +#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ +#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ +#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ +#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ +#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ +#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ +#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */ +#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */ +#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Set the video overlay window */ +#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ +#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */ +#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */ +#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ +#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */ +#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */ +#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */ +#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */ +#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */ +#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */ +#define VIDIOCGMBUF _IOR('v', 20, struct video_mbuf) /* Memory map buffer info */ +#define VIDIOCGUNIT _IOR('v', 21, struct video_unit) /* Get attached units */ +#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get frame buffer */ +#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set frame buffer - root only */ +#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ + + + +#endif/*ifndef __LINUX_VIDEODEV_H*/ --- linux-2.6.27.orig/ubuntu/qc-usb/qc-mjpeg.c +++ linux-2.6.27/ubuntu/qc-usb/qc-mjpeg.c @@ -0,0 +1,1936 @@ +/* Start of file */ + +/* {{{ [fold] Comments */ +/* + * MJPEG decompression routines are from mpeg2dec, + * Copyright (C) 1999-2001 Aaron Holtzman + * Modified by Tuukka Toivonen and Jochen Hoenicke. + * + * Portions of this code are from the MPEG software simulation group + * idct implementation. This code will be replaced with a new + * implementation soon. + * + * The MJPEG routines are from mpeg2dec, a free MPEG-2 video stream decoder. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* }}} */ + +#include "quickcam.h" + +#ifdef __KERNEL__ /* show.c will include this file directly into compilation for userspace */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#include +#else +#include +#endif +#endif /* __KERNEL__ */ + +#if COMPRESS +/* {{{ [fold] **** qc_mjpeg_yuv2rgb: MJPEG decoding: YUV to RGB conversion routines *************** */ + +/* {{{ [fold] Macros */ +#define MODE_RGB 1 +#define MODE_BGR 2 + +#define RGB(i) \ + U = pu[i]; \ + V = pv[i]; \ + r = md->table_rV[V]; \ + g = (void *)(((u8 *)md->table_gU[U]) + md->table_gV[V]);\ + b = md->table_bU[U]; + +#define DST1(i) \ + Y = py_1[2*i]; \ + dst_1[2*i] = r[Y] + g[Y] + b[Y]; \ + Y = py_1[2*i+1]; \ + dst_1[2*i+1] = r[Y] + g[Y] + b[Y]; + +#define DST2(i) \ + Y = py_2[2*i]; \ + dst_2[2*i] = r[Y] + g[Y] + b[Y]; \ + Y = py_2[2*i+1]; \ + dst_2[2*i+1] = r[Y] + g[Y] + b[Y]; + +#define DST1RGB(i) \ + Y = py_1[2*i]; \ + dst_1[6*i] = r[Y]; dst_1[6*i+1] = g[Y]; dst_1[6*i+2] = b[Y]; \ + Y = py_1[2*i+1]; \ + dst_1[6*i+3] = r[Y]; dst_1[6*i+4] = g[Y]; dst_1[6*i+5] = b[Y]; + +#define DST2RGB(i) \ + Y = py_2[2*i]; \ + dst_2[6*i] = r[Y]; dst_2[6*i+1] = g[Y]; dst_2[6*i+2] = b[Y]; \ + Y = py_2[2*i+1]; \ + dst_2[6*i+3] = r[Y]; dst_2[6*i+4] = g[Y]; dst_2[6*i+5] = b[Y]; + +#define DST1BGR(i) \ + Y = py_1[2*i]; \ + dst_1[6*i] = b[Y]; dst_1[6*i+1] = g[Y]; dst_1[6*i+2] = r[Y]; \ + Y = py_1[2*i+1]; \ + dst_1[6*i+3] = b[Y]; dst_1[6*i+4] = g[Y]; dst_1[6*i+5] = r[Y]; + +#define DST2BGR(i) \ + Y = py_2[2*i]; \ + dst_2[6*i] = b[Y]; dst_2[6*i+1] = g[Y]; dst_2[6*i+2] = r[Y]; \ + Y = py_2[2*i+1]; \ + dst_2[6*i+3] = b[Y]; dst_2[6*i+4] = g[Y]; dst_2[6*i+5] = r[Y]; +/* }}} */ + +/* {{{ [fold] qc_mjpeg_yuv2rgb_32() */ +static void qc_mjpeg_yuv2rgb_32(struct qc_mjpeg_data *md, u8 *py_1, u8 *py_2, u8 *pu, u8 *pv, + void *_dst_1, void *_dst_2, int width) +{ + int U, V, Y; + u32 *r, *g, *b; + u32 *dst_1, *dst_2; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_32(md=%p, py_1=%p, py_2=%p, pu=%p, pv=%p, _dst_1=%p, _dst_2=%p, width=%i",md,py_1,py_2,pu,pv,_dst_1,_dst_2,width); + width >>= 3; + dst_1 = _dst_1; + dst_2 = _dst_2; + + do { + RGB(0); + DST1(0); + DST2(0); + + RGB(1); + DST2(1); + DST1(1); + + RGB(2); + DST1(2); + DST2(2); + + RGB(3); + DST2(3); + DST1(3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_32() done"); +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_yuv2rgb_24rgb() */ +/* This is very near from the yuv2rgb_32 code */ +static void qc_mjpeg_yuv2rgb_24rgb(struct qc_mjpeg_data *md, u8 *py_1, u8 *py_2, u8 *pu, u8 *pv, + void *_dst_1, void *_dst_2, int width) +{ + int U, V, Y; + u8 *r, *g, *b; + u8 *dst_1, *dst_2; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_24rgb(md=%p, py_1=%p, py_2=%p, pu=%p, pv=%p, _dst_1=%p, _dst_2=%p, width=%i",md,py_1,py_2,pu,pv,_dst_1,_dst_2,width); + + width >>= 3; + dst_1 = _dst_1; + dst_2 = _dst_2; + + do { + RGB(0); + DST1RGB(0); + DST2RGB(0); + + RGB(1); + DST2RGB(1); + DST1RGB(1); + + RGB(2); + DST1RGB(2); + DST2RGB(2); + + RGB(3); + DST2RGB(3); + DST1RGB(3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_24rgb() done"); +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_yuv2rgb_24bgr() */ +/* only trivial mods from yuv2rgb_24rgb */ +static void qc_mjpeg_yuv2rgb_24bgr(struct qc_mjpeg_data *md, u8 *py_1, u8 *py_2, u8 *pu, u8 *pv, + void *_dst_1, void *_dst_2, int width) +{ + int U, V, Y; + u8 *r, *g, *b; + u8 *dst_1, *dst_2; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_24bgr(md=%p, py_1=%p, py_2=%p, pu=%p, pv=%p, _dst_1=%p, _dst_2=%p, width=%i",md,py_1,py_2,pu,pv,_dst_1,_dst_2,width); + width >>= 3; + dst_1 = _dst_1; + dst_2 = _dst_2; + + do { + RGB(0); + DST1BGR(0); + DST2BGR(0); + + RGB(1); + DST2BGR(1); + DST1BGR(1); + + RGB(2); + DST1BGR(2); + DST2BGR(2); + + RGB(3); + DST2BGR(3); + DST1BGR(3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_24bgr() done"); +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_yuv2rgb_16() */ +/* This is exactly the same code as yuv2rgb_32 except for the types of */ +/* r, g, b, dst_1, dst_2 */ +static void qc_mjpeg_yuv2rgb_16(struct qc_mjpeg_data *md, u8 *py_1, u8 *py_2, u8 *pu, u8 *pv, + void *_dst_1, void *_dst_2, int width) +{ + int U, V, Y; + u16 *r, *g, *b; + u16 *dst_1, *dst_2; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_16(md=%p, py_1=%p, py_2=%p, pu=%p, pv=%p, _dst_1=%p, _dst_2=%p, width=%i",md,py_1,py_2,pu,pv,_dst_1,_dst_2,width); + width >>= 3; + dst_1 = _dst_1; + dst_2 = _dst_2; + + do { + RGB(0); + DST1(0); + DST2(0); + + RGB(1); + DST2(1); + DST1(1); + + RGB(2); + DST1(2); + DST2(2); + + RGB(3); + DST2(3); + DST1(3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_16() done"); +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_yuv2rgb() */ +/* Convert YUV image to RGB */ +static void qc_mjpeg_yuv2rgb(struct qc_mjpeg_data *md, void *dst, u8 *py, u8 *pu, u8 *pv, + int width, int height, int rgb_stride, int y_stride, int uv_stride) +{ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb(md=%p, dst=%p, py=%p, pu=%p, pv=%p, width=%i, height=%i, rgb_stride=%i, y_stride=%i, uv_stride=%i",md,dst,py,pu,pv,width,height,rgb_stride,y_stride,uv_stride); + height >>= 1; + do { + md->yuv2rgb_func(md, py, py + y_stride, pu, pv, dst, ((u8 *)dst) + rgb_stride, width); + py += 2 * y_stride; + pu += uv_stride; + pv += uv_stride; + dst = ((u8 *)dst) + 2 * rgb_stride; + } while (--height); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb() done"); +} +/* }}} */ + +static const u32 matrix_coefficients = 6; +static const s32 Inverse_Table_6_9[8][4] = { + { 117504, 138453, 13954, 34903 }, /* 0: no sequence_display_extension */ + { 117504, 138453, 13954, 34903 }, /* 1: ITU-R Rec. 709 (1990) */ + { 104597, 132201, 25675, 53279 }, /* 2: unspecified */ + { 104597, 132201, 25675, 53279 }, /* 3: reserved */ + { 104448, 132798, 24759, 53109 }, /* 4: FCC */ + { 104597, 132201, 25675, 53279 }, /* 5: ITU-R Rec. 624-4 System B, G */ + { 104597, 132201, 25675, 53279 }, /* 6: SMPTE 170M */ + { 117579, 136230, 16907, 35559 } /* 7: SMPTE 240M (1987) */ +}; + +/* {{{ [fold] div_round(int dividend, int divisor) */ +static int div_round(int dividend, int divisor) +{ + if (dividend > 0) + return (dividend + (divisor>>1)) / divisor; + else + return -((-dividend + (divisor>>1)) / divisor); +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_yuv2rgb_init(struct qc_mjpeg_data *md, int bpp, int mode) */ +/* Initialization of yuv2rgb routines. Return error code if failure */ +static inline int qc_mjpeg_yuv2rgb_init(struct qc_mjpeg_data *md, int bpp, int mode) +{ + static const int table_Y_size = 1024; + u8 *table_Y; + int i, ret = -ENOMEM; + int entry_size = 0; + void *table_r = NULL, *table_g = NULL, *table_b = NULL; + int crv = Inverse_Table_6_9[matrix_coefficients][0]; + int cbu = Inverse_Table_6_9[matrix_coefficients][1]; + int cgu = -Inverse_Table_6_9[matrix_coefficients][2]; + int cgv = -Inverse_Table_6_9[matrix_coefficients][3]; + u32 *table_32; + u16 *table_16; + u8 *table_8; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_init(md=%p, bpp=%i, mode=%i)",md,bpp,mode); + table_Y = kmalloc(table_Y_size,GFP_KERNEL); /* Allocate with kmalloc(), it might not fit into stack */ + if (table_Y==NULL) return -ENOMEM; + + for (i=0; i<1024; i++) { + int j; + j = (76309 * (i - 384 - 16) + 32768) >> 16; + j = (j < 0) ? 0 : ((j > 255) ? 255 : j); + table_Y[i] = j; + } + + switch (bpp) { + case 32: + md->yuv2rgb_func = qc_mjpeg_yuv2rgb_32; + table_32 = md->table = kmalloc((197 + 2*682 + 256 + 132) * sizeof(u32), GFP_KERNEL); /* 0..1948 x 4 */ + if (!md->table) goto fail; + entry_size = sizeof(u32); + table_r = table_32 + 197; /* R: -197..1751 */ + table_b = table_32 + 197 + 685; /* B: -882..1066 */ + table_g = table_32 + 197 + 2*682; /* G: -1561..387 */ + for (i=-197; i<256+197; i++) /* Ri = -197...452 */ + ((u32 *) table_r)[i] = table_Y[i+384] << ((mode==MODE_RGB) ? 16 : 0); + for (i=-132; i<256+132; i++) /* Gi = -132...387 */ + ((u32 *) table_g)[i] = table_Y[i+384] << 8; + for (i=-232; i<256+232; i++) /* Bi = -232...487 */ + ((u32 *) table_b)[i] = table_Y[i+384] << ((mode==MODE_RGB) ? 0 : 16); + break; + case 24: + md->yuv2rgb_func = (mode==MODE_RGB) ? qc_mjpeg_yuv2rgb_24rgb : qc_mjpeg_yuv2rgb_24bgr; + table_8 = md->table = kmalloc((256 + 2*232) * sizeof(u8), GFP_KERNEL); /* 0..719 x 1 */ + if (!md->table) goto fail; + entry_size = sizeof(u8); + table_r = table_g = table_b = table_8 + 232; /* -232..487 */ + for (i=-232; i<256+232; i++) /* i = -232..487 */ + ((u8 *)table_b)[i] = table_Y[i+384]; + break; + case 15: + case 16: + md->yuv2rgb_func = qc_mjpeg_yuv2rgb_16; + table_16 = md->table = kmalloc((197 + 2*682 + 256 + 132) * sizeof(u16), GFP_KERNEL); /* 0..1948 x 2 */ + if (!md->table) goto fail; + entry_size = sizeof(u16); + table_r = table_16 + 197; /* R: -197..1751 */ + table_b = table_16 + 197 + 685; /* B: -882..1066 */ + table_g = table_16 + 197 + 2*682; /* G: -1561..387 */ + for (i=-197; i<256+197; i++) { /* Ri = -197..452 */ + int j = table_Y[i+384] >> 3; + if (mode == MODE_RGB) j <<= ((bpp==16) ? 11 : 10); + ((u16 *)table_r)[i] = j; + } + for (i=-132; i<256+132; i++) { /* Gi = -132..387 */ + int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3); + ((u16 *)table_g)[i] = j << 5; + } + for (i=-232; i<256+232; i++) { /* Bi = -232..487 */ + int j = table_Y[i+384] >> 3; + if (mode == MODE_BGR) j <<= ((bpp==16) ? 11 : 10); + ((u16 *)table_b)[i] = j; + } + break; + default: + PDEBUG("%i bpp not supported by yuv2rgb", bpp); + ret = -EINVAL; + goto fail; + } + for (i=0; i<256; i++) { + md->table_rV[i] = (((u8 *)table_r) + entry_size * div_round(crv * (i-128), 76309)); + md->table_gU[i] = (((u8 *)table_g) + entry_size * div_round(cgu * (i-128), 76309)); + md->table_gV[i] = entry_size * div_round(cgv * (i-128), 76309); + md->table_bU[i] = (((u8 *)table_b) + entry_size * div_round(cbu * (i-128), 76309)); + } + ret = 0; +fail: if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_init()=%i done", ret); + if (PARANOID) memset(table_Y, POISON_VAL, table_Y_size); + kfree(table_Y); + return ret; +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_yuv2rgb_exit(struct qc_mjpeg_data *md) */ +static inline void qc_mjpeg_yuv2rgb_exit(struct qc_mjpeg_data *md) +{ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_exit(md=%p)",md); + kfree(md->table); + POISON(md->table); + POISON(md->yuv2rgb_func); + POISON(md->table_rV); + POISON(md->table_gU); + POISON(md->table_bU); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_yuv2rgb_exit() done"); +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_mjpeg_idct: MJPEG decoding: Inverse DCT routines ************************* */ +/**********************************************************/ +/* inverse two dimensional DCT, Chen-Wang algorithm */ +/* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) */ +/* 32-bit integer arithmetic (8 bit coefficients) */ +/* 11 mults, 29 adds per DCT */ +/* sE, 18.8.91 */ +/**********************************************************/ +/* coefficients extended to 12 bit for IEEE1180-1990 */ +/* compliance sE, 2.1.94 */ +/**********************************************************/ + +/* this code assumes >> to be a two's-complement arithmetic */ +/* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */ + +#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */ +#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */ +#define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */ +#define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */ +#define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */ +#define W7 565 /* 2048*sqrt (2)*cos (7*pi/16) */ + +/* {{{ [fold] qc_mjpeg_idct_row(s16 *block) */ +/* row (horizontal) IDCT + * + * 7 pi 1 + * dst[k] = sum c[l] * src[l] * cos ( -- * ( k + - ) * l ) + * l=0 8 2 + * + * where: c[0] = 128 + * c[1..7] = 128*sqrt (2) + */ +static void inline qc_mjpeg_idct_row(s16 *block) +{ + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + x1 = block[4] << 11; + x2 = block[6]; + x3 = block[2]; + x4 = block[1]; + x5 = block[7]; + x6 = block[5]; + x7 = block[3]; + + /* shortcut */ + if (! (x1 | x2 | x3 | x4 | x5 | x6 | x7)) { + block[0] = block[1] = block[2] = block[3] = block[4] = + block[5] = block[6] = block[7] = block[0]<<3; + return; + } + + x0 = (block[0] << 11) + 128; /* for proper rounding in the fourth stage */ + + /* first stage */ + x8 = W7 * (x4 + x5); + x4 = x8 + (W1 - W7) * x4; + x5 = x8 - (W1 + W7) * x5; + x8 = W3 * (x6 + x7); + x6 = x8 - (W3 - W5) * x6; + x7 = x8 - (W3 + W5) * x7; + + /* second stage */ + x8 = x0 + x1; + x0 -= x1; + x1 = W6 * (x3 + x2); + x2 = x1 - (W2 + W6) * x2; + x3 = x1 + (W2 - W6) * x3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + /* third stage */ + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181 * (x4 + x5) + 128) >> 8; + x4 = (181 * (x4 - x5) + 128) >> 8; + + /* fourth stage */ + block[0] = (x7 + x1) >> 8; + block[1] = (x3 + x2) >> 8; + block[2] = (x0 + x4) >> 8; + block[3] = (x8 + x6) >> 8; + block[4] = (x8 - x6) >> 8; + block[5] = (x0 - x4) >> 8; + block[6] = (x3 - x2) >> 8; + block[7] = (x7 - x1) >> 8; +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_idct_col(s16 *block) */ +/* column (vertical) IDCT + * + * 7 pi 1 + * dst[8*k] = sum c[l] * src[8*l] * cos ( -- * ( k + - ) * l ) + * l=0 8 2 + * + * where: c[0] = 1/1024 + * c[1..7] = (1/1024)*sqrt (2) + */ +static void inline qc_mjpeg_idct_col(s16 *block) +{ + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + /* shortcut */ + x1 = block [8*4] << 8; + x2 = block [8*6]; + x3 = block [8*2]; + x4 = block [8*1]; + x5 = block [8*7]; + x6 = block [8*5]; + x7 = block [8*3]; +#if 0 + if (! (x1 | x2 | x3 | x4 | x5 | x6 | x7 )) { + block[8*0] = block[8*1] = block[8*2] = block[8*3] = block[8*4] = + block[8*5] = block[8*6] = block[8*7] = (block[8*0] + 32) >> 6; + return; + } +#endif + x0 = (block[8*0] << 8) + 8192; + + /* first stage */ + x8 = W7 * (x4 + x5) + 4; + x4 = (x8 + (W1 - W7) * x4) >> 3; + x5 = (x8 - (W1 + W7) * x5) >> 3; + x8 = W3 * (x6 + x7) + 4; + x6 = (x8 - (W3 - W5) * x6) >> 3; + x7 = (x8 - (W3 + W5) * x7) >> 3; + + /* second stage */ + x8 = x0 + x1; + x0 -= x1; + x1 = W6 * (x3 + x2) + 4; + x2 = (x1 - (W2 + W6) * x2) >> 3; + x3 = (x1 + (W2 - W6) * x3) >> 3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + /* third stage */ + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181 * (x4 + x5) + 128) >> 8; + x4 = (181 * (x4 - x5) + 128) >> 8; + + /* fourth stage */ + block[8*0] = (x7 + x1) >> 14; + block[8*1] = (x3 + x2) >> 14; + block[8*2] = (x0 + x4) >> 14; + block[8*3] = (x8 + x6) >> 14; + block[8*4] = (x8 - x6) >> 14; + block[8*5] = (x0 - x4) >> 14; + block[8*6] = (x3 - x2) >> 14; + block[8*7] = (x7 - x1) >> 14; +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_idct(s16 *block, u8 *dest, int stride) */ +/* Inverse discrete cosine transform block, store result to dest */ +static void qc_mjpeg_idct(s16 *block, u8 *dest, int stride) +{ + int i; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_idct(block=%p,dest=%p,stride=%i)",block,dest,stride); + for (i=0; i<8; i++) qc_mjpeg_idct_row(block + 8*i); + for (i=0; i<8; i++) qc_mjpeg_idct_col(block + i); + i = 8; + do { + /* The original code used lookup-tables instead of explicit + * comparisons (as CLIP is doing here). However, sometimes + * the values pointed outside the LUT which caused problems + * in the kernel driver. Thus, the LUTs are removed here. */ + dest[0] = CLIP(block[0],0,255); + dest[1] = CLIP(block[1],0,255); + dest[2] = CLIP(block[2],0,255); + dest[3] = CLIP(block[3],0,255); + dest[4] = CLIP(block[4],0,255); + dest[5] = CLIP(block[5],0,255); + dest[6] = CLIP(block[6],0,255); + dest[7] = CLIP(block[7],0,255); + dest += stride; + block += 8; + } while (--i); +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** MJPEG decoding: bitstream processing (structures and macros) * */ +/* the idea is taken from zlib, but the bits are ordered the other way, so + * I modified the code. + * Variables: + * p points to next unread byte in stream. + * k number of bits read but not processed. + * b contains the read but not processed bits in the k most significant bits. + */ +struct bitstream { + u32 b; + u8 *p; + u8 *end; + int k; +}; + +#define GETWORD(p) ((p)[0] << 8 | (p)[1]) +#define NEEDBITS(b,k,p) \ + do { \ + if ((k) > 0) { \ + (b) |= GETWORD(p) << (k); \ + (p) += 2; \ + (k) -= 16; \ + } \ + } while(0) +#define DUMPBITS(b,k,j) do { (k) += (j); (b) <<= (j); } while (0) +#define BITVALUE(b,j) ((b)>>(32-(j))) +/* }}} */ +/* {{{ [fold] **** qc_mjpeg_lvc: MJPEG decoding: variable length code decoding **************** */ + +/* {{{ [fold] u8 shiftTables[18][64] */ +static const u8 shiftTables[18][64] = { + {2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, + {2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 }, + {2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 }, + {2,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 }, + {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 }, + {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 }, + {2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 }, + {2,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 }, + {2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 }, + {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 }, + {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 }, + {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 }, + {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 }, + {2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 }, + {2,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 }, + {2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 }, + {2,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 }, + {2,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }, +}; +/* }}} */ +/* {{{ [fold] u8 shiftTblIndex[] */ +static const u8 shiftTblIndex[] = { + 8, 17, 8, 16, 7, 16, 7, 15, + 6, 15, 6, 14, 5, 14, 5, 13, + 4, 13, 4, 12, 3, 12, 3, 11, + 2, 11, 2, 10, 1, 9, 0, 9 +}; +/* }}} */ +/* {{{ [fold] s16 scaleTable[64] */ +static const s16 scaleTable[64] = { + 8192, 16704, 16704, 17733, 17032, 17733, 18204, 18081, + 18081, 18204, 18724, 18561, 19195, 18561, 18724, 19265, + 19091, 19704, 19704, 19091, 19265, 21406, 19642, 20267, + 20228, 20267, 19642, 21406, 22725, 21826, 20852, 20805, + 20805, 20852, 21826, 22725, 23170, 23170, 21406, 21399, + 21406, 23170, 23170, 24597, 23785, 22017, 22017, 23785, + 24597, 25250, 24464, 22653, 24464, 25250, 25971, 25171, + 25171, 25971, 26722, 27969, 26722, 29691, 29691, 31520 +}; +/* }}} */ +/* {{{ [fold] u8 scan_norm[64] */ +static const u8 scan_norm[64] = { /* Octals */ + 000, 001, 010, 020, 011, 002, 003, 012, + 021, 030, 040, 031, 022, 013, 004, 005, + 014, 023, 032, 041, 050, 060, 051, 042, + 033, 024, 015, 006, 007, 016, 025, 034, + 043, 052, 061, 070, 071, 062, 053, 044, + 035, 026, 017, 027, 036, 045, 054, 063, + 072, 073, 064, 055, 046, 037, 047, 056, + 065, 074, 075, 066, 057, 067, 076, 077 +}; +/* }}} */ +/* {{{ [fold] hufftable[960] */ +struct hufftable_entry { + s16 value; + u8 bits; + u8 skip; +}; +static const struct hufftable_entry hufftable[960] = { + /* first level entries */ + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { 1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { -1, 3, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { 2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { -2, 4, 1 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 32767, 4, 255 }, + { 1, 5, 2 }, + { 1, 5, 2 }, + { 1, 5, 2 }, + { 1, 5, 2 }, + { 1, 5, 2 }, + { 1, 5, 2 }, + { 1, 5, 2 }, + { 1, 5, 2 }, + { -1, 5, 2 }, + { -1, 5, 2 }, + { -1, 5, 2 }, + { -1, 5, 2 }, + { -1, 5, 2 }, + { -1, 5, 2 }, + { -1, 5, 2 }, + { -1, 5, 2 }, + { 3, 5, 1 }, + { 3, 5, 1 }, + { 3, 5, 1 }, + { 3, 5, 1 }, + { 3, 5, 1 }, + { 3, 5, 1 }, + { 3, 5, 1 }, + { 3, 5, 1 }, + { -3, 5, 1 }, + { -3, 5, 1 }, + { -3, 5, 1 }, + { -3, 5, 1 }, + { -3, 5, 1 }, + { -3, 5, 1 }, + { -3, 5, 1 }, + { -3, 5, 1 }, + { 4, 5, 1 }, + { 4, 5, 1 }, + { 4, 5, 1 }, + { 4, 5, 1 }, + { 4, 5, 1 }, + { 4, 5, 1 }, + { 4, 5, 1 }, + { 4, 5, 1 }, + { -4, 5, 1 }, + { -4, 5, 1 }, + { -4, 5, 1 }, + { -4, 5, 1 }, + { -4, 5, 1 }, + { -4, 5, 1 }, + { -4, 5, 1 }, + { -4, 5, 1 }, + { 1, 6, 3 }, + { 1, 6, 3 }, + { 1, 6, 3 }, + { 1, 6, 3 }, + { -1, 6, 3 }, + { -1, 6, 3 }, + { -1, 6, 3 }, + { -1, 6, 3 }, + { 2, 6, 2 }, + { 2, 6, 2 }, + { 2, 6, 2 }, + { 2, 6, 2 }, + { -2, 6, 2 }, + { -2, 6, 2 }, + { -2, 6, 2 }, + { -2, 6, 2 }, + { 5, 6, 1 }, + { 5, 6, 1 }, + { 5, 6, 1 }, + { 5, 6, 1 }, + { -5, 6, 1 }, + { -5, 6, 1 }, + { -5, 6, 1 }, + { -5, 6, 1 }, + { 6, 6, 1 }, + { 6, 6, 1 }, + { 6, 6, 1 }, + { 6, 6, 1 }, + { -6, 6, 1 }, + { -6, 6, 1 }, + { -6, 6, 1 }, + { -6, 6, 1 }, + { 1, 7, 4 }, + { 1, 7, 4 }, + { -1, 7, 4 }, + { -1, 7, 4 }, + { 1, 7, 5 }, + { 1, 7, 5 }, + { -1, 7, 5 }, + { -1, 7, 5 }, + { 7, 7, 1 }, + { 7, 7, 1 }, + { -7, 7, 1 }, + { -7, 7, 1 }, + { 8, 7, 1 }, + { 8, 7, 1 }, + { -8, 7, 1 }, + { -8, 7, 1 }, + { 1, 8, 6 }, + { -1, 8, 6 }, + { 1, 8, 7 }, + { -1, 8, 7 }, + { 2, 8, 3 }, + { -2, 8, 3 }, + { 3, 8, 2 }, + { -3, 8, 2 }, + { 4, 8, 2 }, + { -4, 8, 2 }, + { 9, 8, 1 }, + { -9, 8, 1 }, + { 10, 8, 1 }, + { -10, 8, 1 }, + { 11, 8, 1 }, + { -11, 8, 1 }, + { 256, 9, 99 }, + { 258, 9, 99 }, + { 260, 9, 99 }, + { 262, 9, 99 }, + { 264, 9, 99 }, + { 266, 9, 99 }, + { 268, 9, 99 }, + { 270, 9, 99 }, + { 272, 9, 99 }, + { 274, 9, 99 }, + { 276, 9, 99 }, + { 278, 9, 99 }, + { 280, 9, 99 }, + { 282, 9, 99 }, + { 284, 9, 99 }, + { 286, 9, 99 }, + { 288, 10, 99 }, + { 292, 10, 99 }, + { 296, 10, 99 }, + { 300, 10, 99 }, + { 304, 10, 99 }, + { 308, 10, 99 }, + { 312, 10, 99 }, + { 316, 10, 99 }, + { 320, 11, 99 }, + { 328, 11, 99 }, + { 336, 12, 99 }, + { 352, 13, 99 }, + { 384, 13, 99 }, + { 416, 13, 99 }, + { 448, 16, 99 }, + { 704, 16, 99 }, + /* indirect entries */ + { 1, 9, 8 }, + { -1, 9, 8 }, + { 1, 9, 9 }, + { -1, 9, 9 }, + { 1, 9, 10 }, + { -1, 9, 10 }, + { 1, 9, 11 }, + { -1, 9, 11 }, + { 2, 9, 4 }, + { -2, 9, 4 }, + { 2, 9, 5 }, + { -2, 9, 5 }, + { 3, 9, 3 }, + { -3, 9, 3 }, + { 5, 9, 2 }, + { -5, 9, 2 }, + { 6, 9, 2 }, + { -6, 9, 2 }, + { 7, 9, 2 }, + { -7, 9, 2 }, + { 12, 9, 1 }, + { -12, 9, 1 }, + { 13, 9, 1 }, + { -13, 9, 1 }, + { 14, 9, 1 }, + { -14, 9, 1 }, + { 15, 9, 1 }, + { -15, 9, 1 }, + { 16, 9, 1 }, + { -16, 9, 1 }, + { 17, 9, 1 }, + { -17, 9, 1 }, + { 1, 10, 12 }, + { -1, 10, 12 }, + { 1, 10, 13 }, + { -1, 10, 13 }, + { 1, 10, 14 }, + { -1, 10, 14 }, + { 1, 10, 15 }, + { -1, 10, 15 }, + { 2, 10, 6 }, + { -2, 10, 6 }, + { 2, 10, 7 }, + { -2, 10, 7 }, + { 3, 10, 4 }, + { -3, 10, 4 }, + { 3, 10, 5 }, + { -3, 10, 5 }, + { 4, 10, 3 }, + { -4, 10, 3 }, + { 5, 10, 3 }, + { -5, 10, 3 }, + { 8, 10, 2 }, + { -8, 10, 2 }, + { 18, 10, 1 }, + { -18, 10, 1 }, + { 19, 10, 1 }, + { -19, 10, 1 }, + { 20, 10, 1 }, + { -20, 10, 1 }, + { 21, 10, 1 }, + { -21, 10, 1 }, + { 22, 10, 1 }, + { -22, 10, 1 }, + { 3, 11, 6 }, + { -3, 11, 6 }, + { 4, 11, 4 }, + { -4, 11, 4 }, + { 5, 11, 4 }, + { -5, 11, 4 }, + { 6, 11, 3 }, + { -6, 11, 3 }, + { 9, 11, 2 }, + { -9, 11, 2 }, + { 10, 11, 2 }, + { -10, 11, 2 }, + { 11, 11, 2 }, + { -11, 11, 2 }, + { 0, 11, 1 }, + { 0, 11, 2 }, + { 3, 12, 7 }, + { -3, 12, 7 }, + { 4, 12, 5 }, + { -4, 12, 5 }, + { 6, 12, 4 }, + { -6, 12, 4 }, + { 12, 12, 2 }, + { -12, 12, 2 }, + { 13, 12, 2 }, + { -13, 12, 2 }, + { 14, 12, 2 }, + { -14, 12, 2 }, + { 0, 12, 3 }, + { 0, 12, 4 }, + { 0, 12, 5 }, + { 0, 12, 6 }, + { 2, 13, 8 }, + { -2, 13, 8 }, + { 2, 13, 9 }, + { -2, 13, 9 }, + { 2, 13, 10 }, + { -2, 13, 10 }, + { 2, 13, 11 }, + { -2, 13, 11 }, + { 3, 13, 8 }, + { -3, 13, 8 }, + { 3, 13, 9 }, + { -3, 13, 9 }, + { 5, 13, 5 }, + { -5, 13, 5 }, + { 7, 13, 4 }, + { -7, 13, 4 }, + { 7, 13, 3 }, + { -7, 13, 3 }, + { 8, 13, 3 }, + { -8, 13, 3 }, + { 9, 13, 3 }, + { -9, 13, 3 }, + { 10, 13, 3 }, + { -10, 13, 3 }, + { 11, 13, 3 }, + { -11, 13, 3 }, + { 15, 13, 2 }, + { -15, 13, 2 }, + { 16, 13, 2 }, + { -16, 13, 2 }, + { 17, 13, 2 }, + { -17, 13, 2 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 0, 13, 7 }, + { 0, 13, 8 }, + { 0, 13, 9 }, + { 0, 13, 10 }, + { 0, 13, 11 }, + { 0, 13, 12 }, + { 0, 13, 13 }, + { 0, 13, 14 }, + { 0, 13, 15 }, + { 0, 13, 16 }, + { 0, 13, 17 }, + { 0, 13, 18 }, + { 0, 13, 19 }, + { 0, 13, 20 }, + { 0, 13, 21 }, + { 0, 13, 22 }, + { 0, 13, 23 }, + { 0, 13, 24 }, + { 0, 13, 25 }, + { 0, 13, 26 }, + { 0, 13, 27 }, + { 0, 13, 28 }, + { 0, 13, 29 }, + { 0, 13, 30 }, + { 0, 13, 31 }, + { 0, 13, 32 }, + { 0, 13, 33 }, + { 0, 13, 34 }, + { 0, 13, 35 }, + { 0, 13, 36 }, + { 0, 13, 37 }, + { 0, 13, 38 }, + { 0, 13, 39 }, + { 0, 13, 40 }, + { 0, 13, 41 }, + { 0, 13, 42 }, + { 0, 13, 43 }, + { 0, 13, 44 }, + { 0, 13, 45 }, + { 0, 13, 46 }, + { 0, 13, 47 }, + { 0, 13, 48 }, + { 0, 13, 49 }, + { 0, 13, 50 }, + { 0, 13, 51 }, + { 0, 13, 52 }, + { 0, 13, 53 }, + { 0, 13, 54 }, + { 0, 13, 55 }, + { 0, 13, 56 }, + { 0, 13, 57 }, + { 0, 13, 58 }, + { 0, 13, 59 }, + { 0, 13, 60 }, + { 0, 13, 61 }, + { 0, 13, 62 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 32767, 0, 255 }, + { 23, 16, 1 }, + { -23, 16, 1 }, + { 24, 16, 1 }, + { -24, 16, 1 }, + { 25, 16, 1 }, + { -25, 16, 1 }, + { 26, 16, 1 }, + { -26, 16, 1 }, + { 27, 16, 1 }, + { -27, 16, 1 }, + { 28, 16, 1 }, + { -28, 16, 1 }, + { 29, 16, 1 }, + { -29, 16, 1 }, + { 30, 16, 1 }, + { -30, 16, 1 }, + { 31, 16, 1 }, + { -31, 16, 1 }, + { 32, 16, 1 }, + { -32, 16, 1 }, + { 33, 16, 1 }, + { -33, 16, 1 }, + { 34, 16, 1 }, + { -34, 16, 1 }, + { 35, 16, 1 }, + { -35, 16, 1 }, + { 36, 16, 1 }, + { -36, 16, 1 }, + { 37, 16, 1 }, + { -37, 16, 1 }, + { 38, 16, 1 }, + { -38, 16, 1 }, + { 39, 16, 1 }, + { -39, 16, 1 }, + { 40, 16, 1 }, + { -40, 16, 1 }, + { 41, 16, 1 }, + { -41, 16, 1 }, + { 42, 16, 1 }, + { -42, 16, 1 }, + { 43, 16, 1 }, + { -43, 16, 1 }, + { 44, 16, 1 }, + { -44, 16, 1 }, + { 45, 16, 1 }, + { -45, 16, 1 }, + { 46, 16, 1 }, + { -46, 16, 1 }, + { 47, 16, 1 }, + { -47, 16, 1 }, + { 48, 16, 1 }, + { -48, 16, 1 }, + { 49, 16, 1 }, + { -49, 16, 1 }, + { 50, 16, 1 }, + { -50, 16, 1 }, + { 51, 16, 1 }, + { -51, 16, 1 }, + { 52, 16, 1 }, + { -52, 16, 1 }, + { 53, 16, 1 }, + { -53, 16, 1 }, + { 54, 16, 1 }, + { -54, 16, 1 }, + { 55, 16, 1 }, + { -55, 16, 1 }, + { 56, 16, 1 }, + { -56, 16, 1 }, + { 57, 16, 1 }, + { -57, 16, 1 }, + { 58, 16, 1 }, + { -58, 16, 1 }, + { 59, 16, 1 }, + { -59, 16, 1 }, + { 60, 16, 1 }, + { -60, 16, 1 }, + { 61, 16, 1 }, + { -61, 16, 1 }, + { 62, 16, 1 }, + { -62, 16, 1 }, + { 63, 16, 1 }, + { -63, 16, 1 }, + { 64, 16, 1 }, + { -64, 16, 1 }, + { 65, 16, 1 }, + { -65, 16, 1 }, + { 66, 16, 1 }, + { -66, 16, 1 }, + { 67, 16, 1 }, + { -67, 16, 1 }, + { 68, 16, 1 }, + { -68, 16, 1 }, + { 69, 16, 1 }, + { -69, 16, 1 }, + { 70, 16, 1 }, + { -70, 16, 1 }, + { 71, 16, 1 }, + { -71, 16, 1 }, + { 72, 16, 1 }, + { -72, 16, 1 }, + { 73, 16, 1 }, + { -73, 16, 1 }, + { 74, 16, 1 }, + { -74, 16, 1 }, + { 75, 16, 1 }, + { -75, 16, 1 }, + { 76, 16, 1 }, + { -76, 16, 1 }, + { 77, 16, 1 }, + { -77, 16, 1 }, + { 78, 16, 1 }, + { -78, 16, 1 }, + { 79, 16, 1 }, + { -79, 16, 1 }, + { 80, 16, 1 }, + { -80, 16, 1 }, + { 81, 16, 1 }, + { -81, 16, 1 }, + { 82, 16, 1 }, + { -82, 16, 1 }, + { 83, 16, 1 }, + { -83, 16, 1 }, + { 84, 16, 1 }, + { -84, 16, 1 }, + { 85, 16, 1 }, + { -85, 16, 1 }, + { 86, 16, 1 }, + { -86, 16, 1 }, + { 87, 16, 1 }, + { -87, 16, 1 }, + { 88, 16, 1 }, + { -88, 16, 1 }, + { 89, 16, 1 }, + { -89, 16, 1 }, + { 90, 16, 1 }, + { -90, 16, 1 }, + { 91, 16, 1 }, + { -91, 16, 1 }, + { 92, 16, 1 }, + { -92, 16, 1 }, + { 93, 16, 1 }, + { -93, 16, 1 }, + { 94, 16, 1 }, + { -94, 16, 1 }, + { 95, 16, 1 }, + { -95, 16, 1 }, + { 96, 16, 1 }, + { -96, 16, 1 }, + { 97, 16, 1 }, + { -97, 16, 1 }, + { 98, 16, 1 }, + { -98, 16, 1 }, + { 99, 16, 1 }, + { -99, 16, 1 }, + { 100, 16, 1 }, + { -100, 16, 1 }, + { 101, 16, 1 }, + { -101, 16, 1 }, + { 102, 16, 1 }, + { -102, 16, 1 }, + { 103, 16, 1 }, + { -103, 16, 1 }, + { 104, 16, 1 }, + { -104, 16, 1 }, + { 105, 16, 1 }, + { -105, 16, 1 }, + { 106, 16, 1 }, + { -106, 16, 1 }, + { 107, 16, 1 }, + { -107, 16, 1 }, + { 108, 16, 1 }, + { -108, 16, 1 }, + { 109, 16, 1 }, + { -109, 16, 1 }, + { 110, 16, 1 }, + { -110, 16, 1 }, + { 111, 16, 1 }, + { -111, 16, 1 }, + { 112, 16, 1 }, + { -112, 16, 1 }, + { 113, 16, 1 }, + { -113, 16, 1 }, + { 114, 16, 1 }, + { -114, 16, 1 }, + { 115, 16, 1 }, + { -115, 16, 1 }, + { 116, 16, 1 }, + { -116, 16, 1 }, + { 117, 16, 1 }, + { -117, 16, 1 }, + { 118, 16, 1 }, + { -118, 16, 1 }, + { 119, 16, 1 }, + { -119, 16, 1 }, + { 120, 16, 1 }, + { -120, 16, 1 }, + { 121, 16, 1 }, + { -121, 16, 1 }, + { 122, 16, 1 }, + { -122, 16, 1 }, + { 123, 16, 1 }, + { -123, 16, 1 }, + { 124, 16, 1 }, + { -124, 16, 1 }, + { 125, 16, 1 }, + { -125, 16, 1 }, + { 126, 16, 1 }, + { -126, 16, 1 }, + { 127, 16, 1 }, + { -127, 16, 1 }, + { 128, 16, 1 }, + { -128, 16, 1 }, + { 129, 16, 1 }, + { -129, 16, 1 }, + { 130, 16, 1 }, + { -130, 16, 1 }, + { 131, 16, 1 }, + { -131, 16, 1 }, + { 132, 16, 1 }, + { -132, 16, 1 }, + { 133, 16, 1 }, + { -133, 16, 1 }, + { 134, 16, 1 }, + { -134, 16, 1 }, + { 135, 16, 1 }, + { -135, 16, 1 }, + { 136, 16, 1 }, + { -136, 16, 1 }, + { 137, 16, 1 }, + { -137, 16, 1 }, + { 138, 16, 1 }, + { -138, 16, 1 }, + { 139, 16, 1 }, + { -139, 16, 1 }, + { 140, 16, 1 }, + { -140, 16, 1 }, + { 141, 16, 1 }, + { -141, 16, 1 }, + { 142, 16, 1 }, + { -142, 16, 1 }, + { 143, 16, 1 }, + { -143, 16, 1 }, + { 144, 16, 1 }, + { -144, 16, 1 }, + { 145, 16, 1 }, + { -145, 16, 1 }, + { 146, 16, 1 }, + { -146, 16, 1 }, + { 147, 16, 1 }, + { -147, 16, 1 }, + { 148, 16, 1 }, + { -148, 16, 1 }, + { 149, 16, 1 }, + { -149, 16, 1 }, + { 150, 16, 1 }, + { -150, 16, 1 }, + { 151, 16, 1 }, + { -151, 16, 1 }, + { 152, 16, 1 }, + { -152, 16, 1 }, + { 153, 16, 1 }, + { -153, 16, 1 }, + { 154, 16, 1 }, + { -154, 16, 1 }, + { 155, 16, 1 }, + { -155, 16, 1 }, + { 156, 16, 1 }, + { -156, 16, 1 }, + { 157, 16, 1 }, + { -157, 16, 1 }, + { 158, 16, 1 }, + { -158, 16, 1 }, + { 159, 16, 1 }, + { -159, 16, 1 }, + { 160, 16, 1 }, + { -160, 16, 1 }, + { 161, 16, 1 }, + { -161, 16, 1 }, + { 162, 16, 1 }, + { -162, 16, 1 }, + { 163, 16, 1 }, + { -163, 16, 1 }, + { 164, 16, 1 }, + { -164, 16, 1 }, + { 165, 16, 1 }, + { -165, 16, 1 }, + { 166, 16, 1 }, + { -166, 16, 1 }, + { 167, 16, 1 }, + { -167, 16, 1 }, + { 168, 16, 1 }, + { -168, 16, 1 }, + { 169, 16, 1 }, + { -169, 16, 1 }, + { 170, 16, 1 }, + { -170, 16, 1 }, + { 171, 16, 1 }, + { -171, 16, 1 }, + { 172, 16, 1 }, + { -172, 16, 1 }, + { 173, 16, 1 }, + { -173, 16, 1 }, + { 174, 16, 1 }, + { -174, 16, 1 }, + { 175, 16, 1 }, + { -175, 16, 1 }, + { 176, 16, 1 }, + { -176, 16, 1 }, + { 177, 16, 1 }, + { -177, 16, 1 }, + { 178, 16, 1 }, + { -178, 16, 1 }, + { 179, 16, 1 }, + { -179, 16, 1 }, + { 180, 16, 1 }, + { -180, 16, 1 }, + { 181, 16, 1 }, + { -181, 16, 1 }, + { 182, 16, 1 }, + { -182, 16, 1 }, + { 183, 16, 1 }, + { -183, 16, 1 }, + { 184, 16, 1 }, + { -184, 16, 1 }, + { 185, 16, 1 }, + { -185, 16, 1 }, + { 186, 16, 1 }, + { -186, 16, 1 }, + { 187, 16, 1 }, + { -187, 16, 1 }, + { 188, 16, 1 }, + { -188, 16, 1 }, + { 189, 16, 1 }, + { -189, 16, 1 }, + { 190, 16, 1 }, + { -190, 16, 1 }, + { 191, 16, 1 }, + { -191, 16, 1 }, + { 192, 16, 1 }, + { -192, 16, 1 }, + { 193, 16, 1 }, + { -193, 16, 1 }, + { 194, 16, 1 }, + { -194, 16, 1 }, + { 195, 16, 1 }, + { -195, 16, 1 }, + { 196, 16, 1 }, + { -196, 16, 1 }, + { 197, 16, 1 }, + { -197, 16, 1 }, + { 198, 16, 1 }, + { -198, 16, 1 }, + { 199, 16, 1 }, + { -199, 16, 1 }, + { 200, 16, 1 }, + { -200, 16, 1 }, + { 201, 16, 1 }, + { -201, 16, 1 }, + { 202, 16, 1 }, + { -202, 16, 1 }, + { 203, 16, 1 }, + { -203, 16, 1 }, + { 204, 16, 1 }, + { -204, 16, 1 }, + { 205, 16, 1 }, + { -205, 16, 1 }, + { 206, 16, 1 }, + { -206, 16, 1 }, + { 207, 16, 1 }, + { -207, 16, 1 }, + { 208, 16, 1 }, + { -208, 16, 1 }, + { 209, 16, 1 }, + { -209, 16, 1 }, + { 210, 16, 1 }, + { -210, 16, 1 }, + { 211, 16, 1 }, + { -211, 16, 1 }, + { 212, 16, 1 }, + { -212, 16, 1 }, + { 213, 16, 1 }, + { -213, 16, 1 }, + { 214, 16, 1 }, + { -214, 16, 1 }, + { 215, 16, 1 }, + { -215, 16, 1 }, + { 216, 16, 1 }, + { -216, 16, 1 }, + { 217, 16, 1 }, + { -217, 16, 1 }, + { 218, 16, 1 }, + { -218, 16, 1 }, + { 219, 16, 1 }, + { -219, 16, 1 }, + { 220, 16, 1 }, + { -220, 16, 1 }, + { 221, 16, 1 }, + { -221, 16, 1 }, + { 222, 16, 1 }, + { -222, 16, 1 }, + { 223, 16, 1 }, + { -223, 16, 1 }, + { 224, 16, 1 }, + { -224, 16, 1 }, + { 225, 16, 1 }, + { -225, 16, 1 }, + { 226, 16, 1 }, + { -226, 16, 1 }, + { 227, 16, 1 }, + { -227, 16, 1 }, + { 228, 16, 1 }, + { -228, 16, 1 }, + { 229, 16, 1 }, + { -229, 16, 1 }, + { 230, 16, 1 }, + { -230, 16, 1 }, + { 231, 16, 1 }, + { -231, 16, 1 }, + { 232, 16, 1 }, + { -232, 16, 1 }, + { 233, 16, 1 }, + { -233, 16, 1 }, + { 234, 16, 1 }, + { -234, 16, 1 }, + { 235, 16, 1 }, + { -235, 16, 1 }, + { 236, 16, 1 }, + { -236, 16, 1 }, + { 237, 16, 1 }, + { -237, 16, 1 }, + { 238, 16, 1 }, + { -238, 16, 1 }, + { 239, 16, 1 }, + { -239, 16, 1 }, + { 240, 16, 1 }, + { -240, 16, 1 }, + { 241, 16, 1 }, + { -241, 16, 1 }, + { 242, 16, 1 }, + { -242, 16, 1 }, + { 243, 16, 1 }, + { -243, 16, 1 }, + { 244, 16, 1 }, + { -244, 16, 1 }, + { 245, 16, 1 }, + { -245, 16, 1 }, + { 246, 16, 1 }, + { -246, 16, 1 }, + { 247, 16, 1 }, + { -247, 16, 1 }, + { 248, 16, 1 }, + { -248, 16, 1 }, + { 249, 16, 1 }, + { -249, 16, 1 }, + { 250, 16, 1 }, + { -250, 16, 1 }, + { 251, 16, 1 }, + { -251, 16, 1 }, + { 252, 16, 1 }, + { -252, 16, 1 }, + { 253, 16, 1 }, + { -253, 16, 1 }, + { 254, 16, 1 }, + { -254, 16, 1 }, + { 255, 16, 1 }, + { -255, 16, 1 } +}; +/* }}} */ +/* {{{ [fold] qc_mjpeg_lvc_decode_block(struct bitstream *bitsrc, s16 *output, int blockval) */ +static inline void qc_mjpeg_lvc_decode_block(struct bitstream *bitsrc, s16 *output, int blockval) +{ + u32 b; + u8 *p; + int k; + int value, skip, bits; + struct hufftable_entry entry; + int offset = 0; + const u8 *shiftPtr; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_lvc_decode_block(bitsrc=%p, output=%p, blockval=%i)", bitsrc, output, blockval); + b = bitsrc->b; + k = bitsrc->k; + p = bitsrc->p; + memset(output, 0, 64 * sizeof(s16)); + if (blockval!=7) PDEBUG("blockval=%i",blockval); + NEEDBITS(b,k,p); + shiftPtr = shiftTables[shiftTblIndex[2*blockval+BITVALUE(b,1)]]; + DUMPBITS(b,k,1); + value = BITVALUE(((signed)b),10); + DUMPBITS(b,k,10); + do { + value = ((value << shiftPtr[offset]) * scaleTable[offset]) >> 14; + output[scan_norm[offset]] = value; + NEEDBITS(b,k,p); + entry = hufftable[BITVALUE(b,8)]; + bits = entry.bits; + if (bits > 8) { + entry = hufftable[entry.value + ((b & 0x00ffffff) >> (32 - bits))]; + if (PARANOID && entry.bits!=bits) { + PDEBUG("entry.bits!=bits shouldn't happen"); + bits = entry.bits; + } + } + DUMPBITS(b,k,bits); + skip = entry.skip; + value = entry.value; + offset += skip; + } while (offset < 64); + bitsrc->b = b; + bitsrc->k = k; + bitsrc->p = p; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_lvc_decode_block() exit"); +} +/* }}} */ + +/* {{{ [fold] struct blockorder */ +struct blockorder { + char widthPad; /* pad width to multiple of this */ + char heightPad; /* pad height to multiple of this */ + char uvWshift; /* shift width by this to get width of U/V image */ + char uvHshift; /* dito for height */ + char blockWidth[2]; /* width of a block for each pass*/ + char subblockCount[2]; /* number of sub block in a block for each pass */ + u32 subblockMap[2]; +}; +static const struct blockorder order_I420 = { + 32, 16, 1, 1, + { 32, 16 }, { 4, 4 }, + { 0x00, 0x90 } +}; +#if 0 +static const struct blockorder order_L422 = { + 16, 16, 1, 0, + { 16, 16 }, { 4, 4 }, + { 0x90, 0x90 } +}; + +static const struct blockorder order_L410 = { + 64, 16, 2, 1, + { 32, 64 }, { 4, 12 }, + { 0x00, 0x909000 } +}; +#endif +/* }}} */ +/* {{{ [fold] qc_mjpeg_lvc_decode() */ +/* Decode given compressed image to YUV image. Return error code if bad data */ +static int qc_mjpeg_lvc_decode(u8 *outY, u8 *outU, u8 *outV, + u8 *input, u32 length, unsigned int width, unsigned int height) +{ + struct bitstream stream; + const struct blockorder *blkorder; + + unsigned int blockx, blocky; + unsigned int pass, subblock, blockval = 0; + unsigned int blocknr = 0; + unsigned int uvWidth; + + s16 blockbuffer[64]; + + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_lvc_decode(outY=%p, outU=%p, outV=%p)", outY, outU, outV); + stream.b = 0; + stream.k = 16; + stream.p = input; + stream.end = input+length; + + blkorder = &order_I420; /* Select compression type */ + + uvWidth = (width >> blkorder->uvWshift); + + if ((width & (blkorder->widthPad - 1)) || (height & (blkorder->heightPad - 1))) { + PDEBUG("something's wrong"); + return -EILSEQ; + } + + for (blocky=0; blockyheightPad) { + for (pass = 0; pass < 2; pass++) { + int blockwidth = blkorder->blockWidth[pass]; + int subblockcount = blkorder->subblockCount[pass]; + u32 map = blkorder->subblockMap[pass]; + for (blockx=0; blockx stream.end) { + PDEBUG("p>stream.end"); + return -EILSEQ; + } + + blockval = BITVALUE(b, 4); + DUMPBITS(b,k,4); + stream.b = b; + stream.k = k; + stream.p = p; + } + qc_mjpeg_lvc_decode_block(&stream, blockbuffer, blockval); + blockbuffer[0] += 1024; + switch (subblkmap & 3) { + case 0: + qc_mjpeg_idct(blockbuffer, outY, width); + outY += 8; + break; + case 1: + qc_mjpeg_idct(blockbuffer, outU, uvWidth); + outU += 8; + break; + case 2: + qc_mjpeg_idct(blockbuffer, outV, uvWidth); + outV += 8; + break; + } + subblkmap >>= 2; + } /* for (subblock = 0; subblock < subblockcount; subblock++) */ + } /* for (blockx = 0; blockx < width; blockx += blockwidth) */ + outY += 7 * width; + if (map) { + outU += 7 * uvWidth; + outV += 7 * uvWidth; + } + } /* for (pass = 0; pass < 2; pass++) */ + + /* next block starts at next 4 byte boundary */ + stream.p -= (16 - stream.k) >> 3; /* push back unread bits */ + stream.p += (input - stream.p) & 3; + stream.k = 16; + stream.b = 0; + } /* for (blocky=0; blockyheightPad) */ + + if (stream.p != stream.end) { + PDEBUG("stream.p != stream.end"); + return -EILSEQ; + } + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_lvc_decode() done"); + return 0; +} +/* }}} */ + +/* }}} */ +/* {{{ [fold] **** qc_mjpeg: Motion JPEG decoding main routines *************************** */ + +static const int qc_mjpeg_width = 320; /* Size of the compressed image */ +static const int qc_mjpeg_height = 240; + +/* {{{ [fold] qc_mjpeg_decode() */ +/* Decode and uncompress given data, return error code if failure + * src = points to compressed bitstream data + * src_len = compressed data length in bytes + * dst = decompressed image will be stored here, size 320x240 x bytes per pixel (2-4) + */ +int qc_mjpeg_decode(struct qc_mjpeg_data *md, unsigned char *src, int src_len, unsigned char *dst) +{ + int r; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_decode(src_len=%i,W=%i,H=%i,depth=%i)",src_len,qc_mjpeg_width,qc_mjpeg_height,md->depth); + IDEBUG_TEST(*md); + if (src_len >= 100000) { + PDEBUG("long frame, length=%i", src_len); + return -EILSEQ; + } + r = qc_mjpeg_lvc_decode(md->encY, md->encU, md->encV, src, src_len, qc_mjpeg_width, qc_mjpeg_height); + if (r<0) { + PRINTK(KERN_ERR,"frame corrupted, len=%i",src_len); + return r; + } + qc_mjpeg_yuv2rgb(md, dst, md->encY, md->encU, md->encV, + qc_mjpeg_width, qc_mjpeg_height, /* Image size */ + qc_mjpeg_width * ((md->depth+1)/8), /* RGB stride */ + qc_mjpeg_width, /* Y stride */ + qc_mjpeg_width/2); /* U and V stride */ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_decode() done"); + return 0; +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_init(struct qc_mjpeg_data *md, int depth, Bool tobgr) */ +/* Initialize Motion JPEG decompression. + * depth = bit depth of the decoded image, either 15=16,24 or 32 + * tobgr = use blue in the lowest address (red otherwise) + */ +int qc_mjpeg_init(struct qc_mjpeg_data *md, int depth, Bool tobgr) +{ + int r = -ENOMEM; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_init(depth=%i)",depth); + md->depth = depth; + /* Temporary buffers used for decoding the image (FIXME:too big for stack?) */ + /* Note: originally this allocated one extra byte for encY/U/V. I removed that. */ + md->encY = kmalloc(qc_mjpeg_width*qc_mjpeg_height, GFP_KERNEL); + if (!md->encY) goto fail1; + md->encU = kmalloc(qc_mjpeg_width*qc_mjpeg_height/4, GFP_KERNEL); + if (!md->encU) goto fail2; + md->encV = kmalloc(qc_mjpeg_width*qc_mjpeg_height/4, GFP_KERNEL); + if (!md->encV) goto fail3; + if ((r=qc_mjpeg_yuv2rgb_init(md, depth, tobgr ? MODE_BGR : MODE_RGB))<0) goto fail4; + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_init() done"); + IDEBUG_INIT(*md); + return 0; + +fail4: kfree(md->encV); +fail3: kfree(md->encU); +fail2: kfree(md->encY); +fail1: PDEBUG("failed qc_mjpeg_init() = %i", r); + POISON(*md); + return r; +} +/* }}} */ +/* {{{ [fold] qc_mjpeg_exit(struct qc_mjpeg_data *md) */ +/* Free up resources allocated for image decompression */ +void qc_mjpeg_exit(struct qc_mjpeg_data *md) +{ + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_exit()"); + IDEBUG_TEST(*md); + qc_mjpeg_yuv2rgb_exit(md); + kfree(md->encV); + kfree(md->encU); + kfree(md->encY); + POISON(md->encV); + POISON(md->encU); + POISON(md->encY); + if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_mjpeg_exit() done"); + IDEBUG_EXIT(*md); +} +/* }}} */ + +/* }}} */ + +#else /* COMPRESS=0 */ +int qc_mjpeg_decode(struct qc_mjpeg_data *md, unsigned char *src, int src_len, unsigned char *dst) { return -ENXIO; } +int qc_mjpeg_init(struct qc_mjpeg_data *md, int depth, Bool tobgr) { return -ENXIO; } +void qc_mjpeg_exit(struct qc_mjpeg_data *md) { } +#endif + +/* End of file */ --- linux-2.6.27.orig/ubuntu/qc-usb/Makefile +++ linux-2.6.27/ubuntu/qc-usb/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_QC_USB) := quickcam.o + +quickcam-objs := qc-driver.o qc-hdcs.o qc-pb0100.o qc-vv6410.o qc-formats.o qc-mjpeg.o qc-memory.o --- linux-2.6.27.orig/ubuntu/qc-usb/qc-memory.h +++ linux-2.6.27/ubuntu/qc-usb/qc-memory.h @@ -0,0 +1,10 @@ +#ifndef _LINUX_QC_MEMORY_H +#define _LINUX_QC_MEMORY_H + +#include + +void *qc_mm_rvmalloc(unsigned long size); +void qc_mm_rvfree(void *mem, unsigned long size); +int qc_mm_remap(struct vm_area_struct *vma, void *src, unsigned long src_size, const void *dst, unsigned long dst_size); + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/kcompat_ethtool.c +++ linux-2.6.27/ubuntu/e1000e/kcompat_ethtool.c @@ -0,0 +1,1169 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* + * net/core/ethtool.c - Ethtool ioctl handler + * Copyright (c) 2003 Matthew Wilcox + * + * This file is where we call all the ethtool_ops commands to get + * the information ethtool needs. We fall back to calling do_ioctl() + * for drivers which haven't been converted to ethtool_ops yet. + * + * It's GPL, stupid. + * + * Modification by sfeldma@pobox.com to work as backward compat + * solution for pre-ethtool_ops kernels. + * - copied struct ethtool_ops from ethtool.h + * - defined SET_ETHTOOL_OPS + * - put in some #ifndef NETIF_F_xxx wrappers + * - changes refs to dev->ethtool_ops to ethtool_ops + * - changed dev_ethtool to ethtool_ioctl + * - remove EXPORT_SYMBOL()s + * - added _kc_ prefix in built-in ethtool_op_xxx ops. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "kcompat.h" + +#undef SUPPORTED_10000baseT_Full +#define SUPPORTED_10000baseT_Full (1 << 12) +#undef ADVERTISED_10000baseT_Full +#define ADVERTISED_10000baseT_Full (1 << 12) +#undef SPEED_10000 +#define SPEED_10000 10000 + +#undef ethtool_ops +#define ethtool_ops _kc_ethtool_ops + +struct _kc_ethtool_ops { + int (*get_settings)(struct net_device *, struct ethtool_cmd *); + int (*set_settings)(struct net_device *, struct ethtool_cmd *); + void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); + int (*get_regs_len)(struct net_device *); + void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); + void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); + int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); + u32 (*get_msglevel)(struct net_device *); + void (*set_msglevel)(struct net_device *, u32); + int (*nway_reset)(struct net_device *); + u32 (*get_link)(struct net_device *); + int (*get_eeprom_len)(struct net_device *); + int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); + int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); + int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); + int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); + void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); + int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); + void (*get_pauseparam)(struct net_device *, + struct ethtool_pauseparam*); + int (*set_pauseparam)(struct net_device *, + struct ethtool_pauseparam*); + u32 (*get_rx_csum)(struct net_device *); + int (*set_rx_csum)(struct net_device *, u32); + u32 (*get_tx_csum)(struct net_device *); + int (*set_tx_csum)(struct net_device *, u32); + u32 (*get_sg)(struct net_device *); + int (*set_sg)(struct net_device *, u32); + u32 (*get_tso)(struct net_device *); + int (*set_tso)(struct net_device *, u32); + int (*self_test_count)(struct net_device *); + void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); + void (*get_strings)(struct net_device *, u32 stringset, u8 *); + int (*phys_id)(struct net_device *, u32); + int (*get_stats_count)(struct net_device *); + void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, + u64 *); +} *ethtool_ops = NULL; + +#undef SET_ETHTOOL_OPS +#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) + +/* + * Some useful ethtool_ops methods that are device independent. If we find that + * all drivers want to do the same thing here, we can turn these into dev_() + * function calls. + */ + +#undef ethtool_op_get_link +#define ethtool_op_get_link _kc_ethtool_op_get_link +u32 _kc_ethtool_op_get_link(struct net_device *dev) +{ + return netif_carrier_ok(dev) ? 1 : 0; +} + +#undef ethtool_op_get_tx_csum +#define ethtool_op_get_tx_csum _kc_ethtool_op_get_tx_csum +u32 _kc_ethtool_op_get_tx_csum(struct net_device *dev) +{ +#ifdef NETIF_F_IP_CSUM + return (dev->features & NETIF_F_IP_CSUM) != 0; +#else + return 0; +#endif +} + +#undef ethtool_op_set_tx_csum +#define ethtool_op_set_tx_csum _kc_ethtool_op_set_tx_csum +int _kc_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) +{ +#ifdef NETIF_F_IP_CSUM + if (data) +#ifdef NETIF_F_IPV6_CSUM + dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + else + dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); +#else + dev->features |= NETIF_F_IP_CSUM; + else + dev->features &= ~NETIF_F_IP_CSUM; +#endif +#endif + + return 0; +} + +#undef ethtool_op_get_sg +#define ethtool_op_get_sg _kc_ethtool_op_get_sg +u32 _kc_ethtool_op_get_sg(struct net_device *dev) +{ +#ifdef NETIF_F_SG + return (dev->features & NETIF_F_SG) != 0; +#else + return 0; +#endif +} + +#undef ethtool_op_set_sg +#define ethtool_op_set_sg _kc_ethtool_op_set_sg +int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) +{ +#ifdef NETIF_F_SG + if (data) + dev->features |= NETIF_F_SG; + else + dev->features &= ~NETIF_F_SG; +#endif + + return 0; +} + +#undef ethtool_op_get_tso +#define ethtool_op_get_tso _kc_ethtool_op_get_tso +u32 _kc_ethtool_op_get_tso(struct net_device *dev) +{ +#ifdef NETIF_F_TSO + return (dev->features & NETIF_F_TSO) != 0; +#else + return 0; +#endif +} + +#undef ethtool_op_set_tso +#define ethtool_op_set_tso _kc_ethtool_op_set_tso +int _kc_ethtool_op_set_tso(struct net_device *dev, u32 data) +{ +#ifdef NETIF_F_TSO + if (data) + dev->features |= NETIF_F_TSO; + else + dev->features &= ~NETIF_F_TSO; +#endif + + return 0; +} + +/* Handlers for each ethtool command */ + +static int ethtool_get_settings(struct net_device *dev, void *useraddr) +{ + struct ethtool_cmd cmd = { ETHTOOL_GSET }; + int err; + + if (!ethtool_ops->get_settings) + return -EOPNOTSUPP; + + err = ethtool_ops->get_settings(dev, &cmd); + if (err < 0) + return err; + + if (copy_to_user(useraddr, &cmd, sizeof(cmd))) + return -EFAULT; + return 0; +} + +static int ethtool_set_settings(struct net_device *dev, void *useraddr) +{ + struct ethtool_cmd cmd; + + if (!ethtool_ops->set_settings) + return -EOPNOTSUPP; + + if (copy_from_user(&cmd, useraddr, sizeof(cmd))) + return -EFAULT; + + return ethtool_ops->set_settings(dev, &cmd); +} + +static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) +{ + struct ethtool_drvinfo info; + struct ethtool_ops *ops = ethtool_ops; + + if (!ops->get_drvinfo) + return -EOPNOTSUPP; + + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GDRVINFO; + ops->get_drvinfo(dev, &info); + + if (ops->self_test_count) + info.testinfo_len = ops->self_test_count(dev); + if (ops->get_stats_count) + info.n_stats = ops->get_stats_count(dev); + if (ops->get_regs_len) + info.regdump_len = ops->get_regs_len(dev); + if (ops->get_eeprom_len) + info.eedump_len = ops->get_eeprom_len(dev); + + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +static int ethtool_get_regs(struct net_device *dev, char *useraddr) +{ + struct ethtool_regs regs; + struct ethtool_ops *ops = ethtool_ops; + void *regbuf; + int reglen, ret; + + if (!ops->get_regs || !ops->get_regs_len) + return -EOPNOTSUPP; + + if (copy_from_user(®s, useraddr, sizeof(regs))) + return -EFAULT; + + reglen = ops->get_regs_len(dev); + if (regs.len > reglen) + regs.len = reglen; + + regbuf = kmalloc(reglen, GFP_USER); + if (!regbuf) + return -ENOMEM; + + ops->get_regs(dev, ®s, regbuf); + + ret = -EFAULT; + if (copy_to_user(useraddr, ®s, sizeof(regs))) + goto out; + useraddr += offsetof(struct ethtool_regs, data); + if (copy_to_user(useraddr, regbuf, reglen)) + goto out; + ret = 0; + +out: + kfree(regbuf); + return ret; +} + +static int ethtool_get_wol(struct net_device *dev, char *useraddr) +{ + struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; + + if (!ethtool_ops->get_wol) + return -EOPNOTSUPP; + + ethtool_ops->get_wol(dev, &wol); + + if (copy_to_user(useraddr, &wol, sizeof(wol))) + return -EFAULT; + return 0; +} + +static int ethtool_set_wol(struct net_device *dev, char *useraddr) +{ + struct ethtool_wolinfo wol; + + if (!ethtool_ops->set_wol) + return -EOPNOTSUPP; + + if (copy_from_user(&wol, useraddr, sizeof(wol))) + return -EFAULT; + + return ethtool_ops->set_wol(dev, &wol); +} + +static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GMSGLVL }; + + if (!ethtool_ops->get_msglevel) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_msglevel(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_msglevel) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + ethtool_ops->set_msglevel(dev, edata.data); + return 0; +} + +static int ethtool_nway_reset(struct net_device *dev) +{ + if (!ethtool_ops->nway_reset) + return -EOPNOTSUPP; + + return ethtool_ops->nway_reset(dev); +} + +static int ethtool_get_link(struct net_device *dev, void *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GLINK }; + + if (!ethtool_ops->get_link) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_link(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) +{ + struct ethtool_eeprom eeprom; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->get_eeprom || !ops->get_eeprom_len) + return -EOPNOTSUPP; + + if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) + return -EFAULT; + + /* Check for wrap and zero */ + if (eeprom.offset + eeprom.len <= eeprom.offset) + return -EINVAL; + + /* Check for exceeding total eeprom len */ + if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) + return -EINVAL; + + data = kmalloc(eeprom.len, GFP_USER); + if (!data) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) + goto out; + + ret = ops->get_eeprom(dev, &eeprom, data); + if (ret) + goto out; + + ret = -EFAULT; + if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) + goto out; + if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) +{ + struct ethtool_eeprom eeprom; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->set_eeprom || !ops->get_eeprom_len) + return -EOPNOTSUPP; + + if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) + return -EFAULT; + + /* Check for wrap and zero */ + if (eeprom.offset + eeprom.len <= eeprom.offset) + return -EINVAL; + + /* Check for exceeding total eeprom len */ + if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) + return -EINVAL; + + data = kmalloc(eeprom.len, GFP_USER); + if (!data) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) + goto out; + + ret = ops->set_eeprom(dev, &eeprom, data); + if (ret) + goto out; + + if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) + ret = -EFAULT; + +out: + kfree(data); + return ret; +} + +static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) +{ + struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; + + if (!ethtool_ops->get_coalesce) + return -EOPNOTSUPP; + + ethtool_ops->get_coalesce(dev, &coalesce); + + if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) + return -EFAULT; + return 0; +} + +static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) +{ + struct ethtool_coalesce coalesce; + + if (!ethtool_ops->get_coalesce) + return -EOPNOTSUPP; + + if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) + return -EFAULT; + + return ethtool_ops->set_coalesce(dev, &coalesce); +} + +static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; + + if (!ethtool_ops->get_ringparam) + return -EOPNOTSUPP; + + ethtool_ops->get_ringparam(dev, &ringparam); + + if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) + return -EFAULT; + return 0; +} + +static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_ringparam ringparam; + + if (!ethtool_ops->get_ringparam) + return -EOPNOTSUPP; + + if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) + return -EFAULT; + + return ethtool_ops->set_ringparam(dev, &ringparam); +} + +static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; + + if (!ethtool_ops->get_pauseparam) + return -EOPNOTSUPP; + + ethtool_ops->get_pauseparam(dev, &pauseparam); + + if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) + return -EFAULT; + return 0; +} + +static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_pauseparam pauseparam; + + if (!ethtool_ops->get_pauseparam) + return -EOPNOTSUPP; + + if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) + return -EFAULT; + + return ethtool_ops->set_pauseparam(dev, &pauseparam); +} + +static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GRXCSUM }; + + if (!ethtool_ops->get_rx_csum) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_rx_csum(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_rx_csum) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + ethtool_ops->set_rx_csum(dev, edata.data); + return 0; +} + +static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + + if (!ethtool_ops->get_tx_csum) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_tx_csum(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_tx_csum) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_tx_csum(dev, edata.data); +} + +static int ethtool_get_sg(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GSG }; + + if (!ethtool_ops->get_sg) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_sg(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_sg(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_sg) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_sg(dev, edata.data); +} + +static int ethtool_get_tso(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GTSO }; + + if (!ethtool_ops->get_tso) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_tso(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_tso(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_tso) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_tso(dev, edata.data); +} + +static int ethtool_self_test(struct net_device *dev, char *useraddr) +{ + struct ethtool_test test; + struct ethtool_ops *ops = ethtool_ops; + u64 *data; + int ret; + + if (!ops->self_test || !ops->self_test_count) + return -EOPNOTSUPP; + + if (copy_from_user(&test, useraddr, sizeof(test))) + return -EFAULT; + + test.len = ops->self_test_count(dev); + data = kmalloc(test.len * sizeof(u64), GFP_USER); + if (!data) + return -ENOMEM; + + ops->self_test(dev, &test, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &test, sizeof(test))) + goto out; + useraddr += sizeof(test); + if (copy_to_user(useraddr, data, test.len * sizeof(u64))) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_get_strings(struct net_device *dev, void *useraddr) +{ + struct ethtool_gstrings gstrings; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->get_strings) + return -EOPNOTSUPP; + + if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) + return -EFAULT; + + switch (gstrings.string_set) { + case ETH_SS_TEST: + if (!ops->self_test_count) + return -EOPNOTSUPP; + gstrings.len = ops->self_test_count(dev); + break; + case ETH_SS_STATS: + if (!ops->get_stats_count) + return -EOPNOTSUPP; + gstrings.len = ops->get_stats_count(dev); + break; + default: + return -EINVAL; + } + + data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); + if (!data) + return -ENOMEM; + + ops->get_strings(dev, gstrings.string_set, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) + goto out; + useraddr += sizeof(gstrings); + if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_phys_id(struct net_device *dev, void *useraddr) +{ + struct ethtool_value id; + + if (!ethtool_ops->phys_id) + return -EOPNOTSUPP; + + if (copy_from_user(&id, useraddr, sizeof(id))) + return -EFAULT; + + return ethtool_ops->phys_id(dev, id.data); +} + +static int ethtool_get_stats(struct net_device *dev, void *useraddr) +{ + struct ethtool_stats stats; + struct ethtool_ops *ops = ethtool_ops; + u64 *data; + int ret; + + if (!ops->get_ethtool_stats || !ops->get_stats_count) + return -EOPNOTSUPP; + + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + + stats.n_stats = ops->get_stats_count(dev); + data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); + if (!data) + return -ENOMEM; + + ops->get_ethtool_stats(dev, &stats, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); + if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +/* The main entry point in this file. Called from net/core/dev.c */ + +#define ETHTOOL_OPS_COMPAT +int ethtool_ioctl(struct ifreq *ifr) +{ + struct net_device *dev = __dev_get_by_name(ifr->ifr_name); + void *useraddr = (void *) ifr->ifr_data; + u32 ethcmd; + + /* + * XXX: This can be pushed down into the ethtool_* handlers that + * need it. Keep existing behavior for the moment. + */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!dev || !netif_device_present(dev)) + return -ENODEV; + + if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GSET: + return ethtool_get_settings(dev, useraddr); + case ETHTOOL_SSET: + return ethtool_set_settings(dev, useraddr); + case ETHTOOL_GDRVINFO: + return ethtool_get_drvinfo(dev, useraddr); + case ETHTOOL_GREGS: + return ethtool_get_regs(dev, useraddr); + case ETHTOOL_GWOL: + return ethtool_get_wol(dev, useraddr); + case ETHTOOL_SWOL: + return ethtool_set_wol(dev, useraddr); + case ETHTOOL_GMSGLVL: + return ethtool_get_msglevel(dev, useraddr); + case ETHTOOL_SMSGLVL: + return ethtool_set_msglevel(dev, useraddr); + case ETHTOOL_NWAY_RST: + return ethtool_nway_reset(dev); + case ETHTOOL_GLINK: + return ethtool_get_link(dev, useraddr); + case ETHTOOL_GEEPROM: + return ethtool_get_eeprom(dev, useraddr); + case ETHTOOL_SEEPROM: + return ethtool_set_eeprom(dev, useraddr); + case ETHTOOL_GCOALESCE: + return ethtool_get_coalesce(dev, useraddr); + case ETHTOOL_SCOALESCE: + return ethtool_set_coalesce(dev, useraddr); + case ETHTOOL_GRINGPARAM: + return ethtool_get_ringparam(dev, useraddr); + case ETHTOOL_SRINGPARAM: + return ethtool_set_ringparam(dev, useraddr); + case ETHTOOL_GPAUSEPARAM: + return ethtool_get_pauseparam(dev, useraddr); + case ETHTOOL_SPAUSEPARAM: + return ethtool_set_pauseparam(dev, useraddr); + case ETHTOOL_GRXCSUM: + return ethtool_get_rx_csum(dev, useraddr); + case ETHTOOL_SRXCSUM: + return ethtool_set_rx_csum(dev, useraddr); + case ETHTOOL_GTXCSUM: + return ethtool_get_tx_csum(dev, useraddr); + case ETHTOOL_STXCSUM: + return ethtool_set_tx_csum(dev, useraddr); + case ETHTOOL_GSG: + return ethtool_get_sg(dev, useraddr); + case ETHTOOL_SSG: + return ethtool_set_sg(dev, useraddr); + case ETHTOOL_GTSO: + return ethtool_get_tso(dev, useraddr); + case ETHTOOL_STSO: + return ethtool_set_tso(dev, useraddr); + case ETHTOOL_TEST: + return ethtool_self_test(dev, useraddr); + case ETHTOOL_GSTRINGS: + return ethtool_get_strings(dev, useraddr); + case ETHTOOL_PHYS_ID: + return ethtool_phys_id(dev, useraddr); + case ETHTOOL_GSTATS: + return ethtool_get_stats(dev, useraddr); + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; +} + +#define mii_if_info _kc_mii_if_info +struct _kc_mii_if_info { + int phy_id; + int advertising; + int phy_id_mask; + int reg_num_mask; + + unsigned int full_duplex : 1; /* is full duplex? */ + unsigned int force_media : 1; /* is autoneg. disabled? */ + + struct net_device *dev; + int (*mdio_read) (struct net_device *dev, int phy_id, int location); + void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val); +}; + +struct ethtool_cmd; +struct mii_ioctl_data; + +#undef mii_link_ok +#define mii_link_ok _kc_mii_link_ok +#undef mii_nway_restart +#define mii_nway_restart _kc_mii_nway_restart +#undef mii_ethtool_gset +#define mii_ethtool_gset _kc_mii_ethtool_gset +#undef mii_ethtool_sset +#define mii_ethtool_sset _kc_mii_ethtool_sset +#undef mii_check_link +#define mii_check_link _kc_mii_check_link +#undef generic_mii_ioctl +#define generic_mii_ioctl _kc_generic_mii_ioctl +extern int _kc_mii_link_ok (struct mii_if_info *mii); +extern int _kc_mii_nway_restart (struct mii_if_info *mii); +extern int _kc_mii_ethtool_gset(struct mii_if_info *mii, + struct ethtool_cmd *ecmd); +extern int _kc_mii_ethtool_sset(struct mii_if_info *mii, + struct ethtool_cmd *ecmd); +extern void _kc_mii_check_link (struct mii_if_info *mii); +extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, + struct mii_ioctl_data *mii_data, int cmd, + unsigned int *duplex_changed); + + +struct _kc_pci_dev_ext { + struct pci_dev *dev; + void *pci_drvdata; + struct pci_driver *driver; +}; + +struct _kc_net_dev_ext { + struct net_device *dev; + unsigned int carrier; +}; + + +/**************************************/ +/* mii support */ + +int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) +{ + struct net_device *dev = mii->dev; + u32 advert, bmcr, lpa, nego; + + ecmd->supported = + (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); + + /* only supports twisted-pair */ + ecmd->port = PORT_MII; + + /* only supports internal transceiver */ + ecmd->transceiver = XCVR_INTERNAL; + + /* this isn't fully supported at higher layers */ + ecmd->phy_address = mii->phy_id; + + ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; + advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); + if (advert & ADVERTISE_10HALF) + ecmd->advertising |= ADVERTISED_10baseT_Half; + if (advert & ADVERTISE_10FULL) + ecmd->advertising |= ADVERTISED_10baseT_Full; + if (advert & ADVERTISE_100HALF) + ecmd->advertising |= ADVERTISED_100baseT_Half; + if (advert & ADVERTISE_100FULL) + ecmd->advertising |= ADVERTISED_100baseT_Full; + + bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); + lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); + if (bmcr & BMCR_ANENABLE) { + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->autoneg = AUTONEG_ENABLE; + + nego = mii_nway_result(advert & lpa); + if (nego == LPA_100FULL || nego == LPA_100HALF) + ecmd->speed = SPEED_100; + else + ecmd->speed = SPEED_10; + if (nego == LPA_100FULL || nego == LPA_10FULL) { + ecmd->duplex = DUPLEX_FULL; + mii->full_duplex = 1; + } else { + ecmd->duplex = DUPLEX_HALF; + mii->full_duplex = 0; + } + } else { + ecmd->autoneg = AUTONEG_DISABLE; + + ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; + ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; + } + + /* ignore maxtxpkt, maxrxpkt for now */ + + return 0; +} + +int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) +{ + struct net_device *dev = mii->dev; + + if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) + return -EINVAL; + if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) + return -EINVAL; + if (ecmd->port != PORT_MII) + return -EINVAL; + if (ecmd->transceiver != XCVR_INTERNAL) + return -EINVAL; + if (ecmd->phy_address != mii->phy_id) + return -EINVAL; + if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) + return -EINVAL; + + /* ignore supported, maxtxpkt, maxrxpkt */ + + if (ecmd->autoneg == AUTONEG_ENABLE) { + u32 bmcr, advert, tmp; + + if ((ecmd->advertising & (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full)) == 0) + return -EINVAL; + + /* advertise only what has been requested */ + advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); + tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + if (ADVERTISED_10baseT_Half) + tmp |= ADVERTISE_10HALF; + if (ADVERTISED_10baseT_Full) + tmp |= ADVERTISE_10FULL; + if (ADVERTISED_100baseT_Half) + tmp |= ADVERTISE_100HALF; + if (ADVERTISED_100baseT_Full) + tmp |= ADVERTISE_100FULL; + if (advert != tmp) { + mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); + mii->advertising = tmp; + } + + /* turn on autonegotiation, and force a renegotiate */ + bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); + bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); + mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); + + mii->force_media = 0; + } else { + u32 bmcr, tmp; + + /* turn off auto negotiation, set speed and duplexity */ + bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); + tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX); + if (ecmd->speed == SPEED_100) + tmp |= BMCR_SPEED100; + if (ecmd->duplex == DUPLEX_FULL) { + tmp |= BMCR_FULLDPLX; + mii->full_duplex = 1; + } else + mii->full_duplex = 0; + if (bmcr != tmp) + mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); + + mii->force_media = 1; + } + return 0; +} + +int _kc_mii_link_ok (struct mii_if_info *mii) +{ + /* first, a dummy read, needed to latch some MII phys */ + mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); + if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) + return 1; + return 0; +} + +int _kc_mii_nway_restart (struct mii_if_info *mii) +{ + int bmcr; + int r = -EINVAL; + + /* if autoneg is off, it's an error */ + bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); + + if (bmcr & BMCR_ANENABLE) { + bmcr |= BMCR_ANRESTART; + mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); + r = 0; + } + + return r; +} + +void _kc_mii_check_link (struct mii_if_info *mii) +{ + int cur_link = mii_link_ok(mii); + int prev_link = netif_carrier_ok(mii->dev); + + if (cur_link && !prev_link) + netif_carrier_on(mii->dev); + else if (prev_link && !cur_link) + netif_carrier_off(mii->dev); +} + +int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, + struct mii_ioctl_data *mii_data, int cmd, + unsigned int *duplex_chg_out) +{ + int rc = 0; + unsigned int duplex_changed = 0; + + if (duplex_chg_out) + *duplex_chg_out = 0; + + mii_data->phy_id &= mii_if->phy_id_mask; + mii_data->reg_num &= mii_if->reg_num_mask; + + switch(cmd) { + case SIOCDEVPRIVATE: /* binary compat, remove in 2.5 */ + case SIOCGMIIPHY: + mii_data->phy_id = mii_if->phy_id; + /* fall through */ + + case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */ + case SIOCGMIIREG: + mii_data->val_out = + mii_if->mdio_read(mii_if->dev, mii_data->phy_id, + mii_data->reg_num); + break; + + case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */ + case SIOCSMIIREG: { + u16 val = mii_data->val_in; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (mii_data->phy_id == mii_if->phy_id) { + switch(mii_data->reg_num) { + case MII_BMCR: { + unsigned int new_duplex = 0; + if (val & (BMCR_RESET|BMCR_ANENABLE)) + mii_if->force_media = 0; + else + mii_if->force_media = 1; + if (mii_if->force_media && + (val & BMCR_FULLDPLX)) + new_duplex = 1; + if (mii_if->full_duplex != new_duplex) { + duplex_changed = 1; + mii_if->full_duplex = new_duplex; + } + break; + } + case MII_ADVERTISE: + mii_if->advertising = val; + break; + default: + /* do nothing */ + break; + } + } + + mii_if->mdio_write(mii_if->dev, mii_data->phy_id, + mii_data->reg_num, val); + break; + } + + default: + rc = -EOPNOTSUPP; + break; + } + + if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) + *duplex_chg_out = 1; + + return rc; +} + --- linux-2.6.27.orig/ubuntu/e1000e/e1000_manage.c +++ linux-2.6.27/ubuntu/e1000e/e1000_manage.c @@ -0,0 +1,383 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "e1000_hw.h" + +static u8 e1000_calculate_checksum(u8 *buffer, u32 length); + +/** + * e1000_calculate_checksum - Calculate checksum for buffer + * @buffer: pointer to EEPROM + * @length: size of EEPROM to calculate a checksum for + * + * Calculates the checksum for some buffer on a specified length. The + * checksum calculated is returned. + **/ +static u8 e1000_calculate_checksum(u8 *buffer, u32 length) +{ + u32 i; + u8 sum = 0; + + DEBUGFUNC("e1000_calculate_checksum"); + + if (!buffer) + return 0; + + for (i = 0; i < length; i++) + sum += buffer[i]; + + return (u8) (0 - sum); +} + +/** + * e1000_mng_enable_host_if_generic - Checks host interface is enabled + * @hw: pointer to the HW structure + * + * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND + * + * This function checks whether the HOST IF is enabled for command operation + * and also checks whether the previous command is completed. It busy waits + * in case of previous command is not completed. + **/ +s32 e1000_mng_enable_host_if_generic(struct e1000_hw * hw) +{ + u32 hicr; + s32 ret_val = E1000_SUCCESS; + u8 i; + + DEBUGFUNC("e1000_mng_enable_host_if_generic"); + + /* Check that the host interface is enabled. */ + hicr = E1000_READ_REG(hw, E1000_HICR); + if ((hicr & E1000_HICR_EN) == 0) { + DEBUGOUT("E1000_HOST_EN bit disabled.\n"); + ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; + goto out; + } + /* check the previous command is completed */ + for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { + hicr = E1000_READ_REG(hw, E1000_HICR); + if (!(hicr & E1000_HICR_C)) + break; + msec_delay_irq(1); + } + + if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { + DEBUGOUT("Previous command timeout failed .\n"); + ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_check_mng_mode_generic - Generic check management mode + * @hw: pointer to the HW structure + * + * Reads the firmware semaphore register and returns true (>0) if + * manageability is enabled, else false (0). + **/ +bool e1000_check_mng_mode_generic(struct e1000_hw *hw) +{ + u32 fwsm; + + DEBUGFUNC("e1000_check_mng_mode_generic"); + + fwsm = E1000_READ_REG(hw, E1000_FWSM); + + return ((fwsm & E1000_FWSM_MODE_MASK) == + (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); +} + +/** + * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX + * @hw: pointer to the HW structure + * + * Enables packet filtering on transmit packets if manageability is enabled + * and host interface is enabled. + **/ +bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) +{ + struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; + u32 *buffer = (u32 *)&hw->mng_cookie; + u32 offset; + s32 ret_val, hdr_csum, csum; + u8 i, len; + bool tx_filter = true; + + DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); + + /* No manageability, no filtering */ + if (!hw->mac.ops.check_mng_mode(hw)) { + tx_filter = false; + goto out; + } + + /* + * If we can't read from the host interface for whatever + * reason, disable filtering. + */ + ret_val = hw->mac.ops.mng_enable_host_if(hw); + if (ret_val != E1000_SUCCESS) { + tx_filter = false; + goto out; + } + + /* Read in the header. Length and offset are in dwords. */ + len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; + offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; + for (i = 0; i < len; i++) { + *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, + E1000_HOST_IF, + offset + i); + } + hdr_csum = hdr->checksum; + hdr->checksum = 0; + csum = e1000_calculate_checksum((u8 *)hdr, + E1000_MNG_DHCP_COOKIE_LENGTH); + /* + * If either the checksums or signature don't match, then + * the cookie area isn't considered valid, in which case we + * take the safe route of assuming Tx filtering is enabled. + */ + if (hdr_csum != csum) + goto out; + if (hdr->signature != E1000_IAMT_SIGNATURE) + goto out; + + /* Cookie area is valid, make the final check for filtering. */ + if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) + tx_filter = false; + +out: + hw->mac.tx_pkt_filtering = tx_filter; + return tx_filter; +} + +/** + * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface + * @hw: pointer to the HW structure + * @buffer: pointer to the host interface + * @length: size of the buffer + * + * Writes the DHCP information to the host interface. + **/ +s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 *buffer, + u16 length) +{ + struct e1000_host_mng_command_header hdr; + s32 ret_val; + u32 hicr; + + DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); + + hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; + hdr.command_length = length; + hdr.reserved1 = 0; + hdr.reserved2 = 0; + hdr.checksum = 0; + + /* Enable the host interface */ + ret_val = hw->mac.ops.mng_enable_host_if(hw); + if (ret_val) + goto out; + + /* Populate the host interface with the contents of "buffer". */ + ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, + sizeof(hdr), &(hdr.checksum)); + if (ret_val) + goto out; + + /* Write the manageability command header */ + ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); + if (ret_val) + goto out; + + /* Tell the ARC a new command is pending. */ + hicr = E1000_READ_REG(hw, E1000_HICR); + E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); + +out: + return ret_val; +} + +/** + * e1000_mng_write_cmd_header_generic - Writes manageability command header + * @hw: pointer to the HW structure + * @hdr: pointer to the host interface command header + * + * Writes the command header after does the checksum calculation. + **/ +s32 e1000_mng_write_cmd_header_generic(struct e1000_hw * hw, + struct e1000_host_mng_command_header * hdr) +{ + u16 i, length = sizeof(struct e1000_host_mng_command_header); + + DEBUGFUNC("e1000_mng_write_cmd_header_generic"); + + /* Write the whole command header structure with new checksum. */ + + hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); + + length >>= 2; + /* Write the relevant command block into the ram area. */ + for (i = 0; i < length; i++) { + E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, + *((u32 *) hdr + i)); + E1000_WRITE_FLUSH(hw); + } + + return E1000_SUCCESS; +} + +/** + * e1000_mng_host_if_write_generic - Write to the manageability host interface + * @hw: pointer to the HW structure + * @buffer: pointer to the host interface buffer + * @length: size of the buffer + * @offset: location in the buffer to write to + * @sum: sum of the data (not checksum) + * + * This function writes the buffer content at the offset given on the host if. + * It also does alignment considerations to do the writes in most efficient + * way. Also fills up the sum of the buffer in *buffer parameter. + **/ +s32 e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 *buffer, + u16 length, u16 offset, u8 *sum) +{ + u8 *tmp; + u8 *bufptr = buffer; + u32 data = 0; + s32 ret_val = E1000_SUCCESS; + u16 remaining, i, j, prev_bytes; + + DEBUGFUNC("e1000_mng_host_if_write_generic"); + + /* sum = only sum of the data and it is not checksum */ + + if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { + ret_val = -E1000_ERR_PARAM; + goto out; + } + + tmp = (u8 *)&data; + prev_bytes = offset & 0x3; + offset >>= 2; + + if (prev_bytes) { + data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); + for (j = prev_bytes; j < sizeof(u32); j++) { + *(tmp + j) = *bufptr++; + *sum += *(tmp + j); + } + E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); + length -= j - prev_bytes; + offset++; + } + + remaining = length & 0x3; + length -= remaining; + + /* Calculate length in DWORDs */ + length >>= 2; + + /* + * The device driver writes the relevant command block into the + * ram area. + */ + for (i = 0; i < length; i++) { + for (j = 0; j < sizeof(u32); j++) { + *(tmp + j) = *bufptr++; + *sum += *(tmp + j); + } + + E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); + } + if (remaining) { + for (j = 0; j < sizeof(u32); j++) { + if (j < remaining) + *(tmp + j) = *bufptr++; + else + *(tmp + j) = 0; + + *sum += *(tmp + j); + } + E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); + } + +out: + return ret_val; +} + +/** + * e1000_enable_mng_pass_thru - Enable processing of ARP's + * @hw: pointer to the HW structure + * + * Verifies the hardware needs to allow ARPs to be processed by the host. + **/ +bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) +{ + u32 manc; + u32 fwsm, factps; + bool ret_val = false; + + DEBUGFUNC("e1000_enable_mng_pass_thru"); + + if (!hw->mac.asf_firmware_present) + goto out; + + manc = E1000_READ_REG(hw, E1000_MANC); + + if (!(manc & E1000_MANC_RCV_TCO_EN) || + !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) + goto out; + + if (hw->mac.arc_subsystem_valid) { + fwsm = E1000_READ_REG(hw, E1000_FWSM); + factps = E1000_READ_REG(hw, E1000_FACTPS); + + if (!(factps & E1000_FACTPS_MNGCG) && + ((fwsm & E1000_FWSM_MODE_MASK) == + (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { + ret_val = true; + goto out; + } + } else { + if ((manc & E1000_MANC_SMBUS_EN) && + !(manc & E1000_MANC_ASF_EN)) { + ret_val = true; + goto out; + } + } + +out: + return ret_val; +} + --- linux-2.6.27.orig/ubuntu/e1000e/kcompat.h +++ linux-2.6.27/ubuntu/e1000e/kcompat.h @@ -0,0 +1,1612 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _KCOMPAT_H_ +#define _KCOMPAT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* NAPI enable/disable flags here */ + +#ifdef DRIVER_E1000E +#define CONFIG_E1000E_NAPI +#define NAPI +#endif + +#ifdef _E1000_H_ +#ifdef CONFIG_E1000_NAPI +#define NAPI +#endif +#ifdef E1000_NAPI +#undef NAPI +#define NAPI +#endif +#ifdef E1000E_NAPI +#undef NAPI +#define NAPI +#endif +#ifdef E1000_NO_NAPI +#undef NAPI +#endif +#ifdef E1000E_NO_NAPI +#undef NAPI +#endif +#endif + + + + + + +#ifdef DRIVER_E1000E +#define adapter_struct e1000_adapter +#define CONFIG_E1000E_MSIX +#endif + + + + +/* and finally set defines so that the code sees the changes */ +#ifdef NAPI +#ifndef CONFIG_E1000_NAPI +#define CONFIG_E1000_NAPI +#endif +#ifndef CONFIG_E1000E_NAPI +#define CONFIG_E1000E_NAPI +#endif +#else +#undef CONFIG_E1000_NAPI +#undef CONFIG_E1000E_NAPI +#undef CONFIG_IXGB_NAPI +#endif + +/* packet split disable/enable */ +#ifdef DISABLE_PACKET_SPLIT +#undef CONFIG_E1000_DISABLE_PACKET_SPLIT +#define CONFIG_E1000_DISABLE_PACKET_SPLIT +#undef CONFIG_IGB_DISABLE_PACKET_SPLIT +#define CONFIG_IGB_DISABLE_PACKET_SPLIT +#endif + +/* MSI compatibility code for all kernels and drivers */ +#ifdef DISABLE_PCI_MSI +#undef CONFIG_PCI_MSI +#endif +#ifndef CONFIG_PCI_MSI +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) +struct msix_entry { + u16 vector; /* kernel uses to write allocated vector */ + u16 entry; /* driver uses to specify entry, OS writes */ +}; +#endif +#define pci_enable_msi(a) -ENOTSUPP +#define pci_disable_msi(a) do {} while (0) +#define pci_enable_msix(a, b, c) -ENOTSUPP +#define pci_disable_msix(a) do {} while (0) +#define msi_remove_pci_irq_vectors(a) do {} while (0) +#endif /* CONFIG_PCI_MSI */ +#ifdef DISABLE_PM +#undef CONFIG_PM +#endif + +#ifdef DISABLE_NET_POLL_CONTROLLER +#undef CONFIG_NET_POLL_CONTROLLER +#endif + +#ifndef PMSG_SUSPEND +#define PMSG_SUSPEND 3 +#endif + +/* generic boolean compatibility */ +#undef TRUE +#undef FALSE +#define TRUE true +#define FALSE false +#ifdef GCC_VERSION +#if ( GCC_VERSION < 3000 ) +#define _Bool char +#endif +#endif +#ifndef bool +#define bool _Bool +#define true 1 +#define false 0 +#endif + + +#ifndef module_param +#define module_param(v,t,p) MODULE_PARM(v, "i"); +#endif + +#ifndef DMA_64BIT_MASK +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#endif + +#ifndef DMA_32BIT_MASK +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#endif + +#ifndef PCI_CAP_ID_EXP +#define PCI_CAP_ID_EXP 0x10 +#endif + +#ifndef mmiowb +#ifdef CONFIG_IA64 +#define mmiowb() asm volatile ("mf.a" ::: "memory") +#else +#define mmiowb() +#endif +#endif + +#ifndef IRQ_HANDLED +#define irqreturn_t void +#define IRQ_HANDLED +#define IRQ_NONE +#endif + +#ifndef SET_NETDEV_DEV +#define SET_NETDEV_DEV(net, pdev) +#endif + +#ifndef HAVE_FREE_NETDEV +#define free_netdev(x) kfree(x) +#endif + +#ifdef HAVE_POLL_CONTROLLER +#define CONFIG_NET_POLL_CONTROLLER +#endif + +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 +#endif + +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 +#endif + +#ifndef NETDEV_TX_LOCKED +#define NETDEV_TX_LOCKED -1 +#endif + +#ifndef SKB_DATAREF_SHIFT +/* if we do not have the infrastructure to detect if skb_header is cloned + just return false in all cases */ +#define skb_header_cloned(x) 0 +#endif + +#ifndef NETIF_F_GSO +#define gso_size tso_size +#define gso_segs tso_segs +#endif + +#ifndef CHECKSUM_PARTIAL +#define CHECKSUM_PARTIAL CHECKSUM_HW +#define CHECKSUM_COMPLETE CHECKSUM_HW +#endif + +#ifndef __read_mostly +#define __read_mostly +#endif + +#ifndef HAVE_NETIF_MSG +#define HAVE_NETIF_MSG 1 +enum { + NETIF_MSG_DRV = 0x0001, + NETIF_MSG_PROBE = 0x0002, + NETIF_MSG_LINK = 0x0004, + NETIF_MSG_TIMER = 0x0008, + NETIF_MSG_IFDOWN = 0x0010, + NETIF_MSG_IFUP = 0x0020, + NETIF_MSG_RX_ERR = 0x0040, + NETIF_MSG_TX_ERR = 0x0080, + NETIF_MSG_TX_QUEUED = 0x0100, + NETIF_MSG_INTR = 0x0200, + NETIF_MSG_TX_DONE = 0x0400, + NETIF_MSG_RX_STATUS = 0x0800, + NETIF_MSG_PKTDATA = 0x1000, + NETIF_MSG_HW = 0x2000, + NETIF_MSG_WOL = 0x4000, +}; + +#else +#define NETIF_MSG_HW 0x2000 +#define NETIF_MSG_WOL 0x4000 +#endif /* HAVE_NETIF_MSG */ + +#ifndef MII_RESV1 +#define MII_RESV1 0x17 /* Reserved... */ +#endif + +#ifndef unlikely +#define unlikely(_x) _x +#define likely(_x) _x +#endif + +#ifndef WARN_ON +#define WARN_ON(x) +#endif + +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif + +#ifndef num_online_cpus +#define num_online_cpus() smp_num_cpus +#endif + +#ifndef _LINUX_RANDOM_H +#include +#endif + +#ifndef DECLARE_BITMAP +#ifndef BITS_TO_LONGS +#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#endif +#define DECLARE_BITMAP(name,bits) long name[BITS_TO_LONGS(bits)] +#endif + +#ifndef VLAN_HLEN +#define VLAN_HLEN 4 +#endif + +#ifndef VLAN_ETH_HLEN +#define VLAN_ETH_HLEN 18 +#endif + +#ifndef VLAN_ETH_FRAME_LEN +#define VLAN_ETH_FRAME_LEN 1518 +#endif + +#ifndef DCA_GET_TAG_TWO_ARGS +#define dca3_get_tag(a,b) dca_get_tag(b) +#endif + + +/*****************************************************************************/ +/* Installations with ethtool version without eeprom, adapter id, or statistics + * support */ + +#ifndef ETH_GSTRING_LEN +#define ETH_GSTRING_LEN 32 +#endif + +#ifndef ETHTOOL_GSTATS +#define ETHTOOL_GSTATS 0x1d +#undef ethtool_drvinfo +#define ethtool_drvinfo k_ethtool_drvinfo +struct k_ethtool_drvinfo { + u32 cmd; + char driver[32]; + char version[32]; + char fw_version[32]; + char bus_info[32]; + char reserved1[32]; + char reserved2[16]; + u32 n_stats; + u32 testinfo_len; + u32 eedump_len; + u32 regdump_len; +}; + +struct ethtool_stats { + u32 cmd; + u32 n_stats; + u64 data[0]; +}; +#endif /* ETHTOOL_GSTATS */ + +#ifndef ETHTOOL_PHYS_ID +#define ETHTOOL_PHYS_ID 0x1c +#endif /* ETHTOOL_PHYS_ID */ + +#ifndef ETHTOOL_GSTRINGS +#define ETHTOOL_GSTRINGS 0x1b +enum ethtool_stringset { + ETH_SS_TEST = 0, + ETH_SS_STATS, +}; +struct ethtool_gstrings { + u32 cmd; /* ETHTOOL_GSTRINGS */ + u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ + u32 len; /* number of strings in the string set */ + u8 data[0]; +}; +#endif /* ETHTOOL_GSTRINGS */ + +#ifndef ETHTOOL_TEST +#define ETHTOOL_TEST 0x1a +enum ethtool_test_flags { + ETH_TEST_FL_OFFLINE = (1 << 0), + ETH_TEST_FL_FAILED = (1 << 1), +}; +struct ethtool_test { + u32 cmd; + u32 flags; + u32 reserved; + u32 len; + u64 data[0]; +}; +#endif /* ETHTOOL_TEST */ + +#ifndef ETHTOOL_GEEPROM +#define ETHTOOL_GEEPROM 0xb +#undef ETHTOOL_GREGS +struct ethtool_eeprom { + u32 cmd; + u32 magic; + u32 offset; + u32 len; + u8 data[0]; +}; + +struct ethtool_value { + u32 cmd; + u32 data; +}; +#endif /* ETHTOOL_GEEPROM */ + +#ifndef ETHTOOL_GLINK +#define ETHTOOL_GLINK 0xa +#endif /* ETHTOOL_GLINK */ + +#ifndef ETHTOOL_GREGS +#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ +#define ethtool_regs _kc_ethtool_regs +/* for passing big chunks of data */ +struct _kc_ethtool_regs { + u32 cmd; + u32 version; /* driver-specific, indicates different chips/revs */ + u32 len; /* bytes */ + u8 data[0]; +}; +#endif /* ETHTOOL_GREGS */ + +#ifndef ETHTOOL_GMSGLVL +#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ +#endif +#ifndef ETHTOOL_SMSGLVL +#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ +#endif +#ifndef ETHTOOL_NWAY_RST +#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ +#endif +#ifndef ETHTOOL_GLINK +#define ETHTOOL_GLINK 0x0000000a /* Get link status */ +#endif +#ifndef ETHTOOL_GEEPROM +#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ +#endif +#ifndef ETHTOOL_SEEPROM +#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ +#endif +#ifndef ETHTOOL_GCOALESCE +#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ +/* for configuring coalescing parameters of chip */ +#define ethtool_coalesce _kc_ethtool_coalesce +struct _kc_ethtool_coalesce { + u32 cmd; /* ETHTOOL_{G,S}COALESCE */ + + /* How many usecs to delay an RX interrupt after + * a packet arrives. If 0, only rx_max_coalesced_frames + * is used. + */ + u32 rx_coalesce_usecs; + + /* How many packets to delay an RX interrupt after + * a packet arrives. If 0, only rx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause RX interrupts to never be + * generated. + */ + u32 rx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being serviced by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 rx_coalesce_usecs_irq; + u32 rx_max_coalesced_frames_irq; + + /* How many usecs to delay a TX interrupt after + * a packet is sent. If 0, only tx_max_coalesced_frames + * is used. + */ + u32 tx_coalesce_usecs; + + /* How many packets to delay a TX interrupt after + * a packet is sent. If 0, only tx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause TX interrupts to never be + * generated. + */ + u32 tx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being serviced by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 tx_coalesce_usecs_irq; + u32 tx_max_coalesced_frames_irq; + + /* How many usecs to delay in-memory statistics + * block updates. Some drivers do not have an in-memory + * statistic block, and in such cases this value is ignored. + * This value must not be zero. + */ + u32 stats_block_coalesce_usecs; + + /* Adaptive RX/TX coalescing is an algorithm implemented by + * some drivers to improve latency under low packet rates and + * improve throughput under high packet rates. Some drivers + * only implement one of RX or TX adaptive coalescing. Anything + * not implemented by the driver causes these values to be + * silently ignored. + */ + u32 use_adaptive_rx_coalesce; + u32 use_adaptive_tx_coalesce; + + /* When the packet rate (measured in packets per second) + * is below pkt_rate_low, the {rx,tx}_*_low parameters are + * used. + */ + u32 pkt_rate_low; + u32 rx_coalesce_usecs_low; + u32 rx_max_coalesced_frames_low; + u32 tx_coalesce_usecs_low; + u32 tx_max_coalesced_frames_low; + + /* When the packet rate is below pkt_rate_high but above + * pkt_rate_low (both measured in packets per second) the + * normal {rx,tx}_* coalescing parameters are used. + */ + + /* When the packet rate is (measured in packets per second) + * is above pkt_rate_high, the {rx,tx}_*_high parameters are + * used. + */ + u32 pkt_rate_high; + u32 rx_coalesce_usecs_high; + u32 rx_max_coalesced_frames_high; + u32 tx_coalesce_usecs_high; + u32 tx_max_coalesced_frames_high; + + /* How often to do adaptive coalescing packet rate sampling, + * measured in seconds. Must not be zero. + */ + u32 rate_sample_interval; +}; +#endif /* ETHTOOL_GCOALESCE */ + +#ifndef ETHTOOL_SCOALESCE +#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ +#endif +#ifndef ETHTOOL_GRINGPARAM +#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ +/* for configuring RX/TX ring parameters */ +#define ethtool_ringparam _kc_ethtool_ringparam +struct _kc_ethtool_ringparam { + u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ + + /* Read only attributes. These indicate the maximum number + * of pending RX/TX ring entries the driver will allow the + * user to set. + */ + u32 rx_max_pending; + u32 rx_mini_max_pending; + u32 rx_jumbo_max_pending; + u32 tx_max_pending; + + /* Values changeable by the user. The valid values are + * in the range 1 to the "*_max_pending" counterpart above. + */ + u32 rx_pending; + u32 rx_mini_pending; + u32 rx_jumbo_pending; + u32 tx_pending; +}; +#endif /* ETHTOOL_GRINGPARAM */ + +#ifndef ETHTOOL_SRINGPARAM +#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ +#endif +#ifndef ETHTOOL_GPAUSEPARAM +#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ +/* for configuring link flow control parameters */ +#define ethtool_pauseparam _kc_ethtool_pauseparam +struct _kc_ethtool_pauseparam { + u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ + + /* If the link is being auto-negotiated (via ethtool_cmd.autoneg + * being true) the user may set 'autoneg' here non-zero to have the + * pause parameters be auto-negotiated too. In such a case, the + * {rx,tx}_pause values below determine what capabilities are + * advertised. + * + * If 'autoneg' is zero or the link is not being auto-negotiated, + * then {rx,tx}_pause force the driver to use/not-use pause + * flow control. + */ + u32 autoneg; + u32 rx_pause; + u32 tx_pause; +}; +#endif /* ETHTOOL_GPAUSEPARAM */ + +#ifndef ETHTOOL_SPAUSEPARAM +#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ +#endif +#ifndef ETHTOOL_GRXCSUM +#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_SRXCSUM +#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_GTXCSUM +#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_STXCSUM +#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_GSG +#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable + * (ethtool_value) */ +#endif +#ifndef ETHTOOL_SSG +#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable + * (ethtool_value). */ +#endif +#ifndef ETHTOOL_TEST +#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ +#endif +#ifndef ETHTOOL_GSTRINGS +#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ +#endif +#ifndef ETHTOOL_PHYS_ID +#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ +#endif +#ifndef ETHTOOL_GSTATS +#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ +#endif +#ifndef ETHTOOL_GTSO +#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_STSO +#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ +#endif + +#ifndef ETHTOOL_BUSINFO_LEN +#define ETHTOOL_BUSINFO_LEN 32 +#endif + +/*****************************************************************************/ +/* 2.4.3 => 2.4.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) + +/**************************************/ +/* PCI DRIVER API */ + +#ifndef pci_set_dma_mask +#define pci_set_dma_mask _kc_pci_set_dma_mask +extern int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); +#endif + +#ifndef pci_request_regions +#define pci_request_regions _kc_pci_request_regions +extern int _kc_pci_request_regions(struct pci_dev *pdev, char *res_name); +#endif + +#ifndef pci_release_regions +#define pci_release_regions _kc_pci_release_regions +extern void _kc_pci_release_regions(struct pci_dev *pdev); +#endif + +/**************************************/ +/* NETWORK DRIVER API */ + +#ifndef alloc_etherdev +#define alloc_etherdev _kc_alloc_etherdev +extern struct net_device * _kc_alloc_etherdev(int sizeof_priv); +#endif + +#ifndef is_valid_ether_addr +#define is_valid_ether_addr _kc_is_valid_ether_addr +extern int _kc_is_valid_ether_addr(u8 *addr); +#endif + +/**************************************/ +/* MISCELLANEOUS */ + +#ifndef INIT_TQUEUE +#define INIT_TQUEUE(_tq, _routine, _data) \ + do { \ + INIT_LIST_HEAD(&(_tq)->list); \ + (_tq)->sync = 0; \ + (_tq)->routine = _routine; \ + (_tq)->data = _data; \ + } while (0) +#endif + +#endif /* 2.4.3 => 2.4.0 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) ) +/* Generic MII registers. */ +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define MII_LPA 0x05 /* Link partner ability reg */ +#define MII_EXPANSION 0x06 /* Expansion register */ +/* Basic mode control register. */ +#define BMCR_FULLDPLX 0x0100 /* Full duplex */ +#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ +/* Basic mode status register. */ +#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ +#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ +#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ +#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ +#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ +#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ +/* Advertisement control register. */ +#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ + ADVERTISE_100HALF | ADVERTISE_100FULL) +/* Expansion register for auto-negotiation. */ +#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */ +#endif + +/*****************************************************************************/ +/* 2.4.6 => 2.4.3 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) + +#ifndef pci_set_power_state +#define pci_set_power_state _kc_pci_set_power_state +extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); +#endif + +#ifndef pci_save_state +#define pci_save_state _kc_pci_save_state +extern int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer); +#endif + +#ifndef pci_restore_state +#define pci_restore_state _kc_pci_restore_state +extern int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer); +#endif + +#ifndef pci_enable_wake +#define pci_enable_wake _kc_pci_enable_wake +extern int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable); +#endif + +#ifndef pci_disable_device +#define pci_disable_device _kc_pci_disable_device +extern void _kc_pci_disable_device(struct pci_dev *pdev); +#endif + +/* PCI PM entry point syntax changed, so don't support suspend/resume */ +#undef CONFIG_PM + +#endif /* 2.4.6 => 2.4.3 */ + +#ifndef HAVE_PCI_SET_MWI +#define pci_set_mwi(X) pci_write_config_word(X, \ + PCI_COMMAND, adapter->hw.bus.pci_cmd_word | \ + PCI_COMMAND_INVALIDATE); +#define pci_clear_mwi(X) pci_write_config_word(X, \ + PCI_COMMAND, adapter->hw.bus.pci_cmd_word & \ + ~PCI_COMMAND_INVALIDATE); +#endif + +/*****************************************************************************/ +/* 2.4.10 => 2.4.9 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) ) + +/**************************************/ +/* MODULE API */ + +#ifndef MODULE_LICENSE + #define MODULE_LICENSE(X) +#endif + +/**************************************/ +/* OTHER */ + +#undef min +#define min(x,y) ({ \ + const typeof(x) _x = (x); \ + const typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x < _y ? _x : _y; }) + +#undef max +#define max(x,y) ({ \ + const typeof(x) _x = (x); \ + const typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x > _y ? _x : _y; }) + +#ifndef list_for_each_safe +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) +#endif + +#endif /* 2.4.10 -> 2.4.6 */ + + +/*****************************************************************************/ +/* 2.4.13 => 2.4.10 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) + +/**************************************/ +/* PCI DMA MAPPING */ + +#ifndef virt_to_page + #define virt_to_page(v) (mem_map + (virt_to_phys(v) >> PAGE_SHIFT)) +#endif + +#ifndef pci_map_page +#define pci_map_page _kc_pci_map_page +extern u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction); +#endif + +#ifndef pci_unmap_page +#define pci_unmap_page _kc_pci_unmap_page +extern void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction); +#endif + +/* pci_set_dma_mask takes dma_addr_t, which is only 32-bits prior to 2.4.13 */ + +#undef DMA_32BIT_MASK +#define DMA_32BIT_MASK 0xffffffff +#undef DMA_64BIT_MASK +#define DMA_64BIT_MASK 0xffffffff + +/**************************************/ +/* OTHER */ + +#ifndef cpu_relax +#define cpu_relax() rep_nop() +#endif + +#endif /* 2.4.13 => 2.4.10 */ + +/*****************************************************************************/ +/* 2.4.17 => 2.4.12 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) ) + +#ifndef __devexit_p + #define __devexit_p(x) &(x) +#endif + +#endif /* 2.4.17 => 2.4.13 */ + +/*****************************************************************************/ +/* 2.4.20 => 2.4.19 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) ) + +/* we won't support NAPI on less than 2.4.20 */ +#ifdef NAPI +#undef CONFIG_E1000_NAPI +#undef CONFIG_E1000E_NAPI +#undef CONFIG_IXGB_NAPI +#endif + +#endif /* 2.4.20 => 2.4.19 */ +/*****************************************************************************/ +/* 2.4.22 => 2.4.17 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) +#define pci_name(x) ((x)->slot_name) +#endif + +/*****************************************************************************/ +/* 2.4.22 => 2.4.17 */ + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) +#endif + +/*****************************************************************************/ +/*****************************************************************************/ +/* 2.4.23 => 2.4.22 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) +/*****************************************************************************/ +#ifdef NAPI +#ifndef netif_poll_disable +#define netif_poll_disable(x) _kc_netif_poll_disable(x) +static inline void _kc_netif_poll_disable(struct net_device *netdev) +{ + while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { + /* No hurry */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } +} +#endif + +#ifndef netif_poll_enable +#define netif_poll_enable(x) _kc_netif_poll_enable(x) +static inline void _kc_netif_poll_enable(struct net_device *netdev) +{ + clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); +} +#endif +#endif /* NAPI */ +#ifndef netif_tx_disable +#define netif_tx_disable(x) _kc_netif_tx_disable(x) +static inline void _kc_netif_tx_disable(struct net_device *dev) +{ + spin_lock_bh(&dev->xmit_lock); + netif_stop_queue(dev); + spin_unlock_bh(&dev->xmit_lock); +} +#endif +#endif /* 2.4.23 => 2.4.22 */ + +/*****************************************************************************/ +/* 2.6.4 => 2.6.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ + ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) +#define ETHTOOL_OPS_COMPAT +#endif /* 2.6.4 => 2.6.0 */ + +/*****************************************************************************/ +/* 2.5.71 => 2.4.x */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71) ) +#include +#define sk_protocol protocol + +#define pci_get_device pci_find_device +#endif /* 2.5.70 => 2.4.x */ + +/*****************************************************************************/ +/* < 2.4.27 or 2.6.0 <= 2.6.5 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) || \ + ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ) + +#ifndef netif_msg_init +#define netif_msg_init _kc_netif_msg_init +static inline u32 _kc_netif_msg_init(int debug_value, int default_msg_enable_bits) +{ + /* use default */ + if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) + return default_msg_enable_bits; + if (debug_value == 0) /* no output */ + return 0; + /* set low N bits */ + return (1 << debug_value) -1; +} +#endif + +#endif /* < 2.4.27 or 2.6.0 <= 2.6.5 */ +/*****************************************************************************/ +#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ + (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ + ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) +#define netdev_priv(x) x->priv +#endif + +/*****************************************************************************/ +/* <= 2.5.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) +#undef pci_register_driver +#define pci_register_driver pci_module_init + +#define dev_err(__unused_dev, format, arg...) \ + printk(KERN_ERR "%s: " format, pci_name(adapter->pdev) , ## arg) + +/* hlist_* code - double linked lists */ +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = NULL; + n->pprev = NULL; +} + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +/* we ignore GFP here */ +#define dma_alloc_coherent(dv, sz, dma, gfp) \ + pci_alloc_consistent(pdev, (sz), (dma)) +#define dma_free_coherent(dv, sz, addr, dma_addr) \ + pci_free_consistent(pdev, (sz), (addr), (dma_addr)) + +#ifndef might_sleep +#define might_sleep() +#endif + +#endif /* <= 2.5.0 */ + +/*****************************************************************************/ +/* 2.5.28 => 2.4.23 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) + +static inline void _kc_synchronize_irq(void) +{ + synchronize_irq(); +} +#undef synchronize_irq +#define synchronize_irq(X) _kc_synchronize_irq() + +#include +#define work_struct tq_struct +#undef INIT_WORK +#define INIT_WORK(a,b) INIT_TQUEUE(a,(void (*)(void *))b,a) +#undef container_of +#define container_of list_entry +#define schedule_work schedule_task +#define flush_scheduled_work flush_scheduled_tasks + +#endif /* 2.5.28 => 2.4.17 */ + +/*****************************************************************************/ +/* 2.6.0 => 2.5.28 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) +#define MODULE_INFO(version, _version) +#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT +#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 +#endif +#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT +#define CONFIG_IGB_DISABLE_PACKET_SPLIT 1 +#endif + +#define pci_set_consistent_dma_mask(dev,mask) 1 + +#undef dev_put +#define dev_put(dev) __dev_put(dev) + +#ifndef skb_fill_page_desc +#define skb_fill_page_desc _kc_skb_fill_page_desc +extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); +#endif + +#ifndef pci_dma_mapping_error +#define pci_dma_mapping_error _kc_pci_dma_mapping_error +static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) +{ + return dma_addr == 0; +} +#endif + +#undef ALIGN +#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + +/* find_first_bit and find_next bit are not defined for most + * 2.4 kernels (except for the redhat 2.4.21 kernels + */ +#include +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) +#undef find_next_bit +#define find_next_bit _kc_find_next_bit +extern unsigned long _kc_find_next_bit(const unsigned long *addr, + unsigned long size, + unsigned long offset); +#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) + +#endif /* 2.6.0 => 2.5.28 */ + +/*****************************************************************************/ +/* 2.6.4 => 2.6.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) +#define MODULE_VERSION(_version) MODULE_INFO(version, _version) +#endif /* 2.6.4 => 2.6.0 */ + +/*****************************************************************************/ +/* 2.6.5 => 2.6.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) +#define pci_dma_sync_single_for_cpu pci_dma_sync_single +#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu +#endif /* 2.6.5 => 2.6.0 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6) ) +/* taken from 2.6 include/linux/bitmap.h */ +#undef bitmap_zero +#define bitmap_zero _kc_bitmap_zero +static inline void _kc_bitmap_zero(unsigned long *dst, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = 0UL; + else { + int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); + memset(dst, 0, len); + } +} +#endif /* < 2.6.6 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ) +#undef if_mii +#define if_mii _kc_if_mii +static inline struct mii_ioctl_data *_kc_if_mii(struct ifreq *rq) +{ + return (struct mii_ioctl_data *) &rq->ifr_ifru; +} +#endif /* < 2.6.7 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) +#define msleep(x) do { set_current_state(TASK_UNINTERRUPTIBLE); \ + schedule_timeout((x * HZ)/1000 + 2); \ + } while (0) + +#endif /* < 2.6.8 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) +#include +#define __iomem + +#ifndef kcalloc +#define kcalloc(n, size, flags) _kc_kzalloc(((n) * (size)), flags) +extern void *_kc_kzalloc(size_t size, int flags); +#endif +#define MSEC_PER_SEC 1000L +static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) +{ +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + return (MSEC_PER_SEC / HZ) * j; +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); +#else + return (j * MSEC_PER_SEC) / HZ; +#endif +} +static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) +{ + if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + return m * (HZ / MSEC_PER_SEC); +#else + return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; +#endif +} + +#define msleep_interruptible _kc_msleep_interruptible +static inline unsigned long _kc_msleep_interruptible(unsigned int msecs) +{ + unsigned long timeout = _kc_msecs_to_jiffies(msecs) + 1; + + while (timeout && !signal_pending(current)) { + __set_current_state(TASK_INTERRUPTIBLE); + timeout = schedule_timeout(timeout); + } + return _kc_jiffies_to_msecs(timeout); +} + +/* Basic mode control register. */ +#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ +#endif /* < 2.6.9 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) +#ifdef pci_save_state +#undef pci_save_state +#endif +#define pci_save_state(X) { \ + int i; \ + if (adapter->pci_state) { \ + for (i = 0; i < 16; i++) { \ + pci_read_config_dword((X), \ + i * 4, \ + &adapter->pci_state[i]); \ + } \ + } \ +} + +#ifdef pci_restore_state +#undef pci_restore_state +#endif +#define pci_restore_state(X) { \ + int i; \ + if (adapter->pci_state) { \ + for (i = 0; i < 16; i++) { \ + pci_write_config_dword((X), \ + i * 4, \ + adapter->pci_state[i]); \ + } \ + } else { \ + for (i = 0; i < 6; i++) { \ + pci_write_config_dword((X), \ + PCI_BASE_ADDRESS_0 + (i * 4), \ + (X)->resource[i].start); \ + } \ + } \ +} +#endif /* 2.4.6 <= x < 2.6.10 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) +#ifdef module_param_array_named +#undef module_param_array_named +#define module_param_array_named(name, array, type, nump, perm) \ + static struct kparam_array __param_arr_##name \ + = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type, \ + sizeof(array[0]), array }; \ + module_param_call(name, param_array_set, param_array_get, \ + &__param_arr_##name, perm) +#endif /* module_param_array_named */ +#endif /* < 2.6.10 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) +#define PCI_D0 0 +#define PCI_D1 1 +#define PCI_D2 2 +#define PCI_D3hot 3 +#define PCI_D3cold 4 +#define pci_choose_state(pdev,state) state +#define PMSG_SUSPEND 3 + +#undef NETIF_F_LLTX + +#ifndef ARCH_HAS_PREFETCH +#define prefetch(X) +#endif + +#ifndef NET_IP_ALIGN +#define NET_IP_ALIGN 2 +#endif + +#define KC_USEC_PER_SEC 1000000L +#define usecs_to_jiffies _kc_usecs_to_jiffies +static inline unsigned int _kc_jiffies_to_usecs(const unsigned long j) +{ +#if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) + return (KC_USEC_PER_SEC / HZ) * j; +#elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) + return (j + (HZ / KC_USEC_PER_SEC) - 1)/(HZ / KC_USEC_PER_SEC); +#else + return (j * KC_USEC_PER_SEC) / HZ; +#endif +} +static inline unsigned long _kc_usecs_to_jiffies(const unsigned int m) +{ + if (m > _kc_jiffies_to_usecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; +#if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) + return (m + (KC_USEC_PER_SEC / HZ) - 1) / (KC_USEC_PER_SEC / HZ); +#elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) + return m * (HZ / KC_USEC_PER_SEC); +#else + return (m * HZ + KC_USEC_PER_SEC - 1) / KC_USEC_PER_SEC; +#endif +} +#endif /* < 2.6.11 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) +#include +#define USE_REBOOT_NOTIFIER + +/* Generic MII registers. */ +#define MII_CTRL1000 0x09 /* 1000BASE-T control */ +#define MII_STAT1000 0x0a /* 1000BASE-T status */ +/* Advertisement control register. */ +#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ +#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymmetric pause */ +/* 1000BASE-T Control register */ +#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ +#endif + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) +#define pm_message_t u32 +#ifndef kzalloc +#define kzalloc _kc_kzalloc +extern void *_kc_kzalloc(size_t size, int flags); +#endif + +/* Generic MII registers. */ +#define MII_ESTATUS 0x0f /* Extended Status */ +/* Basic mode status register. */ +#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ +/* Extended status register. */ +#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ +#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ +#endif + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) ) +#undef HAVE_PCI_ERS +#else /* 2.6.16 and above */ +#undef HAVE_PCI_ERS +#define HAVE_PCI_ERS +#endif + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) + +#ifndef IRQF_PROBE_SHARED +#ifdef SA_PROBEIRQ +#define IRQF_PROBE_SHARED SA_PROBEIRQ +#else +#define IRQF_PROBE_SHARED 0 +#endif +#endif + +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#ifndef netdev_alloc_skb +#define netdev_alloc_skb _kc_netdev_alloc_skb +extern struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, + unsigned int length); +#endif + +#ifndef skb_is_gso +#ifdef NETIF_F_TSO +#define skb_is_gso _kc_skb_is_gso +static inline int _kc_skb_is_gso(const struct sk_buff *skb) +{ + return skb_shinfo(skb)->gso_size; +} +#else +#define skb_is_gso(a) 0 +#endif +#endif + +#endif /* < 2.6.18 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) + +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#endif + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) +#ifndef RHEL_RELEASE_CODE +#define RHEL_RELEASE_CODE 0 +#endif +#ifndef RHEL_RELEASE_VERSION +#define RHEL_RELEASE_VERSION(a,b) 0 +#endif +#if (!(( RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,4) ) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0) ) || ( RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,0) ))) +typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *); +#endif +typedef irqreturn_t (*new_handler_t)(int, void*); +static inline irqreturn_t _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) +#else /* 2.4.x */ +typedef void (*irq_handler_t)(int, void*, struct pt_regs *); +typedef void (*new_handler_t)(int, void*); +static inline int _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) +#endif +{ + irq_handler_t new_handler = (irq_handler_t) handler; + return request_irq(irq, new_handler, flags, devname, dev_id); +} + +#undef request_irq +#define request_irq(irq, handler, flags, devname, dev_id) _kc_request_irq((irq), (handler), (flags), (devname), (dev_id)) + +#define irq_handler_t new_handler_t + +/* pci_restore_state and pci_save_state handles MSI/PCIE from 2.6.19 */ +#define PCIE_CONFIG_SPACE_LEN 256 +#define PCI_CONFIG_SPACE_LEN 64 +#define PCIE_LINK_STATUS 0x12 +#ifdef DRIVER_E1000E +#define pci_config_space_ich8lan() { \ + if (adapter->flags & FLAG_IS_ICH) \ + size = PCIE_CONFIG_SPACE_LEN; \ +} +#else +#define pci_config_space_ich8lan() +#endif +#undef pci_save_state +#define pci_save_state(pdev) _kc_pci_save_state(adapter) +#define _kc_pci_save_state(adapter) 0; { \ + int size = PCI_CONFIG_SPACE_LEN, i; \ + u16 pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); \ + u16 pcie_link_status; \ + \ + if (pcie_cap_offset) { \ + if (!pci_read_config_word(pdev, pcie_cap_offset + PCIE_LINK_STATUS, \ + &pcie_link_status)) \ + size = PCIE_CONFIG_SPACE_LEN; \ + } \ + pci_config_space_ich8lan(); \ + WARN_ON(adapter->config_space != NULL); \ + adapter->config_space = kmalloc(size, GFP_KERNEL); \ + if (!adapter->config_space) { \ + printk(KERN_ERR "Out of memory in pci_save_state\n"); \ + return -ENOMEM; \ + } \ + for (i = 0; i < (size / 4); i++) \ + pci_read_config_dword(pdev, i * 4, &adapter->config_space[i]); \ +} +#undef pci_restore_state +#define pci_restore_state(pdev) _kc_pci_restore_state(adapter) +#define _kc_pci_restore_state(adapter) { \ + int size = PCI_CONFIG_SPACE_LEN, i; \ + u16 pcie_cap_offset; \ + u16 pcie_link_status; \ + \ + if (adapter->config_space != NULL) { \ + pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); \ + if (pcie_cap_offset) { \ + if (!pci_read_config_word(pdev, pcie_cap_offset + PCIE_LINK_STATUS, \ + &pcie_link_status)) \ + size = PCIE_CONFIG_SPACE_LEN; \ + } \ + pci_config_space_ich8lan(); \ + for (i = 0; i < (size / 4); i++) \ + pci_write_config_dword(pdev, i * 4, adapter->config_space[i]); \ + kfree(adapter->config_space); \ + adapter->config_space = NULL; \ + } \ +} + +#endif /* < 2.6.19 */ +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) ) +#undef INIT_WORK +#define INIT_WORK(_work, _func) \ +do { \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->pending = 0; \ + (_work)->func = (void (*)(void *))_func; \ + (_work)->data = _work; \ + init_timer(&(_work)->timer); \ +} while (0) +#endif + +#ifndef PCI_VDEVICE +#define PCI_VDEVICE(ven, dev) \ + PCI_VENDOR_ID_##ven, (dev), \ + PCI_ANY_ID, PCI_ANY_ID, 0, 0 +#endif + +#ifndef round_jiffies +#define round_jiffies(x) x +#endif + +#define csum_offset csum + +#endif /* < 2.6.20 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) +#define vlan_group_get_device(vg, id) (vg->vlan_devices[id]) +#define vlan_group_set_device(vg, id, dev) if (vg) vg->vlan_devices[id] = dev; +#define pci_channel_offline(pdev) (pdev->error_state && \ + pdev->error_state != pci_channel_io_normal) +#endif /* < 2.6.21 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) +#define tcp_hdr(skb) (skb->h.th) +#define tcp_hdrlen(skb) (skb->h.th->doff << 2) +#define skb_transport_offset(skb) (skb->h.raw - skb->data) +#define skb_transport_header(skb) (skb->h.raw) +#define ipv6_hdr(skb) (skb->nh.ipv6h) +#define ip_hdr(skb) (skb->nh.iph) +#define skb_network_offset(skb) (skb->nh.raw - skb->data) +#define skb_network_header(skb) (skb->nh.raw) +#define skb_tail_pointer(skb) skb->tail +#define skb_copy_to_linear_data_offset(skb, offset, from, len) \ + memcpy(skb->data + offset, from, len) +#define skb_network_header_len(skb) (skb->h.raw - skb->nh.raw) +#define pci_register_driver pci_module_init +#define skb_mac_header(skb) skb->mac.raw + +#ifdef NETIF_F_MULTI_QUEUE +#ifndef alloc_etherdev_mq +#define alloc_etherdev_mq(_a, _b) alloc_etherdev(_a) +#endif +#endif /* NETIF_F_MULTI_QUEUE */ + +#ifndef ETH_FCS_LEN +#define ETH_FCS_LEN 4 +#endif +#endif /* < 2.6.22 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) ) +#undef ETHTOOL_GPERMADDR +#undef SET_MODULE_OWNER +#define SET_MODULE_OWNER(dev) do { } while (0) +#endif /* > 2.6.22 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) +/* NAPI API changes in 2.6.24 break everything */ +struct napi_struct { + /* used to look up the real NAPI polling routine */ + int (*poll)(struct napi_struct *, int); + int weight; +}; +#ifdef NAPI +extern int __kc_adapter_clean(struct net_device *, int *); +#define netif_rx_complete(netdev, napi) netif_rx_complete(netdev) +#define netif_rx_schedule_prep(netdev, napi) netif_rx_schedule_prep(netdev) +#define netif_rx_schedule(netdev, napi) netif_rx_schedule(netdev) +#define __netif_rx_schedule(netdev, napi) __netif_rx_schedule(netdev) +#define napi_enable(napi) netif_poll_enable(adapter->netdev) +#define napi_disable(napi) netif_poll_disable(adapter->netdev) +#define netif_napi_add(_netdev, _napi, _poll, _weight) \ + do { \ + struct napi_struct *__napi = _napi; \ + _netdev->poll = &(__kc_adapter_clean); \ + _netdev->weight = (_weight); \ + __napi->poll = &(_poll); \ + __napi->weight = (_weight); \ + netif_poll_disable(_netdev); \ + } while (0) +#else /* NAPI */ +#define netif_napi_add(_netdev, _napi, _poll, _weight) \ + do { \ + struct napi_struct *__napi = _napi; \ + _netdev->poll = &(_poll); \ + _netdev->weight = (_weight); \ + __napi->poll = &(_poll); \ + __napi->weight = (_weight); \ + } while (0) +#endif /* NAPI */ + +#undef dev_get_by_name +#define dev_get_by_name(_a, _b) dev_get_by_name(_b) +#define __netif_subqueue_stopped(_a, _b) netif_subqueue_stopped(_a, _b) +#endif /* < 2.6.24 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) ) +#include +#endif /* > 2.6.24 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) ) +#define PM_QOS_CPU_DMA_LATENCY 1 + +#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) ) +#include +#define PM_QOS_DEFAULT_VALUE INFINITE_LATENCY +#define pm_qos_add_requirement(pm_qos_class, name, value) \ + set_acceptable_latency(name, value) +#define pm_qos_remove_requirement(pm_qos_class, name) \ + remove_acceptable_latency(name) +#define pm_qos_update_requirement(pm_qos_class, name, value) \ + modify_acceptable_latency(name, value) +#else +#define PM_QOS_DEFAULT_VALUE -1 +#define pm_qos_add_requirement(pm_qos_class, name, value) +#define pm_qos_remove_requirement(pm_qos_class, name) +#define pm_qos_update_requirement(pm_qos_class, name, value) { \ + if (value != PM_QOS_DEFAULT_VALUE) { \ + printk(KERN_WARNING "%s: unable to set PM QoS requirement\n", \ + pci_name(adapter->pdev)); \ + } \ +} +#endif /* > 2.6.18 */ + +#endif /* < 2.6.25 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) ) +#endif /* < 2.6.26 */ + +#ifndef NETIF_F_MULTI_QUEUE +#define NETIF_F_MULTI_QUEUE 0 +#define netif_is_multiqueue(a) 0 +#define netif_stop_subqueue(a, b) +#define netif_wake_subqueue(a, b) +#define netif_start_subqueue(a, b) +#endif /* NETIF_F_MULTI_QUEUE */ + +#endif /* _KCOMPAT_H_ */ --- linux-2.6.27.orig/ubuntu/e1000e/netdev.c +++ linux-2.6.27/ubuntu/e1000e/netdev.c @@ -0,0 +1,5636 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef NETIF_F_TSO +#include +#ifdef NETIF_F_TSO6 +#include +#endif +#endif +#include +#include +#include + +#include "e1000.h" + +#ifdef CONFIG_E1000E_NAPI +#define DRV_NAPI "-NAPI" +#else +#define DRV_NAPI +#endif + +#define DRV_DEBUG + +#define DRV_VERSION "0.4.1.7" DRV_NAPI DRV_DEBUG +char e1000e_driver_name[] = "e1000e"; +const char e1000e_driver_version[] = DRV_VERSION; + +static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + static int global_quad_port_a; /* global port a indication */ + struct pci_dev *pdev = adapter->pdev; + u16 eeprom_data = 0; + int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; + + /* tag quad port adapters first, it's used below */ + switch (pdev->device) { + case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_FIBER: + case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: + case E1000_DEV_ID_82571PT_QUAD_COPPER: + adapter->flags |= FLAG_IS_QUAD_PORT; + /* mark the first port */ + if (global_quad_port_a == 0) + adapter->flags |= FLAG_IS_QUAD_PORT_A; + /* Reset for multiple quad port adapters */ + global_quad_port_a++; + if (global_quad_port_a == 4) + global_quad_port_a = 0; + break; + default: + break; + } + + switch (adapter->hw.mac.type) { + case e1000_82571: + /* these dual ports don't have WoL on port B at all */ + if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) || + (pdev->device == E1000_DEV_ID_82571EB_SERDES) || + (pdev->device == E1000_DEV_ID_82571EB_COPPER)) && + (is_port_b)) + adapter->flags &= ~FLAG_HAS_WOL; + /* quad ports only support WoL on port A */ + if (adapter->flags & FLAG_IS_QUAD_PORT && + (!(adapter->flags & FLAG_IS_QUAD_PORT_A))) + adapter->flags &= ~FLAG_HAS_WOL; + /* Does not support WoL on any port */ + if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) + adapter->flags &= ~FLAG_HAS_WOL; + break; + + case e1000_82573: + if (pdev->device == E1000_DEV_ID_82573L) { + adapter->hw.nvm.ops.read(&adapter->hw, NVM_INIT_3GIO_3, + 1, &eeprom_data); + if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) + adapter->flags |= FLAG_HAS_JUMBO_FRAMES; + } + break; + + default: + break; + } + + return 0; +} + +static struct e1000_info e1000_82571_info = { + .mac = e1000_82571, + .flags = FLAG_HAS_HW_VLAN_FILTER + | FLAG_HAS_JUMBO_FRAMES + | FLAG_HAS_WOL + | FLAG_APME_IN_CTRL3 + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_RESET_OVERWRITES_LAA /* errata */ + | FLAG_TARC_SPEED_MODE_BIT /* errata */ + | FLAG_APME_CHECK_PORT_B, + .pba = 38, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; + +static struct e1000_info e1000_82572_info = { + .mac = e1000_82572, + .flags = FLAG_HAS_HW_VLAN_FILTER + | FLAG_HAS_JUMBO_FRAMES + | FLAG_HAS_WOL + | FLAG_APME_IN_CTRL3 + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_TARC_SPEED_MODE_BIT, /* errata */ + .pba = 38, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; + +static struct e1000_info e1000_82573_info = { + .mac = e1000_82573, + .flags = FLAG_HAS_HW_VLAN_FILTER + | FLAG_HAS_WOL + | FLAG_APME_IN_CTRL3 + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT + | FLAG_HAS_ASPM + | FLAG_HAS_ERT + | FLAG_HAS_SWSM_ON_LOAD, + .pba = 20, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; + +static struct e1000_info e1000_82574_info = { + .mac = e1000_82574, + .flags = FLAG_HAS_HW_VLAN_FILTER +#ifdef CONFIG_E1000E_MSIX + | FLAG_HAS_MSIX +#endif + | FLAG_HAS_JUMBO_FRAMES + | FLAG_HAS_WOL + | FLAG_APME_IN_CTRL3 + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT + | FLAG_HAS_ASPM + | FLAG_HAS_CTRLEXT_ON_LOAD, + .pba = 20, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; + +static struct e1000_info e1000_es2_info = { + .mac = e1000_80003es2lan, + .flags = FLAG_HAS_HW_VLAN_FILTER + | FLAG_HAS_JUMBO_FRAMES + | FLAG_HAS_WOL + | FLAG_APME_IN_CTRL3 + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_RX_NEEDS_RESTART /* errata */ + | FLAG_TARC_SET_BIT_ZERO /* errata */ + | FLAG_APME_CHECK_PORT_B + | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ + | FLAG_TIPG_MEDIUM_FOR_80003ESLAN, + .pba = 38, + .init_ops = e1000_init_function_pointers_80003es2lan, + .get_variants = NULL, +}; + +static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) +{ + if (adapter->hw.phy.type == e1000_phy_ife) + adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; + + if ((adapter->hw.mac.type == e1000_ich8lan) && + (adapter->hw.phy.type == e1000_phy_igp_3)) + adapter->flags |= FLAG_LSC_GIG_SPEED_DROP; + + return 0; +} + +static struct e1000_info e1000_ich8_info = { + .mac = e1000_ich8lan, + .flags = FLAG_HAS_WOL + | FLAG_IS_ICH + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, + .pba = 8, + .init_ops = e1000_init_function_pointers_ich8lan, + .get_variants = e1000_get_variants_ich8lan, +}; + +static struct e1000_info e1000_ich9_info = { + .mac = e1000_ich9lan, + .flags = FLAG_HAS_JUMBO_FRAMES + | FLAG_IS_ICH + | FLAG_HAS_WOL + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT + | FLAG_HAS_ERT + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, + .pba = 10, + .init_ops = e1000_init_function_pointers_ich8lan, + .get_variants = e1000_get_variants_ich8lan, +}; + +static struct e1000_info e1000_ich10_info = { + .mac = e1000_ich10lan, + .flags = FLAG_HAS_JUMBO_FRAMES + | FLAG_IS_ICH + | FLAG_HAS_WOL + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT + | FLAG_HAS_ERT + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, + .pba = 10, + .init_ops = e1000_init_function_pointers_ich8lan, + .get_variants = e1000_get_variants_ich8lan, +}; + +static const struct e1000_info *e1000_info_tbl[] = { + [board_82571] = &e1000_82571_info, + [board_82572] = &e1000_82572_info, + [board_82573] = &e1000_82573_info, + [board_82574] = &e1000_82574_info, + [board_80003es2lan] = &e1000_es2_info, + [board_ich8lan] = &e1000_ich8_info, + [board_ich9lan] = &e1000_ich9_info, + [board_ich10lan] = &e1000_ich10_info, +}; + + +void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) +{ + struct e1000_adapter *adapter = hw->back; + + pci_read_config_word(adapter->pdev, reg, value); +} + +s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) +{ + struct e1000_adapter *adapter = hw->back; + u16 cap_offset; + + cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); + if (!cap_offset) + return -E1000_ERR_CONFIG; + + pci_read_config_word(adapter->pdev, cap_offset + reg, value); + + return E1000_SUCCESS; +} + +s32 e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size) +{ + hw->dev_spec = kzalloc(size, GFP_KERNEL); + + if (!hw->dev_spec) + return -ENOMEM; + + return E1000_SUCCESS; +} + +void e1000_free_dev_spec_struct(struct e1000_hw *hw) +{ + if (!hw->dev_spec) + return; + + kfree(hw->dev_spec); +} + +/** + * e1000_desc_unused - calculate if we have unused descriptors + **/ +static int e1000_desc_unused(struct e1000_ring *ring) +{ + if (ring->next_to_clean > ring->next_to_use) + return ring->next_to_clean - ring->next_to_use - 1; + + return ring->count + ring->next_to_clean - ring->next_to_use - 1; +} + +/** + * e1000_receive_skb - helper function to handle Rx indications + * @adapter: board private structure + * @status: descriptor status field as written by hardware + * @vlan: descriptor vlan field as written by hardware (no le/be conversion) + * @skb: pointer to sk_buff to be indicated to stack + **/ +static void e1000_receive_skb(struct e1000_adapter *adapter, + struct net_device *netdev, + struct sk_buff *skb, + u8 status, u16 vlan) +{ + skb->protocol = eth_type_trans(skb, netdev); + +#ifdef CONFIG_E1000E_NAPI + if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, + le16_to_cpu(vlan) & + E1000_RXD_SPC_VLAN_MASK); + else + netif_receive_skb(skb); +#else + if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) + vlan_hwaccel_rx(skb, adapter->vlgrp, + le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK); + else + netif_rx(skb); +#endif + + netdev->last_rx = jiffies; +} + +/** + * e1000_rx_checksum - Receive Checksum Offload for 82543 + * @adapter: board private structure + * @status_err: receive descriptor status and error fields + * @csum: receive descriptor csum field + * @sk_buff: socket buffer with received data + **/ +static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, + u32 csum, struct sk_buff *skb) +{ + u16 status = (u16)status_err; + u8 errors = (u8)(status_err >> 24); + skb->ip_summed = CHECKSUM_NONE; + + /* Ignore Checksum bit is set */ + if (status & E1000_RXD_STAT_IXSM) + return; + /* TCP/UDP checksum error bit is set */ + if (errors & E1000_RXD_ERR_TCPE) { + /* let the stack verify checksum errors */ + adapter->hw_csum_err++; + return; + } + + /* TCP/UDP Checksum has not been calculated */ + if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) + return; + + /* It must be a TCP or UDP packet with a valid checksum */ + if (status & E1000_RXD_STAT_TCPCS) { + /* TCP checksum is good */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + /* + * IP fragment with UDP payload + * Hardware complements the payload checksum, so we undo it + * and then put the value in host order for further stack use. + */ + csum = ntohl(csum ^ 0xFFFF); + skb->csum = csum; + skb->ip_summed = CHECKSUM_COMPLETE; + } + adapter->hw_csum_good++; +} + +/** + * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended + * @adapter: address of board private structure + **/ +static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, + int cleaned_count) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_rx_desc *rx_desc; + struct e1000_buffer *buffer_info; + struct sk_buff *skb; + unsigned int i; + unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; + + i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; + + while (cleaned_count--) { + skb = buffer_info->skb; + if (skb) { + skb_trim(skb, 0); + goto map_skb; + } + + skb = netdev_alloc_skb(netdev, bufsz); + if (!skb) { + /* Better luck next round */ + adapter->alloc_rx_buff_failed++; + break; + } + + /* + * Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + + buffer_info->skb = skb; +map_skb: + buffer_info->dma = pci_map_single(pdev, skb->data, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, buffer_info->dma)) { + dev_err(&pdev->dev, "RX DMA map failed\n"); + adapter->rx_dma_failed++; + break; + } + + rx_desc = E1000_RX_DESC(*rx_ring, i); + rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + + i++; + if (i == rx_ring->count) + i = 0; + buffer_info = &rx_ring->buffer_info[i]; + } + + if (rx_ring->next_to_use != i) { + rx_ring->next_to_use = i; + if (i-- == 0) + i = (rx_ring->count - 1); + + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + writel(i, adapter->hw.hw_addr + rx_ring->tail); + } +} + +/** + * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split + * @adapter: address of board private structure + **/ +static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, + int cleaned_count) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + union e1000_rx_desc_packet_split *rx_desc; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info; + struct e1000_ps_page *ps_page; + struct sk_buff *skb; + unsigned int i, j; + + i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; + + while (cleaned_count--) { + rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + + for (j = 0; j < PS_PAGE_BUFFERS; j++) { + ps_page = &buffer_info->ps_pages[j]; + if (j >= adapter->rx_ps_pages) { + /* all unused desc entries get hw null ptr */ + rx_desc->read.buffer_addr[j+1] = ~0; + continue; + } + if (!ps_page->page) { + ps_page->page = alloc_page(GFP_ATOMIC); + if (!ps_page->page) { + adapter->alloc_rx_buff_failed++; + goto no_buffers; + } + ps_page->dma = pci_map_page(pdev, + ps_page->page, + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, ps_page->dma)) { + dev_err(&adapter->pdev->dev, + "RX DMA page map failed\n"); + adapter->rx_dma_failed++; + goto no_buffers; + } + } + /* + * Refresh the desc even if buffer_addrs + * didn't change because each write-back + * erases this info. + */ + rx_desc->read.buffer_addr[j+1] = + cpu_to_le64(ps_page->dma); + } + + skb = netdev_alloc_skb(netdev, + adapter->rx_ps_bsize0 + NET_IP_ALIGN); + + if (!skb) { + adapter->alloc_rx_buff_failed++; + break; + } + + /* + * Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + + buffer_info->skb = skb; + buffer_info->dma = pci_map_single(pdev, skb->data, + adapter->rx_ps_bsize0, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, buffer_info->dma)) { + dev_err(&pdev->dev, "RX DMA map failed\n"); + adapter->rx_dma_failed++; + /* cleanup skb */ + dev_kfree_skb_any(skb); + buffer_info->skb = NULL; + break; + } + + rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); + + i++; + if (i == rx_ring->count) + i = 0; + buffer_info = &rx_ring->buffer_info[i]; + } + +no_buffers: + if (rx_ring->next_to_use != i) { + rx_ring->next_to_use = i; + + if (!(i--)) + i = (rx_ring->count - 1); + + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + /* + * Hardware increments by 16 bytes, but packet split + * descriptors are 32 bytes...so we increment tail + * twice as much. + */ + writel(i<<1, adapter->hw.hw_addr + rx_ring->tail); + } +} + +#ifdef CONFIG_E1000E_NAPI +/** + * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers + * @adapter: address of board private structure + * @rx_ring: pointer to receive ring structure + * @cleaned_count: number of buffers to allocate this pass + **/ + +static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, + int cleaned_count) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct e1000_rx_desc *rx_desc; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info; + struct sk_buff *skb; + unsigned int i; + unsigned int bufsz = 256 - + 16 /* for skb_reserve */ - + NET_IP_ALIGN; + + i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; + + while (cleaned_count--) { + skb = buffer_info->skb; + if (skb) { + skb_trim(skb, 0); + goto check_page; + } + + skb = netdev_alloc_skb(netdev, bufsz); + if (unlikely(!skb)) { + /* Better luck next round */ + adapter->alloc_rx_buff_failed++; + break; + } + + /* Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + + buffer_info->skb = skb; +check_page: + /* allocate a new page if necessary */ + if (!buffer_info->page) { + buffer_info->page = alloc_page(GFP_ATOMIC); + if (unlikely(!buffer_info->page)) { + adapter->alloc_rx_buff_failed++; + break; + } + } + + if (!buffer_info->dma) + buffer_info->dma = pci_map_page(pdev, + buffer_info->page, 0, + PAGE_SIZE, + PCI_DMA_FROMDEVICE); + + rx_desc = E1000_RX_DESC(*rx_ring, i); + rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + + if (unlikely(++i == rx_ring->count)) + i = 0; + buffer_info = &rx_ring->buffer_info[i]; + } + + if (likely(rx_ring->next_to_use != i)) { + rx_ring->next_to_use = i; + if (unlikely(i-- == 0)) + i = (rx_ring->count - 1); + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). */ + wmb(); + writel(i, adapter->hw.hw_addr + rx_ring->tail); + } +} +#endif /* CONFIG_E1000E_NAPI */ + +/** + * e1000_clean_rx_irq - Send received data up the network stack; legacy + * @adapter: board private structure + * + * the return value indicates whether actual cleaning was done, there + * is no guarantee that everything was cleaned + **/ +#ifdef CONFIG_E1000E_NAPI +static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, + int *work_done, int work_to_do) +#else +static bool e1000_clean_rx_irq(struct e1000_adapter *adapter) +#endif +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_rx_desc *rx_desc, *next_rxd; + struct e1000_buffer *buffer_info, *next_buffer; + u32 length; + unsigned int i; + int cleaned_count = 0; + bool cleaned = 0; + unsigned int total_rx_bytes = 0, total_rx_packets = 0; + + i = rx_ring->next_to_clean; + rx_desc = E1000_RX_DESC(*rx_ring, i); + buffer_info = &rx_ring->buffer_info[i]; + + while (rx_desc->status & E1000_RXD_STAT_DD) { + struct sk_buff *skb; + u8 status; + +#ifdef CONFIG_E1000E_NAPI + if (*work_done >= work_to_do) + break; + (*work_done)++; +#endif + + status = rx_desc->status; + skb = buffer_info->skb; + buffer_info->skb = NULL; + + prefetch(skb->data - NET_IP_ALIGN); + + i++; + if (i == rx_ring->count) + i = 0; + next_rxd = E1000_RX_DESC(*rx_ring, i); + prefetch(next_rxd); + + next_buffer = &rx_ring->buffer_info[i]; + + cleaned = 1; + cleaned_count++; + pci_unmap_single(pdev, + buffer_info->dma, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; + + length = le16_to_cpu(rx_desc->length); + + /* !EOP means multiple descriptors were used to store a single + * packet, also make sure the frame isn't just CRC only */ + if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) { + /* All receives must fit into a single buffer */ + e_dbg("Receive packet consumed multiple buffers\n"); + /* recycle */ + buffer_info->skb = skb; + goto next_desc; + } + + if (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { + /* recycle */ + buffer_info->skb = skb; + goto next_desc; + } + + total_rx_bytes += length; + total_rx_packets++; + + /* + * code added for copybreak, this should improve + * performance for small packets with large amounts + * of reassembly being done in the stack + */ + if (length < copybreak) { + struct sk_buff *new_skb = + netdev_alloc_skb(netdev, length + NET_IP_ALIGN); + if (new_skb) { + skb_reserve(new_skb, NET_IP_ALIGN); + skb_copy_to_linear_data_offset(new_skb, + -NET_IP_ALIGN, + (skb->data - + NET_IP_ALIGN), + (length + + NET_IP_ALIGN)); + /* save the skb in buffer_info as good */ + buffer_info->skb = skb; + skb = new_skb; + } + /* else just continue with the old one */ + } + /* end copybreak code */ + skb_put(skb, length); + + /* Receive Checksum Offload */ + e1000_rx_checksum(adapter, + (u32)(status) | + ((u32)(rx_desc->errors) << 24), + le16_to_cpu(rx_desc->csum), skb); + + e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special); + +next_desc: + rx_desc->status = 0; + + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >= E1000_RX_BUFFER_WRITE) { + adapter->alloc_rx_buf(adapter, cleaned_count); + cleaned_count = 0; + } + + /* use prefetched values */ + rx_desc = next_rxd; + buffer_info = next_buffer; + } + rx_ring->next_to_clean = i; + + cleaned_count = e1000_desc_unused(rx_ring); + if (cleaned_count) + adapter->alloc_rx_buf(adapter, cleaned_count); + + adapter->total_rx_packets += total_rx_packets; + adapter->total_rx_bytes += total_rx_bytes; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; +} + +static void e1000_put_txbuf(struct e1000_adapter *adapter, + struct e1000_buffer *buffer_info) +{ + if (buffer_info->dma) { + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + if (buffer_info->skb) { + dev_kfree_skb_any(buffer_info->skb); + buffer_info->skb = NULL; + } +} + +static void e1000_print_tx_hang(struct e1000_adapter *adapter) +{ + struct e1000_ring *tx_ring = adapter->tx_ring; + unsigned int i = tx_ring->next_to_clean; + unsigned int eop = tx_ring->buffer_info[i].next_to_watch; + struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop); + + /* detected Tx unit hang */ + e_err("Detected Tx Unit Hang:\n" + " TDH <%x>\n" + " TDT <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "buffer_info[next_to_clean]:\n" + " time_stamp <%lx>\n" + " next_to_watch <%x>\n" + " jiffies <%lx>\n" + " next_to_watch.status <%x>\n", + readl(adapter->hw.hw_addr + tx_ring->head), + readl(adapter->hw.hw_addr + tx_ring->tail), + tx_ring->next_to_use, + tx_ring->next_to_clean, + tx_ring->buffer_info[eop].time_stamp, + eop, + jiffies, + eop_desc->upper.fields.status); +} + +/** + * @e1000_alloc_ring - allocate memory for a ring structure + **/ +static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, + struct e1000_ring *ring) +{ + struct pci_dev *pdev = adapter->pdev; + + ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma, + GFP_KERNEL); + if (!ring->desc) + return -ENOMEM; + + return 0; +} + +/** + * e1000e_setup_tx_resources - allocate Tx resources (Descriptors) + * @adapter: board private structure + * + * Return 0 on success, negative on failure + **/ +int e1000_setup_tx_resources(struct e1000_adapter *adapter) +{ + struct e1000_ring *tx_ring = adapter->tx_ring; + int err = -ENOMEM, size; + + size = sizeof(struct e1000_buffer) * tx_ring->count; + tx_ring->buffer_info = vmalloc(size); + if (!tx_ring->buffer_info) + goto err; + memset(tx_ring->buffer_info, 0, size); + + /* round up to nearest 4K */ + tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); + tx_ring->size = ALIGN(tx_ring->size, 4096); + + err = e1000_alloc_ring_dma(adapter, tx_ring); + if (err) + goto err; + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + spin_lock_init(&adapter->tx_queue_lock); + + return 0; +err: + vfree(tx_ring->buffer_info); + e_err("Unable to allocate memory for the transmit descriptor ring\n"); + return err; +} + +/** + * e1000e_setup_rx_resources - allocate Rx resources (Descriptors) + * @adapter: board private structure + * + * Returns 0 on success, negative on failure + **/ +int e1000_setup_rx_resources(struct e1000_adapter *adapter) +{ + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info; + int i, size, desc_len, err = -ENOMEM; + + size = sizeof(struct e1000_buffer) * rx_ring->count; + rx_ring->buffer_info = vmalloc(size); + if (!rx_ring->buffer_info) + goto err; + memset(rx_ring->buffer_info, 0, size); + + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS, + sizeof(struct e1000_ps_page), + GFP_KERNEL); + if (!buffer_info->ps_pages) + goto err_pages; + } + + desc_len = sizeof(union e1000_rx_desc_packet_split); + + /* Round up to nearest 4K */ + rx_ring->size = rx_ring->count * desc_len; + rx_ring->size = ALIGN(rx_ring->size, 4096); + + err = e1000_alloc_ring_dma(adapter, rx_ring); + if (err) + goto err_pages; + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + rx_ring->rx_skb_top = NULL; + + return 0; + +err_pages: + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + kfree(buffer_info->ps_pages); + } +err: + vfree(rx_ring->buffer_info); + e_err("Unable to allocate memory for the transmit descriptor ring\n"); + return err; +} + +/** + * e1000_clean_tx_ring - Free Tx Buffers + * @adapter: board private structure + **/ +static void e1000_clean_tx_ring(struct e1000_adapter *adapter) +{ + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_buffer *buffer_info; + unsigned long size; + unsigned int i; + + for (i = 0; i < tx_ring->count; i++) { + buffer_info = &tx_ring->buffer_info[i]; + e1000_put_txbuf(adapter, buffer_info); + } + + size = sizeof(struct e1000_buffer) * tx_ring->count; + memset(tx_ring->buffer_info, 0, size); + + memset(tx_ring->desc, 0, tx_ring->size); + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + + writel(0, adapter->hw.hw_addr + tx_ring->head); + writel(0, adapter->hw.hw_addr + tx_ring->tail); +} + +/** + * e1000_free_tx_resources - Free Tx Resources per Queue + * @adapter: board private structure + * + * Free all transmit software resources + **/ +void e1000_free_tx_resources(struct e1000_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + struct e1000_ring *tx_ring = adapter->tx_ring; + + e1000_clean_tx_ring(adapter); + + vfree(tx_ring->buffer_info); + tx_ring->buffer_info = NULL; + + dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, + tx_ring->dma); + tx_ring->desc = NULL; +} + +/** + * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split + * @adapter: board private structure + * + * the return value indicates whether actual cleaning was done, there + * is no guarantee that everything was cleaned + **/ +#ifdef CONFIG_E1000E_NAPI +static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, + int *work_done, int work_to_do) +#else +static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) +#endif +{ + union e1000_rx_desc_packet_split *rx_desc, *next_rxd; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info, *next_buffer; + struct e1000_ps_page *ps_page; + struct sk_buff *skb; + unsigned int i, j; + u32 length, staterr; + int cleaned_count = 0; + bool cleaned = 0; + unsigned int total_rx_bytes = 0, total_rx_packets = 0; + + i = rx_ring->next_to_clean; + rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + staterr = le32_to_cpu(rx_desc->wb.middle.status_error); + buffer_info = &rx_ring->buffer_info[i]; + + while (staterr & E1000_RXD_STAT_DD) { +#ifdef CONFIG_E1000E_NAPI + if (*work_done >= work_to_do) + break; + (*work_done)++; +#endif + skb = buffer_info->skb; + + /* in the packet split case this is header only */ + prefetch(skb->data - NET_IP_ALIGN); + + i++; + if (i == rx_ring->count) + i = 0; + next_rxd = E1000_RX_DESC_PS(*rx_ring, i); + prefetch(next_rxd); + + next_buffer = &rx_ring->buffer_info[i]; + + cleaned = 1; + cleaned_count++; + pci_unmap_single(pdev, buffer_info->dma, + adapter->rx_ps_bsize0, + PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; + + if (!(staterr & E1000_RXD_STAT_EOP)) { + e_dbg("Packet Split buffers didn't pick up the full" + " packet\n"); + dev_kfree_skb_irq(skb); + goto next_desc; + } + + if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { + dev_kfree_skb_irq(skb); + goto next_desc; + } + + length = le16_to_cpu(rx_desc->wb.middle.length0); + + if (!length) { + e_dbg("Last part of the packet spanning multiple" + " descriptors\n"); + dev_kfree_skb_irq(skb); + goto next_desc; + } + + /* Good Receive */ + skb_put(skb, length); + +#ifdef CONFIG_E1000E_NAPI + { + /* + * this looks ugly, but it seems compiler issues make it + * more efficient than reusing j + */ + int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); + + /* + * page alloc/put takes too long and effects small packet + * throughput, so unsplit small packets and save the alloc/put + * only valid in softirq (napi) context to call kmap_* + */ + if (l1 && (l1 <= copybreak) && + ((length + l1) <= adapter->rx_ps_bsize0)) { + u8 *vaddr; + + ps_page = &buffer_info->ps_pages[0]; + + /* + * there is no documentation about how to call + * kmap_atomic, so we can't hold the mapping + * very long + */ + pci_dma_sync_single_for_cpu(pdev, ps_page->dma, + PAGE_SIZE, PCI_DMA_FROMDEVICE); + vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ); + memcpy(skb_tail_pointer(skb), vaddr, l1); + kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); + pci_dma_sync_single_for_device(pdev, ps_page->dma, + PAGE_SIZE, PCI_DMA_FROMDEVICE); + + skb_put(skb, l1); + goto copydone; + } /* if */ + } +#endif + + for (j = 0; j < PS_PAGE_BUFFERS; j++) { + length = le16_to_cpu(rx_desc->wb.upper.length[j]); + if (!length) + break; + + ps_page = &buffer_info->ps_pages[j]; + pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + ps_page->dma = 0; + skb_fill_page_desc(skb, j, ps_page->page, 0, length); + ps_page->page = NULL; + skb->len += length; + skb->data_len += length; + skb->truesize += length; + } + +#ifdef CONFIG_E1000E_NAPI +copydone: +#endif + total_rx_bytes += skb->len; + total_rx_packets++; + + e1000_rx_checksum(adapter, staterr, le16_to_cpu( + rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); + + if (rx_desc->wb.upper.header_status & + cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)) + adapter->rx_hdr_split++; + + e1000_receive_skb(adapter, netdev, skb, + staterr, rx_desc->wb.middle.vlan); + +next_desc: + rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); + buffer_info->skb = NULL; + + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >= E1000_RX_BUFFER_WRITE) { + adapter->alloc_rx_buf(adapter, cleaned_count); + cleaned_count = 0; + } + + /* use prefetched values */ + rx_desc = next_rxd; + buffer_info = next_buffer; + + staterr = le32_to_cpu(rx_desc->wb.middle.status_error); + } + rx_ring->next_to_clean = i; + + cleaned_count = e1000_desc_unused(rx_ring); + if (cleaned_count) + adapter->alloc_rx_buf(adapter, cleaned_count); + + adapter->total_rx_packets += total_rx_packets; + adapter->total_rx_bytes += total_rx_bytes; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; +} + +#ifdef CONFIG_E1000E_NAPI +/* NOTE: these new jumbo frame routines rely on NAPI because of the + * pskb_may_pull call, which eventually must call kmap_atomic which you cannot + * call from hard irq context */ + +/** + * e1000_consume_page - helper function + **/ +static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, + u16 length) +{ + bi->page = NULL; + skb->len += length; + skb->data_len += length; + skb->truesize += length; +} + +/** + * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy + * @adapter: board private structure + * + * the return value indicates whether actual cleaning was done, there + * is no guarantee that everything was cleaned + **/ + +static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, + int *work_done, int work_to_do) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_rx_desc *rx_desc, *next_rxd; + struct e1000_buffer *buffer_info, *next_buffer; + u32 length; + unsigned int i; + int cleaned_count = 0; + bool cleaned = FALSE; + unsigned int total_rx_bytes=0, total_rx_packets=0; + + i = rx_ring->next_to_clean; + rx_desc = E1000_RX_DESC(*rx_ring, i); + buffer_info = &rx_ring->buffer_info[i]; + + while (rx_desc->status & E1000_RXD_STAT_DD) { + struct sk_buff *skb; + u8 status; + + if (*work_done >= work_to_do) + break; + (*work_done)++; + + status = rx_desc->status; + skb = buffer_info->skb; + buffer_info->skb = NULL; + + ++i; + if (i == rx_ring->count) + i = 0; + next_rxd = E1000_RX_DESC(*rx_ring, i); + prefetch(next_rxd); + + next_buffer = &rx_ring->buffer_info[i]; + + cleaned = TRUE; + cleaned_count++; + pci_unmap_page(pdev, buffer_info->dma, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; + + length = le16_to_cpu(rx_desc->length); + + /* errors is only valid for DD + EOP descriptors */ + if (unlikely((status & E1000_RXD_STAT_EOP) && + (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) { + /* recycle both page and skb */ + buffer_info->skb = skb; + /* an error means any chain goes out the window + * too */ + if (rx_ring->rx_skb_top) + dev_kfree_skb(rx_ring->rx_skb_top); + rx_ring->rx_skb_top = NULL; + goto next_desc; + } + +#define rxtop rx_ring->rx_skb_top + if (!(status & E1000_RXD_STAT_EOP)) { + /* this descriptor is only the beginning (or middle) */ + if (!rxtop) { + /* this is the beginning of a chain */ + rxtop = skb; + skb_fill_page_desc(rxtop, 0, buffer_info->page, + 0, length); + } else { + /* this is the middle of a chain */ + skb_fill_page_desc(rxtop, + skb_shinfo(rxtop)->nr_frags, + buffer_info->page, 0, length); + /* re-use the skb, only consumed the page */ + buffer_info->skb = skb; + } + e1000_consume_page(buffer_info, rxtop, length); + goto next_desc; + } else { + if (rxtop) { + /* end of the chain */ + skb_fill_page_desc(rxtop, + skb_shinfo(rxtop)->nr_frags, + buffer_info->page, 0, length); + /* re-use the current skb, we only consumed the + * page */ + buffer_info->skb = skb; + skb = rxtop; + rxtop = NULL; + e1000_consume_page(buffer_info, skb, length); + } else { + /* no chain, got EOP, this buf is the packet + * copybreak to save the put_page/alloc_page */ + if (length <= copybreak && + skb_tailroom(skb) >= length) { + u8 *vaddr; + vaddr = kmap_atomic(buffer_info->page, + KM_SKB_DATA_SOFTIRQ); + memcpy(skb_tail_pointer(skb), vaddr, + length); + kunmap_atomic(vaddr, + KM_SKB_DATA_SOFTIRQ); + /* re-use the page, so don't erase + * buffer_info->page */ + skb_put(skb, length); + } else { + skb_fill_page_desc(skb, 0, + buffer_info->page, 0, + length); + e1000_consume_page(buffer_info, skb, + length); + } + } + } + + /* Receive Checksum Offload XXX recompute due to CRC strip? */ + e1000_rx_checksum(adapter, + (u32)(status) | + ((u32)(rx_desc->errors) << 24), + le16_to_cpu(rx_desc->csum), skb); + + /* probably a little skewed due to removing CRC */ + total_rx_bytes += skb->len; + total_rx_packets++; + + /* eth type trans needs skb->data to point to something */ + if (!pskb_may_pull(skb, ETH_HLEN)) { + e_err("pskb_may_pull failed.\n"); + dev_kfree_skb(skb); + goto next_desc; + } + + e1000_receive_skb(adapter, netdev, skb, status, + rx_desc->special); + +next_desc: + rx_desc->status = 0; + + /* return some buffers to hardware, one at a time is too slow */ + if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { + adapter->alloc_rx_buf(adapter, cleaned_count); + cleaned_count = 0; + } + + /* use prefetched values */ + rx_desc = next_rxd; + buffer_info = next_buffer; + } + rx_ring->next_to_clean = i; + + cleaned_count = e1000_desc_unused(rx_ring); + if (cleaned_count) + adapter->alloc_rx_buf(adapter, cleaned_count); + + adapter->total_rx_packets += total_rx_packets; + adapter->total_rx_bytes += total_rx_bytes; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; +} +#endif /* CONFIG_E1000E_NAPI */ + +/** + * e1000_clean_rx_ring - Free Rx Buffers per Queue + * @adapter: board private structure + **/ +static void e1000_clean_rx_ring(struct e1000_adapter *adapter) +{ + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info; + struct e1000_ps_page *ps_page; + struct pci_dev *pdev = adapter->pdev; + unsigned int i, j; + + /* Free all the Rx ring sk_buffs */ + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + if (buffer_info->dma) { + if (adapter->clean_rx == e1000_clean_rx_irq) + pci_unmap_single(pdev, buffer_info->dma, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); +#ifdef CONFIG_E1000E_NAPI + else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) + pci_unmap_page(pdev, buffer_info->dma, + PAGE_SIZE, + PCI_DMA_FROMDEVICE); +#endif + else if (adapter->clean_rx == e1000_clean_rx_irq_ps) + pci_unmap_single(pdev, buffer_info->dma, + adapter->rx_ps_bsize0, + PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; + } + + if (buffer_info->page) { + put_page(buffer_info->page); + buffer_info->page = NULL; + } + + if (buffer_info->skb) { + dev_kfree_skb(buffer_info->skb); + buffer_info->skb = NULL; + } + + for (j = 0; j < PS_PAGE_BUFFERS; j++) { + ps_page = &buffer_info->ps_pages[j]; + if (!ps_page->page) + break; + pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + ps_page->dma = 0; + put_page(ps_page->page); + ps_page->page = NULL; + } + } + +#ifdef CONFIG_E1000E_NAPI + /* there also may be some cached data from a chained receive */ + if (rx_ring->rx_skb_top) { + dev_kfree_skb(rx_ring->rx_skb_top); + rx_ring->rx_skb_top = NULL; + } +#endif + + /* Zero out the descriptor ring */ + memset(rx_ring->desc, 0, rx_ring->size); + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + + writel(0, adapter->hw.hw_addr + rx_ring->head); + writel(0, adapter->hw.hw_addr + rx_ring->tail); +} + +/** + * e1000_free_rx_resources - Free Rx Resources + * @adapter: board private structure + * + * Free all receive software resources + **/ + +void e1000_free_rx_resources(struct e1000_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + struct e1000_ring *rx_ring = adapter->rx_ring; + int i; + + e1000_clean_rx_ring(adapter); + + for (i = 0; i < rx_ring->count; i++) { + kfree(rx_ring->buffer_info[i].ps_pages); + } + + vfree(rx_ring->buffer_info); + rx_ring->buffer_info = NULL; + + dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, + rx_ring->dma); + rx_ring->desc = NULL; +} + +/** + * e1000_update_itr - update the dynamic ITR value based on statistics + * @adapter: pointer to adapter + * @itr_setting: current adapter->itr + * @packets: the number of packets during this measurement interval + * @bytes: the number of bytes during this measurement interval + * + * Stores a new ITR value based on packets and byte + * counts during the last interrupt. The advantage of per interrupt + * computation is faster updates and more accurate ITR for the current + * traffic pattern. Constants in this function were computed + * based on theoretical maximum wire speed and thresholds were set based + * on testing data as well as attempting to minimize response time + * while increasing bulk throughput. This functionality is controlled + * by the InterruptThrottleRate module parameter. + **/ +static unsigned int e1000_update_itr(struct e1000_adapter *adapter, + u16 itr_setting, int packets, + int bytes) +{ + unsigned int retval = itr_setting; + + if (packets == 0) + goto update_itr_done; + + switch (itr_setting) { + case lowest_latency: + /* handle TSO and jumbo frames */ + if (bytes/packets > 8000) + retval = bulk_latency; + else if ((packets < 5) && (bytes > 512)) { + retval = low_latency; + } + break; + case low_latency: /* 50 usec aka 20000 ints/s */ + if (bytes > 10000) { + /* this if handles the TSO accounting */ + if (bytes/packets > 8000) { + retval = bulk_latency; + } else if ((packets < 10) || ((bytes/packets) > 1200)) { + retval = bulk_latency; + } else if ((packets > 35)) { + retval = lowest_latency; + } + } else if (bytes/packets > 2000) { + retval = bulk_latency; + } else if (packets <= 2 && bytes < 512) { + retval = lowest_latency; + } + break; + case bulk_latency: /* 250 usec aka 4000 ints/s */ + if (bytes > 25000) { + if (packets > 35) { + retval = low_latency; + } + } else if (bytes < 6000) { + retval = low_latency; + } + break; + } + +update_itr_done: + return retval; +} + +static void e1000_set_itr(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u16 current_itr; + u32 new_itr = adapter->itr; + + /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ + if (adapter->link_speed != SPEED_1000) { + current_itr = 0; + new_itr = 4000; + goto set_itr_now; + } + + adapter->tx_itr = e1000_update_itr(adapter, + adapter->tx_itr, + adapter->total_tx_packets, + adapter->total_tx_bytes); + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) + adapter->tx_itr = low_latency; + + adapter->rx_itr = e1000_update_itr(adapter, + adapter->rx_itr, + adapter->total_rx_packets, + adapter->total_rx_bytes); + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) + adapter->rx_itr = low_latency; + + current_itr = max(adapter->rx_itr, adapter->tx_itr); + + switch (current_itr) { + /* counts and packets in update_itr are dependent on these numbers */ + case lowest_latency: + new_itr = 70000; + break; + case low_latency: + new_itr = 20000; /* aka hwitr = ~200 */ + break; + case bulk_latency: + new_itr = 4000; + break; + default: + break; + } + +set_itr_now: + if (new_itr != adapter->itr) { + /* + * this attempts to bias the interrupt rate towards Bulk + * by adding intermediate steps when interrupt rate is + * increasing + */ + new_itr = new_itr > adapter->itr ? + min(adapter->itr + (new_itr >> 2), new_itr) : + new_itr; + adapter->itr = new_itr; +#ifdef CONFIG_E1000E_MSIX + adapter->rx_ring->itr_val = new_itr; + if (adapter->msix_entries) + adapter->rx_ring->set_itr = 1; + else +#endif + ew32(ITR, 1000000000 / (new_itr * 256)); + } +} + +/** + * e1000_clean_tx_irq - Reclaim resources after transmit completes + * @adapter: board private structure + * + * the return value indicates if there is more work to do (later) + **/ +static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_tx_desc *tx_desc, *eop_desc; + struct e1000_buffer *buffer_info; + unsigned int i, eop; + bool cleaned = 0, retval = 1; + unsigned int total_tx_bytes = 0, total_tx_packets = 0; + + i = tx_ring->next_to_clean; + eop = tx_ring->buffer_info[i].next_to_watch; + eop_desc = E1000_TX_DESC(*tx_ring, eop); + + while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { + for (cleaned = 0; !cleaned; ) { + tx_desc = E1000_TX_DESC(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; + cleaned = (i == eop); + + if (cleaned) { + struct sk_buff *skb = buffer_info->skb; +#ifdef NETIF_F_TSO + unsigned int segs, bytecount; + segs = skb_shinfo(skb)->gso_segs ?: 1; + /* multiply data chunks by size of headers */ + bytecount = ((segs - 1) * skb_headlen(skb)) + + skb->len; + total_tx_packets += segs; + total_tx_bytes += bytecount; +#else + total_tx_packets++; + total_tx_bytes += skb->len; +#endif + } + + e1000_put_txbuf(adapter, buffer_info); + tx_desc->upper.data = 0; + + i++; + if (i == tx_ring->count) + i = 0; +#ifdef CONFIG_E1000E_NAPI + if (total_tx_packets >= tx_ring->count) { + retval = 0; + goto done_cleaning; + } +#endif + } + + eop = tx_ring->buffer_info[i].next_to_watch; + eop_desc = E1000_TX_DESC(*tx_ring, eop); + } + +#ifdef CONFIG_E1000E_NAPI +done_cleaning: +#endif + tx_ring->next_to_clean = i; + +#define TX_WAKE_THRESHOLD 32 + if (cleaned && netif_carrier_ok(netdev) && + e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { + /* + * Make sure that anybody stopping the queue after this + * sees the new next_to_clean. + */ + smp_mb(); + + if (netif_queue_stopped(netdev) && + !(test_bit(__E1000_DOWN, &adapter->state))) { + netif_wake_queue(netdev); + ++adapter->restart_queue; + } + } + + if (adapter->detect_tx_hung) { + /* + * Detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of i + */ + adapter->detect_tx_hung = 0; + if (tx_ring->buffer_info[eop].dma && + time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + + (adapter->tx_timeout_factor * HZ)) + && !(er32(STATUS) & E1000_STATUS_TXOFF)) { + e1000_print_tx_hang(adapter); + netif_stop_queue(netdev); + } + } + adapter->total_tx_bytes += total_tx_bytes; + adapter->total_tx_packets += total_tx_packets; + adapter->net_stats.tx_bytes += total_tx_bytes; + adapter->net_stats.tx_packets += total_tx_packets; + return retval; +} + +/** + * e1000_intr_msi - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +static irqreturn_t e1000_intr_msi(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; +#ifndef CONFIG_E1000E_NAPI + int i; +#endif + /* read ICR disables interrupts using IAM */ + u32 icr = er32(ICR); + + if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + hw->mac.get_link_status = 1; + /* + * ICH8 workaround-- Call gig speed drop workaround on cable + * disconnect (LSC) before accessing any PHY registers + */ + if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && + (!(er32(STATUS) & E1000_STATUS_LU))) + e1000_gig_downshift_workaround_ich8lan(hw); + + /* + * 80003ES2LAN workaround-- For packet buffer work-around on + * link down event; disable receives here in the ISR and reset + * adapter in watchdog + */ + if (netif_carrier_ok(netdev) && + adapter->flags & FLAG_RX_NEEDS_RESTART) { + /* disable receives */ + u32 rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + adapter->flags |= FLAG_RX_RESTART_NOW; + } + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + +#ifdef CONFIG_E1000E_NAPI + if (netif_rx_schedule_prep(netdev, &adapter->napi)) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; + __netif_rx_schedule(netdev, &adapter->napi); + } +#else + adapter->total_tx_bytes = 0; + adapter->total_rx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_packets = 0; + + for (i = 0; i < E1000_MAX_INTR; i++) { + int rx_cleaned = adapter->clean_rx(adapter); + int tx_cleaned_complete = e1000_clean_tx_irq(adapter); + if (!rx_cleaned && tx_cleaned_complete) + break; + } + + if (likely(adapter->itr_setting & 3)) + e1000_set_itr(adapter); +#endif /* CONFIG_E1000E_NAPI */ + + return IRQ_HANDLED; +} + +/** + * e1000_intr - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +static irqreturn_t e1000_intr(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; +#ifndef CONFIG_E1000E_NAPI + int i; + int rx_cleaned, tx_cleaned_complete; +#endif + u32 rctl, icr = er32(ICR); + + if (!icr) + return IRQ_NONE; /* Not our interrupt */ + +#ifdef CONFIG_E1000E_NAPI + /* + * IMS will not auto-mask if INT_ASSERTED is not set, and if it is + * not set, then the adapter didn't send an interrupt + */ + if (!(icr & E1000_ICR_INT_ASSERTED)) + return IRQ_NONE; + +#endif /* CONFIG_E1000E_NAPI */ + if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + hw->mac.get_link_status = 1; + /* + * ICH8 workaround-- Call gig speed drop workaround on cable + * disconnect (LSC) before accessing any PHY registers + */ + if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && + (!(er32(STATUS) & E1000_STATUS_LU))) + e1000_gig_downshift_workaround_ich8lan(hw); + + /* + * 80003ES2LAN workaround-- + * For packet buffer work-around on link down event; + * disable receives here in the ISR and + * reset adapter in watchdog + */ + if (netif_carrier_ok(netdev) && + (adapter->flags & FLAG_RX_NEEDS_RESTART)) { + /* disable receives */ + rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + adapter->flags |= FLAG_RX_RESTART_NOW; + } + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + +#ifdef CONFIG_E1000E_NAPI + if (netif_rx_schedule_prep(netdev, &adapter->napi)) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; + __netif_rx_schedule(netdev, &adapter->napi); + } +#else + adapter->total_tx_bytes = 0; + adapter->total_rx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_packets = 0; + + for (i = 0; i < E1000_MAX_INTR; i++) { + rx_cleaned = adapter->clean_rx(adapter); + tx_cleaned_complete = e1000_clean_tx_irq(adapter); + if (!rx_cleaned && tx_cleaned_complete) + break; + } + + if (likely(adapter->itr_setting & 3)) + e1000_set_itr(adapter); +#endif /* CONFIG_E1000E_NAPI */ + + return IRQ_HANDLED; +} + +#ifdef CONFIG_E1000E_MSIX +static irqreturn_t e1000_msix_other(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 icr = er32(ICR); + + if (!(icr & E1000_ICR_INT_ASSERTED)) + { + ew32(IMS, E1000_IMS_OTHER); + return IRQ_NONE; + } + + if (icr & adapter->eiac_mask) + ew32(ICS, (icr & adapter->eiac_mask)); + + if (icr & E1000_ICR_OTHER) { + if (!(icr & E1000_ICR_LSC)) + goto no_link_interrupt; + hw->mac.get_link_status = 1; + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + +no_link_interrupt: + ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER); + + return IRQ_HANDLED; +} + + +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER +static irqreturn_t e1000_intr_msix_tx(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *tx_ring = adapter->tx_ring; + + + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + + if (!e1000_clean_tx_irq(adapter)) + /* Ring was not completely cleaned, so fire another interrupt */ + ew32(ICS, tx_ring->ims_val); + + return IRQ_HANDLED; +} + +#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */ +static irqreturn_t e1000_intr_msix_rx(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); +#ifndef CONFIG_E1000E_NAPI + int i; + struct e1000_hw *hw = &adapter->hw; +#endif + + /* Write the ITR value calculated at the end of the + * previous interrupt. + */ + if (adapter->rx_ring->set_itr) { + writel(1000000000 / (adapter->rx_ring->itr_val * 256), + adapter->hw.hw_addr + adapter->rx_ring->itr_register); + adapter->rx_ring->set_itr = 0; + } + +#ifdef CONFIG_E1000E_NAPI + if (netif_rx_schedule_prep(netdev, &adapter->napi)) { + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +#ifndef CONFIG_E1000E_SEPARATE_TX_HANDLER + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; +#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */ + __netif_rx_schedule(netdev, &adapter->napi); + } +#else + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +#ifndef CONFIG_E1000E_SEPARATE_TX_HANDLER + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; +#endif + + for (i = 0; i < E1000_MAX_INTR; i++) { + int rx_cleaned = adapter->clean_rx(adapter); +#ifndef CONFIG_E1000E_SEPARATE_TX_HANDLER + int tx_cleaned_complete = e1000_clean_tx_irq(adapter); + if (!rx_cleaned && tx_cleaned_complete) +#else + if (!rx_cleaned) +#endif + goto out; + } + /* If we got here, the ring was not completely cleaned, + * so fire another interrupt. + */ + ew32(ICS, adapter->rx_ring->ims_val); + +out: +#endif /* CONFIG_E1000E_NAPI */ + return IRQ_HANDLED; +} + +/** + * e1000_configure_msix - Configure MSI-X hardware + * + * e1000_configure_msix sets up the hardware to properly + * generate MSI-X interrupts. + **/ +static void e1000_configure_msix(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_ring *tx_ring = adapter->tx_ring; + int vector = 0; + u32 ctrl_ext, ivar = 0; + + adapter->eiac_mask = 0; + + /* Workaround issue with spurious interrupts on 82574 in MSI-X mode */ + if (hw->mac.type == e1000_82574) { + u32 rfctl = er32(RFCTL); + rfctl |= E1000_RFCTL_ACK_DIS; + ew32(RFCTL, rfctl); + } + +#define E1000_IVAR_INT_ALLOC_VALID 0x8 + /* Configure Rx vector */ + rx_ring->ims_val = E1000_IMS_RXQ0; + adapter->eiac_mask |= rx_ring->ims_val; + if (rx_ring->itr_val) + writel(1000000000 / (rx_ring->itr_val * 256), + hw->hw_addr + rx_ring->itr_register); + else + writel(1, hw->hw_addr + rx_ring->itr_register); + ivar = E1000_IVAR_INT_ALLOC_VALID | vector; + + /* Configure Tx vector */ + tx_ring->ims_val = E1000_IMS_TXQ0; +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER + vector++; + if (tx_ring->itr_val) + writel(1000000000 / (tx_ring->itr_val * 256), + hw->hw_addr + tx_ring->itr_register); + else + writel(1, hw->hw_addr + tx_ring->itr_register); +#else + rx_ring->ims_val |= tx_ring->ims_val; +#endif + adapter->eiac_mask |= tx_ring->ims_val; + ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8); + + /* set vector for Other Causes, e.g. link changes */ + vector++; + ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 16); + if (rx_ring->itr_val) + writel(1000000000 / (rx_ring->itr_val * 256), + hw->hw_addr + E1000_EITR_82574(vector)); + else + writel(1, hw->hw_addr + E1000_EITR_82574(vector)); + + /* Cause Tx interrupts on every write back */ + ivar |= (1 << 31); + + ew32(IVAR, ivar); + + /* enable MSI-X PBA support */ + ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_PBA_CLR; + + /* Auto-Mask Other interrupts upon ICR read */ + ew32(IAM, ~E1000_EIAC_MASK_82574 | E1000_IMS_OTHER); + ctrl_ext |= E1000_CTRL_EXT_EIAME; + ew32(CTRL_EXT, ctrl_ext); + e1e_flush(); +} + +void e1000_reset_interrupt_capability(struct e1000_adapter *adapter) +{ + if (adapter->msix_entries) { + pci_disable_msix(adapter->pdev); + kfree(adapter->msix_entries); + adapter->msix_entries = NULL; + } else if (adapter->flags & FLAG_MSI_ENABLED) { + pci_disable_msi(adapter->pdev); + adapter->flags &= ~FLAG_MSI_ENABLED; + } + + return; +} + +/** + * e1000_set_interrupt_capability - set MSI or MSI-X if supported + * + * Attempt to configure interrupts using the best available + * capabilities of the hardware and kernel. + **/ +void e1000_set_interrupt_capability(struct e1000_adapter *adapter) +{ + int err; + int numvecs, i; + + + switch (adapter->int_mode) { + case E1000E_INT_MODE_MSIX: + if (adapter->flags & FLAG_HAS_MSIX) { +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER + numvecs = 3; /* RxQ0, TxQ0 and other */ +#else + numvecs = 2; /* RxQ0/TxQ0 and other */ +#endif + adapter->msix_entries = kcalloc(numvecs, + sizeof(struct msix_entry), + GFP_KERNEL); + if (adapter->msix_entries) { + for (i=0; i < numvecs; i++) + adapter->msix_entries[i].entry = i; + + err = pci_enable_msix(adapter->pdev, + adapter->msix_entries, + numvecs); + if (err == 0) + return; + } + /* MSI-X failed, so fall through and try MSI */ + e_err("Failed to initialize MSI-X interrupts. " + "Falling back to MSI interrupts.\n"); + e1000_reset_interrupt_capability(adapter); + } + adapter->int_mode = E1000E_INT_MODE_MSI; + /* Fall through */ + case E1000E_INT_MODE_MSI: + if (!pci_enable_msi(adapter->pdev)) { + adapter->flags |= FLAG_MSI_ENABLED; + } else { + adapter->int_mode = E1000E_INT_MODE_LEGACY; + e_err("Failed to initialize MSI interrupts. Falling " + "back to legacy interrupts.\n"); + } + /* Fall through */ + case E1000E_INT_MODE_LEGACY: + /* Don't do anything; this is the system default */ + break; + } + + return; +} + +/** + * e1000_request_msix - Initialize MSI-X interrupts + * + * e1000_request_msix allocates MSI-X vectors and requests interrupts from the + * kernel. + **/ +static int e1000_request_msix(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int err = 0, vector = 0; + + if (strlen(netdev->name) < (IFNAMSIZ - 5)) +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER + sprintf(adapter->rx_ring->name, "%s-rx0", netdev->name); +#else + sprintf(adapter->rx_ring->name, "%s-Q0", netdev->name); +#endif + else + memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ); + err = request_irq(adapter->msix_entries[vector].vector, + &e1000_intr_msix_rx, 0, adapter->rx_ring->name, + netdev); + if (err) + goto out; + adapter->rx_ring->itr_register = E1000_EITR_82574(vector); + adapter->rx_ring->itr_val = adapter->itr; + vector++; + +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER + if (strlen(netdev->name) < (IFNAMSIZ - 5)) + sprintf(adapter->tx_ring->name, "%s-tx0", netdev->name); + else + memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ); + err = request_irq(adapter->msix_entries[vector].vector, + &e1000_intr_msix_tx, 0, adapter->tx_ring->name, + netdev); + if (err) + goto out; + adapter->tx_ring->itr_register = E1000_EITR_82574(vector); + adapter->tx_ring->itr_val = adapter->itr; + vector++; + +#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */ + err = request_irq(adapter->msix_entries[vector].vector, + &e1000_msix_other, 0, netdev->name, netdev); + if (err) + goto out; + + e1000_configure_msix(adapter); + return 0; +out: + return err; +} + +#endif /* CONFIG_E1000E_MSIX */ +/** + * e1000_alloc_queues - Allocate memory for all rings + * @adapter: board private structure to initialize + **/ +static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) +{ + adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); + if (!adapter->tx_ring) + goto err; + + adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); + if (!adapter->rx_ring) + goto err; + + return 0; +err: + e_err("Unable to allocate memory for queues\n"); + kfree(adapter->rx_ring); + kfree(adapter->tx_ring); + return -ENOMEM; +} + +/** + * e1000_request_irq - initialize interrupts + * + * Attempts to configure interrupts using the best available + * capabilities of the hardware and kernel. + **/ +static int e1000_request_irq(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int err; +#ifdef CONFIG_E1000E_MSIX + + if (adapter->msix_entries) { + err = e1000_request_msix(adapter); + if (!err) + return err; + /* fall back to MSI */ + e1000_reset_interrupt_capability(adapter); + adapter->int_mode = E1000E_INT_MODE_MSI; + e1000_set_interrupt_capability(adapter); + } + if (adapter->flags & FLAG_MSI_ENABLED) { + err = request_irq(adapter->pdev->irq, &e1000_intr_msi, 0, + netdev->name, netdev); + if (!err) + return err; + + /* fall back to legacy interrupt */ + e1000_reset_interrupt_capability(adapter); + adapter->int_mode = E1000E_INT_MODE_LEGACY; + } + + err = request_irq(adapter->pdev->irq, &e1000_intr, IRQF_SHARED, + netdev->name, netdev); + if (err) + e_err("Unable to allocate interrupt, Error: %d\n", err); +#else + int irq_flags = IRQF_SHARED; + + if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) { + err = pci_enable_msi(adapter->pdev); + if (!err) { + adapter->flags |= FLAG_MSI_ENABLED; + irq_flags = 0; + } + } + + err = request_irq(adapter->pdev->irq, + ((adapter->flags & FLAG_MSI_ENABLED) ? + &e1000_intr_msi : &e1000_intr), + irq_flags, netdev->name, netdev); + if (err) { + if (adapter->flags & FLAG_MSI_ENABLED) { + pci_disable_msi(adapter->pdev); + adapter->flags &= ~FLAG_MSI_ENABLED; + } + e_err("Unable to allocate interrupt, Error: %d\n", err); + } +#endif /* CONFIG_E1000E_MSIX */ + + return err; +} + +static void e1000_free_irq(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + +#ifdef CONFIG_E1000E_MSIX + if (adapter->msix_entries) { + int vector = 0; + + free_irq(adapter->msix_entries[vector].vector, netdev); + vector++; + +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER + free_irq(adapter->msix_entries[vector].vector, netdev); + vector++; + +#endif + /* Other Causes interrupt vector */ + free_irq(adapter->msix_entries[vector].vector, netdev); + return; + } + +#endif /* CONFIG_E1000E_MSIX */ + free_irq(adapter->pdev->irq, netdev); +#ifndef CONFIG_E1000E_MSIX + if (adapter->flags & FLAG_MSI_ENABLED) { + pci_disable_msi(adapter->pdev); + adapter->flags &= ~FLAG_MSI_ENABLED; + } +#endif +} + +/** + * e1000_irq_disable - Mask off interrupt generation on the NIC + **/ +static void e1000_irq_disable(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + + ew32(IMC, ~0); +#ifdef CONFIG_E1000E_MSIX + if (adapter->msix_entries) { + ew32(EIAC_82574, 0); + } +#endif /* CONFIG_E1000E_MSIX */ + e1e_flush(); + synchronize_irq(adapter->pdev->irq); +} + +/** + * e1000_irq_enable - Enable default interrupt generation settings + **/ +static void e1000_irq_enable(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; +#ifdef CONFIG_E1000E_MSIX + + if (adapter->msix_entries) { + ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); + ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); + } else { + ew32(IMS, IMS_ENABLE_MASK); + } +#else + ew32(IMS, IMS_ENABLE_MASK); +#endif /* CONFIG_E1000E_MSIX */ +} + +/** + * e1000_get_hw_control - get control of the h/w from f/w + * @adapter: address of board private structure + * + * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. + * For ASF and Pass Through versions of f/w this means that + * the driver is loaded. For AMT version (only with 82573) + * of the f/w this means that the network i/f is open. + **/ +static void e1000_get_hw_control(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl_ext; + u32 swsm; + + /* Let firmware know the driver has taken over */ + if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { + swsm = er32(SWSM); + ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD); + } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { + ctrl_ext = er32(CTRL_EXT); + ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); + } +} + +/** + * e1000_release_hw_control - release control of the h/w to f/w + * @adapter: address of board private structure + * + * e1000_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. + * For ASF and Pass Through versions of f/w this means that the + * driver is no longer loaded. For AMT version (only with 82573) i + * of the f/w this means that the network i/f is closed. + * + **/ +static void e1000_release_hw_control(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl_ext; + u32 swsm; + + /* Let firmware taken over control of h/w */ + if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { + swsm = er32(SWSM); + ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD); + } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { + ctrl_ext = er32(CTRL_EXT); + ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); + } +} + +#ifdef CONFIG_E1000E_NAPI +/** + * e1000_poll - NAPI Rx polling callback + * @napi: struct associated with this polling callback + * @budget: amount of packets driver is allowed to process this poll + **/ +static int e1000_poll(struct napi_struct *napi, int budget) +{ + struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, + napi); + struct net_device *netdev = adapter->netdev; + int tx_clean_complete = 1, work_done = 0; +#ifdef CONFIG_E1000E_MSIX + struct e1000_hw *hw = &adapter->hw; + + if (adapter->msix_entries && + !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) + goto clean_rx; + +#endif + /* + * e1000_poll is called per-cpu. This lock protects + * tx_ring from being cleaned by multiple cpus + * simultaneously. A failure obtaining the lock means + * tx_ring is currently being cleaned anyway. + */ + if (spin_trylock(&adapter->tx_queue_lock)) { + tx_clean_complete &= e1000_clean_tx_irq(adapter); + spin_unlock(&adapter->tx_queue_lock); + } + +#ifdef CONFIG_E1000E_MSIX +clean_rx: +#endif + adapter->clean_rx(adapter, &work_done, budget); + + /* If Tx completed and all Rx work done, exit the polling mode */ + if ((tx_clean_complete && (work_done == 0)) || !netif_running(netdev)) { + netif_rx_complete(netdev, napi); + if (adapter->itr_setting & 3) + e1000_set_itr(adapter); + if (!test_bit(__E1000_DOWN, &adapter->state)) { +#ifdef CONFIG_E1000E_MSIX + if (adapter->msix_entries) + ew32(IMS, adapter->rx_ring->ims_val); + else +#endif + e1000_irq_enable(adapter); + } + return 0; + } + + if (!tx_clean_complete) + work_done = budget; + + return work_done; +} + +#endif /* CONFIG_E1000E_NAPI */ +static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 vfta, index; + struct net_device *v_netdev; + + /* don't update vlan cookie if already programmed */ + if ((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && + (vid == adapter->mng_vlan_id)) + return; + /* add VID to filter table */ + index = (vid >> 5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); + vfta |= (1 << (vid & 0x1F)); + if (hw->mac.ops.write_vfta) + hw->mac.ops.write_vfta(hw, index, vfta); + /* + * Copy feature flags from netdev to the vlan netdev for this vid. + * This allows things like TSO to bubble down to our vlan device. + */ + v_netdev = vlan_group_get_device(adapter->vlgrp, vid); + v_netdev->features |= adapter->netdev->features; + vlan_group_set_device(adapter->vlgrp, vid, v_netdev); +} + +static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 vfta, index; + + if (!test_bit(__E1000_DOWN, &adapter->state)) + e1000_irq_disable(adapter); + vlan_group_set_device(adapter->vlgrp, vid, NULL); + if (!test_bit(__E1000_DOWN, &adapter->state)) + e1000_irq_enable(adapter); + + if ((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && + (vid == adapter->mng_vlan_id)) { + /* release control to f/w */ + e1000_release_hw_control(adapter); + return; + } + + /* remove VID from filter table */ + index = (vid >> 5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); + vfta &= ~(1 << (vid & 0x1F)); + if (hw->mac.ops.write_vfta) + hw->mac.ops.write_vfta(hw, index, vfta); +} + +static void e1000_update_mng_vlan(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + u16 vid = adapter->hw.mng_cookie.vlan_id; + u16 old_vid = adapter->mng_vlan_id; + + if (!adapter->vlgrp) + return; + + if (!vlan_group_get_device(adapter->vlgrp, vid)) { + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + if (adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { + e1000_vlan_rx_add_vid(netdev, vid); + adapter->mng_vlan_id = vid; + } + + if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && + (vid != old_vid) && + !vlan_group_get_device(adapter->vlgrp, old_vid)) + e1000_vlan_rx_kill_vid(netdev, old_vid); + } else { + adapter->mng_vlan_id = vid; + } +} + + +static void e1000_vlan_rx_register(struct net_device *netdev, + struct vlan_group *grp) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 ctrl, rctl; + + if (!test_bit(__E1000_DOWN, &adapter->state)) + e1000_irq_disable(adapter); + adapter->vlgrp = grp; + + if (grp) { + /* enable VLAN tag insert/strip */ + ctrl = er32(CTRL); + ctrl |= E1000_CTRL_VME; + ew32(CTRL, ctrl); + + if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { + /* enable VLAN receive filtering */ + rctl = er32(RCTL); + rctl |= E1000_RCTL_VFE; + rctl &= ~E1000_RCTL_CFIEN; + ew32(RCTL, rctl); + e1000_update_mng_vlan(adapter); + } + } else { + /* disable VLAN tag insert/strip */ + ctrl = er32(CTRL); + ctrl &= ~E1000_CTRL_VME; + ew32(CTRL, ctrl); + + if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { + /* disable VLAN filtering */ + rctl = er32(RCTL); + rctl &= ~E1000_RCTL_VFE; + ew32(RCTL, rctl); + if (adapter->mng_vlan_id != + (u16)E1000_MNG_VLAN_NONE) { + e1000_vlan_rx_kill_vid(netdev, + adapter->mng_vlan_id); + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + } + } + } + + if (!test_bit(__E1000_DOWN, &adapter->state)) + e1000_irq_enable(adapter); +} + +static void e1000_restore_vlan(struct e1000_adapter *adapter) +{ + u16 vid; + + e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp); + + if (!adapter->vlgrp) + return; + + for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + if (!vlan_group_get_device(adapter->vlgrp, vid)) + continue; + e1000_vlan_rx_add_vid(adapter->netdev, vid); + } +} + +static void e1000_init_manageability(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 manc, manc2h; + + if (!(adapter->flags & FLAG_MNG_PT_ENABLED)) + return; + + manc = er32(MANC); + + /* + * enable receiving management packets to the host. this will probably + * generate destination unreachable messages from the host OS, but + * the packets will be handled on SMBUS + */ + manc |= E1000_MANC_EN_MNG2HOST; + manc2h = er32(MANC2H); +#define E1000_MNG2HOST_PORT_623 (1 << 5) +#define E1000_MNG2HOST_PORT_664 (1 << 6) + manc2h |= E1000_MNG2HOST_PORT_623; + manc2h |= E1000_MNG2HOST_PORT_664; + ew32(MANC2H, manc2h); + ew32(MANC, manc); +} + +/** + * e1000_configure_tx - Configure 8254x Transmit Unit after Reset + * @adapter: board private structure + * + * Configure the Tx unit of the MAC after a reset. + **/ +static void e1000_configure_tx(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *tx_ring = adapter->tx_ring; + u64 tdba; + u32 tdlen, tctl, tipg, tarc; + u32 ipgr1, ipgr2; + + /* Setup the HW Tx Head and Tail descriptor pointers */ + tdba = tx_ring->dma; + tdlen = tx_ring->count * sizeof(struct e1000_tx_desc); + ew32(TDBAL(0), (tdba & DMA_32BIT_MASK)); + ew32(TDBAH(0), (tdba >> 32)); + ew32(TDLEN(0), tdlen); + ew32(TDH(0), 0); + ew32(TDT(0), 0); + tx_ring->head = E1000_TDH(0); + tx_ring->tail = E1000_TDT(0); + + /* Set the default values for the Tx Inter Packet Gap timer */ + tipg = DEFAULT_82543_TIPG_IPGT_COPPER; /* 8 */ + ipgr1 = DEFAULT_82543_TIPG_IPGR1; /* 8 */ + ipgr2 = DEFAULT_82543_TIPG_IPGR2; /* 6 */ + + if (adapter->flags & FLAG_TIPG_MEDIUM_FOR_80003ESLAN) + ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2; /* 7 */ + + tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT; + tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT; + ew32(TIPG, tipg); + + /* Set the Tx Interrupt Delay register */ + ew32(TIDV, adapter->tx_int_delay); + /* Tx irq moderation */ + ew32(TADV, adapter->tx_abs_int_delay); + + /* Program the Transmit Control Register */ + tctl = er32(TCTL); + tctl &= ~E1000_TCTL_CT; + tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | + (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + + if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { + tarc = er32(TARC(0)); + /* + * set the speed mode bit, we'll clear it if we're not at + * gigabit link later + */ +#define SPEED_MODE_BIT (1 << 21) + tarc |= SPEED_MODE_BIT; + ew32(TARC(0), tarc); + } + + /* errata: program both queues to unweighted RR */ + if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) { + tarc = er32(TARC(0)); + tarc |= 1; + ew32(TARC(0), tarc); + tarc = er32(TARC(1)); + tarc |= 1; + ew32(TARC(1), tarc); + } + + hw->mac.ops.config_collision_dist(hw); + + /* Setup Transmit Descriptor Settings for eop descriptor */ + adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; + + /* only set IDE if we are delaying interrupts using the timers */ + if (adapter->tx_int_delay) + adapter->txd_cmd |= E1000_TXD_CMD_IDE; + + /* enable Report Status bit */ + adapter->txd_cmd |= E1000_TXD_CMD_RS; + + ew32(TCTL, tctl); + + adapter->tx_queue_len = adapter->netdev->tx_queue_len; +} + +/** + * e1000_setup_rctl - configure the receive control registers + * @adapter: Board private structure + **/ +#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ + (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) +static void e1000_setup_rctl(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rctl, rfctl; + u32 psrctl = 0; + u32 pages = 0; + + /* Program MC offset vector base */ + rctl = er32(RCTL); + rctl &= ~(3 << E1000_RCTL_MO_SHIFT); + rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | + E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | + (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); + + /* Do not Store bad packets */ + rctl &= ~E1000_RCTL_SBP; + + /* Enable Long Packet receive */ + if (adapter->netdev->mtu <= ETH_DATA_LEN) + rctl &= ~E1000_RCTL_LPE; + else + rctl |= E1000_RCTL_LPE; + + /* Enable hardware CRC frame stripping */ + rctl |= E1000_RCTL_SECRC; + + /* Setup buffer sizes */ + rctl &= ~E1000_RCTL_SZ_4096; + rctl |= E1000_RCTL_BSEX; + switch (adapter->rx_buffer_len) { + case 256: + rctl |= E1000_RCTL_SZ_256; + rctl &= ~E1000_RCTL_BSEX; + break; + case 512: + rctl |= E1000_RCTL_SZ_512; + rctl &= ~E1000_RCTL_BSEX; + break; + case 1024: + rctl |= E1000_RCTL_SZ_1024; + rctl &= ~E1000_RCTL_BSEX; + break; + case 2048: + default: + rctl |= E1000_RCTL_SZ_2048; + rctl &= ~E1000_RCTL_BSEX; + break; + case 4096: + rctl |= E1000_RCTL_SZ_4096; + break; + case 8192: + rctl |= E1000_RCTL_SZ_8192; + break; + case 16384: + rctl |= E1000_RCTL_SZ_16384; + break; + } + + /* + * 82571 and greater support packet-split where the protocol + * header is placed in skb->data and the packet data is + * placed in pages hanging off of skb_shinfo(skb)->nr_frags. + * In the case of a non-split, skb->data is linearly filled, + * followed by the page buffers. Therefore, skb->data is + * sized to hold the largest protocol header. + * + * allocations using alloc_page take too long for regular MTU + * so only enable packet split for jumbo frames + * + * Using pages when the page size is greater than 16k wastes + * a lot of memory, since we allocate 3 pages at all times + * per packet. + */ + pages = PAGE_USE_COUNT(adapter->netdev->mtu); + if (!(adapter->flags & FLAG_IS_ICH) && (pages <= 3) && + (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) + adapter->rx_ps_pages = pages; + else + adapter->rx_ps_pages = 0; + + if (adapter->rx_ps_pages) { + /* Configure extra packet-split registers */ + rfctl = er32(RFCTL); + rfctl |= E1000_RFCTL_EXTEN; + /* + * disable packet split support for IPv6 extension headers, + * because some malformed IPv6 headers can hang the Rx + */ + rfctl |= (E1000_RFCTL_IPV6_EX_DIS | + E1000_RFCTL_NEW_IPV6_EXT_DIS); + + ew32(RFCTL, rfctl); + + /* Enable Packet split descriptors */ + rctl |= E1000_RCTL_DTYP_PS; + + psrctl |= adapter->rx_ps_bsize0 >> + E1000_PSRCTL_BSIZE0_SHIFT; + + switch (adapter->rx_ps_pages) { + case 3: + psrctl |= PAGE_SIZE << + E1000_PSRCTL_BSIZE3_SHIFT; + case 2: + psrctl |= PAGE_SIZE << + E1000_PSRCTL_BSIZE2_SHIFT; + case 1: + psrctl |= PAGE_SIZE >> + E1000_PSRCTL_BSIZE1_SHIFT; + break; + } + + ew32(PSRCTL, psrctl); + } + + ew32(RCTL, rctl); + /* just started the receive unit, no need to restart */ + adapter->flags &= ~FLAG_RX_RESTART_NOW; +} + +/** + * e1000_configure_rx - Configure Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Rx unit of the MAC after a reset. + **/ +static void e1000_configure_rx(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *rx_ring = adapter->rx_ring; + u64 rdba; + u32 rdlen, rctl, rxcsum, ctrl_ext; + + if (adapter->rx_ps_pages) { + /* this is a 32 byte descriptor */ + rdlen = rx_ring->count * + sizeof(union e1000_rx_desc_packet_split); + adapter->clean_rx = e1000_clean_rx_irq_ps; + adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; +#ifdef CONFIG_E1000E_NAPI + } else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) { + rdlen = rx_ring->count * sizeof(struct e1000_rx_desc); + adapter->clean_rx = e1000_clean_jumbo_rx_irq; + adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers; +#endif + } else { + rdlen = rx_ring->count * sizeof(struct e1000_rx_desc); + adapter->clean_rx = e1000_clean_rx_irq; + adapter->alloc_rx_buf = e1000_alloc_rx_buffers; + } + + /* disable receives while setting up the descriptors */ + rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + e1e_flush(); + msleep(10); + + /* set the Receive Delay Timer Register */ + ew32(RDTR, adapter->rx_int_delay); + + /* irq moderation */ + ew32(RADV, adapter->rx_abs_int_delay); + if (adapter->itr_setting != 0) + ew32(ITR, 1000000000 / (adapter->itr * 256)); + + ctrl_ext = er32(CTRL_EXT); + /* Reset delay timers after every interrupt */ + ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR; +#ifdef CONFIG_E1000E_NAPI + /* Auto-Mask interrupts upon ICR access */ + ctrl_ext |= E1000_CTRL_EXT_IAME; + ew32(IAM, 0xffffffff); +#endif + ew32(CTRL_EXT, ctrl_ext); + e1e_flush(); + + /* + * Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring + */ + rdba = rx_ring->dma; + ew32(RDBAL(0), (rdba & DMA_32BIT_MASK)); + ew32(RDBAH(0), (rdba >> 32)); + ew32(RDLEN(0), rdlen); + ew32(RDH(0), 0); + ew32(RDT(0), 0); + rx_ring->head = E1000_RDH(0); + rx_ring->tail = E1000_RDT(0); + + /* Enable Receive Checksum Offload for TCP and UDP */ + rxcsum = er32(RXCSUM); + if (adapter->flags & FLAG_RX_CSUM_ENABLED) { + rxcsum |= E1000_RXCSUM_TUOFL; + + /* + * IPv4 payload checksum for UDP fragments must be + * used in conjunction with packet-split. + */ + if (adapter->rx_ps_pages) + rxcsum |= E1000_RXCSUM_IPPCSE; + } else { + rxcsum &= ~E1000_RXCSUM_TUOFL; + /* no need to clear IPPCSE as it defaults to 0 */ + } + ew32(RXCSUM, rxcsum); + + /* + * Enable early receives on supported devices, only takes effect when + * packet size is equal or larger than the specified value (in 8 byte + * units), e.g. using jumbo frames when setting to E1000_ERT_2048 + */ + if ((adapter->flags & FLAG_HAS_ERT) && + (adapter->netdev->mtu > ETH_DATA_LEN)) { + u32 rxdctl = er32(RXDCTL(0)); + ew32(RXDCTL(0), rxdctl | 0x3); + ew32(ERT, E1000_ERT_2048 | (1 << 13)); + /* + * With jumbo frames and early-receive enabled, excessive + * C4->C2 latencies result in dropped transactions. + */ + pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, + e1000e_driver_name, 55); + } else { + pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, + e1000e_driver_name, + PM_QOS_DEFAULT_VALUE); + } + + /* Enable Receives */ + ew32(RCTL, rctl); +} + +/** + * e1000_set_multi - Multicast and Promiscuous mode set + * @netdev: network interface device structure + * + * The set_multi entry point is called whenever the multicast address + * list or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper multicast, + * promiscuous mode, and all-multi behavior. + **/ +static void e1000_set_multi(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + struct e1000_mac_info *mac = &hw->mac; + struct dev_mc_list *mc_ptr; + u8 *mta_list; + u32 rctl; + int i; + + /* Check for Promiscuous and All Multicast modes */ + + rctl = er32(RCTL); + + if (netdev->flags & IFF_PROMISC) { + rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); + } else if (netdev->flags & IFF_ALLMULTI) { + rctl |= E1000_RCTL_MPE; + rctl &= ~E1000_RCTL_UPE; + } else { + rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); + } + + ew32(RCTL, rctl); + + if (netdev->mc_count) { + mta_list = kmalloc(netdev->mc_count * 6, GFP_ATOMIC); + if (!mta_list) + return; + + /* prepare a packed array of only addresses. */ + mc_ptr = netdev->mc_list; + + for (i = 0; i < netdev->mc_count; i++) { + if (!mc_ptr) + break; + memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, + ETH_ALEN); + mc_ptr = mc_ptr->next; + } + + hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 1, + mac->rar_entry_count); + kfree(mta_list); + } else { + /* + * if we're called from probe, we might not have + * anything to do here, so clear out the list + */ + hw->mac.ops.update_mc_addr_list(hw, NULL, 0, 1, + mac->rar_entry_count); + } +} + +/** + * e1000_configure - configure the hardware for Rx and Tx + * @adapter: private board structure + **/ +static void e1000_configure(struct e1000_adapter *adapter) +{ + e1000_set_multi(adapter->netdev); + + e1000_restore_vlan(adapter); + e1000_init_manageability(adapter); + + e1000_configure_tx(adapter); + e1000_setup_rctl(adapter); + e1000_configure_rx(adapter); + adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring)); +} + +/** + * e1000e_reset - bring the hardware into a known good state + * + * This function boots the hardware and enables some settings that + * require a configuration cycle of the hardware - those cannot be + * set/changed during runtime. After reset the device needs to be + * properly configured for Rx, Tx etc. + */ +void e1000_reset(struct e1000_adapter *adapter) +{ + struct e1000_mac_info *mac = &adapter->hw.mac; + struct e1000_fc_info *fc = &adapter->hw.fc; + struct e1000_hw *hw = &adapter->hw; + u32 tx_space, min_tx_space, min_rx_space; + u32 pba = adapter->pba; + u16 hwm; + + /* reset Packet Buffer Allocation to default */ + ew32(PBA, pba); + + if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN ) { + /* + * To maintain wire speed transmits, the Tx FIFO should be + * large enough to accommodate two full transmit packets, + * rounded up to the next 1KB and expressed in KB. Likewise, + * the Rx FIFO should be large enough to accommodate at least + * one full receive packet and is similarly rounded up and + * expressed in KB. + */ + pba = er32(PBA); + /* upper 16 bits has Tx packet buffer allocation size in KB */ + tx_space = pba >> 16; + /* lower 16 bits has Rx packet buffer allocation size in KB */ + pba &= 0xffff; + /* + * the Tx fifo also stores 16 bytes of information about the tx + * but don't include ethernet FCS because hardware appends it + */ + min_tx_space = (adapter->max_frame_size + + sizeof(struct e1000_tx_desc) - + ETH_FCS_LEN) * 2; + min_tx_space = ALIGN(min_tx_space, 1024); + min_tx_space >>= 10; + /* software strips receive CRC, so leave room for it */ + min_rx_space = adapter->max_frame_size; + min_rx_space = ALIGN(min_rx_space, 1024); + min_rx_space >>= 10; + + /* + * If current Tx allocation is less than the min Tx FIFO size, + * and the min Tx FIFO size is less than the current Rx FIFO + * allocation, take space away from current Rx allocation + */ + if ((tx_space < min_tx_space) && + ((min_tx_space - tx_space) < pba)) { + pba -= min_tx_space - tx_space; + + /* + * if short on Rx space, Rx wins and must trump tx + * adjustment or use Early Receive if available + */ + if ((pba < min_rx_space) && + (!(adapter->flags & FLAG_HAS_ERT))) + /* ERT enabled in e1000_configure_rx */ + pba = min_rx_space; + } + + ew32(PBA, pba); + } + + + /* + * flow control settings + * + * The high water mark must be low enough to fit one full frame + * (or the size used for early receive) above it in the Rx FIFO. + * Set it to the lower of: + * - 90% of the Rx FIFO size, and + * - the full Rx FIFO size minus the early receive size (for parts + * with ERT support assuming ERT set to E1000_ERT_2048), or + * - the full Rx FIFO size minus one full frame + */ + if (adapter->flags & FLAG_HAS_ERT) + hwm = min(((pba << 10) * 9 / 10), + ((pba << 10) - (E1000_ERT_2048 << 3))); + else + hwm = min(((pba << 10) * 9 / 10), + ((pba << 10) - adapter->max_frame_size)); + + fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */ + fc->low_water = fc->high_water - 8; + + if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) + fc->pause_time = 0xFFFF; + else + fc->pause_time = E1000_FC_PAUSE_TIME; + fc->send_xon = 1; + fc->type = fc->original_type; + + /* Allow time for pending master requests to run */ + mac->ops.reset_hw(hw); + + /* + * For parts with AMT enabled, let the firmware know + * that the network interface is in control + */ + if (adapter->flags & FLAG_HAS_AMT) + e1000_get_hw_control(adapter); + + ew32(WUC, 0); + + if (mac->ops.init_hw(hw)) + e_err("Hardware Error\n"); + + e1000_update_mng_vlan(adapter); + + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ + ew32(VET, ETH_P_8021Q); + + e1000_reset_adaptive_generic(hw); + + if (!hw->phy.ops.get_info) + return; + + hw->phy.ops.get_info(hw); + + if (!(adapter->flags & FLAG_SMART_POWER_DOWN)) { + u16 phy_data = 0; + /* + * speed up time to link by disabling smart power down, ignore + * the return value of this function because there is nothing + * different we would do if it failed + */ + hw->phy.ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); + phy_data &= ~IGP02E1000_PM_SPD; + hw->phy.ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); + } +} + +int e1000_up(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + + /* hardware has been reset, we need to reload some things */ + e1000_configure(adapter); + + clear_bit(__E1000_DOWN, &adapter->state); + +#ifdef CONFIG_E1000E_NAPI + napi_enable(&adapter->napi); +#endif +#ifdef CONFIG_E1000E_MSIX + if (adapter->msix_entries) + e1000_configure_msix(adapter); +#endif /* CONFIG_E1000E_MSIX */ + e1000_irq_enable(adapter); + + /* fire a link change interrupt to start the watchdog */ + ew32(ICS, E1000_ICS_LSC); + return 0; +} + +void e1000_down(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; + u32 tctl, rctl; + + /* + * signal that we're down so the interrupt handler does not + * reschedule our watchdog timer + */ + set_bit(__E1000_DOWN, &adapter->state); + + /* disable receives in the hardware */ + rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + /* flush and sleep below */ + + netif_stop_queue(netdev); + + /* disable transmits in the hardware */ + tctl = er32(TCTL); + tctl &= ~E1000_TCTL_EN; + ew32(TCTL, tctl); + /* flush both disables and wait for them to finish */ + e1e_flush(); + msleep(10); + +#ifdef CONFIG_E1000E_NAPI + napi_disable(&adapter->napi); +#endif + + e1000_irq_disable(adapter); + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_info_timer); + + netdev->tx_queue_len = adapter->tx_queue_len; + netif_carrier_off(netdev); + adapter->link_speed = 0; + adapter->link_duplex = 0; + + e1000_reset(adapter); + e1000_clean_tx_ring(adapter); + e1000_clean_rx_ring(adapter); + + /* + * TODO: for power management, we could drop the link and + * pci_disable_device here. + */ +} + +void e1000_reinit_locked(struct e1000_adapter *adapter) +{ + might_sleep(); + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + msleep(1); + e1000_down(adapter); + e1000_up(adapter); + clear_bit(__E1000_RESETTING, &adapter->state); +} + +/** + * e1000_sw_init - Initialize general software structures (struct e1000_adapter) + * @adapter: board private structure to initialize + * + * e1000_sw_init initializes the Adapter private data structure. + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + **/ +static int __devinit e1000_sw_init(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + s32 rc; + + adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN; + adapter->rx_ps_bsize0 = 128; + adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; + adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + + /* Set various function pointers */ + adapter->ei->init_ops(&adapter->hw); + + rc = adapter->hw.mac.ops.init_params(&adapter->hw); + if (rc) + return rc; + + rc = adapter->hw.nvm.ops.init_params(&adapter->hw); + if (rc) + return rc; + + rc = adapter->hw.phy.ops.init_params(&adapter->hw); + if (rc) + return rc; + +#ifdef CONFIG_E1000E_MSIX + e1000_set_interrupt_capability(adapter); + +#endif /* CONFIG_E1000E_MSIX */ + if (e1000_alloc_queues(adapter)) + return -ENOMEM; + + spin_lock_init(&adapter->tx_queue_lock); + + /* Explicitly disable IRQ since the NIC can be in any state. */ + e1000_irq_disable(adapter); + + spin_lock_init(&adapter->stats_lock); + + set_bit(__E1000_DOWN, &adapter->state); + return 0; +} + +/** + * e1000_intr_msi_test - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +static irqreturn_t e1000_intr_msi_test(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 icr = er32(ICR); + + e_dbg("icr is %08X\n", icr); + if (icr & E1000_ICR_RXSEQ) { + adapter->flags &= ~FLAG_MSI_TEST_FAILED; + wmb(); + } + + return IRQ_HANDLED; +} + +/** + * e1000_test_msi_interrupt - Returns 0 for successful test + * @adapter: board private struct + * + * code flow taken from tg3.c + **/ +static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; + int err; + + /* poll_enable hasn't been called yet, so don't need disable */ + /* clear any pending events */ + er32(ICR); + + /* free the real vector and request a test handler */ + e1000_free_irq(adapter); +#ifdef CONFIG_E1000E_MSIX + e1000_reset_interrupt_capability(adapter); +#endif + + /* Assume that the test fails, if it succeeds then the test + * MSI irq handler will unset this flag */ + adapter->flags |= FLAG_MSI_TEST_FAILED; + + err = pci_enable_msi(adapter->pdev); + if (err) + goto msi_test_failed; + + err = request_irq(adapter->pdev->irq, &e1000_intr_msi_test, 0, + netdev->name, netdev); + if (err) { + pci_disable_msi(adapter->pdev); + goto msi_test_failed; + } + + wmb(); + + e1000_irq_enable(adapter); + + /* fire an unusual interrupt on the test handler */ + ew32(ICS, E1000_ICS_RXSEQ); + e1e_flush(); + msleep(50); + + e1000_irq_disable(adapter); + + rmb(); + + if (adapter->flags & FLAG_MSI_TEST_FAILED) { +#ifdef CONFIG_E1000E_MSIX + adapter->int_mode = E1000E_INT_MODE_LEGACY; +#endif + err = -EIO; + e_info("MSI interrupt test failed!\n"); + } + + free_irq(adapter->pdev->irq, netdev); + pci_disable_msi(adapter->pdev); + + if (err == -EIO) + goto msi_test_failed; + + /* okay so the test worked, restore settings */ + e_dbg("MSI interrupt test succeeded!\n"); +msi_test_failed: +#ifdef CONFIG_E1000E_MSIX + e1000_set_interrupt_capability(adapter); +#else + /* restore the original vector, even if it failed */ +#endif + e1000_request_irq(adapter); + return err; +} + +/** + * e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored + * @adapter: board private struct + * + * code flow taken from tg3.c, called with e1000 interrupts disabled. + **/ +static int e1000_test_msi(struct e1000_adapter *adapter) +{ + int err; + u16 pci_cmd; + + if (!(adapter->flags & FLAG_MSI_ENABLED)) + return 0; + + /* disable SERR in case the MSI write causes a master abort */ + pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); + pci_write_config_word(adapter->pdev, PCI_COMMAND, + pci_cmd & ~PCI_COMMAND_SERR); + + err = e1000_test_msi_interrupt(adapter); + + /* restore previous setting of command word */ + pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); + + /* success ! */ + if (!err) + return 0; + + /* EIO means MSI test failed */ + if (err != -EIO) + return err; + + /* back to INTx mode */ + e_warn("MSI interrupt test failed, using legacy interrupt.\n"); + + e1000_free_irq(adapter); + + err = e1000_request_irq(adapter); + + return err; +} + +/** + * e1000_open - Called when a network interface is made active + * @netdev: network interface device structure + * + * Returns 0 on success, negative value on failure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). At this point all resources needed + * for transmit and receive operations are allocated, the interrupt + * handler is registered with the OS, the watchdog timer is started, + * and the stack is notified that the interface is ready. + **/ +static int e1000_open(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + int err; + + /* disallow open during test */ + if (test_bit(__E1000_TESTING, &adapter->state)) + return -EBUSY; + + /* allocate transmit descriptors */ + err = e1000_setup_tx_resources(adapter); + if (err) + goto err_setup_tx; + + /* allocate receive descriptors */ + err = e1000_setup_rx_resources(adapter); + if (err) + goto err_setup_rx; + + e1000_power_up_phy(hw); + + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + if ((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) + e1000_update_mng_vlan(adapter); + + /* + * If AMT is enabled, let the firmware know that the network + * interface is now open + */ + if (adapter->flags & FLAG_HAS_AMT) + e1000_get_hw_control(adapter); + + /* + * before we allocate an interrupt, we must be ready to handle it. + * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt + * as soon as we call pci_request_irq, so we have to setup our + * clean_rx handler before we do so. + */ + e1000_configure(adapter); + + err = e1000_request_irq(adapter); + if (err) + goto err_req_irq; + + /* + * Work around PCIe errata with MSI interrupts causing some chipsets to + * ignore e1000e MSI messages, which means we need to test our MSI + * interrupt now + */ +#ifdef CONFIG_E1000E_MSIX + if (adapter->int_mode != E1000E_INT_MODE_LEGACY) +#endif + { + err = e1000_test_msi(adapter); + if (err) { + e_err("Interrupt allocation failed\n"); + goto err_req_irq; + } + } + + /* From here on the code is the same as e1000_up() */ + clear_bit(__E1000_DOWN, &adapter->state); + +#ifdef CONFIG_E1000E_NAPI + napi_enable(&adapter->napi); +#endif + + e1000_irq_enable(adapter); + + /* fire a link status change interrupt to start the watchdog */ + ew32(ICS, E1000_ICS_LSC); + + return 0; + +err_req_irq: + e1000_release_hw_control(adapter); + if (!adapter->wol && hw->phy.ops.power_down) + hw->phy.ops.power_down(hw); + e1000_free_rx_resources(adapter); +err_setup_rx: + e1000_free_tx_resources(adapter); +err_setup_tx: + e1000_reset(adapter); + + return err; +} + +/** + * e1000_close - Disables a network interface + * @netdev: network interface device structure + * + * Returns 0, this is not allowed to fail + * + * The close entry point is called when an interface is de-activated + * by the OS. The hardware is still under the drivers control, but + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + **/ +static int e1000_close(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); + e1000_down(adapter); + if (!adapter->wol && hw->phy.ops.power_down) + hw->phy.ops.power_down(hw); + e1000_free_irq(adapter); + + e1000_free_tx_resources(adapter); + e1000_free_rx_resources(adapter); + + /* + * kill manageability vlan ID if supported, but not if a vlan with + * the same ID is registered on the host OS (let 8021q kill it) + */ + if ((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && + !(adapter->vlgrp && + vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) + e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + + /* + * If AMT is enabled, let the firmware know that the network + * interface is now closed + */ + if (adapter->flags & FLAG_HAS_AMT) + e1000_release_hw_control(adapter); + + return 0; +} +/** + * e1000_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + **/ +static int e1000_set_mac(struct net_device *netdev, void *p) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); + + adapter->hw.mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0); + + if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) { + /* activate the work around */ + e1000_set_laa_state_82571(&adapter->hw, 1); + + /* + * Hold a copy of the LAA in RAR[14] This is done so that + * between the time RAR[0] gets clobbered and the time it + * gets fixed (in e1000_watchdog), the actual LAA is in one + * of the RARs and no incoming packets directed to this port + * are dropped. Eventually the LAA will be in RAR[0] and + * RAR[14] + */ + adapter->hw.mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, + adapter->hw.mac.rar_entry_count - 1); + } + + return 0; +} + +/** + * Need to wait a few seconds after link up to get diagnostic information from + * the phy + **/ +static void e1000_update_phy_info(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + if (adapter->hw.phy.ops.get_info) + adapter->hw.phy.ops.get_info(&adapter->hw); +} + +/** + * e1000_update_stats - Update the board statistics counters + * @adapter: board private structure + **/ +void e1000_update_stats(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; +#ifdef HAVE_PCI_ERS + struct pci_dev *pdev = adapter->pdev; +#endif + unsigned long irq_flags; + u16 phy_tmp; + +#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF + + /* + * Prevent stats update while adapter is being reset, or if the pci + * connection is down. + */ + if (adapter->link_speed == 0) + return; +#ifdef HAVE_PCI_ERS + if (pci_channel_offline(pdev)) + return; +#endif + + spin_lock_irqsave(&adapter->stats_lock, irq_flags); + + /* + * these counters are modified from e1000_adjust_tbi_stats, + * called from the interrupt context, so they must only + * be written while holding adapter->stats_lock + */ + + adapter->stats.crcerrs += er32(CRCERRS); + adapter->stats.gprc += er32(GPRC); + adapter->stats.gorc += er32(GORCL); + er32(GORCH); /* Clear gorc */ + adapter->stats.bprc += er32(BPRC); + adapter->stats.mprc += er32(MPRC); + adapter->stats.roc += er32(ROC); + + adapter->stats.mpc += er32(MPC); + adapter->stats.scc += er32(SCC); + adapter->stats.ecol += er32(ECOL); + adapter->stats.mcc += er32(MCC); + adapter->stats.latecol += er32(LATECOL); + adapter->stats.dc += er32(DC); + adapter->stats.xonrxc += er32(XONRXC); + adapter->stats.xontxc += er32(XONTXC); + adapter->stats.xoffrxc += er32(XOFFRXC); + adapter->stats.xofftxc += er32(XOFFTXC); + adapter->stats.gptc += er32(GPTC); + adapter->stats.gotc += er32(GOTCL); + er32(GOTCH); /* Clear gotc */ + adapter->stats.rnbc += er32(RNBC); + adapter->stats.ruc += er32(RUC); + + adapter->stats.mptc += er32(MPTC); + adapter->stats.bptc += er32(BPTC); + + /* used for adaptive IFS */ + + hw->mac.tx_packet_delta = er32(TPT); + adapter->stats.tpt += hw->mac.tx_packet_delta; + hw->mac.collision_delta = er32(COLC); + adapter->stats.colc += hw->mac.collision_delta; + + adapter->stats.algnerrc += er32(ALGNERRC); + adapter->stats.rxerrc += er32(RXERRC); + if (hw->mac.type != e1000_82574) + adapter->stats.tncrs += er32(TNCRS); + adapter->stats.cexterr += er32(CEXTERR); + adapter->stats.tsctc += er32(TSCTC); + adapter->stats.tsctfc += er32(TSCTFC); + + /* Fill out the OS statistics structure */ + adapter->net_stats.multicast = adapter->stats.mprc; + adapter->net_stats.collisions = adapter->stats.colc; + + /* Rx Errors */ + + /* + * RLEC on some newer hardware can be incorrect so build + * our own version based on RUC and ROC + */ + adapter->net_stats.rx_errors = adapter->stats.rxerrc + + adapter->stats.crcerrs + adapter->stats.algnerrc + + adapter->stats.ruc + adapter->stats.roc + + adapter->stats.cexterr; + adapter->net_stats.rx_length_errors = adapter->stats.ruc + + adapter->stats.roc; + adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; + adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; + adapter->net_stats.rx_missed_errors = adapter->stats.mpc; + + /* Tx Errors */ + adapter->net_stats.tx_errors = adapter->stats.ecol + + adapter->stats.latecol; + adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; + adapter->net_stats.tx_window_errors = adapter->stats.latecol; + adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; + + /* Tx Dropped needs to be maintained elsewhere */ + + /* Phy Stats */ + if (hw->phy.media_type == e1000_media_type_copper) { + if ((adapter->link_speed == SPEED_1000) && + (!hw->phy.ops.read_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { + phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; + adapter->phy_stats.idle_errors += phy_tmp; + } + } + + /* Management Stats */ + adapter->stats.mgptc += er32(MGTPTC); + adapter->stats.mgprc += er32(MGTPRC); + adapter->stats.mgpdc += er32(MGTPDC); + + spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); +} + +#ifdef SIOCGMIIPHY +/** + * e1000_phy_read_status - Update the PHY register status snapshot + * @adapter: board private structure + **/ +static void e1000_phy_read_status(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_phy_regs *phy = &adapter->phy_regs; + int ret_val; + unsigned long irq_flags; + + + spin_lock_irqsave(&adapter->stats_lock, irq_flags); + + if ((er32(STATUS) & E1000_STATUS_LU) && + (adapter->hw.phy.media_type == e1000_media_type_copper)) { + ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy->bmcr); + ret_val |= hw->phy.ops.read_reg(hw, PHY_STATUS, &phy->bmsr); + ret_val |= hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, + &phy->advertise); + ret_val |= hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &phy->lpa); + ret_val |= hw->phy.ops.read_reg(hw, PHY_AUTONEG_EXP, + &phy->expansion); + ret_val |= hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, + &phy->ctrl1000); + ret_val |= hw->phy.ops.read_reg(hw, PHY_1000T_STATUS, + &phy->stat1000); + ret_val |= hw->phy.ops.read_reg(hw, PHY_EXT_STATUS, + &phy->estatus); + if (ret_val) + e_warn("Error reading PHY register\n"); + } else { + /* + * Do not read PHY registers if link is not up + * Set values to typical power-on defaults + */ + phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); + phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | + BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | + BMSR_ERCAP); + phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | + ADVERTISE_ALL | ADVERTISE_CSMA); + phy->lpa = 0; + phy->expansion = EXPANSION_ENABLENPAGE; + phy->ctrl1000 = ADVERTISE_1000FULL; + phy->stat1000 = 0; + phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); + } + + spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); +} + +#endif /* SIOCGMIIPHY */ +static void e1000_print_link_info(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl = er32(CTRL); + + e_info("Link is Up %d Mbps %s, Flow Control: %s\n", + adapter->link_speed, + (adapter->link_duplex == FULL_DUPLEX) ? + "Full Duplex" : "Half Duplex", + ((ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE)) ? + "RX/TX" : + ((ctrl & E1000_CTRL_RFCE) ? "RX" : + ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" ))); +} + +static bool e1000_has_link(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + bool link_active = 0; + s32 ret_val = 0; + + /* + * get_link_status is set on LSC (link status) interrupt or + * Rx sequence error interrupt. get_link_status will stay + * false until the check_for_link establishes link + * for copper adapters ONLY + */ + switch (hw->phy.media_type) { + case e1000_media_type_copper: + if (hw->mac.get_link_status) { + ret_val = hw->mac.ops.check_for_link(hw); + link_active = !hw->mac.get_link_status; + } else { + link_active = 1; + } + break; + case e1000_media_type_fiber: + ret_val = hw->mac.ops.check_for_link(hw); + link_active = !!(er32(STATUS) & E1000_STATUS_LU); + break; + case e1000_media_type_internal_serdes: + ret_val = hw->mac.ops.check_for_link(hw); + link_active = adapter->hw.mac.serdes_has_link; + break; + default: + case e1000_media_type_unknown: + break; + } + + if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && + (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) { + /* See e1000_kmrn_lock_loss_workaround_ich8lan() */ + e_info("Gigabit has been disabled, downgrading speed\n"); + } + + return link_active; +} + +static void e1000e_enable_receives(struct e1000_adapter *adapter) +{ + /* make sure the receive unit is started */ + if ((adapter->flags & FLAG_RX_NEEDS_RESTART) && + (adapter->flags & FLAG_RX_RESTART_NOW)) { + struct e1000_hw *hw = &adapter->hw; + u32 rctl = er32(RCTL); + ew32(RCTL, rctl | E1000_RCTL_EN); + adapter->flags &= ~FLAG_RX_RESTART_NOW; + } +} + +/** + * e1000_watchdog - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ +static void e1000_watchdog(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + + /* Do the rest outside of interrupt context */ + schedule_work(&adapter->watchdog_task); + + /* TODO: make this use queue_delayed_work() */ +} + +static void e1000_watchdog_task(struct work_struct *work) +{ + struct e1000_adapter *adapter = container_of(work, + struct e1000_adapter, watchdog_task); + struct net_device *netdev = adapter->netdev; + struct e1000_mac_info *mac = &adapter->hw.mac; + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_hw *hw = &adapter->hw; + u32 link, tctl; + int tx_pending = 0; + unsigned long timer_val; + + link = e1000_has_link(adapter); + if ((netif_carrier_ok(netdev)) && link) { + e1000e_enable_receives(adapter); + goto link_up; + } + + if ((e1000_enable_tx_pkt_filtering_generic(hw)) && + (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)) + e1000_update_mng_vlan(adapter); + + if (link) { + if (!netif_carrier_ok(netdev)) { + bool txb2b = 1; +#ifdef SIOCGMIIPHY + /* update snapshot of PHY registers on LSC */ + e1000_phy_read_status(adapter); +#endif + mac->ops.get_link_up_info(&adapter->hw, + &adapter->link_speed, + &adapter->link_duplex); + e1000_print_link_info(adapter); + + /* + * On supported PHYs, check for duplex mismatch only + * if link has autonegotiated at 10/100 half + */ + if ((hw->phy.type == e1000_phy_igp_3 || + hw->phy.type == e1000_phy_bm) && + (hw->mac.autoneg == TRUE) && + (adapter->link_speed == SPEED_10 || + adapter->link_speed == SPEED_100) && + (adapter->link_duplex == HALF_DUPLEX)) { + u16 autoneg_exp; + + hw->phy.ops.read_reg(hw, PHY_AUTONEG_EXP, + &autoneg_exp); + + if (!(autoneg_exp & NWAY_ER_LP_NWAY_CAPS)) + e_info("Autonegotiated half duplex but" + " link partner cannot autoneg. " + " Try forcing full duplex if " + "link gets many collisions."); + } + + /* + * tweak tx_queue_len according to speed/duplex + * and adjust the timeout factor + */ + netdev->tx_queue_len = adapter->tx_queue_len; + adapter->tx_timeout_factor = 1; + switch (adapter->link_speed) { + case SPEED_10: + txb2b = 0; + netdev->tx_queue_len = 10; + adapter->tx_timeout_factor = 16; + break; + case SPEED_100: + txb2b = 0; + netdev->tx_queue_len = 100; + /* maybe add some timeout factor ? */ + break; + } + + /* + * workaround: re-program speed mode bit after + * link-up event + */ + if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) && + !txb2b) { + u32 tarc0; + tarc0 = er32(TARC(0)); + tarc0 &= ~SPEED_MODE_BIT; + ew32(TARC(0), tarc0); + } + +#ifdef NETIF_F_TSO + /* + * disable TSO for pcie and 10/100 speeds, to avoid + * some hardware issues + */ + if (!(adapter->flags & FLAG_TSO_FORCE)) { + switch (adapter->link_speed) { + case SPEED_10: + case SPEED_100: + e_info("10/100 speed: disabling TSO\n"); + netdev->features &= ~NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + netdev->features &= ~NETIF_F_TSO6; +#endif + break; + case SPEED_1000: + netdev->features |= NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + netdev->features |= NETIF_F_TSO6; +#endif + break; + default: + /* oops */ + break; + } + } +#endif + + /* + * enable transmits in the hardware, need to do this + * after setting TARC(0) + */ + tctl = er32(TCTL); + tctl |= E1000_TCTL_EN; + ew32(TCTL, tctl); + + netif_carrier_on(netdev); + netif_wake_queue(netdev); + } + } else { + if (netif_carrier_ok(netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = 0; + e_info("Link is Down\n"); + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + if (adapter->flags & FLAG_RX_NEEDS_RESTART) + schedule_work(&adapter->reset_task); + } + } + +link_up: + e1000_update_stats(adapter); + + mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; + adapter->tpt_old = adapter->stats.tpt; + mac->collision_delta = adapter->stats.colc - adapter->colc_old; + adapter->colc_old = adapter->stats.colc; + + adapter->gorc = adapter->stats.gorc - adapter->gorc_old; + adapter->gorc_old = adapter->stats.gorc; + adapter->gotc = adapter->stats.gotc - adapter->gotc_old; + adapter->gotc_old = adapter->stats.gotc; + + e1000_update_adaptive_generic(&adapter->hw); + + if (!netif_carrier_ok(netdev)) { + tx_pending = (e1000_desc_unused(tx_ring) + 1 < + tx_ring->count); + if (tx_pending) { + /* + * We've lost link, so the controller stops DMA, + * but we've got queued Tx work that's never going + * to get done, so reset controller to flush Tx. + * (Do the reset outside of interrupt context). + */ + adapter->tx_timeout_count++; + schedule_work(&adapter->reset_task); + } + } + + /* Cause software interrupt to ensure Rx ring is cleaned */ +#ifdef CONFIG_E1000E_MSIX + if (adapter->msix_entries) + ew32(ICS, adapter->rx_ring->ims_val); + else +#endif + ew32(ICS, E1000_ICS_RXDMT0); + + /* Force detection of hung controller every watchdog period */ + adapter->detect_tx_hung = 1; + + /* + * With 82571 controllers, LAA may be overwritten due to controller + * reset from the other port. Set the appropriate LAA in RAR[0] + */ + if (e1000_get_laa_state_82571(hw)) + hw->mac.ops.rar_set(hw, adapter->hw.mac.addr, 0); + + /* Reset the timer */ + if (!test_bit(__E1000_DOWN, &adapter->state)) { + timer_val = jiffies + usecs_to_jiffies(adapter->stats_freq_us); + if (adapter->stats_freq_us > 1000000) + timer_val = round_jiffies(timer_val); + mod_timer(&adapter->watchdog_timer, timer_val); + } +} + +#define E1000_TX_FLAGS_CSUM 0x00000001 +#define E1000_TX_FLAGS_VLAN 0x00000002 +#define E1000_TX_FLAGS_TSO 0x00000004 +#define E1000_TX_FLAGS_IPV4 0x00000008 +#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 +#define E1000_TX_FLAGS_VLAN_SHIFT 16 + +static int e1000_tso(struct e1000_adapter *adapter, + struct sk_buff *skb) +{ +#ifdef NETIF_F_TSO + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_context_desc *context_desc; + struct e1000_buffer *buffer_info; + unsigned int i; + u32 cmd_length = 0; + u16 ipcse = 0, tucse, mss; + u8 ipcss, ipcso, tucss, tucso, hdr_len; + int err; + + if (!skb_is_gso(skb)) + return 0; + + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (err) + return err; + } + + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + mss = skb_shinfo(skb)->gso_size; + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + iph->tot_len = 0; + iph->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, 0, + IPPROTO_TCP, + 0); + cmd_length = E1000_TXD_CMD_IP; + ipcse = skb_transport_offset(skb) - 1; +#ifdef NETIF_F_TSO6 + } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + ipv6_hdr(skb)->payload_len = 0; + tcp_hdr(skb)->check = + ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + 0, IPPROTO_TCP, 0); + ipcse = 0; +#endif + } + ipcss = skb_network_offset(skb); + ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; + tucss = skb_transport_offset(skb); + tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; + tucse = 0; + + cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | + E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); + + i = tx_ring->next_to_use; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; + + context_desc->lower_setup.ip_fields.ipcss = ipcss; + context_desc->lower_setup.ip_fields.ipcso = ipcso; + context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); + context_desc->upper_setup.tcp_fields.tucss = tucss; + context_desc->upper_setup.tcp_fields.tucso = tucso; + context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); + context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); + context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; + context_desc->cmd_and_length = cpu_to_le32(cmd_length); + + buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; + + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; + + return 1; +#else + return 0; +#endif +} + +static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) +{ + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_context_desc *context_desc; + struct e1000_buffer *buffer_info; + unsigned int i; + u8 css; + u32 cmd_len = E1000_TXD_CMD_DEXT; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; + + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + cmd_len |= E1000_TXD_CMD_TCP; + break; + case __constant_htons(ETH_P_IPV6): + /* XXX not handling all IPV6 headers */ + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + cmd_len |= E1000_TXD_CMD_TCP; + break; + default: + if (unlikely(net_ratelimit())) + e_warn("checksum_partial proto=%x!\n", skb->protocol); + break; + } + + css = skb_transport_offset(skb); + + i = tx_ring->next_to_use; + buffer_info = &tx_ring->buffer_info[i]; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + + context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; + context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(cmd_len); + + buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; + + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; + + return 1; +} + +#define E1000_MAX_PER_TXD 8192 +#define E1000_MAX_TXD_PWR 12 + +static int e1000_tx_map(struct e1000_adapter *adapter, + struct sk_buff *skb, unsigned int first, + unsigned int max_per_txd, unsigned int nr_frags, + unsigned int mss) +{ + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_buffer *buffer_info; + unsigned int len = skb->len - skb->data_len; + unsigned int offset = 0, size, count = 0, i; + unsigned int f; + + i = tx_ring->next_to_use; + + while (len) { + buffer_info = &tx_ring->buffer_info[i]; + size = min(len, max_per_txd); + + buffer_info->length = size; + /* set time_stamp *before* dma to help avoid a possible race */ + buffer_info->time_stamp = jiffies; + buffer_info->dma = + pci_map_single(adapter->pdev, + skb->data + offset, + size, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) { + dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); + adapter->tx_dma_failed++; + return -1; + } + buffer_info->next_to_watch = i; + + len -= size; + offset += size; + count++; + i++; + if (i == tx_ring->count) + i = 0; + } + + for (f = 0; f < nr_frags; f++) { + struct skb_frag_struct *frag; + + frag = &skb_shinfo(skb)->frags[f]; + len = frag->size; + offset = frag->page_offset; + + while (len) { + buffer_info = &tx_ring->buffer_info[i]; + size = min(len, max_per_txd); + + buffer_info->length = size; + buffer_info->time_stamp = jiffies; + buffer_info->dma = + pci_map_page(adapter->pdev, + frag->page, + offset, + size, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) { + dev_err(&adapter->pdev->dev, + "TX DMA page map failed\n"); + adapter->tx_dma_failed++; + return -1; + } + + buffer_info->next_to_watch = i; + + len -= size; + offset += size; + count++; + + i++; + if (i == tx_ring->count) + i = 0; + } + } + + if (i == 0) + i = tx_ring->count - 1; + else + i--; + + tx_ring->buffer_info[i].skb = skb; + tx_ring->buffer_info[first].next_to_watch = i; + + return count; +} + +static void e1000_tx_queue(struct e1000_adapter *adapter, + int tx_flags, int count) +{ + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_tx_desc *tx_desc = NULL; + struct e1000_buffer *buffer_info; + u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; + unsigned int i; + + if (tx_flags & E1000_TX_FLAGS_TSO) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | + E1000_TXD_CMD_TSE; + txd_upper |= E1000_TXD_POPTS_TXSM << 8; + + if (tx_flags & E1000_TX_FLAGS_IPV4) + txd_upper |= E1000_TXD_POPTS_IXSM << 8; + } + + if (tx_flags & E1000_TX_FLAGS_CSUM) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; + txd_upper |= E1000_TXD_POPTS_TXSM << 8; + } + + if (tx_flags & E1000_TX_FLAGS_VLAN) { + txd_lower |= E1000_TXD_CMD_VLE; + txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); + } + + i = tx_ring->next_to_use; + + while (count--) { + buffer_info = &tx_ring->buffer_info[i]; + tx_desc = E1000_TX_DESC(*tx_ring, i); + tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + tx_desc->lower.data = + cpu_to_le32(txd_lower | buffer_info->length); + tx_desc->upper.data = cpu_to_le32(txd_upper); + + i++; + if (i == tx_ring->count) + i = 0; + } + + tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); + + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + + tx_ring->next_to_use = i; + writel(i, adapter->hw.hw_addr + tx_ring->tail); + /* + * we need this if more than one processor can write to our tail + * at a time, it synchronizes IO on IA64/Altix systems + */ + mmiowb(); +} + +#define MINIMUM_DHCP_PACKET_SIZE 282 +static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, + struct sk_buff *skb) +{ + struct e1000_hw *hw = &adapter->hw; + u16 length, offset; + + if (vlan_tx_tag_present(skb)) { + if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) + && (adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN))) + return 0; + } + + if (skb->len <= MINIMUM_DHCP_PACKET_SIZE) + return 0; + + if (((struct ethhdr *) skb->data)->h_proto != htons(ETH_P_IP)) + return 0; + + { + const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14); + struct udphdr *udp; + + if (ip->protocol != IPPROTO_UDP) + return 0; + + udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); + if (ntohs(udp->dest) != 67) + return 0; + + offset = (u8 *)udp + 8 - skb->data; + length = skb->len - offset; + return e1000_mng_write_dhcp_info_generic(hw, (u8 *)udp + 8, + length); + } + + return 0; +} + +static int __e1000_maybe_stop_tx(struct net_device *netdev, int size) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + netif_stop_queue(netdev); + /* + * Herbert's original patch had: + * smp_mb__after_netif_stop_queue(); + * but since that doesn't exist yet, just open code it. + */ + smp_mb(); + + /* + * We need to check again in a case another CPU has just + * made room available. + */ + if (e1000_desc_unused(adapter->tx_ring) < size) + return -EBUSY; + + /* A reprieve! */ + netif_start_queue(netdev); + ++adapter->restart_queue; + return 0; +} + +static int e1000_maybe_stop_tx(struct net_device *netdev, int size) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (e1000_desc_unused(adapter->tx_ring) >= size) + return 0; + return __e1000_maybe_stop_tx(netdev, size); +} + +#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) +static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_ring *tx_ring = adapter->tx_ring; + unsigned int first; + unsigned int max_per_txd = E1000_MAX_PER_TXD; + unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; + unsigned int tx_flags = 0; + unsigned int len = skb->len - skb->data_len; +#ifdef NETIF_F_LLTX + unsigned long irq_flags; +#endif + unsigned int nr_frags; + unsigned int mss = 0; + int count = 0; + int tso; + unsigned int f; + + if (test_bit(__E1000_DOWN, &adapter->state)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (skb->len <= 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +#ifdef NETIF_F_TSO + mss = skb_shinfo(skb)->gso_size; + /* + * The controller does a simple calculation to + * make sure there is enough room in the FIFO before + * initiating the DMA for each buffer. The calc is: + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. + */ + if (mss) { + u8 hdr_len; + max_per_txd = min(mss << 2, max_per_txd); + max_txd_pwr = fls(max_per_txd) - 1; + + /* + * TSO Workaround for 82571/2/3 Controllers -- if skb->data + * points to just header, pull a few bytes of payload from + * frags into skb->data + */ + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + /* + * we do this workaround for ES2LAN, but it is un-necessary, + * avoiding it could save a lot of cycles + */ + if (skb->data_len && (hdr_len == len)) { + unsigned int pull_size; + + pull_size = min((unsigned int)4, skb->data_len); + if (!__pskb_pull_tail(skb, pull_size)) { + e_err("__pskb_pull_tail failed.\n"); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + len = skb->len - skb->data_len; + } + } + + /* reserve a descriptor for the offload context */ + if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) + count++; + count++; +#else + if (skb->ip_summed == CHECKSUM_PARTIAL) + count++; +#endif + + count += TXD_USE_COUNT(len, max_txd_pwr); + + nr_frags = skb_shinfo(skb)->nr_frags; + for (f = 0; f < nr_frags; f++) + count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, + max_txd_pwr); + + if (adapter->hw.mac.tx_pkt_filtering) + e1000_transfer_dhcp_info(adapter, skb); + +#ifdef NETIF_F_LLTX + if (!spin_trylock_irqsave(&adapter->tx_queue_lock, irq_flags)) + /* Collision - tell upper layer to requeue */ + return NETDEV_TX_LOCKED; +#endif + + /* + * need: count + 2 desc gap to keep tail from touching + * head, otherwise try next time + */ + if (e1000_maybe_stop_tx(netdev, count + 2)) { +#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); +#endif + return NETDEV_TX_BUSY; + } + + if (adapter->vlgrp && vlan_tx_tag_present(skb)) { + tx_flags |= E1000_TX_FLAGS_VLAN; + tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); + } + + first = tx_ring->next_to_use; + + tso = e1000_tso(adapter, skb); + if (unlikely(tso < 0)) { + dev_kfree_skb_any(skb); +#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); +#endif + return NETDEV_TX_OK; + } + + if (tso) + tx_flags |= E1000_TX_FLAGS_TSO; + else if (e1000_tx_csum(adapter, skb)) + tx_flags |= E1000_TX_FLAGS_CSUM; + + /* + * Old method was to assume IPv4 packet by default if TSO was enabled. + * 82571 hardware supports TSO capabilities for IPv6 as well... + * no longer assume, we must. + */ + if (skb->protocol == htons(ETH_P_IP)) + tx_flags |= E1000_TX_FLAGS_IPV4; + + count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss); + if (unlikely(count < 0)) { + /* handle pci_map_single() error in e1000_tx_map */ + dev_kfree_skb_any(skb); +#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); +#endif + return NETDEV_TX_OK; + } + + e1000_tx_queue(adapter, tx_flags, count); + + netdev->trans_start = jiffies; + + /* Make sure there is space in the ring for the next send. */ + e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2); + +#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); +#endif + return NETDEV_TX_OK; +} + +/** + * e1000_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + **/ +static void e1000_tx_timeout(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + /* Do the reset outside of interrupt context */ + adapter->tx_timeout_count++; + schedule_work(&adapter->reset_task); +} + +static void e1000_reset_task(struct work_struct *work) +{ + struct e1000_adapter *adapter; + adapter = container_of(work, struct e1000_adapter, reset_task); + + e1000_reinit_locked(adapter); +} + +/** + * e1000_get_stats - Get System Network Statistics + * @netdev: network interface device structure + * + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. + **/ +static struct net_device_stats *e1000_get_stats(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + /* only return the current stats */ + return &adapter->net_stats; +} + +/** + * e1000_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + **/ +static int e1000_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; + + if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { + e_err("Invalid MTU setting\n"); + return -EINVAL; + } + + /* Jumbo frame size limits */ + if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) { + if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { + e_err("Jumbo Frames not supported.\n"); + return -EINVAL; + } + } + +#define MAX_STD_JUMBO_FRAME_SIZE 9234 + if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { + e_err("MTU > 9216 not supported.\n"); + return -EINVAL; + } + + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + msleep(1); + /* e1000_down has a dependency on max_frame_size */ + adapter->max_frame_size = max_frame; + if (netif_running(netdev)) + e1000_down(adapter); + + /* + * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + * means we reserve 2 more, this pushes us to allocate from the next + * larger slab size. + * i.e. RXBUFFER_2048 --> size-4096 slab + * However with the new *_jumbo_rx* routines, jumbo receives will use + * fragmented skbs + */ + + if (max_frame <= 256) + adapter->rx_buffer_len = 256; + else if (max_frame <= 512) + adapter->rx_buffer_len = 512; + else if (max_frame <= 1024) + adapter->rx_buffer_len = 1024; + else if (max_frame <= 2048) + adapter->rx_buffer_len = 2048; +#ifdef CONFIG_E1000E_NAPI + else + adapter->rx_buffer_len = 4096; +#else + else if (max_frame <= 4096) + adapter->rx_buffer_len = 4096; + else if (max_frame <= 8192) + adapter->rx_buffer_len = 8192; + else if (max_frame <= 16384) + adapter->rx_buffer_len = 16384; +#endif + + /* adjust allocation if LPE protects us, and we aren't using SBP */ + if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) || + (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)) + adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN + + ETH_FCS_LEN; + + e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu); + netdev->mtu = new_mtu; + + if (netif_running(netdev)) + e1000_up(adapter); + else + e1000_reset(adapter); + + clear_bit(__E1000_RESETTING, &adapter->state); + + return 0; +} + +static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, + int cmd) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct mii_ioctl_data *data = if_mii(ifr); + + if (adapter->hw.phy.media_type != e1000_media_type_copper) + return -EOPNOTSUPP; + + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = adapter->hw.phy.addr; + break; + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + switch (data->reg_num & 0x1F) { + case MII_BMCR: + data->val_out = adapter->phy_regs.bmcr; + break; + case MII_BMSR: + data->val_out = adapter->phy_regs.bmsr; + break; + case MII_PHYSID1: + data->val_out = (adapter->hw.phy.id >> 16); + break; + case MII_PHYSID2: + data->val_out = (adapter->hw.phy.id & 0xFFFF); + break; + case MII_ADVERTISE: + data->val_out = adapter->phy_regs.advertise; + break; + case MII_LPA: + data->val_out = adapter->phy_regs.lpa; + break; + case MII_EXPANSION: + data->val_out = adapter->phy_regs.expansion; + break; + case MII_CTRL1000: + data->val_out = adapter->phy_regs.ctrl1000; + break; + case MII_STAT1000: + data->val_out = adapter->phy_regs.stat1000; + break; + case MII_ESTATUS: + data->val_out = adapter->phy_regs.estatus; + break; + default: + return -EIO; + } + break; + case SIOCSMIIREG: + default: + return -EOPNOTSUPP; + } + return 0; +} + +static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return e1000_mii_ioctl(netdev, ifr, cmd); +#ifdef ETHTOOL_OPS_COMPAT + case SIOCETHTOOL: + return ethtool_ioctl(ifr); +#endif + default: + return -EOPNOTSUPP; + } +} + +static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 ctrl, ctrl_ext, rctl, status; + u32 wufc = adapter->wol; + int retval = 0; + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); + e1000_down(adapter); + e1000_free_irq(adapter); + } + +#ifdef CONFIG_PM + retval = pci_save_state(pdev); + if (retval) + return retval; +#endif + + status = er32(STATUS); + if (status & E1000_STATUS_LU) + wufc &= ~E1000_WUFC_LNKC; + + if (wufc) { + e1000_setup_rctl(adapter); + e1000_set_multi(netdev); + + /* turn on all-multi mode if wake on multicast is enabled */ + if (wufc & E1000_WUFC_MC) { + rctl = er32(RCTL); + rctl |= E1000_RCTL_MPE; + ew32(RCTL, rctl); + } + + ctrl = er32(CTRL); + /* advertise wake from D3Cold */ + #define E1000_CTRL_ADVD3WUC 0x00100000 + /* phy power management enable */ + #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 + ctrl |= E1000_CTRL_ADVD3WUC | + E1000_CTRL_EN_PHY_PWR_MGMT; + ew32(CTRL, ctrl); + + if (adapter->hw.phy.media_type == e1000_media_type_fiber || + adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { + /* keep the laser running in D3 */ + ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; + ew32(CTRL_EXT, ctrl_ext); + } + + if (adapter->flags & FLAG_IS_ICH) + e1000_disable_gig_wol_ich8lan(&adapter->hw); + + /* Allow time for pending master requests to run */ + e1000_disable_pcie_master_generic(&adapter->hw); + + ew32(WUC, E1000_WUC_PME_EN); + ew32(WUFC, wufc); + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } else { + ew32(WUC, 0); + ew32(WUFC, 0); + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + } + + /* make sure adapter isn't asleep if manageability is enabled */ + if (adapter->flags & FLAG_MNG_PT_ENABLED) { + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } + + if (adapter->hw.phy.type == e1000_phy_igp_3) + e1000_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); + + /* + * Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. + */ + e1000_release_hw_control(adapter); + + pci_disable_device(pdev); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +#ifdef CONFIG_PM +static int e1000_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, + "Cannot enable PCI device from suspend\n"); + return err; + } + + pci_set_master(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + if (netif_running(netdev)) { + err = e1000_request_irq(adapter); + if (err) + return err; + } + + e1000_power_up_phy(hw); + e1000_reset(adapter); + ew32(WUS, ~0); + + e1000_init_manageability(adapter); + + if (netif_running(netdev)) + e1000_up(adapter); + + netif_device_attach(netdev); + + /* + * If the controller has AMT, do not set DRV_LOAD until the interface + * is up. For all other cases, let the f/w know that the h/w is now + * under the control of the driver. + */ + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000_get_hw_control(adapter); + + return 0; +} +#endif /* CONFIG_PM */ + +#ifndef USE_REBOOT_NOTIFIER +static void e1000_shutdown(struct pci_dev *pdev) +{ + e1000_suspend(pdev, PMSG_SUSPEND); +} +#else +static struct pci_driver e1000_driver; +static int e1000_notify_reboot(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct pci_dev *pdev = NULL; + + switch (event) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { + if (pci_dev_driver(pdev) == &e1000_driver) + e1000_suspend(pdev, PMSG_SUSPEND); + } + break; + } + return NOTIFY_DONE; +} + +static struct notifier_block e1000_notifier_reboot = { + .notifier_call = e1000_notify_reboot, + .next = NULL, + .priority = 0 +}; +#endif + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +static void e1000_netpoll(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + disable_irq(adapter->pdev->irq); + e1000_intr(adapter->pdev->irq, netdev); + + e1000_clean_tx_irq(adapter); +#ifndef CONFIG_E1000E_NAPI + adapter->clean_rx(adapter); +#endif + + enable_irq(adapter->pdev->irq); +} +#endif + +#ifdef HAVE_PCI_ERS +/** + * e1000_io_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * This function is called after a PCI bus error affecting + * this device has been detected. + */ +static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + + netif_device_detach(netdev); + + if (netif_running(netdev)) + e1000_down(adapter); + pci_disable_device(pdev); + + /* Request a slot slot reset. */ + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * e1000_io_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. Implementation + * resembles the first-half of the e1000_resume routine. + */ +static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + if (pci_enable_device(pdev)) { + dev_err(&pdev->dev, + "Cannot re-enable PCI device after reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + pci_set_master(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + e1000_reset(adapter); + ew32(WUS, ~0); + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * e1000_io_resume - called when traffic can start flowing again. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells us that + * its OK to resume normal operation. Implementation resembles the + * second-half of the e1000_resume routine. + */ +static void e1000_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + + e1000_init_manageability(adapter); + + if (netif_running(netdev)) { + if (e1000_up(adapter)) { + dev_err(&pdev->dev, + "can't bring device back up after reset\n"); + return; + } + } + + netif_device_attach(netdev); + + /* + * If the controller has AMT, do not set DRV_LOAD until the interface + * is up. For all other cases, let the f/w know that the h/w is now + * under the control of the driver. + */ + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000_get_hw_control(adapter); + +} +#endif /* HAVE_PCI_ERS */ + +static void e1000_print_device_info(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + u32 pba_num; + + /* print bus type/speed/width info */ + e_info("(PCI Express:2.5GB/s:%s) %02x:%02x:%02x:%02x:%02x:%02x\n", + /* bus width */ + ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : + "Width x1"), + /* MAC address */ + netdev->dev_addr[0], netdev->dev_addr[1], + netdev->dev_addr[2], netdev->dev_addr[3], + netdev->dev_addr[4], netdev->dev_addr[5]); + e_info("Intel(R) PRO/%s Network Connection\n", + (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000"); + e1000_read_pba_num_generic(hw, &pba_num); + e_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n", + hw->mac.type, hw->phy.type, + (pba_num >> 8), (pba_num & 0xff)); +} + +/** + * e1000_probe - Device Initialization Routine + * @pdev: PCI device information struct + * @ent: entry in e1000e_pci_tbl + * + * Returns 0 on success, negative on failure + * + * e1000_probe initializes an adapter identified by a pci_dev structure. + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ +static int __devinit e1000_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct e1000_adapter *adapter; + struct e1000_hw *hw; + const struct e1000_info *ei = e1000_info_tbl[ent->driver_data]; + + static int cards_found; + int i, err, pci_using_dac; + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + + err = pci_enable_device(pdev); + if (err) + return err; + + pci_using_dac = 0; + err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (!err) { + err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + if (!err) + pci_using_dac = 1; + } else { + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (err) { + err = pci_set_consistent_dma_mask(pdev, + DMA_32BIT_MASK); + if (err) { + printk(KERN_ERR "%s: No usable DMA " + "configuration, aborting\n", + pci_name(pdev)); + goto err_dma; + } + } + } + + err = pci_request_regions(pdev, e1000e_driver_name); + if (err) + goto err_pci_reg; + + pci_set_master(pdev); + + err = -ENOMEM; + netdev = alloc_etherdev(sizeof(struct e1000_adapter)); + if (!netdev) + goto err_alloc_etherdev; + + SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); + + pci_set_drvdata(pdev, netdev); + adapter = netdev_priv(netdev); + hw = &adapter->hw; + adapter->netdev = netdev; + adapter->pdev = pdev; + adapter->ei = ei; + adapter->pba = ei->pba; + adapter->flags = ei->flags; + adapter->hw.back = adapter; + adapter->hw.mac.type = ei->mac; + adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; + adapter->stats_freq_us = 2 * 1000000; /* default watchdog timer 2sec */ + + /* PCI config space info */ + + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_device_id = pdev->subsystem_device; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); + + err = -EIO; + adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (!adapter->hw.hw_addr) + goto err_ioremap; + + if ((adapter->flags & FLAG_HAS_FLASH) && + (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { + adapter->hw.flash_address = ioremap(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); + if (!adapter->hw.flash_address) + goto err_flashmap; + + /* Now that we're sure NV RAM is mappable, unmap it until needed. */ + iounmap(adapter->hw.flash_address); + adapter->hw.flash_address = NULL; + spin_lock_init(&adapter->hw.flash_address_map_lock); + } + + adapter->bd_number = cards_found++; + + e1000_check_options(adapter); + + /* setup adapter struct */ + err = e1000_sw_init(adapter); + if (err) + goto err_sw_init; + + if (ei->get_variants) { + err = ei->get_variants(adapter); + if (err) + goto err_hw_init; + } + + /* construct the net_device struct */ + netdev->open = &e1000_open; + netdev->stop = &e1000_close; + netdev->hard_start_xmit = &e1000_xmit_frame; + netdev->get_stats = &e1000_get_stats; + netdev->set_multicast_list = &e1000_set_multi; + netdev->set_mac_address = &e1000_set_mac; + netdev->change_mtu = &e1000_change_mtu; + netdev->do_ioctl = &e1000_ioctl; + e1000_set_ethtool_ops(netdev); + netdev->tx_timeout = &e1000_tx_timeout; + netdev->watchdog_timeo = 5 * HZ; +#ifdef CONFIG_E1000E_NAPI + netif_napi_add(netdev, &adapter->napi, e1000_poll, 64); +#endif + netdev->vlan_rx_register = e1000_vlan_rx_register; + netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; + netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = e1000_netpoll; +#endif + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + hw->mac.ops.get_bus_info(&adapter->hw); + + adapter->hw.phy.autoneg_wait_to_complete = 0; + + /* Copper options */ + if (adapter->hw.phy.media_type == e1000_media_type_copper) { + adapter->hw.phy.mdix = AUTO_ALL_MODES; + adapter->hw.phy.disable_polarity_correction = 0; + adapter->hw.phy.ms_type = e1000_ms_hw_default; + } + + if (hw->phy.ops.check_reset_block && + hw->phy.ops.check_reset_block(hw)) + e_info("PHY reset is blocked due to SOL/IDER session.\n"); + + netdev->features = NETIF_F_SG | + NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX; + + if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) + netdev->features |= NETIF_F_HW_VLAN_FILTER; + +#ifdef NETIF_F_TSO + netdev->features |= NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + netdev->features |= NETIF_F_TSO6; +#endif +#endif + + if (pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + +#ifdef NETIF_F_LLTX + /* + * We should not be using LLTX anymore, but we are still Tx faster with + * it. + */ + netdev->features |= NETIF_F_LLTX; +#endif + + if (e1000_enable_mng_pass_thru(&adapter->hw)) + adapter->flags |= FLAG_MNG_PT_ENABLED; + + /* + * before reading the NVM, reset the controller to + * put the device in a known good starting state + */ + adapter->hw.mac.ops.reset_hw(&adapter->hw); + + /* + * systems with ASPM and others may see the checksum fail on the first + * attempt. Let's give it a few tries + */ + for (i = 0;; i++) { + if (hw->nvm.ops.validate(hw) >= 0) + break; + if (i == 2) { + e_err("The NVM Checksum Is Not Valid\n"); + err = -EIO; + goto err_eeprom; + } + } + + /* copy the MAC address out of the NVM */ + if (e1000_read_mac_addr(&adapter->hw)) + e_err("NVM Read Error while reading MAC address\n"); + + memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); +#ifdef ETHTOOL_GPERMADDR + memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); + + if (!is_valid_ether_addr(netdev->perm_addr)) { +#else + if (!is_valid_ether_addr(netdev->dev_addr)) { +#endif + e_err("Invalid MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + netdev->dev_addr[0], netdev->dev_addr[1], + netdev->dev_addr[2], netdev->dev_addr[3], + netdev->dev_addr[4], netdev->dev_addr[5]); + err = -EIO; + goto err_eeprom; + } + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &e1000_watchdog; + adapter->watchdog_timer.data = (unsigned long) adapter; + + init_timer(&adapter->phy_info_timer); + adapter->phy_info_timer.function = &e1000_update_phy_info; + adapter->phy_info_timer.data = (unsigned long) adapter; + + INIT_WORK(&adapter->reset_task, e1000_reset_task); + INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); + + /* Initialize link parameters. User can change them with ethtool */ + adapter->hw.mac.autoneg = 1; + adapter->fc_autoneg = 1; + adapter->hw.fc.original_type = e1000_fc_default; + adapter->hw.fc.type = e1000_fc_default; + adapter->hw.phy.autoneg_advertised = 0x2f; + + /* ring size defaults */ + adapter->rx_ring->count = 256; + adapter->tx_ring->count = 256; + + /* + * Initial Wake on LAN setting - If APM wake is enabled in + * the EEPROM, enable the ACPI Magic Packet filter + */ + if (adapter->flags & FLAG_APME_IN_WUC) { + /* APME bit in EEPROM is mapped to WUC.APME */ + eeprom_data = er32(WUC); + eeprom_apme_mask = E1000_WUC_APME; + } else if (adapter->flags & FLAG_APME_IN_CTRL3) { + if (adapter->flags & FLAG_APME_CHECK_PORT_B && + (adapter->hw.bus.func == 1)) + hw->nvm.ops.read(&adapter->hw, NVM_INIT_CONTROL3_PORT_B, + 1, &eeprom_data); + else + hw->nvm.ops.read(&adapter->hw, NVM_INIT_CONTROL3_PORT_A, + 1, &eeprom_data); + } + + /* fetch WoL from EEPROM */ + if (eeprom_data & eeprom_apme_mask) + adapter->eeprom_wol |= E1000_WUFC_MAG; + + /* + * now that we have the eeprom settings, apply the special cases + * where the eeprom may be wrong or the board simply won't support + * wake on lan on a particular port + */ + if (!(adapter->flags & FLAG_HAS_WOL)) + adapter->eeprom_wol = 0; + + /* initialize the wol settings based on the eeprom settings */ + adapter->wol = adapter->eeprom_wol; + + /* reset the hardware with the new settings */ + e1000_reset(adapter); + + /* + * If the controller has AMT, do not set DRV_LOAD until the interface + * is up. For all other cases, let the f/w know that the h/w is now + * under the control of the driver. + */ + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000_get_hw_control(adapter); + + /* tell the stack to leave us alone until e1000_open() is called */ + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + strcpy(netdev->name, "eth%d"); + err = register_netdev(netdev); + if (err) + goto err_register; + + e1000_print_device_info(adapter); + + return 0; + +err_register: + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000_release_hw_control(adapter); +err_eeprom: + if (hw->phy.ops.check_reset_block && + !hw->phy.ops.check_reset_block(hw)) + hw->phy.ops.reset(hw); +err_hw_init: + hw->mac.ops.remove_device(&adapter->hw); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +err_sw_init: + if (adapter->hw.flash_address) + iounmap(adapter->hw.flash_address); +err_flashmap: + iounmap(adapter->hw.hw_addr); +err_ioremap: + free_netdev(netdev); +err_alloc_etherdev: + pci_release_regions(pdev); +err_pci_reg: +err_dma: + pci_disable_device(pdev); + return err; +} + +/** + * e1000_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * e1000_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. The could be caused by a + * Hot-Plug event, or because the driver is going to be removed from + * memory. + **/ +static void __devexit e1000_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + /* + * flush_scheduled work may reschedule our watchdog task, so + * explicitly disable watchdog tasks from being rescheduled + */ + set_bit(__E1000_DOWN, &adapter->state); + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_info_timer); + + flush_scheduled_work(); + + /* + * Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. + */ + e1000_release_hw_control(adapter); + + unregister_netdev(netdev); + + if (hw->phy.ops.check_reset_block && + !hw->phy.ops.check_reset_block(hw)) + hw->phy.ops.reset(hw); + +#ifdef CONFIG_E1000E_MSIX + e1000_reset_interrupt_capability(adapter); +#endif /* CONFIG_E1000E_MSIX */ + hw->mac.ops.remove_device(&adapter->hw); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + + iounmap(adapter->hw.hw_addr); + if (adapter->hw.flash_address) + iounmap(adapter->hw.flash_address); + pci_release_regions(pdev); + + free_netdev(netdev); + + pci_disable_device(pdev); +} + +#ifdef HAVE_PCI_ERS +/* PCI Error Recovery (ERS) */ +static struct pci_error_handlers e1000_err_handler = { + .error_detected = e1000_io_error_detected, + .slot_reset = e1000_io_slot_reset, + .resume = e1000_io_resume, +}; +#endif + +static struct pci_device_id e1000e_pci_tbl[] = { + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER), board_82571 }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_SERDES), board_82572 }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E), board_82573 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E_IAMT), board_82573 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT), + board_80003es2lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_SPT), + board_80003es2lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_DPT), + board_80003es2lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_SPT), + board_80003es2lan }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE), board_ich8lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_G), board_ich8lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_GT), board_ich8lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_AMT), board_ich8lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_AMT), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_C), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_BM), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_V), board_ich9lan }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan }, + + { } /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, e1000e_pci_tbl); + +/* PCI Device API Driver */ +static struct pci_driver e1000_driver = { + .name = e1000e_driver_name, + .id_table = e1000e_pci_tbl, + .probe = e1000_probe, + .remove = __devexit_p(e1000_remove), +#ifdef CONFIG_PM + /* Power Management Hooks */ + .suspend = e1000_suspend, + .resume = e1000_resume, +#endif +#ifndef USE_REBOOT_NOTIFIER + .shutdown = e1000_shutdown, +#endif +#ifdef HAVE_PCI_ERS + .err_handler = &e1000_err_handler +#endif +}; + +/** + * e1000_init_module - Driver Registration Routine + * + * e1000_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + **/ +static int __init e1000_init_module(void) +{ + int ret; + printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Driver - %s\n", + e1000e_driver_name, e1000e_driver_version); + printk(KERN_INFO "%s: Copyright (c) 1999-2008 Intel Corporation.\n", + e1000e_driver_name); + ret = pci_register_driver(&e1000_driver); + pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, e1000e_driver_name, + PM_QOS_DEFAULT_VALUE); +#ifdef USE_REBOOT_NOTIFIER + if (ret >= 0) + register_reboot_notifier(&e1000_notifier_reboot); +#endif + + return ret; +} +module_init(e1000_init_module); + +/** + * e1000_exit_module - Driver Exit Cleanup Routine + * + * e1000_exit_module is called just before the driver is removed + * from memory. + **/ +static void __exit e1000_exit_module(void) +{ +#ifdef USE_REBOOT_NOTIFIER + unregister_reboot_notifier(&e1000_notifier_reboot); +#endif + pci_unregister_driver(&e1000_driver); + pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, e1000e_driver_name); +} +module_exit(e1000_exit_module); + + +MODULE_AUTHOR("Intel Corporation, "); +MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +/* netdev.c */ --- linux-2.6.27.orig/ubuntu/e1000e/e1000_hw.h +++ linux-2.6.27/ubuntu/e1000e/e1000_hw.h @@ -0,0 +1,674 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_HW_H_ +#define _E1000_HW_H_ + +#include "e1000_osdep.h" +#include "e1000_regs.h" +#include "e1000_defines.h" + +struct e1000_hw; + +#define E1000_DEV_ID_82571EB_COPPER 0x105E +#define E1000_DEV_ID_82571EB_FIBER 0x105F +#define E1000_DEV_ID_82571EB_SERDES 0x1060 +#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 +#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA +#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 +#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 +#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 +#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC +#define E1000_DEV_ID_82572EI_COPPER 0x107D +#define E1000_DEV_ID_82572EI_FIBER 0x107E +#define E1000_DEV_ID_82572EI_SERDES 0x107F +#define E1000_DEV_ID_82572EI 0x10B9 +#define E1000_DEV_ID_82573E 0x108B +#define E1000_DEV_ID_82573E_IAMT 0x108C +#define E1000_DEV_ID_82573L 0x109A +#define E1000_DEV_ID_82574L 0x10D3 +#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 +#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 +#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA +#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB +#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 +#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A +#define E1000_DEV_ID_ICH8_IGP_C 0x104B +#define E1000_DEV_ID_ICH8_IFE 0x104C +#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 +#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 +#define E1000_DEV_ID_ICH8_IGP_M 0x104D +#define E1000_DEV_ID_ICH9_IGP_M 0x10BF +#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 +#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB +#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD +#define E1000_DEV_ID_ICH9_BM 0x10E5 +#define E1000_DEV_ID_ICH9_IGP_C 0x294C +#define E1000_DEV_ID_ICH9_IFE 0x10C0 +#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 +#define E1000_DEV_ID_ICH9_IFE_G 0x10C2 +#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC +#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD +#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE +#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE +#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF + +#define E1000_REVISION_0 0 +#define E1000_REVISION_1 1 +#define E1000_REVISION_2 2 +#define E1000_REVISION_3 3 +#define E1000_REVISION_4 4 + +#define E1000_FUNC_0 0 +#define E1000_FUNC_1 1 + +typedef enum { + e1000_undefined = 0, + e1000_82571, + e1000_82572, + e1000_82573, + e1000_82574, + e1000_80003es2lan, + e1000_ich8lan, + e1000_ich9lan, + e1000_ich10lan, + e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ +} e1000_mac_type; + +typedef enum { + e1000_media_type_unknown = 0, + e1000_media_type_copper = 1, + e1000_media_type_fiber = 2, + e1000_media_type_internal_serdes = 3, + e1000_num_media_types +} e1000_media_type; + +typedef enum { + e1000_nvm_unknown = 0, + e1000_nvm_none, + e1000_nvm_eeprom_spi, + e1000_nvm_eeprom_microwire, + e1000_nvm_flash_hw, + e1000_nvm_flash_sw +} e1000_nvm_type; + +typedef enum { + e1000_nvm_override_none = 0, + e1000_nvm_override_spi_small, + e1000_nvm_override_spi_large, + e1000_nvm_override_microwire_small, + e1000_nvm_override_microwire_large +} e1000_nvm_override; + +typedef enum { + e1000_phy_unknown = 0, + e1000_phy_none, + e1000_phy_m88, + e1000_phy_igp, + e1000_phy_igp_2, + e1000_phy_gg82563, + e1000_phy_igp_3, + e1000_phy_ife, + e1000_phy_bm, +} e1000_phy_type; + +typedef enum { + e1000_bus_type_unknown = 0, + e1000_bus_type_pci, + e1000_bus_type_pcix, + e1000_bus_type_pci_express, + e1000_bus_type_reserved +} e1000_bus_type; + +typedef enum { + e1000_bus_speed_unknown = 0, + e1000_bus_speed_33, + e1000_bus_speed_66, + e1000_bus_speed_100, + e1000_bus_speed_120, + e1000_bus_speed_133, + e1000_bus_speed_2500, + e1000_bus_speed_5000, + e1000_bus_speed_reserved +} e1000_bus_speed; + +typedef enum { + e1000_bus_width_unknown = 0, + e1000_bus_width_pcie_x1, + e1000_bus_width_pcie_x2, + e1000_bus_width_pcie_x4 = 4, + e1000_bus_width_pcie_x8 = 8, + e1000_bus_width_32, + e1000_bus_width_64, + e1000_bus_width_reserved +} e1000_bus_width; + +typedef enum { + e1000_1000t_rx_status_not_ok = 0, + e1000_1000t_rx_status_ok, + e1000_1000t_rx_status_undefined = 0xFF +} e1000_1000t_rx_status; + +typedef enum { + e1000_rev_polarity_normal = 0, + e1000_rev_polarity_reversed, + e1000_rev_polarity_undefined = 0xFF +} e1000_rev_polarity; + +typedef enum { + e1000_fc_none = 0, + e1000_fc_rx_pause, + e1000_fc_tx_pause, + e1000_fc_full, + e1000_fc_default = 0xFF +} e1000_fc_type; + + +/* Receive Descriptor */ +struct e1000_rx_desc { + u64 buffer_addr; /* Address of the descriptor's data buffer */ + u16 length; /* Length of data DMAed into data buffer */ + u16 csum; /* Packet checksum */ + u8 status; /* Descriptor status */ + u8 errors; /* Descriptor Errors */ + u16 special; +}; + +/* Receive Descriptor - Extended */ +union e1000_rx_desc_extended { + struct { + u64 buffer_addr; + u64 reserved; + } read; + struct { + struct { + u32 mrq; /* Multiple Rx Queues */ + union { + u32 rss; /* RSS Hash */ + struct { + u16 ip_id; /* IP id */ + u16 csum; /* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; + struct { + u32 status_error; /* ext status/error */ + u16 length; + u16 vlan; /* VLAN tag */ + } upper; + } wb; /* writeback */ +}; + +#define MAX_PS_BUFFERS 4 +/* Receive Descriptor - Packet Split */ +union e1000_rx_desc_packet_split { + struct { + /* one buffer for protocol header(s), three data buffers */ + u64 buffer_addr[MAX_PS_BUFFERS]; + } read; + struct { + struct { + u32 mrq; /* Multiple Rx Queues */ + union { + u32 rss; /* RSS Hash */ + struct { + u16 ip_id; /* IP id */ + u16 csum; /* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; + struct { + u32 status_error; /* ext status/error */ + u16 length0; /* length of buffer 0 */ + u16 vlan; /* VLAN tag */ + } middle; + struct { + u16 header_status; + u16 length[3]; /* length of buffers 1-3 */ + } upper; + u64 reserved; + } wb; /* writeback */ +}; + +/* Transmit Descriptor */ +struct e1000_tx_desc { + u64 buffer_addr; /* Address of the descriptor's data buffer */ + union { + u32 data; + struct { + u16 length; /* Data buffer length */ + u8 cso; /* Checksum offset */ + u8 cmd; /* Descriptor control */ + } flags; + } lower; + union { + u32 data; + struct { + u8 status; /* Descriptor status */ + u8 css; /* Checksum start */ + u16 special; + } fields; + } upper; +}; + +/* Offload Context Descriptor */ +struct e1000_context_desc { + union { + u32 ip_config; + struct { + u8 ipcss; /* IP checksum start */ + u8 ipcso; /* IP checksum offset */ + u16 ipcse; /* IP checksum end */ + } ip_fields; + } lower_setup; + union { + u32 tcp_config; + struct { + u8 tucss; /* TCP checksum start */ + u8 tucso; /* TCP checksum offset */ + u16 tucse; /* TCP checksum end */ + } tcp_fields; + } upper_setup; + u32 cmd_and_length; + union { + u32 data; + struct { + u8 status; /* Descriptor status */ + u8 hdr_len; /* Header length */ + u16 mss; /* Maximum segment size */ + } fields; + } tcp_seg_setup; +}; + +/* Offload data descriptor */ +struct e1000_data_desc { + u64 buffer_addr; /* Address of the descriptor's buffer address */ + union { + u32 data; + struct { + u16 length; /* Data buffer length */ + u8 typ_len_ext; + u8 cmd; + } flags; + } lower; + union { + u32 data; + struct { + u8 status; /* Descriptor status */ + u8 popts; /* Packet Options */ + u16 special; + } fields; + } upper; +}; + +/* Statistics counters collected by the MAC */ +struct e1000_hw_stats { + u64 crcerrs; + u64 algnerrc; + u64 symerrs; + u64 rxerrc; + u64 mpc; + u64 scc; + u64 ecol; + u64 mcc; + u64 latecol; + u64 colc; + u64 dc; + u64 tncrs; + u64 sec; + u64 cexterr; + u64 rlec; + u64 xonrxc; + u64 xontxc; + u64 xoffrxc; + u64 xofftxc; + u64 fcruc; + u64 prc64; + u64 prc127; + u64 prc255; + u64 prc511; + u64 prc1023; + u64 prc1522; + u64 gprc; + u64 bprc; + u64 mprc; + u64 gptc; + u64 gorc; + u64 gotc; + u64 rnbc; + u64 ruc; + u64 rfc; + u64 roc; + u64 rjc; + u64 mgprc; + u64 mgpdc; + u64 mgptc; + u64 tor; + u64 tot; + u64 tpr; + u64 tpt; + u64 ptc64; + u64 ptc127; + u64 ptc255; + u64 ptc511; + u64 ptc1023; + u64 ptc1522; + u64 mptc; + u64 bptc; + u64 tsctc; + u64 tsctfc; + u64 iac; + u64 icrxptc; + u64 icrxatc; + u64 ictxptc; + u64 ictxatc; + u64 ictxqec; + u64 ictxqmtc; + u64 icrxdmtc; + u64 icrxoc; + u64 cbtmpc; + u64 htdpmc; + u64 cbrdpc; + u64 cbrmpc; + u64 rpthc; + u64 hgptc; + u64 htcbdpc; + u64 hgorc; + u64 hgotc; + u64 lenerrs; + u64 scvpc; + u64 hrmpc; +}; + +struct e1000_phy_stats { + u32 idle_errors; + u32 receive_errors; +}; + +struct e1000_host_mng_dhcp_cookie { + u32 signature; + u8 status; + u8 reserved0; + u16 vlan_id; + u32 reserved1; + u16 reserved2; + u8 reserved3; + u8 checksum; +}; + +/* Host Interface "Rev 1" */ +struct e1000_host_command_header { + u8 command_id; + u8 command_length; + u8 command_options; + u8 checksum; +}; + +#define E1000_HI_MAX_DATA_LENGTH 252 +struct e1000_host_command_info { + struct e1000_host_command_header command_header; + u8 command_data[E1000_HI_MAX_DATA_LENGTH]; +}; + +/* Host Interface "Rev 2" */ +struct e1000_host_mng_command_header { + u8 command_id; + u8 checksum; + u16 reserved1; + u16 reserved2; + u16 command_length; +}; + +#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 +struct e1000_host_mng_command_info { + struct e1000_host_mng_command_header command_header; + u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; +}; + +#include "e1000_mac.h" +#include "e1000_phy.h" +#include "e1000_nvm.h" +#include "e1000_manage.h" + +struct e1000_mac_operations { + /* Function pointers for the MAC. */ + s32 (*init_params)(struct e1000_hw *); + s32 (*blink_led)(struct e1000_hw *); + s32 (*check_for_link)(struct e1000_hw *); + bool (*check_mng_mode)(struct e1000_hw *hw); + s32 (*cleanup_led)(struct e1000_hw *); + void (*clear_hw_cntrs)(struct e1000_hw *); + void (*clear_vfta)(struct e1000_hw *); + s32 (*get_bus_info)(struct e1000_hw *); + s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); + s32 (*led_on)(struct e1000_hw *); + s32 (*led_off)(struct e1000_hw *); + void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, + u32); + void (*remove_device)(struct e1000_hw *); + s32 (*reset_hw)(struct e1000_hw *); + s32 (*init_hw)(struct e1000_hw *); + s32 (*setup_link)(struct e1000_hw *); + s32 (*setup_physical_interface)(struct e1000_hw *); + s32 (*setup_led)(struct e1000_hw *); + void (*write_vfta)(struct e1000_hw *, u32, u32); + void (*mta_set)(struct e1000_hw *, u32); + void (*config_collision_dist)(struct e1000_hw*); + void (*rar_set)(struct e1000_hw*, u8*, u32); + s32 (*read_mac_addr)(struct e1000_hw*); + s32 (*validate_mdi_setting)(struct e1000_hw*); + s32 (*mng_host_if_write)(struct e1000_hw*, u8*, u16, u16, u8*); + s32 (*mng_write_cmd_header)(struct e1000_hw *hw, + struct e1000_host_mng_command_header*); + s32 (*mng_enable_host_if)(struct e1000_hw*); + s32 (*wait_autoneg)(struct e1000_hw*); +}; + +struct e1000_phy_operations { + s32 (*init_params)(struct e1000_hw *); + s32 (*acquire)(struct e1000_hw *); + s32 (*check_polarity)(struct e1000_hw *); + s32 (*check_reset_block)(struct e1000_hw *); + s32 (*commit)(struct e1000_hw *); + s32 (*force_speed_duplex)(struct e1000_hw *); + s32 (*get_cfg_done)(struct e1000_hw *hw); + s32 (*get_cable_length)(struct e1000_hw *); + s32 (*get_info)(struct e1000_hw *); + s32 (*read_reg)(struct e1000_hw *, u32, u16 *); + void (*release)(struct e1000_hw *); + s32 (*reset)(struct e1000_hw *); + s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); + s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); + s32 (*write_reg)(struct e1000_hw *, u32, u16); + void (*power_up)(struct e1000_hw *); + void (*power_down)(struct e1000_hw *); +}; + +struct e1000_nvm_operations { + s32 (*init_params)(struct e1000_hw *); + s32 (*acquire)(struct e1000_hw *); + s32 (*read)(struct e1000_hw *, u16, u16, u16 *); + void (*release)(struct e1000_hw *); + void (*reload)(struct e1000_hw *); + s32 (*update)(struct e1000_hw *); + s32 (*valid_led_default)(struct e1000_hw *, u16 *); + s32 (*validate)(struct e1000_hw *); + s32 (*write)(struct e1000_hw *, u16, u16, u16 *); +}; + +struct e1000_mac_info { + struct e1000_mac_operations ops; + u8 addr[6]; + u8 perm_addr[6]; + + e1000_mac_type type; + + u32 collision_delta; + u32 ledctl_default; + u32 ledctl_mode1; + u32 ledctl_mode2; + u32 mc_filter_type; + u32 tx_packet_delta; + u32 txcw; + + u16 current_ifs_val; + u16 ifs_max_val; + u16 ifs_min_val; + u16 ifs_ratio; + u16 ifs_step_size; + u16 mta_reg_count; + u16 rar_entry_count; + + u8 forced_speed_duplex; + + bool adaptive_ifs; + bool arc_subsystem_valid; + bool asf_firmware_present; + bool autoneg; + bool autoneg_failed; + bool disable_av; + bool disable_hw_init_bits; + bool get_link_status; + bool ifs_params_forced; + bool in_ifs_mode; + bool report_tx_early; + bool serdes_has_link; + bool tx_pkt_filtering; +}; + +struct e1000_phy_info { + struct e1000_phy_operations ops; + e1000_phy_type type; + + e1000_1000t_rx_status local_rx; + e1000_1000t_rx_status remote_rx; + e1000_ms_type ms_type; + e1000_ms_type original_ms_type; + e1000_rev_polarity cable_polarity; + e1000_smart_speed smart_speed; + + u32 addr; + u32 id; + u32 reset_delay_us; /* in usec */ + u32 revision; + + e1000_media_type media_type; + + u16 autoneg_advertised; + u16 autoneg_mask; + u16 cable_length; + u16 max_cable_length; + u16 min_cable_length; + + u8 mdix; + + bool disable_polarity_correction; + bool is_mdix; + bool polarity_correction; + bool reset_disable; + bool speed_downgraded; + bool autoneg_wait_to_complete; +}; + +struct e1000_nvm_info { + struct e1000_nvm_operations ops; + e1000_nvm_type type; + e1000_nvm_override override; + + u32 flash_bank_size; + u32 flash_base_addr; + u32 semaphore_delay; + + u16 word_size; + u16 delay_usec; + u16 address_bits; + u16 opcode_bits; + u16 page_size; +}; + +struct e1000_bus_info { + e1000_bus_type type; + e1000_bus_speed speed; + e1000_bus_width width; + + u32 snoop; + + u16 func; + u16 pci_cmd_word; +}; + +struct e1000_fc_info { + u32 high_water; /* Flow control high-water mark */ + u32 low_water; /* Flow control low-water mark */ + u16 pause_time; /* Flow control pause timer */ + bool send_xon; /* Flow control send XON */ + bool strict_ieee; /* Strict IEEE mode */ + e1000_fc_type type; /* Type of flow control */ + e1000_fc_type original_type; +}; + +struct e1000_hw { + void *back; + void *dev_spec; + + u8 __iomem *hw_addr; + u8 __iomem *flash_address; + unsigned long io_base; + + /* Protect access to NV RAM mapping */ + spinlock_t flash_address_map_lock; + u32 flash_address_map_cnt; + + struct e1000_mac_info mac; + struct e1000_fc_info fc; + struct e1000_phy_info phy; + struct e1000_nvm_info nvm; + struct e1000_bus_info bus; + struct e1000_host_mng_dhcp_cookie mng_cookie; + + u32 dev_spec_size; + + u16 device_id; + u16 subsystem_vendor_id; + u16 subsystem_device_id; + u16 vendor_id; + + u8 revision_id; +}; + +#include "e1000_82571.h" +#include "e1000_80003es2lan.h" +#include "e1000_ich8lan.h" + +/* These functions must be implemented by drivers */ +s32 e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size); +s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); +void e1000_free_dev_spec_struct(struct e1000_hw *hw); +void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_80003es2lan.h +++ linux-2.6.27/ubuntu/e1000e/e1000_80003es2lan.h @@ -0,0 +1,95 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_80003ES2LAN_H_ +#define _E1000_80003ES2LAN_H_ + +#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 +#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 +#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 +#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F + +#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 +#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 +#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010 + +#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 +#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 +#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 + +#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ +#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 + +#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8 +#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9 + +/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ +#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Disabled */ +#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 +#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */ +#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */ +#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */ + +/* PHY Specific Control Register 2 (Page 0, Register 26) */ +#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 + /* 1=Reverse Auto-Negotiation */ + +/* MAC Specific Control Register (Page 2, Register 21) */ +/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ +#define GG82563_MSCR_TX_CLK_MASK 0x0007 +#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004 +#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005 +#define GG82563_MSCR_TX_CLK_1000MBPS_2_5 0x0006 +#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007 + +#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ + +/* DSP Distance Register (Page 5, Register 26) */ +/* + * 0 = <50M + * 1 = 50-80M + * 2 = 80-100M + * 3 = 110-140M + * 4 = >140M + */ +#define GG82563_DSPD_CABLE_LENGTH 0x0007 + +/* Kumeran Mode Control Register (Page 193, Register 16) */ +#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 + +/* Max number of times Kumeran read/write should be validated */ +#define GG82563_MAX_KMRN_RETRY 0x5 + +/* Power Management Control Register (Page 193, Register 20) */ +#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 + /* 1=Enable SERDES Electrical Idle */ + +/* In-Band Control Register (Page 194, Register 18) */ +#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/Kconfig +++ linux-2.6.27/ubuntu/e1000e/Kconfig @@ -0,0 +1,22 @@ +config E1000E_NEW + tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support" + depends on PCI && (!SPARC32 || BROKEN) && !E1000E + default m + ---help--- + This driver supports the PCI-Express Intel(R) PRO/1000 gigabit + ethernet family of adapters. For PCI or PCI-X e1000 adapters, + use the regular e1000 driver For more information on how to + identify your adapter, go to the Adapter & Driver ID Guide at: + + + + For general information and support, go to the Intel support + website at: + + + + To compile this driver as a module, choose M here. The module + will be called e1000e. + +config E1000E_ENABLED + def_bool E1000E_NEW != n --- linux-2.6.27.orig/ubuntu/e1000e/ethtool.c +++ linux-2.6.27/ubuntu/e1000e/ethtool.c @@ -0,0 +1,2002 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* ethtool support for e1000 */ + +#include +#ifdef SIOCETHTOOL +#include +#include +#include + +#include "e1000.h" +#ifdef NETIF_F_HW_VLAN_TX +#include +#endif + +#ifdef ETHTOOL_OPS_COMPAT +#include "kcompat_ethtool.c" +#endif + +struct e1000_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; +}; + +#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ + offsetof(struct e1000_adapter, m) +static const struct e1000_stats e1000_gstrings_stats[] = { + { "rx_packets", E1000_STAT(stats.gprc) }, + { "tx_packets", E1000_STAT(stats.gptc) }, + { "rx_bytes", E1000_STAT(stats.gorc) }, + { "tx_bytes", E1000_STAT(stats.gotc) }, + { "rx_broadcast", E1000_STAT(stats.bprc) }, + { "tx_broadcast", E1000_STAT(stats.bptc) }, + { "rx_multicast", E1000_STAT(stats.mprc) }, + { "tx_multicast", E1000_STAT(stats.mptc) }, + { "rx_errors", E1000_STAT(net_stats.rx_errors) }, + { "tx_errors", E1000_STAT(net_stats.tx_errors) }, + { "tx_dropped", E1000_STAT(net_stats.tx_dropped) }, + { "multicast", E1000_STAT(stats.mprc) }, + { "collisions", E1000_STAT(stats.colc) }, + { "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) }, + { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) }, + { "rx_crc_errors", E1000_STAT(stats.crcerrs) }, + { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, + { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, + { "rx_missed_errors", E1000_STAT(stats.mpc) }, + { "tx_aborted_errors", E1000_STAT(stats.ecol) }, + { "tx_carrier_errors", E1000_STAT(stats.tncrs) }, + { "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) }, + { "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) }, + { "tx_window_errors", E1000_STAT(stats.latecol) }, + { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, + { "tx_deferred_ok", E1000_STAT(stats.dc) }, + { "tx_single_coll_ok", E1000_STAT(stats.scc) }, + { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, + { "tx_timeout_count", E1000_STAT(tx_timeout_count) }, + { "tx_restart_queue", E1000_STAT(restart_queue) }, + { "rx_long_length_errors", E1000_STAT(stats.roc) }, + { "rx_short_length_errors", E1000_STAT(stats.ruc) }, + { "rx_align_errors", E1000_STAT(stats.algnerrc) }, + { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) }, + { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) }, + { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) }, + { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, + { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, + { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, + { "rx_long_byte_count", E1000_STAT(stats.gorc) }, + { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, + { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, + { "rx_header_split", E1000_STAT(rx_hdr_split) }, + { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, + { "tx_smbus", E1000_STAT(stats.mgptc) }, + { "rx_smbus", E1000_STAT(stats.mgprc) }, + { "dropped_smbus", E1000_STAT(stats.mgpdc) }, + { "rx_dma_failed", E1000_STAT(rx_dma_failed) }, + { "tx_dma_failed", E1000_STAT(tx_dma_failed) }, +}; + +#define E1000_GLOBAL_STATS_LEN \ + sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) +#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN) +static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { + "Register test (offline)", "Eeprom test (offline)", + "Interrupt test (offline)", "Loopback test (offline)", + "Link test (on/offline)" +}; +#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) + +static int e1000_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 status; + + if (hw->phy.media_type == e1000_media_type_copper) { + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP); + if (hw->phy.type == e1000_phy_ife) + ecmd->supported &= ~SUPPORTED_1000baseT_Full; + ecmd->advertising = ADVERTISED_TP; + + if (hw->mac.autoneg == 1) { + ecmd->advertising |= ADVERTISED_Autoneg; + /* the e1000 autoneg seems to match ethtool nicely */ + ecmd->advertising |= hw->phy.autoneg_advertised; + } + + ecmd->port = PORT_TP; + ecmd->phy_address = hw->phy.addr; + ecmd->transceiver = XCVR_INTERNAL; + + } else { + ecmd->supported = (SUPPORTED_1000baseT_Full | + SUPPORTED_FIBRE | + SUPPORTED_Autoneg); + + ecmd->advertising = (ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE | + ADVERTISED_Autoneg); + + ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_EXTERNAL; + } + + status = er32(STATUS); + if (status & E1000_STATUS_LU) { + if (status & E1000_STATUS_SPEED_1000) + ecmd->speed = 1000; + else if (status & E1000_STATUS_SPEED_100) + ecmd->speed = 100; + else + ecmd->speed = 10; + + if (status & E1000_STATUS_FD) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; + } else { + ecmd->speed = -1; + ecmd->duplex = -1; + } + + ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || + hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; + return 0; +} + +static u32 e1000_get_link(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 status; + + status = er32(STATUS); + return (status & E1000_STATUS_LU); +} + +static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) +{ + struct e1000_mac_info *mac = &adapter->hw.mac; + + mac->autoneg = 0; + + /* Fiber NICs only allow 1000 gbps Full duplex */ + if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && + spddplx != (SPEED_1000 + DUPLEX_FULL)) { + e_err("Unsupported Speed/Duplex configuration\n"); + return -EINVAL; + } + + switch (spddplx) { + case SPEED_10 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_10_HALF; + break; + case SPEED_10 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_10_FULL; + break; + case SPEED_100 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_100_HALF; + break; + case SPEED_100 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_100_FULL; + break; + case SPEED_1000 + DUPLEX_FULL: + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; + break; + case SPEED_1000 + DUPLEX_HALF: /* not supported */ + default: + e_err("Unsupported Speed/Duplex configuration\n"); + return -EINVAL; + } + return 0; +} + +static int e1000_set_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + /* + * When SoL/IDER sessions are active, autoneg/speed/duplex + * cannot be changed + */ + if (hw->phy.ops.check_reset_block && + hw->phy.ops.check_reset_block(&adapter->hw)) { + e_err("Cannot change link characteristics when SoL/IDER" + " is active.\n"); + return -EINVAL; + } + + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + msleep(1); + + if (ecmd->autoneg == AUTONEG_ENABLE) { + hw->mac.autoneg = 1; + if (hw->phy.media_type == e1000_media_type_fiber) + hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE | + ADVERTISED_Autoneg; + else + hw->phy.autoneg_advertised = ecmd->advertising | + ADVERTISED_TP | + ADVERTISED_Autoneg; + ecmd->advertising = hw->phy.autoneg_advertised; + if (adapter->fc_autoneg) + hw->fc.original_type = e1000_fc_default; + } else { + if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { + clear_bit(__E1000_RESETTING, &adapter->state); + return -EINVAL; + } + } + + /* reset the link */ + + if (netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else { + e1000_reset(adapter); + } + + clear_bit(__E1000_RESETTING, &adapter->state); + return 0; +} + +static void e1000_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + pause->autoneg = + (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + + if (hw->fc.type == e1000_fc_rx_pause) { + pause->rx_pause = 1; + } else if (hw->fc.type == e1000_fc_tx_pause) { + pause->tx_pause = 1; + } else if (hw->fc.type == e1000_fc_full) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } +} + +static int e1000_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + int retval = 0; + + adapter->fc_autoneg = pause->autoneg; + + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + msleep(1); + + if (pause->rx_pause && pause->tx_pause) + hw->fc.type = e1000_fc_full; + else if (pause->rx_pause && !pause->tx_pause) + hw->fc.type = e1000_fc_rx_pause; + else if (!pause->rx_pause && pause->tx_pause) + hw->fc.type = e1000_fc_tx_pause; + else if (!pause->rx_pause && !pause->tx_pause) + hw->fc.type = e1000_fc_none; + + hw->fc.original_type = hw->fc.type; + + if (adapter->fc_autoneg == AUTONEG_ENABLE) { + hw->fc.type = e1000_fc_default; + if (netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else { + e1000_reset(adapter); + } + } else { + retval = ((hw->phy.media_type == e1000_media_type_fiber) ? + hw->mac.ops.setup_link(hw) : + e1000_force_mac_fc_generic(hw)); + } + + clear_bit(__E1000_RESETTING, &adapter->state); + return retval; +} + +static u32 e1000_get_rx_csum(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + return (adapter->flags & FLAG_RX_CSUM_ENABLED); +} + +static int e1000_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (data) + adapter->flags |= FLAG_RX_CSUM_ENABLED; + else + adapter->flags &= ~FLAG_RX_CSUM_ENABLED; + + if (netif_running(netdev)) + e1000_reinit_locked(adapter); + else + e1000_reset(adapter); + return 0; +} + +static u32 e1000_get_tx_csum(struct net_device *netdev) +{ + return ((netdev->features & NETIF_F_HW_CSUM) != 0); +} + +static int e1000_set_tx_csum(struct net_device *netdev, u32 data) +{ + if (data) + netdev->features |= NETIF_F_HW_CSUM; + else + netdev->features &= ~NETIF_F_HW_CSUM; + + return 0; +} + +#ifdef NETIF_F_TSO +static int e1000_set_tso(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + int i; + struct net_device *v_netdev; + + if (data) { + netdev->features |= NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + netdev->features |= NETIF_F_TSO6; +#endif + } else { + netdev->features &= ~NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + netdev->features &= ~NETIF_F_TSO6; +#endif +#ifdef NETIF_F_HW_VLAN_TX + /* disable TSO on all VLANs if they're present */ + if (!adapter->vlgrp) + goto tso_out; + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + v_netdev = vlan_group_get_device(adapter->vlgrp, i); + if (!v_netdev) + continue; + + v_netdev->features &= ~NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + v_netdev->features &= ~NETIF_F_TSO6; +#endif + vlan_group_set_device(adapter->vlgrp, i, v_netdev); + } +#endif + } + +tso_out: + e_info("TSO is %s\n", data ? "Enabled" : "Disabled"); + adapter->flags |= FLAG_TSO_FORCE; + return 0; +} +#endif + +static u32 e1000_get_msglevel(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + return adapter->msg_enable; +} + +static void e1000_set_msglevel(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + adapter->msg_enable = data; +} + +static int e1000_get_regs_len(struct net_device *netdev) +{ +#define E1000_REGS_LEN 32 /* overestimate */ + return E1000_REGS_LEN * sizeof(u32); +} + +static void e1000_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 *regs_buff = p; + u16 phy_data; + u8 revision_id; + + memset(p, 0, E1000_REGS_LEN * sizeof(u32)); + + pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id); + + regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device; + + regs_buff[0] = er32(CTRL); + regs_buff[1] = er32(STATUS); + + regs_buff[2] = er32(RCTL); + regs_buff[3] = er32(RDLEN(0)); + regs_buff[4] = er32(RDH(0)); + regs_buff[5] = er32(RDT(0)); + regs_buff[6] = er32(RDTR); + + regs_buff[7] = er32(TCTL); + regs_buff[8] = er32(TDLEN(0)); + regs_buff[9] = er32(TDH(0)); + regs_buff[10] = er32(TDT(0)); + regs_buff[11] = er32(TIDV); + + regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ + if (hw->phy.type == e1000_phy_m88) { + hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + regs_buff[13] = (u32)phy_data; /* cable length */ + regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + regs_buff[17] = (u32)phy_data; /* extended 10bt distance */ + regs_buff[18] = regs_buff[13]; /* cable polarity */ + regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + regs_buff[20] = regs_buff[17]; /* polarity correction */ + /* phy receive errors */ + regs_buff[22] = adapter->phy_stats.receive_errors; + regs_buff[23] = regs_buff[13]; /* mdix mode */ + } + regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ + hw->phy.ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); + regs_buff[24] = (u32)phy_data; /* phy local receiver status */ + regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ +} + +static int e1000_get_eeprom_len(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + return adapter->hw.nvm.word_size * 2; +} + +static int e1000_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u16 *eeprom_buff; + int first_word; + int last_word; + int ret_val = 0; + u16 i; + + if (eeprom->len == 0) + return -EINVAL; + + eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16); + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + + eeprom_buff = kmalloc(sizeof(u16) * + (last_word - first_word + 1), GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + if (hw->nvm.type == e1000_nvm_eeprom_spi) { + ret_val = hw->nvm.ops.read(hw, first_word, + last_word - first_word + 1, + eeprom_buff); + } else { + for (i = 0; i < last_word - first_word + 1; i++) { + ret_val = hw->nvm.ops.read(hw, first_word + i, 1, + &eeprom_buff[i]); + if (ret_val) + break; + } + } + + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + + memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); + kfree(eeprom_buff); + + return ret_val; +} + +static int e1000_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u16 *eeprom_buff; + void *ptr; + int max_len; + int first_word; + int last_word; + int ret_val = 0; + u16 i; + + if (eeprom->len == 0) + return -EOPNOTSUPP; + + if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16))) + return -EFAULT; + + max_len = hw->nvm.word_size * 2; + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + eeprom_buff = kmalloc(max_len, GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + ptr = (void *)eeprom_buff; + + if (eeprom->offset & 1) { + /* need read/modify/write of first changed EEPROM word */ + /* only the second byte of the word is being modified */ + ret_val = hw->nvm.ops.read(hw, first_word, 1, &eeprom_buff[0]); + ptr++; + } + if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) + /* need read/modify/write of last changed EEPROM word */ + /* only the first byte of the word is being modified */ + ret_val = hw->nvm.ops.read(hw, last_word, 1, + &eeprom_buff[last_word - first_word]); + + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + + memcpy(ptr, bytes, eeprom->len); + + for (i = 0; i < last_word - first_word + 1; i++) + eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); + + ret_val = hw->nvm.ops.write(hw, first_word, last_word - first_word + 1, + eeprom_buff); + + /* + * Update the checksum over the first part of the EEPROM if needed + * and flush shadow RAM for 82573 controllers + */ + if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG) || + (hw->mac.type == e1000_82574) || + (hw->mac.type == e1000_82573))) + hw->nvm.ops.update(hw); + + kfree(eeprom_buff); + return ret_val; +} + +static void e1000_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + char firmware_version[32]; + u16 eeprom_data; + + strncpy(drvinfo->driver, e1000e_driver_name, 32); + strncpy(drvinfo->version, e1000e_driver_version, 32); + + /* + * EEPROM image version # is reported as firmware version # for + * PCI-E controllers + */ + hw->nvm.ops.read(&adapter->hw, 5, 1, &eeprom_data); + sprintf(firmware_version, "%d.%d-%d", + (eeprom_data & 0xF000) >> 12, + (eeprom_data & 0x0FF0) >> 4, + eeprom_data & 0x000F); + + strncpy(drvinfo->fw_version, firmware_version, 32); + strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); + drvinfo->regdump_len = e1000_get_regs_len(netdev); + drvinfo->eedump_len = e1000_get_eeprom_len(netdev); +} + +static void e1000_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_ring *rx_ring = adapter->rx_ring; + + ring->rx_max_pending = E1000_MAX_RXD; + ring->tx_max_pending = E1000_MAX_TXD; + ring->rx_mini_max_pending = 0; + ring->rx_jumbo_max_pending = 0; + ring->rx_pending = rx_ring->count; + ring->tx_pending = tx_ring->count; + ring->rx_mini_pending = 0; + ring->rx_jumbo_pending = 0; +} + +static int e1000_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_ring *tx_ring, *tx_old; + struct e1000_ring *rx_ring, *rx_old; + int err; + + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + msleep(1); + + if (netif_running(adapter->netdev)) + e1000_down(adapter); + + tx_old = adapter->tx_ring; + rx_old = adapter->rx_ring; + + err = -ENOMEM; + tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); + if (!tx_ring) + goto err_alloc_tx; + /* + * use a memcpy to save any previously configured + * items like napi structs from having to be + * reinitialized + */ + memcpy(tx_ring, tx_old, sizeof(struct e1000_ring)); + + rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); + if (!rx_ring) + goto err_alloc_rx; + memcpy(rx_ring, rx_old, sizeof(struct e1000_ring)); + + adapter->tx_ring = tx_ring; + adapter->rx_ring = rx_ring; + + rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD); + rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD)); + rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); + + tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD); + tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD)); + tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); + + if (netif_running(adapter->netdev)) { + /* Try to get new resources before deleting old */ + err = e1000_setup_rx_resources(adapter); + if (err) + goto err_setup_rx; + err = e1000_setup_tx_resources(adapter); + if (err) + goto err_setup_tx; + + /* + * restore the old in order to free it, + * then add in the new + */ + adapter->rx_ring = rx_old; + adapter->tx_ring = tx_old; + e1000_free_rx_resources(adapter); + e1000_free_tx_resources(adapter); + kfree(tx_old); + kfree(rx_old); + adapter->rx_ring = rx_ring; + adapter->tx_ring = tx_ring; + err = e1000_up(adapter); + if (err) + goto err_setup; + } + + clear_bit(__E1000_RESETTING, &adapter->state); + return 0; +err_setup_tx: + e1000_free_rx_resources(adapter); +err_setup_rx: + adapter->rx_ring = rx_old; + adapter->tx_ring = tx_old; + kfree(rx_ring); +err_alloc_rx: + kfree(tx_ring); +err_alloc_tx: + e1000_up(adapter); +err_setup: + clear_bit(__E1000_RESETTING, &adapter->state); + return err; +} + +static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, + int reg, int offset, u32 mask, u32 write) +{ + u32 pat, val; + static const u32 test[] = + {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; + for (pat = 0; pat < ARRAY_SIZE(test); pat++) { + E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, + (test[pat] & write)); + val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); + if (val != (test[pat] & write & mask)) { + e_err("pattern test reg %04X failed: got " + "0x%08X expected 0x%08X\n", + reg + offset, + val, (test[pat] & write & mask)); + *data = reg; + return 1; + } + } + return 0; +} + +static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, + int reg, u32 mask, u32 write) +{ + u32 val; + __ew32(&adapter->hw, reg, write & mask); + val = __er32(&adapter->hw, reg); + if ((write & mask) != (val & mask)) { + e_err("set/check reg %04X test failed: got 0x%08X" + "expected 0x%08X\n", reg, (val & mask), (write & mask)); + *data = reg; + return 1; + } + return 0; +} +#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \ + do { \ + if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \ + return 1; \ + } while (0) +#define REG_PATTERN_TEST(reg, mask, write) \ + REG_PATTERN_TEST_ARRAY(reg, 0, mask, write) + +#define REG_SET_AND_CHECK(reg, mask, write) \ + do { \ + if (reg_set_and_check(adapter, data, reg, mask, write)) \ + return 1; \ + } while (0) + +static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_mac_info *mac = &adapter->hw.mac; + u32 value; + u32 before; + u32 after; + u32 i; + u32 toggle; + + /* + * The status register is Read Only, so a write should fail. + * Some bits that get toggled are ignored. + */ + switch (mac->type) { + /* there are several bits on newer hardware that are r/w */ + case e1000_82571: + case e1000_82572: + case e1000_80003es2lan: + toggle = 0x7FFFF3FF; + break; + case e1000_82573: + case e1000_82574: + case e1000_ich8lan: + case e1000_ich9lan: + case e1000_ich10lan: + toggle = 0x7FFFF033; + break; + default: + toggle = 0xFFFFF833; + break; + } + + before = er32(STATUS); + value = (er32(STATUS) & toggle); + ew32(STATUS, toggle); + after = er32(STATUS) & toggle; + if (value != after) { + e_err("failed STATUS register test got: " + "0x%08X expected: 0x%08X\n", after, value); + *data = 1; + return 1; + } + /* restore previous status */ + ew32(STATUS, before); + + if (!(adapter->flags & FLAG_IS_ICH)) { + REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF); + } + + REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF); + REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8); + REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF); + REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF); + + REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000); + + before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE); + REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB); + REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000); + + REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); + if (!(adapter->flags & FLAG_IS_ICH)) + REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); + for (i = 0; i < mac->rar_entry_count; i++) + REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), + ((mac->type == e1000_ich10lan) ? + 0x8007FFFF : 0x8003FFFF), + 0xFFFFFFFF); + + for (i = 0; i < mac->mta_reg_count; i++) + REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); + + *data = 0; + return 0; +} + +static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) +{ + struct e1000_hw *hw = &adapter->hw; + u16 temp; + u16 checksum = 0; + u16 i; + + *data = 0; + /* Read and add up the contents of the EEPROM */ + for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { + if ((hw->nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) { + *data = 1; + break; + } + checksum += temp; + } + + /* If Checksum is not Correct return error else test passed */ + if ((checksum != (u16) NVM_SUM) && !(*data)) + *data = 2; + + return *data; +} + +static irqreturn_t e1000_test_intr(int irq, void *data) +{ + struct net_device *netdev = (struct net_device *) data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + adapter->test_icr |= er32(ICR); + + return IRQ_HANDLED; +} + +static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) +{ + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; + u32 mask; + u32 shared_int = 1; + u32 irq = adapter->pdev->irq; + int i; +#ifdef CONFIG_E1000E_MSIX + int ret_val = 0; + int int_mode = E1000E_INT_MODE_LEGACY; +#endif + + *data = 0; + + /* NOTE: we don't test MSI/MSI-X interrupts here, yet */ +#ifdef CONFIG_E1000E_MSIX + if (adapter->int_mode == E1000E_INT_MODE_MSIX) { + int_mode = adapter->int_mode; + e1000_reset_interrupt_capability(adapter); + adapter->int_mode = E1000E_INT_MODE_LEGACY; + e1000_set_interrupt_capability(adapter); + } +#endif + /* Hook up test interrupt handler just for this test */ + if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, + netdev)) { + shared_int = 0; + } else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED, + netdev->name, netdev)) { + *data = 1; +#ifdef CONFIG_E1000E_MSIX + ret_val = -1; + goto out; +#else + return -1; +#endif + } + e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared")); + + /* Disable all the interrupts */ + ew32(IMC, 0xFFFFFFFF); + msleep(10); + + /* Test each interrupt */ + for (i = 0; i < 10; i++) { + /* Interrupt to test */ + mask = 1 << i; + + if (adapter->flags & FLAG_IS_ICH) { + switch (mask) { + case E1000_ICR_RXSEQ: + continue; + case 0x00000100: + if (adapter->hw.mac.type == e1000_ich8lan || + adapter->hw.mac.type == e1000_ich9lan) + continue; + break; + default: + break; + } + } + + if (!shared_int) { + /* + * Disable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + ew32(IMC, mask); + ew32(ICS, mask); + msleep(10); + + if (adapter->test_icr & mask) { + *data = 3; + break; + } + } + + /* + * Enable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was not posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + ew32(IMS, mask); + ew32(ICS, mask); + msleep(10); + + if (!(adapter->test_icr & mask)) { + *data = 4; + break; + } + + if (!shared_int) { + /* + * Disable the other interrupts to be reported in + * the cause register and then force the other + * interrupts and see if any get posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + ew32(IMC, ~mask & 0x00007FFF); + ew32(ICS, ~mask & 0x00007FFF); + msleep(10); + + if (adapter->test_icr) { + *data = 5; + break; + } + } + } + + /* Disable all the interrupts */ + ew32(IMC, 0xFFFFFFFF); + msleep(10); + + /* Unhook test interrupt handler */ + free_irq(irq, netdev); + +#ifdef CONFIG_E1000E_MSIX +out: + if (int_mode == E1000E_INT_MODE_MSIX) { + e1000_reset_interrupt_capability(adapter); + adapter->int_mode = int_mode; + e1000_set_interrupt_capability(adapter); + } + + return ret_val; +#else + return *data; +#endif +} + +static void e1000_free_desc_rings(struct e1000_adapter *adapter) +{ + struct e1000_ring *tx_ring = &adapter->test_tx_ring; + struct e1000_ring *rx_ring = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + int i; + + if (tx_ring->desc && tx_ring->buffer_info) { + for (i = 0; i < tx_ring->count; i++) { + if (tx_ring->buffer_info[i].dma) + pci_unmap_single(pdev, + tx_ring->buffer_info[i].dma, + tx_ring->buffer_info[i].length, + PCI_DMA_TODEVICE); + if (tx_ring->buffer_info[i].skb) + dev_kfree_skb(tx_ring->buffer_info[i].skb); + } + } + + if (rx_ring->desc && rx_ring->buffer_info) { + for (i = 0; i < rx_ring->count; i++) { + if (rx_ring->buffer_info[i].dma) + pci_unmap_single(pdev, + rx_ring->buffer_info[i].dma, + 2048, PCI_DMA_FROMDEVICE); + if (rx_ring->buffer_info[i].skb) + dev_kfree_skb(rx_ring->buffer_info[i].skb); + } + } + + if (tx_ring->desc) { + dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, + tx_ring->dma); + tx_ring->desc = NULL; + } + if (rx_ring->desc) { + dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, + rx_ring->dma); + rx_ring->desc = NULL; + } + + kfree(tx_ring->buffer_info); + tx_ring->buffer_info = NULL; + kfree(rx_ring->buffer_info); + rx_ring->buffer_info = NULL; +} + +static int e1000_setup_desc_rings(struct e1000_adapter *adapter) +{ + struct e1000_ring *tx_ring = &adapter->test_tx_ring; + struct e1000_ring *rx_ring = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; + u32 rctl; + int i; + int ret_val; + + /* Setup Tx descriptor ring and Tx buffers */ + + if (!tx_ring->count) + tx_ring->count = E1000_DEFAULT_TXD; + + if (!(tx_ring->buffer_info = kcalloc(tx_ring->count, + sizeof(struct e1000_buffer), + GFP_KERNEL))) { + ret_val = 1; + goto err_nomem; + } + + tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); + tx_ring->size = ALIGN(tx_ring->size, 4096); + tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, + &tx_ring->dma, GFP_KERNEL); + if (!tx_ring->desc) { + ret_val = 2; + goto err_nomem; + } + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + + ew32(TDBAL(0), ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); + ew32(TDBAH(0), ((u64) tx_ring->dma >> 32)); + ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc)); + ew32(TDH(0), 0); + ew32(TDT(0), 0); + ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR | + E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | + E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); + + for (i = 0; i < tx_ring->count; i++) { + struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); + struct sk_buff *skb; + unsigned int skb_size = 1024; + + skb = alloc_skb(skb_size, GFP_KERNEL); + if (!skb) { + ret_val = 3; + goto err_nomem; + } + skb_put(skb, skb_size); + tx_ring->buffer_info[i].skb = skb; + tx_ring->buffer_info[i].length = skb->len; + tx_ring->buffer_info[i].dma = + pci_map_single(pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, tx_ring->buffer_info[i].dma)) { + ret_val = 4; + goto err_nomem; + } + tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); + tx_desc->lower.data = cpu_to_le32(skb->len); + tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | + E1000_TXD_CMD_IFCS | + E1000_TXD_CMD_RS); + tx_desc->upper.data = 0; + } + + /* Setup Rx descriptor ring and Rx buffers */ + + if (!rx_ring->count) + rx_ring->count = E1000_DEFAULT_RXD; + + if (!(rx_ring->buffer_info = kcalloc(rx_ring->count, + sizeof(struct e1000_buffer), + GFP_KERNEL))) { + ret_val = 5; + goto err_nomem; + } + + rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc); + rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, + &rx_ring->dma, GFP_KERNEL); + if (!rx_ring->desc) { + ret_val = 6; + goto err_nomem; + } + rx_ring->next_to_use = 0; + rx_ring->next_to_clean = 0; + + rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + ew32(RDBAL(0), ((u64) rx_ring->dma & 0xFFFFFFFF)); + ew32(RDBAH(0), ((u64) rx_ring->dma >> 32)); + ew32(RDLEN(0), rx_ring->size); + ew32(RDH(0), 0); + ew32(RDT(0), 0); + rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | + E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | + E1000_RCTL_SBP | E1000_RCTL_SECRC | + E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | + (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); + ew32(RCTL, rctl); + + for (i = 0; i < rx_ring->count; i++) { + struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); + struct sk_buff *skb; + + skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL); + if (!skb) { + ret_val = 7; + goto err_nomem; + } + skb_reserve(skb, NET_IP_ALIGN); + rx_ring->buffer_info[i].skb = skb; + rx_ring->buffer_info[i].dma = + pci_map_single(pdev, skb->data, 2048, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, rx_ring->buffer_info[i].dma)) { + ret_val = 8; + goto err_nomem; + } + rx_desc->buffer_addr = + cpu_to_le64(rx_ring->buffer_info[i].dma); + memset(skb->data, 0x00, skb->len); + } + + return 0; + +err_nomem: + e1000_free_desc_rings(adapter); + return ret_val; +} + +static void e1000_phy_disable_receiver(struct e1000_adapter *adapter) +{ + /* Write out to PHY registers 29 and 30 to disable the Receiver. */ + adapter->hw.phy.ops.write_reg(&adapter->hw, 29, 0x001F); + adapter->hw.phy.ops.write_reg(&adapter->hw, 30, 0x8FFC); + adapter->hw.phy.ops.write_reg(&adapter->hw, 29, 0x001A); + adapter->hw.phy.ops.write_reg(&adapter->hw, 30, 0x8FF0); +} + +static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl_reg = 0; + u32 stat_reg = 0; + u16 phy_reg = 0; + + hw->mac.autoneg = 0; + + if (hw->phy.type == e1000_phy_m88) { + /* Auto-MDI/MDIX Off */ + hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); + /* reset to update Auto-MDI/MDIX */ + hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x9140); + /* autoneg off */ + hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x8140); + } else if (hw->phy.type == e1000_phy_gg82563) + hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); + + ctrl_reg = er32(CTRL); + + switch (hw->phy.type) { + case e1000_phy_ife: + /* force 100, set loopback */ + hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x6100); + + /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ + ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ + E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ + E1000_CTRL_SPD_100 |/* Force Speed to 100 */ + E1000_CTRL_FD); /* Force Duplex to FULL */ + break; + case e1000_phy_bm: + /* Set Default MAC Interface speed to 1GB */ + hw->phy.ops.read_reg(hw, PHY_REG(2, 21), &phy_reg); + phy_reg &= ~0x0007; + phy_reg |= 0x006; + hw->phy.ops.write_reg(hw, PHY_REG(2, 21), phy_reg); + /* Assert SW reset for above settings to take effect */ + hw->phy.ops.commit(hw); + mdelay(1); + /* Force Full Duplex */ + hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &phy_reg); + hw->phy.ops.write_reg(hw, PHY_REG(769, 16), phy_reg | 0x000C); + /* Set Link Up (in force link) */ + hw->phy.ops.read_reg(hw, PHY_REG(776, 16), &phy_reg); + hw->phy.ops.write_reg(hw, PHY_REG(776, 16), phy_reg | 0x0040); + /* Force Link */ + hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &phy_reg); + hw->phy.ops.write_reg(hw, PHY_REG(769, 16), phy_reg | 0x0040); + /* Set Early Link Enable */ + hw->phy.ops.read_reg(hw, PHY_REG(769, 20), &phy_reg); + hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg | 0x0400); + /* fall through */ + default: + /* force 1000, set loopback */ + hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x4140); + mdelay(250); + + /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = er32(CTRL); + ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ + ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ + E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ + E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ + E1000_CTRL_FD); /* Force Duplex to FULL */ + + if (adapter->flags & FLAG_IS_ICH) + ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ + } + + if (hw->phy.media_type == e1000_media_type_copper && + hw->phy.type == e1000_phy_m88) { + ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ + } else { + /* + * Set the ILOS bit on the fiber Nic if half duplex link is + * detected. + */ + stat_reg = er32(STATUS); + if ((stat_reg & E1000_STATUS_FD) == 0) + ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); + } + + ew32(CTRL, ctrl_reg); + + /* + * Disable the receiver on the PHY so when a cable is plugged in, the + * PHY does not begin to autoneg when a cable is reconnected to the NIC. + */ + if (hw->phy.type == e1000_phy_m88) + e1000_phy_disable_receiver(adapter); + + udelay(500); + + return 0; +} + +static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl = er32(CTRL); + int link = 0; + + /* special requirements for 82571/82572 fiber adapters */ + + /* + * jump through hoops to make sure link is up because serdes + * link is hardwired up + */ + ctrl |= E1000_CTRL_SLU; + ew32(CTRL, ctrl); + + /* disable autoneg */ + ctrl = er32(TXCW); + ctrl &= ~(1 << 31); + ew32(TXCW, ctrl); + + link = (er32(STATUS) & E1000_STATUS_LU); + + if (!link) { + /* set invert loss of signal */ + ctrl = er32(CTRL); + ctrl |= E1000_CTRL_ILOS; + ew32(CTRL, ctrl); + } + + /* + * special write to serdes control register to enable SerDes analog + * loopback + */ +#define E1000_SERDES_LB_ON 0x410 + ew32(SCTL, E1000_SERDES_LB_ON); + msleep(10); + + return 0; +} + +/* only call this for fiber/serdes connections to es2lan */ +static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrlext = er32(CTRL_EXT); + u32 ctrl = er32(CTRL); + + /* + * save CTRL_EXT to restore later, reuse an empty variable (unused + * on mac_type 80003es2lan) + */ + adapter->tx_fifo_head = ctrlext; + + /* clear the serdes mode bits, putting the device into mac loopback */ + ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; + ew32(CTRL_EXT, ctrlext); + + /* force speed to 1000/FD, link up */ + ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); + ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | + E1000_CTRL_SPD_1000 | E1000_CTRL_FD); + ew32(CTRL, ctrl); + + /* set mac loopback */ + ctrl = er32(RCTL); + ctrl |= E1000_RCTL_LBM_MAC; + ew32(RCTL, ctrl); + + /* set testing mode parameters (no need to reset later) */ +#define KMRNCTRLSTA_OPMODE (0x1F << 16) +#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582 + ew32(KMRNCTRLSTA, + (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII)); + + return 0; +} + +static int e1000_setup_loopback_test(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rctl; + + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { + switch (hw->mac.type) { + case e1000_80003es2lan: + return e1000_set_es2lan_mac_loopback(adapter); + break; + case e1000_82571: + case e1000_82572: + return e1000_set_82571_fiber_loopback(adapter); + break; + default: + rctl = er32(RCTL); + rctl |= E1000_RCTL_LBM_TCVR; + ew32(RCTL, rctl); + return 0; + } + } else if (hw->phy.media_type == e1000_media_type_copper) { + return e1000_integrated_phy_loopback(adapter); + } + + return 7; +} + +static void e1000_loopback_cleanup(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rctl; + u16 phy_reg; + + rctl = er32(RCTL); + rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); + ew32(RCTL, rctl); + + switch (hw->mac.type) { + case e1000_80003es2lan: + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { + /* restore CTRL_EXT, stealing space from tx_fifo_head */ + ew32(CTRL_EXT, adapter->tx_fifo_head); + adapter->tx_fifo_head = 0; + } + /* fall through */ + case e1000_82571: + case e1000_82572: + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { +#define E1000_SERDES_LB_OFF 0x400 + ew32(SCTL, E1000_SERDES_LB_OFF); + msleep(10); + break; + } + /* Fall Through */ + default: + hw->mac.autoneg = 1; + if (hw->phy.type == e1000_phy_gg82563) + hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + 0x180); + if(hw->phy.ops.read_reg) + hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_reg); + if (phy_reg & MII_CR_LOOPBACK) { + phy_reg &= ~MII_CR_LOOPBACK; + hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_reg); + if (hw->phy.ops.commit) + hw->phy.ops.commit(hw); + } + break; + } +} + +static void e1000_create_lbtest_frame(struct sk_buff *skb, + unsigned int frame_size) +{ + memset(skb->data, 0xFF, frame_size); + frame_size &= ~1; + memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); + memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); + memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); +} + +static int e1000_check_lbtest_frame(struct sk_buff *skb, + unsigned int frame_size) +{ + frame_size &= ~1; + if (*(skb->data + 3) == 0xFF) + if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && + (*(skb->data + frame_size / 2 + 12) == 0xAF)) + return 0; + return 13; +} + +static int e1000_run_loopback_test(struct e1000_adapter *adapter) +{ + struct e1000_ring *tx_ring = &adapter->test_tx_ring; + struct e1000_ring *rx_ring = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; + int i, j, k, l; + int lc; + int good_cnt; + int ret_val = 0; + unsigned long time; + + ew32(RDT(0), rx_ring->count - 1); + + /* + * Calculate the loop count based on the largest descriptor ring + * The idea is to wrap the largest ring a number of times using 64 + * send/receive pairs during each loop + */ + + if (rx_ring->count <= tx_ring->count) + lc = ((tx_ring->count / 64) * 2) + 1; + else + lc = ((rx_ring->count / 64) * 2) + 1; + + k = 0; + l = 0; + for (j = 0; j <= lc; j++) { /* loop count loop */ + for (i = 0; i < 64; i++) { /* send the packets */ + e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb, + 1024); + pci_dma_sync_single_for_device(pdev, + tx_ring->buffer_info[k].dma, + tx_ring->buffer_info[k].length, + PCI_DMA_TODEVICE); + k++; + if (k == tx_ring->count) + k = 0; + } + ew32(TDT(0), k); + msleep(200); + time = jiffies; /* set the start time for the receive */ + good_cnt = 0; + do { /* receive the sent packets */ + pci_dma_sync_single_for_cpu(pdev, + rx_ring->buffer_info[l].dma, 2048, + PCI_DMA_FROMDEVICE); + + ret_val = e1000_check_lbtest_frame( + rx_ring->buffer_info[l].skb, 1024); + if (!ret_val) + good_cnt++; + l++; + if (l == rx_ring->count) + l = 0; + /* + * time + 20 msecs (200 msecs on 2.4) is more than + * enough time to complete the receives, if it's + * exceeded, break and error off + */ + } while ((good_cnt < 64) && !time_after(jiffies, time + 20)); + if (good_cnt != 64) { + ret_val = 13; /* ret_val is the same as mis-compare */ + break; + } + if (jiffies >= (time + 20)) { + ret_val = 14; /* error code for time out error */ + break; + } + } /* end loop count loop */ + return ret_val; +} + +static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) +{ + struct e1000_hw *hw = &adapter->hw; + /* + * PHY loopback cannot be performed if SoL/IDER + * sessions are active + */ + if (hw->phy.ops.check_reset_block && + hw->phy.ops.check_reset_block(&adapter->hw)) { + e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); + *data = 0; + goto out; + } + + *data = e1000_setup_desc_rings(adapter); + if (*data) + goto out; + + *data = e1000_setup_loopback_test(adapter); + if (*data) + goto err_loopback; + + *data = e1000_run_loopback_test(adapter); + e1000_loopback_cleanup(adapter); + +err_loopback: + e1000_free_desc_rings(adapter); +out: + return *data; +} + +static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) +{ + struct e1000_hw *hw = &adapter->hw; + + *data = 0; + if (hw->phy.media_type == e1000_media_type_internal_serdes) { + int i = 0; + hw->mac.serdes_has_link = 0; + + /* + * On some blade server designs, link establishment + * could take as long as 2-3 minutes + */ + do { + hw->mac.ops.check_for_link(hw); + if (hw->mac.serdes_has_link) + return *data; + msleep(20); + } while (i++ < 3750); + + *data = 1; + } else { + hw->mac.ops.check_for_link(hw); + if (hw->mac.autoneg) + msleep(4000); + + if (!(er32(STATUS) & + E1000_STATUS_LU)) + *data = 1; + } + return *data; +} + +static int e1000_get_self_test_count(struct net_device *netdev) +{ + return E1000_TEST_LEN; +} + +static int e1000_get_stats_count(struct net_device *netdev) +{ + return E1000_STATS_LEN; +} + +static void e1000_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + u16 autoneg_advertised; + u8 forced_speed_duplex; + u8 autoneg; + bool if_running = netif_running(netdev); + + set_bit(__E1000_TESTING, &adapter->state); + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { + /* Offline tests */ + + /* save speed, duplex, autoneg settings */ + autoneg_advertised = adapter->hw.phy.autoneg_advertised; + forced_speed_duplex = adapter->hw.mac.forced_speed_duplex; + autoneg = adapter->hw.mac.autoneg; + + e_info("offline testing starting\n"); + + /* + * Link test performed before hardware reset so autoneg doesn't + * interfere with test result + */ + if (e1000_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + if (if_running) + /* indicate we're in test mode */ + dev_close(netdev); + else + e1000_reset(adapter); + + if (e1000_reg_test(adapter, &data[0])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + e1000_reset(adapter); + if (e1000_eeprom_test(adapter, &data[1])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + e1000_reset(adapter); + if (e1000_intr_test(adapter, &data[2])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + e1000_reset(adapter); + /* make sure the phy is powered up */ + e1000_power_up_phy(&adapter->hw); + if (e1000_loopback_test(adapter, &data[3])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + /* restore speed, duplex, autoneg settings */ + adapter->hw.phy.autoneg_advertised = autoneg_advertised; + adapter->hw.mac.forced_speed_duplex = forced_speed_duplex; + adapter->hw.mac.autoneg = autoneg; + + /* force this routine to wait until autoneg complete/timeout */ + adapter->hw.phy.autoneg_wait_to_complete = 1; + e1000_reset(adapter); + adapter->hw.phy.autoneg_wait_to_complete = 0; + + clear_bit(__E1000_TESTING, &adapter->state); + if (if_running) + dev_open(netdev); + } else { + e_info("online testing starting\n"); + /* Online tests */ + if (e1000_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + /* Online tests aren't run; pass by default */ + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0; + + clear_bit(__E1000_TESTING, &adapter->state); + } + msleep_interruptible(4 * 1000); +} + +static void e1000_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + wol->supported = 0; + wol->wolopts = 0; + + if (!(adapter->flags & FLAG_HAS_WOL)) + return; + + wol->supported = WAKE_UCAST | WAKE_MCAST | + WAKE_BCAST | WAKE_MAGIC | + WAKE_PHY | WAKE_ARP; + + /* apply any specific unsupported masks here */ + if (adapter->flags & FLAG_NO_WAKE_UCAST) { + wol->supported &= ~WAKE_UCAST; + + if (adapter->wol & E1000_WUFC_EX) + e_err("Interface does not support directed (unicast)" + " frame wake-up packets\n"); + } + + if (adapter->wol & E1000_WUFC_EX) + wol->wolopts |= WAKE_UCAST; + if (adapter->wol & E1000_WUFC_MC) + wol->wolopts |= WAKE_MCAST; + if (adapter->wol & E1000_WUFC_BC) + wol->wolopts |= WAKE_BCAST; + if (adapter->wol & E1000_WUFC_MAG) + wol->wolopts |= WAKE_MAGIC; + if (adapter->wol & E1000_WUFC_LNKC) + wol->wolopts |= WAKE_PHY; + if (adapter->wol & E1000_WUFC_ARP) + wol->wolopts |= WAKE_ARP; +} + +static int e1000_set_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & WAKE_MAGICSECURE) + return -EOPNOTSUPP; + + if (!(adapter->flags & FLAG_HAS_WOL)) + return wol->wolopts ? -EOPNOTSUPP : 0; + + /* these settings will always override what we currently have */ + adapter->wol = 0; + + if (wol->wolopts & WAKE_UCAST) + adapter->wol |= E1000_WUFC_EX; + if (wol->wolopts & WAKE_MCAST) + adapter->wol |= E1000_WUFC_MC; + if (wol->wolopts & WAKE_BCAST) + adapter->wol |= E1000_WUFC_BC; + if (wol->wolopts & WAKE_MAGIC) + adapter->wol |= E1000_WUFC_MAG; + if (wol->wolopts & WAKE_PHY) + adapter->wol |= E1000_WUFC_LNKC; + if (wol->wolopts & WAKE_ARP) + adapter->wol |= E1000_WUFC_ARP; + + return 0; +} + +/* toggle LED 4 times per second = 2 "blinks" per second */ +#define E1000_ID_INTERVAL (HZ/4) + +/* bit defines for adapter->led_status */ +#define E1000_LED_ON 0 + +static void e1000_led_blink_callback(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + + if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) + adapter->hw.mac.ops.led_off(&adapter->hw); + else + adapter->hw.mac.ops.led_on(&adapter->hw); + + mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); +} + +static int e1000_phys_id(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + if (!data) + data = INT_MAX; + + if ((hw->phy.type == e1000_phy_ife) || + (hw->mac.type == e1000_82574)) { + if (!adapter->blink_timer.function) { + init_timer(&adapter->blink_timer); + adapter->blink_timer.function = + e1000_led_blink_callback; + adapter->blink_timer.data = (unsigned long) adapter; + } + mod_timer(&adapter->blink_timer, jiffies); + msleep_interruptible(data * 1000); + del_timer_sync(&adapter->blink_timer); + if (hw->phy.type == e1000_phy_ife) + hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, + 0); + } else { + hw->mac.ops.blink_led(hw); + msleep_interruptible(data * 1000); + } + + hw->mac.ops.led_off(hw); + clear_bit(E1000_LED_ON, &adapter->led_status); + hw->mac.ops.cleanup_led(hw); + + return 0; +} + +static int e1000_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (adapter->itr_setting <= 3) + ec->rx_coalesce_usecs = adapter->itr_setting; + else + ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; + + ec->stats_block_coalesce_usecs = adapter->stats_freq_us; + + return 0; +} + +static int e1000_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || + ((ec->rx_coalesce_usecs > 3) && + (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || + (ec->rx_coalesce_usecs == 2) || + (ec->stats_block_coalesce_usecs > (10 * 1000000))) + return -EINVAL; + + adapter->stats_freq_us = ec->stats_block_coalesce_usecs; + + if (ec->rx_coalesce_usecs <= 3) { + adapter->itr = 20000; + adapter->itr_setting = ec->rx_coalesce_usecs; + } else { + adapter->itr = (1000000 / ec->rx_coalesce_usecs); + adapter->itr_setting = adapter->itr & ~3; + } + + if (adapter->itr_setting != 0) + ew32(ITR, 1000000000 / (adapter->itr * 256)); + else + ew32(ITR, 0); + + return 0; +} + +static int e1000_nway_reset(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + if (netif_running(netdev)) + e1000_reinit_locked(adapter); + return 0; +} + +static void e1000_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, + u64 *data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + int i; + + e1000_update_stats(adapter); + for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { + char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; + data[i] = (e1000_gstrings_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } +} + +static void e1000_get_strings(struct net_device *netdev, u32 stringset, + u8 *data) +{ + u8 *p = data; + int i; + + switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test)); + break; + case ETH_SS_STATS: + for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { + memcpy(p, e1000_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + break; + } +} + +static const struct ethtool_ops e1000_ethtool_ops = { + .get_settings = e1000_get_settings, + .set_settings = e1000_set_settings, + .get_drvinfo = e1000_get_drvinfo, + .get_regs_len = e1000_get_regs_len, + .get_regs = e1000_get_regs, + .get_wol = e1000_get_wol, + .set_wol = e1000_set_wol, + .get_msglevel = e1000_get_msglevel, + .set_msglevel = e1000_set_msglevel, + .nway_reset = e1000_nway_reset, + .get_link = e1000_get_link, + .get_eeprom_len = e1000_get_eeprom_len, + .get_eeprom = e1000_get_eeprom, + .set_eeprom = e1000_set_eeprom, + .get_ringparam = e1000_get_ringparam, + .set_ringparam = e1000_set_ringparam, + .get_pauseparam = e1000_get_pauseparam, + .set_pauseparam = e1000_set_pauseparam, + .get_rx_csum = e1000_get_rx_csum, + .set_rx_csum = e1000_set_rx_csum, + .get_tx_csum = e1000_get_tx_csum, + .set_tx_csum = e1000_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ethtool_op_get_tso, + .set_tso = e1000_set_tso, +#endif + .self_test = e1000_diag_test, + .get_strings = e1000_get_strings, + .phys_id = e1000_phys_id, + .get_ethtool_stats = e1000_get_ethtool_stats, + .self_test_count = e1000_get_self_test_count, + .get_stats_count = e1000_get_stats_count, + .get_coalesce = e1000_get_coalesce, + .set_coalesce = e1000_set_coalesce, +}; + +void e1000_set_ethtool_ops(struct net_device *netdev) +{ + /* have to "undeclare" const on this struct to remove warnings */ + SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&e1000_ethtool_ops); +} +#endif /* SIOCETHTOOL */ --- linux-2.6.27.orig/ubuntu/e1000e/e1000_osdep.h +++ linux-2.6.27/ubuntu/e1000e/e1000_osdep.h @@ -0,0 +1,116 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + + +/* glue for the OS-dependent part of e1000 + * includes register access macros + */ + +#ifndef _E1000_OSDEP_H_ +#define _E1000_OSDEP_H_ + +#include +#include +#include +#include + +#include "kcompat.h" + +#define usec_delay(x) udelay(x) +#ifndef msec_delay +#define msec_delay(x) do { if(in_interrupt()) { \ + /* Don't sleep in interrupt context! */ \ + BUG(); \ + } else { \ + msleep(x); \ + } } while (0) + +/* Some workarounds require millisecond delays and are run during interrupt + * context. Most notably, when establishing link, the phy may need tweaking + * but cannot process phy register reads/writes faster than millisecond + * intervals...and we establish link due to a "link status change" interrupt. + */ +#define msec_delay_irq(x) mdelay(x) +#endif + +#define PCI_COMMAND_REGISTER PCI_COMMAND +#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE +#define ETH_ADDR_LEN ETH_ALEN + + +#define DEBUGOUT(S) +#define DEBUGOUT1(S, A...) + +#define DEBUGFUNC(F) DEBUGOUT(F "\n") +#define DEBUGOUT2 DEBUGOUT1 +#define DEBUGOUT3 DEBUGOUT2 +#define DEBUGOUT7 DEBUGOUT3 + +#define E1000_WRITE_REG(a, reg, value) ( \ + writel((value), ((a)->hw_addr + reg))) + +#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + reg)) + +#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ + writel((value), ((a)->hw_addr + reg + ((offset) << 2)))) + +#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ + readl((a)->hw_addr + reg + ((offset) << 2))) + +#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY +#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY + +#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ + writew((value), ((a)->hw_addr + reg + ((offset) << 1)))) + +#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ + readw((a)->hw_addr + reg + ((offset) << 1))) + +#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ + writeb((value), ((a)->hw_addr + reg + (offset)))) + +#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ + readb((a)->hw_addr + reg + (offset))) + +#define E1000_WRITE_REG_IO(a, reg, offset) do { \ + outl(reg, ((a)->io_base)); \ + outl(offset, ((a)->io_base + 4)); } while(0) + +#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) + +#define E1000_WRITE_FLASH_REG(a, reg, value) ( \ + writel((value), ((a)->flash_address + reg))) + +#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \ + writew((value), ((a)->flash_address + reg))) + +#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg)) + +#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg)) + +#endif /* _E1000_OSDEP_H_ */ --- linux-2.6.27.orig/ubuntu/e1000e/e1000_phy.h +++ linux-2.6.27/ubuntu/e1000e/e1000_phy.h @@ -0,0 +1,190 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_PHY_H_ +#define _E1000_PHY_H_ + +typedef enum { + e1000_ms_hw_default = 0, + e1000_ms_force_master, + e1000_ms_force_slave, + e1000_ms_auto +} e1000_ms_type; + +typedef enum { + e1000_smart_speed_default = 0, + e1000_smart_speed_on, + e1000_smart_speed_off +} e1000_smart_speed; + +void e1000_init_phy_ops_generic(struct e1000_hw *hw); +s32 e1000_check_downshift_generic(struct e1000_hw *hw); +s32 e1000_check_polarity_m88(struct e1000_hw *hw); +s32 e1000_check_polarity_igp(struct e1000_hw *hw); +s32 e1000_check_reset_block_generic(struct e1000_hw *hw); +s32 e1000_copper_link_autoneg(struct e1000_hw *hw); +s32 e1000_copper_link_setup_igp(struct e1000_hw *hw); +s32 e1000_copper_link_setup_m88(struct e1000_hw *hw); +s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw); +s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw); +s32 e1000_get_cable_length_m88(struct e1000_hw *hw); +s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw); +s32 e1000_get_cfg_done_generic(struct e1000_hw *hw); +s32 e1000_get_phy_id(struct e1000_hw *hw); +s32 e1000_get_phy_info_igp(struct e1000_hw *hw); +s32 e1000_get_phy_info_m88(struct e1000_hw *hw); +s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw); +void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); +s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); +s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); +s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); +s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); +s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); +s32 e1000_wait_autoneg_generic(struct e1000_hw *hw); +s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_phy_reset_dsp(struct e1000_hw *hw); +s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, + u32 usec_interval, bool *success); +s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); +e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); +s32 e1000_determine_phy_address(struct e1000_hw* hw); +s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, + bool read); +s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); +void e1000_power_up_phy_copper(struct e1000_hw *hw); +void e1000_power_down_phy_copper(struct e1000_hw *hw); +s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); + +#define E1000_MAX_PHY_ADDR 4 + +/* IGP01E1000 Specific Registers */ +#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ +#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ +#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ +#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ +#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ +#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */ +#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ +#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ +#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ +#define IGP_PAGE_SHIFT 5 +#define PHY_REG_MASK 0x1F + +#define BM_WUC_PAGE 800 +#define BM_WUC_ADDRESS_OPCODE 0x11 +#define BM_WUC_DATA_OPCODE 0x12 +#define BM_WUC_ENABLE_PAGE 769 +#define BM_WUC_ENABLE_REG 17 +#define BM_WUC_ENABLE_BIT (1 << 2) +#define BM_WUC_HOST_WU_BIT (1 << 4) + +/* BM PHY Copper Specific Control 1 */ +#define BM_CS_CTRL1 16 +#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */ + +/* BM PHY Copper Specific States */ +#define BM_CS_STATUS 17 +#define BM_CS_STATUS_ENERGY_DETECT 0x0010 /* Energy Detect Status */ + +#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 +#define IGP01E1000_PHY_POLARITY_MASK 0x0078 + +#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 +#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ + +#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 + +/* Enable flexible speed on link-up */ +#define IGP01E1000_GMII_FLEX_SPD 0x0010 +#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ + +#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ +#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ +#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ + +#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 + +#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 +#define IGP01E1000_PSSR_MDIX 0x0008 +#define IGP01E1000_PSSR_SPEED_MASK 0xC000 +#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 + +#define IGP02E1000_PHY_CHANNEL_NUM 4 +#define IGP02E1000_PHY_AGC_A 0x11B1 +#define IGP02E1000_PHY_AGC_B 0x12B1 +#define IGP02E1000_PHY_AGC_C 0x14B1 +#define IGP02E1000_PHY_AGC_D 0x18B1 + +#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */ +#define IGP02E1000_AGC_LENGTH_MASK 0x7F +#define IGP02E1000_AGC_RANGE 15 + +#define IGP03E1000_PHY_MISC_CTRL 0x1B +#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ + +#define E1000_CABLE_LENGTH_UNDEFINED 0xFF + +#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 +#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 +#define E1000_KMRNCTRLSTA_REN 0x00200000 +#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ +#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ + +#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 +#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ +#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */ +#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ + +/* IFE PHY Extended Status Control */ +#define IFE_PESC_POLARITY_REVERSED 0x0100 + +/* IFE PHY Special Control */ +#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 +#define IFE_PSC_FORCE_POLARITY 0x0020 +#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 + +/* IFE PHY Special Control and LED Control */ +#define IFE_PSCL_PROBE_MODE 0x0020 +#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ +#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ + +/* IFE PHY MDIX Control */ +#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ +#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ +#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */ + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_nvm.c +++ linux-2.6.27/ubuntu/e1000e/e1000_nvm.c @@ -0,0 +1,875 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "e1000_hw.h" + +/** + * e1000_init_nvm_ops_generic - Initialize NVM function pointers + * @hw: pointer to the HW structure + * + * Setups up the function pointers to no-op functions + **/ +void e1000_init_nvm_ops_generic(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + DEBUGFUNC("e1000_init_nvm_ops_generic"); + + /* Initialize function pointers */ + nvm->ops.reload = e1000_reload_nvm_generic; +} + +/** + * e1000_raise_eec_clk - Raise EEPROM clock + * @hw: pointer to the HW structure + * @eecd: pointer to the EEPROM + * + * Enable/Raise the EEPROM clock bit. + **/ +static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) +{ + *eecd = *eecd | E1000_EECD_SK; + E1000_WRITE_REG(hw, E1000_EECD, *eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(hw->nvm.delay_usec); +} + +/** + * e1000_lower_eec_clk - Lower EEPROM clock + * @hw: pointer to the HW structure + * @eecd: pointer to the EEPROM + * + * Clear/Lower the EEPROM clock bit. + **/ +static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) +{ + *eecd = *eecd & ~E1000_EECD_SK; + E1000_WRITE_REG(hw, E1000_EECD, *eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(hw->nvm.delay_usec); +} + +/** + * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM + * @hw: pointer to the HW structure + * @data: data to send to the EEPROM + * @count: number of bits to shift out + * + * We need to shift 'count' bits out to the EEPROM. So, the value in the + * "data" parameter will be shifted out to the EEPROM one bit at a time. + * In order to do this, "data" must be broken down into bits. + **/ +static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = E1000_READ_REG(hw, E1000_EECD); + u32 mask; + + DEBUGFUNC("e1000_shift_out_eec_bits"); + + mask = 0x01 << (count - 1); + if (nvm->type == e1000_nvm_eeprom_microwire) + eecd &= ~E1000_EECD_DO; + else if (nvm->type == e1000_nvm_eeprom_spi) + eecd |= E1000_EECD_DO; + + do { + eecd &= ~E1000_EECD_DI; + + if (data & mask) + eecd |= E1000_EECD_DI; + + E1000_WRITE_REG(hw, E1000_EECD, eecd); + E1000_WRITE_FLUSH(hw); + + usec_delay(nvm->delay_usec); + + e1000_raise_eec_clk(hw, &eecd); + e1000_lower_eec_clk(hw, &eecd); + + mask >>= 1; + } while (mask); + + eecd &= ~E1000_EECD_DI; + E1000_WRITE_REG(hw, E1000_EECD, eecd); +} + +/** + * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM + * @hw: pointer to the HW structure + * @count: number of bits to shift in + * + * In order to read a register from the EEPROM, we need to shift 'count' bits + * in from the EEPROM. Bits are "shifted in" by raising the clock input to + * the EEPROM (setting the SK bit), and then reading the value of the data out + * "DO" bit. During this "shifting in" process the data in "DI" bit should + * always be clear. + **/ +static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) +{ + u32 eecd; + u32 i; + u16 data; + + DEBUGFUNC("e1000_shift_in_eec_bits"); + + eecd = E1000_READ_REG(hw, E1000_EECD); + + eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); + data = 0; + + for (i = 0; i < count; i++) { + data <<= 1; + e1000_raise_eec_clk(hw, &eecd); + + eecd = E1000_READ_REG(hw, E1000_EECD); + + eecd &= ~E1000_EECD_DI; + if (eecd & E1000_EECD_DO) + data |= 1; + + e1000_lower_eec_clk(hw, &eecd); + } + + return data; +} + +/** + * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion + * @hw: pointer to the HW structure + * @ee_reg: EEPROM flag for polling + * + * Polls the EEPROM status bit for either read or write completion based + * upon the value of 'ee_reg'. + **/ +s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) +{ + u32 attempts = 100000; + u32 i, reg = 0; + s32 ret_val = -E1000_ERR_NVM; + + DEBUGFUNC("e1000_poll_eerd_eewr_done"); + + for (i = 0; i < attempts; i++) { + if (ee_reg == E1000_NVM_POLL_READ) + reg = E1000_READ_REG(hw, E1000_EERD); + else + reg = E1000_READ_REG(hw, E1000_EEWR); + + if (reg & E1000_NVM_RW_REG_DONE) { + ret_val = E1000_SUCCESS; + break; + } + + usec_delay(5); + } + + return ret_val; +} + +/** + * e1000_acquire_nvm_generic - Generic request for access to EEPROM + * @hw: pointer to the HW structure + * + * Set the EEPROM access request bit and wait for EEPROM access grant bit. + * Return successful if access grant bit set, else clear the request for + * EEPROM access and return -E1000_ERR_NVM (-1). + **/ +s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) +{ + u32 eecd = E1000_READ_REG(hw, E1000_EECD); + s32 timeout = E1000_NVM_GRANT_ATTEMPTS; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_acquire_nvm_generic"); + + E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); + eecd = E1000_READ_REG(hw, E1000_EECD); + + while (timeout) { + if (eecd & E1000_EECD_GNT) + break; + usec_delay(5); + eecd = E1000_READ_REG(hw, E1000_EECD); + timeout--; + } + + if (!timeout) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, E1000_EECD, eecd); + DEBUGOUT("Could not acquire NVM grant\n"); + ret_val = -E1000_ERR_NVM; + } + + return ret_val; +} + +/** + * e1000_standby_nvm - Return EEPROM to standby state + * @hw: pointer to the HW structure + * + * Return the EEPROM to a standby state. + **/ +static void e1000_standby_nvm(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = E1000_READ_REG(hw, E1000_EECD); + + DEBUGFUNC("e1000_standby_nvm"); + + if (nvm->type == e1000_nvm_eeprom_microwire) { + eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); + E1000_WRITE_REG(hw, E1000_EECD, eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(nvm->delay_usec); + + e1000_raise_eec_clk(hw, &eecd); + + /* Select EEPROM */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, E1000_EECD, eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(nvm->delay_usec); + + e1000_lower_eec_clk(hw, &eecd); + } else if (nvm->type == e1000_nvm_eeprom_spi) { + /* Toggle CS to flush commands */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, E1000_EECD, eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(nvm->delay_usec); + eecd &= ~E1000_EECD_CS; + E1000_WRITE_REG(hw, E1000_EECD, eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(nvm->delay_usec); + } +} + +/** + * e1000_stop_nvm - Terminate EEPROM command + * @hw: pointer to the HW structure + * + * Terminates the current command by inverting the EEPROM's chip select pin. + **/ +void e1000_stop_nvm(struct e1000_hw *hw) +{ + u32 eecd; + + DEBUGFUNC("e1000_stop_nvm"); + + eecd = E1000_READ_REG(hw, E1000_EECD); + if (hw->nvm.type == e1000_nvm_eeprom_spi) { + /* Pull CS high */ + eecd |= E1000_EECD_CS; + e1000_lower_eec_clk(hw, &eecd); + } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) { + /* CS on Microwire is active-high */ + eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); + E1000_WRITE_REG(hw, E1000_EECD, eecd); + e1000_raise_eec_clk(hw, &eecd); + e1000_lower_eec_clk(hw, &eecd); + } +} + +/** + * e1000_release_nvm_generic - Release exclusive access to EEPROM + * @hw: pointer to the HW structure + * + * Stop any current commands to the EEPROM and clear the EEPROM request bit. + **/ +void e1000_release_nvm_generic(struct e1000_hw *hw) +{ + u32 eecd; + + DEBUGFUNC("e1000_release_nvm_generic"); + + e1000_stop_nvm(hw); + + eecd = E1000_READ_REG(hw, E1000_EECD); + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, E1000_EECD, eecd); +} + +/** + * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write + * @hw: pointer to the HW structure + * + * Setups the EEPROM for reading and writing. + **/ +static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = E1000_READ_REG(hw, E1000_EECD); + s32 ret_val = E1000_SUCCESS; + u16 timeout = 0; + u8 spi_stat_reg; + + DEBUGFUNC("e1000_ready_nvm_eeprom"); + + if (nvm->type == e1000_nvm_eeprom_microwire) { + /* Clear SK and DI */ + eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); + E1000_WRITE_REG(hw, E1000_EECD, eecd); + /* Set CS */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, E1000_EECD, eecd); + } else if (nvm->type == e1000_nvm_eeprom_spi) { + /* Clear SK and CS */ + eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); + E1000_WRITE_REG(hw, E1000_EECD, eecd); + usec_delay(1); + timeout = NVM_MAX_RETRY_SPI; + + /* + * Read "Status Register" repeatedly until the LSB is cleared. + * The EEPROM will signal that the command has been completed + * by clearing bit 0 of the internal status register. If it's + * not cleared within 'timeout', then error out. + */ + while (timeout) { + e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, + hw->nvm.opcode_bits); + spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); + if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) + break; + + usec_delay(5); + e1000_standby_nvm(hw); + timeout--; + } + + if (!timeout) { + DEBUGOUT("SPI NVM Status error\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + } + +out: + return ret_val; +} + +/** + * e1000_read_nvm_spi - Read EEPROM's using SPI + * @hw: pointer to the HW structure + * @offset: offset of word in the EEPROM to read + * @words: number of words to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM. + **/ +s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 i = 0; + s32 ret_val; + u16 word_in; + u8 read_opcode = NVM_READ_OPCODE_SPI; + + DEBUGFUNC("e1000_read_nvm_spi"); + + /* + * A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + ret_val = e1000_ready_nvm_eeprom(hw); + if (ret_val) + goto release; + + e1000_standby_nvm(hw); + + if ((nvm->address_bits == 8) && (offset >= 128)) + read_opcode |= NVM_A8_OPCODE_SPI; + + /* Send the READ command (opcode + addr) */ + e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); + e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); + + /* + * Read the data. SPI NVMs increment the address with each byte + * read and will roll over if reading beyond the end. This allows + * us to read the whole NVM from any offset + */ + for (i = 0; i < words; i++) { + word_in = e1000_shift_in_eec_bits(hw, 16); + data[i] = (word_in >> 8) | (word_in << 8); + } + +release: + nvm->ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_read_nvm_microwire - Reads EEPROM's using microwire + * @hw: pointer to the HW structure + * @offset: offset of word in the EEPROM to read + * @words: number of words to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM. + **/ +s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 i = 0; + s32 ret_val; + u8 read_opcode = NVM_READ_OPCODE_MICROWIRE; + + DEBUGFUNC("e1000_read_nvm_microwire"); + + /* + * A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + ret_val = e1000_ready_nvm_eeprom(hw); + if (ret_val) + goto release; + + for (i = 0; i < words; i++) { + /* Send the READ command (opcode + addr) */ + e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); + e1000_shift_out_eec_bits(hw, (u16)(offset + i), + nvm->address_bits); + + /* + * Read the data. For microwire, each word requires the + * overhead of setup and tear-down. + */ + data[i] = e1000_shift_in_eec_bits(hw, 16); + e1000_standby_nvm(hw); + } + +release: + nvm->ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_read_nvm_eerd - Reads EEPROM using EERD register + * @hw: pointer to the HW structure + * @offset: offset of word in the EEPROM to read + * @words: number of words to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM using the EERD register. + **/ +s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 i, eerd = 0; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_nvm_eerd"); + + /* + * A check for invalid values: offset too large, too many words, + * too many words for the offset, and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + for (i = 0; i < words; i++) { + eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + + E1000_NVM_RW_REG_START; + + E1000_WRITE_REG(hw, E1000_EERD, eerd); + ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); + if (ret_val) + break; + + data[i] = (E1000_READ_REG(hw, E1000_EERD) >> + E1000_NVM_RW_REG_DATA); + } + +out: + return ret_val; +} + +/** + * e1000_write_nvm_spi - Write to EEPROM using SPI + * @hw: pointer to the HW structure + * @offset: offset within the EEPROM to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the EEPROM + * + * Writes data to EEPROM at offset using SPI interface. + * + * If e1000_update_nvm_checksum is not called after this function , the + * EEPROM will most likely contain an invalid checksum. + **/ +s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + s32 ret_val; + u16 widx = 0; + + DEBUGFUNC("e1000_write_nvm_spi"); + + /* + * A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + while (widx < words) { + u8 write_opcode = NVM_WRITE_OPCODE_SPI; + + ret_val = e1000_ready_nvm_eeprom(hw); + if (ret_val) + goto release; + + e1000_standby_nvm(hw); + + /* Send the WRITE ENABLE command (8 bit opcode) */ + e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, + nvm->opcode_bits); + + e1000_standby_nvm(hw); + + /* + * Some SPI eeproms use the 8th address bit embedded in the + * opcode + */ + if ((nvm->address_bits == 8) && (offset >= 128)) + write_opcode |= NVM_A8_OPCODE_SPI; + + /* Send the Write command (8-bit opcode + addr) */ + e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); + e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), + nvm->address_bits); + + /* Loop to allow for up to whole page write of eeprom */ + while (widx < words) { + u16 word_out = data[widx]; + word_out = (word_out >> 8) | (word_out << 8); + e1000_shift_out_eec_bits(hw, word_out, 16); + widx++; + + if ((((offset + widx) * 2) % nvm->page_size) == 0) { + e1000_standby_nvm(hw); + break; + } + } + } + + msec_delay(nvm->semaphore_delay); +release: + nvm->ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_write_nvm_microwire - Writes EEPROM using microwire + * @hw: pointer to the HW structure + * @offset: offset within the EEPROM to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the EEPROM + * + * Writes data to EEPROM at offset using microwire interface. + * + * If e1000_update_nvm_checksum is not called after this function , the + * EEPROM will most likely contain an invalid checksum. + **/ +s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + s32 ret_val; + u32 eecd; + u16 words_written = 0; + u16 widx = 0; + + DEBUGFUNC("e1000_write_nvm_microwire"); + + /* + * A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + ret_val = e1000_ready_nvm_eeprom(hw); + if (ret_val) + goto release; + + e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE, + (u16)(nvm->opcode_bits + 2)); + + e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); + + e1000_standby_nvm(hw); + + while (words_written < words) { + e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE, + nvm->opcode_bits); + + e1000_shift_out_eec_bits(hw, (u16)(offset + words_written), + nvm->address_bits); + + e1000_shift_out_eec_bits(hw, data[words_written], 16); + + e1000_standby_nvm(hw); + + for (widx = 0; widx < 200; widx++) { + eecd = E1000_READ_REG(hw, E1000_EECD); + if (eecd & E1000_EECD_DO) + break; + usec_delay(50); + } + + if (widx == 200) { + DEBUGOUT("NVM Write did not complete\n"); + ret_val = -E1000_ERR_NVM; + goto release; + } + + e1000_standby_nvm(hw); + + words_written++; + } + + e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE, + (u16)(nvm->opcode_bits + 2)); + + e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); + +release: + nvm->ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_read_pba_num_generic - Read device part number + * @hw: pointer to the HW structure + * @pba_num: pointer to device part number + * + * Reads the product board assembly (PBA) number from the EEPROM and stores + * the value in pba_num. + **/ +s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) +{ + s32 ret_val; + u16 nvm_data; + + DEBUGFUNC("e1000_read_pba_num_generic"); + + ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + *pba_num = (u32)(nvm_data << 16); + + ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + *pba_num |= nvm_data; + +out: + return ret_val; +} + +/** + * e1000_read_mac_addr_generic - Read device MAC address + * @hw: pointer to the HW structure + * + * Reads the device MAC address from the EEPROM and stores the value. + * Since devices with two ports use the same EEPROM, we increment the + * last bit in the MAC address for the second port. + **/ +s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 offset, nvm_data, i; + + DEBUGFUNC("e1000_read_mac_addr"); + + for (i = 0; i < ETH_ADDR_LEN; i += 2) { + offset = i >> 1; + ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); + hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); + } + + /* Flip last bit of mac address if we're on second port */ + if (hw->bus.func == E1000_FUNC_1) + hw->mac.perm_addr[5] ^= 1; + + for (i = 0; i < ETH_ADDR_LEN; i++) + hw->mac.addr[i] = hw->mac.perm_addr[i]; + +out: + return ret_val; +} + +/** + * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Calculates the EEPROM checksum by reading/adding each word of the EEPROM + * and then verifies that the sum of the EEPROM is equal to 0xBABA. + **/ +s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 checksum = 0; + u16 i, nvm_data; + + DEBUGFUNC("e1000_validate_nvm_checksum_generic"); + + for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + checksum += nvm_data; + } + + if (checksum != (u16) NVM_SUM) { + DEBUGOUT("NVM Checksum Invalid\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_update_nvm_checksum_generic - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM checksum by reading/adding each word of the EEPROM + * up to the checksum. Then calculates the EEPROM checksum and writes the + * value to the EEPROM. + **/ +s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) +{ + s32 ret_val; + u16 checksum = 0; + u16 i, nvm_data; + + DEBUGFUNC("e1000_update_nvm_checksum"); + + for (i = 0; i < NVM_CHECKSUM_REG; i++) { + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { + DEBUGOUT("NVM Read Error while updating checksum.\n"); + goto out; + } + checksum += nvm_data; + } + checksum = (u16) NVM_SUM - checksum; + ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); + if (ret_val) { + DEBUGOUT("NVM Write Error while updating checksum.\n"); + } + +out: + return ret_val; +} + +/** + * e1000_reload_nvm_generic - Reloads EEPROM + * @hw: pointer to the HW structure + * + * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the + * extended control register. + **/ +void e1000_reload_nvm_generic(struct e1000_hw *hw) +{ + u32 ctrl_ext; + + DEBUGFUNC("e1000_reload_nvm_generic"); + + usec_delay(10); + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); +} + --- linux-2.6.27.orig/ubuntu/e1000e/e1000_ich8lan.h +++ linux-2.6.27/ubuntu/e1000e/e1000_ich8lan.h @@ -0,0 +1,128 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_ICH8LAN_H_ +#define _E1000_ICH8LAN_H_ + +#define ICH_FLASH_GFPREG 0x0000 +#define ICH_FLASH_HSFSTS 0x0004 +#define ICH_FLASH_HSFCTL 0x0006 +#define ICH_FLASH_FADDR 0x0008 +#define ICH_FLASH_FDATA0 0x0010 + +#define ICH_FLASH_READ_COMMAND_TIMEOUT 500 +#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500 +#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 3000000 +#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF +#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 + +#define ICH_CYCLE_READ 0 +#define ICH_CYCLE_WRITE 2 +#define ICH_CYCLE_ERASE 3 + +#define FLASH_GFPREG_BASE_MASK 0x1FFF +#define FLASH_SECTOR_ADDR_SHIFT 12 + +#define E1000_SHADOW_RAM_WORDS 2048 + +#define ICH_FLASH_SEG_SIZE_256 256 +#define ICH_FLASH_SEG_SIZE_4K 4096 +#define ICH_FLASH_SEG_SIZE_8K 8192 +#define ICH_FLASH_SEG_SIZE_64K 65536 +#define ICH_FLASH_SECTOR_SIZE 4096 + +#define ICH_FLASH_REG_MAPSIZE 0x00A0 + +#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ +#define E1000_ICH_FWSM_DISSW 0x10000000 /* FW Disables SW Writes */ +/* FW established a valid mode */ +#define E1000_ICH_FWSM_FW_VALID 0x00008000 + +#define E1000_ICH_MNG_IAMT_MODE 0x2 + +#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ + (ID_LED_DEF1_OFF2 << 8) | \ + (ID_LED_DEF1_ON2 << 4) | \ + (ID_LED_DEF1_DEF2)) + +#define E1000_ICH_NVM_SIG_WORD 0x13 +#define E1000_ICH_NVM_SIG_MASK 0xC000 + +#define E1000_ICH8_LAN_INIT_TIMEOUT 1500 + +#define E1000_FEXTNVM_SW_CONFIG 1 +#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */ + +#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL + +#define E1000_ICH_RAR_ENTRIES 7 + +#define PHY_PAGE_SHIFT 5 +#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ + ((reg) & MAX_PHY_REG_ADDRESS)) +#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ +#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ +#define IGP3_CAPABILITY PHY_REG(776, 19) /* Capability */ +#define IGP3_PM_CTRL PHY_REG(769, 20) /* Power Management Control */ + +#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 +#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 +#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 +#define IGP3_PM_CTRL_FORCE_PWR_DOWN 0x0020 + +/* + * Additional interrupts need to be handled for ICH family: + * DSW = The FW changed the status of the DISSW bit in FWSM + * PHYINT = The LAN connected device generates an interrupt + * EPRST = Manageability reset event + */ +#define IMS_ICH_ENABLE_MASK (\ + E1000_IMS_DSW | \ + E1000_IMS_PHYINT | \ + E1000_IMS_EPRST) + +/* Additional interrupt register bit definitions */ +#define E1000_ICR_LSECPNC 0x00004000 /* PN threshold - client */ +#define E1000_IMS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */ +#define E1000_ICS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */ + +/* Security Processing bit Indication */ +#define E1000_RXDEXT_LINKSEC_STATUS_LSECH 0x01000000 +#define E1000_RXDEXT_LINKSEC_ERROR_BIT_MASK 0x60000000 +#define E1000_RXDEXT_LINKSEC_ERROR_NO_SA_MATCH 0x20000000 +#define E1000_RXDEXT_LINKSEC_ERROR_REPLAY_ERROR 0x40000000 +#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG 0x60000000 + + +void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, + bool state); +void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); +void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); +void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw); + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_manage.h +++ linux-2.6.27/ubuntu/e1000e/e1000_manage.h @@ -0,0 +1,82 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_MANAGE_H_ +#define _E1000_MANAGE_H_ + +bool e1000_check_mng_mode_generic(struct e1000_hw *hw); +bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw); +s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw); +s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, + u16 length, u16 offset, u8 *sum); +s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, + struct e1000_host_mng_command_header *hdr); +s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, + u8 *buffer, u16 length); +bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); + +typedef enum { + e1000_mng_mode_none = 0, + e1000_mng_mode_asf, + e1000_mng_mode_pt, + e1000_mng_mode_ipmi, + e1000_mng_mode_host_if_only +} e1000_mng_mode; + +#define E1000_FACTPS_MNGCG 0x20000000 + +#define E1000_FWSM_MODE_MASK 0xE +#define E1000_FWSM_MODE_SHIFT 1 + +#define E1000_MNG_IAMT_MODE 0x3 +#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 +#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 +#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 +#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 +#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 +#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 + +#define E1000_VFTA_ENTRY_SHIFT 5 +#define E1000_VFTA_ENTRY_MASK 0x7F +#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F + +#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ +#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ +#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */ + +#define E1000_HICR_EN 0x01 /* Enable bit - RO */ +/* Driver sets this bit when done to put command in RAM */ +#define E1000_HICR_C 0x02 +#define E1000_HICR_SV 0x04 /* Status Validity */ +#define E1000_HICR_FW_RESET_ENABLE 0x40 +#define E1000_HICR_FW_RESET 0x80 + +/* Intel(R) Active Management Technology signature */ +#define E1000_IAMT_SIGNATURE 0x544D4149 + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_mac.c +++ linux-2.6.27/ubuntu/e1000e/e1000_mac.c @@ -0,0 +1,1968 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "e1000_hw.h" + +/** + * e1000_init_mac_ops_generic - Initialize MAC function pointers + * @hw: pointer to the HW structure + * + * Setups up the function pointers to no-op functions + **/ +void e1000_init_mac_ops_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + DEBUGFUNC("e1000_init_mac_ops_generic"); + + /* General Setup */ + mac->ops.read_mac_addr = e1000_read_mac_addr_generic; + mac->ops.remove_device = e1000_remove_device_generic; + mac->ops.config_collision_dist = e1000_config_collision_dist_generic; + /* LINK */ + mac->ops.wait_autoneg = e1000_wait_autoneg_generic; + /* Management */ + mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic; + mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic; + mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic; + /* VLAN, MC, etc. */ + mac->ops.rar_set = e1000_rar_set_generic; + mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic; +} + +/** + * e1000_remove_device_generic - Free device specific structure + * @hw: pointer to the HW structure + * + * If a device specific structure was allocated, this function will + * free it. + **/ +void e1000_remove_device_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_remove_device_generic"); + + /* Freeing the dev_spec member of e1000_hw structure */ + e1000_free_dev_spec_struct(hw); +} + +/** + * e1000_get_bus_info_pcie_generic - Get PCIe bus information + * @hw: pointer to the HW structure + * + * Determines and stores the system bus information for a particular + * network interface. The following bus information is determined and stored: + * bus speed, bus width, type (PCIe), and PCIe function. + **/ +s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + s32 ret_val; + u32 status; + u16 pcie_link_status, pci_header_type; + + DEBUGFUNC("e1000_get_bus_info_pcie_generic"); + + bus->type = e1000_bus_type_pci_express; + bus->speed = e1000_bus_speed_2500; + + ret_val = e1000_read_pcie_cap_reg(hw, + PCIE_LINK_STATUS, + &pcie_link_status); + if (ret_val) + bus->width = e1000_bus_width_unknown; + else + bus->width = (e1000_bus_width)((pcie_link_status & + PCIE_LINK_WIDTH_MASK) >> + PCIE_LINK_WIDTH_SHIFT); + + e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); + if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) { + status = E1000_READ_REG(hw, E1000_STATUS); + bus->func = (status & E1000_STATUS_FUNC_MASK) + >> E1000_STATUS_FUNC_SHIFT; + } else { + bus->func = 0; + } + + return E1000_SUCCESS; +} + +/** + * e1000_clear_vfta_generic - Clear VLAN filter table + * @hw: pointer to the HW structure + * + * Clears the register array which contains the VLAN filter table by + * setting all the values to 0. + **/ +void e1000_clear_vfta_generic(struct e1000_hw *hw) +{ + u32 offset; + + DEBUGFUNC("e1000_clear_vfta_generic"); + + for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { + E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); + E1000_WRITE_FLUSH(hw); + } +} + +/** + * e1000_write_vfta_generic - Write value to VLAN filter table + * @hw: pointer to the HW structure + * @offset: register offset in VLAN filter table + * @value: register value written to VLAN filter table + * + * Writes value at the given offset in the register array which stores + * the VLAN filter table. + **/ +void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) +{ + DEBUGFUNC("e1000_write_vfta_generic"); + + E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); + E1000_WRITE_FLUSH(hw); +} + +/** + * e1000_init_rx_addrs_generic - Initialize receive address's + * @hw: pointer to the HW structure + * @rar_count: receive address registers + * + * Setups the receive address registers by setting the base receive address + * register to the devices MAC address and clearing all the other receive + * address registers to 0. + **/ +void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) +{ + u32 i; + + DEBUGFUNC("e1000_init_rx_addrs_generic"); + + /* Setup the receive address */ + DEBUGOUT("Programming MAC Address into RAR[0]\n"); + + hw->mac.ops.rar_set(hw, hw->mac.addr, 0); + + /* Zero out the other (rar_entry_count - 1) receive addresses */ + DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); + for (i = 1; i < rar_count; i++) { + E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1), 0); + E1000_WRITE_FLUSH(hw); + E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((i << 1) + 1), 0); + E1000_WRITE_FLUSH(hw); + } +} + +/** + * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr + * @hw: pointer to the HW structure + * + * Checks the nvm for an alternate MAC address. An alternate MAC address + * can be setup by pre-boot software and must be treated like a permanent + * address and must override the actual permanent MAC address. If an + * alternate MAC address is found it is saved in the hw struct and + * programmed into RAR0 and the function returns success, otherwise the + * function returns an error. + **/ +s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) +{ + u32 i; + s32 ret_val = E1000_SUCCESS; + u16 offset, nvm_alt_mac_addr_offset, nvm_data; + u8 alt_mac_addr[ETH_ADDR_LEN]; + + DEBUGFUNC("e1000_check_alt_mac_addr_generic"); + + ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, + &nvm_alt_mac_addr_offset); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + + if (nvm_alt_mac_addr_offset == 0xFFFF) { + ret_val = -(E1000_NOT_IMPLEMENTED); + goto out; + } + + if (hw->bus.func == E1000_FUNC_1) + nvm_alt_mac_addr_offset += ETH_ADDR_LEN/sizeof(u16); + + for (i = 0; i < ETH_ADDR_LEN; i += 2) { + offset = nvm_alt_mac_addr_offset + (i >> 1); + ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + + alt_mac_addr[i] = (u8)(nvm_data & 0xFF); + alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); + } + + /* if multicast bit is set, the alternate address will not be used */ + if (alt_mac_addr[0] & 0x01) { + ret_val = -(E1000_NOT_IMPLEMENTED); + goto out; + } + + for (i = 0; i < ETH_ADDR_LEN; i++) + hw->mac.addr[i] = hw->mac.perm_addr[i] = alt_mac_addr[i]; + + hw->mac.ops.rar_set(hw, hw->mac.perm_addr, 0); + +out: + return ret_val; +} + +/** + * e1000_rar_set_generic - Set receive address register + * @hw: pointer to the HW structure + * @addr: pointer to the receive address + * @index: receive address array register + * + * Sets the receive address array register at index to the address passed + * in by addr. + **/ +void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) +{ + u32 rar_low, rar_high; + + DEBUGFUNC("e1000_rar_set_generic"); + + /* + * HW expects these in little endian so we reverse the byte order + * from network order (big endian) to little endian + */ + rar_low = ((u32) addr[0] | + ((u32) addr[1] << 8) | + ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); + + rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); + + /* If MAC address zero, no need to set the AV bit */ + if (rar_low || rar_high) { + if (!hw->mac.disable_av) + rar_high |= E1000_RAH_AV; + } + + E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); + E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); +} + +/** + * e1000_mta_set_generic - Set multicast filter table address + * @hw: pointer to the HW structure + * @hash_value: determines the MTA register and bit to set + * + * The multicast table address is a register array of 32-bit registers. + * The hash_value is used to determine what register the bit is in, the + * current value is read, the new bit is OR'd in and the new value is + * written back into the register. + **/ +void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value) +{ + u32 hash_bit, hash_reg, mta; + + DEBUGFUNC("e1000_mta_set_generic"); + /* + * The MTA is a register array of 32-bit registers. It is + * treated like an array of (32*mta_reg_count) bits. We want to + * set bit BitArray[hash_value]. So we figure out what register + * the bit is in, read it, OR in the new bit, then write + * back the new value. The (hw->mac.mta_reg_count - 1) serves as a + * mask to bits 31:5 of the hash value which gives us the + * register we're modifying. The hash bit within that register + * is determined by the lower 5 bits of the hash value. + */ + hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); + hash_bit = hash_value & 0x1F; + + mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg); + + mta |= (1 << hash_bit); + + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); + E1000_WRITE_FLUSH(hw); +} + +/** + * e1000_update_mc_addr_list_generic - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * @rar_used_count: the first RAR register free to program + * @rar_count: total number of supported Receive Address Registers + * + * Updates the Receive Address Registers and Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. + * The parameter rar_count will usually be hw->mac.rar_entry_count + * unless there are workarounds that change this. + **/ +void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count, + u32 rar_used_count, u32 rar_count) +{ + u32 hash_value; + u32 i; + + DEBUGFUNC("e1000_update_mc_addr_list_generic"); + + /* + * Load the first set of multicast addresses into the exact + * filters (RAR). If there are not enough to fill the RAR + * array, clear the filters. + */ + for (i = rar_used_count; i < rar_count; i++) { + if (mc_addr_count) { + hw->mac.ops.rar_set(hw, mc_addr_list, i); + mc_addr_count--; + mc_addr_list += ETH_ADDR_LEN; + } else { + E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0); + E1000_WRITE_FLUSH(hw); + E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0); + E1000_WRITE_FLUSH(hw); + } + } + + /* Clear the old settings from the MTA */ + DEBUGOUT("Clearing MTA\n"); + for (i = 0; i < hw->mac.mta_reg_count; i++) { + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + E1000_WRITE_FLUSH(hw); + } + + /* Load any remaining multicast addresses into the hash table. */ + for (; mc_addr_count > 0; mc_addr_count--) { + hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list); + DEBUGOUT1("Hash value = 0x%03X\n", hash_value); + hw->mac.ops.mta_set(hw, hash_value); + mc_addr_list += ETH_ADDR_LEN; + } +} + +/** + * e1000_hash_mc_addr_generic - Generate a multicast hash value + * @hw: pointer to the HW structure + * @mc_addr: pointer to a multicast address + * + * Generates a multicast address hash value which is used to determine + * the multicast filter table array address and new table value. See + * e1000_mta_set_generic() + **/ +u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) +{ + u32 hash_value, hash_mask; + u8 bit_shift = 0; + + DEBUGFUNC("e1000_hash_mc_addr_generic"); + + /* Register count multiplied by bits per register */ + hash_mask = (hw->mac.mta_reg_count * 32) - 1; + + /* + * For a mc_filter_type of 0, bit_shift is the number of left-shifts + * where 0xFF would still fall within the hash mask. + */ + while (hash_mask >> bit_shift != 0xFF) + bit_shift++; + + /* + * The portion of the address that is used for the hash table + * is determined by the mc_filter_type setting. + * The algorithm is such that there is a total of 8 bits of shifting. + * The bit_shift for a mc_filter_type of 0 represents the number of + * left-shifts where the MSB of mc_addr[5] would still fall within + * the hash_mask. Case 0 does this exactly. Since there are a total + * of 8 bits of shifting, then mc_addr[4] will shift right the + * remaining number of bits. Thus 8 - bit_shift. The rest of the + * cases are a variation of this algorithm...essentially raising the + * number of bits to shift mc_addr[5] left, while still keeping the + * 8-bit shifting total. + * + * For example, given the following Destination MAC Address and an + * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), + * we can see that the bit_shift for case 0 is 4. These are the hash + * values resulting from each mc_filter_type... + * [0] [1] [2] [3] [4] [5] + * 01 AA 00 12 34 56 + * LSB MSB + * + * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 + * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 + * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 + * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 + */ + switch (hw->mac.mc_filter_type) { + default: + case 0: + break; + case 1: + bit_shift += 1; + break; + case 2: + bit_shift += 2; + break; + case 3: + bit_shift += 4; + break; + } + + hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | + (((u16) mc_addr[5]) << bit_shift))); + + return hash_value; +} + +/** + * e1000_clear_hw_cntrs_base_generic - Clear base hardware counters + * @hw: pointer to the HW structure + * + * Clears the base hardware counters by reading the counter registers. + **/ +void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw) +{ + volatile u32 temp; + + DEBUGFUNC("e1000_clear_hw_cntrs_base_generic"); + + temp = E1000_READ_REG(hw, E1000_CRCERRS); + temp = E1000_READ_REG(hw, E1000_SYMERRS); + temp = E1000_READ_REG(hw, E1000_MPC); + temp = E1000_READ_REG(hw, E1000_SCC); + temp = E1000_READ_REG(hw, E1000_ECOL); + temp = E1000_READ_REG(hw, E1000_MCC); + temp = E1000_READ_REG(hw, E1000_LATECOL); + temp = E1000_READ_REG(hw, E1000_COLC); + temp = E1000_READ_REG(hw, E1000_DC); + temp = E1000_READ_REG(hw, E1000_SEC); + temp = E1000_READ_REG(hw, E1000_RLEC); + temp = E1000_READ_REG(hw, E1000_XONRXC); + temp = E1000_READ_REG(hw, E1000_XONTXC); + temp = E1000_READ_REG(hw, E1000_XOFFRXC); + temp = E1000_READ_REG(hw, E1000_XOFFTXC); + temp = E1000_READ_REG(hw, E1000_FCRUC); + temp = E1000_READ_REG(hw, E1000_GPRC); + temp = E1000_READ_REG(hw, E1000_BPRC); + temp = E1000_READ_REG(hw, E1000_MPRC); + temp = E1000_READ_REG(hw, E1000_GPTC); + temp = E1000_READ_REG(hw, E1000_GORCL); + temp = E1000_READ_REG(hw, E1000_GORCH); + temp = E1000_READ_REG(hw, E1000_GOTCL); + temp = E1000_READ_REG(hw, E1000_GOTCH); + temp = E1000_READ_REG(hw, E1000_RNBC); + temp = E1000_READ_REG(hw, E1000_RUC); + temp = E1000_READ_REG(hw, E1000_RFC); + temp = E1000_READ_REG(hw, E1000_ROC); + temp = E1000_READ_REG(hw, E1000_RJC); + temp = E1000_READ_REG(hw, E1000_TORL); + temp = E1000_READ_REG(hw, E1000_TORH); + temp = E1000_READ_REG(hw, E1000_TOTL); + temp = E1000_READ_REG(hw, E1000_TOTH); + temp = E1000_READ_REG(hw, E1000_TPR); + temp = E1000_READ_REG(hw, E1000_TPT); + temp = E1000_READ_REG(hw, E1000_MPTC); + temp = E1000_READ_REG(hw, E1000_BPTC); +} + +/** + * e1000_check_for_copper_link_generic - Check for link (Copper) + * @hw: pointer to the HW structure + * + * Checks to see of the link status of the hardware has changed. If a + * change in link status has been detected, then we read the PHY registers + * to get the current speed/duplex if link exists. + **/ +s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; + bool link; + + DEBUGFUNC("e1000_check_for_copper_link"); + + /* + * We only want to go out to the PHY registers to see if Auto-Neg + * has completed and/or if our link status has changed. The + * get_link_status flag is set upon receiving a Link Status + * Change or Rx Sequence Error interrupt. + */ + if (!mac->get_link_status) { + ret_val = E1000_SUCCESS; + goto out; + } + + /* + * First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ + ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) + goto out; /* No link detected */ + + mac->get_link_status = false; + + /* + * Check if there was DownShift, must be checked + * immediately after link-up + */ + e1000_check_downshift_generic(hw); + + /* + * If we are forcing speed/duplex, then we simply return since + * we have already determined whether we have link or not. + */ + if (!mac->autoneg) { + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + /* + * Auto-Neg is enabled. Auto Speed Detection takes care + * of MAC speed/duplex configuration. So we only need to + * configure Collision Distance in the MAC. + */ + e1000_config_collision_dist_generic(hw); + + /* + * Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = e1000_config_fc_after_link_up_generic(hw); + if (ret_val) { + DEBUGOUT("Error configuring flow control\n"); + } + +out: + return ret_val; +} + +/** + * e1000_check_for_fiber_link_generic - Check for link (Fiber) + * @hw: pointer to the HW structure + * + * Checks for link up on the hardware. If link is not up and we have + * a signal, then we need to force link up. + **/ +s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 rxcw; + u32 ctrl; + u32 status; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_check_for_fiber_link_generic"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + status = E1000_READ_REG(hw, E1000_STATUS); + rxcw = E1000_READ_REG(hw, E1000_RXCW); + + /* + * If we don't have link (auto-negotiation failed or link partner + * cannot auto-negotiate), the cable is plugged in (we have signal), + * and our link partner is not trying to auto-negotiate with us (we + * are receiving idles or data), we need to force link up. We also + * need to give auto-negotiation time to complete, in case the cable + * was just plugged in. The autoneg_failed flag does this. + */ + /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ + if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) && + (!(rxcw & E1000_RXCW_C))) { + if (mac->autoneg_failed == 0) { + mac->autoneg_failed = 1; + goto out; + } + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); + + /* Disable auto-negotiation in the TXCW register */ + E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); + + /* Force link-up and also force full-duplex. */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + /* Configure Flow Control after forcing link up. */ + ret_val = e1000_config_fc_after_link_up_generic(hw); + if (ret_val) { + DEBUGOUT("Error configuring flow control\n"); + goto out; + } + } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { + /* + * If we are forcing link and we are receiving /C/ ordered + * sets, re-enable auto-negotiation in the TXCW register + * and disable forced link in the Device Control register + * in an attempt to auto-negotiate with our link partner. + */ + DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); + E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); + E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); + + mac->serdes_has_link = true; + } + +out: + return ret_val; +} + +/** + * e1000_check_for_serdes_link_generic - Check for link (Serdes) + * @hw: pointer to the HW structure + * + * Checks for link up on the hardware. If link is not up and we have + * a signal, then we need to force link up. + **/ +s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 rxcw; + u32 ctrl; + u32 status; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_check_for_serdes_link_generic"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + status = E1000_READ_REG(hw, E1000_STATUS); + rxcw = E1000_READ_REG(hw, E1000_RXCW); + + /* + * If we don't have link (auto-negotiation failed or link partner + * cannot auto-negotiate), and our link partner is not trying to + * auto-negotiate with us (we are receiving idles or data), + * we need to force link up. We also need to give auto-negotiation + * time to complete. + */ + /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ + if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { + if (mac->autoneg_failed == 0) { + mac->autoneg_failed = 1; + goto out; + } + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); + + /* Disable auto-negotiation in the TXCW register */ + E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); + + /* Force link-up and also force full-duplex. */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + /* Configure Flow Control after forcing link up. */ + ret_val = e1000_config_fc_after_link_up_generic(hw); + if (ret_val) { + DEBUGOUT("Error configuring flow control\n"); + goto out; + } + } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { + /* + * If we are forcing link and we are receiving /C/ ordered + * sets, re-enable auto-negotiation in the TXCW register + * and disable forced link in the Device Control register + * in an attempt to auto-negotiate with our link partner. + */ + DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); + E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); + E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); + + mac->serdes_has_link = true; + } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { + /* + * If we force link for non-auto-negotiation switch, check + * link status based on MAC synchronization for internal + * serdes media type. + */ + /* SYNCH bit and IV bit are sticky. */ + usec_delay(10); + if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, E1000_RXCW)) { + if (!(rxcw & E1000_RXCW_IV)) { + mac->serdes_has_link = true; + DEBUGOUT("SERDES: Link is up.\n"); + } + } else { + mac->serdes_has_link = false; + DEBUGOUT("SERDES: Link is down.\n"); + } + } + + if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) { + status = E1000_READ_REG(hw, E1000_STATUS); + mac->serdes_has_link = (status & E1000_STATUS_LU) + ? true + : false; + } + +out: + return ret_val; +} + +/** + * e1000_setup_link_generic - Setup flow control and link settings + * @hw: pointer to the HW structure + * + * Determines which flow control settings to use, then configures flow + * control. Calls the appropriate media-specific link configuration + * function. Assuming the adapter has a valid link partner, a valid link + * should be established. Assumes the hardware has previously been reset + * and the transmitter and receiver are not enabled. + **/ +s32 e1000_setup_link_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_setup_link_generic"); + + /* + * In the case of the phy reset being blocked, we already have a link. + * We do not need to set it up again. + */ + if (hw->phy.ops.check_reset_block) + if (hw->phy.ops.check_reset_block(hw)) + goto out; + + /* + * If flow control is set to default, set flow control based on + * the EEPROM flow control settings. + */ + if (hw->fc.type == e1000_fc_default) { + ret_val = e1000_set_default_fc_generic(hw); + if (ret_val) + goto out; + } + + /* + * We want to save off the original Flow Control configuration just + * in case we get disconnected and then reconnected into a different + * hub or switch with different Flow Control capabilities. + */ + hw->fc.original_type = hw->fc.type; + + DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type); + + /* Call the necessary media_type subroutine to configure the link. */ + ret_val = hw->mac.ops.setup_physical_interface(hw); + if (ret_val) + goto out; + + /* + * Initialize the flow control address, type, and PAUSE timer + * registers to their default values. This is done even if flow + * control is disabled, because it does not hurt anything to + * initialize these registers. + */ + DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); + E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); + E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); + E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); + + E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); + + ret_val = e1000_set_fc_watermarks_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes + * @hw: pointer to the HW structure + * + * Configures collision distance and flow control for fiber and serdes + * links. Upon successful setup, poll for link. + **/ +s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) +{ + u32 ctrl; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_setup_fiber_serdes_link_generic"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + + /* Take the link out of reset */ + ctrl &= ~E1000_CTRL_LRST; + + e1000_config_collision_dist_generic(hw); + + ret_val = e1000_commit_fc_settings_generic(hw); + if (ret_val) + goto out; + + /* + * Since auto-negotiation is enabled, take the link out of reset (the + * link will be in reset, because we previously reset the chip). This + * will restart auto-negotiation. If auto-negotiation is successful + * then the link-up status bit will be set and the flow control enable + * bits (RFCE and TFCE) will be set according to their negotiated value. + */ + DEBUGOUT("Auto-negotiation enabled\n"); + + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + msec_delay(1); + + /* + * For these adapters, the SW definable pin 1 is set when the optics + * detect a signal. If we have a signal, then poll for a "Link-Up" + * indication. + */ + if (hw->phy.media_type == e1000_media_type_internal_serdes || + (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { + ret_val = e1000_poll_fiber_serdes_link_generic(hw); + } else { + DEBUGOUT("No signal detected\n"); + } + +out: + return ret_val; +} + +/** + * e1000_config_collision_dist_generic - Configure collision distance + * @hw: pointer to the HW structure + * + * Configures the collision distance to the default value and is used + * during link setup. Currently no func pointer exists and all + * implementations are handled in the generic version of this function. + **/ +void e1000_config_collision_dist_generic(struct e1000_hw *hw) +{ + u32 tctl; + + DEBUGFUNC("e1000_config_collision_dist_generic"); + + tctl = E1000_READ_REG(hw, E1000_TCTL); + + tctl &= ~E1000_TCTL_COLD; + tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; + + E1000_WRITE_REG(hw, E1000_TCTL, tctl); + E1000_WRITE_FLUSH(hw); +} + +/** + * e1000_poll_fiber_serdes_link_generic - Poll for link up + * @hw: pointer to the HW structure + * + * Polls for link up by reading the status register, if link fails to come + * up with auto-negotiation, then the link is forced if a signal is detected. + **/ +s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 i, status; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_poll_fiber_serdes_link_generic"); + + /* + * If we have a signal (the cable is plugged in, or assumed true for + * serdes media) then poll for a "Link-Up" indication in the Device + * Status Register. Time-out if a link isn't seen in 500 milliseconds + * seconds (Auto-negotiation should complete in less than 500 + * milliseconds even if the other end is doing it in SW). + */ + for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { + msec_delay(10); + status = E1000_READ_REG(hw, E1000_STATUS); + if (status & E1000_STATUS_LU) + break; + } + if (i == FIBER_LINK_UP_LIMIT) { + DEBUGOUT("Never got a valid link from auto-neg!!!\n"); + mac->autoneg_failed = 1; + /* + * AutoNeg failed to achieve a link, so we'll call + * mac->check_for_link. This routine will force the + * link up if we detect a signal. This will allow us to + * communicate with non-autonegotiating link partners. + */ + ret_val = hw->mac.ops.check_for_link(hw); + if (ret_val) { + DEBUGOUT("Error while checking for link\n"); + goto out; + } + mac->autoneg_failed = 0; + } else { + mac->autoneg_failed = 0; + DEBUGOUT("Valid Link Found\n"); + } + +out: + return ret_val; +} + +/** + * e1000_commit_fc_settings_generic - Configure flow control + * @hw: pointer to the HW structure + * + * Write the flow control settings to the Transmit Config Word Register (TXCW) + * base on the flow control settings in e1000_mac_info. + **/ +s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 txcw; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_commit_fc_settings_generic"); + + /* + * Check for a software override of the flow control settings, and + * setup the device accordingly. If auto-negotiation is enabled, then + * software will have to set the "PAUSE" bits to the correct value in + * the Transmit Config Word Register (TXCW) and re-start auto- + * negotiation. However, if auto-negotiation is disabled, then + * software will have to manually configure the two flow control enable + * bits in the CTRL register. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but we + * do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + */ + switch (hw->fc.type) { + case e1000_fc_none: + /* Flow control completely disabled by a software over-ride. */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); + break; + case e1000_fc_rx_pause: + /* + * Rx Flow control is enabled and Tx Flow control is disabled + * by a software over-ride. Since there really isn't a way to + * advertise that we are capable of Rx Pause ONLY, we will + * advertise that we support both symmetric and asymmetric RX + * PAUSE. Later, we will disable the adapter's ability to send + * PAUSE frames. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); + break; + case e1000_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is disabled, + * by a software over-ride. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); + break; + case e1000_fc_full: + /* + * Flow control (both Rx and Tx) is enabled by a software + * over-ride. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + break; + } + + E1000_WRITE_REG(hw, E1000_TXCW, txcw); + mac->txcw = txcw; + +out: + return ret_val; +} + +/** + * e1000_set_fc_watermarks_generic - Set flow control high/low watermarks + * @hw: pointer to the HW structure + * + * Sets the flow control high/low threshold (watermark) registers. If + * flow control XON frame transmission is enabled, then set XON frame + * transmission as well. + **/ +s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u32 fcrtl = 0, fcrth = 0; + + DEBUGFUNC("e1000_set_fc_watermarks_generic"); + + /* + * Set the flow control receive threshold registers. Normally, + * these registers will be set to a default threshold that may be + * adjusted later by the driver's runtime code. However, if the + * ability to transmit pause frames is not enabled, then these + * registers will be set to 0. + */ + if (hw->fc.type & e1000_fc_tx_pause) { + /* + * We need to set up the Receive Threshold high and low water + * marks as well as (optionally) enabling the transmission of + * XON frames. + */ + fcrtl = hw->fc.low_water; + if (hw->fc.send_xon) + fcrtl |= E1000_FCRTL_XONE; + + fcrth = hw->fc.high_water; + } + E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl); + E1000_WRITE_REG(hw, E1000_FCRTH, fcrth); + + return ret_val; +} + +/** + * e1000_set_default_fc_generic - Set flow control default values + * @hw: pointer to the HW structure + * + * Read the EEPROM for the default values for flow control and store the + * values. + **/ +s32 e1000_set_default_fc_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 nvm_data; + + DEBUGFUNC("e1000_set_default_fc_generic"); + + /* + * Read and store word 0x0F of the EEPROM. This word contains bits + * that determine the hardware's default PAUSE (flow control) mode, + * a bit that determines whether the HW defaults to enabling or + * disabling auto-negotiation, and the direction of the + * SW defined pins. If there is no SW over-ride of the flow + * control setting, then the variable hw->fc will + * be initialized based on a value in the EEPROM. + */ + ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); + + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + + if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) + hw->fc.type = e1000_fc_none; + else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == + NVM_WORD0F_ASM_DIR) + hw->fc.type = e1000_fc_tx_pause; + else + hw->fc.type = e1000_fc_full; + +out: + return ret_val; +} + +/** + * e1000_force_mac_fc_generic - Force the MAC's flow control settings + * @hw: pointer to the HW structure + * + * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the + * device control register to reflect the adapter settings. TFCE and RFCE + * need to be explicitly set by software when a copper PHY is used because + * autonegotiation is managed by the PHY rather than the MAC. Software must + * also configure these bits when link is forced on a fiber connection. + **/ +s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) +{ + u32 ctrl; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_force_mac_fc_generic"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + + /* + * Because we didn't get link via the internal auto-negotiation + * mechanism (we either forced link or we got link via PHY + * auto-neg), we have to manually enable/disable transmit an + * receive flow control. + * + * The "Case" statement below enables/disable flow control + * according to the "hw->fc.type" parameter. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause + * frames but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames + * frames but we do not receive pause frames). + * 3: Both Rx and Tx flow control (symmetric) is enabled. + * other: No other values should be possible at this point. + */ + DEBUGOUT1("hw->fc.type = %u\n", hw->fc.type); + + switch (hw->fc.type) { + case e1000_fc_none: + ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); + break; + case e1000_fc_rx_pause: + ctrl &= (~E1000_CTRL_TFCE); + ctrl |= E1000_CTRL_RFCE; + break; + case e1000_fc_tx_pause: + ctrl &= (~E1000_CTRL_RFCE); + ctrl |= E1000_CTRL_TFCE; + break; + case e1000_fc_full: + ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + +out: + return ret_val; +} + +/** + * e1000_config_fc_after_link_up_generic - Configures flow control after link + * @hw: pointer to the HW structure + * + * Checks the status of auto-negotiation after link up to ensure that the + * speed and duplex were not forced. If the link needed to be forced, then + * flow control needs to be forced also. If auto-negotiation is enabled + * and did not fail, then we configure flow control based on our link + * partner. + **/ +s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; + u16 speed, duplex; + + DEBUGFUNC("e1000_config_fc_after_link_up_generic"); + + /* + * Check for the case where we have fiber media and auto-neg failed + * so we had to force link. In this case, we need to force the + * configuration of the MAC to match the "fc" parameter. + */ + if (mac->autoneg_failed) { + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) + ret_val = e1000_force_mac_fc_generic(hw); + } else { + if (hw->phy.media_type == e1000_media_type_copper) + ret_val = e1000_force_mac_fc_generic(hw); + } + + if (ret_val) { + DEBUGOUT("Error forcing flow control settings\n"); + goto out; + } + + /* + * Check for the case where we have copper media and auto-neg is + * enabled. In this case, we need to check and see if Auto-Neg + * has completed, and if so, how the PHY and link partner has + * flow control configured. + */ + if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { + /* + * Read the MII Status Register and check to see if AutoNeg + * has completed. We read this twice because this reg has + * some "sticky" (latched) bits. + */ + ret_val = phy->ops.read_reg(hw, PHY_STATUS, &mii_status_reg); + if (ret_val) + goto out; + ret_val = phy->ops.read_reg(hw, PHY_STATUS, &mii_status_reg); + if (ret_val) + goto out; + + if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { + DEBUGOUT("Copper PHY and Auto Neg " + "has not completed.\n"); + goto out; + } + + /* + * The AutoNeg process has completed, so we now need to + * read both the Auto Negotiation Advertisement + * Register (Address 4) and the Auto_Negotiation Base + * Page Ability Register (Address 5) to determine how + * flow control was negotiated. + */ + ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, + &mii_nway_adv_reg); + if (ret_val) + goto out; + ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, + &mii_nway_lp_ability_reg); + if (ret_val) + goto out; + + /* + * Two bits in the Auto Negotiation Advertisement Register + * (Address 4) and two bits in the Auto Negotiation Base + * Page Ability Register (Address 5) determine flow control + * for both the PHY and the link partner. The following + * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, + * 1999, describes these PAUSE resolution bits and how flow + * control is determined based upon these settings. + * NOTE: DC = Don't Care + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution + *-------|---------|-------|---------|-------------------- + * 0 | 0 | DC | DC | e1000_fc_none + * 0 | 1 | 0 | DC | e1000_fc_none + * 0 | 1 | 1 | 0 | e1000_fc_none + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + * 1 | 0 | 0 | DC | e1000_fc_none + * 1 | DC | 1 | DC | e1000_fc_full + * 1 | 1 | 0 | 0 | e1000_fc_none + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + * + * Are both PAUSE bits set to 1? If so, this implies + * Symmetric Flow Control is enabled at both ends. The + * ASM_DIR bits are irrelevant per the spec. + * + * For Symmetric Flow Control: + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | DC | 1 | DC | E1000_fc_full + * + */ + if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { + /* + * Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.original_type == e1000_fc_full) { + hw->fc.type = e1000_fc_full; + DEBUGOUT("Flow Control = FULL.\r\n"); + } else { + hw->fc.type = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = " + "RX PAUSE frames only.\r\n"); + } + } + /* + * For receiving PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + */ + else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { + hw->fc.type = e1000_fc_tx_pause; + DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); + } + /* + * For transmitting PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + */ + else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { + hw->fc.type = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + } else { + /* + * Per the IEEE spec, at this point flow control + * should be disabled. + */ + hw->fc.type = e1000_fc_none; + DEBUGOUT("Flow Control = NONE.\r\n"); + } + + /* + * Now we need to do one last check... If we auto- + * negotiated to HALF DUPLEX, flow control should not be + * enabled per IEEE 802.3 spec. + */ + ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); + if (ret_val) { + DEBUGOUT("Error getting link speed and duplex\n"); + goto out; + } + + if (duplex == HALF_DUPLEX) + hw->fc.type = e1000_fc_none; + + /* + * Now we call a subroutine to actually force the MAC + * controller to use the correct flow control settings. + */ + ret_val = e1000_force_mac_fc_generic(hw); + if (ret_val) { + DEBUGOUT("Error forcing flow control settings\n"); + goto out; + } + } + +out: + return ret_val; +} + +/** + * e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex + * @hw: pointer to the HW structure + * @speed: stores the current speed + * @duplex: stores the current duplex + * + * Read the status register for the current speed/duplex and store the current + * speed and duplex for copper connections. + **/ +s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, + u16 *duplex) +{ + u32 status; + + DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic"); + + status = E1000_READ_REG(hw, E1000_STATUS); + if (status & E1000_STATUS_SPEED_1000) { + *speed = SPEED_1000; + DEBUGOUT("1000 Mbs, "); + } else if (status & E1000_STATUS_SPEED_100) { + *speed = SPEED_100; + DEBUGOUT("100 Mbs, "); + } else { + *speed = SPEED_10; + DEBUGOUT("10 Mbs, "); + } + + if (status & E1000_STATUS_FD) { + *duplex = FULL_DUPLEX; + DEBUGOUT("Full Duplex\n"); + } else { + *duplex = HALF_DUPLEX; + DEBUGOUT("Half Duplex\n"); + } + + return E1000_SUCCESS; +} + +/** + * e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex + * @hw: pointer to the HW structure + * @speed: stores the current speed + * @duplex: stores the current duplex + * + * Sets the speed and duplex to gigabit full duplex (the only possible option) + * for fiber/serdes links. + **/ +s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, + u16 *speed, u16 *duplex) +{ + DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic"); + + *speed = SPEED_1000; + *duplex = FULL_DUPLEX; + + return E1000_SUCCESS; +} + +/** + * e1000_get_hw_semaphore_generic - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the HW semaphore to access the PHY or NVM + **/ +s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) +{ + u32 swsm; + s32 ret_val = E1000_SUCCESS; + s32 timeout = hw->nvm.word_size + 1; + s32 i = 0; + + DEBUGFUNC("e1000_get_hw_semaphore_generic"); + + /* Get the SW semaphore */ + while (i < timeout) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + + usec_delay(50); + i++; + } + + if (i == timeout) { + DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + /* Get the FW semaphore. */ + for (i = 0; i < timeout; i++) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); + + /* Semaphore acquired if bit latched */ + if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) + break; + + usec_delay(50); + } + + if (i == timeout) { + /* Release semaphores */ + e1000_put_hw_semaphore_generic(hw); + DEBUGOUT("Driver can't access the NVM\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_put_hw_semaphore_generic - Release hardware semaphore + * @hw: pointer to the HW structure + * + * Release hardware semaphore used to access the PHY or NVM + **/ +void e1000_put_hw_semaphore_generic(struct e1000_hw *hw) +{ + u32 swsm; + + DEBUGFUNC("e1000_put_hw_semaphore_generic"); + + swsm = E1000_READ_REG(hw, E1000_SWSM); + + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); + + E1000_WRITE_REG(hw, E1000_SWSM, swsm); +} + +/** + * e1000_get_auto_rd_done_generic - Check for auto read completion + * @hw: pointer to the HW structure + * + * Check EEPROM for Auto Read done bit. + **/ +s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) +{ + s32 i = 0; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_get_auto_rd_done_generic"); + + while (i < AUTO_READ_DONE_TIMEOUT) { + if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_AUTO_RD) + break; + msec_delay(1); + i++; + } + + if (i == AUTO_READ_DONE_TIMEOUT) { + DEBUGOUT("Auto read by HW from NVM has not completed.\n"); + ret_val = -E1000_ERR_RESET; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_valid_led_default_generic - Verify a valid default LED config + * @hw: pointer to the HW structure + * @data: pointer to the NVM (EEPROM) + * + * Read the EEPROM for the current default LED configuration. If the + * LED configuration is not valid, set to a valid LED configuration. + **/ +s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data) +{ + s32 ret_val; + + DEBUGFUNC("e1000_valid_led_default_generic"); + + ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + + if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) + *data = ID_LED_DEFAULT; + +out: + return ret_val; +} + +/** + * e1000_id_led_init_generic - + * @hw: pointer to the HW structure + * + **/ +s32 e1000_id_led_init_generic(struct e1000_hw * hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; + const u32 ledctl_mask = 0x000000FF; + const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; + const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; + u16 data, i, temp; + const u16 led_mask = 0x0F; + + DEBUGFUNC("e1000_id_led_init_generic"); + + ret_val = hw->nvm.ops.valid_led_default(hw, &data); + if (ret_val) + goto out; + + mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); + mac->ledctl_mode1 = mac->ledctl_default; + mac->ledctl_mode2 = mac->ledctl_default; + + for (i = 0; i < 4; i++) { + temp = (data >> (i << 2)) & led_mask; + switch (temp) { + case ID_LED_ON1_DEF2: + case ID_LED_ON1_ON2: + case ID_LED_ON1_OFF2: + mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); + mac->ledctl_mode1 |= ledctl_on << (i << 3); + break; + case ID_LED_OFF1_DEF2: + case ID_LED_OFF1_ON2: + case ID_LED_OFF1_OFF2: + mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); + mac->ledctl_mode1 |= ledctl_off << (i << 3); + break; + default: + /* Do nothing */ + break; + } + switch (temp) { + case ID_LED_DEF1_ON2: + case ID_LED_ON1_ON2: + case ID_LED_OFF1_ON2: + mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); + mac->ledctl_mode2 |= ledctl_on << (i << 3); + break; + case ID_LED_DEF1_OFF2: + case ID_LED_ON1_OFF2: + case ID_LED_OFF1_OFF2: + mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); + mac->ledctl_mode2 |= ledctl_off << (i << 3); + break; + default: + /* Do nothing */ + break; + } + } + +out: + return ret_val; +} + +/** + * e1000_setup_led_generic - Configures SW controllable LED + * @hw: pointer to the HW structure + * + * This prepares the SW controllable LED for use and saves the current state + * of the LED so it can be later restored. + **/ +s32 e1000_setup_led_generic(struct e1000_hw *hw) +{ + u32 ledctl; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_setup_led_generic"); + + if (hw->mac.ops.setup_led != e1000_setup_led_generic) { + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + if (hw->phy.media_type == e1000_media_type_fiber) { + ledctl = E1000_READ_REG(hw, E1000_LEDCTL); + hw->mac.ledctl_default = ledctl; + /* Turn off LED0 */ + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | + E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_MODE_MASK); + ledctl |= (E1000_LEDCTL_MODE_LED_OFF << + E1000_LEDCTL_LED0_MODE_SHIFT); + E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); + } else if (hw->phy.media_type == e1000_media_type_copper) { + E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); + } + +out: + return ret_val; +} + +/** + * e1000_cleanup_led_generic - Set LED config to default operation + * @hw: pointer to the HW structure + * + * Remove the current LED configuration and set the LED configuration + * to the default value, saved from the EEPROM. + **/ +s32 e1000_cleanup_led_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_cleanup_led_generic"); + + if (hw->mac.ops.cleanup_led != e1000_cleanup_led_generic) { + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); + +out: + return ret_val; +} + +/** + * e1000_blink_led_generic - Blink LED + * @hw: pointer to the HW structure + * + * Blink the LEDs which are set to be on. + **/ +s32 e1000_blink_led_generic(struct e1000_hw *hw) +{ + u32 ledctl_blink = 0; + u32 i; + + DEBUGFUNC("e1000_blink_led_generic"); + + if (hw->phy.media_type == e1000_media_type_fiber) { + /* always blink LED0 for PCI-E fiber */ + ledctl_blink = E1000_LEDCTL_LED0_BLINK | + (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); + } else { + /* + * set the blink bit for each LED that's "on" (0x0E) + * in ledctl_mode2 + */ + ledctl_blink = hw->mac.ledctl_mode2; + for (i = 0; i < 4; i++) + if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == + E1000_LEDCTL_MODE_LED_ON) + ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << + (i * 8)); + } + + E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink); + + return E1000_SUCCESS; +} + +/** + * e1000_led_on_generic - Turn LED on + * @hw: pointer to the HW structure + * + * Turn LED on. + **/ +s32 e1000_led_on_generic(struct e1000_hw *hw) +{ + u32 ctrl; + + DEBUGFUNC("e1000_led_on_generic"); + + switch (hw->phy.media_type) { + case e1000_media_type_fiber: + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + break; + case e1000_media_type_copper: + E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); + break; + default: + break; + } + + return E1000_SUCCESS; +} + +/** + * e1000_led_off_generic - Turn LED off + * @hw: pointer to the HW structure + * + * Turn LED off. + **/ +s32 e1000_led_off_generic(struct e1000_hw *hw) +{ + u32 ctrl; + + DEBUGFUNC("e1000_led_off_generic"); + + switch (hw->phy.media_type) { + case e1000_media_type_fiber: + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + break; + case e1000_media_type_copper: + E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); + break; + default: + break; + } + + return E1000_SUCCESS; +} + +/** + * e1000_set_pcie_no_snoop_generic - Set PCI-express capabilities + * @hw: pointer to the HW structure + * @no_snoop: bitmap of snoop events + * + * Set the PCI-express register to snoop for events enabled in 'no_snoop'. + **/ +void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) +{ + u32 gcr; + + DEBUGFUNC("e1000_set_pcie_no_snoop_generic"); + + if (hw->bus.type != e1000_bus_type_pci_express) + goto out; + + if (no_snoop) { + gcr = E1000_READ_REG(hw, E1000_GCR); + gcr &= ~(PCIE_NO_SNOOP_ALL); + gcr |= no_snoop; + E1000_WRITE_REG(hw, E1000_GCR, gcr); + } +out: + return; +} + +/** + * e1000_disable_pcie_master_generic - Disables PCI-express master access + * @hw: pointer to the HW structure + * + * Returns 0 (E1000_SUCCESS) if successful, else returns -10 + * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused + * the master requests to be disabled. + * + * Disables PCI-Express master access and verifies there are no pending + * requests. + **/ +s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) +{ + u32 ctrl; + s32 timeout = MASTER_DISABLE_TIMEOUT; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_disable_pcie_master_generic"); + + if (hw->bus.type != e1000_bus_type_pci_express) + goto out; + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + while (timeout) { + if (!(E1000_READ_REG(hw, E1000_STATUS) & + E1000_STATUS_GIO_MASTER_ENABLE)) + break; + usec_delay(100); + timeout--; + } + + if (!timeout) { + DEBUGOUT("Master requests are pending.\n"); + ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_reset_adaptive_generic - Reset Adaptive Interframe Spacing + * @hw: pointer to the HW structure + * + * Reset the Adaptive Interframe Spacing throttle to default values. + **/ +void e1000_reset_adaptive_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + + DEBUGFUNC("e1000_reset_adaptive_generic"); + + if (!mac->adaptive_ifs) { + DEBUGOUT("Not in Adaptive IFS mode!\n"); + goto out; + } + + if (!mac->ifs_params_forced) { + mac->current_ifs_val = 0; + mac->ifs_min_val = IFS_MIN; + mac->ifs_max_val = IFS_MAX; + mac->ifs_step_size = IFS_STEP; + mac->ifs_ratio = IFS_RATIO; + } + + mac->in_ifs_mode = false; + E1000_WRITE_REG(hw, E1000_AIT, 0); +out: + return; +} + +/** + * e1000_update_adaptive_generic - Update Adaptive Interframe Spacing + * @hw: pointer to the HW structure + * + * Update the Adaptive Interframe Spacing Throttle value based on the + * time between transmitted packets and time between collisions. + **/ +void e1000_update_adaptive_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + + DEBUGFUNC("e1000_update_adaptive_generic"); + + if (!mac->adaptive_ifs) { + DEBUGOUT("Not in Adaptive IFS mode!\n"); + goto out; + } + + if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { + if (mac->tx_packet_delta > MIN_NUM_XMITS) { + mac->in_ifs_mode = true; + if (mac->current_ifs_val < mac->ifs_max_val) { + if (!mac->current_ifs_val) + mac->current_ifs_val = mac->ifs_min_val; + else + mac->current_ifs_val += + mac->ifs_step_size; + E1000_WRITE_REG(hw, E1000_AIT, mac->current_ifs_val); + } + } + } else { + if (mac->in_ifs_mode && + (mac->tx_packet_delta <= MIN_NUM_XMITS)) { + mac->current_ifs_val = 0; + mac->in_ifs_mode = false; + E1000_WRITE_REG(hw, E1000_AIT, 0); + } + } +out: + return; +} + +/** + * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings + * @hw: pointer to the HW structure + * + * Verify that when not using auto-negotiation that MDI/MDIx is correctly + * set, which is forced to MDI mode only. + **/ +s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_validate_mdi_setting_generic"); + + if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { + DEBUGOUT("Invalid MDI setting detected\n"); + hw->phy.mdix = 1; + ret_val = -E1000_ERR_CONFIG; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_write_8bit_ctrl_reg_generic - Write a 8bit CTRL register + * @hw: pointer to the HW structure + * @reg: 32bit register offset such as E1000_SCTL + * @offset: register offset to write to + * @data: data to write at register offset + * + * Writes an address/data control type register. There are several of these + * and they all have the format address << 8 | data and bit 31 is polled for + * completion. + **/ +s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, + u32 offset, u8 data) +{ + u32 i, regvalue = 0; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_8bit_ctrl_reg_generic"); + + /* Set up the address and data */ + regvalue = ((u32)data) | (offset << E1000_GEN_CTL_ADDRESS_SHIFT); + E1000_WRITE_REG(hw, reg, regvalue); + + /* Poll the ready bit to see if the MDI read completed */ + for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) { + usec_delay(5); + regvalue = E1000_READ_REG(hw, reg); + if (regvalue & E1000_GEN_CTL_READY) + break; + } + if (!(regvalue & E1000_GEN_CTL_READY)) { + DEBUGOUT1("Reg %08x did not indicate ready\n", reg); + ret_val = -E1000_ERR_PHY; + goto out; + } + +out: + return ret_val; +} --- linux-2.6.27.orig/ubuntu/e1000e/e1000_ich8lan.c +++ linux-2.6.27/ubuntu/e1000e/e1000_ich8lan.c @@ -0,0 +1,2798 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* e1000_ich8lan + * e1000_ich9lan + */ + +#include "e1000.h" + +static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw); +static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw); +static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw); +static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw); +static void e1000_release_swflag_ich8lan(struct e1000_hw *hw); +static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); +static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw); +static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw); +static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw); +static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw); +static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw); +static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, + bool active); +static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, + bool active); +static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); +static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw); +static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, + u16 *data); +static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw); +static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw); +static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw); +static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); +static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); +static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, + u16 *speed, u16 *duplex); +static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); +static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); +static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); +static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); +static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); +static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout); +static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw); +static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw); +static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); +static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); +static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, + u32 offset, u8* data); +static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + u8 size, u16* data); +static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, + u32 offset, u16 *data); +static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, + u32 offset, u8 byte); +static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, + u32 offset, u8 data); +static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + u8 size, u16 data); +static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); +static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); + +/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ +/* Offset 04h HSFSTS */ +union ich8_hws_flash_status { + struct ich8_hsfsts { + u16 flcdone :1; /* bit 0 Flash Cycle Done */ + u16 flcerr :1; /* bit 1 Flash Cycle Error */ + u16 dael :1; /* bit 2 Direct Access error Log */ + u16 berasesz :2; /* bit 4:3 Sector Erase Size */ + u16 flcinprog :1; /* bit 5 flash cycle in Progress */ + u16 reserved1 :2; /* bit 13:6 Reserved */ + u16 reserved2 :6; /* bit 13:6 Reserved */ + u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */ + u16 flockdn :1; /* bit 15 Flash Config Lock-Down */ + } hsf_status; + u16 regval; +}; + +/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ +/* Offset 06h FLCTL */ +union ich8_hws_flash_ctrl { + struct ich8_hsflctl { + u16 flcgo :1; /* 0 Flash Cycle Go */ + u16 flcycle :2; /* 2:1 Flash Cycle */ + u16 reserved :5; /* 7:3 Reserved */ + u16 fldbcount :2; /* 9:8 Flash Data Byte Count */ + u16 flockdn :6; /* 15:10 Reserved */ + } hsf_ctrl; + u16 regval; +}; + +/* ICH Flash Region Access Permissions */ +union ich8_hws_flash_regacc { + struct ich8_flracc { + u32 grra :8; /* 0:7 GbE region Read Access */ + u32 grwa :8; /* 8:15 GbE region Write Access */ + u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */ + u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */ + } hsf_flregacc; + u16 regval; +}; + +struct e1000_shadow_ram { + u16 value; + bool modified; +}; + +struct e1000_dev_spec_ich8lan { + bool kmrn_lock_loss_workaround_enabled; + struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS]; +}; + +/* + * NV RAM mapping can get nested, so keep track of the mapping depth. + */ +static int e1000e_map_nvram(struct e1000_hw *hw) +{ + int ret_val = E1000_SUCCESS; + struct e1000_adapter *adapter = hw->back; + + spin_lock(&hw->flash_address_map_lock); + + hw->flash_address_map_cnt++; + + if (hw->flash_address_map_cnt==1) { + BUG_ON(adapter->hw.flash_address); + WARN_ON(irqs_disabled()); + adapter->hw.flash_address = ioremap(pci_resource_start(adapter->pdev, 1), + pci_resource_len(adapter->pdev, 1)); + if (!adapter->hw.flash_address) { + hw->flash_address_map_cnt--; + ret_val = -E1000_ERR_NVM; + } + } + + spin_unlock(&hw->flash_address_map_lock); + + return ret_val; +} + +static void e1000e_unmap_nvram(struct e1000_hw *hw) +{ + struct e1000_adapter *adapter = hw->back; + + spin_lock(&hw->flash_address_map_lock); + + BUG_ON(!hw->flash_address_map_cnt); + + hw->flash_address_map_cnt--; + + if (hw->flash_address_map_cnt==0) { + BUG_ON(!adapter->hw.flash_address); + WARN_ON(irqs_disabled()); + iounmap(adapter->hw.flash_address); + adapter->hw.flash_address = NULL; + } + + spin_unlock(&hw->flash_address_map_lock); +} + +/** + * e1000_init_phy_params_ich8lan - Initialize PHY function pointers + * @hw: pointer to the HW structure + * + * Initialize family-specific PHY parameters and function pointers. + **/ +static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 i = 0; + + DEBUGFUNC("e1000_init_phy_params_ich8lan"); + + phy->addr = 1; + phy->reset_delay_us = 100; + + phy->ops.acquire = e1000_acquire_swflag_ich8lan; + phy->ops.check_polarity = e1000_check_polarity_ife_ich8lan; + phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ich8lan; + phy->ops.get_cable_length = e1000_get_cable_length_igp_2; + phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; + phy->ops.get_info = e1000_get_phy_info_ich8lan; + phy->ops.read_reg = e1000_read_phy_reg_igp; + phy->ops.release = e1000_release_swflag_ich8lan; + phy->ops.reset = e1000_phy_hw_reset_ich8lan; + phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan; + phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan; + phy->ops.write_reg = e1000_write_phy_reg_igp; + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; + + /* + * We may need to do this twice - once for IGP and if that fails, + * we'll set BM func pointers and try again + */ + ret_val = e1000_determine_phy_address(hw); + if (ret_val) { + phy->ops.write_reg = e1000_write_phy_reg_bm; + phy->ops.read_reg = e1000_read_phy_reg_bm; + ret_val = e1000_determine_phy_address(hw); + if (ret_val) { + DEBUGOUT("Cannot determine PHY address. Erroring out\n"); + goto out; + } + } + + phy->id = 0; + while ((e1000_phy_unknown == e1000_get_phy_type_from_id(phy->id)) && + (i++ < 100)) { + msec_delay(1); + ret_val = e1000_get_phy_id(hw); + if (ret_val) + goto out; + } + + /* Verify phy id */ + switch (phy->id) { + case IGP03E1000_E_PHY_ID: + phy->type = e1000_phy_igp_3; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + break; + case IFE_E_PHY_ID: + case IFE_PLUS_E_PHY_ID: + case IFE_C_E_PHY_ID: + phy->type = e1000_phy_ife; + phy->autoneg_mask = E1000_ALL_NOT_GIG; + break; + case BME1000_E_PHY_ID: + phy->type = e1000_phy_bm; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->ops.read_reg = e1000_read_phy_reg_bm; + phy->ops.write_reg = e1000_write_phy_reg_bm; + phy->ops.commit = e1000_phy_sw_reset_generic; + break; + default: + ret_val = -E1000_ERR_PHY; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers + * @hw: pointer to the HW structure + * + * Initialize family-specific NVM parameters and function + * pointers. + **/ +static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec; + u32 gfpreg, sector_base_addr, sector_end_addr; + s32 ret_val = E1000_SUCCESS; + u16 i; + + DEBUGFUNC("e1000_init_nvm_params_ich8lan"); + + /* Can't read flash registers if the register set isn't mapped. */ + ret_val = e1000e_map_nvram(hw); + if (ret_val) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return -E1000_ERR_CONFIG; + } + + nvm->type = e1000_nvm_flash_sw; + + gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); + + /* + * sector_X_addr is a "sector"-aligned address (4096 bytes) + * Add 1 to sector_end_addr since this sector is included in + * the overall size. + */ + sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; + sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; + + /* flash_base_addr is byte-aligned */ + nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; + + /* + * find total size of the NVM, then cut in half since the total + * size represents two separate NVM banks. + */ + nvm->flash_bank_size = (sector_end_addr - sector_base_addr) + << FLASH_SECTOR_ADDR_SHIFT; + nvm->flash_bank_size /= 2; + /* Adjust to word count */ + nvm->flash_bank_size /= sizeof(u16); + + nvm->word_size = E1000_SHADOW_RAM_WORDS; + + dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; + + if (!dev_spec) { + DEBUGOUT("dev_spec pointer is set to NULL.\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + /* Clear shadow ram */ + for (i = 0; i < nvm->word_size; i++) { + dev_spec->shadow_ram[i].modified = false; + dev_spec->shadow_ram[i].value = 0xFFFF; + } + + /* Function Pointers */ + nvm->ops.acquire = e1000_acquire_swflag_ich8lan; + nvm->ops.read = e1000_read_nvm_ich8lan; + nvm->ops.release = e1000_release_swflag_ich8lan; + nvm->ops.update = e1000_update_nvm_checksum_ich8lan; + nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; + nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; + nvm->ops.write = e1000_write_nvm_ich8lan; + +out: + e1000e_unmap_nvram(hw); + return ret_val; +} + +/** + * e1000_init_mac_params_ich8lan - Initialize MAC function pointers + * @hw: pointer to the HW structure + * + * Initialize family-specific MAC parameters and function + * pointers. + **/ +static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_init_mac_params_ich8lan"); + + /* Set media type function pointer */ + hw->phy.media_type = e1000_media_type_copper; + + /* Set mta register count */ + mac->mta_reg_count = 32; + /* Set rar entry count */ + mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; + if (mac->type == e1000_ich8lan) + mac->rar_entry_count--; + /* Set if part includes ASF firmware */ + mac->asf_firmware_present = true; + /* Set if manageability features are enabled. */ + mac->arc_subsystem_valid = true; + + /* Function pointers */ + + /* bus type/speed/width */ + mac->ops.get_bus_info = e1000_get_bus_info_ich8lan; + /* reset */ + mac->ops.reset_hw = e1000_reset_hw_ich8lan; + /* hw initialization */ + mac->ops.init_hw = e1000_init_hw_ich8lan; + /* link setup */ + mac->ops.setup_link = e1000_setup_link_ich8lan; + /* physical interface setup */ + mac->ops.setup_physical_interface = e1000_setup_copper_link_ich8lan; + /* check for link */ + mac->ops.check_for_link = e1000_check_for_copper_link_generic; + /* check management mode */ + mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; + /* link info */ + mac->ops.get_link_up_info = e1000_get_link_up_info_ich8lan; + /* multicast address update */ + mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; + /* setting MTA */ + mac->ops.mta_set = e1000_mta_set_generic; + /* blink LED */ + mac->ops.blink_led = e1000_blink_led_generic; + /* setup LED */ + mac->ops.setup_led = e1000_setup_led_generic; + /* cleanup LED */ + mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; + /* turn on/off LED */ + mac->ops.led_on = e1000_led_on_ich8lan; + mac->ops.led_off = e1000_led_off_ich8lan; + /* remove device */ + mac->ops.remove_device = e1000_remove_device_generic; + /* clear hardware counters */ + mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; + + hw->dev_spec_size = sizeof(struct e1000_dev_spec_ich8lan); + + /* Device-specific structure allocation */ + ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); + if (ret_val) + goto out; + + /* Enable PCS Lock-loss workaround for ICH8 */ + if (mac->type == e1000_ich8lan) + e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, true); + + +out: + return ret_val; +} + +/** + * e1000_init_function_pointers_ich8lan - Initialize ICH8 function pointers + * @hw: pointer to the HW structure + * + * Initialize family-specific function pointers for PHY, MAC, and NVM. + **/ +void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_init_function_pointers_ich8lan"); + + e1000_init_mac_ops_generic(hw); + e1000_init_nvm_ops_generic(hw); + hw->mac.ops.init_params = e1000_init_mac_params_ich8lan; + hw->nvm.ops.init_params = e1000_init_nvm_params_ich8lan; + hw->phy.ops.init_params = e1000_init_phy_params_ich8lan; +} + +/** + * e1000_acquire_swflag_ich8lan - Acquire software control flag + * @hw: pointer to the HW structure + * + * Acquires the software control flag for performing NVM and PHY + * operations. This is a function pointer entry point only called by + * read/write routines for the PHY and NVM parts. + **/ +static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) +{ + u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_acquire_swflag_ich8lan"); + + while (timeout) { + extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); + extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; + E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); + + extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); + if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) + break; + msec_delay_irq(1); + timeout--; + } + + if (!timeout) { + DEBUGOUT("FW or HW has locked the resource for too long.\n"); + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; + E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_release_swflag_ich8lan - Release software control flag + * @hw: pointer to the HW structure + * + * Releases the software control flag for performing NVM and PHY operations. + * This is a function pointer entry point only called by read/write + * routines for the PHY and NVM parts. + **/ +static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) +{ + u32 extcnf_ctrl; + + DEBUGFUNC("e1000_release_swflag_ich8lan"); + + extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; + E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); + + return; +} + +/** + * e1000_check_mng_mode_ich8lan - Checks management mode + * @hw: pointer to the HW structure + * + * This checks if the adapter has manageability enabled. + * This is a function pointer entry point only called by read/write + * routines for the PHY and NVM parts. + **/ +static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) +{ + u32 fwsm; + + DEBUGFUNC("e1000_check_mng_mode_ich8lan"); + + fwsm = E1000_READ_REG(hw, E1000_FWSM); + + return ((fwsm & E1000_FWSM_MODE_MASK) == + (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); +} + +/** + * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked + * @hw: pointer to the HW structure + * + * Checks if firmware is blocking the reset of the PHY. + * This is a function pointer entry point only called by + * reset routines. + **/ +static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) +{ + u32 fwsm; + + DEBUGFUNC("e1000_check_reset_block_ich8lan"); + + fwsm = E1000_READ_REG(hw, E1000_FWSM); + + return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS + : E1000_BLK_PHY_RESET; +} + +/** + * e1000_phy_force_speed_duplex_ich8lan - Force PHY speed & duplex + * @hw: pointer to the HW structure + * + * Forces the speed and duplex settings of the PHY. + * This is a function pointer entry point only called by + * PHY setup routines. + **/ +static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + bool link; + + DEBUGFUNC("e1000_phy_force_speed_duplex_ich8lan"); + + if (phy->type != e1000_phy_ife) { + ret_val = e1000_phy_force_speed_duplex_igp(hw); + goto out; + } + + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); + if (ret_val) + goto out; + + e1000_phy_force_speed_duplex_setup(hw, &data); + + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); + if (ret_val) + goto out; + + /* Disable MDI-X support for 10/100 */ + ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); + if (ret_val) + goto out; + + data &= ~IFE_PMC_AUTO_MDIX; + data &= ~IFE_PMC_FORCE_MDIX; + + ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); + if (ret_val) + goto out; + + DEBUGOUT1("IFE PMC: %X\n", data); + + usec_delay(1); + + if (phy->autoneg_wait_to_complete) { + DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); + + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + + if (!link) { + DEBUGOUT("Link taking longer than expected.\n"); + } + + /* Try once more */ + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_phy_hw_reset_ich8lan - Performs a PHY reset + * @hw: pointer to the HW structure + * + * Resets the PHY + * This is a function pointer entry point called by drivers + * or other shared routines. + **/ +static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + struct e1000_nvm_info *nvm = &hw->nvm; + u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; + s32 ret_val; + u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT; + u16 word_addr, reg_data, reg_addr, phy_page = 0; + + DEBUGFUNC("e1000_phy_hw_reset_ich8lan"); + + ret_val = e1000_phy_hw_reset_generic(hw); + if (ret_val) + goto out; + + /* + * Initialize the PHY from the NVM on ICH platforms. This + * is needed due to an issue where the NVM configuration is + * not properly autoloaded after power transitions. + * Therefore, after each PHY reset, we will load the + * configuration data out of the NVM manually. + */ + if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) { + /* Check if SW needs configure the PHY */ + if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) || + (hw->device_id == E1000_DEV_ID_ICH8_IGP_M)) + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; + else + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; + + data = E1000_READ_REG(hw, E1000_FEXTNVM); + if (!(data & sw_cfg_mask)) + goto out; + + /* Wait for basic configuration completes before proceeding*/ + do { + data = E1000_READ_REG(hw, E1000_STATUS); + data &= E1000_STATUS_LAN_INIT_DONE; + usec_delay(100); + } while ((!data) && --loop); + + /* + * If basic configuration is incomplete before the above loop + * count reaches 0, loading the configuration from NVM will + * leave the PHY in a bad state possibly resulting in no link. + */ + if (loop == 0) { + DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n"); + } + + /* Clear the Init Done bit for the next init event */ + data = E1000_READ_REG(hw, E1000_STATUS); + data &= ~E1000_STATUS_LAN_INIT_DONE; + E1000_WRITE_REG(hw, E1000_STATUS, data); + + /* + * Make sure HW does not configure LCD from PHY + * extended configuration before SW configuration + */ + data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); + if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) + goto out; + + cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE); + cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; + cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; + if (!cnf_size) + goto out; + + cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; + cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; + + /* + * Configure LCD from extended configuration + * region. + */ + + /* cnf_base_addr is in DWORD */ + word_addr = (u16)(cnf_base_addr << 1); + + for (i = 0; i < cnf_size; i++) { + ret_val = nvm->ops.read(hw, + (word_addr + i * 2), + 1, + ®_data); + if (ret_val) + goto out; + + ret_val = nvm->ops.read(hw, + (word_addr + i * 2 + 1), + 1, + ®_addr); + if (ret_val) + goto out; + + /* Save off the PHY page for future writes. */ + if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { + phy_page = reg_data; + continue; + } + + reg_addr |= phy_page; + + ret_val = phy->ops.write_reg(hw, + (u32)reg_addr, + reg_data); + if (ret_val) + goto out; + } + } + +out: + return ret_val; +} + +/** + * e1000_get_phy_info_ich8lan - Calls appropriate PHY type get_phy_info + * @hw: pointer to the HW structure + * + * Wrapper for calling the get_phy_info routines for the appropriate phy type. + * This is a function pointer entry point called by drivers + * or other shared routines. + **/ +static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = -E1000_ERR_PHY_TYPE; + + DEBUGFUNC("e1000_get_phy_info_ich8lan"); + + switch (hw->phy.type) { + case e1000_phy_ife: + ret_val = e1000_get_phy_info_ife_ich8lan(hw); + break; + case e1000_phy_igp_3: + case e1000_phy_bm: + ret_val = e1000_get_phy_info_igp(hw); + break; + default: + break; + } + + return ret_val; +} + +/** + * e1000_get_phy_info_ife_ich8lan - Retrieves various IFE PHY states + * @hw: pointer to the HW structure + * + * Populates "phy" structure with various feature states. + * This function is only called by other family-specific + * routines. + **/ +static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + bool link; + + DEBUGFUNC("e1000_get_phy_info_ife_ich8lan"); + + ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) { + DEBUGOUT("Phy info is only valid if link is up\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data); + if (ret_val) + goto out; + phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE) + ? false : true; + + if (phy->polarity_correction) { + ret_val = e1000_check_polarity_ife_ich8lan(hw); + if (ret_val) + goto out; + } else { + /* Polarity is forced */ + phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY) + ? e1000_rev_polarity_reversed + : e1000_rev_polarity_normal; + } + + ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); + if (ret_val) + goto out; + + phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false; + + /* The following parameters are undefined for 10/100 operation. */ + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + +out: + return ret_val; +} + +/** + * e1000_check_polarity_ife_ich8lan - Check cable polarity for IFE PHY + * @hw: pointer to the HW structure + * + * Polarity is determined on the polarity reversal feature being enabled. + * This function is only called by other family-specific + * routines. + **/ +static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data, offset, mask; + + DEBUGFUNC("e1000_check_polarity_ife_ich8lan"); + + /* + * Polarity is determined based on the reversal feature + * being enabled. + */ + if (phy->polarity_correction) { + offset = IFE_PHY_EXTENDED_STATUS_CONTROL; + mask = IFE_PESC_POLARITY_REVERSED; + } else { + offset = IFE_PHY_SPECIAL_CONTROL; + mask = IFE_PSC_FORCE_POLARITY; + } + + ret_val = phy->ops.read_reg(hw, offset, &phy_data); + + if (!ret_val) + phy->cable_polarity = (phy_data & mask) + ? e1000_rev_polarity_reversed + : e1000_rev_polarity_normal; + + return ret_val; +} + +/** + * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state + * @hw: pointer to the HW structure + * @active: true to enable LPLU, false to disable + * + * Sets the LPLU D0 state according to the active flag. When + * activating LPLU this function also disables smart speed + * and vice versa. LPLU will not be activated unless the + * device autonegotiation advertisement meets standards of + * either 10 or 10/100 or 10/100/1000 at all duplexes. + * This is a function pointer entry point only called by + * PHY setup routines. + **/ +static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, + bool active) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 phy_ctrl; + s32 ret_val = E1000_SUCCESS; + u16 data; + + DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan"); + + if (phy->type == e1000_phy_ife) + goto out; + + phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); + + if (active) { + phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; + E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); + + /* + * Call gig speed drop workaround on LPLU before accessing + * any PHY registers + */ + if ((hw->mac.type == e1000_ich8lan) && + (hw->phy.type == e1000_phy_igp_3)) + e1000_gig_downshift_workaround_ich8lan(hw); + + /* When LPLU is enabled, we should disable SmartSpeed */ + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } else { + phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; + E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); + + /* + * LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. + */ + if (phy->smart_speed == e1000_smart_speed_on) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data |= IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } else if (phy->smart_speed == e1000_smart_speed_off) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } + } + +out: + return ret_val; +} + +/** + * e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state + * @hw: pointer to the HW structure + * @active: true to enable LPLU, false to disable + * + * Sets the LPLU D3 state according to the active flag. When + * activating LPLU this function also disables smart speed + * and vice versa. LPLU will not be activated unless the + * device autonegotiation advertisement meets standards of + * either 10 or 10/100 or 10/100/1000 at all duplexes. + * This is a function pointer entry point only called by + * PHY setup routines. + **/ +static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, + bool active) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 phy_ctrl; + s32 ret_val = E1000_SUCCESS; + u16 data; + + DEBUGFUNC("e1000_set_d3_lplu_state_ich8lan"); + + phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); + + if (!active) { + phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; + E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); + /* + * LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. + */ + if (phy->smart_speed == e1000_smart_speed_on) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data |= IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } else if (phy->smart_speed == e1000_smart_speed_off) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } + } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || + (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || + (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { + phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; + E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); + + /* + * Call gig speed drop workaround on LPLU before accessing + * any PHY registers + */ + if ((hw->mac.type == e1000_ich8lan) && + (hw->phy.type == e1000_phy_igp_3)) + e1000_gig_downshift_workaround_ich8lan(hw); + + /* When LPLU is enabled, we should disable SmartSpeed */ + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + } + +out: + return ret_val; +} + +/** + * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 + * @hw: pointer to the HW structure + * @bank: pointer to the variable that returns the active bank + * + * Reads signature byte from the NVM using the flash access registers. + **/ +static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) +{ + s32 ret_val = E1000_SUCCESS; + struct e1000_nvm_info *nvm = &hw->nvm; + /* flash bank size is in words */ + u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); + u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; + u8 bank_high_byte = 0; + + if (hw->mac.type != e1000_ich10lan) { + if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL) + *bank = 1; + else + *bank = 0; + } else if (hw->dev_spec != NULL) { + /* + * Make sure the signature for bank 0 is valid, + * if not check for bank1 + */ + e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte); + if ((bank_high_byte & 0xC0) == 0x80) { + *bank = 0; + } else { + /* + * find if segment 1 is valid by verifying + * bit 15:14 = 10b in word 0x13 + */ + e1000_read_flash_byte_ich8lan(hw, + act_offset + bank1_offset, + &bank_high_byte); + + /* bank1 has a valid signature equivalent to SEC1V */ + if ((bank_high_byte & 0xC0) == 0x80) { + *bank = 1; + } else { + DEBUGOUT("ERROR: EEPROM not present\n"); + ret_val = -E1000_ERR_NVM; + } + } + } else { + DEBUGOUT("DEV SPEC is NULL\n"); + ret_val = -E1000_ERR_NVM; + } + + return ret_val; +} + +/** + * e1000_read_nvm_ich8lan - Read word(s) from the NVM + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the word(s) to read. + * @words: Size of data to read in words + * @data: Pointer to the word(s) to read at offset. + * + * Reads a word(s) from the NVM using the flash access registers. + **/ +static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec; + u32 act_offset; + s32 ret_val = E1000_SUCCESS; + u32 bank = 0; + u16 i, word; + + DEBUGFUNC("e1000_read_nvm_ich8lan"); + + dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; + + if (!dev_spec) { + DEBUGOUT("dev_spec pointer is set to NULL.\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + if (ret_val != E1000_SUCCESS) + goto out; + + act_offset = (bank) ? nvm->flash_bank_size : 0; + act_offset += offset; + + for (i = 0; i < words; i++) { + if ((dev_spec->shadow_ram) && + (dev_spec->shadow_ram[offset+i].modified)) { + data[i] = dev_spec->shadow_ram[offset+i].value; + } else { + ret_val = e1000_read_flash_word_ich8lan(hw, + act_offset + i, + &word); + if (ret_val) + break; + data[i] = word; + } + } + + nvm->ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_flash_cycle_init_ich8lan - Initialize flash + * @hw: pointer to the HW structure + * + * This function does initial flash setup so that a new read/write/erase cycle + * can be started. + **/ +static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) +{ + union ich8_hws_flash_status hsfsts; + s32 ret_val = -E1000_ERR_NVM; + s32 i = 0; + + DEBUGFUNC("e1000_flash_cycle_init_ich8lan"); + + ret_val = e1000e_map_nvram(hw); + if (ret_val) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return ret_val; + } + + hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); + + /* Check if the flash descriptor is valid */ + if (hsfsts.hsf_status.fldesvalid == 0) { + DEBUGOUT("Flash descriptor invalid. " + "SW Sequencing must be used."); + goto out; + } + + /* Clear FCERR and DAEL in hw status by writing 1 */ + hsfsts.hsf_status.flcerr = 1; + hsfsts.hsf_status.dael = 1; + + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); + + /* + * Either we should have a hardware SPI cycle in progress + * bit to check against, in order to start a new cycle or + * FDONE bit should be changed in the hardware so that it + * is 1 after hardware reset, which can then be used as an + * indication whether a cycle is in progress or has been + * completed. + */ + + if (hsfsts.hsf_status.flcinprog == 0) { + /* + * There is no cycle running at present, + * so we can start a cycle. + * Begin by setting Flash Cycle Done. + */ + hsfsts.hsf_status.flcdone = 1; + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); + ret_val = E1000_SUCCESS; + } else { + /* + * Otherwise poll for sometime so the current + * cycle has a chance to end before giving up. + */ + for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { + hsfsts.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcinprog == 0) { + ret_val = E1000_SUCCESS; + break; + } + usec_delay(1); + } + if (ret_val == E1000_SUCCESS) { + /* + * Successful in waiting for previous cycle to timeout, + * now set the Flash Cycle Done. + */ + hsfsts.hsf_status.flcdone = 1; + E1000_WRITE_FLASH_REG16(hw, + ICH_FLASH_HSFSTS, + hsfsts.regval); + } else { + DEBUGOUT("Flash controller busy, cannot get access"); + } + } + +out: + e1000e_unmap_nvram(hw); + return ret_val; +} + +/** + * e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) + * @hw: pointer to the HW structure + * @timeout: maximum time to wait for completion + * + * This function starts a flash cycle and waits for its completion. + **/ +static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) +{ + union ich8_hws_flash_ctrl hsflctl; + union ich8_hws_flash_status hsfsts; + s32 ret_val = -E1000_ERR_NVM; + u32 i = 0; + + DEBUGFUNC("e1000_flash_cycle_ich8lan"); + + ret_val = e1000e_map_nvram(hw); + if (ret_val) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return ret_val; + } + + /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ + hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + hsflctl.hsf_ctrl.flcgo = 1; + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + + /* wait till FDONE bit is set to 1 */ + do { + hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcdone == 1) + break; + usec_delay(1); + } while (i++ < timeout); + + if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) + ret_val = E1000_SUCCESS; + + e1000e_unmap_nvram(hw); + + return ret_val; +} + +/** + * e1000_read_flash_word_ich8lan - Read word from flash + * @hw: pointer to the HW structure + * @offset: offset to data location + * @data: pointer to the location for storing the data + * + * Reads the flash word at offset into data. Offset is converted + * to bytes before read. + **/ +static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, + u16 *data) +{ + s32 ret_val; + + DEBUGFUNC("e1000_read_flash_word_ich8lan"); + + if (!data) { + ret_val = -E1000_ERR_NVM; + goto out; + } + + /* Must convert offset into bytes. */ + offset <<= 1; + + ret_val = e1000_read_flash_data_ich8lan(hw, offset, 2, data); + +out: + return ret_val; +} + +/** + * e1000_read_flash_byte_ich8lan - Read byte from flash + * @hw: pointer to the HW structure + * @offset: The offset of the byte to read. + * @data: Pointer to a byte to store the value read. + * + * Reads a single byte from the NVM using the flash access registers. + **/ +static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, + u8* data) +{ + s32 ret_val = E1000_SUCCESS; + u16 word = 0; + + ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); + if (ret_val) + goto out; + + *data = (u8)word; + +out: + return ret_val; +} + +/** + * e1000_read_flash_data_ich8lan - Read byte or word from NVM + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the byte or word to read. + * @size: Size of data to read, 1=byte 2=word + * @data: Pointer to the word to store the value read. + * + * Reads a byte or word from the NVM using the flash access registers. + **/ +static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + u8 size, u16* data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + u32 flash_linear_addr; + u32 flash_data = 0; + s32 ret_val = -E1000_ERR_NVM; + u8 count = 0; + + DEBUGFUNC("e1000_read_flash_data_ich8lan"); + + ret_val = e1000e_map_nvram(hw); + if (ret_val) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return ret_val; + } + + if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + goto out; + + flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + + hw->nvm.flash_base_addr; + + do { + usec_delay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val != E1000_SUCCESS) + break; + + hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ + hsflctl.hsf_ctrl.fldbcount = size - 1; + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); + + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_READ_COMMAND_TIMEOUT); + + /* + * Check if FCERR is set to 1, if set to 1, clear it + * and try the whole sequence a few more times, else + * read in (shift in) the Flash Data0, the order is + * least significant byte first msb to lsb + */ + if (ret_val == E1000_SUCCESS) { + flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0); + if (size == 1) { + *data = (u8)(flash_data & 0x000000FF); + } else if (size == 2) { + *data = (u16)(flash_data & 0x0000FFFF); + } + break; + } else { + /* + * If we've gotten here, then things are probably + * completely hosed, but if the error condition is + * detected, it won't hurt to give it another try... + * ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr == 1) { + /* Repeat for some time before giving up. */ + continue; + } else if (hsfsts.hsf_status.flcdone == 0) { + DEBUGOUT("Timeout error - flash cycle " + "did not complete."); + break; + } + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); + +out: + e1000e_unmap_nvram(hw); + return ret_val; +} + +/** + * e1000_write_nvm_ich8lan - Write word(s) to the NVM + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the word(s) to write. + * @words: Size of data to write in words + * @data: Pointer to the word(s) to write at offset. + * + * Writes a byte or word to the NVM using the flash access registers. + **/ +static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec; + s32 ret_val = E1000_SUCCESS; + u16 i; + + DEBUGFUNC("e1000_write_nvm_ich8lan"); + + dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; + + if (!dev_spec) { + DEBUGOUT("dev_spec pointer is set to NULL.\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + for (i = 0; i < words; i++) { + dev_spec->shadow_ram[offset+i].modified = true; + dev_spec->shadow_ram[offset+i].value = data[i]; + } + + nvm->ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM + * @hw: pointer to the HW structure + * + * The NVM checksum is updated by calling the generic update_nvm_checksum, + * which writes the checksum to the shadow ram. The changes in the shadow + * ram are then committed to the EEPROM by processing each bank at a time + * checking for the modified bit and writing only the pending changes. + * After a successful commit, the shadow ram is cleared and is ready for + * future writes. + **/ +static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec; + u32 i, act_offset, new_bank_offset, old_bank_offset, bank; + s32 ret_val; + u16 data; + + DEBUGFUNC("e1000_update_nvm_checksum_ich8lan"); + + dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; + + ret_val = e1000_update_nvm_checksum_generic(hw); + if (ret_val) + goto out; + + if (nvm->type != e1000_nvm_flash_sw) + goto out; + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + /* + * We're writing to the opposite bank so if we're on bank 1, + * write to bank 0 etc. We also need to erase the segment that + * is going to be written + */ + ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + if (ret_val != E1000_SUCCESS) + goto out; + + if (bank == 0) { + new_bank_offset = nvm->flash_bank_size; + old_bank_offset = 0; + e1000_erase_flash_bank_ich8lan(hw, 1); + } else { + old_bank_offset = nvm->flash_bank_size; + new_bank_offset = 0; + e1000_erase_flash_bank_ich8lan(hw, 0); + } + + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { + /* + * Determine whether to write the value stored + * in the other NVM bank or a modified value stored + * in the shadow RAM + */ + if (dev_spec->shadow_ram[i].modified) { + data = dev_spec->shadow_ram[i].value; + } else { + e1000_read_flash_word_ich8lan(hw, + i + old_bank_offset, + &data); + } + + /* + * If the word is 0x13, then make sure the signature bits + * (15:14) are 11b until the commit has completed. + * This will allow us to write 10b which indicates the + * signature is valid. We want to do this after the write + * has completed so that we don't mark the segment valid + * while the write is still in progress + */ + if (i == E1000_ICH_NVM_SIG_WORD) + data |= E1000_ICH_NVM_SIG_MASK; + + /* Convert offset to bytes. */ + act_offset = (i + new_bank_offset) << 1; + + usec_delay(100); + /* Write the bytes to the new bank. */ + ret_val = e1000_retry_write_flash_byte_ich8lan(hw, + act_offset, + (u8)data); + if (ret_val) + break; + + usec_delay(100); + ret_val = e1000_retry_write_flash_byte_ich8lan(hw, + act_offset + 1, + (u8)(data >> 8)); + if (ret_val) + break; + } + + /* + * Don't bother writing the segment valid bits if sector + * programming failed. + */ + if (ret_val) { + DEBUGOUT("Flash commit failed.\n"); + nvm->ops.release(hw); + goto out; + } + + /* + * Finally validate the new segment by setting bit 15:14 + * to 10b in word 0x13 , this can be done without an + * erase as well since these bits are 11 to start with + * and we need to change bit 14 to 0b + */ + act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; + e1000_read_flash_word_ich8lan(hw, act_offset, &data); + data &= 0xBFFF; + ret_val = e1000_retry_write_flash_byte_ich8lan(hw, + act_offset * 2 + 1, + (u8)(data >> 8)); + if (ret_val) { + nvm->ops.release(hw); + goto out; + } + + /* + * And invalidate the previously valid segment by setting + * its signature word (0x13) high_byte to 0b. This can be + * done without an erase because flash erase sets all bits + * to 1's. We can write 1's to 0's without an erase + */ + act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; + ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); + if (ret_val) { + nvm->ops.release(hw); + goto out; + } + + /* Great! Everything worked, we can now clear the cached entries. */ + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { + dev_spec->shadow_ram[i].modified = false; + dev_spec->shadow_ram[i].value = 0xFFFF; + } + + nvm->ops.release(hw); + + /* + * Reload the EEPROM, or else modifications will not appear + * until after the next adapter reset. + */ + nvm->ops.reload(hw); + msec_delay(10); + +out: + return ret_val; +} + +/** + * e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. + * If the bit is 0, that the EEPROM had been modified, but the checksum was + * not calculated, in which case we need to calculate the checksum and set + * bit 6. + **/ +static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 data; + + DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan"); + + /* + * Read 0x19 and check bit 6. If this bit is 0, the checksum + * needs to be fixed. This bit is an indication that the NVM + * was prepared by OEM software and did not calculate the + * checksum...a likely scenario. + */ + ret_val = hw->nvm.ops.read(hw, 0x19, 1, &data); + if (ret_val) + goto out; + + if ((data & 0x40) == 0) { + data |= 0x40; + ret_val = hw->nvm.ops.write(hw, 0x19, 1, &data); + if (ret_val) + goto out; + ret_val = hw->nvm.ops.update(hw); + if (ret_val) + goto out; + } + + ret_val = e1000_validate_nvm_checksum_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_write_flash_data_ich8lan - Writes bytes to the NVM + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the byte/word to read. + * @size: Size of data to read, 1=byte 2=word + * @data: The byte(s) to write to the NVM. + * + * Writes one/two bytes to the NVM using the flash access registers. + **/ +static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + u8 size, u16 data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + u32 flash_linear_addr; + u32 flash_data = 0; + s32 ret_val = -E1000_ERR_NVM; + u8 count = 0; + + DEBUGFUNC("e1000_write_ich8_data"); + + ret_val = e1000e_map_nvram(hw); + if (ret_val) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return ret_val; + } + + if (size < 1 || size > 2 || data > size * 0xff || + offset > ICH_FLASH_LINEAR_ADDR_MASK) + goto out; + + flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + + hw->nvm.flash_base_addr; + + do { + usec_delay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val != E1000_SUCCESS) + break; + + hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ + hsflctl.hsf_ctrl.fldbcount = size -1; + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); + + if (size == 1) + flash_data = (u32)data & 0x00FF; + else + flash_data = (u32)data; + + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data); + + /* + * check if FCERR is set to 1 , if set to 1, clear it + * and try the whole sequence a few more times else done + */ + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_WRITE_COMMAND_TIMEOUT); + if (ret_val == E1000_SUCCESS) { + break; + } else { + /* + * If we're here, then things are most likely + * completely hosed, but if the error condition + * is detected, it won't hurt to give it another + * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr == 1) { + /* Repeat for some time before giving up. */ + continue; + } else if (hsfsts.hsf_status.flcdone == 0) { + DEBUGOUT("Timeout error - flash cycle " + "did not complete."); + break; + } + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); + +out: + e1000e_unmap_nvram(hw); + return ret_val; +} + +/** + * e1000_write_flash_byte_ich8lan - Write a single byte to NVM + * @hw: pointer to the HW structure + * @offset: The index of the byte to read. + * @data: The byte to write to the NVM. + * + * Writes a single byte to the NVM using the flash access registers. + **/ +static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, + u8 data) +{ + u16 word = (u16)data; + + DEBUGFUNC("e1000_write_flash_byte_ich8lan"); + + return e1000_write_flash_data_ich8lan(hw, offset, 1, word); +} + +/** + * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM + * @hw: pointer to the HW structure + * @offset: The offset of the byte to write. + * @byte: The byte to write to the NVM. + * + * Writes a single byte to the NVM using the flash access registers. + * Goes through a retry algorithm before giving up. + **/ +static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, + u32 offset, u8 byte) +{ + s32 ret_val; + u16 program_retries; + + DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan"); + + ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); + if (ret_val == E1000_SUCCESS) + goto out; + + for (program_retries = 0; program_retries < 100; program_retries++) { + DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset); + usec_delay(100); + ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); + if (ret_val == E1000_SUCCESS) + break; + } + if (program_retries == 100) { + ret_val = -E1000_ERR_NVM; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM + * @hw: pointer to the HW structure + * @bank: 0 for first bank, 1 for second bank, etc. + * + * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. + * bank N is 4096 * N + flash_reg_addr. + **/ +static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + u32 flash_linear_addr; + /* bank size is in 16bit words - adjust to bytes */ + u32 flash_bank_size = nvm->flash_bank_size * 2; + s32 ret_val = E1000_SUCCESS; + s32 count = 0; + s32 j, iteration, sector_size; + + DEBUGFUNC("e1000_erase_flash_bank_ich8lan"); + + ret_val = e1000e_map_nvram(hw); + if (ret_val) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return ret_val; + } + + hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); + + /* + * Determine HW Sector size: Read BERASE bits of hw flash status + * register + * 00: The Hw sector is 256 bytes, hence we need to erase 16 + * consecutive sectors. The start index for the nth Hw sector + * can be calculated as = bank * 4096 + n * 256 + * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. + * The start index for the nth Hw sector can be calculated + * as = bank * 4096 + * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 + * (ich9 only, otherwise error condition) + * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 + */ + switch (hsfsts.hsf_status.berasesz) { + case 0: + /* Hw sector size 256 */ + sector_size = ICH_FLASH_SEG_SIZE_256; + iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; + break; + case 1: + sector_size = ICH_FLASH_SEG_SIZE_4K; + iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K; + break; + case 2: + if (hw->mac.type == e1000_ich9lan) { + sector_size = ICH_FLASH_SEG_SIZE_8K; + iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K; + } else { + ret_val = -E1000_ERR_NVM; + goto out; + } + break; + case 3: + sector_size = ICH_FLASH_SEG_SIZE_64K; + iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K; + break; + default: + ret_val = -E1000_ERR_NVM; + goto out; + } + + /* Start with the base address, then add the sector offset. */ + flash_linear_addr = hw->nvm.flash_base_addr; + flash_linear_addr += (bank) ? (sector_size * iteration) : 0; + + for (j = 0; j < iteration ; j++) { + do { + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val) + goto out; + + /* + * Write a value 11 (block Erase) in Flash + * Cycle field in hw flash control + */ + hsflctl.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFCTL); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; + E1000_WRITE_FLASH_REG16(hw, + ICH_FLASH_HSFCTL, + hsflctl.regval); + + /* + * Write the last 24 bits of an index within the + * block into Flash Linear address field in Flash + * Address. + */ + flash_linear_addr += (j * sector_size); + E1000_WRITE_FLASH_REG(hw, + ICH_FLASH_FADDR, + flash_linear_addr); + + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_ERASE_COMMAND_TIMEOUT); + if (ret_val == E1000_SUCCESS) { + break; + } else { + /* + * Check if FCERR is set to 1. If 1, + * clear it and try the whole sequence + * a few more times else Done + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr == 1) { + /* + * repeat for some time before + * giving up + */ + continue; + } else if (hsfsts.hsf_status.flcdone == 0) + goto out; + } + } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); + } + +out: + e1000e_unmap_nvram(hw); + return ret_val; +} + +/** + * e1000_valid_led_default_ich8lan - Set the default LED settings + * @hw: pointer to the HW structure + * @data: Pointer to the LED settings + * + * Reads the LED default settings from the NVM to data. If the NVM LED + * settings is all 0's or F's, set the LED default to a valid LED default + * setting. + **/ +static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) +{ + s32 ret_val; + + DEBUGFUNC("e1000_valid_led_default_ich8lan"); + + ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + + if (*data == ID_LED_RESERVED_0000 || + *data == ID_LED_RESERVED_FFFF) + *data = ID_LED_DEFAULT_ICH8LAN; + +out: + return ret_val; +} + +/** + * e1000_get_bus_info_ich8lan - Get/Set the bus type and width + * @hw: pointer to the HW structure + * + * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability + * register, so the the bus width is hard coded. + **/ +static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + s32 ret_val; + + DEBUGFUNC("e1000_get_bus_info_ich8lan"); + + ret_val = e1000_get_bus_info_pcie_generic(hw); + + /* + * ICH devices are "PCI Express"-ish. They have + * a configuration space, but do not contain + * PCI Express Capability registers, so bus width + * must be hardcoded. + */ + if (bus->width == e1000_bus_width_unknown) + bus->width = e1000_bus_width_pcie_x1; + + return ret_val; +} + +/** + * e1000_reset_hw_ich8lan - Reset the hardware + * @hw: pointer to the HW structure + * + * Does a full reset of the hardware which includes a reset of the PHY and + * MAC. + **/ +static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) +{ + u32 ctrl, icr, kab; + s32 ret_val; + + DEBUGFUNC("e1000_reset_hw_ich8lan"); + + /* + * Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = e1000_disable_pcie_master_generic(hw); + if (ret_val) { + DEBUGOUT("PCI-E Master disable polling has failed.\n"); + } + + DEBUGOUT("Masking off all interrupts\n"); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + + /* + * Disable the Transmit and Receive units. Then delay to allow + * any pending transactions to complete before we hit the MAC + * with the global reset. + */ + E1000_WRITE_REG(hw, E1000_RCTL, 0); + E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); + E1000_WRITE_FLUSH(hw); + + msec_delay(10); + + /* Workaround for ICH8 bit corruption issue in FIFO memory */ + if (hw->mac.type == e1000_ich8lan) { + /* Set Tx and Rx buffer allocation to 8k apiece. */ + E1000_WRITE_REG(hw, E1000_PBA, E1000_PBA_8K); + /* Set Packet Buffer Size to 16k. */ + E1000_WRITE_REG(hw, E1000_PBS, E1000_PBS_16K); + } + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + + if (!hw->phy.ops.check_reset_block(hw) && !hw->phy.reset_disable) { + /* + * PHY HW reset requires MAC CORE reset at the same + * time to make sure the interface between MAC and the + * external PHY is reset. + */ + ctrl |= E1000_CTRL_PHY_RST; + } + ret_val = e1000_acquire_swflag_ich8lan(hw); + DEBUGOUT("Issuing a global reset to ich8lan"); + E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST)); + msec_delay(20); + + ret_val = e1000_get_auto_rd_done_generic(hw); + if (ret_val) { + /* + * When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ + DEBUGOUT("Auto Read Done did not complete\n"); + } + + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + icr = E1000_READ_REG(hw, E1000_ICR); + + kab = E1000_READ_REG(hw, E1000_KABGTXD); + kab |= E1000_KABGTXD_BGSQLBIAS; + E1000_WRITE_REG(hw, E1000_KABGTXD, kab); + + return ret_val; +} + +/** + * e1000_init_hw_ich8lan - Initialize the hardware + * @hw: pointer to the HW structure + * + * Prepares the hardware for transmit and receive by doing the following: + * - initialize hardware bits + * - initialize LED identification + * - setup receive address registers + * - setup flow control + * - setup transmit descriptors + * - clear statistics + **/ +static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 ctrl_ext, txdctl, snoop; + s32 ret_val; + u16 i; + + DEBUGFUNC("e1000_init_hw_ich8lan"); + + e1000_initialize_hw_bits_ich8lan(hw); + + /* Initialize identification LED */ + ret_val = e1000_id_led_init_generic(hw); + if (ret_val) { + DEBUGOUT("Error initializing identification LED\n"); + /* This is not fatal and we should not stop init due to this */ + } + + /* Setup the receive address. */ + e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); + + /* Zero out the Multicast HASH table */ + DEBUGOUT("Zeroing the MTA\n"); + for (i = 0; i < mac->mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + + /* Setup link and flow control */ + ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy for both queues */ + txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); + txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB; + txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | + E1000_TXDCTL_MAX_TX_DESC_PREFETCH; + E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); + txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1)); + txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB; + txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | + E1000_TXDCTL_MAX_TX_DESC_PREFETCH; + E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl); + + /* + * ICH8 has opposite polarity of no_snoop bits. + * By default, we should use snoop behavior. + */ + if (mac->type == e1000_ich8lan) + snoop = PCIE_ICH8_SNOOP_ALL; + else + snoop = (u32)~(PCIE_NO_SNOOP_ALL); + e1000_set_pcie_no_snoop_generic(hw, snoop); + + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_RO_DIS; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + + /* + * Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. + */ + e1000_clear_hw_cntrs_ich8lan(hw); + + return ret_val; +} +/** + * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits + * @hw: pointer to the HW structure + * + * Sets/Clears required hardware bits necessary for correctly setting up the + * hardware for transmit and receive. + **/ +static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) +{ + u32 reg; + + DEBUGFUNC("e1000_initialize_hw_bits_ich8lan"); + + if (hw->mac.disable_hw_init_bits) + goto out; + + /* Extended Device Control */ + reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + + /* Transmit Descriptor Control 0 */ + reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); + + /* Transmit Descriptor Control 1 */ + reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); + + /* Transmit Arbitration Control 0 */ + reg = E1000_READ_REG(hw, E1000_TARC(0)); + if (hw->mac.type == e1000_ich8lan) + reg |= (1 << 28) | (1 << 29); + reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27); + E1000_WRITE_REG(hw, E1000_TARC(0), reg); + + /* Transmit Arbitration Control 1 */ + reg = E1000_READ_REG(hw, E1000_TARC(1)); + if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) + reg &= ~(1 << 28); + else + reg |= (1 << 28); + reg |= (1 << 24) | (1 << 26) | (1 << 30); + E1000_WRITE_REG(hw, E1000_TARC(1), reg); + + /* Device Status */ + if (hw->mac.type == e1000_ich8lan) { + reg = E1000_READ_REG(hw, E1000_STATUS); + reg &= ~(1 << 31); + E1000_WRITE_REG(hw, E1000_STATUS, reg); + } + +out: + return; +} + +/** + * e1000_setup_link_ich8lan - Setup flow control and link settings + * @hw: pointer to the HW structure + * + * Determines which flow control settings to use, then configures flow + * control. Calls the appropriate media-specific link configuration + * function. Assuming the adapter has a valid link partner, a valid link + * should be established. Assumes the hardware has previously been reset + * and the transmitter and receiver are not enabled. + **/ +static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_setup_link_ich8lan"); + + if (hw->phy.ops.check_reset_block(hw)) + goto out; + + /* + * ICH parts do not have a word in the NVM to determine + * the default flow control setting, so we explicitly + * set it to full. + */ + if (hw->fc.type == e1000_fc_default) + hw->fc.type = e1000_fc_full; + + hw->fc.original_type = hw->fc.type; + + DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type); + + /* Continue to configure the copper link. */ + ret_val = hw->mac.ops.setup_physical_interface(hw); + if (ret_val) + goto out; + + E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); + + ret_val = e1000_set_fc_watermarks_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface + * @hw: pointer to the HW structure + * + * Configures the kumeran interface to the PHY to wait the appropriate time + * when polling the PHY, then call the generic setup_copper_link to finish + * configuring the copper link. + **/ +static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) +{ + u32 ctrl; + s32 ret_val; + u16 reg_data; + + DEBUGFUNC("e1000_setup_copper_link_ich8lan"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + /* + * Set the mac to wait the maximum time between each iteration + * and increase the max iterations when polling the phy; + * this fixes erroneous timeouts at 10Mbps. + */ + ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 4), + 0xFFFF); + if (ret_val) + goto out; + ret_val = e1000_read_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), + ®_data); + if (ret_val) + goto out; + reg_data |= 0x3F; + ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), + reg_data); + if (ret_val) + goto out; + + if (hw->phy.type == e1000_phy_igp_3) { + ret_val = e1000_copper_link_setup_igp(hw); + if (ret_val) + goto out; + } else if (hw->phy.type == e1000_phy_bm) { + ret_val = e1000_copper_link_setup_m88(hw); + if (ret_val) + goto out; + } + + if (hw->phy.type == e1000_phy_ife) { + ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, + ®_data); + if (ret_val) + goto out; + + reg_data &= ~IFE_PMC_AUTO_MDIX; + + switch (hw->phy.mdix) { + case 1: + reg_data &= ~IFE_PMC_FORCE_MDIX; + break; + case 2: + reg_data |= IFE_PMC_FORCE_MDIX; + break; + case 0: + default: + reg_data |= IFE_PMC_AUTO_MDIX; + break; + } + ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, + reg_data); + if (ret_val) + goto out; + } + ret_val = e1000_setup_copper_link_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_get_link_up_info_ich8lan - Get current link speed and duplex + * @hw: pointer to the HW structure + * @speed: pointer to store current link speed + * @duplex: pointer to store the current link duplex + * + * Calls the generic get_speed_and_duplex to retrieve the current link + * information and then calls the Kumeran lock loss workaround for links at + * gigabit speeds. + **/ +static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, + u16 *duplex) +{ + s32 ret_val; + + DEBUGFUNC("e1000_get_link_up_info_ich8lan"); + + ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); + if (ret_val) + goto out; + + if ((hw->mac.type == e1000_ich8lan) && + (hw->phy.type == e1000_phy_igp_3) && + (*speed == SPEED_1000)) { + ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw); + } + +out: + return ret_val; +} + +/** + * e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround + * @hw: pointer to the HW structure + * + * Work-around for 82566 Kumeran PCS lock loss: + * On link status change (i.e. PCI reset, speed change) and link is up and + * speed is gigabit- + * 0) if workaround is optionally disabled do nothing + * 1) wait 1ms for Kumeran link to come up + * 2) check Kumeran Diagnostic register PCS lock loss bit + * 3) if not set the link is locked (all is good), otherwise... + * 4) reset the PHY + * 5) repeat up to 10 times + * Note: this is only called for IGP3 copper when speed is 1gb. + **/ +static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) +{ + struct e1000_dev_spec_ich8lan *dev_spec; + u32 phy_ctrl; + s32 ret_val = E1000_SUCCESS; + u16 i, data; + bool link; + + DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan"); + + dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; + + if (!dev_spec) { + DEBUGOUT("dev_spec pointer is set to NULL.\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + if (!(dev_spec->kmrn_lock_loss_workaround_enabled)) + goto out; + + /* + * Make sure link is up before proceeding. If not just return. + * Attempting this while link is negotiating fouled up link + * stability + */ + ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); + if (!link) { + ret_val = E1000_SUCCESS; + goto out; + } + + for (i = 0; i < 10; i++) { + /* read once to clear */ + ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); + if (ret_val) + goto out; + /* and again to get new status */ + ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); + if (ret_val) + goto out; + + /* check for PCS lock */ + if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) { + ret_val = E1000_SUCCESS; + goto out; + } + + /* Issue PHY reset */ + hw->phy.ops.reset(hw); + msec_delay_irq(5); + } + /* Disable GigE link negotiation */ + phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); + phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE | + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); + E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); + + /* + * Call gig speed drop workaround on Gig disable before accessing + * any PHY registers + */ + e1000_gig_downshift_workaround_ich8lan(hw); + + /* unable to acquire PCS lock */ + ret_val = -E1000_ERR_PHY; + +out: + return ret_val; +} + +/** + * e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state + * @hw: pointer to the HW structure + * @state: boolean value used to set the current Kumeran workaround state + * + * If ICH8, set the current Kumeran workaround state (enabled - true + * /disabled - false). + **/ +void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, + bool state) +{ + struct e1000_dev_spec_ich8lan *dev_spec; + + DEBUGFUNC("e1000_set_kmrn_lock_loss_workaround_ich8lan"); + + if (hw->mac.type != e1000_ich8lan) { + DEBUGOUT("Workaround applies to ICH8 only.\n"); + goto out; + } + + dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; + + if (!dev_spec) { + DEBUGOUT("dev_spec pointer is set to NULL.\n"); + goto out; + } + + dev_spec->kmrn_lock_loss_workaround_enabled = state; + +out: + return; +} + +/** + * e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3 + * @hw: pointer to the HW structure + * + * Workaround for 82566 power-down on D3 entry: + * 1) disable gigabit link + * 2) write VR power-down enable + * 3) read it back + * Continue if successful, else issue LCD reset and repeat + **/ +void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) +{ + u32 reg; + u16 data; + u8 retry = 0; + + DEBUGFUNC("e1000_igp3_phy_powerdown_workaround_ich8lan"); + + if (hw->phy.type != e1000_phy_igp_3) + goto out; + + /* Try the workaround twice (if needed) */ + do { + /* Disable link */ + reg = E1000_READ_REG(hw, E1000_PHY_CTRL); + reg |= (E1000_PHY_CTRL_GBE_DISABLE | + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); + E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg); + + /* + * Call gig speed drop workaround on Gig disable before + * accessing any PHY registers + */ + if (hw->mac.type == e1000_ich8lan) + e1000_gig_downshift_workaround_ich8lan(hw); + + /* Write VR power-down enable */ + hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); + data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; + hw->phy.ops.write_reg(hw, + IGP3_VR_CTRL, + data | IGP3_VR_CTRL_MODE_SHUTDOWN); + + /* Read it back and test */ + hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); + data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; + if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry) + break; + + /* Issue PHY reset and repeat at most one more time */ + reg = E1000_READ_REG(hw, E1000_CTRL); + E1000_WRITE_REG(hw, E1000_CTRL, reg | E1000_CTRL_PHY_RST); + retry++; + } while (retry); + +out: + return; +} + +/** + * e1000_gig_downshift_workaround_ich8lan - WoL from S5 stops working + * @hw: pointer to the HW structure + * + * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), + * LPLU, Gig disable, MDIC PHY reset): + * 1) Set Kumeran Near-end loopback + * 2) Clear Kumeran Near-end loopback + * Should only be called for ICH8[m] devices with IGP_3 Phy. + **/ +void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 reg_data; + + DEBUGFUNC("e1000_gig_downshift_workaround_ich8lan"); + + if ((hw->mac.type != e1000_ich8lan) || + (hw->phy.type != e1000_phy_igp_3)) + goto out; + + ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, + ®_data); + if (ret_val) + goto out; + reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; + ret_val = e1000_write_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_DIAG_OFFSET, + reg_data); + if (ret_val) + goto out; + reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; + ret_val = e1000_write_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_DIAG_OFFSET, + reg_data); +out: + return; +} + +/** + * e1000_disable_gig_wol_ich8lan - disable gig during WoL + * @hw: pointer to the HW structure + * + * During S0 to Sx transition, it is possible the link remains at gig + * instead of negotiating to a lower speed. Before going to Sx, set + * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation + * to a lower speed. + * + * Should only be called for ICH9 and ICH10 devices. + **/ +void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw) +{ + u32 phy_ctrl; + + if ((hw->mac.type == e1000_ich10lan) || + (hw->mac.type == e1000_ich9lan)) { + phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); + phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | + E1000_PHY_CTRL_GBE_DISABLE; + E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); + } + + return; +} + +/** + * e1000_cleanup_led_ich8lan - Restore the default LED operation + * @hw: pointer to the HW structure + * + * Return the LED back to the default configuration. + **/ +static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_cleanup_led_ich8lan"); + + if (hw->phy.type == e1000_phy_ife) + ret_val = hw->phy.ops.write_reg(hw, + IFE_PHY_SPECIAL_CONTROL_LED, + 0); + else + E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); + + return ret_val; +} + +/** + * e1000_led_on_ich8lan - Turn LEDs on + * @hw: pointer to the HW structure + * + * Turn on the LEDs. + **/ +static s32 e1000_led_on_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_led_on_ich8lan"); + + if (hw->phy.type == e1000_phy_ife) + ret_val = hw->phy.ops.write_reg(hw, + IFE_PHY_SPECIAL_CONTROL_LED, + (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); + else + E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); + + return ret_val; +} + +/** + * e1000_led_off_ich8lan - Turn LEDs off + * @hw: pointer to the HW structure + * + * Turn off the LEDs. + **/ +static s32 e1000_led_off_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_led_off_ich8lan"); + + if (hw->phy.type == e1000_phy_ife) + ret_val = hw->phy.ops.write_reg(hw, + IFE_PHY_SPECIAL_CONTROL_LED, + (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF)); + else + E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); + + return ret_val; +} + +/** + * e1000_get_cfg_done_ich8lan - Read config done bit + * @hw: pointer to the HW structure + * + * Read the management control register for the config done bit for + * completion status. NOTE: silicon which is EEPROM-less will fail trying + * to read the config done bit, so an error is *ONLY* logged and returns + * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon + * would not be able to be reset or change link. + **/ +static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u32 bank = 0; + + e1000_get_cfg_done_generic(hw); + + /* If EEPROM is not marked present, init the IGP 3 PHY manually */ + if (hw->mac.type != e1000_ich10lan) { + if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && + (hw->phy.type == e1000_phy_igp_3)) { + e1000_phy_init_script_igp3(hw); + } + } else { + if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { + /* Maybe we should do a basic Boazman config */ + DEBUGOUT("EEPROM not present\n"); + ret_val = -E1000_ERR_CONFIG; + } + } + + return ret_val; +} + +/** + * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, or wake on lan is not enabled, remove the link. + **/ +static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + struct e1000_mac_info *mac = &hw->mac; + + /* If the management interface is not enabled, then power down */ + if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) + e1000_power_down_phy_copper(hw); + + return; +} + +/** + * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters + * @hw: pointer to the HW structure + * + * Clears hardware counters specific to the silicon family and calls + * clear_hw_cntrs_generic to clear all general purpose counters. + **/ +static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) +{ + volatile u32 temp; + + DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan"); + + e1000_clear_hw_cntrs_base_generic(hw); + + temp = E1000_READ_REG(hw, E1000_ALGNERRC); + temp = E1000_READ_REG(hw, E1000_RXERRC); + temp = E1000_READ_REG(hw, E1000_TNCRS); + temp = E1000_READ_REG(hw, E1000_CEXTERR); + temp = E1000_READ_REG(hw, E1000_TSCTC); + temp = E1000_READ_REG(hw, E1000_TSCTFC); + + temp = E1000_READ_REG(hw, E1000_MGTPRC); + temp = E1000_READ_REG(hw, E1000_MGTPDC); + temp = E1000_READ_REG(hw, E1000_MGTPTC); + + temp = E1000_READ_REG(hw, E1000_IAC); + temp = E1000_READ_REG(hw, E1000_ICRXOC); +} + --- linux-2.6.27.orig/ubuntu/e1000e/BOM +++ linux-2.6.27/ubuntu/e1000e/BOM @@ -0,0 +1,7 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=42302 +Current Version: 0.4.7.1 +Comments: + +Changed Kconfig option to E1000E_NEW. Disabled in-kernel driver. Make sure +to also include E1000E_ENABLED config option, since it will alter some +things in e1000 driver (we want that). --- linux-2.6.27.orig/ubuntu/e1000e/e1000_mac.h +++ linux-2.6.27/ubuntu/e1000e/e1000_mac.h @@ -0,0 +1,86 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_MAC_H_ +#define _E1000_MAC_H_ + +/* + * Functions that should not be called directly from drivers but can be used + * by other files in this 'shared code' + */ +void e1000_init_mac_ops_generic(struct e1000_hw *hw); +s32 e1000_blink_led_generic(struct e1000_hw *hw); +s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw); +s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw); +s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw); +s32 e1000_cleanup_led_generic(struct e1000_hw *hw); +s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw); +s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw); +s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw); +s32 e1000_force_mac_fc_generic(struct e1000_hw *hw); +s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw); +s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw); +s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); +s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, + u16 *duplex); +s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, + u16 *speed, u16 *duplex); +s32 e1000_id_led_init_generic(struct e1000_hw *hw); +s32 e1000_led_on_generic(struct e1000_hw *hw); +s32 e1000_led_off_generic(struct e1000_hw *hw); +void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count, + u32 rar_used_count, u32 rar_count); +s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); +s32 e1000_set_default_fc_generic(struct e1000_hw *hw); +s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); +s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); +s32 e1000_setup_led_generic(struct e1000_hw *hw); +s32 e1000_setup_link_generic(struct e1000_hw *hw); +s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); +s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, + u32 offset, u8 data); + +u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); + +void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw); +void e1000_clear_vfta_generic(struct e1000_hw *hw); +void e1000_config_collision_dist_generic(struct e1000_hw *hw); +void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count); +void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value); +void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); +void e1000_put_hw_semaphore_generic(struct e1000_hw *hw); +void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); +s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); +void e1000_remove_device_generic(struct e1000_hw *hw); +void e1000_reset_adaptive_generic(struct e1000_hw *hw); +void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); +void e1000_update_adaptive_generic(struct e1000_hw *hw); +void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_nvm.h +++ linux-2.6.27/ubuntu/e1000e/e1000_nvm.h @@ -0,0 +1,58 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_NVM_H_ +#define _E1000_NVM_H_ + +void e1000_init_nvm_ops_generic(struct e1000_hw *hw); +s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); + +s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); +s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); +s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num); +s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data); +s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data); +s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw); +s32 e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data); +s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); +void e1000_stop_nvm(struct e1000_hw *hw); +void e1000_release_nvm_generic(struct e1000_hw *hw); +void e1000_reload_nvm_generic(struct e1000_hw *hw); + +#define E1000_STM_OPCODE 0xDB00 + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_phy.c +++ linux-2.6.27/ubuntu/e1000e/e1000_phy.c @@ -0,0 +1,2489 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "e1000_hw.h" + +static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); +/* Cable length tables */ +static const u16 e1000_m88_cable_length_table[] = + { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; +#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ + (sizeof(e1000_m88_cable_length_table) / \ + sizeof(e1000_m88_cable_length_table[0])) + +static const u16 e1000_igp_2_cable_length_table[] = + { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, + 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, + 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, + 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, + 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, + 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, + 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, + 104, 109, 114, 118, 121, 124}; +#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ + (sizeof(e1000_igp_2_cable_length_table) / \ + sizeof(e1000_igp_2_cable_length_table[0])) + +/** + * e1000_check_reset_block_generic - Check if PHY reset is blocked + * @hw: pointer to the HW structure + * + * Read the PHY management control register and check whether a PHY reset + * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise + * return E1000_BLK_PHY_RESET (12). + **/ +s32 e1000_check_reset_block_generic(struct e1000_hw *hw) +{ + u32 manc; + + DEBUGFUNC("e1000_check_reset_block"); + + manc = E1000_READ_REG(hw, E1000_MANC); + + return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? + E1000_BLK_PHY_RESET : E1000_SUCCESS; +} + +/** + * e1000_get_phy_id - Retrieve the PHY ID and revision + * @hw: pointer to the HW structure + * + * Reads the PHY registers and stores the PHY ID and possibly the PHY + * revision in the hardware structure. + **/ +s32 e1000_get_phy_id(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_id; + + DEBUGFUNC("e1000_get_phy_id"); + + if (!(phy->ops.read_reg)) + goto out; + + ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); + if (ret_val) + goto out; + + phy->id = (u32)(phy_id << 16); + usec_delay(20); + ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); + if (ret_val) + goto out; + + phy->id |= (u32)(phy_id & PHY_REVISION_MASK); + phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); + +out: + return ret_val; +} + +/** + * e1000_phy_reset_dsp_generic - Reset PHY DSP + * @hw: pointer to the HW structure + * + * Reset the digital signal processor. + **/ +s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_phy_reset_dsp_generic"); + + if (!(hw->phy.ops.write_reg)) + goto out; + + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); + if (ret_val) + goto out; + + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); + +out: + return ret_val; +} + +/** + * e1000_read_phy_reg_mdic - Read MDI control register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the MDI control register in the PHY at offset and stores the + * information read to data. + **/ +s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 i, mdic = 0; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_phy_reg_mdic"); + + /* + * Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + mdic = ((offset << E1000_MDIC_REG_SHIFT) | + (phy->addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_READ)); + + E1000_WRITE_REG(hw, E1000_MDIC, mdic); + + /* + * Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { + usec_delay(50); + mdic = E1000_READ_REG(hw, E1000_MDIC); + if (mdic & E1000_MDIC_READY) + break; + } + if (!(mdic & E1000_MDIC_READY)) { + DEBUGOUT("MDI Read did not complete\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } + if (mdic & E1000_MDIC_ERROR) { + DEBUGOUT("MDI Error\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } + *data = (u16) mdic; + +out: + return ret_val; +} + +/** + * e1000_write_phy_reg_mdic - Write MDI control register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write to register at offset + * + * Writes data to MDI control register in the PHY at offset. + **/ +s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 i, mdic = 0; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_phy_reg_mdic"); + + /* + * Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + mdic = (((u32)data) | + (offset << E1000_MDIC_REG_SHIFT) | + (phy->addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_WRITE)); + + E1000_WRITE_REG(hw, E1000_MDIC, mdic); + + /* + * Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { + usec_delay(50); + mdic = E1000_READ_REG(hw, E1000_MDIC); + if (mdic & E1000_MDIC_READY) + break; + } + if (!(mdic & E1000_MDIC_READY)) { + DEBUGOUT("MDI Write did not complete\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } + if (mdic & E1000_MDIC_ERROR) { + DEBUGOUT("MDI Error\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_read_phy_reg_m88 - Read m88 PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ +s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_phy_reg_m88"); + + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + ret_val = e1000_read_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_write_phy_reg_m88 - Write m88 PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ +s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_phy_reg_m88"); + + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + ret_val = e1000_write_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_read_phy_reg_igp - Read igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ +s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_phy_reg_igp"); + + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + ret_val = e1000_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (u16)offset); + if (ret_val) { + hw->phy.ops.release(hw); + goto out; + } + } + + ret_val = e1000_read_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_write_phy_reg_igp - Write igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ +s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_phy_reg_igp"); + + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + ret_val = e1000_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (u16)offset); + if (ret_val) { + hw->phy.ops.release(hw); + goto out; + } + } + + ret_val = e1000_write_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_read_kmrn_reg_generic - Read kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore, if necessary. Then reads the PHY register at offset + * using the kumeran interface. The information retrieved is stored in data. + * Release any acquired semaphores before exiting. + **/ +s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_kmrn_reg_generic"); + + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; + E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); + + usec_delay(2); + + kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); + *data = (u16)kmrnctrlsta; + + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_write_kmrn_reg_generic - Write kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore, if necessary. Then write the data to PHY register + * at the offset using the kumeran interface. Release any acquired semaphores + * before exiting. + **/ +s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_kmrn_reg_generic"); + + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | data; + E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); + + usec_delay(2); + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link + * @hw: pointer to the HW structure + * + * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock + * and downshift values are set also. + **/ +s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + + DEBUGFUNC("e1000_copper_link_setup_m88"); + + if (phy->reset_disable) { + ret_val = E1000_SUCCESS; + goto out; + } + + /* Enable CRS on TX. This must be set for half-duplex operation. */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + /* For newer PHYs this bit is downshift enable */ + if (phy->type == e1000_phy_m88) + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + + /* + * Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + + switch (phy->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } + + /* + * Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if (phy->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + + /* Enable downshift on BM (disabled by default) */ + if (phy->type == e1000_phy_bm) + phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; + + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + + if ((phy->type == e1000_phy_m88) && + (phy->revision < E1000_REVISION_4) && + (phy->id != BME1000_E_PHY_ID_R2)) { + /* + * Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + ret_val = phy->ops.read_reg(hw, + M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if (ret_val) + goto out; + + phy_data |= M88E1000_EPSCR_TX_CLK_25; + + if ((phy->revision == E1000_REVISION_2) && + (phy->id == M88E1111_I_PHY_ID)) { + /* 82573L PHY - set the downshift counter to 5x. */ + phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; + phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; + } else { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + } + ret_val = phy->ops.write_reg(hw, + M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if (ret_val) + goto out; + } + + if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) { + /* Set PHY page 0, register 29 to 0x0003 */ + ret_val = phy->ops.write_reg(hw, 29, 0x0003); + if (ret_val) + goto out; + + /* Set PHY page 0, register 30 to 0x0000 */ + ret_val = phy->ops.write_reg(hw, 30, 0x0000); + if (ret_val) + goto out; + } + + /* Commit the changes. */ + ret_val = phy->ops.commit(hw); + if (ret_val) { + DEBUGOUT("Error committing the PHY changes\n"); + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_copper_link_setup_igp - Setup igp PHY's for copper link + * @hw: pointer to the HW structure + * + * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for + * igp PHY's. + **/ +s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + + DEBUGFUNC("e1000_copper_link_setup_igp"); + + if (phy->reset_disable) { + ret_val = E1000_SUCCESS; + goto out; + } + + ret_val = hw->phy.ops.reset(hw); + if (ret_val) { + DEBUGOUT("Error resetting the PHY.\n"); + goto out; + } + + /* + * Wait 100ms for MAC to configure PHY from NVM settings, to avoid + * timeout issues when LFS is enabled. + */ + msec_delay(100); + + /* + * The NVM settings will configure LPLU in D3 for + * non-IGP1 PHYs. + */ + if (phy->type == e1000_phy_igp) { + /* disable lplu d3 during driver init */ + ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); + if (ret_val) { + DEBUGOUT("Error Disabling LPLU D3\n"); + goto out; + } + } + + /* disable lplu d0 during driver init */ + if (hw->phy.ops.set_d0_lplu_state) { + ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); + if (ret_val) { + DEBUGOUT("Error Disabling LPLU D0\n"); + goto out; + } + } + /* Configure mdi-mdix settings */ + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCR_AUTO_MDIX; + + switch (phy->mdix) { + case 1: + data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 2: + data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 0: + default: + data |= IGP01E1000_PSCR_AUTO_MDIX; + break; + } + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); + if (ret_val) + goto out; + + /* set auto-master slave resolution settings */ + if (hw->mac.autoneg) { + /* + * when autonegotiation advertisement is only 1000Mbps then we + * should disable SmartSpeed and enable Auto MasterSlave + * resolution as hardware default. + */ + if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + + /* Set auto Master/Slave resolution process */ + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); + if (ret_val) + goto out; + + data &= ~CR_1000T_MS_ENABLE; + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); + if (ret_val) + goto out; + } + + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); + if (ret_val) + goto out; + + /* load defaults for future use */ + phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? + ((data & CR_1000T_MS_VALUE) ? + e1000_ms_force_master : + e1000_ms_force_slave) : + e1000_ms_auto; + + switch (phy->ms_type) { + case e1000_ms_force_master: + data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); + break; + case e1000_ms_force_slave: + data |= CR_1000T_MS_ENABLE; + data &= ~(CR_1000T_MS_VALUE); + break; + case e1000_ms_auto: + data &= ~CR_1000T_MS_ENABLE; + default: + break; + } + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); + if (ret_val) + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link + * @hw: pointer to the HW structure + * + * Performs initial bounds checking on autoneg advertisement parameter, then + * configure to advertise the full capability. Setup the PHY to autoneg + * and restart the negotiation process between the link partner. If + * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. + **/ +s32 e1000_copper_link_autoneg(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_ctrl; + + DEBUGFUNC("e1000_copper_link_autoneg"); + + /* + * Perform some bounds checking on the autoneg advertisement + * parameter. + */ + phy->autoneg_advertised &= phy->autoneg_mask; + + /* + * If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ + if (phy->autoneg_advertised == 0) + phy->autoneg_advertised = phy->autoneg_mask; + + DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); + ret_val = e1000_phy_setup_autoneg(hw); + if (ret_val) { + DEBUGOUT("Error Setting up Auto-Negotiation\n"); + goto out; + } + DEBUGOUT("Restarting Auto-Neg\n"); + + /* + * Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); + if (ret_val) + goto out; + + phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); + if (ret_val) + goto out; + + /* + * Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if (phy->autoneg_wait_to_complete) { + ret_val = hw->mac.ops.wait_autoneg(hw); + if (ret_val) { + DEBUGOUT("Error while waiting for " + "autoneg to complete\n"); + goto out; + } + } + + hw->mac.get_link_status = true; + +out: + return ret_val; +} + +/** + * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation + * @hw: pointer to the HW structure + * + * Reads the MII auto-neg advertisement register and/or the 1000T control + * register and if the PHY is already setup for auto-negotiation, then + * return successful. Otherwise, setup advertisement and flow control to + * the appropriate values for the wanted auto-negotiation. + **/ +s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 mii_autoneg_adv_reg; + u16 mii_1000t_ctrl_reg = 0; + + DEBUGFUNC("e1000_phy_setup_autoneg"); + + phy->autoneg_advertised &= phy->autoneg_mask; + + /* Read the MII Auto-Neg Advertisement Register (Address 4). */ + ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); + if (ret_val) + goto out; + + if (phy->autoneg_mask & ADVERTISE_1000_FULL) { + /* Read the MII 1000Base-T Control Register (Address 9). */ + ret_val = phy->ops.read_reg(hw, + PHY_1000T_CTRL, + &mii_1000t_ctrl_reg); + if (ret_val) + goto out; + } + + /* + * Need to parse both autoneg_advertised and fc and set up + * the appropriate PHY registers. First we will parse for + * autoneg_advertised software override. Since we can advertise + * a plethora of combinations, we need to check each bit + * individually. + */ + + /* + * First we clear all the 10/100 mb speed bits in the Auto-Neg + * Advertisement Register (Address 4) and the 1000 mb speed bits in + * the 1000Base-T Control Register (Address 9). + */ + mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | + NWAY_AR_100TX_HD_CAPS | + NWAY_AR_10T_FD_CAPS | + NWAY_AR_10T_HD_CAPS); + mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); + + DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); + + /* Do we want to advertise 10 Mb Half Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_10_HALF) { + DEBUGOUT("Advertise 10mb Half duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; + } + + /* Do we want to advertise 10 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_10_FULL) { + DEBUGOUT("Advertise 10mb Full duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; + } + + /* Do we want to advertise 100 Mb Half Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_100_HALF) { + DEBUGOUT("Advertise 100mb Half duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; + } + + /* Do we want to advertise 100 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_100_FULL) { + DEBUGOUT("Advertise 100mb Full duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; + } + + /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ + if (phy->autoneg_advertised & ADVERTISE_1000_HALF) { + DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); + } + + /* Do we want to advertise 1000 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { + DEBUGOUT("Advertise 1000mb Full duplex\n"); + mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; + } + + /* + * Check for a software override of the flow control settings, and + * setup the PHY advertisement registers accordingly. If + * auto-negotiation is enabled, then software will have to set the + * "PAUSE" bits to the correct value in the Auto-Negotiation + * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- + * negotiation. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames + * but we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: No software override. The flow control configuration + * in the EEPROM is used. + */ + switch (hw->fc.type) { + case e1000_fc_none: + /* + * Flow control (Rx & Tx) is completely disabled by a + * software over-ride. + */ + mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case e1000_fc_rx_pause: + /* + * Rx Flow control is enabled, and Tx Flow control is + * disabled, by a software over-ride. + * + * Since there really isn't a way to advertise that we are + * capable of Rx Pause ONLY, we will advertise that we + * support both symmetric and asymmetric Rx PAUSE. Later + * (in e1000_config_fc_after_link_up) we will disable the + * hw's ability to send PAUSE frames. + */ + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case e1000_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is + * disabled, by a software over-ride. + */ + mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; + mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; + break; + case e1000_fc_full: + /* + * Flow control (both Rx and Tx) is enabled by a software + * over-ride. + */ + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); + if (ret_val) + goto out; + + DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); + + if (phy->autoneg_mask & ADVERTISE_1000_FULL) { + ret_val = phy->ops.write_reg(hw, + PHY_1000T_CTRL, + mii_1000t_ctrl_reg); + if (ret_val) + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_setup_copper_link_generic - Configure copper link settings + * @hw: pointer to the HW structure + * + * Calls the appropriate function to configure the link for auto-neg or forced + * speed and duplex. Then we check for link, once link is established calls + * to configure collision distance and flow control are called. If link is + * not established, we return -E1000_ERR_PHY (-2). + **/ +s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) +{ + s32 ret_val; + bool link; + + DEBUGFUNC("e1000_setup_copper_link_generic"); + + if (hw->mac.autoneg) { + /* + * Setup autoneg and flow control advertisement and perform + * autonegotiation. + */ + ret_val = e1000_copper_link_autoneg(hw); + if (ret_val) + goto out; + } else { + /* + * PHY will be set to 10H, 10F, 100H or 100F + * depending on user settings. + */ + DEBUGOUT("Forcing Speed and Duplex\n"); + ret_val = hw->phy.ops.force_speed_duplex(hw); + if (ret_val) { + DEBUGOUT("Error Forcing Speed and Duplex\n"); + goto out; + } + } + + /* + * Check link status. Wait up to 100 microseconds for link to become + * valid. + */ + ret_val = e1000_phy_has_link_generic(hw, + COPPER_LINK_UP_LIMIT, + 10, + &link); + if (ret_val) + goto out; + + if (link) { + DEBUGOUT("Valid link established!!!\n"); + e1000_config_collision_dist_generic(hw); + ret_val = e1000_config_fc_after_link_up_generic(hw); + } else { + DEBUGOUT("Unable to establish link!!!\n"); + } + +out: + return ret_val; +} + +/** + * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY + * @hw: pointer to the HW structure + * + * Calls the PHY setup function to force speed and duplex. Clears the + * auto-crossover to force MDI manually. Waits for link and returns + * successful if link up is successful, else -E1000_ERR_PHY (-2). + **/ +s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + bool link; + + DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); + + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + + e1000_phy_force_speed_duplex_setup(hw, &phy_data); + + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + + /* + * Clear Auto-Crossover to force MDI manually. IGP requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); + if (ret_val) + goto out; + + DEBUGOUT1("IGP PSCR: %X\n", phy_data); + + usec_delay(1); + + if (phy->autoneg_wait_to_complete) { + DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); + + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + + if (!link) { + DEBUGOUT("Link taking longer than expected.\n"); + } + + /* Try once more */ + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY + * @hw: pointer to the HW structure + * + * Calls the PHY setup function to force speed and duplex. Clears the + * auto-crossover to force MDI manually. Resets the PHY to commit the + * changes. If time expires while waiting for link up, we reset the DSP. + * After reset, TX_CLK and CRS on Tx must be set. Return successful upon + * successful completion, else return corresponding error code. + **/ +s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + bool link; + + DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); + + /* + * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + + DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); + + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + + e1000_phy_force_speed_duplex_setup(hw, &phy_data); + + /* Reset the phy to commit changes. */ + phy_data |= MII_CR_RESET; + + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + + usec_delay(1); + + if (phy->autoneg_wait_to_complete) { + DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); + + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + + if (!link) { + /* + * We didn't get link. + * Reset the DSP and cross our fingers. + */ + ret_val = phy->ops.write_reg(hw, + M88E1000_PHY_PAGE_SELECT, + 0x001d); + if (ret_val) + goto out; + ret_val = e1000_phy_reset_dsp_generic(hw); + if (ret_val) + goto out; + } + + /* Try once more */ + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + } + + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + /* + * Resetting the phy means we need to re-force TX_CLK in the + * Extended PHY Specific Control Register to 25MHz clock from + * the reset value of 2.5MHz. + */ + phy_data |= M88E1000_EPSCR_TX_CLK_25; + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + + /* + * In addition, we must re-enable CRS on Tx for both half and full + * duplex. + */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + +out: + return ret_val; +} + +/** + * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex + * @hw: pointer to the HW structure + * @phy_ctrl: pointer to current value of PHY_CONTROL + * + * Forces speed and duplex on the PHY by doing the following: disable flow + * control, force speed/duplex on the MAC, disable auto speed detection, + * disable auto-negotiation, configure duplex, configure speed, configure + * the collision distance, write configuration to CTRL register. The + * caller must write to the PHY_CONTROL register for these settings to + * take affect. + **/ +void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 ctrl; + + DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); + + /* Turn off flow control when forcing speed/duplex */ + hw->fc.type = e1000_fc_none; + + /* Force speed/duplex on the mac */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + ctrl &= ~E1000_CTRL_SPD_SEL; + + /* Disable Auto Speed Detection */ + ctrl &= ~E1000_CTRL_ASDE; + + /* Disable autoneg on the phy */ + *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; + + /* Forcing Full or Half Duplex? */ + if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { + ctrl &= ~E1000_CTRL_FD; + *phy_ctrl &= ~MII_CR_FULL_DUPLEX; + DEBUGOUT("Half Duplex\n"); + } else { + ctrl |= E1000_CTRL_FD; + *phy_ctrl |= MII_CR_FULL_DUPLEX; + DEBUGOUT("Full Duplex\n"); + } + + /* Forcing 10mb or 100mb? */ + if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { + ctrl |= E1000_CTRL_SPD_100; + *phy_ctrl |= MII_CR_SPEED_100; + *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); + DEBUGOUT("Forcing 100mb\n"); + } else { + ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); + *phy_ctrl |= MII_CR_SPEED_10; + *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); + DEBUGOUT("Forcing 10mb\n"); + } + + e1000_config_collision_dist_generic(hw); + + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); +} + +/** + * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 + * @hw: pointer to the HW structure + * @active: boolean used to enable/disable lplu + * + * Success returns 0, Failure returns 1 + * + * The low power link up (lplu) state is set to the power management level D3 + * and SmartSpeed is disabled when active is true, else clear lplu for D3 + * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU + * is used during Dx states where the power conservation is most important. + * During driver activity, SmartSpeed should be enabled so performance is + * maintained. + **/ +s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 data; + + DEBUGFUNC("e1000_set_d3_lplu_state_generic"); + + if (!(hw->phy.ops.read_reg)) + goto out; + + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); + if (ret_val) + goto out; + + if (!active) { + data &= ~IGP02E1000_PM_D3_LPLU; + ret_val = phy->ops.write_reg(hw, + IGP02E1000_PHY_POWER_MGMT, + data); + if (ret_val) + goto out; + /* + * LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. + */ + if (phy->smart_speed == e1000_smart_speed_on) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data |= IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } else if (phy->smart_speed == e1000_smart_speed_off) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } + } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || + (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || + (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { + data |= IGP02E1000_PM_D3_LPLU; + ret_val = phy->ops.write_reg(hw, + IGP02E1000_PHY_POWER_MGMT, + data); + if (ret_val) + goto out; + + /* When LPLU is enabled, we should disable SmartSpeed */ + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + } + +out: + return ret_val; +} + +/** + * e1000_check_downshift_generic - Checks whether a downshift in speed occurred + * @hw: pointer to the HW structure + * + * Success returns 0, Failure returns 1 + * + * A downshift is detected by querying the PHY link health. + **/ +s32 e1000_check_downshift_generic(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data, offset, mask; + + DEBUGFUNC("e1000_check_downshift_generic"); + + switch (phy->type) { + case e1000_phy_m88: + case e1000_phy_gg82563: + case e1000_phy_bm: + offset = M88E1000_PHY_SPEC_STATUS; + mask = M88E1000_PSSR_DOWNSHIFT; + break; + case e1000_phy_igp_2: + case e1000_phy_igp: + case e1000_phy_igp_3: + offset = IGP01E1000_PHY_LINK_HEALTH; + mask = IGP01E1000_PLHR_SS_DOWNGRADE; + break; + default: + /* speed downshift not supported */ + phy->speed_downgraded = false; + ret_val = E1000_SUCCESS; + goto out; + } + + ret_val = phy->ops.read_reg(hw, offset, &phy_data); + + if (!ret_val) + phy->speed_downgraded = (phy_data & mask) ? true : false; + +out: + return ret_val; +} + +/** + * e1000_check_polarity_m88 - Checks the polarity. + * @hw: pointer to the HW structure + * + * Success returns 0, Failure returns -E1000_ERR_PHY (-2) + * + * Polarity is determined based on the PHY specific status register. + **/ +s32 e1000_check_polarity_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + + DEBUGFUNC("e1000_check_polarity_m88"); + + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); + + if (!ret_val) + phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) + ? e1000_rev_polarity_reversed + : e1000_rev_polarity_normal; + + return ret_val; +} + +/** + * e1000_check_polarity_igp - Checks the polarity. + * @hw: pointer to the HW structure + * + * Success returns 0, Failure returns -E1000_ERR_PHY (-2) + * + * Polarity is determined based on the PHY port status register, and the + * current speed (since there is no polarity at 100Mbps). + **/ +s32 e1000_check_polarity_igp(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data, offset, mask; + + DEBUGFUNC("e1000_check_polarity_igp"); + + /* + * Polarity is determined based on the speed of + * our connection. + */ + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); + if (ret_val) + goto out; + + if ((data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) { + offset = IGP01E1000_PHY_PCS_INIT_REG; + mask = IGP01E1000_PHY_POLARITY_MASK; + } else { + /* + * This really only applies to 10Mbps since + * there is no polarity for 100Mbps (always 0). + */ + offset = IGP01E1000_PHY_PORT_STATUS; + mask = IGP01E1000_PSSR_POLARITY_REVERSED; + } + + ret_val = phy->ops.read_reg(hw, offset, &data); + + if (!ret_val) + phy->cable_polarity = (data & mask) + ? e1000_rev_polarity_reversed + : e1000_rev_polarity_normal; + +out: + return ret_val; +} + +/** + * e1000_wait_autoneg_generic - Wait for auto-neg completion + * @hw: pointer to the HW structure + * + * Waits for auto-negotiation to complete or for the auto-negotiation time + * limit to expire, which ever happens first. + **/ +s32 e1000_wait_autoneg_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 i, phy_status; + + DEBUGFUNC("e1000_wait_autoneg_generic"); + + if (!(hw->phy.ops.read_reg)) + return E1000_SUCCESS; + + /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ + for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + if (phy_status & MII_SR_AUTONEG_COMPLETE) + break; + msec_delay(100); + } + + /* + * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation + * has completed. + */ + return ret_val; +} + +/** + * e1000_phy_has_link_generic - Polls PHY for link + * @hw: pointer to the HW structure + * @iterations: number of times to poll for link + * @usec_interval: delay between polling attempts + * @success: pointer to whether polling was successful or not + * + * Polls the PHY status register for link, 'iterations' number of times. + **/ +s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, + u32 usec_interval, bool *success) +{ + s32 ret_val = E1000_SUCCESS; + u16 i, phy_status; + + DEBUGFUNC("e1000_phy_has_link_generic"); + + if (!(hw->phy.ops.read_reg)) + return E1000_SUCCESS; + + for (i = 0; i < iterations; i++) { + /* + * Some PHYs require the PHY_STATUS register to be read + * twice due to the link bit being sticky. No harm doing + * it across the board. + */ + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + if (phy_status & MII_SR_LINK_STATUS) + break; + if (usec_interval >= 1000) + msec_delay_irq(usec_interval/1000); + else + usec_delay(usec_interval); + } + + *success = (i < iterations) ? true : false; + + return ret_val; +} + +/** + * e1000_get_cable_length_m88 - Determine cable length for m88 PHY + * @hw: pointer to the HW structure + * + * Reads the PHY specific status register to retrieve the cable length + * information. The cable length is determined by averaging the minimum and + * maximum values to get the "average" cable length. The m88 PHY has four + * possible cable length values, which are: + * Register Value Cable Length + * 0 < 50 meters + * 1 50 - 80 meters + * 2 80 - 110 meters + * 3 110 - 140 meters + * 4 > 140 meters + **/ +s32 e1000_get_cable_length_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data, index; + + DEBUGFUNC("e1000_get_cable_length_m88"); + + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + if (ret_val) + goto out; + + index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT; + phy->min_cable_length = e1000_m88_cable_length_table[index]; + phy->max_cable_length = e1000_m88_cable_length_table[index+1]; + + phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + +out: + return ret_val; +} + +/** + * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY + * @hw: pointer to the HW structure + * + * The automatic gain control (agc) normalizes the amplitude of the + * received signal, adjusting for the attenuation produced by the + * cable. By reading the AGC registers, which represent the + * combination of coarse and fine gain value, the value can be put + * into a lookup table to obtain the approximate cable length + * for each channel. + **/ +s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_data, i, agc_value = 0; + u16 cur_agc_index, max_agc_index = 0; + u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; + u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = + {IGP02E1000_PHY_AGC_A, + IGP02E1000_PHY_AGC_B, + IGP02E1000_PHY_AGC_C, + IGP02E1000_PHY_AGC_D}; + + DEBUGFUNC("e1000_get_cable_length_igp_2"); + + /* Read the AGC registers for all channels */ + for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { + ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); + if (ret_val) + goto out; + + /* + * Getting bits 15:9, which represent the combination of + * coarse and fine gain values. The result is a number + * that can be put into the lookup table to obtain the + * approximate cable length. + */ + cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & + IGP02E1000_AGC_LENGTH_MASK; + + /* Array index bound check. */ + if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || + (cur_agc_index == 0)) { + ret_val = -E1000_ERR_PHY; + goto out; + } + + /* Remove min & max AGC values from calculation. */ + if (e1000_igp_2_cable_length_table[min_agc_index] > + e1000_igp_2_cable_length_table[cur_agc_index]) + min_agc_index = cur_agc_index; + if (e1000_igp_2_cable_length_table[max_agc_index] < + e1000_igp_2_cable_length_table[cur_agc_index]) + max_agc_index = cur_agc_index; + + agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; + } + + agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + + e1000_igp_2_cable_length_table[max_agc_index]); + agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); + + /* Calculate cable length with the error range of +/- 10 meters. */ + phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? + (agc_value - IGP02E1000_AGC_RANGE) : 0; + phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; + + phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + +out: + return ret_val; +} + +/** + * e1000_get_phy_info_m88 - Retrieve PHY information + * @hw: pointer to the HW structure + * + * Valid for only copper links. Read the PHY status register (sticky read) + * to verify that link is up. Read the PHY special control register to + * determine the polarity and 10base-T extended distance. Read the PHY + * special status register to determine MDI/MDIx and current speed. If + * speed is 1000, then determine cable length, local and remote receiver. + **/ +s32 e1000_get_phy_info_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + bool link; + + DEBUGFUNC("e1000_get_phy_info_m88"); + + if (hw->phy.media_type != e1000_media_type_copper) { + DEBUGOUT("Phy info is only valid for copper media\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) { + DEBUGOUT("Phy info is only valid if link is up\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) + ? true + : false; + + ret_val = e1000_check_polarity_m88(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + if (ret_val) + goto out; + + phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; + + if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { + ret_val = hw->phy.ops.get_cable_length(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); + if (ret_val) + goto out; + + phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + + phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + } else { + /* Set values to "undefined" */ + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + } + +out: + return ret_val; +} + +/** + * e1000_get_phy_info_igp - Retrieve igp PHY information + * @hw: pointer to the HW structure + * + * Read PHY status to determine if link is up. If link is up, then + * set/determine 10base-T extended distance and polarity correction. Read + * PHY port status to determine MDI/MDIx and speed. Based on the speed, + * determine on the cable length, local and remote receiver. + **/ +s32 e1000_get_phy_info_igp(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + bool link; + + DEBUGFUNC("e1000_get_phy_info_igp"); + + ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) { + DEBUGOUT("Phy info is only valid if link is up\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + phy->polarity_correction = true; + + ret_val = e1000_check_polarity_igp(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); + if (ret_val) + goto out; + + phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; + + if ((data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) { + ret_val = hw->phy.ops.get_cable_length(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); + if (ret_val) + goto out; + + phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + + phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + } else { + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + } + +out: + return ret_val; +} + +/** + * e1000_phy_sw_reset_generic - PHY software reset + * @hw: pointer to the HW structure + * + * Does a software reset of the PHY by reading the PHY control register and + * setting/write the control register reset bit to the PHY. + **/ +s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 phy_ctrl; + + DEBUGFUNC("e1000_phy_sw_reset_generic"); + + if (!(hw->phy.ops.read_reg)) + goto out; + + ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); + if (ret_val) + goto out; + + phy_ctrl |= MII_CR_RESET; + ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); + if (ret_val) + goto out; + + usec_delay(1); + +out: + return ret_val; +} + +/** + * e1000_phy_hw_reset_generic - PHY hardware reset + * @hw: pointer to the HW structure + * + * Verify the reset block is not blocking us from resetting. Acquire + * semaphore (if necessary) and read/set/write the device control reset + * bit in the PHY. Wait the appropriate delay time for the device to + * reset and release the semaphore (if necessary). + **/ +s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u32 ctrl; + + DEBUGFUNC("e1000_phy_hw_reset_generic"); + + ret_val = phy->ops.check_reset_block(hw); + if (ret_val) { + ret_val = E1000_SUCCESS; + goto out; + } + + ret_val = phy->ops.acquire(hw); + if (ret_val) + goto out; + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); + E1000_WRITE_FLUSH(hw); + + usec_delay(phy->reset_delay_us); + + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + + usec_delay(150); + + phy->ops.release(hw); + + ret_val = phy->ops.get_cfg_done(hw); + +out: + return ret_val; +} + +/** + * e1000_get_cfg_done_generic - Generic configuration done + * @hw: pointer to the HW structure + * + * Generic function to wait 10 milli-seconds for configuration to complete + * and return success. + **/ +s32 e1000_get_cfg_done_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_get_cfg_done_generic"); + + msec_delay_irq(10); + + return E1000_SUCCESS; +} + +/** + * e1000_phy_init_script_igp3 - Inits the IGP3 PHY + * @hw: pointer to the HW structure + * + * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. + **/ +s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) +{ + DEBUGOUT("Running IGP 3 PHY init script\n"); + + /* PHY init IGP 3 */ + /* Enable rise/fall, 10-mode work in class-A */ + hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); + /* Remove all caps from Replica path filter */ + hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); + /* Bias trimming for ADC, AFE and Driver (Default) */ + hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); + /* Increase Hybrid poly bias */ + hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); + /* Add 4% to Tx amplitude in Gig mode */ + hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); + /* Disable trimming (TTT) */ + hw->phy.ops.write_reg(hw, 0x2011, 0x0000); + /* Poly DC correction to 94.6% + 2% for all channels */ + hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); + /* ABS DC correction to 95.9% */ + hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); + /* BG temp curve trim */ + hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); + /* Increasing ADC OPAMP stage 1 currents to max */ + hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); + /* Force 1000 ( required for enabling PHY regs configuration) */ + hw->phy.ops.write_reg(hw, 0x0000, 0x0140); + /* Set upd_freq to 6 */ + hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); + /* Disable NPDFE */ + hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); + /* Disable adaptive fixed FFE (Default) */ + hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); + /* Enable FFE hysteresis */ + hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); + /* Fixed FFE for short cable lengths */ + hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); + /* Fixed FFE for medium cable lengths */ + hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); + /* Fixed FFE for long cable lengths */ + hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); + /* Enable Adaptive Clip Threshold */ + hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); + /* AHT reset limit to 1 */ + hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); + /* Set AHT master delay to 127 msec */ + hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); + /* Set scan bits for AHT */ + hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); + /* Set AHT Preset bits */ + hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); + /* Change integ_factor of channel A to 3 */ + hw->phy.ops.write_reg(hw, 0x1895, 0x0003); + /* Change prop_factor of channels BCD to 8 */ + hw->phy.ops.write_reg(hw, 0x1796, 0x0008); + /* Change cg_icount + enable integbp for channels BCD */ + hw->phy.ops.write_reg(hw, 0x1798, 0xD008); + /* + * Change cg_icount + enable integbp + change prop_factor_master + * to 8 for channel A + */ + hw->phy.ops.write_reg(hw, 0x1898, 0xD918); + /* Disable AHT in Slave mode on channel A */ + hw->phy.ops.write_reg(hw, 0x187A, 0x0800); + /* + * Enable LPLU and disable AN to 1000 in non-D0a states, + * Enable SPD+B2B + */ + hw->phy.ops.write_reg(hw, 0x0019, 0x008D); + /* Enable restart AN on an1000_dis change */ + hw->phy.ops.write_reg(hw, 0x001B, 0x2080); + /* Enable wh_fifo read clock in 10/100 modes */ + hw->phy.ops.write_reg(hw, 0x0014, 0x0045); + /* Restart AN, Speed selection is 1000 */ + hw->phy.ops.write_reg(hw, 0x0000, 0x1340); + + return E1000_SUCCESS; +} + +/** + * e1000_get_phy_type_from_id - Get PHY type from id + * @phy_id: phy_id read from the phy + * + * Returns the phy type from the id. + **/ +e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) +{ + e1000_phy_type phy_type = e1000_phy_unknown; + + switch (phy_id) { + case M88E1000_I_PHY_ID: + case M88E1000_E_PHY_ID: + case M88E1111_I_PHY_ID: + case M88E1011_I_PHY_ID: + phy_type = e1000_phy_m88; + break; + case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ + phy_type = e1000_phy_igp_2; + break; + case GG82563_E_PHY_ID: + phy_type = e1000_phy_gg82563; + break; + case IGP03E1000_E_PHY_ID: + phy_type = e1000_phy_igp_3; + break; + case IFE_E_PHY_ID: + case IFE_PLUS_E_PHY_ID: + case IFE_C_E_PHY_ID: + phy_type = e1000_phy_ife; + break; + case BME1000_E_PHY_ID: + case BME1000_E_PHY_ID_R2: + phy_type = e1000_phy_bm; + break; + default: + phy_type = e1000_phy_unknown; + break; + } + return phy_type; +} + +/** + * e1000_determine_phy_address - Determines PHY address. + * @hw: pointer to the HW structure + * + * This uses a trial and error method to loop through possible PHY + * addresses. It tests each by reading the PHY ID registers and + * checking for a match. + **/ +s32 e1000_determine_phy_address(struct e1000_hw* hw) +{ + s32 ret_val = -E1000_ERR_PHY_TYPE; + u32 phy_addr= 0; + u32 i; + e1000_phy_type phy_type = e1000_phy_unknown; + + for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { + hw->phy.addr = phy_addr; + i = 0; + + do { + e1000_get_phy_id(hw); + phy_type = e1000_get_phy_type_from_id(hw->phy.id); + + /* + * If phy_type is valid, break - we found our + * PHY address + */ + if (phy_type != e1000_phy_unknown) { + ret_val = E1000_SUCCESS; + goto out; + } + msec_delay(1); + i++; + } while (i < 10); + } + +out: + return ret_val; +} + +/** + * e1000_get_phy_addr_for_bm_page - Retrieve PHY page address + * @page: page to access + * + * Returns the phy address for the page requested. + **/ +static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg) +{ + u32 phy_addr = 2; + + if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31)) + phy_addr = 1; + + return phy_addr; +} + +/** + * e1000_write_phy_reg_bm - Write BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ +s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val; + u32 page_select = 0; + u32 page = offset >> IGP_PAGE_SHIFT; + u32 page_shift = 0; + + DEBUGFUNC("e1000_write_phy_reg_bm"); + + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, + offset, &data, false); + goto out; + } + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + /* + * Page select is register 31 for phy address 1 and 22 for + * phy address 2 and 3. Page select is shifted only for + * phy address 1. + */ + if (hw->phy.addr == 1) { + page_shift = IGP_PAGE_SHIFT; + page_select = IGP01E1000_PHY_PAGE_SELECT; + } else { + page_shift = 0; + page_select = BM_PHY_PAGE_SELECT; + } + + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000_write_phy_reg_mdic(hw, page_select, + (page << page_shift)); + if (ret_val) { + hw->phy.ops.release(hw); + goto out; + } + } + + ret_val = e1000_write_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_read_phy_reg_bm - Read BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ +s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val; + u32 page_select = 0; + u32 page = offset >> IGP_PAGE_SHIFT; + u32 page_shift = 0; + + DEBUGFUNC("e1000_read_phy_reg_bm"); + + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, + offset, data, true); + goto out; + } + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + /* + * Page select is register 31 for phy address 1 and 22 for + * phy address 2 and 3. Page select is shifted only for + * phy address 1. + */ + if (hw->phy.addr == 1) { + page_shift = IGP_PAGE_SHIFT; + page_select = IGP01E1000_PHY_PAGE_SELECT; + } else { + page_shift = 0; + page_select = BM_PHY_PAGE_SELECT; + } + + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000_write_phy_reg_mdic(hw, page_select, + (page << page_shift)); + if (ret_val) { + hw->phy.ops.release(hw); + goto out; + } + } + + ret_val = e1000_read_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_read_phy_reg_bm2 - Read BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ +s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val; + u16 page = (u16)(offset >> IGP_PAGE_SHIFT); + + DEBUGFUNC("e1000_write_phy_reg_bm2"); + + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, + true); + goto out; + } + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + hw->phy.addr = 1; + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, + page); + + if (ret_val) { + hw->phy.ops.release(hw); + goto out; + } + } + + ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_write_phy_reg_bm2 - Write BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ +s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val; + u16 page = (u16)(offset >> IGP_PAGE_SHIFT); + + DEBUGFUNC("e1000_write_phy_reg_bm2"); + + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, + false); + goto out; + } + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + hw->phy.addr = 1; + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, + page); + + if (ret_val) { + hw->phy.ops.release(hw); + goto out; + } + } + + ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** + * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register + * @hw: pointer to the HW structure + * @offset: register offset to be read or written + * @data: pointer to the data to read or write + * @read: determines if operation is read or write + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. Note that procedure to read the wakeup + * registers are different. It works as such: + * 1) Set page 769, register 17, bit 2 = 1 + * 2) Set page to 800 for host (801 if we were manageability) + * 3) Write the address using the address opcode (0x11) + * 4) Read or write the data using the data opcode (0x12) + * 5) Restore 769_17.2 to its original value + **/ +s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, + u32 offset, u16 *data, bool read) +{ + s32 ret_val; + u16 reg = ((u16)offset); + u16 phy_reg = 0; + u8 phy_acquired = 1; + + DEBUGFUNC("e1000_read_phy_wakeup_reg_bm"); + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { + DEBUGOUT("Could not acquire PHY\n"); + phy_acquired = 0; + goto out; + } + + /* All operations in this function are phy address 1 */ + hw->phy.addr = 1; + + /* Set page 769 */ + e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); + + ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); + if (ret_val) { + DEBUGOUT("Could not read PHY page 769\n"); + goto out; + } + + /* First clear bit 4 to avoid a power state change */ + phy_reg &= ~(BM_WUC_HOST_WU_BIT); + ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); + if (ret_val) { + DEBUGOUT("Could not clear PHY page 769 bit 4\n"); + goto out; + } + + /* Write bit 2 = 1, and clear bit 4 to 769_17 */ + ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, + phy_reg | BM_WUC_ENABLE_BIT); + if (ret_val) { + DEBUGOUT("Could not write PHY page 769 bit 2\n"); + goto out; + } + + /* Select page 800 */ + ret_val = e1000_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_PAGE << IGP_PAGE_SHIFT)); + + /* Write the page 800 offset value using opcode 0x11 */ + ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); + if (ret_val) { + DEBUGOUT("Could not write address opcode to page 800\n"); + goto out; + } + + if (read) { + /* Read the page 800 value using opcode 0x12 */ + ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, + data); + } else { + /* Read the page 800 value using opcode 0x12 */ + ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, + *data); + } + + if (ret_val) { + DEBUGOUT("Could not read data value from page 800\n"); + goto out; + } + + /* + * Restore 769_17.2 to its original value + * Set page 769 + */ + e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); + + /* Clear 769_17.2 */ + ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); + if (ret_val) { + DEBUGOUT("Could not clear PHY page 769 bit 2\n"); + goto out; + } + +out: + if (phy_acquired == 1) + hw->phy.ops.release(hw); + return ret_val; +} + +/** + * e1000_power_up_phy_copper - Restore copper link in case of PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, or wake on lan is not enabled, restore the link to previous + * settings. + **/ +void e1000_power_up_phy_copper(struct e1000_hw *hw) +{ + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg &= ~MII_CR_POWER_DOWN; + hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); +} + +/** + * e1000_power_down_phy_copper - Restore copper link in case of PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, or wake on lan is not enabled, restore the link to previous + * settings. + **/ +void e1000_power_down_phy_copper(struct e1000_hw *hw) +{ + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; + hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); + msec_delay(1); +} --- linux-2.6.27.orig/ubuntu/e1000e/e1000_80003es2lan.c +++ linux-2.6.27/ubuntu/e1000e/e1000_80003es2lan.c @@ -0,0 +1,1419 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* e1000_80003es2lan + */ + +#include "e1000_hw.h" + +static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw); +static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw); +static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw); +static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw); +static void e1000_release_phy_80003es2lan(struct e1000_hw *hw); +static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw); +static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw); +static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + u32 offset, + u16 *data); +static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + u32 offset, + u16 data); +static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw); +static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw); +static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw); +static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, + u16 *duplex); +static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw); +static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw); +static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw); +static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); +static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); +static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); +static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); +static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw); +static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); +static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); +static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw); +static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw); + +/* + * A table for the GG82563 cable length where the range is defined + * with a lower bound at "index" and the upper bound at + * "index + 5". + */ +static const u16 e1000_gg82563_cable_length_table[] = + { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF }; +#define GG82563_CABLE_LENGTH_TABLE_SIZE \ + (sizeof(e1000_gg82563_cable_length_table) / \ + sizeof(e1000_gg82563_cable_length_table[0])) + +/** + * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. + * @hw: pointer to the HW structure + * + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_init_phy_params_80003es2lan"); + + if (hw->phy.media_type != e1000_media_type_copper) { + phy->type = e1000_phy_none; + goto out; + } else { + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan; + } + + phy->addr = 1; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->reset_delay_us = 100; + phy->type = e1000_phy_gg82563; + + phy->ops.acquire = e1000_acquire_phy_80003es2lan; + phy->ops.check_polarity = e1000_check_polarity_m88; + phy->ops.check_reset_block = e1000_check_reset_block_generic; + phy->ops.commit = e1000_phy_sw_reset_generic; + phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan; + phy->ops.get_info = e1000_get_phy_info_m88; + phy->ops.release = e1000_release_phy_80003es2lan; + phy->ops.reset = e1000_phy_hw_reset_generic; + phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; + + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan; + phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan; + phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan; + phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan; + + /* This can only be done after all function pointers are setup. */ + ret_val = e1000_get_phy_id(hw); + + /* Verify phy id */ + if (phy->id != GG82563_E_PHY_ID) { + ret_val = -E1000_ERR_PHY; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. + * @hw: pointer to the HW structure + * + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = E1000_READ_REG(hw, E1000_EECD); + u16 size; + + DEBUGFUNC("e1000_init_nvm_params_80003es2lan"); + + nvm->opcode_bits = 8; + nvm->delay_usec = 1; + switch (nvm->override) { + case e1000_nvm_override_spi_large: + nvm->page_size = 32; + nvm->address_bits = 16; + break; + case e1000_nvm_override_spi_small: + nvm->page_size = 8; + nvm->address_bits = 8; + break; + default: + nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; + break; + } + + nvm->type = e1000_nvm_eeprom_spi; + + size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> + E1000_EECD_SIZE_EX_SHIFT); + + /* + * Added to a constant, "size" becomes the left-shift value + * for setting word_size. + */ + size += NVM_WORD_SIZE_BASE_SHIFT; + + /* EEPROM access above 16k is unsupported */ + if (size > 14) + size = 14; + nvm->word_size = 1 << size; + + /* Function Pointers */ + nvm->ops.acquire = e1000_acquire_nvm_80003es2lan; + nvm->ops.read = e1000_read_nvm_eerd; + nvm->ops.release = e1000_release_nvm_80003es2lan; + nvm->ops.update = e1000_update_nvm_checksum_generic; + nvm->ops.valid_led_default = e1000_valid_led_default_generic; + nvm->ops.validate = e1000_validate_nvm_checksum_generic; + nvm->ops.write = e1000_write_nvm_80003es2lan; + + return E1000_SUCCESS; +} + +/** + * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. + * @hw: pointer to the HW structure + * + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_init_mac_params_80003es2lan"); + + /* Set media type */ + switch (hw->device_id) { + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: + hw->phy.media_type = e1000_media_type_internal_serdes; + break; + default: + hw->phy.media_type = e1000_media_type_copper; + break; + } + + /* Set mta register count */ + mac->mta_reg_count = 128; + /* Set rar entry count */ + mac->rar_entry_count = E1000_RAR_ENTRIES; + /* Set if part includes ASF firmware */ + mac->asf_firmware_present = true; + /* Set if manageability features are enabled. */ + mac->arc_subsystem_valid = + (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK) + ? true : false; + + /* Function pointers */ + + /* bus type/speed/width */ + mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; + /* reset */ + mac->ops.reset_hw = e1000_reset_hw_80003es2lan; + /* hw initialization */ + mac->ops.init_hw = e1000_init_hw_80003es2lan; + /* link setup */ + mac->ops.setup_link = e1000_setup_link_generic; + /* physical interface link setup */ + mac->ops.setup_physical_interface = + (hw->phy.media_type == e1000_media_type_copper) + ? e1000_setup_copper_link_80003es2lan + : e1000_setup_fiber_serdes_link_generic; + /* check for link */ + switch (hw->phy.media_type) { + case e1000_media_type_copper: + mac->ops.check_for_link = e1000_check_for_copper_link_generic; + break; + case e1000_media_type_fiber: + mac->ops.check_for_link = e1000_check_for_fiber_link_generic; + break; + case e1000_media_type_internal_serdes: + mac->ops.check_for_link = e1000_check_for_serdes_link_generic; + break; + default: + ret_val = -E1000_ERR_CONFIG; + goto out; + break; + } + /* check management mode */ + mac->ops.check_mng_mode = e1000_check_mng_mode_generic; + /* multicast address update */ + mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; + /* writing VFTA */ + mac->ops.write_vfta = e1000_write_vfta_generic; + /* clearing VFTA */ + mac->ops.clear_vfta = e1000_clear_vfta_generic; + /* setting MTA */ + mac->ops.mta_set = e1000_mta_set_generic; + /* read mac address */ + mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan; + /* blink LED */ + mac->ops.blink_led = e1000_blink_led_generic; + /* setup LED */ + mac->ops.setup_led = e1000_setup_led_generic; + /* cleanup LED */ + mac->ops.cleanup_led = e1000_cleanup_led_generic; + /* turn on/off LED */ + mac->ops.led_on = e1000_led_on_generic; + mac->ops.led_off = e1000_led_off_generic; + /* remove device */ + mac->ops.remove_device = e1000_remove_device_generic; + /* clear hardware counters */ + mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan; + /* link info */ + mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan; + +out: + return ret_val; +} + +/** + * e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs. + * @hw: pointer to the HW structure + * + * The only function explicitly called by the api module to initialize + * all function pointers and parameters. + **/ +void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_init_function_pointers_80003es2lan"); + + e1000_init_mac_ops_generic(hw); + e1000_init_nvm_ops_generic(hw); + hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan; + hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan; + hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan; +} + +/** + * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY + * @hw: pointer to the HW structure + * + * A wrapper to acquire access rights to the correct PHY. This is a + * function pointer entry point called by the api module. + **/ +static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) +{ + u16 mask; + + DEBUGFUNC("e1000_acquire_phy_80003es2lan"); + + mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; + mask |= E1000_SWFW_CSR_SM; + + return e1000_acquire_swfw_sync_80003es2lan(hw, mask); +} + +/** + * e1000_release_phy_80003es2lan - Release rights to access PHY + * @hw: pointer to the HW structure + * + * A wrapper to release access rights to the correct PHY. This is a + * function pointer entry point called by the api module. + **/ +static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) +{ + u16 mask; + + DEBUGFUNC("e1000_release_phy_80003es2lan"); + + mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; + mask |= E1000_SWFW_CSR_SM; + + e1000_release_swfw_sync_80003es2lan(hw, mask); +} + +/** + * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM + * @hw: pointer to the HW structure + * + * Acquire the semaphore to access the EEPROM. This is a function + * pointer entry point called by the api module. + **/ +static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw) +{ + s32 ret_val; + + DEBUGFUNC("e1000_acquire_nvm_80003es2lan"); + + ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); + if (ret_val) + goto out; + + ret_val = e1000_acquire_nvm_generic(hw); + + if (ret_val) + e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); + +out: + return ret_val; +} + +/** + * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM + * @hw: pointer to the HW structure + * + * Release the semaphore used to access the EEPROM. This is a + * function pointer entry point called by the api module. + **/ +static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_release_nvm_80003es2lan"); + + e1000_release_nvm_generic(hw); + e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); +} + +/** + * e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore + * @hw: pointer to the HW structure + * @mask: specifies which semaphore to acquire + * + * Acquire the SW/FW semaphore to access the PHY or NVM. The mask + * will also specify which port we're acquiring the lock for. + **/ +static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) +{ + u32 swfw_sync; + u32 swmask = mask; + u32 fwmask = mask << 16; + s32 ret_val = E1000_SUCCESS; + s32 i = 0, timeout = 200; + + DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan"); + + while (i < timeout) { + if (e1000_get_hw_semaphore_generic(hw)) { + ret_val = -E1000_ERR_SWFW_SYNC; + goto out; + } + + swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) + break; + + /* + * Firmware currently using resource (fwmask) + * or other software thread using resource (swmask) + */ + e1000_put_hw_semaphore_generic(hw); + msec_delay_irq(5); + i++; + } + + if (i == timeout) { + DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); + ret_val = -E1000_ERR_SWFW_SYNC; + goto out; + } + + swfw_sync |= swmask; + E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); + + e1000_put_hw_semaphore_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore + * @hw: pointer to the HW structure + * @mask: specifies which semaphore to acquire + * + * Release the SW/FW semaphore used to access the PHY or NVM. The mask + * will also specify which port we're releasing the lock for. + **/ +static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) +{ + u32 swfw_sync; + + DEBUGFUNC("e1000_release_swfw_sync_80003es2lan"); + + while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS); + /* Empty */ + + swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); + swfw_sync &= ~mask; + E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); + + e1000_put_hw_semaphore_generic(hw); +} + +/** + * e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register + * @hw: pointer to the HW structure + * @offset: offset of the register to read + * @data: pointer to the data returned from the operation + * + * Read the GG82563 PHY register. This is a function pointer entry + * point called by the api module. + **/ +static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + u32 offset, u16 *data) +{ + s32 ret_val; + u32 page_select; + u16 temp; + + DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan"); + + ret_val = e1000_acquire_phy_80003es2lan(hw); + if (ret_val) + goto out; + + /* Select Configuration Page */ + if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + page_select = GG82563_PHY_PAGE_SELECT; + } else { + /* + * Use Alternative Page Select register to access + * registers 30 and 31 + */ + page_select = GG82563_PHY_PAGE_SELECT_ALT; + } + + temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); + ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp); + if (ret_val) { + e1000_release_phy_80003es2lan(hw); + goto out; + } + + /* + * The "ready" bit in the MDIC register may be incorrectly set + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ + usec_delay(200); + + /* ...and verify the command was successful. */ + ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp); + + if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { + ret_val = -E1000_ERR_PHY; + e1000_release_phy_80003es2lan(hw); + goto out; + } + + usec_delay(200); + + ret_val = e1000_read_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + usec_delay(200); + e1000_release_phy_80003es2lan(hw); + +out: + return ret_val; +} + +/** + * e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register + * @hw: pointer to the HW structure + * @offset: offset of the register to read + * @data: value to write to the register + * + * Write to the GG82563 PHY register. This is a function pointer entry + * point called by the api module. + **/ +static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + u32 offset, u16 data) +{ + s32 ret_val; + u32 page_select; + u16 temp; + + DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan"); + + ret_val = e1000_acquire_phy_80003es2lan(hw); + if (ret_val) + goto out; + + /* Select Configuration Page */ + if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + page_select = GG82563_PHY_PAGE_SELECT; + } else { + /* + * Use Alternative Page Select register to access + * registers 30 and 31 + */ + page_select = GG82563_PHY_PAGE_SELECT_ALT; + } + + temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); + ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp); + if (ret_val) { + e1000_release_phy_80003es2lan(hw); + goto out; + } + + + /* + * The "ready" bit in the MDIC register may be incorrectly set + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ + usec_delay(200); + + /* ...and verify the command was successful. */ + ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp); + + if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { + ret_val = -E1000_ERR_PHY; + e1000_release_phy_80003es2lan(hw); + goto out; + } + + usec_delay(200); + + ret_val = e1000_write_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + usec_delay(200); + e1000_release_phy_80003es2lan(hw); + +out: + return ret_val; +} + +/** + * e1000_write_nvm_80003es2lan - Write to ESB2 NVM + * @hw: pointer to the HW structure + * @offset: offset of the register to read + * @words: number of words to write + * @data: buffer of data to write to the NVM + * + * Write "words" of data to the ESB2 NVM. This is a function + * pointer entry point called by the api module. + **/ +static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data) +{ + DEBUGFUNC("e1000_write_nvm_80003es2lan"); + + return e1000_write_nvm_spi(hw, offset, words, data); +} + +/** + * e1000_get_cfg_done_80003es2lan - Wait for configuration to complete + * @hw: pointer to the HW structure + * + * Wait a specific amount of time for manageability processes to complete. + * This is a function pointer entry point called by the phy module. + **/ +static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw) +{ + s32 timeout = PHY_CFG_TIMEOUT; + s32 ret_val = E1000_SUCCESS; + u32 mask = E1000_NVM_CFG_DONE_PORT_0; + + DEBUGFUNC("e1000_get_cfg_done_80003es2lan"); + + if (hw->bus.func == 1) + mask = E1000_NVM_CFG_DONE_PORT_1; + + while (timeout) { + if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) + break; + msec_delay(1); + timeout--; + } + if (!timeout) { + DEBUGOUT("MNG configuration cycle has not completed.\n"); + ret_val = -E1000_ERR_RESET; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex + * @hw: pointer to the HW structure + * + * Force the speed and duplex settings onto the PHY. This is a + * function pointer entry point called by the phy module. + **/ +static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 phy_data; + bool link; + + DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan"); + + if (!(hw->phy.ops.read_reg)) + goto out; + + /* + * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO; + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + + DEBUGOUT1("GG82563 PSCR: %X\n", phy_data); + + ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + + e1000_phy_force_speed_duplex_setup(hw, &phy_data); + + /* Reset the phy to commit changes. */ + phy_data |= MII_CR_RESET; + + ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + + usec_delay(1); + + if (hw->phy.autoneg_wait_to_complete) { + DEBUGOUT("Waiting for forced speed/duplex link " + "on GG82563 phy.\n"); + + ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, + 100000, &link); + if (ret_val) + goto out; + + if (!link) { + /* + * We didn't get link. + * Reset the DSP and cross our fingers. + */ + ret_val = e1000_phy_reset_dsp_generic(hw); + if (ret_val) + goto out; + } + + /* Try once more */ + ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, + 100000, &link); + if (ret_val) + goto out; + } + + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + /* + * Resetting the phy means we need to verify the TX_CLK corresponds + * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. + */ + phy_data &= ~GG82563_MSCR_TX_CLK_MASK; + if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED) + phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5; + else + phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; + + /* + * In addition, we must re-enable CRS on Tx for both half and full + * duplex. + */ + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); + +out: + return ret_val; +} + +/** + * e1000_get_cable_length_80003es2lan - Set approximate cable length + * @hw: pointer to the HW structure + * + * Find the approximate cable length as measured by the GG82563 PHY. + * This is a function pointer entry point called by the phy module. + **/ +static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_data, index; + + DEBUGFUNC("e1000_get_cable_length_80003es2lan"); + + if (!(hw->phy.ops.read_reg)) + goto out; + + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); + if (ret_val) + goto out; + + index = phy_data & GG82563_DSPD_CABLE_LENGTH; + phy->min_cable_length = e1000_gg82563_cable_length_table[index]; + phy->max_cable_length = e1000_gg82563_cable_length_table[index+5]; + + phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + +out: + return ret_val; +} + +/** + * e1000_get_link_up_info_80003es2lan - Report speed and duplex + * @hw: pointer to the HW structure + * @speed: pointer to speed buffer + * @duplex: pointer to duplex buffer + * + * Retrieve the current speed and duplex configuration. + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, + u16 *duplex) +{ + s32 ret_val; + + DEBUGFUNC("e1000_get_link_up_info_80003es2lan"); + + if (hw->phy.media_type == e1000_media_type_copper) { + ret_val = e1000_get_speed_and_duplex_copper_generic(hw, + speed, + duplex); + if (ret_val) + goto out; + if (*speed == SPEED_1000) + ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); + else + ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, + *duplex); + } else { + ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw, + speed, + duplex); + } + +out: + return ret_val; +} + +/** + * e1000_reset_hw_80003es2lan - Reset the ESB2 controller + * @hw: pointer to the HW structure + * + * Perform a global reset to the ESB2 controller. + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) +{ + u32 ctrl, icr; + s32 ret_val; + + DEBUGFUNC("e1000_reset_hw_80003es2lan"); + + /* + * Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = e1000_disable_pcie_master_generic(hw); + if (ret_val) { + DEBUGOUT("PCI-E Master disable polling has failed.\n"); + } + + DEBUGOUT("Masking off all interrupts\n"); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + + E1000_WRITE_REG(hw, E1000_RCTL, 0); + E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); + E1000_WRITE_FLUSH(hw); + + msec_delay(10); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + + DEBUGOUT("Issuing a global reset to MAC\n"); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); + + ret_val = e1000_get_auto_rd_done_generic(hw); + if (ret_val) + /* We don't want to continue accessing MAC registers. */ + goto out; + + /* Clear any pending interrupt events. */ + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + icr = E1000_READ_REG(hw, E1000_ICR); + + e1000_check_alt_mac_addr_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_init_hw_80003es2lan - Initialize the ESB2 controller + * @hw: pointer to the HW structure + * + * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 reg_data; + s32 ret_val; + u16 i; + + DEBUGFUNC("e1000_init_hw_80003es2lan"); + + e1000_initialize_hw_bits_80003es2lan(hw); + + /* Initialize identification LED */ + ret_val = e1000_id_led_init_generic(hw); + if (ret_val) { + DEBUGOUT("Error initializing identification LED\n"); + /* This is not fatal and we should not stop init due to this */ + } + + /* Disabling VLAN filtering */ + DEBUGOUT("Initializing the IEEE VLAN\n"); + mac->ops.clear_vfta(hw); + + /* Setup the receive address. */ + e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); + + /* Zero out the Multicast HASH table */ + DEBUGOUT("Zeroing the MTA\n"); + for (i = 0; i < mac->mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + + /* Setup link and flow control */ + ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy */ + reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); + reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; + E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data); + + /* ...for both queues. */ + reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1)); + reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; + E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data); + + /* Enable retransmit on late collisions */ + reg_data = E1000_READ_REG(hw, E1000_TCTL); + reg_data |= E1000_TCTL_RTLC; + E1000_WRITE_REG(hw, E1000_TCTL, reg_data); + + /* Configure Gigabit Carry Extend Padding */ + reg_data = E1000_READ_REG(hw, E1000_TCTL_EXT); + reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; + reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN; + E1000_WRITE_REG(hw, E1000_TCTL_EXT, reg_data); + + /* Configure Transmit Inter-Packet Gap */ + reg_data = E1000_READ_REG(hw, E1000_TIPG); + reg_data &= ~E1000_TIPG_IPGT_MASK; + reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; + E1000_WRITE_REG(hw, E1000_TIPG, reg_data); + + reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001); + reg_data &= ~0x00100000; + E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); + + /* + * Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. + */ + e1000_clear_hw_cntrs_80003es2lan(hw); + + return ret_val; +} + +/** + * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2 + * @hw: pointer to the HW structure + * + * Initializes required hardware-dependent bits needed for normal operation. + **/ +static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) +{ + u32 reg; + + DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan"); + + if (hw->mac.disable_hw_init_bits) + goto out; + + /* Transmit Descriptor Control 0 */ + reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); + + /* Transmit Descriptor Control 1 */ + reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); + + /* Transmit Arbitration Control 0 */ + reg = E1000_READ_REG(hw, E1000_TARC(0)); + reg &= ~(0xF << 27); /* 30:27 */ + if (hw->phy.media_type != e1000_media_type_copper) + reg &= ~(1 << 20); + E1000_WRITE_REG(hw, E1000_TARC(0), reg); + + /* Transmit Arbitration Control 1 */ + reg = E1000_READ_REG(hw, E1000_TARC(1)); + if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) + reg &= ~(1 << 28); + else + reg |= (1 << 28); + E1000_WRITE_REG(hw, E1000_TARC(1), reg); + +out: + return; +} + +/** + * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link + * @hw: pointer to the HW structure + * + * Setup some GG82563 PHY registers for obtaining link + **/ +static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u32 ctrl_ext; + u32 i = 0; + u16 data, data2; + + DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan"); + + if (!phy->reset_disable) { + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, + &data); + if (ret_val) + goto out; + + data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ + data |= GG82563_MSCR_TX_CLK_1000MBPS_25; + + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, + data); + if (ret_val) + goto out; + + /* + * Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data); + if (ret_val) + goto out; + + data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; + + switch (phy->mdix) { + case 1: + data |= GG82563_PSCR_CROSSOVER_MODE_MDI; + break; + case 2: + data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; + break; + case 0: + default: + data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; + break; + } + + /* + * Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + if (phy->disable_polarity_correction) + data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data); + if (ret_val) + goto out; + + /* SW Reset the PHY so all changes take effect */ + ret_val = hw->phy.ops.commit(hw); + if (ret_val) { + DEBUGOUT("Error Resetting the PHY\n"); + goto out; + } + + } + + /* Bypass Rx and Tx FIFO's */ + ret_val = e1000_write_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, + E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | + E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); + if (ret_val) + goto out; + + ret_val = e1000_read_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, + &data); + if (ret_val) + goto out; + data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; + ret_val = e1000_write_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, + data); + if (ret_val) + goto out; + + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data); + if (ret_val) + goto out; + + data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data); + if (ret_val) + goto out; + + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); + if (ret_val) + goto out; + + /* + * Do not init these registers when the HW is in IAMT mode, since the + * firmware will have already initialized them. We only initialize + * them if the HW is not in IAMT mode. + */ + if (!(hw->mac.ops.check_mng_mode(hw))) { + /* Enable Electrical Idle on the PHY */ + data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; + ret_val = hw->phy.ops.write_reg(hw, + GG82563_PHY_PWR_MGMT_CTRL, + data); + if (ret_val) + goto out; + + do { + ret_val = hw->phy.ops.read_reg(hw, + GG82563_PHY_KMRN_MODE_CTRL, + &data); + if (ret_val) + goto out; + + ret_val = hw->phy.ops.read_reg(hw, + GG82563_PHY_KMRN_MODE_CTRL, + &data2); + if (ret_val) + goto out; + i++; + } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY)); + + data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + ret_val = hw->phy.ops.write_reg(hw, + GG82563_PHY_KMRN_MODE_CTRL, + data); + + if (ret_val) + goto out; + } + + /* + * Workaround: Disable padding in Kumeran interface in the MAC + * and in the PHY to avoid CRC errors. + */ + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data); + if (ret_val) + goto out; + + data |= GG82563_ICR_DIS_PADDING; + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data); + if (ret_val) + goto out; + +out: + return ret_val; +} + +/** + * e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2 + * @hw: pointer to the HW structure + * + * Essentially a wrapper for setting up all things "copper" related. + * This is a function pointer entry point called by the mac module. + **/ +static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) +{ + u32 ctrl; + s32 ret_val; + u16 reg_data; + + DEBUGFUNC("e1000_setup_copper_link_80003es2lan"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + /* + * Set the mac to wait the maximum time between each + * iteration and increase the max iterations when + * polling the phy; this fixes erroneous timeouts at 10Mbps. + */ + ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 4), + 0xFFFF); + if (ret_val) + goto out; + ret_val = e1000_read_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), + ®_data); + if (ret_val) + goto out; + reg_data |= 0x3F; + ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), + reg_data); + if (ret_val) + goto out; + ret_val = e1000_read_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, + ®_data); + if (ret_val) + goto out; + reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; + ret_val = e1000_write_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, + reg_data); + if (ret_val) + goto out; + + ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw); + if (ret_val) + goto out; + + ret_val = e1000_setup_copper_link_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation + * @hw: pointer to the HW structure + * @duplex: current duplex setting + * + * Configure the KMRN interface by applying last minute quirks for + * 10/100 operation. + **/ +static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) +{ + s32 ret_val = E1000_SUCCESS; + u32 tipg; + u32 i = 0; + u16 reg_data, reg_data2; + + DEBUGFUNC("e1000_configure_kmrn_for_10_100"); + + reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; + ret_val = e1000_write_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + goto out; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, E1000_TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; + E1000_WRITE_REG(hw, E1000_TIPG, tipg); + + + do { + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data); + if (ret_val) + goto out; + + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data2); + if (ret_val) + goto out; + i++; + } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); + + if (duplex == HALF_DUPLEX) + reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; + else + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); + +out: + return ret_val; +} + +/** + * e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation + * @hw: pointer to the HW structure + * + * Configure the KMRN interface by applying last minute quirks for + * gigabit operation. + **/ +static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 reg_data, reg_data2; + u32 tipg; + u32 i = 0; + + DEBUGFUNC("e1000_configure_kmrn_for_1000"); + + reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; + ret_val = e1000_write_kmrn_reg_generic(hw, + E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + goto out; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, E1000_TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; + E1000_WRITE_REG(hw, E1000_TIPG, tipg); + + + do { + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data); + if (ret_val) + goto out; + + ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data2); + if (ret_val) + goto out; + i++; + } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); + + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); + +out: + return ret_val; +} + +/** + * e1000_read_mac_addr_80003es2lan - Read device MAC address + * @hw: pointer to the HW structure + **/ +static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_mac_addr_80003es2lan"); + if (e1000_check_alt_mac_addr_generic(hw)) + ret_val = e1000_read_mac_addr_generic(hw); + + return ret_val; +} + +/** + * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, or wake on lan is not enabled, remove the link. + **/ +static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw) +{ + /* If the management interface is not enabled, then power down */ + if (!(hw->mac.ops.check_mng_mode(hw) || + hw->phy.ops.check_reset_block(hw))) + e1000_power_down_phy_copper(hw); + + return; +} + +/** + * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters + * @hw: pointer to the HW structure + * + * Clears the hardware counters by reading the counter registers. + **/ +static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) +{ + volatile u32 temp; + + DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan"); + + e1000_clear_hw_cntrs_base_generic(hw); + + temp = E1000_READ_REG(hw, E1000_PRC64); + temp = E1000_READ_REG(hw, E1000_PRC127); + temp = E1000_READ_REG(hw, E1000_PRC255); + temp = E1000_READ_REG(hw, E1000_PRC511); + temp = E1000_READ_REG(hw, E1000_PRC1023); + temp = E1000_READ_REG(hw, E1000_PRC1522); + temp = E1000_READ_REG(hw, E1000_PTC64); + temp = E1000_READ_REG(hw, E1000_PTC127); + temp = E1000_READ_REG(hw, E1000_PTC255); + temp = E1000_READ_REG(hw, E1000_PTC511); + temp = E1000_READ_REG(hw, E1000_PTC1023); + temp = E1000_READ_REG(hw, E1000_PTC1522); + + temp = E1000_READ_REG(hw, E1000_ALGNERRC); + temp = E1000_READ_REG(hw, E1000_RXERRC); + temp = E1000_READ_REG(hw, E1000_TNCRS); + temp = E1000_READ_REG(hw, E1000_CEXTERR); + temp = E1000_READ_REG(hw, E1000_TSCTC); + temp = E1000_READ_REG(hw, E1000_TSCTFC); + + temp = E1000_READ_REG(hw, E1000_MGTPRC); + temp = E1000_READ_REG(hw, E1000_MGTPDC); + temp = E1000_READ_REG(hw, E1000_MGTPTC); + + temp = E1000_READ_REG(hw, E1000_IAC); + temp = E1000_READ_REG(hw, E1000_ICRXOC); + + temp = E1000_READ_REG(hw, E1000_ICRXPTC); + temp = E1000_READ_REG(hw, E1000_ICRXATC); + temp = E1000_READ_REG(hw, E1000_ICTXPTC); + temp = E1000_READ_REG(hw, E1000_ICTXATC); + temp = E1000_READ_REG(hw, E1000_ICTXQEC); + temp = E1000_READ_REG(hw, E1000_ICTXQMTC); + temp = E1000_READ_REG(hw, E1000_ICRXDMTC); +} --- linux-2.6.27.orig/ubuntu/e1000e/e1000.h +++ linux-2.6.27/ubuntu/e1000e/e1000.h @@ -0,0 +1,444 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* Linux PRO/1000 Ethernet Driver main header file */ + +#ifndef _E1000_H_ +#define _E1000_H_ + +#include +#include +#include +#include + +#include "kcompat.h" + +#include "e1000_hw.h" + +struct e1000_info; + +#define e_printk(level, adapter, format, arg...) \ + printk(level "%s: %s: " format, pci_name(adapter->pdev), \ + (strchr(adapter->netdev->name, '%') ? "" : \ + adapter->netdev->name), ## arg) + +#define e_dbg(format, arg...) do { (void)(adapter); } while (0) + +#define e_err(format, arg...) \ + e_printk(KERN_ERR, adapter, format, ## arg) +#define e_info(format, arg...) \ + e_printk(KERN_INFO, adapter, format, ## arg) +#define e_warn(format, arg...) \ + e_printk(KERN_WARNING, adapter, format, ## arg) +#define e_notice(format, arg...) \ + e_printk(KERN_NOTICE, adapter, format, ## arg) + + +#ifdef CONFIG_E1000E_MSIX +/* Interrupt modes, as used by the IntMode paramter */ +#define E1000E_INT_MODE_LEGACY 0 +#define E1000E_INT_MODE_MSI 1 +#define E1000E_INT_MODE_MSIX 2 + +#endif /* CONFIG_E1000E_MSIX */ + +#define E1000_MAX_INTR 10 + +/* Tx/Rx descriptor defines */ +#define E1000_DEFAULT_TXD 256 +#define E1000_MAX_TXD 4096 +#define E1000_MIN_TXD 80 + +#define E1000_DEFAULT_RXD 256 +#define E1000_MAX_RXD 4096 +#define E1000_MIN_RXD 80 + +#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ +#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ + +/* Early Receive defines */ +#define E1000_ERT_2048 0x100 + +#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */ + +/* How many Tx Descriptors do we need to call netif_wake_queue ? */ +/* How many Rx Buffers do we bundle into one write to the hardware ? */ +#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ + +#define AUTO_ALL_MODES 0 +#define E1000_EEPROM_APME 0x0400 + +#define E1000_MNG_VLAN_NONE (-1) + +/* Number of packet split data buffers (not including the header buffer) */ +#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) + +enum e1000_boards { + board_82571, + board_82572, + board_82573, + board_82574, + board_80003es2lan, + board_ich8lan, + board_ich9lan, + board_ich10lan, +}; + +struct e1000_queue_stats { + u64 packets; + u64 bytes; +}; + +struct e1000_ps_page { + struct page *page; + u64 dma; /* must be u64 - written to hw */ +}; + +/* + * wrappers around a pointer to a socket buffer, + * so a DMA handle can be stored along with the buffer + */ +struct e1000_buffer { + dma_addr_t dma; + struct sk_buff *skb; + union { + /* Tx */ + struct { + unsigned long time_stamp; + u16 length; + u16 next_to_watch; + }; + /* Rx */ + /* arrays of page information for packet split */ + struct e1000_ps_page *ps_pages; + }; + struct page *page; +}; + +struct e1000_ring { + void *desc; /* pointer to ring memory */ + dma_addr_t dma; /* phys address of ring */ + unsigned int size; /* length of ring in bytes */ + unsigned int count; /* number of desc. in ring */ + + u16 next_to_use; + u16 next_to_clean; + + u16 head; + u16 tail; + + /* array of buffer information structs */ + struct e1000_buffer *buffer_info; + +#ifdef CONFIG_E1000E_MSIX + char name[IFNAMSIZ + 5]; + u32 ims_val; + u32 itr_val; + u16 itr_register; + int set_itr; + +#endif /* CONFIG_E1000E_MSIX */ + struct sk_buff *rx_skb_top; + + struct e1000_queue_stats stats; +}; + +#ifdef SIOCGMIIPHY +/* PHY register snapshot values */ +struct e1000_phy_regs { + u16 bmcr; /* basic mode control register */ + u16 bmsr; /* basic mode status register */ + u16 advertise; /* auto-negotiation advertisement */ + u16 lpa; /* link partner ability register */ + u16 expansion; /* auto-negotiation expansion reg */ + u16 ctrl1000; /* 1000BASE-T control register */ + u16 stat1000; /* 1000BASE-T status register */ + u16 estatus; /* extended status register */ +}; +#endif + +/* board specific private data structure */ +struct e1000_adapter { + struct timer_list watchdog_timer; + struct timer_list phy_info_timer; + struct timer_list blink_timer; + + struct work_struct reset_task; + struct work_struct watchdog_task; + + const struct e1000_info *ei; + + struct vlan_group *vlgrp; + u32 bd_number; + u32 rx_buffer_len; + u16 mng_vlan_id; + u16 link_speed; + u16 link_duplex; + + spinlock_t tx_queue_lock; /* prevent concurrent tail updates */ + + /* track device up/down/testing state */ + unsigned long state; + + /* Interrupt Throttle Rate */ + u32 itr; + u32 itr_setting; + u16 tx_itr; + u16 rx_itr; + + /* + * Tx + */ + struct e1000_ring *tx_ring /* One per active queue */ + ____cacheline_aligned_in_smp; + +#ifdef CONFIG_E1000E_NAPI + struct napi_struct napi; +#endif + + unsigned long tx_queue_len; + unsigned int restart_queue; + u32 txd_cmd; + + bool detect_tx_hung; + u8 tx_timeout_factor; + + u32 tx_int_delay; + u32 tx_abs_int_delay; + + unsigned int total_tx_bytes; + unsigned int total_tx_packets; + unsigned int total_rx_bytes; + unsigned int total_rx_packets; + + /* Tx stats */ + u64 tpt_old; + u64 colc_old; + u32 gotc; + u64 gotc_old; + u32 tx_timeout_count; + u32 tx_fifo_head; + u32 tx_head_addr; + u32 tx_fifo_size; + u32 tx_dma_failed; + + /* + * Rx + */ +#ifdef CONFIG_E1000E_NAPI + bool (*clean_rx) (struct e1000_adapter *adapter, + int *work_done, int work_to_do) + ____cacheline_aligned_in_smp; +#else + bool (*clean_rx) (struct e1000_adapter *adapter) + ____cacheline_aligned_in_smp; +#endif + void (*alloc_rx_buf) (struct e1000_adapter *adapter, + int cleaned_count); + struct e1000_ring *rx_ring; + + u32 rx_int_delay; + u32 rx_abs_int_delay; + + /* Rx stats */ + u64 hw_csum_err; + u64 hw_csum_good; + u64 rx_hdr_split; + u32 gorc; + u64 gorc_old; + u32 alloc_rx_buff_failed; + u32 rx_dma_failed; + + unsigned int rx_ps_pages; + u16 rx_ps_bsize0; + u32 max_frame_size; + u32 min_frame_size; + + /* OS defined structs */ + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; + spinlock_t stats_lock; /* prevent concurrent stats updates */ + + /* structs defined in e1000_hw.h */ + struct e1000_hw hw; + + struct e1000_hw_stats stats; + struct e1000_phy_info phy_info; + struct e1000_phy_stats phy_stats; + +#ifdef SIOCGMIIPHY + /* Snapshot of PHY registers */ + struct e1000_phy_regs phy_regs; +#endif + + struct e1000_ring test_tx_ring; + struct e1000_ring test_rx_ring; + u32 test_icr; + + u32 msg_enable; +#ifdef CONFIG_E1000E_MSIX + struct msix_entry *msix_entries; + int int_mode; + u32 eiac_mask; +#endif /* CONFIG_E1000E_MSIX */ + + u32 eeprom_wol; + u32 wol; + u32 pba; + + bool fc_autoneg; + + unsigned long led_status; + + unsigned int flags; + u32 *config_space; + u32 stats_freq_us; /* stats update freq (microseconds) */ +}; + +struct e1000_info { + e1000_mac_type mac; + unsigned int flags; + u32 pba; + void (*init_ops)(struct e1000_hw *); + s32 (*get_variants)(struct e1000_adapter *); +}; + +/* hardware capability, feature, and workaround flags */ +#define FLAG_HAS_AMT (1 << 0) +#define FLAG_HAS_FLASH (1 << 1) +#define FLAG_HAS_HW_VLAN_FILTER (1 << 2) +#define FLAG_HAS_WOL (1 << 3) +#define FLAG_HAS_ERT (1 << 4) +#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) +#define FLAG_HAS_SWSM_ON_LOAD (1 << 6) +#define FLAG_HAS_JUMBO_FRAMES (1 << 7) +#define FLAG_HAS_ASPM (1 << 8) +#define FLAG_IS_ICH (1 << 9) +#define FLAG_HAS_MSIX (1 << 10) +#define FLAG_HAS_SMART_POWER_DOWN (1 << 11) +#define FLAG_IS_QUAD_PORT_A (1 << 12) +#define FLAG_IS_QUAD_PORT (1 << 13) +#define FLAG_TIPG_MEDIUM_FOR_80003ESLAN (1 << 14) +#define FLAG_APME_IN_WUC (1 << 15) +#define FLAG_APME_IN_CTRL3 (1 << 16) +#define FLAG_APME_CHECK_PORT_B (1 << 17) +#define FLAG_DISABLE_FC_PAUSE_TIME (1 << 18) +#define FLAG_NO_WAKE_UCAST (1 << 19) +#define FLAG_MNG_PT_ENABLED (1 << 20) +#define FLAG_RESET_OVERWRITES_LAA (1 << 21) +#define FLAG_TARC_SPEED_MODE_BIT (1 << 22) +#define FLAG_TARC_SET_BIT_ZERO (1 << 23) +#define FLAG_RX_NEEDS_RESTART (1 << 24) +#define FLAG_LSC_GIG_SPEED_DROP (1 << 25) +#define FLAG_SMART_POWER_DOWN (1 << 26) +#define FLAG_MSI_ENABLED (1 << 27) +#define FLAG_RX_CSUM_ENABLED (1 << 28) +#define FLAG_TSO_FORCE (1 << 29) +#define FLAG_MSI_TEST_FAILED (1 << 30) +#define FLAG_RX_RESTART_NOW (1 << 31) + + +#define E1000_RX_DESC_PS(R, i) \ + (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) +#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) +#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) +#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) +#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) + +enum e1000_state_t { + __E1000_TESTING, + __E1000_RESETTING, + __E1000_DOWN +}; + +enum latency_range { + lowest_latency = 0, + low_latency = 1, + bulk_latency = 2, + latency_invalid = 255 +}; + +extern char e1000e_driver_name[]; +extern const char e1000e_driver_version[]; + +extern void e1000_check_options(struct e1000_adapter *adapter); +extern void e1000_set_ethtool_ops(struct net_device *netdev); +#ifdef ETHTOOL_OPS_COMPAT +extern int ethtool_ioctl(struct ifreq *ifr); +#endif + +extern int e1000_up(struct e1000_adapter *adapter); +extern void e1000_down(struct e1000_adapter *adapter); +extern void e1000_reinit_locked(struct e1000_adapter *adapter); +extern void e1000_reset(struct e1000_adapter *adapter); +extern int e1000_setup_rx_resources(struct e1000_adapter *adapter); +extern int e1000_setup_tx_resources(struct e1000_adapter *adapter); +extern void e1000_free_rx_resources(struct e1000_adapter *adapter); +extern void e1000_free_tx_resources(struct e1000_adapter *adapter); +extern void e1000_update_stats(struct e1000_adapter *adapter); +#ifdef CONFIG_E1000E_MSIX +extern void e1000_set_interrupt_capability(struct e1000_adapter *adapter); +extern void e1000_reset_interrupt_capability(struct e1000_adapter *adapter); +#endif + +extern unsigned int copybreak; + +static inline u32 __er32(struct e1000_hw *hw, unsigned long reg) +{ + return readl(hw->hw_addr + reg); +} + +static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val) +{ + writel(val, hw->hw_addr + reg); +} +#define er32(reg) E1000_READ_REG(hw, E1000_##reg) +#define ew32(reg,val) E1000_WRITE_REG(hw, E1000_##reg, (val)) +#define e1e_flush() er32(STATUS) + +extern void e1000_init_function_pointers_82571(struct e1000_hw *hw); +extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw); +extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw); + +static inline s32 e1000_read_mac_addr(struct e1000_hw *hw) +{ + if (hw->mac.ops.read_mac_addr) + return hw->mac.ops.read_mac_addr(hw); + + return e1000_read_mac_addr_generic(hw); +} + +static inline void e1000_power_up_phy(struct e1000_hw *hw) +{ + if(hw->phy.ops.power_up) + hw->phy.ops.power_up(hw); + hw->mac.ops.setup_link(hw); +} + +#endif /* _E1000_H_ */ --- linux-2.6.27.orig/ubuntu/e1000e/param.c +++ linux-2.6.27/ubuntu/e1000e/param.c @@ -0,0 +1,447 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include + +#include "e1000.h" + +/* + * This is the only thing that needs to be changed to adjust the + * maximum number of ports that the driver can manage. + */ + +#define E1000_MAX_NIC 32 + +#define OPTION_UNSET -1 +#define OPTION_DISABLED 0 +#define OPTION_ENABLED 1 + +#define COPYBREAK_DEFAULT 256 +unsigned int copybreak = COPYBREAK_DEFAULT; +module_param(copybreak, uint, 0644); +MODULE_PARM_DESC(copybreak, + "Maximum size of packet that is copied to a new buffer on receive"); + +/* + * All parameters are treated the same, as an integer array of values. + * This macro just reduces the need to repeat the same declaration code + * over and over (plus this helps to avoid typo bugs). + */ + +#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } +#ifndef module_param_array +/* Module Parameters are always initialized to -1, so that the driver + * can tell the difference between no user specified value or the + * user asking for the default value. + * The true default values are loaded in when e1000_check_options is called. + * + * This is a GCC extension to ANSI C. + * See the item "Labeled Elements in Initializers" in the section + * "Extensions to the C Language Family" of the GCC documentation. + */ +#define E1000_PARAM(X, desc) \ + static const int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ + static unsigned int num_##X; \ + MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \ + MODULE_PARM_DESC(X, desc); +#else +#define E1000_PARAM(X, desc) \ + static int __devinitdata X[E1000_MAX_NIC+1] \ + = E1000_PARAM_INIT; \ + static unsigned int num_##X; \ + module_param_array_named(X, X, int, &num_##X, 0); \ + MODULE_PARM_DESC(X, desc); +#endif + +/* + * Transmit Interrupt Delay in units of 1.024 microseconds + * Tx interrupt delay needs to typically be set to something non zero + * + * Valid Range: 0-65535 + */ +E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); +#define DEFAULT_TIDV 8 +#define MAX_TXDELAY 0xFFFF +#define MIN_TXDELAY 0 + +/* + * Transmit Absolute Interrupt Delay in units of 1.024 microseconds + * + * Valid Range: 0-65535 + */ +E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); +#define DEFAULT_TADV 32 +#define MAX_TXABSDELAY 0xFFFF +#define MIN_TXABSDELAY 0 + +/* + * Receive Interrupt Delay in units of 1.024 microseconds + * hardware will likely hang if you set this to anything but zero. + * + * Valid Range: 0-65535 + */ +E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); +#define DEFAULT_RDTR 0 +#define MAX_RXDELAY 0xFFFF +#define MIN_RXDELAY 0 + +/* + * Receive Absolute Interrupt Delay in units of 1.024 microseconds + * + * Valid Range: 0-65535 + */ +E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); +#define DEFAULT_RADV 8 +#define MAX_RXABSDELAY 0xFFFF +#define MIN_RXABSDELAY 0 + +/* + * Interrupt Throttle Rate (interrupts/sec) + * + * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative) + */ +E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); +#define DEFAULT_ITR 3 +#define MAX_ITR 100000 +#define MIN_ITR 100 + +#ifdef CONFIG_E1000E_MSIX +/* IntMode (Interrupt Mode) + * + * Valid Range: 0 - 2 + * + * Default Value: 2 (MSI-X) + */ +E1000_PARAM(IntMode, "Interrupt Mode"); +#define MAX_INTMODE 2 +#define MIN_INTMODE 0 + +#endif /* CONFIG_E1000E_MSIX */ +/* + * Enable Smart Power Down of the PHY + * + * Valid Range: 0, 1 + * + * Default Value: 0 (disabled) + */ +E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); + +/* + * Enable Kumeran Lock Loss workaround + * + * Valid Range: 0, 1 + * + * Default Value: 1 (enabled) + */ +E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); + +struct e1000_option { + enum { enable_option, range_option, list_option } type; + const char *name; + const char *err; + int def; + union { + struct { /* range_option info */ + int min; + int max; + } r; + struct { /* list_option info */ + int nr; + struct e1000_opt_list { int i; char *str; } *p; + } l; + } arg; +}; + +static int __devinit e1000_validate_option(unsigned int *value, + const struct e1000_option *opt, + struct e1000_adapter *adapter) +{ + if (*value == OPTION_UNSET) { + *value = opt->def; + return 0; + } + + switch (opt->type) { + case enable_option: + switch (*value) { + case OPTION_ENABLED: + e_info("%s Enabled\n", opt->name); + return 0; + case OPTION_DISABLED: + e_info("%s Disabled\n", opt->name); + return 0; + } + break; + case range_option: + if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { + e_info("%s set to %i\n", opt->name, *value); + return 0; + } + break; + case list_option: { + int i; + struct e1000_opt_list *ent; + + for (i = 0; i < opt->arg.l.nr; i++) { + ent = &opt->arg.l.p[i]; + if (*value == ent->i) { + if (ent->str[0] != '\0') + e_info("%s\n", ent->str); + return 0; + } + } + } + break; + default: + BUG(); + } + + e_info("Invalid %s value specified (%i) %s\n", opt->name, *value, + opt->err); + *value = opt->def; + return -1; +} + +/** + * e1000_check_options - Range Checking for Command Line Parameters + * @adapter: board private structure + * + * This routine checks all command line parameters for valid user + * input. If an invalid value is given, or if no user specified + * value exists, a default value is used. The final value is stored + * in a variable in the adapter structure. + **/ +void __devinit e1000_check_options(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + int bd = adapter->bd_number; + + if (bd >= E1000_MAX_NIC) { + e_notice("Warning: no configuration for board #%i\n", bd); + e_notice("Using defaults for all values\n"); + } + + { /* Transmit Interrupt Delay */ + const struct e1000_option opt = { + .type = range_option, + .name = "Transmit Interrupt Delay", + .err = "using default of " + __MODULE_STRING(DEFAULT_TIDV), + .def = DEFAULT_TIDV, + .arg = { .r = { .min = MIN_TXDELAY, + .max = MAX_TXDELAY } } + }; + + if (num_TxIntDelay > bd) { + adapter->tx_int_delay = TxIntDelay[bd]; + e1000_validate_option(&adapter->tx_int_delay, &opt, + adapter); + } else { + adapter->tx_int_delay = opt.def; + } + } + { /* Transmit Absolute Interrupt Delay */ + const struct e1000_option opt = { + .type = range_option, + .name = "Transmit Absolute Interrupt Delay", + .err = "using default of " + __MODULE_STRING(DEFAULT_TADV), + .def = DEFAULT_TADV, + .arg = { .r = { .min = MIN_TXABSDELAY, + .max = MAX_TXABSDELAY } } + }; + + if (num_TxAbsIntDelay > bd) { + adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; + e1000_validate_option(&adapter->tx_abs_int_delay, &opt, + adapter); + } else { + adapter->tx_abs_int_delay = opt.def; + } + } + { /* Receive Interrupt Delay */ + struct e1000_option opt = { + .type = range_option, + .name = "Receive Interrupt Delay", + .err = "using default of " + __MODULE_STRING(DEFAULT_RDTR), + .def = DEFAULT_RDTR, + .arg = { .r = { .min = MIN_RXDELAY, + .max = MAX_RXDELAY } } + }; + + /* + * modify min and default if 82573 for slow ping w/a, + * a value greater than 8 needs to be set for RDTR + */ + if (adapter->flags & FLAG_HAS_ASPM) { + opt.def = 32; + opt.arg.r.min = 8; + } + + if (num_RxIntDelay > bd) { + adapter->rx_int_delay = RxIntDelay[bd]; + e1000_validate_option(&adapter->rx_int_delay, &opt, + adapter); + } else { + adapter->rx_int_delay = opt.def; + } + } + { /* Receive Absolute Interrupt Delay */ + const struct e1000_option opt = { + .type = range_option, + .name = "Receive Absolute Interrupt Delay", + .err = "using default of " + __MODULE_STRING(DEFAULT_RADV), + .def = DEFAULT_RADV, + .arg = { .r = { .min = MIN_RXABSDELAY, + .max = MAX_RXABSDELAY } } + }; + + if (num_RxAbsIntDelay > bd) { + adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; + e1000_validate_option(&adapter->rx_abs_int_delay, &opt, + adapter); + } else { + adapter->rx_abs_int_delay = opt.def; + } + } + { /* Interrupt Throttling Rate */ + const struct e1000_option opt = { + .type = range_option, + .name = "Interrupt Throttling Rate (ints/sec)", + .err = "using default of " + __MODULE_STRING(DEFAULT_ITR), + .def = DEFAULT_ITR, + .arg = { .r = { .min = MIN_ITR, + .max = MAX_ITR } } + }; + + if (num_InterruptThrottleRate > bd) { + adapter->itr = InterruptThrottleRate[bd]; + switch (adapter->itr) { + case 0: + e_info("%s turned off\n", opt.name); + break; + case 1: + e_info("%s set to dynamic mode\n", opt.name); + adapter->itr_setting = adapter->itr; + adapter->itr = 20000; + break; + case 3: + e_info("%s set to dynamic conservative mode\n", + opt.name); + adapter->itr_setting = adapter->itr; + adapter->itr = 20000; + break; + default: + /* + * Save the setting, because the dynamic bits + * change itr. + */ + if (e1000_validate_option(&adapter->itr, &opt, + adapter) && + (adapter->itr == 3)) { + /* + * In case of invalid user value, + * default to conservative mode. + */ + adapter->itr_setting = adapter->itr; + adapter->itr = 20000; + } else { + /* + * Clear the lower two bits because + * they are used as control. + */ + adapter->itr_setting = + adapter->itr & ~3; + } + break; + } + } else { + adapter->itr_setting = opt.def; + adapter->itr = 20000; + } + } +#ifdef CONFIG_E1000E_MSIX + { /* Interrupt Mode */ + struct e1000_option opt = { + .type = range_option, + .name = "Interrupt Mode", + .err = "defaulting to 2 (MSI-X)", + .def = E1000E_INT_MODE_MSIX, + .arg = { .r = { .min = MIN_INTMODE, + .max = MAX_INTMODE }} + }; + + if (num_IntMode > bd) { + unsigned int int_mode = IntMode[bd]; + e1000_validate_option(&int_mode, &opt, adapter); + adapter->int_mode = int_mode; + } else { + adapter->int_mode = opt.def; + } + } +#endif /* CONFIG_E1000E_MSIX */ + { /* Smart Power Down */ + const struct e1000_option opt = { + .type = enable_option, + .name = "PHY Smart Power Down", + .err = "defaulting to Disabled", + .def = OPTION_DISABLED + }; + + if (num_SmartPowerDownEnable > bd) { + unsigned int spd = SmartPowerDownEnable[bd]; + e1000_validate_option(&spd, &opt, adapter); + if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) + && spd) + adapter->flags |= FLAG_SMART_POWER_DOWN; + } + } + { /* Kumeran Lock Loss Workaround */ + const struct e1000_option opt = { + .type = enable_option, + .name = "Kumeran Lock Loss Workaround", + .err = "defaulting to Enabled", + .def = OPTION_ENABLED + }; + + if (num_KumeranLockLoss > bd) { + unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; + e1000_validate_option(&kmrn_lock_loss, &opt, adapter); + if (hw->mac.type == e1000_ich8lan) + e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, + kmrn_lock_loss); + } else { + if (hw->mac.type == e1000_ich8lan) + e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, + opt.def); + } + } +} --- linux-2.6.27.orig/ubuntu/e1000e/e1000_defines.h +++ linux-2.6.27/ubuntu/e1000e/e1000_defines.h @@ -0,0 +1,1435 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_DEFINES_H_ +#define _E1000_DEFINES_H_ + +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ +#define REQ_TX_DESCRIPTOR_MULTIPLE 8 +#define REQ_RX_DESCRIPTOR_MULTIPLE 8 + +/* Definitions for power management and wakeup registers */ +/* Wake Up Control */ +#define E1000_WUC_APME 0x00000001 /* APM Enable */ +#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ +#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ +#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ +#define E1000_WUC_LSCWE 0x00000010 /* Link Status wake up enable */ +#define E1000_WUC_LSCWO 0x00000020 /* Link Status wake up override */ +#define E1000_WUC_SPM 0x80000000 /* Enable SPM */ +#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ + +/* Wake Up Filter Control */ +#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ +#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ +#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ +#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ +#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ +#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ +#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ +#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ +#define E1000_WUFC_IGNORE_TCO_BM 0x00000800 /* Ignore WakeOn TCO packets */ +#define E1000_WUFC_FLX0_BM 0x00001000 /* Flexible Filter 0 Enable */ +#define E1000_WUFC_FLX1_BM 0x00002000 /* Flexible Filter 1 Enable */ +#define E1000_WUFC_FLX2_BM 0x00004000 /* Flexible Filter 2 Enable */ +#define E1000_WUFC_FLX3_BM 0x00008000 /* Flexible Filter 3 Enable */ +#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ +#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ +#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ +#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ +#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ +#define E1000_WUFC_ALL_FILTERS_BM 0x0000F0FF /* Mask for all wakeup filters */ +#define E1000_WUFC_FLX_OFFSET_BM 12 /* Offset to the Flexible Filters bits */ +#define E1000_WUFC_FLX_FILTERS_BM 0x0000F000 /* Mask for the 4 flexible filters */ +#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ +#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ +#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ + +/* Wake Up Status */ +#define E1000_WUS_LNKC E1000_WUFC_LNKC +#define E1000_WUS_MAG E1000_WUFC_MAG +#define E1000_WUS_EX E1000_WUFC_EX +#define E1000_WUS_MC E1000_WUFC_MC +#define E1000_WUS_BC E1000_WUFC_BC +#define E1000_WUS_ARP E1000_WUFC_ARP +#define E1000_WUS_IPV4 E1000_WUFC_IPV4 +#define E1000_WUS_IPV6 E1000_WUFC_IPV6 +#define E1000_WUS_FLX0_BM E1000_WUFC_FLX0_BM +#define E1000_WUS_FLX1_BM E1000_WUFC_FLX1_BM +#define E1000_WUS_FLX2_BM E1000_WUFC_FLX2_BM +#define E1000_WUS_FLX3_BM E1000_WUFC_FLX3_BM +#define E1000_WUS_FLX_FILTERS_BM E1000_WUFC_FLX_FILTERS_BM +#define E1000_WUS_FLX0 E1000_WUFC_FLX0 +#define E1000_WUS_FLX1 E1000_WUFC_FLX1 +#define E1000_WUS_FLX2 E1000_WUFC_FLX2 +#define E1000_WUS_FLX3 E1000_WUFC_FLX3 +#define E1000_WUS_FLX_FILTERS E1000_WUFC_FLX_FILTERS + +/* Wake Up Packet Length */ +#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ + +/* Four Flexible Filters are supported */ +#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 + +/* Each Flexible Filter is at most 128 (0x80) bytes in length */ +#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 + +#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX +#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX +#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX + +/* Extended Device Control */ +#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ +#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ +#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN +#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ +#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ +/* Reserved (bits 4,5) in >= 82575 */ +#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Definable Pin 4 */ +#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */ +#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA +#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */ +#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ +/* SDP 4/5 (bits 8,9) are reserved in >= 82575 */ +#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ +#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ +#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ +#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ +#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ +#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ +#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ +#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ +#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ +#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_PCIX_SERDES 0x00800000 +#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 +#define E1000_CTRL_EXT_EIAME 0x01000000 +#define E1000_CTRL_EXT_IRCA 0x00000001 +#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 +#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 +#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 +#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 +#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 +#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */ +#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ +/* IAME enable bit (27) was removed in >= 82575 */ +#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ +#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ +#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ +#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ +#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 +#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ +#define E1000_CTRL_EXT_LSECCK 0x00001000 +#define E1000_I2CCMD_REG_ADDR_SHIFT 16 +#define E1000_I2CCMD_REG_ADDR 0x00FF0000 +#define E1000_I2CCMD_PHY_ADDR_SHIFT 24 +#define E1000_I2CCMD_PHY_ADDR 0x07000000 +#define E1000_I2CCMD_OPCODE_READ 0x08000000 +#define E1000_I2CCMD_OPCODE_WRITE 0x00000000 +#define E1000_I2CCMD_RESET 0x10000000 +#define E1000_I2CCMD_READY 0x20000000 +#define E1000_I2CCMD_INTERRUPT_ENA 0x40000000 +#define E1000_I2CCMD_ERROR 0x80000000 +#define E1000_MAX_SGMII_PHY_REG_ADDR 255 +#define E1000_I2CCMD_PHY_TIMEOUT 200 + +/* Receive Descriptor bit definitions */ +#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ +#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ +#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ +#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ +#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ +#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ +#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ +#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ +#define E1000_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */ +#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */ +#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ +#define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ +#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ +#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ +#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ +#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ +#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ +#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ +#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ +#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ +#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ +#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ +#define E1000_RXD_SPC_PRI_SHIFT 13 +#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ +#define E1000_RXD_SPC_CFI_SHIFT 12 + +#define E1000_RXDEXT_STATERR_CE 0x01000000 +#define E1000_RXDEXT_STATERR_SE 0x02000000 +#define E1000_RXDEXT_STATERR_SEQ 0x04000000 +#define E1000_RXDEXT_STATERR_CXE 0x10000000 +#define E1000_RXDEXT_STATERR_TCPE 0x20000000 +#define E1000_RXDEXT_STATERR_IPE 0x40000000 +#define E1000_RXDEXT_STATERR_RXE 0x80000000 + +#define E1000_RXDEXT_LSECH 0x01000000 +#define E1000_RXDEXT_LSECE_MASK 0x60000000 +#define E1000_RXDEXT_LSECE_NO_ERROR 0x00000000 +#define E1000_RXDEXT_LSECE_NO_SA_MATCH 0x20000000 +#define E1000_RXDEXT_LSECE_REPLAY_DETECT 0x40000000 +#define E1000_RXDEXT_LSECE_BAD_SIG 0x60000000 + +/* mask to determine if packets should be dropped due to frame errors */ +#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ + E1000_RXD_ERR_CE | \ + E1000_RXD_ERR_SE | \ + E1000_RXD_ERR_SEQ | \ + E1000_RXD_ERR_CXE | \ + E1000_RXD_ERR_RXE) + +/* Same mask, but for extended and packet split descriptors */ +#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ + E1000_RXDEXT_STATERR_CE | \ + E1000_RXDEXT_STATERR_SE | \ + E1000_RXDEXT_STATERR_SEQ | \ + E1000_RXDEXT_STATERR_CXE | \ + E1000_RXDEXT_STATERR_RXE) + +#define E1000_MRQC_ENABLE_MASK 0x00000007 +#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001 +#define E1000_MRQC_ENABLE_RSS_INT 0x00000004 +#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 +#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 +#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 +#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 +#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000 +#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 +#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 + +#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 +#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF + +/* Management Control */ +#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ +#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ +#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */ +#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */ +#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */ +#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */ +#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ +#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ +#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ +/* Enable Neighbor Discovery Filtering */ +#define E1000_MANC_NEIGHBOR_EN 0x00004000 +#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */ +#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ +#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ +#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ +#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */ +#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ +/* Enable MAC address filtering */ +#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 +/* Enable MNG packets to host memory */ +#define E1000_MANC_EN_MNG2HOST 0x00200000 +/* Enable IP address filtering */ +#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 +#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */ +#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */ +#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ +#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ +#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ +#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */ +#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */ +#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */ + +#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ +#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ + +/* Receive Control */ +#define E1000_RCTL_RST 0x00000001 /* Software reset */ +#define E1000_RCTL_EN 0x00000002 /* enable */ +#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ +#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ +#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ +#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ +#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ +#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ +#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ +#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ +#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */ +#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ +#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ +#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ +#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ +#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ +#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ +#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ +#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ +/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ +#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ +#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ +#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ +#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ +/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ +#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ +#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ +#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ +#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ +#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ +#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ +#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ +#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ +#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ +#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ +#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */ +#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */ + +/* + * Use byte values for the following shift parameters + * Usage: + * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & + * E1000_PSRCTL_BSIZE0_MASK) | + * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & + * E1000_PSRCTL_BSIZE1_MASK) | + * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & + * E1000_PSRCTL_BSIZE2_MASK) | + * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; + * E1000_PSRCTL_BSIZE3_MASK)) + * where value0 = [128..16256], default=256 + * value1 = [1024..64512], default=4096 + * value2 = [0..64512], default=4096 + * value3 = [0..64512], default=0 + */ + +#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F +#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 +#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 +#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 + +#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ +#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ +#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ +#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ + +/* SWFW_SYNC Definitions */ +#define E1000_SWFW_EEP_SM 0x1 +#define E1000_SWFW_PHY0_SM 0x2 +#define E1000_SWFW_PHY1_SM 0x4 +#define E1000_SWFW_CSR_SM 0x8 + +/* FACTPS Definitions */ +#define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */ +/* Device Control */ +#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ +#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ +#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ +#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */ +#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ +#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ +#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ +#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ +#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ +#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ +#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ +#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ +#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ +#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ +#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ +#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ +#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ +#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ +#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ +#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ +#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ +#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ +#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ +#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ +#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ +#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ +#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ +#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ +#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ +#define E1000_CTRL_RST 0x04000000 /* Global reset */ +#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ +#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ +#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ +#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ +#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ +#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */ +#define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */ + +/* Bit definitions for the Management Data IO (MDIO) and Management Data + * Clock (MDC) pins in the Device Control Register. + */ +#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 +#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0 +#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 +#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 +#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 +#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 +#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR +#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA + +#define E1000_CONNSW_ENRGSRC 0x4 +#define E1000_PCS_CFG_PCS_EN 8 +#define E1000_PCS_LCTL_FLV_LINK_UP 1 +#define E1000_PCS_LCTL_FSV_10 0 +#define E1000_PCS_LCTL_FSV_100 2 +#define E1000_PCS_LCTL_FSV_1000 4 +#define E1000_PCS_LCTL_FDV_FULL 8 +#define E1000_PCS_LCTL_FSD 0x10 +#define E1000_PCS_LCTL_FORCE_LINK 0x20 +#define E1000_PCS_LCTL_LOW_LINK_LATCH 0x40 +#define E1000_PCS_LCTL_AN_ENABLE 0x10000 +#define E1000_PCS_LCTL_AN_RESTART 0x20000 +#define E1000_PCS_LCTL_AN_TIMEOUT 0x40000 +#define E1000_PCS_LCTL_AN_SGMII_BYPASS 0x80000 +#define E1000_PCS_LCTL_AN_SGMII_TRIGGER 0x100000 +#define E1000_PCS_LCTL_FAST_LINK_TIMER 0x1000000 +#define E1000_PCS_LCTL_LINK_OK_FIX 0x2000000 +#define E1000_PCS_LCTL_CRS_ON_NI 0x4000000 +#define E1000_ENABLE_SERDES_LOOPBACK 0x0410 + +#define E1000_PCS_LSTS_LINK_OK 1 +#define E1000_PCS_LSTS_SPEED_10 0 +#define E1000_PCS_LSTS_SPEED_100 2 +#define E1000_PCS_LSTS_SPEED_1000 4 +#define E1000_PCS_LSTS_DUPLEX_FULL 8 +#define E1000_PCS_LSTS_SYNK_OK 0x10 +#define E1000_PCS_LSTS_AN_COMPLETE 0x10000 +#define E1000_PCS_LSTS_AN_PAGE_RX 0x20000 +#define E1000_PCS_LSTS_AN_TIMED_OUT 0x40000 +#define E1000_PCS_LSTS_AN_REMOTE_FAULT 0x80000 +#define E1000_PCS_LSTS_AN_ERROR_RWS 0x100000 + +/* Device Status */ +#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ +#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ +#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ +#define E1000_STATUS_FUNC_SHIFT 2 +#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ +#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ +#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ +#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ +#define E1000_STATUS_SPEED_MASK 0x000000C0 +#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ +#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ +#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ +#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ +#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ +#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */ +#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ +#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ +#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ +#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ +#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ +#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ +#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */ +#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ +#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ +#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ +#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ +#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ +#define E1000_STATUS_FUSE_8 0x04000000 +#define E1000_STATUS_FUSE_9 0x08000000 +#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */ +#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */ + +/* Constants used to interpret the masked PCI-X bus speed. */ +#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ +#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ +#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ + +#define SPEED_10 10 +#define SPEED_100 100 +#define SPEED_1000 1000 +#define HALF_DUPLEX 1 +#define FULL_DUPLEX 2 + +#define PHY_FORCE_TIME 20 + +#define ADVERTISE_10_HALF 0x0001 +#define ADVERTISE_10_FULL 0x0002 +#define ADVERTISE_100_HALF 0x0004 +#define ADVERTISE_100_FULL 0x0008 +#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ +#define ADVERTISE_1000_FULL 0x0020 + +/* 1000/H is not supported, nor spec-compliant. */ +#define E1000_ALL_SPEED_DUPLEX ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ + ADVERTISE_100_HALF | ADVERTISE_100_FULL | \ + ADVERTISE_1000_FULL) +#define E1000_ALL_NOT_GIG ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ + ADVERTISE_100_HALF | ADVERTISE_100_FULL) +#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) +#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) +#define E1000_ALL_FULL_DUPLEX (ADVERTISE_10_FULL | ADVERTISE_100_FULL | \ + ADVERTISE_1000_FULL) +#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) + +#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX + +/* LED Control */ +#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F +#define E1000_LEDCTL_LED0_MODE_SHIFT 0 +#define E1000_LEDCTL_LED0_BLINK_RATE 0x00000020 +#define E1000_LEDCTL_LED0_IVRT 0x00000040 +#define E1000_LEDCTL_LED0_BLINK 0x00000080 +#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 +#define E1000_LEDCTL_LED1_MODE_SHIFT 8 +#define E1000_LEDCTL_LED1_BLINK_RATE 0x00002000 +#define E1000_LEDCTL_LED1_IVRT 0x00004000 +#define E1000_LEDCTL_LED1_BLINK 0x00008000 +#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 +#define E1000_LEDCTL_LED2_MODE_SHIFT 16 +#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000 +#define E1000_LEDCTL_LED2_IVRT 0x00400000 +#define E1000_LEDCTL_LED2_BLINK 0x00800000 +#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 +#define E1000_LEDCTL_LED3_MODE_SHIFT 24 +#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000 +#define E1000_LEDCTL_LED3_IVRT 0x40000000 +#define E1000_LEDCTL_LED3_BLINK 0x80000000 + +#define E1000_LEDCTL_MODE_LINK_10_1000 0x0 +#define E1000_LEDCTL_MODE_LINK_100_1000 0x1 +#define E1000_LEDCTL_MODE_LINK_UP 0x2 +#define E1000_LEDCTL_MODE_ACTIVITY 0x3 +#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4 +#define E1000_LEDCTL_MODE_LINK_10 0x5 +#define E1000_LEDCTL_MODE_LINK_100 0x6 +#define E1000_LEDCTL_MODE_LINK_1000 0x7 +#define E1000_LEDCTL_MODE_PCIX_MODE 0x8 +#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9 +#define E1000_LEDCTL_MODE_COLLISION 0xA +#define E1000_LEDCTL_MODE_BUS_SPEED 0xB +#define E1000_LEDCTL_MODE_BUS_SIZE 0xC +#define E1000_LEDCTL_MODE_PAUSED 0xD +#define E1000_LEDCTL_MODE_LED_ON 0xE +#define E1000_LEDCTL_MODE_LED_OFF 0xF + +/* Transmit Descriptor bit definitions */ +#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ +#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ +#define E1000_TXD_POPTS_SHIFT 8 /* POPTS shift */ +#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ +#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ +#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ +#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ +#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ +#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ +#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ +#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ +#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ +#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ +#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ +#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ +#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ +#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ +#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ +#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ +#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ +#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ +/* Extended desc bits for Linksec and timesync */ +#define E1000_TXD_CMD_LINKSEC 0x10000000 /* Apply LinkSec on packet */ +#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ + +/* Transmit Control */ +#define E1000_TCTL_RST 0x00000001 /* software reset */ +#define E1000_TCTL_EN 0x00000002 /* enable tx */ +#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ +#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ +#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ +#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ +#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ +#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ +#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ +#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ +#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ + +/* Transmit Arbitration Count */ +#define E1000_TARC0_ENABLE 0x00000400 /* Enable Tx Queue 0 */ + +/* SerDes Control */ +#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 + +/* Receive Checksum Control */ +#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ +#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ +#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ +#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ +#define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ +#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ +#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ + +/* Header split receive */ +#define E1000_RFCTL_ISCSI_DIS 0x00000001 +#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E +#define E1000_RFCTL_ISCSI_DWC_SHIFT 1 +#define E1000_RFCTL_NFSW_DIS 0x00000040 +#define E1000_RFCTL_NFSR_DIS 0x00000080 +#define E1000_RFCTL_NFS_VER_MASK 0x00000300 +#define E1000_RFCTL_NFS_VER_SHIFT 8 +#define E1000_RFCTL_IPV6_DIS 0x00000400 +#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800 +#define E1000_RFCTL_ACK_DIS 0x00001000 +#define E1000_RFCTL_ACKD_DIS 0x00002000 +#define E1000_RFCTL_IPFRSP_DIS 0x00004000 +#define E1000_RFCTL_EXTEN 0x00008000 +#define E1000_RFCTL_IPV6_EX_DIS 0x00010000 +#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 + +/* Collision related configuration parameters */ +#define E1000_COLLISION_THRESHOLD 15 +#define E1000_CT_SHIFT 4 +#define E1000_COLLISION_DISTANCE 63 +#define E1000_COLD_SHIFT 12 + +/* Default values for the transmit IPG register */ +#define DEFAULT_82543_TIPG_IPGT_FIBER 9 +#define DEFAULT_82543_TIPG_IPGT_COPPER 8 + +#define E1000_TIPG_IPGT_MASK 0x000003FF +#define E1000_TIPG_IPGR1_MASK 0x000FFC00 +#define E1000_TIPG_IPGR2_MASK 0x3FF00000 + +#define DEFAULT_82543_TIPG_IPGR1 8 +#define E1000_TIPG_IPGR1_SHIFT 10 + +#define DEFAULT_82543_TIPG_IPGR2 6 +#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 +#define E1000_TIPG_IPGR2_SHIFT 20 + +/* Ethertype field values */ +#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ + +#define ETHERNET_FCS_SIZE 4 +#define MAX_JUMBO_FRAME_SIZE 0x3F00 + +/* Extended Configuration Control and Size */ +#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 +#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 +#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 +#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 +#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 +#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 +#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16 + +#define E1000_PHY_CTRL_SPD_EN 0x00000001 +#define E1000_PHY_CTRL_D0A_LPLU 0x00000002 +#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 +#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 +#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 + +#define E1000_KABGTXD_BGSQLBIAS 0x00050000 + +/* PBA constants */ +#define E1000_PBA_6K 0x0006 /* 6KB */ +#define E1000_PBA_8K 0x0008 /* 8KB */ +#define E1000_PBA_12K 0x000C /* 12KB */ +#define E1000_PBA_16K 0x0010 /* 16KB */ +#define E1000_PBA_20K 0x0014 +#define E1000_PBA_22K 0x0016 +#define E1000_PBA_24K 0x0018 +#define E1000_PBA_30K 0x001E +#define E1000_PBA_32K 0x0020 +#define E1000_PBA_34K 0x0022 +#define E1000_PBA_38K 0x0026 +#define E1000_PBA_40K 0x0028 +#define E1000_PBA_48K 0x0030 /* 48KB */ +#define E1000_PBA_64K 0x0040 /* 64KB */ + +#define E1000_PBS_16K E1000_PBA_16K +#define E1000_PBS_24K E1000_PBA_24K + +#define IFS_MAX 80 +#define IFS_MIN 40 +#define IFS_RATIO 4 +#define IFS_STEP 10 +#define MIN_NUM_XMITS 1000 + +/* SW Semaphore Register */ +#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ +#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ +#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ +#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ + +/* Interrupt Cause Read */ +#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ +#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ +#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ +#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ +#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ +#define E1000_ICR_RXO 0x00000040 /* rx overrun */ +#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ +#define E1000_ICR_VMMB 0x00000100 /* VM MB event */ +#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ +#define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */ +#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ +#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ +#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ +#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ +#define E1000_ICR_TXD_LOW 0x00008000 +#define E1000_ICR_SRPD 0x00010000 +#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ +#define E1000_ICR_MNG 0x00040000 /* Manageability event */ +#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ +#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ +#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ +#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ +#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ +#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */ +#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ +#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ +#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ +#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ +#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ +#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ +#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ + +/* Extended Interrupt Cause Read */ +#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ +#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */ +#define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */ +#define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */ +#define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */ +#define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */ +#define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */ +#define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */ +#define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ +#define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ +/* TCP Timer */ +#define E1000_TCPTIMER_KS 0x00000100 /* KickStart */ +#define E1000_TCPTIMER_COUNT_ENABLE 0x00000200 /* Count Enable */ +#define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */ +#define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */ + +/* + * This defines the bits that are set in the Interrupt Mask + * Set/Read Register. Each bit is documented below: + * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) + * o RXSEQ = Receive Sequence Error + */ +#define POLL_IMS_ENABLE_MASK ( \ + E1000_IMS_RXDMT0 | \ + E1000_IMS_RXSEQ) + +/* + * This defines the bits that are set in the Interrupt Mask + * Set/Read Register. Each bit is documented below: + * o RXT0 = Receiver Timer Interrupt (ring 0) + * o TXDW = Transmit Descriptor Written Back + * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) + * o RXSEQ = Receive Sequence Error + * o LSC = Link Status Change + */ +#define IMS_ENABLE_MASK ( \ + E1000_IMS_RXT0 | \ + E1000_IMS_TXDW | \ + E1000_IMS_RXDMT0 | \ + E1000_IMS_RXSEQ | \ + E1000_IMS_LSC) + +/* Interrupt Mask Set */ +#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */ +#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMS_SRPD E1000_ICR_SRPD +#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ +#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ +#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_IMS_DSW E1000_ICR_DSW +#define E1000_IMS_PHYINT E1000_ICR_PHYINT +#define E1000_IMS_EPRST E1000_ICR_EPRST +#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ +#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ +#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ +#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */ +#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */ + +/* Extended Interrupt Mask Set */ +#define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ +#define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ +#define E1000_EIMS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ +#define E1000_EIMS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ +#define E1000_EIMS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ +#define E1000_EIMS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ +#define E1000_EIMS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ +#define E1000_EIMS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ +#define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ +#define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ + +/* Interrupt Cause Set */ +#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */ +#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_ICS_SRPD E1000_ICR_SRPD +#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ +#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ +#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_ICS_DSW E1000_ICR_DSW +#define E1000_ICS_PHYINT E1000_ICR_PHYINT +#define E1000_ICS_EPRST E1000_ICR_EPRST + +/* Extended Interrupt Cause Set */ +#define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ +#define E1000_EICS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ +#define E1000_EICS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ +#define E1000_EICS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ +#define E1000_EICS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ +#define E1000_EICS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ +#define E1000_EICS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ +#define E1000_EICS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ +#define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ +#define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ + +/* Transmit Descriptor Control */ +#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ +#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ +#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ +#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ +#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ +#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ +#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */ +/* Enable the counting of descriptors still to be processed. */ +#define E1000_TXDCTL_COUNT_DESC 0x00400000 + +/* Flow Control Constants */ +#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 +#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 +#define FLOW_CONTROL_TYPE 0x8808 + +/* 802.1q VLAN Packet Size */ +#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ +#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ + +/* Receive Address */ +/* + * Number of high/low register pairs in the RAR. The RAR (Receive Address + * Registers) holds the directed and multicast addresses that we monitor. + * Technically, we have 16 spots. However, we reserve one of these spots + * (RAR[15]) for our directed address used by controllers with + * manageability enabled, allowing us room for 15 multicast addresses. + */ +#define E1000_RAR_ENTRIES 15 +#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ + +/* Error Codes */ +#define E1000_SUCCESS 0 +#define E1000_ERR_NVM 1 +#define E1000_ERR_PHY 2 +#define E1000_ERR_CONFIG 3 +#define E1000_ERR_PARAM 4 +#define E1000_ERR_MAC_INIT 5 +#define E1000_ERR_PHY_TYPE 6 +#define E1000_ERR_RESET 9 +#define E1000_ERR_MASTER_REQUESTS_PENDING 10 +#define E1000_ERR_HOST_INTERFACE_COMMAND 11 +#define E1000_BLK_PHY_RESET 12 +#define E1000_ERR_SWFW_SYNC 13 +#define E1000_NOT_IMPLEMENTED 14 + +/* Loop limit on how long we wait for auto-negotiation to complete */ +#define FIBER_LINK_UP_LIMIT 50 +#define COPPER_LINK_UP_LIMIT 10 +#define PHY_AUTO_NEG_LIMIT 45 +#define PHY_FORCE_LIMIT 20 +/* Number of 100 microseconds we wait for PCI Express master disable */ +#define MASTER_DISABLE_TIMEOUT 800 +/* Number of milliseconds we wait for PHY configuration done after MAC reset */ +#define PHY_CFG_TIMEOUT 100 +/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */ +#define MDIO_OWNERSHIP_TIMEOUT 10 +/* Number of milliseconds for NVM auto read done after MAC reset. */ +#define AUTO_READ_DONE_TIMEOUT 10 + +/* Flow Control */ +#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ +#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */ +#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ +#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ + +/* Transmit Configuration Word */ +#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ +#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ +#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ +#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ +#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ +#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */ +#define E1000_TXCW_NP 0x00008000 /* TXCW next page */ +#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */ +#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */ +#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ + +/* Receive Configuration Word */ +#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ +#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */ +#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ +#define E1000_RXCW_CC 0x10000000 /* Receive config change */ +#define E1000_RXCW_C 0x20000000 /* Receive config */ +#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ +#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ + +/* PCI Express Control */ +#define E1000_GCR_RXD_NO_SNOOP 0x00000001 +#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 +#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 +#define E1000_GCR_TXD_NO_SNOOP 0x00000008 +#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 +#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 + +#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ + E1000_GCR_RXDSCW_NO_SNOOP | \ + E1000_GCR_RXDSCR_NO_SNOOP | \ + E1000_GCR_TXD_NO_SNOOP | \ + E1000_GCR_TXDSCW_NO_SNOOP | \ + E1000_GCR_TXDSCR_NO_SNOOP) + +/* PHY Control Register */ +#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ +#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ +#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ +#define MII_CR_SPEED_1000 0x0040 +#define MII_CR_SPEED_100 0x2000 +#define MII_CR_SPEED_10 0x0000 + +/* PHY Status Register */ +#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ +#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ +#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ +#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ +#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ +#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ +#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ +#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ +#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ +#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ +#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ +#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ +#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ +#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ +#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ + +/* Autoneg Advertisement Register */ +#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ +#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ +#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ +#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ +#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ +#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ +#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ +#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ +#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ +#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Link Partner Ability Register (Base Page) */ +#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ +#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ +#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ +#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ +#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ +#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ +#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ +#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ +#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ +#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ +#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Autoneg Expansion Register */ +#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ +#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ +#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ +#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ +#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ + +/* 1000BASE-T Control Register */ +#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ +#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ +#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ +#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ + /* 0=DTE device */ +#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ + /* 0=Configure PHY as Slave */ +#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ + /* 0=Automatic Master/Slave config */ +#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ +#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ +#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ +#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ +#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ + +/* 1000BASE-T Status Register */ +#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ +#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ +#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ +#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ +#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ +#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ +#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local Tx is Master, 0=Slave */ +#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ + +#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 + +/* PHY 1000 MII Register/Bit Definitions */ +/* PHY Registers defined by IEEE */ +#define PHY_CONTROL 0x00 /* Control Register */ +#define PHY_STATUS 0x01 /* Status Register */ +#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ +#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ +#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */ +#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ +#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ + +/* NVM Control */ +#define E1000_EECD_SK 0x00000001 /* NVM Clock */ +#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ +#define E1000_EECD_DI 0x00000004 /* NVM Data In */ +#define E1000_EECD_DO 0x00000008 /* NVM Data Out */ +#define E1000_EECD_FWE_MASK 0x00000030 +#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ +#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ +#define E1000_EECD_FWE_SHIFT 4 +#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */ +#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */ +#define E1000_EECD_PRES 0x00000100 /* NVM Present */ +#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */ +/* NVM Addressing bits based on type 0=small, 1=large */ +#define E1000_EECD_ADDR_BITS 0x00000400 +#define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */ +#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ +#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ +#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ +#define E1000_EECD_SIZE_EX_SHIFT 11 +#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */ +#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */ +#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */ +#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ +#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ +#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ +#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ +#define E1000_EECD_SECVAL_SHIFT 22 + +#define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */ +#define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */ +#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write registers */ +#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ +#define E1000_NVM_RW_REG_START 1 /* Start operation */ +#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ +#define E1000_NVM_POLL_WRITE 1 /* Flag for polling for write complete */ +#define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */ +#define E1000_FLASH_UPDATES 2000 + +/* NVM Word Offsets */ +#define NVM_COMPAT 0x0003 +#define NVM_ID_LED_SETTINGS 0x0004 +#define NVM_VERSION 0x0005 +#define NVM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ +#define NVM_PHY_CLASS_WORD 0x0007 +#define NVM_INIT_CONTROL1_REG 0x000A +#define NVM_INIT_CONTROL2_REG 0x000F +#define NVM_SWDEF_PINS_CTRL_PORT_1 0x0010 +#define NVM_INIT_CONTROL3_PORT_B 0x0014 +#define NVM_INIT_3GIO_3 0x001A +#define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020 +#define NVM_INIT_CONTROL3_PORT_A 0x0024 +#define NVM_CFG 0x0012 +#define NVM_FLASH_VERSION 0x0032 +#define NVM_ALT_MAC_ADDR_PTR 0x0037 +#define NVM_CHECKSUM_REG 0x003F + +#define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */ +#define E1000_NVM_CFG_DONE_PORT_1 0x80000 /* ...for second port */ + +/* Mask bits for fields in Word 0x0f of the NVM */ +#define NVM_WORD0F_PAUSE_MASK 0x3000 +#define NVM_WORD0F_PAUSE 0x1000 +#define NVM_WORD0F_ASM_DIR 0x2000 +#define NVM_WORD0F_ANE 0x0800 +#define NVM_WORD0F_SWPDIO_EXT_MASK 0x00F0 +#define NVM_WORD0F_LPLU 0x0001 + +/* Mask bits for fields in Word 0x1a of the NVM */ +#define NVM_WORD1A_ASPM_MASK 0x000C + +/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ +#define NVM_SUM 0xBABA + +#define NVM_MAC_ADDR_OFFSET 0 +#define NVM_PBA_OFFSET_0 8 +#define NVM_PBA_OFFSET_1 9 +#define NVM_RESERVED_WORD 0xFFFF +#define NVM_PHY_CLASS_A 0x8000 +#define NVM_SERDES_AMPLITUDE_MASK 0x000F +#define NVM_SIZE_MASK 0x1C00 +#define NVM_SIZE_SHIFT 10 +#define NVM_WORD_SIZE_BASE_SHIFT 6 +#define NVM_SWDPIO_EXT_SHIFT 4 + +/* NVM Commands - Microwire */ +#define NVM_READ_OPCODE_MICROWIRE 0x6 /* NVM read opcode */ +#define NVM_WRITE_OPCODE_MICROWIRE 0x5 /* NVM write opcode */ +#define NVM_ERASE_OPCODE_MICROWIRE 0x7 /* NVM erase opcode */ +#define NVM_EWEN_OPCODE_MICROWIRE 0x13 /* NVM erase/write enable */ +#define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erase/write disable */ + +/* NVM Commands - SPI */ +#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ +#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */ +#define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */ +#define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ +#define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */ +#define NVM_WRDI_OPCODE_SPI 0x04 /* NVM reset Write Enable latch */ +#define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */ +#define NVM_WRSR_OPCODE_SPI 0x01 /* NVM write Status register */ + +/* SPI NVM Status Register */ +#define NVM_STATUS_RDY_SPI 0x01 +#define NVM_STATUS_WEN_SPI 0x02 +#define NVM_STATUS_BP0_SPI 0x04 +#define NVM_STATUS_BP1_SPI 0x08 +#define NVM_STATUS_WPEN_SPI 0x80 + +/* Word definitions for ID LED Settings */ +#define ID_LED_RESERVED_0000 0x0000 +#define ID_LED_RESERVED_FFFF 0xFFFF +#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ + (ID_LED_OFF1_OFF2 << 8) | \ + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_DEF1_DEF2)) +#define ID_LED_DEF1_DEF2 0x1 +#define ID_LED_DEF1_ON2 0x2 +#define ID_LED_DEF1_OFF2 0x3 +#define ID_LED_ON1_DEF2 0x4 +#define ID_LED_ON1_ON2 0x5 +#define ID_LED_ON1_OFF2 0x6 +#define ID_LED_OFF1_DEF2 0x7 +#define ID_LED_OFF1_ON2 0x8 +#define ID_LED_OFF1_OFF2 0x9 + +#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF +#define IGP_ACTIVITY_LED_ENABLE 0x0300 +#define IGP_LED3_MODE 0x07000000 + +/* PCI/PCI-X/PCI-EX Config space */ +#define PCIX_COMMAND_REGISTER 0xE6 +#define PCIX_STATUS_REGISTER_LO 0xE8 +#define PCIX_STATUS_REGISTER_HI 0xEA +#define PCI_HEADER_TYPE_REGISTER 0x0E +#define PCIE_LINK_STATUS 0x12 + +#define PCIX_COMMAND_MMRBC_MASK 0x000C +#define PCIX_COMMAND_MMRBC_SHIFT 0x2 +#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 +#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 +#define PCIX_STATUS_HI_MMRBC_4K 0x3 +#define PCIX_STATUS_HI_MMRBC_2K 0x2 +#define PCIX_STATUS_LO_FUNC_MASK 0x7 +#define PCI_HEADER_TYPE_MULTIFUNC 0x80 +#define PCIE_LINK_WIDTH_MASK 0x3F0 +#define PCIE_LINK_WIDTH_SHIFT 4 + +#ifndef ETH_ADDR_LEN +#define ETH_ADDR_LEN 6 +#endif + +#define PHY_REVISION_MASK 0xFFFFFFF0 +#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ +#define MAX_PHY_MULTI_PAGE_REG 0xF + +/* Bit definitions for valid PHY IDs. */ +/* + * I = Integrated + * E = External + */ +#define M88E1000_E_PHY_ID 0x01410C50 +#define M88E1000_I_PHY_ID 0x01410C30 +#define M88E1011_I_PHY_ID 0x01410C20 +#define IGP01E1000_I_PHY_ID 0x02A80380 +#define M88E1011_I_REV_4 0x04 +#define M88E1111_I_PHY_ID 0x01410CC0 +#define GG82563_E_PHY_ID 0x01410CA0 +#define IGP03E1000_E_PHY_ID 0x02A80390 +#define IFE_E_PHY_ID 0x02A80330 +#define IFE_PLUS_E_PHY_ID 0x02A80320 +#define IFE_C_E_PHY_ID 0x02A80310 +#define BME1000_E_PHY_ID 0x01410CB0 +#define BME1000_E_PHY_ID_R2 0x01410CB1 +#define M88_VENDOR 0x0141 + +/* M88E1000 Specific Registers */ +#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ +#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ +#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */ +#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */ +#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ +#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ + +#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ +#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ +#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ +#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ +#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ + +/* M88E1000 PHY Specific Control Register */ +#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ +#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ +#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ +/* 1=CLK125 low, 0=CLK125 toggling */ +#define M88E1000_PSCR_CLK125_DISABLE 0x0010 +#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ + /* Manual MDI configuration */ +#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ +/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ +#define M88E1000_PSCR_AUTO_X_1000T 0x0040 +/* Auto crossover enabled all speeds */ +#define M88E1000_PSCR_AUTO_X_MODE 0x0060 +/* + * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold + * 0=Normal 10BASE-T Rx Threshold + */ +#define M88E1000_PSCR_EN_10BT_EXT_DIST 0x0080 +/* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */ +#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 +#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ +#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ +#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ + +/* M88E1000 PHY Specific Status Register */ +#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ +#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ +#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ +#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ +/* + * 0 = <50M + * 1 = 50-80M + * 2 = 80-110M + * 3 = 110-140M + * 4 = >140M + */ +#define M88E1000_PSSR_CABLE_LENGTH 0x0380 +#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ +#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ +#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */ +#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ +#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ +#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */ +#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ +#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ + +#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 + +/* M88E1000 Extended PHY Specific Control Register */ +#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */ +/* + * 1 = Lost lock detect enabled. + * Will assert lost lock and bring + * link down if idle not seen + * within 1ms in 1000BASE-T + */ +#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 +/* + * Number of times we will attempt to autonegotiate before downshifting if we + * are the master + */ +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 +/* + * Number of times we will attempt to autonegotiate before downshifting if we + * are the slave + */ +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300 +#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */ +#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ +#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ + +/* M88EC018 Rev 2 specific DownShift settings */ +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00 + +/* BME1000 PHY Specific Control Register */ +#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ + +/* + * Bits... + * 15-5: page + * 4-0: register offset + */ +#define GG82563_PAGE_SHIFT 5 +#define GG82563_REG(page, reg) \ + (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) +#define GG82563_MIN_ALT_REG 30 + +/* GG82563 Specific Registers */ +#define GG82563_PHY_SPEC_CTRL \ + GG82563_REG(0, 16) /* PHY Specific Control */ +#define GG82563_PHY_SPEC_STATUS \ + GG82563_REG(0, 17) /* PHY Specific Status */ +#define GG82563_PHY_INT_ENABLE \ + GG82563_REG(0, 18) /* Interrupt Enable */ +#define GG82563_PHY_SPEC_STATUS_2 \ + GG82563_REG(0, 19) /* PHY Specific Status 2 */ +#define GG82563_PHY_RX_ERR_CNTR \ + GG82563_REG(0, 21) /* Receive Error Counter */ +#define GG82563_PHY_PAGE_SELECT \ + GG82563_REG(0, 22) /* Page Select */ +#define GG82563_PHY_SPEC_CTRL_2 \ + GG82563_REG(0, 26) /* PHY Specific Control 2 */ +#define GG82563_PHY_PAGE_SELECT_ALT \ + GG82563_REG(0, 29) /* Alternate Page Select */ +#define GG82563_PHY_TEST_CLK_CTRL \ + GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */ + +#define GG82563_PHY_MAC_SPEC_CTRL \ + GG82563_REG(2, 21) /* MAC Specific Control Register */ +#define GG82563_PHY_MAC_SPEC_CTRL_2 \ + GG82563_REG(2, 26) /* MAC Specific Control 2 */ + +#define GG82563_PHY_DSP_DISTANCE \ + GG82563_REG(5, 26) /* DSP Distance */ + +/* Page 193 - Port Control Registers */ +#define GG82563_PHY_KMRN_MODE_CTRL \ + GG82563_REG(193, 16) /* Kumeran Mode Control */ +#define GG82563_PHY_PORT_RESET \ + GG82563_REG(193, 17) /* Port Reset */ +#define GG82563_PHY_REVISION_ID \ + GG82563_REG(193, 18) /* Revision ID */ +#define GG82563_PHY_DEVICE_ID \ + GG82563_REG(193, 19) /* Device ID */ +#define GG82563_PHY_PWR_MGMT_CTRL \ + GG82563_REG(193, 20) /* Power Management Control */ +#define GG82563_PHY_RATE_ADAPT_CTRL \ + GG82563_REG(193, 25) /* Rate Adaptation Control */ + +/* Page 194 - KMRN Registers */ +#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \ + GG82563_REG(194, 16) /* FIFO's Control/Status */ +#define GG82563_PHY_KMRN_CTRL \ + GG82563_REG(194, 17) /* Control */ +#define GG82563_PHY_INBAND_CTRL \ + GG82563_REG(194, 18) /* Inband Control */ +#define GG82563_PHY_KMRN_DIAGNOSTIC \ + GG82563_REG(194, 19) /* Diagnostic */ +#define GG82563_PHY_ACK_TIMEOUTS \ + GG82563_REG(194, 20) /* Acknowledge Timeouts */ +#define GG82563_PHY_ADV_ABILITY \ + GG82563_REG(194, 21) /* Advertised Ability */ +#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \ + GG82563_REG(194, 23) /* Link Partner Advertised Ability */ +#define GG82563_PHY_ADV_NEXT_PAGE \ + GG82563_REG(194, 24) /* Advertised Next Page */ +#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \ + GG82563_REG(194, 25) /* Link Partner Advertised Next page */ +#define GG82563_PHY_KMRN_MISC \ + GG82563_REG(194, 26) /* Misc. */ + +/* MDI Control */ +#define E1000_MDIC_DATA_MASK 0x0000FFFF +#define E1000_MDIC_REG_MASK 0x001F0000 +#define E1000_MDIC_REG_SHIFT 16 +#define E1000_MDIC_PHY_MASK 0x03E00000 +#define E1000_MDIC_PHY_SHIFT 21 +#define E1000_MDIC_OP_WRITE 0x04000000 +#define E1000_MDIC_OP_READ 0x08000000 +#define E1000_MDIC_READY 0x10000000 +#define E1000_MDIC_INT_EN 0x20000000 +#define E1000_MDIC_ERROR 0x40000000 + +/* SerDes Control */ +#define E1000_GEN_CTL_READY 0x80000000 +#define E1000_GEN_CTL_ADDRESS_SHIFT 8 +#define E1000_GEN_POLL_TIMEOUT 640 + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_82571.h +++ linux-2.6.27/ubuntu/e1000e/e1000_82571.h @@ -0,0 +1,53 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_82571_H_ +#define _E1000_82571_H_ + +#define ID_LED_RESERVED_F746 0xF746 +#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \ + (ID_LED_OFF1_ON2 << 8) | \ + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_DEF1_DEF2)) + +#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 + +/* Intr Throttling - RW */ +#define E1000_EITR_82574(_n) (0x000E8 + (0x4 * (_n))) + +#define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ +#define E1000_EIAC_MASK_82574 0x01F00000 + +#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ + +#define E1000_RXCFGL 0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */ + +bool e1000_get_laa_state_82571(struct e1000_hw *hw); +void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state); + +#endif --- linux-2.6.27.orig/ubuntu/e1000e/e1000_82571.c +++ linux-2.6.27/ubuntu/e1000e/e1000_82571.c @@ -0,0 +1,1538 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* e1000_82571 + * e1000_82572 + * e1000_82573 + * e1000_82574 + */ + +#include "e1000_hw.h" + +static s32 e1000_init_phy_params_82571(struct e1000_hw *hw); +static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw); +static s32 e1000_init_mac_params_82571(struct e1000_hw *hw); +static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw); +static void e1000_release_nvm_82571(struct e1000_hw *hw); +static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw); +static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw); +static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw); +static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, + bool active); +static s32 e1000_reset_hw_82571(struct e1000_hw *hw); +static s32 e1000_init_hw_82571(struct e1000_hw *hw); +static void e1000_clear_vfta_82571(struct e1000_hw *hw); +static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); +static s32 e1000_led_on_82574(struct e1000_hw *hw); +static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count, + u32 rar_used_count, u32 rar_count); +static s32 e1000_setup_link_82571(struct e1000_hw *hw); +static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw); +static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw); +static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data); +static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); +static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw); +static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw); +static s32 e1000_get_phy_id_82571(struct e1000_hw *hw); +static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); +static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw); +static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); +static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw); +static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); + +struct e1000_dev_spec_82571 { + bool laa_is_present; +}; + +/** + * e1000_init_phy_params_82571 - Init PHY func ptrs. + * @hw: pointer to the HW structure + * + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_init_phy_params_82571"); + + if (hw->phy.media_type != e1000_media_type_copper) { + phy->type = e1000_phy_none; + goto out; + } + + phy->addr = 1; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->reset_delay_us = 100; + + phy->ops.acquire = e1000_get_hw_semaphore_82571; + phy->ops.check_polarity = e1000_check_polarity_igp; + phy->ops.check_reset_block = e1000_check_reset_block_generic; + phy->ops.release = e1000_put_hw_semaphore_82571; + phy->ops.reset = e1000_phy_hw_reset_generic; + phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82571; + phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_82571; + + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + phy->type = e1000_phy_igp_2; + phy->ops.get_cfg_done = e1000_get_cfg_done_82571; + phy->ops.get_info = e1000_get_phy_info_igp; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; + phy->ops.get_cable_length = e1000_get_cable_length_igp_2; + phy->ops.read_reg = e1000_read_phy_reg_igp; + phy->ops.write_reg = e1000_write_phy_reg_igp; + + /* This uses above function pointers */ + ret_val = e1000_get_phy_id_82571(hw); + + /* Verify PHY ID */ + if (phy->id != IGP01E1000_I_PHY_ID) { + ret_val = -E1000_ERR_PHY; + goto out; + } + break; + case e1000_82573: + phy->type = e1000_phy_m88; + phy->ops.get_cfg_done = e1000_get_cfg_done_generic; + phy->ops.get_info = e1000_get_phy_info_m88; + phy->ops.commit = e1000_phy_sw_reset_generic; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; + phy->ops.get_cable_length = e1000_get_cable_length_m88; + phy->ops.read_reg = e1000_read_phy_reg_m88; + phy->ops.write_reg = e1000_write_phy_reg_m88; + + /* This uses above function pointers */ + ret_val = e1000_get_phy_id_82571(hw); + + /* Verify PHY ID */ + if (phy->id != M88E1111_I_PHY_ID) { + ret_val = -E1000_ERR_PHY; + DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id); + goto out; + } + break; + case e1000_82574: + phy->type = e1000_phy_bm; + phy->ops.get_cfg_done = e1000_get_cfg_done_generic; + phy->ops.get_info = e1000_get_phy_info_m88; + phy->ops.commit = e1000_phy_sw_reset_generic; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; + phy->ops.get_cable_length = e1000_get_cable_length_m88; + phy->ops.read_reg = e1000_read_phy_reg_bm2; + phy->ops.write_reg = e1000_write_phy_reg_bm2; + + /* This uses above function pointers */ + ret_val = e1000_get_phy_id_82571(hw); + /* Verify PHY ID */ + if (phy->id != BME1000_E_PHY_ID_R2) { + ret_val = -E1000_ERR_PHY; + DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id); + goto out; + } + break; + default: + ret_val = -E1000_ERR_PHY; + goto out; + break; + } + +out: + return ret_val; +} + +/** + * e1000_init_nvm_params_82571 - Init NVM func ptrs. + * @hw: pointer to the HW structure + * + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = E1000_READ_REG(hw, E1000_EECD); + u16 size; + + DEBUGFUNC("e1000_init_nvm_params_82571"); + + nvm->opcode_bits = 8; + nvm->delay_usec = 1; + switch (nvm->override) { + case e1000_nvm_override_spi_large: + nvm->page_size = 32; + nvm->address_bits = 16; + break; + case e1000_nvm_override_spi_small: + nvm->page_size = 8; + nvm->address_bits = 8; + break; + default: + nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; + break; + } + + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + if (((eecd >> 15) & 0x3) == 0x3) { + nvm->type = e1000_nvm_flash_hw; + nvm->word_size = 2048; + /* + * Autonomous Flash update bit must be cleared due + * to Flash update issue. + */ + eecd &= ~E1000_EECD_AUPDEN; + E1000_WRITE_REG(hw, E1000_EECD, eecd); + break; + } + /* Fall Through */ + default: + nvm->type = e1000_nvm_eeprom_spi; + size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> + E1000_EECD_SIZE_EX_SHIFT); + /* + * Added to a constant, "size" becomes the left-shift value + * for setting word_size. + */ + size += NVM_WORD_SIZE_BASE_SHIFT; + + /* EEPROM access above 16k is unsupported */ + if (size > 14) + size = 14; + nvm->word_size = 1 << size; + break; + } + + /* Function Pointers */ + nvm->ops.acquire = e1000_acquire_nvm_82571; + nvm->ops.read = e1000_read_nvm_eerd; + nvm->ops.release = e1000_release_nvm_82571; + nvm->ops.update = e1000_update_nvm_checksum_82571; + nvm->ops.validate = e1000_validate_nvm_checksum_82571; + nvm->ops.valid_led_default = e1000_valid_led_default_82571; + nvm->ops.write = e1000_write_nvm_82571; + + return E1000_SUCCESS; +} + +/** + * e1000_init_mac_params_82571 - Init MAC func ptrs. + * @hw: pointer to the HW structure + * + * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_init_mac_params_82571"); + + /* Set media type */ + switch (hw->device_id) { + case E1000_DEV_ID_82571EB_FIBER: + case E1000_DEV_ID_82572EI_FIBER: + case E1000_DEV_ID_82571EB_QUAD_FIBER: + hw->phy.media_type = e1000_media_type_fiber; + break; + case E1000_DEV_ID_82571EB_SERDES: + case E1000_DEV_ID_82571EB_SERDES_DUAL: + case E1000_DEV_ID_82571EB_SERDES_QUAD: + case E1000_DEV_ID_82572EI_SERDES: + hw->phy.media_type = e1000_media_type_internal_serdes; + break; + default: + hw->phy.media_type = e1000_media_type_copper; + break; + } + + /* Set mta register count */ + mac->mta_reg_count = 128; + /* Set rar entry count */ + mac->rar_entry_count = E1000_RAR_ENTRIES; + /* Set if part includes ASF firmware */ + mac->asf_firmware_present = true; + /* Set if manageability features are enabled. */ + mac->arc_subsystem_valid = + (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK) + ? true : false; + + /* Function pointers */ + + /* bus type/speed/width */ + mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; + /* reset */ + mac->ops.reset_hw = e1000_reset_hw_82571; + /* hw initialization */ + mac->ops.init_hw = e1000_init_hw_82571; + /* link setup */ + mac->ops.setup_link = e1000_setup_link_82571; + /* physical interface link setup */ + mac->ops.setup_physical_interface = + (hw->phy.media_type == e1000_media_type_copper) + ? e1000_setup_copper_link_82571 + : e1000_setup_fiber_serdes_link_82571; + /* check for link */ + switch (hw->phy.media_type) { + case e1000_media_type_copper: + mac->ops.check_for_link = e1000_check_for_copper_link_generic; + break; + case e1000_media_type_fiber: + mac->ops.check_for_link = e1000_check_for_fiber_link_generic; + break; + case e1000_media_type_internal_serdes: + mac->ops.check_for_link = e1000_check_for_serdes_link_generic; + break; + default: + ret_val = -E1000_ERR_CONFIG; + goto out; + break; + } + /* check management mode */ + switch (hw->mac.type) { + case e1000_82574: + mac->ops.check_mng_mode = e1000_check_mng_mode_82574; + break; + default: + mac->ops.check_mng_mode = e1000_check_mng_mode_generic; + break; + } + /* multicast address update */ + mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82571; + /* writing VFTA */ + mac->ops.write_vfta = e1000_write_vfta_generic; + /* clearing VFTA */ + mac->ops.clear_vfta = e1000_clear_vfta_82571; + /* setting MTA */ + mac->ops.mta_set = e1000_mta_set_generic; + /* read mac address */ + mac->ops.read_mac_addr = e1000_read_mac_addr_82571; + /* blink LED */ + mac->ops.blink_led = e1000_blink_led_generic; + /* setup LED */ + mac->ops.setup_led = e1000_setup_led_generic; + /* cleanup LED */ + mac->ops.cleanup_led = e1000_cleanup_led_generic; + /* turn on/off LED */ + switch (hw->mac.type) { + case e1000_82574: + mac->ops.led_on = e1000_led_on_82574; + break; + default: + mac->ops.led_on = e1000_led_on_generic; + break; + } + mac->ops.led_off = e1000_led_off_generic; + /* remove device */ + mac->ops.remove_device = e1000_remove_device_generic; + /* clear hardware counters */ + mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82571; + /* link info */ + mac->ops.get_link_up_info = + (hw->phy.media_type == e1000_media_type_copper) + ? e1000_get_speed_and_duplex_copper_generic + : e1000_get_speed_and_duplex_fiber_serdes_generic; + + hw->dev_spec_size = sizeof(struct e1000_dev_spec_82571); + + /* Device-specific structure allocation */ + ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); + +out: + return ret_val; +} + +/** + * e1000_init_function_pointers_82571 - Init func ptrs. + * @hw: pointer to the HW structure + * + * The only function explicitly called by the api module to initialize + * all function pointers and parameters. + **/ +void e1000_init_function_pointers_82571(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_init_function_pointers_82571"); + + e1000_init_mac_ops_generic(hw); + e1000_init_nvm_ops_generic(hw); + hw->mac.ops.init_params = e1000_init_mac_params_82571; + hw->nvm.ops.init_params = e1000_init_nvm_params_82571; + hw->phy.ops.init_params = e1000_init_phy_params_82571; +} + +/** + * e1000_get_phy_id_82571 - Retrieve the PHY ID and revision + * @hw: pointer to the HW structure + * + * Reads the PHY registers and stores the PHY ID and possibly the PHY + * revision in the hardware structure. + **/ +static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_id = 0; + + DEBUGFUNC("e1000_get_phy_id_82571"); + + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + /* + * The 82571 firmware may still be configuring the PHY. + * In this case, we cannot access the PHY until the + * configuration is done. So we explicitly set the + * PHY ID. + */ + phy->id = IGP01E1000_I_PHY_ID; + break; + case e1000_82573: + ret_val = e1000_get_phy_id(hw); + break; + case e1000_82574: + ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); + if (ret_val) + goto out; + + phy->id = (u32)(phy_id << 16); + usec_delay(20); + ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); + if (ret_val) + goto out; + + phy->id |= (u32)(phy_id); + phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); + break; + default: + ret_val = -E1000_ERR_PHY; + break; + } + +out: + return ret_val; +} + +/** + * e1000_get_hw_semaphore_82571 - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the HW semaphore to access the PHY or NVM + **/ +static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) +{ + u32 swsm; + s32 ret_val = E1000_SUCCESS; + s32 timeout = hw->nvm.word_size + 1; + s32 i = 0; + + DEBUGFUNC("e1000_get_hw_semaphore_82571"); + + /* Get the FW semaphore. */ + for (i = 0; i < timeout; i++) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); + + /* Semaphore acquired if bit latched */ + if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) + break; + + usec_delay(50); + } + + if (i == timeout) { + /* Release semaphores */ + e1000_put_hw_semaphore_generic(hw); + DEBUGOUT("Driver can't access the NVM\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_put_hw_semaphore_82571 - Release hardware semaphore + * @hw: pointer to the HW structure + * + * Release hardware semaphore used to access the PHY or NVM + **/ +static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) +{ + u32 swsm; + + DEBUGFUNC("e1000_put_hw_semaphore_82571"); + + swsm = E1000_READ_REG(hw, E1000_SWSM); + + swsm &= ~E1000_SWSM_SWESMBI; + + E1000_WRITE_REG(hw, E1000_SWSM, swsm); +} + +/** + * e1000_acquire_nvm_82571 - Request for access to the EEPROM + * @hw: pointer to the HW structure + * + * To gain access to the EEPROM, first we must obtain a hardware semaphore. + * Then for non-82573 hardware, set the EEPROM access request bit and wait + * for EEPROM access grant bit. If the access grant bit is not set, release + * hardware semaphore. + **/ +static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) +{ + s32 ret_val; + + DEBUGFUNC("e1000_acquire_nvm_82571"); + + ret_val = e1000_get_hw_semaphore_82571(hw); + if (ret_val) + goto out; + + if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574) + ret_val = e1000_acquire_nvm_generic(hw); + + if (ret_val) + e1000_put_hw_semaphore_82571(hw); + +out: + return ret_val; +} + +/** + * e1000_release_nvm_82571 - Release exclusive access to EEPROM + * @hw: pointer to the HW structure + * + * Stop any current commands to the EEPROM and clear the EEPROM request bit. + **/ +static void e1000_release_nvm_82571(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_release_nvm_82571"); + + e1000_release_nvm_generic(hw); + e1000_put_hw_semaphore_82571(hw); +} + +/** + * e1000_write_nvm_82571 - Write to EEPROM using appropriate interface + * @hw: pointer to the HW structure + * @offset: offset within the EEPROM to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the EEPROM + * + * For non-82573 silicon, write data to EEPROM at offset using SPI interface. + * + * If e1000_update_nvm_checksum is not called after this function, the + * EEPROM will most likely contain an invalid checksum. + **/ +static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_nvm_82571"); + + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); + break; + case e1000_82571: + case e1000_82572: + ret_val = e1000_write_nvm_spi(hw, offset, words, data); + break; + default: + ret_val = -E1000_ERR_NVM; + break; + } + + return ret_val; +} + +/** + * e1000_update_nvm_checksum_82571 - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM checksum by reading/adding each word of the EEPROM + * up to the checksum. Then calculates the EEPROM checksum and writes the + * value to the EEPROM. + **/ +static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) +{ + u32 eecd; + s32 ret_val; + u16 i; + + DEBUGFUNC("e1000_update_nvm_checksum_82571"); + + ret_val = e1000_update_nvm_checksum_generic(hw); + if (ret_val) + goto out; + + /* + * If our nvm is an EEPROM, then we're done + * otherwise, commit the checksum to the flash NVM. + */ + if (hw->nvm.type != e1000_nvm_flash_hw) + goto out; + + /* Check for pending operations. */ + for (i = 0; i < E1000_FLASH_UPDATES; i++) { + msec_delay(1); + if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0) + break; + } + + if (i == E1000_FLASH_UPDATES) { + ret_val = -E1000_ERR_NVM; + goto out; + } + + /* Reset the firmware if using STM opcode. */ + if ((E1000_READ_REG(hw, E1000_FLOP) & 0xFF00) == E1000_STM_OPCODE) { + /* + * The enabling of and the actual reset must be done + * in two write cycles. + */ + E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET_ENABLE); + E1000_WRITE_FLUSH(hw); + E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET); + } + + /* Commit the write to flash */ + eecd = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD; + E1000_WRITE_REG(hw, E1000_EECD, eecd); + + for (i = 0; i < E1000_FLASH_UPDATES; i++) { + msec_delay(1); + if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0) + break; + } + + if (i == E1000_FLASH_UPDATES) { + ret_val = -E1000_ERR_NVM; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Calculates the EEPROM checksum by reading/adding each word of the EEPROM + * and then verifies that the sum of the EEPROM is equal to 0xBABA. + **/ +static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_validate_nvm_checksum_82571"); + + if (hw->nvm.type == e1000_nvm_flash_hw) + e1000_fix_nvm_checksum_82571(hw); + + return e1000_validate_nvm_checksum_generic(hw); +} + +/** + * e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon + * @hw: pointer to the HW structure + * @offset: offset within the EEPROM to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the EEPROM + * + * After checking for invalid values, poll the EEPROM to ensure the previous + * command has completed before trying to write the next word. After write + * poll for completion. + * + * If e1000_update_nvm_checksum is not called after this function, the + * EEPROM will most likely contain an invalid checksum. + **/ +static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 i, eewr = 0; + s32 ret_val = 0; + + DEBUGFUNC("e1000_write_nvm_eewr_82571"); + + /* + * A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + for (i = 0; i < words; i++) { + eewr = (data[i] << E1000_NVM_RW_REG_DATA) | + ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | + E1000_NVM_RW_REG_START; + + ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); + if (ret_val) + break; + + E1000_WRITE_REG(hw, E1000_EEWR, eewr); + + ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); + if (ret_val) + break; + } + +out: + return ret_val; +} + +/** + * e1000_get_cfg_done_82571 - Poll for configuration done + * @hw: pointer to the HW structure + * + * Reads the management control register for the config done bit to be set. + **/ +static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) +{ + s32 timeout = PHY_CFG_TIMEOUT; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_get_cfg_done_82571"); + + while (timeout) { + if (E1000_READ_REG(hw, E1000_EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) + break; + msec_delay(1); + timeout--; + } + if (!timeout) { + DEBUGOUT("MNG configuration cycle has not completed.\n"); + ret_val = -E1000_ERR_RESET; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state + * @hw: pointer to the HW structure + * @active: true to enable LPLU, false to disable + * + * Sets the LPLU D0 state according to the active flag. When activating LPLU + * this function also disables smart speed and vice versa. LPLU will not be + * activated unless the device autonegotiation advertisement meets standards + * of either 10 or 10/100 or 10/100/1000 at all duplexes. This is a function + * pointer entry point only called by PHY setup routines. + **/ +static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 data; + + DEBUGFUNC("e1000_set_d0_lplu_state_82571"); + + if (!(phy->ops.read_reg)) + goto out; + + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); + if (ret_val) + goto out; + + if (active) { + data |= IGP02E1000_PM_D0_LPLU; + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, + data); + if (ret_val) + goto out; + + /* When LPLU is enabled, we should disable SmartSpeed */ + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &data); + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } else { + data &= ~IGP02E1000_PM_D0_LPLU; + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, + data); + /* + * LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. + */ + if (phy->smart_speed == e1000_smart_speed_on) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data |= IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } else if (phy->smart_speed == e1000_smart_speed_off) { + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } + } + +out: + return ret_val; +} + +/** + * e1000_reset_hw_82571 - Reset hardware + * @hw: pointer to the HW structure + * + * This resets the hardware into a known state. This is a + * function pointer entry point called by the api module. + **/ +static s32 e1000_reset_hw_82571(struct e1000_hw *hw) +{ + u32 ctrl, extcnf_ctrl, ctrl_ext, icr; + s32 ret_val; + u16 i = 0; + + DEBUGFUNC("e1000_reset_hw_82571"); + + /* + * Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = e1000_disable_pcie_master_generic(hw); + if (ret_val) { + DEBUGOUT("PCI-E Master disable polling has failed.\n"); + } + + DEBUGOUT("Masking off all interrupts\n"); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + + E1000_WRITE_REG(hw, E1000_RCTL, 0); + E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); + E1000_WRITE_FLUSH(hw); + + msec_delay(10); + + /* + * Must acquire the MDIO ownership before MAC reset. + * Ownership defaults to firmware after a reset. + */ + if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + + do { + E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); + extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); + + if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) + break; + + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + + msec_delay(2); + i++; + } while (i < MDIO_OWNERSHIP_TIMEOUT); + } + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + + DEBUGOUT("Issuing a global reset to MAC\n"); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); + + if (hw->nvm.type == e1000_nvm_flash_hw) { + usec_delay(10); + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + } + + ret_val = e1000_get_auto_rd_done_generic(hw); + if (ret_val) + /* We don't want to continue accessing MAC registers. */ + goto out; + + /* + * Phy configuration from NVM just starts after EECD_AUTO_RD is set. + * Need to wait for Phy configuration completion before accessing + * NVM and Phy. + */ + if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) + msec_delay(25); + + /* Clear any pending interrupt events. */ + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + icr = E1000_READ_REG(hw, E1000_ICR); + + if (!(e1000_check_alt_mac_addr_generic(hw))) + e1000_set_laa_state_82571(hw, true); + +out: + return ret_val; +} + +/** + * e1000_init_hw_82571 - Initialize hardware + * @hw: pointer to the HW structure + * + * This inits the hardware readying it for operation. + **/ +static s32 e1000_init_hw_82571(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 reg_data; + s32 ret_val; + u16 i, rar_count = mac->rar_entry_count; + + DEBUGFUNC("e1000_init_hw_82571"); + + e1000_initialize_hw_bits_82571(hw); + + /* Initialize identification LED */ + ret_val = e1000_id_led_init_generic(hw); + if (ret_val) { + DEBUGOUT("Error initializing identification LED\n"); + /* This is not fatal and we should not stop init due to this */ + } + + /* Disabling VLAN filtering */ + DEBUGOUT("Initializing the IEEE VLAN\n"); + mac->ops.clear_vfta(hw); + + /* Setup the receive address. */ + /* + * If, however, a locally administered address was assigned to the + * 82571, we must reserve a RAR for it to work around an issue where + * resetting one port will reload the MAC on the other port. + */ + if (e1000_get_laa_state_82571(hw)) + rar_count--; + e1000_init_rx_addrs_generic(hw, rar_count); + + /* Zero out the Multicast HASH table */ + DEBUGOUT("Zeroing the MTA\n"); + for (i = 0; i < mac->mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + + /* Setup link and flow control */ + ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy */ + reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); + reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB | + E1000_TXDCTL_COUNT_DESC; + E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data); + + /* ...for both queues. */ + if (mac->type != e1000_82573 && mac->type != e1000_82574) { + reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1)); + reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB | + E1000_TXDCTL_COUNT_DESC; + E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data); + } else { + e1000_enable_tx_pkt_filtering_generic(hw); + reg_data = E1000_READ_REG(hw, E1000_GCR); + reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; + E1000_WRITE_REG(hw, E1000_GCR, reg_data); + } + + /* + * Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. + */ + e1000_clear_hw_cntrs_82571(hw); + + return ret_val; +} + +/** + * e1000_initialize_hw_bits_82571 - Initialize hardware-dependent bits + * @hw: pointer to the HW structure + * + * Initializes required hardware-dependent bits needed for normal operation. + **/ +static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) +{ + u32 reg; + + DEBUGFUNC("e1000_initialize_hw_bits_82571"); + + if (hw->mac.disable_hw_init_bits) + goto out; + + /* Transmit Descriptor Control 0 */ + reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); + + /* Transmit Descriptor Control 1 */ + reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); + + /* Transmit Arbitration Control 0 */ + reg = E1000_READ_REG(hw, E1000_TARC(0)); + reg &= ~(0xF << 27); /* 30:27 */ + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26); + break; + default: + break; + } + E1000_WRITE_REG(hw, E1000_TARC(0), reg); + + /* Transmit Arbitration Control 1 */ + reg = E1000_READ_REG(hw, E1000_TARC(1)); + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + reg &= ~((1 << 29) | (1 << 30)); + reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26); + if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) + reg &= ~(1 << 28); + else + reg |= (1 << 28); + E1000_WRITE_REG(hw, E1000_TARC(1), reg); + break; + default: + break; + } + + /* Device Control */ + if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + reg = E1000_READ_REG(hw, E1000_CTRL); + reg &= ~(1 << 29); + E1000_WRITE_REG(hw, E1000_CTRL, reg); + } + + /* Extended Device Control */ + if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + reg &= ~(1 << 23); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + } + + /* PCI-Ex Control Register */ + if (hw->mac.type == e1000_82574) { + reg = E1000_READ_REG(hw, E1000_GCR); + reg |= (1 << 22); + E1000_WRITE_REG(hw, E1000_GCR, reg); + } + +out: + return; +} + +/** + * e1000_clear_vfta_82571 - Clear VLAN filter table + * @hw: pointer to the HW structure + * + * Clears the register array which contains the VLAN filter table by + * setting all the values to 0. + **/ +static void e1000_clear_vfta_82571(struct e1000_hw *hw) +{ + u32 offset; + u32 vfta_value = 0; + u32 vfta_offset = 0; + u32 vfta_bit_in_reg = 0; + + DEBUGFUNC("e1000_clear_vfta_82571"); + + if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + if (hw->mng_cookie.vlan_id != 0) { + /* + * The VFTA is a 4096b bit-field, each identifying + * a single VLAN ID. The following operations + * determine which 32b entry (i.e. offset) into the + * array we want to set the VLAN ID (i.e. bit) of + * the manageability unit. + */ + vfta_offset = (hw->mng_cookie.vlan_id >> + E1000_VFTA_ENTRY_SHIFT) & + E1000_VFTA_ENTRY_MASK; + vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & + E1000_VFTA_ENTRY_BIT_SHIFT_MASK); + } + } + for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { + /* + * If the offset we want to clear is the same offset of the + * manageability VLAN ID, then clear all bits except that of + * the manageability unit. + */ + vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; + E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value); + E1000_WRITE_FLUSH(hw); + } +} + +/** + * e1000_check_mng_mode_82574 - Check manageability is enabled + * @hw: pointer to the HW structure + * + * Reads the NVM Initialization Control Word 2 and returns true + * (>0) if any manageability is enabled, else false (0). + **/ +static bool e1000_check_mng_mode_82574(struct e1000_hw *hw) +{ + u16 data; + + DEBUGFUNC("e1000_check_mng_mode_82574"); + + hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data); + return ((data & E1000_NVM_INIT_CTRL2_MNGM) != 0); +} + +/** + * e1000_led_on_82574 - Turn LED on + * @hw: pointer to the HW structure + * + * Turn LED on. + **/ +static s32 e1000_led_on_82574(struct e1000_hw *hw) +{ + u32 ctrl; + u32 i; + + DEBUGFUNC("e1000_led_on_82574"); + + ctrl = hw->mac.ledctl_mode2; + if (!(E1000_STATUS_LU & E1000_READ_REG(hw, E1000_STATUS))) { + /* + * If no link, then turn LED on by setting the invert bit + * for each LED that's "on" (0x0E) in ledctl_mode2. + */ + for (i = 0; i < 4; i++) + if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == + E1000_LEDCTL_MODE_LED_ON) + ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8)); + } + E1000_WRITE_REG(hw, E1000_LEDCTL, ctrl); + + return E1000_SUCCESS; +} + +/** + * e1000_update_mc_addr_list_82571 - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * @rar_used_count: the first RAR register free to program + * @rar_count: total number of supported Receive Address Registers + * + * Updates the Receive Address Registers and Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. + * The parameter rar_count will usually be hw->mac.rar_entry_count + * unless there are workarounds that change this. + **/ +static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count, + u32 rar_used_count, u32 rar_count) +{ + DEBUGFUNC("e1000_update_mc_addr_list_82571"); + + if (e1000_get_laa_state_82571(hw)) + rar_count--; + + e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count, + rar_used_count, rar_count); +} + +/** + * e1000_setup_link_82571 - Setup flow control and link settings + * @hw: pointer to the HW structure + * + * Determines which flow control settings to use, then configures flow + * control. Calls the appropriate media-specific link configuration + * function. Assuming the adapter has a valid link partner, a valid link + * should be established. Assumes the hardware has previously been reset + * and the transmitter and receiver are not enabled. + **/ +static s32 e1000_setup_link_82571(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_setup_link_82571"); + + /* + * 82573 does not have a word in the NVM to determine + * the default flow control setting, so we explicitly + * set it to full. + */ + if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) && + hw->fc.type == e1000_fc_default) + hw->fc.type = e1000_fc_full; + + return e1000_setup_link_generic(hw); +} + +/** + * e1000_setup_copper_link_82571 - Configure copper link settings + * @hw: pointer to the HW structure + * + * Configures the link for auto-neg or forced speed and duplex. Then we check + * for link, once link is established calls to configure collision distance + * and flow control are called. + **/ +static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) +{ + u32 ctrl, led_ctrl; + s32 ret_val; + + DEBUGFUNC("e1000_setup_copper_link_82571"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + switch (hw->phy.type) { + case e1000_phy_m88: + case e1000_phy_bm: + ret_val = e1000_copper_link_setup_m88(hw); + break; + case e1000_phy_igp_2: + ret_val = e1000_copper_link_setup_igp(hw); + /* Setup activity LED */ + led_ctrl = E1000_READ_REG(hw, E1000_LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); + E1000_WRITE_REG(hw, E1000_LEDCTL, led_ctrl); + break; + default: + ret_val = -E1000_ERR_PHY; + break; + } + + if (ret_val) + goto out; + + ret_val = e1000_setup_copper_link_generic(hw); + +out: + return ret_val; +} + +/** + * e1000_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes + * @hw: pointer to the HW structure + * + * Configures collision distance and flow control for fiber and serdes links. + * Upon successful setup, poll for link. + **/ +static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_setup_fiber_serdes_link_82571"); + + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + /* + * If SerDes loopback mode is entered, there is no form + * of reset to take the adapter out of that mode. So we + * have to explicitly take the adapter out of loopback + * mode. This prevents drivers from twiddling their thumbs + * if another tool failed to take it out of loopback mode. + */ + E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); + break; + default: + break; + } + + return e1000_setup_fiber_serdes_link_generic(hw); +} + +/** + * e1000_valid_led_default_82571 - Verify a valid default LED config + * @hw: pointer to the HW structure + * @data: pointer to the NVM (EEPROM) + * + * Read the EEPROM for the current default LED configuration. If the + * LED configuration is not valid, set to a valid LED configuration. + **/ +static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) +{ + s32 ret_val; + + DEBUGFUNC("e1000_valid_led_default_82571"); + + ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + + if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) && + *data == ID_LED_RESERVED_F746) + *data = ID_LED_DEFAULT_82573; + else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) + *data = ID_LED_DEFAULT; +out: + return ret_val; +} + +/** + * e1000_get_laa_state_82571 - Get locally administered address state + * @hw: pointer to the HW structure + * + * Retrieve and return the current locally administered address state. + **/ +bool e1000_get_laa_state_82571(struct e1000_hw *hw) +{ + struct e1000_dev_spec_82571 *dev_spec; + bool state = false; + + DEBUGFUNC("e1000_get_laa_state_82571"); + + if (hw->mac.type != e1000_82571) + goto out; + + dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec; + + state = dev_spec->laa_is_present; + +out: + return state; +} + +/** + * e1000_set_laa_state_82571 - Set locally administered address state + * @hw: pointer to the HW structure + * @state: enable/disable locally administered address + * + * Enable/Disable the current locally administered address state. + **/ +void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state) +{ + struct e1000_dev_spec_82571 *dev_spec; + + DEBUGFUNC("e1000_set_laa_state_82571"); + + if (hw->mac.type != e1000_82571) + goto out; + + dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec; + + dev_spec->laa_is_present = state; + + /* If workaround is activated... */ + if (state) { + /* + * Hold a copy of the LAA in RAR[14] This is done so that + * between the time RAR[0] gets clobbered and the time it + * gets fixed, the actual LAA is in one of the RARs and no + * incoming packets directed to this port are dropped. + * Eventually the LAA will be in RAR[0] and RAR[14]. + */ + e1000_rar_set_generic(hw, hw->mac.addr, + hw->mac.rar_entry_count - 1); + } + +out: + return; +} + +/** + * e1000_fix_nvm_checksum_82571 - Fix EEPROM checksum + * @hw: pointer to the HW structure + * + * Verifies that the EEPROM has completed the update. After updating the + * EEPROM, we need to check bit 15 in work 0x23 for the checksum fix. If + * the checksum fix is not implemented, we need to set the bit and update + * the checksum. Otherwise, if bit 15 is set and the checksum is incorrect, + * we need to return bad checksum. + **/ +static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + s32 ret_val = E1000_SUCCESS; + u16 data; + + DEBUGFUNC("e1000_fix_nvm_checksum_82571"); + + if (nvm->type != e1000_nvm_flash_hw) + goto out; + + /* + * Check bit 4 of word 10h. If it is 0, firmware is done updating + * 10h-12h. Checksum may need to be fixed. + */ + ret_val = nvm->ops.read(hw, 0x10, 1, &data); + if (ret_val) + goto out; + + if (!(data & 0x10)) { + /* + * Read 0x23 and check bit 15. This bit is a 1 + * when the checksum has already been fixed. If + * the checksum is still wrong and this bit is a + * 1, we need to return bad checksum. Otherwise, + * we need to set this bit to a 1 and update the + * checksum. + */ + ret_val = nvm->ops.read(hw, 0x23, 1, &data); + if (ret_val) + goto out; + + if (!(data & 0x8000)) { + data |= 0x8000; + ret_val = nvm->ops.write(hw, 0x23, 1, &data); + if (ret_val) + goto out; + ret_val = nvm->ops.update(hw); + } + } + +out: + return ret_val; +} + +/** + * e1000_read_mac_addr_82571 - Read device MAC address + * @hw: pointer to the HW structure + **/ +static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_mac_addr_82571"); + if (e1000_check_alt_mac_addr_generic(hw)) + ret_val = e1000_read_mac_addr_generic(hw); + + return ret_val; +} + +/** + * e1000_power_down_phy_copper_82571 - Remove link during PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, or wake on lan is not enabled, remove the link. + **/ +static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + struct e1000_mac_info *mac = &hw->mac; + + if (!(phy->ops.check_reset_block)) + return; + + /* If the management interface is not enabled, then power down */ + if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) + e1000_power_down_phy_copper(hw); + + return; +} + +/** + * e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters + * @hw: pointer to the HW structure + * + * Clears the hardware counters by reading the counter registers. + **/ +static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) +{ + volatile u32 temp; + + DEBUGFUNC("e1000_clear_hw_cntrs_82571"); + + e1000_clear_hw_cntrs_base_generic(hw); + temp = E1000_READ_REG(hw, E1000_PRC64); + temp = E1000_READ_REG(hw, E1000_PRC127); + temp = E1000_READ_REG(hw, E1000_PRC255); + temp = E1000_READ_REG(hw, E1000_PRC511); + temp = E1000_READ_REG(hw, E1000_PRC1023); + temp = E1000_READ_REG(hw, E1000_PRC1522); + temp = E1000_READ_REG(hw, E1000_PTC64); + temp = E1000_READ_REG(hw, E1000_PTC127); + temp = E1000_READ_REG(hw, E1000_PTC255); + temp = E1000_READ_REG(hw, E1000_PTC511); + temp = E1000_READ_REG(hw, E1000_PTC1023); + temp = E1000_READ_REG(hw, E1000_PTC1522); + + temp = E1000_READ_REG(hw, E1000_ALGNERRC); + temp = E1000_READ_REG(hw, E1000_RXERRC); + temp = E1000_READ_REG(hw, E1000_TNCRS); + temp = E1000_READ_REG(hw, E1000_CEXTERR); + temp = E1000_READ_REG(hw, E1000_TSCTC); + temp = E1000_READ_REG(hw, E1000_TSCTFC); + + temp = E1000_READ_REG(hw, E1000_MGTPRC); + temp = E1000_READ_REG(hw, E1000_MGTPDC); + temp = E1000_READ_REG(hw, E1000_MGTPTC); + + temp = E1000_READ_REG(hw, E1000_IAC); + temp = E1000_READ_REG(hw, E1000_ICRXOC); + + temp = E1000_READ_REG(hw, E1000_ICRXPTC); + temp = E1000_READ_REG(hw, E1000_ICRXATC); + temp = E1000_READ_REG(hw, E1000_ICTXPTC); + temp = E1000_READ_REG(hw, E1000_ICTXATC); + temp = E1000_READ_REG(hw, E1000_ICTXQEC); + temp = E1000_READ_REG(hw, E1000_ICTXQMTC); + temp = E1000_READ_REG(hw, E1000_ICRXDMTC); +} --- linux-2.6.27.orig/ubuntu/e1000e/kcompat.c +++ linux-2.6.27/ubuntu/e1000e/kcompat.c @@ -0,0 +1,318 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + + + +#ifdef DRIVER_E1000E +#include "e1000.h" +#endif + + + + +#include "kcompat.h" + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) + +/**************************************/ +/* PCI DMA MAPPING */ + +#if defined(CONFIG_HIGHMEM) + +#ifndef PCI_DRAM_OFFSET +#define PCI_DRAM_OFFSET 0 +#endif + +u64 +_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, + size_t size, int direction) +{ + return (((u64) (page - mem_map) << PAGE_SHIFT) + offset + + PCI_DRAM_OFFSET); +} + +#else /* CONFIG_HIGHMEM */ + +u64 +_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, + size_t size, int direction) +{ + return pci_map_single(dev, (void *)page_address(page) + offset, size, + direction); +} + +#endif /* CONFIG_HIGHMEM */ + +void +_kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, + int direction) +{ + return pci_unmap_single(dev, dma_addr, size, direction); +} + +#endif /* 2.4.13 => 2.4.3 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) + +/**************************************/ +/* PCI DRIVER API */ + +int +_kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) +{ + if (!pci_dma_supported(dev, mask)) + return -EIO; + dev->dma_mask = mask; + return 0; +} + +int +_kc_pci_request_regions(struct pci_dev *dev, char *res_name) +{ + int i; + + for (i = 0; i < 6; i++) { + if (pci_resource_len(dev, i) == 0) + continue; + + if (pci_resource_flags(dev, i) & IORESOURCE_IO) { + if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { + pci_release_regions(dev); + return -EBUSY; + } + } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { + if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { + pci_release_regions(dev); + return -EBUSY; + } + } + } + return 0; +} + +void +_kc_pci_release_regions(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < 6; i++) { + if (pci_resource_len(dev, i) == 0) + continue; + + if (pci_resource_flags(dev, i) & IORESOURCE_IO) + release_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); + + else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) + release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); + } +} + +/**************************************/ +/* NETWORK DRIVER API */ + +struct net_device * +_kc_alloc_etherdev(int sizeof_priv) +{ + struct net_device *dev; + int alloc_size; + + alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 31; + dev = kmalloc(alloc_size, GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, alloc_size); + + if (sizeof_priv) + dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31); + dev->name[0] = '\0'; + ether_setup(dev); + + return dev; +} + +int +_kc_is_valid_ether_addr(u8 *addr) +{ + const char zaddr[6] = { 0, }; + + return !(addr[0] & 1) && memcmp(addr, zaddr, 6); +} + +#endif /* 2.4.3 => 2.4.0 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) + +int +_kc_pci_set_power_state(struct pci_dev *dev, int state) +{ + return 0; +} + +int +_kc_pci_save_state(struct pci_dev *dev, u32 *buffer) +{ + return 0; +} + +int +_kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) +{ + return 0; +} + +int +_kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) +{ + return 0; +} + +#endif /* 2.4.6 => 2.4.3 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) +void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, + int off, int size) +{ + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + frag->page = page; + frag->page_offset = off; + frag->size = size; + skb_shinfo(skb)->nr_frags = i + 1; +} + +/* + * Original Copyright: + * find_next_bit.c: fallback find next bit implementation + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +/** + * find_next_bit - find the next set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < BITS_PER_LONG) + goto found_first; + if (tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if ((tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp &= (~0UL >> (BITS_PER_LONG - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + ffs(tmp); +} + +#endif /* 2.6.0 => 2.4.6 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) +void *_kc_kzalloc(size_t size, int flags) +{ + void *ret = kmalloc(size, flags); + if (ret) + memset(ret, 0, size); + return ret; +} +#endif /* <= 2.6.13 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) +struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, + unsigned int length) +{ + /* 16 == NET_PAD_SKB */ + struct sk_buff *skb; + skb = alloc_skb(length + 16, GFP_ATOMIC); + if (likely(skb != NULL)) { + skb_reserve(skb, 16); + skb->dev = dev; + } + return skb; +} +#endif /* <= 2.6.17 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ) +#endif /* < 2.6.23 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) +#ifdef NAPI +int __kc_adapter_clean(struct net_device *netdev, int *budget) +{ + int work_done; + int work_to_do = min(*budget, netdev->quota); + struct adapter_struct *adapter = netdev_priv(netdev); +#ifdef DRIVER_E1000E + struct napi_struct *napi = &adapter->napi; +#else + struct napi_struct *napi = &adapter->rx_ring[0].napi; +#endif + + work_done = napi->poll(napi, work_to_do); + *budget -= work_done; + netdev->quota -= work_done; + return work_done ? 1 : 0; +} +#endif /* NAPI */ +#endif /* <= 2.6.24 */ + --- linux-2.6.27.orig/ubuntu/e1000e/e1000_regs.h +++ linux-2.6.27/ubuntu/e1000e/e1000_regs.h @@ -0,0 +1,310 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2008 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_REGS_H_ +#define _E1000_REGS_H_ + +#define E1000_CTRL 0x00000 /* Device Control - RW */ +#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ +#define E1000_STATUS 0x00008 /* Device Status - RO */ +#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ +#define E1000_EERD 0x00014 /* EEPROM Read - RW */ +#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ +#define E1000_FLA 0x0001C /* Flash Access - RW */ +#define E1000_MDIC 0x00020 /* MDI Control - RW */ +#define E1000_SCTL 0x00024 /* SerDes Control - RW */ +#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ +#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ +#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ +#define E1000_FCT 0x00030 /* Flow Control Type - RW */ +#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ +#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ +#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ +#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ +#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ +#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ +#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ +#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ +#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ +#define E1000_RCTL 0x00100 /* Rx Control - RW */ +#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ +#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ +#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ +#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ +#define E1000_EITR(_n) (0x01680 + (0x4 * (_n))) +#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */ +#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ +#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ +#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ +#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */ +#define E1000_TCTL 0x00400 /* Tx Control - RW */ +#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ +#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ +#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */ +#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ +#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ +#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ +#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ +#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ +#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ +#define E1000_PBS 0x01008 /* Packet Buffer Size */ +#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ +#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ +#define E1000_FLASHT 0x01028 /* FLASH Timer Register */ +#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ +#define E1000_FLSWCTL 0x01030 /* FLASH control register */ +#define E1000_FLSWDATA 0x01034 /* FLASH data register */ +#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ +#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ +#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */ +#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ +#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */ +#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */ +#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ +#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ +#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ +#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ +#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ +#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ +#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) +#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */ +#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ +/* Split and Replication Rx Control - RW */ +#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */ +#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */ +#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */ +#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */ +#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */ +#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ +#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ +/* + * Convenience macros + * + * Note: "_n" is the queue number of the register to be written to. + * + * Example usage: + * E1000_RDBAL_REG(current_rx_queue) + */ +#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : (0x0C000 + ((_n) * 0x40))) +#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : (0x0C004 + ((_n) * 0x40))) +#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : (0x0C008 + ((_n) * 0x40))) +#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : (0x0C00C + ((_n) * 0x40))) +#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : (0x0C010 + ((_n) * 0x40))) +#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : (0x0C018 + ((_n) * 0x40))) +#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : (0x0C028 + ((_n) * 0x40))) +#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : (0x0E000 + ((_n) * 0x40))) +#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : (0x0E004 + ((_n) * 0x40))) +#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : (0x0E008 + ((_n) * 0x40))) +#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : (0x0E010 + ((_n) * 0x40))) +#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : (0x0E018 + ((_n) * 0x40))) +#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : (0x0E028 + ((_n) * 0x40))) +#define E1000_TARC(_n) (0x03840 + (_n << 8)) +#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) +#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) +#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : (0x0E038 + ((_n) * 0x40))) +#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : (0x0E03C + ((_n) * 0x40))) +#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */ +#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ +#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */ +#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ +#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4)) +#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : (0x054E0 + ((_i - 16) * 8))) +#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : (0x054E4 + ((_i - 16) * 8))) +#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8)) +#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4)) +#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) +#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8)) +#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8)) +#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8)) +#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ +#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ +#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ +#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ +#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ +#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */ +#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */ +#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */ +#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */ +#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */ +#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */ +#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ +#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ +#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ +#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ +#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ +#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ +#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ +#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ +#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ +#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ +#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ +#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ +#define E1000_COLC 0x04028 /* Collision Count - R/clr */ +#define E1000_DC 0x04030 /* Defer Count - R/clr */ +#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ +#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ +#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ +#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ +#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ +#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ +#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ +#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ +#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ +#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ +#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ +#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ +#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ +#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ +#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ +#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ +#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ +#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ +#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ +#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ +#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ +#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ +#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ +#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ +#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ +#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ +#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ +#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ +#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ +#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ +#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ +#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ +#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ +#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ +#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ +#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ +#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ +#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ +#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ +#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ +#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ +#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ +#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ +#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ +#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ +#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ +#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ +#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ +#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */ +#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */ +#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */ +#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */ +#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ +#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */ +#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */ +#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ + +#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */ +#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ +#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ +#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */ +#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */ +#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */ +#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */ +#define E1000_RPTHC 0x04104 /* Rx Packets To Host */ +#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */ +#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */ +#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */ +#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */ +#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ +#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ +#define E1000_LENERRS 0x04138 /* Length Errors Count */ +#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */ +#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */ +#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ +#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ +#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */ +#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */ +#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */ +#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ +#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */ +#define E1000_RFCTL 0x05008 /* Receive Filter Control*/ +#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ +#define E1000_RA 0x05400 /* Receive Address - RW Array */ +#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ +#define E1000_VMD_CTL 0x0581C /* VMDq Control - RW */ +#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */ +#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */ +#define E1000_WUC 0x05800 /* Wakeup Control - RW */ +#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ +#define E1000_WUS 0x05810 /* Wakeup Status - RO */ +#define E1000_MANC 0x05820 /* Management Control - RW */ +#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ +#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ +#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ +#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ +#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ +#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */ +#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ +#define E1000_HOST_IF 0x08800 /* Host Interface */ +#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ +#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ + +#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ +#define E1000_MDPHYA 0x0003C /* PHY address - RW */ +#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ +#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ +#define E1000_CCMCTL 0x05B48 /* CCM Control Register */ +#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ +#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */ +#define E1000_GCR 0x05B00 /* PCI-Ex Control */ +#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ +#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ +#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ +#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ +#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ +#define E1000_SWSM 0x05B50 /* SW Semaphore */ +#define E1000_FWSM 0x05B54 /* FW Semaphore */ +#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */ +#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */ +#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ +#define E1000_HICR 0x08F00 /* Host Interface Control */ + +/* RSS registers */ +#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ +#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ +#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ +#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/ +#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */ +#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register (_i) - RW */ +#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr low reg 0 - RW */ +#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr upper reg 0 - RW */ +#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry message reg 0 - RW */ +#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry vector ctrl reg 0 - RW */ +#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */ +#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW Array */ +#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */ +#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ +#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ +#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Message Type - RW */ +#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ +#endif --- linux-2.6.27.orig/ubuntu/e1000e/Makefile +++ linux-2.6.27/ubuntu/e1000e/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_E1000E_NEW) += e1000e.o + +e1000e-objs := netdev.o ethtool.o param.o e1000_82571.o e1000_ich8lan.o \ + e1000_80003es2lan.o e1000_mac.o e1000_nvm.o e1000_phy.o e1000_manage.o \ + kcompat.o --- linux-2.6.27.orig/ubuntu/misc/fsam7400.c +++ linux-2.6.27/ubuntu/misc/fsam7400.c @@ -0,0 +1,373 @@ +/******************************************************************************* + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Author: + Marcel Naziri + + Based on: + pbe5.c by Pedro Ramalhais + + Many thanks to: + Pedro Ramalhais for spending several nights with me on IRC disassembling + the structure of the windows driver files... :) + +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "fsam7400" +#define DRV_VERSION "0.4.0" +#define DRV_DESCRIPTION "SW RF kill switch for Fujitsu Siemens Amilo M 7400" +#define DRV_COPYRIGHT "Copyright(c) 2004 zwobbl ;)" +#define DRV_AUTHOR "Marcel Naziri" +#define DRV_LICENSE "GPL" + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_AUTHOR); +MODULE_LICENSE(DRV_LICENSE); + +#define RADIO_NONE 0xFFFFFFFF +#define RADIO_OFF 0x00000000 +#define RADIO_ON 0x00000010 + +static int radio = RADIO_NONE; +module_param(radio, uint, 0400); +MODULE_PARM_DESC(radio, "desired radio state when loading module"); + +static int autooff = 1; +module_param(autooff, uint, 0400); +MODULE_PARM_DESC(autooff, "turns radio off when unloading module " + "(default)"); + +static int uid = 0; +module_param(uid, uint, 0400); +MODULE_PARM_DESC(uid, "user ID for proc entry"); + +static int gid = 0; +module_param(gid, uint, 0400); +MODULE_PARM_DESC(gid, "group ID for proc entry"); + +/* some more or less useful macros */ +#ifdef CONFIG_IPW2100_DEBUG +#define DEBUG_OUT0(a) printk(KERN_INFO DRV_NAME ": " a) +#define DEBUG_OUT1(a,b) printk(KERN_INFO DRV_NAME ": " a,b) +#define DEBUG_OUT2(a,b,c) printk(KERN_INFO DRV_NAME ": " a,b,c) +#define DEBUG_OUT3(a,b,c,d) printk(KERN_INFO DRV_NAME ": " a,b,c,d) +#else +#define DEBUG_OUT0(a) +#define DEBUG_OUT1(a,b) +#define DEBUG_OUT2(a,b,c) +#define DEBUG_OUT3(a,b,c,d) +#endif + +#define ONOFF(x) (x) ? "ON" : "OFF" +#define RADIO_ONOFF(x) (x) == RADIO_ON ? "ON" : "OFF" +#define TOUL(x) (unsigned long) (x) + +/* + * NOTE: These values were obtained from disassembling the wbutton.sys driver + * installed in the Fujitsu Siemens Amilo M 7400 laptop. The names were guessed, + * so don't rely on them. + */ + +/*** hardware dependant stuff ***/ + +#define BIOS_CODE_ADDR 0x000F0000 +#define BIOS_CODE_ALT_MASK 0xFFFFC000 + +#define BIOS_CODE_MAPSIZE 0x010000 +#define BIOS_CODE_ALT_MAPSIZE 0x004000 + +#define BIOS_MAGIC_COMMAND 0x9610 +#define BIOS_MAGIC_OFF 0x0035 +#define BIOS_MAGIC_ON 0x0135 +#define BIOS_MAGIC_CHECK 0x0235 + +#define PTR_POSITION 5 +#define ALLIGNED_STEP 0x10 + +#define BIOS_SIGN_SIZE 4 +static const char bios_sign[] = { + 0x42, 0x21, 0x55, 0x30 +}; + +#define WLAN_DISABLED_IN_BIOS 0x01 +#define WLAN_ENABLED_IN_BIOS 0x03 + +static unsigned long bios_code = 0; + +static int fsam_bios_routine(int eax, int ebx) +{ + __asm__ __volatile__( + "call *%3 \t\n" + : "=a"(eax) + : "a"(eax), "b"(ebx), "c"(bios_code) + ); + return (eax & 0xFF); +} + +static int fsam_call_bios(int value) +{ + if (bios_code) { + int command = BIOS_MAGIC_COMMAND; + + DEBUG_OUT2("bios routine gets parameter eax=%X and ebx=%X\n", + command, value); + + value = fsam_bios_routine(command, value); + + DEBUG_OUT1("bios routine results %X\n", value); + return value; + } + return ~0; +} + +/* pointer to mapped memory*/ +static void *mem_code = NULL; + +static inline void fsam_unmap_memory(void) +{ + bios_code = 0; + if (mem_code) { + iounmap(mem_code); + } +} + +static inline int fsam_map_memory(void) +{ + const unsigned long max_offset = BIOS_CODE_MAPSIZE - BIOS_SIGN_SIZE - PTR_POSITION; + unsigned long offset; + unsigned int addr; + + mem_code = ioremap(BIOS_CODE_ADDR, BIOS_CODE_MAPSIZE); + if (!mem_code) + goto fail; + + DEBUG_OUT3("physical memory %x-%x mapped to virtual address %p\n", + BIOS_CODE_ADDR, BIOS_CODE_ADDR+BIOS_CODE_MAPSIZE, mem_code); + + for ( offset = 0; offset < max_offset; offset += ALLIGNED_STEP ) + if (check_signature(mem_code + offset, bios_sign, BIOS_SIGN_SIZE)) + break; + + if (offset >= max_offset) + goto fail; + + DEBUG_OUT1("bios signature found at offset %lx\n", offset); + + addr = readl(mem_code + offset + PTR_POSITION); + + if (addr < BIOS_CODE_ADDR) + { + DEBUG_OUT0("bios routine out of memory range, " + "doing some new memory mapping...\n"); + iounmap(mem_code); + mem_code = NULL; + + addr &= BIOS_CODE_ALT_MASK; + + mem_code = ioremap(addr, BIOS_CODE_ALT_MAPSIZE); + if (!mem_code) + goto fail; + + DEBUG_OUT3("physical memory %x-%x mapped to virtual address %p\n", + addr, addr+BIOS_CODE_ALT_MAPSIZE, mem_code); + + addr &= 0x3FFF; + } + else + addr &= 0xFFFF; + + bios_code = addr + TOUL(mem_code); + DEBUG_OUT1("supposed address of bios routine is %lx\n", bios_code); + + return 1; + + fail: + fsam_unmap_memory(); + return 0; +} + +/*** interface stuff ***/ + +static void rfkill_set_radio(int value) +{ + radio = value == RADIO_ON ? fsam_call_bios(BIOS_MAGIC_ON) : + fsam_call_bios(BIOS_MAGIC_OFF); +} + +static inline int rfkill_get_radio(void) +{ + return radio; +} + +static inline int rfkill_supported(void) +{ + return bios_code != 0; +} + +static inline void rfkill_initialize(void) { + fsam_map_memory(); + + if (rfkill_supported()) { + radio = radio != RADIO_NONE + ? ( radio ? RADIO_ON : RADIO_OFF ) /*module parameter*/ + : ( fsam_call_bios(BIOS_MAGIC_CHECK) == WLAN_ENABLED_IN_BIOS + ? RADIO_ON : RADIO_OFF ); + } +} + +static inline void rfkill_uninitialize(void) { + fsam_unmap_memory(); +} + +/*** proc stuff ***/ + +static inline int common_proc_set_radio(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned long len = 4; + char newstate[len]; + + len = count < len ? count : len; + + if ( copy_from_user(newstate, buffer, len) != 0 ) + return -EFAULT; + + if ( (*newstate == '1' || *newstate == '0') && + (count == 1 || isspace(newstate[1])) ) + rfkill_set_radio(*newstate == '1' ? RADIO_ON : RADIO_OFF); + else + if ( !strncmp(newstate, "on", 2) && + (count == 2 || isspace(newstate[2])) ) + rfkill_set_radio(RADIO_ON); + else + if ( !strncmp(newstate, "off", 3) && + (count == 3 || isspace(newstate[3])) ) + rfkill_set_radio(RADIO_OFF); + + return count; +} + +static inline int common_proc_get_radio(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = snprintf(page, count, DRV_DESCRIPTION ", v" DRV_VERSION "\n" + " auto-off is %s\n", + ONOFF(autooff)); + len += snprintf(page+len, count-len, " radio state is %s\n", + RADIO_ONOFF(rfkill_get_radio())); + *eof = 1; + + return len; +} + +#define PROC_DIR "driver/wireless" +#define PROC_RADIO "radio" + +static struct proc_dir_entry *dir_base = NULL; + +static inline void common_proc_cleanup(void) +{ + if (dir_base) { + remove_proc_entry(PROC_RADIO, dir_base); + remove_proc_entry(PROC_DIR, NULL); + dir_base = NULL; + } +} + +static inline int common_proc_init(void) +{ + struct proc_dir_entry *ent; + int err = 0; + + dir_base = proc_mkdir(PROC_DIR, NULL); + if (dir_base == NULL) { + printk(KERN_ERR DRV_NAME ": Unable to initialize /proc/" PROC_DIR "\n"); + err = -ENOMEM; + goto fail; + } + + ent = create_proc_entry(PROC_RADIO, + S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP, + dir_base); + ent->uid = uid; + ent->gid = gid; + if (ent) { + ent->read_proc = common_proc_get_radio; + ent->write_proc = common_proc_set_radio; + } else { + printk(KERN_ERR DRV_NAME ": Unable to initialize /proc/" + PROC_DIR "/" PROC_RADIO "\n"); + err = -ENOMEM; + goto fail; + } + return 0; + + fail: + common_proc_cleanup(); + return err; +} + +/*** module stuff ***/ + +static int __init common_init(void) +{ + printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", v" DRV_VERSION "\n"); + printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + + rfkill_initialize(); + + if (rfkill_supported()) { + common_proc_init(); + if (radio != RADIO_NONE) + rfkill_set_radio(radio); + } else + printk(KERN_INFO DRV_NAME ": no supported wireless hardware found\n"); + + return 0; +} + +static void __exit common_exit(void) +{ + if (rfkill_supported() && autooff) + rfkill_set_radio(RADIO_OFF); + + common_proc_cleanup(); + rfkill_uninitialize(); + + printk(KERN_INFO DRV_NAME ": module removed successfully\n"); +} + +module_init(common_init); +module_exit(common_exit); + +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ --- linux-2.6.27.orig/ubuntu/misc/thinkpad_ec.c +++ linux-2.6.27/ubuntu/misc/thinkpad_ec.c @@ -0,0 +1,489 @@ +/* + * thinkpad_ec.c - ThinkPad embedded controller LPC3 functions + * + * The embedded controller on ThinkPad laptops has a non-standard interface, + * where LPC channel 3 of the H8S EC chip is hooked up to IO ports + * 0x1600-0x161F and implements (a special case of) the H8S LPC protocol. + * The EC LPC interface provides various system management services (currently + * known: battery information and accelerometer readouts). This driver + * provides access and mutual exclusion for the EC interface. +* + * The LPC protocol and terminology is documented here: + * "H8S/2104B Group Hardware Manual", + * http://documentation.renesas.com/eng/products/mpumcu/rej09b0300_2140bhm.pdf + * + * Copyright (C) 2006-2007 Shem Multinymous + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include "thinkpad_ec.h" +#include +#include +#include + +#define TP_VERSION "0.37" + +MODULE_AUTHOR("Shem Multinymous"); +MODULE_DESCRIPTION("ThinkPad embedded controller hardware access"); +MODULE_VERSION(TP_VERSION); +MODULE_LICENSE("GPL"); + +/* IO ports used by embedded controller LPC channel 3: */ +#define TPC_BASE_PORT 0x1600 +#define TPC_NUM_PORTS 0x20 +#define TPC_STR3_PORT 0x1604 /* Reads H8S EC register STR3 */ +#define TPC_TWR0_PORT 0x1610 /* Mapped to H8S EC register TWR0MW/SW */ +#define TPC_TWR15_PORT 0x161F /* Mapped to H8S EC register TWR15. */ + /* (and port TPC_TWR0_PORT+i is mapped to H8S reg TWRi for 00x%02x", \ + msg, args->val[0x0], args->val[0xF], code) + +/* State of request prefetching: */ +static u8 prefetch_arg0, prefetch_argF; /* Args of last prefetch */ +static u64 prefetch_jiffies; /* time of prefetch, or: */ +#define TPC_PREFETCH_NONE INITIAL_JIFFIES /* No prefetch */ +#define TPC_PREFETCH_JUNK (INITIAL_JIFFIES+1) /* Ignore prefetch */ + +/* Locking: */ + +static DECLARE_MUTEX(thinkpad_ec_mutex); + +/** + * thinkpad_ec_lock - get lock on the ThinkPad EC + * + * Get exclusive lock for accesing the ThinkPad embedded controller LPC3 + * interface. Returns 0 iff lock acquired. + */ +int thinkpad_ec_lock(void) +{ + int ret; + ret = down_interruptible(&thinkpad_ec_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(thinkpad_ec_lock); + +/** + * thinkpad_ec_try_lock - try getting lock on the ThinkPad EC + * + * Try getting an exclusive lock for accesing the ThinkPad embedded + * controller LPC3. Returns immediately if lock is not available; neither + * blocks nor sleeps. Returns 0 iff lock acquired . + */ +int thinkpad_ec_try_lock(void) +{ + return down_trylock(&thinkpad_ec_mutex); +} +EXPORT_SYMBOL_GPL(thinkpad_ec_try_lock); + +/** + * thinkpad_ec_unlock - release lock on ThinkPad EC + * + * Release a previously acquired exclusive lock on the ThinkPad ebmedded + * controller LPC3 interface. + */ +void thinkpad_ec_unlock(void) +{ + up(&thinkpad_ec_mutex); +} +EXPORT_SYMBOL_GPL(thinkpad_ec_unlock); + +/** + * thinkpad_ec_request_row - tell embedded controller to prepare a row + * @args Input register arguments + * + * Requests a data row by writing to H8S LPC registers TRW0 through TWR15 (or + * a subset thereof) following the protocol prescribed by the "H8S/2104B Group + * Hardware Manual". Does sanity checks via status register STR3. + */ +static int thinkpad_ec_request_row(const struct thinkpad_ec_row *args) +{ + u8 str3; + int i; + + /* EC protocol requires write to TWR0 (function code): */ + if (!(args->mask & 0x0001)) { + printk(KERN_ERR MSG_FMT("bad args->mask=0x%02x", args->mask)); + return -EINVAL; + } + + /* Check initial STR3 status: */ + str3 = inb(TPC_STR3_PORT) & H8S_STR3_MASK; + if (str3 & H8S_STR3_OBF3B) { /* data already pending */ + inb(TPC_TWR15_PORT); /* marks end of previous transaction */ + if (prefetch_jiffies == TPC_PREFETCH_NONE) + printk(KERN_WARNING REQ_FMT( + "EC has result from unrequested transaction", + str3)); + return -EBUSY; /* EC will be ready in a few usecs */ + } else if (str3 == H8S_STR3_SWMF) { /* busy with previous request */ + if (prefetch_jiffies == TPC_PREFETCH_NONE) + printk(KERN_WARNING REQ_FMT( + "EC is busy with unrequested transaction", + str3)); + return -EBUSY; /* data will be pending in a few usecs */ + } else if (str3 != 0x00) { /* unexpected status? */ + printk(KERN_WARNING REQ_FMT("unexpected initial STR3", str3)); + return -EIO; + } + + /* Send TWR0MW: */ + outb(args->val[0], TPC_TWR0_PORT); + str3 = inb(TPC_STR3_PORT) & H8S_STR3_MASK; + if (str3 != H8S_STR3_MWMF) { /* not accepted? */ + printk(KERN_WARNING REQ_FMT("arg0 rejected", str3)); + return -EIO; + } + + /* Send TWR1 through TWR14: */ + for (i = 1; i < TP_CONTROLLER_ROW_LEN-1; i++) + if ((args->mask>>i)&1) + outb(args->val[i], TPC_TWR0_PORT+i); + + /* Send TWR15 (default to 0x01). This marks end of command. */ + outb((args->mask & 0x8000) ? args->val[0xF] : 0x01, TPC_TWR15_PORT); + + /* Wait until EC starts writing its reply (~60ns on average). + * Releasing locks before this happens may cause an EC hang + * due to firmware bug! + */ + for (i = 0; i < TPC_REQUEST_RETRIES; i++) { + str3 = inb(TPC_STR3_PORT) & H8S_STR3_MASK; + if (str3 & H8S_STR3_SWMF) /* EC started replying */ + return 0; + else if (!(str3 & ~(H8S_STR3_IBF3B|H8S_STR3_MWMF))) + /* Normal progress (the EC hasn't seen the request + * yet, or is processing it). Wait it out. */ + ndelay(TPC_REQUEST_NDELAY); + else { /* weird EC status */ + printk(KERN_WARNING + REQ_FMT("bad end STR3", str3)); + return -EIO; + } + } + printk(KERN_WARNING REQ_FMT("EC is mysteriously silent", str3)); + return -EIO; +} + +/** + * thinkpad_ec_read_data - read pre-requested row-data from EC + * @args Input register arguments of pre-requested rows + * @data Output register values + * + * Reads current row data from the controller, assuming it's already + * requested. Follows the H8S spec for register access and status checks. + */ +static int thinkpad_ec_read_data(const struct thinkpad_ec_row *args, + struct thinkpad_ec_row *data) +{ + int i; + u8 str3 = inb(TPC_STR3_PORT) & H8S_STR3_MASK; + /* Once we make a request, STR3 assumes the sequence of values listed + * in the following 'if' as it reads the request and writes its data. + * It takes about a few dozen nanosecs total, with very high variance. + */ + if (str3 == (H8S_STR3_IBF3B|H8S_STR3_MWMF) || + str3 == 0x00 || /* the 0x00 is indistinguishable from idle EC! */ + str3 == H8S_STR3_SWMF) + return -EBUSY; /* not ready yet */ + /* Finally, the EC signals output buffer full: */ + if (str3 != (H8S_STR3_OBF3B|H8S_STR3_SWMF)) { + printk(KERN_WARNING + REQ_FMT("bad initial STR3", str3)); + return -EIO; + } + + /* Read first byte (signals start of read transactions): */ + data->val[0] = inb(TPC_TWR0_PORT); + /* Optionally read 14 more bytes: */ + for (i = 1; i < TP_CONTROLLER_ROW_LEN-1; i++) + if ((data->mask >> i)&1) + data->val[i] = inb(TPC_TWR0_PORT+i); + /* Read last byte from 0x161F (signals end of read transaction): */ + data->val[0xF] = inb(TPC_TWR15_PORT); + + /* Readout still pending? */ + str3 = inb(TPC_STR3_PORT) & H8S_STR3_MASK; + if (str3 & H8S_STR3_OBF3B) + printk(KERN_WARNING + REQ_FMT("OBF3B=1 after read", str3)); + /* If port 0x161F returns 0x80 too often, the EC may lock up. Warn: */ + if (data->val[0xF] == 0x80) + printk(KERN_WARNING + REQ_FMT("0x161F reports error", data->val[0xF])); + return 0; +} + +/** + * thinkpad_ec_is_row_fetched - is the given row currently prefetched? + * + * To keep things simple we compare only the first and last args; + * this suffices for all known cases. + */ +static int thinkpad_ec_is_row_fetched(const struct thinkpad_ec_row *args) +{ + return (prefetch_jiffies != TPC_PREFETCH_NONE) && + (prefetch_jiffies != TPC_PREFETCH_JUNK) && + (prefetch_arg0 == args->val[0]) && + (prefetch_argF == args->val[0xF]) && + (get_jiffies_64() < prefetch_jiffies + TPC_PREFETCH_TIMEOUT); +} + +/** + * thinkpad_ec_read_row - request and read data from ThinkPad EC + * @args Input register arguments + * @data Output register values + * + * Read a data row from the ThinkPad embedded controller LPC3 interface. + * Does fetching and retrying if needed. The row is specified by an + * array of 16 bytes, some of which may be undefined (but the first is + * mandatory). These bytes are given in @args->val[], where @args->val[i] is + * used iff (@args->mask>>i)&1). The resulting row data is stored in + * @data->val[], but is only guaranteed to be valid for indices corresponding + * to set bit in @data->mask. That is, if @data->mask&(1<val[i] is undefined. + * + * Returns -EBUSY on transient error and -EIO on abnormal condition. + * Caller must hold controller lock. + */ +int thinkpad_ec_read_row(const struct thinkpad_ec_row *args, + struct thinkpad_ec_row *data) +{ + int retries, ret; + + if (thinkpad_ec_is_row_fetched(args)) + goto read_row; /* already requested */ + + /* Request the row */ + for (retries = 0; retries < TPC_READ_RETRIES; ++retries) { + ret = thinkpad_ec_request_row(args); + if (!ret) + goto read_row; + if (ret != -EBUSY) + break; + ndelay(TPC_READ_NDELAY); + } + printk(KERN_ERR REQ_FMT("failed requesting row", ret)); + goto out; + +read_row: + /* Read the row's data */ + for (retries = 0; retries < TPC_READ_RETRIES; ++retries) { + ret = thinkpad_ec_read_data(args, data); + if (!ret) + goto out; + if (ret != -EBUSY) + break; + ndelay(TPC_READ_NDELAY); + } + + printk(KERN_ERR REQ_FMT("failed waiting for data", ret)); + +out: + prefetch_jiffies = TPC_PREFETCH_JUNK; + return ret; +} +EXPORT_SYMBOL_GPL(thinkpad_ec_read_row); + +/** + * thinkpad_ec_try_read_row - try reading prefetched data from ThinkPad EC + * @args Input register arguments + * @data Output register values + * + * Try reading a data row from the ThinkPad embedded controller LPC3 + * interface, if this raw was recently prefetched using + * thinkpad_ec_prefetch_row(). Does not fetch, retry or block. + * The parameters have the same meaning as in thinkpad_ec_read_row(). + * + * Returns -EBUSY is data not ready and -ENODATA if row not prefetched. + * Caller must hold controller lock. + */ +int thinkpad_ec_try_read_row(const struct thinkpad_ec_row *args, + struct thinkpad_ec_row *data) +{ + int ret; + if (!thinkpad_ec_is_row_fetched(args)) { + ret = -ENODATA; + } else { + ret = thinkpad_ec_read_data(args, data); + if (!ret) + prefetch_jiffies = TPC_PREFETCH_NONE; /* eaten up */ + } + return ret; +} +EXPORT_SYMBOL_GPL(thinkpad_ec_try_read_row); + +/** + * thinkpad_ec_prefetch_row - prefetch data from ThinkPad EC + * @args Input register arguments + * + * Prefetch a data row from the ThinkPad embedded controller LCP3 + * interface. A subsequent call to thinkpad_ec_read_row() with the + * same arguments will be faster, and a subsequent call to + * thinkpad_ec_try_read_row() stands a good chance of succeeding if + * done neither too soon nor too late. See + * thinkpad_ec_read_row() for the meaning of @args. + * + * Returns -EBUSY on transient error and -EIO on abnormal condition. + * Caller must hold controller lock. + */ +int thinkpad_ec_prefetch_row(const struct thinkpad_ec_row *args) +{ + int ret; + ret = thinkpad_ec_request_row(args); + if (ret) { + prefetch_jiffies = TPC_PREFETCH_JUNK; + } else { + prefetch_jiffies = get_jiffies_64(); + prefetch_arg0 = args->val[0x0]; + prefetch_argF = args->val[0xF]; + } + return ret; +} +EXPORT_SYMBOL_GPL(thinkpad_ec_prefetch_row); + +/** + * thinkpad_ec_invalidate - invalidate prefetched ThinkPad EC data + * + * Invalidate the data prefetched via thinkpad_ec_prefetch_row() from the + * ThinkPad embedded controller LPC3 interface. + * Must be called before unlocking by any code that accesses the controller + * ports directly. + */ +void thinkpad_ec_invalidate(void) +{ + prefetch_jiffies = TPC_PREFETCH_JUNK; +} +EXPORT_SYMBOL_GPL(thinkpad_ec_invalidate); + + +/*** Checking for EC hardware ***/ + +/** + * thinkpad_ec_test - verify the EC is present and follows protocol + * + * Ensure the EC LPC3 channel really works on this machine by making + * an EC request and seeing if the EC follows the documented H8S protocol. + * The requested row just reads battery status, so it should be harmless to + * access it (on a correct EC). + * This test writes to IO ports, so execute only after checking DMI. + */ +static int __init thinkpad_ec_test(void) +{ + int ret; + const struct thinkpad_ec_row args = /* battery 0 basic status */ + { .mask = 0x8001, .val = {0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x00} }; + struct thinkpad_ec_row data = { .mask = 0x0000 }; + ret = thinkpad_ec_lock(); + if (ret) + return ret; + ret = thinkpad_ec_read_row(&args, &data); + thinkpad_ec_unlock(); + return ret; +} + +/* Search all DMI device names of a given type for a substring */ +static int __init dmi_find_substring(int type, const char *substr) +{ + const struct dmi_device *dev = NULL; + while ((dev = dmi_find_device(type, NULL, dev))) { + if (strstr(dev->name, substr)) + return 1; + } + return 0; +} + +#define TP_DMI_MATCH(vendor,model) { \ + .ident = vendor " " model, \ + .matches = { \ + DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ + DMI_MATCH(DMI_PRODUCT_VERSION, model) \ + } \ +} + +/* Check DMI for existence of ThinkPad embedded controller */ +static int __init check_dmi_for_ec(void) +{ + /* A few old models that have a good EC but don't report it in DMI */ + struct dmi_system_id tp_whitelist[] = { + TP_DMI_MATCH("IBM", "ThinkPad A30"), + TP_DMI_MATCH("IBM", "ThinkPad T23"), + TP_DMI_MATCH("IBM", "ThinkPad X24"), + { .ident = NULL } + }; + return dmi_find_substring(DMI_DEV_TYPE_OEM_STRING, + "IBM ThinkPad Embedded Controller") || + dmi_check_system(tp_whitelist); +} + +/*** Init and cleanup ***/ + +static int __init thinkpad_ec_init(void) +{ + if (!check_dmi_for_ec()) { + printk(KERN_WARNING + "thinkpad_ec: no ThinkPad embedded controller!\n"); + return -ENODEV; + } + + if (!request_region(TPC_BASE_PORT, TPC_NUM_PORTS, + "thinkpad_ec")) { + printk(KERN_ERR "thinkpad_ec: cannot claim io ports %#x-%#x\n", + TPC_BASE_PORT, + TPC_BASE_PORT + TPC_NUM_PORTS - 1); + return -ENXIO; + } + prefetch_jiffies = TPC_PREFETCH_JUNK; + if (thinkpad_ec_test()) { + printk(KERN_ERR "thinkpad_ec: initial ec test failed\n"); + release_region(TPC_BASE_PORT, TPC_NUM_PORTS); + return -ENXIO; + } + printk(KERN_INFO "thinkpad_ec: thinkpad_ec " TP_VERSION " loaded.\n"); + return 0; +} + +static void __exit thinkpad_ec_exit(void) +{ + release_region(TPC_BASE_PORT, TPC_NUM_PORTS); + printk(KERN_INFO "thinkpad_ec: unloaded.\n"); +} + +module_init(thinkpad_ec_init); +module_exit(thinkpad_ec_exit); --- linux-2.6.27.orig/ubuntu/misc/appleir.c +++ linux-2.6.27/ubuntu/misc/appleir.c @@ -0,0 +1,401 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Version Information + * + */ + +#if 0 +#define DUMP_PACKETS +#else +#undef DUMP_PACKETS +#endif + +#define DRIVER_VERSION "v1.1" +#define DRIVER_AUTHOR "James McKenzie" +#define DRIVER_DESC "USB Apple MacMini IR Receiver driver" +#define DRIVER_LICENSE "GPL" + +MODULE_AUTHOR (DRIVER_AUTHOR); +MODULE_DESCRIPTION (DRIVER_DESC); +MODULE_LICENSE (DRIVER_LICENSE); + +#ifndef USB_VENDOR_ID_APPLE +#define USB_VENDOR_ID_APPLE 0x05ac +#endif +#ifndef USB_DEVICE_ID_APPLE_IR +#define USB_DEVICE_ID_APPLE_IR 0x8240 +#endif +#ifndef USB_DEVICE_ID_APPLE_IR2 +#define USB_DEVICE_ID_APPLE_IR2 0x8242 +#endif + +#define URB_SIZE 32 + +#define MAX_KEYS 8 +#define MAX_KEYS_MASK (MAX_KEYS - 1 ) + +struct appleir +{ + struct input_dev *dev; + uint8_t *data; + dma_addr_t dma_buf; + struct usb_device *usbdev; + struct urb *urb; + int timer_initted; + struct timer_list key_up_timer; + int current_key; + char phys[32]; +}; + + +static struct usb_device_id appleir_ids[] = { + {USB_DEVICE (USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR),.driver_info = 0}, + {USB_DEVICE (USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR2),.driver_info = 0}, + {} +}; + +MODULE_DEVICE_TABLE (usb, appleir_ids); + + +/* I have two devices both of which report the following */ +/* 25 87 ee 83 0a + */ +/* 25 87 ee 83 0c - */ +/* 25 87 ee 83 09 << */ +/* 25 87 ee 83 06 >> */ +/* 25 87 ee 83 05 >" */ +/* 25 87 ee 83 03 menu */ +/* 26 00 00 00 00 for key repeat*/ + +/* Thomas Glanzmann reports the following responses */ +/* 25 87 ee ca 0b + */ +/* 25 87 ee ca 0d - */ +/* 25 87 ee ca 08 << */ +/* 25 87 ee ca 07 >> */ +/* 25 87 ee ca 04 >" */ +/* 25 87 ee ca 02 menu */ +/* 26 00 00 00 00 for key repeat*/ +/* He also observes the following event sometimes */ +/* sent after a key is release, which I interpret */ +/* as a flat battery message */ +/* 25 87 e0 ca 06 flat battery */ + +/* Alexandre Karpenko reports the following responses for Device ID 0x8242 */ +/* 25 87 ee 47 0b + */ +/* 25 87 ee 47 0d - */ +/* 25 87 ee 47 08 << */ +/* 25 87 ee 47 07 >> */ +/* 25 87 ee 47 04 >" */ +/* 25 87 ee 47 02 menu */ +/* 26 87 ee 47 ** for key repeat (** is the code of the key being held) */ + + +static int keymap[MAX_KEYS] = { + KEY_RESERVED, KEY_MENU, + KEY_PLAYPAUSE, KEY_FORWARD, + KEY_BACK, KEY_VOLUMEUP, + KEY_VOLUMEDOWN, KEY_RESERVED +}; + +static void +dump_packet (struct appleir *appleir, char *msg, uint8_t * data, int len) +{ + int i; + + printk (KERN_ERR "appleir: %s (%d bytes)", msg, len); + + for (i = 0; i < len; ++i) + { + printk (" %02x", data[i]); + } + + printk ("\n"); +} + + +static void +key_up (struct appleir *appleir, int key) +{ + //printk (KERN_ERR "key %d up\n", key); + input_report_key (appleir->dev, key, 0); + input_sync (appleir->dev); +} + +static void +key_down (struct appleir *appleir, int key) +{ + //printk (KERN_ERR "key %d down\n", key); + input_report_key (appleir->dev, key, 1); + input_sync (appleir->dev); +} + +static void +battery_flat (struct appleir *appleir) +{ + printk (KERN_ERR "appleir: possible flat battery?\n"); +} + +static void +key_up_tick (unsigned long data) +{ + struct appleir *appleir = (struct appleir *) data; + + if (appleir->current_key) + { + key_up (appleir, appleir->current_key); + appleir->current_key = 0; + } +} + +static void +new_data (struct appleir *appleir, uint8_t * data, int len) +{ + static const uint8_t keydown[] = { 0x25, 0x87, 0xee }; + static const uint8_t keyrepeat[] = { 0x26 }; + static const uint8_t flatbattery[] = { 0x25, 0x87, 0xe0 }; + +#ifdef DUMP_PACKETS + dump_packet (appleir, "received", data, len); +#endif + + if (len != 5) + return; + + if (!memcmp (data, keydown, sizeof (keydown))) + { + /*If we already have a key down, take it up before marking */ + /*this one down */ + if (appleir->current_key) + key_up (appleir, appleir->current_key); + appleir->current_key = keymap[(data[4] >> 1) & MAX_KEYS_MASK]; + + key_down (appleir, appleir->current_key); + /*remote doesn't do key up, either pull them up, in the test */ + /*above, or here set a timer which pulls them up after 1/8 s */ + mod_timer (&appleir->key_up_timer, jiffies + HZ / 8); + + return; + } + + if (!memcmp (data, keyrepeat, sizeof (keyrepeat))) + { + key_down (appleir, appleir->current_key); + /*remote doesn't do key up, either pull them up, in the test */ + /*above, or here set a timer which pulls them up after 1/8 s */ + mod_timer (&appleir->key_up_timer, jiffies + HZ / 8); + return; + } + + if (!memcmp (data, flatbattery, sizeof (flatbattery))) + { + battery_flat (appleir); + /*Fall through */ + } + + dump_packet (appleir, "unknown packet", data, len); +} + +static void +appleir_urb (struct urb *urb) +{ + struct appleir *appleir = urb->context; + int retval; + + switch (urb->status) + { + case 0: + new_data (appleir, urb->transfer_buffer, urb->actual_length); + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg ("%s - urb shutting down with status: %d", __FUNCTION__, + urb->status); + return; + default: + dbg ("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + } + + retval = usb_submit_urb (urb, GFP_ATOMIC); + if (retval) + err ("%s - usb_submit_urb failed with result %d", __FUNCTION__, retval); +} + + +static int +appleir_open (struct input_dev *dev) +{ + struct appleir *appleir = (struct appleir *)input_get_drvdata(dev); + + if (usb_submit_urb (appleir->urb, GFP_KERNEL)) + return -EIO; + + return 0; +} + +static void +appleir_close (struct input_dev *dev) +{ + struct appleir *appleir = (struct appleir *)input_get_drvdata(dev); + usb_kill_urb (appleir->urb); + del_timer_sync (&appleir->key_up_timer); +} + + + + +static int +appleir_probe (struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev (intf); + struct usb_endpoint_descriptor *endpoint; + struct appleir *appleir = NULL; + struct input_dev *input_dev; + int i; + + appleir = kzalloc (sizeof (struct appleir), GFP_KERNEL); + if (!appleir) + goto fail; + + memset (appleir, 0, sizeof (struct appleir)); + + + appleir->data = + usb_buffer_alloc (dev, URB_SIZE, GFP_KERNEL, &appleir->dma_buf); + if (!appleir->data) + goto fail; + + appleir->urb = usb_alloc_urb (0, GFP_KERNEL); + if (!appleir->urb) + goto fail; + + appleir->usbdev = dev; + + input_dev = input_allocate_device (); + if (!input_dev) + goto fail; + + appleir->dev = input_dev; + + + usb_make_path (dev, appleir->phys, sizeof (appleir->phys)); + strlcpy (appleir->phys, "/input0", sizeof (appleir->phys)); + + input_dev->name = "Apple Mac mini infrared remote control driver"; + input_dev->phys = appleir->phys; + usb_to_input_id (dev, &input_dev->id); + input_dev->dev.parent = &intf->dev; + input_set_drvdata(input_dev, appleir); + + input_dev->evbit[0] = BIT (EV_KEY) | BIT (EV_REP); + input_dev->ledbit[0] = 0; + + for (i = 0; i < MAX_KEYS; i++) + { + set_bit (keymap[i], input_dev->keybit); + } + + clear_bit (0, input_dev->keybit); + + input_dev->open = appleir_open; + input_dev->close = appleir_close; + + endpoint = &intf->cur_altsetting->endpoint[0].desc; + + usb_fill_int_urb (appleir->urb, dev, + usb_rcvintpipe (dev, endpoint->bEndpointAddress), + appleir->data, 8, + appleir_urb, appleir, endpoint->bInterval); + + appleir->urb->transfer_dma = appleir->dma_buf; + appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_set_intfdata (intf, appleir); + + init_timer (&appleir->key_up_timer); + + appleir->key_up_timer.function = key_up_tick; + appleir->key_up_timer.data = (unsigned long) appleir; + + appleir->timer_initted++; + + input_register_device (appleir->dev); + + return 0; + +fail: + + if (appleir) + { + + + if (appleir->data) + usb_buffer_free (dev, URB_SIZE, appleir->data, appleir->dma_buf); + + if (appleir->timer_initted) + del_timer_sync (&appleir->key_up_timer); + + if (appleir->dev) + input_free_device (appleir->dev); + + kfree (appleir); + } + + return -ENOMEM; +} + +static void +appleir_disconnect (struct usb_interface *intf) +{ + struct appleir *appleir = usb_get_intfdata (intf); + + usb_set_intfdata (intf, NULL); + if (appleir) + { + input_unregister_device (appleir->dev); + if (appleir->timer_initted) + del_timer_sync (&appleir->key_up_timer); + usb_kill_urb (appleir->urb); + usb_free_urb (appleir->urb); + usb_buffer_free (interface_to_usbdev (intf), URB_SIZE, appleir->data, + appleir->dma_buf); + kfree (appleir); + } +} + +static struct usb_driver appleir_driver = { + .name = "appleir", + .probe = appleir_probe, + .disconnect = appleir_disconnect, + .id_table = appleir_ids, +}; + +static int __init +appleir_init (void) +{ + int retval; + retval = usb_register (&appleir_driver); + if (retval) + goto out; + info (DRIVER_VERSION ":" DRIVER_DESC); +out: + return retval; +} + +static void __exit +appleir_exit (void) +{ + usb_deregister (&appleir_driver); +} + +module_init (appleir_init); +module_exit (appleir_exit); --- linux-2.6.27.orig/ubuntu/misc/Kconfig +++ linux-2.6.27/ubuntu/misc/Kconfig @@ -0,0 +1,35 @@ +config USB_APPLEIR + tristate "Apple USB Infrared Receiver" + default m + depends on USB + +config BLK_DEV_DM_BBR + tristate "Bad-block-relocation target for device-mapper" + default m + depends on BLK_DEV_DM + +config INPUT_ACERHK + tristate "Acer Travelmate laptop special key support" + default m + depends on X86_32 + +config FSAM7400 + tristate "SW RF kill switch for Fujitsu Siemens Amilo M 7400" + default m + +config LMPCM_USB + tristate "USB Logitech MediaPlay Cordless Mouse driver" + default m + depends on USB + +config TP_SMAPI + tristate "ThinkPad SMAPI Support" + default m + +config TP_SMAPI_EC + tristate "ThinkPad embedded controller LPC3 functions" + default m + +source "ubuntu/misc/media/Kconfig" + +source "ubuntu/misc/wireless/Kconfig" --- linux-2.6.27.orig/ubuntu/misc/BOM +++ linux-2.6.27/ubuntu/misc/BOM @@ -0,0 +1,3 @@ +Module: dm-bbr +Downloaded from: http://dev.gentoo.org/~dsd/gentoo-sources/patches-2.6.25-2.htm +Comments: Changes in md headers for 2.6.26 required some munging. --- linux-2.6.27.orig/ubuntu/misc/dm-bbr.h +++ linux-2.6.27/ubuntu/misc/dm-bbr.h @@ -0,0 +1,132 @@ +/* + * (C) Copyright IBM Corp. 2002, 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * linux/drivers/md/dm-bbr.h + * + * Bad-block-relocation (BBR) target for device-mapper. + * + * The BBR target is designed to remap I/O write failures to another safe + * location on disk. Note that most disk drives have BBR built into them, + * this means that our software BBR will be only activated when all hardware + * BBR replacement sectors have been used. + */ + +#include +#include +#include + +#define BBR_TABLE_SIGNATURE 0x42627254 /* BbrT */ +#define BBR_ENTRIES_PER_SECT 31 +#define INITIAL_CRC 0xFFFFFFFF +#define CRC_POLYNOMIAL 0xEDB88320L + +/** + * Macros to cleanly print 64-bit numbers on both 32-bit and 64-bit machines. + * Use these in place of %Ld, %Lu, and %Lx. + **/ +#if BITS_PER_LONG > 32 +#define PFU64 "%lu" +#else +#define PFU64 "%Lu" +#endif + +/** + * struct bbr_table_entry + * @bad_sect: LBA of bad location. + * @replacement_sect: LBA of new location. + * + * Structure to describe one BBR remap. + **/ +struct bbr_table_entry { + u64 bad_sect; + u64 replacement_sect; +}; + +/** + * struct bbr_table + * @signature: Signature on each BBR table sector. + * @crc: CRC for this table sector. + * @sequence_number: Used to resolve conflicts when primary and secondary + * tables do not match. + * @in_use_cnt: Number of in-use table entries. + * @entries: Actual table of remaps. + * + * Structure to describe each sector of the metadata table. Each sector in this + * table can describe 31 remapped sectors. + **/ +struct bbr_table { + u32 signature; + u32 crc; + u32 sequence_number; + u32 in_use_cnt; + struct bbr_table_entry entries[BBR_ENTRIES_PER_SECT]; +}; + +/** + * struct bbr_runtime_remap + * + * Node in the binary tree used to keep track of remaps. + **/ +struct bbr_runtime_remap { + struct bbr_table_entry remap; + struct bbr_runtime_remap *left; + struct bbr_runtime_remap *right; +}; + +/** + * struct bbr_private + * @dev: Info about underlying device. + * @bbr_table: Copy of metadata table. + * @remap_root: Binary tree containing all remaps. + * @remap_root_lock: Lock for the binary tree. + * @remap_work: For adding work items to the work-queue. + * @remap_ios: List of I/Os for the work-queue to handle. + * @remap_ios_lock: Lock for the remap_ios list. + * @offset: LBA of data area. + * @lba_table1: LBA of primary BBR table. + * @lba_table2: LBA of secondary BBR table. + * @nr_sects_bbr_table: Size of each BBR table. + * @nr_replacement_blks: Number of replacement blocks. + * @start_replacement_sect: LBA of start of replacement blocks. + * @blksize_in_sects: Size of each block. + * @in_use_replacement_blks: Current number of remapped blocks. + * + * Private data for each BBR target. + **/ +struct bbr_private { + struct dm_dev *dev; + struct bbr_table *bbr_table; + struct bbr_runtime_remap *remap_root; + spinlock_t remap_root_lock; + + struct dm_io_request vma_io_req; + struct dm_io_request page_io_req; + + struct work_struct remap_work; + struct bio_list remap_ios; + spinlock_t remap_ios_lock; + + u64 offset; + u64 lba_table1; + u64 lba_table2; + u64 nr_sects_bbr_table; + u64 start_replacement_sect; + u64 nr_replacement_blks; + u32 blksize_in_sects; + atomic_t in_use_replacement_blks; +}; + --- linux-2.6.27.orig/ubuntu/misc/lmpcm_usb.c +++ linux-2.6.27/ubuntu/misc/lmpcm_usb.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2004-2005 David Oliveira + * + * USB Logitech MediaPlay Cordless Mouse driver + * + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * If you need to contact me, you can do it by e-mail, sending a mail + * message to + */ + +#include +#include +#include +#include +#include +#include + +#ifdef BIT +#undef BIT +#endif +#define BIT(x) (1UL<<((x)%BITS_PER_LONG)) +#define LONG(x) ((x)/BITS_PER_LONG) + +#define DRIVER_VERSION "v0.5.5" +#define DRIVER_AUTHOR "David Oliveira " +#define DRIVER_DESC "USB Logitech MediaPlay Cordless Mouse driver" +#define DRIVER_LICENSE "GPL" + +#define GETBIT(v,n) ((v>>(n))&0x01) +#define SETBIT(v,n) (v |= (0x01<<(n))) + +#ifdef SLAB_ATOMIC +# define ATOMIC SLAB_ATOMIC +#else +# define ATOMIC GFP_ATOMIC +#endif + + +/* Module properties */ + +MODULE_AUTHOR ( DRIVER_AUTHOR ); +MODULE_DESCRIPTION ( DRIVER_DESC ); +MODULE_LICENSE ( DRIVER_LICENSE ); + + +/* Own type */ + +typedef struct usb_lmpcm { + + // Device name + + char name[128]; + + // USB interrupt data + + signed char *data; + + char phys[64]; + + dma_addr_t data_dma; + + // USB device + + struct usb_device *usbdev; + + // Input device + + struct input_dev *inputdev; + + // USB Request block + + struct urb *urb; + + // Number of openned times + + int open; + +} lmpcm_t; + + +// Initialize lmpcm structure + +void lmpcm_init ( lmpcm_t *lmpcm ) { + + memset(lmpcm, 0, sizeof(lmpcm_t)); + lmpcm->inputdev = NULL; + lmpcm->urb = NULL; + lmpcm->data = NULL; + +} + + +// Free lmpcm buffers + +void lmpcm_free ( lmpcm_t *lmpcm ) { + + if ( lmpcm->urb ) + usb_free_urb(lmpcm->urb); + + if ( lmpcm->data ) + usb_buffer_free(lmpcm->usbdev,8,lmpcm->data,lmpcm->data_dma); + + kfree(lmpcm); + +} + + +// Create new lmpcm (buffer allocation + +lmpcm_t *lmpcm_new ( struct usb_device *dev ) { + + lmpcm_t *lmpcm; + + // Create object + + if (!(lmpcm = kmalloc(sizeof(lmpcm_t), GFP_KERNEL))) + return NULL; + + // Initialize + + lmpcm_init(lmpcm); + + + // Input device + + if ( (lmpcm->inputdev = input_allocate_device()) == NULL ) { + lmpcm_free(lmpcm); + return NULL; + } + + + // Create urb handler + + if (!(lmpcm->urb = usb_alloc_urb(0, GFP_KERNEL))) { + lmpcm_free(lmpcm); + return NULL; + } + + + // Create data required for urb transfer + + if (!(lmpcm->data = usb_buffer_alloc(dev,8,ATOMIC,&lmpcm->data_dma))) { + lmpcm_free(lmpcm); + return NULL; + } + + + // Set lmpcm usb device + + lmpcm->usbdev = dev; + + + return lmpcm; + +} + + + + + +// Get data from urb and send to input API + +void input_send_data ( struct input_dev *dev, char *data ) { + + char + btn = data[0], // Basic buttons (left, right, middle, side and extra) + mbtn = data[6], // Media buttons + x = data[1], // X movement + y = data[2], // Y movement + w = data[3]; // Wheel movement + + + input_report_key(dev, BTN_LEFT, GETBIT(btn,0)); + input_report_key(dev, BTN_RIGHT, GETBIT(btn,1)); + input_report_key(dev, BTN_MIDDLE, GETBIT(btn,2)); + input_report_key(dev, BTN_SIDE, GETBIT(btn,3)); + input_report_key(dev, BTN_EXTRA, GETBIT(btn,4)); + input_report_key(dev, KEY_PLAYCD, GETBIT(btn,5)); + input_report_key(dev, KEY_BACK, GETBIT(btn,6)); + input_report_key(dev, KEY_FORWARD, GETBIT(btn,7)); + + input_report_key(dev, KEY_VOLUMEUP, GETBIT(mbtn,0)); + input_report_key(dev, KEY_VOLUMEDOWN, GETBIT(mbtn,1)); + input_report_key(dev, KEY_NEXTSONG, GETBIT(mbtn,2)); + input_report_key(dev, KEY_PREVIOUSSONG, GETBIT(mbtn,3)); + input_report_key(dev, KEY_PLAYPAUSE, GETBIT(mbtn,4)); + + input_report_rel(dev, REL_X, x); + input_report_rel(dev, REL_Y, y); + input_report_rel(dev, REL_WHEEL, w); + +} + +static void usb_lmpcm_handle(struct urb *urb) { + + lmpcm_t *mouse = urb->context; + signed char *data = mouse->data; + struct input_dev *inputdev = mouse->inputdev; + + + // Check returned status + + if (urb->status) return ; + + + // Send data to input interface + + input_send_data(inputdev,data); + + input_sync(inputdev); + usb_submit_urb(urb,ATOMIC); + +} + +static int usb_lmpcm_open(struct input_dev *dev) { + + lmpcm_t *mouse = (lmpcm_t *)input_get_drvdata(dev); + + if (mouse->open++) + return 0; + + mouse->urb->dev = mouse->usbdev; + + if (usb_submit_urb(mouse->urb, GFP_KERNEL)) { + mouse->open--; + return -EIO; + } + + return 0; + +} + +static void usb_lmpcm_close(struct input_dev *dev) { + + lmpcm_t *mouse = (lmpcm_t *)input_get_drvdata(dev); + + if (!--mouse->open) + usb_kill_urb(mouse->urb); + +} + +static void input_device_init ( struct input_dev *inputdev, struct usb_interface *intf, void *private, struct usb_device *dev ) { + + char path[64]; + + lmpcm_t *mouse = (lmpcm_t *) private; + + int + x, + keys[] = { KEY_PLAYPAUSE, KEY_BACK, KEY_FORWARD, KEY_PLAYCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, + KEY_NEXTSONG, KEY_PREVIOUSSONG, 0 }; + + + // Events + + inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + + // Add special keys + + for ( x = 0 ; keys[x] ; x++ ) + set_bit(keys[x],inputdev->keybit); + + // Add basic buttons + + inputdev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | + BIT(BTN_SIDE) | BIT(BTN_EXTRA); + + // Add move mouse movement (X/Y) + + inputdev->relbit[0] = BIT(REL_X) | BIT(REL_Y); + + // Add wheel + + inputdev->relbit[0] |= BIT(REL_WHEEL); + + + // Private data structure + + input_set_drvdata(inputdev, mouse); + + // Input file operations + + inputdev->open = usb_lmpcm_open; + inputdev->close = usb_lmpcm_close; + + // Device + + inputdev->name = mouse->name; + + usb_make_path(dev,path,64); + snprintf(mouse->phys,64,"%s/input0",path); + + inputdev->phys = mouse->phys; + inputdev->id.bustype = BUS_USB; + inputdev->id.vendor = dev->descriptor.idVendor; + inputdev->id.product = dev->descriptor.idProduct; + inputdev->id.version = dev->descriptor.bcdDevice; + +} + +static int usb_lmpcm_probe(struct usb_interface *intf, const struct usb_device_id *id) { + + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_host_interface *interface; + + + struct usb_endpoint_descriptor *endpoint; + lmpcm_t *mouse; + int pipe, maxp; + char *buf; + + + // Get mouse endpoint + + interface = intf->cur_altsetting; + + if ( interface->desc.bNumEndpoints != 1 ) return -ENODEV; + endpoint = &interface->endpoint[0].desc; + + + // Check endpoint + + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) + return -ENODEV; + + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) + return -ENODEV; + + + // Create endpoint pipe + + pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + + // Create lmpcm object + + if (!(mouse = lmpcm_new(dev))) + return -ENOMEM; + + // Initialize input device + + input_device_init(mouse->inputdev,intf,mouse,dev); + + + // Set device name + + if (!(buf = kmalloc(63, GFP_KERNEL))) { + lmpcm_free(mouse); + return -ENOMEM; + } + + + if (dev->descriptor.iManufacturer && + usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) + strcat(mouse->name, buf); + + if (dev->descriptor.iProduct && + usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + sprintf(mouse->name, "%s %s", mouse->name, buf); + + if (!strlen(mouse->name)) + sprintf(mouse->name, "lmpcm_usb.c: Logitech MediaPlay Mouse on usb%04x:%04x", + mouse->inputdev->id.vendor, mouse->inputdev->id.product); + + kfree(buf); + + + // Initialize interrupt transfer + + usb_fill_int_urb(mouse->urb,dev,pipe,mouse->data,((maxp > 8)?8:maxp),usb_lmpcm_handle,mouse,endpoint->bInterval); + mouse->urb->transfer_dma = mouse->data_dma; + mouse->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + + // Register input device + + input_register_device(mouse->inputdev); + + + printk(KERN_INFO "lmpcm_usb.c: Detected device: %s\n", mouse->name); + + // Set usb handler interface data + + usb_set_intfdata(intf,mouse); + + + return 0; + +} + + +static void usb_lmpcm_disconnect(struct usb_interface *intf) { + + lmpcm_t *mouse = usb_get_intfdata(intf); + + usb_set_intfdata(intf,NULL); + if (mouse) { + usb_kill_urb(mouse->urb); + input_unregister_device(mouse->inputdev); + lmpcm_free(mouse); + } + +} + + + + +/* Module structures */ + +static struct usb_device_id usb_lmpcm_id_table [] = { + { USB_DEVICE(0x46d, 0xc50e) }, + { } +}; + +MODULE_DEVICE_TABLE (usb, usb_lmpcm_id_table); + +static struct usb_driver usb_lmpcm_driver = { + + .name = "lmpcm_usb", + .probe = usb_lmpcm_probe, + .disconnect = usb_lmpcm_disconnect, + .id_table = usb_lmpcm_id_table + +}; + + + +/* Module main functions */ + +static int __init usb_lmpcm_init(void) { + + int rv; + + // Register usb driver + + rv = usb_register(&usb_lmpcm_driver); + + info(DRIVER_VERSION ":" DRIVER_DESC); + + return rv; +} + +static void __exit usb_lmpcm_exit(void) { + + usb_deregister(&usb_lmpcm_driver); + +} + +// Set + +module_init(usb_lmpcm_init); +module_exit(usb_lmpcm_exit); --- linux-2.6.27.orig/ubuntu/misc/acerhk.h +++ linux-2.6.27/ubuntu/misc/acerhk.h @@ -0,0 +1,91 @@ +#ifndef __ACERHK_H__ +#define __ACERHK_H__ + +#include + +#define ACERHK_MINOR MISC_DYNAMIC_MINOR + +#define ACERHK_GET_KEYCOUNT _IOR('p', 0x01, char) /* Get number of cached key presses */ +#define ACERHK_GET_KEYID _IOR('p', 0x02, char) /* Get first key in queue */ +#define ACERHK_CONNECT _IO('p', 0x03) /* ? */ +#define ACERHK_DISCONNECT _IO('p', 0x04) /* ? */ +#define ACERHK_GET_THERMAL_EVENT _IOR('p', 0x05, short) /* ? */ +#define ACERHK_MAIL_LED_OFF _IO('p', 0x10) /* switch mail LED off */ +#define ACERHK_MAIL_LED_ON _IO('p', 0x11) /* switch mail LED on (blinking) */ +#define ACERHK_START_POLLING _IO('p', 0x12) /* poll keys in kernel, send real key events */ +#define ACERHK_STOP_POLLING _IO('p', 0x13) /* stop key polling in kernel */ +#define ACERHK_GET_KEY_MAP _IOR('p', 0x20, int) /* Get mapping of key names to key events, */ +#define ACERHK_SET_KEY_MAP _IOW('p', 0x21, int) /* Set mapping of key names to key events */ + +/* all possible keys (known to me) */ +typedef enum e_key_names { + k_none = 0, + k_help = 1, /* Fn+F1 */ + k_setup = 2, /* Fn+F2 */ + k_p1 = 3, + k_p2 = 4, + k_p3 = 5, + k_www = 6, + k_mail = 7, + k_wireless = 8, + k_power = 9, /* Fn+F3 */ + k_mute = 10, /* Fn+F8 */ + k_volup = 11, /* Fn+Up */ + k_voldn = 12, /* Fn+Down */ + k_res = 13, /* resolution change on Medion MD 40100 */ + k_close = 14, /* if lid is closed in tablet mode */ + k_open = 15, /* if lid is opend in tablet mode */ + k_wireless2 = 16, /* second wireless button on TM 243LC */ + k_play = 17, /* Play/Pause found on AOpen */ + k_stop = 18, /* Stop/Eject found on AOpen */ + k_prev = 19, /* Prev found on AOpen */ + k_next = 20, /* Next found on AOpen */ + k_display = 21 /* Change internal/external display on MD 42200 */ +} t_key_names; +#define NR_KEY_NAMES 22 +typedef unsigned int t_map_name2event[NR_KEY_NAMES]; + +#ifdef __KERNEL__ + +/* available features */ +#define TM_F_WLAN_EC1 0x00000010 +#define TM_F_BLUE_EC1 0x00000020 +#define TM_F_WLAN_EC2 0x00000040 +#define TM_F_BLUE_EC2 0x00000080 +#define TM_F_MUTE_LED_EC 0x00001000 +#define TM_F_MAIL_LED 0x00010000 +#define TM_F_MAIL_LED_EC 0x00020000 +#define TM_F_MAIL_LED_EC2 0x00040000 +#define TM_F_MAIL_LED_EC3 0x00080000 + +#define TM_F_CONNECT 0x00100000 +#define TM_F_THERMAL 0x00200000 +#define TM_F_PBUTTON 0x00400000 +#define TM_F_WBUTTON 0x00800000 + +typedef enum acer_type { + TM_unknown, + /* 200, 210, 520, 600 and 730 series, Medion MD42200 */ + TM_old, + /* C100, C110, 220, 230, 240, 260, 350, 360, 610, 620, 630, 740 series + Medion MD40100, Aspire 1600, FS Amilo */ + TM_new, + /* Aspire 13xx, 14xx, 1700, TM 290, 650, 660, 800 */ + TM_dritek +} t_acer_type; + +struct register_buffer { + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + unsigned int edi; + unsigned int esi; + unsigned int ebp; +}; + +typedef asmlinkage void (*bios_call) (struct register_buffer *); + +#endif + +#endif --- linux-2.6.27.orig/ubuntu/misc/tp_smapi.c +++ linux-2.6.27/ubuntu/misc/tp_smapi.c @@ -0,0 +1,1477 @@ +/* + * tp_smapi.c - ThinkPad SMAPI support + * + * This driver exposes some features of the System Management Application + * Program Interface (SMAPI) BIOS found on ThinkPad laptops. It works on + * models in which the SMAPI BIOS runs in SMM and is invoked by writing + * to the APM control port 0xB2. Older models use a different interface; + * for those, try the out-of-tree "thinkpad" module from "tpctl". + * It also exposes battery status information, obtained from the ThinkPad + * embedded controller (via the thinkpad_ec module). + * + * Many of the battery status values obtained from the EC simply mirror + * values provided by the battery's Smart Battery System (SBS) interface, so + * their meaning is defined by the Smart Battery Data Specification. + * References to this SBS spec are given in the code where relevant. + * + * Copyright (C) 2006 Shem Multinymous . + * SMAPI access code based on the mwave driver by Mike Sullivan. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include /* CMOS defines */ +#include +#include +#include "thinkpad_ec.h" +#include +#include +#include + +#define TP_VERSION "0.37" +#define TP_DESC "ThinkPad SMAPI Support" +#define TP_DIR "smapi" + +MODULE_AUTHOR("Shem Multinymous"); +MODULE_DESCRIPTION(TP_DESC); +MODULE_VERSION(TP_VERSION); +MODULE_LICENSE("GPL"); + +static struct platform_device *pdev; + +static int tp_debug; +module_param_named(debug, tp_debug, int, 0600); +MODULE_PARM_DESC(debug, "Debug level (0=off, 1=on)"); + +/* A few macros for printk()ing: */ +#define TPRINTK(level, fmt, args...) \ + dev_printk(level, &(pdev->dev), "%s: " fmt "\n", __func__, ## args) +#define DPRINTK(fmt, args...) \ + do { if (tp_debug) TPRINTK(KERN_DEBUG, fmt, ## args); } while (0) + +/********************************************************************* + * SMAPI interface + */ + +/* SMAPI functions (register BX when making the SMM call). */ +#define SMAPI_GET_INHIBIT_CHARGE 0x2114 +#define SMAPI_SET_INHIBIT_CHARGE 0x2115 +#define SMAPI_GET_THRESH_START 0x2116 +#define SMAPI_SET_THRESH_START 0x2117 +#define SMAPI_GET_FORCE_DISCHARGE 0x2118 +#define SMAPI_SET_FORCE_DISCHARGE 0x2119 +#define SMAPI_GET_THRESH_STOP 0x211a +#define SMAPI_SET_THRESH_STOP 0x211b + +/* SMAPI error codes (see ThinkPad 770 Technical Reference Manual p.83 at + http://www-307.ibm.com/pc/support/site.wss/document.do?lndocid=PFAN-3TUQQD */ +#define SMAPI_RETCODE_EOF 0xff +static struct { u8 rc; char *msg; int ret; } smapi_retcode[] = +{ + {0x00, "OK", 0}, + {0x53, "SMAPI fuction is not available", -ENXIO}, + {0x81, "Invalid parameter", -EINVAL}, + {0x86, "Function is not supported by SMAPI BIOS", -EOPNOTSUPP}, + {0x90, "System error", -EIO}, + {0x91, "System is invalid", -EIO}, + {0x92, "System is busy, -EBUSY"}, + {0xa0, "Device error (disk read error)", -EIO}, + {0xa1, "Device is busy", -EBUSY}, + {0xa2, "Device is not attached", -ENXIO}, + {0xa3, "Device is disbled", -EIO}, + {0xa4, "Request parameter is out of range", -EINVAL}, + {0xa5, "Request parameter is not accepted", -EINVAL}, + {0xa6, "Transient error", -EBUSY}, /* ? */ + {SMAPI_RETCODE_EOF, "Unknown error code", -EIO} +}; + + +#define SMAPI_MAX_RETRIES 10 +#define SMAPI_PORT2 0x4F /* fixed port, meaning unclear */ +static unsigned short smapi_port; /* APM control port, normally 0xB2 */ + +static DECLARE_MUTEX(smapi_mutex); + +/** + * find_smapi_port - read SMAPI port from NVRAM + */ +static int __init find_smapi_port(void) +{ + u16 smapi_id = 0; + unsigned short port = 0; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + smapi_id = CMOS_READ(0x7C); + smapi_id |= (CMOS_READ(0x7D) << 8); + spin_unlock_irqrestore(&rtc_lock, flags); + + if (smapi_id != 0x5349) { + printk(KERN_ERR "SMAPI not supported (ID=0x%x)\n", smapi_id); + return -ENXIO; + } + spin_lock_irqsave(&rtc_lock, flags); + port = CMOS_READ(0x7E); + port |= (CMOS_READ(0x7F) << 8); + spin_unlock_irqrestore(&rtc_lock, flags); + if (port == 0) { + printk(KERN_ERR "unable to read SMAPI port number\n"); + return -ENXIO; + } + return port; +} + +/** + * smapi_request - make a SMAPI call + * @inEBX, @inECX, @inEDI, @inESI: input registers + * @outEBX, @outECX, @outEDX, @outEDI, @outESI: outputs registers + * @msg: textual error message + * Invokes the SMAPI SMBIOS with the given input and outpu args. + * All outputs are optional (can be %NULL). + * Returns 0 when successful, and a negative errno constant + * (see smapi_retcode above) upon failure. + */ +static int smapi_request(u32 inEBX, u32 inECX, + u32 inEDI, u32 inESI, + u32 *outEBX, u32 *outECX, u32 *outEDX, + u32 *outEDI, u32 *outESI, const char **msg) +{ + int ret = 0; + int i; + int retries; + u8 rc; + /* Must use local vars for output regs, due to reg pressure. */ + u32 tmpEAX, tmpEBX, tmpECX, tmpEDX, tmpEDI, tmpESI; + + for (retries = 0; retries < SMAPI_MAX_RETRIES; ++retries) { + DPRINTK("req_in: BX=%x CX=%x DI=%x SI=%x", + inEBX, inECX, inEDI, inESI); + + /* SMAPI's SMBIOS call and thinkpad_ec end up using use + * different interfaces to the same chip, so play it safe. */ + ret = thinkpad_ec_lock(); + if (ret) + return ret; + + __asm__ __volatile__( + "movl $0x00005380,%%eax\n\t" + "movl %6,%%ebx\n\t" + "movl %7,%%ecx\n\t" + "movl %8,%%edi\n\t" + "movl %9,%%esi\n\t" + "xorl %%edx,%%edx\n\t" + "movw %10,%%dx\n\t" + "out %%al,%%dx\n\t" /* trigger SMI to SMBIOS */ + "out %%al,$0x4F\n\t" + "movl %%eax,%0\n\t" + "movl %%ebx,%1\n\t" + "movl %%ecx,%2\n\t" + "movl %%edx,%3\n\t" + "movl %%edi,%4\n\t" + "movl %%esi,%5\n\t" + :"=m"(tmpEAX), + "=m"(tmpEBX), + "=m"(tmpECX), + "=m"(tmpEDX), + "=m"(tmpEDI), + "=m"(tmpESI) + :"m"(inEBX), "m"(inECX), "m"(inEDI), "m"(inESI), + "m"((u16)smapi_port) + :"%eax", "%ebx", "%ecx", "%edx", "%edi", + "%esi"); + + thinkpad_ec_invalidate(); + thinkpad_ec_unlock(); + + /* Don't let the next SMAPI access happen too quickly, + * may case problems. (We're hold smapi_mutex). */ + msleep(50); + + if (outEBX) *outEBX = tmpEBX; + if (outECX) *outECX = tmpECX; + if (outEDX) *outEDX = tmpEDX; + if (outESI) *outESI = tmpESI; + if (outEDI) *outEDI = tmpEDI; + + /* Look up error code */ + rc = (tmpEAX>>8)&0xFF; + for (i = 0; smapi_retcode[i].rc != SMAPI_RETCODE_EOF && + smapi_retcode[i].rc != rc; ++i) {} + ret = smapi_retcode[i].ret; + if (msg) + *msg = smapi_retcode[i].msg; + + DPRINTK("req_out: AX=%x BX=%x CX=%x DX=%x DI=%x SI=%x r=%d", + tmpEAX, tmpEBX, tmpECX, tmpEDX, tmpEDI, tmpESI, ret); + if (ret) + TPRINTK(KERN_NOTICE, "SMAPI error: %s (func=%x)", + smapi_retcode[i].msg, inEBX); + + if (ret != -EBUSY) + return ret; + } + return ret; +} + +/* Convenience wrapper: discard output arguments */ +static int smapi_write(u32 inEBX, u32 inECX, + u32 inEDI, u32 inESI, const char **msg) +{ + return smapi_request(inEBX, inECX, inEDI, inESI, + NULL, NULL, NULL, NULL, NULL, msg); +} + + +/********************************************************************* + * Specific SMAPI services + * All of these functions return 0 upon success, and a negative errno + * constant (see smapi_retcode) on failure. + */ + +enum thresh_type { + THRESH_STOP = 0, /* the code assumes this is 0 for brevity */ + THRESH_START +}; +#define THRESH_NAME(which) ((which == THRESH_START) ? "start" : "stop") + +/** + * __get_real_thresh - read battery charge start/stop threshold from SMAPI + * @bat: battery number (0 or 1) + * @which: THRESH_START or THRESH_STOP + * @thresh: 1..99, 0=default 1..99, 0=default (pass this as-is to SMAPI) + * @outEDI: some additional state that needs to be preserved, meaning unknown + * @outESI: some additional state that needs to be preserved, meaning unknown + */ +static int __get_real_thresh(int bat, enum thresh_type which, int *thresh, + u32 *outEDI, u32 *outESI) +{ + u32 ebx = (which == THRESH_START) ? SMAPI_GET_THRESH_START + : SMAPI_GET_THRESH_STOP; + u32 ecx = (bat+1)<<8; + const char *msg; + int ret = smapi_request(ebx, ecx, 0, 0, NULL, + &ecx, NULL, outEDI, outESI, &msg); + if (ret) { + TPRINTK(KERN_NOTICE, "cannot get %s_thresh of bat=%d: %s", + THRESH_NAME(which), bat, msg); + return ret; + } + if (!(ecx&0x00000100)) { + TPRINTK(KERN_NOTICE, "cannot get %s_thresh of bat=%d: ecx=0%x", + THRESH_NAME(which), bat, ecx); + return -EIO; + } + if (thresh) + *thresh = ecx&0xFF; + return 0; +} + +/** + * get_real_thresh - read battery charge start/stop threshold from SMAPI + * @bat: battery number (0 or 1) + * @which: THRESH_START or THRESH_STOP + * @thresh: 1..99, 0=default (passes as-is to SMAPI) + */ +static int get_real_thresh(int bat, enum thresh_type which, int *thresh) +{ + return __get_real_thresh(bat, which, thresh, NULL, NULL); +} + +/** + * set_real_thresh - write battery start/top charge threshold to SMAPI + * @bat: battery number (0 or 1) + * @which: THRESH_START or THRESH_STOP + * @thresh: 1..99, 0=default (passes as-is to SMAPI) + */ +static int set_real_thresh(int bat, enum thresh_type which, int thresh) +{ + u32 ebx = (which == THRESH_START) ? SMAPI_SET_THRESH_START + : SMAPI_SET_THRESH_STOP; + u32 ecx = ((bat+1)<<8) + thresh; + u32 getDI, getSI; + const char *msg; + int ret; + + /* verify read before writing */ + ret = __get_real_thresh(bat, which, NULL, &getDI, &getSI); + if (ret) + return ret; + + ret = smapi_write(ebx, ecx, getDI, getSI, &msg); + if (ret) + TPRINTK(KERN_NOTICE, "set %s to %d for bat=%d failed: %s", + THRESH_NAME(which), thresh, bat, msg); + else + TPRINTK(KERN_INFO, "set %s to %d for bat=%d", + THRESH_NAME(which), thresh, bat); + return ret; +} + +/** + * __get_inhibit_charge_minutes - get inhibit charge period from SMAPI + * @bat: battery number (0 or 1) + * @minutes: period in minutes (1..65535 minutes, 0=disabled) + * @outECX: some additional state that needs to be preserved, meaning unknown + * Note that @minutes is the originally set value, it does not count down. + */ +static int __get_inhibit_charge_minutes(int bat, int *minutes, u32 *outECX) +{ + u32 ecx = (bat+1)<<8; + u32 esi; + const char *msg; + int ret = smapi_request(SMAPI_GET_INHIBIT_CHARGE, ecx, 0, 0, + NULL, &ecx, NULL, NULL, &esi, &msg); + if (ret) { + TPRINTK(KERN_NOTICE, "failed for bat=%d: %s", bat, msg); + return ret; + } + if (!(ecx&0x0100)) { + TPRINTK(KERN_NOTICE, "bad ecx=0x%x for bat=%d", ecx, bat); + return -EIO; + } + if (minutes) + *minutes = (ecx&0x0001)?esi:0; + if (outECX) + *outECX = ecx; + return 0; +} + +/** + * get_inhibit_charge_minutes - get inhibit charge period from SMAPI + * @bat: battery number (0 or 1) + * @minutes: period in minutes (1..65535 minutes, 0=disabled) + * Note that @minutes is the originally set value, it does not count down. + */ +static int get_inhibit_charge_minutes(int bat, int *minutes) +{ + return __get_inhibit_charge_minutes(bat, minutes, NULL); +} + +/** + * set_inhibit_charge_minutes - write inhibit charge period to SMAPI + * @bat: battery number (0 or 1) + * @minutes: period in minutes (1..65535 minutes, 0=disabled) + */ +static int set_inhibit_charge_minutes(int bat, int minutes) +{ + u32 ecx; + const char *msg; + int ret; + + /* verify read before writing */ + ret = __get_inhibit_charge_minutes(bat, NULL, &ecx); + if (ret) + return ret; + + ecx = ((bat+1)<<8) | (ecx&0x00FE) | (minutes > 0 ? 0x0001 : 0x0000); + if (minutes > 0xFFFF) + minutes = 0xFFFF; + ret = smapi_write(SMAPI_SET_INHIBIT_CHARGE, ecx, 0, minutes, &msg); + if (ret) + TPRINTK(KERN_NOTICE, + "set to %d failed for bat=%d: %s", minutes, bat, msg); + else + TPRINTK(KERN_INFO, "set to %d for bat=%d\n", minutes, bat); + return ret; +} + + +/** + * get_force_discharge - get status of forced discharging from SMAPI + * @bat: battery number (0 or 1) + * @enabled: 1 if forced discharged is enabled, 0 if not + */ +static int get_force_discharge(int bat, int *enabled) +{ + u32 ecx = (bat+1)<<8; + const char *msg; + int ret = smapi_request(SMAPI_GET_FORCE_DISCHARGE, ecx, 0, 0, + NULL, &ecx, NULL, NULL, NULL, &msg); + if (ret) { + TPRINTK(KERN_NOTICE, "failed for bat=%d: %s", bat, msg); + return ret; + } + *enabled = (!(ecx&0x00000100) && (ecx&0x00000001))?1:0; + return 0; +} + +/** + * set_force_discharge - write status of forced discharging to SMAPI + * @bat: battery number (0 or 1) + * @enabled: 1 if forced discharged is enabled, 0 if not + */ +static int set_force_discharge(int bat, int enabled) +{ + u32 ecx = (bat+1)<<8; + const char *msg; + int ret = smapi_request(SMAPI_GET_FORCE_DISCHARGE, ecx, 0, 0, + NULL, &ecx, NULL, NULL, NULL, &msg); + if (ret) { + TPRINTK(KERN_NOTICE, "get failed for bat=%d: %s", bat, msg); + return ret; + } + if (ecx&0x00000100) { + TPRINTK(KERN_NOTICE, "cannot force discharge bat=%d", bat); + return -EIO; + } + + ecx = ((bat+1)<<8) | (ecx&0x000000FA) | (enabled?0x00000001:0); + ret = smapi_write(SMAPI_SET_FORCE_DISCHARGE, ecx, 0, 0, &msg); + if (ret) + TPRINTK(KERN_NOTICE, "set to %d failed for bat=%d: %s", + enabled, bat, msg); + else + TPRINTK(KERN_INFO, "set to %d for bat=%d", enabled, bat); + return ret; +} + + +/********************************************************************* + * Wrappers to threshold-related SMAPI functions, which handle default + * thresholds and related quirks. + */ + +/* Minimum, default and minimum difference for battery charging thresholds: */ +#define MIN_THRESH_DELTA 4 /* Min delta between start and stop thresh */ +#define MIN_THRESH_START 2 +#define MAX_THRESH_START (100-MIN_THRESH_DELTA) +#define MIN_THRESH_STOP (MIN_THRESH_START + MIN_THRESH_DELTA) +#define MAX_THRESH_STOP 100 +#define DEFAULT_THRESH_START MAX_THRESH_START +#define DEFAULT_THRESH_STOP MAX_THRESH_STOP + +/* The GUI of IBM's Battery Maximizer seems to show a start threshold that + * is 1 more than the value we set/get via SMAPI. Since the threshold is + * maintained across reboot, this can be confusing. So we kludge our + * interface for interoperability: */ +#define BATMAX_FIX 1 + +/* Get charge start/stop threshold (1..100), + * substituting default values if needed and applying BATMAT_FIX. */ +static int get_thresh(int bat, enum thresh_type which, int *thresh) +{ + int ret = get_real_thresh(bat, which, thresh); + if (ret) + return ret; + if (*thresh == 0) + *thresh = (which == THRESH_START) ? DEFAULT_THRESH_START + : DEFAULT_THRESH_STOP; + else if (which == THRESH_START) + *thresh += BATMAX_FIX; + return 0; +} + + +/* Set charge start/stop threshold (1..100), + * substituting default values if needed and applying BATMAT_FIX. */ +static int set_thresh(int bat, enum thresh_type which, int thresh) +{ + if (which == THRESH_STOP && thresh == DEFAULT_THRESH_STOP) + thresh = 0; /* 100 is out of range, but default means 100 */ + if (which == THRESH_START) + thresh -= BATMAX_FIX; + return set_real_thresh(bat, which, thresh); +} + +/********************************************************************* + * ThinkPad embedded controller readout and basic functions + */ + +/** + * read_tp_ec_row - read data row from the ThinkPad embedded controller + * @arg0: EC command code + * @bat: battery number, 0 or 1 + * @j: the byte value to be used for "junk" (unused) input/outputs + * @dataval: result vector + */ +static int read_tp_ec_row(u8 arg0, int bat, u8 j, u8 *dataval) +{ + int ret; + const struct thinkpad_ec_row args = { .mask = 0xFFFF, + .val = {arg0, j,j,j,j,j,j,j,j,j,j,j,j,j,j, (u8)bat} }; + struct thinkpad_ec_row data = { .mask = 0xFFFF }; + + ret = thinkpad_ec_lock(); + if (ret) + return ret; + ret = thinkpad_ec_read_row(&args, &data); + thinkpad_ec_unlock(); + memcpy(dataval, &data.val, TP_CONTROLLER_ROW_LEN); + return ret; +} + +/** + * power_device_present - check for presence of battery or AC power + * @bat: 0 for battery 0, 1 for battery 1, otherwise AC power + * Returns 1 if present, 0 if not present, negative if error. + */ +static int power_device_present(int bat) +{ + u8 row[TP_CONTROLLER_ROW_LEN]; + u8 test; + int ret = read_tp_ec_row(1, bat, 0, row); + if (ret) + return ret; + switch (bat) { + case 0: test = 0x40; break; /* battery 0 */ + case 1: test = 0x20; break; /* battery 1 */ + default: test = 0x80; /* AC power */ + } + return (row[0] & test) ? 1 : 0; +} + +/** + * bat_has_status - check if battery can report detailed status + * @bat: 0 for battery 0, 1 for battery 1 + * Returns 1 if yes, 0 if no, negative if error. + */ +static int bat_has_status(int bat) +{ + u8 row[TP_CONTROLLER_ROW_LEN]; + int ret = read_tp_ec_row(1, bat, 0, row); + if (ret) + return ret; + if ((row[0] & (bat?0x20:0x40)) == 0) /* no battery */ + return 0; + if ((row[1] & (0x60)) == 0) /* no status */ + return 0; + return 1; +} + +/** + * get_tp_ec_bat_16 - read a 16-bit value from EC battery status data + * @arg0: first argument to EC + * @off: offset in row returned from EC + * @bat: battery (0 or 1) + * @val: the 16-bit value obtained + * Returns nonzero on error. + */ +static int get_tp_ec_bat_16(u8 arg0, int offset, int bat, u16 *val) +{ + u8 row[TP_CONTROLLER_ROW_LEN]; + int ret; + if (bat_has_status(bat) != 1) + return -ENXIO; + ret = read_tp_ec_row(arg0, bat, 0, row); + if (ret) + return ret; + *val = *(u16 *)(row+offset); + return 0; +} + +/********************************************************************* + * sysfs attributes for batteries - + * definitions and helper functions + */ + +/* A custom device attribute struct which holds a battery number */ +struct bat_device_attribute { + struct device_attribute dev_attr; + int bat; +}; + +/** + * attr_get_bat - get the battery to which the attribute belongs + */ +static int attr_get_bat(struct device_attribute *attr) +{ + return container_of(attr, struct bat_device_attribute, dev_attr)->bat; +} + +/** + * show_tp_ec_bat_u16 - show an unsigned 16-bit battery attribute + * @arg0: specified 1st argument of EC raw to read + * @offset: byte offset in EC raw data + * @mul: correction factor to multiply by + * @na_msg: string to output is value not available (0xFFFFFFFF) + * @attr: battery attribute + * @buf: output buffer + * The 16-bit value is read from the EC, treated as unsigned, + * transformed as x->mul*x, and printed to the buffer. + * If the value is 0xFFFFFFFF and na_msg!=%NULL, na_msg is printed instead. + */ +static ssize_t show_tp_ec_bat_u16(u8 arg0, int offset, int mul, + const char *na_msg, + struct device_attribute *attr, char *buf) +{ + u16 val; + int ret = get_tp_ec_bat_16(arg0, offset, attr_get_bat(attr), &val); + if (ret) + return ret; + if (na_msg && val == 0xFFFF) + return sprintf(buf, "%s\n", na_msg); + else + return sprintf(buf, "%u\n", mul*(unsigned int)val); +} + +/** + * show_tp_ec_bat_s16 - show an signed 16-bit battery attribute + * @arg0: specified 1st argument of EC raw to read + * @offset: byte offset in EC raw data + * @mul: correction factor to multiply by + * @add: correction term to add after multiplication + * @attr: battery attribute + * @buf: output buffer + * The 16-bit value is read from the EC, treated as signed, + * transformed as x->mul*x+add, and printed to the buffer. + */ +static ssize_t show_tp_ec_bat_s16(u8 arg0, int offset, int mul, int add, + struct device_attribute *attr, char *buf) +{ + u16 val; + int ret = get_tp_ec_bat_16(arg0, offset, attr_get_bat(attr), &val); + if (ret) + return ret; + return sprintf(buf, "%d\n", mul*(s16)val+add); +} + +/** + * show_tp_ec_bat_str - show a string from EC battery status data + * @arg0: specified 1st argument of EC raw to read + * @offset: byte offset in EC raw data + * @maxlen: maximum string length + * @attr: battery attribute + * @buf: output buffer + */ +static ssize_t show_tp_ec_bat_str(u8 arg0, int offset, int maxlen, + struct device_attribute *attr, char *buf) +{ + int bat = attr_get_bat(attr); + u8 row[TP_CONTROLLER_ROW_LEN]; + int ret; + if (bat_has_status(bat) != 1) + return -ENXIO; + ret = read_tp_ec_row(arg0, bat, 0, row); + if (ret) + return ret; + strncpy(buf, (char *)row+offset, maxlen); + buf[maxlen] = 0; + strcat(buf, "\n"); + return strlen(buf); +} + +/** + * show_tp_ec_bat_power - show a power readout from EC battery status data + * @arg0: specified 1st argument of EC raw to read + * @offV: byte offset of voltage in EC raw data + * @offI: byte offset of current in EC raw data + * @attr: battery attribute + * @buf: output buffer + * Computes the power as current*voltage from the two given readout offsets. + */ +static ssize_t show_tp_ec_bat_power(u8 arg0, int offV, int offI, + struct device_attribute *attr, char *buf) +{ + u8 row[TP_CONTROLLER_ROW_LEN]; + int milliamp, millivolt, ret; + int bat = attr_get_bat(attr); + if (bat_has_status(bat) != 1) + return -ENXIO; + ret = read_tp_ec_row(1, bat, 0, row); + if (ret) + return ret; + millivolt = *(u16 *)(row+offV); + milliamp = *(s16 *)(row+offI); + return sprintf(buf, "%d\n", milliamp*millivolt/1000); /* units: mW */ +} + +/** + * show_tp_ec_bat_date - decode and show a date from EC battery status data + * @arg0: specified 1st argument of EC raw to read + * @offset: byte offset in EC raw data + * @attr: battery attribute + * @buf: output buffer + */ +static ssize_t show_tp_ec_bat_date(u8 arg0, int offset, + struct device_attribute *attr, char *buf) +{ + u8 row[TP_CONTROLLER_ROW_LEN]; + u16 v; + int ret; + int day, month, year; + int bat = attr_get_bat(attr); + if (bat_has_status(bat) != 1) + return -ENXIO; + ret = read_tp_ec_row(arg0, bat, 0, row); + if (ret) + return ret; + + /* Decode bit-packed: v = day | (month<<5) | ((year-1980)<<9) */ + v = *(u16 *)(row+offset); + day = v & 0x1F; + month = (v >> 5) & 0xF; + year = (v >> 9) + 1980; + + return sprintf(buf, "%04d-%02d-%02d\n", year, month, day); +} + + +/********************************************************************* + * sysfs attribute I/O for batteries - + * the actual attribute show/store functions + */ + +static ssize_t show_battery_start_charge_thresh(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int thresh; + int bat = attr_get_bat(attr); + int ret = get_thresh(bat, THRESH_START, &thresh); + if (ret) + return ret; + return sprintf(buf, "%d\n", thresh); /* units: percent */ +} + +static ssize_t show_battery_stop_charge_thresh(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int thresh; + int bat = attr_get_bat(attr); + int ret = get_thresh(bat, THRESH_STOP, &thresh); + if (ret) + return ret; + return sprintf(buf, "%d\n", thresh); /* units: percent */ +} + +/** + * store_battery_start_charge_thresh - store battery_start_charge_thresh attr + * Since this is a kernel<->user interface, we ensure a valid state for + * the hardware. We do this by clamping the requested threshold to the + * valid range and, if necessary, moving the other threshold so that + * it's MIN_THRESH_DELTA away from this one. + */ +static ssize_t store_battery_start_charge_thresh(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int thresh, other_thresh, ret; + int bat = attr_get_bat(attr); + + if (sscanf(buf, "%d", &thresh) != 1 || thresh < 1 || thresh > 100) + return -EINVAL; + + if (thresh < MIN_THRESH_START) /* clamp up to MIN_THRESH_START */ + thresh = MIN_THRESH_START; + if (thresh > MAX_THRESH_START) /* clamp down to MAX_THRESH_START */ + thresh = MAX_THRESH_START; + + down(&smapi_mutex); + ret = get_thresh(bat, THRESH_STOP, &other_thresh); + if (ret != -EOPNOTSUPP) { + if (ret) /* other threshold is set? */ + goto out; + ret = get_real_thresh(bat, THRESH_START, NULL); + if (ret) /* this threshold is set? */ + goto out; + if (other_thresh < thresh+MIN_THRESH_DELTA) { + /* move other thresh to keep it above this one */ + ret = set_thresh(bat, THRESH_STOP, + thresh+MIN_THRESH_DELTA); + if (ret) + goto out; + } + } + ret = set_thresh(bat, THRESH_START, thresh); +out: + up(&smapi_mutex); + return count; + +} + +/** + * store_battery_stop_charge_thresh - store battery_stop_charge_thresh attr + * Since this is a kernel<->user interface, we ensure a valid state for + * the hardware. We do this by clamping the requested threshold to the + * valid range and, if necessary, moving the other threshold so that + * it's MIN_THRESH_DELTA away from this one. + */ +static ssize_t store_battery_stop_charge_thresh(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int thresh, other_thresh, ret; + int bat = attr_get_bat(attr); + + if (sscanf(buf, "%d", &thresh) != 1 || thresh < 1 || thresh > 100) + return -EINVAL; + + if (thresh < MIN_THRESH_STOP) /* clamp up to MIN_THRESH_STOP */ + thresh = MIN_THRESH_STOP; + + down(&smapi_mutex); + ret = get_thresh(bat, THRESH_START, &other_thresh); + if (ret != -EOPNOTSUPP) { /* other threshold exists? */ + if (ret) + goto out; + /* this threshold exists? */ + ret = get_real_thresh(bat, THRESH_STOP, NULL); + if (ret) + goto out; + if (other_thresh >= thresh-MIN_THRESH_DELTA) { + /* move other thresh to be below this one */ + ret = set_thresh(bat, THRESH_START, + thresh-MIN_THRESH_DELTA); + if (ret) + goto out; + } + } + ret = set_thresh(bat, THRESH_STOP, thresh); +out: + up(&smapi_mutex); + return count; +} + +static ssize_t show_battery_inhibit_charge_minutes(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int minutes; + int bat = attr_get_bat(attr); + int ret = get_inhibit_charge_minutes(bat, &minutes); + if (ret) + return ret; + return sprintf(buf, "%d\n", minutes); /* units: minutes */ +} + +static ssize_t store_battery_inhibit_charge_minutes(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + int minutes; + int bat = attr_get_bat(attr); + if (sscanf(buf, "%d", &minutes) != 1 || minutes < 0) { + TPRINTK(KERN_ERR, "inhibit_charge_minutes: " + "must be a non-negative integer"); + return -EINVAL; + } + ret = set_inhibit_charge_minutes(bat, minutes); + if (ret) + return ret; + return count; +} + +static ssize_t show_battery_force_discharge(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int enabled; + int bat = attr_get_bat(attr); + int ret = get_force_discharge(bat, &enabled); + if (ret) + return ret; + return sprintf(buf, "%d\n", enabled); /* type: boolean */ +} + +static ssize_t store_battery_force_discharge(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + int enabled; + int bat = attr_get_bat(attr); + if (sscanf(buf, "%d", &enabled) != 1 || enabled < 0 || enabled > 1) + return -EINVAL; + ret = set_force_discharge(bat, enabled); + if (ret) + return ret; + return count; +} + +static ssize_t show_battery_installed( + struct device *dev, struct device_attribute *attr, char *buf) +{ + int bat = attr_get_bat(attr); + int ret = power_device_present(bat); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", ret); /* type: boolean */ +} + +static ssize_t show_battery_state( + struct device *dev, struct device_attribute *attr, char *buf) +{ + u8 row[TP_CONTROLLER_ROW_LEN]; + const char *txt; + int ret; + int bat = attr_get_bat(attr); + if (bat_has_status(bat) != 1) + return sprintf(buf, "none\n"); + ret = read_tp_ec_row(1, bat, 0, row); + if (ret) + return ret; + switch (row[1] & 0xf0) { + case 0xc0: txt = "idle"; break; + case 0xd0: txt = "discharging"; break; + case 0xe0: txt = "charging"; break; + default: return sprintf(buf, "unknown (0x%x)\n", row[1]); + } + return sprintf(buf, "%s\n", txt); /* type: string from fixed set */ +} + +static ssize_t show_battery_manufacturer( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* type: string. SBS spec v1.1 p34: ManufacturerName() */ + return show_tp_ec_bat_str(4, 2, TP_CONTROLLER_ROW_LEN-2, attr, buf); +} + +static ssize_t show_battery_model( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* type: string. SBS spec v1.1 p34: DeviceName() */ + return show_tp_ec_bat_str(5, 2, TP_CONTROLLER_ROW_LEN-2, attr, buf); +} + +static ssize_t show_battery_barcoding( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* type: string */ + return show_tp_ec_bat_str(7, 2, TP_CONTROLLER_ROW_LEN-2, attr, buf); +} + +static ssize_t show_battery_chemistry( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* type: string. SBS spec v1.1 p34-35: DeviceChemistry() */ + return show_tp_ec_bat_str(6, 2, 5, attr, buf); +} + +static ssize_t show_battery_voltage( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mV. SBS spec v1.1 p24: Voltage() */ + return show_tp_ec_bat_u16(1, 6, 1, NULL, attr, buf); +} + +static ssize_t show_battery_design_voltage( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mV. SBS spec v1.1 p32: DesignVoltage() */ + return show_tp_ec_bat_u16(3, 4, 1, NULL, attr, buf); +} + +static ssize_t show_battery_charging_max_voltage( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mV. SBS spec v1.1 p37,39: ChargingVoltage() */ + return show_tp_ec_bat_u16(9, 8, 1, NULL, attr, buf); +} + +static ssize_t show_battery_group0_voltage( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mV */ + return show_tp_ec_bat_u16(0xA, 12, 1, NULL, attr, buf); +} + +static ssize_t show_battery_group1_voltage( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mV */ + return show_tp_ec_bat_u16(0xA, 10, 1, NULL, attr, buf); +} + +static ssize_t show_battery_group2_voltage( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mV */ + return show_tp_ec_bat_u16(0xA, 8, 1, NULL, attr, buf); +} + +static ssize_t show_battery_group3_voltage( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mV */ + return show_tp_ec_bat_u16(0xA, 6, 1, NULL, attr, buf); +} + +static ssize_t show_battery_current_now( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mA. SBS spec v1.1 p24: Current() */ + return show_tp_ec_bat_s16(1, 8, 1, 0, attr, buf); +} + +static ssize_t show_battery_current_avg( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mA. SBS spec v1.1 p24: AverageCurrent() */ + return show_tp_ec_bat_s16(1, 10, 1, 0, attr, buf); +} + +static ssize_t show_battery_charging_max_current( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mA. SBS spec v1.1 p36,38: ChargingCurrent() */ + return show_tp_ec_bat_s16(9, 6, 1, 0, attr, buf); +} + +static ssize_t show_battery_power_now( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mW. SBS spec v1.1: Voltage()*Current() */ + return show_tp_ec_bat_power(1, 6, 8, attr, buf); +} + +static ssize_t show_battery_power_avg( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mW. SBS spec v1.1: Voltage()*AverageCurrent() */ + return show_tp_ec_bat_power(1, 6, 10, attr, buf); +} + +static ssize_t show_battery_remaining_percent( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: percent. SBS spec v1.1 p25: RelativeStateOfCharge() */ + return show_tp_ec_bat_u16(1, 12, 1, NULL, attr, buf); +} + +static ssize_t show_battery_remaining_charging_time( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: minutes. SBS spec v1.1 p27: AverageTimeToFull() */ + return show_tp_ec_bat_u16(2, 8, 1, "not_charging", attr, buf); +} + +static ssize_t show_battery_remaining_running_time( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: minutes. SBS spec v1.1 p27: RunTimeToEmpty() */ + return show_tp_ec_bat_u16(2, 6, 1, "not_discharging", attr, buf); +} + +static ssize_t show_battery_remaining_running_time_now( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: minutes. SBS spec v1.1 p27: RunTimeToEmpty() */ + return show_tp_ec_bat_u16(2, 4, 1, "not_discharging", attr, buf); +} + +static ssize_t show_battery_remaining_capacity( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mWh. SBS spec v1.1 p26. */ + return show_tp_ec_bat_u16(1, 14, 10, "", attr, buf); +} + +static ssize_t show_battery_last_full_capacity( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mWh. SBS spec v1.1 p26: FullChargeCapacity() */ + return show_tp_ec_bat_u16(2, 2, 10, "", attr, buf); +} + +static ssize_t show_battery_design_capacity( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: mWh. SBS spec v1.1 p32: DesignCapacity() */ + return show_tp_ec_bat_u16(3, 2, 10, "", attr, buf); +} + +static ssize_t show_battery_cycle_count( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: ordinal. SBS spec v1.1 p32: CycleCount() */ + return show_tp_ec_bat_u16(2, 12, 1, "", attr, buf); +} + +static ssize_t show_battery_temperature( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* units: millicelsius. SBS spec v1.1: Temperature()*10 */ + return show_tp_ec_bat_s16(1, 4, 100, -273100, attr, buf); +} + +static ssize_t show_battery_serial( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* type: int. SBS spec v1.1 p34: SerialNumber() */ + return show_tp_ec_bat_u16(3, 10, 1, "", attr, buf); +} + +static ssize_t show_battery_manufacture_date( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* type: YYYY-MM-DD. SBS spec v1.1 p34: ManufactureDate() */ + return show_tp_ec_bat_date(3, 8, attr, buf); +} + +static ssize_t show_battery_first_use_date( + struct device *dev, struct device_attribute *attr, char *buf) +{ + /* type: YYYY-MM-DD */ + return show_tp_ec_bat_date(8, 2, attr, buf); +} + +/** + * show_battery_dump - show the battery's dump attribute + * The dump attribute gives a hex dump of all EC readouts related to a + * battery. Some of the enumerated values don't really exist (i.e., the + * EC function just leaves them untouched); we use a kludge to detect and + * denote these. + */ +#define MIN_DUMP_ARG0 0x00 +#define MAX_DUMP_ARG0 0x0a /* 0x0b is useful too but hangs old EC firmware */ +static ssize_t show_battery_dump( + struct device *dev, struct device_attribute *attr, char *buf) +{ + int i; + char *p = buf; + int bat = attr_get_bat(attr); + u8 arg0; /* first argument to EC */ + u8 rowa[TP_CONTROLLER_ROW_LEN], + rowb[TP_CONTROLLER_ROW_LEN]; + const u8 junka = 0xAA, + junkb = 0x55; /* junk values for testing changes */ + int ret; + + for (arg0 = MIN_DUMP_ARG0; arg0 <= MAX_DUMP_ARG0; ++arg0) { + if ((p-buf) > PAGE_SIZE-TP_CONTROLLER_ROW_LEN*5) + return -ENOMEM; /* don't overflow sysfs buf */ + /* Read raw twice with different junk values, + * to detect unused output bytes which are left unchaged: */ + ret = read_tp_ec_row(arg0, bat, junka, rowa); + if (ret) + return ret; + ret = read_tp_ec_row(arg0, bat, junkb, rowb); + if (ret) + return ret; + for (i = 0; i < TP_CONTROLLER_ROW_LEN; i++) { + if (rowa[i] == junka && rowb[i] == junkb) + p += sprintf(p, "-- "); /* unused by EC */ + else + p += sprintf(p, "%02x ", rowa[i]); + } + p += sprintf(p, "\n"); + } + return p-buf; +} + + +/********************************************************************* + * sysfs attribute I/O, other than batteries + */ + +static ssize_t show_ac_connected( + struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = power_device_present(0xFF); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", ret); /* type: boolean */ +} + +/********************************************************************* + * The the "smapi_request" sysfs attribute executes a raw SMAPI call. + * You write to make a request and read to get the result. The state + * is saved globally rather than per fd (sysfs limitation), so + * simultaenous requests may get each other's results! So this is for + * development and debugging only. + */ +#define MAX_SMAPI_ATTR_ANSWER_LEN 128 +static char smapi_attr_answer[MAX_SMAPI_ATTR_ANSWER_LEN] = ""; + +static ssize_t show_smapi_request(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = snprintf(buf, PAGE_SIZE, "%s", smapi_attr_answer); + smapi_attr_answer[0] = '\0'; + return ret; +} + +static ssize_t store_smapi_request(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int inEBX, inECX, inEDI, inESI; + u32 outEBX, outECX, outEDX, outEDI, outESI; + const char *msg; + int ret; + if (sscanf(buf, "%x %x %x %x", &inEBX, &inECX, &inEDI, &inESI) != 4) { + smapi_attr_answer[0] = '\0'; + return -EINVAL; + } + ret = smapi_request( + inEBX, inECX, inEDI, inESI, + &outEBX, &outECX, &outEDX, &outEDI, &outESI, &msg); + snprintf(smapi_attr_answer, MAX_SMAPI_ATTR_ANSWER_LEN, + "%x %x %x %x %x %d '%s'\n", + (unsigned int)outEBX, (unsigned int)outECX, + (unsigned int)outEDX, (unsigned int)outEDI, + (unsigned int)outESI, ret, msg); + if (ret) + return ret; + else + return count; +} + +/********************************************************************* + * Power management: the embedded controller forgets the battery + * thresholds when the system is suspended to disk and unplugged from + * AC and battery, so we restore it upon resume. + */ + +static int saved_threshs[4] = {-1, -1, -1, -1}; /* -1 = don't know */ + +static int tp_suspend(struct platform_device *dev, pm_message_t state) +{ + if (get_real_thresh(0, THRESH_STOP , &saved_threshs[0])) + saved_threshs[0] = -1; + if (get_real_thresh(0, THRESH_START, &saved_threshs[1])) + saved_threshs[1] = -1; + if (get_real_thresh(1, THRESH_STOP , &saved_threshs[2])) + saved_threshs[2] = -1; + if (get_real_thresh(1, THRESH_START, &saved_threshs[3])) + saved_threshs[3] = -1; + DPRINTK("suspend saved: %d %d %d %d", saved_threshs[0], + saved_threshs[1], saved_threshs[2], saved_threshs[3]); + return 0; +} + +static int tp_resume(struct platform_device *dev) +{ + DPRINTK("resume restoring: %d %d %d %d", saved_threshs[0], + saved_threshs[1], saved_threshs[2], saved_threshs[3]); + if (saved_threshs[0] >= 0) + set_real_thresh(0, THRESH_STOP , saved_threshs[0]); + if (saved_threshs[1] >= 0) + set_real_thresh(0, THRESH_START, saved_threshs[1]); + if (saved_threshs[2] >= 0) + set_real_thresh(1, THRESH_STOP , saved_threshs[2]); + if (saved_threshs[3] >= 0) + set_real_thresh(1, THRESH_START, saved_threshs[3]); + return 0; +} + + +/********************************************************************* + * Driver model + */ + +static struct platform_driver tp_driver = { + .suspend = tp_suspend, + .resume = tp_resume, + .driver = { + .name = "smapi", + .owner = THIS_MODULE + }, +}; + + +/********************************************************************* + * Sysfs device model + */ + +/* Attributes in /sys/devices/platform/smapi/ */ + +static DEVICE_ATTR(ac_connected, 0444, show_ac_connected, NULL); +static DEVICE_ATTR(smapi_request, 0600, show_smapi_request, + store_smapi_request); + +static struct attribute *tp_root_attributes[] = { + &dev_attr_ac_connected.attr, + &dev_attr_smapi_request.attr, + NULL +}; +static struct attribute_group tp_root_attribute_group = { + .attrs = tp_root_attributes +}; + +/* Attributes under /sys/devices/platform/smapi/BAT{0,1}/ : + * Every attribute needs to be defined (i.e., statically allocated) for + * each battery, and then referenced in the attribute list of each battery. + * We use preprocessor voodoo to avoid duplicating the list of attributes 4 + * times. The preprocessor output is just normal sysfs attributes code. + */ + +/** + * FOREACH_BAT_ATTR - invoke the given macros on all our battery attributes + * @_BAT: battery number (0 or 1) + * @_ATTR_RW: macro to invoke for each read/write attribute + * @_ATTR_R: macro to invoke for each read-only attribute + */ +#define FOREACH_BAT_ATTR(_BAT, _ATTR_RW, _ATTR_R) \ + _ATTR_RW(_BAT, start_charge_thresh) \ + _ATTR_RW(_BAT, stop_charge_thresh) \ + _ATTR_RW(_BAT, inhibit_charge_minutes) \ + _ATTR_RW(_BAT, force_discharge) \ + _ATTR_R(_BAT, installed) \ + _ATTR_R(_BAT, state) \ + _ATTR_R(_BAT, manufacturer) \ + _ATTR_R(_BAT, model) \ + _ATTR_R(_BAT, barcoding) \ + _ATTR_R(_BAT, chemistry) \ + _ATTR_R(_BAT, voltage) \ + _ATTR_R(_BAT, group0_voltage) \ + _ATTR_R(_BAT, group1_voltage) \ + _ATTR_R(_BAT, group2_voltage) \ + _ATTR_R(_BAT, group3_voltage) \ + _ATTR_R(_BAT, current_now) \ + _ATTR_R(_BAT, current_avg) \ + _ATTR_R(_BAT, charging_max_current) \ + _ATTR_R(_BAT, power_now) \ + _ATTR_R(_BAT, power_avg) \ + _ATTR_R(_BAT, remaining_percent) \ + _ATTR_R(_BAT, remaining_charging_time) \ + _ATTR_R(_BAT, remaining_running_time) \ + _ATTR_R(_BAT, remaining_running_time_now) \ + _ATTR_R(_BAT, remaining_capacity) \ + _ATTR_R(_BAT, last_full_capacity) \ + _ATTR_R(_BAT, design_voltage) \ + _ATTR_R(_BAT, charging_max_voltage) \ + _ATTR_R(_BAT, design_capacity) \ + _ATTR_R(_BAT, cycle_count) \ + _ATTR_R(_BAT, temperature) \ + _ATTR_R(_BAT, serial) \ + _ATTR_R(_BAT, manufacture_date) \ + _ATTR_R(_BAT, first_use_date) \ + _ATTR_R(_BAT, dump) + +/* Define several macros we will feed into FOREACH_BAT_ATTR: */ + +#define DEFINE_BAT_ATTR_RW(_BAT,_NAME) \ + static struct bat_device_attribute dev_attr_##_NAME##_##_BAT = { \ + .dev_attr = __ATTR(_NAME, 0644, show_battery_##_NAME, \ + store_battery_##_NAME), \ + .bat = _BAT \ + }; + +#define DEFINE_BAT_ATTR_R(_BAT,_NAME) \ + static struct bat_device_attribute dev_attr_##_NAME##_##_BAT = { \ + .dev_attr = __ATTR(_NAME, 0644, show_battery_##_NAME, 0), \ + .bat = _BAT \ + }; + +#define REF_BAT_ATTR(_BAT,_NAME) \ + &dev_attr_##_NAME##_##_BAT.dev_attr.attr, + +/* This provide all attributes for one battery: */ + +#define PROVIDE_BAT_ATTRS(_BAT) \ + FOREACH_BAT_ATTR(_BAT, DEFINE_BAT_ATTR_RW, DEFINE_BAT_ATTR_R) \ + static struct attribute *tp_bat##_BAT##_attributes[] = { \ + FOREACH_BAT_ATTR(_BAT, REF_BAT_ATTR, REF_BAT_ATTR) \ + NULL \ + }; \ + static struct attribute_group tp_bat##_BAT##_attribute_group = { \ + .name = "BAT" #_BAT, \ + .attrs = tp_bat##_BAT##_attributes \ + }; + +/* Finally genereate the attributes: */ + +PROVIDE_BAT_ATTRS(0) +PROVIDE_BAT_ATTRS(1) + +/* List of attribute groups */ + +static struct attribute_group *attr_groups[] = { + &tp_root_attribute_group, + &tp_bat0_attribute_group, + &tp_bat1_attribute_group, + NULL +}; + + +/********************************************************************* + * Init and cleanup + */ + +static struct attribute_group **next_attr_group; /* next to register */ + +static int __init tp_init(void) +{ + int ret; + printk(KERN_INFO "tp_smapi " TP_VERSION " loading...\n"); + + ret = find_smapi_port(); + if (ret < 0) + goto err; + else + smapi_port = ret; + + if (!request_region(smapi_port, 1, "smapi")) { + printk(KERN_ERR "tp_smapi cannot claim port 0x%x\n", + smapi_port); + ret = -ENXIO; + goto err; + } + + if (!request_region(SMAPI_PORT2, 1, "smapi")) { + printk(KERN_ERR "tp_smapi cannot claim port 0x%x\n", + SMAPI_PORT2); + ret = -ENXIO; + goto err_port1; + } + + ret = platform_driver_register(&tp_driver); + if (ret) + goto err_port2; + + pdev = platform_device_alloc("smapi", -1); + if (!pdev) { + ret = -ENOMEM; + goto err_driver; + } + + ret = platform_device_add(pdev); + if (ret) + goto err_device_free; + + for (next_attr_group = attr_groups; *next_attr_group; + ++next_attr_group) { + ret = sysfs_create_group(&pdev->dev.kobj, *next_attr_group); + if (ret) + goto err_attr; + } + + printk(KERN_INFO "tp_smapi successfully loaded (smapi_port=0x%x).\n", + smapi_port); + return 0; + +err_attr: + while (--next_attr_group >= attr_groups) + sysfs_remove_group(&pdev->dev.kobj, *next_attr_group); + platform_device_unregister(pdev); +err_device_free: + platform_device_put(pdev); +err_driver: + platform_driver_unregister(&tp_driver); +err_port2: + release_region(SMAPI_PORT2, 1); +err_port1: + release_region(smapi_port, 1); +err: + printk(KERN_ERR "tp_smapi init failed (ret=%d)!\n", ret); + return ret; +} + +static void __exit tp_exit(void) +{ + while (next_attr_group && --next_attr_group >= attr_groups) + sysfs_remove_group(&pdev->dev.kobj, *next_attr_group); + platform_device_unregister(pdev); + platform_driver_unregister(&tp_driver); + release_region(SMAPI_PORT2, 1); + if (smapi_port) + release_region(smapi_port, 1); + + printk(KERN_INFO "tp_smapi unloaded.\n"); +} + +module_init(tp_init); +module_exit(tp_exit); --- linux-2.6.27.orig/ubuntu/misc/dm-bbr.c +++ linux-2.6.27/ubuntu/misc/dm-bbr.c @@ -0,0 +1,1012 @@ +/* + * (C) Copyright IBM Corp. 2002, 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * linux/drivers/md/dm-bbr.c + * + * Bad-block-relocation (BBR) target for device-mapper. + * + * The BBR target is designed to remap I/O write failures to another safe + * location on disk. Note that most disk drives have BBR built into them, + * this means that our software BBR will be only activated when all hardware + * BBR replacement sectors have been used. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm-bio-record.h" +#include "dm.h" +#include "dm-bbr.h" + +#define DM_MSG_PREFIX "bbr" +#define SECTOR_SIZE (1 << SECTOR_SHIFT) + +static struct workqueue_struct *dm_bbr_wq = NULL; +static void bbr_remap_handler(struct work_struct *work); +static struct kmem_cache *bbr_remap_cache; +static struct kmem_cache *bbr_io_cache; +static mempool_t *bbr_io_pool; + +/** + * bbr_binary_tree_destroy + * + * Destroy the binary tree. + **/ +static void bbr_binary_tree_destroy(struct bbr_runtime_remap *root) +{ + struct bbr_runtime_remap **link = NULL; + struct bbr_runtime_remap *node = root; + + while (node) { + if (node->left) { + link = &node->left; + node = node->left; + continue; + } + if (node->right) { + link = &node->right; + node = node->right; + continue; + } + + kmem_cache_free(bbr_remap_cache, node); + if (node == root) { + /* If root is deleted, we're done. */ + break; + } + + /* Back to root. */ + node = root; + *link = NULL; + } +} + +static void bbr_free_remap(struct bbr_private *bbr_id) +{ + spin_lock_irq(&bbr_id->remap_root_lock); + bbr_binary_tree_destroy(bbr_id->remap_root); + bbr_id->remap_root = NULL; + spin_unlock_irq(&bbr_id->remap_root_lock); +} + +static struct bbr_private *bbr_alloc_private(void) +{ + struct bbr_private *bbr_id; + + bbr_id = kzalloc(sizeof(*bbr_id), GFP_KERNEL); + if (bbr_id == NULL) + return NULL; + + INIT_WORK(&bbr_id->remap_work, bbr_remap_handler); + spin_lock_init(&bbr_id->remap_root_lock); + spin_lock_init(&bbr_id->remap_ios_lock); + bbr_id->in_use_replacement_blks = (atomic_t) ATOMIC_INIT(0); + + return bbr_id; +} + +static void bbr_free_private(struct bbr_private *bbr_id) +{ + vfree(bbr_id->bbr_table); + bbr_free_remap(bbr_id); + kfree(bbr_id); +} + +static u32 crc_table[256]; +static u32 crc_table_built = 0; + +static void build_crc_table(void) +{ + u32 i, j, crc; + + for (i = 0; i <= 255; i++) { + crc = i; + for (j = 8; j > 0; j--) { + if (crc & 1) + crc = (crc >> 1) ^ CRC_POLYNOMIAL; + else + crc >>= 1; + } + crc_table[i] = crc; + } + crc_table_built = 1; +} + +static u32 calculate_crc(u32 crc, void *buffer, u32 buffersize) +{ + unsigned char *current_byte; + u32 temp1, temp2, i; + + current_byte = (unsigned char *) buffer; + /* Make sure the crc table is available */ + if (!crc_table_built) + build_crc_table(); + /* Process each byte in the buffer. */ + for (i = 0; i < buffersize; i++) { + temp1 = (crc >> 8) & 0x00FFFFFF; + temp2 = crc_table[(crc ^ (u32) * current_byte) & + (u32) 0xff]; + current_byte++; + crc = temp1 ^ temp2; + } + return crc; +} + +/** + * le_bbr_table_sector_to_cpu + * + * Convert bbr meta data from on-disk (LE) format + * to the native cpu endian format. + **/ +static void le_bbr_table_sector_to_cpu(struct bbr_table *p) +{ + int i; + p->signature = le32_to_cpup(&p->signature); + p->crc = le32_to_cpup(&p->crc); + p->sequence_number = le32_to_cpup(&p->sequence_number); + p->in_use_cnt = le32_to_cpup(&p->in_use_cnt); + for (i = 0; i < BBR_ENTRIES_PER_SECT; i++) { + p->entries[i].bad_sect = + le64_to_cpup(&p->entries[i].bad_sect); + p->entries[i].replacement_sect = + le64_to_cpup(&p->entries[i].replacement_sect); + } +} + +/** + * cpu_bbr_table_sector_to_le + * + * Convert bbr meta data from cpu endian format to on-disk (LE) format + **/ +static void cpu_bbr_table_sector_to_le(struct bbr_table *p, + struct bbr_table *le) +{ + int i; + le->signature = cpu_to_le32p(&p->signature); + le->crc = cpu_to_le32p(&p->crc); + le->sequence_number = cpu_to_le32p(&p->sequence_number); + le->in_use_cnt = cpu_to_le32p(&p->in_use_cnt); + for (i = 0; i < BBR_ENTRIES_PER_SECT; i++) { + le->entries[i].bad_sect = + cpu_to_le64p(&p->entries[i].bad_sect); + le->entries[i].replacement_sect = + cpu_to_le64p(&p->entries[i].replacement_sect); + } +} + +/** + * validate_bbr_table_sector + * + * Check the specified BBR table sector for a valid signature and CRC. If it's + * valid, endian-convert the table sector. + **/ +static int validate_bbr_table_sector(struct bbr_table *p) +{ + int org_crc, final_crc; + + if (le32_to_cpup(&p->signature) != BBR_TABLE_SIGNATURE) { + DMERR("BBR table signature doesn't match!"); + DMERR("Found 0x%x. Expecting 0x%x", + le32_to_cpup(&p->signature), BBR_TABLE_SIGNATURE); + return -EINVAL; + } + + if (!p->crc) { + DMERR("BBR table sector has no CRC!"); + return -EINVAL; + } + + org_crc = le32_to_cpup(&p->crc); + p->crc = 0; + final_crc = calculate_crc(INITIAL_CRC, (void *)p, sizeof(*p)); + if (final_crc != org_crc) { + DMERR("CRC failed!"); + DMERR("Found 0x%x. Expecting 0x%x", + org_crc, final_crc); + return -EINVAL; + } + + p->crc = cpu_to_le32p(&org_crc); + le_bbr_table_sector_to_cpu(p); + + return 0; +} + +/** + * bbr_binary_tree_insert + * + * Insert a node into the binary tree. + **/ +static void bbr_binary_tree_insert(struct bbr_runtime_remap **root, + struct bbr_runtime_remap *newnode) +{ + struct bbr_runtime_remap **node = root; + while (node && *node) { + node = (newnode->remap.bad_sect > (*node)->remap.bad_sect) ? + &(*node)->right : &(*node)->left; + } + + newnode->left = newnode->right = NULL; + *node = newnode; +} + +/** + * bbr_binary_search + * + * Search for a node that contains bad_sect == lsn. + **/ +static struct bbr_runtime_remap *bbr_binary_search( + struct bbr_runtime_remap *root, + u64 lsn) +{ + struct bbr_runtime_remap *node = root; + while (node) { + if (node->remap.bad_sect == lsn) + break; + + node = (lsn > node->remap.bad_sect) ? node->right : node->left; + } + return node; +} + +/** + * bbr_insert_remap_entry + * + * Create a new remap entry and add it to the binary tree for this node. + **/ +static int bbr_insert_remap_entry(struct bbr_private *bbr_id, + struct bbr_table_entry *new_bbr_entry) +{ + struct bbr_runtime_remap *newnode; + + newnode = kmem_cache_alloc(bbr_remap_cache, GFP_NOIO); + if (!newnode) { + DMERR("Could not allocate from remap cache!"); + return -ENOMEM; + } + newnode->remap.bad_sect = new_bbr_entry->bad_sect; + newnode->remap.replacement_sect = new_bbr_entry->replacement_sect; + spin_lock_irq(&bbr_id->remap_root_lock); + bbr_binary_tree_insert(&bbr_id->remap_root, newnode); + spin_unlock_irq(&bbr_id->remap_root_lock); + return 0; +} + +/** + * bbr_table_to_remap_list + * + * The on-disk bbr table is sorted by the replacement sector LBA. In order to + * improve run time performance, the in memory remap list must be sorted by + * the bad sector LBA. This function is called at discovery time to initialize + * the remap list. This function assumes that at least one copy of meta data + * is valid. + **/ +static u32 bbr_table_to_remap_list(struct bbr_private *bbr_id) +{ + u32 in_use_blks = 0; + int i, j; + struct bbr_table *p; + + for (i = 0, p = bbr_id->bbr_table; + i < bbr_id->nr_sects_bbr_table; + i++, p++) { + if (!p->in_use_cnt) + break; + + in_use_blks += p->in_use_cnt; + for (j = 0; j < p->in_use_cnt; j++) + bbr_insert_remap_entry(bbr_id, &p->entries[j]); + } + if (in_use_blks) { + char b[32]; + DMWARN("There are %u BBR entries for device %s", + in_use_blks, format_dev_t(b, bbr_id->dev->bdev->bd_dev)); + } + + return in_use_blks; +} + +/** + * bbr_search_remap_entry + * + * Search remap entry for the specified sector. If found, return a pointer to + * the table entry. Otherwise, return NULL. + **/ +static struct bbr_table_entry *bbr_search_remap_entry( + struct bbr_private *bbr_id, + u64 lsn) +{ + struct bbr_runtime_remap *p; + + spin_lock_irq(&bbr_id->remap_root_lock); + p = bbr_binary_search(bbr_id->remap_root, lsn); + spin_unlock_irq(&bbr_id->remap_root_lock); + return (p) ? &p->remap : NULL; +} + +/** + * bbr_remap + * + * If *lsn is in the remap table, return TRUE and modify *lsn, + * else, return FALSE. + **/ +static int bbr_remap(struct bbr_private *bbr_id, + u64 *lsn) +{ + struct bbr_table_entry *e; + + if (atomic_read(&bbr_id->in_use_replacement_blks)) { + e = bbr_search_remap_entry(bbr_id, *lsn); + if (e) { + *lsn = e->replacement_sect; + return 1; + } + } + return 0; +} + +/** + * bbr_remap_probe + * + * If any of the sectors in the range [lsn, lsn+nr_sects] are in the remap + * table return TRUE, Else, return FALSE. + **/ +static int bbr_remap_probe(struct bbr_private *bbr_id, + u64 lsn, u64 nr_sects) +{ + u64 tmp, cnt; + + if (atomic_read(&bbr_id->in_use_replacement_blks)) { + for (cnt = 0, tmp = lsn; + cnt < nr_sects; + cnt += bbr_id->blksize_in_sects, tmp = lsn + cnt) { + if (bbr_remap(bbr_id,&tmp)) + return 1; + } + } + return 0; +} + +static int rw_table(struct bbr_private *bbr_id, void *vma, + struct dm_io_region *ptr, int rw) +{ + bbr_id->vma_io_req.bi_rw = rw; + bbr_id->vma_io_req.mem.ptr.vma = vma; + bbr_id->vma_io_req.notify.fn = NULL; + + return dm_io(&bbr_id->vma_io_req, 1, ptr, NULL); +} + +static int io_sync(struct bbr_private *bbr_id, struct page_list *pl, + unsigned offset, struct dm_io_region *ptr, int rw) +{ + bbr_id->page_io_req.bi_rw = rw; + bbr_id->page_io_req.mem.ptr.pl = pl; + bbr_id->page_io_req.mem.offset = offset; + bbr_id->page_io_req.notify.fn = NULL; + + return dm_io(&bbr_id->page_io_req, 1, ptr, NULL); +} + +/** + * bbr_setup + * + * Read the remap tables from disk and set up the initial remap tree. + **/ +static int bbr_setup(struct bbr_private *bbr_id) +{ + struct bbr_table *table = bbr_id->bbr_table; + struct dm_io_region job; + int i, rc = 0; + + job.bdev = bbr_id->dev->bdev; + job.count = 1; + + /* Read and verify each BBR table sector individually. */ + for (i = 0; i < bbr_id->nr_sects_bbr_table; i++, table++) { + job.sector = bbr_id->lba_table1 + i; + rc = rw_table(bbr_id, table, &job, READ); + if (rc && bbr_id->lba_table2) { + job.sector = bbr_id->lba_table2 + i; + rc = rw_table(bbr_id, table, &job, READ); + } + if (rc) { + goto out; + } + + rc = validate_bbr_table_sector(table); + if (rc) { + goto out; + } + } + atomic_set(&bbr_id->in_use_replacement_blks, + bbr_table_to_remap_list(bbr_id)); + +out: + if (rc) + DMERR("error during device setup: %d", rc); + return rc; +} + +/** + * bbr_io_remap_error + * @bbr_id: Private data for the BBR node. + * @rw: READ or WRITE. + * @starting_lsn: Starting sector of request to remap. + * @count: Number of sectors in the request. + * @page: Page containing the data for the request. + * @offset: Byte-offset of the data within the page. + * + * For the requested range, try to write each sector individually. For each + * sector that fails, find the next available remap location and write the + * data to that new location. Then update the table and write both copies + * of the table to disk. Finally, update the in-memory mapping and do any + * other necessary bookkeeping. + **/ +static int bbr_io_remap_error(struct bbr_private *bbr_id, + int rw, + u64 starting_lsn, + u64 count, + struct page *page, + unsigned int offset) +{ + struct bbr_table *bbr_table; + struct dm_io_region job; + struct page_list pl; + unsigned long table_sector_index; + unsigned long table_sector_offset; + unsigned long index; + u64 lsn, new_lsn; + char b[32]; + int rc; + + job.bdev = bbr_id->dev->bdev; + job.count = 1; + pl.page = page; + pl.next = NULL; + + /* For each sector in the request. */ + for (lsn = 0; lsn < count; lsn++, offset += SECTOR_SIZE) { + job.sector = starting_lsn + lsn; + rc = io_sync(bbr_id, &pl, offset, &job, rw); + while (rc) { + /* Find the next available relocation sector. */ + new_lsn = atomic_read(&bbr_id->in_use_replacement_blks); + if (new_lsn >= bbr_id->nr_replacement_blks) { + /* No more replacement sectors available. */ + return -EIO; + } + new_lsn += bbr_id->start_replacement_sect; + + /* Write the data to its new location. */ + DMWARN("device %s: Trying to remap bad sector "PFU64" to sector "PFU64, + format_dev_t(b, bbr_id->dev->bdev->bd_dev), + starting_lsn + lsn, new_lsn); + job.sector = new_lsn; + rc = io_sync(bbr_id, &pl, offset, &job, rw); + if (rc) { + /* This replacement sector is bad. + * Try the next one. + */ + DMERR("device %s: replacement sector "PFU64" is bad. Skipping.", + format_dev_t(b, bbr_id->dev->bdev->bd_dev), new_lsn); + atomic_inc(&bbr_id->in_use_replacement_blks); + continue; + } + + /* Add this new entry to the on-disk table. */ + table_sector_index = new_lsn - + bbr_id->start_replacement_sect; + table_sector_offset = table_sector_index / + BBR_ENTRIES_PER_SECT; + index = table_sector_index % BBR_ENTRIES_PER_SECT; + + bbr_table = &bbr_id->bbr_table[table_sector_offset]; + bbr_table->entries[index].bad_sect = starting_lsn + lsn; + bbr_table->entries[index].replacement_sect = new_lsn; + bbr_table->in_use_cnt++; + bbr_table->sequence_number++; + bbr_table->crc = 0; + bbr_table->crc = calculate_crc(INITIAL_CRC, + bbr_table, + sizeof(struct bbr_table)); + + /* Write the table to disk. */ + cpu_bbr_table_sector_to_le(bbr_table, bbr_table); + if (bbr_id->lba_table1) { + job.sector = bbr_id->lba_table1 + table_sector_offset; + rc = rw_table(bbr_id, bbr_table, &job, WRITE); + } + if (bbr_id->lba_table2) { + job.sector = bbr_id->lba_table2 + table_sector_offset; + rc |= rw_table(bbr_id, bbr_table, &job, WRITE); + } + le_bbr_table_sector_to_cpu(bbr_table); + + if (rc) { + /* Error writing one of the tables to disk. */ + DMERR("device %s: error updating BBR tables on disk.", + format_dev_t(b, bbr_id->dev->bdev->bd_dev)); + return rc; + } + + /* Insert a new entry in the remapping binary-tree. */ + rc = bbr_insert_remap_entry(bbr_id, + &bbr_table->entries[index]); + if (rc) { + DMERR("device %s: error adding new entry to remap tree.", + format_dev_t(b, bbr_id->dev->bdev->bd_dev)); + return rc; + } + + atomic_inc(&bbr_id->in_use_replacement_blks); + } + } + + return 0; +} + +/** + * bbr_io_process_request + * + * For each sector in this request, check if the sector has already + * been remapped. If so, process all previous sectors in the request, + * followed by the remapped sector. Then reset the starting lsn and + * count, and keep going with the rest of the request as if it were + * a whole new request. If any of the sync_io's return an error, + * call the remapper to relocate the bad sector(s). + * + * 2.5 Note: When switching over to bio's for the I/O path, we have made + * the assumption that the I/O request described by the bio is one + * virtually contiguous piece of memory (even though the bio vector + * describes it using a series of physical page addresses). + **/ +static int bbr_io_process_request(struct bbr_private *bbr_id, + struct bio *bio) +{ + struct dm_io_region job; + u64 starting_lsn = bio->bi_sector; + u64 count, lsn, remapped_lsn; + struct page_list pl; + unsigned int offset; + int i, rw = bio_data_dir(bio); + int rc = 0; + + job.bdev = bbr_id->dev->bdev; + pl.next = NULL; + + /* Each bio can contain multiple vectors, each with a different page. + * Treat each vector as a separate request. + */ + /* KMC: Is this the right way to walk the bvec list? */ + for (i = 0; + i < bio->bi_vcnt; + i++, bio->bi_idx++, starting_lsn += count) { + + /* Bvec info: number of sectors, page, + * and byte-offset within page. + */ + count = bio_iovec(bio)->bv_len >> SECTOR_SHIFT; + pl.page = bio_iovec(bio)->bv_page; + offset = bio_iovec(bio)->bv_offset; + + /* For each sector in this bvec, check if the sector has + * already been remapped. If so, process all previous sectors + * in this request, followed by the remapped sector. Then reset + * the starting lsn and count and keep going with the rest of + * the request as if it were a whole new request. + */ + for (lsn = 0; lsn < count; lsn++) { + remapped_lsn = starting_lsn + lsn; + rc = bbr_remap(bbr_id, &remapped_lsn); + if (!rc) { + /* This sector is fine. */ + continue; + } + + /* Process all sectors in the request up to this one. */ + if (lsn > 0) { + job.sector = starting_lsn; + job.count = lsn; + rc = io_sync(bbr_id, &pl, offset, &job, rw); + if (rc) { + /* If this I/O failed, then one of the + * sectors in this request needs to be + * relocated. + */ + rc = bbr_io_remap_error(bbr_id, rw, + starting_lsn, + lsn, pl.page, + offset); + if (rc) { + /* KMC: Return? Or continue to next bvec? */ + return rc; + } + } + offset += (lsn << SECTOR_SHIFT); + } + + /* Process the remapped sector. */ + job.sector = remapped_lsn; + job.count = 1; + rc = io_sync(bbr_id, &pl, offset, &job, rw); + if (rc) { + /* BUGBUG - Need more processing if this caused + * an error. If this I/O failed, then the + * existing remap is now bad, and we need to + * find a new remap. Can't use + * bbr_io_remap_error(), because the existing + * map entry needs to be changed, not added + * again, and the original table entry also + * needs to be changed. + */ + return rc; + } + + starting_lsn += (lsn + 1); + count -= (lsn + 1); + lsn = -1; + offset += SECTOR_SIZE; + } + + /* Check for any remaining sectors after the last split. This + * could potentially be the whole request, but that should be a + * rare case because requests should only be processed by the + * thread if we know an error occurred or they contained one or + * more remapped sectors. + */ + if (count) { + job.sector = starting_lsn; + job.count = count; + rc = io_sync(bbr_id, &pl, offset, &job, rw); + if (rc) { + /* If this I/O failed, then one of the sectors + * in this request needs to be relocated. + */ + rc = bbr_io_remap_error(bbr_id, rw, starting_lsn, + count, pl.page, offset); + if (rc) { + /* KMC: Return? Or continue to next bvec? */ + return rc; + } + } + } + } + + return 0; +} + +static void bbr_io_process_requests(struct bbr_private *bbr_id, + struct bio *bio) +{ + struct bio *next; + int rc; + + while (bio) { + next = bio->bi_next; + bio->bi_next = NULL; + + rc = bbr_io_process_request(bbr_id, bio); + + bio_endio(bio, rc); + + bio = next; + } +} + +/** + * bbr_remap_handler + * + * This is the handler for the bbr work-queue. + * + * I/O requests should only be sent to this handler if we know that: + * a) the request contains at least one remapped sector. + * or + * b) the request caused an error on the normal I/O path. + * + * This function uses synchronous I/O, so sending a request to this + * thread that doesn't need special processing will cause severe + * performance degredation. + **/ +static void bbr_remap_handler(struct work_struct *work) +{ + struct bbr_private *bbr_id = + container_of(work, struct bbr_private, remap_work); + struct bio *bio; + unsigned long flags; + + spin_lock_irqsave(&bbr_id->remap_ios_lock, flags); + bio = bio_list_get(&bbr_id->remap_ios); + spin_unlock_irqrestore(&bbr_id->remap_ios_lock, flags); + + bbr_io_process_requests(bbr_id, bio); +} + +/** + * bbr_endio + * + * This is the callback for normal write requests. Check for an error + * during the I/O, and send to the thread for processing if necessary. + **/ +static int bbr_endio(struct dm_target *ti, struct bio *bio, + int error, union map_info *map_context) +{ + struct bbr_private *bbr_id = ti->private; + struct dm_bio_details *bbr_io = map_context->ptr; + + if (error && bbr_io) { + unsigned long flags; + char b[32]; + + dm_bio_restore(bbr_io, bio); + map_context->ptr = NULL; + + DMERR("device %s: I/O failure on sector %lu. " + "Scheduling for retry.", + format_dev_t(b, bbr_id->dev->bdev->bd_dev), + (unsigned long)bio->bi_sector); + + spin_lock_irqsave(&bbr_id->remap_ios_lock, flags); + bio_list_add(&bbr_id->remap_ios, bio); + spin_unlock_irqrestore(&bbr_id->remap_ios_lock, flags); + + queue_work(dm_bbr_wq, &bbr_id->remap_work); + + error = 1; + } + + if (bbr_io) + mempool_free(bbr_io, bbr_io_pool); + + return error; +} + +/** + * Construct a bbr mapping + **/ +static int bbr_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + struct bbr_private *bbr_id; + unsigned long block_size; + char *end; + int rc = -EINVAL; + + if (argc != 8) { + ti->error = "dm-bbr requires exactly 8 arguments: " + "device offset table1_lsn table2_lsn table_size start_replacement nr_replacement_blks block_size"; + goto out1; + } + + bbr_id = bbr_alloc_private(); + if (!bbr_id) { + ti->error = "dm-bbr: Error allocating bbr private data."; + goto out1; + } + + bbr_id->offset = simple_strtoull(argv[1], &end, 10); + bbr_id->lba_table1 = simple_strtoull(argv[2], &end, 10); + bbr_id->lba_table2 = simple_strtoull(argv[3], &end, 10); + bbr_id->nr_sects_bbr_table = simple_strtoull(argv[4], &end, 10); + bbr_id->start_replacement_sect = simple_strtoull(argv[5], &end, 10); + bbr_id->nr_replacement_blks = simple_strtoull(argv[6], &end, 10); + block_size = simple_strtoul(argv[7], &end, 10); + bbr_id->blksize_in_sects = (block_size >> SECTOR_SHIFT); + + bbr_id->vma_io_req.mem.type = DM_IO_VMA; + bbr_id->vma_io_req.client = dm_io_client_create(1); + if (IS_ERR(bbr_id->vma_io_req.client)) { + rc = PTR_ERR(bbr_id->vma_io_req.client); + DMWARN("couldn't allocate disk VMA io client"); + goto out2; + } + + bbr_id->page_io_req.mem.type = DM_IO_PAGE_LIST; + bbr_id->page_io_req.client = dm_io_client_create(1); + if (IS_ERR(bbr_id->page_io_req.client)) { + rc = PTR_ERR(bbr_id->page_io_req.client); + DMWARN("couldn't allocate pagelist io client"); + goto out3; + } + + bbr_id->bbr_table = vmalloc(bbr_id->nr_sects_bbr_table << SECTOR_SHIFT); + if (!bbr_id->bbr_table) { + ti->error = "dm-bbr: Error allocating bbr table."; + goto out4; + } + + if (dm_get_device(ti, argv[0], 0, ti->len, + dm_table_get_mode(ti->table), &bbr_id->dev)) { + ti->error = "dm-bbr: Device lookup failed"; + goto out4; + } + + rc = bbr_setup(bbr_id); + if (rc) { + ti->error = "dm-bbr: Device setup failed"; + goto out5; + } + + ti->private = bbr_id; + return 0; + +out5: + dm_put_device(ti, bbr_id->dev); +out4: + dm_io_client_destroy(bbr_id->page_io_req.client); +out3: + dm_io_client_destroy(bbr_id->vma_io_req.client); +out2: + bbr_free_private(bbr_id); +out1: + return rc; +} + +static void bbr_dtr(struct dm_target *ti) +{ + struct bbr_private *bbr_id = ti->private; + + dm_put_device(ti, bbr_id->dev); + dm_io_client_destroy(bbr_id->page_io_req.client); + dm_io_client_destroy(bbr_id->vma_io_req.client); + bbr_free_private(bbr_id); +} + +static int bbr_map(struct dm_target *ti, struct bio *bio, + union map_info *map_context) +{ + struct bbr_private *bbr_id = ti->private; + struct dm_bio_details *bbr_io; + unsigned long flags; + int rc = 1; + + bio->bi_sector += bbr_id->offset; + + if (atomic_read(&bbr_id->in_use_replacement_blks) == 0 || + !bbr_remap_probe(bbr_id, bio->bi_sector, bio_sectors(bio))) { + /* No existing remaps or this request doesn't + * contain any remapped sectors. + */ + bio->bi_bdev = bbr_id->dev->bdev; + + bbr_io = mempool_alloc(bbr_io_pool, GFP_NOIO); + dm_bio_record(bbr_io, bio); + map_context->ptr = bbr_io; + } else { + /* This request has at least one remapped sector. + * Give it to the work-queue for processing. + */ + map_context->ptr = NULL; + spin_lock_irqsave(&bbr_id->remap_ios_lock, flags); + bio_list_add(&bbr_id->remap_ios, bio); + spin_unlock_irqrestore(&bbr_id->remap_ios_lock, flags); + + queue_work(dm_bbr_wq, &bbr_id->remap_work); + rc = 0; + } + + return rc; +} + +static int bbr_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) +{ + struct bbr_private *bbr_id = ti->private; + char b[BDEVNAME_SIZE]; + + switch (type) { + case STATUSTYPE_INFO: + result[0] = '\0'; + break; + + case STATUSTYPE_TABLE: + snprintf(result, maxlen, "%s "PFU64" "PFU64" "PFU64" "PFU64" "PFU64" "PFU64" %u", + format_dev_t(b, bbr_id->dev->bdev->bd_dev), + bbr_id->offset, bbr_id->lba_table1, bbr_id->lba_table2, + bbr_id->nr_sects_bbr_table, + bbr_id->start_replacement_sect, + bbr_id->nr_replacement_blks, + bbr_id->blksize_in_sects << SECTOR_SHIFT); + break; + } + return 0; +} + +static struct target_type bbr_target = { + .name = "bbr", + .version= {1, 0, 1}, + .module = THIS_MODULE, + .ctr = bbr_ctr, + .dtr = bbr_dtr, + .map = bbr_map, + .end_io = bbr_endio, + .status = bbr_status, +}; + +int __init dm_bbr_init(void) +{ + int rc; + + rc = dm_register_target(&bbr_target); + if (rc) { + DMERR("error registering target."); + goto err1; + } + + bbr_remap_cache = kmem_cache_create("bbr-remap", + sizeof(struct bbr_runtime_remap), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (!bbr_remap_cache) { + DMERR("error creating remap cache."); + rc = ENOMEM; + goto err2; + } + + bbr_io_cache = kmem_cache_create("bbr-io", sizeof(struct dm_bio_details), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (!bbr_io_cache) { + DMERR("error creating io cache."); + rc = ENOMEM; + goto err3; + } + + bbr_io_pool = mempool_create(256, mempool_alloc_slab, + mempool_free_slab, bbr_io_cache); + if (!bbr_io_pool) { + DMERR("error creating io mempool."); + rc = ENOMEM; + goto err4; + } + + dm_bbr_wq = create_workqueue("dm-bbr"); + if (!dm_bbr_wq) { + DMERR("error creating work-queue."); + rc = ENOMEM; + goto err5; + } + + return 0; + +err5: + mempool_destroy(bbr_io_pool); +err4: + kmem_cache_destroy(bbr_io_cache); +err3: + kmem_cache_destroy(bbr_remap_cache); +err2: + dm_unregister_target(&bbr_target); +err1: + return rc; +} + +void __exit dm_bbr_exit(void) +{ + destroy_workqueue(dm_bbr_wq); + mempool_destroy(bbr_io_pool); + kmem_cache_destroy(bbr_io_cache); + kmem_cache_destroy(bbr_remap_cache); + dm_unregister_target(&bbr_target); +} + +module_init(dm_bbr_init); +module_exit(dm_bbr_exit); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/misc/thinkpad_ec.h +++ linux-2.6.27/ubuntu/misc/thinkpad_ec.h @@ -0,0 +1,47 @@ +/* + * thinkpad_ec.h - interface to ThinkPad embedded controller LPC3 functions + * + * Copyright (C) 2005 Shem Multinymous + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _THINKPAD_EC_H +#define _THINKPAD_EC_H + +#ifdef __KERNEL__ + +#define TP_CONTROLLER_ROW_LEN 16 + +/* EC transactions input and output (possibly partial) vectors of 16 bytes. */ +struct thinkpad_ec_row { + u16 mask; /* bitmap of which entries of val[] are meaningful */ + u8 val[TP_CONTROLLER_ROW_LEN]; +}; + +extern int __must_check thinkpad_ec_lock(void); +extern int __must_check thinkpad_ec_try_lock(void); +extern void thinkpad_ec_unlock(void); + +extern int thinkpad_ec_read_row(const struct thinkpad_ec_row *args, + struct thinkpad_ec_row *data); +extern int thinkpad_ec_try_read_row(const struct thinkpad_ec_row *args, + struct thinkpad_ec_row *mask); +extern int thinkpad_ec_prefetch_row(const struct thinkpad_ec_row *args); +extern void thinkpad_ec_invalidate(void); + + +#endif /* __KERNEL */ +#endif /* _THINKPAD_EC_H */ --- linux-2.6.27.orig/ubuntu/misc/acerhk.c +++ linux-2.6.27/ubuntu/misc/acerhk.c @@ -0,0 +1,3001 @@ +/********************************************************************* + * Filename: acerhk.c + * Version: 0.5 + * + * Copyright (C) 2002-2006, Olaf Tauber (olaf-tauber@versanet.de) + * + * Description: kernel driver for Acer Travelmate and similar + * laptops special keys + * Author: Olaf Tauber + * Created at: Mon Apr 29 22:16:42 2002 + * Modified at: Tue Feb 28 21:38:41 2006 + * Modified by: Olaf Tauber + * Modified at: Thu Nov 24 13:03:01 2005 + * Modified by: Antonio Cuni + * Modified at: Wed Oct 27 19:47:11 CEST 2004 + * Modified by: Joachim Fenkes + * + * This program is free software; you can redistribute + * it and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * + * + */ + +/* This driver is heavily dependent on the architecture, don't let anyone + * without an X86 machine use it. I doubt that there are laptops out there + * which would need this driver and are not X86, so it doesn't matter anyway. + */ +#ifdef CONFIG_X86 + +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#define KERNEL26 +#include +#else +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +#define STATIC_INPUT_DEV +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acerhk.h" + +/* #define ACERDEBUG */ +/* #define DUMMYHW */ + +#define ACERHK_VERSION "0.5.34" +#define MODULE_NAME "acerhk" + +/* maximum number of polling loops, adjust it if needed to values between + * 1 and 32 + */ +#define MAX_POLLING_LOOPS 16U + +/* maximum length for model string */ +#define ACERHK_MODEL_STRLEN 16 +/* size of mapped areas */ +#define AREA_SIZE 0xffff +/* needed for colussi algorithm */ +#define XSIZE 20 + +/* Module parameters */ +static int poll=1; +static int autowlan; +static int usedritek=1; +static int wlan_state=-1; +static int bluetooth_state=-1; +static int verbose; +static unsigned int force_series; +#ifdef KERNEL26 +module_param(poll, int, 0444); +module_param(autowlan, int, 0444); +module_param(usedritek, int, 0444); +module_param(verbose, int, 0444); +module_param(wlan_state, int, 0444); +module_param(bluetooth_state, int, 0444); +module_param(force_series, uint, 0444); +#else +MODULE_PARM(poll, "i"); +MODULE_PARM(autowlan, "i"); +MODULE_PARM(wlan_state, "i"); +MODULE_PARM(bluetooth_state, "i"); +MODULE_PARM(usedritek, "i"); +MODULE_PARM(verbose, "i"); +MODULE_PARM(force_series, "i"); +#endif +MODULE_PARM_DESC(poll, "start polling timer"); +MODULE_PARM_DESC(autowlan, "automatic switching of wlan hardware"); +MODULE_PARM_DESC(wlan_state, "(assumed) initial state of WLAN LED/hardware"); +MODULE_PARM_DESC(bluetooth_state, "(assumed) initial state of Bluetooth LED/hardware"); +MODULE_PARM_DESC(usedritek, "enable dritek keyboard extension"); +MODULE_PARM_DESC(verbose, "output additional information"); +MODULE_PARM_DESC(force_series, "force laptop series, skip autodetection"); + +/* input device */ +static struct input_dev *acerhk_input_dev_ptr; +#ifdef STATIC_INPUT_DEV +static struct input_dev acerhk_input_dev; +#endif + +/* mapped IO area from 0xf0000 */ +static void *reg1; +/* mapped IO area from 0xe0000 */ +static void *reg2; +/* Pointer to mapped area at 0x400 on 520 series */ +static void *preg400; +/* location of IO routine in mapped area */ +static unsigned int bios_routine; +/* index of CMOS port to get key event */ +static unsigned int cmos_index; +/* function for bios call */ +static bios_call call_bios; +/* address of model string */ +static char *acerhk_model_addr; +/* copied string, maximum length 16 ('TravelMate xxx') */ +static char acerhk_model_string[ACERHK_MODEL_STRLEN]; +/* type of hardware access */ +static t_acer_type acerhk_type; +/* travelmate series */ +static unsigned int acerhk_series; +/* supported features for this model */ +static unsigned int acerhk_model_features; +/* map of acer key codes to acer key names */ +static unsigned char acerhk_key2name[0xff]; +/* map of acer key names to key events */ +static t_map_name2event acerhk_name2event; +/* timer for polling key presses */ +static struct timer_list acerhk_timer_poll; +/* polling active */ +static int acerhk_polling_state; +/* polling delay */ +static unsigned acerhk_polling_delay = HZ/5; +/* wlan hardware toggle */ +static int acerhk_wlan_state; +/* bluetooth hardware toggle */ +static int acerhk_bluetooth_state; + +/* bluetooth blinking state; added by Antonio Cuni + possible values: + -1: blinking disabled (default) + 0: blinking enabled, led currently off + 1: blinking enabled, led currently on +*/ +static int acerhk_blueled_blinking = -1; +/* delay between two changes of state, in jiffies */ +static unsigned acerhk_blueled_blinking_delay; +/* timer for blinking */ +static struct timer_list acerhk_timer_blinking; + +/* function prototypes */ +static void start_polling(void); +static void stop_polling(void); + +/* Added by Antonio Cuni */ +static void start_blinking(void); +static void stop_blinking(void); + +/* {{{ Experimental use of dritek keyboard extension */ + +#define EC_STATUS_REG 0x66 /* Status register of EC (R) */ +#define EC_CNTL_REG 0x66 /* Controller command register of EC (W) */ +#define EC_DATA_REG 0x62 /* EC data register (R/W) */ + +#ifdef KERNEL26 + +#include + +#define KBD_STATUS_REG 0x64 /* Status register (R) */ +#define KBD_CNTL_REG 0x64 /* Controller command register (W) */ +#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */ + +#else + +#ifndef KEY_MEDIA +#define KEY_MEDIA 226 +#endif + +#define preempt_disable() do { } while (0) +#define preempt_enable_no_resched() do { } while (0) +#define preempt_enable() do { } while (0) +#define preempt_check_resched() do { } while (0) +#include + +#endif + +static inline int my_i8042_read_status(void) +{ + return inb(KBD_STATUS_REG); +} +static int my_i8042_wait_write(void) +{ + int i = 0; + while ((my_i8042_read_status() & 0x02) && (i < 10000)) { + udelay(50); + i++; + } + return -(i == 10000); +} +static void send_kbd_cmd(unsigned char cmd, unsigned char val) +{ + if (usedritek) { + preempt_disable(); + if (!my_i8042_wait_write()) + outb(cmd, KBD_CNTL_REG); + if (!my_i8042_wait_write()) + outb(val, KBD_DATA_REG); + preempt_enable_no_resched(); + } else { + printk(KERN_INFO"acerhk: request for accessing EC ignored\n" + KERN_INFO"acerhk: Use of dritek keyboard extension not enabled, use module\n" + KERN_INFO"acerhk: parameter usedritek=1 to do that (possibly dangerous)\n"); + } +} +#ifdef ACERDEBUG +static inline int my_i8042_read_ecstatus(void) +{ + return inb(EC_STATUS_REG); +} +static int my_i8042_wait_ecwrite(void) +{ + int i = 0; + while ((my_i8042_read_ecstatus() & 0x02) && (i < 10000)) { + udelay(50); + i++; + } + return -(i == 10000); +} +static void send_ec_cmd(unsigned char cmd, unsigned char val) +{ + if (usedritek) { + preempt_disable(); + if (!my_i8042_wait_ecwrite()) + outb(cmd, EC_CNTL_REG); + if (!my_i8042_wait_ecwrite()) + outb(val, EC_DATA_REG); + preempt_enable_no_resched(); + } else { + printk(KERN_INFO"acerhk: request for accessing EC ignored\n" + KERN_INFO"acerhk: Use of dritek keyboard extension not enabled, use module\n" + KERN_INFO"acerhk: parameter usedritek=1 to do that (possibly dangerous)\n"); + } +} +#endif +#ifdef ACERDEBUG +static void enable_mute_led_ec(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling mute led via EC\n"); + send_kbd_cmd(0x59, 0x94); +} +static void disable_mute_led_ec(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling mute led via EC\n"); + send_kbd_cmd(0x59, 0x95); +} +static void enable_dmm_function(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling WLAN via EC variant 2\n"); + send_kbd_cmd(0x45, 0xd3); +} +#endif +static void enable_wlan_ec_1(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling WLAN via EC variant 1\n"); + send_kbd_cmd(0xe7, 0x01); + acerhk_wlan_state = 1; +} +static void disable_wlan_ec_1(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling WLAN via EC variant 1\n"); + send_kbd_cmd(0xe7, 0x00); + acerhk_wlan_state = 0; +} +static void enable_bluetooth_ec_1(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling Bluetooth via EC variant 1\n"); + send_kbd_cmd(0xe7, 0x03); + acerhk_bluetooth_state = 1; +} +static void disable_bluetooth_ec_1(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling Bluetooth via EC variant 1\n"); + send_kbd_cmd(0xe7, 0x02); + acerhk_bluetooth_state = 0; +} +static void enable_wlan_ec_2(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling WLAN via EC variant 2\n"); + send_kbd_cmd(0x45, acerhk_bluetooth_state ? 0xa2 : 0xa0); + acerhk_wlan_state = 1; +} +static void disable_wlan_ec_2(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling WLAN via EC variant 2\n"); + send_kbd_cmd(0x45, acerhk_bluetooth_state ? 0xa1 : 0xa3); + acerhk_wlan_state = 0; +} +static void enable_bluetooth_ec_2(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling Bluetooth via EC variant 2\n"); + send_kbd_cmd(0x45, acerhk_wlan_state ? 0xa2 : 0xa1); + acerhk_bluetooth_state = 1; +} +static void disable_bluetooth_ec_2(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling Bluetooth via EC variant 2\n"); + send_kbd_cmd(0x45, acerhk_wlan_state ? 0xa0 : 0xa3); + acerhk_bluetooth_state = 0; +} +#ifdef ACERDEBUG +static void enable_wireless_ec(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling wireless hardware\n"); + if (usedritek) { + preempt_disable(); + if (!my_i8042_wait_ecwrite()) + outb(0x4d, EC_CNTL_REG); + if (!my_i8042_wait_ecwrite()) + outb(0xd2, EC_DATA_REG); + if (!my_i8042_wait_ecwrite()) + outb(0x01, EC_DATA_REG); + preempt_enable_no_resched(); + } + acerhk_wlan_state = 1; +} +static void disable_wireless_ec(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling wireless hardware\n"); + if (usedritek) { + preempt_disable(); + if (!my_i8042_wait_ecwrite()) + outb(0x4d, EC_CNTL_REG); + if (!my_i8042_wait_ecwrite()) + outb(0xd2, EC_DATA_REG); + if (!my_i8042_wait_ecwrite()) + outb(0x00, EC_DATA_REG); + preempt_enable_no_resched(); + } + acerhk_wlan_state = 0; +} +#endif +static void enable_dritek_keyboard(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling dritek keyboard extension\n"); + send_kbd_cmd(0x59, 0x90); +} +static void disable_dritek_keyboard(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling dritek keyboard extension\n"); + send_kbd_cmd(0x59, 0x91); +} +static void enable_mail_led_ec_1(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling mail led via EC variant 1\n"); + send_kbd_cmd(0xe8, 0x01); +} +static void disable_mail_led_ec_1(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling mail led via EC variant 1\n"); + send_kbd_cmd(0xe8, 0x00); +} + +static void enable_mail_led_ec_2(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling mail led via EC variant 2\n"); + send_kbd_cmd(0x59, 0x92); +} +static void disable_mail_led_ec_2(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling mail led via EC variant 2\n"); + send_kbd_cmd(0x59, 0x93); +} +static void enable_mail_led_ec_3(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: enabling mail led via EC variant 3\n"); + if (usedritek) { + preempt_disable(); + if (!my_i8042_wait_write()) + outl(0x80008894, 0xCF8); + if (!my_i8042_wait_write()) + outw(0xC061, 0xCFC); + preempt_enable_no_resched(); + } +} +static void disable_mail_led_ec_3(void) +{ + if (verbose) + printk(KERN_INFO "acerhk: disabling mail led via EC variant 3\n"); + if (usedritek) { + preempt_disable(); + if (!my_i8042_wait_write()) + outl(0x80008894, 0xCF8); + if (!my_i8042_wait_write()) + outw(0xC060, 0xCFC); + preempt_enable_no_resched(); + } +} + +/* }}} */ + +/* {{{ string search functions */ + +/* This is the Colussi algorithm, the code is taken from + http://www-igm.univ-mlv.fr/~lecroq/string +*/ +int preColussi(char *x, int m, int *h, int *next, int *shift) +{ + int i, k, nd, q, r, s; + int hmax[XSIZE], kmin[XSIZE], nhd0[XSIZE], rmin[XSIZE]; + /* Computation of hmax */ + i = k = 1; + do { + while (x[i] == x[i - k]) + i++; + hmax[k] = i; + q = k + 1; + while (hmax[q - k] + k < i) { + hmax[q] = hmax[q - k] + k; + q++; + } + k = q; + if (k == i + 1) + i = k; + } while (k <= m); /* Computation of kmin */ + memset(kmin, 0, m*sizeof(int)); + r = 0; + for (i = m; i >= 1; --i) + if (hmax[i] < m) + kmin[hmax[i]] = i; /* Computation of rmin */ + for (i = m - 1; i >= 0; --i) { + if (hmax[i + 1] == m) + r = i + 1; + if (kmin[i] == 0) + rmin[i] = r; + else + rmin[i] = 0; + } /* Computation of h */ + s = -1; + r = m; + for (i = 0; i < m; ++i) + if (kmin[i] == 0) + h[--r] = i; + else + h[++s] = i; + nd = s; /* Computation of shift */ + for (i = 0; i <= nd; ++i) + shift[i] = kmin[h[i]]; + for (i = nd + 1; i < m; ++i) + shift[i] = rmin[h[i]]; + shift[m] = rmin[0]; /* Computation of nhd0 */ + s = 0; + for (i = 0; i < m; ++i) { + nhd0[i] = s; + if (kmin[i] > 0) + ++s; + } /* Computation of next */ + for (i = 0; i <= nd; ++i) + next[i] = nhd0[h[i] - kmin[h[i]]]; + for (i = nd + 1; i < m; ++i) + next[i] = nhd0[m - rmin[h[i]]]; + next[m] = nhd0[m - rmin[h[m - 1]]]; return(nd); +} + +int COLUSSI(char *x, int m, char *y, int n) { + int i, j, last, nd, + h[XSIZE], next[XSIZE], shift[XSIZE]; /* Processing */ + int match_pos; /* position of first match */ + nd = preColussi(x, m, h, next, shift); /* Searching */ + i = j = 0; + last = -1; + match_pos = -1; + while ( (match_pos == -1) + && (j <= n - m) ) { + while (i < m && last < j + h[i] && + x[h[i]] == y[j + h[i]]) + i++; + if (i >= m || last >= j + h[i]) { + /* Match found, bail out */ + match_pos = j; + i = m; + } + if (i > nd) + last = j + m - 1; + j += shift[i]; + i = next[i]; + } + return match_pos; +} + +/* }}} */ + +/* {{{ hardware access functions */ + +/* call_bios_ + * + * call request handler in mapped system rom + * + * the request is handed over via all 6 general purpose registers, results are + * taken from them and copied back to buf + */ +static asmlinkage void call_bios_6xx(struct register_buffer *buf) +{ + if (bios_routine) { + local_irq_disable(); + __asm__ __volatile__( + "movl %1,%%edx\n\t" + "pusha\n\t" + "movl %%edx,%%ebp\n\t" + "movl (%%ebp),%%eax\n\t" + "movl 4(%%ebp),%%ebx\n\t" + "movl 8(%%ebp),%%ecx\n\t" + "movl 12(%%ebp),%%edx\n\t" + "movl 16(%%ebp),%%edi\n\t" + "movl 20(%%ebp),%%esi\n\t" + "pushl %%ebp\n\t" + "call *%0\n\t" + "popl %%ebp\n\t" + "movl %%eax, (%%ebp)\n\t" + "movl %%ebx, 4(%%ebp)\n\t" + "movl %%ecx, 8(%%ebp)\n\t" + "movl %%edx, 12(%%ebp)\n\t" + "movl %%edi, 16(%%ebp)\n\t" + "movl %%esi, 20(%%ebp)\n\t" + "popa\n\t" + : + :"m" (bios_routine), "m" (buf) + :"%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi"//, "%ebp" + ); + local_irq_enable(); + } +} + +static asmlinkage void call_bios_52x(struct register_buffer *buf) +{ + if (bios_routine) { + local_irq_disable(); + __asm__ __volatile__( + "movl %2,%%edx\n\t" + "pusha\n\t" + "movl %%edx,%%ebp\n\t" + "movl (%%ebp),%%eax\n\t" + "movl 4(%%ebp),%%ebx\n\t" + "movl 8(%%ebp),%%ecx\n\t" + "movl 12(%%ebp),%%edx\n\t" + "movl 16(%%ebp),%%edi\n\t" + "movl 20(%%ebp),%%esi\n\t" + "pushl %%ebp\n\t" + "movl %1, %%ebp\n\t" + "call *%0\n\t" + "popl %%ebp\n\t" + "movl %%eax, (%%ebp)\n\t" + "movl %%ebx, 4(%%ebp)\n\t" + "movl %%ecx, 8(%%ebp)\n\t" + "movl %%edx, 12(%%ebp)\n\t" + "movl %%edi, 16(%%ebp)\n\t" + "movl %%esi, 20(%%ebp)\n\t" + "popa\n\t" + : + :"m" (bios_routine), "m" (preg400), "m" (buf) + :"%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi"//, "%ebp" + ); + local_irq_enable(); + } +} + +#define PRINT_BUFFER(x) \ + printk(KERN_INFO"acerhk: eax=0x%x ebx=0x%x ecx=0x%x edx=0x%x\n" \ + "acerhk: edi=0x%x esi=0x%x ebp=0x%x\n", \ + x.eax, x.ebx, x.ecx, x.edx, x.edi, x.esi, x.ebp); + +/* get_fnkey_event + * + * gets the first (oldest) key id from the queue of events + * + * return value: id of key + */ +static int get_fnkey_event(void) +{ + struct register_buffer regs; + regs.eax = 0x9610; + regs.ebx = 0x61C; + /* clear other registers, some models need this */ + regs.ecx = 0; + regs.edx = 0; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + return regs.eax & 0xffff; +} + +/* get_thermal_event + * + * does what? + * + * return value: event ? + */ +static int get_thermal_event(void) +{ + struct register_buffer regs; + if (acerhk_model_features & TM_F_THERMAL) { + regs.eax = 0x9612; + regs.ebx = 0x12e; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + if (verbose > 3) + printk(KERN_INFO"acerhk: thermal event = 0x%x\n", regs.eax); + } else { + regs.eax = 0x00; + if (verbose > 3) + printk(KERN_INFO"acerhk: thermal event not supported\n"); + } + return regs.eax & 0xffff; +} + +#ifdef ACERDEBUG +/* pbutton_fct + * + * does what? + * + * return value: ? + */ +static int pbutton_fct(void) +{ + struct register_buffer regs; + if (acerhk_model_features & TM_F_PBUTTON) { + regs.eax = 0x9612; + regs.ebx = 0x10b; + regs.ecx = 0x2; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + if (verbose > 3) + printk(KERN_INFO"acerhk: pbutton = 0x%x\n", regs.eax); + } else { + if (verbose > 3) + printk(KERN_INFO"acerhk: pbutton function not supported\n"); + regs.eax = 0x00; + } + return regs.eax & 0xffff; +} +#endif + +/* wbutton_fct_1 + * + * turn on installed Bluetooth hardware together with the corresponding LED + * + * val: 0 turns off the LED + * 1 turns the LED to green/blue + * + * return value: ? + */ +static int wbutton_fct_1(int val) +{ + struct register_buffer regs; + if (acerhk_model_features & TM_F_WBUTTON) { + acerhk_bluetooth_state = val; + regs.eax = 0x9610; + regs.ebx = ((val & 0xff) << 8) | 0x34; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + if (verbose > 3) + printk(KERN_INFO"acerhk: wbutton1 = 0x%x\n", regs.eax); + } else { + if (verbose > 3) + printk(KERN_INFO"acerhk: wbutton function 1 not supported\n"); + regs.eax = 0x00; + } + return regs.eax & 0xffff; +} + +/* wbutton_fct_2 + * + * turn on installed WLAN hardware together with the corresponding LED + * + * val: 0 turns off the LED + * 1 turns the LED to orange + * + * return value: ? + */ +static int wbutton_fct_2(int val) +{ + struct register_buffer regs; + if (acerhk_model_features & TM_F_WBUTTON) { + acerhk_wlan_state = val; + regs.eax = 0x9610; + regs.ebx = ((val & 0xff) << 8) | 0x35; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + if (verbose > 3) + printk(KERN_INFO"acerhk: wbutton2 = 0x%x\n", regs.eax); + } else { + if (verbose > 3) + printk(KERN_INFO"acerhk: wbutton function 2 not supported\n"); + regs.eax = 0x00; + } + return regs.eax & 0xffff; +} + +/* get_cmos_index + * + * gets index of CMOS port from ROM. The number of events is monitored + * in this port. + * + * return value: index of CMOS port + */ +static int get_cmos_index(void) +{ + struct register_buffer regs; + regs.eax = 0x9610; + regs.ebx = 0x51C; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + cmos_index = regs.ecx & 0xff; + if (verbose) + printk(KERN_INFO"acerhk: cmos index set to 0x%x\n", cmos_index); + return cmos_index; +} + +/* get_nr_events + * + * gets the number of cached events (keys pressed) in queue. Up to 31 events + * are cached. + * + * return value: number of events in queue + */ +static int get_nr_events(void) +{ + unsigned long flags; + unsigned char c = 0; + + spin_lock_irqsave (&rtc_lock, flags); +#ifndef DUMMYHW + if (cmos_index) + c = CMOS_READ(cmos_index); + else if (verbose > 3) + printk(KERN_INFO"acerhk: get_nr_events - no valid cmos index set\n"); +#endif + spin_unlock_irqrestore (&rtc_lock, flags); + return c; +} + +/* set_mail_led + * + * change state of mail led + * + * val: 0 - switch led off + * 1 - switch led on (blinking) + * + * return value: 1 - action succesfull (val valid) + * 0 - no action taken (val invalid) + */ +static int set_mail_led(int val) +{ + struct register_buffer regs; + if (acerhk_model_features & TM_F_MAIL_LED) { + regs.eax = 0x9610; + regs.ebx = ((val & 0xff) << 8) | 0x31; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + if (verbose > 3) + printk(KERN_INFO"acerhk: mail led set to = 0x%x\n", val); + } else if (acerhk_model_features & TM_F_MAIL_LED_EC) { + if (val == 1) + enable_mail_led_ec_1(); + else if (val == 0) + disable_mail_led_ec_1(); + } else if (acerhk_model_features & TM_F_MAIL_LED_EC2) { + if (val == 1) + enable_mail_led_ec_2(); + else if (val == 0) + disable_mail_led_ec_2(); + } else if (acerhk_model_features & TM_F_MAIL_LED_EC3) { + if (val == 1) + enable_mail_led_ec_3(); + else if (val == 0) + disable_mail_led_ec_3(); + } else { + if (verbose > 3) + printk(KERN_INFO"acerhk: mail led not supported\n"); + regs.eax = 0x00; + } + return regs.eax & 0xffff; +} + +/* launch_connect + * + * does what? + * val: 1 - only known value from windows driver + */ +static int launch_connect(int val) +{ + struct register_buffer regs; + if (acerhk_model_features & TM_F_CONNECT) { + regs.eax = 0x9610; + regs.ebx = ((val & 0xff) << 8) | 0x2e; + preempt_disable(); + call_bios(®s); + preempt_enable_no_resched(); + if (verbose > 3) + printk(KERN_INFO"acerhk: connect(%d) = 0x%x\n", val, regs.eax); + } else { + if (verbose > 3) + printk(KERN_INFO"acerhk: connect not supported\n"); + regs.eax = 0x00; + } + return regs.eax & 0xffff; +} + +/* }}} */ + +/* {{{ hardware probing */ + +static struct proc_dir_entry *proc_acer_dir; + +static unsigned int __init find_hk_area(void) +{ + int offset, sig; + unsigned int fkt; + fkt = 0; + sig = -1; /* offset to signature in io area */ + /* Look for signature, start at 0xf0000, search until 0xffff0 */ + for (offset = 0;offset < 0xfffd; offset += 16) { + if (readl(reg1 + offset) == 0x30552142) { + sig = offset; + offset = 0xffff; + } + } + if (sig < 0) + printk(KERN_WARNING"acerhk: could not find request handler, possibly not all functions available\n"); + else { + /* compute location of bios routine */ + fkt = readl(reg1 + sig + 5); + /* adjust fkt to address of mapped IO area */ + if (fkt >= 0xf0000) + fkt = (unsigned int)reg1 + fkt - 0xf0000; + else if (fkt >= 0xe0000) + fkt = (unsigned int)reg1 + fkt - 0xe0000; + else + fkt = 0; + } + return fkt; +} + +static void print_features(void) +{ + int i; + printk(KERN_INFO"acerhk: supported keys:"); + for (i = 0; i < 255; i++) { + switch (acerhk_key2name[i]) { + case k_help: printk(" help"); break; + case k_setup: printk(" setup"); break; + case k_p1: printk(" p1"); break; + case k_p2: printk(" p2"); break; + case k_p3: printk(" p3"); break; + case k_www: printk(" www"); break; + case k_mail: printk(" mail"); break; + case k_wireless: printk(" wireless"); break; + case k_power: printk(" power"); break; + case k_mute: printk(" mute"); break; + case k_volup: printk(" volup"); break; + case k_voldn: printk(" voldn"); break; + case k_res: printk(" res"); break; + case k_close: printk(" close"); break; + case k_open: printk(" open"); break; + case k_wireless2: printk(" wireless2"); break; + case k_play: printk(" play"); break; + case k_stop: printk(" stop"); break; + case k_prev: printk(" prev"); break; + case k_next: printk(" next"); break; + case k_display: printk(" display"); break; + default: break; + } + } + printk("\n"); + if (acerhk_model_features & TM_F_MUTE_LED_EC) + printk(KERN_INFO"acerhk: mute led is supported\n"); + if (acerhk_model_features & TM_F_MAIL_LED) + printk(KERN_INFO"acerhk: mail led is supported\n"); + else if (acerhk_model_features & TM_F_MAIL_LED_EC) + printk(KERN_INFO"acerhk: mail led (EC) is supported\n"); + else if (acerhk_model_features & TM_F_MAIL_LED_EC2) + printk(KERN_INFO"acerhk: mail led (EC2) is supported\n"); + else if (acerhk_model_features & TM_F_MAIL_LED_EC3) + printk(KERN_INFO"acerhk: mail led (EC3) is supported\n"); + printk(KERN_INFO"acerhk: supported functions:"); + if (acerhk_model_features & TM_F_CONNECT) + printk(" connect"); + if (acerhk_model_features & TM_F_THERMAL) + printk(" thermal"); + if (acerhk_model_features & TM_F_PBUTTON) + printk(" pbutton"); + if (acerhk_model_features & TM_F_WBUTTON) + printk(" wbutton"); + printk("\n"); +} + +static void __init setup_keymap_model(unsigned int series) +{ + /* clear mapping keycode -> keyname, */ + memset(&acerhk_key2name[0], k_none, sizeof(acerhk_key2name)); + /* first set the common keys, namely FnF1 and FnF2, */ + acerhk_key2name[1] = k_help; + acerhk_key2name[2] = k_setup; + /* then set known keycodes according to model */ + switch (series) { + case 110: + acerhk_key2name[48] = k_wireless; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[54] = k_www; + acerhk_key2name[49] = k_mail; + acerhk_key2name[3] = k_power; + acerhk_key2name[8] = k_mute; + acerhk_key2name[32] = k_volup; + acerhk_key2name[33] = k_voldn; + /* C110 generates 2 extra codes when opening/closing the lid */ + acerhk_key2name[74] = k_close; + acerhk_key2name[75] = k_open; + break; + case 300: /* treat C300 like C100 with Bluetooth button */ + acerhk_key2name[68] = k_wireless2; + case 100: + acerhk_key2name[48] = k_wireless; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[49] = k_www; + acerhk_key2name[54] = k_mail; + acerhk_key2name[3] = k_power; + acerhk_key2name[8] = k_mute; + acerhk_key2name[32] = k_volup; + acerhk_key2name[33] = k_voldn; + break; + default: + /* only the two common keys are supported */ + break; + case 210: + acerhk_key2name[19] = k_p1; + acerhk_key2name[20] = k_p2; + acerhk_key2name[17] = k_www; + acerhk_key2name[18] = k_mail; + break; + case 220: + case 260: /* 260 with same keys? */ + acerhk_key2name[49] = k_p1; + acerhk_key2name[19] = k_p2; + acerhk_key2name[18] = k_www; + acerhk_key2name[17] = k_mail; + break; + case 230: + case 280: /* 280 with same keys? */ + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[49] = k_mail; + acerhk_key2name[54] = k_www; + break; + case 1500: + acerhk_key2name[0x49] = k_setup; + acerhk_key2name[0x36] = k_www; + acerhk_key2name[0x31] = k_mail; + acerhk_key2name[0x11] = k_p1; + acerhk_key2name[0x12] = k_p2; + acerhk_key2name[0x30] = k_wireless; + acerhk_key2name[0x44] = k_wireless2; + acerhk_key2name[0x03] = k_power; + break; + case 240: + acerhk_key2name[0x31] = k_www; + acerhk_key2name[0x36] = k_mail; + acerhk_key2name[0x11] = k_p1; + acerhk_key2name[0x12] = k_p2; + acerhk_key2name[0x44] = k_wireless; + acerhk_key2name[0x30] = k_wireless2; + acerhk_key2name[0x03] = k_power; + acerhk_key2name[0x08] = k_mute; + // acerhk_key2name[] = k_volup; + // acerhk_key2name[] = k_voldn; + break; + case 2900: + acerhk_key2name[0x31] = k_mail; /* with led */ + acerhk_key2name[0x36] = k_www; + acerhk_key2name[0x11] = k_p1; + acerhk_key2name[0x12] = k_p2; + acerhk_key2name[0x30] = k_wireless; /* wireless, with led, related with autowlan=1 */ + break; + case 250: /* enriqueg@altern.org */ + /* TravelMate 254LMi_DT manual common for 240/250 series, but key order + differ from 240 already present on acerhk driver */ + /* TravelMate 254LMi_DT: 6 buttons: left to right: mail, www, p1, p2, bluetooth, wireless */ + acerhk_key2name[0x31] = k_mail; /* with led */ + acerhk_key2name[0x36] = k_www; + acerhk_key2name[0x11] = k_p1; + acerhk_key2name[0x12] = k_p2; + acerhk_key2name[0x44] = k_wireless2; /* bluetooth, hw optional */ + acerhk_key2name[0x30] = k_wireless; /* wireless, with led, related with autowlan=1 */ + acerhk_key2name[0x03] = k_power; /* Fn+F3 */ + acerhk_key2name[0x08] = k_mute; /* Fn+F8 */ + break; + case 380: + /* TM 380 has same codes as TM 370, with an additional one */ + acerhk_key2name[0x03] = k_power; + case 370: + acerhk_key2name[0x30] = k_wireless; + acerhk_key2name[0x11] = k_p1; + acerhk_key2name[0x12] = k_p2; + acerhk_key2name[0x13] = k_p3; + acerhk_key2name[0x36] = k_www; + acerhk_key2name[0x31] = k_mail; + break; + case 360: + /* 360 series has the same layout as 350, with an + additional wireless key */ + acerhk_key2name[64] = k_wireless; + case 350: + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[20] = k_p3; + acerhk_key2name[21] = k_www; + acerhk_key2name[19] = k_mail; + break; + case 520: + acerhk_key2name[19] = k_p1; + acerhk_key2name[20] = k_p2; + acerhk_key2name[17] = k_www; + acerhk_key2name[18] = k_mail; + break; + case 610: + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[19] = k_p3; + acerhk_key2name[21] = k_www; + acerhk_key2name[20] = k_mail; + acerhk_key2name[64] = k_wireless; + break; + case 630: + /* 630 has all keys of 620 plus one */ + acerhk_key2name[8] = k_mute; + case 620: + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[19] = k_p3; + acerhk_key2name[54] = k_www; + acerhk_key2name[49] = k_mail; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[3] = k_power; + acerhk_key2name[32] = k_volup; + acerhk_key2name[33] = k_voldn; + break; + case 290: + case 420: + case 430: + case 530: + case 540: + case 650: + case 660: + case 800: + case 1450: + case 2300: + case 2350: + case 4000: + case 4050: + case 6000: + case 8000: + case 4100: + case 4150: + case 4500: + case 4600: + case 4650: + case 1680: + case 1690: + /* keys are handled by dritek EC */ + acerhk_key2name[1] = k_none; + acerhk_key2name[2] = k_none; + break; + case 1300: + case 1310: + case 1350: + case 1360: + case 1400: + case 1700: + case 1800: + case 2000: + case 2010: + case 2020: + /* Aspire 13xx series laptops use dritek hardware, no + acerhk-mapping needed + VolUp and VolDown are managed as normal keys + 1300/1310 series should have P1, P2, Mail, WWW, Mute buttons + 1353 has bluetooth, wifi, p1, p2, www, mail, help, setup, power + and mute + Aspire 1400/1450/Ferrari use dritek EC, too + 1450 should have bluetooth, wifi, p1, p2, www, mail, help, + setup, power and mute + Aspire 1700 uses dritek EC, too + 1700 should have bluetooth, wifi, p1, p2, www, mail, help, + setup, power and mute + need the MM-buttons Activation? (forward, shuffle, ...) + 2000 hast lots of MM buttons + 2010 should have bluetooth, wifi, p1, p2, www, mail, help, + setup, power and mute + */ + acerhk_key2name[1] = k_none; + acerhk_key2name[2] = k_none; + break; + case 1600: + /* Aspire 1600 has acer keycode 0x49 for FnF2 */ + acerhk_key2name[73] = k_setup; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[49] = k_mail; + acerhk_key2name[54] = k_www; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[19] = k_p3; + acerhk_key2name[3] = k_power; + acerhk_key2name[8] = k_mute; + /* VolUp and VolDown keys doesn't seem to be managed as special keys + but as normal keys ! */ + break; + case 5020: /* Aspire 5020 has 0x6a for Fn+F2 */ + acerhk_key2name[2] = k_none; + acerhk_key2name[106] = k_setup; + acerhk_key2name[3] = k_power; + acerhk_key2name[5] = k_display; + acerhk_key2name[49] = k_mail; + acerhk_key2name[54] = k_www; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[68] = k_wireless2; + break; + case 2410: /* TM 2410 is very similar to Aspire 5020, but has 0x6s for Fn-F3 */ + acerhk_key2name[2] = k_none; + acerhk_key2name[106] = k_setup; + acerhk_key2name[109] = k_power; + acerhk_key2name[49] = k_mail; + acerhk_key2name[54] = k_www; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[68] = k_wireless2; + break; + case 40100: + /* Medion MD40100, 4 keys */ + acerhk_key2name[54] = k_www; + acerhk_key2name[49] = k_mail; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[55] = k_res; + break; + case 96500: + case 95400: + /* Medion MD95400, many keys */ + acerhk_key2name[49] = k_mail; /* 1 */ + acerhk_key2name[54] = k_www; /* 2 */ + acerhk_key2name[48] = k_wireless; /* 3 */ + acerhk_key2name[68] = k_wireless2; /* 4 (Bluetooth) */ + + acerhk_key2name[17] = k_p1; /* 5 */ + acerhk_key2name[18] = k_p2; /* 6 */ + acerhk_key2name[36] = k_play; /* 7 */ + acerhk_key2name[37] = k_stop; /* 8 */ + acerhk_key2name[34] = k_prev; /* 9 */ + acerhk_key2name[35] = k_next; /* 10 */ + acerhk_key2name[33] = k_voldn; /* 11 */ + acerhk_key2name[32] = k_volup; /* 12 */ + acerhk_key2name[38] = k_p3; /* 13 */ + acerhk_key2name[8] = k_mute; /* 14 */ + + acerhk_key2name[1] = k_help; /* FN+F1 (Help) */ + acerhk_key2name[5] = k_display; /* FN+F3 (Display switch) */ + acerhk_key2name[6] = k_res; /* FN+F4 (Display ein/ausschalten) */ + break; + case 42200: + /* Medion MD42200, 7 keys, no setup */ + acerhk_key2name[2] = k_none; + acerhk_key2name[5] = k_display; + acerhk_key2name[54] = k_www; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[49] = k_mail; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + break; + case 9783: + /* Medion MD9783, 6 keys + info, no setup */ + acerhk_key2name[2] = k_none; + acerhk_key2name[54] = k_www; + acerhk_key2name[49] = k_mail; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[19] = k_p3; + acerhk_key2name[8] = k_mute; + break; + case 7400: + /* Amilo Pro V2000 does not have Help and Setup key (?) + Amilo M 7400 has Help key, disabling only setup + */ + acerhk_key2name[2] = k_none; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[49] = k_mail; + acerhk_key2name[54] = k_www; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + break; + case 1559: + acerhk_key2name[6] = k_display; /* FN+F4 (Display ein/ausschalten) */ + case 1555: + /* AOpen (Ahtec Signal 1555M) is similar to FS Amilo M */ + acerhk_key2name[2] = k_none; + acerhk_key2name[48] = k_wireless; + acerhk_key2name[49] = k_mail; + acerhk_key2name[54] = k_www; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[34] = k_prev; + acerhk_key2name[35] = k_next; + acerhk_key2name[36] = k_play; + acerhk_key2name[37] = k_stop; + break; + case 6800: + case 7820: + /* Amilo D does not have Setup key */ + acerhk_key2name[2] = k_none; + acerhk_key2name[49] = k_mail; + acerhk_key2name[54] = k_www; + acerhk_key2name[17] = k_p1; + acerhk_key2name[18] = k_p2; + acerhk_key2name[19] = k_p3; + acerhk_key2name[8] = k_mute; + break; + case 6805: /* Added by damagedspline@aim.com */ + /* Amilo A1xxx does not have Setup key nor a mail key */ + acerhk_key2name[2] = k_none; + acerhk_key2name[54] = k_www; + acerhk_key2name[5] = k_display; + acerhk_key2name[110] = k_setup; //This is the Fancy Fan (cool-n'-quiet) key on A1650g + acerhk_key2name[48] = k_wireless; + break; + } +} + +static void __init setup_model_features(unsigned int series) +{ + switch (series) { + case 200: + case 210: + case 520: + /* nothing special */ + acerhk_model_features = 0; + acerhk_type = TM_old; + break; + case 220: + case 230: + case 260: + case 280: + case 360: + case 40100: /* Medion MD40100 */ + case 95400: /* Medion MD95400 */ + case 96500: /* Medion MD96500 */ + /* all special functions, no mail led */ + acerhk_model_features = 0x00f00000; + acerhk_type = TM_new; + break; + case 42200: /* Medion MD42200 */ + /* has WLAN button, should call connect() */ + acerhk_model_features = TM_F_WBUTTON | TM_F_CONNECT; + acerhk_type = TM_old; + break; + case 9783: /* Medion MD9783 */ + /* only email led */ + acerhk_model_features = TM_F_MAIL_LED; + acerhk_type = TM_new; + break; + case 1600: + acerhk_type = TM_new; + /* Do Aspire 1600 series have special functions or not ? I enable + them, perhaps it helps with problems Francois Valenduc has */ + acerhk_model_features = 0x00f00000; + break; + case 300: + case 100: + case 110: + case 240: + case 350: + case 610: + case 620: + case 630: + /* all special functions, mail led */ + acerhk_model_features = TM_F_MAIL_LED | 0x00f00000; + acerhk_type = TM_new; + break; + case 370: + case 380: + case 2410: + case 2900: /* Medion MD2900 */ + case 2100: /* TM 2100 uses same driver as 5020 */ + case 5020: /* Aspire 5020 is still old hardware */ + acerhk_model_features = TM_F_MAIL_LED | TM_F_CONNECT| TM_F_WBUTTON; + acerhk_type = TM_new; + break; + case 7400: + case 1555: + case 1559: + /* all special functions for Fujitsu-Siemens Amilo M7400, Pro V2000; AOpen */ + acerhk_model_features = 0x00f00000; + acerhk_type = TM_new; + break; + case 6805: /* Added by damagedspline@aim.com */ + /* Amilo A1xxx does not have a mail led */ + acerhk_model_features = 0x00f00000; + acerhk_type = TM_new; + break; + case 6800: + case 7820: + /* mail led and all special functions for FS Amilo D */ + acerhk_model_features = TM_F_MAIL_LED | 0x00f00000; + acerhk_type = TM_new; + break; + case 2350: + case 4050: + acerhk_wlan_state = 1; // Default state is on + case 290: + /* no special functions, wireless hardware controlled by EC */ + acerhk_model_features = TM_F_WLAN_EC2 | TM_F_BLUE_EC2; + acerhk_type = TM_dritek; + break; + case 650: + case 1300: + case 1310: + case 1400: + case 1700: + /* all special functions, wireless hardware can be controlled */ + acerhk_model_features = 0x00f00000; + acerhk_type = TM_dritek; + break; + case 4100: + case 4600: + case 1680: + case 1690: /* Aspire 1680/1690 should be similar to TM 4100/4600 */ + /* mail led, wireless and bluetooth controlled the old way, but keys are + controlled by normal keyboard controller, so mark as dritek and + deactivate dritek use */ + acerhk_model_features = TM_F_MAIL_LED | TM_F_WBUTTON; + acerhk_type = TM_dritek; + usedritek=0; + break; + case 660: + case 800: + /* all special functions, mail led */ + acerhk_model_features = TM_F_MAIL_LED | 0x00f00000; + acerhk_type = TM_dritek; + break; + case 1350: + case 1360: + /* mail led, handled by EC, wireless HW is not (yet) controllable ? */ + acerhk_model_features = TM_F_MAIL_LED_EC|TM_F_WLAN_EC1; + acerhk_type = TM_dritek; + break; + case 1450: + /* Bluetooth/Wlan led, Mail led handled by EC (variant 3) */ + acerhk_model_features = TM_F_MAIL_LED_EC3|TM_F_WBUTTON; + acerhk_type = TM_dritek; + break; + case 1500: + /* Bluetooth/Wlan led */ + acerhk_model_features = TM_F_WBUTTON; + acerhk_type = TM_new; + break; + case 420: + case 430: + /* all functions and dritek EC, mail LED is handled by EC, second + variant. An additional led is available, mute. (really?) + */ + acerhk_type = TM_dritek; + acerhk_model_features = TM_F_MUTE_LED_EC|TM_F_MAIL_LED_EC2; + break; + case 2300: + case 4000: + case 4500: + /* wireless hardware, hopefully under control of my driver */ + acerhk_type = TM_dritek; + acerhk_model_features = TM_F_BLUE_EC1|TM_F_WLAN_EC1; + break; + case 3200: + /* test, if this model uses old style wlan control */ + acerhk_model_features = TM_F_WBUTTON; + acerhk_type = TM_dritek; + break; + case 6000: + case 8000: + /* 6000 and 8000 have wireless hardware, but I don't know how to handle, + so I choose no features */ + acerhk_type = TM_dritek; + break; + case 530: + case 540: + case 2000: + /* No features (?) dritek EC, mail LED is handled by EC but + different from other Aspire series */ + acerhk_type = TM_dritek; + acerhk_model_features = TM_F_MAIL_LED_EC2; + break; + case 4150: + case 4650: + /* Dritek EC, bluetooth, wifi, mail */ + /* According to Andreas Stumpfl his TM 4652LMi does also work as series + 3200, which might mean that the BIOS function accesses the EC */ + acerhk_type = TM_dritek; + acerhk_model_features = TM_F_MAIL_LED_EC2 | TM_F_WLAN_EC2 | TM_F_BLUE_EC2; + break; + case 1800: + case 2010: + case 2020: + /* Dritek EC, bluetooth, wifi, mail */ + acerhk_type = TM_dritek; + acerhk_model_features = TM_F_MAIL_LED_EC2 | TM_F_WLAN_EC2 | TM_F_BLUE_EC2; + acerhk_wlan_state = 1; // Default state is on + break; + case 250: /* enriqueg@altern.org */ + /* TravelMate254LMi_DT : mail led, bluetooth (button present, hw optional), wifi (with led) */ + acerhk_model_features = TM_F_MAIL_LED| + TM_F_WBUTTON ; + acerhk_type = TM_new; + acerhk_wlan_state = 0; //Initial state is off on 254LMi_DT + break; + default: + /* nothing special */ + acerhk_model_features = 0; + acerhk_type = TM_unknown; + break; + } + /* set the correct bios call function according to type */ + if ((acerhk_type == TM_new) || (acerhk_type == TM_dritek)) { + call_bios = call_bios_6xx; + if (verbose > 2) + printk(KERN_INFO"acerhk: using call_bios_6xx mode\n"); + } else { + call_bios = call_bios_52x; + if (verbose > 2) + printk(KERN_INFO"acerhk: using call_bios_52x mode\n"); + } + /* remove key file on dritek hardware */ + if (acerhk_type == TM_dritek) { + remove_proc_entry("key", proc_acer_dir); + } + /* setup available keys */ + setup_keymap_model(acerhk_series); + if (verbose > 1) + print_features(); +} + +static unsigned int __init determine_laptop_series(char * str) +{ + /* 0 means unknown series, handled like TM 200 */ + unsigned int series = 0; + if (strncmp(str, "TravelMate ", 11) == 0) { + switch (str[11]) { + case 'C': + if (str[12] == '1') { + if (str[13] == '0') { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates TM C100 series\n"); + series = 100; + } else if (str[13] == '1') { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates TM C110 series\n"); + series = 110; + } + } else if (str[12] == '3') { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates TM C300 series\n"); + series = 300; + } + break; + case 'F': + if (str[12] == '4') { + series = 230; + } + break; + case '2': + if (str[14] == '0') { + /* newer Travelmate 2xxx series */ + switch (str[12]) { + case '0': + case '5': + series = 2000; // 2000 and 2500 are the same + break; + case '1': + if (str[13] == '0') + series = 2100; + break; + case '2': + case '7': + series = 2200; // 2200 and 2700 are the same + break; + case '3': + if (str[13] == '0') + series = 4000; // 2300 is the same as 4000 + else if (str[13] == '5') + series = 4050; // 2350 is the same as 4050 + break; + case '4': + if (str[13] == '1') + series = 2410; + break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM 2xxx series\n"); + break; + } + } else { + /* older Travelmate 2xx series */ + switch (str[12]) { + case '0': series = 200; break; + case '1': series = 210; break; + case '2': series = 220; break; + case '4': series = 240; break; + case '5': series = 250; break; /* enriqueg@altern.org */ + case '6': series = 260; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM 2xx series\n"); + break; + } + } + break; + case '3': + switch (str[12]) { + case '0': series = 3200; break; /* TM 3000 works like TM 3200 */ + /* Travelmate 3xx series */ + case '5': series = 350; break; + case '6': series = 360; break; + case '7': series = 370; break; + case '8': series = 380; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM 3xx series\n"); + break; + } + break; + case '4': + if ( (strnlen(str, ACERHK_MODEL_STRLEN-1) == 15) && + (str[14] == '0') ) { /* Travelmate 4xxx series */ + switch (str[12]) { + case '0': /* 4000 and 4500 are the same */ + case '5': + series = 4000; + break; + case '1': + case '6': /* 4100 and 4600 are the same */ + series = 4100; + break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM 4xxx series\n"); + break; + } + } else { /* Travelmate 4xx series */ + switch (str[12]) { + case '2': series = 420; break; + case '3': series = 430; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM 4xx series\n"); + break; + } + } + break; + case '5': /* Travelmate 5xx series */ + if (str[12] == '2') + series = 520; + else if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM 5xx series\n"); + break; + case '6': /* older Travelmate 6xx series */ + switch (str[12]) { + case '1': series = 610; break; + case '2': series = 620; break; + case '3': series = 630; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM 6xx series\n"); + break; + } + break; + default: + printk(KERN_INFO"acerhk: model string indicates unknown TM xxx series\n"); + break; + } + if (series && verbose > 1) + printk(KERN_INFO"acerhk: model string indicates TM %d series\n", series); + } + /* newer Travelmate series do not have a space after 'TravelMate' */ + else if (strncmp(str, "TravelMate", 10) == 0) { + switch (str[10]) { + case '2': + if (str[11] == '9') { + series = 290; + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM2xx series\n"); + } + break; + case '3': + if (str[11] == '2' && str[14] == '3') { + // TM 3200 uses "TravelMate32003" + series = 3200; + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM3xxx series\n"); + } + break; + case '4': + switch (str[11]) { + case '3': series = 430; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM4xx series\n"); + break; + } + break; + case '5': + switch (str[11]) { + case '3': series = 530; break; + case '4': series = 540; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM5xx series\n"); + break; + } + break; + case '6': + switch (str[11]) { + case '5': series = 650; break; + case '6': series = 660; break; + case '0': + if (strncmp(str, "TravelMate60003", 15) == 0) { + series = 6000; break; + } + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM6xx series\n"); + break; + } + break; + case '8': + if (strncmp(str, "TravelMate80003", 15) == 0) { + series = 8000; + } else if (str[11] == '0') { + series = 800; + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown TM8xx series\n"); + } + break; + default: + printk(KERN_INFO"acerhk: model string indicates unknown TMxxx series\n"); + break; + } + if (series && verbose > 1) + printk(KERN_INFO"acerhk: model string indicates TM%d series\n", series); + } + else if (strncmp(str, "Aspire ", 7) == 0) { + switch(str[7]) { + case '1': /* Aspire 1xxx series */ + switch(str[8]) { + case '3': /* Aspire 13xx series */ + switch (str[9]) { + case '0': series = 1300; break; + case '1': series = 1310; break; + case '5': series = 1350; break; + case '6': series = 1360; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 13xx series\n"); + break; + } + break; + case '4': /* Aspire 14xx series */ + switch (str[9]) { + case '0': series = 1400; break; + case '5': series = 1450; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 14xx series\n"); + break; + } + break; + case '5': series = 1500; break; + case '6': /* Aspire 14xx series */ + switch (str[9]) { + case '0': series = 1600; break; + case '8': + case '9': series = 1680; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 16xx series\n"); + break; + } + break; + case '7': series = 1700; break; + case '8': series = 1800; break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 1xxx series\n"); + break; + } + break; + case '2': /* Aspire 2xxx series */ + if (str[8] == '0') { + switch (str[9]) { + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 20xx series\n"); + break; + case '0': series = 2000; break; + case '1': series = 2010; break; + case '2': series = 2020; break; + } + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 2xxx series\n"); + } + break; + case '3': /* Aspire 3xxx series */ + if (str[8] == '0') { + switch (str[9]) { + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 30xx series\n"); + break; + case '2': series = 5020; break; /* Aspire 3020/5020 are identical */ + } + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 3xxx series\n"); + } + break; + case '5': /* Aspire 5xxx series */ + if (str[8] == '0') { + switch (str[9]) { + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 50xx series\n"); + break; + case '2': series = 5020; break; + } + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire 5xxx series\n"); + } + break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Aspire series\n"); + break; + } + if (series && verbose > 1) + printk(KERN_INFO"acerhk: model string indicates Aspire %d series\n", series); + } + else if (strncmp(str, "Extensa ", 8) == 0) { + /* Extensa series */ + switch (str[8]) { + case '3': + switch (str[9]) { + case '0': + series = 3000; break; + default: break; + } + break; + default: break; + } + if (series && verbose > 1) + printk(KERN_INFO"acerhk: model string indicates Extensa %d series\n", series); + else if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown Extensa series\n"); + } + else if (strncmp(str, "Amilo ", 6) == 0) { + switch (str[6]) { + case 'D': /* complete string is "Amilo D-Series", there seems to be no model number */ + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates FS Amilo D series\n"); + /* this is the model number of my Amilo */ + series = 7820; + break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown FS Amilo XX series\n"); + series = 7820; + } + } + else if (strncmp(str, "AMILO ", 6) == 0) { + switch (str[6]) { + case 'D': /* AMILO D 6800 P4-2000 */ + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates FS AMILO D series\n"); + series = 6800; + break; + case 'M': + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates FS AMILO M(7400) series\n"); + series = 7400; + break; + case 'P': + /* it is assumed, that 'AMILO P' appears only on Amilo Pro Series */ + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates FS AMILO Pro (V2000) series\n"); + series = 7400; + break; + case 'A': /* AMILO Axxxx - added by damagedspline@aim.com */ + switch (str[7]) { + case '1': /* AMILO A1xxx */ + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates FS AMILO A1xxx series\n"); + series = 6805; + break; + } + break; + default: + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates unknown FS AMILO XX series\n"); + series = 6800; + } + } + else if (strncmp(str, "MEDIONPC", 8) == 0) { + uint medionmodel; + if ((medionmodel = COLUSSI("WIM 2040", 4, reg1, AREA_SIZE)) >= 0) { + printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel); + series = 96500; + } else { + if ((medionmodel = COLUSSI("MD 9", 4, reg1, AREA_SIZE)) >= 0) { + printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel); + } + series = 95400; + } + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates a medion MD %d\n", series); + } + else if (strncmp(str, "MEDIONNB", 8) == 0) { + /* Search for the Product string of the MD9783. */ + if (COLUSSI("MD 42200", 8, reg1, AREA_SIZE) >= 0) { + if (verbose>1) + printk(KERN_INFO"acerhk: model string indicates a Medion MD 42200\n"); + series = 42200; + } else if (COLUSSI("MD 9783", 7, reg1, AREA_SIZE) >= 0){ + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates a medion MD 9783\n"); + series = 9783; + } else if (COLUSSI("WIM 2000", 7, reg1, AREA_SIZE) >= 0){ + if (verbose>1) + printk(KERN_INFO"acerhk: model string indicates a Medion MD 2900\n"); + series = 2900; + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates a medion MD40100\n"); + series = 40100; + } + } else if (strncmp(str, "AOpen", 5) == 0) { + if (strncmp(str, "AOpen*EzRestore", 15) == 0) { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates a AOpen 1559\n"); + series = 1559; + } else { + /* Unless I know of other models no further differentiation, + although there is a second part of the model string */ + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates a AOpen\n"); + series = 1555; + } + } else if (strncmp(str, "CL56", 4) == 0) { + /* Unless I know of other models no further differentiation, + although there are strings with more numbers ("CL561" on a Compal + CL56/Zepto 4200, reported by Stian B. Barmen) + It has the same functions as Acer Aspire 2010 + */ + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates a Compal CL56 (or similar)\n"); + series = 2010; + } else { + if (verbose > 1) + printk(KERN_INFO"acerhk: model string indicates no supported hardware\n"); + } + return (series); +} + +static void __init probe_model(void) { + int offset; /* offset from beginning of reg1 to Model string */ + if (verbose) + printk(KERN_INFO"acerhk: start search for model string at %p\n", reg1); + /* first we look for Travelmate, if it isn't one we try to identify other + laptops, such as Medion or Aspire */ + offset = COLUSSI("Travel", 6, reg1, AREA_SIZE); + /* Try to detect Aspire laptops */ + if (offset < 0) + offset = COLUSSI("Aspire", 6, reg1, AREA_SIZE); + /* Try to detect Extensa laptops */ + if (offset < 0) + offset = COLUSSI("Extensa", 7, reg1, AREA_SIZE); + /* Try to detect Medion laptops */ + if (offset < 0) + offset = COLUSSI("MEDION", 6, reg1, AREA_SIZE); + /* Try to detect AOpen laptops */ + if (offset < 0) + offset = COLUSSI("AOpen", 5, reg1, AREA_SIZE); + /* Try to detect Fujitsu Siemens Amilo laptops */ + if (offset < 0) + offset = COLUSSI("Amilo", 5, reg1, AREA_SIZE); + if (offset < 0) + offset = COLUSSI("AMILO", 5, reg1, AREA_SIZE); + /* Try to detect Compal */ + if (offset < 0) + offset = COLUSSI("CL56", 4, reg1, AREA_SIZE); + if (offset >= 0) { + acerhk_model_addr = reg1 + offset; + /* copy the string, but not more than 15 characters */ + strncpy(acerhk_model_string, acerhk_model_addr, ACERHK_MODEL_STRLEN-1); + if (verbose) + printk(KERN_INFO"acerhk: found model string '%s' at %p\n", + acerhk_model_string, acerhk_model_addr); + if (bios_routine && verbose > 2) + printk(KERN_INFO"acerhk: offset from model string to function address: 0x%lx\n", + bios_routine - (unsigned long)acerhk_model_addr); + acerhk_series = determine_laptop_series(acerhk_model_string); + } else { + printk(KERN_WARNING"acerhk: Could not find model string, will assume type 200 series\n"); + acerhk_series = 200; + } +} + +/* }}} */ + +/* {{{ key polling and translation */ + +static void print_mapping(void) +{ + printk(KERN_INFO"acerhk: key mapping:\n"); + printk("acerhk: help 0x%x\n", acerhk_name2event[k_help]); + printk("acerhk: setup 0x%x\n", acerhk_name2event[k_setup]); + printk("acerhk: p1 0x%x\n", acerhk_name2event[k_p1]); + printk("acerhk: p2 0x%x\n", acerhk_name2event[k_p2]); + printk("acerhk: p3 0x%x\n", acerhk_name2event[k_p3]); + printk("acerhk: www 0x%x\n", acerhk_name2event[k_www]); + printk("acerhk: mail 0x%x\n", acerhk_name2event[k_mail]); + printk("acerhk: wireless 0x%x\n", acerhk_name2event[k_wireless]); + printk("acerhk: power 0x%x\n", acerhk_name2event[k_power]); + printk("acerhk: mute 0x%x\n", acerhk_name2event[k_mute]); + printk("acerhk: volup 0x%x\n", acerhk_name2event[k_volup]); + printk("acerhk: voldn 0x%x\n", acerhk_name2event[k_voldn]); + printk("acerhk: res 0x%x\n", acerhk_name2event[k_res]); + printk("acerhk: close 0x%x\n", acerhk_name2event[k_close]); + printk("acerhk: open 0x%x\n", acerhk_name2event[k_open]); + printk("acerhk: wireless2 0x%x\n", acerhk_name2event[k_wireless2]); + printk("acerhk: play 0x%x\n", acerhk_name2event[k_play]); + printk("acerhk: stop 0x%x\n", acerhk_name2event[k_stop]); + printk("acerhk: prev 0x%x\n", acerhk_name2event[k_prev]); + printk("acerhk: next 0x%x\n", acerhk_name2event[k_next]); + printk("acerhk: display 0x%x\n", acerhk_name2event[k_display]); +} + +static void set_keymap_name(t_key_names name, unsigned int key) +{ + acerhk_name2event[name] = key; +} + +static void init_keymap_input(void) +{ + /* these values for input keys are chosen to match the key names on the + actual Acer laptop */ + set_keymap_name(k_none, KEY_RESERVED); + set_keymap_name(k_help, KEY_HELP); + set_keymap_name(k_setup, KEY_CONFIG); + set_keymap_name(k_p1, KEY_PROG1); + set_keymap_name(k_p2, KEY_PROG2); + set_keymap_name(k_p3, KEY_PROG3); + set_keymap_name(k_www, KEY_WWW); + set_keymap_name(k_mail, KEY_MAIL); + set_keymap_name(k_wireless, KEY_XFER); + set_keymap_name(k_power, KEY_POWER); + set_keymap_name(k_mute, KEY_MUTE); + set_keymap_name(k_volup, KEY_VOLUMEUP); + set_keymap_name(k_voldn, KEY_VOLUMEDOWN); + set_keymap_name(k_res, KEY_CONFIG); + set_keymap_name(k_close, KEY_CLOSE); + set_keymap_name(k_open, KEY_OPEN); + /* I am not really happy with the selections for wireless and wireless2, + but coffee looks good. Michal Veselenyi proposed this value */ + set_keymap_name(k_wireless2, KEY_COFFEE); + set_keymap_name(k_play, KEY_PLAYPAUSE); + set_keymap_name(k_stop, KEY_STOPCD); + set_keymap_name(k_prev, KEY_PREVIOUSSONG); + set_keymap_name(k_next, KEY_NEXTSONG); + set_keymap_name(k_display, KEY_MEDIA); /* also not happy with this */ + if (verbose > 1) + print_mapping(); +} + +static int filter_idle_value(int keycode) +{ + int validkey = 0; + if (keycode != 0x0 && + keycode != 0x9610 && + keycode != 0xc100 && /* Francois Valenduc, Aspire 1601 LC */ + keycode != 0x8610 && + keycode != 0x861 && + keycode != 0x8650 && + keycode != 0x865) + validkey = keycode; + if (verbose > 4 && !validkey) + printk(KERN_INFO"acerhk: throw away idle value 0x%x\n", keycode); + return validkey; +} + +static void send_key_event(t_key_names key) +{ + unsigned int input_key; + if (key != k_none) { + /* convert key name to kernel keycode */ + input_key = acerhk_name2event[key]; + if (verbose > 2) + printk(KERN_INFO"acerhk: translated acer key name 0x%x to input key 0x%x\n", + key, input_key); + /* send press and release together, as there is no such event from acer as 'release' */ + input_report_key(acerhk_input_dev_ptr, input_key, 1); + input_report_key(acerhk_input_dev_ptr, input_key, 0); + } +} + +static t_key_names transl8_key_code(int keycode) +{ + t_key_names keyname = k_none; + /* first filter out idle values */ + if ( (keycode = filter_idle_value(keycode)) ) { + if (verbose > 3) + printk(KERN_INFO"acerhk: received key code 0x%x\n", keycode); + /* translate keycode to key name */ + if (keycode >= 0 && keycode <= 255) + keyname = acerhk_key2name[keycode]; + else { + if (verbose > 3) + printk(KERN_INFO"acerhk: keycode 0x%x too big, will use only 8 bits\n", keycode); + /* use only lower 8 bits of value to distinguish keys */ + keyname = acerhk_key2name[keycode&0xff]; + } + /* produce some log information for higher verbosity levels */ + if (keyname != k_none && verbose > 2) + printk(KERN_INFO"acerhk: translated acer key code 0x%x to key name 0x%x\n", + keycode, keyname); + else if (keyname == k_none && verbose > 3) + printk(KERN_INFO"acerhk: translated acer key code 0x%x to no key\n", + keycode); + if (autowlan) { + /* if automatic switching of wlan hardware is enabled, do it here + on wireless key press */ + if (keyname == k_wireless2) { + if (acerhk_bluetooth_state) + wbutton_fct_1(0); + else + wbutton_fct_1(1); + } + if (keyname == k_wireless) { + if (acerhk_wlan_state) + wbutton_fct_2(0); + else + wbutton_fct_2(1); + } + } + } + return keyname; +} + +/* polling timer handler */ +static void acerhk_poll_event(unsigned long save_size) +{ +#ifndef DUMMYHW + unsigned int max = MAX_POLLING_LOOPS; + /* make sure not to loop more then 32 times */ + if (!max || max > 32) + max = 32; + if (acerhk_type != TM_dritek) { + while (get_nr_events() && max--) { + send_key_event(transl8_key_code(get_fnkey_event())); + } + } else { + send_key_event(transl8_key_code(get_fnkey_event())); + } +#endif + acerhk_timer_poll.expires = jiffies + acerhk_polling_delay; + add_timer(&acerhk_timer_poll); +} + +/* blinking timer handler; added by Antonio Cuni */ +static void acerhk_blink_event(unsigned long not_used) +{ + if (acerhk_blueled_blinking != -1) { + acerhk_blueled_blinking = !acerhk_blueled_blinking; +#ifndef DUMMYHW + wbutton_fct_1(acerhk_blueled_blinking); +#endif + acerhk_timer_blinking.expires = jiffies + acerhk_blueled_blinking_delay; + add_timer(&acerhk_timer_blinking); + } + else + printk(KERN_WARNING "acerhk: blinking event called, but blinking not active\n"); +} + +static void init_input(void) +{ + int i; + +#ifndef KERNEL26 + /* request keyboard input module */ + request_module("keybdev"); + if (verbose > 3) + printk(KERN_INFO"requested keyboard input driver\n"); +#endif + +#ifndef STATIC_INPUT_DEV + /* allocate acerhk input device */ + acerhk_input_dev_ptr=input_allocate_device(); + /* enter some name */ + acerhk_input_dev_ptr->name = "Acer hotkey driver"; +#else + acerhk_input_dev_ptr=&acerhk_input_dev; +#endif + + /* some laptops have a mail led, should I announce it here? */ + acerhk_input_dev_ptr->evbit[0] = BIT(EV_KEY); + /* announce keys to input system + * the generated keys can be changed on runtime, + * but to publish those changes the device needs to + * get reconnected (I dont't know any other way) + * Therefore I enable all possible keys */ + for (i = KEY_RESERVED; i < BTN_MISC; i++) + set_bit(i, acerhk_input_dev_ptr->keybit); + /* set mapping keyname -> input event */ + init_keymap_input(); + if (verbose) + printk(KERN_INFO"acerhk: registered input device\n"); + input_register_device(acerhk_input_dev_ptr); + init_timer(&acerhk_timer_poll); + acerhk_polling_state = 0; +} + +static void stop_polling(void) +{ + if (acerhk_polling_state == 1) { + del_timer(&acerhk_timer_poll); + if (verbose) + printk(KERN_INFO"acerhk: key polling stopped\n"); + acerhk_polling_state = 0; + } else + if (verbose) + printk(KERN_INFO"acerhk: key polling not active\n"); +} + +static void start_polling(void) +{ + if (acerhk_polling_state != 1) { + acerhk_timer_poll.function = acerhk_poll_event; + acerhk_timer_poll.expires = jiffies + acerhk_polling_delay; + acerhk_timer_poll.data = get_nr_events(); + add_timer(&acerhk_timer_poll); + acerhk_polling_state = 1; + if (acerhk_type == TM_dritek) { + printk(KERN_INFO"acerhk: Your hardware does not need polling enabled for hotkeys to work, " + "you can safely disable polling by using the module parameter poll=0 (unless you " + "want to play around with the driver and see if there are buttons which need polling).\n"); + } + if (verbose) + printk(KERN_INFO"acerhk: starting key polling, every %d ms\n", acerhk_polling_delay); + } else + if (verbose) + printk(KERN_INFO"acerhk: key polling already active\n"); +} + +/* addedd by Antonio Cuni */ +static void start_blinking(void) +{ + if (acerhk_blueled_blinking == -1) { + // blinking was disabled... enable it! + acerhk_timer_blinking.function = acerhk_blink_event; + acerhk_timer_blinking.expires = jiffies + acerhk_blueled_blinking_delay; + acerhk_timer_blinking.data = 0; // not used + add_timer(&acerhk_timer_blinking); + acerhk_blueled_blinking = 0; + if (verbose) + printk(KERN_INFO "acerhk: starting blueled blinking\n"); + } else + if (verbose) + printk(KERN_INFO "acerhk: blueled already blinking\n"); +} + +/* Added by Antonio Cuni */ +static void stop_blinking(void) +{ + if (acerhk_blueled_blinking != -1) { + del_timer(&acerhk_timer_blinking); + if (verbose) + printk(KERN_INFO "acerhk: blueled blinking stopped\n"); + acerhk_blueled_blinking = -1; + } +} + +static void release_input(void) +{ + stop_polling(); + input_unregister_device(acerhk_input_dev_ptr); +} + +/* }}} */ + +/* {{{ procfs functions */ + +#ifndef CONFIG_PROC_FS + +static int acerhk_proc_init(void) +{ + return 1; +} +#else + +/* This macro frees the machine specific function from bounds checking and + * things like that... */ +#define PRINT_PROC(fmt,args...) \ + do { \ + *len += sprintf( buffer+*len, fmt, ##args ); \ + if (*begin + *len > offset + size) \ + return( 0 ); \ + if (*begin + *len < offset) { \ + *begin += *len; \ + *len = 0; \ + } \ + } while(0) + +static int pc_proc_infos( char *buffer, int *len, + off_t *begin, off_t offset, int size ) +{ + PRINT_PROC( "Acer hotkeys version %s\n", ACERHK_VERSION); + PRINT_PROC( "Model(Type)\t: %s(", acerhk_model_string); + switch(acerhk_type) { + default: + PRINT_PROC( "unknown)\n"); + break; + case TM_old: + PRINT_PROC( "old)\n"); + break; + case TM_new: + PRINT_PROC( "new)\n"); + break; + case TM_dritek: + PRINT_PROC( "Dritek)\n"); + break; + } + if (bios_routine != 0) { + PRINT_PROC( "request handler\t: 0x%x\n", bios_routine); + if (cmos_index) { + PRINT_PROC( "CMOS index\t: 0x%x\n", cmos_index); + PRINT_PROC( "events pending\t: %u\n", get_nr_events()); + } else { + PRINT_PROC( "CMOS index\t: not available\n"); + } + if (acerhk_polling_state == 1) + PRINT_PROC( "kernel polling\t: active\n"); + else + PRINT_PROC( "kernel polling\t: inactive\n"); + PRINT_PROC( "autoswitch wlan\t: "); + if (autowlan == 1) + PRINT_PROC( "enabled\n"); + else + PRINT_PROC( "disabled\n"); + } else { + PRINT_PROC( "request handler\t: not found\n"); + PRINT_PROC( "kernel polling\t: not possible\n"); + } + /* model specific infos */ + if (acerhk_type == TM_dritek) { + PRINT_PROC( "use of Dritek EC: "); + if (usedritek) + PRINT_PROC( "enabled\n"); + else + PRINT_PROC( "disabled\n"); + } + if (acerhk_type == TM_old) + PRINT_PROC( "preg400\t\t: 0x%p\n", preg400); + return (1); +} + +static int acerhk_proc_info( char *buffer, char **start, off_t offset, + int size, int *eof, void *data ) +{ + int len = 0; + off_t begin = 0; + + *eof = pc_proc_infos( buffer, &len, &begin, offset, size ); + + if (offset >= begin + len) + return( 0 ); + *start = buffer + (offset - begin); + return( size < begin + len - offset ? size : begin + len - offset ); + +} + +static int acerhk_proc_key( char *buffer, char **start, off_t offset, + int size, int *eof, void *data ) +{ + if (size >= 5 && offset == 0) { + if (acerhk_type == TM_dritek || acerhk_polling_state == 1) { + snprintf(buffer+offset, size, "n/a\n"); + } else { + snprintf(buffer+offset, size, "0x%02x\n", filter_idle_value(get_fnkey_event())); + } + *eof = 1; + return 5; + } + *eof = 1; + return 0; +} + +static int acerhk_proc_led(struct file* file, const char* buffer, + unsigned long count, void* data) +{ + char str[4]; + int len; + if (count > 4) + len = 4; + else + len = count; + if (copy_from_user(str, buffer, len)) + return -EFAULT; + str[3] = '\0'; + if ( ( (len >= 2) && (!strncmp(str, "on", 2) || !strncmp(str, "an", 2)) ) + || str[0] == '1') + set_mail_led(1); + else + set_mail_led(0); + return len; +} + +static int acerhk_proc_wirelessled(struct file* file, const char* buffer, + unsigned long count, void* data) +{ + char str[4]; + int len; + if (count > 4) + len = 4; + else + len = count; + if (copy_from_user(str, buffer, len)) + return -EFAULT; + str[3] = '\0'; + if ( ( (len >= 2) && (!strncmp(str, "on", 2) || !strncmp(str, "an", 2)) ) + || str[0] == '1') { + if (acerhk_model_features & TM_F_WLAN_EC1) + enable_wlan_ec_1(); + else if (acerhk_model_features & TM_F_WLAN_EC2) + enable_wlan_ec_2(); + else + wbutton_fct_2(1); + } + else { + if (acerhk_model_features & TM_F_WLAN_EC1) + disable_wlan_ec_1(); + else if (acerhk_model_features & TM_F_WLAN_EC2) + disable_wlan_ec_2(); + else + wbutton_fct_2(0); + } + return len; +} + + +/* Modified by Antonio Cuni: added support for blinking + possible values: + - off, 0: led always off + - on, an, 1: led alway on + - n (a number): led blinking; n is the delay between + two changes of state, in jiffies; n must + be > 50, to prevent the user from overloading + the kernel. + + */ +static int acerhk_proc_blueled(struct file* file, const char* buffer, + unsigned long count, void* data) +{ + const int MAXLEN=11; + char str[MAXLEN]; + int len; + int isNumber; + + if (count > MAXLEN) + len = MAXLEN; + else + len = count; + if (copy_from_user(str, buffer, len)) + return -EFAULT; + str[MAXLEN - 1] = '\0'; + + /* try to parse a number */ + isNumber = sscanf(str, "%u", &acerhk_blueled_blinking_delay); + /* if the delay is 0, turn off the led */ + if (isNumber && acerhk_blueled_blinking_delay != 0 && acerhk_blueled_blinking_delay != 1) { + if (acerhk_blueled_blinking_delay < 50) + printk(KERN_INFO"acerhk: blinking request rejected. The delay must be > 50.\n"); + else { + if (verbose) + printk(KERN_INFO"acerhk: blinking delay set to %u.\n", acerhk_blueled_blinking_delay); + start_blinking(); + } + } else if (acerhk_blueled_blinking_delay == 1 || !strncmp(str, "on", 2) || !strncmp(str, "an", 2)) { + stop_blinking(); + if (acerhk_model_features & TM_F_BLUE_EC1) + enable_bluetooth_ec_1(); + else if (acerhk_model_features & TM_F_BLUE_EC2) + enable_bluetooth_ec_2(); + else + wbutton_fct_1(1); + } else { + /* it's 0 or everything else */ + stop_blinking(); + if (acerhk_model_features & TM_F_BLUE_EC1) + disable_bluetooth_ec_1(); + else if (acerhk_model_features & TM_F_BLUE_EC2) + disable_bluetooth_ec_2(); + else + wbutton_fct_1(0); + } + return len; +} + +#ifdef ACERDEBUG +static void do_debug(const char* buffer, unsigned long len) +{ + unsigned int h, i; + switch (buffer[0]) { + case 'b': + /* test WLAN on TM 4001 */ + switch (buffer[1]) { + case '0': + disable_wlan_ec_1(); + break; + case '1': + default: + enable_wlan_ec_1(); + } + break; + case 'B': + /* test BLUETOOTH on TM 4001 */ + switch (buffer[1]) { + case '0': + disable_bluetooth_ec_1(); + break; + case '1': + default: + enable_bluetooth_ec_1(); + } + break; + case 'D': + /* test "DMM Function Enabled" entry of TM 4150/4650 */ + enable_dmm_function(); + break; + case 'i': + case '1': +#ifndef KERNEL26 + MOD_INC_USE_COUNT; +#endif + break; + case 'e': + switch (buffer[1]) { + case '1': + start_polling(); + break; + default: + stop_polling(); + } + break; + case 'k': + for (i = 0; i <= 255;i++) { + input_report_key(acerhk_input_dev_ptr, i, 1); + input_report_key(acerhk_input_dev_ptr, i, 0); + } + break; + case 'm': + /* set mapping key names -> input events */ + sscanf(&buffer[2],"%x", &i); + h = buffer[1] - '0' + 1; + printk("acerhk: key name %x maps to %x\n", h, i); + acerhk_name2event[h] = i; + break; + case 'M': + /* test mute LED on dritek hardware */ + switch (buffer[1]) { + case '0': + disable_mute_led_ec(); + break; + case '1': + default: + enable_mute_led_ec(); + } + break; + case 'p': + printk("acerhk: pbutton = 0x%x\n", pbutton_fct()); + break; + case 's': + /* send key event to test the key translation in input system */ + sscanf(&buffer[1],"%x", &h); + printk("acerhk: sending key event 0x%x\n", h); + input_report_key(acerhk_input_dev_ptr, h, 1); + input_report_key(acerhk_input_dev_ptr, h, 0); + break; + case 'S': + /* simulate key codes to test the key translation in acerhk */ + sscanf(&buffer[1],"%x", &h); + send_key_event(transl8_key_code(h)); + break; + case 't': + printk("acerhk: thermal event = 0x%x\n", get_thermal_event()); + break; + case 'w': + /* test the wbutton functions, someone really needs to have another look + at the windows driver */ + switch (buffer[1]) { + case '2': + printk("acerhk: wbutton_2(%d) = 0x%x\n", buffer[2]-'0', wbutton_fct_2(buffer[2]-'0')); + break; + case '1': + default: + printk("acerhk: wbutton_1(%d) = 0x%x\n", buffer[2]-'0', wbutton_fct_1(buffer[2]-'0')); + } + break; + case 'W': + /* test wireless HW/LED on some models using dritek hardware */ + switch (buffer[1]) { + case '0': + disable_wireless_ec(); + break; + case '1': + default: + enable_wireless_ec(); + } + break; + case 'v': + verbose = buffer[1]-'0'; + printk("acerhk: verbosity level changed to %d\n", verbose); + break; + case 'd': + case '0': + default: +#ifndef KERNEL26 + MOD_DEC_USE_COUNT; +#endif + break; + } +} + +static int acerhk_proc_debug(struct file* file, const char* buffer, + unsigned long count, void* data) +{ + char str[5]; + int len; + if (count > 5) + len = 5; + else + len = count; + if (copy_from_user(str, buffer, len)) + return -EFAULT; + str[4] = '\0'; + do_debug(str, len); + return len; +} +#endif + +static int acerhk_proc_init(void) +{ + int retval; + struct proc_dir_entry *entry; + /* create own directory */ + proc_acer_dir = proc_mkdir("driver/acerhk", NULL); + if (proc_acer_dir == NULL) { + retval = 0; + printk(KERN_INFO"acerhk: could not create /proc/driver/acerhk\n"); + } + else { + proc_acer_dir->owner = THIS_MODULE; + /* now create several files, first general info ... */ + entry = create_proc_read_entry("info", + 0444, proc_acer_dir, acerhk_proc_info, NULL); + if (entry == NULL) { + printk(KERN_INFO"acerhk: cannot create info file\n"); + remove_proc_entry("driver/acerhk", NULL); + retval = 0; + } else { + entry->owner = THIS_MODULE; + /* ... last pressed key ... */ + entry = create_proc_read_entry("key", + 0444, proc_acer_dir, acerhk_proc_key, NULL); + if (entry == NULL) { + printk(KERN_INFO"acerhk: cannot create key file\n"); + remove_proc_entry("info", proc_acer_dir); + remove_proc_entry("driver/acerhk", NULL); + retval = 0; + } else { + entry->owner = THIS_MODULE; + /* ... and led control file */ + entry = create_proc_entry("led", 0222, proc_acer_dir); + if (entry == NULL) { + printk(KERN_INFO"acerhk: cannot create LED file\n"); + remove_proc_entry("info", proc_acer_dir); + remove_proc_entry("key", proc_acer_dir); + remove_proc_entry("driver/acerhk", NULL); + retval = 0; + } + else { + entry->write_proc = acerhk_proc_led; + entry->owner = THIS_MODULE; + /* ... and wireless led controll file */ + entry = create_proc_entry("wirelessled", 0222, proc_acer_dir); + if (entry == NULL) { + printk(KERN_INFO"acerhk: cannot create wirelessled file\n"); + remove_proc_entry("info", proc_acer_dir); + remove_proc_entry("key", proc_acer_dir); + remove_proc_entry("led", proc_acer_dir); + remove_proc_entry("driver/acerhk", NULL); + retval = 0; + } + else { + entry->write_proc = acerhk_proc_wirelessled; + entry->owner = THIS_MODULE; + /* ... and bluetooth led controll file */ + entry = create_proc_entry("blueled", 0222, proc_acer_dir); + if (entry == NULL) { + printk(KERN_INFO"acerhk: cannot create blueled file\n"); + remove_proc_entry("info", proc_acer_dir); + remove_proc_entry("key", proc_acer_dir); + remove_proc_entry("led", proc_acer_dir); + remove_proc_entry("wirelessled", proc_acer_dir); + remove_proc_entry("driver/acerhk", NULL); + retval = 0; + } else { + entry->write_proc = acerhk_proc_blueled; + entry->owner = THIS_MODULE; + retval = 1; +#ifdef ACERDEBUG + /* add extra file for debugging purposes */ + entry = create_proc_entry("debug", 0222, proc_acer_dir); + if (entry == NULL) { + printk(KERN_INFO"acerhk: cannot create debug file\n"); + remove_proc_entry("info", proc_acer_dir); + remove_proc_entry("key", proc_acer_dir); + remove_proc_entry("led", proc_acer_dir); + remove_proc_entry("wirelessled", proc_acer_dir); + remove_proc_entry("blueled", proc_acer_dir); + remove_proc_entry("driver/acerhk", NULL); + retval = 0; + } + else { + entry->write_proc = acerhk_proc_debug; + entry->owner = THIS_MODULE; + retval = 1; + } +#endif + } + } + } + } + } + } + return retval; +} + +static void acerhk_proc_cleanup(void) +{ + if (proc_acer_dir) { + remove_proc_entry("info", proc_acer_dir); + /* On dritek type hardware key file is already removed */ + if (acerhk_type != TM_dritek) + remove_proc_entry("key", proc_acer_dir); + remove_proc_entry("led", proc_acer_dir); + remove_proc_entry("wirelessled", proc_acer_dir); + remove_proc_entry("blueled", proc_acer_dir); +#ifdef ACERDEBUG + remove_proc_entry("debug", proc_acer_dir); +#endif + remove_proc_entry("driver/acerhk", NULL); + proc_acer_dir = NULL; + } +} + +#endif /* CONFIG_PROC_FS */ + +/* }}} */ + +/* {{{ file operations */ + +static int acerhk_ioctl( struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg ) +{ + int retval; + switch( cmd ) { + case ACERHK_GET_KEYCOUNT: + { + char nr; + nr = get_nr_events(); + put_user(nr, (char*)arg); + retval = 0; + break; + } + case ACERHK_GET_KEYID: + { + char id; + id = get_fnkey_event(); + put_user(id, (char*)arg); + retval = 0; + break; + } + case ACERHK_CONNECT: + launch_connect(1); + retval = 0; + break; + case ACERHK_START_POLLING: + start_polling(); + retval = 0; + break; + case ACERHK_STOP_POLLING: + stop_polling(); + retval = 0; + break; + case ACERHK_DISCONNECT: + launch_connect(0); + retval = 0; + break; + case ACERHK_GET_THERMAL_EVENT: + { + short event; + event = get_thermal_event(); + put_user(event, (short*)arg); + retval = 0; + break; + } + case ACERHK_MAIL_LED_OFF: + set_mail_led(0); + retval = 0; + break; + case ACERHK_MAIL_LED_ON: + set_mail_led(1); + retval = 0; + break; + case ACERHK_GET_KEY_MAP: + if (copy_to_user((t_map_name2event*)arg, &acerhk_name2event, sizeof(acerhk_name2event))) + retval = -EFAULT; + else + retval = 0; + break; + case ACERHK_SET_KEY_MAP: + if (copy_from_user(&acerhk_name2event, (t_map_name2event*)arg, sizeof(acerhk_name2event))) + retval = -EFAULT; + else { + if (verbose) { + printk(KERN_INFO"acerhk: changed key mapping\n"); + print_mapping(); + } + retval = 0; + } + break; + default: + retval = -EINVAL; + } + return retval; +} + +#ifdef ACERDEBUG +static ssize_t acerhk_write (struct file* file, const char* buffer, size_t length, loff_t* offset) +{ + if (length) + do_debug(buffer, length); + return length; +} +#endif + +static int acerhk_open( struct inode *inode, struct file *file ) +{ + return 0; +} + +static int acerhk_release( struct inode *inode, struct file *file ) +{ + return 0; +} + +static struct file_operations acerhk_fops = { + owner: THIS_MODULE, + ioctl: acerhk_ioctl, + open: acerhk_open, +#ifdef ACERDEBUG + write: acerhk_write, +#endif + release: acerhk_release, +}; + +static struct miscdevice acerhk_dev = { + MISC_DYNAMIC_MINOR, + "acerhk", + &acerhk_fops +}; + +/* }}} */ + +static void __init model_init(void) +{ + /* set callroutine, features and keymap for model */ + setup_model_features(acerhk_series); + /* override initial state of wireless hardware if specified by module options */ + if (wlan_state >= 0) acerhk_wlan_state = wlan_state; + if (bluetooth_state >= 0) acerhk_bluetooth_state = bluetooth_state; + /* Launch connect only if available */ + if (acerhk_model_features & TM_F_CONNECT) { + if (verbose) + printk(KERN_INFO"acerhk: Model type %d, calling launch_connect(1)\n", + acerhk_type); + launch_connect(1); + } + if ( acerhk_type != TM_dritek ) { + get_cmos_index(); + } + if ( acerhk_type == TM_dritek ) { + enable_dritek_keyboard(); + } + /* added by Antonio Cuni */ + init_timer(&acerhk_timer_blinking); +} + + +static void __exit acerhk_cleanup_module (void); +static int __init acerhk_init(void) +{ + int ret; + + ret = misc_register( &acerhk_dev ); + if (ret) { + printk(KERN_ERR "acerhk: can't misc_register on minor=%d\n", ACERHK_MINOR); + ret = -EAGAIN; + } + else if (!acerhk_proc_init()) { + printk(KERN_ERR "acerhk: can't create procfs entries\n"); + ret = -ENOMEM; + misc_deregister( &acerhk_dev ); + } + else { + reg1 = ioremap(0xf0000, 0xffff); + if (verbose > 1) + printk(KERN_INFO"acerhk: area from 0xf000 to 0xffff mapped to %p\n", reg1); + reg2 = ioremap(0xe0000, 0xffff); + if (verbose > 1) + printk(KERN_INFO"acerhk: area from 0xe000 to 0xffff mapped to %p\n", reg2); + /* the area 0x400 is used as data area by earlier (520) series */ + preg400 = ioremap(0x400, 0xfff); + if (verbose > 1) + printk(KERN_INFO"acerhk: area from 0x400 to 0x13ff mapped to %p\n", preg400); + /* attach to input system */ + init_input(); + memset(acerhk_model_string, 0x00, ACERHK_MODEL_STRLEN); +#ifdef DUMMYHW + acerhk_model_addr = (void*)0x12345678; + /* copy the string, but not more than 15 characters */ + strncpy(acerhk_model_string, "TravelmateDummy", ACERHK_MODEL_STRLEN-1); + /* set callroutine for model */ + if (force_series) + acerhk_series = force_series; + else + acerhk_series = 2000; + setup_model_features(acerhk_series); + printk(KERN_INFO "Acer Travelmate hotkey driver v" ACERHK_VERSION " dummy\n"); + if ( acerhk_type == TM_dritek ) + enable_dritek_keyboard(); + if (poll) + start_polling(); + init_timer(&acerhk_timer_blinking); +#else + bios_routine = find_hk_area(); + if (!force_series) + probe_model(); + else { + if (verbose) + printk(KERN_INFO"acerhk: forced laptop series to %d\n", force_series); + acerhk_series = force_series; + } + /* do model specific initialization */ + model_init(); + /* Without a bios routine we cannot do anything except on dritek + type HW, unload on other types */ + if (bios_routine || (acerhk_type == TM_dritek)) { + ret = 0; + if (verbose && bios_routine) + printk(KERN_INFO"acerhk: bios routine found at 0x%x\n", bios_routine); + printk(KERN_INFO "Acer Travelmate hotkey driver v" ACERHK_VERSION "\n"); + /* If automatic switching of wlan is wanted but polling is disabled, + automatically enable it */ + if (!poll && autowlan) { + printk(KERN_INFO "Automatic switching of wireless hardware needs polling, enabling it\n"); + poll = 1; + } + /* start automatic polling of key presses if wanted and bios routine found */ + if (poll && bios_routine) + start_polling(); + } else { + printk(KERN_ERR "acerhk: can't find bios routine, cannot do anything for you, sorry!\n"); + ret = -ENOMEM; + acerhk_cleanup_module(); + } +#endif + } + return ret; +} + +static void __exit acerhk_cleanup_module (void) +{ + acerhk_proc_cleanup(); + stop_blinking(); + if (reg1) + iounmap(reg1); + if (reg2) + iounmap(reg2); + if (preg400) + iounmap(preg400); + release_input(); + misc_deregister( &acerhk_dev ); + if ( acerhk_type == TM_dritek ) { + disable_dritek_keyboard(); + } + if (verbose > 2) + printk(KERN_INFO "acerhk: unloaded\n"); +} + +module_init(acerhk_init); +module_exit(acerhk_cleanup_module); + +MODULE_AUTHOR("Olaf Tauber"); +MODULE_DESCRIPTION("AcerHotkeys extra buttons keyboard driver"); +MODULE_LICENSE("GPL"); + +#ifndef KERNEL26 +EXPORT_NO_SYMBOLS; +#endif + +#else +#error This driver is only available for X86 architecture +#endif +/* + * Local variables: + * c-indent-level: 4 + * tab-width: 4 + * End: + */ + --- linux-2.6.27.orig/ubuntu/misc/Makefile +++ linux-2.6.27/ubuntu/misc/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for Ubuntu additional drivers +# + +obj-$(CONFIG_USB_APPLEIR) += appleir.o +obj-$(CONFIG_BLK_DEV_DM_BBR) += dm-bbr.o +obj-$(CONFIG_INPUT_ACERHK) += acerhk.o +obj-$(CONFIG_LMPCM_USB) += lmpcm_usb.o +obj-$(CONFIG_TP_SMAPI) += tp_smapi.o +obj-$(CONFIG_TP_SMAPI_EC) += thinkpad_ec.o +obj-$(CONFIG_FSAM7400) += fsam7400.o + +obj-m += media/ wireless/ + +CFLAGS_dm-bbr.o += -I$(srctree)/drivers/md --- linux-2.6.27.orig/ubuntu/misc/wireless/Kconfig +++ linux-2.6.27/ubuntu/misc/wireless/Kconfig @@ -0,0 +1,24 @@ +menu "Wireless Drivers" + +config WIRELESS_ACX + tristate "TI ACX1xx based wireless cards (CardBus/PCI/USB)" + default m + depends on NET && IEEE80211 + +config P80211 + tristate + default n + depends on NET + +config PRISM2_USB + tristate "Prism2 based USB devices" + default m + depends on NET + select P80211 + +config WIRELESS_AT76 + tristate "Wireless devices based on Atmel AT76C503A/505/505A" + default m + depends on NET && IEEE80211 + +endmenu --- linux-2.6.27.orig/ubuntu/misc/wireless/Makefile +++ linux-2.6.27/ubuntu/misc/wireless/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for Ubuntu additional drivers +# + +obj-$(CONFIG_WIRELESS_ACX) += acx/ +obj-$(CONFIG_P80211) += p80211/ +obj-$(CONFIG_PRISM2_USB) += prism2_usb/ +obj-$(CONFIG_WIRELESS_AT76) += at76/ --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/hfa384x_usb.c +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/hfa384x_usb.c @@ -0,0 +1,5068 @@ +/* src/prism2/driver/hfa384x_usb.c +* +* Functions that talk to the USB variantof the Intersil hfa384x MAC +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file implements functions that correspond to the prism2/hfa384x +* 802.11 MAC hardware and firmware host interface. +* +* The functions can be considered to represent several levels of +* abstraction. The lowest level functions are simply C-callable wrappers +* around the register accesses. The next higher level represents C-callable +* prism2 API functions that match the Intersil documentation as closely +* as is reasonable. The next higher layer implements common sequences +* of invokations of the API layer (e.g. write to bap, followed by cmd). +* +* Common sequences: +* hfa384x_drvr_xxx Highest level abstractions provided by the +* hfa384x code. They are driver defined wrappers +* for common sequences. These functions generally +* use the services of the lower levels. +* +* hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These +* functions are wrappers for the RID get/set +* sequence. They call copy_[to|from]_bap() and +* cmd_access(). These functions operate on the +* RIDs and buffers without validation. The caller +* is responsible for that. +* +* API wrapper functions: +* hfa384x_cmd_xxx functions that provide access to the f/w commands. +* The function arguments correspond to each command +* argument, even command arguments that get packed +* into single registers. These functions _just_ +* issue the command by setting the cmd/parm regs +* & reading the status/resp regs. Additional +* activities required to fully use a command +* (read/write from/to bap, get/set int status etc.) +* are implemented separately. Think of these as +* C-callable prism2 commands. +* +* Lowest Layer Functions: +* hfa384x_docmd_xxx These functions implement the sequence required +* to issue any prism2 command. Primarily used by the +* hfa384x_cmd_xxx functions. +* +* hfa384x_bap_xxx BAP read/write access functions. +* Note: we usually use BAP0 for non-interrupt context +* and BAP1 for interrupt context. +* +* hfa384x_dl_xxx download related functions. +* +* Driver State Issues: +* Note that there are two pairs of functions that manage the +* 'initialized' and 'running' states of the hw/MAC combo. The four +* functions are create(), destroy(), start(), and stop(). create() +* sets up the data structures required to support the hfa384x_* +* functions and destroy() cleans them up. The start() function gets +* the actual hardware running and enables the interrupts. The stop() +* function shuts the hardware down. The sequence should be: +* create() +* start() +* . +* . Do interesting things w/ the hardware +* . +* stop() +* destroy() +* +* Note that destroy() can be called without calling stop() first. +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if (WLAN_HOSTIF != WLAN_USB) +#error "This file is specific to USB" +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +static int +wait_for_completion_interruptible(struct completion *x) +{ + int ret = 0; + + might_sleep(); + + spin_lock_irq(&x->wait.lock); + if (!x->done) { + DECLARE_WAITQUEUE(wait, current); + + wait.flags |= WQ_FLAG_EXCLUSIVE; + __add_wait_queue_tail(&x->wait, &wait); + do { + if (signal_pending(current)) { + ret = -ERESTARTSYS; + __remove_wait_queue(&x->wait, &wait); + goto out; + } + __set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(&x->wait.lock); + schedule(); + spin_lock_irq(&x->wait.lock); + } while (!x->done); + __remove_wait_queue(&x->wait, &wait); + } + x->done--; +out: + spin_unlock_irq(&x->wait.lock); + + return ret; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69) +static void +usb_init_urb(struct urb *urb) +{ + memset(urb, 0, sizeof(*urb)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */ + urb->count = (atomic_t)ATOMIC_INIT(1); +#endif + spin_lock_init(&urb->lock); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */ +# define SUBMIT_URB(u,f) usb_submit_urb(u,f) +#else +# define SUBMIT_URB(u,f) usb_submit_urb(u) +#endif + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + +enum cmd_mode +{ + DOWAIT = 0, + DOASYNC +}; +typedef enum cmd_mode CMD_MODE; + +#define THROTTLE_JIFFIES (HZ/8) + +/*================================================================*/ +/* Local Macros */ + +#define ROUNDUP64(a) (((a)+63)&~63) + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ +extern int prism2_debug; + +/*================================================================*/ +/* Local Function Declarations */ + +#ifdef DEBUG_USB +static void +dbprint_urb(struct urb* urb); +#endif + +static void +hfa384x_int_rxmonitor( + wlandevice_t *wlandev, + hfa384x_usb_rxfrm_t *rxfrm); + +static void +hfa384x_usb_defer(struct work_struct *data); + +static int +submit_rx_urb(hfa384x_t *hw, gfp_t flags); + +static int +submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t flags); + +/*---------------------------------------------------*/ +/* Callbacks */ +#ifdef URB_ONLY_CALLBACK +static void +hfa384x_usbout_callback(struct urb *urb); +static void +hfa384x_ctlxout_callback(struct urb *urb); +static void +hfa384x_usbin_callback(struct urb *urb); +#else +static void +hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs); +static void +hfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs); +static void +hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs); +#endif + +static void +hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); + +static void +hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb); + +static void +hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); + +static void +hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout); + +static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, + int urb_status); + +/*---------------------------------------------------*/ +/* Functions to support the prism2 usb command queue */ + +static void +hfa384x_usbctlxq_run(hfa384x_t *hw); + +static void +hfa384x_usbctlx_reqtimerfn(unsigned long data); + +static void +hfa384x_usbctlx_resptimerfn(unsigned long data); + +static void +hfa384x_usb_throttlefn(unsigned long data); + +static void +hfa384x_usbctlx_completion_task(unsigned long data); + +static void +hfa384x_usbctlx_reaper_task(unsigned long data); + +static int +hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); + +static void +unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); + +struct usbctlx_completor +{ + int (*complete)(struct usbctlx_completor*); +}; +typedef struct usbctlx_completor usbctlx_completor_t; + +static int +hfa384x_usbctlx_complete_sync(hfa384x_t *hw, + hfa384x_usbctlx_t *ctlx, + usbctlx_completor_t *completor); + +static int +unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); + +static void +hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); + +static void +hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); + +static int +usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, + hfa384x_cmdresult_t *result); + +static void +usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, + hfa384x_rridresult_t *result); + +/*---------------------------------------------------*/ +/* Low level req/resp CTLX formatters and submitters */ +static int +hfa384x_docmd( + hfa384x_t *hw, + CMD_MODE mode, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dorrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dowrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dormem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dowmem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_isgood_pdrcode(UINT16 pdrcode); + +/*================================================================*/ +/* Function Definitions */ +static inline const char* ctlxstr(CTLX_STATE s) +{ + static const char* ctlx_str[] = { + "Initial state", + "Complete", + "Request failed", + "Request pending", + "Request packet submitted", + "Request packet completed", + "Response packet completed" + }; + + return ctlx_str[s]; +}; + + +static inline hfa384x_usbctlx_t* +get_active_ctlx(hfa384x_t *hw) +{ + return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list); +} + + +#ifdef DEBUG_USB +void +dbprint_urb(struct urb* urb) +{ + WLAN_LOG_DEBUG(3,"urb->pipe=0x%08x\n", urb->pipe); + WLAN_LOG_DEBUG(3,"urb->status=0x%08x\n", urb->status); + WLAN_LOG_DEBUG(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags); + WLAN_LOG_DEBUG(3,"urb->transfer_buffer=0x%08x\n", (UINT)urb->transfer_buffer); + WLAN_LOG_DEBUG(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length); + WLAN_LOG_DEBUG(3,"urb->actual_length=0x%08x\n", urb->actual_length); + WLAN_LOG_DEBUG(3,"urb->bandwidth=0x%08x\n", urb->bandwidth); + WLAN_LOG_DEBUG(3,"urb->setup_packet(ctl)=0x%08x\n", (UINT)urb->setup_packet); + WLAN_LOG_DEBUG(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame); + WLAN_LOG_DEBUG(3,"urb->interval(irq)=0x%08x\n", urb->interval); + WLAN_LOG_DEBUG(3,"urb->error_count(iso)=0x%08x\n", urb->error_count); + WLAN_LOG_DEBUG(3,"urb->timeout=0x%08x\n", urb->timeout); + WLAN_LOG_DEBUG(3,"urb->context=0x%08x\n", (UINT)urb->context); + WLAN_LOG_DEBUG(3,"urb->complete=0x%08x\n", (UINT)urb->complete); +} +#endif + + +/*---------------------------------------------------------------- +* submit_rx_urb +* +* Listen for input data on the BULK-IN pipe. If the pipe has +* stalled then schedule it to be reset. +* +* Arguments: +* hw device struct +* memflags memory allocation flags +* +* Returns: +* error code from submission +* +* Call context: +* Any +----------------------------------------------------------------*/ +static int +submit_rx_urb(hfa384x_t *hw, gfp_t memflags) +{ + struct sk_buff *skb; + int result; + + DBFENTER; + + skb = dev_alloc_skb(sizeof(hfa384x_usbin_t)); + if (skb == NULL) { + result = -ENOMEM; + goto done; + } + + /* Post the IN urb */ + usb_fill_bulk_urb(&hw->rx_urb, hw->usb, + hw->endp_in, + skb->data, sizeof(hfa384x_usbin_t), + hfa384x_usbin_callback, hw->wlandev); + + hw->rx_urb_skb = skb; + + result = -ENOLINK; + if ( !hw->wlandev->hwremoved && !test_bit(WORK_RX_HALT, &hw->usb_flags)) { + result = SUBMIT_URB(&hw->rx_urb, memflags); + + /* Check whether we need to reset the RX pipe */ + if (result == -EPIPE) { + WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); + if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) + schedule_work(&hw->usb_work); + } + } + + /* Don't leak memory if anything should go wrong */ + if (result != 0) { + dev_kfree_skb(skb); + hw->rx_urb_skb = NULL; + } + + done: + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* submit_tx_urb +* +* Prepares and submits the URB of transmitted data. If the +* submission fails then it will schedule the output pipe to +* be reset. +* +* Arguments: +* hw device struct +* tx_urb URB of data for tranmission +* memflags memory allocation flags +* +* Returns: +* error code from submission +* +* Call context: +* Any +----------------------------------------------------------------*/ +static int +submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) +{ + struct net_device *netdev = hw->wlandev->netdev; + int result; + + DBFENTER; + + result = -ENOLINK; + if ( netif_running(netdev) ) { + + if ( !hw->wlandev->hwremoved && !test_bit(WORK_TX_HALT, &hw->usb_flags) ) { + result = SUBMIT_URB(tx_urb, memflags); + + /* Test whether we need to reset the TX pipe */ + if (result == -EPIPE) { + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + netdev->name); + set_bit(WORK_TX_HALT, &hw->usb_flags); + schedule_work(&hw->usb_work); + } else if (result == 0) { + netif_stop_queue(netdev); + } + } + } + + DBFEXIT; + + return result; +} + +/*---------------------------------------------------------------- +* hfa394x_usb_defer +* +* There are some things that the USB stack cannot do while +* in interrupt context, so we arrange this function to run +* in process context. +* +* Arguments: +* hw device structure +* +* Returns: +* nothing +* +* Call context: +* process (by design) +----------------------------------------------------------------*/ +static void +hfa384x_usb_defer(struct work_struct *data) +{ + hfa384x_t *hw = container_of(data, struct hfa384x, usb_work); + struct net_device *netdev = hw->wlandev->netdev; + + DBFENTER; + + /* Don't bother trying to reset anything if the plug + * has been pulled ... + */ + if ( hw->wlandev->hwremoved ) { + DBFEXIT; + return; + } + + /* Reception has stopped: try to reset the input pipe */ + if (test_bit(WORK_RX_HALT, &hw->usb_flags)) { + int ret; + + usb_kill_urb(&hw->rx_urb); /* Cannot be holding spinlock! */ + + ret = usb_clear_halt(hw->usb, hw->endp_in); + if (ret != 0) { + printk(KERN_ERR + "Failed to clear rx pipe for %s: err=%d\n", + netdev->name, ret); + } else { + printk(KERN_INFO "%s rx pipe reset complete.\n", + netdev->name); + clear_bit(WORK_RX_HALT, &hw->usb_flags); + set_bit(WORK_RX_RESUME, &hw->usb_flags); + } + } + + /* Resume receiving data back from the device. */ + if ( test_bit(WORK_RX_RESUME, &hw->usb_flags) ) { + int ret; + + ret = submit_rx_urb(hw, GFP_KERNEL); + if (ret != 0) { + printk(KERN_ERR + "Failed to resume %s rx pipe.\n", netdev->name); + } else { + clear_bit(WORK_RX_RESUME, &hw->usb_flags); + } + } + + /* Transmission has stopped: try to reset the output pipe */ + if (test_bit(WORK_TX_HALT, &hw->usb_flags)) { + int ret; + + usb_kill_urb(&hw->tx_urb); + ret = usb_clear_halt(hw->usb, hw->endp_out); + if (ret != 0) { + printk(KERN_ERR + "Failed to clear tx pipe for %s: err=%d\n", + netdev->name, ret); + } else { + printk(KERN_INFO "%s tx pipe reset complete.\n", + netdev->name); + clear_bit(WORK_TX_HALT, &hw->usb_flags); + set_bit(WORK_TX_RESUME, &hw->usb_flags); + + /* Stopping the BULK-OUT pipe also blocked + * us from sending any more CTLX URBs, so + * we need to re-run our queue ... + */ + hfa384x_usbctlxq_run(hw); + } + } + + /* Resume transmitting. */ + if ( test_and_clear_bit(WORK_TX_RESUME, &hw->usb_flags) ) { + p80211netdev_wake_queue(hw->wlandev); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_create +* +* Sets up the hfa384x_t data structure for use. Note this +* does _not_ intialize the actual hardware, just the data structures +* we use to keep track of its state. +* +* Arguments: +* hw device structure +* irq device irq number +* iobase i/o base address for register access +* membase memory base address for register access +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +void +hfa384x_create( hfa384x_t *hw, struct usb_device *usb) +{ + DBFENTER; + + memset(hw, 0, sizeof(hfa384x_t)); + hw->usb = usb; + + /* set up the endpoints */ + hw->endp_in = usb_rcvbulkpipe(usb, 1); + hw->endp_out = usb_sndbulkpipe(usb, 2); + + /* Set up the waitq */ + init_waitqueue_head(&hw->cmdq); + + /* Initialize the command queue */ + spin_lock_init(&hw->ctlxq.lock); + INIT_LIST_HEAD(&hw->ctlxq.pending); + INIT_LIST_HEAD(&hw->ctlxq.active); + INIT_LIST_HEAD(&hw->ctlxq.completing); + INIT_LIST_HEAD(&hw->ctlxq.reapable); + + /* Initialize the authentication queue */ + skb_queue_head_init(&hw->authq); + + tasklet_init(&hw->reaper_bh, + hfa384x_usbctlx_reaper_task, + (unsigned long)hw); + tasklet_init(&hw->completion_bh, + hfa384x_usbctlx_completion_task, + (unsigned long)hw); + INIT_WORK2(&hw->link_bh, prism2sta_processing_defer); + INIT_WORK2(&hw->usb_work, hfa384x_usb_defer); + + init_timer(&hw->throttle); + hw->throttle.function = hfa384x_usb_throttlefn; + hw->throttle.data = (unsigned long)hw; + + init_timer(&hw->resptimer); + hw->resptimer.function = hfa384x_usbctlx_resptimerfn; + hw->resptimer.data = (unsigned long)hw; + + init_timer(&hw->reqtimer); + hw->reqtimer.function = hfa384x_usbctlx_reqtimerfn; + hw->reqtimer.data = (unsigned long)hw; + + usb_init_urb(&hw->rx_urb); + usb_init_urb(&hw->tx_urb); + usb_init_urb(&hw->ctlx_urb); + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + INIT_WORK2(&hw->commsqual_bh, prism2sta_commsqual_defer); + init_timer(&hw->commsqual_timer); + hw->commsqual_timer.data = (unsigned long) hw; + hw->commsqual_timer.function = prism2sta_commsqual_timer; + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_destroy +* +* Partner to hfa384x_create(). This function cleans up the hw +* structure so that it can be freed by the caller using a simple +* kfree. Currently, this function is just a placeholder. If, at some +* point in the future, an hw in the 'shutdown' state requires a 'deep' +* kfree, this is where it should be done. Note that if this function +* is called on a _running_ hw structure, the drvr_stop() function is +* called. +* +* Arguments: +* hw device structure +* +* Returns: +* nothing, this function is not allowed to fail. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +void +hfa384x_destroy( hfa384x_t *hw) +{ + struct sk_buff *skb; + + DBFENTER; + + if ( hw->state == HFA384x_STATE_RUNNING ) { + hfa384x_drvr_stop(hw); + } + hw->state = HFA384x_STATE_PREINIT; + + if (hw->scanresults) { + kfree(hw->scanresults); + hw->scanresults = NULL; + } + + /* Now to clean out the auth queue */ + while ( (skb = skb_dequeue(&hw->authq)) ) { + dev_kfree_skb(skb); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- + */ +static hfa384x_usbctlx_t* usbctlx_alloc(void) +{ + hfa384x_usbctlx_t *ctlx; + + ctlx = kmalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (ctlx != NULL) + { + memset(ctlx, 0, sizeof(*ctlx)); + init_completion(&ctlx->done); + } + + return ctlx; +} + + +/*---------------------------------------------------------------- + * +----------------------------------------------------------------*/ +static int +usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, + hfa384x_cmdresult_t *result) +{ + DBFENTER; + + result->status = hfa384x2host_16(cmdresp->status); + result->resp0 = hfa384x2host_16(cmdresp->resp0); + result->resp1 = hfa384x2host_16(cmdresp->resp1); + result->resp2 = hfa384x2host_16(cmdresp->resp2); + + WLAN_LOG_DEBUG(4, "cmdresult:status=0x%04x " + "resp0=0x%04x resp1=0x%04x resp2=0x%04x\n", + result->status, + result->resp0, + result->resp1, + result->resp2); + + DBFEXIT; + return (result->status & HFA384x_STATUS_RESULT); +} + +static void +usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, + hfa384x_rridresult_t *result) +{ + DBFENTER; + + result->rid = hfa384x2host_16(rridresp->rid); + result->riddata = rridresp->data; + result->riddata_len = ((hfa384x2host_16(rridresp->frmlen) - 1) * 2); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* Completor object: +* This completor must be passed to hfa384x_usbctlx_complete_sync() +* when processing a CTLX that returns a hfa384x_cmdresult_t structure. +----------------------------------------------------------------*/ +struct usbctlx_cmd_completor +{ + usbctlx_completor_t head; + + const hfa384x_usb_cmdresp_t *cmdresp; + hfa384x_cmdresult_t *result; +}; +typedef struct usbctlx_cmd_completor usbctlx_cmd_completor_t; + +static int usbctlx_cmd_completor_fn(usbctlx_completor_t *head) +{ + usbctlx_cmd_completor_t *complete = (usbctlx_cmd_completor_t*)head; + return usbctlx_get_status(complete->cmdresp, complete->result); +} + +static inline usbctlx_completor_t* +init_cmd_completor(usbctlx_cmd_completor_t *completor, + const hfa384x_usb_cmdresp_t *cmdresp, + hfa384x_cmdresult_t *result) +{ + completor->head.complete = usbctlx_cmd_completor_fn; + completor->cmdresp = cmdresp; + completor->result = result; + return &(completor->head); +} + +/*---------------------------------------------------------------- +* Completor object: +* This completor must be passed to hfa384x_usbctlx_complete_sync() +* when processing a CTLX that reads a RID. +----------------------------------------------------------------*/ +struct usbctlx_rrid_completor +{ + usbctlx_completor_t head; + + const hfa384x_usb_rridresp_t *rridresp; + void *riddata; + UINT riddatalen; +}; +typedef struct usbctlx_rrid_completor usbctlx_rrid_completor_t; + +static int usbctlx_rrid_completor_fn(usbctlx_completor_t *head) +{ + usbctlx_rrid_completor_t *complete = (usbctlx_rrid_completor_t*)head; + hfa384x_rridresult_t rridresult; + + usbctlx_get_rridresult(complete->rridresp, &rridresult); + + /* Validate the length, note body len calculation in bytes */ + if ( rridresult.riddata_len != complete->riddatalen ) { + WLAN_LOG_WARNING( + "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", + rridresult.rid, + complete->riddatalen, + rridresult.riddata_len); + return -ENODATA; + } + + memcpy(complete->riddata, + rridresult.riddata, + complete->riddatalen); + return 0; +} + +static inline usbctlx_completor_t* +init_rrid_completor(usbctlx_rrid_completor_t *completor, + const hfa384x_usb_rridresp_t *rridresp, + void *riddata, + UINT riddatalen) +{ + completor->head.complete = usbctlx_rrid_completor_fn; + completor->rridresp = rridresp; + completor->riddata = riddata; + completor->riddatalen = riddatalen; + return &(completor->head); +} + +/*---------------------------------------------------------------- +* Completor object: +* Interprets the results of a synchronous RID-write +----------------------------------------------------------------*/ +typedef usbctlx_cmd_completor_t usbctlx_wrid_completor_t; +#define init_wrid_completor init_cmd_completor + +/*---------------------------------------------------------------- +* Completor object: +* Interprets the results of a synchronous memory-write +----------------------------------------------------------------*/ +typedef usbctlx_cmd_completor_t usbctlx_wmem_completor_t; +#define init_wmem_completor init_cmd_completor + +/*---------------------------------------------------------------- +* Completor object: +* Interprets the results of a synchronous memory-read +----------------------------------------------------------------*/ +struct usbctlx_rmem_completor +{ + usbctlx_completor_t head; + + const hfa384x_usb_rmemresp_t *rmemresp; + void *data; + UINT len; +}; +typedef struct usbctlx_rmem_completor usbctlx_rmem_completor_t; + +static int usbctlx_rmem_completor_fn(usbctlx_completor_t *head) +{ + usbctlx_rmem_completor_t *complete = (usbctlx_rmem_completor_t*)head; + + WLAN_LOG_DEBUG(4,"rmemresp:len=%d\n", complete->rmemresp->frmlen); + memcpy(complete->data, complete->rmemresp->data, complete->len); + return 0; +} + +static inline usbctlx_completor_t* +init_rmem_completor(usbctlx_rmem_completor_t *completor, + hfa384x_usb_rmemresp_t *rmemresp, + void *data, + UINT len) +{ + completor->head.complete = usbctlx_rmem_completor_fn; + completor->rmemresp = rmemresp; + completor->data = data; + completor->len = len; + return &(completor->head); +} + +/*---------------------------------------------------------------- +* hfa384x_cb_status +* +* Ctlx_complete handler for async CMD type control exchanges. +* mark the hw struct as such. +* +* Note: If the handling is changed here, it should probably be +* changed in docmd as well. +* +* Arguments: +* hw hw struct +* ctlx completed CTLX +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +{ + DBFENTER; + + if ( ctlx->usercb != NULL ) { + hfa384x_cmdresult_t cmdresult; + + if (ctlx->state != CTLX_COMPLETE) { + memset(&cmdresult, 0, sizeof(cmdresult)); + cmdresult.status = HFA384x_STATUS_RESULT_SET(HFA384x_CMD_ERR); + } else { + usbctlx_get_status(&ctlx->inbuf.cmdresp, &cmdresult); + } + + ctlx->usercb(hw, &cmdresult, ctlx->usercb_data); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_cb_rrid +* +* CTLX completion handler for async RRID type control exchanges. +* +* Note: If the handling is changed here, it should probably be +* changed in dorrid as well. +* +* Arguments: +* hw hw struct +* ctlx completed CTLX +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +{ + DBFENTER; + + if ( ctlx->usercb != NULL ) { + hfa384x_rridresult_t rridresult; + + if (ctlx->state != CTLX_COMPLETE) { + memset(&rridresult, 0, sizeof(rridresult)); + rridresult.rid = hfa384x2host_16(ctlx->outbuf.rridreq.rid); + } else { + usbctlx_get_rridresult(&ctlx->inbuf.rridresp, &rridresult); + } + + ctlx->usercb(hw, &rridresult, ctlx->usercb_data); + } + + DBFEXIT; +} + +static inline int +hfa384x_docmd_wait(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); +} + +static inline int +hfa384x_docmd_async(hfa384x_t *hw, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_docmd(hw, DOASYNC, cmd, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dorrid_wait(hfa384x_t *hw, UINT16 rid, void *riddata, UINT riddatalen) +{ + return hfa384x_dorrid(hw, DOWAIT, + rid, riddata, riddatalen, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dorrid_async(hfa384x_t *hw, + UINT16 rid, void *riddata, UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dorrid(hw, DOASYNC, + rid, riddata, riddatalen, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dowrid_wait(hfa384x_t *hw, UINT16 rid, void *riddata, UINT riddatalen) +{ + return hfa384x_dowrid(hw, DOWAIT, + rid, riddata, riddatalen, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dowrid_async(hfa384x_t *hw, + UINT16 rid, void *riddata, UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dowrid(hw, DOASYNC, + rid, riddata, riddatalen, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dormem_wait(hfa384x_t *hw, + UINT16 page, UINT16 offset, void *data, UINT len) +{ + return hfa384x_dormem(hw, DOWAIT, + page, offset, data, len, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dormem_async(hfa384x_t *hw, + UINT16 page, UINT16 offset, void *data, UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dormem(hw, DOASYNC, + page, offset, data, len, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dowmem_wait( + hfa384x_t *hw, + UINT16 page, + UINT16 offset, + void *data, + UINT len) +{ + return hfa384x_dowmem(hw, DOWAIT, + page, offset, data, len, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dowmem_async( + hfa384x_t *hw, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dowmem(hw, DOASYNC, + page, offset, data, len, + cmdcb, usercb, usercb_data); +} + +/*---------------------------------------------------------------- +* hfa384x_cmd_initialize +* +* Issues the initialize command and sets the hw->state based +* on the result. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_cmd_initialize(hfa384x_t *hw) +{ + int result = 0; + int i; + hfa384x_metacmd_t cmd; + + DBFENTER; + + + cmd.cmd = HFA384x_CMDCODE_INIT; + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + + WLAN_LOG_DEBUG(3,"cmdresp.init: " + "status=0x%04x, resp0=0x%04x, " + "resp1=0x%04x, resp2=0x%04x\n", + cmd.result.status, + cmd.result.resp0, + cmd.result.resp1, + cmd.result.resp2); + if ( result == 0 ) { + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + } + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_disable +* +* Issues the disable command to stop communications on one of +* the MACs 'ports'. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_enable +* +* Issues the enable command to enable communications on one of +* the MACs 'ports'. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_notify +* +* Sends an info frame to the firmware to alter the behavior +* of the f/w asynch processes. Can only be called when the MAC +* is in the enabled state. +* +* Arguments: +* hw device structure +* reclaim [0|1] indicates whether the given FID will +* be handed back (via Alloc event) for reuse. +* (host order) +* fid FID of buffer containing the frame that was +* previously copied to MAC memory via the bap. +* (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* hw->resp0 will contain the FID being used by async notify +* process. If reclaim==0, resp0 will be the same as the fid +* argument. If reclaim==1, resp0 will be the different. +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, + void *buf, UINT16 len) +{ +#if 0 + int result = 0; + UINT16 cmd; + DBFENTER; + cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_NOTIFY) | + HFA384x_CMD_RECL_SET(reclaim); + result = hfa384x_docmd_wait(hw, cmd); + + DBFEXIT; + return result; +#endif +return 0; +} + + +#if 0 +/*---------------------------------------------------------------- +* hfa384x_cmd_inquiry +* +* Requests an info frame from the firmware. The info frame will +* be delivered asynchronously via the Info event. +* +* Arguments: +* hw device structure +* fid FID of the info frame requested. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_inquiry(hfa384x_t *hw, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_INQ); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} +#endif + + +/*---------------------------------------------------------------- +* hfa384x_cmd_monitor +* +* Enables the 'monitor mode' of the MAC. Here's the description of +* monitor mode that I've received thus far: +* +* "The "monitor mode" of operation is that the MAC passes all +* frames for which the PLCP checks are correct. All received +* MPDUs are passed to the host with MAC Port = 7, with a +* receive status of good, FCS error, or undecryptable. Passing +* certain MPDUs is a violation of the 802.11 standard, but useful +* for a debugging tool." Normal communication is not possible +* while monitor mode is enabled. +* +* Arguments: +* hw device structure +* enable a code (0x0b|0x0f) that enables/disables +* monitor mode. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | + HFA384x_CMD_AINFO_SET(enable); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_download +* +* Sets the controls for the MAC controller code/data download +* process. The arguments set the mode and address associated +* with a download. Note that the aux registers should be enabled +* prior to setting one of the download enable modes. +* +* Arguments: +* hw device structure +* mode 0 - Disable programming and begin code exec +* 1 - Enable volatile mem programming +* 2 - Enable non-volatile mem programming +* 3 - Program non-volatile section from NV download +* buffer. +* (host order) +* lowaddr +* highaddr For mode 1, sets the high & low order bits of +* the "destination address". This address will be +* the execution start address when download is +* subsequently disabled. +* For mode 2, sets the high & low order bits of +* the destination in NV ram. +* For modes 0 & 3, should be zero. (host order) +* NOTE: these are CMD format. +* codelen Length of the data to write in mode 2, +* zero otherwise. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_download(hfa384x_t *hw, UINT16 mode, UINT16 lowaddr, + UINT16 highaddr, UINT16 codelen) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + WLAN_LOG_DEBUG(5, + "mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n", + mode, lowaddr, highaddr, codelen); + + cmd.cmd = (HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) | + HFA384x_CMD_PROGMODE_SET(mode)); + + cmd.parm0 = lowaddr; + cmd.parm1 = highaddr; + cmd.parm2 = codelen; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_from_aux +* +* Copies a collection of bytes from the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* buf contains the data copied +* +* Call context: +* process +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_from_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + DBFENTER; + WLAN_LOG_ERROR("not used in USB.\n"); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_to_aux +* +* Copies a collection of bytes to the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* Controller memory now contains a copy of buf +* +* Call context: +* process +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_to_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + DBFENTER; + WLAN_LOG_ERROR("not used in USB.\n"); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_corereset +* +* Perform a reset of the hfa38xx MAC core. We assume that the hw +* structure is in its "created" state. That is, it is initialized +* with proper values. Note that if a reset is done after the +* device has been active for awhile, the caller might have to clean +* up some leftover cruft in the hw structure. +* +* Arguments: +* hw device structure +* holdtime how long (in ms) to hold the reset +* settletime how long (in ms) to wait after releasing +* the reset +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) +{ +#if 0 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + struct usb_device *parent = hw->usb->parent; + int i; + int port = -1; +#endif +#endif + int result = 0; + + +#define P2_USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) +#define P2_USB_FEAT_RESET 4 +#define P2_USB_FEAT_C_RESET 20 + + DBFENTER; + +#if 0 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + /* Find the hub port */ + for ( i = 0; i < parent->maxchild; i++) { + if (parent->children[i] == hw->usb) { + port = i; + break; + } + } + if (port < 0) return -ENOENT; + + /* Set and clear the reset */ + usb_control_msg(parent, usb_sndctrlpipe(parent, 0), + USB_REQ_SET_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_RESET, + port+1, NULL, 0, 1*HZ); + wait_ms(holdtime); + usb_control_msg(parent, usb_sndctrlpipe(parent, 0), + USB_REQ_CLEAR_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_C_RESET, + port+1, NULL, 0, 1*HZ); + wait_ms(settletime); + + /* Set the device address */ + result=usb_set_address(hw->usb); + if (result < 0) { + WLAN_LOG_ERROR("reset_usbdev: Dev not accepting address, " + "result=%d\n", result); + clear_bit(hw->usb->devnum, &hw->usb->bus->devmap.devicemap); + hw->usb->devnum = -1; + goto done; + } + /* Let the address settle */ + wait_ms(20); + + /* Assume we're reusing the original descriptor data */ + + /* Set the configuration. */ + WLAN_LOG_DEBUG(3, "Setting Configuration %d\n", + hw->usb->config[0].bConfigurationValue); + result=usb_set_configuration(hw->usb, hw->usb->config[0].bConfigurationValue); + if ( result ) { + WLAN_LOG_ERROR("usb_set_configuration() failed, result=%d.\n", + result); + goto done; + } + /* Let the configuration settle */ + wait_ms(20); + + done: +#else + result=usb_reset_device(hw->usb); + if(result<0) { + WLAN_LOG_ERROR("usb_reset_device() failed, result=%d.\n",result); + } +#endif +#endif + + result=usb_reset_device(hw->usb); + if(result<0) { + WLAN_LOG_ERROR("usb_reset_device() failed, result=%d.\n",result); + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_complete_sync +* +* Waits for a synchronous CTLX object to complete, +* and then handles the response. +* +* Arguments: +* hw device structure +* ctlx CTLX ptr +* completor functor object to decide what to +* do with the CTLX's result. +* +* Returns: +* 0 Success +* -ERESTARTSYS Interrupted by a signal +* -EIO CTLX failed +* -ENODEV Adapter was unplugged +* ??? Result from completor +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, + hfa384x_usbctlx_t *ctlx, + usbctlx_completor_t *completor) +{ + unsigned long flags; + int result; + + DBFENTER; + + result = wait_for_completion_interruptible(&ctlx->done); + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* + * We can only handle the CTLX if the USB disconnect + * function has not run yet ... + */ + cleanup: + if ( hw->wlandev->hwremoved ) + { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + result = -ENODEV; + } + else if ( result != 0 ) + { + int runqueue = 0; + + /* + * We were probably interrupted, so delete + * this CTLX asynchronously, kill the timers + * and the URB, and then start the next + * pending CTLX. + * + * NOTE: We can only delete the timers and + * the URB if this CTLX is active. + */ + if (ctlx == get_active_ctlx(hw)) + { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + del_singleshot_timer_sync(&hw->reqtimer); + del_singleshot_timer_sync(&hw->resptimer); + hw->req_timer_done = 1; + hw->resp_timer_done = 1; + usb_kill_urb(&hw->ctlx_urb); + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + runqueue = 1; + + /* + * This scenario is so unlikely that I'm + * happy with a grubby "goto" solution ... + */ + if ( hw->wlandev->hwremoved ) + goto cleanup; + } + + /* + * The completion task will send this CTLX + * to the reaper the next time it runs. We + * are no longer in a hurry. + */ + ctlx->reapable = 1; + ctlx->state = CTLX_REQ_FAILED; + list_move_tail(&ctlx->list, &hw->ctlxq.completing); + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if (runqueue) + hfa384x_usbctlxq_run(hw); + } else { + if (ctlx->state == CTLX_COMPLETE) { + result = completor->complete(completor); + } else { + WLAN_LOG_WARNING("CTLX[%d] error: state(%s)\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state)); + result = -EIO; + } + + list_del(&ctlx->list); + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + kfree(ctlx); + } + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_docmd +* +* Constructs a command CTLX and submits it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbcmd() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* cmd cmd structure. Includes all arguments and result +* data points. All in host order. in host order +* cmdcb command-specific callback +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls, NULL +* for DOASYNC calls +* +* Returns: +* 0 success +* -EIO CTLX failure +* -ERESTARTSYS Awakened on signal +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* +* Call context: +* process +----------------------------------------------------------------*/ +static int +hfa384x_docmd( + hfa384x_t *hw, + CMD_MODE mode, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.cmdreq.type = host2hfa384x_16(HFA384x_USB_CMDREQ); + ctlx->outbuf.cmdreq.cmd = host2hfa384x_16(cmd->cmd); + ctlx->outbuf.cmdreq.parm0 = host2hfa384x_16(cmd->parm0); + ctlx->outbuf.cmdreq.parm1 = host2hfa384x_16(cmd->parm1); + ctlx->outbuf.cmdreq.parm2 = host2hfa384x_16(cmd->parm2); + + ctlx->outbufsize = sizeof(ctlx->outbuf.cmdreq); + + WLAN_LOG_DEBUG(4, "cmdreq: cmd=0x%04x " + "parm0=0x%04x parm1=0x%04x parm2=0x%04x\n", + cmd->cmd, + cmd->parm0, + cmd->parm1, + cmd->parm2); + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if (mode == DOWAIT) { + usbctlx_cmd_completor_t completor; + + result = hfa384x_usbctlx_complete_sync( + hw, ctlx, init_cmd_completor(&completor, + &ctlx->inbuf.cmdresp, + &cmd->result) ); + } + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_dorrid +* +* Constructs a read rid CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbrrid() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* rid Read RID number (host order) +* riddata Caller supplied buffer that MAC formatted RID.data +* record will be written to for DOWAIT calls. Should +* be NULL for DOASYNC calls. +* riddatalen Buffer length for DOWAIT calls. Zero for DOASYNC calls. +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls, NULL +* for DOWAIT calls +* +* Returns: +* 0 success +* -EIO CTLX failure +* -ERESTARTSYS Awakened on signal +* -ENODATA riddatalen != macdatalen +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOASYNC) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dorrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.rridreq.type = host2hfa384x_16(HFA384x_USB_RRIDREQ); + ctlx->outbuf.rridreq.frmlen = + host2hfa384x_16(sizeof(ctlx->outbuf.rridreq.rid)); + ctlx->outbuf.rridreq.rid = host2hfa384x_16(rid); + + ctlx->outbufsize = sizeof(ctlx->outbuf.rridreq); + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + /* Submit the CTLX */ + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if (mode == DOWAIT) { + usbctlx_rrid_completor_t completor; + + result = hfa384x_usbctlx_complete_sync( + hw, ctlx, init_rrid_completor(&completor, + &ctlx->inbuf.rridresp, + riddata, + riddatalen) ); + } + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_dowrid +* +* Constructs a write rid CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbwrid() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* CMD_MODE DOWAIT or DOASYNC +* rid RID code +* riddata Data portion of RID formatted for MAC +* riddatalen Length of the data portion in bytes +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOASYNC) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dowrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.wridreq.type = host2hfa384x_16(HFA384x_USB_WRIDREQ); + ctlx->outbuf.wridreq.frmlen = host2hfa384x_16( + (sizeof(ctlx->outbuf.wridreq.rid) + + riddatalen + 1) / 2); + ctlx->outbuf.wridreq.rid = host2hfa384x_16(rid); + memcpy(ctlx->outbuf.wridreq.data, riddata, riddatalen); + + ctlx->outbufsize = sizeof(ctlx->outbuf.wridreq.type) + + sizeof(ctlx->outbuf.wridreq.frmlen) + + sizeof(ctlx->outbuf.wridreq.rid) + + riddatalen; + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + /* Submit the CTLX */ + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if (mode == DOWAIT) { + usbctlx_wrid_completor_t completor; + hfa384x_cmdresult_t wridresult; + + result = hfa384x_usbctlx_complete_sync( + hw, + ctlx, + init_wrid_completor(&completor, + &ctlx->inbuf.wridresp, + &wridresult) ); + } + +done: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_dormem +* +* Constructs a readmem CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbrmem() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* page MAC address space page (CMD format) +* offset MAC address space offset +* data Ptr to data buffer to receive read +* len Length of the data to read (max == 2048) +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOASYNC) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dormem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.rmemreq.type = host2hfa384x_16(HFA384x_USB_RMEMREQ); + ctlx->outbuf.rmemreq.frmlen = host2hfa384x_16( + sizeof(ctlx->outbuf.rmemreq.offset) + + sizeof(ctlx->outbuf.rmemreq.page) + + len); + ctlx->outbuf.rmemreq.offset = host2hfa384x_16(offset); + ctlx->outbuf.rmemreq.page = host2hfa384x_16(page); + + ctlx->outbufsize = sizeof(ctlx->outbuf.rmemreq); + + WLAN_LOG_DEBUG(4, + "type=0x%04x frmlen=%d offset=0x%04x page=0x%04x\n", + ctlx->outbuf.rmemreq.type, + ctlx->outbuf.rmemreq.frmlen, + ctlx->outbuf.rmemreq.offset, + ctlx->outbuf.rmemreq.page); + + WLAN_LOG_DEBUG(4,"pktsize=%zd\n", + ROUNDUP64(sizeof(ctlx->outbuf.rmemreq))); + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if ( mode == DOWAIT ) { + usbctlx_rmem_completor_t completor; + + result = hfa384x_usbctlx_complete_sync( + hw, ctlx, init_rmem_completor(&completor, + &ctlx->inbuf.rmemresp, + data, + len) ); + } + +done: + DBFEXIT; + return result; +} + + + +/*---------------------------------------------------------------- +* hfa384x_dowmem +* +* Constructs a writemem CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbwmem() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* page MAC address space page (CMD format) +* offset MAC address space offset +* data Ptr to data buffer containing write data +* len Length of the data to read (max == 2048) +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls. +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOWAIT) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dowmem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + WLAN_LOG_DEBUG(5, "page=0x%04x offset=0x%04x len=%d\n", + page,offset,len); + + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.wmemreq.type = host2hfa384x_16(HFA384x_USB_WMEMREQ); + ctlx->outbuf.wmemreq.frmlen = host2hfa384x_16( + sizeof(ctlx->outbuf.wmemreq.offset) + + sizeof(ctlx->outbuf.wmemreq.page) + + len); + ctlx->outbuf.wmemreq.offset = host2hfa384x_16(offset); + ctlx->outbuf.wmemreq.page = host2hfa384x_16(page); + memcpy(ctlx->outbuf.wmemreq.data, data, len); + + ctlx->outbufsize = sizeof(ctlx->outbuf.wmemreq.type) + + sizeof(ctlx->outbuf.wmemreq.frmlen) + + sizeof(ctlx->outbuf.wmemreq.offset) + + sizeof(ctlx->outbuf.wmemreq.page) + + len; + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if ( mode == DOWAIT ) { + usbctlx_wmem_completor_t completor; + hfa384x_cmdresult_t wmemresult; + + result = hfa384x_usbctlx_complete_sync( + hw, + ctlx, + init_wmem_completor(&completor, + &ctlx->inbuf.wmemresp, + &wmemresult) ); + } + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_commtallies +* +* Send a commtallies inquiry to the MAC. Note that this is an async +* call that will result in an info frame arriving sometime later. +* +* Arguments: +* hw device structure +* +* Returns: +* zero success. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_commtallies( hfa384x_t *hw ) +{ + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMDCODE_INQ; + cmd.parm0 = HFA384x_IT_COMMTALLIES; + cmd.parm1 = 0; + cmd.parm2 = 0; + + hfa384x_docmd_async(hw, &cmd, NULL, NULL, NULL); + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_disable +* +* Issues the disable command to stop communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also disable macports 1-6. Only ports that have been +* previously enabled may be disabled. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + !(hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_disable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 0; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_enable +* +* Issues the enable command to enable communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also enable macports 1-6. Only ports that are currently +* disabled may be enabled. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + (hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_enable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 1; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_enable +* +* Begins the flash download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and retrieves the flash download +* buffer location, buffer size, and timeout length. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) +{ + int result = 0; + int i; + + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_DEBUG(1,"called when port enabled.\n"); + return -EINVAL; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + return -EINVAL; + } + + /* Retrieve the buffer loc&size and timeout */ + if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, + &(hw->bufinfo), sizeof(hw->bufinfo))) ) { + return result; + } + hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); + hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); + hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); + if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, + &(hw->dltimeout))) ) { + return result; + } + hw->dltimeout = hfa384x2host_16(hw->dltimeout); + + WLAN_LOG_DEBUG(1,"flashdl_enable\n"); + + hw->dlstate = HFA384x_DLSTATE_FLASHENABLED; + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_disable +* +* Ends the flash download state. Note that this will cause the MAC +* firmware to restart. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + WLAN_LOG_DEBUG(1,"flashdl_enable\n"); + + /* There isn't much we can do at this point, so I don't */ + /* bother w/ the return value */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hw->dlstate = HFA384x_DLSTATE_DISABLED; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_write +* +* Performs a FLASH download of a chunk of data. First checks to see +* that we're in the FLASH download state, then sets the download +* mode, uses the aux functions to 1) copy the data to the flash +* buffer, 2) sets the download 'write flash' mode, 3) readback and +* compare. Lather rinse, repeat as many times an necessary to get +* all the given data into flash. +* When all data has been written using this function (possibly +* repeatedly), call drvr_flashdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_flashdl_write( + hfa384x_t *hw, + UINT32 daddr, + void *buf, + UINT32 len) +{ + int result = 0; + UINT32 dlbufaddr; + int nburns; + UINT32 burnlen; + UINT32 burndaddr; + UINT16 burnlo; + UINT16 burnhi; + int nwrites; + UINT8 *writebuf; + UINT16 writepage; + UINT16 writeoffset; + UINT32 writelen; + int i; + int j; + + DBFENTER; + WLAN_LOG_DEBUG(5,"daddr=0x%08x len=%d\n", daddr, len); + + /* Check that we're in the flash download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr); + + /* Convert to flat address for arithmetic */ + /* NOTE: dlbuffer RID stores the address in AUX format */ + dlbufaddr = HFA384x_ADDR_AUX_MKFLAT( + hw->bufinfo.page, hw->bufinfo.offset); + WLAN_LOG_DEBUG(5, + "dlbuf.page=0x%04x dlbuf.offset=0x%04x dlbufaddr=0x%08x\n", + hw->bufinfo.page, hw->bufinfo.offset, dlbufaddr); + +#if 0 +WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout); +#endif + /* Calculations to determine how many fills of the dlbuffer to do + * and how many USB wmemreq's to do for each fill. At this point + * in time, the dlbuffer size and the wmemreq size are the same. + * Therefore, nwrites should always be 1. The extra complexity + * here is a hedge against future changes. + */ + + /* Figure out how many times to do the flash programming */ + nburns = len / hw->bufinfo.len; + nburns += (len % hw->bufinfo.len) ? 1 : 0; + + /* For each flash program cycle, how many USB wmemreq's are needed? */ + nwrites = hw->bufinfo.len / HFA384x_USB_RWMEM_MAXLEN; + nwrites += (hw->bufinfo.len % HFA384x_USB_RWMEM_MAXLEN) ? 1 : 0; + + /* For each burn */ + for ( i = 0; i < nburns; i++) { + /* Get the dest address and len */ + burnlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ? + hw->bufinfo.len : + (len - (hw->bufinfo.len * i)); + burndaddr = daddr + (hw->bufinfo.len * i); + burnlo = HFA384x_ADDR_CMD_MKOFF(burndaddr); + burnhi = HFA384x_ADDR_CMD_MKPAGE(burndaddr); + + WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n", + burnlen, burndaddr); + + /* Set the download mode */ + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV, + burnlo, burnhi, burnlen); + if ( result ) { + WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + burnlo, burnhi, burnlen, result); + goto exit_proc; + } + + /* copy the data to the flash download buffer */ + for ( j=0; j < nwrites; j++) { + writebuf = buf + + (i*hw->bufinfo.len) + + (j*HFA384x_USB_RWMEM_MAXLEN); + + writepage = HFA384x_ADDR_CMD_MKPAGE( + dlbufaddr + + (j*HFA384x_USB_RWMEM_MAXLEN)); + writeoffset = HFA384x_ADDR_CMD_MKOFF( + dlbufaddr + + (j*HFA384x_USB_RWMEM_MAXLEN)); + + writelen = burnlen-(j*HFA384x_USB_RWMEM_MAXLEN); + writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ? + HFA384x_USB_RWMEM_MAXLEN : + writelen; + + result = hfa384x_dowmem_wait( hw, + writepage, + writeoffset, + writebuf, + writelen ); +#if 0 + +Comment out for debugging, assume the write was successful. + if (result) { + WLAN_LOG_ERROR( + "Write to dl buffer failed, " + "result=0x%04x. Aborting.\n", + result); + goto exit_proc; + } +#endif + + } + + /* set the download 'write flash' mode */ + result = hfa384x_cmd_download(hw, + HFA384x_PROGMODE_NVWRITE, + 0,0,0); + if ( result ) { + WLAN_LOG_ERROR( + "download(NVWRITE,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + burnlo, burnhi, burnlen, result); + goto exit_proc; + } + + /* TODO: We really should do a readback and compare. */ + } + +exit_proc: + + /* Leave the firmware in the 'post-prog' mode. flashdl_disable will */ + /* actually disable programming mode. Remember, that will cause the */ + /* the firmware to effectively reset itself. */ + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_getconfig +* +* Performs the sequence necessary to read a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (host order) +* buf host side record buffer. Upon return it will +* contain the body portion of the record (minus the +* RID and len). +* len buffer length (in bytes, should match record length) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ENODATA length mismatch between argument and retrieved +* record. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + int result; + DBFENTER; + + result = hfa384x_dorrid_wait(hw, rid, buf, len); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- + * hfa384x_drvr_getconfig_async + * + * Performs the sequence necessary to perform an async read of + * of a config/info item. + * + * Arguments: + * hw device structure + * rid config/info record id (host order) + * buf host side record buffer. Upon return it will + * contain the body portion of the record (minus the + * RID and len). + * len buffer length (in bytes, should match record length) + * cbfn caller supplied callback, called when the command + * is done (successful or not). + * cbfndata pointer to some caller supplied data that will be + * passed in as an argument to the cbfn. + * + * Returns: + * nothing the cbfn gets a status argument identifying if + * any errors occur. + * Side effects: + * Queues an hfa384x_usbcmd_t for subsequent execution. + * + * Call context: + * Any + ----------------------------------------------------------------*/ +int +hfa384x_drvr_getconfig_async( + hfa384x_t *hw, + UINT16 rid, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dorrid_async(hw, rid, NULL, 0, + hfa384x_cb_rrid, usercb, usercb_data); +} + +/*---------------------------------------------------------------- + * hfa384x_drvr_setconfig_async + * + * Performs the sequence necessary to write a config/info item. + * + * Arguments: + * hw device structure + * rid config/info record id (in host order) + * buf host side record buffer + * len buffer length (in bytes) + * usercb completion callback + * usercb_data completion callback argument + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + ----------------------------------------------------------------*/ +int +hfa384x_drvr_setconfig_async( + hfa384x_t *hw, + UINT16 rid, + void *buf, + UINT16 len, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dowrid_async(hw, rid, buf, len, + hfa384x_cb_status, usercb, usercb_data); +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_handover +* +* Sends a handover notification to the MAC. +* +* Arguments: +* hw device structure +* addr address of station that's left +* +* Returns: +* zero success. +* -ERESTARTSYS received signal while waiting for semaphore. +* -EIO failed to write to bap, or failed in cmd. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr) +{ + DBFENTER; + WLAN_LOG_ERROR("Not currently supported in USB!\n"); + DBFEXIT; + return -EIO; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_low_level +* +* Write test commands to the card. Some test commands don't make +* sense without prior set-up. For example, continous TX isn't very +* useful until you set the channel. That functionality should be +* +* Side effects: +* +* Call context: +* process thread +* -----------------------------------------------------------------*/ +int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result; + DBFENTER; + + /* Do i need a host2hfa... conversion ? */ + + result = hfa384x_docmd_wait(hw, cmd); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_read +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* register The test register to be accessed (must be even #). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp) +{ +#if 0 + int result = 0; + UINT16 cmd_code = (UINT16) 0x30; + UINT16 param = (UINT16) addr; + DBFENTER; + + /* Do i need a host2hfa... conversion ? */ + result = hfa384x_docmd_wait(hw, cmd_code); + + DBFEXIT; + return result; +#endif +return 0; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_write +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* addr The test register to be accessed (must be even #). +* data The data value to write to the register. +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ + +int +hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data) +{ +#if 0 + int result = 0; + UINT16 cmd_code = (UINT16) 0x31; + UINT16 param0 = (UINT16) addr; + UINT16 param1 = (UINT16) data; + DBFENTER; + + WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08lx\n", addr); + WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08lx\n", data); + + /* Do i need a host2hfa... conversion ? */ + result = hfa384x_docmd_wait(hw, cmd_code); + + DBFEXIT; + return result; +#endif +return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_disable +* +* Ends the ram download state. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_ramdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) { + return -EINVAL; + } + + WLAN_LOG_DEBUG(3,"ramdl_disable()\n"); + + /* There isn't much we can do at this point, so I don't */ + /* bother w/ the return value */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hw->dlstate = HFA384x_DLSTATE_DISABLED; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_enable +* +* Begins the ram download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and calls cmd_download with the +* ENABLE_VOLATILE subcommand and the exeaddr argument. +* +* Arguments: +* hw device structure +* exeaddr the card execution address that will be +* jumped to when ramdl_disable() is called +* (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr) +{ + int result = 0; + UINT16 lowaddr; + UINT16 hiaddr; + int i; + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_ERROR( + "Can't download with a macport enabled.\n"); + return -EINVAL; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + WLAN_LOG_ERROR( + "Download state not disabled.\n"); + return -EINVAL; + } + + WLAN_LOG_DEBUG(3,"ramdl_enable, exeaddr=0x%08x\n", exeaddr); + + /* Call the download(1,addr) function */ + lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr); + hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); + + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, + lowaddr, hiaddr, 0); + + if ( result == 0) { + /* Set the download state */ + hw->dlstate = HFA384x_DLSTATE_RAMENABLED; + } else { + WLAN_LOG_DEBUG(1, + "cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", + lowaddr, + hiaddr, + result); + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_write +* +* Performs a RAM download of a chunk of data. First checks to see +* that we're in the RAM download state, then uses the [read|write]mem USB +* commands to 1) copy the data, 2) readback and compare. The download +* state is unaffected. When all data has been written using +* this function, call drvr_ramdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) +{ + int result = 0; + int nwrites; + UINT8 *data = buf; + int i; + UINT32 curraddr; + UINT16 currpage; + UINT16 curroffset; + UINT16 currlen; + DBFENTER; + /* Check that we're in the ram download state */ + if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr); + + /* How many dowmem calls? */ + nwrites = len / HFA384x_USB_RWMEM_MAXLEN; + nwrites += len % HFA384x_USB_RWMEM_MAXLEN ? 1 : 0; + + /* Do blocking wmem's */ + for(i=0; i < nwrites; i++) { + /* make address args */ + curraddr = daddr + (i * HFA384x_USB_RWMEM_MAXLEN); + currpage = HFA384x_ADDR_CMD_MKPAGE(curraddr); + curroffset = HFA384x_ADDR_CMD_MKOFF(curraddr); + currlen = len - (i * HFA384x_USB_RWMEM_MAXLEN); + if ( currlen > HFA384x_USB_RWMEM_MAXLEN) { + currlen = HFA384x_USB_RWMEM_MAXLEN; + } + + /* Do blocking ctlx */ + result = hfa384x_dowmem_wait( hw, + currpage, + curroffset, + data + (i*HFA384x_USB_RWMEM_MAXLEN), + currlen ); + + if (result) break; + + /* TODO: We really should have a readback. */ + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_readpda +* +* Performs the sequence to read the PDA space. Note there is no +* drvr_writepda() function. Writing a PDA is +* generally implemented by a calling component via calls to +* cmd_download and writing to the flash download buffer via the +* aux regs. +* +* Arguments: +* hw device structure +* buf buffer to store PDA in +* len buffer length +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ETIMEOUT timout waiting for the cmd regs to become +* available, or waiting for the control reg +* to indicate the Aux port is enabled. +* -ENODATA the buffer does NOT contain a valid PDA. +* Either the card PDA is bad, or the auxdata +* reads are giving us garbage. + +* +* Side effects: +* +* Call context: +* process or non-card interrupt. +----------------------------------------------------------------*/ +int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len) +{ + int result = 0; + UINT16 *pda = buf; + int pdaok = 0; + int morepdrs = 1; + int currpdr = 0; /* word offset of the current pdr */ + size_t i; + UINT16 pdrlen; /* pdr length in bytes, host order */ + UINT16 pdrcode; /* pdr code, host order */ + UINT16 currpage; + UINT16 curroffset; + struct pdaloc { + UINT32 cardaddr; + UINT16 auxctl; + } pdaloc[] = + { + { HFA3842_PDA_BASE, 0}, + { HFA3841_PDA_BASE, 0}, + { HFA3841_PDA_BOGUS_BASE, 0} + }; + + DBFENTER; + + /* Read the pda from each known address. */ + for ( i = 0; i < ARRAY_SIZE(pdaloc); i++) { + /* Make address */ + currpage = HFA384x_ADDR_CMD_MKPAGE(pdaloc[i].cardaddr); + curroffset = HFA384x_ADDR_CMD_MKOFF(pdaloc[i].cardaddr); + + result = hfa384x_dormem_wait(hw, + currpage, + curroffset, + buf, + len); /* units of bytes */ + + if (result) { + WLAN_LOG_WARNING( + "Read from index %zd failed, continuing\n", + i ); + continue; + } + + /* Test for garbage */ + pdaok = 1; /* initially assume good */ + morepdrs = 1; + while ( pdaok && morepdrs ) { + pdrlen = hfa384x2host_16(pda[currpdr]) * 2; + pdrcode = hfa384x2host_16(pda[currpdr+1]); + /* Test the record length */ + if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { + WLAN_LOG_ERROR("pdrlen invalid=%d\n", + pdrlen); + pdaok = 0; + break; + } + /* Test the code */ + if ( !hfa384x_isgood_pdrcode(pdrcode) ) { + WLAN_LOG_ERROR("pdrcode invalid=%d\n", + pdrcode); + pdaok = 0; + break; + } + /* Test for completion */ + if ( pdrcode == HFA384x_PDR_END_OF_PDA) { + morepdrs = 0; + } + + /* Move to the next pdr (if necessary) */ + if ( morepdrs ) { + /* note the access to pda[], need words here */ + currpdr += hfa384x2host_16(pda[currpdr]) + 1; + } + } + if ( pdaok ) { + WLAN_LOG_INFO( + "PDA Read from 0x%08x in %s space.\n", + pdaloc[i].cardaddr, + pdaloc[i].auxctl == 0 ? "EXTDS" : + pdaloc[i].auxctl == 1 ? "NV" : + pdaloc[i].auxctl == 2 ? "PHY" : + pdaloc[i].auxctl == 3 ? "ICSRAM" : + ""); + break; + } + } + result = pdaok ? 0 : -ENODATA; + + if ( result ) { + WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n"); + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_setconfig +* +* Performs the sequence necessary to write a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (in host order) +* buf host side record buffer +* len buffer length (in bytes) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + return hfa384x_dowrid_wait(hw, rid, buf, len); +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_start +* +* Issues the MAC initialize command, sets up some data structures, +* and enables the interrupts. After this function completes, the +* low-level stuff should be ready for any/all commands. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_start(hfa384x_t *hw) +{ + int result, result1, result2; + u16 status; + DBFENTER; + + might_sleep(); + + /* Clear endpoint stalls - but only do this if the endpoint + * is showing a stall status. Some prism2 cards seem to behave + * badly if a clear_halt is called when the endpoint is already + * ok + */ + result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status); + if (result < 0) { + WLAN_LOG_ERROR( + "Cannot get bulk in endpoint status.\n"); + goto done; + } + if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in)) { + WLAN_LOG_ERROR( + "Failed to reset bulk in endpoint.\n"); + } + + result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status); + if (result < 0) { + WLAN_LOG_ERROR( + "Cannot get bulk out endpoint status.\n"); + goto done; + } + if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_out)) { + WLAN_LOG_ERROR( + "Failed to reset bulk out endpoint.\n"); + } + + /* Synchronous unlink, in case we're trying to restart the driver */ + usb_kill_urb(&hw->rx_urb); + + /* Post the IN urb */ + result = submit_rx_urb(hw, GFP_KERNEL); + if (result != 0) { + WLAN_LOG_ERROR( + "Fatal, failed to submit RX URB, result=%d\n", + result); + goto done; + } + + /* Call initialize twice, with a 1 second sleep in between. + * This is a nasty work-around since many prism2 cards seem to + * need time to settle after an init from cold. The second + * call to initialize in theory is not necessary - but we call + * it anyway as a double insurance policy: + * 1) If the first init should fail, the second may well succeed + * and the card can still be used + * 2) It helps ensures all is well with the card after the first + * init and settle time. + */ + result1 = hfa384x_cmd_initialize(hw); + msleep(1000); + result = result2 = hfa384x_cmd_initialize(hw); + if (result1 != 0) { + if (result2 != 0) { + WLAN_LOG_ERROR( + "cmd_initialize() failed on two attempts, results %d and %d\n", + result1, result2); + usb_kill_urb(&hw->rx_urb); + goto done; + } else { + WLAN_LOG_DEBUG(0, "First cmd_initialize() failed (result %d),\n", + result1); + WLAN_LOG_DEBUG(0, "but second attempt succeeded. All should be ok\n"); + } + } else if (result2 != 0) { + WLAN_LOG_WARNING( + "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n", + result2); + WLAN_LOG_WARNING("Most likely the card will be functional\n"); + goto done; + } + + hw->state = HFA384x_STATE_RUNNING; + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_stop +* +* Shuts down the MAC to the point where it is safe to unload the +* driver. Any subsystem that may be holding a data or function +* ptr into the driver must be cleared/deinitialized. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_stop(hfa384x_t *hw) +{ + int result = 0; + int i; + DBFENTER; + + might_sleep(); + + /* There's no need for spinlocks here. The USB "disconnect" + * function sets this "removed" flag and then calls us. + */ + if ( !hw->wlandev->hwremoved ) { + /* Call initialize to leave the MAC in its 'reset' state */ + hfa384x_cmd_initialize(hw); + + /* Cancel the rxurb */ + usb_kill_urb(&hw->rx_urb); + } + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + del_timer_sync(&hw->commsqual_timer); + + /* Clear all the port status */ + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_txframe +* +* Takes a frame from prism2sta and queues it for transmission. +* +* Arguments: +* hw device structure +* skb packet buffer struct. Contains an 802.11 +* data frame. +* p80211_hdr points to the 802.11 header for the packet. +* Returns: +* 0 Success and more buffs available +* 1 Success but no more buffs +* 2 Allocation failure +* 4 Buffer full or queue busy +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) + +{ + int usbpktlen = sizeof(hfa384x_tx_frame_t); + int result; + int ret; + char *ptr; + + DBFENTER; + + if (hw->tx_urb.status == -EINPROGRESS) { + WLAN_LOG_WARNING("TX URB already in use\n"); + result = 3; + goto exit; + } + + /* Build Tx frame structure */ + /* Set up the control field */ + memset(&hw->txbuff.txfrm.desc, 0, sizeof(hw->txbuff.txfrm.desc)); + + /* Setup the usb type field */ + hw->txbuff.type = host2hfa384x_16(HFA384x_USB_TXFRM); + + /* Set up the sw_support field to identify this frame */ + hw->txbuff.txfrm.desc.sw_support = 0x0123; + +/* Tx complete and Tx exception disable per dleach. Might be causing + * buf depletion + */ +//#define DOEXC SLP -- doboth breaks horribly under load, doexc less so. +#if defined(DOBOTH) + hw->txbuff.txfrm.desc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1); +#elif defined(DOEXC) + hw->txbuff.txfrm.desc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0); +#else + hw->txbuff.txfrm.desc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0); +#endif + hw->txbuff.txfrm.desc.tx_control = + host2hfa384x_16(hw->txbuff.txfrm.desc.tx_control); + + /* copy the header over to the txdesc */ + memcpy(&(hw->txbuff.txfrm.desc.frame_control), p80211_hdr, sizeof(p80211_hdr_t)); + + /* if we're using host WEP, increase size by IV+ICV */ + if (p80211_wep->data) { + hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len+8); + // hw->txbuff.txfrm.desc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1); + usbpktlen+=8; + } else { + hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len); + } + + usbpktlen += skb->len; + + /* copy over the WEP IV if we are using host WEP */ + ptr = hw->txbuff.txfrm.data; + if (p80211_wep->data) { + memcpy(ptr, p80211_wep->iv, sizeof(p80211_wep->iv)); + ptr+= sizeof(p80211_wep->iv); + memcpy(ptr, p80211_wep->data, skb->len); + } else { + memcpy(ptr, skb->data, skb->len); + } + /* copy over the packet data */ + ptr+= skb->len; + + /* copy over the WEP ICV if we are using host WEP */ + if (p80211_wep->data) { + memcpy(ptr, p80211_wep->icv, sizeof(p80211_wep->icv)); + } + + /* Send the USB packet */ + usb_fill_bulk_urb( &(hw->tx_urb), hw->usb, + hw->endp_out, + &(hw->txbuff), ROUNDUP64(usbpktlen), + hfa384x_usbout_callback, hw->wlandev ); + hw->tx_urb.transfer_flags |= USB_QUEUE_BULK; + + result = 1; + ret = submit_tx_urb(hw, &hw->tx_urb, GFP_ATOMIC); + if ( ret != 0 ) { + WLAN_LOG_ERROR( + "submit_tx_urb() failed, error=%d\n", ret); + result = 3; + } + + exit: + DBFEXIT; + return result; +} + +void hfa384x_tx_timeout(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + if ( !hw->wlandev->hwremoved && + /* Note the bitwise OR, not the logical OR. */ + ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) | + !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) ) + { + schedule_work(&hw->usb_work); + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_reaper_task +* +* Tasklet to delete dead CTLX objects +* +* Arguments: +* data ptr to a hfa384x_t +* +* Returns: +* +* Call context: +* Interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbctlx_reaper_task(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + struct list_head *entry; + struct list_head *temp; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* This list is guaranteed to be empty if someone + * has unplugged the adapter. + */ + list_for_each_safe(entry, temp, &hw->ctlxq.reapable) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_del(&ctlx->list); + kfree(ctlx); + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_completion_task +* +* Tasklet to call completion handlers for returned CTLXs +* +* Arguments: +* data ptr to hfa384x_t +* +* Returns: +* Nothing +* +* Call context: +* Interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbctlx_completion_task(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + struct list_head *entry; + struct list_head *temp; + unsigned long flags; + + int reap = 0; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* This list is guaranteed to be empty if someone + * has unplugged the adapter ... + */ + list_for_each_safe(entry, temp, &hw->ctlxq.completing) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + + /* Call the completion function that this + * command was assigned, assuming it has one. + */ + if ( ctlx->cmdcb != NULL ) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + ctlx->cmdcb(hw, ctlx); + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* Make sure we don't try and complete + * this CTLX more than once! + */ + ctlx->cmdcb = NULL; + + /* Did someone yank the adapter out + * while our list was (briefly) unlocked? + */ + if ( hw->wlandev->hwremoved ) + { + reap = 0; + break; + } + } + + /* + * "Reapable" CTLXs are ones which don't have any + * threads waiting for them to die. Hence they must + * be delivered to The Reaper! + */ + if ( ctlx->reapable ) { + /* Move the CTLX off the "completing" list (hopefully) + * on to the "reapable" list where the reaper task + * can find it. And "reapable" means that this CTLX + * isn't sitting on a wait-queue somewhere. + */ + list_move_tail(&ctlx->list, &hw->ctlxq.reapable); + reap = 1; + } + + complete(&ctlx->done); + } + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if (reap) + tasklet_schedule(&hw->reaper_bh); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* unlocked_usbctlx_cancel_async +* +* Mark the CTLX dead asynchronously, and ensure that the +* next command on the queue is run afterwards. +* +* Arguments: +* hw ptr to the hfa384x_t structure +* ctlx ptr to a CTLX structure +* +* Returns: +* 0 the CTLX's URB is inactive +* -EINPROGRESS the URB is currently being unlinked +* +* Call context: +* Either process or interrupt, but presumably interrupt +----------------------------------------------------------------*/ +static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +{ + int ret; + + DBFENTER; + + /* + * Try to delete the URB containing our request packet. + * If we succeed, then its completion handler will be + * called with a status of -ECONNRESET. + */ + hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK; + ret = usb_unlink_urb(&hw->ctlx_urb); + + if (ret != -EINPROGRESS) { + /* + * The OUT URB had either already completed + * or was still in the pending queue, so the + * URB's completion function will not be called. + * We will have to complete the CTLX ourselves. + */ + ctlx->state = CTLX_REQ_FAILED; + unlocked_usbctlx_complete(hw, ctlx); + ret = 0; + } + + DBFEXIT; + + return ret; +} + +/*---------------------------------------------------------------- +* unlocked_usbctlx_complete +* +* A CTLX has completed. It may have been successful, it may not +* have been. At this point, the CTLX should be quiescent. The URBs +* aren't active and the timers should have been stopped. +* +* The CTLX is migrated to the "completing" queue, and the completing +* tasklet is scheduled. +* +* Arguments: +* hw ptr to a hfa384x_t structure +* ctlx ptr to a ctlx structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* Either, assume interrupt +----------------------------------------------------------------*/ +static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +{ + DBFENTER; + + /* Timers have been stopped, and ctlx should be in + * a terminal state. Retire it from the "active" + * queue. + */ + list_move_tail(&ctlx->list, &hw->ctlxq.completing); + tasklet_schedule(&hw->completion_bh); + + switch (ctlx->state) { + case CTLX_COMPLETE: + case CTLX_REQ_FAILED: + /* This are the correct terminating states. */ + break; + + default: + WLAN_LOG_ERROR("CTLX[%d] not in a terminating state(%s)\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state)); + break; + } /* switch */ + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usbctlxq_run +* +* Checks to see if the head item is running. If not, starts it. +* +* Arguments: +* hw ptr to hfa384x_t +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* any +----------------------------------------------------------------*/ +static void +hfa384x_usbctlxq_run(hfa384x_t *hw) +{ + unsigned long flags; + DBFENTER; + + /* acquire lock */ + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* Only one active CTLX at any one time, because there's no + * other (reliable) way to match the response URB to the + * correct CTLX. + * + * Don't touch any of these CTLXs if the hardware + * has been removed or the USB subsystem is stalled. + */ + if ( !list_empty(&hw->ctlxq.active) || + test_bit(WORK_TX_HALT, &hw->usb_flags) || + hw->wlandev->hwremoved ) + goto unlock; + + while ( !list_empty(&hw->ctlxq.pending) ) { + hfa384x_usbctlx_t *head; + int result; + + /* This is the first pending command */ + head = list_entry(hw->ctlxq.pending.next, + hfa384x_usbctlx_t, + list); + + /* We need to split this off to avoid a race condition */ + list_move_tail(&head->list, &hw->ctlxq.active); + + /* Fill the out packet */ + usb_fill_bulk_urb( &(hw->ctlx_urb), hw->usb, + hw->endp_out, + &(head->outbuf), ROUNDUP64(head->outbufsize), + hfa384x_ctlxout_callback, hw); + hw->ctlx_urb.transfer_flags |= USB_QUEUE_BULK; + + /* Now submit the URB and update the CTLX's state + */ + if ((result = SUBMIT_URB(&hw->ctlx_urb, GFP_ATOMIC)) == 0) { + /* This CTLX is now running on the active queue */ + head->state = CTLX_REQ_SUBMITTED; + + /* Start the OUT wait timer */ + hw->req_timer_done = 0; + hw->reqtimer.expires = jiffies + HZ; + add_timer(&hw->reqtimer); + + /* Start the IN wait timer */ + hw->resp_timer_done = 0; + hw->resptimer.expires = jiffies + 2*HZ; + add_timer(&hw->resptimer); + + break; + } + + if (result == -EPIPE) { + /* The OUT pipe needs resetting, so put + * this CTLX back in the "pending" queue + * and schedule a reset ... + */ + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); + list_move(&head->list, &hw->ctlxq.pending); + set_bit(WORK_TX_HALT, &hw->usb_flags); + schedule_work(&hw->usb_work); + break; + } + + if (result == -ESHUTDOWN) { + WLAN_LOG_WARNING("%s urb shutdown!\n", + hw->wlandev->netdev->name); + break; + } + + WLAN_LOG_ERROR("Failed to submit CTLX[%d]: error=%d\n", + hfa384x2host_16(head->outbuf.type), result); + unlocked_usbctlx_complete(hw, head); + } /* while */ + + unlock: + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_callback +* +* Callback for URBs on the BULKIN endpoint. +* +* Arguments: +* urb ptr to the completed urb +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +#ifdef URB_ONLY_CALLBACK +static void hfa384x_usbin_callback(struct urb *urb) +#else +static void hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs) +#endif +{ + wlandevice_t *wlandev = urb->context; + hfa384x_t *hw; + hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) urb->transfer_buffer; + struct sk_buff *skb = NULL; + int result; + int urb_status; + UINT16 type; + + enum USBIN_ACTION { + HANDLE, + RESUBMIT, + ABORT + } action; + + DBFENTER; + + if ( !wlandev || + !wlandev->netdev || + wlandev->hwremoved ) + goto exit; + + hw = wlandev->priv; + if (!hw) + goto exit; + + skb = hw->rx_urb_skb; + if (!skb || (skb->data != urb->transfer_buffer)) { + BUG(); + } + hw->rx_urb_skb = NULL; + + /* Check for error conditions within the URB */ + switch (urb->status) { + case 0: + action = HANDLE; + + /* Check for short packet */ + if ( urb->actual_length == 0 ) { + ++(wlandev->linux_stats.rx_errors); + ++(wlandev->linux_stats.rx_length_errors); + action = RESUBMIT; + } + break; + + case -EPIPE: + WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n", + wlandev->netdev->name); + if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) + schedule_work(&hw->usb_work); + ++(wlandev->linux_stats.rx_errors); + action = ABORT; + break; + + case -EILSEQ: + case -ETIMEDOUT: + case -EPROTO: + if ( !test_and_set_bit(THROTTLE_RX, &hw->usb_flags) && + !timer_pending(&hw->throttle) ) { + mod_timer(&hw->throttle, jiffies + THROTTLE_JIFFIES); + } + ++(wlandev->linux_stats.rx_errors); + action = ABORT; + break; + + case -EOVERFLOW: + ++(wlandev->linux_stats.rx_over_errors); + action = RESUBMIT; + break; + + case -ENODEV: + case -ESHUTDOWN: + WLAN_LOG_DEBUG(3,"status=%d, device removed.\n", urb->status); + action = ABORT; + break; + + case -ENOENT: + case -ECONNRESET: + WLAN_LOG_DEBUG(3,"status=%d, urb explicitly unlinked.\n", urb->status); + action = ABORT; + break; + + default: + WLAN_LOG_DEBUG(3,"urb status=%d, transfer flags=0x%x\n", + urb->status, urb->transfer_flags); + ++(wlandev->linux_stats.rx_errors); + action = RESUBMIT; + break; + } + + urb_status = urb->status; + + if (action != ABORT) { + /* Repost the RX URB */ + result = submit_rx_urb(hw, GFP_ATOMIC); + + if (result != 0) { + WLAN_LOG_ERROR( + "Fatal, failed to resubmit rx_urb. error=%d\n", + result); + } + } + + /* Handle any USB-IN packet */ + /* Note: the check of the sw_support field, the type field doesn't + * have bit 12 set like the docs suggest. + */ + type = hfa384x2host_16(usbin->type); + if (HFA384x_USB_ISRXFRM(type)) { + if (action == HANDLE) { + if (usbin->txfrm.desc.sw_support == 0x0123) { + hfa384x_usbin_txcompl(wlandev, usbin); + } else { + skb_put(skb, sizeof(*usbin)); + hfa384x_usbin_rx(wlandev, skb); + skb = NULL; + } + } + goto exit; + } + if (HFA384x_USB_ISTXFRM(type)) { + if (action == HANDLE) + hfa384x_usbin_txcompl(wlandev, usbin); + goto exit; + } + switch (type) { + case HFA384x_USB_INFOFRM: + if (action == ABORT) + goto exit; + if (action == HANDLE) + hfa384x_usbin_info(wlandev, usbin); + break; + + case HFA384x_USB_CMDRESP: + case HFA384x_USB_WRIDRESP: + case HFA384x_USB_RRIDRESP: + case HFA384x_USB_WMEMRESP: + case HFA384x_USB_RMEMRESP: + /* ALWAYS, ALWAYS, ALWAYS handle this CTLX!!!! */ + hfa384x_usbin_ctlx(hw, usbin, urb_status); + break; + + case HFA384x_USB_BUFAVAIL: + WLAN_LOG_DEBUG(3,"Received BUFAVAIL packet, frmlen=%d\n", + usbin->bufavail.frmlen); + break; + + case HFA384x_USB_ERROR: + WLAN_LOG_DEBUG(3,"Received USB_ERROR packet, errortype=%d\n", + usbin->usberror.errortype); + break; + + default: + WLAN_LOG_DEBUG(3,"Unrecognized USBIN packet, type=%x, status=%d\n", + usbin->type, urb_status); + break; + } /* switch */ + +exit: + + if (skb) + dev_kfree_skb(skb); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_ctlx +* +* We've received a URB containing a Prism2 "response" message. +* This message needs to be matched up with a CTLX on the active +* queue and our state updated accordingly. +* +* Arguments: +* hw ptr to hfa384x_t +* usbin ptr to USB IN packet +* urb_status status of this Bulk-In URB +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, + int urb_status) +{ + hfa384x_usbctlx_t *ctlx; + int run_queue = 0; + unsigned long flags; + + DBFENTER; + +retry: + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* There can be only one CTLX on the active queue + * at any one time, and this is the CTLX that the + * timers are waiting for. + */ + if ( list_empty(&hw->ctlxq.active) ) { + goto unlock; + } + + /* Remove the "response timeout". It's possible that + * we are already too late, and that the timeout is + * already running. And that's just too bad for us, + * because we could lose our CTLX from the active + * queue here ... + */ + if (del_timer(&hw->resptimer) == 0) { + if (hw->resp_timer_done == 0) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + goto retry; + } + } + else { + hw->resp_timer_done = 1; + } + + ctlx = get_active_ctlx(hw); + + if (urb_status != 0) { + /* + * Bad CTLX, so get rid of it. But we only + * remove it from the active queue if we're no + * longer expecting the OUT URB to complete. + */ + if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) + run_queue = 1; + } else { + const UINT16 intype = (usbin->type&~host2hfa384x_16(0x8000)); + + /* + * Check that our message is what we're expecting ... + */ + if (ctlx->outbuf.type != intype) { + WLAN_LOG_WARNING("Expected IN[%d], received IN[%d] - ignored.\n", + hfa384x2host_16(ctlx->outbuf.type), + hfa384x2host_16(intype)); + goto unlock; + } + + /* This URB has succeeded, so grab the data ... */ + memcpy(&ctlx->inbuf, usbin, sizeof(ctlx->inbuf)); + + switch (ctlx->state) { + case CTLX_REQ_SUBMITTED: + /* + * We have received our response URB before + * our request has been acknowledged. Odd, + * but our OUT URB is still alive... + */ + WLAN_LOG_DEBUG(0, "Causality violation: please reboot Universe, or email linux-wlan-devel@lists.linux-wlan.com\n"); + ctlx->state = CTLX_RESP_COMPLETE; + break; + + case CTLX_REQ_COMPLETE: + /* + * This is the usual path: our request + * has already been acknowledged, and + * now we have received the reply too. + */ + ctlx->state = CTLX_COMPLETE; + unlocked_usbctlx_complete(hw, ctlx); + run_queue = 1; + break; + + default: + /* + * Throw this CTLX away ... + */ + WLAN_LOG_ERROR("Matched IN URB, CTLX[%d] in invalid state(%s)." + " Discarded.\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state)); + if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) + run_queue = 1; + break; + } /* switch */ + } + +unlock: + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if (run_queue) + hfa384x_usbctlxq_run(hw); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_txcompl +* +* At this point we have the results of a previous transmit. +* +* Arguments: +* wlandev wlan device +* usbin ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +{ + UINT16 status; + DBFENTER; + + status = hfa384x2host_16(usbin->type); /* yeah I know it says type...*/ + + /* Was there an error? */ + if (HFA384x_TXSTATUS_ISERROR(status)) { + prism2sta_ev_txexc(wlandev, status); + } else { + prism2sta_ev_tx(wlandev, status); + } + // prism2sta_ev_alloc(wlandev); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_rx +* +* At this point we have a successful received a rx frame packet. +* +* Arguments: +* wlandev wlan device +* usbin ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) +{ + hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) skb->data; + hfa384x_t *hw = wlandev->priv; + int hdrlen; + p80211_rxmeta_t *rxmeta; + UINT16 data_len; + UINT16 fc; + + DBFENTER; + + /* Byte order convert once up front. */ + usbin->rxfrm.desc.status = + hfa384x2host_16(usbin->rxfrm.desc.status); + usbin->rxfrm.desc.time = + hfa384x2host_32(usbin->rxfrm.desc.time); + + /* Now handle frame based on port# */ + switch( HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) ) + { + case 0: + fc = ieee2host16(usbin->rxfrm.desc.frame_control); + + /* If exclude and we receive an unencrypted, drop it */ + if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) && + !WLAN_GET_FC_ISWEP(fc)){ + goto done; + } + + data_len = hfa384x2host_16(usbin->rxfrm.desc.data_len); + + /* How much header data do we have? */ + hdrlen = p80211_headerlen(fc); + + /* Pull off the descriptor */ + skb_pull(skb, sizeof(hfa384x_rx_frame_t)); + + /* Now shunt the header block up against the data block + * with an "overlapping" copy + */ + memmove(skb_push(skb, hdrlen), + &usbin->rxfrm.desc.frame_control, + hdrlen); + + skb->dev = wlandev->netdev; + skb->dev->last_rx = jiffies; + + /* And set the frame length properly */ + skb_trim(skb, data_len + hdrlen); + + /* The prism2 series does not return the CRC */ + memset(skb_put(skb, WLAN_CRC_LEN), 0xff, WLAN_CRC_LEN); + + skb_reset_mac_header(skb); + + /* Attach the rxmeta, set some stuff */ + p80211skb_rxmeta_attach(wlandev, skb); + rxmeta = P80211SKB_RXMETA(skb); + rxmeta->mactime = usbin->rxfrm.desc.time; + rxmeta->rxrate = usbin->rxfrm.desc.rate; + rxmeta->signal = usbin->rxfrm.desc.signal - hw->dbmadjust; + rxmeta->noise = usbin->rxfrm.desc.silence - hw->dbmadjust; + + prism2sta_ev_rx(wlandev, skb); + + break; + + case 7: + if ( ! HFA384x_RXSTATUS_ISFCSERR(usbin->rxfrm.desc.status) ) { + /* Copy to wlansnif skb */ + hfa384x_int_rxmonitor( wlandev, &usbin->rxfrm); + dev_kfree_skb(skb); + } else { + WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n"); + } + break; + + default: + WLAN_LOG_WARNING("Received frame on unsupported port=%d\n", + HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) ); + goto done; + break; + } + +done: + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_int_rxmonitor +* +* Helper function for int_rx. Handles monitor frames. +* Note that this function allocates space for the FCS and sets it +* to 0xffffffff. The hfa384x doesn't give us the FCS value but the +* higher layers expect it. 0xffffffff is used as a flag to indicate +* the FCS is bogus. +* +* Arguments: +* wlandev wlan device structure +* rxfrm rx descriptor read from card in int_rx +* +* Returns: +* nothing +* +* Side effects: +* Allocates an skb and passes it up via the PF_PACKET interface. +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *rxfrm) +{ + hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc); + UINT hdrlen = 0; + UINT datalen = 0; + UINT skblen = 0; + p80211msg_lnxind_wlansniffrm_t *msg; + UINT8 *datap; + UINT16 fc; + struct sk_buff *skb; + hfa384x_t *hw = wlandev->priv; + + + DBFENTER; + /* Don't forget the status, time, and data_len fields are in host order */ + /* Figure out how big the frame is */ + fc = ieee2host16(rxdesc->frame_control); + hdrlen = p80211_headerlen(fc); + datalen = hfa384x2host_16(rxdesc->data_len); + + /* Allocate an ind message+framesize skb */ + skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) + + hdrlen + datalen + WLAN_CRC_LEN; + + /* sanity check the length */ + if ( skblen > + (sizeof(p80211msg_lnxind_wlansniffrm_t) + + WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) { + WLAN_LOG_DEBUG(1, "overlen frm: len=%zd\n", + skblen - sizeof(p80211msg_lnxind_wlansniffrm_t)); + } + + if ( (skb = dev_alloc_skb(skblen)) == NULL ) { + WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen); + return; + } + + /* only prepend the prism header if in the right mode */ + if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr == 0)) { + datap = skb_put(skb, sizeof(p80211msg_lnxind_wlansniffrm_t)); + msg = (p80211msg_lnxind_wlansniffrm_t*) datap; + + /* Initialize the message members */ + msg->msgcode = DIDmsg_lnxind_wlansniffrm; + msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t); + strcpy(msg->devname, wlandev->name); + + msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + msg->hosttime.status = 0; + msg->hosttime.len = 4; + msg->hosttime.data = jiffies; + + msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + msg->mactime.status = 0; + msg->mactime.len = 4; + msg->mactime.data = rxdesc->time; + + msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + msg->channel.status = 0; + msg->channel.len = 4; + msg->channel.data = hw->sniff_channel; + + msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + msg->rssi.status = P80211ENUM_msgitem_status_no_value; + msg->rssi.len = 4; + msg->rssi.data = 0; + + msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq; + msg->sq.status = P80211ENUM_msgitem_status_no_value; + msg->sq.len = 4; + msg->sq.data = 0; + + msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + msg->signal.status = 0; + msg->signal.len = 4; + msg->signal.data = rxdesc->signal; + + msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + msg->noise.status = 0; + msg->noise.len = 4; + msg->noise.data = rxdesc->silence; + + msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + msg->rate.status = 0; + msg->rate.len = 4; + msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */ + + msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + msg->istx.status = 0; + msg->istx.len = 4; + msg->istx.data = P80211ENUM_truth_false; + + msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + msg->frmlen.status = 0; + msg->frmlen.len = 4; + msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN; + } else if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr != 0)) { + p80211_caphdr_t *caphdr; + /* The NEW header format! */ + datap = skb_put(skb, sizeof(p80211_caphdr_t)); + caphdr = (p80211_caphdr_t*) datap; + + caphdr->version = htonl(P80211CAPTURE_VERSION); + caphdr->length = htonl(sizeof(p80211_caphdr_t)); + caphdr->mactime = __cpu_to_be64(rxdesc->time) * 1000; + caphdr->hosttime = __cpu_to_be64(jiffies); + caphdr->phytype = htonl(4); /* dss_dot11_b */ + caphdr->channel = htonl(hw->sniff_channel); + caphdr->datarate = htonl(rxdesc->rate); + caphdr->antenna = htonl(0); /* unknown */ + caphdr->priority = htonl(0); /* unknown */ + caphdr->ssi_type = htonl(3); /* rssi_raw */ + caphdr->ssi_signal = htonl(rxdesc->signal); + caphdr->ssi_noise = htonl(rxdesc->silence); + caphdr->preamble = htonl(0); /* unknown */ + caphdr->encoding = htonl(1); /* cck */ + } + + /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */ + datap = skb_put(skb, hdrlen); + memcpy( datap, &(rxdesc->frame_control), hdrlen); + + /* If any, copy the data from the card to the skb */ + if ( datalen > 0 ) + { + datap = skb_put(skb, datalen); + memcpy(datap, rxfrm->data, datalen); + + /* check for unencrypted stuff if WEP bit set. */ + if (*(datap - hdrlen + 1) & 0x40) // wep set + if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa)) + *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header! + } + + if (hw->sniff_fcs) { + /* Set the FCS */ + datap = skb_put(skb, WLAN_CRC_LEN); + memset( datap, 0xff, WLAN_CRC_LEN); + } + + /* pass it back up */ + prism2sta_ev_rx(wlandev, skb); + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* hfa384x_usbin_info +* +* At this point we have a successful received a Prism2 info frame. +* +* Arguments: +* wlandev wlan device +* usbin ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +{ + DBFENTER; + + usbin->infofrm.info.framelen = hfa384x2host_16(usbin->infofrm.info.framelen); + prism2sta_ev_info(wlandev, &usbin->infofrm.info); + + DBFEXIT; +} + + + +/*---------------------------------------------------------------- +* hfa384x_usbout_callback +* +* Callback for URBs on the BULKOUT endpoint. +* +* Arguments: +* urb ptr to the completed urb +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +#ifdef URB_ONLY_CALLBACK +static void hfa384x_usbout_callback(struct urb *urb) +#else +static void hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs) +#endif +{ + wlandevice_t *wlandev = urb->context; + hfa384x_usbout_t *usbout = urb->transfer_buffer; + DBFENTER; + +#ifdef DEBUG_USB + dbprint_urb(urb); +#endif + + if ( wlandev && + wlandev->netdev ) { + + switch(urb->status) { + case 0: + hfa384x_usbout_tx(wlandev, usbout); + break; + + case -EPIPE: + { + hfa384x_t *hw = wlandev->priv; + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + wlandev->netdev->name); + if ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) ) + schedule_work(&hw->usb_work); + ++(wlandev->linux_stats.tx_errors); + break; + } + + case -EPROTO: + case -ETIMEDOUT: + case -EILSEQ: + { + hfa384x_t *hw = wlandev->priv; + + if ( !test_and_set_bit(THROTTLE_TX, &hw->usb_flags) + && !timer_pending(&hw->throttle) ) { + mod_timer(&hw->throttle, + jiffies + THROTTLE_JIFFIES); + } + ++(wlandev->linux_stats.tx_errors); + netif_stop_queue(wlandev->netdev); + break; + } + + case -ENOENT: + case -ESHUTDOWN: + /* Ignorable errors */ + break; + + default: + WLAN_LOG_INFO("unknown urb->status=%d\n", urb->status); + ++(wlandev->linux_stats.tx_errors); + break; + } /* switch */ + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_ctlxout_callback +* +* Callback for control data on the BULKOUT endpoint. +* +* Arguments: +* urb ptr to the completed urb +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +#ifdef URB_ONLY_CALLBACK +static void hfa384x_ctlxout_callback(struct urb *urb) +#else +static void hfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs) +#endif +{ + hfa384x_t *hw = urb->context; + int delete_resptimer = 0; + int timer_ok = 1; + int run_queue = 0; + hfa384x_usbctlx_t *ctlx; + unsigned long flags; + + DBFENTER; + + WLAN_LOG_DEBUG(3,"urb->status=%d\n", urb->status); +#ifdef DEBUG_USB + dbprint_urb(urb); +#endif + if ( (urb->status == -ESHUTDOWN) || + (urb->status == -ENODEV) || + (hw == NULL) ) + goto done; + +retry: + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* + * Only one CTLX at a time on the "active" list, and + * none at all if we are unplugged. However, we can + * rely on the disconnect function to clean everything + * up if someone unplugged the adapter. + */ + if ( list_empty(&hw->ctlxq.active) ) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + goto done; + } + + /* + * Having something on the "active" queue means + * that we have timers to worry about ... + */ + if (del_timer(&hw->reqtimer) == 0) { + if (hw->req_timer_done == 0) { + /* + * This timer was actually running while we + * were trying to delete it. Let it terminate + * gracefully instead. + */ + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + goto retry; + } + } + else { + hw->req_timer_done = 1; + } + + ctlx = get_active_ctlx(hw); + + if ( urb->status == 0 ) { + /* Request portion of a CTLX is successful */ + switch ( ctlx->state ) { + case CTLX_REQ_SUBMITTED: + /* This OUT-ACK received before IN */ + ctlx->state = CTLX_REQ_COMPLETE; + break; + + case CTLX_RESP_COMPLETE: + /* IN already received before this OUT-ACK, + * so this command must now be complete. + */ + ctlx->state = CTLX_COMPLETE; + unlocked_usbctlx_complete(hw, ctlx); + run_queue = 1; + break; + + default: + /* This is NOT a valid CTLX "success" state! */ + WLAN_LOG_ERROR( + "Illegal CTLX[%d] success state(%s, %d) in OUT URB\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state), urb->status); + break; + } /* switch */ + } else { + /* If the pipe has stalled then we need to reset it */ + if ( (urb->status == -EPIPE) && + !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) ) { + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); + schedule_work(&hw->usb_work); + } + + /* If someone cancels the OUT URB then its status + * should be either -ECONNRESET or -ENOENT. + */ + ctlx->state = CTLX_REQ_FAILED; + unlocked_usbctlx_complete(hw, ctlx); + delete_resptimer = 1; + run_queue = 1; + } + + delresp: + if (delete_resptimer) { + if ((timer_ok = del_timer(&hw->resptimer)) != 0) { + hw->resp_timer_done = 1; + } + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if ( !timer_ok && (hw->resp_timer_done == 0) ) { + spin_lock_irqsave(&hw->ctlxq.lock, flags); + goto delresp; + } + + if (run_queue) + hfa384x_usbctlxq_run(hw); + + done: + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_reqtimerfn +* +* Timer response function for CTLX request timeouts. If this +* function is called, it means that the callback for the OUT +* URB containing a Prism2.x XXX_Request was never called. +* +* Arguments: +* data a ptr to the hfa384x_t +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_usbctlx_reqtimerfn(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + unsigned long flags; + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + hw->req_timer_done = 1; + + /* Removing the hardware automatically empties + * the active list ... + */ + if ( !list_empty(&hw->ctlxq.active) ) + { + /* + * We must ensure that our URB is removed from + * the system, if it hasn't already expired. + */ + hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK; + if (usb_unlink_urb(&hw->ctlx_urb) == -EINPROGRESS) + { + hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + + ctlx->state = CTLX_REQ_FAILED; + + /* This URB was active, but has now been + * cancelled. It will now have a status of + * -ECONNRESET in the callback function. + * + * We are cancelling this CTLX, so we're + * not going to need to wait for a response. + * The URB's callback function will check + * that this timer is truly dead. + */ + if (del_timer(&hw->resptimer) != 0) + hw->resp_timer_done = 1; + } + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_resptimerfn +* +* Timer response function for CTLX response timeouts. If this +* function is called, it means that the callback for the IN +* URB containing a Prism2.x XXX_Response was never called. +* +* Arguments: +* data a ptr to the hfa384x_t +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_usbctlx_resptimerfn(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + hw->resp_timer_done = 1; + + /* The active list will be empty if the + * adapter has been unplugged ... + */ + if ( !list_empty(&hw->ctlxq.active) ) + { + hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + + if ( unlocked_usbctlx_cancel_async(hw, ctlx) == 0 ) + { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + hfa384x_usbctlxq_run(hw); + goto done; + } + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + done: + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usb_throttlefn +* +* +* Arguments: +* data ptr to hw +* +* Returns: +* Nothing +* +* Side effects: +* +* Call context: +* Interrupt +----------------------------------------------------------------*/ +static void +hfa384x_usb_throttlefn(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* + * We need to check BOTH the RX and the TX throttle controls, + * so we use the bitwise OR instead of the logical OR. + */ + WLAN_LOG_DEBUG(3, "flags=0x%lx\n", hw->usb_flags); + if ( !hw->wlandev->hwremoved && + ( + (test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && + !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) + | + (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && + !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags)) + ) ) + { + schedule_work(&hw->usb_work); + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_submit +* +* Called from the doxxx functions to submit a CTLX to the queue +* +* Arguments: +* hw ptr to the hw struct +* ctlx ctlx structure to enqueue +* +* Returns: +* -ENODEV if the adapter is unplugged +* 0 +* +* Side effects: +* +* Call context: +* process or interrupt +----------------------------------------------------------------*/ +static int +hfa384x_usbctlx_submit( + hfa384x_t *hw, + hfa384x_usbctlx_t *ctlx) +{ + unsigned long flags; + int ret; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + if (hw->wlandev->hwremoved) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + ret = -ENODEV; + } else { + ctlx->state = CTLX_PENDING; + list_add_tail(&ctlx->list, &hw->ctlxq.pending); + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + hfa384x_usbctlxq_run(hw); + ret = 0; + } + + DBFEXIT; + return ret; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbout_tx +* +* At this point we have finished a send of a frame. Mark the URB +* as available and call ev_alloc to notify higher layers we're +* ready for more. +* +* Arguments: +* wlandev wlan device +* usbout ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout) +{ + DBFENTER; + + prism2sta_ev_alloc(wlandev); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_isgood_pdrcore +* +* Quick check of PDR codes. +* +* Arguments: +* pdrcode PDR code number (host order) +* +* Returns: +* zero not good. +* one is good. +* +* Side effects: +* +* Call context: +----------------------------------------------------------------*/ +static int +hfa384x_isgood_pdrcode(UINT16 pdrcode) +{ + switch(pdrcode) { + case HFA384x_PDR_END_OF_PDA: + case HFA384x_PDR_PCB_PARTNUM: + case HFA384x_PDR_PDAVER: + case HFA384x_PDR_NIC_SERIAL: + case HFA384x_PDR_MKK_MEASUREMENTS: + case HFA384x_PDR_NIC_RAMSIZE: + case HFA384x_PDR_MFISUPRANGE: + case HFA384x_PDR_CFISUPRANGE: + case HFA384x_PDR_NICID: + case HFA384x_PDR_MAC_ADDRESS: + case HFA384x_PDR_REGDOMAIN: + case HFA384x_PDR_ALLOWED_CHANNEL: + case HFA384x_PDR_DEFAULT_CHANNEL: + case HFA384x_PDR_TEMPTYPE: + case HFA384x_PDR_IFR_SETTING: + case HFA384x_PDR_RFR_SETTING: + case HFA384x_PDR_HFA3861_BASELINE: + case HFA384x_PDR_HFA3861_SHADOW: + case HFA384x_PDR_HFA3861_IFRF: + case HFA384x_PDR_HFA3861_CHCALSP: + case HFA384x_PDR_HFA3861_CHCALI: + case HFA384x_PDR_3842_NIC_CONFIG: + case HFA384x_PDR_USB_ID: + case HFA384x_PDR_PCI_ID: + case HFA384x_PDR_PCI_IFCONF: + case HFA384x_PDR_PCI_PMCONF: + case HFA384x_PDR_RFENRGY: + case HFA384x_PDR_HFA3861_MANF_TESTSP: + case HFA384x_PDR_HFA3861_MANF_TESTI: + /* code is OK */ + return 1; + break; + default: + if ( pdrcode < 0x1000 ) { + /* code is OK, but we don't know exactly what it is */ + WLAN_LOG_DEBUG(3, + "Encountered unknown PDR#=0x%04x, " + "assuming it's ok.\n", + pdrcode); + return 1; + } else { + /* bad code */ + WLAN_LOG_DEBUG(3, + "Encountered unknown PDR#=0x%04x, " + "(>=0x1000), assuming it's bad.\n", + pdrcode); + return 0; + } + break; + } + return 0; /* avoid compiler warnings */ +} + --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/BOM +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/BOM @@ -0,0 +1,15 @@ +# Jul 29, 2008 +# Copied from the linux-wlan-ng 0.2.9+dfsg source package + +Run "make config" then "make" in src/mkmeta + +cp -a src/prism2/driver $KERNEL/ubuntu/misc/wireless/prism2_usb +cp -a src/p80211 $KERNEL/ubuntu/misc/wireless/ +cp -a src/include/wlan $KERNEL/ubuntu/misc/wireless/p80211/ +cp -a src/prism2/include/prism2 $KERNEL/ubuntu/misc/wireless/prism2_usb/ + +Strip down prism2_usb/Makefile and p80211/Makefile +rm prism2_usb/prism2_{cs,pci,plx} + +Use dev_net_set() for 2.6.26 in p80211/p80211netdev.c:wlan_setup() + --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/prism2_usb.c +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/prism2_usb.c @@ -0,0 +1,367 @@ +#define WLAN_HOSTIF WLAN_USB +#include "hfa384x_usb.c" +#include "prism2mgmt.c" +#include "prism2mib.c" +#include "prism2sta.c" + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#error "prism2_usb requires at least a 2.4.x kernel!" +#endif + +#define PRISM_USB_DEVICE(vid, pid, name) \ + USB_DEVICE(vid, pid), \ + .driver_info = (unsigned long) name + +static struct usb_device_id usb_prism_tbl[] = { + {PRISM_USB_DEVICE(0x0707, 0xee04, "Intersil Americas USB 802.11b WLAN DEVICE")}, + {PRISM_USB_DEVICE(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS")}, + {PRISM_USB_DEVICE(0x07aa, 0x0012, "Corega Wireless LAN USB Stick-11")}, + {PRISM_USB_DEVICE(0x09aa, 0x3642, "Prism2.x 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x067c, 0x1022, "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x049f, 0x0033, "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")}, + {PRISM_USB_DEVICE(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE(0x08de, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, + {PRISM_USB_DEVICE(0x8086, 0x1111, "Intel PRO/Wireless 2011B LAN USB Adapter")}, + {PRISM_USB_DEVICE(0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, + {PRISM_USB_DEVICE(0x045e, 0x006e, "Microsoft MN510 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0967, 0x0204, "Acer Warplink USB Adapter")}, + {PRISM_USB_DEVICE(0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated")}, + {PRISM_USB_DEVICE(0x0cde, 0x0005, "Z-Com Xl735 Wireless 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x413c, 0x8100, "Dell TrueMobile 1180 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0b3b, 0x1601, "ALLNET 0193 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0baf, 0x00eb, "USRobotics USR1120 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter")}, + {PRISM_USB_DEVICE(0x0846, 0x4110, "NetGear MA111")}, + {PRISM_USB_DEVICE(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter")}, +// {PRISM_USB_DEVICE(0x0ace, 0x1201, "ZyDAS ZD1201 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x2821, 0x3300, "ASUS-WL140 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x2001, 0x3700, "DWL-122 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x2001, 0x3702, "DWL-120 Rev F Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x50c2, 0x4013, "Averatec USB WLAN Adapter")}, + {PRISM_USB_DEVICE(0x2c02, 0x14ea, "Planex GW-US11H WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x124a, 0x168b, "Airvast PRISM3 WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x083a, 0x3503, "T-Sinus 111 USB WLAN Adapter")}, + {PRISM_USB_DEVICE(0x2821, 0x3300, "Hawking HighDB USB Adapter")}, + {PRISM_USB_DEVICE(0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE(0x1668, 0x6106, "ROPEX FreeLan 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x124a, 0x4017, "Pheenet WL-503IA 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x0bb2, 0x0302, "Ambit Microsystems Corp.")}, + {PRISM_USB_DEVICE(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x0543, 0x0f01, "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)")}, + { /* terminator */ } +}; + +MODULE_DEVICE_TABLE(usb, usb_prism_tbl); + +/*---------------------------------------------------------------- +* prism2sta_probe_usb +* +* Probe routine called by the USB subsystem. +* +* Arguments: +* dev ptr to the usb_device struct +* ifnum interface number being offered +* +* Returns: +* NULL - we're not claiming the device+interface +* non-NULL - we are claiming the device+interface and +* this is a ptr to the data we want back +* when disconnect is called. +* +* Side effects: +* +* Call context: +* I'm not sure, assume it's interrupt. +* +----------------------------------------------------------------*/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static void __devinit *prism2sta_probe_usb( + struct usb_device *dev, + unsigned int ifnum, + const struct usb_device_id *id) +#else +static int prism2sta_probe_usb( + struct usb_interface *interface, + const struct usb_device_id *id) +#endif +{ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + struct usb_interface *interface; +#else + struct usb_device *dev; +#endif + + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + int result = 0; + + DBFENTER; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + interface = &dev->actconfig->interface[ifnum]; +#else + dev = interface_to_usbdev(interface); +#endif + + + if ((wlandev = create_wlan()) == NULL) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + result = -EIO; + goto failed; + } + hw = wlandev->priv; + + if ( wlan_setup(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); + result = -EIO; + goto failed; + } + + /* Initialize the hw data */ + hfa384x_create(hw, dev); + hw->wlandev = wlandev; + + SET_MODULE_OWNER(wlandev->netdev); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + SET_NETDEV_DEV(wlandev->netdev, &(interface->dev)); +#endif + + /* Do a chip-level reset on the MAC */ + if (prism2_doreset) { + result = hfa384x_corereset(hw, + prism2_reset_holdtime, + prism2_reset_settletime, 0); + if (result != 0) { + hfa384x_destroy(hw); + result = -EIO; + WLAN_LOG_ERROR( + "%s: hfa384x_corereset() failed.\n", + dev_info); + goto failed; + } + } + +#ifndef NEW_MODULE_CODE + usb_inc_dev_use(dev); +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + usb_get_dev(dev); +#endif + + wlandev->msdstate = WLAN_MSD_HWPRESENT; + + /* Register the wlandev, this gets us a name and registers the + * linux netdevice. + */ + if ( register_wlandev(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); + result = -EIO; + goto failed; + } + + if (wlan_wext_write) + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); + + goto done; + + failed: + if (wlandev) kfree(wlandev); + if (hw) kfree(hw); + wlandev = NULL; + + done: + DBFEXIT; + + p80211_allow_ioctls(wlandev); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + return wlandev; +#else + usb_set_intfdata(interface, wlandev); + return result; +#endif +} + + +/*---------------------------------------------------------------- +* prism2sta_disconnect_usb +* +* Called when a device previously claimed by probe is removed +* from the USB. +* +* Arguments: +* dev ptr to the usb_device struct +* ptr ptr returned by probe() when the device +* was claimed. +* +* Returns: +* Nothing +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static void __devexit +prism2sta_disconnect_usb(struct usb_device *dev, void *ptr) +#else +static void +prism2sta_disconnect_usb(struct usb_interface *interface) +#endif +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + wlandevice_t *wlandev; +#else + wlandevice_t *wlandev = (wlandevice_t*)ptr; +#endif + + DBFENTER; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + wlandev = (wlandevice_t *) usb_get_intfdata(interface); +#endif + + if ( wlandev != NULL ) { + LIST_HEAD(cleanlist); + struct list_head *entry; + struct list_head *temp; + unsigned long flags; + + hfa384x_t *hw = wlandev->priv; + + if (!hw) + goto exit; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + p80211netdev_hwremoved(wlandev); + list_splice_init(&hw->ctlxq.reapable, &cleanlist); + list_splice_init(&hw->ctlxq.completing, &cleanlist); + list_splice_init(&hw->ctlxq.pending, &cleanlist); + list_splice_init(&hw->ctlxq.active, &cleanlist); + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + /* There's no hardware to shutdown, but the driver + * might have some tasks or tasklets that must be + * stopped before we can tear everything down. + */ + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + + del_singleshot_timer_sync(&hw->throttle); + del_singleshot_timer_sync(&hw->reqtimer); + del_singleshot_timer_sync(&hw->resptimer); + + /* Unlink all the URBs. This "removes the wheels" + * from the entire CTLX handling mechanism. + */ + usb_kill_urb(&hw->rx_urb); + usb_kill_urb(&hw->tx_urb); + usb_kill_urb(&hw->ctlx_urb); + + tasklet_kill(&hw->completion_bh); + tasklet_kill(&hw->reaper_bh); + + flush_scheduled_work(); + + /* Now we complete any outstanding commands + * and tell everyone who is waiting for their + * responses that we have shut down. + */ + list_for_each(entry, &cleanlist) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + complete(&ctlx->done); + } + + /* Give any outstanding synchronous commands + * a chance to complete. All they need to do + * is "wake up", so that's easy. + * (I'd like a better way to do this, really.) + */ + msleep(100); + + /* Now delete the CTLXs, because no-one else can now. */ + list_for_each_safe(entry, temp, &cleanlist) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + kfree(ctlx); + } + + /* Unhook the wlandev */ + unregister_wlandev(wlandev); + wlan_unsetup(wlandev); + +#ifndef NEW_MODULE_CODE + usb_dec_dev_use(hw->usb); +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + usb_put_dev(hw->usb); +#endif + + hfa384x_destroy(hw); + kfree(hw); + + kfree(wlandev); + } + + exit: + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + usb_set_intfdata(interface, NULL); +#endif + DBFEXIT; +} + + +static struct usb_driver prism2_usb_driver = { +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) + .owner = THIS_MODULE, +#endif + .name = "prism2_usb", + .probe = prism2sta_probe_usb, + .disconnect = prism2sta_disconnect_usb, + .id_table = usb_prism_tbl, + /* fops, minor? */ +}; + +#ifdef MODULE + +static int __init prism2usb_init(void) +{ + DBFENTER; + + WLAN_LOG_NOTICE("%s Loaded\n", version); + WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info); + + /* This call will result in calls to prism2sta_probe_usb. */ + return usb_register(&prism2_usb_driver); + + DBFEXIT; +}; + +static void __exit prism2usb_cleanup(void) +{ + DBFENTER; + + usb_deregister(&prism2_usb_driver); + + printk(KERN_NOTICE "%s Unloaded\n", version); + + DBFEXIT; +}; + +module_init(prism2usb_init); +module_exit(prism2usb_cleanup); + +#endif // module --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/prism2sta.c +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/prism2sta.c @@ -0,0 +1,2502 @@ +/* src/prism2/driver/prism2sta.c +* +* Implements the station functionality for prism2 +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file implements the module and linux pcmcia routines for the +* prism2 driver. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include + + +#include + +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25)) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include +#else +#include +#endif + +#include +#include +#include +#include + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#include +#include +#include +#include +#include +#include +#endif + +#include + +#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI)) +#include +#include +#endif + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + +/*================================================================*/ +/* Local Macros */ + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#define DRIVER_SUFFIX "_cs" +#elif (WLAN_HOSTIF == WLAN_PLX) +#define DRIVER_SUFFIX "_plx" +typedef char* dev_info_t; +#elif (WLAN_HOSTIF == WLAN_PCI) +#define DRIVER_SUFFIX "_pci" +typedef char* dev_info_t; +#elif (WLAN_HOSTIF == WLAN_USB) +#define DRIVER_SUFFIX "_usb" +typedef char* dev_info_t; +#else +#error "HOSTIF unsupported or undefined!" +#endif + +static char *version = "prism2" DRIVER_SUFFIX ".o: " WLAN_RELEASE; +static dev_info_t dev_info = "prism2" DRIVER_SUFFIX; + +#if (WLAN_HOSTIF == WLAN_PLX || WLAN_HOSTIF == WLAN_PCI) +#ifdef CONFIG_PM +static int prism2sta_suspend_pci(struct pci_dev *pdev, pm_message_t state); +static int prism2sta_resume_pci(struct pci_dev *pdev); +#endif +#endif + +#if (WLAN_HOSTIF == WLAN_PCI) + +#endif /* WLAN_PCI */ + +static wlandevice_t *create_wlan(void); + +/*----------------------------------------------------------------*/ +/* --Module Parameters */ + +int prism2_reset_holdtime=30; /* Reset hold time in ms */ +int prism2_reset_settletime=100; /* Reset settle time in ms */ + +#if (WLAN_HOSTIF == WLAN_USB) +static int prism2_doreset=0; /* Do a reset at init? */ +#else +static int prism2_doreset=1; /* Do a reset at init? */ +int prism2_bap_timeout=1000; /* BAP timeout */ +int prism2_irq_evread_max=20; /* Maximum number of + * ev_reads (loops) + * in irq handler + */ +#endif + +#ifdef WLAN_INCLUDE_DEBUG +int prism2_debug=0; +module_param( prism2_debug, int, 0644); +MODULE_PARM_DESC(prism2_debug, "prism2 debugging"); +#endif + +module_param( prism2_doreset, int, 0644); +MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization"); + +module_param( prism2_reset_holdtime, int, 0644); +MODULE_PARM_DESC( prism2_reset_holdtime, "reset hold time in ms"); +module_param( prism2_reset_settletime, int, 0644); +MODULE_PARM_DESC( prism2_reset_settletime, "reset settle time in ms"); + +#if (WLAN_HOSTIF != WLAN_USB) +module_param( prism2_bap_timeout, int, 0644); +MODULE_PARM_DESC(prism2_bap_timeout, "BufferAccessPath Timeout in 10*n us"); +module_param( prism2_irq_evread_max, int, 0644); +MODULE_PARM_DESC( prism2_irq_evread_max, "Maximim number of event reads in interrupt handler"); +#endif + +MODULE_LICENSE("Dual MPL/GPL"); + +/*================================================================*/ +/* Local Function Declarations */ + +static int prism2sta_open(wlandevice_t *wlandev); +static int prism2sta_close(wlandevice_t *wlandev); +static void prism2sta_reset(wlandevice_t *wlandev ); +static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); +static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg); +static int prism2sta_getcardinfo(wlandevice_t *wlandev); +static int prism2sta_globalsetup(wlandevice_t *wlandev); +static int prism2sta_setmulticast(wlandevice_t *wlandev, + netdevice_t *dev); + +static void prism2sta_inf_handover( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_tallies( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_hostscanresults( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_scanresults( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_chinforesults( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_linkstatus( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_assocstatus( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_authreq( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_authreq_defer( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_psusercnt( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); + +#ifdef CONFIG_PROC_FS +static int +prism2sta_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data); +#endif + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* dmpmem +* +* Debug utility function to dump memory to the kernel debug log. +* +* Arguments: +* buf ptr data we want dumped +* len length of data +* +* Returns: +* nothing +* Side effects: +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +inline void dmpmem(void *buf, int n) +{ + int c; + for ( c= 0; c < n; c++) { + if ( (c % 16) == 0 ) printk(KERN_DEBUG"dmp[%d]: ", c); + printk("%02x ", ((UINT8*)buf)[c]); + if ( (c % 16) == 15 ) printk("\n"); + } + if ( (c % 16) != 0 ) printk("\n"); +} + + +/*---------------------------------------------------------------- +* prism2sta_open +* +* WLAN device open method. Called from p80211netdev when kernel +* device open (start) method is called in response to the +* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP +* from clear to set. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_open(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef ANCIENT_MODULE_CODE + MOD_INC_USE_COUNT; +#endif + + /* We don't currently have to do anything else. + * The setup of the MAC should be subsequently completed via + * the mlme commands. + * Higher layers know we're ready from dev->start==1 and + * dev->tbusy==0. Our rx path knows to pass up received/ + * frames because of dev->flags&IFF_UP is true. + */ + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2sta_close +* +* WLAN device close method. Called from p80211netdev when kernel +* device close method is called in response to the +* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP +* from set to clear. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_close(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef ANCIENT_MODULE_CODE + MOD_DEC_USE_COUNT; +#endif + + /* We don't currently have to do anything else. + * Higher layers know we're not ready from dev->start==0 and + * dev->tbusy==1. Our rx path knows to not pass up received + * frames because of dev->flags&IFF_UP is false. + */ + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2sta_reset +* +* Not currently implented. +* +* Arguments: +* wlandev wlan device structure +* none +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static void prism2sta_reset(wlandevice_t *wlandev ) +{ + DBFENTER; + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_txframe +* +* Takes a frame from p80211 and queues it for transmission. +* +* Arguments: +* wlandev wlan device structure +* pb packet buffer struct. Contains an 802.11 +* data frame. +* p80211_hdr points to the 802.11 header for the packet. +* Returns: +* 0 Success and more buffs available +* 1 Success but no more buffs +* 2 Allocation failure +* 4 Buffer full or queue busy +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, + p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + int result; + DBFENTER; + + /* If necessary, set the 802.11 WEP bit */ + if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == HOSTWEP_PRIVACYINVOKED) { + p80211_hdr->a3.fc |= host2ieee16(WLAN_SET_FC_ISWEP(1)); + } + + result = hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_mlmerequest +* +* wlan command message handler. All we do here is pass the message +* over to the prism2sta_mgmt_handler. +* +* Arguments: +* wlandev wlan device structure +* msg wlan command message +* Returns: +* 0 success +* <0 successful acceptance of message, but we're +* waiting for an async process to finish before +* we're done with the msg. When the asynch +* process is done, we'll call the p80211 +* function p80211req_confirm() . +* >0 An error occurred while we were handling +* the message. +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + int result = 0; + DBFENTER; + + switch( msg->msgcode ) + { + case DIDmsg_dot11req_mibget : + WLAN_LOG_DEBUG(2,"Received mibget request\n"); + result = prism2mgmt_mibset_mibget(wlandev, msg); + break; + case DIDmsg_dot11req_mibset : + WLAN_LOG_DEBUG(2,"Received mibset request\n"); + result = prism2mgmt_mibset_mibget(wlandev, msg); + break; + case DIDmsg_dot11req_powermgmt : + WLAN_LOG_DEBUG(2,"Received powermgmt request\n"); + result = prism2mgmt_powermgmt(wlandev, msg); + break; + case DIDmsg_dot11req_scan : + WLAN_LOG_DEBUG(2,"Received scan request\n"); + result = prism2mgmt_scan(wlandev, msg); + break; + case DIDmsg_dot11req_scan_results : + WLAN_LOG_DEBUG(2,"Received scan_results request\n"); + result = prism2mgmt_scan_results(wlandev, msg); + break; + case DIDmsg_dot11req_join : + WLAN_LOG_DEBUG(2,"Received join request\n"); + result = prism2mgmt_join(wlandev, msg); + break; + case DIDmsg_dot11req_authenticate : + WLAN_LOG_DEBUG(2,"Received authenticate request\n"); + result = prism2mgmt_authenticate(wlandev, msg); + break; + case DIDmsg_dot11req_deauthenticate : + WLAN_LOG_DEBUG(2,"Received mlme deauthenticate request\n"); + result = prism2mgmt_deauthenticate(wlandev, msg); + break; + case DIDmsg_dot11req_associate : + WLAN_LOG_DEBUG(2,"Received mlme associate request\n"); + result = prism2mgmt_associate(wlandev, msg); + break; + case DIDmsg_dot11req_reassociate : + WLAN_LOG_DEBUG(2,"Received mlme reassociate request\n"); + result = prism2mgmt_reassociate(wlandev, msg); + break; + case DIDmsg_dot11req_disassociate : + WLAN_LOG_DEBUG(2,"Received mlme disassociate request\n"); + result = prism2mgmt_disassociate(wlandev, msg); + break; + case DIDmsg_dot11req_reset : + WLAN_LOG_DEBUG(2,"Received mlme reset request\n"); + result = prism2mgmt_reset(wlandev, msg); + break; + case DIDmsg_dot11req_start : + WLAN_LOG_DEBUG(2,"Received mlme start request\n"); + result = prism2mgmt_start(wlandev, msg); + break; + /* + * Prism2 specific messages + */ + case DIDmsg_p2req_join : + WLAN_LOG_DEBUG(2,"Received p2 join request\n"); + result = prism2mgmt_p2_join(wlandev, msg); + break; + case DIDmsg_p2req_readpda : + WLAN_LOG_DEBUG(2,"Received mlme readpda request\n"); + result = prism2mgmt_readpda(wlandev, msg); + break; + case DIDmsg_p2req_readcis : + WLAN_LOG_DEBUG(2,"Received mlme readcis request\n"); + result = prism2mgmt_readcis(wlandev, msg); + break; + case DIDmsg_p2req_auxport_state : + WLAN_LOG_DEBUG(2,"Received mlme auxport_state request\n"); + result = prism2mgmt_auxport_state(wlandev, msg); + break; + case DIDmsg_p2req_auxport_read : + WLAN_LOG_DEBUG(2,"Received mlme auxport_read request\n"); + result = prism2mgmt_auxport_read(wlandev, msg); + break; + case DIDmsg_p2req_auxport_write : + WLAN_LOG_DEBUG(2,"Received mlme auxport_write request\n"); + result = prism2mgmt_auxport_write(wlandev, msg); + break; + case DIDmsg_p2req_low_level : + WLAN_LOG_DEBUG(2,"Received mlme low_level request\n"); + result = prism2mgmt_low_level(wlandev, msg); + break; + case DIDmsg_p2req_test_command : + WLAN_LOG_DEBUG(2,"Received mlme test_command request\n"); + result = prism2mgmt_test_command(wlandev, msg); + break; + case DIDmsg_p2req_mmi_read : + WLAN_LOG_DEBUG(2,"Received mlme mmi_read request\n"); + result = prism2mgmt_mmi_read(wlandev, msg); + break; + case DIDmsg_p2req_mmi_write : + WLAN_LOG_DEBUG(2,"Received mlme mmi_write request\n"); + result = prism2mgmt_mmi_write(wlandev, msg); + break; + case DIDmsg_p2req_ramdl_state : + WLAN_LOG_DEBUG(2,"Received mlme ramdl_state request\n"); + result = prism2mgmt_ramdl_state(wlandev, msg); + break; + case DIDmsg_p2req_ramdl_write : + WLAN_LOG_DEBUG(2,"Received mlme ramdl_write request\n"); + result = prism2mgmt_ramdl_write(wlandev, msg); + break; + case DIDmsg_p2req_flashdl_state : + WLAN_LOG_DEBUG(2,"Received mlme flashdl_state request\n"); + result = prism2mgmt_flashdl_state(wlandev, msg); + break; + case DIDmsg_p2req_flashdl_write : + WLAN_LOG_DEBUG(2,"Received mlme flashdl_write request\n"); + result = prism2mgmt_flashdl_write(wlandev, msg); + break; + case DIDmsg_p2req_dump_state : + WLAN_LOG_DEBUG(2,"Received mlme dump_state request\n"); + result = prism2mgmt_dump_state(wlandev, msg); + break; + case DIDmsg_p2req_channel_info : + WLAN_LOG_DEBUG(2,"Received mlme channel_info request\n"); + result = prism2mgmt_channel_info(wlandev, msg); + break; + case DIDmsg_p2req_channel_info_results : + WLAN_LOG_DEBUG(2,"Received mlme channel_info_results request\n"); + result = prism2mgmt_channel_info_results(wlandev, msg); + break; + /* + * Linux specific messages + */ + case DIDmsg_lnxreq_hostwep : + break; // ignore me. + case DIDmsg_lnxreq_ifstate : + { + p80211msg_lnxreq_ifstate_t *ifstatemsg; + WLAN_LOG_DEBUG(2,"Received mlme ifstate request\n"); + ifstatemsg = (p80211msg_lnxreq_ifstate_t*)msg; + result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data); + ifstatemsg->resultcode.status = + P80211ENUM_msgitem_status_data_ok; + ifstatemsg->resultcode.data = result; + result = 0; + } + break; + case DIDmsg_lnxreq_wlansniff : + WLAN_LOG_DEBUG(2,"Received mlme wlansniff request\n"); + result = prism2mgmt_wlansniff(wlandev, msg); + break; + case DIDmsg_lnxreq_autojoin : + WLAN_LOG_DEBUG(2,"Received mlme autojoin request\n"); + result = prism2mgmt_autojoin(wlandev, msg); + break; + case DIDmsg_p2req_enable : + WLAN_LOG_DEBUG(2,"Received mlme enable request\n"); + result = prism2mgmt_enable(wlandev, msg); + break; + case DIDmsg_lnxreq_commsquality: { + p80211msg_lnxreq_commsquality_t *qualmsg; + + WLAN_LOG_DEBUG(2,"Received commsquality request\n"); + + if (hw->ap) + break; + + qualmsg = (p80211msg_lnxreq_commsquality_t*) msg; + + qualmsg->link.status = P80211ENUM_msgitem_status_data_ok; + qualmsg->level.status = P80211ENUM_msgitem_status_data_ok; + qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok; + + + qualmsg->link.data = hfa384x2host_16(hw->qual.CQ_currBSS); + qualmsg->level.data = hfa384x2host_16(hw->qual.ASL_currBSS); + qualmsg->noise.data = hfa384x2host_16(hw->qual.ANL_currFC); + + break; + } + default: + WLAN_LOG_WARNING("Unknown mgmt request message 0x%08x", msg->msgcode); + break; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_ifstate +* +* Interface state. This is the primary WLAN interface enable/disable +* handler. Following the driver/load/deviceprobe sequence, this +* function must be called with a state of "enable" before any other +* commands will be accepted. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* A p80211 message resultcode value. +* +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +UINT32 prism2sta_ifstate(wlandevice_t *wlandev, UINT32 ifstate) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + UINT32 result; + DBFENTER; + + result = P80211ENUM_resultcode_implementation_failure; + + WLAN_LOG_DEBUG(2, "Current MSD state(%d), requesting(%d)\n", + wlandev->msdstate, ifstate); + switch (ifstate) + { + case P80211ENUM_ifstate_fwload: + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING; + /* + * Initialize the device+driver sufficiently + * for firmware loading. + */ +#if (WLAN_HOSTIF != WLAN_USB) + result=hfa384x_cmd_initialize(hw); +#else + if ((result=hfa384x_drvr_start(hw))) { + WLAN_LOG_ERROR( + "hfa384x_drvr_start() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } +#endif + wlandev->msdstate = WLAN_MSD_FWLOAD; + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_FWLOAD: + hfa384x_cmd_initialize(hw); + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_RUNNING: + WLAN_LOG_WARNING( + "Cannot enter fwload state from enable state," + "you must disable first.\n"); + result = P80211ENUM_resultcode_invalid_parameters; + break; + case WLAN_MSD_HWFAIL: + default: + /* probe() had a problem or the msdstate contains + * an unrecognized value, there's nothing we can do. + */ + result = P80211ENUM_resultcode_implementation_failure; + break; + } + break; + case P80211ENUM_ifstate_enable: + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + case WLAN_MSD_FWLOAD: + wlandev->msdstate = WLAN_MSD_RUNNING_PENDING; + /* Initialize the device+driver for full + * operation. Note that this might me an FWLOAD to + * to RUNNING transition so we must not do a chip + * or board level reset. Note that on failure, + * the MSD state is set to HWPRESENT because we + * can't make any assumptions about the state + * of the hardware or a previous firmware load. + */ + if ((result=hfa384x_drvr_start(hw))) { + WLAN_LOG_ERROR( + "hfa384x_drvr_start() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } + + if ((result=prism2sta_getcardinfo(wlandev))) { + WLAN_LOG_ERROR( + "prism2sta_getcardinfo() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + hfa384x_drvr_stop(hw); + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } + if ((result=prism2sta_globalsetup(wlandev))) { + WLAN_LOG_ERROR( + "prism2sta_globalsetup() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + hfa384x_drvr_stop(hw); + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } + wlandev->msdstate = WLAN_MSD_RUNNING; + hw->join_ap = 0; + hw->join_retries = 60; + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_RUNNING: + /* Do nothing, we're already in this state.*/ + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_HWFAIL: + default: + /* probe() had a problem or the msdstate contains + * an unrecognized value, there's nothing we can do. + */ + result = P80211ENUM_resultcode_implementation_failure; + break; + } + break; + case P80211ENUM_ifstate_disable: + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + /* Do nothing, we're already in this state.*/ + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_FWLOAD: + case WLAN_MSD_RUNNING: + wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING; + /* + * TODO: Shut down the MAC completely. Here a chip + * or board level reset is probably called for. + * After a "disable" _all_ results are lost, even + * those from a fwload. + */ + if (!wlandev->hwremoved) + netif_carrier_off(wlandev->netdev); + + hfa384x_drvr_stop(hw); + + wlandev->macmode = WLAN_MACMODE_NONE; + wlandev->msdstate = WLAN_MSD_HWPRESENT; + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_HWFAIL: + default: + /* probe() had a problem or the msdstate contains + * an unrecognized value, there's nothing we can do. + */ + result = P80211ENUM_resultcode_implementation_failure; + break; + } + break; + default: + result = P80211ENUM_resultcode_invalid_parameters; + break; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_getcardinfo +* +* Collect the NICID, firmware version and any other identifiers +* we'd like to have in host-side data structures. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* Either. +----------------------------------------------------------------*/ +static int prism2sta_getcardinfo(wlandevice_t *wlandev) +{ + int result = 0; + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + UINT16 temp; + UINT8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; + char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1]; + + DBFENTER; + + /* Collect version and compatibility info */ + /* Some are critical, some are not */ + /* NIC identity */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY, + &hw->ident_nic, sizeof(hfa384x_compident_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve NICIDENTITY\n"); + goto failed; + } + + /* get all the nic id fields in host byte order */ + hw->ident_nic.id = hfa384x2host_16(hw->ident_nic.id); + hw->ident_nic.variant = hfa384x2host_16(hw->ident_nic.variant); + hw->ident_nic.major = hfa384x2host_16(hw->ident_nic.major); + hw->ident_nic.minor = hfa384x2host_16(hw->ident_nic.minor); + + WLAN_LOG_INFO( "ident: nic h/w: id=0x%02x %d.%d.%d\n", + hw->ident_nic.id, hw->ident_nic.major, + hw->ident_nic.minor, hw->ident_nic.variant); + + /* Primary f/w identity */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY, + &hw->ident_pri_fw, sizeof(hfa384x_compident_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve PRIIDENTITY\n"); + goto failed; + } + + /* get all the private fw id fields in host byte order */ + hw->ident_pri_fw.id = hfa384x2host_16(hw->ident_pri_fw.id); + hw->ident_pri_fw.variant = hfa384x2host_16(hw->ident_pri_fw.variant); + hw->ident_pri_fw.major = hfa384x2host_16(hw->ident_pri_fw.major); + hw->ident_pri_fw.minor = hfa384x2host_16(hw->ident_pri_fw.minor); + + WLAN_LOG_INFO( "ident: pri f/w: id=0x%02x %d.%d.%d\n", + hw->ident_pri_fw.id, hw->ident_pri_fw.major, + hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); + + /* Station (Secondary?) f/w identity */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY, + &hw->ident_sta_fw, sizeof(hfa384x_compident_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STAIDENTITY\n"); + goto failed; + } + + if (hw->ident_nic.id < 0x8000) { + WLAN_LOG_ERROR("FATAL: Card is not an Intersil Prism2/2.5/3\n"); + result = -1; + goto failed; + } + + /* get all the station fw id fields in host byte order */ + hw->ident_sta_fw.id = hfa384x2host_16(hw->ident_sta_fw.id); + hw->ident_sta_fw.variant = hfa384x2host_16(hw->ident_sta_fw.variant); + hw->ident_sta_fw.major = hfa384x2host_16(hw->ident_sta_fw.major); + hw->ident_sta_fw.minor = hfa384x2host_16(hw->ident_sta_fw.minor); + + /* strip out the 'special' variant bits */ + hw->mm_mods = hw->ident_sta_fw.variant & (BIT14 | BIT15); + hw->ident_sta_fw.variant &= ~((UINT16)(BIT14 | BIT15)); + + if ( hw->ident_sta_fw.id == 0x1f ) { + hw->ap = 0; + WLAN_LOG_INFO( + "ident: sta f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } else { + hw->ap = 1; + WLAN_LOG_INFO( + "ident: ap f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } + + /* Compatibility range, Modem supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE, + &hw->cap_sup_mfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve MFISUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, modem interface supplier + fields in byte order */ + hw->cap_sup_mfi.role = hfa384x2host_16(hw->cap_sup_mfi.role); + hw->cap_sup_mfi.id = hfa384x2host_16(hw->cap_sup_mfi.id); + hw->cap_sup_mfi.variant = hfa384x2host_16(hw->cap_sup_mfi.variant); + hw->cap_sup_mfi.bottom = hfa384x2host_16(hw->cap_sup_mfi.bottom); + hw->cap_sup_mfi.top = hfa384x2host_16(hw->cap_sup_mfi.top); + + WLAN_LOG_INFO( + "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_mfi.role, hw->cap_sup_mfi.id, + hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom, + hw->cap_sup_mfi.top); + + /* Compatibility range, Controller supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE, + &hw->cap_sup_cfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve CFISUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, controller interface supplier + fields in byte order */ + hw->cap_sup_cfi.role = hfa384x2host_16(hw->cap_sup_cfi.role); + hw->cap_sup_cfi.id = hfa384x2host_16(hw->cap_sup_cfi.id); + hw->cap_sup_cfi.variant = hfa384x2host_16(hw->cap_sup_cfi.variant); + hw->cap_sup_cfi.bottom = hfa384x2host_16(hw->cap_sup_cfi.bottom); + hw->cap_sup_cfi.top = hfa384x2host_16(hw->cap_sup_cfi.top); + + WLAN_LOG_INFO( + "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_cfi.role, hw->cap_sup_cfi.id, + hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom, + hw->cap_sup_cfi.top); + + /* Compatibility range, Primary f/w supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE, + &hw->cap_sup_pri, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve PRISUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, primary firmware supplier + fields in byte order */ + hw->cap_sup_pri.role = hfa384x2host_16(hw->cap_sup_pri.role); + hw->cap_sup_pri.id = hfa384x2host_16(hw->cap_sup_pri.id); + hw->cap_sup_pri.variant = hfa384x2host_16(hw->cap_sup_pri.variant); + hw->cap_sup_pri.bottom = hfa384x2host_16(hw->cap_sup_pri.bottom); + hw->cap_sup_pri.top = hfa384x2host_16(hw->cap_sup_pri.top); + + WLAN_LOG_INFO( + "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_pri.role, hw->cap_sup_pri.id, + hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom, + hw->cap_sup_pri.top); + + /* Compatibility range, Station f/w supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE, + &hw->cap_sup_sta, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STASUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, station firmware supplier + fields in byte order */ + hw->cap_sup_sta.role = hfa384x2host_16(hw->cap_sup_sta.role); + hw->cap_sup_sta.id = hfa384x2host_16(hw->cap_sup_sta.id); + hw->cap_sup_sta.variant = hfa384x2host_16(hw->cap_sup_sta.variant); + hw->cap_sup_sta.bottom = hfa384x2host_16(hw->cap_sup_sta.bottom); + hw->cap_sup_sta.top = hfa384x2host_16(hw->cap_sup_sta.top); + + if ( hw->cap_sup_sta.id == 0x04 ) { + WLAN_LOG_INFO( + "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_sta.role, hw->cap_sup_sta.id, + hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, + hw->cap_sup_sta.top); + } else { + WLAN_LOG_INFO( + "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_sta.role, hw->cap_sup_sta.id, + hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, + hw->cap_sup_sta.top); + } + + /* Compatibility range, primary f/w actor, CFI supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES, + &hw->cap_act_pri_cfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve PRI_CFIACTRANGES\n"); + goto failed; + } + + /* get all the Compatibility range, primary f/w actor, CFI supplier + fields in byte order */ + hw->cap_act_pri_cfi.role = hfa384x2host_16(hw->cap_act_pri_cfi.role); + hw->cap_act_pri_cfi.id = hfa384x2host_16(hw->cap_act_pri_cfi.id); + hw->cap_act_pri_cfi.variant = hfa384x2host_16(hw->cap_act_pri_cfi.variant); + hw->cap_act_pri_cfi.bottom = hfa384x2host_16(hw->cap_act_pri_cfi.bottom); + hw->cap_act_pri_cfi.top = hfa384x2host_16(hw->cap_act_pri_cfi.top); + + WLAN_LOG_INFO( + "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id, + hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom, + hw->cap_act_pri_cfi.top); + + /* Compatibility range, sta f/w actor, CFI supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES, + &hw->cap_act_sta_cfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STA_CFIACTRANGES\n"); + goto failed; + } + + /* get all the Compatibility range, station f/w actor, CFI supplier + fields in byte order */ + hw->cap_act_sta_cfi.role = hfa384x2host_16(hw->cap_act_sta_cfi.role); + hw->cap_act_sta_cfi.id = hfa384x2host_16(hw->cap_act_sta_cfi.id); + hw->cap_act_sta_cfi.variant = hfa384x2host_16(hw->cap_act_sta_cfi.variant); + hw->cap_act_sta_cfi.bottom = hfa384x2host_16(hw->cap_act_sta_cfi.bottom); + hw->cap_act_sta_cfi.top = hfa384x2host_16(hw->cap_act_sta_cfi.top); + + WLAN_LOG_INFO( + "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id, + hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom, + hw->cap_act_sta_cfi.top); + + /* Compatibility range, sta f/w actor, MFI supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES, + &hw->cap_act_sta_mfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STA_MFIACTRANGES\n"); + goto failed; + } + + /* get all the Compatibility range, station f/w actor, MFI supplier + fields in byte order */ + hw->cap_act_sta_mfi.role = hfa384x2host_16(hw->cap_act_sta_mfi.role); + hw->cap_act_sta_mfi.id = hfa384x2host_16(hw->cap_act_sta_mfi.id); + hw->cap_act_sta_mfi.variant = hfa384x2host_16(hw->cap_act_sta_mfi.variant); + hw->cap_act_sta_mfi.bottom = hfa384x2host_16(hw->cap_act_sta_mfi.bottom); + hw->cap_act_sta_mfi.top = hfa384x2host_16(hw->cap_act_sta_mfi.top); + + WLAN_LOG_INFO( + "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id, + hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom, + hw->cap_act_sta_mfi.top); + + /* Serial Number */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, + snum, HFA384x_RID_NICSERIALNUMBER_LEN); + if ( !result ) { + wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN, + pstr, sizeof(pstr)); + WLAN_LOG_INFO("Prism2 card SN: %s\n", pstr); + } else { + WLAN_LOG_ERROR("Failed to retrieve Prism2 Card SN\n"); + goto failed; + } + + /* Collect the MAC address */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR, + wlandev->netdev->dev_addr, WLAN_ADDR_LEN); + if ( result != 0 ) { + WLAN_LOG_ERROR("Failed to retrieve mac address\n"); + goto failed; + } + + /* short preamble is always implemented */ + wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE; + + /* find out if hardware wep is implemented */ + hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp); + if (temp) + wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP; + + /* get the dBm Scaling constant */ + hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp); + hw->dbmadjust = temp; + + /* Only enable scan by default on newer firmware */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(1,5,5)) { + wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN; + } + + /* TODO: Set any internally managed config items */ + + goto done; +failed: + WLAN_LOG_ERROR("Failed, result=%d\n", result); +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_globalsetup +* +* Set any global RIDs that we want to set at device activation. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_globalsetup(wlandevice_t *wlandev) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + /* Set the maximum frame size */ + return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, + WLAN_DATA_MAXLEN); +} + +static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev) +{ + int result = 0; + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + UINT16 promisc; + + DBFENTER; + + /* If we're not ready, what's the point? */ + if ( hw->state != HFA384x_STATE_RUNNING ) + goto exit; + + /* If we're an AP, do nothing here */ + if (hw->ap) + goto exit; + + if ( (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0 ) + promisc = P80211ENUM_truth_true; + else + promisc = P80211ENUM_truth_false; + + result = hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, promisc); + + /* XXX TODO: configure the multicast list */ + // CLEAR_HW_MULTICAST_LIST + // struct dev_mc_list element = dev->mc_list; + // while (element != null) { + // HW_ADD_MULTICAST_ADDR(element->dmi_addr, dmi_addrlen) + // element = element->next; + // } + + exit: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_handover +* +* Handles the receipt of a Handover info frame. Should only be present +* in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +{ + DBFENTER; + WLAN_LOG_DEBUG(2,"received infoframe:HANDOVER (unhandled)\n"); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_inf_tallies +* +* Handles the receipt of a CommTallies info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_tallies(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + UINT16 *src16; + UINT32 *dst; + UINT32 *src32; + int i; + int cnt; + + DBFENTER; + + /* + ** Determine if these are 16-bit or 32-bit tallies, based on the + ** record length of the info record. + */ + + cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(UINT32); + if (inf->framelen > 22) { + dst = (UINT32 *) &hw->tallies; + src32 = (UINT32 *) &inf->info.commtallies32; + for (i = 0; i < cnt; i++, dst++, src32++) + *dst += hfa384x2host_32(*src32); + } else { + dst = (UINT32 *) &hw->tallies; + src16 = (UINT16 *) &inf->info.commtallies16; + for (i = 0; i < cnt; i++, dst++, src16++) + *dst += hfa384x2host_16(*src16); + } + + DBFEXIT; + + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_scanresults +* +* Handles the receipt of a Scan Results info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_scanresults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + int nbss; + hfa384x_ScanResult_t *sr = &(inf->info.scanresult); + int i; + hfa384x_JoinRequest_data_t joinreq; + int result; + DBFENTER; + + /* Get the number of results, first in bytes, then in results */ + nbss = (inf->framelen * sizeof(UINT16)) - + sizeof(inf->infotype) - + sizeof(inf->info.scanresult.scanreason); + nbss /= sizeof(hfa384x_ScanResultSub_t); + + /* Print em */ + WLAN_LOG_DEBUG(1,"rx scanresults, reason=%d, nbss=%d:\n", + inf->info.scanresult.scanreason, nbss); + for ( i = 0; i < nbss; i++) { + WLAN_LOG_DEBUG(1, "chid=%d anl=%d sl=%d bcnint=%d\n", + sr->result[i].chid, + sr->result[i].anl, + sr->result[i].sl, + sr->result[i].bcnint); + WLAN_LOG_DEBUG(1, " capinfo=0x%04x proberesp_rate=%d\n", + sr->result[i].capinfo, + sr->result[i].proberesp_rate); + } + /* issue a join request */ + joinreq.channel = sr->result[0].chid; + memcpy( joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN); + result = hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + if (result) { + WLAN_LOG_ERROR("setconfig(joinreq) failed, result=%d\n", result); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_hostscanresults +* +* Handles the receipt of a Scan Results info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + int nbss; + DBFENTER; + + nbss = (inf->framelen - 3) / 32; + WLAN_LOG_DEBUG(1, "Received %d hostscan results\n", nbss); + + if (nbss > 32) + nbss = 32; + + if (hw->scanresults) + kfree(hw->scanresults); + + hw->scanresults = kmalloc(sizeof(hfa384x_InfFrame_t), GFP_ATOMIC); + memcpy(hw->scanresults, inf, sizeof(hfa384x_InfFrame_t)); + + if (nbss == 0) + nbss = -1; + + /* Notify/wake the sleeping caller. */ + hw->scanflag = nbss; + wake_up_interruptible(&hw->cmdq); + + DBFEXIT; +}; + +/*---------------------------------------------------------------- +* prism2sta_inf_chinforesults +* +* Handles the receipt of a Channel Info Results info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + unsigned int i, n; + + DBFENTER; + hw->channel_info.results.scanchannels = + hfa384x2host_16(inf->info.chinforesult.scanchannels); +#if 0 + memcpy(&inf->info.chinforesult, &hw->channel_info.results, sizeof(hfa384x_ChInfoResult_t)); +#endif + + for (i=0, n=0; ichannel_info.results.scanchannels & (1<info.chinforesult.result[n].chid)-1; + hfa384x_ChInfoResultSub_t *chinforesult=&hw->channel_info.results.result[channel]; + chinforesult->chid = channel; + chinforesult->anl = hfa384x2host_16(inf->info.chinforesult.result[n].anl); + chinforesult->pnl = hfa384x2host_16(inf->info.chinforesult.result[n].pnl); + chinforesult->active = hfa384x2host_16(inf->info.chinforesult.result[n].active); + WLAN_LOG_DEBUG(2, "chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n", + channel+1, + chinforesult->active & + HFA384x_CHINFORESULT_BSSACTIVE ? "signal" : "noise", + chinforesult->anl, chinforesult->pnl, + chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0 + ); + n++; + } + } + atomic_set(&hw->channel_info.done, 2); + + hw->channel_info.count = n; + DBFEXIT; + return; +} + +void prism2sta_processing_defer(struct work_struct *data) +{ + hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); + wlandevice_t *wlandev = hw->wlandev; + hfa384x_bytestr32_t ssid; + int result; + + DBFENTER; + /* First let's process the auth frames */ + { + struct sk_buff *skb; + hfa384x_InfFrame_t *inf; + + while ( (skb = skb_dequeue(&hw->authq)) ) { + inf = (hfa384x_InfFrame_t *) skb->data; + prism2sta_inf_authreq_defer(wlandev, inf); + } + + } + + /* Now let's handle the linkstatus stuff */ + if (hw->link_status == hw->link_status_new) + goto failed; + + hw->link_status = hw->link_status_new; + + switch(hw->link_status) { + case HFA384x_LINK_NOTCONNECTED: + /* I'm currently assuming that this is the initial link + * state. It should only be possible immediately + * following an Enable command. + * Response: + * Block Transmits, Ignore receives of data frames + */ + netif_carrier_off(wlandev->netdev); + + WLAN_LOG_INFO("linkstatus=NOTCONNECTED (unhandled)\n"); + break; + + case HFA384x_LINK_CONNECTED: + /* This one indicates a successful scan/join/auth/assoc. + * When we have the full MLME complement, this event will + * signify successful completion of both mlme_authenticate + * and mlme_associate. State management will get a little + * ugly here. + * Response: + * Indicate authentication and/or association + * Enable Transmits, Receives and pass up data frames + */ + + netif_carrier_on(wlandev->netdev); + + /* If we are joining a specific AP, set our state and reset retries */ + if(hw->join_ap == 1) + hw->join_ap = 2; + hw->join_retries = 60; + + /* Don't call this in monitor mode */ + if ( wlandev->netdev->type == ARPHRD_ETHER ) { + UINT16 portstatus; + + WLAN_LOG_INFO("linkstatus=CONNECTED\n"); + + /* For non-usb devices, we can use the sync versions */ + /* Collect the BSSID, and set state to allow tx */ + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTBSSID, + wlandev->bssid, WLAN_BSSID_LEN); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); + goto failed; + } + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTSSID, + &ssid, sizeof(ssid)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); + goto failed; + } + prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, + (p80211pstrd_t *) &wlandev->ssid); + + /* Collect the port status */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_PORTSTATUS, &portstatus); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_PORTSTATUS, result); + goto failed; + } + wlandev->macmode = + (portstatus == HFA384x_PSTATUS_CONN_IBSS) ? + WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA; + + /* Get the ball rolling on the comms quality stuff */ + prism2sta_commsqual_defer(&hw->commsqual_bh); + } + break; + + case HFA384x_LINK_DISCONNECTED: + /* This one indicates that our association is gone. We've + * lost connection with the AP and/or been disassociated. + * This indicates that the MAC has completely cleared it's + * associated state. We * should send a deauth indication + * (implying disassoc) up * to the MLME. + * Response: + * Indicate Deauthentication + * Block Transmits, Ignore receives of data frames + */ + if(hw->join_ap == 2) + { + hfa384x_JoinRequest_data_t joinreq; + joinreq = hw->joinreq; + /* Send the join request */ + hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + WLAN_LOG_INFO("linkstatus=DISCONNECTED (re-submitting join)\n"); + } else { + if (wlandev->netdev->type == ARPHRD_ETHER) + WLAN_LOG_INFO("linkstatus=DISCONNECTED (unhandled)\n"); + } + wlandev->macmode = WLAN_MACMODE_NONE; + + netif_carrier_off(wlandev->netdev); + + break; + + case HFA384x_LINK_AP_CHANGE: + /* This one indicates that the MAC has decided to and + * successfully completed a change to another AP. We + * should probably implement a reassociation indication + * in response to this one. I'm thinking that the the + * p80211 layer needs to be notified in case of + * buffering/queueing issues. User mode also needs to be + * notified so that any BSS dependent elements can be + * updated. + * associated state. We * should send a deauth indication + * (implying disassoc) up * to the MLME. + * Response: + * Indicate Reassociation + * Enable Transmits, Receives and pass up data frames + */ + WLAN_LOG_INFO("linkstatus=AP_CHANGE\n"); + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTBSSID, + wlandev->bssid, WLAN_BSSID_LEN); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); + goto failed; + } + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTSSID, + &ssid, sizeof(ssid)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); + goto failed; + } + prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, + (p80211pstrd_t *) &wlandev->ssid); + + + hw->link_status = HFA384x_LINK_CONNECTED; + netif_carrier_on(wlandev->netdev); + + break; + + case HFA384x_LINK_AP_OUTOFRANGE: + /* This one indicates that the MAC has decided that the + * AP is out of range, but hasn't found a better candidate + * so the MAC maintains its "associated" state in case + * we get back in range. We should block transmits and + * receives in this state. Do we need an indication here? + * Probably not since a polling user-mode element would + * get this status from from p2PortStatus(FD40). What about + * p80211? + * Response: + * Block Transmits, Ignore receives of data frames + */ + WLAN_LOG_INFO("linkstatus=AP_OUTOFRANGE (unhandled)\n"); + + netif_carrier_off(wlandev->netdev); + + break; + + case HFA384x_LINK_AP_INRANGE: + /* This one indicates that the MAC has decided that the + * AP is back in range. We continue working with our + * existing association. + * Response: + * Enable Transmits, Receives and pass up data frames + */ + WLAN_LOG_INFO("linkstatus=AP_INRANGE\n"); + + hw->link_status = HFA384x_LINK_CONNECTED; + netif_carrier_on(wlandev->netdev); + + break; + + case HFA384x_LINK_ASSOCFAIL: + /* This one is actually a peer to CONNECTED. We've + * requested a join for a given SSID and optionally BSSID. + * We can use this one to indicate authentication and + * association failures. The trick is going to be + * 1) identifying the failure, and 2) state management. + * Response: + * Disable Transmits, Ignore receives of data frames + */ + if(hw->join_ap && --hw->join_retries > 0) + { + hfa384x_JoinRequest_data_t joinreq; + joinreq = hw->joinreq; + /* Send the join request */ + hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + WLAN_LOG_INFO("linkstatus=ASSOCFAIL (re-submitting join)\n"); + } else { + WLAN_LOG_INFO("linkstatus=ASSOCFAIL (unhandled)\n"); + } + + netif_carrier_off(wlandev->netdev); + + break; + + default: + /* This is bad, IO port problems? */ + WLAN_LOG_WARNING( + "unknown linkstatus=0x%02x\n", hw->link_status); + goto failed; + break; + } + + wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED); +#ifdef WIRELESS_EXT + p80211wext_event_associated(wlandev, wlandev->linkstatus); +#endif + + failed: + DBFEXIT; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_linkstatus +* +* Handles the receipt of a Link Status info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + DBFENTER; + + hw->link_status_new = hfa384x2host_16(inf->info.linkstatus.linkstatus); + + schedule_work(&hw->link_bh); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_assocstatus +* +* Handles the receipt of an Association Status info frame. Should +* be present in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_AssocStatus_t rec; + int i; + + DBFENTER; + + memcpy(&rec, &inf->info.assocstatus, sizeof(rec)); + rec.assocstatus = hfa384x2host_16(rec.assocstatus); + rec.reason = hfa384x2host_16(rec.reason); + + /* + ** Find the address in the list of authenticated stations. If it wasn't + ** found, then this address has not been previously authenticated and + ** something weird has happened if this is anything other than an + ** "authentication failed" message. If the address was found, then + ** set the "associated" flag for that station, based on whether the + ** station is associating or losing its association. Something weird + ** has also happened if we find the address in the list of authenticated + ** stations but we are getting an "authentication failed" message. + */ + + for (i = 0; i < hw->authlist.cnt; i++) + if (memcmp(rec.sta_addr, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0) + break; + + if (i >= hw->authlist.cnt) { + if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL) + WLAN_LOG_WARNING("assocstatus info frame received for non-authenticated station.\n"); + } else { + hw->authlist.assoc[i] = + (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC || + rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC); + + if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL) + WLAN_LOG_WARNING("authfail assocstatus info frame received for authenticated station.\n"); + } + + DBFEXIT; + + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_authreq +* +* Handles the receipt of an Authentication Request info frame. Should +* be present in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +* +----------------------------------------------------------------*/ +static void prism2sta_inf_authreq(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + struct sk_buff *skb; + + DBFENTER; + + skb = dev_alloc_skb(sizeof(*inf)); + if (skb) { + skb_put(skb, sizeof(*inf)); + memcpy(skb->data, inf, sizeof(*inf)); + skb_queue_tail(&hw->authq, skb); + schedule_work(&hw->link_bh); + } + + DBFEXIT; +} + +static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_authenticateStation_data_t rec; + + int i, added, result, cnt; + UINT8 *addr; + + DBFENTER; + + /* + ** Build the AuthenticateStation record. Initialize it for denying + ** authentication. + */ + + memcpy(rec.address, inf->info.authreq.sta_addr, WLAN_ADDR_LEN); + rec.status = P80211ENUM_status_unspec_failure; + + /* + ** Authenticate based on the access mode. + */ + + switch (hw->accessmode) { + case WLAN_ACCESS_NONE: + + /* + ** Deny all new authentications. However, if a station + ** is ALREADY authenticated, then accept it. + */ + + for (i = 0; i < hw->authlist.cnt; i++) + if (memcmp(rec.address, hw->authlist.addr[i], + WLAN_ADDR_LEN) == 0) { + rec.status = P80211ENUM_status_successful; + break; + } + + break; + + case WLAN_ACCESS_ALL: + + /* + ** Allow all authentications. + */ + + rec.status = P80211ENUM_status_successful; + break; + + case WLAN_ACCESS_ALLOW: + + /* + ** Only allow the authentication if the MAC address + ** is in the list of allowed addresses. + ** + ** Since this is the interrupt handler, we may be here + ** while the access list is in the middle of being + ** updated. Choose the list which is currently okay. + ** See "prism2mib_priv_accessallow()" for details. + */ + + if (hw->allow.modify == 0) { + cnt = hw->allow.cnt; + addr = hw->allow.addr[0]; + } else { + cnt = hw->allow.cnt1; + addr = hw->allow.addr1[0]; + } + + for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN) + if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) { + rec.status = P80211ENUM_status_successful; + break; + } + + break; + + case WLAN_ACCESS_DENY: + + /* + ** Allow the authentication UNLESS the MAC address is + ** in the list of denied addresses. + ** + ** Since this is the interrupt handler, we may be here + ** while the access list is in the middle of being + ** updated. Choose the list which is currently okay. + ** See "prism2mib_priv_accessdeny()" for details. + */ + + if (hw->deny.modify == 0) { + cnt = hw->deny.cnt; + addr = hw->deny.addr[0]; + } else { + cnt = hw->deny.cnt1; + addr = hw->deny.addr1[0]; + } + + rec.status = P80211ENUM_status_successful; + + for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN) + if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) { + rec.status = P80211ENUM_status_unspec_failure; + break; + } + + break; + } + + /* + ** If the authentication is okay, then add the MAC address to the list + ** of authenticated stations. Don't add the address if it is already in + ** the list. (802.11b does not seem to disallow a station from issuing + ** an authentication request when the station is already authenticated. + ** Does this sort of thing ever happen? We might as well do the check + ** just in case.) + */ + + added = 0; + + if (rec.status == P80211ENUM_status_successful) { + for (i = 0; i < hw->authlist.cnt; i++) + if (memcmp(rec.address, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0) + break; + + if (i >= hw->authlist.cnt) { + if (hw->authlist.cnt >= WLAN_AUTH_MAX) { + rec.status = P80211ENUM_status_ap_full; + } else { + memcpy(hw->authlist.addr[hw->authlist.cnt], + rec.address, WLAN_ADDR_LEN); + hw->authlist.cnt++; + added = 1; + } + } + } + + /* + ** Send back the results of the authentication. If this doesn't work, + ** then make sure to remove the address from the authenticated list if + ** it was added. + */ + + rec.status = host2hfa384x_16(rec.status); + rec.algorithm = inf->info.authreq.algorithm; + + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA, + &rec, sizeof(rec)); + if (result) { + if (added) hw->authlist.cnt--; + WLAN_LOG_ERROR("setconfig(authenticatestation) failed, result=%d\n", result); + } + + DBFEXIT; + + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_inf_psusercnt +* +* Handles the receipt of a PowerSaveUserCount info frame. Should +* be present in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + DBFENTER; + + hw->psusercount = hfa384x2host_16(inf->info.psusercnt.usercnt); + + DBFEXIT; + + return; +} + +/*---------------------------------------------------------------- +* prism2sta_ev_dtim +* +* Handles the DTIM early warning event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_dtim(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; +#endif + DBFENTER; + WLAN_LOG_DEBUG(3, "DTIM event, currently unhandled.\n"); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_infdrop +* +* Handles the InfDrop event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_infdrop(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; +#endif + DBFENTER; + WLAN_LOG_DEBUG(3, "Info frame dropped due to card mem low.\n"); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_info +* +* Handles the Info event. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to a generic info frame +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +{ + DBFENTER; + inf->infotype = hfa384x2host_16(inf->infotype); + /* Dispatch */ + switch ( inf->infotype ) { + case HFA384x_IT_HANDOVERADDR: + prism2sta_inf_handover(wlandev, inf); + break; + case HFA384x_IT_COMMTALLIES: + prism2sta_inf_tallies(wlandev, inf); + break; + case HFA384x_IT_HOSTSCANRESULTS: + prism2sta_inf_hostscanresults(wlandev, inf); + break; + case HFA384x_IT_SCANRESULTS: + prism2sta_inf_scanresults(wlandev, inf); + break; + case HFA384x_IT_CHINFORESULTS: + prism2sta_inf_chinforesults(wlandev, inf); + break; + case HFA384x_IT_LINKSTATUS: + prism2sta_inf_linkstatus(wlandev, inf); + break; + case HFA384x_IT_ASSOCSTATUS: + prism2sta_inf_assocstatus(wlandev, inf); + break; + case HFA384x_IT_AUTHREQ: + prism2sta_inf_authreq(wlandev, inf); + break; + case HFA384x_IT_PSUSERCNT: + prism2sta_inf_psusercnt(wlandev, inf); + break; + case HFA384x_IT_KEYIDCHANGED: + WLAN_LOG_WARNING("Unhandled IT_KEYIDCHANGED\n"); + break; + case HFA384x_IT_ASSOCREQ: + WLAN_LOG_WARNING("Unhandled IT_ASSOCREQ\n"); + break; + case HFA384x_IT_MICFAILURE: + WLAN_LOG_WARNING("Unhandled IT_MICFAILURE\n"); + break; + default: + WLAN_LOG_WARNING( + "Unknown info type=0x%02x\n", inf->infotype); + break; + } + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_txexc +* +* Handles the TxExc event. A Transmit Exception event indicates +* that the MAC's TX process was unsuccessful - so the packet did +* not get transmitted. +* +* Arguments: +* wlandev wlan device structure +* status tx frame status word +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_txexc(wlandevice_t *wlandev, UINT16 status) +{ + DBFENTER; + + WLAN_LOG_DEBUG(3, "TxExc status=0x%x.\n", status); + + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_tx +* +* Handles the Tx event. +* +* Arguments: +* wlandev wlan device structure +* status tx frame status word +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_tx(wlandevice_t *wlandev, UINT16 status) +{ + DBFENTER; + WLAN_LOG_DEBUG(4, "Tx Complete, status=0x%04x\n", status); + /* update linux network stats */ + wlandev->linux_stats.tx_packets++; + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_rx +* +* Handles the Rx event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb) +{ + DBFENTER; + + p80211netdev_rx(wlandev, skb); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2sta_ev_alloc +* +* Handles the Alloc event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_alloc(wlandevice_t *wlandev) +{ + DBFENTER; + + p80211netdev_wake_queue(wlandev); + + DBFEXIT; + return; +} + +#if (WLAN_HOSTIF == WLAN_PLX || WLAN_HOSTIF == WLAN_PCI) +#ifdef CONFIG_PM +static int prism2sta_suspend_pci(struct pci_dev *pdev, pm_message_t state) +{ + wlandevice_t *wlandev; + + wlandev = (wlandevice_t *) pci_get_drvdata(pdev); + + /* reset hardware */ + if (wlandev) { + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + p80211_suspend(wlandev); + } + + // call a netif_device_detach(wlandev->netdev) ? + + return 0; +} + +static int prism2sta_resume_pci (struct pci_dev *pdev) +{ + wlandevice_t *wlandev; + + wlandev = (wlandevice_t *) pci_get_drvdata(pdev); + + if (wlandev) { + p80211_resume(wlandev); + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); + } + + return 0; +} +#endif +#endif + +/*---------------------------------------------------------------- +* create_wlan +* +* Called at module init time. This creates the wlandevice_t structure +* and initializes it with relevant bits. +* +* Arguments: +* none +* +* Returns: +* the created wlandevice_t structure. +* +* Side effects: +* also allocates the priv/hw structures. +* +* Call context: +* process thread +* +----------------------------------------------------------------*/ +static wlandevice_t *create_wlan(void) +{ + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + + /* Alloc our structures */ + wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL); + hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL); + + if (!wlandev || !hw) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + if (wlandev) kfree(wlandev); + if (hw) kfree(hw); + return NULL; + } + + /* Clear all the structs */ + memset(wlandev, 0, sizeof(wlandevice_t)); + memset(hw, 0, sizeof(hfa384x_t)); + + /* Initialize the network device object. */ + wlandev->nsdname = dev_info; + wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING; + wlandev->priv = hw; + wlandev->open = prism2sta_open; + wlandev->close = prism2sta_close; + wlandev->reset = prism2sta_reset; +#ifdef CONFIG_PROC_FS + wlandev->nsd_proc_read = prism2sta_proc_read; +#endif + wlandev->txframe = prism2sta_txframe; + wlandev->mlmerequest = prism2sta_mlmerequest; + wlandev->set_multicast_list = prism2sta_setmulticast; + wlandev->tx_timeout = hfa384x_tx_timeout; + + wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | + P80211_NSDCAP_AUTOJOIN; + + /* Initialize the device private data stucture. */ + hw->dot11_desired_bss_type = 1; + + return wlandev; +} + +#ifdef CONFIG_PROC_FS +static int +prism2sta_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + char *p = page; + wlandevice_t *wlandev = (wlandevice_t *) data; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + + UINT16 hwtype = 0; + + DBFENTER; + if (offset != 0) { + *eof = 1; + goto exit; + } + + // XXX 0x0001 for prism2.5/3, 0x0000 for prism2. + hwtype = BIT0; + +#if (WLAN_HOSTIF != WLAN_USB) + if (hw->isram16) + hwtype |= BIT1; +#endif + +#if (WLAN_HOSTIF == WLAN_PCI) + hwtype |= BIT2; +#endif + +#define PRISM2_CVS_ID "$Id: prism2sta.c 1858 2008-03-24 18:49:31Z pizza $" + + p += sprintf(p, "# %s version %s (%s) '%s'\n\n", + dev_info, + WLAN_RELEASE, WLAN_BUILD_DATE, PRISM2_CVS_ID); + + p += sprintf(p, "# nic h/w: id=0x%02x %d.%d.%d\n", + hw->ident_nic.id, hw->ident_nic.major, + hw->ident_nic.minor, hw->ident_nic.variant); + + p += sprintf(p, "# pri f/w: id=0x%02x %d.%d.%d\n", + hw->ident_pri_fw.id, hw->ident_pri_fw.major, + hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); + + if (hw->ident_sta_fw.id == 0x1f) { + p += sprintf(p, "# sta f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } else { + p += sprintf(p, "# ap f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } + +#if (WLAN_HOSTIF != WLAN_USB) + p += sprintf(p, "# initial nic hw type, needed for SSF ramdl\n"); + p += sprintf(p, "initnichw=%04x\n", hwtype); +#endif + + exit: + DBFEXIT; + return (p - page); +} +#endif + +void prism2sta_commsqual_defer(struct work_struct *data) +{ + hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); + wlandevice_t *wlandev = hw->wlandev; + hfa384x_bytestr32_t ssid; + int result = 0; + + DBFENTER; + + if (hw->wlandev->hwremoved) + goto done; + + /* we don't care if we're in AP mode */ + if ((wlandev->macmode == WLAN_MACMODE_NONE) || + (wlandev->macmode == WLAN_MACMODE_ESS_AP)) { + goto done; + } + + /* It only makes sense to poll these in non-IBSS */ + if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) { + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY, + &hw->qual, + HFA384x_RID_DBMCOMMSQUALITY_LEN); + + if (result) { + WLAN_LOG_ERROR("error fetching commsqual\n"); + goto done; + } + + // qual.CQ_currBSS; // link + // ASL_currBSS; // level + // qual.ANL_currFC; // noise + + WLAN_LOG_DEBUG(3, "commsqual %d %d %d\n", + hfa384x2host_16(hw->qual.CQ_currBSS), + hfa384x2host_16(hw->qual.ASL_currBSS), + hfa384x2host_16(hw->qual.ANL_currFC)); + } + + /* Lastly, we need to make sure the BSSID didn't change on us */ + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTBSSID, + wlandev->bssid, WLAN_BSSID_LEN); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); + goto done; + } + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTSSID, + &ssid, sizeof(ssid)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); + goto done; + } + prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, + (p80211pstrd_t *) &wlandev->ssid); + + + /* Reschedule timer */ + mod_timer(&hw->commsqual_timer, round_jiffies(jiffies + HZ)); + + done: + DBFEXIT; +} + +void prism2sta_commsqual_timer(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t *) data; + + DBFENTER; + + schedule_work(&hw->commsqual_bh); + + DBFEXIT; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/prism2mgmt.c +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/prism2mgmt.c @@ -0,0 +1,2956 @@ +/* src/prism2/driver/prism2mgmt.c +* +* Management request handler functions. +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* The functions in this file handle management requests sent from +* user mode. +* +* Most of these functions have two separate blocks of code that are +* conditional on whether this is a station or an AP. This is used +* to separate out the STA and AP responses to these management primitives. +* It's a choice (good, bad, indifferent?) to have the code in the same +* place so it's clear that the same primitive is implemented in both +* cases but has different behavior. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (WLAN_HOSTIF == WLAN_USB) +#include +#endif + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#include +#include +#include +#include +#include +#include +#endif + +#include + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + + +/*================================================================*/ +/* Local Macros */ + +/* Converts 802.11 format rate specifications to prism2 */ +#define p80211rate_to_p2bit(n) ((((n)&~BIT7) == 2) ? BIT0 : \ + (((n)&~BIT7) == 4) ? BIT1 : \ + (((n)&~BIT7) == 11) ? BIT2 : \ + (((n)&~BIT7) == 22) ? BIT3 : 0) + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + + +/*================================================================*/ +/* Local Function Declarations */ + + +/*================================================================*/ +/* Function Definitions */ + + +/*---------------------------------------------------------------- +* prism2mgmt_powermgmt +* +* Set the power management state of this station's MAC. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_powermgmt(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_powermgmt_t *msg = msgp; + + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* + * Set CNFPMENABLED (on or off) + * Set CNFMULTICASTRX (if PM on, otherwise clear) + * Spout a notice stating that SleepDuration and + * HoldoverDuration and PMEPS also have an impact. + */ + /* Powermgmt is currently unsupported for STA */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Powermgmt is never supported for AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_scan +* +* Initiate a scan for BSSs. +* +* This function corresponds to MLME-scan.request and part of +* MLME-scan.confirm. As far as I can tell in the standard, there +* are no restrictions on when a scan.request may be issued. We have +* to handle in whatever state the driver/MAC happen to be. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_scan_t *msg = msgp; + UINT16 roamingmode, word; + int i, timeout; + int istmpenable = 0; + + hfa384x_HostScanRequest_data_t scanreq; + + DBFENTER; + + if (hw->ap) { + WLAN_LOG_ERROR("Prism2 in AP mode cannot perform scans.\n"); + result = 1; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto exit; + } + + /* gatekeeper check */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(1,3,2)) { + WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n"); + result = 1; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto exit; + } + + memset(&scanreq, 0, sizeof(scanreq)); + + /* save current roaming mode */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, &roamingmode); + if ( result ) { + WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + /* drop into mode 3 for the scan */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, + HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); + if ( result ) { + WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + /* active or passive? */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) > + HFA384x_FIRMWARE_VERSION(1,5,0)) { + if (msg->scantype.data != P80211ENUM_scantype_active) { + word = host2hfa384x_16(msg->maxchanneltime.data); + } else { + word = 0; + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word); + if ( result ) { + WLAN_LOG_WARNING("Passive scan not supported with " + "current firmware. (<1.5.1)\n"); + } + } + + /* set up the txrate to be 2MBPS. Should be fastest basicrate... */ + word = HFA384x_RATEBIT_2; + scanreq.txRate = host2hfa384x_16(word); + + /* set up the channel list */ + word = 0; + for (i = 0; i < msg->channellist.data.len; i++) { + UINT8 channel = msg->channellist.data.data[i]; + if (channel > 14) continue; + /* channel 1 is BIT0 ... channel 14 is BIT13 */ + word |= (1 << (channel-1)); + } + scanreq.channelList = host2hfa384x_16(word); + + /* set up the ssid, if present. */ + scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len); + memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len); + + /* Enable the MAC port if it's not already enabled */ + result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word); + if ( result ) { + WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. " + "result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + if (word == HFA384x_PORTSTATUS_DISABLED) { + UINT16 wordbuf[17]; + + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, + HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); + if ( result ) { + WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + /* Construct a bogus SSID and assign it to OwnSSID and + * DesiredSSID + */ + wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN); + get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN); + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, + wordbuf, HFA384x_RID_CNFOWNSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set OwnSSID.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID, + wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set DesiredSSID.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + /* bsstype */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFPORTTYPE, + HFA384x_PORTTYPE_IBSS); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + /* ibss options */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CREATEIBSS, + HFA384x_CREATEIBSS_JOINCREATEIBSS); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("drvr_enable(0) failed. " + "result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + istmpenable = 1; + } + + /* Figure out our timeout first Kus, then HZ */ + timeout = msg->channellist.data.len * msg->maxchanneltime.data; + timeout = (timeout * HZ)/1000; + + /* Issue the scan request */ + hw->scanflag = 0; + + WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq)); + + result = hfa384x_drvr_setconfig( hw, + HFA384x_RID_HOSTSCAN, &scanreq, + sizeof(hfa384x_HostScanRequest_data_t)); + if ( result ) { + WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + /* sleep until info frame arrives */ + wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout); + + msg->numbss.status = P80211ENUM_msgitem_status_data_ok; + if (hw->scanflag == -1) + hw->scanflag = 0; + + msg->numbss.data = hw->scanflag; + + hw->scanflag = 0; + + /* Disable port if we temporarily enabled it. */ + if (istmpenable) { + result = hfa384x_drvr_disable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("drvr_disable(0) failed. " + "result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + } + + /* restore original roaming mode */ + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, + roamingmode); + if ( result ) { + WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + result = 0; + msg->resultcode.data = P80211ENUM_resultcode_success; + + exit: + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_scan_results +* +* Retrieve the BSS description for one of the BSSs identified in +* a scan. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + p80211msg_dot11req_scan_results_t *req; + hfa384x_t *hw = wlandev->priv; + hfa384x_HScanResultSub_t *item = NULL; + + int count; + + DBFENTER; + + req = (p80211msg_dot11req_scan_results_t *) msgp; + + req->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + if (hw->ap) { + result = 1; + req->resultcode.data = P80211ENUM_resultcode_not_supported; + goto exit; + } + + if (! hw->scanresults) { + WLAN_LOG_ERROR("dot11req_scan_results can only be used after a successful dot11req_scan.\n"); + result = 2; + req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + goto exit; + } + + count = (hw->scanresults->framelen - 3) / 32; + if (count > 32) count = 32; + + if (req->bssindex.data >= count) { + WLAN_LOG_DEBUG(0, "requested index (%d) out of range (%d)\n", + req->bssindex.data, count); + result = 2; + req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + goto exit; + } + + item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]); + /* signal and noise */ + req->signal.status = P80211ENUM_msgitem_status_data_ok; + req->noise.status = P80211ENUM_msgitem_status_data_ok; + req->signal.data = hfa384x2host_16(item->sl); + req->noise.data = hfa384x2host_16(item->anl); + + /* BSSID */ + req->bssid.status = P80211ENUM_msgitem_status_data_ok; + req->bssid.data.len = WLAN_BSSID_LEN; + memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN); + + /* SSID */ + req->ssid.status = P80211ENUM_msgitem_status_data_ok; + req->ssid.data.len = hfa384x2host_16(item->ssid.len); + memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); + + /* supported rates */ + for (count = 0; count < 10 ; count++) + if (item->supprates[count] == 0) + break; + +#define REQBASICRATE(N) \ + if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \ + req->basicrate ## N .data = item->supprates[(N)-1]; \ + req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \ + } + + REQBASICRATE(1); + REQBASICRATE(2); + REQBASICRATE(3); + REQBASICRATE(4); + REQBASICRATE(5); + REQBASICRATE(6); + REQBASICRATE(7); + REQBASICRATE(8); + +#define REQSUPPRATE(N) \ + if (count >= N) { \ + req->supprate ## N .data = item->supprates[(N)-1]; \ + req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \ + } + + REQSUPPRATE(1); + REQSUPPRATE(2); + REQSUPPRATE(3); + REQSUPPRATE(4); + REQSUPPRATE(5); + REQSUPPRATE(6); + REQSUPPRATE(7); + REQSUPPRATE(8); + + /* beacon period */ + req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok; + req->beaconperiod.data = hfa384x2host_16(item->bcnint); + + /* timestamps */ + req->timestamp.status = P80211ENUM_msgitem_status_data_ok; + req->timestamp.data = jiffies; + req->localtime.status = P80211ENUM_msgitem_status_data_ok; + req->localtime.data = jiffies; + + /* atim window */ + req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok; + req->ibssatimwindow.data = hfa384x2host_16(item->atim); + + /* Channel */ + req->dschannel.status = P80211ENUM_msgitem_status_data_ok; + req->dschannel.data = hfa384x2host_16(item->chid); + + /* capinfo bits */ + count = hfa384x2host_16(item->capinfo); + + /* privacy flag */ + req->privacy.status = P80211ENUM_msgitem_status_data_ok; + req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count); + + /* cfpollable */ + req->cfpollable.status = P80211ENUM_msgitem_status_data_ok; + req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count); + + /* cfpollreq */ + req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok; + req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count); + + /* bsstype */ + req->bsstype.status = P80211ENUM_msgitem_status_data_ok; + req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ? + P80211ENUM_bsstype_infrastructure : + P80211ENUM_bsstype_independent; + + // item->proberesp_rate +/* + req->fhdwelltime + req->fhhopset + req->fhhoppattern + req->fhhopindex + req->cfpdurremaining +*/ + + result = 0; + req->resultcode.data = P80211ENUM_resultcode_success; + + exit: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_join +* +* Join a BSS whose BSS description was previously obtained with +* a scan. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_join(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_join_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Implement after scan */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Never supported by APs */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_p2_join +* +* Join a specific BSS +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_join_t *msg = msgp; + UINT16 reg; + p80211pstrd_t *pstr; + UINT8 bytebuf[256]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; + hfa384x_JoinRequest_data_t joinreq; + DBFENTER; + + if (!hw->ap) { + + wlandev->macmode = WLAN_MACMODE_NONE; + + /*** STATION ***/ + /* Set the PortType */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + /* ess port */ + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1); + if ( result ) { + WLAN_LOG_ERROR("Failed to set Port Type\n"); + goto failed; + } + + /* Set the auth type */ + if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) { + reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY; + } else { + reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set Authentication\n"); + goto failed; + } + + /* Turn off all roaming */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, 3); + if ( result ) { + WLAN_LOG_ERROR("Failed to Turn off Roaming\n"); + goto failed; + } + + /* Basic rates */ + reg = 0; + if ( msg->basicrate1.status == P80211ENUM_msgitem_status_data_ok ) { + reg = p80211rate_to_p2bit(msg->basicrate1.data); + } + if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate2.data); + } + if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate3.data); + } + if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate4.data); + } + if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate5.data); + } + if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate6.data); + } + if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate7.data); + } + if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate8.data); + } + if( reg == 0) + reg = 0x03; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", reg); + goto failed; + } + + /* Operational rates (supprates and txratecontrol) */ + reg = 0; + if ( msg->operationalrate1.status == P80211ENUM_msgitem_status_data_ok ) { + reg = p80211rate_to_p2bit(msg->operationalrate1.data); + } + if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate2.data); + } + if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate3.data); + } + if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate4.data); + } + if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate5.data); + } + if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate6.data); + } + if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate7.data); + } + if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate8.data); + } + if( reg == 0) + reg = 0x0f; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set supprates=%d.\n", reg); + goto failed; + } + + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set txrates=%d.\n", reg); + goto failed; + } + + /* Set the ssid */ + memset(bytebuf, 0, 256); + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( + hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set SSID\n"); + goto failed; + } + + /* Enable the Port */ + result = hfa384x_cmd_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + /* Fill in the join request */ + joinreq.channel = msg->channel.data; + memcpy( joinreq.bssid, ((unsigned char *) &msg->bssid.data) + 1, WLAN_BSSID_LEN); + hw->joinreq = joinreq; + hw->join_ap = 1; + + /* Send the join request */ + result = hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + if(result != 0) { + WLAN_LOG_ERROR("Join request failed, result=%d.\n", result); + goto failed; + } + + } else { + + /*** ACCESS POINT ***/ + + /* Never supported by APs */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + goto done; +failed: + WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result); + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + +done: + result = 0; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_authenticate +* +* Station should be begin an authentication exchange. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_authenticate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_authenticate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Decide how we're going to handle this one w/ Prism2 */ + /* It could be entertaining since Prism2 doesn't have */ + /* an explicit way to control this */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Never supported by APs */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_deauthenticate +* +* Send a deauthenticate notification. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_deauthenticate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_deauthenticate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Decide how we're going to handle this one w/ Prism2 */ + /* It could be entertaining since Prism2 doesn't have */ + /* an explicit way to control this */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data); + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_associate +* +* Associate with an ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + int result = 0; + p80211msg_dot11req_associate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + +#if 0 + /* Set the TxRates */ + reg = 0x000f; + hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg); +#endif + + /* Set the PortType */ + /* ess port */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1); + + /* Enable the Port */ + hfa384x_drvr_enable(hw, 0); + + /* Set the resultcode */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + } else { + + /*** ACCESS POINT ***/ + + /* Never supported on AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_reassociate +* +* Renew association because of a BSS change. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_reassociate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_reassociate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Not supported yet...not sure how we're going to do it */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Never supported on AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_disassociate +* +* Send a disassociation notification. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_disassociate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_disassociate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Not supported yet...not sure how to do it */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data); + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_reset +* +* Reset the MAC and MSD. The p80211 layer has it's own handling +* that should be done before and after this function. +* Procedure: +* - disable system interrupts ?? +* - disable MAC interrupts +* - restore system interrupts +* - issue the MAC initialize command +* - clear any MSD level state (including timers, queued events, +* etc.). Note that if we're removing timer'd/queue events, we may +* need to have remained in the system interrupt disabled state. +* We should be left in the same state that we're in following +* driver initialization. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer, MAY BE NULL! for a driver local +* call. +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread, commonly wlanctl, but might be rmmod/pci_close. +----------------------------------------------------------------*/ +int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_reset_t *msg = msgp; + DBFENTER; + + /* + * This is supported on both AP and STA and it's not allowed + * to fail. + */ + if ( msgp ) { + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + WLAN_LOG_INFO("dot11req_reset: the macaddress and " + "setdefaultmib arguments are currently unsupported.\n"); + } + + /* + * If we got this far, the MSD must be in the MSDRUNNING state + * therefore, we must stop and then restart the hw/MAC combo. + */ + hfa384x_drvr_stop(hw); + result = hfa384x_drvr_start(hw); + if (result != 0) { + WLAN_LOG_ERROR("dot11req_reset: Initialize command failed," + " bad things will happen from here.\n"); + return 0; + } + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_start +* +* Start a BSS. Any station can do this for IBSS, only AP for ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_start_t *msg = msgp; + + p80211pstrd_t *pstr; + UINT8 bytebuf[80]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; + hfa384x_PCFInfo_data_t *pcfinfo = (hfa384x_PCFInfo_data_t*)bytebuf; + UINT16 word; + DBFENTER; + + wlandev->macmode = WLAN_MACMODE_NONE; + + /* Set the SSID */ + memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); + + if (!hw->ap) { + /*** ADHOC IBSS ***/ + /* see if current f/w is less than 8c3 */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(0,8,3)) { + /* Ad-Hoc not quite supported on Prism2 */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /*** STATION ***/ + /* Set the REQUIRED config items */ + /* SSID */ + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, + bytebuf, HFA384x_RID_CNFOWNSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CnfOwnSSID\n"); + goto failed; + } + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CnfDesiredSSID\n"); + goto failed; + } + + /* bsstype - we use the default in the ap firmware */ + /* IBSS port */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0); + + /* beacon period */ + word = msg->beaconperiod.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word); + goto failed; + } + + /* dschannel */ + word = msg->dschannel.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set channel=%d.\n", word); + goto failed; + } + /* Basic rates */ + word = p80211rate_to_p2bit(msg->basicrate1.data); + if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate2.data); + } + if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate3.data); + } + if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate4.data); + } + if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate5.data); + } + if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate6.data); + } + if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate7.data); + } + if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word); + goto failed; + } + + /* Operational rates (supprates and txratecontrol) */ + word = p80211rate_to_p2bit(msg->operationalrate1.data); + if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate2.data); + } + if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate3.data); + } + if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate4.data); + } + if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate5.data); + } + if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate6.data); + } + if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate7.data); + } + if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word); + goto failed; + } + + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word); + goto failed; + } + + /* Set the macmode so the frame setup code knows what to do */ + if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) { + wlandev->macmode = WLAN_MACMODE_IBSS_STA; + /* lets extend the data length a bit */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304); + } + + /* Enable the Port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + + goto done; + } + + /*** ACCESS POINT ***/ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* Validate the command, if BSStype=infra is the tertiary loaded? */ + if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) { + WLAN_LOG_ERROR("AP driver cannot create IBSS.\n"); + goto failed; + } else if ( hw->cap_sup_sta.id != 5) { + WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n"); + goto failed; + } + + /* Set the REQUIRED config items */ + /* SSID */ + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, + bytebuf, HFA384x_RID_CNFOWNSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set SSID, result=0x%04x\n", result); + goto failed; + } + + /* bsstype - we use the default in the ap firmware */ + + /* beacon period */ + word = msg->beaconperiod.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word); + goto failed; + } + + /* dschannel */ + word = msg->dschannel.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set channel=%d.\n", word); + goto failed; + } + /* Basic rates */ + word = p80211rate_to_p2bit(msg->basicrate1.data); + if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate2.data); + } + if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate3.data); + } + if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate4.data); + } + if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate5.data); + } + if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate6.data); + } + if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate7.data); + } + if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word); + goto failed; + } + + /* Operational rates (supprates and txratecontrol) */ + word = p80211rate_to_p2bit(msg->operationalrate1.data); + if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate2.data); + } + if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate3.data); + } + if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate4.data); + } + if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate5.data); + } + if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate6.data); + } + if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate7.data); + } + if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word); + goto failed; + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL0, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word); + goto failed; + } + + /* ibssatimwindow */ + if (msg->ibssatimwindow.status == P80211ENUM_msgitem_status_data_ok) { + WLAN_LOG_INFO("prism2mgmt_start: atimwindow not used in " + "Infrastructure mode, ignored.\n"); + } + + /* DTIM period */ + word = msg->dtimperiod.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNDTIMPER, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set dtim period=%d.\n", word); + goto failed; + } + + /* probedelay */ + if (msg->probedelay.status == P80211ENUM_msgitem_status_data_ok) { + WLAN_LOG_INFO("prism2mgmt_start: probedelay not " + "supported in prism2, ignored.\n"); + } + + /* cfpollable, cfpollreq, cfpperiod, cfpmaxduration */ + if (msg->cfpollable.data == P80211ENUM_truth_true && + msg->cfpollreq.data == P80211ENUM_truth_true ) { + WLAN_LOG_ERROR("cfpollable=cfpollreq=true is illegal.\n"); + result = -1; + goto failed; + } + + /* read the PCFInfo and update */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFAPPCFINFO, + pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN); + if ( result ) { + WLAN_LOG_INFO("prism2mgmt_start: read(pcfinfo) failed, " + "assume it's " + "not supported, pcf settings ignored.\n"); + goto pcf_skip; + } + if ((msg->cfpollable.data == P80211ENUM_truth_false && + msg->cfpollreq.data == P80211ENUM_truth_false) ) { + pcfinfo->MediumOccupancyLimit = 0; + pcfinfo->CFPPeriod = 0; + pcfinfo->CFPMaxDuration = 0; + pcfinfo->CFPFlags &= host2hfa384x_16((UINT16)~BIT0); + + if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok || + msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok ) { + WLAN_LOG_WARNING( + "Setting cfpperiod or cfpmaxduration when " + "cfpollable and cfreq are false is pointless.\n"); + } + } + if ((msg->cfpollable.data == P80211ENUM_truth_true || + msg->cfpollreq.data == P80211ENUM_truth_true) ) { + if ( msg->cfpollable.data == P80211ENUM_truth_true) { + pcfinfo->CFPFlags |= host2hfa384x_16((UINT16)BIT0); + } + + if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok) { + pcfinfo->CFPPeriod = msg->cfpperiod.data; + pcfinfo->CFPPeriod = host2hfa384x_16(pcfinfo->CFPPeriod); + } + + if ( msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok) { + pcfinfo->CFPMaxDuration = msg->cfpmaxduration.data; + pcfinfo->CFPMaxDuration = host2hfa384x_16(pcfinfo->CFPMaxDuration); + pcfinfo->MediumOccupancyLimit = pcfinfo->CFPMaxDuration; + } + } + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFAPPCFINFO, + pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN); + if ( result ) { + WLAN_LOG_ERROR("write(pcfinfo) failed.\n"); + goto failed; + } + +pcf_skip: + /* Set the macmode so the frame setup code knows what to do */ + if ( msg->bsstype.data == P80211ENUM_bsstype_infrastructure ) { + wlandev->macmode = WLAN_MACMODE_ESS_AP; + /* lets extend the data length a bit */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304); + } + + /* Set the BSSID to the same as our MAC */ + memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN); + + /* Enable the Port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + + goto done; +failed: + WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result); + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + +done: + result = 0; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_enable +* +* Start a BSS. Any station can do this for IBSS, only AP for ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_enable(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_enable_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* Ad-Hoc not quite supported on Prism2 */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + /*** ACCESS POINT ***/ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* Is the tertiary loaded? */ + if ( hw->cap_sup_sta.id != 5) { + WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n"); + goto failed; + } + + /* Set the macmode so the frame setup code knows what to do */ + wlandev->macmode = WLAN_MACMODE_ESS_AP; + + /* Set the BSSID to the same as our MAC */ + memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN); + + /* Enable the Port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + + goto done; +failed: + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + +done: + result = 0; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_readpda +* +* Collect the PDA data and put it in the message. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_readpda_t *msg = msgp; + int result; + DBFENTER; + + /* We only support collecting the PDA when in the FWLOAD + * state. + */ + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "PDA may only be read " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + } else { + /* Call drvr_readpda(), it handles the auxport enable + * and validating the returned PDA. + */ + result = hfa384x_drvr_readpda( + hw, + msg->pda.data, + HFA384x_PDA_LEN_MAX); + if (result) { + WLAN_LOG_ERROR( + "hfa384x_drvr_readpda() failed, " + "result=%d\n", + result); + + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = + P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + msg->pda.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + } + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_readcis +* +* Collect the CIS data and put it in the message. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp) +{ + int result; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_readcis_t *msg = msgp; + + DBFENTER; + + memset(msg->cis.data, 0, sizeof(msg->cis.data)); + + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CIS, + msg->cis.data, HFA384x_RID_CIS_LEN); + if ( result ) { + WLAN_LOG_INFO("prism2mgmt_readcis: read(cis) failed.\n"); + msg->cis.status = P80211ENUM_msgitem_status_no_value; + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + + } + else { + msg->cis.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_auxport_state +* +* Enables/Disables the card's auxiliary port. Should be called +* before and after a sequence of auxport_read()/auxport_write() +* calls. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp) +{ + p80211msg_p2req_auxport_state_t *msg = msgp; + +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + if (msg->enable.data == P80211ENUM_truth_true) { + if ( hfa384x_cmd_aux_enable(hw, 0) ) { + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } else { + msg->resultcode.data = P80211ENUM_resultcode_success; + } + } else { + hfa384x_cmd_aux_disable(hw); + msg->resultcode.data = P80211ENUM_resultcode_success; + } + +#else /* !USB */ + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + +#endif /* WLAN_HOSTIF != WLAN_USB */ + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_auxport_read +* +* Copies data from the card using the auxport. The auxport must +* have previously been enabled. Note: this is not the way to +* do downloads, see the [ram|flash]dl functions. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp) +{ +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_auxport_read_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8* buf; + UINT32 maxlen = sizeof(msg->data.data); + DBFENTER; + + if ( hw->auxen ) { + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( len <= maxlen ) { /* max read/write size */ + hfa384x_copy_from_aux(hw, addr, HFA384x_AUX_CTL_EXTDS, buf, len); + msg->resultcode.data = P80211ENUM_resultcode_success; + } else { + WLAN_LOG_DEBUG(1,"Attempt to read > maxlen from auxport.\n"); + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + + } else { + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + msg->data.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return 0; +#else + DBFENTER; + + WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n"); + + DBFEXIT; + return 0; +#endif +} + + +/*---------------------------------------------------------------- +* prism2mgmt_auxport_write +* +* Copies data to the card using the auxport. The auxport must +* have previously been enabled. Note: this is not the way to +* do downloads, see the [ram|flash]dl functions. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp) +{ +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_auxport_write_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8* buf; + UINT32 maxlen = sizeof(msg->data.data); + DBFENTER; + + if ( hw->auxen ) { + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( len <= maxlen ) { /* max read/write size */ + hfa384x_copy_to_aux(hw, addr, HFA384x_AUX_CTL_EXTDS, buf, len); + } else { + WLAN_LOG_DEBUG(1,"Attempt to write > maxlen from auxport.\n"); + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + + } else { + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + msg->data.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return 0; +#else + DBFENTER; + WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n"); + DBFEXIT; + return 0; +#endif +} + +/*---------------------------------------------------------------- +* prism2mgmt_low_level +* +* Puts the card into the desired test mode. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_low_level_t *msg = msgp; + hfa384x_metacmd_t cmd; + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* call some routine to execute the test command */ + cmd.cmd = (UINT16) msg->command.data; + cmd.parm0 = (UINT16) msg->param0.data; + cmd.parm1 = (UINT16) msg->param1.data; + cmd.parm2 = (UINT16) msg->param2.data; + + hfa384x_drvr_low_level(hw,&cmd); + + msg->resp0.data = (UINT32) cmd.result.resp0; + msg->resp1.data = (UINT32) cmd.result.resp1; + msg->resp2.data = (UINT32) cmd.result.resp2; + + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_test_command +* +* Puts the card into the desired test mode. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_test_command_t *msg = msgp; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = ((UINT16) msg->testcode.data) << 8 | 0x38; + cmd.parm0 = (UINT16) msg->testparam.data; + cmd.parm1 = 0; + cmd.parm2 = 0; + + /* call some routine to execute the test command */ + + hfa384x_drvr_low_level(hw,&cmd); + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + msg->status.status = P80211ENUM_msgitem_status_data_ok; + msg->status.data = cmd.result.status; + msg->resp0.status = P80211ENUM_msgitem_status_data_ok; + msg->resp0.data = cmd.result.resp0; + msg->resp1.status = P80211ENUM_msgitem_status_data_ok; + msg->resp1.data = cmd.result.resp1; + msg->resp2.status = P80211ENUM_msgitem_status_data_ok; + msg->resp2.data = cmd.result.resp2; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_mmi_read +* +* Read from one of the MMI registers. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_mmi_read_t *msg = msgp; + UINT32 resp = 0; + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* call some routine to execute the test command */ + + hfa384x_drvr_mmi_read(hw, msg->addr.data, &resp); + + /* I'm not sure if this is "architecturally" correct, but it + is expedient. */ + + msg->value.status = P80211ENUM_msgitem_status_data_ok; + msg->value.data = resp; + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_mmi_write +* +* Write a data value to one of the MMI registers. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_mmi_write_t *msg = msgp; + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* call some routine to execute the test command */ + + hfa384x_drvr_mmi_write(hw, msg->addr.data, msg->data.data); + + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_ramdl_state +* +* Establishes the beginning/end of a card RAM download session. +* +* It is expected that the ramdl_write() function will be called +* one or more times between the 'enable' and 'disable' calls to +* this function. +* +* Note: This function should not be called when a mac comm port +* is active. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_ramdl_state_t *msg = msgp; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "ramdl_state(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + /* + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + if ( msg->enable.data == P80211ENUM_truth_true ) { + if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) { + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } else { + msg->resultcode.data = P80211ENUM_resultcode_success; + } + } else { + hfa384x_drvr_ramdl_disable(hw); + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_ramdl_write +* +* Writes a buffer to the card RAM using the download state. This +* is for writing code to card RAM. To just read or write raw data +* use the aux functions. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_ramdl_write_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8 *buf; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "ramdl_write(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + /* first validate the length */ + if ( msg->len.data > sizeof(msg->data.data) ) { + msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters; + return 0; + } + /* call the hfa384x function to do the write */ + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) { + msg->resultcode.data = P80211ENUM_resultcode_refused; + + } + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_flashdl_state +* +* Establishes the beginning/end of a card Flash download session. +* +* It is expected that the flashdl_write() function will be called +* one or more times between the 'enable' and 'disable' calls to +* this function. +* +* Note: This function should not be called when a mac comm port +* is active. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_flashdl_state_t *msg = msgp; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "flashdl_state(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + /* + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + if ( msg->enable.data == P80211ENUM_truth_true ) { + if ( hfa384x_drvr_flashdl_enable(hw) ) { + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } else { + msg->resultcode.data = P80211ENUM_resultcode_success; + } + } else { + hfa384x_drvr_flashdl_disable(hw); + msg->resultcode.data = P80211ENUM_resultcode_success; + /* NOTE: At this point, the MAC is in the post-reset + * state and the driver is in the fwload state. + * We need to get the MAC back into the fwload + * state. To do this, we set the nsdstate to HWPRESENT + * and then call the ifstate function to redo everything + * that got us into the fwload state. + */ + wlandev->msdstate = WLAN_MSD_HWPRESENT; + result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload); + if (result != P80211ENUM_resultcode_success) { + WLAN_LOG_ERROR("prism2sta_ifstate(fwload) failed," + "P80211ENUM_resultcode=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + result = -1; + } + } + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_flashdl_write +* +* +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_flashdl_write_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8 *buf; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "flashdl_write(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + /* + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + /* first validate the length */ + if ( msg->len.data > sizeof(msg->data.data) ) { + msg->resultcode.status = + P80211ENUM_resultcode_invalid_parameters; + return 0; + } + /* call the hfa384x function to do the write */ + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) { + msg->resultcode.data = P80211ENUM_resultcode_refused; + + } + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_dump_state +* +* Dumps the driver's and hardware's current state via the kernel +* log at KERN_NOTICE level. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp) +{ + p80211msg_p2req_dump_state_t *msg = msgp; + int result = 0; + +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + UINT16 auxbuf[15]; + DBFENTER; + + WLAN_LOG_NOTICE("prism2 driver and hardware state:\n"); + if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { + WLAN_LOG_ERROR("aux_enable failed, result=%d\n", result); + goto failed; + } + hfa384x_copy_from_aux(hw, + 0x01e2, + HFA384x_AUX_CTL_EXTDS, + auxbuf, + sizeof(auxbuf)); + hfa384x_cmd_aux_disable(hw); + WLAN_LOG_NOTICE(" cmac: FreeBlocks=%d\n", auxbuf[5]); + WLAN_LOG_NOTICE(" cmac: IntEn=0x%02x EvStat=0x%02x\n", + hfa384x_getreg(hw, HFA384x_INTEN), + hfa384x_getreg(hw, HFA384x_EVSTAT)); + + #ifdef USE_FID_STACK + WLAN_LOG_NOTICE(" drvr: txfid_top=%d stacksize=%d\n", + hw->txfid_top,HFA384x_DRVR_FIDSTACKLEN_MAX); + #else + WLAN_LOG_NOTICE(" drvr: txfid_head=%d txfid_tail=%d txfid_N=%d\n", + hw->txfid_head, hw->txfid_tail, hw->txfid_N); + #endif + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + +#else /* (WLAN_HOSTIF == WLAN_USB) */ + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto failed; + +#endif /* (WLAN_HOSTIF != WLAN_USB) */ + +failed: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* prism2mgmt_channel_info +* +* Issues a ChannelInfoRequest. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_channel_info(wlandevice_t *wlandev, void *msgp) +{ + p80211msg_p2req_channel_info_t *msg=msgp; + hfa384x_t *hw = wlandev->priv; + int result, i, n=0; + UINT16 channel_mask=0; + hfa384x_ChannelInfoRequest_data_t chinforeq; + // unsigned long now; + + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* Not supported in STA f/w */ + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_not_supported); + goto done; + } + + /*** ACCESS POINT ***/ + +#define CHINFO_TIMEOUT 2 + + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_success); + + /* setting default value for channellist = all channels */ + if (!msg->channellist.data) { + P80211_SET_INT(msg->channellist, 0x00007FFE); + } + /* setting default value for channeldwelltime = 100 ms */ + if (!msg->channeldwelltime.data) { + P80211_SET_INT(msg->channeldwelltime, 100); + } + channel_mask = (UINT16) (msg->channellist.data >> 1); + for (i=0, n=0; i < 14; i++) { + if (channel_mask & (1<numchinfo, n); + chinforeq.channelList = host2hfa384x_16(channel_mask); + chinforeq.channelDwellTime = host2hfa384x_16(msg->channeldwelltime.data); + + atomic_set(&hw->channel_info.done, 1); + + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CHANNELINFOREQUEST, + &chinforeq, HFA384x_RID_CHANNELINFOREQUEST_LEN); + if ( result ) { + WLAN_LOG_ERROR("setconfig(CHANNELINFOREQUEST) failed. result=%d\n", + result); + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + /* + now = jiffies; + while (atomic_read(&hw->channel_info.done) != 1) { + if ((jiffies - now) > CHINFO_TIMEOUT*HZ) { + WLAN_LOG_NOTICE("ChannelInfo results not received in %d seconds, aborting.\n", + CHINFO_TIMEOUT); + msg->resultcode.data = P80211ENUM_resultcode_timeout; + goto done; + } + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/4); + current->state = TASK_RUNNING; + } + */ + +done: + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_channel_info_results +* +* Returns required ChannelInfo result. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_channel_info_results(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + + p80211msg_p2req_channel_info_results_t *msg=msgp; + int result=0; + int channel; + + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* Not supported in STA f/w */ + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_not_supported); + goto done; + } + + /*** ACCESS POINT ***/ + + switch (atomic_read(&hw->channel_info.done)) { + case 0: msg->resultcode.status = P80211ENUM_msgitem_status_no_value; + goto done; + case 1: msg->resultcode.status = P80211ENUM_msgitem_status_incomplete_itemdata; + goto done; + } + + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_success); + channel=msg->channel.data-1; + + if (channel < 0 || ! (hw->channel_info.results.scanchannels & 1<resultcode.data = P80211ENUM_resultcode_invalid_parameters; + goto done; + } + WLAN_LOG_DEBUG(2, "chinfo_results: channel %d, avg/peak level=%d/%d dB, active=%d\n", + channel+1, + hw->channel_info.results.result[channel].anl, + hw->channel_info.results.result[channel].pnl, + hw->channel_info.results.result[channel].active + ); + P80211_SET_INT(msg->avgnoiselevel, hw->channel_info.results.result[channel].anl); + P80211_SET_INT(msg->peaknoiselevel, hw->channel_info.results.result[channel].pnl); + P80211_SET_INT(msg->bssactive, hw->channel_info.results.result[channel].active & + HFA384x_CHINFORESULT_BSSACTIVE + ? P80211ENUM_truth_true + : P80211ENUM_truth_false) ; + P80211_SET_INT(msg->pcfactive, hw->channel_info.results.result[channel].active & + HFA384x_CHINFORESULT_PCFACTIVE + ? P80211ENUM_truth_true + : P80211ENUM_truth_false) ; + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_autojoin +* +* Associate with an ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + int result = 0; + UINT16 reg; + UINT16 port_type; + p80211msg_lnxreq_autojoin_t *msg = msgp; + p80211pstrd_t *pstr; + UINT8 bytebuf[256]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; + DBFENTER; + + wlandev->macmode = WLAN_MACMODE_NONE; + + /* Set the SSID */ + memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); + + if (hw->ap) { + + /*** ACCESS POINT ***/ + + /* Never supported on AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + /* Disable the Port */ + hfa384x_drvr_disable(hw, 0); + + /*** STATION ***/ + /* Set the TxRates */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f); + + /* Set the auth type */ + if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) { + reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY; + } else { + reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; + } + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg); + + /* Set the ssid */ + memset(bytebuf, 0, 256); + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( + hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); +#if 0 + /* we can use the new-fangled auto-unknown mode if the firmware + is 1.3.3 or newer */ + if (HFA384x_FIRMARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) >= + HFA384x_FIRMWARE_VERSION(1,3,3)) { + /* Set up the IBSS options */ + reg = HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS; + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CREATEIBSS, reg); + + /* Set the PortType */ + port_type = HFA384x_PORTTYPE_IBSS; + } else { + port_type = HFA384x_PORTTYPE_BSS; + } +#else + port_type = HFA384x_PORTTYPE_BSS; +#endif + /* Set the PortType */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type); + + /* Enable the Port */ + hfa384x_drvr_enable(hw, 0); + + /* Set the resultcode */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_wlansniff +* +* Start or stop sniffing. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + p80211msg_lnxreq_wlansniff_t *msg = msgp; + + hfa384x_t *hw = wlandev->priv; + UINT16 word; + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + switch (msg->enable.data) + { + case P80211ENUM_truth_false: + /* Confirm that we're in monitor mode */ + if ( wlandev->netdev->type == ARPHRD_ETHER ) { + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + result = 0; + goto exit; + } + /* Disable monitor mode */ + result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to disable monitor mode, result=%d\n", + result); + goto failed; + } + /* Disable port 0 */ + result = hfa384x_drvr_disable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to disable port 0 after sniffing, result=%d\n", + result); + goto failed; + } + /* Clear the driver state */ + wlandev->netdev->type = ARPHRD_ETHER; + + /* Restore the wepflags */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFWEPFLAGS, + hw->presniff_wepflags); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to restore wepflags=0x%04x, result=%d\n", + hw->presniff_wepflags, + result); + goto failed; + } + + /* Set the port to its prior type and enable (if necessary) */ + if (hw->presniff_port_type != 0 ) { + word = hw->presniff_port_type; + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFPORTTYPE, word); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to restore porttype, result=%d\n", + result); + goto failed; + } + + /* Enable the port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, "failed to enable port to presniff setting, result=%d\n", result); + goto failed; + } + } else { + result = hfa384x_drvr_disable(hw, 0); + + } + + WLAN_LOG_INFO("monitor mode disabled\n"); + msg->resultcode.data = P80211ENUM_resultcode_success; + result = 0; + goto exit; + break; + case P80211ENUM_truth_true: + /* Disable the port (if enabled), only check Port 0 */ + if ( hw->port_enabled[0]) { + if (wlandev->netdev->type == ARPHRD_ETHER) { + /* Save macport 0 state */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_CNFPORTTYPE, + &(hw->presniff_port_type)); + if ( result ) { + WLAN_LOG_DEBUG(1,"failed to read porttype, result=%d\n", result); + goto failed; + } + /* Save the wepflags state */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_CNFWEPFLAGS, + &(hw->presniff_wepflags)); + if ( result ) { + WLAN_LOG_DEBUG(1,"failed to read wepflags, result=%d\n", result); + goto failed; + } + hfa384x_drvr_stop(hw); + result = hfa384x_drvr_start(hw); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to restart the card for sniffing, result=%d\n", + result); + goto failed; + } + } else { + /* Disable the port */ + result = hfa384x_drvr_disable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to enable port for sniffing, result=%d\n", + result); + goto failed; + } + } + } else { + hw->presniff_port_type = 0; + } + + /* Set the channel we wish to sniff */ + word = msg->channel.data; + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFOWNCHANNEL, word); + hw->sniff_channel=word; + + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to set channel %d, result=%d\n", + word, + result); + goto failed; + } + + /* Now if we're already sniffing, we can skip the rest */ + if (wlandev->netdev->type != ARPHRD_ETHER) { + /* Set the port type to pIbss */ + word = HFA384x_PORTTYPE_PSUEDOIBSS; + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFPORTTYPE, word); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to set porttype %d, result=%d\n", + word, + result); + goto failed; + } + if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) { + /* Set the wepflags for no decryption */ + word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT | + HFA384x_WEPFLAGS_DISABLE_RXCRYPT; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word); + } + + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to set wepflags=0x%04x, result=%d\n", + word, + result); + goto failed; + } + } + + /* Do we want to strip the FCS in monitor mode? */ + if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) { + hw->sniff_fcs = 0; + } else { + hw->sniff_fcs = 1; + } + + /* Do we want to truncate the packets? */ + if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) { + hw->sniff_truncate = msg->packet_trunc.data; + } else { + hw->sniff_truncate = 0; + } + + /* Enable the port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to enable port for sniffing, result=%d\n", + result); + goto failed; + } + /* Enable monitor mode */ + result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to enable monitor mode, result=%d\n", + result); + goto failed; + } + + if (wlandev->netdev->type == ARPHRD_ETHER) { + WLAN_LOG_INFO("monitor mode enabled\n"); + } + + /* Set the driver state */ + /* Do we want the prism2 header? */ + if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) { + hw->sniffhdr = 0; + wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; + } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) { + hw->sniffhdr = 1; + wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; + } else { + wlandev->netdev->type = ARPHRD_IEEE80211; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + result = 0; + goto exit; + break; + default: + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + result = 0; + goto exit; + break; + } + +failed: + msg->resultcode.data = P80211ENUM_resultcode_refused; + result = 0; +exit: + + DBFEXIT; + return result; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/prism2mib.c +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/prism2mib.c @@ -0,0 +1,3794 @@ +/* src/prism2/driver/prism2mib.c +* +* Management request for mibset/mibget +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* The functions in this file handle the mibset/mibget management +* functions. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#include +#include +#include +#include +#include +#include +#endif + +#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI)) +#include +#include +#endif + +#if (WLAN_HOSTIF == WLAN_USB) +#include +#endif + +#include + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + +#define MIB_TMP_MAXLEN 200 /* Max length of RID record (in bytes). */ + +/*================================================================*/ +/* Local Types */ + +#define F_AP 0x1 /* MIB is supported on Access Points. */ +#define F_STA 0x2 /* MIB is supported on stations. */ +#define F_READ 0x4 /* MIB may be read. */ +#define F_WRITE 0x8 /* MIB may be written. */ + +typedef struct mibrec +{ + UINT32 did; + UINT16 flag; + UINT16 parm1; + UINT16 parm2; + UINT16 parm3; + int (*func)(struct mibrec *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data); +} mibrec_t; + +/*================================================================*/ +/* Local Function Declarations */ + +static int prism2mib_bytestr2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_bytearea2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_uint32( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_uint32array( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_uint32offset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_truth( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_preamble( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_flag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_appcfinfoflag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_regulatorydomains( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_wepdefaultkey( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_powermanagement( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_privacyinvoked( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_excludeunencrypted( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_fragmentationthreshold( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_operationalrateset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_groupaddress( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_fwid( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_authalg( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_authalgenable( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_priv( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static void prism2mib_priv_authlist( +hfa384x_t *hw, +prism2sta_authlist_t *list); + +static void prism2mib_priv_accessmode( +hfa384x_t *hw, +UINT32 mode); + +static void prism2mib_priv_accessallow( +hfa384x_t *hw, +p80211macarray_t *macarray); + +static void prism2mib_priv_accessdeny( +hfa384x_t *hw, +p80211macarray_t *macarray); + +static void prism2mib_priv_deauthenticate( +hfa384x_t *hw, +UINT8 *addr); + +/*================================================================*/ +/* Local Static Definitions */ + +static mibrec_t mibtab[] = { + + /* dot11smt MIB's */ + + { DIDmib_dot11smt_dot11StationConfigTable_dot11StationID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11MediumOccupancyLimit, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPollable, + F_STA | F_READ, + HFA384x_RID_CFPOLLABLE, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPPeriod, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPMaxDuration, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticationResponseTimeOut, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFAUTHRSPTIMEOUT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11PrivacyOptionImplemented, + F_AP | F_STA | F_READ, + HFA384x_RID_PRIVACYOPTIMP, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11PowerManagementMode, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMENABLED, 0, 0, + prism2mib_powermanagement }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredSSID, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFDESIREDSSID, HFA384x_RID_CNFDESIREDSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet, + F_STA | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL, 0, 0, + prism2mib_operationalrateset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL0, 0, 0, + prism2mib_operationalrateset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11BeaconPeriod, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPBCNINT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11DTIMPeriod, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNDTIMPER, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11AssociationResponseTimeOut, + F_AP | F_STA | F_READ, + HFA384x_RID_PROTOCOLRSPTIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm1, + F_AP | F_STA | F_READ, + 1, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm2, + F_AP | F_STA | F_READ, + 2, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm3, + F_AP | F_STA | F_READ, + 3, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm4, + F_AP | F_STA | F_READ, + 4, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm5, + F_AP | F_STA | F_READ, + 5, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm6, + F_AP | F_STA | F_READ, + 6, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable1, + F_AP | F_STA | F_READ | F_WRITE, + 1, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable2, + F_AP | F_STA | F_READ | F_WRITE, + 2, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable3, + F_AP | F_STA | F_READ | F_WRITE, + 3, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable4, + F_AP | F_STA | F_READ | F_WRITE, + 4, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable5, + F_AP | F_STA | F_READ | F_WRITE, + 5, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable6, + F_AP | F_STA | F_READ | F_WRITE, + 6, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_PRIVINVOKED, 0, + prism2mib_privacyinvoked }, + { DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, + prism2mib_excludeunencrypted }, + { DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSHORTPREAMBLE, 0, 0, + prism2mib_preamble }, + + /* dot11mac MIB's */ + + { DIDmib_dot11mac_dot11OperationTable_dot11MACAddress, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH0, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_SHORTRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_LONGRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH0, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXTXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11MaxReceiveLifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXRXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + + /* dot11phy MIB's */ + + { DIDmib_dot11phy_dot11PhyOperationTable_dot11PHYType, + F_AP | F_STA | F_READ, + HFA384x_RID_PHYTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyOperationTable_dot11TempType, + F_AP | F_STA | F_READ, + HFA384x_RID_TEMPTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, + F_STA | F_READ, + HFA384x_RID_CURRENTCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, + F_AP | F_READ, + HFA384x_RID_CNFOWNCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentCCAMode, + F_AP | F_STA | F_READ, + HFA384x_RID_CCAMODE, 0, 0, + prism2mib_uint32 }, + + /* p2Table MIB's */ + + { DIDmib_p2_p2Table_p2MMTx, + F_AP | F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2EarlyBeacon, + F_AP | F_READ | F_WRITE, + BIT7, 0, 0, + prism2mib_appcfinfoflag }, + { DIDmib_p2_p2Table_p2ReceivedFrameStatistics, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2CommunicationTallies, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2Authenticated, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2Associated, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2PowerSaveUserCount, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2Comment, + F_AP | F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2AccessMode, + F_AP | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2AccessAllow, + F_AP | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2AccessDeny, + F_AP | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2ChannelInfoResults, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + + /* p2Static MIB's */ + + { DIDmib_p2_p2Static_p2CnfPortType, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPORTTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfOwnMACAddress, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfDesiredSSID, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFDESIREDSSID, HFA384x_RID_CNFDESIREDSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2Static_p2CnfOwnChannel, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfOwnSSID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNSSID, HFA384x_RID_CNFOWNSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2Static_p2CnfOwnATIMWindow, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNATIMWIN, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfSystemScale, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSYSSCALE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfMaxDataLength, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFMAXDATALEN, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfWDSAddress, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR, HFA384x_RID_CNFWDSADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfPMEnabled, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMENABLED, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfPMEPS, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMEPS, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfMulticastReceive, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFMULTICASTRX, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfMaxSleepDuration, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFMAXSLEEPDUR, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfPMHoldoverDuration, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMHOLDDUR, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfOwnName, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNNAME, HFA384x_RID_CNFOWNNAME_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2Static_p2CnfOwnDTIMPeriod, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNDTIMPER, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfWDSAddress1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR1, HFA384x_RID_CNFWDSADDR1_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR2, HFA384x_RID_CNFWDSADDR2_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR3, HFA384x_RID_CNFWDSADDR3_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR4, HFA384x_RID_CNFWDSADDR4_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR5, HFA384x_RID_CNFWDSADDR5_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR6, HFA384x_RID_CNFWDSADDR6_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfMulticastPMBuffering, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFMCASTPMBUFF, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKeyID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey0, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey1, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey2, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey3, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPFlags, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfAuthentication, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFAUTHENTICATION, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfMaxAssociatedStations, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFMAXASSOCSTATIONS, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfTxControl, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFTXCONTROL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfRoamingMode, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFROAMINGMODE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfHostAuthentication, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFHOSTAUTHASSOC, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfRcvCrcError, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFRCVCRCERROR, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfAltRetryCount, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFALTRETRYCNT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfBeaconInterval, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPBCNINT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfMediumOccupancyLimit, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfCFPPeriod, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfCFPMaxDuration, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfCFPFlags, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 3, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfSTAPCFInfo, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSTAPCFINFO, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfPriorityQUsage, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPRIORITYQUSAGE, HFA384x_RID_CNFPRIOQUSAGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2Static_p2CnfTIMCtrl, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFTIMCTRL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfThirty2Tally, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFTHIRTY2TALLY, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfEnhSecurity, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFENHSECURITY, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfShortPreamble, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSHORTPREAMBLE, 0, 0, + prism2mib_preamble }, + { DIDmib_p2_p2Static_p2CnfExcludeLongPreamble, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFEXCLONGPREAMBLE, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfAuthenticationRspTO, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFAUTHRSPTIMEOUT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfBasicRates, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFBASICRATES, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfSupportedRates, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSUPPRATES, 0, 0, + prism2mib_uint32 }, + + /* p2Dynamic MIB's */ + + { DIDmib_p2_p2Dynamic_p2CreateIBSS, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CREATEIBSS, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl, + F_STA | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2PromiscuousMode, + F_STA | F_READ | F_WRITE, + HFA384x_RID_PROMISCMODE, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold0, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH0, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH1, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH2, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH3, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH4, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH5, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH6, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold0, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH0, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH1, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH2, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH3, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH4, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH5, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH6, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl0, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL0, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL1, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL2, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL3, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL4, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL5, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL6, 0, 0, + prism2mib_uint32 }, + + /* p2Behavior MIB's */ + + { DIDmib_p2_p2Behavior_p2TickTime, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_ITICKTIME, 0, 0, + prism2mib_uint32 }, + + /* p2NIC MIB's */ + + { DIDmib_p2_p2NIC_p2MaxLoadTime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXLOADTIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2NIC_p2DLBufferPage, + F_AP | F_STA | F_READ, + HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2NIC_p2DLBufferOffset, + F_AP | F_STA | F_READ, + HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2NIC_p2DLBufferLength, + F_AP | F_STA | F_READ, + HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2NIC_p2PRIIdentity, + F_AP | F_STA | F_READ, + HFA384x_RID_PRIIDENTITY, HFA384x_RID_PRIIDENTITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2PRISupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_PRISUPRANGE, HFA384x_RID_PRISUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2CFIActRanges, + F_AP | F_STA | F_READ, + HFA384x_RID_PRI_CFIACTRANGES, HFA384x_RID_CFIACTRANGES_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2BuildSequence, + F_AP | F_STA | F_READ, + HFA384x_RID_BUILDSEQ, HFA384x_RID_BUILDSEQ_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2PrimaryFWID, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_fwid }, + { DIDmib_p2_p2NIC_p2SecondaryFWID, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_fwid }, + { DIDmib_p2_p2NIC_p2TertiaryFWID, + F_AP | F_READ, + 0, 0, 0, + prism2mib_fwid }, + { DIDmib_p2_p2NIC_p2NICSerialNumber, + F_AP | F_STA | F_READ, + HFA384x_RID_NICSERIALNUMBER, HFA384x_RID_NICSERIALNUMBER_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2NIC_p2NICIdentity, + F_AP | F_STA | F_READ, + HFA384x_RID_NICIDENTITY, HFA384x_RID_NICIDENTITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2MFISupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_MFISUPRANGE, HFA384x_RID_MFISUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2CFISupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_CFISUPRANGE, HFA384x_RID_CFISUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2ChannelList, + F_AP | F_STA | F_READ, + HFA384x_RID_CHANNELLIST, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2NIC_p2RegulatoryDomains, + F_AP | F_STA | F_READ, + HFA384x_RID_REGULATORYDOMAINS, HFA384x_RID_REGULATORYDOMAINS_LEN, 0, + prism2mib_regulatorydomains }, + { DIDmib_p2_p2NIC_p2TempType, + F_AP | F_STA | F_READ, + HFA384x_RID_TEMPTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2NIC_p2STAIdentity, + F_AP | F_STA | F_READ, + HFA384x_RID_STAIDENTITY, HFA384x_RID_STAIDENTITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2STASupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_STASUPRANGE, HFA384x_RID_STASUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2MFIActRanges, + F_AP | F_STA | F_READ, + HFA384x_RID_STA_MFIACTRANGES, HFA384x_RID_MFIACTRANGES_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2STACFIActRanges, + F_AP | F_STA | F_READ, + HFA384x_RID_STA_CFIACTRANGES, HFA384x_RID_CFIACTRANGES2_LEN, 0, + prism2mib_uint32array }, + + /* p2MAC MIB's */ + + { DIDmib_p2_p2MAC_p2PortStatus, + F_STA | F_READ, + HFA384x_RID_PORTSTATUS, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentSSID, + F_STA | F_READ, + HFA384x_RID_CURRENTSSID, HFA384x_RID_CURRENTSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2MAC_p2CurrentBSSID, + F_STA | F_READ, + HFA384x_RID_CURRENTBSSID, HFA384x_RID_CURRENTBSSID_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2MAC_p2CommsQuality, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2CommsQualityCQ, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2CommsQualityASL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2CommsQualityANL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2dbmCommsQuality, + F_STA | F_READ, + HFA384x_RID_DBMCOMMSQUALITY, HFA384x_RID_DBMCOMMSQUALITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2dbmCommsQualityCQ, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2dbmCommsQualityASL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2dbmCommsQualityANL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2CurrentTxRate, + F_STA | F_READ, + HFA384x_RID_CURRENTTXRATE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentBeaconInterval, + F_AP | F_STA | F_READ, + HFA384x_RID_CURRENTBCNINT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2StaCurrentScaleThresholds, + F_STA | F_READ, + HFA384x_RID_CURRENTSCALETHRESH, HFA384x_RID_STACURSCALETHRESH_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2APCurrentScaleThresholds, + F_AP | F_READ, + HFA384x_RID_CURRENTSCALETHRESH, HFA384x_RID_APCURSCALETHRESH_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2ProtocolRspTime, + F_AP | F_STA | F_READ, + HFA384x_RID_PROTOCOLRSPTIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2ShortRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_SHORTRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2LongRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_LONGRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2MaxTransmitLifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXTXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2MaxReceiveLifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXRXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CFPollable, + F_STA | F_READ, + HFA384x_RID_CFPOLLABLE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2AuthenticationAlgorithms, + F_AP | F_STA | F_READ, + HFA384x_RID_AUTHALGORITHMS, HFA384x_RID_AUTHALGORITHMS_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2PrivacyOptionImplemented, + F_AP | F_STA | F_READ, + HFA384x_RID_PRIVACYOPTIMP, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate1, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE1, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate2, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE2, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate3, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE3, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate4, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE4, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate5, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE5, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate6, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE6, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2OwnMACAddress, + F_AP | F_READ, + HFA384x_RID_OWNMACADDRESS, HFA384x_RID_OWNMACADDRESS_LEN, 0, + prism2mib_bytearea2pstr }, + + /* p2Modem MIB's */ + + { DIDmib_p2_p2Modem_p2PHYType, + F_AP | F_STA | F_READ, + HFA384x_RID_PHYTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2CurrentChannel, + F_AP | F_STA | F_READ, + HFA384x_RID_CURRENTCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2CurrentPowerState, + F_AP | F_STA | F_READ, + HFA384x_RID_CURRENTPOWERSTATE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2CCAMode, + F_AP | F_STA | F_READ, + HFA384x_RID_CCAMODE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2TxPowerMax, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_TXPOWERMAX, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_TXPOWERMAX, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2SupportedDataRates, + F_AP | F_STA | F_READ, + HFA384x_RID_SUPPORTEDDATARATES, HFA384x_RID_SUPPORTEDDATARATES_LEN, 0, + prism2mib_bytestr2pstr }, + + /* And finally, lnx mibs */ + { DIDmib_lnx_lnxConfigTable_lnxRSNAIE, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWPADATA, 0, 0, + prism2mib_priv }, + { 0, 0, 0, 0, 0, NULL}}; + +/*---------------------------------------------------------------- +These MIB's are not supported at this time: + +DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityPresent +DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityEnabled +DIDmib_dot11phy_dot11PhyDSSSTable_dot11PBCCOptionImplemented +DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportIndex +DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxIndex +DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxValue +DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxIndex +DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxValue + +DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportValue +TODO: need to investigate why wlan has this as enumerated and Prism2 has this + as btye str. + +DIDmib_dot11phy_dot11PhyDSSSTable_dot11ShortPreambleOptionImplemented +TODO: Find out the firmware version number(s) for identifying + whether the firmware is capable of short preamble. TRUE or FALSE + will be returned based on the version of the firmware. + +WEP Key mappings aren't supported in the f/w. +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingIndex +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingAddress +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingWEPOn +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingValue +DIDmib_dot11smt_dot11PrivacyTable_dot11WEPKeyMappingLength + +TODO: implement counters. +DIDmib_dot11smt_dot11PrivacyTable_dot11WEPICVErrorCount +DIDmib_dot11smt_dot11PrivacyTable_dot11WEPExcludedCount +DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFragmentCount +DIDmib_dot11mac_dot11CountersTable_dot11MulticastTransmittedFrameCount +DIDmib_dot11mac_dot11CountersTable_dot11FailedCount +DIDmib_dot11mac_dot11CountersTable_dot11RetryCount +DIDmib_dot11mac_dot11CountersTable_dot11MultipleRetryCount +DIDmib_dot11mac_dot11CountersTable_dot11FrameDuplicateCount +DIDmib_dot11mac_dot11CountersTable_dot11RTSSuccessCount +DIDmib_dot11mac_dot11CountersTable_dot11RTSFailureCount +DIDmib_dot11mac_dot11CountersTable_dot11ACKFailureCount +DIDmib_dot11mac_dot11CountersTable_dot11ReceivedFragmentCount +DIDmib_dot11mac_dot11CountersTable_dot11MulticastReceivedFrameCount +DIDmib_dot11mac_dot11CountersTable_dot11FCSErrorCount +DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFrameCount +DIDmib_dot11mac_dot11CountersTable_dot11WEPUndecryptableCount + +TODO: implement sane values for these. +DIDmib_dot11mac_dot11OperationTable_dot11ManufacturerID +DIDmib_dot11mac_dot11OperationTable_dot11ProductID + +Not too worried about these at the moment. +DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentTxAntenna +DIDmib_dot11phy_dot11PhyAntennaTable_dot11DiversitySupport +DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentRxAntenna +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11NumberSupportedPowerLevels +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel + +Ummm, FH and IR don't apply +DIDmib_dot11phy_dot11PhyFHSSTable_dot11HopTime +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentChannelNumber +DIDmib_dot11phy_dot11PhyFHSSTable_dot11MaxDwellTime +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentDwellTime +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentSet +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentPattern +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentIndex +DIDmib_dot11phy_dot11PhyDSSSTable_dot11CCAModeSupported +DIDmib_dot11phy_dot11PhyDSSSTable_dot11EDThreshold +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMax +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMax +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMin +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMin + +We just don't have enough antennas right now to worry about this. +DIDmib_dot11phy_dot11AntennasListTable_dot11AntennaListIndex +DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedTxAntenna +DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedRxAntenna +DIDmib_dot11phy_dot11AntennasListTable_dot11DiversitySelectionRx + +------------------------------------------------------------------*/ + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* prism2mgmt_mibset_mibget +* +* Set the value of a mib item. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ + +int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + int result, isget; + mibrec_t *mib; + UINT16 which; + + p80211msg_dot11req_mibset_t *msg = msgp; + p80211itemd_t *mibitem; + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + /* + ** Determine if this is an Access Point or a station. + */ + + which = hw->ap ? F_AP : F_STA; + + /* + ** Find the MIB in the MIB table. Note that a MIB may be in the + ** table twice...once for an AP and once for a station. Make sure + ** to get the correct one. Note that DID=0 marks the end of the + ** MIB table. + */ + + mibitem = (p80211itemd_t *) msg->mibattribute.data; + + for (mib = mibtab; mib->did != 0; mib++) + if (mib->did == mibitem->did && (mib->flag & which)) + break; + + if (mib->did == 0) { + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + /* + ** Determine if this is a "mibget" or a "mibset". If this is a + ** "mibget", then make sure that the MIB may be read. Otherwise, + ** this is a "mibset" so make make sure that the MIB may be written. + */ + + isget = (msg->msgcode == DIDmsg_dot11req_mibget); + + if (isget) { + if (!(mib->flag & F_READ)) { + msg->resultcode.data = + P80211ENUM_resultcode_cant_get_writeonly_mib; + goto done; + } + } else { + if (!(mib->flag & F_WRITE)) { + msg->resultcode.data = + P80211ENUM_resultcode_cant_set_readonly_mib; + goto done; + } + } + + /* + ** Execute the MIB function. If things worked okay, then make + ** sure that the MIB function also worked okay. If so, and this + ** is a "mibget", then the status value must be set for both the + ** "mibattribute" parameter and the mib item within the data + ** portion of the "mibattribute". + */ + + result = mib->func(mib, isget, wlandev, hw, msg, + (void *) mibitem->data); + + if (msg->resultcode.data == P80211ENUM_resultcode_success) { + if (result != 0) { + WLAN_LOG_DEBUG(1, "get/set failure, result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + } else { + if (isget) { + msg->mibattribute.status = + P80211ENUM_msgitem_status_data_ok; + mibitem->status = + P80211ENUM_msgitem_status_data_ok; + } + } + } + +done: + DBFEXIT; + + return(0); +} + +/*---------------------------------------------------------------- +* prism2mib_bytestr2pstr +* +* Get/set pstr data to/from a byte string. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_bytestr2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2); + prism2mgmt_bytestr2pstr(p2bytestr, pstr); + } else { + memset(bytebuf, 0, mib->parm2); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_bytearea2pstr +* +* Get/set pstr data to/from a byte area. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_bytearea2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2); + prism2mgmt_bytearea2pstr(bytebuf, pstr, mib->parm2); + } else { + memset(bytebuf, 0, mib->parm2); + prism2mgmt_pstr2bytearea(bytebuf, pstr); + result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_uint32 +* +* Get/set uint32 data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_uint32( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + *uint32 = *wordbuf; + /* [MSM] Removed, getconfig16 returns the value in host order. + * prism2mgmt_prism2int2p80211int(wordbuf, uint32); + */ + } else { + /* [MSM] Removed, setconfig16 expects host order. + * prism2mgmt_p80211int2prism2int(wordbuf, uint32); + */ + *wordbuf = *uint32; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_uint32array +* +* Get/set an array of uint32 data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_uint32array( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32 *) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + int i, cnt; + + DBFENTER; + + cnt = mib->parm2 / sizeof(UINT16); + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2); + for (i = 0; i < cnt; i++) + prism2mgmt_prism2int2p80211int(wordbuf+i, uint32+i); + } else { + for (i = 0; i < cnt; i++) + prism2mgmt_p80211int2prism2int(wordbuf+i, uint32+i); + result = hfa384x_drvr_setconfig(hw, mib->parm1, wordbuf, mib->parm2); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_uint32offset +* +* Get/set a single element in an array of uint32 data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Element index. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_uint32offset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + UINT16 cnt; + + DBFENTER; + + cnt = mib->parm2 / sizeof(UINT16); + + result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2); + if (result == 0) { + if (isget) { + if (mib->parm3 < cnt) + prism2mgmt_prism2int2p80211int(wordbuf+mib->parm3, uint32); + else + *uint32 = 0; + } else { + if (mib->parm3 < cnt) { + prism2mgmt_p80211int2prism2int(wordbuf+mib->parm3, uint32); + result = hfa384x_drvr_setconfig(hw, mib->parm1, wordbuf, mib->parm2); + } + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_truth +* +* Get/set truth data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_truth( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + *uint32 = (*wordbuf) ? + P80211ENUM_truth_true : P80211ENUM_truth_false; + } else { + *wordbuf = ((*uint32) == P80211ENUM_truth_true) ? 1 : 0; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_flag +* +* Get/set a flag. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Bit to get/set. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_flag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + UINT32 flags; + + DBFENTER; + + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + if (result == 0) { + /* [MSM] Removed, getconfig16 returns the value in host order. + * prism2mgmt_prism2int2p80211int(wordbuf, &flags); + */ + flags = *wordbuf; + if (isget) { + *uint32 = (flags & mib->parm2) ? + P80211ENUM_truth_true : P80211ENUM_truth_false; + } else { + if ((*uint32) == P80211ENUM_truth_true) + flags |= mib->parm2; + else + flags &= ~mib->parm2; + /* [MSM] Removed, setconfig16 expects host order. + * prism2mgmt_p80211int2prism2int(wordbuf, &flags); + */ + *wordbuf = flags; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_appcfinfoflag +* +* Get/set a single flag in the APPCFINFO record. +* +* MIB record parameters: +* parm1 Bit to get/set. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_appcfinfoflag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + UINT16 word; + + DBFENTER; + + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFAPPCFINFO, + bytebuf, HFA384x_RID_CNFAPPCFINFO_LEN); + if (result == 0) { + if (isget) { + *uint32 = (hfa384x2host_16(wordbuf[3]) & mib->parm1) ? + P80211ENUM_truth_true : P80211ENUM_truth_false; + } else { + word = hfa384x2host_16(wordbuf[3]); + word = ((*uint32) == P80211ENUM_truth_true) ? + (word | mib->parm1) : (word & ~mib->parm1); + wordbuf[3] = host2hfa384x_16(word); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFAPPCFINFO, + bytebuf, HFA384x_RID_CNFAPPCFINFO_LEN); + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_regulatorydomains +* +* Get regulatory domain data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_regulatorydomains( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 cnt; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + result = 0; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2); + prism2mgmt_prism2int2p80211int(wordbuf, &cnt); + pstr->len = (UINT8) cnt; + memcpy(pstr->data, &wordbuf[1], pstr->len); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_wepdefaultkey +* +* Get/set WEP default keys. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_wepdefaultkey( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 len; + + DBFENTER; + + if (isget) { + result = 0; /* Should never happen. */ + } else { + len = (pstr->len > 5) ? HFA384x_RID_CNFWEP128DEFAULTKEY_LEN : + HFA384x_RID_CNFWEPDEFAULTKEY_LEN; + memset(bytebuf, 0, len); + prism2mgmt_pstr2bytearea(bytebuf, pstr); + result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, len); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_powermanagement +* +* Get/set 802.11 power management value. Note that this is defined differently +* by 802.11 and Prism2: +* +* Meaning 802.11 Prism2 +* active 1 false +* powersave 2 true +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_powermanagement( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT32 value; + + DBFENTER; + + if (isget) { + result = prism2mib_uint32(mib, isget, wlandev, hw, msg, &value); + *uint32 = (value == 0) ? 1 : 2; + } else { + value = ((*uint32) == 1) ? 0 : 1; + result = prism2mib_uint32(mib, isget, wlandev, hw, msg, &value); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_preamble +* +* Get/set Prism2 short preamble +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_preamble( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + *uint32 = *wordbuf; + } else { + *wordbuf = *uint32; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_privacyinvoked +* +* Get/set the dot11PrivacyInvoked value. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Bit value for PrivacyInvoked flag. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_privacyinvoked( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + + DBFENTER; + + if (wlandev->hostwep & HOSTWEP_DECRYPT) { + if (wlandev->hostwep & HOSTWEP_DECRYPT) + mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_RXCRYPT; + if (wlandev->hostwep & HOSTWEP_ENCRYPT) + mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_TXCRYPT; + } + + result = prism2mib_flag(mib, isget, wlandev, hw, msg, data); + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_excludeunencrypted +* +* Get/set the dot11ExcludeUnencrypted value. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Bit value for ExcludeUnencrypted flag. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_excludeunencrypted( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + + DBFENTER; + + result = prism2mib_flag(mib, isget, wlandev, hw, msg, data); + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_fragmentationthreshold +* +* Get/set the fragmentation threshold. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_fragmentationthreshold( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + + DBFENTER; + + if (!isget) + if ((*uint32) % 2) { + WLAN_LOG_WARNING("Attempt to set odd number " + "FragmentationThreshold\n"); + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + return(0); + } + + result = prism2mib_uint32(mib, isget, wlandev, hw, msg, data); + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_operationalrateset +* +* Get/set the operational rate set. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_operationalrateset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + prism2mgmt_get_oprateset(wordbuf, pstr); + } else { + prism2mgmt_set_oprateset(wordbuf, pstr); + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_groupaddress +* +* Get/set the dot11GroupAddressesTable. +* +* MIB record parameters: +* parm1 Not used. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_groupaddress( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 len; + + DBFENTER; + + /* TODO: fix this. f/w doesn't support mcast filters */ + + if (isget) { + prism2mgmt_get_grpaddr(mib->did, pstr, hw); + return(0); + } + + result = prism2mgmt_set_grpaddr(mib->did, bytebuf, pstr, hw); + if (result != 0) { + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + return(result); + } + + if (hw->dot11_grpcnt <= MAX_PRISM2_GRP_ADDR) { + len = hw->dot11_grpcnt * WLAN_ADDR_LEN; + memcpy(bytebuf, hw->dot11_grp_addr[0], len); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_GROUPADDR, bytebuf, len); + + /* + ** Turn off promiscuous mode if count is equal to MAX. We may + ** have been at a higher count in promiscuous mode and need to + ** turn it off. + */ + + /* but only if we're not already in promisc mode. :) */ + if ((hw->dot11_grpcnt == MAX_PRISM2_GRP_ADDR) && + !( wlandev->netdev->flags & IFF_PROMISC)) { + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_PROMISCMODE, 0); + } + } else { + + /* + ** Clear group addresses in card and set to promiscuous mode. + */ + + memset(bytebuf, 0, sizeof(bytebuf)); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_GROUPADDR, + bytebuf, 0); + if (result == 0) { + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_PROMISCMODE, 1); + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_fwid +* +* Get the firmware ID. +* +* MIB record parameters: +* parm1 Not used. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_fwid( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + hfa384x_FWID_t fwid; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_FWID, + &fwid, HFA384x_RID_FWID_LEN); + if (mib->did == DIDmib_p2_p2NIC_p2PrimaryFWID) { + fwid.primary[HFA384x_FWID_LEN - 1] = '\0'; + pstr->len = strlen(fwid.primary); + memcpy(pstr->data, fwid.primary, pstr->len); + } else { + fwid.secondary[HFA384x_FWID_LEN - 1] = '\0'; + pstr->len = strlen(fwid.secondary); + memcpy(pstr->data, fwid.secondary, pstr->len); + } + } else + result = 0; /* Should never happen. */ + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_authalg +* +* Get values from the AuhtenticationAlgorithmsTable. +* +* MIB record parameters: +* parm1 Table index (1-6). +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_authalg( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + UINT32 *uint32 = (UINT32*) data; + + DBFENTER; + + /* MSM: pkx supplied code that code queries RID FD4D....but the f/w's + * results are bogus. Therefore, we have to simulate the appropriate + * results here in the driver based on our knowledge of existing MAC + * features. That's the whole point behind this ugly function. + */ + + if (isget) { + msg->resultcode.data = P80211ENUM_resultcode_success; + switch (mib->parm1) { + case 1: /* Open System */ + *uint32 = P80211ENUM_authalg_opensystem; + break; + case 2: /* SharedKey */ + *uint32 = P80211ENUM_authalg_sharedkey; + break; + default: + *uint32 = 0; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + break; + } + } + + DBFEXIT; + return(0); +} + +/*---------------------------------------------------------------- +* prism2mib_authalgenable +* +* Get/set the enable values from the AuhtenticationAlgorithmsTable. +* +* MIB record parameters: +* parm1 Table index (1-6). +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_authalgenable( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + + int index; + UINT16 cnf_auth; + UINT16 mask; + + DBFENTER; + + index = mib->parm1 - 1; + + result = hfa384x_drvr_getconfig16( hw, + HFA384x_RID_CNFAUTHENTICATION, &cnf_auth); + WLAN_LOG_DEBUG(2,"cnfAuthentication0=%d, index=%d\n", cnf_auth, index); + + if (isget) { + if ( index == 0 || index == 1 ) { + *uint32 = (cnf_auth & (1<resultcode.data = P80211ENUM_resultcode_not_supported; + } + } else { + if ( index == 0 || index == 1 ) { + mask = 1 << index; + if (*uint32==P80211ENUM_truth_true ) { + cnf_auth |= mask; + } else { + cnf_auth &= ~mask; + } + result = hfa384x_drvr_setconfig16( hw, + HFA384x_RID_CNFAUTHENTICATION, cnf_auth); + WLAN_LOG_DEBUG(2,"cnfAuthentication:=%d\n", cnf_auth); + if ( result ) { + WLAN_LOG_DEBUG(1,"Unable to set p2cnfAuthentication to %d\n", cnf_auth); + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } + } else { + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_priv +* +* Get/set values in the "priv" data structure. +* +* MIB record parameters: +* parm1 Not used. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_priv( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + UINT32 *uint32 = (UINT32*) data; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + p80211macarray_t *macarray = (p80211macarray_t *) data; + + int i, cnt, result, done; + + DBFENTER; + + switch (mib->did) { + case DIDmib_p2_p2Table_p2ReceivedFrameStatistics: + + /* + ** Note: The values in this record are changed by the + ** interrupt handler and therefore cannot be guaranteed + ** to be stable while they are being copied. However, + ** the interrupt handler will take priority over this + ** code. Hence, if the same values are copied twice, + ** then we are ensured that the values have not been + ** changed. If they have, then just try again. Don't + ** try more than 10 times...if we still haven't got it, + ** then the values we do have are probably good enough. + ** This scheme for copying values is used in order to + ** prevent having to block the interrupt handler while + ** we copy the values. + */ + + if (isget) { + UINT8 test[sizeof(wlandev->rx)]; + for (i = 0; i < 10; i++) { + memcpy(data, &wlandev->rx, sizeof(wlandev->rx)); + memcpy(test, &wlandev->rx, sizeof(wlandev->rx)); + if (memcmp(data, test, sizeof(wlandev->rx)) == 0) break; + } + } + break; + + case DIDmib_p2_p2Table_p2CommunicationTallies: + + /* + ** Note: The values in this record are changed by the + ** interrupt handler and therefore cannot be guaranteed + ** to be stable while they are being copied. See the + ** note above about copying values. + */ + + if (isget) { + UINT8 test[sizeof(hw->tallies)]; + result = hfa384x_drvr_commtallies(hw); + + /* ?????? We need to wait a bit here for the */ + /* tallies to get updated. ?????? */ + /* MSM: TODO: The right way to do this is to + * add a "commtallie" wait queue to the + * priv structure that gets run every time + * we receive a commtally info frame. + * This process would sleep on that + * queue and get awakened when the + * the requested info frame arrives. + * Don't have time to do and test this + * right now. + */ + + /* Ugh, this is nasty. */ + for (i = 0; i < 10; i++) { + memcpy(data, + &hw->tallies, + sizeof(hw->tallies)); + memcpy(test, + &hw->tallies, + sizeof(hw->tallies)); + if ( memcmp(data, + test, + sizeof(hw->tallies)) == 0) + break; + } + } + + break; + + case DIDmib_p2_p2Table_p2Authenticated: + + if (isget) { + prism2sta_authlist_t old; + prism2mib_priv_authlist(hw, &old); + + macarray->cnt = 0; + for (i = 0; i < old.cnt; i++) { + if (!old.assoc[i]) { + memcpy(macarray->data[macarray->cnt], old.addr[i], WLAN_ADDR_LEN); + macarray->cnt++; + } + } + } + + break; + + case DIDmib_p2_p2Table_p2Associated: + + if (isget) { + prism2sta_authlist_t old; + prism2mib_priv_authlist(hw, &old); + + macarray->cnt = 0; + for (i = 0; i < old.cnt; i++) { + if (old.assoc[i]) { + memcpy(macarray->data[macarray->cnt], old.addr[i], WLAN_ADDR_LEN); + macarray->cnt++; + } + } + } + + break; + + case DIDmib_p2_p2Table_p2PowerSaveUserCount: + + if (isget) + *uint32 = hw->psusercount; + + break; + + case DIDmib_p2_p2Table_p2Comment: + + if (isget) { + pstr->len = strlen(hw->comment); + memcpy(pstr->data, hw->comment, pstr->len); + } else { + cnt = pstr->len; + if (cnt < 0) cnt = 0; + if (cnt >= sizeof(hw->comment)) + cnt = sizeof(hw->comment)-1; + memcpy(hw->comment, pstr->data, cnt); + pstr->data[cnt] = '\0'; + } + + break; + + case DIDmib_p2_p2Table_p2AccessMode: + + if (isget) + *uint32 = hw->accessmode; + else + prism2mib_priv_accessmode(hw, *uint32); + + break; + + case DIDmib_p2_p2Table_p2AccessAllow: + + if (isget) { + macarray->cnt = hw->allow.cnt; + memcpy(macarray->data, hw->allow.addr, + macarray->cnt*WLAN_ADDR_LEN); + } else { + prism2mib_priv_accessallow(hw, macarray); + } + + break; + + case DIDmib_p2_p2Table_p2AccessDeny: + + if (isget) { + macarray->cnt = hw->deny.cnt; + memcpy(macarray->data, hw->deny.addr, + macarray->cnt*WLAN_ADDR_LEN); + } else { + prism2mib_priv_accessdeny(hw, macarray); + } + + break; + + case DIDmib_p2_p2Table_p2ChannelInfoResults: + + if (isget) { + done = atomic_read(&hw->channel_info.done); + if (done == 0) { + msg->resultcode.status = P80211ENUM_msgitem_status_no_value; + break; + } + if (done == 1) { + msg->resultcode.status = P80211ENUM_msgitem_status_incomplete_itemdata; + break; + } + + for (i = 0; i < 14; i++, uint32 += 5) { + uint32[0] = i+1; + uint32[1] = hw->channel_info.results.result[i].anl; + uint32[2] = hw->channel_info.results.result[i].pnl; + uint32[3] = (hw->channel_info.results.result[i].active & HFA384x_CHINFORESULT_BSSACTIVE) ? 1 : 0; + uint32[4] = (hw->channel_info.results.result[i].active & HFA384x_CHINFORESULT_PCFACTIVE) ? 1 : 0; + } + } + + break; + + case DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType: + + if (isget) + *uint32 = hw->dot11_desired_bss_type; + else + hw->dot11_desired_bss_type = *uint32; + + break; + + case DIDmib_lnx_lnxConfigTable_lnxRSNAIE: { + hfa384x_WPAData_t wpa; + if (isget) { + hfa384x_drvr_getconfig( hw, HFA384x_RID_CNFWPADATA, + (UINT8 *) &wpa, sizeof(wpa)); + pstr->len = hfa384x2host_16(wpa.datalen); + memcpy(pstr->data, wpa.data, pstr->len); + } else { + wpa.datalen = host2hfa384x_16(pstr->len); + memcpy(wpa.data, pstr->data, pstr->len); + + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFWPADATA, + (UINT8 *) &wpa, sizeof(wpa)); + } + break; + } + default: + WLAN_LOG_ERROR("Unhandled DID 0x%08x\n", mib->did); + } + + DBFEXIT; + return(0); +} + +/*---------------------------------------------------------------- +* prism2mib_priv_authlist +* +* Get a copy of the list of authenticated stations. +* +* Arguments: +* priv "priv" structure. +* list List of authenticated stations. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_authlist( +hfa384x_t *hw, +prism2sta_authlist_t *list) +{ + prism2sta_authlist_t test; + int i; + + DBFENTER; + + /* + ** Note: The values in this record are changed by the interrupt + ** handler and therefore cannot be guaranteed to be stable while + ** they are being copied. However, the interrupt handler will + ** take priority over this code. Hence, if the same values are + ** copied twice, then we are ensured that the values have not + ** been changed. If they have, then just try again. Don't try + ** more than 10 times...the list of authenticated stations is + ** unlikely to be changing frequently enough that we can't get + ** a snapshot in 10 tries. Don't try more than this so that we + ** don't risk locking-up for long periods of time. If we still + ** haven't got the snapshot, then generate an error message and + ** return an empty list (since this is the only valid list that + ** we can guarentee). This scheme for copying values is used in + ** order to prevent having to block the interrupt handler while + ** we copy the values. + */ + + for (i = 0; i < 10; i++) { + memcpy(list, &hw->authlist, sizeof(prism2sta_authlist_t)); + memcpy(&test, &hw->authlist, sizeof(prism2sta_authlist_t)); + if (memcmp(list, &test, sizeof(prism2sta_authlist_t)) == 0) + break; + } + + if (i >= 10) { + list->cnt = 0; + WLAN_LOG_ERROR("Could not obtain snapshot of authenticated stations.\n"); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_accessmode +* +* Set the Access Mode. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* mode New access mode. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_accessmode( +hfa384x_t *hw, +UINT32 mode) +{ + prism2sta_authlist_t old; + int i, j, deauth; + UINT8 *addr; + + DBFENTER; + + /* + ** If the mode is not changing or it is changing to "All", then it's + ** okay to go ahead without a lot of messing around. Otherwise, the + ** access mode is changing in a way that may leave some stations + ** authenticated which should not be authenticated. It will be + ** necessary to de-authenticate these stations. + */ + + if (mode == WLAN_ACCESS_ALL || mode == hw->accessmode) { + hw->accessmode = mode; + return; + } + + /* + ** Switch to the new access mode. Once this is done, then the interrupt + ** handler (which uses this value) will be prevented from authenticating + ** ADDITIONAL stations which should not be authenticated. Then get a + ** copy of the current list of authenticated stations. + */ + + hw->accessmode = mode; + + prism2mib_priv_authlist(hw, &old); + + /* + ** Now go through the list of previously authenticated stations (some + ** of which might de-authenticate themselves while we are processing it + ** but that is okay). Any station which no longer matches the access + ** mode, must be de-authenticated. + */ + + for (i = 0; i < old.cnt; i++) { + addr = old.addr[i]; + + if (mode == WLAN_ACCESS_NONE) + deauth = 1; + else { + if (mode == WLAN_ACCESS_ALLOW) { + for (j = 0; j < hw->allow.cnt; j++) + if (memcmp(addr, hw->allow.addr[j], + WLAN_ADDR_LEN) == 0) + break; + deauth = (j >= hw->allow.cnt); + } else { + for (j = 0; j < hw->deny.cnt; j++) + if (memcmp(addr, hw->deny.addr[j], + WLAN_ADDR_LEN) == 0) + break; + deauth = (j < hw->deny.cnt); + } + } + + if (deauth) prism2mib_priv_deauthenticate(hw, addr); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_accessallow +* +* Change the list of allowed MAC addresses. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* macarray New array of MAC addresses. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_accessallow( +hfa384x_t *hw, +p80211macarray_t *macarray) +{ + prism2sta_authlist_t old; + int i, j; + + DBFENTER; + + /* + ** Change the access list. Note that the interrupt handler may be in + ** the middle of using the access list!!! Since the interrupt handler + ** will always have priority over this process and this is the only + ** process that will modify the list, this problem can be handled as + ** follows: + ** + ** 1. Set the "modify" flag. + ** 2. Change the first copy of the list. + ** 3. Clear the "modify" flag. + ** 4. Change the backup copy of the list. + ** + ** The interrupt handler will check the "modify" flag. If NOT set, then + ** the first copy of the list is valid and may be used. Otherwise, the + ** first copy is being changed but the backup copy is valid and may be + ** used. Doing things this way prevents having to have the interrupt + ** handler block while the list is being updated. + */ + + hw->allow.modify = 1; + + hw->allow.cnt = macarray->cnt; + memcpy(hw->allow.addr, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + hw->allow.modify = 0; + + hw->allow.cnt1 = macarray->cnt; + memcpy(hw->allow.addr1, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + /* + ** If the current access mode is "Allow", then changing the access + ** list may leave some stations authenticated which should not be + ** authenticated. It will be necessary to de-authenticate these + ** stations. Otherwise, the list can be changed without a lot of fuss. + */ + + if (hw->accessmode == WLAN_ACCESS_ALLOW) { + + /* + ** Go through the list of authenticated stations (some of + ** which might de-authenticate themselves while we are + ** processing it but that is okay). Any station which is + ** no longer in the list of allowed stations, must be + ** de-authenticated. + */ + + prism2mib_priv_authlist(hw, &old); + + for (i = 0; i < old.cnt; i++) { + for (j = 0; j < hw->allow.cnt; j++) + if (memcmp(old.addr[i], hw->allow.addr[j], + WLAN_ADDR_LEN) == 0) + break; + if (j >= hw->allow.cnt) + prism2mib_priv_deauthenticate(hw, old.addr[i]); + } + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_accessdeny +* +* Change the list of denied MAC addresses. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* macarray New array of MAC addresses. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_accessdeny( +hfa384x_t *hw, +p80211macarray_t *macarray) +{ + prism2sta_authlist_t old; + int i, j; + + DBFENTER; + + /* + ** Change the access list. Note that the interrupt handler may be in + ** the middle of using the access list!!! Since the interrupt handler + ** will always have priority over this process and this is the only + ** process that will modify the list, this problem can be handled as + ** follows: + ** + ** 1. Set the "modify" flag. + ** 2. Change the first copy of the list. + ** 3. Clear the "modify" flag. + ** 4. Change the backup copy of the list. + ** + ** The interrupt handler will check the "modify" flag. If NOT set, then + ** the first copy of the list is valid and may be used. Otherwise, the + ** first copy is being changed but the backup copy is valid and may be + ** used. Doing things this way prevents having to have the interrupt + ** handler block while the list is being updated. + */ + + hw->deny.modify = 1; + + hw->deny.cnt = macarray->cnt; + memcpy(hw->deny.addr, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + hw->deny.modify = 0; + + hw->deny.cnt1 = macarray->cnt; + memcpy(hw->deny.addr1, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + /* + ** If the current access mode is "Deny", then changing the access + ** list may leave some stations authenticated which should not be + ** authenticated. It will be necessary to de-authenticate these + ** stations. Otherwise, the list can be changed without a lot of fuss. + */ + + if (hw->accessmode == WLAN_ACCESS_DENY) { + + /* + ** Go through the list of authenticated stations (some of + ** which might de-authenticate themselves while we are + ** processing it but that is okay). Any station which is + ** now in the list of denied stations, must be de-authenticated. + */ + + prism2mib_priv_authlist(hw, &old); + + for (i = 0; i < old.cnt; i++) + for (j = 0; j < hw->deny.cnt; j++) + if (memcmp(old.addr[i], hw->deny.addr[j], + WLAN_ADDR_LEN) == 0) { + prism2mib_priv_deauthenticate(hw, old.addr[i]); + break; + } + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_deauthenticate +* +* De-authenticate a station. This is done by sending a HandoverAddress +* information frame to the firmware. This should work, according to +* Intersil. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* addr MAC address of station to be de-authenticated. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_deauthenticate( +hfa384x_t *hw, +UINT8 *addr) +{ + DBFENTER; + hfa384x_drvr_handover(hw, addr); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_pstr2bytestr +* +* Convert the pstr data in the WLAN message structure into an hfa384x +* byte string format. +* +* Arguments: +* bytestr hfa384x byte string data type +* pstr wlan message data +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) +{ + DBFENTER; + + bytestr->len = host2hfa384x_16((UINT16)(pstr->len)); + memcpy(bytestr->data, pstr->data, pstr->len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_pstr2bytearea +* +* Convert the pstr data in the WLAN message structure into an hfa384x +* byte area format. +* +* Arguments: +* bytearea hfa384x byte area data type +* pstr wlan message data +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_pstr2bytearea(UINT8 *bytearea, p80211pstrd_t *pstr) +{ + DBFENTER; + + memcpy(bytearea, pstr->data, pstr->len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_bytestr2pstr +* +* Convert the data in an hfa384x byte string format into a +* pstr in the WLAN message. +* +* Arguments: +* bytestr hfa384x byte string data type +* msg wlan message +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) +{ + DBFENTER; + + pstr->len = (UINT8)(hfa384x2host_16((UINT16)(bytestr->len))); + memcpy(pstr->data, bytestr->data, pstr->len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_bytearea2pstr +* +* Convert the data in an hfa384x byte area format into a pstr +* in the WLAN message. +* +* Arguments: +* bytearea hfa384x byte area data type +* msg wlan message +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_bytearea2pstr(UINT8 *bytearea, p80211pstrd_t *pstr, int len) +{ + DBFENTER; + + pstr->len = (UINT8)len; + memcpy(pstr->data, bytearea, len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_prism2int2p80211int +* +* Convert an hfa384x integer into a wlan integer +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_prism2int2p80211int(UINT16 *prism2int, UINT32 *wlanint) +{ + DBFENTER; + + *wlanint = (UINT32)hfa384x2host_16(*prism2int); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_p80211int2prism2int +* +* Convert a wlan integer into an hfa384x integer +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_p80211int2prism2int(UINT16 *prism2int, UINT32 *wlanint) +{ + DBFENTER; + + *prism2int = host2hfa384x_16((UINT16)(*wlanint)); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_prism2enum2p80211enum +* +* Convert the hfa384x enumerated int into a p80211 enumerated int +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* rid hfa384x record id +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_prism2enum2p80211enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid) +{ + DBFENTER; + + /* At the moment, the need for this functionality hasn't + presented itself. All the wlan enumerated values are + a 1-to-1 match against the Prism2 enumerated values*/ + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_p80211enum2prism2enum +* +* Convert the p80211 enumerated int into an hfa384x enumerated int +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* rid hfa384x record id +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_p80211enum2prism2enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid) +{ + DBFENTER; + + /* At the moment, the need for this functionality hasn't + presented itself. All the wlan enumerated values are + a 1-to-1 match against the Prism2 enumerated values*/ + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_get_oprateset +* +* Convert the hfa384x bit area into a wlan octet string. +* +* Arguments: +* rate Prism2 bit area +* pstr wlan octet string +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_get_oprateset(UINT16 *rate, p80211pstrd_t *pstr) +{ + UINT8 len; + UINT8 *datarate; + + DBFENTER; + + len = 0; + datarate = pstr->data; + + /* 1 Mbps */ + if ( BIT0 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)2; + datarate++; + } + + /* 2 Mbps */ + if ( BIT1 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)4; + datarate++; + } + + /* 5.5 Mbps */ + if ( BIT2 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)11; + datarate++; + } + + /* 11 Mbps */ + if ( BIT3 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)22; + datarate++; + } + + pstr->len = len; + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_set_oprateset +* +* Convert the wlan octet string into an hfa384x bit area. +* +* Arguments: +* rate Prism2 bit area +* pstr wlan octet string +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_set_oprateset(UINT16 *rate, p80211pstrd_t *pstr) +{ + UINT8 *datarate; + int i; + + DBFENTER; + + *rate = 0; + + datarate = pstr->data; + + for ( i=0; i < pstr->len; i++, datarate++ ) { + switch (*datarate) { + case 2: /* 1 Mbps */ + *rate |= BIT0; + break; + case 4: /* 2 Mbps */ + *rate |= BIT1; + break; + case 11: /* 5.5 Mbps */ + *rate |= BIT2; + break; + case 22: /* 11 Mbps */ + *rate |= BIT3; + break; + default: + WLAN_LOG_DEBUG(1, "Unrecoginzed Rate of %d\n", + *datarate); + break; + } + } + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_get_grpaddr +* +* Retrieves a particular group address from the list of +* group addresses. +* +* Arguments: +* did mibitem did +* pstr wlan octet string +* priv prism2 driver private data structure +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_get_grpaddr(UINT32 did, p80211pstrd_t *pstr, + hfa384x_t *hw ) +{ + int index; + + DBFENTER; + + index = prism2mgmt_get_grpaddr_index(did); + + if ( index >= 0 ) { + pstr->len = WLAN_ADDR_LEN; + memcpy(pstr->data, hw->dot11_grp_addr[index], + WLAN_ADDR_LEN); + } + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_set_grpaddr +* +* Convert the wlan octet string into an hfa384x bit area. +* +* Arguments: +* did mibitem did +* buf +* groups +* +* Returns: +* 0 Success +* !0 Error +* +----------------------------------------------------------------*/ +int prism2mgmt_set_grpaddr(UINT32 did, UINT8 *prism2buf, + p80211pstrd_t *pstr, hfa384x_t *hw ) +{ + UINT8 no_addr[WLAN_ADDR_LEN]; + int index; + + DBFENTER; + + memset(no_addr, 0, WLAN_ADDR_LEN); + if (memcmp(no_addr, pstr->data, WLAN_ADDR_LEN) != 0) { + + /* + ** The address is NOT 0 so we are "adding" an address to the + ** group address list. Check to make sure we aren't trying + ** to add more than the maximum allowed number of group + ** addresses in the list. The new address is added to the + ** end of the list regardless of the DID used to add the + ** address. + */ + + if (hw->dot11_grpcnt >= MAX_GRP_ADDR) return(-1); + + memcpy(hw->dot11_grp_addr[hw->dot11_grpcnt], pstr->data, + WLAN_ADDR_LEN); + hw->dot11_grpcnt += 1; + } else { + + /* + ** The address is 0. Interpret this as "deleting" an address + ** from the group address list. Get the address index from + ** the DID. If this is within the range of used addresses, + ** then delete the specified address by shifting all following + ** addresses down. Then clear the last address (which should + ** now be unused). If the address index is NOT within the + ** range of used addresses, then just ignore the address. + */ + + index = prism2mgmt_get_grpaddr_index(did); + if (index >= 0 && index < hw->dot11_grpcnt) { + hw->dot11_grpcnt -= 1; + memmove(hw->dot11_grp_addr[index], + hw->dot11_grp_addr[index + 1], + ((hw->dot11_grpcnt)-index) * WLAN_ADDR_LEN); + memset(hw->dot11_grp_addr[hw->dot11_grpcnt], 0, + WLAN_ADDR_LEN); + } + } + + DBFEXIT; + return(0); +} + + +/*---------------------------------------------------------------- +* prism2mgmt_get_grpaddr_index +* +* Gets the index in the group address list based on the did. +* +* Arguments: +* did mibitem did +* +* Returns: +* >= 0 If valid did +* < 0 If not valid did +* +----------------------------------------------------------------*/ +int prism2mgmt_get_grpaddr_index( UINT32 did ) +{ + int index; + + DBFENTER; + + index = -1; + + switch (did) { + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1: + index = 0; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2: + index = 1; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3: + index = 2; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4: + index = 3; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5: + index = 4; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6: + index = 5; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7: + index = 6; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8: + index = 7; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9: + index = 8; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10: + index = 9; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11: + index = 10; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12: + index = 11; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13: + index = 12; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14: + index = 13; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15: + index = 14; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16: + index = 15; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17: + index = 16; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18: + index = 17; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19: + index = 18; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20: + index = 19; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21: + index = 20; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22: + index = 21; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23: + index = 22; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24: + index = 23; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25: + index = 24; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26: + index = 25; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27: + index = 26; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28: + index = 27; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29: + index = 28; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30: + index = 29; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31: + index = 30; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32: + index = 31; + break; + } + + DBFEXIT; + return index; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/hfa384x.c +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/hfa384x.c @@ -0,0 +1,4018 @@ +/* src/prism2/driver/hfa384x.c +* +* Implements the functions of the Intersil hfa384x MAC +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file implements functions that correspond to the prism2/hfa384x +* 802.11 MAC hardware and firmware host interface. +* +* The functions can be considered to represent several levels of +* abstraction. The lowest level functions are simply C-callable wrappers +* around the register accesses. The next higher level represents C-callable +* prism2 API functions that match the Intersil documentation as closely +* as is reasonable. The next higher layer implements common sequences +* of invokations of the API layer (e.g. write to bap, followed by cmd). +* +* Common sequences: +* hfa384x_drvr_xxx Highest level abstractions provided by the +* hfa384x code. They are driver defined wrappers +* for common sequences. These functions generally +* use the services of the lower levels. +* +* hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These +* functions are wrappers for the RID get/set +* sequence. They call copy_[to|from]_bap() and +* cmd_access(). These functions operate on the +* RIDs and buffers without validation. The caller +* is responsible for that. +* +* API wrapper functions: +* hfa384x_cmd_xxx functions that provide access to the f/w commands. +* The function arguments correspond to each command +* argument, even command arguments that get packed +* into single registers. These functions _just_ +* issue the command by setting the cmd/parm regs +* & reading the status/resp regs. Additional +* activities required to fully use a command +* (read/write from/to bap, get/set int status etc.) +* are implemented separately. Think of these as +* C-callable prism2 commands. +* +* Lowest Layer Functions: +* hfa384x_docmd_xxx These functions implement the sequence required +* to issue any prism2 command. Primarily used by the +* hfa384x_cmd_xxx functions. +* +* hfa384x_bap_xxx BAP read/write access functions. +* Note: we usually use BAP0 for non-interrupt context +* and BAP1 for interrupt context. +* +* hfa384x_dl_xxx download related functions. +* +* Driver State Issues: +* Note that there are two pairs of functions that manage the +* 'initialized' and 'running' states of the hw/MAC combo. The four +* functions are create(), destroy(), start(), and stop(). create() +* sets up the data structures required to support the hfa384x_* +* functions and destroy() cleans them up. The start() function gets +* the actual hardware running and enables the interrupts. The stop() +* function shuts the hardware down. The sequence should be: +* create() +* . +* . Self contained test routines can run here, particularly +* . corereset() and test_hostif(). +* . +* start() +* . +* . Do interesting things w/ the hardware +* . +* stop() +* destroy() +* +* Note that destroy() can be called without calling stop() first. +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ + +/* System Includes */ +#define WLAN_DBVAR prism2_debug +#include + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include +#else +#include +#endif + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) +#include +#endif +#include +#include +#include +#include +#include +#endif + +#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI)) +#include +#include +#endif + +#include + +// XXXX #define CMD_IRQ + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + +static const UINT16 crc16tab[256] = +{ + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, + 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, + 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, + 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, + 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, + 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, + 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, + 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, + 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, + 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, + 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, + 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, + 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, + 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, + 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, + 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, + 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, + 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, + 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, + 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, + 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, + 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, + 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, + 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, + 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, + 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, + 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, + 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 +}; + +/*================================================================*/ +/* Local Macros */ + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ +extern int prism2_debug; + +/*================================================================*/ +/* Local Function Declarations */ + +static void hfa384x_int_dtim(wlandevice_t *wlandev); +static void hfa384x_int_infdrop(wlandevice_t *wlandev); + +static void hfa384x_bap_tasklet(unsigned long data); + +static void hfa384x_int_info(wlandevice_t *wlandev); +static void hfa384x_int_txexc(wlandevice_t *wlandev); +static void hfa384x_int_tx(wlandevice_t *wlandev); +static void hfa384x_int_rx(wlandevice_t *wlandev); + +#ifdef CMD_IRQ +static void hfa384x_int_cmd(wlandevice_t *wlandev); +#endif +static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, + UINT16 rxfid, hfa384x_rx_frame_t *rxdesc); +static void hfa384x_int_alloc(wlandevice_t *wlandev); + +static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd); + +static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd); + +static UINT16 +hfa384x_mkcrc16(UINT8 *p, int len); + +int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len, void* buf2, UINT len2, + void *buf3, UINT len3, void* buf4, UINT len4); + +/*================================================================*/ +/* Function Definitions */ + +static UINT16 +txfid_queue_empty(hfa384x_t *hw) +{ + return (hw->txfid_head == hw->txfid_tail) ? 1 : 0; +} + +static UINT16 +txfid_queue_remove(hfa384x_t *hw) +{ + UINT16 result= 0; + + if (txfid_queue_empty(hw)) { + WLAN_LOG_DEBUG(3,"queue empty.\n"); + } else { + result = hw->txfid_queue[hw->txfid_head]; + hw->txfid_head = (hw->txfid_head + 1) % hw->txfid_N; + } + + return (UINT16)result; +} + +static INT16 +txfid_queue_add(hfa384x_t *hw, UINT16 val) +{ + INT16 result = 0; + + if (hw->txfid_head == ((hw->txfid_tail + 1) % hw->txfid_N)) { + result = -1; + WLAN_LOG_DEBUG(3,"queue full.\n"); + } else { + hw->txfid_queue[hw->txfid_tail] = val; + result = hw->txfid_tail; + hw->txfid_tail = (hw->txfid_tail + 1) % hw->txfid_N; + } + + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_create +* +* Initializes the hfa384x_t data structure for use. Note this +* does _not_ intialize the actual hardware, just the data structures +* we use to keep track of its state. +* +* Arguments: +* hw device structure +* irq device irq number +* iobase [pcmcia] i/o base address for register access +* [pci] zero +* [plx] i/o base address for register access +* membase [pcmcia] pcmcia_cs "link" pointer +* [pci] memory base address for register access +* [plx] memory base address for card attribute memory +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +void hfa384x_create(hfa384x_t *hw, UINT irq, UINT32 iobase, + UINT8 __iomem *membase) +{ + DBFENTER; + memset(hw, 0, sizeof(hfa384x_t)); + hw->irq = irq; + hw->iobase = iobase; + hw->membase = membase; + spin_lock_init(&(hw->cmdlock)); + + /* BAP setup */ + spin_lock_init(&(hw->baplock)); + tasklet_init(&hw->bap_tasklet, + hfa384x_bap_tasklet, + (unsigned long) hw); + + init_waitqueue_head(&hw->cmdq); + sema_init(&hw->infofid_sem, 1); + + hw->txfid_head = 0; + hw->txfid_tail = 0; + hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX; + memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue)); + + hw->isram16 = 1; + + /* Init the auth queue head */ + skb_queue_head_init(&hw->authq); + + INIT_WORK2(&hw->link_bh, prism2sta_processing_defer); + + INIT_WORK2(&hw->commsqual_bh, prism2sta_commsqual_defer); + + init_timer(&hw->commsqual_timer); + hw->commsqual_timer.data = (unsigned long) hw; + hw->commsqual_timer.function = prism2sta_commsqual_timer; + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_destroy +* +* Partner to hfa384x_create(). This function cleans up the hw +* structure so that it can be freed by the caller using a simple +* kfree. Currently, this function is just a placeholder. If, at some +* point in the future, an hw in the 'shutdown' state requires a 'deep' +* kfree, this is where it should be done. Note that if this function +* is called on a _running_ hw structure, the drvr_stop() function is +* called. +* +* Arguments: +* hw device structure +* +* Returns: +* nothing, this function is not allowed to fail. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +void +hfa384x_destroy( hfa384x_t *hw) +{ + struct sk_buff *skb; + + DBFENTER; + + if ( hw->state == HFA384x_STATE_RUNNING ) { + hfa384x_drvr_stop(hw); + } + hw->state = HFA384x_STATE_PREINIT; + + if (hw->scanresults) { + kfree(hw->scanresults); + hw->scanresults = NULL; + } + + /* Now to clean out the auth queue */ + while ( (skb = skb_dequeue(&hw->authq)) ) { + dev_kfree_skb(skb); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_getconfig +* +* Performs the sequence necessary to read a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (host order) +* buf host side record buffer. Upon return it will +* contain the body portion of the record (minus the +* RID and len). +* len buffer length (in bytes, should match record length) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ENODATA length mismatch between argument and retrieved +* record. +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + int result = 0; + DBFENTER; + + result = hfa384x_cmd_access( hw, 0, rid, buf, len); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_setconfig +* +* Performs the sequence necessary to write a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (in host order) +* buf host side record buffer +* len buffer length (in bytes) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + int result = 0; + DBFENTER; + + result = hfa384x_cmd_access( hw, 1, rid, buf, len); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_readpda +* +* Performs the sequence to read the PDA space. Note there is no +* drvr_writepda() function. Writing a PDA is +* generally implemented by a calling component via calls to +* cmd_download and writing to the flash download buffer via the +* aux regs. +* +* Arguments: +* hw device structure +* buf buffer to store PDA in +* len buffer length +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ETIMEOUT timout waiting for the cmd regs to become +* available, or waiting for the control reg +* to indicate the Aux port is enabled. +* -ENODATA the buffer does NOT contain a valid PDA. +* Either the card PDA is bad, or the auxdata +* reads are giving us garbage. + +* +* Side effects: +* +* Call context: +* process thread or non-card interrupt. +----------------------------------------------------------------*/ +int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len) +{ + int result = 0; + UINT16 *pda = buf; + int pdaok = 0; + int morepdrs = 1; + int currpdr = 0; /* word offset of the current pdr */ + int i; + UINT16 pdrlen; /* pdr length in bytes, host order */ + UINT16 pdrcode; /* pdr code, host order */ + UINT16 crc; + UINT16 pdacrc; + struct pdaloc { + UINT32 cardaddr; + UINT16 auxctl; + } pdaloc[] = + { + { HFA3842_PDA_BASE, HFA384x_AUX_CTL_NV}, + { HFA3842_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, + { HFA3841_PDA_BASE, HFA384x_AUX_CTL_NV}, + { HFA3841_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, + { HFA3841_PDA_BOGUS_BASE, HFA384x_AUX_CTL_NV} + }; + + DBFENTER; + /* Check for aux available */ + result = hfa384x_cmd_aux_enable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1,"aux_enable() failed. result=%d\n", result); + goto failed; + } + + /* Read the pda from each known address. */ + for ( i = 0; i < (sizeof(pdaloc)/sizeof(pdaloc[0])); i++) { + WLAN_LOG_DEBUG( 3, "Checking PDA@(0x%08x,%s)\n", + pdaloc[i].cardaddr, + pdaloc[i].auxctl == HFA384x_AUX_CTL_NV ? + "CTL_NV" : "CTL_EXTDS"); + + /* Copy bufsize bytes from our current pdaloc */ + hfa384x_copy_from_aux(hw, + pdaloc[i].cardaddr, + pdaloc[i].auxctl, + buf, + len); + + /* Test for garbage */ + /* Traverse the PDR list Looking for PDA-END */ + pdaok = 1; /* intially assume good */ + morepdrs = 1; + currpdr = 0; + while ( pdaok && morepdrs ) { + pdrlen = hfa384x2host_16(pda[currpdr]) * 2; + pdrcode = hfa384x2host_16(pda[currpdr+1]); + + /* Test for completion at END record */ + if ( pdrcode == HFA384x_PDR_END_OF_PDA ) { + if ( pdrlen == 4 ) { + morepdrs = 0; + /* Calculate CRC-16 and compare to PDA + * value. Note the addition of 2 words + * for ENDREC.len and ENDREC.code + * fields. + */ + crc = hfa384x_mkcrc16( (UINT8*)pda, + (currpdr + 2) * sizeof(UINT16)); + pdacrc =hfa384x2host_16(pda[currpdr+2]); + if ( crc != pdacrc ) { + WLAN_LOG_DEBUG(3, + "PDA crc failed:" + "calc_crc=0x%04x," + "pdr_crc=0x%04x.\n", + crc, pdacrc); + pdaok = 0; + } + } else { + WLAN_LOG_DEBUG(3, + "END record detected w/ " + "len(%d) != 2, assuming bad PDA\n", + pdrlen); + pdaok = 0; + + } + break; + } + + /* Test the record length */ + if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { + WLAN_LOG_DEBUG(3, + "pdrlen for address #%d " + "at %#x:%#x:%d\n", + i, pdaloc[i].cardaddr, + pdaloc[i].auxctl, pdrlen); + WLAN_LOG_DEBUG(3,"pdrlen invalid=%d\n", + pdrlen); + pdaok = 0; + break; + } + + /* Move to the next pdr */ + if ( morepdrs ) { + /* note the access to pda[], we need words */ + currpdr += hfa384x2host_16(pda[currpdr]) + 1; + if (currpdr*sizeof(UINT16) > len) { + WLAN_LOG_DEBUG(3, + "Didn't find PDA_END in buffer, " + "trying next location.\n"); + pdaok = 0; + break; + } + } + } + if ( pdaok ) { + WLAN_LOG_INFO( + "PDA Read from 0x%08x in %s space.\n", + pdaloc[i].cardaddr, + pdaloc[i].auxctl == 0 ? "EXTDS" : + pdaloc[i].auxctl == 1 ? "NV" : + pdaloc[i].auxctl == 2 ? "PHY" : + pdaloc[i].auxctl == 3 ? "ICSRAM" : + ""); + break; + } + } + result = pdaok ? 0 : -ENODATA; + + if ( result ) { + WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n"); + } + + hfa384x_cmd_aux_disable(hw); +failed: + DBFEXIT; + return result; +} + + + +/*---------------------------------------------------------------- +* mkpda_crc +* +* Calculates the CRC16 for the given PDA and inserts the value +* into the end record. +* +* Arguments: +* pda ptr to the PDA data structure. +* +* Returns: +* 0 - success +* ~0 - failure (probably an errno) +----------------------------------------------------------------*/ +static UINT16 +hfa384x_mkcrc16(UINT8 *p, int len) +{ + UINT16 crc = 0; + UINT8 *lim = p + len; + + while (p < lim) { + crc = (crc >> 8 ) ^ crc16tab[(crc & 0xff) ^ *p++]; + } + + return crc; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_enable +* +* Begins the ram download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and calls cmd_download with the +* ENABLE_VOLATILE subcommand and the exeaddr argument. +* +* Arguments: +* hw device structure +* exeaddr the card execution address that will be +* jumped to when ramdl_disable() is called +* (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr) +{ + int result = 0; + UINT16 lowaddr; + UINT16 hiaddr; + int i; + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_DEBUG(1,"Can't download with a port enabled.\n"); + result = -EINVAL; + goto done; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + WLAN_LOG_DEBUG(1,"Download state not disabled.\n"); + result = -EINVAL; + goto done; + } + + /* Are we supposed to go into genesis mode? */ + if (exeaddr == 0x3f0000) { + UINT16 initseq[2] = { 0xe100, 0xffa1 }; + UINT16 readbuf[2]; + UINT8 hcr = 0x0f; /* Default to x16 SRAM */ + hw->isram16 = 1; + + WLAN_LOG_DEBUG(1, "Dropping into Genesis mode\n"); + + /* Issue card reset and enable aux port */ + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, 0); + hfa384x_cmd_aux_enable(hw, 1); + + /* Genesis set */ + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, hcr); + + /* Validate memory config */ + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + readbuf, sizeof(initseq)); + WLAN_HEX_DUMP(3, "readback", readbuf, sizeof(readbuf)); + + if (memcmp(initseq, readbuf, sizeof(readbuf))) { + hcr = 0x1f; /* x8 SRAM */ + hw->isram16 = 0; + + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, hcr); + + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + readbuf, sizeof(initseq)); + WLAN_HEX_DUMP(2, "readback", readbuf, sizeof(readbuf)); + + if (memcmp(initseq, readbuf, sizeof(readbuf))) { + WLAN_LOG_ERROR("Genesis mode failed\n"); + result = -1; + goto done; + } + } + + /* Now we're in genesis mode */ + hw->dlstate = HFA384x_DLSTATE_GENESIS; + goto done; + } + + /* Retrieve the buffer loc&size and timeout */ + if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, + &(hw->bufinfo), sizeof(hw->bufinfo))) ) { + goto done; + } + hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); + hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); + hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); + if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, + &(hw->dltimeout))) ) { + goto done; + } + hw->dltimeout = hfa384x2host_16(hw->dltimeout); + + /* Enable the aux port */ + if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { + WLAN_LOG_DEBUG(1,"Aux enable failed, result=%d.\n", result); + goto done; + } + + /* Call the download(1,addr) function */ + lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr); + hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); + + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, + lowaddr, hiaddr, 0); + if ( result == 0) { + /* Set the download state */ + hw->dlstate = HFA384x_DLSTATE_RAMENABLED; + } else { + WLAN_LOG_DEBUG(1,"cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", + lowaddr,hiaddr, result); + /* Disable the aux port */ + hfa384x_cmd_aux_disable(hw); + } + + done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_disable +* +* Ends the ram download state. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && + ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { + return -EINVAL; + } + + if (hw->dlstate == HFA384x_DLSTATE_GENESIS) { + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, + hw->isram16 ? 0x07: 0x17); + goto done; + } + + /* Disable the aux port */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + + done: + hw->dlstate = HFA384x_DLSTATE_DISABLED; + hfa384x_cmd_aux_disable(hw); + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_write +* +* Performs a RAM download of a chunk of data. First checks to see +* that we're in the RAM download state, then uses the aux functions +* to 1) copy the data, 2) readback and compare. The download +* state is unaffected. When all data has been written using +* this function, call drvr_ramdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) +{ + int result = 0; + UINT8 *verbuf; + DBFENTER; + /* Check that we're in the ram download state */ + if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && + ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr); +#if 0 +WLAN_HEX_DUMP(1, "dldata", buf, len); +#endif + /* Copy the data via the aux port */ + hfa384x_copy_to_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, buf, len); + + /* Create a buffer for the verify */ + verbuf = kmalloc(len, GFP_KERNEL); + if (verbuf == NULL ) return 1; + + /* Read back and compare */ + hfa384x_copy_from_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, verbuf, len); + + if ( memcmp(buf, verbuf, len) ) { + WLAN_LOG_DEBUG(1,"ramdl verify failed!\n"); + result = -EINVAL; + } + + kfree_s(verbuf, len); + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_enable +* +* Begins the flash download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and retrieves the flash download +* buffer location, buffer size, and timeout length. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) +{ + int result = 0; + int i; + + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_DEBUG(1,"called when port enabled.\n"); + return -EINVAL; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + return -EINVAL; + } + + /* Retrieve the buffer loc&size and timeout */ + if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, + &(hw->bufinfo), sizeof(hw->bufinfo))) ) { + return result; + } + hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); + hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); + hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); + if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, + &(hw->dltimeout))) ) { + return result; + } + hw->dltimeout = hfa384x2host_16(hw->dltimeout); + + /* Enable the aux port */ + if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { + return result; + } + + hw->dlstate = HFA384x_DLSTATE_FLASHENABLED; + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_disable +* +* Ends the flash download state. Note that this will cause the MAC +* firmware to restart. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + /* There isn't much we can do at this point, so I don't */ + /* bother w/ the return value */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hw->dlstate = HFA384x_DLSTATE_DISABLED; + + /* Disable the aux port */ + hfa384x_cmd_aux_disable(hw); + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_write +* +* Performs a FLASH download of a chunk of data. First checks to see +* that we're in the FLASH download state, then sets the download +* mode, uses the aux functions to 1) copy the data to the flash +* buffer, 2) sets the download 'write flash' mode, 3) readback and +* compare. Lather rinse, repeat as many times an necessary to get +* all the given data into flash. +* When all data has been written using this function (possibly +* repeatedly), call drvr_flashdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) +{ + int result = 0; + UINT8 *verbuf; + UINT32 dlbufaddr; + UINT32 currlen; + UINT32 currdaddr; + UINT16 destlo; + UINT16 desthi; + int nwrites; + int i; + + DBFENTER; + /* Check that we're in the flash download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr); + + /* Need a flat address for arithmetic */ + dlbufaddr = HFA384x_ADDR_AUX_MKFLAT( + hw->bufinfo.page, + hw->bufinfo.offset); + verbuf = kmalloc(hw->bufinfo.len, GFP_KERNEL); + +#if 0 +WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout); +#endif + /* Figure out how many times to to the flash prog */ + nwrites = len / hw->bufinfo.len; + nwrites += (len % hw->bufinfo.len) ? 1 : 0; + + if ( verbuf == NULL ) { + WLAN_LOG_ERROR("Failed to allocate flash verify buffer\n"); + return 1; + } + /* For each */ + for ( i = 0; i < nwrites; i++) { + /* Get the dest address and len */ + currlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ? + hw->bufinfo.len : + (len - (hw->bufinfo.len * i)); + currdaddr = daddr + (hw->bufinfo.len * i); + destlo = HFA384x_ADDR_CMD_MKOFF(currdaddr); + desthi = HFA384x_ADDR_CMD_MKPAGE(currdaddr); + WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n", currlen, currdaddr); +#if 0 +WLAN_HEX_DUMP(1, "dldata", buf+(hw->bufinfo.len*i), currlen); +#endif + /* Set the download mode */ + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV, + destlo, desthi, currlen); + if ( result ) { + WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + destlo, desthi, currlen, result); + goto exit_proc; + } + /* copy the data to the flash buffer */ + hfa384x_copy_to_aux(hw, dlbufaddr, HFA384x_AUX_CTL_EXTDS, + buf+(hw->bufinfo.len*i), currlen); + /* set the download 'write flash' mode */ + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NVWRITE, 0,0,0); + if ( result ) { + WLAN_LOG_ERROR( + "download(NVWRITE,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + destlo, desthi, currlen, result); + goto exit_proc; + } + /* readback and compare, if fail...bail */ + hfa384x_copy_from_aux(hw, + currdaddr, HFA384x_AUX_CTL_NV, + verbuf, currlen); + + if ( memcmp(buf+(hw->bufinfo.len*i), verbuf, currlen) ) { + return -EINVAL; + } + } + +exit_proc: + /* DOH! This kfree's for you Mark :-) My forehead hurts... */ + kfree(verbuf); + + /* Leave the firmware in the 'post-prog' mode. flashdl_disable will */ + /* actually disable programming mode. Remember, that will cause the */ + /* the firmware to effectively reset itself. */ + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_initialize +* +* Issues the initialize command and sets the hw->state based +* on the result. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_initialize(hfa384x_t *hw) +{ + int result = 0; + int i; + hfa384x_metacmd_t cmd; + + DBFENTER; + + /* we don't want to be interrupted during the reset */ + hfa384x_setreg(hw, 0, HFA384x_INTEN); + hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); + + cmd.cmd = HFA384x_CMDCODE_INIT; + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + if ( result == 0 ) { + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + } + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_commtallies +* +* Send a commtallies inquiry to the MAC. Note that this is an async +* call that will result in an info frame arriving sometime later. +* +* Arguments: +* hw device structure +* +* Returns: +* zero success. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_commtallies( hfa384x_t *hw ) +{ + hfa384x_metacmd_t cmd; + int result; + + DBFENTER; + + cmd.cmd = HFA384x_CMDCODE_INQ; + cmd.parm0 = HFA384x_IT_COMMTALLIES; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_enable +* +* Issues the enable command to enable communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also enable macports 1-6. Only ports that are currently +* disabled may be enabled. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + (hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_enable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 1; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_enable +* +* Issues the the enable command to enable communications on one of the +* MACs 'ports'. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_disable +* +* Issues the disable command to stop communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also disable macports 1-6. Only ports that have been +* previously enabled may be disabled. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + !(hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_disable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 0; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_disable +* +* Issues the command to disable a port. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_diagnose +* +* Issues the diagnose command to test the: register interface, +* MAC controller (including loopback), External RAM, Non-volatile +* memory integrity, and synthesizers. Following execution of this +* command, MAC/firmware are in the 'initial state'. Therefore, +* the Initialize command should be issued after successful +* completion of this command. This function may only be called +* when the MAC is in the 'communication disabled' state. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +#define DIAG_PATTERNA ((UINT16)0xaaaa) +#define DIAG_PATTERNB ((UINT16)0x5555) + +int hfa384x_cmd_diagnose(hfa384x_t *hw) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DIAG); + cmd.parm0 = DIAG_PATTERNA; + cmd.parm1 = DIAG_PATTERNB; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_allocate +* +* Issues the allocate command instructing the firmware to allocate +* a 'frame structure buffer' in MAC controller RAM. This command +* does not provide the result, it only initiates one of the f/w's +* asynchronous processes to construct the buffer. When the +* allocation is complete, it will be indicated via the Alloc +* bit in the EvStat register and the FID identifying the allocated +* space will be available from the AllocFID register. Some care +* should be taken when waiting for the Alloc event. If a Tx or +* Notify command w/ Reclaim has been previously executed, it's +* possible the first Alloc event after execution of this command +* will be for the reclaimed buffer and not the one you asked for. +* This case must be handled in the Alloc event handler. +* +* Arguments: +* hw device structure +* len allocation length, must be an even value +* in the range [4-2400]. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + if ( (len % 2) || + len < HFA384x_CMD_ALLOC_LEN_MIN || + len > HFA384x_CMD_ALLOC_LEN_MAX ) { + result = -EINVAL; + } else { + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC); + cmd.parm0 = len; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_transmit +* +* Instructs the firmware to transmit a frame previously copied +* to a given buffer. This function returns immediately, the Tx +* results are available via the Tx or TxExc events (if the frame +* control bits are set). The reclaim argument specifies if the +* FID passed will be used by the f/w tx process or returned for +* use w/ another transmit command. If reclaim is set, expect an +* Alloc event signalling the availibility of the FID for reuse. +* +* NOTE: hw->cmdlock MUST BE HELD before calling this function! +* +* Arguments: +* hw device structure +* reclaim [0|1] indicates whether the given FID will +* be handed back (via Alloc event) for reuse. +* (host order) +* qos [0-3] Value to put in the QoS field of the +* tx command, identifies a queue to place the +* outgoing frame in. +* (host order) +* fid FID of buffer containing the frame that was +* previously copied to MAC memory via the bap. +* (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* hw->resp0 will contain the FID being used by async tx +* process. If reclaim==0, resp0 will be the same as the fid +* argument. If reclaim==1, resp0 will be the different and +* is the value to watch for in the Tx|TxExc to indicate completion +* of the frame passed in fid. +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX) | + HFA384x_CMD_RECL_SET(reclaim) | + HFA384x_CMD_QOS_SET(qos); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_clearpersist +* +* Instructs the firmware to clear the persistence bit in a given +* FID. This has the effect of telling the firmware to drop the +* persistent frame. The FID must be one that was previously used +* to transmit a PRST frame. +* +* Arguments: +* hw device structure +* fid FID of the persistent frame (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_CLRPRST); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_cmd_notify +* +* Sends an info frame to the firmware to alter the behavior +* of the f/w asynch processes. Can only be called when the MAC +* is in the enabled state. +* +* Arguments: +* hw device structure +* reclaim [0|1] indicates whether the given FID will +* be handed back (via Alloc event) for reuse. +* (host order) +* fid FID of buffer containing the frame that was +* previously copied to MAC memory via the bap. +* (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* hw->resp0 will contain the FID being used by async notify +* process. If reclaim==0, resp0 will be the same as the fid +* argument. If reclaim==1, resp0 will be the different. +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, + void *buf, UINT16 len) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_NOTIFY) | + HFA384x_CMD_RECL_SET(reclaim); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + + /* Copy the record to FID */ + result = hfa384x_copy_to_bap(hw, HFA384x_BAP_PROC, hw->infofid, 0, buf, len); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_to_bap(%04x, 0, %d) failed, result=0x%x\n", + hw->infofid, len, result); + result = -EIO; + goto failed; + } + + result = hfa384x_docmd_wait(hw, &cmd); + + failed: + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +#if 0 +/*---------------------------------------------------------------- +* hfa384x_cmd_inquiry +* +* Requests an info frame from the firmware. The info frame will +* be delivered asynchronously via the Info event. +* +* Arguments: +* hw device structure +* fid FID of the info frame requested. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int hfa384x_cmd_inquiry(hfa384x_t *hw, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_INQ); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} +#endif + + +/*---------------------------------------------------------------- +* hfa384x_cmd_access +* +* Requests that a given record be copied to/from the record +* buffer. If we're writing from the record buffer, the contents +* must previously have been written to the record buffer via the +* bap. If we're reading into the record buffer, the record can +* be read out of the record buffer after this call. +* +* Arguments: +* hw device structure +* write [0|1] copy the record buffer to the given +* configuration record. (host order) +* rid RID of the record to read/write. (host order) +* buf host side record buffer. Upon return it will +* contain the body portion of the record (minus the +* RID and len). +* len buffer length (in bytes, should match record length) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, + void* buf, UINT16 len) +{ + int result = 0; + hfa384x_metacmd_t cmd; + hfa384x_rec_t rec; + + DBFENTER; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) + /* This should NOT be called in interrupt context! */ + if (in_irq()) { + WLAN_LOG_ERROR("Krap, in Interrupt context!"); +#ifdef WLAN_INCLUDE_DEBUG + BUG(); +#endif + } +#endif + spin_lock_bh(&hw->cmdlock); + + if (write) { + rec.rid = host2hfa384x_16(rid); + rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */ + /* write the record */ + result = hfa384x_copy_to_bap4( hw, HFA384x_BAP_PROC, rid, 0, + &rec, sizeof(rec), + buf, len, + NULL, 0, NULL, 0); + if ( result ) { + WLAN_LOG_DEBUG(3,"Failure writing record header+data\n"); + goto fail; + } + + } + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | + HFA384x_CMD_WRITE_SET(write); + cmd.parm0 = rid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + if ( result ) { + WLAN_LOG_ERROR("Call to hfa384x_docmd_wait failed (%d %d)\n", + result, cmd.result.resp0); + goto fail; + } + + if (!write) { + result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, 0, &rec, sizeof(rec)); + if ( result ) { + WLAN_LOG_DEBUG(3,"Call to hfa384x_copy_from_bap failed\n"); + goto fail; + } + + /* Validate the record length */ + if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */ + WLAN_LOG_DEBUG(1, "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", + rid, len, (hfa384x2host_16(rec.reclen)-1)*2); + result = -ENODATA; + goto fail; + } + + result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, sizeof(rec), buf, len); + + } + + fail: + spin_unlock_bh(&hw->cmdlock); + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_monitor +* +* Enables the 'monitor mode' of the MAC. Here's the description of +* monitor mode that I've received thus far: +* +* "The "monitor mode" of operation is that the MAC passes all +* frames for which the PLCP checks are correct. All received +* MPDUs are passed to the host with MAC Port = 7, with a +* receive status of good, FCS error, or undecryptable. Passing +* certain MPDUs is a violation of the 802.11 standard, but useful +* for a debugging tool." Normal communication is not possible +* while monitor mode is enabled. +* +* Arguments: +* hw device structure +* enable a code (0x0b|0x0f) that enables/disables +* monitor mode. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | + HFA384x_CMD_AINFO_SET(enable); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_download +* +* Sets the controls for the MAC controller code/data download +* process. The arguments set the mode and address associated +* with a download. Note that the aux registers should be enabled +* prior to setting one of the download enable modes. +* +* Arguments: +* hw device structure +* mode 0 - Disable programming and begin code exec +* 1 - Enable volatile mem programming +* 2 - Enable non-volatile mem programming +* 3 - Program non-volatile section from NV download +* buffer. +* (host order) +* lowaddr +* highaddr For mode 1, sets the high & low order bits of +* the "destination address". This address will be +* the execution start address when download is +* subsequently disabled. +* For mode 2, sets the high & low order bits of +* the destination in NV ram. +* For modes 0 & 3, should be zero. (host order) +* NOTE: these address args are in CMD format +* codelen Length of the data to write in mode 2, +* zero otherwise. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_download(hfa384x_t *hw, UINT16 mode, UINT16 lowaddr, + UINT16 highaddr, UINT16 codelen) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) | + HFA384x_CMD_PROGMODE_SET(mode); + cmd.parm0 = lowaddr; + cmd.parm1 = highaddr; + cmd.parm2 = codelen; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_dl_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_aux_enable +* +* Goes through the process of enabling the auxilary port. This +* is necessary prior to raw reads/writes to card data space. +* Direct access to the card data space is only used for downloading +* code and debugging. +* Note that a call to this function is required before attempting +* a download. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_aux_enable(hfa384x_t *hw, int force) +{ + int result = -ETIMEDOUT; + unsigned long flags; + UINT32 retries_remaining; + UINT16 reg; + UINT auxen_mirror = hw->auxen; + + DBFENTER; + + /* Check for existing enable */ + if ( hw->auxen ) { + hw->auxen++; + return 0; + } + + /* acquire the lock */ + spin_lock_irqsave( &(hw->cmdlock), flags); + /* wait for cmd register busy bit to clear */ + retries_remaining = 100000; + do { + reg = hfa384x_getreg(hw, HFA384x_CMD); + udelay(10); + } + while (HFA384x_CMD_ISBUSY(reg) && --retries_remaining); + if (retries_remaining != 0) { + /* busy bit clear, it's OK to write to ParamX regs */ + hfa384x_setreg(hw, HFA384x_AUXPW0, + HFA384x_PARAM0); + hfa384x_setreg(hw, HFA384x_AUXPW1, + HFA384x_PARAM1); + hfa384x_setreg(hw, HFA384x_AUXPW2, + HFA384x_PARAM2); + + /* Set the aux enable in the Control register */ + hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DOENABLE, + HFA384x_CONTROL); + + /* Now wait for completion */ + retries_remaining = 100000; + do { + reg = hfa384x_getreg(hw, HFA384x_CONTROL); + udelay(10); + } + while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISENABLED) && + --retries_remaining ); + if (retries_remaining != 0) { + result = 0; + hw->auxen++; + } + } + + /* Force it enabled even if the command failed, if told.. */ + if ((hw->auxen == auxen_mirror) && force) + hw->auxen++; + + spin_unlock_irqrestore( &(hw->cmdlock), flags); + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_aux_disable +* +* Goes through the process of disabling the auxilary port +* enabled with aux_enable(). +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_aux_disable(hfa384x_t *hw) +{ + int result = -ETIMEDOUT; + unsigned long timeout; + UINT16 reg = 0; + + DBFENTER; + + /* See if there's more than one enable */ + if (hw->auxen) hw->auxen--; + if (hw->auxen) return 0; + + /* Clear the aux enable in the Control register */ + hfa384x_setreg(hw, 0, HFA384x_PARAM0); + hfa384x_setreg(hw, 0, HFA384x_PARAM1); + hfa384x_setreg(hw, 0, HFA384x_PARAM2); + hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DODISABLE, + HFA384x_CONTROL); + + /* Now wait for completion */ + timeout = jiffies + 1*HZ; + reg = hfa384x_getreg(hw, HFA384x_CONTROL); + while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISDISABLED) && + time_before(jiffies,timeout) ){ + udelay(10); + reg = hfa384x_getreg(hw, HFA384x_CONTROL); + } + if ((reg & (BIT14|BIT15)) == HFA384x_CONTROL_AUX_ISDISABLED ) { + result = 0; + } + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_low_level +* +* Write test commands to the card. Some test commands don't make +* sense without prior set-up. For example, continous TX isn't very +* useful until you set the channel. That functionality should be +* +* Side effects: +* +* Call context: +* process thread +* -----------------------------------------------------------------*/ +int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result = 0; + DBFENTER; + + /* Do i need a host2hfa... conversion ? */ +#if 0 + printk(KERN_INFO "%#x %#x %#x %#x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2); +#endif + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/* TODO: determine if these will ever be needed */ +#if 0 +int hfa384x_cmd_readmif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} + + +int hfa384x_cmd_writemif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} +#endif + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_read +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* register The test register to be accessed (must be even #). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = (UINT16) 0x30; + cmd.parm0 = (UINT16) addr; + cmd.parm1 = 0; + cmd.parm2 = 0; + + /* Do i need a host2hfa... conversion ? */ + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + *resp = (UINT32) cmd.result.resp0; + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_write +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* addr The test register to be accessed (must be even #). +* data The data value to write to the register. +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ + +int +hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = (UINT16) 0x31; + cmd.parm0 = (UINT16) addr; + cmd.parm1 = (UINT16) data; + cmd.parm2 = 0; + + WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08x\n", addr); + WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08x\n", data); + + /* Do i need a host2hfa... conversion ? */ + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/* TODO: determine if these will ever be needed */ +#if 0 +int hfa384x_cmd_readmif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} + + +int hfa384x_cmd_writemif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} +#endif + + + +/*---------------------------------------------------------------- +* hfa384x_copy_from_bap +* +* Copies a collection of bytes from the MAC controller memory via +* one set of BAP registers. +* +* Arguments: +* hw device structure +* bap [0|1] which BAP to use +* id FID or RID, destined for the select register (host order) +* offset An _even_ offset into the buffer for the given +* FID/RID. We haven't the means to validate this, +* so be careful. (host order) +* buf ptr to array of bytes +* len length of data to transfer in bytes +* +* Returns: +* 0 success +* >0 f/w reported failure - value of offset reg. +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len) +{ + int result = 0; + unsigned long flags = 0; + UINT8 *d = (UINT8*)buf; + UINT selectreg; + UINT offsetreg; + UINT datareg; + UINT i; + UINT16 reg = 0; + + DBFENTER; + + /* Validate bap, offset, buf, and len */ + if ( (bap > 1) || + (offset > HFA384x_BAP_OFFSET_MAX) || + (offset % 2) || + (buf == NULL) || + (len > HFA384x_BAP_DATALEN_MAX) ){ + result = -EINVAL; + } else { + selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0 ; + offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0 ; + datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0 ; + + /* Obtain lock */ + spin_lock_irqsave( &(hw->baplock), flags); + + /* Write id to select reg */ + hfa384x_setreg(hw, id, selectreg); + /* Write offset to offset reg */ + hfa384x_setreg(hw, offset, offsetreg); + /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ + i = 0; + do { + reg = hfa384x_getreg(hw, offsetreg); + if ( i > 0 ) udelay(10); + i++; + } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg)); +#if (WLAN_HOSTIF != WLAN_PCI) + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + if ( HFA384x_OFFSET_ISBUSY(reg) ){ + /* If timeout, return -ETIMEDOUT */ + result = reg; + } else if ( HFA384x_OFFSET_ISERR(reg) ){ + /* If offset[err] == 1, return -EINVAL */ + result = reg; + } else { + /* Read even(len) buf contents from data reg */ + for ( i = 0; i < (len & 0xfffe); i+=2 ) { + *(UINT16*)(&(d[i])) = + hfa384x_getreg_noswap(hw, datareg); + } + /* If len odd, handle last byte */ + if ( len % 2 ){ + reg = hfa384x_getreg_noswap(hw, datareg); + d[len-1] = ((UINT8*)(®))[0]; + } + } + + /* According to Intersil errata dated 9/16/02: + + "In PRISM PCI MAC host interface, if both BAPs are concurrently + requesing memory access, both will accept the Ack. There is no + firmware workaround possible. To prevent BAP access failures or + hang conditions the host MUST NOT access both BAPs in sucession + unless at least 5us elapses between accesses. The safest choice + is to USE ONLY ONE BAP for all data movement operations." + + What this means: + + We have to serialize ALL BAP accesses, and furthermore, add a 5us + delay after access if we're using a PCI platform. + + Unfortunately, this means we have to lock out interrupts througout + the entire BAP copy. + + It remains to be seen if "BAP access" means "BAP setup" or the more + literal definition of "copying data back and forth" I'm erring for + the latter, safer definition. -- SLP. + + */ + +#if (WLAN_HOSTIF == WLAN_PCI) + udelay(5); + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + } + + if (result) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + reg, len, result); + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_to_bap +* +* Copies a collection of bytes to the MAC controller memory via +* one set of BAP registers. +* +* Arguments: +* hw device structure +* bap [0|1] which BAP to use +* id FID or RID, destined for the select register (host order) +* offset An _even_ offset into the buffer for the given +* FID/RID. We haven't the means to validate this, +* so be careful. (host order) +* buf ptr to array of bytes +* len length of data to transfer (in bytes) +* +* Returns: +* 0 success +* >0 f/w reported failure - value of offset reg. +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len) +{ + return hfa384x_copy_to_bap4(hw, bap, id, offset, buf, len, NULL, 0, NULL, 0, NULL, 0); +} + +int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len1, void* buf2, UINT len2, + void *buf3, UINT len3, void *buf4, UINT len4) +{ + int result = 0; + unsigned long flags = 0; + UINT8 *d; + UINT selectreg; + UINT offsetreg; + UINT datareg; + UINT i; + UINT16 reg; + + DBFENTER; + +// printk(KERN_DEBUG "ctb1 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4); + + /* Validate bap, offset, buf, and len */ + if ( (bap > 1) || + (offset > HFA384x_BAP_OFFSET_MAX) || + (offset % 2) || + (buf == NULL) || + (len1+len2+len3+len4 > HFA384x_BAP_DATALEN_MAX) ){ + result = -EINVAL; + } else { + selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0; + offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0; + datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0; + /* Obtain lock */ + spin_lock_irqsave( &(hw->baplock), flags); + + /* Write id to select reg */ + hfa384x_setreg(hw, id, selectreg); + udelay(10); + /* Write offset to offset reg */ + hfa384x_setreg(hw, offset, offsetreg); + /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ + i = 0; + do { + reg = hfa384x_getreg(hw, offsetreg); + if ( i > 0 ) udelay(10); + i++; + } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg)); + +#if (WLAN_HOSTIF != WLAN_PCI) + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + if ( HFA384x_OFFSET_ISBUSY(reg) ){ + /* If timeout, return reg */ + result = reg; + } else if ( HFA384x_OFFSET_ISERR(reg) ){ + /* If offset[err] == 1, return reg */ + result = reg; + } else { + d = (UINT8*)buf; + /* Write even(len1) buf contents to data reg */ + for ( i = 0; i < (len1 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, + *(UINT16*)(&(d[i])), datareg); + } + if (len1 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len1-1]; + if (buf2 != NULL) { + d = (UINT8*)buf2; + b[1] = d[0]; + len2--; + buf2++; + } + hfa384x_setreg_noswap(hw, data, datareg); + } + if ((buf2 != NULL) && (len2 > 0)) { + /* Write even(len2) buf contents to data reg */ + d = (UINT8*)buf2; + for ( i = 0; i < (len2 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); + } + if (len2 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len2-1]; + if (buf3 != NULL) { + d = (UINT8*)buf3; + b[1] = d[0]; + len3--; + buf3++; + } + hfa384x_setreg_noswap(hw, data, datareg); + } + } + + if ((buf3 != NULL) && (len3 > 0)) { + /* Write even(len3) buf contents to data reg */ + d = (UINT8*)buf3; + for ( i = 0; i < (len3 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); + } + if (len3 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len3-1]; + if (buf4 != NULL) { + d = (UINT8*)buf4; + b[1] = d[0]; + len4--; + buf4++; + } + hfa384x_setreg_noswap(hw, data, datareg); + } + } + if ((buf4 != NULL) && (len4 > 0)) { + /* Write even(len4) buf contents to data reg */ + d = (UINT8*)buf4; + for ( i = 0; i < (len4 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); + } + if (len4 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len4-1]; + b[1] = 0; + + hfa384x_setreg_noswap(hw, data, datareg); + } + } +// printk(KERN_DEBUG "ctb2 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4); + + } + +#if (WLAN_HOSTIF == WLAN_PCI) + udelay(5); + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + } + + if (result) + WLAN_LOG_ERROR("copy_to_bap() failed.\n"); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_from_aux +* +* Copies a collection of bytes from the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* buf contains the data copied +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_from_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + UINT16 currpage; + UINT16 curroffset; + UINT i = 0; + + DBFENTER; + + if ( !(hw->auxen) ) { + WLAN_LOG_DEBUG(1, + "Attempt to read 0x%04x when aux not enabled\n", + cardaddr); + return; + + } + /* Build appropriate aux page and offset */ + currpage = HFA384x_AUX_MKPAGE(cardaddr); + curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl); + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + + /* read the data */ + while ( i < len) { + *((UINT16*)(buf+i)) = hfa384x_getreg_noswap(hw, HFA384x_AUXDATA); + i+=2; + curroffset+=2; + if ( (curroffset&HFA384x_ADDR_AUX_OFF_MASK) > + HFA384x_ADDR_AUX_OFF_MAX ) { + currpage++; + curroffset = 0; + curroffset = HFA384x_AUX_MKOFF(curroffset, auxctl); + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + } + } + /* Make sure the auxctl bits are clear */ + hfa384x_setreg(hw, 0, HFA384x_AUXOFFSET); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_to_aux +* +* Copies a collection of bytes to the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* Controller memory now contains a copy of buf +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_to_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + UINT16 currpage; + UINT16 curroffset; + UINT i = 0; + + DBFENTER; + + if ( !(hw->auxen) ) { + WLAN_LOG_DEBUG(1, + "Attempt to read 0x%04x when aux not enabled\n", + cardaddr); + return; + + } + /* Build appropriate aux page and offset */ + currpage = HFA384x_AUX_MKPAGE(cardaddr); + curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl); + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + + /* write the data */ + while ( i < len) { + hfa384x_setreg_noswap(hw, + *((UINT16*)(buf+i)), HFA384x_AUXDATA); + i+=2; + curroffset+=2; + if ( curroffset > HFA384x_ADDR_AUX_OFF_MAX ) { + currpage++; + curroffset = 0; + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + } + } + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_wait +* +* Waits for availability of the Command register, then +* issues the given command. Then polls the Evstat register +* waiting for command completion. Timeouts shouldn't be +* possible since we're preventing overlapping commands and all +* commands should be cleared and acknowledged. +* +* Arguments: +* wlandev device structure +* cmd cmd structure. Includes all arguments and result +* data points. All in host order. +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result = -ETIMEDOUT; + UINT16 reg = 0; + UINT16 counter; + + DBFENTER; + + hw->cmdflag = 0; + hw->cmddata = cmd; + + /* wait for the busy bit to clear */ + counter = 0; + reg = hfa384x_getreg(hw, HFA384x_CMD); + while ( HFA384x_CMD_ISBUSY(reg) && + (counter < 10)) { + reg = hfa384x_getreg(hw, HFA384x_CMD); + counter++; + udelay(10); + } + + if (HFA384x_CMD_ISBUSY(reg)) { + WLAN_LOG_ERROR("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg); + goto failed; + } + if (!HFA384x_CMD_ISBUSY(reg)) { + /* busy bit clear, write command */ + hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0); + hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1); + hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2); + hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD); + +#ifdef CMD_IRQ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)) + while (! hw->cmdflag) + interruptible_sleep_on(&hw->cmdq); +#else + wait_event_interruptible(hw->cmdq, hw->cmdflag); +#endif + result = HFA384x_STATUS_RESULT_GET(cmd->status); +#else // CMD_IRQ + /* Now wait for completion */ + counter = 0; + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + /* Initialization is the problem. It takes about + 100ms. "normal" commands are typically is about + 200-400 us (I've never seen less than 200). Longer + is better so that we're not hammering the bus. */ + while ( !HFA384x_EVSTAT_ISCMD(reg) && + (counter < 5000)) { + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + counter++; + udelay(200); + } + + if ( HFA384x_EVSTAT_ISCMD(reg) ) { + result = 0; + cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS); + cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0); + cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1); + cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2); + hfa384x_setreg(hw, HFA384x_EVACK_CMD, + HFA384x_EVACK); + result = HFA384x_STATUS_RESULT_GET(cmd->result.status); + } else { + WLAN_LOG_ERROR("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg); + } +#endif /* CMD_IRQ */ + } + + failed: + hw->cmdflag = 0; + hw->cmddata = NULL; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_dl_docmd_wait +* +* Waits for availability of the Command register, then +* issues the given command. Then polls the Evstat register +* waiting for command completion. Timeouts shouldn't be +* possible since we're preventing overlapping commands and all +* commands should be cleared and acknowledged. +* +* This routine is only used for downloads. Since it doesn't lock out +* interrupts the system response is much better. +* +* Arguments: +* wlandev device structure +* cmd cmd structure. Includes all arguments and result +* data points. All in host order. +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result = -ETIMEDOUT; + unsigned long timeout; + UINT16 reg = 0; + + DBFENTER; + /* wait for the busy bit to clear */ + timeout = jiffies + 1*HZ; + reg = hfa384x_getreg(hw, HFA384x_CMD); + while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) { + reg = hfa384x_getreg(hw, HFA384x_CMD); + udelay(10); + } + if (HFA384x_CMD_ISBUSY(reg)) { + WLAN_LOG_WARNING("Timed out waiting for cmd register.\n"); + goto failed; + } + + if (!HFA384x_CMD_ISBUSY(reg)) { + /* busy bit clear, write command */ + hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0); + hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1); + hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2); + hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD); + + /* Now wait for completion */ + if ( (HFA384x_CMD_CMDCODE_GET(cmd->cmd) == HFA384x_CMDCODE_DOWNLD) ) { + /* dltimeout is in ms */ + timeout = (((UINT32)hw->dltimeout) / 1000UL) * HZ; + if ( timeout > 0 ) { + timeout += jiffies; + } else { + timeout = jiffies + 1*HZ; + } + } else { + timeout = jiffies + 1*HZ; + } + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + while ( !HFA384x_EVSTAT_ISCMD(reg) && time_before(jiffies,timeout) ) { + udelay(100); + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + } + if ( HFA384x_EVSTAT_ISCMD(reg) ) { + result = 0; + cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS); + cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0); + cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1); + cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2); + hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK); + result = HFA384x_STATUS_RESULT_GET(cmd->result.status); + } + } + +failed: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_start +* +* Issues the MAC initialize command, sets up some data structures, +* and enables the interrupts. After this function completes, the +* low-level stuff should be ready for any/all commands. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_start(hfa384x_t *hw) +{ + int result = 0; + UINT16 reg; + int i; + int j; + DBFENTER; + + /* call initialize */ + result = hfa384x_cmd_initialize(hw); + if (result != 0) { + WLAN_LOG_ERROR("Initialize command failed.\n"); + goto failed; + } + + /* make sure interrupts are disabled and any layabout events cleared */ + hfa384x_setreg(hw, 0, HFA384x_INTEN); + hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); + + hw->txfid_head = 0; + hw->txfid_tail = 0; + hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX; + memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue)); + + /* Allocate tx and notify FIDs */ + /* First, tx */ + for ( i = 0; i < HFA384x_DRVR_FIDSTACKLEN_MAX-1; i++) { + result = hfa384x_cmd_allocate(hw, HFA384x_DRVR_TXBUF_MAX); + if (result != 0) { + WLAN_LOG_ERROR("Allocate(tx) command failed.\n"); + goto failed; + } + j = 0; + do { + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + udelay(10); + j++; + } while ( !HFA384x_EVSTAT_ISALLOC(reg) && j < 50); /* 50 is timeout */ + if ( j >= 50 ) { + WLAN_LOG_ERROR("Timed out waiting for evalloc(tx).\n"); + result = -ETIMEDOUT; + goto failed; + } + reg = hfa384x_getreg(hw, HFA384x_ALLOCFID); + + txfid_queue_add(hw, reg); + + WLAN_LOG_DEBUG(4,"hw->txfid_queue[%d]=0x%04x\n",i,reg); + + reg = HFA384x_EVACK_ALLOC_SET(1); + hfa384x_setreg(hw, reg, HFA384x_EVACK); + + } + + /* Now, the info frame fid */ + result = hfa384x_cmd_allocate(hw, HFA384x_INFOFRM_MAXLEN); + if (result != 0) { + WLAN_LOG_ERROR("Allocate(tx) command failed.\n"); + goto failed; + } + i = 0; + do { + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + udelay(10); + i++; + } while ( !HFA384x_EVSTAT_ISALLOC(reg) && i < 50); /* 50 is timeout */ + if ( i >= 50 ) { + WLAN_LOG_ERROR("Timed out waiting for evalloc(info).\n"); + result = -ETIMEDOUT; + goto failed; + } + hw->infofid = hfa384x_getreg(hw, HFA384x_ALLOCFID); + reg = HFA384x_EVACK_ALLOC_SET(1); + hfa384x_setreg(hw, reg, HFA384x_EVACK); + WLAN_LOG_DEBUG(4,"hw->infofid=0x%04x\n", hw->infofid); + + /* Set swsupport regs to magic # for card presence detection */ + hfa384x_setreg(hw, HFA384x_DRVR_MAGIC, HFA384x_SWSUPPORT0); + + /* Now enable the interrupts and set the running state */ + hfa384x_setreg(hw, 0xffff, HFA384x_EVSTAT); + hfa384x_events_all(hw); + + hw->state = HFA384x_STATE_RUNNING; + + goto done; +failed: + WLAN_LOG_ERROR("Failed, result=%d\n", result); +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_stop +* +* Issues the initialize command to leave us in the 'reset' state. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_stop(hfa384x_t *hw) +{ + int result = 0; + int i; + DBFENTER; + + del_timer_sync(&hw->commsqual_timer); + + if ( hw->wlandev->hwremoved ) { + /* only flush when we're shutting down for good */ + flush_scheduled_work(); + } + + if (hw->state == HFA384x_STATE_RUNNING) { + /* + * Send the MAC initialize cmd. + */ + hfa384x_cmd_initialize(hw); + + /* + * Make absolutely sure interrupts are disabled and any + * layabout events cleared + */ + hfa384x_setreg(hw, 0, HFA384x_INTEN); + hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); + } + + tasklet_kill(&hw->bap_tasklet); + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + /* Clear all the port status */ + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_txframe +* +* Takes a frame from prism2sta and queues it for transmission. +* +* Arguments: +* hw device structure +* skb packet buffer struct. Contains an 802.11 +* data frame. +* p80211_hdr points to the 802.11 header for the packet. +* Returns: +* 0 Success and more buffs available +* 1 Success but no more buffs +* 2 Allocation failure +* 3 MAC Tx command failed +* 4 Buffer full or queue busy +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) +{ + hfa384x_tx_frame_t txdesc; + UINT16 macq = 0; + UINT16 fid; + int result; + + DBFENTER; + + /* Build Tx frame structure */ + /* Set up the control field */ + memset(&txdesc, 0, sizeof(txdesc)); + +/* Tx complete and Tx exception disable per dleach. Might be causing + * buf depletion + */ +#define DOBOTH 1 +#if DOBOTH + txdesc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1); +#elif DOEXC + txdesc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0); +#else + txdesc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0); +#endif + + /* if we're using host WEP, increase size by IV+ICV */ + if (p80211_wep->data) { + txdesc.data_len = host2hfa384x_16(skb->len+8); + // txdesc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1); + } else { + txdesc.data_len = host2hfa384x_16(skb->len); + } + + txdesc.tx_control = host2hfa384x_16(txdesc.tx_control); + /* copy the header over to the txdesc */ + memcpy(&(txdesc.frame_control), p80211_hdr, sizeof(p80211_hdr_t)); + + /* Since tbusy is set whenever the stack is empty, there should + * always be something on the stack if we get to this point. + * [MSM]: NOT TRUE!!!!! so I added the test of fid below. + */ + + /* Allocate FID */ + + fid = txfid_queue_remove(hw); + + if ( fid == 0 ) { /* stack or queue was empty */ + return 4; + } + + /* now let's get the cmdlock */ + spin_lock(&hw->cmdlock); + + /* Copy descriptor+payload to FID */ + if (p80211_wep->data) { + result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0, + &txdesc, sizeof(txdesc), + p80211_wep->iv, sizeof(p80211_wep->iv), + p80211_wep->data, skb->len, + p80211_wep->icv, sizeof(p80211_wep->icv)); + } else { + result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0, + &txdesc, sizeof(txdesc), + skb->data, skb->len, + NULL, 0, NULL, 0); + } + + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_to_bap(%04x, %d, %d) failed, result=0x%x\n", + fid, + sizeof(txdesc), + skb->len, + result); + + /* put the fid back in the queue */ + txfid_queue_add(hw, fid); + + result = 3; + goto failed; + } + + /* Issue Tx command */ + result = hfa384x_cmd_transmit(hw, HFA384x_TXCMD_RECL, macq, fid); + + if ( result != 0 ) { + txfid_queue_add(hw, fid); + + WLAN_LOG_DEBUG(1,"cmd_tx(%04x) failed, result=%d\n", + fid, result); + result = 3; + goto failed; + } + + /* indicate we haven't any buffers, int_alloc will clear */ + result = txfid_queue_empty(hw); +failed: + + spin_unlock(&hw->cmdlock); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_interrupt +* +* Driver interrupt handler. +* +* Arguments: +* irq irq number +* dev_id pointer to the device +* regs registers +* +* Returns: +* nothing +* +* Side effects: +* May result in a frame being passed up the stack or an info +* frame being handled. +* +* Call context: +* Ummm, could it be interrupt? +----------------------------------------------------------------*/ +irqreturn_t hfa384x_interrupt(int irq, void *dev_id PT_REGS) +{ + int reg; + wlandevice_t *wlandev = (wlandevice_t*)dev_id; + hfa384x_t *hw = wlandev->priv; + int ev_read = 0; + DBFENTER; + + if (!wlandev || wlandev->hwremoved) + return IRQ_NONE; /* Not much we can do w/o hardware */ +#if (WLAN_HOSTIF == WLAN_PCMCIA) + if (hw->iobase == 0) /* XXX FIXME Properly */ + return IRQ_NONE; +#endif + + for (;;ev_read++) { + if (ev_read >= prism2_irq_evread_max) + break; + + /* Check swsupport reg magic # for card presence */ + reg = hfa384x_getreg(hw, HFA384x_SWSUPPORT0); + if ( reg != HFA384x_DRVR_MAGIC) { + WLAN_LOG_DEBUG(2, "irq=%d, no magic. Card removed?.\n", irq); + break; + } + + /* read the EvStat register for interrupt enabled events */ + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + + /* AND with the enabled interrupts */ + reg &= hfa384x_getreg(hw, HFA384x_INTEN); + + /* Handle the events */ + if ( HFA384x_EVSTAT_ISWTERR(reg) ){ + WLAN_LOG_ERROR( + "Error: WTERR interrupt received (unhandled).\n"); + hfa384x_setreg(hw, HFA384x_EVACK_WTERR_SET(1), + HFA384x_EVACK); + } + + if ( HFA384x_EVSTAT_ISINFDROP(reg) ){ + hfa384x_int_infdrop(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_INFDROP_SET(1), + HFA384x_EVACK); + } + + if (HFA384x_EVSTAT_ISBAP_OP(reg)) { + /* Disable the BAP interrupts */ + hfa384x_events_nobap(hw); + tasklet_schedule(&hw->bap_tasklet); + } + + if ( HFA384x_EVSTAT_ISALLOC(reg) ){ + hfa384x_int_alloc(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_ALLOC_SET(1), + HFA384x_EVACK); + } + + if ( HFA384x_EVSTAT_ISDTIM(reg) ){ + hfa384x_int_dtim(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_DTIM_SET(1), + HFA384x_EVACK); + } +#ifdef CMD_IRQ + if ( HFA384x_EVSTAT_ISCMD(reg) ){ + hfa384x_int_cmd(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_CMD_SET(1), + HFA384x_EVACK); + } +#endif + + /* allow the evstat to be updated after the evack */ + udelay(20); + } + + DBFEXIT; + return IRQ_HANDLED; +} + +#ifdef CMD_IRQ +/*---------------------------------------------------------------- +* hfa384x_int_cmd +* +* Handles command completion event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void hfa384x_int_cmd(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + DBFENTER; + + // check to make sure it's the right command? + if (hw->cmddata) { + hw->cmddata->status = hfa384x_getreg(hw, HFA384x_STATUS); + hw->cmddata->resp0 = hfa384x_getreg(hw, HFA384x_RESP0); + hw->cmddata->resp1 = hfa384x_getreg(hw, HFA384x_RESP1); + hw->cmddata->resp2 = hfa384x_getreg(hw, HFA384x_RESP2); + } + hw->cmdflag = 1; + + printk(KERN_INFO "um. int_cmd\n"); + + wake_up_interruptible(&hw->cmdq); + + // XXXX perform a bap copy too? + + DBFEXIT; + return; +} +#endif + +/*---------------------------------------------------------------- +* hfa384x_int_dtim +* +* Handles the DTIM early warning event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_dtim(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = wlandev->priv; +#endif + DBFENTER; + prism2sta_ev_dtim(wlandev); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_infdrop +* +* Handles the InfDrop event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_infdrop(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = wlandev->priv; +#endif + DBFENTER; + prism2sta_ev_infdrop(wlandev); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_info +* +* Handles the Info event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_info(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 reg; + hfa384x_InfFrame_t inf; + int result; + DBFENTER; + /* Retrieve the FID */ + reg = hfa384x_getreg(hw, HFA384x_INFOFID); + + /* Retrieve the length */ + result = hfa384x_copy_from_bap( hw, + HFA384x_BAP_INT, reg, 0, &inf.framelen, sizeof(UINT16)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + reg, sizeof(inf), result); + goto failed; + } + inf.framelen = hfa384x2host_16(inf.framelen); + + /* Retrieve the rest */ + result = hfa384x_copy_from_bap( hw, + HFA384x_BAP_INT, reg, sizeof(UINT16), + &(inf.infotype), inf.framelen * sizeof(UINT16)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + reg, sizeof(inf), result); + goto failed; + } + + prism2sta_ev_info(wlandev, &inf); +failed: + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_txexc +* +* Handles the TxExc event. A Transmit Exception event indicates +* that the MAC's TX process was unsuccessful - so the packet did +* not get transmitted. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_txexc(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 status; + UINT16 fid; + int result = 0; + DBFENTER; + /* Collect the status and display */ + fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID); + result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + fid, sizeof(status), result); + goto failed; + } + status = hfa384x2host_16(status); + prism2sta_ev_txexc(wlandev, status); +failed: + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_tx +* +* Handles the Tx event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_tx(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 fid; + UINT16 status; + int result = 0; + DBFENTER; + fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID); + result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + fid, sizeof(status), result); + goto failed; + } + status = hfa384x2host_16(status); + prism2sta_ev_tx(wlandev, status); +failed: + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_int_rx +* +* Handles the Rx event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_rx(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 rxfid; + hfa384x_rx_frame_t rxdesc; + int result; + int hdrlen; + UINT16 fc; + p80211_rxmeta_t *rxmeta; + struct sk_buff *skb = NULL; + UINT8 *datap; + + DBFENTER; + + /* Get the FID */ + rxfid = hfa384x_getreg(hw, HFA384x_RXFID); + /* Get the descriptor (including headers) */ + result = hfa384x_copy_from_bap(hw, + HFA384x_BAP_INT, + rxfid, + 0, + &rxdesc, + sizeof(rxdesc)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n", + rxfid, + 0, + sizeof(rxdesc), + result); + goto done; + } + + /* Byte order convert once up front. */ + rxdesc.status = hfa384x2host_16(rxdesc.status); + rxdesc.time = hfa384x2host_32(rxdesc.time); + + /* drop errors and whatnot in promisc mode */ + if (( wlandev->netdev->flags & IFF_PROMISC ) && + (HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) || + HFA384x_RXSTATUS_ISUNDECR(rxdesc.status))) + goto done; + + /* Now handle frame based on port# */ + switch( HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) ) + { + case 0: + + fc = ieee2host16(rxdesc.frame_control); + + /* If exclude and we receive an unencrypted, drop it */ + if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) && + !WLAN_GET_FC_ISWEP(fc)) { + goto done; + } + + hdrlen = p80211_headerlen(fc); + + /* Allocate the buffer, note CRC (aka FCS). pballoc */ + /* assumes there needs to be space for one */ + skb = dev_alloc_skb(hfa384x2host_16(rxdesc.data_len) + hdrlen + WLAN_CRC_LEN + 2); /* a little extra */ + + if ( ! skb ) { + WLAN_LOG_ERROR("alloc_skb failed.\n"); + goto done; + } + + skb->dev = wlandev->netdev; + + /* theoretically align the IP header on a 32-bit word. */ + if ( hdrlen == WLAN_HDR_A4_LEN ) + skb_reserve(skb, 2); + + /* Copy the 802.11 hdr to the buffer */ + datap = skb_put(skb, WLAN_HDR_A3_LEN); + memcpy(datap, &rxdesc.frame_control, WLAN_HDR_A3_LEN); + + /* Snag the A4 address if present */ + if (hdrlen == WLAN_HDR_A4_LEN) { + datap = skb_put(skb, WLAN_ADDR_LEN); + memcpy(datap, &rxdesc.address4, WLAN_HDR_A3_LEN); + } + + /* we can convert the data_len as we passed the original on */ + rxdesc.data_len = hfa384x2host_16(rxdesc.data_len); + + /* Copy the payload data to the buffer */ + if ( rxdesc.data_len > 0 ) { + datap = skb_put(skb, rxdesc.data_len); + result = hfa384x_copy_from_bap(hw, + HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF, + datap, rxdesc.data_len); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n", + rxfid, + HFA384x_RX_DATA_OFF, + rxdesc.data_len, + result); + goto failed; + } + } + /* the prism2 cards don't return the FCS */ + datap = skb_put(skb, WLAN_CRC_LEN); + memset (datap, 0xff, WLAN_CRC_LEN); + skb_reset_mac_header(skb); + + /* Attach the rxmeta, set some stuff */ + p80211skb_rxmeta_attach(wlandev, skb); + rxmeta = P80211SKB_RXMETA(skb); + rxmeta->mactime = rxdesc.time; + rxmeta->rxrate = rxdesc.rate; + rxmeta->signal = rxdesc.signal - hw->dbmadjust; + rxmeta->noise = rxdesc.silence - hw->dbmadjust; + + prism2sta_ev_rx(wlandev, skb); + goto done; + case 7: + + if ( ! HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) ) { + hfa384x_int_rxmonitor( wlandev, rxfid, &rxdesc); + } else { + WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n"); + } + goto done; + + default: + + WLAN_LOG_WARNING("Received frame on unsupported port=%d\n", + HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) ); + goto done; + } + + failed: + dev_kfree_skb(skb); + + done: + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_rxmonitor +* +* Helper function for int_rx. Handles monitor frames. +* Note that this function allocates space for the FCS and sets it +* to 0xffffffff. The hfa384x doesn't give us the FCS value but the +* higher layers expect it. 0xffffffff is used as a flag to indicate +* the FCS is bogus. +* +* Arguments: +* wlandev wlan device structure +* rxfid received FID +* rxdesc rx descriptor read from card in int_rx +* +* Returns: +* nothing +* +* Side effects: +* Allocates an skb and passes it up via the PF_PACKET interface. +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, UINT16 rxfid, + hfa384x_rx_frame_t *rxdesc) +{ + hfa384x_t *hw = wlandev->priv; + UINT hdrlen = 0; + UINT datalen = 0; + UINT skblen = 0; + UINT truncated = 0; + UINT8 *datap; + UINT16 fc; + struct sk_buff *skb; + + DBFENTER; + /* Don't forget the status, time, and data_len fields are in host order */ + /* Figure out how big the frame is */ + fc = ieee2host16(rxdesc->frame_control); + hdrlen = p80211_headerlen(fc); + datalen = hfa384x2host_16(rxdesc->data_len); + + /* Allocate an ind message+framesize skb */ + skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) + + hdrlen + datalen + WLAN_CRC_LEN; + + /* sanity check the length */ + if ( skblen > + (sizeof(p80211msg_lnxind_wlansniffrm_t) + + WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) { + WLAN_LOG_DEBUG(1, "overlen frm: len=%d\n", + skblen - sizeof(p80211msg_lnxind_wlansniffrm_t)); + } + + if ( (skb = dev_alloc_skb(skblen)) == NULL ) { + WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen); + return; + } + + /* only prepend the prism header if in the right mode */ + if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr == 0)) { + p80211msg_lnxind_wlansniffrm_t *msg; + datap = skb_put(skb, sizeof(p80211msg_lnxind_wlansniffrm_t)); + msg = (p80211msg_lnxind_wlansniffrm_t*) datap; + + /* Initialize the message members */ + msg->msgcode = DIDmsg_lnxind_wlansniffrm; + msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t); + strcpy(msg->devname, wlandev->name); + + msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + msg->hosttime.status = 0; + msg->hosttime.len = 4; + msg->hosttime.data = jiffies; + + msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + msg->mactime.status = 0; + msg->mactime.len = 4; + msg->mactime.data = rxdesc->time * 1000; + + msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + msg->channel.status = 0; + msg->channel.len = 4; + msg->channel.data = hw->sniff_channel; + + msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + msg->rssi.status = P80211ENUM_msgitem_status_no_value; + msg->rssi.len = 4; + msg->rssi.data = 0; + + msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq; + msg->sq.status = P80211ENUM_msgitem_status_no_value; + msg->sq.len = 4; + msg->sq.data = 0; + + msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + msg->signal.status = 0; + msg->signal.len = 4; + msg->signal.data = rxdesc->signal; + + msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + msg->noise.status = 0; + msg->noise.len = 4; + msg->noise.data = rxdesc->silence; + + msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + msg->rate.status = 0; + msg->rate.len = 4; + msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */ + + msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + msg->istx.status = 0; + msg->istx.len = 4; + msg->istx.data = P80211ENUM_truth_false; + + msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + msg->frmlen.status = 0; + msg->frmlen.len = 4; + msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN; + } else if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr != 0)) { + p80211_caphdr_t *caphdr; + /* The NEW header format! */ + datap = skb_put(skb, sizeof(p80211_caphdr_t)); + caphdr = (p80211_caphdr_t*) datap; + + caphdr->version = htonl(P80211CAPTURE_VERSION); + caphdr->length = htonl(sizeof(p80211_caphdr_t)); + caphdr->mactime = __cpu_to_be64(rxdesc->time); + caphdr->hosttime = __cpu_to_be64(jiffies); + caphdr->phytype = htonl(4); /* dss_dot11_b */ + caphdr->channel = htonl(hw->sniff_channel); + caphdr->datarate = htonl(rxdesc->rate); + caphdr->antenna = htonl(0); /* unknown */ + caphdr->priority = htonl(0); /* unknown */ + caphdr->ssi_type = htonl(3); /* rssi_raw */ + caphdr->ssi_signal = htonl(rxdesc->signal); + caphdr->ssi_noise = htonl(rxdesc->silence); + caphdr->preamble = htonl(0); /* unknown */ + caphdr->encoding = htonl(1); /* cck */ + } + /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */ + datap = skb_put(skb, hdrlen); + memcpy( datap, &(rxdesc->frame_control), hdrlen); + + /* If any, copy the data from the card to the skb */ + if ( datalen > 0 ) + { + /* Truncate the packet if the user wants us to */ + UINT dataread = datalen; + if(hw->sniff_truncate > 0 && dataread > hw->sniff_truncate) { + dataread = hw->sniff_truncate; + truncated = 1; + } + + datap = skb_put(skb, dataread); + hfa384x_copy_from_bap(hw, + HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF, + datap, dataread); + + /* check for unencrypted stuff if WEP bit set. */ + if (*(datap - hdrlen + 1) & 0x40) // wep set + if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa)) + *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header! + } + + if (!truncated && hw->sniff_fcs) { + /* Set the FCS */ + datap = skb_put(skb, WLAN_CRC_LEN); + memset( datap, 0xff, WLAN_CRC_LEN); + } + + /* pass it back up */ + prism2sta_ev_rx(wlandev, skb); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_int_alloc +* +* Handles the Alloc event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_alloc(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 fid; + INT16 result; + + DBFENTER; + + /* Handle the reclaimed FID */ + /* collect the FID and push it onto the stack */ + fid = hfa384x_getreg(hw, HFA384x_ALLOCFID); + + if ( fid != hw->infofid ) { /* It's a transmit fid */ + WLAN_LOG_DEBUG(5, "int_alloc(%#x)\n", fid); + result = txfid_queue_add(hw, fid); + if (result != -1) { + prism2sta_ev_alloc(wlandev); + WLAN_LOG_DEBUG(5, "q_add.\n"); + } else { + WLAN_LOG_DEBUG(5, "q_full.\n"); + } + } else { + /* unlock the info fid */ + up(&hw->infofid_sem); + } + + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_handover +* +* Sends a handover notification to the MAC. +* +* Arguments: +* hw device structure +* addr address of station that's left +* +* Returns: +* zero success. +* -ERESTARTSYS received signal while waiting for semaphore. +* -EIO failed to write to bap, or failed in cmd. +* +* Side effects: +* +* Call context: +* process thread, NOTE: this call may block on a semaphore! +----------------------------------------------------------------*/ +int hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr) +{ + int result = 0; + hfa384x_HandoverAddr_t rec; + UINT len; + DBFENTER; + + /* Acquire the infofid */ + if ( down_interruptible(&hw->infofid_sem) ) { + result = -ERESTARTSYS; + goto failed; + } + + /* Set up the record */ + len = sizeof(hfa384x_HandoverAddr_t); + rec.framelen = host2hfa384x_16(len/2 - 1); + rec.infotype = host2hfa384x_16(HFA384x_IT_HANDOVERADDR); + memcpy(rec.handover_addr, addr, sizeof(rec.handover_addr)); + + /* Issue the command */ + result = hfa384x_cmd_notify(hw, 1, hw->infofid, &rec, len); + + if ( result != 0 ) { + WLAN_LOG_DEBUG(1,"cmd_notify(%04x) failed, result=%d", + hw->infofid, result); + result = -EIO; + goto failed; + } + +failed: + DBFEXIT; + return result; +} + +void hfa384x_tx_timeout(wlandevice_t *wlandev) +{ + DBFENTER; + + WLAN_LOG_WARNING("Implement me.\n"); + + DBFEXIT; +} + +/* Handles all "rx" BAP operations */ +static void hfa384x_bap_tasklet(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t *) data; + wlandevice_t *wlandev = hw->wlandev; + int counter = prism2_irq_evread_max; + int reg; + + DBFENTER; + + while (counter-- > 0) { + /* Get interrupt register */ + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + + if ((reg == 0xffff) || + !(reg & HFA384x_INT_BAP_OP)) { + break; + } + + if ( HFA384x_EVSTAT_ISINFO(reg) ){ + hfa384x_int_info(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_INFO_SET(1), + HFA384x_EVACK); + } + if ( HFA384x_EVSTAT_ISTXEXC(reg) ){ + hfa384x_int_txexc(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_TXEXC_SET(1), + HFA384x_EVACK); + } + if ( HFA384x_EVSTAT_ISTX(reg) ){ + hfa384x_int_tx(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_TX_SET(1), + HFA384x_EVACK); + } + if ( HFA384x_EVSTAT_ISRX(reg) ){ + hfa384x_int_rx(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), + HFA384x_EVACK); + } + } + + /* re-enable interrupts */ + hfa384x_events_all(hw); + + DBFEXIT; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/Makefile +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_PRISM2_USB) += prism2_usb.o + +EXTRA_CFLAGS += -I$(src)/../p80211 -I$(src) --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/prism2/hfa384x.h +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/prism2/hfa384x.h @@ -0,0 +1,3067 @@ +/* src/prism2/include/prism2/hfa384x.h +* +* Defines the constants and data structures for the hfa384x +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* [Implementation and usage notes] +* +* [References] +* CW10 Programmer's Manual v1.5 +* IEEE 802.11 D10.0 +* +* -------------------------------------------------------------------- +*/ + +#ifndef _HFA384x_H +#define _HFA384x_H + +/*=============================================================*/ +#define HFA384x_FIRMWARE_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) + +#define HFA384x_LEVEL_TO_dBm(v) (0x100 + (v) * 100 / 255 - 100) + +/*------ Constants --------------------------------------------*/ +/*--- Mins & Maxs -----------------------------------*/ +#define HFA384x_CMD_ALLOC_LEN_MIN ((UINT16)4) +#define HFA384x_CMD_ALLOC_LEN_MAX ((UINT16)2400) +#define HFA384x_BAP_DATALEN_MAX ((UINT16)4096) +#define HFA384x_BAP_OFFSET_MAX ((UINT16)4096) +#define HFA384x_PORTID_MAX ((UINT16)7) +#define HFA384x_NUMPORTS_MAX ((UINT16)(HFA384x_PORTID_MAX+1)) +#define HFA384x_PDR_LEN_MAX ((UINT16)512) /* in bytes, from EK */ +#define HFA384x_PDA_RECS_MAX ((UINT16)200) /* a guess */ +#define HFA384x_PDA_LEN_MAX ((UINT16)1024) /* in bytes, from EK */ +#define HFA384x_SCANRESULT_MAX ((UINT16)31) +#define HFA384x_HSCANRESULT_MAX ((UINT16)31) +#define HFA384x_CHINFORESULT_MAX ((UINT16)16) +#define HFA384x_DRVR_FIDSTACKLEN_MAX (10) +#define HFA384x_DRVR_TXBUF_MAX (sizeof(hfa384x_tx_frame_t) + \ + WLAN_DATA_MAXLEN - \ + WLAN_WEP_IV_LEN - \ + WLAN_WEP_ICV_LEN + 2) +#define HFA384x_DRVR_MAGIC (0x4a2d) +#define HFA384x_INFODATA_MAXLEN (sizeof(hfa384x_infodata_t)) +#define HFA384x_INFOFRM_MAXLEN (sizeof(hfa384x_InfFrame_t)) +#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */ +#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN +#define HFA384x_USB_RWMEM_MAXLEN 2048 + +/*--- Support Constants -----------------------------*/ +#define HFA384x_BAP_PROC ((UINT16)0) +#define HFA384x_BAP_INT ((UINT16)1) +#define HFA384x_PORTTYPE_IBSS ((UINT16)0) +#define HFA384x_PORTTYPE_BSS ((UINT16)1) +#define HFA384x_PORTTYPE_WDS ((UINT16)2) +#define HFA384x_PORTTYPE_PSUEDOIBSS ((UINT16)3) +#define HFA384x_PORTTYPE_HOSTAP ((UINT16)6) +#define HFA384x_WEPFLAGS_PRIVINVOKED ((UINT16)BIT0) +#define HFA384x_WEPFLAGS_EXCLUDE ((UINT16)BIT1) +#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((UINT16)BIT4) +#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((UINT16)BIT7) +#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((UINT16)BIT11) +#define HFA384x_WEPFLAGS_IV_INTERVAL1 ((UINT16)0) +#define HFA384x_WEPFLAGS_IV_INTERVAL10 ((UINT16)BIT5) +#define HFA384x_WEPFLAGS_IV_INTERVAL50 ((UINT16)BIT6) +#define HFA384x_WEPFLAGS_IV_INTERVAL100 ((UINT16)(BIT5 | BIT6)) +#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((UINT16)BIT8) +#define HFA384x_WEPFLAGS_HOST_MIC ((UINT16)BIT9) +#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((UINT16)1) +#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((UINT16)2) +#define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((UINT16)3) +#define HFA384x_PORTSTATUS_DISABLED ((UINT16)1) +#define HFA384x_PORTSTATUS_INITSRCH ((UINT16)2) +#define HFA384x_PORTSTATUS_CONN_IBSS ((UINT16)3) +#define HFA384x_PORTSTATUS_CONN_ESS ((UINT16)4) +#define HFA384x_PORTSTATUS_OOR_ESS ((UINT16)5) +#define HFA384x_PORTSTATUS_CONN_WDS ((UINT16)6) +#define HFA384x_PORTSTATUS_HOSTAP ((UINT16)8) +#define HFA384x_RATEBIT_1 ((UINT16)1) +#define HFA384x_RATEBIT_2 ((UINT16)2) +#define HFA384x_RATEBIT_5dot5 ((UINT16)4) +#define HFA384x_RATEBIT_11 ((UINT16)8) + +/*--- Just some symbolic names for legibility -------*/ +#define HFA384x_TXCMD_NORECL ((UINT16)0) +#define HFA384x_TXCMD_RECL ((UINT16)1) + +/*--- MAC Internal memory constants and macros ------*/ +/* masks and macros used to manipulate MAC internal memory addresses. */ +/* MAC internal memory addresses are 23 bit quantities. The MAC uses + * a paged address space where the upper 16 bits are the page number + * and the lower 7 bits are the offset. There are various Host API + * elements that require two 16-bit quantities to specify a MAC + * internal memory address. Unfortunately, some of the API's use a + * page/offset format where the offset value is JUST the lower seven + * bits and the page is the remaining 16 bits. Some of the API's + * assume that the 23 bit address has been split at the 16th bit. We + * refer to these two formats as AUX format and CMD format. The + * macros below help handle some of this. + */ + +/* Handy constant */ +#define HFA384x_ADDR_AUX_OFF_MAX ((UINT16)0x007f) + +/* Mask bits for discarding unwanted pieces in a flat address */ +#define HFA384x_ADDR_FLAT_AUX_PAGE_MASK (0x007fff80) +#define HFA384x_ADDR_FLAT_AUX_OFF_MASK (0x0000007f) +#define HFA384x_ADDR_FLAT_CMD_PAGE_MASK (0xffff0000) +#define HFA384x_ADDR_FLAT_CMD_OFF_MASK (0x0000ffff) + +/* Mask bits for discarding unwanted pieces in AUX format 16-bit address parts */ +#define HFA384x_ADDR_AUX_PAGE_MASK (0xffff) +#define HFA384x_ADDR_AUX_OFF_MASK (0x007f) + +/* Mask bits for discarding unwanted pieces in CMD format 16-bit address parts */ +#define HFA384x_ADDR_CMD_PAGE_MASK (0x007f) +#define HFA384x_ADDR_CMD_OFF_MASK (0xffff) + +/* Make a 32-bit flat address from AUX format 16-bit page and offset */ +#define HFA384x_ADDR_AUX_MKFLAT(p,o) \ + (((UINT32)(((UINT16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \ + ((UINT32)(((UINT16)(o))&HFA384x_ADDR_AUX_OFF_MASK)) + +/* Make a 32-bit flat address from CMD format 16-bit page and offset */ +#define HFA384x_ADDR_CMD_MKFLAT(p,o) \ + (((UINT32)(((UINT16)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \ + ((UINT32)(((UINT16)(o))&HFA384x_ADDR_CMD_OFF_MASK)) + +/* Make AUX format offset and page from a 32-bit flat address */ +#define HFA384x_ADDR_AUX_MKPAGE(f) \ + ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7)) +#define HFA384x_ADDR_AUX_MKOFF(f) \ + ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_OFF_MASK)) + +/* Make CMD format offset and page from a 32-bit flat address */ +#define HFA384x_ADDR_CMD_MKPAGE(f) \ + ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) +#define HFA384x_ADDR_CMD_MKOFF(f) \ + ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK)) + +/*--- Aux register masks/tests ----------------------*/ +/* Some of the upper bits of the AUX offset register are used to */ +/* select address space. */ +#define HFA384x_AUX_CTL_EXTDS (0x00) +#define HFA384x_AUX_CTL_NV (0x01) +#define HFA384x_AUX_CTL_PHY (0x02) +#define HFA384x_AUX_CTL_ICSRAM (0x03) + +/* Make AUX register offset and page values from a flat address */ +#define HFA384x_AUX_MKOFF(f, c) \ + (HFA384x_ADDR_AUX_MKOFF(f) | (((UINT16)(c))<<12)) +#define HFA384x_AUX_MKPAGE(f) HFA384x_ADDR_AUX_MKPAGE(f) + + +/*--- Controller Memory addresses -------------------*/ +#define HFA3842_PDA_BASE (0x007f0000UL) +#define HFA3841_PDA_BASE (0x003f0000UL) +#define HFA3841_PDA_BOGUS_BASE (0x00390000UL) + +/*--- Driver Download states -----------------------*/ +#define HFA384x_DLSTATE_DISABLED 0 +#define HFA384x_DLSTATE_RAMENABLED 1 +#define HFA384x_DLSTATE_FLASHENABLED 2 +#define HFA384x_DLSTATE_FLASHWRITTEN 3 +#define HFA384x_DLSTATE_FLASHWRITEPENDING 4 +#define HFA384x_DLSTATE_GENESIS 5 + +/*--- Register I/O offsets --------------------------*/ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + +#define HFA384x_CMD_OFF (0x00) +#define HFA384x_PARAM0_OFF (0x02) +#define HFA384x_PARAM1_OFF (0x04) +#define HFA384x_PARAM2_OFF (0x06) +#define HFA384x_STATUS_OFF (0x08) +#define HFA384x_RESP0_OFF (0x0A) +#define HFA384x_RESP1_OFF (0x0C) +#define HFA384x_RESP2_OFF (0x0E) +#define HFA384x_INFOFID_OFF (0x10) +#define HFA384x_RXFID_OFF (0x20) +#define HFA384x_ALLOCFID_OFF (0x22) +#define HFA384x_TXCOMPLFID_OFF (0x24) +#define HFA384x_SELECT0_OFF (0x18) +#define HFA384x_OFFSET0_OFF (0x1C) +#define HFA384x_DATA0_OFF (0x36) +#define HFA384x_SELECT1_OFF (0x1A) +#define HFA384x_OFFSET1_OFF (0x1E) +#define HFA384x_DATA1_OFF (0x38) +#define HFA384x_EVSTAT_OFF (0x30) +#define HFA384x_INTEN_OFF (0x32) +#define HFA384x_EVACK_OFF (0x34) +#define HFA384x_CONTROL_OFF (0x14) +#define HFA384x_SWSUPPORT0_OFF (0x28) +#define HFA384x_SWSUPPORT1_OFF (0x2A) +#define HFA384x_SWSUPPORT2_OFF (0x2C) +#define HFA384x_AUXPAGE_OFF (0x3A) +#define HFA384x_AUXOFFSET_OFF (0x3C) +#define HFA384x_AUXDATA_OFF (0x3E) + +#elif (WLAN_HOSTIF == WLAN_PCI || WLAN_HOSTIF == WLAN_USB) + +#define HFA384x_CMD_OFF (0x00) +#define HFA384x_PARAM0_OFF (0x04) +#define HFA384x_PARAM1_OFF (0x08) +#define HFA384x_PARAM2_OFF (0x0c) +#define HFA384x_STATUS_OFF (0x10) +#define HFA384x_RESP0_OFF (0x14) +#define HFA384x_RESP1_OFF (0x18) +#define HFA384x_RESP2_OFF (0x1c) +#define HFA384x_INFOFID_OFF (0x20) +#define HFA384x_RXFID_OFF (0x40) +#define HFA384x_ALLOCFID_OFF (0x44) +#define HFA384x_TXCOMPLFID_OFF (0x48) +#define HFA384x_SELECT0_OFF (0x30) +#define HFA384x_OFFSET0_OFF (0x38) +#define HFA384x_DATA0_OFF (0x6c) +#define HFA384x_SELECT1_OFF (0x34) +#define HFA384x_OFFSET1_OFF (0x3c) +#define HFA384x_DATA1_OFF (0x70) +#define HFA384x_EVSTAT_OFF (0x60) +#define HFA384x_INTEN_OFF (0x64) +#define HFA384x_EVACK_OFF (0x68) +#define HFA384x_CONTROL_OFF (0x28) +#define HFA384x_SWSUPPORT0_OFF (0x50) +#define HFA384x_SWSUPPORT1_OFF (0x54) +#define HFA384x_SWSUPPORT2_OFF (0x58) +#define HFA384x_AUXPAGE_OFF (0x74) +#define HFA384x_AUXOFFSET_OFF (0x78) +#define HFA384x_AUXDATA_OFF (0x7c) +#define HFA384x_PCICOR_OFF (0x4c) +#define HFA384x_PCIHCR_OFF (0x5c) +#define HFA384x_PCI_M0_ADDRH_OFF (0x80) +#define HFA384x_PCI_M0_ADDRL_OFF (0x84) +#define HFA384x_PCI_M0_LEN_OFF (0x88) +#define HFA384x_PCI_M0_CTL_OFF (0x8c) +#define HFA384x_PCI_STATUS_OFF (0x98) +#define HFA384x_PCI_M1_ADDRH_OFF (0xa0) +#define HFA384x_PCI_M1_ADDRL_OFF (0xa4) +#define HFA384x_PCI_M1_LEN_OFF (0xa8) +#define HFA384x_PCI_M1_CTL_OFF (0xac) + +#endif + +/*--- Register Field Masks --------------------------*/ +#define HFA384x_CMD_BUSY ((UINT16)BIT15) +#define HFA384x_CMD_AINFO ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) +#define HFA384x_CMD_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) +#define HFA384x_CMD_RECL ((UINT16)BIT8) +#define HFA384x_CMD_WRITE ((UINT16)BIT8) +#define HFA384x_CMD_PROGMODE ((UINT16)(BIT9 | BIT8)) +#define HFA384x_CMD_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) + +#define HFA384x_STATUS_RESULT ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) +#define HFA384x_STATUS_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) + +#define HFA384x_OFFSET_BUSY ((UINT16)BIT15) +#define HFA384x_OFFSET_ERR ((UINT16)BIT14) +#define HFA384x_OFFSET_DATAOFF ((UINT16)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1)) + +#define HFA384x_EVSTAT_TICK ((UINT16)BIT15) +#define HFA384x_EVSTAT_WTERR ((UINT16)BIT14) +#define HFA384x_EVSTAT_INFDROP ((UINT16)BIT13) +#define HFA384x_EVSTAT_INFO ((UINT16)BIT7) +#define HFA384x_EVSTAT_DTIM ((UINT16)BIT5) +#define HFA384x_EVSTAT_CMD ((UINT16)BIT4) +#define HFA384x_EVSTAT_ALLOC ((UINT16)BIT3) +#define HFA384x_EVSTAT_TXEXC ((UINT16)BIT2) +#define HFA384x_EVSTAT_TX ((UINT16)BIT1) +#define HFA384x_EVSTAT_RX ((UINT16)BIT0) + +#define HFA384x_INT_BAP_OP (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC) + +#define HFA384x_INT_NORMAL (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC|HFA384x_EVSTAT_INFDROP|HFA384x_EVSTAT_ALLOC|HFA384x_EVSTAT_DTIM) + +#define HFA384x_INTEN_TICK ((UINT16)BIT15) +#define HFA384x_INTEN_WTERR ((UINT16)BIT14) +#define HFA384x_INTEN_INFDROP ((UINT16)BIT13) +#define HFA384x_INTEN_INFO ((UINT16)BIT7) +#define HFA384x_INTEN_DTIM ((UINT16)BIT5) +#define HFA384x_INTEN_CMD ((UINT16)BIT4) +#define HFA384x_INTEN_ALLOC ((UINT16)BIT3) +#define HFA384x_INTEN_TXEXC ((UINT16)BIT2) +#define HFA384x_INTEN_TX ((UINT16)BIT1) +#define HFA384x_INTEN_RX ((UINT16)BIT0) + +#define HFA384x_EVACK_TICK ((UINT16)BIT15) +#define HFA384x_EVACK_WTERR ((UINT16)BIT14) +#define HFA384x_EVACK_INFDROP ((UINT16)BIT13) +#define HFA384x_EVACK_INFO ((UINT16)BIT7) +#define HFA384x_EVACK_DTIM ((UINT16)BIT5) +#define HFA384x_EVACK_CMD ((UINT16)BIT4) +#define HFA384x_EVACK_ALLOC ((UINT16)BIT3) +#define HFA384x_EVACK_TXEXC ((UINT16)BIT2) +#define HFA384x_EVACK_TX ((UINT16)BIT1) +#define HFA384x_EVACK_RX ((UINT16)BIT0) + +#define HFA384x_CONTROL_AUXEN ((UINT16)(BIT15 | BIT14)) + + +/*--- Command Code Constants --------------------------*/ +/*--- Controller Commands --------------------------*/ +#define HFA384x_CMDCODE_INIT ((UINT16)0x00) +#define HFA384x_CMDCODE_ENABLE ((UINT16)0x01) +#define HFA384x_CMDCODE_DISABLE ((UINT16)0x02) +#define HFA384x_CMDCODE_DIAG ((UINT16)0x03) + +/*--- Buffer Mgmt Commands --------------------------*/ +#define HFA384x_CMDCODE_ALLOC ((UINT16)0x0A) +#define HFA384x_CMDCODE_TX ((UINT16)0x0B) +#define HFA384x_CMDCODE_CLRPRST ((UINT16)0x12) + +/*--- Regulate Commands --------------------------*/ +#define HFA384x_CMDCODE_NOTIFY ((UINT16)0x10) +#define HFA384x_CMDCODE_INQ ((UINT16)0x11) + +/*--- Configure Commands --------------------------*/ +#define HFA384x_CMDCODE_ACCESS ((UINT16)0x21) +#define HFA384x_CMDCODE_DOWNLD ((UINT16)0x22) + +/*--- Debugging Commands -----------------------------*/ +#define HFA384x_CMDCODE_MONITOR ((UINT16)(0x38)) +#define HFA384x_MONITOR_ENABLE ((UINT16)(0x0b)) +#define HFA384x_MONITOR_DISABLE ((UINT16)(0x0f)) + +/*--- Result Codes --------------------------*/ +#define HFA384x_SUCCESS ((UINT16)(0x00)) +#define HFA384x_CARD_FAIL ((UINT16)(0x01)) +#define HFA384x_NO_BUFF ((UINT16)(0x05)) +#define HFA384x_CMD_ERR ((UINT16)(0x7F)) + +/*--- Programming Modes -------------------------- + MODE 0: Disable programming + MODE 1: Enable volatile memory programming + MODE 2: Enable non-volatile memory programming + MODE 3: Program non-volatile memory section +--------------------------------------------------*/ +#define HFA384x_PROGMODE_DISABLE ((UINT16)0x00) +#define HFA384x_PROGMODE_RAM ((UINT16)0x01) +#define HFA384x_PROGMODE_NV ((UINT16)0x02) +#define HFA384x_PROGMODE_NVWRITE ((UINT16)0x03) + +/*--- AUX register enable --------------------------*/ +#define HFA384x_AUXPW0 ((UINT16)0xfe01) +#define HFA384x_AUXPW1 ((UINT16)0xdc23) +#define HFA384x_AUXPW2 ((UINT16)0xba45) + +#define HFA384x_CONTROL_AUX_ISDISABLED ((UINT16)0x0000) +#define HFA384x_CONTROL_AUX_ISENABLED ((UINT16)0xc000) +#define HFA384x_CONTROL_AUX_DOENABLE ((UINT16)0x8000) +#define HFA384x_CONTROL_AUX_DODISABLE ((UINT16)0x4000) + +/*--- Record ID Constants --------------------------*/ +/*-------------------------------------------------------------------- +Configuration RIDs: Network Parameters, Static Configuration Entities +--------------------------------------------------------------------*/ +#define HFA384x_RID_CNFPORTTYPE ((UINT16)0xFC00) +#define HFA384x_RID_CNFOWNMACADDR ((UINT16)0xFC01) +#define HFA384x_RID_CNFDESIREDSSID ((UINT16)0xFC02) +#define HFA384x_RID_CNFOWNCHANNEL ((UINT16)0xFC03) +#define HFA384x_RID_CNFOWNSSID ((UINT16)0xFC04) +#define HFA384x_RID_CNFOWNATIMWIN ((UINT16)0xFC05) +#define HFA384x_RID_CNFSYSSCALE ((UINT16)0xFC06) +#define HFA384x_RID_CNFMAXDATALEN ((UINT16)0xFC07) +#define HFA384x_RID_CNFWDSADDR ((UINT16)0xFC08) +#define HFA384x_RID_CNFPMENABLED ((UINT16)0xFC09) +#define HFA384x_RID_CNFPMEPS ((UINT16)0xFC0A) +#define HFA384x_RID_CNFMULTICASTRX ((UINT16)0xFC0B) +#define HFA384x_RID_CNFMAXSLEEPDUR ((UINT16)0xFC0C) +#define HFA384x_RID_CNFPMHOLDDUR ((UINT16)0xFC0D) +#define HFA384x_RID_CNFOWNNAME ((UINT16)0xFC0E) +#define HFA384x_RID_CNFOWNDTIMPER ((UINT16)0xFC10) +#define HFA384x_RID_CNFWDSADDR1 ((UINT16)0xFC11) +#define HFA384x_RID_CNFWDSADDR2 ((UINT16)0xFC12) +#define HFA384x_RID_CNFWDSADDR3 ((UINT16)0xFC13) +#define HFA384x_RID_CNFWDSADDR4 ((UINT16)0xFC14) +#define HFA384x_RID_CNFWDSADDR5 ((UINT16)0xFC15) +#define HFA384x_RID_CNFWDSADDR6 ((UINT16)0xFC16) +#define HFA384x_RID_CNFMCASTPMBUFF ((UINT16)0xFC17) + +/*-------------------------------------------------------------------- +Configuration RID lengths: Network Params, Static Config Entities + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +/* TODO: fill in the rest of these */ +#define HFA384x_RID_CNFPORTTYPE_LEN ((UINT16)2) +#define HFA384x_RID_CNFOWNMACADDR_LEN ((UINT16)6) +#define HFA384x_RID_CNFDESIREDSSID_LEN ((UINT16)34) +#define HFA384x_RID_CNFOWNCHANNEL_LEN ((UINT16)2) +#define HFA384x_RID_CNFOWNSSID_LEN ((UINT16)34) +#define HFA384x_RID_CNFOWNATIMWIN_LEN ((UINT16)2) +#define HFA384x_RID_CNFSYSSCALE_LEN ((UINT16)0) +#define HFA384x_RID_CNFMAXDATALEN_LEN ((UINT16)0) +#define HFA384x_RID_CNFWDSADDR_LEN ((UINT16)6) +#define HFA384x_RID_CNFPMENABLED_LEN ((UINT16)0) +#define HFA384x_RID_CNFPMEPS_LEN ((UINT16)0) +#define HFA384x_RID_CNFMULTICASTRX_LEN ((UINT16)0) +#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0) +#define HFA384x_RID_CNFPMHOLDDUR_LEN ((UINT16)0) +#define HFA384x_RID_CNFOWNNAME_LEN ((UINT16)34) +#define HFA384x_RID_CNFOWNDTIMPER_LEN ((UINT16)0) +#define HFA384x_RID_CNFWDSADDR1_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR2_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR3_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR4_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR5_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR6_LEN ((UINT16)6) +#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((UINT16)0) +#define HFA384x_RID_CNFAUTHENTICATION_LEN ((UINT16)sizeof(UINT16)) +#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0) + +/*-------------------------------------------------------------------- +Configuration RIDs: Network Parameters, Dynamic Configuration Entities +--------------------------------------------------------------------*/ +#define HFA384x_RID_GROUPADDR ((UINT16)0xFC80) +#define HFA384x_RID_CREATEIBSS ((UINT16)0xFC81) +#define HFA384x_RID_FRAGTHRESH ((UINT16)0xFC82) +#define HFA384x_RID_RTSTHRESH ((UINT16)0xFC83) +#define HFA384x_RID_TXRATECNTL ((UINT16)0xFC84) +#define HFA384x_RID_PROMISCMODE ((UINT16)0xFC85) +#define HFA384x_RID_FRAGTHRESH0 ((UINT16)0xFC90) +#define HFA384x_RID_FRAGTHRESH1 ((UINT16)0xFC91) +#define HFA384x_RID_FRAGTHRESH2 ((UINT16)0xFC92) +#define HFA384x_RID_FRAGTHRESH3 ((UINT16)0xFC93) +#define HFA384x_RID_FRAGTHRESH4 ((UINT16)0xFC94) +#define HFA384x_RID_FRAGTHRESH5 ((UINT16)0xFC95) +#define HFA384x_RID_FRAGTHRESH6 ((UINT16)0xFC96) +#define HFA384x_RID_RTSTHRESH0 ((UINT16)0xFC97) +#define HFA384x_RID_RTSTHRESH1 ((UINT16)0xFC98) +#define HFA384x_RID_RTSTHRESH2 ((UINT16)0xFC99) +#define HFA384x_RID_RTSTHRESH3 ((UINT16)0xFC9A) +#define HFA384x_RID_RTSTHRESH4 ((UINT16)0xFC9B) +#define HFA384x_RID_RTSTHRESH5 ((UINT16)0xFC9C) +#define HFA384x_RID_RTSTHRESH6 ((UINT16)0xFC9D) +#define HFA384x_RID_TXRATECNTL0 ((UINT16)0xFC9E) +#define HFA384x_RID_TXRATECNTL1 ((UINT16)0xFC9F) +#define HFA384x_RID_TXRATECNTL2 ((UINT16)0xFCA0) +#define HFA384x_RID_TXRATECNTL3 ((UINT16)0xFCA1) +#define HFA384x_RID_TXRATECNTL4 ((UINT16)0xFCA2) +#define HFA384x_RID_TXRATECNTL5 ((UINT16)0xFCA3) +#define HFA384x_RID_TXRATECNTL6 ((UINT16)0xFCA4) + +/*-------------------------------------------------------------------- +Configuration RID Lengths: Network Param, Dynamic Config Entities + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +/* TODO: fill in the rest of these */ +#define HFA384x_RID_GROUPADDR_LEN ((UINT16)16 * WLAN_ADDR_LEN) +#define HFA384x_RID_CREATEIBSS_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL_LEN ((UINT16)4) +#define HFA384x_RID_PROMISCMODE_LEN ((UINT16)2) +#define HFA384x_RID_FRAGTHRESH0_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH1_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH2_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH3_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH4_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH5_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH6_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH0_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH1_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH2_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH3_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH4_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH5_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH6_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL0_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL1_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL2_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL3_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL4_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL5_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL6_LEN ((UINT16)0) + +/*-------------------------------------------------------------------- +Configuration RIDs: Behavior Parameters +--------------------------------------------------------------------*/ +#define HFA384x_RID_ITICKTIME ((UINT16)0xFCE0) + +/*-------------------------------------------------------------------- +Configuration RID Lengths: Behavior Parameters + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_ITICKTIME_LEN ((UINT16)2) + +/*---------------------------------------------------------------------- +Information RIDs: NIC Information +--------------------------------------------------------------------*/ +#define HFA384x_RID_MAXLOADTIME ((UINT16)0xFD00) +#define HFA384x_RID_DOWNLOADBUFFER ((UINT16)0xFD01) +#define HFA384x_RID_PRIIDENTITY ((UINT16)0xFD02) +#define HFA384x_RID_PRISUPRANGE ((UINT16)0xFD03) +#define HFA384x_RID_PRI_CFIACTRANGES ((UINT16)0xFD04) +#define HFA384x_RID_NICSERIALNUMBER ((UINT16)0xFD0A) +#define HFA384x_RID_NICIDENTITY ((UINT16)0xFD0B) +#define HFA384x_RID_MFISUPRANGE ((UINT16)0xFD0C) +#define HFA384x_RID_CFISUPRANGE ((UINT16)0xFD0D) +#define HFA384x_RID_CHANNELLIST ((UINT16)0xFD10) +#define HFA384x_RID_REGULATORYDOMAINS ((UINT16)0xFD11) +#define HFA384x_RID_TEMPTYPE ((UINT16)0xFD12) +#define HFA384x_RID_CIS ((UINT16)0xFD13) +#define HFA384x_RID_STAIDENTITY ((UINT16)0xFD20) +#define HFA384x_RID_STASUPRANGE ((UINT16)0xFD21) +#define HFA384x_RID_STA_MFIACTRANGES ((UINT16)0xFD22) +#define HFA384x_RID_STA_CFIACTRANGES ((UINT16)0xFD23) +#define HFA384x_RID_BUILDSEQ ((UINT16)0xFFFE) +#define HFA384x_RID_FWID ((UINT16)0xFFFF) + +/*---------------------------------------------------------------------- +Information RID Lengths: NIC Information + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_MAXLOADTIME_LEN ((UINT16)0) +#define HFA384x_RID_DOWNLOADBUFFER_LEN ((UINT16)sizeof(hfa384x_downloadbuffer_t)) +#define HFA384x_RID_PRIIDENTITY_LEN ((UINT16)8) +#define HFA384x_RID_PRISUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_CFIACTRANGES_LEN ((UINT16)10) +#define HFA384x_RID_NICSERIALNUMBER_LEN ((UINT16)12) +#define HFA384x_RID_NICIDENTITY_LEN ((UINT16)8) +#define HFA384x_RID_MFISUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_CFISUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_CHANNELLIST_LEN ((UINT16)0) +#define HFA384x_RID_REGULATORYDOMAINS_LEN ((UINT16)12) +#define HFA384x_RID_TEMPTYPE_LEN ((UINT16)0) +#define HFA384x_RID_CIS_LEN ((UINT16)480) +#define HFA384x_RID_STAIDENTITY_LEN ((UINT16)8) +#define HFA384x_RID_STASUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_MFIACTRANGES_LEN ((UINT16)10) +#define HFA384x_RID_CFIACTRANGES2_LEN ((UINT16)10) +#define HFA384x_RID_BUILDSEQ_LEN ((UINT16)sizeof(hfa384x_BuildSeq_t)) +#define HFA384x_RID_FWID_LEN ((UINT16)sizeof(hfa384x_FWID_t)) + +/*-------------------------------------------------------------------- +Information RIDs: MAC Information +--------------------------------------------------------------------*/ +#define HFA384x_RID_PORTSTATUS ((UINT16)0xFD40) +#define HFA384x_RID_CURRENTSSID ((UINT16)0xFD41) +#define HFA384x_RID_CURRENTBSSID ((UINT16)0xFD42) +#define HFA384x_RID_COMMSQUALITY ((UINT16)0xFD43) +#define HFA384x_RID_CURRENTTXRATE ((UINT16)0xFD44) +#define HFA384x_RID_CURRENTBCNINT ((UINT16)0xFD45) +#define HFA384x_RID_CURRENTSCALETHRESH ((UINT16)0xFD46) +#define HFA384x_RID_PROTOCOLRSPTIME ((UINT16)0xFD47) +#define HFA384x_RID_SHORTRETRYLIMIT ((UINT16)0xFD48) +#define HFA384x_RID_LONGRETRYLIMIT ((UINT16)0xFD49) +#define HFA384x_RID_MAXTXLIFETIME ((UINT16)0xFD4A) +#define HFA384x_RID_MAXRXLIFETIME ((UINT16)0xFD4B) +#define HFA384x_RID_CFPOLLABLE ((UINT16)0xFD4C) +#define HFA384x_RID_AUTHALGORITHMS ((UINT16)0xFD4D) +#define HFA384x_RID_PRIVACYOPTIMP ((UINT16)0xFD4F) +#define HFA384x_RID_DBMCOMMSQUALITY ((UINT16)0xFD51) +#define HFA384x_RID_CURRENTTXRATE1 ((UINT16)0xFD80) +#define HFA384x_RID_CURRENTTXRATE2 ((UINT16)0xFD81) +#define HFA384x_RID_CURRENTTXRATE3 ((UINT16)0xFD82) +#define HFA384x_RID_CURRENTTXRATE4 ((UINT16)0xFD83) +#define HFA384x_RID_CURRENTTXRATE5 ((UINT16)0xFD84) +#define HFA384x_RID_CURRENTTXRATE6 ((UINT16)0xFD85) +#define HFA384x_RID_OWNMACADDRESS ((UINT16)0xFD86) +// #define HFA384x_RID_PCFINFO ((UINT16)0xFD87) +#define HFA384x_RID_SCANRESULTS ((UINT16)0xFD88) // NEW +#define HFA384x_RID_HOSTSCANRESULTS ((UINT16)0xFD89) // NEW +#define HFA384x_RID_AUTHENTICATIONUSED ((UINT16)0xFD8A) // NEW +#define HFA384x_RID_ASSOCIATEFAILURE ((UINT16)0xFD8D) // 1.8.0 + +/*-------------------------------------------------------------------- +Information RID Lengths: MAC Information + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_PORTSTATUS_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTSSID_LEN ((UINT16)34) +#define HFA384x_RID_CURRENTBSSID_LEN ((UINT16)WLAN_BSSID_LEN) +#define HFA384x_RID_COMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_commsquality_t)) +#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_dbmcommsquality_t)) +#define HFA384x_RID_CURRENTTXRATE_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTBCNINT_LEN ((UINT16)0) +#define HFA384x_RID_STACURSCALETHRESH_LEN ((UINT16)12) +#define HFA384x_RID_APCURSCALETHRESH_LEN ((UINT16)6) +#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((UINT16)0) +#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((UINT16)0) +#define HFA384x_RID_LONGRETRYLIMIT_LEN ((UINT16)0) +#define HFA384x_RID_MAXTXLIFETIME_LEN ((UINT16)0) +#define HFA384x_RID_MAXRXLIFETIME_LEN ((UINT16)0) +#define HFA384x_RID_CFPOLLABLE_LEN ((UINT16)0) +#define HFA384x_RID_AUTHALGORITHMS_LEN ((UINT16)4) +#define HFA384x_RID_PRIVACYOPTIMP_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE1_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE2_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE3_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE4_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE5_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE6_LEN ((UINT16)0) +#define HFA384x_RID_OWNMACADDRESS_LEN ((UINT16)6) +#define HFA384x_RID_PCFINFO_LEN ((UINT16)6) +#define HFA384x_RID_CNFAPPCFINFO_LEN ((UINT16)sizeof(hfa384x_PCFInfo_data_t)) +#define HFA384x_RID_SCANREQUEST_LEN ((UINT16)sizeof(hfa384x_ScanRequest_data_t)) +#define HFA384x_RID_JOINREQUEST_LEN ((UINT16)sizeof(hfa384x_JoinRequest_data_t)) +#define HFA384x_RID_AUTHENTICATESTA_LEN ((UINT16)sizeof(hfa384x_authenticateStation_data_t)) +#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((UINT16)sizeof(hfa384x_ChannelInfoRequest_data_t)) +/*-------------------------------------------------------------------- +Information RIDs: Modem Information +--------------------------------------------------------------------*/ +#define HFA384x_RID_PHYTYPE ((UINT16)0xFDC0) +#define HFA384x_RID_CURRENTCHANNEL ((UINT16)0xFDC1) +#define HFA384x_RID_CURRENTPOWERSTATE ((UINT16)0xFDC2) +#define HFA384x_RID_CCAMODE ((UINT16)0xFDC3) +#define HFA384x_RID_SUPPORTEDDATARATES ((UINT16)0xFDC6) +#define HFA384x_RID_LFOSTATUS ((UINT16)0xFDC7) // 1.7.1 + +/*-------------------------------------------------------------------- +Information RID Lengths: Modem Information + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_PHYTYPE_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTCHANNEL_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((UINT16)0) +#define HFA384x_RID_CCAMODE_LEN ((UINT16)0) +#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((UINT16)10) + +/*-------------------------------------------------------------------- +API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) +--------------------------------------------------------------------*/ +#define HFA384x_RID_CNFWEPDEFAULTKEYID ((UINT16)0xFC23) +#define HFA384x_RID_CNFWEPDEFAULTKEY0 ((UINT16)0xFC24) +#define HFA384x_RID_CNFWEPDEFAULTKEY1 ((UINT16)0xFC25) +#define HFA384x_RID_CNFWEPDEFAULTKEY2 ((UINT16)0xFC26) +#define HFA384x_RID_CNFWEPDEFAULTKEY3 ((UINT16)0xFC27) +#define HFA384x_RID_CNFWEPFLAGS ((UINT16)0xFC28) +#define HFA384x_RID_CNFWEPKEYMAPTABLE ((UINT16)0xFC29) +#define HFA384x_RID_CNFAUTHENTICATION ((UINT16)0xFC2A) +#define HFA384x_RID_CNFMAXASSOCSTATIONS ((UINT16)0xFC2B) +#define HFA384x_RID_CNFTXCONTROL ((UINT16)0xFC2C) +#define HFA384x_RID_CNFROAMINGMODE ((UINT16)0xFC2D) +#define HFA384x_RID_CNFHOSTAUTHASSOC ((UINT16)0xFC2E) +#define HFA384x_RID_CNFRCVCRCERROR ((UINT16)0xFC30) +// #define HFA384x_RID_CNFMMLIFE ((UINT16)0xFC31) +#define HFA384x_RID_CNFALTRETRYCNT ((UINT16)0xFC32) +#define HFA384x_RID_CNFAPBCNINT ((UINT16)0xFC33) +#define HFA384x_RID_CNFAPPCFINFO ((UINT16)0xFC34) +#define HFA384x_RID_CNFSTAPCFINFO ((UINT16)0xFC35) +#define HFA384x_RID_CNFPRIORITYQUSAGE ((UINT16)0xFC37) +#define HFA384x_RID_CNFTIMCTRL ((UINT16)0xFC40) +#define HFA384x_RID_CNFTHIRTY2TALLY ((UINT16)0xFC42) +#define HFA384x_RID_CNFENHSECURITY ((UINT16)0xFC43) +#define HFA384x_RID_CNFDBMADJUST ((UINT16)0xFC46) // NEW +#define HFA384x_RID_CNFWPADATA ((UINT16)0xFC48) // 1.7.0 +#define HFA384x_RID_CNFPROPOGATIONDELAY ((UINT16)0xFC49) // 1.7.6 +#define HFA384x_RID_CNFSHORTPREAMBLE ((UINT16)0xFCB0) +#define HFA384x_RID_CNFEXCLONGPREAMBLE ((UINT16)0xFCB1) +#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((UINT16)0xFCB2) +#define HFA384x_RID_CNFBASICRATES ((UINT16)0xFCB3) +#define HFA384x_RID_CNFSUPPRATES ((UINT16)0xFCB4) +#define HFA384x_RID_CNFFALLBACKCTRL ((UINT16)0xFCB5) // NEW +#define HFA384x_RID_WEPKEYSTATUS ((UINT16)0xFCB6) // NEW +#define HFA384x_RID_WEPKEYMAPINDEX ((UINT16)0xFCB7) // NEW +#define HFA384x_RID_BROADCASTKEYID ((UINT16)0xFCB8) // NEW +#define HFA384x_RID_ENTSECFLAGEYID ((UINT16)0xFCB9) // NEW +#define HFA384x_RID_CNFPASSIVESCANCTRL ((UINT16)0xFCBA) // NEW STA +#define HFA384x_RID_CNFWPAHANDLING ((UINT16)0xFCBB) // 1.7.0 +#define HFA384x_RID_MDCCONTROL ((UINT16)0xFCBC) // 1.7.0/1.4.0 +#define HFA384x_RID_MDCCOUNTRY ((UINT16)0xFCBD) // 1.7.0/1.4.0 +#define HFA384x_RID_TXPOWERMAX ((UINT16)0xFCBE) // 1.7.0/1.4.0 +#define HFA384x_RID_CNFLFOENBLED ((UINT16)0xFCBF) // 1.6.3 +#define HFA384x_RID_CAPINFO ((UINT16)0xFCC0) // 1.7.0/1.3.7 +#define HFA384x_RID_LISTENINTERVAL ((UINT16)0xFCC1) // 1.7.0/1.3.7 +#define HFA384x_RID_DIVERSITYENABLED ((UINT16)0xFCC2) // 1.7.0/1.3.7 +#define HFA384x_RID_LED_CONTROL ((UINT16)0xFCC4) // 1.7.6 +#define HFA384x_RID_HFO_DELAY ((UINT16)0xFCC5) // 1.7.6 +#define HFA384x_RID_DISSALOWEDBSSID ((UINT16)0xFCC6) // 1.8.0 +#define HFA384x_RID_SCANREQUEST ((UINT16)0xFCE1) +#define HFA384x_RID_JOINREQUEST ((UINT16)0xFCE2) +#define HFA384x_RID_AUTHENTICATESTA ((UINT16)0xFCE3) +#define HFA384x_RID_CHANNELINFOREQUEST ((UINT16)0xFCE4) +#define HFA384x_RID_HOSTSCAN ((UINT16)0xFCE5) // NEW STA +#define HFA384x_RID_ASSOCIATESTA ((UINT16)0xFCE6) + +#define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((UINT16)6) +#define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((UINT16)14) +#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((UINT16)4) +/*-------------------------------------------------------------------- +PD Record codes +--------------------------------------------------------------------*/ +#define HFA384x_PDR_PCB_PARTNUM ((UINT16)0x0001) +#define HFA384x_PDR_PDAVER ((UINT16)0x0002) +#define HFA384x_PDR_NIC_SERIAL ((UINT16)0x0003) +#define HFA384x_PDR_MKK_MEASUREMENTS ((UINT16)0x0004) +#define HFA384x_PDR_NIC_RAMSIZE ((UINT16)0x0005) +#define HFA384x_PDR_MFISUPRANGE ((UINT16)0x0006) +#define HFA384x_PDR_CFISUPRANGE ((UINT16)0x0007) +#define HFA384x_PDR_NICID ((UINT16)0x0008) +//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((UINT16)0x0010) +//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((UINT16)0x0020) +//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((UINT16)0x0030) +//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((UINT16)0x0040) +//#define HFA384x_PDR_COREGA_HACK ((UINT16)0x00ff) +#define HFA384x_PDR_MAC_ADDRESS ((UINT16)0x0101) +//#define HFA384x_PDR_MKK_CALLNAME ((UINT16)0x0102) +#define HFA384x_PDR_REGDOMAIN ((UINT16)0x0103) +#define HFA384x_PDR_ALLOWED_CHANNEL ((UINT16)0x0104) +#define HFA384x_PDR_DEFAULT_CHANNEL ((UINT16)0x0105) +//#define HFA384x_PDR_PRIVACY_OPTION ((UINT16)0x0106) +#define HFA384x_PDR_TEMPTYPE ((UINT16)0x0107) +//#define HFA384x_PDR_REFDAC_SETUP ((UINT16)0x0110) +//#define HFA384x_PDR_VGDAC_SETUP ((UINT16)0x0120) +//#define HFA384x_PDR_LEVEL_COMP_SETUP ((UINT16)0x0130) +//#define HFA384x_PDR_TRIMDAC_SETUP ((UINT16)0x0140) +#define HFA384x_PDR_IFR_SETTING ((UINT16)0x0200) +#define HFA384x_PDR_RFR_SETTING ((UINT16)0x0201) +#define HFA384x_PDR_HFA3861_BASELINE ((UINT16)0x0202) +#define HFA384x_PDR_HFA3861_SHADOW ((UINT16)0x0203) +#define HFA384x_PDR_HFA3861_IFRF ((UINT16)0x0204) +#define HFA384x_PDR_HFA3861_CHCALSP ((UINT16)0x0300) +#define HFA384x_PDR_HFA3861_CHCALI ((UINT16)0x0301) +#define HFA384x_PDR_MAX_TX_POWER ((UINT16)0x0302) +#define HFA384x_PDR_MASTER_CHAN_LIST ((UINT16)0x0303) +#define HFA384x_PDR_3842_NIC_CONFIG ((UINT16)0x0400) +#define HFA384x_PDR_USB_ID ((UINT16)0x0401) +#define HFA384x_PDR_PCI_ID ((UINT16)0x0402) +#define HFA384x_PDR_PCI_IFCONF ((UINT16)0x0403) +#define HFA384x_PDR_PCI_PMCONF ((UINT16)0x0404) +#define HFA384x_PDR_RFENRGY ((UINT16)0x0406) +#define HFA384x_PDR_USB_POWER_TYPE ((UINT16)0x0407) +//#define HFA384x_PDR_UNKNOWN408 ((UINT16)0x0408) +#define HFA384x_PDR_USB_MAX_POWER ((UINT16)0x0409) +#define HFA384x_PDR_USB_MANUFACTURER ((UINT16)0x0410) +#define HFA384x_PDR_USB_PRODUCT ((UINT16)0x0411) +#define HFA384x_PDR_ANT_DIVERSITY ((UINT16)0x0412) +#define HFA384x_PDR_HFO_DELAY ((UINT16)0x0413) +#define HFA384x_PDR_SCALE_THRESH ((UINT16)0x0414) + +#define HFA384x_PDR_HFA3861_MANF_TESTSP ((UINT16)0x0900) +#define HFA384x_PDR_HFA3861_MANF_TESTI ((UINT16)0x0901) +#define HFA384x_PDR_END_OF_PDA ((UINT16)0x0000) + + +/*=============================================================*/ +/*------ Macros -----------------------------------------------*/ + +/*--- Register ID macros ------------------------*/ + +#define HFA384x_CMD HFA384x_CMD_OFF +#define HFA384x_PARAM0 HFA384x_PARAM0_OFF +#define HFA384x_PARAM1 HFA384x_PARAM1_OFF +#define HFA384x_PARAM2 HFA384x_PARAM2_OFF +#define HFA384x_STATUS HFA384x_STATUS_OFF +#define HFA384x_RESP0 HFA384x_RESP0_OFF +#define HFA384x_RESP1 HFA384x_RESP1_OFF +#define HFA384x_RESP2 HFA384x_RESP2_OFF +#define HFA384x_INFOFID HFA384x_INFOFID_OFF +#define HFA384x_RXFID HFA384x_RXFID_OFF +#define HFA384x_ALLOCFID HFA384x_ALLOCFID_OFF +#define HFA384x_TXCOMPLFID HFA384x_TXCOMPLFID_OFF +#define HFA384x_SELECT0 HFA384x_SELECT0_OFF +#define HFA384x_OFFSET0 HFA384x_OFFSET0_OFF +#define HFA384x_DATA0 HFA384x_DATA0_OFF +#define HFA384x_SELECT1 HFA384x_SELECT1_OFF +#define HFA384x_OFFSET1 HFA384x_OFFSET1_OFF +#define HFA384x_DATA1 HFA384x_DATA1_OFF +#define HFA384x_EVSTAT HFA384x_EVSTAT_OFF +#define HFA384x_INTEN HFA384x_INTEN_OFF +#define HFA384x_EVACK HFA384x_EVACK_OFF +#define HFA384x_CONTROL HFA384x_CONTROL_OFF +#define HFA384x_SWSUPPORT0 HFA384x_SWSUPPORT0_OFF +#define HFA384x_SWSUPPORT1 HFA384x_SWSUPPORT1_OFF +#define HFA384x_SWSUPPORT2 HFA384x_SWSUPPORT2_OFF +#define HFA384x_AUXPAGE HFA384x_AUXPAGE_OFF +#define HFA384x_AUXOFFSET HFA384x_AUXOFFSET_OFF +#define HFA384x_AUXDATA HFA384x_AUXDATA_OFF +#define HFA384x_PCICOR HFA384x_PCICOR_OFF +#define HFA384x_PCIHCR HFA384x_PCIHCR_OFF + + +/*--- Register Test/Get/Set Field macros ------------------------*/ + +#define HFA384x_CMD_ISBUSY(value) ((UINT16)(((UINT16)value) & HFA384x_CMD_BUSY)) +#define HFA384x_CMD_AINFO_GET(value) ((UINT16)(((UINT16)(value) & HFA384x_CMD_AINFO) >> 8)) +#define HFA384x_CMD_AINFO_SET(value) ((UINT16)((UINT16)(value) << 8)) +#define HFA384x_CMD_MACPORT_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_MACPORT))) +#define HFA384x_CMD_MACPORT_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value)) +#define HFA384x_CMD_ISRECL(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_RECL))) +#define HFA384x_CMD_RECL_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value)) +#define HFA384x_CMD_QOS_GET(value) ((UINT16((((UINT16)(value))&((UINT16)0x3000)) >> 12)) +#define HFA384x_CMD_QOS_SET(value) ((UINT16)((((UINT16)(value)) << 12) & 0x3000)) +#define HFA384x_CMD_ISWRITE(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_WRITE))) +#define HFA384x_CMD_WRITE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value)) +#define HFA384x_CMD_PROGMODE_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_PROGMODE))) +#define HFA384x_CMD_PROGMODE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value)) +#define HFA384x_CMD_CMDCODE_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_CMD_CMDCODE)) +#define HFA384x_CMD_CMDCODE_SET(value) ((UINT16)(value)) + +#define HFA384x_STATUS_RESULT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_STATUS_RESULT) >> 8)) +#define HFA384x_STATUS_RESULT_SET(value) (((UINT16)(value)) << 8) +#define HFA384x_STATUS_CMDCODE_GET(value) (((UINT16)(value)) & HFA384x_STATUS_CMDCODE) +#define HFA384x_STATUS_CMDCODE_SET(value) ((UINT16)(value)) + +#define HFA384x_OFFSET_ISBUSY(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_BUSY)) +#define HFA384x_OFFSET_ISERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_ERR)) +#define HFA384x_OFFSET_DATAOFF_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_DATAOFF)) +#define HFA384x_OFFSET_DATAOFF_SET(value) ((UINT16)(value)) + +#define HFA384x_EVSTAT_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TICK)) +#define HFA384x_EVSTAT_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_WTERR)) +#define HFA384x_EVSTAT_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFDROP)) +#define HFA384x_EVSTAT_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFO)) +#define HFA384x_EVSTAT_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_DTIM)) +#define HFA384x_EVSTAT_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_CMD)) +#define HFA384x_EVSTAT_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_ALLOC)) +#define HFA384x_EVSTAT_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TXEXC)) +#define HFA384x_EVSTAT_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TX)) +#define HFA384x_EVSTAT_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_RX)) + +#define HFA384x_EVSTAT_ISBAP_OP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INT_BAP_OP)) + +#define HFA384x_INTEN_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TICK)) +#define HFA384x_INTEN_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15)) +#define HFA384x_INTEN_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_WTERR)) +#define HFA384x_INTEN_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14)) +#define HFA384x_INTEN_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFDROP)) +#define HFA384x_INTEN_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13)) +#define HFA384x_INTEN_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFO)) +#define HFA384x_INTEN_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7)) +#define HFA384x_INTEN_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_DTIM)) +#define HFA384x_INTEN_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5)) +#define HFA384x_INTEN_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_CMD)) +#define HFA384x_INTEN_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4)) +#define HFA384x_INTEN_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_ALLOC)) +#define HFA384x_INTEN_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3)) +#define HFA384x_INTEN_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TXEXC)) +#define HFA384x_INTEN_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2)) +#define HFA384x_INTEN_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TX)) +#define HFA384x_INTEN_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1)) +#define HFA384x_INTEN_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_RX)) +#define HFA384x_INTEN_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0)) + +#define HFA384x_EVACK_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TICK)) +#define HFA384x_EVACK_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15)) +#define HFA384x_EVACK_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_WTERR)) +#define HFA384x_EVACK_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14)) +#define HFA384x_EVACK_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFDROP)) +#define HFA384x_EVACK_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13)) +#define HFA384x_EVACK_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFO)) +#define HFA384x_EVACK_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7)) +#define HFA384x_EVACK_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_DTIM)) +#define HFA384x_EVACK_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5)) +#define HFA384x_EVACK_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_CMD)) +#define HFA384x_EVACK_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4)) +#define HFA384x_EVACK_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_ALLOC)) +#define HFA384x_EVACK_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3)) +#define HFA384x_EVACK_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TXEXC)) +#define HFA384x_EVACK_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2)) +#define HFA384x_EVACK_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TX)) +#define HFA384x_EVACK_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1)) +#define HFA384x_EVACK_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_RX)) +#define HFA384x_EVACK_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0)) + +#define HFA384x_CONTROL_AUXEN_SET(value) ((UINT16)(((UINT16)(value)) << 14)) +#define HFA384x_CONTROL_AUXEN_GET(value) ((UINT16)(((UINT16)(value)) >> 14)) + +/* Byte Order */ +#ifdef __KERNEL__ +#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n))) +#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n))) +#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n))) +#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n))) +#endif + +/* Host Maintained State Info */ +#define HFA384x_STATE_PREINIT 0 +#define HFA384x_STATE_INIT 1 +#define HFA384x_STATE_RUNNING 2 + +/*=============================================================*/ +/*------ Types and their related constants --------------------*/ + +#define HFA384x_HOSTAUTHASSOC_HOSTAUTH BIT0 +#define HFA384x_HOSTAUTHASSOC_HOSTASSOC BIT1 + +#define HFA384x_WHAHANDLING_DISABLED 0 +#define HFA384x_WHAHANDLING_PASSTHROUGH BIT1 + +/*-------------------------------------------------------------*/ +/* Commonly used basic types */ +typedef struct hfa384x_bytestr +{ + UINT16 len; + UINT8 data[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_bytestr_t; + +typedef struct hfa384x_bytestr32 +{ + UINT16 len; + UINT8 data[32]; +} __WLAN_ATTRIB_PACK__ hfa384x_bytestr32_t; + +/*-------------------------------------------------------------------- +Configuration Record Structures: + Network Parameters, Static Configuration Entities +--------------------------------------------------------------------*/ +/* Prototype structure: all configuration record structures start with +these members */ + +typedef struct hfa384x_record +{ + UINT16 reclen; + UINT16 rid; +} __WLAN_ATTRIB_PACK__ hfa384x_rec_t; + +typedef struct hfa384x_record16 +{ + UINT16 reclen; + UINT16 rid; + UINT16 val; +} __WLAN_ATTRIB_PACK__ hfa384x_rec16_t; + +typedef struct hfa384x_record32 +{ + UINT16 reclen; + UINT16 rid; + UINT32 val; +} __WLAN_ATTRIB_PACK__ hfa384x_rec32; + +/*-- Hardware/Firmware Component Information ----------*/ +typedef struct hfa384x_compident +{ + UINT16 id; + UINT16 variant; + UINT16 major; + UINT16 minor; +} __WLAN_ATTRIB_PACK__ hfa384x_compident_t; + +typedef struct hfa384x_caplevel +{ + UINT16 role; + UINT16 id; + UINT16 variant; + UINT16 bottom; + UINT16 top; +} __WLAN_ATTRIB_PACK__ hfa384x_caplevel_t; + +/*-- Configuration Record: cnfPortType --*/ +typedef struct hfa384x_cnfPortType +{ + UINT16 cnfPortType; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPortType_t; + +/*-- Configuration Record: cnfOwnMACAddress --*/ +typedef struct hfa384x_cnfOwnMACAddress +{ + UINT8 cnfOwnMACAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnMACAddress_t; + +/*-- Configuration Record: cnfDesiredSSID --*/ +typedef struct hfa384x_cnfDesiredSSID +{ + UINT8 cnfDesiredSSID[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfDesiredSSID_t; + +/*-- Configuration Record: cnfOwnChannel --*/ +typedef struct hfa384x_cnfOwnChannel +{ + UINT16 cnfOwnChannel; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnChannel_t; + +/*-- Configuration Record: cnfOwnSSID --*/ +typedef struct hfa384x_cnfOwnSSID +{ + UINT8 cnfOwnSSID[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnSSID_t; + +/*-- Configuration Record: cnfOwnATIMWindow --*/ +typedef struct hfa384x_cnfOwnATIMWindow +{ + UINT16 cnfOwnATIMWindow; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnATIMWindow_t; + +/*-- Configuration Record: cnfSystemScale --*/ +typedef struct hfa384x_cnfSystemScale +{ + UINT16 cnfSystemScale; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfSystemScale_t; + +/*-- Configuration Record: cnfMaxDataLength --*/ +typedef struct hfa384x_cnfMaxDataLength +{ + UINT16 cnfMaxDataLength; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxDataLength_t; + +/*-- Configuration Record: cnfWDSAddress --*/ +typedef struct hfa384x_cnfWDSAddress +{ + UINT8 cnfWDSAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddress_t; + +/*-- Configuration Record: cnfPMEnabled --*/ +typedef struct hfa384x_cnfPMEnabled +{ + UINT16 cnfPMEnabled; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEnabled_t; + +/*-- Configuration Record: cnfPMEPS --*/ +typedef struct hfa384x_cnfPMEPS +{ + UINT16 cnfPMEPS; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEPS_t; + +/*-- Configuration Record: cnfMulticastReceive --*/ +typedef struct hfa384x_cnfMulticastReceive +{ + UINT16 cnfMulticastReceive; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastReceive_t; + +/*-- Configuration Record: cnfAuthentication --*/ +#define HFA384x_CNFAUTHENTICATION_OPENSYSTEM 0x0001 +#define HFA384x_CNFAUTHENTICATION_SHAREDKEY 0x0002 +#define HFA384x_CNFAUTHENTICATION_LEAP 0x0004 + +/*-- Configuration Record: cnfMaxSleepDuration --*/ +typedef struct hfa384x_cnfMaxSleepDuration +{ + UINT16 cnfMaxSleepDuration; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxSleepDuration_t; + +/*-- Configuration Record: cnfPMHoldoverDuration --*/ +typedef struct hfa384x_cnfPMHoldoverDuration +{ + UINT16 cnfPMHoldoverDuration; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMHoldoverDuration_t; + +/*-- Configuration Record: cnfOwnName --*/ +typedef struct hfa384x_cnfOwnName +{ + UINT8 cnfOwnName[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnName_t; + +/*-- Configuration Record: cnfOwnDTIMPeriod --*/ +typedef struct hfa384x_cnfOwnDTIMPeriod +{ + UINT16 cnfOwnDTIMPeriod; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnDTIMPeriod_t; + +/*-- Configuration Record: cnfWDSAddress --*/ +typedef struct hfa384x_cnfWDSAddressN +{ + UINT8 cnfWDSAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddressN_t; + +/*-- Configuration Record: cnfMulticastPMBuffering --*/ +typedef struct hfa384x_cnfMulticastPMBuffering +{ + UINT16 cnfMulticastPMBuffering; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastPMBuffering_t; + +/*-------------------------------------------------------------------- +Configuration Record Structures: + Network Parameters, Dynamic Configuration Entities +--------------------------------------------------------------------*/ + +/*-- Configuration Record: GroupAddresses --*/ +typedef struct hfa384x_GroupAddresses +{ + UINT8 MACAddress[16][6]; +} __WLAN_ATTRIB_PACK__ hfa384x_GroupAddresses_t; + +/*-- Configuration Record: CreateIBSS --*/ +typedef struct hfa384x_CreateIBSS +{ + UINT16 CreateIBSS; +} __WLAN_ATTRIB_PACK__ hfa384x_CreateIBSS_t; + +#define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 +#define HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS 1 +#define HFA384x_CREATEIBSS_JOINIBSS 2 +#define HFA384x_CREATEIBSS_JOINESS_JOINIBSS 3 + +/*-- Configuration Record: FragmentationThreshold --*/ +typedef struct hfa384x_FragmentationThreshold +{ + UINT16 FragmentationThreshold; +} __WLAN_ATTRIB_PACK__ hfa384x_FragmentationThreshold_t; + +/*-- Configuration Record: RTSThreshold --*/ +typedef struct hfa384x_RTSThreshold +{ + UINT16 RTSThreshold; +} __WLAN_ATTRIB_PACK__ hfa384x_RTSThreshold_t; + +/*-- Configuration Record: TxRateControl --*/ +typedef struct hfa384x_TxRateControl +{ + UINT16 TxRateControl; +} __WLAN_ATTRIB_PACK__ hfa384x_TxRateControl_t; + +/*-- Configuration Record: PromiscuousMode --*/ +typedef struct hfa384x_PromiscuousMode +{ + UINT16 PromiscuousMode; +} __WLAN_ATTRIB_PACK__ hfa384x_PromiscuousMode_t; + +/*-- Configuration Record: ScanRequest (data portion only) --*/ +typedef struct hfa384x_ScanRequest_data +{ + UINT16 channelList; + UINT16 txRate; +} __WLAN_ATTRIB_PACK__ hfa384x_ScanRequest_data_t; + +/*-- Configuration Record: HostScanRequest (data portion only) --*/ +typedef struct hfa384x_HostScanRequest_data +{ + UINT16 channelList; + UINT16 txRate; + hfa384x_bytestr32_t ssid; +} __WLAN_ATTRIB_PACK__ hfa384x_HostScanRequest_data_t; + +/*-- Configuration Record: JoinRequest (data portion only) --*/ +typedef struct hfa384x_JoinRequest_data +{ + UINT8 bssid[WLAN_BSSID_LEN]; + UINT16 channel; +} __WLAN_ATTRIB_PACK__ hfa384x_JoinRequest_data_t; + +/*-- Configuration Record: authenticateStation (data portion only) --*/ +typedef struct hfa384x_authenticateStation_data +{ + UINT8 address[WLAN_ADDR_LEN]; + UINT16 status; + UINT16 algorithm; +} __WLAN_ATTRIB_PACK__ hfa384x_authenticateStation_data_t; + +/*-- Configuration Record: associateStation (data portion only) --*/ +typedef struct hfa384x_associateStation_data +{ + UINT8 address[WLAN_ADDR_LEN]; + UINT16 status; + UINT16 type; +} __WLAN_ATTRIB_PACK__ hfa384x_associateStation_data_t; + +/*-- Configuration Record: ChannelInfoRequest (data portion only) --*/ +typedef struct hfa384x_ChannelInfoRequest_data +{ + UINT16 channelList; + UINT16 channelDwellTime; +} __WLAN_ATTRIB_PACK__ hfa384x_ChannelInfoRequest_data_t; + +/*-- Configuration Record: WEPKeyMapping (data portion only) --*/ +typedef struct hfa384x_WEPKeyMapping +{ + UINT8 address[WLAN_ADDR_LEN]; + UINT16 key_index; + UINT8 key[16]; + UINT8 mic_transmit_key[4]; + UINT8 mic_receive_key[4]; +} __WLAN_ATTRIB_PACK__ hfa384x_WEPKeyMapping_t; + +/*-- Configuration Record: WPAData (data portion only) --*/ +typedef struct hfa384x_WPAData +{ + UINT16 datalen; + UINT8 data[0]; // max 80 +} __WLAN_ATTRIB_PACK__ hfa384x_WPAData_t; + +/*-------------------------------------------------------------------- +Configuration Record Structures: Behavior Parameters +--------------------------------------------------------------------*/ + +/*-- Configuration Record: TickTime --*/ +typedef struct hfa384x_TickTime +{ + UINT16 TickTime; +} __WLAN_ATTRIB_PACK__ hfa384x_TickTime_t; + +/*-------------------------------------------------------------------- +Information Record Structures: NIC Information +--------------------------------------------------------------------*/ + +/*-- Information Record: MaxLoadTime --*/ +typedef struct hfa384x_MaxLoadTime +{ + UINT16 MaxLoadTime; +} __WLAN_ATTRIB_PACK__ hfa384x_MaxLoadTime_t; + +/*-- Information Record: DownLoadBuffer --*/ +/* NOTE: The page and offset are in AUX format */ +typedef struct hfa384x_downloadbuffer +{ + UINT16 page; + UINT16 offset; + UINT16 len; +} __WLAN_ATTRIB_PACK__ hfa384x_downloadbuffer_t; + +/*-- Information Record: PRIIdentity --*/ +typedef struct hfa384x_PRIIdentity +{ + UINT16 PRICompID; + UINT16 PRIVariant; + UINT16 PRIMajorVersion; + UINT16 PRIMinorVersion; +} __WLAN_ATTRIB_PACK__ hfa384x_PRIIdentity_t; + +/*-- Information Record: PRISupRange --*/ +typedef struct hfa384x_PRISupRange +{ + UINT16 PRIRole; + UINT16 PRIID; + UINT16 PRIVariant; + UINT16 PRIBottom; + UINT16 PRITop; +} __WLAN_ATTRIB_PACK__ hfa384x_PRISupRange_t; + +/*-- Information Record: CFIActRanges --*/ +typedef struct hfa384x_CFIActRanges +{ + UINT16 CFIRole; + UINT16 CFIID; + UINT16 CFIVariant; + UINT16 CFIBottom; + UINT16 CFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_CFIActRanges_t; + +/*-- Information Record: NICSerialNumber --*/ +typedef struct hfa384x_NICSerialNumber +{ + UINT8 NICSerialNumber[12]; +} __WLAN_ATTRIB_PACK__ hfa384x_NICSerialNumber_t; + +/*-- Information Record: NICIdentity --*/ +typedef struct hfa384x_NICIdentity +{ + UINT16 NICCompID; + UINT16 NICVariant; + UINT16 NICMajorVersion; + UINT16 NICMinorVersion; +} __WLAN_ATTRIB_PACK__ hfa384x_NICIdentity_t; + +/*-- Information Record: MFISupRange --*/ +typedef struct hfa384x_MFISupRange +{ + UINT16 MFIRole; + UINT16 MFIID; + UINT16 MFIVariant; + UINT16 MFIBottom; + UINT16 MFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_MFISupRange_t; + +/*-- Information Record: CFISupRange --*/ +typedef struct hfa384x_CFISupRange +{ + UINT16 CFIRole; + UINT16 CFIID; + UINT16 CFIVariant; + UINT16 CFIBottom; + UINT16 CFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_CFISupRange_t; + +/*-- Information Record: BUILDSEQ:BuildSeq --*/ +typedef struct hfa384x_BuildSeq { + UINT16 primary; + UINT16 secondary; +} __WLAN_ATTRIB_PACK__ hfa384x_BuildSeq_t; + +/*-- Information Record: FWID --*/ +#define HFA384x_FWID_LEN 14 +typedef struct hfa384x_FWID { + UINT8 primary[HFA384x_FWID_LEN]; + UINT8 secondary[HFA384x_FWID_LEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_FWID_t; + +/*-- Information Record: ChannelList --*/ +typedef struct hfa384x_ChannelList +{ + UINT16 ChannelList; +} __WLAN_ATTRIB_PACK__ hfa384x_ChannelList_t; + +/*-- Information Record: RegulatoryDomains --*/ +typedef struct hfa384x_RegulatoryDomains +{ + UINT8 RegulatoryDomains[12]; +} __WLAN_ATTRIB_PACK__ hfa384x_RegulatoryDomains_t; + +/*-- Information Record: TempType --*/ +typedef struct hfa384x_TempType +{ + UINT16 TempType; +} __WLAN_ATTRIB_PACK__ hfa384x_TempType_t; + +/*-- Information Record: CIS --*/ +typedef struct hfa384x_CIS +{ + UINT8 CIS[480]; +} __WLAN_ATTRIB_PACK__ hfa384x_CIS_t; + +/*-- Information Record: STAIdentity --*/ +typedef struct hfa384x_STAIdentity +{ + UINT16 STACompID; + UINT16 STAVariant; + UINT16 STAMajorVersion; + UINT16 STAMinorVersion; +} __WLAN_ATTRIB_PACK__ hfa384x_STAIdentity_t; + +/*-- Information Record: STASupRange --*/ +typedef struct hfa384x_STASupRange +{ + UINT16 STARole; + UINT16 STAID; + UINT16 STAVariant; + UINT16 STABottom; + UINT16 STATop; +} __WLAN_ATTRIB_PACK__ hfa384x_STASupRange_t; + +/*-- Information Record: MFIActRanges --*/ +typedef struct hfa384x_MFIActRanges +{ + UINT16 MFIRole; + UINT16 MFIID; + UINT16 MFIVariant; + UINT16 MFIBottom; + UINT16 MFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_MFIActRanges_t; + +/*-------------------------------------------------------------------- +Information Record Structures: NIC Information +--------------------------------------------------------------------*/ + +/*-- Information Record: PortStatus --*/ +typedef struct hfa384x_PortStatus +{ + UINT16 PortStatus; +} __WLAN_ATTRIB_PACK__ hfa384x_PortStatus_t; + +#define HFA384x_PSTATUS_DISABLED ((UINT16)1) +#define HFA384x_PSTATUS_SEARCHING ((UINT16)2) +#define HFA384x_PSTATUS_CONN_IBSS ((UINT16)3) +#define HFA384x_PSTATUS_CONN_ESS ((UINT16)4) +#define HFA384x_PSTATUS_OUTOFRANGE ((UINT16)5) +#define HFA384x_PSTATUS_CONN_WDS ((UINT16)6) + +/*-- Information Record: CurrentSSID --*/ +typedef struct hfa384x_CurrentSSID +{ + UINT8 CurrentSSID[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentSSID_t; + +/*-- Information Record: CurrentBSSID --*/ +typedef struct hfa384x_CurrentBSSID +{ + UINT8 CurrentBSSID[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBSSID_t; + +/*-- Information Record: commsquality --*/ +typedef struct hfa384x_commsquality +{ + UINT16 CQ_currBSS; + UINT16 ASL_currBSS; + UINT16 ANL_currFC; +} __WLAN_ATTRIB_PACK__ hfa384x_commsquality_t; + +/*-- Information Record: dmbcommsquality --*/ +typedef struct hfa384x_dbmcommsquality +{ + UINT16 CQdbm_currBSS; + UINT16 ASLdbm_currBSS; + UINT16 ANLdbm_currFC; +} __WLAN_ATTRIB_PACK__ hfa384x_dbmcommsquality_t; + +/*-- Information Record: CurrentTxRate --*/ +typedef struct hfa384x_CurrentTxRate +{ + UINT16 CurrentTxRate; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentTxRate_t; + +/*-- Information Record: CurrentBeaconInterval --*/ +typedef struct hfa384x_CurrentBeaconInterval +{ + UINT16 CurrentBeaconInterval; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBeaconInterval_t; + +/*-- Information Record: CurrentScaleThresholds --*/ +typedef struct hfa384x_CurrentScaleThresholds +{ + UINT16 EnergyDetectThreshold; + UINT16 CarrierDetectThreshold; + UINT16 DeferDetectThreshold; + UINT16 CellSearchThreshold; /* Stations only */ + UINT16 DeadSpotThreshold; /* Stations only */ +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentScaleThresholds_t; + +/*-- Information Record: ProtocolRspTime --*/ +typedef struct hfa384x_ProtocolRspTime +{ + UINT16 ProtocolRspTime; +} __WLAN_ATTRIB_PACK__ hfa384x_ProtocolRspTime_t; + +/*-- Information Record: ShortRetryLimit --*/ +typedef struct hfa384x_ShortRetryLimit +{ + UINT16 ShortRetryLimit; +} __WLAN_ATTRIB_PACK__ hfa384x_ShortRetryLimit_t; + +/*-- Information Record: LongRetryLimit --*/ +typedef struct hfa384x_LongRetryLimit +{ + UINT16 LongRetryLimit; +} __WLAN_ATTRIB_PACK__ hfa384x_LongRetryLimit_t; + +/*-- Information Record: MaxTransmitLifetime --*/ +typedef struct hfa384x_MaxTransmitLifetime +{ + UINT16 MaxTransmitLifetime; +} __WLAN_ATTRIB_PACK__ hfa384x_MaxTransmitLifetime_t; + +/*-- Information Record: MaxReceiveLifetime --*/ +typedef struct hfa384x_MaxReceiveLifetime +{ + UINT16 MaxReceiveLifetime; +} __WLAN_ATTRIB_PACK__ hfa384x_MaxReceiveLifetime_t; + +/*-- Information Record: CFPollable --*/ +typedef struct hfa384x_CFPollable +{ + UINT16 CFPollable; +} __WLAN_ATTRIB_PACK__ hfa384x_CFPollable_t; + +/*-- Information Record: AuthenticationAlgorithms --*/ +typedef struct hfa384x_AuthenticationAlgorithms +{ + UINT16 AuthenticationType; + UINT16 TypeEnabled; +} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_t; + +/*-- Information Record: AuthenticationAlgorithms +(data only --*/ +typedef struct hfa384x_AuthenticationAlgorithms_data +{ + UINT16 AuthenticationType; + UINT16 TypeEnabled; +} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_data_t; + +/*-- Information Record: PrivacyOptionImplemented --*/ +typedef struct hfa384x_PrivacyOptionImplemented +{ + UINT16 PrivacyOptionImplemented; +} __WLAN_ATTRIB_PACK__ hfa384x_PrivacyOptionImplemented_t; + +/*-- Information Record: OwnMACAddress --*/ +typedef struct hfa384x_OwnMACAddress +{ + UINT8 OwnMACAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_OwnMACAddress_t; + +/*-- Information Record: PCFInfo --*/ +typedef struct hfa384x_PCFInfo +{ + UINT16 MediumOccupancyLimit; + UINT16 CFPPeriod; + UINT16 CFPMaxDuration; + UINT16 CFPFlags; +} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_t; + +/*-- Information Record: PCFInfo (data portion only) --*/ +typedef struct hfa384x_PCFInfo_data +{ + UINT16 MediumOccupancyLimit; + UINT16 CFPPeriod; + UINT16 CFPMaxDuration; + UINT16 CFPFlags; +} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_data_t; + +/*-------------------------------------------------------------------- +Information Record Structures: Modem Information Records +--------------------------------------------------------------------*/ + +/*-- Information Record: PHYType --*/ +typedef struct hfa384x_PHYType +{ + UINT16 PHYType; +} __WLAN_ATTRIB_PACK__ hfa384x_PHYType_t; + +/*-- Information Record: CurrentChannel --*/ +typedef struct hfa384x_CurrentChannel +{ + UINT16 CurrentChannel; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentChannel_t; + +/*-- Information Record: CurrentPowerState --*/ +typedef struct hfa384x_CurrentPowerState +{ + UINT16 CurrentPowerState; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentPowerState_t; + +/*-- Information Record: CCAMode --*/ +typedef struct hfa384x_CCAMode +{ + UINT16 CCAMode; +} __WLAN_ATTRIB_PACK__ hfa384x_CCAMode_t; + +/*-- Information Record: SupportedDataRates --*/ +typedef struct hfa384x_SupportedDataRates +{ + UINT8 SupportedDataRates[10]; +} __WLAN_ATTRIB_PACK__ hfa384x_SupportedDataRates_t; + +/*-- Information Record: LFOStatus --*/ +typedef struct hfa384x_LFOStatus +{ + UINT16 TestResults; + UINT16 LFOResult; + UINT16 VRHFOResult; +} __WLAN_ATTRIB_PACK__ hfa384x_LFOStatus_t; + +#define HFA384x_TESTRESULT_ALLPASSED BIT0 +#define HFA384x_TESTRESULT_LFO_FAIL BIT1 +#define HFA384x_TESTRESULT_VR_HF0_FAIL BIT2 +#define HFA384x_HOST_FIRM_COORDINATE BIT7 +#define HFA384x_TESTRESULT_COORDINATE BIT15 + +/*-- Information Record: LEDControl --*/ +typedef struct hfa384x_LEDControl +{ + UINT16 searching_on; + UINT16 searching_off; + UINT16 assoc_on; + UINT16 assoc_off; + UINT16 activity; +} __WLAN_ATTRIB_PACK__ hfa384x_LEDControl_t; + +/*-------------------------------------------------------------------- + FRAME DESCRIPTORS AND FRAME STRUCTURES + +FRAME DESCRIPTORS: Offsets + +---------------------------------------------------------------------- +Control Info (offset 44-51) +--------------------------------------------------------------------*/ +#define HFA384x_FD_STATUS_OFF ((UINT16)0x44) +#define HFA384x_FD_TIME_OFF ((UINT16)0x46) +#define HFA384x_FD_SWSUPPORT_OFF ((UINT16)0x4A) +#define HFA384x_FD_SILENCE_OFF ((UINT16)0x4A) +#define HFA384x_FD_SIGNAL_OFF ((UINT16)0x4B) +#define HFA384x_FD_RATE_OFF ((UINT16)0x4C) +#define HFA384x_FD_RXFLOW_OFF ((UINT16)0x4D) +#define HFA384x_FD_RESERVED_OFF ((UINT16)0x4E) +#define HFA384x_FD_TXCONTROL_OFF ((UINT16)0x50) +/*-------------------------------------------------------------------- +802.11 Header (offset 52-6B) +--------------------------------------------------------------------*/ +#define HFA384x_FD_FRAMECONTROL_OFF ((UINT16)0x52) +#define HFA384x_FD_DURATIONID_OFF ((UINT16)0x54) +#define HFA384x_FD_ADDRESS1_OFF ((UINT16)0x56) +#define HFA384x_FD_ADDRESS2_OFF ((UINT16)0x5C) +#define HFA384x_FD_ADDRESS3_OFF ((UINT16)0x62) +#define HFA384x_FD_SEQCONTROL_OFF ((UINT16)0x68) +#define HFA384x_FD_ADDRESS4_OFF ((UINT16)0x6A) +#define HFA384x_FD_DATALEN_OFF ((UINT16)0x70) +/*-------------------------------------------------------------------- +802.3 Header (offset 72-7F) +--------------------------------------------------------------------*/ +#define HFA384x_FD_DESTADDRESS_OFF ((UINT16)0x72) +#define HFA384x_FD_SRCADDRESS_OFF ((UINT16)0x78) +#define HFA384x_FD_DATALENGTH_OFF ((UINT16)0x7E) + +/*-------------------------------------------------------------------- +FRAME STRUCTURES: Communication Frames +---------------------------------------------------------------------- +Communication Frames: Transmit Frames +--------------------------------------------------------------------*/ +/*-- Communication Frame: Transmit Frame Structure --*/ +typedef struct hfa384x_tx_frame +{ + UINT16 status; + UINT16 reserved1; + UINT16 reserved2; + UINT32 sw_support; + UINT8 tx_retrycount; + UINT8 tx_rate; + UINT16 tx_control; + + /*-- 802.11 Header Information --*/ + + UINT16 frame_control; + UINT16 duration_id; + UINT8 address1[6]; + UINT8 address2[6]; + UINT8 address3[6]; + UINT16 sequence_control; + UINT8 address4[6]; + UINT16 data_len; /* little endian format */ + + /*-- 802.3 Header Information --*/ + + UINT8 dest_addr[6]; + UINT8 src_addr[6]; + UINT16 data_length; /* big endian format */ +} __WLAN_ATTRIB_PACK__ hfa384x_tx_frame_t; +/*-------------------------------------------------------------------- +Communication Frames: Field Masks for Transmit Frames +--------------------------------------------------------------------*/ +/*-- Status Field --*/ +#define HFA384x_TXSTATUS_ACKERR ((UINT16)BIT5) +#define HFA384x_TXSTATUS_FORMERR ((UINT16)BIT3) +#define HFA384x_TXSTATUS_DISCON ((UINT16)BIT2) +#define HFA384x_TXSTATUS_AGEDERR ((UINT16)BIT1) +#define HFA384x_TXSTATUS_RETRYERR ((UINT16)BIT0) +/*-- Transmit Control Field --*/ +#define HFA384x_TX_CFPOLL ((UINT16)BIT12) +#define HFA384x_TX_PRST ((UINT16)BIT11) +#define HFA384x_TX_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) +#define HFA384x_TX_NOENCRYPT ((UINT16)BIT7) +#define HFA384x_TX_RETRYSTRAT ((UINT16)(BIT6 | BIT5)) +#define HFA384x_TX_STRUCTYPE ((UINT16)(BIT4 | BIT3)) +#define HFA384x_TX_TXEX ((UINT16)BIT2) +#define HFA384x_TX_TXOK ((UINT16)BIT1) +/*-------------------------------------------------------------------- +Communication Frames: Test/Get/Set Field Values for Transmit Frames +--------------------------------------------------------------------*/ +/*-- Status Field --*/ +#define HFA384x_TXSTATUS_ISERROR(v) \ + (((UINT16)(v))&\ + (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\ + HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\ + HFA384x_TXSTATUS_RETRYERR)) + +#define HFA384x_TXSTATUS_ISACKERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_ACKERR)) +#define HFA384x_TXSTATUS_ISFORMERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_FORMERR)) +#define HFA384x_TXSTATUS_ISDISCON(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_DISCON)) +#define HFA384x_TXSTATUS_ISAGEDERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_AGEDERR)) +#define HFA384x_TXSTATUS_ISRETRYERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_RETRYERR)) + +#define HFA384x_TX_GET(v,m,s) ((((UINT16)(v))&((UINT16)(m)))>>((UINT16)(s))) +#define HFA384x_TX_SET(v,m,s) ((((UINT16)(v))<<((UINT16)(s)))&((UINT16)(m))) + +#define HFA384x_TX_CFPOLL_GET(v) HFA384x_TX_GET(v, HFA384x_TX_CFPOLL,12) +#define HFA384x_TX_CFPOLL_SET(v) HFA384x_TX_SET(v, HFA384x_TX_CFPOLL,12) +#define HFA384x_TX_PRST_GET(v) HFA384x_TX_GET(v, HFA384x_TX_PRST,11) +#define HFA384x_TX_PRST_SET(v) HFA384x_TX_SET(v, HFA384x_TX_PRST,11) +#define HFA384x_TX_MACPORT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_MACPORT, 8) +#define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8) +#define HFA384x_TX_NOENCRYPT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_NOENCRYPT, 7) +#define HFA384x_TX_NOENCRYPT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_NOENCRYPT, 7) +#define HFA384x_TX_RETRYSTRAT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_RETRYSTRAT, 5) +#define HFA384x_TX_RETRYSTRAT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_RETRYSTRAT, 5) +#define HFA384x_TX_STRUCTYPE_GET(v) HFA384x_TX_GET(v, HFA384x_TX_STRUCTYPE, 3) +#define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, HFA384x_TX_STRUCTYPE, 3) +#define HFA384x_TX_TXEX_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXEX, 2) +#define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2) +#define HFA384x_TX_TXOK_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXOK, 1) +#define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1) +/*-------------------------------------------------------------------- +Communication Frames: Receive Frames +--------------------------------------------------------------------*/ +/*-- Communication Frame: Receive Frame Structure --*/ +typedef struct hfa384x_rx_frame +{ + /*-- MAC rx descriptor (hfa384x byte order) --*/ + UINT16 status; + UINT32 time; + UINT8 silence; + UINT8 signal; + UINT8 rate; + UINT8 rx_flow; + UINT16 reserved1; + UINT16 reserved2; + + /*-- 802.11 Header Information (802.11 byte order) --*/ + UINT16 frame_control; + UINT16 duration_id; + UINT8 address1[6]; + UINT8 address2[6]; + UINT8 address3[6]; + UINT16 sequence_control; + UINT8 address4[6]; + UINT16 data_len; /* hfa384x (little endian) format */ + + /*-- 802.3 Header Information --*/ + UINT8 dest_addr[6]; + UINT8 src_addr[6]; + UINT16 data_length; /* IEEE? (big endian) format */ +} __WLAN_ATTRIB_PACK__ hfa384x_rx_frame_t; +/*-------------------------------------------------------------------- +Communication Frames: Field Masks for Receive Frames +--------------------------------------------------------------------*/ +/*-- Offsets --------*/ +#define HFA384x_RX_DATA_LEN_OFF ((UINT16)44) +#define HFA384x_RX_80211HDR_OFF ((UINT16)14) +#define HFA384x_RX_DATA_OFF ((UINT16)60) + +/*-- Status Fields --*/ +#define HFA384x_RXSTATUS_MSGTYPE ((UINT16)(BIT15 | BIT14 | BIT13)) +#define HFA384x_RXSTATUS_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) +#define HFA384x_RXSTATUS_UNDECR ((UINT16)BIT1) +#define HFA384x_RXSTATUS_FCSERR ((UINT16)BIT0) +/*-------------------------------------------------------------------- +Communication Frames: Test/Get/Set Field Values for Receive Frames +--------------------------------------------------------------------*/ +#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13)) +#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((UINT16)(((UINT16)(value)) << 13)) +#define HFA384x_RXSTATUS_MACPORT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8)) +#define HFA384x_RXSTATUS_MACPORT_SET(value) ((UINT16)(((UINT16)(value)) << 8)) +#define HFA384x_RXSTATUS_ISUNDECR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_UNDECR)) +#define HFA384x_RXSTATUS_ISFCSERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_FCSERR)) +/*-------------------------------------------------------------------- + FRAME STRUCTURES: Information Types and Information Frame Structures +---------------------------------------------------------------------- +Information Types +--------------------------------------------------------------------*/ +#define HFA384x_IT_HANDOVERADDR ((UINT16)0xF000UL) +#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((UINT16)0xF001UL)//AP 1.3.7 +#define HFA384x_IT_COMMTALLIES ((UINT16)0xF100UL) +#define HFA384x_IT_SCANRESULTS ((UINT16)0xF101UL) +#define HFA384x_IT_CHINFORESULTS ((UINT16)0xF102UL) +#define HFA384x_IT_HOSTSCANRESULTS ((UINT16)0xF103UL) +#define HFA384x_IT_LINKSTATUS ((UINT16)0xF200UL) +#define HFA384x_IT_ASSOCSTATUS ((UINT16)0xF201UL) +#define HFA384x_IT_AUTHREQ ((UINT16)0xF202UL) +#define HFA384x_IT_PSUSERCNT ((UINT16)0xF203UL) +#define HFA384x_IT_KEYIDCHANGED ((UINT16)0xF204UL) +#define HFA384x_IT_ASSOCREQ ((UINT16)0xF205UL) +#define HFA384x_IT_MICFAILURE ((UINT16)0xF206UL) + +/*-------------------------------------------------------------------- +Information Frames Structures +---------------------------------------------------------------------- +Information Frames: Notification Frame Structures +--------------------------------------------------------------------*/ +/*-- Notification Frame,MAC Mgmt: Handover Address --*/ +typedef struct hfa384x_HandoverAddr +{ + UINT16 framelen; + UINT16 infotype; + UINT8 handover_addr[WLAN_BSSID_LEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_HandoverAddr_t; + +/*-- Inquiry Frame, Diagnose: Communication Tallies --*/ +typedef struct hfa384x_CommTallies16 +{ + UINT16 txunicastframes; + UINT16 txmulticastframes; + UINT16 txfragments; + UINT16 txunicastoctets; + UINT16 txmulticastoctets; + UINT16 txdeferredtrans; + UINT16 txsingleretryframes; + UINT16 txmultipleretryframes; + UINT16 txretrylimitexceeded; + UINT16 txdiscards; + UINT16 rxunicastframes; + UINT16 rxmulticastframes; + UINT16 rxfragments; + UINT16 rxunicastoctets; + UINT16 rxmulticastoctets; + UINT16 rxfcserrors; + UINT16 rxdiscardsnobuffer; + UINT16 txdiscardswrongsa; + UINT16 rxdiscardswepundecr; + UINT16 rxmsginmsgfrag; + UINT16 rxmsginbadmsgfrag; +} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies16_t; + +typedef struct hfa384x_CommTallies32 +{ + UINT32 txunicastframes; + UINT32 txmulticastframes; + UINT32 txfragments; + UINT32 txunicastoctets; + UINT32 txmulticastoctets; + UINT32 txdeferredtrans; + UINT32 txsingleretryframes; + UINT32 txmultipleretryframes; + UINT32 txretrylimitexceeded; + UINT32 txdiscards; + UINT32 rxunicastframes; + UINT32 rxmulticastframes; + UINT32 rxfragments; + UINT32 rxunicastoctets; + UINT32 rxmulticastoctets; + UINT32 rxfcserrors; + UINT32 rxdiscardsnobuffer; + UINT32 txdiscardswrongsa; + UINT32 rxdiscardswepundecr; + UINT32 rxmsginmsgfrag; + UINT32 rxmsginbadmsgfrag; +} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies32_t; + +/*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ +typedef struct hfa384x_ScanResultSub +{ + UINT16 chid; + UINT16 anl; + UINT16 sl; + UINT8 bssid[WLAN_BSSID_LEN]; + UINT16 bcnint; + UINT16 capinfo; + hfa384x_bytestr32_t ssid; + UINT8 supprates[10]; /* 802.11 info element */ + UINT16 proberesp_rate; +} __WLAN_ATTRIB_PACK__ hfa384x_ScanResultSub_t; + +typedef struct hfa384x_ScanResult +{ + UINT16 rsvd; + UINT16 scanreason; + hfa384x_ScanResultSub_t + result[HFA384x_SCANRESULT_MAX]; +} __WLAN_ATTRIB_PACK__ hfa384x_ScanResult_t; + +/*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ +typedef struct hfa384x_ChInfoResultSub +{ + UINT16 chid; + UINT16 anl; + UINT16 pnl; + UINT16 active; +} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResultSub_t; + +#define HFA384x_CHINFORESULT_BSSACTIVE BIT0 +#define HFA384x_CHINFORESULT_PCFACTIVE BIT1 + +typedef struct hfa384x_ChInfoResult +{ + UINT16 scanchannels; + hfa384x_ChInfoResultSub_t + result[HFA384x_CHINFORESULT_MAX]; +} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResult_t; + +/*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ +typedef struct hfa384x_HScanResultSub +{ + UINT16 chid; + UINT16 anl; + UINT16 sl; + UINT8 bssid[WLAN_BSSID_LEN]; + UINT16 bcnint; + UINT16 capinfo; + hfa384x_bytestr32_t ssid; + UINT8 supprates[10]; /* 802.11 info element */ + UINT16 proberesp_rate; + UINT16 atim; +} __WLAN_ATTRIB_PACK__ hfa384x_HScanResultSub_t; + +typedef struct hfa384x_HScanResult +{ + UINT16 nresult; + UINT16 rsvd; + hfa384x_HScanResultSub_t + result[HFA384x_HSCANRESULT_MAX]; +} __WLAN_ATTRIB_PACK__ hfa384x_HScanResult_t; + +/*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ + +#define HFA384x_LINK_NOTCONNECTED ((UINT16)0) +#define HFA384x_LINK_CONNECTED ((UINT16)1) +#define HFA384x_LINK_DISCONNECTED ((UINT16)2) +#define HFA384x_LINK_AP_CHANGE ((UINT16)3) +#define HFA384x_LINK_AP_OUTOFRANGE ((UINT16)4) +#define HFA384x_LINK_AP_INRANGE ((UINT16)5) +#define HFA384x_LINK_ASSOCFAIL ((UINT16)6) + +typedef struct hfa384x_LinkStatus +{ + UINT16 linkstatus; +} __WLAN_ATTRIB_PACK__ hfa384x_LinkStatus_t; + + +/*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/ + +#define HFA384x_ASSOCSTATUS_STAASSOC ((UINT16)1) +#define HFA384x_ASSOCSTATUS_REASSOC ((UINT16)2) +#define HFA384x_ASSOCSTATUS_DISASSOC ((UINT16)3) +#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((UINT16)4) +#define HFA384x_ASSOCSTATUS_AUTHFAIL ((UINT16)5) + +typedef struct hfa384x_AssocStatus +{ + UINT16 assocstatus; + UINT8 sta_addr[WLAN_ADDR_LEN]; + /* old_ap_addr is only valid if assocstatus == 2 */ + UINT8 old_ap_addr[WLAN_ADDR_LEN]; + UINT16 reason; + UINT16 reserved; +} __WLAN_ATTRIB_PACK__ hfa384x_AssocStatus_t; + +/*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ + +typedef struct hfa384x_AuthRequest +{ + UINT8 sta_addr[WLAN_ADDR_LEN]; + UINT16 algorithm; +} __WLAN_ATTRIB_PACK__ hfa384x_AuthReq_t; + +/*-- Unsolicited Frame, MAC Mgmt: AssocRequest (AP Only) --*/ + +typedef struct hfa384x_AssocRequest +{ + UINT8 sta_addr[WLAN_ADDR_LEN]; + UINT16 type; + UINT8 wpa_data[80]; +} __WLAN_ATTRIB_PACK__ hfa384x_AssocReq_t; + + +#define HFA384x_ASSOCREQ_TYPE_ASSOC 0 +#define HFA384x_ASSOCREQ_TYPE_REASSOC 1 + +/*-- Unsolicited Frame, MAC Mgmt: MIC Failure (AP Only) --*/ + +typedef struct hfa384x_MicFailure +{ + UINT8 sender[WLAN_ADDR_LEN]; + UINT8 dest[WLAN_ADDR_LEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_MicFailure_t; + +/*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ + +typedef struct hfa384x_PSUserCount +{ + UINT16 usercnt; +} __WLAN_ATTRIB_PACK__ hfa384x_PSUserCount_t; + +typedef struct hfa384x_KeyIDChanged +{ + UINT8 sta_addr[WLAN_ADDR_LEN]; + UINT16 keyid; +} __WLAN_ATTRIB_PACK__ hfa384x_KeyIDChanged_t; + +/*-- Collection of all Inf frames ---------------*/ +typedef union hfa384x_infodata { + hfa384x_CommTallies16_t commtallies16; + hfa384x_CommTallies32_t commtallies32; + hfa384x_ScanResult_t scanresult; + hfa384x_ChInfoResult_t chinforesult; + hfa384x_HScanResult_t hscanresult; + hfa384x_LinkStatus_t linkstatus; + hfa384x_AssocStatus_t assocstatus; + hfa384x_AuthReq_t authreq; + hfa384x_PSUserCount_t psusercnt; + hfa384x_KeyIDChanged_t keyidchanged; +} __WLAN_ATTRIB_PACK__ hfa384x_infodata_t; + +typedef struct hfa384x_InfFrame +{ + UINT16 framelen; + UINT16 infotype; + hfa384x_infodata_t info; +} __WLAN_ATTRIB_PACK__ hfa384x_InfFrame_t; + +#if (WLAN_HOSTIF == WLAN_USB) +/*-------------------------------------------------------------------- +USB Packet structures and constants. +--------------------------------------------------------------------*/ + +/* Should be sent to the ctrlout endpoint */ +#define HFA384x_USB_ENBULKIN 6 + +/* Should be sent to the bulkout endpoint */ +#define HFA384x_USB_TXFRM 0 +#define HFA384x_USB_CMDREQ 1 +#define HFA384x_USB_WRIDREQ 2 +#define HFA384x_USB_RRIDREQ 3 +#define HFA384x_USB_WMEMREQ 4 +#define HFA384x_USB_RMEMREQ 5 + +/* Received from the bulkin endpoint */ +#define HFA384x_USB_ISFRM(a) (!((a) & 0x8000)) +#define HFA384x_USB_ISTXFRM(a) (((a) & 0x9000) == 0x1000) +#define HFA384x_USB_ISRXFRM(a) (!((a) & 0x9000)) +#define HFA384x_USB_INFOFRM 0x8000 +#define HFA384x_USB_CMDRESP 0x8001 +#define HFA384x_USB_WRIDRESP 0x8002 +#define HFA384x_USB_RRIDRESP 0x8003 +#define HFA384x_USB_WMEMRESP 0x8004 +#define HFA384x_USB_RMEMRESP 0x8005 +#define HFA384x_USB_BUFAVAIL 0x8006 +#define HFA384x_USB_ERROR 0x8007 + +/*------------------------------------*/ +/* Request (bulk OUT) packet contents */ + +typedef struct hfa384x_usb_txfrm { + hfa384x_tx_frame_t desc; + UINT8 data[WLAN_DATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_txfrm_t; + +typedef struct hfa384x_usb_cmdreq { + UINT16 type; + UINT16 cmd; + UINT16 parm0; + UINT16 parm1; + UINT16 parm2; + UINT8 pad[54]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdreq_t; + +typedef struct hfa384x_usb_wridreq { + UINT16 type; + UINT16 frmlen; + UINT16 rid; + UINT8 data[HFA384x_RIDDATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_wridreq_t; + +typedef struct hfa384x_usb_rridreq { + UINT16 type; + UINT16 frmlen; + UINT16 rid; + UINT8 pad[58]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridreq_t; + +typedef struct hfa384x_usb_wmemreq { + UINT16 type; + UINT16 frmlen; + UINT16 offset; + UINT16 page; + UINT8 data[HFA384x_USB_RWMEM_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_wmemreq_t; + +typedef struct hfa384x_usb_rmemreq { + UINT16 type; + UINT16 frmlen; + UINT16 offset; + UINT16 page; + UINT8 pad[56]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemreq_t; + +/*------------------------------------*/ +/* Response (bulk IN) packet contents */ + +typedef struct hfa384x_usb_rxfrm { + hfa384x_rx_frame_t desc; + UINT8 data[WLAN_DATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rxfrm_t; + +typedef struct hfa384x_usb_infofrm { + UINT16 type; + hfa384x_InfFrame_t info; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_infofrm_t; + +typedef struct hfa384x_usb_statusresp { + UINT16 type; + UINT16 status; + UINT16 resp0; + UINT16 resp1; + UINT16 resp2; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdresp_t; + +typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t; + +typedef struct hfa384x_usb_rridresp { + UINT16 type; + UINT16 frmlen; + UINT16 rid; + UINT8 data[HFA384x_RIDDATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridresp_t; + +typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t; + +typedef struct hfa384x_usb_rmemresp { + UINT16 type; + UINT16 frmlen; + UINT8 data[HFA384x_USB_RWMEM_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemresp_t; + +typedef struct hfa384x_usb_bufavail { + UINT16 type; + UINT16 frmlen; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_bufavail_t; + +typedef struct hfa384x_usb_error { + UINT16 type; + UINT16 errortype; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_error_t; + +/*----------------------------------------------------------*/ +/* Unions for packaging all the known packet types together */ + +typedef union hfa384x_usbout { + UINT16 type; + hfa384x_usb_txfrm_t txfrm; + hfa384x_usb_cmdreq_t cmdreq; + hfa384x_usb_wridreq_t wridreq; + hfa384x_usb_rridreq_t rridreq; + hfa384x_usb_wmemreq_t wmemreq; + hfa384x_usb_rmemreq_t rmemreq; +} __WLAN_ATTRIB_PACK__ hfa384x_usbout_t; + +typedef union hfa384x_usbin { + UINT16 type; + hfa384x_usb_rxfrm_t rxfrm; + hfa384x_usb_txfrm_t txfrm; + hfa384x_usb_infofrm_t infofrm; + hfa384x_usb_cmdresp_t cmdresp; + hfa384x_usb_wridresp_t wridresp; + hfa384x_usb_rridresp_t rridresp; + hfa384x_usb_wmemresp_t wmemresp; + hfa384x_usb_rmemresp_t rmemresp; + hfa384x_usb_bufavail_t bufavail; + hfa384x_usb_error_t usberror; + UINT8 boguspad[3000]; +} __WLAN_ATTRIB_PACK__ hfa384x_usbin_t; + +#endif /* WLAN_USB */ + +/*-------------------------------------------------------------------- +PD record structures. +--------------------------------------------------------------------*/ + +typedef struct hfa384x_pdr_pcb_partnum +{ + UINT8 num[8]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_partnum_t; + +typedef struct hfa384x_pdr_pcb_tracenum +{ + UINT8 num[8]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_tracenum_t; + +typedef struct hfa384x_pdr_nic_serial +{ + UINT8 num[12]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_serial_t; + +typedef struct hfa384x_pdr_mkk_measurements +{ + double carrier_freq; + double occupied_band; + double power_density; + double tx_spur_f1; + double tx_spur_f2; + double tx_spur_f3; + double tx_spur_f4; + double tx_spur_l1; + double tx_spur_l2; + double tx_spur_l3; + double tx_spur_l4; + double rx_spur_f1; + double rx_spur_f2; + double rx_spur_l1; + double rx_spur_l2; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_measurements_t; + +typedef struct hfa384x_pdr_nic_ramsize +{ + UINT8 size[12]; /* units of KB */ +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_ramsize_t; + +typedef struct hfa384x_pdr_mfisuprange +{ + UINT16 id; + UINT16 variant; + UINT16 bottom; + UINT16 top; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mfisuprange_t; + +typedef struct hfa384x_pdr_cfisuprange +{ + UINT16 id; + UINT16 variant; + UINT16 bottom; + UINT16 top; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_cfisuprange_t; + +typedef struct hfa384x_pdr_nicid +{ + UINT16 id; + UINT16 variant; + UINT16 major; + UINT16 minor; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nicid_t; + + +typedef struct hfa384x_pdr_refdac_measurements +{ + UINT16 value[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_measurements_t; + +typedef struct hfa384x_pdr_vgdac_measurements +{ + UINT16 value[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_measurements_t; + +typedef struct hfa384x_pdr_level_comp_measurements +{ + UINT16 value[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_compc_measurements_t; + +typedef struct hfa384x_pdr_mac_address +{ + UINT8 addr[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mac_address_t; + +typedef struct hfa384x_pdr_mkk_callname +{ + UINT8 callname[8]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_callname_t; + +typedef struct hfa384x_pdr_regdomain +{ + UINT16 numdomains; + UINT16 domain[5]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_regdomain_t; + +typedef struct hfa384x_pdr_allowed_channel +{ + UINT16 ch_bitmap; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_allowed_channel_t; + +typedef struct hfa384x_pdr_default_channel +{ + UINT16 channel; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_default_channel_t; + +typedef struct hfa384x_pdr_privacy_option +{ + UINT16 available; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_privacy_option_t; + +typedef struct hfa384x_pdr_temptype +{ + UINT16 type; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_temptype_t; + +typedef struct hfa384x_pdr_refdac_setup +{ + UINT16 ch_value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_setup_t; + +typedef struct hfa384x_pdr_vgdac_setup +{ + UINT16 ch_value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_setup_t; + +typedef struct hfa384x_pdr_level_comp_setup +{ + UINT16 ch_value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_comp_setup_t; + +typedef struct hfa384x_pdr_trimdac_setup +{ + UINT16 trimidac; + UINT16 trimqdac; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_trimdac_setup_t; + +typedef struct hfa384x_pdr_ifr_setting +{ + UINT16 value[3]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_ifr_setting_t; + +typedef struct hfa384x_pdr_rfr_setting +{ + UINT16 value[3]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_rfr_setting_t; + +typedef struct hfa384x_pdr_hfa3861_baseline +{ + UINT16 value[50]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_baseline_t; + +typedef struct hfa384x_pdr_hfa3861_shadow +{ + UINT32 value[32]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_shadow_t; + +typedef struct hfa384x_pdr_hfa3861_ifrf +{ + UINT32 value[20]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_ifrf_t; + +typedef struct hfa384x_pdr_hfa3861_chcalsp +{ + UINT16 value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcalsp_t; + +typedef struct hfa384x_pdr_hfa3861_chcali +{ + UINT16 value[17]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcali_t; + +typedef struct hfa384x_pdr_hfa3861_nic_config +{ + UINT16 config_bitmap; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_config_t; + +typedef struct hfa384x_pdr_hfo_delay +{ + UINT8 hfo_delay; +} __WLAN_ATTRIB_PACK__ hfa384x_hfo_delay_t; + +typedef struct hfa384x_pdr_hfa3861_manf_testsp +{ + UINT16 value[30]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testsp_t; + +typedef struct hfa384x_pdr_hfa3861_manf_testi +{ + UINT16 value[30]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testi_t; + +typedef struct hfa384x_end_of_pda +{ + UINT16 crc; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_end_of_pda_t; + +typedef struct hfa384x_pdrec +{ + UINT16 len; /* in words */ + UINT16 code; + union pdr { + hfa384x_pdr_pcb_partnum_t pcb_partnum; + hfa384x_pdr_pcb_tracenum_t pcb_tracenum; + hfa384x_pdr_nic_serial_t nic_serial; + hfa384x_pdr_mkk_measurements_t mkk_measurements; + hfa384x_pdr_nic_ramsize_t nic_ramsize; + hfa384x_pdr_mfisuprange_t mfisuprange; + hfa384x_pdr_cfisuprange_t cfisuprange; + hfa384x_pdr_nicid_t nicid; + hfa384x_pdr_refdac_measurements_t refdac_measurements; + hfa384x_pdr_vgdac_measurements_t vgdac_measurements; + hfa384x_pdr_level_compc_measurements_t level_compc_measurements; + hfa384x_pdr_mac_address_t mac_address; + hfa384x_pdr_mkk_callname_t mkk_callname; + hfa384x_pdr_regdomain_t regdomain; + hfa384x_pdr_allowed_channel_t allowed_channel; + hfa384x_pdr_default_channel_t default_channel; + hfa384x_pdr_privacy_option_t privacy_option; + hfa384x_pdr_temptype_t temptype; + hfa384x_pdr_refdac_setup_t refdac_setup; + hfa384x_pdr_vgdac_setup_t vgdac_setup; + hfa384x_pdr_level_comp_setup_t level_comp_setup; + hfa384x_pdr_trimdac_setup_t trimdac_setup; + hfa384x_pdr_ifr_setting_t ifr_setting; + hfa384x_pdr_rfr_setting_t rfr_setting; + hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; + hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; + hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; + hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; + hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; + hfa384x_pdr_nic_config_t nic_config; + hfa384x_hfo_delay_t hfo_delay; + hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; + hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; + hfa384x_pdr_end_of_pda_t end_of_pda; + + } data; +} __WLAN_ATTRIB_PACK__ hfa384x_pdrec_t; + + +#ifdef __KERNEL__ +/*-------------------------------------------------------------------- +--- MAC state structure, argument to all functions -- +--- Also, a collection of support types -- +--------------------------------------------------------------------*/ +typedef struct hfa384x_statusresult +{ + UINT16 status; + UINT16 resp0; + UINT16 resp1; + UINT16 resp2; +} hfa384x_cmdresult_t; + +#if (WLAN_HOSTIF == WLAN_USB) + +/* USB Control Exchange (CTLX): + * A queue of the structure below is maintained for all of the + * Request/Response type USB packets supported by Prism2. + */ +/* The following hfa384x_* structures are arguments to + * the usercb() for the different CTLX types. + */ +typedef hfa384x_cmdresult_t hfa384x_wridresult_t; +typedef hfa384x_cmdresult_t hfa384x_wmemresult_t; + +typedef struct hfa384x_rridresult +{ + UINT16 rid; + const void *riddata; + UINT riddata_len; +} hfa384x_rridresult_t; + +enum ctlx_state { + CTLX_START = 0, /* Start state, not queued */ + + CTLX_COMPLETE, /* CTLX successfully completed */ + CTLX_REQ_FAILED, /* OUT URB completed w/ error */ + + CTLX_PENDING, /* Queued, data valid */ + CTLX_REQ_SUBMITTED, /* OUT URB submitted */ + CTLX_REQ_COMPLETE, /* OUT URB complete */ + CTLX_RESP_COMPLETE /* IN URB received */ +}; +typedef enum ctlx_state CTLX_STATE; + +struct hfa384x_usbctlx; +struct hfa384x; + +typedef void (*ctlx_cmdcb_t)( struct hfa384x*, const struct hfa384x_usbctlx* ); + +typedef void (*ctlx_usercb_t)( + struct hfa384x *hw, + void *ctlxresult, + void *usercb_data); + +typedef struct hfa384x_usbctlx +{ + struct list_head list; + + size_t outbufsize; + hfa384x_usbout_t outbuf; /* pkt buf for OUT */ + hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */ + + CTLX_STATE state; /* Tracks running state */ + + struct completion done; + volatile int reapable; /* Food for the reaper task */ + + ctlx_cmdcb_t cmdcb; /* Async command callback */ + ctlx_usercb_t usercb; /* Async user callback, */ + void *usercb_data; /* at CTLX completion */ + + int variant; /* Identifies cmd variant */ +} hfa384x_usbctlx_t; + +typedef struct hfa384x_usbctlxq +{ + spinlock_t lock; + struct list_head pending; + struct list_head active; + struct list_head completing; + struct list_head reapable; +} hfa384x_usbctlxq_t; +#endif + +typedef struct hfa484x_metacmd +{ + UINT16 cmd; + + UINT16 parm0; + UINT16 parm1; + UINT16 parm2; + +#if 0 //XXX cmd irq stuff + UINT16 bulkid; /* what RID/FID to copy down. */ + int bulklen; /* how much to copy from BAP */ + char *bulkdata; /* And to where? */ +#endif + + hfa384x_cmdresult_t result; +} hfa384x_metacmd_t; + +#define MAX_PRISM2_GRP_ADDR 16 +#define MAX_GRP_ADDR 32 +#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */ + +#define MM_SAT_PCF (BIT14) +#define MM_GCSD_PCF (BIT15) +#define MM_GCSD_PCF_EB (BIT14 | BIT15) + +#define WLAN_STATE_STOPPED 0 /* Network is not active. */ +#define WLAN_STATE_STARTED 1 /* Network has been started. */ + +#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */ +#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */ +#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */ +#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */ +#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */ +#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */ + +/* XXX These are going away ASAP */ +typedef struct prism2sta_authlist +{ + UINT cnt; + UINT8 addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN]; + UINT8 assoc[WLAN_AUTH_MAX]; +} prism2sta_authlist_t; + +typedef struct prism2sta_accesslist +{ + UINT modify; + UINT cnt; + UINT8 addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; + UINT cnt1; + UINT8 addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; +} prism2sta_accesslist_t; + +typedef struct hfa384x +{ +#if (WLAN_HOSTIF != WLAN_USB) + /* Resource config */ + UINT32 iobase; + char __iomem *membase; + UINT32 irq; +#else + /* USB support data */ + struct usb_device *usb; + struct urb rx_urb; + struct sk_buff *rx_urb_skb; + struct urb tx_urb; + struct urb ctlx_urb; + hfa384x_usbout_t txbuff; + hfa384x_usbctlxq_t ctlxq; + struct timer_list reqtimer; + struct timer_list resptimer; + + struct timer_list throttle; + + struct tasklet_struct reaper_bh; + struct tasklet_struct completion_bh; + + struct work_struct usb_work; + + unsigned long usb_flags; +#define THROTTLE_RX 0 +#define THROTTLE_TX 1 +#define WORK_RX_HALT 2 +#define WORK_TX_HALT 3 +#define WORK_RX_RESUME 4 +#define WORK_TX_RESUME 5 + + unsigned short req_timer_done:1; + unsigned short resp_timer_done:1; + + int endp_in; + int endp_out; +#endif /* !USB */ + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + struct pcmcia_device *pdev; +#else + dev_link_t *link; +#endif + dev_node_t node; +#endif + + int sniff_fcs; + int sniff_channel; + int sniff_truncate; + int sniffhdr; + + wait_queue_head_t cmdq; /* wait queue itself */ + + /* Controller state */ + UINT32 state; + UINT32 isap; + UINT8 port_enabled[HFA384x_NUMPORTS_MAX]; +#if (WLAN_HOSTIF != WLAN_USB) + UINT auxen; + UINT isram16; +#endif /* !USB */ + + /* Download support */ + UINT dlstate; + hfa384x_downloadbuffer_t bufinfo; + UINT16 dltimeout; + +#if (WLAN_HOSTIF != WLAN_USB) + spinlock_t cmdlock; + volatile int cmdflag; /* wait queue flag */ + hfa384x_metacmd_t *cmddata; /* for our async callback */ + + /* BAP support */ + spinlock_t baplock; + struct tasklet_struct bap_tasklet; + + /* MAC buffer ids */ + UINT16 txfid_head; + UINT16 txfid_tail; + UINT txfid_N; + UINT16 txfid_queue[HFA384x_DRVR_FIDSTACKLEN_MAX]; + UINT16 infofid; + struct semaphore infofid_sem; +#endif /* !USB */ + + int scanflag; /* to signal scan comlete */ + int join_ap; /* are we joined to a specific ap */ + int join_retries; /* number of join retries till we fail */ + hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ + + wlandevice_t *wlandev; + /* Timer to allow for the deferred processing of linkstatus messages */ + struct work_struct link_bh; + + struct work_struct commsqual_bh; + hfa384x_commsquality_t qual; + struct timer_list commsqual_timer; + + UINT16 link_status; + UINT16 link_status_new; + struct sk_buff_head authq; + + /* And here we have stuff that used to be in priv */ + + /* State variables */ + UINT presniff_port_type; + UINT16 presniff_wepflags; + UINT32 dot11_desired_bss_type; + int ap; /* AP flag: 0 - Station, 1 - Access Point. */ + + int dbmadjust; + + /* Group Addresses - right now, there are up to a total + of MAX_GRP_ADDR group addresses */ + UINT8 dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN]; + UINT dot11_grpcnt; + + /* Component Identities */ + hfa384x_compident_t ident_nic; + hfa384x_compident_t ident_pri_fw; + hfa384x_compident_t ident_sta_fw; + hfa384x_compident_t ident_ap_fw; + UINT16 mm_mods; + + /* Supplier compatibility ranges */ + hfa384x_caplevel_t cap_sup_mfi; + hfa384x_caplevel_t cap_sup_cfi; + hfa384x_caplevel_t cap_sup_pri; + hfa384x_caplevel_t cap_sup_sta; + hfa384x_caplevel_t cap_sup_ap; + + /* Actor compatibility ranges */ + hfa384x_caplevel_t cap_act_pri_cfi; /* pri f/w to controller interface */ + hfa384x_caplevel_t cap_act_sta_cfi; /* sta f/w to controller interface */ + hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */ + hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */ + hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */ + + UINT32 psusercount; /* Power save user count. */ + hfa384x_CommTallies32_t tallies; /* Communication tallies. */ + UINT8 comment[WLAN_COMMENT_MAX+1]; /* User comment */ + + /* Channel Info request results (AP only) */ + struct { + atomic_t done; + UINT8 count; + hfa384x_ChInfoResult_t results; + } channel_info; + + hfa384x_InfFrame_t *scanresults; + + + prism2sta_authlist_t authlist; /* Authenticated station list. */ + UINT accessmode; /* Access mode. */ + prism2sta_accesslist_t allow; /* Allowed station list. */ + prism2sta_accesslist_t deny; /* Denied station list. */ + +} hfa384x_t; + +/*=============================================================*/ +/*--- Function Declarations -----------------------------------*/ +/*=============================================================*/ +#if (WLAN_HOSTIF == WLAN_USB) +void +hfa384x_create( + hfa384x_t *hw, + struct usb_device *usb); +#else +void +hfa384x_create( + hfa384x_t *hw, + UINT irq, + UINT32 iobase, + UINT8 __iomem *membase); +#endif + +void hfa384x_destroy(hfa384x_t *hw); + +irqreturn_t +hfa384x_interrupt(int irq, void *dev_id PT_REGS); +int +hfa384x_corereset( hfa384x_t *hw, int holdtime, int settletime, int genesis); +int +hfa384x_drvr_chinforesults( hfa384x_t *hw); +int +hfa384x_drvr_commtallies( hfa384x_t *hw); +int +hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_drvr_flashdl_enable(hfa384x_t *hw); +int +hfa384x_drvr_flashdl_disable(hfa384x_t *hw); +int +hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len); +int +hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len); +int +hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr); +int +hfa384x_drvr_hostscanresults( hfa384x_t *hw); +int +hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd); +int +hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 address, UINT32 *result); +int +hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 address, UINT32 data); +int +hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr); +int +hfa384x_drvr_ramdl_disable(hfa384x_t *hw); +int +hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len); +int +hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len); +int +hfa384x_drvr_scanresults( hfa384x_t *hw); + +int +hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len); + +static inline int +hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val) +{ + int result = 0; + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16)); + if ( result == 0 ) { + *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val)); + } + return result; +} + +static inline int +hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val) +{ + int result = 0; + + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32)); + if ( result == 0 ) { + *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val)); + } + + return result; +} + +static inline int +hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 val) +{ + UINT16 value = host2hfa384x_16(val); + return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); +} + +static inline int +hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 val) +{ + UINT32 value = host2hfa384x_32(val); + return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); +} + +#if (WLAN_HOSTIF == WLAN_USB) +int +hfa384x_drvr_getconfig_async(hfa384x_t *hw, + UINT16 rid, + ctlx_usercb_t usercb, + void *usercb_data); + +int +hfa384x_drvr_setconfig_async(hfa384x_t *hw, + UINT16 rid, + void *buf, + UINT16 len, + ctlx_usercb_t usercb, + void *usercb_data); +#else +static inline int +hfa384x_drvr_setconfig_async(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len, + void *ptr1, void *ptr2) +{ + (void)ptr1; + (void)ptr2; + return hfa384x_drvr_setconfig(hw, rid, buf, len); +} +#endif + +static inline int +hfa384x_drvr_setconfig16_async(hfa384x_t *hw, UINT16 rid, UINT16 val) +{ + UINT16 value = host2hfa384x_16(val); + return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), + NULL , NULL); +} + +static inline int +hfa384x_drvr_setconfig32_async(hfa384x_t *hw, UINT16 rid, UINT32 val) +{ + UINT32 value = host2hfa384x_32(val); + return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), + NULL , NULL); +} + + +int +hfa384x_drvr_start(hfa384x_t *hw); +int +hfa384x_drvr_stop(hfa384x_t *hw); +int +hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); +void +hfa384x_tx_timeout(wlandevice_t *wlandev); + +int +hfa384x_cmd_initialize(hfa384x_t *hw); +int +hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_cmd_diagnose(hfa384x_t *hw); +int +hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len); +int +hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid); +int +hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid); +int +hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, void *buf, UINT16 len); +int +hfa384x_cmd_inquire(hfa384x_t *hw, UINT16 fid); +int +hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, void *buf, UINT16 len); +int +hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable); +int +hfa384x_cmd_download( + hfa384x_t *hw, + UINT16 mode, + UINT16 lowaddr, + UINT16 highaddr, + UINT16 codelen); +int +hfa384x_cmd_aux_enable(hfa384x_t *hw, int force); +int +hfa384x_cmd_aux_disable(hfa384x_t *hw); +int +hfa384x_copy_from_bap( + hfa384x_t *hw, + UINT16 bap, + UINT16 id, + UINT16 offset, + void *buf, + UINT len); +int +hfa384x_copy_to_bap( + hfa384x_t *hw, + UINT16 bap, + UINT16 id, + UINT16 offset, + void *buf, + UINT len); +void +hfa384x_copy_from_aux( + hfa384x_t *hw, + UINT32 cardaddr, + UINT32 auxctl, + void *buf, + UINT len); +void +hfa384x_copy_to_aux( + hfa384x_t *hw, + UINT32 cardaddr, + UINT32 auxctl, + void *buf, + UINT len); + +#if (WLAN_HOSTIF != WLAN_USB) + +/* + HFA384x is a LITTLE ENDIAN part. + + the get/setreg functions implicitly byte-swap the data to LE. + the _noswap variants do not perform a byte-swap on the data. +*/ + +static inline UINT16 +__hfa384x_getreg(hfa384x_t *hw, UINT reg); + +static inline void +__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg); + +static inline UINT16 +__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg); + +static inline void +__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg); + +#ifdef REVERSE_ENDIAN +#define hfa384x_getreg __hfa384x_getreg_noswap +#define hfa384x_setreg __hfa384x_setreg_noswap +#define hfa384x_getreg_noswap __hfa384x_getreg +#define hfa384x_setreg_noswap __hfa384x_setreg +#else +#define hfa384x_getreg __hfa384x_getreg +#define hfa384x_setreg __hfa384x_setreg +#define hfa384x_getreg_noswap __hfa384x_getreg_noswap +#define hfa384x_setreg_noswap __hfa384x_setreg_noswap +#endif + +/*---------------------------------------------------------------- +* hfa384x_getreg +* +* Retrieve the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* NOTE: This function returns the value in HOST ORDER!!!!!! +* +* Arguments: +* hw MAC part structure +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Value from the register in HOST ORDER!!!! +----------------------------------------------------------------*/ +static inline UINT16 +__hfa384x_getreg(hfa384x_t *hw, UINT reg) +{ +/* printk(KERN_DEBUG "Reading from 0x%0x\n", hw->membase + reg); */ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + return wlan_inw_le16_to_cpu(hw->iobase+reg); +#elif (WLAN_HOSTIF == WLAN_PCI) + return __le16_to_cpu(readw(hw->membase + reg)); +#endif +} + +/*---------------------------------------------------------------- +* hfa384x_setreg +* +* Set the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* NOTE: This function assumes the value is in HOST ORDER!!!!!! +* +* Arguments: +* hw MAC part structure +* val Value, in HOST ORDER!!, to put in the register +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Nothing +----------------------------------------------------------------*/ +static inline void +__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg) +{ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + wlan_outw_cpu_to_le16( val, hw->iobase + reg); + return; +#elif (WLAN_HOSTIF == WLAN_PCI) + writew(__cpu_to_le16(val), hw->membase + reg); + return; +#endif +} + + +/*---------------------------------------------------------------- +* hfa384x_getreg_noswap +* +* Retrieve the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* +* Arguments: +* hw MAC part structure +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Value from the register. +----------------------------------------------------------------*/ +static inline UINT16 +__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg) +{ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + return wlan_inw(hw->iobase+reg); +#elif (WLAN_HOSTIF == WLAN_PCI) + return readw(hw->membase + reg); +#endif +} + + +/*---------------------------------------------------------------- +* hfa384x_setreg_noswap +* +* Set the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* +* Arguments: +* hw MAC part structure +* val Value to put in the register +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Nothing +----------------------------------------------------------------*/ +static inline void +__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg) +{ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + wlan_outw( val, hw->iobase + reg); + return; +#elif (WLAN_HOSTIF == WLAN_PCI) + writew(val, hw->membase + reg); + return; +#endif +} + + +static inline void hfa384x_events_all(hfa384x_t *hw) +{ + hfa384x_setreg(hw, + HFA384x_INT_NORMAL +#ifdef CMD_IRQ + | HFA384x_INTEN_CMD_SET(1) +#endif + , + HFA384x_INTEN); + +} + +static inline void hfa384x_events_nobap(hfa384x_t *hw) +{ + hfa384x_setreg(hw, + (HFA384x_INT_NORMAL & ~HFA384x_INT_BAP_OP) +#ifdef CMD_IRQ + | HFA384x_INTEN_CMD_SET(1) +#endif + , + HFA384x_INTEN); + +} + +#endif /* WLAN_HOSTIF != WLAN_USB */ +#endif /* __KERNEL__ */ + +#endif /* _HFA384x_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/prism2_usb/prism2/prism2mgmt.h +++ linux-2.6.27/ubuntu/misc/wireless/prism2_usb/prism2/prism2mgmt.h @@ -0,0 +1,182 @@ +/* src/prism2/include/prism2/prism2mgmt.h +* +* Declares the mgmt command handler functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file contains the constants and data structures for interaction +* with the hfa384x Wireless LAN (WLAN) Media Access Contoller (MAC). +* The hfa384x is a portion of the Harris PRISM(tm) WLAN chipset. +* +* [Implementation and usage notes] +* +* [References] +* CW10 Programmer's Manual v1.5 +* IEEE 802.11 D10.0 +* +* -------------------------------------------------------------------- +*/ + +#ifndef _PRISM2MGMT_H +#define _PRISM2MGMT_H + + +/*=============================================================*/ +/*------ Constants --------------------------------------------*/ + +/*=============================================================*/ +/*------ Macros -----------------------------------------------*/ + +/*=============================================================*/ +/*------ Types and their related constants --------------------*/ + +/*=============================================================*/ +/*------ Static variable externs ------------------------------*/ + +#if (WLAN_HOSTIF != WLAN_USB) +extern int prism2_bap_timeout; +extern int prism2_irq_evread_max; +#endif +extern int prism2_debug; +extern int prism2_reset_holdtime; +extern int prism2_reset_settletime; +/*=============================================================*/ +/*--- Function Declarations -----------------------------------*/ +/*=============================================================*/ + +UINT32 +prism2sta_ifstate(wlandevice_t *wlandev, UINT32 ifstate); + +void +prism2sta_ev_dtim(wlandevice_t *wlandev); +void +prism2sta_ev_infdrop(wlandevice_t *wlandev); +void +prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +void +prism2sta_ev_txexc(wlandevice_t *wlandev, UINT16 status); +void +prism2sta_ev_tx(wlandevice_t *wlandev, UINT16 status); +void +prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb); +void +prism2sta_ev_alloc(wlandevice_t *wlandev); + + +int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_powermgmt(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_join(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_authenticate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_deauthenticate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_reassociate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_disassociate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_start(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mm_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_enable(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_channel_info(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_channel_info_results(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp); + +/*--------------------------------------------------------------- +* conversion functions going between wlan message data types and +* Prism2 data types +---------------------------------------------------------------*/ +/* byte area conversion functions*/ +void prism2mgmt_pstr2bytearea(UINT8 *bytearea, p80211pstrd_t *pstr); +void prism2mgmt_bytearea2pstr(UINT8 *bytearea, p80211pstrd_t *pstr, int len); + +/* byte string conversion functions*/ +void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); +void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); + +/* integer conversion functions */ +void prism2mgmt_prism2int2p80211int(UINT16 *prism2int, UINT32 *wlanint); +void prism2mgmt_p80211int2prism2int(UINT16 *prism2int, UINT32 *wlanint); + +/* enumerated integer conversion functions */ +void prism2mgmt_prism2enum2p80211enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid); +void prism2mgmt_p80211enum2prism2enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid); + +/* functions to convert a bit area to/from an Operational Rate Set */ +void prism2mgmt_get_oprateset(UINT16 *rate, p80211pstrd_t *pstr); +void prism2mgmt_set_oprateset(UINT16 *rate, p80211pstrd_t *pstr); + +/* functions to convert Group Addresses */ +void prism2mgmt_get_grpaddr(UINT32 did, + p80211pstrd_t *pstr, hfa384x_t *priv ); +int prism2mgmt_set_grpaddr(UINT32 did, + UINT8 *prism2buf, p80211pstrd_t *pstr, hfa384x_t *priv ); +int prism2mgmt_get_grpaddr_index( UINT32 did ); + +void prism2sta_processing_defer(struct work_struct *data); + +void prism2sta_commsqual_defer(struct work_struct *data); +void prism2sta_commsqual_timer(unsigned long data); + +/*=============================================================*/ +/*--- Inline Function Definitions (if supported) --------------*/ +/*=============================================================*/ + + + +#endif --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/p80211wep.c +++ linux-2.6.27/ubuntu/misc/wireless/p80211/p80211wep.c @@ -0,0 +1,317 @@ +/* src/p80211/p80211wep.c +* +* WEP encode/decode for P80211. +* +* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include + +#include +#include +#include +#include + +#include +#include + +// #define WEP_DEBUG + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + +#define SSWAP(a,b) {UINT8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;} +#define WEP_KEY(x) (((x) & 0xC0) >> 6) + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + +static const UINT32 wep_crc32_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; + +/*================================================================*/ +/* Local Function Declarations */ + +/*================================================================*/ +/* Function Definitions */ + +/* keylen in bytes! */ + +int wep_change_key(wlandevice_t *wlandev, int keynum, UINT8* key, int keylen) +{ + if (keylen < 0) return -1; + if (keylen >= MAX_KEYLEN) return -1; + if (key == NULL) return -1; + if (keynum < 0) return -1; + if (keynum >= NUM_WEPKEYS) return -1; + + +#ifdef WEP_DEBUG + printk(KERN_DEBUG "WEP key %d len %d = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]); +#endif + + wlandev->wep_keylens[keynum] = keylen; + memcpy(wlandev->wep_keys[keynum], key, keylen); + + return 0; +} + +/* + 4-byte IV at start of buffer, 4-byte ICV at end of buffer. + if successful, buf start is payload begin, length -= 8; + */ +int wep_decrypt(wlandevice_t *wlandev, UINT8 *buf, UINT32 len, int key_override, UINT8 *iv, UINT8 *icv) +{ + UINT32 i, j, k, crc, keylen; + UINT8 s[256], key[64], c_crc[4]; + UINT8 keyidx; + + /* Needs to be at least 8 bytes of payload */ + if (len <= 0) return -1; + + /* initialize the first bytes of the key from the IV */ + key[0] = iv[0]; + key[1] = iv[1]; + key[2] = iv[2]; + keyidx = WEP_KEY(iv[3]); + + if (key_override >= 0) + keyidx = key_override; + + if (keyidx >= NUM_WEPKEYS) return -2; + + keylen = wlandev->wep_keylens[keyidx]; + + if (keylen == 0) return -3; + + /* copy the rest of the key over from the designated key */ + memcpy(key+3, wlandev->wep_keys[keyidx], keylen); + + keylen+=3; /* add in IV bytes */ + +#ifdef WEP_DEBUG + printk(KERN_DEBUG "D %d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len, key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5], key[6], key[7]); +#endif + + /* set up the RC4 state */ + for (i = 0; i < 256; i++) + s[i] = i; + j = 0; + for (i = 0; i < 256; i++) { + j = (j + s[i] + key[i % keylen]) & 0xff; + SSWAP(i,j); + } + + /* Apply the RC4 to the data, update the CRC32 */ + crc = ~0; + i = j = 0; + for (k = 0; k < len; k++) { + i = (i+1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + buf[k] ^= s[(s[i] + s[j]) & 0xff]; + crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8); + } + crc = ~crc; + + /* now let's check the crc */ + c_crc[0] = crc; + c_crc[1] = crc >> 8; + c_crc[2] = crc >> 16; + c_crc[3] = crc >> 24; + + for (k = 0; k < 4; k++) { + i = (i + 1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k]) + return -(4 | (k << 4)) ; /* ICV mismatch */ + } + + return 0; +} + +/* encrypts in-place. */ +int wep_encrypt(wlandevice_t *wlandev, UINT8 *buf, UINT8 *dst, UINT32 len, int keynum, UINT8 *iv, UINT8 *icv) +{ + UINT32 i, j, k, crc, keylen; + UINT8 s[256], key[64]; + + /* no point in WEPping an empty frame */ + if (len <= 0) return -1; + + /* we need to have a real key.. */ + if (keynum >= NUM_WEPKEYS) return -2; + keylen = wlandev->wep_keylens[keynum]; + if (keylen <= 0) return -3; + + /* use a random IV. And skip known weak ones. */ + get_random_bytes(iv, 3); + while ((iv[1] == 0xff) && (iv[0] >= 3) && (iv[0] < keylen)) + get_random_bytes(iv, 3); + + iv[3] = (keynum & 0x03) << 6; + + key[0] = iv[0]; + key[1] = iv[1]; + key[2] = iv[2]; + + /* copy the rest of the key over from the designated key */ + memcpy(key+3, wlandev->wep_keys[keynum], keylen); + + keylen+=3; /* add in IV bytes */ + +#ifdef WEP_DEBUG + printk(KERN_DEBUG "E %d (%d/%d %d) %02x %02x %02x %02x:%02x:%02x:%02x:%02x\n", len, iv[3], keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]); +#endif + + /* set up the RC4 state */ + for (i = 0; i < 256; i++) + s[i] = i; + j = 0; + for (i = 0; i < 256; i++) { + j = (j + s[i] + key[i % keylen]) & 0xff; + SSWAP(i,j); + } + + /* Update CRC32 then apply RC4 to the data */ + crc = ~0; + i = j = 0; + for (k = 0; k < len; k++) { + crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8); + i = (i+1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff]; + } + crc = ~crc; + + /* now let's encrypt the crc */ + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + + for (k = 0; k < 4; k++) { + i = (i + 1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + icv[k] ^= s[(s[i] + s[j]) & 0xff]; + } + + return 0; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/p80211req.c +++ linux-2.6.27/ubuntu/misc/wireless/p80211/p80211req.c @@ -0,0 +1,329 @@ +/* src/p80211/p80211req.c +* +* Request/Indication/MacMgmt interface handling functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file contains the functions, types, and macros to support the +* MLME request interface that's implemented via the device ioctls. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + +/* Maximum amount of time we'll wait for a request to complete */ +#define P80211REQ_MAXTIME 3*HZ /* 3 seconds */ + +/*================================================================*/ +/* Local Macros */ + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ + +/*================================================================*/ +/* Local Function Declarations */ + +static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg); +static int p80211req_mibset_mibget(wlandevice_t *wlandev, p80211msg_dot11req_mibget_t *mib_msg, int isget); + +/*================================================================*/ +/* Function Definitions */ + + +/*---------------------------------------------------------------- +* p80211req_dorequest +* +* Handles an MLME reqest/confirm message. +* +* Arguments: +* wlandev WLAN device struct +* msgbuf Buffer containing a request message +* +* Returns: +* 0 on success, an errno otherwise +* +* Call context: +* Potentially blocks the caller, so it's a good idea to +* not call this function from an interrupt context. +----------------------------------------------------------------*/ +int p80211req_dorequest( wlandevice_t *wlandev, UINT8 *msgbuf) +{ + int result = 0; + p80211msg_t *msg = (p80211msg_t*)msgbuf; + + DBFENTER; + + /* Check to make sure the MSD is running */ + if ( + !((wlandev->msdstate == WLAN_MSD_HWPRESENT && + msg->msgcode == DIDmsg_lnxreq_ifstate) || + wlandev->msdstate == WLAN_MSD_RUNNING || + wlandev->msdstate == WLAN_MSD_FWLOAD) ) { + return -ENODEV; + } + + /* Check Permissions */ + if (!capable(CAP_NET_ADMIN) && + (msg->msgcode != DIDmsg_dot11req_mibget)) { + WLAN_LOG_ERROR("%s: only dot11req_mibget allowed for non-root.\n", wlandev->name); + return -EPERM; + } + + /* Check for busy status */ + if ( test_and_set_bit(1, &(wlandev->request_pending))) { + return -EBUSY; + } + + /* Allow p80211 to look at msg and handle if desired. */ + /* So far, all p80211 msgs are immediate, no waitq/timer necessary */ + /* This may change. */ + p80211req_handlemsg(wlandev, msg); + + /* Pass it down to wlandev via wlandev->mlmerequest */ + if ( wlandev->mlmerequest != NULL ) + wlandev->mlmerequest(wlandev, msg); + + clear_bit( 1, &(wlandev->request_pending)); + DBFEXIT; + return result; /* if result==0, msg->status still may contain an err */ +} + +/*---------------------------------------------------------------- +* p80211req_handlemsg +* +* p80211 message handler. Primarily looks for messages that +* belong to p80211 and then dispatches the appropriate response. +* TODO: we don't do anything yet. Once the linuxMIB is better +* defined we'll need a get/set handler. +* +* Arguments: +* wlandev WLAN device struct +* msg message structure +* +* Returns: +* nothing (any results are set in the status field of the msg) +* +* Call context: +* Process thread +----------------------------------------------------------------*/ +static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg) +{ + DBFENTER; + + switch (msg->msgcode) { + + case DIDmsg_lnxreq_hostwep: { + p80211msg_lnxreq_hostwep_t *req = (p80211msg_lnxreq_hostwep_t*) msg; + wlandev->hostwep &= ~(HOSTWEP_DECRYPT|HOSTWEP_ENCRYPT); + if (req->decrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_DECRYPT; + if (req->encrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_ENCRYPT; + + break; + } + case DIDmsg_dot11req_mibget: + case DIDmsg_dot11req_mibset: { + int isget = (msg->msgcode == DIDmsg_dot11req_mibget); + p80211msg_dot11req_mibget_t *mib_msg = (p80211msg_dot11req_mibget_t *) msg; + p80211req_mibset_mibget (wlandev, mib_msg, isget); + } + default: + // XXX do nothing! + ; + } /* switch msg->msgcode */ + + DBFEXIT; + + return; +} + +static int p80211req_mibset_mibget(wlandevice_t *wlandev, + p80211msg_dot11req_mibget_t *mib_msg, + int isget) +{ + p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data; + p80211pstrd_t *pstr = (p80211pstrd_t*) mibitem->data; + UINT8 *key = mibitem->data + sizeof(p80211pstrd_t); + + DBFENTER; + + switch (mibitem->did) { + case DIDmib_dot11smt_p80211Table_p80211_ifstate: { + UINT32 *data = (UINT32 *) mibitem->data; + if (isget) + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + *data = P80211ENUM_ifstate_disable; + break; + case WLAN_MSD_FWLOAD: + *data = P80211ENUM_ifstate_fwload; + break; + case WLAN_MSD_RUNNING: + *data = P80211ENUM_ifstate_enable; + break; + default: + *data = P80211ENUM_ifstate_enable; + } + break; + } + case DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) + *data = wlandev->shortpreamble; + else + wlandev->shortpreamble = *data; + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0: { + if (!isget) + wep_change_key(wlandev, 0, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1: { + if (!isget) + wep_change_key(wlandev, 1, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: { + if (!isget) + wep_change_key(wlandev, 2, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: { + if (!isget) + wep_change_key(wlandev, 3, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) { + *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; + } else { + wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK); + + wlandev->hostwep |= (*data & HOSTWEP_DEFAULTKEY_MASK); + } + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) { + if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_PRIVACYINVOKED; + } + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) { + if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= ~(HOSTWEP_EXCLUDEUNENCRYPTED); + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_EXCLUDEUNENCRYPTED; + } + break; + } + default: + // XXXX do nothing! + ; + } + + DBFEXIT; + return 0; +} + --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/p80211conv.c +++ linux-2.6.27/ubuntu/misc/wireless/p80211/p80211conv.c @@ -0,0 +1,691 @@ +/* src/p80211/p80211conv.c +* +* Ether/802.11 conversions and packet buffer routines +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file defines the functions that perform Ethernet to/from +* 802.11 frame conversions. +* +* -------------------------------------------------------------------- +*/ +/*================================================================*/ +/* System Includes */ + +#define __NO_VERSION__ /* prevent the static definition */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/*================================================================*/ +/* Local Constants */ + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + +static UINT8 oui_rfc1042[] = {0x00, 0x00, 0x00}; +static UINT8 oui_8021h[] = {0x00, 0x00, 0xf8}; + +/*================================================================*/ +/* Local Function Declarations */ + + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* p80211pb_ether_to_80211 +* +* Uses the contents of the ether frame and the etherconv setting +* to build the elements of the 802.11 frame. +* +* We don't actually set +* up the frame header here. That's the MAC's job. We're only handling +* conversion of DIXII or 802.3+LLC frames to something that works +* with 802.11. +* +* Note -- 802.11 header is NOT part of the skb. Likewise, the 802.11 +* FCS is also not present and will need to be added elsewhere. +* +* Arguments: +* ethconv Conversion type to perform +* skb skbuff containing the ether frame +* p80211_hdr 802.11 header +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int skb_ether_to_p80211( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) +{ + + UINT16 fc; + UINT16 proto; + wlan_ethhdr_t e_hdr; + wlan_llc_t *e_llc; + wlan_snap_t *e_snap; + int foo; + + DBFENTER; + memcpy(&e_hdr, skb->data, sizeof(e_hdr)); + + if (skb->len <= 0) { + WLAN_LOG_DEBUG(1, "zero-length skb!\n"); + return 1; + } + + if ( ethconv == WLAN_ETHCONV_ENCAP ) { /* simplest case */ + WLAN_LOG_DEBUG(3, "ENCAP len: %d\n", skb->len); + /* here, we don't care what kind of ether frm. Just stick it */ + /* in the 80211 payload */ + /* which is to say, leave the skb alone. */ + } else { + /* step 1: classify ether frame, DIX or 802.3? */ + proto = ntohs(e_hdr.type); + if ( proto <= 1500 ) { + WLAN_LOG_DEBUG(3, "802.3 len: %d\n", skb->len); + /* codes <= 1500 reserved for 802.3 lengths */ + /* it's 802.3, pass ether payload unchanged, */ + + /* trim off ethernet header */ + skb_pull(skb, WLAN_ETHHDR_LEN); + + /* leave off any PAD octets. */ + skb_trim(skb, proto); + } else { + WLAN_LOG_DEBUG(3, "DIXII len: %d\n", skb->len); + /* it's DIXII, time for some conversion */ + + /* trim off ethernet header */ + skb_pull(skb, WLAN_ETHHDR_LEN); + + /* tack on SNAP */ + e_snap = (wlan_snap_t *) skb_push(skb, sizeof(wlan_snap_t)); + e_snap->type = htons(proto); + if ( ethconv == WLAN_ETHCONV_8021h && p80211_stt_findproto(proto) ) { + memcpy( e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN); + } else { + memcpy( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN); + } + + /* tack on llc */ + e_llc = (wlan_llc_t *) skb_push(skb, sizeof(wlan_llc_t)); + e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ + e_llc->ssap = 0xAA; + e_llc->ctl = 0x03; + + } + } + + /* Set up the 802.11 header */ + /* It's a data frame */ + fc = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY)); + + switch ( wlandev->macmode ) { + case WLAN_MACMODE_IBSS_STA: + memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a3, wlandev->bssid, WLAN_ADDR_LEN); + break; + case WLAN_MACMODE_ESS_STA: + fc |= host2ieee16(WLAN_SET_FC_TODS(1)); + memcpy(p80211_hdr->a3.a1, wlandev->bssid, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, WLAN_ADDR_LEN); + break; + case WLAN_MACMODE_ESS_AP: + fc |= host2ieee16(WLAN_SET_FC_FROMDS(1)); + memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a2, wlandev->bssid, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, WLAN_ADDR_LEN); + break; + default: + WLAN_LOG_ERROR("Error: Converting eth to wlan in unknown mode.\n"); + return 1; + break; + } + + p80211_wep->data = NULL; + + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && (wlandev->hostwep & HOSTWEP_ENCRYPT)) { + // XXXX need to pick keynum other than default? + +#if 1 + p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC); +#else + p80211_wep->data = skb->data; +#endif + + if ((foo = wep_encrypt(wlandev, skb->data, p80211_wep->data, + skb->len, + (wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK), + p80211_wep->iv, p80211_wep->icv))) { + WLAN_LOG_WARNING("Host en-WEP failed, dropping frame (%d).\n", foo); + return 2; + } + fc |= host2ieee16(WLAN_SET_FC_ISWEP(1)); + } + + + // skb->nh.raw = skb->data; + + p80211_hdr->a3.fc = fc; + p80211_hdr->a3.dur = 0; + p80211_hdr->a3.seq = 0; + + DBFEXIT; + return 0; +} + +/* jkriegl: from orinoco, modified */ +static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, + p80211_rxmeta_t *rxmeta) +{ + int i; + + /* Gather wireless spy statistics: for each packet, compare the + * source address with out list, and if match, get the stats... */ + + for (i = 0; i < wlandev->spy_number; i++) { + + if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) { + memcpy(wlandev->spy_address[i], mac, ETH_ALEN); + wlandev->spy_stat[i].level = rxmeta->signal; + wlandev->spy_stat[i].noise = rxmeta->noise; + wlandev->spy_stat[i].qual = (rxmeta->signal > rxmeta->noise) ? \ + (rxmeta->signal - rxmeta->noise) : 0; + wlandev->spy_stat[i].updated = 0x7; + } + } +} + +/*---------------------------------------------------------------- +* p80211pb_80211_to_ether +* +* Uses the contents of a received 802.11 frame and the etherconv +* setting to build an ether frame. +* +* This function extracts the src and dest address from the 802.11 +* frame to use in the construction of the eth frame. +* +* Arguments: +* ethconv Conversion type to perform +* skb Packet buffer containing the 802.11 frame +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *skb) +{ + netdevice_t *netdev = wlandev->netdev; + UINT16 fc; + UINT payload_length; + UINT payload_offset; + UINT8 daddr[WLAN_ETHADDR_LEN]; + UINT8 saddr[WLAN_ETHADDR_LEN]; + p80211_hdr_t *w_hdr; + wlan_ethhdr_t *e_hdr; + wlan_llc_t *e_llc; + wlan_snap_t *e_snap; + + int foo; + + DBFENTER; + + payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN; + payload_offset = WLAN_HDR_A3_LEN; + + w_hdr = (p80211_hdr_t *) skb->data; + + /* setup some vars for convenience */ + fc = ieee2host16(w_hdr->a3.fc); + if ( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0) ) { + memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN); + } else if( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 1) ) { + memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN); + } else if( (WLAN_GET_FC_TODS(fc) == 1) && (WLAN_GET_FC_FROMDS(fc) == 0) ) { + memcpy(daddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN); + } else { + payload_offset = WLAN_HDR_A4_LEN; + payload_length -= ( WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN ); + if (payload_length < 0 ) { + WLAN_LOG_ERROR("A4 frame too short!\n"); + return 1; + } + memcpy(daddr, w_hdr->a4.a3, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a4.a4, WLAN_ETHADDR_LEN); + } + + /* perform de-wep if necessary.. */ + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) && (wlandev->hostwep & HOSTWEP_DECRYPT)) { + if (payload_length <= 8) { + WLAN_LOG_ERROR("WEP frame too short (%u).\n", + skb->len); + return 1; + } + if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4, + payload_length - 8, -1, + skb->data + payload_offset, + skb->data + payload_offset + payload_length - 4))) { + /* de-wep failed, drop skb. */ + WLAN_LOG_DEBUG(1, "Host de-WEP failed, dropping frame (%d).\n", foo); + wlandev->rx.decrypt_err++; + return 2; + } + + /* subtract the IV+ICV length off the payload */ + payload_length -= 8; + /* chop off the IV */ + skb_pull(skb, 4); + /* chop off the ICV. */ + skb_trim(skb, skb->len - 4); + + wlandev->rx.decrypt++; + } + + e_hdr = (wlan_ethhdr_t *) (skb->data + payload_offset); + + e_llc = (wlan_llc_t *) (skb->data + payload_offset); + e_snap = (wlan_snap_t *) (skb->data + payload_offset + sizeof(wlan_llc_t)); + + /* Test for the various encodings */ + if ( (payload_length >= sizeof(wlan_ethhdr_t)) && + ( e_llc->dsap != 0xaa || e_llc->ssap != 0xaa ) && + ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) || + (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) { + WLAN_LOG_DEBUG(3, "802.3 ENCAP len: %d\n", payload_length); + /* 802.3 Encapsulated */ + /* Test for an overlength frame */ + if ( payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) { + /* A bogus length ethfrm has been encap'd. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("ENCAP frame too large (%d > %d)\n", + payload_length, netdev->mtu + WLAN_ETHHDR_LEN); + return 1; + } + + /* Chop off the 802.11 header. it's already sane. */ + skb_pull(skb, payload_offset); + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + + } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03) && + (((memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)==0) && + (ethconv == WLAN_ETHCONV_8021h) && + (p80211_stt_findproto(ieee2host16(e_snap->type)))) || + (memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)!=0))) + { + WLAN_LOG_DEBUG(3, "SNAP+RFC1042 len: %d\n", payload_length); + /* it's a SNAP + RFC1042 frame && protocol is in STT */ + /* build 802.3 + RFC1042 */ + + /* Test for an overlength frame */ + if ( payload_length > netdev->mtu ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("SNAP frame too large (%d > %d)\n", + payload_length, netdev->mtu); + return 1; + } + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + + /* create 802.3 header at beginning of skb. */ + e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); + memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + e_hdr->type = htons(payload_length); + + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + + } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03) ) { + WLAN_LOG_DEBUG(3, "802.1h/RFC1042 len: %d\n", payload_length); + /* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */ + /* build a DIXII + RFC894 */ + + /* Test for an overlength frame */ + if ((payload_length - sizeof(wlan_llc_t) - sizeof(wlan_snap_t)) + > netdev->mtu) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("DIXII frame too large (%ld > %d)\n", + (long int) (payload_length - sizeof(wlan_llc_t) - + sizeof(wlan_snap_t)), + netdev->mtu); + return 1; + } + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + + /* chop llc header from skb. */ + skb_pull(skb, sizeof(wlan_llc_t)); + + /* chop snap header from skb. */ + skb_pull(skb, sizeof(wlan_snap_t)); + + /* create 802.3 header at beginning of skb. */ + e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); + e_hdr->type = e_snap->type; + memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + } else { + WLAN_LOG_DEBUG(3, "NON-ENCAP len: %d\n", payload_length); + /* any NON-ENCAP */ + /* it's a generic 80211+LLC or IPX 'Raw 802.3' */ + /* build an 802.3 frame */ + /* allocate space and setup hostbuf */ + + /* Test for an overlength frame */ + if ( payload_length > netdev->mtu ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("OTHER frame too large (%d > %d)\n", + payload_length, + netdev->mtu); + return 1; + } + + /* Chop off the 802.11 header. */ + skb_pull(skb, payload_offset); + + /* create 802.3 header at beginning of skb. */ + e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); + memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + e_hdr->type = htons(payload_length); + + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + + } + + /* + * Note that eth_type_trans() expects an skb w/ skb->data pointing + * at the MAC header, it then sets the following skb members: + * skb->mac_header, + * skb->data, and + * skb->pkt_type. + * It then _returns_ the value that _we're_ supposed to stuff in + * skb->protocol. This is nuts. + */ + skb->protocol = eth_type_trans(skb, netdev); + + /* jkriegl: process signal and noise as set in hfa384x_int_rx() */ + /* jkriegl: only process signal/noise if requested by iwspy */ + if (wlandev->spy_number) + orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source, P80211SKB_RXMETA(skb)); + + /* Free the metadata */ + p80211skb_rxmeta_detach(skb); + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* p80211_stt_findproto +* +* Searches the 802.1h Selective Translation Table for a given +* protocol. +* +* Arguments: +* proto protocl number (in host order) to search for. +* +* Returns: +* 1 - if the table is empty or a match is found. +* 0 - if the table is non-empty and a match is not found. +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int p80211_stt_findproto(UINT16 proto) +{ + /* Always return found for now. This is the behavior used by the */ + /* Zoom Win95 driver when 802.1h mode is selected */ + /* TODO: If necessary, add an actual search we'll probably + need this to match the CMAC's way of doing things. + Need to do some testing to confirm. + */ + + if (proto == 0x80f3) /* APPLETALK */ + return 1; + + return 0; +} + +/*---------------------------------------------------------------- +* p80211skb_rxmeta_detach +* +* Disconnects the frmmeta and rxmeta from an skb. +* +* Arguments: +* wlandev The wlandev this skb belongs to. +* skb The skb we're attaching to. +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +void +p80211skb_rxmeta_detach(struct sk_buff *skb) +{ + p80211_rxmeta_t *rxmeta; + p80211_frmmeta_t *frmmeta; + + DBFENTER; + /* Sanity checks */ + if ( skb==NULL ) { /* bad skb */ + WLAN_LOG_DEBUG(1, "Called w/ null skb.\n"); + goto exit; + } + frmmeta = P80211SKB_FRMMETA(skb); + if ( frmmeta == NULL ) { /* no magic */ + WLAN_LOG_DEBUG(1, "Called w/ bad frmmeta magic.\n"); + goto exit; + } + rxmeta = frmmeta->rx; + if ( rxmeta == NULL ) { /* bad meta ptr */ + WLAN_LOG_DEBUG(1, "Called w/ bad rxmeta ptr.\n"); + goto exit; + } + + /* Free rxmeta */ + kfree(rxmeta); + + /* Clear skb->cb */ + memset(skb->cb, 0, sizeof(skb->cb)); +exit: + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* p80211skb_rxmeta_attach +* +* Allocates a p80211rxmeta structure, initializes it, and attaches +* it to an skb. +* +* Arguments: +* wlandev The wlandev this skb belongs to. +* skb The skb we're attaching to. +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int +p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) +{ + int result = 0; + p80211_rxmeta_t *rxmeta; + p80211_frmmeta_t *frmmeta; + + DBFENTER; + + /* If these already have metadata, we error out! */ + if (P80211SKB_RXMETA(skb) != NULL) { + WLAN_LOG_ERROR("%s: RXmeta already attached!\n", + wlandev->name); + result = 0; + goto exit; + } + + /* Allocate the rxmeta */ + rxmeta = kmalloc(sizeof(p80211_rxmeta_t), GFP_ATOMIC); + + if ( rxmeta == NULL ) { + WLAN_LOG_ERROR("%s: Failed to allocate rxmeta.\n", + wlandev->name); + result = 1; + goto exit; + } + + /* Initialize the rxmeta */ + memset(rxmeta, 0, sizeof(p80211_rxmeta_t)); + rxmeta->wlandev = wlandev; + rxmeta->hosttime = jiffies; + + /* Overlay a frmmeta_t onto skb->cb */ + memset(skb->cb, 0, sizeof(p80211_frmmeta_t)); + frmmeta = (p80211_frmmeta_t*)(skb->cb); + frmmeta->magic = P80211_FRMMETA_MAGIC; + frmmeta->rx = rxmeta; +exit: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* p80211skb_free +* +* Frees an entire p80211skb by checking and freeing the meta struct +* and then freeing the skb. +* +* Arguments: +* wlandev The wlandev this skb belongs to. +* skb The skb we're attaching to. +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +void +p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) +{ + p80211_frmmeta_t *meta; + DBFENTER; + meta = P80211SKB_FRMMETA(skb); + if ( meta && meta->rx) { + p80211skb_rxmeta_detach(skb); + } else { + WLAN_LOG_ERROR("Freeing an skb (%p) w/ no frmmeta.\n", skb); + } + + dev_kfree_skb(skb); + DBFEXIT; + return; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/p80211netdev.c +++ linux-2.6.27/ubuntu/misc/wireless/p80211/p80211netdev.c @@ -0,0 +1,1558 @@ +/* src/p80211/p80211knetdev.c +* +* Linux Kernel net device interface +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* The functions required for a Linux network device are defined here. +* +* -------------------------------------------------------------------- +*/ + + +/*================================================================*/ +/* System Includes */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef SIOCETHTOOL +#include +#endif + +#if WIRELESS_EXT > 12 +#include +#endif + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ + +#define __NO_VERSION__ /* prevent the static definition */ + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_p80211; +#endif + +/*================================================================*/ +/* Local Function Declarations */ + +/* Support functions */ +static void p80211netdev_rx_bh(unsigned long arg); + +/* netdevice method functions */ +static int p80211knetdev_init( netdevice_t *netdev); +static struct net_device_stats* p80211knetdev_get_stats(netdevice_t *netdev); +static int p80211knetdev_open( netdevice_t *netdev); +static int p80211knetdev_stop( netdevice_t *netdev ); +static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev); +static void p80211knetdev_set_multicast_list(netdevice_t *dev); +static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd); +static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr); +static void p80211knetdev_tx_timeout(netdevice_t *netdev); +static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc); + +#ifdef CONFIG_PROC_FS +static int +p80211netdev_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data); +#endif + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* p80211knetdev_startup +* +* Initialize the wlandevice/netdevice part of 802.11 services at +* load time. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +void p80211netdev_startup(void) +{ + DBFENTER; + +#ifdef CONFIG_PROC_FS + if (PROC_NET != NULL) { + proc_p80211 = create_proc_entry( + "p80211", + (S_IFDIR|S_IRUGO|S_IXUGO), + PROC_NET); + } +#endif + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* p80211knetdev_shutdown +* +* Shutdown the wlandevice/netdevice part of 802.11 services at +* unload time. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +void +p80211netdev_shutdown(void) +{ + DBFENTER; +#ifdef CONFIG_PROC_FS + if (proc_p80211 != NULL) { + remove_proc_entry("p80211", PROC_NET); + } +#endif + DBFEXIT; +} + +/*---------------------------------------------------------------- +* p80211knetdev_init +* +* Init method for a Linux netdevice. Called in response to +* register_netdev. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +static int p80211knetdev_init( netdevice_t *netdev) +{ + DBFENTER; + /* Called in response to register_netdev */ + /* This is usually the probe function, but the probe has */ + /* already been done by the MSD and the create_kdev */ + /* function. All we do here is return success */ + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_get_stats +* +* Statistics retrieval for linux netdevices. Here we're reporting +* the Linux i/f level statistics. Hence, for the primary numbers, +* we don't want to report the numbers from the MIB. Eventually, +* it might be useful to collect some of the error counters though. +* +* Arguments: +* netdev Linux netdevice +* +* Returns: +* the address of the statistics structure +----------------------------------------------------------------*/ +static struct net_device_stats* +p80211knetdev_get_stats(netdevice_t *netdev) +{ + wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; + DBFENTER; + + /* TODO: review the MIB stats for items that correspond to + linux stats */ + + DBFEXIT; + return &(wlandev->linux_stats); +} + + +/*---------------------------------------------------------------- +* p80211knetdev_open +* +* Linux netdevice open method. Following a successful call here, +* the device is supposed to be ready for tx and rx. In our +* situation that may not be entirely true due to the state of the +* MAC below. +* +* Arguments: +* netdev Linux network device structure +* +* Returns: +* zero on success, non-zero otherwise +----------------------------------------------------------------*/ +static int p80211knetdev_open( netdevice_t *netdev ) +{ + int result = 0; /* success */ + wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv); + + DBFENTER; + + /* Check to make sure the MSD is running */ + if ( wlandev->msdstate != WLAN_MSD_RUNNING ) { + return -ENODEV; + } + + /* Tell the MSD to open */ + if ( wlandev->open != NULL) { + result = wlandev->open(wlandev); + if ( result == 0 ) { +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) ) + netdev->interrupt = 0; +#endif + p80211netdev_start_queue(wlandev); + wlandev->state = WLAN_DEVICE_OPEN; + } + } else { + result = -EAGAIN; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_stop +* +* Linux netdevice stop (close) method. Following this call, +* no frames should go up or down through this interface. +* +* Arguments: +* netdev Linux network device structure +* +* Returns: +* zero on success, non-zero otherwise +----------------------------------------------------------------*/ +static int p80211knetdev_stop( netdevice_t *netdev ) +{ + int result = 0; + wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv); + + DBFENTER; + + if ( wlandev->close != NULL ) { + result = wlandev->close(wlandev); + } + + p80211netdev_stop_queue(wlandev); + wlandev->state = WLAN_DEVICE_CLOSED; + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* p80211netdev_rx +* +* Frame receive function called by the mac specific driver. +* +* Arguments: +* wlandev WLAN network device structure +* skb skbuff containing a full 802.11 frame. +* Returns: +* nothing +* Side effects: +* +----------------------------------------------------------------*/ +void +p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb ) +{ + DBFENTER; + + /* Enqueue for post-irq processing */ + skb_queue_tail(&wlandev->nsd_rxq, skb); + + tasklet_schedule(&wlandev->rx_bh); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* p80211netdev_rx_bh +* +* Deferred processing of all received frames. +* +* Arguments: +* wlandev WLAN network device structure +* skb skbuff containing a full 802.11 frame. +* Returns: +* nothing +* Side effects: +* +----------------------------------------------------------------*/ +static void p80211netdev_rx_bh(unsigned long arg) +{ + wlandevice_t *wlandev = (wlandevice_t *) arg; + struct sk_buff *skb = NULL; + netdevice_t *dev = wlandev->netdev; + p80211_hdr_a3_t *hdr; + UINT16 fc; + + DBFENTER; + + /* Let's empty our our queue */ + while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { + if (wlandev->state == WLAN_DEVICE_OPEN) { + + if (dev->type != ARPHRD_ETHER) { + /* RAW frame; we shouldn't convert it */ + // XXX Append the Prism Header here instead. + + /* set up various data fields */ + skb->dev = dev; + skb_reset_mac_header(skb); + + skb->ip_summed = CHECKSUM_NONE; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_80211_RAW); + dev->last_rx = jiffies; + + wlandev->linux_stats.rx_packets++; + wlandev->linux_stats.rx_bytes += skb->len; + netif_rx_ni(skb); + continue; + } else { + hdr = (p80211_hdr_a3_t *)skb->data; + fc = ieee2host16(hdr->fc); + if (p80211_rx_typedrop(wlandev, fc)) { + dev_kfree_skb(skb); + continue; + } + + /* perform mcast filtering */ + if (wlandev->netdev->flags & IFF_ALLMULTI) { + /* allow my local address through */ + if (memcmp(hdr->a1, wlandev->netdev->dev_addr, WLAN_ADDR_LEN) != 0) { + /* but reject anything else that isn't multicast */ + if (!(hdr->a1[0] & 0x01)) { + dev_kfree_skb(skb); + continue; + } + } + } + + if ( skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0 ) { + skb->dev->last_rx = jiffies; + wlandev->linux_stats.rx_packets++; + wlandev->linux_stats.rx_bytes += skb->len; + netif_rx_ni(skb); + continue; + } + WLAN_LOG_DEBUG(1, "p80211_to_ether failed.\n"); + } + } + dev_kfree_skb(skb); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_hard_start_xmit +* +* Linux netdevice method for transmitting a frame. +* +* Arguments: +* skb Linux sk_buff containing the frame. +* netdev Linux netdevice. +* +* Side effects: +* If the lower layers report that buffers are full. netdev->tbusy +* will be set to prevent higher layers from sending more traffic. +* +* Note: If this function returns non-zero, higher layers retain +* ownership of the skb. +* +* Returns: +* zero on success, non-zero on failure. +----------------------------------------------------------------*/ +static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev) +{ + int result = 0; + int txresult = -1; + wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; + p80211_hdr_t p80211_hdr; + p80211_metawep_t p80211_wep; + + DBFENTER; + + if (skb == NULL) { + return 0; + } + + if (wlandev->state != WLAN_DEVICE_OPEN) { + result = 1; + goto failed; + } + + memset(&p80211_hdr, 0, sizeof(p80211_hdr_t)); + memset(&p80211_wep, 0, sizeof(p80211_metawep_t)); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + if ( test_and_set_bit(0, (void*)&(netdev->tbusy)) != 0 ) { + /* We've been called w/ tbusy set, has the tx */ + /* path stalled? */ + WLAN_LOG_DEBUG(1, "called when tbusy set\n"); + result = 1; + goto failed; + } +#else + if ( netif_queue_stopped(netdev) ) { + WLAN_LOG_DEBUG(1, "called when queue stopped.\n"); + result = 1; + goto failed; + } + + netif_stop_queue(netdev); + + /* No timeout handling here, 2.3.38+ kernels call the + * timeout function directly. + * TODO: Add timeout handling. + */ +#endif + + /* Check to see that a valid mode is set */ + switch( wlandev->macmode ) { + case WLAN_MACMODE_IBSS_STA: + case WLAN_MACMODE_ESS_STA: + case WLAN_MACMODE_ESS_AP: + break; + default: + /* Mode isn't set yet, just drop the frame + * and return success . + * TODO: we need a saner way to handle this + */ + if(skb->protocol != ETH_P_80211_RAW) { + p80211netdev_start_queue(wlandev); + WLAN_LOG_NOTICE( + "Tx attempt prior to association, frame dropped.\n"); + wlandev->linux_stats.tx_dropped++; + result = 0; + goto failed; + } + break; + } + + /* Check for raw transmits */ + if(skb->protocol == ETH_P_80211_RAW) { + if (!capable(CAP_NET_ADMIN)) { + result = 1; + goto failed; + } + /* move the header over */ + memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr_t)); + skb_pull(skb, sizeof(p80211_hdr_t)); + } else { + if ( skb_ether_to_p80211(wlandev, wlandev->ethconv, skb, &p80211_hdr, &p80211_wep) != 0 ) { + /* convert failed */ + WLAN_LOG_DEBUG(1, "ether_to_80211(%d) failed.\n", + wlandev->ethconv); + result = 1; + goto failed; + } + } + if ( wlandev->txframe == NULL ) { + result = 1; + goto failed; + } + + netdev->trans_start = jiffies; + + wlandev->linux_stats.tx_packets++; + /* count only the packet payload */ + wlandev->linux_stats.tx_bytes += skb->len; + + txresult = wlandev->txframe(wlandev, skb, &p80211_hdr, &p80211_wep); + + if ( txresult == 0) { + /* success and more buf */ + /* avail, re: hw_txdata */ + p80211netdev_wake_queue(wlandev); + result = 0; + } else if ( txresult == 1 ) { + /* success, no more avail */ + WLAN_LOG_DEBUG(3, "txframe success, no more bufs\n"); + /* netdev->tbusy = 1; don't set here, irqhdlr */ + /* may have already cleared it */ + result = 0; + } else if ( txresult == 2 ) { + /* alloc failure, drop frame */ + WLAN_LOG_DEBUG(3, "txframe returned alloc_fail\n"); + result = 1; + } else { + /* buffer full or queue busy, drop frame. */ + WLAN_LOG_DEBUG(3, "txframe returned full or busy\n"); + result = 1; + } + + failed: + /* Free up the WEP buffer if it's not the same as the skb */ + if ((p80211_wep.data) && (p80211_wep.data != skb->data)) + kfree(p80211_wep.data); + + /* we always free the skb here, never in a lower level. */ + if (!result) + dev_kfree_skb(skb); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_set_multicast_list +* +* Called from higher lavers whenever there's a need to set/clear +* promiscuous mode or rewrite the multicast list. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +static void p80211knetdev_set_multicast_list(netdevice_t *dev) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + /* TODO: real multicast support as well */ + + if (wlandev->set_multicast_list) + wlandev->set_multicast_list(wlandev, dev); + + DBFEXIT; +} + +#ifdef SIOCETHTOOL + +static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) +{ + UINT32 ethcmd; + struct ethtool_drvinfo info; + struct ethtool_value edata; + + memset(&info, 0, sizeof(info)); + memset(&edata, 0, sizeof(edata)); + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: + info.cmd = ethcmd; + snprintf(info.driver, sizeof(info.driver), "p80211_%s", + wlandev->nsdname); + snprintf(info.version, sizeof(info.version), "%s", + WLAN_RELEASE); + + // info.fw_version + // info.bus_info + + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; +#ifdef ETHTOOL_GLINK + case ETHTOOL_GLINK: + edata.cmd = ethcmd; + + if (wlandev->linkstatus && + (wlandev->macmode != WLAN_MACMODE_NONE)) { + edata.data = 1; + } else { + edata.data = 0; + } + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } +#endif + + return -EOPNOTSUPP; +} + +#endif + +/*---------------------------------------------------------------- +* p80211knetdev_do_ioctl +* +* Handle an ioctl call on one of our devices. Everything Linux +* ioctl specific is done here. Then we pass the contents of the +* ifr->data to the request message handler. +* +* Arguments: +* dev Linux kernel netdevice +* ifr Our private ioctl request structure, typed for the +* generic struct ifreq so we can use ptr to func +* w/o cast. +* +* Returns: +* zero on success, a negative errno on failure. Possible values: +* -ENETDOWN Device isn't up. +* -EBUSY cmd already in progress +* -ETIME p80211 cmd timed out (MSD may have its own timers) +* -EFAULT memory fault copying msg from user buffer +* -ENOMEM unable to allocate kernel msg buffer +* -ENOSYS bad magic, it the cmd really for us? +* -EINTR sleeping on cmd, awakened by signal, cmd cancelled. +* +* Call Context: +* Process thread (ioctl caller). TODO: SMP support may require +* locks. +----------------------------------------------------------------*/ +static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) +{ + int result = 0; + p80211ioctl_req_t *req = (p80211ioctl_req_t*)ifr; + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + UINT8 *msgbuf; + DBFENTER; + + WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); + + mutex_lock(&wlandev->ioctl_lock); +#if WIRELESS_EXT < 13 + /* Is this a wireless extensions ioctl? */ + if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { + if ((result = p80211wext_support_ioctl(dev, ifr, cmd)) + != (-EOPNOTSUPP)) { + goto bail; + } + } +#endif + +#ifdef SIOCETHTOOL + if (cmd == SIOCETHTOOL) { + result = p80211netdev_ethtool(wlandev, (void __user *) ifr->ifr_data); + goto bail; + } +#endif + + /* Test the magic, assume ifr is good if it's there */ + if ( req->magic != P80211_IOCTL_MAGIC ) { + result = -ENOSYS; + goto bail; + } + + if ( cmd == P80211_IFTEST ) { + result = 0; + goto bail; + } else if ( cmd != P80211_IFREQ ) { + result = -ENOSYS; + goto bail; + } + + /* Allocate a buf of size req->len */ + if ((msgbuf = kmalloc( req->len, GFP_KERNEL))) { + if ( copy_from_user( msgbuf, (void __user *) req->data, req->len) ) { + result = -EFAULT; + } else { + result = p80211req_dorequest( wlandev, msgbuf); + } + + if ( result == 0 ) { + if ( copy_to_user( (void __user *) req->data, msgbuf, req->len)) { + result = -EFAULT; + } + } + kfree(msgbuf); + } else { + result = -ENOMEM; + } +bail: + mutex_unlock(&wlandev->ioctl_lock); + + DBFEXIT; + + return result; /* If allocate,copyfrom or copyto fails, return errno */ +} + +/*---------------------------------------------------------------- +* p80211knetdev_set_mac_address +* +* Handles the ioctl for changing the MACAddress of a netdevice +* +* references: linux/netdevice.h and drivers/net/net_init.c +* +* NOTE: [MSM] We only prevent address changes when the netdev is +* up. We don't control anything based on dot11 state. If the +* address is changed on a STA that's currently associated, you +* will probably lose the ability to send and receive data frames. +* Just be aware. Therefore, this should usually only be done +* prior to scan/join/auth/assoc. +* +* Arguments: +* dev netdevice struct +* addr the new MACAddress (a struct) +* +* Returns: +* zero on success, a negative errno on failure. Possible values: +* -EBUSY device is bussy (cmd not possible) +* -and errors returned by: p80211req_dorequest(..) +* +* by: Collin R. Mulliner +----------------------------------------------------------------*/ +static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) +{ + struct sockaddr *new_addr = addr; + p80211msg_dot11req_mibset_t dot11req; + p80211item_unk392_t *mibattr; + p80211item_pstr6_t *macaddr; + p80211item_uint32_t *resultcode; + int result = 0; + + DBFENTER; + /* If we're running, we don't allow MAC address changes */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + if ( dev->start) { + return -EBUSY; + } +#else + if (netif_running(dev)) { + return -EBUSY; + } +#endif + + /* Set up some convenience pointers. */ + mibattr = &dot11req.mibattribute; + macaddr = (p80211item_pstr6_t*)&mibattr->data; + resultcode = &dot11req.resultcode; + + /* Set up a dot11req_mibset */ + memset(&dot11req, 0, sizeof(p80211msg_dot11req_mibset_t)); + dot11req.msgcode = DIDmsg_dot11req_mibset; + dot11req.msglen = sizeof(p80211msg_dot11req_mibset_t); + memcpy(dot11req.devname, + ((wlandevice_t*)(dev->priv))->name, + WLAN_DEVNAMELEN_MAX - 1); + + /* Set up the mibattribute argument */ + mibattr->did = DIDmsg_dot11req_mibset_mibattribute; + mibattr->status = P80211ENUM_msgitem_status_data_ok; + mibattr->len = sizeof(mibattr->data); + + macaddr->did = DIDmib_dot11mac_dot11OperationTable_dot11MACAddress; + macaddr->status = P80211ENUM_msgitem_status_data_ok; + macaddr->len = sizeof(macaddr->data); + macaddr->data.len = WLAN_ADDR_LEN; + memcpy(&macaddr->data.data, new_addr->sa_data, WLAN_ADDR_LEN); + + /* Set up the resultcode argument */ + resultcode->did = DIDmsg_dot11req_mibset_resultcode; + resultcode->status = P80211ENUM_msgitem_status_no_value; + resultcode->len = sizeof(resultcode->data); + resultcode->data = 0; + + /* now fire the request */ + result = p80211req_dorequest(dev->priv, (UINT8*)&dot11req); + + /* If the request wasn't successful, report an error and don't + * change the netdev address + */ + if ( result != 0 || resultcode->data != P80211ENUM_resultcode_success) { + WLAN_LOG_ERROR( + "Low-level driver failed dot11req_mibset(dot11MACAddress).\n"); + result = -EADDRNOTAVAIL; + } else { + /* everything's ok, change the addr in netdev */ + memcpy(dev->dev_addr, new_addr->sa_data, dev->addr_len); + } + + DBFEXIT; + return result; +} + +static int wlan_change_mtu(netdevice_t *dev, int new_mtu) +{ + DBFENTER; + // 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) + // and another 8 for wep. + if ( (new_mtu < 68) || (new_mtu > (2312 - 20 - 8))) + return -EINVAL; + + dev->mtu = new_mtu; + + DBFEXIT; + + return 0; +} + +/*--------------------------------------------------------- + * wlan_alloc_netdev + * + * create a netdev properly over different kernel versions + * this should work with kernels earlier than 2.6.26, and if + * anyone cares they can change it +----------------------------------------------------------*/ + +static inline netdevice_t * wlan_alloc_netdev() { + netdevice_t *dev; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ) + dev = alloc_netdev(0,"wlan%d",ether_setup); +#else + dev = kmalloc(sizeof(netdevice_t), GFP_ATOMIC); + if ( dev ) { + memset( dev, 0, sizeof(netdevice_t)); + ether_setup(dev); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ) + dev->nd_net = &init_net; +#endif + } +#endif + return dev; +} + + +/*---------------------------------------------------------------- +* wlan_setup +* +* Roughly matches the functionality of ether_setup. Here +* we set up any members of the wlandevice structure that are common +* to all devices. Additionally, we allocate a linux 'struct device' +* and perform the same setup as ether_setup. +* +* Note: It's important that the caller have setup the wlandev->name +* ptr prior to calling this function. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Should be process thread. We'll assume it might be +* interrupt though. When we add support for statically +* compiled drivers, this function will be called in the +* context of the kernel startup code. +----------------------------------------------------------------*/ +int wlan_setup(wlandevice_t *wlandev) +{ + int result = 0; + netdevice_t *dev; + + DBFENTER; + + /* Set up the wlandev */ + wlandev->state = WLAN_DEVICE_CLOSED; + wlandev->ethconv = WLAN_ETHCONV_8021h; + wlandev->macmode = WLAN_MACMODE_NONE; + + /* Set up the rx queue */ + skb_queue_head_init(&wlandev->nsd_rxq); + tasklet_init(&wlandev->rx_bh, + p80211netdev_rx_bh, + (unsigned long)wlandev); + + /* Allocate and initialize the struct net device */ + dev = wlan_alloc_netdev(); + if ( dev == NULL ) { + WLAN_LOG_ERROR("Failed to alloc netdev.\n"); + result = 1; + } else { + wlandev->netdev = dev; + dev->priv = wlandev; + dev->hard_start_xmit = p80211knetdev_hard_start_xmit; + dev->get_stats = p80211knetdev_get_stats; + + mutex_init(&wlandev->ioctl_lock); + /* block ioctls until fully initialised. Don't forget to call allow_ioctls at some point!*/ + mutex_lock(&wlandev->ioctl_lock); + +#ifdef HAVE_PRIVATE_IOCTL + dev->do_ioctl = p80211knetdev_do_ioctl; +#endif +#ifdef HAVE_MULTICAST + dev->set_multicast_list = p80211knetdev_set_multicast_list; +#endif + dev->init = p80211knetdev_init; + dev->open = p80211knetdev_open; + dev->stop = p80211knetdev_stop; + +#if defined(CONFIG_NET_WIRELESS) || defined(WIRELESS_EXT) +#if (WIRELESS_EXT < 17) + dev->get_wireless_stats = p80211wext_get_wireless_stats; +#endif +#if WIRELESS_EXT > 12 + dev->wireless_handlers = &p80211wext_handler_def; +#endif +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + dev->tbusy = 1; + dev->start = 0; +#else + netif_stop_queue(dev); +#endif +#ifdef HAVE_CHANGE_MTU + dev->change_mtu = wlan_change_mtu; +#endif +#ifdef HAVE_SET_MAC_ADDR + dev->set_mac_address = p80211knetdev_set_mac_address; +#endif +#ifdef HAVE_TX_TIMEOUT + dev->tx_timeout = &p80211knetdev_tx_timeout; + dev->watchdog_timeo = (wlan_watchdog * HZ) / 1000; +#endif + netif_carrier_off(dev); + } + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* wlan_unsetup +* +* This function is paired with the wlan_setup routine. It should +* be called after unregister_wlandev. Basically, all it does is +* free the 'struct device' that's associated with the wlandev. +* We do it here because the 'struct device' isn't allocated +* explicitly in the driver code, it's done in wlan_setup. To +* do the free in the driver might seem like 'magic'. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Should be process thread. We'll assume it might be +* interrupt though. When we add support for statically +* compiled drivers, this function will be called in the +* context of the kernel startup code. +----------------------------------------------------------------*/ +int wlan_unsetup(wlandevice_t *wlandev) +{ + int result = 0; + + DBFENTER; + + tasklet_kill(&wlandev->rx_bh); + + if (wlandev->netdev == NULL ) { + WLAN_LOG_ERROR("called without wlandev->netdev set.\n"); + result = 1; + } else { + free_netdev(wlandev->netdev); + wlandev->netdev = NULL; + } + + DBFEXIT; + return 0; +} + + + +/*---------------------------------------------------------------- +* register_wlandev +* +* Roughly matches the functionality of register_netdev. This function +* is called after the driver has successfully probed and set up the +* resources for the device. It's now ready to become a named device +* in the Linux system. +* +* First we allocate a name for the device (if not already set), then +* we call the Linux function register_netdevice. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Can be either interrupt or not. +----------------------------------------------------------------*/ +int register_wlandev(wlandevice_t *wlandev) +{ + int i = 0; + netdevice_t *dev = wlandev->netdev; + + DBFENTER; +/* alloc_netdev already sets up the name */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ) + i = register_netdev(dev); + if (i) + return i; +#else + i = dev_alloc_name(wlandev->netdev, "wlan%d"); + if (i >= 0) { + i = register_netdev(wlandev->netdev); + } + if (i != 0) { + return -EIO; + } + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) ) + dev->name = wlandev->name; +#else + strcpy(wlandev->name, dev->name); +#endif +#endif + + +#ifdef CONFIG_PROC_FS + if (proc_p80211) { + wlandev->procdir = proc_mkdir(wlandev->name, proc_p80211); + if ( wlandev->procdir ) + wlandev->procwlandev = + create_proc_read_entry("wlandev", 0, + wlandev->procdir, + p80211netdev_proc_read, + wlandev); + if (wlandev->nsd_proc_read) + create_proc_read_entry("nsd", 0, + wlandev->procdir, + wlandev->nsd_proc_read, + wlandev); + } +#endif + + if (wlan_wext_write) { +/* + // fake out a call to ifstate_enable! + p80211msg_lnxreq_ifstate_t msg; + memset(&msg, 0, sizeof(msg)); + msg.msgcode = DIDmsg_lnxreq_ifstate; + msg.msglen = sizeof(msg); + msg.ifstate.status = P80211ENUM_msgitem_status_data_ok; + msg.ifstate.data = P80211ENUM_ifstate_enable; + + p80211req_dorequest(wlandev, &msg); +*/ + } else { +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REGISTER); +#endif + } + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* unregister_wlandev +* +* Roughly matches the functionality of unregister_netdev. This +* function is called to remove a named device from the system. +* +* First we tell linux that the device should no longer exist. +* Then we remove it from the list of known wlan devices. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Can be either interrupt or not. +----------------------------------------------------------------*/ +int unregister_wlandev(wlandevice_t *wlandev) +{ + struct sk_buff *skb; + + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REMOVE); +#endif + +#ifdef CONFIG_PROC_FS + if ( wlandev->procwlandev ) { + remove_proc_entry("wlandev", wlandev->procdir); + } + if ( wlandev->nsd_proc_read ) { + remove_proc_entry("nsd", wlandev->procdir); + } + if (wlandev->procdir) { + remove_proc_entry(wlandev->name, proc_p80211); + } +#endif + + unregister_netdev(wlandev->netdev); + + /* Now to clean out the rx queue */ + while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { + dev_kfree_skb(skb); + } + + DBFEXIT; + return 0; +} + +#ifdef CONFIG_PROC_FS +/*---------------------------------------------------------------- +* proc_read +* +* Read function for /proc/net/p80211//wlandev +* +* Arguments: +* buf +* start +* offset +* count +* eof +* data +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Can be either interrupt or not. +----------------------------------------------------------------*/ +static int +p80211netdev_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + char *p = page; + wlandevice_t *wlandev = (wlandevice_t *) data; + + DBFENTER; + if (offset != 0) { + *eof = 1; + goto exit; + } + + p += sprintf(p, "p80211 version: %s (%s)\n\n", + WLAN_RELEASE, WLAN_BUILD_DATE); + p += sprintf(p, "name : %s\n", wlandev->name); + p += sprintf(p, "nsd name : %s\n", wlandev->nsdname); + p += sprintf(p, "address : %02x:%02x:%02x:%02x:%02x:%02x\n", + wlandev->netdev->dev_addr[0], wlandev->netdev->dev_addr[1], wlandev->netdev->dev_addr[2], + wlandev->netdev->dev_addr[3], wlandev->netdev->dev_addr[4], wlandev->netdev->dev_addr[5]); + p += sprintf(p, "nsd caps : %s%s%s%s%s%s%s%s%s%s\n", + (wlandev->nsdcaps & P80211_NSDCAP_HARDWAREWEP) ? "wep_hw " : "", + (wlandev->nsdcaps & P80211_NSDCAP_TIEDWEP) ? "wep_tied " : "", + (wlandev->nsdcaps & P80211_NSDCAP_NOHOSTWEP) ? "wep_hw_only " : "", + (wlandev->nsdcaps & P80211_NSDCAP_PBCC) ? "pbcc " : "", + (wlandev->nsdcaps & P80211_NSDCAP_SHORT_PREAMBLE) ? "short_preamble " : "", + (wlandev->nsdcaps & P80211_NSDCAP_AGILITY) ? "agility " : "", + (wlandev->nsdcaps & P80211_NSDCAP_AP_RETRANSMIT) ? "ap_retransmit " : "", + (wlandev->nsdcaps & P80211_NSDCAP_HWFRAGMENT) ? "hw_frag " : "", + (wlandev->nsdcaps & P80211_NSDCAP_AUTOJOIN) ? "autojoin " : "", + (wlandev->nsdcaps & P80211_NSDCAP_NOSCAN) ? "" : "scan "); + + + p += sprintf(p, "bssid : %02x:%02x:%02x:%02x:%02x:%02x\n", + wlandev->bssid[0], wlandev->bssid[1], wlandev->bssid[2], + wlandev->bssid[3], wlandev->bssid[4], wlandev->bssid[5]); + + p += sprintf(p, "Enabled : %s%s\n", + (wlandev->shortpreamble) ? "short_preamble " : "", + (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) ? "privacy" : ""); + p += sprintf(p, "msdstate=%d\n", wlandev->msdstate); + + + exit: + DBFEXIT; + return (p - page); +} +#endif + +/*---------------------------------------------------------------- +* p80211netdev_hwremoved +* +* Hardware removed notification. This function should be called +* immediately after an MSD has detected that the underlying hardware +* has been yanked out from under us. The primary things we need +* to do are: +* - Mark the wlandev +* - Prevent any further traffic from the knetdev i/f +* - Prevent any further requests from mgmt i/f +* - If there are any waitq'd mgmt requests or mgmt-frame exchanges, +* shut them down. +* - Call the MSD hwremoved function. +* +* The remainder of the cleanup will be handled by unregister(). +* Our primary goal here is to prevent as much tickling of the MSD +* as possible since the MSD is already in a 'wounded' state. +* +* TODO: As new features are added, this function should be +* updated. +* +* Arguments: +* wlandev WLAN network device structure +* Returns: +* nothing +* Side effects: +* +* Call context: +* Usually interrupt. +----------------------------------------------------------------*/ +void p80211netdev_hwremoved(wlandevice_t *wlandev) +{ + DBFENTER; + wlandev->hwremoved = 1; + if ( wlandev->state == WLAN_DEVICE_OPEN) { + p80211netdev_stop_queue(wlandev); + } + + netif_device_detach(wlandev->netdev); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* p80211_rx_typedrop +* +* Classifies the frame, increments the appropriate counter, and +* returns 0|1|2 indicating whether the driver should handle, ignore, or +* drop the frame +* +* Arguments: +* wlandev wlan device structure +* fc frame control field +* +* Returns: +* zero if the frame should be handled by the driver, +* one if the frame should be ignored +* anything else means we drop it. +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc) +{ + UINT16 ftype; + UINT16 fstype; + int drop = 0; + /* Classify frame, increment counter */ + ftype = WLAN_GET_FC_FTYPE(fc); + fstype = WLAN_GET_FC_FSTYPE(fc); +#if 0 + WLAN_LOG_DEBUG(4, + "rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype); +#endif + switch ( ftype ) { + case WLAN_FTYPE_MGMT: + if ((wlandev->netdev->flags & IFF_PROMISC) || + (wlandev->netdev->flags & IFF_ALLMULTI)) { + drop = 1; + break; + } + WLAN_LOG_DEBUG(3, "rx'd mgmt:\n"); + wlandev->rx.mgmt++; + switch( fstype ) { + case WLAN_FSTYPE_ASSOCREQ: + /* printk("assocreq"); */ + wlandev->rx.assocreq++; + break; + case WLAN_FSTYPE_ASSOCRESP: + /* printk("assocresp"); */ + wlandev->rx.assocresp++; + break; + case WLAN_FSTYPE_REASSOCREQ: + /* printk("reassocreq"); */ + wlandev->rx.reassocreq++; + break; + case WLAN_FSTYPE_REASSOCRESP: + /* printk("reassocresp"); */ + wlandev->rx.reassocresp++; + break; + case WLAN_FSTYPE_PROBEREQ: + /* printk("probereq"); */ + wlandev->rx.probereq++; + break; + case WLAN_FSTYPE_PROBERESP: + /* printk("proberesp"); */ + wlandev->rx.proberesp++; + break; + case WLAN_FSTYPE_BEACON: + /* printk("beacon"); */ + wlandev->rx.beacon++; + break; + case WLAN_FSTYPE_ATIM: + /* printk("atim"); */ + wlandev->rx.atim++; + break; + case WLAN_FSTYPE_DISASSOC: + /* printk("disassoc"); */ + wlandev->rx.disassoc++; + break; + case WLAN_FSTYPE_AUTHEN: + /* printk("authen"); */ + wlandev->rx.authen++; + break; + case WLAN_FSTYPE_DEAUTHEN: + /* printk("deauthen"); */ + wlandev->rx.deauthen++; + break; + default: + /* printk("unknown"); */ + wlandev->rx.mgmt_unknown++; + break; + } + /* printk("\n"); */ + drop = 2; + break; + + case WLAN_FTYPE_CTL: + if ((wlandev->netdev->flags & IFF_PROMISC) || + (wlandev->netdev->flags & IFF_ALLMULTI)) { + drop = 1; + break; + } + WLAN_LOG_DEBUG(3, "rx'd ctl:\n"); + wlandev->rx.ctl++; + switch( fstype ) { + case WLAN_FSTYPE_PSPOLL: + /* printk("pspoll"); */ + wlandev->rx.pspoll++; + break; + case WLAN_FSTYPE_RTS: + /* printk("rts"); */ + wlandev->rx.rts++; + break; + case WLAN_FSTYPE_CTS: + /* printk("cts"); */ + wlandev->rx.cts++; + break; + case WLAN_FSTYPE_ACK: + /* printk("ack"); */ + wlandev->rx.ack++; + break; + case WLAN_FSTYPE_CFEND: + /* printk("cfend"); */ + wlandev->rx.cfend++; + break; + case WLAN_FSTYPE_CFENDCFACK: + /* printk("cfendcfack"); */ + wlandev->rx.cfendcfack++; + break; + default: + /* printk("unknown"); */ + wlandev->rx.ctl_unknown++; + break; + } + /* printk("\n"); */ + drop = 2; + break; + + case WLAN_FTYPE_DATA: + wlandev->rx.data++; + switch( fstype ) { + case WLAN_FSTYPE_DATAONLY: + wlandev->rx.dataonly++; + break; + case WLAN_FSTYPE_DATA_CFACK: + wlandev->rx.data_cfack++; + break; + case WLAN_FSTYPE_DATA_CFPOLL: + wlandev->rx.data_cfpoll++; + break; + case WLAN_FSTYPE_DATA_CFACK_CFPOLL: + wlandev->rx.data__cfack_cfpoll++; + break; + case WLAN_FSTYPE_NULL: + WLAN_LOG_DEBUG(3, "rx'd data:null\n"); + wlandev->rx.null++; + break; + case WLAN_FSTYPE_CFACK: + WLAN_LOG_DEBUG(3, "rx'd data:cfack\n"); + wlandev->rx.cfack++; + break; + case WLAN_FSTYPE_CFPOLL: + WLAN_LOG_DEBUG(3, "rx'd data:cfpoll\n"); + wlandev->rx.cfpoll++; + break; + case WLAN_FSTYPE_CFACK_CFPOLL: + WLAN_LOG_DEBUG(3, "rx'd data:cfack_cfpoll\n"); + wlandev->rx.cfack_cfpoll++; + break; + default: + /* printk("unknown"); */ + wlandev->rx.data_unknown++; + break; + } + + break; + } + return drop; +} + +#ifdef CONFIG_HOTPLUG +/* Notify userspace when a netdevice event occurs, + * by running '/sbin/hotplug net' with certain + * environment variables set. + */ +int p80211_run_sbin_hotplug(wlandevice_t *wlandev, char *action) +{ + char *argv[3], *envp[7], ifname[12 + IFNAMSIZ], action_str[32]; + char nsdname[32], wlan_wext[32]; + int i; + + if (wlandev) { + sprintf(ifname, "INTERFACE=%s", wlandev->name); + sprintf(nsdname, "NSDNAME=%s", wlandev->nsdname); + } else { + sprintf(ifname, "INTERFACE=null"); + sprintf(nsdname, "NSDNAME=null"); + } + + sprintf(wlan_wext, "WLAN_WEXT=%s", wlan_wext_write ? "y" : ""); + sprintf(action_str, "ACTION=%s", action); + + i = 0; + argv[i++] = hotplug_path; + argv[i++] = "wlan"; + argv[i] = NULL; + + i = 0; + /* minimal command environment */ + envp [i++] = "HOME=/"; + envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + envp [i++] = ifname; + envp [i++] = action_str; + envp [i++] = nsdname; + envp [i++] = wlan_wext; + envp [i] = NULL; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62)) + return call_usermodehelper(argv [0], argv, envp); +#else + return call_usermodehelper(argv [0], argv, envp, 0); +#endif +} + +#endif + + +void p80211_suspend(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_SUSPEND); +#endif + + DBFEXIT; +} + +void p80211_resume(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_RESUME); +#endif + + DBFEXIT; +} + +static void p80211knetdev_tx_timeout( netdevice_t *netdev) +{ + wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; + DBFENTER; + + if (wlandev->tx_timeout) { + wlandev->tx_timeout(wlandev); + } else { + WLAN_LOG_WARNING("Implement tx_timeout for %s\n", + wlandev->nsdname); + p80211netdev_wake_queue(wlandev); + } + + DBFEXIT; +} + +void p80211_allow_ioctls(wlandevice_t *wlandev) { + mutex_unlock(&wlandev->ioctl_lock); +} --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/p80211mod.c +++ linux-2.6.27/ubuntu/misc/wireless/p80211/p80211mod.c @@ -0,0 +1,219 @@ +/* src/p80211/p80211mod.c +* +* Module entry and exit for p80211 +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file contains the p80211.o entry and exit points defined for linux +* kernel modules. +* +* Notes: +* - all module parameters for p80211.o should be defined here. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include + +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25)) +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +/*================================================================*/ +/* Project Includes */ + +#include +#include +#include +#include +#include +#include +#include + +/*================================================================*/ +/* Local Constants */ + + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + +static char *version = "p80211.o: " WLAN_RELEASE; + + +/*----------------------------------------------------------------*/ +/* --Module Parameters */ + +int wlan_watchdog = 5000; +module_param(wlan_watchdog, int, 0644); +MODULE_PARM_DESC(wlan_watchdog, "transmit timeout in milliseconds"); + +int wlan_wext_write = 1; +#if WIRELESS_EXT > 12 +module_param(wlan_wext_write, int, 0644); +MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions"); +#endif + +#ifdef WLAN_INCLUDE_DEBUG +int wlan_debug=0; +module_param(wlan_debug, int, 0644); +MODULE_PARM_DESC(wlan_debug, "p80211 debug level"); +#endif + +MODULE_LICENSE("Dual MPL/GPL"); + +/*================================================================*/ +/* Local Function Declarations */ + +int init_module(void); +void cleanup_module(void); + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* init_module +* +* Module initialization routine, called once at module load time. +* +* Arguments: +* none +* +* Returns: +* 0 - success +* ~0 - failure, module is unloaded. +* +* Side effects: +* TODO: define +* +* Call context: +* process thread (insmod or modprobe) +----------------------------------------------------------------*/ +int init_module(void) +{ + DBFENTER; + +#if 0 + printk(KERN_NOTICE "%s (%s) Loaded\n", version, WLAN_BUILD_DATE); +#endif + + p80211netdev_startup(); +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(NULL, WLAN_HOTPLUG_STARTUP); +#endif + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* cleanup_module +* +* Called at module unload time. This is our last chance to +* clean up after ourselves. +* +* Arguments: +* none +* +* Returns: +* nothing +* +* Side effects: +* TODO: define +* +* Call context: +* process thread +* +----------------------------------------------------------------*/ +void cleanup_module(void) +{ + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(NULL, WLAN_HOTPLUG_SHUTDOWN); +#endif + p80211netdev_shutdown(); + printk(KERN_NOTICE "%s Unloaded\n", version); + + DBFEXIT; + return; +} + +EXPORT_SYMBOL(p80211netdev_hwremoved); +EXPORT_SYMBOL(register_wlandev); +EXPORT_SYMBOL(p80211netdev_rx); +EXPORT_SYMBOL(unregister_wlandev); +EXPORT_SYMBOL(wlan_setup); +EXPORT_SYMBOL(wlan_unsetup); +EXPORT_SYMBOL(p80211_suspend); +EXPORT_SYMBOL(p80211_resume); + +EXPORT_SYMBOL(p80211skb_free); +EXPORT_SYMBOL(p80211skb_rxmeta_attach); + +EXPORT_SYMBOL(p80211wext_event_associated); + +EXPORT_SYMBOL(wlan_wext_write); +EXPORT_SYMBOL(p80211_allow_ioctls); --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/Makefile +++ linux-2.6.27/ubuntu/misc/wireless/p80211/Makefile @@ -0,0 +1,11 @@ +obj-$(CONFIG_P80211) := p80211.o + +p80211-objs := p80211mod.o \ + p80211conv.o \ + p80211req.o \ + p80211wep.o \ + p80211wext.o \ + p80211netdev.o + +EXTRA_CFLAGS += -DWLAN_TXMGMT_MINBRATE -DRSN_INTERNAL_ROAM \ + -DWLAN_HOSTIF=WLAN_NONE -I$(src) --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/p80211wext.c +++ linux-2.6.27/ubuntu/misc/wireless/p80211/p80211wext.c @@ -0,0 +1,2174 @@ +/* src/p80211/p80211wext.c +* +* Glue code to make linux-wlan-ng a happy wireless extension camper. +* +* original author: Reyk Floeter +* Completely re-written by Solomon Peachy +* +* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#if WIRELESS_EXT > 12 +#include +#endif +#include +#include +#include +#include + +/*================================================================*/ +/* Project Includes */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int p80211wext_giwrate(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra); +static int p80211wext_giwessid(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid); +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +static UINT8 p80211_mhz_to_channel(UINT16 mhz) +{ + if (mhz >= 5000) { + return ((mhz - 5000) / 5); + } + + if (mhz == 2482) + return 14; + + if (mhz >= 2407) { + return ((mhz - 2407) / 5); + } + + return 0; +} + +static UINT16 p80211_channel_to_mhz(UINT8 ch, int dot11a) +{ + + if (ch == 0) + return 0; + if (ch > 200) + return 0; + + /* 5G */ + + if (dot11a) { + return (5000 + (5 * ch)); + } + + /* 2.4G */ + + if (ch == 14) + return 2484; + + if ((ch < 14) && (ch > 0)) { + return (2407 + (5 * ch)); + } + + return 0; +} + +/* taken from orinoco.c ;-) */ +static const long p80211wext_channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; +#define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0])) + +/* steal a spare bit to store the shared/opensystems state. should default to open if not set */ +#define HOSTWEP_SHAREDKEY BIT3 + + +/** function declarations =============== */ + +static int qual_as_percent(int snr ) { + if ( snr <= 0 ) + return 0; + if ( snr <= 40 ) + return snr*5/2; + return 100; +} + +static inline int invalid_state(wlandevice_t *wlandev ) { + return wlandev->msdstate != WLAN_MSD_RUNNING; +} + +static int p80211wext_dorequest(wlandevice_t *wlandev, UINT32 did, UINT32 data) +{ + p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + int result; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = did; + mibitem.data = data; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + DBFEXIT; + return result; +} + +static int p80211wext_autojoin(wlandevice_t *wlandev) +{ + p80211msg_lnxreq_autojoin_t msg; + struct iw_point data; + char ssid[IW_ESSID_MAX_SIZE]; + + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + + /* Get ESSID */ + result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid); + + if (result) { + err = -EFAULT; + goto exit; + } + + if ( wlandev->hostwep & HOSTWEP_SHAREDKEY ) + msg.authtype.data = P80211ENUM_authalg_sharedkey; + else + msg.authtype.data = P80211ENUM_authalg_opensystem; + + msg.msgcode = DIDmsg_lnxreq_autojoin; + + /* Trim the last '\0' to fit the SSID format */ + + if (data.length && ssid[data.length-1] == '\0') { + data.length = data.length - 1; + } + + memcpy(msg.ssid.data.data, ssid, data.length); + msg.ssid.data.len = data.length; + + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + +exit: + + DBFEXIT; + return err; + +} + +/* called by /proc/net/wireless */ +struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev) +{ + p80211msg_lnxreq_commsquality_t quality; + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_statistics* wstats = &wlandev->wstats; + int retval; + + DBFENTER; + /* Check */ + if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) ) + return NULL; + + /* XXX Only valid in station mode */ + wstats->status = 0; + + /* build request message */ + quality.msgcode = DIDmsg_lnxreq_commsquality; + quality.dbm.data = P80211ENUM_truth_true; + quality.dbm.status = P80211ENUM_msgitem_status_data_ok; + + /* send message to nsd */ + if ( wlandev->mlmerequest == NULL ) + return NULL; + + retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality); + + wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */ + wstats->qual.level = quality.level.data; /* instant signal level */ + wstats->qual.noise = quality.noise.data; /* instant noise level */ + +#if WIRELESS_EXT > 18 + wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; +#else + wstats->qual.updated = 7; +#endif + wstats->discard.code = wlandev->rx.decrypt_err; + wstats->discard.nwid = 0; + wstats->discard.misc = 0; + +#if WIRELESS_EXT > 11 + wstats->discard.fragment = 0; // incomplete fragments + wstats->discard.retries = 0; // tx retries. + wstats->miss.beacon = 0; +#endif + + DBFEXIT; + + return wstats; +} + +static int p80211wext_giwname(netdevice_t *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + struct iw_param rate; + int result; + int err = 0; + + DBFENTER; + + result = p80211wext_giwrate(dev, NULL, &rate, NULL); + + if (result) { + err = -EFAULT; + goto exit; + } + + switch (rate.value) { + case 1000000: + case 2000000: + strcpy(name, "IEEE 802.11-DS"); + break; + case 5500000: + case 11000000: + strcpy(name, "IEEE 802.11-b"); + break; + } +exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwfreq(netdevice_t *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + if (mibitem.data > NUM_CHANNELS) { + err = -EFAULT; + goto exit; + } + + /* convert into frequency instead of a channel */ + freq->e = 1; + freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000; + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_siwfreq(netdevice_t *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; + mibitem.status = P80211ENUM_msgitem_status_data_ok; + + if ( (freq->e == 0) && (freq->m <= 1000) ) + mibitem.data = freq->m; + else + mibitem.data = p80211_mhz_to_channel(freq->m); + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +#if WIRELESS_EXT > 8 + +static int p80211wext_giwmode(netdevice_t *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + switch (wlandev->macmode) { + case WLAN_MACMODE_IBSS_STA: + *mode = IW_MODE_ADHOC; + break; + case WLAN_MACMODE_ESS_STA: + *mode = IW_MODE_INFRA; + break; + case WLAN_MACMODE_ESS_AP: + *mode = IW_MODE_MASTER; + break; + default: + /* Not set yet. */ + *mode = IW_MODE_AUTO; + } + + DBFEXIT; + return 0; +} + +static int p80211wext_siwmode(netdevice_t *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA && + *mode != IW_MODE_MASTER) { + err = (-EOPNOTSUPP); + goto exit; + } + + /* Operation mode is the same with current mode */ + if (*mode == wlandev->macmode) + goto exit; + + switch (*mode) { + case IW_MODE_ADHOC: + wlandev->macmode = WLAN_MACMODE_IBSS_STA; + break; + case IW_MODE_INFRA: + wlandev->macmode = WLAN_MACMODE_ESS_STA; + break; + case IW_MODE_MASTER: + wlandev->macmode = WLAN_MACMODE_ESS_AP; + break; + default: + /* Not set yet. */ + WLAN_LOG_INFO("Operation mode: %d not support\n", *mode); + return -EOPNOTSUPP; + } + + /* Set Operation mode to the PORT TYPE RID */ + +#warning "get rid of p2mib here" + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = DIDmib_p2_p2Static_p2CnfPortType; + mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) + err = -EFAULT; + + exit: + DBFEXIT; + + return err; +} + + +static int p80211wext_giwrange(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + struct iw_range *range = (struct iw_range *) extra; + int i, val; + + DBFENTER; + + // for backward compatability set size & zero everything we don't understand + data->length = sizeof(*range); + memset(range,0,sizeof(*range)); + +#if WIRELESS_EXT > 9 + range->txpower_capa = IW_TXPOW_DBM; + // XXX what about min/max_pmp, min/max_pmt, etc. +#endif + +#if WIRELESS_EXT > 10 + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 13; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; +#endif /* WIRELESS_EXT > 10 */ + +#if WIRELESS_EXT > 16 + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode + range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) | + IW_EVENT_CAPA_MASK(IWEVCUSTOM) ); +#endif + + range->num_channels = NUM_CHANNELS; + + /* XXX need to filter against the regulatory domain &| active set */ + val = 0; + for (i = 0; i < NUM_CHANNELS ; i++) { + range->freq[val].i = i + 1; + range->freq[val].m = p80211wext_channel_freq[i] * 100000; + range->freq[val].e = 1; + val++; + } + + range->num_frequency = val; + + /* Max of /proc/net/wireless */ + range->max_qual.qual = 100; + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->sensitivity = 3; + // XXX these need to be nsd-specific! + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + + range->max_encoding_tokens = NUM_WEPKEYS; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + // XXX what about num_bitrates/throughput? + range->num_bitrates = 0; + + /* estimated max throughput */ + // XXX need to cap it if we're running at ~2Mbps.. + range->throughput = 5500000; + + DBFEXIT; + return 0; +} +#endif + +static int p80211wext_giwap(netdevice_t *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN); + ap_addr->sa_family = ARPHRD_ETHER; + + DBFEXIT; + return 0; +} + +#if WIRELESS_EXT > 8 +static int p80211wext_giwencode(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *erq, char *key) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + int err = 0; + int i; + + DBFENTER; + + i = (erq->flags & IW_ENCODE_INDEX) - 1; + erq->flags = 0; + + if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) + erq->flags |= IW_ENCODE_ENABLED; + else + erq->flags |= IW_ENCODE_DISABLED; + + if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) + erq->flags |= IW_ENCODE_RESTRICTED; + else + erq->flags |= IW_ENCODE_OPEN; + + if (i == -1) + i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; + + if ((i < 0) || (i >= NUM_WEPKEYS)) { + err = -EINVAL; + goto exit; + } + + erq->flags |= i + 1; + + /* copy the key from the driver cache as the keys are read-only MIBs */ + erq->length = wlandev->wep_keylens[i]; + memcpy(key, wlandev->wep_keys[i], erq->length); + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_siwencode(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *erq, char *key) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t pstr; + + int err = 0; + int result = 0; + int i; + + DBFENTER; + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + /* Check the Key index first. */ + if((i = (erq->flags & IW_ENCODE_INDEX))) { + + if ((i < 1) || (i > NUM_WEPKEYS)) { + err = -EINVAL; + goto exit; + } else { + i--; + } + + /* Set current key number only if no keys are given */ + if (erq->flags & IW_ENCODE_NOKEY) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i); + + if (result) { + err = -EFAULT; + goto exit; + } + } + + } else { + // Use defaultkey if no Key Index + i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; + } + + /* Check if there is no key information in the iwconfig request */ + if((erq->flags & IW_ENCODE_NOKEY) == 0 ) { + + /*------------------------------------------------------------ + * If there is WEP Key for setting, check the Key Information + * and then set it to the firmware. + -------------------------------------------------------------*/ + + if (erq->length > 0) { + + /* copy the key from the driver cache as the keys are read-only MIBs */ + wlandev->wep_keylens[i] = erq->length; + memcpy(wlandev->wep_keys[i], key, erq->length); + + /* Prepare data struture for p80211req_dorequest. */ + memcpy(pstr.data.data, key, erq->length); + pstr.data.len = erq->length; + + switch(i) + { + case 0: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } + + } + + /* Check the PrivacyInvoked flag */ + if (erq->flags & IW_ENCODE_DISABLED) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); + } else { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); + } + + if (result) { + err = -EFAULT; + goto exit; + } + + /* The security mode may be open or restricted, and its meaning + depends on the card used. With most cards, in open mode no + authentication is used and the card may also accept non- + encrypted sessions, whereas in restricted mode only encrypted + sessions are accepted and the card will use authentication if + available. + */ + if (erq->flags & IW_ENCODE_RESTRICTED) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true); + // wlandev->hostwep |= HOSTWEP_SHAREDKEY; + } else if (erq->flags & IW_ENCODE_OPEN) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false); + // wlandev->hostwep &= ~HOSTWEP_SHAREDKEY; + } + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + + DBFEXIT; + return err; +} + +static int p80211wext_giwessid(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + if (wlandev->ssid.len) { + data->length = wlandev->ssid.len; + data->flags = 1; + memcpy(essid, wlandev->ssid.data, data->length); + essid[data->length] = 0; +#if (WIRELESS_EXT < 21) + data->length++; +#endif + } else { + memset(essid, 0, sizeof(wlandev->ssid.data)); + data->length = 0; + data->flags = 0; + } + + DBFEXIT; + return 0; +} + +static int p80211wext_siwessid(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_lnxreq_autojoin_t msg; + + int result; + int err = 0; + int length = data->length; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + + if ( wlandev->hostwep & HOSTWEP_SHAREDKEY ) + msg.authtype.data = P80211ENUM_authalg_sharedkey; + else + msg.authtype.data = P80211ENUM_authalg_opensystem; + + msg.msgcode = DIDmsg_lnxreq_autojoin; + +#if (WIRELESS_EXT < 21) + if (length) length--; +#endif + + /* Trim the last '\0' to fit the SSID format */ + + if (length && essid[length-1] == '\0') { + length--; + } + + memcpy(msg.ssid.data.data, essid, length); + msg.ssid.data.len = length; + + WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + + +static int p80211wext_siwcommit(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + /* Auto Join */ + err = p80211wext_autojoin(wlandev); + + exit: + DBFEXIT; + return err; +} + + +static int p80211wext_giwrate(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + rrq->fixed = 0; /* can it change? */ + rrq->disabled = 0; + rrq->value = 0; + +#define HFA384x_RATEBIT_1 ((UINT16)1) +#define HFA384x_RATEBIT_2 ((UINT16)2) +#define HFA384x_RATEBIT_5dot5 ((UINT16)4) +#define HFA384x_RATEBIT_11 ((UINT16)8) + + switch (mibitem.data) { + case HFA384x_RATEBIT_1: + rrq->value = 1000000; + break; + case HFA384x_RATEBIT_2: + rrq->value = 2000000; + break; + case HFA384x_RATEBIT_5dot5: + rrq->value = 5500000; + break; + case HFA384x_RATEBIT_11: + rrq->value = 11000000; + break; + default: + err = -EINVAL; + } + exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwrts(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + rts->value = mibitem.data; + rts->disabled = (rts->value == 2347); + rts->fixed = 1; + + exit: + DBFEXIT; + return err; +} + + +static int p80211wext_siwrts(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold; + if (rts->disabled) + mibitem.data = 2347; + else + mibitem.data = rts->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwfrag(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + frag->value = mibitem.data; + frag->disabled = (frag->value == 2346); + frag->fixed = 1; + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_siwfrag(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; + + if (frag->disabled) + mibitem.data = 2346; + else + mibitem.data = frag->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +#endif /* WIRELESS_EXT > 8 */ + +#if WIRELESS_EXT > 10 + +#ifndef IW_RETRY_LONG +#define IW_RETRY_LONG IW_RETRY_MAX +#endif + +#ifndef IW_RETRY_SHORT +#define IW_RETRY_SHORT IW_RETRY_MIN +#endif + +static int p80211wext_giwretry(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + UINT16 shortretry, longretry, lifetime; + + DBFENTER; + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + shortretry = mibitem.data; + + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + longretry = mibitem.data; + + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + lifetime = mibitem.data; + + rrq->disabled = 0; + + if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + rrq->flags = IW_RETRY_LIFETIME; + rrq->value = lifetime * 1024; + } else { + if (rrq->flags & IW_RETRY_LONG) { + rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; + rrq->value = longretry; + } else { + rrq->flags = IW_RETRY_LIMIT; + rrq->value = shortretry; + if (shortretry != longretry) + rrq->flags |= IW_RETRY_SHORT; + } + } + + exit: + DBFEXIT; + return err; + +} + +static int p80211wext_siwretry(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + if (rrq->disabled) { + err = -EINVAL; + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + + if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; + mibitem.data = rrq->value /= 1024; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } else { + if (rrq->flags & IW_RETRY_LONG) { + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit; + mibitem.data = rrq->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } + + if (rrq->flags & IW_RETRY_SHORT) { + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit; + mibitem.data = rrq->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } + } + + exit: + DBFEXIT; + return err; + +} + +#endif /* WIRELESS_EXT > 10 */ + +#if WIRELESS_EXT > 9 +static int p80211wext_siwtxpow(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + + switch (rrq->value) { + + case 1 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1; break; + case 2 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2; break; + case 3 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3; break; + case 4 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4; break; + case 5 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5; break; + case 6 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6; break; + case 7 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7; break; + case 8 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break; + default: mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break; + } + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwtxpow(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + // XXX handle OFF by setting disabled = 1; + + rrq->flags = 0; // IW_TXPOW_DBM; + rrq->disabled = 0; + rrq->fixed = 0; + rrq->value = mibitem.data; + + exit: + DBFEXIT; + return err; +} +#endif /* WIRELESS_EXT > 9 */ + +static int p80211wext_siwspy(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct sockaddr address[IW_MAX_SPY]; + int number = srq->length; + int i; + + DBFENTER; + + /* Copy the data from the input buffer */ + memcpy(address, extra, sizeof(struct sockaddr)*number); + + wlandev->spy_number = 0; + + if (number > 0) { + + /* extract the addresses */ + for (i = 0; i < number; i++) { + + memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN); + } + + /* reset stats */ + memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY); + + /* set number of addresses */ + wlandev->spy_number = number; + } + + DBFEXIT; + return 0; +} + +/* jkriegl: from orinoco, modified */ +static int p80211wext_giwspy(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + struct sockaddr address[IW_MAX_SPY]; + struct iw_quality spy_stat[IW_MAX_SPY]; + int number; + int i; + + DBFENTER; + + number = wlandev->spy_number; + + if (number > 0) { + + /* populate address and spy struct's */ + for (i = 0; i < number; i++) { + memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN); + address[i].sa_family = AF_UNIX; + memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality)); + } + + /* reset update flag */ + for (i=0; i < number; i++) + wlandev->spy_stat[i].updated = 0; + } + + /* push stuff to user space */ + srq->length = number; + memcpy(extra, address, sizeof(struct sockaddr)*number); + memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number); + + DBFEXIT; + return 0; +} + +static int prism2_result2err (int prism2_result) +{ + int err = 0; + + switch (prism2_result) { + case P80211ENUM_resultcode_invalid_parameters: + err = -EINVAL; + break; + case P80211ENUM_resultcode_implementation_failure: + err = -EIO; + break; + case P80211ENUM_resultcode_not_supported: + err = -EOPNOTSUPP; + break; + default: + err = 0; + break; + } + + return err; +} + +#if WIRELESS_EXT > 13 +static int p80211wext_siwscan(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_dot11req_scan_t msg; + int result; + int err = 0; + int i = 0; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { + WLAN_LOG_ERROR("Can't scan in AP mode\n"); + err = (-EOPNOTSUPP); + goto exit; + } + + memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t)); + msg.msgcode = DIDmsg_dot11req_scan; + msg.bsstype.data = P80211ENUM_bsstype_any; + + memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t)); + msg.bssid.data.len = 6; + + msg.scantype.data = P80211ENUM_scantype_active; + msg.probedelay.data = 0; + + for (i = 1; i <= 14; i++) + msg.channellist.data.data[i-1] = i; + msg.channellist.data.len = 14; + + msg.maxchanneltime.data = 250; + msg.minchanneltime.data = 200; + + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + if (result) + err = prism2_result2err (msg.resultcode.data); + + exit: + DBFEXIT; + return err; +} + + +/* Helper to translate scan into Wireless Extensions scan results. + * Inspired by the prism54 code, which was in turn inspired by the + * airo driver code. + */ +static char * +wext_translate_bss(char *current_ev, char *end_buf, p80211msg_dot11req_scan_results_t *bss, + struct iw_request_info *info) +{ + struct iw_event iwe; /* Temporary buffer */ + + /* The first entry must be the MAC address */ + memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN); + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + iwe.cmd = SIOCGIWAP; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + + /* The following entries will be displayed in the same order we give them */ + + /* The ESSID. */ + if (bss->ssid.data.len > 0) { + char essid[IW_ESSID_MAX_SIZE + 1]; + int size; + + size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len); + memset(&essid, 0, sizeof (essid)); + memcpy(&essid, bss->ssid.data.data, size); + WLAN_LOG_DEBUG(1, " essid size = %d\n", size); + iwe.u.data.length = size; + iwe.u.data.flags = 1; + iwe.cmd = SIOCGIWESSID; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]); + WLAN_LOG_DEBUG(1, " essid size OK.\n"); + } + + switch (bss->bsstype.data) { + case P80211ENUM_bsstype_infrastructure: + iwe.u.mode = IW_MODE_MASTER; + break; + + case P80211ENUM_bsstype_independent: + iwe.u.mode = IW_MODE_ADHOC; + break; + + default: + iwe.u.mode = 0; + break; + } + iwe.cmd = SIOCGIWMODE; + if (iwe.u.mode) + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + + /* Encryption capability */ + if (bss->privacy.data == P80211ENUM_truth_true) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + iwe.cmd = SIOCGIWENCODE; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL); + + /* Add frequency. (short) bss->channel is the frequency in MHz */ + iwe.u.freq.m = bss->dschannel.data; + iwe.u.freq.e = 0; + iwe.cmd = SIOCGIWFREQ; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + + /* Add quality statistics */ + iwe.u.qual.level = bss->signal.data; + iwe.u.qual.noise = bss->noise.data; + /* do a simple SNR for quality */ + iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data); + iwe.cmd = IWEVQUAL; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + + return current_ev; +} + + +static int p80211wext_giwscan(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_dot11req_scan_results_t msg; + int result = 0; + int err = 0; + int i = 0; + int scan_good = 0; + char *current_ev = extra; + + DBFENTER; + + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + err = -EBUSY; + goto exit; + } + + /* Since wireless tools doesn't really have a way of passing how + * many scan results results there were back here, keep grabbing them + * until we fail. + */ + do { + memset(&msg, 0, sizeof(msg)); + msg.msgcode = DIDmsg_dot11req_scan_results; + msg.bssindex.data = i; + + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + if ((result != 0) || + (msg.resultcode.data != P80211ENUM_resultcode_success)) { + break; + } + + current_ev = wext_translate_bss(current_ev, extra + IW_SCAN_MAX_DATA, &msg, info); + scan_good = 1; + i++; + } while (i < IW_MAX_AP); + + srq->length = (current_ev - extra); + srq->flags = 0; /* todo */ + + if (result && !scan_good) + err = prism2_result2err (msg.resultcode.data); + exit: + DBFEXIT; + return err; +} +#endif + +/*****************************************************/ +//extra wireless extensions stuff to support NetworkManager (I hope) + +#if WIRELESS_EXT > 17 +/* SIOCSIWENCODEEXT */ +static int p80211wext_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t *pstr; + + int result = 0; + struct iw_point *encoding = &wrqu->encoding; + int idx = encoding->flags & IW_ENCODE_INDEX; + + DBFENTER; + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + result = -EBUSY; + goto exit; + } + + WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len); + + + if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) { + // set default key ? I'm not sure if this the the correct thing to do here + + if ( idx ) { + if (idx < 1 || idx > NUM_WEPKEYS) { + return -EINVAL; + } else + idx--; + } + WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx); + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx); + if ( result ) + return -EFAULT; + } + + + if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) { + if ( ! ext->alg & IW_ENCODE_ALG_WEP) { + WLAN_LOG_DEBUG(1,"asked to set a non wep key :("); + return -EINVAL; + } + if (idx) { + if (idx <1 || idx > NUM_WEPKEYS) + return -EINVAL; + else + idx--; + } + WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx); + wlandev->wep_keylens[idx] = ext->key_len; + memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len); + + memset( &msg,0,sizeof(msg)); + pstr = (p80211item_pstr32_t*)&msg.mibattribute.data; + memcpy(pstr->data.data, ext->key,ext->key_len); + pstr->data.len = ext->key_len; + switch (idx) { + case 0: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + case 1: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + case 2: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + case 3: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + default: + break; + } + msg.msgcode = DIDmsg_dot11req_mibset; + result = p80211req_dorequest(wlandev,(UINT8*)&msg); + WLAN_LOG_DEBUG(1,"result (%d)\n",result); + } + exit: + DBFEXIT; + return result; +} + +/* SIOCGIWENCODEEXT */ +static int p80211wext_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) + +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + + struct iw_point *encoding = &wrqu->encoding; + int result = 0; + int max_len; + int idx; + + DBFENTER; + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + result = -EBUSY; + goto exit; + } + + + WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len); + + + max_len = encoding->length - sizeof(*ext); + if ( max_len <= 0) { + WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len); + result = -EINVAL; + goto exit; + } + idx = encoding->flags & IW_ENCODE_INDEX; + + WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx); + + if (idx) { + if (idx < 1 || idx > NUM_WEPKEYS ) { + WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx); + result = -EINVAL; + goto exit; + } + idx--; + } else { + /* default key ? not sure what to do */ + /* will just use key[0] for now ! FIX ME */ + } + + encoding->flags = idx + 1; + memset(ext,0,sizeof(*ext)); + + ext->alg = IW_ENCODE_ALG_WEP; + ext->key_len = wlandev->wep_keylens[idx]; + memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len ); + + encoding->flags |= IW_ENCODE_ENABLED; +exit: + DBFEXIT; + + return result; +} + + +/* SIOCSIWAUTH */ +static int p80211_wext_set_iwauth (struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_param *param = &wrqu->param; + int result =0; + + DBFENTER; + if ( invalid_state(wlandev) ) { + WLAN_LOG_DEBUG(1,"called from invalid state [%d]\n",wlandev->msdstate); + result = -EBUSY; + goto exit; + } + + + WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX ); + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value); + if (param->value) + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true); + else + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false); + break; + + case IW_AUTH_PRIVACY_INVOKED: + WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value); + if ( param->value) + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); + else + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); + + break; + + case IW_AUTH_80211_AUTH_ALG: + if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) { + WLAN_LOG_DEBUG(1,"set open_system\n"); + wlandev->hostwep &= ~HOSTWEP_SHAREDKEY; + } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) { + WLAN_LOG_DEBUG(1,"set shared key\n"); + wlandev->hostwep |= HOSTWEP_SHAREDKEY; + } else { + /* don't know what to do know :( */ + WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value); + result = -EINVAL; + } + break; + + default: + break; + } + + exit: + DBFEXIT; + return result; +} + +/* SIOCSIWAUTH */ +static int p80211_wext_get_iwauth (struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_param *param = &wrqu->param; + int result =0; + + DBFENTER; + WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX ); + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0; + break; + + case IW_AUTH_PRIVACY_INVOKED: + param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0; + break; + + case IW_AUTH_80211_AUTH_ALG: + param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM; + break; + + + default: + break; + } + + DBFEXIT; + + return result; +} + + +#endif + + + + + + +/*****************************************************/ + + + + + +/* +typedef int (*iw_handler)(netdevice_t *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +*/ + +#if WIRELESS_EXT > 12 +static iw_handler p80211wext_handlers[] = { + (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */ + (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */ + (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */ + (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */ + (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */ + (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */ + (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */ + (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */ + (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWAP */ + (iw_handler) p80211wext_giwap, /* SIOCGIWAP */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCGIWAPLIST */ +#if WIRELESS_EXT > 13 + (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */ + (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */ +#else /* WIRELESS_EXT > 13 */ + (iw_handler) NULL, /* null */ /* SIOCSIWSCAN */ + (iw_handler) NULL, /* null */ /* SIOCGIWSCAN */ +#endif /* WIRELESS_EXT > 13 */ + (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */ + (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWRATE */ + (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */ + (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */ + (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */ + (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */ + (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */ + (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */ + (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */ + (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */ + (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ +#if WIRELESS_EXT > 17 +/* WPA operations */ + + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */ + (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */ + (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */ + (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */ + + (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */ + (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */ + (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */ +#endif +}; + +struct iw_handler_def p80211wext_handler_def = { + .num_standard = sizeof(p80211wext_handlers) / sizeof(iw_handler), + .num_private = 0, + .num_private_args = 0, + .standard = p80211wext_handlers, + .private = NULL, + .private_args = NULL, +#if WIRELESS_EXT > 16 + .get_wireless_stats = p80211wext_get_wireless_stats +#endif +}; + +#endif + +/* wireless extensions' ioctls */ +int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + +#if WIRELESS_EXT < 13 + struct iwreq *iwr = (struct iwreq*)ifr; +#endif + + p80211item_uint32_t mibitem; + int err = 0; + + DBFENTER; + + mibitem.status = P80211ENUM_msgitem_status_data_ok; + + if ( wlandev->msdstate != WLAN_MSD_RUNNING ) { + err = -ENODEV; + goto exit; + } + + WLAN_LOG_DEBUG(1, "Received wireless extension ioctl #%d.\n", cmd); + + switch (cmd) { +#if WIRELESS_EXT < 13 + case SIOCSIWNAME: /* unused */ + err = (-EOPNOTSUPP); + break; + case SIOCGIWNAME: /* get name == wireless protocol */ + err = p80211wext_giwname(dev, NULL, (char *) &iwr->u, NULL); + break; + case SIOCSIWNWID: + case SIOCGIWNWID: + err = (-EOPNOTSUPP); + break; + case SIOCSIWFREQ: /* set channel */ + err = p80211wext_siwfreq(dev, NULL, &(iwr->u.freq), NULL); + break; + case SIOCGIWFREQ: /* get channel */ + err = p80211wext_giwfreq(dev, NULL, &(iwr->u.freq), NULL); + break; + case SIOCSIWRANGE: + case SIOCSIWPRIV: + case SIOCSIWAP: /* set access point MAC addresses (BSSID) */ + err = (-EOPNOTSUPP); + break; + + case SIOCGIWAP: /* get access point MAC addresses (BSSID) */ + err = p80211wext_giwap(dev, NULL, &(iwr->u.ap_addr), NULL); + break; + +#if WIRELESS_EXT > 8 + case SIOCSIWMODE: /* set operation mode */ + case SIOCSIWESSID: /* set SSID (network name) */ + case SIOCSIWRATE: /* set default bit rate (bps) */ + err = (-EOPNOTSUPP); + break; + + case SIOCGIWMODE: /* get operation mode */ + err = p80211wext_giwmode(dev, NULL, &iwr->u.mode, NULL); + + break; + case SIOCGIWNICKN: /* get node name/nickname */ + case SIOCGIWESSID: /* get SSID */ + if(iwr->u.essid.pointer) { + char ssid[IW_ESSID_MAX_SIZE+1]; + memset(ssid, 0, sizeof(ssid)); + + err = p80211wext_giwessid(dev, NULL, &iwr->u.essid, ssid); + if(copy_to_user(iwr->u.essid.pointer, ssid, sizeof(ssid))) + err = (-EFAULT); + } + break; + case SIOCGIWRATE: + err = p80211wext_giwrate(dev, NULL, &iwr->u.bitrate, NULL); + break; + case SIOCGIWRTS: + err = p80211wext_giwrts(dev, NULL, &iwr->u.rts, NULL); + break; + case SIOCGIWFRAG: + err = p80211wext_giwfrag(dev, NULL, &iwr->u.rts, NULL); + break; + case SIOCGIWENCODE: + if (!capable(CAP_NET_ADMIN)) + err = -EPERM; + else if (iwr->u.encoding.pointer) { + char keybuf[MAX_KEYLEN]; + err = p80211wext_giwencode(dev, NULL, + &iwr->u.encoding, keybuf); + if (copy_to_user(iwr->u.encoding.pointer, keybuf, + iwr->u.encoding.length)) + err = -EFAULT; + } + break; + case SIOCGIWAPLIST: + case SIOCSIWRTS: + case SIOCSIWFRAG: + case SIOCSIWSENS: + case SIOCGIWSENS: + case SIOCSIWNICKN: /* set node name/nickname */ + case SIOCSIWENCODE: /* set encoding token & mode */ + case SIOCSIWSPY: + case SIOCGIWSPY: + case SIOCSIWPOWER: + case SIOCGIWPOWER: + case SIOCGIWPRIV: + err = (-EOPNOTSUPP); + break; + case SIOCGIWRANGE: + if(iwr->u.data.pointer != NULL) { + struct iw_range range; + err = p80211wext_giwrange(dev, NULL, &iwr->u.data, + (char *) &range); + /* Push that up to the caller */ + if (copy_to_user(iwr->u.data.pointer, &range, sizeof(range))) + err = -EFAULT; + } + break; +#endif /* WIRELESS_EXT > 8 */ +#if WIRELESS_EXT > 9 + case SIOCSIWTXPOW: + err = (-EOPNOTSUPP); + break; + case SIOCGIWTXPOW: + err = p80211wext_giwtxpow(dev, NULL, &iwr->u.txpower, NULL); + break; +#endif /* WIRELESS_EXT > 9 */ +#if WIRELESS_EXT > 10 + case SIOCSIWRETRY: + err = (-EOPNOTSUPP); + break; + case SIOCGIWRETRY: + err = p80211wext_giwretry(dev, NULL, &iwr->u.retry, NULL); + break; +#endif /* WIRELESS_EXT > 10 */ + +#endif /* WIRELESS_EXT <= 12 */ + + default: + err = (-EOPNOTSUPP); + break; + } + + exit: + DBFEXIT; + return (err); +} + +int p80211wext_event_associated(wlandevice_t *wlandev, int assoc) +{ + union iwreq_data data; + + DBFENTER; + +#if WIRELESS_EXT > 13 + /* Send the association state first */ + data.ap_addr.sa_family = ARPHRD_ETHER; + if (assoc) { + memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN); + } else { + memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN); + } + + if (wlan_wext_write) + wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL); + + if (!assoc) goto done; + + // XXX send association data, like IEs, etc etc. +#endif + done: + DBFEXIT; + return 0; +} + + +#endif /* compatibility to wireless extensions */ + + + + --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211metastruct.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211metastruct.h @@ -0,0 +1,644 @@ +/* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. +* -------------------------------------------------------------------- +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MKMETASTRUCT_H +#define _P80211MKMETASTRUCT_H + + +typedef struct p80211msg_dot11req_mibget +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk392_t mibattribute ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibget_t; + +typedef struct p80211msg_dot11req_mibset +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk392_t mibattribute ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibset_t; + +typedef struct p80211msg_dot11req_powermgmt +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t powermgmtmode ; + p80211item_uint32_t wakeup ; + p80211item_uint32_t receivedtims ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_powermgmt_t; + +typedef struct p80211msg_dot11req_scan +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t bsstype ; + p80211item_pstr6_t bssid ; + UINT8 pad_0C[1] ; + p80211item_pstr32_t ssid ; + UINT8 pad_1D[3] ; + p80211item_uint32_t scantype ; + p80211item_uint32_t probedelay ; + p80211item_pstr14_t channellist ; + UINT8 pad_2C[1] ; + p80211item_uint32_t minchanneltime ; + p80211item_uint32_t maxchanneltime ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t numbss ; + p80211item_uint32_t append ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_t; + +typedef struct p80211msg_dot11req_scan_results +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t bssindex ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t signal ; + p80211item_uint32_t noise ; + p80211item_pstr6_t bssid ; + UINT8 pad_3C[1] ; + p80211item_pstr32_t ssid ; + UINT8 pad_4D[3] ; + p80211item_uint32_t bsstype ; + p80211item_uint32_t beaconperiod ; + p80211item_uint32_t dtimperiod ; + p80211item_uint32_t timestamp ; + p80211item_uint32_t localtime ; + p80211item_uint32_t fhdwelltime ; + p80211item_uint32_t fhhopset ; + p80211item_uint32_t fhhoppattern ; + p80211item_uint32_t fhhopindex ; + p80211item_uint32_t dschannel ; + p80211item_uint32_t cfpcount ; + p80211item_uint32_t cfpperiod ; + p80211item_uint32_t cfpmaxduration ; + p80211item_uint32_t cfpdurremaining ; + p80211item_uint32_t ibssatimwindow ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t privacy ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t supprate1 ; + p80211item_uint32_t supprate2 ; + p80211item_uint32_t supprate3 ; + p80211item_uint32_t supprate4 ; + p80211item_uint32_t supprate5 ; + p80211item_uint32_t supprate6 ; + p80211item_uint32_t supprate7 ; + p80211item_uint32_t supprate8 ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_results_t; + +typedef struct p80211msg_dot11req_join +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t bssid ; + UINT8 pad_5C[1] ; + p80211item_uint32_t joinfailuretimeout ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t operationalrate1 ; + p80211item_uint32_t operationalrate2 ; + p80211item_uint32_t operationalrate3 ; + p80211item_uint32_t operationalrate4 ; + p80211item_uint32_t operationalrate5 ; + p80211item_uint32_t operationalrate6 ; + p80211item_uint32_t operationalrate7 ; + p80211item_uint32_t operationalrate8 ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_join_t; + +typedef struct p80211msg_dot11req_authenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_6C[1] ; + p80211item_uint32_t authenticationtype ; + p80211item_uint32_t authenticationfailuretimeout ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_authenticate_t; + +typedef struct p80211msg_dot11req_deauthenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_7C[1] ; + p80211item_uint32_t reasoncode ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_deauthenticate_t; + +typedef struct p80211msg_dot11req_associate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_8C[1] ; + p80211item_uint32_t associatefailuretimeout ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t privacy ; + p80211item_uint32_t listeninterval ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_associate_t; + +typedef struct p80211msg_dot11req_reassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t newapaddress ; + UINT8 pad_9C[1] ; + p80211item_uint32_t reassociatefailuretimeout ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t privacy ; + p80211item_uint32_t listeninterval ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_reassociate_t; + +typedef struct p80211msg_dot11req_disassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_10C[1] ; + p80211item_uint32_t reasoncode ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_disassociate_t; + +typedef struct p80211msg_dot11req_reset +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t setdefaultmib ; + p80211item_pstr6_t macaddress ; + UINT8 pad_11C[1] ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_reset_t; + +typedef struct p80211msg_dot11req_start +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr32_t ssid ; + UINT8 pad_12D[3] ; + p80211item_uint32_t bsstype ; + p80211item_uint32_t beaconperiod ; + p80211item_uint32_t dtimperiod ; + p80211item_uint32_t cfpperiod ; + p80211item_uint32_t cfpmaxduration ; + p80211item_uint32_t fhdwelltime ; + p80211item_uint32_t fhhopset ; + p80211item_uint32_t fhhoppattern ; + p80211item_uint32_t dschannel ; + p80211item_uint32_t ibssatimwindow ; + p80211item_uint32_t probedelay ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t operationalrate1 ; + p80211item_uint32_t operationalrate2 ; + p80211item_uint32_t operationalrate3 ; + p80211item_uint32_t operationalrate4 ; + p80211item_uint32_t operationalrate5 ; + p80211item_uint32_t operationalrate6 ; + p80211item_uint32_t operationalrate7 ; + p80211item_uint32_t operationalrate8 ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_start_t; + +typedef struct p80211msg_dot11ind_authenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_13C[1] ; + p80211item_uint32_t authenticationtype ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_authenticate_t; + +typedef struct p80211msg_dot11ind_deauthenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_14C[1] ; + p80211item_uint32_t reasoncode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_deauthenticate_t; + +typedef struct p80211msg_dot11ind_associate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_15C[1] ; + p80211item_uint32_t aid ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_associate_t; + +typedef struct p80211msg_dot11ind_reassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_16C[1] ; + p80211item_uint32_t aid ; + p80211item_pstr6_t oldapaddress ; + UINT8 pad_17C[1] ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_reassociate_t; + +typedef struct p80211msg_dot11ind_disassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_18C[1] ; + p80211item_uint32_t reasoncode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_disassociate_t; + +typedef struct p80211msg_lnxreq_ifstate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t ifstate ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_ifstate_t; + +typedef struct p80211msg_lnxreq_wlansniff +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t channel ; + p80211item_uint32_t prismheader ; + p80211item_uint32_t wlanheader ; + p80211item_uint32_t keepwepflags ; + p80211item_uint32_t stripfcs ; + p80211item_uint32_t packet_trunc ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_wlansniff_t; + +typedef struct p80211msg_lnxreq_hostwep +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t decrypt ; + p80211item_uint32_t encrypt ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_hostwep_t; + +typedef struct p80211msg_lnxreq_commsquality +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t dbm ; + p80211item_uint32_t link ; + p80211item_uint32_t level ; + p80211item_uint32_t noise ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_commsquality_t; + +typedef struct p80211msg_lnxreq_autojoin +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr32_t ssid ; + UINT8 pad_19D[3] ; + p80211item_uint32_t authtype ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_autojoin_t; + +typedef struct p80211msg_lnxind_wlansniffrm +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t hosttime ; + p80211item_uint32_t mactime ; + p80211item_uint32_t channel ; + p80211item_uint32_t rssi ; + p80211item_uint32_t sq ; + p80211item_uint32_t signal ; + p80211item_uint32_t noise ; + p80211item_uint32_t rate ; + p80211item_uint32_t istx ; + p80211item_uint32_t frmlen ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxind_wlansniffrm_t; + +typedef struct p80211msg_lnxind_roam +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t reason ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxind_roam_t; + +typedef struct p80211msg_p2req_join +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t bssid ; + UINT8 pad_20C[1] ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t operationalrate1 ; + p80211item_uint32_t operationalrate2 ; + p80211item_uint32_t operationalrate3 ; + p80211item_uint32_t operationalrate4 ; + p80211item_uint32_t operationalrate5 ; + p80211item_uint32_t operationalrate6 ; + p80211item_uint32_t operationalrate7 ; + p80211item_uint32_t operationalrate8 ; + p80211item_pstr32_t ssid ; + UINT8 pad_21D[3] ; + p80211item_uint32_t channel ; + p80211item_uint32_t authtype ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_join_t; + +typedef struct p80211msg_p2req_readpda +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk1024_t pda ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readpda_t; + +typedef struct p80211msg_p2req_readcis +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk1024_t cis ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readcis_t; + +typedef struct p80211msg_p2req_auxport_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_state_t; + +typedef struct p80211msg_p2req_auxport_read +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk1024_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_read_t; + +typedef struct p80211msg_p2req_auxport_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk1024_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_write_t; + +typedef struct p80211msg_p2req_low_level +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t command ; + p80211item_uint32_t param0 ; + p80211item_uint32_t param1 ; + p80211item_uint32_t param2 ; + p80211item_uint32_t resp0 ; + p80211item_uint32_t resp1 ; + p80211item_uint32_t resp2 ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_low_level_t; + +typedef struct p80211msg_p2req_test_command +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t testcode ; + p80211item_uint32_t testparam ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t status ; + p80211item_uint32_t resp0 ; + p80211item_uint32_t resp1 ; + p80211item_uint32_t resp2 ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_test_command_t; + +typedef struct p80211msg_p2req_mmi_read +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t value ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mmi_read_t; + +typedef struct p80211msg_p2req_mmi_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mmi_write_t; + +typedef struct p80211msg_p2req_ramdl_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t exeaddr ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_state_t; + +typedef struct p80211msg_p2req_ramdl_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk4096_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_write_t; + +typedef struct p80211msg_p2req_flashdl_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_state_t; + +typedef struct p80211msg_p2req_flashdl_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk4096_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_write_t; + +typedef struct p80211msg_p2req_mm_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mm_state_t; + +typedef struct p80211msg_p2req_dump_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t level ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_dump_state_t; + +typedef struct p80211msg_p2req_channel_info +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t channellist ; + p80211item_uint32_t channeldwelltime ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t numchinfo ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_channel_info_t; + +typedef struct p80211msg_p2req_channel_info_results +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t channel ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t avgnoiselevel ; + p80211item_uint32_t peaknoiselevel ; + p80211item_uint32_t bssactive ; + p80211item_uint32_t pcfactive ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_channel_info_results_t; + +typedef struct p80211msg_p2req_enable +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_enable_t; + +#endif --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211netdev.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211netdev.h @@ -0,0 +1,339 @@ +/* src/include/wlan/p80211netdev.h +* +* WLAN net device structure and functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the structure type that represents each wlan +* interface. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _LINUX_P80211NETDEV_H +#define _LINUX_P80211NETDEV_H + +#include +#include + +/*================================================================*/ +/* Constants */ + +#define WLAN_DEVICE_CLOSED 0 +#define WLAN_DEVICE_OPEN 1 + +#define WLAN_MACMODE_NONE 0 +#define WLAN_MACMODE_IBSS_STA 1 +#define WLAN_MACMODE_ESS_STA 2 +#define WLAN_MACMODE_ESS_AP 3 + +/* MSD States */ +#define WLAN_MSD_START -1 +#define WLAN_MSD_DRIVERLOADED 0 +#define WLAN_MSD_HWPRESENT_PENDING 1 +#define WLAN_MSD_HWFAIL 2 +#define WLAN_MSD_HWPRESENT 3 +#define WLAN_MSD_FWLOAD_PENDING 4 +#define WLAN_MSD_FWLOAD 5 +#define WLAN_MSD_RUNNING_PENDING 6 +#define WLAN_MSD_RUNNING 7 + +#ifndef ETH_P_ECONET +#define ETH_P_ECONET 0x0018 /* needed for 2.2.x kernels */ +#endif + +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) + +#ifndef ARPHRD_IEEE80211 +#define ARPHRD_IEEE80211 801 /* kernel 2.4.6 */ +#endif + +#ifndef ARPHRD_IEEE80211_PRISM /* kernel 2.4.18 */ +#define ARPHRD_IEEE80211_PRISM 802 +#endif + +/*--- NSD Capabilities Flags ------------------------------*/ +#define P80211_NSDCAP_HARDWAREWEP 0x01 /* hardware wep engine */ +#define P80211_NSDCAP_TIEDWEP 0x02 /* can't decouple en/de */ +#define P80211_NSDCAP_NOHOSTWEP 0x04 /* must use hardware wep */ +#define P80211_NSDCAP_PBCC 0x08 /* hardware supports PBCC */ +#define P80211_NSDCAP_SHORT_PREAMBLE 0x10 /* hardware supports */ +#define P80211_NSDCAP_AGILITY 0x20 /* hardware supports */ +#define P80211_NSDCAP_AP_RETRANSMIT 0x40 /* nsd handles retransmits */ +#define P80211_NSDCAP_HWFRAGMENT 0x80 /* nsd handles frag/defrag */ +#define P80211_NSDCAP_AUTOJOIN 0x100 /* nsd does autojoin */ +#define P80211_NSDCAP_NOSCAN 0x200 /* nsd can scan */ + +/*================================================================*/ +/* Macros */ + +/*================================================================*/ +/* Types */ + +/* Received frame statistics */ +typedef struct p80211_frmrx_t +{ + UINT32 mgmt; + UINT32 assocreq; + UINT32 assocresp; + UINT32 reassocreq; + UINT32 reassocresp; + UINT32 probereq; + UINT32 proberesp; + UINT32 beacon; + UINT32 atim; + UINT32 disassoc; + UINT32 authen; + UINT32 deauthen; + UINT32 mgmt_unknown; + UINT32 ctl; + UINT32 pspoll; + UINT32 rts; + UINT32 cts; + UINT32 ack; + UINT32 cfend; + UINT32 cfendcfack; + UINT32 ctl_unknown; + UINT32 data; + UINT32 dataonly; + UINT32 data_cfack; + UINT32 data_cfpoll; + UINT32 data__cfack_cfpoll; + UINT32 null; + UINT32 cfack; + UINT32 cfpoll; + UINT32 cfack_cfpoll; + UINT32 data_unknown; + UINT32 decrypt; + UINT32 decrypt_err; +} p80211_frmrx_t; + +#ifdef WIRELESS_EXT +/* called by /proc/net/wireless */ +struct iw_statistics* p80211wext_get_wireless_stats(netdevice_t *dev); +/* wireless extensions' ioctls */ +int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd); +#if WIRELESS_EXT > 12 +extern struct iw_handler_def p80211wext_handler_def; +#endif + +int p80211wext_event_associated(struct wlandevice *wlandev, int assoc); + +#endif /* wireless extensions */ + +/* WEP stuff */ +#define NUM_WEPKEYS 4 +#define MAX_KEYLEN 32 + +#define HOSTWEP_DEFAULTKEY_MASK (BIT1|BIT0) +#define HOSTWEP_DECRYPT BIT4 +#define HOSTWEP_ENCRYPT BIT5 +#define HOSTWEP_PRIVACYINVOKED BIT6 +#define HOSTWEP_EXCLUDEUNENCRYPTED BIT7 + +extern int wlan_watchdog; +extern int wlan_wext_write; + +/* WLAN device type */ +typedef struct wlandevice +{ + struct wlandevice *next; /* link for list of devices */ + void *priv; /* private data for MSD */ + + /* Subsystem State */ + char name[WLAN_DEVNAMELEN_MAX]; /* Dev name, from register_wlandev()*/ + char *nsdname; + + UINT32 state; /* Device I/F state (open/closed) */ + UINT32 msdstate; /* state of underlying driver */ + UINT32 hwremoved; /* Has the hw been yanked out? */ + + /* Hardware config */ + UINT irq; + UINT iobase; + UINT membase; + UINT32 nsdcaps; /* NSD Capabilities flags */ + + /* Config vars */ + UINT ethconv; + + /* device methods (init by MSD, used by p80211 */ + int (*open)(struct wlandevice *wlandev); + int (*close)(struct wlandevice *wlandev); + void (*reset)(struct wlandevice *wlandev ); + int (*txframe)(struct wlandevice *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); + int (*mlmerequest)(struct wlandevice *wlandev, p80211msg_t *msg); + int (*set_multicast_list)(struct wlandevice *wlandev, + netdevice_t *dev); + void (*tx_timeout)(struct wlandevice *wlandev); + +#ifdef CONFIG_PROC_FS + int (*nsd_proc_read)(char *page, char **start, off_t offset, int count, int *eof, void *data); +#endif + + /* 802.11 State */ + UINT8 bssid[WLAN_BSSID_LEN]; + p80211pstr32_t ssid; + UINT32 macmode; + int linkstatus; + int shortpreamble; /* C bool */ + + /* WEP State */ + UINT8 wep_keys[NUM_WEPKEYS][MAX_KEYLEN]; + UINT8 wep_keylens[NUM_WEPKEYS]; + int hostwep; + + /* Request/Confirm i/f state (used by p80211) */ + unsigned long request_pending; /* flag, access atomically */ + + /* netlink socket */ + /* queue for indications waiting for cmd completion */ + /* Linux netdevice and support */ + netdevice_t *netdev; /* ptr to linux netdevice */ + struct net_device_stats linux_stats; + +#ifdef CONFIG_PROC_FS + /* Procfs support */ + struct proc_dir_entry *procdir; + struct proc_dir_entry *procwlandev; +#endif + + /* Rx bottom half */ + struct tasklet_struct rx_bh; + + struct sk_buff_head nsd_rxq; + + /* 802.11 device statistics */ + struct p80211_frmrx_t rx; + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + struct iw_statistics wstats; + + /* jkriegl: iwspy fields */ + UINT8 spy_number; + char spy_address[IW_MAX_SPY][ETH_ALEN]; + struct iw_quality spy_stat[IW_MAX_SPY]; + +#endif + + struct mutex ioctl_lock; +} wlandevice_t; + +/* WEP stuff */ +int wep_change_key(wlandevice_t *wlandev, int keynum, UINT8* key, int keylen); +int wep_decrypt(wlandevice_t *wlandev, UINT8 *buf, UINT32 len, int key_override, UINT8 *iv, UINT8 *icv); +int wep_encrypt(wlandevice_t *wlandev, UINT8 *buf, UINT8 *dst, UINT32 len, int keynum, UINT8 *iv, UINT8 *icv); + +/*================================================================*/ +/* Externs */ + +/*================================================================*/ +/* Function Declarations */ + +void p80211netdev_startup(void); +void p80211netdev_shutdown(void); +int wlan_setup(wlandevice_t *wlandev); +int wlan_unsetup(wlandevice_t *wlandev); +int register_wlandev(wlandevice_t *wlandev); +int unregister_wlandev(wlandevice_t *wlandev); +void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); +void p80211netdev_hwremoved(wlandevice_t *wlandev); +void p80211_suspend(wlandevice_t *wlandev); +void p80211_resume(wlandevice_t *wlandev); + +void p80211_allow_ioctls(wlandevice_t *wlandev); + +/*================================================================*/ +/* Function Definitions */ + +static inline void +p80211netdev_stop_queue(wlandevice_t *wlandev) +{ + if ( !wlandev ) return; + if ( !wlandev->netdev ) return; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + wlandev->netdev->tbusy = 1; + wlandev->netdev->start = 0; +#else + netif_stop_queue(wlandev->netdev); +#endif +} + +static inline void +p80211netdev_start_queue(wlandevice_t *wlandev) +{ + if ( !wlandev ) return; + if ( !wlandev->netdev ) return; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + wlandev->netdev->tbusy = 0; + wlandev->netdev->start = 1; +#else + netif_start_queue(wlandev->netdev); +#endif +} + +static inline void +p80211netdev_wake_queue(wlandevice_t *wlandev) +{ + if ( !wlandev ) return; + if ( !wlandev->netdev ) return; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + wlandev->netdev->tbusy = 0; + mark_bh(NET_BH); +#else + netif_wake_queue(wlandev->netdev); +#endif +} + +#ifdef CONFIG_HOTPLUG +#define WLAN_HOTPLUG_REGISTER "register" +#define WLAN_HOTPLUG_REMOVE "remove" +#define WLAN_HOTPLUG_STARTUP "startup" +#define WLAN_HOTPLUG_SHUTDOWN "shutdown" +#define WLAN_HOTPLUG_SUSPEND "suspend" +#define WLAN_HOTPLUG_RESUME "resume" +int p80211_run_sbin_hotplug(wlandevice_t *wlandev, char *action); +#endif + +#endif --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211types.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211types.h @@ -0,0 +1,675 @@ +/* src/include/wlan/p80211types.h +* +* Macros, constants, types, and funcs for p80211 data types +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211TYPES_H +#define _P80211TYPES_H + +/*================================================================*/ +/* System Includes */ +/*================================================================*/ + +/*================================================================*/ +/* Project Includes */ +/*================================================================*/ + +#ifndef _WLAN_COMPAT_H +#include +#endif + +/*================================================================*/ +/* Constants */ +/*================================================================*/ + +/*----------------------------------------------------------------*/ +/* p80211 data type codes used for MIB items and message */ +/* arguments. The various metadata structures provide additional */ +/* information about these types. */ + +#define P80211_TYPE_OCTETSTR 1 /* pascal array of bytes */ +#define P80211_TYPE_DISPLAYSTR 2 /* pascal array of bytes containing ascii */ +#define P80211_TYPE_INT 4 /* UINT32 min and max limited by 32 bits */ +#define P80211_TYPE_ENUMINT 5 /* UINT32 holding a numeric + code that can be mapped + to a textual name */ +#define P80211_TYPE_UNKDATA 6 /* Data item containing an + unknown data type */ +#define P80211_TYPE_INTARRAY 7 /* Array of 32-bit integers. */ +#define P80211_TYPE_BITARRAY 8 /* Array of bits. */ +#define P80211_TYPE_MACARRAY 9 /* Array of MAC addresses. */ + +/*----------------------------------------------------------------*/ +/* The following constants are indexes into the Mib Category List */ +/* and the Message Category List */ + +/* Mib Category List */ +#define P80211_MIB_CAT_DOT11SMT 1 +#define P80211_MIB_CAT_DOT11MAC 2 +#define P80211_MIB_CAT_DOT11PHY 3 + +#define P80211SEC_DOT11SMT P80211_MIB_CAT_DOT11SMT +#define P80211SEC_DOT11MAC P80211_MIB_CAT_DOT11MAC +#define P80211SEC_DOT11PHY P80211_MIB_CAT_DOT11PHY + +/* Message Category List */ +#define P80211_MSG_CAT_DOT11REQ 1 +#define P80211_MSG_CAT_DOT11IND 2 +/* #define P80211_MSG_CAT_DOT11CFM 3 (doesn't exist at this time) */ + +#define P80211SEC_DOT11REQ P80211_MSG_CAT_DOT11REQ +#define P80211SEC_DOT11IND P80211_MSG_CAT_DOT11IND +/* #define P80211SEC_DOT11CFM P80211_MSG_CAT_DOT11CFM (doesn't exist at this time */ + + + +/*----------------------------------------------------------------*/ +/* p80211 DID field codes that represent access type and */ +/* is_table status. */ + +#define P80211DID_ACCESS_READ 0x10000000 +#define P80211DID_ACCESS_WRITE 0x08000000 +#define P80211DID_WRITEONLY 0x00000001 +#define P80211DID_READONLY 0x00000002 +#define P80211DID_READWRITE 0x00000003 +#define P80211DID_ISTABLE_FALSE 0 +#define P80211DID_ISTABLE_TRUE 1 + +/*----------------------------------------------------------------*/ +/* p80211 enumeration constants. The value to text mappings for */ +/* these is in p80211types.c. These defines were generated */ +/* from the mappings. */ + +/* error codes for lookups */ +#define P80211ENUM_BAD 0xffffffffUL +#define P80211ENUM_BADSTR "P80211ENUM_BAD" + +#define P80211ENUM_truth_false 0 +#define P80211ENUM_truth_true 1 +#define P80211ENUM_ifstate_disable 0 +#define P80211ENUM_ifstate_fwload 1 +#define P80211ENUM_ifstate_enable 2 +#define P80211ENUM_powermgmt_active 1 +#define P80211ENUM_powermgmt_powersave 2 +#define P80211ENUM_bsstype_infrastructure 1 +#define P80211ENUM_bsstype_independent 2 +#define P80211ENUM_bsstype_any 3 +#define P80211ENUM_authalg_opensystem 1 +#define P80211ENUM_authalg_sharedkey 2 +#define P80211ENUM_phytype_fhss 1 +#define P80211ENUM_phytype_dsss 2 +#define P80211ENUM_phytype_irbaseband 3 +#define P80211ENUM_temptype_commercial 1 +#define P80211ENUM_temptype_industrial 2 +#define P80211ENUM_regdomain_fcc 16 +#define P80211ENUM_regdomain_doc 32 +#define P80211ENUM_regdomain_etsi 48 +#define P80211ENUM_regdomain_spain 49 +#define P80211ENUM_regdomain_france 50 +#define P80211ENUM_regdomain_mkk 64 +#define P80211ENUM_ccamode_edonly 1 +#define P80211ENUM_ccamode_csonly 2 +#define P80211ENUM_ccamode_edandcs 4 +#define P80211ENUM_ccamode_cswithtimer 8 +#define P80211ENUM_ccamode_hrcsanded 16 +#define P80211ENUM_diversity_fixedlist 1 +#define P80211ENUM_diversity_notsupported 2 +#define P80211ENUM_diversity_dynamic 3 +#define P80211ENUM_scantype_active 1 +#define P80211ENUM_scantype_passive 2 +#define P80211ENUM_scantype_both 3 +#define P80211ENUM_resultcode_success 1 +#define P80211ENUM_resultcode_invalid_parameters 2 +#define P80211ENUM_resultcode_not_supported 3 +#define P80211ENUM_resultcode_timeout 4 +#define P80211ENUM_resultcode_too_many_req 5 +#define P80211ENUM_resultcode_refused 6 +#define P80211ENUM_resultcode_bss_already 7 +#define P80211ENUM_resultcode_invalid_access 8 +#define P80211ENUM_resultcode_invalid_mibattribute 9 +#define P80211ENUM_resultcode_cant_set_readonly_mib 10 +#define P80211ENUM_resultcode_implementation_failure 11 +#define P80211ENUM_resultcode_cant_get_writeonly_mib 12 +#define P80211ENUM_reason_unspec_reason 1 +#define P80211ENUM_reason_auth_not_valid 2 +#define P80211ENUM_reason_deauth_lv_ss 3 +#define P80211ENUM_reason_inactivity 4 +#define P80211ENUM_reason_ap_overload 5 +#define P80211ENUM_reason_class23_err 6 +#define P80211ENUM_reason_class3_err 7 +#define P80211ENUM_reason_disas_lv_ss 8 +#define P80211ENUM_reason_asoc_not_auth 9 +#define P80211ENUM_status_successful 0 +#define P80211ENUM_status_unspec_failure 1 +#define P80211ENUM_status_unsup_cap 10 +#define P80211ENUM_status_reasoc_no_asoc 11 +#define P80211ENUM_status_fail_other 12 +#define P80211ENUM_status_unspt_alg 13 +#define P80211ENUM_status_auth_seq_fail 14 +#define P80211ENUM_status_chlng_fail 15 +#define P80211ENUM_status_auth_timeout 16 +#define P80211ENUM_status_ap_full 17 +#define P80211ENUM_status_unsup_rate 18 +#define P80211ENUM_status_unsup_shortpreamble 19 +#define P80211ENUM_status_unsup_pbcc 20 +#define P80211ENUM_status_unsup_agility 21 +#define P80211ENUM_msgitem_status_data_ok 0 +#define P80211ENUM_msgitem_status_no_value 1 +#define P80211ENUM_msgitem_status_invalid_itemname 2 +#define P80211ENUM_msgitem_status_invalid_itemdata 3 +#define P80211ENUM_msgitem_status_missing_itemdata 4 +#define P80211ENUM_msgitem_status_incomplete_itemdata 5 +#define P80211ENUM_msgitem_status_invalid_msg_did 6 +#define P80211ENUM_msgitem_status_invalid_mib_did 7 +#define P80211ENUM_msgitem_status_missing_conv_func 8 +#define P80211ENUM_msgitem_status_string_too_long 9 +#define P80211ENUM_msgitem_status_data_out_of_range 10 +#define P80211ENUM_msgitem_status_string_too_short 11 +#define P80211ENUM_msgitem_status_missing_valid_func 12 +#define P80211ENUM_msgitem_status_unknown 13 +#define P80211ENUM_msgitem_status_invalid_did 14 +#define P80211ENUM_msgitem_status_missing_print_func 15 + +#define P80211ENUM_lnxroam_reason_unknown 0 +#define P80211ENUM_lnxroam_reason_beacon 1 +#define P80211ENUM_lnxroam_reason_signal 2 +#define P80211ENUM_lnxroam_reason_txretry 3 +#define P80211ENUM_lnxroam_reason_notjoined 4 + +#define P80211ENUM_p2preamble_long 0 +#define P80211ENUM_p2preamble_short 2 +#define P80211ENUM_p2preamble_mixed 3 + +/*----------------------------------------------------------------*/ +/* p80211 max length constants for the different pascal strings. */ + +#define MAXLEN_PSTR6 (6) /* pascal array of 6 bytes */ +#define MAXLEN_PSTR14 (14) /* pascal array of 14 bytes */ +#define MAXLEN_PSTR32 (32) /* pascal array of 32 bytes */ +#define MAXLEN_PSTR255 (255) /* pascal array of 255 bytes */ +#define MAXLEN_MIBATTRIBUTE (392) /* maximum mibattribute */ + /* where the size of the DATA itself */ + /* is a DID-LEN-DATA triple */ + /* with a max size of 4+4+384 */ + +#define P80211_SET_INT(item, value) do { \ + (item).data = (value); \ + (item).status = P80211ENUM_msgitem_status_data_ok; \ + } while(0) +/*----------------------------------------------------------------*/ +/* string constants */ + +#define NOT_SET "NOT_SET" +#define NOT_SUPPORTED "NOT_SUPPORTED" +#define UNKNOWN_DATA "UNKNOWN_DATA" + + +/*--------------------------------------------------------------------*/ +/* Metadata flags */ + +/* MSM: Do these belong in p80211meta.h? I'm not sure. */ + +#define ISREQUIRED (0x80000000UL) +#define ISREQUEST (0x40000000UL) +#define ISCONFIRM (0x20000000UL) + + +/*================================================================*/ +/* Macros */ + +/*--------------------------------------------------------------------*/ +/* The following macros are used to manipulate the 'flags' field in */ +/* the metadata. These are only used when the metadata is for */ +/* command arguments to determine if the data item is required, and */ +/* whether the metadata item is for a request command, confirm */ +/* command or both. */ +/*--------------------------------------------------------------------*/ +/* MSM: Do these belong in p80211meta.h? I'm not sure */ + +#define P80211ITEM_SETFLAGS(q, r, c) ( q | r | c ) + +#define P80211ITEM_ISREQUIRED(flags) (((UINT32)(flags & ISREQUIRED)) >> 31 ) +#define P80211ITEM_ISREQUEST(flags) (((UINT32)(flags & ISREQUEST)) >> 30 ) +#define P80211ITEM_ISCONFIRM(flags) (((UINT32)(flags & ISCONFIRM)) >> 29 ) + +/*----------------------------------------------------------------*/ +/* The following macro creates a name for an enum */ + +#define MKENUMNAME(name) p80211enum_ ## name + +/*---------------------------------------------------------------- +* The following constants and macros are used to construct and +* deconstruct the Data ID codes. The coding is as follows: +* +* ...rwtnnnnnnnniiiiiiggggggssssss s - Section +* g - Group +* i - Item +* n - Index +* t - Table flag +* w - Write flag +* r - Read flag +* . - Unused +*/ + +#define P80211DID_INVALID 0xffffffffUL +#define P80211DID_VALID 0x00000000UL + +#define P80211DID_LSB_SECTION (0) +#define P80211DID_LSB_GROUP (6) +#define P80211DID_LSB_ITEM (12) +#define P80211DID_LSB_INDEX (18) +#define P80211DID_LSB_ISTABLE (26) +#define P80211DID_LSB_ACCESS (27) + +#define P80211DID_MASK_SECTION (0x0000003fUL) +#define P80211DID_MASK_GROUP (0x0000003fUL) +#define P80211DID_MASK_ITEM (0x0000003fUL) +#define P80211DID_MASK_INDEX (0x000000ffUL) +#define P80211DID_MASK_ISTABLE (0x00000001UL) +#define P80211DID_MASK_ACCESS (0x00000003UL) + + +#define P80211DID_MK(a,m,l) ((((UINT32)(a)) & (m)) << (l)) + +#define P80211DID_MKSECTION(a) P80211DID_MK(a, \ + P80211DID_MASK_SECTION, \ + P80211DID_LSB_SECTION ) +#define P80211DID_MKGROUP(a) P80211DID_MK(a, \ + P80211DID_MASK_GROUP, \ + P80211DID_LSB_GROUP ) +#define P80211DID_MKITEM(a) P80211DID_MK(a, \ + P80211DID_MASK_ITEM, \ + P80211DID_LSB_ITEM ) +#define P80211DID_MKINDEX(a) P80211DID_MK(a, \ + P80211DID_MASK_INDEX, \ + P80211DID_LSB_INDEX ) +#define P80211DID_MKISTABLE(a) P80211DID_MK(a, \ + P80211DID_MASK_ISTABLE, \ + P80211DID_LSB_ISTABLE ) + + +#define P80211DID_MKID(s,g,i,n,t,a) (P80211DID_MKSECTION(s) | \ + P80211DID_MKGROUP(g) | \ + P80211DID_MKITEM(i) | \ + P80211DID_MKINDEX(n) | \ + P80211DID_MKISTABLE(t) | \ + (a) ) + + +#define P80211DID_GET(a,m,l) ((((UINT32)(a)) >> (l)) & (m)) + +#define P80211DID_SECTION(a) P80211DID_GET(a, \ + P80211DID_MASK_SECTION, \ + P80211DID_LSB_SECTION) +#define P80211DID_GROUP(a) P80211DID_GET(a, \ + P80211DID_MASK_GROUP, \ + P80211DID_LSB_GROUP) +#define P80211DID_ITEM(a) P80211DID_GET(a, \ + P80211DID_MASK_ITEM, \ + P80211DID_LSB_ITEM) +#define P80211DID_INDEX(a) P80211DID_GET(a, \ + P80211DID_MASK_INDEX, \ + P80211DID_LSB_INDEX) +#define P80211DID_ISTABLE(a) P80211DID_GET(a, \ + P80211DID_MASK_ISTABLE, \ + P80211DID_LSB_ISTABLE) +#define P80211DID_ACCESS(a) P80211DID_GET(a, \ + P80211DID_MASK_ACCESS, \ + P80211DID_LSB_ACCESS) + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* The following structure types are used for the represenation */ +/* of ENUMINT type metadata. */ + +typedef struct p80211enumpair +{ + UINT32 val; + char *name; +} p80211enumpair_t; + +typedef struct p80211enum +{ + INT nitems; + p80211enumpair_t *list; +} p80211enum_t; + +/*----------------------------------------------------------------*/ +/* The following structure types are used to store data items in */ +/* messages. */ + +/* Template pascal string */ +typedef struct p80211pstr +{ + UINT8 len; +} __WLAN_ATTRIB_PACK__ p80211pstr_t; + +typedef struct p80211pstrd +{ + UINT8 len; + UINT8 data[0]; +} __WLAN_ATTRIB_PACK__ p80211pstrd_t; + +/* Maximum pascal string */ +typedef struct p80211pstr255 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR255]; +} __WLAN_ATTRIB_PACK__ p80211pstr255_t; + +/* pascal string for macaddress and bssid */ +typedef struct p80211pstr6 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR6]; +} __WLAN_ATTRIB_PACK__ p80211pstr6_t; + +/* pascal string for channel list */ +typedef struct p80211pstr14 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR14]; +} __WLAN_ATTRIB_PACK__ p80211pstr14_t; + +/* pascal string for ssid */ +typedef struct p80211pstr32 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR32]; +} __WLAN_ATTRIB_PACK__ p80211pstr32_t; + +/* MAC address array */ +typedef struct p80211macarray +{ + UINT32 cnt; + UINT8 data[1][MAXLEN_PSTR6]; +} __WLAN_ATTRIB_PACK__ p80211macarray_t; + +/* prototype template */ +typedef struct p80211item +{ + UINT32 did; + UINT16 status; + UINT16 len; +} __WLAN_ATTRIB_PACK__ p80211item_t; + +/* prototype template w/ data item */ +typedef struct p80211itemd +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[0]; +} __WLAN_ATTRIB_PACK__ p80211itemd_t; + +/* message data item for INT, BOUNDEDINT, ENUMINT */ +typedef struct p80211item_uint32 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT32 data; +} __WLAN_ATTRIB_PACK__ p80211item_uint32_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr6 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr6_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr6_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr14 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr14_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr14_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr32 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr32_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr32_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr255 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr255_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr255_t; + +/* message data item for UNK 392, namely mib items */ +typedef struct p80211item_unk392 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[MAXLEN_MIBATTRIBUTE]; +} __WLAN_ATTRIB_PACK__ p80211item_unk392_t; + +/* message data item for UNK 1025, namely p2 pdas */ +typedef struct p80211item_unk1024 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[1024]; +} __WLAN_ATTRIB_PACK__ p80211item_unk1024_t; + +/* message data item for UNK 4096, namely p2 download chunks */ +typedef struct p80211item_unk4096 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[4096]; +} __WLAN_ATTRIB_PACK__ p80211item_unk4096_t; + +struct catlistitem; + +/*----------------------------------------------------------------*/ +/* The following structure type is used to represent all of the */ +/* metadata items. Some components may choose to use more, */ +/* less or different metadata items. */ + +typedef void (*p80211_totext_t)( struct catlistitem *, UINT32 did, UINT8* itembuf, char *textbuf); +typedef void (*p80211_fromtext_t)( struct catlistitem *, UINT32 did, UINT8* itembuf, char *textbuf); +typedef UINT32 (*p80211_valid_t)( struct catlistitem *, UINT32 did, UINT8* itembuf); + + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* Enumeration Lists */ +/* The following are the external declarations */ +/* for all enumerations */ + +extern p80211enum_t MKENUMNAME(truth); +extern p80211enum_t MKENUMNAME(ifstate); +extern p80211enum_t MKENUMNAME(powermgmt); +extern p80211enum_t MKENUMNAME(bsstype); +extern p80211enum_t MKENUMNAME(authalg); +extern p80211enum_t MKENUMNAME(phytype); +extern p80211enum_t MKENUMNAME(temptype); +extern p80211enum_t MKENUMNAME(regdomain); +extern p80211enum_t MKENUMNAME(ccamode); +extern p80211enum_t MKENUMNAME(diversity); +extern p80211enum_t MKENUMNAME(scantype); +extern p80211enum_t MKENUMNAME(resultcode); +extern p80211enum_t MKENUMNAME(reason); +extern p80211enum_t MKENUMNAME(status); +extern p80211enum_t MKENUMNAME(msgcode); +extern p80211enum_t MKENUMNAME(msgitem_status); + +extern p80211enum_t MKENUMNAME(lnxroam_reason); + +extern p80211enum_t MKENUMNAME(p2preamble); + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* The following declare some utility functions for use with the */ +/* p80211enum_t type. */ + +UINT32 p80211enum_text2int(p80211enum_t *ep, char *text); +UINT32 p80211enum_int2text(p80211enum_t *ep, UINT32 val, char *text); +void p80211_error2text(int err_code, char *err_str); + +/*----------------------------------------------------------------*/ +/* The following declare some utility functions for use with the */ +/* p80211item_t and p80211meta_t types. */ + +/*----------------------------------------------------------------*/ +/* The following declare functions that perform validation and */ +/* text to binary conversions based on the metadata for interface */ +/* and MIB data items. */ +/*----------------------------------------------------------------*/ + +/*-- DISPLAYSTR ------------------------------------------------------*/ +/* pstr ==> cstr */ +void p80211_totext_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* cstr ==> pstr */ +void p80211_fromtext_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a displaystr binary value */ +UINT32 p80211_isvalid_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- OCTETSTR --------------------------------------------------------*/ +/* pstr ==> "xx:xx:...." */ +void p80211_totext_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* "xx:xx:...." ==> pstr */ +void p80211_fromtext_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an octetstr binary value */ +UINT32 p80211_isvalid_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- INT -------------------------------------------------------------*/ +/* UINT32 ==> %d */ +void p80211_totext_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* %d ==> UINT32 */ +void p80211_fromtext_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an int's binary value (always successful) */ +UINT32 p80211_isvalid_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- ENUMINT ---------------------------------------------------------*/ +/* UINT32 ==> */ +void p80211_totext_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* ==> UINT32 */ +void p80211_fromtext_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an enum's binary value */ +UINT32 p80211_isvalid_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- INTARRAY --------------------------------------------------------*/ +/* UINT32[] => %d,%d,%d,... */ +void p80211_totext_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* %d,%d,%d,... ==> UINT32[] */ +void p80211_fromtext_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an integer array's value */ +UINT32 p80211_isvalid_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- BITARRAY --------------------------------------------------------*/ +/* UINT32 ==> %d,%d,%d,... */ +void p80211_totext_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* %d,%d,%d,... ==> UINT32 */ +void p80211_fromtext_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a bit array's value */ +UINT32 p80211_isvalid_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- MACARRAY --------------------------------------------------------*/ +void p80211_totext_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +void p80211_fromtext_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a MAC address array's value */ +UINT32 p80211_isvalid_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- MIBATTRIUBTE ------------------------------------------------------*/ +/* ==> */ +void p80211_totext_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); +void p80211_totext_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + + +/* ==> */ +void p80211_fromtext_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); +void p80211_fromtext_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a mibitem's binary value */ +UINT32 p80211_isvalid_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); +UINT32 p80211_isvalid_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +#endif /* _P80211TYPES_H */ + --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/version.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/version.h @@ -0,0 +1,64 @@ +/* src/include/wlan/version.h +* +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ +#ifndef _WLAN_VERSION_H +#define _WLAN_VERSION_H +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +/* WLAN_HOSTIF (generally set on the command line, not detected) */ +#define WLAN_NONE 0 +#define WLAN_PCMCIA 1 +#define WLAN_ISA 2 +#define WLAN_PCI 3 +#define WLAN_USB 4 +#define WLAN_PLX 5 +#define WLAN_SLAVE 6 +#define WLAN_RELEASE "0.2.9" +#define WLAN_RELEASE_CODE 0x000209 +#define WLAN_BUILD_DATE "Sun Jul 27 23:23:32 CEST 2008" + +#endif --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211metadef.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211metadef.h @@ -0,0 +1,2524 @@ +/* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. +* -------------------------------------------------------------------- +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MKMETADEF_H +#define _P80211MKMETADEF_H + + +#define DIDmsg_cat_dot11req \ + P80211DID_MKSECTION(1) +#define DIDmsg_dot11req_mibget \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_dot11req_mibget_mibattribute \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_mibget_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_mibset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_dot11req_mibset_mibattribute \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_mibset_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_powermgmt \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_dot11req_powermgmt_powermgmtmode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_powermgmt_wakeup \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_powermgmt_receivedtims \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_powermgmt_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_scan \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_dot11req_scan_bsstype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_scan_bssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_scan_ssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_scan_scantype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_scan_probedelay \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_scan_channellist \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_scan_minchanneltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_scan_maxchanneltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_scan_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_scan_numbss \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_scan_append \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_scan_results \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_dot11req_scan_results_bssindex \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_scan_results_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_scan_results_signal \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_scan_results_noise \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_scan_results_bssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_scan_results_ssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_scan_results_bsstype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_scan_results_beaconperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_scan_results_dtimperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_scan_results_timestamp \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_scan_results_localtime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhdwelltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhhopset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhhoppattern \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhhopindex \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_dot11req_scan_results_dschannel \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpcount \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpmaxduration \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpdurremaining \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(20) | 0x00000000) +#define DIDmsg_dot11req_scan_results_ibssatimwindow \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(21) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(22) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(23) | 0x00000000) +#define DIDmsg_dot11req_scan_results_privacy \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(24) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(25) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(26) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(27) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(28) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(29) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(30) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(31) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(32) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(33) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(34) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(35) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(36) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(37) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(38) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(39) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(40) | 0x00000000) +#define DIDmsg_dot11req_join \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6)) +#define DIDmsg_dot11req_join_bssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_join_joinfailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_dot11req_join_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_dot11req_authenticate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7)) +#define DIDmsg_dot11req_authenticate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_authenticate_authenticationtype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_authenticate_authenticationfailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_authenticate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_deauthenticate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8)) +#define DIDmsg_dot11req_deauthenticate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_deauthenticate_reasoncode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_deauthenticate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_associate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9)) +#define DIDmsg_dot11req_associate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_associate_associatefailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_associate_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_associate_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_associate_privacy \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_associate_listeninterval \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_associate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_reassociate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10)) +#define DIDmsg_dot11req_reassociate_newapaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_reassociate_reassociatefailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_reassociate_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_reassociate_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_reassociate_privacy \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_reassociate_listeninterval \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_reassociate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_disassociate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11)) +#define DIDmsg_dot11req_disassociate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_disassociate_reasoncode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_disassociate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_reset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12)) +#define DIDmsg_dot11req_reset_setdefaultmib \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_reset_macaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_reset_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_start \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13)) +#define DIDmsg_dot11req_start_ssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_start_bsstype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_start_beaconperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_start_dtimperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_start_cfpperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_start_cfpmaxduration \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_start_fhdwelltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_start_fhhopset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_start_fhhoppattern \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_start_dschannel \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_start_ibssatimwindow \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_start_probedelay \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_dot11req_start_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_dot11req_start_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(20) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(21) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(22) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(23) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(24) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(25) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(26) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(27) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(28) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(29) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(30) | 0x00000000) +#define DIDmsg_dot11req_start_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(31) | 0x00000000) +#define DIDmsg_cat_dot11ind \ + P80211DID_MKSECTION(2) +#define DIDmsg_dot11ind_authenticate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_dot11ind_authenticate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_authenticate_authenticationtype \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_deauthenticate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_dot11ind_deauthenticate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_deauthenticate_reasoncode \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_associate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_dot11ind_associate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_associate_aid \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_reassociate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_dot11ind_reassociate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_reassociate_aid \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_reassociate_oldapaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11ind_disassociate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_dot11ind_disassociate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_disassociate_reasoncode \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_cat_lnxreq \ + P80211DID_MKSECTION(3) +#define DIDmsg_lnxreq_ifstate \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_lnxreq_ifstate_ifstate \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_ifstate_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_lnxreq_wlansniff_enable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_channel \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_prismheader \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_wlanheader \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_keepwepflags \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_stripfcs \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_packet_trunc \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_lnxreq_hostwep \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_lnxreq_hostwep_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_hostwep_decrypt \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_hostwep_encrypt \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxreq_commsquality \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_lnxreq_commsquality_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_dbm \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_link \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_level \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_noise \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_lnxreq_autojoin \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_lnxreq_autojoin_ssid \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_autojoin_authtype \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_autojoin_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_cat_lnxind \ + P80211DID_MKSECTION(4) +#define DIDmsg_lnxind_wlansniffrm \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_lnxind_wlansniffrm_hosttime \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_mactime \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_channel \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_rssi \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_sq \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_signal \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_noise \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_rate \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_istx \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_frmlen \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_lnxind_roam \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_lnxind_roam_reason \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_cat_p2req \ + P80211DID_MKSECTION(5) +#define DIDmsg_p2req_join \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_p2req_join_bssid \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_join_basicrate1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_join_basicrate2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_join_basicrate3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_join_basicrate4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_join_basicrate5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_join_basicrate6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_p2req_join_basicrate7 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_p2req_join_basicrate8 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate7 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate8 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_p2req_join_ssid \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_p2req_join_channel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_p2req_join_authtype \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(20) | 0x00000000) +#define DIDmsg_p2req_join_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(21) | 0x00000000) +#define DIDmsg_p2req_readpda \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_p2req_readpda_pda \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_readpda_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_readcis \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_p2req_readcis_cis \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_readcis_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_p2req_auxport_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_auxport_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_read \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_p2req_auxport_read_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_auxport_read_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_read_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_auxport_read_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_auxport_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6)) +#define DIDmsg_p2req_auxport_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_auxport_write_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_auxport_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_low_level \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7)) +#define DIDmsg_p2req_low_level_command \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_low_level_param0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_low_level_param1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_low_level_param2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_low_level_resp0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_low_level_resp1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_low_level_resp2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_p2req_low_level_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_p2req_test_command \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8)) +#define DIDmsg_p2req_test_command_testcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_test_command_testparam \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_test_command_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_test_command_status \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_test_command_resp0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_test_command_resp1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_test_command_resp2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_p2req_mmi_read \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9)) +#define DIDmsg_p2req_mmi_read_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_mmi_read_value \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_mmi_read_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_mmi_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10)) +#define DIDmsg_p2req_mmi_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_mmi_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_mmi_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_ramdl_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11)) +#define DIDmsg_p2req_ramdl_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_ramdl_state_exeaddr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_ramdl_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_ramdl_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12)) +#define DIDmsg_p2req_ramdl_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_ramdl_write_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_ramdl_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_ramdl_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_flashdl_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(13)) +#define DIDmsg_p2req_flashdl_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_flashdl_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_flashdl_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14)) +#define DIDmsg_p2req_flashdl_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_flashdl_write_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_flashdl_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_flashdl_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_mm_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(15)) +#define DIDmsg_p2req_mm_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(15) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_mm_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(15) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_dump_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(16)) +#define DIDmsg_p2req_dump_state_level \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(16) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_dump_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(16) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_channel_info \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17)) +#define DIDmsg_p2req_channel_info_channellist \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_channel_info_channeldwelltime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_channel_info_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_channel_info_numchinfo \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_channel_info_results \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18)) +#define DIDmsg_p2req_channel_info_results_channel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_avgnoiselevel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_peaknoiselevel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_bssactive \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_pcfactive \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(19)) +#define DIDmsg_p2req_enable_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(19) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmib_cat_dot11smt \ + P80211DID_MKSECTION(1) +#define DIDmib_dot11smt_p80211Table \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_dot11smt_p80211Table_p80211_ifstate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11StationID \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11MediumOccupancyLimit \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPPeriod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPMaxDuration \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticationResponseTimeOut \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11PrivacyOptionImplemented \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11PowerManagementMode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredSSID \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11BeaconPeriod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(12) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DTIMPeriod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(13) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AssociationResponseTimeOut \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DisassociateReason \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(15) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DisassociateStation \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(16) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DeauthenticateReason \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(17) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DeauthenticateStation \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(18) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticateFailStatus \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(19) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticateFailStation \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(20) | 0x10000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(11) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(12) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4)) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5)) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingIndex \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingAddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingWEPOn \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingValue \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11smt_dot11PrivacyTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6)) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPKeyMappingLength \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPICVErrorCount \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPExcludedCount \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_cat_dot11mac \ + P80211DID_MKSECTION(2) +#define DIDmib_dot11mac_dot11OperationTable \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_dot11mac_dot11OperationTable_dot11MACAddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11MaxReceiveLifetime \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11ManufacturerID \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11ProductID \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFragmentCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11MulticastTransmittedFrameCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11FailedCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11RetryCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11MultipleRetryCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11FrameDuplicateCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11RTSSuccessCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11RTSFailureCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11ACKFailureCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11ReceivedFragmentCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(10) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11MulticastReceivedFrameCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(11) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11FCSErrorCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFrameCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(13) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11WEPUndecryptableCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(11) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(12) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(13) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(14) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(15) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(16) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(17) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(18) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(19) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(20) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(21) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(22) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(23) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(24) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(25) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(26) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(27) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(28) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(29) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(30) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(31) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(32) | 0x1c000000) +#define DIDmib_cat_dot11phy \ + P80211DID_MKSECTION(3) +#define DIDmib_dot11phy_dot11PhyOperationTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11PHYType \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11CurrentRegDomain \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11TempType \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityPresent \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityEnabled \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyAntennaTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentTxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11DiversitySupport \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentRxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11NumberSupportedPowerLevels \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4)) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11HopTime \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentChannelNumber \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11MaxDwellTime \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentDwellTime \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentSet \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentPattern \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(7) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5)) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CCAModeSupported \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentCCAMode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11EDThreshold \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11ShortPreambleOptionImplemented \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11PBCCOptionImplemented \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyIRTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6)) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMax \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMax \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMin \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMin \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11phy_dot11RegDomainsSupportedTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(7)) +#define DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportValue \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x14000000) +#define DIDmib_dot11phy_dot11AntennasListTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8)) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11AntennaListIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedTxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedRxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(3) | 0x1c000000) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11DiversitySelectionRx \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(9)) +#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxValue \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(2) | 0x14000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(10)) +#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxValue \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(2) | 0x14000000) +#define DIDmib_cat_lnx \ + P80211DID_MKSECTION(4) +#define DIDmib_lnx_lnxConfigTable \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_lnx_lnxConfigTable_lnxRSNAIE \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_cat_p2 \ + P80211DID_MKSECTION(5) +#define DIDmib_p2_p2Table \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_p2_p2Table_p2MMTx \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2Table_p2EarlyBeacon \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_p2_p2Table_p2ReceivedFrameStatistics \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2Table_p2CommunicationTallies \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2Table_p2Authenticated \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2Table_p2Associated \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_p2_p2Table_p2PowerSaveUserCount \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_p2_p2Table_p2Comment \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_p2_p2Table_p2AccessMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_p2_p2Table_p2AccessAllow \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_p2_p2Table_p2AccessDeny \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_p2_p2Table_p2ChannelInfoResults \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_p2_p2Static \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_p2_p2Static_p2CnfPortType \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnMACAddress \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfDesiredSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnChannel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnATIMWindow \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfSystemScale \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMaxDataLength \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPMEnabled \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPMEPS \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMulticastReceive \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(12) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMaxSleepDuration \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(13) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPMHoldoverDuration \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(14) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnName \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(15) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnDTIMPeriod \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(16) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(17) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(18) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(19) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(20) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(21) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(22) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMulticastPMBuffering \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(23) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKeyID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(24) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(25) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(26) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(27) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(28) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPFlags \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(29) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfAuthentication \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(30) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMaxAssociatedStations \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(31) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfTxControl \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(32) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfRoamingMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(33) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfHostAuthentication \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(34) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfRcvCrcError \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(35) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfAltRetryCount \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(36) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfBeaconInterval \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(37) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMediumOccupancyLimit \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(38) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfCFPPeriod \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(39) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfCFPMaxDuration \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(40) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfCFPFlags \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(41) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfSTAPCFInfo \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(42) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPriorityQUsage \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(43) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfTIMCtrl \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(44) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfThirty2Tally \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(45) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfEnhSecurity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(46) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfShortPreamble \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(47) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfExcludeLongPreamble \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(48) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfAuthenticationRspTO \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(49) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfBasicRates \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(50) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfSupportedRates \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(51) | 0x18000000) +#define DIDmib_p2_p2Dynamic \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_p2_p2Dynamic_p2CreateIBSS \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2PromiscuousMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(12) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(13) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(14) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(15) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(16) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(17) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(18) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(19) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(20) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(21) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(22) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(23) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(24) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(25) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(26) | 0x18000000) +#define DIDmib_p2_p2Behavior \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4)) +#define DIDmib_p2_p2Behavior_p2TickTime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2NIC \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5)) +#define DIDmib_p2_p2NIC_p2MaxLoadTime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_p2_p2NIC_p2DLBufferPage \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_p2_p2NIC_p2DLBufferOffset \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2NIC_p2DLBufferLength \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2NIC_p2PRIIdentity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2NIC_p2PRISupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_p2_p2NIC_p2CFIActRanges \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_p2_p2NIC_p2NICSerialNumber \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_p2_p2NIC_p2NICIdentity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_p2_p2NIC_p2MFISupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(10) | 0x10000000) +#define DIDmib_p2_p2NIC_p2CFISupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(11) | 0x10000000) +#define DIDmib_p2_p2NIC_p2ChannelList \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_p2_p2NIC_p2RegulatoryDomains \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(13) | 0x10000000) +#define DIDmib_p2_p2NIC_p2TempType \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_p2_p2NIC_p2STAIdentity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(15) | 0x10000000) +#define DIDmib_p2_p2NIC_p2STASupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(16) | 0x10000000) +#define DIDmib_p2_p2NIC_p2MFIActRanges \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(17) | 0x10000000) +#define DIDmib_p2_p2NIC_p2STACFIActRanges \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(18) | 0x10000000) +#define DIDmib_p2_p2NIC_p2BuildSequence \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(19) | 0x10000000) +#define DIDmib_p2_p2NIC_p2PrimaryFWID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(20) | 0x10000000) +#define DIDmib_p2_p2NIC_p2SecondaryFWID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(21) | 0x10000000) +#define DIDmib_p2_p2NIC_p2TertiaryFWID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(22) | 0x10000000) +#define DIDmib_p2_p2MAC \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6)) +#define DIDmib_p2_p2MAC_p2PortStatus \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentBSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQuality \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQualityCQ \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQualityASL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQualityANL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQuality \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQualityCQ \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQualityASL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(10) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQualityANL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(11) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentBeaconInterval \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(13) | 0x10000000) +#define DIDmib_p2_p2MAC_p2StaCurrentScaleThresholds \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_p2_p2MAC_p2APCurrentScaleThresholds \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(15) | 0x10000000) +#define DIDmib_p2_p2MAC_p2ProtocolRspTime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(16) | 0x10000000) +#define DIDmib_p2_p2MAC_p2ShortRetryLimit \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(17) | 0x10000000) +#define DIDmib_p2_p2MAC_p2LongRetryLimit \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(18) | 0x10000000) +#define DIDmib_p2_p2MAC_p2MaxTransmitLifetime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(19) | 0x10000000) +#define DIDmib_p2_p2MAC_p2MaxReceiveLifetime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(20) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CFPollable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(21) | 0x10000000) +#define DIDmib_p2_p2MAC_p2AuthenticationAlgorithms \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(22) | 0x10000000) +#define DIDmib_p2_p2MAC_p2PrivacyOptionImplemented \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(23) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(24) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(25) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(26) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(27) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(28) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(29) | 0x10000000) +#define DIDmib_p2_p2MAC_p2OwnMACAddress \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(30) | 0x10000000) +#define DIDmib_p2_p2Modem \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7)) +#define DIDmib_p2_p2Modem_p2PHYType \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_p2_p2Modem_p2CurrentChannel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_p2_p2Modem_p2CurrentPowerState \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2Modem_p2CCAMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2Modem_p2SupportedDataRates \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2Modem_p2TxPowerMax \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(6) | 0x18000000) +#endif --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211meta.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211meta.h @@ -0,0 +1,169 @@ +/* src/include/wlan/p80211meta.h +* +* Macros, constants, types, and funcs for p80211 metadata +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211META_H +#define _P80211META_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include +#endif + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Macros */ + +/*----------------------------------------------------------------*/ +/* The following macros are used to ensure consistent naming */ +/* conventions for all the different metadata lists. */ + +#define MKREQMETANAME(name) p80211meta_ ## req ## _ ## name +#define MKINDMETANAME(name) p80211meta_ ## ind ## _ ## name +#define MKMIBMETANAME(name) p80211meta_ ## mib ## _ ## name +#define MKGRPMETANAME(name) p80211meta_ ## grp ## _ ## name + +#define MKREQMETASIZE(name) p80211meta_ ## req ## _ ## name ## _ ## size +#define MKINDMETASIZE(name) p80211meta_ ## ind ## _ ## name ## _ ## size +#define MKMIBMETASIZE(name) p80211meta_ ## mib ## _ ## name ## _ ## size +#define MKGRPMETASIZE(name) p80211meta_ ## grp ## _ ## name ## _ ## size + +#define GETMETASIZE(aptr) (**((UINT32**)(aptr))) + +/*----------------------------------------------------------------*/ +/* The following ifdef depends on the following defines: */ +/* P80211_NOINCLUDESTRINGS - if defined, all metadata name fields */ +/* are empty strings */ + +#ifdef P80211_NOINCLUDESTRINGS + #define MKITEMNAME(s) ("") +#else + #define MKITEMNAME(s) (s) +#endif + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* The following structure types are used for the metadata */ +/* representation of category list metadata, group list metadata, */ +/* and data item metadata for both Mib and Messages. */ + +typedef struct p80211meta +{ + char *name; /* data item name */ + UINT32 did; /* partial did */ + UINT32 flags; /* set of various flag bits */ + UINT32 min; /* min value of a BOUNDEDINT */ + UINT32 max; /* max value of a BOUNDEDINT */ + + UINT32 maxlen; /* maxlen of a OCTETSTR or DISPLAYSTR */ + UINT32 minlen; /* minlen of a OCTETSTR or DISPLAYSTR */ + p80211enum_t *enumptr; /* ptr to the enum type for ENUMINT */ + p80211_totext_t totextptr; /* ptr to totext conversion function */ + p80211_fromtext_t fromtextptr; /* ptr to totext conversion function */ + p80211_valid_t validfunptr; /* ptr to totext conversion function */ +} p80211meta_t; + +typedef struct grplistitem +{ + char *name; + p80211meta_t *itemlist; +} grplistitem_t; + +typedef struct catlistitem +{ + char *name; + grplistitem_t *grplist; +} catlistitem_t; + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* */ +UINT32 p80211_text2did(catlistitem_t *catlist, char *catname, char *grpname, char *itemname); +UINT32 p80211_text2catdid(catlistitem_t *list, char *name ); +UINT32 p80211_text2grpdid(grplistitem_t *list, char *name ); +UINT32 p80211_text2itemdid(p80211meta_t *list, char *name ); +UINT32 p80211_isvalid_did( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211_isvalid_catdid( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211_isvalid_grpdid( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211_isvalid_itemdid( catlistitem_t *catlist, UINT32 did ); +catlistitem_t *p80211_did2cat( catlistitem_t *catlist, UINT32 did ); +grplistitem_t *p80211_did2grp( catlistitem_t *catlist, UINT32 did ); +p80211meta_t *p80211_did2item( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211item_maxdatalen( struct catlistitem *metalist, UINT32 did ); +UINT32 p80211_metaname2did(struct catlistitem *metalist, char *itemname); +UINT32 p80211item_getoffset( struct catlistitem *metalist, UINT32 did ); +int p80211item_gettype(p80211meta_t *meta); + +#endif /* _P80211META_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211ioctl.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211ioctl.h @@ -0,0 +1,123 @@ +/* src/include/wlan/p80211ioctl.h +* +* Declares constants and types for the p80211 ioctls +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* While this file is called 'ioctl' is purpose goes a little beyond +* that. This file defines the types and contants used to implement +* the p80211 request/confirm/indicate interfaces on Linux. The +* request/confirm interface is, in fact, normally implemented as an +* ioctl. The indicate interface on the other hand, is implemented +* using the Linux 'netlink' interface. +* +* The reason I say that request/confirm is 'normally' implemented +* via ioctl is that we're reserving the right to be able to send +* request commands via the netlink interface. This will be necessary +* if we ever need to send request messages when there aren't any +* wlan network devices present (i.e. sending a message that only p80211 +* cares about. +* -------------------------------------------------------------------- +*/ + + +#ifndef _P80211IOCTL_H +#define _P80211IOCTL_H + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* p80211 ioctl "request" codes. See argument 2 of ioctl(2). */ + +#define P80211_IFTEST (SIOCDEVPRIVATE + 0) +#define P80211_IFREQ (SIOCDEVPRIVATE + 1) + +/*----------------------------------------------------------------*/ +/* Magic number, a quick test to see we're getting the desired struct */ + +#define P80211_IOCTL_MAGIC (0x4a2d464dUL) + +/*----------------------------------------------------------------*/ +/* Netlink protocol numbers for the indication interface */ + +#define P80211_NL_SOCK_IND NETLINK_USERSOCK + +/*----------------------------------------------------------------*/ +/* Netlink multicast bits for different types of messages */ + +#define P80211_NL_MCAST_GRP_MLME BIT0 /* Local station messages */ +#define P80211_NL_MCAST_GRP_SNIFF BIT1 /* Sniffer messages */ +#define P80211_NL_MCAST_GRP_DIST BIT2 /* Distribution system messages */ + +/*================================================================*/ +/* Macros */ + + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* A ptr to the following structure type is passed as the third */ +/* argument to the ioctl system call when issuing a request to */ +/* the p80211 module. */ + +typedef struct p80211ioctl_req +{ + char name[WLAN_DEVNAMELEN_MAX]; + caddr_t data; + UINT32 magic; + UINT16 len; + UINT32 result; +} __WLAN_ATTRIB_PACK__ p80211ioctl_req_t; + + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + + +#endif /* _P80211IOCTL_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211metamib.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211metamib.h @@ -0,0 +1,105 @@ +/* src/include/wlan/p80211metamib.h +* +* Macros, const, types, and funcs for p80211 mib metadata +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211METAMIB_H +#define _P80211METAMIB_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include +#endif + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Macros */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* The following is the external declaration for the mib */ +/* category metadata list */ + +extern catlistitem_t mib_catlist[]; +extern UINT32 mib_catlist_size; + + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* */ + +#endif /* _P80211METAMIB_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211metamsg.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211metamsg.h @@ -0,0 +1,105 @@ +/* src/include/wlan/p80211metamsg.h +* +* Macros, const, types, and funcs for p80211 msg metadata +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211METAMSG_H +#define _P80211METAMSG_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include +#endif + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Macros */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* The following is the external declaration for the message */ +/* category metadata list */ + +extern catlistitem_t msg_catlist[]; +extern UINT32 msg_catlist_size; + + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* */ + +#endif /* _P80211METAMSG_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211hdr.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211hdr.h @@ -0,0 +1,299 @@ +/* src/include/wlan/p80211hdr.h +* +* Macros, types, and functions for handling 802.11 MAC headers +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the constants and types used in the interface +* between a wlan driver and the user mode utilities. +* +* Note: +* - Constant values are always in HOST byte order. To assign +* values to multi-byte fields they _must_ be converted to +* ieee byte order. To retrieve multi-byte values from incoming +* frames, they must be converted to host order. +* +* All functions declared here are implemented in p80211.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211HDR_H +#define _P80211HDR_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include +#endif + + +/*================================================================*/ +/* Constants */ + +/*--- Sizes -----------------------------------------------*/ +#define WLAN_ADDR_LEN 6 +#define WLAN_CRC_LEN 4 +#define WLAN_BSSID_LEN 6 +#define WLAN_BSS_TS_LEN 8 +#define WLAN_HDR_A3_LEN 24 +#define WLAN_HDR_A4_LEN 30 +#define WLAN_SSID_MAXLEN 32 +#define WLAN_DATA_MAXLEN 2312 +#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) +#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) +#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334) +#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0) +#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) +#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48) +#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) +#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54) +#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) +#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44) +#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78) +#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261) +#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) +#define WLAN_WEP_NKEYS 4 +#define WLAN_WEP_MAXKEYLEN 13 +#define WLAN_CHALLENGE_IE_LEN 130 +#define WLAN_CHALLENGE_LEN 128 +#define WLAN_WEP_IV_LEN 4 +#define WLAN_WEP_ICV_LEN 4 + +/*--- Frame Control Field -------------------------------------*/ +/* Frame Types */ +#define WLAN_FTYPE_MGMT 0x00 +#define WLAN_FTYPE_CTL 0x01 +#define WLAN_FTYPE_DATA 0x02 + +/* Frame subtypes */ +/* Management */ +#define WLAN_FSTYPE_ASSOCREQ 0x00 +#define WLAN_FSTYPE_ASSOCRESP 0x01 +#define WLAN_FSTYPE_REASSOCREQ 0x02 +#define WLAN_FSTYPE_REASSOCRESP 0x03 +#define WLAN_FSTYPE_PROBEREQ 0x04 +#define WLAN_FSTYPE_PROBERESP 0x05 +#define WLAN_FSTYPE_BEACON 0x08 +#define WLAN_FSTYPE_ATIM 0x09 +#define WLAN_FSTYPE_DISASSOC 0x0a +#define WLAN_FSTYPE_AUTHEN 0x0b +#define WLAN_FSTYPE_DEAUTHEN 0x0c + +/* Control */ +#define WLAN_FSTYPE_BLOCKACKREQ 0x8 +#define WLAN_FSTYPE_BLOCKACK 0x9 +#define WLAN_FSTYPE_PSPOLL 0x0a +#define WLAN_FSTYPE_RTS 0x0b +#define WLAN_FSTYPE_CTS 0x0c +#define WLAN_FSTYPE_ACK 0x0d +#define WLAN_FSTYPE_CFEND 0x0e +#define WLAN_FSTYPE_CFENDCFACK 0x0f + +/* Data */ +#define WLAN_FSTYPE_DATAONLY 0x00 +#define WLAN_FSTYPE_DATA_CFACK 0x01 +#define WLAN_FSTYPE_DATA_CFPOLL 0x02 +#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03 +#define WLAN_FSTYPE_NULL 0x04 +#define WLAN_FSTYPE_CFACK 0x05 +#define WLAN_FSTYPE_CFPOLL 0x06 +#define WLAN_FSTYPE_CFACK_CFPOLL 0x07 + + +/*================================================================*/ +/* Macros */ + +/*--- FC Macros ----------------------------------------------*/ +/* Macros to get/set the bitfields of the Frame Control Field */ +/* GET_FC_??? - takes the host byte-order value of an FC */ +/* and retrieves the value of one of the */ +/* bitfields and moves that value so its lsb is */ +/* in bit 0. */ +/* SET_FC_??? - takes a host order value for one of the FC */ +/* bitfields and moves it to the proper bit */ +/* location for ORing into a host order FC. */ +/* To send the FC produced from SET_FC_???, */ +/* one must put the bytes in IEEE order. */ +/* e.g. */ +/* printf("the frame subtype is %x", */ +/* GET_FC_FTYPE( ieee2host( rx.fc ))) */ +/* */ +/* tx.fc = host2ieee( SET_FC_FTYPE(WLAN_FTYP_CTL) | */ +/* SET_FC_FSTYPE(WLAN_FSTYPE_RTS) ); */ +/*------------------------------------------------------------*/ + +#define WLAN_GET_FC_PVER(n) (((UINT16)(n)) & (BIT0 | BIT1)) +#define WLAN_GET_FC_FTYPE(n) ((((UINT16)(n)) & (BIT2 | BIT3)) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((UINT16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4) +#define WLAN_GET_FC_TODS(n) ((((UINT16)(n)) & (BIT8)) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((UINT16)(n)) & (BIT9)) >> 9) +#define WLAN_GET_FC_MOREFRAG(n) ((((UINT16)(n)) & (BIT10)) >> 10) +#define WLAN_GET_FC_RETRY(n) ((((UINT16)(n)) & (BIT11)) >> 11) +#define WLAN_GET_FC_PWRMGT(n) ((((UINT16)(n)) & (BIT12)) >> 12) +#define WLAN_GET_FC_MOREDATA(n) ((((UINT16)(n)) & (BIT13)) >> 13) +#define WLAN_GET_FC_ISWEP(n) ((((UINT16)(n)) & (BIT14)) >> 14) +#define WLAN_GET_FC_ORDER(n) ((((UINT16)(n)) & (BIT15)) >> 15) + +#define WLAN_SET_FC_PVER(n) ((UINT16)(n)) +#define WLAN_SET_FC_FTYPE(n) (((UINT16)(n)) << 2) +#define WLAN_SET_FC_FSTYPE(n) (((UINT16)(n)) << 4) +#define WLAN_SET_FC_TODS(n) (((UINT16)(n)) << 8) +#define WLAN_SET_FC_FROMDS(n) (((UINT16)(n)) << 9) +#define WLAN_SET_FC_MOREFRAG(n) (((UINT16)(n)) << 10) +#define WLAN_SET_FC_RETRY(n) (((UINT16)(n)) << 11) +#define WLAN_SET_FC_PWRMGT(n) (((UINT16)(n)) << 12) +#define WLAN_SET_FC_MOREDATA(n) (((UINT16)(n)) << 13) +#define WLAN_SET_FC_ISWEP(n) (((UINT16)(n)) << 14) +#define WLAN_SET_FC_ORDER(n) (((UINT16)(n)) << 15) + +/*--- Duration Macros ----------------------------------------*/ +/* Macros to get/set the bitfields of the Duration Field */ +/* - the duration value is only valid when bit15 is zero */ +/* - the firmware handles these values, so I'm not going */ +/* these macros right now. */ +/*------------------------------------------------------------*/ + +/*--- Sequence Control Macros -------------------------------*/ +/* Macros to get/set the bitfields of the Sequence Control */ +/* Field. */ +/*------------------------------------------------------------*/ +#define WLAN_GET_SEQ_FRGNUM(n) (((UINT16)(n)) & (BIT0|BIT1|BIT2|BIT3)) +#define WLAN_GET_SEQ_SEQNUM(n) ((((UINT16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) + +/*--- Data ptr macro -----------------------------------------*/ +/* Creates a UINT8* to the data portion of a frame */ +/* Assumes you're passing in a ptr to the beginning of the hdr*/ +/*------------------------------------------------------------*/ +#define WLAN_HDR_A3_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A3_LEN) +#define WLAN_HDR_A4_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A4_LEN) + +#define DOT11_RATE5_ISBASIC_GET(r) (((UINT8)(r)) & BIT7) + +/*================================================================*/ +/* Types */ + +/* BSS Timestamp */ +typedef UINT8 wlan_bss_ts_t[WLAN_BSS_TS_LEN]; + +/* Generic 802.11 Header types */ + +typedef struct p80211_hdr_a3 +{ + UINT16 fc; + UINT16 dur; + UINT8 a1[WLAN_ADDR_LEN]; + UINT8 a2[WLAN_ADDR_LEN]; + UINT8 a3[WLAN_ADDR_LEN]; + UINT16 seq; +} __WLAN_ATTRIB_PACK__ p80211_hdr_a3_t; + +typedef struct p80211_hdr_a4 +{ + UINT16 fc; + UINT16 dur; + UINT8 a1[WLAN_ADDR_LEN]; + UINT8 a2[WLAN_ADDR_LEN]; + UINT8 a3[WLAN_ADDR_LEN]; + UINT16 seq; + UINT8 a4[WLAN_ADDR_LEN]; +} __WLAN_ATTRIB_PACK__ p80211_hdr_a4_t; + +typedef union p80211_hdr +{ + p80211_hdr_a3_t a3; + p80211_hdr_a4_t a4; +} __WLAN_ATTRIB_PACK__ p80211_hdr_t; + + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + +/* Frame and header lenght macros */ + +#define WLAN_CTL_FRAMELEN(fstype) (\ + (fstype) == WLAN_FSTYPE_BLOCKACKREQ ? 24 : \ + (fstype) == WLAN_FSTYPE_BLOCKACK ? 152 : \ + (fstype) == WLAN_FSTYPE_PSPOLL ? 20 : \ + (fstype) == WLAN_FSTYPE_RTS ? 20 : \ + (fstype) == WLAN_FSTYPE_CTS ? 14 : \ + (fstype) == WLAN_FSTYPE_ACK ? 14 : \ + (fstype) == WLAN_FSTYPE_CFEND ? 20 : \ + (fstype) == WLAN_FSTYPE_CFENDCFACK ? 20 : 4) + +#define WLAN_FCS_LEN 4 + +/* ftcl in HOST order */ +inline static UINT16 p80211_headerlen(UINT16 fctl) +{ + UINT16 hdrlen = 0; + + switch ( WLAN_GET_FC_FTYPE(fctl) ) { + case WLAN_FTYPE_MGMT: + hdrlen = WLAN_HDR_A3_LEN; + break; + case WLAN_FTYPE_DATA: + hdrlen = WLAN_HDR_A3_LEN; + if ( WLAN_GET_FC_TODS(fctl) && WLAN_GET_FC_FROMDS(fctl) ) { + hdrlen += WLAN_ADDR_LEN; + } + break; + case WLAN_FTYPE_CTL: + hdrlen = WLAN_CTL_FRAMELEN(WLAN_GET_FC_FSTYPE(fctl)) - + WLAN_FCS_LEN; + break; + default: + hdrlen = WLAN_HDR_A3_LEN; + } + + return hdrlen; +} + +#endif /* _P80211HDR_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211mgmt.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211mgmt.h @@ -0,0 +1,575 @@ +/* src/include/wlan/p80211mgmt.h +* +* Macros, types, and functions to handle 802.11 mgmt frames +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the constants and types used in the interface +* between a wlan driver and the user mode utilities. +* +* Notes: +* - Constant values are always in HOST byte order. To assign +* values to multi-byte fields they _must_ be converted to +* ieee byte order. To retrieve multi-byte values from incoming +* frames, they must be converted to host order. +* +* - The len member of the frame structure does NOT!!! include +* the MAC CRC. Therefore, the len field on rx'd frames should +* have 4 subtracted from it. +* +* All functions declared here are implemented in p80211.c +* +* The types, macros, and functions defined here are primarily +* used for encoding and decoding management frames. They are +* designed to follow these patterns of use: +* +* DECODE: +* 1) a frame of length len is received into buffer b +* 2) using the hdr structure and macros, we determine the type +* 3) an appropriate mgmt frame structure, mf, is allocated and zeroed +* 4) mf.hdr = b +* mf.buf = b +* mf.len = len +* 5) call mgmt_decode( mf ) +* 6) the frame field pointers in mf are now set. Note that any +* multi-byte frame field values accessed using the frame field +* pointers are in ieee byte order and will have to be converted +* to host order. +* +* ENCODE: +* 1) Library client allocates buffer space for maximum length +* frame of the desired type +* 2) Library client allocates a mgmt frame structure, called mf, +* of the desired type +* 3) Set the following: +* mf.type = +* mf.buf = +* 4) call mgmt_encode( mf ) +* 5) all of the fixed field pointers and fixed length information element +* pointers in mf are now set to their respective locations in the +* allocated space (fortunately, all variable length information elements +* fall at the end of their respective frames). +* 5a) The length field is set to include the last of the fixed and fixed +* length fields. It may have to be updated for optional or variable +* length information elements. +* 6) Optional and variable length information elements are special cases +* and must be handled individually by the client code. +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MGMT_H +#define _P80211MGMT_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include +#endif + +#ifndef _P80211HDR_H +#include +#endif + + +/*================================================================*/ +/* Constants */ + +/*-- Information Element IDs --------------------*/ +#define WLAN_EID_SSID 0 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_FH_PARMS 2 +#define WLAN_EID_DS_PARMS 3 +#define WLAN_EID_CF_PARMS 4 +#define WLAN_EID_TIM 5 +#define WLAN_EID_IBSS_PARMS 6 +/*-- values 7-15 reserved --*/ +#define WLAN_EID_CHALLENGE 16 +/*-- values 17-31 reserved for challenge text extension --*/ +/*-- values 32-255 reserved --*/ + +/*-- Reason Codes -------------------------------*/ +#define WLAN_MGMT_REASON_RSVD 0 +#define WLAN_MGMT_REASON_UNSPEC 1 +#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2 +#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3 +#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4 +#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5 +#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6 +#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7 +#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8 +#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9 + +/*-- Status Codes -------------------------------*/ +#define WLAN_MGMT_STATUS_SUCCESS 0 +#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1 +#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10 +#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12 +#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13 +#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14 +#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15 +#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18 + /* p80211b additions */ +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOSHORT 19 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC 20 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY 21 + + + +/*-- Auth Algorithm Field ---------------------------*/ +#define WLAN_AUTH_ALG_OPENSYSTEM 0 +#define WLAN_AUTH_ALG_SHAREDKEY 1 + +/*-- Management Frame Field Offsets -------------*/ +/* Note: Not all fields are listed because of variable lengths, */ +/* see the code in p80211.c to see how we search for fields */ +/* Note: These offsets are from the start of the frame data */ + +#define WLAN_BEACON_OFF_TS 0 +#define WLAN_BEACON_OFF_BCN_INT 8 +#define WLAN_BEACON_OFF_CAPINFO 10 +#define WLAN_BEACON_OFF_SSID 12 + +#define WLAN_DISASSOC_OFF_REASON 0 + +#define WLAN_ASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_ASSOCREQ_OFF_SSID 4 + +#define WLAN_ASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_ASSOCRESP_OFF_STATUS 2 +#define WLAN_ASSOCRESP_OFF_AID 4 +#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_REASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_REASSOCREQ_OFF_CURR_AP 4 +#define WLAN_REASSOCREQ_OFF_SSID 10 + +#define WLAN_REASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_REASSOCRESP_OFF_STATUS 2 +#define WLAN_REASSOCRESP_OFF_AID 4 +#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_PROBEREQ_OFF_SSID 0 + +#define WLAN_PROBERESP_OFF_TS 0 +#define WLAN_PROBERESP_OFF_BCN_INT 8 +#define WLAN_PROBERESP_OFF_CAP_INFO 10 +#define WLAN_PROBERESP_OFF_SSID 12 + +#define WLAN_AUTHEN_OFF_AUTH_ALG 0 +#define WLAN_AUTHEN_OFF_AUTH_SEQ 2 +#define WLAN_AUTHEN_OFF_STATUS 4 +#define WLAN_AUTHEN_OFF_CHALLENGE 6 + +#define WLAN_DEAUTHEN_OFF_REASON 0 + + +/*================================================================*/ +/* Macros */ + +/*-- Capability Field ---------------------------*/ +#define WLAN_GET_MGMT_CAP_INFO_ESS(n) ((n) & BIT0) +#define WLAN_GET_MGMT_CAP_INFO_IBSS(n) (((n) & BIT1) >> 1) +#define WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(n) (((n) & BIT2) >> 2) +#define WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(n) (((n) & BIT3) >> 3) +#define WLAN_GET_MGMT_CAP_INFO_PRIVACY(n) (((n) & BIT4) >> 4) + /* p80211b additions */ +#define WLAN_GET_MGMT_CAP_INFO_SHORT(n) (((n) & BIT5) >> 5) +#define WLAN_GET_MGMT_CAP_INFO_PBCC(n) (((n) & BIT6) >> 6) +#define WLAN_GET_MGMT_CAP_INFO_AGILITY(n) (((n) & BIT7) >> 7) + +#define WLAN_SET_MGMT_CAP_INFO_ESS(n) (n) +#define WLAN_SET_MGMT_CAP_INFO_IBSS(n) ((n) << 1) +#define WLAN_SET_MGMT_CAP_INFO_CFPOLLABLE(n) ((n) << 2) +#define WLAN_SET_MGMT_CAP_INFO_CFPOLLREQ(n) ((n) << 3) +#define WLAN_SET_MGMT_CAP_INFO_PRIVACY(n) ((n) << 4) + /* p80211b additions */ +#define WLAN_SET_MGMT_CAP_INFO_SHORT(n) ((n) << 5) +#define WLAN_SET_MGMT_CAP_INFO_PBCC(n) ((n) << 6) +#define WLAN_SET_MGMT_CAP_INFO_AGILITY(n) ((n) << 7) + + +/*================================================================*/ +/* Types */ + +/*-- Information Element Types --------------------*/ +/* prototype structure, all IEs start with these members */ + +typedef struct wlan_ie +{ + UINT8 eid; + UINT8 len; +} __WLAN_ATTRIB_PACK__ wlan_ie_t; + +/*-- Service Set Identity (SSID) -----------------*/ +typedef struct wlan_ie_ssid +{ + UINT8 eid; + UINT8 len; + UINT8 ssid[1]; /* may be zero, ptrs may overlap */ +} __WLAN_ATTRIB_PACK__ wlan_ie_ssid_t; + +/*-- Supported Rates -----------------------------*/ +typedef struct wlan_ie_supp_rates +{ + UINT8 eid; + UINT8 len; + UINT8 rates[1]; /* had better be at LEAST one! */ +} __WLAN_ATTRIB_PACK__ wlan_ie_supp_rates_t; + +/*-- FH Parameter Set ----------------------------*/ +typedef struct wlan_ie_fh_parms +{ + UINT8 eid; + UINT8 len; + UINT16 dwell; + UINT8 hopset; + UINT8 hoppattern; + UINT8 hopindex; +} __WLAN_ATTRIB_PACK__ wlan_ie_fh_parms_t; + +/*-- DS Parameter Set ----------------------------*/ +typedef struct wlan_ie_ds_parms +{ + UINT8 eid; + UINT8 len; + UINT8 curr_ch; +} __WLAN_ATTRIB_PACK__ wlan_ie_ds_parms_t; + +/*-- CF Parameter Set ----------------------------*/ + +typedef struct wlan_ie_cf_parms +{ + UINT8 eid; + UINT8 len; + UINT8 cfp_cnt; + UINT8 cfp_period; + UINT16 cfp_maxdur; + UINT16 cfp_durremaining; +} __WLAN_ATTRIB_PACK__ wlan_ie_cf_parms_t; + +/*-- TIM ------------------------------------------*/ +typedef struct wlan_ie_tim +{ + UINT8 eid; + UINT8 len; + UINT8 dtim_cnt; + UINT8 dtim_period; + UINT8 bitmap_ctl; + UINT8 virt_bm[1]; +} __WLAN_ATTRIB_PACK__ wlan_ie_tim_t; + +/*-- IBSS Parameter Set ---------------------------*/ +typedef struct wlan_ie_ibss_parms +{ + UINT8 eid; + UINT8 len; + UINT16 atim_win; +} __WLAN_ATTRIB_PACK__ wlan_ie_ibss_parms_t; + +/*-- Challenge Text ------------------------------*/ +typedef struct wlan_ie_challenge +{ + UINT8 eid; + UINT8 len; + UINT8 challenge[1]; +} __WLAN_ATTRIB_PACK__ wlan_ie_challenge_t; + +/*-------------------------------------------------*/ +/* Frame Types */ + +/* prototype structure, all mgmt frame types will start with these members */ +typedef struct wlan_fr_mgmt +{ + UINT16 type; + UINT16 len; /* DOES NOT include CRC !!!!*/ + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ +} wlan_fr_mgmt_t; + +/*-- Beacon ---------------------------------------*/ +typedef struct wlan_fr_beacon +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT64 *ts; + UINT16 *bcn_int; + UINT16 *cap_info; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_fh_parms_t *fh_parms; + wlan_ie_ds_parms_t *ds_parms; + wlan_ie_cf_parms_t *cf_parms; + wlan_ie_ibss_parms_t *ibss_parms; + wlan_ie_tim_t *tim; + +} wlan_fr_beacon_t; + + +/*-- IBSS ATIM ------------------------------------*/ +typedef struct wlan_fr_ibssatim +{ + UINT16 type; + UINT16 len; + UINT8* buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ + + /* this frame type has a null body */ + +} wlan_fr_ibssatim_t; + +/*-- Disassociation -------------------------------*/ +typedef struct wlan_fr_disassoc +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *reason; + + /*-- info elements ----------*/ + +} wlan_fr_disassoc_t; + +/*-- Association Request --------------------------*/ +typedef struct wlan_fr_assocreq +{ + UINT16 type; + UINT16 len; + UINT8* buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *listen_int; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_assocreq_t; + +/*-- Association Response -------------------------*/ +typedef struct wlan_fr_assocresp +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *status; + UINT16 *aid; + /*-- info elements ----------*/ + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_assocresp_t; + +/*-- Reassociation Request ------------------------*/ +typedef struct wlan_fr_reassocreq +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *listen_int; + UINT8 *curr_ap; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_reassocreq_t; + +/*-- Reassociation Response -----------------------*/ +typedef struct wlan_fr_reassocresp +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *status; + UINT16 *aid; + /*-- info elements ----------*/ + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_reassocresp_t; + +/*-- Probe Request --------------------------------*/ +typedef struct wlan_fr_probereq +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_probereq_t; + +/*-- Probe Response -------------------------------*/ +typedef struct wlan_fr_proberesp +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT64 *ts; + UINT16 *bcn_int; + UINT16 *cap_info; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_fh_parms_t *fh_parms; + wlan_ie_ds_parms_t *ds_parms; + wlan_ie_cf_parms_t *cf_parms; + wlan_ie_ibss_parms_t *ibss_parms; +} wlan_fr_proberesp_t; + +/*-- Authentication -------------------------------*/ +typedef struct wlan_fr_authen +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *auth_alg; + UINT16 *auth_seq; + UINT16 *status; + /*-- info elements ----------*/ + wlan_ie_challenge_t *challenge; + +} wlan_fr_authen_t; + +/*-- Deauthenication -----------------------------*/ +typedef struct wlan_fr_deauthen +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *reason; + + /*-- info elements ----------*/ + +} wlan_fr_deauthen_t; + + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + +void wlan_mgmt_encode_beacon( wlan_fr_beacon_t *f ); +void wlan_mgmt_decode_beacon( wlan_fr_beacon_t *f ); +void wlan_mgmt_encode_disassoc( wlan_fr_disassoc_t *f ); +void wlan_mgmt_decode_disassoc( wlan_fr_disassoc_t *f ); +void wlan_mgmt_encode_assocreq( wlan_fr_assocreq_t *f ); +void wlan_mgmt_decode_assocreq( wlan_fr_assocreq_t *f ); +void wlan_mgmt_encode_assocresp( wlan_fr_assocresp_t *f ); +void wlan_mgmt_decode_assocresp( wlan_fr_assocresp_t *f ); +void wlan_mgmt_encode_reassocreq( wlan_fr_reassocreq_t *f ); +void wlan_mgmt_decode_reassocreq( wlan_fr_reassocreq_t *f ); +void wlan_mgmt_encode_reassocresp( wlan_fr_reassocresp_t *f ); +void wlan_mgmt_decode_reassocresp( wlan_fr_reassocresp_t *f ); +void wlan_mgmt_encode_probereq( wlan_fr_probereq_t *f ); +void wlan_mgmt_decode_probereq( wlan_fr_probereq_t *f ); +void wlan_mgmt_encode_proberesp( wlan_fr_proberesp_t *f ); +void wlan_mgmt_decode_proberesp( wlan_fr_proberesp_t *f ); +void wlan_mgmt_encode_authen( wlan_fr_authen_t *f ); +void wlan_mgmt_decode_authen( wlan_fr_authen_t *f ); +void wlan_mgmt_encode_deauthen( wlan_fr_deauthen_t *f ); +void wlan_mgmt_decode_deauthen( wlan_fr_deauthen_t *f ); + + +#endif /* _P80211MGMT_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211conv.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211conv.h @@ -0,0 +1,186 @@ +/* src/include/wlan/p80211conv.h +* +* Ether/802.11 conversions and packet buffer routines +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the functions, types and macros that perform +* Ethernet to/from 802.11 frame conversions. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _LINUX_P80211CONV_H +#define _LINUX_P80211CONV_H + +/*================================================================*/ +/* Constants */ + +#define WLAN_ETHADDR_LEN 6 +#define WLAN_IEEE_OUI_LEN 3 + +#define WLAN_ETHCONV_ENCAP 1 +#define WLAN_ETHCONV_RFC1042 2 +#define WLAN_ETHCONV_8021h 3 + +#define WLAN_MIN_ETHFRM_LEN 60 +#define WLAN_MAX_ETHFRM_LEN 1514 +#define WLAN_ETHHDR_LEN 14 + +#define P80211CAPTURE_VERSION 0x80211001 + +/*================================================================*/ +/* Macros */ + +#define P80211_FRMMETA_MAGIC 0x802110 + +#define P80211SKB_FRMMETA(s) \ + (((((p80211_frmmeta_t*)((s)->cb))->magic)==P80211_FRMMETA_MAGIC) ? \ + ((p80211_frmmeta_t*)((s)->cb)) : \ + (NULL)) + +#define P80211SKB_RXMETA(s) \ + (P80211SKB_FRMMETA((s)) ? P80211SKB_FRMMETA((s))->rx : ((p80211_rxmeta_t*)(NULL))) + +typedef struct p80211_rxmeta +{ + struct wlandevice *wlandev; + + UINT64 mactime; /* Hi-rez MAC-supplied time value */ + UINT64 hosttime; /* Best-rez host supplied time value */ + + UINT rxrate; /* Receive data rate in 100kbps */ + UINT priority; /* 0-15, 0=contention, 6=CF */ + INT signal; /* An SSI, see p80211netdev.h */ + INT noise; /* An SSI, see p80211netdev.h */ + UINT channel; /* Receive channel (mostly for snifs) */ + UINT preamble; /* P80211ENUM_preambletype_* */ + UINT encoding; /* P80211ENUM_encoding_* */ + +} p80211_rxmeta_t; + +typedef struct p80211_frmmeta +{ + UINT magic; + p80211_rxmeta_t *rx; +} p80211_frmmeta_t; + +void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb); +int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb); +void p80211skb_rxmeta_detach(struct sk_buff *skb); + +/*================================================================*/ +/* Types */ + +/* + * Frame capture header. (See doc/capturefrm.txt) + */ +typedef struct p80211_caphdr +{ + UINT32 version; + UINT32 length; + UINT64 mactime; + UINT64 hosttime; + UINT32 phytype; + UINT32 channel; + UINT32 datarate; + UINT32 antenna; + UINT32 priority; + UINT32 ssi_type; + INT32 ssi_signal; + INT32 ssi_noise; + UINT32 preamble; + UINT32 encoding; +} p80211_caphdr_t; + +/* buffer free method pointer type */ +typedef void (* freebuf_method_t)(void *buf, int size); + +typedef struct p80211_metawep { + void *data; + UINT8 iv[4]; + UINT8 icv[4]; +} p80211_metawep_t; + +/* local ether header type */ +typedef struct wlan_ethhdr +{ + UINT8 daddr[WLAN_ETHADDR_LEN]; + UINT8 saddr[WLAN_ETHADDR_LEN]; + UINT16 type; +} __WLAN_ATTRIB_PACK__ wlan_ethhdr_t; + +/* local llc header type */ +typedef struct wlan_llc +{ + UINT8 dsap; + UINT8 ssap; + UINT8 ctl; +} __WLAN_ATTRIB_PACK__ wlan_llc_t; + +/* local snap header type */ +typedef struct wlan_snap +{ + UINT8 oui[WLAN_IEEE_OUI_LEN]; + UINT16 type; +} __WLAN_ATTRIB_PACK__ wlan_snap_t; + +/* Circular include trick */ +struct wlandevice; + +/*================================================================*/ +/* Externs */ + +/*================================================================*/ +/*Function Declarations */ + +int skb_p80211_to_ether( struct wlandevice *wlandev, UINT32 ethconv, + struct sk_buff *skb); +int skb_ether_to_p80211( struct wlandevice *wlandev, UINT32 ethconv, + struct sk_buff *skb, p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep ); + +int p80211_stt_findproto(UINT16 proto); +int p80211_stt_addproto(UINT16 proto); + +#endif --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211req.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211req.h @@ -0,0 +1,68 @@ +/* src/include/wlan/p80211req.h +* +* Request handling functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _LINUX_P80211REQ_H +#define _LINUX_P80211REQ_H + +/*================================================================*/ +/* Constants */ + +/*================================================================*/ +/* Macros */ + +/*================================================================*/ +/* Types */ + +/*================================================================*/ +/* Externs */ + +/*================================================================*/ +/* Function Declarations */ + +int p80211req_dorequest(wlandevice_t *wlandev, UINT8 *msgbuf); + +#endif --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/wlan_compat.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/wlan_compat.h @@ -0,0 +1,784 @@ +/* src/include/wlan/wlan_compat.h +* +* Types and macros to aid in portability +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _WLAN_COMPAT_H +#define _WLAN_COMPAT_H + +/*=============================================================*/ +/*------ Establish Platform Identity --------------------------*/ +/*=============================================================*/ +/* Key macros: */ +/* WLAN_CPU_FAMILY */ + #define WLAN_Ix86 1 + #define WLAN_PPC 2 + #define WLAN_Ix96 3 + #define WLAN_ARM 4 + #define WLAN_ALPHA 5 + #define WLAN_MIPS 6 + #define WLAN_HPPA 7 + #define WLAN_SPARC 8 + #define WLAN_SH 9 + #define WLAN_x86_64 10 +/* WLAN_SYSARCH */ + #define WLAN_PCAT 1 + #define WLAN_MBX 2 + #define WLAN_RPX 3 + #define WLAN_LWARCH 4 + #define WLAN_PMAC 5 + #define WLAN_SKIFF 6 + #define WLAN_BITSY 7 + #define WLAN_ALPHAARCH 7 + #define WLAN_MIPSARCH 9 + #define WLAN_HPPAARCH 10 + #define WLAN_SPARCARCH 11 + #define WLAN_SHARCH 12 + +/* Note: the PLX HOSTIF above refers to some vendors implementations for */ +/* PCI. It's a PLX chip that is a PCI to PCMCIA adapter, but it */ +/* isn't a real PCMCIA host interface adapter providing all the */ +/* card&socket services. */ + +#if (defined(CONFIG_PPC) || defined(CONFIG_8xx) || defined(__powerpc__)) +#ifndef __ppc__ +#define __ppc__ +#endif +#endif + +#if defined(__KERNEL__) + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#if defined(__x86_64__) + #define WLAN_CPU_FAMILY WLAN_x86_64 + #define WLAN_SYSARCH WLAN_PCAT +#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) + #define WLAN_CPU_FAMILY WLAN_Ix86 + #define WLAN_SYSARCH WLAN_PCAT +#elif defined(__ppc__) + #define WLAN_CPU_FAMILY WLAN_PPC + #if defined(CONFIG_MBX) + #define WLAN_SYSARCH WLAN_MBX + #elif defined(CONFIG_RPXLITE) + #define WLAN_SYSARCH WLAN_RPX + #elif defined(CONFIG_RPXCLASSIC) + #define WLAN_SYSARCH WLAN_RPX + #else + #define WLAN_SYSARCH WLAN_PMAC + #endif +#elif defined(__arm__) + #define WLAN_CPU_FAMILY WLAN_ARM + #define WLAN_SYSARCH WLAN_SKIFF +#elif defined(__alpha__) + #define WLAN_CPU_FAMILY WLAN_ALPHA + #define WLAN_SYSARCH WLAN_ALPHAARCH +#elif defined(__mips__) + #define WLAN_CPU_FAMILY WLAN_MIPS + #define WLAN_SYSARCH WLAN_MIPSARCH +#elif defined(__hppa__) + #define WLAN_CPU_FAMILY WLAN_HPPA + #define WLAN_SYSARCH WLAN_HPPAARCH +#elif defined(__sparc__) + #define WLAN_CPU_FAMILY WLAN_SPARC + #define WLAN_SYSARCH WLAN_SPARC +#elif defined(__sh__) + #define WLAN_CPU_FAMILY WLAN_SH + #define WLAN_SYSARCH WLAN_SHARCH + #ifndef __LITTLE_ENDIAN__ + #define __LITTLE_ENDIAN__ + #endif +#else + #error "No CPU identified!" +#endif +#endif /* __KERNEL__ */ + +/* + Some big endian machines implicitly do all I/O in little endian mode. + + In particular: + Linux/PPC on PowerMacs (PCI) + Arm/Intel Xscale (PCI) + + This may also affect PLX boards and other BE &| PPC platforms; + as new ones are discovered, add them below. +*/ + +#if defined(WLAN_HOSTIF) +#if ((WLAN_HOSTIF == WLAN_PCI) || (WLAN_HOSTIF == WLAN_PLX)) +#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC) || (WLAN_SYSARCH == WLAN_SPARC)) +#define REVERSE_ENDIAN +#endif +#endif +#endif + +/*=============================================================*/ +/*------ Bit settings -----------------------------------------*/ +/*=============================================================*/ + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#include + +typedef u_int8_t UINT8; +typedef u_int16_t UINT16; +typedef u_int32_t UINT32; + +typedef int8_t INT8; +typedef int16_t INT16; +typedef int32_t INT32; + +typedef unsigned int UINT; +typedef signed int INT; + +typedef u_int64_t UINT64; +typedef int64_t INT64; + +#define UINT8_MAX (0xffUL) +#define UINT16_MAX (0xffffUL) +#define UINT32_MAX (0xffffffffUL) + +#define INT8_MAX (0x7fL) +#define INT16_MAX (0x7fffL) +#define INT32_MAX (0x7fffffffL) + +/*=============================================================*/ +/*------ Compiler Portability Macros --------------------------*/ +/*=============================================================*/ +#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed)) + +/*=============================================================*/ +/*------ OS Portability Macros --------------------------------*/ +/*=============================================================*/ + +#ifndef WLAN_DBVAR +#define WLAN_DBVAR wlan_debug +#endif + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) +# if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)) +# include +# else +# include +# endif +#elif defined(__KERNEL__) +# define PREEMPT_MASK (0x000000FFUL) +# define preempt_count() (0UL) +#endif + +#define WLAN_LOG_ERROR(x,args...) printk(KERN_ERR "%s: " x , __FUNCTION__ , ##args); + +#define WLAN_LOG_WARNING(x,args...) printk(KERN_WARNING "%s: " x , __FUNCTION__ , ##args); + +#define WLAN_LOG_NOTICE(x,args...) printk(KERN_NOTICE "%s: " x , __FUNCTION__ , ##args); + +#define WLAN_LOG_INFO(args... ) printk(KERN_INFO args) + +#if defined(WLAN_INCLUDE_DEBUG) + #define WLAN_ASSERT(c) if ((!(c)) && WLAN_DBVAR >= 1) { \ + WLAN_LOG_DEBUG(1, "Assertion failure!\n"); } + #define WLAN_HEX_DUMP( l, x, p, n) if( WLAN_DBVAR >= (l) ){ \ + int __i__; \ + printk(KERN_DEBUG x ":"); \ + for( __i__=0; __i__ < (n); __i__++) \ + printk( " %02x", ((UINT8*)(p))[__i__]); \ + printk("\n"); } + #define DBFENTER { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"---->\n"); } } + #define DBFEXIT { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"<----\n"); } } + + #define WLAN_LOG_DEBUG(l,x,args...) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s(%lu): " x , __FUNCTION__, (preempt_count() & PREEMPT_MASK), ##args ); +#else + #define WLAN_ASSERT(c) + #define WLAN_HEX_DUMP( l, s, p, n) + #define DBFENTER + #define DBFEXIT + + #define WLAN_LOG_DEBUG(l, s, args...) +#endif + +#ifdef CONFIG_SMP +#define __SMP__ 1 +#endif + +#if defined(__KERNEL__) + +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19))) +#define URB_ONLY_CALLBACK +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +#define PT_REGS , struct pt_regs *regs +#else +#define PT_REGS +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) +# define del_singleshot_timer_sync(a) del_timer_sync(a) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)) +#define CONFIG_NETLINK 1 +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) +#define kfree_s(a, b) kfree((a)) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) +#ifndef init_waitqueue_head +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,0,16)) +#define init_waitqueue_head(p) (*(p) = NULL) +#else +#define init_waitqueue_head(p) init_waitqueue(p) +#endif +typedef struct wait_queue *wait_queue_head_t; +typedef struct wait_queue wait_queue_t; +#define set_current_state(b) { current->state = (b); mb(); } +#define init_waitqueue_entry(a, b) { (a)->task = current; } +#endif +#endif + +#ifndef wait_event_interruptible_timeout +// retval == 0; signal met; we're good. +// retval < 0; interrupted by signal. +// retval > 0; timed out. + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) // fixme? + +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret) ; \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + set_current_state(TASK_RUNNING); \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#else // 2.2 + + +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + struct wait_queue __wait; \ + \ + __wait.task = current; \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + current->state = TASK_INTERRUPTIBLE; \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#endif // version >= 2.4 + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) + +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)) +#ifdef _LINUX_LIST_H + +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + + +#endif // LIST_H +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#define SET_MODULE_OWNER(x) do { } while (0) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,90)) +#define spin_lock(l) do { } while (0) +#define spin_unlock(l) do { } while (0) +#define spin_lock_irqsave(l,f) do { save_flags(f); cli(); } while (0) +#define spin_unlock_irqrestore(l,f) do { restore_flags(f); } while (0) +#define spin_lock_init(s) do { } while (0) +#define spin_trylock(l) (1) +typedef int spinlock_t; +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) // XXX ??? +#define spin_lock_bh spin_lock +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#ifdef CONFIG_SMP +#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0) +#else +#define spin_is_locked(l) (0) +#endif +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,28)) +#define __user +#define __iomem +#endif + +#ifdef _LINUX_PROC_FS_H + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +#define PROC_NET proc_net +#else +#define PROC_NET init_net.proc_net +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,25)) + +extern inline struct proc_dir_entry * +create_proc_read_entry(const char *name, mode_t mode, + struct proc_dir_entry *base, + read_proc_t *read_proc, void *data) +{ + struct proc_dir_entry *res = create_proc_entry(name, mode, base); + if (res) { + res->read_proc = read_proc; + res->data = data; + } + return res; +} +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)) +#ifndef proc_mkdir +#define proc_mkdir(name, root) create_proc_entry(name, S_IFDIR, root) +#endif +#endif +#endif /* _LINUX_PROC_FS_H */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +#define skb_reset_mac_header(__a) (__a)->mac.raw = (__a)->data +#define SKB_MAC_HEADER(__a) (__a)->mac.raw +#else +#define SKB_MAC_HEADER(__a) (__a)->mac_header +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#define IRQF_DISABLED SA_INTERRUPT +#define IRQF_SHARED SA_SHIRQ +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#ifndef INIT_TQUEUE +#define PREPARE_TQUEUE(_tq, _routine, _data) \ + do { \ + (_tq)->routine = _routine; \ + (_tq)->data = _data; \ + } while (0) +#define INIT_TQUEUE(_tq, _routine, _data) \ + do { \ + INIT_LIST_HEAD(&(_tq)->list); \ + (_tq)->sync = 0; \ + PREPARE_TQUEUE((_tq), (_routine), (_data)); \ + } while (0) +#endif + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#ifndef INIT_WORK +#define work_struct tq_struct + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#define schedule_work(a) queue_task(a, &tq_scheduler) +#else +#define schedule_work(a) schedule_task(a) +#endif + +#define flush_scheduled_work flush_scheduled_tasks +#define INIT_WORK2(_wq, _routine) INIT_TQUEUE(_wq, (void (*)(void *))_routine, _wq) +#endif + +#else // >= 2.5 kernel + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#define INIT_WORK2(_wq, _routine) INIT_WORK(_wq, (void (*)(void *))_routine, _wq) +#else +#define INIT_WORK2(_wq, _routine) INIT_WORK(_wq, _routine) +#endif + +#endif // >= 2.5 kernel + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38)) +typedef struct device netdevice_t; +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)) +typedef struct net_device netdevice_t; +#else +#undef netdevice_t +typedef struct net_device netdevice_t; +#endif + +#ifdef WIRELESS_EXT +#if (WIRELESS_EXT < 13) +struct iw_request_info +{ + __u16 cmd; /* Wireless Extension command */ + __u16 flags; /* More to come ;-) */ +}; +#endif +#endif + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,18)) +#define MODULE_PARM(a,b) extern int __bogus_decl +#define MODULE_AUTHOR(a) extern int __bogus_decl +#define MODULE_DESCRIPTION(a) extern int __bogus_decl +#define MODULE_SUPPORTED_DEVICE(a) extern int __bogus_decl +#undef GET_USE_COUNT +#define GET_USE_COUNT(m) mod_use_count_ +#endif + +#ifndef MODULE_OWNER +#define MODULE_OWNER(a) extern int __bogus_decl +#define ANCIENT_MODULE_CODE +#endif + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(m) extern int __bogus_decl +#endif + +/* TODO: Do we care about this? */ +#ifndef MODULE_DEVICE_TABLE +#define MODULE_DEVICE_TABLE(foo,bar) +#endif + +#define wlan_minutes2ticks(a) ((a)*(wlan_ticks_per_sec * 60)) +#define wlan_seconds2ticks(a) ((a)*(wlan_ticks_per_sec)) + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,47)) +#define NEW_MODULE_CODE +#ifdef ANCIENT_MODULE_CODE +#undef ANCIENT_MODULE_CODE +#endif +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25)) +#define module_param(name, type, perm) \ + static inline void *__check_existence_##name(void) { return &name; } \ + MODULE_PARM(name, _MODULE_PARM_STRING_ ## type) + +#define _MODULE_PARM_STRING_byte "b" +#define _MODULE_PARM_STRING_short "h" +#define _MODULE_PARM_STRING_ushort "h" +#define _MODULE_PARM_STRING_int "i" +#define _MODULE_PARM_STRING_uint "i" +#define _MODULE_PARM_STRING_long "l" +#define _MODULE_PARM_STRING_ulong "l" +#define _MODULE_PARM_STRING_bool "i" +#endif + +/* linux < 2.5.69 */ +#ifndef IRQ_NONE +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) +#endif + +#ifndef in_atomic +#define in_atomic() 0 +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +#define URB_ASYNC_UNLINK 0 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) +#define URB_ASYNC_UNLINK USB_ASYNC_UNLINK +#define usb_fill_bulk_urb FILL_BULK_URB +#define usb_kill_urb usb_unlink_urb +#else +#define USB_QUEUE_BULK 0 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) +typedef u32 pm_message_t; +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)) +#define hotplug_path "/etc/hotplug/wlan.agent" +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +#define free_netdev(x) kfree(x) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) +#define eth_hdr(x) (x)->mac.ethernet +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#define del_timer_sync(a) del_timer(a) +#endif + +#ifndef might_sleep +#define might_sleep(a) do { } while (0) +#endif + +/* Apparently 2.4.2 ethtool is quite different, maybe newer too? */ +#if (defined(SIOETHTOOL) && !defined(ETHTOOL_GDRVINFO)) +#undef SIOETHTOOL +#endif + +// pcmcia-cs stuff +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) && \ + !defined(pcmcia_access_configuration_register)) +#define pcmcia_access_configuration_register(handle, reg) \ + CardServices(AccessConfigurationRegister, handle, reg) +#define pcmcia_register_client(handle, reg) \ + CardServices(RegisterClient, handle, reg) +#define pcmcia_deregister_client(handle) \ + CardServices(DeregisterClient, handle) +#define pcmcia_get_first_tuple(handle, tuple) \ + CardServices(GetFirstTuple, handle, tuple) +#define pcmcia_get_next_tuple(handle, tuple) \ + CardServices(GetNextTuple, handle, tuple) +#define pcmcia_get_tuple_data(handle, tuple) \ + CardServices(GetTupleData, handle, tuple) +#define pcmcia_parse_tuple(handle, tuple, parse) \ + CardServices(ParseTuple, handle, tuple, parse) +#define pcmcia_get_configuration_info(handle, config) \ + CardServices(GetConfigurationInfo, handle, config) +#define pcmcia_request_io(handle, req) \ + CardServices(RequestIO, handle, req) +#define pcmcia_request_irq(handle, req) \ + CardServices(RequestIRQ, handle, req) +#define pcmcia_request_configuration(handle, req) \ + CardServices(RequestConfiguration, handle, req) +#define pcmcia_release_configuration(handle) \ + CardServices(ReleaseConfiguration, handle) +#define pcmcia_release_io(handle, req) \ + CardServices(ReleaseIO, handle, req) +#define pcmcia_release_irq(handle, req) \ + CardServices(ReleaseIRQ, handle, req) +#define pcmcia_release_window(win) \ + CardServices(ReleaseWindow, win) +#define pcmcia_get_card_services_info(info) \ + CardServices(GetCardServicesInfo, info) +#define pcmcia_report_error(handle, err) \ + CardServices(ReportError, handle, err) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) +#define round_jiffies(a) (a) +#endif + +#endif /* __KERNEL__ */ + +/*=============================================================*/ +/*------ Hardware Portability Macros --------------------------*/ +/*=============================================================*/ + +#define ieee2host16(n) __le16_to_cpu(n) +#define ieee2host32(n) __le32_to_cpu(n) +#define host2ieee16(n) __cpu_to_le16(n) +#define host2ieee32(n) __cpu_to_le32(n) + +#if (WLAN_CPU_FAMILY != WLAN_MIPS) +typedef UINT32 phys_t; +#endif + +#if (WLAN_CPU_FAMILY == WLAN_PPC) + #define wlan_inw(a) in_be16((unsigned short *)((a)+_IO_BASE)) + #define wlan_inw_le16_to_cpu(a) inw((a)) + #define wlan_outw(v,a) out_be16((unsigned short *)((a)+_IO_BASE), (v)) + #define wlan_outw_cpu_to_le16(v,a) outw((v),(a)) +#else + #define wlan_inw(a) inw((a)) + #define wlan_inw_le16_to_cpu(a) __cpu_to_le16(inw((a))) + #define wlan_outw(v,a) outw((v),(a)) + #define wlan_outw_cpu_to_le16(v,a) outw(__cpu_to_le16((v)),(a)) +#endif + +/*=============================================================*/ +/*--- General Macros ------------------------------------------*/ +/*=============================================================*/ + +#define wlan_max(a, b) (((a) > (b)) ? (a) : (b)) +#define wlan_min(a, b) (((a) < (b)) ? (a) : (b)) + +#define wlan_isprint(c) (((c) > (0x19)) && ((c) < (0x7f))) + +#define wlan_hexchar(x) (((x) < 0x0a) ? ('0' + (x)) : ('a' + ((x) - 0x0a))) + +/* Create a string of printable chars from something that might not be */ +/* It's recommended that the str be 4*len + 1 bytes long */ +#define wlan_mkprintstr(buf, buflen, str, strlen) \ +{ \ + int i = 0; \ + int j = 0; \ + memset(str, 0, (strlen)); \ + for (i = 0; i < (buflen); i++) { \ + if ( wlan_isprint((buf)[i]) ) { \ + (str)[j] = (buf)[i]; \ + j++; \ + } else { \ + (str)[j] = '\\'; \ + (str)[j+1] = 'x'; \ + (str)[j+2] = wlan_hexchar(((buf)[i] & 0xf0) >> 4); \ + (str)[j+3] = wlan_hexchar(((buf)[i] & 0x0f)); \ + j += 4; \ + } \ + } \ +} + +/*=============================================================*/ +/*--- Variables -----------------------------------------------*/ +/*=============================================================*/ + +#ifdef WLAN_INCLUDE_DEBUG +extern int wlan_debug; +#endif + +extern int wlan_ethconv; /* What's the default ethconv? */ + +/*=============================================================*/ +/*--- Functions -----------------------------------------------*/ +/*=============================================================*/ +#endif /* _WLAN_COMPAT_H */ + --- linux-2.6.27.orig/ubuntu/misc/wireless/p80211/wlan/p80211msg.h +++ linux-2.6.27/ubuntu/misc/wireless/p80211/wlan/p80211msg.h @@ -0,0 +1,102 @@ +/* src/include/wlan/p80211msg.h +* +* Macros, constants, types, and funcs for req and ind messages +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MSG_H +#define _P80211MSG_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include +#endif + +/*================================================================*/ +/* Constants */ + +#define MSG_BUFF_LEN 4000 +#define WLAN_DEVNAMELEN_MAX 16 + +/*================================================================*/ +/* Macros */ + +/*================================================================*/ +/* Types */ + +/*--------------------------------------------------------------------*/ +/*----- Message Structure Types --------------------------------------*/ + +/*--------------------------------------------------------------------*/ +/* Prototype msg type */ + +typedef struct p80211msg +{ + UINT32 msgcode; + UINT32 msglen; + UINT8 devname[WLAN_DEVNAMELEN_MAX]; +} __WLAN_ATTRIB_PACK__ p80211msg_t; + +typedef struct p80211msgd +{ + UINT32 msgcode; + UINT32 msglen; + UINT8 devname[WLAN_DEVNAMELEN_MAX]; + UINT8 args[0]; +} __WLAN_ATTRIB_PACK__ p80211msgd_t; + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + +#endif /* _P80211MSG_H */ + --- linux-2.6.27.orig/ubuntu/misc/wireless/at76/at76c503.h +++ linux-2.6.27/ubuntu/misc/wireless/at76/at76c503.h @@ -0,0 +1,729 @@ +/* -*- linux-c -*- */ +/* + * Copyright (c) 2002 - 2003 Oliver Kurth + * (c) 2003 - 2004 Jörg Albert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This driver was based on information from the Sourceforge driver + * released and maintained by Atmel: + * + * http://sourceforge.net/projects/atmelwlandriver/ + * + * Although the code was completely re-written, + * it would have been impossible without Atmel's decision to + * release an Open Source driver (unfortunately the firmware was + * kept binary only). Thanks for that decision to Atmel! + * + * For the latest version of this driver, mailinglists + * and other info, please check + * http://at76c503a.berlios.de/ + */ + +#ifndef _AT76C503_H +#define _AT76C503_H + +#include + +/* current driver version */ +#define DRIVER_VERSION "0.14beta1" + + +/* our private ioctl's */ +/* set preamble length*/ +#define PRIV_IOCTL_SET_SHORT_PREAMBLE (SIOCIWFIRSTPRIV + 0x0) +/* set debug parameter */ +#define PRIV_IOCTL_SET_DEBUG (SIOCIWFIRSTPRIV + 0x2) +/* set power save mode (incl. the Atmel proprietary smart save mode */ +#define PRIV_IOCTL_SET_POWERSAVE_MODE (SIOCIWFIRSTPRIV + 0x4) +/* set min and max channel times for scan */ +#define PRIV_IOCTL_SET_SCAN_TIMES (SIOCIWFIRSTPRIV + 0x6) +/* set scan mode */ +#define PRIV_IOCTL_SET_SCAN_MODE (SIOCIWFIRSTPRIV + 0x8) +/* set international roaming */ +#define PRIV_IOCTL_SET_INTL_ROAMING (SIOCIWFIRSTPRIV + 0x10) +/* set monitor mode */ +#define PRIV_IOCTL_SET_MONITOR_MODE (SIOCIWFIRSTPRIV + 0x12) + +#define DEVICE_VENDOR_REQUEST_OUT 0x40 +#define DEVICE_VENDOR_REQUEST_IN 0xc0 +#define INTERFACE_VENDOR_REQUEST_OUT 0x41 +#define INTERFACE_VENDOR_REQUEST_IN 0xc1 +#define CLASS_REQUEST_OUT 0x21 +#define CLASS_REQUEST_IN 0xa1 + +#define CMD_STATUS_IDLE 0x00 +#define CMD_STATUS_COMPLETE 0x01 +#define CMD_STATUS_UNKNOWN 0x02 +#define CMD_STATUS_INVALID_PARAMETER 0x03 +#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04 +#define CMD_STATUS_TIME_OUT 0x07 +#define CMD_STATUS_IN_PROGRESS 0x08 +#define CMD_STATUS_HOST_FAILURE 0xff +#define CMD_STATUS_SCAN_FAILED 0xf0 + +/* answers to get op mode */ +#define OPMODE_NONE 0x00 +#define OPMODE_NORMAL_NIC_WITH_FLASH 0x01 +#define OPMODE_HW_CONFIG_MODE 0x02 +#define OPMODE_DFU_MODE_WITH_FLASH 0x03 +#define OPMODE_NORMAL_NIC_WITHOUT_FLASH 0x04 + +#define CMD_SET_MIB 0x01 +#define CMD_GET_MIB 0x02 +#define CMD_SCAN 0x03 +#define CMD_JOIN 0x04 +#define CMD_START_IBSS 0x05 +#define CMD_RADIO 0x06 +#define CMD_STARTUP 0x0B +#define CMD_GETOPMODE 0x33 + +#define MIB_LOCAL 0x01 +#define MIB_MAC_ADD 0x02 +#define MIB_MAC 0x03 +#define MIB_MAC_MGMT 0x05 +#define MIB_MAC_WEP 0x06 +#define MIB_PHY 0x07 +#define MIB_FW_VERSION 0x08 +#define MIB_MDOMAIN 0x09 + +#define ADHOC_MODE 1 +#define INFRASTRUCTURE_MODE 2 + +/* values for struct mib_local, field preamble_type */ +#define PREAMBLE_TYPE_SHORT 1 +#define PREAMBLE_TYPE_LONG 0 + +/* values for tx_rate */ +#define TX_RATE_1MBIT 0 +#define TX_RATE_2MBIT 1 +#define TX_RATE_5_5MBIT 2 +#define TX_RATE_11MBIT 3 +#define TX_RATE_AUTO 4 + +/* power management modes */ +#define PM_ACTIVE 1 +#define PM_SAVE 2 +#define PM_SMART_SAVE 3 + +/* international roaming state */ +#define IR_OFF 0 +#define IR_ON 1 + +/* monitor mode - param of private ioctl */ +#define MM_OFF 0 +#define MM_ON 1 +#define MM_ON_NO_PRISM 2 + + +/* offsets into the MIBs we use to configure the device */ +#define TX_AUTORATE_FALLBACK_OFFSET offsetof(struct mib_local,txautorate_fallback) +#define FRAGMENTATION_OFFSET offsetof(struct mib_mac,frag_threshold) +#define PREAMBLE_TYPE_OFFSET offsetof(struct mib_local,preamble_type) +#define RTS_OFFSET offsetof(struct mib_mac, rts_threshold) + +/* valid only for rfmd and 505 !*/ +#define IBSS_CHANGE_OK_OFFSET offsetof(struct mib_mac_mgmt, ibss_change) +#define IROAMING_IMPL_OFFSET offsetof(struct mib_mac_mgmt, multi_domain_capability_implemented) +#define IROAMING_OFFSET \ + offsetof(struct mib_mac_mgmt, multi_domain_capability_enabled) +/* the AssocID */ +#define STATION_ID_OFFSET offsetof(struct mib_mac_mgmt, station_id) +#define POWER_MGMT_MODE_OFFSET offsetof(struct mib_mac_mgmt, power_mgmt_mode) +#define LISTEN_INTERVAL_OFFSET offsetof(struct mib_mac, listen_interval) + +#define PRIVACY_OPT_IMPL offsetof(struct mib_mac_mgmt, privacy_option_implemented) + +#define BOARDTYPE_503_INTERSIL_3861 1 +#define BOARDTYPE_503_INTERSIL_3863 2 +#define BOARDTYPE_503_RFMD 3 +#define BOARDTYPE_503_RFMD_ACC 4 +#define BOARDTYPE_505_RFMD 5 +#define BOARDTYPE_505_RFMD_2958 6 +#define BOARDTYPE_505A_RFMD_2958 7 +#define BOARDTYPE_505AMX_RFMD 8 + +struct hwcfg_r505 { + u8 cr39_values[14]; + u8 reserved1[14]; + u8 bb_cr[14]; + u8 pidvid[4]; + u8 mac_addr[ETH_ALEN]; + u8 regulatory_domain; + u8 reserved2[14]; + u8 cr15_values[14]; + u8 reserved3[3]; +} __attribute__ ((packed)); + +struct hwcfg_rfmd { + u8 cr20_values[14]; + u8 cr21_values[14]; + u8 bb_cr[14]; + u8 pidvid[4]; + u8 mac_addr[ETH_ALEN]; + u8 regulatory_domain; + u8 low_power_values[14]; + u8 normal_power_values[14]; + u8 reserved1[3]; +} __attribute__ ((packed)); + +struct hwcfg_intersil { + u8 mac_addr[ETH_ALEN]; + u8 cr31_values[14]; + u8 cr58_values[14]; + u8 pidvid[4]; + u8 regulatory_domain; + u8 reserved[1]; +} __attribute__ ((packed)); + +#define WEP_SMALL_KEY_LEN (40/8) +#define WEP_LARGE_KEY_LEN (104/8) + +struct at76c503_card_config{ + u8 exclude_unencrypted; + u8 promiscuous_mode; + u8 short_retry_limit; + u8 encryption_type; + __le16 rts_threshold; + __le16 fragmentation_threshold; // 256..2346 + u8 basic_rate_set[4]; + u8 auto_rate_fallback; //0,1 + u8 channel; + u8 privacy_invoked; + u8 wep_default_key_id; // 0..3 + u8 current_ssid[32]; + u8 wep_default_key_value[4][WEP_KEY_LEN]; + u8 ssid_len; + u8 short_preamble; + __le16 beacon_period; +} __attribute__ ((packed)); + +struct at76c503_command{ + u8 cmd; + u8 reserved; + __le16 size; +} __attribute__ ((packed)); + +/* the length of the Atmel firmware specific rx header before IEEE 802.11 starts */ +#define AT76C503_RX_HDRLEN offsetof(struct at76c503_rx_buffer, packet) + +struct at76c503_rx_buffer { + __le16 wlength; + u8 rx_rate; + u8 newbss; + u8 fragmentation; + u8 rssi; + u8 link_quality; + u8 noise_level; + u8 rx_time[4]; + u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN]; +} __attribute__ ((packed)); + +/* the length of the Atmel firmware specific tx header before IEEE 802.11 starts */ +#define AT76C503_TX_HDRLEN offsetof(struct at76c503_tx_buffer, packet) + +struct at76c503_tx_buffer { + __le16 wlength; + u8 tx_rate; + u8 padding; + u8 reserved[4]; + u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN]; +} __attribute__ ((packed)); + +/* defines for scan_type below */ +#define SCAN_TYPE_ACTIVE 0 +#define SCAN_TYPE_PASSIVE 1 + +struct at76c503_start_scan { + u8 bssid[ETH_ALEN]; + u8 essid[32]; + u8 scan_type; + u8 channel; + __le16 probe_delay; + __le16 min_channel_time; + __le16 max_channel_time; + u8 essid_size; + u8 international_scan; +} __attribute__ ((packed)); + +struct at76c503_start_bss { + u8 bssid[ETH_ALEN]; + u8 essid[32]; + u8 bss_type; + u8 channel; + u8 essid_size; + u8 reserved[3]; +} __attribute__ ((packed)); + +struct at76c503_join { + u8 bssid[ETH_ALEN]; + u8 essid[32]; + u8 bss_type; + u8 channel; + __le16 timeout; + u8 essid_size; + u8 reserved; +} __attribute__ ((packed)); + +struct set_mib_buffer { + u8 type; + u8 size; + u8 index; + u8 reserved; + u8 data[72]; +} __attribute__ ((packed)); + +struct mib_local { + u16 reserved0; + u8 beacon_enable; + u8 txautorate_fallback; + u8 reserved1; + u8 ssid_size; + u8 promiscuous_mode; + u16 reserved2; + u8 preamble_type; + u16 reserved3; +} __attribute__ ((packed)); + +struct mib_mac_addr { + u8 mac_addr[ETH_ALEN]; + u8 res[2]; /* ??? */ + u8 group_addr[4][ETH_ALEN]; + u8 group_addr_status[4]; +} __attribute__ ((packed)); + +struct mib_mac { + __le32 max_tx_msdu_lifetime; + __le32 max_rx_lifetime; + __le16 frag_threshold; + __le16 rts_threshold; + __le16 cwmin; + __le16 cwmax; + u8 short_retry_time; + u8 long_retry_time; + u8 scan_type; /* active or passive */ + u8 scan_channel; + __le16 probe_delay; /* delay before sending a ProbeReq in active scan, RO */ + __le16 min_channel_time; + __le16 max_channel_time; + __le16 listen_interval; + u8 desired_ssid[32]; + u8 desired_bssid[ETH_ALEN]; + u8 desired_bsstype; /* ad-hoc or infrastructure */ + u8 reserved2; +} __attribute__ ((packed)); + +struct mib_mac_mgmt { + __le16 beacon_period; + __le16 CFP_max_duration; + __le16 medium_occupancy_limit; + __le16 station_id; /* assoc id */ + __le16 ATIM_window; + u8 CFP_mode; + u8 privacy_option_implemented; + u8 DTIM_period; + u8 CFP_period; + u8 current_bssid[ETH_ALEN]; + u8 current_essid[32]; + u8 current_bss_type; + u8 power_mgmt_mode; + /* rfmd and 505 */ + u8 ibss_change; + u8 res; + u8 multi_domain_capability_implemented; + u8 multi_domain_capability_enabled; + u8 country_string[3]; + u8 reserved[3]; +} __attribute__ ((packed)); + +struct mib_mac_wep { + u8 privacy_invoked; /* 0 disable encr., 1 enable encr */ + u8 wep_default_key_id; + u8 wep_key_mapping_len; + u8 exclude_unencrypted; + __le32 wep_icv_error_count; + __le32 wep_excluded_count; + u8 wep_default_keyvalue[WEP_KEYS][WEP_KEY_LEN]; + u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */ +} __attribute__ ((packed)); + +struct mib_phy { + __le32 ed_threshold; + + __le16 slot_time; + __le16 sifs_time; + __le16 preamble_length; + __le16 plcp_header_length; + __le16 mpdu_max_length; + __le16 cca_mode_supported; + + u8 operation_rate_set[4]; + u8 channel_id; + u8 current_cca_mode; + u8 phy_type; + u8 current_reg_domain; +} __attribute__ ((packed)); + +struct mib_fw_version { + u8 major; + u8 minor; + u8 patch; + u8 build; +} __attribute__ ((packed)); + +struct mib_mdomain { + u8 tx_powerlevel[14]; + u8 channel_list[14]; /* 0 for invalid channels */ +} __attribute__ ((packed)); + +/* states in infrastructure mode */ +enum infra_state { + INIT, + SCANNING, + AUTHENTICATING, + ASSOCIATING, + REASSOCIATING, + DISASSOCIATING, + JOINING, + CONNECTED, + STARTIBSS, + INTFW_DOWNLOAD, + EXTFW_DOWNLOAD, + WAIT_FOR_DISCONNECT, + MONITORING, +}; + +/* a description of a regulatory domain and the allowed channels */ +struct reg_domain { + u16 code; + char const *name; + u32 channel_map; /* if bit N is set, channel (N+1) is allowed */ +}; + +/* how long do we keep a (I)BSS in the bss_list in jiffies + this should be long enough for the user to retrieve the table + (by iwlist ?) after the device started, because all entries from + other channels than the one the device locks on get removed, too */ +#define BSS_LIST_TIMEOUT (120*HZ) + +/* struct to store BSS info found during scan */ +#define BSS_LIST_MAX_RATE_LEN 32 /* 32 rates should be enough ... */ + +struct bss_info{ + struct list_head list; + + u8 mac[ETH_ALEN]; /* real mac address, differs + for ad-hoc from bssid */ + u8 bssid[ETH_ALEN]; /* bssid */ + u8 ssid[IW_ESSID_MAX_SIZE+1]; /* ssid, +1 for trailing \0 + to make it printable */ + u8 ssid_len; /* length of ssid above */ + u8 channel; + u16 capa; /* the capabilities of the BSS (in original endianess - + we only check IEEE802_11 bits in it) */ + u16 beacon_interval; /* the beacon interval in units of TU (1.024 ms) + (in CPU endianess - we must calc. values from it) */ + u8 rates[BSS_LIST_MAX_RATE_LEN]; /* supported rates (list of bytes: + (basic_rate ? 0x80 : 0) + rate/(500 Kbit/s); e.g. + x82,x84,x8b,x96 for basic rates 1,2,5.5,11 MBit/s) */ + u8 rates_len; + + /* quality of received beacon */ + u8 rssi; + u8 link_qual; + u8 noise_level; + + unsigned long last_rx; /* time (jiffies) of last beacon received */ + u16 assoc_id; /* if this is dev->curr_bss this is the assoc id we got + in a successful AssocResponse */ +}; + +/* a rx data buffer to collect rx fragments */ +struct rx_data_buf { + u8 sender[ETH_ALEN]; /* sender address */ + u16 seqnr; /* sequence number */ + u16 fragnr; /* last fragment received */ + unsigned long last_rx; /* jiffies of last rx */ + struct sk_buff *skb; /* == NULL if entry is free */ +}; + +#define NR_RX_DATA_BUF 8 + +/* how often do we try to submit a rx urb until giving up */ +#define NR_SUBMIT_RX_TRIES 8 + +struct at76c503 { + struct usb_device *udev; /* USB device pointer */ + struct net_device *netdev; /* net device pointer */ + struct net_device_stats stats; + struct iw_statistics wstats; + struct usb_interface *interface; /* the interface for this device */ + +// unsigned char num_ports; /* the number of ports this device has */ +// char num_interrupt_in; /* number of interrupt in endpoints we have */ +// char num_bulk_in; /* number of bulk in endpoints we have */ +// char num_bulk_out; /* number of bulk out endpoints we have */ + + struct sk_buff * rx_skb; /* skbuff for receiving packets */ + __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ + + unsigned char * bulk_out_buffer; /* the buffer to send data */ + int bulk_out_size; /* the size of the send buffer */ + struct urb * write_urb; /* the urb used to send data */ + struct urb * read_urb; + __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ + +// struct work_struct tqueue; /* task queue for line discipline waking up */ + int open_count; /* number of times this port has been opened */ + struct semaphore sem; /* locks this structure */ + + + unsigned long kevent_flags; + struct work_struct kevent; + int nr_submit_rx_tries; /* number of tries to submit an rx urb left */ + struct tasklet_struct tasklet; + struct urb *rx_urb; /* tmp urb pointer for rx_tasklet */ + + unsigned char *ctrl_buffer; + struct urb *ctrl_urb; + + u8 op_mode; + + /* the WEP stuff */ + int wep_enabled; /* 1 if WEP is enabled */ + int wep_key_id; /* key id to be used */ + u8 wep_keys[WEP_KEYS][WEP_KEY_LEN]; /* the four WEP keys, + 5 or 13 bytes are used */ + u8 wep_keys_len[WEP_KEYS]; /* the length of the above keys */ + + int channel; + int iw_mode; + int curr_ap; + u8 bssid[ETH_ALEN]; + u8 essid[IW_ESSID_MAX_SIZE]; + char nickn[IW_ESSID_MAX_SIZE+1]; /* nickname, only used in the iwconfig i/f */ + int essid_size; + int radio_on; + int promisc; + + int preamble_type; /* 0 - long preamble, 1 - short preamble */ + int auth_mode; /* authentication type: 0 open, 1 shared key */ + int txrate; /* 0,1,2,3 = 1,2,5.5,11 MBit, 4 is auto-fallback */ + int frag_threshold; /* threshold for fragmentation of tx packets */ + int rts_threshold; /* threshold for RTS mechanism */ + int short_retry_limit; + //int long_retry_limit; + + int scan_min_time; /* scan min channel time */ + int scan_max_time; /* scan max channel time */ + int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */ + int scan_runs; /* counts how many scans are started */ + + /* the list we got from scanning */ + spinlock_t bss_list_spinlock; /* protects bss_list operations and setting + curr_bss and new_bss */ + struct list_head bss_list; /* the list of bss we received beacons from */ + struct timer_list bss_list_timer; /* a timer removing old entries from + the bss_list. It must acquire bss_list_spinlock + before and must not remove curr_bss nor + new_bss ! */ + struct bss_info *curr_bss; /* if istate == AUTH, ASSOC, REASSOC, JOIN or CONN + dev->bss[curr_bss] is the currently selected BSS + we operate on */ + struct bss_info *new_bss; /* if istate == REASSOC dev->new_bss + is the new bss we want to reassoc to */ + + u8 wanted_bssid[ETH_ALEN]; + int wanted_bssid_valid; /* != 0 if wanted_bssid is to be used */ + + /* some data for infrastructure mode only */ + spinlock_t mgmt_spinlock; /* this spinlock protects access to + next_mgmt_bulk */ + spinlock_t istate_spinlock; /* this spinlock protects access to + istate */ + + + struct at76c503_tx_buffer *next_mgmt_bulk; /* pending management msg to + send via bulk out */ + enum infra_state istate; + enum { + SITE_SURVEY_IDLE, + SITE_SURVEY_IN_PROGRESS, + SITE_SURVEY_COMPLETED + } site_survey_state; + time_t last_survey; + + struct timer_list restart_timer; /* the timer we use to delay the restart a bit */ + + struct timer_list mgmt_timer; /* the timer we use to repeat auth_req etc. */ + int retries; /* counts backwards while re-trying to send auth/assoc_req's */ + u16 assoc_id; /* the assoc_id for states JOINING, REASSOCIATING, CONNECTED */ + u8 pm_mode ; /* power management mode: ACTIVE, SAVE, SMART_SAVE */ + u32 pm_period_us; /* power manag. period (in us ?) - set by iwconfig */ + u32 pm_period_beacon; /* power manag. period (in beacon intervals + of the curr_bss) */ + u32 board_type; /* BOARDTYPE_* defined above*/ + + struct reg_domain const *domain; /* the description of the regulatory domain */ + + /* iwspy support */ + spinlock_t spy_spinlock; + struct iw_spy_data spy_data; + +#if WIRELESS_EXT > 16 + struct iw_public_data wireless_data; +#endif /* WIRELESS_EXT > 16 */ + + /* These fields contain HW config provided by the device (not all of + * these fields are used by all board types) */ + u8 mac_addr[ETH_ALEN]; + u8 bb_cr[14]; + u8 pidvid[4]; + u8 regulatory_domain; + u8 cr15_values[14]; + u8 cr20_values[14]; + u8 cr21_values[14]; + u8 cr31_values[14]; + u8 cr39_values[14]; + u8 cr58_values[14]; + u8 low_power_values[14]; + u8 normal_power_values[14]; + + struct at76c503_card_config card_config; + struct mib_fw_version fw_version; + + int rx_data_fcs_len; /* length of the trailing FCS + (0 for fw <= 0.84.x, 4 otherwise) */ + + /* store rx fragments until complete */ + struct rx_data_buf rx_data[NR_RX_DATA_BUF]; + + /* firmware downloading stuff */ + struct timer_list fw_dl_timer; /* timer used to wait after REMAP + until device is reset */ + int extfw_size; + int intfw_size; + /* these point into a buffer managed by at76c503-xxx.o, no need to dealloc */ + u8 *extfw; /* points to external firmware part, extfw_size bytes long */ + u8 *intfw; /* points to internal firmware part, intfw_size bytes long */ + struct usb_driver *calling_driver; /* the calling driver: at76c503-{rfmd,i3861,i3863,...} */ + unsigned int device_unplugged:1; + unsigned int netdev_registered:1; + char obuf[2*256+1]; /* global debug output buffer to reduce stack usage */ + char obuf_s[3*32]; /* small global debug output buffer to reduce stack usage */ + struct set_mib_buffer mib_buf; /* global buffer for set_mib calls */ + + /* new whiz-bang feature flags */ + int international_roaming; + int monitor_prism_header; /* if iw_mode == IW_MODE_MONITOR, + use Prism header */ + int monitor_scan_min_time; + int monitor_scan_max_time; + + int beacon_period; /* period of mgmt beacons */ + int beacons_received; + unsigned long beacons_last_qual; /* last time we reset beacons_received = 0 */ +}; + +/* Quasi-monitor mode defs (copied from /drivers/net/wireless/orinoco.h) */ + +/* message data item for INT, BOUNDEDINT, ENUMINT */ +typedef struct p80211item_uint32 +{ + uint32_t did __attribute__ ((packed)); + uint16_t status __attribute__ ((packed)); + uint16_t len __attribute__ ((packed)); + uint32_t data __attribute__ ((packed)); +} __attribute__ ((packed)) p80211item_uint32_t; + +typedef struct p80211msg +{ + uint32_t msgcode __attribute__ ((packed)); + uint32_t msglen __attribute__ ((packed)); + uint8_t devname[IFNAMSIZ]; +} __attribute__ ((packed)) p80211msg_t; + +#define P80211ENUM_msgitem_status_data_ok 0 +#define P80211ENUM_msgitem_status_no_value 1 +#define P80211ENUM_truth_false 0 +#define P80211ENUM_truth_true 1 + +#define DIDmsg_lnxind_wlansniffrm 0x0041 +#define DIDmsg_lnxind_wlansniffrm_hosttime 0x1041 +#define DIDmsg_lnxind_wlansniffrm_mactime 0x2041 +#define DIDmsg_lnxind_wlansniffrm_channel 0x3041 +#define DIDmsg_lnxind_wlansniffrm_rssi 0x4041 +#define DIDmsg_lnxind_wlansniffrm_sq 0x5041 +#define DIDmsg_lnxind_wlansniffrm_signal 0x6041 +#define DIDmsg_lnxind_wlansniffrm_noise 0x7041 +#define DIDmsg_lnxind_wlansniffrm_rate 0x8041 +#define DIDmsg_lnxind_wlansniffrm_istx 0x9041 +#define DIDmsg_lnxind_wlansniffrm_frmlen 0xA041 + +typedef struct p80211msg_lnxind_wlansniffrm +{ + uint32_t msgcode; + uint32_t msglen; + uint8_t devname[IFNAMSIZ]; + p80211item_uint32_t hosttime; + p80211item_uint32_t mactime; + p80211item_uint32_t channel; + p80211item_uint32_t rssi; + p80211item_uint32_t sq; + p80211item_uint32_t signal; + p80211item_uint32_t noise; + p80211item_uint32_t rate; + p80211item_uint32_t istx; + p80211item_uint32_t frmlen; +} __attribute__ ((packed)) p80211msg_lnxind_wlansniffrm_t; + +/* at76_debug bits */ +#define DBG_PROGRESS 0x00000001 /* progress of scan-join-(auth-assoc)-connected */ +#define DBG_BSS_TABLE 0x00000002 /* show the bss table after scans */ +#define DBG_IOCTL 0x00000004 /* ioctl calls / settings */ +#define DBG_KEVENT 0x00000008 /* kevents */ +#define DBG_TX_DATA 0x00000010 /* tx header */ +#define DBG_TX_DATA_CONTENT 0x00000020 /* tx content */ +#define DBG_TX_MGMT 0x00000040 +#define DBG_RX_DATA 0x00000080 /* rx data header */ +#define DBG_RX_DATA_CONTENT 0x00000100 /* rx data content */ +#define DBG_RX_MGMT 0x00000200 /* rx mgmt header except beacon and probe responses */ +#define DBG_RX_BEACON 0x00000400 /* rx beacon */ +#define DBG_RX_CTRL 0x00000800 /* rx control */ +#define DBG_RX_MGMT_CONTENT 0x00001000 /* rx mgmt content */ +#define DBG_RX_FRAGS 0x00002000 /* rx data fragment handling */ +#define DBG_DEVSTART 0x00004000 /* fw download, device start */ +#define DBG_URB 0x00008000 /* rx urb status, ... */ +#define DBG_RX_ATMEL_HDR 0x00010000 /* the Atmel specific header of each rx packet */ +#define DBG_PROC_ENTRY 0x00020000 /* procedure entries and exits */ +#define DBG_PM 0x00040000 /* power management settings */ +#define DBG_BSS_MATCH 0x00080000 /* show why a certain bss did not match */ +#define DBG_PARAMS 0x00100000 /* show the configured parameters */ +#define DBG_WAIT_COMPLETE 0x00200000 /* show the wait_completion progress */ +#define DBG_RX_FRAGS_SKB 0x00400000 /* show skb header for incoming rx fragments */ +#define DBG_BSS_TABLE_RM 0x00800000 /* inform on removal of old bss table entries */ +#define DBG_MONITOR_MODE 0x01000000 /* debugs from monitor mode */ +#define DBG_MIB 0x02000000 /* dump all MIBs in startup_device */ +#define DBG_MGMT_TIMER 0x04000000 /* dump mgmt_timer ops */ +#define DBG_WE_EVENTS 0x08000000 /* dump wireless events */ +#define DBG_FW 0x10000000 /* firmware download */ +#define DBG_DFU 0x20000000 /* device firmware upgrade */ + +#define DBG_DEFAULTS 0 +extern int at76_debug; + +/* Use our own dbg macro */ +#undef dbg +#define dbg(bits, format, arg...) \ + do { \ + if (at76_debug & (bits)) \ + printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg);\ + } while (0) + +int usbdfu_download(struct usb_device *udev, u8 *fw_buf, u32 fw_len, + int manifest_sync_timeout); + +#endif /* _AT76C503_H */ --- linux-2.6.27.orig/ubuntu/misc/wireless/at76/at76_usbdfu.c +++ linux-2.6.27/ubuntu/misc/wireless/at76/at76_usbdfu.c @@ -0,0 +1,315 @@ +/* -*- linux-c -*- */ +/* + * USB Device Firmware Upgrade (DFU) handler + * + * Copyright (c) 2003 Oliver Kurth + * Copyright (c) 2004 Jörg Albert + * + * This file is part of the driver for WLAN USB devices based on the Atmel + * AT76C503A/505/505A. See at76c503.h for details. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 2003_01_19 0.1: + * - initial release + * + * TODO: + * (someday) + * - make a way for drivers to feed firmware data at download time (instead of + * providing it all at once during register) + * - procfs support for userland firmware downloaders + * - Firmware upload (device-to-host) support + */ + +#include +#include +#include "at76c503.h" + +/* DFU states */ + +#define STATE_IDLE 0x00 +#define STATE_DETACH 0x01 +#define STATE_DFU_IDLE 0x02 +#define STATE_DFU_DOWNLOAD_SYNC 0x03 +#define STATE_DFU_DOWNLOAD_BUSY 0x04 +#define STATE_DFU_DOWNLOAD_IDLE 0x05 +#define STATE_DFU_MANIFEST_SYNC 0x06 +#define STATE_DFU_MANIFEST 0x07 +#define STATE_DFU_MANIFEST_WAIT_RESET 0x08 +#define STATE_DFU_UPLOAD_IDLE 0x09 +#define STATE_DFU_ERROR 0x0a + +/* DFU commands */ +#define DFU_DETACH 0 +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +struct dfu_status { + unsigned char bStatus; + unsigned char bwPollTimeout[3]; + unsigned char bState; + unsigned char iString; +} __attribute__ ((packed)); + + +/* driver independent download context */ +struct dfu_ctx { + struct usb_device *udev; + u8 dfu_state; + struct dfu_status dfu_status; + u8 *buf; +}; + +#define USB_SUCCESS(a) ((a) >= 0) + +#define DFU_PACKETSIZE 1024 + +static +int dfu_download_block(struct dfu_ctx *ctx, u8 *buffer, + int bytes, int block) +{ + int result; + u8 *tmpbuf = ctx->buf; + struct usb_device *udev = ctx->udev; + + dbg(DBG_DFU, "dfu_download_block(): buffer=%p, bytes=%d, block=%d", buffer, bytes, block); + + if(tmpbuf == NULL) + return -ENOMEM; + + memcpy(tmpbuf, buffer, bytes); + + result = usb_control_msg(udev, usb_sndctrlpipe(udev,0), + DFU_DNLOAD, + USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, + block, /* Value */ + 0, /* Index */ + tmpbuf, /* Buffer */ + bytes, /* Size */ + HZ); + return result; +} + +static +int dfu_get_status(struct dfu_ctx *ctx, struct dfu_status *status) +{ + int result; + struct usb_device *udev = ctx->udev; + +// dbg(DBG_DFU, "dfu_get_status()"); + + result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + DFU_GETSTATUS, + USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE, + 0, /* Value */ + 0, /* Index */ + status, /* Buffer */ + sizeof(struct dfu_status), /* Size */ + HZ); + + return result; +} + +static +u8 dfu_get_state(struct usb_device *udev, u8 *state) +{ + int result; + +// dbg(DBG_DFU, "dfu_get_state()"); + + result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + DFU_GETSTATE, /* Request */ + USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE, + 0, /* Value */ + 0, /* Index */ + state, /* Buffer */ + 1, /* Size */ + HZ); + + return result; +} + +static inline +u32 __get_timeout(struct dfu_status *s) +{ + unsigned long ret = 0; + + ret = (unsigned long) (s->bwPollTimeout[2] << 16); + ret |= (unsigned long) (s->bwPollTimeout[1] << 8); + ret |= (unsigned long) (s->bwPollTimeout[0]); + + return ret; +} + +static +struct dfu_ctx *dfu_alloc_ctx(struct usb_device *udev) +{ + struct dfu_ctx *ctx; + + ctx = kmalloc(sizeof(struct dfu_ctx) + DFU_PACKETSIZE, GFP_KERNEL|GFP_DMA); + if(ctx){ + ctx->udev = udev; + ctx->buf = (u8 *)&(ctx[1]); + } + return ctx; +} + +/* == PROC usbdfu_download == + if manifest_sync_timeout > 0 use this timeout (in msec) instead of the + one reported by the device in state MANIFEST_SYNC */ +int usbdfu_download(struct usb_device *udev, u8 *dfu_buffer, u32 dfu_len, + int manifest_sync_timeout) +{ + struct dfu_ctx *ctx; + struct dfu_status *dfu_stat_buf; + int status = 0; + int need_dfu_state = 1; + int is_done = 0; + u8 dfu_state = 0; + u32 dfu_timeout = 0; + int dfu_block_bytes = 0, dfu_bytes_left = dfu_len, dfu_buffer_offset = 0; + int dfu_block_cnt = 0; + + dbg(DBG_DFU, "%s( %p, %u, %d)", __FUNCTION__, dfu_buffer, + dfu_len, manifest_sync_timeout); + + if (dfu_len == 0) { + err("FW Buffer length invalid!"); + return -EINVAL; + } + + ctx = dfu_alloc_ctx(udev); + if(ctx == NULL) + return -ENOMEM; + + dfu_stat_buf = &ctx->dfu_status; + + do { + if (need_dfu_state) { + status = dfu_get_state(ctx->udev, &ctx->dfu_state); + if (!USB_SUCCESS(status)) { + err("DFU: Failed to get DFU state: %d", status); + goto exit; + } + dfu_state = ctx->dfu_state; + need_dfu_state = 0; + } + + switch (dfu_state) { + case STATE_DFU_DOWNLOAD_SYNC: + dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_SYNC"); + status = dfu_get_status(ctx, dfu_stat_buf); + if (USB_SUCCESS(status)) { + dfu_state = dfu_stat_buf->bState; + dfu_timeout = __get_timeout(dfu_stat_buf); + need_dfu_state = 0; + } else + err("dfu_get_status failed with %d", status); + break; + + case STATE_DFU_DOWNLOAD_BUSY: + dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_BUSY"); + need_dfu_state = 1; + + if (dfu_timeout >= 0){ + dbg(DBG_DFU, "DFU: Resetting device"); + set_current_state( TASK_INTERRUPTIBLE ); + schedule_timeout(1+dfu_timeout*HZ/1000); + }else + dbg(DBG_DFU, "DFU: In progress"); + + break; + + case STATE_DFU_DOWNLOAD_IDLE: + dbg(DBG_DFU, "DOWNLOAD..."); + /* fall through */ + case STATE_DFU_IDLE: + dbg(DBG_DFU, "DFU IDLE"); + + if (dfu_bytes_left <= DFU_PACKETSIZE) + dfu_block_bytes = dfu_bytes_left; + else + dfu_block_bytes = DFU_PACKETSIZE; + + dfu_bytes_left -= dfu_block_bytes; + status = dfu_download_block(ctx, + dfu_buffer + + dfu_buffer_offset, + dfu_block_bytes, + dfu_block_cnt); + dfu_buffer_offset += dfu_block_bytes; + dfu_block_cnt++; + + if (!USB_SUCCESS(status)) + err("dfu_download_block failed with %d", status); + need_dfu_state = 1; + break; + + case STATE_DFU_MANIFEST_SYNC: + dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC"); + + status = dfu_get_status(ctx, dfu_stat_buf); + + if (USB_SUCCESS(status)) { + dfu_state = dfu_stat_buf->bState; + dfu_timeout = __get_timeout(dfu_stat_buf); + need_dfu_state = 0; + + /* override the timeout from the status response, + needed for AT76C505A */ + if (manifest_sync_timeout > 0) + dfu_timeout = manifest_sync_timeout; + + if (dfu_timeout >= 0){ + dbg(DBG_DFU, "DFU: Waiting for manifest phase"); + + set_current_state( TASK_INTERRUPTIBLE ); + schedule_timeout((dfu_timeout*HZ+999)/1000); + }else + dbg(DBG_DFU, "DFU: In progress"); + } + break; + + case STATE_DFU_MANIFEST: + dbg(DBG_DFU, "STATE_DFU_MANIFEST"); + is_done = 1; + break; + + case STATE_DFU_MANIFEST_WAIT_RESET: + dbg(DBG_DFU, "STATE_DFU_MANIFEST_WAIT_RESET"); +// usb_reset_device(udev); + is_done = 1; + break; + + case STATE_DFU_UPLOAD_IDLE: + dbg(DBG_DFU, "STATE_DFU_UPLOAD_IDLE"); + break; + + case STATE_DFU_ERROR: + dbg(DBG_DFU, "STATE_DFU_ERROR"); +// usb_reset_device(udev); + status = -EPIPE; + break; + + default: + dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", dfu_state); + status = -EINVAL; + break; + } + } while (!is_done && USB_SUCCESS(status)); + + exit: + kfree(ctx); + if (status < 0) + return status; + else + return 0; +} + --- linux-2.6.27.orig/ubuntu/misc/wireless/at76/Makefile +++ linux-2.6.27/ubuntu/misc/wireless/at76/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_WIRELESS_AT76) += at76_usb.o + +at76_usb-objs := at76c503.o at76_usbdfu.o --- linux-2.6.27.orig/ubuntu/misc/wireless/at76/at76c503.c +++ linux-2.6.27/ubuntu/misc/wireless/at76/at76c503.c @@ -0,0 +1,7138 @@ +/* -*- linux-c -*- */ +/* + * USB at76c503/at76c505 driver + * + * Copyright (c) 2002 - 2003 Oliver Kurth + * Copyright (c) 2004 Joerg Albert + * Copyright (c) 2004 Nick Jones + * Copyright (c) 2004 Balint Seeber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This file is part of the Berlios driver for WLAN USB devices based on the + * Atmel AT76C503A/505/505A. See at76c503.h for details. + * + * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for rtnl_lock() */ +#include + +#ifdef CONFIG_IPAQ_HANDHELD +#include +#include +#include +#include +#endif + +#include "at76c503.h" + +#if WIRELESS_EXT < 17 +#define IW_QUAL_QUAL_UPDATED 0x01 +#define IW_QUAL_LEVEL_UPDATED 0x02 +#define IW_QUAL_NOISE_UPDATED 0x04 +#define IW_QUAL_QUAL_INVALID 0x10 +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#endif + +#if WIRELESS_EXT < 19 +#define IW_QUAL_ALL_UPDATED 0x07 +#define IW_QUAL_DBM 0x08 +#define IW_QUAL_ALL_INVALID 0x70 +#endif + +/* timeout in seconds for the usb_control_msg in get_cmd_status + * and set_card_command + */ +#ifndef USB_CTRL_GET_TIMEOUT +# define USB_CTRL_GET_TIMEOUT 5 +#endif + +/* number of endpoints of an interface */ +#define NUM_EP(intf) (intf)->altsetting[0].desc.bNumEndpoints +#define EP(intf,nr) (intf)->altsetting[0].endpoint[(nr)].desc +#define GET_DEV(udev) usb_get_dev((udev)) +#define PUT_DEV(udev) usb_put_dev((udev)) +#define SET_NETDEV_OWNER(ndev,owner) /* not needed anymore ??? */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) +#define gfp_t int +#endif + +/* Backwards compatibility for usb_kill_urb() */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) +# define usb_kill_urb usb_unlink_urb +#endif + +/* wireless extension level this source currently supports */ +#define WIRELESS_EXT_SUPPORTED 16 + +#ifndef USB_ASYNC_UNLINK +#ifdef URB_ASYNC_UNLINK +#define USB_ASYNC_UNLINK URB_ASYNC_UNLINK +#else +#define USB_ASYNC_UNLINK 0 +#endif +#endif + +#ifndef FILL_BULK_URB +#define FILL_BULK_URB(a,b,c,d,e,f,g) usb_fill_bulk_urb(a,b,c,d,e,f,g) +#endif + +int at76_debug = DBG_DEFAULTS; + +/* uncond. debug output */ +#define dbg_uc(format, arg...) \ + printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg) + +#ifndef min +#define min(x,y) ((x) < (y) ? (x) : (y)) +#endif + +#define assert(x) \ + do {\ + if (!(x)) \ + err("%d: assertion " #x " failed", __LINE__);\ + } while (0) + +/* how often do we re-try these packets ? */ +#define AUTH_RETRIES 3 +#define ASSOC_RETRIES 3 +#define DISASSOC_RETRIES 3 + + + +static unsigned long spin_l_istate_flags; +#define LOCK_ISTATE() spin_lock_irqsave(&dev->istate_spinlock,spin_l_istate_flags); +#define UNLOCK_ISTATE() spin_unlock_irqrestore(&dev->istate_spinlock,spin_l_istate_flags); + + +#define NEW_STATE(dev,newstate) \ + do {\ + scan_hook(newstate == SCANNING); \ + LOCK_ISTATE() \ + dbg(DBG_PROGRESS, "%s: state %d -> %d (" #newstate ")",\ + dev->netdev->name, dev->istate, newstate);\ + dev->istate = newstate;\ + UNLOCK_ISTATE() \ + } while (0) + +/* the beacon timeout in infra mode when we are connected (in seconds) */ +#define BEACON_TIMEOUT 10 + +/* the interval in ticks we poll if scan is completed */ +#define SCAN_POLL_INTERVAL (HZ/4) + + +/* Version Information */ +#define DRIVER_NAME "at76_usb" +#define DRIVER_AUTHOR \ +"Oliver Kurth , Joerg Albert , " \ +"Alex , Nick Jones, Balint Seeber " +#define DRIVER_DESC "Atmel at76c50x USB Wireless LAN Driver" + + +/* Module paramaters */ +module_param_named(debug, at76_debug, int, 0600); +MODULE_PARM_DESC(debug, "Debugging level"); + +static int rx_copybreak = 200; +module_param(rx_copybreak, int, 0400); +MODULE_PARM_DESC(rx_copybreak, "rx packet copy threshold"); + +static int scan_min_time = 10; +module_param(scan_min_time, int, 0400); +MODULE_PARM_DESC(scan_min_time, "scan min channel time (default: 10)"); + +static int scan_max_time = 120; +module_param(scan_max_time, int, 0400); +MODULE_PARM_DESC(scan_max_time, "scan max channel time (default: 120)"); + +static int scan_mode = SCAN_TYPE_ACTIVE; +module_param(scan_mode, int, 0400); +MODULE_PARM_DESC(scan_mode, "scan mode: 0 active (with ProbeReq, default), 1 passive"); + +static int preamble_type = PREAMBLE_TYPE_LONG; +module_param(preamble_type, int, 0400); +MODULE_PARM_DESC(preamble_type, "preamble type: 0 long (default), 1 short"); + +static int auth_mode = 0; +module_param(auth_mode, int, 0400); +MODULE_PARM_DESC(auth_mode, "authentication mode: 0 open system (default), " + "1 shared secret"); + +static int pm_mode = PM_ACTIVE; +module_param(pm_mode, int, 0400); +MODULE_PARM_DESC(pm_mode, "power management mode: 1 active (def.), 2 powersave, 3 smart save"); + +static int pm_period = 0; +module_param(pm_period, int, 0400); +MODULE_PARM_DESC(pm_period, "period of waking up the device in usec"); + +static int international_roaming = IR_OFF; +module_param(international_roaming, int, 0400); +MODULE_PARM_DESC(international_roaming, "enable international roaming: 0 (no, default), 1 (yes)"); + +static int default_iw_mode = IW_MODE_INFRA; +module_param(default_iw_mode, int, 0400); +MODULE_PARM_DESC(default_iw_mode, "default IW mode for a new device: " + "1 (ad-hoc), 2 (infrastructure, def.), 6 (monitor mode)"); + +static int monitor_scan_min_time = 50; +module_param(monitor_scan_min_time, int, 0400); +MODULE_PARM_DESC(monitor_scan_min_time, "scan min channel time in MONITOR MODE (default: 50)"); + +static int monitor_scan_max_time = 600; +module_param(monitor_scan_max_time, int, 0400); +MODULE_PARM_DESC(monitor_scan_max_time, "scan max channel time in MONITOR MODE (default: 600)"); + +static char* netdev_name = "wlan%d"; +module_param(netdev_name, charp, 0400); +MODULE_PARM_DESC(netdev_name, "network device name (default is wlan%d)"); + + +#define DEF_RTS_THRESHOLD 1536 +#define DEF_FRAG_THRESHOLD 1536 +#define DEF_SHORT_RETRY_LIMIT 8 +//#define DEF_LONG_RETRY_LIMIT 4 +#define DEF_CHANNEL 10 + +#define MAX_RTS_THRESHOLD (MAX_FRAG_THRESHOLD + 1) + +/* The frequency of each channel in MHz */ +static const long channel_frequency[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; +#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) ) + +/* the broadcast address */ +static const u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; +static const u8 off_addr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* the supported rates of this hardware, bit7 marks a basic rate */ +static const u8 hw_rates[4] = {0x82,0x84,0x0b,0x16}; + +/* the max padding size for tx in bytes (see calc_padding)*/ +#define MAX_PADDING_SIZE 53 + +/* the size of the ieee802.11 header (excl. the at76c503 tx header) */ +#define IEEE802_11_MGMT_HEADER_SIZE offsetof(struct ieee80211_hdr_3addr, payload) + +#define BEACON_MAX_DATA_LENGTH 1500 +/* beacon in ieee80211_hdr_3addr.payload */ +struct ieee802_11_beacon_data { + u8 timestamp[8]; // TSFTIMER + __le16 beacon_interval; // Kms between TBTTs (Target Beacon Transmission Times) + __le16 capability_information; + u8 data[BEACON_MAX_DATA_LENGTH]; /* contains: SSID (tag,length,value), + Supported Rates (tlv), channel */ +} __attribute__ ((packed)); + +/* disassoc frame in ieee80211_hdr_3addr.payload */ +struct ieee802_11_disassoc_frame { + __le16 reason; +} __attribute__ ((packed)); +#define DISASSOC_FRAME_SIZE \ + (AT76C503_TX_HDRLEN + IEEE802_11_MGMT_HEADER_SIZE +\ + sizeof(struct ieee802_11_disassoc_frame)) + +/* assoc request in ieee80211_hdr_3addr.payload */ +struct ieee802_11_assoc_req { + __le16 capability; + __le16 listen_interval; + u8 data[1]; /* variable number of bytes for SSID + and supported rates (tlv coded) */ +}; +/* the maximum size of an AssocReq packet */ +#define ASSOCREQ_MAX_SIZE \ + (AT76C503_TX_HDRLEN + IEEE802_11_MGMT_HEADER_SIZE +\ + offsetof(struct ieee802_11_assoc_req,data) +\ + 1+1+IW_ESSID_MAX_SIZE + 1+1+4) + +/* reassoc request in ieee80211_hdr_3addr.payload */ +struct ieee802_11_reassoc_req { + __le16 capability; + __le16 listen_interval; + u8 curr_ap[ETH_ALEN]; /* the bssid of the AP we are + currently associated to */ + u8 data[1]; /* variable number of bytes for SSID + and supported rates (tlv coded) */ +} __attribute__ ((packed)); + +/* the maximum size of an AssocReq packet */ +#define REASSOCREQ_MAX_SIZE \ + (AT76C503_TX_HDRLEN + IEEE802_11_MGMT_HEADER_SIZE +\ + offsetof(struct ieee802_11_reassoc_req,data) +\ + 1+1+IW_ESSID_MAX_SIZE + 1+1+4) + + +/* assoc/reassoc response */ +struct ieee802_11_assoc_resp { + __le16 capability; + __le16 status; + __le16 assoc_id; + u8 data[1]; /* variable number of bytes for + supported rates (tlv coded) */ +} __attribute__ ((packed)); + +/* auth. request/response in ieee80211_hdr_3addr.payload */ +struct ieee802_11_auth_frame { + __le16 algorithm; + __le16 seq_nr; + __le16 status; + u8 challenge[0]; +} __attribute__ ((packed)); +/* for shared secret auth, add the challenge text size */ +#define AUTH_FRAME_SIZE \ + (AT76C503_TX_HDRLEN + IEEE802_11_MGMT_HEADER_SIZE +\ + sizeof(struct ieee802_11_auth_frame)) + +/* deauth frame in ieee80211_hdr_3addr.payload */ +struct ieee802_11_deauth_frame { + __le16 reason; +} __attribute__ ((packed)); +#define DEAUTH_FRAME_SIZE \ + (AT76C503_TX_HDRLEN + IEEE802_11_MGMT_HEADER_SIZE +\ + sizeof(struct ieee802_11_disauth_frame)) + + +#define KEVENT_CTRL_HALT 1 +#define KEVENT_NEW_BSS 2 +#define KEVENT_SET_PROMISC 3 +#define KEVENT_MGMT_TIMEOUT 4 +#define KEVENT_SCAN 5 +#define KEVENT_JOIN 6 +#define KEVENT_STARTIBSS 7 +#define KEVENT_SUBMIT_RX 8 +#define KEVENT_RESTART 9 /* restart the device */ +#define KEVENT_ASSOC_DONE 10 /* execute the power save settings: + listen interval, pm mode, assoc id */ +#define KEVENT_EXTERNAL_FW 11 +#define KEVENT_INTERNAL_FW 12 +#define KEVENT_RESET_DEVICE 13 + + +static u8 snapsig[] = {0xaa, 0xaa, 0x03}; +//#ifdef COLLAPSE_RFC1042 +/* RFC 1042 encapsulates Ethernet frames in 802.2 SNAP (0xaa, 0xaa, 0x03) with + * a SNAP OID of 0 (0x00, 0x00, 0x00) */ +static u8 rfc1042sig[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +//#endif /* COLLAPSE_RFC1042 */ + +/* local function prototypes */ +static void iwspy_update(struct at76c503 *dev, struct at76c503_rx_buffer *buf); + +static void at76c503_read_bulk_callback (struct urb *urb); +static void at76c503_write_bulk_callback(struct urb *urb); +static void defer_kevent (struct at76c503 *dev, int flag); +static struct bss_info *find_matching_bss(struct at76c503 *dev, + struct bss_info *curr); +static int auth_req(struct at76c503 *dev, struct bss_info *bss, int seq_nr, + u8 *challenge); +static int disassoc_req(struct at76c503 *dev, struct bss_info *bss); +static int assoc_req(struct at76c503 *dev, struct bss_info *bss); +static int reassoc_req(struct at76c503 *dev, struct bss_info *curr, + struct bss_info *new); +static void dump_bss_table(struct at76c503 *dev, int force_output); +static int submit_rx_urb(struct at76c503 *dev); +static int startup_device(struct at76c503 *dev); + +static int set_iroaming(struct at76c503 *dev, int onoff); +static void set_monitor_mode(struct at76c503 *dev, int use_prism); + +/* second step of initialization (after fw download) */ +static int init_new_device(struct at76c503 *dev); + +/* some abbrev. for wireless events */ +static inline void iwevent_scan_complete(struct net_device *dev) +{ + union iwreq_data wrqu; + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); + dbg(DBG_WE_EVENTS, "%s: SIOCGIWSCAN sent", dev->name); +} +static inline void iwevent_bss_connect(struct net_device *dev, u8 *bssid) +{ + union iwreq_data wrqu; + wrqu.data.length = 0; + wrqu.data.flags = 0; + memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", dev->name, __FUNCTION__); +} + +static inline void iwevent_bss_disconnect(struct net_device *dev) +{ + union iwreq_data wrqu; + wrqu.data.length = 0; + wrqu.data.flags = 0; + memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", dev->name, __FUNCTION__); +} + + +/* hexdump len many bytes from buf into obuf, separated by delim, + add a trailing \0 into obuf */ +static char *hex2str(char *obuf, u8 *buf, int len, char delim) +{ +#define BIN2HEX(x) ((x) < 10 ? '0'+(x) : (x)+'A'-10) + + char *ret = obuf; + while (len--) { + *obuf++ = BIN2HEX(*buf>>4); + *obuf++ = BIN2HEX(*buf&0xf); + if (delim != '\0') + *obuf++ = delim; + buf++; + } + if (delim != '\0' && obuf > ret) + obuf--; // remove last inserted delimiter + *obuf = '\0'; + + return ret; +} + +/* == PROC is_cloaked_ssid == + returns != 0, if the given SSID is a cloaked one: + - length 0 + - length > 0, all bytes are \0 + - length == 1, SSID ' ' +*/ +static inline int is_cloaked_ssid(u8 *ssid, int length) +{ + static const u8 zeros[32]; + + return (length == 0) || + (length == 1 && *ssid == ' ') || + (length > 0 && !memcmp(ssid,zeros,length)); +} + +static inline void free_bss_list(struct at76c503 *dev) +{ + struct list_head *next, *ptr; + unsigned long flags; + + spin_lock_irqsave(&dev->bss_list_spinlock, flags); + + dev->curr_bss = dev->new_bss = NULL; + + list_for_each_safe(ptr, next, &dev->bss_list) { + list_del(ptr); + kfree(list_entry(ptr, struct bss_info, list)); + } + + spin_unlock_irqrestore(&dev->bss_list_spinlock, flags); +} + +static inline char *mac2str(u8 *mac) +{ + static char str [6*3]; + + sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return str; +} + +static void scan_hook(int blink) +{ +#ifdef CONFIG_IPAQ_HANDHELD + if (machine_is_h5400()) { + if (blink) + ipaq_led_blink (RED_LED, 1, 2); + else + ipaq_led_off (RED_LED); + } +#endif +} + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) + +/* == PROC analyze_usb_config == + This procedure analyzes the configuration after the + USB device got reset and find the start of the interface and the + two endpoint descriptors. + Returns < 0 if the descriptors seems to be wrong. */ +static int analyze_usb_config(u8 *cfgd, int cfgd_len, + int *intf_idx, int *ep0_idx, int *ep1_idx) +{ + u8 *cfgd_start = cfgd; + u8 *cfgd_end = cfgd + cfgd_len; /* first byte after config descriptor */ + int nr_intf=0, nr_ep=0; /* number of interface, number of endpoint descr. + found */ + + assert(cfgd_len >= 2); + if (cfgd_len < 2) + return -1; + + if (*(cfgd+1) != USB_DT_CONFIG) { + err("not a config descriptor"); + return -2; + } + + if (*cfgd != USB_DT_CONFIG_SIZE) { + err("invalid length for config descriptor: %d", *cfgd); + return -3; + } + + /* scan the config descr */ + while ((cfgd+1) < cfgd_end) { + + switch (*(cfgd+1)) { + + case USB_DT_INTERFACE: + nr_intf++; + if (nr_intf == 1) + *intf_idx = cfgd - cfgd_start; + break; + + case USB_DT_ENDPOINT: + nr_ep++; + if (nr_ep == 1) + *ep0_idx = cfgd - cfgd_start; + else + if (nr_ep == 2) + *ep1_idx = cfgd - cfgd_start; + break; + default: + ; + } + cfgd += *cfgd; + } /* while ((cfgd+1) < cfgd_end) */ + + if (nr_ep != 2 || nr_intf != 1) { + err("unexpected nr of intf (%d) or endpoints (%d)", + nr_intf, nr_ep); + return -4; + } + + return 0; +} /* end of analyze_usb_config */ + + + +/* == PROC update_usb_intf_descr == + currently (2.6.0-test2) usb_reset_device() does not recognize that + the interface descr. are changed. + This procedure reads the configuration and does a limited parsing of + the interface and endpoint descriptors. + This is IMHO needed until usb_reset_device() is changed inside the + kernel's USB subsystem. + Copied from usb/core/config.c:usb_get_configuration() + + THIS IS VERY UGLY CODE - DO NOT COPY IT ! */ + +#define AT76C503A_USB_CONFDESCR_LEN 0x20 +/* the short configuration descriptor before reset */ +//#define AT76C503A_USB_SHORT_CONFDESCR_LEN 0x19 + +static int update_usb_intf_descr(struct at76c503 *dev) +{ + int intf0; /* begin of intf descriptor in configuration */ + int ep0, ep1; /* begin of endpoint descriptors */ + + struct usb_device *udev = dev->udev; + struct usb_config_descriptor *cfg_desc; + int result = 0, size; + u8 *buffer; + struct usb_host_interface *ifp; + int i; + + dbg(DBG_DEVSTART, "%s: ENTER", __FUNCTION__); + + cfg_desc = (struct usb_config_descriptor *) + kmalloc(AT76C503A_USB_CONFDESCR_LEN, GFP_KERNEL); + if (!cfg_desc) { + err("cannot kmalloc config desc"); + return -ENOMEM; + } + + result = usb_get_descriptor(udev, USB_DT_CONFIG, 0, + cfg_desc, AT76C503A_USB_CONFDESCR_LEN); + if (result < AT76C503A_USB_CONFDESCR_LEN) { + if (result < 0) + err("unable to get descriptor"); + else { + err("config descriptor too short (expected >= %i, got %i)", + AT76C503A_USB_CONFDESCR_LEN, result); + result = -EINVAL; + } + goto err; + } + + /* now check the config descriptor */ + le16_to_cpus(&cfg_desc->wTotalLength); + size = cfg_desc->wTotalLength; + buffer = (u8 *)cfg_desc; + + if (cfg_desc->bNumInterfaces > 1) { + err("found %d interfaces", cfg_desc->bNumInterfaces); + result = - EINVAL; + goto err; + } + + if ((result=analyze_usb_config(buffer, size, &intf0, &ep0, &ep1))) { + + err("analyze_usb_config returned %d for config desc %s", + result, + hex2str(dev->obuf, (u8 *)cfg_desc, + min((int)(sizeof(dev->obuf)-1)/2,size), '\0')); + result=-EINVAL; + goto err; + } + + /* we got the correct config descriptor - update the interface's endpoints */ + ifp = &udev->actconfig->interface[0]->altsetting[0]; + + if (ifp->endpoint) + kfree(ifp->endpoint); + + memcpy(&ifp->desc, buffer+intf0, USB_DT_INTERFACE_SIZE); + + if (!(ifp->endpoint = kmalloc(2 * sizeof(struct usb_host_endpoint), + GFP_KERNEL))) { + result = -ENOMEM; + goto err; + } + memset(ifp->endpoint, 0, 2 * sizeof(struct usb_host_endpoint)); + memcpy(&ifp->endpoint[0].desc, buffer+ep0, USB_DT_ENDPOINT_SIZE); + le16_to_cpus(&ifp->endpoint[0].desc.wMaxPacketSize); + memcpy(&ifp->endpoint[1].desc, buffer+ep1, USB_DT_ENDPOINT_SIZE); + le16_to_cpus(&ifp->endpoint[1].desc.wMaxPacketSize); + + /* we must set the max packet for the new ep (see usb_set_maxpacket() ) */ + +#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) + for(i=0; i < ifp->desc.bNumEndpoints; i++) { + struct usb_endpoint_descriptor *d = &ifp->endpoint[i].desc; + int b = d->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if (usb_endpoint_out(d->bEndpointAddress)) { + if (d->wMaxPacketSize > udev->epmaxpacketout[b]) + udev->epmaxpacketout[b] = d->wMaxPacketSize; + } else { + if (d->wMaxPacketSize > udev->epmaxpacketin[b]) + udev->epmaxpacketin[b] = d->wMaxPacketSize; + } + } + + dbg(DBG_DEVSTART, "%s: ifp %p num_altsetting %d " + "endpoint addr x%x, x%x", __FUNCTION__, + ifp, udev->actconfig->interface[0]->num_altsetting, + ifp->endpoint[0].desc.bEndpointAddress, + ifp->endpoint[1].desc.bEndpointAddress); + result = 0; +err: + kfree(cfg_desc); + dbg(DBG_DEVSTART, "%s: EXIT with %d", __FUNCTION__, result); + return result; +} /* update_usb_intf_descr */ + +#endif /* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) */ + + +static int at76c503_remap(struct usb_device *udev) +{ + int ret; + ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), + 0x0a, INTERFACE_VENDOR_REQUEST_OUT, + 0, 0, + NULL, 0, HZ * USB_CTRL_GET_TIMEOUT); + if (ret < 0) + return ret; + + return 0; +} + + +static int get_op_mode(struct usb_device *udev) +{ + int ret; + u8 op_mode; + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x33, INTERFACE_VENDOR_REQUEST_IN, + 0x01, 0, + &op_mode, 1, HZ * USB_CTRL_GET_TIMEOUT); + if(ret < 0) + return ret; + return op_mode; +} + +/* this loads a block of the second part of the firmware */ +static inline int load_ext_fw_block(struct usb_device *udev, + int i, unsigned char *buf, int bsize) +{ + return usb_control_msg(udev, usb_sndctrlpipe(udev,0), + 0x0e, DEVICE_VENDOR_REQUEST_OUT, + 0x0802, i, + buf, bsize, HZ * USB_CTRL_GET_TIMEOUT); +} + +static inline int get_hw_cfg_rfmd(struct usb_device *udev, + unsigned char *buf, int buf_size) +{ + return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + 0x33, INTERFACE_VENDOR_REQUEST_IN, + ((0x0a << 8) | 0x02), 0, + buf, buf_size, HZ * USB_CTRL_GET_TIMEOUT); +} + +/* Intersil boards use a different "value" for GetHWConfig requests */ +static inline +int get_hw_cfg_intersil(struct usb_device *udev, + unsigned char *buf, int buf_size) +{ + return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + 0x33, INTERFACE_VENDOR_REQUEST_IN, + ((0x09 << 8) | 0x02), 0, + buf, buf_size, HZ * USB_CTRL_GET_TIMEOUT); +} + +/* Get the hardware configuration for the adapter and place the appropriate + * data in the appropriate fields of 'dev' (the GetHWConfig request and + * interpretation of the result depends on the type of board we're dealing + * with) */ +static int get_hw_config(struct at76c503 *dev) +{ + int ret; + union { + struct hwcfg_intersil i; + struct hwcfg_rfmd r3; + struct hwcfg_r505 r5; + } *hwcfg = kmalloc(sizeof(*hwcfg), GFP_KERNEL); + + if (!hwcfg) + return -ENOMEM; + + switch (dev->board_type) { + + case BOARDTYPE_503_INTERSIL_3861: + case BOARDTYPE_503_INTERSIL_3863: + ret = get_hw_cfg_intersil(dev->udev, (unsigned char *)&hwcfg->i, sizeof(hwcfg->i)); + if (ret < 0) break; + memcpy(dev->mac_addr, hwcfg->i.mac_addr, ETH_ALEN); + memcpy(dev->cr31_values, hwcfg->i.cr31_values, 14); + memcpy(dev->cr58_values, hwcfg->i.cr58_values, 14); + memcpy(dev->pidvid, hwcfg->i.pidvid, 4); + dev->regulatory_domain = hwcfg->i.regulatory_domain; + break; + + case BOARDTYPE_503_RFMD: + case BOARDTYPE_503_RFMD_ACC: + ret = get_hw_cfg_rfmd(dev->udev, (unsigned char *)&hwcfg->r3, sizeof(hwcfg->r3)); + if (ret < 0) break; + memcpy(dev->cr20_values, hwcfg->r3.cr20_values, 14); + memcpy(dev->cr21_values, hwcfg->r3.cr21_values, 14); + memcpy(dev->bb_cr, hwcfg->r3.bb_cr, 14); + memcpy(dev->pidvid, hwcfg->r3.pidvid, 4); + memcpy(dev->mac_addr, hwcfg->r3.mac_addr, ETH_ALEN); + dev->regulatory_domain = hwcfg->r3.regulatory_domain; + memcpy(dev->low_power_values, hwcfg->r3.low_power_values, 14); + memcpy(dev->normal_power_values, hwcfg->r3.normal_power_values, 14); + break; + + case BOARDTYPE_505_RFMD: + case BOARDTYPE_505_RFMD_2958: + case BOARDTYPE_505A_RFMD_2958: + ret = get_hw_cfg_rfmd(dev->udev, (unsigned char *)&hwcfg->r5, sizeof(hwcfg->r5)); + if (ret < 0) break; + memcpy(dev->cr39_values, hwcfg->r5.cr39_values, 14); + memcpy(dev->bb_cr, hwcfg->r5.bb_cr, 14); + memcpy(dev->pidvid, hwcfg->r5.pidvid, 4); + memcpy(dev->mac_addr, hwcfg->r5.mac_addr, ETH_ALEN); + dev->regulatory_domain = hwcfg->r5.regulatory_domain; + memcpy(dev->cr15_values, hwcfg->r5.cr15_values, 14); + break; + + default: + err("Bad board type set (%d). Unable to get hardware config.", dev->board_type); + ret = -EINVAL; + } + + kfree(hwcfg); + + if (ret < 0) { + err("Get HW Config failed (%d)", ret); + } + return ret; +} + +/* == PROC getRegDomain == */ +static struct reg_domain const *getRegDomain(u16 code) +{ + static struct reg_domain const fd_tab[] = { + {0x10, "FCC (U.S)", 0x7ff}, /* ch 1-11 */ + {0x20, "IC (Canada)", 0x7ff}, /* ch 1-11 */ + {0x30, "ETSI (Europe - (Spain+France)", 0x1fff}, /* ch 1-13 */ + {0x31, "Spain", 0x600}, /* ch 10,11 */ + {0x32, "France", 0x1e00}, /* ch 10-13 */ + {0x40, "MKK (Japan)", 0x2000}, /* ch 14 */ + {0x41, "MKK1 (Japan)", 0x3fff}, /* ch 1-14 */ + {0x50, "Israel", 0x3fc}, /* ch 3-9 */ + }; + static int const tab_len = sizeof(fd_tab) / sizeof(struct reg_domain); + + /* use this if an unknown code comes in */ + static struct reg_domain const unknown = + {0, "", 0xffffffff}; + + int i; + + for(i=0; i < tab_len; i++) + if (code == fd_tab[i].code) + break; + + return (i >= tab_len) ? &unknown : &fd_tab[i]; +} /* getFreqDomain */ + +static inline int get_mib(struct usb_device *udev, + u16 mib, u8 *buf, int buf_size) +{ + return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + 0x33, INTERFACE_VENDOR_REQUEST_IN, + mib << 8, 0, + buf, buf_size, HZ * USB_CTRL_GET_TIMEOUT); +} + +static inline int get_cmd_status(struct usb_device *udev, + u8 cmd, u8 *cmd_status) +{ + return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + 0x22, INTERFACE_VENDOR_REQUEST_IN, + cmd, 0, + cmd_status, 40, HZ * USB_CTRL_GET_TIMEOUT); +} + +#define EXT_FW_BLOCK_SIZE 1024 +static int download_external_fw(struct usb_device *udev, u8 *buf, int size) +{ + int i = 0, ret = 0; + u8 *block; + + if (size < 0) return -EINVAL; + if ((size > 0) && (buf == NULL)) return -EFAULT; + + block = kmalloc(EXT_FW_BLOCK_SIZE, GFP_KERNEL); + if (block == NULL) return -ENOMEM; + + dbg(DBG_DEVSTART, "downloading external firmware"); + + while(size > 0){ + int bsize = size > EXT_FW_BLOCK_SIZE ? EXT_FW_BLOCK_SIZE : size; + + memcpy(block, buf, bsize); + dbg(DBG_DEVSTART, + "ext fw, size left = %5d, bsize = %4d, i = %2d", size, bsize, i); + if((ret = load_ext_fw_block(udev, i, block, bsize)) < 0){ + err("load_ext_fw_block failed: %d, i = %d", ret, i); + goto exit; + } + buf += bsize; + size -= bsize; + i++; + } + + /* for fw >= 0.100, the device needs + an extra empty block: */ + if((ret = load_ext_fw_block(udev, i, block, 0)) < 0){ + err("load_ext_fw_block failed: %d, i = %d", ret, i); + goto exit; + } + + exit: + kfree(block); + return ret; +} + +static int set_card_command(struct usb_device *udev, int cmd, + unsigned char *buf, int buf_size) +{ + int ret; + struct at76c503_command *cmd_buf = + (struct at76c503_command *)kmalloc( + sizeof(struct at76c503_command) + buf_size, + GFP_KERNEL); + + if(cmd_buf){ + cmd_buf->cmd = cmd; + cmd_buf->reserved = 0; + cmd_buf->size = cpu_to_le16(buf_size); + if(buf_size > 0) + memcpy(&(cmd_buf[1]), buf, buf_size); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), + 0x0e, DEVICE_VENDOR_REQUEST_OUT, + 0, 0, + cmd_buf, + sizeof(struct at76c503_command) + buf_size, + HZ * USB_CTRL_GET_TIMEOUT); + kfree(cmd_buf); + return ret; + } + + return -ENOMEM; +} + +#define MAKE_CMD_STATUS_CASE(c) case (c): return #c + +static const char* get_cmd_status_string(u8 cmd_status) +{ + switch (cmd_status) + { + MAKE_CMD_STATUS_CASE(CMD_STATUS_IDLE); + MAKE_CMD_STATUS_CASE(CMD_STATUS_COMPLETE); + MAKE_CMD_STATUS_CASE(CMD_STATUS_UNKNOWN); + MAKE_CMD_STATUS_CASE(CMD_STATUS_INVALID_PARAMETER); + MAKE_CMD_STATUS_CASE(CMD_STATUS_FUNCTION_NOT_SUPPORTED); + MAKE_CMD_STATUS_CASE(CMD_STATUS_TIME_OUT); + MAKE_CMD_STATUS_CASE(CMD_STATUS_IN_PROGRESS); + MAKE_CMD_STATUS_CASE(CMD_STATUS_HOST_FAILURE); + MAKE_CMD_STATUS_CASE(CMD_STATUS_SCAN_FAILED); + } + + return "UNKNOWN"; +} + +/* TODO: should timeout */ +static int wait_completion(struct at76c503 *dev, int cmd) +{ + u8 *cmd_status = kmalloc(40, GFP_KERNEL); + struct net_device *netdev = dev->netdev; + int ret = 0; + + do{ + ret = get_cmd_status(dev->udev, cmd, cmd_status); + if(ret < 0){ + err("%s: get_cmd_status failed: %d", netdev->name, ret); + break; + } + + dbg(DBG_WAIT_COMPLETE, "%s: Waiting on cmd %d, cmd_status[5] = %d (%s)", + dev->netdev->name, cmd, cmd_status[5], get_cmd_status_string(cmd_status[5])); + + if(cmd_status[5] == CMD_STATUS_IN_PROGRESS || + cmd_status[5] == CMD_STATUS_IDLE){ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); // 100 ms + }else break; + }while(1); + + if (ret >= 0) + /* if get_cmd_status did not fail, return the status + retrieved */ + ret = cmd_status[5]; + kfree(cmd_status); + return ret; +} + +static int set_mib(struct at76c503 *dev, struct set_mib_buffer *buf) +{ + struct usb_device *udev = dev->udev; + int ret; + struct at76c503_command *cmd_buf = + (struct at76c503_command *)kmalloc( + sizeof(struct at76c503_command) + buf->size + 4, + GFP_KERNEL); + + if(cmd_buf){ + cmd_buf->cmd = CMD_SET_MIB; + cmd_buf->reserved = 0; + cmd_buf->size = cpu_to_le16(buf->size + 4); + memcpy(&(cmd_buf[1]), buf, buf->size + 4); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), + 0x0e, DEVICE_VENDOR_REQUEST_OUT, + 0, 0, + cmd_buf, + sizeof(struct at76c503_command) + buf->size + 4, + HZ * USB_CTRL_GET_TIMEOUT); + if (ret >= 0) + if ((ret=wait_completion(dev, CMD_SET_MIB)) != + CMD_STATUS_COMPLETE) { + info("%s: set_mib: wait_completion failed with %d", + dev->netdev->name, ret); + ret = -156; /* ??? */ + } + kfree(cmd_buf); + return ret; + } + + return -ENOMEM; +} + +/* return < 0 on error, == 0 if no command sent, == 1 if cmd sent */ +static int set_radio(struct at76c503 *dev, int on_off) +{ + int ret; + + if(dev->radio_on != on_off){ + ret = set_card_command(dev->udev, CMD_RADIO, NULL, 0); + if(ret < 0){ + err("%s: set_card_command(CMD_RADIO) failed: %d", dev->netdev->name, ret); + } else + ret = 1; + dev->radio_on = on_off; + } else + ret = 0; + return ret; +} + + +/* == PROC set_pm_mode == + sets power save modi (PM_ACTIVE/PM_SAVE/PM_SMART_SAVE) */ +static int set_pm_mode(struct at76c503 *dev, u8 mode) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_MGMT; + dev->mib_buf.size = 1; + dev->mib_buf.index = POWER_MGMT_MODE_OFFSET; + + dev->mib_buf.data[0] = mode; + + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (pm_mode) failed: %d", dev->netdev->name, ret); + } + return ret; +} + +/* == PROC set_associd == + sets the assoc id for power save mode */ +static int set_associd(struct at76c503 *dev, u16 id) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_MGMT; + dev->mib_buf.size = 2; + dev->mib_buf.index = STATION_ID_OFFSET; + + dev->mib_buf.data[0] = id & 0xff; + dev->mib_buf.data[1] = id >> 8; + + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (associd) failed: %d", dev->netdev->name, ret); + } + return ret; +} + +/* == PROC set_listen_interval == + sets the listen interval for power save mode. + really needed, as we have a similar parameter in the assocreq ??? */ +static int set_listen_interval(struct at76c503 *dev, u16 interval) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC; + dev->mib_buf.size = 2; + dev->mib_buf.index = STATION_ID_OFFSET; + + dev->mib_buf.data[0] = interval & 0xff; + dev->mib_buf.data[1] = interval >> 8; + + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (listen_interval) failed: %d", + dev->netdev->name, ret); + } + return ret; +} + +static int set_preamble(struct at76c503 *dev, u8 type) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_LOCAL; + dev->mib_buf.size = 1; + dev->mib_buf.index = PREAMBLE_TYPE_OFFSET; + dev->mib_buf.data[0] = type; + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (preamble) failed: %d", dev->netdev->name, ret); + } + return ret; +} + +static int set_frag(struct at76c503 *dev, u16 size) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC; + dev->mib_buf.size = 2; + dev->mib_buf.index = FRAGMENTATION_OFFSET; + *(__le16*)dev->mib_buf.data = cpu_to_le16(size); + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (frag threshold) failed: %d", dev->netdev->name, ret); + } + return ret; +} + +static int set_rts(struct at76c503 *dev, u16 size) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC; + dev->mib_buf.size = 2; + dev->mib_buf.index = RTS_OFFSET; + *(__le16*)dev->mib_buf.data = cpu_to_le16(size); + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (rts) failed: %d", dev->netdev->name, ret); + } + return ret; +} + +static int set_autorate_fallback(struct at76c503 *dev, int onoff) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_LOCAL; + dev->mib_buf.size = 1; + dev->mib_buf.index = TX_AUTORATE_FALLBACK_OFFSET; + dev->mib_buf.data[0] = onoff; + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (autorate fallback) failed: %d", dev->netdev->name, ret); + } + return ret; +} + +static int set_mac_address(struct at76c503 *dev, void *addr) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_ADD; + dev->mib_buf.size = ETH_ALEN; + dev->mib_buf.index = offsetof(struct mib_mac_addr, mac_addr); + memcpy(dev->mib_buf.data, addr, ETH_ALEN); + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (MAC_ADDR, mac_addr) failed: %d", + dev->netdev->name, ret); + } + return ret; +} + +#if 0 +/* implemented to get promisc. mode working, but does not help. + May still be useful for multicast eventually. */ +static int set_group_address(struct at76c503 *dev, u8 *addr, int n) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_ADD; + dev->mib_buf.size = ETH_ALEN; + dev->mib_buf.index = offsetof(struct mib_mac_addr, group_addr) + n*ETH_ALEN; + memcpy(dev->mib_buf.data, addr, ETH_ALEN); + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (MIB_MAC_ADD, group_addr) failed: %d", + dev->netdev->name, ret); + } + +#if 1 + /* I do not know anything about the group_addr_status field... (oku) */ + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_ADD; + dev->mib_buf.size = 1; + dev->mib_buf.index = offsetof(struct mib_mac_addr, group_addr_status) + n; + dev->mib_buf.data[0] = 1; + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (MIB_MAC_ADD, group_addr_status) failed: %d", + dev->netdev->name, ret); + } +#endif + return ret; +} +#endif + +static int set_promisc(struct at76c503 *dev, int onoff) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_LOCAL; + dev->mib_buf.size = 1; + dev->mib_buf.index = offsetof(struct mib_local, promiscuous_mode); + dev->mib_buf.data[0] = onoff ? 1 : 0; + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (promiscuous_mode) failed: %d", dev->netdev->name, ret); + } + return ret; +} + +static int dump_mib_mac_addr(struct at76c503 *dev) +{ + int ret = 0; + struct mib_mac_addr *mac_addr = + kmalloc(sizeof(struct mib_mac_addr), GFP_KERNEL); + + if(!mac_addr){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_MAC_ADD, + (u8*)mac_addr, sizeof(struct mib_mac_addr)); + if(ret < 0){ + err("%s: get_mib (MAC_ADDR) failed: %d", dev->netdev->name, ret); + goto err; + } + + dbg_uc("%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x group_addr %s status %d %d %d %d", + dev->netdev->name, mac2str(mac_addr->mac_addr), + mac_addr->res[0], mac_addr->res[1], + hex2str(dev->obuf, (u8 *)mac_addr->group_addr, + min((int)(sizeof(dev->obuf)-1)/2, 4*ETH_ALEN), '\0'), + mac_addr->group_addr_status[0], mac_addr->group_addr_status[1], + mac_addr->group_addr_status[2], mac_addr->group_addr_status[3]); + + err: + kfree(mac_addr); + exit: + return ret; +} + +static int dump_mib_mac_wep(struct at76c503 *dev) +{ + int ret = 0; + struct mib_mac_wep *mac_wep = + kmalloc(sizeof(struct mib_mac_wep), GFP_KERNEL); + + if(!mac_wep){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_MAC_WEP, + (u8*)mac_wep, sizeof(struct mib_mac_wep)); + if(ret < 0){ + err("%s: get_mib (MAC_WEP) failed: %d", dev->netdev->name, ret); + goto err; + } + + dbg_uc("%s: MIB MAC_WEP: priv_invoked %u def_key_id %u key_len %u " + "excl_unencr %u wep_icv_err %u wep_excluded %u encr_level %u key %d: %s", + dev->netdev->name, mac_wep->privacy_invoked, + mac_wep->wep_default_key_id, mac_wep->wep_key_mapping_len, + mac_wep->exclude_unencrypted,le32_to_cpu( mac_wep->wep_icv_error_count), + le32_to_cpu(mac_wep->wep_excluded_count), + mac_wep->encryption_level, mac_wep->wep_default_key_id, + mac_wep->wep_default_key_id < 4 ? + hex2str(dev->obuf, + mac_wep->wep_default_keyvalue[mac_wep->wep_default_key_id], + min((int)(sizeof(dev->obuf)-1)/2, + mac_wep->encryption_level == 2 ? 13 : 5), '\0') : + ""); + + err: + kfree(mac_wep); + exit: + return ret; +} + +static int dump_mib_mac_mgmt(struct at76c503 *dev) +{ + int ret = 0; + struct mib_mac_mgmt *mac_mgmt = + kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL); + char country_string[4]; + + if(!mac_mgmt){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_MAC_MGMT, + (u8*)mac_mgmt, sizeof(struct mib_mac_mgmt)); + if(ret < 0){ + err("%s: get_mib failed: %d", dev->netdev->name, ret); + goto err; + } + + memcpy(&country_string, mac_mgmt->country_string, 3); + country_string[3] = '\0'; + + dbg_uc("%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration %d " + "medium_occupancy_limit %d station_id 0x%x ATIM_window %d " + "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d " + "current_bssid %s current_essid %s current_bss_type %d " + "pm_mode %d ibss_change %d res %d " + "multi_domain_capability_implemented %d " + "international_roaming %d country_string %s", + dev->netdev->name, + le16_to_cpu(mac_mgmt->beacon_period), + le16_to_cpu(mac_mgmt->CFP_max_duration), + le16_to_cpu(mac_mgmt->medium_occupancy_limit), + le16_to_cpu(mac_mgmt->station_id), + le16_to_cpu(mac_mgmt->ATIM_window), + mac_mgmt->CFP_mode, + mac_mgmt->privacy_option_implemented, + mac_mgmt->DTIM_period, + mac_mgmt->CFP_period, + mac2str(mac_mgmt->current_bssid), + hex2str(dev->obuf, (u8 *)mac_mgmt->current_essid, + min((int)(sizeof(dev->obuf)-1)/2, + IW_ESSID_MAX_SIZE), '\0'), + mac_mgmt->current_bss_type, + mac_mgmt->power_mgmt_mode, + mac_mgmt->ibss_change, + mac_mgmt->res, + mac_mgmt->multi_domain_capability_implemented, + mac_mgmt->multi_domain_capability_enabled, + country_string); + err: + kfree(mac_mgmt); + exit: + return ret; +} + +static int dump_mib_mac(struct at76c503 *dev) +{ + int ret = 0; + struct mib_mac *mac = + kmalloc(sizeof(struct mib_mac), GFP_KERNEL); + + if(!mac){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_MAC, + (u8*)mac, sizeof(struct mib_mac)); + if(ret < 0){ + err("%s: get_mib failed: %d", dev->netdev->name, ret); + goto err; + } + + dbg_uc("%s: MIB MAC: max_tx_msdu_lifetime %d max_rx_lifetime %d " + "frag_threshold %d rts_threshold %d cwmin %d cwmax %d " + "short_retry_time %d long_retry_time %d scan_type %d " + "scan_channel %d probe_delay %u min_channel_time %d " + "max_channel_time %d listen_int %d desired_ssid %s " + "desired_bssid %s desired_bsstype %d", + dev->netdev->name, + le32_to_cpu(mac->max_tx_msdu_lifetime), + le32_to_cpu(mac->max_rx_lifetime), + le16_to_cpu(mac->frag_threshold), + le16_to_cpu(mac->rts_threshold), + le16_to_cpu(mac->cwmin), + le16_to_cpu(mac->cwmax), + mac->short_retry_time, + mac->long_retry_time, + mac->scan_type, + mac->scan_channel, + le16_to_cpu(mac->probe_delay), + le16_to_cpu(mac->min_channel_time), + le16_to_cpu(mac->max_channel_time), + le16_to_cpu(mac->listen_interval), + hex2str(dev->obuf, mac->desired_ssid, + min((int)(sizeof(dev->obuf)-1)/2, + IW_ESSID_MAX_SIZE), '\0'), + mac2str(mac->desired_bssid), + mac->desired_bsstype); + err: + kfree(mac); + exit: + return ret; +} + +static int dump_mib_phy(struct at76c503 *dev) +{ + int ret = 0; + struct mib_phy *phy = + kmalloc(sizeof(struct mib_phy), GFP_KERNEL); + + if(!phy){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_PHY, + (u8*)phy, sizeof(struct mib_phy)); + if(ret < 0){ + err("%s: get_mib failed: %d", dev->netdev->name, ret); + goto err; + } + + dbg_uc("%s: MIB PHY: ed_threshold %d slot_time %d sifs_time %d " + "preamble_length %d plcp_header_length %d mpdu_max_length %d " + "cca_mode_supported %d operation_rate_set " + "0x%x 0x%x 0x%x 0x%x channel_id %d current_cca_mode %d " + "phy_type %d current_reg_domain %d", + dev->netdev->name, + le32_to_cpu(phy->ed_threshold), + le16_to_cpu(phy->slot_time), + le16_to_cpu(phy->sifs_time), + le16_to_cpu(phy->preamble_length), + le16_to_cpu(phy->plcp_header_length), + le16_to_cpu(phy->mpdu_max_length), + le16_to_cpu(phy->cca_mode_supported), + phy->operation_rate_set[0], phy->operation_rate_set[1], + phy->operation_rate_set[2], phy->operation_rate_set[3], + phy->channel_id, + phy->current_cca_mode, + phy->phy_type, + phy->current_reg_domain); + err: + kfree(phy); + exit: + return ret; +} + +static int dump_mib_local(struct at76c503 *dev) +{ + int ret = 0; + struct mib_local *local = + kmalloc(sizeof(struct mib_phy), GFP_KERNEL); + + if(!local){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_LOCAL, + (u8*)local, sizeof(struct mib_local)); + if(ret < 0){ + err("%s: get_mib failed: %d", dev->netdev->name, ret); + goto err; + } + + dbg_uc("%s: MIB PHY: beacon_enable %d txautorate_fallback %d " + "ssid_size %d promiscuous_mode %d preamble_type %d", + dev->netdev->name, + local->beacon_enable, + local->txautorate_fallback, + local->ssid_size, + local->promiscuous_mode, + local->preamble_type); + err: + kfree(local); + exit: + return ret; +} + + +static int get_mib_mdomain(struct at76c503 *dev, struct mib_mdomain *val) +{ + int ret = 0; + struct mib_mdomain *mdomain = + kmalloc(sizeof(struct mib_mdomain), GFP_KERNEL); + + if(!mdomain){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_MDOMAIN, + (u8*)mdomain, sizeof(struct mib_mdomain)); + if(ret < 0){ + err("%s: get_mib failed: %d", dev->netdev->name, ret); + goto err; + } + + memcpy(val, mdomain, sizeof(*val)); + + err: + kfree(mdomain); + exit: + return ret; +} + +static void dump_mib_mdomain(struct at76c503 *dev) +{ + char obuf1[2*14+1], obuf2[2*14+1]; /* to hexdump tx_powerlevel, + channel_list */ + int ret; + struct mib_mdomain mdomain; + + if ((ret=get_mib_mdomain(dev, &mdomain)) < 0) { + err("%s: get_mib_mdomain returned %d", __FUNCTION__, ret); + return; + } + + dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s tx_powerlevel %s", + dev->netdev->name, + hex2str(obuf1, mdomain.channel_list, + (sizeof(obuf1)-1)/2,'\0'), + hex2str(obuf2, mdomain.tx_powerlevel, + (sizeof(obuf2)-1)/2,'\0')); +} + +static +int get_current_bssid(struct at76c503 *dev) +{ + int ret = 0; + struct mib_mac_mgmt *mac_mgmt = + kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL); + + if(!mac_mgmt){ + ret = -ENOMEM; + goto exit; + } + + ret = get_mib(dev->udev, MIB_MAC_MGMT, + (u8*)mac_mgmt, sizeof(struct mib_mac_mgmt)); + if(ret < 0){ + err("%s: get_mib failed: %d", dev->netdev->name, ret); + goto err; + } + memcpy(dev->bssid, mac_mgmt->current_bssid, ETH_ALEN); + info("using BSSID %s", mac2str(dev->bssid)); + err: + kfree(mac_mgmt); + exit: + return ret; +} + +static int get_current_channel(struct at76c503 *dev) +{ + int ret = 0; + struct mib_phy *phy = + kmalloc(sizeof(struct mib_phy), GFP_KERNEL); + + if(!phy){ + ret = -ENOMEM; + goto exit; + } + ret = get_mib(dev->udev, MIB_PHY, (u8*)phy, + sizeof(struct mib_phy)); + if(ret < 0){ + err("%s: get_mib(MIB_PHY) failed: %d", dev->netdev->name, ret); + goto err; + } + dev->channel = phy->channel_id; + err: + kfree(phy); + exit: + return ret; +} + +/* == PROC start_scan == + start a scan. use_essid is != 0 if any probe_delay (if scan mode is not + passive) should contain the ESSID configured. ir_step describes the + international roaming step (0, 1) */ +static int start_scan(struct at76c503 *dev, int use_essid, int ir_step) +{ + struct at76c503_start_scan scan; + + memset(&scan, 0, sizeof(struct at76c503_start_scan)); + memset(scan.bssid, 0xff, ETH_ALEN); + + if (use_essid) { + memcpy(scan.essid, dev->essid, IW_ESSID_MAX_SIZE); + scan.essid_size = dev->essid_size; + } else + scan.essid_size = 0; + + //jal: why should we start at a certain channel? we do scan the whole range + //allowed by reg domain. + scan.channel = dev->channel; + + /* atmelwlandriver differs between scan type 0 and 1 (active/passive) + For ad-hoc mode, it uses type 0 only.*/ + if ((dev->international_roaming == IR_ON && ir_step == 0) || + dev->iw_mode == IW_MODE_MONITOR) + scan.scan_type = SCAN_TYPE_PASSIVE; + else + scan.scan_type = dev->scan_mode; + + /* INFO: For probe_delay, not multiplying by 1024 as this will be + slightly less than min_channel_time + (per spec: probe delay < min. channel time) */ + LOCK_ISTATE() + if (dev->istate == MONITORING) { + scan.min_channel_time = cpu_to_le16(dev->monitor_scan_min_time); + scan.max_channel_time = cpu_to_le16(dev->monitor_scan_max_time); + scan.probe_delay = cpu_to_le16(dev->monitor_scan_min_time * 1000); + } else { + scan.min_channel_time = cpu_to_le16(dev->scan_min_time); + scan.max_channel_time = cpu_to_le16(dev->scan_max_time); + scan.probe_delay = cpu_to_le16(dev->scan_min_time * 1000); + } + UNLOCK_ISTATE() + if (dev->international_roaming == IR_ON && ir_step == 1) + scan.international_scan = 0; + else + scan.international_scan = dev->international_roaming; + + /* other values are set to 0 for type 0 */ + + dbg(DBG_PROGRESS, "%s: start_scan (use_essid = %d, intl = %d, " + "channel = %d, probe_delay = %d, scan_min_time = %d, " + "scan_max_time = %d)", + dev->netdev->name, use_essid, + scan.international_scan, scan.channel, + le16_to_cpu(scan.probe_delay), + le16_to_cpu(scan.min_channel_time), + le16_to_cpu(scan.max_channel_time)); + + return set_card_command(dev->udev, CMD_SCAN, + (unsigned char*)&scan, sizeof(scan)); +} + +static int start_ibss(struct at76c503 *dev) +{ + struct at76c503_start_bss bss; + + memset(&bss, 0, sizeof(struct at76c503_start_bss)); + memset(bss.bssid, 0xff, ETH_ALEN); + memcpy(bss.essid, dev->essid, IW_ESSID_MAX_SIZE); + bss.essid_size = dev->essid_size; + bss.bss_type = ADHOC_MODE; + bss.channel = dev->channel; + + return set_card_command(dev->udev, CMD_START_IBSS, + (unsigned char*)&bss, sizeof(struct at76c503_start_bss)); +} + +/* idx points into dev->bss */ +static int join_bss(struct at76c503 *dev, struct bss_info *ptr) +{ + struct at76c503_join join; + + assert(ptr != NULL); + + memset(&join, 0, sizeof(struct at76c503_join)); + memcpy(join.bssid, ptr->bssid, ETH_ALEN); + memcpy(join.essid, ptr->ssid, ptr->ssid_len); + join.essid_size = ptr->ssid_len; + join.bss_type = (dev->iw_mode == IW_MODE_ADHOC ? 1 : 2); + join.channel = ptr->channel; + join.timeout = cpu_to_le16(2000); + + dbg(DBG_PROGRESS, "%s join addr %s ssid %s type %d ch %d timeout %d", + dev->netdev->name, mac2str(join.bssid), + join.essid, join.bss_type, join.channel, le16_to_cpu(join.timeout)); + return set_card_command(dev->udev, CMD_JOIN, + (unsigned char*)&join, + sizeof(struct at76c503_join)); +} /* join_bss */ + +/* the firmware download timeout (after remap) */ +static void fw_dl_timeout(unsigned long par) +{ + struct at76c503 *dev = (struct at76c503 *)par; + defer_kevent(dev, KEVENT_RESET_DEVICE); +} + + +/* the restart timer timed out */ +static void restart_timeout(unsigned long par) +{ + struct at76c503 *dev = (struct at76c503 *)par; + defer_kevent(dev, KEVENT_RESTART); +} + +/* we got to check the bss_list for old entries */ +static void bss_list_timeout(unsigned long par) +{ + struct at76c503 *dev = (struct at76c503 *)par; + unsigned long flags; + struct list_head *lptr, *nptr; + struct bss_info *ptr; + + spin_lock_irqsave(&dev->bss_list_spinlock, flags); + + list_for_each_safe(lptr, nptr, &dev->bss_list) { + + ptr = list_entry(lptr, struct bss_info, list); + + if (ptr != dev->curr_bss && ptr != dev->new_bss && + time_after(jiffies, ptr->last_rx+BSS_LIST_TIMEOUT)) { + dbg(DBG_BSS_TABLE_RM, + "%s: bss_list: removing old BSS %s ch %d", + dev->netdev->name, mac2str(ptr->bssid), ptr->channel); + list_del(&ptr->list); + kfree(ptr); + } + } + spin_unlock_irqrestore(&dev->bss_list_spinlock, flags); + /* restart the timer */ + mod_timer(&dev->bss_list_timer, jiffies+BSS_LIST_TIMEOUT); + +} + +/* we got a timeout for a infrastructure mgmt packet */ +static void mgmt_timeout(unsigned long par) +{ + struct at76c503 *dev = (struct at76c503 *)par; + defer_kevent(dev, KEVENT_MGMT_TIMEOUT); +} + +/* == PROC handle_mgmt_timeout_scan == */ +/* called in istate SCANNING on expiry of the mgmt_timer, when a scan was run before + (dev->scan_runs > 0) */ +static void handle_mgmt_timeout_scan(struct at76c503 *dev) +{ + + u8 *cmd_status; + int ret; + struct mib_mdomain mdomain; + + cmd_status = kmalloc(40, GFP_KERNEL); + if (cmd_status == NULL) { + err("%s: %s: cmd_status kmalloc returned NULL", + dev->netdev->name, __FUNCTION__); + return; + } + + + if ((ret=get_cmd_status(dev->udev, CMD_SCAN, cmd_status)) < 0) { + err("%s: %s: get_cmd_status failed with %d", + dev->netdev->name, __FUNCTION__, ret); + cmd_status[5] = CMD_STATUS_IN_PROGRESS; + /* INFO: Hope it was a one off error - if not, scanning + further down the line and stop this cycle */ + } + LOCK_ISTATE() + dbg(DBG_PROGRESS, "%s %s:%d got cmd_status %d (istate %d, " + "scan_runs %d)", + dev->netdev->name, __FUNCTION__, __LINE__, cmd_status[5], + dev->istate, dev->scan_runs); + UNLOCK_ISTATE() + if (cmd_status[5] == CMD_STATUS_COMPLETE) { + LOCK_ISTATE() + if (dev->istate == SCANNING) { + UNLOCK_ISTATE() + dump_bss_table(dev,0); + switch (dev->scan_runs) { + + case 1: + assert(dev->international_roaming); + if ((ret=get_mib_mdomain(dev, &mdomain)) < 0) { + err("get_mib_mdomain returned %d", ret); + } else { + char obuf1[2*14+1], obuf2[2*14+1]; + + dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s " + "tx_powerlevel %s", + dev->netdev->name, + hex2str(obuf1, mdomain.channel_list, + (sizeof(obuf1)-1)/2,'\0'), + hex2str(obuf2, mdomain.tx_powerlevel, + (sizeof(obuf2)-1)/2,'\0')); + } + if ((ret = start_scan(dev, 0, 1)) < 0) { + err("%s: %s: start_scan (ANY) failed with %d", + dev->netdev->name, __FUNCTION__, ret); + } + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer for %d ticks", + __FUNCTION__, __LINE__, SCAN_POLL_INTERVAL); + mod_timer(&dev->mgmt_timer, jiffies + SCAN_POLL_INTERVAL); + break; + + case 2: + if ((ret = start_scan(dev, 1, 1)) < 0) { + err("%s: %s: start_scan (SSID) failed with %d", + dev->netdev->name, __FUNCTION__, ret); + } + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer for %d ticks", + __FUNCTION__, __LINE__, SCAN_POLL_INTERVAL); + mod_timer(&dev->mgmt_timer, jiffies + SCAN_POLL_INTERVAL); + break; + + case 3: + dev->site_survey_state = SITE_SURVEY_COMPLETED; + /* report the end of scan to user space */ + iwevent_scan_complete(dev->netdev); + NEW_STATE(dev,JOINING); + assert(dev->curr_bss == NULL); /* done in free_bss_list, + find_bss will start with first bss */ + /* call join_bss immediately after + re-run of all other threads in kevent */ + defer_kevent(dev,KEVENT_JOIN); + break; + + default: + err("unexpected dev->scan_runs %d", dev->scan_runs); + } /* switch (dev->scan_runs)*/ + dev->scan_runs++; + } else { + + assert(dev->istate == MONITORING); + UNLOCK_ISTATE() + dbg(DBG_MONITOR_MODE, "%s: MONITOR MODE: restart scan", + dev->netdev->name); + start_scan(dev, 0, 0); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer for %d ticks", + __FUNCTION__, __LINE__, SCAN_POLL_INTERVAL); + mod_timer(&dev->mgmt_timer, jiffies + SCAN_POLL_INTERVAL); + } + + } else { + if ((cmd_status[5] != CMD_STATUS_IN_PROGRESS) && + (cmd_status[5] != CMD_STATUS_IDLE)) + err("%s: %s: Bad scan status: %s", + dev->netdev->name, __FUNCTION__, + get_cmd_status_string(cmd_status[5])); + + /* the first cmd status after scan start is always a IDLE -> + start the timer to poll again until COMPLETED */ + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer for %d ticks", + __FUNCTION__, __LINE__, SCAN_POLL_INTERVAL); + mod_timer(&dev->mgmt_timer, jiffies + SCAN_POLL_INTERVAL); + } + + kfree(cmd_status); +} + +/* the deferred procedure called from kevent() */ +static void handle_mgmt_timeout(struct at76c503 *dev) +{ + LOCK_ISTATE() + if ((dev->istate != SCANNING && dev->istate != MONITORING) || + (at76_debug & DBG_MGMT_TIMER)) + /* this is normal behavior in states MONITORING, SCANNING ... */ + dbg(DBG_PROGRESS, "%s: timeout, state %d", dev->netdev->name, + dev->istate); + + switch(dev->istate) { + + case MONITORING: + case SCANNING: + UNLOCK_ISTATE() + handle_mgmt_timeout_scan(dev); + break; + + case JOINING: + UNLOCK_ISTATE() + assert(0); + break; + + case CONNECTED: /* we haven't received the beacon of this BSS for + BEACON_TIMEOUT seconds */ + UNLOCK_ISTATE() + info("%s: lost beacon bssid %s", + dev->netdev->name, mac2str(dev->curr_bss->bssid)); + /* jal: starting mgmt_timer in ad-hoc mode is questionable, + but I'll leave it here to track down another lockup problem */ + if (dev->iw_mode != IW_MODE_ADHOC) { + netif_carrier_off(dev->netdev); + netif_stop_queue(dev->netdev); + iwevent_bss_disconnect(dev->netdev); + NEW_STATE(dev,SCANNING); + defer_kevent(dev,KEVENT_SCAN); + } + break; + + case AUTHENTICATING: + UNLOCK_ISTATE() + if (dev->retries-- >= 0) { + auth_req(dev, dev->curr_bss, 1, NULL); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", + __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer, jiffies+HZ); + } else { + /* try to get next matching BSS */ + NEW_STATE(dev,JOINING); + defer_kevent(dev,KEVENT_JOIN); + } + break; + + case ASSOCIATING: + UNLOCK_ISTATE() + if (dev->retries-- >= 0) { + assoc_req(dev,dev->curr_bss); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", + __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer, jiffies+HZ); + } else { + /* jal: TODO: we may be authenticated to several + BSS and may try to associate to the next of them here + in the future ... */ + + /* try to get next matching BSS */ + NEW_STATE(dev,JOINING); + defer_kevent(dev,KEVENT_JOIN); + } + break; + + case REASSOCIATING: + UNLOCK_ISTATE() + if (dev->retries-- >= 0) + reassoc_req(dev, dev->curr_bss, dev->new_bss); + else { + /* we disassociate from the curr_bss and + scan again ... */ + NEW_STATE(dev,DISASSOCIATING); + dev->retries = DISASSOC_RETRIES; + disassoc_req(dev, dev->curr_bss); + } + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", + __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer, jiffies+HZ); + break; + + case DISASSOCIATING: + UNLOCK_ISTATE() + if (dev->retries-- >= 0) { + disassoc_req(dev, dev->curr_bss); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", + __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer,jiffies+HZ); + } else { + /* we scan again ... */ + NEW_STATE(dev,SCANNING); + defer_kevent(dev,KEVENT_SCAN); + } + break; + + case INIT: + UNLOCK_ISTATE() + break; + + default: + UNLOCK_ISTATE() + assert(0); + } /* switch (dev->istate) */ + +}/* handle_mgmt_timeout */ + +/* calc. the padding from txbuf->wlength (which excludes the USB TX header) + guess this is needed to compensate a flaw in the AT76C503A USB part ... */ +static inline int calc_padding(int wlen) +{ + /* add the USB TX header */ + wlen += AT76C503_TX_HDRLEN; + + wlen = wlen % 64; + + if (wlen < 50) + return 50 - wlen; + + if (wlen >=61) + return 64 + 50 - wlen; + + return 0; +} + +/* send a management frame on bulk-out. + txbuf->wlength must be set (in LE format !) */ +static int send_mgmt_bulk(struct at76c503 *dev, struct at76c503_tx_buffer *txbuf) +{ + unsigned long flags; + int ret = 0; + int urb_status; + void *oldbuf = NULL; + + netif_carrier_off(dev->netdev); /* disable running netdev watchdog */ + netif_stop_queue(dev->netdev); /* stop tx data packets */ + + spin_lock_irqsave(&dev->mgmt_spinlock, flags); + + if ((urb_status=dev->write_urb->status) == -EINPROGRESS) { + oldbuf=dev->next_mgmt_bulk; /* to kfree below */ + dev->next_mgmt_bulk = txbuf; + txbuf = NULL; + } + spin_unlock_irqrestore(&dev->mgmt_spinlock, flags); + + if (oldbuf) { + /* a data/mgmt tx is already pending in the URB - + if this is no error in some situations we must + implement a queue or silently modify the old msg */ + err("%s: %s removed pending mgmt buffer %s", + dev->netdev->name, __FUNCTION__, + hex2str(dev->obuf, (u8 *)dev->next_mgmt_bulk, + min((int)(sizeof(dev->obuf))/3, 64),' ')); + kfree(dev->next_mgmt_bulk); + } + + if (txbuf) { + + txbuf->tx_rate = 0; +// txbuf->padding = 0; + txbuf->padding = calc_padding(le16_to_cpu(txbuf->wlength)); + + if (dev->next_mgmt_bulk) { + err("%s: %s URB status %d, but mgmt is pending", + dev->netdev->name, __FUNCTION__, urb_status); + } + + dbg(DBG_TX_MGMT, "%s: tx mgmt: wlen %d tx_rate %d pad %d %s", + dev->netdev->name, le16_to_cpu(txbuf->wlength), + txbuf->tx_rate, txbuf->padding, + hex2str(dev->obuf, txbuf->packet, + min((sizeof(dev->obuf)-1)/2, + (size_t)le16_to_cpu(txbuf->wlength)),'\0')); + + /* txbuf was not consumed above -> send mgmt msg immediately */ + memcpy(dev->bulk_out_buffer, txbuf, + le16_to_cpu(txbuf->wlength) + AT76C503_TX_HDRLEN); + FILL_BULK_URB(dev->write_urb, dev->udev, + usb_sndbulkpipe(dev->udev, + dev->bulk_out_endpointAddr), + dev->bulk_out_buffer, + le16_to_cpu(txbuf->wlength) + + txbuf->padding + + AT76C503_TX_HDRLEN, + (usb_complete_t)at76c503_write_bulk_callback, dev); + ret = usb_submit_urb(dev->write_urb, GFP_ATOMIC); + if (ret) { + err("%s: %s error in tx submit urb: %d", + dev->netdev->name, __FUNCTION__, ret); + } + kfree(txbuf); + } /* if (txbuf) */ + + return ret; + +} /* send_mgmt_bulk */ + +static int disassoc_req(struct at76c503 *dev, struct bss_info *bss) +{ + struct at76c503_tx_buffer *tx_buffer; + struct ieee80211_hdr_3addr *mgmt; + struct ieee802_11_disassoc_frame *req; + + assert(bss != NULL); + if (bss == NULL) + return -EFAULT; + + tx_buffer = kmalloc(DISASSOC_FRAME_SIZE + MAX_PADDING_SIZE, + GFP_ATOMIC); + if (!tx_buffer) + return -ENOMEM; + + mgmt = (struct ieee80211_hdr_3addr *)&(tx_buffer->packet); + req = (struct ieee802_11_disassoc_frame *)&(mgmt->payload); + + /* make wireless header */ + mgmt->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_AUTH); + mgmt->duration_id = cpu_to_le16(0x8000); + memcpy(mgmt->addr1, bss->bssid, ETH_ALEN); + memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN); + memcpy(mgmt->addr3, bss->bssid, ETH_ALEN); + mgmt->seq_ctl = cpu_to_le16(0); + + req->reason = 0; + + /* init. at76c503 tx header */ + tx_buffer->wlength = cpu_to_le16(DISASSOC_FRAME_SIZE - + AT76C503_TX_HDRLEN); + + dbg(DBG_TX_MGMT, "%s: DisAssocReq bssid %s", + dev->netdev->name, mac2str(mgmt->addr3)); + + /* either send immediately (if no data tx is pending + or put it in pending list */ + return send_mgmt_bulk(dev, tx_buffer); + +} /* disassoc_req */ + +/* challenge is the challenge string (in TLV format) + we got with seq_nr 2 for shared secret authentication only and + send in seq_nr 3 WEP encrypted to prove we have the correct WEP key; + otherwise it is NULL */ +static int auth_req(struct at76c503 *dev, struct bss_info *bss, int seq_nr, u8 *challenge) +{ + struct at76c503_tx_buffer *tx_buffer; + struct ieee80211_hdr_3addr *mgmt; + struct ieee802_11_auth_frame *req; + + int buf_len = (seq_nr != 3 ? AUTH_FRAME_SIZE : + AUTH_FRAME_SIZE + 1 + 1 + challenge[1]); + + assert(bss != NULL); + assert(seq_nr != 3 || challenge != NULL); + + tx_buffer = kmalloc(buf_len + MAX_PADDING_SIZE, GFP_ATOMIC); + if (!tx_buffer) + return -ENOMEM; + + mgmt = (struct ieee80211_hdr_3addr *)&(tx_buffer->packet); + req = (struct ieee802_11_auth_frame *)&(mgmt->payload); + + /* make wireless header */ + /* first auth msg is not encrypted, only the second (seq_nr == 3) */ + mgmt->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH | + (seq_nr == 3 ? IEEE80211_FCTL_PROTECTED : 0)); + + mgmt->duration_id = cpu_to_le16(0x8000); + memcpy(mgmt->addr1, bss->bssid, ETH_ALEN); + memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN); + memcpy(mgmt->addr3, bss->bssid, ETH_ALEN); + mgmt->seq_ctl = cpu_to_le16(0); + + req->algorithm = cpu_to_le16(dev->auth_mode); + req->seq_nr = cpu_to_le16(seq_nr); + req->status = cpu_to_le16(0); + + if (seq_nr == 3) + memcpy(req->challenge, challenge, 1+1+challenge[1]); + + /* init. at76c503 tx header */ + tx_buffer->wlength = cpu_to_le16(buf_len - AT76C503_TX_HDRLEN); + + dbg(DBG_TX_MGMT, "%s: AuthReq bssid %s alg %d seq_nr %d", + dev->netdev->name, mac2str(mgmt->addr3), + le16_to_cpu(req->algorithm), le16_to_cpu(req->seq_nr)); + if (seq_nr == 3) { + dbg(DBG_TX_MGMT, "%s: AuthReq challenge: %s ...", + dev->netdev->name, + hex2str(dev->obuf, req->challenge, + min((int)sizeof(dev->obuf)/3, 18),' ')); + } + + /* either send immediately (if no data tx is pending + or put it in pending list */ + return send_mgmt_bulk(dev, tx_buffer); + +} /* auth_req */ + +static int assoc_req(struct at76c503 *dev, struct bss_info *bss) +{ + struct at76c503_tx_buffer *tx_buffer; + struct ieee80211_hdr_3addr *mgmt; + struct ieee802_11_assoc_req *req; + u8 *tlv; + + assert(bss != NULL); + + tx_buffer = kmalloc(ASSOCREQ_MAX_SIZE + MAX_PADDING_SIZE, + GFP_ATOMIC); + if (!tx_buffer) + return -ENOMEM; + + mgmt = (struct ieee80211_hdr_3addr *)&(tx_buffer->packet); + req = (struct ieee802_11_assoc_req *)&(mgmt->payload); + tlv = req->data; + + /* make wireless header */ + mgmt->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_ASSOC_REQ); + + mgmt->duration_id = cpu_to_le16(0x8000); + memcpy(mgmt->addr1, bss->bssid, ETH_ALEN); + memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN); + memcpy(mgmt->addr3, bss->bssid, ETH_ALEN); + mgmt->seq_ctl = cpu_to_le16(0); + + /* we must set the Privacy bit in the capabilities to assure an + Agere-based AP with optional WEP transmits encrypted frames + to us. AP only set the Privacy bit in their capabilities + if WEP is mandatory in the BSS! */ + req->capability = cpu_to_le16(bss->capa | + (dev->wep_enabled ? WLAN_CAPABILITY_PRIVACY : 0) | + (dev->preamble_type == PREAMBLE_TYPE_SHORT ? + WLAN_CAPABILITY_SHORT_PREAMBLE : 0)); + + req->listen_interval = cpu_to_le16(2 * bss->beacon_interval); + + /* write TLV data elements */ + + *tlv++ = MFIE_TYPE_SSID; + *tlv++ = bss->ssid_len; + memcpy(tlv, bss->ssid, bss->ssid_len); + tlv += bss->ssid_len; + + *tlv++ = MFIE_TYPE_RATES; + *tlv++ = sizeof(hw_rates); + memcpy(tlv, hw_rates, sizeof(hw_rates)); + tlv += sizeof(hw_rates); /* tlv points behind the supp_rates field */ + + /* init. at76c503 tx header */ + tx_buffer->wlength = cpu_to_le16(tlv-(u8 *)mgmt); + + { + /* output buffer for ssid and rates */ + char orates[4*2+1]; + int len; + + tlv = req->data; + len = min(IW_ESSID_MAX_SIZE, (int)*(tlv+1)); + memcpy(dev->obuf, tlv+2, len); + dev->obuf[len] = '\0'; + tlv += (1 + 1 + *(tlv+1)); /* points to IE of rates now */ + dbg(DBG_TX_MGMT, "%s: AssocReq bssid %s capa x%04x ssid %s rates %s", + dev->netdev->name, mac2str(mgmt->addr3), + le16_to_cpu(req->capability), dev->obuf, + hex2str(orates,tlv+2,min((sizeof(orates)-1)/2,(size_t)*(tlv+1)), + '\0')); + } + + /* either send immediately (if no data tx is pending + or put it in pending list */ + return send_mgmt_bulk(dev, tx_buffer); + +} /* assoc_req */ + +/* we are currently associated to curr_bss and + want to reassoc to new_bss */ +static int reassoc_req(struct at76c503 *dev, struct bss_info *curr_bss, + struct bss_info *new_bss) +{ + struct at76c503_tx_buffer *tx_buffer; + struct ieee80211_hdr_3addr *mgmt; + struct ieee802_11_reassoc_req *req; + + u8 *tlv; + + assert(curr_bss != NULL); + assert(new_bss != NULL); + if (curr_bss == NULL || new_bss == NULL) + return -EFAULT; + + tx_buffer = kmalloc(REASSOCREQ_MAX_SIZE + MAX_PADDING_SIZE, + GFP_ATOMIC); + if (!tx_buffer) + return -ENOMEM; + + mgmt = (struct ieee80211_hdr_3addr *)&(tx_buffer->packet); + req = (struct ieee802_11_reassoc_req *)&(mgmt->payload); + tlv = req->data; + + /* make wireless header */ + /* jal: encrypt this packet if wep_enabled is TRUE ??? */ + mgmt->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_REASSOC_REQ); + mgmt->duration_id = cpu_to_le16(0x8000); + memcpy(mgmt->addr1, new_bss->bssid, ETH_ALEN); + memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN); + memcpy(mgmt->addr3, new_bss->bssid, ETH_ALEN); + mgmt->seq_ctl = cpu_to_le16(0); + + /* we must set the Privacy bit in the capabilities to assure an + Agere-based AP with optional WEP transmits encrypted frames + to us. AP only set the Privacy bit in their capabilities + if WEP is mandatory in the BSS! */ + req->capability = cpu_to_le16(new_bss->capa | + (dev->wep_enabled ? WLAN_CAPABILITY_PRIVACY : 0) | + (dev->preamble_type == PREAMBLE_TYPE_SHORT ? + WLAN_CAPABILITY_SHORT_PREAMBLE : 0)); + + req->listen_interval = cpu_to_le16(2 * new_bss->beacon_interval); + + memcpy(req->curr_ap, curr_bss->bssid, ETH_ALEN); + + /* write TLV data elements */ + + *tlv++ = MFIE_TYPE_SSID; + *tlv++ = new_bss->ssid_len; + memcpy(tlv,new_bss->ssid, new_bss->ssid_len); + tlv += new_bss->ssid_len; + + *tlv++ = MFIE_TYPE_RATES; + *tlv++ = sizeof(hw_rates); + memcpy(tlv, hw_rates, sizeof(hw_rates)); + tlv += sizeof(hw_rates); /* tlv points behind the supp_rates field */ + + /* init. at76c503 tx header */ + tx_buffer->wlength = cpu_to_le16(tlv-(u8 *)mgmt); + + { + /* output buffer for rates and bssid */ + char orates[4*2+1]; + char ocurr[6*3+1]; + tlv = req->data; + memcpy(dev->obuf, tlv+2, min(sizeof(dev->obuf),(size_t)*(tlv+1))); + dev->obuf[IW_ESSID_MAX_SIZE] = '\0'; + tlv += (1 + 1 + *(tlv+1)); /* points to IE of rates now */ + dbg(DBG_TX_MGMT, "%s: ReAssocReq curr %s new %s capa x%04x ssid %s rates %s", + dev->netdev->name, + hex2str(ocurr, req->curr_ap, ETH_ALEN, ':'), + mac2str(mgmt->addr3), le16_to_cpu(req->capability), dev->obuf, + hex2str(orates,tlv+2,min((sizeof(orates)-1)/2,(size_t)*(tlv+1)), + '\0')); + } + + /* either send immediately (if no data tx is pending + or put it in pending list */ + return send_mgmt_bulk(dev, tx_buffer); + +} /* reassoc_req */ + + +/* shamelessly copied from usbnet.c (oku) */ +static void defer_kevent (struct at76c503 *dev, int flag) +{ + set_bit (flag, &dev->kevent_flags); + if (!schedule_work (&dev->kevent)) + dbg(DBG_KEVENT, "%s: kevent %d may have been dropped", + dev->netdev->name, flag); + else + dbg(DBG_KEVENT, "%s: kevent %d scheduled", + dev->netdev->name, flag); +} + +static void kevent(struct work_struct *ws) +{ + struct at76c503 *dev = container_of(ws, struct at76c503, kevent); + int ret; + unsigned long flags; + + /* on errors, bits aren't cleared, but no reschedule + is done. So work will be done next time something + else has to be done. This is ugly. TODO! (oku) */ + + dbg(DBG_KEVENT, "%s: kevent entry flags: 0x%lx", dev->netdev->name, + dev->kevent_flags); + + down(&dev->sem); + + if(test_bit(KEVENT_CTRL_HALT, &dev->kevent_flags)){ + /* this never worked... but it seems + that it's rarely necessary, if at all (oku) */ + ret = usb_clear_halt(dev->udev, + usb_sndctrlpipe (dev->udev, 0)); + if(ret < 0) + err("usb_clear_halt() failed: %d", ret); + else{ + clear_bit(KEVENT_CTRL_HALT, &dev->kevent_flags); + info("usb_clear_halt() successful"); + } + } + if(test_bit(KEVENT_NEW_BSS, &dev->kevent_flags)){ + struct net_device *netdev = dev->netdev; + struct mib_mac_mgmt *mac_mgmt = kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL); + + ret = get_mib(dev->udev, MIB_MAC_MGMT, (u8*)mac_mgmt, + sizeof(struct mib_mac_mgmt)); + if(ret < 0){ + err("%s: get_mib failed: %d", netdev->name, ret); + goto new_bss_clean; + } + + dbg(DBG_PROGRESS, "ibss_change = 0x%2x", mac_mgmt->ibss_change); + memcpy(dev->bssid, mac_mgmt->current_bssid, ETH_ALEN); + dbg(DBG_PROGRESS, "using BSSID %s", mac2str(dev->bssid)); + + iwevent_bss_connect(dev->netdev, dev->bssid); + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_MGMT; + dev->mib_buf.size = 1; + dev->mib_buf.index = IBSS_CHANGE_OK_OFFSET; + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (ibss change ok) failed: %d", netdev->name, ret); + goto new_bss_clean; + } + clear_bit(KEVENT_NEW_BSS, &dev->kevent_flags); + new_bss_clean: + kfree(mac_mgmt); + } + + if(test_bit(KEVENT_SET_PROMISC, &dev->kevent_flags)){ + info("%s: KEVENT_SET_PROMISC", dev->netdev->name); + + set_promisc(dev, dev->promisc); + clear_bit(KEVENT_SET_PROMISC, &dev->kevent_flags); + } + + /* check this _before_ KEVENT_JOIN, 'cause _JOIN sets _STARTIBSS bit */ + if (test_bit(KEVENT_STARTIBSS, &dev->kevent_flags)) { + clear_bit(KEVENT_STARTIBSS, &dev->kevent_flags); + LOCK_ISTATE() + assert(dev->istate == STARTIBSS); + UNLOCK_ISTATE() + ret = start_ibss(dev); + if(ret < 0){ + err("%s: start_ibss failed: %d", dev->netdev->name, ret); + goto end_startibss; + } + + ret = wait_completion(dev, CMD_START_IBSS); + if (ret != CMD_STATUS_COMPLETE) { + err("%s start_ibss failed to complete,%d", + dev->netdev->name, ret); + goto end_startibss; + } + + ret = get_current_bssid(dev); + if(ret < 0) goto end_startibss; + + ret = get_current_channel(dev); + if(ret < 0) goto end_startibss; + + /* not sure what this is good for ??? */ + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_MGMT; + dev->mib_buf.size = 1; + dev->mib_buf.index = IBSS_CHANGE_OK_OFFSET; + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (ibss change ok) failed: %d", dev->netdev->name, ret); + goto end_startibss; + } + + netif_carrier_on(dev->netdev); + netif_start_queue(dev->netdev); + } +end_startibss: + + /* check this _before_ KEVENT_SCAN, 'cause _SCAN sets _JOIN bit */ + if (test_bit(KEVENT_JOIN, &dev->kevent_flags)) { + clear_bit(KEVENT_JOIN, &dev->kevent_flags); + LOCK_ISTATE() + if (dev->istate == INIT){ + UNLOCK_ISTATE() + goto end_join; + } + assert(dev->istate == JOINING); + UNLOCK_ISTATE() + /* dev->curr_bss == NULL signals a new round, + starting with list_entry(dev->bss_list.next, ...) */ + + /* secure the access to dev->curr_bss ! */ + spin_lock_irqsave(&dev->bss_list_spinlock, flags); + dev->curr_bss=find_matching_bss(dev, dev->curr_bss); + spin_unlock_irqrestore(&dev->bss_list_spinlock, flags); + + if (dev->curr_bss != NULL) { + if ((ret=join_bss(dev,dev->curr_bss)) < 0) { + err("%s: join_bss failed with %d", + dev->netdev->name, ret); + goto end_join; + } + + ret=wait_completion(dev,CMD_JOIN); + if (ret != CMD_STATUS_COMPLETE) { + if (ret != CMD_STATUS_TIME_OUT) + err("%s join_bss completed with %d", + dev->netdev->name, ret); + else + info("%s join_bss ssid %s timed out", + dev->netdev->name, + mac2str(dev->curr_bss->bssid)); + + /* retry next BSS immediately */ + defer_kevent(dev,KEVENT_JOIN); + goto end_join; + } + + /* here we have joined the (I)BSS */ + if (dev->iw_mode == IW_MODE_ADHOC) { + struct bss_info *bptr = dev->curr_bss; + NEW_STATE(dev,CONNECTED); + /* get ESSID, BSSID and channel for dev->curr_bss */ + dev->essid_size = bptr->ssid_len; + memcpy(dev->essid, bptr->ssid, bptr->ssid_len); + memcpy(dev->bssid, bptr->bssid, ETH_ALEN); + dev->channel = bptr->channel; + iwevent_bss_connect(dev->netdev,bptr->bssid); + netif_carrier_on(dev->netdev); + netif_start_queue(dev->netdev); + /* just to be sure */ + del_timer_sync(&dev->mgmt_timer); + } else { + /* send auth req */ + NEW_STATE(dev,AUTHENTICATING); + auth_req(dev, dev->curr_bss, 1, NULL); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", + __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer, jiffies+HZ); + } + goto end_join; + } /* if (dev->curr_bss != NULL) */ + + /* here we haven't found a matching (i)bss ... */ + if (dev->iw_mode == IW_MODE_ADHOC) { + NEW_STATE(dev,STARTIBSS); + defer_kevent(dev,KEVENT_STARTIBSS); + goto end_join; + } + /* haven't found a matching BSS in infra mode - try again */ + NEW_STATE(dev,SCANNING); + defer_kevent(dev, KEVENT_SCAN); + } /* if (test_bit(KEVENT_JOIN, &dev->kevent_flags)) */ +end_join: + + if(test_bit(KEVENT_MGMT_TIMEOUT, &dev->kevent_flags)){ + clear_bit(KEVENT_MGMT_TIMEOUT, &dev->kevent_flags); + handle_mgmt_timeout(dev); + } + + if (test_bit(KEVENT_SCAN, &dev->kevent_flags)) { + clear_bit(KEVENT_SCAN, &dev->kevent_flags); + LOCK_ISTATE() + assert(dev->istate == SCANNING); + + /* only clear the bss list when a scan is actively initiated, + * otherwise simply rely on bss_list_timeout */ + if( dev->site_survey_state == SITE_SURVEY_IN_PROGRESS) + free_bss_list(dev); + UNLOCK_ISTATE() + + dev->scan_runs=3; + if ((ret=start_scan(dev, 0, 1)) < 0) { + err("%s: %s: start_scan failed with %d", + dev->netdev->name, __FUNCTION__, ret); + } else { + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer for %d ticks", + __FUNCTION__, __LINE__, SCAN_POLL_INTERVAL); + mod_timer(&dev->mgmt_timer, jiffies + SCAN_POLL_INTERVAL); + } + + } /* if (test_bit(KEVENT_SCAN, &dev->kevent_flags)) */ + + + if (test_bit(KEVENT_SUBMIT_RX, &dev->kevent_flags)) { + clear_bit(KEVENT_SUBMIT_RX, &dev->kevent_flags); + submit_rx_urb(dev); + } + + + if (test_bit(KEVENT_RESTART, &dev->kevent_flags)) { + clear_bit(KEVENT_RESTART, &dev->kevent_flags); + LOCK_ISTATE() + assert(dev->istate == INIT); + UNLOCK_ISTATE() + startup_device(dev); + + /* call it here for default_iw_mode == IW_MODE_MONITOR and + no subsequent "iwconfig wlanX mode monitor" or + "iwpriv wlanX monitor 1|2 C" to set dev->netdev->type + correctly */ + set_monitor_mode(dev, dev->monitor_prism_header); + + + netif_carrier_off(dev->netdev); /* disable running netdev watchdog */ + netif_stop_queue(dev->netdev); /* stop tx data packets */ + if (dev->iw_mode != IW_MODE_MONITOR) { + NEW_STATE(dev,SCANNING); + defer_kevent(dev,KEVENT_SCAN); + } else { + NEW_STATE(dev,MONITORING); + start_scan(dev,0,0); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer for %d ticks", + __FUNCTION__, __LINE__, SCAN_POLL_INTERVAL); + mod_timer(&dev->mgmt_timer, jiffies + SCAN_POLL_INTERVAL); + } + } + + if (test_bit(KEVENT_ASSOC_DONE, &dev->kevent_flags)) { + clear_bit(KEVENT_ASSOC_DONE, &dev->kevent_flags); + LOCK_ISTATE() + assert(dev->istate == ASSOCIATING || + dev->istate == REASSOCIATING); + UNLOCK_ISTATE() + if (dev->iw_mode == IW_MODE_INFRA) { + assert(dev->curr_bss != NULL); + if (dev->curr_bss != NULL && + dev->pm_mode != PM_ACTIVE) { + /* calc the listen interval in units of + beacon intervals of the curr_bss */ + dev->pm_period_beacon = (dev->pm_period_us >> 10) / + dev->curr_bss->beacon_interval; + +#ifdef DEBUG /* only to check if we need to set the listen interval here + or could do it in the (re)assoc_req parameter */ + dump_mib_mac(dev); +#endif + + if (dev->pm_period_beacon < 2) + dev->pm_period_beacon = 2; + else + if ( dev->pm_period_beacon > 0xffff) + dev->pm_period_beacon = 0xffff; + + dbg(DBG_PM, "%s: pm_mode %d assoc id x%x listen int %d", + dev->netdev->name, dev->pm_mode, + dev->curr_bss->assoc_id, dev->pm_period_beacon); + + set_associd(dev, dev->curr_bss->assoc_id); + set_listen_interval(dev, (u16)dev->pm_period_beacon); + set_pm_mode(dev, dev->pm_mode); +#ifdef DEBUG + dump_mib_mac(dev); + dump_mib_mac_mgmt(dev); +#endif + } + } + + netif_carrier_on(dev->netdev); + netif_wake_queue(dev->netdev); /* _start_queue ??? */ + NEW_STATE(dev,CONNECTED); + iwevent_bss_connect(dev->netdev,dev->curr_bss->bssid); + dbg(DBG_PROGRESS, "%s: connected to BSSID %s", + dev->netdev->name, mac2str(dev->curr_bss->bssid)); + } + + + if (test_bit(KEVENT_RESET_DEVICE, &dev->kevent_flags)) { + + clear_bit(KEVENT_RESET_DEVICE, &dev->kevent_flags); + + dbg(DBG_DEVSTART, "resetting the device"); + + usb_reset_device(dev->udev); + +/* with 2.6.8 the reset above will cause a disconnect as the USB subsys + recognizes the change in the config descriptors. Subsequently the device + will be registered again. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) + + //jal: patch the state (patch by Dmitri) + dev->udev->state = USB_STATE_CONFIGURED; + + /* jal: currently (2.6.0-test2 and 2.4.23) + usb_reset_device() does not recognize that + the interface descr. are changed. + This procedure reads the configuration and does a limited parsing of + the interface and endpoint descriptors */ + update_usb_intf_descr(dev); + + /* continue immediately with external fw download */ + set_bit (KEVENT_EXTERNAL_FW, &dev->kevent_flags); +#else + /* kernel >= 2.6.8 */ + NEW_STATE(dev, WAIT_FOR_DISCONNECT); +#endif + } + + if (test_bit(KEVENT_EXTERNAL_FW, &dev->kevent_flags)) { + u8 op_mode; + + clear_bit(KEVENT_EXTERNAL_FW, &dev->kevent_flags); + + op_mode = get_op_mode(dev->udev); + dbg(DBG_DEVSTART, "opmode %d", op_mode); + + if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) { + err("unexpected opmode %d", op_mode); + goto end_external_fw; + } + + if (dev->extfw && dev->extfw_size) { + ret = download_external_fw(dev->udev, dev->extfw, + dev->extfw_size); + if (ret < 0) { + err("Downloading external firmware failed: %d", ret); + goto end_external_fw; + } + if (dev->board_type == BOARDTYPE_505A_RFMD_2958) { + info("200 ms delay for board type 7"); + /* jal: can I do this in kevent ??? */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/5+1); + } + } + NEW_STATE(dev,INIT); + init_new_device(dev); + } +end_external_fw: + + if (test_bit(KEVENT_INTERNAL_FW, &dev->kevent_flags)) { + clear_bit(KEVENT_INTERNAL_FW, &dev->kevent_flags); + + dbg(DBG_DEVSTART, "downloading internal firmware"); + + ret=usbdfu_download(dev->udev, dev->intfw, + dev->intfw_size, + dev->board_type == BOARDTYPE_505A_RFMD_2958 ? 2000: 0); + + if (ret < 0) { + err("downloading internal fw failed with %d",ret); + goto end_internal_fw; + } + + dbg(DBG_DEVSTART, "sending REMAP"); + + /* no REMAP for 505A (see SF driver) */ + if (dev->board_type != BOARDTYPE_505A_RFMD_2958) + if ((ret=at76c503_remap(dev->udev)) < 0) { + err("sending REMAP failed with %d",ret); + goto end_internal_fw; + } + + dbg(DBG_DEVSTART, "sleeping for 2 seconds"); + NEW_STATE(dev,EXTFW_DOWNLOAD); + mod_timer(&dev->fw_dl_timer, jiffies+2*HZ+1); + } +end_internal_fw: + + up(&dev->sem); + + dbg(DBG_KEVENT, "%s: kevent exit flags: 0x%lx", dev->netdev->name, + dev->kevent_flags); + + return; +} + +static int essid_matched(struct at76c503 *dev, struct bss_info *ptr) +{ + /* common criteria for both modi */ + + int retval = (dev->essid_size == 0 /* ANY ssid */ || + (dev->essid_size == ptr->ssid_len && + !memcmp(dev->essid, ptr->ssid, ptr->ssid_len))); + if (!retval) + dbg(DBG_BSS_MATCH, "%s bss table entry %p: essid didn't match", + dev->netdev->name, ptr); + return retval; +} + +static inline int mode_matched(struct at76c503 *dev, struct bss_info *ptr) +{ + int retval; + + if (dev->iw_mode == IW_MODE_ADHOC) + retval = ptr->capa & WLAN_CAPABILITY_IBSS; + else + retval = ptr->capa & WLAN_CAPABILITY_ESS; + if (!retval) + dbg(DBG_BSS_MATCH, "%s bss table entry %p: mode didn't match", + dev->netdev->name, ptr); + return retval; +} + +static int rates_matched(struct at76c503 *dev, struct bss_info *ptr) +{ + int i; + u8 *rate; + + for(i=0,rate=ptr->rates; i < ptr->rates_len; i++,rate++) + if (*rate & 0x80) { + /* this is a basic rate we have to support + (see IEEE802.11, ch. 7.3.2.2) */ + if (*rate != (0x80|hw_rates[0]) && *rate != (0x80|hw_rates[1]) && + *rate != (0x80|hw_rates[2]) && *rate != (0x80|hw_rates[3])) { + dbg(DBG_BSS_MATCH, + "%s: bss table entry %p: basic rate %02x not supported", + dev->netdev->name, ptr, *rate); + return 0; + } + } + /* if we use short preamble, the bss must support it */ + if (dev->preamble_type == PREAMBLE_TYPE_SHORT && + !(ptr->capa & WLAN_CAPABILITY_SHORT_PREAMBLE)) { + dbg(DBG_BSS_MATCH, "%s: %p does not support short preamble", + dev->netdev->name, ptr); + return 0; + } else + return 1; +} + +static inline int wep_matched(struct at76c503 *dev, struct bss_info *ptr) +{ + if (!dev->wep_enabled && + ptr->capa & WLAN_CAPABILITY_PRIVACY) { + /* we have disabled WEP, but the BSS signals privacy */ + dbg(DBG_BSS_MATCH, "%s: bss table entry %p: requires encryption", + dev->netdev->name, ptr); + return 0; + } + /* otherwise if the BSS does not signal privacy it may well + accept encrypted packets from us ... */ + return 1; +} + +static inline int bssid_matched(struct at76c503 *dev, struct bss_info *ptr) +{ + if (!dev->wanted_bssid_valid || + !memcmp(ptr->bssid, dev->wanted_bssid, ETH_ALEN)) { + return 1; + } else { + if (at76_debug & DBG_BSS_MATCH) { + dbg_uc("%s: requested bssid - %s does not match", + dev->netdev->name, mac2str(dev->wanted_bssid)); + dbg_uc(" AP bssid - %s of bss table entry %p", + mac2str(ptr->bssid), ptr); + } + return 0; + } +} + +static void dump_bss_table(struct at76c503 *dev, int force_output) +{ + struct bss_info *ptr; + /* hex dump output buffer for debug */ + unsigned long flags; + struct list_head *lptr; + + if ((at76_debug & DBG_BSS_TABLE) || (force_output)) { + spin_lock_irqsave(&dev->bss_list_spinlock, flags); + + dbg_uc("%s BSS table (curr=%p, new=%p):", dev->netdev->name, + dev->curr_bss, dev->new_bss); + + list_for_each(lptr, &dev->bss_list) { + ptr = list_entry(lptr, struct bss_info, list); + dbg_uc("0x%p: bssid %s channel %d ssid %s (%s)" + " capa x%04x rates %s rssi %d link %d noise %d", + ptr, mac2str(ptr->bssid), + ptr->channel, + ptr->ssid, + hex2str(dev->obuf, ptr->ssid, + min((sizeof(dev->obuf)-1)/2, + (size_t)ptr->ssid_len),'\0'), + ptr->capa, + hex2str(dev->obuf_s, ptr->rates, + min(sizeof(dev->obuf_s)/3, + (size_t)ptr->rates_len), ' '), + ptr->rssi, ptr->link_qual, ptr->noise_level); + } + + spin_unlock_irqrestore(&dev->bss_list_spinlock, flags); + } +} + +/* try to find a matching bss in dev->bss, starting at position start. + returns the ptr to a matching bss in the list or + NULL if none found */ +/* last is the last bss tried, last == NULL signals a new round, + starting with list_entry(dev->bss_list.next, ...) */ +/* this proc must be called inside an acquired dev->bss_list_spinlock + otherwise the timeout on bss may remove the newly chosen entry ! */ +static struct bss_info *find_matching_bss(struct at76c503 *dev, + struct bss_info *last) +{ + struct bss_info *ptr = NULL; + struct list_head *curr; + + curr = last != NULL ? last->list.next : dev->bss_list.next; + while (curr != &dev->bss_list) { + ptr = list_entry(curr, struct bss_info, list); + if (essid_matched(dev,ptr) && + mode_matched(dev,ptr) && + wep_matched(dev,ptr) && + rates_matched(dev,ptr) && + bssid_matched(dev,ptr)) + break; + curr = curr->next; + } + + if (curr == &dev->bss_list) + ptr = NULL; + /* otherwise ptr points to the struct bss_info we have chosen */ + + dbg(DBG_BSS_TABLE, "%s %s: returned %p", dev->netdev->name, + __FUNCTION__, ptr); + return ptr; +} /* find_matching_bss */ + + +/* we got an association response */ +static void rx_mgmt_assoc(struct at76c503 *dev, + struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *mgmt = + (struct ieee80211_hdr_3addr *)buf->packet; + struct ieee802_11_assoc_resp *resp = + (struct ieee802_11_assoc_resp *)mgmt->payload; + u16 assoc_id = le16_to_cpu(resp->assoc_id); + u16 status = le16_to_cpu(resp->status); + u16 capa = le16_to_cpu(resp->capability); + dbg(DBG_RX_MGMT, "%s: rx AssocResp bssid %s capa x%04x status x%04x " + "assoc_id x%04x rates %s", + dev->netdev->name, mac2str(mgmt->addr3), capa, status, assoc_id, + hex2str(dev->obuf, resp->data+2, + min((size_t)*(resp->data+1),(sizeof(dev->obuf)-1)/2), '\0')); + LOCK_ISTATE() + if (dev->istate == ASSOCIATING) { + UNLOCK_ISTATE() + assert(dev->curr_bss != NULL); + if (dev->curr_bss == NULL) + return; + + if (status == WLAN_STATUS_SUCCESS) { + struct bss_info *ptr = dev->curr_bss; + ptr->assoc_id = assoc_id & 0x3fff; + /* update iwconfig params */ + memcpy(dev->bssid, ptr->bssid, ETH_ALEN); + memcpy(dev->essid, ptr->ssid, ptr->ssid_len); + dev->essid_size = ptr->ssid_len; + dev->channel = ptr->channel; + defer_kevent(dev,KEVENT_ASSOC_DONE); + } else { + NEW_STATE(dev,JOINING); + defer_kevent(dev,KEVENT_JOIN); + } + del_timer_sync(&dev->mgmt_timer); + } else { + UNLOCK_ISTATE() + info("%s: AssocResp in state %d ignored", + dev->netdev->name, dev->istate); + } +} /* rx_mgmt_assoc */ + +static void rx_mgmt_reassoc(struct at76c503 *dev, + struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *mgmt = + (struct ieee80211_hdr_3addr *)buf->packet; + struct ieee802_11_assoc_resp *resp = + (struct ieee802_11_assoc_resp *)mgmt->payload; + unsigned long flags; + u16 capa = le16_to_cpu(resp->capability); + u16 status = le16_to_cpu(resp->status); + u16 assoc_id = le16_to_cpu(resp->assoc_id); + + dbg(DBG_RX_MGMT, "%s: rx ReAssocResp bssid %s capa x%04x status x%04x " + "assoc_id x%04x rates %s", + dev->netdev->name, mac2str(mgmt->addr3), capa, status, assoc_id, + hex2str(dev->obuf, resp->data+2, + min((size_t)*(resp->data+1),(sizeof(dev->obuf)-1)/2), '\0')); + LOCK_ISTATE() + if (dev->istate == REASSOCIATING) { + UNLOCK_ISTATE() + assert(dev->new_bss != NULL); + if (dev->new_bss == NULL) + return; + + if (status == WLAN_STATUS_SUCCESS) { + struct bss_info *bptr = dev->new_bss; + bptr->assoc_id = assoc_id; + NEW_STATE(dev,CONNECTED); + + iwevent_bss_connect(dev->netdev,bptr->bssid); + + spin_lock_irqsave(&dev->bss_list_spinlock, flags); + dev->curr_bss = dev->new_bss; + dev->new_bss = NULL; + spin_unlock_irqrestore(&dev->bss_list_spinlock, flags); + + /* get ESSID, BSSID and channel for dev->curr_bss */ + dev->essid_size = bptr->ssid_len; + memcpy(dev->essid, bptr->ssid, bptr->ssid_len); + memcpy(dev->bssid, bptr->bssid, ETH_ALEN); + dev->channel = bptr->channel; + dbg(DBG_PROGRESS, "%s: reassociated to BSSID %s", + dev->netdev->name, mac2str(dev->bssid)); + defer_kevent(dev, KEVENT_ASSOC_DONE); + } else { + del_timer_sync(&dev->mgmt_timer); + NEW_STATE(dev,JOINING); + defer_kevent(dev,KEVENT_JOIN); + } + } else { + info("%s: ReAssocResp in state %d ignored", + dev->netdev->name, dev->istate); + UNLOCK_ISTATE() + } +} /* rx_mgmt_reassoc */ + +static void rx_mgmt_disassoc(struct at76c503 *dev, + struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *mgmt = + (struct ieee80211_hdr_3addr *)buf->packet; + struct ieee802_11_disassoc_frame *resp = + (struct ieee802_11_disassoc_frame *)mgmt->payload; + + dbg(DBG_RX_MGMT, "%s: rx DisAssoc bssid %s reason x%04x destination %s", + dev->netdev->name, mac2str(mgmt->addr3), + le16_to_cpu(resp->reason), + hex2str(dev->obuf, mgmt->addr1, + min((int)sizeof(dev->obuf)/3, ETH_ALEN), ':')); + LOCK_ISTATE() + if (dev->istate == SCANNING || dev->istate == INIT) { + UNLOCK_ISTATE() + return; + } + UNLOCK_ISTATE() + + assert(dev->curr_bss != NULL); + if (dev->curr_bss == NULL) + return; + LOCK_ISTATE() + if (dev->istate == REASSOCIATING) { + UNLOCK_ISTATE() + assert(dev->new_bss != NULL); + if (dev->new_bss == NULL) + return; + } else + UNLOCK_ISTATE() + if (!memcmp(mgmt->addr3, dev->curr_bss->bssid, ETH_ALEN) && + (!memcmp(dev->netdev->dev_addr, mgmt->addr1, ETH_ALEN) || + !memcmp(bc_addr, mgmt->addr1, ETH_ALEN))) { + /* this is a DisAssoc from the BSS we are connected or + trying to connect to, directed to us or broadcasted */ + /* jal: TODO: can the DisAssoc also come from the BSS + we've sent a ReAssocReq to (i.e. from dev->new_bss) ? */ + LOCK_ISTATE() + if (dev->istate == DISASSOCIATING || + dev->istate == ASSOCIATING || + dev->istate == REASSOCIATING || + dev->istate == CONNECTED || + dev->istate == JOINING) + { + if (dev->istate == CONNECTED) { + UNLOCK_ISTATE() + netif_carrier_off(dev->netdev); + netif_stop_queue(dev->netdev); + iwevent_bss_disconnect(dev->netdev); + } else UNLOCK_ISTATE() + del_timer_sync(&dev->mgmt_timer); + NEW_STATE(dev,JOINING); + defer_kevent(dev,KEVENT_JOIN); + } else { + + /* ignore DisAssoc in states AUTH, ASSOC */ + info("%s: DisAssoc in state %d ignored", + dev->netdev->name, dev->istate); + UNLOCK_ISTATE() + } + } + /* ignore DisAssoc to other STA or from other BSSID */ +} /* rx_mgmt_disassoc */ + +static void rx_mgmt_auth(struct at76c503 *dev, + struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *mgmt = + (struct ieee80211_hdr_3addr *)buf->packet; + struct ieee802_11_auth_frame *resp = + (struct ieee802_11_auth_frame *)mgmt->payload; + int seq_nr = le16_to_cpu(resp->seq_nr); + int alg = le16_to_cpu(resp->algorithm); + int status = le16_to_cpu(resp->status); + + dbg(DBG_RX_MGMT, "%s: rx AuthFrame bssid %s alg %d seq_nr %d status %d " + "destination %s", + dev->netdev->name, mac2str(mgmt->addr3), + alg, seq_nr, status, + hex2str(dev->obuf, mgmt->addr1, + min((int)sizeof(dev->obuf)/3, ETH_ALEN), ':')); + + if (alg == WLAN_AUTH_SHARED_KEY && + seq_nr == 2) { + dbg(DBG_RX_MGMT, "%s: AuthFrame challenge %s ...", + dev->netdev->name, + hex2str(dev->obuf, resp->challenge, + min((int)sizeof(dev->obuf)/3,18), ' ')); + } + LOCK_ISTATE() + if (dev->istate != AUTHENTICATING) { + info("%s: ignored AuthFrame in state %d", + dev->netdev->name, dev->istate); + UNLOCK_ISTATE() + return; + } + UNLOCK_ISTATE() + if (dev->auth_mode != alg) { + info("%s: ignored AuthFrame for alg %d", + dev->netdev->name, alg); + return; + } + + assert(dev->curr_bss != NULL); + if (dev->curr_bss == NULL) + return; + + if (!memcmp(mgmt->addr3, dev->curr_bss->bssid, ETH_ALEN) && + !memcmp(dev->netdev->dev_addr, mgmt->addr1, ETH_ALEN)) { + /* this is a AuthFrame from the BSS we are connected or + trying to connect to, directed to us */ + if (status != WLAN_STATUS_SUCCESS) { + del_timer_sync(&dev->mgmt_timer); + /* try to join next bss */ + NEW_STATE(dev,JOINING); + defer_kevent(dev,KEVENT_JOIN); + return; + } + + if (dev->auth_mode == WLAN_AUTH_OPEN || + seq_nr == 4) { + dev->retries = ASSOC_RETRIES; + NEW_STATE(dev,ASSOCIATING); + assoc_req(dev, dev->curr_bss); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", + __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer,jiffies+HZ); + return; + } + + assert(seq_nr == 2); + auth_req(dev, dev->curr_bss, seq_nr+1, resp->challenge); + dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", + __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer,jiffies+HZ); + } + /* else: ignore AuthFrames to other recipients */ +} /* rx_mgmt_auth */ + +static void rx_mgmt_deauth(struct at76c503 *dev, + struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *mgmt = + (struct ieee80211_hdr_3addr *)buf->packet; + struct ieee802_11_deauth_frame *resp = + (struct ieee802_11_deauth_frame *)mgmt->payload; + + dbg(DBG_RX_MGMT|DBG_PROGRESS, + "%s: rx DeAuth bssid %s reason x%04x destination %s", + dev->netdev->name, mac2str(mgmt->addr3), + le16_to_cpu(resp->reason), + hex2str(dev->obuf, mgmt->addr1, + min((int)sizeof(dev->obuf)/3,ETH_ALEN), ':')); + LOCK_ISTATE() + if (dev->istate == DISASSOCIATING || + dev->istate == AUTHENTICATING || + dev->istate == ASSOCIATING || + dev->istate == REASSOCIATING || + dev->istate == CONNECTED) { + UNLOCK_ISTATE() + assert(dev->curr_bss != NULL); + if (dev->curr_bss == NULL) + return; + + if (!memcmp(mgmt->addr3, dev->curr_bss->bssid, ETH_ALEN) && + (!memcmp(dev->netdev->dev_addr, mgmt->addr1, ETH_ALEN) || + !memcmp(bc_addr, mgmt->addr1, ETH_ALEN))) { + /* this is a DeAuth from the BSS we are connected or + trying to connect to, directed to us or broadcasted */ + LOCK_ISTATE() + if (dev->istate == CONNECTED) { + UNLOCK_ISTATE() + iwevent_bss_disconnect(dev->netdev); + } else UNLOCK_ISTATE() + NEW_STATE(dev,JOINING); + defer_kevent(dev,KEVENT_JOIN); + del_timer_sync(&dev->mgmt_timer); + } + /* ignore DeAuth to other STA or from other BSSID */ + } else { + /* ignore DeAuth in states SCANNING */ + info("%s: DeAuth in state %d ignored", + dev->netdev->name, dev->istate); + UNLOCK_ISTATE() + } +} /* rx_mgmt_deauth */ + +static void rx_mgmt_beacon(struct at76c503 *dev, + struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *mgmt = + (struct ieee80211_hdr_3addr *)buf->packet; + + /* beacon content */ + struct ieee802_11_beacon_data *bdata = + (struct ieee802_11_beacon_data *)mgmt->payload; + + /* length of var length beacon parameters */ + int varpar_len = min(le16_to_cpu(buf->wlength) - + (int)(IEEE802_11_MGMT_HEADER_SIZE + + offsetof(struct ieee802_11_beacon_data, data)), + BEACON_MAX_DATA_LENGTH); + + struct list_head *lptr; + struct bss_info *match; /* entry matching addr3 with its bssid */ + int new_entry = 0; + int len; + struct data_element { + u8 type; + u8 length; + u8 data_head; + } *element; + int have_ssid = 0; + int have_rates = 0; + int have_channel = 0; + int keep_going = 1; + unsigned long flags; + + spin_lock_irqsave(&dev->bss_list_spinlock, flags); + LOCK_ISTATE() + if (dev->istate == CONNECTED) { + UNLOCK_ISTATE() + /* in state CONNECTED we use the mgmt_timer to control + the beacon of the BSS */ + assert(dev->curr_bss != NULL); + if (dev->curr_bss == NULL) + goto rx_mgmt_beacon_end; + if (!memcmp(dev->curr_bss->bssid, mgmt->addr3, ETH_ALEN)) { + //dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer " + // "+BEACON_TIMEOUT*HZ", __FUNCTION__, __LINE__); + mod_timer(&dev->mgmt_timer, jiffies+BEACON_TIMEOUT*HZ); + dev->curr_bss->rssi = buf->rssi; + dev->beacons_received++; + goto rx_mgmt_beacon_end; + } + } else + UNLOCK_ISTATE() + + /* look if we have this BSS already in the list */ + match = NULL; + + if (!list_empty(&dev->bss_list)) { + list_for_each(lptr, &dev->bss_list) { + struct bss_info *bss_ptr = + list_entry(lptr, struct bss_info, list); + if (!memcmp(bss_ptr->bssid, mgmt->addr3, ETH_ALEN)) { + match = bss_ptr; + break; + } + } + } + + if (match == NULL) { + /* haven't found the bss in the list */ + if ((match=kmalloc(sizeof(struct bss_info), GFP_ATOMIC)) == NULL) { + dbg(DBG_BSS_TABLE, "%s: cannot kmalloc new bss info (%zd byte)", + dev->netdev->name, sizeof(struct bss_info)); + goto rx_mgmt_beacon_end; + } + memset(match,0,sizeof(*match)); + new_entry = 1; + /* append new struct into list */ + list_add_tail(&match->list, &dev->bss_list); + } + + /* we either overwrite an existing entry or append a new one + match points to the entry in both cases */ + + match->capa = le16_to_cpu(bdata->capability_information); + + /* while beacon_interval is not (!) */ + match->beacon_interval = le16_to_cpu(bdata->beacon_interval); + + match->rssi = buf->rssi; + match->link_qual = buf->link_quality; + match->noise_level = buf->noise_level; + + memcpy(match->mac,mgmt->addr2,ETH_ALEN); //just for info + memcpy(match->bssid,mgmt->addr3,ETH_ALEN); + dbg(DBG_RX_BEACON, "%s: bssid %s", dev->netdev->name, + mac2str(match->bssid)); + + element = (struct data_element*)bdata->data; + +#define data_end(element) (&(element->data_head) + element->length) + + // This routine steps through the bdata->data array to try and get + // some useful information about the access point. + // Currently, this implementation supports receipt of: SSID, + // supported transfer rates and channel, in any order, with some + // tolerance for intermittent unknown codes (although this + // functionality may not be necessary as the useful information will + // usually arrive in consecutively, but there have been some + // reports of some of the useful information fields arriving in a + // different order). + // It does not support any more IE types although MFIE_TYPE_TIM may + // be supported (on my AP at least). + // The bdata->data array is about 1500 bytes long but only ~36 of those + // bytes are useful, hence the have_ssid etc optimizations. + + while (keep_going && + ((int)(data_end(element) - bdata->data) <= varpar_len)) { + + switch (element->type) { + + case MFIE_TYPE_SSID: + len = min(IW_ESSID_MAX_SIZE, (int)element->length); + if (!have_ssid && ((new_entry) || + !is_cloaked_ssid(&(element->data_head), len))) { + /* we copy only if this is a new entry, + or the incoming SSID is not a cloaked SSID. This + will protect us from overwriting a real SSID read + in a ProbeResponse with a cloaked one from a + following beacon. */ + + match->ssid_len = len; + memcpy(match->ssid, &(element->data_head), len); + match->ssid[len] = '\0'; /* terminate the + string for + printing */ + dbg(DBG_RX_BEACON, "%s: SSID - %s", + dev->netdev->name, match->ssid); + } + have_ssid = 1; + break; + + case MFIE_TYPE_RATES: + if (!have_rates) { + match->rates_len = + min((int)sizeof(match->rates), + (int)element->length); + memcpy(match->rates, &(element->data_head), + match->rates_len); + have_rates = 1; + dbg(DBG_RX_BEACON, + "%s: SUPPORTED RATES %s", + dev->netdev->name, + hex2str(dev->obuf, &(element->data_head), + min((sizeof(dev->obuf)-1)/2, + (size_t)element->length), '\0')); + } + break; + + case MFIE_TYPE_DS_SET: + if (!have_channel) { + match->channel = element->data_head; + have_channel = 1; + dbg(DBG_RX_BEACON, "%s: CHANNEL - %d", + dev->netdev->name, match->channel); + } + break; + + case MFIE_TYPE_CF_SET: + case MFIE_TYPE_TIM: + case MFIE_TYPE_IBSS_SET: + default: + { + dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s", + dev->netdev->name, element->type, element->length, + hex2str(dev->obuf,&(element->data_head), + min((sizeof(dev->obuf)-1)/2, + (size_t)element->length),'\0')); + break; + } + + } // switch (element->type) + + // advance to the next 'element' of data + element = (struct data_element*)data_end(element); + + // Optimization: after all, the bdata->data array is + // varpar_len bytes long, whereas we get all of the useful + // information after only ~36 bytes, this saves us a lot of + // time (and trouble as the remaining portion of the array + // could be full of junk) + // Comment this out if you want to see what other information + // comes from the AP - although little of it may be useful + + //if (have_ssid && have_rates && have_channel) + // keep_going = 0; + } + + dbg(DBG_RX_BEACON, "%s: Finished processing beacon data", + dev->netdev->name); + + match->last_rx = jiffies; /* record last rx of beacon */ + +rx_mgmt_beacon_end: + spin_unlock_irqrestore(&dev->bss_list_spinlock, flags); +} /* rx_mgmt_beacon */ + + +/* calc the link level from a given rx_buffer */ +static void calc_level(struct at76c503 *dev, struct at76c503_rx_buffer *buf, struct iw_quality* qual) +{ int max_rssi = 42; /* just a gues for now, might be different for other chips */ + + qual->level = (buf->rssi * 100 / max_rssi); + if (qual->level > 100) + qual->level = 100; + qual->updated |= IW_QUAL_LEVEL_UPDATED; +} + + +/* calc the link quality from a given rx_buffer */ +static void calc_qual(struct at76c503 *dev, struct at76c503_rx_buffer *buf, struct iw_quality* qual) +{ + if((dev->board_type == BOARDTYPE_503_INTERSIL_3861) || + (dev->board_type == BOARDTYPE_503_INTERSIL_3863)) { + qual->qual=buf->link_quality; + } else { + qual->qual = qual->level * dev->beacons_received * + dev->beacon_period / + (jiffies_to_msecs(jiffies) - dev->beacons_last_qual); + + dev->beacons_last_qual = jiffies_to_msecs(jiffies); + dev->beacons_received = 0; + } + qual->qual = (qual->qual > 100) ? 100 : qual->qual; + qual->updated |= IW_QUAL_QUAL_UPDATED; +} + + +/* calc the noise quality from a given rx_buffer */ +static void calc_noise(struct at76c503 *dev, struct at76c503_rx_buffer *buf, struct iw_quality* qual) +{ + qual->noise = 0; + qual->updated |= IW_QUAL_NOISE_INVALID; +} + + +static void update_wstats(struct at76c503 *dev, struct at76c503_rx_buffer *buf) +{ + struct iw_quality *qual = &dev->wstats.qual; + + if (buf->rssi && dev->istate == CONNECTED) { + qual->updated = 0; + calc_level(dev, buf, qual); + calc_qual(dev, buf, qual); + calc_noise(dev, buf, qual); + } else { + qual->qual = 0; + qual->level = 0; + qual->noise = 0; + qual->updated = IW_QUAL_ALL_INVALID; + } +} + +static void rx_mgmt(struct at76c503 *dev, struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *mgmt = + (struct ieee80211_hdr_3addr *)buf->packet; + u16 subtype = le16_to_cpu(mgmt->frame_ctl) & IEEE80211_FCTL_STYPE; + + /* update wstats */ + LOCK_ISTATE() + if (dev->istate != INIT && dev->istate != SCANNING) { + UNLOCK_ISTATE() + /* jal: this is a dirty hack needed by Tim in ad-hoc mode */ + if (dev->iw_mode == IW_MODE_ADHOC || + (dev->curr_bss != NULL && + !memcmp(mgmt->addr3, dev->curr_bss->bssid, ETH_ALEN))) { + /* Data packets always seem to have a 0 link level, so we + only read link quality info from management packets. + Atmel driver actually averages the present, and previous + values, we just present the raw value at the moment - TJS */ + + update_wstats(dev, buf); + } + } else UNLOCK_ISTATE() + + if (at76_debug & DBG_RX_MGMT_CONTENT) { + dbg_uc("%s rx mgmt subtype x%x %s", + dev->netdev->name, subtype, + hex2str(dev->obuf, (u8 *)mgmt, + min((sizeof(dev->obuf)-1)/2, + (size_t)le16_to_cpu(buf->wlength)), '\0')); + } + + switch (subtype) { + case IEEE80211_STYPE_BEACON: + case IEEE80211_STYPE_PROBE_RESP: + rx_mgmt_beacon(dev,buf); + break; + + case IEEE80211_STYPE_ASSOC_RESP: + rx_mgmt_assoc(dev,buf); + break; + + case IEEE80211_STYPE_REASSOC_RESP: + rx_mgmt_reassoc(dev,buf); + break; + + case IEEE80211_STYPE_DISASSOC: + rx_mgmt_disassoc(dev,buf); + break; + + case IEEE80211_STYPE_AUTH: + rx_mgmt_auth(dev,buf); + break; + + case IEEE80211_STYPE_DEAUTH: + rx_mgmt_deauth(dev,buf); + break; + + default: + info("%s: mgmt, but not beacon, subtype = %x", + dev->netdev->name, subtype); + } + + return; +} + +static void dbg_dumpbuf(const char *tag, const u8 *buf, int size) +{ + int i; + + if (!at76_debug) return; + + for (i=0; i <-- 6 --> <-- 2 --> <-46-1500-> + + Type 0x80 0x00 = TCP/IP + Type 0x06 0x00 = XNS + Type 0x81 0x37 = Novell NetWare + + +802.3 + + +---------+---------+---------+---------- + | Dst | Src | Length | Data... + +---------+---------+---------+---------- + + <-- 6 --> <-- 6 --> <-- 2 --> <-46-1500-> + +802.2 (802.3 with 802.2 header) + + +---------+---------+---------+-------+-------+-------+---------- + | Dst | Src | Length | DSAP | SSAP |Control| Data... + +---------+---------+---------+-------+-------+-------+---------- + + <- 1 -> <- 1 -> <- 1 -> <-43-1497-> + +SNAP (802.3 with 802.2 and SNAP headers) + + +---------+---------+---------+-------+-------+-------+-----------+---------+----------- + | Dst | Src | Length | 0xAA | 0xAA | 0x03 | Org Code | Type | Data... + +---------+---------+---------+-------+-------+-------+-----------+---------+----------- + + <-- 3 --> <-- 2 --> <-38-1492-> + +*/ + +/* Convert the 802.11 header on a packet into an ethernet-style header + * (basically, pretend we're an ethernet card receiving ethernet packets) + * + * This routine returns with the skbuff pointing to the actual data (just past + * the end of the newly-created ethernet header). + */ +static void ieee80211_to_eth(struct sk_buff *skb, int iw_mode) +{ + struct ieee80211_hdr_3addr *i802_11_hdr; + struct ethhdr *eth_hdr_p; + u8 *src_addr; + u8 *dest_addr; + __be16 proto = 0; + int build_ethhdr = 1; + + i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data; + +#ifdef DEBUG + { + dbg_uc("%s: ENTRY skb len %d data %s", __FUNCTION__, + skb->len, hex2str(dev->obuf, skb->data, + min((int)sizeof(dev->obuf)/3,64), ' ')); + } +#endif + + skb_pull(skb, sizeof(struct ieee80211_hdr_3addr)); +// skb_trim(skb, skb->len - 4); /* Trim CRC */ + + src_addr = iw_mode == IW_MODE_ADHOC ? i802_11_hdr->addr2 + : i802_11_hdr->addr3; + dest_addr = i802_11_hdr->addr1; + + eth_hdr_p = (struct ethhdr *)skb->data; + if (!memcmp(eth_hdr_p->h_source, src_addr, ETH_ALEN) && + !memcmp(eth_hdr_p->h_dest, dest_addr, ETH_ALEN)) { + /* An ethernet frame is encapsulated within the data portion. + * Just use its header instead. */ + skb_pull(skb, sizeof(struct ethhdr)); + build_ethhdr = 0; + } else if (!memcmp(skb->data, snapsig, sizeof(snapsig))) { + /* SNAP frame - collapse it */ + skb_pull(skb, sizeof(rfc1042sig)+2); + proto = *(__be16 *)(skb->data - 2); + } else { +#ifdef IEEE_STANDARD + /* According to all standards, we should assume the data + * portion contains 802.2 LLC information, so we should give it + * an 802.3 header (which has the same implications) */ + proto = htons(skb->len); +#else /* IEEE_STANDARD */ + /* Unfortunately, it appears no actual 802.11 implementations + * follow any standards specs. They all appear to put a + * 16-bit ethertype after the 802.11 header instead, so we take + * that value and make it into an Ethernet-II packet. */ + /* Note that this means we can never support non-SNAP 802.2 + * frames (because we can't tell when we get one) */ + + /* jal: This isn't true. My WRT54G happily sends SNAP. + Difficult to speak for all APs, so I don't dare to define + IEEE_STANDARD ... */ + proto = *(__be16 *)(skb->data); + skb_pull(skb, 2); +#endif /* IEEE_STANDARD */ + } + + skb_reset_mac_header(skb); + eth_hdr_p = eth_hdr(skb); + if (build_ethhdr) { + /* This needs to be done in this order (eth_hdr_p->h_dest may + * overlap src_addr) */ + memcpy(eth_hdr_p->h_source, src_addr, ETH_ALEN); + memcpy(eth_hdr_p->h_dest, dest_addr, ETH_ALEN); + /* make an 802.3 header (proto = length) */ + eth_hdr_p->h_proto = proto; + } + + if (ntohs(eth_hdr_p->h_proto) > 1518) { + skb->protocol = eth_hdr_p->h_proto; + } else if (*(unsigned short *)skb->data == 0xFFFF) { + /* Magic hack for Novell IPX-in-802.3 packets */ + skb->protocol = htons(ETH_P_802_3); + } else { + /* Assume it's an 802.2 packet (it should be, and we have no + * good way to tell if it isn't) */ + skb->protocol = htons(ETH_P_802_2); + } + +#ifdef DEBUG + { + char da[3*ETH_ALEN], sa[3*ETH_ALEN]; + dbg_uc("%s: EXIT skb da %s sa %s proto x%04x len %d data %s", __FUNCTION__, + hex2str(da, eth_hdr(skb)->h_dest, ETH_ALEN, ':'), + hex2str(sa, eth_hdr(skb)->h_source, ETH_ALEN, ':'), + ntohs(skb->protocol), skb->len, + hex2str(dev->obuf, skb->data, + min((int)sizeof(dev->obuf)/3,64), ' ')); + } +#endif + +} + +/* Adjust the skb to trim the hardware header and CRC, and set up skb->mac, + * skb->protocol, etc. + */ +static void ieee80211_fixup(struct sk_buff *skb, int iw_mode) +{ + struct ieee80211_hdr_3addr *i802_11_hdr; + struct ethhdr *eth_hdr_p; + u8 *src_addr; + u8 *dest_addr; + __be16 proto = 0; + + i802_11_hdr = (struct ieee80211_hdr_3addr *)eth_hdr(skb); + skb_pull(skb, sizeof(struct ieee80211_hdr_3addr)); +// skb_trim(skb, skb->len - 4); /* Trim CRC */ + + src_addr = iw_mode == IW_MODE_ADHOC ? i802_11_hdr->addr2 + : i802_11_hdr->addr3; + dest_addr = i802_11_hdr->addr1; + + skb_reset_mac_header(skb); + eth_hdr_p = eth_hdr(skb); + if (!memcmp(eth_hdr_p->h_source, src_addr, ETH_ALEN) && + !memcmp(eth_hdr_p->h_dest, dest_addr, ETH_ALEN)) { + /* There's an ethernet header encapsulated within the data + * portion, count it as part of the hardware header */ + skb_pull(skb, sizeof(struct ethhdr)); + proto = eth_hdr_p->h_proto; + } else if (!memcmp(skb->data, snapsig, sizeof(snapsig))) { + /* SNAP frame - collapse it */ + /* RFC1042/802.1h encapsulated packet. Treat the SNAP header + * as part of the HW header and note the protocol. */ + /* NOTE: prism2 doesn't collapse Appletalk frames (why?). */ + skb_pull(skb, sizeof(rfc1042sig) + 2); + proto = *(__be16 *)(skb->data - 2); + } + + if (ntohs(proto) > 1518) { + skb->protocol = proto; + } else { +#ifdef IEEE_STANDARD + /* According to all standards, we should assume the data + * portion contains 802.2 LLC information */ + skb->protocol = htons(ETH_P_802_2); +#else /* IEEE_STANDARD */ + /* Unfortunately, it appears no actual 802.11 implementations + * follow any standards specs. They all appear to put a + * 16-bit ethertype after the 802.11 header instead, so we'll + * use that (and consider it part of the hardware header). */ + /* Note that this means we can never support non-SNAP 802.2 + * frames (because we can't tell when we get one) */ + skb->protocol = *(__be16 *)skb->data; + skb_pull(skb, 2); +#endif /* IEEE_STANDARD */ + } +} + +/* check for fragmented data in dev->rx_skb. If the packet was no fragment + or it was the last of a fragment set a skb containing the whole packet + is returned for further processing. Otherwise we get NULL and are + done and the packet is either stored inside the fragment buffer + or thrown away. The check for rx_copybreak is moved here. + Every returned skb starts with the ieee802_11 header and contains + _no_ FCS at the end */ +static struct sk_buff *check_for_rx_frags(struct at76c503 *dev) +{ + struct sk_buff *skb = (struct sk_buff *)dev->rx_skb; + struct at76c503_rx_buffer *buf = (struct at76c503_rx_buffer *)skb->data; + struct ieee80211_hdr_3addr *i802_11_hdr = + (struct ieee80211_hdr_3addr *)buf->packet; + /* seq_ctrl, fragment_number, sequence number of new packet */ + u16 sctl = le16_to_cpu(i802_11_hdr->seq_ctl); + u16 fragnr = sctl & 0xf; + u16 seqnr = sctl>>4; + u16 frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl); + + /* length including the IEEE802.11 header, excl. the trailing FCS, + excl. the struct at76c503_rx_buffer */ + int length = le16_to_cpu(buf->wlength) - dev->rx_data_fcs_len; + + /* where does the data payload start in skb->data ? */ + u8 *data = (u8 *)i802_11_hdr + sizeof(struct ieee80211_hdr_3addr); + + /* length of payload, excl. the trailing FCS */ + int data_len = length - (data - (u8 *)i802_11_hdr); + + int i; + struct rx_data_buf *bptr, *optr; + unsigned long oldest = ~0UL; + + dbg(DBG_RX_FRAGS, "%s: rx data frame_ctl %04x addr2 %s seq/frag %d/%d " + "length %d data %d: %s ...", + dev->netdev->name, frame_ctl, + mac2str(i802_11_hdr->addr2), + seqnr, fragnr, length, data_len, + hex2str(dev->obuf, data, + min((int)(sizeof(dev->obuf)-1)/2,32), '\0')); + + dbg(DBG_RX_FRAGS_SKB, "%s: incoming skb: head %p data %p " + "tail %lu end %lu len %d", + dev->netdev->name, skb->head, skb->data, (unsigned long)skb->tail, + (unsigned long)skb->end, skb->len); + + if (data_len <= 0) { + /* buffers contains no data */ + info("%s: rx skb without data", dev->netdev->name); + return NULL; + } + + if (fragnr == 0 && !(frame_ctl & IEEE80211_FCTL_MOREFRAGS)) { + /* unfragmented packet received */ + if (length < rx_copybreak && (skb = dev_alloc_skb(length)) != NULL) { + memcpy(skb_put(skb, length), + dev->rx_skb->data + AT76C503_RX_HDRLEN, length); + } else { + skb_pull(skb, AT76C503_RX_HDRLEN); + skb_trim(skb, length); + /* Use a new skb for the next receive */ + dev->rx_skb = NULL; + } + + dbg(DBG_RX_FRAGS, "%s: unfragmented", dev->netdev->name); + + return skb; + } + + /* remove the at76c503_rx_buffer header - we don't need it anymore */ + /* we need the IEEE802.11 header (for the addresses) if this packet + is the first of a chain */ + + assert(length > AT76C503_RX_HDRLEN); + skb_pull(skb, AT76C503_RX_HDRLEN); + /* remove FCS at end */ + skb_trim(skb, length); + + dbg(DBG_RX_FRAGS_SKB, "%s: trimmed skb: head %p data %p tail %lu " + "end %lu len %d data %p data_len %d", + dev->netdev->name, skb->head, skb->data, (unsigned long)skb->tail, + (unsigned long)skb->end, skb->len, data, data_len); + + /* look if we've got a chain for the sender address. + afterwards optr points to first free or the oldest entry, + or, if i < NR_RX_DATA_BUF, bptr points to the entry for the + sender address */ + /* determining the oldest entry doesn't cope with jiffies wrapping + but I don't care to delete a young entry at these rare moments ... */ + + for(i=0,bptr=dev->rx_data,optr=NULL; i < NR_RX_DATA_BUF; i++,bptr++) { + if (bptr->skb != NULL) { + if (!memcmp(i802_11_hdr->addr2, bptr->sender,ETH_ALEN)) + break; + else + if (optr == NULL) { + optr = bptr; + oldest = bptr->last_rx; + } else { + if (bptr->last_rx < oldest) + optr = bptr; + } + } else { + optr = bptr; + oldest = 0UL; + } + } + + if (i < NR_RX_DATA_BUF) { + + dbg(DBG_RX_FRAGS, "%s: %d. cacheentry (seq/frag=%d/%d) " + "matched sender addr", + dev->netdev->name, i, bptr->seqnr, bptr->fragnr); + + /* bptr points to an entry for the sender address */ + if (bptr->seqnr == seqnr) { + int left; + /* the fragment has the current sequence number */ + if (((bptr->fragnr+1)&0xf) == fragnr) { + bptr->last_rx = jiffies; + /* the next following fragment number -> + add the data at the end */ + /* is & 0xf necessary above ??? */ + + // for test only ??? + if ((left=skb_tailroom(bptr->skb)) < data_len) { + info("%s: only %d byte free (need %d)", + dev->netdev->name, left, data_len); + } else + memcpy(skb_put(bptr->skb, data_len), + data, data_len); + bptr->fragnr = fragnr; + if (!(frame_ctl & + IEEE80211_FCTL_MOREFRAGS)) { + /* this was the last fragment - send it */ + skb = bptr->skb; + bptr->skb = NULL; /* free the entry */ + dbg(DBG_RX_FRAGS, "%s: last frag of seq %d", + dev->netdev->name, seqnr); + return skb; + } else + return NULL; + } else { + /* wrong fragment number -> ignore it */ + dbg(DBG_RX_FRAGS, "%s: frag nr does not match: %d+1 != %d", + dev->netdev->name, bptr->fragnr, fragnr); + return NULL; + } + } else { + /* got another sequence number */ + if (fragnr == 0) { + /* it's the start of a new chain - replace the + old one by this */ + /* bptr->sender has the correct value already */ + dbg(DBG_RX_FRAGS, "%s: start of new seq %d, " + "removing old seq %d", dev->netdev->name, + seqnr, bptr->seqnr); + bptr->seqnr = seqnr; + bptr->fragnr = 0; + bptr->last_rx = jiffies; + /* swap bptr->skb and dev->rx_skb */ + skb = bptr->skb; + bptr->skb = dev->rx_skb; + dev->rx_skb = skb; + } else { + /* it from the middle of a new chain -> + delete the old entry and skip the new one */ + dbg(DBG_RX_FRAGS, "%s: middle of new seq %d (%d) " + "removing old seq %d", dev->netdev->name, + seqnr, fragnr, bptr->seqnr); + dev_kfree_skb(bptr->skb); + bptr->skb = NULL; + } + return NULL; + } + } else { + /* if we didn't find a chain for the sender address optr + points either to the first free or the oldest entry */ + + if (fragnr != 0) { + /* this is not the begin of a fragment chain ... */ + dbg(DBG_RX_FRAGS, "%s: no chain for non-first fragment (%d)", + dev->netdev->name, fragnr); + return NULL; + } + assert(optr != NULL); + if (optr == NULL) + return NULL; + + if (optr->skb != NULL) { + /* swap the skb's */ + skb = optr->skb; + optr->skb = dev->rx_skb; + dev->rx_skb = skb; + + dbg(DBG_RX_FRAGS, "%s: free old contents: sender %s seq/frag %d/%d", + dev->netdev->name, mac2str(optr->sender), + optr->seqnr, optr->fragnr); + + } else { + /* take the skb from dev->rx_skb */ + optr->skb = dev->rx_skb; + dev->rx_skb = NULL; /* let submit_rx_urb() allocate a new skb */ + + dbg(DBG_RX_FRAGS, "%s: use a free entry", dev->netdev->name); + } + memcpy(optr->sender, i802_11_hdr->addr2, ETH_ALEN); + optr->seqnr = seqnr; + optr->fragnr = 0; + optr->last_rx = jiffies; + + return NULL; + } +} /* check_for_rx_frags */ + +/* rx interrupt: we expect the complete data buffer in dev->rx_skb */ +static void rx_data(struct at76c503 *dev) +{ + struct net_device *netdev = (struct net_device *)dev->netdev; + struct net_device_stats *stats = &dev->stats; + struct sk_buff *skb = dev->rx_skb; + struct at76c503_rx_buffer *buf = (struct at76c503_rx_buffer *)skb->data; + struct ieee80211_hdr_3addr *i802_11_hdr; + int length = le16_to_cpu(buf->wlength); + + if (at76_debug & DBG_RX_DATA) { + dbg_uc("%s received data packet:", netdev->name); + dbg_dumpbuf(" rxhdr", skb->data, AT76C503_RX_HDRLEN); + } + if (at76_debug & DBG_RX_DATA_CONTENT) + dbg_dumpbuf("packet", skb->data + AT76C503_RX_HDRLEN, + length); + + if ((skb=check_for_rx_frags(dev)) == NULL) + return; + + /* if an skb is returned, the at76c503a_rx_header and the FCS is already removed */ + i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data; + + skb->dev = netdev; + skb->ip_summed = CHECKSUM_NONE; /* TODO: should check CRC */ + + if (i802_11_hdr->addr1[0] & 1) { + if (!memcmp(i802_11_hdr->addr1, netdev->broadcast, ETH_ALEN)) + skb->pkt_type = PACKET_BROADCAST; + else + skb->pkt_type = PACKET_MULTICAST; + } else if (memcmp(i802_11_hdr->addr1, netdev->dev_addr, ETH_ALEN)) { + skb->pkt_type=PACKET_OTHERHOST; + } + + if (netdev->type == ARPHRD_ETHER) { + ieee80211_to_eth(skb, dev->iw_mode); + } else { + ieee80211_fixup(skb, dev->iw_mode); + } + + netdev->last_rx = jiffies; + netif_rx(skb); + stats->rx_packets++; + stats->rx_bytes += length; + + return; +} + +static int submit_rx_urb(struct at76c503 *dev) +{ + int ret, size; + struct sk_buff *skb = dev->rx_skb; + + if (dev->read_urb == NULL) { + err("%s: dev->read_urb is NULL", __FUNCTION__); + return -EFAULT; + } + + if (skb == NULL) { + skb = dev_alloc_skb(sizeof(struct at76c503_rx_buffer)); + if (skb == NULL) { + err("%s: unable to allocate rx skbuff.", dev->netdev->name); + ret = -ENOMEM; + goto exit; + } + dev->rx_skb = skb; + } else { + skb_push(skb, skb_headroom(skb)); + skb_trim(skb, 0); + } + + size = skb_tailroom(skb); + FILL_BULK_URB(dev->read_urb, dev->udev, + usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), + skb_put(skb, size), size, + (usb_complete_t)at76c503_read_bulk_callback, dev); + ret = usb_submit_urb(dev->read_urb, GFP_ATOMIC); + if (ret < 0) { + if (ret == -ENODEV) + dbg(DBG_DEVSTART, "usb_submit_urb returned -ENODEV"); + else + err("%s: rx, usb_submit_urb failed: %d", dev->netdev->name, ret); + } + +exit: + if (ret < 0) { + if (ret != -ENODEV) { + /* If we can't submit the URB, the adapter becomes completely + * useless, so try again later */ + if (--dev->nr_submit_rx_tries > 0) + defer_kevent(dev, KEVENT_SUBMIT_RX); + else { + err("%s: giving up to submit rx urb after %d failures -" + " please unload the driver and/or power cycle the device", + dev->netdev->name, NR_SUBMIT_RX_TRIES); + } + } + } else + /* reset counter to initial value */ + dev->nr_submit_rx_tries = NR_SUBMIT_RX_TRIES; + return ret; +} + + +/* we are doing a lot of things here in an interrupt. Need + a bh handler (Watching TV with a TV card is probably + a good test: if you see flickers, we are doing too much. + Currently I do see flickers... even with our tasklet :-( ) + Maybe because the bttv driver and usb-uhci use the same interrupt +*/ +/* Or maybe because our BH handler is preempting bttv's BH handler.. BHs don't + * solve everything.. (alex) */ +static void at76c503_read_bulk_callback (struct urb *urb) +{ + struct at76c503 *dev = (struct at76c503 *)urb->context; + + dev->rx_urb = urb; + tasklet_schedule(&dev->tasklet); + + return; +} + +static void rx_monitor_mode(struct at76c503 *dev) +{ + struct net_device *netdev = (struct net_device *)dev->netdev; + struct at76c503_rx_buffer *buf = + (struct at76c503_rx_buffer *)dev->rx_skb->data; + /* length including the IEEE802.11 header, excl. the trailing FCS, + excl. the struct at76c503_rx_buffer */ + int length = le16_to_cpu(buf->wlength) - dev->rx_data_fcs_len; + struct sk_buff *skb = dev->rx_skb; + struct net_device_stats *stats = &dev->stats; + struct iw_statistics *wstats = &dev->wstats; + + update_wstats(dev, buf); + + if (length < 0) { + /* buffer contains no data */ + dbg(DBG_MONITOR_MODE, "%s: MONITOR MODE: rx skb without data", + dev->netdev->name); + return; + } + + if (netdev->type == ARPHRD_IEEE80211_PRISM) { + int skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) + length; + p80211msg_lnxind_wlansniffrm_t *prism; + u8* payload; + + if ((skb = dev_alloc_skb(skblen)) == NULL) { + err("%s: MONITOR MODE: dev_alloc_skb for Prism header " + "returned NULL", dev->netdev->name); + return; + } + + skb_put(skb, skblen); + + prism = (p80211msg_lnxind_wlansniffrm_t*)skb->data; + payload = skb->data + sizeof(p80211msg_lnxind_wlansniffrm_t); + + prism->msgcode = DIDmsg_lnxind_wlansniffrm; + prism->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t); + strcpy(prism->devname, netdev->name); + + prism->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + prism->hosttime.status = 0; + prism->hosttime.len = 4; + prism->hosttime.data = jiffies; + + prism->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + prism->mactime.status = 0; + prism->mactime.len = 4; + memcpy(&prism->mactime.data, buf->rx_time, 4); + + prism->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + prism->channel.status = P80211ENUM_msgitem_status_no_value; + prism->channel.len = 4; + /* INFO: The channel is encoded in the beacon info. + (Kismet can figure it out, so less processing here) */ + prism->channel.data = 0; + + prism->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + prism->rssi.status = 0; + prism->rssi.len = 4; + prism->rssi.data = buf->rssi; + + prism->sq.did = DIDmsg_lnxind_wlansniffrm_sq; + prism->sq.status = 0; + prism->sq.len = 4; + prism->sq.data = wstats->qual.qual; + + prism->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + prism->signal.status = 0; + prism->signal.len = 4; + prism->signal.data = wstats->qual.level; + + prism->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + prism->noise.status = 0; + prism->noise.len = 4; + prism->noise.data = wstats->qual.noise; + + prism->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + prism->rate.status = 0; + prism->rate.len = 4; + prism->rate.data = hw_rates[buf->rx_rate] & (~0x80); + + prism->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + prism->istx.status = 0; + prism->istx.len = 4; + prism->istx.data = P80211ENUM_truth_false; + + prism->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + prism->frmlen.status = 0; + prism->frmlen.len = 4; + prism->frmlen.data = length; + + memcpy(payload, buf->packet, length); + } else { + /* netdev->type != ARPHRD_IEEE80211_PRISM */ + skb_pull(skb, AT76C503_RX_HDRLEN); + skb_trim(skb, length); + dev->rx_skb = NULL; + } + + skb->dev = netdev; + skb->ip_summed = CHECKSUM_NONE; + skb_reset_mac_header(skb); + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_80211_RAW); + + netdev->last_rx = jiffies; + netif_rx(skb); + stats->rx_packets++; + stats->rx_bytes += length; +} /* end of rx_monitor_mode */ + + +static void rx_tasklet(unsigned long param) +{ + struct at76c503 *dev = (struct at76c503 *)param; + struct urb *urb; + struct net_device *netdev; + struct at76c503_rx_buffer *buf; + struct ieee80211_hdr_3addr *i802_11_hdr; + u16 frame_ctl; + + if (!dev) return; + urb = dev->rx_urb; + netdev = (struct net_device *)dev->netdev; + + if (dev->device_unplugged) { + dbg(DBG_DEVSTART, "device unplugged"); + if (urb) + dbg(DBG_DEVSTART, "urb status %d", urb->status); + return; + } + + + if(!urb || !dev->rx_skb || !netdev || !dev->rx_skb->data) return; + + buf = (struct at76c503_rx_buffer *)dev->rx_skb->data; + + if (!buf) return; + + i802_11_hdr = (struct ieee80211_hdr_3addr *)buf->packet; + if (!i802_11_hdr) return; + + frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl); + + if(urb->status != 0){ + if ((urb->status != -ENOENT) && + (urb->status != -ECONNRESET)) { + dbg(DBG_URB,"%s %s: - nonzero read bulk status received: %d", + __FUNCTION__, netdev->name, urb->status); + goto no_more_urb; + } + return; + } + + if (at76_debug & DBG_RX_ATMEL_HDR) { + dbg_uc("%s: rx frame: rate %d rssi %d noise %d link %d %s", + dev->netdev->name, + buf->rx_rate, buf->rssi, buf->noise_level, + buf->link_quality, + hex2str(dev->obuf,(u8 *)i802_11_hdr, + min((int)(sizeof(dev->obuf)-1)/2,48),'\0')); + } + LOCK_ISTATE() + if (dev->istate == MONITORING) { + UNLOCK_ISTATE() + rx_monitor_mode(dev); + goto finish; + } + UNLOCK_ISTATE() + + /* there is a new bssid around, accept it: */ + if(buf->newbss && dev->iw_mode == IW_MODE_ADHOC) { + dbg(DBG_PROGRESS, "%s: rx newbss", netdev->name); + defer_kevent(dev, KEVENT_NEW_BSS); + } + + switch (frame_ctl & IEEE80211_FCTL_FTYPE) { + case IEEE80211_FTYPE_DATA: + rx_data(dev); + break; + + case IEEE80211_FTYPE_MGMT: + /* jal: TODO: find out if we can update iwspy also on + other frames than management (might depend on the + radio chip / firmware version !) */ + + iwspy_update(dev, buf); + + rx_mgmt(dev, buf); + break; + + case IEEE80211_FTYPE_CTL: + dbg(DBG_RX_CTRL, "%s: ignored ctrl frame: %04x", dev->netdev->name, + frame_ctl); + break; + + default: + info("%s: it's a frame from mars: %2x", dev->netdev->name, + frame_ctl); + } /* switch (frame_ctl & IEEE80211_FCTL_FTYPE) */ +finish: + submit_rx_urb(dev); + no_more_urb: + return; +} + +static void at76c503_write_bulk_callback (struct urb *urb) +{ + struct at76c503 *dev = (struct at76c503 *)urb->context; + struct net_device_stats *stats = &dev->stats; + unsigned long flags; + struct at76c503_tx_buffer *mgmt_buf; + int ret; + + if(urb->status != 0){ + if((urb->status != -ENOENT) && + (urb->status != -ECONNRESET)) { + dbg(DBG_URB, "%s - nonzero write bulk status received: %d", + __FUNCTION__, urb->status); + }else + return; /* urb has been unlinked */ + stats->tx_errors++; + }else + stats->tx_packets++; + + spin_lock_irqsave(&dev->mgmt_spinlock, flags); + mgmt_buf = dev->next_mgmt_bulk; + dev->next_mgmt_bulk = NULL; + spin_unlock_irqrestore(&dev->mgmt_spinlock, flags); + + if (mgmt_buf) { + /* we don't copy the padding bytes, but add them + to the length */ + memcpy(dev->bulk_out_buffer, mgmt_buf, + le16_to_cpu(mgmt_buf->wlength) + + offsetof(struct at76c503_tx_buffer,packet)); + FILL_BULK_URB(dev->write_urb, dev->udev, + usb_sndbulkpipe(dev->udev, + dev->bulk_out_endpointAddr), + dev->bulk_out_buffer, + le16_to_cpu(mgmt_buf->wlength) + + mgmt_buf->padding + AT76C503_TX_HDRLEN, + (usb_complete_t)at76c503_write_bulk_callback, dev); + ret = usb_submit_urb(dev->write_urb, GFP_ATOMIC); + if (ret) { + err("%s: %s error in tx submit urb: %d", + dev->netdev->name, __FUNCTION__, ret); + } + kfree(mgmt_buf); + } else + netif_wake_queue(dev->netdev); + +} + +#ifdef CONFIG_IPAQ_HANDHELD + +static struct timer_list led_timer; + +static void +ipaq_clear_led (unsigned long time) +{ + ipaq_led_off (RED_LED_2); +} + +static void +ipaq_blink_led (void) +{ + ipaq_led_on (RED_LED_2); + + mod_timer (&led_timer, jiffies + (HZ / 25)); +} + +static void +ipaq_init_led (void) +{ + led_timer.function = ipaq_clear_led; + + init_timer (&led_timer); +} + +#endif + +static int at76c503_tx(struct sk_buff *skb, struct net_device *netdev) +{ + struct at76c503 *dev = (struct at76c503 *)(netdev->priv); + struct net_device_stats *stats = &dev->stats; + int ret = 0; + int wlen; + int submit_len; + struct at76c503_tx_buffer *tx_buffer = + (struct at76c503_tx_buffer *)dev->bulk_out_buffer; + struct ieee80211_hdr_3addr *i802_11_hdr = + (struct ieee80211_hdr_3addr *)&(tx_buffer->packet); + u8 *payload = tx_buffer->packet + sizeof(struct ieee80211_hdr_3addr); + + if (netif_queue_stopped(netdev)) { + err("%s: %s called while netdev is stopped", netdev->name, + __FUNCTION__); + //skip this packet + dev_kfree_skb(skb); + return 0; + } + + if (dev->write_urb->status == -EINPROGRESS) { + err("%s: %s called while dev->write_urb is pending for tx", + netdev->name, __FUNCTION__); + //skip this packet + dev_kfree_skb(skb); + return 0; + } + + if (skb->len < 2*ETH_ALEN) { + err("%s: %s: skb too short (%d)", dev->netdev->name, + __FUNCTION__, skb->len); + dev_kfree_skb(skb); + return 0; + } + +#ifdef CONFIG_IPAQ_HANDHELD + if (machine_is_h5400 ()) + ipaq_blink_led (); +#endif + + /* we can get rid of memcpy, if we set netdev->hard_header_len + to 8 + sizeof(struct ieee80211_hdr_3addr), because then we have + enough space */ + // dbg(DBG_TX, "skb->data - skb->head = %d", skb->data - skb->head); + + if (ntohs(*(__be16 *)(skb->data + 2*ETH_ALEN)) <= 1518) { + /* this is a 802.3 packet */ + if (skb->data[2*ETH_ALEN+2] == rfc1042sig[0] && + skb->data[2*ETH_ALEN+2+1] == rfc1042sig[1]) { + /* higher layer delivered SNAP header - keep it */ + memcpy(payload, skb->data + 2*ETH_ALEN+2, skb->len - 2*ETH_ALEN -2); + wlen = sizeof(struct ieee80211_hdr_3addr) + skb->len - 2*ETH_ALEN -2; + } else { + err("%s: %s: no support for non-SNAP 802.2 packets " + "(DSAP x%02x SSAP x%02x cntrl x%02x)", + dev->netdev->name, __FUNCTION__, + skb->data[2*ETH_ALEN+2], skb->data[2*ETH_ALEN+2+1], + skb->data[2*ETH_ALEN+2+2]); + dev_kfree_skb(skb); + return 0; + } + } else { + /* add RFC 1042 header in front */ + memcpy(payload, rfc1042sig, sizeof(rfc1042sig)); + memcpy(payload + sizeof(rfc1042sig), + skb->data + 2*ETH_ALEN, skb->len - 2*ETH_ALEN); + wlen = sizeof(struct ieee80211_hdr_3addr) + sizeof(rfc1042sig) + + skb->len - 2*ETH_ALEN; + } + + /* make wireless header */ + i802_11_hdr->frame_ctl = + cpu_to_le16(IEEE80211_FTYPE_DATA | + (dev->wep_enabled ? IEEE80211_FCTL_PROTECTED : 0) | + (dev->iw_mode == IW_MODE_INFRA ? IEEE80211_FCTL_TODS : 0)); + + if(dev->iw_mode == IW_MODE_ADHOC){ + memcpy(i802_11_hdr->addr1, skb->data, ETH_ALEN); /* destination */ + memcpy(i802_11_hdr->addr2, skb->data+ETH_ALEN, ETH_ALEN); /* source */ + memcpy(i802_11_hdr->addr3, dev->bssid, ETH_ALEN); + }else if(dev->iw_mode == IW_MODE_INFRA){ + memcpy(i802_11_hdr->addr1, dev->bssid, ETH_ALEN); + memcpy(i802_11_hdr->addr2, skb->data+ETH_ALEN, ETH_ALEN); /* source */ + memcpy(i802_11_hdr->addr3, skb->data, ETH_ALEN); /* destination */ + } + + i802_11_hdr->duration_id = cpu_to_le16(0); + i802_11_hdr->seq_ctl = cpu_to_le16(0); + + /* setup 'Atmel' header */ + tx_buffer->wlength = cpu_to_le16(wlen); + tx_buffer->tx_rate = dev->txrate; + /* for broadcast destination addresses, the firmware 0.100.x + seems to choose the highest rate set with CMD_STARTUP in + basic_rate_set replacing this value */ + + memset(tx_buffer->reserved, 0, 4); + + tx_buffer->padding = calc_padding(wlen); + submit_len = wlen + AT76C503_TX_HDRLEN + tx_buffer->padding; + + { + dbg(DBG_TX_DATA_CONTENT, "%s skb->data %s", dev->netdev->name, + hex2str(dev->obuf, skb->data, + min((int)(sizeof(dev->obuf)-1)/2,32),'\0')); + dbg(DBG_TX_DATA, "%s tx wlen x%x pad x%x rate %d hdr %s", + dev->netdev->name, + le16_to_cpu(tx_buffer->wlength), + tx_buffer->padding, tx_buffer->tx_rate, + hex2str(dev->obuf, (u8 *)i802_11_hdr, + min((sizeof(dev->obuf)-1)/2, + sizeof(struct ieee80211_hdr_3addr)),'\0')); + dbg(DBG_TX_DATA_CONTENT, "%s payload %s", dev->netdev->name, + hex2str(dev->obuf, payload, + min((int)(sizeof(dev->obuf)-1)/2,48),'\0')); + } + + /* send stuff */ + netif_stop_queue(netdev); + netdev->trans_start = jiffies; + + FILL_BULK_URB(dev->write_urb, dev->udev, + usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), + tx_buffer, submit_len, + (usb_complete_t)at76c503_write_bulk_callback, dev); + ret = usb_submit_urb(dev->write_urb, GFP_ATOMIC); + if(ret){ + stats->tx_errors++; + err("%s: error in tx submit urb: %d", netdev->name, ret); + if (ret == -EINVAL) + err("-EINVAL: urb %p urb->hcpriv %p urb->complete %p", + dev->write_urb, + dev->write_urb ? dev->write_urb->hcpriv : (void *)-1, + dev->write_urb ? dev->write_urb->complete : (void *)-1); + goto err; + } + + stats->tx_bytes += skb->len; + + dev_kfree_skb(skb); + return 0; + + err: + return ret; +} + + +static void at76c503_tx_timeout(struct net_device *netdev) +{ + struct at76c503 *dev = (struct at76c503 *)(netdev->priv); + + if (!dev) + return; + warn("%s: tx timeout.", netdev->name); +#if WIRELESS_EXT < 17 + dev->write_urb->transfer_flags |= USB_ASYNC_UNLINK; +#endif + usb_unlink_urb(dev->write_urb); + dev->stats.tx_errors++; +} + +static int startup_device(struct at76c503 *dev) +{ + struct at76c503_card_config *ccfg = &dev->card_config; + int ret; + + if (at76_debug & DBG_PARAMS) { + char ossid[IW_ESSID_MAX_SIZE+1]; + + /* make dev->essid printable */ + assert(dev->essid_size <= IW_ESSID_MAX_SIZE); + memcpy(ossid, dev->essid, dev->essid_size); + ossid[dev->essid_size] = '\0'; + + dbg_uc("%s param: ssid %s (%s) mode %s ch %d wep %s key %d keylen %d", + dev->netdev->name, ossid, + hex2str(dev->obuf, dev->essid, + min((int)(sizeof(dev->obuf)-1)/2, + IW_ESSID_MAX_SIZE), '\0'), + dev->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra", + dev->channel, + dev->wep_enabled ? "enabled" : "disabled", + dev->wep_key_id, dev->wep_keys_len[dev->wep_key_id]); + dbg_uc("%s param: preamble %s rts %d retry %d frag %d " + "txrate %s auth_mode %d", + dev->netdev->name, + dev->preamble_type == PREAMBLE_TYPE_SHORT ? "short" : "long", + dev->rts_threshold, dev->short_retry_limit, + dev->frag_threshold, + dev->txrate == TX_RATE_1MBIT ? "1MBit" : + dev->txrate == TX_RATE_2MBIT ? "2MBit" : + dev->txrate == TX_RATE_5_5MBIT ? "5.5MBit" : + dev->txrate == TX_RATE_11MBIT ? "11MBit" : + dev->txrate == TX_RATE_AUTO ? "auto" : "", + dev->auth_mode); + dbg_uc("%s param: pm_mode %d pm_period %d auth_mode %s " + "scan_times %d %d scan_mode %s international_roaming %d", + dev->netdev->name, + dev->pm_mode, dev->pm_period_us, + dev->auth_mode == WLAN_AUTH_OPEN ? + "open" : "shared_secret", + dev->scan_min_time, dev->scan_max_time, + dev->scan_mode == SCAN_TYPE_ACTIVE ? "active" : "passive", + dev->international_roaming); + } + + memset(ccfg, 0, sizeof(struct at76c503_card_config)); + ccfg->promiscuous_mode = 0; + ccfg->short_retry_limit = dev->short_retry_limit; + //ccfg->long_retry_limit = dev->long_retry_limit; + + if (dev->wep_enabled) { + if (dev->wep_keys_len[dev->wep_key_id] > WEP_SMALL_KEY_LEN) + ccfg->encryption_type = 2; + else + ccfg->encryption_type = 1; + + /* jal: always exclude unencrypted if WEP is active */ + ccfg->exclude_unencrypted = 1; + } else { + ccfg->exclude_unencrypted = 0; + ccfg->encryption_type = 0; + } + + ccfg->rts_threshold = cpu_to_le16(dev->rts_threshold); + ccfg->fragmentation_threshold = cpu_to_le16(dev->frag_threshold); + + memcpy(ccfg->basic_rate_set, hw_rates, 4); + /* jal: really needed, we do a set_mib for autorate later ??? */ + ccfg->auto_rate_fallback = (dev->txrate == TX_RATE_AUTO ? 1 : 0); + ccfg->channel = dev->channel; + ccfg->privacy_invoked = dev->wep_enabled; + memcpy(ccfg->current_ssid, dev->essid, IW_ESSID_MAX_SIZE); + ccfg->ssid_len = dev->essid_size; + + ccfg->wep_default_key_id = dev->wep_key_id; + memcpy(ccfg->wep_default_key_value, dev->wep_keys, 4 * WEP_KEY_LEN); + + ccfg->short_preamble = dev->preamble_type; + ccfg->beacon_period = cpu_to_le16(dev->beacon_period); + + ret = set_card_command(dev->udev, CMD_STARTUP, (unsigned char *)&dev->card_config, + sizeof(struct at76c503_card_config)); + if(ret < 0){ + err("%s: set_card_command failed: %d", dev->netdev->name, ret); + return ret; + } + + wait_completion(dev, CMD_STARTUP); + + /* remove BSSID from previous run */ + memset(dev->bssid, 0, ETH_ALEN); + + if (set_radio(dev, 1) == 1) + wait_completion(dev, CMD_RADIO); + + if ((ret=set_preamble(dev, dev->preamble_type)) < 0) + return ret; + if ((ret=set_frag(dev, dev->frag_threshold)) < 0) + return ret; + + if ((ret=set_rts(dev, dev->rts_threshold)) < 0) + return ret; + + if ((ret=set_autorate_fallback(dev, dev->txrate == TX_RATE_AUTO ? 1 : 0)) < 0) + return ret; + + if ((ret=set_pm_mode(dev, dev->pm_mode)) < 0) + return ret; + + if ((ret=set_iroaming(dev, dev->international_roaming)) < 0) + return ret; + + if (at76_debug & DBG_MIB) + { + dump_mib_mac(dev); + dump_mib_mac_addr(dev); + dump_mib_mac_mgmt(dev); + dump_mib_mac_wep(dev); + dump_mib_mdomain(dev); + dump_mib_phy(dev); + dump_mib_local(dev); + } + + return 0; +} + +static int at76c503_open(struct net_device *netdev) +{ + struct at76c503 *dev = (struct at76c503 *)(netdev->priv); + int ret = 0; + + dbg(DBG_PROC_ENTRY, "at76c503_open entry"); + + if(down_interruptible(&dev->sem)) + return -EINTR; + + /* if netdev->dev_addr != dev->mac_addr we must + set the mac address in the device ! */ + if (memcmp(netdev->dev_addr, dev->mac_addr, ETH_ALEN)) { + if (set_mac_address(dev,netdev->dev_addr) >= 0) + dbg(DBG_PROGRESS, "%s: set new MAC addr %s", + netdev->name, mac2str(netdev->dev_addr)); + } + +#ifdef DEBUG //test only !!! + dump_mib_mac_addr(dev); +#endif + + dev->site_survey_state=SITE_SURVEY_IDLE; + dev->last_survey = jiffies; + dev->nr_submit_rx_tries = NR_SUBMIT_RX_TRIES; /* init counter */ + + if((ret=submit_rx_urb(dev)) < 0){ + err("%s: open: submit_rx_urb failed: %d", netdev->name, ret); + goto err; + } + + dev->open_count++; + + defer_kevent(dev, KEVENT_RESTART); + + dbg(DBG_PROC_ENTRY, "at76c503_open end"); + err: + up(&dev->sem); + return ret < 0 ? ret : 0; +} + +static int at76c503_stop(struct net_device *netdev) +{ + struct at76c503 *dev = (struct at76c503 *)(netdev->priv); + unsigned long flags; + + dbg(DBG_DEVSTART, "%s: ENTER", __FUNCTION__); + + if (down_interruptible(&dev->sem)) + return -EINTR; + + netif_stop_queue(netdev); + + NEW_STATE(dev,INIT); + + if (!(dev->device_unplugged)) { + /* we are called by "ifconfig wlanX down", not because the + device isn't avail. anymore */ + set_radio(dev, 0); + + /* we unlink the read urb, because the _open() + submits it again. _delete_device() takes care of the + read_urb otherwise. */ + usb_kill_urb(dev->read_urb); + } + + del_timer_sync(&dev->mgmt_timer); + + spin_lock_irqsave(&dev->mgmt_spinlock,flags); + if (dev->next_mgmt_bulk) { + kfree(dev->next_mgmt_bulk); + dev->next_mgmt_bulk = NULL; + } + spin_unlock_irqrestore(&dev->mgmt_spinlock,flags); + + /* free the bss_list */ + free_bss_list(dev); + + assert(dev->open_count > 0); + dev->open_count--; + + up(&dev->sem); + + dbg(DBG_DEVSTART, "%s: EXIT", __FUNCTION__); + + return 0; +} + +static struct net_device_stats *at76c503_get_stats(struct net_device *netdev) +{ + struct at76c503 *dev = (struct at76c503 *)netdev->priv; + + return &dev->stats; +} + +static struct iw_statistics *at76c503_get_wireless_stats(struct net_device *netdev) +{ + struct at76c503 *dev = (struct at76c503 *)netdev->priv; + + dbg(DBG_IOCTL, "RETURN qual %d level %d noise %d updated %d", + dev->wstats.qual.qual, dev->wstats.qual.level, + dev->wstats.qual.noise, dev->wstats.qual.updated); + + return &dev->wstats; +} + +static void at76c503_set_multicast(struct net_device *netdev) +{ + struct at76c503 *dev = (struct at76c503 *)netdev->priv; + int promisc; + + promisc = ((netdev->flags & IFF_PROMISC) != 0); + if(promisc != dev->promisc){ + /* grmbl. This gets called in interrupt. */ + dev->promisc = promisc; + defer_kevent(dev, KEVENT_SET_PROMISC); + } +} + +/* we only store the new mac address in netdev struct, + it got set when the netdev gets opened. */ +static int at76c503_set_mac_address(struct net_device *netdev, void *addr) +{ + struct sockaddr *mac = addr; + memcpy(netdev->dev_addr, mac->sa_data, ETH_ALEN); + return 1; +} + +/* == PROC iwspy_update == + check if we spy on the sender address of buf and update statistics */ +static void iwspy_update(struct at76c503 *dev, struct at76c503_rx_buffer *buf) +{ + struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)buf->packet; + struct iw_quality qual; + + /* We can only set the level here */ + qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; + qual.level = 0; + qual.noise = 0; + calc_level(dev, buf, &qual); + + spin_lock_bh(&(dev->spy_spinlock)); + + if (dev->spy_data.spy_number > 0) { + wireless_spy_update(dev->netdev, hdr->addr2, &qual); + } + spin_unlock_bh(&(dev->spy_spinlock)); +} /* iwspy_update */ + + +/******************************************************************************* + * structure that describes the private ioctls/iw handlers of this driver + */ +static const struct iw_priv_args at76c503_priv_args[] = { + { PRIV_IOCTL_SET_SHORT_PREAMBLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "short_preamble" }, // 0 - long, 1 -short + + { PRIV_IOCTL_SET_DEBUG, + // we must pass the new debug mask as a string, + // 'cause iwpriv cannot parse hex numbers + // starting with 0x :-( + IW_PRIV_TYPE_CHAR | 10, 0, + "set_debug"}, // set debug value + + { PRIV_IOCTL_SET_POWERSAVE_MODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "powersave_mode"}, // 1 - active, 2 - power save, + // 3 - smart power save + { PRIV_IOCTL_SET_SCAN_TIMES, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, + "scan_times"}, // min_channel_time, + // max_channel_time + { PRIV_IOCTL_SET_SCAN_MODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "scan_mode"}, // 0 - active, 1 - passive scan + + { PRIV_IOCTL_SET_INTL_ROAMING, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "intl_roaming"}, + + /* needed for Kismet, orinoco mode */ + { PRIV_IOCTL_SET_MONITOR_MODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, + "monitor"}, /* param1: monitor mode: 0 (off), 1 (on,Prism header), + 2 (on, no Prism header) + param2: channel (to start scan at) */ +}; + + +/******************************************************************************* + * at76c503 implementations of iw_handler functions: + */ +static int at76c503_iw_handler_commit(struct net_device *netdev, + struct iw_request_info *info, + void *null, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + unsigned long flags; + + dbg(DBG_IOCTL, "%s %s: restarting the device", netdev->name, + __FUNCTION__); + + // stop any pending tx bulk urb + //TODO + + // jal: TODO: protect access to dev->istate by a spinlock + // (ISR's on other processors may read/write it) + LOCK_ISTATE() + if (dev->istate != INIT) { + UNLOCK_ISTATE() + NEW_STATE(dev,INIT); + // stop pending management stuff + del_timer_sync(&dev->mgmt_timer); + + spin_lock_irqsave(&dev->mgmt_spinlock,flags); + if (dev->next_mgmt_bulk) { + kfree(dev->next_mgmt_bulk); + dev->next_mgmt_bulk = NULL; + } + spin_unlock_irqrestore(&dev->mgmt_spinlock,flags); + + netif_carrier_off(dev->netdev); + netif_stop_queue(dev->netdev); + } else UNLOCK_ISTATE() + + // do the restart after two seconds to catch + // following ioctl's (from more params of iwconfig) + // in _one_ restart + mod_timer(&dev->restart_timer, jiffies+2*HZ); + + return 0; +} + +static int at76c503_iw_handler_get_name(struct net_device *netdev, + struct iw_request_info *info, + char *name, + char *extra) +{ + strcpy(name, "IEEE 802.11b"); + + dbg(DBG_IOCTL, "%s: SIOCGIWNAME - name %s", netdev->name, name); + + return 0; +} + +static int at76c503_iw_handler_set_freq(struct net_device *netdev, + struct iw_request_info *info, + struct iw_freq *freq, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int chan = -1; + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - freq.m %d freq.e %d", netdev->name, + freq->m, freq->e); + + // modelled on orinoco.c + if ((freq->e == 0) && (freq->m <= 1000)) + { + // Setting by channel number + chan = freq->m; + } + else + { + // Setting by frequency - search the table + int mult = 1; + int i; + + for (i = 0; i < (6 - freq->e); i++) { + mult *= 10; + } + + for (i = 0; i < NUM_CHANNELS; i++) { + if (freq->m == (channel_frequency[i] * mult)) + chan = i + 1; + } + } + + if (chan < 1 || !dev->domain ) { + // non-positive channels are invalid + // we need a domain info to set the channel + // either that or an invalid frequency was + // provided by the user + ret = -EINVAL; + } else if (!dev->international_roaming) { + if (!(dev->domain->channel_map & (1 << (chan-1)))) { + info("%s: channel %d not allowed for domain %s " + "(and international_roaming is OFF)", + dev->netdev->name, chan, dev->domain->name); + ret = -EINVAL; + } + } + + if (ret == -EIWCOMMIT) { + dev->channel = chan; + dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - ch %d", netdev->name, chan); + } + + return ret; +} + +static int at76c503_iw_handler_get_freq(struct net_device *netdev, + struct iw_request_info *info, + struct iw_freq *freq, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + freq->m = dev->channel; + freq->e = 0; + + if (dev->channel) + { + dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - freq %ld x 10e%d", netdev->name, + channel_frequency[dev->channel - 1], 6); + } + dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - ch %d", netdev->name, dev->channel); + + return 0; +} + +static int at76c503_iw_handler_set_mode(struct net_device *netdev, + struct iw_request_info *info, + __u32 *mode, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: SIOCSIWMODE - %d", netdev->name, *mode); + + if ((*mode != IW_MODE_ADHOC) && (*mode != IW_MODE_INFRA) && + (*mode != IW_MODE_MONITOR)) { + ret = -EINVAL; + } else { + dev->iw_mode = *mode; + } + return ret; +} + +static int at76c503_iw_handler_get_mode(struct net_device *netdev, + struct iw_request_info *info, + __u32 *mode, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + *mode = dev->iw_mode; + + dbg(DBG_IOCTL, "%s: SIOCGIWMODE - %d", netdev->name, *mode); + + return 0; +} + +static int at76c503_iw_handler_get_range(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + // inspired by atmel.c + struct at76c503 *dev = (struct at76c503*)netdev->priv; + struct iw_range *range = (struct iw_range*)extra; + int i; + + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + + //TODO: range->throughput = xxxxxx; + + range->min_nwid = 0x0000; + range->max_nwid = 0x0000; + + // this driver doesn't maintain sensitivity information + range->sensitivity = 0; + + range->max_qual.qual = 100; + range->max_qual.level = 100; + range->max_qual.noise = 0; + range->max_qual.updated = IW_QUAL_NOISE_INVALID; + + range->avg_qual.qual = 50; + range->avg_qual.level = 50; + range->avg_qual.noise = 0; + range->avg_qual.updated = IW_QUAL_NOISE_INVALID; + + range->bitrate[0] = 1000000; + range->bitrate[1] = 2000000; + range->bitrate[2] = 5500000; + range->bitrate[3] = 11000000; + range->num_bitrates = 4; + + + range->min_rts = 0; + range->max_rts = MAX_RTS_THRESHOLD; + + range->min_frag = MIN_FRAG_THRESHOLD; + range->max_frag = MAX_FRAG_THRESHOLD; + + + //range->min_pmp = 0; + //range->max_pmp = 5000000; + //range->min_pmt = 0; + //range->max_pnt = 0; + //range->pmp_flags = IW_POWER_PERIOD; + //range->pmt_flags = 0; + //range->pm_capa = IW_POWER_PERIOD; + //TODO: find out what values we can use to describe PM capabilities + range->pmp_flags = IW_POWER_ON; + range->pmt_flags = IW_POWER_ON; + range->pm_capa = 0; + + + range->encoding_size[0] = WEP_SMALL_KEY_LEN; + range->encoding_size[1] = WEP_LARGE_KEY_LEN; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = WEP_KEYS; + //TODO: do we need this? what is a valid value if we don't support? + //range->encoding_login_index = -1; + + /* both WL-240U and Linksys WUSB11 v2.6 specify 15 dBm as output power + - take this for all (ignore antenna gains) */ + range->txpower[0] = 15; + range->num_txpower = 1; + range->txpower_capa = IW_TXPOW_DBM; + + // at time of writing (22/Feb/2004), version we intend to support + // is v16, + range->we_version_source = WIRELESS_EXT_SUPPORTED; + range->we_version_compiled = WIRELESS_EXT; + + // same as the values used in atmel.c + range->retry_capa = IW_RETRY_LIMIT ; + range->retry_flags = IW_RETRY_LIMIT; + range->r_time_flags = 0; + range->min_retry = 1; + range->max_retry = 255; + + + range->num_channels = NUM_CHANNELS; + range->num_frequency = 0; + + for (i = 0; + i < 32; //number of bits in reg_domain.channel_map + i++) + { + // test if channel map bit is raised + if (dev->domain->channel_map & (0x1 << i)) + { + range->num_frequency += 1; + + range->freq[i].i = i + 1; + range->freq[i].m = channel_frequency[i] * 100000; + range->freq[i].e = 1; // channel frequency*100000 * 10^1 + } + } + + dbg(DBG_IOCTL, "%s: SIOCGIWRANGE", netdev->name); + + return 0; +} + +static int at76c503_iw_handler_set_spy(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = 0; + + dbg(DBG_IOCTL, "%s: SIOCSIWSPY - number of addresses %d", + netdev->name, data->length); + + spin_lock_bh(&(dev->spy_spinlock)); + ret = iw_handler_set_spy(dev->netdev, info, (union iwreq_data *)data, + extra); + spin_unlock_bh(&(dev->spy_spinlock)); + + return ret; +} + +static int at76c503_iw_handler_get_spy(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = 0; + + spin_lock_bh(&(dev->spy_spinlock)); + ret = iw_handler_get_spy(dev->netdev, info, + (union iwreq_data *)data, extra); + spin_unlock_bh(&(dev->spy_spinlock)); + + dbg(DBG_IOCTL, "%s: SIOCGIWSPY - number of addresses %d", + netdev->name, data->length); + + return ret; +} + +static int at76c503_iw_handler_set_thrspy(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret; + + dbg(DBG_IOCTL, "%s: SIOCSIWTHRSPY - number of addresses %d)", + netdev->name, data->length); + + spin_lock_bh(&(dev->spy_spinlock)); + ret = iw_handler_set_thrspy(netdev, info, (union iwreq_data *)data, + extra); + spin_unlock_bh(&(dev->spy_spinlock)); + + return ret; +} + +static int at76c503_iw_handler_get_thrspy(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret; + + spin_lock_bh(&(dev->spy_spinlock)); + ret = iw_handler_get_thrspy(netdev, info, (union iwreq_data *)data, + extra); + spin_unlock_bh(&(dev->spy_spinlock)); + + dbg(DBG_IOCTL, "%s: SIOCGIWTHRSPY - number of addresses %d)", + netdev->name, data->length); + + return ret; +} + +static int at76c503_iw_handler_set_wap(struct net_device *netdev, + struct iw_request_info *info, + struct sockaddr *ap_addr, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + dbg(DBG_IOCTL, "%s: SIOCSIWAP - wap/bssid %s", netdev->name, + mac2str(ap_addr->sa_data)); + + // if the incoming address == ff:ff:ff:ff:ff:ff, the user has + // chosen any or auto AP preference + if (!memcmp(ap_addr->sa_data, bc_addr, ETH_ALEN) + || !memcmp(ap_addr->sa_data, off_addr, ETH_ALEN)) { + dev->wanted_bssid_valid = 0; + } else { + // user wants to set a preferred AP address + dev->wanted_bssid_valid = 1; + memcpy(dev->wanted_bssid, ap_addr->sa_data, ETH_ALEN); + } + + return -EIWCOMMIT; +} + +static int at76c503_iw_handler_get_wap(struct net_device *netdev, + struct iw_request_info *info, + struct sockaddr *ap_addr, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + ap_addr->sa_family = ARPHRD_ETHER; + memcpy(ap_addr->sa_data, dev->bssid, ETH_ALEN); + + dbg(DBG_IOCTL, "%s: SIOCGIWAP - wap/bssid %s", netdev->name, + mac2str(ap_addr->sa_data)); + + return 0; +} + + +static int at76c503_iw_handler_set_scan(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + unsigned long flags; + int ret = 0; +#if WIRELESS_EXT > 19 + struct iw_scan_req *req = NULL; +#endif + + dbg(DBG_IOCTL, "%s: SIOCSIWSCAN", netdev->name); + + if (!netif_running(netdev)) + return -ENETDOWN; + + /* jal: we don't allow "iwlist wlanX scan" while we are + in monitor mode */ + if (dev->iw_mode == IW_MODE_MONITOR) + return -EBUSY; + + /* Timeout old surveys. */ + if ((jiffies - dev->last_survey) > (20 * HZ)) + dev->site_survey_state = SITE_SURVEY_IDLE; + dev->last_survey = jiffies; + + /* Initiate a scan command */ + if (dev->site_survey_state == SITE_SURVEY_IN_PROGRESS) + return -EBUSY; + + dev->site_survey_state = SITE_SURVEY_IN_PROGRESS; + + // stop pending management stuff + del_timer_sync(&(dev->mgmt_timer)); + + spin_lock_irqsave(&(dev->mgmt_spinlock), flags); + if (dev->next_mgmt_bulk) { + kfree(dev->next_mgmt_bulk); + dev->next_mgmt_bulk = NULL; + } + spin_unlock_irqrestore(&(dev->mgmt_spinlock), flags); + + if (netif_running(dev->netdev)) { + // pause network activity + netif_carrier_off(dev->netdev); + netif_stop_queue(dev->netdev); + } +// Try to do passive or active scan if WE asks as. +#if WIRELESS_EXT > 19 + if (wrqu->data.length + && wrqu->data.length == sizeof(struct iw_scan_req)) { + req = (struct iw_scan_req *)extra; + + if (req->scan_type == IW_SCAN_TYPE_PASSIVE) + dev->scan_mode = SCAN_TYPE_PASSIVE; + else if (req->scan_type == IW_SCAN_TYPE_ACTIVE) + dev->scan_mode = SCAN_TYPE_ACTIVE; + + /* Sanity check values? */ + LOCK_ISTATE() + if (req->min_channel_time > 0) { + if (dev->istate == MONITORING) + dev->monitor_scan_min_time = req->min_channel_time; + else + dev->scan_min_time = req->min_channel_time; + } + if (req->max_channel_time > 0) { + if (dev->istate == MONITORING) + dev->monitor_scan_max_time = req->max_channel_time; + else + dev->scan_max_time = req->max_channel_time; + } + UNLOCK_ISTATE() + } +#endif + + // change to scanning state + NEW_STATE(dev, SCANNING); + defer_kevent(dev, KEVENT_SCAN); + + return ret; +} + +static int at76c503_iw_handler_get_scan(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + unsigned long flags; + struct list_head *lptr, *nptr; + struct bss_info *curr_bss; + struct iw_event *iwe = kmalloc(sizeof(struct iw_event), GFP_KERNEL); + char *curr_val, *curr_pos = extra; + int i; + + dbg(DBG_IOCTL, "%s: SIOCGIWSCAN", netdev->name); + + if (!iwe) + return -ENOMEM; + + if (dev->site_survey_state != SITE_SURVEY_COMPLETED) + /* scan not yet finished */ + return -EAGAIN; + + spin_lock_irqsave(&(dev->bss_list_spinlock), flags); + + list_for_each_safe(lptr, nptr, &(dev->bss_list)) { + curr_bss = list_entry(lptr, struct bss_info, list); + + iwe->cmd = SIOCGIWAP; + iwe->u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe->u.ap_addr.sa_data, curr_bss->bssid, 6); + curr_pos = iwe_stream_add_event(info, curr_pos, + extra + IW_SCAN_MAX_DATA, iwe, IW_EV_ADDR_LEN); + + iwe->u.data.length = curr_bss->ssid_len; + iwe->cmd = SIOCGIWESSID; + iwe->u.data.flags = 1; + + curr_pos = iwe_stream_add_point(info, curr_pos, + extra + IW_SCAN_MAX_DATA, iwe, curr_bss->ssid); + + iwe->cmd = SIOCGIWMODE; + iwe->u.mode = (curr_bss->capa & WLAN_CAPABILITY_IBSS) ? + IW_MODE_ADHOC : + (curr_bss->capa & WLAN_CAPABILITY_ESS) ? + IW_MODE_MASTER : + IW_MODE_AUTO; + // IW_MODE_AUTO = 0 which I thought is + // the most logical value to return in this case + curr_pos = iwe_stream_add_event(info, curr_pos, + extra + IW_SCAN_MAX_DATA, iwe, IW_EV_UINT_LEN); + + iwe->cmd = SIOCGIWFREQ; + iwe->u.freq.m = curr_bss->channel; + iwe->u.freq.e = 0; + curr_pos = iwe_stream_add_event(info, curr_pos, + extra + IW_SCAN_MAX_DATA, iwe, IW_EV_FREQ_LEN); + + iwe->cmd = SIOCGIWENCODE; + if (curr_bss->capa & WLAN_CAPABILITY_PRIVACY) { + iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + } else { + iwe->u.data.flags = IW_ENCODE_DISABLED; + } + iwe->u.data.length = 0; + curr_pos = iwe_stream_add_point(info, curr_pos, + extra + IW_SCAN_MAX_DATA, iwe, NULL); + + /* Add quality statistics */ + iwe->cmd = IWEVQUAL; + iwe->u.qual.noise=0; + iwe->u.qual.updated=IW_QUAL_NOISE_INVALID | IW_QUAL_LEVEL_UPDATED; + iwe->u.qual.level = (curr_bss->rssi * 100 / 42); + if (iwe->u.qual.level > 100) + iwe->u.qual.level = 100; + if((dev->board_type == BOARDTYPE_503_INTERSIL_3861) || + (dev->board_type == BOARDTYPE_503_INTERSIL_3863)) { + iwe->u.qual.qual=curr_bss->link_qual; + } else { + iwe->u.qual.qual=0; + iwe->u.qual.updated |= IW_QUAL_QUAL_INVALID; + } + /* Add new value to event */ + curr_pos = iwe_stream_add_event(info, curr_pos, + extra + IW_SCAN_MAX_DATA, iwe, IW_EV_QUAL_LEN); + + /* Rate : stuffing multiple values in a single event require a bit + * more of magic - Jean II */ + curr_val = curr_pos + IW_EV_LCP_LEN; + + iwe->cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe->u.bitrate.fixed = iwe->u.bitrate.disabled = 0; + /* Max 8 values */ + for(i=0; i < curr_bss->rates_len; i++) { + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe->u.bitrate.value = + ((curr_bss->rates[i] & 0x7f) * 500000); + /* Add new value to event */ + curr_val = iwe_stream_add_value(info, curr_pos, curr_val, + extra + IW_SCAN_MAX_DATA, + iwe, IW_EV_PARAM_LEN); + } + + /* Check if we added any event */ + if ((curr_val - curr_pos) > IW_EV_LCP_LEN) + curr_pos = curr_val; + + + // more information may be sent back using IWECUSTOM + + } + + spin_unlock_irqrestore(&(dev->bss_list_spinlock), flags); + + data->length = (curr_pos - extra); + data->flags = 0; + + kfree(iwe); + return 0; +} + + +static int at76c503_iw_handler_set_essid(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + dbg(DBG_IOCTL, "%s: SIOCSIWESSID - %s", netdev->name, extra); + + if (data->flags) + { + memcpy(dev->essid, extra, data->length); + dev->essid_size = data->length; +#if WIRELESS_EXT < 21 + /* For historic reasons, the SSID length used to include one + * extra character, C string nul termination, even though SSID is + * really an octet string that should not be presented as a C + * string. WE-21 changes this to explicitly require the length + * _not_ to include nul termination, but for WE < 21, decrement + * the length count here to remove the nul termination. */ + dev->essid_size = max(dev->essid_size - 1, 0); +#endif + } + else + { + /* Use any SSID */ + dev->essid_size = 0; + } + + return -EIWCOMMIT; +} + +static int at76c503_iw_handler_get_essid(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + if (dev->essid_size) { + // not the ANY ssid in dev->essid + data->flags = 1; + data->length = dev->essid_size; + memcpy(extra, dev->essid, data->length); + extra[data->length] = '\0'; + data->length += 1; + } else { + // the ANY ssid was specified + LOCK_ISTATE() + if (dev->istate == CONNECTED && + dev->curr_bss != NULL) { + UNLOCK_ISTATE() + // report the SSID we have found + data->flags = 1; + data->length = dev->curr_bss->ssid_len; + memcpy(extra, dev->curr_bss->ssid, data->length); + extra[dev->curr_bss->ssid_len] = '\0'; + data->length += 1; + } else { + UNLOCK_ISTATE() + // report ANY back + data->flags=0; + data->length=0; + } + } + + dbg(DBG_IOCTL, "%s: SIOCGIWESSID - %s", netdev->name, extra); + + return 0; +} + +static int at76c503_iw_handler_set_nickname(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + dbg(DBG_IOCTL, "%s: SIOCSIWNICKN - %s", netdev->name, extra); + + // iwconfig gives length including 0 byte like in the case of essid + memcpy(dev->nickn, extra, data->length); + + return 0; +} + +static int at76c503_iw_handler_get_nickname(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + data->length = strlen(dev->nickn); + memcpy(extra, dev->nickn, data->length); + extra[data->length] = '\0'; + data->length += 1; + + dbg(DBG_IOCTL, "%s: SIOCGIWNICKN - %s", netdev->name, extra); + + return 0; +} + +static int at76c503_iw_handler_set_rate(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *bitrate, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: SIOCSIWRATE - %d", netdev->name, + bitrate->value); + + switch (bitrate->value) + { + case -1: dev->txrate = TX_RATE_AUTO; break; // auto rate + case 1000000: dev->txrate = TX_RATE_1MBIT; break; + case 2000000: dev->txrate = TX_RATE_2MBIT; break; + case 5500000: dev->txrate = TX_RATE_5_5MBIT; break; + case 11000000: dev->txrate = TX_RATE_11MBIT; break; + default: ret = -EINVAL; + } + + return ret; +} + +static int at76c503_iw_handler_get_rate(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *bitrate, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = 0; + + switch (dev->txrate) + { + // return max rate if RATE_AUTO + case TX_RATE_AUTO: bitrate->value = 11000000; break; + case TX_RATE_1MBIT: bitrate->value = 1000000; break; + case TX_RATE_2MBIT: bitrate->value = 2000000; break; + case TX_RATE_5_5MBIT: bitrate->value = 5500000; break; + case TX_RATE_11MBIT: bitrate->value = 11000000; break; + default: ret = -EINVAL; + } + + bitrate->fixed = (dev->txrate != TX_RATE_AUTO); + bitrate->disabled = 0; + + dbg(DBG_IOCTL, "%s: SIOCGIWRATE - %d", netdev->name, + bitrate->value); + + return ret; +} + +static int at76c503_iw_handler_set_rts(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *rts, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = -EIWCOMMIT; + int rthr = rts->value; + + dbg(DBG_IOCTL, "%s: SIOCSIWRTS - value %d disabled %s", + netdev->name, rts->value, + (rts->disabled) ? "true" : "false"); + + if (rts->disabled) + rthr = MAX_RTS_THRESHOLD; + + if ((rthr < 0) || (rthr > MAX_RTS_THRESHOLD)) { + ret = -EINVAL; + } else { + dev->rts_threshold = rthr; + } + + return ret; +} + +static int at76c503_iw_handler_get_rts(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *rts, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + rts->value = dev->rts_threshold; + rts->disabled = (rts->value >= MAX_RTS_THRESHOLD); + rts->fixed = 1; + + dbg(DBG_IOCTL, "%s: SIOCGIWRTS - value %d disabled %s", + netdev->name, rts->value, + (rts->disabled) ? "true" : "false"); + + return 0; +} + +static int at76c503_iw_handler_set_frag(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *frag, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = -EIWCOMMIT; + int fthr = frag->value; + + dbg(DBG_IOCTL, "%s: SIOCSIWFRAG - value %d, disabled %s", + netdev->name, frag->value, + (frag->disabled) ? "true" : "false"); + + if(frag->disabled) + fthr = MAX_FRAG_THRESHOLD; + + if ((fthr < MIN_FRAG_THRESHOLD) || (fthr > MAX_FRAG_THRESHOLD)) { + ret = -EINVAL; + } else { + dev->frag_threshold = fthr & ~0x1; // get an even value + } + + return ret; +} + +static int at76c503_iw_handler_get_frag(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *frag, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + frag->value = dev->frag_threshold; + frag->disabled = (frag->value >= MAX_FRAG_THRESHOLD); + frag->fixed = 1; + + dbg(DBG_IOCTL, "%s: SIOCGIWFRAG - value %d, disabled %s", + netdev->name, frag->value, + (frag->disabled) ? "true" : "false"); + + return 0; +} + +static int at76c503_iw_handler_get_txpow(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *power, + char *extra) +{ + power->value = 15; + power->fixed = 1; /* No power control */ + power->disabled = 0; + power->flags = IW_TXPOW_DBM; + + dbg(DBG_IOCTL, "%s: SIOCGIWTXPOW - txpow %d dBm", netdev->name, + power->value); + + return 0; +} + +/* jal: short retry is handled by the firmware (at least 0.90.x), + while long retry is not (?) */ +static int at76c503_iw_handler_set_retry(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *retry, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: SIOCSIWRETRY disabled %d flags x%x val %d", + netdev->name, retry->disabled, retry->flags, retry->value); + + if(!retry->disabled && (retry->flags & IW_RETRY_LIMIT)) { + if ((retry->flags & IW_RETRY_MIN) || + !(retry->flags & IW_RETRY_MAX)) { + dev->short_retry_limit = retry->value; + } else + ret = -EINVAL; + } else { + ret = -EINVAL; + } + + return ret; +} + +// adapted (ripped) from atmel.c +static int at76c503_iw_handler_get_retry(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *retry, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + dbg(DBG_IOCTL, "%s: SIOCGIWRETRY", netdev->name); + + retry->disabled = 0; // Can't be disabled + + // Note : by default, display the min retry number + //if((retry->flags & IW_RETRY_MAX)) { + // retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + // retry->value = dev->long_retry_limit; + //} else { + retry->flags = IW_RETRY_LIMIT; + retry->value = dev->short_retry_limit; + + //if(dev->long_retry_limit != dev->short_retry_limit) { + // dev->retry.flags |= IW_RETRY_MIN; + //} + //} + + return 0; +} + +static int at76c503_iw_handler_set_encode(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *encoding, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int index = (encoding->flags & IW_ENCODE_INDEX) - 1; + int len = encoding->length; + + dbg(DBG_IOCTL, "%s: SIOCSIWENCODE - enc.flags %08x " + "pointer %p len %d", netdev->name, encoding->flags, + encoding->pointer, encoding->length); + dbg(DBG_IOCTL, "%s: SIOCSIWENCODE - old wepstate: enabled %s key_id %d " + "auth_mode %s", + netdev->name, (dev->wep_enabled) ? "true" : "false", + dev->wep_key_id, + (dev->auth_mode == WLAN_AUTH_SHARED_KEY) ? + "restricted" : "open"); + + // take the old default key if index is invalid + if ((index < 0) || (index >= WEP_KEYS)) + index = dev->wep_key_id; + + if (len > 0) + { + if (len > WEP_LARGE_KEY_LEN) + len = WEP_LARGE_KEY_LEN; + + memset(dev->wep_keys[index], 0, WEP_KEY_LEN); + memcpy(dev->wep_keys[index], extra, len); + dev->wep_keys_len[index] = (len <= WEP_SMALL_KEY_LEN) ? + WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN; + dev->wep_enabled = 1; + } + + dev->wep_key_id = index; + dev->wep_enabled = ((encoding->flags & IW_ENCODE_DISABLED) == 0); + + if (encoding->flags & IW_ENCODE_RESTRICTED) + dev->auth_mode = WLAN_AUTH_SHARED_KEY; + if (encoding->flags & IW_ENCODE_OPEN) + dev->auth_mode = WLAN_AUTH_OPEN; + + dbg(DBG_IOCTL, "%s: SIOCSIWENCODE - new wepstate: enabled %s key_id %d " + "key_len %d auth_mode %s", + netdev->name, (dev->wep_enabled) ? "true" : "false", + dev->wep_key_id + 1, dev->wep_keys_len[dev->wep_key_id], + (dev->auth_mode == WLAN_AUTH_SHARED_KEY) ? + "restricted" : "open"); + + return -EIWCOMMIT; +} + +static int at76c503_iw_handler_get_encode(struct net_device *netdev, + struct iw_request_info *info, + struct iw_point *encoding, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int index = (encoding->flags & IW_ENCODE_INDEX) - 1; + + if ((index < 0) || (index >= WEP_KEYS)) + index = dev->wep_key_id; + + encoding->flags = + (dev->auth_mode == WLAN_AUTH_SHARED_KEY) ? + IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN; + + if (!dev->wep_enabled) + encoding->flags |= IW_ENCODE_DISABLED; + + if (encoding->pointer) + { + encoding->length = dev->wep_keys_len[index]; + + memcpy(extra, dev->wep_keys[index], dev->wep_keys_len[index]); + + encoding->flags |= (index + 1); + } + + dbg(DBG_IOCTL, "%s: SIOCGIWENCODE - enc.flags %08x " + "pointer %p len %d", netdev->name, encoding->flags, + encoding->pointer, encoding->length); + dbg(DBG_IOCTL, "%s: SIOCGIWENCODE - wepstate: enabled %s key_id %d " + "key_len %d auth_mode %s", + netdev->name, (dev->wep_enabled) ? "true" : "false", + dev->wep_key_id + 1, dev->wep_keys_len[dev->wep_key_id], + (dev->auth_mode == WLAN_AUTH_SHARED_KEY) ? + "restricted" : "open"); + + return 0; +} + +static int at76c503_iw_handler_set_power(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *power, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + dbg(DBG_IOCTL, "%s: SIOCSIWPOWER - disabled %s flags x%x value x%x", + netdev->name, (power->disabled) ? "true" : "false", + power->flags, power->value); + + if (power->disabled) + { + dev->pm_mode = PM_ACTIVE; + } + else + { + // we set the listen_interval based on the period given + // no idea how to handle the timeout of iwconfig ??? + if (power->flags & IW_POWER_PERIOD) + { + dev->pm_period_us = power->value; + } + + dev->pm_mode = PM_SAVE; // use iw_priv to select SMART_SAVE + } + + return -EIWCOMMIT; +} + +static int at76c503_iw_handler_get_power(struct net_device *netdev, + struct iw_request_info *info, + struct iw_param *power, + char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + + power->disabled = dev->pm_mode == PM_ACTIVE; + + if ((power->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) + { + power->flags = IW_POWER_TIMEOUT; + power->value = 0; + } + else + { + unsigned long flags; + u16 beacon_int; // of the current bss + + power->flags = IW_POWER_PERIOD; + + spin_lock_irqsave(&dev->bss_list_spinlock, flags); + beacon_int = dev->curr_bss != NULL ? + dev->curr_bss->beacon_interval : 0; + spin_unlock_irqrestore(&dev->bss_list_spinlock, flags); + + if (beacon_int != 0) + { + power->value = + (beacon_int * dev->pm_period_beacon) << 10; + } + else + { + power->value = dev->pm_period_us; + } + } + + power->flags |= IW_POWER_ALL_R; + + dbg(DBG_IOCTL, "%s: SIOCGIWPOWER - disabled %s flags x%x value x%x", + netdev->name, (power->disabled) ? "true" : "false", + power->flags, power->value); + + return 0; +} + + +/******************************************************************************* + * Private IOCTLS + */ +static int at76c503_iw_handler_PRIV_IOCTL_SET_SHORT_PREAMBLE + (struct net_device *netdev, struct iw_request_info *info, + char *name, char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int val = *((int *)name); + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: PRIV_IOCTL_SET_SHORT_PREAMBLE, %d", + netdev->name, val); + + if (val < 0 || val > 2) { + //allow value of 2 - in the win98 driver it stands + //for "auto preamble" ...? + ret = -EINVAL; + } else { + dev->preamble_type = val; + } + + return ret; +} + +static int at76c503_iw_handler_PRIV_IOCTL_SET_DEBUG + (struct net_device *netdev, struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + char *ptr; + u32 val; + + if (data->length > 0) { + val = simple_strtol(extra, &ptr, 0); + + if (ptr == extra) { + val = DBG_DEFAULTS; + } + + dbg_uc("%s: PRIV_IOCTL_SET_DEBUG input %d: %s -> x%x", + netdev->name, data->length, extra, val); + } else { + val = DBG_DEFAULTS; + } + + dbg_uc("%s: PRIV_IOCTL_SET_DEBUG, old 0x%x new 0x%x", + netdev->name, at76_debug, val); + + /* jal: some more output to pin down lockups */ + dbg_uc("%s: netif running %d queue_stopped %d carrier_ok %d", + netdev->name, + netif_running(netdev), + netif_queue_stopped(netdev), + netif_carrier_ok(netdev)); + + at76_debug = val; + + return 0; +} + +static int at76c503_iw_handler_PRIV_IOCTL_SET_POWERSAVE_MODE + (struct net_device *netdev, struct iw_request_info *info, + char *name, char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int val = *((int *)name); + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: PRIV_IOCTL_SET_POWERSAVE_MODE, %d (%s)", + netdev->name, val, + val == PM_ACTIVE ? "active" : val == PM_SAVE ? "save" : + val == PM_SMART_SAVE ? "smart save" : ""); + if (val < PM_ACTIVE || val > PM_SMART_SAVE) { + ret = -EINVAL; + } else { + dev->pm_mode = val; + } + + return ret; +} + +static int at76c503_iw_handler_PRIV_IOCTL_SET_SCAN_TIMES + (struct net_device *netdev, struct iw_request_info *info, + char *name, char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int mint = *((int *)name); + int maxt = *((int *)name + 1); + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: PRIV_IOCTL_SET_SCAN_TIMES - min %d max %d", + netdev->name, mint, maxt); + if (mint <= 0 || maxt <= 0 || mint > maxt) { + ret = -EINVAL; + } else { + LOCK_ISTATE() + if (dev->istate == MONITORING) { + dev->monitor_scan_min_time = mint; + dev->monitor_scan_max_time = maxt; + ret = 0; + } else { + dev->scan_min_time = mint; + dev->scan_max_time = maxt; + } + UNLOCK_ISTATE() + } + + return ret; +} + +static int at76c503_iw_handler_PRIV_IOCTL_SET_SCAN_MODE + (struct net_device *netdev, struct iw_request_info *info, + char *name, char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int val = *((int *)name); + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: PRIV_IOCTL_SET_SCAN_MODE - mode %s", + netdev->name, (val = SCAN_TYPE_ACTIVE) ? "active" : + (val = SCAN_TYPE_PASSIVE) ? "passive" : ""); + + if (val != SCAN_TYPE_ACTIVE && val != SCAN_TYPE_PASSIVE) { + ret = -EINVAL; + } else { + dev->scan_mode = val; + } + + return ret; +} + +static int set_iroaming(struct at76c503 *dev, int onoff) +{ + int ret = 0; + + memset(&dev->mib_buf, 0, sizeof(struct set_mib_buffer)); + dev->mib_buf.type = MIB_MAC_MGMT; + dev->mib_buf.size = 1; + dev->mib_buf.index = IROAMING_OFFSET; + dev->mib_buf.data[0] = (dev->international_roaming ? 1 : 0); + ret = set_mib(dev, &dev->mib_buf); + if(ret < 0){ + err("%s: set_mib (intl_roaming_enable) failed: %d", dev->netdev->name, ret); + } + + return ret; +} + +static int at76c503_iw_handler_PRIV_IOCTL_SET_INTL_ROAMING + (struct net_device *netdev, struct iw_request_info *info, + char *name, char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int val = *((int *)name); + int ret = -EIWCOMMIT; + + dbg(DBG_IOCTL, "%s: PRIV_IOCTL_SET_INTL_ROAMING - mode %s", + netdev->name, (val == IR_OFF) ? "off" : + (val == IR_ON) ? "on" : ""); + + if (val != IR_OFF && val != IR_ON) { + ret = -EINVAL; + } else { + if (dev->international_roaming != val) { + dev->international_roaming = val; + set_iroaming(dev, val); + } + } + + return ret; +} + +/* == PROC set_monitor_mode == + sets dev->netdev->type */ +static void set_monitor_mode(struct at76c503 *dev, int use_prism) +{ + if (dev->iw_mode == IW_MODE_MONITOR) { + if (use_prism) { + dbg(DBG_MONITOR_MODE, "%s: MONITOR MODE ON: " + "Prism headers ARE used", dev->netdev->name); + dev->netdev->type = ARPHRD_IEEE80211_PRISM; + } else { + dbg(DBG_MONITOR_MODE, "%s: MONITOR MODE ON: " + "Prism headers NOT used", dev->netdev->name); + dev->netdev->type = ARPHRD_IEEE80211; + } + } else { + dbg(DBG_MONITOR_MODE, "%s: MONITOR MODE OFF", + dev->netdev->name); + dev->netdev->type = ARPHRD_ETHER; + } +} /* set_monitor_mode */ + +static int at76c503_iw_handler_PRIV_IOCTL_SET_MONITOR_MODE + (struct net_device *netdev, struct iw_request_info *info, + char *name, char *extra) +{ + struct at76c503 *dev = (struct at76c503*)netdev->priv; + int *params = ((int *)name); + int mode = params[0]; + int channel = params[1]; + int ret = 0; + + dbg(DBG_IOCTL, "%s: PRIV_IOCTL_SET_MONITOR_MODE - mode %d ch %d", + netdev->name, mode, channel); + + if (mode != MM_OFF && mode != MM_ON && mode != MM_ON_NO_PRISM) + ret = -EINVAL; + else { + if (mode != MM_OFF) { + if ((channel >= 1) && + (channel <= (sizeof(channel_frequency) / + sizeof(channel_frequency[0])))) + // INFO: This doesn't actually affect the scan + dev->channel = channel; + + dev->monitor_prism_header = (mode == MM_ON); + + if (dev->iw_mode != IW_MODE_MONITOR) { + ret = -EIWCOMMIT; + dev->iw_mode = IW_MODE_MONITOR; + } + } else { + /* mode == MM_OFF */ + if (dev->iw_mode == IW_MODE_MONITOR) { + ret = -EIWCOMMIT; + dev->iw_mode = IW_MODE_INFRA; + } + } + set_monitor_mode(dev, dev->monitor_prism_header); + } + + return ret; +} + +/******************************************************************************* + * structure that advertises the iw handlers of this driver + */ +static const iw_handler at76c503_handlers[] = +{ + [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_commit, + [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_name, + [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_freq, + [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_freq, + [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_mode, + [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_mode, + [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_range, + [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_spy, + [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_spy, + [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_thrspy, + [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_thrspy, + [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_wap, + [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_wap, + [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_scan, + [SIOCGIWSCAN -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_scan, + [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_essid, + [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_essid, + [SIOCSIWNICKN -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_nickname, + [SIOCGIWNICKN -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_nickname, + [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_rate, + [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_rate, + [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_rts, + [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_rts, + [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_frag, + [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_frag, + [SIOCGIWTXPOW -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_txpow, + [SIOCGIWRETRY -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_retry, + [SIOCGIWRETRY -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_retry, + [SIOCSIWENCODE-SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_encode, + [SIOCGIWENCODE-SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_encode, + [SIOCSIWPOWER -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_set_power, + [SIOCGIWPOWER -SIOCIWFIRST] = (iw_handler) at76c503_iw_handler_get_power, +}; + +/******************************************************************************* + * structure that advertises the private iw handlers of this driver + */ +static const iw_handler at76c503_priv_handlers[] = +{ + (iw_handler) at76c503_iw_handler_PRIV_IOCTL_SET_SHORT_PREAMBLE, + (iw_handler) NULL, + (iw_handler) at76c503_iw_handler_PRIV_IOCTL_SET_DEBUG, + (iw_handler) NULL, + (iw_handler) at76c503_iw_handler_PRIV_IOCTL_SET_POWERSAVE_MODE, + (iw_handler) NULL, + (iw_handler) at76c503_iw_handler_PRIV_IOCTL_SET_SCAN_TIMES, + (iw_handler) NULL, + (iw_handler) at76c503_iw_handler_PRIV_IOCTL_SET_SCAN_MODE, + (iw_handler) NULL, + (iw_handler) at76c503_iw_handler_PRIV_IOCTL_SET_INTL_ROAMING, + (iw_handler) NULL, + (iw_handler) at76c503_iw_handler_PRIV_IOCTL_SET_MONITOR_MODE, + (iw_handler) NULL, +}; + +static const struct iw_handler_def at76c503_handler_def = +{ + .num_standard = sizeof(at76c503_handlers)/sizeof(iw_handler), + .num_private = sizeof(at76c503_priv_handlers)/sizeof(iw_handler), + .num_private_args = sizeof(at76c503_priv_args)/ + sizeof(struct iw_priv_args), + .standard = (iw_handler *) at76c503_handlers, + .private = (iw_handler *) at76c503_priv_handlers, + .private_args = (struct iw_priv_args *) at76c503_priv_args, +#if WIRELESS_EXT > 16 + .get_wireless_stats = at76c503_get_wireless_stats, +#endif +#if WIRELESS_EXT == 15 || WIRELESS_EXT == 16 + .spy_offset = offsetof(struct at76c503, spy_data), +#endif +}; + + +static void at76c503_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct at76c503 *dev = (struct at76c503 *)netdev->priv; + + strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); + + strncpy(info->version, DRIVER_VERSION, sizeof(info->version)); + info->version[sizeof(info->version)-1] = '\0'; + + snprintf(info->bus_info, sizeof(info->bus_info) - 1, "usb%d:%d", + dev->udev->bus->busnum, dev->udev->devnum); + + snprintf(info->fw_version, sizeof(info->fw_version) - 1, + "%d.%d.%d-%d", + dev->fw_version.major, dev->fw_version.minor, + dev->fw_version.patch, dev->fw_version.build); +} + +static struct ethtool_ops at76c503_ethtool_ops = { + .get_drvinfo = at76c503_get_drvinfo, +}; + + +static void at76c503_delete_device(struct at76c503 *dev) +{ + int i; + + if (!dev) + return; + + /* signal to _stop() that the device is gone */ + dev->device_unplugged = 1; + + dbg(DBG_PROC_ENTRY, "%s: ENTER",__FUNCTION__); + + if (dev->netdev_registered) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) + if (down_trylock(&rtnl_sem) != 0) { +#else + if (rtnl_trylock() == 0) { +#endif + info("%s: rtnl_sem already down'ed", __FUNCTION__); + } else { + /* synchronously calls at76c503_stop() */ + unregister_netdevice(dev->netdev); + rtnl_unlock(); + } + } + + PUT_DEV(dev->udev); + + // assuming we used keventd, it must quiesce too + flush_scheduled_work (); + + if(dev->bulk_out_buffer != NULL) + kfree(dev->bulk_out_buffer); + + kfree(dev->ctrl_buffer); + + if(dev->write_urb != NULL) { + usb_kill_urb(dev->write_urb); + usb_free_urb(dev->write_urb); + } + if(dev->read_urb != NULL) { + usb_kill_urb(dev->read_urb); + usb_free_urb(dev->read_urb); + } + if(dev->ctrl_buffer != NULL) { + usb_kill_urb(dev->ctrl_urb); + usb_free_urb(dev->ctrl_urb); + } + + dbg(DBG_PROC_ENTRY,"%s: unlinked urbs",__FUNCTION__); + + if(dev->rx_skb != NULL) + kfree_skb(dev->rx_skb); + + free_bss_list(dev); + del_timer_sync(&dev->bss_list_timer); + + LOCK_ISTATE() + if (dev->istate == CONNECTED) { + UNLOCK_ISTATE() + iwevent_bss_disconnect(dev->netdev); + } else UNLOCK_ISTATE() + + for(i=0; i < NR_RX_DATA_BUF; i++) + if (dev->rx_data[i].skb != NULL) { + dev_kfree_skb(dev->rx_data[i].skb); + dev->rx_data[i].skb = NULL; + } + dbg(DBG_PROC_ENTRY, "%s: before freeing dev/netdev", __FUNCTION__); + free_netdev(dev->netdev); /* dev is in net_dev */ +#ifdef CONFIG_IPAQ_HANDHELD + if (machine_is_h5400()) { + ipaq_led_off (RED_LED); + ipaq_led_off (RED_LED_2); + } +#endif + dbg(DBG_PROC_ENTRY, "%s: EXIT", __FUNCTION__); +} + +static int at76c503_alloc_urbs(struct at76c503 *dev) +{ + struct usb_interface *interface = dev->interface; +// struct usb_host_interface *iface_desc = &interface->altsetting[0]; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev = dev->udev; + int i, buffer_size; + + dbg(DBG_PROC_ENTRY, "%s: ENTER", __FUNCTION__); + + dbg(DBG_URB, "%s: NumEndpoints %d ", __FUNCTION__, NUM_EP(interface)); + + for(i = 0; i < NUM_EP(interface); i++) { + endpoint = &EP(interface,i); + + dbg(DBG_URB, "%s: %d. endpoint: addr x%x attr x%x", + __FUNCTION__, + i, + endpoint->bEndpointAddress, + endpoint->bmAttributes); + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + + dev->read_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->read_urb) { + err("No free urbs available"); + return -1; + } + dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; + } + + if (((endpoint->bEndpointAddress & 0x80) == 0x00) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk out endpoint */ + dev->write_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->write_urb) { + err("no free urbs available"); + return -1; + } + buffer_size = sizeof(struct at76c503_tx_buffer) + + MAX_PADDING_SIZE; + dev->bulk_out_size = buffer_size; + dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; + dev->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!dev->bulk_out_buffer) { + err("couldn't allocate bulk_out_buffer"); + return -1; + } + FILL_BULK_URB(dev->write_urb, udev, + usb_sndbulkpipe(udev, + endpoint->bEndpointAddress), + dev->bulk_out_buffer, buffer_size, + (usb_complete_t)at76c503_write_bulk_callback, dev); + } + } + + dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->ctrl_urb) { + err("no free urbs available"); + return -1; + } + dev->ctrl_buffer = kmalloc(1024, GFP_KERNEL); + if (!dev->ctrl_buffer) { + err("couldn't allocate ctrl_buffer"); + return -1; + } + + dbg(DBG_PROC_ENTRY, "%s: EXIT", __FUNCTION__); + + return 0; +} + +static struct at76c503 *alloc_new_device(struct usb_device *udev, + int board_type, + const char *netdev_name) +{ + struct net_device *netdev; + struct at76c503 *dev = NULL; + int i; + + /* allocate memory for our device state and initialize it */ + netdev = alloc_etherdev(sizeof(struct at76c503)); + if (netdev == NULL) { + err("out of memory"); + return NULL; + } + + dev = (struct at76c503 *)netdev->priv; + memset(dev, 0, sizeof(*dev)); + + dev->udev = udev; + dev->netdev = netdev; + + init_MUTEX (&dev->sem); + INIT_WORK (&dev->kevent, kevent); + + dev->open_count = 0; + + init_timer(&dev->restart_timer); + dev->restart_timer.data = (unsigned long)dev; + dev->restart_timer.function = restart_timeout; + + init_timer(&dev->mgmt_timer); + dev->mgmt_timer.data = (unsigned long)dev; + dev->mgmt_timer.function = mgmt_timeout; + + init_timer(&dev->fw_dl_timer); + dev->fw_dl_timer.data = (unsigned long)dev; + dev->fw_dl_timer.function = fw_dl_timeout; + + + spin_lock_init(&dev->mgmt_spinlock); + spin_lock_init(&dev->istate_spinlock); + dev->next_mgmt_bulk = NULL; + dev->istate = INTFW_DOWNLOAD; + + /* initialize empty BSS list */ + dev->curr_bss = dev->new_bss = NULL; + INIT_LIST_HEAD(&dev->bss_list); + spin_lock_init(&dev->bss_list_spinlock); + + init_timer(&dev->bss_list_timer); + dev->bss_list_timer.data = (unsigned long)dev; + dev->bss_list_timer.function = bss_list_timeout; + + spin_lock_init(&dev->spy_spinlock); + + /* mark all rx data entries as unused */ + for(i=0; i < NR_RX_DATA_BUF; i++) + dev->rx_data[i].skb = NULL; + + dev->tasklet.func = rx_tasklet; + dev->tasklet.data = (unsigned long)dev; + + dev->board_type = board_type; + + dev->pm_mode = pm_mode; + dev->pm_period_us = pm_period; + + dev_alloc_name(netdev, netdev_name); + + return dev; +} /* alloc_new_device */ + +/* == PROC init_new_device == + firmware got downloaded, we can continue with init */ +/* We may have to move the register_netdev into alloc_new_device, + because hotplug may try to configure the netdev _before_ + (or parallel to) the download of firmware */ +static int init_new_device(struct at76c503 *dev) +{ + struct net_device *netdev = dev->netdev; + int ret; + + /* set up the endpoint information */ + /* check out the endpoints */ + + dev->interface = dev->udev->actconfig->interface[0]; + + dbg(DBG_DEVSTART, "USB interface: %d endpoints", + NUM_EP(dev->interface)); + + /* we let this timer run the whole time this driver instance lives */ + mod_timer(&dev->bss_list_timer, jiffies+BSS_LIST_TIMEOUT); + +#ifdef CONFIG_IPAQ_HANDHELD + if (machine_is_h5400 ()) + ipaq_init_led (); +#endif + + if(at76c503_alloc_urbs(dev) < 0) + goto error; + + /* get firmware version */ + ret = get_mib(dev->udev, MIB_FW_VERSION, (u8*)&dev->fw_version, sizeof(dev->fw_version)); + if((ret < 0) || ((dev->fw_version.major == 0) && + (dev->fw_version.minor == 0) && + (dev->fw_version.patch == 0) && + (dev->fw_version.build == 0))){ + err("getting firmware failed with %d, or version is 0", ret); + err("this probably means that the ext. fw was not loaded correctly"); + goto error; + } + + /* fw 0.84 doesn't send FCS with rx data */ + if (dev->fw_version.major == 0 && dev->fw_version.minor <= 84) + dev->rx_data_fcs_len = 0; + else + dev->rx_data_fcs_len = 4; + + info("firmware version %d.%d.%d #%d (fcs_len %d)", + dev->fw_version.major, dev->fw_version.minor, + dev->fw_version.patch, dev->fw_version.build, + dev->rx_data_fcs_len); + + /* MAC address */ + ret = get_hw_config(dev); + if(ret < 0){ + err("could not get MAC address"); + goto error; + } + + dev->domain = getRegDomain(dev->regulatory_domain); + /* init. netdev->dev_addr */ + memcpy(netdev->dev_addr, dev->mac_addr, ETH_ALEN); + info("device's MAC %s, regulatory domain %s (id %d)", + mac2str(dev->mac_addr), dev->domain->name, + dev->regulatory_domain); + + /* initializing */ + dev->international_roaming = international_roaming; + dev->channel = DEF_CHANNEL; + dev->iw_mode = default_iw_mode; + dev->monitor_prism_header = 1; + memset(dev->essid, 0, IW_ESSID_MAX_SIZE); + memset(dev->nickn, 0, sizeof(dev->nickn)); + dev->rts_threshold = DEF_RTS_THRESHOLD; + dev->frag_threshold = DEF_FRAG_THRESHOLD; + dev->short_retry_limit = DEF_SHORT_RETRY_LIMIT; + //dev->long_retr_limit = DEF_LONG_RETRY_LIMIT; + dev->txrate = TX_RATE_AUTO; + dev->preamble_type = preamble_type; + dev->beacon_period = 100; + dev->beacons_last_qual=jiffies_to_msecs(jiffies); + dev->auth_mode = auth_mode ? WLAN_AUTH_SHARED_KEY : + WLAN_AUTH_OPEN; + dev->scan_min_time = scan_min_time; + dev->scan_max_time = scan_max_time; + dev->scan_mode = scan_mode; + dev->monitor_scan_min_time = monitor_scan_min_time; + dev->monitor_scan_max_time = monitor_scan_max_time; + + netdev->flags &= ~IFF_MULTICAST; /* not yet or never */ + netdev->open = at76c503_open; + netdev->stop = at76c503_stop; + netdev->get_stats = at76c503_get_stats; + netdev->ethtool_ops = &at76c503_ethtool_ops; + +#if WIRELESS_EXT > 16 + /* Add pointers to enable iwspy support. */ + dev->wireless_data.spy_data = &dev->spy_data; + netdev->wireless_data = &dev->wireless_data; +#else /* WIRELESS_EXT > 16 */ + netdev->get_wireless_stats = at76c503_get_wireless_stats; +#endif /* WIRELESS_EXT > 16 */ + + netdev->hard_start_xmit = at76c503_tx; + netdev->tx_timeout = at76c503_tx_timeout; + netdev->watchdog_timeo = 2 * HZ; + netdev->wireless_handlers = + (struct iw_handler_def*)&at76c503_handler_def; + netdev->set_multicast_list = at76c503_set_multicast; + netdev->set_mac_address = at76c503_set_mac_address; + // netdev->hard_header_len = 8 + sizeof(struct ieee80211_hdr_3addr); + /* +// netdev->hard_header = at76c503_header; +*/ + + /* putting this inside rtnl_lock() - rtnl_unlock() hangs modprobe ...? */ + ret = register_netdev(dev->netdev); + if (ret) { + err("unable to register netdevice %s (status %d)!", + dev->netdev->name, ret); + return -1; + } + info("registered %s", dev->netdev->name); + dev->netdev_registered = 1; + + return 0; + + error: + at76c503_delete_device(dev); + return -1; + +} /* init_new_device */ + + +/* == PROC at76c503_get_fw_info == + disassembles the firmware image into version, str, + internal and external fw part. returns 0 on success, < 0 on error */ +static int at76c503_get_fw_info(u8 *fw_data, int fw_size, + u32 *board, u32 *version, char **str, + u8 **int_fw, int *int_fw_size, + u8 **ext_fw, int *ext_fw_size) +{ +/* fw structure (all numbers are little_endian) + offset length description + 0 4 crc 32 (seed ~0, no post, all gaps are zeros, header included) + 4 4 board type (see at76c503.h) + 8 4 version (major<<24|middle<<16|minor<<8|build) + c 4 offset of printable string (id) area from begin of image + (must be \0 terminated !) + 10 4 offset of internal fw part area + 14 4 length of internal fw part + 18 4 offset of external fw part area (may be first byte _behind_ + image in case we have no external part) + 1c 4 length of external fw part +*/ + + __le32 val; + + if (fw_size < 0x21) { + err("fw too short (x%x)",fw_size); + return -EFAULT; + } + + /* crc currently not checked */ + + memcpy(&val,fw_data+4,4); + *board = le32_to_cpu(val); + + memcpy(&val,fw_data+8,4); + *version = le32_to_cpu(val); + + memcpy(&val,fw_data+0xc,4); + *str = fw_data + le32_to_cpu(val); + + memcpy(&val,fw_data+0x10,4); + *int_fw = fw_data + le32_to_cpu(val); + memcpy(&val,fw_data+0x14,4); + *int_fw_size = le32_to_cpu(val); + + memcpy(&val,fw_data+0x18,4); + *ext_fw = fw_data + le32_to_cpu(val); + memcpy(&val,fw_data+0x1c,4); + *ext_fw_size = le32_to_cpu(val); + + return 0; +} + +/* == PROC at76c503_do_probe == */ +static int at76c503_do_probe(struct module *mod, struct usb_device *udev, + const u8 *fw_data, int fw_size, u32 board_type, + const char *netdev_name) +{ + struct usb_interface *intf = udev->actconfig->interface[0]; + int ret; + struct at76c503 *dev = NULL; + int op_mode; + char *id_str; + u32 version; + + GET_DEV(udev); + + if ((dev=alloc_new_device(udev, (u8)board_type, netdev_name)) == NULL) { + ret = -ENOMEM; + goto error; + } + + op_mode = get_op_mode(udev); + + usb_set_intfdata(intf, dev); + dev->interface = intf; + + dbg(DBG_DEVSTART, "opmode %d", op_mode); + + /* we get OPMODE_NONE with 2.4.23, SMC2662W-AR ??? + we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */ + + if (op_mode == OPMODE_HW_CONFIG_MODE) { + err("cannot handle a device in HW_CONFIG_MODE (opmode %d)", op_mode); + ret = -ENODEV; + goto error; + } + + if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH && + op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) { + + dbg(DBG_DEVSTART, "need to download firmware"); + + /* disassem. the firmware */ + if ((ret=at76c503_get_fw_info(fw_data, fw_size, &dev->board_type, + &version, &id_str, + &dev->intfw, &dev->intfw_size, + &dev->extfw, &dev->extfw_size))) { + goto error; + } + + dbg(DBG_DEVSTART, "firmware board %u version %u.%u.%u#%u " + "(int %x:%tx, ext %x:%tx)", + dev->board_type, version>>24,(version>>16)&0xff, + (version>>8)&0xff, version&0xff, + dev->intfw_size, dev->intfw-fw_data, + dev->extfw_size, dev->extfw-fw_data); + if (*id_str) + dbg(DBG_DEVSTART, "firmware id %s",id_str); + + if (dev->board_type != board_type) { + err("inconsistent board types %u != %u", + board_type, dev->board_type); + at76c503_delete_device(dev); + goto error; + } + + /* download internal firmware part */ + dbg(DBG_DEVSTART, "downloading internal firmware"); + NEW_STATE(dev,INTFW_DOWNLOAD); + defer_kevent(dev,KEVENT_INTERNAL_FW); + + } else { + /* internal firmware already inside the device */ + /* get firmware version to test if external firmware is loaded */ + /* This works only for newer firmware, e.g. the Intersil 0.90.x + says "control timeout on ep0in" and subsequent get_op_mode() fail + too :-( */ + int force_fw_dwl = 0; + + /* disassem. the firmware */ + if ((ret=at76c503_get_fw_info(fw_data, fw_size, &dev->board_type, + &version, &id_str, + &dev->intfw, &dev->intfw_size, + &dev->extfw, &dev->extfw_size))) { + goto error; + } + + /* if version >= 0.100.x.y or device with built-in flash we can query the device + * for the fw version */ + if (version >= ((0<<24)|(100<<16)) || (op_mode == OPMODE_NORMAL_NIC_WITH_FLASH)) { + ret = get_mib(udev, MIB_FW_VERSION, (u8*)&dev->fw_version, + sizeof(dev->fw_version)); + } else { + /* force fw download only if the device has no flash inside */ + force_fw_dwl = 1; + } + + if ((force_fw_dwl) || (ret < 0) || ((dev->fw_version.major == 0) && + (dev->fw_version.minor == 0) && + (dev->fw_version.patch == 0) && + (dev->fw_version.build == 0))) { + if (force_fw_dwl) + dbg(DBG_DEVSTART, "forced download of external firmware part"); + else + dbg(DBG_DEVSTART, "cannot get firmware (ret %d) or all zeros " + "- download external firmware", ret); + dbg(DBG_DEVSTART, "firmware board %u version %u.%u.%u#%u " + "(int %x:%tx, ext %x:%tx)", + dev->board_type, version>>24,(version>>16)&0xff, + (version>>8)&0xff, version&0xff, + dev->intfw_size, dev->intfw-fw_data, + dev->extfw_size, dev->extfw-fw_data); + if (*id_str) + dbg(DBG_DEVSTART, "firmware id %s",id_str); + + if (dev->board_type != board_type) { + err("inconsistent board types %u != %u", + board_type, dev->board_type); + at76c503_delete_device(dev); + goto error; + } + + NEW_STATE(dev,EXTFW_DOWNLOAD); + defer_kevent(dev,KEVENT_EXTERNAL_FW); + } else { + NEW_STATE(dev,INIT); + if (init_new_device(dev) < 0) { + ret = -ENODEV; + goto error; + } + } + } + + SET_NETDEV_DEV(dev->netdev, &intf->dev); + return 0; + +error: + PUT_DEV(udev); + return ret; +} + + +/* Firmware names - this must be in sync with boardtype definitions */ +static struct fwentry { + const char *const fwname; + const struct firmware *fw; +} firmwares[] = { + { "" }, + { "atmel_at76c503-i3861.bin" }, + { "atmel_at76c503-i3863.bin" }, + { "atmel_at76c503-rfmd.bin" }, + { "atmel_at76c503-rfmd-acc.bin" }, + { "atmel_at76c505-rfmd.bin" }, + { "atmel_at76c505-rfmd2958.bin" }, + { "atmel_at76c505a-rfmd2958.bin" }, + { "atmel_at76c505amx-rfmd.bin" } +}; + +/* USB Device IDs supported by this driver */ + +/* at76c503-i3861 */ +#define VENDOR_ID_ATMEL 0x03eb +#define PRODUCT_ID_ATMEL_503I 0x7603 /* Generic AT76C503/3861 device */ + +#define VENDOR_ID_LINKSYS_OLD 0x066b +#define PRODUCT_ID_LINKSYS_WUSB11_V21 0x2211 /* Linksys WUSB11 v2.1/v2.6 */ + +#define VENDOR_ID_NETGEAR 0x0864 +#define PRODUCT_ID_NETGEAR_MA101A 0x4100 /* Netgear MA 101 Rev. A */ + +#define VENDOR_ID_TEKRAM 0x0b3b +#define PRODUCT_ID_TEKRAM_U300C 0x1612 /* Tekram U-300C / Allnet ALL0193 */ + +#define VENDOR_ID_HP 0x03f0 +#define PRODUCT_ID_HP_HN210W 0x011c /* HP HN210W PKW-J7801A */ + +#define VENDOR_ID_M4Y750 0x0cde /* Unknown Vendor ID! */ +#define PRODUCT_ID_M4Y750 0x0001 /* Sitecom/Z-Com/Zyxel M4Y-750 */ + +#define VENDOR_ID_DYNALINK 0x069a +#define PRODUCT_ID_DYNALINK_WLL013_I 0x0320 /* Dynalink/Askey WLL013 (intersil) */ + +#define VENDOR_ID_SMC_OLD 0x0d5c +#define PRODUCT_ID_SMC2662W_V1 0xa001 /* EZ connect 11Mpbs +Wireless USB Adapter SMC2662W (v1) */ + +#define VENDOR_ID_BENQ 0x04a5 /* BenQ (Acer) */ +#define PRODUCT_ID_BENQ_AWL_300 0x9000 /* AWL-300 */ + +/* this adapter contains flash */ +#define VENDOR_ID_ADDTRON 0x05dd /* Addtron */ +#define PRODUCT_ID_ADDTRON_AWU120 0xff31 /* AWU-120 */ +/* also Compex WLU11 */ + +#define VENDOR_ID_INTEL 0x8086 /* Intel */ +#define PRODUCT_ID_INTEL_AP310 0x0200 /* AP310 AnyPoint II USB */ + +#define VENDOR_ID_CONCEPTRONIC 0x0d8e +#define PRODUCT_ID_CONCEPTRONIC_C11U 0x7100 /* also Dynalink L11U */ + +#define VENDOR_ID_ARESCOM 0xd8e +#define PRODUCT_ID_WL_210 0x7110 /* Arescom WL-210, + FCC id 07J-GL2411USB */ +#define VENDOR_ID_IO_DATA 0x04bb +#define PRODUCT_ID_IO_DATA_WN_B11_USB 0x0919 /* IO-DATA WN-B11/USB */ + +#define VENDOR_ID_BT 0x069a +#define PRODUCT_ID_BT_VOYAGER_1010 0x0821 /* BT Voyager 1010 */ + + +/* at76c503-i3863 */ +#define VENDOR_ID_ATMEL 0x03eb +#define PRODUCT_ID_ATMEL_503_I3863 0x7604 /* Generic AT76C503/3863 device */ + +#define VENDOR_ID_SAMSUNG 0x055d +#define PRODUCT_ID_SAMSUNG_SWL2100U 0xa000 /* Samsung SWL-2100U */ + + +/* at76c503-rfmd */ +#define VENDOR_ID_ATMEL 0x03eb +#define PRODUCT_ID_ATMEL_503R 0x7605 /* Generic AT76C503/RFMD device */ +#define PRODUCT_ID_W_BUDDIE_WN210 0x4102 /* AirVast W-Buddie WN210 */ + +#define VENDOR_ID_DYNALINK 0x069a +#define PRODUCT_ID_DYNALINK_WLL013_R 0x0321 /* Dynalink/Askey WLL013 (rfmd) */ + +#define VENDOR_ID_LINKSYS 0x077b +#define PRODUCT_ID_LINKSYS_WUSB11_V26 0x2219 /* Linksys WUSB11 v2.6 */ +#define PRODUCT_ID_NE_NWU11B 0x2227 /* Network Everywhere NWU11B */ + +#define VENDOR_ID_NETGEAR 0x0864 +#define PRODUCT_ID_NETGEAR_MA101B 0x4102 /* Netgear MA 101 Rev. B */ + +#define VENDOR_ID_ACTIONTEC 0x1668 +#define PRODUCT_ID_ACTIONTEC_802UAT1 0x7605 /* Actiontec 802UAT1, HWU01150-01UK */ + +#define VENDOR_ID_DLINK 0x2001 /* D-Link */ +#define PRODUCT_ID_DLINK_DWL120 0x3200 /* DWL-120 rev. E */ + +#define VENDOR_ID_DICK_SMITH_ELECTR 0x1371 /* Dick Smith Electronics */ +#define PRODUCT_ID_DSE_XH1153 0x5743 /* XH1153 802.11b USB adapter */ + /* also: CNet CNUSB611 (D) */ +#define PRODUCT_ID_WL_200U 0x0002 /* WL-200U */ + +#define VENDOR_ID_BENQ 0x04a5 /* BenQ (Acer) */ +#define PRODUCT_ID_BENQ_AWL_400 0x9001 /* BenQ AWL-400 USB stick */ + +#define VENDOR_ID_3COM 0x506 +#define PRODUCT_ID_3COM_3CRSHEW696 0xa01 /* 3COM 3CRSHEW696 */ + +#define VENDOR_ID_SIEMENS 0x681 +#define PRODUCT_ID_SIEMENS_SANTIS_WLL013 0x1b /* Siemens Santis ADSL WLAN + USB adapter WLL 013 */ + +#define VENDOR_ID_BELKIN_2 0x50d +#define PRODUCT_ID_BELKIN_F5D6050_V2 0x50 /* Belkin F5D6050, version 2 */ + +#define VENDOR_ID_BLITZ 0x07b8 +#define PRODUCT_ID_BLITZ_NETWAVE_BWU613 0xb000 /* iBlitzz, BWU613 (not *B or *SB !) */ + +#define VENDOR_ID_GIGABYTE 0x1044 +#define PRODUCT_ID_GIGABYTE_GN_WLBM101 0x8003 /* Gigabyte GN-WLBM101 */ + +#define VENDOR_ID_PLANEX 0x2019 +#define PRODUCT_ID_PLANEX_GW_US11S 0x3220 /* Planex GW-US11S */ + +#define VENDOR_ID_COMPAQ 0x049f +#define PRODUCT_ID_IPAQ_INT_WLAN 0x0032 /* internal WLAN adapter in h5[4,5]xx series iPAQs */ + + +/* at76c503-rfmd-acc */ +#define VENDOR_ID_BELKIN 0x0d5c +#define PRODUCT_ID_BELKIN_F5D6050 0xa002 /* Belkin F5D6050 / SMC 2662W v2 / SMC 2662W-AR */ + +#define VENDOR_ID_SMC 0x083a +#define PRODUCT_ID_SMC_2664W 0x3501 + + +/* at76c505-rfmd */ +#define VENDOR_ID_ATMEL 0x03eb +#define PRODUCT_ID_ATMEL_505R 0x7606 /* Generic AT76C505/RFMD device */ + + +/* at76c505-rfmd2958 */ +#define VENDOR_ID_ATMEL 0x03eb +#define PRODUCT_ID_ATMEL_505R2958 0x7613 /* Generic AT76C505/RFMD device + also OvisLink WL-1130USB */ + +#define VENDOR_ID_CNET 0x1371 +#define PRODUCT_ID_CNET_CNUSB611G 0x0013 /* CNet CNUSB 611G */ +#define PRODUCT_ID_FL_WL240U 0x0014 /* Fiberline WL-240U with the + CNet vendor id */ + +#define VENDOR_ID_LINKSYS_1915 0x1915 +#define PRODUCT_ID_LINKSYS_WUSB11V28 0x2233 /* Linksys WUSB11 v2.8 */ + +#define VENDOR_ID_XTERASYS 0x12fd +#define PRODUCT_ID_XTERASYS_XN_2122B 0x1001 /* Xterasys XN-2122B, also + IBlitzz BWU613B / BWU613SB */ + +#define VENDOR_ID_COREGA 0x07aa +#define PRODUCT_ID_COREGA_USB_STICK_11_KK 0x7613 /* Corega WLAN USB Stick 11 (K.K.) */ + +#define VENDOR_ID_MSI 0x0db0 +#define PRODUCT_ID_MSI_MS6978_WLAN_BOX_PC2PC 0x1020 + + +/* at76c505a-rfmd2958 */ +#define VENDOR_ID_ATMEL 0x03eb +#define PRODUCT_ID_ATMEL_505A 0x7614 /* Generic AT76C505A device */ +#define PRODUCT_ID_ATMEL_505AS 0x7617 /* Generic AT76C505AS device */ + +#define VENDOR_ID_GIGASET 0x1690 +#define PRODUCT_ID_GIGASET_11 0x0701 + + +/* at76c505amx-rfmd */ +#define VENDOR_ID_ATMEL 0x03eb +#define PRODUCT_ID_ATMEL_505AMX 0x7615 /* Generic AT76C505AMX device */ + + +static struct usb_device_id dev_table[] = { + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_503I ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_LINKSYS_OLD, PRODUCT_ID_LINKSYS_WUSB11_V21), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_NETGEAR, PRODUCT_ID_NETGEAR_MA101A ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_TEKRAM, PRODUCT_ID_TEKRAM_U300C ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_HP, PRODUCT_ID_HP_HN210W ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_M4Y750, PRODUCT_ID_M4Y750 ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_DYNALINK, PRODUCT_ID_DYNALINK_WLL013_I ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_SMC_OLD, PRODUCT_ID_SMC2662W_V1 ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_BENQ, PRODUCT_ID_BENQ_AWL_300 ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_ADDTRON, PRODUCT_ID_ADDTRON_AWU120 ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_INTEL, PRODUCT_ID_INTEL_AP310 ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_CONCEPTRONIC,PRODUCT_ID_CONCEPTRONIC_C11U), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_ARESCOM, PRODUCT_ID_WL_210), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_IO_DATA, PRODUCT_ID_IO_DATA_WN_B11_USB), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + { USB_DEVICE(VENDOR_ID_BT, PRODUCT_ID_BT_VOYAGER_1010 ), + .driver_info = BOARDTYPE_503_INTERSIL_3861 }, + + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_503_I3863 ), + .driver_info = BOARDTYPE_503_INTERSIL_3863 }, + { USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG_SWL2100U), + .driver_info = BOARDTYPE_503_INTERSIL_3863 }, + + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_503R ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_DYNALINK, PRODUCT_ID_DYNALINK_WLL013_R ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_LINKSYS, PRODUCT_ID_LINKSYS_WUSB11_V26), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_LINKSYS, PRODUCT_ID_NE_NWU11B ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_NETGEAR, PRODUCT_ID_NETGEAR_MA101B ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_DLINK, PRODUCT_ID_DLINK_DWL120 ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_ACTIONTEC,PRODUCT_ID_ACTIONTEC_802UAT1 ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_W_BUDDIE_WN210 ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_DICK_SMITH_ELECTR, PRODUCT_ID_DSE_XH1153), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_DICK_SMITH_ELECTR, PRODUCT_ID_WL_200U), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_BENQ, PRODUCT_ID_BENQ_AWL_400), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_3COM, PRODUCT_ID_3COM_3CRSHEW696), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_SIEMENS, PRODUCT_ID_SIEMENS_SANTIS_WLL013), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_BELKIN_2, PRODUCT_ID_BELKIN_F5D6050_V2 ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_BLITZ, PRODUCT_ID_BLITZ_NETWAVE_BWU613 ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_GIGABYTE, PRODUCT_ID_GIGABYTE_GN_WLBM101 ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_PLANEX, PRODUCT_ID_PLANEX_GW_US11S ), + .driver_info = BOARDTYPE_503_RFMD }, + { USB_DEVICE(VENDOR_ID_COMPAQ, PRODUCT_ID_IPAQ_INT_WLAN), + .driver_info = BOARDTYPE_503_RFMD }, + + { USB_DEVICE(VENDOR_ID_SMC, PRODUCT_ID_SMC_2664W), + .driver_info = BOARDTYPE_503_RFMD_ACC }, + { USB_DEVICE(VENDOR_ID_BELKIN, PRODUCT_ID_BELKIN_F5D6050 ), + .driver_info = BOARDTYPE_503_RFMD_ACC }, + + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_505R ), + .driver_info = BOARDTYPE_505_RFMD }, + + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_505R2958 ), + .driver_info = BOARDTYPE_505_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_CNET, PRODUCT_ID_FL_WL240U ), + .driver_info = BOARDTYPE_505_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_CNET, PRODUCT_ID_CNET_CNUSB611G ), + .driver_info = BOARDTYPE_505_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_LINKSYS_1915, PRODUCT_ID_LINKSYS_WUSB11V28 ), + .driver_info = BOARDTYPE_505_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_XTERASYS, PRODUCT_ID_XTERASYS_XN_2122B ), + .driver_info = BOARDTYPE_505_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_COREGA, PRODUCT_ID_COREGA_USB_STICK_11_KK ), + .driver_info = BOARDTYPE_505_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_MSI, PRODUCT_ID_MSI_MS6978_WLAN_BOX_PC2PC), + .driver_info = BOARDTYPE_505_RFMD_2958 }, + + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_505A ), + .driver_info = BOARDTYPE_505A_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_505AS ), + .driver_info = BOARDTYPE_505A_RFMD_2958 }, + { USB_DEVICE(VENDOR_ID_GIGASET, PRODUCT_ID_GIGASET_11 ), + .driver_info = BOARDTYPE_505A_RFMD_2958 }, + + { USB_DEVICE(VENDOR_ID_ATMEL, PRODUCT_ID_ATMEL_505AMX ), + .driver_info = BOARDTYPE_505AMX_RFMD }, + + { } +}; + +MODULE_DEVICE_TABLE (usb, dev_table); + + +static int at76c50x_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + int retval; + + struct usb_device *udev; + int boardtype = (int)id->driver_info; + const char *const fw_name = firmwares[boardtype].fwname; + const struct firmware *fw = firmwares[boardtype].fw; + udev = interface_to_usbdev(interface); + + if (fw == NULL) { + dbg(DBG_FW, "downloading firmware %s", fw_name); + retval = request_firmware(&fw, fw_name, &udev->dev); + if (retval == 0) { + dbg(DBG_FW, "got it."); + } else { + err("firmware %s not found.", fw_name); + err("You may need to download the firmware from " + "https://developer.berlios.de/projects/at76c503a/"); + return retval; + } + } else + dbg(DBG_FW, "re-using previously loaded fw"); + + retval = at76c503_do_probe(THIS_MODULE, udev, + fw->data, fw->size, + boardtype, netdev_name); + return retval; +} + +static void at76c50x_disconnect(struct usb_interface *interface) +{ + struct at76c503 *ptr; + + ptr = usb_get_intfdata (interface); + usb_set_intfdata(interface, NULL); + + info("%s disconnecting", ((struct at76c503 *)ptr)->netdev->name); + at76c503_delete_device(ptr); + info(DRIVER_NAME " disconnected"); +} + +/* structure for registering this driver with the USB subsystem */ +static struct usb_driver module_usb = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) + .owner = THIS_MODULE, +#endif + .name = DRIVER_NAME, + .probe = at76c50x_probe, + .disconnect = at76c50x_disconnect, + .id_table = dev_table, +}; + + +static int __init mod_init(void) +{ + int result; + + info(DRIVER_DESC " " DRIVER_VERSION " loading"); + +#ifdef CONFIG_IPAQ_HANDHELD + if (machine_is_h5400()) { + /* turn WLAN power on */ + /* both needed? */ + SET_H5400_ASIC_GPIO (GPB, RF_POWER_ON, 1); + SET_H5400_ASIC_GPIO (GPB, WLAN_POWER_ON, 1); + } +#endif + + /* register this driver with the USB subsystem */ + result = usb_register(&module_usb); + if (result < 0) { + err("usb_register failed (status %d)", result); + return -1; + } + + return 0; +} + +static void __exit mod_exit(void) +{ + int i; + + info(DRIVER_DESC " " DRIVER_VERSION " unloading"); + usb_deregister(&module_usb); + for (i = 0; i < ARRAY_SIZE(firmwares); i++) { + if (firmwares[i].fw) + release_firmware(firmwares[i].fw); + } + +#ifdef CONFIG_IPAQ_HANDHELD + if (machine_is_h5400()) { + /* turn WLAN power off */ + SET_H5400_ASIC_GPIO (GPB, RF_POWER_ON, 0); + SET_H5400_ASIC_GPIO (GPB, WLAN_POWER_ON, 0); + } +#endif +} + +module_init(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/acx.h +++ linux-2.6.27/ubuntu/misc/wireless/acx/acx.h @@ -0,0 +1,6 @@ +#include "acx_config.h" +#include "wlan_compat.h" +#include "wlan_hdr.h" +#include "wlan_mgmt.h" +#include "acx_struct.h" +#include "acx_func.h" --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/wlan_mgmt.h +++ linux-2.6.27/ubuntu/misc/wireless/acx/wlan_mgmt.h @@ -0,0 +1,582 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +/*********************************************************************** +** This code is based on elements which are +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +** info@linux-wlan.com +** http://www.linux-wlan.com +*/ + +/*********************************************************************** +** Constants +*/ + +/*-- Information Element IDs --------------------*/ +#define WLAN_EID_SSID 0 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_FH_PARMS 2 +#define WLAN_EID_DS_PARMS 3 +#define WLAN_EID_CF_PARMS 4 +#define WLAN_EID_TIM 5 +#define WLAN_EID_IBSS_PARMS 6 +#define WLAN_EID_COUNTRY 7 /* 802.11d */ +#define WLAN_EID_FH_HOP_PARMS 8 /* 802.11d */ +#define WLAN_EID_FH_TABLE 9 /* 802.11d */ +#define WLAN_EID_REQUEST 10 /* 802.11d */ +/*-- values 11-15 reserved --*/ +#define WLAN_EID_CHALLENGE 16 +/*-- values 17-31 reserved for challenge text extension --*/ +#define WLAN_EID_PWR_CONSTRAINT 32 /* 11h PowerConstraint */ +#define WLAN_EID_ERP_INFO 42 /* was seen from WRT54GS with OpenWrt */ +#define WLAN_EID_NONERP 47 /* was seen from WRT54GS with OpenWrt */ +#define WLAN_EID_RSN 48 +#define WLAN_EID_EXT_RATES 50 +#define WLAN_EID_UNKNOWN128 128 +#define WLAN_EID_UNKNOWN133 133 +#define WLAN_EID_GENERIC 221 /* was seen from WRT54GS with OpenWrt */ +#define WLAN_EID_UNKNOWN223 223 + +#if 0 +#define WLAN_EID_PWR_CAP 33 /* 11h PowerCapability */ +#define WLAN_EID_TPC_REQUEST 34 /* 11h TPC Request */ +#define WLAN_EID_TPC_REPORT 35 /* 11h TPC Report */ +#define WLAN_EID_SUPP_CHANNELS 36 /* 11h Supported Channels */ +#define WLAN_EID_CHANNEL_SWITCH 37 /* 11h ChannelSwitch */ +#define WLAN_EID_MEASURE_REQUEST 38 /* 11h MeasurementRequest */ +#define WLAN_EID_MEASURE_REPORT 39 /* 11h MeasurementReport */ +#define WLAN_EID_QUIET_ID 40 /* 11h Quiet */ +#define WLAN_EID_IBSS_DFS_ID 41 /* 11h IBSS_DFS */ +#endif + +/*-- Reason Codes -------------------------------*/ +#define WLAN_MGMT_REASON_RSVD 0 +#define WLAN_MGMT_REASON_UNSPEC 1 +#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2 +#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3 +#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4 +#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5 +#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6 +#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7 +#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8 +#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9 + +/*-- Status Codes -------------------------------*/ +#define WLAN_MGMT_STATUS_SUCCESS 0 +#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1 +#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10 +#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12 +#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13 +#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14 +#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15 +#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18 +/* p80211b additions */ +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOSHORT 19 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC 20 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY 21 + +/*-- Auth Algorithm Field ---------------------------*/ +#define WLAN_AUTH_ALG_OPENSYSTEM 0 +#define WLAN_AUTH_ALG_SHAREDKEY 1 + +/*-- Management Frame Field Offsets -------------*/ +/* Note: Not all fields are listed because of variable lengths */ +/* Note: These offsets are from the start of the frame data */ + +#define WLAN_BEACON_OFF_TS 0 +#define WLAN_BEACON_OFF_BCN_INT 8 +#define WLAN_BEACON_OFF_CAPINFO 10 +#define WLAN_BEACON_OFF_SSID 12 + +#define WLAN_DISASSOC_OFF_REASON 0 + +#define WLAN_ASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_ASSOCREQ_OFF_SSID 4 + +#define WLAN_ASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_ASSOCRESP_OFF_STATUS 2 +#define WLAN_ASSOCRESP_OFF_AID 4 +#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_REASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_REASSOCREQ_OFF_CURR_AP 4 +#define WLAN_REASSOCREQ_OFF_SSID 10 + +#define WLAN_REASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_REASSOCRESP_OFF_STATUS 2 +#define WLAN_REASSOCRESP_OFF_AID 4 +#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_PROBEREQ_OFF_SSID 0 + +#define WLAN_PROBERESP_OFF_TS 0 +#define WLAN_PROBERESP_OFF_BCN_INT 8 +#define WLAN_PROBERESP_OFF_CAP_INFO 10 +#define WLAN_PROBERESP_OFF_SSID 12 + +#define WLAN_AUTHEN_OFF_AUTH_ALG 0 +#define WLAN_AUTHEN_OFF_AUTH_SEQ 2 +#define WLAN_AUTHEN_OFF_STATUS 4 +#define WLAN_AUTHEN_OFF_CHALLENGE 6 + +#define WLAN_DEAUTHEN_OFF_REASON 0 + +enum { +IEEE16(WF_MGMT_CAP_ESS, 0x0001) +IEEE16(WF_MGMT_CAP_IBSS, 0x0002) +/* In (re)assoc request frames by STA: +** Pollable=0, PollReq=0: STA is not CF-Pollable +** 0 1: STA is CF-Pollable, not requesting to be placed on the CF-Polling list +** 1 0: STA is CF-Pollable, requesting to be placed on the CF-Polling list +** 1 1: STA is CF-Pollable, requesting never to be polled +** In beacon, proberesp, (re)assoc resp frames by AP: +** 0 0: No point coordinator at AP +** 0 1: Point coordinator at AP for delivery only (no polling) +** 1 0: Point coordinator at AP for delivery and polling +** 1 1: Reserved */ +IEEE16(WF_MGMT_CAP_CFPOLLABLE, 0x0004) +IEEE16(WF_MGMT_CAP_CFPOLLREQ, 0x0008) +/* 1=non-WEP data frames are disallowed */ +IEEE16(WF_MGMT_CAP_PRIVACY, 0x0010) +/* In beacon, proberesp, (re)assocresp by AP/AdHoc: +** 1=use of shortpre is allowed ("I can receive shortpre") */ +IEEE16(WF_MGMT_CAP_SHORT, 0x0020) +IEEE16(WF_MGMT_CAP_PBCC, 0x0040) +IEEE16(WF_MGMT_CAP_AGILITY, 0x0080) +/* In (re)assoc request frames by STA: +** 1=short slot time implemented and enabled +** NB: AP shall use long slot time beginning at the next Beacon after assoc +** of STA with this bit set to 0 +** In beacon, proberesp, (re)assoc resp frames by AP: +** currently used slot time value: 0/1 - long/short */ +IEEE16(WF_MGMT_CAP_SHORTSLOT, 0x0400) +/* In (re)assoc request frames by STA: 1=CCK-OFDM is implemented and enabled +** In beacon, proberesp, (re)assoc resp frames by AP/AdHoc: +** 1=CCK-OFDM is allowed */ +IEEE16(WF_MGMT_CAP_CCKOFDM, 0x2000) +}; + + +/*********************************************************************** +** Types +*/ + +/* Information Element types */ + +/* prototype structure, all IEs start with these members */ +typedef struct wlan_ie { + u8 eid; + u8 len; +} WLAN_PACKED wlan_ie_t; + +/*-- Service Set Identity (SSID) -----------------*/ +typedef struct wlan_ie_ssid { + u8 eid; + u8 len; + u8 ssid[1]; /* may be zero */ +} WLAN_PACKED wlan_ie_ssid_t; + +/*-- Supported Rates -----------------------------*/ +typedef struct wlan_ie_supp_rates { + u8 eid; + u8 len; + u8 rates[1]; /* had better be at LEAST one! */ +} WLAN_PACKED wlan_ie_supp_rates_t; + +/*-- FH Parameter Set ----------------------------*/ +typedef struct wlan_ie_fh_parms { + u8 eid; + u8 len; + u16 dwell; + u8 hopset; + u8 hoppattern; + u8 hopindex; +} WLAN_PACKED wlan_ie_fh_parms_t; + +/*-- DS Parameter Set ----------------------------*/ +typedef struct wlan_ie_ds_parms { + u8 eid; + u8 len; + u8 curr_ch; +} WLAN_PACKED wlan_ie_ds_parms_t; + +/*-- CF Parameter Set ----------------------------*/ +typedef struct wlan_ie_cf_parms { + u8 eid; + u8 len; + u8 cfp_cnt; + u8 cfp_period; + u16 cfp_maxdur; + u16 cfp_durremaining; +} WLAN_PACKED wlan_ie_cf_parms_t; + +/*-- TIM ------------------------------------------*/ +typedef struct wlan_ie_tim { + u8 eid; + u8 len; + u8 dtim_cnt; + u8 dtim_period; + u8 bitmap_ctl; + u8 virt_bm[1]; +} WLAN_PACKED wlan_ie_tim_t; + +/*-- IBSS Parameter Set ---------------------------*/ +typedef struct wlan_ie_ibss_parms { + u8 eid; + u8 len; + u16 atim_win; +} WLAN_PACKED wlan_ie_ibss_parms_t; + +/*-- Challenge Text ------------------------------*/ +typedef struct wlan_ie_challenge { + u8 eid; + u8 len; + u8 challenge[1]; +} WLAN_PACKED wlan_ie_challenge_t; + +/*-- ERP (42) -------------------------------------*/ +typedef struct wlan_ie_erp { + u8 eid; + u8 len; + /* bit 0:Non ERP present + ** 1:Use Protection + ** 2:Barker Preamble mode + ** 3-7:reserved */ + u8 erp; +} WLAN_PACKED wlan_ie_erp_t; + +/* Types for parsing mgmt frames */ + +/* prototype structure, all mgmt frame types will start with these members */ +typedef struct wlan_fr_mgmt { + u16 type; + u16 len; /* DOES NOT include FCS */ + wlan_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ +} WLAN_PACKED wlan_fr_mgmt_t; + +/*-- Beacon ---------------------------------------*/ +typedef struct wlan_fr_beacon { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u64 *ts; + u16 *bcn_int; + u16 *cap_info; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *ext_rates; + wlan_ie_fh_parms_t *fh_parms; + wlan_ie_ds_parms_t *ds_parms; + wlan_ie_cf_parms_t *cf_parms; + wlan_ie_ibss_parms_t *ibss_parms; + wlan_ie_tim_t *tim; /* in beacon only, not proberesp */ + wlan_ie_erp_t *erp; /* in beacon only, not proberesp */ +} wlan_fr_beacon_t; +#define wlan_fr_proberesp wlan_fr_beacon +#define wlan_fr_proberesp_t wlan_fr_beacon_t + +/*-- IBSS ATIM ------------------------------------*/ +typedef struct wlan_fr_ibssatim { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ + /* this frame type has a null body */ +} wlan_fr_ibssatim_t; + +/*-- Disassociation -------------------------------*/ +typedef struct wlan_fr_disassoc { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u16 *reason; + /*-- info elements ----------*/ +} wlan_fr_disassoc_t; + +/*-- Association Request --------------------------*/ +typedef struct wlan_fr_assocreq { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u16 *cap_info; + u16 *listen_int; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *ext_rates; +} wlan_fr_assocreq_t; + +/*-- Association Response -------------------------*/ +typedef struct wlan_fr_assocresp { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u16 *cap_info; + u16 *status; + u16 *aid; + /*-- info elements ----------*/ + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *ext_rates; +} wlan_fr_assocresp_t; + +/*-- Reassociation Request ------------------------*/ +typedef struct wlan_fr_reassocreq { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u16 *cap_info; + u16 *listen_int; + u8 *curr_ap; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *ext_rates; +} wlan_fr_reassocreq_t; + +/*-- Reassociation Response -----------------------*/ +typedef struct wlan_fr_reassocresp { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u16 *cap_info; + u16 *status; + u16 *aid; + /*-- info elements ----------*/ + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *ext_rates; +} wlan_fr_reassocresp_t; + +/*-- Probe Request --------------------------------*/ +typedef struct wlan_fr_probereq { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *ext_rates; +} wlan_fr_probereq_t; + +/*-- Authentication -------------------------------*/ +typedef struct wlan_fr_authen { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u16 *auth_alg; + u16 *auth_seq; + u16 *status; + /*-- info elements ----------*/ + wlan_ie_challenge_t *challenge; +} wlan_fr_authen_t; + +/*-- Deauthenication -----------------------------*/ +typedef struct wlan_fr_deauthen { + u16 type; + u16 len; + wlan_hdr_t *hdr; + /*-- fixed fields -----------*/ + u16 *reason; + /*-- info elements ----------*/ +} wlan_fr_deauthen_t; + +/* Types for building mgmt frames */ + +/* Warning. Several types used in below structs are +** in fact variable length. Use structs with such fields with caution */ +typedef struct auth_frame_body { + u16 auth_alg; + u16 auth_seq; + u16 status; + wlan_ie_challenge_t challenge; +} WLAN_PACKED auth_frame_body_t; + +typedef struct assocresp_frame_body { + u16 cap_info; + u16 status; + u16 aid; + wlan_ie_supp_rates_t rates; +} WLAN_PACKED assocresp_frame_body_t; + +typedef struct reassocreq_frame_body { + u16 cap_info; + u16 listen_int; + u8 current_ap[ETH_ALEN]; + wlan_ie_ssid_t ssid; +/* access to this one is disabled since ssid_t is variable length: */ + /* wlan_ie_supp_rates_t rates; */ +} WLAN_PACKED reassocreq_frame_body_t; + +typedef struct reassocresp_frame_body { + u16 cap_info; + u16 status; + u16 aid; + wlan_ie_supp_rates_t rates; +} WLAN_PACKED reassocresp_frame_body_t; + +typedef struct deauthen_frame_body { + u16 reason; +} WLAN_PACKED deauthen_frame_body_t; + +typedef struct disassoc_frame_body { + u16 reason; +} WLAN_PACKED disassoc_frame_body_t; + +typedef struct probereq_frame_body { + wlan_ie_ssid_t ssid; + wlan_ie_supp_rates_t rates; +} WLAN_PACKED probereq_frame_body_t; + +typedef struct proberesp_frame_body { + u8 timestamp[8]; + u16 beacon_int; + u16 cap_info; + wlan_ie_ssid_t ssid; +/* access to these is disabled since ssid_t is variable length: */ + /* wlan_ie_supp_rates_t rates; */ + /* fhps_t fhps; */ + /* dsps_t dsps; */ + /* cfps_t cfps; */ +} WLAN_PACKED proberesp_frame_body_t; + + +/*********************************************************************** +** Functions +*/ + +/* Helpers for parsing mgmt frames */ +void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t *f); +void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t *f); +void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t *f); +void wlan_mgmt_decode_authen(wlan_fr_authen_t *f); +void wlan_mgmt_decode_beacon(wlan_fr_beacon_t *f); +void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t *f); +void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t *f); +void wlan_mgmt_decode_probereq(wlan_fr_probereq_t *f); +void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t *f); +void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t *f); +void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t *f); + +/* Helpers for building mgmt frames */ +static inline u8* +wlan_fill_ie_ssid(u8 *p, int len, const char *ssid) +{ + struct wlan_ie_ssid *ie = (void*)p; + ie->eid = WLAN_EID_SSID; + ie->len = len; + memcpy(ie->ssid, ssid, len); + return p + len + 2; +} +/* This controls whether we create 802.11g 'ext supported rates' IEs +** or just create overlong 'supported rates' IEs instead +** (non-11g compliant) */ +#define WE_OBEY_802_11G 1 +static inline u8* +wlan_fill_ie_rates(u8 *p, int len, const u8 *rates) +{ + struct wlan_ie_supp_rates *ie = (void*)p; +#if WE_OBEY_802_11G + if (len > 8 ) len = 8; +#endif + /* supported rates (1 to 8 octets) */ + ie->eid = WLAN_EID_SUPP_RATES; + ie->len = len; + memcpy(ie->rates, rates, len); + return p + len + 2; +} +/* This one wouldn't create an IE at all if not needed */ +static inline u8* +wlan_fill_ie_rates_ext(u8 *p, int len, const u8 *rates) +{ + struct wlan_ie_supp_rates *ie = (void*)p; +#if !WE_OBEY_802_11G + return p; +#endif + len -= 8; + if (len <= 0) return p; + /* ext supported rates */ + ie->eid = WLAN_EID_EXT_RATES; + ie->len = len; + memcpy(ie->rates, rates+8, len); + return p + len + 2; +} +static inline u8* +wlan_fill_ie_ds_parms(u8 *p, int channel) +{ + struct wlan_ie_ds_parms *ie = (void*)p; + ie->eid = WLAN_EID_DS_PARMS; + ie->len = 1; + ie->curr_ch = channel; + return p + sizeof(*ie); +} +static inline u8* +wlan_fill_ie_ibss_parms(u8 *p, int atim_win) +{ + struct wlan_ie_ibss_parms *ie = (void*)p; + ie->eid = WLAN_EID_IBSS_PARMS; + ie->len = 2; + ie->atim_win = atim_win; + return p + sizeof(*ie); +} +static inline u8* +wlan_fill_ie_tim(u8 *p, int rem, int period, int bcast, + int ofs, int len, const u8 *vbm) +{ + struct wlan_ie_tim *ie = (void*)p; + ie->eid = WLAN_EID_TIM; + ie->len = len + 3; + ie->dtim_cnt = rem; + ie->dtim_period = period; + ie->bitmap_ctl = ofs | (bcast!=0); + if (vbm) + memcpy(ie->virt_bm, vbm, len); /* min 1 byte */ + else + ie->virt_bm[0] = 0; + return p + len + 3 + 2; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/acx_struct.h +++ linux-2.6.27/ubuntu/misc/wireless/acx/acx_struct.h @@ -0,0 +1,2049 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +/*********************************************************************** +** Forward declarations of types +*/ +typedef struct tx tx_t; +typedef struct acx_device acx_device_t; +typedef struct client client_t; +typedef struct rxdesc rxdesc_t; +typedef struct txdesc txdesc_t; +typedef struct rxhostdesc rxhostdesc_t; +typedef struct txhostdesc txhostdesc_t; + + +/*********************************************************************** +** Debug / log functionality +*/ +enum { + L_LOCK = (ACX_DEBUG>1)*0x0001, /* locking debug log */ + L_INIT = (ACX_DEBUG>0)*0x0002, /* special card initialization logging */ + L_IRQ = (ACX_DEBUG>0)*0x0004, /* interrupt stuff */ + L_ASSOC = (ACX_DEBUG>0)*0x0008, /* assocation (network join) and station log */ + L_FUNC = (ACX_DEBUG>1)*0x0020, /* logging of function enter / leave */ + L_XFER = (ACX_DEBUG>1)*0x0080, /* logging of transfers and mgmt */ + L_DATA = (ACX_DEBUG>1)*0x0100, /* logging of transfer data */ + L_DEBUG = (ACX_DEBUG>1)*0x0200, /* log of debug info */ + L_IOCTL = (ACX_DEBUG>0)*0x0400, /* log ioctl calls */ + L_CTL = (ACX_DEBUG>1)*0x0800, /* log of low-level ctl commands */ + L_BUFR = (ACX_DEBUG>1)*0x1000, /* debug rx buffer mgmt (ring buffer etc.) */ + L_XFER_BEACON = (ACX_DEBUG>1)*0x2000, /* also log beacon packets */ + L_BUFT = (ACX_DEBUG>1)*0x4000, /* debug tx buffer mgmt (ring buffer etc.) */ + L_USBRXTX = (ACX_DEBUG>0)*0x8000, /* debug USB rx/tx operations */ + L_BUF = L_BUFR + L_BUFT, + L_ANY = 0xffff +}; + +#if ACX_DEBUG +extern unsigned int acx_debug; +#else +enum { acx_debug = 0 }; +#endif + +extern char firmware_ver[]; + + +/*********************************************************************** +** Random helpers +*/ +#define ACX_PACKED __attribute__ ((packed)) + +#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/* Use worker_queues for 2.5/2.6 kernels and queue tasks for 2.4 kernels + (used for the 'bottom half' of the interrupt routine) */ + +#include +#define USE_WORKER_TASKS +#define WORK_STRUCT struct work_struct +#define SCHEDULE_WORK schedule_work +#define FLUSH_SCHEDULED_WORK flush_scheduled_work + + +/*********************************************************************** +** Constants +*/ +#define OK 0 +#define NOT_OK 1 + +/* The supported chip models */ +#define CHIPTYPE_ACX100 1 +#define CHIPTYPE_ACX111 2 + +#define IS_ACX100(adev) ((adev)->chip_type == CHIPTYPE_ACX100) +#define IS_ACX111(adev) ((adev)->chip_type == CHIPTYPE_ACX111) + +/* Supported interfaces */ +#define DEVTYPE_PCI 0 +#define DEVTYPE_USB 1 + +#if defined(CONFIG_NET_ACX_PCI) + #if !defined(CONFIG_NET_ACX_USB) + #define IS_PCI(adev) 1 + #else + #define IS_PCI(adev) ((adev)->dev_type == DEVTYPE_PCI) + #endif +#else + #define IS_PCI(adev) 0 +#endif + +#if defined(CONFIG_NET_ACX_USB) + #if !defined(CONFIG_NET_ACX_PCI) + #define IS_USB(adev) 1 + #else + #define IS_USB(adev) ((adev)->dev_type == DEVTYPE_USB) + #endif +#else + #define IS_USB(adev) 0 +#endif + +/* Driver defaults */ +#define DEFAULT_DTIM_INTERVAL 10 +/* used to be 2048, but FreeBSD driver changed it to 4096 to work properly +** in noisy wlans */ +#define DEFAULT_MSDU_LIFETIME 4096 +#define DEFAULT_RTS_THRESHOLD 2312 /* max. size: disable RTS mechanism */ +#define DEFAULT_BEACON_INTERVAL 100 + +#define ACX100_BAP_DATALEN_MAX 4096 +#define ACX100_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */ +#define ACX100_RIDDATA_MAXLEN ACX100_RID_GUESSING_MAXLEN + +/* Support Constants */ +/* Radio type names, found in Win98 driver's TIACXLN.INF */ +#define RADIO_MAXIM_0D 0x0d +#define RADIO_RFMD_11 0x11 +#define RADIO_RALINK_15 0x15 +/* used in ACX111 cards (WG311v2, WL-121, ...): */ +#define RADIO_RADIA_16 0x16 +/* most likely *sometimes* used in ACX111 cards: */ +#define RADIO_UNKNOWN_17 0x17 +/* FwRad19.bin was found in a Safecom driver; must be an ACX111 radio: */ +#define RADIO_UNKNOWN_19 0x19 +#define RADIO_UNKNOWN_1B 0x1b /* radio in SafeCom SWLUT-54125 USB adapter; entirely unknown!! */ + +/* Controller Commands */ +/* can be found in table cmdTable in firmware "Rev. 1.5.0" (FW150) */ +#define ACX1xx_CMD_RESET 0x00 +#define ACX1xx_CMD_INTERROGATE 0x01 +#define ACX1xx_CMD_CONFIGURE 0x02 +#define ACX1xx_CMD_ENABLE_RX 0x03 +#define ACX1xx_CMD_ENABLE_TX 0x04 +#define ACX1xx_CMD_DISABLE_RX 0x05 +#define ACX1xx_CMD_DISABLE_TX 0x06 +#define ACX1xx_CMD_FLUSH_QUEUE 0x07 +#define ACX1xx_CMD_SCAN 0x08 +#define ACX1xx_CMD_STOP_SCAN 0x09 +#define ACX1xx_CMD_CONFIG_TIM 0x0a +#define ACX1xx_CMD_JOIN 0x0b +#define ACX1xx_CMD_WEP_MGMT 0x0c +#ifdef OLD_FIRMWARE_VERSIONS +#define ACX100_CMD_HALT 0x0e /* mapped to unknownCMD in FW150 */ +#else +#define ACX1xx_CMD_MEM_READ 0x0d +#define ACX1xx_CMD_MEM_WRITE 0x0e +#endif +#define ACX1xx_CMD_SLEEP 0x0f +#define ACX1xx_CMD_WAKE 0x10 +#define ACX1xx_CMD_UNKNOWN_11 0x11 /* mapped to unknownCMD in FW150 */ +#define ACX100_CMD_INIT_MEMORY 0x12 +#define ACX1FF_CMD_DISABLE_RADIO 0x12 /* new firmware? TNETW1450? */ +#define ACX1xx_CMD_CONFIG_BEACON 0x13 +#define ACX1xx_CMD_CONFIG_PROBE_RESPONSE 0x14 +#define ACX1xx_CMD_CONFIG_NULL_DATA 0x15 +#define ACX1xx_CMD_CONFIG_PROBE_REQUEST 0x16 +#define ACX1xx_CMD_FCC_TEST 0x17 +#define ACX1xx_CMD_RADIOINIT 0x18 +#define ACX111_CMD_RADIOCALIB 0x19 +#define ACX1FF_CMD_NOISE_HISTOGRAM 0x1c /* new firmware? TNETW1450? */ +#define ACX1FF_CMD_RX_RESET 0x1d /* new firmware? TNETW1450? */ +#define ACX1FF_CMD_LNA_CONTROL 0x20 /* new firmware? TNETW1450? */ +#define ACX1FF_CMD_CONTROL_DBG_TRACE 0x21 /* new firmware? TNETW1450? */ + +/* 'After Interrupt' Commands */ +#define ACX_AFTER_IRQ_CMD_STOP_SCAN 0x01 +#define ACX_AFTER_IRQ_CMD_ASSOCIATE 0x02 +#define ACX_AFTER_IRQ_CMD_RADIO_RECALIB 0x04 +#define ACX_AFTER_IRQ_UPDATE_CARD_CFG 0x08 +#define ACX_AFTER_IRQ_TX_CLEANUP 0x10 +#define ACX_AFTER_IRQ_COMPLETE_SCAN 0x20 +#define ACX_AFTER_IRQ_RESTART_SCAN 0x40 + +/*********************************************************************** +** Tx/Rx buffer sizes and watermarks +** +** This will alloc and use DMAable buffers of +** WLAN_A4FR_MAXLEN_WEP_FCS * (RX_CNT + TX_CNT) bytes +** RX/TX_CNT=32 -> ~150k DMA buffers +** RX/TX_CNT=16 -> ~75k DMA buffers +** +** 2005-10-10: reduced memory usage by lowering both to 16 +*/ +#define RX_CNT 16 +#define TX_CNT 16 + +/* we clean up txdescs when we have N free txdesc: */ +#define TX_CLEAN_BACKLOG (TX_CNT/4) +#define TX_START_CLEAN (TX_CNT - TX_CLEAN_BACKLOG) +#define TX_EMERG_CLEAN 2 +/* we stop queue if we have < N free txbufs: */ +#define TX_STOP_QUEUE 3 +/* we start queue if we have >= N free txbufs: */ +#define TX_START_QUEUE 5 + +/*********************************************************************** +** Interrogate/Configure cmd constants +** +** NB: length includes JUST the data part of the IE +** (does not include size of the (type,len) pair) +** +** TODO: seems that acx100, acx100usb, acx111 have some differences, +** fix code with regard to this! +*/ + +#define DEF_IE(name, val, len) enum { ACX##name=val, ACX##name##_LEN=len } + +/* Information Elements: Network Parameters, Static Configuration Entities */ +/* these are handled by real_cfgtable in firmware "Rev 1.5.0" (FW150) */ +DEF_IE(1xx_IE_UNKNOWN_00 ,0x0000, -1); /* mapped to cfgInvalid in FW150 */ +DEF_IE(100_IE_ACX_TIMER ,0x0001, 0x10); +DEF_IE(1xx_IE_POWER_MGMT ,0x0002, 0x06); /* TNETW1450: length 0x18!! */ +DEF_IE(1xx_IE_QUEUE_CONFIG ,0x0003, 0x1c); +DEF_IE(100_IE_BLOCK_SIZE ,0x0004, 0x02); +DEF_IE(1FF_IE_SLOT_TIME ,0x0004, 0x08); /* later firmware versions only? */ +DEF_IE(1xx_IE_MEMORY_CONFIG_OPTIONS ,0x0005, 0x14); +DEF_IE(1FF_IE_QUEUE_HEAD ,0x0005, 0x14 /* FIXME: length? */); +DEF_IE(1xx_IE_RATE_FALLBACK ,0x0006, 0x01); /* TNETW1450: length 2 */ +DEF_IE(100_IE_WEP_OPTIONS ,0x0007, 0x03); +DEF_IE(111_IE_RADIO_BAND ,0x0007, -1); +DEF_IE(1FF_IE_TIMING_CFG ,0x0007, -1); /* later firmware versions; TNETW1450 only? */ +DEF_IE(100_IE_SSID ,0x0008, 0x20); /* huh? */ +DEF_IE(1xx_IE_MEMORY_MAP ,0x0008, 0x28); /* huh? TNETW1450 has length 0x40!! */ +DEF_IE(1xx_IE_SCAN_STATUS ,0x0009, 0x04); /* mapped to cfgInvalid in FW150 */ +DEF_IE(1xx_IE_ASSOC_ID ,0x000a, 0x02); +DEF_IE(1xx_IE_UNKNOWN_0B ,0x000b, -1); /* mapped to cfgInvalid in FW150 */ +DEF_IE(1FF_IE_TX_POWER_LEVEL_TABLE ,0x000b, 0x18); /* later firmware versions; TNETW1450 only? */ +DEF_IE(100_IE_UNKNOWN_0C ,0x000c, -1); /* very small implementation in FW150! */ +/* ACX100 has an equivalent struct in the cmd mailbox directly after reset. + * 0x14c seems extremely large, will trash stack on failure (memset!) + * in case of small input struct --> OOPS! */ +DEF_IE(111_IE_CONFIG_OPTIONS ,0x000c, 0x14c); +DEF_IE(1xx_IE_FWREV ,0x000d, 0x18); +DEF_IE(1xx_IE_FCS_ERROR_COUNT ,0x000e, 0x04); +DEF_IE(1xx_IE_MEDIUM_USAGE ,0x000f, 0x08); +DEF_IE(1xx_IE_RXCONFIG ,0x0010, 0x04); +DEF_IE(100_IE_UNKNOWN_11 ,0x0011, -1); /* NONBINARY: large implementation in FW150! link quality readings or so? */ +DEF_IE(111_IE_QUEUE_THRESH ,0x0011, -1); +DEF_IE(100_IE_UNKNOWN_12 ,0x0012, -1); /* NONBINARY: VERY large implementation in FW150!! */ +DEF_IE(111_IE_BSS_POWER_SAVE ,0x0012, /* -1 */ 2); +DEF_IE(1xx_IE_FIRMWARE_STATISTICS ,0x0013, 0x9c); /* TNETW1450: length 0x134!! */ +DEF_IE(1FF_IE_RX_INTR_CONFIG ,0x0014, 0x14); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1xx_IE_FEATURE_CONFIG ,0x0015, 0x08); +DEF_IE(111_IE_KEY_CHOOSE ,0x0016, 0x04); /* for rekeying. really len=4?? */ +DEF_IE(1FF_IE_MISC_CONFIG_TABLE ,0x0017, 0x04); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_WONE_CONFIG ,0x0018, -1); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_TID_CONFIG ,0x001a, 0x2c); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_CALIB_ASSESSMENT ,0x001e, 0x04); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_BEACON_FILTER_OPTIONS ,0x001f, 0x02); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_LOW_RSSI_THRESH_OPT ,0x0020, 0x04); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_NOISE_HISTOGRAM_RESULTS ,0x0021, 0x30); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_PACKET_DETECT_THRESH ,0x0023, 0x04); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_TX_CONFIG_OPTIONS ,0x0024, 0x04); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_CCA_THRESHOLD ,0x0025, 0x02); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_EVENT_MASK ,0x0026, 0x08); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_DTIM_PERIOD ,0x0027, 0x02); /* later firmware versions, TNETW1450 only? */ +DEF_IE(1FF_IE_ACI_CONFIG_SET ,0x0029, 0x06); /* later firmware versions; maybe TNETW1450 only? */ +DEF_IE(1FF_IE_EEPROM_VER ,0x0030, 0x04); /* later firmware versions; maybe TNETW1450 only? */ +DEF_IE(1xx_IE_DOT11_STATION_ID ,0x1001, 0x06); +DEF_IE(100_IE_DOT11_UNKNOWN_1002 ,0x1002, -1); /* mapped to cfgInvalid in FW150 */ +DEF_IE(111_IE_DOT11_FRAG_THRESH ,0x1002, -1); /* mapped to cfgInvalid in FW150; TNETW1450 has length 2!! */ +DEF_IE(100_IE_DOT11_BEACON_PERIOD ,0x1003, 0x02); /* mapped to cfgInvalid in FW150 */ +DEF_IE(1xx_IE_DOT11_DTIM_PERIOD ,0x1004, -1); /* mapped to cfgInvalid in FW150 */ +DEF_IE(1FF_IE_DOT11_MAX_RX_LIFETIME ,0x1004, -1); /* later firmware versions; maybe TNETW1450 only? */ +DEF_IE(1xx_IE_DOT11_SHORT_RETRY_LIMIT ,0x1005, 0x01); /* TNETW1450: length 2 */ +DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT ,0x1006, 0x01); /* TNETW1450: length 2 */ +DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE ,0x1007, 0x20); /* configure default keys; TNETW1450 has length 0x24!! */ +DEF_IE(1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME ,0x1008, 0x04); +DEF_IE(1xx_IE_DOT11_GROUP_ADDR ,0x1009, -1); +DEF_IE(1xx_IE_DOT11_CURRENT_REG_DOMAIN ,0x100a, 0x02); +/* It's harmless to have larger struct. Use USB case always. */ +DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA ,0x100b, 0x02); /* in fact len=1 for PCI */ +DEF_IE(1xx_IE_DOT11_UNKNOWN_100C ,0x100c, -1); /* mapped to cfgInvalid in FW150 */ +DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL ,0x100d, 0x01); /* TNETW1450 has length 2!! */ +DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE ,0x100e, 0x02); /* in fact len=1 for PCI */ +/* USB doesn't return anything - len==0?! */ +DEF_IE(100_IE_DOT11_ED_THRESHOLD ,0x100f, 0x04); +DEF_IE(1xx_IE_DOT11_WEP_DEFAULT_KEY_SET ,0x1010, 0x01); /* set default key ID; TNETW1450: length 2 */ +DEF_IE(100_IE_DOT11_UNKNOWN_1011 ,0x1011, -1); /* mapped to cfgInvalid in FW150 */ +DEF_IE(1FF_IE_DOT11_CURR_5GHZ_REGDOM ,0x1011, -1); /* later firmware versions; maybe TNETW1450 only? */ +DEF_IE(100_IE_DOT11_UNKNOWN_1012 ,0x1012, -1); /* mapped to cfgInvalid in FW150 */ +DEF_IE(100_IE_DOT11_UNKNOWN_1013 ,0x1013, -1); /* mapped to cfgInvalid in FW150 */ + +#if 0 +/* Experimentally obtained on acx100, fw 1.9.8.b +** -1 means that fw returned 'invalid IE' +** 0200 FC00 nnnn... are test read contents: u16 type, u16 len, data +** (AA are poison bytes marking bytes not written by fw) +** +** Looks like acx100 fw does not update len field (thus len=256-4=FC here) +** A number of IEs seem to trash type,len fields +** IEs marked 'huge' return gobs of data (no poison bytes remain) +*/ +DEF_IE(100_IE_INVAL_00, 0x0000, -1); +DEF_IE(100_IE_INVAL_01, 0x0001, -1); /* IE_ACX_TIMER, len=16 on older fw */ +DEF_IE(100_IE_POWER_MGMT, 0x0002, 4); /* 0200FC00 00040000 AAAAAAAA */ +DEF_IE(100_IE_QUEUE_CONFIG, 0x0003, 28); /* 0300FC00 48060000 9CAD0000 0101AAAA DCB00000 E4B00000 9CAA0000 00AAAAAA */ +DEF_IE(100_IE_BLOCK_SIZE, 0x0004, 2); /* 0400FC00 0001AAAA AAAAAAAA AAAAAAAA */ +/* write only: */ +DEF_IE(100_IE_MEMORY_CONFIG_OPTIONS, 0x0005, 20); +DEF_IE(100_IE_RATE_FALLBACK, 0x0006, 1); /* 0600FC00 00AAAAAA AAAAAAAA AAAAAAAA */ +/* write only: */ +DEF_IE(100_IE_WEP_OPTIONS, 0x0007, 3); +DEF_IE(100_IE_MEMORY_MAP, 0x0008, 40); /* huge: 0800FC00 30000000 6CA20000 70A20000... */ +/* gives INVAL on read: */ +DEF_IE(100_IE_SCAN_STATUS, 0x0009, -1); +DEF_IE(100_IE_ASSOC_ID, 0x000a, 2); /* huge: 0A00FC00 00000000 01040800 00000000... */ +DEF_IE(100_IE_INVAL_0B, 0x000b, -1); +/* 'command rejected': */ +DEF_IE(100_IE_CONFIG_OPTIONS, 0x000c, -3); +DEF_IE(100_IE_FWREV, 0x000d, 24); /* 0D00FC00 52657620 312E392E 382E6200 AAAAAAAA AAAAAAAA 05050201 AAAAAAAA */ +DEF_IE(100_IE_FCS_ERROR_COUNT, 0x000e, 4); +DEF_IE(100_IE_MEDIUM_USAGE, 0x000f, 8); /* E41F0000 2D780300 FCC91300 AAAAAAAA */ +DEF_IE(100_IE_RXCONFIG, 0x0010, 4); /* 1000FC00 00280000 AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_QUEUE_THRESH, 0x0011, 12); /* 1100FC00 AAAAAAAA 00000000 00000000 */ +DEF_IE(100_IE_BSS_POWER_SAVE, 0x0012, 1); /* 1200FC00 00AAAAAA AAAAAAAA AAAAAAAA */ +/* read only, variable len */ +DEF_IE(100_IE_FIRMWARE_STATISTICS, 0x0013, 256); /* 0000AC00 00000000 ... */ +DEF_IE(100_IE_INT_CONFIG, 0x0014, 20); /* 00000000 00000000 00000000 00000000 5D74D105 00000000 AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_FEATURE_CONFIG, 0x0015, 8); /* 1500FC00 16000000 AAAAAAAA AAAAAAAA */ +/* returns 'invalid MAC': */ +DEF_IE(100_IE_KEY_CHOOSE, 0x0016, -4); +DEF_IE(100_IE_INVAL_17, 0x0017, -1); +DEF_IE(100_IE_UNKNOWN_18, 0x0018, 0); /* null len?! 1800FC00 AAAAAAAA AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_UNKNOWN_19, 0x0019, 256); /* huge: 1900FC00 9C1F00EA FEFFFFEA FEFFFFEA... */ +DEF_IE(100_IE_INVAL_1A, 0x001A, -1); + +DEF_IE(100_IE_DOT11_INVAL_1000, 0x1000, -1); +DEF_IE(100_IE_DOT11_STATION_ID, 0x1001, 6); /* huge: 0110FC00 58B10E2F 03000000 00000000... */ +DEF_IE(100_IE_DOT11_INVAL_1002, 0x1002, -1); +DEF_IE(100_IE_DOT11_INVAL_1003, 0x1003, -1); +DEF_IE(100_IE_DOT11_INVAL_1004, 0x1004, -1); +DEF_IE(100_IE_DOT11_SHORT_RETRY_LIMIT, 0x1005, 1); +DEF_IE(100_IE_DOT11_LONG_RETRY_LIMIT, 0x1006, 1); +/* write only: */ +DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE, 0x1007, 32); +DEF_IE(100_IE_DOT11_MAX_XMIT_MSDU_LIFETIME, 0x1008, 4); /* huge: 0810FC00 00020000 F4010000 00000000... */ +/* undoc but returns something */ +DEF_IE(100_IE_DOT11_GROUP_ADDR, 0x1009, 12); /* huge: 0910FC00 00000000 00000000 00000000... */ +DEF_IE(100_IE_DOT11_CURRENT_REG_DOMAIN, 0x100a, 1); /* 0A10FC00 30AAAAAA AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_DOT11_CURRENT_ANTENNA, 0x100b, 1); /* 0B10FC00 8FAAAAAA AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_DOT11_INVAL_100C, 0x100c, -1); +DEF_IE(100_IE_DOT11_TX_POWER_LEVEL, 0x100d, 2); /* 00000000 0100AAAA AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_DOT11_CURRENT_CCA_MODE, 0x100e, 1); /* 0E10FC00 0DAAAAAA AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_DOT11_ED_THRESHOLD, 0x100f, 4); /* 0F10FC00 70000000 AAAAAAAA AAAAAAAA */ +/* set default key ID */ +DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_SET, 0x1010, 1); /* 1010FC00 00AAAAAA AAAAAAAA AAAAAAAA */ +DEF_IE(100_IE_DOT11_INVAL_1011, 0x1011, -1); +DEF_IE(100_IE_DOT11_INVAL_1012, 0x1012, -1); +DEF_IE(100_IE_DOT11_INVAL_1013, 0x1013, -1); +DEF_IE(100_IE_DOT11_UNKNOWN_1014, 0x1014, 256); /* huge */ +DEF_IE(100_IE_DOT11_UNKNOWN_1015, 0x1015, 256); /* huge */ +DEF_IE(100_IE_DOT11_UNKNOWN_1016, 0x1016, 256); /* huge */ +DEF_IE(100_IE_DOT11_UNKNOWN_1017, 0x1017, 256); /* huge */ +DEF_IE(100_IE_DOT11_UNKNOWN_1018, 0x1018, 256); /* huge */ +DEF_IE(100_IE_DOT11_UNKNOWN_1019, 0x1019, 256); /* huge */ +#endif + +#if 0 +/* Experimentally obtained on PCI acx111 Xterasys XN-2522g, fw 1.2.1.34 +** -1 means that fw returned 'invalid IE' +** 0400 0800 nnnn... are test read contents: u16 type, u16 len, data +** (AA are poison bytes marking bytes not written by fw) +** +** Looks like acx111 fw reports real len! +*/ +DEF_IE(111_IE_INVAL_00, 0x0000, -1); +DEF_IE(111_IE_INVAL_01, 0x0001, -1); +DEF_IE(111_IE_POWER_MGMT, 0x0002, 12); +/* write only, variable len: 12 + rxqueue_cnt*8 + txqueue_cnt*4: */ +DEF_IE(111_IE_MEMORY_CONFIG, 0x0003, 24); +DEF_IE(111_IE_BLOCK_SIZE, 0x0004, 8); /* 04000800 AA00AAAA AAAAAAAA */ +/* variable len: 8 + rxqueue_cnt*8 + txqueue_cnt*8: */ +DEF_IE(111_IE_QUEUE_HEAD, 0x0005, 24); +DEF_IE(111_IE_RATE_FALLBACK, 0x0006, 1); +/* acx100 name:WEP_OPTIONS */ +/* said to have len:1 (not true, actually returns 12 bytes): */ +DEF_IE(111_IE_RADIO_BAND, 0x0007, 12); /* 07000C00 AAAA1F00 FF03AAAA AAAAAAAA */ +DEF_IE(111_IE_MEMORY_MAP, 0x0008, 48); +/* said to have len:4, but gives INVAL on read: */ +DEF_IE(111_IE_SCAN_STATUS, 0x0009, -1); +DEF_IE(111_IE_ASSOC_ID, 0x000a, 2); +/* write only, len is not known: */ +DEF_IE(111_IE_UNKNOWN_0B, 0x000b, 0); +/* read only, variable len. I see 67 byte reads: */ +DEF_IE(111_IE_CONFIG_OPTIONS, 0x000c, 67); /* 0C004300 01160500 ... */ +DEF_IE(111_IE_FWREV, 0x000d, 24); +DEF_IE(111_IE_FCS_ERROR_COUNT, 0x000e, 4); +DEF_IE(111_IE_MEDIUM_USAGE, 0x000f, 8); +DEF_IE(111_IE_RXCONFIG, 0x0010, 4); +DEF_IE(111_IE_QUEUE_THRESH, 0x0011, 12); +DEF_IE(111_IE_BSS_POWER_SAVE, 0x0012, 1); +/* read only, variable len. I see 240 byte reads: */ +DEF_IE(111_IE_FIRMWARE_STATISTICS, 0x0013, 240); /* 1300F000 00000000 ... */ +/* said to have len=17. looks like fw pads it to 20: */ +DEF_IE(111_IE_INT_CONFIG, 0x0014, 20); /* 14001400 00000000 00000000 00000000 00000000 00000000 */ +DEF_IE(111_IE_FEATURE_CONFIG, 0x0015, 8); +/* said to be name:KEY_INDICATOR, len:4, but gives INVAL on read: */ +DEF_IE(111_IE_KEY_CHOOSE, 0x0016, -1); +/* said to have len:4, but in fact returns 8: */ +DEF_IE(111_IE_MAX_USB_XFR, 0x0017, 8); /* 17000800 00014000 00000000 */ +DEF_IE(111_IE_INVAL_18, 0x0018, -1); +DEF_IE(111_IE_INVAL_19, 0x0019, -1); +/* undoc but returns something: */ +/* huh, fw indicates len=20 but uses 4 more bytes in buffer??? */ +DEF_IE(111_IE_UNKNOWN_1A, 0x001A, 20); /* 1A001400 AA00AAAA 0000020F FF030000 00020000 00000007 04000000 */ + +DEF_IE(111_IE_DOT11_INVAL_1000, 0x1000, -1); +DEF_IE(111_IE_DOT11_STATION_ID, 0x1001, 6); +DEF_IE(111_IE_DOT11_FRAG_THRESH, 0x1002, 2); +/* acx100 only? gives INVAL on read: */ +DEF_IE(111_IE_DOT11_BEACON_PERIOD, 0x1003, -1); +/* said to be MAX_RECV_MSDU_LIFETIME: */ +DEF_IE(111_IE_DOT11_DTIM_PERIOD, 0x1004, 4); +DEF_IE(111_IE_DOT11_SHORT_RETRY_LIMIT, 0x1005, 1); +DEF_IE(111_IE_DOT11_LONG_RETRY_LIMIT, 0x1006, 1); +/* acx100 only? gives INVAL on read: */ +DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_WRITE, 0x1007, -1); +DEF_IE(111_IE_DOT11_MAX_XMIT_MSDU_LIFETIME, 0x1008, 4); +/* undoc but returns something. maybe it's 2 multicast MACs to listen to? */ +DEF_IE(111_IE_DOT11_GROUP_ADDR, 0x1009, 12); /* 09100C00 00000000 00000000 00000000 */ +DEF_IE(111_IE_DOT11_CURRENT_REG_DOMAIN, 0x100a, 1); +DEF_IE(111_IE_DOT11_CURRENT_ANTENNA, 0x100b, 2); +DEF_IE(111_IE_DOT11_INVAL_100C, 0x100c, -1); +DEF_IE(111_IE_DOT11_TX_POWER_LEVEL, 0x100d, 1); +/* said to have len=1 but gives INVAL on read: */ +DEF_IE(111_IE_DOT11_CURRENT_CCA_MODE, 0x100e, -1); +/* said to have len=4 but gives INVAL on read: */ +DEF_IE(111_IE_DOT11_ED_THRESHOLD, 0x100f, -1); +/* set default key ID. write only: */ +DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_SET, 0x1010, 1); +/* undoc but returns something: */ +DEF_IE(111_IE_DOT11_UNKNOWN_1011, 0x1011, 1); /* 11100100 20 */ +DEF_IE(111_IE_DOT11_INVAL_1012, 0x1012, -1); +DEF_IE(111_IE_DOT11_INVAL_1013, 0x1013, -1); +#endif + + +/*********************************************************************** +**Information Frames Structures +*/ + +/* Used in beacon frames and the like */ +#define DOT11RATEBYTE_1 (1*2) +#define DOT11RATEBYTE_2 (2*2) +#define DOT11RATEBYTE_5_5 (5*2+1) +#define DOT11RATEBYTE_11 (11*2) +#define DOT11RATEBYTE_22 (22*2) +#define DOT11RATEBYTE_6_G (6*2) +#define DOT11RATEBYTE_9_G (9*2) +#define DOT11RATEBYTE_12_G (12*2) +#define DOT11RATEBYTE_18_G (18*2) +#define DOT11RATEBYTE_24_G (24*2) +#define DOT11RATEBYTE_36_G (36*2) +#define DOT11RATEBYTE_48_G (48*2) +#define DOT11RATEBYTE_54_G (54*2) +#define DOT11RATEBYTE_BASIC 0x80 /* flags rates included in basic rate set */ + + +/*********************************************************************** +** rxbuffer_t +** +** This is the format of rx data returned by acx +*/ + +/* I've hoped it's a 802.11 PHY header, but no... + * so far, I've seen on acx111: + * 0000 3a00 0000 0000 IBSS Beacons + * 0000 3c00 0000 0000 ESS Beacons + * 0000 2700 0000 0000 Probe requests + * --vda + */ +typedef struct phy_hdr { + u8 unknown[4]; + u8 acx111_unknown[4]; +} ACX_PACKED phy_hdr_t; + +/* seems to be a bit similar to hfa384x_rx_frame. + * These fields are still not quite obvious, though. + * Some seem to have different meanings... */ + +#define RXBUF_HDRSIZE 12 +#define RXBUF_BYTES_RCVD(adev, rxbuf) \ + ((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) - (adev)->phy_header_len) +#define RXBUF_BYTES_USED(rxbuf) \ + ((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE) +/* USBism */ +#define RXBUF_IS_TXSTAT(rxbuf) (le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0x8000) +/* +mac_cnt_rcvd: + 12 bits: length of frame from control field to first byte of FCS + 3 bits: reserved + 1 bit: 1 = it's a tx status info, not a rx packet (USB only) + +mac_cnt_mblks: + 6 bits: number of memory block used to store frame in adapter memory + 1 bit: Traffic Indicator bit in TIM of received Beacon was set + +mac_status: 1 byte (bitmap): + 7 Matching BSSID + 6 Matching SSID + 5 BDCST Address 1 field is a broadcast + 4 VBM received beacon frame has more than one set bit (?!) + 3 TIM Set bit representing this station is set in TIM of received beacon + 2 GROUP Address 1 is a multicast + 1 ADDR1 Address 1 matches our MAC + 0 FCSGD FSC is good + +phy_stat_baseband: 1 byte (bitmap): + 7 Preamble frame had a long preamble + 6 PLCP Error CRC16 error in PLCP header + 5 Unsup_Mod unsupported modulation + 4 Selected Antenna antenna 1 was used to receive this frame + 3 PBCC/CCK frame used: 1=PBCC, 0=CCK modulation + 2 OFDM frame used OFDM modulation + 1 TI Protection protection frame was detected + 0 Reserved + +phy_plcp_signal: 1 byte: + Receive PLCP Signal field from the Baseband Processor + +phy_level: 1 byte: + receive AGC gain level (can be used to measure receive signal strength) + +phy_snr: 1 byte: + estimated noise power of equalized receive signal + at input of FEC decoder (can be used to measure receive signal quality) + +time: 4 bytes: + timestamp sampled from either the Access Manager TSF counter + or free-running microsecond counter when the MAC receives + first byte of PLCP header. +*/ + +typedef struct rxbuffer { + u16 mac_cnt_rcvd; /* only 12 bits are len! (0xfff) */ + u8 mac_cnt_mblks; + u8 mac_status; + u8 phy_stat_baseband; /* bit 0x80: used LNA (Low-Noise Amplifier) */ + u8 phy_plcp_signal; + u8 phy_level; /* PHY stat */ + u8 phy_snr; /* PHY stat */ + u32 time; /* timestamp upon MAC rcv first byte */ +/* 4-byte (acx100) or 8-byte (acx111) phy header will be here +** if RX_CFG1_INCLUDE_PHY_HDR is in effect: +** phy_hdr_t phy */ + wlan_hdr_a3_t hdr_a3; + /* maximally sized data part of wlan packet */ + u8 data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN]; + /* can add hdr/data_a4 if needed */ +} ACX_PACKED rxbuffer_t; + + +/*--- Firmware statistics ----------------------------------------------------*/ + +/* define a random 100 bytes more to catch firmware versions which + * provide a bigger struct */ +#define FW_STATS_FUTURE_EXTENSION 100 + +typedef struct fw_stats_tx { + u32 tx_desc_of; +} ACX_PACKED fw_stats_tx_t; + +typedef struct fw_stats_rx { + u32 rx_oom; + u32 rx_hdr_of; + u32 rx_hw_stuck; /* old: u32 rx_hdr_use_next */ + u32 rx_dropped_frame; + u32 rx_frame_ptr_err; + u32 rx_xfr_hint_trig; + u32 rx_aci_events; /* later versions only */ + u32 rx_aci_resets; /* later versions only */ +} ACX_PACKED fw_stats_rx_t; + +typedef struct fw_stats_dma { + u32 rx_dma_req; + u32 rx_dma_err; + u32 tx_dma_req; + u32 tx_dma_err; +} ACX_PACKED fw_stats_dma_t; + +typedef struct fw_stats_irq { + u32 cmd_cplt; + u32 fiq; + u32 rx_hdrs; + u32 rx_cmplt; + u32 rx_mem_of; + u32 rx_rdys; + u32 irqs; + u32 tx_procs; + u32 decrypt_done; + u32 dma_0_done; + u32 dma_1_done; + u32 tx_exch_complet; + u32 commands; + u32 rx_procs; + u32 hw_pm_mode_changes; + u32 host_acks; + u32 pci_pm; + u32 acm_wakeups; +} ACX_PACKED fw_stats_irq_t; + +typedef struct fw_stats_wep { + u32 wep_key_count; + u32 wep_default_key_count; + u32 dot11_def_key_mib; + u32 wep_key_not_found; + u32 wep_decrypt_fail; + u32 wep_pkt_decrypt; + u32 wep_decrypt_irqs; +} ACX_PACKED fw_stats_wep_t; + +typedef struct fw_stats_pwr { + u32 tx_start_ctr; + u32 no_ps_tx_too_short; + u32 rx_start_ctr; + u32 no_ps_rx_too_short; + u32 lppd_started; + u32 no_lppd_too_noisy; + u32 no_lppd_too_short; + u32 no_lppd_matching_frame; +} ACX_PACKED fw_stats_pwr_t; + +typedef struct fw_stats_mic { + u32 mic_rx_pkts; + u32 mic_calc_fail; +} ACX_PACKED fw_stats_mic_t; + +typedef struct fw_stats_aes { + u32 aes_enc_fail; + u32 aes_dec_fail; + u32 aes_enc_pkts; + u32 aes_dec_pkts; + u32 aes_enc_irq; + u32 aes_dec_irq; +} ACX_PACKED fw_stats_aes_t; + +typedef struct fw_stats_event { + u32 heartbeat; + u32 calibration; + u32 rx_mismatch; + u32 rx_mem_empty; + u32 rx_pool; + u32 oom_late; + u32 phy_tx_err; + u32 tx_stuck; +} ACX_PACKED fw_stats_event_t; + +/* mainly for size calculation only */ +typedef struct fw_stats { + u16 type; + u16 len; + fw_stats_tx_t tx; + fw_stats_rx_t rx; + fw_stats_dma_t dma; + fw_stats_irq_t irq; + fw_stats_wep_t wep; + fw_stats_pwr_t pwr; + fw_stats_mic_t mic; + fw_stats_aes_t aes; + fw_stats_event_t evt; + u8 _padding[FW_STATS_FUTURE_EXTENSION]; +} fw_stats_t; + +/* Firmware version struct */ + +typedef struct fw_ver { + u16 cmd; + u16 size; + char fw_id[20]; + u32 hw_id; +} ACX_PACKED fw_ver_t; + +#define FW_ID_SIZE 20 + + +/*--- WEP stuff --------------------------------------------------------------*/ +#define DOT11_MAX_DEFAULT_WEP_KEYS 4 + +/* non-firmware struct, no packing necessary */ +typedef struct wep_key { + size_t size; /* most often used member first */ + u8 index; + u8 key[29]; + u16 strange_filler; +} wep_key_t; /* size = 264 bytes (33*8) */ +/* FIXME: We don't have size 264! Or is there 2 bytes beyond the key + * (strange_filler)? */ + +/* non-firmware struct, no packing necessary */ +typedef struct key_struct { + u8 addr[ETH_ALEN]; /* 0x00 */ + u16 filler1; /* 0x06 */ + u32 filler2; /* 0x08 */ + u32 index; /* 0x0c */ + u16 len; /* 0x10 */ + u8 key[29]; /* 0x12; is this long enough??? */ +} key_struct_t; /* size = 276. FIXME: where is the remaining space?? */ + + +/*--- Client (peer) info -----------------------------------------------------*/ +/* adev->sta_list[] is used for: +** accumulating and processing of scan results +** keeping client info in AP mode +** keeping AP info in STA mode (AP is the only one 'client') +** keeping peer info in ad-hoc mode +** non-firmware struct --> no packing necessary */ +enum { + CLIENT_EMPTY_SLOT_0 = 0, + CLIENT_EXIST_1 = 1, + CLIENT_AUTHENTICATED_2 = 2, + CLIENT_ASSOCIATED_3 = 3, + CLIENT_JOIN_CANDIDATE = 4 +}; +struct client { + /* most frequent access first */ + u8 used; /* misnamed, more like 'status' */ + struct client* next; + unsigned long mtime; /* last time we heard it, in jiffies */ + size_t essid_len; /* length of ESSID (without '\0') */ + u32 sir; /* Standard IR */ + u32 snr; /* Signal to Noise Ratio */ + u16 aid; /* association ID */ + u16 seq; /* from client's auth req */ + u16 auth_alg; /* from client's auth req */ + u16 cap_info; /* from client's assoc req */ + u16 rate_cap; /* what client supports (all rates) */ + u16 rate_bas; /* what client supports (basic rates) */ + u16 rate_cfg; /* what is allowed (by iwconfig etc) */ + u16 rate_cur; /* currently used rate mask */ + u8 rate_100; /* currently used rate byte (acx100 only) */ + u8 address[ETH_ALEN]; + u8 bssid[ETH_ALEN]; /* ad-hoc hosts can have bssid != mac */ + u8 channel; + u8 auth_step; + u8 ignore_count; + u8 fallback_count; + u8 stepup_count; + char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID and trailing '\0' */ +/* FIXME: this one is too damn big */ + char challenge_text[WLAN_CHALLENGE_LEN]; +}; + + +/*********************************************************************** +** Hardware structures +*/ + +/* An opaque typesafe helper type + * + * Some hardware fields are actually pointers, + * but they have to remain u32, since using ptr instead + * (8 bytes on 64bit systems!) would disrupt the fixed descriptor + * format the acx firmware expects in the non-user area. + * Since we cannot cram an 8 byte ptr into 4 bytes, we need to + * enforce that pointed to data remains in low memory + * (address value needs to fit in 4 bytes) on 64bit systems. + * + * This is easy to get wrong, thus we are using a small struct + * and special macros to access it. Macros will check for + * attempts to overflow an acx_ptr with value > 0xffffffff. + * + * Attempts to use acx_ptr without macros result in compile-time errors */ + +typedef struct { + u32 v; +} ACX_PACKED acx_ptr; + +#if ACX_DEBUG +#define CHECK32(n) BUG_ON(sizeof(n)>4 && (long)(n)>0xffffff00) +#else +#define CHECK32(n) ((void)0) +#endif + +/* acx_ptr <-> integer conversion */ +#define cpu2acx(n) ({ CHECK32(n); ((acx_ptr){ .v = cpu_to_le32(n) }); }) +#define acx2cpu(a) (le32_to_cpu(a.v)) + +/* acx_ptr <-> pointer conversion */ +#define ptr2acx(p) ({ CHECK32(p); ((acx_ptr){ .v = cpu_to_le32((u32)(long)(p)) }); }) +#define acx2ptr(a) ((void*)le32_to_cpu(a.v)) + +/* Values for rate field (acx100 only) */ +#define RATE100_1 10 +#define RATE100_2 20 +#define RATE100_5 55 +#define RATE100_11 110 +#define RATE100_22 220 +/* This bit denotes use of PBCC: +** (PBCC encoding is usable with 11 and 22 Mbps speeds only) */ +#define RATE100_PBCC511 0x80 + +/* Bit values for rate111 field */ +#define RATE111_1 0x0001 /* DBPSK */ +#define RATE111_2 0x0002 /* DQPSK */ +#define RATE111_5 0x0004 /* CCK or PBCC */ +#define RATE111_6 0x0008 /* CCK-OFDM or OFDM */ +#define RATE111_9 0x0010 /* CCK-OFDM or OFDM */ +#define RATE111_11 0x0020 /* CCK or PBCC */ +#define RATE111_12 0x0040 /* CCK-OFDM or OFDM */ +#define RATE111_18 0x0080 /* CCK-OFDM or OFDM */ +#define RATE111_22 0x0100 /* PBCC */ +#define RATE111_24 0x0200 /* CCK-OFDM or OFDM */ +#define RATE111_36 0x0400 /* CCK-OFDM or OFDM */ +#define RATE111_48 0x0800 /* CCK-OFDM or OFDM */ +#define RATE111_54 0x1000 /* CCK-OFDM or OFDM */ +#define RATE111_RESERVED 0x2000 +#define RATE111_PBCC511 0x4000 /* PBCC mod at 5.5 or 11Mbit (else CCK) */ +#define RATE111_SHORTPRE 0x8000 /* short preamble */ +/* Special 'try everything' value */ +#define RATE111_ALL 0x1fff +/* These bits denote acx100 compatible settings */ +#define RATE111_ACX100_COMPAT 0x0127 +/* These bits denote 802.11b compatible settings */ +#define RATE111_80211B_COMPAT 0x0027 + +/* Descriptor Ctl field bits + * init value is 0x8e, "idle" value is 0x82 (in idle tx descs) + */ +#define DESC_CTL_SHORT_PREAMBLE 0x01 /* preamble type: 0 = long; 1 = short */ +#define DESC_CTL_FIRSTFRAG 0x02 /* this is the 1st frag of the frame */ +#define DESC_CTL_AUTODMA 0x04 +#define DESC_CTL_RECLAIM 0x08 /* ready to reuse */ +#define DESC_CTL_HOSTDONE 0x20 /* host has finished processing */ +#define DESC_CTL_ACXDONE 0x40 /* acx has finished processing */ +/* host owns the desc [has to be released last, AFTER modifying all other desc fields!] */ +#define DESC_CTL_HOSTOWN 0x80 +#define DESC_CTL_ACXDONE_HOSTOWN (DESC_CTL_ACXDONE | DESC_CTL_HOSTOWN) + +/* Descriptor Status field + */ +#define DESC_STATUS_FULL (1 << 31) + +/* NB: some bits may be interesting for Monitor mode tx (aka Raw tx): */ +#define DESC_CTL2_SEQ 0x01 /* don't increase sequence field */ +#define DESC_CTL2_FCS 0x02 /* don't add the FCS */ +#define DESC_CTL2_MORE_FRAG 0x04 +#define DESC_CTL2_RETRY 0x08 /* don't increase retry field */ +#define DESC_CTL2_POWER 0x10 /* don't increase power mgmt. field */ +#define DESC_CTL2_RTS 0x20 /* do RTS/CTS magic before sending */ +#define DESC_CTL2_WEP 0x40 /* encrypt this frame */ +#define DESC_CTL2_DUR 0x80 /* don't increase duration field */ + +/*********************************************************************** +** PCI structures +*/ +/* IRQ Constants +** (outside of "#ifdef PCI" because USB (mis)uses HOST_INT_SCAN_COMPLETE) */ +#define HOST_INT_RX_DATA 0x0001 +#define HOST_INT_TX_COMPLETE 0x0002 +#define HOST_INT_TX_XFER 0x0004 +#define HOST_INT_RX_COMPLETE 0x0008 +#define HOST_INT_DTIM 0x0010 +#define HOST_INT_BEACON 0x0020 +#define HOST_INT_TIMER 0x0040 +#define HOST_INT_KEY_NOT_FOUND 0x0080 +#define HOST_INT_IV_ICV_FAILURE 0x0100 +#define HOST_INT_CMD_COMPLETE 0x0200 +#define HOST_INT_INFO 0x0400 +#define HOST_INT_OVERFLOW 0x0800 +#define HOST_INT_PROCESS_ERROR 0x1000 +#define HOST_INT_SCAN_COMPLETE 0x2000 +#define HOST_INT_FCS_THRESHOLD 0x4000 +#define HOST_INT_UNKNOWN 0x8000 + +/* Outside of "#ifdef PCI" because USB needs to know sizeof() +** of txdesc and rxdesc: */ +struct txdesc { + acx_ptr pNextDesc; /* pointer to next txdesc */ + acx_ptr HostMemPtr; /* 0x04 */ + acx_ptr AcxMemPtr; /* 0x08 */ + u32 tx_time; /* 0x0c */ + u16 total_length; /* 0x10 */ + u16 Reserved; /* 0x12 */ + +/* The following 16 bytes do not change when acx100 owns the descriptor */ +/* BUG: fw clears last byte of this area which is supposedly reserved +** for driver use. amd64 blew up. We dare not use it now */ + u32 dummy[4]; + + u8 Ctl_8; /* 0x24, 8bit value */ + u8 Ctl2_8; /* 0x25, 8bit value */ + u8 error; /* 0x26 */ + u8 ack_failures; /* 0x27 */ + u8 rts_failures; /* 0x28 */ + u8 rts_ok; /* 0x29 */ + union { + struct { + u8 rate; /* 0x2a */ + u8 queue_ctrl; /* 0x2b */ + } ACX_PACKED r1; + struct { + u16 rate111; /* 0x2a */ + } ACX_PACKED r2; + } ACX_PACKED u; + u32 queue_info; /* 0x2c (acx100, reserved on acx111) */ +} ACX_PACKED; /* size : 48 = 0x30 */ +/* NB: acx111 txdesc structure is 4 byte larger */ +/* All these 4 extra bytes are reserved. tx alloc code takes them into account */ + +struct rxdesc { + acx_ptr pNextDesc; /* 0x00 */ + acx_ptr HostMemPtr; /* 0x04 */ + acx_ptr ACXMemPtr; /* 0x08 */ + u32 rx_time; /* 0x0c */ + u16 total_length; /* 0x10 */ + u16 WEP_length; /* 0x12 */ + u32 WEP_ofs; /* 0x14 */ + +/* the following 16 bytes do not change when acx100 owns the descriptor */ + u8 driverWorkspace[16]; /* 0x18 */ + + u8 Ctl_8; + u8 rate; + u8 error; + u8 SNR; /* Signal-to-Noise Ratio */ + u8 RxLevel; + u8 queue_ctrl; + u16 unknown; + u32 unknown2; +} ACX_PACKED; /* size 52 = 0x34 */ + +#ifdef ACX_PCI + +/* Register I/O offsets */ +#define ACX100_EEPROM_ID_OFFSET 0x380 + +/* please add further ACX hardware register definitions only when + it turns out you need them in the driver, and please try to use + firmware functionality instead, since using direct I/O access instead + of letting the firmware do it might confuse the firmware's state + machine */ + +/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION +** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */ +enum { + IO_ACX_SOFT_RESET = 0, + + IO_ACX_SLV_MEM_ADDR, + IO_ACX_SLV_MEM_DATA, + IO_ACX_SLV_MEM_CTL, + IO_ACX_SLV_END_CTL, + + IO_ACX_FEMR, /* Function Event Mask */ + + IO_ACX_INT_TRIG, + IO_ACX_IRQ_MASK, + IO_ACX_IRQ_STATUS_NON_DES, + IO_ACX_IRQ_STATUS_CLEAR, /* CLEAR = clear on read */ + IO_ACX_IRQ_ACK, + IO_ACX_HINT_TRIG, + + IO_ACX_ENABLE, + + IO_ACX_EEPROM_CTL, + IO_ACX_EEPROM_ADDR, + IO_ACX_EEPROM_DATA, + IO_ACX_EEPROM_CFG, + + IO_ACX_PHY_ADDR, + IO_ACX_PHY_DATA, + IO_ACX_PHY_CTL, + + IO_ACX_GPIO_OE, + + IO_ACX_GPIO_OUT, + + IO_ACX_CMD_MAILBOX_OFFS, + IO_ACX_INFO_MAILBOX_OFFS, + IO_ACX_EEPROM_INFORMATION, + + IO_ACX_EE_START, + IO_ACX_SOR_CFG, + IO_ACX_ECPU_CTRL +}; +/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION +** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */ + +/* Values for IO_ACX_INT_TRIG register: */ +/* inform hw that rxdesc in queue needs processing */ +#define INT_TRIG_RXPRC 0x08 +/* inform hw that txdesc in queue needs processing */ +#define INT_TRIG_TXPRC 0x04 +/* ack that we received info from info mailbox */ +#define INT_TRIG_INFOACK 0x02 +/* inform hw that we have filled command mailbox */ +#define INT_TRIG_CMD 0x01 + +struct txhostdesc { + acx_ptr data_phy; /* 0x00 [u8 *] */ + u16 data_offset; /* 0x04 */ + u16 reserved; /* 0x06 */ + u16 Ctl_16; /* 16bit value, endianness!! */ + u16 length; /* 0x0a */ + acx_ptr desc_phy_next; /* 0x0c [txhostdesc *] */ + acx_ptr pNext; /* 0x10 [txhostdesc *] */ + u32 Status; /* 0x14, unused on Tx */ +/* From here on you can use this area as you want (variable length, too!) */ + u8 *data; +} ACX_PACKED; + +struct rxhostdesc { + acx_ptr data_phy; /* 0x00 [rxbuffer_t *] */ + u16 data_offset; /* 0x04 */ + u16 reserved; /* 0x06 */ + u16 Ctl_16; /* 0x08; 16bit value, endianness!! */ + u16 length; /* 0x0a */ + acx_ptr desc_phy_next; /* 0x0c [rxhostdesc_t *] */ + acx_ptr pNext; /* 0x10 [rxhostdesc_t *] */ + u32 Status; /* 0x14 */ +/* From here on you can use this area as you want (variable length, too!) */ + rxbuffer_t *data; +} ACX_PACKED; + +#endif /* ACX_PCI */ + +/*********************************************************************** +** USB structures and constants +*/ +#ifdef ACX_USB + +/* Used for usb_txbuffer.desc field */ +#define USB_TXBUF_TXDESC 0xA +/* Size of header (everything up to data[]) */ +#define USB_TXBUF_HDRSIZE 14 +typedef struct usb_txbuffer { + u16 desc; + u16 mpdu_len; + u8 queue_index; + u8 rate; + u32 hostdata; + u8 ctrl1; + u8 ctrl2; + u16 data_len; + /* wlan packet content is placed here: */ + u8 data[WLAN_A4FR_MAXLEN_WEP_FCS]; +} ACX_PACKED usb_txbuffer_t; + +/* USB returns either rx packets (see rxbuffer) or +** these "tx status" structs: */ +typedef struct usb_txstatus { + u16 mac_cnt_rcvd; /* only 12 bits are len! (0xfff) */ + u8 queue_index; + u8 mac_status; /* seen 0x20 on tx failure */ + u32 hostdata; + u8 rate; + u8 ack_failures; + u8 rts_failures; + u8 rts_ok; +} ACX_PACKED usb_txstatus_t; + +typedef struct usb_tx { + unsigned busy:1; + struct urb *urb; + acx_device_t *adev; + /* actual USB bulk output data block is here: */ + usb_txbuffer_t bulkout; +} usb_tx_t; + +struct usb_rx_plain { + unsigned busy:1; + struct urb *urb; + acx_device_t *adev; + rxbuffer_t bulkin; +}; + +typedef struct usb_rx { + unsigned busy:1; + struct urb *urb; + acx_device_t *adev; + rxbuffer_t bulkin; + /* Make entire structure 4k. Report if it breaks something. */ + u8 padding[4*1024 - sizeof(struct usb_rx_plain)]; +} usb_rx_t; +#endif /* ACX_USB */ + + +/* Config Option structs */ + +typedef struct co_antennas { + u8 type; + u8 len; + u8 list[2]; +} ACX_PACKED co_antennas_t; + +typedef struct co_powerlevels { + u8 type; + u8 len; + u16 list[8]; +} ACX_PACKED co_powerlevels_t; + +typedef struct co_datarates { + u8 type; + u8 len; + u8 list[8]; +} ACX_PACKED co_datarates_t; + +typedef struct co_domains { + u8 type; + u8 len; + u8 list[6]; +} ACX_PACKED co_domains_t; + +typedef struct co_product_id { + u8 type; + u8 len; + u8 list[128]; +} ACX_PACKED co_product_id_t; + +typedef struct co_manuf_id { + u8 type; + u8 len; + u8 list[128]; +} ACX_PACKED co_manuf_t; + +typedef struct co_fixed { + char NVSv[8]; +/* u16 NVS_vendor_offs; ACX111-only */ +/* u16 unknown; ACX111-only */ + u8 MAC[6]; /* ACX100-only */ + u16 probe_delay; /* ACX100-only */ + u32 eof_memory; + u8 dot11CCAModes; + u8 dot11Diversity; + u8 dot11ShortPreambleOption; + u8 dot11PBCCOption; + u8 dot11ChannelAgility; + u8 dot11PhyType; /* FIXME: does 802.11 call it "dot11PHYType"? */ + u8 dot11TempType; + u8 table_count; +} ACX_PACKED co_fixed_t; + +typedef struct acx111_ie_configoption { + u16 type; + u16 len; +/* Do not access below members directly, they are in fact variable length */ + co_fixed_t fixed; + co_antennas_t antennas; + co_powerlevels_t power_levels; + co_datarates_t data_rates; + co_domains_t domains; + co_product_id_t product_id; + co_manuf_t manufacturer; + u8 _padding[4]; +} ACX_PACKED acx111_ie_configoption_t; + + +/*********************************************************************** +** Main acx per-device data structure +*/ +#define ACX_STATE_FW_LOADED 0x01 +#define ACX_STATE_IFACE_UP 0x02 + +/* MAC mode (BSS type) defines + * Note that they shouldn't be redefined, since they are also used + * during communication with firmware */ +#define ACX_MODE_0_ADHOC 0 +#define ACX_MODE_1_UNUSED 1 +#define ACX_MODE_2_STA 2 +#define ACX_MODE_3_AP 3 +/* These are our own inventions. Sending these to firmware +** makes it stop emitting beacons, which is exactly what we want +** for these modes */ +#define ACX_MODE_MONITOR 0xfe +#define ACX_MODE_OFF 0xff +/* 'Submode': identifies exact status of ADHOC/STA host */ +#define ACX_STATUS_0_STOPPED 0 +#define ACX_STATUS_1_SCANNING 1 +#define ACX_STATUS_2_WAIT_AUTH 2 +#define ACX_STATUS_3_AUTHENTICATED 3 +#define ACX_STATUS_4_ASSOCIATED 4 + +/* FIXME: this should be named something like struct acx_priv (typedef'd to + * acx_priv_t) */ + +/* non-firmware struct, no packing necessary */ +struct acx_device { + /* most frequent accesses first (dereferencing and cache line!) */ + + /*** Locking ***/ + /* FIXME: try to convert semaphore to more efficient mutex according + to Ingo Molnar's docs (but not before driver is in mainline or + pre-mutex Linux 2.6.10 is very outdated). */ + struct semaphore sem; + spinlock_t lock; +#if defined(PARANOID_LOCKING) /* Lock debugging */ + const char *last_sem; + const char *last_lock; + unsigned long sem_time; + unsigned long lock_time; +#endif + + /*** Linux network device ***/ + struct net_device *ndev; /* pointer to linux netdevice */ + + /*** Device statistics ***/ + struct net_device_stats stats; /* net device statistics */ +#ifdef WIRELESS_EXT + struct iw_statistics wstats; /* wireless statistics */ +#endif + /*** Power managment ***/ + struct pm_dev *pm; /* PM crap */ + + /*** Management timer ***/ + struct timer_list mgmt_timer; + + /*** Hardware identification ***/ + const char *chip_name; + u8 dev_type; + u8 chip_type; + u8 form_factor; + u8 radio_type; + u8 eeprom_version; + + /*** Config retrieved from EEPROM ***/ + char cfgopt_NVSv[8]; + u16 cfgopt_NVS_vendor_offs; + u8 cfgopt_MAC[6]; + u16 cfgopt_probe_delay; + u32 cfgopt_eof_memory; + u8 cfgopt_dot11CCAModes; + u8 cfgopt_dot11Diversity; + u8 cfgopt_dot11ShortPreambleOption; + u8 cfgopt_dot11PBCCOption; + u8 cfgopt_dot11ChannelAgility; + u8 cfgopt_dot11PhyType; + u8 cfgopt_dot11TempType; + co_antennas_t cfgopt_antennas; + co_powerlevels_t cfgopt_power_levels; + co_datarates_t cfgopt_data_rates; + co_domains_t cfgopt_domains; + co_product_id_t cfgopt_product_id; + co_manuf_t cfgopt_manufacturer; + + /*** Firmware identification ***/ + char firmware_version[FW_ID_SIZE+1]; + u32 firmware_numver; + u32 firmware_id; + const u16 *ie_len; + const u16 *ie_len_dot11; + + /*** Device state ***/ + u16 dev_state_mask; + u8 led_power; /* power LED status */ + u32 get_mask; /* mask of settings to fetch from the card */ + u32 set_mask; /* mask of settings to write to the card */ + + /* Barely used in USB case */ + u16 irq_status; + + u8 after_interrupt_jobs; /* mini job list for doing actions after an interrupt occurred */ + WORK_STRUCT after_interrupt_task; /* our task for after interrupt actions */ + + /*** scanning ***/ + u16 scan_count; /* number of times to do channel scan */ + u8 scan_mode; /* 0 == active, 1 == passive, 2 == background */ + u8 scan_rate; + u16 scan_duration; + u16 scan_probe_delay; +#if WIRELESS_EXT > 15 + struct iw_spy_data spy_data; /* FIXME: needs to be implemented! */ +#endif + + /*** Wireless network settings ***/ + /* copy of the device address (ifconfig hw ether) that we actually use + ** for 802.11; copied over from the network device's MAC address + ** (ifconfig) when it makes sense only */ + u8 dev_addr[MAX_ADDR_LEN]; + u8 bssid[ETH_ALEN]; /* the BSSID after having joined */ + u8 ap[ETH_ALEN]; /* The AP we want, FF:FF:FF:FF:FF:FF is any */ + u16 aid; /* The Association ID sent from the AP / last used AID if we're an AP */ + u16 mode; /* mode from iwconfig */ + int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */ + u16 status; /* 802.11 association status */ + u8 essid_active; /* specific ESSID active, or select any? */ + u8 essid_len; /* to avoid dozens of strlen() */ + /* INCLUDES \0 termination for easy printf - but many places + ** simply want the string data memcpy'd plus a length indicator! + ** Keep that in mind... */ + char essid[IW_ESSID_MAX_SIZE+1]; + /* essid we are going to use for association, in case of "essid 'any'" + ** and in case of hidden ESSID (use configured ESSID then) */ + char essid_for_assoc[IW_ESSID_MAX_SIZE+1]; + char nick[IW_ESSID_MAX_SIZE+1]; /* see essid! */ + u8 channel; + u8 reg_dom_id; /* reg domain setting */ + u16 reg_dom_chanmask; + u16 auth_or_assoc_retries; + u16 scan_retries; + unsigned long scan_start; /* YES, jiffies is defined as "unsigned long" */ + + /* stations known to us (if we're an ap) */ + client_t sta_list[32]; /* tab is larger than list, so that */ + client_t *sta_hash_tab[64]; /* hash collisions are not likely */ + client_t *ap_client; /* this one is our AP (STA mode only) */ + + int dup_count; + int nondup_count; + unsigned long dup_msg_expiry; + u16 last_seq_ctrl; /* duplicate packet detection */ + + /* 802.11 power save mode */ + u8 ps_wakeup_cfg; + u8 ps_listen_interval; + u8 ps_options; + u8 ps_hangover_period; + u32 ps_enhanced_transition_time; + u32 ps_beacon_rx_time; + + /*** PHY settings ***/ + u8 fallback_threshold; + u8 stepup_threshold; + u16 rate_basic; + u16 rate_oper; + u16 rate_bcast; + u16 rate_bcast100; + u8 rate_auto; /* false if "iwconfig rate N" (WITHOUT 'auto'!) */ + u8 preamble_mode; /* 0 == Long Preamble, 1 == Short, 2 == Auto */ + u8 preamble_cur; + + u8 tx_disabled; + u8 tx_level_dbm; + /* u8 tx_level_val; */ + /* u8 tx_level_auto; whether to do automatic power adjustment */ + + unsigned long recalib_time_last_success; + unsigned long recalib_time_last_attempt; + int recalib_failure_count; + int recalib_msg_ratelimit; + int retry_errors_msg_ratelimit; + + unsigned long brange_time_last_state_change; /* time the power LED was last changed */ + u8 brange_last_state; /* last state of the LED */ + u8 brange_max_quality; /* maximum quality that equates to full speed */ + + u8 sensitivity; + u8 antenna; /* antenna settings */ + u8 ed_threshold; /* energy detect threshold */ + u8 cca; /* clear channel assessment */ + + u16 rts_threshold; + u16 frag_threshold; + u32 short_retry; + u32 long_retry; + u16 msdu_lifetime; + u16 listen_interval; /* given in units of beacon interval */ + u32 beacon_interval; + + u16 capabilities; + u8 rate_supported_len; + u8 rate_supported[13]; + + /*** Encryption settings (WEP) ***/ + u32 auth_alg; /* used in transmit_authen1 */ + u8 wep_enabled; + u8 wep_restricted; + u8 wep_current_index; + wep_key_t wep_keys[DOT11_MAX_DEFAULT_WEP_KEYS]; /* the default WEP keys */ + key_struct_t wep_key_struct[10]; + + /*** Unknown ***/ + u8 dtim_interval; + + /*** Card Rx/Tx management ***/ + u16 rx_config_1; + u16 rx_config_2; + u16 memblocksize; + unsigned int tx_free; + unsigned int tx_head; /* keep as close as possible to Tx stuff below (cache line) */ + u16 phy_header_len; + +/************************************************************************* + *** PCI/USB/... must be last or else hw agnostic code breaks horribly *** + *************************************************************************/ + + /* hack to let common code compile. FIXME */ + dma_addr_t rxhostdesc_startphy; + + /*** PCI stuff ***/ +#ifdef ACX_PCI + /* pointers to tx buffers, tx host descriptors (in host memory) + ** and tx descs in device memory */ + unsigned int tx_tail; + u8 *txbuf_start; + txhostdesc_t *txhostdesc_start; + txdesc_t *txdesc_start; /* points to PCI-mapped memory */ + dma_addr_t txbuf_startphy; + dma_addr_t txhostdesc_startphy; + /* sizes of above host memory areas */ + unsigned int txbuf_area_size; + unsigned int txhostdesc_area_size; + + unsigned int txdesc_size; /* size of txdesc; ACX111 = ACX100 + 4 */ + client_t *txc[TX_CNT]; + u16 txr[TX_CNT]; + + /* same for rx */ + unsigned int rx_tail; + rxbuffer_t *rxbuf_start; + rxhostdesc_t *rxhostdesc_start; + rxdesc_t *rxdesc_start; + /* physical addresses of above host memory areas */ + dma_addr_t rxbuf_startphy; + /* dma_addr_t rxhostdesc_startphy; */ + unsigned int rxbuf_area_size; + unsigned int rxhostdesc_area_size; + + u8 need_radio_fw; + u8 irqs_active; /* whether irq sending is activated */ + + const u16 *io; /* points to ACX100 or ACX111 PCI I/O register address set */ + + struct pci_dev *pdev; + + unsigned long membase; + unsigned long membase2; + void __iomem *iobase; + void __iomem *iobase2; + /* command interface */ + u8 __iomem *cmd_area; + u8 __iomem *info_area; + + u16 irq_mask; /* interrupt types to mask out (not wanted) with many IRQs activated */ + u16 irq_mask_off; /* interrupt types to mask out (not wanted) with IRQs off */ + unsigned int irq_loops_this_jiffy; + unsigned long irq_last_jiffies; +#endif + + /*** USB stuff ***/ +#ifdef ACX_USB + struct usb_device *usbdev; + + rxbuffer_t rxtruncbuf; + + usb_tx_t *usb_tx; + usb_rx_t *usb_rx; + + int bulkinep; /* bulk-in endpoint */ + int bulkoutep; /* bulk-out endpoint */ + int rxtruncsize; +#endif + +}; + +static inline acx_device_t* +ndev2adev(struct net_device *ndev) +{ + return netdev_priv(ndev); +} + + +/* For use with ACX1xx_IE_RXCONFIG */ +/* bit description + * 13 include additional header (length etc.) *required* + * struct is defined in 'struct rxbuffer' + * is this bit acx100 only? does acx111 always put the header, + * and bit setting is irrelevant? --vda + * 10 receive frames only with SSID used in last join cmd + * 9 discard broadcast + * 8 receive packets for multicast address 1 + * 7 receive packets for multicast address 0 + * 6 discard all multicast packets + * 5 discard frames from foreign BSSID + * 4 discard frames with foreign destination MAC address + * 3 promiscuous mode (receive ALL frames, disable filter) + * 2 include FCS + * 1 include phy header + * 0 ??? + */ +#define RX_CFG1_INCLUDE_RXBUF_HDR 0x2000 /* ACX100 only */ +#define RX_CFG1_FILTER_SSID 0x0400 +#define RX_CFG1_FILTER_BCAST 0x0200 +#define RX_CFG1_RCV_MC_ADDR1 0x0100 +#define RX_CFG1_RCV_MC_ADDR0 0x0080 +#define RX_CFG1_FILTER_ALL_MULTI 0x0040 +#define RX_CFG1_FILTER_BSSID 0x0020 +#define RX_CFG1_FILTER_MAC 0x0010 +#define RX_CFG1_RCV_PROMISCUOUS 0x0008 +#define RX_CFG1_INCLUDE_FCS 0x0004 +#define RX_CFG1_INCLUDE_PHY_HDR (WANT_PHY_HDR ? 0x0002 : 0) +/* bit description + * 11 receive association requests etc. + * 10 receive authentication frames + * 9 receive beacon frames + * 8 receive contention free packets + * 7 receive control frames + * 6 receive data frames + * 5 receive broken frames + * 4 receive management frames + * 3 receive probe requests + * 2 receive probe responses + * 1 receive RTS/CTS/ACK frames + * 0 receive other + */ +#define RX_CFG2_RCV_ASSOC_REQ 0x0800 +#define RX_CFG2_RCV_AUTH_FRAMES 0x0400 +#define RX_CFG2_RCV_BEACON_FRAMES 0x0200 +#define RX_CFG2_RCV_CONTENTION_FREE 0x0100 +#define RX_CFG2_RCV_CTRL_FRAMES 0x0080 +#define RX_CFG2_RCV_DATA_FRAMES 0x0040 +#define RX_CFG2_RCV_BROKEN_FRAMES 0x0020 +#define RX_CFG2_RCV_MGMT_FRAMES 0x0010 +#define RX_CFG2_RCV_PROBE_REQ 0x0008 +#define RX_CFG2_RCV_PROBE_RESP 0x0004 +#define RX_CFG2_RCV_ACK_FRAMES 0x0002 +#define RX_CFG2_RCV_OTHER 0x0001 + +/* For use with ACX1xx_IE_FEATURE_CONFIG */ +#define FEATURE1_80MHZ_CLOCK 0x00000040L +#define FEATURE1_4X 0x00000020L +#define FEATURE1_LOW_RX 0x00000008L +#define FEATURE1_EXTRA_LOW_RX 0x00000001L + +#define FEATURE2_SNIFFER 0x00000080L +#define FEATURE2_NO_TXCRYPT 0x00000001L + +/*-- get and set mask values --*/ +#define GETSET_LED_POWER 0x00000001L +#define GETSET_STATION_ID 0x00000002L +#define SET_TEMPLATES 0x00000004L +#define SET_STA_LIST 0x00000008L +#define GETSET_TX 0x00000010L +#define GETSET_RX 0x00000020L +#define SET_RXCONFIG 0x00000040L +#define GETSET_ANTENNA 0x00000080L +#define GETSET_SENSITIVITY 0x00000100L +#define GETSET_TXPOWER 0x00000200L +#define GETSET_ED_THRESH 0x00000400L +#define GETSET_CCA 0x00000800L +#define GETSET_POWER_80211 0x00001000L +#define GETSET_RETRY 0x00002000L +#define GETSET_REG_DOMAIN 0x00004000L +#define GETSET_CHANNEL 0x00008000L +/* Used when ESSID changes etc and we need to scan for AP anew */ +#define GETSET_RESCAN 0x00010000L +#define GETSET_MODE 0x00020000L +#define GETSET_WEP 0x00040000L +#define SET_WEP_OPTIONS 0x00080000L +#define SET_MSDU_LIFETIME 0x00100000L +#define SET_RATE_FALLBACK 0x00200000L + +/* keep in sync with the above */ +#define GETSET_ALL (0 \ +/* GETSET_LED_POWER */ | 0x00000001L \ +/* GETSET_STATION_ID */ | 0x00000002L \ +/* SET_TEMPLATES */ | 0x00000004L \ +/* SET_STA_LIST */ | 0x00000008L \ +/* GETSET_TX */ | 0x00000010L \ +/* GETSET_RX */ | 0x00000020L \ +/* SET_RXCONFIG */ | 0x00000040L \ +/* GETSET_ANTENNA */ | 0x00000080L \ +/* GETSET_SENSITIVITY */| 0x00000100L \ +/* GETSET_TXPOWER */ | 0x00000200L \ +/* GETSET_ED_THRESH */ | 0x00000400L \ +/* GETSET_CCA */ | 0x00000800L \ +/* GETSET_POWER_80211 */| 0x00001000L \ +/* GETSET_RETRY */ | 0x00002000L \ +/* GETSET_REG_DOMAIN */ | 0x00004000L \ +/* GETSET_CHANNEL */ | 0x00008000L \ +/* GETSET_RESCAN */ | 0x00010000L \ +/* GETSET_MODE */ | 0x00020000L \ +/* GETSET_WEP */ | 0x00040000L \ +/* SET_WEP_OPTIONS */ | 0x00080000L \ +/* SET_MSDU_LIFETIME */ | 0x00100000L \ +/* SET_RATE_FALLBACK */ | 0x00200000L \ + ) + + +/*********************************************************************** +** Firmware loading +*/ +#include /* request_firmware() */ +#include /* struct pci_device */ + + +/*********************************************************************** +*/ +typedef struct acx100_ie_memblocksize { + u16 type; + u16 len; + u16 size; +} ACX_PACKED acx100_ie_memblocksize_t; + +typedef struct acx100_ie_queueconfig { + u16 type; + u16 len; + u32 AreaSize; + u32 RxQueueStart; + u8 QueueOptions; + u8 NumTxQueues; + u8 NumRxDesc; /* for USB only */ + u8 pad1; + u32 QueueEnd; + u32 HostQueueEnd; /* QueueEnd2 */ + u32 TxQueueStart; + u8 TxQueuePri; + u8 NumTxDesc; + u16 pad2; +} ACX_PACKED acx100_ie_queueconfig_t; + +typedef struct acx111_ie_queueconfig { + u16 type; + u16 len; + u32 tx_memory_block_address; + u32 rx_memory_block_address; + u32 rx1_queue_address; + u32 reserved1; + u32 tx1_queue_address; + u8 tx1_attributes; + u16 reserved2; + u8 reserved3; +} ACX_PACKED acx111_ie_queueconfig_t; + +typedef struct acx100_ie_memconfigoption { + u16 type; + u16 len; + u32 DMA_config; + acx_ptr pRxHostDesc; + u32 rx_mem; + u32 tx_mem; + u16 RxBlockNum; + u16 TxBlockNum; +} ACX_PACKED acx100_ie_memconfigoption_t; + +typedef struct acx111_ie_memoryconfig { + u16 type; + u16 len; + u16 no_of_stations; + u16 memory_block_size; + u8 tx_rx_memory_block_allocation; + u8 count_rx_queues; + u8 count_tx_queues; + u8 options; + u8 fragmentation; + u16 reserved1; + u8 reserved2; + + /* start of rx1 block */ + u8 rx_queue1_count_descs; + u8 rx_queue1_reserved1; + u8 rx_queue1_type; /* must be set to 7 */ + u8 rx_queue1_prio; /* must be set to 0 */ + acx_ptr rx_queue1_host_rx_start; + /* end of rx1 block */ + + /* start of tx1 block */ + u8 tx_queue1_count_descs; + u8 tx_queue1_reserved1; + u8 tx_queue1_reserved2; + u8 tx_queue1_attributes; + /* end of tx1 block */ +} ACX_PACKED acx111_ie_memoryconfig_t; + +typedef struct acx_ie_memmap { + u16 type; + u16 len; + u32 CodeStart; + u32 CodeEnd; + u32 WEPCacheStart; + u32 WEPCacheEnd; + u32 PacketTemplateStart; + u32 PacketTemplateEnd; + u32 QueueStart; + u32 QueueEnd; + u32 PoolStart; + u32 PoolEnd; +} ACX_PACKED acx_ie_memmap_t; + +typedef struct acx111_ie_feature_config { + u16 type; + u16 len; + u32 feature_options; + u32 data_flow_options; +} ACX_PACKED acx111_ie_feature_config_t; + +typedef struct acx111_ie_tx_level { + u16 type; + u16 len; + u8 level; +} ACX_PACKED acx111_ie_tx_level_t; + +#define PS_CFG_ENABLE 0x80 +#define PS_CFG_PENDING 0x40 /* status flag when entering PS */ +#define PS_CFG_WAKEUP_MODE_MASK 0x07 +#define PS_CFG_WAKEUP_BY_HOST 0x03 +#define PS_CFG_WAKEUP_EACH_ITVL 0x02 +#define PS_CFG_WAKEUP_ON_DTIM 0x01 +#define PS_CFG_WAKEUP_ALL_BEAC 0x00 + +/* Enhanced PS mode: sleep until Rx Beacon w/ the STA's AID bit set +** in the TIM; newer firmwares only(?) */ +#define PS_OPT_ENA_ENHANCED_PS 0x04 +#define PS_OPT_TX_PSPOLL 0x02 /* send PSPoll frame to fetch waiting frames from AP (on frame with matching AID) */ +#define PS_OPT_STILL_RCV_BCASTS 0x01 + +typedef struct acx100_ie_powersave { + u16 type; + u16 len; + u8 wakeup_cfg; + u8 listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */ + u8 options; + u8 hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */ + u16 enhanced_ps_transition_time; /* rem. wake time for Enh. PS */ +} ACX_PACKED acx100_ie_powersave_t; + +typedef struct acx111_ie_powersave { + u16 type; + u16 len; + u8 wakeup_cfg; + u8 listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */ + u8 options; + u8 hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */ + u32 beacon_rx_time; + u32 enhanced_ps_transition_time; /* rem. wake time for Enh. PS */ +} ACX_PACKED acx111_ie_powersave_t; + + +/*********************************************************************** +** Commands and template structures +*/ + +/* +** SCAN command structure +** +** even though acx100 scan rates match RATE100 constants, +** acx111 ones do not match! Therefore we do not use RATE100 #defines */ +#define ACX_SCAN_RATE_1 10 +#define ACX_SCAN_RATE_2 20 +#define ACX_SCAN_RATE_5 55 +#define ACX_SCAN_RATE_11 110 +#define ACX_SCAN_RATE_22 220 +#define ACX_SCAN_RATE_PBCC 0x80 /* OR with this if needed */ +#define ACX_SCAN_OPT_ACTIVE 0x00 /* a bit mask */ +#define ACX_SCAN_OPT_PASSIVE 0x01 +/* Background scan: we go into Power Save mode (by transmitting +** NULL data frame to AP with the power mgmt bit set), do the scan, +** and then exit Power Save mode. A plus is that AP buffers frames +** for us while we do background scan. Thus we avoid frame losses. +** Background scan can be active or passive, just like normal one */ +#define ACX_SCAN_OPT_BACKGROUND 0x02 +typedef struct acx100_scan { + u16 count; /* number of scans to do, 0xffff == continuous */ + u16 start_chan; + u16 flags; /* channel list mask; 0x8000 == all channels? */ + u8 max_rate; /* max. probe rate */ + u8 options; /* bit mask, see defines above */ + u16 chan_duration; + u16 max_probe_delay; +} ACX_PACKED acx100_scan_t; /* length 0xc */ + +#define ACX111_SCAN_RATE_6 0x0B +#define ACX111_SCAN_RATE_9 0x0F +#define ACX111_SCAN_RATE_12 0x0A +#define ACX111_SCAN_RATE_18 0x0E +#define ACX111_SCAN_RATE_24 0x09 +#define ACX111_SCAN_RATE_36 0x0D +#define ACX111_SCAN_RATE_48 0x08 +#define ACX111_SCAN_RATE_54 0x0C +#define ACX111_SCAN_OPT_5GHZ 0x04 /* else 2.4GHZ */ +#define ACX111_SCAN_MOD_SHORTPRE 0x01 /* you can combine SHORTPRE and PBCC */ +#define ACX111_SCAN_MOD_PBCC 0x80 +#define ACX111_SCAN_MOD_OFDM 0x40 +typedef struct acx111_scan { + u16 count; /* number of scans to do */ + u8 channel_list_select; /* 0: scan all channels, 1: from chan_list only */ + u16 reserved1; + u8 reserved2; + u8 rate; /* rate for probe requests (if active scan) */ + u8 options; /* bit mask, see defines above */ + u16 chan_duration; /* min time to wait for reply on one channel (in TU) */ + /* (active scan only) (802.11 section 11.1.3.2.2) */ + u16 max_probe_delay; /* max time to wait for reply on one channel (active scan) */ + /* time to listen on a channel (passive scan) */ + u8 modulation; + u8 channel_list[26]; /* bits 7:0 first byte: channels 8:1 */ + /* bits 7:0 second byte: channels 16:9 */ + /* 26 bytes is enough to cover 802.11a */ +} ACX_PACKED acx111_scan_t; + + +/* +** Radio calibration command structure +*/ +typedef struct acx111_cmd_radiocalib { +/* 0x80000000 == automatic calibration by firmware, according to interval; + * bits 0..3: select calibration methods to go through: + * calib based on DC, AfeDC, Tx mismatch, Tx equilization */ + u32 methods; + u32 interval; +} ACX_PACKED acx111_cmd_radiocalib_t; + + +/* +** Packet template structures +** +** Packet templates store contents of Beacon, Probe response, Probe request, +** Null data frame, and TIM data frame. Firmware automatically transmits +** contents of template at appropriate time: +** - Beacon: when configured as AP or Ad-hoc +** - Probe response: when configured as AP or Ad-hoc, whenever +** a Probe request frame is received +** - Probe request: when host issues SCAN command (active) +** - Null data frame: when entering 802.11 power save mode +** - TIM data: at the end of Beacon frames (if no TIM template +** is configured, then transmits default TIM) +** NB: +** - size field must be set to size of actual template +** (NOT sizeof(struct) - templates are variable in length), +** size field is not itself counted. +** - members flagged with an asterisk must be initialized with host, +** rest must be zero filled. +** - variable length fields shown only in comments */ +typedef struct acx_template_tim { + u16 size; + u8 tim_eid; /* 00 1 TIM IE ID * */ + u8 len; /* 01 1 Length * */ + u8 dtim_cnt; /* 02 1 DTIM Count */ + u8 dtim_period; /* 03 1 DTIM Period */ + u8 bitmap_ctrl; /* 04 1 Bitmap Control * (except bit0) */ + /* 05 n Partial Virtual Bitmap * */ + u8 variable[0x100 - 1-1-1-1-1]; +} ACX_PACKED acx_template_tim_t; + +typedef struct acx_template_probereq { + u16 size; + u16 fc; /* 00 2 fc * */ + u16 dur; /* 02 2 Duration */ + u8 da[6]; /* 04 6 Destination Address * */ + u8 sa[6]; /* 0A 6 Source Address * */ + u8 bssid[6]; /* 10 6 BSSID * */ + u16 seq; /* 16 2 Sequence Control */ + /* 18 n SSID * */ + /* nn n Supported Rates * */ + u8 variable[0x44 - 2-2-6-6-6-2]; +} ACX_PACKED acx_template_probereq_t; + +typedef struct acx_template_proberesp { + u16 size; + u16 fc; /* 00 2 fc * (bits [15:12] and [10:8] per 802.11 section 7.1.3.1) */ + u16 dur; /* 02 2 Duration */ + u8 da[6]; /* 04 6 Destination Address */ + u8 sa[6]; /* 0A 6 Source Address */ + u8 bssid[6]; /* 10 6 BSSID */ + u16 seq; /* 16 2 Sequence Control */ + u8 timestamp[8];/* 18 8 Timestamp */ + u16 beacon_interval; /* 20 2 Beacon Interval * */ + u16 cap; /* 22 2 Capability Information * */ + /* 24 n SSID * */ + /* nn n Supported Rates * */ + /* nn 1 DS Parameter Set * */ + u8 variable[0x54 - 2-2-6-6-6-2-8-2-2]; +} ACX_PACKED acx_template_proberesp_t; +#define acx_template_beacon_t acx_template_proberesp_t +#define acx_template_beacon acx_template_proberesp + +typedef struct acx_template_nullframe { + u16 size; + struct wlan_hdr_a3 hdr; +} ACX_PACKED acx_template_nullframe_t; + + +/* +** JOIN command structure +** +** as opposed to acx100, acx111 dtim interval is AFTER rates_basic111. +** NOTE: took me about an hour to get !@#$%^& packing right --> struct packing is eeeeevil... */ +typedef struct acx_joinbss { + u8 bssid[ETH_ALEN]; + u16 beacon_interval; + union { + struct { + u8 dtim_interval; + u8 rates_basic; + u8 rates_supported; + } ACX_PACKED acx100; + struct { + u16 rates_basic; + u8 dtim_interval; + } ACX_PACKED acx111; + } ACX_PACKED u; + u8 genfrm_txrate; /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */ + u8 genfrm_mod_pre; /* generated frame modulation/preamble: + ** bit7: PBCC, bit6: OFDM (else CCK/DQPSK/DBPSK) + ** bit5: short pre */ + u8 macmode; /* BSS Type, must be one of ACX_MODE_xxx */ + u8 channel; + u8 essid_len; + char essid[IW_ESSID_MAX_SIZE]; +} ACX_PACKED acx_joinbss_t; + +#define JOINBSS_RATES_1 0x01 +#define JOINBSS_RATES_2 0x02 +#define JOINBSS_RATES_5 0x04 +#define JOINBSS_RATES_11 0x08 +#define JOINBSS_RATES_22 0x10 + +/* Looks like missing bits are used to indicate 11g rates! +** (it follows from the fact that constants below match 1:1 to RATE111_nn) +** This was actually seen! Look at that Assoc Request sent by acx111, +** it _does_ contain 11g rates in basic set: +01:30:20.070772 Beacon (xxx) [1.0* 2.0* 5.5* 11.0* 6.0* 9.0* 12.0* 18.0* 24.0* 36.0* 48.0* 54.0* Mbit] ESS CH: 1 +01:30:20.074425 Authentication (Open System)-1: Succesful +01:30:20.076539 Authentication (Open System)-2: +01:30:20.076620 Acknowledgment +01:30:20.088546 Assoc Request (xxx) [1.0* 2.0* 5.5* 6.0* 9.0* 11.0* 12.0* 18.0* 24.0* 36.0* 48.0* 54.0* Mbit] +01:30:20.122413 Assoc Response AID(1) :: Succesful +01:30:20.122679 Acknowledgment +01:30:20.173204 Beacon (xxx) [1.0* 2.0* 5.5* 11.0* 6.0* 9.0* 12.0* 18.0* 24.0* 36.0* 48.0* 54.0* Mbit] ESS CH: 1 +*/ +#define JOINBSS_RATES_BASIC111_1 0x0001 +#define JOINBSS_RATES_BASIC111_2 0x0002 +#define JOINBSS_RATES_BASIC111_5 0x0004 +#define JOINBSS_RATES_BASIC111_11 0x0020 +#define JOINBSS_RATES_BASIC111_22 0x0100 + + +/*********************************************************************** +*/ +typedef struct mem_read_write { + u16 addr; + u16 type; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg.; or maybe it's actually 0x30 for MAC? Better verify it by writing and reading back and checking whether the value holds! */ + u32 len; + u32 data; +} ACX_PACKED mem_read_write_t; + +typedef struct firmware_image { + u32 chksum; + u32 size; + u8 data[1]; /* the byte array of the actual firmware... */ +} ACX_PACKED firmware_image_t; + +typedef struct acx_cmd_radioinit { + u32 offset; + u32 len; +} ACX_PACKED acx_cmd_radioinit_t; + +typedef struct acx100_ie_wep_options { + u16 type; + u16 len; + u16 NumKeys; /* max # of keys */ + u8 WEPOption; /* 0 == decrypt default key only, 1 == override decrypt */ + u8 Pad; /* used only for acx111 */ +} ACX_PACKED acx100_ie_wep_options_t; + +typedef struct ie_dot11WEPDefaultKey { + u16 type; + u16 len; + u8 action; + u8 keySize; + u8 defaultKeyNum; + u8 key[29]; /* check this! was Key[19] */ +} ACX_PACKED ie_dot11WEPDefaultKey_t; + +typedef struct acx111WEPDefaultKey { + u8 MacAddr[ETH_ALEN]; + u16 action; /* NOTE: this is a u16, NOT a u8!! */ + u16 reserved; + u8 keySize; + u8 type; + u8 index; + u8 defaultKeyNum; + u8 counter[6]; + u8 key[32]; /* up to 32 bytes (for TKIP!) */ +} ACX_PACKED acx111WEPDefaultKey_t; + +typedef struct ie_dot11WEPDefaultKeyID { + u16 type; + u16 len; + u8 KeyID; +} ACX_PACKED ie_dot11WEPDefaultKeyID_t; + +typedef struct acx100_cmd_wep_mgmt { + u8 MacAddr[ETH_ALEN]; + u16 Action; + u16 KeySize; + u8 Key[29]; /* 29*8 == 232bits == WEP256 */ +} ACX_PACKED acx100_cmd_wep_mgmt_t; + +typedef struct acx_ie_generic { + u16 type; + u16 len; + union { + /* Association ID IE: just a 16bit value: */ + u16 aid; + /* generic member for quick implementation of commands */ + u8 bytes[32]; + } ACX_PACKED m; +} ACX_PACKED acx_ie_generic_t; + +/*********************************************************************** +*/ +#define CHECK_SIZEOF(type,size) { \ + extern void BUG_bad_size_for_##type(void); \ + if (sizeof(type)!=(size)) BUG_bad_size_for_##type(); \ +} + +static inline void +acx_struct_size_check(void) +{ + CHECK_SIZEOF(txdesc_t, 0x30); + CHECK_SIZEOF(acx100_ie_memconfigoption_t, 24); + CHECK_SIZEOF(acx100_ie_queueconfig_t, 0x20); + CHECK_SIZEOF(acx_joinbss_t, 0x30); + /* IEs need 4 bytes for (type,len) tuple */ + CHECK_SIZEOF(acx111_ie_configoption_t, ACX111_IE_CONFIG_OPTIONS_LEN + 4); +} + + +/*********************************************************************** +** Global data +*/ +extern const u8 acx_bitpos2ratebyte[]; +extern const u8 acx_bitpos2rate100[]; + +extern const u8 acx_reg_domain_ids[]; +extern const char * const acx_reg_domain_strings[]; +enum { + acx_reg_domain_ids_len = 8 +}; + +extern const struct iw_handler_def acx_ioctl_handler_def; --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/wlan_hdr.h +++ linux-2.6.27/ubuntu/misc/wireless/acx/wlan_hdr.h @@ -0,0 +1,497 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +/*********************************************************************** +** This code is based on elements which are +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +** info@linux-wlan.com +** http://www.linux-wlan.com +*/ + +/* mini-doc + +Here are all 11b/11g/11a rates and modulations: + + 11b 11g 11a + --- --- --- + 1 |B |B | + 2 |Q |Q | + 5.5|Cp |C p| + 6 | |Od |O + 9 | |od |o +11 |Cp |C p| +12 | |Od |O +18 | |od |o +22 | | p| +24 | |Od |O +33 | | p| +36 | |od |o +48 | |od |o +54 | |od |o + +Mandatory: + B - DBPSK (Differential Binary Phase Shift Keying) + Q - DQPSK (Differential Quaternary Phase Shift Keying) + C - CCK (Complementary Code Keying, a form of DSSS + (Direct Sequence Spread Spectrum) modulation) + O - OFDM (Orthogonal Frequency Division Multiplexing) +Optional: + o - OFDM + d - CCK-OFDM (also known as DSSS-OFDM) + p - PBCC (Packet Binary Convolutional Coding) + +The term CCK-OFDM may be used interchangeably with DSSS-OFDM +(the IEEE 802.11g-2003 standard uses the latter terminology). +In the CCK-OFDM, the PLCP header of the frame uses the CCK form of DSSS, +while the PLCP payload (the MAC frame) is modulated using OFDM. + +Basically, you must use CCK-OFDM if you have mixed 11b/11g environment, +or else (pure OFDM) 11b equipment may not realize that AP +is sending a packet and start sending its own one. +Sadly, looks like acx111 does not support CCK-OFDM, only pure OFDM. + +Re PBCC: avoid using it. It makes sense only if you have +TI "11b+" hardware. You _must_ use PBCC in order to reach 22Mbps on it. + +Preambles: + +Long preamble (at 1Mbit rate, takes 144 us): + 16 bytes ones + 2 bytes 0xF3A0 (lsb sent first) +PLCP header follows (at 1Mbit also): + 1 byte Signal: speed, in 0.1Mbit units, except for: + 33Mbit: 33 (instead of 330 - doesn't fit in octet) + all CCK-OFDM rates: 30 + 1 byte Service + 0,1,4: reserved + 2: 1=locked clock + 3: 1=PBCC + 5: Length Extension (PBCC 22,33Mbit (11g only)) <- + 6: Length Extension (PBCC 22,33Mbit (11g only)) <- BLACK MAGIC HERE + 7: Length Extension <- + 2 bytes Length (time needed to tx this frame) + a) 5.5 Mbit/s CCK + Length = octets*8/5.5, rounded up to integer + b) 11 Mbit/s CCK + Length = octets*8/11, rounded up to integer + Service bit 7: + 0 = rounding took less than 8/11 + 1 = rounding took more than or equal to 8/11 + c) 5.5 Mbit/s PBCC + Length = (octets+1)*8/5.5, rounded up to integer + d) 11 Mbit/s PBCC + Length = (octets+1)*8/11, rounded up to integer + Service bit 7: + 0 = rounding took less than 8/11 + 1 = rounding took more than or equal to 8/11 + e) 22 Mbit/s PBCC + Length = (octets+1)*8/22, rounded up to integer + Service bits 6,7: + 00 = rounding took less than 8/22ths + 01 = rounding took 8/22...15/22ths + 10 = rounding took 16/22ths or more. + f) 33 Mbit/s PBCC + Length = (octets+1)*8/33, rounded up to integer + Service bits 5,6,7: + 000 rounding took less than 8/33 + 001 rounding took 8/33...15/33 + 010 rounding took 16/33...23/33 + 011 rounding took 24/33...31/33 + 100 rounding took 32/33 or more + 2 bytes CRC + +PSDU follows (up to 2346 bytes at selected rate) + +While Signal value alone is not enough to determine rate and modulation, +Signal+Service is always sufficient. + +Short preamble (at 1Mbit rate, takes 72 us): + 7 bytes zeroes + 2 bytes 0x05CF (lsb sent first) +PLCP header follows *at 2Mbit/s*. Format is the same as in long preamble. +PSDU follows (up to 2346 bytes at selected rate) + +OFDM preamble is completely different, uses OFDM +modulation from the start and thus easily identifiable. +Not shown here. +*/ + + +/*********************************************************************** +** Constants +*/ + +#define WLAN_HDR_A3_LEN 24 +#define WLAN_HDR_A4_LEN 30 +/* IV structure: +** 3 bytes: Initialization Vector (24 bits) +** 1 byte: 0..5: padding, must be 0; 6..7: key selector (0-3) +*/ +#define WLAN_WEP_IV_LEN 4 +/* 802.11 says 2312 but looks like 2312 is a max size of _WEPed data_ */ +#define WLAN_DATA_MAXLEN 2304 +#define WLAN_WEP_ICV_LEN 4 +#define WLAN_FCS_LEN 4 +#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN) +#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN) +#define WLAN_A3FR_MAXLEN_FCS (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + 4) +#define WLAN_A4FR_MAXLEN_FCS (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + 4) +#define WLAN_A3FR_MAXLEN_WEP (WLAN_A3FR_MAXLEN + 8) +#define WLAN_A4FR_MAXLEN_WEP (WLAN_A4FR_MAXLEN + 8) +#define WLAN_A3FR_MAXLEN_WEP_FCS (WLAN_A3FR_MAXLEN_FCS + 8) +#define WLAN_A4FR_MAXLEN_WEP_FCS (WLAN_A4FR_MAXLEN_FCS + 8) + +#define WLAN_BSS_TS_LEN 8 +#define WLAN_SSID_MAXLEN 32 +#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334) +#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0) +#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) +#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48) +#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) +#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54) +#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) +#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44) +#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78) +#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261) +#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) +#define WLAN_CHALLENGE_IE_LEN 130 +#define WLAN_CHALLENGE_LEN 128 +#define WLAN_WEP_MAXKEYLEN 13 +#define WLAN_WEP_NKEYS 4 + +/*--- Frame Control Field -------------------------------------*/ +/* Frame Types */ +#define WLAN_FTYPE_MGMT 0x00 +#define WLAN_FTYPE_CTL 0x01 +#define WLAN_FTYPE_DATA 0x02 + +/* Frame subtypes */ +/* Management */ +#define WLAN_FSTYPE_ASSOCREQ 0x00 +#define WLAN_FSTYPE_ASSOCRESP 0x01 +#define WLAN_FSTYPE_REASSOCREQ 0x02 +#define WLAN_FSTYPE_REASSOCRESP 0x03 +#define WLAN_FSTYPE_PROBEREQ 0x04 +#define WLAN_FSTYPE_PROBERESP 0x05 +#define WLAN_FSTYPE_BEACON 0x08 +#define WLAN_FSTYPE_ATIM 0x09 +#define WLAN_FSTYPE_DISASSOC 0x0a +#define WLAN_FSTYPE_AUTHEN 0x0b +#define WLAN_FSTYPE_DEAUTHEN 0x0c + +/* Control */ +#define WLAN_FSTYPE_PSPOLL 0x0a +#define WLAN_FSTYPE_RTS 0x0b +#define WLAN_FSTYPE_CTS 0x0c +#define WLAN_FSTYPE_ACK 0x0d +#define WLAN_FSTYPE_CFEND 0x0e +#define WLAN_FSTYPE_CFENDCFACK 0x0f + +/* Data */ +#define WLAN_FSTYPE_DATAONLY 0x00 +#define WLAN_FSTYPE_DATA_CFACK 0x01 +#define WLAN_FSTYPE_DATA_CFPOLL 0x02 +#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03 +#define WLAN_FSTYPE_NULL 0x04 +#define WLAN_FSTYPE_CFACK 0x05 +#define WLAN_FSTYPE_CFPOLL 0x06 +#define WLAN_FSTYPE_CFACK_CFPOLL 0x07 + +/*--- FC Constants v. 2.0 ------------------------------------*/ +/* Each constant is defined twice: WF_CONST is in host */ +/* byteorder, WF_CONSTi is in ieee byteorder. */ +/* Usage: */ +/* printf("the frame subtype is %X", WF_FC_FTYPEi & rx.fc); */ +/* tx.fc = WF_FTYPE_CTLi | WF_FSTYPE_RTSi; */ +/*------------------------------------------------------------*/ + +enum { +/*--- Frame Control Field -------------------------------------*/ +/* Protocol version: always 0 for current 802.11 standards */ +IEEE16(WF_FC_PVER, 0x0003) +IEEE16(WF_FC_FTYPE, 0x000c) +IEEE16(WF_FC_FSTYPE, 0x00f0) +IEEE16(WF_FC_TODS, 0x0100) +IEEE16(WF_FC_FROMDS, 0x0200) +IEEE16(WF_FC_FROMTODS, 0x0300) +IEEE16(WF_FC_MOREFRAG, 0x0400) +IEEE16(WF_FC_RETRY, 0x0800) +/* Indicates PS mode in which STA will be after successful completion +** of current frame exchange sequence. Always 0 for AP frames */ +IEEE16(WF_FC_PWRMGT, 0x1000) +/* What MoreData=1 means: +** From AP to STA in PS mode: don't sleep yet, I have more frames for you +** From Contention-Free (CF) Pollable STA in response to a CF-Poll: +** STA has buffered frames for transmission in response to next CF-Poll +** Bcast/mcast frames transmitted from AP: +** when additional bcast/mcast frames remain to be transmitted by AP +** during this beacon interval +** In all other cases MoreData=0 */ +IEEE16(WF_FC_MOREDATA, 0x2000) +IEEE16(WF_FC_ISWEP, 0x4000) +IEEE16(WF_FC_ORDER, 0x8000) + +/* Frame Types */ +IEEE16(WF_FTYPE_MGMT, 0x00) +IEEE16(WF_FTYPE_CTL, 0x04) +IEEE16(WF_FTYPE_DATA, 0x08) + +/* Frame subtypes */ +/* Management */ +IEEE16(WF_FSTYPE_ASSOCREQ, 0x00) +IEEE16(WF_FSTYPE_ASSOCRESP, 0x10) +IEEE16(WF_FSTYPE_REASSOCREQ, 0x20) +IEEE16(WF_FSTYPE_REASSOCRESP, 0x30) +IEEE16(WF_FSTYPE_PROBEREQ, 0x40) +IEEE16(WF_FSTYPE_PROBERESP, 0x50) +IEEE16(WF_FSTYPE_BEACON, 0x80) +IEEE16(WF_FSTYPE_ATIM, 0x90) +IEEE16(WF_FSTYPE_DISASSOC, 0xa0) +IEEE16(WF_FSTYPE_AUTHEN, 0xb0) +IEEE16(WF_FSTYPE_DEAUTHEN, 0xc0) + +/* Control */ +IEEE16(WF_FSTYPE_PSPOLL, 0xa0) +IEEE16(WF_FSTYPE_RTS, 0xb0) +IEEE16(WF_FSTYPE_CTS, 0xc0) +IEEE16(WF_FSTYPE_ACK, 0xd0) +IEEE16(WF_FSTYPE_CFEND, 0xe0) +IEEE16(WF_FSTYPE_CFENDCFACK, 0xf0) + +/* Data */ +IEEE16(WF_FSTYPE_DATAONLY, 0x00) +IEEE16(WF_FSTYPE_DATA_CFACK, 0x10) +IEEE16(WF_FSTYPE_DATA_CFPOLL, 0x20) +IEEE16(WF_FSTYPE_DATA_CFACK_CFPOLL, 0x30) +IEEE16(WF_FSTYPE_NULL, 0x40) +IEEE16(WF_FSTYPE_CFACK, 0x50) +IEEE16(WF_FSTYPE_CFPOLL, 0x60) +IEEE16(WF_FSTYPE_CFACK_CFPOLL, 0x70) +}; + + +/*********************************************************************** +** Macros +*/ + +/*--- Duration Macros ----------------------------------------*/ +/* Macros to get/set the bitfields of the Duration Field */ +/* - the duration value is only valid when bit15 is zero */ +/* - the firmware handles these values, so I'm not going */ +/* to use these macros right now. */ +/*------------------------------------------------------------*/ + +/*--- Sequence Control Macros -------------------------------*/ +/* Macros to get/set the bitfields of the Sequence Control */ +/* Field. */ +/*------------------------------------------------------------*/ +#define WLAN_GET_SEQ_FRGNUM(n) ((u16)(n) & 0x000f) +#define WLAN_GET_SEQ_SEQNUM(n) (((u16)(n) & 0xfff0) >> 4) + +/*--- Data ptr macro -----------------------------------------*/ +/* Creates a u8* to the data portion of a frame */ +/* Assumes you're passing in a ptr to the beginning of the hdr*/ +/*------------------------------------------------------------*/ +#define WLAN_HDR_A3_DATAP(p) (((u8*)(p)) + WLAN_HDR_A3_LEN) +#define WLAN_HDR_A4_DATAP(p) (((u8*)(p)) + WLAN_HDR_A4_LEN) + + +/*********************************************************************** +** Types +*/ + +/* 802.11 header type +** +** Note the following: +** a1 *always* is receiver's mac or bcast/mcast +** a2 *always* is transmitter's mac, if a2 exists +** seq: [0:3] frag#, [4:15] seq# - used for dup detection +** (dups from retries have same seq#) */ +typedef struct wlan_hdr { + u16 fc; + u16 dur; + u8 a1[ETH_ALEN]; + u8 a2[ETH_ALEN]; + u8 a3[ETH_ALEN]; + u16 seq; + u8 a4[ETH_ALEN]; +} WLAN_PACKED wlan_hdr_t; + +/* Separate structs for use if frame type is known */ +typedef struct wlan_hdr_a3 { + u16 fc; + u16 dur; + u8 a1[ETH_ALEN]; + u8 a2[ETH_ALEN]; + u8 a3[ETH_ALEN]; + u16 seq; +} WLAN_PACKED wlan_hdr_a3_t; + +typedef struct wlan_hdr_mgmt { + u16 fc; + u16 dur; + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u16 seq; +} WLAN_PACKED wlan_hdr_mgmt_t; + +#ifdef NOT_NEEDED_YET +typedef struct { /* ad-hoc peer->peer (to/from DS = 0/0) */ + u16 fc; + u16 dur; + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u16 seq; +} WLAN_PACKED ibss; +typedef struct { /* ap->sta (to/from DS = 0/1) */ + u16 fc; + u16 dur; + u8 da[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u16 seq; +} WLAN_PACKED fromap; +typedef struct { /* sta->ap (to/from DS = 1/0) */ + u16 fc; + u16 dur; + u8 bssid[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u8 da[ETH_ALEN]; + u16 seq; +} WLAN_PACKED toap; +typedef struct { /* wds->wds (to/from DS = 1/1), the only 4addr pkt */ + u16 fc; + u16 dur; + u8 ra[ETH_ALEN]; + u8 ta[ETH_ALEN]; + u8 da[ETH_ALEN]; + u16 seq; + u8 sa[ETH_ALEN]; +} WLAN_PACKED wds; +typedef struct { /* all management packets */ + u16 fc; + u16 dur; + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u16 seq; +} WLAN_PACKED mgmt; +typedef struct { /* has no body, just a FCS */ + u16 fc; + u16 dur; + u8 ra[ETH_ALEN]; + u8 ta[ETH_ALEN]; +} WLAN_PACKED rts; +typedef struct { /* has no body, just a FCS */ + u16 fc; + u16 dur; + u8 ra[ETH_ALEN]; +} WLAN_PACKED cts; +typedef struct { /* has no body, just a FCS */ + u16 fc; + u16 dur; + u8 ra[ETH_ALEN]; +} WLAN_PACKED ack; +typedef struct { /* has no body, just a FCS */ + u16 fc; + /* NB: this one holds Assoc ID in dur field: */ + u16 aid; + u8 bssid[ETH_ALEN]; + u8 ta[ETH_ALEN]; +} WLAN_PACKED pspoll; +typedef struct { /* has no body, just a FCS */ + u16 fc; + u16 dur; + u8 ra[ETH_ALEN]; + u8 bssid[ETH_ALEN]; +} WLAN_PACKED cfend; +typedef struct { /* has no body, just a FCS */ + u16 fc; + u16 dur; + u8 ra[ETH_ALEN]; + u8 bssid[ETH_ALEN]; +} WLAN_PACKED cfendcfack; +#endif + +/* Prism header emulation (monitor mode) */ +typedef struct wlanitem_u32 { + u32 did; + u16 status; + u16 len; + u32 data; +} WLAN_PACKED wlanitem_u32_t; +#define WLANITEM_STATUS_data_ok 0 +#define WLANITEM_STATUS_no_value 1 +#define WLANITEM_STATUS_invalid_itemname 2 +#define WLANITEM_STATUS_invalid_itemdata 3 +#define WLANITEM_STATUS_missing_itemdata 4 +#define WLANITEM_STATUS_incomplete_itemdata 5 +#define WLANITEM_STATUS_invalid_msg_did 6 +#define WLANITEM_STATUS_invalid_mib_did 7 +#define WLANITEM_STATUS_missing_conv_func 8 +#define WLANITEM_STATUS_string_too_long 9 +#define WLANITEM_STATUS_data_out_of_range 10 +#define WLANITEM_STATUS_string_too_short 11 +#define WLANITEM_STATUS_missing_valid_func 12 +#define WLANITEM_STATUS_unknown 13 +#define WLANITEM_STATUS_invalid_did 14 +#define WLANITEM_STATUS_missing_print_func 15 + +#define WLAN_DEVNAMELEN_MAX 16 +typedef struct wlansniffrm { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + wlanitem_u32_t hosttime; + wlanitem_u32_t mactime; + wlanitem_u32_t channel; + wlanitem_u32_t rssi; + wlanitem_u32_t sq; + wlanitem_u32_t signal; + wlanitem_u32_t noise; + wlanitem_u32_t rate; + wlanitem_u32_t istx; /* tx? 0:no 1:yes */ + wlanitem_u32_t frmlen; +} WLAN_PACKED wlansniffrm_t; +#define WLANSNIFFFRM 0x0041 +#define WLANSNIFFFRM_hosttime 0x1041 +#define WLANSNIFFFRM_mactime 0x2041 +#define WLANSNIFFFRM_channel 0x3041 +#define WLANSNIFFFRM_rssi 0x4041 +#define WLANSNIFFFRM_sq 0x5041 +#define WLANSNIFFFRM_signal 0x6041 +#define WLANSNIFFFRM_noise 0x7041 +#define WLANSNIFFFRM_rate 0x8041 +#define WLANSNIFFFRM_istx 0x9041 +#define WLANSNIFFFRM_frmlen 0xA041 --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/conv.c +++ linux-2.6.27/ubuntu/misc/wireless/acx/conv.c @@ -0,0 +1,504 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +#include +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) +#include +#endif +#include +#include +#include +#include +#include + +#include "acx.h" + + +/*********************************************************************** +** proto_is_stt +** +** Searches the 802.1h Selective Translation Table for a given +** protocol. +** +** prottype - protocol number (in host order) to search for. +** +** Returns: +** 1 - if the table is empty or a match is found. +** 0 - if the table is non-empty and a match is not found. +** +** Based largely on p80211conv.c of the linux-wlan-ng project +*/ +static inline int +proto_is_stt(unsigned int proto) +{ + /* Always return found for now. This is the behavior used by the */ + /* Zoom Win95 driver when 802.1h mode is selected */ + /* TODO: If necessary, add an actual search we'll probably + need this to match the CMAC's way of doing things. + Need to do some testing to confirm. + */ + + if (proto == 0x80f3) /* APPLETALK */ + return 1; + + return 0; +/* return ((prottype == ETH_P_AARP) || (prottype == ETH_P_IPX)); */ +} + +/* Helpers */ + +static inline void +store_llc_snap(struct wlan_llc *llc) +{ + llc->dsap = 0xaa; /* SNAP, see IEEE 802 */ + llc->ssap = 0xaa; + llc->ctl = 0x03; +} +static inline int +llc_is_snap(const struct wlan_llc *llc) +{ + return (llc->dsap == 0xaa) + && (llc->ssap == 0xaa) + && (llc->ctl == 0x03); +} +static inline void +store_oui_rfc1042(struct wlan_snap *snap) +{ + snap->oui[0] = 0; + snap->oui[1] = 0; + snap->oui[2] = 0; +} +static inline int +oui_is_rfc1042(const struct wlan_snap *snap) +{ + return (snap->oui[0] == 0) + && (snap->oui[1] == 0) + && (snap->oui[2] == 0); +} +static inline void +store_oui_8021h(struct wlan_snap *snap) +{ + snap->oui[0] = 0; + snap->oui[1] = 0; + snap->oui[2] = 0xf8; +} +static inline int +oui_is_8021h(const struct wlan_snap *snap) +{ + return (snap->oui[0] == 0) + && (snap->oui[1] == 0) + && (snap->oui[2] == 0xf8); +} + + +/*********************************************************************** +** acx_ether_to_txbuf +** +** Uses the contents of the ether frame to build the elements of +** the 802.11 frame. +** +** We don't actually set up the frame header here. That's the +** MAC's job. We're only handling conversion of DIXII or 802.3+LLC +** frames to something that works with 802.11. +** +** Based largely on p80211conv.c of the linux-wlan-ng project +*/ +int +acx_ether_to_txbuf(acx_device_t *adev, void *txbuf, const struct sk_buff *skb) +{ + struct wlan_hdr_a3 *w_hdr; + struct wlan_ethhdr *e_hdr; + struct wlan_llc *e_llc; + struct wlan_snap *e_snap; + const u8 *a1, *a3; + int header_len, payload_len = -1; + /* protocol type or data length, depending on whether + * DIX or 802.3 ethernet format */ + u16 proto; + u16 fc; + + FN_ENTER; + + if (unlikely(!skb->len)) { + log(L_DEBUG, "zero-length skb!\n"); + goto end; + } + + w_hdr = (struct wlan_hdr_a3*)txbuf; + + switch (adev->mode) { + case ACX_MODE_MONITOR: + /* NB: one day we might want to play with DESC_CTL2_FCS + ** Will need to stop doing "- WLAN_FCS_LEN" here then */ + if (unlikely(skb->len >= WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_FCS_LEN)) { + printk("%s: can't tx oversized frame (%d bytes)\n", + adev->ndev->name, skb->len); + goto end; + } + memcpy(w_hdr, skb->data, skb->len); + payload_len = skb->len; + goto end; + } + + /* step 1: classify ether frame, DIX or 802.3? */ + e_hdr = (wlan_ethhdr_t *)skb->data; + proto = ntohs(e_hdr->type); + if (proto <= 1500) { + log(L_DEBUG, "tx: 802.3 len: %d\n", skb->len); + /* codes <= 1500 reserved for 802.3 lengths */ + /* it's 802.3, pass ether payload unchanged, */ + /* trim off ethernet header and copy payload to txdesc */ + header_len = WLAN_HDR_A3_LEN; + } else { + /* it's DIXII, time for some conversion */ + /* Create 802.11 packet. Header also contains llc and snap. */ + + log(L_DEBUG, "tx: DIXII len: %d\n", skb->len); + + /* size of header is 802.11 header + llc + snap */ + header_len = WLAN_HDR_A3_LEN + sizeof(wlan_llc_t) + sizeof(wlan_snap_t); + /* llc is located behind the 802.11 header */ + e_llc = (wlan_llc_t*)(w_hdr + 1); + /* snap is located behind the llc */ + e_snap = (wlan_snap_t*)(e_llc + 1); + + /* setup the LLC header */ + store_llc_snap(e_llc); + + /* setup the SNAP header */ + e_snap->type = htons(proto); + if (proto_is_stt(proto)) { + store_oui_8021h(e_snap); + } else { + store_oui_rfc1042(e_snap); + } + } + /* trim off ethernet header and copy payload to txbuf */ + payload_len = skb->len - sizeof(wlan_ethhdr_t); + /* TODO: can we just let acx DMA payload from skb instead? */ + memcpy((u8*)txbuf + header_len, skb->data + sizeof(wlan_ethhdr_t), payload_len); + payload_len += header_len; + + /* Set up the 802.11 header */ + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi); + a1 = e_hdr->daddr; + a3 = adev->bssid; + break; + case ACX_MODE_2_STA: + fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_TODSi); + a1 = adev->bssid; + a3 = e_hdr->daddr; + break; + case ACX_MODE_3_AP: + fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_FROMDSi); + a1 = e_hdr->daddr; + a3 = e_hdr->saddr; + break; + default: + printk("%s: error - converting eth to wlan in unknown mode\n", + adev->ndev->name); + payload_len = -1; + goto end; + } + if (adev->wep_enabled) + SET_BIT(fc, WF_FC_ISWEPi); + + w_hdr->fc = fc; + w_hdr->dur = 0; + MAC_COPY(w_hdr->a1, a1); + MAC_COPY(w_hdr->a2, adev->dev_addr); + MAC_COPY(w_hdr->a3, a3); + w_hdr->seq = 0; + +#ifdef DEBUG_CONVERT + if (acx_debug & L_DATA) { + printk("original eth frame [%d]: ", skb->len); + acx_dump_bytes(skb->data, skb->len); + printk("802.11 frame [%d]: ", payload_len); + acx_dump_bytes(w_hdr, payload_len); + } +#endif + +end: + FN_EXIT1(payload_len); + return payload_len; +} + + +/*********************************************************************** +** acx_rxbuf_to_ether +** +** Uses the contents of a received 802.11 frame to build an ether +** frame. +** +** This function extracts the src and dest address from the 802.11 +** frame to use in the construction of the eth frame. +** +** Based largely on p80211conv.c of the linux-wlan-ng project +*/ +struct sk_buff* +acx_rxbuf_to_ether(acx_device_t *adev, rxbuffer_t *rxbuf) +{ + struct wlan_hdr *w_hdr; + struct wlan_ethhdr *e_hdr; + struct wlan_llc *e_llc; + struct wlan_snap *e_snap; + struct sk_buff *skb; + const u8 *daddr; + const u8 *saddr; + const u8 *e_payload; + int buflen, payload_length; + unsigned int payload_offset, mtu; + u16 fc; + + FN_ENTER; + + /* This looks complex because it must handle possible + ** phy header in rxbuff */ + w_hdr = acx_get_wlan_hdr(adev, rxbuf); + payload_offset = WLAN_HDR_A3_LEN; /* it is relative to w_hdr */ + payload_length = RXBUF_BYTES_USED(rxbuf) /* entire rxbuff... */ + - ((u8*)w_hdr - (u8*)rxbuf) /* minus space before 802.11 frame */ + - WLAN_HDR_A3_LEN; /* minus 802.11 header */ + + /* setup some vars for convenience */ + fc = w_hdr->fc; + switch (WF_FC_FROMTODSi & fc) { + case 0: + daddr = w_hdr->a1; + saddr = w_hdr->a2; + break; + case WF_FC_FROMDSi: + daddr = w_hdr->a1; + saddr = w_hdr->a3; + break; + case WF_FC_TODSi: + daddr = w_hdr->a3; + saddr = w_hdr->a2; + break; + default: /* WF_FC_FROMTODSi */ + payload_offset += (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN); + payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN); + daddr = w_hdr->a3; + saddr = w_hdr->a4; + } + + if ((WF_FC_ISWEPi & fc) && IS_ACX100(adev)) { + /* chop off the IV+ICV WEP header and footer */ + log(L_DATA|L_DEBUG, "rx: WEP packet, " + "chopping off IV and ICV\n"); + payload_offset += WLAN_WEP_IV_LEN; + payload_length -= WLAN_WEP_IV_LEN + WLAN_WEP_ICV_LEN; + } + + if (unlikely(payload_length < 0)) { + printk("%s: rx frame too short, ignored\n", adev->ndev->name); + goto ret_null; + } + + e_hdr = (wlan_ethhdr_t*) ((u8*) w_hdr + payload_offset); + e_llc = (wlan_llc_t*) e_hdr; + e_snap = (wlan_snap_t*) (e_llc + 1); + mtu = adev->ndev->mtu; + e_payload = (u8*) (e_snap + 1); + + log(L_DATA, "rx: payload_offset %d, payload_length %d\n", + payload_offset, payload_length); + log(L_XFER|L_DATA, + "rx: frame info: llc=%02X%02X%02X " + "snap.oui=%02X%02X%02X snap.type=%04X\n", + e_llc->dsap, e_llc->ssap, e_llc->ctl, + e_snap->oui[0], e_snap->oui[1], e_snap->oui[2], + ntohs(e_snap->type)); + + /* Test for the various encodings */ + if ((payload_length >= sizeof(wlan_ethhdr_t)) + && ((e_llc->dsap != 0xaa) || (e_llc->ssap != 0xaa)) + && ( (mac_is_equal(daddr, e_hdr->daddr)) + || (mac_is_equal(saddr, e_hdr->saddr)) + ) + ) { + /* 802.3 Encapsulated: */ + /* wlan frame body contains complete eth frame (header+body) */ + log(L_DEBUG|L_DATA, "rx: 802.3 ENCAP len=%d\n", payload_length); + + if (unlikely(payload_length > (mtu + ETH_HLEN))) { + printk("%s: rx: ENCAP frame too large (%d > %d)\n", + adev->ndev->name, + payload_length, mtu + ETH_HLEN); + goto ret_null; + } + + /* allocate space and setup host buffer */ + buflen = payload_length; + /* Attempt to align IP header (14 bytes eth header + 2 = 16) */ + skb = dev_alloc_skb(buflen + 2); + if (unlikely(!skb)) + goto no_skb; + skb_reserve(skb, 2); + skb_put(skb, buflen); /* make room */ + + /* now copy the data from the 80211 frame */ + memcpy(skb->data, e_hdr, payload_length); + + } else if ( (payload_length >= sizeof(wlan_llc_t)+sizeof(wlan_snap_t)) + && llc_is_snap(e_llc) ) { + /* wlan frame body contains: AA AA 03 ... (it's a SNAP) */ + + if ( !oui_is_rfc1042(e_snap) + || (proto_is_stt(ieee2host16(e_snap->type)) /* && (ethconv == WLAN_ETHCONV_8021h) */)) { + log(L_DEBUG|L_DATA, "rx: SNAP+RFC1042 len=%d\n", payload_length); + /* wlan frame body contains: AA AA 03 !(00 00 00) ... -or- */ + /* wlan frame body contains: AA AA 03 00 00 00 0x80f3 ... */ + /* build eth hdr, type = len, copy AA AA 03... as eth body */ + /* it's a SNAP + RFC1042 frame && protocol is in STT */ + + if (unlikely(payload_length > mtu)) { + printk("%s: rx: SNAP frame too large (%d > %d)\n", + adev->ndev->name, + payload_length, mtu); + goto ret_null; + } + + /* allocate space and setup host buffer */ + buflen = payload_length + ETH_HLEN; + skb = dev_alloc_skb(buflen + 2); + if (unlikely(!skb)) + goto no_skb; + skb_reserve(skb, 2); + skb_put(skb, buflen); /* make room */ + + /* create 802.3 header */ + e_hdr = (wlan_ethhdr_t*) skb->data; + MAC_COPY(e_hdr->daddr, daddr); + MAC_COPY(e_hdr->saddr, saddr); + e_hdr->type = htons(payload_length); + + /* Now copy the data from the 80211 frame. + Make room in front for the eth header, and keep the + llc and snap from the 802.11 payload */ + memcpy(skb->data + ETH_HLEN, + e_llc, payload_length); + + } else { + /* wlan frame body contains: AA AA 03 00 00 00 [type] [tail] */ + /* build eth hdr, type=[type], copy [tail] as eth body */ + log(L_DEBUG|L_DATA, "rx: 802.1h/RFC1042 len=%d\n", + payload_length); + /* it's an 802.1h frame (an RFC1042 && protocol is not in STT) */ + /* build a DIXII + RFC894 */ + + payload_length -= sizeof(wlan_llc_t) + sizeof(wlan_snap_t); + if (unlikely(payload_length > mtu)) { + printk("%s: rx: DIXII frame too large (%d > %d)\n", + adev->ndev->name, + payload_length, mtu); + goto ret_null; + } + + /* allocate space and setup host buffer */ + buflen = payload_length + ETH_HLEN; + skb = dev_alloc_skb(buflen + 2); + if (unlikely(!skb)) + goto no_skb; + skb_reserve(skb, 2); + skb_put(skb, buflen); /* make room */ + + /* create 802.3 header */ + e_hdr = (wlan_ethhdr_t *) skb->data; + MAC_COPY(e_hdr->daddr, daddr); + MAC_COPY(e_hdr->saddr, saddr); + e_hdr->type = e_snap->type; + + /* Now copy the data from the 80211 frame. + Make room in front for the eth header, and cut off the + llc and snap from the 802.11 payload */ + memcpy(skb->data + ETH_HLEN, + e_payload, payload_length); + } + + } else { + log(L_DEBUG|L_DATA, "rx: NON-ENCAP len=%d\n", payload_length); + /* build eth hdr, type=len, copy wlan body as eth body */ + /* any NON-ENCAP */ + /* it's a generic 80211+LLC or IPX 'Raw 802.3' */ + /* build an 802.3 frame */ + + if (unlikely(payload_length > mtu)) { + printk("%s: rx: OTHER frame too large (%d > %d)\n", + adev->ndev->name, payload_length, mtu); + goto ret_null; + } + + /* allocate space and setup host buffer */ + buflen = payload_length + ETH_HLEN; + skb = dev_alloc_skb(buflen + 2); + if (unlikely(!skb)) + goto no_skb; + skb_reserve(skb, 2); + skb_put(skb, buflen); /* make room */ + + /* set up the 802.3 header */ + e_hdr = (wlan_ethhdr_t *) skb->data; + MAC_COPY(e_hdr->daddr, daddr); + MAC_COPY(e_hdr->saddr, saddr); + e_hdr->type = htons(payload_length); + + /* now copy the data from the 80211 frame */ + memcpy(skb->data + ETH_HLEN, e_llc, payload_length); + } + + skb->dev = adev->ndev; + skb->protocol = eth_type_trans(skb, adev->ndev); + +#ifdef DEBUG_CONVERT + if (acx_debug & L_DATA) { + int len = RXBUF_BYTES_RCVD(adev, rxbuf); + printk("p802.11 frame [%d]: ", len); + acx_dump_bytes(w_hdr, len); + printk("eth frame [%d]: ", skb->len); + acx_dump_bytes(skb->data, skb->len); + } +#endif + + FN_EXIT0; + return skb; + +no_skb: + printk("%s: rx: no memory for skb (%d bytes)\n", + adev->ndev->name, buflen + 2); +ret_null: + FN_EXIT1((int)NULL); + return NULL; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/setrate.c +++ linux-2.6.27/ubuntu/misc/wireless/acx/setrate.c @@ -0,0 +1,213 @@ +/* TODO: stop #including, move into wireless.c + * until then, keep in sync copies in prism54/ and acx/ dirs + * code+data size: less than 1k */ + +enum { + DOT11_RATE_1, + DOT11_RATE_2, + DOT11_RATE_5, + DOT11_RATE_11, + DOT11_RATE_22, + DOT11_RATE_33, + DOT11_RATE_6, + DOT11_RATE_9, + DOT11_RATE_12, + DOT11_RATE_18, + DOT11_RATE_24, + DOT11_RATE_36, + DOT11_RATE_48, + DOT11_RATE_54 +}; +enum { + DOT11_MOD_DBPSK, + DOT11_MOD_DQPSK, + DOT11_MOD_CCK, + DOT11_MOD_OFDM, + DOT11_MOD_CCKOFDM, + DOT11_MOD_PBCC +}; +static const u8 ratelist[] = { 1,2,5,11,22,33,6,9,12,18,24,36,48,54 }; +static const u8 dot11ratebyte[] = { 1*2,2*2,11,11*2,22*2,33*2,6*2,9*2,12*2,18*2,24*2,36*2,48*2,54*2 }; +static const u8 default_modulation[] = { + DOT11_MOD_DBPSK, + DOT11_MOD_DQPSK, + DOT11_MOD_CCK, + DOT11_MOD_CCK, + DOT11_MOD_PBCC, + DOT11_MOD_PBCC, + DOT11_MOD_OFDM, + DOT11_MOD_OFDM, + DOT11_MOD_OFDM, + DOT11_MOD_OFDM, + DOT11_MOD_OFDM, + DOT11_MOD_OFDM, + DOT11_MOD_OFDM, + DOT11_MOD_OFDM +}; + +static /* TODO: remove 'static' when moved to wireless.c */ +int +rate_mbit2enum(int n) { + int i=0; + while(i=DOT11_RATE_6) return DOT11_MOD_OFDM; */ + return default_modulation[r_enum]; + } + if(suffix=='c') { + if(r_enumDOT11_RATE_11) return -EINVAL; + return DOT11_MOD_CCK; + } + if(suffix=='p') { + if(r_enumDOT11_RATE_33) return -EINVAL; + return DOT11_MOD_PBCC; + } + if(suffix=='o') { + if(r_enumINT_MAX) return -EINVAL; + + rate_enum = rate_mbit2enum(rate_mbit); + if(rate_enum<0) return rate_enum; + + c = *str; + mod = get_modulation(rate_enum, c); + if(mod<0) return mod; + + if(c>='a' && c<='z') c = *++str; + if(c!=',' && c!=' ' && c!='\0') return -EINVAL; + + if(supported) { + int r = supported(rate_mbit, mod, opaque); + if(r) return r; + } + + *vector++ = dot11ratebyte[rate_enum] | or_mask; + + size--; + str++; + } while(size>0 && c==','); + + if(size<1) return -E2BIG; + *vector=0; /* TODO: sort, remove dups? */ + + *pstr = str-1; + return 0; +} + +static /* TODO: remove 'static' when moved to wireless.c */ +int +fill_ratevectors(const char *str, u8 *brate, u8 *orate, int size, + int (*supported)(int mbit, int mod, void *opaque), void *opaque) +{ + int r; + + r = fill_ratevector(&str, brate, size, supported, opaque, 0x80); + if(r) return r; + + orate[0] = 0; + if(*str==' ') { + str++; + r = fill_ratevector(&str, orate, size, supported, opaque, 0); + if(r) return r; + /* TODO: sanitize, e.g. remove/error on rates already in basic rate set? */ + } + if(*str) + return -EINVAL; + + return 0; +} +#endif + +/* TODO: use u64 masks? */ + +static int +fill_ratemask(const char **pstr, u32* mask, + int (*supported)(int mbit, int mod,void *opaque), + u32 (*gen_mask)(int mbit, int mod,void *opaque), + void *opaque) +{ + unsigned long rate_mbit; + int rate_enum,mod; + u32 m = 0; + const char *str = *pstr; + char c; + + do { + rate_mbit = simple_strtoul(str, (char**)&str, 10); + if(rate_mbit>INT_MAX) return -EINVAL; + + rate_enum = rate_mbit2enum(rate_mbit); + if(rate_enum<0) return rate_enum; + + c = *str; + mod = get_modulation(rate_enum, c); + if(mod<0) return mod; + + if(c>='a' && c<='z') c = *++str; + if(c!=',' && c!=' ' && c!='\0') return -EINVAL; + + if(supported) { + int r = supported(rate_mbit, mod, opaque); + if(r) return r; + } + + m |= gen_mask(rate_mbit, mod, opaque); + str++; + } while(c==','); + + *pstr = str-1; + *mask |= m; + return 0; +} + +static /* TODO: remove 'static' when moved to wireless.c */ +int +fill_ratemasks(const char *str, u32 *bmask, u32 *omask, + int (*supported)(int mbit, int mod,void *opaque), + u32 (*gen_mask)(int mbit, int mod,void *opaque), + void *opaque) +{ + int r; + + r = fill_ratemask(&str, bmask, supported, gen_mask, opaque); + if(r) return r; + + if(*str==' ') { + str++; + r = fill_ratemask(&str, omask, supported, gen_mask, opaque); + if(r) return r; + } + if(*str) + return -EINVAL; + return 0; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/wlan.c +++ linux-2.6.27/ubuntu/misc/wireless/acx/wlan.c @@ -0,0 +1,421 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +/*********************************************************************** +** This code is based on elements which are +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +** info@linux-wlan.com +** http://www.linux-wlan.com +*/ + +#include +#include +#include +#include +#include + +#include "acx.h" + + +/*********************************************************************** +*/ +#define LOG_BAD_EID(hdr,len,ie_ptr) acx_log_bad_eid(hdr, len, ((wlan_ie_t*)ie_ptr)) + +#define IE_EID(ie_ptr) (((wlan_ie_t*)(ie_ptr))->eid) +#define IE_LEN(ie_ptr) (((wlan_ie_t*)(ie_ptr))->len) +#define OFFSET(hdr,off) (WLAN_HDR_A3_DATAP(hdr) + (off)) + + +/*********************************************************************** +** wlan_mgmt_decode_XXX +** +** Given a complete frame in f->hdr, sets the pointers in f to +** the areas that correspond to the parts of the frame. +** +** Assumptions: +** 1) f->len and f->hdr are already set +** 2) f->len is the length of the MAC header + data, the FCS +** is NOT included +** 3) all members except len and hdr are zero +** Arguments: +** f frame structure +** +** Returns: +** nothing +** +** Side effects: +** frame structure members are pointing at their +** respective portions of the frame buffer. +*/ +void +wlan_mgmt_decode_beacon(wlan_fr_beacon_t * f) +{ + u8 *ie_ptr; + u8 *end = (u8*)f->hdr + f->len; + + f->type = WLAN_FSTYPE_BEACON; + + /*-- Fixed Fields ----*/ + f->ts = (u64 *) OFFSET(f->hdr, WLAN_BEACON_OFF_TS); + f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_BCN_INT); + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_CAPINFO); + + /*-- Information elements */ + ie_ptr = OFFSET(f->hdr, WLAN_BEACON_OFF_SSID); + while (ie_ptr < end) { + switch (IE_EID(ie_ptr)) { + case WLAN_EID_SSID: + f->ssid = (wlan_ie_ssid_t *) ie_ptr; + break; + case WLAN_EID_SUPP_RATES: + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + case WLAN_EID_EXT_RATES: + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + case WLAN_EID_FH_PARMS: + f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr; + break; + case WLAN_EID_DS_PARMS: + f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr; + break; + case WLAN_EID_CF_PARMS: + f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr; + break; + case WLAN_EID_IBSS_PARMS: + f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr; + break; + case WLAN_EID_TIM: + f->tim = (wlan_ie_tim_t *) ie_ptr; + break; + case WLAN_EID_ERP_INFO: + f->erp = (wlan_ie_erp_t *) ie_ptr; + break; + + case WLAN_EID_COUNTRY: + /* was seen: 07 06 47 42 20 01 0D 14 */ + case WLAN_EID_PWR_CONSTRAINT: + /* was seen by Ashwin Mansinghka from + Atheros-based PCI card in AP mode using madwifi drivers: */ + /* 20 01 00 */ + case WLAN_EID_NONERP: + /* was seen from WRT54GS with OpenWrt: 2F 01 07 */ + case WLAN_EID_UNKNOWN128: + /* was seen by Jacek Jablonski from Orinoco AP */ + /* 80 06 00 60 1D 2C 3B 00 */ + case WLAN_EID_UNKNOWN133: + /* was seen by David Bronaugh from ???? */ + /* 85 1E 00 00 84 12 07 00 FF 00 11 00 61 70 63 31 */ + /* 63 73 72 30 34 32 00 00 00 00 00 00 00 00 00 25 */ + case WLAN_EID_UNKNOWN223: + /* was seen by Carlos Martin from ???? */ + /* DF 20 01 1E 04 00 00 00 06 63 09 02 FF 0F 30 30 */ + /* 30 42 36 42 33 34 30 39 46 31 00 00 00 00 00 00 00 00 */ + case WLAN_EID_GENERIC: + /* WPA: hostap code: + if (pos[1] >= 4 && + pos[2] == 0x00 && pos[3] == 0x50 && + pos[4] == 0xf2 && pos[5] == 1) { + wpa = pos; + wpa_len = pos[1] + 2; + } + TI x4 mode: seen DD 04 08 00 28 00 + (08 00 28 is TI's OUI) + last byte is probably 0/1 - disabled/enabled + */ + case WLAN_EID_RSN: + /* hostap does something with it: + rsn = pos; + rsn_len = pos[1] + 2; + */ + break; + + default: + LOG_BAD_EID(f->hdr, f->len, ie_ptr); + break; + } + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr); + } +} + + +#ifdef UNUSED +void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t * f) +{ + f->type = WLAN_FSTYPE_ATIM; + /*-- Fixed Fields ----*/ + /*-- Information elements */ +} +#endif /* UNUSED */ + +void +wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t * f) +{ + f->type = WLAN_FSTYPE_DISASSOC; + + /*-- Fixed Fields ----*/ + f->reason = (u16 *) OFFSET(f->hdr, WLAN_DISASSOC_OFF_REASON); + + /*-- Information elements */ +} + + +void +wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t * f) +{ + u8 *ie_ptr; + u8 *end = (u8*)f->hdr + f->len; + + + f->type = WLAN_FSTYPE_ASSOCREQ; + + /*-- Fixed Fields ----*/ + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_CAP_INFO); + f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_LISTEN_INT); + + /*-- Information elements */ + ie_ptr = OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_SSID); + while (ie_ptr < end) { + switch (IE_EID(ie_ptr)) { + case WLAN_EID_SSID: + f->ssid = (wlan_ie_ssid_t *) ie_ptr; + break; + case WLAN_EID_SUPP_RATES: + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + case WLAN_EID_EXT_RATES: + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + default: + LOG_BAD_EID(f->hdr, f->len, ie_ptr); + break; + } + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr); + } +} + + +void +wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t * f) +{ + f->type = WLAN_FSTYPE_ASSOCRESP; + + /*-- Fixed Fields ----*/ + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_CAP_INFO); + f->status = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_STATUS); + f->aid = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_AID); + + /*-- Information elements */ + f->supp_rates = (wlan_ie_supp_rates_t *) + OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_SUPP_RATES); +} + + +#ifdef UNUSED +void +wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t * f) +{ + u8 *ie_ptr; + u8 *end = (u8*)f->hdr + f->len; + + f->type = WLAN_FSTYPE_REASSOCREQ; + + /*-- Fixed Fields ----*/ + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CAP_INFO); + f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_LISTEN_INT); + f->curr_ap = (u8 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CURR_AP); + + /*-- Information elements */ + ie_ptr = OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_SSID); + while (ie_ptr < end) { + switch (IE_EID(ie_ptr)) { + case WLAN_EID_SSID: + f->ssid = (wlan_ie_ssid_t *) ie_ptr; + break; + case WLAN_EID_SUPP_RATES: + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + case WLAN_EID_EXT_RATES: + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + default: + LOG_BAD_EID(f->hdr, f->len, ie_ptr); + break; + } + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr); + } +} + + +void +wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t * f) +{ + f->type = WLAN_FSTYPE_REASSOCRESP; + + /*-- Fixed Fields ----*/ + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_CAP_INFO); + f->status = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_STATUS); + f->aid = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_AID); + + /*-- Information elements */ + f->supp_rates = (wlan_ie_supp_rates_t *) + OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_SUPP_RATES); +} + + +void +wlan_mgmt_decode_probereq(wlan_fr_probereq_t * f) +{ + u8 *ie_ptr; + u8 *end = (u8*)f->hdr + f->len; + + f->type = WLAN_FSTYPE_PROBEREQ; + + /*-- Fixed Fields ----*/ + + /*-- Information elements */ + ie_ptr = OFFSET(f->hdr, WLAN_PROBEREQ_OFF_SSID); + while (ie_ptr < end) { + switch (IE_EID(ie_ptr)) { + case WLAN_EID_SSID: + f->ssid = (wlan_ie_ssid_t *) ie_ptr; + break; + case WLAN_EID_SUPP_RATES: + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + case WLAN_EID_EXT_RATES: + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + default: + LOG_BAD_EID(f->hdr, f->len, ie_ptr); + break; + } + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr); + } +} +#endif /* UNUSED */ + + +/* TODO: decoding of beacon and proberesp can be merged (similar structure) */ +void +wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t * f) +{ + u8 *ie_ptr; + u8 *end = (u8*)f->hdr + f->len; + + f->type = WLAN_FSTYPE_PROBERESP; + + /*-- Fixed Fields ----*/ + f->ts = (u64 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_TS); + f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_BCN_INT); + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_CAP_INFO); + + /*-- Information elements */ + ie_ptr = OFFSET(f->hdr, WLAN_PROBERESP_OFF_SSID); + while (ie_ptr < end) { + switch (IE_EID(ie_ptr)) { + case WLAN_EID_SSID: + f->ssid = (wlan_ie_ssid_t *) ie_ptr; + break; + case WLAN_EID_SUPP_RATES: + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + case WLAN_EID_EXT_RATES: + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr; + break; + case WLAN_EID_FH_PARMS: + f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr; + break; + case WLAN_EID_DS_PARMS: + f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr; + break; + case WLAN_EID_CF_PARMS: + f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr; + break; + case WLAN_EID_IBSS_PARMS: + f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr; + break; +#ifdef DONT_DO_IT_ADD_REAL_HANDLING_INSTEAD + case WLAN_EID_COUNTRY: + break; + ... +#endif +#ifdef SENT_HERE_BY_OPENWRT + /* should those be trapped or handled?? */ + case WLAN_EID_ERP_INFO: + break; + case WLAN_EID_NONERP: + break; + case WLAN_EID_GENERIC: + break; +#endif + default: + LOG_BAD_EID(f->hdr, f->len, ie_ptr); + break; + } + + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr); + } +} + + +void +wlan_mgmt_decode_authen(wlan_fr_authen_t * f) +{ + u8 *ie_ptr; + u8 *end = (u8*)f->hdr + f->len; + + f->type = WLAN_FSTYPE_AUTHEN; + + /*-- Fixed Fields ----*/ + f->auth_alg = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_ALG); + f->auth_seq = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_SEQ); + f->status = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_STATUS); + + /*-- Information elements */ + ie_ptr = OFFSET(f->hdr, WLAN_AUTHEN_OFF_CHALLENGE); + if ((ie_ptr < end) && (IE_EID(ie_ptr) == WLAN_EID_CHALLENGE)) { + f->challenge = (wlan_ie_challenge_t *) ie_ptr; + } +} + + +void +wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t * f) +{ + f->type = WLAN_FSTYPE_DEAUTHEN; + + /*-- Fixed Fields ----*/ + f->reason = (u16 *) OFFSET(f->hdr, WLAN_DEAUTHEN_OFF_REASON); + + /*-- Information elements */ +} --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/usb.c +++ linux-2.6.27/ubuntu/misc/wireless/acx/usb.c @@ -0,0 +1,1725 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +/*********************************************************************** +** USB support for TI ACX100 based devices. Many parts are taken from +** the PCI driver. +** +** Authors: +** Martin Wawro +** Andreas Mohr +** +** LOCKING +** callback functions called by USB core are running in interrupt context +** and thus have names with _i_. +*/ +#define ACX_USB 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acx.h" + + +/*********************************************************************** +*/ +/* number of endpoints of an interface */ +#define NUM_EP(intf) (intf)->altsetting[0].desc.bNumEndpoints +#define EP(intf, nr) (intf)->altsetting[0].endpoint[(nr)].desc +#define GET_DEV(udev) usb_get_dev((udev)) +#define PUT_DEV(udev) usb_put_dev((udev)) +#define SET_NETDEV_OWNER(ndev, owner) /* not needed anymore ??? */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) +/* removed in 2.6.14. We will use fake value for now */ +#define URB_ASYNC_UNLINK 0 +#endif + + +/*********************************************************************** +*/ +/* ACX100 (TNETW1100) USB device: D-Link DWL-120+ */ +#define ACX100_VENDOR_ID 0x2001 +#define ACX100_PRODUCT_ID_UNBOOTED 0x3B01 +#define ACX100_PRODUCT_ID_BOOTED 0x3B00 + +/* TNETW1450 USB devices */ +#define VENDOR_ID_DLINK 0x07b8 /* D-Link Corp. */ +#define PRODUCT_ID_WUG2400 0xb21a /* AboCom WUG2400 or SafeCom SWLUT-54125 */ +#define VENDOR_ID_AVM_GMBH 0x057c +#define PRODUCT_ID_AVM_WLAN_USB 0x5601 +#define PRODUCT_ID_AVM_WLAN_USB_si 0x6201 /* "self install" named Version: driver kills kernel on inbound scans from fritz box ??? */ +#define VENDOR_ID_ZCOM 0x0cde +#define PRODUCT_ID_ZCOM_XG750 0x0017 /* not tested yet */ +#define VENDOR_ID_TI 0x0451 +#define PRODUCT_ID_TI_UNKNOWN 0x60c5 /* not tested yet */ + +#define ACX_USB_CTRL_TIMEOUT 5500 /* steps in ms */ + +/* Buffer size for fw upload, same for both ACX100 USB and TNETW1450 */ +#define ACX_USB_RWMEM_MAXLEN 2048 + +/* The number of bulk URBs to use */ +#define ACX_TX_URB_CNT 8 +#define ACX_RX_URB_CNT 2 + +/* Should be sent to the bulkout endpoint */ +#define ACX_USB_REQ_UPLOAD_FW 0x10 +#define ACX_USB_REQ_ACK_CS 0x11 +#define ACX_USB_REQ_CMD 0x12 + +/*********************************************************************** +** Prototypes +*/ +static int acxusb_e_probe(struct usb_interface *, const struct usb_device_id *); +static void acxusb_e_disconnect(struct usb_interface *); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) +static void acxusb_i_complete_tx(struct urb *); +static void acxusb_i_complete_rx(struct urb *); +#else +static void acxusb_i_complete_tx(struct urb *, struct pt_regs *); +static void acxusb_i_complete_rx(struct urb *, struct pt_regs *); +#endif +static int acxusb_e_open(struct net_device *); +static int acxusb_e_close(struct net_device *); +static void acxusb_i_set_rx_mode(struct net_device *); +static int acxusb_boot(struct usb_device *); + +static void acxusb_l_poll_rx(acx_device_t *adev, usb_rx_t* rx); + +static void acxusb_i_tx_timeout(struct net_device *); + +/* static void dump_device(struct usb_device *); */ +/* static void dump_device_descriptor(struct usb_device_descriptor *); */ +/* static void dump_config_descriptor(struct usb_config_descriptor *); */ + +/*********************************************************************** +** Module Data +*/ +#define TXBUFSIZE sizeof(usb_txbuffer_t) +/* + * Now, this is just plain lying, but the device insists in giving us + * huge packets. We supply extra space after rxbuffer. Need to understand + * it better... + */ +#define RXBUFSIZE (sizeof(rxbuffer_t) + \ + (sizeof(usb_rx_t) - sizeof(struct usb_rx_plain))) + +static const struct usb_device_id +acxusb_ids[] = { + { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) }, + { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) }, + {} +}; +MODULE_DEVICE_TABLE(usb, acxusb_ids); + +/* USB driver data structure as required by the kernel's USB core */ +static struct usb_driver +acxusb_driver = { + .name = "acx_usb", + .probe = acxusb_e_probe, + .disconnect = acxusb_e_disconnect, + .id_table = acxusb_ids +}; + + +/*********************************************************************** +** USB helper +** +** ldd3 ch13 says: +** When the function is usb_kill_urb, the urb lifecycle is stopped. This +** function is usually used when the device is disconnected from the system, +** in the disconnect callback. For some drivers, the usb_unlink_urb function +** should be used to tell the USB core to stop an urb. This function does not +** wait for the urb to be fully stopped before returning to the caller. +** This is useful for stoppingthe urb while in an interrupt handler or when +** a spinlock is held, as waiting for a urb to fully stop requires the ability +** for the USB core to put the calling process to sleep. This function requires +** that the URB_ASYNC_UNLINK flag value be set in the urb that is being asked +** to be stopped in order to work properly. +** +** (URB_ASYNC_UNLINK is obsolete, usb_unlink_urb will always be +** asynchronous while usb_kill_urb is synchronous and should be called +** directly (drivers/usb/core/urb.c)) +** +** In light of this, timeout is just for paranoid reasons... +* +* Actually, it's useful for debugging. If we reach timeout, we're doing +* something wrong with the urbs. +*/ +static void +acxusb_unlink_urb(struct urb* urb) +{ + if (!urb) + return; + + if (urb->status == -EINPROGRESS) { + int timeout = 10; + + usb_unlink_urb(urb); + while (--timeout && urb->status == -EINPROGRESS) { + mdelay(1); + } + if (!timeout) { + printk("acx_usb: urb unlink timeout!\n"); + } + } +} + + +/*********************************************************************** +** EEPROM and PHY read/write helpers +*/ +/*********************************************************************** +** acxusb_s_read_phy_reg +*/ +int +acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf) +{ + /* mem_read_write_t mem; */ + + FN_ENTER; + + printk("%s doesn't seem to work yet, disabled.\n", __func__); + + /* + mem.addr = cpu_to_le16(reg); + mem.type = cpu_to_le16(0x82); + mem.len = cpu_to_le32(4); + acx_s_issue_cmd(adev, ACX1xx_CMD_MEM_READ, &mem, sizeof(mem)); + *charbuf = mem.data; + log(L_DEBUG, "read radio PHY[0x%04X]=0x%02X\n", reg, *charbuf); + */ + + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +*/ +int +acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value) +{ + mem_read_write_t mem; + + FN_ENTER; + + mem.addr = cpu_to_le16(reg); + mem.type = cpu_to_le16(0x82); + mem.len = cpu_to_le32(4); + mem.data = value; + acx_s_issue_cmd(adev, ACX1xx_CMD_MEM_WRITE, &mem, sizeof(mem)); + log(L_DEBUG, "write radio PHY[0x%04X]=0x%02X\n", reg, value); + + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +** acxusb_s_issue_cmd_timeo +** Excecutes a command in the command mailbox +** +** buffer = a pointer to the data. +** The data must not include 4 byte command header +*/ + +/* TODO: ideally we shall always know how much we need +** and this shall be 0 */ +#define BOGUS_SAFETY_PADDING 0x40 + +#undef FUNC +#define FUNC "issue_cmd" + +#if !ACX_DEBUG +int +acxusb_s_issue_cmd_timeo( + acx_device_t *adev, + unsigned cmd, + void *buffer, + unsigned buflen, + unsigned timeout) +{ +#else +int +acxusb_s_issue_cmd_timeo_debug( + acx_device_t *adev, + unsigned cmd, + void *buffer, + unsigned buflen, + unsigned timeout, + const char* cmdstr) +{ +#endif + /* USB ignores timeout param */ + + struct usb_device *usbdev; + struct { + u16 cmd; + u16 status; + u8 data[1]; + } ACX_PACKED *loc; + const char *devname; + int acklen, blocklen, inpipe, outpipe; + int cmd_status; + int result; + + FN_ENTER; + + devname = adev->ndev->name; + /* no "wlan%%d: ..." please */ + if (!devname || !devname[0] || devname[4]=='%') + devname = "acx"; + + log(L_CTL, FUNC"(cmd:%s,buflen:%u,type:0x%04X)\n", + cmdstr, buflen, + buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1); + + loc = kmalloc(buflen + 4 + BOGUS_SAFETY_PADDING, GFP_KERNEL); + if (!loc) { + printk("%s: "FUNC"(): no memory for data buffer\n", devname); + goto bad; + } + + /* get context from acx_device */ + usbdev = adev->usbdev; + + /* check which kind of command was issued */ + loc->cmd = cpu_to_le16(cmd); + loc->status = 0; + +/* NB: buflen == frmlen + 4 +** +** Interrogate: write 8 bytes: (cmd,status,rid,frmlen), then +** read (cmd,status,rid,frmlen,data[frmlen]) back +** +** Configure: write (cmd,status,rid,frmlen,data[frmlen]) +** +** Possibly bogus special handling of ACX1xx_IE_SCAN_STATUS removed +*/ + + /* now write the parameters of the command if needed */ + acklen = buflen + 4 + BOGUS_SAFETY_PADDING; + blocklen = buflen; + if (buffer && buflen) { + /* if it's an INTERROGATE command, just pass the length + * of parameters to read, as data */ + if (cmd == ACX1xx_CMD_INTERROGATE) { + blocklen = 4; + acklen = buflen + 4; + } + memcpy(loc->data, buffer, blocklen); + } + blocklen += 4; /* account for cmd,status */ + + /* obtain the I/O pipes */ + outpipe = usb_sndctrlpipe(usbdev, 0); + inpipe = usb_rcvctrlpipe(usbdev, 0); + log(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe); + log(L_CTL, "sending USB control msg (out) (blocklen=%d)\n", blocklen); + if (acx_debug & L_DATA) + acx_dump_bytes(loc, blocklen); + + result = usb_control_msg(usbdev, outpipe, + ACX_USB_REQ_CMD, /* request */ + USB_TYPE_VENDOR|USB_DIR_OUT, /* requesttype */ + 0, /* value */ + 0, /* index */ + loc, /* dataptr */ + blocklen, /* size */ + ACX_USB_CTRL_TIMEOUT /* timeout in ms */ + ); + + if (result == -ENODEV) { + log(L_CTL, "no device present (unplug?)\n"); + goto good; + } + + log(L_CTL, "wrote %d bytes\n", result); + if (result < 0) { + goto bad; + } + + /* check for device acknowledge */ + log(L_CTL, "sending USB control msg (in) (acklen=%d)\n", acklen); + loc->status = 0; /* delete old status flag -> set to IDLE */ + /* shall we zero out the rest? */ + result = usb_control_msg(usbdev, inpipe, + ACX_USB_REQ_CMD, /* request */ + USB_TYPE_VENDOR|USB_DIR_IN, /* requesttype */ + 0, /* value */ + 0, /* index */ + loc, /* dataptr */ + acklen, /* size */ + ACX_USB_CTRL_TIMEOUT /* timeout in ms */ + ); + if (result < 0) { + printk("%s: "FUNC"(): USB read error %d\n", devname, result); + goto bad; + } + if (acx_debug & L_CTL) { + printk("read %d bytes: ", result); + acx_dump_bytes(loc, result); + } + +/* + check for result==buflen+4? Was seen: + +interrogate(type:ACX100_IE_DOT11_ED_THRESHOLD,len:4) +issue_cmd(cmd:ACX1xx_CMD_INTERROGATE,buflen:8,type:4111) +ctrl inpipe=0x80000280 outpipe=0x80000200 +sending USB control msg (out) (blocklen=8) +01 00 00 00 0F 10 04 00 +wrote 8 bytes +sending USB control msg (in) (acklen=12) sizeof(loc->data +read 4 bytes <==== MUST BE 12!! +*/ + + cmd_status = le16_to_cpu(loc->status); + if (cmd_status != 1) { + printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s)\n", + devname, cmd_status, acx_cmd_status_str(cmd_status)); + /* TODO: goto bad; ? */ + } + if ((cmd == ACX1xx_CMD_INTERROGATE) && buffer && buflen) { + memcpy(buffer, loc->data, buflen); + log(L_CTL, "response frame: cmd=0x%04X status=%d\n", + le16_to_cpu(loc->cmd), + cmd_status); + } +good: + kfree(loc); + FN_EXIT1(OK); + return OK; +bad: + /* Give enough info so that callers can avoid + ** printing their own diagnostic messages */ +#if ACX_DEBUG + printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr); +#else + printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd); +#endif + dump_stack(); + kfree(loc); + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +** acxusb_boot() +** Inputs: +** usbdev -> Pointer to kernel's usb_device structure +** +** Returns: +** (int) Errorcode or 0 on success +** +** This function triggers the loading of the firmware image from harddisk +** and then uploads the firmware to the USB device. After uploading the +** firmware and transmitting the checksum, the device resets and appears +** as a new device on the USB bus (the device we can finally deal with) +*/ +static int +acxusb_boot(struct usb_device *usbdev) +{ + char filename[256]; + char *firmware = NULL; + char *usbbuf; + unsigned int offset; + unsigned int len, inpipe, outpipe; + u32 checksum; + u32 size; + int result; + + FN_ENTER; + + usbbuf = kmalloc(ACX_USB_RWMEM_MAXLEN, GFP_KERNEL); + if (!usbbuf) { + printk(KERN_ERR "acx: no memory for USB transfer buffer (" + STRING(ACX_USB_RWMEM_MAXLEN)" bytes)\n"); + result = -ENOMEM; + goto end; + } + + snprintf(filename, sizeof(filename), "acx/%s/tiacx100usb", firmware_ver); + firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size); + if (!firmware) { + result = -EIO; + goto end; + } + log(L_INIT, "firmware size: %d bytes\n", size); + + /* Obtain the I/O pipes */ + outpipe = usb_sndctrlpipe(usbdev, 0); + inpipe = usb_rcvctrlpipe(usbdev, 0); + + /* now upload the firmware, slice the data into blocks */ + offset = 8; + while (offset < size) { + len = size - offset; + if (len >= ACX_USB_RWMEM_MAXLEN) { + len = ACX_USB_RWMEM_MAXLEN; + } + log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n", + len, offset); + result = 0; + memcpy(usbbuf, firmware + offset, len); + result = usb_control_msg(usbdev, outpipe, + ACX_USB_REQ_UPLOAD_FW, + USB_TYPE_VENDOR|USB_DIR_OUT, + size - 8, /* value */ + 0, /* index */ + usbbuf, /* dataptr */ + len, /* size */ + 3000 /* timeout in ms */ + ); + offset += len; + if (result < 0) { + printk(KERN_ERR "acx: error %d during upload " + "of firmware, aborting\n", result); + goto end; + } + } + + /* finally, send the checksum and reboot the device */ + /* does this trigger the reboot? */ + checksum = le32_to_cpu(*(u32 *)firmware); + result = usb_control_msg(usbdev, outpipe, + ACX_USB_REQ_UPLOAD_FW, + USB_TYPE_VENDOR|USB_DIR_OUT, + checksum & 0xffff, /* value */ + checksum >> 16, /* index */ + NULL, /* dataptr */ + 0, /* size */ + 3000 /* timeout in ms */ + ); + if (result < 0) { + printk(KERN_ERR "acx: error %d during tx of checksum, " + "aborting\n", result); + goto end; + } + result = usb_control_msg(usbdev, inpipe, + ACX_USB_REQ_ACK_CS, + USB_TYPE_VENDOR|USB_DIR_IN, + checksum & 0xffff, /* value */ + checksum >> 16, /* index */ + usbbuf, /* dataptr */ + 8, /* size */ + 3000 /* timeout in ms */ + ); + if (result < 0) { + printk(KERN_ERR "acx: error %d during ACK of checksum, " + "aborting\n", result); + goto end; + } + if (*usbbuf != 0x10) { + kfree(usbbuf); + printk(KERN_ERR "acx: invalid checksum?\n"); + result = -EINVAL; + goto end; + } + result = 0; + +end: + vfree(firmware); + kfree(usbbuf); + + FN_EXIT1(result); + return result; +} + + +/* FIXME: maybe merge it with usual eeprom reading, into common code? */ +static void +acxusb_s_read_eeprom_version(acx_device_t *adev) +{ + u8 eeprom_ver[0x8]; + + memset(eeprom_ver, 0, sizeof(eeprom_ver)); + acx_s_interrogate(adev, &eeprom_ver, ACX1FF_IE_EEPROM_VER); + + /* FIXME: which one of those values to take? */ + adev->eeprom_version = eeprom_ver[5]; +} + + +/* + * temporary helper function to at least fill important cfgopt members with + * useful replacement values until we figure out how one manages to fetch + * the configoption struct in the USB device case... + */ +static int +acxusb_s_fill_configoption(acx_device_t *adev) +{ + adev->cfgopt_probe_delay = 200; + adev->cfgopt_dot11CCAModes = 4; + adev->cfgopt_dot11Diversity = 1; + adev->cfgopt_dot11ShortPreambleOption = 1; + adev->cfgopt_dot11PBCCOption = 1; + adev->cfgopt_dot11ChannelAgility = 0; + adev->cfgopt_dot11PhyType = 5; + adev->cfgopt_dot11TempType = 1; + return OK; +} + + +/*********************************************************************** +** acxusb_e_probe() +** +** This function is invoked by the kernel's USB core whenever a new device is +** attached to the system or the module is loaded. It is presented a usb_device +** structure from which information regarding the device is obtained and evaluated. +** In case this driver is able to handle one of the offered devices, it returns +** a non-null pointer to a driver context and thereby claims the device. +*/ + +static void +dummy_netdev_init(struct net_device *ndev) {} + +static int +acxusb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID) +{ + struct usb_device *usbdev = interface_to_usbdev(intf); + acx_device_t *adev = NULL; + struct net_device *ndev = NULL; + struct usb_config_descriptor *config; + struct usb_endpoint_descriptor *epdesc; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) + struct usb_host_endpoint *ep; +#endif + struct usb_interface_descriptor *ifdesc; + const char* msg; + int numconfigs, numfaces, numep; + int result = OK; + int i; + + FN_ENTER; + + /* First check if this is the "unbooted" hardware */ + if ((usbdev->descriptor.idVendor == ACX100_VENDOR_ID) + && (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED)) { + /* Boot the device (i.e. upload the firmware) */ + acxusb_boot(usbdev); + + /* OK, we are done with booting. Normally, the + ** ID for the unbooted device should disappear + ** and it will not need a driver anyway...so + ** return a NULL + */ + log(L_INIT, "finished booting, returning from probe()\n"); + result = OK; /* success */ + goto end; + } + + if ((usbdev->descriptor.idVendor != ACX100_VENDOR_ID) + || (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)) { + goto end_nodev; + } + +/* Ok, so it's our device and it has already booted */ + + /* Allocate memory for a network device */ + + ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init); + /* (NB: memsets to 0 entire area) */ + if (!ndev) { + msg = "acx: no memory for netdev\n"; + goto end_nomem; + } + + /* Register the callbacks for the network device functions */ + + ether_setup(ndev); + ndev->open = &acxusb_e_open; + ndev->stop = &acxusb_e_close; + ndev->hard_start_xmit = (void *)&acx_i_start_xmit; + ndev->get_stats = (void *)&acx_e_get_stats; + ndev->set_multicast_list = (void *)&acxusb_i_set_rx_mode; +#ifdef HAVE_TX_TIMEOUT + ndev->tx_timeout = &acxusb_i_tx_timeout; + ndev->watchdog_timeo = 4 * HZ; +#endif + ndev->change_mtu = &acx_e_change_mtu; + + /* Setup private driver context */ + + adev = netdev_priv(ndev); + adev->ndev = ndev; + + adev->dev_type = DEVTYPE_USB; + adev->chip_type = CHIPTYPE_ACX100; + + /* FIXME: should be read from register (via firmware) using standard ACX code */ + adev->radio_type = RADIO_MAXIM_0D; + + adev->usbdev = usbdev; + spin_lock_init(&adev->lock); /* initial state: unlocked */ + sema_init(&adev->sem, 1); /* initial state: 1 (upped) */ + + /* Check that this is really the hardware we know about. + ** If not sure, at least notify the user that he + ** may be in trouble... + */ + numconfigs = (int)usbdev->descriptor.bNumConfigurations; + if (numconfigs != 1) + printk("acx: number of configurations is %d, " + "this driver only knows how to handle 1, " + "be prepared for surprises\n", numconfigs); + + config = &usbdev->config->desc; + numfaces = config->bNumInterfaces; + if (numfaces != 1) + printk("acx: number of interfaces is %d, " + "this driver only knows how to handle 1, " + "be prepared for surprises\n", numfaces); + + ifdesc = &intf->altsetting->desc; + numep = ifdesc->bNumEndpoints; + log(L_DEBUG, "# of endpoints: %d\n", numep); + + /* obtain information about the endpoint + ** addresses, begin with some default values + */ + adev->bulkoutep = 1; + adev->bulkinep = 1; + for (i = 0; i < numep; i++) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) + ep = usbdev->ep_in[i]; + if (!ep) + continue; + epdesc = &ep->desc; +#else + epdesc = usb_epnum_to_ep_desc(usbdev, i); + if (!epdesc) + continue; +#endif + if (epdesc->bmAttributes & USB_ENDPOINT_XFER_BULK) { + if (epdesc->bEndpointAddress & 0x80) + adev->bulkinep = epdesc->bEndpointAddress & 0xF; + else + adev->bulkoutep = epdesc->bEndpointAddress & 0xF; + } + } + log(L_DEBUG, "bulkout ep: 0x%X\n", adev->bulkoutep); + log(L_DEBUG, "bulkin ep: 0x%X\n", adev->bulkinep); + + /* already done by memset: adev->rxtruncsize = 0; */ + log(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n", + (int) TXBUFSIZE, (int) RXBUFSIZE); + + /* Allocate the RX/TX containers. */ + adev->usb_tx = kmalloc(sizeof(usb_tx_t) * ACX_TX_URB_CNT, GFP_KERNEL); + if (!adev->usb_tx) { + msg = "acx: no memory for tx container"; + goto end_nomem; + } + adev->usb_rx = kmalloc(sizeof(usb_rx_t) * ACX_RX_URB_CNT, GFP_KERNEL); + if (!adev->usb_rx) { + msg = "acx: no memory for rx container"; + goto end_nomem; + } + + /* Setup URBs for bulk-in/out messages */ + for (i = 0; i < ACX_RX_URB_CNT; i++) { + adev->usb_rx[i].urb = usb_alloc_urb(0, GFP_KERNEL); + if (!adev->usb_rx[i].urb) { + msg = "acx: no memory for input URB\n"; + goto end_nomem; + } + adev->usb_rx[i].urb->status = 0; + adev->usb_rx[i].adev = adev; + adev->usb_rx[i].busy = 0; + } + + for (i = 0; i< ACX_TX_URB_CNT; i++) { + adev->usb_tx[i].urb = usb_alloc_urb(0, GFP_KERNEL); + if (!adev->usb_tx[i].urb) { + msg = "acx: no memory for output URB\n"; + goto end_nomem; + } + adev->usb_tx[i].urb->status = 0; + adev->usb_tx[i].adev = adev; + adev->usb_tx[i].busy = 0; + } + adev->tx_free = ACX_TX_URB_CNT; + + usb_set_intfdata(intf, adev); + SET_NETDEV_DEV(ndev, &intf->dev); + + /* TODO: move all of fw cmds to open()? But then we won't know our MAC addr + until ifup (it's available via reading ACX1xx_IE_DOT11_STATION_ID)... */ + + /* put acx out of sleep mode and initialize it */ + acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0); + + result = acx_s_init_mac(adev); + if (result) + goto end; + + /* TODO: see similar code in pci.c */ + acxusb_s_read_eeprom_version(adev); + acxusb_s_fill_configoption(adev); + acx_s_set_defaults(adev); + acx_s_get_firmware_version(adev); + acx_display_hardware_details(adev); + + /* Register the network device */ + log(L_INIT, "registering network device\n"); + result = register_netdev(ndev); + if (result) { + msg = "acx: failed to register USB network device " + "(error %d)\n"; + goto end_nomem; + } + + acx_proc_register_entries(ndev); + + acx_stop_queue(ndev, "on probe"); + acx_carrier_off(ndev, "on probe"); + + printk("acx: USB module " ACX_RELEASE " loaded successfully\n"); + +#if CMD_DISCOVERY + great_inquisitor(adev); +#endif + + /* Everything went OK, we are happy now */ + result = OK; + goto end; + +end_nomem: + printk(msg, result); + + if (ndev) { + if (adev->usb_rx) { + for (i = 0; i < ACX_RX_URB_CNT; i++) + usb_free_urb(adev->usb_rx[i].urb); + kfree(adev->usb_rx); + } + if (adev->usb_tx) { + for (i = 0; i < ACX_TX_URB_CNT; i++) + usb_free_urb(adev->usb_tx[i].urb); + kfree(adev->usb_tx); + } + free_netdev(ndev); + } + + result = -ENOMEM; + goto end; + +end_nodev: + /* no device we could handle, return error. */ + result = -EIO; + +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acxusb_e_disconnect() +** +** This function is invoked whenever the user pulls the plug from the USB +** device or the module is removed from the kernel. In these cases, the +** network devices have to be taken down and all allocated memory has +** to be freed. +*/ +static void +acxusb_e_disconnect(struct usb_interface *intf) +{ + acx_device_t *adev = usb_get_intfdata(intf); + unsigned long flags; + int i; + + FN_ENTER; + + /* No WLAN device... no sense */ + if (!adev) + goto end; + + /* Unregister network device + * + * If the interface is up, unregister_netdev() will take + * care of calling our close() function, which takes + * care of unlinking the urbs, sending the device to + * sleep, etc... + * This can't be called with sem or lock held because + * _close() will try to grab it as well if it's called, + * deadlocking the machine. + */ + unregister_netdev(adev->ndev); + + acx_sem_lock(adev); + acx_lock(adev, flags); + /* This device exists no more */ + usb_set_intfdata(intf, NULL); + acx_proc_unregister_entries(adev->ndev); + + /* + * Here we only free them. _close() took care of + * unlinking them. + */ + for (i = 0; i < ACX_RX_URB_CNT; ++i) { + usb_free_urb(adev->usb_rx[i].urb); + } + for (i = 0; i< ACX_TX_URB_CNT; ++i) { + usb_free_urb(adev->usb_tx[i].urb); + } + + /* Freeing containers */ + kfree(adev->usb_rx); + kfree(adev->usb_tx); + + acx_unlock(adev, flags); + acx_sem_unlock(adev); + + free_netdev(adev->ndev); +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acxusb_e_open() +** This function is called when the user sets up the network interface. +** It initializes a management timer, sets up the USB card and starts +** the network tx queue and USB receive. +*/ +static int +acxusb_e_open(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + int i; + + FN_ENTER; + + acx_sem_lock(adev); + + /* put the ACX100 out of sleep mode */ + acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0); + + acx_init_task_scheduler(adev); + + init_timer(&adev->mgmt_timer); + adev->mgmt_timer.function = acx_i_timer; + adev->mgmt_timer.data = (unsigned long)adev; + + /* acx_s_start needs it */ + SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP); + acx_s_start(adev); + + /* don't acx_start_queue() here, we need to associate first */ + + acx_lock(adev, flags); + for (i = 0; i < ACX_RX_URB_CNT; i++) { + adev->usb_rx[i].urb->status = 0; + } + + acxusb_l_poll_rx(adev, &adev->usb_rx[0]); + + acx_unlock(adev, flags); + + acx_sem_unlock(adev); + + FN_EXIT0; + return 0; +} + + +/*********************************************************************** +** acxusb_e_close() +** +** This function stops the network functionality of the interface (invoked +** when the user calls ifconfig down). The tx queue is halted and +** the device is marked as down. In case there were any pending USB bulk +** transfers, these are unlinked (asynchronously). The module in-use count +** is also decreased in this function. +*/ +static int +acxusb_e_close(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + int i; + + FN_ENTER; + +#ifdef WE_STILL_DONT_CARE_ABOUT_IT + /* Transmit a disassociate frame */ + lock + acx_l_transmit_disassoc(adev, &client); + unlock +#endif + + acx_sem_lock(adev); + + CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP); + +/* Code below is remarkably similar to acxpci_s_down(). Maybe we can merge them? */ + + /* Make sure we don't get any more rx requests */ + acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0); + acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0); + + /* + * We must do FLUSH *without* holding sem to avoid a deadlock. + * See pci.c:acxpci_s_down() for deails. + */ + acx_sem_unlock(adev); + FLUSH_SCHEDULED_WORK(); + acx_sem_lock(adev); + + /* Power down the device */ + acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0); + + /* Stop the transmit queue, mark the device as DOWN */ + acx_lock(adev, flags); + acx_stop_queue(ndev, "on ifdown"); + acx_set_status(adev, ACX_STATUS_0_STOPPED); + /* stop pending rx/tx urb transfers */ + for (i = 0; i < ACX_TX_URB_CNT; i++) { + acxusb_unlink_urb(adev->usb_tx[i].urb); + adev->usb_tx[i].busy = 0; + } + for (i = 0; i < ACX_RX_URB_CNT; i++) { + acxusb_unlink_urb(adev->usb_rx[i].urb); + adev->usb_rx[i].busy = 0; + } + adev->tx_free = ACX_TX_URB_CNT; + acx_unlock(adev, flags); + + /* Must do this outside of lock */ + del_timer_sync(&adev->mgmt_timer); + + acx_sem_unlock(adev); + + FN_EXIT0; + return 0; +} + + +/*********************************************************************** +** acxusb_l_poll_rx +** This function (re)initiates a bulk-in USB transfer on a given urb +*/ +static void +acxusb_l_poll_rx(acx_device_t *adev, usb_rx_t* rx) +{ + struct usb_device *usbdev; + struct urb *rxurb; + int errcode, rxnum; + unsigned int inpipe; + + FN_ENTER; + + rxurb = rx->urb; + usbdev = adev->usbdev; + + rxnum = rx - adev->usb_rx; + + inpipe = usb_rcvbulkpipe(usbdev, adev->bulkinep); + if (unlikely(rxurb->status == -EINPROGRESS)) { + printk(KERN_ERR "acx: error, rx triggered while rx urb in progress\n"); + /* FIXME: this is nasty, receive is being cancelled by this code + * on the other hand, this should not happen anyway... + */ + usb_unlink_urb(rxurb); + } else + if (unlikely(rxurb->status == -ECONNRESET)) { + log(L_USBRXTX, "acx_usb: _poll_rx: connection reset\n"); + goto end; + } + rxurb->actual_length = 0; + usb_fill_bulk_urb(rxurb, usbdev, inpipe, + &rx->bulkin, /* dataptr */ + RXBUFSIZE, /* size */ + acxusb_i_complete_rx, /* handler */ + rx /* handler param */ + ); + rxurb->transfer_flags = URB_ASYNC_UNLINK; + + /* ATOMIC: we may be called from complete_rx() usb callback */ + errcode = usb_submit_urb(rxurb, GFP_ATOMIC); + /* FIXME: evaluate the error code! */ + log(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n", + rxnum, inpipe, (int) RXBUFSIZE, errcode); +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acxusb_i_complete_rx() +** Inputs: +** urb -> pointer to USB request block +** regs -> pointer to register-buffer for syscalls (see asm/ptrace.h) +** +** This function is invoked by USB subsystem whenever a bulk receive +** request returns. +** The received data is then committed to the network stack and the next +** USB receive is triggered. +*/ +static void +acxusb_i_complete_rx(struct urb *urb) +{ + acx_device_t *adev; + rxbuffer_t *ptr; + rxbuffer_t *inbuf; + usb_rx_t *rx; + unsigned long flags; + int size, remsize, packetsize, rxnum; + + FN_ENTER; + + BUG_ON(!urb->context); + + rx = (usb_rx_t *)urb->context; + adev = rx->adev; + + acx_lock(adev, flags); + + /* + * Happens on disconnect or close. Don't play with the urb. + * Don't resubmit it. It will get unlinked by close() + */ + if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) { + log(L_USBRXTX, "rx: device is down, not doing anything\n"); + goto end_unlock; + } + + inbuf = &rx->bulkin; + size = urb->actual_length; + remsize = size; + rxnum = rx - adev->usb_rx; + + log(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n", + rxnum, urb->status, size); + + /* Send the URB that's waiting. */ + log(L_USBRXTX, "rxnum=%d, sending=%d\n", rxnum, rxnum^1); + acxusb_l_poll_rx(adev, &adev->usb_rx[rxnum^1]); + + if (unlikely(size > sizeof(rxbuffer_t))) + printk("acx_usb: rx too large: %d, please report\n", size); + + /* check if the transfer was aborted */ + switch (urb->status) { + case 0: /* No error */ + break; + case -EOVERFLOW: + printk(KERN_ERR "acx: rx data overrun\n"); + adev->rxtruncsize = 0; /* Not valid anymore. */ + goto end_unlock; + case -ECONNRESET: + adev->rxtruncsize = 0; + goto end_unlock; + case -ESHUTDOWN: /* rmmod */ + adev->rxtruncsize = 0; + goto end_unlock; + default: + adev->rxtruncsize = 0; + adev->stats.rx_errors++; + printk("acx: rx error (urb status=%d)\n", urb->status); + goto end_unlock; + } + + if (unlikely(!size)) + printk("acx: warning, encountered zerolength rx packet\n"); + + if (urb->transfer_buffer != inbuf) + goto end_unlock; + + /* check if previous frame was truncated + ** FIXME: this code can only handle truncation + ** of consecutive packets! + */ + ptr = inbuf; + if (adev->rxtruncsize) { + int tail_size; + + ptr = &adev->rxtruncbuf; + packetsize = RXBUF_BYTES_USED(ptr); + if (acx_debug & L_USBRXTX) { + printk("handling truncated frame (truncsize=%d size=%d " + "packetsize(from trunc)=%d)\n", + adev->rxtruncsize, size, packetsize); + acx_dump_bytes(ptr, RXBUF_HDRSIZE); + acx_dump_bytes(inbuf, RXBUF_HDRSIZE); + } + + /* bytes needed for rxtruncbuf completion: */ + tail_size = packetsize - adev->rxtruncsize; + + if (size < tail_size) { + /* there is not enough data to complete this packet, + ** simply append the stuff to the truncation buffer + */ + memcpy(((char *)ptr) + adev->rxtruncsize, inbuf, size); + adev->rxtruncsize += size; + remsize = 0; + } else { + /* ok, this data completes the previously + ** truncated packet. copy it into a descriptor + ** and give it to the rest of the stack */ + + /* append tail to previously truncated part + ** NB: adev->rxtruncbuf (pointed to by ptr) can't + ** overflow because this is already checked before + ** truncation buffer was filled. See below, + ** "if (packetsize > sizeof(rxbuffer_t))..." code */ + memcpy(((char *)ptr) + adev->rxtruncsize, inbuf, tail_size); + + if (acx_debug & L_USBRXTX) { + printk("full trailing packet + 12 bytes:\n"); + acx_dump_bytes(inbuf, tail_size + RXBUF_HDRSIZE); + } + acx_l_process_rxbuf(adev, ptr); + adev->rxtruncsize = 0; + ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size); + remsize -= tail_size; + } + log(L_USBRXTX, "post-merge size=%d remsize=%d\n", + size, remsize); + } + + /* size = USB data block size + ** remsize = unprocessed USB bytes left + ** ptr = current pos in USB data block + */ + while (remsize) { + if (remsize < RXBUF_HDRSIZE) { + printk("acx: truncated rx header (%d bytes)!\n", + remsize); + if (ACX_DEBUG) + acx_dump_bytes(ptr, remsize); + break; + } + + packetsize = RXBUF_BYTES_USED(ptr); + log(L_USBRXTX, "packet with packetsize=%d\n", packetsize); + + if (RXBUF_IS_TXSTAT(ptr)) { + /* do rate handling */ + usb_txstatus_t *stat = (void*)ptr; + u16 client_no = (u16)stat->hostdata; + + log(L_USBRXTX, "tx: stat: mac_cnt_rcvd:%04X " + "queue_index:%02X mac_status:%02X hostdata:%08X " + "rate:%u ack_failures:%02X rts_failures:%02X " + "rts_ok:%02X\n", + stat->mac_cnt_rcvd, + stat->queue_index, stat->mac_status, stat->hostdata, + stat->rate, stat->ack_failures, stat->rts_failures, + stat->rts_ok); + + if (adev->rate_auto && client_no < VEC_SIZE(adev->sta_list)) { + client_t *clt = &adev->sta_list[client_no]; + u16 cur = stat->hostdata >> 16; + + if (clt && clt->rate_cur == cur) { + acx_l_handle_txrate_auto(adev, clt, + cur, /* intended rate */ + stat->rate, 0, /* actually used rate */ + stat->mac_status, /* error? */ + ACX_TX_URB_CNT - adev->tx_free); + } + } + goto next; + } + + if (packetsize > sizeof(rxbuffer_t)) { + printk("acx: packet exceeds max wlan " + "frame size (%d > %d). size=%d\n", + packetsize, (int) sizeof(rxbuffer_t), size); + if (ACX_DEBUG) + acx_dump_bytes(ptr, 16); + /* FIXME: put some real error-handling in here! */ + break; + } + + if (packetsize > remsize) { + /* frame truncation handling */ + if (acx_debug & L_USBRXTX) { + printk("need to truncate packet, " + "packetsize=%d remsize=%d " + "size=%d bytes:", + packetsize, remsize, size); + acx_dump_bytes(ptr, RXBUF_HDRSIZE); + } + memcpy(&adev->rxtruncbuf, ptr, remsize); + adev->rxtruncsize = remsize; + break; + } + + /* packetsize <= remsize */ + /* now handle the received data */ + acx_l_process_rxbuf(adev, ptr); +next: + ptr = (rxbuffer_t *)(((char *)ptr) + packetsize); + remsize -= packetsize; + if ((acx_debug & L_USBRXTX) && remsize) { + printk("more than one packet in buffer, " + "second packet hdr:"); + acx_dump_bytes(ptr, RXBUF_HDRSIZE); + } + } + +end_unlock: + acx_unlock(adev, flags); +/* end: */ + FN_EXIT0; +} + + +/*********************************************************************** +** acxusb_i_complete_tx() +** Inputs: +** urb -> pointer to USB request block +** regs -> pointer to register-buffer for syscalls (see asm/ptrace.h) +** +** This function is invoked upon termination of a USB transfer. +*/ +static void +acxusb_i_complete_tx(struct urb *urb) +{ + acx_device_t *adev; + usb_tx_t *tx; + unsigned long flags; + int txnum; + + FN_ENTER; + + BUG_ON(!urb->context); + + tx = (usb_tx_t *)urb->context; + adev = tx->adev; + + txnum = tx - adev->usb_tx; + + acx_lock(adev, flags); + + /* + * If the iface isn't up, we don't have any right + * to play with them. The urb may get unlinked. + */ + if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) { + log(L_USBRXTX, "tx: device is down, not doing anything\n"); + goto end_unlock; + } + + log(L_USBRXTX, "RETURN TX (%d): status=%d size=%d\n", + txnum, urb->status, urb->actual_length); + + /* handle USB transfer errors */ + switch (urb->status) { + case 0: /* No error */ + break; + case -ESHUTDOWN: + goto end_unlock; + break; + case -ECONNRESET: + goto end_unlock; + break; + /* FIXME: real error-handling code here please */ + default: + printk(KERN_ERR "acx: tx error, urb status=%d\n", urb->status); + /* FIXME: real error-handling code here please */ + } + + /* free the URB and check for more data */ + tx->busy = 0; + adev->tx_free++; + if ((adev->tx_free >= TX_START_QUEUE) + && (adev->status == ACX_STATUS_4_ASSOCIATED) + && (acx_queue_stopped(adev->ndev)) + ) { + log(L_BUF, "tx: wake queue (%u free txbufs)\n", + adev->tx_free); + acx_wake_queue(adev->ndev, NULL); + } + +end_unlock: + acx_unlock(adev, flags); +/* end: */ + FN_EXIT0; +} + + +/*************************************************************** +** acxusb_l_alloc_tx +** Actually returns a usb_tx_t* ptr +*/ +tx_t* +acxusb_l_alloc_tx(acx_device_t *adev) +{ + usb_tx_t *tx; + unsigned head; + + FN_ENTER; + + head = adev->tx_head; + do { + head = (head + 1) % ACX_TX_URB_CNT; + if (!adev->usb_tx[head].busy) { + log(L_USBRXTX, "allocated tx %d\n", head); + tx = &adev->usb_tx[head]; + tx->busy = 1; + adev->tx_free--; + /* Keep a few free descs between head and tail of tx ring. + ** It is not absolutely needed, just feels safer */ + if (adev->tx_free < TX_STOP_QUEUE) { + log(L_BUF, "tx: stop queue " + "(%u free txbufs)\n", adev->tx_free); + acx_stop_queue(adev->ndev, NULL); + } + goto end; + } + } while (likely(head!=adev->tx_head)); + tx = NULL; + printk_ratelimited("acx: tx buffers full\n"); +end: + adev->tx_head = head; + FN_EXIT0; + return (tx_t*)tx; +} + + +/*************************************************************** +** Used if alloc_tx()'ed buffer needs to be cancelled without doing tx +*/ +void +acxusb_l_dealloc_tx(tx_t *tx_opaque) +{ + usb_tx_t* tx = (usb_tx_t*)tx_opaque; + tx->busy = 0; +} + + +/*************************************************************** +*/ +void* +acxusb_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque) +{ + usb_tx_t* tx = (usb_tx_t*)tx_opaque; + return &tx->bulkout.data; +} + + +/*************************************************************** +** acxusb_l_tx_data +** +** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx). +** Can be called from acx_i_start_xmit (data frames from net core). +*/ +void +acxusb_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int wlanpkt_len) +{ + struct usb_device *usbdev; + struct urb* txurb; + usb_tx_t* tx; + usb_txbuffer_t* txbuf; + client_t *clt; + wlan_hdr_t* whdr; + unsigned int outpipe; + int ucode, txnum; + + FN_ENTER; + + tx = ((usb_tx_t *)tx_opaque); + txurb = tx->urb; + txbuf = &tx->bulkout; + whdr = (wlan_hdr_t *)txbuf->data; + txnum = tx - adev->usb_tx; + + log(L_DEBUG, "using buf#%d free=%d len=%d\n", + txnum, adev->tx_free, wlanpkt_len); + + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_3_AP: + clt = acx_l_sta_list_get(adev, whdr->a1); + break; + case ACX_MODE_2_STA: + clt = adev->ap_client; + break; + default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */ + clt = NULL; + break; + } + + if (unlikely(clt && !clt->rate_cur)) { + printk("acx: driver bug! bad ratemask\n"); + goto end; + } + + /* fill the USB transfer header */ + txbuf->desc = cpu_to_le16(USB_TXBUF_TXDESC); + txbuf->mpdu_len = cpu_to_le16(wlanpkt_len); + txbuf->queue_index = 1; + if (clt) { + txbuf->rate = clt->rate_100; + txbuf->hostdata = (clt - adev->sta_list) | (clt->rate_cur << 16); + } else { + txbuf->rate = adev->rate_bcast100; + txbuf->hostdata = ((u16)-1) | (adev->rate_bcast << 16); + } + txbuf->ctrl1 = DESC_CTL_FIRSTFRAG; + if (1 == adev->preamble_cur) + SET_BIT(txbuf->ctrl1, DESC_CTL_SHORT_PREAMBLE); + txbuf->ctrl2 = 0; + txbuf->data_len = cpu_to_le16(wlanpkt_len); + + if (unlikely(acx_debug & L_DATA)) { + printk("dump of bulk out urb:\n"); + acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE); + } + + if (unlikely(txurb->status == -EINPROGRESS)) { + printk("acx: trying to submit tx urb while already in progress\n"); + } + + /* now schedule the USB transfer */ + usbdev = adev->usbdev; + outpipe = usb_sndbulkpipe(usbdev, adev->bulkoutep); + + usb_fill_bulk_urb(txurb, usbdev, outpipe, + txbuf, /* dataptr */ + wlanpkt_len + USB_TXBUF_HDRSIZE, /* size */ + acxusb_i_complete_tx, /* handler */ + tx /* handler param */ + ); + + txurb->transfer_flags = URB_ASYNC_UNLINK|URB_ZERO_PACKET; + ucode = usb_submit_urb(txurb, GFP_ATOMIC); + log(L_USBRXTX, "SUBMIT TX (%d): outpipe=0x%X buf=%p txsize=%d " + "rate=%u errcode=%d\n", txnum, outpipe, txbuf, + wlanpkt_len + USB_TXBUF_HDRSIZE, txbuf->rate, ucode); + + if (unlikely(ucode)) { + printk(KERN_ERR "acx: submit_urb() error=%d txsize=%d\n", + ucode, wlanpkt_len + USB_TXBUF_HDRSIZE); + + /* on error, just mark the frame as done and update + ** the statistics + */ + adev->stats.tx_errors++; + tx->busy = 0; + adev->tx_free++; + /* needed? if (adev->tx_free > TX_START_QUEUE) acx_wake_queue(...) */ + } +end: + FN_EXIT0; +} + + +/*********************************************************************** +*/ +static void +acxusb_i_set_rx_mode(struct net_device *ndev) +{ +} + + +/*********************************************************************** +*/ +#ifdef HAVE_TX_TIMEOUT +static void +acxusb_i_tx_timeout(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + int i; + + FN_ENTER; + + acx_lock(adev, flags); + /* unlink the URBs */ + for (i = 0; i < ACX_TX_URB_CNT; i++) { + acxusb_unlink_urb(adev->usb_tx[i].urb); + adev->usb_tx[i].busy = 0; + } + adev->tx_free = ACX_TX_URB_CNT; + /* TODO: stats update */ + acx_unlock(adev, flags); + + FN_EXIT0; +} +#endif + + +/*********************************************************************** +** init_module() +** +** This function is invoked upon loading of the kernel module. +** It registers itself at the kernel's USB subsystem. +** +** Returns: Errorcode on failure, 0 on success +*/ +int __init +acxusb_e_init_module(void) +{ + log(L_INIT, "USB module " ACX_RELEASE " initialized, " + "probing for devices...\n"); + return usb_register(&acxusb_driver); +} + + + +/*********************************************************************** +** cleanup_module() +** +** This function is invoked as last step of the module unloading. It simply +** deregisters this module at the kernel's USB subsystem. +*/ +void __exit +acxusb_e_cleanup_module() +{ + usb_deregister(&acxusb_driver); +} + + +/*********************************************************************** +** DEBUG STUFF +*/ +#if ACX_DEBUG + +#ifdef UNUSED +static void +dump_device(struct usb_device *usbdev) +{ + int i; + struct usb_config_descriptor *cd; + + printk("acx device dump:\n"); + printk(" devnum: %d\n", usbdev->devnum); + printk(" speed: %d\n", usbdev->speed); + printk(" tt: 0x%X\n", (unsigned int)(usbdev->tt)); + printk(" ttport: %d\n", (unsigned int)(usbdev->ttport)); + printk(" toggle[0]: 0x%X toggle[1]: 0x%X\n", (unsigned int)(usbdev->toggle[0]), (unsigned int)(usbdev->toggle[1])); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) + /* This saw a change after 2.6.10 */ + printk(" ep_in wMaxPacketSize: "); + for (i = 0; i < 16; ++i) + if (usbdev->ep_in[i] != NULL) + printk("%d:%d ", i, usbdev->ep_in[i]->desc.wMaxPacketSize); + printk("\n"); + printk(" ep_out wMaxPacketSize: "); + for (i = 0; i < VEC_SIZE(usbdev->ep_out); ++i) + if (usbdev->ep_out[i] != NULL) + printk("%d:%d ", i, usbdev->ep_out[i]->desc.wMaxPacketSize); + printk("\n"); +#else + printk(" epmaxpacketin: "); + for (i = 0; i < 16; i++) + printk("%d ", usbdev->epmaxpacketin[i]); + printk("\n"); + printk(" epmaxpacketout: "); + for (i = 0; i < 16; i++) + printk("%d ", usbdev->epmaxpacketout[i]); + printk("\n"); +#endif + printk(" parent: 0x%X\n", (unsigned int)usbdev->parent); + printk(" bus: 0x%X\n", (unsigned int)usbdev->bus); +#ifdef NO_DATATYPE + printk(" configs: "); + for (i = 0; i < usbdev->descriptor.bNumConfigurations; i++) + printk("0x%X ", usbdev->config[i]); + printk("\n"); +#endif + printk(" actconfig: %p\n", usbdev->actconfig); + dump_device_descriptor(&usbdev->descriptor); + + cd = &usbdev->config->desc; + dump_config_descriptor(cd); +} + + +/*********************************************************************** +*/ +static void +dump_config_descriptor(struct usb_config_descriptor *cd) +{ + printk("Configuration Descriptor:\n"); + if (!cd) { + printk("NULL\n"); + return; + } + printk(" bLength: %d (0x%X)\n", cd->bLength, cd->bLength); + printk(" bDescriptorType: %d (0x%X)\n", cd->bDescriptorType, cd->bDescriptorType); + printk(" bNumInterfaces: %d (0x%X)\n", cd->bNumInterfaces, cd->bNumInterfaces); + printk(" bConfigurationValue: %d (0x%X)\n", cd->bConfigurationValue, cd->bConfigurationValue); + printk(" iConfiguration: %d (0x%X)\n", cd->iConfiguration, cd->iConfiguration); + printk(" bmAttributes: %d (0x%X)\n", cd->bmAttributes, cd->bmAttributes); + /* printk(" MaxPower: %d (0x%X)\n", cd->bMaxPower, cd->bMaxPower); */ +} + + +static void +dump_device_descriptor(struct usb_device_descriptor *dd) +{ + printk("Device Descriptor:\n"); + if (!dd) { + printk("NULL\n"); + return; + } + printk(" bLength: %d (0x%X)\n", dd->bLength, dd->bLength); + printk(" bDescriptortype: %d (0x%X)\n", dd->bDescriptorType, dd->bDescriptorType); + printk(" bcdUSB: %d (0x%X)\n", dd->bcdUSB, dd->bcdUSB); + printk(" bDeviceClass: %d (0x%X)\n", dd->bDeviceClass, dd->bDeviceClass); + printk(" bDeviceSubClass: %d (0x%X)\n", dd->bDeviceSubClass, dd->bDeviceSubClass); + printk(" bDeviceProtocol: %d (0x%X)\n", dd->bDeviceProtocol, dd->bDeviceProtocol); + printk(" bMaxPacketSize0: %d (0x%X)\n", dd->bMaxPacketSize0, dd->bMaxPacketSize0); + printk(" idVendor: %d (0x%X)\n", dd->idVendor, dd->idVendor); + printk(" idProduct: %d (0x%X)\n", dd->idProduct, dd->idProduct); + printk(" bcdDevice: %d (0x%X)\n", dd->bcdDevice, dd->bcdDevice); + printk(" iManufacturer: %d (0x%X)\n", dd->iManufacturer, dd->iManufacturer); + printk(" iProduct: %d (0x%X)\n", dd->iProduct, dd->iProduct); + printk(" iSerialNumber: %d (0x%X)\n", dd->iSerialNumber, dd->iSerialNumber); + printk(" bNumConfigurations: %d (0x%X)\n", dd->bNumConfigurations, dd->bNumConfigurations); +} +#endif /* UNUSED */ + +#endif /* ACX_DEBUG */ --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/acx_config.h +++ linux-2.6.27/ubuntu/misc/wireless/acx/acx_config.h @@ -0,0 +1,41 @@ +/* Driver version */ +#define ACX_RELEASE "v0.3.36" + +/* set to 0 if you don't want any debugging code to be compiled in */ +/* set to 1 if you want some debugging */ +/* set to 2 if you want extensive debug log */ +#define ACX_DEBUG 0 +#define ACX_DEFAULT_MSG (L_ASSOC|L_INIT) + +/* assume 32bit I/O width + * (16bit is also compatible with Compact Flash) */ +#define ACX_IO_WIDTH 32 + +/* Set this to 1 if you want monitor mode to use + * phy header. Currently it is not useful anyway since we + * don't know what useful info (if any) is in phy header. + * If you want faster/smaller code, say 0 here */ +#define WANT_PHY_HDR 0 + +/* whether to do Tx descriptor cleanup in softirq (i.e. not in IRQ + * handler) or not. Note that doing it later does slightly increase + * system load, so still do that stuff in the IRQ handler for now, + * even if that probably means worse latency */ +#define TX_CLEANUP_IN_SOFTIRQ 0 + +/* if you want very experimental 802.11 power save mode features */ +#define POWER_SAVE_80211 0 + +/* if you want very early packet fragmentation bits and pieces */ +#define ACX_FRAGMENTATION 0 + +/* Locking: */ +/* very talkative */ +/* #define PARANOID_LOCKING 1 */ +/* normal (use when bug-free) */ +#define DO_LOCKING 1 +/* else locking is disabled! */ + +/* 0 - normal mode */ +/* 1 - development/debug: probe for IEs on modprobe */ +#define CMD_DISCOVERY 0 --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/acx_func.h +++ linux-2.6.27/ubuntu/misc/wireless/acx/acx_func.h @@ -0,0 +1,651 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + + +/*********************************************************************** +** LOGGING +** +** - Avoid SHOUTING needlessly. Avoid excessive verbosity. +** Gradually remove messages which are old debugging aids. +** +** - Use printk() for messages which are to be always logged. +** Supply either 'acx:' or ':' prefix so that user +** can figure out who's speaking among other kernel chatter. +** acx: is for general issues (e.g. "acx: no firmware image!") +** while : is related to a particular device +** (think about multi-card setup). Double check that message +** is not confusing to the average user. +** +** - use printk KERN_xxx level only if message is not a WARNING +** but is INFO, ERR etc. +** +** - Use printk_ratelimited() for messages which may flood +** (e.g. "rx DUP pkt!"). +** +** - Use log() for messages which may be omitted (and they +** _will_ be omitted in non-debug builds). Note that +** message levels may be disabled at compile-time selectively, +** thus select them wisely. Example: L_DEBUG is the lowest +** (most likely to be compiled out) -> use for less important stuff. +** +** - Do not print important stuff with log(), or else people +** will never build non-debug driver. +** +** Style: +** hex: capital letters, zero filled (e.g. 0x02AC) +** str: dont start from capitals, no trailing periods ("tx: queue is stopped") +*/ +#if ACX_DEBUG > 1 + +void log_fn_enter(const char *funcname); +void log_fn_exit(const char *funcname); +void log_fn_exit_v(const char *funcname, int v); + +#define FN_ENTER \ + do { \ + if (unlikely(acx_debug & L_FUNC)) { \ + log_fn_enter(__func__); \ + } \ + } while (0) + +#define FN_EXIT1(v) \ + do { \ + if (unlikely(acx_debug & L_FUNC)) { \ + log_fn_exit_v(__func__, v); \ + } \ + } while (0) +#define FN_EXIT0 \ + do { \ + if (unlikely(acx_debug & L_FUNC)) { \ + log_fn_exit(__func__); \ + } \ + } while (0) + +#else + +#define FN_ENTER +#define FN_EXIT1(v) +#define FN_EXIT0 + +#endif /* ACX_DEBUG > 1 */ + + +#if ACX_DEBUG + +#define log(chan, args...) \ + do { \ + if (acx_debug & (chan)) \ + printk(args); \ + } while (0) +#define printk_ratelimited(args...) printk(args) + +#else /* Non-debug build: */ + +#define log(chan, args...) +/* Standard way of log flood prevention */ +#define printk_ratelimited(args...) \ +do { \ + if (printk_ratelimit()) \ + printk(args); \ +} while (0) + +#endif /* ACX_DEBUG */ + +void acx_print_mac(const char *head, const u8 *mac, const char *tail); + +/* Optimized out to nothing in non-debug build */ +static inline void +acxlog_mac(int level, const char *head, const u8 *mac, const char *tail) +{ + if (acx_debug & level) { + acx_print_mac(head, mac, tail); + } +} + + +/*********************************************************************** +** MAC address helpers +*/ +static inline void +MAC_COPY(u8 *mac, const u8 *src) +{ + *(u32*)mac = *(u32*)src; + ((u16*)mac)[2] = ((u16*)src)[2]; + /* kernel's memcpy will do the same: memcpy(dst, src, ETH_ALEN); */ +} + +static inline void +MAC_FILL(u8 *mac, u8 val) +{ + memset(mac, val, ETH_ALEN); +} + +static inline void +MAC_BCAST(u8 *mac) +{ + ((u16*)mac)[2] = *(u32*)mac = -1; +} + +static inline void +MAC_ZERO(u8 *mac) +{ + ((u16*)mac)[2] = *(u32*)mac = 0; +} + +static inline int +mac_is_equal(const u8 *a, const u8 *b) +{ + /* can't beat this */ + return memcmp(a, b, ETH_ALEN) == 0; +} + +static inline int +mac_is_bcast(const u8 *mac) +{ + /* AND together 4 first bytes with sign-extended 2 last bytes + ** Only bcast address gives 0xffffffff. +1 gives 0 */ + return ( *(s32*)mac & ((s16*)mac)[2] ) + 1 == 0; +} + +static inline int +mac_is_zero(const u8 *mac) +{ + return ( *(u32*)mac | ((u16*)mac)[2] ) == 0; +} + +static inline int +mac_is_directed(const u8 *mac) +{ + return (mac[0] & 1)==0; +} + +static inline int +mac_is_mcast(const u8 *mac) +{ + return (mac[0] & 1) && !mac_is_bcast(mac); +} + +#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X" +#define MAC(bytevector) \ + ((unsigned char *)bytevector)[0], \ + ((unsigned char *)bytevector)[1], \ + ((unsigned char *)bytevector)[2], \ + ((unsigned char *)bytevector)[3], \ + ((unsigned char *)bytevector)[4], \ + ((unsigned char *)bytevector)[5] + + +/*********************************************************************** +** Random helpers +*/ +#define TO_STRING(x) #x +#define STRING(x) TO_STRING(x) + +#define CLEAR_BIT(val, mask) ((val) &= ~(mask)) +#define SET_BIT(val, mask) ((val) |= (mask)) + +/* undefined if v==0 */ +static inline unsigned int +lowest_bit(u16 v) +{ + unsigned int n = 0; + while (!(v & 0xf)) { v>>=4; n+=4; } + while (!(v & 1)) { v>>=1; n++; } + return n; +} + +/* undefined if v==0 */ +static inline unsigned int +highest_bit(u16 v) +{ + unsigned int n = 0; + while (v>0xf) { v>>=4; n+=4; } + while (v>1) { v>>=1; n++; } + return n; +} + +/* undefined if v==0 */ +static inline int +has_only_one_bit(u16 v) +{ + return ((v-1) ^ v) >= v; +} + + +static inline int +is_hidden_essid(char *essid) +{ + return (('\0' == essid[0]) || + ((' ' == essid[0]) && ('\0' == essid[1]))); +} + +/*********************************************************************** +** LOCKING +** We have adev->sem and adev->lock. +** +** We employ following naming convention in order to get locking right: +** +** acx_e_xxxx - external entry points called from process context. +** It is okay to sleep. adev->sem is to be taken on entry. +** acx_i_xxxx - external entry points possibly called from atomic context. +** Sleeping is not allowed (and thus down(sem) is not legal!) +** acx_s_xxxx - potentially sleeping functions. Do not ever call under lock! +** acx_l_xxxx - functions which expect lock to be already taken. +** rest - non-sleeping functions which do not require locking +** but may be run under lock +** +** A small number of local helpers do not have acx_[eisl]_ prefix. +** They are always close to caller and are to be reviewed locally. +** +** Theory of operation: +** +** All process-context entry points (_e_ functions) take sem +** immediately. IRQ handler and other 'atomic-context' entry points +** (_i_ functions) take lock immediately on entry, but dont take sem +** because that might sleep. +** +** Thus *all* code is either protected by sem or lock, or both. +** +** Code which must not run concurrently with IRQ takes lock. +** Such code is marked with _l_. +** +** This results in the following rules of thumb useful in code review: +** +** + If a function calls _s_ fn, it must be an _s_ itself. +** + You can call _l_ fn only (a) from another _l_ fn +** or (b) from _s_, _e_ or _i_ fn by taking lock, calling _l_, +** and dropping lock. +** + All IRQ code runs under lock. +** + Any _s_ fn is running under sem. +** + Code under sem can race only with IRQ code. +** + Code under sem+lock cannot race with anything. +*/ + +/* These functions *must* be inline or they will break horribly on SPARC, due + * to its weird semantics for save/restore flags */ + +#if defined(PARANOID_LOCKING) /* Lock debugging */ + +void acx_lock_debug(acx_device_t *adev, const char* where); +void acx_unlock_debug(acx_device_t *adev, const char* where); +void acx_down_debug(acx_device_t *adev, const char* where); +void acx_up_debug(acx_device_t *adev, const char* where); +void acx_lock_unhold(void); +void acx_sem_unhold(void); + +static inline void +acx_lock_helper(acx_device_t *adev, unsigned long *fp, const char* where) +{ + acx_lock_debug(adev, where); + spin_lock_irqsave(&adev->lock, *fp); +} +static inline void +acx_unlock_helper(acx_device_t *adev, unsigned long *fp, const char* where) +{ + acx_unlock_debug(adev, where); + spin_unlock_irqrestore(&adev->lock, *fp); +} +static inline void +acx_down_helper(acx_device_t *adev, const char* where) +{ + acx_down_debug(adev, where); +} +static inline void +acx_up_helper(acx_device_t *adev, const char* where) +{ + acx_up_debug(adev, where); +} +#define acx_lock(adev, flags) acx_lock_helper(adev, &(flags), __FILE__ ":" STRING(__LINE__)) +#define acx_unlock(adev, flags) acx_unlock_helper(adev, &(flags), __FILE__ ":" STRING(__LINE__)) +#define acx_sem_lock(adev) acx_down_helper(adev, __FILE__ ":" STRING(__LINE__)) +#define acx_sem_unlock(adev) acx_up_helper(adev, __FILE__ ":" STRING(__LINE__)) + +#elif defined(DO_LOCKING) + +#define acx_lock(adev, flags) spin_lock_irqsave(&adev->lock, flags) +#define acx_unlock(adev, flags) spin_unlock_irqrestore(&adev->lock, flags) +#define acx_sem_lock(adev) down(&adev->sem) +#define acx_sem_unlock(adev) up(&adev->sem) +#define acx_lock_unhold() ((void)0) +#define acx_sem_unhold() ((void)0) + +#else /* no locking! :( */ + +#define acx_lock(adev, flags) ((void)0) +#define acx_unlock(adev, flags) ((void)0) +#define acx_sem_lock(adev) ((void)0) +#define acx_sem_unlock(adev) ((void)0) +#define acx_lock_unhold() ((void)0) +#define acx_sem_unhold() ((void)0) + +#endif + + +/*********************************************************************** +*/ + +/* Can race with rx path (which is not protected by sem): +** rx -> process_[re]assocresp() -> set_status(ASSOCIATED) -> wake_queue() +** Can race with tx_complete IRQ: +** IRQ -> acxpci_l_clean_txdesc -> acx_wake_queue +** Review carefully all callsites */ +static inline void +acx_stop_queue(struct net_device *ndev, const char *msg) +{ + if (netif_queue_stopped(ndev)) + return; + + netif_stop_queue(ndev); + if (msg) + log(L_BUFT, "tx: stop queue %s\n", msg); +} + +static inline int +acx_queue_stopped(struct net_device *ndev) +{ + return netif_queue_stopped(ndev); +} + +/* +static inline void +acx_start_queue(struct net_device *ndev, const char *msg) +{ + netif_start_queue(ndev); + if (msg) + log(L_BUFT, "tx: start queue %s\n", msg); +} +*/ + +static inline void +acx_wake_queue(struct net_device *ndev, const char *msg) +{ + netif_wake_queue(ndev); + if (msg) + log(L_BUFT, "tx: wake queue %s\n", msg); +} + +static inline void +acx_carrier_off(struct net_device *ndev, const char *msg) +{ + netif_carrier_off(ndev); + if (msg) + log(L_BUFT, "tx: carrier off %s\n", msg); +} + +static inline void +acx_carrier_on(struct net_device *ndev, const char *msg) +{ + netif_carrier_on(ndev); + if (msg) + log(L_BUFT, "tx: carrier on %s\n", msg); +} + +/* This function does not need locking UNLESS you call it +** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can +** wake queue. This can race with stop_queue elsewhere. */ +void acx_set_status(acx_device_t *adev, u16 status); + + +/*********************************************************************** +** Communication with firmware +*/ +#define CMD_TIMEOUT_MS(n) (n) +#define ACX_CMD_TIMEOUT_DEFAULT CMD_TIMEOUT_MS(50) + +#if ACX_DEBUG + +/* We want to log cmd names */ +int acxpci_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr); +int acxusb_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr); +static inline int +acx_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr) +{ + if (IS_PCI(adev)) + return acxpci_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr); + return acxusb_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr); +} +#define acx_s_issue_cmd(adev,cmd,param,len) \ + acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,ACX_CMD_TIMEOUT_DEFAULT,#cmd) +#define acx_s_issue_cmd_timeo(adev,cmd,param,len,timeo) \ + acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,timeo,#cmd) +int acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* str); +#define acx_s_configure(adev,pdr,type) \ + acx_s_configure_debug(adev,pdr,type,#type) +int acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type, const char* str); +#define acx_s_interrogate(adev,pdr,type) \ + acx_s_interrogate_debug(adev,pdr,type,#type) + +#else + +int acxpci_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout); +int acxusb_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout); +static inline int +acx_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout) +{ + if (IS_PCI(adev)) + return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, timeout); + return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, timeout); +} +static inline int +acx_s_issue_cmd(acx_device_t *adev, unsigned cmd, void *param, unsigned len) +{ + if (IS_PCI(adev)) + return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT); + return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT); +} +int acx_s_configure(acx_device_t *adev, void *pdr, int type); +int acx_s_interrogate(acx_device_t *adev, void *pdr, int type); + +#endif + +void acx_s_cmd_start_scan(acx_device_t *adev); + + +/*********************************************************************** +** Ioctls +*/ +int +acx111pci_ioctl_info( + struct net_device *ndev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra); +int +acx100pci_ioctl_set_phy_amp_bias( + struct net_device *ndev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra); + + +/*********************************************************************** +** /proc +*/ +#ifdef CONFIG_PROC_FS +int acx_proc_register_entries(const struct net_device *ndev); +int acx_proc_unregister_entries(const struct net_device *ndev); +#else +static inline int +acx_proc_register_entries(const struct net_device *ndev) { return OK; } +static inline int +acx_proc_unregister_entries(const struct net_device *ndev) { return OK; } +#endif + + +/*********************************************************************** +*/ +firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size); +int acxpci_s_upload_radio(acx_device_t *adev); + + +/*********************************************************************** +** Unsorted yet :) +*/ +int acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf); +int acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf); +static inline int +acx_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf) +{ + if (IS_PCI(adev)) + return acxpci_s_read_phy_reg(adev, reg, charbuf); + return acxusb_s_read_phy_reg(adev, reg, charbuf); +} + +int acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value); +int acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value); +static inline int +acx_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value) +{ + if (IS_PCI(adev)) + return acxpci_s_write_phy_reg(adev, reg, value); + return acxusb_s_write_phy_reg(adev, reg, value); +} + +tx_t* acxpci_l_alloc_tx(acx_device_t *adev); +tx_t* acxusb_l_alloc_tx(acx_device_t *adev); +static inline tx_t* +acx_l_alloc_tx(acx_device_t *adev) +{ + if (IS_PCI(adev)) + return acxpci_l_alloc_tx(adev); + return acxusb_l_alloc_tx(adev); +} + +void acxusb_l_dealloc_tx(tx_t *tx_opaque); +static inline void +acx_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque) +{ + if (IS_USB(adev)) + acxusb_l_dealloc_tx(tx_opaque); +} + +void* acxpci_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque); +void* acxusb_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque); +static inline void* +acx_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque) +{ + if (IS_PCI(adev)) + return acxpci_l_get_txbuf(adev, tx_opaque); + return acxusb_l_get_txbuf(adev, tx_opaque); +} + +void acxpci_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len); +void acxusb_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len); +static inline void +acx_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len) +{ + if (IS_PCI(adev)) + acxpci_l_tx_data(adev, tx_opaque, len); + else + acxusb_l_tx_data(adev, tx_opaque, len); +} + +static inline wlan_hdr_t* +acx_get_wlan_hdr(acx_device_t *adev, const rxbuffer_t *rxbuf) +{ + return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + adev->phy_header_len); +} + +void acxpci_l_power_led(acx_device_t *adev, int enable); +int acxpci_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf); +unsigned int acxpci_l_clean_txdesc(acx_device_t *adev); +void acxpci_l_clean_txdesc_emergency(acx_device_t *adev); +int acxpci_s_create_hostdesc_queues(acx_device_t *adev); +void acxpci_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start); +void acxpci_free_desc_queues(acx_device_t *adev); +char* acxpci_s_proc_diag_output(char *p, acx_device_t *adev); +int acxpci_proc_eeprom_output(char *p, acx_device_t *adev); +void acxpci_set_interrupt_mask(acx_device_t *adev); +int acx100pci_s_set_tx_level(acx_device_t *adev, u8 level_dbm); + +void acx_s_msleep(int ms); +int acx_s_init_mac(acx_device_t *adev); +void acx_set_reg_domain(acx_device_t *adev, unsigned char reg_dom_id); +void acx_set_timer(acx_device_t *adev, int timeout_us); +void acx_update_capabilities(acx_device_t *adev); +void acx_s_start(acx_device_t *adev); + +void acx_s_update_card_settings(acx_device_t *adev); +void acx_s_parse_configoption(acx_device_t *adev, const acx111_ie_configoption_t *pcfg); +void acx_l_update_ratevector(acx_device_t *adev); + +void acx_init_task_scheduler(acx_device_t *adev); +void acx_schedule_task(acx_device_t *adev, unsigned int set_flag); + +int acx_e_ioctl_old(struct net_device *ndev, struct ifreq *ifr, int cmd); + +client_t *acx_l_sta_list_get(acx_device_t *adev, const u8 *address); +void acx_l_sta_list_del(acx_device_t *adev, client_t *clt); + +int acx_l_transmit_disassoc(acx_device_t *adev, client_t *clt); +void acx_i_timer(unsigned long a); +int acx_s_complete_scan(acx_device_t *adev); + +struct sk_buff *acx_rxbuf_to_ether(acx_device_t *adev, rxbuffer_t *rxbuf); +int acx_ether_to_txbuf(acx_device_t *adev, void *txbuf, const struct sk_buff *skb); + +u8 acx_signal_determine_quality(u8 signal, u8 noise); + +void acx_l_process_rxbuf(acx_device_t *adev, rxbuffer_t *rxbuf); +void acx_l_handle_txrate_auto(acx_device_t *adev, struct client *txc, + u16 intended_rate, u8 rate100, u16 rate111, u8 error, + int pkts_to_ignore); + +void acx_dump_bytes(const void *, int); +void acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr); + +u8 acx_rate111to100(u16); + +void acx_s_set_defaults(acx_device_t *adev); + +#if !ACX_DEBUG +static inline const char* acx_get_packet_type_string(u16 fc) { return ""; } +#else +const char* acx_get_packet_type_string(u16 fc); +#endif +const char* acx_cmd_status_str(unsigned int state); + +int acx_i_start_xmit(struct sk_buff *skb, struct net_device *ndev); + +void great_inquisitor(acx_device_t *adev); + +void acx_s_get_firmware_version(acx_device_t *adev); +void acx_display_hardware_details(acx_device_t *adev); + +int acx_e_change_mtu(struct net_device *ndev, int mtu); +struct net_device_stats* acx_e_get_stats(struct net_device *ndev); +struct iw_statistics* acx_e_get_wireless_stats(struct net_device *ndev); + +int __init acxpci_e_init_module(void); +int __init acxusb_e_init_module(void); +void __exit acxpci_e_cleanup_module(void); +void __exit acxusb_e_cleanup_module(void); --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/pci.c +++ linux-2.6.27/ubuntu/misc/wireless/acx/pci.c @@ -0,0 +1,4260 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ +#define ACX_PCI 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acx.h" + + +/*********************************************************************** +*/ +#define PCI_TYPE (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE) +#define PCI_ACX100_REGION1 0x01 +#define PCI_ACX100_REGION1_SIZE 0x1000 /* Memory size - 4K bytes */ +#define PCI_ACX100_REGION2 0x02 +#define PCI_ACX100_REGION2_SIZE 0x10000 /* Memory size - 64K bytes */ + +#define PCI_ACX111_REGION1 0x00 +#define PCI_ACX111_REGION1_SIZE 0x2000 /* Memory size - 8K bytes */ +#define PCI_ACX111_REGION2 0x01 +#define PCI_ACX111_REGION2_SIZE 0x20000 /* Memory size - 128K bytes */ + +/* Texas Instruments Vendor ID */ +#define PCI_VENDOR_ID_TI 0x104c + +/* ACX100 22Mb/s WLAN controller */ +#define PCI_DEVICE_ID_TI_TNETW1100A 0x8400 +#define PCI_DEVICE_ID_TI_TNETW1100B 0x8401 + +/* ACX111 54Mb/s WLAN controller */ +#define PCI_DEVICE_ID_TI_TNETW1130 0x9066 + +/* PCI Class & Sub-Class code, Network-'Other controller' */ +#define PCI_CLASS_NETWORK_OTHERS 0x0280 + +#define CARD_EEPROM_ID_SIZE 6 + +#ifndef PCI_D0 +/* From include/linux/pci.h */ +#define PCI_D0 0 +#define PCI_D1 1 +#define PCI_D2 2 +#define PCI_D3hot 3 +#define PCI_D3cold 4 +#define PCI_UNKNOWN 5 +#define PCI_POWER_ERROR -1 +#endif + + +/*********************************************************************** +*/ +static void acxpci_i_tx_timeout(struct net_device *ndev); +static irqreturn_t acxpci_i_interrupt(int irq, void *dev_id); +static void acxpci_i_set_multicast_list(struct net_device *ndev); + +static int acxpci_e_open(struct net_device *ndev); +static int acxpci_e_close(struct net_device *ndev); +static void acxpci_s_up(struct net_device *ndev); +static void acxpci_s_down(struct net_device *ndev); + + +/*********************************************************************** +** Register access +*/ + +/* Pick one */ +/* #define INLINE_IO static */ +#define INLINE_IO static inline + +INLINE_IO u32 +read_reg32(acx_device_t *adev, unsigned int offset) +{ +#if ACX_IO_WIDTH == 32 + return readl((u8 *)adev->iobase + adev->io[offset]); +#else + return readw((u8 *)adev->iobase + adev->io[offset]) + + (readw((u8 *)adev->iobase + adev->io[offset] + 2) << 16); +#endif +} + +INLINE_IO u16 +read_reg16(acx_device_t *adev, unsigned int offset) +{ + return readw((u8 *)adev->iobase + adev->io[offset]); +} + +INLINE_IO u8 +read_reg8(acx_device_t *adev, unsigned int offset) +{ + return readb((u8 *)adev->iobase + adev->io[offset]); +} + +INLINE_IO void +write_reg32(acx_device_t *adev, unsigned int offset, u32 val) +{ +#if ACX_IO_WIDTH == 32 + writel(val, (u8 *)adev->iobase + adev->io[offset]); +#else + writew(val & 0xffff, (u8 *)adev->iobase + adev->io[offset]); + writew(val >> 16, (u8 *)adev->iobase + adev->io[offset] + 2); +#endif +} + +INLINE_IO void +write_reg16(acx_device_t *adev, unsigned int offset, u16 val) +{ + writew(val, (u8 *)adev->iobase + adev->io[offset]); +} + +INLINE_IO void +write_reg8(acx_device_t *adev, unsigned int offset, u8 val) +{ + writeb(val, (u8 *)adev->iobase + adev->io[offset]); +} + +/* Handle PCI posting properly: + * Make sure that writes reach the adapter in case they require to be executed + * *before* the next write, by reading a random (and safely accessible) register. + * This call has to be made if there is no read following (which would flush the data + * to the adapter), yet the written data has to reach the adapter immediately. */ +INLINE_IO void +write_flush(acx_device_t *adev) +{ + /* readb(adev->iobase + adev->io[IO_ACX_INFO_MAILBOX_OFFS]); */ + /* faster version (accesses the first register, IO_ACX_SOFT_RESET, + * which should also be safe): */ + readb(adev->iobase); +} + +INLINE_IO int +adev_present(acx_device_t *adev) +{ + /* fast version (accesses the first register, IO_ACX_SOFT_RESET, + * which should be safe): */ + return readl(adev->iobase) != 0xffffffff; +} + + +/*********************************************************************** +*/ +static inline txdesc_t* +get_txdesc(acx_device_t *adev, int index) +{ + return (txdesc_t*) (((u8*)adev->txdesc_start) + index * adev->txdesc_size); +} + +static inline txdesc_t* +advance_txdesc(acx_device_t *adev, txdesc_t* txdesc, int inc) +{ + return (txdesc_t*) (((u8*)txdesc) + inc * adev->txdesc_size); +} + +static txhostdesc_t* +get_txhostdesc(acx_device_t *adev, txdesc_t* txdesc) +{ + int index = (u8*)txdesc - (u8*)adev->txdesc_start; + if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) { + printk("bad txdesc ptr %p\n", txdesc); + return NULL; + } + index /= adev->txdesc_size; + if (unlikely(ACX_DEBUG && (index >= TX_CNT))) { + printk("bad txdesc ptr %p\n", txdesc); + return NULL; + } + return &adev->txhostdesc_start[index*2]; +} + +static inline client_t* +get_txc(acx_device_t *adev, txdesc_t* txdesc) +{ + int index = (u8*)txdesc - (u8*)adev->txdesc_start; + if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) { + printk("bad txdesc ptr %p\n", txdesc); + return NULL; + } + index /= adev->txdesc_size; + if (unlikely(ACX_DEBUG && (index >= TX_CNT))) { + printk("bad txdesc ptr %p\n", txdesc); + return NULL; + } + return adev->txc[index]; +} + +static inline u16 +get_txr(acx_device_t *adev, txdesc_t* txdesc) +{ + int index = (u8*)txdesc - (u8*)adev->txdesc_start; + index /= adev->txdesc_size; + return adev->txr[index]; +} + +static inline void +put_txcr(acx_device_t *adev, txdesc_t* txdesc, client_t* c, u16 r111) +{ + int index = (u8*)txdesc - (u8*)adev->txdesc_start; + if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) { + printk("bad txdesc ptr %p\n", txdesc); + return; + } + index /= adev->txdesc_size; + if (unlikely(ACX_DEBUG && (index >= TX_CNT))) { + printk("bad txdesc ptr %p\n", txdesc); + return; + } + adev->txc[index] = c; + adev->txr[index] = r111; +} + + +/*********************************************************************** +** EEPROM and PHY read/write helpers +*/ +/*********************************************************************** +** acxpci_read_eeprom_byte +** +** Function called to read an octet in the EEPROM. +** +** This function is used by acxpci_e_probe to check if the +** connected card is a legal one or not. +** +** Arguments: +** adev ptr to acx_device structure +** addr address to read in the EEPROM +** charbuf ptr to a char. This is where the read octet +** will be stored +*/ +int +acxpci_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf) +{ + int result; + int count; + + write_reg32(adev, IO_ACX_EEPROM_CFG, 0); + write_reg32(adev, IO_ACX_EEPROM_ADDR, addr); + write_flush(adev); + write_reg32(adev, IO_ACX_EEPROM_CTL, 2); + + count = 0xffff; + while (read_reg16(adev, IO_ACX_EEPROM_CTL)) { + /* scheduling away instead of CPU burning loop + * doesn't seem to work here at all: + * awful delay, sometimes also failure. + * Doesn't matter anyway (only small delay). */ + if (unlikely(!--count)) { + printk("%s: timeout waiting for EEPROM read\n", + adev->ndev->name); + result = NOT_OK; + goto fail; + } + cpu_relax(); + } + + *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA); + log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf); + result = OK; + +fail: + return result; +} + + +/*********************************************************************** +** We don't lock hw accesses here since we never r/w eeprom in IRQ +** Note: this function sleeps only because of GFP_KERNEL alloc +*/ +#ifdef UNUSED +int +acxpci_s_write_eeprom(acx_device_t *adev, u32 addr, u32 len, const u8 *charbuf) +{ + u8 *data_verify = NULL; + unsigned long flags; + int count, i; + int result = NOT_OK; + u16 gpio_orig; + + printk("acx: WARNING! I would write to EEPROM now. " + "Since I really DON'T want to unless you know " + "what you're doing (THIS CODE WILL PROBABLY " + "NOT WORK YET!), I will abort that now. And " + "definitely make sure to make a " + "/proc/driver/acx_wlan0_eeprom backup copy first!!! " + "(the EEPROM content includes the PCI config header!! " + "If you kill important stuff, then you WILL " + "get in trouble and people DID get in trouble already)\n"); + return OK; + + FN_ENTER; + + data_verify = kmalloc(len, GFP_KERNEL); + if (!data_verify) { + goto end; + } + + /* first we need to enable the OE (EEPROM Output Enable) GPIO line + * to be able to write to the EEPROM. + * NOTE: an EEPROM writing success has been reported, + * but you probably have to modify GPIO_OUT, too, + * and you probably need to activate a different GPIO + * line instead! */ + gpio_orig = read_reg16(adev, IO_ACX_GPIO_OE); + write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig & ~1); + write_flush(adev); + + /* ok, now start writing the data out */ + for (i = 0; i < len; i++) { + write_reg32(adev, IO_ACX_EEPROM_CFG, 0); + write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i); + write_reg32(adev, IO_ACX_EEPROM_DATA, *(charbuf + i)); + write_flush(adev); + write_reg32(adev, IO_ACX_EEPROM_CTL, 1); + + count = 0xffff; + while (read_reg16(adev, IO_ACX_EEPROM_CTL)) { + if (unlikely(!--count)) { + printk("WARNING, DANGER!!! " + "Timeout waiting for EEPROM write\n"); + goto end; + } + cpu_relax(); + } + } + + /* disable EEPROM writing */ + write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig); + write_flush(adev); + + /* now start a verification run */ + for (i = 0; i < len; i++) { + write_reg32(adev, IO_ACX_EEPROM_CFG, 0); + write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i); + write_flush(adev); + write_reg32(adev, IO_ACX_EEPROM_CTL, 2); + + count = 0xffff; + while (read_reg16(adev, IO_ACX_EEPROM_CTL)) { + if (unlikely(!--count)) { + printk("timeout waiting for EEPROM read\n"); + goto end; + } + cpu_relax(); + } + + data_verify[i] = read_reg16(adev, IO_ACX_EEPROM_DATA); + } + + if (0 == memcmp(charbuf, data_verify, len)) + result = OK; /* read data matches, success */ + +end: + kfree(data_verify); + FN_EXIT1(result); + return result; +} +#endif /* UNUSED */ + + +/*********************************************************************** +** acxpci_s_read_phy_reg +** +** Messing with rx/tx disabling and enabling here +** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic +*/ +int +acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf) +{ + int result = NOT_OK; + int count; + + FN_ENTER; + + write_reg32(adev, IO_ACX_PHY_ADDR, reg); + write_flush(adev); + write_reg32(adev, IO_ACX_PHY_CTL, 2); + + count = 0xffff; + while (read_reg32(adev, IO_ACX_PHY_CTL)) { + /* scheduling away instead of CPU burning loop + * doesn't seem to work here at all: + * awful delay, sometimes also failure. + * Doesn't matter anyway (only small delay). */ + if (unlikely(!--count)) { + printk("%s: timeout waiting for phy read\n", + adev->ndev->name); + *charbuf = 0; + goto fail; + } + cpu_relax(); + } + + log(L_DEBUG, "count was %u\n", count); + *charbuf = read_reg8(adev, IO_ACX_PHY_DATA); + + log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg); + result = OK; + goto fail; /* silence compiler warning */ +fail: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +int +acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value) +{ + FN_ENTER; + + /* mprusko said that 32bit accesses result in distorted sensitivity + * on his card. Unconfirmed, looks like it's not true (most likely since we + * now properly flush writes). */ + write_reg32(adev, IO_ACX_PHY_DATA, value); + write_reg32(adev, IO_ACX_PHY_ADDR, reg); + write_flush(adev); + write_reg32(adev, IO_ACX_PHY_CTL, 1); + write_flush(adev); + log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg); + + FN_EXIT1(OK); + return OK; +} + + +#define NO_AUTO_INCREMENT 1 + +/*********************************************************************** +** acxpci_s_write_fw +** +** Write the firmware image into the card. +** +** Arguments: +** adev wlan device structure +** fw_image firmware image. +** +** Returns: +** 1 firmware image corrupted +** 0 success +*/ +static int +acxpci_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset) +{ + int len, size; + u32 sum, v32; + /* we skip the first four bytes which contain the control sum */ + const u8 *p = (u8*)fw_image + 4; + + /* start the image checksum by adding the image size value */ + sum = p[0]+p[1]+p[2]+p[3]; + p += 4; + + write_reg32(adev, IO_ACX_SLV_END_CTL, 0); + +#if NO_AUTO_INCREMENT + write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */ +#else + write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */ + write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */ + write_flush(adev); +#endif + + len = 0; + size = le32_to_cpu(fw_image->size) & (~3); + + while (likely(len < size)) { + v32 = be32_to_cpu(*(u32*)p); + sum += p[0]+p[1]+p[2]+p[3]; + p += 4; + len += 4; + +#if NO_AUTO_INCREMENT + write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4); + write_flush(adev); +#endif + write_reg32(adev, IO_ACX_SLV_MEM_DATA, v32); + } + + log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n", + size, sum, le32_to_cpu(fw_image->chksum)); + + /* compare our checksum with the stored image checksum */ + return (sum != le32_to_cpu(fw_image->chksum)); +} + + +/*********************************************************************** +** acxpci_s_validate_fw +** +** Compare the firmware image given with +** the firmware image written into the card. +** +** Arguments: +** adev wlan device structure +** fw_image firmware image. +** +** Returns: +** NOT_OK firmware image corrupted or not correctly written +** OK success +*/ +static int +acxpci_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image, + u32 offset) +{ + u32 sum, v32, w32; + int len, size; + int result = OK; + /* we skip the first four bytes which contain the control sum */ + const u8 *p = (u8*)fw_image + 4; + + /* start the image checksum by adding the image size value */ + sum = p[0]+p[1]+p[2]+p[3]; + p += 4; + + write_reg32(adev, IO_ACX_SLV_END_CTL, 0); + +#if NO_AUTO_INCREMENT + write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */ +#else + write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */ + write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */ +#endif + + len = 0; + size = le32_to_cpu(fw_image->size) & (~3); + + while (likely(len < size)) { + v32 = be32_to_cpu(*(u32*)p); + p += 4; + len += 4; + +#if NO_AUTO_INCREMENT + write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4); +#endif + w32 = read_reg32(adev, IO_ACX_SLV_MEM_DATA); + + if (unlikely(w32 != v32)) { + printk("acx: FATAL: firmware upload: " + "data parts at offset %d don't match (0x%08X vs. 0x%08X)! " + "I/O timing issues or defective memory, with DWL-xx0+? " + "ACX_IO_WIDTH=16 may help. Please report\n", + len, v32, w32); + result = NOT_OK; + break; + } + + sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24); + } + + /* sum control verification */ + if (result != NOT_OK) { + if (sum != le32_to_cpu(fw_image->chksum)) { + printk("acx: FATAL: firmware upload: " + "checksums don't match!\n"); + result = NOT_OK; + } + } + + return result; +} + +struct fw_match { + unsigned short vendor; + unsigned short device; + unsigned short subvendor; + unsigned short subdevice; + const char *verstr; + int announced; +}; + +/* NOTE: This is NOT the module device table. We're just abusing the + * pci_device_id struct for our own purposes */ +static struct fw_match fw_ver_table[] = { + { /* Abocom WG24500, reported by Franz Pletz */ + .vendor = PCI_VENDOR_ID_TI, + .device = PCI_DEVICE_ID_TI_TNETW1130, + .subvendor = 0x13d1, + .subdevice = 0xab80, + .verstr = "1.2.0.30", + }, + { /* Texas Instruments ACX 111 54Mbps Wireless Interface */ + .vendor = PCI_VENDOR_ID_TI, + .device = PCI_DEVICE_ID_TI_TNETW1130, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .verstr = "1.2.1.34", + }, + { 0 } +}; + +#define PCI_MATCH(a,b) (a == b || a == (unsigned short)PCI_ANY_ID) + +/* Returns an alternate version of the firmware for specific devices. The + * above table will _always_ be overriden by module param. */ +static const char *get_firmware_ver(struct pci_dev *dev) +{ + struct fw_match *dev_match; + + if (!dev || strcmp(firmware_ver, "default")) + goto use_default; + + for (dev_match = fw_ver_table; dev_match->vendor; dev_match++) { + if (PCI_MATCH(dev_match->vendor, dev->vendor) && + PCI_MATCH(dev_match->device, dev->device) && + PCI_MATCH(dev_match->subvendor, dev->subsystem_vendor) && + PCI_MATCH(dev_match->subdevice, dev->subsystem_device)) + return dev_match->verstr; + } + +use_default: + return firmware_ver; +} + + +/*********************************************************************** +** acxpci_s_upload_fw +** +** Called from acx_reset_dev +*/ +static int +acxpci_s_upload_fw(acx_device_t *adev) +{ + firmware_image_t *fw_image = NULL; + int res = NOT_OK; + int try; + u32 file_size; + char filename[256]; + + FN_ENTER; + + printk(KERN_INFO "acx: loading firmware for acx1%02d chipset with radio" + " ID %02X\n", IS_ACX111(adev)*111, adev->radio_type); + + /* Try combined, then main image */ + adev->need_radio_fw = 0; + snprintf(filename, sizeof(filename), "acx/%s/tiacx1%02dc%02X", + get_firmware_ver(adev->pdev), + IS_ACX111(adev)*11, adev->radio_type); + + fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size); + if (!fw_image) { + adev->need_radio_fw = 1; + filename[strlen(filename) - 3] = '\0'; + fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size); + if (!fw_image) { + FN_EXIT1(NOT_OK); + return NOT_OK; + } + } + + for (try = 1; try <= 5; try++) { + res = acxpci_s_write_fw(adev, fw_image, 0); + log(L_DEBUG|L_INIT, "acx_write_fw (main/combined): %d\n", res); + if (OK == res) { + res = acxpci_s_validate_fw(adev, fw_image, 0); + log(L_DEBUG|L_INIT, "acx_validate_fw " + "(main/combined): %d\n", res); + } + + if (OK == res) { + SET_BIT(adev->dev_state_mask, ACX_STATE_FW_LOADED); + break; + } + printk("acx: firmware upload attempt #%d FAILED, " + "retrying...\n", try); + acx_s_msleep(1000); /* better wait for a while... */ + } + + vfree(fw_image); + + FN_EXIT1(res); + return res; +} + + +/*********************************************************************** +** acxpci_s_upload_radio +** +** Uploads the appropriate radio module firmware into the card. +*/ +int +acxpci_s_upload_radio(acx_device_t *adev) +{ + acx_ie_memmap_t mm; + firmware_image_t *radio_image; + acx_cmd_radioinit_t radioinit; + int res = NOT_OK; + int try; + u32 offset; + u32 size; + char filename[256]; + + if (!adev->need_radio_fw) return OK; + + FN_ENTER; + + printk(KERN_INFO "acx: loading radio image for radio %02X\n", + adev->radio_type); + + acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP); + offset = le32_to_cpu(mm.CodeEnd); + + snprintf(filename, sizeof(filename), "acx/%s/tiacx1%02dr%02X", + get_firmware_ver(adev->pdev), IS_ACX111(adev)*11, + adev->radio_type); + radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size); + if (!radio_image) { + printk("acx: can't load radio module '%s'\n", filename); + goto fail; + } + + acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0); + + for (try = 1; try <= 5; try++) { + res = acxpci_s_write_fw(adev, radio_image, offset); + log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res); + if (OK == res) { + res = acxpci_s_validate_fw(adev, radio_image, offset); + log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res); + } + + if (OK == res) + break; + printk("acx: radio firmware upload attempt #%d FAILED, " + "retrying...\n", try); + acx_s_msleep(1000); /* better wait for a while... */ + } + + acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0); + radioinit.offset = cpu_to_le32(offset); + /* no endian conversion needed, remains in card CPU area: */ + radioinit.len = radio_image->size; + + vfree(radio_image); + + if (OK != res) + goto fail; + + /* will take a moment so let's have a big timeout */ + acx_s_issue_cmd_timeo(adev, ACX1xx_CMD_RADIOINIT, + &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000)); + + res = acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP); +fail: + FN_EXIT1(res); + return res; +} + + +/*********************************************************************** +** acxpci_l_reset_mac +** +** MAC will be reset +** Call context: reset_dev +*/ +static void +acxpci_l_reset_mac(acx_device_t *adev) +{ + u16 temp; + + FN_ENTER; + + /* halt eCPU */ + temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1; + write_reg16(adev, IO_ACX_ECPU_CTRL, temp); + + /* now do soft reset of eCPU, set bit */ + temp = read_reg16(adev, IO_ACX_SOFT_RESET) | 0x1; + log(L_DEBUG, "%s: enable soft reset...\n", __func__); + write_reg16(adev, IO_ACX_SOFT_RESET, temp); + write_flush(adev); + + /* now clear bit again: deassert eCPU reset */ + log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__); + write_reg16(adev, IO_ACX_SOFT_RESET, temp & ~0x1); + + /* now start a burst read from initial EEPROM */ + temp = read_reg16(adev, IO_ACX_EE_START) | 0x1; + write_reg16(adev, IO_ACX_EE_START, temp); + write_flush(adev); + + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_s_verify_init +*/ +static int +acxpci_s_verify_init(acx_device_t *adev) +{ + int result = NOT_OK; + unsigned long timeout; + + FN_ENTER; + + timeout = jiffies + 2*HZ; + for (;;) { + u16 irqstat = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES); + if (irqstat & HOST_INT_FCS_THRESHOLD) { + result = OK; + write_reg16(adev, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD); + break; + } + if (time_after(jiffies, timeout)) + break; + /* Init may take up to ~0.5 sec total */ + acx_s_msleep(50); + } + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** A few low-level helpers +** +** Note: these functions are not protected by lock +** and thus are never allowed to be called from IRQ. +** Also they must not race with fw upload which uses same hw regs +*/ + +/*********************************************************************** +** acxpci_write_cmd_type_status +*/ + +static inline void +acxpci_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status) +{ + writel(type | (status << 16), adev->cmd_area); + write_flush(adev); +} + + +/*********************************************************************** +** acxpci_read_cmd_type_status +*/ +static u32 +acxpci_read_cmd_type_status(acx_device_t *adev) +{ + u32 cmd_type, cmd_status; + + cmd_type = readl(adev->cmd_area); + cmd_status = (cmd_type >> 16); + cmd_type = (u16)cmd_type; + + log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n", + cmd_type, cmd_status, + acx_cmd_status_str(cmd_status)); + + return cmd_status; +} + + +/*********************************************************************** +** acxpci_s_reset_dev +** +** Arguments: +** netdevice that contains the adev variable +** Returns: +** NOT_OK on fail +** OK on success +** Side effects: +** device is hard reset +** Call context: +** acxpci_e_probe +** Comment: +** This resets the device using low level hardware calls +** as well as uploads and verifies the firmware to the card +*/ + +static inline void +init_mboxes(acx_device_t *adev) +{ + u32 cmd_offs, info_offs; + + cmd_offs = read_reg32(adev, IO_ACX_CMD_MAILBOX_OFFS); + info_offs = read_reg32(adev, IO_ACX_INFO_MAILBOX_OFFS); + adev->cmd_area = (u8 *)adev->iobase2 + cmd_offs; + adev->info_area = (u8 *)adev->iobase2 + info_offs; + log(L_DEBUG, "iobase2=%p\n" + "cmd_mbox_offset=%X cmd_area=%p\n" + "info_mbox_offset=%X info_area=%p\n", + adev->iobase2, + cmd_offs, adev->cmd_area, + info_offs, adev->info_area); +} + + +static inline void +read_eeprom_area(acx_device_t *adev) +{ +#if ACX_DEBUG > 1 + int offs; + u8 tmp; + + for (offs = 0x8c; offs < 0xb9; offs++) + acxpci_read_eeprom_byte(adev, offs, &tmp); +#endif +} + + +static int +acxpci_s_reset_dev(acx_device_t *adev) +{ + const char* msg = ""; + unsigned long flags; + int result = NOT_OK; + u16 hardware_info; + u16 ecpu_ctrl; + int count; + + FN_ENTER; + + /* reset the device to make sure the eCPU is stopped + * to upload the firmware correctly */ + + acx_lock(adev, flags); + + acxpci_l_reset_mac(adev); + + ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1; + if (!ecpu_ctrl) { + msg = "eCPU is already running. "; + goto end_unlock; + } + +#ifdef WE_DONT_NEED_THAT_DO_WE + if (read_reg16(adev, IO_ACX_SOR_CFG) & 2) { + /* eCPU most likely means "embedded CPU" */ + msg = "eCPU did not start after boot from flash. "; + goto end_unlock; + } + + /* check sense on reset flags */ + if (read_reg16(adev, IO_ACX_SOR_CFG) & 0x10) { + printk("%s: eCPU did not start after boot (SOR), " + "is this fatal?\n", adev->ndev->name); + } +#endif + /* scan, if any, is stopped now, setting corresponding IRQ bit */ + adev->irq_status |= HOST_INT_SCAN_COMPLETE; + + acx_unlock(adev, flags); + + /* need to know radio type before fw load */ + /* Need to wait for arrival of this information in a loop, + * most probably since eCPU runs some init code from EEPROM + * (started burst read in reset_mac()) which also + * sets the radio type ID */ + + count = 0xffff; + do { + hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION); + if (!--count) { + msg = "eCPU didn't indicate radio type"; + goto end_fail; + } + cpu_relax(); + } while (!(hardware_info & 0xff00)); /* radio type still zero? */ + + /* printk("DEBUG: count %d\n", count); */ + adev->form_factor = hardware_info & 0xff; + adev->radio_type = hardware_info >> 8; + + /* load the firmware */ + if (OK != acxpci_s_upload_fw(adev)) + goto end_fail; + + /* acx_s_msleep(10); this one really shouldn't be required */ + + /* now start eCPU by clearing bit */ + write_reg16(adev, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1); + log(L_DEBUG, "booted eCPU up and waiting for completion...\n"); + + /* wait for eCPU bootup */ + if (OK != acxpci_s_verify_init(adev)) { + msg = "timeout waiting for eCPU. "; + goto end_fail; + } + log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n"); + + init_mboxes(adev); + acxpci_write_cmd_type_status(adev, 0, 0); + + /* test that EEPROM is readable */ + read_eeprom_area(adev); + + result = OK; + goto end; + +/* Finish error message. Indicate which function failed */ +end_unlock: + acx_unlock(adev, flags); +end_fail: + printk("acx: %sreset_dev() FAILED\n", msg); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acxpci_s_issue_cmd_timeo +** +** Sends command to fw, extract result +** +** NB: we do _not_ take lock inside, so be sure to not touch anything +** which may interfere with IRQ handler operation +** +** TODO: busy wait is a bit silly, so: +** 1) stop doing many iters - go to sleep after first +** 2) go to waitqueue based approach: wait, not poll! +*/ +#undef FUNC +#define FUNC "issue_cmd" + +#if !ACX_DEBUG +int +acxpci_s_issue_cmd_timeo( + acx_device_t *adev, + unsigned int cmd, + void *buffer, + unsigned buflen, + unsigned cmd_timeout) +{ +#else +int +acxpci_s_issue_cmd_timeo_debug( + acx_device_t *adev, + unsigned cmd, + void *buffer, + unsigned buflen, + unsigned cmd_timeout, + const char* cmdstr) +{ + unsigned long start = jiffies; +#endif + const char *devname; + unsigned counter; + u16 irqtype; + u16 cmd_status; + unsigned long timeout; + + FN_ENTER; + + devname = adev->ndev->name; + if (!devname || !devname[0] || devname[4]=='%') + devname = "acx"; + + log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n", + cmdstr, buflen, cmd_timeout, + buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1); + + if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) { + printk("%s: "FUNC"(): firmware is not loaded yet, " + "cannot execute commands!\n", devname); + goto bad; + } + + if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) { + printk("input buffer (len=%u):\n", buflen); + acx_dump_bytes(buffer, buflen); + } + + /* wait for firmware to become idle for our command submission */ + timeout = HZ/5; + counter = (timeout * 1000 / HZ) - 1; /* in ms */ + timeout += jiffies; + do { + cmd_status = acxpci_read_cmd_type_status(adev); + /* Test for IDLE state */ + if (!cmd_status) + break; + if (counter % 8 == 0) { + if (time_after(jiffies, timeout)) { + counter = 0; + break; + } + /* we waited 8 iterations, no luck. Sleep 8 ms */ + acx_s_msleep(8); + } + } while (likely(--counter)); + + if (!counter) { + /* the card doesn't get idle, we're in trouble */ + printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n", + devname, cmd_status); + goto bad; + } else if (counter < 190) { /* if waited >10ms... */ + log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. " + "Please report\n", 199 - counter); + } + + /* now write the parameters of the command if needed */ + if (buffer && buflen) { + /* if it's an INTERROGATE command, just pass the length + * of parameters to read, as data */ +#if CMD_DISCOVERY + if (cmd == ACX1xx_CMD_INTERROGATE) + memset_io(adev->cmd_area + 4, 0xAA, buflen); +#endif + /* adev->cmd_area points to PCI device's memory, not to RAM! */ + memcpy_toio(adev->cmd_area + 4, buffer, + (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen); + } + /* now write the actual command type */ + acxpci_write_cmd_type_status(adev, cmd, 0); + /* execute command */ + write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD); + write_flush(adev); + + /* wait for firmware to process command */ + + /* Ensure nonzero and not too large timeout. + ** Also converts e.g. 100->99, 200->199 + ** which is nice but not essential */ + cmd_timeout = (cmd_timeout-1) | 1; + if (unlikely(cmd_timeout > 1199)) + cmd_timeout = 1199; + /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */ + adev->irq_status &= ~HOST_INT_CMD_COMPLETE; + + /* we schedule away sometimes (timeout can be large) */ + counter = cmd_timeout; + timeout = jiffies + cmd_timeout * HZ / 1000; + do { + if (!adev->irqs_active) { /* IRQ disabled: poll */ + irqtype = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES); + if (irqtype & HOST_INT_CMD_COMPLETE) { + write_reg16(adev, IO_ACX_IRQ_ACK, + HOST_INT_CMD_COMPLETE); + break; + } + } else { /* Wait when IRQ will set the bit */ + irqtype = adev->irq_status; + if (irqtype & HOST_INT_CMD_COMPLETE) + break; + } + + if (counter % 8 == 0) { + if (time_after(jiffies, timeout)) { + counter = 0; + break; + } + /* we waited 8 iterations, no luck. Sleep 8 ms */ + acx_s_msleep(8); + } + } while (likely(--counter)); + + /* save state for debugging */ + cmd_status = acxpci_read_cmd_type_status(adev); + + /* put the card in IDLE state */ + acxpci_write_cmd_type_status(adev, 0, 0); + + if (!counter) { /* timed out! */ + printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. " + "irq bits:0x%04X irq_status:0x%04X timeout:%dms " + "cmd_status:%d (%s)\n", + devname, (adev->irqs_active) ? "waiting" : "polling", + irqtype, adev->irq_status, cmd_timeout, + cmd_status, acx_cmd_status_str(cmd_status)); + goto bad; + } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */ + log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. " + "count:%d. Please report\n", + (adev->irqs_active) ? "waited" : "polled", + cmd_timeout - counter, counter); + } + + if (1 != cmd_status) { /* it is not a 'Success' */ + printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). " + "Took %dms of %d\n", + devname, cmd_status, acx_cmd_status_str(cmd_status), + cmd_timeout - counter, cmd_timeout); + /* zero out result buffer + * WARNING: this will trash stack in case of illegally large input + * length! */ + if (buffer && buflen) + memset(buffer, 0, buflen); + goto bad; + } + + /* read in result parameters if needed */ + if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) { + /* adev->cmd_area points to PCI device's memory, not to RAM! */ + memcpy_fromio(buffer, adev->cmd_area + 4, buflen); + if (acx_debug & L_DEBUG) { + printk("output buffer (len=%u): ", buflen); + acx_dump_bytes(buffer, buflen); + } + } +/* ok: */ + log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n", + cmdstr, jiffies - start); + FN_EXIT1(OK); + return OK; + +bad: + /* Give enough info so that callers can avoid + ** printing their own diagnostic messages */ +#if ACX_DEBUG + printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr); +#else + printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd); +#endif + dump_stack(); + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +*/ +#ifdef NONESSENTIAL_FEATURES +typedef struct device_id { + unsigned char id[6]; + char *descr; + char *type; +} device_id_t; + +static const device_id_t +device_ids[] = +{ + { + {'G', 'l', 'o', 'b', 'a', 'l'}, + NULL, + NULL, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + "uninitialized", + "SpeedStream SS1021 or Gigafast WF721-AEX" + }, + { + {0x80, 0x81, 0x82, 0x83, 0x84, 0x85}, + "non-standard", + "DrayTek Vigor 520" + }, + { + {'?', '?', '?', '?', '?', '?'}, + "non-standard", + "Level One WPC-0200" + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "empty", + "DWL-650+ variant" + } +}; + +static void +acx_show_card_eeprom_id(acx_device_t *adev) +{ + unsigned char buffer[CARD_EEPROM_ID_SIZE]; + int i; + + memset(&buffer, 0, CARD_EEPROM_ID_SIZE); + /* use direct EEPROM access */ + for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) { + if (OK != acxpci_read_eeprom_byte(adev, + ACX100_EEPROM_ID_OFFSET + i, + &buffer[i])) { + printk("acx: reading EEPROM FAILED\n"); + break; + } + } + + for (i = 0; i < VEC_SIZE(device_ids); i++) { + if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) { + if (device_ids[i].descr) { + printk("acx: EEPROM card ID string check " + "found %s card ID: is this %s?\n", + device_ids[i].descr, device_ids[i].type); + } + break; + } + } + if (i == VEC_SIZE(device_ids)) { + printk("acx: EEPROM card ID string check found " + "unknown card: expected 'Global', got '%.*s\'. " + "Please report\n", CARD_EEPROM_ID_SIZE, buffer); + } +} +#endif /* NONESSENTIAL_FEATURES */ + + +/*********************************************************************** +** acxpci_free_desc_queues +** +** Releases the queues that have been allocated, the +** others have been initialised to NULL so this +** function can be used if only part of the queues were allocated. +*/ + +static inline void +free_coherent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, + size, vaddr, dma_handle); +} + +void +acxpci_free_desc_queues(acx_device_t *adev) +{ +#define ACX_FREE_QUEUE(size, ptr, phyaddr) \ + if (ptr) { \ + free_coherent(0, size, ptr, phyaddr); \ + ptr = NULL; \ + size = 0; \ + } + + FN_ENTER; + + ACX_FREE_QUEUE(adev->txhostdesc_area_size, adev->txhostdesc_start, adev->txhostdesc_startphy); + ACX_FREE_QUEUE(adev->txbuf_area_size, adev->txbuf_start, adev->txbuf_startphy); + + adev->txdesc_start = NULL; + + ACX_FREE_QUEUE(adev->rxhostdesc_area_size, adev->rxhostdesc_start, adev->rxhostdesc_startphy); + ACX_FREE_QUEUE(adev->rxbuf_area_size, adev->rxbuf_start, adev->rxbuf_startphy); + + adev->rxdesc_start = NULL; + + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_s_delete_dma_regions +*/ +static void +acxpci_s_delete_dma_regions(acx_device_t *adev) +{ + unsigned long flags; + + FN_ENTER; + /* disable radio Tx/Rx. Shouldn't we use the firmware commands + * here instead? Or are we that much down the road that it's no + * longer possible here? */ + write_reg16(adev, IO_ACX_ENABLE, 0); + + acx_s_msleep(100); + + acx_lock(adev, flags); + acxpci_free_desc_queues(adev); + acx_unlock(adev, flags); + + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_e_probe +** +** Probe routine called when a PCI device w/ matching ID is found. +** Here's the sequence: +** - Allocate the PCI resources. +** - Read the PCMCIA attribute memory to make sure we have a WLAN card +** - Reset the MAC +** - Initialize the dev and wlan data +** - Initialize the MAC +** +** pdev - ptr to pci device structure containing info about pci configuration +** id - ptr to the device id entry that matched this device +*/ +static const u16 +IO_ACX100[] = +{ + 0x0000, /* IO_ACX_SOFT_RESET */ + + 0x0014, /* IO_ACX_SLV_MEM_ADDR */ + 0x0018, /* IO_ACX_SLV_MEM_DATA */ + 0x001c, /* IO_ACX_SLV_MEM_CTL */ + 0x0020, /* IO_ACX_SLV_END_CTL */ + + 0x0034, /* IO_ACX_FEMR */ + + 0x007c, /* IO_ACX_INT_TRIG */ + 0x0098, /* IO_ACX_IRQ_MASK */ + 0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */ + 0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */ + 0x00ac, /* IO_ACX_IRQ_ACK */ + 0x00b0, /* IO_ACX_HINT_TRIG */ + + 0x0104, /* IO_ACX_ENABLE */ + + 0x0250, /* IO_ACX_EEPROM_CTL */ + 0x0254, /* IO_ACX_EEPROM_ADDR */ + 0x0258, /* IO_ACX_EEPROM_DATA */ + 0x025c, /* IO_ACX_EEPROM_CFG */ + + 0x0268, /* IO_ACX_PHY_ADDR */ + 0x026c, /* IO_ACX_PHY_DATA */ + 0x0270, /* IO_ACX_PHY_CTL */ + + 0x0290, /* IO_ACX_GPIO_OE */ + + 0x0298, /* IO_ACX_GPIO_OUT */ + + 0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */ + 0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */ + 0x02ac, /* IO_ACX_EEPROM_INFORMATION */ + + 0x02d0, /* IO_ACX_EE_START */ + 0x02d4, /* IO_ACX_SOR_CFG */ + 0x02d8 /* IO_ACX_ECPU_CTRL */ +}; + +static const u16 +IO_ACX111[] = +{ + 0x0000, /* IO_ACX_SOFT_RESET */ + + 0x0014, /* IO_ACX_SLV_MEM_ADDR */ + 0x0018, /* IO_ACX_SLV_MEM_DATA */ + 0x001c, /* IO_ACX_SLV_MEM_CTL */ + 0x0020, /* IO_ACX_SLV_END_CTL */ + + 0x0034, /* IO_ACX_FEMR */ + + 0x00b4, /* IO_ACX_INT_TRIG */ + 0x00d4, /* IO_ACX_IRQ_MASK */ + /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */ + 0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */ + 0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */ + 0x00e8, /* IO_ACX_IRQ_ACK */ + 0x00ec, /* IO_ACX_HINT_TRIG */ + + 0x01d0, /* IO_ACX_ENABLE */ + + 0x0338, /* IO_ACX_EEPROM_CTL */ + 0x033c, /* IO_ACX_EEPROM_ADDR */ + 0x0340, /* IO_ACX_EEPROM_DATA */ + 0x0344, /* IO_ACX_EEPROM_CFG */ + + 0x0350, /* IO_ACX_PHY_ADDR */ + 0x0354, /* IO_ACX_PHY_DATA */ + 0x0358, /* IO_ACX_PHY_CTL */ + + 0x0374, /* IO_ACX_GPIO_OE */ + + 0x037c, /* IO_ACX_GPIO_OUT */ + + 0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */ + 0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */ + 0x0390, /* IO_ACX_EEPROM_INFORMATION */ + + 0x0100, /* IO_ACX_EE_START */ + 0x0104, /* IO_ACX_SOR_CFG */ + 0x0108, /* IO_ACX_ECPU_CTRL */ +}; + +static void +dummy_netdev_init(struct net_device *ndev) {} + +static int __devinit +acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + acx111_ie_configoption_t co; + unsigned long mem_region1 = 0; + unsigned long mem_region2 = 0; + unsigned long mem_region1_size; + unsigned long mem_region2_size; + unsigned long phymem1; + unsigned long phymem2; + void *mem1 = NULL; + void *mem2 = NULL; + acx_device_t *adev = NULL; + struct net_device *ndev = NULL; + const char *chip_name; + int result = -EIO; + int err; + u8 chip_type; + + FN_ENTER; + + /* Enable the PCI device */ + if (pci_enable_device(pdev)) { + printk("acx: pci_enable_device() FAILED\n"); + result = -ENODEV; + goto fail_pci_enable_device; + } + + /* enable busmastering (required for CardBus) */ + pci_set_master(pdev); + + /* FIXME: prism54 calls pci_set_mwi() here, + * should we do/support the same? */ + + /* chiptype is u8 but id->driver_data is ulong + ** Works for now (possible values are 1 and 2) */ + chip_type = (u8)id->driver_data; + /* acx100 and acx111 have different PCI memory regions */ + if (chip_type == CHIPTYPE_ACX100) { + chip_name = "ACX100"; + mem_region1 = PCI_ACX100_REGION1; + mem_region1_size = PCI_ACX100_REGION1_SIZE; + + mem_region2 = PCI_ACX100_REGION2; + mem_region2_size = PCI_ACX100_REGION2_SIZE; + } else if (chip_type == CHIPTYPE_ACX111) { + chip_name = "ACX111"; + mem_region1 = PCI_ACX111_REGION1; + mem_region1_size = PCI_ACX111_REGION1_SIZE; + + mem_region2 = PCI_ACX111_REGION2; + mem_region2_size = PCI_ACX111_REGION2_SIZE; + } else { + printk("acx: unknown chip type 0x%04X\n", chip_type); + goto fail_unknown_chiptype; + } + + /* Figure out our resources */ + phymem1 = pci_resource_start(pdev, mem_region1); + phymem2 = pci_resource_start(pdev, mem_region2); + if (!request_mem_region(phymem1, pci_resource_len(pdev, mem_region1), "acx_1")) { + printk("acx: cannot reserve PCI memory region 1 (are you sure " + "you have CardBus support in kernel?)\n"); + goto fail_request_mem_region1; + } + if (!request_mem_region(phymem2, pci_resource_len(pdev, mem_region2), "acx_2")) { + printk("acx: cannot reserve PCI memory region 2\n"); + goto fail_request_mem_region2; + } + + /* this used to be ioremap(), but ioremap_nocache() + * is much less risky, right? (and slower?) + * FIXME: we may want to go back to cached variant if it's + * certain that our code really properly handles + * cached operation (memory barriers, volatile?, ...) + * (but always keep this comment here regardless!) + * Possibly make this a driver config setting? */ + + mem1 = ioremap(phymem1, mem_region1_size); + if (!mem1) { + printk("acx: ioremap() FAILED\n"); + goto fail_ioremap1; + } + mem2 = ioremap(phymem2, mem_region2_size); + if (!mem2) { + printk("acx: ioremap() #2 FAILED\n"); + goto fail_ioremap2; + } + + printk("acx: found %s-based wireless network card at %s, irq:%d, " + "phymem1:0x%lX, phymem2:0x%lX, mem1:0x%p, mem1_size:%ld, " + "mem2:0x%p, mem2_size:%ld\n", + chip_name, pci_name(pdev), pdev->irq, phymem1, phymem2, + mem1, mem_region1_size, + mem2, mem_region2_size); + log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug); + + if (0 == pdev->irq) { + printk("acx: can't use IRQ 0\n"); + goto fail_irq; + } + + ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init); + /* (NB: memsets to 0 entire area) */ + if (!ndev) { + printk("acx: no memory for netdevice struct\n"); + goto fail_alloc_netdev; + } + + ether_setup(ndev); + ndev->open = &acxpci_e_open; + ndev->stop = &acxpci_e_close; + ndev->hard_start_xmit = &acx_i_start_xmit; + ndev->get_stats = &acx_e_get_stats; +#if IW_HANDLER_VERSION <= 5 + ndev->get_wireless_stats = &acx_e_get_wireless_stats; +#endif + ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def; + ndev->set_multicast_list = &acxpci_i_set_multicast_list; + ndev->tx_timeout = &acxpci_i_tx_timeout; + ndev->change_mtu = &acx_e_change_mtu; + ndev->watchdog_timeo = 4 * HZ; + ndev->irq = pdev->irq; + ndev->base_addr = pci_resource_start(pdev, 0); + + adev = ndev2adev(ndev); + spin_lock_init(&adev->lock); /* initial state: unlocked */ + /* We do not start with downed sem: we want PARANOID_LOCKING to work */ + sema_init(&adev->sem, 1); /* initial state: 1 (upped) */ + /* since nobody can see new netdev yet, we can as well + ** just _presume_ that we're under sem (instead of actually taking it): */ + /* acx_sem_lock(adev); */ + adev->pdev = pdev; + adev->ndev = ndev; + adev->dev_type = DEVTYPE_PCI; + adev->chip_type = chip_type; + adev->chip_name = chip_name; + adev->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111; + adev->membase = phymem1; + adev->iobase = mem1; + adev->membase2 = phymem2; + adev->iobase2 = mem2; + /* to find crashes due to weird driver access + * to unconfigured interface (ifup) */ + adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead; + +#ifdef NONESSENTIAL_FEATURES + acx_show_card_eeprom_id(adev); +#endif /* NONESSENTIAL_FEATURES */ + +#ifdef SET_MODULE_OWNER + SET_MODULE_OWNER(ndev); +#endif + SET_NETDEV_DEV(ndev, &pdev->dev); + + log(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq); + + /* need to be able to restore PCI state after a suspend */ + pci_save_state(pdev); + pci_set_drvdata(pdev, ndev); + + /* ok, pci setup is finished, now start initializing the card */ + + /* NB: read_reg() reads may return bogus data before reset_dev(), + * since the firmware which directly controls large parts of the I/O + * registers isn't initialized yet. + * acx100 seems to be more affected than acx111 */ + if (OK != acxpci_s_reset_dev(adev)) + goto fail_reset; + + if (IS_ACX100(adev)) { + /* ACX100: configopt struct in cmd mailbox - directly after reset */ + memcpy_fromio(&co, adev->cmd_area, sizeof(co)); + } + + if (OK != acx_s_init_mac(adev)) + goto fail_init_mac; + + if (IS_ACX111(adev)) { + /* ACX111: configopt struct needs to be queried after full init */ + acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS); + } + +/* TODO: merge them into one function, they are called just once and are the same for pci & usb */ + if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version)) + goto fail_read_eeprom_version; + + acx_s_parse_configoption(adev, &co); + acx_s_set_defaults(adev); + acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */ + acx_display_hardware_details(adev); + + /* Register the card, AFTER everything else has been set up, + * since otherwise an ioctl could step on our feet due to + * firmware operations happening in parallel or uninitialized data */ + err = register_netdev(ndev); + if (OK != err) { + printk("acx: register_netdev() FAILED: %d\n", err); + goto fail_register_netdev; + } + + acx_proc_register_entries(ndev); + + /* Now we have our device, so make sure the kernel doesn't try + * to send packets even though we're not associated to a network yet */ + acx_stop_queue(ndev, "on probe"); + acx_carrier_off(ndev, "on probe"); + + /* after register_netdev() userspace may start working with dev + * (in particular, on other CPUs), we only need to up the sem */ + /* acx_sem_unlock(adev); */ + + printk("acx "ACX_RELEASE": net device %s, driver compiled " + "against wireless extensions %d and Linux %s\n", + ndev->name, WIRELESS_EXT, UTS_RELEASE); + +#if CMD_DISCOVERY + great_inquisitor(adev); +#endif + + result = OK; + goto done; + + /* error paths: undo everything in reverse order... */ + +fail_register_netdev: + + acxpci_s_delete_dma_regions(adev); + pci_set_drvdata(pdev, NULL); + +fail_init_mac: +fail_read_eeprom_version: +fail_reset: + + free_netdev(ndev); +fail_alloc_netdev: +fail_irq: + + iounmap(mem2); +fail_ioremap2: + + iounmap(mem1); +fail_ioremap1: + + release_mem_region(pci_resource_start(pdev, mem_region2), + pci_resource_len(pdev, mem_region2)); +fail_request_mem_region2: + + release_mem_region(pci_resource_start(pdev, mem_region1), + pci_resource_len(pdev, mem_region1)); +fail_request_mem_region1: +fail_unknown_chiptype: + + pci_disable_device(pdev); +fail_pci_enable_device: + + pci_set_power_state(pdev, PCI_D3hot); + +done: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acxpci_e_remove +** +** Shut device down (if not hot unplugged) +** and deallocate PCI resources for the acx chip. +** +** pdev - ptr to PCI device structure containing info about pci configuration +*/ +static void __devexit +acxpci_e_remove(struct pci_dev *pdev) +{ + struct net_device *ndev; + acx_device_t *adev; + unsigned long mem_region1, mem_region2; + unsigned long flags; + + FN_ENTER; + + ndev = (struct net_device*) pci_get_drvdata(pdev); + if (!ndev) { + log(L_DEBUG, "%s: card is unused. Skipping any release code\n", + __func__); + goto end; + } + + adev = ndev2adev(ndev); + + /* If device wasn't hot unplugged... */ + if (adev_present(adev)) { + + acx_sem_lock(adev); + + /* disable both Tx and Rx to shut radio down properly */ + acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0); + acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0); + +#ifdef REDUNDANT + /* put the eCPU to sleep to save power + * Halting is not possible currently, + * since not supported by all firmware versions */ + acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0); +#endif + acx_lock(adev, flags); + /* disable power LED to save power :-) */ + log(L_INIT, "switching off power LED to save power\n"); + acxpci_l_power_led(adev, 0); + /* stop our eCPU */ + if (IS_ACX111(adev)) { + /* FIXME: does this actually keep halting the eCPU? + * I don't think so... + */ + acxpci_l_reset_mac(adev); + } else { + u16 temp; + /* halt eCPU */ + temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1; + write_reg16(adev, IO_ACX_ECPU_CTRL, temp); + write_flush(adev); + } + acx_unlock(adev, flags); + + acx_sem_unlock(adev); + } + + /* unregister the device to not let the kernel + * (e.g. ioctls) access a half-deconfigured device + * NB: this will cause acxpci_e_close() to be called, + * thus we shouldn't call it under sem! */ + log(L_INIT, "removing device %s\n", ndev->name); + unregister_netdev(ndev); + + /* unregister_netdev ensures that no references to us left. + * For paranoid reasons we continue to follow the rules */ + acx_sem_lock(adev); + + if (adev->dev_state_mask & ACX_STATE_IFACE_UP) { + acxpci_s_down(ndev); + CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP); + } + + acx_proc_unregister_entries(ndev); + + if (IS_ACX100(adev)) { + mem_region1 = PCI_ACX100_REGION1; + mem_region2 = PCI_ACX100_REGION2; + } else { + mem_region1 = PCI_ACX111_REGION1; + mem_region2 = PCI_ACX111_REGION2; + } + + /* finally, clean up PCI bus state */ + acxpci_s_delete_dma_regions(adev); + if (adev->iobase) iounmap(adev->iobase); + if (adev->iobase2) iounmap(adev->iobase2); + release_mem_region(pci_resource_start(pdev, mem_region1), + pci_resource_len(pdev, mem_region1)); + release_mem_region(pci_resource_start(pdev, mem_region2), + pci_resource_len(pdev, mem_region2)); + pci_disable_device(pdev); + + /* remove dev registration */ + pci_set_drvdata(pdev, NULL); + + acx_sem_unlock(adev); + + /* Free netdev (quite late, + * since otherwise we might get caught off-guard + * by a netdev timeout handler execution + * expecting to see a working dev...) */ + free_netdev(ndev); + + /* put device into ACPI D3 mode (shutdown) */ + pci_set_power_state(pdev, PCI_D3hot); + +end: + FN_EXIT0; +} + + +/*********************************************************************** +** TODO: PM code needs to be fixed / debugged / tested. +*/ +#ifdef CONFIG_PM +static int +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) +acxpci_e_suspend(struct pci_dev *pdev, pm_message_t state) +#else +acxpci_e_suspend(struct pci_dev *pdev, u32 state) +#endif +{ + struct net_device *ndev = pci_get_drvdata(pdev); + acx_device_t *adev; + + FN_ENTER; + printk("acx: suspend handler is experimental!\n"); + printk("sus: dev %p\n", ndev); + + if (!netif_running(ndev)) + goto end; + + adev = ndev2adev(ndev); + printk("sus: adev %p\n", adev); + + acx_sem_lock(adev); + + netif_device_detach(ndev); /* this one cannot sleep */ + acxpci_s_down(ndev); + /* down() does not set it to 0xffff, but here we really want that */ + write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff); + write_reg16(adev, IO_ACX_FEMR, 0x0); + acxpci_s_delete_dma_regions(adev); + pci_save_state(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + acx_sem_unlock(adev); +end: + FN_EXIT0; + return OK; +} + + +static int +acxpci_e_resume(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + acx_device_t *adev; + + FN_ENTER; + + printk("acx: resume handler is experimental!\n"); + printk("rsm: got dev %p\n", ndev); + + if (!netif_running(ndev)) + goto end; + + adev = ndev2adev(ndev); + printk("rsm: got adev %p\n", adev); + + acx_sem_lock(adev); + + pci_set_power_state(pdev, PCI_D0); + printk("rsm: power state PCI_D0 set\n"); + pci_restore_state(pdev); + printk("rsm: PCI state restored\n"); + + if (OK != acxpci_s_reset_dev(adev)) + goto end_unlock; + printk("rsm: device reset done\n"); + if (OK != acx_s_init_mac(adev)) + goto end_unlock; + printk("rsm: init MAC done\n"); + + acxpci_s_up(ndev); + printk("rsm: acx up done\n"); + + /* now even reload all card parameters as they were before suspend, + * and possibly be back in the network again already :-) */ + if (ACX_STATE_IFACE_UP & adev->dev_state_mask) { + adev->set_mask = GETSET_ALL; + acx_s_update_card_settings(adev); + printk("rsm: settings updated\n"); + } + netif_device_attach(ndev); + printk("rsm: device attached\n"); + +end_unlock: + acx_sem_unlock(adev); +end: + /* we need to return OK here anyway, right? */ + FN_EXIT0; + return OK; +} +#endif /* CONFIG_PM */ + + +/*********************************************************************** +** acxpci_s_up +** +** This function is called by acxpci_e_open (when ifconfig sets the device as up) +** +** Side effects: +** - Enables on-card interrupt requests +** - calls acx_s_start +*/ + +static void +enable_acx_irq(acx_device_t *adev) +{ + FN_ENTER; + write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask); + write_reg16(adev, IO_ACX_FEMR, 0x8000); + adev->irqs_active = 1; + FN_EXIT0; +} + +static void +acxpci_s_up(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + + FN_ENTER; + + acx_lock(adev, flags); + enable_acx_irq(adev); + acx_unlock(adev, flags); + + /* acx fw < 1.9.3.e has a hardware timer, and older drivers + ** used to use it. But we don't do that anymore, our OS + ** has reliable software timers */ + init_timer(&adev->mgmt_timer); + adev->mgmt_timer.function = acx_i_timer; + adev->mgmt_timer.data = (unsigned long)adev; + + /* Need to set ACX_STATE_IFACE_UP first, or else + ** timer won't be started by acx_set_status() */ + SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP); + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_2_STA: + /* actual scan cmd will happen in start() */ + acx_set_status(adev, ACX_STATUS_1_SCANNING); break; + case ACX_MODE_3_AP: + case ACX_MODE_MONITOR: + acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); break; + } + + acx_s_start(adev); + + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_s_down +** +** NB: device may be already hot unplugged if called from acxpci_e_remove() +** +** Disables on-card interrupt request, stops softirq and timer, stops queue, +** sets status == STOPPED +*/ + +static void +disable_acx_irq(acx_device_t *adev) +{ + FN_ENTER; + + /* I guess mask is not 0xffff because acx100 won't signal + ** cmd completion then (needed for ifup). + ** Someone with acx100 please confirm */ + write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask_off); + write_reg16(adev, IO_ACX_FEMR, 0x0); + adev->irqs_active = 0; + FN_EXIT0; +} + +static void +acxpci_s_down(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + + FN_ENTER; + + /* Disable IRQs first, so that IRQs cannot race with us */ + /* then wait until interrupts have finished executing on other CPUs */ + acx_lock(adev, flags); + disable_acx_irq(adev); + synchronize_irq(adev->pdev->irq); + acx_unlock(adev, flags); + + /* we really don't want to have an asynchronous tasklet disturb us + ** after something vital for its job has been shut down, so + ** end all remaining work now. + ** + ** NB: carrier_off (done by set_status below) would lead to + ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK(). + ** That's why we do FLUSH first. + ** + ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK() + ** waits for acx_e_after_interrupt_task to complete if it is running + ** on another CPU, but acx_e_after_interrupt_task + ** will sleep on sem forever, because it is taken by us! + ** Work around that by temporary sem unlock. + ** This will fail miserably if we'll be hit by concurrent + ** iwconfig or something in between. TODO! */ + acx_sem_unlock(adev); + FLUSH_SCHEDULED_WORK(); + acx_sem_lock(adev); + + /* This is possible: + ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task -> + ** -> set_status(ASSOCIATED) -> wake_queue() + ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK + ** lock/unlock is just paranoia, maybe not needed */ + acx_lock(adev, flags); + acx_stop_queue(ndev, "on ifdown"); + acx_set_status(adev, ACX_STATUS_0_STOPPED); + acx_unlock(adev, flags); + + /* kernel/timer.c says it's illegal to del_timer_sync() + ** a timer which restarts itself. We guarantee this cannot + ** ever happen because acx_i_timer() never does this if + ** status is ACX_STATUS_0_STOPPED */ + del_timer_sync(&adev->mgmt_timer); + + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_e_open +** +** Called as a result of SIOCSIFFLAGS ioctl changing the flags bit IFF_UP +** from clear to set. In other words: ifconfig up. +** +** Returns: +** 0 success +** >0 f/w reported error +** <0 driver reported error +*/ +static int +acxpci_e_open(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + int result = OK; + + FN_ENTER; + + acx_sem_lock(adev); + + acx_init_task_scheduler(adev); + +/* TODO: pci_set_power_state(pdev, PCI_D0); ? */ + + /* request shared IRQ handler */ + if (request_irq(ndev->irq, acxpci_i_interrupt, IRQF_SHARED, ndev->name, ndev)) { + printk("%s: request_irq FAILED\n", ndev->name); + result = -EAGAIN; + goto done; + } + log(L_DEBUG|L_IRQ, "request_irq %d successful\n", ndev->irq); + + /* ifup device */ + acxpci_s_up(ndev); + + /* We don't currently have to do anything else. + * The setup of the MAC should be subsequently completed via + * the mlme commands. + * Higher layers know we're ready from dev->start==1 and + * dev->tbusy==0. Our rx path knows to pass up received/ + * frames because of dev->flags&IFF_UP is true. + */ +done: + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acxpci_e_close +** +** Called as a result of SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP +** from set to clear. I.e. called by "ifconfig DEV down" +** +** Returns: +** 0 success +** >0 f/w reported error +** <0 driver reported error +*/ +static int +acxpci_e_close(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + + FN_ENTER; + + acx_sem_lock(adev); + + /* ifdown device */ + CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP); + if (netif_device_present(ndev)) { + acxpci_s_down(ndev); + } + + /* disable all IRQs, release shared IRQ handler */ + write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff); + write_reg16(adev, IO_ACX_FEMR, 0x0); + free_irq(ndev->irq, ndev); + +/* TODO: pci_set_power_state(pdev, PCI_D3hot); ? */ + + /* We currently don't have to do anything else. + * Higher layers know we're not ready from dev->start==0 and + * dev->tbusy==1. Our rx path knows to not pass up received + * frames because of dev->flags&IFF_UP is false. + */ + acx_sem_unlock(adev); + + log(L_INIT, "closed device\n"); + FN_EXIT0; + return OK; +} + + +/*********************************************************************** +** acxpci_i_tx_timeout +** +** Called from network core. Must not sleep! +*/ +static void +acxpci_i_tx_timeout(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + unsigned int tx_num_cleaned; + + FN_ENTER; + + acx_lock(adev, flags); + + /* clean processed tx descs, they may have been completely full */ + tx_num_cleaned = acxpci_l_clean_txdesc(adev); + + /* nothing cleaned, yet (almost) no free buffers available? + * --> clean all tx descs, no matter which status!! + * Note that I strongly suspect that doing emergency cleaning + * may confuse the firmware. This is a last ditch effort to get + * ANYTHING to work again... + * + * TODO: it's best to simply reset & reinit hw from scratch... + */ + if ((adev->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) { + printk("%s: FAILED to free any of the many full tx buffers. " + "Switching to emergency freeing. " + "Please report!\n", ndev->name); + acxpci_l_clean_txdesc_emergency(adev); + } + + if (acx_queue_stopped(ndev) && (ACX_STATUS_4_ASSOCIATED == adev->status)) + acx_wake_queue(ndev, "after tx timeout"); + + /* stall may have happened due to radio drift, so recalib radio */ + acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB); + + /* do unimportant work last */ + printk("%s: tx timeout!\n", ndev->name); + adev->stats.tx_errors++; + + acx_unlock(adev, flags); + + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_i_set_multicast_list +** FIXME: most likely needs refinement +*/ +static void +acxpci_i_set_multicast_list(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + + FN_ENTER; + + acx_lock(adev, flags); + + /* firmwares don't have allmulti capability, + * so just use promiscuous mode instead in this case. */ + if (ndev->flags & (IFF_PROMISC|IFF_ALLMULTI)) { + SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS); + CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI); + SET_BIT(adev->set_mask, SET_RXCONFIG); + /* let kernel know in case *we* needed to set promiscuous */ + ndev->flags |= (IFF_PROMISC|IFF_ALLMULTI); + } else { + CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS); + SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI); + SET_BIT(adev->set_mask, SET_RXCONFIG); + ndev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI); + } + + /* cannot update card settings directly here, atomic context */ + acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG); + + acx_unlock(adev, flags); + + FN_EXIT0; +} + + +/*************************************************************** +** acxpci_l_process_rxdesc +** +** Called directly and only from the IRQ handler +*/ + +#if !ACX_DEBUG +static inline void log_rxbuffer(const acx_device_t *adev) {} +#else +static void +log_rxbuffer(const acx_device_t *adev) +{ + register const struct rxhostdesc *rxhostdesc; + int i; + /* no FN_ENTER here, we don't want that */ + + rxhostdesc = adev->rxhostdesc_start; + if (unlikely(!rxhostdesc)) return; + for (i = 0; i < RX_CNT; i++) { + if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN)) + && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) + printk("rx: buf %d full\n", i); + rxhostdesc++; + } +} +#endif + +static void +acxpci_l_process_rxdesc(acx_device_t *adev) +{ + register rxhostdesc_t *hostdesc; + unsigned count, tail; + + FN_ENTER; + + if (unlikely(acx_debug & L_BUFR)) + log_rxbuffer(adev); + + /* First, have a loop to determine the first descriptor that's + * full, just in case there's a mismatch between our current + * rx_tail and the full descriptor we're supposed to handle. */ + tail = adev->rx_tail; + count = RX_CNT; + while (1) { + hostdesc = &adev->rxhostdesc_start[tail]; + /* advance tail regardless of outcome of the below test */ + tail = (tail + 1) % RX_CNT; + + if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN)) + && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) + break; /* found it! */ + + if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */ + goto end; + } + + /* now process descriptors, starting with the first we figured out */ + while (1) { + log(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n", + tail, hostdesc->Ctl_16, hostdesc->Status); + + acx_l_process_rxbuf(adev, hostdesc->data); + + hostdesc->Status = 0; + /* flush all writes before adapter sees CTL_HOSTOWN change */ + wmb(); + /* Host no longer owns this, needs to be LAST */ + CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN)); + + /* ok, descriptor is handled, now check the next descriptor */ + hostdesc = &adev->rxhostdesc_start[tail]; + + /* if next descriptor is empty, then bail out */ + if (!(hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN)) + || !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) + break; + + tail = (tail + 1) % RX_CNT; + } +end: + adev->rx_tail = tail; + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_i_interrupt +** +** IRQ handler (atomic context, must not sleep, blah, blah) +*/ + +/* scan is complete. all frames now on the receive queue are valid */ +#define INFO_SCAN_COMPLETE 0x0001 +#define INFO_WEP_KEY_NOT_FOUND 0x0002 +/* hw has been reset as the result of a watchdog timer timeout */ +#define INFO_WATCH_DOG_RESET 0x0003 +/* failed to send out NULL frame from PS mode notification to AP */ +/* recommended action: try entering 802.11 PS mode again */ +#define INFO_PS_FAIL 0x0004 +/* encryption/decryption process on a packet failed */ +#define INFO_IV_ICV_FAILURE 0x0005 + +/* Info mailbox format: +2 bytes: type +2 bytes: status +more bytes may follow + rumors say about status: + 0x0000 info available (set by hw) + 0x0001 information received (must be set by host) + 0x1000 info available, mailbox overflowed (messages lost) (set by hw) + but in practice we've seen: + 0x9000 when we did not set status to 0x0001 on prev message + 0x1001 when we did set it + 0x0000 was never seen + conclusion: this is really a bitfield: + 0x1000 is 'info available' bit + 'mailbox overflowed' bit is 0x8000, not 0x1000 + value of 0x0000 probably means that there are no messages at all + P.S. I dunno how in hell hw is supposed to notice that messages are lost - + it does NOT clear bit 0x0001, and this bit will probably stay forever set + after we set it once. Let's hope this will be fixed in firmware someday +*/ + +static void +handle_info_irq(acx_device_t *adev) +{ +#if ACX_DEBUG + static const char * const info_type_msg[] = { + "(unknown)", + "scan complete", + "WEP key not found", + "internal watchdog reset was done", + "failed to send powersave (NULL frame) notification to AP", + "encrypt/decrypt on a packet has failed", + "TKIP tx keys disabled", + "TKIP rx keys disabled", + "TKIP rx: key ID not found", + "???", + "???", + "???", + "???", + "???", + "???", + "???", + "TKIP IV value exceeds thresh" + }; +#endif + u32 info_type, info_status; + + info_type = readl(adev->info_area); + info_status = (info_type >> 16); + info_type = (u16)info_type; + + /* inform fw that we have read this info message */ + writel(info_type | 0x00010000, adev->info_area); + write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK); + write_flush(adev); + + log(L_CTL, "info_type:%04X info_status:%04X\n", + info_type, info_status); + + log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n", + info_status, info_type, + info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ? + 0 : info_type] + ); +} + + +static void +log_unusual_irq(u16 irqtype) { + /* + if (!printk_ratelimit()) + return; + */ + + printk("acx: got"); + if (irqtype & HOST_INT_RX_DATA) { + printk(" Rx_Data"); + } + /* HOST_INT_TX_COMPLETE */ + if (irqtype & HOST_INT_TX_XFER) { + printk(" Tx_Xfer"); + } + /* HOST_INT_RX_COMPLETE */ + if (irqtype & HOST_INT_DTIM) { + printk(" DTIM"); + } + if (irqtype & HOST_INT_BEACON) { + printk(" Beacon"); + } + if (irqtype & HOST_INT_TIMER) { + log(L_IRQ, " Timer"); + } + if (irqtype & HOST_INT_KEY_NOT_FOUND) { + printk(" Key_Not_Found"); + } + if (irqtype & HOST_INT_IV_ICV_FAILURE) { + printk(" IV_ICV_Failure (crypto)"); + } + /* HOST_INT_CMD_COMPLETE */ + /* HOST_INT_INFO */ + if (irqtype & HOST_INT_OVERFLOW) { + printk(" Overflow"); + } + if (irqtype & HOST_INT_PROCESS_ERROR) { + printk(" Process_Error"); + } + /* HOST_INT_SCAN_COMPLETE */ + if (irqtype & HOST_INT_FCS_THRESHOLD) { + printk(" FCS_Threshold"); + } + if (irqtype & HOST_INT_UNKNOWN) { + printk(" Unknown"); + } + printk(" IRQ(s)\n"); +} + + +static void +update_link_quality_led(acx_device_t *adev) +{ + int qual; + + qual = acx_signal_determine_quality(adev->wstats.qual.level, adev->wstats.qual.noise); + if (qual > adev->brange_max_quality) + qual = adev->brange_max_quality; + + if (time_after(jiffies, adev->brange_time_last_state_change + + (HZ/2 - HZ/2 * (unsigned long)qual / adev->brange_max_quality ) )) { + acxpci_l_power_led(adev, (adev->brange_last_state == 0)); + adev->brange_last_state ^= 1; /* toggle */ + adev->brange_time_last_state_change = jiffies; + } +} + + +#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* a la orinoco.c */ + +static irqreturn_t +acxpci_i_interrupt(int irq, void *dev_id) +{ + acx_device_t *adev; + unsigned long flags; + unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY; + register u16 irqtype; + u16 unmasked; + + adev = ndev2adev((struct net_device*)dev_id); + + /* LOCKING: can just spin_lock() since IRQs are disabled anyway. + * I am paranoid */ + acx_lock(adev, flags); + + unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR); + if (unlikely(0xffff == unmasked)) { + /* 0xffff value hints at missing hardware, + * so don't do anything. + * Not very clean, but other drivers do the same... */ + log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n"); + goto none; + } + + /* We will check only "interesting" IRQ types */ + irqtype = unmasked & ~adev->irq_mask; + if (!irqtype) { + /* We are on a shared IRQ line and it wasn't our IRQ */ + log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n", + unmasked, adev->irq_mask); + goto none; + } + + /* Done here because IRQ_NONEs taking three lines of log + ** drive me crazy */ + FN_ENTER; + +#define IRQ_ITERATE 1 +#if IRQ_ITERATE +if (jiffies != adev->irq_last_jiffies) { + adev->irq_loops_this_jiffy = 0; + adev->irq_last_jiffies = jiffies; +} + +/* safety condition; we'll normally abort loop below + * in case no IRQ type occurred */ +while (likely(--irqcount)) { +#endif + /* ACK all IRQs ASAP */ + write_reg16(adev, IO_ACX_IRQ_ACK, 0xffff); + + log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n", + unmasked, adev->irq_mask, irqtype); + + /* Handle most important IRQ types first */ + if (irqtype & HOST_INT_RX_COMPLETE) { + log(L_IRQ, "got Rx_Complete IRQ\n"); + acxpci_l_process_rxdesc(adev); + } + if (irqtype & HOST_INT_TX_COMPLETE) { + log(L_IRQ, "got Tx_Complete IRQ\n"); + /* don't clean up on each Tx complete, wait a bit + * unless we're going towards full, in which case + * we do it immediately, too (otherwise we might lockup + * with a full Tx buffer if we go into + * acxpci_l_clean_txdesc() at a time when we won't wakeup + * the net queue in there for some reason...) */ + if (adev->tx_free <= TX_START_CLEAN) { +#if TX_CLEANUP_IN_SOFTIRQ + acx_schedule_task(adev, ACX_AFTER_IRQ_TX_CLEANUP); +#else + acxpci_l_clean_txdesc(adev); +#endif + } + } + + /* Less frequent ones */ + if (irqtype & (0 + | HOST_INT_CMD_COMPLETE + | HOST_INT_INFO + | HOST_INT_SCAN_COMPLETE + )) { + if (irqtype & HOST_INT_CMD_COMPLETE) { + log(L_IRQ, "got Command_Complete IRQ\n"); + /* save the state for the running issue_cmd() */ + SET_BIT(adev->irq_status, HOST_INT_CMD_COMPLETE); + } + if (irqtype & HOST_INT_INFO) { + handle_info_irq(adev); + } + if (irqtype & HOST_INT_SCAN_COMPLETE) { + log(L_IRQ, "got Scan_Complete IRQ\n"); + /* need to do that in process context */ + acx_schedule_task(adev, ACX_AFTER_IRQ_COMPLETE_SCAN); + /* remember that fw is not scanning anymore */ + SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE); + } + } + + /* These we just log, but either they happen rarely + * or we keep them masked out */ + if (irqtype & (0 + | HOST_INT_RX_DATA + /* | HOST_INT_TX_COMPLETE */ + | HOST_INT_TX_XFER + /* | HOST_INT_RX_COMPLETE */ + | HOST_INT_DTIM + | HOST_INT_BEACON + | HOST_INT_TIMER + | HOST_INT_KEY_NOT_FOUND + | HOST_INT_IV_ICV_FAILURE + /* | HOST_INT_CMD_COMPLETE */ + /* | HOST_INT_INFO */ + | HOST_INT_OVERFLOW + | HOST_INT_PROCESS_ERROR + /* | HOST_INT_SCAN_COMPLETE */ + | HOST_INT_FCS_THRESHOLD + | HOST_INT_UNKNOWN + )) { + log_unusual_irq(irqtype); + } + +#if IRQ_ITERATE + unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR); + irqtype = unmasked & ~adev->irq_mask; + /* Bail out if no new IRQ bits or if all are masked out */ + if (!irqtype) + break; + + if (unlikely(++adev->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) { + printk(KERN_ERR "acx: too many interrupts per jiffy!\n"); + /* Looks like card floods us with IRQs! Try to stop that */ + write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff); + /* This will short-circuit all future attempts to handle IRQ. + * We cant do much more... */ + adev->irq_mask = 0; + break; + } +} +#endif + /* Routine to perform blink with range */ + if (unlikely(adev->led_power == 2)) + update_link_quality_led(adev); + +/* handled: */ + /* write_flush(adev); - not needed, last op was read anyway */ + acx_unlock(adev, flags); + FN_EXIT0; + return IRQ_HANDLED; + +none: + acx_unlock(adev, flags); + return IRQ_NONE; +} + + +/*********************************************************************** +** acxpci_l_power_led +*/ +void +acxpci_l_power_led(acx_device_t *adev, int enable) +{ + u16 gpio_pled = IS_ACX111(adev) ? 0x0040 : 0x0800; + + /* A hack. Not moving message rate limiting to adev->xxx + * (it's only a debug message after all) */ + static int rate_limit = 0; + + if (rate_limit++ < 3) + log(L_IOCTL, "Please report in case toggling the power " + "LED doesn't work for your card!\n"); + if (enable) + write_reg16(adev, IO_ACX_GPIO_OUT, + read_reg16(adev, IO_ACX_GPIO_OUT) & ~gpio_pled); + else + write_reg16(adev, IO_ACX_GPIO_OUT, + read_reg16(adev, IO_ACX_GPIO_OUT) | gpio_pled); +} + + +/*********************************************************************** +** Ioctls +*/ + +/*********************************************************************** +*/ +int +acx111pci_ioctl_info( + struct net_device *ndev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ +#if ACX_DEBUG > 1 + acx_device_t *adev = ndev2adev(ndev); + rxdesc_t *rxdesc; + txdesc_t *txdesc; + rxhostdesc_t *rxhostdesc; + txhostdesc_t *txhostdesc; + struct acx111_ie_memoryconfig memconf; + struct acx111_ie_queueconfig queueconf; + unsigned long flags; + int i; + char memmap[0x34]; + char rxconfig[0x8]; + char fcserror[0x8]; + char ratefallback[0x5]; + + if ( !(acx_debug & (L_IOCTL|L_DEBUG)) ) + return OK; + /* using printk() since we checked debug flag already */ + + acx_sem_lock(adev); + + if (!IS_ACX111(adev)) { + printk("acx111-specific function called " + "with non-acx111 chip, aborting\n"); + goto end_ok; + } + + /* get Acx111 Memory Configuration */ + memset(&memconf, 0, sizeof(memconf)); + /* BTW, fails with 12 (Write only) error code. + ** Retained for easy testing of issue_cmd error handling :) */ + acx_s_interrogate(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG); + + /* get Acx111 Queue Configuration */ + memset(&queueconf, 0, sizeof(queueconf)); + acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS); + + /* get Acx111 Memory Map */ + memset(memmap, 0, sizeof(memmap)); + acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP); + + /* get Acx111 Rx Config */ + memset(rxconfig, 0, sizeof(rxconfig)); + acx_s_interrogate(adev, &rxconfig, ACX1xx_IE_RXCONFIG); + + /* get Acx111 fcs error count */ + memset(fcserror, 0, sizeof(fcserror)); + acx_s_interrogate(adev, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT); + + /* get Acx111 rate fallback */ + memset(ratefallback, 0, sizeof(ratefallback)); + acx_s_interrogate(adev, &ratefallback, ACX1xx_IE_RATE_FALLBACK); + + /* force occurrence of a beacon interrupt */ + /* TODO: comment why is this necessary */ + write_reg16(adev, IO_ACX_HINT_TRIG, HOST_INT_BEACON); + + /* dump Acx111 Mem Configuration */ + printk("dump mem config:\n" + "data read: %d, struct size: %d\n" + "Number of stations: %1X\n" + "Memory block size: %1X\n" + "tx/rx memory block allocation: %1X\n" + "count rx: %X / tx: %X queues\n" + "options %1X\n" + "fragmentation %1X\n" + "Rx Queue 1 Count Descriptors: %X\n" + "Rx Queue 1 Host Memory Start: %X\n" + "Tx Queue 1 Count Descriptors: %X\n" + "Tx Queue 1 Attributes: %X\n", + memconf.len, (int) sizeof(memconf), + memconf.no_of_stations, + memconf.memory_block_size, + memconf.tx_rx_memory_block_allocation, + memconf.count_rx_queues, memconf.count_tx_queues, + memconf.options, + memconf.fragmentation, + memconf.rx_queue1_count_descs, + acx2cpu(memconf.rx_queue1_host_rx_start), + memconf.tx_queue1_count_descs, + memconf.tx_queue1_attributes); + + /* dump Acx111 Queue Configuration */ + printk("dump queue head:\n" + "data read: %d, struct size: %d\n" + "tx_memory_block_address (from card): %X\n" + "rx_memory_block_address (from card): %X\n" + "rx1_queue address (from card): %X\n" + "tx1_queue address (from card): %X\n" + "tx1_queue attributes (from card): %X\n", + queueconf.len, (int) sizeof(queueconf), + queueconf.tx_memory_block_address, + queueconf.rx_memory_block_address, + queueconf.rx1_queue_address, + queueconf.tx1_queue_address, + queueconf.tx1_attributes); + + /* dump Acx111 Mem Map */ + printk("dump mem map:\n" + "data read: %d, struct size: %d\n" + "Code start: %X\n" + "Code end: %X\n" + "WEP default key start: %X\n" + "WEP default key end: %X\n" + "STA table start: %X\n" + "STA table end: %X\n" + "Packet template start: %X\n" + "Packet template end: %X\n" + "Queue memory start: %X\n" + "Queue memory end: %X\n" + "Packet memory pool start: %X\n" + "Packet memory pool end: %X\n" + "iobase: %p\n" + "iobase2: %p\n", + *((u16 *)&memmap[0x02]), (int) sizeof(memmap), + *((u32 *)&memmap[0x04]), + *((u32 *)&memmap[0x08]), + *((u32 *)&memmap[0x0C]), + *((u32 *)&memmap[0x10]), + *((u32 *)&memmap[0x14]), + *((u32 *)&memmap[0x18]), + *((u32 *)&memmap[0x1C]), + *((u32 *)&memmap[0x20]), + *((u32 *)&memmap[0x24]), + *((u32 *)&memmap[0x28]), + *((u32 *)&memmap[0x2C]), + *((u32 *)&memmap[0x30]), + adev->iobase, + adev->iobase2); + + /* dump Acx111 Rx Config */ + printk("dump rx config:\n" + "data read: %d, struct size: %d\n" + "rx config: %X\n" + "rx filter config: %X\n", + *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig), + *((u16 *)&rxconfig[0x04]), + *((u16 *)&rxconfig[0x06])); + + /* dump Acx111 fcs error */ + printk("dump fcserror:\n" + "data read: %d, struct size: %d\n" + "fcserrors: %X\n", + *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror), + *((u32 *)&fcserror[0x04])); + + /* dump Acx111 rate fallback */ + printk("dump rate fallback:\n" + "data read: %d, struct size: %d\n" + "ratefallback: %X\n", + *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback), + *((u8 *)&ratefallback[0x04])); + + /* protect against IRQ */ + acx_lock(adev, flags); + + /* dump acx111 internal rx descriptor ring buffer */ + rxdesc = adev->rxdesc_start; + + /* loop over complete receive pool */ + if (rxdesc) for (i = 0; i < RX_CNT; i++) { + printk("\ndump internal rxdesc %d:\n" + "mem pos %p\n" + "next 0x%X\n" + "acx mem pointer (dynamic) 0x%X\n" + "CTL (dynamic) 0x%X\n" + "Rate (dynamic) 0x%X\n" + "RxStatus (dynamic) 0x%X\n" + "Mod/Pre (dynamic) 0x%X\n", + i, + rxdesc, + acx2cpu(rxdesc->pNextDesc), + acx2cpu(rxdesc->ACXMemPtr), + rxdesc->Ctl_8, + rxdesc->rate, + rxdesc->error, + rxdesc->SNR); + rxdesc++; + } + + /* dump host rx descriptor ring buffer */ + + rxhostdesc = adev->rxhostdesc_start; + + /* loop over complete receive pool */ + if (rxhostdesc) for (i = 0; i < RX_CNT; i++) { + printk("\ndump host rxdesc %d:\n" + "mem pos %p\n" + "buffer mem pos 0x%X\n" + "buffer mem offset 0x%X\n" + "CTL 0x%X\n" + "Length 0x%X\n" + "next 0x%X\n" + "Status 0x%X\n", + i, + rxhostdesc, + acx2cpu(rxhostdesc->data_phy), + rxhostdesc->data_offset, + le16_to_cpu(rxhostdesc->Ctl_16), + le16_to_cpu(rxhostdesc->length), + acx2cpu(rxhostdesc->desc_phy_next), + rxhostdesc->Status); + rxhostdesc++; + } + + /* dump acx111 internal tx descriptor ring buffer */ + txdesc = adev->txdesc_start; + + /* loop over complete transmit pool */ + if (txdesc) for (i = 0; i < TX_CNT; i++) { + printk("\ndump internal txdesc %d:\n" + "size 0x%X\n" + "mem pos %p\n" + "next 0x%X\n" + "acx mem pointer (dynamic) 0x%X\n" + "host mem pointer (dynamic) 0x%X\n" + "length (dynamic) 0x%X\n" + "CTL (dynamic) 0x%X\n" + "CTL2 (dynamic) 0x%X\n" + "Status (dynamic) 0x%X\n" + "Rate (dynamic) 0x%X\n", + i, + (int) sizeof(struct txdesc), + txdesc, + acx2cpu(txdesc->pNextDesc), + acx2cpu(txdesc->AcxMemPtr), + acx2cpu(txdesc->HostMemPtr), + le16_to_cpu(txdesc->total_length), + txdesc->Ctl_8, + txdesc->Ctl2_8, txdesc->error, + txdesc->u.r1.rate); + txdesc = advance_txdesc(adev, txdesc, 1); + } + + /* dump host tx descriptor ring buffer */ + + txhostdesc = adev->txhostdesc_start; + + /* loop over complete host send pool */ + if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) { + printk("\ndump host txdesc %d:\n" + "mem pos %p\n" + "buffer mem pos 0x%X\n" + "buffer mem offset 0x%X\n" + "CTL 0x%X\n" + "Length 0x%X\n" + "next 0x%X\n" + "Status 0x%X\n", + i, + txhostdesc, + acx2cpu(txhostdesc->data_phy), + txhostdesc->data_offset, + le16_to_cpu(txhostdesc->Ctl_16), + le16_to_cpu(txhostdesc->length), + acx2cpu(txhostdesc->desc_phy_next), + le32_to_cpu(txhostdesc->Status)); + txhostdesc++; + } + + /* write_reg16(adev, 0xb4, 0x4); */ + + acx_unlock(adev, flags); +end_ok: + + acx_sem_unlock(adev); +#endif /* ACX_DEBUG */ + return OK; +} + + +/*********************************************************************** +*/ +int +acx100pci_ioctl_set_phy_amp_bias( + struct net_device *ndev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + u16 gpio_old; + + if (!IS_ACX100(adev)) { + /* WARNING!!! + * Removing this check *might* damage + * hardware, since we're tweaking GPIOs here after all!!! + * You've been warned... + * WARNING!!! */ + printk("acx: sorry, setting bias level for non-acx100 " + "is not supported yet\n"); + return OK; + } + + if (*extra > 7) { + printk("acx: invalid bias parameter, range is 0-7\n"); + return -EINVAL; + } + + acx_sem_lock(adev); + + /* Need to lock accesses to [IO_ACX_GPIO_OUT]: + * IRQ handler uses it to update LED */ + acx_lock(adev, flags); + gpio_old = read_reg16(adev, IO_ACX_GPIO_OUT); + write_reg16(adev, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8)); + acx_unlock(adev, flags); + + log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old); + printk("%s: PHY power amplifier bias: old:%d, new:%d\n", + ndev->name, + (gpio_old & 0x0700) >> 8, (unsigned char)*extra); + + acx_sem_unlock(adev); + + return OK; +} + + +/*************************************************************** +** acxpci_l_alloc_tx +** Actually returns a txdesc_t* ptr +** +** FIXME: in case of fragments, should allocate multiple descrs +** after figuring out how many we need and whether we still have +** sufficiently many. +*/ +tx_t* +acxpci_l_alloc_tx(acx_device_t *adev) +{ + struct txdesc *txdesc; + unsigned head; + u8 ctl8; + + FN_ENTER; + + if (unlikely(!adev->tx_free)) { + printk("acx: BUG: no free txdesc left\n"); + txdesc = NULL; + goto end; + } + + head = adev->tx_head; + txdesc = get_txdesc(adev, head); + ctl8 = txdesc->Ctl_8; + + /* 2005-10-11: there were several bug reports on this happening + ** but now cause seems to be understood & fixed */ + if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_ACXDONE_HOSTOWN))) { + /* whoops, descr at current index is not free, so probably + * ring buffer already full */ + printk("acx: BUG: tx_head:%d Ctl8:0x%02X - failed to find " + "free txdesc\n", head, ctl8); + txdesc = NULL; + goto end; + } + + /* Needed in case txdesc won't be eventually submitted for tx */ + txdesc->Ctl_8 = DESC_CTL_ACXDONE_HOSTOWN; + + adev->tx_free--; + log(L_BUFT, "tx: got desc %u, %u remain\n", + head, adev->tx_free); + /* Keep a few free descs between head and tail of tx ring. + ** It is not absolutely needed, just feels safer */ + if (adev->tx_free < TX_STOP_QUEUE) { + log(L_BUF, "stop queue (%u tx desc left)\n", + adev->tx_free); + acx_stop_queue(adev->ndev, NULL); + } + + /* returning current descriptor, so advance to next free one */ + adev->tx_head = (head + 1) % TX_CNT; +end: + FN_EXIT0; + + return (tx_t*)txdesc; +} + + +/*********************************************************************** +*/ +void* +acxpci_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque) +{ + return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data; +} + + +/*********************************************************************** +** acxpci_l_tx_data +** +** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx). +** Can be called from acx_i_start_xmit (data frames from net core). +** +** FIXME: in case of fragments, should loop over the number of +** pre-allocated tx descrs, properly setting up transfer data and +** CTL_xxx flags according to fragment number. +*/ +void +acxpci_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len) +{ + txdesc_t *txdesc = (txdesc_t*)tx_opaque; + txhostdesc_t *hostdesc1, *hostdesc2; + client_t *clt; + u16 rate_cur; + u8 Ctl_8, Ctl2_8; + + FN_ENTER; + + /* fw doesn't tx such packets anyhow */ + if (unlikely(len < WLAN_HDR_A3_LEN)) + goto end; + + hostdesc1 = get_txhostdesc(adev, txdesc); + /* modify flag status in separate variable to be able to write it back + * in one big swoop later (also in order to have less device memory + * accesses) */ + Ctl_8 = txdesc->Ctl_8; + Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */ + + hostdesc2 = hostdesc1 + 1; + + /* DON'T simply set Ctl field to 0 here globally, + * it needs to maintain a consistent flag status (those are state flags!!), + * otherwise it may lead to severe disruption. Only set or reset particular + * flags at the exact moment this is needed... */ + + /* let chip do RTS/CTS handshaking before sending + * in case packet size exceeds threshold */ + if (len > adev->rts_threshold) + SET_BIT(Ctl2_8, DESC_CTL2_RTS); + else + CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS); + + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_3_AP: + clt = acx_l_sta_list_get(adev, ((wlan_hdr_t*)hostdesc1->data)->a1); + break; + case ACX_MODE_2_STA: + clt = adev->ap_client; + break; +#if 0 +/* testing was done on acx111: */ + case ACX_MODE_MONITOR: + SET_BIT(Ctl2_8, 0 +/* sends CTS to self before packet */ + + DESC_CTL2_SEQ /* don't increase sequence field */ +/* not working (looks like good fcs is still added) */ + + DESC_CTL2_FCS /* don't add the FCS */ +/* not tested */ + + DESC_CTL2_MORE_FRAG +/* not tested */ + + DESC_CTL2_RETRY /* don't increase retry field */ +/* not tested */ + + DESC_CTL2_POWER /* don't increase power mgmt. field */ +/* no effect */ + + DESC_CTL2_WEP /* encrypt this frame */ +/* not tested */ + + DESC_CTL2_DUR /* don't increase duration field */ + ); + /* fallthrough */ +#endif + default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */ + clt = NULL; + break; + } + + rate_cur = clt ? clt->rate_cur : adev->rate_bcast; + if (unlikely(!rate_cur)) { + printk("acx: driver bug! bad ratemask\n"); + goto end; + } + + /* used in tx cleanup routine for auto rate and accounting: */ + put_txcr(adev, txdesc, clt, rate_cur); + + txdesc->total_length = cpu_to_le16(len); + hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN); + if (IS_ACX111(adev)) { + /* note that if !txdesc->do_auto, txrate->cur + ** has only one nonzero bit */ + txdesc->u.r2.rate111 = cpu_to_le16( + rate_cur + /* WARNING: I was never able to make it work with prism54 AP. + ** It was falling down to 1Mbit where shortpre is not applicable, + ** and not working at all at "5,11 basic rates only" setting. + ** I even didn't see tx packets in radio packet capture. + ** Disabled for now --vda */ + /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */ + ); +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS + /* should add this to rate111 above as necessary */ + | (clt->pbcc511 ? RATE111_PBCC511 : 0) +#endif + hostdesc1->length = cpu_to_le16(len); + } else { /* ACX100 */ + u8 rate_100 = clt ? clt->rate_100 : adev->rate_bcast100; + txdesc->u.r1.rate = rate_100; +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS + if (clt->pbcc511) { + if (n == RATE100_5 || n == RATE100_11) + n |= RATE100_PBCC511; + } + + if (clt->shortpre && (clt->cur != RATE111_1)) + SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */ +#endif + /* set autodma and reclaim and 1st mpdu */ + SET_BIT(Ctl_8, DESC_CTL_AUTODMA | DESC_CTL_RECLAIM | DESC_CTL_FIRSTFRAG); +#if ACX_FRAGMENTATION + /* SET_BIT(Ctl2_8, DESC_CTL2_MORE_FRAG); cannot set it unconditionally, needs to be set for all non-last fragments */ +#endif + hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN); + } + /* don't need to clean ack/rts statistics here, already + * done on descr cleanup */ + + /* clears HOSTOWN and ACXDONE bits, thus telling that the descriptors + * are now owned by the acx100; do this as LAST operation */ + CLEAR_BIT(Ctl_8, DESC_CTL_ACXDONE_HOSTOWN); + /* flush writes before we release hostdesc to the adapter here */ + wmb(); + CLEAR_BIT(hostdesc1->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN)); + CLEAR_BIT(hostdesc2->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN)); + + /* write back modified flags */ + txdesc->Ctl2_8 = Ctl2_8; + txdesc->Ctl_8 = Ctl_8; + /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */ + + /* flush writes before we tell the adapter that it's its turn now */ + mmiowb(); + write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC); + write_flush(adev); + + /* log the packet content AFTER sending it, + * in order to not delay sending any further than absolutely needed + * Do separate logs for acx100/111 to have human-readable rates */ + if (unlikely(acx_debug & (L_XFER|L_DATA))) { + u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc; + if (IS_ACX111(adev)) + printk("tx: pkt (%s): len %d " + "rate %04X%s status %u\n", + acx_get_packet_type_string(le16_to_cpu(fc)), len, + le16_to_cpu(txdesc->u.r2.rate111), + (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "", + adev->status); + else + printk("tx: pkt (%s): len %d rate %03u%s status %u\n", + acx_get_packet_type_string(fc), len, + txdesc->u.r1.rate, + (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "", + adev->status); + + if (acx_debug & L_DATA) { + printk("tx: 802.11 [%d]: ", len); + acx_dump_bytes(hostdesc1->data, len); + } + } +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_l_clean_txdesc +** +** This function resets the txdescs' status when the ACX100 +** signals the TX done IRQ (txdescs have been processed), starting with +** the pool index of the descriptor which we would use next, +** in order to make sure that we can be as fast as possible +** in filling new txdescs. +** Everytime we get called we know where the next packet to be cleaned is. +*/ + +#if !ACX_DEBUG +static inline void log_txbuffer(const acx_device_t *adev) {} +#else +static void +log_txbuffer(acx_device_t *adev) +{ + txdesc_t *txdesc; + int i; + + /* no FN_ENTER here, we don't want that */ + /* no locks here, since it's entirely non-critical code */ + txdesc = adev->txdesc_start; + if (unlikely(!txdesc)) return; + printk("tx: desc->Ctl8's:"); + for (i = 0; i < TX_CNT; i++) { + printk(" %02X", txdesc->Ctl_8); + txdesc = advance_txdesc(adev, txdesc, 1); + } + printk("\n"); +} +#endif + + +static void +handle_tx_error(acx_device_t *adev, u8 error, unsigned int finger) +{ + const char *err = "unknown error"; + + /* hmm, should we handle this as a mask + * of *several* bits? + * For now I think only caring about + * individual bits is ok... */ + switch (error) { + case 0x01: + err = "no Tx due to error in other fragment"; + adev->wstats.discard.fragment++; + break; + case 0x02: + err = "Tx aborted"; + adev->stats.tx_aborted_errors++; + break; + case 0x04: + err = "Tx desc wrong parameters"; + adev->wstats.discard.misc++; + break; + case 0x08: + err = "WEP key not found"; + adev->wstats.discard.misc++; + break; + case 0x10: + err = "MSDU lifetime timeout? - try changing " + "'iwconfig retry lifetime XXX'"; + adev->wstats.discard.misc++; + break; + case 0x20: + err = "excessive Tx retries due to either distance " + "too high or unable to Tx or Tx frame error - " + "try changing 'iwconfig txpower XXX' or " + "'sens'itivity or 'retry'"; + adev->wstats.discard.retries++; + /* Tx error 0x20 also seems to occur on + * overheating, so I'm not sure whether we + * actually want to do aggressive radio recalibration, + * since people maybe won't notice then that their hardware + * is slowly getting cooked... + * Or is it still a safe long distance from utter + * radio non-functionality despite many radio recalibs + * to final destructive overheating of the hardware? + * In this case we really should do recalib here... + * I guess the only way to find out is to do a + * potentially fatal self-experiment :-\ + * Or maybe only recalib in case we're using Tx + * rate auto (on errors switching to lower speed + * --> less heat?) or 802.11 power save mode? + * + * ok, just do it. */ + if (++adev->retry_errors_msg_ratelimit % 4 == 0) { + if (adev->retry_errors_msg_ratelimit <= 20) { + printk("%s: several excessive Tx " + "retry errors occurred, attempting " + "to recalibrate radio. Radio " + "drift might be caused by increasing " + "card temperature, please check the card " + "before it's too late!\n", + adev->ndev->name); + if (adev->retry_errors_msg_ratelimit == 20) + printk("disabling above message\n"); + } + + acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB); + } + break; + case 0x40: + err = "Tx buffer overflow"; + adev->stats.tx_fifo_errors++; + break; + case 0x80: + /* possibly ACPI C-state powersaving related!!! + * (DMA timeout due to excessively high wakeup + * latency after C-state activation!?) + * Disable C-State powersaving and try again, + * then PLEASE REPORT, I'm VERY interested in + * whether my theory is correct that this is + * actually the problem here. + * In that case, use new Linux idle wakeup latency + * requirements kernel API to prevent this issue. */ + err = "DMA error"; + adev->wstats.discard.misc++; + break; + } + adev->stats.tx_errors++; + if (adev->stats.tx_errors <= 20) + printk("%s: tx error 0x%02X, buf %02u! (%s)\n", + adev->ndev->name, error, finger, err); + else + printk("%s: tx error 0x%02X, buf %02u!\n", + adev->ndev->name, error, finger); +} + + +unsigned int +acxpci_l_clean_txdesc(acx_device_t *adev) +{ + txdesc_t *txdesc; + unsigned finger; + int num_cleaned; + u16 r111; + u8 error, ack_failures, rts_failures, rts_ok, r100; + + FN_ENTER; + + if (unlikely(acx_debug & L_DEBUG)) + log_txbuffer(adev); + + log(L_BUFT, "tx: cleaning up bufs from %u\n", adev->tx_tail); + + /* We know first descr which is not free yet. We advance it as far + ** as we see correct bits set in following descs (if next desc + ** is NOT free, we shouldn't advance at all). We know that in + ** front of tx_tail may be "holes" with isolated free descs. + ** We will catch up when all intermediate descs will be freed also */ + + finger = adev->tx_tail; + num_cleaned = 0; + while (likely(finger != adev->tx_head)) { + txdesc = get_txdesc(adev, finger); + + /* If we allocated txdesc on tx path but then decided + ** to NOT use it, then it will be left as a free "bubble" + ** in the "allocated for tx" part of the ring. + ** We may meet it on the next ring pass here. */ + + /* stop if not marked as "tx finished" and "host owned" */ + if ((txdesc->Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN) + != DESC_CTL_ACXDONE_HOSTOWN) { + if (unlikely(!num_cleaned)) { /* maybe remove completely */ + log(L_BUFT, "clean_txdesc: tail isn't free. " + "tail:%d head:%d\n", + adev->tx_tail, adev->tx_head); + } + break; + } + + /* remember desc values... */ + error = txdesc->error; + ack_failures = txdesc->ack_failures; + rts_failures = txdesc->rts_failures; + rts_ok = txdesc->rts_ok; + r100 = txdesc->u.r1.rate; + r111 = le16_to_cpu(txdesc->u.r2.rate111); + + /* need to check for certain error conditions before we + * clean the descriptor: we still need valid descr data here */ + if (unlikely(0x30 & error)) { + /* only send IWEVTXDROP in case of retry or lifetime exceeded; + * all other errors mean we screwed up locally */ + union iwreq_data wrqu; + wlan_hdr_t *hdr; + txhostdesc_t *hostdesc; + + hostdesc = get_txhostdesc(adev, txdesc); + hdr = (wlan_hdr_t *)hostdesc->data; + MAC_COPY(wrqu.addr.sa_data, hdr->a1); + wireless_send_event(adev->ndev, IWEVTXDROP, &wrqu, NULL); + } + + /* ...and free the desc */ + txdesc->error = 0; + txdesc->ack_failures = 0; + txdesc->rts_failures = 0; + txdesc->rts_ok = 0; + /* signal host owning it LAST, since ACX already knows that this + ** descriptor is finished since it set Ctl_8 accordingly. */ + txdesc->Ctl_8 = DESC_CTL_HOSTOWN; + + adev->tx_free++; + num_cleaned++; + + if ((adev->tx_free >= TX_START_QUEUE) + && (adev->status == ACX_STATUS_4_ASSOCIATED) + && (acx_queue_stopped(adev->ndev)) + ) { + log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n", + adev->tx_free); + acx_wake_queue(adev->ndev, NULL); + } + + /* do error checking, rate handling and logging + * AFTER having done the work, it's faster */ + + /* do rate handling */ + if (adev->rate_auto) { + struct client *clt = get_txc(adev, txdesc); + if (clt) { + u16 cur = get_txr(adev, txdesc); + if (clt->rate_cur == cur) { + acx_l_handle_txrate_auto(adev, clt, + cur, /* intended rate */ + r100, r111, /* actually used rate */ + (error & 0x30), /* was there an error? */ + TX_CNT + TX_CLEAN_BACKLOG - adev->tx_free); + } + } + } + + if (unlikely(error)) + handle_tx_error(adev, error, finger); + + if (IS_ACX111(adev)) + log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n", + finger, ack_failures, rts_failures, rts_ok, r111); + else + log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n", + finger, ack_failures, rts_failures, rts_ok, r100); + + /* update pointer for descr to be cleaned next */ + finger = (finger + 1) % TX_CNT; + } + + /* remember last position */ + adev->tx_tail = finger; +/* end: */ + FN_EXIT1(num_cleaned); + return num_cleaned; +} + +/* clean *all* Tx descriptors, and regardless of their previous state. + * Used for brute-force reset handling. */ +void +acxpci_l_clean_txdesc_emergency(acx_device_t *adev) +{ + txdesc_t *txdesc; + int i; + + FN_ENTER; + + for (i = 0; i < TX_CNT; i++) { + txdesc = get_txdesc(adev, i); + + /* free it */ + txdesc->ack_failures = 0; + txdesc->rts_failures = 0; + txdesc->rts_ok = 0; + txdesc->error = 0; + txdesc->Ctl_8 = DESC_CTL_HOSTOWN; + } + + adev->tx_free = TX_CNT; + + FN_EXIT0; +} + + +/*********************************************************************** +** acxpci_s_create_tx_host_desc_queue +*/ + +static void* +allocate(acx_device_t *adev, size_t size, dma_addr_t *phy, const char *msg) +{ + void *ptr; + + ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL, + size, phy, GFP_KERNEL); + + if (ptr) { + log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n", + msg, (int)size, ptr, (unsigned long long)*phy); + memset(ptr, 0, size); + return ptr; + } + printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n", + msg, (int)size); + return NULL; +} + + +static int +acxpci_s_create_tx_host_desc_queue(acx_device_t *adev) +{ + txhostdesc_t *hostdesc; + u8 *txbuf; + dma_addr_t hostdesc_phy; + dma_addr_t txbuf_phy; + int i; + + FN_ENTER; + + /* allocate TX buffer */ + adev->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS; + adev->txbuf_start = allocate(adev, adev->txbuf_area_size, + &adev->txbuf_startphy, "txbuf_start"); + if (!adev->txbuf_start) + goto fail; + + /* allocate the TX host descriptor queue pool */ + adev->txhostdesc_area_size = TX_CNT * 2*sizeof(*hostdesc); + adev->txhostdesc_start = allocate(adev, adev->txhostdesc_area_size, + &adev->txhostdesc_startphy, "txhostdesc_start"); + if (!adev->txhostdesc_start) + goto fail; + /* check for proper alignment of TX host descriptor pool */ + if ((long) adev->txhostdesc_start & 3) { + printk("acx: driver bug: dma alloc returns unaligned address\n"); + goto fail; + } + + hostdesc = adev->txhostdesc_start; + hostdesc_phy = adev->txhostdesc_startphy; + txbuf = adev->txbuf_start; + txbuf_phy = adev->txbuf_startphy; + +#if 0 +/* Each tx buffer is accessed by hardware via +** txdesc -> txhostdesc(s) -> txbuffer(s). +** We use only one txhostdesc per txdesc, but it looks like +** acx111 is buggy: it accesses second txhostdesc +** (via hostdesc.desc_phy_next field) even if +** txdesc->length == hostdesc->length and thus +** entire packet was placed into first txhostdesc. +** Due to this bug acx111 hangs unless second txhostdesc +** has le16_to_cpu(hostdesc.length) = 3 (or larger) +** Storing NULL into hostdesc.desc_phy_next +** doesn't seem to help. +** +** Update: although it worked on Xterasys XN-2522g +** with len=3 trick, WG311v2 is even more bogus, doesn't work. +** Keeping this code (#ifdef'ed out) for documentational purposes. +*/ + for (i = 0; i < TX_CNT*2; i++) { + hostdesc_phy += sizeof(*hostdesc); + if (!(i & 1)) { + hostdesc->data_phy = cpu2acx(txbuf_phy); + /* hostdesc->data_offset = ... */ + /* hostdesc->reserved = ... */ + hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN); + /* hostdesc->length = ... */ + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy); + hostdesc->pNext = ptr2acx(NULL); + /* hostdesc->Status = ... */ + /* below: non-hardware fields */ + hostdesc->data = txbuf; + + txbuf += WLAN_A4FR_MAXLEN_WEP_FCS; + txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS; + } else { + /* hostdesc->data_phy = ... */ + /* hostdesc->data_offset = ... */ + /* hostdesc->reserved = ... */ + /* hostdesc->Ctl_16 = ... */ + hostdesc->length = cpu_to_le16(3); /* bug workaround */ + /* hostdesc->desc_phy_next = ... */ + /* hostdesc->pNext = ... */ + /* hostdesc->Status = ... */ + /* below: non-hardware fields */ + /* hostdesc->data = ... */ + } + hostdesc++; + } +#endif +/* We initialize two hostdescs so that they point to adjacent +** memory areas. Thus txbuf is really just a contiguous memory area */ + for (i = 0; i < TX_CNT*2; i++) { + hostdesc_phy += sizeof(*hostdesc); + + hostdesc->data_phy = cpu2acx(txbuf_phy); + /* done by memset(0): hostdesc->data_offset = 0; */ + /* hostdesc->reserved = ... */ + hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN); + /* hostdesc->length = ... */ + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy); + /* done by memset(0): hostdesc->pNext = ptr2acx(NULL); */ + /* hostdesc->Status = ... */ + /* ->data is a non-hardware field: */ + hostdesc->data = txbuf; + + if (!(i & 1)) { + txbuf += WLAN_HDR_A3_LEN; + txbuf_phy += WLAN_HDR_A3_LEN; + } else { + txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN; + txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN; + } + hostdesc++; + } + hostdesc--; + hostdesc->desc_phy_next = cpu2acx(adev->txhostdesc_startphy); + + FN_EXIT1(OK); + return OK; +fail: + printk("acx: create_tx_host_desc_queue FAILED\n"); + /* dealloc will be done by free function on error case */ + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*************************************************************** +** acxpci_s_create_rx_host_desc_queue +*/ +/* the whole size of a data buffer (header plus data body) + * plus 32 bytes safety offset at the end */ +#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32) + +static int +acxpci_s_create_rx_host_desc_queue(acx_device_t *adev) +{ + rxhostdesc_t *hostdesc; + rxbuffer_t *rxbuf; + dma_addr_t hostdesc_phy; + dma_addr_t rxbuf_phy; + int i; + + FN_ENTER; + + /* allocate the RX host descriptor queue pool */ + adev->rxhostdesc_area_size = RX_CNT * sizeof(*hostdesc); + adev->rxhostdesc_start = allocate(adev, adev->rxhostdesc_area_size, + &adev->rxhostdesc_startphy, "rxhostdesc_start"); + if (!adev->rxhostdesc_start) + goto fail; + /* check for proper alignment of RX host descriptor pool */ + if ((long) adev->rxhostdesc_start & 3) { + printk("acx: driver bug: dma alloc returns unaligned address\n"); + goto fail; + } + + /* allocate Rx buffer pool which will be used by the acx + * to store the whole content of the received frames in it */ + adev->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE; + adev->rxbuf_start = allocate(adev, adev->rxbuf_area_size, + &adev->rxbuf_startphy, "rxbuf_start"); + if (!adev->rxbuf_start) + goto fail; + + rxbuf = adev->rxbuf_start; + rxbuf_phy = adev->rxbuf_startphy; + hostdesc = adev->rxhostdesc_start; + hostdesc_phy = adev->rxhostdesc_startphy; + + /* don't make any popular C programming pointer arithmetic mistakes + * here, otherwise I'll kill you... + * (and don't dare asking me why I'm warning you about that...) */ + for (i = 0; i < RX_CNT; i++) { + hostdesc->data = rxbuf; + hostdesc->data_phy = cpu2acx(rxbuf_phy); + hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE); + CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN)); + rxbuf++; + rxbuf_phy += sizeof(*rxbuf); + hostdesc_phy += sizeof(*hostdesc); + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy); + hostdesc++; + } + hostdesc--; + hostdesc->desc_phy_next = cpu2acx(adev->rxhostdesc_startphy); + FN_EXIT1(OK); + return OK; +fail: + printk("acx: create_rx_host_desc_queue FAILED\n"); + /* dealloc will be done by free function on error case */ + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*************************************************************** +** acxpci_s_create_hostdesc_queues +*/ +int +acxpci_s_create_hostdesc_queues(acx_device_t *adev) +{ + int result; + result = acxpci_s_create_tx_host_desc_queue(adev); + if (OK != result) return result; + result = acxpci_s_create_rx_host_desc_queue(adev); + return result; +} + + +/*************************************************************** +** acxpci_create_tx_desc_queue +*/ +static void +acxpci_create_tx_desc_queue(acx_device_t *adev, u32 tx_queue_start) +{ + txdesc_t *txdesc; + txhostdesc_t *hostdesc; + dma_addr_t hostmemptr; + u32 mem_offs; + int i; + + FN_ENTER; + + if (IS_ACX100(adev)) + adev->txdesc_size = sizeof(*txdesc); + else + /* the acx111 txdesc is 4 bytes larger */ + adev->txdesc_size = sizeof(*txdesc) + 4; + + adev->txdesc_start = (txdesc_t *) (adev->iobase2 + tx_queue_start); + + log(L_DEBUG, "adev->iobase2=%p\n" + "tx_queue_start=%08X\n" + "adev->txdesc_start=%p\n", + adev->iobase2, + tx_queue_start, + adev->txdesc_start); + + adev->tx_free = TX_CNT; + /* done by memset: adev->tx_head = 0; */ + /* done by memset: adev->tx_tail = 0; */ + txdesc = adev->txdesc_start; + mem_offs = tx_queue_start; + hostmemptr = adev->txhostdesc_startphy; + hostdesc = adev->txhostdesc_start; + + if (IS_ACX111(adev)) { + /* ACX111 has a preinitialized Tx buffer! */ + /* loop over whole send pool */ + /* FIXME: do we have to do the hostmemptr stuff here?? */ + for (i = 0; i < TX_CNT; i++) { + txdesc->HostMemPtr = ptr2acx(hostmemptr); + txdesc->Ctl_8 = DESC_CTL_HOSTOWN; + /* reserve two (hdr desc and payload desc) */ + hostdesc += 2; + hostmemptr += 2 * sizeof(*hostdesc); + txdesc = advance_txdesc(adev, txdesc, 1); + } + } else { + /* ACX100 Tx buffer needs to be initialized by us */ + /* clear whole send pool. sizeof is safe here (we are acx100) */ + memset(adev->txdesc_start, 0, TX_CNT * sizeof(*txdesc)); + + /* loop over whole send pool */ + for (i = 0; i < TX_CNT; i++) { + log(L_DEBUG, "configure card tx descriptor: 0x%p, " + "size: 0x%X\n", txdesc, adev->txdesc_size); + + /* pointer to hostdesc memory */ + txdesc->HostMemPtr = ptr2acx(hostmemptr); + /* initialise ctl */ + txdesc->Ctl_8 = ( DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM + | DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG); + /* done by memset(0): txdesc->Ctl2_8 = 0; */ + /* point to next txdesc */ + txdesc->pNextDesc = cpu2acx(mem_offs + adev->txdesc_size); + /* reserve two (hdr desc and payload desc) */ + hostdesc += 2; + hostmemptr += 2 * sizeof(*hostdesc); + /* go to the next one */ + mem_offs += adev->txdesc_size; + /* ++ is safe here (we are acx100) */ + txdesc++; + } + /* go back to the last one */ + txdesc--; + /* and point to the first making it a ring buffer */ + txdesc->pNextDesc = cpu2acx(tx_queue_start); + } + FN_EXIT0; +} + + +/*************************************************************** +** acxpci_create_rx_desc_queue +*/ +static void +acxpci_create_rx_desc_queue(acx_device_t *adev, u32 rx_queue_start) +{ + rxdesc_t *rxdesc; + u32 mem_offs; + int i; + + FN_ENTER; + + /* done by memset: adev->rx_tail = 0; */ + + /* ACX111 doesn't need any further config: preconfigures itself. + * Simply print ring buffer for debugging */ + if (IS_ACX111(adev)) { + /* rxdesc_start already set here */ + + adev->rxdesc_start = (rxdesc_t *) ((u8 *)adev->iobase2 + rx_queue_start); + + rxdesc = adev->rxdesc_start; + for (i = 0; i < RX_CNT; i++) { + log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc); + rxdesc = adev->rxdesc_start = (rxdesc_t *) + (adev->iobase2 + acx2cpu(rxdesc->pNextDesc)); + } + } else { + /* we didn't pre-calculate rxdesc_start in case of ACX100 */ + /* rxdesc_start should be right AFTER Tx pool */ + adev->rxdesc_start = (rxdesc_t *) + ((u8 *) adev->txdesc_start + (TX_CNT * sizeof(txdesc_t))); + /* NB: sizeof(txdesc_t) above is valid because we know + ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere! + ** acx111's txdesc is larger! */ + + memset(adev->rxdesc_start, 0, RX_CNT * sizeof(*rxdesc)); + + /* loop over whole receive pool */ + rxdesc = adev->rxdesc_start; + mem_offs = rx_queue_start; + for (i = 0; i < RX_CNT; i++) { + log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc); + rxdesc->Ctl_8 = DESC_CTL_RECLAIM | DESC_CTL_AUTODMA; + /* point to next rxdesc */ + rxdesc->pNextDesc = cpu2acx(mem_offs + sizeof(*rxdesc)); + /* go to the next one */ + mem_offs += sizeof(*rxdesc); + rxdesc++; + } + /* go to the last one */ + rxdesc--; + + /* and point to the first making it a ring buffer */ + rxdesc->pNextDesc = cpu2acx(rx_queue_start); + } + FN_EXIT0; +} + + +/*************************************************************** +** acxpci_create_desc_queues +*/ +void +acxpci_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start) +{ + acxpci_create_tx_desc_queue(adev, tx_queue_start); + acxpci_create_rx_desc_queue(adev, rx_queue_start); +} + + +/*************************************************************** +** acxpci_s_proc_diag_output +*/ +char* +acxpci_s_proc_diag_output(char *p, acx_device_t *adev) +{ + const char *rtl, *thd, *ttl; + rxhostdesc_t *rxhostdesc; + txdesc_t *txdesc; + int i; + + FN_ENTER; + + p += sprintf(p, "** Rx buf **\n"); + rxhostdesc = adev->rxhostdesc_start; + if (rxhostdesc) for (i = 0; i < RX_CNT; i++) { + rtl = (i == adev->rx_tail) ? " [tail]" : ""; + if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN)) + && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)) ) + p += sprintf(p, "%02u FULL%s\n", i, rtl); + else + p += sprintf(p, "%02u empty%s\n", i, rtl); + rxhostdesc++; + } + p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", adev->tx_free, + acx_queue_stopped(adev->ndev) ? "STOPPED" : "running"); + txdesc = adev->txdesc_start; + if (txdesc) for (i = 0; i < TX_CNT; i++) { + thd = (i == adev->tx_head) ? " [head]" : ""; + ttl = (i == adev->tx_tail) ? " [tail]" : ""; + if (txdesc->Ctl_8 & DESC_CTL_ACXDONE) + p += sprintf(p, "%02u free (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl); + else + p += sprintf(p, "%02u tx (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl); + txdesc = advance_txdesc(adev, txdesc, 1); + } + p += sprintf(p, + "\n" + "** PCI data **\n" + "txbuf_start %p, txbuf_area_size %u, txbuf_startphy %08llx\n" + "txdesc_size %u, txdesc_start %p\n" + "txhostdesc_start %p, txhostdesc_area_size %u, txhostdesc_startphy %08llx\n" + "rxdesc_start %p\n" + "rxhostdesc_start %p, rxhostdesc_area_size %u, rxhostdesc_startphy %08llx\n" + "rxbuf_start %p, rxbuf_area_size %u, rxbuf_startphy %08llx\n", + adev->txbuf_start, adev->txbuf_area_size, + (unsigned long long)adev->txbuf_startphy, + adev->txdesc_size, adev->txdesc_start, + adev->txhostdesc_start, adev->txhostdesc_area_size, + (unsigned long long)adev->txhostdesc_startphy, + adev->rxdesc_start, + adev->rxhostdesc_start, adev->rxhostdesc_area_size, + (unsigned long long)adev->rxhostdesc_startphy, + adev->rxbuf_start, adev->rxbuf_area_size, + (unsigned long long)adev->rxbuf_startphy); + + FN_EXIT0; + return p; +} + + +/*********************************************************************** +*/ +int +acxpci_proc_eeprom_output(char *buf, acx_device_t *adev) +{ + char *p = buf; + int i; + + FN_ENTER; + + for (i = 0; i < 0x400; i++) { + acxpci_read_eeprom_byte(adev, i, p++); + } + + FN_EXIT1(p - buf); + return p - buf; +} + + +/*********************************************************************** +*/ +void +acxpci_set_interrupt_mask(acx_device_t *adev) +{ + if (IS_ACX111(adev)) { + adev->irq_mask = (u16) ~(0 + /* | HOST_INT_RX_DATA */ + | HOST_INT_TX_COMPLETE + /* | HOST_INT_TX_XFER */ + | HOST_INT_RX_COMPLETE + /* | HOST_INT_DTIM */ + /* | HOST_INT_BEACON */ + /* | HOST_INT_TIMER */ + /* | HOST_INT_KEY_NOT_FOUND */ + | HOST_INT_IV_ICV_FAILURE + | HOST_INT_CMD_COMPLETE + | HOST_INT_INFO + /* | HOST_INT_OVERFLOW */ + /* | HOST_INT_PROCESS_ERROR */ + | HOST_INT_SCAN_COMPLETE + | HOST_INT_FCS_THRESHOLD + /* | HOST_INT_UNKNOWN */ + ); + /* Or else acx100 won't signal cmd completion, right? */ + adev->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */ + } else { + adev->irq_mask = (u16) ~(0 + /* | HOST_INT_RX_DATA */ + | HOST_INT_TX_COMPLETE + /* | HOST_INT_TX_XFER */ + | HOST_INT_RX_COMPLETE + /* | HOST_INT_DTIM */ + /* | HOST_INT_BEACON */ + /* | HOST_INT_TIMER */ + /* | HOST_INT_KEY_NOT_FOUND */ + /* | HOST_INT_IV_ICV_FAILURE */ + | HOST_INT_CMD_COMPLETE + | HOST_INT_INFO + /* | HOST_INT_OVERFLOW */ + /* | HOST_INT_PROCESS_ERROR */ + | HOST_INT_SCAN_COMPLETE + /* | HOST_INT_FCS_THRESHOLD */ + /* | HOST_INT_UNKNOWN */ + ); + adev->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */ + } +} + + +/*********************************************************************** +*/ +int +acx100pci_s_set_tx_level(acx_device_t *adev, u8 level_dbm) +{ + /* since it can be assumed that at least the Maxim radio has a + * maximum power output of 20dBm and since it also can be + * assumed that these values drive the DAC responsible for + * setting the linear Tx level, I'd guess that these values + * should be the corresponding linear values for a dBm value, + * in other words: calculate the values from that formula: + * Y [dBm] = 10 * log (X [mW]) + * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm) + * and you're done... + * Hopefully that's ok, but you never know if we're actually + * right... (especially since Windows XP doesn't seem to show + * actual Tx dBm values :-P) */ + + /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the + * values are EXACTLY mW!!! Not sure about RFMD and others, + * though... */ + static const u8 dbm2val_maxim[21] = { + 63, 63, 63, 62, + 61, 61, 60, 60, + 59, 58, 57, 55, + 53, 50, 47, 43, + 38, 31, 23, 13, + 0 + }; + static const u8 dbm2val_rfmd[21] = { + 0, 0, 0, 1, + 2, 2, 3, 3, + 4, 5, 6, 8, + 10, 13, 16, 20, + 25, 32, 41, 50, + 63 + }; + const u8 *table; + + switch (adev->radio_type) { + case RADIO_MAXIM_0D: + table = &dbm2val_maxim[0]; + break; + case RADIO_RFMD_11: + case RADIO_RALINK_15: + table = &dbm2val_rfmd[0]; + break; + default: + printk("%s: unknown/unsupported radio type, " + "cannot modify tx power level yet!\n", + adev->ndev->name); + return NOT_OK; + } + printk("%s: changing radio power level to %u dBm (%u)\n", + adev->ndev->name, level_dbm, table[level_dbm]); + acxpci_s_write_phy_reg(adev, 0x11, table[level_dbm]); + return OK; +} + + +/*********************************************************************** +** Data for init_module/cleanup_module +*/ +static DEFINE_PCI_DEVICE_TABLE(acxpci_id_tbl) = { + { + .vendor = PCI_VENDOR_ID_TI, + .device = PCI_DEVICE_ID_TI_TNETW1100A, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = CHIPTYPE_ACX100, + }, + { + .vendor = PCI_VENDOR_ID_TI, + .device = PCI_DEVICE_ID_TI_TNETW1100B, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = CHIPTYPE_ACX100, + }, + { + .vendor = PCI_VENDOR_ID_TI, + .device = PCI_DEVICE_ID_TI_TNETW1130, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = CHIPTYPE_ACX111, + }, + { + .vendor = 0, + .device = 0, + .subvendor = 0, + .subdevice = 0, + .driver_data = 0, + } +}; + +MODULE_DEVICE_TABLE(pci, acxpci_id_tbl); + +static struct pci_driver acxpci_driver = { + .name = "acx_pci", + .id_table = acxpci_id_tbl, + .probe = acxpci_e_probe, + .remove = __devexit_p(acxpci_e_remove), +#ifdef CONFIG_PM + .suspend = acxpci_e_suspend, + .resume = acxpci_e_resume +#endif /* CONFIG_PM */ +}; + + +/*********************************************************************** +** acxpci_e_init_module +** +** Module initialization routine, called once at module load time +*/ +int __init +acxpci_e_init_module(void) +{ + int res; + + FN_ENTER; + +#if (ACX_IO_WIDTH==32) + printk("acx: compiled to use 32bit I/O access. " + "I/O timing issues might occur, such as " + "non-working firmware upload. Report them\n"); +#else + printk("acx: compiled to use 16bit I/O access only " + "(compatibility mode)\n"); +#endif + +#ifdef __LITTLE_ENDIAN +#define ENDIANNESS_STRING "running on a little-endian CPU\n" +#else +#define ENDIANNESS_STRING "running on a BIG-ENDIAN CPU\n" +#endif + log(L_INIT, + ENDIANNESS_STRING + "PCI module " ACX_RELEASE " initialized, " + "waiting for cards to probe...\n" + ); + + res = pci_register_driver(&acxpci_driver); + FN_EXIT1(res); + return res; +} + + +/*********************************************************************** +** acxpci_e_cleanup_module +** +** Called at module unload time. This is our last chance to +** clean up after ourselves. +*/ +void __exit +acxpci_e_cleanup_module(void) +{ + FN_ENTER; + + pci_unregister_driver(&acxpci_driver); + + FN_EXIT0; +} --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/common.c +++ linux-2.6.27/ubuntu/misc/wireless/acx/common.c @@ -0,0 +1,7220 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acx.h" + + +/*********************************************************************** +*/ +static client_t *acx_l_sta_list_alloc(acx_device_t *adev); +static client_t *acx_l_sta_list_get_from_hash(acx_device_t *adev, const u8 *address); + +static int acx_l_process_data_frame_master(acx_device_t *adev, rxbuffer_t *rxbuf); +static int acx_l_process_data_frame_client(acx_device_t *adev, rxbuffer_t *rxbuf); +/* static int acx_l_process_NULL_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala); */ +static int acx_l_process_mgmt_frame(acx_device_t *adev, rxbuffer_t *rxbuf); +static void acx_l_process_disassoc_from_sta(acx_device_t *adev, const wlan_fr_disassoc_t *req); +static void acx_l_process_disassoc_from_ap(acx_device_t *adev, const wlan_fr_disassoc_t *req); +static void acx_l_process_deauth_from_sta(acx_device_t *adev, const wlan_fr_deauthen_t *req); +static void acx_l_process_deauth_from_ap(acx_device_t *adev, const wlan_fr_deauthen_t *req); +static int acx_l_process_probe_response(acx_device_t *adev, wlan_fr_proberesp_t *req, const rxbuffer_t *rxbuf); +static int acx_l_process_assocresp(acx_device_t *adev, const wlan_fr_assocresp_t *req); +static int acx_l_process_reassocresp(acx_device_t *adev, const wlan_fr_reassocresp_t *req); +static int acx_l_process_authen(acx_device_t *adev, const wlan_fr_authen_t *req); +static int acx_l_transmit_assocresp(acx_device_t *adev, const wlan_fr_assocreq_t *req); +static int acx_l_transmit_reassocresp(acx_device_t *adev, const wlan_fr_reassocreq_t *req); +static int acx_l_transmit_deauthen(acx_device_t *adev, const u8 *addr, u16 reason); +static int acx_l_transmit_authen1(acx_device_t *adev); +static int acx_l_transmit_authen2(acx_device_t *adev, const wlan_fr_authen_t *req, client_t *clt); +static int acx_l_transmit_authen3(acx_device_t *adev, const wlan_fr_authen_t *req); +static int acx_l_transmit_authen4(acx_device_t *adev, const wlan_fr_authen_t *req); +static int acx_l_transmit_assoc_req(acx_device_t *adev); + + +/*********************************************************************** +*/ +#if ACX_DEBUG +unsigned int acx_debug = ACX_DEFAULT_MSG; +#endif + +char firmware_ver[33] = "default"; +module_param_string(firmware_ver, firmware_ver, sizeof(firmware_ver), 0444); +MODULE_PARM_DESC(firmware_ver, "Alternate firmware version."); + +#if ACX_DEBUG +module_param_named(debug, acx_debug, uint, 0); +#endif + +#if ACX_DEBUG +MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)"); +#endif + +#ifdef MODULE_LICENSE +MODULE_LICENSE("Dual MPL/GPL"); +#endif +/* USB had this: MODULE_AUTHOR("Martin Wawro "); */ +MODULE_AUTHOR("ACX100 Open Source Driver development team"); +MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)"); + + +/*********************************************************************** +*/ +/* Probably a number of acx's intermediate buffers for USB transfers, +** not to be confused with number of descriptors in tx/rx rings +** (which are not directly accessible to host in USB devices) */ +#define USB_RX_CNT 10 +#define USB_TX_CNT 10 + + +/*********************************************************************** +*/ + +/* minutes to wait until next radio recalibration: */ +#define RECALIB_PAUSE 5 + +/* Please keep acx_reg_domain_ids_len in sync... */ +const u8 acx_reg_domain_ids[acx_reg_domain_ids_len] = + { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 }; +static const u16 reg_domain_channel_masks[acx_reg_domain_ids_len] = + { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc }; +const char * const +acx_reg_domain_strings[] = { + /* 0 */ " 1-11 FCC (USA)", + /* 1 */ " 1-11 DOC/IC (Canada)", +/* BTW: WLAN use in ETSI is regulated by ETSI standard EN 300 328-2 V1.1.2 */ + /* 2 */ " 1-13 ETSI (Europe)", + /* 3 */ "10-11 Spain", + /* 4 */ "10-13 France", + /* 5 */ " 14 MKK (Japan)", + /* 6 */ " 1-14 MKK1", + /* 7 */ " 3-9 Israel (not all firmware versions)", + NULL /* needs to remain as last entry */ +}; + + + +/*********************************************************************** +** Debugging support +*/ +#ifdef PARANOID_LOCKING +static unsigned max_lock_time; +static unsigned max_sem_time; + +void +acx_lock_unhold() { max_lock_time = 0; } +void +acx_sem_unhold() { max_sem_time = 0; } + +static inline const char* +sanitize_str(const char *s) +{ + const char* t = strrchr(s, '/'); + if (t) return t + 1; + return s; +} + +void +acx_lock_debug(acx_device_t *adev, const char* where) +{ + unsigned int count = 100*1000*1000; + where = sanitize_str(where); + while (--count) { + if (!spin_is_locked(&adev->lock)) break; + cpu_relax(); + } + if (!count) { + printk(KERN_EMERG "LOCKUP: already taken at %s!\n", adev->last_lock); + BUG(); + } + adev->last_lock = where; + rdtscl(adev->lock_time); +} +void +acx_unlock_debug(acx_device_t *adev, const char* where) +{ +#ifdef SMP + if (!spin_is_locked(&adev->lock)) { + where = sanitize_str(where); + printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where); + BUG(); + } +#endif + if (acx_debug & L_LOCK) { + unsigned long diff; + rdtscl(diff); + diff -= adev->lock_time; + if (diff > max_lock_time) { + where = sanitize_str(where); + printk("max lock hold time %ld CPU ticks from %s " + "to %s\n", diff, adev->last_lock, where); + max_lock_time = diff; + } + } +} +void +acx_down_debug(acx_device_t *adev, const char* where) +{ + int sem_count; + unsigned long timeout = jiffies + 5*HZ; + + where = sanitize_str(where); + + for (;;) { + sem_count = atomic_read(&adev->sem.count); + if (sem_count) break; + if (time_after(jiffies, timeout)) + break; + msleep(5); + } + if (!sem_count) { + printk(KERN_EMERG "D STATE at %s! last sem at %s\n", + where, adev->last_sem); + dump_stack(); + } + adev->last_sem = where; + adev->sem_time = jiffies; + down(&adev->sem); + if (acx_debug & L_LOCK) { + printk("%s: sem_down %d -> %d\n", + where, sem_count, atomic_read(&adev->sem.count)); + } +} +void +acx_up_debug(acx_device_t *adev, const char* where) +{ + int sem_count = atomic_read(&adev->sem.count); + if (sem_count) { + where = sanitize_str(where); + printk(KERN_EMERG "STRAY UP at %s! sem.count=%d\n", where, sem_count); + dump_stack(); + } + if (acx_debug & L_LOCK) { + unsigned long diff = jiffies - adev->sem_time; + if (diff > max_sem_time) { + where = sanitize_str(where); + printk("max sem hold time %ld jiffies from %s " + "to %s\n", diff, adev->last_sem, where); + max_sem_time = diff; + } + } + up(&adev->sem); + if (acx_debug & L_LOCK) { + where = sanitize_str(where); + printk("%s: sem_up %d -> %d\n", + where, sem_count, atomic_read(&adev->sem.count)); + } +} +#endif /* PARANOID_LOCKING */ + + +/*********************************************************************** +*/ +#if ACX_DEBUG > 1 + +static int acx_debug_func_indent; +#define DEBUG_TSC 0 +#define FUNC_INDENT_INCREMENT 2 + +#if DEBUG_TSC +#define TIMESTAMP(d) unsigned long d; rdtscl(d) +#else +#define TIMESTAMP(d) unsigned long d = jiffies +#endif + +static const char +spaces[] = " " " "; /* Nx10 spaces */ + +void +log_fn_enter(const char *funcname) +{ + int indent; + TIMESTAMP(d); + + indent = acx_debug_func_indent; + if (indent >= sizeof(spaces)) + indent = sizeof(spaces)-1; + + printk("%08ld %s==> %s\n", + d % 100000000, + spaces + (sizeof(spaces)-1) - indent, + funcname + ); + + acx_debug_func_indent += FUNC_INDENT_INCREMENT; +} +void +log_fn_exit(const char *funcname) +{ + int indent; + TIMESTAMP(d); + + acx_debug_func_indent -= FUNC_INDENT_INCREMENT; + + indent = acx_debug_func_indent; + if (indent >= sizeof(spaces)) + indent = sizeof(spaces)-1; + + printk("%08ld %s<== %s\n", + d % 100000000, + spaces + (sizeof(spaces)-1) - indent, + funcname + ); +} +void +log_fn_exit_v(const char *funcname, int v) +{ + int indent; + TIMESTAMP(d); + + acx_debug_func_indent -= FUNC_INDENT_INCREMENT; + + indent = acx_debug_func_indent; + if (indent >= sizeof(spaces)) + indent = sizeof(spaces)-1; + + printk("%08ld %s<== %s: %08X\n", + d % 100000000, + spaces + (sizeof(spaces)-1) - indent, + funcname, + v + ); +} +#endif /* ACX_DEBUG > 1 */ + + +/*********************************************************************** +** Basically a msleep with logging +*/ +void +acx_s_msleep(int ms) +{ + FN_ENTER; + msleep(ms); + FN_EXIT0; +} + + +/*********************************************************************** +** Not inlined: it's larger than it seems +*/ +void +acx_print_mac(const char *head, const u8 *mac, const char *tail) +{ + printk("%s"MACSTR"%s", head, MAC(mac), tail); +} + + +/*********************************************************************** +** acx_get_status_name +*/ +static const char* +acx_get_status_name(u16 status) +{ + static const char * const str[] = { + "STOPPED", "SCANNING", "WAIT_AUTH", + "AUTHENTICATED", "ASSOCIATED", "INVALID??" + }; + if (status > VEC_SIZE(str)-1) + status = VEC_SIZE(str)-1; + + return str[status]; +} + + +/*********************************************************************** +** acx_get_packet_type_string +*/ +#if ACX_DEBUG +const char* +acx_get_packet_type_string(u16 fc) +{ + static const char * const mgmt_arr[] = { + "MGMT/AssocReq", "MGMT/AssocResp", "MGMT/ReassocReq", + "MGMT/ReassocResp", "MGMT/ProbeReq", "MGMT/ProbeResp", + "MGMT/UNKNOWN", "MGMT/UNKNOWN", "MGMT/Beacon", "MGMT/ATIM", + "MGMT/Disassoc", "MGMT/Authen", "MGMT/Deauthen" + }; + static const char * const ctl_arr[] = { + "CTL/PSPoll", "CTL/RTS", "CTL/CTS", "CTL/Ack", "CTL/CFEnd", + "CTL/CFEndCFAck" + }; + static const char * const data_arr[] = { + "DATA/DataOnly", "DATA/Data CFAck", "DATA/Data CFPoll", + "DATA/Data CFAck/CFPoll", "DATA/Null", "DATA/CFAck", + "DATA/CFPoll", "DATA/CFAck/CFPoll" + }; + const char *str; + u8 fstype = (WF_FC_FSTYPE & fc) >> 4; + u8 ctl; + + switch (WF_FC_FTYPE & fc) { + case WF_FTYPE_MGMT: + if (fstype < VEC_SIZE(mgmt_arr)) + str = mgmt_arr[fstype]; + else + str = "MGMT/UNKNOWN"; + break; + case WF_FTYPE_CTL: + ctl = fstype - 0x0a; + if (ctl < VEC_SIZE(ctl_arr)) + str = ctl_arr[ctl]; + else + str = "CTL/UNKNOWN"; + break; + case WF_FTYPE_DATA: + if (fstype < VEC_SIZE(data_arr)) + str = data_arr[fstype]; + else + str = "DATA/UNKNOWN"; + break; + default: + str = "UNKNOWN"; + break; + } + return str; +} +#endif + + +/*********************************************************************** +** acx_wlan_reason_str +*/ +static inline const char* +acx_wlan_reason_str(u16 reason) +{ + static const char* const reason_str[] = { + /* 0 */ "?", + /* 1 */ "unspecified", + /* 2 */ "prev auth is not valid", + /* 3 */ "leaving BBS", + /* 4 */ "due to inactivity", + /* 5 */ "AP is busy", + /* 6 */ "got class 2 frame from non-auth'ed STA", + /* 7 */ "got class 3 frame from non-assoc'ed STA", + /* 8 */ "STA has left BSS", + /* 9 */ "assoc without auth is not allowed", + /* 10 */ "bad power setting (802.11h)", + /* 11 */ "bad channel (802.11i)", + /* 12 */ "?", + /* 13 */ "invalid IE", + /* 14 */ "MIC failure", + /* 15 */ "four-way handshake timeout", + /* 16 */ "group key handshake timeout", + /* 17 */ "IE is different", + /* 18 */ "invalid group cipher", + /* 19 */ "invalid pairwise cipher", + /* 20 */ "invalid AKMP", + /* 21 */ "unsupported RSN version", + /* 22 */ "invalid RSN IE cap", + /* 23 */ "802.1x failed", + /* 24 */ "cipher suite rejected" + }; + return reason < VEC_SIZE(reason_str) ? reason_str[reason] : "?"; +} + + +/*********************************************************************** +** acx_cmd_status_str +*/ +const char* +acx_cmd_status_str(unsigned int state) +{ + static const char * const cmd_error_strings[] = { + "Idle", + "Success", + "Unknown Command", + "Invalid Information Element", + "Channel rejected", + "Channel invalid in current regulatory domain", + "MAC invalid", + "Command rejected (read-only information element)", + "Command rejected", + "Already asleep", + "TX in progress", + "Already awake", + "Write only", + "RX in progress", + "Invalid parameter", + "Scan in progress", + "Failed" + }; + return state < VEC_SIZE(cmd_error_strings) ? + cmd_error_strings[state] : "?"; +} + + +/*********************************************************************** +** get_status_string +*/ +static inline const char* +get_status_string(unsigned int status) +{ + /* A bit shortened, but hopefully still understandable */ + static const char * const status_str[] = { + /* 0 */ "Successful", + /* 1 */ "Unspecified failure", + /* 2 */ "reserved", + /* 3 */ "reserved", + /* 4 */ "reserved", + /* 5 */ "reserved", + /* 6 */ "reserved", + /* 7 */ "reserved", + /* 8 */ "reserved", + /* 9 */ "reserved", + /*10 */ "Cannot support all requested capabilities in Capability Information field", + /*11 */ "Reassoc denied (reason outside of 802.11b scope)", + /*12 */ "Assoc denied (reason outside of 802.11b scope) -- maybe MAC filtering by peer?", + /*13 */ "Responding station doesnt support specified auth algorithm -- maybe WEP auth Open vs. Restricted?", + /*14 */ "Auth rejected: wrong transaction sequence number", + /*15 */ "Auth rejected: challenge failure", + /*16 */ "Auth rejected: timeout for next frame in sequence", + /*17 */ "Assoc denied: too many STAs on this AP", + /*18 */ "Assoc denied: requesting STA doesnt support all data rates in basic set", + /*19 */ "Assoc denied: requesting STA doesnt support Short Preamble", + /*20 */ "Assoc denied: requesting STA doesnt support PBCC Modulation", + /*21 */ "Assoc denied: requesting STA doesnt support Channel Agility" + /*22 */ "reserved", + /*23 */ "reserved", + /*24 */ "reserved", + /*25 */ "Assoc denied: requesting STA doesnt support Short Slot Time", + /*26 */ "Assoc denied: requesting STA doesnt support DSSS-OFDM" + }; + + return status_str[status < VEC_SIZE(status_str) ? status : 2]; +} + + +/*********************************************************************** +*/ +void +acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr) +{ + if (acx_debug & L_ASSOC) { + int offset = (u8*)ie_ptr - (u8*)hdr; + printk("acx: unknown EID %d in mgmt frame at offset %d. IE: ", + ie_ptr->eid, offset); + /* IE len can be bogus, IE can extend past packet end. Oh well... */ + acx_dump_bytes(ie_ptr, ie_ptr->len + 2); + if (acx_debug & L_DATA) { + printk("frame (%s): ", + acx_get_packet_type_string(le16_to_cpu(hdr->fc))); + acx_dump_bytes(hdr, len); + } + } +} + + +/*********************************************************************** +*/ +#if ACX_DEBUG +void +acx_dump_bytes(const void *data, int num) +{ + const u8* ptr = (const u8*)data; + + if (num <= 0) { + printk("\n"); + return; + } + + while (num >= 16) { + printk( "%02X %02X %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X %02X %02X\n", + ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7], + ptr[8], ptr[9], ptr[10], ptr[11], + ptr[12], ptr[13], ptr[14], ptr[15]); + num -= 16; + ptr += 16; + } + if (num > 0) { + while (--num > 0) + printk("%02X ", *ptr++); + printk("%02X\n", *ptr); + } +} +#endif + + +/*********************************************************************** +** acx_s_get_firmware_version +*/ +void +acx_s_get_firmware_version(acx_device_t *adev) +{ + fw_ver_t fw; + u8 hexarr[4] = { 0, 0, 0, 0 }; + int hexidx = 0, val = 0; + const char *num; + char c; + + FN_ENTER; + + memset(fw.fw_id, 'E', FW_ID_SIZE); + acx_s_interrogate(adev, &fw, ACX1xx_IE_FWREV); + memcpy(adev->firmware_version, fw.fw_id, FW_ID_SIZE); + adev->firmware_version[FW_ID_SIZE] = '\0'; + + log(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n", + adev->firmware_version, fw.hw_id); + + if (strncmp(fw.fw_id, "Rev ", 4) != 0) { + printk("acx: strange firmware version string " + "'%s', please report\n", adev->firmware_version); + adev->firmware_numver = 0x01090407; /* assume 1.9.4.7 */ + } else { + num = &fw.fw_id[4]; + while (1) { + c = *num++; + if ((c == '.') || (c == '\0')) { + hexarr[hexidx++] = val; + if ((hexidx > 3) || (c == '\0')) /* end? */ + break; + val = 0; + continue; + } + if ((c >= '0') && (c <= '9')) + c -= '0'; + else + c = c - 'a' + (char)10; + val = val*16 + c; + } + + adev->firmware_numver = (u32)( + (hexarr[0] << 24) | (hexarr[1] << 16) + | (hexarr[2] << 8) | hexarr[3]); + log(L_DEBUG, "firmware_numver 0x%08X\n", adev->firmware_numver); + } + if (IS_ACX111(adev)) { + if (adev->firmware_numver == 0x00010011) { + /* This one does not survive floodpinging */ + printk("acx: firmware '%s' is known to be buggy, " + "please upgrade\n", adev->firmware_version); + } + } + + adev->firmware_id = le32_to_cpu(fw.hw_id); + + /* we're able to find out more detailed chip names now */ + switch (adev->firmware_id & 0xffff0000) { + case 0x01010000: + case 0x01020000: + adev->chip_name = "TNETW1100A"; + break; + case 0x01030000: + adev->chip_name = "TNETW1100B"; + break; + case 0x03000000: + case 0x03010000: + adev->chip_name = "TNETW1130"; + break; + case 0x04030000: /* 0x04030101 is TNETW1450 */ + adev->chip_name = "TNETW1450"; + break; + default: + printk("acx: unknown chip ID 0x%08X, " + "please report\n", adev->firmware_id); + break; + } + + FN_EXIT0; +} + + +/*********************************************************************** +** acx_display_hardware_details +** +** Displays hw/fw version, radio type etc... +*/ +void +acx_display_hardware_details(acx_device_t *adev) +{ + const char *radio_str, *form_str; + + FN_ENTER; + + switch (adev->radio_type) { + case RADIO_MAXIM_0D: + radio_str = "Maxim"; + break; + case RADIO_RFMD_11: + radio_str = "RFMD"; + break; + case RADIO_RALINK_15: + radio_str = "Ralink"; + break; + case RADIO_RADIA_16: + radio_str = "Radia"; + break; + case RADIO_UNKNOWN_17: + /* TI seems to have a radio which is + * additionally 802.11a capable, too */ + radio_str = "802.11a/b/g radio?! Please report"; + break; + case RADIO_UNKNOWN_19: + radio_str = "A radio used by Safecom cards?! Please report"; + break; + case RADIO_UNKNOWN_1B: + radio_str = "An unknown radio used by TNETW1450 USB adapters"; + break; + default: + radio_str = "UNKNOWN, please report radio type name!"; + break; + } + + switch (adev->form_factor) { + case 0x00: + form_str = "unspecified"; + break; + case 0x01: + form_str = "(mini-)PCI / CardBus"; + break; + case 0x02: + form_str = "USB"; + break; + case 0x03: + form_str = "Compact Flash"; + break; + default: + form_str = "UNKNOWN, please report"; + break; + } + + printk("acx: === chipset %s, radio type 0x%02X (%s), " + "form factor 0x%02X (%s), EEPROM version 0x%02X: " + "uploaded firmware '%s' ===\n", + adev->chip_name, adev->radio_type, radio_str, + adev->form_factor, form_str, adev->eeprom_version, + adev->firmware_version); + + FN_EXIT0; +} + + +/*********************************************************************** +*/ +int +acx_e_change_mtu(struct net_device *ndev, int mtu) +{ + enum { + MIN_MTU = 256, + MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN) + }; + + if (mtu < MIN_MTU || mtu > MAX_MTU) + return -EINVAL; + + ndev->mtu = mtu; + return 0; +} + + +/*********************************************************************** +** acx_e_get_stats, acx_e_get_wireless_stats +*/ +struct net_device_stats* +acx_e_get_stats(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + return &adev->stats; +} + +struct iw_statistics* +acx_e_get_wireless_stats(struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + return &adev->wstats; +} + + +/*********************************************************************** +** maps acx111 tx descr rate field to acx100 one +*/ +const u8 +acx_bitpos2rate100[] = { + RATE100_1 ,/* 0 */ + RATE100_2 ,/* 1 */ + RATE100_5 ,/* 2 */ + RATE100_2 ,/* 3, should not happen */ + RATE100_2 ,/* 4, should not happen */ + RATE100_11 ,/* 5 */ + RATE100_2 ,/* 6, should not happen */ + RATE100_2 ,/* 7, should not happen */ + RATE100_22 ,/* 8 */ + RATE100_2 ,/* 9, should not happen */ + RATE100_2 ,/* 10, should not happen */ + RATE100_2 ,/* 11, should not happen */ + RATE100_2 ,/* 12, should not happen */ + RATE100_2 ,/* 13, should not happen */ + RATE100_2 ,/* 14, should not happen */ + RATE100_2 ,/* 15, should not happen */ +}; + +u8 +acx_rate111to100(u16 r) { + return acx_bitpos2rate100[highest_bit(r)]; +} + + +/*********************************************************************** +** Calculate level like the feb 2003 windows driver seems to do +*/ +static u8 +acx_signal_to_winlevel(u8 rawlevel) +{ + /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */ + u8 winlevel = ((4 + (rawlevel * 5)) / 8); + + if (winlevel > 100) + winlevel = 100; + return winlevel; +} + +u8 +acx_signal_determine_quality(u8 signal, u8 noise) +{ + int qual; + + qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2; + + if (qual > 100) + return 100; + if (qual < 0) + return 0; + return qual; +} + + +/*********************************************************************** +** Interrogate/configure commands +*/ + +/* FIXME: the lengths given here probably aren't always correct. + * They should be gradually replaced by proper "sizeof(acx1XX_ie_XXXX)-4", + * unless the firmware actually expects a different length than the struct length */ +static const u16 +acx100_ie_len[] = { + 0, + ACX100_IE_ACX_TIMER_LEN, + sizeof(acx100_ie_powersave_t)-4, /* is that 6 or 8??? */ + ACX1xx_IE_QUEUE_CONFIG_LEN, + ACX100_IE_BLOCK_SIZE_LEN, + ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN, + ACX1xx_IE_RATE_FALLBACK_LEN, + ACX100_IE_WEP_OPTIONS_LEN, + ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */ + 0, + ACX1xx_IE_ASSOC_ID_LEN, + 0, + ACX111_IE_CONFIG_OPTIONS_LEN, + ACX1xx_IE_FWREV_LEN, + ACX1xx_IE_FCS_ERROR_COUNT_LEN, + ACX1xx_IE_MEDIUM_USAGE_LEN, + ACX1xx_IE_RXCONFIG_LEN, + 0, + 0, + sizeof(fw_stats_t)-4, + 0, + ACX1xx_IE_FEATURE_CONFIG_LEN, + ACX111_IE_KEY_CHOOSE_LEN, + ACX1FF_IE_MISC_CONFIG_TABLE_LEN, + ACX1FF_IE_WONE_CONFIG_LEN, + 0, + ACX1FF_IE_TID_CONFIG_LEN, + 0, + 0, + 0, + ACX1FF_IE_CALIB_ASSESSMENT_LEN, + ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN, + ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN, + ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN, + 0, + ACX1FF_IE_PACKET_DETECT_THRESH_LEN, + ACX1FF_IE_TX_CONFIG_OPTIONS_LEN, + ACX1FF_IE_CCA_THRESHOLD_LEN, + ACX1FF_IE_EVENT_MASK_LEN, + ACX1FF_IE_DTIM_PERIOD_LEN, + 0, + ACX1FF_IE_ACI_CONFIG_SET_LEN, + 0, + 0, + 0, + 0, + 0, + 0, + ACX1FF_IE_EEPROM_VER_LEN, +}; + +static const u16 +acx100_ie_len_dot11[] = { + 0, + ACX1xx_IE_DOT11_STATION_ID_LEN, + 0, + ACX100_IE_DOT11_BEACON_PERIOD_LEN, + ACX1xx_IE_DOT11_DTIM_PERIOD_LEN, + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN, + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN, + ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN, + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN, + 0, + ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN, + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN, + 0, + ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN, + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN, + ACX100_IE_DOT11_ED_THRESHOLD_LEN, + ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN, + 0, + 0, + 0, +}; + +static const u16 +acx111_ie_len[] = { + 0, + ACX100_IE_ACX_TIMER_LEN, + sizeof(acx111_ie_powersave_t)-4, + ACX1xx_IE_QUEUE_CONFIG_LEN, + ACX100_IE_BLOCK_SIZE_LEN, + ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN, + ACX1xx_IE_RATE_FALLBACK_LEN, + ACX100_IE_WEP_OPTIONS_LEN, + ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */ + 0, + ACX1xx_IE_ASSOC_ID_LEN, + 0, + ACX111_IE_CONFIG_OPTIONS_LEN, + ACX1xx_IE_FWREV_LEN, + ACX1xx_IE_FCS_ERROR_COUNT_LEN, + ACX1xx_IE_MEDIUM_USAGE_LEN, + ACX1xx_IE_RXCONFIG_LEN, + 0, + 0, + sizeof(fw_stats_t)-4, + 0, + ACX1xx_IE_FEATURE_CONFIG_LEN, + ACX111_IE_KEY_CHOOSE_LEN, + ACX1FF_IE_MISC_CONFIG_TABLE_LEN, + ACX1FF_IE_WONE_CONFIG_LEN, + 0, + ACX1FF_IE_TID_CONFIG_LEN, + 0, + 0, + 0, + ACX1FF_IE_CALIB_ASSESSMENT_LEN, + ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN, + ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN, + ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN, + 0, + ACX1FF_IE_PACKET_DETECT_THRESH_LEN, + ACX1FF_IE_TX_CONFIG_OPTIONS_LEN, + ACX1FF_IE_CCA_THRESHOLD_LEN, + ACX1FF_IE_EVENT_MASK_LEN, + ACX1FF_IE_DTIM_PERIOD_LEN, + 0, + ACX1FF_IE_ACI_CONFIG_SET_LEN, + 0, + 0, + 0, + 0, + 0, + 0, + ACX1FF_IE_EEPROM_VER_LEN, +}; + +static const u16 +acx111_ie_len_dot11[] = { + 0, + ACX1xx_IE_DOT11_STATION_ID_LEN, + 0, + ACX100_IE_DOT11_BEACON_PERIOD_LEN, + ACX1xx_IE_DOT11_DTIM_PERIOD_LEN, + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN, + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN, + ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN, + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN, + 0, + ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN, + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN, + 0, + ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN, + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN, + ACX100_IE_DOT11_ED_THRESHOLD_LEN, + ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN, + 0, + 0, + 0, +}; + + +#undef FUNC +#define FUNC "configure" +#if !ACX_DEBUG +int +acx_s_configure(acx_device_t *adev, void *pdr, int type) +{ +#else +int +acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* typestr) +{ +#endif + u16 len; + int res; + + if (type < 0x1000) + len = adev->ie_len[type]; + else + len = adev->ie_len_dot11[type - 0x1000]; + + log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len); + if (unlikely(!len)) { + log(L_DEBUG, "zero-length type %s?!\n", typestr); + } + + ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type); + ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len); + res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIGURE, pdr, len + 4); + if (unlikely(OK != res)) { +#if ACX_DEBUG + printk("%s: "FUNC"(type:%s) FAILED\n", adev->ndev->name, typestr); +#else + printk("%s: "FUNC"(type:0x%X) FAILED\n", adev->ndev->name, type); +#endif + /* dump_stack() is already done in issue_cmd() */ + } + return res; +} + +#undef FUNC +#define FUNC "interrogate" +#if !ACX_DEBUG +int +acx_s_interrogate(acx_device_t *adev, void *pdr, int type) +{ +#else +int +acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type, + const char* typestr) +{ +#endif + u16 len; + int res; + + /* FIXME: no check whether this exceeds the array yet. + * We should probably remember the number of entries... */ + if (type < 0x1000) + len = adev->ie_len[type]; + else + len = adev->ie_len_dot11[type-0x1000]; + + log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len); + + ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type); + ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len); + res = acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, pdr, len + 4); + if (unlikely(OK != res)) { +#if ACX_DEBUG + printk("%s: "FUNC"(type:%s) FAILED\n", adev->ndev->name, typestr); +#else + printk("%s: "FUNC"(type:0x%X) FAILED\n", adev->ndev->name, type); +#endif + /* dump_stack() is already done in issue_cmd() */ + } + return res; +} + +#if CMD_DISCOVERY +void +great_inquisitor(acx_device_t *adev) +{ + static struct { + u16 type; + u16 len; + /* 0x200 was too large here: */ + u8 data[0x100 - 4]; + } ACX_PACKED ie; + u16 type; + + FN_ENTER; + + /* 0..0x20, 0x1000..0x1020 */ + for (type = 0; type <= 0x1020; type++) { + if (type == 0x21) + type = 0x1000; + ie.type = cpu_to_le16(type); + ie.len = cpu_to_le16(sizeof(ie) - 4); + acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, &ie, sizeof(ie)); + } + FN_EXIT0; +} +#endif + + +#ifdef CONFIG_PROC_FS +/*********************************************************************** +** /proc files +*/ +/*********************************************************************** +** acx_l_proc_output +** Generate content for our /proc entry +** +** Arguments: +** buf is a pointer to write output to +** adev is the usual pointer to our private struct acx_device +** Returns: +** number of bytes actually written to buf +** Side effects: +** none +*/ +static int +acx_l_proc_output(char *buf, acx_device_t *adev) +{ + char *p = buf; + int i; + + FN_ENTER; + + p += sprintf(p, + "acx driver version:\t\t" ACX_RELEASE "\n" + "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n" + "chip name:\t\t\t%s (0x%08X)\n" + "radio type:\t\t\t0x%02X\n" + "form factor:\t\t\t0x%02X\n" + "EEPROM version:\t\t\t0x%02X\n" + "firmware version:\t\t%s (0x%08X)\n", + adev->chip_name, adev->firmware_id, + adev->radio_type, + adev->form_factor, + adev->eeprom_version, + adev->firmware_version, adev->firmware_numver); + + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + struct client *bss = &adev->sta_list[i]; + if (!bss->used) continue; + p += sprintf(p, "BSS %u BSSID "MACSTR" ESSID %s channel %u " + "Cap 0x%X SIR %u SNR %u\n", + i, MAC(bss->bssid), (char*)bss->essid, bss->channel, + bss->cap_info, bss->sir, bss->snr); + } + p += sprintf(p, "status:\t\t\t%u (%s)\n", + adev->status, acx_get_status_name(adev->status)); + + FN_EXIT1(p - buf); + return p - buf; +} + + +/*********************************************************************** +*/ +static int +acx_s_proc_diag_output(char *buf, acx_device_t *adev) +{ + char *p = buf; + unsigned long flags; + unsigned int len = 0, partlen; + u32 temp1, temp2; + u8 *st, *st_end; +#ifdef __BIG_ENDIAN + u8 *st2; +#endif + fw_stats_t *fw_stats; + char *part_str = NULL; + fw_stats_tx_t *tx = NULL; + fw_stats_rx_t *rx = NULL; + fw_stats_dma_t *dma = NULL; + fw_stats_irq_t *irq = NULL; + fw_stats_wep_t *wep = NULL; + fw_stats_pwr_t *pwr = NULL; + fw_stats_mic_t *mic = NULL; + fw_stats_aes_t *aes = NULL; + fw_stats_event_t *evt = NULL; + + FN_ENTER; + + acx_lock(adev, flags); + + if (IS_PCI(adev)) + p = acxpci_s_proc_diag_output(p, adev); + + p += sprintf(p, + "\n" + "** network status **\n" + "dev_state_mask 0x%04X\n" + "status %u (%s), " + "mode %u, channel %u, " + "reg_dom_id 0x%02X, reg_dom_chanmask 0x%04X, ", + adev->dev_state_mask, + adev->status, acx_get_status_name(adev->status), + adev->mode, adev->channel, + adev->reg_dom_id, adev->reg_dom_chanmask + ); + p += sprintf(p, + "ESSID \"%s\", essid_active %d, essid_len %d, " + "essid_for_assoc \"%s\", nick \"%s\"\n" + "WEP ena %d, restricted %d, idx %d\n", + adev->essid, adev->essid_active, (int)adev->essid_len, + adev->essid_for_assoc, adev->nick, + adev->wep_enabled, adev->wep_restricted, + adev->wep_current_index); + p += sprintf(p, "dev_addr "MACSTR"\n", MAC(adev->dev_addr)); + p += sprintf(p, "bssid "MACSTR"\n", MAC(adev->bssid)); + p += sprintf(p, "ap_filter "MACSTR"\n", MAC(adev->ap)); + + p += sprintf(p, + "\n" + "** PHY status **\n" + "tx_disabled %d, tx_level_dbm %d\n" /* "tx_level_val %d, tx_level_auto %d\n" */ + "sensitivity %d, antenna 0x%02X, ed_threshold %d, cca %d, preamble_mode %d\n" + "rate_basic 0x%04X, rate_oper 0x%04X\n" + "rts_threshold %d, frag_threshold %d, short_retry %d, long_retry %d\n" + "msdu_lifetime %d, listen_interval %d, beacon_interval %d\n", + adev->tx_disabled, adev->tx_level_dbm, /* adev->tx_level_val, adev->tx_level_auto, */ + adev->sensitivity, adev->antenna, adev->ed_threshold, adev->cca, adev->preamble_mode, + adev->rate_basic, adev->rate_oper, + adev->rts_threshold, adev->frag_threshold, adev->short_retry, adev->long_retry, + adev->msdu_lifetime, adev->listen_interval, adev->beacon_interval); + + acx_unlock(adev, flags); + + p += sprintf(p, + "\n" + "** Firmware **\n" + "NOTE: version dependent statistics layout, " + "please report if you suspect wrong parsing!\n" + "\n" + "version \"%s\"\n", adev->firmware_version); + + /* TODO: may replace kmalloc/memset with kzalloc once + * Linux 2.6.14 is widespread */ + fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL); + if (!fw_stats) { + FN_EXIT1(0); + return 0; + } + memset(fw_stats, 0, sizeof(*fw_stats)); + + st = (u8 *)fw_stats; + + part_str = "statistics query command"; + + if (OK != acx_s_interrogate(adev, st, ACX1xx_IE_FIRMWARE_STATISTICS)) + goto fw_stats_end; + + st += sizeof(u16); + len = *(u16 *)st; + + if (len > sizeof(*fw_stats)) { + p += sprintf(p, + "firmware version with bigger fw_stats struct detected\n" + "(%u vs. %zu), please report\n", len, sizeof(fw_stats_t)); + if (len > sizeof(*fw_stats)) { + p += sprintf(p, "struct size exceeded allocation!\n"); + len = sizeof(*fw_stats); + } + } + st += sizeof(u16); + st_end = st - 2*sizeof(u16) + len; + +#ifdef __BIG_ENDIAN + /* let's make one bold assumption here: + * (hopefully!) *all* statistics fields are u32 only, + * thus if we need to make endianness corrections + * we can simply do them in one go, in advance */ + st2 = (u8 *)fw_stats; + for (temp1 = 0; temp1 < len; temp1 += 4, st2 += 4) + *(u32 *)st2 = le32_to_cpu(*(u32 *)st2); +#endif + + part_str = "Rx/Tx"; + + /* directly at end of a struct part? --> no error! */ + if (st == st_end) + goto fw_stats_end; + + tx = (fw_stats_tx_t *)st; + st += sizeof(fw_stats_tx_t); + rx = (fw_stats_rx_t *)st; + st += sizeof(fw_stats_rx_t); + partlen = sizeof(fw_stats_tx_t) + sizeof(fw_stats_rx_t); + + if (IS_ACX100(adev)) { + /* at least ACX100 PCI F/W 1.9.8.b + * and ACX100 USB F/W 1.0.7-USB + * don't have those two fields... */ + st -= 2*sizeof(u32); + + /* our parsing doesn't quite match this firmware yet, + * log failure */ + if (st > st_end) + goto fw_stats_fail; + temp1 = temp2 = 999999999; + } else { + if (st > st_end) + goto fw_stats_fail; + temp1 = rx->rx_aci_events; + temp2 = rx->rx_aci_resets; + } + + p += sprintf(p, + "%s:\n" + " tx_desc_overfl %u\n" + " rx_OutOfMem %u, rx_hdr_overfl %u, rx_hw_stuck %u\n" + " rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u\n" + " rx_aci_events %u, rx_aci_resets %u\n", + part_str, + tx->tx_desc_of, + rx->rx_oom, + rx->rx_hdr_of, + rx->rx_hw_stuck, + rx->rx_dropped_frame, + rx->rx_frame_ptr_err, + rx->rx_xfr_hint_trig, + temp1, + temp2); + + part_str = "DMA"; + + if (st == st_end) + goto fw_stats_end; + + dma = (fw_stats_dma_t *)st; + partlen = sizeof(fw_stats_dma_t); + st += partlen; + + if (st > st_end) + goto fw_stats_fail; + + p += sprintf(p, + "%s:\n" + " rx_dma_req %u, rx_dma_err %u, tx_dma_req %u, tx_dma_err %u\n", + part_str, + dma->rx_dma_req, + dma->rx_dma_err, + dma->tx_dma_req, + dma->tx_dma_err); + + part_str = "IRQ"; + + if (st == st_end) + goto fw_stats_end; + + irq = (fw_stats_irq_t *)st; + partlen = sizeof(fw_stats_irq_t); + st += partlen; + + if (st > st_end) + goto fw_stats_fail; + + p += sprintf(p, + "%s:\n" + " cmd_cplt %u, fiq %u\n" + " rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u\n" + " irqs %u, tx_procs %u, decrypt_done %u\n" + " dma_0_done %u, dma_1_done %u, tx_exch_complet %u\n" + " commands %u, rx_procs %u, hw_pm_mode_changes %u\n" + " host_acks %u, pci_pm %u, acm_wakeups %u\n", + part_str, + irq->cmd_cplt, + irq->fiq, + irq->rx_hdrs, + irq->rx_cmplt, + irq->rx_mem_of, + irq->rx_rdys, + irq->irqs, + irq->tx_procs, + irq->decrypt_done, + irq->dma_0_done, + irq->dma_1_done, + irq->tx_exch_complet, + irq->commands, + irq->rx_procs, + irq->hw_pm_mode_changes, + irq->host_acks, + irq->pci_pm, + irq->acm_wakeups); + + part_str = "WEP"; + + if (st == st_end) + goto fw_stats_end; + + wep = (fw_stats_wep_t *)st; + partlen = sizeof(fw_stats_wep_t); + st += partlen; + + if ( + (IS_PCI(adev) && IS_ACX100(adev)) + || (IS_USB(adev) && IS_ACX100(adev)) + ) { + /* at least ACX100 PCI F/W 1.9.8.b + * and ACX100 USB F/W 1.0.7-USB + * don't have those two fields... */ + st -= 2*sizeof(u32); + if (st > st_end) + goto fw_stats_fail; + temp1 = temp2 = 999999999; + } else { + if (st > st_end) + goto fw_stats_fail; + temp1 = wep->wep_pkt_decrypt; + temp2 = wep->wep_decrypt_irqs; + } + + p += sprintf(p, + "%s:\n" + " wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n" + " wep_key_not_found %u, wep_decrypt_fail %u\n" + " wep_pkt_decrypt %u, wep_decrypt_irqs %u\n", + part_str, + wep->wep_key_count, + wep->wep_default_key_count, + wep->dot11_def_key_mib, + wep->wep_key_not_found, + wep->wep_decrypt_fail, + temp1, + temp2); + + part_str = "power"; + + if (st == st_end) + goto fw_stats_end; + + pwr = (fw_stats_pwr_t *)st; + partlen = sizeof(fw_stats_pwr_t); + st += partlen; + + if (st > st_end) + goto fw_stats_fail; + + p += sprintf(p, + "%s:\n" + " tx_start_ctr %u, no_ps_tx_too_short %u\n" + " rx_start_ctr %u, no_ps_rx_too_short %u\n" + " lppd_started %u\n" + " no_lppd_too_noisy %u, no_lppd_too_short %u, no_lppd_matching_frame %u\n", + part_str, + pwr->tx_start_ctr, + pwr->no_ps_tx_too_short, + pwr->rx_start_ctr, + pwr->no_ps_rx_too_short, + pwr->lppd_started, + pwr->no_lppd_too_noisy, + pwr->no_lppd_too_short, + pwr->no_lppd_matching_frame); + + part_str = "MIC"; + + if (st == st_end) + goto fw_stats_end; + + mic = (fw_stats_mic_t *)st; + partlen = sizeof(fw_stats_mic_t); + st += partlen; + + if (st > st_end) + goto fw_stats_fail; + + p += sprintf(p, + "%s:\n" + " mic_rx_pkts %u, mic_calc_fail %u\n", + part_str, + mic->mic_rx_pkts, + mic->mic_calc_fail); + + part_str = "AES"; + + if (st == st_end) + goto fw_stats_end; + + aes = (fw_stats_aes_t *)st; + partlen = sizeof(fw_stats_aes_t); + st += partlen; + + if (st > st_end) + goto fw_stats_fail; + + p += sprintf(p, + "%s:\n" + " aes_enc_fail %u, aes_dec_fail %u\n" + " aes_enc_pkts %u, aes_dec_pkts %u\n" + " aes_enc_irq %u, aes_dec_irq %u\n", + part_str, + aes->aes_enc_fail, + aes->aes_dec_fail, + aes->aes_enc_pkts, + aes->aes_dec_pkts, + aes->aes_enc_irq, + aes->aes_dec_irq); + + part_str = "event"; + + if (st == st_end) + goto fw_stats_end; + + evt = (fw_stats_event_t *)st; + partlen = sizeof(fw_stats_event_t); + st += partlen; + + if (st > st_end) + goto fw_stats_fail; + + p += sprintf(p, + "%s:\n" + " heartbeat %u, calibration %u\n" + " rx_mismatch %u, rx_mem_empty %u, rx_pool %u\n" + " oom_late %u\n" + " phy_tx_err %u, tx_stuck %u\n", + part_str, + evt->heartbeat, + evt->calibration, + evt->rx_mismatch, + evt->rx_mem_empty, + evt->rx_pool, + evt->oom_late, + evt->phy_tx_err, + evt->tx_stuck); + + if (st < st_end) + goto fw_stats_bigger; + + goto fw_stats_end; + +fw_stats_fail: + st -= partlen; + p += sprintf(p, + "failed at %s part (size %u), offset %lu (struct size %u), " + "please report\n", part_str, partlen, + (unsigned long)st - (unsigned long)fw_stats, len); + +fw_stats_bigger: + for (; st < st_end; st += 4) + p += sprintf(p, + "UNKN%3lu: %u\n", (unsigned long)st - (unsigned long)fw_stats, *(u32 *)st); + +fw_stats_end: + kfree(fw_stats); + + FN_EXIT1(p - buf); + return p - buf; +} + + +/*********************************************************************** +*/ +static int +acx_s_proc_phy_output(char *buf, acx_device_t *adev) +{ + char *p = buf; + int i; + + FN_ENTER; + + /* + if (RADIO_RFMD_11 != adev->radio_type) { + printk("sorry, not yet adapted for radio types " + "other than RFMD, please verify " + "PHY size etc. first!\n"); + goto end; + } + */ + + /* The PHY area is only 0x80 bytes long; further pages after that + * only have some page number registers with altered value, + * all other registers remain the same. */ + for (i = 0; i < 0x80; i++) { + acx_s_read_phy_reg(adev, i, p++); + } + + FN_EXIT1(p - buf); + return p - buf; +} + + +/*********************************************************************** +** acx_e_read_proc_XXXX +** Handle our /proc entry +** +** Arguments: +** standard kernel read_proc interface +** Returns: +** number of bytes written to buf +** Side effects: +** none +*/ +static int +acx_e_read_proc(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + acx_device_t *adev = (acx_device_t*)data; + unsigned long flags; + int length; + + FN_ENTER; + + acx_sem_lock(adev); + acx_lock(adev, flags); + /* fill buf */ + length = acx_l_proc_output(buf, adev); + acx_unlock(adev, flags); + acx_sem_unlock(adev); + + /* housekeeping */ + if (length <= offset + count) + *eof = 1; + *start = buf + offset; + length -= offset; + if (length > count) + length = count; + if (length < 0) + length = 0; + FN_EXIT1(length); + return length; +} + +static int +acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + acx_device_t *adev = (acx_device_t*)data; + int length; + + FN_ENTER; + + acx_sem_lock(adev); + /* fill buf */ + length = acx_s_proc_diag_output(buf, adev); + acx_sem_unlock(adev); + + /* housekeeping */ + if (length <= offset + count) + *eof = 1; + *start = buf + offset; + length -= offset; + if (length > count) + length = count; + if (length < 0) + length = 0; + FN_EXIT1(length); + return length; +} + +static int +acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + acx_device_t *adev = (acx_device_t*)data; + int length; + + FN_ENTER; + + /* fill buf */ + length = 0; + if (IS_PCI(adev)) { + acx_sem_lock(adev); + length = acxpci_proc_eeprom_output(buf, adev); + acx_sem_unlock(adev); + } + + /* housekeeping */ + if (length <= offset + count) + *eof = 1; + *start = buf + offset; + length -= offset; + if (length > count) + length = count; + if (length < 0) + length = 0; + FN_EXIT1(length); + return length; +} + +static int +acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + acx_device_t *adev = (acx_device_t*)data; + int length; + + FN_ENTER; + + acx_sem_lock(adev); + /* fill buf */ + length = acx_s_proc_phy_output(buf, adev); + acx_sem_unlock(adev); + + /* housekeeping */ + if (length <= offset + count) + *eof = 1; + *start = buf + offset; + length -= offset; + if (length > count) + length = count; + if (length < 0) + length = 0; + FN_EXIT1(length); + return length; +} + + +/*********************************************************************** +** /proc files registration +*/ +static const char * const +proc_files[] = { "", "_diag", "_eeprom", "_phy" }; + +static read_proc_t * const +proc_funcs[] = { + acx_e_read_proc, + acx_e_read_proc_diag, + acx_e_read_proc_eeprom, + acx_e_read_proc_phy +}; + +static int +manage_proc_entries(const struct net_device *ndev, int remove) +{ + acx_device_t *adev = ndev2adev((struct net_device *)ndev); + char procbuf[80]; + int i; + + for (i = 0; i < VEC_SIZE(proc_files); i++) { + snprintf(procbuf, sizeof(procbuf), + "driver/acx_%s%s", ndev->name, proc_files[i]); + log(L_INIT, "%sing /proc entry %s\n", + remove ? "remov" : "creat", procbuf); + if (!remove) { + if (!create_proc_read_entry(procbuf, 0, 0, proc_funcs[i], adev)) { + printk("acx: cannot register /proc entry %s\n", procbuf); + return NOT_OK; + } + } else { + remove_proc_entry(procbuf, NULL); + } + } + return OK; +} + +int +acx_proc_register_entries(const struct net_device *ndev) +{ + return manage_proc_entries(ndev, 0); +} + +int +acx_proc_unregister_entries(const struct net_device *ndev) +{ + return manage_proc_entries(ndev, 1); +} +#endif /* CONFIG_PROC_FS */ + + +/*********************************************************************** +** acx_cmd_join_bssid +** +** Common code for both acx100 and acx111. +*/ +/* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */ +static const u8 +bitpos2genframe_txrate[] = { + 10, /* 0. 1 Mbit/s */ + 20, /* 1. 2 Mbit/s */ + 55, /* 2. 5.5 Mbit/s */ + 0x0B, /* 3. 6 Mbit/s */ + 0x0F, /* 4. 9 Mbit/s */ + 110, /* 5. 11 Mbit/s */ + 0x0A, /* 6. 12 Mbit/s */ + 0x0E, /* 7. 18 Mbit/s */ + 220, /* 8. 22 Mbit/s */ + 0x09, /* 9. 24 Mbit/s */ + 0x0D, /* 10. 36 Mbit/s */ + 0x08, /* 11. 48 Mbit/s */ + 0x0C, /* 12. 54 Mbit/s */ + 10, /* 13. 1 Mbit/s, should never happen */ + 10, /* 14. 1 Mbit/s, should never happen */ + 10, /* 15. 1 Mbit/s, should never happen */ +}; + +/* Looks scary, eh? +** Actually, each one compiled into one AND and one SHIFT, +** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */ +static inline unsigned int +rate111to5bits(unsigned int rate) +{ + return (rate & 0x7) + | ( (rate & RATE111_11) / (RATE111_11/JOINBSS_RATES_11) ) + | ( (rate & RATE111_22) / (RATE111_22/JOINBSS_RATES_22) ) + ; +} + +static void +acx_s_cmd_join_bssid(acx_device_t *adev, const u8 *bssid) +{ + acx_joinbss_t tmp; + int dtim_interval; + int i; + + if (mac_is_zero(bssid)) + return; + + FN_ENTER; + + dtim_interval = (ACX_MODE_0_ADHOC == adev->mode) ? + 1 : adev->dtim_interval; + + memset(&tmp, 0, sizeof(tmp)); + + for (i = 0; i < ETH_ALEN; i++) { + tmp.bssid[i] = bssid[ETH_ALEN-1 - i]; + } + + tmp.beacon_interval = cpu_to_le16(adev->beacon_interval); + + /* Basic rate set. Control frame responses (such as ACK or CTS frames) + ** are sent with one of these rates */ + if (IS_ACX111(adev)) { + /* It was experimentally determined that rates_basic + ** can take 11g rates as well, not only rates + ** defined with JOINBSS_RATES_BASIC111_nnn. + ** Just use RATE111_nnn constants... */ + tmp.u.acx111.dtim_interval = dtim_interval; + tmp.u.acx111.rates_basic = cpu_to_le16(adev->rate_basic); + log(L_ASSOC, "rates_basic:%04X, rates_supported:%04X\n", + adev->rate_basic, adev->rate_oper); + } else { + tmp.u.acx100.dtim_interval = dtim_interval; + tmp.u.acx100.rates_basic = rate111to5bits(adev->rate_basic); + tmp.u.acx100.rates_supported = rate111to5bits(adev->rate_oper); + log(L_ASSOC, "rates_basic:%04X->%02X, " + "rates_supported:%04X->%02X\n", + adev->rate_basic, tmp.u.acx100.rates_basic, + adev->rate_oper, tmp.u.acx100.rates_supported); + } + + /* Setting up how Beacon, Probe Response, RTS, and PS-Poll frames + ** will be sent (rate/modulation/preamble) */ + tmp.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(adev->rate_basic)]; + tmp.genfrm_mod_pre = 0; /* FIXME: was = adev->capab_short (which was always 0); */ + /* we can use short pre *if* all peers can understand it */ + /* FIXME #2: we need to correctly set PBCC/OFDM bits here too */ + + /* we switch fw to STA mode in MONITOR mode, it seems to be + ** the only mode where fw does not emit beacons by itself + ** but allows us to send anything (we really want to retain + ** ability to tx arbitrary frames in MONITOR mode) + */ + tmp.macmode = (adev->mode != ACX_MODE_MONITOR ? adev->mode : ACX_MODE_2_STA); + tmp.channel = adev->channel; + tmp.essid_len = adev->essid_len; + /* NOTE: the code memcpy'd essid_len + 1 before, which is WRONG! */ + memcpy(tmp.essid, adev->essid, tmp.essid_len); + acx_s_issue_cmd(adev, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11); + + log(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode); + acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", adev->bssid, "\n"); + + acx_update_capabilities(adev); + FN_EXIT0; +} + + +/*********************************************************************** +** acx_s_cmd_start_scan +** +** Issue scan command to the hardware +** +** unified function for both ACX111 and ACX100 +*/ +static void +acx_s_scan_chan(acx_device_t *adev) +{ + union { + acx111_scan_t acx111; + acx100_scan_t acx100; + } s; + + FN_ENTER; + + memset(&s, 0, sizeof(s)); + + /* first common positions... */ + + s.acx111.count = cpu_to_le16(adev->scan_count); + s.acx111.rate = adev->scan_rate; + s.acx111.options = adev->scan_mode; + s.acx111.chan_duration = cpu_to_le16(adev->scan_duration); + s.acx111.max_probe_delay = cpu_to_le16(adev->scan_probe_delay); + + /* ...then differences */ + + if (IS_ACX111(adev)) { + s.acx111.channel_list_select = 0; /* scan every allowed channel */ + /*s.acx111.channel_list_select = 1;*/ /* scan given channels */ + /*s.acx111.modulation = 0x40;*/ /* long preamble? OFDM? -> only for active scan */ + s.acx111.modulation = 0; + /*s.acx111.channel_list[0] = 6; + s.acx111.channel_list[1] = 4;*/ + } else { + s.acx100.start_chan = cpu_to_le16(1); + s.acx100.flags = cpu_to_le16(0x8000); + } + + acx_s_issue_cmd(adev, ACX1xx_CMD_SCAN, &s, sizeof(s)); + FN_EXIT0; +} + + +void +acx_s_cmd_start_scan(acx_device_t *adev) +{ + /* time_before check is 'just in case' thing */ + if (!(adev->irq_status & HOST_INT_SCAN_COMPLETE) + && time_before(jiffies, adev->scan_start + 10*HZ) + ) { + log(L_INIT, "start_scan: seems like previous scan " + "is still running. Not starting anew. Please report\n"); + return; + } + + log(L_INIT, "starting radio scan\n"); + /* remember that fw is commanded to do scan */ + adev->scan_start = jiffies; + CLEAR_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE); + /* issue it */ + acx_s_scan_chan(adev); +} + + +/*********************************************************************** +** acx111 feature config +*/ +static int +acx111_s_get_feature_config(acx_device_t *adev, + u32 *feature_options, u32 *data_flow_options) +{ + struct acx111_ie_feature_config feat; + + if (!IS_ACX111(adev)) { + return NOT_OK; + } + + memset(&feat, 0, sizeof(feat)); + + if (OK != acx_s_interrogate(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) { + return NOT_OK; + } + log(L_DEBUG, + "got Feature option:0x%X, DataFlow option: 0x%X\n", + feat.feature_options, + feat.data_flow_options); + + if (feature_options) + *feature_options = le32_to_cpu(feat.feature_options); + if (data_flow_options) + *data_flow_options = le32_to_cpu(feat.data_flow_options); + + return OK; +} + +static int +acx111_s_set_feature_config(acx_device_t *adev, + u32 feature_options, u32 data_flow_options, + unsigned int mode /* 0 == remove, 1 == add, 2 == set */) +{ + struct acx111_ie_feature_config feat; + + if (!IS_ACX111(adev)) { + return NOT_OK; + } + + if ((mode < 0) || (mode > 2)) + return NOT_OK; + + if (mode != 2) + /* need to modify old data */ + acx111_s_get_feature_config(adev, &feat.feature_options, &feat.data_flow_options); + else { + /* need to set a completely new value */ + feat.feature_options = 0; + feat.data_flow_options = 0; + } + + if (mode == 0) { /* remove */ + CLEAR_BIT(feat.feature_options, cpu_to_le32(feature_options)); + CLEAR_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options)); + } else { /* add or set */ + SET_BIT(feat.feature_options, cpu_to_le32(feature_options)); + SET_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options)); + } + + log(L_DEBUG, + "old: feature 0x%08X dataflow 0x%08X. mode: %u\n" + "new: feature 0x%08X dataflow 0x%08X\n", + feature_options, data_flow_options, mode, + le32_to_cpu(feat.feature_options), + le32_to_cpu(feat.data_flow_options)); + + if (OK != acx_s_configure(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) { + return NOT_OK; + } + + return OK; +} + +static inline int +acx111_s_feature_off(acx_device_t *adev, u32 f, u32 d) +{ + return acx111_s_set_feature_config(adev, f, d, 0); +} +static inline int +acx111_s_feature_on(acx_device_t *adev, u32 f, u32 d) +{ + return acx111_s_set_feature_config(adev, f, d, 1); +} +static inline int +acx111_s_feature_set(acx_device_t *adev, u32 f, u32 d) +{ + return acx111_s_set_feature_config(adev, f, d, 2); +} + + +/*********************************************************************** +** acx100_s_init_memory_pools +*/ +static int +acx100_s_init_memory_pools(acx_device_t *adev, const acx_ie_memmap_t *mmt) +{ + acx100_ie_memblocksize_t MemoryBlockSize; + acx100_ie_memconfigoption_t MemoryConfigOption; + int TotalMemoryBlocks; + int RxBlockNum; + int TotalRxBlockSize; + int TxBlockNum; + int TotalTxBlockSize; + + FN_ENTER; + + /* Let's see if we can follow this: + first we select our memory block size (which I think is + completely arbitrary) */ + MemoryBlockSize.size = cpu_to_le16(adev->memblocksize); + + /* Then we alert the card to our decision of block size */ + if (OK != acx_s_configure(adev, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) { + goto bad; + } + + /* We figure out how many total blocks we can create, using + the block size we chose, and the beginning and ending + memory pointers, i.e.: end-start/size */ + TotalMemoryBlocks = (le32_to_cpu(mmt->PoolEnd) - le32_to_cpu(mmt->PoolStart)) / adev->memblocksize; + + log(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n", + TotalMemoryBlocks, TotalMemoryBlocks*adev->memblocksize); + + /* MemoryConfigOption.DMA_config bitmask: + access to ACX memory is to be done: + 0x00080000 using PCI conf space?! + 0x00040000 using IO instructions? + 0x00000000 using memory access instructions + 0x00020000 using local memory block linked list (else what?) + 0x00010000 using host indirect descriptors (else host must access ACX memory?) + */ + if (IS_PCI(adev)) { + MemoryConfigOption.DMA_config = cpu_to_le32(0x30000); + /* Declare start of the Rx host pool */ + MemoryConfigOption.pRxHostDesc = cpu2acx(adev->rxhostdesc_startphy); + log(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n", + acx2cpu(MemoryConfigOption.pRxHostDesc), + (long)adev->rxhostdesc_startphy); + } else { + MemoryConfigOption.DMA_config = cpu_to_le32(0x20000); + } + + /* 50% of the allotment of memory blocks go to tx descriptors */ + TxBlockNum = TotalMemoryBlocks / 2; + MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum); + + /* and 50% go to the rx descriptors */ + RxBlockNum = TotalMemoryBlocks - TxBlockNum; + MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum); + + /* size of the tx and rx descriptor queues */ + TotalTxBlockSize = TxBlockNum * adev->memblocksize; + TotalRxBlockSize = RxBlockNum * adev->memblocksize; + log(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u " + "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum, + TotalTxBlockSize, TotalRxBlockSize); + + + /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */ + MemoryConfigOption.rx_mem = + cpu_to_le32((le32_to_cpu(mmt->PoolStart) + 0x1f) & ~0x1f); + + /* align the rx descriptor queue to units of 0x20 + * and offset it by the tx descriptor queue */ + MemoryConfigOption.tx_mem = + cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize + 0x1f) & ~0x1f); + log(L_DEBUG, "rx_mem %08X rx_mem %08X\n", + MemoryConfigOption.tx_mem, MemoryConfigOption.rx_mem); + + /* alert the device to our decision */ + if (OK != acx_s_configure(adev, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) { + goto bad; + } + + /* and tell the device to kick it into gear */ + if (OK != acx_s_issue_cmd(adev, ACX100_CMD_INIT_MEMORY, NULL, 0)) { + goto bad; + } + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +** acx100_s_create_dma_regions +** +** Note that this fn messes up heavily with hardware, but we cannot +** lock it (we need to sleep). Not a problem since IRQs can't happen +*/ +static int +acx100_s_create_dma_regions(acx_device_t *adev) +{ + acx100_ie_queueconfig_t queueconf; + acx_ie_memmap_t memmap; + int res = NOT_OK; + u32 tx_queue_start, rx_queue_start; + + FN_ENTER; + + /* read out the acx100 physical start address for the queues */ + if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) { + goto fail; + } + + tx_queue_start = le32_to_cpu(memmap.QueueStart); + rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t); + + log(L_DEBUG, "initializing Queue Indicator\n"); + + memset(&queueconf, 0, sizeof(queueconf)); + + /* Not needed for PCI, so we can avoid setting them altogether */ + if (IS_USB(adev)) { + queueconf.NumTxDesc = USB_TX_CNT; + queueconf.NumRxDesc = USB_RX_CNT; + } + + /* calculate size of queues */ + queueconf.AreaSize = cpu_to_le32( + TX_CNT * sizeof(txdesc_t) + + RX_CNT * sizeof(rxdesc_t) + 8 + ); + queueconf.NumTxQueues = 1; /* number of tx queues */ + /* sets the beginning of the tx descriptor queue */ + queueconf.TxQueueStart = memmap.QueueStart; + /* done by memset: queueconf.TxQueuePri = 0; */ + queueconf.RxQueueStart = cpu_to_le32(rx_queue_start); + queueconf.QueueOptions = 1; /* auto reset descriptor */ + /* sets the end of the rx descriptor queue */ + queueconf.QueueEnd = cpu_to_le32( + rx_queue_start + RX_CNT * sizeof(rxdesc_t) + ); + /* sets the beginning of the next queue */ + queueconf.HostQueueEnd = cpu_to_le32(le32_to_cpu(queueconf.QueueEnd) + 8); + if (OK != acx_s_configure(adev, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) { + goto fail; + } + + if (IS_PCI(adev)) { + /* sets the beginning of the rx descriptor queue, after the tx descrs */ + if (OK != acxpci_s_create_hostdesc_queues(adev)) + goto fail; + acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start); + } + + if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) { + goto fail; + } + + memmap.PoolStart = cpu_to_le32( + (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f + ); + + if (OK != acx_s_configure(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) { + goto fail; + } + + if (OK != acx100_s_init_memory_pools(adev, &memmap)) { + goto fail; + } + + res = OK; + goto end; + +fail: + acx_s_msleep(1000); /* ? */ + if (IS_PCI(adev)) + acxpci_free_desc_queues(adev); +end: + FN_EXIT1(res); + return res; +} + + +/*********************************************************************** +** acx111_s_create_dma_regions +** +** Note that this fn messes heavily with hardware, but we cannot +** lock it (we need to sleep). Not a problem since IRQs can't happen +*/ +#define ACX111_PERCENT(percent) ((percent)/5) + +static int +acx111_s_create_dma_regions(acx_device_t *adev) +{ + struct acx111_ie_memoryconfig memconf; + struct acx111_ie_queueconfig queueconf; + u32 tx_queue_start, rx_queue_start; + + FN_ENTER; + + /* Calculate memory positions and queue sizes */ + + /* Set up our host descriptor pool + data pool */ + if (IS_PCI(adev)) { + if (OK != acxpci_s_create_hostdesc_queues(adev)) + goto fail; + } + + memset(&memconf, 0, sizeof(memconf)); + /* the number of STAs (STA contexts) to support + ** NB: was set to 1 and everything seemed to work nevertheless... */ + memconf.no_of_stations = cpu_to_le16(VEC_SIZE(adev->sta_list)); + /* specify the memory block size. Default is 256 */ + memconf.memory_block_size = cpu_to_le16(adev->memblocksize); + /* let's use 50%/50% for tx/rx (specify percentage, units of 5%) */ + memconf.tx_rx_memory_block_allocation = ACX111_PERCENT(50); + /* set the count of our queues + ** NB: struct acx111_ie_memoryconfig shall be modified + ** if we ever will switch to more than one rx and/or tx queue */ + memconf.count_rx_queues = 1; + memconf.count_tx_queues = 1; + /* 0 == Busmaster Indirect Memory Organization, which is what we want + * (using linked host descs with their allocated mem). + * 2 == Generic Bus Slave */ + /* done by memset: memconf.options = 0; */ + /* let's use 25% for fragmentations and 75% for frame transfers + * (specified in units of 5%) */ + memconf.fragmentation = ACX111_PERCENT(75); + /* Rx descriptor queue config */ + memconf.rx_queue1_count_descs = RX_CNT; + memconf.rx_queue1_type = 7; /* must be set to 7 */ + /* done by memset: memconf.rx_queue1_prio = 0; low prio */ + if (IS_PCI(adev)) { + memconf.rx_queue1_host_rx_start = cpu2acx(adev->rxhostdesc_startphy); + } + /* Tx descriptor queue config */ + memconf.tx_queue1_count_descs = TX_CNT; + /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */ + + /* NB1: this looks wrong: (memconf,ACX1xx_IE_QUEUE_CONFIG), + ** (queueconf,ACX1xx_IE_MEMORY_CONFIG_OPTIONS) look swapped, eh? + ** But it is actually correct wrt IE numbers. + ** NB2: sizeof(memconf) == 28 == 0x1c but configure(ACX1xx_IE_QUEUE_CONFIG) + ** writes 0x20 bytes (because same IE for acx100 uses struct acx100_ie_queueconfig + ** which is 4 bytes larger. what a mess. TODO: clean it up) */ + if (OK != acx_s_configure(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG)) { + goto fail; + } + + acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS); + + tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address); + rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address); + + log(L_INIT, "dump queue head (from card):\n" + "len: %u\n" + "tx_memory_block_address: %X\n" + "rx_memory_block_address: %X\n" + "tx1_queue address: %X\n" + "rx1_queue address: %X\n", + le16_to_cpu(queueconf.len), + le32_to_cpu(queueconf.tx_memory_block_address), + le32_to_cpu(queueconf.rx_memory_block_address), + tx_queue_start, + rx_queue_start); + + if (IS_PCI(adev)) + acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start); + + FN_EXIT1(OK); + return OK; +fail: + if (IS_PCI(adev)) + acxpci_free_desc_queues(adev); + + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +*/ +static void +acx_s_initialize_rx_config(acx_device_t *adev) +{ + struct { + u16 id; + u16 len; + u16 rx_cfg1; + u16 rx_cfg2; + } ACX_PACKED cfg; + + switch (adev->mode) { + case ACX_MODE_OFF: + adev->rx_config_1 = (u16) (0 + /* | RX_CFG1_INCLUDE_RXBUF_HDR */ + /* | RX_CFG1_FILTER_SSID */ + /* | RX_CFG1_FILTER_BCAST */ + /* | RX_CFG1_RCV_MC_ADDR1 */ + /* | RX_CFG1_RCV_MC_ADDR0 */ + /* | RX_CFG1_FILTER_ALL_MULTI */ + /* | RX_CFG1_FILTER_BSSID */ + /* | RX_CFG1_FILTER_MAC */ + /* | RX_CFG1_RCV_PROMISCUOUS */ + /* | RX_CFG1_INCLUDE_FCS */ + /* | RX_CFG1_INCLUDE_PHY_HDR */ + ); + adev->rx_config_2 = (u16) (0 + /*| RX_CFG2_RCV_ASSOC_REQ */ + /*| RX_CFG2_RCV_AUTH_FRAMES */ + /*| RX_CFG2_RCV_BEACON_FRAMES */ + /*| RX_CFG2_RCV_CONTENTION_FREE */ + /*| RX_CFG2_RCV_CTRL_FRAMES */ + /*| RX_CFG2_RCV_DATA_FRAMES */ + /*| RX_CFG2_RCV_BROKEN_FRAMES */ + /*| RX_CFG2_RCV_MGMT_FRAMES */ + /*| RX_CFG2_RCV_PROBE_REQ */ + /*| RX_CFG2_RCV_PROBE_RESP */ + /*| RX_CFG2_RCV_ACK_FRAMES */ + /*| RX_CFG2_RCV_OTHER */ + ); + break; + case ACX_MODE_MONITOR: + adev->rx_config_1 = (u16) (0 + /* | RX_CFG1_INCLUDE_RXBUF_HDR */ + /* | RX_CFG1_FILTER_SSID */ + /* | RX_CFG1_FILTER_BCAST */ + /* | RX_CFG1_RCV_MC_ADDR1 */ + /* | RX_CFG1_RCV_MC_ADDR0 */ + /* | RX_CFG1_FILTER_ALL_MULTI */ + /* | RX_CFG1_FILTER_BSSID */ + /* | RX_CFG1_FILTER_MAC */ + | RX_CFG1_RCV_PROMISCUOUS + /* | RX_CFG1_INCLUDE_FCS */ + /* | RX_CFG1_INCLUDE_PHY_HDR */ + ); + adev->rx_config_2 = (u16) (0 + | RX_CFG2_RCV_ASSOC_REQ + | RX_CFG2_RCV_AUTH_FRAMES + | RX_CFG2_RCV_BEACON_FRAMES + | RX_CFG2_RCV_CONTENTION_FREE + | RX_CFG2_RCV_CTRL_FRAMES + | RX_CFG2_RCV_DATA_FRAMES + | RX_CFG2_RCV_BROKEN_FRAMES + | RX_CFG2_RCV_MGMT_FRAMES + | RX_CFG2_RCV_PROBE_REQ + | RX_CFG2_RCV_PROBE_RESP + | RX_CFG2_RCV_ACK_FRAMES + | RX_CFG2_RCV_OTHER + ); + break; + default: + adev->rx_config_1 = (u16) (0 + /* | RX_CFG1_INCLUDE_RXBUF_HDR */ + /* | RX_CFG1_FILTER_SSID */ + /* | RX_CFG1_FILTER_BCAST */ + /* | RX_CFG1_RCV_MC_ADDR1 */ + /* | RX_CFG1_RCV_MC_ADDR0 */ + /* | RX_CFG1_FILTER_ALL_MULTI */ + /* | RX_CFG1_FILTER_BSSID */ + | RX_CFG1_FILTER_MAC + /* | RX_CFG1_RCV_PROMISCUOUS */ + /* | RX_CFG1_INCLUDE_FCS */ + /* | RX_CFG1_INCLUDE_PHY_HDR */ + ); + adev->rx_config_2 = (u16) (0 + | RX_CFG2_RCV_ASSOC_REQ + | RX_CFG2_RCV_AUTH_FRAMES + | RX_CFG2_RCV_BEACON_FRAMES + | RX_CFG2_RCV_CONTENTION_FREE + | RX_CFG2_RCV_CTRL_FRAMES + | RX_CFG2_RCV_DATA_FRAMES + /*| RX_CFG2_RCV_BROKEN_FRAMES */ + | RX_CFG2_RCV_MGMT_FRAMES + | RX_CFG2_RCV_PROBE_REQ + | RX_CFG2_RCV_PROBE_RESP + /*| RX_CFG2_RCV_ACK_FRAMES */ + | RX_CFG2_RCV_OTHER + ); + break; + } + adev->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR; + + if ((adev->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR) + || (adev->firmware_numver >= 0x02000000)) + adev->phy_header_len = IS_ACX111(adev) ? 8 : 4; + else + adev->phy_header_len = 0; + + log(L_INIT, "setting RXconfig to %04X:%04X\n", + adev->rx_config_1, adev->rx_config_2); + cfg.rx_cfg1 = cpu_to_le16(adev->rx_config_1); + cfg.rx_cfg2 = cpu_to_le16(adev->rx_config_2); + acx_s_configure(adev, &cfg, ACX1xx_IE_RXCONFIG); +} + + +/*********************************************************************** +** acx_s_set_defaults +*/ +void +acx_s_set_defaults(acx_device_t *adev) +{ + unsigned long flags; + + FN_ENTER; + + /* do it before getting settings, prevent bogus channel 0 warning */ + adev->channel = 1; + + /* query some settings from the card. + * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial + * query is REQUIRED, otherwise the card won't work correctly! */ + adev->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN; + /* Only ACX100 supports ED and CCA */ + if (IS_ACX100(adev)) + adev->get_mask |= GETSET_CCA|GETSET_ED_THRESH; + + acx_s_update_card_settings(adev); + + acx_lock(adev, flags); + + /* set our global interrupt mask */ + if (IS_PCI(adev)) + acxpci_set_interrupt_mask(adev); + + adev->led_power = 1; /* LED is active on startup */ + adev->brange_max_quality = 60; /* LED blink max quality is 60 */ + adev->brange_time_last_state_change = jiffies; + + /* copy the MAC address we just got from the card + * into our MAC address used during current 802.11 session */ + MAC_COPY(adev->dev_addr, adev->ndev->dev_addr); + MAC_BCAST(adev->ap); + + adev->essid_len = + snprintf(adev->essid, sizeof(adev->essid), "STA%02X%02X%02X", + adev->dev_addr[3], adev->dev_addr[4], adev->dev_addr[5]); + adev->essid_active = 1; + + /* we have a nick field to waste, so why not abuse it + * to announce the driver version? ;-) */ + strncpy(adev->nick, "acx " ACX_RELEASE, IW_ESSID_MAX_SIZE); + + if (IS_PCI(adev)) { /* FIXME: this should be made to apply to USB, too! */ + /* first regulatory domain entry in EEPROM == default reg. domain */ + adev->reg_dom_id = adev->cfgopt_domains.list[0]; + } + + /* 0xffff would be better, but then we won't get a "scan complete" + * interrupt, so our current infrastructure will fail: */ + adev->scan_count = 1; + adev->scan_mode = ACX_SCAN_OPT_ACTIVE; + adev->scan_duration = 100; + adev->scan_probe_delay = 200; + /* reported to break scanning: adev->scan_probe_delay = adev->cfgopt_probe_delay; */ + adev->scan_rate = ACX_SCAN_RATE_1; + + adev->mode = ACX_MODE_2_STA; + adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM; + adev->listen_interval = 100; + adev->beacon_interval = DEFAULT_BEACON_INTERVAL; + adev->dtim_interval = DEFAULT_DTIM_INTERVAL; + + adev->msdu_lifetime = DEFAULT_MSDU_LIFETIME; + + adev->rts_threshold = DEFAULT_RTS_THRESHOLD; + adev->frag_threshold = 2346; + + /* use standard default values for retry limits */ + adev->short_retry = 7; /* max. retries for (short) non-RTS packets */ + adev->long_retry = 4; /* max. retries for long (RTS) packets */ + + adev->preamble_mode = 2; /* auto */ + adev->fallback_threshold = 3; + adev->stepup_threshold = 10; + adev->rate_bcast = RATE111_1; + adev->rate_bcast100 = RATE100_1; + adev->rate_basic = RATE111_1 | RATE111_2; + adev->rate_auto = 1; + if (IS_ACX111(adev)) { + adev->rate_oper = RATE111_ALL; + } else { + adev->rate_oper = RATE111_ACX100_COMPAT; + } + + /* Supported Rates element - the rates here are given in units of + * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */ + acx_l_update_ratevector(adev); + + /* set some more defaults */ + if (IS_ACX111(adev)) { + /* 30mW (15dBm) is default, at least in my acx111 card: */ + adev->tx_level_dbm = 15; + } else { + /* don't use max. level, since it might be dangerous + * (e.g. WRT54G people experience + * excessive Tx power damage!) */ + adev->tx_level_dbm = 18; + } + /* adev->tx_level_auto = 1; */ + if (IS_ACX111(adev)) { + /* start with sensitivity level 1 out of 3: */ + adev->sensitivity = 1; + } + +/* #define ENABLE_POWER_SAVE */ +#ifdef ENABLE_POWER_SAVE + adev->ps_wakeup_cfg = PS_CFG_ENABLE | PS_CFG_WAKEUP_ALL_BEAC; + adev->ps_listen_interval = 1; + adev->ps_options = PS_OPT_ENA_ENHANCED_PS | PS_OPT_TX_PSPOLL | PS_OPT_STILL_RCV_BCASTS; + adev->ps_hangover_period = 30; + adev->ps_enhanced_transition_time = 0; +#else + adev->ps_wakeup_cfg = 0; + adev->ps_listen_interval = 0; + adev->ps_options = 0; + adev->ps_hangover_period = 0; + adev->ps_enhanced_transition_time = 0; +#endif + + /* These settings will be set in fw on ifup */ + adev->set_mask = 0 + | GETSET_RETRY + | SET_MSDU_LIFETIME + /* configure card to do rate fallback when in auto rate mode */ + | SET_RATE_FALLBACK + | SET_RXCONFIG + | GETSET_TXPOWER + /* better re-init the antenna value we got above */ + | GETSET_ANTENNA +#if POWER_SAVE_80211 + | GETSET_POWER_80211 +#endif + ; + + acx_unlock(adev, flags); + acx_lock_unhold(); /* hold time 844814 CPU ticks @2GHz */ + + acx_s_initialize_rx_config(adev); + + FN_EXIT0; +} + + +/*********************************************************************** +** FIXME: this should be solved in a general way for all radio types +** by decoding the radio firmware module, +** since it probably has some standard structure describing how to +** set the power level of the radio module which it controls. +** Or maybe not, since the radio module probably has a function interface +** instead which then manages Tx level programming :-\ +*/ +static int +acx111_s_set_tx_level(acx_device_t *adev, u8 level_dbm) +{ + struct acx111_ie_tx_level tx_level; + + /* my acx111 card has two power levels in its configoptions (== EEPROM): + * 1 (30mW) [15dBm] + * 2 (10mW) [10dBm] + * For now, just assume all other acx111 cards have the same. + * FIXME: Ideally we would query it here, but we first need a + * standard way to query individual configoptions easily. + * Well, now we have proper cfgopt txpower variables, but this still + * hasn't been done yet, since it also requires dBm <-> mW conversion here... */ + if (level_dbm <= 12) { + tx_level.level = 2; /* 10 dBm */ + adev->tx_level_dbm = 10; + } else { + tx_level.level = 1; /* 15 dBm */ + adev->tx_level_dbm = 15; + } + if (level_dbm != adev->tx_level_dbm) + log(L_INIT, "acx111 firmware has specific " + "power levels only: adjusted %d dBm to %d dBm!\n", + level_dbm, adev->tx_level_dbm); + + return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL); +} + +static int +acx_s_set_tx_level(acx_device_t *adev, u8 level_dbm) +{ + if (IS_ACX111(adev)) { + return acx111_s_set_tx_level(adev, level_dbm); + } + if (IS_PCI(adev)) { + return acx100pci_s_set_tx_level(adev, level_dbm); + } + return OK; +} + + +/*********************************************************************** +*/ +#ifdef UNUSED +/* Returns the current tx level (ACX111) */ +static u8 +acx111_s_get_tx_level(acx_device_t *adev) +{ + struct acx111_ie_tx_level tx_level; + + tx_level.level = 0; + acx_s_interrogate(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL); + return tx_level.level; +} +#endif + + +/*********************************************************************** +** acx_l_rxmonitor +** Called from IRQ context only +*/ +static void +acx_l_rxmonitor(acx_device_t *adev, const rxbuffer_t *rxbuf) +{ + wlansniffrm_t *msg; + struct sk_buff *skb; + void *datap; + unsigned int skb_len; + int payload_offset; + + FN_ENTER; + + /* we are in big luck: the acx100 doesn't modify any of the fields */ + /* in the 802.11 frame. just pass this packet into the PF_PACKET */ + /* subsystem. yeah. */ + payload_offset = ((u8*)acx_get_wlan_hdr(adev, rxbuf) - (u8*)rxbuf); + skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset; + + /* sanity check */ + if (unlikely(skb_len > WLAN_A4FR_MAXLEN_WEP)) { + printk("%s: monitor mode panic: oversized frame!\n", + adev->ndev->name); + goto end; + } + + if (adev->ndev->type == ARPHRD_IEEE80211_PRISM) + skb_len += sizeof(*msg); + + /* allocate skb */ + skb = dev_alloc_skb(skb_len); + if (unlikely(!skb)) { + printk("%s: no memory for skb (%u bytes)\n", + adev->ndev->name, skb_len); + goto end; + } + + skb_put(skb, skb_len); + + if (adev->ndev->type == ARPHRD_IEEE80211) { + /* when in raw 802.11 mode, just copy frame as-is */ + datap = skb->data; + } else if (adev->ndev->type == ARPHRD_IEEE80211_PRISM) { + /* emulate prism header */ + msg = (wlansniffrm_t*)skb->data; + datap = msg + 1; + + msg->msgcode = WLANSNIFFFRM; + msg->msglen = sizeof(*msg); + strncpy(msg->devname, adev->ndev->name, sizeof(msg->devname)-1); + msg->devname[sizeof(msg->devname)-1] = '\0'; + + msg->hosttime.did = WLANSNIFFFRM_hosttime; + msg->hosttime.status = WLANITEM_STATUS_data_ok; + msg->hosttime.len = 4; + msg->hosttime.data = jiffies; + + msg->mactime.did = WLANSNIFFFRM_mactime; + msg->mactime.status = WLANITEM_STATUS_data_ok; + msg->mactime.len = 4; + msg->mactime.data = rxbuf->time; + + msg->channel.did = WLANSNIFFFRM_channel; + msg->channel.status = WLANITEM_STATUS_data_ok; + msg->channel.len = 4; + msg->channel.data = adev->channel; + + msg->rssi.did = WLANSNIFFFRM_rssi; + msg->rssi.status = WLANITEM_STATUS_no_value; + msg->rssi.len = 4; + msg->rssi.data = 0; + + msg->sq.did = WLANSNIFFFRM_sq; + msg->sq.status = WLANITEM_STATUS_no_value; + msg->sq.len = 4; + msg->sq.data = 0; + + msg->signal.did = WLANSNIFFFRM_signal; + msg->signal.status = WLANITEM_STATUS_data_ok; + msg->signal.len = 4; + msg->signal.data = rxbuf->phy_snr; + + msg->noise.did = WLANSNIFFFRM_noise; + msg->noise.status = WLANITEM_STATUS_data_ok; + msg->noise.len = 4; + msg->noise.data = rxbuf->phy_level; + + msg->rate.did = WLANSNIFFFRM_rate; + msg->rate.status = WLANITEM_STATUS_data_ok; + msg->rate.len = 4; + msg->rate.data = rxbuf->phy_plcp_signal / 5; + + msg->istx.did = WLANSNIFFFRM_istx; + msg->istx.status = WLANITEM_STATUS_data_ok; + msg->istx.len = 4; + msg->istx.data = 0; /* tx=0: it's not a tx packet */ + + skb_len -= sizeof(*msg); + + msg->frmlen.did = WLANSNIFFFRM_signal; + msg->frmlen.status = WLANITEM_STATUS_data_ok; + msg->frmlen.len = 4; + msg->frmlen.data = skb_len; + } else { + printk("acx: unsupported netdev type %d!\n", adev->ndev->type); + dev_kfree_skb(skb); + return; + } + + /* sanity check (keep it here) */ + if (unlikely((int)skb_len < 0)) { + printk("acx: skb_len=%d. Driver bug, please report\n", (int)skb_len); + dev_kfree_skb(skb); + return; + } + memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len); + + skb->dev = adev->ndev; + skb->dev->last_rx = jiffies; + + skb_reset_mac_header(skb); + skb->ip_summed = CHECKSUM_NONE; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_80211_RAW); + netif_rx(skb); + + adev->stats.rx_packets++; + adev->stats.rx_bytes += skb->len; + +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_rx_ieee802_11_frame +** +** Called from IRQ context only +*/ + +/* All these contortions are for saner dup logging +** +** We want: (a) to know about excessive dups +** (b) to not spam kernel log about occasional dups +** +** 1/64 threshold was chosen by running "ping -A" +** It gave "rx: 59 DUPs in 2878 packets" only with 4 parallel +** "ping -A" streams running. */ +/* 2005-10-11: bumped up to 1/8 +** subtract a $smallint from dup_count in order to +** avoid "2 DUPs in 19 packets" messages */ +static inline int +acx_l_handle_dup(acx_device_t *adev, u16 seq) +{ + if (adev->dup_count) { + adev->nondup_count++; + if (time_after(jiffies, adev->dup_msg_expiry)) { + /* Log only if more than 1 dup in 64 packets */ + if (adev->nondup_count/8 < adev->dup_count-5) { + printk(KERN_INFO "%s: rx: %d DUPs in " + "%d packets received in 10 secs\n", + adev->ndev->name, + adev->dup_count, + adev->nondup_count); + } + adev->dup_count = 0; + adev->nondup_count = 0; + } + } + if (unlikely(seq == adev->last_seq_ctrl)) { + if (!adev->dup_count++) + adev->dup_msg_expiry = jiffies + 10*HZ; + adev->stats.rx_errors++; + return 1; /* a dup */ + } + adev->last_seq_ctrl = seq; + return 0; +} + +static int +acx_l_rx_ieee802_11_frame(acx_device_t *adev, rxbuffer_t *rxbuf) +{ + unsigned int ftype, fstype; + const wlan_hdr_t *hdr; + int result = NOT_OK; + + FN_ENTER; + + hdr = acx_get_wlan_hdr(adev, rxbuf); + + /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */ + if (unlikely((hdr->fc & WF_FC_PVERi) != 0)) { + printk_ratelimited(KERN_INFO "rx: unsupported 802.11 protocol\n"); + goto end; + } + + ftype = hdr->fc & WF_FC_FTYPEi; + fstype = hdr->fc & WF_FC_FSTYPEi; + + switch (ftype) { + /* check data frames first, for speed */ + case WF_FTYPE_DATAi: + switch (fstype) { + case WF_FSTYPE_DATAONLYi: + if (acx_l_handle_dup(adev, hdr->seq)) + break; /* a dup, simply discard it */ + + /* TODO: + if (WF_FC_FROMTODSi == (hdr->fc & WF_FC_FROMTODSi)) { + result = acx_l_process_data_frame_wds(adev, rxbuf); + break; + } + */ + + switch (adev->mode) { + case ACX_MODE_3_AP: + result = acx_l_process_data_frame_master(adev, rxbuf); + break; + case ACX_MODE_0_ADHOC: + case ACX_MODE_2_STA: + result = acx_l_process_data_frame_client(adev, rxbuf); + break; + } + case WF_FSTYPE_DATA_CFACKi: + case WF_FSTYPE_DATA_CFPOLLi: + case WF_FSTYPE_DATA_CFACK_CFPOLLi: + case WF_FSTYPE_CFPOLLi: + case WF_FSTYPE_CFACK_CFPOLLi: + /* see above. + acx_process_class_frame(adev, rxbuf, 3); */ + break; + case WF_FSTYPE_NULLi: + /* acx_l_process_NULL_frame(adev, rxbuf, 3); */ + break; + /* FIXME: same here, see above */ + case WF_FSTYPE_CFACKi: + default: + break; + } + break; + case WF_FTYPE_MGMTi: + result = acx_l_process_mgmt_frame(adev, rxbuf); + break; + case WF_FTYPE_CTLi: + if (fstype == WF_FSTYPE_PSPOLLi) + result = OK; + /* this call is irrelevant, since + * acx_process_class_frame is a stub, so return + * immediately instead. + * return acx_process_class_frame(adev, rxbuf, 3); */ + break; + default: + break; + } +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_l_process_rxbuf +** +** NB: used by USB code also +*/ +void +acx_l_process_rxbuf(acx_device_t *adev, rxbuffer_t *rxbuf) +{ + struct wlan_hdr *hdr; + unsigned int qual; + int buf_len; + u16 fc; + + hdr = acx_get_wlan_hdr(adev, rxbuf); + fc = le16_to_cpu(hdr->fc); + /* length of frame from control field to first byte of FCS */ + buf_len = RXBUF_BYTES_RCVD(adev, rxbuf); + + if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON) + || (acx_debug & L_XFER_BEACON) + ) { + log(L_XFER|L_DATA, "rx: %s " + "time:%u len:%u signal:%u SNR:%u macstat:%02X " + "phystat:%02X phyrate:%u status:%u\n", + acx_get_packet_type_string(fc), + le32_to_cpu(rxbuf->time), + buf_len, + acx_signal_to_winlevel(rxbuf->phy_level), + acx_signal_to_winlevel(rxbuf->phy_snr), + rxbuf->mac_status, + rxbuf->phy_stat_baseband, + rxbuf->phy_plcp_signal, + adev->status); + } + + if (unlikely(acx_debug & L_DATA)) { + printk("rx: 802.11 buf[%u]: ", buf_len); + acx_dump_bytes(hdr, buf_len); + } + + /* FIXME: should check for Rx errors (rxbuf->mac_status? + * discard broken packets - but NOT for monitor!) + * and update Rx packet statistics here */ + + if (unlikely(adev->mode == ACX_MODE_MONITOR)) { + acx_l_rxmonitor(adev, rxbuf); + } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) { + acx_l_rx_ieee802_11_frame(adev, rxbuf); + } else { + log(L_DEBUG|L_XFER|L_DATA, + "rx: NOT receiving packet (%s): " + "size too small (%u)\n", + acx_get_packet_type_string(fc), + buf_len); + } + + /* Now check Rx quality level, AFTER processing packet. + * I tried to figure out how to map these levels to dBm + * values, but for the life of me I really didn't + * manage to get it. Either these values are not meant to + * be expressed in dBm, or it's some pretty complicated + * calculation. */ + +#ifdef FROM_SCAN_SOURCE_ONLY + /* only consider packets originating from the MAC + * address of the device that's managing our BSSID. + * Disable it for now, since it removes information (levels + * from different peers) and slows the Rx path. */ + if (adev->ap_client + && mac_is_equal(hdr->a2, adev->ap_client->address)) { +#endif + adev->wstats.qual.level = acx_signal_to_winlevel(rxbuf->phy_level); + adev->wstats.qual.noise = acx_signal_to_winlevel(rxbuf->phy_snr); +#ifndef OLD_QUALITY + qual = acx_signal_determine_quality(adev->wstats.qual.level, + adev->wstats.qual.noise); +#else + qual = (adev->wstats.qual.noise <= 100) ? + 100 - adev->wstats.qual.noise : 0; +#endif + adev->wstats.qual.qual = qual; + adev->wstats.qual.updated = 7; /* all 3 indicators updated */ +#ifdef FROM_SCAN_SOURCE_ONLY + } +#endif +} + + +/*********************************************************************** +** acx_l_handle_txrate_auto +** +** Theory of operation: +** client->rate_cap is a bitmask of rates client is capable of. +** client->rate_cfg is a bitmask of allowed (configured) rates. +** It is set as a result of iwconfig rate N [auto] +** or iwpriv set_rates "N,N,N N,N,N" commands. +** It can be fixed (e.g. 0x0080 == 18Mbit only), +** auto (0x00ff == 18Mbit or any lower value), +** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_). +** +** client->rate_cur is a value for rate111 field in tx descriptor. +** It is always set to txrate_cfg sans zero or more most significant +** bits. This routine handles selection of new rate_cur value depending on +** outcome of last tx event. +** +** client->rate_100 is a precalculated rate value for acx100 +** (we can do without it, but will need to calculate it on each tx). +** +** You cannot configure mixed usage of 5.5 and/or 11Mbit rate +** with PBCC and CCK modulation. Either both at CCK or both at PBCC. +** In theory you can implement it, but so far it is considered not worth doing. +** +** 22Mbit, of course, is PBCC always. */ + +/* maps acx100 tx descr rate field to acx111 one */ +static u16 +rate100to111(u8 r) +{ + switch (r) { + case RATE100_1: return RATE111_1; + case RATE100_2: return RATE111_2; + case RATE100_5: + case (RATE100_5 | RATE100_PBCC511): return RATE111_5; + case RATE100_11: + case (RATE100_11 | RATE100_PBCC511): return RATE111_11; + case RATE100_22: return RATE111_22; + default: + printk("acx: unexpected acx100 txrate: %u! " + "Please report\n", r); + return RATE111_1; + } +} + + +void +acx_l_handle_txrate_auto(acx_device_t *adev, struct client *txc, + u16 cur, u8 rate100, u16 rate111, + u8 error, int pkts_to_ignore) +{ + u16 sent_rate; + int slower_rate_was_used; + + /* vda: hmm. current code will do this: + ** 1. send packets at 11 Mbit, stepup++ + ** 2. will try to send at 22Mbit. hardware will see no ACK, + ** retries at 11Mbit, success. code notes that used rate + ** is lower. stepup = 0, fallback++ + ** 3. repeat step 2 fallback_count times. Fall back to + ** 11Mbit. go to step 1. + ** If stepup_count is large (say, 16) and fallback_count + ** is small (3), this wouldn't be too bad wrt throughput */ + + if (unlikely(!cur)) { + printk("acx: BUG! ratemask is empty\n"); + return; /* or else we may lock up the box */ + } + + /* do some preparations, i.e. calculate the one rate that was + * used to send this packet */ + if (IS_ACX111(adev)) { + sent_rate = 1 << highest_bit(rate111 & RATE111_ALL); + } else { + sent_rate = rate100to111(rate100); + } + /* sent_rate has only one bit set now, corresponding to tx rate + * which was used by hardware to tx this particular packet */ + + /* now do the actual auto rate management */ + log(L_XFER, "tx: %sclient=%p/"MACSTR" used=%04X cur=%04X cfg=%04X " + "__=%u/%u ^^=%u/%u\n", + (txc->ignore_count > 0) ? "[IGN] " : "", + txc, MAC(txc->address), sent_rate, cur, txc->rate_cfg, + txc->fallback_count, adev->fallback_threshold, + txc->stepup_count, adev->stepup_threshold + ); + + /* we need to ignore old packets already in the tx queue since + * they use older rate bytes configured before our last rate change, + * otherwise our mechanism will get confused by interpreting old data. + * Do it after logging above */ + if (txc->ignore_count) { + txc->ignore_count--; + return; + } + + /* true only if the only nonzero bit in sent_rate is + ** less significant than highest nonzero bit in cur */ + slower_rate_was_used = ( cur > ((sent_rate<<1)-1) ); + + if (slower_rate_was_used || error) { + txc->stepup_count = 0; + if (++txc->fallback_count <= adev->fallback_threshold) + return; + txc->fallback_count = 0; + + /* clear highest 1 bit in cur */ + sent_rate = RATE111_54; + while (!(cur & sent_rate)) sent_rate >>= 1; + CLEAR_BIT(cur, sent_rate); + if (!cur) /* we can't disable all rates! */ + cur = sent_rate; + log(L_XFER, "tx: falling back to ratemask %04X\n", cur); + + } else { /* there was neither lower rate nor error */ + txc->fallback_count = 0; + if (++txc->stepup_count <= adev->stepup_threshold) + return; + txc->stepup_count = 0; + + /* Sanitize. Sort of not needed, but I dont trust hw that much... + ** what if it can report bogus tx rates sometimes? */ + while (!(cur & sent_rate)) sent_rate >>= 1; + + /* try to find a higher sent_rate that isn't yet in our + * current set, but is an allowed cfg */ + while (1) { + sent_rate <<= 1; + if (sent_rate > txc->rate_cfg) + /* no higher rates allowed by config */ + return; + if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate)) + /* found */ + break; + /* not found, try higher one */ + } + SET_BIT(cur, sent_rate); + log(L_XFER, "tx: stepping up to ratemask %04X\n", cur); + } + + txc->rate_cur = cur; + txc->ignore_count = pkts_to_ignore; + /* calculate acx100 style rate byte if needed */ + if (IS_ACX100(adev)) { + txc->rate_100 = acx_bitpos2rate100[highest_bit(cur)]; + } +} + + +/*********************************************************************** +** acx_i_start_xmit +** +** Called by network core. Can be called outside of process context. +*/ +int +acx_i_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + acx_device_t *adev = ndev2adev(ndev); + tx_t *tx; + void *txbuf; + unsigned long flags; + int txresult = NOT_OK; + int len; + + FN_ENTER; + + if (unlikely(!skb)) { + /* indicate success */ + txresult = OK; + goto end_no_unlock; + } + if (unlikely(!adev)) { + goto end_no_unlock; + } + + acx_lock(adev, flags); + + if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) { + goto end; + } + if (unlikely(adev->mode == ACX_MODE_OFF)) { + goto end; + } + if (unlikely(acx_queue_stopped(ndev))) { + log(L_DEBUG, "%s: called when queue stopped\n", __func__); + goto end; + } + if (unlikely(ACX_STATUS_4_ASSOCIATED != adev->status)) { + log(L_XFER, "trying to xmit, but not associated yet: " + "aborting...\n"); + /* silently drop the packet, since we're not connected yet */ + txresult = OK; + /* ...but indicate an error nevertheless */ + adev->stats.tx_errors++; + goto end; + } + + tx = acx_l_alloc_tx(adev); + if (unlikely(!tx)) { + printk_ratelimited("%s: start_xmit: txdesc ring is full, " + "dropping tx\n", ndev->name); + txresult = NOT_OK; + goto end; + } + + txbuf = acx_l_get_txbuf(adev, tx); + if (unlikely(!txbuf)) { + /* Card was removed */ + txresult = NOT_OK; + acx_l_dealloc_tx(adev, tx); + goto end; + } + len = acx_ether_to_txbuf(adev, txbuf, skb); + if (unlikely(len < 0)) { + /* Error in packet conversion */ + txresult = NOT_OK; + acx_l_dealloc_tx(adev, tx); + goto end; + } + acx_l_tx_data(adev, tx, len); + ndev->trans_start = jiffies; + + txresult = OK; + adev->stats.tx_packets++; + adev->stats.tx_bytes += skb->len; + +end: + acx_unlock(adev, flags); + +end_no_unlock: + if ((txresult == OK) && skb) + dev_kfree_skb_any(skb); + + FN_EXIT1(txresult); + return txresult; +} + + +/*********************************************************************** +** acx_l_update_ratevector +** +** Updates adev->rate_supported[_len] according to rate_{basic,oper} +*/ +const u8 +acx_bitpos2ratebyte[] = { + DOT11RATEBYTE_1, + DOT11RATEBYTE_2, + DOT11RATEBYTE_5_5, + DOT11RATEBYTE_6_G, + DOT11RATEBYTE_9_G, + DOT11RATEBYTE_11, + DOT11RATEBYTE_12_G, + DOT11RATEBYTE_18_G, + DOT11RATEBYTE_22, + DOT11RATEBYTE_24_G, + DOT11RATEBYTE_36_G, + DOT11RATEBYTE_48_G, + DOT11RATEBYTE_54_G, +}; + +void +acx_l_update_ratevector(acx_device_t *adev) +{ + u16 bcfg = adev->rate_basic; + u16 ocfg = adev->rate_oper; + u8 *supp = adev->rate_supported; + const u8 *dot11 = acx_bitpos2ratebyte; + + FN_ENTER; + + while (ocfg) { + if (ocfg & 1) { + *supp = *dot11; + if (bcfg & 1) { + *supp |= 0x80; + } + supp++; + } + dot11++; + ocfg >>= 1; + bcfg >>= 1; + } + adev->rate_supported_len = supp - adev->rate_supported; + if (acx_debug & L_ASSOC) { + printk("new ratevector: "); + acx_dump_bytes(adev->rate_supported, adev->rate_supported_len); + } + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_sta_list_init +*/ +static void +acx_l_sta_list_init(acx_device_t *adev) +{ + FN_ENTER; + memset(adev->sta_hash_tab, 0, sizeof(adev->sta_hash_tab)); + memset(adev->sta_list, 0, sizeof(adev->sta_list)); + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_sta_list_get_from_hash +*/ +static inline client_t* +acx_l_sta_list_get_from_hash(acx_device_t *adev, const u8 *address) +{ + return adev->sta_hash_tab[address[5] % VEC_SIZE(adev->sta_hash_tab)]; +} + + +/*********************************************************************** +** acx_l_sta_list_get +*/ +client_t* +acx_l_sta_list_get(acx_device_t *adev, const u8 *address) +{ + client_t *client; + FN_ENTER; + client = acx_l_sta_list_get_from_hash(adev, address); + while (client) { + if (mac_is_equal(address, client->address)) { + client->mtime = jiffies; + break; + } + client = client->next; + } + FN_EXIT0; + return client; +} + + +/*********************************************************************** +** acx_l_sta_list_del +*/ +void +acx_l_sta_list_del(acx_device_t *adev, client_t *victim) +{ + client_t *client, *next; + + client = acx_l_sta_list_get_from_hash(adev, victim->address); + next = client; + /* tricky. next = client on first iteration only, + ** on all other iters next = client->next */ + while (next) { + if (next == victim) { + client->next = victim->next; + /* Overkill */ + memset(victim, 0, sizeof(*victim)); + break; + } + client = next; + next = client->next; + } +} + + +/*********************************************************************** +** acx_l_sta_list_alloc +** +** Never fails - will evict oldest client if needed +*/ +static client_t* +acx_l_sta_list_alloc(acx_device_t *adev) +{ + int i; + unsigned long age, oldest_age; + client_t *client, *oldest; + + FN_ENTER; + + oldest = &adev->sta_list[0]; + oldest_age = 0; + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + client = &adev->sta_list[i]; + + if (!client->used) { + goto found; + } else { + age = jiffies - client->mtime; + if (oldest_age < age) { + oldest_age = age; + oldest = client; + } + } + } + acx_l_sta_list_del(adev, oldest); + client = oldest; +found: + memset(client, 0, sizeof(*client)); + FN_EXIT0; + return client; +} + + +/*********************************************************************** +** acx_l_sta_list_add +** +** Never fails - will evict oldest client if needed +*/ +/* In case we will reimplement it differently... */ +#define STA_LIST_ADD_CAN_FAIL 0 + +static client_t* +acx_l_sta_list_add(acx_device_t *adev, const u8 *address) +{ + client_t *client; + int index; + + FN_ENTER; + + client = acx_l_sta_list_alloc(adev); + + client->mtime = jiffies; + MAC_COPY(client->address, address); + client->used = CLIENT_EXIST_1; + client->auth_alg = WLAN_AUTH_ALG_SHAREDKEY; + client->auth_step = 1; + /* give some tentative peer rate values + ** (needed because peer may do auth without probing us first, + ** thus we'll have no idea of peer's ratevector yet). + ** Will be overwritten by scanning or assoc code */ + client->rate_cap = adev->rate_basic; + client->rate_cfg = adev->rate_basic; + client->rate_cur = 1 << lowest_bit(adev->rate_basic); + + index = address[5] % VEC_SIZE(adev->sta_hash_tab); + client->next = adev->sta_hash_tab[index]; + adev->sta_hash_tab[index] = client; + + acxlog_mac(L_ASSOC, "sta_list_add: sta=", address, "\n"); + + FN_EXIT0; + return client; +} + + +/*********************************************************************** +** acx_l_sta_list_get_or_add +** +** Never fails - will evict oldest client if needed +*/ +static client_t* +acx_l_sta_list_get_or_add(acx_device_t *adev, const u8 *address) +{ + client_t *client = acx_l_sta_list_get(adev, address); + if (!client) + client = acx_l_sta_list_add(adev, address); + return client; +} + + +/*********************************************************************** +** acx_set_status +** +** This function is called in many atomic regions, must not sleep +** +** This function does not need locking UNLESS you call it +** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can +** wake queue. This can race with stop_queue elsewhere. +** See acx_stop_queue comment. */ +void +acx_set_status(acx_device_t *adev, u16 new_status) +{ +#define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */ + u16 old_status = adev->status; + + FN_ENTER; + + log(L_ASSOC, "%s(%d):%s\n", + __func__, new_status, acx_get_status_name(new_status)); + + /* wireless_send_event never sleeps */ + if (ACX_STATUS_4_ASSOCIATED == new_status) { + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(adev->ndev, SIOCGIWSCAN, &wrqu, NULL); + + wrqu.data.length = 0; + wrqu.data.flags = 0; + MAC_COPY(wrqu.ap_addr.sa_data, adev->bssid); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(adev->ndev, SIOCGIWAP, &wrqu, NULL); + } else { + union iwreq_data wrqu; + + /* send event with empty BSSID to indicate we're not associated */ + MAC_ZERO(wrqu.ap_addr.sa_data); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(adev->ndev, SIOCGIWAP, &wrqu, NULL); + } + + adev->status = new_status; + + switch (new_status) { + case ACX_STATUS_1_SCANNING: + adev->scan_retries = 0; + /* 1.0 s initial scan time */ + acx_set_timer(adev, 1000000); + break; + case ACX_STATUS_2_WAIT_AUTH: + case ACX_STATUS_3_AUTHENTICATED: + adev->auth_or_assoc_retries = 0; + acx_set_timer(adev, 1500000); /* 1.5 s */ + break; + } + +#if QUEUE_OPEN_AFTER_ASSOC + if (new_status == ACX_STATUS_4_ASSOCIATED) { + if (old_status < ACX_STATUS_4_ASSOCIATED) { + /* ah, we're newly associated now, + * so let's indicate carrier */ + acx_carrier_on(adev->ndev, "after association"); + acx_wake_queue(adev->ndev, "after association"); + } + } else { + /* not associated any more, so let's kill carrier */ + if (old_status >= ACX_STATUS_4_ASSOCIATED) { + acx_carrier_off(adev->ndev, "after losing association"); + acx_stop_queue(adev->ndev, "after losing association"); + } + } +#endif + FN_EXIT0; +} + + +/*********************************************************************** +** acx_i_timer +** +** Fires up periodically. Used to kick scan/auth/assoc if something goes wrong +*/ +void +acx_i_timer(unsigned long address) +{ + unsigned long flags; + acx_device_t *adev = (acx_device_t*)address; + + FN_ENTER; + + acx_lock(adev, flags); + + log(L_DEBUG|L_ASSOC, "%s: adev->status=%d (%s)\n", + __func__, adev->status, acx_get_status_name(adev->status)); + + switch (adev->status) { + case ACX_STATUS_1_SCANNING: + /* was set to 0 by set_status() */ + if (++adev->scan_retries < 7) { + acx_set_timer(adev, 1000000); + /* used to interrogate for scan status. + ** We rely on SCAN_COMPLETE IRQ instead */ + log(L_ASSOC, "continuing scan (%d sec)\n", + adev->scan_retries); + } else { + log(L_ASSOC, "stopping scan\n"); + /* send stop_scan cmd when we leave the interrupt context, + * and make a decision what to do next (COMPLETE_SCAN) */ + acx_schedule_task(adev, + ACX_AFTER_IRQ_CMD_STOP_SCAN + ACX_AFTER_IRQ_COMPLETE_SCAN); + } + break; + case ACX_STATUS_2_WAIT_AUTH: + /* was set to 0 by set_status() */ + if (++adev->auth_or_assoc_retries < 10) { + log(L_ASSOC, "resend authen1 request (attempt %d)\n", + adev->auth_or_assoc_retries + 1); + acx_l_transmit_authen1(adev); + } else { + /* time exceeded: fall back to scanning mode */ + log(L_ASSOC, + "authen1 request reply timeout, giving up\n"); + /* we are a STA, need to find AP anyhow */ + acx_set_status(adev, ACX_STATUS_1_SCANNING); + acx_schedule_task(adev, ACX_AFTER_IRQ_RESTART_SCAN); + } + /* used to be 1500000, but some other driver uses 2.5s */ + acx_set_timer(adev, 2500000); + break; + case ACX_STATUS_3_AUTHENTICATED: + /* was set to 0 by set_status() */ + if (++adev->auth_or_assoc_retries < 10) { + log(L_ASSOC, "resend assoc request (attempt %d)\n", + adev->auth_or_assoc_retries + 1); + acx_l_transmit_assoc_req(adev); + } else { + /* time exceeded: give up */ + log(L_ASSOC, + "association request reply timeout, giving up\n"); + /* we are a STA, need to find AP anyhow */ + acx_set_status(adev, ACX_STATUS_1_SCANNING); + acx_schedule_task(adev, ACX_AFTER_IRQ_RESTART_SCAN); + } + acx_set_timer(adev, 2500000); /* see above */ + break; + case ACX_STATUS_4_ASSOCIATED: + default: + break; + } + + acx_unlock(adev, flags); + + FN_EXIT0; +} + + +/*********************************************************************** +** acx_set_timer +** +** Sets the 802.11 state management timer's timeout. +*/ +void +acx_set_timer(acx_device_t *adev, int timeout_us) +{ + FN_ENTER; + + log(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000); + if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) { + printk("attempt to set the timer " + "when the card interface is not up!\n"); + goto end; + } + + /* first check if the timer was already initialized, THEN modify it */ + if (adev->mgmt_timer.function) { + mod_timer(&adev->mgmt_timer, + jiffies + (timeout_us * HZ / 1000000)); + } +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_transmit_assocresp +** +** We are an AP here +*/ +static const u8 +dot11ratebyte[] = { + DOT11RATEBYTE_1, + DOT11RATEBYTE_2, + DOT11RATEBYTE_5_5, + DOT11RATEBYTE_6_G, + DOT11RATEBYTE_9_G, + DOT11RATEBYTE_11, + DOT11RATEBYTE_12_G, + DOT11RATEBYTE_18_G, + DOT11RATEBYTE_22, + DOT11RATEBYTE_24_G, + DOT11RATEBYTE_36_G, + DOT11RATEBYTE_48_G, + DOT11RATEBYTE_54_G, +}; + +static inline int +find_pos(const u8 *p, int size, u8 v) +{ + int i; + for (i = 0; i < size; i++) + if (p[i] == v) + return i; + /* printk a message about strange byte? */ + return 0; +} + +static void +add_bits_to_ratemasks(u8* ratevec, int len, u16* brate, u16* orate) +{ + while (len--) { + int n = 1 << find_pos(dot11ratebyte, + sizeof(dot11ratebyte), *ratevec & 0x7f); + if (*ratevec & 0x80) + *brate |= n; + *orate |= n; + ratevec++; + } +} + +static int +acx_l_transmit_assocresp(acx_device_t *adev, const wlan_fr_assocreq_t *req) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct assocresp_frame_body *body; + u8 *p; + const u8 *da; + /* const u8 *sa; */ + const u8 *bssid; + client_t *clt; + + FN_ENTER; + + /* sa = req->hdr->a1; */ + da = req->hdr->a2; + bssid = req->hdr->a3; + + clt = acx_l_sta_list_get(adev, da); + if (!clt) + goto ok; + + /* Assoc without auth is a big no-no */ + /* Let's be liberal: if already assoc'ed STA sends assoc req again, + ** we won't be rude */ + if (clt->used != CLIENT_AUTHENTICATED_2 + && clt->used != CLIENT_ASSOCIATED_3) { + acx_l_transmit_deauthen(adev, da, WLAN_MGMT_REASON_CLASS2_NONAUTH); + goto bad; + } + + clt->used = CLIENT_ASSOCIATED_3; + + if (clt->aid == 0) + clt->aid = ++adev->aid; + clt->cap_info = ieee2host16(*(req->cap_info)); + + /* We cheat here a bit. We don't really care which rates are flagged + ** as basic by the client, so we stuff them in single ratemask */ + clt->rate_cap = 0; + if (req->supp_rates) + add_bits_to_ratemasks(req->supp_rates->rates, + req->supp_rates->len, &clt->rate_cap, &clt->rate_cap); + if (req->ext_rates) + add_bits_to_ratemasks(req->ext_rates->rates, + req->ext_rates->len, &clt->rate_cap, &clt->rate_cap); + /* We can check that client supports all basic rates, + ** and deny assoc if not. But let's be liberal, right? ;) */ + clt->rate_cfg = clt->rate_cap & adev->rate_oper; + if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(adev->rate_oper); + clt->rate_cur = 1 << lowest_bit(clt->rate_cfg); + if (IS_ACX100(adev)) + clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)]; + clt->fallback_count = clt->stepup_count = 0; + clt->ignore_count = 16; + + tx = acx_l_alloc_tx(adev); + if (!tx) + goto bad; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto bad; + } + body = (void*)(head + 1); + + head->fc = WF_FSTYPE_ASSOCRESPi; + head->dur = req->hdr->dur; + MAC_COPY(head->da, da); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, bssid); + head->seq = req->hdr->seq; + + body->cap_info = host2ieee16(adev->capabilities); + body->status = host2ieee16(0); + body->aid = host2ieee16(clt->aid); + p = wlan_fill_ie_rates((u8*)&body->rates, adev->rate_supported_len, + adev->rate_supported); + p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, + adev->rate_supported); + + acx_l_tx_data(adev, tx, p - (u8*)head); +ok: + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +* acx_l_transmit_reassocresp + +You may be wondering, just like me, what the hell ReAuth is. +In practice it was seen sent by STA when STA feels like losing connection. + +[802.11] + +5.4.2.3 Reassociation + +Association is sufficient for no-transition message delivery between +IEEE 802.11 stations. Additional functionality is needed to support +BSS-transition mobility. The additional required functionality +is provided by the reassociation service. Reassociation is a DSS. +The reassociation service is invoked to 'move' a current association +from one AP to another. This keeps the DS informed of the current +mapping between AP and STA as the station moves from BSS to BSS within +an ESS. Reassociation also enables changing association attributes +of an established association while the STA remains associated with +the same AP. Reassociation is always initiated by the mobile STA. + +5.4.3.1 Authentication +... +A STA may be authenticated with many other STAs at any given instant. + +5.4.3.1.1 Preauthentication + +Because the authentication process could be time-consuming (depending +on the authentication protocol in use), the authentication service can +be invoked independently of the association service. Preauthentication +is typically done by a STA while it is already associated with an AP +(with which it previously authenticated). IEEE 802.11 does not require +that STAs preauthenticate with APs. However, authentication is required +before an association can be established. If the authentication is left +until reassociation time, this may impact the speed with which a STA can +reassociate between APs, limiting BSS-transition mobility performance. +The use of preauthentication takes the authentication service overhead +out of the time-critical reassociation process. + +5.7.3 Reassociation + +For a STA to reassociate, the reassociation service causes the following +message to occur: + + Reassociation request + +* Message type: Management +* Message subtype: Reassociation request +* Information items: + - IEEE address of the STA + - IEEE address of the AP with which the STA will reassociate + - IEEE address of the AP with which the STA is currently associated + - ESSID +* Direction of message: From STA to 'new' AP + +The address of the current AP is included for efficiency. The inclusion +of the current AP address facilitates MAC reassociation to be independent +of the DS implementation. + + Reassociation response +* Message type: Management +* Message subtype: Reassociation response +* Information items: + - Result of the requested reassociation. (success/failure) + - If the reassociation is successful, the response shall include the AID. +* Direction of message: From AP to STA + +7.2.3.6 Reassociation Request frame format + +The frame body of a management frame of subtype Reassociation Request +contains the information shown in Table 9. + +Table 9 Reassociation Request frame body +Order Information +1 Capability information +2 Listen interval +3 Current AP address +4 SSID +5 Supported rates + +7.2.3.7 Reassociation Response frame format + +The frame body of a management frame of subtype Reassociation Response +contains the information shown in Table 10. + +Table 10 Reassociation Response frame body +Order Information +1 Capability information +2 Status code +3 Association ID (AID) +4 Supported rates + +*/ +static int +acx_l_transmit_reassocresp(acx_device_t *adev, const wlan_fr_reassocreq_t *req) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct reassocresp_frame_body *body; + u8 *p; + const u8 *da; + /* const u8 *sa; */ + const u8 *bssid; + client_t *clt; + + FN_ENTER; + + /* sa = req->hdr->a1; */ + da = req->hdr->a2; + bssid = req->hdr->a3; + + /* Must be already authenticated, so it must be in the list */ + clt = acx_l_sta_list_get(adev, da); + if (!clt) + goto ok; + + /* Assoc without auth is a big no-no */ + /* Already assoc'ed STAs sending ReAssoc req are ok per 802.11 */ + if (clt->used != CLIENT_AUTHENTICATED_2 + && clt->used != CLIENT_ASSOCIATED_3) { + acx_l_transmit_deauthen(adev, da, WLAN_MGMT_REASON_CLASS2_NONAUTH); + goto bad; + } + + clt->used = CLIENT_ASSOCIATED_3; + if (clt->aid == 0) { + clt->aid = ++adev->aid; + } + if (req->cap_info) + clt->cap_info = ieee2host16(*(req->cap_info)); + + /* We cheat here a bit. We don't really care which rates are flagged + ** as basic by the client, so we stuff them in single ratemask */ + clt->rate_cap = 0; + if (req->supp_rates) + add_bits_to_ratemasks(req->supp_rates->rates, + req->supp_rates->len, &clt->rate_cap, &clt->rate_cap); + if (req->ext_rates) + add_bits_to_ratemasks(req->ext_rates->rates, + req->ext_rates->len, &clt->rate_cap, &clt->rate_cap); + /* We can check that client supports all basic rates, + ** and deny assoc if not. But let's be liberal, right? ;) */ + clt->rate_cfg = clt->rate_cap & adev->rate_oper; + if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(adev->rate_oper); + clt->rate_cur = 1 << lowest_bit(clt->rate_cfg); + if (IS_ACX100(adev)) + clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)]; + + clt->fallback_count = clt->stepup_count = 0; + clt->ignore_count = 16; + + tx = acx_l_alloc_tx(adev); + if (!tx) + goto ok; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto ok; + } + body = (void*)(head + 1); + + head->fc = WF_FSTYPE_REASSOCRESPi; + head->dur = req->hdr->dur; + MAC_COPY(head->da, da); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, bssid); + head->seq = req->hdr->seq; + + /* IEs: 1. caps */ + body->cap_info = host2ieee16(adev->capabilities); + /* 2. status code */ + body->status = host2ieee16(0); + /* 3. AID */ + body->aid = host2ieee16(clt->aid); + /* 4. supp rates */ + p = wlan_fill_ie_rates((u8*)&body->rates, adev->rate_supported_len, + adev->rate_supported); + /* 5. ext supp rates */ + p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, + adev->rate_supported); + + acx_l_tx_data(adev, tx, p - (u8*)head); +ok: + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +** acx_l_process_disassoc_from_sta +*/ +static void +acx_l_process_disassoc_from_sta(acx_device_t *adev, const wlan_fr_disassoc_t *req) +{ + const u8 *ta; + client_t *clt; + + FN_ENTER; + + ta = req->hdr->a2; + clt = acx_l_sta_list_get(adev, ta); + if (!clt) + goto end; + + if (clt->used != CLIENT_ASSOCIATED_3 + && clt->used != CLIENT_AUTHENTICATED_2) { + /* it's disassociating, but it's + ** not even authenticated! Let it know that */ + acxlog_mac(L_ASSOC|L_XFER, "peer ", ta, "has sent disassoc " + "req but it is not even auth'ed! sending deauth\n"); + acx_l_transmit_deauthen(adev, ta, + WLAN_MGMT_REASON_CLASS2_NONAUTH); + clt->used = CLIENT_EXIST_1; + } else { + /* mark it as auth'ed only */ + clt->used = CLIENT_AUTHENTICATED_2; + } +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_process_deauthen_from_sta +*/ +static void +acx_l_process_deauth_from_sta(acx_device_t *adev, const wlan_fr_deauthen_t *req) +{ + const wlan_hdr_t *hdr; + client_t *client; + + FN_ENTER; + + hdr = req->hdr; + + if (acx_debug & L_ASSOC) { + acx_print_mac("got deauth from sta:", hdr->a2, " "); + acx_print_mac("a1:", hdr->a1, " "); + acx_print_mac("a3:", hdr->a3, " "); + acx_print_mac("adev->addr:", adev->dev_addr, " "); + acx_print_mac("adev->bssid:", adev->bssid, "\n"); + } + + if (!mac_is_equal(adev->dev_addr, hdr->a1)) { + goto end; + } + + client = acx_l_sta_list_get(adev, hdr->a2); + if (!client) { + goto end; + } + client->used = CLIENT_EXIST_1; +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_process_disassoc_from_ap +*/ +static void +acx_l_process_disassoc_from_ap(acx_device_t *adev, const wlan_fr_disassoc_t *req) +{ + FN_ENTER; + + if (!adev->ap_client) { + /* Hrm, we aren't assoc'ed yet anyhow... */ + goto end; + } + + printk("%s: got disassoc frame with reason %d (%s)\n", + adev->ndev->name, *req->reason, + acx_wlan_reason_str(*req->reason)); + + if (mac_is_equal(adev->dev_addr, req->hdr->a1)) { + acx_l_transmit_deauthen(adev, adev->bssid, + WLAN_MGMT_REASON_DEAUTH_LEAVING); + SET_BIT(adev->set_mask, GETSET_RESCAN); + acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG); + } +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_process_deauth_from_ap +*/ +static void +acx_l_process_deauth_from_ap(acx_device_t *adev, const wlan_fr_deauthen_t *req) +{ + FN_ENTER; + + if (!adev->ap_client) { + /* Hrm, we aren't assoc'ed yet anyhow... */ + goto end; + } + + printk("%s: got deauth frame with reason %d (%s)\n", + adev->ndev->name, *req->reason, + acx_wlan_reason_str(*req->reason)); + + /* Chk: is ta verified to be from our AP? */ + if (mac_is_equal(adev->dev_addr, req->hdr->a1)) { + log(L_DEBUG, "AP sent us deauth packet\n"); + SET_BIT(adev->set_mask, GETSET_RESCAN); + acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG); + } +end: + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_rx +** +** The end of the Rx path. Pulls data from a rxhostdesc into a socket +** buffer and feeds it to the network stack via netif_rx(). +*/ +static void +acx_l_rx(acx_device_t *adev, rxbuffer_t *rxbuf) +{ + FN_ENTER; + if (likely(adev->dev_state_mask & ACX_STATE_IFACE_UP)) { + struct sk_buff *skb; + skb = acx_rxbuf_to_ether(adev, rxbuf); + if (likely(skb)) { + netif_rx(skb); + adev->ndev->last_rx = jiffies; + adev->stats.rx_packets++; + adev->stats.rx_bytes += skb->len; + } + } + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_process_data_frame_master +*/ +static int +acx_l_process_data_frame_master(acx_device_t *adev, rxbuffer_t *rxbuf) +{ + struct wlan_hdr *hdr; + struct tx *tx; + void *txbuf; + int len; + int result = NOT_OK; + + FN_ENTER; + + hdr = acx_get_wlan_hdr(adev, rxbuf); + + switch (WF_FC_FROMTODSi & hdr->fc) { + case 0: + case WF_FC_FROMDSi: + log(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n"); + goto done; + case WF_FC_TODSi: + break; + default: /* WF_FC_FROMTODSi */ + log(L_DEBUG, "wds data frame ignored (TODO)\n"); + goto done; + } + + /* check if it is our BSSID, if not, leave */ + if (!mac_is_equal(adev->bssid, hdr->a1)) { + goto done; + } + + if (mac_is_equal(adev->dev_addr, hdr->a3)) { + /* this one is for us */ + acx_l_rx(adev, rxbuf); + } else { + if (mac_is_bcast(hdr->a3)) { + /* this one is bcast, rx it too */ + acx_l_rx(adev, rxbuf); + } + tx = acx_l_alloc_tx(adev); + if (!tx) { + goto fail; + } + /* repackage, tx, and hope it someday reaches its destination */ + /* order is important, we do it in-place */ + MAC_COPY(hdr->a1, hdr->a3); + MAC_COPY(hdr->a3, hdr->a2); + MAC_COPY(hdr->a2, adev->bssid); + /* To_DS = 0, From_DS = 1 */ + hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi; + + txbuf = acx_l_get_txbuf(adev, tx); + if (txbuf) { + len = RXBUF_BYTES_RCVD(adev, rxbuf); + memcpy(txbuf, hdr, len); + acx_l_tx_data(adev, tx, len); + } else { + acx_l_dealloc_tx(adev, tx); + } + } +done: + result = OK; +fail: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_l_process_data_frame_client +*/ +static int +acx_l_process_data_frame_client(acx_device_t *adev, rxbuffer_t *rxbuf) +{ + const u8 *da, *bssid; + const wlan_hdr_t *hdr; + struct net_device *ndev = adev->ndev; + int result = NOT_OK; + + FN_ENTER; + + if (ACX_STATUS_4_ASSOCIATED != adev->status) + goto drop; + + hdr = acx_get_wlan_hdr(adev, rxbuf); + + switch (WF_FC_FROMTODSi & hdr->fc) { + case 0: + if (adev->mode != ACX_MODE_0_ADHOC) { + log(L_DEBUG, "adhoc->adhoc data frame ignored\n"); + goto drop; + } + bssid = hdr->a3; + break; + case WF_FC_FROMDSi: + if (adev->mode != ACX_MODE_2_STA) { + log(L_DEBUG, "ap->sta data frame ignored\n"); + goto drop; + } + bssid = hdr->a2; + break; + case WF_FC_TODSi: + log(L_DEBUG, "sta->ap data frame ignored\n"); + goto drop; + default: /* WF_FC_FROMTODSi: wds->wds */ + log(L_DEBUG, "wds data frame ignored (todo)\n"); + goto drop; + } + + da = hdr->a1; + + if (unlikely(acx_debug & L_DEBUG)) { + acx_print_mac("rx: da=", da, ""); + acx_print_mac(" bssid=", bssid, ""); + acx_print_mac(" adev->bssid=", adev->bssid, ""); + acx_print_mac(" adev->addr=", adev->dev_addr, "\n"); + } + + /* promiscuous mode --> receive all packets */ + if (unlikely(ndev->flags & IFF_PROMISC)) + goto process; + + /* FIRST, check if it is our BSSID */ + if (!mac_is_equal(adev->bssid, bssid)) { + /* is not our BSSID, so bail out */ + goto drop; + } + + /* then, check if it is our address */ + if (mac_is_equal(adev->dev_addr, da)) { + goto process; + } + + /* then, check if it is broadcast */ + if (mac_is_bcast(da)) { + goto process; + } + + if (mac_is_mcast(da)) { + /* unconditionally receive all multicasts */ + if (ndev->flags & IFF_ALLMULTI) + goto process; + + /* FIXME: need to check against the list of + * multicast addresses that are configured + * for the interface (ifconfig) */ + log(L_XFER, "FIXME: multicast packet, need to check " + "against a list of multicast addresses " + "(to be created!); accepting packet for now\n"); + /* for now, just accept it here */ + goto process; + } + + log(L_DEBUG, "rx: foreign packet, dropping\n"); + goto drop; +process: + /* receive packet */ + acx_l_rx(adev, rxbuf); + + result = OK; +drop: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_l_process_mgmt_frame +** +** Theory of operation: mgmt packet gets parsed (to make it easy +** to access variable-sized IEs), results stored in 'parsed'. +** Then we react to the packet. +*/ +typedef union parsed_mgmt_req { + wlan_fr_mgmt_t mgmt; + wlan_fr_assocreq_t assocreq; + wlan_fr_reassocreq_t reassocreq; + wlan_fr_assocresp_t assocresp; + wlan_fr_reassocresp_t reassocresp; + wlan_fr_beacon_t beacon; + wlan_fr_disassoc_t disassoc; + wlan_fr_authen_t authen; + wlan_fr_deauthen_t deauthen; + wlan_fr_proberesp_t proberesp; +} parsed_mgmt_req_t; + +void BUG_excessive_stack_usage(void); + +static int +acx_l_process_mgmt_frame(acx_device_t *adev, rxbuffer_t *rxbuf) +{ + parsed_mgmt_req_t parsed; /* takes ~100 bytes of stack */ + wlan_hdr_t *hdr; + int adhoc, sta_scan, sta, ap; + int len; + + if (sizeof(parsed) > 256) + BUG_excessive_stack_usage(); + + FN_ENTER; + + hdr = acx_get_wlan_hdr(adev, rxbuf); + + /* Management frames never have these set */ + if (WF_FC_FROMTODSi & hdr->fc) { + FN_EXIT1(NOT_OK); + return NOT_OK; + } + + len = RXBUF_BYTES_RCVD(adev, rxbuf); + if (WF_FC_ISWEPi & hdr->fc) + len -= 0x10; + + adhoc = (adev->mode == ACX_MODE_0_ADHOC); + sta_scan = ((adev->mode == ACX_MODE_2_STA) + && (adev->status != ACX_STATUS_4_ASSOCIATED)); + sta = ((adev->mode == ACX_MODE_2_STA) + && (adev->status == ACX_STATUS_4_ASSOCIATED)); + ap = (adev->mode == ACX_MODE_3_AP); + + switch (WF_FC_FSTYPEi & hdr->fc) { + /* beacons first, for speed */ + case WF_FSTYPE_BEACONi: + memset(&parsed.beacon, 0, sizeof(parsed.beacon)); + parsed.beacon.hdr = hdr; + parsed.beacon.len = len; + if (acx_debug & L_DATA) { + printk("beacon len:%d fc:%04X dur:%04X seq:%04X", + len, hdr->fc, hdr->dur, hdr->seq); + acx_print_mac(" a1:", hdr->a1, ""); + acx_print_mac(" a2:", hdr->a2, ""); + acx_print_mac(" a3:", hdr->a3, "\n"); + } + wlan_mgmt_decode_beacon(&parsed.beacon); + /* beacon and probe response are very similar, so... */ + acx_l_process_probe_response(adev, &parsed.beacon, rxbuf); + break; + case WF_FSTYPE_ASSOCREQi: + if (!ap) + break; + memset(&parsed.assocreq, 0, sizeof(parsed.assocreq)); + parsed.assocreq.hdr = hdr; + parsed.assocreq.len = len; + wlan_mgmt_decode_assocreq(&parsed.assocreq); + if (mac_is_equal(hdr->a1, adev->bssid) + && mac_is_equal(hdr->a3, adev->bssid)) { + acx_l_transmit_assocresp(adev, &parsed.assocreq); + } + break; + case WF_FSTYPE_REASSOCREQi: + if (!ap) + break; + memset(&parsed.assocreq, 0, sizeof(parsed.assocreq)); + parsed.assocreq.hdr = hdr; + parsed.assocreq.len = len; + wlan_mgmt_decode_assocreq(&parsed.assocreq); + /* reassocreq and assocreq are equivalent */ + acx_l_transmit_reassocresp(adev, &parsed.reassocreq); + break; + case WF_FSTYPE_ASSOCRESPi: + if (!sta_scan) + break; + memset(&parsed.assocresp, 0, sizeof(parsed.assocresp)); + parsed.assocresp.hdr = hdr; + parsed.assocresp.len = len; + wlan_mgmt_decode_assocresp(&parsed.assocresp); + acx_l_process_assocresp(adev, &parsed.assocresp); + break; + case WF_FSTYPE_REASSOCRESPi: + if (!sta_scan) + break; + memset(&parsed.assocresp, 0, sizeof(parsed.assocresp)); + parsed.assocresp.hdr = hdr; + parsed.assocresp.len = len; + wlan_mgmt_decode_assocresp(&parsed.assocresp); + acx_l_process_reassocresp(adev, &parsed.reassocresp); + break; + case WF_FSTYPE_PROBEREQi: + if (ap || adhoc) { + /* FIXME: since we're supposed to be an AP, + ** we need to return a Probe Response packet. + ** Currently firmware is doing it for us, + ** but firmware is buggy! See comment elsewhere --vda */ + } + break; + case WF_FSTYPE_PROBERESPi: + memset(&parsed.proberesp, 0, sizeof(parsed.proberesp)); + parsed.proberesp.hdr = hdr; + parsed.proberesp.len = len; + wlan_mgmt_decode_proberesp(&parsed.proberesp); + acx_l_process_probe_response(adev, &parsed.proberesp, rxbuf); + break; + case 6: + case 7: + /* exit */ + break; + case WF_FSTYPE_ATIMi: + /* exit */ + break; + case WF_FSTYPE_DISASSOCi: + if (!sta && !ap) + break; + memset(&parsed.disassoc, 0, sizeof(parsed.disassoc)); + parsed.disassoc.hdr = hdr; + parsed.disassoc.len = len; + wlan_mgmt_decode_disassoc(&parsed.disassoc); + if (sta) + acx_l_process_disassoc_from_ap(adev, &parsed.disassoc); + else + acx_l_process_disassoc_from_sta(adev, &parsed.disassoc); + break; + case WF_FSTYPE_AUTHENi: + if (!sta_scan && !ap) + break; + memset(&parsed.authen, 0, sizeof(parsed.authen)); + parsed.authen.hdr = hdr; + parsed.authen.len = len; + wlan_mgmt_decode_authen(&parsed.authen); + acx_l_process_authen(adev, &parsed.authen); + break; + case WF_FSTYPE_DEAUTHENi: + if (!sta && !ap) + break; + memset(&parsed.deauthen, 0, sizeof(parsed.deauthen)); + parsed.deauthen.hdr = hdr; + parsed.deauthen.len = len; + wlan_mgmt_decode_deauthen(&parsed.deauthen); + if (sta) + acx_l_process_deauth_from_ap(adev, &parsed.deauthen); + else + acx_l_process_deauth_from_sta(adev, &parsed.deauthen); + break; + } + + FN_EXIT1(OK); + return OK; +} + + +#ifdef UNUSED +/*********************************************************************** +** acx_process_class_frame +** +** Called from IRQ context only +*/ +static int +acx_process_class_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala) +{ + return OK; +} +#endif + + +/*********************************************************************** +** acx_l_process_NULL_frame +*/ +#ifdef BOGUS_ITS_NOT_A_NULL_FRAME_HANDLER_AT_ALL +static int +acx_l_process_NULL_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala) +{ + const signed char *esi; + const u8 *ebx; + const wlan_hdr_t *hdr; + const client_t *client; + int result = NOT_OK; + + hdr = acx_get_wlan_hdr(adev, rxbuf); + + switch (WF_FC_FROMTODSi & hdr->fc) { + case 0: + esi = hdr->a1; + ebx = hdr->a2; + break; + case WF_FC_FROMDSi: + esi = hdr->a1; + ebx = hdr->a3; + break; + case WF_FC_TODSi: + esi = hdr->a1; + ebx = hdr->a2; + break; + default: /* WF_FC_FROMTODSi */ + esi = hdr->a1; /* added by me! --vda */ + ebx = hdr->a2; + } + + if (esi[0x0] < 0) { + result = OK; + goto done; + } + + client = acx_l_sta_list_get(adev, ebx); + if (client) + result = NOT_OK; + else { +#ifdef IS_IT_BROKEN + log(L_DEBUG|L_XFER, "\n"); + acx_l_transmit_deauthen(adev, ebx, + WLAN_MGMT_REASON_CLASS2_NONAUTH); +#else + log(L_DEBUG, "received NULL frame from unknown client! " + "We really shouldn't send deauthen here, right?\n"); +#endif + result = OK; + } +done: + return result; +} +#endif + + +/*********************************************************************** +** acx_l_process_probe_response +*/ +static int +acx_l_process_probe_response(acx_device_t *adev, wlan_fr_proberesp_t *req, + const rxbuffer_t *rxbuf) +{ + struct client *bss; + wlan_hdr_t *hdr; + + FN_ENTER; + + hdr = req->hdr; + + if (mac_is_equal(hdr->a3, adev->dev_addr)) { + log(L_ASSOC, "huh, scan found our own MAC!?\n"); + goto ok; /* just skip this one silently */ + } + + bss = acx_l_sta_list_get_or_add(adev, hdr->a2); + + /* NB: be careful modifying bss data! It may be one + ** of the already known clients (like our AP if we are a STA) + ** Thus do not blindly modify e.g. current ratemask! */ + + if (STA_LIST_ADD_CAN_FAIL && !bss) { + /* uh oh, we found more sites/stations than we can handle with + * our current setup: pull the emergency brake and stop scanning! */ + acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_STOP_SCAN); + /* TODO: a nice comment what below call achieves --vda */ + acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH); + goto ok; + } + /* NB: get_or_add already filled bss->address = hdr->a2 */ + MAC_COPY(bss->bssid, hdr->a3); + + /* copy the ESSID element */ + if (req->ssid && req->ssid->len <= IW_ESSID_MAX_SIZE) { + bss->essid_len = req->ssid->len; + memcpy(bss->essid, req->ssid->ssid, req->ssid->len); + bss->essid[req->ssid->len] = '\0'; + } else { + /* Either no ESSID IE or oversized one */ + printk("%s: received packet has bogus ESSID\n", + adev->ndev->name); + } + + if (req->ds_parms) + bss->channel = req->ds_parms->curr_ch; + if (req->cap_info) + bss->cap_info = ieee2host16(*req->cap_info); + + bss->sir = acx_signal_to_winlevel(rxbuf->phy_level); + bss->snr = acx_signal_to_winlevel(rxbuf->phy_snr); + + bss->rate_cap = 0; /* operational mask */ + bss->rate_bas = 0; /* basic mask */ + if (req->supp_rates) + add_bits_to_ratemasks(req->supp_rates->rates, + req->supp_rates->len, &bss->rate_bas, &bss->rate_cap); + if (req->ext_rates) + add_bits_to_ratemasks(req->ext_rates->rates, + req->ext_rates->len, &bss->rate_bas, &bss->rate_cap); + /* Fix up any possible bogosity - code elsewhere + * is not expecting empty masks */ + if (!bss->rate_cap) + bss->rate_cap = adev->rate_basic; + if (!bss->rate_bas) + bss->rate_bas = 1 << lowest_bit(bss->rate_cap); + if (!bss->rate_cur) + bss->rate_cur = 1 << lowest_bit(bss->rate_bas); + + /* People moan about this being too noisy at L_ASSOC */ + log(L_DEBUG, + "found %s: ESSID=\"%s\" ch=%d " + "BSSID="MACSTR" caps=0x%04X SIR=%d SNR=%d\n", + (bss->cap_info & WF_MGMT_CAP_IBSS) ? "Ad-Hoc peer" : "AP", + bss->essid, bss->channel, MAC(bss->bssid), bss->cap_info, + bss->sir, bss->snr); +ok: + FN_EXIT0; + return OK; +} + + +/*********************************************************************** +** acx_l_process_assocresp +*/ +static int +acx_l_process_assocresp(acx_device_t *adev, const wlan_fr_assocresp_t *req) +{ + const wlan_hdr_t *hdr; + int res = OK; + + FN_ENTER; + + hdr = req->hdr; + + if ((ACX_MODE_2_STA == adev->mode) + && mac_is_equal(adev->dev_addr, hdr->a1)) { + u16 st = ieee2host16(*(req->status)); + if (WLAN_MGMT_STATUS_SUCCESS == st) { + adev->aid = ieee2host16(*(req->aid)); + /* tell the card we are associated when + ** we are out of interrupt context */ + acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_ASSOCIATE); + } else { + + /* TODO: we shall delete peer from sta_list, and try + ** other candidates... */ + + printk("%s: association FAILED: peer sent " + "Status Code %d (%s)\n", + adev->ndev->name, st, get_status_string(st)); + res = NOT_OK; + } + } + + FN_EXIT1(res); + return res; +} + + +/*********************************************************************** +** acx_l_process_reassocresp +*/ +static int +acx_l_process_reassocresp(acx_device_t *adev, const wlan_fr_reassocresp_t *req) +{ + const wlan_hdr_t *hdr; + int result = NOT_OK; + u16 st; + + FN_ENTER; + + hdr = req->hdr; + + if (!mac_is_equal(adev->dev_addr, hdr->a1)) { + goto end; + } + st = ieee2host16(*(req->status)); + if (st == WLAN_MGMT_STATUS_SUCCESS) { + acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); + result = OK; + } else { + printk("%s: reassociation FAILED: peer sent " + "response code %d (%s)\n", + adev->ndev->name, st, get_status_string(st)); + } +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_l_process_authen +** +** Called only in STA_SCAN or AP mode +*/ +static int +acx_l_process_authen(acx_device_t *adev, const wlan_fr_authen_t *req) +{ + const wlan_hdr_t *hdr; + client_t *clt; + wlan_ie_challenge_t *chal; + u16 alg, seq, status; + int ap, result; + + FN_ENTER; + + hdr = req->hdr; + + if (acx_debug & L_ASSOC) { + acx_print_mac("AUTHEN adev->addr=", adev->dev_addr, " "); + acx_print_mac("a1=", hdr->a1, " "); + acx_print_mac("a2=", hdr->a2, " "); + acx_print_mac("a3=", hdr->a3, " "); + acx_print_mac("adev->bssid=", adev->bssid, "\n"); + } + + if (!mac_is_equal(adev->dev_addr, hdr->a1) + || !mac_is_equal(adev->bssid, hdr->a3)) { + result = OK; + goto end; + } + + alg = ieee2host16(*(req->auth_alg)); + seq = ieee2host16(*(req->auth_seq)); + status = ieee2host16(*(req->status)); + + log(L_ASSOC, "auth algorithm %d, auth sequence %d, status %d\n", alg, seq, status); + + ap = (adev->mode == ACX_MODE_3_AP); + + if (adev->auth_alg <= 1) { + if (adev->auth_alg != alg) { + log(L_ASSOC, "auth algorithm mismatch: " + "our:%d peer:%d\n", adev->auth_alg, alg); + result = NOT_OK; + goto end; + } + } + if (ap) { + clt = acx_l_sta_list_get_or_add(adev, hdr->a2); + if (STA_LIST_ADD_CAN_FAIL && !clt) { + log(L_ASSOC, "could not allocate room for client\n"); + result = NOT_OK; + goto end; + } + } else { + clt = adev->ap_client; + if (!mac_is_equal(clt->address, hdr->a2)) { + printk("%s: malformed auth frame from AP?!\n", + adev->ndev->name); + result = NOT_OK; + goto end; + } + } + + /* now check which step in the authentication sequence we are + * currently in, and act accordingly */ + switch (seq) { + case 1: + if (!ap) + break; + acx_l_transmit_authen2(adev, req, clt); + break; + case 2: + if (ap) + break; + if (status == WLAN_MGMT_STATUS_SUCCESS) { + if (alg == WLAN_AUTH_ALG_OPENSYSTEM) { + acx_set_status(adev, ACX_STATUS_3_AUTHENTICATED); + acx_l_transmit_assoc_req(adev); + } else + if (alg == WLAN_AUTH_ALG_SHAREDKEY) { + acx_l_transmit_authen3(adev, req); + } + } else { + printk("%s: auth FAILED: peer sent " + "response code %d (%s), " + "still waiting for authentication\n", + adev->ndev->name, + status, get_status_string(status)); + acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH); + } + break; + case 3: + if (!ap) + break; + if ((clt->auth_alg != WLAN_AUTH_ALG_SHAREDKEY) + || (alg != WLAN_AUTH_ALG_SHAREDKEY) + || (clt->auth_step != 2)) + break; + chal = req->challenge; + if (!chal + || memcmp(chal->challenge, clt->challenge_text, WLAN_CHALLENGE_LEN) + || (chal->eid != WLAN_EID_CHALLENGE) + || (chal->len != WLAN_CHALLENGE_LEN) + ) + break; + acx_l_transmit_authen4(adev, req); + MAC_COPY(clt->address, hdr->a2); + clt->used = CLIENT_AUTHENTICATED_2; + clt->auth_step = 4; + clt->seq = ieee2host16(hdr->seq); + break; + case 4: + if (ap) + break; + /* ok, we're through: we're authenticated. Woohoo!! */ + acx_set_status(adev, ACX_STATUS_3_AUTHENTICATED); + log(L_ASSOC, "Authenticated!\n"); + /* now that we're authenticated, request association */ + acx_l_transmit_assoc_req(adev); + break; + } + result = OK; +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_gen_challenge +*/ +static inline void +acx_gen_challenge(wlan_ie_challenge_t* d) +{ + FN_ENTER; + d->eid = WLAN_EID_CHALLENGE; + d->len = WLAN_CHALLENGE_LEN; + get_random_bytes(d->challenge, WLAN_CHALLENGE_LEN); + FN_EXIT0; +} + + +/*********************************************************************** +** acx_l_transmit_deauthen +*/ +static int +acx_l_transmit_deauthen(acx_device_t *adev, const u8 *addr, u16 reason) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct deauthen_frame_body *body; + + FN_ENTER; + + tx = acx_l_alloc_tx(adev); + if (!tx) + goto bad; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto bad; + } + body = (void*)(head + 1); + + head->fc = (WF_FTYPE_MGMTi | WF_FSTYPE_DEAUTHENi); + head->dur = 0; + MAC_COPY(head->da, addr); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, adev->bssid); + head->seq = 0; + + log(L_DEBUG|L_ASSOC|L_XFER, + "sending deauthen to "MACSTR" for %d\n", + MAC(addr), reason); + + body->reason = host2ieee16(reason); + + /* body is fixed size here, but beware of cutting-and-pasting this - + ** do not use sizeof(*body) for variable sized mgmt packets! */ + acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + sizeof(*body)); + + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +** acx_l_transmit_authen1 +*/ +static int +acx_l_transmit_authen1(acx_device_t *adev) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct auth_frame_body *body; + + FN_ENTER; + + log(L_ASSOC, "sending authentication1 request (auth algo %d), " + "awaiting response\n", adev->auth_alg); + + tx = acx_l_alloc_tx(adev); + if (!tx) + goto bad; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto bad; + } + body = (void*)(head + 1); + + head->fc = WF_FSTYPE_AUTHENi; + /* duration should be 0 instead of 0x8000 to have + * the firmware calculate the value, right? */ + head->dur = 0; + MAC_COPY(head->da, adev->bssid); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, adev->bssid); + head->seq = 0; + + body->auth_alg = host2ieee16(adev->auth_alg); + body->auth_seq = host2ieee16(1); + body->status = host2ieee16(0); + + acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2); + + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +** acx_l_transmit_authen2 +*/ +static int +acx_l_transmit_authen2(acx_device_t *adev, const wlan_fr_authen_t *req, + client_t *clt) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct auth_frame_body *body; + unsigned int packet_len; + + FN_ENTER; + + if (!clt) + goto ok; + + MAC_COPY(clt->address, req->hdr->a2); +#ifdef UNUSED + clt->ps = ((WF_FC_PWRMGTi & req->hdr->fc) != 0); +#endif + clt->auth_alg = ieee2host16(*(req->auth_alg)); + clt->auth_step = 2; + clt->seq = ieee2host16(req->hdr->seq); + + tx = acx_l_alloc_tx(adev); + if (!tx) + goto bad; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto bad; + } + body = (void*)(head + 1); + + head->fc = WF_FSTYPE_AUTHENi; + head->dur = 0 /* req->hdr->dur */; + MAC_COPY(head->da, req->hdr->a2); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, req->hdr->a3); + head->seq = 0 /* req->hdr->seq */; + + /* already in IEEE format, no endianness conversion */ + body->auth_alg = *(req->auth_alg); + body->auth_seq = host2ieee16(2); + body->status = host2ieee16(0); + + packet_len = WLAN_HDR_A3_LEN + 2 + 2 + 2; + if (ieee2host16(*(req->auth_alg)) == WLAN_AUTH_ALG_OPENSYSTEM) { + clt->used = CLIENT_AUTHENTICATED_2; + } else { /* shared key */ + acx_gen_challenge(&body->challenge); + memcpy(&clt->challenge_text, body->challenge.challenge, WLAN_CHALLENGE_LEN); + packet_len += 2 + 2 + 2 + 1+1+WLAN_CHALLENGE_LEN; + } + + acxlog_mac(L_ASSOC|L_XFER, + "transmit_auth2: BSSID=", head->bssid, "\n"); + + acx_l_tx_data(adev, tx, packet_len); +ok: + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +** acx_l_transmit_authen3 +*/ +static int +acx_l_transmit_authen3(acx_device_t *adev, const wlan_fr_authen_t *req) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct auth_frame_body *body; + unsigned int packet_len; + + FN_ENTER; + + tx = acx_l_alloc_tx(adev); + if (!tx) + goto ok; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto ok; + } + body = (void*)(head + 1); + + /* add WF_FC_ISWEPi: auth step 3 needs to be encrypted */ + head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi; + /* FIXME: is this needed?? authen4 does it... + * I think it's even wrong since we shouldn't re-use old + * values but instead let the firmware calculate proper ones + head->dur = req->hdr->dur; + head->seq = req->hdr->seq; + */ + MAC_COPY(head->da, adev->bssid); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, adev->bssid); + + /* already in IEEE format, no endianness conversion */ + body->auth_alg = *(req->auth_alg); + body->auth_seq = host2ieee16(3); + body->status = host2ieee16(0); + memcpy(&body->challenge, req->challenge, req->challenge->len + 2); + packet_len = WLAN_HDR_A3_LEN + 8 + req->challenge->len; + + log(L_ASSOC|L_XFER, "transmit_authen3!\n"); + + acx_l_tx_data(adev, tx, packet_len); +ok: + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +** acx_l_transmit_authen4 +*/ +static int +acx_l_transmit_authen4(acx_device_t *adev, const wlan_fr_authen_t *req) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct auth_frame_body *body; + + FN_ENTER; + + tx = acx_l_alloc_tx(adev); + if (!tx) + goto ok; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto ok; + } + body = (void*)(head + 1); + + head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */ + head->dur = 0 /* req->hdr->dur */; + MAC_COPY(head->da, req->hdr->a2); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, req->hdr->a3); + head->seq = 0 /* req->hdr->seq */; + + /* already in IEEE format, no endianness conversion */ + body->auth_alg = *(req->auth_alg); + body->auth_seq = host2ieee16(4); + body->status = host2ieee16(0); + + acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2); +ok: + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +** acx_l_transmit_assoc_req +** +** adev->ap_client is a current candidate AP here +*/ +static int +acx_l_transmit_assoc_req(acx_device_t *adev) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + u8 *body, *p, *prate; + unsigned int packet_len; + u16 cap; + + FN_ENTER; + + log(L_ASSOC, "sending association request, " + "awaiting response. NOT ASSOCIATED YET\n"); + tx = acx_l_alloc_tx(adev); + if (!tx) + goto bad; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto bad; + } + body = (void*)(head + 1); + + head->fc = WF_FSTYPE_ASSOCREQi; + head->dur = host2ieee16(0x8000); + MAC_COPY(head->da, adev->bssid); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, adev->bssid); + head->seq = 0; + + p = body; + /* now start filling the AssocReq frame body */ + + /* since this assoc request will most likely only get + * sent in the STA to AP case (and not when Ad-Hoc IBSS), + * the cap combination indicated here will thus be + * WF_MGMT_CAP_ESSi *always* (no IBSS ever) + * The specs are more than non-obvious on all that: + * + * 802.11 7.3.1.4 Capability Information field + ** APs set the ESS subfield to 1 and the IBSS subfield to 0 within + ** Beacon or Probe Response management frames. STAs within an IBSS + ** set the ESS subfield to 0 and the IBSS subfield to 1 in transmitted + ** Beacon or Probe Response management frames + ** + ** APs set the Privacy subfield to 1 within transmitted Beacon, + ** Probe Response, Association Response, and Reassociation Response + ** if WEP is required for all data type frames within the BSS. + ** STAs within an IBSS set the Privacy subfield to 1 in Beacon + ** or Probe Response management frames if WEP is required + ** for all data type frames within the IBSS */ + + /* note that returning 0 will be refused by several APs... + * (so this indicates that you're probably supposed to + * "confirm" the ESS mode) */ + cap = WF_MGMT_CAP_ESSi; + + /* this one used to be a check on wep_restricted, + * but more likely it's wep_enabled instead */ + if (adev->wep_enabled) + SET_BIT(cap, WF_MGMT_CAP_PRIVACYi); + + /* Probably we can just set these always, because our hw is + ** capable of shortpre and PBCC --vda */ + /* only ask for short preamble if the peer station supports it */ + if (adev->ap_client->cap_info & WF_MGMT_CAP_SHORT) + SET_BIT(cap, WF_MGMT_CAP_SHORTi); + /* only ask for PBCC support if the peer station supports it */ + if (adev->ap_client->cap_info & WF_MGMT_CAP_PBCC) + SET_BIT(cap, WF_MGMT_CAP_PBCCi); + + /* IEs: 1. caps */ + *(u16*)p = cap; p += 2; + /* 2. listen interval */ + *(u16*)p = host2ieee16(adev->listen_interval); p += 2; + /* 3. ESSID */ + p = wlan_fill_ie_ssid(p, + strlen(adev->essid_for_assoc), adev->essid_for_assoc); + /* 4. supp rates */ + prate = p; + p = wlan_fill_ie_rates(p, + adev->rate_supported_len, adev->rate_supported); + /* 5. ext supp rates */ + p = wlan_fill_ie_rates_ext(p, + adev->rate_supported_len, adev->rate_supported); + + if (acx_debug & L_DEBUG) { + printk("association: rates element\n"); + acx_dump_bytes(prate, p - prate); + } + + /* calculate lengths */ + packet_len = WLAN_HDR_A3_LEN + (p - body); + + log(L_ASSOC, "association: requesting caps 0x%04X, ESSID \"%s\"\n", + cap, adev->essid_for_assoc); + + acx_l_tx_data(adev, tx, packet_len); + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} + + +/*********************************************************************** +** acx_l_transmit_disassoc +** +** FIXME: looks like incomplete implementation of a helper: +** acx_l_transmit_disassoc(adev, clt) - kick this client (we're an AP) +** acx_l_transmit_disassoc(adev, NULL) - leave BSSID (we're a STA) +*/ +#ifdef BROKEN +int +acx_l_transmit_disassoc(acx_device_t *adev, client_t *clt) +{ + struct tx *tx; + struct wlan_hdr_mgmt *head; + struct disassoc_frame_body *body; + + FN_ENTER; +/* if (clt != NULL) { */ + tx = acx_l_alloc_tx(adev); + if (!tx) + goto bad; + head = acx_l_get_txbuf(adev, tx); + if (!head) { + acx_l_dealloc_tx(adev, tx); + goto bad; + } + body = (void*)(head + 1); + +/* clt->used = CLIENT_AUTHENTICATED_2; - not (yet?) associated */ + + head->fc = WF_FSTYPE_DISASSOCi; + head->dur = 0; + /* huh? It muchly depends on whether we're STA or AP... + ** sta->ap: da=bssid, sa=own, bssid=bssid + ** ap->sta: da=sta, sa=bssid, bssid=bssid. FIXME! */ + MAC_COPY(head->da, adev->bssid); + MAC_COPY(head->sa, adev->dev_addr); + MAC_COPY(head->bssid, adev->dev_addr); + head->seq = 0; + + /* "Class 3 frame received from nonassociated station." */ + body->reason = host2ieee16(7); + + /* fixed size struct, ok to sizeof */ + acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + sizeof(*body)); +/* } */ + FN_EXIT1(OK); + return OK; +bad: + FN_EXIT1(NOT_OK); + return NOT_OK; +} +#endif + + +/*********************************************************************** +** acx_s_complete_scan +** +** Called either from after_interrupt_task() if: +** 1) there was Scan_Complete IRQ, or +** 2) scanning expired in timer() +** We need to decide which ESS or IBSS to join. +** Iterates thru adev->sta_list: +** if adev->ap is not bcast, will join only specified +** ESS or IBSS with this bssid +** checks peers' caps for ESS/IBSS bit +** checks peers' SSID, allows exact match or hidden SSID +** If station to join is chosen: +** points adev->ap_client to the chosen struct client +** sets adev->essid_for_assoc for future assoc attempt +** Auth/assoc is not yet performed +** Returns OK if there is no need to restart scan +*/ +int +acx_s_complete_scan(acx_device_t *adev) +{ + struct client *bss; + unsigned long flags; + u16 needed_cap; + int i; + int idx_found = -1; + int result = OK; + + FN_ENTER; + + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + needed_cap = WF_MGMT_CAP_IBSS; /* 2, we require Ad-Hoc */ + break; + case ACX_MODE_2_STA: + needed_cap = WF_MGMT_CAP_ESS; /* 1, we require Managed */ + break; + default: + printk("acx: driver bug: mode=%d in complete_scan()\n", adev->mode); + dump_stack(); + goto end; + } + + acx_lock(adev, flags); + + /* TODO: sta_iterator hiding implementation would be nice here... */ + + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + bss = &adev->sta_list[i]; + if (!bss->used) continue; + + log(L_ASSOC, "scan table: SSID=\"%s\" CH=%d SIR=%d SNR=%d\n", + bss->essid, bss->channel, bss->sir, bss->snr); + + if (!mac_is_bcast(adev->ap)) + if (!mac_is_equal(bss->bssid, adev->ap)) + continue; /* keep looking */ + + /* broken peer with no mode flags set? */ + if (unlikely(!(bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)))) { + printk("%s: strange peer "MACSTR" found with " + "neither ESS (AP) nor IBSS (Ad-Hoc) " + "capability - skipped\n", + adev->ndev->name, MAC(bss->address)); + continue; + } + log(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n", + bss->cap_info, needed_cap); + + /* does peer station support what we need? */ + if ((bss->cap_info & needed_cap) != needed_cap) + continue; /* keep looking */ + + /* strange peer with NO basic rates?! */ + if (unlikely(!bss->rate_bas)) { + printk("%s: strange peer "MACSTR" with empty rate set " + "- skipped\n", + adev->ndev->name, MAC(bss->address)); + continue; + } + + /* do we support all basic rates of this peer? */ + if ((bss->rate_bas & adev->rate_oper) != bss->rate_bas) { +/* we probably need to have all rates as operational rates, + even in case of an 11M-only configuration */ +#ifdef THIS_IS_TROUBLESOME + printk("%s: peer "MACSTR": incompatible basic rates " + "(AP requests 0x%04X, we have 0x%04X) " + "- skipped\n", + adev->ndev->name, MAC(bss->address), + bss->rate_bas, adev->rate_oper); + continue; +#else + printk("%s: peer "MACSTR": incompatible basic rates " + "(AP requests 0x%04X, we have 0x%04X). " + "Considering anyway...\n", + adev->ndev->name, MAC(bss->address), + bss->rate_bas, adev->rate_oper); +#endif + } + + if ( !(adev->reg_dom_chanmask & (1<<(bss->channel-1))) ) { + printk("%s: warning: peer "MACSTR" is on channel %d " + "outside of channel range of current " + "regulatory domain - couldn't join " + "even if other settings match. " + "You might want to adapt your config\n", + adev->ndev->name, MAC(bss->address), + bss->channel); + continue; /* keep looking */ + } + + if (!adev->essid_active || !strcmp(bss->essid, adev->essid)) { + log(L_ASSOC, + "found station with matching ESSID! ('%s' " + "station, '%s' config)\n", + bss->essid, + (adev->essid_active) ? adev->essid : "[any]"); + /* TODO: continue looking for peer with better SNR */ + bss->used = CLIENT_JOIN_CANDIDATE; + idx_found = i; + + /* stop searching if this station is + * on the current channel, otherwise + * keep looking for an even better match */ + if (bss->channel == adev->channel) + break; + } else + if (is_hidden_essid(bss->essid)) { + /* hmm, station with empty or single-space SSID: + * using hidden SSID broadcast? + */ + /* This behaviour is broken: which AP from zillion + ** of APs with hidden SSID you'd try? + ** We should use Probe requests to get Probe responses + ** and check for real SSID (are those never hidden?) */ + bss->used = CLIENT_JOIN_CANDIDATE; + if (idx_found == -1) + idx_found = i; + log(L_ASSOC, "found station with empty or " + "single-space (hidden) SSID, considering " + "for assoc attempt\n"); + /* ...and keep looking for better matches */ + } else { + log(L_ASSOC, "ESSID doesn't match! ('%s' " + "station, '%s' config)\n", + bss->essid, + (adev->essid_active) ? adev->essid : "[any]"); + } + } + + /* TODO: iterate thru join candidates instead */ + /* TODO: rescan if not associated within some timeout */ + if (idx_found != -1) { + char *essid_src; + size_t essid_len; + + bss = &adev->sta_list[idx_found]; + adev->ap_client = bss; + + if (is_hidden_essid(bss->essid)) { + /* if the ESSID of the station we found is empty + * (no broadcast), then use user-configured ESSID + * instead */ + essid_src = adev->essid; + essid_len = adev->essid_len; + } else { + essid_src = bss->essid; + essid_len = strlen(bss->essid); + } + + acx_update_capabilities(adev); + + memcpy(adev->essid_for_assoc, essid_src, essid_len); + adev->essid_for_assoc[essid_len] = '\0'; + adev->channel = bss->channel; + MAC_COPY(adev->bssid, bss->bssid); + + bss->rate_cfg = (bss->rate_cap & adev->rate_oper); + bss->rate_cur = 1 << lowest_bit(bss->rate_cfg); + bss->rate_100 = acx_rate111to100(bss->rate_cur); + + acxlog_mac(L_ASSOC, + "matching station found: ", adev->bssid, ", joining\n"); + + /* TODO: do we need to switch to the peer's channel first? */ + + if (ACX_MODE_0_ADHOC == adev->mode) { + acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); + } else { + acx_l_transmit_authen1(adev); + acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH); + } + } else { /* idx_found == -1 */ + /* uh oh, no station found in range */ + if (ACX_MODE_0_ADHOC == adev->mode) { + printk("%s: no matching station found in range, " + "generating our own IBSS instead\n", + adev->ndev->name); + /* we do it the HostAP way: */ + MAC_COPY(adev->bssid, adev->dev_addr); + adev->bssid[0] |= 0x02; /* 'local assigned addr' bit */ + /* add IBSS bit to our caps... */ + acx_update_capabilities(adev); + acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); + /* In order to cmd_join be called below */ + idx_found = 0; + } else { + /* we shall scan again, AP can be + ** just temporarily powered off */ + log(L_ASSOC, + "no matching station found in range yet\n"); + acx_set_status(adev, ACX_STATUS_1_SCANNING); + result = NOT_OK; + } + } + + acx_unlock(adev, flags); + + if (idx_found != -1) { + if (ACX_MODE_0_ADHOC == adev->mode) { + /* need to update channel in beacon template */ + SET_BIT(adev->set_mask, SET_TEMPLATES); + if (ACX_STATE_IFACE_UP & adev->dev_state_mask) + acx_s_update_card_settings(adev); + } + /* Inform firmware on our decision to start or join BSS */ + acx_s_cmd_join_bssid(adev, adev->bssid); + } + +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_s_read_fw +** +** Loads a firmware image +** +** Returns: +** 0 unable to load file +** pointer to firmware success +*/ +firmware_image_t* +acx_s_read_fw(struct device *dev, const char *file, u32 *size) +{ + firmware_image_t *res; + const struct firmware *fw_entry; + + res = NULL; + log(L_INIT, "requesting firmware image '%s'\n", file); + if (!request_firmware(&fw_entry, file, dev)) { + *size = 8; + if (fw_entry->size >= 8) + *size = 8 + le32_to_cpu(*(u32 *)(fw_entry->data + 4)); + if (fw_entry->size != *size) { + printk("acx: firmware size does not match " + "firmware header: %d != %d, " + "aborting fw upload\n", + (int) fw_entry->size, (int) *size); + goto release_ret; + } + res = vmalloc(*size); + if (!res) { + printk("acx: no memory for firmware " + "(%u bytes)\n", *size); + goto release_ret; + } + memcpy(res, fw_entry->data, fw_entry->size); +release_ret: + release_firmware(fw_entry); + return res; + } + printk("acx: firmware image '%s' was not provided. " + "Check your hotplug scripts\n", file); + + /* checksum will be verified in write_fw, so don't bother here */ + return res; +} + + +/*********************************************************************** +** acx_s_set_wepkey +*/ +static void +acx100_s_set_wepkey(acx_device_t *adev) +{ + ie_dot11WEPDefaultKey_t dk; + int i; + + for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) { + if (adev->wep_keys[i].size != 0) { + log(L_INIT, "setting WEP key: %d with " + "total size: %d\n", i, (int) adev->wep_keys[i].size); + dk.action = 1; + dk.keySize = adev->wep_keys[i].size; + dk.defaultKeyNum = i; + memcpy(dk.key, adev->wep_keys[i].key, dk.keySize); + acx_s_configure(adev, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE); + } + } +} + +static void +acx111_s_set_wepkey(acx_device_t *adev) +{ + acx111WEPDefaultKey_t dk; + int i; + + for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) { + if (adev->wep_keys[i].size != 0) { + log(L_INIT, "setting WEP key: %d with " + "total size: %d\n", i, (int) adev->wep_keys[i].size); + memset(&dk, 0, sizeof(dk)); + dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */ + dk.keySize = adev->wep_keys[i].size; + + /* are these two lines necessary? */ + dk.type = 0; /* default WEP key */ + dk.index = 0; /* ignored when setting default key */ + + dk.defaultKeyNum = i; + memcpy(dk.key, adev->wep_keys[i].key, dk.keySize); + acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk)); + } + } +} + +static void +acx_s_set_wepkey(acx_device_t *adev) +{ + if (IS_ACX111(adev)) + acx111_s_set_wepkey(adev); + else + acx100_s_set_wepkey(adev); +} + + +/*********************************************************************** +** acx100_s_init_wep +** +** FIXME: this should probably be moved into the new card settings +** management, but since we're also modifying the memory map layout here +** due to the WEP key space we want, we should take care... +*/ +static int +acx100_s_init_wep(acx_device_t *adev) +{ + acx100_ie_wep_options_t options; + ie_dot11WEPDefaultKeyID_t dk; + acx_ie_memmap_t pt; + int res = NOT_OK; + + FN_ENTER; + + if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) { + goto fail; + } + + log(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd); + + pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4); + pt.WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4); + + if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) { + goto fail; + } + + /* let's choose maximum setting: 4 default keys, plus 10 other keys: */ + options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10); + options.WEPOption = 0x00; + + log(L_ASSOC, "%s: writing WEP options\n", __func__); + acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS); + + acx100_s_set_wepkey(adev); + + if (adev->wep_keys[adev->wep_current_index].size != 0) { + log(L_ASSOC, "setting active default WEP key number: %d\n", + adev->wep_current_index); + dk.KeyID = adev->wep_current_index; + acx_s_configure(adev, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */ + } + /* FIXME!!! wep_key_struct is filled nowhere! But adev + * is initialized to 0, and we don't REALLY need those keys either */ +/* for (i = 0; i < 10; i++) { + if (adev->wep_key_struct[i].len != 0) { + MAC_COPY(wep_mgmt.MacAddr, adev->wep_key_struct[i].addr); + wep_mgmt.KeySize = cpu_to_le16(adev->wep_key_struct[i].len); + memcpy(&wep_mgmt.Key, adev->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize)); + wep_mgmt.Action = cpu_to_le16(1); + log(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize)); + if (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) { + adev->wep_key_struct[i].index = i; + } + } + } +*/ + + /* now retrieve the updated WEPCacheEnd pointer... */ + if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) { + printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n", + adev->ndev->name); + goto fail; + } + /* ...and tell it to start allocating templates at that location */ + /* (no endianness conversion needed) */ + pt.PacketTemplateStart = pt.WEPCacheEnd; + + if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) { + printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n", + adev->ndev->name); + goto fail; + } + res = OK; + +fail: + FN_EXIT1(res); + return res; +} + + +static int +acx_s_init_max_template_generic(acx_device_t *adev, unsigned int len, unsigned int cmd) +{ + int res; + union { + acx_template_nullframe_t null; + acx_template_beacon_t b; + acx_template_tim_t tim; + acx_template_probereq_t preq; + acx_template_proberesp_t presp; + } templ; + + memset(&templ, 0, len); + templ.null.size = cpu_to_le16(len - 2); + res = acx_s_issue_cmd(adev, cmd, &templ, len); + return res; +} + +static inline int +acx_s_init_max_null_data_template(acx_device_t *adev) +{ + return acx_s_init_max_template_generic( + adev, sizeof(acx_template_nullframe_t), ACX1xx_CMD_CONFIG_NULL_DATA + ); +} + +static inline int +acx_s_init_max_beacon_template(acx_device_t *adev) +{ + return acx_s_init_max_template_generic( + adev, sizeof(acx_template_beacon_t), ACX1xx_CMD_CONFIG_BEACON + ); +} + +static inline int +acx_s_init_max_tim_template(acx_device_t *adev) +{ + return acx_s_init_max_template_generic( + adev, sizeof(acx_template_tim_t), ACX1xx_CMD_CONFIG_TIM + ); +} + +static inline int +acx_s_init_max_probe_response_template(acx_device_t *adev) +{ + return acx_s_init_max_template_generic( + adev, sizeof(acx_template_proberesp_t), ACX1xx_CMD_CONFIG_PROBE_RESPONSE + ); +} + +static inline int +acx_s_init_max_probe_request_template(acx_device_t *adev) +{ + return acx_s_init_max_template_generic( + adev, sizeof(acx_template_probereq_t), ACX1xx_CMD_CONFIG_PROBE_REQUEST + ); +} + +/*********************************************************************** +** acx_s_set_tim_template +** +** FIXME: In full blown driver we will regularly update partial virtual bitmap +** by calling this function +** (it can be done by irq handler on each DTIM irq or by timer...) + +[802.11 7.3.2.6] TIM information element: +- 1 EID +- 1 Length +1 1 DTIM Count + indicates how many beacons (including this) appear before next DTIM + (0=this one is a DTIM) +2 1 DTIM Period + number of beacons between successive DTIMs + (0=reserved, 1=all TIMs are DTIMs, 2=every other, etc) +3 1 Bitmap Control + bit0: Traffic Indicator bit associated with Assoc ID 0 (Bcast AID?) + set to 1 in TIM elements with a value of 0 in the DTIM Count field + when one or more broadcast or multicast frames are buffered at the AP. + bit1-7: Bitmap Offset (logically Bitmap_Offset = Bitmap_Control & 0xFE). +4 n Partial Virtual Bitmap + Visible part of traffic-indication bitmap. + Full bitmap consists of 2008 bits (251 octets) such that bit number N + (0<=N<=2007) in the bitmap corresponds to bit number (N mod 8) + in octet number N/8 where the low-order bit of each octet is bit0, + and the high order bit is bit7. + Each set bit in virtual bitmap corresponds to traffic buffered by AP + for a specific station (with corresponding AID?). + Partial Virtual Bitmap shows a part of bitmap which has non-zero. + Bitmap Offset is a number of skipped zero octets (see above). + 'Missing' octets at the tail are also assumed to be zero. + Example: Length=6, Bitmap_Offset=2, Partial_Virtual_Bitmap=55 55 55 + This means that traffic-indication bitmap is: + 00000000 00000000 01010101 01010101 01010101 00000000 00000000... + (is bit0 in the map is always 0 and real value is in Bitmap Control bit0?) +*/ +static int +acx_s_set_tim_template(acx_device_t *adev) +{ +/* For now, configure smallish test bitmap, all zero ("no pending data") */ + enum { bitmap_size = 5 }; + + acx_template_tim_t t; + int result; + + FN_ENTER; + + memset(&t, 0, sizeof(t)); + t.size = 5 + bitmap_size; /* eid+len+count+period+bmap_ctrl + bmap */ + t.tim_eid = WLAN_EID_TIM; + t.len = 3 + bitmap_size; /* count+period+bmap_ctrl + bmap */ + result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t)); + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_fill_beacon_or_proberesp_template +** +** For frame format info, please see 802.11-1999.pdf item 7.2.3.9 and below!! +** +** NB: we use the fact that +** struct acx_template_proberesp and struct acx_template_beacon are the same +** (well, almost...) +** +** [802.11] Beacon's body consist of these IEs: +** 1 Timestamp +** 2 Beacon interval +** 3 Capability information +** 4 SSID +** 5 Supported rates (up to 8 rates) +** 6 FH Parameter Set (frequency-hopping PHYs only) +** 7 DS Parameter Set (direct sequence PHYs only) +** 8 CF Parameter Set (only if PCF is supported) +** 9 IBSS Parameter Set (ad-hoc only) +** +** Beacon only: +** 10 TIM (AP only) (see 802.11 7.3.2.6) +** 11 Country Information (802.11d) +** 12 FH Parameters (802.11d) +** 13 FH Pattern Table (802.11d) +** ... (?!! did not yet find relevant PDF file... --vda) +** 19 ERP Information (extended rate PHYs) +** 20 Extended Supported Rates (if more than 8 rates) +** +** Proberesp only: +** 10 Country information (802.11d) +** 11 FH Parameters (802.11d) +** 12 FH Pattern Table (802.11d) +** 13-n Requested information elements (802.11d) +** ???? +** 18 ERP Information (extended rate PHYs) +** 19 Extended Supported Rates (if more than 8 rates) +*/ +static int +acx_fill_beacon_or_proberesp_template(acx_device_t *adev, + struct acx_template_beacon *templ, + u16 fc /* in host order! */) +{ + int len; + u8 *p; + + FN_ENTER; + + memset(templ, 0, sizeof(*templ)); + MAC_BCAST(templ->da); + MAC_COPY(templ->sa, adev->dev_addr); + MAC_COPY(templ->bssid, adev->bssid); + + templ->beacon_interval = cpu_to_le16(adev->beacon_interval); + acx_update_capabilities(adev); + templ->cap = cpu_to_le16(adev->capabilities); + + p = templ->variable; + p = wlan_fill_ie_ssid(p, adev->essid_len, adev->essid); + p = wlan_fill_ie_rates(p, adev->rate_supported_len, adev->rate_supported); + p = wlan_fill_ie_ds_parms(p, adev->channel); + /* NB: should go AFTER tim, but acx seem to keep tim last always */ + p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, adev->rate_supported); + + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + /* ATIM window */ + p = wlan_fill_ie_ibss_parms(p, 0); break; + case ACX_MODE_3_AP: + /* TIM IE is set up as separate template */ + break; + } + + len = p - (u8*)templ; + templ->fc = cpu_to_le16(WF_FTYPE_MGMT | fc); + /* - 2: do not count 'u16 size' field */ + templ->size = cpu_to_le16(len - 2); + + FN_EXIT1(len); + return len; +} + + +#if POWER_SAVE_80211 +/*********************************************************************** +** acx_s_set_null_data_template +*/ +static int +acx_s_set_null_data_template(acx_device_t *adev) +{ + struct acx_template_nullframe b; + int result; + + FN_ENTER; + + /* memset(&b, 0, sizeof(b)); not needed, setting all members */ + + b.size = cpu_to_le16(sizeof(b) - 2); + b.hdr.fc = WF_FTYPE_MGMTi | WF_FSTYPE_NULLi; + b.hdr.dur = 0; + MAC_BCAST(b.hdr.a1); + MAC_COPY(b.hdr.a2, adev->dev_addr); + MAC_COPY(b.hdr.a3, adev->bssid); + b.hdr.seq = 0; + + result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b)); + + FN_EXIT1(result); + return result; +} +#endif + + +/*********************************************************************** +** acx_s_set_beacon_template +*/ +static int +acx_s_set_beacon_template(acx_device_t *adev) +{ + struct acx_template_beacon bcn; + int len, result; + + FN_ENTER; + + len = acx_fill_beacon_or_proberesp_template(adev, &bcn, WF_FSTYPE_BEACON); + result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_BEACON, &bcn, len); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_s_set_probe_response_template +*/ +static int +acx_s_set_probe_response_template(acx_device_t *adev) +{ + struct acx_template_proberesp pr; + int len, result; + + FN_ENTER; + + len = acx_fill_beacon_or_proberesp_template(adev, &pr, WF_FSTYPE_PROBERESP); + result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, len); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_s_init_packet_templates() +** +** NOTE: order is very important here, to have a correct memory layout! +** init templates: max Probe Request (station mode), max NULL data, +** max Beacon, max TIM, max Probe Response. +*/ +static int +acx_s_init_packet_templates(acx_device_t *adev) +{ + acx_ie_memmap_t mm; /* ACX100 only */ + int result = NOT_OK; + + FN_ENTER; + + log(L_DEBUG|L_INIT, "initializing max packet templates\n"); + + if (OK != acx_s_init_max_probe_request_template(adev)) + goto failed; + + if (OK != acx_s_init_max_null_data_template(adev)) + goto failed; + + if (OK != acx_s_init_max_beacon_template(adev)) + goto failed; + + if (OK != acx_s_init_max_tim_template(adev)) + goto failed; + + if (OK != acx_s_init_max_probe_response_template(adev)) + goto failed; + + if (IS_ACX111(adev)) { + /* ACX111 doesn't need the memory map magic below, + * and the other templates will be set later (acx_start) */ + result = OK; + goto success; + } + + /* ACX100 will have its TIM template set, + * and we also need to update the memory map */ + + if (OK != acx_s_set_tim_template(adev)) + goto failed_acx100; + + log(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm)); + + if (OK != acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP)) + goto failed_acx100; + + mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4); + if (OK != acx_s_configure(adev, &mm, ACX1xx_IE_MEMORY_MAP)) + goto failed_acx100; + + result = OK; + goto success; + +failed_acx100: + log(L_DEBUG|L_INIT, + /* "cb=0x%X\n" */ + "ACXMemoryMap:\n" + ".CodeStart=0x%X\n" + ".CodeEnd=0x%X\n" + ".WEPCacheStart=0x%X\n" + ".WEPCacheEnd=0x%X\n" + ".PacketTemplateStart=0x%X\n" + ".PacketTemplateEnd=0x%X\n", + /* len, */ + le32_to_cpu(mm.CodeStart), + le32_to_cpu(mm.CodeEnd), + le32_to_cpu(mm.WEPCacheStart), + le32_to_cpu(mm.WEPCacheEnd), + le32_to_cpu(mm.PacketTemplateStart), + le32_to_cpu(mm.PacketTemplateEnd)); + +failed: + printk("%s: %s() FAILED\n", adev->ndev->name, __func__); + +success: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +static int +acx_s_set_probe_request_template(acx_device_t *adev) +{ + struct acx_template_probereq probereq; + char *p; + int res; + int frame_len; + + FN_ENTER; + + memset(&probereq, 0, sizeof(probereq)); + + probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi; + MAC_BCAST(probereq.da); + MAC_COPY(probereq.sa, adev->dev_addr); + MAC_BCAST(probereq.bssid); + + p = probereq.variable; + p = wlan_fill_ie_ssid(p, adev->essid_len, adev->essid); + p = wlan_fill_ie_rates(p, adev->rate_supported_len, adev->rate_supported); + p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, adev->rate_supported); + frame_len = p - (char*)&probereq; + probereq.size = cpu_to_le16(frame_len - 2); + + res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len); + FN_EXIT0; + return res; +} + + +/*********************************************************************** +** acx_s_init_mac +*/ +int +acx_s_init_mac(acx_device_t *adev) +{ + int result = NOT_OK; + + FN_ENTER; + + if (IS_ACX111(adev)) { + adev->ie_len = acx111_ie_len; + adev->ie_len_dot11 = acx111_ie_len_dot11; + } else { + adev->ie_len = acx100_ie_len; + adev->ie_len_dot11 = acx100_ie_len_dot11; + } + + if (IS_PCI(adev)) { + adev->memblocksize = 256; /* 256 is default */ + /* try to load radio for both ACX100 and ACX111, since both + * chips have at least some firmware versions making use of an + * external radio module */ + acxpci_s_upload_radio(adev); + } else { + adev->memblocksize = 128; + } + + if (IS_ACX111(adev)) { + /* for ACX111, the order is different from ACX100 + 1. init packet templates + 2. create station context and create dma regions + 3. init wep default keys + */ + if (OK != acx_s_init_packet_templates(adev)) + goto fail; + if (OK != acx111_s_create_dma_regions(adev)) { + printk("%s: acx111_create_dma_regions FAILED\n", + adev->ndev->name); + goto fail; + } + } else { + if (OK != acx100_s_init_wep(adev)) + goto fail; + if (OK != acx_s_init_packet_templates(adev)) + goto fail; + if (OK != acx100_s_create_dma_regions(adev)) { + printk("%s: acx100_create_dma_regions FAILED\n", + adev->ndev->name); + goto fail; + } + } + + MAC_COPY(adev->ndev->dev_addr, adev->dev_addr); + result = OK; + +fail: + if (result) + printk("acx: init_mac() FAILED\n"); + FN_EXIT1(result); + return result; +} + + +void +acx_s_set_sane_reg_domain(acx_device_t *adev, int do_set) +{ + unsigned mask; + + unsigned int i; + + for (i = 0; i < sizeof(acx_reg_domain_ids); i++) + if (acx_reg_domain_ids[i] == adev->reg_dom_id) + break; + + if (sizeof(acx_reg_domain_ids) == i) { + log(L_INIT, "Invalid or unsupported regulatory domain" + " 0x%02X specified, falling back to FCC (USA)!" + " Please report if this sounds fishy!\n", + adev->reg_dom_id); + i = 0; + adev->reg_dom_id = acx_reg_domain_ids[i]; + + /* since there was a mismatch, we need to force updating */ + do_set = 1; + } + + if (do_set) { + acx_ie_generic_t dom; + dom.m.bytes[0] = adev->reg_dom_id; + acx_s_configure(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN); + } + + adev->reg_dom_chanmask = reg_domain_channel_masks[i]; + + mask = (1 << (adev->channel - 1)); + if (!(adev->reg_dom_chanmask & mask)) { + /* hmm, need to adjust our channel to reside within domain */ + mask = 1; + for (i = 1; i <= 14; i++) { + if (adev->reg_dom_chanmask & mask) { + printk("%s: adjusting selected channel from %d " + "to %d due to new regulatory domain\n", + adev->ndev->name, adev->channel, i); + adev->channel = i; + break; + } + mask <<= 1; + } + } +} + + +#if POWER_SAVE_80211 +static void +acx_s_update_80211_powersave_mode(acx_device_t *adev) +{ + /* merge both structs in a union to be able to have common code */ + union { + acx111_ie_powersave_t acx111; + acx100_ie_powersave_t acx100; + } pm; + + /* change 802.11 power save mode settings */ + log(L_INIT, "updating 802.11 power save mode settings: " + "wakeup_cfg 0x%02X, listen interval %u, " + "options 0x%02X, hangover period %u, " + "enhanced_ps_transition_time %u\n", + adev->ps_wakeup_cfg, adev->ps_listen_interval, + adev->ps_options, adev->ps_hangover_period, + adev->ps_enhanced_transition_time); + acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT); + log(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, " + "listen interval %u, options 0x%02X, " + "hangover period %u, " + "enhanced_ps_transition_time %u, beacon_rx_time %u\n", + pm.acx111.wakeup_cfg, + pm.acx111.listen_interval, + pm.acx111.options, + pm.acx111.hangover_period, + IS_ACX111(adev) ? + pm.acx111.enhanced_ps_transition_time + : pm.acx100.enhanced_ps_transition_time, + IS_ACX111(adev) ? + pm.acx111.beacon_rx_time + : (u32)-1 + ); + pm.acx111.wakeup_cfg = adev->ps_wakeup_cfg; + pm.acx111.listen_interval = adev->ps_listen_interval; + pm.acx111.options = adev->ps_options; + pm.acx111.hangover_period = adev->ps_hangover_period; + if (IS_ACX111(adev)) { + pm.acx111.beacon_rx_time = cpu_to_le32(adev->ps_beacon_rx_time); + pm.acx111.enhanced_ps_transition_time = cpu_to_le32(adev->ps_enhanced_transition_time); + } else { + pm.acx100.enhanced_ps_transition_time = cpu_to_le16(adev->ps_enhanced_transition_time); + } + acx_s_configure(adev, &pm, ACX1xx_IE_POWER_MGMT); + acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT); + log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg); + acx_s_msleep(40); + acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT); + log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg); + log(L_INIT, "power save mode change %s\n", + (pm.acx111.wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful"); + /* FIXME: maybe verify via PS_CFG_PENDING bit here + * that power save mode change was successful. */ + /* FIXME: we shouldn't trigger a scan immediately after + * fiddling with power save mode (since the firmware is sending + * a NULL frame then). */ +} +#endif + + +/*********************************************************************** +** acx_s_update_card_settings +** +** Applies accumulated changes in various adev->xxxx members +** Called by ioctl commit handler, acx_start, acx_set_defaults, +** acx_s_after_interrupt_task (if IRQ_CMD_UPDATE_CARD_CFG), +*/ +static void +acx111_s_sens_radio_16_17(acx_device_t *adev) +{ + u32 feature1, feature2; + + if ((adev->sensitivity < 1) || (adev->sensitivity > 3)) { + printk("%s: invalid sensitivity setting (1..3), " + "setting to 1\n", adev->ndev->name); + adev->sensitivity = 1; + } + acx111_s_get_feature_config(adev, &feature1, &feature2); + CLEAR_BIT(feature1, FEATURE1_LOW_RX|FEATURE1_EXTRA_LOW_RX); + if (adev->sensitivity > 1) + SET_BIT(feature1, FEATURE1_LOW_RX); + if (adev->sensitivity > 2) + SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX); + acx111_s_feature_set(adev, feature1, feature2); +} + + +void +acx_s_update_card_settings(acx_device_t *adev) +{ + unsigned long flags; + unsigned int start_scan = 0; + int i; + + FN_ENTER; + + log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n", + adev->get_mask, adev->set_mask); + + /* Track dependencies betweed various settings */ + + if (adev->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) { + log(L_INIT, "important setting has been changed. " + "Need to update packet templates, too\n"); + SET_BIT(adev->set_mask, SET_TEMPLATES); + } + if (adev->set_mask & GETSET_CHANNEL) { + /* This will actually tune RX/TX to the channel */ + SET_BIT(adev->set_mask, GETSET_RX|GETSET_TX); + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_3_AP: + /* Beacons contain channel# - update them */ + SET_BIT(adev->set_mask, SET_TEMPLATES); + } + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_2_STA: + start_scan = 1; + } + } + + /* Apply settings */ + +#ifdef WHY_SHOULD_WE_BOTHER /* imagine we were just powered off */ + /* send a disassoc request in case it's required */ + if (adev->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP)) { + if (ACX_MODE_2_STA == adev->mode) { + if (ACX_STATUS_4_ASSOCIATED == adev->status) { + log(L_ASSOC, "we were ASSOCIATED - " + "sending disassoc request\n"); + acx_lock(adev, flags); + acx_l_transmit_disassoc(adev, NULL); + /* FIXME: deauth? */ + acx_unlock(adev, flags); + } + /* need to reset some other stuff as well */ + log(L_DEBUG, "resetting bssid\n"); + MAC_ZERO(adev->bssid); + SET_BIT(adev->set_mask, SET_TEMPLATES|SET_STA_LIST); + start_scan = 1; + } + } +#endif + + if (adev->get_mask & GETSET_STATION_ID) { + u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN]; + const u8 *paddr; + + acx_s_interrogate(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID); + paddr = &stationID[4]; + for (i = 0; i < ETH_ALEN; i++) { + /* we copy the MAC address (reversed in + * the card) to the netdevice's MAC + * address, and on ifup it will be + * copied into iwadev->dev_addr */ + adev->ndev->dev_addr[ETH_ALEN - 1 - i] = paddr[i]; + } + CLEAR_BIT(adev->get_mask, GETSET_STATION_ID); + } + + if (adev->get_mask & GETSET_SENSITIVITY) { + if ((RADIO_RFMD_11 == adev->radio_type) + || (RADIO_MAXIM_0D == adev->radio_type) + || (RADIO_RALINK_15 == adev->radio_type)) { + acx_s_read_phy_reg(adev, 0x30, &adev->sensitivity); + } else { + log(L_INIT, "don't know how to get sensitivity " + "for radio type 0x%02X\n", adev->radio_type); + adev->sensitivity = 0; + } + log(L_INIT, "got sensitivity value %u\n", adev->sensitivity); + + CLEAR_BIT(adev->get_mask, GETSET_SENSITIVITY); + } + + if (adev->get_mask & GETSET_ANTENNA) { + u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN]; + + memset(antenna, 0, sizeof(antenna)); + acx_s_interrogate(adev, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA); + adev->antenna = antenna[4]; + log(L_INIT, "got antenna value 0x%02X\n", adev->antenna); + CLEAR_BIT(adev->get_mask, GETSET_ANTENNA); + } + + if (adev->get_mask & GETSET_ED_THRESH) { + if (IS_ACX100(adev)) { + u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN]; + + memset(ed_threshold, 0, sizeof(ed_threshold)); + acx_s_interrogate(adev, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD); + adev->ed_threshold = ed_threshold[4]; + } else { + log(L_INIT, "acx111 doesn't support ED\n"); + adev->ed_threshold = 0; + } + log(L_INIT, "got Energy Detect (ED) threshold %u\n", adev->ed_threshold); + CLEAR_BIT(adev->get_mask, GETSET_ED_THRESH); + } + + if (adev->get_mask & GETSET_CCA) { + if (IS_ACX100(adev)) { + u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN]; + + memset(cca, 0, sizeof(adev->cca)); + acx_s_interrogate(adev, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE); + adev->cca = cca[4]; + } else { + log(L_INIT, "acx111 doesn't support CCA\n"); + adev->cca = 0; + } + log(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", adev->cca); + CLEAR_BIT(adev->get_mask, GETSET_CCA); + } + + if (adev->get_mask & GETSET_REG_DOMAIN) { + acx_ie_generic_t dom; + + acx_s_interrogate(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN); + adev->reg_dom_id = dom.m.bytes[0]; + acx_s_set_sane_reg_domain(adev, 0); + log(L_INIT, "got regulatory domain 0x%02X\n", adev->reg_dom_id); + CLEAR_BIT(adev->get_mask, GETSET_REG_DOMAIN); + } + + if (adev->set_mask & GETSET_STATION_ID) { + u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN]; + u8 *paddr; + + paddr = &stationID[4]; + memcpy(adev->dev_addr, adev->ndev->dev_addr, ETH_ALEN); + for (i = 0; i < ETH_ALEN; i++) { + /* copy the MAC address we obtained when we noticed + * that the ethernet iface's MAC changed + * to the card (reversed in + * the card!) */ + paddr[i] = adev->dev_addr[ETH_ALEN - 1 - i]; + } + acx_s_configure(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID); + CLEAR_BIT(adev->set_mask, GETSET_STATION_ID); + } + + if (adev->set_mask & SET_TEMPLATES) { + log(L_INIT, "updating packet templates\n"); + switch (adev->mode) { + case ACX_MODE_2_STA: + acx_s_set_probe_request_template(adev); +#if POWER_SAVE_80211 + acx_s_set_null_data_template(adev); +#endif + break; + case ACX_MODE_0_ADHOC: + acx_s_set_probe_request_template(adev); +#if POWER_SAVE_80211 + /* maybe power save functionality is somehow possible + * for Ad-Hoc mode, too... FIXME: verify it somehow? firmware debug fields? */ + acx_s_set_null_data_template(adev); +#endif + /* fall through */ + case ACX_MODE_3_AP: + acx_s_set_beacon_template(adev); + acx_s_set_tim_template(adev); + /* BTW acx111 firmware would not send probe responses + ** if probe request does not have all basic rates flagged + ** by 0x80! Thus firmware does not conform to 802.11, + ** it should ignore 0x80 bit in ratevector from STA. + ** We can 'fix' it by not using this template and + ** sending probe responses by hand. TODO --vda */ + acx_s_set_probe_response_template(adev); + } + /* Needed if generated frames are to be emitted at different tx rate now */ + log(L_IRQ, "redoing cmd_join_bssid() after template cfg\n"); + acx_s_cmd_join_bssid(adev, adev->bssid); + CLEAR_BIT(adev->set_mask, SET_TEMPLATES); + } + if (adev->set_mask & SET_STA_LIST) { + acx_lock(adev, flags); + acx_l_sta_list_init(adev); + CLEAR_BIT(adev->set_mask, SET_STA_LIST); + acx_unlock(adev, flags); + } + if (adev->set_mask & SET_RATE_FALLBACK) { + u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN]; + + /* configure to not do fallbacks when not in auto rate mode */ + rate[4] = (adev->rate_auto) ? /* adev->txrate_fallback_retries */ 1 : 0; + log(L_INIT, "updating Tx fallback to %u retries\n", rate[4]); + acx_s_configure(adev, &rate, ACX1xx_IE_RATE_FALLBACK); + CLEAR_BIT(adev->set_mask, SET_RATE_FALLBACK); + } + if (adev->set_mask & GETSET_TXPOWER) { + log(L_INIT, "updating transmit power: %u dBm\n", + adev->tx_level_dbm); + acx_s_set_tx_level(adev, adev->tx_level_dbm); + CLEAR_BIT(adev->set_mask, GETSET_TXPOWER); + } + + if (adev->set_mask & GETSET_SENSITIVITY) { + log(L_INIT, "updating sensitivity value: %u\n", + adev->sensitivity); + switch (adev->radio_type) { + case RADIO_RFMD_11: + case RADIO_MAXIM_0D: + case RADIO_RALINK_15: + acx_s_write_phy_reg(adev, 0x30, adev->sensitivity); + break; + case RADIO_RADIA_16: + case RADIO_UNKNOWN_17: + acx111_s_sens_radio_16_17(adev); + break; + default: + log(L_INIT, "don't know how to modify sensitivity " + "for radio type 0x%02X\n", adev->radio_type); + } + CLEAR_BIT(adev->set_mask, GETSET_SENSITIVITY); + } + + if (adev->set_mask & GETSET_ANTENNA) { + /* antenna */ + u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN]; + + memset(antenna, 0, sizeof(antenna)); + antenna[4] = adev->antenna; + log(L_INIT, "updating antenna value: 0x%02X\n", + adev->antenna); + acx_s_configure(adev, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA); + CLEAR_BIT(adev->set_mask, GETSET_ANTENNA); + } + + if (adev->set_mask & GETSET_ED_THRESH) { + /* ed_threshold */ + log(L_INIT, "updating Energy Detect (ED) threshold: %u\n", + adev->ed_threshold); + if (IS_ACX100(adev)) { + u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN]; + + memset(ed_threshold, 0, sizeof(ed_threshold)); + ed_threshold[4] = adev->ed_threshold; + acx_s_configure(adev, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD); + } + else + log(L_INIT, "acx111 doesn't support ED!\n"); + CLEAR_BIT(adev->set_mask, GETSET_ED_THRESH); + } + + if (adev->set_mask & GETSET_CCA) { + /* CCA value */ + log(L_INIT, "updating Channel Clear Assessment " + "(CCA) value: 0x%02X\n", adev->cca); + if (IS_ACX100(adev)) { + u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN]; + + memset(cca, 0, sizeof(cca)); + cca[4] = adev->cca; + acx_s_configure(adev, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE); + } + else + log(L_INIT, "acx111 doesn't support CCA!\n"); + CLEAR_BIT(adev->set_mask, GETSET_CCA); + } + + if (adev->set_mask & GETSET_LED_POWER) { + /* Enable Tx */ + log(L_INIT, "updating power LED status: %u\n", adev->led_power); + + acx_lock(adev, flags); + if (IS_PCI(adev)) + acxpci_l_power_led(adev, adev->led_power); + CLEAR_BIT(adev->set_mask, GETSET_LED_POWER); + acx_unlock(adev, flags); + } + + if (adev->set_mask & GETSET_POWER_80211) { +#if POWER_SAVE_80211 + acx_s_update_80211_powersave_mode(adev); +#endif + CLEAR_BIT(adev->set_mask, GETSET_POWER_80211); + } + + if (adev->set_mask & GETSET_CHANNEL) { + /* channel */ + log(L_INIT, "updating channel to: %u\n", adev->channel); + CLEAR_BIT(adev->set_mask, GETSET_CHANNEL); + } + + if (adev->set_mask & GETSET_TX) { + /* set Tx */ + log(L_INIT, "updating: %s Tx\n", + adev->tx_disabled ? "disable" : "enable"); + if (adev->tx_disabled) + acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0); + else + acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX, &adev->channel, 1); + CLEAR_BIT(adev->set_mask, GETSET_TX); + } + + if (adev->set_mask & GETSET_RX) { + /* Enable Rx */ + log(L_INIT, "updating: enable Rx on channel: %u\n", + adev->channel); + acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1); + CLEAR_BIT(adev->set_mask, GETSET_RX); + } + + if (adev->set_mask & GETSET_RETRY) { + u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN]; + u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN]; + + log(L_INIT, "updating short retry limit: %u, long retry limit: %u\n", + adev->short_retry, adev->long_retry); + short_retry[0x4] = adev->short_retry; + long_retry[0x4] = adev->long_retry; + acx_s_configure(adev, &short_retry, ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT); + acx_s_configure(adev, &long_retry, ACX1xx_IE_DOT11_LONG_RETRY_LIMIT); + CLEAR_BIT(adev->set_mask, GETSET_RETRY); + } + + if (adev->set_mask & SET_MSDU_LIFETIME) { + u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN]; + + log(L_INIT, "updating tx MSDU lifetime: %u\n", + adev->msdu_lifetime); + *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)adev->msdu_lifetime); + acx_s_configure(adev, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME); + CLEAR_BIT(adev->set_mask, SET_MSDU_LIFETIME); + } + + if (adev->set_mask & GETSET_REG_DOMAIN) { + log(L_INIT, "updating regulatory domain: 0x%02X\n", + adev->reg_dom_id); + acx_s_set_sane_reg_domain(adev, 1); + CLEAR_BIT(adev->set_mask, GETSET_REG_DOMAIN); + } + + if (adev->set_mask & GETSET_MODE) { + adev->ndev->type = (adev->mode == ACX_MODE_MONITOR) ? + adev->monitor_type : ARPHRD_ETHER; + + switch (adev->mode) { + case ACX_MODE_3_AP: + + acx_lock(adev, flags); + acx_l_sta_list_init(adev); + adev->aid = 0; + adev->ap_client = NULL; + MAC_COPY(adev->bssid, adev->dev_addr); + /* this basically says "we're connected" */ + acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); + acx_unlock(adev, flags); + + acx111_s_feature_off(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER); + /* start sending beacons */ + acx_s_cmd_join_bssid(adev, adev->bssid); + break; + case ACX_MODE_MONITOR: + acx111_s_feature_on(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER); + /* this stops beacons */ + acx_s_cmd_join_bssid(adev, adev->bssid); + /* this basically says "we're connected" */ + acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); + SET_BIT(adev->set_mask, SET_RXCONFIG|SET_WEP_OPTIONS); + break; + case ACX_MODE_0_ADHOC: + case ACX_MODE_2_STA: + acx111_s_feature_off(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER); + + acx_lock(adev, flags); + adev->aid = 0; + adev->ap_client = NULL; + acx_unlock(adev, flags); + + /* we want to start looking for peer or AP */ + start_scan = 1; + break; + case ACX_MODE_OFF: + /* TODO: disable RX/TX, stop any scanning activity etc: */ + /* adev->tx_disabled = 1; */ + /* SET_BIT(adev->set_mask, GETSET_RX|GETSET_TX); */ + + /* This stops beacons (invalid macmode...) */ + acx_s_cmd_join_bssid(adev, adev->bssid); + acx_set_status(adev, ACX_STATUS_0_STOPPED); + break; + } + CLEAR_BIT(adev->set_mask, GETSET_MODE); + } + + if (adev->set_mask & SET_RXCONFIG) { + acx_s_initialize_rx_config(adev); + CLEAR_BIT(adev->set_mask, SET_RXCONFIG); + } + + if (adev->set_mask & GETSET_RESCAN) { + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_2_STA: + start_scan = 1; + break; + } + CLEAR_BIT(adev->set_mask, GETSET_RESCAN); + } + + if (adev->set_mask & GETSET_WEP) { + /* encode */ + + ie_dot11WEPDefaultKeyID_t dkey; +#ifdef DEBUG_WEP + struct { + u16 type; + u16 len; + u8 val; + } ACX_PACKED keyindic; +#endif + log(L_INIT, "updating WEP key settings\n"); + + acx_s_set_wepkey(adev); + + dkey.KeyID = adev->wep_current_index; + log(L_INIT, "setting WEP key %u as default\n", dkey.KeyID); + acx_s_configure(adev, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); +#ifdef DEBUG_WEP + keyindic.val = 3; + acx_s_configure(adev, &keyindic, ACX111_IE_KEY_CHOOSE); +#endif + start_scan = 1; + CLEAR_BIT(adev->set_mask, GETSET_WEP); + } + + if (adev->set_mask & SET_WEP_OPTIONS) { + acx100_ie_wep_options_t options; + + if (IS_ACX111(adev)) { + log(L_DEBUG, "setting WEP Options for acx111 is not supported\n"); + } else { + log(L_INIT, "setting WEP Options\n"); + + /* let's choose maximum setting: 4 default keys, + * plus 10 other keys: */ + options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10); + /* don't decrypt default key only, + * don't override decryption: */ + options.WEPOption = 0; + if (adev->mode == ACX_MODE_MONITOR) { + /* don't decrypt default key only, + * override decryption mechanism: */ + options.WEPOption = 2; + } + + acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS); + } + CLEAR_BIT(adev->set_mask, SET_WEP_OPTIONS); + } + + /* Rescan was requested */ + if (start_scan) { + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_2_STA: + /* We can avoid clearing list if join code + ** will be a bit more clever about not picking + ** 'bad' AP over and over again */ + acx_lock(adev, flags); + adev->ap_client = NULL; + acx_l_sta_list_init(adev); + acx_set_status(adev, ACX_STATUS_1_SCANNING); + acx_unlock(adev, flags); + + acx_s_cmd_start_scan(adev); + } + } + + /* debug, rate, and nick don't need any handling */ + /* what about sniffing mode?? */ + + log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n", + adev->get_mask, adev->set_mask); + +/* end: */ + FN_EXIT0; +} + + +/*********************************************************************** +** acx_e_after_interrupt_task +*/ +static int +acx_s_recalib_radio(acx_device_t *adev) +{ + if (IS_ACX111(adev)) { + acx111_cmd_radiocalib_t cal; + + printk("%s: recalibrating radio\n", adev->ndev->name); + /* automatic recalibration, choose all methods: */ + cal.methods = cpu_to_le32(0x8000000f); + /* automatic recalibration every 60 seconds (value in TUs) + * I wonder what the firmware default here is? */ + cal.interval = cpu_to_le32(58594); + return acx_s_issue_cmd_timeo(adev, ACX111_CMD_RADIOCALIB, + &cal, sizeof(cal), CMD_TIMEOUT_MS(100)); + } else { + /* On ACX100, we need to recalibrate the radio + * by issuing a GETSET_TX|GETSET_RX */ + if (/* (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0)) && + (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */ + (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX, &adev->channel, 1)) && + (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1)) ) + return OK; + return NOT_OK; + } +} + +static void +acx_s_after_interrupt_recalib(acx_device_t *adev) +{ + int res; + + /* this helps with ACX100 at least; + * hopefully ACX111 also does a + * recalibration here */ + + /* clear flag beforehand, since we want to make sure + * it's cleared; then only set it again on specific circumstances */ + CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_RADIO_RECALIB); + + /* better wait a bit between recalibrations to + * prevent overheating due to torturing the card + * into working too long despite high temperature + * (just a safety measure) */ + if (adev->recalib_time_last_success + && time_before(jiffies, adev->recalib_time_last_success + + RECALIB_PAUSE * 60 * HZ)) { + if (adev->recalib_msg_ratelimit <= 4) { + printk("%s: less than " STRING(RECALIB_PAUSE) + " minutes since last radio recalibration, " + "not recalibrating (maybe card is too hot?)\n", + adev->ndev->name); + adev->recalib_msg_ratelimit++; + if (adev->recalib_msg_ratelimit == 5) + printk("disabling above message until next recalib\n"); + } + return; + } + + adev->recalib_msg_ratelimit = 0; + + /* note that commands sometimes fail (card busy), + * so only clear flag if we were fully successful */ + res = acx_s_recalib_radio(adev); + if (res == OK) { + printk("%s: successfully recalibrated radio\n", + adev->ndev->name); + adev->recalib_time_last_success = jiffies; + adev->recalib_failure_count = 0; + } else { + /* failed: resubmit, but only limited + * amount of times within some time range + * to prevent endless loop */ + + adev->recalib_time_last_success = 0; /* we failed */ + + /* if some time passed between last + * attempts, then reset failure retry counter + * to be able to do next recalib attempt */ + if (time_after(jiffies, adev->recalib_time_last_attempt + 5*HZ)) + adev->recalib_failure_count = 0; + + if (adev->recalib_failure_count < 5) { + /* increment inside only, for speedup of outside path */ + adev->recalib_failure_count++; + adev->recalib_time_last_attempt = jiffies; + acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB); + } + } +} + +static void +acx_e_after_interrupt_task(struct work_struct *work) +{ + acx_device_t *adev = container_of(work, acx_device_t, after_interrupt_task); + + FN_ENTER; + + acx_sem_lock(adev); + + if (!adev->after_interrupt_jobs) + goto end; /* no jobs to do */ + +#if TX_CLEANUP_IN_SOFTIRQ + /* can happen only on PCI */ + if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_TX_CLEANUP) { + acx_lock(adev, flags); + acxpci_l_clean_txdesc(adev); + CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_TX_CLEANUP); + acx_unlock(adev, flags); + } +#endif + /* we see lotsa tx errors */ + if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) { + acx_s_after_interrupt_recalib(adev); + } + + /* a poor interrupt code wanted to do update_card_settings() */ + if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) { + if (ACX_STATE_IFACE_UP & adev->dev_state_mask) + acx_s_update_card_settings(adev); + CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_UPDATE_CARD_CFG); + } + + /* 1) we detected that no Scan_Complete IRQ came from fw, or + ** 2) we found too many STAs */ + if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) { + log(L_IRQ, "sending a stop scan cmd...\n"); + acx_s_issue_cmd(adev, ACX1xx_CMD_STOP_SCAN, NULL, 0); + /* HACK: set the IRQ bit, since we won't get a + * scan complete IRQ any more on ACX111 (works on ACX100!), + * since _we_, not a fw, have stopped the scan */ + SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE); + CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_STOP_SCAN); + } + + /* either fw sent Scan_Complete or we detected that + ** no Scan_Complete IRQ came from fw. Finish scanning, + ** pick join partner if any */ + if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) { + if (adev->status == ACX_STATUS_1_SCANNING) { + if (OK != acx_s_complete_scan(adev)) { + SET_BIT(adev->after_interrupt_jobs, + ACX_AFTER_IRQ_RESTART_SCAN); + } + } else { + /* + scan kills current join status - restore it + ** (do we need it for STA?) */ + /* + does it happen only with active scans? + ** active and passive scans? ALL scans including + ** background one? */ + /* + was not verified that everything is restored + ** (but at least we start to emit beacons again) */ + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_3_AP: + log(L_IRQ, "redoing cmd_join_bssid() after scan\n"); + acx_s_cmd_join_bssid(adev, adev->bssid); + } + } + CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN); + } + + /* STA auth or assoc timed out, start over again */ + if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) { + log(L_IRQ, "sending a start_scan cmd...\n"); + acx_s_cmd_start_scan(adev); + CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN); + } + + /* whee, we got positive assoc response! 8) */ + if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) { + acx_ie_generic_t pdr; + /* tiny race window exists, checking that we still a STA */ + switch (adev->mode) { + case ACX_MODE_2_STA: + pdr.m.aid = cpu_to_le16(adev->aid); + acx_s_configure(adev, &pdr, ACX1xx_IE_ASSOC_ID); + acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); + log(L_ASSOC|L_DEBUG, "ASSOCIATED!\n"); + CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE); + } + } +end: + acx_sem_unlock(adev); + FN_EXIT0; +} + + +/*********************************************************************** +** acx_schedule_task +** +** Schedule the call of the after_interrupt method after leaving +** the interrupt context. +*/ +void +acx_schedule_task(acx_device_t *adev, unsigned int set_flag) +{ + SET_BIT(adev->after_interrupt_jobs, set_flag); + SCHEDULE_WORK(&adev->after_interrupt_task); +} + + +/*********************************************************************** +*/ +void +acx_init_task_scheduler(acx_device_t *adev) +{ + /* configure task scheduler */ + INIT_WORK(&adev->after_interrupt_task, acx_e_after_interrupt_task); +} + + +/*********************************************************************** +** acx_s_start +*/ +void +acx_s_start(acx_device_t *adev) +{ + FN_ENTER; + + /* + * Ok, now we do everything that can possibly be done with ioctl + * calls to make sure that when it was called before the card + * was up we get the changes asked for + */ + + SET_BIT(adev->set_mask, SET_TEMPLATES|SET_STA_LIST|GETSET_WEP + |GETSET_TXPOWER|GETSET_ANTENNA|GETSET_ED_THRESH|GETSET_CCA + |GETSET_REG_DOMAIN|GETSET_MODE|GETSET_CHANNEL + |GETSET_TX|GETSET_RX|GETSET_STATION_ID); + + log(L_INIT, "updating initial settings on iface activation\n"); + acx_s_update_card_settings(adev); + + FN_EXIT0; +} + + +/*********************************************************************** +** acx_update_capabilities +*/ +void +acx_update_capabilities(acx_device_t *adev) +{ + u16 cap = 0; + + switch (adev->mode) { + case ACX_MODE_3_AP: + SET_BIT(cap, WF_MGMT_CAP_ESS); break; + case ACX_MODE_0_ADHOC: + SET_BIT(cap, WF_MGMT_CAP_IBSS); break; + /* other types of stations do not emit beacons */ + } + + if (adev->wep_restricted) { + SET_BIT(cap, WF_MGMT_CAP_PRIVACY); + } + if (adev->cfgopt_dot11ShortPreambleOption) { + SET_BIT(cap, WF_MGMT_CAP_SHORT); + } + if (adev->cfgopt_dot11PBCCOption) { + SET_BIT(cap, WF_MGMT_CAP_PBCC); + } + if (adev->cfgopt_dot11ChannelAgility) { + SET_BIT(cap, WF_MGMT_CAP_AGILITY); + } + log(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n", + adev->capabilities, cap); + adev->capabilities = cap; +} + +/*********************************************************************** +** Common function to parse ALL configoption struct formats +** (ACX100 and ACX111; FIXME: how to make it work with ACX100 USB!?!?). +** FIXME: logging should be removed here and added to a /proc file instead +*/ +void +acx_s_parse_configoption(acx_device_t *adev, const acx111_ie_configoption_t *pcfg) +{ + const u8 *pEle; + int i; + int is_acx111 = IS_ACX111(adev); + + if (acx_debug & L_DEBUG) { + printk("configoption struct content:\n"); + acx_dump_bytes(pcfg, sizeof(*pcfg)); + } + + if (( is_acx111 && (adev->eeprom_version == 5)) + || (!is_acx111 && (adev->eeprom_version == 4)) + || (!is_acx111 && (adev->eeprom_version == 5))) { + /* these versions are known to be supported */ + } else { + printk("unknown chip and EEPROM version combination (%s, v%d), " + "don't know how to parse config options yet. " + "Please report\n", is_acx111 ? "ACX111" : "ACX100", + adev->eeprom_version); + return; + } + + /* first custom-parse the first part which has chip-specific layout */ + + pEle = (const u8 *) pcfg; + + pEle += 4; /* skip (type,len) header */ + + memcpy(adev->cfgopt_NVSv, pEle, sizeof(adev->cfgopt_NVSv)); + pEle += sizeof(adev->cfgopt_NVSv); + + if (is_acx111) { + adev->cfgopt_NVS_vendor_offs = le16_to_cpu(*(u16 *)pEle); + pEle += sizeof(adev->cfgopt_NVS_vendor_offs); + + adev->cfgopt_probe_delay = 200; /* good default value? */ + pEle += 2; /* FIXME: unknown, value 0x0001 */ + } else { + memcpy(adev->cfgopt_MAC, pEle, sizeof(adev->cfgopt_MAC)); + pEle += sizeof(adev->cfgopt_MAC); + + adev->cfgopt_probe_delay = le16_to_cpu(*(u16 *)pEle); + pEle += sizeof(adev->cfgopt_probe_delay); + if ((adev->cfgopt_probe_delay < 100) || (adev->cfgopt_probe_delay > 500)) { + printk("strange probe_delay value %d, " + "tweaking to 200\n", adev->cfgopt_probe_delay); + adev->cfgopt_probe_delay = 200; + } + } + + adev->cfgopt_eof_memory = le32_to_cpu(*(u32 *)pEle); + pEle += sizeof(adev->cfgopt_eof_memory); + + printk("NVS_vendor_offs:%04X probe_delay:%d eof_memory:%d\n", + adev->cfgopt_NVS_vendor_offs, + adev->cfgopt_probe_delay, + adev->cfgopt_eof_memory); + + adev->cfgopt_dot11CCAModes = *pEle++; + adev->cfgopt_dot11Diversity = *pEle++; + adev->cfgopt_dot11ShortPreambleOption = *pEle++; + adev->cfgopt_dot11PBCCOption = *pEle++; + adev->cfgopt_dot11ChannelAgility = *pEle++; + adev->cfgopt_dot11PhyType = *pEle++; + adev->cfgopt_dot11TempType = *pEle++; + printk("CCAModes:%02X Diversity:%02X ShortPreOpt:%02X " + "PBCC:%02X ChanAgil:%02X PHY:%02X Temp:%02X\n", + adev->cfgopt_dot11CCAModes, + adev->cfgopt_dot11Diversity, + adev->cfgopt_dot11ShortPreambleOption, + adev->cfgopt_dot11PBCCOption, + adev->cfgopt_dot11ChannelAgility, + adev->cfgopt_dot11PhyType, + adev->cfgopt_dot11TempType); + + /* then use common parsing for next part which has common layout */ + + pEle++; /* skip table_count (6) */ + + adev->cfgopt_antennas.type = pEle[0]; + adev->cfgopt_antennas.len = pEle[1]; + printk("AntennaID:%02X Len:%02X Data:", + adev->cfgopt_antennas.type, adev->cfgopt_antennas.len); + for (i = 0; i < pEle[1]; i++) { + adev->cfgopt_antennas.list[i] = pEle[i+2]; + printk("%02X ", pEle[i+2]); + } + printk("\n"); + + pEle += pEle[1] + 2; + adev->cfgopt_power_levels.type = pEle[0]; + adev->cfgopt_power_levels.len = pEle[1]; + printk("PowerLevelID:%02X Len:%02X Data:", + adev->cfgopt_power_levels.type, adev->cfgopt_power_levels.len); + for (i = 0; i < pEle[1]; i++) { + adev->cfgopt_power_levels.list[i] = le16_to_cpu(*(u16 *)&pEle[i*2+2]); + printk("%04X ", adev->cfgopt_power_levels.list[i]); + } + printk("\n"); + + pEle += pEle[1]*2 + 2; + adev->cfgopt_data_rates.type = pEle[0]; + adev->cfgopt_data_rates.len = pEle[1]; + printk("DataRatesID:%02X Len:%02X Data:", + adev->cfgopt_data_rates.type, adev->cfgopt_data_rates.len); + for (i = 0; i < pEle[1]; i++) { + adev->cfgopt_data_rates.list[i] = pEle[i+2]; + printk("%02X ", pEle[i+2]); + } + printk("\n"); + + pEle += pEle[1] + 2; + adev->cfgopt_domains.type = pEle[0]; + adev->cfgopt_domains.len = pEle[1]; + printk("DomainID:%02X Len:%02X Data:", + adev->cfgopt_domains.type, adev->cfgopt_domains.len); + for (i = 0; i < pEle[1]; i++) { + adev->cfgopt_domains.list[i] = pEle[i+2]; + printk("%02X ", pEle[i+2]); + } + printk("\n"); + + pEle += pEle[1] + 2; + adev->cfgopt_product_id.type = pEle[0]; + adev->cfgopt_product_id.len = pEle[1]; + for (i = 0; i < pEle[1]; i++) { + adev->cfgopt_product_id.list[i] = pEle[i+2]; + } + printk("ProductID:%02X Len:%02X Data:%.*s\n", + adev->cfgopt_product_id.type, adev->cfgopt_product_id.len, + adev->cfgopt_product_id.len, (char *)adev->cfgopt_product_id.list); + + pEle += pEle[1] + 2; + adev->cfgopt_manufacturer.type = pEle[0]; + adev->cfgopt_manufacturer.len = pEle[1]; + for (i = 0; i < pEle[1]; i++) { + adev->cfgopt_manufacturer.list[i] = pEle[i+2]; + } + printk("ManufacturerID:%02X Len:%02X Data:%.*s\n", + adev->cfgopt_manufacturer.type, adev->cfgopt_manufacturer.len, + adev->cfgopt_manufacturer.len, (char *)adev->cfgopt_manufacturer.list); +/* + printk("EEPROM part:\n"); + for (i=0; i<58; i++) { + printk("%02X =======> 0x%02X\n", + i, (u8 *)adev->cfgopt_NVSv[i-2]); + } +*/ +} + + +/*********************************************************************** +*/ +static int __init +acx_e_init_module(void) +{ + int r1,r2; + + acx_struct_size_check(); +#if 0 + printk("acx: this driver is still EXPERIMENTAL\n" + "acx: reading README file and/or Craig's HOWTO is " + "recommended, visit http://acx100.sf.net in case " + "of further questions/discussion\n"); +#endif + printk(KERN_INFO "acx: Loaded combined PCI/USB driver, firmware_ver=%s\n", + firmware_ver); +#if defined(CONFIG_NET_ACX_PCI) + r1 = acxpci_e_init_module(); +#else + r1 = -EINVAL; +#endif +#if defined(CONFIG_NET_ACX_USB) + r2 = acxusb_e_init_module(); +#else + r2 = -EINVAL; +#endif + if (r2 && r1) /* both failed! */ + return r2 ? r2 : r1; + /* return success if at least one succeeded */ + return 0; +} + +static void __exit +acx_e_cleanup_module(void) +{ +#if defined(CONFIG_NET_ACX_PCI) + acxpci_e_cleanup_module(); +#endif +#if defined(CONFIG_NET_ACX_USB) + acxusb_e_cleanup_module(); +#endif +} + +module_init(acx_e_init_module) +module_exit(acx_e_cleanup_module) --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/wlan_compat.h +++ linux-2.6.27/ubuntu/misc/wireless/acx/wlan_compat.h @@ -0,0 +1,264 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +/*********************************************************************** +** This code is based on elements which are +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +** info@linux-wlan.com +** http://www.linux-wlan.com +*/ + +/*=============================================================*/ +/*------ Establish Platform Identity --------------------------*/ +/*=============================================================*/ +/* Key macros: */ +/* WLAN_CPU_FAMILY */ +#define WLAN_Ix86 1 +#define WLAN_PPC 2 +#define WLAN_Ix96 3 +#define WLAN_ARM 4 +#define WLAN_ALPHA 5 +#define WLAN_MIPS 6 +#define WLAN_HPPA 7 +#define WLAN_SPARC 8 +#define WLAN_SH 9 +#define WLAN_x86_64 10 +#define WLAN_IA64 11 +/* WLAN_CPU_CORE */ +#define WLAN_I386CORE 1 +#define WLAN_PPCCORE 2 +#define WLAN_I296 3 +#define WLAN_ARMCORE 4 +#define WLAN_ALPHACORE 5 +#define WLAN_MIPSCORE 6 +#define WLAN_HPPACORE 7 +/* WLAN_CPU_PART */ +#define WLAN_I386PART 1 +#define WLAN_MPC860 2 +#define WLAN_MPC823 3 +#define WLAN_I296SA 4 +#define WLAN_PPCPART 5 +#define WLAN_ARMPART 6 +#define WLAN_ALPHAPART 7 +#define WLAN_MIPSPART 8 +#define WLAN_HPPAPART 9 +/* WLAN_SYSARCH */ +#define WLAN_PCAT 1 +#define WLAN_MBX 2 +#define WLAN_RPX 3 +#define WLAN_LWARCH 4 +#define WLAN_PMAC 5 +#define WLAN_SKIFF 6 +#define WLAN_BITSY 7 +#define WLAN_ALPHAARCH 7 +#define WLAN_MIPSARCH 9 +#define WLAN_HPPAARCH 10 +/* WLAN_HOSTIF (generally set on the command line, not detected) */ +#define WLAN_PCMCIA 1 +#define WLAN_ISA 2 +#define WLAN_PCI 3 +#define WLAN_USB 4 +#define WLAN_PLX 5 + +/* Note: the PLX HOSTIF above refers to some vendors implementations for */ +/* PCI. It's a PLX chip that is a PCI to PCMCIA adapter, but it */ +/* isn't a real PCMCIA host interface adapter providing all the */ +/* card&socket services. */ + +#ifdef __powerpc__ +#ifndef __ppc__ +#define __ppc__ +#endif +#endif + +#if (defined(CONFIG_PPC) || defined(CONFIG_8xx)) +#ifndef __ppc__ +#define __ppc__ +#endif +#endif + +#if defined(__x86_64__) + #define WLAN_CPU_FAMILY WLAN_x86_64 + #define WLAN_SYSARCH WLAN_PCAT +#elif defined (__ia64__) + #define WLAN_CPU_FAMILY WLAN_IA64 + #define WLAN_SYSARCH WLAN_PCAT +#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) + #define WLAN_CPU_FAMILY WLAN_Ix86 + #define WLAN_CPU_CORE WLAN_I386CORE + #define WLAN_CPU_PART WLAN_I386PART + #define WLAN_SYSARCH WLAN_PCAT +#elif defined(__ppc__) + #define WLAN_CPU_FAMILY WLAN_PPC + #define WLAN_CPU_CORE WLAN_PPCCORE + #if defined(CONFIG_MBX) + #define WLAN_CPU_PART WLAN_MPC860 + #define WLAN_SYSARCH WLAN_MBX + #elif defined(CONFIG_RPXLITE) + #define WLAN_CPU_PART WLAN_MPC823 + #define WLAN_SYSARCH WLAN_RPX + #elif defined(CONFIG_RPXCLASSIC) + #define WLAN_CPU_PART WLAN_MPC860 + #define WLAN_SYSARCH WLAN_RPX + #else + #define WLAN_CPU_PART WLAN_PPCPART + #define WLAN_SYSARCH WLAN_PMAC + #endif +#elif defined(__arm__) + #define WLAN_CPU_FAMILY WLAN_ARM + #define WLAN_CPU_CORE WLAN_ARMCORE + #define WLAN_CPU_PART WLAN_ARM_PART + #define WLAN_SYSARCH WLAN_SKIFF +#elif defined(__alpha__) + #define WLAN_CPU_FAMILY WLAN_ALPHA + #define WLAN_CPU_CORE WLAN_ALPHACORE + #define WLAN_CPU_PART WLAN_ALPHAPART + #define WLAN_SYSARCH WLAN_ALPHAARCH +#elif defined(__mips__) + #define WLAN_CPU_FAMILY WLAN_MIPS + #define WLAN_CPU_CORE WLAN_MIPSCORE + #define WLAN_CPU_PART WLAN_MIPSPART + #define WLAN_SYSARCH WLAN_MIPSARCH +#elif defined(__hppa__) + #define WLAN_CPU_FAMILY WLAN_HPPA + #define WLAN_CPU_CORE WLAN_HPPACORE + #define WLAN_CPU_PART WLAN_HPPAPART + #define WLAN_SYSARCH WLAN_HPPAARCH +#elif defined(__sparc__) + #define WLAN_CPU_FAMILY WLAN_SPARC + #define WLAN_SYSARCH WLAN_SPARC +#elif defined(__sh__) + #define WLAN_CPU_FAMILY WLAN_SH + #define WLAN_SYSARCH WLAN_SHARCH + #ifndef __LITTLE_ENDIAN__ + #define __LITTLE_ENDIAN__ + #endif +#else + #error "No CPU identified!" +#endif + +/* + Some big endian machines implicitly do all I/O in little endian mode. + + In particular: + Linux/PPC on PowerMacs (PCI) + Arm/Intel Xscale (PCI) + + This may also affect PLX boards and other BE &| PPC platforms; + as new ones are discovered, add them below. +*/ + +#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC)) +#define REVERSE_ENDIAN +#endif + +/*=============================================================*/ +/*------ Hardware Portability Macros --------------------------*/ +/*=============================================================*/ +#if (WLAN_CPU_FAMILY == WLAN_PPC) +#define wlan_inw(a) in_be16((unsigned short *)((a)+_IO_BASE)) +#define wlan_inw_le16_to_cpu(a) inw((a)) +#define wlan_outw(v,a) out_be16((unsigned short *)((a)+_IO_BASE), (v)) +#define wlan_outw_cpu_to_le16(v,a) outw((v),(a)) +#else +#define wlan_inw(a) inw((a)) +#define wlan_inw_le16_to_cpu(a) __cpu_to_le16(inw((a))) +#define wlan_outw(v,a) outw((v),(a)) +#define wlan_outw_cpu_to_le16(v,a) outw(__cpu_to_le16((v)),(a)) +#endif + +/*=============================================================*/ +/*------ Bit settings -----------------------------------------*/ +/*=============================================================*/ +#define ieee2host16(n) __le16_to_cpu(n) +#define ieee2host32(n) __le32_to_cpu(n) +#define host2ieee16(n) __cpu_to_le16(n) +#define host2ieee32(n) __cpu_to_le32(n) + +/* for constants */ +#ifdef __LITTLE_ENDIAN + #define IEEE16(a,n) a = n, a##i = n, +#else + #ifdef __BIG_ENDIAN + /* shifts would produce gcc warnings. Oh well... */ + #define IEEE16(a,n) a = n, a##i = ((n&0xff)*256 + ((n&0xff00)/256)), + #else + #error give me endianness or give me death + #endif +#endif + +/*=============================================================*/ +/*------ Compiler Portability Macros --------------------------*/ +/*=============================================================*/ +#define WLAN_PACKED __attribute__ ((packed)) + +/* Interrupt handler backwards compatibility stuff */ +#ifndef IRQ_NONE +#define IRQ_NONE +#define IRQ_HANDLED +typedef void irqreturn_t; +#endif + +#ifndef ARPHRD_IEEE80211_PRISM +#define ARPHRD_IEEE80211_PRISM 802 +#endif + +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) + +/*============================================================================* + * Constants * + *============================================================================*/ +#define WLAN_IEEE_OUI_LEN 3 + +/*============================================================================* + * Types * + *============================================================================*/ + +/* local ether header type */ +typedef struct wlan_ethhdr { + u8 daddr[ETH_ALEN]; + u8 saddr[ETH_ALEN]; + u16 type; +} WLAN_PACKED wlan_ethhdr_t; + +/* local llc header type */ +typedef struct wlan_llc { + u8 dsap; + u8 ssap; + u8 ctl; +} WLAN_PACKED wlan_llc_t; + +/* local snap header type */ +typedef struct wlan_snap { + u8 oui[WLAN_IEEE_OUI_LEN]; + u16 type; +} WLAN_PACKED wlan_snap_t; --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/ioctl.c +++ linux-2.6.27/ubuntu/misc/wireless/acx/ioctl.c @@ -0,0 +1,2745 @@ +/*********************************************************************** +** Copyright (C) 2003 ACX100 Open Source Project +** +** The contents of this file are subject to the Mozilla Public +** License Version 1.1 (the "License"); you may not use this file +** except in compliance with the License. You may obtain a copy of +** the License at http://www.mozilla.org/MPL/ +** +** Software distributed under the License is distributed on an "AS +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +** implied. See the License for the specific language governing +** rights and limitations under the License. +** +** Alternatively, the contents of this file may be used under the +** terms of the GNU Public License version 2 (the "GPL"), in which +** case the provisions of the GPL are applicable instead of the +** above. If you wish to allow the use of your version of this file +** only under the terms of the GPL and not to allow others to use +** your version of this file under the MPL, indicate your decision +** by deleting the provisions above and replace them with the notice +** and other provisions required by the GPL. If you do not delete +** the provisions above, a recipient may use your version of this +** file under either the MPL or the GPL. +** --------------------------------------------------------------------- +** Inquiries regarding the ACX100 Open Source Project can be +** made directly to: +** +** acx100-users@lists.sf.net +** http://acx100.sf.net +** --------------------------------------------------------------------- +*/ + +#include +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) +#include +#endif +#include +#include +#include +/* #include */ /* required for 2.4.x kernels; verify_write() */ +#include +#include +#include + +#include "acx.h" + + +/*********************************************************************** +*/ + +/* channel frequencies + * TODO: Currently, every other 802.11 driver keeps its own copy of this. In + * the long run this should be integrated into ieee802_11.h or wireless.h or + * whatever IEEE802.11x framework evolves */ +static const u16 acx_channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484, +}; + + +/*********************************************************************** +** acx_ioctl_commit +*/ +static int +acx_ioctl_commit(struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + + FN_ENTER; + + acx_sem_lock(adev); + if (ACX_STATE_IFACE_UP & adev->dev_state_mask) + acx_s_update_card_settings(adev); + acx_sem_unlock(adev); + + FN_EXIT0; + return OK; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_get_name( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" }; + + strcpy(wrqu->name, names[IS_ACX111(adev) ? 0 : 1]); + + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_freq +*/ +static int +acx_ioctl_set_freq( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int channel = -1; + unsigned int mult = 1; + int result; + + FN_ENTER; + + if (wrqu->freq.e == 0 && wrqu->freq.m <= 1000) { + /* Setting by channel number */ + channel = wrqu->freq.m; + } else { + /* If setting by frequency, convert to a channel */ + int i; + + for (i = 0; i < (6 - wrqu->freq.e); i++) + mult *= 10; + + for (i = 1; i <= 14; i++) + if (wrqu->freq.m == acx_channel_freq[i - 1] * mult) + channel = i; + } + + if (channel > 14) { + result = -EINVAL; + goto end; + } + + acx_sem_lock(adev); + + adev->channel = channel; + /* hmm, the following code part is strange, but this is how + * it was being done before... */ + log(L_IOCTL, "Changing to channel %d\n", channel); + SET_BIT(adev->set_mask, GETSET_CHANNEL); + + result = -EINPROGRESS; /* need to call commit handler */ + + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +static inline int +acx_ioctl_get_freq( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + wrqu->freq.e = 0; + wrqu->freq.m = adev->channel; + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_mode +*/ +static int +acx_ioctl_set_mode( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + acx_sem_lock(adev); + + switch (wrqu->mode) { + case IW_MODE_AUTO: + adev->mode = ACX_MODE_OFF; + break; + case IW_MODE_MONITOR: + adev->mode = ACX_MODE_MONITOR; + break; + case IW_MODE_ADHOC: + adev->mode = ACX_MODE_0_ADHOC; + break; + case IW_MODE_INFRA: + adev->mode = ACX_MODE_2_STA; + break; + case IW_MODE_MASTER: + printk("acx: master mode (HostAP) is very, very " + "experimental! It might work partially, but " + "better get prepared for nasty surprises " + "at any time\n"); + adev->mode = ACX_MODE_3_AP; + break; + case IW_MODE_REPEAT: + case IW_MODE_SECOND: + default: + result = -EOPNOTSUPP; + goto end_unlock; + } + + log(L_ASSOC, "new adev->mode=%d\n", adev->mode); + SET_BIT(adev->set_mask, GETSET_MODE); + result = -EINPROGRESS; + +end_unlock: + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_get_mode( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result = 0; + + switch (adev->mode) { + case ACX_MODE_OFF: + wrqu->mode = IW_MODE_AUTO; break; + case ACX_MODE_MONITOR: + wrqu->mode = IW_MODE_MONITOR; break; + case ACX_MODE_0_ADHOC: + wrqu->mode = IW_MODE_ADHOC; break; + case ACX_MODE_2_STA: + wrqu->mode = IW_MODE_INFRA; break; + case ACX_MODE_3_AP: + wrqu->mode = IW_MODE_MASTER; break; + default: + result = -EOPNOTSUPP; + } + return result; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_set_sens( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->sens; + acx_device_t *adev = ndev2adev(ndev); + + acx_sem_lock(adev); + + adev->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value; + SET_BIT(adev->set_mask, GETSET_SENSITIVITY); + + acx_sem_unlock(adev); + + return -EINPROGRESS; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_get_sens( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->sens; + acx_device_t *adev = ndev2adev(ndev); + + if (IS_USB(adev)) + /* setting the PHY reg via fw cmd doesn't work yet */ + return -EOPNOTSUPP; + + /* acx_sem_lock(adev); */ + + vwrq->value = adev->sensitivity; + vwrq->disabled = (vwrq->value == 0); + vwrq->fixed = 1; + + /* acx_sem_unlock(adev); */ + + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_ap +** +** Sets the MAC address of the AP to associate with +*/ +static int +acx_ioctl_set_ap( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct sockaddr *awrq = &wrqu->ap_addr; + acx_device_t *adev = ndev2adev(ndev); + int result = 0; + const u8 *ap; + + FN_ENTER; + if (NULL == awrq) { + result = -EFAULT; + goto end; + } + if (ARPHRD_ETHER != awrq->sa_family) { + result = -EINVAL; + goto end; + } + + ap = awrq->sa_data; + acxlog_mac(L_IOCTL, "set AP=", ap, "\n"); + + MAC_COPY(adev->ap, ap); + + /* We want to start rescan in managed or ad-hoc mode, + ** otherwise just set adev->ap. + ** "iwconfig ap mode managed": we must be able + ** to set ap _first_ and _then_ set mode */ + switch (adev->mode) { + case ACX_MODE_0_ADHOC: + case ACX_MODE_2_STA: + /* FIXME: if there is a convention on what zero AP means, + ** please add a comment about that. I don't know of any --vda */ + if (mac_is_zero(ap)) { + /* "off" == 00:00:00:00:00:00 */ + MAC_BCAST(adev->ap); + log(L_IOCTL, "Not reassociating\n"); + } else { + log(L_IOCTL, "Forcing reassociation\n"); + SET_BIT(adev->set_mask, GETSET_RESCAN); + } + break; + } + result = -EINPROGRESS; +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_get_ap( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct sockaddr *awrq = &wrqu->ap_addr; + acx_device_t *adev = ndev2adev(ndev); + + if (ACX_STATUS_4_ASSOCIATED == adev->status) { + /* as seen in Aironet driver, airo.c */ + MAC_COPY(awrq->sa_data, adev->bssid); + } else { + MAC_ZERO(awrq->sa_data); + } + awrq->sa_family = ARPHRD_ETHER; + return OK; +} + + +/*********************************************************************** +** acx_ioctl_get_aplist +** +** Deprecated in favor of iwscan. +** We simply return the list of currently available stations in range, +** don't do a new scan. +*/ +static int +acx_ioctl_get_aplist( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->data; + acx_device_t *adev = ndev2adev(ndev); + struct sockaddr *address = (struct sockaddr *) extra; + struct iw_quality qual[IW_MAX_AP]; + int i, cur; + int result = OK; + + FN_ENTER; + + /* we have AP list only in STA mode */ + if (ACX_MODE_2_STA != adev->mode) { + result = -EOPNOTSUPP; + goto end; + } + + cur = 0; + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + struct client *bss = &adev->sta_list[i]; + if (!bss->used) continue; + MAC_COPY(address[cur].sa_data, bss->bssid); + address[cur].sa_family = ARPHRD_ETHER; + qual[cur].level = bss->sir; + qual[cur].noise = bss->snr; +#ifndef OLD_QUALITY + qual[cur].qual = acx_signal_determine_quality(qual[cur].level, + qual[cur].noise); +#else + qual[cur].qual = (qual[cur].noise <= 100) ? + 100 - qual[cur].noise : 0; +#endif + /* no scan: level/noise/qual not updated: */ + qual[cur].updated = 0; + cur++; + } + if (cur) { + dwrq->flags = 1; + memcpy(extra + sizeof(struct sockaddr)*cur, &qual, + sizeof(struct iw_quality)*cur); + } + dwrq->length = cur; +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_set_scan( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + acx_sem_lock(adev); + + /* don't start scan if device is not up yet */ + if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) { + result = -EAGAIN; + goto end_unlock; + } + + /* This is NOT a rescan for new AP! + ** Do not use SET_BIT(GETSET_RESCAN); */ + acx_s_cmd_start_scan(adev); + result = OK; + +end_unlock: + acx_sem_unlock(adev); +/* end: */ + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_s_scan_add_station +*/ +/* helper. not sure whether it's really a _s_leeping fn */ +static char* +acx_s_scan_add_station( + acx_device_t *adev, + char *ptr, + char *end_buf, + struct client *bss, + struct iw_request_info *info) +{ + struct iw_event iwe; + char *ptr_rate; + + FN_ENTER; + + /* MAC address has to be added first */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + MAC_COPY(iwe.u.ap_addr.sa_data, bss->bssid); + acxlog_mac(L_IOCTL, "scan, station address: ", bss->bssid, "\n"); + ptr = iwe_stream_add_event(info, ptr, end_buf, &iwe, IW_EV_ADDR_LEN); + + /* Add ESSID */ + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = bss->essid_len; + iwe.u.data.flags = 1; + log(L_IOCTL, "scan, essid: %s\n", bss->essid); + ptr = iwe_stream_add_point(info, ptr, end_buf, &iwe, bss->essid); + + /* Add mode */ + iwe.cmd = SIOCGIWMODE; + if (bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)) { + if (bss->cap_info & WF_MGMT_CAP_ESS) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + log(L_IOCTL, "scan, mode: %d\n", iwe.u.mode); + ptr = iwe_stream_add_event(info, ptr, end_buf, &iwe, IW_EV_UINT_LEN); + } + + /* Add frequency */ + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = acx_channel_freq[bss->channel - 1] * 100000; + iwe.u.freq.e = 1; + log(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m); + ptr = iwe_stream_add_event(info, ptr, end_buf, &iwe, IW_EV_FREQ_LEN); + + /* Add link quality */ + iwe.cmd = IWEVQUAL; + /* FIXME: these values should be expressed in dBm, but we don't know + * how to calibrate it yet */ + iwe.u.qual.level = bss->sir; + iwe.u.qual.noise = bss->snr; +#ifndef OLD_QUALITY + iwe.u.qual.qual = acx_signal_determine_quality(iwe.u.qual.level, + iwe.u.qual.noise); +#else + iwe.u.qual.qual = (iwe.u.qual.noise <= 100) ? + 100 - iwe.u.qual.noise : 0; +#endif + iwe.u.qual.updated = 7; + log(L_IOCTL, "scan, link quality: %d/%d/%d\n", + iwe.u.qual.level, iwe.u.qual.noise, iwe.u.qual.qual); + ptr = iwe_stream_add_event(info, ptr, end_buf, &iwe, IW_EV_QUAL_LEN); + + /* Add encryption */ + iwe.cmd = SIOCGIWENCODE; + if (bss->cap_info & WF_MGMT_CAP_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + log(L_IOCTL, "scan, encryption flags: %X\n", iwe.u.data.flags); + ptr = iwe_stream_add_point(info, ptr, end_buf, &iwe, bss->essid); + + /* add rates */ + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + ptr_rate = ptr + IW_EV_LCP_LEN; + + { + u16 rate = bss->rate_cap; + const u8* p = acx_bitpos2ratebyte; + while (rate) { + if (rate & 1) { + iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */ + log(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value); + ptr_rate = iwe_stream_add_value(info, ptr, ptr_rate, end_buf, + &iwe, IW_EV_PARAM_LEN); + } + rate >>= 1; + p++; + }} + + if ((ptr_rate - ptr) > (ptrdiff_t)IW_EV_LCP_LEN) + ptr = ptr_rate; + + /* drop remaining station data items for now */ + + FN_EXIT0; + return ptr; +} + + +/*********************************************************************** + * acx_ioctl_get_scan + */ +static int +acx_ioctl_get_scan( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->data; + acx_device_t *adev = ndev2adev(ndev); + char *ptr = extra; + int i; + int result = OK; + + FN_ENTER; + + acx_sem_lock(adev); + + /* no scan available if device is not up yet */ + if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) { + log(L_IOCTL, "iface not up yet\n"); + result = -EAGAIN; + goto end_unlock; + } + +#ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY + if (adev->bss_table_count == 0) { + /* no stations found */ + result = -ENODATA; + goto end_unlock; + } +#endif + + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + struct client *bss = &adev->sta_list[i]; + if (!bss->used) continue; + ptr = acx_s_scan_add_station(adev, ptr, + extra + IW_SCAN_MAX_DATA, bss, info); + } + dwrq->length = ptr - extra; + dwrq->flags = 0; + +end_unlock: + acx_sem_unlock(adev); +/* end: */ + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_set_essid +*/ +static int +acx_ioctl_set_essid( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->essid; + acx_device_t *adev = ndev2adev(ndev); + int len = dwrq->length; + int result; + + FN_ENTER; + + if (len < 0) { + result = -EINVAL; + goto end; + } + + log(L_IOCTL, "set ESSID '%*s', length %d, flags 0x%04X\n", + len, extra, len, dwrq->flags); + +#if WIRELESS_EXT >= 21 + /* WE 21 gives real ESSID strlen, not +1 (trailing zero): + * see LKML "[patch] drivers/net/wireless: correct reported ssid lengths" */ + len += 1; +#endif + + acx_sem_lock(adev); + + /* ESSID disabled? */ + if (0 == dwrq->flags) { + adev->essid_active = 0; + + } else { + if (dwrq->length > IW_ESSID_MAX_SIZE+1) { + result = -E2BIG; + goto end_unlock; + } + + if (len > sizeof(adev->essid)) + len = sizeof(adev->essid); + memcpy(adev->essid, extra, len-1); + adev->essid[len-1] = '\0'; + /* Paranoia: just in case there is a '\0'... */ + adev->essid_len = strlen(adev->essid); + adev->essid_active = 1; + } + + SET_BIT(adev->set_mask, GETSET_RESCAN); + + result = -EINPROGRESS; + +end_unlock: + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_get_essid( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->essid; + acx_device_t *adev = ndev2adev(ndev); + + dwrq->flags = adev->essid_active; + if (adev->essid_active) { + memcpy(extra, adev->essid, adev->essid_len); + extra[adev->essid_len] = '\0'; + dwrq->length = adev->essid_len + 1; + dwrq->flags = 1; + } + return OK; +} + + +/*********************************************************************** +** acx_l_update_client_rates +*/ +static void +acx_l_update_client_rates(acx_device_t *adev, u16 rate) +{ + int i; + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + client_t *clt = &adev->sta_list[i]; + if (!clt->used) continue; + clt->rate_cfg = (clt->rate_cap & rate); + if (!clt->rate_cfg) { + /* no compatible rates left: kick client */ + acxlog_mac(L_ASSOC, "client ",clt->address," kicked: " + "rates are not compatible anymore\n"); + acx_l_sta_list_del(adev, clt); + continue; + } + clt->rate_cur &= clt->rate_cfg; + if (!clt->rate_cur) { + /* current rate become invalid, choose a valid one */ + clt->rate_cur = 1 << lowest_bit(clt->rate_cfg); + } + if (IS_ACX100(adev)) + clt->rate_100 = acx_bitpos2rate100[highest_bit(clt->rate_cur)]; + clt->fallback_count = clt->stepup_count = 0; + clt->ignore_count = 16; + } + switch (adev->mode) { + case ACX_MODE_2_STA: + if (adev->ap_client && !adev->ap_client->used) { + /* Owwww... we kicked our AP!! :) */ + SET_BIT(adev->set_mask, GETSET_RESCAN); + } + } +} + + +/*********************************************************************** +*/ +/* maps bits from acx111 rate to rate in Mbits */ +static const unsigned int +acx111_rate_tbl[] = { + 1000000, /* 0 */ + 2000000, /* 1 */ + 5500000, /* 2 */ + 6000000, /* 3 */ + 9000000, /* 4 */ + 11000000, /* 5 */ + 12000000, /* 6 */ + 18000000, /* 7 */ + 22000000, /* 8 */ + 24000000, /* 9 */ + 36000000, /* 10 */ + 48000000, /* 11 */ + 54000000, /* 12 */ + 500000, /* 13, should not happen */ + 500000, /* 14, should not happen */ + 500000, /* 15, should not happen */ +}; + +/*********************************************************************** + * acx_ioctl_set_rate + */ +static int +acx_ioctl_set_rate( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->param; + acx_device_t *adev = ndev2adev(ndev); + u16 txrate_cfg = 1; + unsigned long flags; + int autorate; + int result = -EINVAL; + + FN_ENTER; + log(L_IOCTL, "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n", + vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags); + + if ((0 == vwrq->fixed) || (1 == vwrq->fixed)) { + int i = VEC_SIZE(acx111_rate_tbl)-1; + if (vwrq->value == -1) + /* "iwconfig rate auto" --> choose highest */ + vwrq->value = IS_ACX100(adev) ? 22000000 : 54000000; + while (i >= 0) { + if (vwrq->value == acx111_rate_tbl[i]) { + txrate_cfg <<= i; + i = 0; + break; + } + i--; + } + if (i == -1) { /* no matching rate */ + result = -EINVAL; + goto end; + } + } else { /* rate N, N<1000 (driver specific): we don't use this */ + result = -EOPNOTSUPP; + goto end; + } + /* now: only one bit is set in txrate_cfg, corresponding to + ** indicated rate */ + + autorate = (vwrq->fixed == 0) && (RATE111_1 != txrate_cfg); + if (autorate) { + /* convert 00100000 -> 00111111 */ + txrate_cfg = (txrate_cfg<<1)-1; + } + + if (IS_ACX100(adev)) { + txrate_cfg &= RATE111_ACX100_COMPAT; + if (!txrate_cfg) { + result = -ENOTSUPP; /* rate is not supported by acx100 */ + goto end; + } + } + + acx_sem_lock(adev); + acx_lock(adev, flags); + + adev->rate_auto = autorate; + adev->rate_oper = txrate_cfg; + adev->rate_basic = txrate_cfg; + /* only do that in auto mode, non-auto will be able to use + * one specific Tx rate only anyway */ + if (autorate) { + /* only use 802.11b base rates, for standard 802.11b H/W + * compatibility */ + adev->rate_basic &= RATE111_80211B_COMPAT; + } + adev->rate_bcast = 1 << lowest_bit(txrate_cfg); + if (IS_ACX100(adev)) + adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast); + acx_l_update_ratevector(adev); + acx_l_update_client_rates(adev, txrate_cfg); + + /* Do/don't do tx rate fallback; beacon contents and rate */ + SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES); + result = -EINPROGRESS; + + acx_unlock(adev, flags); + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_get_rate +*/ +static int +acx_ioctl_get_rate( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->param; + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + u16 rate; + + acx_lock(adev, flags); + rate = adev->rate_oper; + if (adev->ap_client) + rate = adev->ap_client->rate_cur; + vwrq->value = acx111_rate_tbl[highest_bit(rate)]; + vwrq->fixed = !adev->rate_auto; + vwrq->disabled = 0; + acx_unlock(adev, flags); + + return OK; +} + +static int +acx_ioctl_set_rts( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->rts; + acx_device_t *adev = ndev2adev(ndev); + int val = vwrq->value; + + if (vwrq->disabled) + val = 2312; + if ((val < 0) || (val > 2312)) + return -EINVAL; + + adev->rts_threshold = val; + return OK; +} + +static inline int +acx_ioctl_get_rts( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->rts; + acx_device_t *adev = ndev2adev(ndev); + + vwrq->value = adev->rts_threshold; + vwrq->disabled = (vwrq->value >= 2312); + vwrq->fixed = 1; + return OK; +} + + +#if ACX_FRAGMENTATION +static int +acx_ioctl_set_frag( + struct net_device *ndev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int val = vwrq->value; + + if (vwrq->disabled) + val = 32767; + else + if ((val < 256) || (val > 2347)) + return -EINVAL; + + adev->frag_threshold = val; + return OK; +} + +static inline int +acx_ioctl_get_frag( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->frag; + acx_device_t *adev = ndev2adev(ndev); + + vwrq->value = adev->frag_threshold; + vwrq->disabled = (vwrq->value >= 2347); + vwrq->fixed = 1; + return OK; +} +#endif + + +/*********************************************************************** +** acx_ioctl_set_encode +*/ +static int +acx_ioctl_set_encode( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->encoding; + acx_device_t *adev = ndev2adev(ndev); + int index; + int result; + + FN_ENTER; + + log(L_IOCTL, "set encoding flags=0x%04X, size=%d, key: %s\n", + dwrq->flags, dwrq->length, extra ? "set" : "No key"); + + acx_sem_lock(adev); + + index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + + if (dwrq->length > 0) { + /* if index is 0 or invalid, use default key */ + if ((index < 0) || (index > 3)) + index = (int)adev->wep_current_index; + + if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) { + if (dwrq->length > 29) + dwrq->length = 29; /* restrict it */ + + if (dwrq->length > 13) { + /* 29*8 == 232, WEP256 */ + adev->wep_keys[index].size = 29; + } else if (dwrq->length > 5) { + /* 13*8 == 104bit, WEP128 */ + adev->wep_keys[index].size = 13; + } else if (dwrq->length > 0) { + /* 5*8 == 40bit, WEP64 */ + adev->wep_keys[index].size = 5; + } else { + /* disable key */ + adev->wep_keys[index].size = 0; + } + + memset(adev->wep_keys[index].key, 0, + sizeof(adev->wep_keys[index].key)); + memcpy(adev->wep_keys[index].key, extra, dwrq->length); + } + } else { + /* set transmit key */ + if ((index >= 0) && (index <= 3)) + adev->wep_current_index = index; + else if (0 == (dwrq->flags & IW_ENCODE_MODE)) { + /* complain if we were not just setting + * the key mode */ + result = -EINVAL; + goto end_unlock; + } + } + + adev->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED); + + if (dwrq->flags & IW_ENCODE_OPEN) { + adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM; + adev->wep_restricted = 0; + + } else if (dwrq->flags & IW_ENCODE_RESTRICTED) { + adev->auth_alg = WLAN_AUTH_ALG_SHAREDKEY; + adev->wep_restricted = 1; + } + + /* set flag to make sure the card WEP settings get updated */ + SET_BIT(adev->set_mask, GETSET_WEP); + + log(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n", + dwrq->length, extra, dwrq->flags); + + for (index = 0; index <= 3; index++) { + if (adev->wep_keys[index].size) { + log(L_IOCTL, "index=%d, size=%d, key at 0x%p\n", + adev->wep_keys[index].index, + (int) adev->wep_keys[index].size, + adev->wep_keys[index].key); + } + } + result = -EINPROGRESS; + +end_unlock: + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_get_encode +*/ +static int +acx_ioctl_get_encode( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->encoding; + acx_device_t *adev = ndev2adev(ndev); + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + + FN_ENTER; + + if (adev->wep_enabled == 0) { + dwrq->flags = IW_ENCODE_DISABLED; + } else { + if ((index < 0) || (index > 3)) + index = (int)adev->wep_current_index; + + dwrq->flags = (adev->wep_restricted == 1) ? + IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN; + dwrq->length = adev->wep_keys[index].size; + + memcpy(extra, adev->wep_keys[index].key, + adev->wep_keys[index].size); + } + + /* set the current index */ + SET_BIT(dwrq->flags, index + 1); + + log(L_IOCTL, "len=%d, key=%p, flags=0x%X\n", + dwrq->length, dwrq->pointer, + dwrq->flags); + + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_set_power( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->power; + acx_device_t *adev = ndev2adev(ndev); + int result = -EINPROGRESS; + + FN_ENTER; + + log(L_IOCTL, "set 802.11 powersave flags=0x%04X\n", vwrq->flags); + + acx_sem_lock(adev); + + if (vwrq->disabled) { + CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE); + SET_BIT(adev->set_mask, GETSET_POWER_80211); + goto end; + } + if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + u16 ps_timeout = (vwrq->value * 1024) / 1000; + + if (ps_timeout > 255) + ps_timeout = 255; + log(L_IOCTL, "setting PS timeout value to %d time units " + "due to %dus\n", ps_timeout, vwrq->value); + adev->ps_hangover_period = ps_timeout; + } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { + u16 ps_periods = vwrq->value / 1000000; + + if (ps_periods > 255) + ps_periods = 255; + log(L_IOCTL, "setting PS period value to %d periods " + "due to %dus\n", ps_periods, vwrq->value); + adev->ps_listen_interval = ps_periods; + CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK); + SET_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_EACH_ITVL); + } + + switch (vwrq->flags & IW_POWER_MODE) { + /* FIXME: are we doing the right thing here? */ + case IW_POWER_UNICAST_R: + CLEAR_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS); + break; + case IW_POWER_MULTICAST_R: + SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS); + break; + case IW_POWER_ALL_R: + SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS); + break; + case IW_POWER_ON: + break; + default: + log(L_IOCTL, "unknown PS mode\n"); + result = -EINVAL; + goto end; + } + + SET_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE); + SET_BIT(adev->set_mask, GETSET_POWER_80211); +end: + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +*/ +static int +acx_ioctl_get_power( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->power; + acx_device_t *adev = ndev2adev(ndev); + + FN_ENTER; + + log(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags); + vwrq->disabled = ((adev->ps_wakeup_cfg & PS_CFG_ENABLE) == 0); + if (vwrq->disabled) + goto end; + + if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + vwrq->value = adev->ps_hangover_period * 1000 / 1024; + vwrq->flags = IW_POWER_TIMEOUT; + } else { + vwrq->value = adev->ps_listen_interval * 1000000; + vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE; + } + if (adev->ps_options & PS_OPT_STILL_RCV_BCASTS) + SET_BIT(vwrq->flags, IW_POWER_ALL_R); + else + SET_BIT(vwrq->flags, IW_POWER_UNICAST_R); +end: + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +** acx_ioctl_get_txpow +*/ +static inline int +acx_ioctl_get_txpow( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->power; + acx_device_t *adev = ndev2adev(ndev); + + FN_ENTER; + + vwrq->flags = IW_TXPOW_DBM; + vwrq->disabled = 0; + vwrq->fixed = 1; + vwrq->value = adev->tx_level_dbm; + + log(L_IOCTL, "get txpower:%d dBm\n", adev->tx_level_dbm); + + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_txpow +*/ +static int +acx_ioctl_set_txpow( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->power; + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + log(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n", + vwrq->value, vwrq->disabled, vwrq->flags); + + acx_sem_lock(adev); + + if (vwrq->disabled != adev->tx_disabled) { + SET_BIT(adev->set_mask, GETSET_TX); + } + + adev->tx_disabled = vwrq->disabled; + if (vwrq->value == -1) { + if (vwrq->disabled) { + adev->tx_level_dbm = 0; + log(L_IOCTL, "disable radio tx\n"); + } else { + /* adev->tx_level_auto = 1; */ + log(L_IOCTL, "set tx power auto (NIY)\n"); + } + } else { + adev->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20; + /* adev->tx_level_auto = 0; */ + log(L_IOCTL, "set txpower=%d dBm\n", adev->tx_level_dbm); + } + SET_BIT(adev->set_mask, GETSET_TXPOWER); + + result = -EINPROGRESS; + + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_get_range +*/ +static int +acx_ioctl_get_range( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->data; + struct iw_range *range = (struct iw_range *)extra; + acx_device_t *adev = ndev2adev(ndev); + int i,n; + + FN_ENTER; + + if (!dwrq->pointer) + goto end; + + dwrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + n = 0; + for (i = 1; i <= 14; i++) { + if (adev->reg_dom_chanmask & (1 << (i - 1))) { + range->freq[n].i = i; + range->freq[n].m = acx_channel_freq[i - 1] * 100000; + range->freq[n].e = 1; /* units are MHz */ + n++; + } + } + range->num_channels = n; + range->num_frequency = n; + + range->min_rts = 0; + range->max_rts = 2312; + +#if ACX_FRAGMENTATION + range->min_frag = 256; + range->max_frag = 2312; +#endif + + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + range->encoding_size[2] = 29; + range->num_encoding_sizes = 3; + range->max_encoding_tokens = 4; + + range->min_pmp = 0; + range->max_pmp = 5000000; + range->min_pmt = 0; + range->max_pmt = 65535 * 1000; + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; + + if (IS_ACX100(adev)) { /* ACX100 has direct radio programming - arbitrary levels, so offer a lot */ + for (i = 0; i <= IW_MAX_TXPOWER - 1; i++) + range->txpower[i] = 20 * i / (IW_MAX_TXPOWER - 1); + range->num_txpower = IW_MAX_TXPOWER; + range->txpower_capa = IW_TXPOW_DBM; + } + else { + int count = min(IW_MAX_TXPOWER, (int)adev->cfgopt_power_levels.len); + for (i = 0; i <= count; i++) + range->txpower[i] = adev->cfgopt_power_levels.list[i]; + range->num_txpower = count; + /* this list is given in mW */ + range->txpower_capa = IW_TXPOW_MWATT; + } + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 0x9; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 1; + range->max_retry = 255; + + range->r_time_flags = IW_RETRY_LIFETIME; + range->min_r_time = 0; + /* FIXME: lifetime ranges and orders of magnitude are strange?? */ + range->max_r_time = 65535; + + if (IS_USB(adev)) + range->sensitivity = 0; + else if (IS_ACX111(adev)) + range->sensitivity = 3; + else + range->sensitivity = 255; + + for (i=0; i < adev->rate_supported_len; i++) { + range->bitrate[i] = (adev->rate_supported[i] & ~0x80) * 500000; + /* never happens, but keep it, to be safe: */ + if (range->bitrate[i] == 0) + break; + } + range->num_bitrates = i; + + range->max_qual.qual = 100; + range->max_qual.level = 100; + range->max_qual.noise = 100; + /* TODO: better values */ + range->avg_qual.qual = 90; + range->avg_qual.level = 80; + range->avg_qual.noise = 2; + +end: + FN_EXIT1(OK); + return OK; +} + + +/*********************************************************************** +** Private functions +*/ + +/*********************************************************************** +** acx_ioctl_get_nick +*/ +static inline int +acx_ioctl_get_nick( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->data; + acx_device_t *adev = ndev2adev(ndev); + + strcpy(extra, adev->nick); + dwrq->length = strlen(extra) + 1; + + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_nick +*/ +static int +acx_ioctl_set_nick( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_point *dwrq = &wrqu->data; + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + acx_sem_lock(adev); + + if (dwrq->length > IW_ESSID_MAX_SIZE + 1) { + result = -E2BIG; + goto end_unlock; + } + + /* extra includes trailing \0, so it's ok */ + strcpy(adev->nick, extra); + result = OK; + +end_unlock: + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_get_retry +*/ +static int +acx_ioctl_get_retry( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->retry; + acx_device_t *adev = ndev2adev(ndev); + unsigned int type = vwrq->flags & IW_RETRY_TYPE; + unsigned int modifier = vwrq->flags & IW_RETRY_MODIFIER; + int result; + + FN_ENTER; + + acx_sem_lock(adev); + + /* return the short retry number by default */ + if (type == IW_RETRY_LIFETIME) { + vwrq->flags = IW_RETRY_LIFETIME; + vwrq->value = adev->msdu_lifetime; + } else if (modifier == IW_RETRY_MAX) { + vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + vwrq->value = adev->long_retry; + } else { + vwrq->flags = IW_RETRY_LIMIT; + if (adev->long_retry != adev->short_retry) + SET_BIT(vwrq->flags, IW_RETRY_MIN); + vwrq->value = adev->short_retry; + } + + /* can't be disabled */ + vwrq->disabled = (u8)0; + result = OK; + + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_set_retry +*/ +static int +acx_ioctl_set_retry( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->retry; + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + if (!vwrq) { + result = -EFAULT; + goto end; + } + if (vwrq->disabled) { + result = -EINVAL; + goto end; + } + + acx_sem_lock(adev); + + result = -EINVAL; + if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) { + printk("old retry limits: short %d long %d\n", + adev->short_retry, adev->long_retry); + if (vwrq->flags & IW_RETRY_MAX) { + adev->long_retry = vwrq->value; + } else if (vwrq->flags & IW_RETRY_MIN) { + adev->short_retry = vwrq->value; + } else { + /* no modifier: set both */ + adev->long_retry = vwrq->value; + adev->short_retry = vwrq->value; + } + printk("new retry limits: short %d long %d\n", + adev->short_retry, adev->long_retry); + SET_BIT(adev->set_mask, GETSET_RETRY); + result = -EINPROGRESS; + } + else if (vwrq->flags & IW_RETRY_LIFETIME) { + adev->msdu_lifetime = vwrq->value; + printk("new MSDU lifetime: %d\n", adev->msdu_lifetime); + SET_BIT(adev->set_mask, SET_MSDU_LIFETIME); + result = -EINPROGRESS; + } + + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/************************ private ioctls ******************************/ + + +/*********************************************************************** +** acx_ioctl_set_debug +*/ +#if ACX_DEBUG +static int +acx_ioctl_set_debug( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + unsigned int debug_new = *((unsigned int *)extra); + int result = -EINVAL; + + log(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new); + acx_debug = debug_new; + + result = OK; + return result; + +} +#endif + + +/*********************************************************************** +** acx_ioctl_list_reg_domain +*/ +static int +acx_ioctl_list_reg_domain( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int i = 1; + const char * const *entry = acx_reg_domain_strings; + + printk("dom# chan# domain/country\n"); + while (*entry) + printk("%4d %s\n", i++, *entry++); + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_reg_domain +*/ +static int +acx_ioctl_set_reg_domain( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + if ((*extra < 1) || ((size_t)*extra > acx_reg_domain_ids_len)) { + result = -EINVAL; + goto end; + } + + acx_sem_lock(adev); + + adev->reg_dom_id = acx_reg_domain_ids[*extra - 1]; + SET_BIT(adev->set_mask, GETSET_REG_DOMAIN); + + result = -EINPROGRESS; + + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_get_reg_domain +*/ +static int +acx_ioctl_get_reg_domain( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int dom,i; + + /* no locking */ + dom = adev->reg_dom_id; + + for (i = 1; i <= acx_reg_domain_ids_len; i++) { + if (acx_reg_domain_ids[i-1] == dom) { + log(L_IOCTL, "regulatory domain is currently set " + "to %d (0x%X): %s\n", i, dom, + acx_reg_domain_strings[i-1]); + *extra = i; + break; + } + } + + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_short_preamble +*/ +static const char * const +preamble_modes[] = { + "off", + "on", + "auto (peer capability dependent)", + "unknown mode, error" +}; + +static int +acx_ioctl_set_short_preamble( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int i; + int result; + + FN_ENTER; + + if ((unsigned char)*extra > 2) { + result = -EINVAL; + goto end; + } + + acx_sem_lock(adev); + + adev->preamble_mode = (u8)*extra; + switch (adev->preamble_mode) { + case 0: /* long */ + adev->preamble_cur = 0; + break; + case 1: + /* short, kick incapable peers */ + adev->preamble_cur = 1; + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + client_t *clt = &adev->sta_list[i]; + if (!clt->used) continue; + if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) { + clt->used = CLIENT_EMPTY_SLOT_0; + } + } + switch (adev->mode) { + case ACX_MODE_2_STA: + if (adev->ap_client && !adev->ap_client->used) { + /* We kicked our AP :) */ + SET_BIT(adev->set_mask, GETSET_RESCAN); + } + } + break; + case 2: /* auto. short only if all peers are short-capable */ + adev->preamble_cur = 1; + for (i = 0; i < VEC_SIZE(adev->sta_list); i++) { + client_t *clt = &adev->sta_list[i]; + if (!clt->used) continue; + if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) { + adev->preamble_cur = 0; + break; + } + } + break; + } + printk("new short preamble setting: configured %s, active %s\n", + preamble_modes[adev->preamble_mode], + preamble_modes[adev->preamble_cur]); + result = OK; + + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_get_short_preamble +*/ +static int +acx_ioctl_get_short_preamble( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + + acx_sem_lock(adev); + + printk("current short preamble setting: configured %s, active %s\n", + preamble_modes[adev->preamble_mode], + preamble_modes[adev->preamble_cur]); + + *extra = (char)adev->preamble_mode; + + acx_sem_unlock(adev); + + return OK; +} + + +/*********************************************************************** +** acx_ioctl_set_antenna +** +** TX and RX antenna can be set separately but this function good +** for testing 0-4 bits +*/ +static int +acx_ioctl_set_antenna( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + + acx_sem_lock(adev); + + printk("old antenna value: 0x%02X (COMBINED bit mask)\n" + "Rx antenna selection:\n" + "0x00 ant. 1\n" + "0x40 ant. 2\n" + "0x80 full diversity\n" + "0xc0 partial diversity\n" + "0x0f dwell time mask (in units of us)\n" + "Tx antenna selection:\n" + "0x00 ant. 2\n" /* yep, those ARE reversed! */ + "0x20 ant. 1\n" + "new antenna value: 0x%02X\n", + adev->antenna, (u8)*extra); + + adev->antenna = (u8)*extra; + SET_BIT(adev->set_mask, GETSET_ANTENNA); + + acx_sem_unlock(adev); + + return -EINPROGRESS; +} + + +/*********************************************************************** +** acx_ioctl_get_antenna +*/ +static int +acx_ioctl_get_antenna( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + + /* no locking. it's pointless to lock a single load */ + printk("current antenna value: 0x%02X (COMBINED bit mask)\n" + "Rx antenna selection:\n" + "0x00 ant. 1\n" + "0x40 ant. 2\n" + "0x80 full diversity\n" + "0xc0 partial diversity\n" + "Tx antenna selection:\n" + "0x00 ant. 2\n" /* yep, those ARE reversed! */ + "0x20 ant. 1\n", adev->antenna); + + return 0; +} + + +/*********************************************************************** +** acx_ioctl_set_rx_antenna +** +** 0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity +** Could anybody test which antenna is the external one? +*/ +static int +acx_ioctl_set_rx_antenna( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + if (*extra > 3) { + result = -EINVAL; + goto end; + } + + printk("old antenna value: 0x%02X\n", adev->antenna); + + acx_sem_lock(adev); + + adev->antenna &= 0x3f; + SET_BIT(adev->antenna, (*extra << 6)); + SET_BIT(adev->set_mask, GETSET_ANTENNA); + printk("new antenna value: 0x%02X\n", adev->antenna); + result = -EINPROGRESS; + + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_set_tx_antenna +** +** Arguments: 0 == antenna2; 1 == antenna1; +** Could anybody test which antenna is the external one? +*/ +static int +acx_ioctl_set_tx_antenna( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + + FN_ENTER; + + if (*extra > 1) { + result = -EINVAL; + goto end; + } + + printk("old antenna value: 0x%02X\n", adev->antenna); + + acx_sem_lock(adev); + + adev->antenna &= ~0x30; + SET_BIT(adev->antenna, ((*extra & 0x01) << 5)); + SET_BIT(adev->set_mask, GETSET_ANTENNA); + printk("new antenna value: 0x%02X\n", adev->antenna); + result = -EINPROGRESS; + + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_wlansniff +** +** can we just remove this in favor of monitor mode? --vda +*/ +static int +acx_ioctl_wlansniff( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned int *params = (unsigned int*)extra; + unsigned int enable = (unsigned int)(params[0] > 0); + int result; + + FN_ENTER; + + acx_sem_lock(adev); + + /* not using printk() here, since it distorts kismet display + * when printk messages activated */ + log(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]); + + switch (params[0]) { + case 0: + /* no monitor mode. hmm, should we simply ignore it + * or go back to enabling adev->netdev->type ARPHRD_ETHER? */ + break; + case 1: + adev->monitor_type = ARPHRD_IEEE80211_PRISM; + break; + case 2: + adev->monitor_type = ARPHRD_IEEE80211; + break; + } + + if (params[0]) { + adev->mode = ACX_MODE_MONITOR; + SET_BIT(adev->set_mask, GETSET_MODE); + } + + if (enable) { + adev->channel = params[1]; + SET_BIT(adev->set_mask, GETSET_RX); + } + result = -EINPROGRESS; + + acx_sem_unlock(adev); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_unknown11 +** FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken +*/ +static int +acx_ioctl_unknown11( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ +#ifdef BROKEN + struct iw_param *vwrq = &wrqu->param; + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + client_t client; + int result; + + acx_sem_lock(adev); + acx_lock(adev, flags); + + acx_l_transmit_disassoc(adev, &client); + result = OK; + + acx_unlock(adev, flags); + acx_sem_unlock(adev); + + return result; +#endif + return -EINVAL; +} + + +/*********************************************************************** +** debug helper function to be able to debug various issues relatively easily +*/ +static int +acx_ioctl_dbg_set_masks( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + const unsigned int *params = (unsigned int*)extra; + int result; + + acx_sem_lock(adev); + + log(L_IOCTL, "setting flags in settings mask: " + "get_mask %08X set_mask %08X\n" + "before: get_mask %08X set_mask %08X\n", + params[0], params[1], + adev->get_mask, adev->set_mask); + SET_BIT(adev->get_mask, params[0]); + SET_BIT(adev->set_mask, params[1]); + log(L_IOCTL, "after: get_mask %08X set_mask %08X\n", + adev->get_mask, adev->set_mask); + result = -EINPROGRESS; /* immediately call commit handler */ + + acx_sem_unlock(adev); + + return result; +} + + +/*********************************************************************** +* acx_ioctl_set_rates +* +* This ioctl takes string parameter. Examples: +* iwpriv wlan0 SetRates "1,2" +* use 1 and 2 Mbit rates, both are in basic rate set +* iwpriv wlan0 SetRates "1,2 5,11" +* use 1,2,5.5,11 Mbit rates. 1 and 2 are basic +* iwpriv wlan0 SetRates "1,2 5c,11c" +* same ('c' means 'CCK modulation' and it is a default for 5 and 11) +* iwpriv wlan0 SetRates "1,2 5p,11p" +* use 1,2,5.5,11 Mbit, 1,2 are basic. 5 and 11 are using PBCC +* iwpriv wlan0 SetRates "1,2,5,11 22p" +* use 1,2,5.5,11,22 Mbit. 1,2,5.5 and 11 are basic. 22 is using PBCC +* (this is the maximum acx100 can do (modulo x4 mode)) +* iwpriv wlan0 SetRates "1,2,5,11 22" +* same. 802.11 defines only PBCC modulation +* for 22 and 33 Mbit rates, so there is no ambiguity +* iwpriv wlan0 SetRates "1,2,5,11 6o,9o,12o,18o,24o,36o,48o,54o" +* 1,2,5.5 and 11 are basic. 11g OFDM rates are enabled but +* they are not in basic rate set. 22 Mbit is disabled. +* iwpriv wlan0 SetRates "1,2,5,11 6,9,12,18,24,36,48,54" +* same. OFDM is default for 11g rates except 22 and 33 Mbit, +* thus 'o' is optional +* iwpriv wlan0 SetRates "1,2,5,11 6d,9d,12d,18d,24d,36d,48d,54d" +* 1,2,5.5 and 11 are basic. 11g CCK-OFDM rates are enabled +* (acx111 does not support CCK-OFDM, driver will reject this cmd) +* iwpriv wlan0 SetRates "6,9,12 18,24,36,48,54" +* 6,9,12 are basic, rest of 11g rates is enabled. Using OFDM +*/ +#include "setrate.c" + +/* disallow: 33Mbit (unsupported by hw) */ +/* disallow: CCKOFDM (unsupported by hw) */ +static int +acx111_supported(int mbit, int modulation, void *opaque) +{ + if (mbit==33) return -ENOTSUPP; + if (modulation==DOT11_MOD_CCKOFDM) return -ENOTSUPP; + return OK; +} + +static const u16 +acx111mask[] = { + [DOT11_RATE_1 ] = RATE111_1 , + [DOT11_RATE_2 ] = RATE111_2 , + [DOT11_RATE_5 ] = RATE111_5 , + [DOT11_RATE_11] = RATE111_11, + [DOT11_RATE_22] = RATE111_22, + /* [DOT11_RATE_33] = */ + [DOT11_RATE_6 ] = RATE111_6 , + [DOT11_RATE_9 ] = RATE111_9 , + [DOT11_RATE_12] = RATE111_12, + [DOT11_RATE_18] = RATE111_18, + [DOT11_RATE_24] = RATE111_24, + [DOT11_RATE_36] = RATE111_36, + [DOT11_RATE_48] = RATE111_48, + [DOT11_RATE_54] = RATE111_54, +}; + +static u32 +acx111_gen_mask(int mbit, int modulation, void *opaque) +{ + /* lower 16 bits show selected 1, 2, CCK and OFDM rates */ + /* upper 16 bits show selected PBCC rates */ + u32 m = acx111mask[rate_mbit2enum(mbit)]; + if (modulation==DOT11_MOD_PBCC) + return m<<16; + return m; +} + +static int +verify_rate(u32 rate, int chip_type) +{ + /* never happens. be paranoid */ + if (!rate) return -EINVAL; + + /* disallow: mixing PBCC and CCK at 5 and 11Mbit + ** (can be supported, but needs complicated handling in tx code) */ + if (( rate & ((RATE111_11+RATE111_5)<<16) ) + && ( rate & (RATE111_11+RATE111_5) ) + ) { + return -ENOTSUPP; + } + if (CHIPTYPE_ACX100 == chip_type) { + if ( rate & ~(RATE111_ACX100_COMPAT+(RATE111_ACX100_COMPAT<<16)) ) + return -ENOTSUPP; + } + return 0; +} + +static int +acx_ioctl_set_rates(struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + unsigned long flags; + int result; + u32 brate = 0, orate = 0; /* basic, operational rate set */ + + FN_ENTER; + + log(L_IOCTL, "set_rates %s\n", extra); + result = fill_ratemasks(extra, &brate, &orate, + acx111_supported, acx111_gen_mask, 0); + if (result) goto end; + SET_BIT(orate, brate); + log(L_IOCTL, "brate %08X orate %08X\n", brate, orate); + + result = verify_rate(brate, adev->chip_type); + if (result) goto end; + result = verify_rate(orate, adev->chip_type); + if (result) goto end; + + acx_sem_lock(adev); + acx_lock(adev, flags); + + adev->rate_basic = brate; + adev->rate_oper = orate; + /* TODO: ideally, we shall monitor highest basic rate + ** which was successfully sent to every peer + ** (say, last we checked, everybody could hear 5.5 Mbits) + ** and use that for bcasts when we want to reach all peers. + ** For beacons, we probably shall use lowest basic rate + ** because we want to reach all *potential* new peers too */ + adev->rate_bcast = 1 << lowest_bit(brate); + if (IS_ACX100(adev)) + adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast); + adev->rate_auto = !has_only_one_bit(orate); + acx_l_update_client_rates(adev, orate); + /* TODO: get rid of ratevector, build it only when needed */ + acx_l_update_ratevector(adev); + + /* Do/don't do tx rate fallback; beacon contents and rate */ + SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES); + result = -EINPROGRESS; + + acx_unlock(adev, flags); + acx_sem_unlock(adev); +end: + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acx_ioctl_get_phy_chan_busy_percentage +*/ +static int +acx_ioctl_get_phy_chan_busy_percentage( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + struct { + u16 type; + u16 len; + u32 busytime; + u32 totaltime; + } ACX_PACKED usage; + int result; + + acx_sem_lock(adev); + + if (OK != acx_s_interrogate(adev, &usage, ACX1xx_IE_MEDIUM_USAGE)) { + result = NOT_OK; + goto end_unlock; + } + + usage.busytime = le32_to_cpu(usage.busytime); + usage.totaltime = le32_to_cpu(usage.totaltime); + + /* yes, this is supposed to be "Medium" (singular of media), + not "average"! OK, reword the message to make it obvious... */ + printk("%s: busy percentage of medium (since last invocation): %d%% " + "(%u of %u microseconds)\n", + ndev->name, + usage.busytime / ((usage.totaltime / 100) + 1), + usage.busytime, usage.totaltime); + + result = OK; + +end_unlock: + acx_sem_unlock(adev); + + return result; +} + + +/*********************************************************************** +** acx_ioctl_set_ed_threshold +*/ +static inline int +acx_ioctl_set_ed_threshold( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + + acx_sem_lock(adev); + + printk("old ED threshold value: %d\n", adev->ed_threshold); + adev->ed_threshold = (unsigned char)*extra; + printk("new ED threshold value: %d\n", (unsigned char)*extra); + SET_BIT(adev->set_mask, GETSET_ED_THRESH); + + acx_sem_unlock(adev); + + return -EINPROGRESS; +} + + +/*********************************************************************** +** acx_ioctl_set_cca +*/ +static inline int +acx_ioctl_set_cca( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + + acx_sem_lock(adev); + + printk("old CCA value: 0x%02X\n", adev->cca); + adev->cca = (unsigned char)*extra; + printk("new CCA value: 0x%02X\n", (unsigned char)*extra); + SET_BIT(adev->set_mask, GETSET_CCA); + result = -EINPROGRESS; + + acx_sem_unlock(adev); + + return result; +} + + +/*********************************************************************** +*/ +static const char * const +scan_modes[] = { "active", "passive", "background" }; + +static void +acx_print_scan_params(acx_device_t *adev, const char* head) +{ + printk("%s: %smode %d (%s), min chan time %dTU, " + "max chan time %dTU, max scan rate byte: %d\n", + adev->ndev->name, head, + adev->scan_mode, scan_modes[adev->scan_mode], + adev->scan_probe_delay, adev->scan_duration, adev->scan_rate); +} + +static int +acx_ioctl_set_scan_params( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + const int *params = (int *)extra; + + acx_sem_lock(adev); + + acx_print_scan_params(adev, "old scan parameters: "); + if ((params[0] != -1) && (params[0] >= 0) && (params[0] <= 2)) + adev->scan_mode = params[0]; + if (params[1] != -1) + adev->scan_probe_delay = params[1]; + if (params[2] != -1) + adev->scan_duration = params[2]; + if ((params[3] != -1) && (params[3] <= 255)) + adev->scan_rate = params[3]; + acx_print_scan_params(adev, "new scan parameters: "); + SET_BIT(adev->set_mask, GETSET_RESCAN); + result = -EINPROGRESS; + + acx_sem_unlock(adev); + + return result; +} + +static int +acx_ioctl_get_scan_params( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + int result; + int *params = (int *)extra; + + acx_sem_lock(adev); + + acx_print_scan_params(adev, "current scan parameters: "); + params[0] = adev->scan_mode; + params[1] = adev->scan_probe_delay; + params[2] = adev->scan_duration; + params[3] = adev->scan_rate; + result = OK; + + acx_sem_unlock(adev); + + return result; +} + + +/*********************************************************************** +*/ +static int +acx100_ioctl_set_led_power( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + static const char * const led_modes[] = { "off", "on", "LinkQuality" }; + + acx_device_t *adev = ndev2adev(ndev); + int result; + + acx_sem_lock(adev); + + printk("%s: power LED status: old %d (%s), ", + ndev->name, + adev->led_power, + led_modes[adev->led_power]); + adev->led_power = extra[0]; + if (adev->led_power > 2) adev->led_power = 2; + printk("new %d (%s)\n", + adev->led_power, + led_modes[adev->led_power]); + + if (adev->led_power == 2) { + printk("%s: max link quality setting: old %d, ", + ndev->name, adev->brange_max_quality); + if (extra[1]) + adev->brange_max_quality = extra[1]; + printk("new %d\n", adev->brange_max_quality); + } + + SET_BIT(adev->set_mask, GETSET_LED_POWER); + + result = -EINPROGRESS; + + acx_sem_unlock(adev); + + return result; +} + + +/*********************************************************************** +*/ +static inline int +acx100_ioctl_get_led_power( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + acx_device_t *adev = ndev2adev(ndev); + + acx_sem_lock(adev); + + extra[0] = adev->led_power; + if (adev->led_power == 2) + extra[1] = adev->brange_max_quality; + else + extra[1] = -1; + + acx_sem_unlock(adev); + + return OK; +} + + +/*********************************************************************** +*/ +static int +acx111_ioctl_info( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->param; + if (!IS_PCI(ndev2adev(ndev))) + return OK; + return acx111pci_ioctl_info(ndev, info, vwrq, extra); +} + + +/*********************************************************************** +*/ +static int +acx100_ioctl_set_phy_amp_bias( + struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct iw_param *vwrq = &wrqu->param; + if (!IS_PCI(ndev2adev(ndev))) { + printk("acx: set_phy_amp_bias() is not supported on USB\n"); + return OK; + } + return acx100pci_ioctl_set_phy_amp_bias(ndev, info, vwrq, extra); +} + + +/*********************************************************************** +*/ +static const iw_handler acx_ioctl_handler[] = +{ + acx_ioctl_commit, /* SIOCSIWCOMMIT */ + acx_ioctl_get_name, /* SIOCGIWNAME */ + NULL, /* SIOCSIWNWID */ + NULL, /* SIOCGIWNWID */ + acx_ioctl_set_freq, /* SIOCSIWFREQ */ + acx_ioctl_get_freq, /* SIOCGIWFREQ */ + acx_ioctl_set_mode, /* SIOCSIWMODE */ + acx_ioctl_get_mode, /* SIOCGIWMODE */ + acx_ioctl_set_sens, /* SIOCSIWSENS */ + acx_ioctl_get_sens, /* SIOCGIWSENS */ + NULL, /* SIOCSIWRANGE */ + acx_ioctl_get_range, /* SIOCGIWRANGE */ + NULL, /* SIOCSIWPRIV */ + NULL, /* SIOCGIWPRIV */ + NULL, /* SIOCSIWSTATS */ + NULL, /* SIOCGIWSTATS */ +#if IW_HANDLER_VERSION > 4 + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ +#else /* IW_HANDLER_VERSION > 4 */ +#ifdef WIRELESS_SPY + NULL /* acx_ioctl_set_spy FIXME */, /* SIOCSIWSPY */ + NULL /* acx_ioctl_get_spy */, /* SIOCGIWSPY */ +#else /* WSPY */ + NULL, /* SIOCSIWSPY */ + NULL, /* SIOCGIWSPY */ +#endif /* WSPY */ + NULL, /* [nothing] */ + NULL, /* [nothing] */ +#endif /* IW_HANDLER_VERSION > 4 */ + acx_ioctl_set_ap, /* SIOCSIWAP */ + acx_ioctl_get_ap, /* SIOCGIWAP */ + NULL, /* [nothing] */ + acx_ioctl_get_aplist, /* SIOCGIWAPLIST */ + acx_ioctl_set_scan, /* SIOCSIWSCAN */ + acx_ioctl_get_scan, /* SIOCGIWSCAN */ + acx_ioctl_set_essid, /* SIOCSIWESSID */ + acx_ioctl_get_essid, /* SIOCGIWESSID */ + acx_ioctl_set_nick, /* SIOCSIWNICKN */ + acx_ioctl_get_nick, /* SIOCGIWNICKN */ + NULL, /* [nothing] */ + NULL, /* [nothing] */ + acx_ioctl_set_rate, /* SIOCSIWRATE */ + acx_ioctl_get_rate, /* SIOCGIWRATE */ + acx_ioctl_set_rts, /* SIOCSIWRTS */ + acx_ioctl_get_rts, /* SIOCGIWRTS */ +#if ACX_FRAGMENTATION + acx_ioctl_set_frag, /* SIOCSIWFRAG */ + acx_ioctl_get_frag, /* SIOCGIWFRAG */ +#else + NULL, /* SIOCSIWFRAG */ + NULL, /* SIOCGIWFRAG */ +#endif + acx_ioctl_set_txpow, /* SIOCSIWTXPOW */ + acx_ioctl_get_txpow, /* SIOCGIWTXPOW */ + acx_ioctl_set_retry, /* SIOCSIWRETRY */ + acx_ioctl_get_retry, /* SIOCGIWRETRY */ + acx_ioctl_set_encode, /* SIOCSIWENCODE */ + acx_ioctl_get_encode, /* SIOCGIWENCODE */ + acx_ioctl_set_power, /* SIOCSIWPOWER */ + acx_ioctl_get_power, /* SIOCGIWPOWER */ +}; + + +/*********************************************************************** +*/ + +/* if you plan to reorder something, make sure to reorder all other places + * accordingly! */ +/* SET/GET convention: SETs must have even position, GETs odd */ +#define ACX100_IOCTL SIOCIWFIRSTPRIV +enum { + ACX100_IOCTL_DEBUG = ACX100_IOCTL, + ACX100_IOCTL_GET__________UNUSED1, + ACX100_IOCTL_SET_PLED, + ACX100_IOCTL_GET_PLED, + ACX100_IOCTL_SET_RATES, + ACX100_IOCTL_LIST_DOM, + ACX100_IOCTL_SET_DOM, + ACX100_IOCTL_GET_DOM, + ACX100_IOCTL_SET_SCAN_PARAMS, + ACX100_IOCTL_GET_SCAN_PARAMS, + ACX100_IOCTL_SET_PREAMB, + ACX100_IOCTL_GET_PREAMB, + ACX100_IOCTL_SET_ANT, + ACX100_IOCTL_GET_ANT, + ACX100_IOCTL_RX_ANT, + ACX100_IOCTL_TX_ANT, + ACX100_IOCTL_SET_PHY_AMP_BIAS, + ACX100_IOCTL_GET_PHY_CHAN_BUSY, + ACX100_IOCTL_SET_ED, + ACX100_IOCTL_GET__________UNUSED3, + ACX100_IOCTL_SET_CCA, + ACX100_IOCTL_GET__________UNUSED4, + ACX100_IOCTL_MONITOR, + ACX100_IOCTL_TEST, + ACX100_IOCTL_DBG_SET_MASKS, + ACX111_IOCTL_INFO, + ACX100_IOCTL_DBG_SET_IO, + ACX100_IOCTL_DBG_GET_IO +}; + + +static const iw_handler acx_ioctl_private_handler[] = +{ +#if ACX_DEBUG +[ACX100_IOCTL_DEBUG - ACX100_IOCTL] = acx_ioctl_set_debug, +#endif +[ACX100_IOCTL_SET_PLED - ACX100_IOCTL] = acx100_ioctl_set_led_power, +[ACX100_IOCTL_GET_PLED - ACX100_IOCTL] = acx100_ioctl_get_led_power, +[ACX100_IOCTL_SET_RATES - ACX100_IOCTL] = acx_ioctl_set_rates, +[ACX100_IOCTL_LIST_DOM - ACX100_IOCTL] = acx_ioctl_list_reg_domain, +[ACX100_IOCTL_SET_DOM - ACX100_IOCTL] = acx_ioctl_set_reg_domain, +[ACX100_IOCTL_GET_DOM - ACX100_IOCTL] = acx_ioctl_get_reg_domain, +[ACX100_IOCTL_SET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_set_scan_params, +[ACX100_IOCTL_GET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_get_scan_params, +[ACX100_IOCTL_SET_PREAMB - ACX100_IOCTL] = acx_ioctl_set_short_preamble, +[ACX100_IOCTL_GET_PREAMB - ACX100_IOCTL] = acx_ioctl_get_short_preamble, +[ACX100_IOCTL_SET_ANT - ACX100_IOCTL] = acx_ioctl_set_antenna, +[ACX100_IOCTL_GET_ANT - ACX100_IOCTL] = acx_ioctl_get_antenna, +[ACX100_IOCTL_RX_ANT - ACX100_IOCTL] = acx_ioctl_set_rx_antenna, +[ACX100_IOCTL_TX_ANT - ACX100_IOCTL] = acx_ioctl_set_tx_antenna, +[ACX100_IOCTL_SET_PHY_AMP_BIAS - ACX100_IOCTL] = acx100_ioctl_set_phy_amp_bias, +[ACX100_IOCTL_GET_PHY_CHAN_BUSY - ACX100_IOCTL] = acx_ioctl_get_phy_chan_busy_percentage, +[ACX100_IOCTL_SET_ED - ACX100_IOCTL] = acx_ioctl_set_ed_threshold, +[ACX100_IOCTL_SET_CCA - ACX100_IOCTL] = acx_ioctl_set_cca, +[ACX100_IOCTL_MONITOR - ACX100_IOCTL] = acx_ioctl_wlansniff, +[ACX100_IOCTL_TEST - ACX100_IOCTL] = acx_ioctl_unknown11, +[ACX100_IOCTL_DBG_SET_MASKS - ACX100_IOCTL] = acx_ioctl_dbg_set_masks, +[ACX111_IOCTL_INFO - ACX100_IOCTL] = acx111_ioctl_info, +}; + + +static const struct iw_priv_args acx_ioctl_private_args[] = { +#if ACX_DEBUG +{ cmd : ACX100_IOCTL_DEBUG, + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetDebug" }, +#endif +{ cmd : ACX100_IOCTL_SET_PLED, + set_args : IW_PRIV_TYPE_BYTE | 2, + get_args : 0, + name : "SetLEDPower" }, +{ cmd : ACX100_IOCTL_GET_PLED, + set_args : 0, + get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, + name : "GetLEDPower" }, +{ cmd : ACX100_IOCTL_SET_RATES, + set_args : IW_PRIV_TYPE_CHAR | 256, + get_args : 0, + name : "SetRates" }, +{ cmd : ACX100_IOCTL_LIST_DOM, + set_args : 0, + get_args : 0, + name : "ListRegDomain" }, +{ cmd : ACX100_IOCTL_SET_DOM, + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetRegDomain" }, +{ cmd : ACX100_IOCTL_GET_DOM, + set_args : 0, + get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + name : "GetRegDomain" }, +{ cmd : ACX100_IOCTL_SET_SCAN_PARAMS, + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, + get_args : 0, + name : "SetScanParams" }, +{ cmd : ACX100_IOCTL_GET_SCAN_PARAMS, + set_args : 0, + get_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, + name : "GetScanParams" }, +{ cmd : ACX100_IOCTL_SET_PREAMB, + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetSPreamble" }, +{ cmd : ACX100_IOCTL_GET_PREAMB, + set_args : 0, + get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + name : "GetSPreamble" }, +{ cmd : ACX100_IOCTL_SET_ANT, + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetAntenna" }, +{ cmd : ACX100_IOCTL_GET_ANT, + set_args : 0, + get_args : 0, + name : "GetAntenna" }, +{ cmd : ACX100_IOCTL_RX_ANT, + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetRxAnt" }, +{ cmd : ACX100_IOCTL_TX_ANT, + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetTxAnt" }, +{ cmd : ACX100_IOCTL_SET_PHY_AMP_BIAS, + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetPhyAmpBias"}, +{ cmd : ACX100_IOCTL_GET_PHY_CHAN_BUSY, + set_args : 0, + get_args : 0, + name : "GetPhyChanBusy" }, +{ cmd : ACX100_IOCTL_SET_ED, + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetED" }, +{ cmd : ACX100_IOCTL_SET_CCA, + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + get_args : 0, + name : "SetCCA" }, +{ cmd : ACX100_IOCTL_MONITOR, + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + get_args : 0, + name : "monitor" }, +{ cmd : ACX100_IOCTL_TEST, + set_args : 0, + get_args : 0, + name : "Test" }, +{ cmd : ACX100_IOCTL_DBG_SET_MASKS, + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + get_args : 0, + name : "DbgSetMasks" }, +{ cmd : ACX111_IOCTL_INFO, + set_args : 0, + get_args : 0, + name : "GetAcx111Info" }, +{ cmd : ACX100_IOCTL_DBG_SET_IO, + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, + get_args : 0, + name : "DbgSetIO" }, +{ cmd : ACX100_IOCTL_DBG_GET_IO, + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + get_args : 0, + name : "DbgGetIO" }, +}; + + +const struct iw_handler_def acx_ioctl_handler_def = +{ + .num_standard = VEC_SIZE(acx_ioctl_handler), + .num_private = VEC_SIZE(acx_ioctl_private_handler), + .num_private_args = VEC_SIZE(acx_ioctl_private_args), + .standard = (iw_handler *) acx_ioctl_handler, + .private = (iw_handler *) acx_ioctl_private_handler, + .private_args = (struct iw_priv_args *) acx_ioctl_private_args, +#if IW_HANDLER_VERSION > 5 + .get_wireless_stats = acx_e_get_wireless_stats +#endif /* IW > 5 */ +}; --- linux-2.6.27.orig/ubuntu/misc/wireless/acx/Makefile +++ linux-2.6.27/ubuntu/misc/wireless/acx/Makefile @@ -0,0 +1,5 @@ +EXTRA_CFLAGS = -DCONFIG_NET_ACX_PCI -DCONFIG_NET_ACX_USB + +obj-$(CONFIG_WIRELESS_ACX) += acx.o + +acx-objs := wlan.o conv.o ioctl.o common.o pci.o usb.o --- linux-2.6.27.orig/ubuntu/misc/media/Kconfig +++ linux-2.6.27/ubuntu/misc/media/Kconfig @@ -0,0 +1,13 @@ +menu "Media related drivers" + +config SND_BTSCO + tristate "Bluetooth SCO Sound driver" + default m + depends on SND && BT + +config USB_OV511_NEW + tristate "OmniVision OV511 Camera-to-USB Bridge Driver" + default m + depends on USB && VIDEO_V4L2 + +endmenu --- linux-2.6.27.orig/ubuntu/misc/media/snd-bt-sco.c +++ linux-2.6.27/ubuntu/misc/media/snd-bt-sco.c @@ -0,0 +1,1231 @@ +/* + * Bluetooth SCO soundcard + * Copyright (c) 2003, 2004 by Jonathan Paisley + * + * Based on dummy.c which is + * Copyright (c) by Jaroslav Kysela + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +/* note: defining these two independently is not tested, + * thus not recommended + */ + +/* enable dynamic compression */ +#define DYNAMIC_COMPRESSION +/* enable automatic endianness fixup */ +#define AUTO_FIXUP_BYTESHIFT + + +#ifdef DYNAMIC_COMPRESSION +/* Autoadjust mic at most this often in 1/8000s */ +#define GRABSAMPLES 400 +/* Maximum push for the mike 16= 1:1 - default 20:1 = 320 */ +#define COMPRESSION_MAX_16 320 +/* Minimum push for the mike 1= 1:16 */ +#define COMPRESSION_MIN_16 1 +#endif + +#define chip_t snd_card_bt_sco_t + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// this was ostensibly for newer kernels but fails on 2.6.19.2 +#if 0 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) +#include +#endif +#endif +#include +#include +#include +#include +#include +#define SNDRV_GET_ID +#include + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) +#include +#else +#define mutex semaphore +#define mutex_init init_MUTEX +#define mutex_lock down +#define mutex_unlock up +#endif + +#ifndef SNDRV_HWDEP_IFACE_BLUETOOTH +#define SNDRV_HWDEP_IFACE_BLUETOOTH (SNDRV_HWDEP_IFACE_EMUX_WAVETABLE + 1) +#endif + +#ifndef SNDRV_HWDEP_IFACE_BT_SCO +#define SNDRV_HWDEP_IFACE_BT_SCO (SNDRV_HWDEP_IFACE_BLUETOOTH + 1) +#endif + +#define SNDRV_BT_SCO_IOCTL_SET_SCO_SOCKET _IOW ('H', 0x10, int) +#define SNDRV_BT_SCO_IOCTL_REQ_INFO _IO ('H', 0x11) + +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ + +#define MOD_REVISION "$Revision: 1.19 $"; +static char *mod_revision = MOD_REVISION; + +MODULE_AUTHOR("Jonathan Paisley "); +MODULE_DESCRIPTION("Bluetooth SCO Headset Soundcard"); +MODULE_VERSION(MOD_REVISION); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{ALSA,Bluetooth SCO Soundcard}}"); + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for Bluetooth SCO Headset Soundcard."); + +#undef dprintk +#if 1 +#define dprintk(fmt...) printk(KERN_INFO "snd-bt-sco: " fmt) +#else +#define dprintk(fmt...) do {} while(0) +#endif + +#define MAX_BUFFER_SIZE (32*1024) + +#define MIXER_ADDR_MASTER 0 +#define MIXER_ADDR_MIC 1 +#define MIXER_ADDR_LAST 1 + +#define MIXER_MASK_MASTER 1 +#define MIXER_MASK_MIC 2 + +#define MIXER_MIN_VOLUME 1 +#define MIXER_MAX_VOLUME 15 + +struct snd_card_bt_sco_pcm; + +typedef struct snd_card_bt_sco_info { + int mixer_volume[MIXER_ADDR_LAST + 1]; + int playback_count, capture_count; +} snd_card_bt_sco_info_t; + +typedef struct snd_card_bt_sco { + struct snd_card *card; + spinlock_t mixer_lock; + int mixer_volume[MIXER_ADDR_LAST + 1]; +#ifdef DYNAMIC_COMPRESSION + struct snd_kcontrol *mixer_controls[MIXER_ADDR_LAST + 2 + 1]; /* also loopback and agc */ +#else + struct snd_kcontrol *mixer_controls[MIXER_ADDR_LAST + 2 ]; /* also loopback */ +#endif + volatile int loopback; +#ifdef DYNAMIC_COMPRESSION + volatile int agc; +#endif + atomic_t playback_count, capture_count; + volatile int count_changed; + spinlock_t count_changed_lock; + + spinlock_t mixer_changed_lock; + volatile int mixer_changed; + wait_queue_head_t hwdep_wait; + + struct task_struct *thread; + + struct mutex thread_sem; + + volatile struct socket *sco_sock; + struct mutex sock_sem; + wait_queue_head_t wait; + + struct mutex playback_sem; + struct snd_card_bt_sco_pcm *playback; + struct mutex capture_sem; + struct snd_card_bt_sco_pcm *capture; +} snd_card_bt_sco_t; + +typedef struct snd_card_bt_sco_pcm { + snd_card_bt_sco_t *bt_sco; + spinlock_t lock; + unsigned int pcm_size; + unsigned int pcm_count; + unsigned int pcm_bps; /* bytes per second */ + unsigned int pcm_irq_pos; /* IRQ position */ + unsigned int pcm_buf_pos; /* position in buffer */ + struct snd_pcm_substream *substream; +} snd_card_bt_sco_pcm_t; + +static struct snd_card *snd_bt_sco_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; + +static int snd_card_bt_sco_playback_trigger(struct snd_pcm_substream * + substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_pcm_t *bspcm = runtime->private_data; + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream); + + dprintk("playback_trigger %d\n", cmd); + + if (cmd == SNDRV_PCM_TRIGGER_START) { + bt_sco->playback = bspcm; + dprintk("setting playback to bspcm\n"); + } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { + bt_sco->playback = NULL; + dprintk("setting playback to NULL\n"); + } else { + return -EINVAL; + } + return 0; +} + +static int snd_card_bt_sco_capture_trigger(struct snd_pcm_substream * + substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_pcm_t *bspcm = runtime->private_data; + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream); + + dprintk("capture_trigger %d\n", cmd); + + if (cmd == SNDRV_PCM_TRIGGER_START) { + bt_sco->capture = bspcm; + dprintk("setting capture to bspcm\n"); + } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { + bt_sco->capture = NULL; + dprintk("setting capture to NULL\n"); + } else { + return -EINVAL; + } + return 0; +} + +static int snd_card_bt_sco_pcm_prepare(struct snd_pcm_substream * substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_pcm_t *bspcm = runtime->private_data; + unsigned int bps; + + bps = runtime->rate * runtime->channels; + bps *= snd_pcm_format_width(runtime->format); + bps /= 8; + if (bps <= 0) + return -EINVAL; + bspcm->pcm_bps = bps; + bspcm->pcm_size = snd_pcm_lib_buffer_bytes(substream); + bspcm->pcm_count = snd_pcm_lib_period_bytes(substream); + bspcm->pcm_irq_pos = 0; + bspcm->pcm_buf_pos = 0; + dprintk("prepare ok bps: %d size: %d count: %d\n", + bspcm->pcm_bps, bspcm->pcm_size, bspcm->pcm_count); + return 0; +} + +static int snd_card_bt_sco_playback_prepare(struct snd_pcm_substream * substream) +{ + return snd_card_bt_sco_pcm_prepare(substream); +} + +static int snd_card_bt_sco_capture_prepare(struct snd_pcm_substream * substream) +{ + dprintk("capture_prepare\n"); + return snd_card_bt_sco_pcm_prepare(substream); +} + +static void snd_card_bt_sco_pcm_receive(snd_card_bt_sco_pcm_t * bspcm, + unsigned char *data, unsigned int len) +{ + unsigned long flags; + unsigned int oldptr; + + spin_lock_irqsave(&bspcm->lock, flags); + oldptr = bspcm->pcm_buf_pos; + bspcm->pcm_irq_pos += len; + bspcm->pcm_buf_pos += len; + bspcm->pcm_buf_pos %= bspcm->pcm_size; + spin_unlock_irqrestore(&bspcm->lock, flags); + /* copy a data chunk */ + if (oldptr + len > bspcm->pcm_size) { + unsigned int cnt = bspcm->pcm_size - oldptr; + memcpy(bspcm->substream->runtime->dma_area + oldptr, data, cnt); + memcpy(bspcm->substream->runtime->dma_area, data + cnt, + len - cnt); + } else { + memcpy(bspcm->substream->runtime->dma_area + oldptr, data, len); + } + /* update the pointer, call callback if necessary */ + spin_lock_irqsave(&bspcm->lock, flags); + if (bspcm->pcm_irq_pos >= bspcm->pcm_count) { + bspcm->pcm_irq_pos %= bspcm->pcm_count; + spin_unlock_irqrestore(&bspcm->lock, flags); + snd_pcm_period_elapsed(bspcm->substream); + } else + spin_unlock_irqrestore(&bspcm->lock, flags); + +} + +static void snd_card_bt_sco_pcm_send(snd_card_bt_sco_pcm_t * bspcm, + unsigned char *data, unsigned int len) +{ + unsigned long flags; + unsigned int oldptr; + + spin_lock_irqsave(&bspcm->lock, flags); + oldptr = bspcm->pcm_buf_pos; + bspcm->pcm_irq_pos += len; + bspcm->pcm_buf_pos += len; + bspcm->pcm_buf_pos %= bspcm->pcm_size; + spin_unlock_irqrestore(&bspcm->lock, flags); + /* copy a data chunk */ + if (oldptr + len > bspcm->pcm_size) { + unsigned int cnt = bspcm->pcm_size - oldptr; + memcpy(data, bspcm->substream->runtime->dma_area + oldptr, cnt); + memcpy(data + cnt, bspcm->substream->runtime->dma_area, + len - cnt); + } else { + memcpy(data, bspcm->substream->runtime->dma_area + oldptr, len); + } + /* update the pointer, call callback if necessary */ + spin_lock_irqsave(&bspcm->lock, flags); + if (bspcm->pcm_irq_pos >= bspcm->pcm_count) { + bspcm->pcm_irq_pos %= bspcm->pcm_count; + spin_unlock_irqrestore(&bspcm->lock, flags); + snd_pcm_period_elapsed(bspcm->substream); + } else + spin_unlock_irqrestore(&bspcm->lock, flags); +} + +static snd_pcm_uframes_t +snd_card_bt_sco_playback_pointer(struct snd_pcm_substream * substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_pcm_t *bspcm = runtime->private_data; + + return bytes_to_frames(runtime, bspcm->pcm_buf_pos); +} + +static snd_pcm_uframes_t +snd_card_bt_sco_capture_pointer(struct snd_pcm_substream * substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_pcm_t *bspcm = runtime->private_data; + + return bytes_to_frames(runtime, bspcm->pcm_buf_pos); +} + +static struct snd_pcm_hardware snd_card_bt_sco_playback = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 1, + .channels_max = 1, + .buffer_bytes_max = MAX_BUFFER_SIZE, + .period_bytes_min = 24, + .period_bytes_max = MAX_BUFFER_SIZE, + .periods_min = 1, + .periods_max = 4 * 8000 / 24, + .fifo_size = 0, +}; + +static struct snd_pcm_hardware snd_card_bt_sco_capture = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 1, + .channels_max = 1, + .buffer_bytes_max = MAX_BUFFER_SIZE, + .period_bytes_min = 24, + .period_bytes_max = MAX_BUFFER_SIZE, + .periods_min = 1, + .periods_max = 4 * 8000 / 24, + .fifo_size = 0, +}; + +static void snd_card_bt_sco_runtime_free(struct snd_pcm_runtime * runtime) +{ + snd_card_bt_sco_pcm_t *bspcm = runtime->private_data; + kfree(bspcm); +} + +static int snd_card_bt_sco_playback_open(struct snd_pcm_substream * substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_pcm_t *bspcm; + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream); + + dprintk("playback_open\n"); + + bspcm = kmalloc(sizeof(*bspcm), GFP_KERNEL); + if (bspcm == NULL) + return -ENOMEM; + memset(bspcm, 0, sizeof(*bspcm)); + if ((runtime->dma_area = + snd_malloc_pages(MAX_BUFFER_SIZE, GFP_KERNEL)) == NULL) { + kfree(bspcm); + return -ENOMEM; + } + runtime->dma_bytes = MAX_BUFFER_SIZE; + spin_lock_init(&bspcm->lock); + bspcm->substream = substream; + runtime->private_data = bspcm; + runtime->private_free = snd_card_bt_sco_runtime_free; + runtime->hw = snd_card_bt_sco_playback; + + atomic_inc(&bt_sco->playback_count); + spin_lock_irq(&bt_sco->count_changed_lock); + bt_sco->count_changed = 1; + spin_unlock_irq(&bt_sco->count_changed_lock); + wake_up(&bt_sco->hwdep_wait); + + return 0; +} + +static int snd_card_bt_sco_capture_open(struct snd_pcm_substream * substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_pcm_t *bspcm; + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream); + + dprintk("capture_open\n"); + + bspcm = kmalloc(sizeof(*bspcm), GFP_KERNEL); + if (bspcm == NULL) + return -ENOMEM; + memset(bspcm, 0, sizeof(*bspcm)); + if ((runtime->dma_area = + snd_malloc_pages(MAX_BUFFER_SIZE, GFP_KERNEL)) == NULL) { + kfree(bspcm); + return -ENOMEM; + } + runtime->dma_bytes = MAX_BUFFER_SIZE; + memset(runtime->dma_area, 0, runtime->dma_bytes); + spin_lock_init(&bspcm->lock); + bspcm->substream = substream; + runtime->private_data = bspcm; + runtime->private_free = snd_card_bt_sco_runtime_free; + runtime->hw = snd_card_bt_sco_capture; + + atomic_inc(&bt_sco->capture_count); + spin_lock_irq(&bt_sco->count_changed_lock); + bt_sco->count_changed = 1; + spin_unlock_irq(&bt_sco->count_changed_lock); + wake_up(&bt_sco->hwdep_wait); + + return 0; +} + +static int snd_card_bt_sco_playback_close(struct snd_pcm_substream * substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream); + + snd_assert(bt_sco->playback == NULL,; + ); + + /* Ensure any references to this in our thread have finished */ + mutex_lock(&bt_sco->playback_sem); + mutex_unlock(&bt_sco->playback_sem); + + atomic_dec(&bt_sco->playback_count); + spin_lock_irq(&bt_sco->count_changed_lock); + bt_sco->count_changed = 1; + spin_unlock_irq(&bt_sco->count_changed_lock); + wake_up(&bt_sco->hwdep_wait); + + snd_free_pages(runtime->dma_area, runtime->dma_bytes); + return 0; +} + +static int snd_card_bt_sco_capture_close(struct snd_pcm_substream * substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_card_bt_sco *bt_sco = + (struct snd_card_bt_sco *)substream->private_data; + + snd_assert(bt_sco->capture == NULL,; + ); + + /* Ensure any references to this in our thread have finished */ + mutex_lock(&bt_sco->capture_sem); + mutex_unlock(&bt_sco->capture_sem); + + atomic_dec(&bt_sco->capture_count); + spin_lock_irq(&bt_sco->count_changed_lock); + bt_sco->count_changed = 1; + spin_unlock_irq(&bt_sco->count_changed_lock); + wake_up(&bt_sco->hwdep_wait); + + snd_free_pages(runtime->dma_area, runtime->dma_bytes); + return 0; +} + +static struct snd_pcm_ops snd_card_bt_sco_playback_ops = { + .open = snd_card_bt_sco_playback_open, + .close = snd_card_bt_sco_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .prepare = snd_card_bt_sco_playback_prepare, + .trigger = snd_card_bt_sco_playback_trigger, + .pointer = snd_card_bt_sco_playback_pointer, +}; + +static struct snd_pcm_ops snd_card_bt_sco_capture_ops = { + .open = snd_card_bt_sco_capture_open, + .close = snd_card_bt_sco_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .prepare = snd_card_bt_sco_capture_prepare, + .trigger = snd_card_bt_sco_capture_trigger, + .pointer = snd_card_bt_sco_capture_pointer, +}; + +static int __init snd_card_bt_sco_pcm(snd_card_bt_sco_t * bt_sco) +{ + struct snd_pcm *pcm; + int err; + + if ((err = + snd_pcm_new(bt_sco->card, "Bluetooth SCO PCM", 0, 1, 1, &pcm)) < 0) + return err; + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_card_bt_sco_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_card_bt_sco_capture_ops); + pcm->private_data = bt_sco; + pcm->info_flags = 0; + strcpy(pcm->name, "BT SCO PCM"); + return 0; +} + +#define BT_SCO_VOLUME(xname, xindex, addr) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ + .info = snd_bt_sco_volume_info, \ + .get = snd_bt_sco_volume_get, .put = snd_bt_sco_volume_put, \ + .private_value = addr } + +static int snd_bt_sco_volume_info(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_info * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = MIXER_MIN_VOLUME; + uinfo->value.integer.max = MIXER_MAX_VOLUME; + return 0; +} + +static int snd_bt_sco_volume_get(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) +{ + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int addr = kcontrol->private_value; + + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + ucontrol->value.integer.value[0] = bt_sco->mixer_volume[addr]; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + return 0; +} + +static int snd_bt_sco_volume_put(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) +{ + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int changed, addr = kcontrol->private_value; + int vol; + + vol = ucontrol->value.integer.value[0]; + if (vol < MIXER_MIN_VOLUME) + vol = MIXER_MIN_VOLUME; + if (vol > MIXER_MAX_VOLUME) + vol = MIXER_MAX_VOLUME; + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + changed = bt_sco->mixer_volume[addr] != vol; + bt_sco->mixer_volume[addr] = vol; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + if (changed) { + spin_lock_irqsave(&bt_sco->mixer_changed_lock, flags); + bt_sco->mixer_changed = 1; + spin_unlock_irqrestore(&bt_sco->mixer_changed_lock, flags); + wake_up(&bt_sco->hwdep_wait); + } + return changed; +} + +static int snd_bt_sco_boolean_info(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_info * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_bt_sco_loopback_get(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) +{ + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + ucontrol->value.integer.value[0] = bt_sco->loopback; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + return 0; +} + +static int snd_bt_sco_loopback_put(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) +{ + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int changed; + int loopback; + + loopback = !!ucontrol->value.integer.value[0]; + + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + changed = bt_sco->loopback != loopback; + bt_sco->loopback = loopback; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + return changed; +} + +#ifdef DYNAMIC_COMPRESSION +static int snd_bt_sco_agc_get(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) +{ + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + ucontrol->value.integer.value[0] = bt_sco->agc; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + return 0; +} + +static int snd_bt_sco_agc_put(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) +{ + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int changed; + int agc; + + agc = !!ucontrol->value.integer.value[0]; + + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + changed = bt_sco->agc != agc; + bt_sco->agc = agc; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + return changed; +} +#endif + +#define BT_SCO_CONTROLS (sizeof(snd_bt_sco_controls)/sizeof(struct snd_kcontrol_new)) + +static struct snd_kcontrol_new snd_bt_sco_controls[] = { + BT_SCO_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER), + BT_SCO_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC), + {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Loopback Switch", + .index = 0, + .info = snd_bt_sco_boolean_info, + .get = snd_bt_sco_loopback_get, + .put = snd_bt_sco_loopback_put, + } +#ifdef DYNAMIC_COMPRESSION + , + {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "AGC Switch", + .index = 0, + .info = snd_bt_sco_boolean_info, + .get = snd_bt_sco_agc_get, + .put = snd_bt_sco_agc_put, + } +#endif +}; + +int __init snd_card_bt_sco_new_mixer(snd_card_bt_sco_t * bt_sco) +{ + struct snd_card *card = bt_sco->card; + + unsigned int idx; + int err; + + snd_assert(bt_sco != NULL, return -EINVAL); + spin_lock_init(&bt_sco->mixer_lock); + strcpy(card->mixername, "BT Headset Mixer"); + + for (idx = 0; idx < BT_SCO_CONTROLS; idx++) { + bt_sco->mixer_controls[idx] = + snd_ctl_new1(&snd_bt_sco_controls[idx], bt_sco); + + if ((err = snd_ctl_add(card, bt_sco->mixer_controls[idx])) < 0) + return err; + } + return 0; +} + +static int snd_card_bt_open(struct snd_hwdep * hw, struct file *file) +{ + return 0; +} + +static int snd_card_bt_release(struct snd_hwdep * hw, struct file *file) +{ + return 0; +} + +static int snd_card_bt_ioctl(struct snd_hwdep * hw, struct file *file, + unsigned int cmd, unsigned long arg) +{ + snd_card_bt_sco_t *bt_sco = hw->card->private_data; + struct socket *sock; + int err = -ENOTTY; + int fd = arg; + + switch (cmd) { + case SNDRV_BT_SCO_IOCTL_SET_SCO_SOCKET: + err = 0; + /* Interrupt any socket operations, so that we may + * change the socket */ + mutex_lock(&bt_sco->sock_sem); + kthread_stop(bt_sco->thread); + if (bt_sco->sco_sock) { + dprintk("Disposing of previous socket count %d\n", + file_count(bt_sco->sco_sock->file)); + /* Extra brackets needed here since sockfd_put is a poorly implemented macro */ + sockfd_put(((struct socket *)bt_sco->sco_sock)); + + bt_sco->sco_sock = NULL; + } + + if (fd >= 0) { + err = -EINVAL; + sock = sockfd_lookup(fd, &err); + if (sock) { + if (sock->sk->sk_family == PF_BLUETOOTH && + sock->sk->sk_protocol == BTPROTO_SCO) { + bt_sco->sco_sock = sock; + wake_up(&bt_sco->wait); + err = 0; + } else { + dprintk + ("Not a bluetooth SCO socket %d:%d\n", + sock->sk->sk_family, + sock->sk->sk_protocol); + sockfd_put(sock); + } + } + } + mutex_unlock(&bt_sco->sock_sem); + break; + case SNDRV_BT_SCO_IOCTL_REQ_INFO: + spin_lock_irq(&bt_sco->count_changed_lock); + bt_sco->count_changed = 1; + spin_unlock_irq(&bt_sco->count_changed_lock); + wake_up(&bt_sco->hwdep_wait); + break; + } + return err; +} + +static long snd_card_bt_write(struct snd_hwdep * hw, const char *buf, long count, + loff_t * offset) +{ + snd_card_bt_sco_t *bt_sco = hw->card->private_data; + int mixer_volume[MIXER_ADDR_LAST + 1]; + int retval; + int i; + + if (count != sizeof(mixer_volume)) + return -EINVAL; + + if (copy_from_user(mixer_volume, buf, sizeof(mixer_volume))) + return -EFAULT; + + retval = sizeof(mixer_volume); + + spin_lock_irq(&bt_sco->mixer_lock); + for (i = 0; i <= MIXER_ADDR_LAST; i++) { + int vol = mixer_volume[i]; + if (vol > MIXER_MAX_VOLUME) + vol = MIXER_MAX_VOLUME; + if (vol < MIXER_MIN_VOLUME) + vol = MIXER_MIN_VOLUME; + if (bt_sco->mixer_volume[i] != vol) { + bt_sco->mixer_volume[i] = vol; + snd_ctl_notify(bt_sco->card, + SNDRV_CTL_EVENT_MASK_VALUE, + &bt_sco->mixer_controls[i]->id); + } + } + spin_unlock_irq(&bt_sco->mixer_lock); + + return retval; +} + +static long snd_card_bt_read(struct snd_hwdep * hw, char *buf, long count, + loff_t * offset) +{ + snd_card_bt_sco_t *bt_sco = hw->card->private_data; + DECLARE_WAITQUEUE(wait, current); + ssize_t retval; + int changed; + snd_card_bt_sco_info_t infobuf; + + if (count < sizeof(bt_sco->mixer_volume)) + return -EINVAL; + + add_wait_queue(&bt_sco->hwdep_wait, &wait); + current->state = TASK_INTERRUPTIBLE; + do { + changed = 0; + spin_lock_irq(&bt_sco->mixer_changed_lock); + if(bt_sco->mixer_changed) + changed = 1; + bt_sco->mixer_changed = 0; + spin_unlock_irq(&bt_sco->mixer_changed_lock); + + spin_lock_irq(&bt_sco->count_changed_lock); + if(bt_sco->count_changed) + changed = 1; + bt_sco->count_changed = 0; + spin_unlock_irq(&bt_sco->count_changed_lock); + + if (changed != 0) + break; + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + schedule(); + } while (1); + + memcpy(infobuf.mixer_volume, bt_sco->mixer_volume, sizeof(infobuf.mixer_volume)); + infobuf.playback_count = atomic_read(&bt_sco->playback_count); + infobuf.capture_count = atomic_read(&bt_sco->capture_count); + + if (copy_to_user + (buf, &infobuf, sizeof(infobuf))) + retval = -EFAULT; + else + retval = sizeof(infobuf); + + out: + current->state = TASK_RUNNING; + remove_wait_queue(&bt_sco->hwdep_wait, &wait); + return retval; +} + +static unsigned int snd_card_bt_poll(struct snd_hwdep * hw, + struct file *file, poll_table * wait) +{ + snd_card_bt_sco_t *bt_sco = hw->card->private_data; + int ret; + + poll_wait(file, &bt_sco->hwdep_wait, wait); + + ret = 0; + spin_lock_irq(&bt_sco->mixer_changed_lock); + if(bt_sco->mixer_changed) + ret |= POLLIN | POLLRDNORM; + spin_unlock_irq(&bt_sco->mixer_changed_lock); + + spin_lock_irq(&bt_sco->count_changed_lock); + if(bt_sco->count_changed) + ret |= POLLIN | POLLRDNORM; + spin_unlock_irq(&bt_sco->count_changed_lock); + + return ret; +} + +static int snd_card_bt_sco_thread(void *data) +{ + struct snd_card *card = (struct snd_card *) data; + snd_card_bt_sco_t *bt_sco = card->private_data; + struct socket *sock; + int len; +#define BUF_SIZE 256 + unsigned char buf[BUF_SIZE]; + struct msghdr msg; + struct iovec iov; +#if defined(DYNAMIC_COMPRESSION) || defined(AUTO_FIXUP_BYTESHIFT) + int i; +#endif +#ifdef DYNAMIC_COMPRESSION + static int factor=16; + static int maxvalsmoothed=0; + static int maxvalgrablen=GRABSAMPLES; /* adjust volume at most 4 times/second */ +#endif +#ifdef AUTO_FIXUP_BYTESHIFT + static int shift=0; + static unsigned char lastbyte; +#endif + + set_freezable(); + + dprintk("snd-bt-scod thread starting\n"); + mutex_unlock(&bt_sco->thread_sem); + + do { + /* This may be woken up by a wake_up() when + * a new socket is installed, or by a signal. + * Signals are sent to terminate the thread, + * in which case thread_exit is set, and to force + * recvmesg() to wake up (from the ioctl handler) + */ + wait_event_freezable(bt_sco->wait, bt_sco->sco_sock || kthread_should_stop()); + + mutex_lock(&bt_sco->sock_sem); + sock = (struct socket *)bt_sco->sco_sock; + if (sock) + get_file(sock->file); + mutex_unlock(&bt_sco->sock_sem); + + if (!sock) + continue; + + /* We have a socket, let's read from it and write to it... */ + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iov; + iov.iov_base = buf; + iov.iov_len = BUF_SIZE; + + /* This will block until we receive data or a signal */ + len = sock_recvmsg(sock, &msg, BUF_SIZE, 0); + if (len > 0) { + +#if defined (AUTO_FIXUP_BYTESHIFT) || defined (DYNAMIC_COMPRESSION) + +#ifdef AUTO_FIXUP_BYTESHIFT + int lostatcnt=0; +#endif + if (len&1) dprintk("odd len %d\n",len); +#ifdef AUTO_FIXUP_BYTESHIFT + if (shift) { + unsigned char newlastbyte; + newlastbyte=buf[len-1]; + memmove(buf+1,buf,len-1); + buf[0]=lastbyte; + lastbyte=newlastbyte; + } +#endif + for(i=0;i0x7fff) { + k=0x7fff; + if (bt_sco->agc&&factor>COMPRESSION_MIN_16) factor--; + } else if (k<-0x8000) { + k=0x8000; + if (bt_sco->agc&&factor>COMPRESSION_MIN_16) factor--; + } + buf[i+1]=(k>>8)&0xff; + buf[i ]=k&0xff; + + /* find the highest absolute value in a + * GRABSAMPLES long interval. + */ + if (k<0) k=-j; + if (k>maxvalsmoothed) maxvalsmoothed=k; + /* if the interval is over, recalculate + * the compression factor. Move it slowly. + */ + if (maxvalgrablen--<=0) { + maxvalgrablen=GRABSAMPLES; + /* If the noise goes up over 1000, we stop + * pushing the software gain + */ + if (maxvalsmoothed<1000&&factoragc) factor=16; + maxvalsmoothed=0; + } +#endif + } +#ifdef AUTO_FIXUP_BYTESHIFT + if (lostatcnt==len/2&&len>32) { + shift=!shift; + //dprintk("Shift problem detected! Fixing to %d.\n",shift); + } +#endif +#endif /* any of them */ + mutex_lock(&bt_sco->capture_sem); + if (bt_sco->capture) { + snd_card_bt_sco_pcm_receive + (bt_sco->capture, buf, len); + } + mutex_unlock(&bt_sco->capture_sem); + + mutex_lock(&bt_sco->playback_sem); + + if (bt_sco->playback || !bt_sco->loopback) { + memset(buf, 0, len); +#if 0 + /* fill with tone instead of silence */ + int i; + + for (i = 0; i < len / 2; i++) { + buf[i] = 0; + } + for (i = len / 2; i < len; i++) { + buf[i] = 127; + } +#endif + } + if (bt_sco->playback) { + int i, notzero = -1; + + snd_card_bt_sco_pcm_send + (bt_sco->playback, buf, len); + + /* Strangely, when the device is open but no audio is + being written by the app, there's an occasional glitch + in the silence data. This hack eliminates it. */ + + for (i = 0; i < len; i++) { + if (buf[i] != 0) { + if (notzero >= 0) + break; + notzero = i; + } + } + if (notzero >= 0 && i >= len) { + buf[notzero] = 0; + } + } + mutex_unlock(&bt_sco->playback_sem); + +#if 0 + /* This chunk of code lets us record (using arecord) + what data alsa is sending out. + + e.g., when idle, we'd expect something like: + + 8080 8080 8080 8080 8483 8281 8182 8384 + 8080 8080 8080 8080 8080 8080 8080 8080 + 8080 8080 8080 8080 8483 8281 8182 8384 + 8080 8080 8080 8080 8080 8080 8080 8080 + + (this is from 'xxd' of a wav file, that data in + which is unsigned, whereas we are dealing with signed). + */ + + mutex_lock(&bt_sco->capture_sem); + if (bt_sco->capture) { + snd_card_bt_sco_pcm_receive + (bt_sco->capture, "\001\002\003\004", 4); + snd_card_bt_sco_pcm_receive + (bt_sco->capture, buf, len); + snd_card_bt_sco_pcm_receive + (bt_sco->capture, "\004\003\002\001", 4); + } + mutex_unlock(&bt_sco->capture_sem); +#endif + msg.msg_flags = 0; + msg.msg_iov = &iov; + iov.iov_base = buf; + iov.iov_len = BUF_SIZE; + sock_sendmsg(sock, &msg, len); + } + + /* Expect this to be 3 because we (this thead) have a copy, + the driver process keeps one, and the app has the socket open. + */ + if (file_count(sock->file) != 3) { + dprintk("file_count is %d (expected 3)\n", + file_count(sock->file)); + } + fput(sock->file); + + schedule(); + } while (!kthread_should_stop() || bt_sco->sco_sock); + + dprintk("thread exiting\n"); + + return 0; +} + +static void snd_card_bt_private_free(struct snd_card * card) +{ + snd_card_bt_sco_t *bt_sco = card->private_data; + + dprintk("private_free, killing thread\n"); + kthread_stop(bt_sco->thread); + dprintk("private_free, thread exited\n"); + + if (bt_sco->sco_sock) { + dprintk("shutdown: freeing socket count %d\n", + file_count(bt_sco->sco_sock->file)); + + sockfd_put(((struct socket *)bt_sco->sco_sock)); + } + + kfree(bt_sco); +} + +static int __init snd_card_bt_sco_probe(int dev) +{ + struct snd_card *card; + snd_card_bt_sco_t *bt_sco; + int err; + struct snd_hwdep *hw; + + card = + snd_card_new(index[dev], SNDRV_DEFAULT_STR1, + THIS_MODULE, 0); + if (card == NULL) + return -ENOMEM; + + bt_sco = kmalloc(sizeof(*bt_sco), GFP_KERNEL); + if(bt_sco == NULL) + return -ENOMEM; + memset(bt_sco, 0, sizeof(*bt_sco)); + card->private_data = bt_sco; + card->private_free = snd_card_bt_private_free; + + bt_sco->card = card; + + mutex_init(&bt_sco->thread_sem); + mutex_lock(&bt_sco->thread_sem); + mutex_init(&bt_sco->sock_sem); + mutex_init(&bt_sco->capture_sem); + mutex_init(&bt_sco->playback_sem); + init_waitqueue_head(&bt_sco->wait); + init_waitqueue_head(&bt_sco->hwdep_wait); + spin_lock_init(&bt_sco->mixer_changed_lock); + spin_lock_init(&bt_sco->count_changed_lock); + + /* These clone flags copied from some other driver. + Not sure that they're really correct... */ + bt_sco->thread = + kthread_run(snd_card_bt_sco_thread, card, "snd-bt-scod"); + if (IS_ERR(bt_sco->thread)) { + err = PTR_ERR(bt_sco->thread); + goto __nodev; + } + + mutex_lock(&bt_sco->thread_sem); + + if ((err = snd_card_bt_sco_pcm(bt_sco)) < 0) + goto __nodev; + if ((err = snd_card_bt_sco_new_mixer(bt_sco)) < 0) + goto __nodev; + strcpy(card->driver, "Bluetooth SCO"); + strcpy(card->shortname, "BT Headset"); + sprintf(card->longname, "BT Headset %i", dev + 1); + + err = snd_hwdep_new(card, "BTSCO", 0, &hw); + if (err < 0) + goto __nodev; + + sprintf(hw->name, "BTSCO"); + hw->iface = SNDRV_HWDEP_IFACE_BT_SCO; + hw->ops.open = snd_card_bt_open; + hw->ops.ioctl = snd_card_bt_ioctl; + hw->ops.release = snd_card_bt_release; + hw->ops.read = snd_card_bt_read; + hw->ops.write = snd_card_bt_write; + hw->ops.poll = snd_card_bt_poll; + + if ((err = snd_card_register(card)) == 0) { + snd_bt_sco_cards[dev] = card; + return 0; + } + __nodev: + snd_card_free(card); + return err; +} + +static int __init alsa_card_bt_sco_init(void) +{ + printk(KERN_INFO "snd-bt-sco revision %s\n", mod_revision + 11); + + if (snd_card_bt_sco_probe(0) < 0) { +#ifdef MODULE + printk(KERN_ERR + "Bluetooth SCO soundcard not found or device busy\n"); +#endif + return -ENODEV; + } + return 0; +} + +static void __exit alsa_card_bt_sco_exit(void) +{ + int idx; + + for (idx = 0; idx < SNDRV_CARDS; idx++) + snd_card_free(snd_bt_sco_cards[idx]); +} + +module_init(alsa_card_bt_sco_init) + module_exit(alsa_card_bt_sco_exit) +#ifndef MODULE +static int __init alsa_card_bt_sco_setup(char *str) +{ + static unsigned __initdata nr_dev = 0; + + if (nr_dev >= SNDRV_CARDS) + return 0; + nr_dev++; + return 1; +} + +__setup("snd-bt-sco=", alsa_card_bt_sco_setup); + +#endif /* ifndef MODULE */ --- linux-2.6.27.orig/ubuntu/misc/media/Makefile +++ linux-2.6.27/ubuntu/misc/media/Makefile @@ -0,0 +1,4 @@ +# + +obj-$(CONFIG_SND_BTSCO) += snd-bt-sco.o +obj-$(CONFIG_USB_OV511_NEW) += ov511/ --- linux-2.6.27.orig/ubuntu/misc/media/ov511/ov511.h +++ linux-2.6.27/ubuntu/misc/media/ov511/ov511.h @@ -0,0 +1,570 @@ +#ifndef __LINUX_OV511_H +#define __LINUX_OV511_H + +#include +#include +#include +#include +#include + +#define OV511_DEBUG /* Turn on debug messages */ + +#ifdef OV511_DEBUG + #define PDEBUG(level, fmt, args...) \ + if (debug >= (level)) info("[%s:%d] " fmt, \ + __FUNCTION__, __LINE__ , ## args) +#else + #define PDEBUG(level, fmt, args...) do {} while(0) +#endif + +/* This macro restricts an int variable to an inclusive range */ +#define RESTRICT_TO_RANGE(v,mi,ma) { \ + if ((v) < (mi)) (v) = (mi); \ + else if ((v) > (ma)) (v) = (ma); \ +} + +/* --------------------------------- */ +/* DEFINES FOR OV511 AND OTHER CHIPS */ +/* --------------------------------- */ + +/* USB IDs */ +#define VEND_OMNIVISION 0x05A9 +#define PROD_OV511 0x0511 +#define PROD_OV511PLUS 0xA511 +#define PROD_OV518 0x0518 +#define PROD_OV518PLUS 0xA518 + +#define VEND_MATTEL 0x0813 +#define PROD_ME2CAM 0x0002 + +/* --------------------------------- */ +/* OV51x REGISTER MNEMONICS */ +/* --------------------------------- */ + +/* Camera interface register numbers */ +#define R511_CAM_DELAY 0x10 +#define R511_CAM_EDGE 0x11 +#define R511_CAM_PXCNT 0x12 +#define R511_CAM_LNCNT 0x13 +#define R511_CAM_PXDIV 0x14 +#define R511_CAM_LNDIV 0x15 +#define R511_CAM_UV_EN 0x16 +#define R511_CAM_LINE_MODE 0x17 +#define R511_CAM_OPTS 0x18 + +/* Snapshot mode camera interface register numbers */ +#define R511_SNAP_FRAME 0x19 +#define R511_SNAP_PXCNT 0x1A +#define R511_SNAP_LNCNT 0x1B +#define R511_SNAP_PXDIV 0x1C +#define R511_SNAP_LNDIV 0x1D +#define R511_SNAP_UV_EN 0x1E +#define R511_SNAP_OPTS 0x1F + +/* DRAM register numbers */ +#define R511_DRAM_FLOW_CTL 0x20 +#define R511_DRAM_ARCP 0x21 +#define R511_DRAM_MRC 0x22 +#define R511_DRAM_RFC 0x23 + +/* ISO FIFO register numbers */ +#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ +#define R511_FIFO_OPTS 0x31 + +/* Parallel IO register numbers */ +#define R511_PIO_OPTS 0x38 +#define R511_PIO_DATA 0x39 +#define R511_PIO_BIST 0x3E +#define R518_GPIO_IN 0x55 /* OV518(+) only */ +#define R518_GPIO_OUT 0x56 /* OV518(+) only */ +#define R518_GPIO_CTL 0x57 /* OV518(+) only */ +#define R518_GPIO_PULSE_IN 0x58 /* OV518(+) only */ +#define R518_GPIO_PULSE_CLEAR 0x59 /* OV518(+) only */ +#define R518_GPIO_PULSE_POL 0x5a /* OV518(+) only */ +#define R518_GPIO_PULSE_EN 0x5b /* OV518(+) only */ +#define R518_GPIO_RESET 0x5c /* OV518(+) only */ + +/* I2C registers */ +#define R511_I2C_CTL 0x40 +#define R518_I2C_CTL 0x47 /* OV518(+) only */ +#define R51x_I2C_W_SID 0x41 +#define R51x_I2C_SADDR_3 0x42 +#define R51x_I2C_SADDR_2 0x43 +#define R51x_I2C_R_SID 0x44 +#define R51x_I2C_DATA 0x45 +#define R51x_I2C_CLOCK 0x46 +#define R51x_I2C_TIMEOUT 0x47 + +/* I2C snapshot registers */ +#define R511_SI2C_SADDR_3 0x48 +#define R511_SI2C_DATA 0x49 + +/* System control registers */ +#define R51x_SYS_RESET 0x50 + /* Reset type definitions */ +#define OV511_RESET_UDC 0x01 +#define OV511_RESET_I2C 0x02 +#define OV511_RESET_FIFO 0x04 +#define OV511_RESET_OMNICE 0x08 +#define OV511_RESET_DRAM 0x10 +#define OV511_RESET_CAM_INT 0x20 +#define OV511_RESET_OV511 0x40 +#define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ +#define OV511_RESET_ALL 0x7F + +#define R511_SYS_CLOCK_DIV 0x51 +#define R51x_SYS_SNAP 0x52 +#define R51x_SYS_INIT 0x53 +#define R511_SYS_PWR_CLK 0x54 /* OV511+/OV518(+) only */ +#define R511_SYS_LED_CTL 0x55 /* OV511+ only */ +#define R511_SYS_USER 0x5E +#define R511_SYS_CUST_ID 0x5F + +/* OmniCE (compression) registers */ +#define R511_COMP_PHY 0x70 +#define R511_COMP_PHUV 0x71 +#define R511_COMP_PVY 0x72 +#define R511_COMP_PVUV 0x73 +#define R511_COMP_QHY 0x74 +#define R511_COMP_QHUV 0x75 +#define R511_COMP_QVY 0x76 +#define R511_COMP_QVUV 0x77 +#define R511_COMP_EN 0x78 +#define R511_COMP_LUT_EN 0x79 +#define R511_COMP_LUT_BEGIN 0x80 + +/* --------------------------------- */ +/* ALTERNATE NUMBERS */ +/* --------------------------------- */ + +/* Alternate numbers for various max packet sizes (OV511 only) */ +#define OV511_ALT_SIZE_992 0 +#define OV511_ALT_SIZE_993 1 +#define OV511_ALT_SIZE_768 2 +#define OV511_ALT_SIZE_769 3 +#define OV511_ALT_SIZE_512 4 +#define OV511_ALT_SIZE_513 5 +#define OV511_ALT_SIZE_257 6 +#define OV511_ALT_SIZE_0 7 + +/* Alternate numbers for various max packet sizes (OV511+ only) */ +#define OV511PLUS_ALT_SIZE_0 0 +#define OV511PLUS_ALT_SIZE_33 1 +#define OV511PLUS_ALT_SIZE_129 2 +#define OV511PLUS_ALT_SIZE_257 3 +#define OV511PLUS_ALT_SIZE_385 4 +#define OV511PLUS_ALT_SIZE_513 5 +#define OV511PLUS_ALT_SIZE_769 6 +#define OV511PLUS_ALT_SIZE_961 7 + +/* Alternate numbers for various max packet sizes (OV518(+) only) */ +#define OV518_ALT_SIZE_0 0 +#define OV518_ALT_SIZE_128 1 +#define OV518_ALT_SIZE_256 2 +#define OV518_ALT_SIZE_384 3 +#define OV518_ALT_SIZE_512 4 +#define OV518_ALT_SIZE_640 5 +#define OV518_ALT_SIZE_768 6 +#define OV518_ALT_SIZE_896 7 + +/* --------------------------------- */ +/* OV7610 REGISTER MNEMONICS */ +/* --------------------------------- */ + +/* OV7610 registers */ +#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ +#define OV7610_REG_BLUE 0x01 /* blue channel balance */ +#define OV7610_REG_RED 0x02 /* red channel balance */ +#define OV7610_REG_SAT 0x03 /* saturation */ + /* 04 reserved */ +#define OV7610_REG_CNT 0x05 /* Y contrast */ +#define OV7610_REG_BRT 0x06 /* Y brightness */ + /* 08-0b reserved */ +#define OV7610_REG_BLUE_BIAS 0x0C /* blue channel bias (5:0) */ +#define OV7610_REG_RED_BIAS 0x0D /* read channel bias (5:0) */ +#define OV7610_REG_GAMMA_COEFF 0x0E /* gamma settings */ +#define OV7610_REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ +#define OV7610_REG_EXP 0x10 /* manual exposure setting */ +#define OV7610_REG_CLOCK 0x11 /* polarity/clock prescaler */ +#define OV7610_REG_COM_A 0x12 /* misc common regs */ +#define OV7610_REG_COM_B 0x13 /* misc common regs */ +#define OV7610_REG_COM_C 0x14 /* misc common regs */ +#define OV7610_REG_COM_D 0x15 /* misc common regs */ +#define OV7610_REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ +#define OV7610_REG_HWIN_START 0x17 /* horizontal window start */ +#define OV7610_REG_HWIN_END 0x18 /* horizontal window end */ +#define OV7610_REG_VWIN_START 0x19 /* vertical window start */ +#define OV7610_REG_VWIN_END 0x1A /* vertical window end */ +#define OV7610_REG_PIXEL_SHIFT 0x1B /* pixel shift */ +#define OV7610_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ +#define OV7610_REG_ID_LOW 0x1D /* manufacturer ID LSB */ + /* 0e-0f reserved */ +#define OV7610_REG_COM_E 0x20 /* misc common regs */ +#define OV7610_REG_YOFFSET 0x21 /* Y channel offset */ +#define OV7610_REG_UOFFSET 0x22 /* U channel offset */ + /* 23 reserved */ +#define OV7610_REG_ECW 0x24 /* Exposure white level for AEC */ +#define OV7610_REG_ECB 0x25 /* Exposure black level for AEC */ +#define OV7610_REG_COM_F 0x26 /* misc settings */ +#define OV7610_REG_COM_G 0x27 /* misc settings */ +#define OV7610_REG_COM_H 0x28 /* misc settings */ +#define OV7610_REG_COM_I 0x29 /* misc settings */ +#define OV7610_REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ +#define OV7610_REG_FRAMERATE_L 0x2B /* frame rate LSB */ +#define OV7610_REG_ALC 0x2C /* Auto Level Control settings */ +#define OV7610_REG_COM_J 0x2D /* misc settings */ +#define OV7610_REG_VOFFSET 0x2E /* V channel offset adjustment */ +#define OV7610_REG_ARRAY_BIAS 0x2F /* Array bias -- don't change */ + /* 30-32 reserved */ +#define OV7610_REG_YGAMMA 0x33 /* misc gamma settings (7:6) */ +#define OV7610_REG_BIAS_ADJUST 0x34 /* misc bias settings */ +#define OV7610_REG_COM_L 0x35 /* misc settings */ + /* 36-37 reserved */ +#define OV7610_REG_COM_K 0x38 /* misc registers */ + +/* --------------------------------- */ +/* I2C ADDRESSES */ +/* --------------------------------- */ + +#define OV7xx0_SID 0x42 +#define OV6xx0_SID 0xC0 +#define OV8xx0_SID 0xA0 +#define KS0127_SID 0xD8 +#define SAA7111A_SID 0x48 + +/* --------------------------------- */ +/* MISCELLANEOUS DEFINES */ +/* --------------------------------- */ + +#define I2C_CLOCK_PRESCALER 0x03 + +#define FRAMES_PER_DESC 10 /* FIXME - What should this be? */ +#define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */ +#define PIXELS_PER_SEG 256 /* Pixels per segment */ + +#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ + +#define OV511_NUMFRAMES 2 +#if OV511_NUMFRAMES > VIDEO_MAX_FRAME + #error "OV511_NUMFRAMES is too high" +#endif + +#define OV511_NUMSBUF 2 + +/* Control transfers use up to 4 bytes */ +#define OV511_CBUF_SIZE 4 + +/* Size of usb_make_path() buffer */ +#define OV511_USB_PATH_LEN 64 + +/* Bridge types */ +enum { + BRG_UNKNOWN, + BRG_OV511, + BRG_OV511PLUS, + BRG_OV518, + BRG_OV518PLUS, +}; + +/* Bridge classes */ +enum { + BCL_UNKNOWN, + BCL_OV511, + BCL_OV518, +}; + +/* Sensor types */ +enum { + SEN_UNKNOWN, + SEN_OV76BE, + SEN_OV7610, + SEN_OV7620, + SEN_OV7620AE, + SEN_OV6620, + SEN_OV6630, + SEN_OV6630AE, + SEN_OV6630AF, + SEN_OV8600, + SEN_KS0127, + SEN_KS0127B, + SEN_SAA7111A, +}; + +enum { + STATE_SCANNING, /* Scanning for start */ + STATE_HEADER, /* Parsing header */ + STATE_LINES, /* Parsing lines */ +}; + +/* Buffer states */ +enum { + BUF_NOT_ALLOCATED, + BUF_ALLOCATED, +}; + +/* --------- Definition of ioctl interface --------- */ + +#define OV511_INTERFACE_VER 101 + +/* LED options */ +enum { + LED_OFF, + LED_ON, + LED_AUTO, +}; + +/* Raw frame formats */ +enum { + RAWFMT_INVALID, + RAWFMT_YUV400, + RAWFMT_YUV420, + RAWFMT_YUV422, + RAWFMT_GBR422, +}; + +struct ov511_i2c_struct { + unsigned char slave; /* Write slave ID (read ID - 1) */ + unsigned char reg; /* Index of register */ + unsigned char value; /* User sets this w/ write, driver does w/ read */ + unsigned char mask; /* Bits to be changed. Not used with read ops */ +}; + +/* ioctls */ +#define OV511IOC_WI2C _IOW('v', BASE_VIDIOCPRIVATE + 5, \ + struct ov511_i2c_struct) +#define OV511IOC_RI2C _IOWR('v', BASE_VIDIOCPRIVATE + 6, \ + struct ov511_i2c_struct) +/* ------------- End IOCTL interface -------------- */ + +struct usb_ov511; /* Forward declaration */ + +struct ov511_sbuf { + struct usb_ov511 *ov; + unsigned char *data; + struct urb *urb; + spinlock_t lock; + int n; +}; + +enum { + FRAME_UNUSED, /* Unused (no MCAPTURE) */ + FRAME_READY, /* Ready to start grabbing */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_ERROR, /* Something bad happened while processing */ +}; + +struct ov511_regvals { + enum { + OV511_DONE_BUS, + OV511_REG_BUS, + OV511_I2C_BUS, + } bus; + unsigned char reg; + unsigned char val; +}; + +struct ov511_frame { + int framenum; /* Index of this frame */ + unsigned char *data; /* Frame buffer */ + unsigned char *tempdata; /* Temp buffer for multi-stage conversions */ + unsigned char *rawdata; /* Raw camera data buffer */ + unsigned char *compbuf; /* Temp buffer for decompressor */ + + int depth; /* Bytes per pixel */ + int width; /* Width application is expecting */ + int height; /* Height application is expecting */ + + int rawwidth; /* Actual width of frame sent from camera */ + int rawheight; /* Actual height of frame sent from camera */ + + int sub_flag; /* Sub-capture mode for this frame? */ + unsigned int format; /* Format for this frame */ + int compressed; /* Is frame compressed? */ + + volatile int grabstate; /* State of grabbing */ + int scanstate; /* State of scanning */ + + int bytes_recvd; /* Number of image bytes received from camera */ + + long bytes_read; /* Amount that has been read() */ + + wait_queue_head_t wq; /* Processes waiting */ + + int snapshot; /* True if frame was a snapshot */ +}; + +#define DECOMP_INTERFACE_VER 4 + +/* Compression module operations */ +struct ov51x_decomp_ops { + int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *, + int, int, int); + int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *, + int, int, int); + int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *, + int, int, int); + struct module *owner; +}; + +struct usb_ov511 { + struct video_device *vdev; + struct usb_device *dev; + + int customid; + char *desc; + unsigned char iface; + char usb_path[OV511_USB_PATH_LEN]; + + /* Determined by sensor type */ + int maxwidth; + int maxheight; + int minwidth; + int minheight; + + int brightness; + int colour; + int contrast; + int hue; + int whiteness; + int exposure; + int auto_brt; /* Auto brightness enabled flag */ + int auto_gain; /* Auto gain control enabled flag */ + int auto_exp; /* Auto exposure enabled flag */ + int backlight; /* Backlight exposure algorithm flag */ + int mirror; /* Image is reversed horizontally */ + + int led_policy; /* LED: off|on|auto; OV511+ only */ + + struct semaphore lock; /* Serializes user-accessible operations */ + int user; /* user count for exclusive use */ + + int streaming; /* Are we streaming Isochronous? */ + int grabbing; /* Are we grabbing? */ + + int compress; /* Should the next frame be compressed? */ + int compress_inited; /* Are compression params uploaded? */ + + int lightfreq; /* Power (lighting) frequency */ + int bandfilt; /* Banding filter enabled flag */ + + unsigned char *fbuf; /* Videodev buffer area */ + unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */ + unsigned char *rawfbuf; /* Raw camera data buffer area */ + + int sub_flag; /* Pix Array subcapture on flag */ + int subx; /* Pix Array subcapture x offset */ + int suby; /* Pix Array subcapture y offset */ + int subw; /* Pix Array subcapture width */ + int subh; /* Pix Array subcapture height */ + + int curframe; /* Current receiving sbuf */ + struct ov511_frame frame[OV511_NUMFRAMES]; + + struct ov511_sbuf sbuf[OV511_NUMSBUF]; + + wait_queue_head_t wq; /* Processes waiting */ + + int snap_enabled; /* Snapshot mode enabled */ + + int bridge; /* Type of bridge (BRG_*) */ + int bclass; /* Class of bridge (BCL_*) */ + int sensor; /* Type of image sensor chip (SEN_*) */ + + int packet_size; /* Frame size per isoc desc */ + int packet_numbering; /* Is ISO frame numbering enabled? */ + + struct semaphore param_lock; /* params lock for this camera */ + + /* Framebuffer/sbuf management */ + int buf_state; + struct semaphore buf_lock; + + struct ov51x_decomp_ops *decomp_ops; + + /* Stop streaming while changing picture settings */ + int stop_during_set; + + int stopped; /* Streaming is temporarily paused */ + + /* Video decoder stuff */ + int input; /* Composite, S-VIDEO, etc... */ + int num_inputs; /* Number of inputs */ + int norm; /* NTSC / PAL / SECAM */ + int has_decoder; /* Device has a video decoder */ + int pal; /* Device is designed for PAL resolution */ + + /* I2C interface */ + struct semaphore i2c_lock; /* Protect I2C controller regs */ + unsigned char primary_i2c_slave; /* I2C write id of sensor */ + + /* Control transaction stuff */ + unsigned char *cbuf; /* Buffer for payload */ + struct semaphore cbuf_lock; +}; + +/* Used to represent a list of values and their respective symbolic names */ +struct symbolic_list { + int num; + char *name; +}; + +#define NOT_DEFINED_STR "Unknown" + +/* Returns the name of the matching element in the symbolic_list array. The + * end of the list must be marked with an element that has a NULL name. + */ +static inline char * +symbolic(struct symbolic_list list[], int num) +{ + int i; + + for (i = 0; list[i].name != NULL; i++) + if (list[i].num == num) + return (list[i].name); + + return (NOT_DEFINED_STR); +} + +/* Compression stuff */ + +#define OV511_QUANTABLESIZE 64 +#define OV518_QUANTABLESIZE 32 + +#define OV511_YQUANTABLE { \ + 0, 1, 1, 2, 2, 3, 3, 4, \ + 1, 1, 1, 2, 2, 3, 4, 4, \ + 1, 1, 2, 2, 3, 4, 4, 4, \ + 2, 2, 2, 3, 4, 4, 4, 4, \ + 2, 2, 3, 4, 4, 5, 5, 5, \ + 3, 3, 4, 4, 5, 5, 5, 5, \ + 3, 4, 4, 4, 5, 5, 5, 5, \ + 4, 4, 4, 4, 5, 5, 5, 5 \ +} + +#define OV511_UVQUANTABLE { \ + 0, 2, 2, 3, 4, 4, 4, 4, \ + 2, 2, 2, 4, 4, 4, 4, 4, \ + 2, 2, 3, 4, 4, 4, 4, 4, \ + 3, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4 \ +} + +#define OV518_YQUANTABLE { \ + 5, 4, 5, 6, 6, 7, 7, 7, \ + 5, 5, 5, 5, 6, 7, 7, 7, \ + 6, 6, 6, 6, 7, 7, 7, 8, \ + 7, 7, 6, 7, 7, 7, 8, 8 \ +} + +#define OV518_UVQUANTABLE { \ + 6, 6, 6, 7, 7, 7, 7, 7, \ + 6, 6, 6, 7, 7, 7, 7, 7, \ + 6, 6, 6, 7, 7, 7, 7, 8, \ + 7, 7, 7, 7, 7, 7, 8, 8 \ +} + +#endif --- linux-2.6.27.orig/ubuntu/misc/media/ov511/ov511.c +++ linux-2.6.27/ubuntu/misc/media/ov511/ov511.c @@ -0,0 +1,6123 @@ +/* + * OmniVision OV511 Camera-to-USB Bridge Driver + * + * Copyright (c) 1999-2003 Mark W. McClelland + * Original decompression code Copyright 1998-2000 OmniVision Technologies + * Many improvements by Bret Wallach + * Color fixes by by Orion Sky Lawlor (2/26/2000) + * Snapshot code by Kevin Moore + * OV7620 fixes by Charl P. Botha + * Changes by Claudio Matsuoka + * Original SAA7111A code by Dave Perks + * URB error messages from pwc driver by Nemosoft + * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox + * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others + * + * Based on the Linux CPiA driver written by Peter Pregler, + * Scott J. Bertin and Johannes Erdfelt. + * + * Please see the file: Documentation/usb/ov511.txt + * and the website at: http://alpha.dyndns.org/ov511 + * for more info. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (__i386__) + #include +#endif + +#include "ov511.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.64 for Linux 2.5" +#define EMAIL "mark@alpha.dyndns.org" +#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \ + & Orion Sky Lawlor & Kevin Moore & Charl P. Botha \ + & Claudio Matsuoka " +#define DRIVER_DESC "ov511 USB Camera Driver" + +#define OV511_I2C_RETRIES 3 +#define ENABLE_Y_QUANTABLE 1 +#define ENABLE_UV_QUANTABLE 1 + +#define OV511_MAX_UNIT_VIDEO 16 + +/* Pixel count * bytes per YUV420 pixel (1.5) */ +#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3 / 2) + +#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval)) + +/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */ +#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024) + +#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM) + +/********************************************************************** + * Module Parameters + * (See ov511.txt for detailed descriptions of these) + **********************************************************************/ + +/* These variables (and all static globals) default to zero */ +static int autobright = 1; +static int autogain = 1; +static int autoexp = 1; +static int debug; +static int snapshot; +static int cams = 1; +static int compress; +static int testpat; +static int dumppix; +static int led = 1; +static int dump_bridge; +static int dump_sensor; +static int printph; +static int phy = 0x1f; +static int phuv = 0x05; +static int pvy = 0x06; +static int pvuv = 0x06; +static int qhy = 0x14; +static int qhuv = 0x03; +static int qvy = 0x04; +static int qvuv = 0x04; +static int lightfreq; +static int bandingfilter; +static int clockdiv = -1; +static int packetsize = -1; +static int framedrop = -1; +static int fastset; +static int force_palette; +static int backlight; +static int unit_video[OV511_MAX_UNIT_VIDEO]; +static int remove_zeros; +static int mirror; +static int ov518_color; + +module_param(autobright, int, 0); +MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness"); +module_param(autogain, int, 0); +MODULE_PARM_DESC(autogain, "Sensor automatically changes gain"); +module_param(autoexp, int, 0); +MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure"); +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, + "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max"); +module_param(snapshot, int, 0); +MODULE_PARM_DESC(snapshot, "Enable snapshot mode"); +module_param(cams, int, 0); +MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); +module_param(compress, int, 0); +MODULE_PARM_DESC(compress, "Turn on compression"); +module_param(testpat, int, 0); +MODULE_PARM_DESC(testpat, + "Replace image with vertical bar testpattern (only partially working)"); +module_param(dumppix, int, 0); +MODULE_PARM_DESC(dumppix, "Dump raw pixel data"); +module_param(led, int, 0); +MODULE_PARM_DESC(led, + "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)"); +module_param(dump_bridge, int, 0); +MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers"); +module_param(dump_sensor, int, 0); +MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers"); +module_param(printph, int, 0); +MODULE_PARM_DESC(printph, "Print frame start/end headers"); +module_param(phy, int, 0); +MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)"); +module_param(phuv, int, 0); +MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)"); +module_param(pvy, int, 0); +MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)"); +module_param(pvuv, int, 0); +MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)"); +module_param(qhy, int, 0); +MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)"); +module_param(qhuv, int, 0); +MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)"); +module_param(qvy, int, 0); +MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)"); +module_param(qvuv, int, 0); +MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)"); +module_param(lightfreq, int, 0); +MODULE_PARM_DESC(lightfreq, + "Light frequency. Set to 50 or 60 Hz, or zero for default settings"); +module_param(bandingfilter, int, 0); +MODULE_PARM_DESC(bandingfilter, + "Enable banding filter (to reduce effects of fluorescent lighting)"); +module_param(clockdiv, int, 0); +MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value"); +module_param(packetsize, int, 0); +MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size"); +module_param(framedrop, int, 0); +MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting"); +module_param(fastset, int, 0); +MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately"); +module_param(force_palette, int, 0); +MODULE_PARM_DESC(force_palette, "Force the palette to a specific value"); +module_param(backlight, int, 0); +MODULE_PARM_DESC(backlight, "For objects that are lit from behind"); +static int num_uv; +module_param_array(unit_video, int, &num_uv, 0); +MODULE_PARM_DESC(unit_video, + "Force use of specific minor number(s). 0 is not allowed."); +module_param(remove_zeros, int, 0); +MODULE_PARM_DESC(remove_zeros, + "Remove zero-padding from uncompressed incoming data"); +module_param(mirror, int, 0); +MODULE_PARM_DESC(mirror, "Reverse image horizontally"); +module_param(ov518_color, int, 0); +MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)"); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/********************************************************************** + * Miscellaneous Globals + **********************************************************************/ + +static struct usb_driver ov511_driver; + +static struct ov51x_decomp_ops *ov511_decomp_ops; +static struct ov51x_decomp_ops *ov511_mmx_decomp_ops; +static struct ov51x_decomp_ops *ov518_decomp_ops; +static struct ov51x_decomp_ops *ov518_mmx_decomp_ops; + +/* Number of times to retry a failed I2C transaction. Increase this if you + * are getting "Failed to read sensor ID..." */ +static int i2c_detect_tries = 5; + +/* MMX support is present in kernel and CPU. Checked upon decomp module load. */ +#if defined(__i386__) || defined(__x86_64__) +#define ov51x_mmx_available (cpu_has_mmx) +#else +#define ov51x_mmx_available (0) +#endif + +static struct usb_device_id device_table [] = { + { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, + { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, + { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) }, + { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) }, + { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, device_table); + +static unsigned char yQuanTable511[] = OV511_YQUANTABLE; +static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE; +static unsigned char yQuanTable518[] = OV518_YQUANTABLE; +static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE; + +/********************************************************************** + * Symbolic Names + **********************************************************************/ + +/* Known OV511-based cameras */ +static struct symbolic_list camlist[] = { + { 0, "Generic Camera (no ID)" }, + { 1, "Mustek WCam 3X" }, + { 3, "D-Link DSB-C300" }, + { 4, "Generic OV511/OV7610" }, + { 5, "Puretek PT-6007" }, + { 6, "Lifeview USB Life TV (NTSC)" }, + { 21, "Creative Labs WebCam 3" }, + { 22, "Lifeview USB Life TV (PAL D/K+B/G)" }, + { 36, "Koala-Cam" }, + { 38, "Lifeview USB Life TV (PAL)" }, + { 41, "Samsung Anycam MPC-M10" }, + { 43, "Mtekvision Zeca MV402" }, + { 46, "Suma eON" }, + { 70, "Lifeview USB Life TV (PAL/SECAM)" }, + { 100, "Lifeview RoboCam" }, + { 102, "AverMedia InterCam Elite" }, + { 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */ + { 134, "Ezonics EZCam II" }, + { 192, "Webeye 2000B" }, + { 253, "Alpha Vision Tech. AlphaCam SE" }, + { -1, NULL } +}; + +/* Video4Linux1 Palettes */ +static struct symbolic_list v4l1_plist[] = { + { VIDEO_PALETTE_GREY, "GREY" }, + { VIDEO_PALETTE_HI240, "HI240" }, + { VIDEO_PALETTE_RGB565, "RGB565" }, + { VIDEO_PALETTE_RGB24, "RGB24" }, + { VIDEO_PALETTE_RGB32, "RGB32" }, + { VIDEO_PALETTE_RGB555, "RGB555" }, + { VIDEO_PALETTE_YUV422, "YUV422" }, + { VIDEO_PALETTE_YUYV, "YUYV" }, + { VIDEO_PALETTE_UYVY, "UYVY" }, + { VIDEO_PALETTE_YUV420, "YUV420" }, + { VIDEO_PALETTE_YUV411, "YUV411" }, + { VIDEO_PALETTE_RAW, "RAW" }, + { VIDEO_PALETTE_YUV422P,"YUV422P" }, + { VIDEO_PALETTE_YUV411P,"YUV411P" }, + { VIDEO_PALETTE_YUV420P,"YUV420P" }, + { VIDEO_PALETTE_YUV410P,"YUV410P" }, + { -1, NULL } +}; + +static struct symbolic_list brglist[] = { + { BRG_OV511, "OV511" }, + { BRG_OV511PLUS, "OV511+" }, + { BRG_OV518, "OV518" }, + { BRG_OV518PLUS, "OV518+" }, + { -1, NULL } +}; + +static struct symbolic_list senlist[] = { + { SEN_OV76BE, "OV76BE" }, + { SEN_OV7610, "OV7610" }, + { SEN_OV7620, "OV7620" }, + { SEN_OV7620AE, "OV7620AE" }, + { SEN_OV6620, "OV6620" }, + { SEN_OV6630, "OV6630" }, + { SEN_OV6630AE, "OV6630AE" }, + { SEN_OV6630AF, "OV6630AF" }, + { SEN_OV8600, "OV8600" }, + { SEN_KS0127, "KS0127" }, + { SEN_KS0127B, "KS0127B" }, + { SEN_SAA7111A, "SAA7111A" }, + { -1, NULL } +}; + +/* URB error codes: */ +static struct symbolic_list urb_errlist[] = { + { -ENOSR, "Buffer error (overrun)" }, + { -EPIPE, "Stalled (device not responding)" }, + { -EOVERFLOW, "Babble (bad cable?)" }, + { -EPROTO, "Bit-stuff error (bad cable?)" }, + { -EILSEQ, "CRC/Timeout" }, + { -ETIMEDOUT, "NAK (device does not respond)" }, + { -1, NULL } +}; + +/********************************************************************** + * Memory management + **********************************************************************/ +static void * +rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void +rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + +/********************************************************************** + * + * Register I/O + * + **********************************************************************/ + +/* Write an OV51x register */ +static int +reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) +{ + int rc; + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + down(&ov->cbuf_lock); + ov->cbuf[0] = value; + rc = usb_control_msg(ov->dev, + usb_sndctrlpipe(ov->dev, 0), + (ov->bclass == BCL_OV518)?1:2 /* REG_IO */, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, (__u16)reg, &ov->cbuf[0], 1, 1000); + up(&ov->cbuf_lock); + + if (rc < 0) + err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc)); + + return rc; +} + +/* Read from an OV51x register */ +/* returns: negative is error, pos or zero is data */ +static int +reg_r(struct usb_ov511 *ov, unsigned char reg) +{ + int rc; + + down(&ov->cbuf_lock); + rc = usb_control_msg(ov->dev, + usb_rcvctrlpipe(ov->dev, 0), + (ov->bclass == BCL_OV518)?1:3 /* REG_IO */, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, (__u16)reg, &ov->cbuf[0], 1, 1000); + + if (rc < 0) { + err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc)); + } else { + rc = ov->cbuf[0]; + PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]); + } + + up(&ov->cbuf_lock); + + return rc; +} + +/* + * Writes bits at positions specified by mask to an OV51x reg. Bits that are in + * the same position as 1's in "mask" are cleared and set to "value". Bits + * that are in the same position as 0's in "mask" are preserved, regardless + * of their respective state in "value". + */ +static int +reg_w_mask(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int ret; + unsigned char oldval, newval; + + ret = reg_r(ov, reg); + if (ret < 0) + return ret; + + oldval = (unsigned char) ret; + oldval &= (~mask); /* Clear the masked bits */ + value &= mask; /* Enforce mask on value */ + newval = oldval | value; /* Set the desired bits */ + + return (reg_w(ov, reg, newval)); +} + +/* + * Writes multiple (n) byte value to a single register. Only valid with certain + * registers (0x30 and 0xc4 - 0xce). + */ +static int +ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n) +{ + int rc; + + PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n); + + down(&ov->cbuf_lock); + + *((__le32 *)ov->cbuf) = __cpu_to_le32(val); + + rc = usb_control_msg(ov->dev, + usb_sndctrlpipe(ov->dev, 0), + 1 /* REG_IO */, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, (__u16)reg, ov->cbuf, n, 1000); + up(&ov->cbuf_lock); + + if (rc < 0) + err("reg write multiple: error %d: %s", rc, + symbolic(urb_errlist, rc)); + + return rc; +} + +static int +ov511_upload_quan_tables(struct usb_ov511 *ov) +{ + unsigned char *pYTable = yQuanTable511; + unsigned char *pUVTable = uvQuanTable511; + unsigned char val0, val1; + int i, rc, reg = R511_COMP_LUT_BEGIN; + + PDEBUG(4, "Uploading quantization tables"); + + for (i = 0; i < OV511_QUANTABLESIZE / 2; i++) { + if (ENABLE_Y_QUANTABLE) { + val0 = *pYTable++; + val1 = *pYTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg, val0); + if (rc < 0) + return rc; + } + + if (ENABLE_UV_QUANTABLE) { + val0 = *pUVTable++; + val1 = *pUVTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0); + if (rc < 0) + return rc; + } + + reg++; + } + + return 0; +} + +/* OV518 quantization tables are 8x4 (instead of 8x8) */ +static int +ov518_upload_quan_tables(struct usb_ov511 *ov) +{ + unsigned char *pYTable = yQuanTable518; + unsigned char *pUVTable = uvQuanTable518; + unsigned char val0, val1; + int i, rc, reg = R511_COMP_LUT_BEGIN; + + PDEBUG(4, "Uploading quantization tables"); + + for (i = 0; i < OV518_QUANTABLESIZE / 2; i++) { + if (ENABLE_Y_QUANTABLE) { + val0 = *pYTable++; + val1 = *pYTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg, val0); + if (rc < 0) + return rc; + } + + if (ENABLE_UV_QUANTABLE) { + val0 = *pUVTable++; + val1 = *pUVTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0); + if (rc < 0) + return rc; + } + + reg++; + } + + return 0; +} + +static int +ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type) +{ + int rc; + + /* Setting bit 0 not allowed on 518/518Plus */ + if (ov->bclass == BCL_OV518) + reset_type &= 0xfe; + + PDEBUG(4, "Reset: type=0x%02X", reset_type); + + rc = reg_w(ov, R51x_SYS_RESET, reset_type); + rc = reg_w(ov, R51x_SYS_RESET, 0); + + if (rc < 0) + err("reset: command failed"); + + return rc; +} + +/********************************************************************** + * + * Low-level I2C I/O functions + * + **********************************************************************/ + +/* NOTE: Do not call this function directly! + * The OV518 I2C I/O procedure is different, hence, this function. + * This is normally only called from i2c_w(). Note that this function + * always succeeds regardless of whether the sensor is present and working. + */ +static int +ov518_i2c_write_internal(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value) +{ + int rc; + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_3, reg); + if (rc < 0) + return rc; + + /* Write "value" to I2C data port of OV511 */ + rc = reg_w(ov, R51x_I2C_DATA, value); + if (rc < 0) + return rc; + + /* Initiate 3-byte write cycle */ + rc = reg_w(ov, R518_I2C_CTL, 0x01); + if (rc < 0) + return rc; + + return 0; +} + +/* NOTE: Do not call this function directly! */ +static int +ov511_i2c_write_internal(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value) +{ + int rc, retries; + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + /* Three byte write cycle */ + for (retries = OV511_I2C_RETRIES; ; ) { + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_3, reg); + if (rc < 0) + break; + + /* Write "value" to I2C data port of OV511 */ + rc = reg_w(ov, R51x_I2C_DATA, value); + if (rc < 0) + break; + + /* Initiate 3-byte write cycle */ + rc = reg_w(ov, R511_I2C_CTL, 0x01); + if (rc < 0) + break; + + /* Retry until idle */ + do + rc = reg_r(ov, R511_I2C_CTL); + while (rc > 0 && ((rc&1) == 0)); + if (rc < 0) + break; + + /* Ack? */ + if ((rc&2) == 0) { + rc = 0; + break; + } +#if 0 + /* I2C abort */ + reg_w(ov, R511_I2C_CTL, 0x10); +#endif + if (--retries < 0) { + err("i2c write retries exhausted"); + rc = -1; + break; + } + } + + return rc; +} + +/* NOTE: Do not call this function directly! + * The OV518 I2C I/O procedure is different, hence, this function. + * This is normally only called from i2c_r(). Note that this function + * always succeeds regardless of whether the sensor is present and working. + */ +static int +ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) +{ + int rc, value; + + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_2, reg); + if (rc < 0) + return rc; + + /* Initiate 2-byte write cycle */ + rc = reg_w(ov, R518_I2C_CTL, 0x03); + if (rc < 0) + return rc; + + /* Initiate 2-byte read cycle */ + rc = reg_w(ov, R518_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + value = reg_r(ov, R51x_I2C_DATA); + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + return value; +} + +/* NOTE: Do not call this function directly! + * returns: negative is error, pos or zero is data */ +static int +ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) +{ + int rc, value, retries; + + /* Two byte write cycle */ + for (retries = OV511_I2C_RETRIES; ; ) { + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_2, reg); + if (rc < 0) + return rc; + + /* Initiate 2-byte write cycle */ + rc = reg_w(ov, R511_I2C_CTL, 0x03); + if (rc < 0) + return rc; + + /* Retry until idle */ + do + rc = reg_r(ov, R511_I2C_CTL); + while (rc > 0 && ((rc&1) == 0)); + if (rc < 0) + return rc; + + if ((rc&2) == 0) /* Ack? */ + break; + + /* I2C abort */ + reg_w(ov, R511_I2C_CTL, 0x10); + + if (--retries < 0) { + err("i2c write retries exhausted"); + return -1; + } + } + + /* Two byte read cycle */ + for (retries = OV511_I2C_RETRIES; ; ) { + /* Initiate 2-byte read cycle */ + rc = reg_w(ov, R511_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + /* Retry until idle */ + do + rc = reg_r(ov, R511_I2C_CTL); + while (rc > 0 && ((rc&1) == 0)); + if (rc < 0) + return rc; + + if ((rc&2) == 0) /* Ack? */ + break; + + /* I2C abort */ + rc = reg_w(ov, R511_I2C_CTL, 0x10); + if (rc < 0) + return rc; + + if (--retries < 0) { + err("i2c read retries exhausted"); + return -1; + } + } + + value = reg_r(ov, R51x_I2C_DATA); + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + /* This is needed to make i2c_w() work */ + rc = reg_w(ov, R511_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + return value; +} + +/* returns: negative is error, pos or zero is data */ +static int +i2c_r(struct usb_ov511 *ov, unsigned char reg) +{ + int rc; + + down(&ov->i2c_lock); + + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_read_internal(ov, reg); + else + rc = ov511_i2c_read_internal(ov, reg); + + up(&ov->i2c_lock); + + return rc; +} + +static int +i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) +{ + int rc; + + down(&ov->i2c_lock); + + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_write_internal(ov, reg, value); + else + rc = ov511_i2c_write_internal(ov, reg, value); + + up(&ov->i2c_lock); + + return rc; +} + +/* Do not call this function directly! */ +static int +ov51x_i2c_write_mask_internal(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int rc; + unsigned char oldval, newval; + + if (mask == 0xff) { + newval = value; + } else { + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_read_internal(ov, reg); + else + rc = ov511_i2c_read_internal(ov, reg); + if (rc < 0) + return rc; + + oldval = (unsigned char) rc; + oldval &= (~mask); /* Clear the masked bits */ + value &= mask; /* Enforce mask on value */ + newval = oldval | value; /* Set the desired bits */ + } + + if (ov->bclass == BCL_OV518) + return (ov518_i2c_write_internal(ov, reg, newval)); + else + return (ov511_i2c_write_internal(ov, reg, newval)); +} + +/* Writes bits at positions specified by mask to an I2C reg. Bits that are in + * the same position as 1's in "mask" are cleared and set to "value". Bits + * that are in the same position as 0's in "mask" are preserved, regardless + * of their respective state in "value". + */ +static int +i2c_w_mask(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int rc; + + down(&ov->i2c_lock); + rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); + up(&ov->i2c_lock); + + return rc; +} + +/* Set the read and write slave IDs. The "slave" argument is the write slave, + * and the read slave will be set to (slave + 1). ov->i2c_lock should be held + * when calling this. This should not be called from outside the i2c I/O + * functions. + */ +static int +i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave) +{ + int rc; + + rc = reg_w(ov, R51x_I2C_W_SID, slave); + if (rc < 0) + return rc; + + rc = reg_w(ov, R51x_I2C_R_SID, slave + 1); + if (rc < 0) + return rc; + + return 0; +} + +/* Write to a specific I2C slave ID and register, using the specified mask */ +static int +i2c_w_slave(struct usb_ov511 *ov, + unsigned char slave, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int rc = 0; + + down(&ov->i2c_lock); + + /* Set new slave IDs */ + rc = i2c_set_slave_internal(ov, slave); + if (rc < 0) + goto out; + + rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); + +out: + /* Restore primary IDs */ + if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) + err("Couldn't restore primary I2C slave"); + + up(&ov->i2c_lock); + return rc; +} + +/* Read from a specific I2C slave ID and register */ +static int +i2c_r_slave(struct usb_ov511 *ov, + unsigned char slave, + unsigned char reg) +{ + int rc; + + down(&ov->i2c_lock); + + /* Set new slave IDs */ + rc = i2c_set_slave_internal(ov, slave); + if (rc < 0) + goto out; + + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_read_internal(ov, reg); + else + rc = ov511_i2c_read_internal(ov, reg); + +out: + /* Restore primary IDs */ + if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) + err("Couldn't restore primary I2C slave"); + + up(&ov->i2c_lock); + return rc; +} + +/* Sets I2C read and write slave IDs. Returns <0 for error */ +static int +ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid) +{ + int rc; + + down(&ov->i2c_lock); + + rc = i2c_set_slave_internal(ov, sid); + if (rc < 0) + goto out; + + // FIXME: Is this actually necessary? + rc = ov51x_reset(ov, OV511_RESET_NOREGS); +out: + up(&ov->i2c_lock); + return rc; +} + +static int +write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals) +{ + int rc; + + while (pRegvals->bus != OV511_DONE_BUS) { + if (pRegvals->bus == OV511_REG_BUS) { + if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0) + return rc; + } else if (pRegvals->bus == OV511_I2C_BUS) { + if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0) + return rc; + } else { + err("Bad regval array"); + return -1; + } + pRegvals++; + } + return 0; +} + +#ifdef OV511_DEBUG +static void +dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) +{ + int i, rc; + + for (i = reg1; i <= regn; i++) { + rc = i2c_r(ov, i); + info("Sensor[0x%02X] = 0x%02X", i, rc); + } +} + +static void +dump_i2c_regs(struct usb_ov511 *ov) +{ + info("I2C REGS"); + dump_i2c_range(ov, 0x00, 0x7C); +} + +static void +dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) +{ + int i, rc; + + for (i = reg1; i <= regn; i++) { + rc = reg_r(ov, i); + info("OV511[0x%02X] = 0x%02X", i, rc); + } +} + +static void +ov511_dump_regs(struct usb_ov511 *ov) +{ + info("CAMERA INTERFACE REGS"); + dump_reg_range(ov, 0x10, 0x1f); + info("DRAM INTERFACE REGS"); + dump_reg_range(ov, 0x20, 0x23); + info("ISO FIFO REGS"); + dump_reg_range(ov, 0x30, 0x31); + info("PIO REGS"); + dump_reg_range(ov, 0x38, 0x39); + dump_reg_range(ov, 0x3e, 0x3e); + info("I2C REGS"); + dump_reg_range(ov, 0x40, 0x49); + info("SYSTEM CONTROL REGS"); + dump_reg_range(ov, 0x50, 0x55); + dump_reg_range(ov, 0x5e, 0x5f); + info("OmniCE REGS"); + dump_reg_range(ov, 0x70, 0x79); + /* NOTE: Quantization tables are not readable. You will get the value + * in reg. 0x79 for every table register */ + dump_reg_range(ov, 0x80, 0x9f); + dump_reg_range(ov, 0xa0, 0xbf); + +} + +static void +ov518_dump_regs(struct usb_ov511 *ov) +{ + info("VIDEO MODE REGS"); + dump_reg_range(ov, 0x20, 0x2f); + info("DATA PUMP AND SNAPSHOT REGS"); + dump_reg_range(ov, 0x30, 0x3f); + info("I2C REGS"); + dump_reg_range(ov, 0x40, 0x4f); + info("SYSTEM CONTROL AND VENDOR REGS"); + dump_reg_range(ov, 0x50, 0x5f); + info("60 - 6F"); + dump_reg_range(ov, 0x60, 0x6f); + info("70 - 7F"); + dump_reg_range(ov, 0x70, 0x7f); + info("Y QUANTIZATION TABLE"); + dump_reg_range(ov, 0x80, 0x8f); + info("UV QUANTIZATION TABLE"); + dump_reg_range(ov, 0x90, 0x9f); + info("A0 - BF"); + dump_reg_range(ov, 0xa0, 0xbf); + info("CBR"); + dump_reg_range(ov, 0xc0, 0xcf); +} +#endif + +/*****************************************************************************/ + +/* Temporarily stops OV511 from functioning. Must do this before changing + * registers while the camera is streaming */ +static inline int +ov51x_stop(struct usb_ov511 *ov) +{ + PDEBUG(4, "stopping"); + ov->stopped = 1; + if (ov->bclass == BCL_OV518) + return (reg_w_mask(ov, R51x_SYS_RESET, 0x3a, 0x3a)); + else + return (reg_w(ov, R51x_SYS_RESET, 0x3d)); +} + +/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not + * actually stopped (for performance). */ +static inline int +ov51x_restart(struct usb_ov511 *ov) +{ + if (ov->stopped) { + PDEBUG(4, "restarting"); + ov->stopped = 0; + + /* Reinitialize the stream */ + if (ov->bclass == BCL_OV518) + reg_w(ov, 0x2f, 0x80); + + return (reg_w(ov, R51x_SYS_RESET, 0x00)); + } + + return 0; +} + +/* Sleeps until no frames are active. Returns !0 if got signal */ +static int +ov51x_wait_frames_inactive(struct usb_ov511 *ov) +{ + return wait_event_interruptible(ov->wq, ov->curframe < 0); +} + +/* Resets the hardware snapshot button */ +static void +ov51x_clear_snapshot(struct usb_ov511 *ov) +{ + if (ov->bclass == BCL_OV511) { + reg_w(ov, R51x_SYS_SNAP, 0x00); + reg_w(ov, R51x_SYS_SNAP, 0x02); + reg_w(ov, R51x_SYS_SNAP, 0x00); + } else if (ov->bclass == BCL_OV518) { + warn("snapshot reset not supported yet on OV518(+)"); + } else { + err("clear snap: invalid bridge type"); + } +} + +#if 0 +/* Checks the status of the snapshot button. Returns 1 if it was pressed since + * it was last cleared, and zero in all other cases (including errors) */ +static int +ov51x_check_snapshot(struct usb_ov511 *ov) +{ + int ret, status = 0; + + if (ov->bclass == BCL_OV511) { + ret = reg_r(ov, R51x_SYS_SNAP); + if (ret < 0) { + err("Error checking snspshot status (%d)", ret); + } else if (ret & 0x08) { + status = 1; + } + } else if (ov->bclass == BCL_OV518) { + warn("snapshot check not supported yet on OV518(+)"); + } else { + err("check snap: invalid bridge type"); + } + + return status; +} +#endif + +/* This does an initial reset of an OmniVision sensor and ensures that I2C + * is synchronized. Returns <0 for failure. + */ +static int +init_ov_sensor(struct usb_ov511 *ov) +{ + int i, success; + + /* Reset the sensor */ + if (i2c_w(ov, 0x12, 0x80) < 0) + return -EIO; + + /* Wait for it to initialize */ + msleep(150); + + for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) { + if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && + (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { + success = 1; + continue; + } + + /* Reset the sensor */ + if (i2c_w(ov, 0x12, 0x80) < 0) + return -EIO; + /* Wait for it to initialize */ + msleep(150); + /* Dummy read to sync I2C */ + if (i2c_r(ov, 0x00) < 0) + return -EIO; + } + + if (!success) + return -EIO; + + PDEBUG(1, "I2C synced in %d attempt(s)", i); + + return 0; +} + +static int +ov511_set_packet_size(struct usb_ov511 *ov, int size) +{ + int alt, mult; + + if (ov51x_stop(ov) < 0) + return -EIO; + + mult = size >> 5; + + if (ov->bridge == BRG_OV511) { + if (size == 0) + alt = OV511_ALT_SIZE_0; + else if (size == 257) + alt = OV511_ALT_SIZE_257; + else if (size == 513) + alt = OV511_ALT_SIZE_513; + else if (size == 769) + alt = OV511_ALT_SIZE_769; + else if (size == 993) + alt = OV511_ALT_SIZE_993; + else { + err("Set packet size: invalid size (%d)", size); + return -EINVAL; + } + } else if (ov->bridge == BRG_OV511PLUS) { + if (size == 0) + alt = OV511PLUS_ALT_SIZE_0; + else if (size == 33) + alt = OV511PLUS_ALT_SIZE_33; + else if (size == 129) + alt = OV511PLUS_ALT_SIZE_129; + else if (size == 257) + alt = OV511PLUS_ALT_SIZE_257; + else if (size == 385) + alt = OV511PLUS_ALT_SIZE_385; + else if (size == 513) + alt = OV511PLUS_ALT_SIZE_513; + else if (size == 769) + alt = OV511PLUS_ALT_SIZE_769; + else if (size == 961) + alt = OV511PLUS_ALT_SIZE_961; + else { + err("Set packet size: invalid size (%d)", size); + return -EINVAL; + } + } else { + err("Set packet size: Invalid bridge type"); + return -EINVAL; + } + + PDEBUG(3, "%d, mult=%d, alt=%d", size, mult, alt); + + if (reg_w(ov, R51x_FIFO_PSIZE, mult) < 0) + return -EIO; + + if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { + err("Set packet size: set interface error"); + return -EBUSY; + } + + if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) + return -EIO; + + ov->packet_size = size; + + if (ov51x_restart(ov) < 0) + return -EIO; + + return 0; +} + +/* Note: Unlike the OV511/OV511+, the size argument does NOT include the + * optional packet number byte. The actual size *is* stored in ov->packet_size, + * though. */ +static int +ov518_set_packet_size(struct usb_ov511 *ov, int size) +{ + int alt; + + if (ov51x_stop(ov) < 0) + return -EIO; + + if (ov->bclass == BCL_OV518) { + if (size == 0) + alt = OV518_ALT_SIZE_0; + else if (size == 128) + alt = OV518_ALT_SIZE_128; + else if (size == 256) + alt = OV518_ALT_SIZE_256; + else if (size == 384) + alt = OV518_ALT_SIZE_384; + else if (size == 512) + alt = OV518_ALT_SIZE_512; + else if (size == 640) + alt = OV518_ALT_SIZE_640; + else if (size == 768) + alt = OV518_ALT_SIZE_768; + else if (size == 896) + alt = OV518_ALT_SIZE_896; + else { + err("Set packet size: invalid size (%d)", size); + return -EINVAL; + } + } else { + err("Set packet size: Invalid bridge type"); + return -EINVAL; + } + + PDEBUG(3, "%d, alt=%d", size, alt); + + ov->packet_size = size; + if (size > 0) { + /* Program ISO FIFO size reg (packet number isn't included) */ + ov518_reg_w32(ov, 0x30, size, 2); + + if (ov->packet_numbering) + ++ov->packet_size; + } + + if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { + err("Set packet size: set interface error"); + return -EBUSY; + } + + /* Initialize the stream */ + if (reg_w(ov, 0x2f, 0x80) < 0) + return -EIO; + + if (ov51x_restart(ov) < 0) + return -EIO; + + if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) + return -EIO; + + return 0; +} + +/* Upload compression params and quantization tables. Returns 0 for success. */ +static int +ov511_init_compression(struct usb_ov511 *ov) +{ + int rc = 0; + + if (!ov->compress_inited) { + reg_w(ov, 0x70, phy); + reg_w(ov, 0x71, phuv); + reg_w(ov, 0x72, pvy); + reg_w(ov, 0x73, pvuv); + reg_w(ov, 0x74, qhy); + reg_w(ov, 0x75, qhuv); + reg_w(ov, 0x76, qvy); + reg_w(ov, 0x77, qvuv); + + if (ov511_upload_quan_tables(ov) < 0) { + err("Error uploading quantization tables"); + rc = -EIO; + goto out; + } + } + + ov->compress_inited = 1; +out: + return rc; +} + +/* Upload compression params and quantization tables. Returns 0 for success. */ +static int +ov518_init_compression(struct usb_ov511 *ov) +{ + int rc = 0; + + if (!ov->compress_inited) { + if (ov518_upload_quan_tables(ov) < 0) { + err("Error uploading quantization tables"); + rc = -EIO; + goto out; + } + } + + ov->compress_inited = 1; +out: + return rc; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's contrast setting to "val" */ +static int +sensor_set_contrast(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + { + rc = i2c_w(ov, OV7610_REG_CNT, val >> 8); + if (rc < 0) + goto out; + break; + } + case SEN_OV6630: + { + rc = i2c_w_mask(ov, OV7610_REG_CNT, val >> 12, 0x0f); + if (rc < 0) + goto out; + break; + } + case SEN_OV7620: + { + unsigned char ctab[] = { + 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, + 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff + }; + + /* Use Y gamma control instead. Bit 0 enables it. */ + rc = i2c_w(ov, 0x64, ctab[val>>12]); + if (rc < 0) + goto out; + break; + } + case SEN_SAA7111A: + { + rc = i2c_w(ov, 0x0b, val >> 9); + if (rc < 0) + goto out; + break; + } + default: + { + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + } + + rc = 0; /* Success */ + ov->contrast = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's contrast setting */ +static int +sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + rc = i2c_r(ov, OV7610_REG_CNT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_CNT); + if (rc < 0) + return rc; + else + *val = rc << 12; + break; + case SEN_OV7620: + /* Use Y gamma reg instead. Bit 0 is the enable bit. */ + rc = i2c_r(ov, 0x64); + if (rc < 0) + return rc; + else + *val = (rc & 0xfe) << 8; + break; + case SEN_SAA7111A: + *val = ov->contrast; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->contrast = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's brightness setting to "val" */ +static int +sensor_set_brightness(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(4, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_OV7620: + /* 7620 doesn't like manual changes when in auto mode */ + if (!ov->auto_brt) { + rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); + if (rc < 0) + goto out; + } + break; + case SEN_SAA7111A: + rc = i2c_w(ov, 0x0a, val >> 8); + if (rc < 0) + goto out; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + + rc = 0; /* Success */ + ov->brightness = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's brightness setting */ +static int +sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV7620: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_BRT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_SAA7111A: + *val = ov->brightness; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->brightness = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's saturation (color intensity) setting to "val" */ +static int +sensor_set_saturation(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_OV7620: +// /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ +// rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e); +// if (rc < 0) +// goto out; + rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_SAA7111A: + rc = i2c_w(ov, 0x0c, val >> 9); + if (rc < 0) + goto out; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + + rc = 0; /* Success */ + ov->colour = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's saturation (color intensity) setting */ +static int +sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_SAT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_OV7620: +// /* Use UV gamma reg instead. Bits 0 & 7 are reserved. */ +// rc = i2c_r(ov, 0x62); +// if (rc < 0) +// return rc; +// else +// *val = (rc & 0x7e) << 9; + rc = i2c_r(ov, OV7610_REG_SAT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_SAA7111A: + *val = ov->colour; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->colour = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's hue (red/blue balance) setting to "val" */ +static int +sensor_set_hue(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8)); + if (rc < 0) + goto out; + + rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_OV7620: +// Hue control is causing problems. I will enable it once it's fixed. +#if 0 + rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb); + if (rc < 0) + goto out; + + rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb); + if (rc < 0) + goto out; +#endif + break; + case SEN_SAA7111A: + rc = i2c_w(ov, 0x0d, (val + 32768) >> 8); + if (rc < 0) + goto out; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + + rc = 0; /* Success */ + ov->hue = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's hue (red/blue balance) setting */ +static int +sensor_get_hue(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_BLUE); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_OV7620: + rc = i2c_r(ov, 0x7a); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_SAA7111A: + *val = ov->hue; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->hue = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +static int +sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p) +{ + int rc; + + PDEBUG(4, "sensor_set_picture"); + + ov->whiteness = p->whiteness; + + /* Don't return error if a setting is unsupported, or rest of settings + * will not be performed */ + + rc = sensor_set_contrast(ov, p->contrast); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_brightness(ov, p->brightness); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_saturation(ov, p->colour); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_hue(ov, p->hue); + if (FATAL_ERROR(rc)) + return rc; + + return 0; +} + +static int +sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p) +{ + int rc; + + PDEBUG(4, "sensor_get_picture"); + + /* Don't return error if a setting is unsupported, or rest of settings + * will not be performed */ + + rc = sensor_get_contrast(ov, &(p->contrast)); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_get_brightness(ov, &(p->brightness)); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_get_saturation(ov, &(p->colour)); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_get_hue(ov, &(p->hue)); + if (FATAL_ERROR(rc)) + return rc; + + p->whiteness = 105 << 8; + + return 0; +} + +#if 0 +// FIXME: Exposure range is only 0x00-0x7f in interlace mode +/* Sets current exposure for sensor. This only has an effect if auto-exposure + * is off */ +static inline int +sensor_set_exposure(struct usb_ov511 *ov, unsigned char val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV6620: + case SEN_OV6630: + case SEN_OV7610: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + rc = i2c_w(ov, 0x10, val); + if (rc < 0) + goto out; + + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_exposure"); + return -EINVAL; + } + + rc = 0; /* Success */ + ov->exposure = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} +#endif + +/* Gets current exposure level from sensor, regardless of whether it is under + * manual control. */ +static int +sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + case SEN_OV6630: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + rc = i2c_r(ov, 0x10); + if (rc < 0) + return rc; + else + *val = rc; + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + val = NULL; + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for get_exposure"); + return -EINVAL; + } + + PDEBUG(3, "%d", *val); + ov->exposure = *val; + + return 0; +} + +/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */ +static void +ov51x_led_control(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + if (ov->bridge == BRG_OV511PLUS) + reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0); + else if (ov->bclass == BCL_OV518) + reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02); + + return; +} + +/* Matches the sensor's internal frame rate to the lighting frequency. + * Valid frequencies are: + * 50 - 50Hz, for European and Asian lighting + * 60 - 60Hz, for American lighting + * + * Tested with: OV7610, OV7620, OV76BE, OV6620 + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_light_freq(struct usb_ov511 *ov, int freq) +{ + int sixty; + + PDEBUG(4, "%d Hz", freq); + + if (freq == 60) + sixty = 1; + else if (freq == 50) + sixty = 0; + else { + err("Invalid light freq (%d Hz)", freq); + return -EINVAL; + } + + switch (ov->sensor) { + case SEN_OV7610: + i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); + i2c_w(ov, 0x2b, sixty?0x00:0xac); + i2c_w_mask(ov, 0x13, 0x10, 0x10); + i2c_w_mask(ov, 0x13, 0x00, 0x10); + break; + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); + i2c_w(ov, 0x2b, sixty?0x00:0xac); + i2c_w_mask(ov, 0x76, 0x01, 0x01); + break; + case SEN_OV6620: + case SEN_OV6630: + i2c_w(ov, 0x2b, sixty?0xa8:0x28); + i2c_w(ov, 0x2a, sixty?0x84:0xa4); + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_light_freq"); + return -EINVAL; + } + + ov->lightfreq = freq; + + return 0; +} + +/* If enable is true, turn on the sensor's banding filter, otherwise turn it + * off. This filter tries to reduce the pattern of horizontal light/dark bands + * caused by some (usually fluorescent) lighting. The light frequency must be + * set either before or after enabling it with ov51x_set_light_freq(). + * + * Tested with: OV7610, OV7620, OV76BE, OV6620. + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_banding_filter(struct usb_ov511 *ov, int enable) +{ + int rc; + + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B + || ov->sensor == SEN_SAA7111A) { + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + } + + rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04); + if (rc < 0) + return rc; + + ov->bandfilt = enable; + + return 0; +} + +/* If enable is true, turn on the sensor's auto brightness control, otherwise + * turn it off. + * + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_auto_brightness(struct usb_ov511 *ov, int enable) +{ + int rc; + + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B + || ov->sensor == SEN_SAA7111A) { + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + } + + rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10); + if (rc < 0) + return rc; + + ov->auto_brt = enable; + + return 0; +} + +/* If enable is true, turn on the sensor's auto exposure control, otherwise + * turn it off. + * + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_auto_exposure(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + switch (ov->sensor) { + case SEN_OV7610: + i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80); + break; + case SEN_OV6620: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01); + break; + case SEN_OV6630: + i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10); + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_auto_exposure"); + return -EINVAL; + } + + ov->auto_exp = enable; + + return 0; +} + +/* Modifies the sensor's exposure algorithm to allow proper exposure of objects + * that are illuminated from behind. + * + * Tested with: OV6620, OV7620 + * Unsupported: OV7610, OV76BE, KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_backlight(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + switch (ov->sensor) { + case SEN_OV7620: + case SEN_OV8600: + i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0); + i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); + i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); + break; + case SEN_OV6620: + i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0); + i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); + i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80); + break; + case SEN_OV6630: + i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0); + i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); + i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); + break; + case SEN_OV7610: + case SEN_OV76BE: + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_backlight"); + return -EINVAL; + } + + ov->backlight = enable; + + return 0; +} + +static int +sensor_set_mirror(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + switch (ov->sensor) { + case SEN_OV6620: + case SEN_OV6630: + case SEN_OV7610: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + i2c_w_mask(ov, 0x12, enable?0x40:0x00, 0x40); + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_mirror"); + return -EINVAL; + } + + ov->mirror = enable; + + return 0; +} + +/* Returns number of bits per pixel (regardless of where they are located; + * planar or not), or zero for unsupported format. + */ +static inline int +get_depth(int palette) +{ + switch (palette) { + case VIDEO_PALETTE_GREY: return 8; + case VIDEO_PALETTE_YUV420: return 12; + case VIDEO_PALETTE_YUV420P: return 12; /* Planar */ + default: return 0; /* Invalid format */ + } +} + +/* Bytes per frame. Used by read(). Return of 0 indicates error */ +static inline long int +get_frame_length(struct ov511_frame *frame) +{ + if (!frame) + return 0; + else + return ((frame->width * frame->height + * get_depth(frame->format)) >> 3); +} + +static int +mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height, + int mode, int sub_flag, int qvga) +{ + int clock; + + /******** Mode (VGA/QVGA) and sensor specific regs ********/ + + switch (ov->sensor) { + case SEN_OV7610: + i2c_w(ov, 0x14, qvga?0x24:0x04); +// FIXME: Does this improve the image quality or frame rate? +#if 0 + i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); + i2c_w(ov, 0x24, 0x10); + i2c_w(ov, 0x25, qvga?0x40:0x8a); + i2c_w(ov, 0x2f, qvga?0x30:0xb0); + i2c_w(ov, 0x35, qvga?0x1c:0x9c); +#endif + break; + case SEN_OV7620: +// i2c_w(ov, 0x2b, 0x00); + i2c_w(ov, 0x14, qvga?0xa4:0x84); + i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); + i2c_w(ov, 0x24, qvga?0x20:0x3a); + i2c_w(ov, 0x25, qvga?0x30:0x60); + i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); + i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0); + i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); + break; + case SEN_OV76BE: +// i2c_w(ov, 0x2b, 0x00); + i2c_w(ov, 0x14, qvga?0xa4:0x84); +// FIXME: Enable this once 7620AE uses 7620 initial settings +#if 0 + i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); + i2c_w(ov, 0x24, qvga?0x20:0x3a); + i2c_w(ov, 0x25, qvga?0x30:0x60); + i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); + i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0); + i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); +#endif + break; + case SEN_OV6620: + i2c_w(ov, 0x14, qvga?0x24:0x04); + break; + case SEN_OV6630: + i2c_w(ov, 0x14, qvga?0xa0:0x80); + break; + default: + err("Invalid sensor"); + return -EINVAL; + } + + /******** Palette-specific regs ********/ + + if (mode == VIDEO_PALETTE_GREY) { + if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { + /* these aren't valid on the OV6620/OV7620/6630? */ + i2c_w_mask(ov, 0x0e, 0x40, 0x40); + } + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x00, 0x10); + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } + } else { + if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { + /* not valid on the OV6620/OV7620/6630? */ + i2c_w_mask(ov, 0x0e, 0x00, 0x40); + } + + /* The OV518 needs special treatment. Although both the OV518 + * and the OV6630 support a 16-bit video bus, only the 8 bit Y + * bus is actually used. The UV bus is tied to ground. + * Therefore, the OV6630 needs to be in 8-bit multiplexed + * output mode */ + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x10, 0x10); + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } + } + + /******** Clock programming ********/ + + /* The OV6620 needs special handling. This prevents the + * severe banding that normally occurs */ + if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) + { + /* Clock down */ + + i2c_w(ov, 0x2a, 0x04); + + if (ov->compress) { +// clock = 0; /* This ensures the highest frame rate */ + clock = 3; + } else if (clockdiv == -1) { /* If user didn't override it */ + clock = 3; /* Gives better exposure time */ + } else { + clock = clockdiv; + } + + PDEBUG(4, "Setting clock divisor to %d", clock); + + i2c_w(ov, 0x11, clock); + + i2c_w(ov, 0x2a, 0x84); + /* This next setting is critical. It seems to improve + * the gain or the contrast. The "reserved" bits seem + * to have some effect in this case. */ + i2c_w(ov, 0x2d, 0x85); + } + else + { + if (ov->compress) { + clock = 1; /* This ensures the highest frame rate */ + } else if (clockdiv == -1) { /* If user didn't override it */ + /* Calculate and set the clock divisor */ + clock = ((sub_flag ? ov->subw * ov->subh + : width * height) + * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2) + / 66000; + } else { + clock = clockdiv; + } + + PDEBUG(4, "Setting clock divisor to %d", clock); + + i2c_w(ov, 0x11, clock); + } + + /******** Special Features ********/ + + if (framedrop >= 0) + i2c_w(ov, 0x16, framedrop); + + /* Test Pattern */ + i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02); + + /* Enable auto white balance */ + i2c_w_mask(ov, 0x12, 0x04, 0x04); + + // This will go away as soon as ov51x_mode_init_sensor_regs() + // is fully tested. + /* 7620/6620/6630? don't have register 0x35, so play it safe */ + if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { + if (width == 640 && height == 480) + i2c_w(ov, 0x35, 0x9e); + else + i2c_w(ov, 0x35, 0x1e); + } + + return 0; +} + +static int +set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode, + int sub_flag) +{ + int ret; + int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; + int hoffset, voffset, hwscale = 0, vwscale = 0; + + /* The different sensor ICs handle setting up of window differently. + * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */ + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + hwsbase = 0x38; + hwebase = 0x3a; + vwsbase = vwebase = 0x05; + break; + case SEN_OV6620: + case SEN_OV6630: + hwsbase = 0x38; + hwebase = 0x3a; + vwsbase = 0x05; + vwebase = 0x06; + break; + case SEN_OV7620: + hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ + hwebase = 0x2f; + vwsbase = vwebase = 0x05; + break; + default: + err("Invalid sensor"); + return -EINVAL; + } + + if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) { + /* Note: OV518(+) does downsample on its own) */ + if ((width > 176 && height > 144) + || ov->bclass == BCL_OV518) { /* CIF */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 0); + if (ret < 0) + return ret; + hwscale = 1; + vwscale = 1; /* The datasheet says 0; it's wrong */ + hwsize = 352; + vwsize = 288; + } else if (width > 176 || height > 144) { + err("Illegal dimensions"); + return -EINVAL; + } else { /* QCIF */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 1); + if (ret < 0) + return ret; + hwsize = 176; + vwsize = 144; + } + } else { + if (width > 320 && height > 240) { /* VGA */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 0); + if (ret < 0) + return ret; + hwscale = 2; + vwscale = 1; + hwsize = 640; + vwsize = 480; + } else if (width > 320 || height > 240) { + err("Illegal dimensions"); + return -EINVAL; + } else { /* QVGA */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 1); + if (ret < 0) + return ret; + hwscale = 1; + hwsize = 320; + vwsize = 240; + } + } + + /* Center the window */ + hoffset = ((hwsize - width) / 2) >> hwscale; + voffset = ((vwsize - height) / 2) >> vwscale; + + /* FIXME! - This needs to be changed to support 160x120 and 6620!!! */ + if (sub_flag) { + i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale)); + i2c_w(ov, 0x18, hwebase+((ov->subx+ov->subw)>>hwscale)); + i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale)); + i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale)); + } else { + i2c_w(ov, 0x17, hwsbase + hoffset); + i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale)); + i2c_w(ov, 0x19, vwsbase + voffset); + i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale)); + } + +#ifdef OV511_DEBUG + if (dump_sensor) + dump_i2c_regs(ov); +#endif + + return 0; +} + +/* Set up the OV511/OV511+ with the given image parameters. + * + * Do not put any sensor-specific code in here (including I2C I/O functions) + */ +static int +ov511_mode_init_regs(struct usb_ov511 *ov, + int width, int height, int mode, int sub_flag) +{ + int hsegs, vsegs; + + if (sub_flag) { + width = ov->subw; + height = ov->subh; + } + + PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", + width, height, mode, sub_flag); + + // FIXME: This should be moved to a 7111a-specific function once + // subcapture is dealt with properly + if (ov->sensor == SEN_SAA7111A) { + if (width == 320 && height == 240) { + /* No need to do anything special */ + } else if (width == 640 && height == 480) { + /* Set the OV511 up as 320x480, but keep the + * V4L resolution as 640x480 */ + width = 320; + } else { + err("SAA7111A only allows 320x240 or 640x480"); + return -EINVAL; + } + } + + /* Make sure width and height are a multiple of 8 */ + if (width % 8 || height % 8) { + err("Invalid size (%d, %d) (mode = %d)", width, height, mode); + return -EINVAL; + } + + if (width < ov->minwidth || height < ov->minheight) { + err("Requested dimensions are too small"); + return -EINVAL; + } + + if (ov51x_stop(ov) < 0) + return -EIO; + + if (mode == VIDEO_PALETTE_GREY) { + reg_w(ov, R511_CAM_UV_EN, 0x00); + reg_w(ov, R511_SNAP_UV_EN, 0x00); + reg_w(ov, R511_SNAP_OPTS, 0x01); + } else { + reg_w(ov, R511_CAM_UV_EN, 0x01); + reg_w(ov, R511_SNAP_UV_EN, 0x01); + reg_w(ov, R511_SNAP_OPTS, 0x03); + } + + /* Here I'm assuming that snapshot size == image size. + * I hope that's always true. --claudio + */ + hsegs = (width >> 3) - 1; + vsegs = (height >> 3) - 1; + + reg_w(ov, R511_CAM_PXCNT, hsegs); + reg_w(ov, R511_CAM_LNCNT, vsegs); + reg_w(ov, R511_CAM_PXDIV, 0x00); + reg_w(ov, R511_CAM_LNDIV, 0x00); + + /* YUV420, low pass filter on */ + reg_w(ov, R511_CAM_OPTS, 0x03); + + /* Snapshot additions */ + reg_w(ov, R511_SNAP_PXCNT, hsegs); + reg_w(ov, R511_SNAP_LNCNT, vsegs); + reg_w(ov, R511_SNAP_PXDIV, 0x00); + reg_w(ov, R511_SNAP_LNDIV, 0x00); + + if (ov->compress) { + /* Enable Y and UV quantization and compression */ + reg_w(ov, R511_COMP_EN, 0x07); + reg_w(ov, R511_COMP_LUT_EN, 0x03); + ov51x_reset(ov, OV511_RESET_OMNICE); + } + + if (ov51x_restart(ov) < 0) + return -EIO; + + return 0; +} + +/* Sets up the OV518/OV518+ with the given image parameters + * + * OV518 needs a completely different approach, until we can figure out what + * the individual registers do. Also, only 15 FPS is supported now. + * + * Do not put any sensor-specific code in here (including I2C I/O functions) + */ +static int +ov518_mode_init_regs(struct usb_ov511 *ov, + int width, int height, int mode, int sub_flag) +{ + int hsegs, vsegs, hi_res; + + if (sub_flag) { + width = ov->subw; + height = ov->subh; + } + + PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", + width, height, mode, sub_flag); + + if (width % 16 || height % 8) { + err("Invalid size (%d, %d)", width, height); + return -EINVAL; + } + + if (width < ov->minwidth || height < ov->minheight) { + err("Requested dimensions are too small"); + return -EINVAL; + } + + if (width >= 320 && height >= 240) { + hi_res = 1; + } else if (width >= 320 || height >= 240) { + err("Invalid width/height combination (%d, %d)", width, height); + return -EINVAL; + } else { + hi_res = 0; + } + + if (ov51x_stop(ov) < 0) + return -EIO; + + /******** Set the mode ********/ + + reg_w(ov, 0x2b, 0); + reg_w(ov, 0x2c, 0); + reg_w(ov, 0x2d, 0); + reg_w(ov, 0x2e, 0); + reg_w(ov, 0x3b, 0); + reg_w(ov, 0x3c, 0); + reg_w(ov, 0x3d, 0); + reg_w(ov, 0x3e, 0); + + if (ov->bridge == BRG_OV518 && ov518_color) { + /* OV518 needs U and V swapped */ + i2c_w_mask(ov, 0x15, 0x00, 0x01); + + if (mode == VIDEO_PALETTE_GREY) { + /* Set 16-bit input format (UV data are ignored) */ + reg_w_mask(ov, 0x20, 0x00, 0x08); + + /* Set 8-bit (4:0:0) output format */ + reg_w_mask(ov, 0x28, 0x00, 0xf0); + reg_w_mask(ov, 0x38, 0x00, 0xf0); + } else { + /* Set 8-bit (YVYU) input format */ + reg_w_mask(ov, 0x20, 0x08, 0x08); + + /* Set 12-bit (4:2:0) output format */ + reg_w_mask(ov, 0x28, 0x80, 0xf0); + reg_w_mask(ov, 0x38, 0x80, 0xf0); + } + } else { + reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + } + + hsegs = width / 16; + vsegs = height / 4; + + reg_w(ov, 0x29, hsegs); + reg_w(ov, 0x2a, vsegs); + + reg_w(ov, 0x39, hsegs); + reg_w(ov, 0x3a, vsegs); + + /* Windows driver does this here; who knows why */ + reg_w(ov, 0x2f, 0x80); + + /******** Set the framerate (to 15 FPS) ********/ + + /* Mode independent, but framerate dependent, regs */ + reg_w(ov, 0x51, 0x02); /* Clock divider; lower==faster */ + reg_w(ov, 0x22, 0x18); + reg_w(ov, 0x23, 0xff); + + if (ov->bridge == BRG_OV518PLUS) + reg_w(ov, 0x21, 0x19); + else + reg_w(ov, 0x71, 0x19); /* Compression-related? */ + + // FIXME: Sensor-specific + /* Bit 5 is what matters here. Of course, it is "reserved" */ + i2c_w(ov, 0x54, 0x23); + + reg_w(ov, 0x2f, 0x80); + + if (ov->bridge == BRG_OV518PLUS) { + reg_w(ov, 0x24, 0x94); + reg_w(ov, 0x25, 0x90); + ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ + ov518_reg_w32(ov, 0xc6, 540, 2); /* 21ch */ + ov518_reg_w32(ov, 0xc7, 540, 2); /* 21ch */ + ov518_reg_w32(ov, 0xc8, 108, 2); /* 6ch */ + ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ + ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ + ov518_reg_w32(ov, 0xcc, 2400, 2); /* 960h */ + ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ + ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ + } else { + reg_w(ov, 0x24, 0x9f); + reg_w(ov, 0x25, 0x90); + ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ + ov518_reg_w32(ov, 0xc6, 500, 2); /* 1f4h */ + ov518_reg_w32(ov, 0xc7, 500, 2); /* 1f4h */ + ov518_reg_w32(ov, 0xc8, 142, 2); /* 8eh */ + ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ + ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ + ov518_reg_w32(ov, 0xcc, 2000, 2); /* 7d0h */ + ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ + ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ + } + + reg_w(ov, 0x2f, 0x80); + + if (ov51x_restart(ov) < 0) + return -EIO; + + /* Reset it just for good measure */ + if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) + return -EIO; + + return 0; +} + +/* This is a wrapper around the OV511, OV518, and sensor specific functions */ +static int +mode_init_regs(struct usb_ov511 *ov, + int width, int height, int mode, int sub_flag) +{ + int rc = 0; + + if (!ov || !ov->dev) + return -EFAULT; + + if (ov->bclass == BCL_OV518) { + rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag); + } else { + rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag); + } + + if (FATAL_ERROR(rc)) + return rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + case SEN_OV6620: + case SEN_OV6630: + rc = set_ov_sensor_window(ov, width, height, mode, sub_flag); + break; + case SEN_KS0127: + case SEN_KS0127B: + err("KS0127-series decoders not supported yet"); + rc = -EINVAL; + break; + case SEN_SAA7111A: +// rc = mode_init_saa_sensor_regs(ov, width, height, mode, +// sub_flag); + + PDEBUG(1, "SAA status = 0x%02X", i2c_r(ov, 0x1f)); + break; + default: + err("Unknown sensor"); + rc = -EINVAL; + } + + if (FATAL_ERROR(rc)) + return rc; + + /* Sensor-independent settings */ + rc = sensor_set_auto_brightness(ov, ov->auto_brt); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_auto_exposure(ov, ov->auto_exp); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_banding_filter(ov, bandingfilter); + if (FATAL_ERROR(rc)) + return rc; + + if (ov->lightfreq) { + rc = sensor_set_light_freq(ov, lightfreq); + if (FATAL_ERROR(rc)) + return rc; + } + + rc = sensor_set_backlight(ov, ov->backlight); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_mirror(ov, ov->mirror); + if (FATAL_ERROR(rc)) + return rc; + + return 0; +} + +/* This sets the default image parameters. This is useful for apps that use + * read() and do not set these. + */ +static int +ov51x_set_default_params(struct usb_ov511 *ov) +{ + int i; + + /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used + * (using read() instead). */ + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].width = ov->maxwidth; + ov->frame[i].height = ov->maxheight; + ov->frame[i].bytes_read = 0; + if (force_palette) + ov->frame[i].format = force_palette; + else + ov->frame[i].format = VIDEO_PALETTE_YUV420; + + ov->frame[i].depth = get_depth(ov->frame[i].format); + } + + PDEBUG(3, "%dx%d, %s", ov->maxwidth, ov->maxheight, + symbolic(v4l1_plist, ov->frame[0].format)); + + /* Initialize to max width/height, YUV420 or RGB24 (if supported) */ + if (mode_init_regs(ov, ov->maxwidth, ov->maxheight, + ov->frame[0].format, 0) < 0) + return -EINVAL; + + return 0; +} + +/********************************************************************** + * + * Video decoder stuff + * + **********************************************************************/ + +/* Set analog input port of decoder */ +static int +decoder_set_input(struct usb_ov511 *ov, int input) +{ + PDEBUG(4, "port %d", input); + + switch (ov->sensor) { + case SEN_SAA7111A: + { + /* Select mode */ + i2c_w_mask(ov, 0x02, input, 0x07); + /* Bypass chrominance trap for modes 4..7 */ + i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80); + break; + } + default: + return -EINVAL; + } + + return 0; +} + +/* Get ASCII name of video input */ +static int +decoder_get_input_name(struct usb_ov511 *ov, int input, char *name) +{ + switch (ov->sensor) { + case SEN_SAA7111A: + { + if (input < 0 || input > 7) + return -EINVAL; + else if (input < 4) + sprintf(name, "CVBS-%d", input); + else // if (input < 8) + sprintf(name, "S-Video-%d", input - 4); + break; + } + default: + sprintf(name, "%s", "Camera"); + } + + return 0; +} + +/* Set norm (NTSC, PAL, SECAM, AUTO) */ +static int +decoder_set_norm(struct usb_ov511 *ov, int norm) +{ + PDEBUG(4, "%d", norm); + + switch (ov->sensor) { + case SEN_SAA7111A: + { + int reg_8, reg_e; + + if (norm == VIDEO_MODE_NTSC) { + reg_8 = 0x40; /* 60 Hz */ + reg_e = 0x00; /* NTSC M / PAL BGHI */ + } else if (norm == VIDEO_MODE_PAL) { + reg_8 = 0x00; /* 50 Hz */ + reg_e = 0x00; /* NTSC M / PAL BGHI */ + } else if (norm == VIDEO_MODE_AUTO) { + reg_8 = 0x80; /* Auto field detect */ + reg_e = 0x00; /* NTSC M / PAL BGHI */ + } else if (norm == VIDEO_MODE_SECAM) { + reg_8 = 0x00; /* 50 Hz */ + reg_e = 0x50; /* SECAM / PAL 4.43 */ + } else { + return -EINVAL; + } + + i2c_w_mask(ov, 0x08, reg_8, 0xc0); + i2c_w_mask(ov, 0x0e, reg_e, 0x70); + break; + } + default: + return -EINVAL; + } + + return 0; +} + +/********************************************************************** + * + * Raw data parsing + * + **********************************************************************/ + +/* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the + * image at pOut is specified by w. + */ +static inline void +make_8x8(unsigned char *pIn, unsigned char *pOut, int w) +{ + unsigned char *pOut1 = pOut; + int x, y; + + for (y = 0; y < 8; y++) { + pOut1 = pOut; + for (x = 0; x < 8; x++) { + *pOut1++ = *pIn++; + } + pOut += w; + } +} + +/* + * For RAW BW (YUV 4:0:0) images, data show up in 256 byte segments. + * The segments represent 4 squares of 8x8 pixels as follows: + * + * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 + * 8 9 ... 15 72 73 ... 79 200 201 ... 207 + * ... ... ... + * 56 57 ... 63 120 121 ... 127 248 249 ... 255 + * + */ +static void +yuv400raw_to_yuv400p(struct ov511_frame *frame, + unsigned char *pIn0, unsigned char *pOut0) +{ + int x, y; + unsigned char *pIn, *pOut, *pOutLine; + + /* Copy Y */ + pIn = pIn0; + pOutLine = pOut0; + for (y = 0; y < frame->rawheight - 1; y += 8) { + pOut = pOutLine; + for (x = 0; x < frame->rawwidth - 1; x += 8) { + make_8x8(pIn, pOut, frame->rawwidth); + pIn += 64; + pOut += 8; + } + pOutLine += 8 * frame->rawwidth; + } +} + +/* + * For YUV 4:2:0 images, the data show up in 384 byte segments. + * The first 64 bytes of each segment are U, the next 64 are V. The U and + * V are arranged as follows: + * + * 0 1 ... 7 + * 8 9 ... 15 + * ... + * 56 57 ... 63 + * + * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block). + * + * The next 256 bytes are full resolution Y data and represent 4 squares + * of 8x8 pixels as follows: + * + * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 + * 8 9 ... 15 72 73 ... 79 200 201 ... 207 + * ... ... ... + * 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255 + * + * Note that the U and V data in one segment represent a 16 x 16 pixel + * area, but the Y data represent a 32 x 8 pixel area. If the width is not an + * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the + * next horizontal stripe. + * + * If dumppix module param is set, _parse_data just dumps the incoming segments, + * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 + * this puts the data on the standard output and can be analyzed with the + * parseppm.c utility I wrote. That's a much faster way for figuring out how + * these data are scrambled. + */ + +/* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0. + * + * FIXME: Currently only handles width and height that are multiples of 16 + */ +static void +yuv420raw_to_yuv420p(struct ov511_frame *frame, + unsigned char *pIn0, unsigned char *pOut0) +{ + int k, x, y; + unsigned char *pIn, *pOut, *pOutLine; + const unsigned int a = frame->rawwidth * frame->rawheight; + const unsigned int w = frame->rawwidth / 2; + + /* Copy U and V */ + pIn = pIn0; + pOutLine = pOut0 + a; + for (y = 0; y < frame->rawheight - 1; y += 16) { + pOut = pOutLine; + for (x = 0; x < frame->rawwidth - 1; x += 16) { + make_8x8(pIn, pOut, w); + make_8x8(pIn + 64, pOut + a/4, w); + pIn += 384; + pOut += 8; + } + pOutLine += 8 * w; + } + + /* Copy Y */ + pIn = pIn0 + 128; + pOutLine = pOut0; + k = 0; + for (y = 0; y < frame->rawheight - 1; y += 8) { + pOut = pOutLine; + for (x = 0; x < frame->rawwidth - 1; x += 8) { + make_8x8(pIn, pOut, frame->rawwidth); + pIn += 64; + pOut += 8; + if ((++k) > 3) { + k = 0; + pIn += 128; + } + } + pOutLine += 8 * frame->rawwidth; + } +} + +/********************************************************************** + * + * Decompression + * + **********************************************************************/ + +/* Chooses a decompression module, locks it, and sets ov->decomp_ops + * accordingly. Returns -ENXIO if decompressor is not available, otherwise + * returns 0 if no other error. + */ +static int +request_decompressor(struct usb_ov511 *ov) +{ + if (!ov) + return -ENODEV; + + if (ov->decomp_ops) { + err("ERROR: Decompressor already requested!"); + return -EINVAL; + } + + lock_kernel(); + + /* Try to get MMX, and fall back on no-MMX if necessary */ + if (ov->bclass == BCL_OV511) { + if (ov511_mmx_decomp_ops) { + PDEBUG(3, "Using OV511 MMX decompressor"); + ov->decomp_ops = ov511_mmx_decomp_ops; + } else if (ov511_decomp_ops) { + PDEBUG(3, "Using OV511 decompressor"); + ov->decomp_ops = ov511_decomp_ops; + } else { + err("No decompressor available"); + } + } else if (ov->bclass == BCL_OV518) { + if (ov518_mmx_decomp_ops) { + PDEBUG(3, "Using OV518 MMX decompressor"); + ov->decomp_ops = ov518_mmx_decomp_ops; + } else if (ov518_decomp_ops) { + PDEBUG(3, "Using OV518 decompressor"); + ov->decomp_ops = ov518_decomp_ops; + } else { + err("No decompressor available"); + } + } else { + err("Unknown bridge"); + } + + if (!ov->decomp_ops) + goto nosys; + + if (!ov->decomp_ops->owner) { + ov->decomp_ops = NULL; + goto nosys; + } + + if (!try_module_get(ov->decomp_ops->owner)) + goto nosys; + + unlock_kernel(); + return 0; + + nosys: + unlock_kernel(); + return -ENOSYS; +} + +/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even + * if ov->decomp_ops is NULL. + */ +static void +release_decompressor(struct usb_ov511 *ov) +{ + int released = 0; /* Did we actually do anything? */ + + if (!ov) + return; + + lock_kernel(); + + if (ov->decomp_ops) { + module_put(ov->decomp_ops->owner); + released = 1; + } + + ov->decomp_ops = NULL; + + unlock_kernel(); + + if (released) + PDEBUG(3, "Decompressor released"); +} + +static void +decompress(struct usb_ov511 *ov, struct ov511_frame *frame, + unsigned char *pIn0, unsigned char *pOut0) +{ + if (!ov->decomp_ops) + if (request_decompressor(ov)) + return; + + PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd); + + if (frame->format == VIDEO_PALETTE_GREY + && ov->decomp_ops->decomp_400) { + int ret = ov->decomp_ops->decomp_400( + pIn0, + pOut0, + frame->compbuf, + frame->rawwidth, + frame->rawheight, + frame->bytes_recvd); + PDEBUG(4, "DEBUG: decomp_400 returned %d", ret); + } else if (frame->format != VIDEO_PALETTE_GREY + && ov->decomp_ops->decomp_420) { + int ret = ov->decomp_ops->decomp_420( + pIn0, + pOut0, + frame->compbuf, + frame->rawwidth, + frame->rawheight, + frame->bytes_recvd); + PDEBUG(4, "DEBUG: decomp_420 returned %d", ret); + } else { + err("Decompressor does not support this format"); + } +} + +/********************************************************************** + * + * Format conversion + * + **********************************************************************/ + +/* Fuses even and odd fields together, and doubles width. + * INPUT: an odd field followed by an even field at pIn0, in YUV planar format + * OUTPUT: a normal YUV planar image, with correct aspect ratio + */ +static void +deinterlace(struct ov511_frame *frame, int rawformat, + unsigned char *pIn0, unsigned char *pOut0) +{ + const int fieldheight = frame->rawheight / 2; + const int fieldpix = fieldheight * frame->rawwidth; + const int w = frame->width; + int x, y; + unsigned char *pInEven, *pInOdd, *pOut; + + PDEBUG(5, "fieldheight=%d", fieldheight); + + if (frame->rawheight != frame->height) { + err("invalid height"); + return; + } + + if ((frame->rawwidth * 2) != frame->width) { + err("invalid width"); + return; + } + + /* Y */ + pInOdd = pIn0; + pInEven = pInOdd + fieldpix; + pOut = pOut0; + for (y = 0; y < fieldheight; y++) { + for (x = 0; x < frame->rawwidth; x++) { + *pOut = *pInEven; + *(pOut+1) = *pInEven++; + *(pOut+w) = *pInOdd; + *(pOut+w+1) = *pInOdd++; + pOut += 2; + } + pOut += w; + } + + if (rawformat == RAWFMT_YUV420) { + /* U */ + pInOdd = pIn0 + fieldpix * 2; + pInEven = pInOdd + fieldpix / 4; + for (y = 0; y < fieldheight / 2; y++) { + for (x = 0; x < frame->rawwidth / 2; x++) { + *pOut = *pInEven; + *(pOut+1) = *pInEven++; + *(pOut+w/2) = *pInOdd; + *(pOut+w/2+1) = *pInOdd++; + pOut += 2; + } + pOut += w/2; + } + /* V */ + pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2; + pInEven = pInOdd + fieldpix / 4; + for (y = 0; y < fieldheight / 2; y++) { + for (x = 0; x < frame->rawwidth / 2; x++) { + *pOut = *pInEven; + *(pOut+1) = *pInEven++; + *(pOut+w/2) = *pInOdd; + *(pOut+w/2+1) = *pInOdd++; + pOut += 2; + } + pOut += w/2; + } + } +} + +static void +ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame) +{ + /* Deinterlace frame, if necessary */ + if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, + frame->tempdata); + else + yuv400raw_to_yuv400p(frame, frame->rawdata, + frame->tempdata); + + deinterlace(frame, RAWFMT_YUV400, frame->tempdata, + frame->data); + } else { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, + frame->data); + else + yuv400raw_to_yuv400p(frame, frame->rawdata, + frame->data); + } +} + +/* Process raw YUV420 data into standard YUV420P */ +static void +ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame) +{ + /* Deinterlace frame, if necessary */ + if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, frame->tempdata); + else + yuv420raw_to_yuv420p(frame, frame->rawdata, + frame->tempdata); + + deinterlace(frame, RAWFMT_YUV420, frame->tempdata, + frame->data); + } else { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, frame->data); + else + yuv420raw_to_yuv420p(frame, frame->rawdata, + frame->data); + } +} + +/* Post-processes the specified frame. This consists of: + * 1. Decompress frame, if necessary + * 2. Deinterlace frame and scale to proper size, if necessary + * 3. Convert from YUV planar to destination format, if necessary + * 4. Fix the RGB offset, if necessary + */ +static void +ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame) +{ + if (dumppix) { + memset(frame->data, 0, + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); + PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd); + memcpy(frame->data, frame->rawdata, frame->bytes_recvd); + } else { + switch (frame->format) { + case VIDEO_PALETTE_GREY: + ov51x_postprocess_grey(ov, frame); + break; + case VIDEO_PALETTE_YUV420: + case VIDEO_PALETTE_YUV420P: + ov51x_postprocess_yuv420(ov, frame); + break; + default: + err("Cannot convert data to %s", + symbolic(v4l1_plist, frame->format)); + } + } +} + +/********************************************************************** + * + * OV51x data transfer, IRQ handler + * + **********************************************************************/ + +static inline void +ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) +{ + int num, offset; + int pnum = in[ov->packet_size - 1]; /* Get packet number */ + int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); + struct ov511_frame *frame = &ov->frame[ov->curframe]; + struct timeval *ts; + + /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th + * byte non-zero. The EOF packet has image width/height in the + * 10th and 11th bytes. The 9th byte is given as follows: + * + * bit 7: EOF + * 6: compression enabled + * 5: 422/420/400 modes + * 4: 422/420/400 modes + * 3: 1 + * 2: snapshot button on + * 1: snapshot frame + * 0: even/odd field + */ + + if (printph) { + info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", + pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], + in[7], in[8], in[9], in[10], in[11]); + } + + /* Check for SOF/EOF packet */ + if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) || + (~in[8] & 0x08)) + goto check_middle; + + /* Frame end */ + if (in[8] & 0x80) { + ts = (struct timeval *)(frame->data + + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); + do_gettimeofday(ts); + + /* Get the actual frame size from the EOF header */ + frame->rawwidth = ((int)(in[9]) + 1) * 8; + frame->rawheight = ((int)(in[10]) + 1) * 8; + + PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d", + ov->curframe, pnum, frame->rawwidth, frame->rawheight, + frame->bytes_recvd); + + /* Validate the header data */ + RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); + RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, + ov->maxheight); + + /* Don't allow byte count to exceed buffer size */ + RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); + + if (frame->scanstate == STATE_LINES) { + int nextf; + + frame->grabstate = FRAME_DONE; + wake_up_interruptible(&frame->wq); + + /* If next frame is ready or grabbing, + * point to it */ + nextf = (ov->curframe + 1) % OV511_NUMFRAMES; + if (ov->frame[nextf].grabstate == FRAME_READY + || ov->frame[nextf].grabstate == FRAME_GRABBING) { + ov->curframe = nextf; + ov->frame[nextf].scanstate = STATE_SCANNING; + } else { + if (frame->grabstate == FRAME_DONE) { + PDEBUG(4, "** Frame done **"); + } else { + PDEBUG(4, "Frame not ready? state = %d", + ov->frame[nextf].grabstate); + } + + ov->curframe = -1; + } + } else { + PDEBUG(5, "Frame done, but not scanning"); + } + /* Image corruption caused by misplaced frame->segment = 0 + * fixed by carlosf@conectiva.com.br + */ + } else { + /* Frame start */ + PDEBUG(4, "Frame start, framenum = %d", ov->curframe); + + /* Check to see if it's a snapshot frame */ + /* FIXME?? Should the snapshot reset go here? Performance? */ + if (in[8] & 0x02) { + frame->snapshot = 1; + PDEBUG(3, "snapshot detected"); + } + + frame->scanstate = STATE_LINES; + frame->bytes_recvd = 0; + frame->compressed = in[8] & 0x40; + } + +check_middle: + /* Are we in a frame? */ + if (frame->scanstate != STATE_LINES) { + PDEBUG(5, "Not in a frame; packet skipped"); + return; + } + + /* If frame start, skip header */ + if (frame->bytes_recvd == 0) + offset = 9; + else + offset = 0; + + num = n - offset - 1; + + /* Dump all data exactly as received */ + if (dumppix == 2) { + frame->bytes_recvd += n - 1; + if (frame->bytes_recvd <= max_raw) + memcpy(frame->rawdata + frame->bytes_recvd - (n - 1), + in, n - 1); + else + PDEBUG(3, "Raw data buffer overrun!! (%d)", + frame->bytes_recvd - max_raw); + } else if (!frame->compressed && !remove_zeros) { + frame->bytes_recvd += num; + if (frame->bytes_recvd <= max_raw) + memcpy(frame->rawdata + frame->bytes_recvd - num, + in + offset, num); + else + PDEBUG(3, "Raw data buffer overrun!! (%d)", + frame->bytes_recvd - max_raw); + } else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */ + int b, read = 0, allzero, copied = 0; + if (offset) { + frame->bytes_recvd += 32 - offset; // Bytes out + memcpy(frame->rawdata, in + offset, 32 - offset); + read += 32; + } + + while (read < n - 1) { + allzero = 1; + for (b = 0; b < 32; b++) { + if (in[read + b]) { + allzero = 0; + break; + } + } + + if (allzero) { + /* Don't copy it */ + } else { + if (frame->bytes_recvd + copied + 32 <= max_raw) + { + memcpy(frame->rawdata + + frame->bytes_recvd + copied, + in + read, 32); + copied += 32; + } else { + PDEBUG(3, "Raw data buffer overrun!!"); + } + } + read += 32; + } + + frame->bytes_recvd += copied; + } +} + +static inline void +ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n) +{ + int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); + struct ov511_frame *frame = &ov->frame[ov->curframe]; + struct timeval *ts; + + /* Don't copy the packet number byte */ + if (ov->packet_numbering) + --n; + + /* A false positive here is likely, until OVT gives me + * the definitive SOF/EOF format */ + if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { + if (printph) { + info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0], + in[1], in[2], in[3], in[4], in[5], in[6], in[7]); + } + + if (frame->scanstate == STATE_LINES) { + PDEBUG(4, "Detected frame end/start"); + goto eof; + } else { //scanstate == STATE_SCANNING + /* Frame start */ + PDEBUG(4, "Frame start, framenum = %d", ov->curframe); + goto sof; + } + } else { + goto check_middle; + } + +eof: + ts = (struct timeval *)(frame->data + + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); + do_gettimeofday(ts); + + PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d", + ov->curframe, + (int)(in[9]), (int)(in[10]), frame->bytes_recvd); + + // FIXME: Since we don't know the header formats yet, + // there is no way to know what the actual image size is + frame->rawwidth = frame->width; + frame->rawheight = frame->height; + + /* Validate the header data */ + RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); + RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight); + + /* Don't allow byte count to exceed buffer size */ + RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); + + if (frame->scanstate == STATE_LINES) { + int nextf; + + frame->grabstate = FRAME_DONE; + wake_up_interruptible(&frame->wq); + + /* If next frame is ready or grabbing, + * point to it */ + nextf = (ov->curframe + 1) % OV511_NUMFRAMES; + if (ov->frame[nextf].grabstate == FRAME_READY + || ov->frame[nextf].grabstate == FRAME_GRABBING) { + ov->curframe = nextf; + ov->frame[nextf].scanstate = STATE_SCANNING; + frame = &ov->frame[nextf]; + } else { + if (frame->grabstate == FRAME_DONE) { + PDEBUG(4, "** Frame done **"); + } else { + PDEBUG(4, "Frame not ready? state = %d", + ov->frame[nextf].grabstate); + } + + ov->curframe = -1; + PDEBUG(4, "SOF dropped (no active frame)"); + return; /* Nowhere to store this frame */ + } + } +sof: + PDEBUG(4, "Starting capture on frame %d", frame->framenum); + +// Snapshot not reverse-engineered yet. +#if 0 + /* Check to see if it's a snapshot frame */ + /* FIXME?? Should the snapshot reset go here? Performance? */ + if (in[8] & 0x02) { + frame->snapshot = 1; + PDEBUG(3, "snapshot detected"); + } +#endif + frame->scanstate = STATE_LINES; + frame->bytes_recvd = 0; + frame->compressed = 1; + +check_middle: + /* Are we in a frame? */ + if (frame->scanstate != STATE_LINES) { + PDEBUG(4, "scanstate: no SOF yet"); + return; + } + + /* Dump all data exactly as received */ + if (dumppix == 2) { + frame->bytes_recvd += n; + if (frame->bytes_recvd <= max_raw) + memcpy(frame->rawdata + frame->bytes_recvd - n, in, n); + else + PDEBUG(3, "Raw data buffer overrun!! (%d)", + frame->bytes_recvd - max_raw); + } else { + /* All incoming data are divided into 8-byte segments. If the + * segment contains all zero bytes, it must be skipped. These + * zero-segments allow the OV518 to mainain a constant data rate + * regardless of the effectiveness of the compression. Segments + * are aligned relative to the beginning of each isochronous + * packet. The first segment in each image is a header (the + * decompressor skips it later). + */ + + int b, read = 0, allzero, copied = 0; + + while (read < n) { + allzero = 1; + for (b = 0; b < 8; b++) { + if (in[read + b]) { + allzero = 0; + break; + } + } + + if (allzero) { + /* Don't copy it */ + } else { + if (frame->bytes_recvd + copied + 8 <= max_raw) + { + memcpy(frame->rawdata + + frame->bytes_recvd + copied, + in + read, 8); + copied += 8; + } else { + PDEBUG(3, "Raw data buffer overrun!!"); + } + } + read += 8; + } + frame->bytes_recvd += copied; + } +} + +static void +ov51x_isoc_irq(struct urb *urb) +{ + int i; + struct usb_ov511 *ov; + struct ov511_sbuf *sbuf; + + if (!urb->context) { + PDEBUG(4, "no context"); + return; + } + + sbuf = urb->context; + ov = sbuf->ov; + + if (!ov || !ov->dev || !ov->user) { + PDEBUG(4, "no device, or not open"); + return; + } + + if (!ov->streaming) { + PDEBUG(4, "hmmm... not streaming, but got interrupt"); + return; + } + + if (urb->status == -ENOENT || urb->status == -ECONNRESET) { + PDEBUG(4, "URB unlinked"); + return; + } + + if (urb->status != -EINPROGRESS && urb->status != 0) { + err("ERROR: urb->status=%d: %s", urb->status, + symbolic(urb_errlist, urb->status)); + } + + /* Copy the data received into our frame buffer */ + PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n, + urb->number_of_packets); + for (i = 0; i < urb->number_of_packets; i++) { + /* Warning: Don't call *_move_data() if no frame active! */ + if (ov->curframe >= 0) { + int n = urb->iso_frame_desc[i].actual_length; + int st = urb->iso_frame_desc[i].status; + unsigned char *cdata; + + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = 0; + + cdata = urb->transfer_buffer + + urb->iso_frame_desc[i].offset; + + if (!n) { + PDEBUG(4, "Zero-length packet"); + continue; + } + + if (st) + PDEBUG(2, "data error: [%d] len=%d, status=%d", + i, n, st); + + if (ov->bclass == BCL_OV511) + ov511_move_data(ov, cdata, n); + else if (ov->bclass == BCL_OV518) + ov518_move_data(ov, cdata, n); + else + err("Unknown bridge device (%d)", ov->bridge); + + } else if (waitqueue_active(&ov->wq)) { + wake_up_interruptible(&ov->wq); + } + } + + /* Resubmit this URB */ + urb->dev = ov->dev; + if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) + err("usb_submit_urb() ret %d", i); + + return; +} + +/**************************************************************************** + * + * Stream initialization and termination + * + ***************************************************************************/ + +static int +ov51x_init_isoc(struct usb_ov511 *ov) +{ + struct urb *urb; + int fx, err, n, size; + + PDEBUG(3, "*** Initializing capture ***"); + + ov->curframe = -1; + + if (ov->bridge == BRG_OV511) { + if (cams == 1) + size = 993; + else if (cams == 2) + size = 513; + else if (cams == 3 || cams == 4) + size = 257; + else { + err("\"cams\" parameter too high!"); + return -1; + } + } else if (ov->bridge == BRG_OV511PLUS) { + if (cams == 1) + size = 961; + else if (cams == 2) + size = 513; + else if (cams == 3 || cams == 4) + size = 257; + else if (cams >= 5 && cams <= 8) + size = 129; + else if (cams >= 9 && cams <= 31) + size = 33; + else { + err("\"cams\" parameter too high!"); + return -1; + } + } else if (ov->bclass == BCL_OV518) { + if (cams == 1) + size = 896; + else if (cams == 2) + size = 512; + else if (cams == 3 || cams == 4) + size = 256; + else if (cams >= 5 && cams <= 8) + size = 128; + else { + err("\"cams\" parameter too high!"); + return -1; + } + } else { + err("invalid bridge type"); + return -1; + } + + // FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now + if (ov->bclass == BCL_OV518) { + if (packetsize == -1) { + ov518_set_packet_size(ov, 640); + } else { + info("Forcing packet size to %d", packetsize); + ov518_set_packet_size(ov, packetsize); + } + } else { + if (packetsize == -1) { + ov511_set_packet_size(ov, size); + } else { + info("Forcing packet size to %d", packetsize); + ov511_set_packet_size(ov, packetsize); + } + } + + for (n = 0; n < OV511_NUMSBUF; n++) { + urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); + if (!urb) { + err("init isoc: usb_alloc_urb ret. NULL"); + return -ENOMEM; + } + ov->sbuf[n].urb = urb; + urb->dev = ov->dev; + urb->context = &ov->sbuf[n]; + urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = ov->sbuf[n].data; + urb->complete = ov51x_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC; + urb->interval = 1; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = ov->packet_size * fx; + urb->iso_frame_desc[fx].length = ov->packet_size; + } + } + + ov->streaming = 1; + + for (n = 0; n < OV511_NUMSBUF; n++) { + ov->sbuf[n].urb->dev = ov->dev; + err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL); + if (err) { + err("init isoc: usb_submit_urb(%d) ret %d", n, err); + return err; + } + } + + return 0; +} + +static void +ov51x_unlink_isoc(struct usb_ov511 *ov) +{ + int n; + + /* Unschedule all of the iso td's */ + for (n = OV511_NUMSBUF - 1; n >= 0; n--) { + if (ov->sbuf[n].urb) { + usb_kill_urb(ov->sbuf[n].urb); + usb_free_urb(ov->sbuf[n].urb); + ov->sbuf[n].urb = NULL; + } + } +} + +static void +ov51x_stop_isoc(struct usb_ov511 *ov) +{ + if (!ov->streaming || !ov->dev) + return; + + PDEBUG(3, "*** Stopping capture ***"); + + if (ov->bclass == BCL_OV518) + ov518_set_packet_size(ov, 0); + else + ov511_set_packet_size(ov, 0); + + ov->streaming = 0; + + ov51x_unlink_isoc(ov); +} + +static int +ov51x_new_frame(struct usb_ov511 *ov, int framenum) +{ + struct ov511_frame *frame; + int newnum; + + PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum); + + if (!ov->dev) + return -1; + + /* If we're not grabbing a frame right now and the other frame is */ + /* ready to be grabbed into, then use it instead */ + if (ov->curframe == -1) { + newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES; + if (ov->frame[newnum].grabstate == FRAME_READY) + framenum = newnum; + } else + return 0; + + frame = &ov->frame[framenum]; + + PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum, + frame->width, frame->height); + + frame->grabstate = FRAME_GRABBING; + frame->scanstate = STATE_SCANNING; + frame->snapshot = 0; + + ov->curframe = framenum; + + /* Make sure it's not too big */ + if (frame->width > ov->maxwidth) + frame->width = ov->maxwidth; + + frame->width &= ~7L; /* Multiple of 8 */ + + if (frame->height > ov->maxheight) + frame->height = ov->maxheight; + + frame->height &= ~3L; /* Multiple of 4 */ + + return 0; +} + +/**************************************************************************** + * + * Buffer management + * + ***************************************************************************/ + +/* + * - You must acquire buf_lock before entering this function. + * - Because this code will free any non-null pointer, you must be sure to null + * them if you explicitly free them somewhere else! + */ +static void +ov51x_do_dealloc(struct usb_ov511 *ov) +{ + int i; + PDEBUG(4, "entered"); + + if (ov->fbuf) { + rvfree(ov->fbuf, OV511_NUMFRAMES + * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); + ov->fbuf = NULL; + } + + vfree(ov->rawfbuf); + ov->rawfbuf = NULL; + + vfree(ov->tempfbuf); + ov->tempfbuf = NULL; + + for (i = 0; i < OV511_NUMSBUF; i++) { + kfree(ov->sbuf[i].data); + ov->sbuf[i].data = NULL; + } + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].data = NULL; + ov->frame[i].rawdata = NULL; + ov->frame[i].tempdata = NULL; + if (ov->frame[i].compbuf) { + free_page((unsigned long) ov->frame[i].compbuf); + ov->frame[i].compbuf = NULL; + } + } + + PDEBUG(4, "buffer memory deallocated"); + ov->buf_state = BUF_NOT_ALLOCATED; + PDEBUG(4, "leaving"); +} + +static int +ov51x_alloc(struct usb_ov511 *ov) +{ + int i; + const int w = ov->maxwidth; + const int h = ov->maxheight; + const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h); + const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h); + + PDEBUG(4, "entered"); + down(&ov->buf_lock); + + if (ov->buf_state == BUF_ALLOCATED) + goto out; + + ov->fbuf = rvmalloc(data_bufsize); + if (!ov->fbuf) + goto error; + + ov->rawfbuf = vmalloc(raw_bufsize); + if (!ov->rawfbuf) + goto error; + + memset(ov->rawfbuf, 0, raw_bufsize); + + ov->tempfbuf = vmalloc(raw_bufsize); + if (!ov->tempfbuf) + goto error; + + memset(ov->tempfbuf, 0, raw_bufsize); + + for (i = 0; i < OV511_NUMSBUF; i++) { + ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC * + MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); + if (!ov->sbuf[i].data) + goto error; + + PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data); + } + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h); + ov->frame[i].rawdata = ov->rawfbuf + + i * MAX_RAW_DATA_SIZE(w, h); + ov->frame[i].tempdata = ov->tempfbuf + + i * MAX_RAW_DATA_SIZE(w, h); + + ov->frame[i].compbuf = + (unsigned char *) __get_free_page(GFP_KERNEL); + if (!ov->frame[i].compbuf) + goto error; + + PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data); + } + + ov->buf_state = BUF_ALLOCATED; +out: + up(&ov->buf_lock); + PDEBUG(4, "leaving"); + return 0; +error: + ov51x_do_dealloc(ov); + up(&ov->buf_lock); + PDEBUG(4, "errored"); + return -ENOMEM; +} + +static void +ov51x_dealloc(struct usb_ov511 *ov) +{ + PDEBUG(4, "entered"); + down(&ov->buf_lock); + ov51x_do_dealloc(ov); + up(&ov->buf_lock); + PDEBUG(4, "leaving"); +} + +/**************************************************************************** + * + * V4L 1 API + * + ***************************************************************************/ + +static int +ov51x_v4l1_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct usb_ov511 *ov = video_get_drvdata(vdev); + int err, i; + + PDEBUG(4, "opening"); + + down(&ov->lock); + + err = -EBUSY; + if (ov->user) + goto out; + + ov->sub_flag = 0; + + /* In case app doesn't set them... */ + err = ov51x_set_default_params(ov); + if (err < 0) + goto out; + + /* Make sure frames are reset */ + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].grabstate = FRAME_UNUSED; + ov->frame[i].bytes_read = 0; + } + + /* If compression is on, make sure now that a + * decompressor can be loaded */ + if (ov->compress && !ov->decomp_ops) { + err = request_decompressor(ov); + if (err && !dumppix) + goto out; + } + + err = ov51x_alloc(ov); + if (err < 0) + goto out; + + err = ov51x_init_isoc(ov); + if (err) { + ov51x_dealloc(ov); + goto out; + } + + ov->user++; + file->private_data = vdev; + + if (ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 1); + +out: + up(&ov->lock); + return err; +} + +static int +ov51x_v4l1_close(struct inode *inode, struct file *file) +{ + struct video_device *vdev = file->private_data; + struct usb_ov511 *ov = video_get_drvdata(vdev); + + PDEBUG(4, "ov511_close"); + + down(&ov->lock); + + ov->user--; + ov51x_stop_isoc(ov); + + release_decompressor(ov); + + if (ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 0); + + if (ov->dev) + ov51x_dealloc(ov); + + up(&ov->lock); + + /* Device unplugged while open. Only a minimum of unregistration is done + * here; the disconnect callback already did the rest. */ + if (!ov->dev) { + down(&ov->cbuf_lock); + kfree(ov->cbuf); + ov->cbuf = NULL; + up(&ov->cbuf_lock); + + ov51x_dealloc(ov); + kfree(ov); + ov = NULL; + } + + file->private_data = NULL; + return 0; +} + +/* Do not call this function directly! */ +static int +ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vdev = file->private_data; + struct usb_ov511 *ov = video_get_drvdata(vdev); + PDEBUG(5, "IOCtl: 0x%X", cmd); + + if (!ov->dev) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability *b = arg; + + PDEBUG(4, "VIDIOCGCAP"); + + memset(b, 0, sizeof(struct video_capability)); + sprintf(b->name, "%s USB Camera", + symbolic(brglist, ov->bridge)); + b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; + b->channels = ov->num_inputs; + b->audios = 0; + b->maxwidth = ov->maxwidth; + b->maxheight = ov->maxheight; + b->minwidth = ov->minwidth; + b->minheight = ov->minheight; + + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + PDEBUG(4, "VIDIOCGCHAN"); + + if ((unsigned)(v->channel) >= ov->num_inputs) { + err("Invalid channel (%d)", v->channel); + return -EINVAL; + } + + v->norm = ov->norm; + v->type = VIDEO_TYPE_CAMERA; + v->flags = 0; +// v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0; + v->tuners = 0; + decoder_get_input_name(ov, v->channel, v->name); + + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + int err; + + PDEBUG(4, "VIDIOCSCHAN"); + + /* Make sure it's not a camera */ + if (!ov->has_decoder) { + if (v->channel == 0) + return 0; + else + return -EINVAL; + } + + if (v->norm != VIDEO_MODE_PAL && + v->norm != VIDEO_MODE_NTSC && + v->norm != VIDEO_MODE_SECAM && + v->norm != VIDEO_MODE_AUTO) { + err("Invalid norm (%d)", v->norm); + return -EINVAL; + } + + if ((unsigned)(v->channel) >= ov->num_inputs) { + err("Invalid channel (%d)", v->channel); + return -EINVAL; + } + + err = decoder_set_input(ov, v->channel); + if (err) + return err; + + err = decoder_set_norm(ov, v->norm); + if (err) + return err; + + return 0; + } + case VIDIOCGPICT: + { + struct video_picture *p = arg; + + PDEBUG(4, "VIDIOCGPICT"); + + memset(p, 0, sizeof(struct video_picture)); + if (sensor_get_picture(ov, p)) + return -EIO; + + /* Can we get these from frame[0]? -claudio? */ + p->depth = ov->frame[0].depth; + p->palette = ov->frame[0].format; + + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *p = arg; + int i, rc; + + PDEBUG(4, "VIDIOCSPICT"); + + if (!get_depth(p->palette)) + return -EINVAL; + + if (sensor_set_picture(ov, p)) + return -EIO; + + if (force_palette && p->palette != force_palette) { + info("Palette rejected (%s)", + symbolic(v4l1_plist, p->palette)); + return -EINVAL; + } + + // FIXME: Format should be independent of frames + if (p->palette != ov->frame[0].format) { + PDEBUG(4, "Detected format change"); + + rc = ov51x_wait_frames_inactive(ov); + if (rc) + return rc; + + mode_init_regs(ov, ov->frame[0].width, + ov->frame[0].height, p->palette, ov->sub_flag); + } + + PDEBUG(4, "Setting depth=%d, palette=%s", + p->depth, symbolic(v4l1_plist, p->palette)); + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].depth = p->depth; + ov->frame[i].format = p->palette; + } + + return 0; + } + case VIDIOCGCAPTURE: + { + int *vf = arg; + + PDEBUG(4, "VIDIOCGCAPTURE"); + + ov->sub_flag = *vf; + return 0; + } + case VIDIOCSCAPTURE: + { + struct video_capture *vc = arg; + + PDEBUG(4, "VIDIOCSCAPTURE"); + + if (vc->flags) + return -EINVAL; + if (vc->decimation) + return -EINVAL; + + vc->x &= ~3L; + vc->y &= ~1L; + vc->y &= ~31L; + + if (vc->width == 0) + vc->width = 32; + + vc->height /= 16; + vc->height *= 16; + if (vc->height == 0) + vc->height = 16; + + ov->subx = vc->x; + ov->suby = vc->y; + ov->subw = vc->width; + ov->subh = vc->height; + + return 0; + } + case VIDIOCSWIN: + { + struct video_window *vw = arg; + int i, rc; + + PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height); + +#if 0 + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (vw->height != ov->maxheight) + return -EINVAL; + if (vw->width != ov->maxwidth) + return -EINVAL; +#endif + + rc = ov51x_wait_frames_inactive(ov); + if (rc) + return rc; + + rc = mode_init_regs(ov, vw->width, vw->height, + ov->frame[0].format, ov->sub_flag); + if (rc < 0) + return rc; + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].width = vw->width; + ov->frame[i].height = vw->height; + } + + return 0; + } + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + memset(vw, 0, sizeof(struct video_window)); + vw->x = 0; /* FIXME */ + vw->y = 0; + vw->width = ov->frame[0].width; + vw->height = ov->frame[0].height; + vw->flags = 30; + + PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height); + + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf *vm = arg; + int i; + + PDEBUG(4, "VIDIOCGMBUF"); + + memset(vm, 0, sizeof(struct video_mbuf)); + vm->size = OV511_NUMFRAMES + * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); + vm->frames = OV511_NUMFRAMES; + + vm->offsets[0] = 0; + for (i = 1; i < OV511_NUMFRAMES; i++) { + vm->offsets[i] = vm->offsets[i-1] + + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); + } + + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *vm = arg; + int rc, depth; + unsigned int f = vm->frame; + + PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width, + vm->height, symbolic(v4l1_plist, vm->format)); + + depth = get_depth(vm->format); + if (!depth) { + PDEBUG(2, "VIDIOCMCAPTURE: invalid format (%s)", + symbolic(v4l1_plist, vm->format)); + return -EINVAL; + } + + if (f >= OV511_NUMFRAMES) { + err("VIDIOCMCAPTURE: invalid frame (%d)", f); + return -EINVAL; + } + + if (vm->width > ov->maxwidth + || vm->height > ov->maxheight) { + err("VIDIOCMCAPTURE: requested dimensions too big"); + return -EINVAL; + } + + if (ov->frame[f].grabstate == FRAME_GRABBING) { + PDEBUG(4, "VIDIOCMCAPTURE: already grabbing"); + return -EBUSY; + } + + if (force_palette && (vm->format != force_palette)) { + PDEBUG(2, "palette rejected (%s)", + symbolic(v4l1_plist, vm->format)); + return -EINVAL; + } + + if ((ov->frame[f].width != vm->width) || + (ov->frame[f].height != vm->height) || + (ov->frame[f].format != vm->format) || + (ov->frame[f].sub_flag != ov->sub_flag) || + (ov->frame[f].depth != depth)) { + PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters"); + + rc = ov51x_wait_frames_inactive(ov); + if (rc) + return rc; + + rc = mode_init_regs(ov, vm->width, vm->height, + vm->format, ov->sub_flag); +#if 0 + if (rc < 0) { + PDEBUG(1, "Got error while initializing regs "); + return ret; + } +#endif + ov->frame[f].width = vm->width; + ov->frame[f].height = vm->height; + ov->frame[f].format = vm->format; + ov->frame[f].sub_flag = ov->sub_flag; + ov->frame[f].depth = depth; + } + + /* Mark it as ready */ + ov->frame[f].grabstate = FRAME_READY; + + PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f); + + return ov51x_new_frame(ov, f); + } + case VIDIOCSYNC: + { + unsigned int fnum = *((unsigned int *) arg); + struct ov511_frame *frame; + int rc; + + if (fnum >= OV511_NUMFRAMES) { + err("VIDIOCSYNC: invalid frame (%d)", fnum); + return -EINVAL; + } + + frame = &ov->frame[fnum]; + + PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum, + frame->grabstate); + + switch (frame->grabstate) { + case FRAME_UNUSED: + return -EINVAL; + case FRAME_READY: + case FRAME_GRABBING: + case FRAME_ERROR: +redo: + if (!ov->dev) + return -EIO; + + rc = wait_event_interruptible(frame->wq, + (frame->grabstate == FRAME_DONE) + || (frame->grabstate == FRAME_ERROR)); + + if (rc) + return rc; + + if (frame->grabstate == FRAME_ERROR) { + if ((rc = ov51x_new_frame(ov, fnum)) < 0) + return rc; + goto redo; + } + /* Fall through */ + case FRAME_DONE: + if (ov->snap_enabled && !frame->snapshot) { + if ((rc = ov51x_new_frame(ov, fnum)) < 0) + return rc; + goto redo; + } + + frame->grabstate = FRAME_UNUSED; + + /* Reset the hardware snapshot button */ + /* FIXME - Is this the best place for this? */ + if ((ov->snap_enabled) && (frame->snapshot)) { + frame->snapshot = 0; + ov51x_clear_snapshot(ov); + } + + /* Decompression, format conversion, etc... */ + ov51x_postprocess(ov, frame); + + break; + } /* end switch */ + + return 0; + } + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + PDEBUG(4, "VIDIOCGFBUF"); + + memset(vb, 0, sizeof(struct video_buffer)); + + return 0; + } + case VIDIOCGUNIT: + { + struct video_unit *vu = arg; + + PDEBUG(4, "VIDIOCGUNIT"); + + memset(vu, 0, sizeof(struct video_unit)); + + vu->video = ov->vdev->minor; + vu->vbi = VIDEO_NO_UNIT; + vu->radio = VIDEO_NO_UNIT; + vu->audio = VIDEO_NO_UNIT; + vu->teletext = VIDEO_NO_UNIT; + + return 0; + } + case OV511IOC_WI2C: + { + struct ov511_i2c_struct *w = arg; + + return i2c_w_slave(ov, w->slave, w->reg, w->value, w->mask); + } + case OV511IOC_RI2C: + { + struct ov511_i2c_struct *r = arg; + int rc; + + rc = i2c_r_slave(ov, r->slave, r->reg); + if (rc < 0) + return rc; + + r->value = rc; + return 0; + } + default: + PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd); + return -ENOIOCTLCMD; + } /* end switch */ + + return 0; +} + +static int +ov51x_v4l1_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct video_device *vdev = file->private_data; + struct usb_ov511 *ov = video_get_drvdata(vdev); + int rc; + + if (down_interruptible(&ov->lock)) + return -EINTR; + + rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal); + + up(&ov->lock); + return rc; +} + +static ssize_t +ov51x_v4l1_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos) +{ + struct video_device *vdev = file->private_data; + int noblock = file->f_flags&O_NONBLOCK; + unsigned long count = cnt; + struct usb_ov511 *ov = video_get_drvdata(vdev); + int i, rc = 0, frmx = -1; + struct ov511_frame *frame; + + if (down_interruptible(&ov->lock)) + return -EINTR; + + PDEBUG(4, "%ld bytes, noblock=%d", count, noblock); + + if (!vdev || !buf) { + rc = -EFAULT; + goto error; + } + + if (!ov->dev) { + rc = -EIO; + goto error; + } + +// FIXME: Only supports two frames + /* See if a frame is completed, then use it. */ + if (ov->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */ + frmx = 0; + else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */ + frmx = 1; + + /* If nonblocking we return immediately */ + if (noblock && (frmx == -1)) { + rc = -EAGAIN; + goto error; + } + + /* If no FRAME_DONE, look for a FRAME_GRABBING state. */ + /* See if a frame is in process (grabbing), then use it. */ + if (frmx == -1) { + if (ov->frame[0].grabstate == FRAME_GRABBING) + frmx = 0; + else if (ov->frame[1].grabstate == FRAME_GRABBING) + frmx = 1; + } + + /* If no frame is active, start one. */ + if (frmx == -1) { + if ((rc = ov51x_new_frame(ov, frmx = 0))) { + err("read: ov51x_new_frame error"); + goto error; + } + } + + frame = &ov->frame[frmx]; + +restart: + if (!ov->dev) { + rc = -EIO; + goto error; + } + + /* Wait while we're grabbing the image */ + PDEBUG(4, "Waiting image grabbing"); + rc = wait_event_interruptible(frame->wq, + (frame->grabstate == FRAME_DONE) + || (frame->grabstate == FRAME_ERROR)); + + if (rc) + goto error; + + PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate); + PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd); + + if (frame->grabstate == FRAME_ERROR) { + frame->bytes_read = 0; + err("** ick! ** Errored frame %d", ov->curframe); + if (ov51x_new_frame(ov, frmx)) { + err("read: ov51x_new_frame error"); + goto error; + } + goto restart; + } + + + /* Repeat until we get a snapshot frame */ + if (ov->snap_enabled) + PDEBUG(4, "Waiting snapshot frame"); + if (ov->snap_enabled && !frame->snapshot) { + frame->bytes_read = 0; + if ((rc = ov51x_new_frame(ov, frmx))) { + err("read: ov51x_new_frame error"); + goto error; + } + goto restart; + } + + /* Clear the snapshot */ + if (ov->snap_enabled && frame->snapshot) { + frame->snapshot = 0; + ov51x_clear_snapshot(ov); + } + + /* Decompression, format conversion, etc... */ + ov51x_postprocess(ov, frame); + + PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx, + frame->bytes_read, + get_frame_length(frame)); + + /* copy bytes to user space; we allow for partials reads */ +// if ((count + frame->bytes_read) +// > get_frame_length((struct ov511_frame *)frame)) +// count = frame->scanlength - frame->bytes_read; + + /* FIXME - count hardwired to be one frame... */ + count = get_frame_length(frame); + + PDEBUG(4, "Copy to user space: %ld bytes", count); + if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) { + PDEBUG(4, "Copy failed! %d bytes not copied", i); + rc = -EFAULT; + goto error; + } + + frame->bytes_read += count; + PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld", + count, frame->bytes_read); + + /* If all data have been read... */ + if (frame->bytes_read + >= get_frame_length(frame)) { + frame->bytes_read = 0; + +// FIXME: Only supports two frames + /* Mark it as available to be used again. */ + ov->frame[frmx].grabstate = FRAME_UNUSED; + if ((rc = ov51x_new_frame(ov, !frmx))) { + err("ov51x_new_frame returned error"); + goto error; + } + } + + PDEBUG(4, "read finished, returning %ld (sweet)", count); + + up(&ov->lock); + return count; + +error: + up(&ov->lock); + return rc; +} + +static int +ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = file->private_data; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; + struct usb_ov511 *ov = video_get_drvdata(vdev); + unsigned long page, pos; + + if (ov->dev == NULL) + return -EIO; + + PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); + + if (size > (((OV511_NUMFRAMES + * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight) + + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) + return -EINVAL; + + if (down_interruptible(&ov->lock)) + return -EINTR; + + pos = (unsigned long)ov->fbuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + up(&ov->lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + up(&ov->lock); + return 0; +} + +static struct file_operations ov511_fops = { + .owner = THIS_MODULE, + .open = ov51x_v4l1_open, + .release = ov51x_v4l1_close, + .read = ov51x_v4l1_read, + .mmap = ov51x_v4l1_mmap, + .ioctl = ov51x_v4l1_ioctl, + .llseek = no_llseek, +}; + +static struct video_device vdev_template = { + .name = "OV511 USB Camera", + .fops = &ov511_fops, + .release = video_device_release, + .minor = -1, +}; + +/**************************************************************************** + * + * OV511 and sensor configuration + * + ***************************************************************************/ + +/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses + * the same register settings as the OV7610, since they are very similar. + */ +static int +ov7xx0_configure(struct usb_ov511 *ov) +{ + int i, success; + int rc; + + /* Lawrence Glaister reports: + * + * Register 0x0f in the 7610 has the following effects: + * + * 0x85 (AEC method 1): Best overall, good contrast range + * 0x45 (AEC method 2): Very overexposed + * 0xa5 (spec sheet default): Ok, but the black level is + * shifted resulting in loss of contrast + * 0x05 (old driver setting): very overexposed, too much + * contrast + */ + static struct ov511_regvals aRegvalsNorm7610[] = { + { OV511_I2C_BUS, 0x10, 0xff }, + { OV511_I2C_BUS, 0x16, 0x06 }, + { OV511_I2C_BUS, 0x28, 0x24 }, + { OV511_I2C_BUS, 0x2b, 0xac }, + { OV511_I2C_BUS, 0x12, 0x00 }, + { OV511_I2C_BUS, 0x38, 0x81 }, + { OV511_I2C_BUS, 0x28, 0x24 }, /* 0c */ + { OV511_I2C_BUS, 0x0f, 0x85 }, /* lg's setting */ + { OV511_I2C_BUS, 0x15, 0x01 }, + { OV511_I2C_BUS, 0x20, 0x1c }, + { OV511_I2C_BUS, 0x23, 0x2a }, + { OV511_I2C_BUS, 0x24, 0x10 }, + { OV511_I2C_BUS, 0x25, 0x8a }, + { OV511_I2C_BUS, 0x26, 0xa2 }, + { OV511_I2C_BUS, 0x27, 0xc2 }, + { OV511_I2C_BUS, 0x2a, 0x04 }, + { OV511_I2C_BUS, 0x2c, 0xfe }, + { OV511_I2C_BUS, 0x2d, 0x93 }, + { OV511_I2C_BUS, 0x30, 0x71 }, + { OV511_I2C_BUS, 0x31, 0x60 }, + { OV511_I2C_BUS, 0x32, 0x26 }, + { OV511_I2C_BUS, 0x33, 0x20 }, + { OV511_I2C_BUS, 0x34, 0x48 }, + { OV511_I2C_BUS, 0x12, 0x24 }, + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + static struct ov511_regvals aRegvalsNorm7620[] = { + { OV511_I2C_BUS, 0x00, 0x00 }, + { OV511_I2C_BUS, 0x01, 0x80 }, + { OV511_I2C_BUS, 0x02, 0x80 }, + { OV511_I2C_BUS, 0x03, 0xc0 }, + { OV511_I2C_BUS, 0x06, 0x60 }, + { OV511_I2C_BUS, 0x07, 0x00 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x12, 0x24 }, + { OV511_I2C_BUS, 0x13, 0x01 }, + { OV511_I2C_BUS, 0x14, 0x84 }, + { OV511_I2C_BUS, 0x15, 0x01 }, + { OV511_I2C_BUS, 0x16, 0x03 }, + { OV511_I2C_BUS, 0x17, 0x2f }, + { OV511_I2C_BUS, 0x18, 0xcf }, + { OV511_I2C_BUS, 0x19, 0x06 }, + { OV511_I2C_BUS, 0x1a, 0xf5 }, + { OV511_I2C_BUS, 0x1b, 0x00 }, + { OV511_I2C_BUS, 0x20, 0x18 }, + { OV511_I2C_BUS, 0x21, 0x80 }, + { OV511_I2C_BUS, 0x22, 0x80 }, + { OV511_I2C_BUS, 0x23, 0x00 }, + { OV511_I2C_BUS, 0x26, 0xa2 }, + { OV511_I2C_BUS, 0x27, 0xea }, + { OV511_I2C_BUS, 0x28, 0x20 }, + { OV511_I2C_BUS, 0x29, 0x00 }, + { OV511_I2C_BUS, 0x2a, 0x10 }, + { OV511_I2C_BUS, 0x2b, 0x00 }, + { OV511_I2C_BUS, 0x2c, 0x88 }, + { OV511_I2C_BUS, 0x2d, 0x91 }, + { OV511_I2C_BUS, 0x2e, 0x80 }, + { OV511_I2C_BUS, 0x2f, 0x44 }, + { OV511_I2C_BUS, 0x60, 0x27 }, + { OV511_I2C_BUS, 0x61, 0x02 }, + { OV511_I2C_BUS, 0x62, 0x5f }, + { OV511_I2C_BUS, 0x63, 0xd5 }, + { OV511_I2C_BUS, 0x64, 0x57 }, + { OV511_I2C_BUS, 0x65, 0x83 }, + { OV511_I2C_BUS, 0x66, 0x55 }, + { OV511_I2C_BUS, 0x67, 0x92 }, + { OV511_I2C_BUS, 0x68, 0xcf }, + { OV511_I2C_BUS, 0x69, 0x76 }, + { OV511_I2C_BUS, 0x6a, 0x22 }, + { OV511_I2C_BUS, 0x6b, 0x00 }, + { OV511_I2C_BUS, 0x6c, 0x02 }, + { OV511_I2C_BUS, 0x6d, 0x44 }, + { OV511_I2C_BUS, 0x6e, 0x80 }, + { OV511_I2C_BUS, 0x6f, 0x1d }, + { OV511_I2C_BUS, 0x70, 0x8b }, + { OV511_I2C_BUS, 0x71, 0x00 }, + { OV511_I2C_BUS, 0x72, 0x14 }, + { OV511_I2C_BUS, 0x73, 0x54 }, + { OV511_I2C_BUS, 0x74, 0x00 }, + { OV511_I2C_BUS, 0x75, 0x8e }, + { OV511_I2C_BUS, 0x76, 0x00 }, + { OV511_I2C_BUS, 0x77, 0xff }, + { OV511_I2C_BUS, 0x78, 0x80 }, + { OV511_I2C_BUS, 0x79, 0x80 }, + { OV511_I2C_BUS, 0x7a, 0x80 }, + { OV511_I2C_BUS, 0x7b, 0xe2 }, + { OV511_I2C_BUS, 0x7c, 0x00 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + PDEBUG(4, "starting configuration"); + + /* This looks redundant, but is necessary for WebCam 3 */ + ov->primary_i2c_slave = OV7xx0_SID; + if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) + return -1; + + if (init_ov_sensor(ov) >= 0) { + PDEBUG(1, "OV7xx0 sensor initalized (method 1)"); + } else { + /* Reset the 76xx */ + if (i2c_w(ov, 0x12, 0x80) < 0) + return -1; + + /* Wait for it to initialize */ + msleep(150); + + i = 0; + success = 0; + while (i <= i2c_detect_tries) { + if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && + (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { + success = 1; + break; + } else { + i++; + } + } + +// Was (i == i2c_detect_tries) previously. This obviously used to always report +// success. Whether anyone actually depended on that bug is unknown + if ((i >= i2c_detect_tries) && (success == 0)) { + err("Failed to read sensor ID. You might not have an"); + err("OV7610/20, or it may be not responding. Report"); + err("this to " EMAIL); + err("This is only a warning. You can attempt to use"); + err("your camera anyway"); +// Only issue a warning for now +// return -1; + } else { + PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1); + } + } + + /* Detect sensor (sub)type */ + rc = i2c_r(ov, OV7610_REG_COM_I); + + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } else if ((rc & 3) == 3) { + info("Sensor is an OV7610"); + ov->sensor = SEN_OV7610; + } else if ((rc & 3) == 1) { + /* I don't know what's different about the 76BE yet. */ + if (i2c_r(ov, 0x15) & 1) + info("Sensor is an OV7620AE"); + else + info("Sensor is an OV76BE"); + + /* OV511+ will return all zero isoc data unless we + * configure the sensor as a 7620. Someone needs to + * find the exact reg. setting that causes this. */ + if (ov->bridge == BRG_OV511PLUS) { + info("Enabling 511+/7620AE workaround"); + ov->sensor = SEN_OV7620; + } else { + ov->sensor = SEN_OV76BE; + } + } else if ((rc & 3) == 0) { + info("Sensor is an OV7620"); + ov->sensor = SEN_OV7620; + } else { + err("Unknown image sensor version: %d", rc & 3); + return -1; + } + + if (ov->sensor == SEN_OV7620) { + PDEBUG(4, "Writing 7620 registers"); + if (write_regvals(ov, aRegvalsNorm7620)) + return -1; + } else { + PDEBUG(4, "Writing 7610 registers"); + if (write_regvals(ov, aRegvalsNorm7610)) + return -1; + } + + /* Set sensor-specific vars */ + ov->maxwidth = 640; + ov->maxheight = 480; + ov->minwidth = 64; + ov->minheight = 48; + + // FIXME: These do not match the actual settings yet + ov->brightness = 0x80 << 8; + ov->contrast = 0x80 << 8; + ov->colour = 0x80 << 8; + ov->hue = 0x80 << 8; + + return 0; +} + +/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ +static int +ov6xx0_configure(struct usb_ov511 *ov) +{ + int rc; + + static struct ov511_regvals aRegvalsNorm6x20[] = { + { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x03, 0x60 }, + { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ + { OV511_I2C_BUS, 0x07, 0xa8 }, + /* The ratio of 0x0c and 0x0d controls the white point */ + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_I2C_BUS, 0x0f, 0x15 }, /* COMS */ + { OV511_I2C_BUS, 0x10, 0x75 }, /* AEC Exposure time */ + { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */ + { OV511_I2C_BUS, 0x14, 0x04 }, + /* 0x16: 0x06 helps frame stability with moving objects */ + { OV511_I2C_BUS, 0x16, 0x06 }, +// { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ + { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ + /* 0x28: 0x05 Selects RGB format if RGB on */ + { OV511_I2C_BUS, 0x28, 0x05 }, + { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ +// { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ + { OV511_I2C_BUS, 0x2d, 0x99 }, + { OV511_I2C_BUS, 0x33, 0xa0 }, /* Color Processing Parameter */ + { OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */ + { OV511_I2C_BUS, 0x38, 0x8b }, + { OV511_I2C_BUS, 0x39, 0x40 }, + + { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ + { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ + { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ + + { OV511_I2C_BUS, 0x3d, 0x80 }, + /* These next two registers (0x4a, 0x4b) are undocumented. They + * control the color balance */ + { OV511_I2C_BUS, 0x4a, 0x80 }, + { OV511_I2C_BUS, 0x4b, 0x80 }, + { OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */ + { OV511_I2C_BUS, 0x4e, 0xc1 }, + { OV511_I2C_BUS, 0x4f, 0x04 }, +// Do 50-53 have any effect? +// Toggle 0x12[2] off and on here? + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ + }; + + static struct ov511_regvals aRegvalsNorm6x30[] = { + /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ + { OV511_I2C_BUS, 0x11, 0x00 }, + /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 }, + /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ + { OV511_I2C_BUS, 0x07, 0xa8 }, + /* The ratio of 0x0c and 0x0d controls the white point */ + /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 }, + /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 }, + /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 }, +// /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 }, + { OV511_I2C_BUS, 0x16, 0x03 }, +// /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ + // 21 & 22? The suggested values look wrong. Go with default + /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 }, + /*A*/ { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default +// /*OK*/ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ + + /* 0x28: 0x05 Selects RGB format if RGB on */ +// /*04?*/ { OV511_I2C_BUS, 0x28, 0x05 }, +// /*04?*/ { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus + + /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ +// /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ + { OV511_I2C_BUS, 0x2d, 0x99 }, +// /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620 +// /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */ +// /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 }, +// /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7 +// { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ +// { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ +// { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ + { OV511_I2C_BUS, 0x3d, 0x80 }, +// /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e }, + + /* These next two registers (0x4a, 0x4b) are undocumented. They + * control the color balance */ +// /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these +// /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 }, + { OV511_I2C_BUS, 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ + /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 }, + + /* UV average mode, color killer: strongest */ + { OV511_I2C_BUS, 0x4f, 0x07 }, + + { OV511_I2C_BUS, 0x54, 0x23 }, /* Max AGC gain: 18dB */ + { OV511_I2C_BUS, 0x57, 0x81 }, /* (default) */ + { OV511_I2C_BUS, 0x59, 0x01 }, /* AGC dark current comp: +1 */ + { OV511_I2C_BUS, 0x5a, 0x2c }, /* (undocumented) */ + { OV511_I2C_BUS, 0x5b, 0x0f }, /* AWB chrominance levels */ +// { OV511_I2C_BUS, 0x5c, 0x10 }, + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ + }; + + PDEBUG(4, "starting sensor configuration"); + + if (init_ov_sensor(ov) < 0) { + err("Failed to read sensor ID. You might not have an OV6xx0,"); + err("or it may be not responding. Report this to " EMAIL); + return -1; + } else { + PDEBUG(1, "OV6xx0 sensor detected"); + } + + /* Detect sensor (sub)type */ + rc = i2c_r(ov, OV7610_REG_COM_I); + + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } + + if ((rc & 3) == 0) { + ov->sensor = SEN_OV6630; + info("Sensor is an OV6630"); + } else if ((rc & 3) == 1) { + ov->sensor = SEN_OV6620; + info("Sensor is an OV6620"); + } else if ((rc & 3) == 2) { + ov->sensor = SEN_OV6630; + info("Sensor is an OV6630AE"); + } else if ((rc & 3) == 3) { + ov->sensor = SEN_OV6630; + info("Sensor is an OV6630AF"); + } + + /* Set sensor-specific vars */ + ov->maxwidth = 352; + ov->maxheight = 288; + ov->minwidth = 64; + ov->minheight = 48; + + // FIXME: These do not match the actual settings yet + ov->brightness = 0x80 << 8; + ov->contrast = 0x80 << 8; + ov->colour = 0x80 << 8; + ov->hue = 0x80 << 8; + + if (ov->sensor == SEN_OV6620) { + PDEBUG(4, "Writing 6x20 registers"); + if (write_regvals(ov, aRegvalsNorm6x20)) + return -1; + } else { + PDEBUG(4, "Writing 6x30 registers"); + if (write_regvals(ov, aRegvalsNorm6x30)) + return -1; + } + + return 0; +} + +/* This initializes the KS0127 and KS0127B video decoders. */ +static int +ks0127_configure(struct usb_ov511 *ov) +{ + int rc; + +// FIXME: I don't know how to sync or reset it yet +#if 0 + if (ov51x_init_ks_sensor(ov) < 0) { + err("Failed to initialize the KS0127"); + return -1; + } else { + PDEBUG(1, "KS012x(B) sensor detected"); + } +#endif + + /* Detect decoder subtype */ + rc = i2c_r(ov, 0x00); + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } else if (rc & 0x08) { + rc = i2c_r(ov, 0x3d); + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } else if ((rc & 0x0f) == 0) { + info("Sensor is a KS0127"); + ov->sensor = SEN_KS0127; + } else if ((rc & 0x0f) == 9) { + info("Sensor is a KS0127B Rev. A"); + ov->sensor = SEN_KS0127B; + } + } else { + err("Error: Sensor is an unsupported KS0122"); + return -1; + } + + /* Set sensor-specific vars */ + ov->maxwidth = 640; + ov->maxheight = 480; + ov->minwidth = 64; + ov->minheight = 48; + + // FIXME: These do not match the actual settings yet + ov->brightness = 0x80 << 8; + ov->contrast = 0x80 << 8; + ov->colour = 0x80 << 8; + ov->hue = 0x80 << 8; + + /* This device is not supported yet. Bail out now... */ + err("This sensor is not supported yet."); + return -1; + + return 0; +} + +/* This initializes the SAA7111A video decoder. */ +static int +saa7111a_configure(struct usb_ov511 *ov) +{ + int rc; + + /* Since there is no register reset command, all registers must be + * written, otherwise gives erratic results */ + static struct ov511_regvals aRegvalsNormSAA7111A[] = { + { OV511_I2C_BUS, 0x06, 0xce }, + { OV511_I2C_BUS, 0x07, 0x00 }, + { OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */ + { OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */ + { OV511_I2C_BUS, 0x00, 0x00 }, + { OV511_I2C_BUS, 0x01, 0x00 }, + { OV511_I2C_BUS, 0x03, 0x23 }, + { OV511_I2C_BUS, 0x04, 0x00 }, + { OV511_I2C_BUS, 0x05, 0x00 }, + { OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */ + { OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */ + { OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */ + { OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */ + { OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */ + { OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */ + { OV511_I2C_BUS, 0x0f, 0x00 }, + { OV511_I2C_BUS, 0x11, 0x0c }, + { OV511_I2C_BUS, 0x12, 0x00 }, + { OV511_I2C_BUS, 0x13, 0x00 }, + { OV511_I2C_BUS, 0x14, 0x00 }, + { OV511_I2C_BUS, 0x15, 0x00 }, + { OV511_I2C_BUS, 0x16, 0x00 }, + { OV511_I2C_BUS, 0x17, 0x00 }, + { OV511_I2C_BUS, 0x02, 0xc0 }, /* Composite input 0 */ + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + +// FIXME: I don't know how to sync or reset it yet +#if 0 + if (ov51x_init_saa_sensor(ov) < 0) { + err("Failed to initialize the SAA7111A"); + return -1; + } else { + PDEBUG(1, "SAA7111A sensor detected"); + } +#endif + + /* 640x480 not supported with PAL */ + if (ov->pal) { + ov->maxwidth = 320; + ov->maxheight = 240; /* Even field only */ + } else { + ov->maxwidth = 640; + ov->maxheight = 480; /* Even/Odd fields */ + } + + ov->minwidth = 320; + ov->minheight = 240; /* Even field only */ + + ov->has_decoder = 1; + ov->num_inputs = 8; + ov->norm = VIDEO_MODE_AUTO; + ov->stop_during_set = 0; /* Decoder guarantees stable image */ + + /* Decoder doesn't change these values, so we use these instead of + * acutally reading the registers (which doesn't work) */ + ov->brightness = 0x80 << 8; + ov->contrast = 0x40 << 9; + ov->colour = 0x40 << 9; + ov->hue = 32768; + + PDEBUG(4, "Writing SAA7111A registers"); + if (write_regvals(ov, aRegvalsNormSAA7111A)) + return -1; + + /* Detect version of decoder. This must be done after writing the + * initial regs or the decoder will lock up. */ + rc = i2c_r(ov, 0x00); + + if (rc < 0) { + err("Error detecting sensor version"); + return -1; + } else { + info("Sensor is an SAA7111A (version 0x%x)", rc); + ov->sensor = SEN_SAA7111A; + } + + // FIXME: Fix this for OV518(+) + /* Latch to negative edge of clock. Otherwise, we get incorrect + * colors and jitter in the digital signal. */ + if (ov->bclass == BCL_OV511) + reg_w(ov, 0x11, 0x00); + else + warn("SAA7111A not yet supported with OV518/OV518+"); + + return 0; +} + +/* This initializes the OV511/OV511+ and the sensor */ +static int +ov511_configure(struct usb_ov511 *ov) +{ + static struct ov511_regvals aRegvalsInit511[] = { + { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, + { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, + { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x3f }, + { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x3d }, + { OV511_DONE_BUS, 0x0, 0x00}, + }; + + static struct ov511_regvals aRegvalsNorm511[] = { + { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R511_FIFO_OPTS, 0x1f }, + { OV511_REG_BUS, R511_COMP_EN, 0x00 }, + { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + static struct ov511_regvals aRegvalsNorm511Plus[] = { + { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0xff }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R511_FIFO_OPTS, 0xff }, + { OV511_REG_BUS, R511_COMP_EN, 0x00 }, + { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + PDEBUG(4, ""); + + ov->customid = reg_r(ov, R511_SYS_CUST_ID); + if (ov->customid < 0) { + err("Unable to read camera bridge registers"); + goto error; + } + + PDEBUG (1, "CustomID = %d", ov->customid); + ov->desc = symbolic(camlist, ov->customid); + info("model: %s", ov->desc); + + if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { + err("Camera type (%d) not recognized", ov->customid); + err("Please notify " EMAIL " of the name,"); + err("manufacturer, model, and this number of your camera."); + err("Also include the output of the detection process."); + } + + if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */ + ov->pal = 1; + + if (write_regvals(ov, aRegvalsInit511)) + goto error; + + if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 0); + + /* The OV511+ has undocumented bits in the flow control register. + * Setting it to 0xff fixes the corruption with moving objects. */ + if (ov->bridge == BRG_OV511) { + if (write_regvals(ov, aRegvalsNorm511)) + goto error; + } else if (ov->bridge == BRG_OV511PLUS) { + if (write_regvals(ov, aRegvalsNorm511Plus)) + goto error; + } else { + err("Invalid bridge"); + } + + if (ov511_init_compression(ov)) + goto error; + + ov->packet_numbering = 1; + ov511_set_packet_size(ov, 0); + + ov->snap_enabled = snapshot; + + /* Test for 7xx0 */ + PDEBUG(3, "Testing for 0V7xx0"); + ov->primary_i2c_slave = OV7xx0_SID; + if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) + goto error; + + if (i2c_w(ov, 0x12, 0x80) < 0) { + /* Test for 6xx0 */ + PDEBUG(3, "Testing for 0V6xx0"); + ov->primary_i2c_slave = OV6xx0_SID; + if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) + goto error; + + if (i2c_w(ov, 0x12, 0x80) < 0) { + /* Test for 8xx0 */ + PDEBUG(3, "Testing for 0V8xx0"); + ov->primary_i2c_slave = OV8xx0_SID; + if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) + goto error; + + if (i2c_w(ov, 0x12, 0x80) < 0) { + /* Test for SAA7111A */ + PDEBUG(3, "Testing for SAA7111A"); + ov->primary_i2c_slave = SAA7111A_SID; + if (ov51x_set_slave_ids(ov, SAA7111A_SID) < 0) + goto error; + + if (i2c_w(ov, 0x0d, 0x00) < 0) { + /* Test for KS0127 */ + PDEBUG(3, "Testing for KS0127"); + ov->primary_i2c_slave = KS0127_SID; + if (ov51x_set_slave_ids(ov, KS0127_SID) < 0) + goto error; + + if (i2c_w(ov, 0x10, 0x00) < 0) { + err("Can't determine sensor slave IDs"); + goto error; + } else { + if (ks0127_configure(ov) < 0) { + err("Failed to configure KS0127"); + goto error; + } + } + } else { + if (saa7111a_configure(ov) < 0) { + err("Failed to configure SAA7111A"); + goto error; + } + } + } else { + err("Detected unsupported OV8xx0 sensor"); + goto error; + } + } else { + if (ov6xx0_configure(ov) < 0) { + err("Failed to configure OV6xx0"); + goto error; + } + } + } else { + if (ov7xx0_configure(ov) < 0) { + err("Failed to configure OV7xx0"); + goto error; + } + } + + return 0; + +error: + err("OV511 Config failed"); + + return -EBUSY; +} + +/* This initializes the OV518/OV518+ and the sensor */ +static int +ov518_configure(struct usb_ov511 *ov) +{ + /* For 518 and 518+ */ + static struct ov511_regvals aRegvalsInit518[] = { + { OV511_REG_BUS, R51x_SYS_RESET, 0x40 }, + { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x3e }, + { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x00 }, + { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, + { OV511_REG_BUS, 0x46, 0x00 }, + { OV511_REG_BUS, 0x5d, 0x03 }, + { OV511_DONE_BUS, 0x0, 0x00}, + }; + + static struct ov511_regvals aRegvalsNorm518[] = { + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ + { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ + { OV511_REG_BUS, 0x31, 0x0f }, + { OV511_REG_BUS, 0x5d, 0x03 }, + { OV511_REG_BUS, 0x24, 0x9f }, + { OV511_REG_BUS, 0x25, 0x90 }, + { OV511_REG_BUS, 0x20, 0x00 }, + { OV511_REG_BUS, 0x51, 0x04 }, + { OV511_REG_BUS, 0x71, 0x19 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + static struct ov511_regvals aRegvalsNorm518Plus[] = { + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ + { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ + { OV511_REG_BUS, 0x31, 0x0f }, + { OV511_REG_BUS, 0x5d, 0x03 }, + { OV511_REG_BUS, 0x24, 0x9f }, + { OV511_REG_BUS, 0x25, 0x90 }, + { OV511_REG_BUS, 0x20, 0x60 }, + { OV511_REG_BUS, 0x51, 0x02 }, + { OV511_REG_BUS, 0x71, 0x19 }, + { OV511_REG_BUS, 0x40, 0xff }, + { OV511_REG_BUS, 0x41, 0x42 }, + { OV511_REG_BUS, 0x46, 0x00 }, + { OV511_REG_BUS, 0x33, 0x04 }, + { OV511_REG_BUS, 0x21, 0x19 }, + { OV511_REG_BUS, 0x3f, 0x10 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + PDEBUG(4, ""); + + /* First 5 bits of custom ID reg are a revision ID on OV518 */ + info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID)); + + /* Give it the default description */ + ov->desc = symbolic(camlist, 0); + + if (write_regvals(ov, aRegvalsInit518)) + goto error; + + /* Set LED GPIO pin to output mode */ + if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) + goto error; + + /* LED is off by default with OV518; have to explicitly turn it on */ + if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 0); + else + ov51x_led_control(ov, 1); + + /* Don't require compression if dumppix is enabled; otherwise it's + * required. OV518 has no uncompressed mode, to save RAM. */ + if (!dumppix && !ov->compress) { + ov->compress = 1; + warn("Compression required with OV518...enabling"); + } + + if (ov->bridge == BRG_OV518) { + if (write_regvals(ov, aRegvalsNorm518)) + goto error; + } else if (ov->bridge == BRG_OV518PLUS) { + if (write_regvals(ov, aRegvalsNorm518Plus)) + goto error; + } else { + err("Invalid bridge"); + } + + if (reg_w(ov, 0x2f, 0x80) < 0) + goto error; + + if (ov518_init_compression(ov)) + goto error; + + if (ov->bridge == BRG_OV518) + { + struct usb_interface *ifp; + struct usb_host_interface *alt; + __u16 mxps = 0; + + ifp = usb_ifnum_to_if(ov->dev, 0); + if (ifp) { + alt = usb_altnum_to_altsetting(ifp, 7); + if (alt) + mxps = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + } + + /* Some OV518s have packet numbering by default, some don't */ + if (mxps == 897) + ov->packet_numbering = 1; + else + ov->packet_numbering = 0; + } else { + /* OV518+ has packet numbering turned on by default */ + ov->packet_numbering = 1; + } + + ov518_set_packet_size(ov, 0); + + ov->snap_enabled = snapshot; + + /* Test for 76xx */ + ov->primary_i2c_slave = OV7xx0_SID; + if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) + goto error; + + /* The OV518 must be more aggressive about sensor detection since + * I2C write will never fail if the sensor is not present. We have + * to try to initialize the sensor to detect its presence */ + + if (init_ov_sensor(ov) < 0) { + /* Test for 6xx0 */ + ov->primary_i2c_slave = OV6xx0_SID; + if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) + goto error; + + if (init_ov_sensor(ov) < 0) { + /* Test for 8xx0 */ + ov->primary_i2c_slave = OV8xx0_SID; + if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) + goto error; + + if (init_ov_sensor(ov) < 0) { + err("Can't determine sensor slave IDs"); + goto error; + } else { + err("Detected unsupported OV8xx0 sensor"); + goto error; + } + } else { + if (ov6xx0_configure(ov) < 0) { + err("Failed to configure OV6xx0"); + goto error; + } + } + } else { + if (ov7xx0_configure(ov) < 0) { + err("Failed to configure OV7xx0"); + goto error; + } + } + + ov->maxwidth = 352; + ov->maxheight = 288; + + // The OV518 cannot go as low as the sensor can + ov->minwidth = 160; + ov->minheight = 120; + + return 0; + +error: + err("OV518 Config failed"); + + return -EBUSY; +} + +/**************************************************************************** + * sysfs + ***************************************************************************/ + +static inline struct usb_ov511 *cd_to_ov(struct device *cd) +{ + struct video_device *vdev = to_video_device(cd); + return video_get_drvdata(vdev); +} + +static ssize_t show_custom_id(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%d\n", ov->customid); +} +static DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); + +static ssize_t show_model(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%s\n", ov->desc); +} +static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); + +static ssize_t show_bridge(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); +} +static DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); + +static ssize_t show_sensor(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); +} +static DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); + +static ssize_t show_brightness(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_brightness(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); + +static ssize_t show_saturation(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_saturation(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); + +static ssize_t show_contrast(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_contrast(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); + +static ssize_t show_hue(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_hue(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); + +static ssize_t show_exposure(struct device *cd, struct device_attribute *attr, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned char exp = 0; + + if (!ov->dev) + return -ENODEV; + sensor_get_exposure(ov, &exp); + return sprintf(buf, "%d\n", exp >> 8); +} +static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); + +static void ov_create_sysfs(struct device *dev) +{ + device_create_file(dev, &dev_attr_custom_id); + device_create_file(dev, &dev_attr_model); + device_create_file(dev, &dev_attr_bridge); + device_create_file(dev, &dev_attr_sensor); + device_create_file(dev, &dev_attr_brightness); + device_create_file(dev, &dev_attr_saturation); + device_create_file(dev, &dev_attr_contrast); + device_create_file(dev, &dev_attr_hue); + device_create_file(dev, &dev_attr_exposure); +} + +/**************************************************************************** + * USB routines + ***************************************************************************/ + +static int +ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_interface_descriptor *idesc; + struct usb_ov511 *ov; + int i; + + PDEBUG(1, "probing for device..."); + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + idesc = &intf->cur_altsetting->desc; + + if (idesc->bInterfaceClass != 0xFF) + return -ENODEV; + if (idesc->bInterfaceSubClass != 0x00) + return -ENODEV; + + if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { + err("couldn't kmalloc ov struct"); + goto error_out; + } + + memset(ov, 0, sizeof(*ov)); + + ov->dev = dev; + ov->iface = idesc->bInterfaceNumber; + ov->led_policy = led; + ov->compress = compress; + ov->lightfreq = lightfreq; + ov->num_inputs = 1; /* Video decoder init functs. change this */ + ov->stop_during_set = !fastset; + ov->backlight = backlight; + ov->mirror = mirror; + ov->auto_brt = autobright; + ov->auto_gain = autogain; + ov->auto_exp = autoexp; + + switch (le16_to_cpu(dev->descriptor.idProduct)) { + case PROD_OV511: + ov->bridge = BRG_OV511; + ov->bclass = BCL_OV511; + break; + case PROD_OV511PLUS: + ov->bridge = BRG_OV511PLUS; + ov->bclass = BCL_OV511; + break; + case PROD_OV518: + ov->bridge = BRG_OV518; + ov->bclass = BCL_OV518; + break; + case PROD_OV518PLUS: + ov->bridge = BRG_OV518PLUS; + ov->bclass = BCL_OV518; + break; + case PROD_ME2CAM: + if (le16_to_cpu(dev->descriptor.idVendor) != VEND_MATTEL) + goto error; + ov->bridge = BRG_OV511PLUS; + ov->bclass = BCL_OV511; + break; + default: + err("Unknown product ID 0x%04x", le16_to_cpu(dev->descriptor.idProduct)); + goto error; + } + + info("USB %s video device found", symbolic(brglist, ov->bridge)); + + init_waitqueue_head(&ov->wq); + + init_MUTEX(&ov->lock); /* to 1 == available */ + init_MUTEX(&ov->buf_lock); + init_MUTEX(&ov->param_lock); + init_MUTEX(&ov->i2c_lock); + init_MUTEX(&ov->cbuf_lock); + + ov->buf_state = BUF_NOT_ALLOCATED; + + if (usb_make_path(dev, ov->usb_path, OV511_USB_PATH_LEN) < 0) { + err("usb_make_path error"); + goto error; + } + + /* Allocate control transfer buffer. */ + /* Must be kmalloc()'ed, for DMA compatibility */ + ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL); + if (!ov->cbuf) + goto error; + + if (ov->bclass == BCL_OV518) { + if (ov518_configure(ov) < 0) + goto error; + } else { + if (ov511_configure(ov) < 0) + goto error; + } + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].framenum = i; + init_waitqueue_head(&ov->frame[i].wq); + } + + for (i = 0; i < OV511_NUMSBUF; i++) { + ov->sbuf[i].ov = ov; + spin_lock_init(&ov->sbuf[i].lock); + ov->sbuf[i].n = i; + } + + /* Unnecessary? (This is done on open(). Need to make sure variables + * are properly initialized without this before removing it, though). */ + if (ov51x_set_default_params(ov) < 0) + goto error; + +#ifdef OV511_DEBUG + if (dump_bridge) { + if (ov->bclass == BCL_OV511) + ov511_dump_regs(ov); + else + ov518_dump_regs(ov); + } +#endif + + ov->vdev = video_device_alloc(); + if (!ov->vdev) + goto error; + + memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev)); +// ov->vdev->dev = &dev->dev; + video_set_drvdata(ov->vdev, ov); + + for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) { + /* Minor 0 cannot be specified; assume user wants autodetect */ + if (unit_video[i] == 0) + break; + + if (video_register_device(ov->vdev, VFL_TYPE_GRABBER, + unit_video[i]) >= 0) { + break; + } + } + + /* Use the next available one */ + if ((ov->vdev->minor == -1) && + video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) { + err("video_register_device failed"); + goto error; + } + + info("Device at %s registered to minor %d", ov->usb_path, + ov->vdev->minor); + + usb_set_intfdata(intf, ov); + ov_create_sysfs(&ov->dev->dev); + return 0; + +error: + if (ov->vdev) { + if (-1 == ov->vdev->minor) + video_device_release(ov->vdev); + else + video_unregister_device(ov->vdev); + ov->vdev = NULL; + } + + if (ov->cbuf) { + down(&ov->cbuf_lock); + kfree(ov->cbuf); + ov->cbuf = NULL; + up(&ov->cbuf_lock); + } + + kfree(ov); + ov = NULL; + +error_out: + err("Camera initialization failed"); + return -EIO; +} + +static void +ov51x_disconnect(struct usb_interface *intf) +{ + struct usb_ov511 *ov = usb_get_intfdata(intf); + int n; + + PDEBUG(3, ""); + + usb_set_intfdata (intf, NULL); + + if (!ov) + return; + + if (ov->vdev) + video_unregister_device(ov->vdev); + + for (n = 0; n < OV511_NUMFRAMES; n++) + ov->frame[n].grabstate = FRAME_ERROR; + + ov->curframe = -1; + + /* This will cause the process to request another frame */ + for (n = 0; n < OV511_NUMFRAMES; n++) + wake_up_interruptible(&ov->frame[n].wq); + + wake_up_interruptible(&ov->wq); + + ov->streaming = 0; + ov51x_unlink_isoc(ov); + + ov->dev = NULL; + + /* Free the memory */ + if (ov && !ov->user) { + down(&ov->cbuf_lock); + kfree(ov->cbuf); + ov->cbuf = NULL; + up(&ov->cbuf_lock); + + ov51x_dealloc(ov); + kfree(ov); + ov = NULL; + } + + PDEBUG(3, "Disconnect complete"); +} + +static struct usb_driver ov511_driver = { + .name = "ov511", + .id_table = device_table, + .probe = ov51x_probe, + .disconnect = ov51x_disconnect +}; + +/**************************************************************************** + * + * Module routines + * + ***************************************************************************/ + +/* Returns 0 for success */ +int +ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518, + int mmx) +{ + if (ver != DECOMP_INTERFACE_VER) { + err("Decompression module has incompatible"); + err("interface version %d", ver); + err("Interface version %d is required", DECOMP_INTERFACE_VER); + return -EINVAL; + } + + if (!ops) + return -EFAULT; + + if (mmx && !ov51x_mmx_available) { + err("MMX not available on this system or kernel"); + return -EINVAL; + } + + lock_kernel(); + + if (ov518) { + if (mmx) { + if (ov518_mmx_decomp_ops) + goto err_in_use; + else + ov518_mmx_decomp_ops = ops; + } else { + if (ov518_decomp_ops) + goto err_in_use; + else + ov518_decomp_ops = ops; + } + } else { + if (mmx) { + if (ov511_mmx_decomp_ops) + goto err_in_use; + else + ov511_mmx_decomp_ops = ops; + } else { + if (ov511_decomp_ops) + goto err_in_use; + else + ov511_decomp_ops = ops; + } + } + + unlock_kernel(); + return 0; + +err_in_use: + unlock_kernel(); + return -EBUSY; +} + +void +ov511_deregister_decomp_module(int ov518, int mmx) +{ + lock_kernel(); + + if (ov518) { + if (mmx) + ov518_mmx_decomp_ops = NULL; + else + ov518_decomp_ops = NULL; + } else { + if (mmx) + ov511_mmx_decomp_ops = NULL; + else + ov511_decomp_ops = NULL; + } + + unlock_kernel(); +} + +static int __init +usb_ov511_init(void) +{ + int retval; + + retval = usb_register(&ov511_driver); + if (retval) + goto out; + + info(DRIVER_VERSION " : " DRIVER_DESC); + +out: + return retval; +} + +static void __exit +usb_ov511_exit(void) +{ + usb_deregister(&ov511_driver); + info("driver deregistered"); + +} + +module_init(usb_ov511_init); +module_exit(usb_ov511_exit); + +EXPORT_SYMBOL(ov511_register_decomp_module); +EXPORT_SYMBOL(ov511_deregister_decomp_module); --- linux-2.6.27.orig/ubuntu/misc/media/ov511/ov518_decomp.c +++ linux-2.6.27/ubuntu/misc/media/ov511/ov518_decomp.c @@ -0,0 +1,1566 @@ +/* OV518 Decompression Support Module (No-MMX version) + * + * Copyright (c) 2002-2003 Mark W. McClelland. All rights reserved. + * http://alpha.dyndns.org/ov511/ + * + * Fast integer iDCT by Yuri van Oers + * Original OV511 decompression code Copyright 1998-2000 OmniVision Technologies + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + */ + + +#if defined(OUTSIDE_KERNEL) + #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS + #endif + + #include + + #ifdef MODVERSIONS + #include + #endif +#else + #include +#endif + +#include +#include + +#include "ov511.h" + +/****************************************************************************** + * Compile-time Options + ******************************************************************************/ + +/* Defining APPROXIMATE_MUL_BY_SHIFT increases performance by approximation + * the multiplications by shifts. I think there's no change in the + * calculated picture, but I'm not sure, so the choice is still in here. */ +#undef APPROXIMATE_MUL_BY_SHIFT + +/* Allows printing the dynamic quantization tables (only if debug >= 5) */ +#define PRINT_QT + +/****************************************************************************** + * Version Information + ******************************************************************************/ + +#define DRIVER_VERSION "v1.3" +#define DRIVER_AUTHOR "Mark McClelland , \ +Yuri van Oers , OmniVision Technologies \ +" +#define DRIVER_DESC "OV518 Decompression Module" + +/****************************************************************************** + * Decompression Module Interface Constants + ******************************************************************************/ + +static const int interface_ver = DECOMP_INTERFACE_VER; +static const int ov518 = 1; +static const int mmx = 0; + +/****************************************************************************** + * Module Features + ******************************************************************************/ + +static int debug = 0; + +/* Static quantization. This uses a fixed quantization table versus the one + * that is normally embedded in the data. Define this if you see very bad + * contrast or "blockiness" in the decompressed output. */ +static int staticquant = 0; + +module_param(debug, uint, 0400); +MODULE_PARM_DESC(debug, + "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max"); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +#if defined(MODULE_LICENSE) /* Introduced in ~2.4.10 */ +MODULE_LICENSE("GPL"); +#endif + +/****************************************************************************** + * Prototypes + ******************************************************************************/ + +extern int ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, + int ov518, int mmx); +extern void ov511_deregister_decomp_module(int ov518, int mmx); + +/****************************************************************************** + * Local Data Types + ******************************************************************************/ + +/* Make sure this remains naturally aligned and 2^n bytes in size */ +struct tree_node { + short left; /* Pointer to left child node */ + short right; /* Pointer to right child node */ + signed char depth; /* Depth (starting at 1) if leaf, else -1 */ + signed char coeffbits; /* Size of coefficient data, or zero if none */ + signed char skip; /* Number of zero coefficients. Unused w/ DC */ + char padding; /* Pad out to 8 bytes */ +}; + +struct comp_info { + int bytes; /* Number of processed input bytes */ + int bits; /* Number of unprocessed input bits */ + int rawLen; /* Total number of bytes in input buffer */ + unsigned char *qt; /* Current quantization table */ +}; + +/****************************************************************************** + * Constant Data Definitions + ******************************************************************************/ + +/* Zig-Zag Table */ +static const unsigned char ZigZag518[] = { + 0x00, 0x02, 0x03, 0x09, + 0x01, 0x04, 0x08, 0x0a, + 0x05, 0x07, 0x0b, 0x11, + 0x06, 0x0c, 0x10, 0x12, + 0x0d, 0x0f, 0x13, 0x19, + 0x0e, 0x14, 0x18, 0x1a, + 0x15, 0x17, 0x1b, 0x1e, + 0x16, 0x1c, 0x1d, 0x1f +}; + +/* Huffman trees */ + +static const struct tree_node treeYAC[] = { + { 1, 4, -1, 0, -1}, { 2, 3, -1, 0, -1}, + { -1, -1, 2, 1, 0}, { -1, -1, 2, 2, 0}, + { 5, 9, -1, 0, -1}, { 6, 7, -1, 0, -1}, + { -1, -1, 3, 3, 0}, {323, 8, -1, 0, -1}, + { -1, -1, 4, 4, 0}, { 10, 13, -1, 0, -1}, + { 38, 11, -1, 0, -1}, { 12, 39, -1, 0, -1}, + { -1, -1, 5, 5, 0}, { 59, 14, -1, 0, -1}, + { 15, 18, -1, 0, -1}, { 16, 113, -1, 0, -1}, + { 17, 40, -1, 0, -1}, { -1, -1, 7, 6, 0}, + { 19, 22, -1, 0, -1}, { 20, 41, -1, 0, -1}, + { 21, 61, -1, 0, -1}, { -1, -1, 8, 7, 0}, + { 23, 27, -1, 0, -1}, {169, 24, -1, 0, -1}, + {208, 25, -1, 0, -1}, { 26, 62, -1, 0, -1}, + { -1, -1, 10, 8, 0}, { 44, 28, -1, 0, -1}, + { 63, 29, -1, 0, -1}, { 30, 191, -1, 0, -1}, + { 31, 119, -1, 0, -1}, { 32, 82, -1, 0, -1}, + { 33, 55, -1, 0, -1}, { 34, 48, -1, 0, -1}, + {171, 35, -1, 0, -1}, { 36, 37, -1, 0, -1}, + { -1, -1, 16, 9, 0}, { -1, -1, 16, 10, 0}, + { -1, -1, 4, 1, 1}, { -1, -1, 5, 2, 1}, + { -1, -1, 7, 3, 1}, {151, 42, -1, 0, -1}, + { 43, 79, -1, 0, -1}, { -1, -1, 9, 4, 1}, + { 96, 45, -1, 0, -1}, {246, 46, -1, 0, -1}, + { 47, 115, -1, 0, -1}, { -1, -1, 11, 5, 1}, + { 49, 52, -1, 0, -1}, { 50, 51, -1, 0, -1}, + { -1, -1, 16, 6, 1}, { -1, -1, 16, 7, 1}, + { 53, 54, -1, 0, -1}, { -1, -1, 16, 8, 1}, + { -1, -1, 16, 9, 1}, { 56, 71, -1, 0, -1}, + { 57, 68, -1, 0, -1}, { 58, 67, -1, 0, -1}, + { -1, -1, 16, 10, 1}, { 60, 77, -1, 0, -1}, + { -1, -1, 5, 1, 2}, { -1, -1, 8, 2, 2}, + { -1, -1, 10, 3, 2}, {265, 64, -1, 0, -1}, + { 65, 134, -1, 0, -1}, { 66, 80, -1, 0, -1}, + { -1, -1, 12, 4, 2}, { -1, -1, 16, 5, 2}, + { 69, 70, -1, 0, -1}, { -1, -1, 16, 6, 2}, + { -1, -1, 16, 7, 2}, { 72, 75, -1, 0, -1}, + { 73, 74, -1, 0, -1}, { -1, -1, 16, 8, 2}, + { -1, -1, 16, 9, 2}, { 76, 81, -1, 0, -1}, + { -1, -1, 16, 10, 2}, { 78, 95, -1, 0, -1}, + { -1, -1, 6, 1, 3}, { -1, -1, 9, 2, 3}, + { -1, -1, 12, 3, 3}, { -1, -1, 16, 4, 3}, + { 83, 101, -1, 0, -1}, { 84, 91, -1, 0, -1}, + { 85, 88, -1, 0, -1}, { 86, 87, -1, 0, -1}, + { -1, -1, 16, 5, 3}, { -1, -1, 16, 6, 3}, + { 89, 90, -1, 0, -1}, { -1, -1, 16, 7, 3}, + { -1, -1, 16, 8, 3}, { 92, 98, -1, 0, -1}, + { 93, 94, -1, 0, -1}, { -1, -1, 16, 9, 3}, + { -1, -1, 16, 10, 3}, { -1, -1, 6, 1, 4}, + { 97, 225, -1, 0, -1}, { -1, -1, 10, 2, 4}, + { 99, 100, -1, 0, -1}, { -1, -1, 16, 3, 4}, + { -1, -1, 16, 4, 4}, {102, 109, -1, 0, -1}, + {103, 106, -1, 0, -1}, {104, 105, -1, 0, -1}, + { -1, -1, 16, 5, 4}, { -1, -1, 16, 6, 4}, + {107, 108, -1, 0, -1}, { -1, -1, 16, 7, 4}, + { -1, -1, 16, 8, 4}, {110, 116, -1, 0, -1}, + {111, 112, -1, 0, -1}, { -1, -1, 16, 9, 4}, + { -1, -1, 16, 10, 4}, {114, 133, -1, 0, -1}, + { -1, -1, 7, 1, 5}, { -1, -1, 11, 2, 5}, + {117, 118, -1, 0, -1}, { -1, -1, 16, 3, 5}, + { -1, -1, 16, 4, 5}, {120, 156, -1, 0, -1}, + {121, 139, -1, 0, -1}, {122, 129, -1, 0, -1}, + {123, 126, -1, 0, -1}, {124, 125, -1, 0, -1}, + { -1, -1, 16, 5, 5}, { -1, -1, 16, 6, 5}, + {127, 128, -1, 0, -1}, { -1, -1, 16, 7, 5}, + { -1, -1, 16, 8, 5}, {130, 136, -1, 0, -1}, + {131, 132, -1, 0, -1}, { -1, -1, 16, 9, 5}, + { -1, -1, 16, 10, 5}, { -1, -1, 7, 1, 6}, + {135, 152, -1, 0, -1}, { -1, -1, 12, 2, 6}, + {137, 138, -1, 0, -1}, { -1, -1, 16, 3, 6}, + { -1, -1, 16, 4, 6}, {140, 147, -1, 0, -1}, + {141, 144, -1, 0, -1}, {142, 143, -1, 0, -1}, + { -1, -1, 16, 5, 6}, { -1, -1, 16, 6, 6}, + {145, 146, -1, 0, -1}, { -1, -1, 16, 7, 6}, + { -1, -1, 16, 8, 6}, {148, 153, -1, 0, -1}, + {149, 150, -1, 0, -1}, { -1, -1, 16, 9, 6}, + { -1, -1, 16, 10, 6}, { -1, -1, 8, 1, 7}, + { -1, -1, 12, 2, 7}, {154, 155, -1, 0, -1}, + { -1, -1, 16, 3, 7}, { -1, -1, 16, 4, 7}, + {157, 175, -1, 0, -1}, {158, 165, -1, 0, -1}, + {159, 162, -1, 0, -1}, {160, 161, -1, 0, -1}, + { -1, -1, 16, 5, 7}, { -1, -1, 16, 6, 7}, + {163, 164, -1, 0, -1}, { -1, -1, 16, 7, 7}, + { -1, -1, 16, 8, 7}, {166, 172, -1, 0, -1}, + {167, 168, -1, 0, -1}, { -1, -1, 16, 9, 7}, + { -1, -1, 16, 10, 7}, {170, 187, -1, 0, -1}, + { -1, -1, 9, 1, 8}, { -1, -1, 15, 2, 8}, + {173, 174, -1, 0, -1}, { -1, -1, 16, 3, 8}, + { -1, -1, 16, 4, 8}, {176, 183, -1, 0, -1}, + {177, 180, -1, 0, -1}, {178, 179, -1, 0, -1}, + { -1, -1, 16, 5, 8}, { -1, -1, 16, 6, 8}, + {181, 182, -1, 0, -1}, { -1, -1, 16, 7, 8}, + { -1, -1, 16, 8, 8}, {184, 188, -1, 0, -1}, + {185, 186, -1, 0, -1}, { -1, -1, 16, 9, 8}, + { -1, -1, 16, 10, 8}, { -1, -1, 9, 1, 9}, + {189, 190, -1, 0, -1}, { -1, -1, 16, 2, 9}, + { -1, -1, 16, 3, 9}, {192, 258, -1, 0, -1}, + {193, 226, -1, 0, -1}, {194, 210, -1, 0, -1}, + {195, 202, -1, 0, -1}, {196, 199, -1, 0, -1}, + {197, 198, -1, 0, -1}, { -1, -1, 16, 4, 9}, + { -1, -1, 16, 5, 9}, {200, 201, -1, 0, -1}, + { -1, -1, 16, 6, 9}, { -1, -1, 16, 7, 9}, + {203, 206, -1, 0, -1}, {204, 205, -1, 0, -1}, + { -1, -1, 16, 8, 9}, { -1, -1, 16, 9, 9}, + {207, 209, -1, 0, -1}, { -1, -1, 16, 10, 9}, + { -1, -1, 9, 1, 10}, { -1, -1, 16, 2, 10}, + {211, 218, -1, 0, -1}, {212, 215, -1, 0, -1}, + {213, 214, -1, 0, -1}, { -1, -1, 16, 3, 10}, + { -1, -1, 16, 4, 10}, {216, 217, -1, 0, -1}, + { -1, -1, 16, 5, 10}, { -1, -1, 16, 6, 10}, + {219, 222, -1, 0, -1}, {220, 221, -1, 0, -1}, + { -1, -1, 16, 7, 10}, { -1, -1, 16, 8, 10}, + {223, 224, -1, 0, -1}, { -1, -1, 16, 9, 10}, + { -1, -1, 16, 10, 10}, { -1, -1, 10, 1, 11}, + {227, 242, -1, 0, -1}, {228, 235, -1, 0, -1}, + {229, 232, -1, 0, -1}, {230, 231, -1, 0, -1}, + { -1, -1, 16, 2, 11}, { -1, -1, 16, 3, 11}, + {233, 234, -1, 0, -1}, { -1, -1, 16, 4, 11}, + { -1, -1, 16, 5, 11}, {236, 239, -1, 0, -1}, + {237, 238, -1, 0, -1}, { -1, -1, 16, 6, 11}, + { -1, -1, 16, 7, 11}, {240, 241, -1, 0, -1}, + { -1, -1, 16, 8, 11}, { -1, -1, 16, 9, 11}, + {243, 251, -1, 0, -1}, {244, 248, -1, 0, -1}, + {245, 247, -1, 0, -1}, { -1, -1, 16, 10, 11}, + { -1, -1, 10, 1, 12}, { -1, -1, 16, 2, 12}, + {249, 250, -1, 0, -1}, { -1, -1, 16, 3, 12}, + { -1, -1, 16, 4, 12}, {252, 255, -1, 0, -1}, + {253, 254, -1, 0, -1}, { -1, -1, 16, 5, 12}, + { -1, -1, 16, 6, 12}, {256, 257, -1, 0, -1}, + { -1, -1, 16, 7, 12}, { -1, -1, 16, 8, 12}, + {259, 292, -1, 0, -1}, {260, 277, -1, 0, -1}, + {261, 270, -1, 0, -1}, {262, 267, -1, 0, -1}, + {263, 264, -1, 0, -1}, { -1, -1, 16, 9, 12}, + { -1, -1, 16, 10, 12}, {266, 322, -1, 0, -1}, + { -1, -1, 11, 1, 13}, {268, 269, -1, 0, -1}, + { -1, -1, 16, 2, 13}, { -1, -1, 16, 3, 13}, + {271, 274, -1, 0, -1}, {272, 273, -1, 0, -1}, + { -1, -1, 16, 4, 13}, { -1, -1, 16, 5, 13}, + {275, 276, -1, 0, -1}, { -1, -1, 16, 6, 13}, + { -1, -1, 16, 7, 13}, {278, 285, -1, 0, -1}, + {279, 282, -1, 0, -1}, {280, 281, -1, 0, -1}, + { -1, -1, 16, 8, 13}, { -1, -1, 16, 9, 13}, + {283, 284, -1, 0, -1}, { -1, -1, 16, 10, 13}, + { -1, -1, 16, 1, 14}, {286, 289, -1, 0, -1}, + {287, 288, -1, 0, -1}, { -1, -1, 16, 2, 14}, + { -1, -1, 16, 3, 14}, {290, 291, -1, 0, -1}, + { -1, -1, 16, 4, 14}, { -1, -1, 16, 5, 14}, + {293, 308, -1, 0, -1}, {294, 301, -1, 0, -1}, + {295, 298, -1, 0, -1}, {296, 297, -1, 0, -1}, + { -1, -1, 16, 6, 14}, { -1, -1, 16, 7, 14}, + {299, 300, -1, 0, -1}, { -1, -1, 16, 8, 14}, + { -1, -1, 16, 9, 14}, {302, 305, -1, 0, -1}, + {303, 304, -1, 0, -1}, { -1, -1, 16, 10, 14}, + { -1, -1, 16, 1, 15}, {306, 307, -1, 0, -1}, + { -1, -1, 16, 2, 15}, { -1, -1, 16, 3, 15}, + {309, 316, -1, 0, -1}, {310, 313, -1, 0, -1}, + {311, 312, -1, 0, -1}, { -1, -1, 16, 4, 15}, + { -1, -1, 16, 5, 15}, {314, 315, -1, 0, -1}, + { -1, -1, 16, 6, 15}, { -1, -1, 16, 7, 15}, + {317, 320, -1, 0, -1}, {318, 319, -1, 0, -1}, + { -1, -1, 16, 8, 15}, { -1, -1, 16, 9, 15}, + {321, -1, -1, 0, -1}, { -1, -1, 16, 10, 15}, + { -1, -1, 11, 0, 16}, { -1, -1, 4, 0, -1}, +}; + +static const struct tree_node treeUVAC[] = { + { 1, 3, -1, 0, -1}, {323, 2, -1, 0, -1}, + { -1, -1, 2, 1, 0}, { 4, 8, -1, 0, -1}, + { 5, 6, -1, 0, -1}, { -1, -1, 3, 2, 0}, + { 7, 37, -1, 0, -1}, { -1, -1, 4, 3, 0}, + { 9, 13, -1, 0, -1}, { 10, 60, -1, 0, -1}, + { 11, 12, -1, 0, -1}, { -1, -1, 5, 4, 0}, + { -1, -1, 5, 5, 0}, { 14, 17, -1, 0, -1}, + { 15, 97, -1, 0, -1}, { 16, 38, -1, 0, -1}, + { -1, -1, 6, 6, 0}, { 18, 21, -1, 0, -1}, + { 19, 39, -1, 0, -1}, { 20, 135, -1, 0, -1}, + { -1, -1, 7, 7, 0}, { 22, 26, -1, 0, -1}, + { 82, 23, -1, 0, -1}, { 24, 99, -1, 0, -1}, + { 25, 42, -1, 0, -1}, { -1, -1, 9, 8, 0}, + { 27, 31, -1, 0, -1}, {211, 28, -1, 0, -1}, + {248, 29, -1, 0, -1}, { 30, 63, -1, 0, -1}, + { -1, -1, 10, 9, 0}, { 43, 32, -1, 0, -1}, + { 33, 48, -1, 0, -1}, {153, 34, -1, 0, -1}, + { 35, 64, -1, 0, -1}, { 36, 47, -1, 0, -1}, + { -1, -1, 12, 10, 0}, { -1, -1, 4, 1, 1}, + { -1, -1, 6, 2, 1}, {152, 40, -1, 0, -1}, + { 41, 62, -1, 0, -1}, { -1, -1, 8, 3, 1}, + { -1, -1, 9, 4, 1}, { 84, 44, -1, 0, -1}, + {322, 45, -1, 0, -1}, { 46, 136, -1, 0, -1}, + { -1, -1, 11, 5, 1}, { -1, -1, 12, 6, 1}, + { 49, 189, -1, 0, -1}, { 50, 119, -1, 0, -1}, + { 51, 76, -1, 0, -1}, { 66, 52, -1, 0, -1}, + { 53, 69, -1, 0, -1}, { 54, 57, -1, 0, -1}, + { 55, 56, -1, 0, -1}, { -1, -1, 16, 7, 1}, + { -1, -1, 16, 8, 1}, { 58, 59, -1, 0, -1}, + { -1, -1, 16, 9, 1}, { -1, -1, 16, 10, 1}, + { 61, 81, -1, 0, -1}, { -1, -1, 5, 1, 2}, + { -1, -1, 8, 2, 2}, { -1, -1, 10, 3, 2}, + { 65, 86, -1, 0, -1}, { -1, -1, 12, 4, 2}, + {286, 67, -1, 0, -1}, { 68, 304, -1, 0, -1}, + { -1, -1, 15, 5, 2}, { 70, 73, -1, 0, -1}, + { 71, 72, -1, 0, -1}, { -1, -1, 16, 6, 2}, + { -1, -1, 16, 7, 2}, { 74, 75, -1, 0, -1}, + { -1, -1, 16, 8, 2}, { -1, -1, 16, 9, 2}, + { 77, 102, -1, 0, -1}, { 78, 91, -1, 0, -1}, + { 79, 88, -1, 0, -1}, { 80, 87, -1, 0, -1}, + { -1, -1, 16, 10, 2}, { -1, -1, 5, 1, 3}, + { 83, 171, -1, 0, -1}, { -1, -1, 8, 2, 3}, + { 85, 117, -1, 0, -1}, { -1, -1, 10, 3, 3}, + { -1, -1, 12, 4, 3}, { -1, -1, 16, 5, 3}, + { 89, 90, -1, 0, -1}, { -1, -1, 16, 6, 3}, + { -1, -1, 16, 7, 3}, { 92, 95, -1, 0, -1}, + { 93, 94, -1, 0, -1}, { -1, -1, 16, 8, 3}, + { -1, -1, 16, 9, 3}, { 96, 101, -1, 0, -1}, + { -1, -1, 16, 10, 3}, { 98, 116, -1, 0, -1}, + { -1, -1, 6, 1, 4}, {100, 188, -1, 0, -1}, + { -1, -1, 9, 2, 4}, { -1, -1, 16, 3, 4}, + {103, 110, -1, 0, -1}, {104, 107, -1, 0, -1}, + {105, 106, -1, 0, -1}, { -1, -1, 16, 4, 4}, + { -1, -1, 16, 5, 4}, {108, 109, -1, 0, -1}, + { -1, -1, 16, 6, 4}, { -1, -1, 16, 7, 4}, + {111, 114, -1, 0, -1}, {112, 113, -1, 0, -1}, + { -1, -1, 16, 8, 4}, { -1, -1, 16, 9, 4}, + {115, 118, -1, 0, -1}, { -1, -1, 16, 10, 4}, + { -1, -1, 6, 1, 5}, { -1, -1, 10, 2, 5}, + { -1, -1, 16, 3, 5}, {120, 156, -1, 0, -1}, + {121, 138, -1, 0, -1}, {122, 129, -1, 0, -1}, + {123, 126, -1, 0, -1}, {124, 125, -1, 0, -1}, + { -1, -1, 16, 4, 5}, { -1, -1, 16, 5, 5}, + {127, 128, -1, 0, -1}, { -1, -1, 16, 6, 5}, + { -1, -1, 16, 7, 5}, {130, 133, -1, 0, -1}, + {131, 132, -1, 0, -1}, { -1, -1, 16, 8, 5}, + { -1, -1, 16, 9, 5}, {134, 137, -1, 0, -1}, + { -1, -1, 16, 10, 5}, { -1, -1, 7, 1, 6}, + { -1, -1, 11, 2, 6}, { -1, -1, 16, 3, 6}, + {139, 146, -1, 0, -1}, {140, 143, -1, 0, -1}, + {141, 142, -1, 0, -1}, { -1, -1, 16, 4, 6}, + { -1, -1, 16, 5, 6}, {144, 145, -1, 0, -1}, + { -1, -1, 16, 6, 6}, { -1, -1, 16, 7, 6}, + {147, 150, -1, 0, -1}, {148, 149, -1, 0, -1}, + { -1, -1, 16, 8, 6}, { -1, -1, 16, 9, 6}, + {151, 155, -1, 0, -1}, { -1, -1, 16, 10, 6}, + { -1, -1, 7, 1, 7}, {154, 267, -1, 0, -1}, + { -1, -1, 11, 2, 7}, { -1, -1, 16, 3, 7}, + {157, 173, -1, 0, -1}, {158, 165, -1, 0, -1}, + {159, 162, -1, 0, -1}, {160, 161, -1, 0, -1}, + { -1, -1, 16, 4, 7}, { -1, -1, 16, 5, 7}, + {163, 164, -1, 0, -1}, { -1, -1, 16, 6, 7}, + { -1, -1, 16, 7, 7}, {166, 169, -1, 0, -1}, + {167, 168, -1, 0, -1}, { -1, -1, 16, 8, 7}, + { -1, -1, 16, 9, 7}, {170, 172, -1, 0, -1}, + { -1, -1, 16, 10, 7}, { -1, -1, 8, 1, 8}, + { -1, -1, 16, 2, 8}, {174, 181, -1, 0, -1}, + {175, 178, -1, 0, -1}, {176, 177, -1, 0, -1}, + { -1, -1, 16, 3, 8}, { -1, -1, 16, 4, 8}, + {179, 180, -1, 0, -1}, { -1, -1, 16, 5, 8}, + { -1, -1, 16, 6, 8}, {182, 185, -1, 0, -1}, + {183, 184, -1, 0, -1}, { -1, -1, 16, 7, 8}, + { -1, -1, 16, 8, 8}, {186, 187, -1, 0, -1}, + { -1, -1, 16, 9, 8}, { -1, -1, 16, 10, 8}, + { -1, -1, 9, 1, 9}, {190, 257, -1, 0, -1}, + {191, 224, -1, 0, -1}, {192, 207, -1, 0, -1}, + {193, 200, -1, 0, -1}, {194, 197, -1, 0, -1}, + {195, 196, -1, 0, -1}, { -1, -1, 16, 2, 9}, + { -1, -1, 16, 3, 9}, {198, 199, -1, 0, -1}, + { -1, -1, 16, 4, 9}, { -1, -1, 16, 5, 9}, + {201, 204, -1, 0, -1}, {202, 203, -1, 0, -1}, + { -1, -1, 16, 6, 9}, { -1, -1, 16, 7, 9}, + {205, 206, -1, 0, -1}, { -1, -1, 16, 8, 9}, + { -1, -1, 16, 9, 9}, {208, 217, -1, 0, -1}, + {209, 214, -1, 0, -1}, {210, 213, -1, 0, -1}, + { -1, -1, 16, 10, 9}, {212, 230, -1, 0, -1}, + { -1, -1, 9, 1, 10}, { -1, -1, 16, 2, 10}, + {215, 216, -1, 0, -1}, { -1, -1, 16, 3, 10}, + { -1, -1, 16, 4, 10}, {218, 221, -1, 0, -1}, + {219, 220, -1, 0, -1}, { -1, -1, 16, 5, 10}, + { -1, -1, 16, 6, 10}, {222, 223, -1, 0, -1}, + { -1, -1, 16, 7, 10}, { -1, -1, 16, 8, 10}, + {225, 241, -1, 0, -1}, {226, 234, -1, 0, -1}, + {227, 231, -1, 0, -1}, {228, 229, -1, 0, -1}, + { -1, -1, 16, 9, 10}, { -1, -1, 16, 10, 10}, + { -1, -1, 9, 1, 11}, {232, 233, -1, 0, -1}, + { -1, -1, 16, 2, 11}, { -1, -1, 16, 3, 11}, + {235, 238, -1, 0, -1}, {236, 237, -1, 0, -1}, + { -1, -1, 16, 4, 11}, { -1, -1, 16, 5, 11}, + {239, 240, -1, 0, -1}, { -1, -1, 16, 6, 11}, + { -1, -1, 16, 7, 11}, {242, 250, -1, 0, -1}, + {243, 246, -1, 0, -1}, {244, 245, -1, 0, -1}, + { -1, -1, 16, 8, 11}, { -1, -1, 16, 9, 11}, + {247, 249, -1, 0, -1}, { -1, -1, 16, 10, 11}, + { -1, -1, 9, 1, 12}, { -1, -1, 16, 2, 12}, + {251, 254, -1, 0, -1}, {252, 253, -1, 0, -1}, + { -1, -1, 16, 3, 12}, { -1, -1, 16, 4, 12}, + {255, 256, -1, 0, -1}, { -1, -1, 16, 5, 12}, + { -1, -1, 16, 6, 12}, {258, 291, -1, 0, -1}, + {259, 275, -1, 0, -1}, {260, 268, -1, 0, -1}, + {261, 264, -1, 0, -1}, {262, 263, -1, 0, -1}, + { -1, -1, 16, 7, 12}, { -1, -1, 16, 8, 12}, + {265, 266, -1, 0, -1}, { -1, -1, 16, 9, 12}, + { -1, -1, 16, 10, 12}, { -1, -1, 11, 1, 13}, + {269, 272, -1, 0, -1}, {270, 271, -1, 0, -1}, + { -1, -1, 16, 2, 13}, { -1, -1, 16, 3, 13}, + {273, 274, -1, 0, -1}, { -1, -1, 16, 4, 13}, + { -1, -1, 16, 5, 13}, {276, 283, -1, 0, -1}, + {277, 280, -1, 0, -1}, {278, 279, -1, 0, -1}, + { -1, -1, 16, 6, 13}, { -1, -1, 16, 7, 13}, + {281, 282, -1, 0, -1}, { -1, -1, 16, 8, 13}, + { -1, -1, 16, 9, 13}, {284, 288, -1, 0, -1}, + {285, 287, -1, 0, -1}, { -1, -1, 16, 10, 13}, + { -1, -1, 14, 1, 14}, { -1, -1, 16, 2, 14}, + {289, 290, -1, 0, -1}, { -1, -1, 16, 3, 14}, + { -1, -1, 16, 4, 14}, {292, 308, -1, 0, -1}, + {293, 300, -1, 0, -1}, {294, 297, -1, 0, -1}, + {295, 296, -1, 0, -1}, { -1, -1, 16, 5, 14}, + { -1, -1, 16, 6, 14}, {298, 299, -1, 0, -1}, + { -1, -1, 16, 7, 14}, { -1, -1, 16, 8, 14}, + {301, 305, -1, 0, -1}, {302, 303, -1, 0, -1}, + { -1, -1, 16, 9, 14}, { -1, -1, 16, 10, 14}, + { -1, -1, 15, 1, 15}, {306, 307, -1, 0, -1}, + { -1, -1, 16, 2, 15}, { -1, -1, 16, 3, 15}, + {309, 316, -1, 0, -1}, {310, 313, -1, 0, -1}, + {311, 312, -1, 0, -1}, { -1, -1, 16, 4, 15}, + { -1, -1, 16, 5, 15}, {314, 315, -1, 0, -1}, + { -1, -1, 16, 6, 15}, { -1, -1, 16, 7, 15}, + {317, 320, -1, 0, -1}, {318, 319, -1, 0, -1}, + { -1, -1, 16, 8, 15}, { -1, -1, 16, 9, 15}, + {321, -1, -1, 0, -1}, { -1, -1, 16, 10, 15}, + { -1, -1, 10, 0, 16}, { -1, -1, 2, 0, -1}, +}; + +static const struct tree_node treeYDC[] = { + { 1, 6, -1, 0}, { 2, 3, -1, 0}, + { -1, -1, 2, 0}, { 4, 5, -1, 0}, + { -1, -1, 3, 1}, { -1, -1, 3, 2}, + { 7, 10, -1, 0}, { 8, 9, -1, 0}, + { -1, -1, 3, 3}, { -1, -1, 3, 4}, + { 11, 12, -1, 0}, { -1, -1, 3, 5}, + { 13, 14, -1, 0}, { -1, -1, 4, 6}, + { 15, 16, -1, 0}, { -1, -1, 5, 7}, + { 17, 18, -1, 0}, { -1, -1, 6, 8}, + { 19, 20, -1, 0}, { -1, -1, 7, 9}, + { 21, 22, -1, 0}, { -1, -1, 8, 10}, + { 23, -1, -1, 0}, { -1, -1, 9, 11}, +}; + +static const struct tree_node treeUVDC[] = { + { 1, 4, -1, 0}, { 2, 3, -1, 0}, + { -1, -1, 2, 0}, { -1, -1, 2, 1}, + { 5, 6, -1, 0}, { -1, -1, 2, 2}, + { 7, 8, -1, 0}, { -1, -1, 3, 3}, + { 9, 10, -1, 0}, { -1, -1, 4, 4}, + { 11, 12, -1, 0}, { -1, -1, 5, 5}, + { 13, 14, -1, 0}, { -1, -1, 6, 6}, + { 15, 16, -1, 0}, { -1, -1, 7, 7}, + { 17, 18, -1, 0}, { -1, -1, 8, 8}, + { 19, 20, -1, 0}, { -1, -1, 9, 9}, + { 21, 22, -1, 0}, { -1, -1, 10, 10}, + { 23, -1, -1, 0}, { -1, -1, 11, 11}, +}; + +/****************************************************************************** + * Debugging + ******************************************************************************/ + +#ifdef PRINT_QT +#define PRN_QT_ROW(a, i) PDEBUG(5, "%02x %02x %02x %02x %02x %02x %02x %02x", \ + (a)[(i)], (a)[(i)+1], (a)[(i)+2], (a)[(i)+3], (a)[(i)+4], (a)[(i)+5], \ + (a)[(i)+6], (a)[(i)+7]) + +static inline void +print_qt(unsigned char *qt) +{ + PDEBUG(5, "Y Quantization table:"); + PRN_QT_ROW(qt, 0); + PRN_QT_ROW(qt, 8); + PRN_QT_ROW(qt, 16); + PRN_QT_ROW(qt, 24); + PDEBUG(5, "UV Quantization table:"); + PRN_QT_ROW(qt, 32); + PRN_QT_ROW(qt, 40); + PRN_QT_ROW(qt, 48); + PRN_QT_ROW(qt, 56); +} +#else +static inline void +print_qt(unsigned char *qt) { } +#endif /* PRINT_QT */ + +/****************************************************************************** + * Huffman Decoder + ******************************************************************************/ + +/* Note: There is no penalty for passing the tree as an argument, since dummy + * args are passed anyway (to maintain 16-byte stack alignment), and since the + * address is loaded into a register either way. */ + +/* If no node is found, coeffbits and skip will not be modified */ +/* Return: Depth of node found, or -1 if invalid input code */ +static int +getNodeAC(unsigned int in, signed char *coeffbits, signed char *skip, + const struct tree_node *tree) +{ + int node = 0; + int i = 0; + int depth; + + do { + if ((in & 0x80000000) == 0) + node = tree[node].left; + else + node = tree[node].right; + + if (node == -1) + break; + + depth = tree[node].depth; + + /* Is it a leaf? If not, branch downward */ + if (depth != -1) { + *coeffbits = tree[node].coeffbits; + *skip = tree[node].skip; + return depth; + } + + in <<= 1; + ++i; + } while (i <= 15); + + return -1; +} + +/* If no node is found, coeffbits will not be modified */ +/* Return: Depth of node found, or -1 if invalid input code */ +static int +getNodeDC(unsigned int in, signed char *coeffbits, const struct tree_node *tree) +{ + int node = 0; + int i = 0; + int depth; + + do { + if ((in & 0x80000000) == 0) + node = tree[node].left; + else + node = tree[node].right; + + if (node == -1) + break; + + depth = tree[node].depth; + + /* Is it a leaf? If not, branch downward */ + if (depth != -1) { + *coeffbits = tree[node].coeffbits; + return depth; + } + + in <<= 1; + ++i; + } while (i <= 15); + + return -1; +} + +static inline unsigned int +getBytes(int *rawData, struct comp_info *cinfo) +{ + int bufLen = cinfo->rawLen; + int bits = cinfo->bits; + int bytes = cinfo->bytes; + unsigned char *in = bytes + (unsigned char *) rawData; + unsigned char b1, b2, b3, b4, b5; + unsigned int packedIn; + + /* Pull 5 bytes out of raw data */ + if (bytes < bufLen - 4) { + b1 = in[0]; + b2 = in[1]; + b3 = in[2]; + b4 = in[3]; + b5 = in[4]; + } else { + if (bytes < bufLen - 3) { + b1 = in[0]; + b2 = in[1]; + b3 = in[2]; + b4 = in[3]; + } else { + if (bytes < bufLen - 2) { + b1 = in[0]; + b2 = in[1]; + b3 = in[2]; + } else { + if (bytes < bufLen - 1) { + b1 = in[0]; + b2 = in[1]; + } else { + if (bytes <= bufLen) { + b1 = in[0]; + } else { + b1 = 0; + } + b2 = 0; + } + b3 = 0; + } + b4 = 0; + } + b5 = 0; + } + + /* Pack the bytes */ + packedIn = b1 << 24; + packedIn += b2 << 16; + packedIn += b3 << 8; + packedIn += b4; + + if (bits != 0) { + packedIn = packedIn << bits; + packedIn += b5 >> (8 - bits); + } + + return packedIn; +} + +static int +getACCoefficient(int *rawData, int *coeff, struct comp_info *cinfo, + const struct tree_node *tree) +{ + int input, bits, bytes, tmp_c; + signed char coeffbits = 0; + signed char skip = 0; + + input = getBytes(rawData, cinfo); + bits = getNodeAC(input, &coeffbits, &skip, tree); + + if (coeffbits) { + input = input << (bits - 1); + input &= 0x7fffffff; + if (! (input & 0x40000000)) + input |= 0x80000000; + + tmp_c = input >> (31 - coeffbits); + if (tmp_c < 0) + tmp_c++; + *coeff = tmp_c; + + bits += coeffbits; + } + + bytes = (bits + cinfo->bits) >> 3; + cinfo->bytes += bytes; + cinfo->bits += bits - (bytes << 3); + + return skip; +} + +static void +getDCCoefficient(int *rawData, int *coeff, struct comp_info *cinfo, + const struct tree_node *tree) +{ + int input, bits, bytes, tmp_c; + signed char coeffbits = 0; + + input = getBytes(rawData, cinfo); + bits = getNodeDC(input, &coeffbits, tree); + + if (bits == -1) { + bits = 1; /* Try to re-sync at the next bit */ + *coeff = 0; /* Indicates no change from last DC */ + } else { + + input = input << (bits - 1); + input &= 0x7fffffff; + if (! (input & 0x40000000)) + input |= 0x80000000; + + tmp_c = input >> (31 - coeffbits); + if (tmp_c < 0) + tmp_c++; + *coeff = tmp_c; + + bits += coeffbits; + } + + bytes = (bits + cinfo->bits) >> 3; + cinfo->bytes += bytes; + cinfo->bits += bits - (bytes << 3); +} + +/* For AC coefficients, here is what the "skip" value means: + * -1: Either the 8x4 block has ended, or the decoding failed. + * 0: Use the returned coeff. Don't skip anything. + * 1-15: The next coeffs are zero. The returned coeff is used. + * 16: The next 16 coeffs are zero. The returned coeff is ignored. + * + * You must ensure that the C[] array not be overrun, or stack corruption will + * result. + */ +static void +huffmanDecoderY(int *C, int *pIn, struct comp_info *cinfo) +{ + int coeff = 0; + int i = 1; + int k, skip; + + getDCCoefficient(pIn, C, cinfo, treeYDC); + + i = 1; + do { + skip = getACCoefficient(pIn, &coeff, cinfo, treeYAC); + + if (skip == -1) { + break; + } else if (skip == 0) { + C[i++] = coeff; + } else if (skip == 16) { + k = 16; + if (i > 16) + k = 32 - i; + + while (k--) + C[i++] = 0; + } else { + k = skip; + if (skip > 31 - i) + k = 31 - i; + + while (k--) + C[i++] = 0; + + C[i++] = coeff; + } + } while (i <= 31); + + if (skip == -1) + while (i <= 31) C[i++] = 0; + else + getACCoefficient(pIn, &coeff, cinfo, treeYAC); +} + +/* Same as huffmanDecoderY, except for the tables used */ +static void +huffmanDecoderUV(int *C, int *pIn, struct comp_info *cinfo) +{ + int coeff = 0; + int i = 1; + int k, skip; + + getDCCoefficient(pIn, C, cinfo, treeUVDC); + + i = 1; + do { + skip = getACCoefficient(pIn, &coeff, cinfo, treeUVAC); + + if (skip == -1) { + break; + } else if (skip == 0) { + C[i++] = coeff; + } else if (skip == 16) { + k = 16; + if (i > 16) + k = 32 - i; + + while (k--) + C[i++] = 0; + } else { + k = skip; + if (skip > 31 - i) + k = 31 - i; + + while (k--) + C[i++] = 0; + + C[i++] = coeff; + } + } while (i <= 31); + + if (skip == -1) + while (i <= 31) C[i++] = 0; + else + getACCoefficient(pIn, &coeff, cinfo, treeUVAC); +} + +/****************************************************************************** + * iDCT Functions + ******************************************************************************/ + +#ifndef APPROXIMATE_MUL_BY_SHIFT + +#define IDCT_MESSAGE "iDCT with multiply" + +#define TIMES_16382(u) ((u)? 16382 * (u):0) +#define TIMES_23168(u) ((u)? 23168 * (u):0) +#define TIMES_30270(u) ((u)? 30270 * (u):0) +#define TIMES_41986(u) ((u)? 41986 * (u):0) +#define TIMES_35594(u) ((u)? 35594 * (u):0) +#define TIMES_23783(u) ((u)? 23783 * (u):0) +#define TIMES_8351(u) ((u)? 8351 * (u):0) +#define TIMES_17391(u) ((u)? 17391 * (u):0) +#define TIMES_14743(u) ((u)? 14743 * (u):0) +#define TIMES_9851(u) ((u)? 9851 * (u):0) +#define TIMES_3459(u) ((u)? 3459 * (u):0) +#define TIMES_32134(u) ((u)? 32134 * (u):0) +#define TIMES_27242(u) ((u)? 27242 * (u):0) +#define TIMES_18202(u) ((u)? 18202 * (u):0) +#define TIMES_6392(u) ((u)? 6392 * (u):0) +#define TIMES_39550(u) ((u)? 39550 * (u):0) +#define TIMES_6785(u) ((u)? 6785 * (u):0) +#define TIMES_12538(u) ((u)? 12538 * (u):0) + +#else + +#define IDCT_MESSAGE "iDCT with shift" + +#define TIMES_16382(u) ( (u)? x=(u) , (x<<14) - (x<<1) :0 ) +#define TIMES_23168(u) ( (u)? x=(u) , (x<<14) + (x<<12) + (x<<11) + (x<<9) :0 ) +#define TIMES_30270(u) ( (u)? x=(u) , (x<<15) - (x<<11) :0 ) +#define TIMES_41986(u) ( (u)? x=(u) , (x<<15) + (x<<13) + (x<<10) :0 ) +#define TIMES_35594(u) ( (u)? x=(u) , (x<<15) + (x<<11) + (x<<9) + (x<<8) :0 ) +#define TIMES_23783(u) ( (u)? x=(u) , (x<<14) + (x<<13) - (x<<9) - (x<<8) :0 ) +#define TIMES_8351(u) ( (u)? x=(u) , (x<<13) :0 ) +#define TIMES_17391(u) ( (u)? x=(u) , (x<<14) + (x<<10) :0 ) +#define TIMES_14743(u) ( (u)? x=(u) , (x<<14) - (x<<10) - (x<<9) :0 ) +#define TIMES_9851(u) ( (u)? x=(u) , (x<<13) + (x<<10) + (x<<9) :0 ) +#define TIMES_3459(u) ( (u)? x=(u) , (x<<12) - (x<<9) :0 ) +#define TIMES_32134(u) ( (u)? x=(u) , (x<<15) - (x<<9) :0 ) +#define TIMES_27242(u) ( (u)? x=(u) , (x<<14) + (x<<13) + (x<<11) + (x<<9) :0 ) +#define TIMES_18202(u) ( (u)? x=(u) , (x<<14) + (x<<11) - (x<<8) :0 ) +#define TIMES_6392(u) ( (u)? x=(u) , (x<<13) - (x<<11) + (x<<8) :0 ) +#define TIMES_39550(u) ( (u)? x=(u) , (x<<15) + (x<<12) + (x<<11) + (x<<9) :0 ) +#define TIMES_6785(u) ( (u)? x=(u) , (x<<12) + (x<<11) + (x<<9) :0 ) +#define TIMES_12538(u) ( (u)? x=(u) , (x<<13) + (x<<12) + (x<<8) :0 ) + +/* + * The variables C0, C4, C16 and C20 can also be removed from the algorithm + * if APPROXIMATE_MUL_BY_SHIFTS is defined. They store correction values + * and can be considered insignificant. + */ + +#endif + +static void +DCT_8x4(int *coeff, unsigned char *out) +/* pre: coeff == coefficients + post: coeff != coefficients + ** DO NOT ASSUME coeff TO BE THE SAME BEFORE AND AFTER CALLING THIS FUNCTION! +*/ +{ + register int base,val1,val2,val3; + int tmp1,tmp2; + int C0,C4,C16,C20; + int C2_18,C6_22,C1_17,C3_19,C5_21,C7_23; + register int t; +#ifdef APPROXIMATE_MUL_BY_SHIFT + register int x; +#endif + + C0=coeff[0]; + C4=coeff[4]; + C16=coeff[16]; + C20=coeff[20]; + + coeff[0]=TIMES_23168(coeff[0]); + coeff[4]=TIMES_23168(coeff[4]); + coeff[16]=TIMES_23168(coeff[16]); + coeff[20]=TIMES_23168(coeff[20]); + + C2_18 = coeff[2]+coeff[18]; + C6_22 = coeff[6]+coeff[22]; + C1_17 = coeff[1]+coeff[17]; + C3_19 = coeff[3]+coeff[19]; + C5_21 = coeff[5]+coeff[21]; + C7_23 = coeff[7]+coeff[23]; + +// 0,7,25,32 + + base = 0x1000000; + base += coeff[0]+coeff[4]+coeff[16]+coeff[20]; + base += TIMES_30270(C2_18); + base += TIMES_12538(C6_22); + + val1 = TIMES_41986(coeff[9]); + val1 += TIMES_35594(coeff[11]); + val1 += TIMES_23783(coeff[13]); + val1 += TIMES_8351(coeff[15]); + val1 += TIMES_17391(coeff[25]); + val1 += TIMES_14743(coeff[27]); + val1 += TIMES_9851(coeff[29]); + val1 += TIMES_3459(coeff[31]); + + val2 = TIMES_32134(C1_17); + val2 += TIMES_27242(C3_19); + val2 += TIMES_18202(C5_21); + val2 += TIMES_6392(C7_23); + + val3 = TIMES_39550(coeff[10]); + val3 += TIMES_16382(coeff[14]+coeff[26]); + val3 += TIMES_6785(coeff[30]); + val3 += TIMES_30270(coeff[8]+coeff[12]); + val3 += TIMES_12538(coeff[24]+coeff[28]); + + t=(base + val1 + val2 + val3) >> 17; + out[0]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3 - C4 - C20) >> 17; + out[7]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3 - C16- C20) >> 17; + out[24]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3 - C4 - C16 - C20) >> 17; + out[31]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + +//1,6,25,30 + + base = 0x1000000; + base += coeff[0]-coeff[4]+coeff[16]-coeff[20]; + base += TIMES_12538(C2_18); + base -= TIMES_30270(C6_22); + + val1 = TIMES_35594(coeff[9]); + val1 -= TIMES_8351(coeff[11]); + val1 -= TIMES_41986(coeff[13]); + val1 -= TIMES_23783(coeff[15]); + val1 -= TIMES_14743(coeff[25]); + val1 -= TIMES_3459(coeff[27]); + val1 -= TIMES_17391(coeff[29]); + val1 -= TIMES_9851(coeff[31]); + + val2 = TIMES_27242(C1_17); + val2 -= TIMES_6392(C3_19); + val2 -= TIMES_32134(C5_21); + val2 -= TIMES_18202(C7_23); + + val3 = TIMES_16382(coeff[10]-coeff[30]); + val3 -= TIMES_39550(coeff[14]); + val3 += TIMES_6785(coeff[26]); + val3 += TIMES_12538(coeff[24]-coeff[28]); + val3 += TIMES_30270(coeff[8]-coeff[12]); + + t=(base + val1 + val2 + val3 + C4 + C20) >> 17; + out[1]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3) >> 17; + out[6]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3 + C4 - C16 + C20) >> 17; + out[25]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3 + C20) >> 17; + out[30]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + +//2,5,26,29 + + base = 0x1000000; + base += coeff[0] - coeff[4] + coeff[16] - coeff[20]; + base -= TIMES_12538(C2_18); + base += TIMES_30270(C6_22); + + val1 = TIMES_23783(coeff[9]); + val1 -= TIMES_41986(coeff[11]); + val1 += TIMES_8351(coeff[13]); + val1 += TIMES_35594(coeff[15]); + val1 += TIMES_9851(coeff[25]); + val1 -= TIMES_17391(coeff[27]); + val1 += TIMES_3459(coeff[29]); + val1 += TIMES_14743(coeff[31]); + + val2 = TIMES_18202(C1_17); + val2 -= TIMES_32134(C3_19); + val2 += TIMES_6392(C5_21); + val2 += TIMES_27242(C7_23); + + val3 = -TIMES_16382(coeff[10] - coeff[30]); + val3 += TIMES_39550(coeff[14]); + val3 -= TIMES_6785(coeff[26]); + val3 += TIMES_12538(coeff[24] - coeff[28]); + val3 += TIMES_30270(coeff[8] - coeff[12]); + + t=(base + val1 + val2 + val3) >> 17; + out[2]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3) >> 17; + out[5]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3 - C16) >> 17; + out[26]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3 + C4 - C16 + C20) >> 17; + out[29]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + +//3,4,27,28 + + base = 0x1000000; + base += coeff[0] + coeff[4] + coeff[16] + coeff[20]; + base -= TIMES_30270(C2_18); + base -= TIMES_12538(C6_22); + + val1 = TIMES_8351(coeff[9]); + val1 -= TIMES_23783(coeff[11]); + val1 += TIMES_35594(coeff[13]); + val1 += TIMES_3459(coeff[25]); + val1 -= TIMES_9851(coeff[27]); + val1 += TIMES_14743(coeff[29]); + + val2 = TIMES_6392(C1_17); + val2 -= TIMES_18202(C3_19); + val2 += TIMES_27242(C5_21); + + val3 = -TIMES_39550(coeff[10]); + val3 += TIMES_16382(coeff[14] + coeff[26]); + val3 -= TIMES_6785(coeff[30]); + val3 += TIMES_30270(coeff[8] + coeff[12]); + val3 += TIMES_12538(coeff[24] + coeff[28]); + + tmp1 = TIMES_32134(C7_23); + tmp2 = TIMES_41986(coeff[15]) + TIMES_17391(coeff[31]); + + t=(base + val1 + val2 + val3 - tmp1 - tmp2 - C4 - C20) >> 17; + out[3]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3) >> 17; + out[4]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3 - tmp1 + tmp2) >> 17; + out[27]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3 - C16 - C20) >> 17; + out[28]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + +// Second half + C2_18 = coeff[2] - coeff[18]; + C6_22 = coeff[6] - coeff[22]; + C1_17 = coeff[1] - coeff[17]; + C3_19 = coeff[3] - coeff[19]; + C5_21 = coeff[5] - coeff[21]; + C7_23 = coeff[7] - coeff[23]; + +// 8,15,16,23 + + base = 0x1000000; + base += coeff[0] + coeff[4] - coeff[16] - coeff[20]; + base +=TIMES_30270(C2_18); + base +=TIMES_12538(C6_22); + + val1 = TIMES_17391(coeff[9]); + val1 += TIMES_14743(coeff[11]); + val1 += TIMES_9851(coeff[13]); + val1 += TIMES_3459(coeff[15]); + val1 -= TIMES_41986(coeff[25]); + val1 -= TIMES_35594(coeff[27]); + val1 -= TIMES_23783(coeff[29]); + val1 -= TIMES_8351(coeff[31]); + + val2 = TIMES_32134(C1_17); + val2 += TIMES_27242(C3_19); + val2 += TIMES_18202(C5_21); + val2 += TIMES_6392(C7_23); + + val3 = TIMES_16382(coeff[10] - coeff[30]); + val3 += TIMES_6785(coeff[14]); + val3 -= TIMES_39550(coeff[26]); + val3 -=TIMES_30270(coeff[24] + coeff[28]); + val3 +=TIMES_12538(coeff[8] + coeff[12]); + + t=(base + val1 + val2 + val3) >> 17; + out[8]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3 - C4 + C16 + C20) >> 17; + out[15]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3) >> 17; + out[16]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3 - C4 + C20) >> 17; + out[23]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + +//9,14,17,22 + + base = 0x1000000; + base += coeff[0] - coeff[4] - coeff[16] + coeff[20]; + base += TIMES_12538(C2_18); + base -= TIMES_30270(C6_22); + + val1 = TIMES_14743(coeff[9]); + val1 -= TIMES_3459(coeff[11]); + val1 -= TIMES_17391(coeff[13]); + val1 -= TIMES_9851(coeff[15]); + val1 -= TIMES_35594(coeff[25]); + val1 += TIMES_8351(coeff[27]); + val1 += TIMES_41986(coeff[29]); + val1 += TIMES_23783(coeff[31]); + + val2 = TIMES_27242(C1_17); + val2 -= TIMES_6392(C3_19); + val2 -= TIMES_32134(C5_21); + val2 -= TIMES_18202(C7_23); + + val3 = TIMES_6785(coeff[10]); + val3 -= TIMES_16382(coeff[14] + coeff[26]); + val3 += TIMES_39550(coeff[30]); + val3 += TIMES_12538(coeff[8] - coeff[12]); + val3 -= TIMES_30270(coeff[24] - coeff[28]); + + t=(base + val1 + val2 + val3 + C4 + C16 - C20) >> 17; + out[9]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3 + C16) >> 17; + out[14]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3 + C4) >> 17; + out[17]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3) >> 17; + out[22]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + +//10,13,18,21 + + base = 0x1000000; + base += coeff[0] - coeff[4] - coeff[16] + coeff[20]; + base -= TIMES_12538(C2_18); + base += TIMES_30270(C6_22); + + val1 = TIMES_9851(coeff[9]); + val1 -= TIMES_17391(coeff[11]); + val1 += TIMES_3459(coeff[13]); + val1 += TIMES_14743(coeff[15]); + val1 -= TIMES_23783(coeff[25]); + val1 += TIMES_41986(coeff[27]); + val1 -= TIMES_8351(coeff[29]); + val1 -= TIMES_35594(coeff[31]); + + val2 = TIMES_18202(C1_17); + val2 -= TIMES_32134(C3_19); + val2 += TIMES_6392(C5_21); + val2 += TIMES_27242(C7_23); + + val3 = -TIMES_6785(coeff[10]); + val3 += TIMES_16382(coeff[14]+coeff[26]); + val3 -= TIMES_39550(coeff[30]); + val3 += TIMES_12538(coeff[8]-coeff[12]); + val3 -= TIMES_30270(coeff[24]-coeff[28]); + + t=(base + val1 + val2 + val3) >> 17; + out[10]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3 + C4 + C16 - C20) >> 17; + out[13]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3) >> 17; + out[18]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3 + C4) >> 17; + out[21]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + +// 11,12,19,20 + + base = 0x1000000; + base += coeff[0]+coeff[4]-coeff[16]-coeff[20]; + base -= TIMES_30270(C2_18); + base -= TIMES_12538(C6_22); + + val1 = TIMES_3459(coeff[9]); + val1 -= TIMES_9851(coeff[11]); + val1 += TIMES_14743(coeff[13]); + val1 -= TIMES_8351(coeff[25]); + val1 += TIMES_23783(coeff[27]); + val1 -= TIMES_35594(coeff[29]); + + val2 = TIMES_6392(C1_17); + val2 -= TIMES_18202(C3_19); + val2 += TIMES_27242(C5_21); + + val3 = -TIMES_16382(coeff[10] - coeff[30]); + val3 -= TIMES_6785(coeff[14]); + val3 += TIMES_39550(coeff[26]); + val3 -= TIMES_30270(coeff[24]+coeff[28]); + val3 += TIMES_12538(coeff[8]+coeff[12]); + + tmp1 = TIMES_32134(C7_23); + tmp2 = -TIMES_17391(coeff[15]) + TIMES_41986(coeff[31]); + + t=(base + val1 + val2 + val3 - tmp1 + tmp2 + C16 + C20) >> 17; + out[11]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 - val2 + val3 + C16 + C20) >> 17; + out[12]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base - val1 + val2 - val3 - tmp1 - tmp2 - C4 + C20) >> 17; + out[19]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; + t=(base + val1 - val2 - val3) >> 17; + out[20]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t; +} + +#undef TIMES_16382 +#undef TIMES_23168 +#undef TIMES_30270 +#undef TIMES_41986 +#undef TIMES_35594 +#undef TIMES_23783 +#undef TIMES_8351 +#undef TIMES_17391 +#undef TIMES_14743 +#undef TIMES_9851 +#undef TIMES_3459 +#undef TIMES_32134 +#undef TIMES_27242 +#undef TIMES_18202 +#undef TIMES_6392 +#undef TIMES_39550 +#undef TIMES_6785 +#undef TIMES_12538 + +/****************************************************************************** + * Main Decoder Functions + ******************************************************************************/ + +/* This function handles the decompression of a single 8x4 block. It is + * independent of the palette (YUV422, YUV420, YUV400, GBR422...). cinfo->bytes + * determines the positin in the input buffer. + */ +static int +decompress8x4(unsigned char *pOut, + unsigned char *pIn, + int *lastDC, + int uvFlag, + struct comp_info *cinfo) +{ + int i, x, y, dc; + int coeffs[32]; + int deZigZag[32]; + int *dest; + int *src; + unsigned char *qt = cinfo->qt; + + if (! uvFlag) { + huffmanDecoderY(coeffs, (int*) pIn, cinfo); + + /* iDPCM and dequantize first coefficient */ + dc = (*lastDC) + coeffs[0]; + coeffs[0] = dc * (qt[0] + 1); + *lastDC = dc; + + /* ...and the second coefficient */ + coeffs[1] = ((qt[1] + 1) * coeffs[1]) >> 1; + + /* Dequantize, starting at 3rd element */ + for (i = 2; i < 32; i++) + coeffs[i] = (qt[i] + 1) * coeffs[i]; + } else { + huffmanDecoderUV(coeffs, (int*) pIn, cinfo); + + /* iDPCM */ + dc = (*lastDC) + coeffs[0]; + coeffs[0] = dc; + *lastDC = dc; + + /* Dequantize */ + for (i = 0; i < 32; i++) + coeffs[i] = (qt[32 + i] + 1) * coeffs[i]; + } + + /* Dezigzag */ + for (i = 0; i < 32; i++) + deZigZag[i] = coeffs[ZigZag518[i]]; + + /* Transpose the dezigzagged coefficient matrix */ + src = deZigZag; + dest = coeffs; + for (y = 0; y <= 3; ++y) { + for (x = 0; x <= 7; ++x) { + dest[x] = src[x * 4]; + } + src += 1; + dest += 8; + } + + /* Do the inverse DCT transform */ + DCT_8x4(coeffs, pOut); + + return 0; /* Always returns 0 */ +} + +static inline void +copyBlock(unsigned char *src, unsigned char *dest, int destInc) +{ + int i; + unsigned int *pSrc, *pDest; + + for (i = 0; i <= 3; i++) { + pSrc = (unsigned int *) src; + pDest = (unsigned int *) dest; + pDest[0] = pSrc[0]; + pDest[1] = pSrc[1]; + src += 8; + dest += destInc; + } +} + +static inline int +decompress400NoMMXOV518(unsigned char *pIn, + unsigned char *pOut, + unsigned char *pTmp, + const int w, + const int h, + const int numpix, + struct comp_info *cinfo) +{ + int iOutY, x, y; + int lastYDC = 0; + + /* Start Y loop */ + y = 0; + do { + iOutY = w * y; + x = 0; + do { + decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo); + copyBlock(pTmp, pOut + iOutY, w); + iOutY += 8; + x += 8; + } while (x < w); + y += 4; + } while (y < h); + + /* Did we decode too much? */ + if (cinfo->bytes > cinfo->rawLen + 897) + return 1; + + /* Did we decode enough? */ + if (cinfo->bytes >= cinfo->rawLen - 897) + return 0; + else + return 1; +} + +static inline int +decompress420NoMMXOV518(unsigned char *pIn, + unsigned char *pOut, + unsigned char *pTmp, + const int w, + const int h, + const int numpix, + struct comp_info *cinfo) +{ + unsigned char *pOutU = pOut + numpix; + unsigned char *pOutV = pOutU + numpix / 4; + int iOutY, iOutU, iOutV, x, y; + int lastYDC = 0; + int lastUDC = 0; + int lastVDC = 0; + + /* Start Y loop */ + y = 0; + do { + iOutY = w * y; + iOutV = iOutU = iOutY / 4; + + x = 0; + do { + decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo); + copyBlock(pTmp, pOut + iOutY, w); + iOutY += 8; + x += 8; + } while (x < w); + + + + iOutY = w * (y + 4); + x = 0; + do { + decompress8x4(pTmp, pIn, &lastUDC, 1, cinfo); + copyBlock(pTmp, pOutU + iOutU, w/2); + iOutU += 8; + + decompress8x4(pTmp, pIn, &lastVDC, 1, cinfo); + copyBlock(pTmp, pOutV + iOutV, w/2); + iOutV += 8; + + decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo); + copyBlock(pTmp, pOut + iOutY, w); + iOutY += 8; + + decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo); + copyBlock(pTmp, pOut + iOutY, w); + iOutY += 8; + + x += 16; + } while (x < w); + + y += 8; + } while (y < h); + + /* Did we decode too much? */ + if (cinfo->bytes > cinfo->rawLen + 897) + return 1; + + /* Did we decode enough? */ + if (cinfo->bytes >= cinfo->rawLen - 897) + return 0; + else + return 1; +} + +/* Get quantization tables from static arrays + * Returns: <0 if error, or >=0 otherwise */ +static int +get_qt_static(struct comp_info *cinfo) +{ + unsigned char qtY[] = OV518_YQUANTABLE; + unsigned char qtUV[] = OV518_UVQUANTABLE; + unsigned char qt[64]; + + memcpy(qt, qtY, 32); + memcpy(qt + 32, qtUV, 32); + cinfo->qt = qt; + + return 0; +} + + +/* Get quantization tables from input + * Returns: <0 if error, or >=0 otherwise */ +static int +get_qt_dynamic(unsigned char *pIn, struct comp_info *cinfo) +{ + int rawLen = cinfo->rawLen; + + /* Make sure input is actually big enough to hold trailer */ + if (rawLen < 72) { + PDEBUG(1, "Not enough input to decompress"); + return -EINVAL; + } + + cinfo->qt = pIn + rawLen - 64; + + print_qt(cinfo->qt); + + return 0; +} + +/* Input format is raw isoc. data (with intact SOF header, packet numbers + * stripped, and all-zero blocks removed). + * Output format is planar YUV400 + * Returns uncompressed data length if success, or zero if error + */ +static int +Decompress400(unsigned char *pIn, + unsigned char *pOut, + unsigned char *pTmp, + int w, + int h, + int inSize) +{ + struct comp_info cinfo; + int numpix = w * h; + + PDEBUG(4, "%dx%d pIn=%p pOut=%p pTmp=%p inSize=%d", w, h, pIn, pOut, + pTmp, inSize); + + cinfo.bytes = 0; + cinfo.bits = 0; + cinfo.rawLen = inSize; + + if (staticquant) { + if (get_qt_static(&cinfo) < 0) + return 0; + } else { + if (get_qt_dynamic(pIn, &cinfo) < 0) + return 0; + } + + /* Decompress, skipping the 8-byte SOF header */ + if (decompress400NoMMXOV518(pIn + 8, pOut, pTmp, w, h, numpix, &cinfo)) +// return 0; + ; /* Don't return error yet */ + + return (numpix); +} + +/* Input format is raw isoc. data (with intact SOF header, packet numbers + * stripped, and all-zero blocks removed). + * Output format is planar YUV420 + * Returns uncompressed data length if success, or zero if error + */ +static int +Decompress420(unsigned char *pIn, + unsigned char *pOut, + unsigned char *pTmp, + int w, + int h, + int inSize) +{ + struct comp_info cinfo; + int numpix = w * h; + + PDEBUG(4, "%dx%d pIn=%p pOut=%p pTmp=%p inSize=%d", w, h, pIn, pOut, + pTmp, inSize); + + cinfo.bytes = 0; + cinfo.bits = 0; + cinfo.rawLen = inSize; + + if (staticquant) { + if (get_qt_static(&cinfo) < 0) + return 0; + } else { + if (get_qt_dynamic(pIn, &cinfo) < 0) + return 0; + } + + /* Decompress, skipping the 8-byte SOF header */ + if (decompress420NoMMXOV518(pIn + 8, pOut, pTmp, w, h, numpix, &cinfo)) +// return 0; + ; /* Don't return error yet */ + + return (numpix * 3 / 2); +} + +/****************************************************************************** + * Module Functions + ******************************************************************************/ + +static struct ov51x_decomp_ops decomp_ops = { + .decomp_400 = Decompress400, + .decomp_420 = Decompress420, + .owner = THIS_MODULE, +}; + +static int __init +decomp_init(void) +{ + int rc; + + rc = ov511_register_decomp_module(DECOMP_INTERFACE_VER, &decomp_ops, + ov518, mmx); + if (rc) { + err("Could not register with ov511 (rc=%d)", rc); + return -1; + } + + info(DRIVER_VERSION " : " DRIVER_DESC); + PDEBUG(1, "Using %s, %s quantization", IDCT_MESSAGE, + staticquant ? "static" : "dynamic"); + + return 0; +} + +static void __exit +decomp_exit(void) +{ + ov511_deregister_decomp_module(ov518, mmx); + info("deregistered"); +} + +module_init(decomp_init); +module_exit(decomp_exit); --- linux-2.6.27.orig/ubuntu/misc/media/ov511/ov511_decomp.c +++ linux-2.6.27/ubuntu/misc/media/ov511/ov511_decomp.c @@ -0,0 +1,581 @@ +/* OV511 Decompression Support Module + * + * Copyright (c) 1999-2003 Mark W. McClelland. All rights reserved. + * http://alpha.dyndns.org/ov511/ + * + * Original decompression code Copyright 1998-2000 OmniVision Technologies + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + */ + + +#if defined(OUTSIDE_KERNEL) + #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS + #endif + + #include + + #ifdef MODVERSIONS + #include + #endif +#else + #include +#endif + +#include +#include + +#include "ov511.h" + +/****************************************************************************** + * Version Information + ******************************************************************************/ + +#define DRIVER_VERSION "v1.6" +#define DRIVER_AUTHOR "Mark McClelland , OmniVision \ +Technologies " +#define DRIVER_DESC "OV511 Decompression Module" + +/****************************************************************************** + * Prototypes + ******************************************************************************/ + +extern int ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, + int ov518, int mmx); +extern void ov511_deregister_decomp_module(int ov518, int mmx); + +/****************************************************************************** + * Decompression Module Interface Constants + ******************************************************************************/ + +static const int interface_ver = DECOMP_INTERFACE_VER; +static const int ov518 = 0; +static const int mmx = 0; + +/****************************************************************************** + * Module Features + ******************************************************************************/ + +static int debug; + +module_param(debug, uint, 0400); +MODULE_PARM_DESC(debug, + "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max"); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +#if defined(MODULE_LICENSE) /* Introduced in ~2.4.10 */ +MODULE_LICENSE("GPL"); +#endif + +/****************************************************************************** + * Decompression Functions + ******************************************************************************/ + +static void +DecompressYHI(unsigned char *pIn, + unsigned char *pOut, + int *iIn, /* in/out */ + int *iOut, /* in/out */ + const int w, + const int YUVFlag) +{ + short ZigZag[64]; + int temp[64]; + int Zcnt_Flag = 0; + int Num8_Flag = 0; + int in_pos = *iIn; + int out_pos = *iOut; + int tmp, tmp1, tmp2, tmp3; + unsigned char header, ZTable[64]; + short tmpl, tmph, half_byte, idx, count; + unsigned long ZigZag_length = 0, ZT_length, i, j; + short DeZigZag[64]; + + const short a = 11584; + const short b = 16068; + const short c = 15136; + const short d = 13624; + const short e = 9104; + const short f = 6270; + const short g = 3196; + + int out_idx; + + /* Take off every 'Zig' */ + for (i = 0; i < 64; i++) { + ZigZag[i] = 0; + } + + /***************************** + * Read in the Y header byte * + *****************************/ + + header = pIn[in_pos]; + in_pos++; + + ZigZag_length = header & 0x3f; + ZigZag_length = ZigZag_length + 1; + + Num8_Flag = header & 0x40; + Zcnt_Flag = header & 0x80; + + /************************* + * Read in the Y content * + *************************/ + + if (Zcnt_Flag == 0) { /* Without Zero Table read contents directly */ + /* Read in ZigZag[0] */ + ZigZag[0] = pIn[in_pos++]; + tmpl = pIn[in_pos++]; + tmph = tmpl<<8; + ZigZag[0] = ZigZag[0] | tmph; + ZigZag[0] = ZigZag[0]<<4; + ZigZag[0] = ZigZag[0]>>4; + + if (Num8_Flag) { /* 8 Bits */ + for (i = 1; i < ZigZag_length; i++) { + ZigZag[i] = pIn[in_pos++]; + ZigZag[i] = ZigZag[i]<<8; + ZigZag[i] = ZigZag[i]>>8; + } + } else { /* 12 bits and has no Zero Table */ + idx = 1; + half_byte = 0; + for (i = 1; i < ZigZag_length; i++) { + if (half_byte == 0) { + ZigZag[i] = pIn[in_pos++]; + tmpl = pIn[in_pos++]; + tmph = tmpl<<8; + tmph = tmph&0x0f00; + ZigZag[i] = ZigZag[i] | tmph; + ZigZag[i] = ZigZag[i]<<4; + ZigZag[i] = ZigZag[i]>>4; + half_byte = 1; + } else { + ZigZag[i] = pIn[in_pos++]; + ZigZag[i] = ZigZag[i]<<8; + tmpl = tmpl & 0x00f0; + ZigZag[i] = ZigZag[i] | tmpl; + ZigZag[i] = ZigZag[i]>>4; + half_byte = 0; + } + } + } + } else { /* Has Zero Table */ + /* Calculate Z-Table length */ + ZT_length = ZigZag_length/8; + tmp = ZigZag_length%8; + + if (tmp > 0) { + ZT_length = ZT_length + 1; + } + + /* Read in Zero Table */ + for (j = 0; j < ZT_length; j++) { + ZTable[j] = pIn[in_pos++]; + } + + /* Read in ZigZag[0] */ + ZigZag[0] = pIn[in_pos++]; + tmpl = pIn[in_pos++]; + tmph = tmpl<<8; + ZigZag[0] = ZigZag[0] | tmph; + ZigZag[0] = ZigZag[0]<<4; + ZigZag[0] = ZigZag[0]>>4; + + /* Decode ZigZag */ + idx = 0; + ZTable[idx] = ZTable[idx]<<1; + count = 7; + + if (Num8_Flag) { /* 8 Bits and has zero table */ + for (i = 1; i < ZigZag_length; i++) { + if ((ZTable[idx]&0x80)) { + ZigZag[i] = pIn[in_pos++]; + ZigZag[i] = ZigZag[i]<<8; + ZigZag[i] = ZigZag[i]>>8; + } + + ZTable[idx]=ZTable[idx]<<1; + count--; + if (count == 0) { + count = 8; + idx++; + } + } + } else { /* 12 bits and has Zero Table */ + half_byte = 0; + for (i = 1; i < ZigZag_length; i++) { + if (ZTable[idx]&0x80) { + if (half_byte == 0) { + ZigZag[i] = pIn[in_pos++]; + tmpl = pIn[in_pos++]; + tmph = tmpl <<8; + tmph = tmph & 0x0f00; + ZigZag[i] = ZigZag[i] | tmph; + ZigZag[i] = ZigZag[i]<<4; + ZigZag[i] = ZigZag[i]>>4; + half_byte = 1; + } else { + ZigZag[i] = pIn[in_pos++]; + ZigZag[i] = ZigZag[i]<<8; + tmpl = tmpl & 0x00f0; + ZigZag[i] = ZigZag[i] | tmpl; + ZigZag[i] = ZigZag[i]>>4; + half_byte = 0; + } + } + + ZTable[idx] = ZTable[idx]<<1; + count--; + if (count == 0) { + count = 8; + idx++; + } + } + } + } + + /************* + * De-ZigZag * + *************/ + + for (j = 0; j < 64; j++) { + DeZigZag[j] = 0; + } + + if (YUVFlag == 1) { + DeZigZag[0] = ZigZag[0]; + DeZigZag[1] = ZigZag[1]<<1; + DeZigZag[2] = ZigZag[5]<<1; + DeZigZag[3] = ZigZag[6]<<2; + + DeZigZag[8] = ZigZag[2]<<1; + DeZigZag[9] = ZigZag[4]<<1; + DeZigZag[10] = ZigZag[7]<<1; + DeZigZag[11] = ZigZag[13]<<2; + + DeZigZag[16] = ZigZag[3]<<1; + DeZigZag[17] = ZigZag[8]<<1; + DeZigZag[18] = ZigZag[12]<<2; + DeZigZag[19] = ZigZag[17]<<2; + + DeZigZag[24] = ZigZag[9]<<2; + DeZigZag[25] = ZigZag[11]<<2; + DeZigZag[26] = ZigZag[18]<<2; + DeZigZag[27] = ZigZag[24]<<3; + } else { + DeZigZag[0] = ZigZag[0]; + DeZigZag[1] = ZigZag[1]<<2; + DeZigZag[2] = ZigZag[5]<<2; + DeZigZag[3] = ZigZag[6]<<3; + + DeZigZag[8] = ZigZag[2]<<2; + DeZigZag[9] = ZigZag[4]<<2; + DeZigZag[10] = ZigZag[7]<<2; + DeZigZag[11] = ZigZag[13]<<4; + + DeZigZag[16] = ZigZag[3]<<2; + DeZigZag[17] = ZigZag[8]<<2; + DeZigZag[18] = ZigZag[12]<<3; + DeZigZag[19] = ZigZag[17]<<4; + + DeZigZag[24] = ZigZag[9]<<3; + DeZigZag[25] = ZigZag[11]<<4; + DeZigZag[26] = ZigZag[18]<<4; + DeZigZag[27] = ZigZag[24]<<4; + } + + /***************** + **** IDCT 1D **** + *****************/ + +#define IDCT_1D(c0, c1, c2, c3, in) \ + do { \ + tmp1=((c0)*DeZigZag[in])+((c2)*DeZigZag[(in)+2]); \ + tmp2=(c1)*DeZigZag[(in)+1]; \ + tmp3=(c3)*DeZigZag[(in)+3]; \ + } while (0) + +#define COMPOSE_1(out1, out2) \ + do { \ + tmp=tmp1+tmp2+tmp3; \ + temp[out1] = tmp>>15; \ + tmp=tmp1-tmp2-tmp3; \ + temp[out2] = tmp>>15; \ + } while (0) + +#define COMPOSE_2(out1, out2) \ + do { \ + tmp=tmp1+tmp2-tmp3; \ + temp[out1] = tmp>>15; \ + tmp=tmp1-tmp2+tmp3; \ + temp[out2] = tmp>>15; \ + } while (0) + + /* j = 0 */ + IDCT_1D(a, b, c, d, 0); COMPOSE_1( 0, 56); + IDCT_1D(a, b, c, d, 8); COMPOSE_1( 1, 57); + IDCT_1D(a, b, c, d, 16); COMPOSE_1( 2, 58); + IDCT_1D(a, b, c, d, 24); COMPOSE_1( 3, 59); + + /* j = 1 */ + IDCT_1D(a, d, f, g, 0); COMPOSE_2( 8, 48); + IDCT_1D(a, d, f, g, 8); COMPOSE_2( 9, 49); + IDCT_1D(a, d, f, g, 16); COMPOSE_2(10, 50); + IDCT_1D(a, d, f, g, 24); COMPOSE_2(11, 51); + + /* j = 2 */ + IDCT_1D(a, e, -f, b, 0); COMPOSE_2(16, 40); + IDCT_1D(a, e, -f, b, 8); COMPOSE_2(17, 41); + IDCT_1D(a, e, -f, b, 16); COMPOSE_2(18, 42); + IDCT_1D(a, e, -f, b, 24); COMPOSE_2(19, 43); + + /* j = 3 */ + IDCT_1D(a, g, -c, e, 0); COMPOSE_2(24, 32); + IDCT_1D(a, g, -c, e, 8); COMPOSE_2(25, 33); + IDCT_1D(a, g, -c, e, 16); COMPOSE_2(26, 34); + IDCT_1D(a, g, -c, e, 24); COMPOSE_2(27, 35); + +#undef IDCT_1D +#undef COMPOSE_1 +#undef COMPOSE_2 + + /***************** + **** IDCT 2D **** + *****************/ + +#define IDCT_2D(c0, c1, c2, c3, in) \ + do { \ + tmp = temp[in]*(c0) + temp[(in)+1]*(c1) \ + + temp[(in)+2]*(c2) + temp[(in)+3]*(c3); \ + } while (0) + +#define STORE(i) \ + do { \ + tmp = tmp >> 15; \ + tmp = tmp + 128; \ + if (tmp > 255) tmp = 255; \ + if (tmp < 0) tmp = 0; \ + pOut[i] = (unsigned char) tmp; \ + } while (0) + +#define IDCT_2D_ROW(in) \ + do { \ + IDCT_2D(a, b, c, d, in); STORE(0+out_idx); \ + IDCT_2D(a, d, f, -g, in); STORE(1+out_idx); \ + IDCT_2D(a, e, -f, -b, in); STORE(2+out_idx); \ + IDCT_2D(a, g, -c, -e, in); STORE(3+out_idx); \ + IDCT_2D(a, -g, -c, e, in); STORE(4+out_idx); \ + IDCT_2D(a, -e, -f, b, in); STORE(5+out_idx); \ + IDCT_2D(a, -d, f, g, in); STORE(6+out_idx); \ + IDCT_2D(a, -b, c, -d, in); STORE(7+out_idx); \ + } while (0) + + +#define IDCT_2D_FAST(c0, c1, c2, c3, in) \ + do { \ + tmp1=((c0)*temp[in])+((c2)*temp[(in)+2]); \ + tmp2=(c1)*temp[(in)+1]; \ + tmp3=(c3)*temp[(in)+3]; \ + } while (0) + +#define STORE_FAST_1(out1, out2) \ + do { \ + tmp=tmp1+tmp2+tmp3; \ + STORE((out1)+out_idx); \ + tmp=tmp1-tmp2-tmp3; \ + STORE((out2)+out_idx); \ + } while (0) + +#define STORE_FAST_2(out1, out2) \ + do { \ + tmp=tmp1+tmp2-tmp3; \ + STORE((out1)+out_idx); \ + tmp=tmp1-tmp2+tmp3; \ + STORE((out2)+out_idx); \ + } while (0) + +#define IDCT_2D_FAST_ROW(in) \ + do { \ + IDCT_2D_FAST(a, b, c, d, in); STORE_FAST_1(0, 7); \ + IDCT_2D_FAST(a, d, f, g, in); STORE_FAST_2(1, 6); \ + IDCT_2D_FAST(a, e, -f, b, in); STORE_FAST_2(2, 5); \ + IDCT_2D_FAST(a, g, -c, e, in); STORE_FAST_2(3, 4); \ + } while (0) + + out_idx = out_pos; + + IDCT_2D_ROW(0); out_idx += w; + IDCT_2D_ROW(8); out_idx += w; + IDCT_2D_ROW(16); out_idx += w; + IDCT_2D_ROW(24); out_idx += w; + IDCT_2D_ROW(32); out_idx += w; + IDCT_2D_ROW(40); out_idx += w; + IDCT_2D_FAST_ROW(48); out_idx += w; + IDCT_2D_FAST_ROW(56); + + *iIn = in_pos; + *iOut = out_pos + 8; +} + +#define DECOMP_Y() DecompressYHI(pIn, pY, &iIn, &iY, w, 1) +#define DECOMP_U() DecompressYHI(pIn, pU, &iIn, &iU, w/2, 2) +#define DECOMP_V() DecompressYHI(pIn, pV, &iIn, &iV, w/2, 2) + +inline static int +Decompress400HiNoMMX(unsigned char *pIn, + unsigned char *pOut, + const int w, + const int h, + const int inSize) +{ + unsigned char *pY = pOut; + int x, y, iIn, iY; + + iIn = 0; + for (y = 0; y < h; y += 8) { + iY = w*y; + + for (x = 0; x < w; x += 8) + DECOMP_Y(); + } + + return 0; +} + +inline static int +Decompress420HiNoMMX(unsigned char *pIn, + unsigned char *pOut, + const int w, + const int h, + const int inSize) +{ + unsigned char *pY = pOut; + unsigned char *pU = pY + w*h; + unsigned char *pV = pU + w*h/4; + int xY, xUV, iY, iU, iV, iIn, count; + const int nBlocks = (w*h) / (32*8); + + iIn = 0; + iY = iU = iV = 0; + xY = xUV = 0; + + for (count = 0; count < nBlocks; count++) { + DECOMP_U(); + DECOMP_V(); xUV += 16; + if (xUV >= w) { + iU += (w*7)/2; + iV += (w*7)/2; + xUV = 0; + } + + DECOMP_Y(); xY += 8; + DECOMP_Y(); xY += 8; + if (xY >= w) { + iY += w*7; + xY = 0; + } + DECOMP_Y(); xY += 8; + DECOMP_Y(); xY += 8; + if (xY >= w) { + iY += w*7; + xY = 0; + } + } + + return 0; +} + +/* Input format is raw isoc. data (with header and packet + * number stripped, and all-zero blocks removed). + * Output format is YUV400 + * Returns uncompressed data length if success, or zero if error + */ +static int +Decompress400(unsigned char *pIn, + unsigned char *pOut, + unsigned char *pTmp, + int w, + int h, + int inSize) +{ + int numpix = w * h; + int rc; + + PDEBUG(4, "%dx%d pIn=%p pOut=%p inSize=%d", w, h, pIn, pOut, inSize); + + rc = Decompress400HiNoMMX(pIn, pOut, w, h, inSize); + + if (rc) + return 0; + + return numpix; +} + +/* Input format is raw isoc. data (with header and packet + * number stripped, and all-zero blocks removed). + * Output format is planar YUV420 + * Returns uncompressed data length if success, or zero if error + */ +static int +Decompress420(unsigned char *pIn, + unsigned char *pOut, + unsigned char *pTmp, + int w, + int h, + int inSize) +{ + int numpix = w * h; + int rc; + + PDEBUG(4, "%dx%d pIn=%p pOut=%p inSize=%d", w, h, pIn, pOut, inSize); + + rc = Decompress420HiNoMMX(pIn, pOut, w, h, inSize); + + if (rc) + return 0; + + return (numpix * 3 / 2); +} + +/****************************************************************************** + * Module Functions + ******************************************************************************/ + +static struct ov51x_decomp_ops decomp_ops = { + .decomp_400 = Decompress400, + .decomp_420 = Decompress420, + .owner = THIS_MODULE, +}; + +static int __init +decomp_init(void) +{ + int rc; + + rc = ov511_register_decomp_module(DECOMP_INTERFACE_VER, &decomp_ops, + ov518, mmx); + if (rc) { + err("Could not register with ov511 (rc=%d)", rc); + return -1; + } + + info(DRIVER_VERSION " : " DRIVER_DESC); + + return 0; +} + +static void __exit +decomp_exit(void) +{ + ov511_deregister_decomp_module(ov518, mmx); + info("deregistered\n"); +} + +module_init(decomp_init); +module_exit(decomp_exit); --- linux-2.6.27.orig/ubuntu/misc/media/ov511/Makefile +++ linux-2.6.27/ubuntu/misc/media/ov511/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_USB_OV511_NEW) += ov511.o ov511_decomp.o ov518_decomp.o --- linux-2.6.27.orig/ubuntu/squashfs/Kconfig +++ linux-2.6.27/ubuntu/squashfs/Kconfig @@ -0,0 +1,50 @@ +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + --- linux-2.6.27.orig/ubuntu/squashfs/BOM +++ linux-2.6.27/ubuntu/squashfs/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=63835 +Current Version: 3.3 --- linux-2.6.27.orig/ubuntu/squashfs/inode.c +++ linux-2.6.27/ubuntu/squashfs/inode.c @@ -0,0 +1,2187 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "squashfs.h" + +int squashfs_cached_blks; + +#ifdef USE_EXPORT +static struct dentry *squashfs_get_parent(struct dentry *child); +#endif + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, +}; + +#ifdef USE_EXPORT +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; +#endif + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + mutex_lock(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + mutex_unlock(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + mutex_unlock(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + mutex_unlock(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + mutex_unlock(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + mutex_unlock(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + mutex_lock(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + mutex_unlock(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + mutex_lock(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + mutex_unlock(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + mutex_unlock(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + mutex_unlock(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + mutex_lock(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + mutex_unlock(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + mutex_unlock(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + +#ifdef USE_EXPORT +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} +#endif + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if (!i) + return ERR_PTR(-ENOMEM); + + if (i->i_state & I_NEW) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->block_cache_mutex); + mutex_init(&msblk->fragment_mutex); + mutex_init(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; +#ifdef USE_EXPORT + s->s_export_op = &squashfs_export_ops; +#endif + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void *foo) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher "); +MODULE_LICENSE("GPL"); --- linux-2.6.27.orig/ubuntu/squashfs/squashfs2_0.c +++ linux-2.6.27/ubuntu/squashfs/squashfs2_0.c @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include +#include +#include +#include +#include +#include + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} --- linux-2.6.27.orig/ubuntu/squashfs/squashfs.h +++ linux-2.6.27/ubuntu/squashfs/squashfs.h @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif --- linux-2.6.27.orig/ubuntu/squashfs/Makefile +++ linux-2.6.27/ubuntu/squashfs/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-objs := inode.o squashfs2_0.o --- linux-2.6.27.orig/ubuntu/compcache/compcache.h +++ linux-2.6.27/ubuntu/compcache/compcache.h @@ -0,0 +1,96 @@ +/* + * Compressed RAM based swap device + * + * (C) 2008 Nitin Gupta + * + * This RAM based block device acts as swap disk. + * Pages swapped to this device are compressed and + * stored in memory. + * + * Released under the terms of the GNU General Public + * License (version 2). See linux/COPYING for more information. + * + * Project home: http://code.google.com/p/compcache + */ + +#ifndef _COMPCACHE_H_ +#define _COMPCACHE_H_ + +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE (1 << SECTOR_SHIFT) +#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) +#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) + +/*-- Configurable parameters */ +/* Default compcache size: 25% of total RAM */ +#define DEFAULT_COMPCACHE_PERCENT 25 +#define INIT_SIZE_BYTES (16 * 1024) +#define GROW_SIZE_BYTES INIT_SIZE_BYTES +/*-- */ + +/* Message prefix */ +#define C "compcache: " + +/* Debugging and Stats */ +#define NOP do { } while(0) + +#if defined(CONFIG_BLK_DEV_COMPCACHE_DEBUG) +#define DEBUG +#endif + +#if defined(CONFIG_BLK_DEV_COMPCACHE_STATS) +#define STATS +#endif + +#if defined(STATS) +#define stat_inc(stat) (stat++) +#define stat_dec(stat) (stat--) +#define stat_set(stat, val) (stat = val) +#define stat_setmax(stat, curr) (stat = (curr) > stat ? (curr) : stat) +#define stat_inc_if_less(stat, val1, val2) \ + (stat += ((val1) < (val2) ? 1 : 0)) +#else /* STATS */ +#define stat_inc(x) NOP +#define stat_dec(x) NOP +#define stat_set(x, v) NOP +#define stat_setmax(x, v) NOP +#define stat_inc_if_less(x, v1, v2) NOP +#endif /* STATS */ + +/*-- Data structures */ +/* Indexed by page no. */ +struct table { + void *addr; + unsigned long len; +}; + +struct compcache { + void *mem_pool; + void *compress_workmem; + void *compress_buffer; + struct table *table; + struct mutex lock; + struct gendisk *disk; + size_t size; /* In sectors */ +}; + +#if defined(STATS) +struct compcache_stats { + u32 num_reads; /* failed + successful */ + u32 num_writes; /* --do-- */ + u32 failed_reads; /* can happen when memory is tooo low */ + u32 failed_writes; /* should NEVER! happen */ + u32 invalid_io; /* non-swap I/O requests */ + u32 good_compress; /* no. of pages with compression + * ratio <= 50%. TODO: export full + * compressed page size histogram */ + u32 pages_expand; /* no. of incompressible pages */ + u32 notify_free; /* count of swap entry free notifications */ + size_t curr_pages; /* current no. of compressed pages */ + size_t curr_mem; /* current total size of compressed pages */ + size_t peak_mem; +}; +#endif +/*-- */ + +#endif --- linux-2.6.27.orig/ubuntu/compcache/Kconfig +++ linux-2.6.27/ubuntu/compcache/Kconfig @@ -0,0 +1,61 @@ +menu "Compcache options" + +config BLK_DEV_COMPCACHE + tristate "Compressed RAM based swap device" + default m + select TLSF + select LZO_COMPRESS + select LZO_DECOMPRESS + help + This creates RAM based block device which acts as swap disk. Pages + swapped to this disk are compressed and stored in memory itself. + Project Home: http://code.google.com/p/compcache/ + +config BLK_DEV_COMPCACHE_DEBUG + default n + depends on BLK_DEV_COMPCACHE + bool "Enable debugging" + help + This causes negligible performance loss and size increase. + If unsure, say Y. + +config BLK_DEV_COMPCACHE_STATS + default n + depends on BLK_DEV_COMPCACHE + bool "Enable statistics" + help + Creates /proc/compcache to export various statistics. + This adds about 4K to size with negligible performance loss. + If unsure, say Y. +endmenu + +menu "Two Level Segregate Fit Allocator" + +config TLSF + tristate "TLSF Allocator" + default m + help + Two Level Segregate Fit Allocator. Its fast and gives low + fragmentation. See: + http://rtportal.upv.es/rtmalloc/ + http://code.google.com/p/compcache/wiki/TLSFAllocator + for more information. + +config TLSF_DEBUG + default n + depends on TLSF + bool "Enable TLSF allocator debugging" + help + Enable TLSF debugging. + This causes negligible performance loss and size increase. + If unusure, say Y. + +config TLSF_STATS + default n + depends on TLSF + bool "Collect TLSF statistics" + help + Creates /proc/tlsfinfo to export various tlsf statistics. + This adds about 30K to size with significant performance loss. + If unsure, say N. +endmenu --- linux-2.6.27.orig/ubuntu/compcache/compcache.txt +++ linux-2.6.27/ubuntu/compcache/compcache.txt @@ -0,0 +1,29 @@ + +compcache: Compressed RAM based swap device +------------------------------------------- + +Project home: http://code.google.com/p/compcache + +* Introduction +This is a RAM based block device which acts as swap disk. +Pages swapped to this device are compressed and stored in +memory itself. + +It uses these components: + - TLSF: memory allocator + - LZO: de/compressor + +* Usage + - modprobe compcache compcache_size_kbytes= + (If no size is specified, default size of 25% of RAM is taken). + - swapon /dev/ramzswap0 + +* Notes + - Allocator and compcache statistics are exported via /proc interface: + (if stats are enabled for corresponding modules) + - /proc/tlsfinfo (from tlsf.ko) + - /proc/compcache (from compcache.ko) + + +Nitin Gupta +(nitingupta910@gmail.com) --- linux-2.6.27.orig/ubuntu/compcache/BOM +++ linux-2.6.27/ubuntu/compcache/BOM @@ -0,0 +1,5 @@ +Downloaded from: http://code.google.com/p/compcache/ +Current Version: Patch for 2.6.26.rc6 + +Moved compcache and tlsf modules to ubuntu/. Only touches swap subsystem +for free page callback. --- linux-2.6.27.orig/ubuntu/compcache/tlsf.c +++ linux-2.6.27/ubuntu/compcache/tlsf.c @@ -0,0 +1,676 @@ +/* + * Two Levels Segregate Fit memory allocator (TLSF) + * Version 2.3.2 + * + * Written by Miguel Masmano Tello + * + * Thanks to Ismael Ripoll for his suggestions and reviews + * + * Copyright (C) 2007, 2006, 2005, 2004 + * + * This code is released using a dual license strategy: GPL/LGPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of the GNU General Public License Version 2.0 + * Released under the terms of the GNU Lesser General Public License Version 2.1 + * + * This is kernel port of TLSF allocator. + * Original code can be found at: http://rtportal.upv.es/rtmalloc/ + * - Nitin Gupta (nitingupta910@gmail.com) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "tlsf_int.h" + +static spinlock_t pool_list_lock; +static struct list_head pool_list_head; + +#if defined(CONFIG_TLSF_STATS) +static struct proc_dir_entry *proc; + +/* Print in format similar to /proc/slabinfo -- easy to awk */ +static void print_tlsfinfo_header(struct seq_file *tlsf) +{ + seq_puts(tlsf, "# Size in kB\n"); + seq_puts(tlsf, "# name " + " "); +#if defined(CONFIG_TLSF_STATS) + seq_puts(tlsf, " " + " " + " "); +#endif +#if defined(CONFIG_TLSF_DEBUG) + seq_puts(tlsf, " "); +#endif + + seq_putc(tlsf, '\n'); +} + +/* Get pool no. (*pos) from pool list */ +static void *tlsf_start(struct seq_file *tlsf, loff_t *pos) +{ + struct list_head *lp; + loff_t p = *pos; + + spin_lock(&pool_list_lock); + if (!p) + return SEQ_START_TOKEN; + + list_for_each(lp, &pool_list_head) { + if (!--p) + return lp; + } + + return NULL; +} + +/* Get pool next to the one given by tlsf_start()/previous tlsf_next() */ +static void *tlsf_next(struct seq_file *tlsf, void *v, loff_t *pos) +{ + struct list_head *lp; + + if (v == SEQ_START_TOKEN) + lp = &pool_list_head; + else + lp = v; + + lp = lp->next; + if (lp == &pool_list_head) + return NULL; + + ++*pos; + return lp; +} + +static void tlsf_stop(struct seq_file *tlsf, void *v) +{ + spin_unlock(&pool_list_lock); +} + +/* Display stats for pool given by tlsf_next() */ +static int tlsf_show(struct seq_file *tlsf, void *v) +{ + struct pool *pool; + size_t used, total; + if (v == SEQ_START_TOKEN) { + print_tlsfinfo_header(tlsf); + return 0; + } + + pool = list_entry(v, struct pool, list); + used = tlsf_get_used_size(pool); + total = tlsf_get_total_size(pool); +#define K(x) ((x) >> 10) + seq_printf(tlsf, "%-16s %6zu %6zu %6zu %6zu %6zu %6zu", + pool->name, + K(pool->init_size), + K(pool->max_size), + K(pool->grow_size), + K(used), + K(total), + K(total - used)); + +#if defined(CONFIG_TLSF_STATS) + seq_printf(tlsf, " %6zu %6zu %6zu %6zu %6zu %6zu %6zu %6zu", + K(pool->peak_used), + K(pool->peak_total), + K(pool->peak_extra), + pool->count_alloc, + pool->count_free, + pool->count_region_alloc, + pool->count_region_free, + pool->count_failed_alloc); +#endif + +#if defined(CONFIG_TLSF_DEBUG) + seq_printf(tlsf, " %u", pool->valid); +#endif + + seq_putc(tlsf, '\n'); + return 0; +} + +static struct seq_operations tlsfinfo_op = { + .start = tlsf_start, + .next = tlsf_next, + .stop = tlsf_stop, + .show = tlsf_show, +}; + +static int tlsfinfo_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &tlsfinfo_op); +} + +static const struct file_operations proc_tlsfinfo_operations = { + .open = tlsfinfo_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#endif /* CONFIG_TLSF_STATS */ + +/* + * Helping functions + */ + +/** + * Returns indexes (fl, sl) of the list used to serve request of size r + */ +static inline void MAPPING_SEARCH(size_t *r, int *fl, int *sl) +{ + int t; + + if (*r < SMALL_BLOCK) { + *fl = 0; + *sl = *r / (SMALL_BLOCK / MAX_SLI); + } else { + t = (1 << (fls(*r) - 1 - MAX_LOG2_SLI)) - 1; + *r = *r + t; + *fl = fls(*r) - 1; + *sl = (*r >> (*fl - MAX_LOG2_SLI)) - MAX_SLI; + *fl -= FLI_OFFSET; + /*if ((*fl -= FLI_OFFSET) < 0) // FL will be always >0! + *fl = *sl = 0; + */ + *r &= ~t; + } +} + +/** + * Returns indexes (fl, sl) which is used as starting point to search + * for a block of size r. It also rounds up requested size(r) to the + * next list. + */ +static inline void MAPPING_INSERT(size_t r, int *fl, int *sl) +{ + if (r < SMALL_BLOCK) { + *fl = 0; + *sl = r / (SMALL_BLOCK / MAX_SLI); + } else { + *fl = fls(r) - 1; + *sl = (r >> (*fl - MAX_LOG2_SLI)) - MAX_SLI; + *fl -= FLI_OFFSET; + } +} + +/** + * Returns first block from a list that hold blocks larger than or + * equal to the one pointed by the indexes (fl, sl) + */ +static inline struct bhdr *FIND_SUITABLE_BLOCK(struct pool *p, int *fl, + int *sl) +{ + u32 tmp = p->sl_bitmap[*fl] & (~0 << *sl); + struct bhdr *b = NULL; + + if (tmp) { + *sl = ffs(tmp) - 1; + b = p->matrix[*fl][*sl]; + } else { + *fl = ffs(p->fl_bitmap & (~0 << (*fl + 1))) - 1; + if (*fl > 0) { /* likely */ + *sl = ffs(p->sl_bitmap[*fl]) - 1; + b = p->matrix[*fl][*sl]; + } + } + return b; +} + +/** + * Remove first free block(b) from free list with indexes (fl, sl). + */ +static inline void EXTRACT_BLOCK_HDR(struct bhdr *b, struct pool *p, int fl, + int sl) +{ + p->matrix[fl][sl] = b->ptr.free_ptr.next; + if (p->matrix[fl][sl]) + p->matrix[fl][sl]->ptr.free_ptr.prev = NULL; + else { + clear_bit(sl, (void *)&p->sl_bitmap[fl]); + if(!p->sl_bitmap[fl]) + clear_bit (fl, (void *)&p->fl_bitmap); + } + b->ptr.free_ptr = (struct free_ptr) {NULL, NULL}; +} + +/** + * Removes block(b) from free list with indexes (fl, sl) + */ +static inline void EXTRACT_BLOCK(struct bhdr *b, struct pool *p, int fl, + int sl) +{ + if (b->ptr.free_ptr.next) + b->ptr.free_ptr.next->ptr.free_ptr.prev = + b->ptr.free_ptr.prev; + if (b->ptr.free_ptr.prev) + b->ptr.free_ptr.prev->ptr.free_ptr.next = + b->ptr.free_ptr.next; + if (p->matrix[fl][sl] == b) { + p->matrix[fl][sl] = b->ptr.free_ptr.next; + if (!p->matrix[fl][sl]) { + clear_bit(sl, (void *)&p->sl_bitmap[fl]); + if (!p->sl_bitmap[fl]) + clear_bit (fl, (void *)&p->fl_bitmap); + } + } + b->ptr.free_ptr = (struct free_ptr) {NULL, NULL}; +} + +/** + * Insert block(b) in free list with indexes (fl, sl) + */ +static inline void INSERT_BLOCK(struct bhdr *b, struct pool *p, int fl, int sl) +{ + b->ptr.free_ptr = (struct free_ptr) {NULL, p->matrix[fl][sl]}; + if (p->matrix[fl][sl]) + p->matrix[fl][sl]->ptr.free_ptr.prev = b; + p->matrix[fl][sl] = b; + set_bit(sl, (void *)&p->sl_bitmap[fl]); + set_bit(fl, (void *)&p->fl_bitmap); +} + +/** + * Region is a virtually contiguous memory region and Pool is + * collection of such regions + */ +static inline void ADD_REGION(void *region, size_t region_size, + struct pool *pool) +{ + int fl, sl; + struct bhdr *b, *lb; + + b = (struct bhdr *)(region); + b->prev_hdr = NULL; + b->size = ROUNDDOWN_SIZE(region_size - 2 * BHDR_OVERHEAD) + | FREE_BLOCK | PREV_USED; + MAPPING_INSERT(b->size & BLOCK_SIZE_MASK, &fl, &sl); + INSERT_BLOCK(b, pool, fl, sl); + /* The sentinel block: allows us to know when we're in the last block */ + lb = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE_MASK); + lb->prev_hdr = b; + lb->size = 0 | USED_BLOCK | PREV_FREE; + pool->used_size += BHDR_OVERHEAD; /* only sentinel block is "used" */ + pool->num_regions++; + stat_inc(pool->count_region_alloc); +} + +/* + * Allocator code start + */ + +/** + * tlsf_create_memory_pool - create dynamic memory pool + * @name: name of the pool + * @get_mem: callback function used to expand pool + * @put_mem: callback function used to shrink pool + * @init_size: inital pool size (in bytes) + * @max_size: maximum pool size (in bytes) - set this as 0 for no limit + * @grow_size: amount of memory (in bytes) added to pool whenever required + * + * All size values are rounded up to next page boundary. + */ +void *tlsf_create_memory_pool(const char *name, + get_memory get_mem, + put_memory put_mem, + size_t init_size, + size_t max_size, + size_t grow_size) +{ + struct pool *pool; + void *region; +#if defined(CONFIG_TLSF_STATS) + size_t used, total; +#endif + + if (max_size) + BUG_ON(max_size < init_size); + + pool = get_mem(ROUNDUP_SIZE(sizeof(*pool))); + if (pool == NULL) + goto out; + memset(pool, 0, ROUNDUP_SIZE(sizeof(*pool))); + + /* Round to next page boundary */ + init_size = ROUNDUP_PAGE(init_size); + max_size = ROUNDUP_PAGE(max_size); + grow_size = ROUNDUP_PAGE(grow_size); + pr_info(T "pool: %p, init_size=%zu, max_size=%zu, grow_size=%zu\n", + pool, init_size, max_size, grow_size); + + /* pool global overhead not included in used size */ + pool->used_size = 0; + + pool->init_size = init_size; + pool->max_size = max_size; + pool->grow_size = grow_size; + pool->get_mem = get_mem; + pool->put_mem = put_mem; + strncpy(pool->name, name, MAX_POOL_NAME_LEN); + pool->name[MAX_POOL_NAME_LEN - 1] = '\0'; +#if defined(CONFIG_TLSF_DEBUG) + pool->valid = 1; +#endif + region = get_mem(init_size); + if (region == NULL) + goto out_region; + ADD_REGION(region, init_size, pool); + pool->init_region = region; + + spin_lock_init(&pool->lock); + + spin_lock(&pool_list_lock); + list_add_tail(&pool->list, &pool_list_head); + spin_unlock(&pool_list_lock); + + /* Pool created: update stats */ + stat_set(used, tlsf_get_used_size(pool)); + stat_set(total, tlsf_get_total_size(pool)); + stat_inc(pool->count_alloc); + stat_setmax(pool->peak_extra, total - used); + stat_setmax(pool->peak_used, used); + stat_setmax(pool->peak_total, total); + + return pool; + +out_region: + put_mem(pool); + +out: + return NULL; +} +EXPORT_SYMBOL_GPL(tlsf_create_memory_pool); + +/** + * tlsf_get_used_size - get memory currently used by given pool + * + * Used memory includes stored data + metadata + internal fragmentation + */ +size_t tlsf_get_used_size(void *mem_pool) +{ + struct pool *pool = (struct pool *)mem_pool; + return pool->used_size; +} +EXPORT_SYMBOL_GPL(tlsf_get_used_size); + +/** + * tlsf_get_total_size - get total memory currently allocated for given pool + * + * This is the total memory currently allocated for this pool which includes + * used size + free size. + * + * (Total - Used) is good indicator of memory efficiency of allocator. + */ +size_t tlsf_get_total_size(void *mem_pool) +{ + size_t total; + struct pool *pool = (struct pool *)mem_pool; + total = ROUNDUP_SIZE(sizeof(*pool)) + + pool->init_size + + (pool->num_regions - 1) * pool->grow_size; + return total; +} +EXPORT_SYMBOL_GPL(tlsf_get_total_size); + +/** + * tlsf_destory_memory_pool - cleanup given pool + * @mem_pool: Pool to be destroyed + * + * Data structures associated with pool are freed. + * All memory allocated from pool must be freed before + * destorying it. + */ +void tlsf_destroy_memory_pool(void *mem_pool) +{ + struct pool *pool; + + if (mem_pool == NULL) + return; + + pool = (struct pool *)mem_pool; + + /* User is destorying without ever allocating from this pool */ + if (tlsf_get_used_size(pool) == BHDR_OVERHEAD) { + pool->put_mem(pool->init_region); + pool->used_size -= BHDR_OVERHEAD; + stat_inc(pool->count_region_free); + } + + /* Check for memory leaks in this pool */ + if (tlsf_get_used_size(pool)) { + pr_warning(T "memory leak in pool: %s (%p). " + "%zu bytes still in use.\n", + pool->name, pool, tlsf_get_used_size(pool)); + +#if defined(CONFIG_TLSF_DEBUG) + pool->valid = 0; + /* Invalid pools stay in list for debugging purpose */ + return; +#endif + } + spin_lock(&pool_list_lock); + list_del_init(&pool->list); + spin_unlock(&pool_list_lock); + pool->put_mem(pool); +} +EXPORT_SYMBOL_GPL(tlsf_destroy_memory_pool); + +/** + * tlsf_malloc - allocate memory from given pool + * @size: no. of bytes + * @mem_pool: pool to allocate from + */ +void *tlsf_malloc(size_t size, void *mem_pool) +{ + struct pool *pool = (struct pool *)mem_pool; + struct bhdr *b, *b2, *next_b, *region; + int fl, sl; + size_t tmp_size; +#if defined(CONFIG_TLSF_STATS) + size_t used, total; +#endif + +#if defined(CONFIG_TLSF_DEBUG) + unsigned int retries = 0; +#endif + + size = (size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(size); + /* Rounding up the requested size and calculating fl and sl */ + + spin_lock(&pool->lock); +retry_find: + MAPPING_SEARCH(&size, &fl, &sl); + + /* Searching a free block */ + if (!(b = FIND_SUITABLE_BLOCK(pool, &fl, &sl))) { +#if defined(CONFIG_TLSF_DEBUG) + /* + * This can happen if there are too many users + * allocating from this pool simultaneously. + */ + if (unlikely(retries == MAX_RETRY_EXPAND)) + goto out_locked; + retries++; +#endif + /* Not found */ + if (size > (pool->grow_size - 2 * BHDR_OVERHEAD)) + goto out_locked; + if (pool->max_size && (pool->init_size + + pool->num_regions * pool->grow_size + > pool->max_size)) + goto out_locked; + spin_unlock(&pool->lock); + if ((region = pool->get_mem(pool->grow_size)) == NULL) + goto out; + spin_lock(&pool->lock); + ADD_REGION(region, pool->grow_size, pool); + goto retry_find; + } + EXTRACT_BLOCK_HDR(b, pool, fl, sl); + + /*-- found: */ + next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE_MASK); + /* Should the block be split? */ + tmp_size = (b->size & BLOCK_SIZE_MASK) - size; + if (tmp_size >= sizeof(struct bhdr) ) { + tmp_size -= BHDR_OVERHEAD; + b2 = GET_NEXT_BLOCK(b->ptr.buffer, size); + + b2->size = tmp_size | FREE_BLOCK | PREV_USED; + b2->prev_hdr = b; + + next_b->prev_hdr = b2; + + MAPPING_INSERT(tmp_size, &fl, &sl); + INSERT_BLOCK(b2, pool, fl, sl); + + b->size = size | (b->size & PREV_STATE); + } else { + next_b->size &= (~PREV_FREE); + b->size &= (~FREE_BLOCK); /* Now it's used */ + } + + pool->used_size += (b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD; + + /* Successful alloc: update stats. */ + stat_set(used, tlsf_get_used_size(pool)); + stat_set(total, tlsf_get_total_size(pool)); + stat_inc(pool->count_alloc); + stat_setmax(pool->peak_extra, total - used); + stat_setmax(pool->peak_used, used); + stat_setmax(pool->peak_total, total); + + spin_unlock(&pool->lock); + return (void *)b->ptr.buffer; + + /* Failed alloc */ +out_locked: + spin_unlock(&pool->lock); + +out: + stat_inc(pool->count_failed_alloc); + return NULL; +} +EXPORT_SYMBOL_GPL(tlsf_malloc); + +/** + * tlsf_free - free memory from given pool + * @ptr: address of memory to be freed + * @mem_pool: pool to free from + */ +void tlsf_free(void *ptr, void *mem_pool) +{ + struct pool *pool = (struct pool *)mem_pool; + struct bhdr *b, *tmp_b; + int fl = 0, sl = 0; +#if defined(CONFIG_TLSF_STATS) + size_t used, total; +#endif + if (unlikely(ptr == NULL)) + return; + + b = (struct bhdr *) ((char *) ptr - BHDR_OVERHEAD); + + spin_lock(&pool->lock); + b->size |= FREE_BLOCK; + pool->used_size -= (b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD; + b->ptr.free_ptr = (struct free_ptr) { NULL, NULL}; + tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE_MASK); + if (tmp_b->size & FREE_BLOCK) { + MAPPING_INSERT(tmp_b->size & BLOCK_SIZE_MASK, &fl, &sl); + EXTRACT_BLOCK(tmp_b, pool, fl, sl); + b->size += (tmp_b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD; + } + if (b->size & PREV_FREE) { + tmp_b = b->prev_hdr; + MAPPING_INSERT(tmp_b->size & BLOCK_SIZE_MASK, &fl, &sl); + EXTRACT_BLOCK(tmp_b, pool, fl, sl); + tmp_b->size += (b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD; + b = tmp_b; + } + tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE_MASK); + tmp_b->prev_hdr = b; + + MAPPING_INSERT(b->size & BLOCK_SIZE_MASK, &fl, &sl); + + if ((b->prev_hdr == NULL) && ((tmp_b->size & BLOCK_SIZE_MASK) == 0)) { + pool->put_mem(b); + pool->num_regions--; + pool->used_size -= BHDR_OVERHEAD; /* sentinel block header */ + stat_inc(pool->count_region_free); + goto out; + } + + INSERT_BLOCK(b, pool, fl, sl); + + tmp_b->size |= PREV_FREE; + tmp_b->prev_hdr = b; +out: + /* Update stats */ + stat_set(used, tlsf_get_used_size(pool)); + stat_set(total, tlsf_get_total_size(pool)); + stat_inc(pool->count_free); + stat_setmax(pool->peak_extra, total - used); + stat_setmax(pool->peak_used, used); + stat_setmax(pool->peak_total, total); + + spin_unlock(&pool->lock); +} +EXPORT_SYMBOL_GPL(tlsf_free); + +/** + * tlsf_calloc - allocate and zero-out memory from given pool + * @size: no. of bytes + * @mem_pool: pool to allocate from + */ +void *tlsf_calloc(size_t nelem, size_t elem_size, void *mem_pool) +{ + void *ptr; + + if (nelem == 0 || elem_size == 0) + return NULL; + + if ((ptr = tlsf_malloc(nelem * elem_size, mem_pool)) == NULL) + return NULL; + memset(ptr, 0, nelem * elem_size); + + return ptr; +} +EXPORT_SYMBOL_GPL(tlsf_calloc); + +static int __init tlsf_init(void) +{ + INIT_LIST_HEAD(&pool_list_head); + spin_lock_init(&pool_list_lock); +#if defined(CONFIG_TLSF_STATS) + proc = create_proc_entry("tlsfinfo", S_IRUGO, NULL); + if (proc) + proc->proc_fops = &proc_tlsfinfo_operations; + else + pr_warning(T "error creating proc entry\n"); +#endif + return 0; +} + +static void __exit tlsf_exit(void) +{ +#if defined(CONFIG_TLSF_STATS) + if (proc) + remove_proc_entry("tlsfinfo", proc->parent); +#endif + return; +} + +module_init(tlsf_init); +module_exit(tlsf_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nitin Gupta "); +MODULE_DESCRIPTION("TLSF Memory Allocator"); --- linux-2.6.27.orig/ubuntu/compcache/compcache.c +++ linux-2.6.27/ubuntu/compcache/compcache.c @@ -0,0 +1,480 @@ +/* + * Compressed RAM based swap device + * + * (C) 2008 Nitin Gupta + * + * This RAM based block device acts as swap disk. + * Pages swapped to this device are compressed and + * stored in memory. + * + * Released under the terms of the GNU General Public + * License (version 2). See linux/COPYING for more information. + * + * Project home: http://code.google.com/p/compcache + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "compcache.h" + +static struct block_device_operations compcache_devops = { + .owner = THIS_MODULE, +}; + +static unsigned int init_done; +static struct compcache compcache; +static unsigned long compcache_size_kbytes; +#if defined(STATS) +static struct compcache_stats stats; +#endif + +#if defined(STATS) +static struct proc_dir_entry *proc; + +static int proc_compcache_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; +#if defined(STATS) + size_t succ_writes; + unsigned int good_compress_perc = 0, no_compress_perc = 0; +#endif + + if (off > 0) { + *eof = 1; + return 0; + } + + len = sprintf(page, + "DiskSize: %8zu kB\n", + compcache.size >> (10 - SECTOR_SHIFT)); +#if defined(STATS) + succ_writes = stats.num_writes - stats.failed_writes; + if (succ_writes) { + good_compress_perc = stats.good_compress * 100 / succ_writes; + no_compress_perc = stats.pages_expand * 100 / succ_writes; + } + +#define K(x) ((x) >> 10) + len += sprintf(page + len, + "NumReads: %8u\n" + "NumWrites: %8u\n" + "FailedReads: %8u\n" + "FailedWrites: %8u\n" + "InvalidIO: %8u\n" + "GoodCompress: %8u %%\n" + "NoCompress: %8u %%\n" + "NotifyFree: %8u\n" + "CurrentPages: %8zu\n" + "CurrentMem: %8zu kB\n" + "PeakMem: %8zu kB\n", + stats.num_reads, + stats.num_writes, + stats.failed_reads, + stats.failed_writes, + stats.invalid_io, + good_compress_perc, + no_compress_perc, + stats.notify_free, + stats.curr_pages, + K(stats.curr_mem), + K(stats.peak_mem)); +#endif + return len; +} +#endif /* STATS */ + +/* + * callback function called when swap_map[offset] == 0 + * i.e page at this swap offset is no longer used + */ +static void notify_swap_entry_free(unsigned long offset) +{ + stat_inc(stats.notify_free); + + /* + * + * This callback happened due to some page being + * freed from swap-cache. This page was not written + * to swap disk. + */ + if (compcache.table[offset].addr == NULL) + return; + + tlsf_free(compcache.table[offset].addr, compcache.mem_pool); + stat_dec(stats.curr_pages); + stat_set(stats.curr_mem, stats.curr_mem - + compcache.table[offset].len); + compcache.table[offset].addr = NULL; + compcache.table[offset].len = 0; +} + +/* Check if request is within bounds and page aligned */ +static inline int valid_swap_request(struct bio *bio) +{ + if (unlikely((bio->bi_sector >= compcache.size) || + (bio->bi_sector & (SECTORS_PER_PAGE - 1)) || + (bio->bi_vcnt != 1) || + (bio->bi_size != PAGE_SIZE) || + (bio->bi_io_vec[0].bv_offset != 0))) + return 0; + return 1; +} + +static int compcache_make_request(struct request_queue *queue, struct bio *bio) +{ + int ret; + size_t clen, page_no; + void *user_mem; + struct page *page; + + if (!valid_swap_request(bio)) { + stat_inc(stats.invalid_io); + goto out_nomap; + } + + page = bio->bi_io_vec[0].bv_page; + page_no = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + + if (unlikely(!init_done) && PageSwapCache(page)) { + swp_entry_t entry = { .val = page_private(page) }; + set_notify_swap_entry_free(swp_type(entry), + notify_swap_entry_free); + init_done = 1; + } + + user_mem = kmap(page); + + if (bio_data_dir(bio) == READ) { + stat_inc(stats.num_reads); + /* + * This is attempt to read before any previous write + * to this location. This happens due to readahead when + * swap device is read from user-space (e.g. during swapon) + */ + if (unlikely(compcache.table[page_no].addr == NULL)) { + pr_debug("Read before write on swap device: " + "sector=%lu, size=%u, offset=%u\n", + (ulong)(bio->bi_sector), + bio->bi_size, + bio->bi_io_vec[0].bv_offset); + memset(user_mem, 0, PAGE_SIZE); + kunmap(page); + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + } + + /* Page is stored uncompressed since its incompressible */ + if (unlikely(compcache.table[page_no].len == PAGE_SIZE)) { + memcpy(user_mem, compcache.table[page_no].addr, + PAGE_SIZE); + kunmap(page); + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + } + + clen = PAGE_SIZE; + ret = lzo1x_decompress_safe( + compcache.table[page_no].addr, + compcache.table[page_no].len, + user_mem, + &clen); + + /* should NEVER happen */ + if (unlikely(ret != LZO_E_OK)) { + pr_err(C "Decompression failed! " + "err=%d, page=%zu, len=%lu\n", ret, page_no, + compcache.table[page_no].len); + stat_inc(stats.failed_reads); + goto out; + } + + kunmap(page); + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + } else { /* Write */ + unsigned char *src = compcache.compress_buffer; + stat_inc(stats.num_writes); + /* + * System swaps to same sector again when the stored page + * is no longer referenced by any process. So, its now safe + * to free the memory that was allocated for this page. + */ + if (compcache.table[page_no].addr) { + tlsf_free(compcache.table[page_no].addr, + compcache.mem_pool); + stat_dec(stats.curr_pages); + stat_set(stats.curr_mem, stats.curr_mem - + compcache.table[page_no].len); + compcache.table[page_no].addr = NULL; + compcache.table[page_no].len = 0; + } + + mutex_lock(&compcache.lock); + ret = lzo1x_1_compress(user_mem, PAGE_SIZE, + src, &clen, compcache.compress_workmem); + if (unlikely(ret != LZO_E_OK)) { + mutex_unlock(&compcache.lock); + pr_err(C "Compression failed! err=%d\n", ret); + compcache.table[page_no].addr = NULL; + compcache.table[page_no].len = 0; + stat_inc(stats.failed_writes); + goto out; + } + + /* Page is incompressible - store it as is */ + if (clen >= PAGE_SIZE) { + pr_debug("Page expand on compression: " + "page=%zu, size=%zu\n", page_no, clen); + clen = PAGE_SIZE; + src = user_mem; + } + + if ((compcache.table[page_no].addr = tlsf_malloc(clen, + compcache.mem_pool)) == NULL) { + mutex_unlock(&compcache.lock); + pr_err(C "Error allocating memory for compressed " + "page: %zu, size=%zu \n", page_no, clen); + compcache.table[page_no].len = 0; + stat_inc(stats.failed_writes); + goto out; + } + + memcpy(compcache.table[page_no].addr, src, clen); + + /* Update stats */ + stat_inc(stats.curr_pages); + stat_set(stats.curr_mem, stats.curr_mem + clen); + stat_setmax(stats.peak_mem, stats.curr_mem); + stat_inc_if_less(stats.pages_expand, PAGE_SIZE - 1, clen); + stat_inc_if_less(stats.good_compress, clen, + PAGE_SIZE / 2 + 1); + mutex_unlock(&compcache.lock); + + compcache.table[page_no].len = clen; + + kunmap(page); + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + } +out: + kunmap(page); +out_nomap: + bio_io_error(bio); + return 0; +} + +static void setup_swap_header(union swap_header *s) +{ + s->info.version = 1; + s->info.last_page = compcache.size >> SECTORS_PER_PAGE_SHIFT; + s->info.nr_badpages = 0; + memcpy(s->magic.magic, "SWAPSPACE2", 10); +} + +static void *get_mem(size_t size) +{ + return __vmalloc(size, GFP_NOIO, PAGE_KERNEL); +} + +static void put_mem(void *ptr) +{ + vfree(ptr); +} + +static int __init compcache_init(void) +{ + int ret; + size_t num_pages; + struct sysinfo i; + + mutex_init(&compcache.lock); + + if (compcache_size_kbytes == 0) { + pr_info(C "compcache size not provided." + " Using default: (%u%% of Total RAM).\n" + "Use compcache_size_kbytes module param to specify" + " custom size\n", DEFAULT_COMPCACHE_PERCENT); + si_meminfo(&i); + compcache_size_kbytes = ((DEFAULT_COMPCACHE_PERCENT * + i.totalram) / 100) << (PAGE_SHIFT - 10); + } + + compcache.size = compcache_size_kbytes << 10; + compcache.size = (compcache.size + PAGE_SIZE - 1) & PAGE_MASK; + pr_info(C "Compressed swap size set to: %zu KB\n", compcache.size >> 10); + compcache.size >>= SECTOR_SHIFT; + + compcache.compress_workmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); + if (compcache.compress_workmem == NULL) { + pr_err(C "Error allocating compressor working memory\n"); + ret = -ENOMEM; + goto fail; + } + + compcache.compress_buffer = kmalloc(2 * PAGE_SIZE, GFP_KERNEL); + if (compcache.compress_buffer == NULL) { + pr_err(C "Error allocating compressor buffer space\n"); + ret = -ENOMEM; + goto fail; + } + + num_pages = compcache.size >> SECTORS_PER_PAGE_SHIFT; + compcache.table = vmalloc(num_pages * sizeof(*compcache.table)); + if (compcache.table == NULL) { + pr_err(C "Error allocating compcache address table\n"); + ret = -ENOMEM; + goto fail; + } + memset(compcache.table, 0, num_pages * sizeof(*compcache.table)); + + compcache.table[0].addr = (void *)get_zeroed_page(GFP_KERNEL); + if (compcache.table[0].addr == NULL) { + pr_err(C "Error allocating swap header page\n"); + ret = -ENOMEM; + goto fail; + } + compcache.table[0].len = PAGE_SIZE; + setup_swap_header((union swap_header *)(compcache.table[0].addr)); + + compcache.disk = alloc_disk(1); + if (compcache.disk == NULL) { + pr_err(C "Error allocating disk structure\n"); + ret = -ENOMEM; + goto fail; + } + + compcache.disk->first_minor = 0; + compcache.disk->fops = &compcache_devops; + /* + * It is named like this to prevent distro installers + * from offering compcache as installation target. They + * seem to ignore all devices beginning with 'ram' + */ + strcpy(compcache.disk->disk_name, "ramzswap0"); + + compcache.disk->major = register_blkdev(0, compcache.disk->disk_name); + if (compcache.disk->major < 0) { + pr_err(C "Cannot register block device\n"); + ret = -EFAULT; + goto fail; + } + + compcache.disk->queue = blk_alloc_queue(GFP_KERNEL); + if (compcache.disk->queue == NULL) { + pr_err(C "Cannot register disk queue\n"); + ret = -EFAULT; + goto fail; + } + + set_capacity(compcache.disk, compcache.size); + blk_queue_make_request(compcache.disk->queue, compcache_make_request); + blk_queue_hardsect_size(compcache.disk->queue, PAGE_SIZE); + add_disk(compcache.disk); + + compcache.mem_pool = tlsf_create_memory_pool("compcache", + get_mem, put_mem, + INIT_SIZE_BYTES, 0, GROW_SIZE_BYTES); + if (compcache.mem_pool == NULL) { + pr_err(C "Error creating memory pool\n"); + ret = -ENOMEM; + goto fail; + } + +#if defined(STATS) + proc = create_proc_entry("compcache", S_IRUGO, NULL); + if (proc) + proc->read_proc = &proc_compcache_read; + else { + ret = -ENOMEM; + pr_warning(C "Error creating proc entry\n"); + goto fail; + } +#endif + + pr_debug(C "Initialization done!\n"); + return 0; + +fail: + if (compcache.disk != NULL) { + if (compcache.disk->major > 0) + unregister_blkdev(compcache.disk->major, + compcache.disk->disk_name); + del_gendisk(compcache.disk); + } + + free_page((unsigned long)compcache.table[0].addr); + kfree(compcache.compress_workmem); + kfree(compcache.compress_buffer); + vfree(compcache.table); + tlsf_destroy_memory_pool(compcache.mem_pool); +#if defined(STATS) + if (proc) + remove_proc_entry("compcache", proc->parent); +#endif + pr_err(C "Initialization failed: err=%d\n", ret); + return ret; +} + +static void __exit compcache_exit(void) +{ + size_t i, num_pages; + num_pages = compcache.size >> SECTORS_PER_PAGE_SHIFT; + + unregister_blkdev(compcache.disk->major, compcache.disk->disk_name); + del_gendisk(compcache.disk); + free_page((unsigned long)compcache.table[0].addr); + kfree(compcache.compress_workmem); + kfree(compcache.compress_buffer); + + /* Free all pages that are still in compcache */ + for (i = 1; i < num_pages; i++) + if (compcache.table[i].addr) + tlsf_free(compcache.table[i].addr, compcache.mem_pool); + vfree(compcache.table); + tlsf_destroy_memory_pool(compcache.mem_pool); + +#if defined(STATS) + remove_proc_entry("compcache", proc->parent); +#endif + pr_debug("cleanup done!\n"); +} + +#ifndef MODULE +static int __init compcache_size_setup(char *str) +{ + if (str) + compcache_size_kbytes = strtoul(str, NULL, 10); + return 1; +} + +__setup("compcache_size_kbytes=", compcache_size_setup); +#endif + +module_param(compcache_size_kbytes, ulong, 0); +MODULE_PARM_DESC(compcache_size_kbytes, "compcache device size (in KB)"); + +module_init(compcache_init); +module_exit(compcache_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nitin Gupta "); +MODULE_DESCRIPTION("Compressed RAM Based Swap Device"); --- linux-2.6.27.orig/ubuntu/compcache/Makefile +++ linux-2.6.27/ubuntu/compcache/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_BLK_DEV_COMPCACHE) += compcache.o +obj-$(CONFIG_TLSF) += tlsf.o --- linux-2.6.27.orig/ubuntu/compcache/tlsf_int.h +++ linux-2.6.27/ubuntu/compcache/tlsf_int.h @@ -0,0 +1,145 @@ +/* + * To be used internally by TLSF allocator. + */ + +#ifndef _TLSF_INT_H_ +#define _TLSF_INT_H_ + +#include +#include + +/* Debugging and Stats */ +#define NOP do { } while(0) + +#if defined(CONFIG_TLSF_STATS) +#define stat_inc(stat) (stat++) +#define stat_set(stat, val) (stat = val) +#define stat_setmax(stat, curr) (stat = (curr) > stat ? (curr) : stat) + +#else /* STATS */ +#define stat_inc(x) NOP +#define stat_dec(x) NOP +#define stat_set(x, v) NOP +#define stat_setmax(x, v) NOP +#endif /* STATS */ + +/* Messsage prefix */ +#define T "TLSF: " + +#define MAX_POOL_NAME_LEN 16 + +/*-- TLSF structures */ + +/* Some IMPORTANT TLSF parameters */ +#define MEM_ALIGN (sizeof(void *) * 2) +#define MEM_ALIGN_MASK (~(MEM_ALIGN - 1)) + +#define MAX_FLI (30) +#define MAX_LOG2_SLI (5) +#define MAX_SLI (1 << MAX_LOG2_SLI) + +#define FLI_OFFSET (6) +/* tlsf structure just will manage blocks bigger than 128 bytes */ +#define SMALL_BLOCK (128) +#define REAL_FLI (MAX_FLI - FLI_OFFSET) +#define MIN_BLOCK_SIZE (sizeof(struct free_ptr)) +#define BHDR_OVERHEAD (sizeof(struct bhdr) - MIN_BLOCK_SIZE) + +#define PTR_MASK (sizeof(void *) - 1) +#define BLOCK_SIZE_MASK (0xFFFFFFFF - PTR_MASK) + +#define GET_NEXT_BLOCK(addr, r) ((struct bhdr *) \ + ((char *)(addr) + (r))) +#define ROUNDUP_SIZE(r) (((r) + MEM_ALIGN - 1) & MEM_ALIGN_MASK) +#define ROUNDDOWN_SIZE(r) ((r) & MEM_ALIGN_MASK) +#define ROUNDUP_PAGE(r) (((r) + PAGE_SIZE - 1) & PAGE_MASK) + +#define BLOCK_STATE (0x1) +#define PREV_STATE (0x2) + +/* bit 0 of the block size */ +#define FREE_BLOCK (0x1) +#define USED_BLOCK (0x0) + +/* bit 1 of the block size */ +#define PREV_FREE (0x2) +#define PREV_USED (0x0) + +#if defined(CONFIG_TLSF_DEBUG) +#define MAX_RETRY_EXPAND 10 +#endif + +struct free_ptr { + struct bhdr *prev; + struct bhdr *next; +}; + +struct bhdr { + /* All blocks in a region are linked in order of physical address */ + struct bhdr *prev_hdr; + /* + * The size is stored in bytes + * bit 0: block is free, if set + * bit 1: previous block is free, if set + */ + u32 size; + /* Free blocks in individual freelists are linked */ + union { + struct free_ptr free_ptr; + u8 buffer[sizeof(struct free_ptr)]; + } ptr; +}; + +struct pool { + /* First level bitmap (REAL_FLI bits) */ + u32 fl_bitmap; + + /* Second level bitmap */ + u32 sl_bitmap[REAL_FLI]; + + /* Free lists */ + struct bhdr *matrix[REAL_FLI][MAX_SLI]; + + spinlock_t lock; + + size_t init_size; + size_t max_size; + size_t grow_size; + + /* Basic stats */ + size_t used_size; + size_t num_regions; + + /* User provided functions for expanding/shrinking pool */ + get_memory *get_mem; + put_memory *put_mem; + + struct list_head list; + +#if defined(CONFIG_TLSF_STATS) + /* Extra stats */ + size_t peak_used; + size_t peak_total; + size_t peak_extra; /* MAX(Total - Used) */ + size_t count_alloc; + size_t count_free; + size_t count_region_alloc; + size_t count_region_free; + size_t count_failed_alloc; +#endif + +#if defined(CONFIG_TLSF_DEBUG) + /* + * Pool used size must be 0 when its destroyed. + * When non-empty pool is destroyed, it suggests + * memory leak. Such pools are marked invalid + * and kept in pool list for later debugging. + */ + unsigned int valid; +#endif + void *init_region; + char name[MAX_POOL_NAME_LEN]; +}; +/*-- TLSF structures end */ + +#endif --- linux-2.6.27.orig/ubuntu/dm-loop/Kconfig +++ linux-2.6.27/ubuntu/dm-loop/Kconfig @@ -0,0 +1,9 @@ +config DM_LOOP + tristate "Loop target (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + ---help--- + This device-mapper target allows you to treat a regular file as + a block device. + + If unsure, say N. + --- linux-2.6.27.orig/ubuntu/dm-loop/BOM +++ linux-2.6.27/ubuntu/dm-loop/BOM @@ -0,0 +1,4 @@ +Downloaded from: http://sources.redhat.com/lvm2/wiki/DMLoop +Current Version: Tues, 10 Jun 2008 09:10:03 -0000 +Comments: Fairly easy to integrate in + --- linux-2.6.27.orig/ubuntu/dm-loop/dm-loop.c +++ linux-2.6.27/ubuntu/dm-loop/dm-loop.c @@ -0,0 +1,1036 @@ +/* + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. + * + * This file is part of device-mapper. + * + * Extent mapping implementation heavily influenced by mm/swapfile.c + * Bryn Reeves + * + * File mapping and block lookup algorithms support by + * Heinz Mauelshagen . + * + * This file is released under the GPL. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm.h" +#include "dm-bio-list.h" + +#define DM_LOOP_DAEMON "kloopd" +#define DM_MSG_PREFIX "loop" + +enum flags { DM_LOOP_BMAP, DM_LOOP_FSIO }; + +/*-------------------------------------------------------------------- + * Loop context + *--------------------------------------------------------------------*/ + +struct loop_c { + unsigned long flags; + + /* Backing store */ + + struct file *filp; + char *path; + loff_t offset; + struct block_device *bdev; + unsigned blkbits; /* file system block size shift bits */ + + loff_t size; /* size of entire file in bytes */ + loff_t blocks; /* blocks allocated to loop file */ + sector_t mapped_sectors; /* size of mapped area in sectors */ + + int (*map_fn)(struct dm_target *, struct bio *); + void *map_data; +}; + +/* + * Block map extent + */ +struct dm_loop_extent { + sector_t start; /* start sector in mapped device */ + sector_t to; /* start sector on target device */ + sector_t len; /* length in sectors */ +}; + +/* + * Temporary extent list + */ +struct extent_list { + struct dm_loop_extent *extent; + struct list_head list; +}; + +static struct kmem_cache *dm_loop_extent_cache; + +/* + * Block map private context + */ +struct block_map_c { + int nr_extents; /* number of extents in map */ + struct dm_loop_extent **map; /* linear map of extent pointers */ + struct dm_loop_extent **mru; /* pointer to mru entry */ + spinlock_t mru_lock; /* protects mru */ +}; + +/* + * File map private context + */ +struct file_map_c { + spinlock_t lock; /* protects in */ + struct bio_list in; /* new bios for processing */ + struct bio_list work; /* bios queued for processing */ + struct workqueue_struct *wq; /* workqueue */ + struct work_struct ws; /* loop work */ + struct loop_c *loop; /* for filp & offset */ +}; + +/*-------------------------------------------------------------------- + * Generic helpers + *--------------------------------------------------------------------*/ + +static sector_t blk2sect(struct loop_c *lc, blkcnt_t block) +{ + return block << (lc->blkbits - SECTOR_SHIFT); +} + +static blkcnt_t sec2blk(struct loop_c *lc, sector_t sector) +{ + return sector >> (lc->blkbits - SECTOR_SHIFT); +} + +/*-------------------------------------------------------------------- + * File I/O helpers + *--------------------------------------------------------------------*/ + +/* + * transfer data to/from file using the read/write file_operations. + */ +static int fs_io(int rw, struct file *filp, loff_t *pos, struct bio_vec *bv) +{ + ssize_t r; + void __user *ptr = (void __user __force *) kmap(bv->bv_page) + bv->bv_offset; + mm_segment_t old_fs = get_fs(); + + set_fs(get_ds()); + r = (rw == READ) ? filp->f_op->read(filp, ptr, bv->bv_len, pos) : + filp->f_op->write(filp, ptr, bv->bv_len, pos); + set_fs(old_fs); + kunmap(bv->bv_page); + + return (r == bv->bv_len) ? 0 : -EIO; +} + +/* + * Handle I/O for one bio + */ +static void do_one_bio(struct file_map_c *fc, struct bio *bio) +{ + int r = 0, rw = bio_data_dir(bio); + loff_t start = (bio->bi_sector << 9) + fc->loop->offset, pos = start; + struct bio_vec *bv, *bv_end = bio->bi_io_vec + bio->bi_vcnt; + + for (bv = bio->bi_io_vec; bv < bv_end; bv++) { + r = fs_io(rw, fc->loop->filp, &pos, bv); + if (r) { + DMERR("%s error %d", rw ? "write" : "read", r); + break; + } + } + + bio_endio(bio, r); +} + +/* + * Worker thread for a 'file' type loop device + */ +static void do_loop_work(struct work_struct *ws) +{ + struct file_map_c *fc = container_of(ws, struct file_map_c, ws); + struct bio *bio; + + /* quickly grab all new bios queued and add them to the work list */ + spin_lock_irq(&fc->lock); + bio_list_merge(&fc->work, &fc->in); + bio_list_init(&fc->in); + spin_unlock_irq(&fc->lock); + + /* work the list and do file I/O on all bios */ + while ((bio = bio_list_pop(&fc->work))) + do_one_bio(fc, bio); +} + +/* + * Create work queue and initialize work + */ +static int loop_work_init(struct loop_c *lc) +{ + struct file_map_c *fc = lc->map_data; + + fc->wq = create_singlethread_workqueue(DM_LOOP_DAEMON); + if (!fc->wq) + return -ENOMEM; + + return 0; +} + +/* + * Destroy work queue + */ +static void loop_work_exit(struct loop_c *lc) +{ + struct file_map_c *fc = lc->map_data; + + if (fc->wq) + destroy_workqueue(fc->wq); +} + +/* + * DM_LOOP_FSIO map_fn. Mapping just queues bios to the file map + * context and lets the daemon deal with them. + */ +static int loop_file_map(struct dm_target *ti, struct bio *bio) +{ + int wake; + struct loop_c *lc = ti->private; + struct file_map_c *fc = lc->map_data; + + spin_lock_irq(&fc->lock); + wake = bio_list_empty(&fc->in); + bio_list_add(&fc->in, bio); + spin_unlock_irq(&fc->lock); + + /* + * Only call queue_work() if necessary to avoid + * superfluous preempt_{disable/enable}() overhead. + */ + if (wake) + queue_work(fc->wq, &fc->ws); + + /* Handling bio - will submit later. */ + return 0; +} + +/* + * Shutdown the workqueue and free a file mapping + */ +static void destroy_file_map(struct loop_c *lc) +{ + loop_work_exit(lc); + kfree(lc->map_data); +} + +/* + * Set up a file map context and workqueue + */ +static int setup_file_map(struct loop_c *lc) +{ + struct file_map_c *fc = kzalloc(sizeof(*fc), GFP_KERNEL); + + if (!fc) + return -ENOMEM; + + spin_lock_init(&fc->lock); + bio_list_init(&fc->in); + bio_list_init(&fc->work); + INIT_WORK(&fc->ws, do_loop_work); + fc->loop = lc; + + lc->map_data = fc; + lc->map_fn = loop_file_map; + + return loop_work_init(lc); +} + +/*-------------------------------------------------------------------- + * Block I/O helpers + *--------------------------------------------------------------------*/ + +static int contains_sector(struct dm_loop_extent *e, sector_t s) +{ + if (likely(e)) + return s < (e->start + (e->len)) && s >= e->start; + + return 0; +} + +/* + * Walk over a linked list of extent_list structures, freeing them as + * we go. Does not free el->extent. + */ +static void destroy_extent_list(struct list_head *head) +{ + struct list_head *curr, *n; + struct extent_list *el; + + if (list_empty(head)) + return; + + list_for_each_safe(curr, n, head) { + el = list_entry(curr, struct extent_list, list); + list_del(curr); + kfree(el); + } +} + +/* + * Add a new extent to the tail of the list at *head with + * start/to/len parameters. Allocates from the extent cache. + */ +static int list_add_extent(struct list_head *head, sector_t start, + sector_t to, sector_t len) +{ + struct dm_loop_extent *extent; + struct extent_list *list; + + extent = kmem_cache_alloc(dm_loop_extent_cache, GFP_KERNEL); + if (!extent) + goto out; + + list = kmalloc(sizeof(*list), GFP_KERNEL); + if (!list) + goto out; + + extent->start = start; + extent->to = to; + extent->len = len; + + list->extent = extent; + list_add_tail(&list->list, head); + + return 0; +out: + if (extent) + kmem_cache_free(dm_loop_extent_cache, extent); + return -ENOMEM; +} + +/* + * Return an extent range (i.e. beginning and ending physical block numbers). + */ +static int extent_range(struct inode *inode, + blkcnt_t logical_blk, blkcnt_t last_blk, + blkcnt_t *begin_blk, blkcnt_t *end_blk) +{ + sector_t dist = 0, phys_blk, probe_blk = logical_blk; + + /* Find beginning physical block of extent starting at logical_blk. */ + *begin_blk = phys_blk = bmap(inode, probe_blk); + if (!phys_blk) + return -ENXIO; + + for (; phys_blk == *begin_blk + dist; dist++) { + *end_blk = phys_blk; + if (++probe_blk > last_blk) + break; + + phys_blk = bmap(inode, probe_blk); + if (unlikely(!phys_blk)) + return -ENXIO; + } + + return 0; +} + +/* + * Create a sequential list of extents from an inode and return + * it in *head. On success return the number of extents found or + * -ERRNO on failure. + */ +static int loop_extents(struct loop_c *lc, struct inode *inode, + struct list_head *head) +{ + sector_t start = 0; + int r, nr_extents = 0; + blkcnt_t nr_blks = 0, begin_blk = 0, end_blk = 0; + blkcnt_t after_last_blk = sec2blk(lc, + (lc->mapped_sectors + (lc->offset >> 9))); + blkcnt_t logical_blk = sec2blk(lc, (lc->offset >> 9)); + + /* for each block in the mapped region */ + while (logical_blk < after_last_blk) { + r = extent_range(inode, logical_blk, after_last_blk - 1, + &begin_blk, &end_blk); + + /* sparse file fallback */ + if (unlikely(r)) { + DMWARN("%s has a hole; sparse file detected - " + "switching to filesystem I/O", lc->path); + clear_bit(DM_LOOP_BMAP, &lc->flags); + set_bit(DM_LOOP_FSIO, &lc->flags); + return r; + } + + nr_blks = 1 + end_blk - begin_blk; + + if (unlikely(!nr_blks)) + continue; + + r = list_add_extent(head, start, blk2sect(lc, begin_blk), + blk2sect(lc, nr_blks)); + if (unlikely(r)) + return r; + + /* advance to next extent */ + nr_extents++; + start += blk2sect(lc, nr_blks); + logical_blk += nr_blks; + } + + return nr_extents; +} + +/* + * Walk over the extents in a block_map_c, returning them to the cache and + * freeing bc->map and bc. + */ +static void destroy_block_map(struct block_map_c *bc) +{ + unsigned i; + + if (!bc) + return; + + for (i = 0; i < bc->nr_extents; i++) + kmem_cache_free(dm_loop_extent_cache, bc->map[i]); + + DMDEBUG("destroying block map of %d entries", i); + + vfree(bc->map); + kfree(bc); +} + +/* + * Find an extent in *bc using binary search. Returns a pointer into the + * extent map. Calculate index as (extent - bc->map). + */ +static struct dm_loop_extent **extent_binary_lookup(struct block_map_c *bc, + struct dm_loop_extent **extent_mru, sector_t sector) +{ + unsigned nr_extents = bc->nr_extents; + unsigned delta, dist, prev_dist = 0; + struct dm_loop_extent **eptr; + + /* Optimize lookup range based on MRU extent. */ + dist = extent_mru - bc->map; + if ((*extent_mru)->start >= sector) + delta = dist = dist / 2; + else { + delta = (nr_extents - dist) / 2; + dist += delta; + } + + eptr = bc->map + dist; + while (*eptr && !contains_sector(*eptr, sector)) { + if (sector >= (*eptr)->start + (*eptr)->len) { + prev_dist = dist; + if (delta > 1) + delta /= 2; + dist += delta; + } else { + delta = (dist - prev_dist) / 2; + if (!delta) + delta = 1; + dist -= delta; + } + eptr = bc->map + dist; + } + + return eptr; +} + +/* + * Lookup an extent for a sector using the mru cache and binary search. + */ +static struct dm_loop_extent *extent_lookup(struct block_map_c *bc, sector_t sector) +{ + struct dm_loop_extent **eptr; + + spin_lock_irq(&bc->mru_lock); + eptr = bc->mru; + spin_unlock_irq(&bc->mru_lock); + + if (contains_sector(*eptr, sector)) + return *eptr; + + eptr = extent_binary_lookup(bc, eptr, sector); + if (!eptr) + return NULL; + + spin_lock_irq(&bc->mru_lock); + bc->mru = eptr; + spin_unlock_irq(&bc->mru_lock); + + return *eptr; +} + +/* + * DM_LOOP_BMAP map_fn. Looks up the sector in the extent map and + * rewrites the bio device and bi_sector fields. + */ +static int loop_block_map(struct dm_target *ti, struct bio *bio) +{ + struct loop_c *lc = ti->private; + struct dm_loop_extent *extent = extent_lookup(lc->map_data, bio->bi_sector); + + if (likely(extent)) { + bio->bi_bdev = lc->bdev; + bio->bi_sector = extent->to + (bio->bi_sector - extent->start); + return 1; /* Done with bio -> submit */ + } + + DMERR("no matching extent in map for sector %llu", + (unsigned long long) bio->bi_sector + ti->begin); + BUG(); + + return -EIO; +} + +/* + * Turn an extent_list into a linear pointer map of nr_extents + 1 entries + * and set the final entry to NULL. + */ +static struct dm_loop_extent **build_extent_map(struct list_head *head, int nr_extents, + unsigned long *flags) +{ + unsigned map_size, cache_size; + struct dm_loop_extent **map, **curr; + struct list_head *pos; + struct extent_list *el; + + map_size = 1 + (sizeof(*map) * nr_extents); + cache_size = kmem_cache_size(dm_loop_extent_cache) * nr_extents; + + map = vmalloc(map_size); + curr = map; + + DMDEBUG("allocated extent map of %u %s for %d extents (%u %s)", + (map_size < 8192) ? map_size : map_size >> 10, + (map_size < 8192) ? "bytes" : "kilobytes", nr_extents, + (cache_size < 8192) ? cache_size : cache_size >> 10, + (cache_size < 8192) ? "bytes" : "kilobytes"); + + list_for_each(pos, head) { + el = list_entry(pos, struct extent_list, list); + *(curr++) = el->extent; + } + *curr = NULL; + + return map; +} + +/* + * Set up a block map context and extent map + */ +static int setup_block_map(struct loop_c *lc, struct inode *inode) +{ + int r, nr_extents; + struct block_map_c *bc; + LIST_HEAD(head); + + if (!inode || !inode->i_sb || !inode->i_sb->s_bdev) + return -ENXIO; + + /* build a linked list of extents in linear order */ + r = nr_extents = loop_extents(lc, inode, &head); + if (nr_extents < 1) + goto out; + + r = -ENOMEM; + bc = kzalloc(sizeof(*bc), GFP_KERNEL); + if (!bc) + goto out; + + /* create a linear map of pointers into the extent cache */ + bc->map = build_extent_map(&head, nr_extents, &lc->flags); + destroy_extent_list(&head); + + if (IS_ERR(bc->map)) { + r = PTR_ERR(bc->map); + goto out; + } + + spin_lock_init(&bc->mru_lock); + bc->mru = bc->map; + bc->nr_extents = nr_extents; + lc->bdev = inode->i_sb->s_bdev; + lc->map_data = bc; + lc->map_fn = loop_block_map; + + return 0; + +out: + return r; +} + +/*-------------------------------------------------------------------- + * Generic helpers + *--------------------------------------------------------------------*/ + +/* + * Invalidate all unlocked loop file pages + */ +static int loop_invalidate_file(struct file *filp) +{ + int r; + + /* Same as generic_file_direct_IO() */ + unmap_mapping_range(filp->f_mapping, 0, ~0UL, 0); + + r = filemap_write_and_wait(filp->f_mapping); + if (r) + return r; + + /* + * This will remove all pages except dirty ones. + * If there are dirty pages at this point, it means that the user + * is writing to the file and the coherency is lost anyway. + * If the user was writing to the file simultaneously, this + * returns non-zero, but we ignore that. + */ + invalidate_inode_pages2_range(filp->f_mapping, 0, ~0UL); + + return 0; +} + +/* + * Acquire or release a "no-truncate" lock on *filp. + * We overload the S_SWAPFILE flag for loop targets because + * it provides the same no-truncate semantics we require, and + * holding onto i_sem is no longer an option. + */ +static void file_truncate_lock(struct file *filp) +{ + struct inode *inode = filp->f_mapping->host; + + mutex_lock(&inode->i_mutex); + inode->i_flags |= S_SWAPFILE; + mutex_unlock(&inode->i_mutex); +} + +static void file_truncate_unlock(struct file *filp) +{ + struct inode *inode = filp->f_mapping->host; + + mutex_lock(&inode->i_mutex); + inode->i_flags &= ~S_SWAPFILE; + mutex_unlock(&inode->i_mutex); +} + +/* + * Fill out split_io for taget backing store + */ +static void set_split_io(struct dm_target *ti) +{ + struct loop_c *lc = ti->private; + + if (test_bit(DM_LOOP_BMAP, &lc->flags)) + /* Split I/O at block boundaries */ + ti->split_io = 1 << (lc->blkbits - SECTOR_SHIFT); + else + ti->split_io = 64; + + DMDEBUG("splitting io at %llu sector boundaries", + (unsigned long long) ti->split_io); +} + +/* + * Check that the loop file is regular and available. + */ +static int loop_check_file(struct dm_target *ti) +{ + struct loop_c *lc = ti->private; + struct file *filp = lc->filp; + struct inode *inode = filp->f_mapping->host; + + if (!inode) + return -ENXIO; + + ti->error = "backing file must be a regular file"; + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + ti->error = "backing file is mapped into userspace for writing"; + if (mapping_writably_mapped(filp->f_mapping)) + return -EBUSY; + + if (mapping_mapped(filp->f_mapping)) + DMWARN("%s is mapped into userspace", lc->path); + + if (!inode->i_sb || !inode->i_sb->s_bdev) { + DMWARN("%s has no blockdevice - switching to filesystem I/O", + lc->path); + clear_bit(DM_LOOP_BMAP, &lc->flags); + set_bit(DM_LOOP_FSIO, &lc->flags); + } + + ti->error = "backing file already in use"; + if (IS_SWAPFILE(inode)) + return -EBUSY; + + return 0; +} + +/* + * Check loop file size and store it in the loop context + */ +static int loop_setup_size(struct dm_target *ti) +{ + struct loop_c *lc = ti->private; + struct inode *inode = lc->filp->f_mapping->host; + int r = -EINVAL; + + lc->size = i_size_read(inode); + lc->blkbits = inode->i_blkbits; + + ti->error = "backing file is empty"; + if (!lc->size) + goto out; + + DMDEBUG("set backing file size to %llu", (unsigned long long) lc->size); + + ti->error = "backing file cannot be less than one block in size"; + if (lc->size < (blk2sect(lc, 1) << 9)) + goto out; + + ti->error = "loop file offset must be a multiple of fs blocksize"; + if (lc->offset & ((1 << lc->blkbits) - 1)) + goto out; + + ti->error = "loop file offset too large"; + if (lc->offset > (lc->size - (1 << 9))) + goto out; + + lc->mapped_sectors = (lc->size - lc->offset) >> 9; + DMDEBUG("set mapped sectors to %llu (%llu bytes)", + (unsigned long long) lc->mapped_sectors, + (lc->size - lc->offset)); + + if ((lc->offset + (lc->mapped_sectors << 9)) < lc->size) + DMWARN("not using %llu bytes in incomplete block at EOF", + lc->size - (lc->offset + (lc->mapped_sectors << 9))); + + ti->error = "mapped region cannot be smaller than target size"; + if (lc->size - lc->offset < (ti->len << 9)) + goto out; + + r = 0; + +out: + return r; +} + +/* + * release a loop file + */ +static void loop_put_file(struct file *filp) +{ + if (!filp) + return; + + file_truncate_unlock(filp); + filp_close(filp, NULL); +} + +/* + * Open loop file and perform type, availability and size checks. + */ +static int loop_get_file(struct dm_target *ti) +{ + int flags = ((dm_table_get_mode(ti->table) & FMODE_WRITE) ? + O_RDWR : O_RDONLY) | O_LARGEFILE; + struct loop_c *lc = ti->private; + struct file *filp; + int r = 0; + + ti->error = "could not open backing file"; + filp = filp_open(lc->path, flags, 0); + if (IS_ERR(filp)) + return PTR_ERR(filp); + lc->filp = filp; + r = loop_check_file(ti); + if (r) + goto err; + + r = loop_setup_size(ti); + if (r) + goto err; + + file_truncate_lock(filp); + return 0; + +err: + fput(filp); + return r; +} + +/* + * invalidate mapped pages belonging to the loop file + */ +static void loop_flush(struct dm_target *ti) +{ + struct loop_c *lc = ti->private; + + loop_invalidate_file(lc->filp); +} + +/*-------------------------------------------------------------------- + * Device-mapper target methods + *--------------------------------------------------------------------*/ + +/* + * Generic loop map function. Re-base I/O to target begin and submit + */ +static int loop_map(struct dm_target *ti, struct bio *bio, + union map_info *context) +{ + struct loop_c *lc = ti->private; + + if (unlikely(bio_barrier(bio))) + return -EOPNOTSUPP; + + bio->bi_sector -= ti->begin; + + if (lc->map_fn) + return lc->map_fn(ti, bio); + + return -EIO; +} + +/* + * Block status helper + */ +static ssize_t loop_file_status(struct loop_c *lc, char *result, + unsigned maxlen) +{ + ssize_t sz = 0; + struct file_map_c *fc = lc->map_data; + int qlen; + + spin_lock_irq(&fc->lock); + qlen = bio_list_size(&fc->work); + qlen += bio_list_size(&fc->in); + spin_unlock_irq(&fc->lock); + + DMEMIT("file %d", qlen); + + return sz; +} + +/* + * File status helper + */ +static ssize_t loop_block_status(struct loop_c *lc, char *result, + unsigned maxlen) +{ + ssize_t sz = 0; + struct block_map_c *bc = lc->map_data; + int mru; + + spin_lock_irq(&bc->mru_lock); + mru = bc->mru - bc->map; + spin_unlock_irq(&bc->mru_lock); + + DMEMIT("block %d %d", bc->nr_extents, mru); + + return sz; +} + +/* + * This needs some thought on handling unlinked backing files. some parts of + * the kernel return a cached name (now invalid), while others return a dcache + * "/path/to/foo (deleted)" name (never was/is valid). Which is "better" is + * debatable. + * + * On the one hand, using a cached name gives table output which is directly + * usable assuming the user re-creates the unlinked image file, on the other + * it is more consistent with e.g. swap to use the dcache name. + * +*/ +static int loop_status(struct dm_target *ti, status_type_t type, char *result, + unsigned maxlen) +{ + struct loop_c *lc = ti->private; + ssize_t sz = 0; + + switch (type) { + case STATUSTYPE_INFO: + if (test_bit(DM_LOOP_BMAP, &lc->flags)) + sz += loop_block_status(lc, result, maxlen - sz); + else if (test_bit(DM_LOOP_FSIO, &lc->flags)) + sz += loop_file_status(lc, result, maxlen - sz); + break; + + case STATUSTYPE_TABLE: + DMEMIT("%s %llu", lc->path, lc->offset); + break; + } + return 0; +} + +/* + * Destroy a loopback mapping + */ +static void loop_dtr(struct dm_target *ti) +{ + struct loop_c *lc = ti->private; + + if ((dm_table_get_mode(ti->table) & FMODE_WRITE)) + loop_invalidate_file(lc->filp); + + if (test_bit(DM_LOOP_BMAP, &lc->flags) && lc->map_data) + destroy_block_map((struct block_map_c *)lc->map_data); + if (test_bit(DM_LOOP_FSIO, &lc->flags) && lc->map_data) + destroy_file_map(lc); + + loop_put_file(lc->filp); + DMINFO("released file %s", lc->path); + + kfree(lc); +} + +/* + * Construct a loopback mapping: + */ +static int loop_ctr(struct dm_target *ti, unsigned argc, char **argv) +{ + struct loop_c *lc = NULL; + int r = -EINVAL; + + ti->error = "invalid argument count"; + if (argc != 2) + goto err; + + r = -ENOMEM; + ti->error = "cannot allocate loop context"; + lc = kzalloc(sizeof(*lc), GFP_KERNEL); + if (!lc) + goto err; + + /* default */ + set_bit(DM_LOOP_BMAP, &lc->flags); + ti->error = "cannot allocate loop path"; + lc->path = kstrdup(argv[0], GFP_KERNEL); + if (!lc->path) + goto err; + + ti->private = lc; + + r = -EINVAL; + ti->error = "invalid file offset"; + if (sscanf(argv[1], "%lld", &lc->offset) != 1) + goto err; + + if (lc->offset) + DMDEBUG("setting file offset to %lld", lc->offset); + + /* open & check file and set size parameters */ + r = loop_get_file(ti); + + /* ti->error has been set by loop_get_file */ + if (r) + goto err; + + ti->error = "could not create loop mapping"; + if (test_bit(DM_LOOP_BMAP, &lc->flags)) + r = setup_block_map(lc, lc->filp->f_mapping->host); + if (test_bit(DM_LOOP_FSIO, &lc->flags)) + r = setup_file_map(lc); + + if (r) + goto err_putf; + + loop_invalidate_file(lc->filp); + + set_split_io(ti); + if (lc->bdev) + dm_set_device_limits(ti, lc->bdev); + + DMDEBUG("constructed loop target on %s " + "(%lldk, %llu sectors)", lc->path, + (lc->size >> 10), (unsigned long long)lc->mapped_sectors); + ti->error = NULL; + + return 0; + +err_putf: + loop_put_file(lc->filp); +err: + if (lc) + kfree(lc); + return r; +} + +static struct target_type loop_target = { + .name = "loop", + .version = {0, 0, 2}, + .module = THIS_MODULE, + .ctr = loop_ctr, + .dtr = loop_dtr, + .map = loop_map, + .presuspend = loop_flush, + .flush = loop_flush, + .status = loop_status, +}; + +/*-------------------------------------------------------------------- + * Module bits + *--------------------------------------------------------------------*/ +static int __init dm_loop_init(void) +{ + int r; + + r = dm_register_target(&loop_target); + if (r < 0) { + DMERR("register failed %d", r); + goto err; + } + + r = -ENOMEM; + dm_loop_extent_cache = KMEM_CACHE(dm_loop_extent, SLAB_HWCACHE_ALIGN); + if (!dm_loop_extent_cache) + goto err; + + DMINFO("version %u.%u.%u loaded", + loop_target.version[0], loop_target.version[1], + loop_target.version[2]); + + return 0; + +err: + if (dm_loop_extent_cache) + kmem_cache_destroy(dm_loop_extent_cache); + + return r; +} + +static void __exit dm_loop_exit(void) +{ + int r; + + r = dm_unregister_target(&loop_target); + kmem_cache_destroy(dm_loop_extent_cache); + + if (r < 0) + DMERR("target unregister failed %d", r); + else + DMINFO("version %u.%u.%u unloaded", + loop_target.version[0], loop_target.version[1], + loop_target.version[2]); +} + +module_init(dm_loop_init); +module_exit(dm_loop_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Bryn Reeves "); +MODULE_DESCRIPTION("device-mapper loop target"); --- linux-2.6.27.orig/ubuntu/dm-loop/Makefile +++ linux-2.6.27/ubuntu/dm-loop/Makefile @@ -0,0 +1,5 @@ +EXTRA_CFLAGS += -I$(srctree)/drivers/md + +obj-$(CONFIG_DM_LOOP) += dm-loop.o + +